mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-02 04:58:29 +00:00
fix: pos for small screen and checkout page (#47092)
* feat: Prevent need for scrolling in lower screens (Point of Sale) * fix: pos checkout page * refactor: renaming variable in pos profile conf * fix: change variable name according to pos conf * fix: removing redundant api call * refactor: adding function * refactor: moving pos settings invoice fields to modal * fix: label for change amount and remaining amount * fix: always display numpad * refactor: function rename * fix: better information * fix: auto scroll to highlighted cart item * chore: added patch --------- Co-authored-by: devdiogenes <diogenes.cruz2001@gmail.com>
This commit is contained in:
@@ -31,7 +31,7 @@
|
||||
"ignore_pricing_rule",
|
||||
"allow_rate_change",
|
||||
"allow_discount_change",
|
||||
"disable_grand_total_to_default_mop",
|
||||
"set_grand_total_to_default_mop",
|
||||
"section_break_23",
|
||||
"item_groups",
|
||||
"column_break_25",
|
||||
@@ -402,12 +402,6 @@
|
||||
"fieldtype": "Check",
|
||||
"label": "Print Receipt on Order Complete"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "disable_grand_total_to_default_mop",
|
||||
"fieldtype": "Check",
|
||||
"label": "Disable auto setting Grand Total to default Payment Mode"
|
||||
},
|
||||
{
|
||||
"fieldname": "project",
|
||||
"fieldtype": "Link",
|
||||
@@ -415,6 +409,12 @@
|
||||
"oldfieldname": "cost_center",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Project"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"fieldname": "set_grand_total_to_default_mop",
|
||||
"fieldtype": "Check",
|
||||
"label": "Set Grand Total to Default Payment Method"
|
||||
}
|
||||
],
|
||||
"grid_page_length": 50,
|
||||
@@ -443,7 +443,7 @@
|
||||
"link_fieldname": "pos_profile"
|
||||
}
|
||||
],
|
||||
"modified": "2025-04-09 11:35:13.779613",
|
||||
"modified": "2025-05-09 11:23:28.632136",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "POS Profile",
|
||||
|
||||
@@ -40,7 +40,6 @@ class POSProfile(Document):
|
||||
currency: DF.Link
|
||||
customer: DF.Link | None
|
||||
customer_groups: DF.Table[POSCustomerGroup]
|
||||
disable_grand_total_to_default_mop: DF.Check
|
||||
disable_rounded_total: DF.Check
|
||||
disabled: DF.Check
|
||||
expense_account: DF.Link | None
|
||||
@@ -56,6 +55,7 @@ class POSProfile(Document):
|
||||
project: DF.Link | None
|
||||
select_print_heading: DF.Link | None
|
||||
selling_price_list: DF.Link | None
|
||||
set_grand_total_to_default_mop: DF.Check
|
||||
tax_category: DF.Link | None
|
||||
taxes_and_charges: DF.Link | None
|
||||
tc_name: DF.Link | None
|
||||
|
||||
@@ -411,3 +411,4 @@ erpnext.patches.v15_0.update_payment_schedule_fields_in_invoices
|
||||
erpnext.patches.v15_0.rename_group_by_to_categorize_by
|
||||
execute:frappe.db.set_single_value("Accounts Settings", "receivable_payable_fetch_method", "Buffered Cursor")
|
||||
erpnext.patches.v14_0.set_update_price_list_based_on
|
||||
erpnext.patches.v15_0.set_grand_total_to_default_mop
|
||||
|
||||
9
erpnext/patches/v15_0/set_grand_total_to_default_mop.py
Normal file
9
erpnext/patches/v15_0/set_grand_total_to_default_mop.py
Normal file
@@ -0,0 +1,9 @@
|
||||
import frappe
|
||||
|
||||
|
||||
def execute():
|
||||
POSProfile = frappe.qb.DocType("POS Profile")
|
||||
|
||||
frappe.qb.update(POSProfile).set(POSProfile.set_grand_total_to_default_mop, 1).where(
|
||||
POSProfile.disable_grand_total_to_default_mop == 0
|
||||
).run()
|
||||
@@ -947,9 +947,9 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
|
||||
var me = this;
|
||||
var payment_status = true;
|
||||
if(this.frm.doc.is_pos && (update_paid_amount===undefined || update_paid_amount)) {
|
||||
let r = await frappe.db.get_value("POS Profile", this.frm.doc.pos_profile, "disable_grand_total_to_default_mop");
|
||||
let r = await frappe.db.get_value("POS Profile", this.frm.doc.pos_profile, "set_grand_total_to_default_mop");
|
||||
|
||||
if (r.message.disable_grand_total_to_default_mop) {
|
||||
if (!r.message.set_grand_total_to_default_mop) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
padding: 1%;
|
||||
|
||||
section {
|
||||
min-height: 45rem;
|
||||
height: calc(100vh - 200px);
|
||||
max-height: calc(100vh - 200px);
|
||||
min-height: 30rem;
|
||||
height: calc(100vh - 125px);
|
||||
max-height: calc(100vh - 125px);
|
||||
}
|
||||
|
||||
.frappe-control {
|
||||
@@ -375,6 +375,7 @@
|
||||
flex-direction: column;
|
||||
flex: 1 1 0%;
|
||||
overflow-y: scroll;
|
||||
min-height: 50px;
|
||||
|
||||
> .cart-item-wrapper {
|
||||
@extend .pointer-no-select;
|
||||
@@ -775,6 +776,7 @@
|
||||
|
||||
.submit-order-btn {
|
||||
@extend .primary-action;
|
||||
margin-top: 0%;
|
||||
background-color: var(--btn-primary);
|
||||
color: var(--neutral);
|
||||
}
|
||||
@@ -785,117 +787,136 @@
|
||||
margin-bottom: var(--margin-md);
|
||||
}
|
||||
|
||||
> .payment-modes {
|
||||
> .payment-split-container {
|
||||
display: flex;
|
||||
padding-bottom: var(--padding-sm);
|
||||
margin-bottom: var(--margin-sm);
|
||||
overflow-x: scroll;
|
||||
overflow-y: hidden;
|
||||
flex-shrink: 0;
|
||||
|
||||
> .payment-mode-wrapper {
|
||||
min-width: 40%;
|
||||
padding: var(--padding-xs);
|
||||
> .payment-container-left {
|
||||
width: 50%;
|
||||
margin-bottom: var(--margin-md);
|
||||
|
||||
> .mode-of-payment {
|
||||
@extend .pos-card;
|
||||
@extend .pointer-no-select;
|
||||
padding: var(--padding-md) var(--padding-lg);
|
||||
.payment-modes {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-right: var(--padding-sm);
|
||||
margin-right: var(--margin-sm);
|
||||
min-height: 15rem;
|
||||
overflow-y: scroll;
|
||||
height: calc(100vh - 350px);
|
||||
|
||||
> .pay-amount {
|
||||
display: inline;
|
||||
float: right;
|
||||
font-weight: 700;
|
||||
}
|
||||
> .payment-mode-wrapper {
|
||||
min-width: 40%;
|
||||
padding: var(--padding-xs);
|
||||
|
||||
> .mode-of-payment-control {
|
||||
display: none;
|
||||
align-items: center;
|
||||
margin-top: var(--margin-sm);
|
||||
margin-bottom: var(--margin-xs);
|
||||
}
|
||||
|
||||
> .loyalty-amount-name {
|
||||
display: none;
|
||||
float: right;
|
||||
font-weight: 700;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
> .cash-shortcuts {
|
||||
display: none;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: var(--margin-sm);
|
||||
font-size: var(--text-sm);
|
||||
text-align: center;
|
||||
|
||||
> .shortcut {
|
||||
> .mode-of-payment {
|
||||
@extend .pos-card;
|
||||
@extend .pointer-no-select;
|
||||
border-radius: var(--border-radius-sm);
|
||||
background-color: var(--control-bg);
|
||||
font-weight: 500;
|
||||
padding: var(--padding-xs) var(--padding-sm);
|
||||
transition: all 0.15s ease-in-out;
|
||||
padding: var(--padding-md) var(--padding-lg);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--control-bg);
|
||||
> .pay-amount {
|
||||
display: inline;
|
||||
float: right;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
> .mode-of-payment-control {
|
||||
display: none;
|
||||
align-items: center;
|
||||
margin-top: var(--margin-sm);
|
||||
margin-bottom: var(--margin-xs);
|
||||
}
|
||||
|
||||
> .loyalty-amount-name {
|
||||
display: none;
|
||||
float: right;
|
||||
font-weight: 700;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
> .cash-shortcuts {
|
||||
display: none;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: var(--margin-sm);
|
||||
font-size: var(--text-sm);
|
||||
text-align: center;
|
||||
|
||||
> .shortcut {
|
||||
@extend .pointer-no-select;
|
||||
border-radius: var(--border-radius-sm);
|
||||
background-color: var(--control-bg);
|
||||
font-weight: 500;
|
||||
padding: var(--padding-xs) var(--padding-sm);
|
||||
transition: all 0.15s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--control-bg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .loyalty-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .loyalty-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .fields-numpad-container {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
justify-content: flex-end;
|
||||
|
||||
> .fields-section {
|
||||
flex: 1;
|
||||
> .payment-container-right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
padding-bottom: var(--margin-md);
|
||||
|
||||
.invoice-fields {
|
||||
overflow-y: scroll;
|
||||
.fields-numpad-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
padding-right: var(--padding-sm);
|
||||
}
|
||||
}
|
||||
position: relative;
|
||||
justify-content: flex-end;
|
||||
|
||||
> .number-pad {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: flex-end;
|
||||
max-width: 50%;
|
||||
|
||||
.numpad-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: var(--margin-md);
|
||||
margin-bottom: var(--margin-md);
|
||||
|
||||
> .numpad-btn {
|
||||
@extend .pointer-no-select;
|
||||
border-radius: var(--border-radius-md);
|
||||
> .fields-section {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: var(--padding-md);
|
||||
box-shadow: var(--shadow-sm);
|
||||
flex-direction: column;
|
||||
padding-left: var(--margin-md);
|
||||
|
||||
.invoice-fields {
|
||||
height: 100%;
|
||||
margin-left: auto;
|
||||
padding: var(--padding-sm);
|
||||
}
|
||||
}
|
||||
|
||||
.number-pad {
|
||||
position: absolute;
|
||||
z-index: 4;
|
||||
right: 0px;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
|
||||
.numpad-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: var(--margin-md);
|
||||
margin-bottom: var(--margin-md);
|
||||
background-color: var(--fg-color);
|
||||
border-radius: var(--border-radius-md);
|
||||
padding: var(--padding-sm);
|
||||
|
||||
> .numpad-btn {
|
||||
@extend .pointer-no-select;
|
||||
border-radius: var(--border-radius-md);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: var(--padding-md);
|
||||
box-shadow: var(--shadow-base);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,6 +156,28 @@ erpnext.PointOfSale.Controller = class {
|
||||
},
|
||||
});
|
||||
|
||||
this.fetch_invoice_fields();
|
||||
this.setup_listener_for_pos_closing();
|
||||
}
|
||||
|
||||
fetch_invoice_fields() {
|
||||
const me = this;
|
||||
frappe.db.get_doc("POS Settings", undefined).then((doc) => {
|
||||
me.settings.invoice_fields = doc.invoice_fields.map((field) => {
|
||||
return {
|
||||
fieldname: field.fieldname,
|
||||
label: field.label,
|
||||
fieldtype: field.fieldtype,
|
||||
reqd: field.reqd,
|
||||
options: field.options,
|
||||
default_value: field.default_value,
|
||||
read_only: field.read_only,
|
||||
};
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
setup_listener_for_pos_closing() {
|
||||
frappe.realtime.on(`poe_${this.pos_opening}_closed`, (data) => {
|
||||
const route = frappe.get_route_str();
|
||||
if (data && route == "point-of-sale") {
|
||||
@@ -426,6 +448,7 @@ erpnext.PointOfSale.Controller = class {
|
||||
init_payments() {
|
||||
this.payment = new erpnext.PointOfSale.Payment({
|
||||
wrapper: this.$components_wrapper,
|
||||
settings: this.settings,
|
||||
events: {
|
||||
get_frm: () => this.frm || {},
|
||||
|
||||
|
||||
@@ -171,6 +171,9 @@ erpnext.PointOfSale.ItemCart = class {
|
||||
|
||||
me.toggle_item_highlight(this);
|
||||
|
||||
const scrollTop = $cart_item.offset().top - me.$cart_items_wrapper.offset().top;
|
||||
me.$cart_items_wrapper.animate({ scrollTop });
|
||||
|
||||
const payment_section_hidden = !me.$totals_section.find(".edit-cart-btn").is(":visible");
|
||||
if (!payment_section_hidden) {
|
||||
// payment section is visible
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
erpnext.PointOfSale.Payment = class {
|
||||
constructor({ events, wrapper }) {
|
||||
constructor({ events, wrapper, settings }) {
|
||||
this.wrapper = wrapper;
|
||||
this.events = events;
|
||||
this.set_gt_to_default_mop = settings.set_grand_total_to_default_mop;
|
||||
this.invoice_fields = settings.invoice_fields;
|
||||
|
||||
this.init_component();
|
||||
}
|
||||
@@ -17,14 +19,23 @@ erpnext.PointOfSale.Payment = class {
|
||||
prepare_dom() {
|
||||
this.wrapper.append(
|
||||
`<section class="payment-container">
|
||||
<div class="section-label payment-section">${__("Payment Method")}</div>
|
||||
<div class="payment-modes"></div>
|
||||
<div class="fields-numpad-container">
|
||||
<div class="fields-section">
|
||||
<div class="section-label">${__("Additional Information")}</div>
|
||||
<div class="invoice-fields"></div>
|
||||
<div class="payment-split-container">
|
||||
<div class="payment-container-left">
|
||||
<div class="section-label payment-section">${__("Payment Method")}</div>
|
||||
<div class="payment-modes"></div>
|
||||
</div>
|
||||
<div class="payment-container-right">
|
||||
<div class="fields-numpad-container">
|
||||
<div class="fields-section">
|
||||
<div class="invoice-fields">
|
||||
<button class="btn btn-default btn-sm btn-shadow addl-fields hidden">${__(
|
||||
"Update Additional Information"
|
||||
)}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="number-pad"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="number-pad"></div>
|
||||
</div>
|
||||
<div class="totals-section">
|
||||
<div class="totals"></div>
|
||||
@@ -40,48 +51,61 @@ erpnext.PointOfSale.Payment = class {
|
||||
this.$invoice_fields_section = this.$component.find(".fields-section");
|
||||
}
|
||||
|
||||
make_invoice_fields_control() {
|
||||
this.reqd_invoice_fields = [];
|
||||
frappe.db.get_doc("POS Settings", undefined).then((doc) => {
|
||||
const fields = doc.invoice_fields;
|
||||
if (!fields.length) return;
|
||||
make_invoice_field_dialog() {
|
||||
const me = this;
|
||||
if (!me.invoice_fields.length) return;
|
||||
me.addl_dlg = new frappe.ui.Dialog({
|
||||
title: __("Additional Information"),
|
||||
fields: me.invoice_fields,
|
||||
size: "small",
|
||||
primary_action_label: __("Save"),
|
||||
primary_action(values) {
|
||||
me.set_values_to_frm(values);
|
||||
this.hide();
|
||||
},
|
||||
});
|
||||
me.add_btn_field_click_listener();
|
||||
me.set_value_on_dialog_fields();
|
||||
me.make_addl_info_dialog_btn_visible();
|
||||
}
|
||||
|
||||
this.$invoice_fields = this.$invoice_fields_section.find(".invoice-fields");
|
||||
this.$invoice_fields.html("");
|
||||
const frm = this.events.get_frm();
|
||||
set_values_to_frm(values) {
|
||||
const frm = this.events.get_frm();
|
||||
for (const value in values) {
|
||||
frm.set_value(value, values[value]);
|
||||
}
|
||||
frappe.show_alert({
|
||||
message: __("Additional Information updated successfully."),
|
||||
indicator: "green",
|
||||
});
|
||||
}
|
||||
|
||||
fields.forEach((df) => {
|
||||
this.$invoice_fields.append(
|
||||
`<div class="invoice_detail_field ${df.fieldname}-field" data-fieldname="${df.fieldname}"></div>`
|
||||
);
|
||||
let df_events = {
|
||||
onchange: function () {
|
||||
frm.set_value(this.df.fieldname, this.get_value());
|
||||
},
|
||||
};
|
||||
if (df.fieldtype == "Button") {
|
||||
df_events = {
|
||||
click: function () {
|
||||
if (frm.script_manager.has_handlers(df.fieldname, frm.doc.doctype)) {
|
||||
frm.script_manager.trigger(df.fieldname, frm.doc.doctype, frm.doc.docname);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
if (df.reqd && (df.fieldtype !== "Button" || !df.read_only)) {
|
||||
this.reqd_invoice_fields.push({ fieldname: df.fieldname, label: df.label });
|
||||
}
|
||||
|
||||
this[`${df.fieldname}_field`] = frappe.ui.form.make_control({
|
||||
df: {
|
||||
...df,
|
||||
...df_events,
|
||||
},
|
||||
parent: this.$invoice_fields.find(`.${df.fieldname}-field`),
|
||||
render_input: true,
|
||||
add_btn_field_click_listener() {
|
||||
const frm = this.events.get_frm();
|
||||
this.addl_dlg.fields.forEach((df) => {
|
||||
if (df.fieldtype === "Button") {
|
||||
this.addl_dlg.fields_dict[df.fieldname].$input.on("click", function () {
|
||||
if (frm.script_manager.has_handlers(df.fieldname, frm.doc.doctype)) {
|
||||
frm.script_manager.trigger(df.fieldname, frm.doc.doctype, frm.doc.docname);
|
||||
}
|
||||
});
|
||||
this[`${df.fieldname}_field`].set_value(frm.doc[df.fieldname]);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
set_value_on_dialog_fields() {
|
||||
const doc = this.events.get_frm().doc;
|
||||
this.addl_dlg.fields.forEach((df) => {
|
||||
if (doc[df.fieldname] || df.default_value) {
|
||||
this.addl_dlg.set_value(df.fieldname, doc[df.fieldname] || df.default_value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
make_addl_info_dialog_btn_visible() {
|
||||
this.$invoice_fields_section.find(".addl-fields").removeClass("hidden");
|
||||
this.$invoice_fields_section.find(".addl-fields").on("click", () => {
|
||||
this.addl_dlg.show();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -164,6 +188,16 @@ erpnext.PointOfSale.Payment = class {
|
||||
}
|
||||
});
|
||||
|
||||
frappe.ui.form.on("POS Invoice", "contact_mobile", (frm) => {
|
||||
const contact = frm.doc.contact_mobile;
|
||||
const request_button = $(this.request_for_payment_field?.$input[0]);
|
||||
if (contact) {
|
||||
request_button.removeClass("btn-default").addClass("btn-primary");
|
||||
} else {
|
||||
request_button.removeClass("btn-primary").addClass("btn-default");
|
||||
}
|
||||
});
|
||||
|
||||
frappe.ui.form.on("POS Invoice", "coupon_code", (frm) => {
|
||||
this.bind_coupon_code_event(frm);
|
||||
});
|
||||
@@ -355,9 +389,9 @@ erpnext.PointOfSale.Payment = class {
|
||||
|
||||
render_payment_section() {
|
||||
this.render_payment_mode_dom();
|
||||
this.make_invoice_fields_control();
|
||||
this.make_invoice_field_dialog();
|
||||
this.update_totals_section();
|
||||
this.unset_grand_total_to_default_mop();
|
||||
this.set_grand_total_to_default_mop();
|
||||
}
|
||||
|
||||
after_render() {
|
||||
@@ -610,7 +644,7 @@ erpnext.PointOfSale.Payment = class {
|
||||
const remaining = grand_total - doc.paid_amount;
|
||||
const change = doc.change_amount || remaining <= 0 ? -1 * remaining : undefined;
|
||||
const currency = doc.currency;
|
||||
const label = __("Change Amount");
|
||||
const label = doc.paid_amount > grand_total ? __("Change Amount") : __("Remaining Amount");
|
||||
|
||||
this.$totals.html(
|
||||
`<div class="col">
|
||||
@@ -642,32 +676,28 @@ erpnext.PointOfSale.Payment = class {
|
||||
.toLowerCase();
|
||||
}
|
||||
|
||||
async unset_grand_total_to_default_mop() {
|
||||
const doc = this.events.get_frm().doc;
|
||||
let r = await frappe.db.get_value(
|
||||
"POS Profile",
|
||||
doc.pos_profile,
|
||||
"disable_grand_total_to_default_mop"
|
||||
);
|
||||
|
||||
if (!r.message.disable_grand_total_to_default_mop) {
|
||||
set_grand_total_to_default_mop() {
|
||||
if (this.set_gt_to_default_mop) {
|
||||
this.focus_on_default_mop();
|
||||
}
|
||||
}
|
||||
|
||||
validate_reqd_invoice_fields() {
|
||||
const doc = this.events.get_frm().doc;
|
||||
let validation_flag = true;
|
||||
for (let field of this.reqd_invoice_fields) {
|
||||
if (!doc[field.fieldname]) {
|
||||
validation_flag = false;
|
||||
for (const df of this.addl_dlg.fields) {
|
||||
if (df.reqd && !doc[df.fieldname]) {
|
||||
frappe.show_alert({
|
||||
message: __("{0} is a mandatory field.", [field.label]),
|
||||
indicator: "orange",
|
||||
message: __(
|
||||
"Invoice cannot be submitted without filling the mandatory Additional Information fields."
|
||||
),
|
||||
indicator: "red",
|
||||
});
|
||||
frappe.utils.play_sound("error");
|
||||
this.addl_dlg.show();
|
||||
this.addl_dlg.fields_dict[df.fieldname].$input.focus();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return validation_flag;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user