From ecaf0aba3c8ccda3a5fa2771e1dd467b9f3b712e Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Mon, 17 Jul 2023 16:45:11 +0200 Subject: [PATCH 1/4] fix: rounding of percentage fields Always round with precision of 2 --- .../doctype/purchase_order/purchase_order.js | 14 +++++++------- erpnext/controllers/website_list_for_contact.py | 6 ++++-- erpnext/patches/v12_0/update_bom_in_so_mr.py | 4 +++- erpnext/selling/doctype/sales_order/sales_order.js | 14 +++++++------- .../doctype/sales_order/sales_order_list.js | 10 +++++----- erpnext/templates/form_grid/item_grid.html | 2 +- 6 files changed, 27 insertions(+), 23 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js index 8fa8f305549..147b447e806 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.js +++ b/erpnext/buying/doctype/purchase_order/purchase_order.js @@ -62,7 +62,7 @@ frappe.ui.form.on("Purchase Order", { get_materials_from_supplier: function(frm) { let po_details = []; - if (frm.doc.supplied_items && (frm.doc.per_received == 100 || frm.doc.status === 'Closed')) { + if (frm.doc.supplied_items && (flt(frm.doc.per_received, 2) == 100 || frm.doc.status === 'Closed')) { frm.doc.supplied_items.forEach(d => { if (d.total_supplied_qty && d.total_supplied_qty != d.consumed_qty) { po_details.push(d.name) @@ -181,7 +181,7 @@ erpnext.buying.PurchaseOrderController = class PurchaseOrderController extends e } if(!in_list(["Closed", "Delivered"], doc.status)) { - if(this.frm.doc.status !== 'Closed' && flt(this.frm.doc.per_received) < 100 && flt(this.frm.doc.per_billed) < 100) { + if(this.frm.doc.status !== 'Closed' && flt(this.frm.doc.per_received, 2) < 100 && flt(this.frm.doc.per_billed, 2) < 100) { // Don't add Update Items button if the PO is following the new subcontracting flow. if (!(this.frm.doc.is_subcontracted && !this.frm.doc.is_old_subcontracting_flow)) { this.frm.add_custom_button(__('Update Items'), () => { @@ -195,7 +195,7 @@ erpnext.buying.PurchaseOrderController = class PurchaseOrderController extends e } } if (this.frm.has_perm("submit")) { - if(flt(doc.per_billed, 6) < 100 || flt(doc.per_received, 6) < 100) { + if(flt(doc.per_billed, 2) < 100 || flt(doc.per_received, 2) < 100) { if (doc.status != "On Hold") { this.frm.add_custom_button(__('Hold'), () => this.hold_purchase_order(), __("Status")); } else{ @@ -218,7 +218,7 @@ erpnext.buying.PurchaseOrderController = class PurchaseOrderController extends e } if(doc.status != "Closed") { if (doc.status != "On Hold") { - if(flt(doc.per_received) < 100 && allow_receipt) { + if(flt(doc.per_received, 2) < 100 && allow_receipt) { cur_frm.add_custom_button(__('Purchase Receipt'), this.make_purchase_receipt, __('Create')); if (doc.is_subcontracted) { if (doc.is_old_subcontracting_flow) { @@ -231,11 +231,11 @@ erpnext.buying.PurchaseOrderController = class PurchaseOrderController extends e } } } - if(flt(doc.per_billed) < 100) + if(flt(doc.per_billed, 2) < 100) cur_frm.add_custom_button(__('Purchase Invoice'), this.make_purchase_invoice, __('Create')); - if(flt(doc.per_billed) < 100 && doc.status != "Delivered") { + if(flt(doc.per_billed, 2) < 100 && doc.status != "Delivered") { this.frm.add_custom_button( __('Payment'), () => this.make_payment_entry(), @@ -243,7 +243,7 @@ erpnext.buying.PurchaseOrderController = class PurchaseOrderController extends e ); } - if(flt(doc.per_billed) < 100) { + if(flt(doc.per_billed, 2) < 100) { this.frm.add_custom_button(__('Payment Request'), function() { me.make_payment_request() }, __('Create')); } diff --git a/erpnext/controllers/website_list_for_contact.py b/erpnext/controllers/website_list_for_contact.py index 642722ae6bf..01b6f5ceba1 100644 --- a/erpnext/controllers/website_list_for_contact.py +++ b/erpnext/controllers/website_list_for_contact.py @@ -206,9 +206,11 @@ def post_process(doctype, data): ) if doc.get("per_delivered"): - doc.status_percent += flt(doc.per_delivered) + doc.status_percent += flt(doc.per_delivered, 2) doc.status_display.append( - _("Delivered") if doc.per_delivered == 100 else _("{0}% Delivered").format(doc.per_delivered) + _("Delivered") + if flt(doc.per_delivered, 2) == 100 + else _("{0}% Delivered").format(doc.per_delivered) ) if hasattr(doc, "set_indicator"): diff --git a/erpnext/patches/v12_0/update_bom_in_so_mr.py b/erpnext/patches/v12_0/update_bom_in_so_mr.py index 114f65d100e..d35b4bcdd67 100644 --- a/erpnext/patches/v12_0/update_bom_in_so_mr.py +++ b/erpnext/patches/v12_0/update_bom_in_so_mr.py @@ -6,7 +6,9 @@ def execute(): frappe.reload_doc("selling", "doctype", "sales_order_item") for doctype in ["Sales Order", "Material Request"]: - condition = " and child_doc.stock_qty > child_doc.produced_qty and doc.per_delivered < 100" + condition = ( + " and child_doc.stock_qty > child_doc.produced_qty and ROUND(doc.per_delivered, 2) < 100" + ) if doctype == "Material Request": condition = " and doc.per_ordered < 100 and doc.material_request_type = 'Manufacture'" diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index 5d43a07d96c..f1a68af8d9f 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -50,7 +50,7 @@ frappe.ui.form.on("Sales Order", { refresh: function(frm) { if(frm.doc.docstatus === 1) { - if (frm.doc.status !== 'Closed' && flt(frm.doc.per_delivered, 6) < 100 && flt(frm.doc.per_billed, 6) < 100) { + if (frm.doc.status !== 'Closed' && flt(frm.doc.per_delivered, 2) < 100 && flt(frm.doc.per_billed, 2) < 100) { frm.add_custom_button(__('Update Items'), () => { erpnext.utils.update_child_items({ frm: frm, @@ -307,7 +307,7 @@ erpnext.selling.SalesOrderController = class SalesOrderController extends erpnex me.frm.cscript.update_status('Resume', 'Draft') }, __("Status")); - if(flt(doc.per_delivered, 6) < 100 || flt(doc.per_billed) < 100) { + if(flt(doc.per_delivered, 2) < 100 || flt(doc.per_billed, 2) < 100) { // close this.frm.add_custom_button(__('Close'), () => this.close_sales_order(), __("Status")) } @@ -325,7 +325,7 @@ erpnext.selling.SalesOrderController = class SalesOrderController extends erpnex && !this.frm.doc.skip_delivery_note if (this.frm.has_perm("submit")) { - if(flt(doc.per_delivered, 6) < 100 || flt(doc.per_billed) < 100) { + if(flt(doc.per_delivered, 2) < 100 || flt(doc.per_billed, 2) < 100) { // hold this.frm.add_custom_button(__('Hold'), () => this.hold_sales_order(), __("Status")) // close @@ -333,7 +333,7 @@ erpnext.selling.SalesOrderController = class SalesOrderController extends erpnex } } - if (flt(doc.per_picked, 6) < 100 && flt(doc.per_delivered, 6) < 100) { + if (flt(doc.per_picked, 2) < 100 && flt(doc.per_delivered, 2) < 100) { this.frm.add_custom_button(__('Pick List'), () => this.create_pick_list(), __('Create')); } @@ -343,18 +343,18 @@ erpnext.selling.SalesOrderController = class SalesOrderController extends erpnex const order_is_a_custom_sale = ["Sales", "Shopping Cart", "Maintenance"].indexOf(doc.order_type) === -1; // delivery note - if(flt(doc.per_delivered, 6) < 100 && (order_is_a_sale || order_is_a_custom_sale) && allow_delivery) { + if(flt(doc.per_delivered, 2) < 100 && (order_is_a_sale || order_is_a_custom_sale) && allow_delivery) { this.frm.add_custom_button(__('Delivery Note'), () => this.make_delivery_note_based_on_delivery_date(), __('Create')); this.frm.add_custom_button(__('Work Order'), () => this.make_work_order(), __('Create')); } // sales invoice - if(flt(doc.per_billed, 6) < 100) { + if(flt(doc.per_billed, 2) < 100) { this.frm.add_custom_button(__('Sales Invoice'), () => me.make_sales_invoice(), __('Create')); } // material request - if(!doc.order_type || (order_is_a_sale || order_is_a_custom_sale) && flt(doc.per_delivered, 6) < 100) { + if(!doc.order_type || (order_is_a_sale || order_is_a_custom_sale) && flt(doc.per_delivered, 2) < 100) { this.frm.add_custom_button(__('Material Request'), () => this.make_material_request(), __('Create')); this.frm.add_custom_button(__('Request for Raw Materials'), () => this.make_raw_material_request(), __('Create')); } diff --git a/erpnext/selling/doctype/sales_order/sales_order_list.js b/erpnext/selling/doctype/sales_order/sales_order_list.js index 64c58ef5d7b..518f0187260 100644 --- a/erpnext/selling/doctype/sales_order/sales_order_list.js +++ b/erpnext/selling/doctype/sales_order/sales_order_list.js @@ -10,7 +10,7 @@ frappe.listview_settings['Sales Order'] = { return [__("On Hold"), "orange", "status,=,On Hold"]; } else if (doc.status === "Completed") { return [__("Completed"), "green", "status,=,Completed"]; - } else if (!doc.skip_delivery_note && flt(doc.per_delivered, 6) < 100) { + } else if (!doc.skip_delivery_note && flt(doc.per_delivered, 2) < 100) { if (frappe.datetime.get_diff(doc.delivery_date) < 0) { // not delivered & overdue return [__("Overdue"), "red", @@ -19,7 +19,7 @@ frappe.listview_settings['Sales Order'] = { // not delivered (zeroount order) return [__("To Deliver"), "orange", "per_delivered,<,100|grand_total,=,0|status,!=,Closed"]; - } else if (flt(doc.per_billed, 6) < 100) { + } else if (flt(doc.per_billed, 2) < 100) { // not delivered & not billed return [__("To Deliver and Bill"), "orange", "per_delivered,<,100|per_billed,<,100|status,!=,Closed"]; @@ -28,12 +28,12 @@ frappe.listview_settings['Sales Order'] = { return [__("To Deliver"), "orange", "per_delivered,<,100|per_billed,=,100|status,!=,Closed"]; } - } else if ((flt(doc.per_delivered, 6) === 100) && flt(doc.grand_total) !== 0 - && flt(doc.per_billed, 6) < 100) { + } else if ((flt(doc.per_delivered, 2) === 100) && flt(doc.grand_total) !== 0 + && flt(doc.per_billed, 2) < 100) { // to bill return [__("To Bill"), "orange", "per_delivered,=,100|per_billed,<,100|status,!=,Closed"]; - } else if (doc.skip_delivery_note && flt(doc.per_billed, 6) < 100){ + } else if (doc.skip_delivery_note && flt(doc.per_billed, 2) < 100){ return [__("To Bill"), "orange", "per_billed,<,100|status,!=,Closed"]; } }, diff --git a/erpnext/templates/form_grid/item_grid.html b/erpnext/templates/form_grid/item_grid.html index c596890aa32..027046fd92f 100644 --- a/erpnext/templates/form_grid/item_grid.html +++ b/erpnext/templates/form_grid/item_grid.html @@ -17,7 +17,7 @@ title = "Warehouse", actual_qty = (frm.doc.doctype==="Sales Order" ? doc.projected_qty : doc.actual_qty); - if(flt(frm.doc.per_delivered) < 100 + if(flt(frm.doc.per_delivered, 2) < 100 && in_list(["Sales Order Item", "Delivery Note Item"], doc.doctype)) { if(actual_qty != undefined) { if(actual_qty >= doc.qty) { From 3558c3d24e3a6dbc10a2d20a03a50a894f359b00 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Tue, 25 Jul 2023 21:42:01 +0200 Subject: [PATCH 2/4] fix: german translations --- erpnext/translations/de.csv | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv index 8efa94df5a2..fc487551793 100644 --- a/erpnext/translations/de.csv +++ b/erpnext/translations/de.csv @@ -1145,6 +1145,7 @@ Get Items from Prescriptions,Holen Sie sich Artikel aus Verordnungen, Get Items from Product Bundle,Artikel aus dem Produkt-Bundle übernehmen, Get Suppliers,Holen Sie sich Lieferanten, Get Suppliers By,Holen Sie sich Lieferanten durch, +Get Supplier Group Details,Werte aus Lieferantengruppe übernehmen, Get Updates,Newsletter abonnieren, Get customers from,Holen Sie Kunden von, Get from Patient Encounter,Von der Patientenbegegnung erhalten, @@ -5018,6 +5019,7 @@ Credit To,Gutschreiben auf, Party Account Currency,Währung des Kontos der Partei, Against Expense Account,Zu Aufwandskonto, Inter Company Invoice Reference,Unternehmensübergreifende Rechnungsreferenz, +Internal Supplier,Interner Lieferant, Is Internal Supplier,Ist interner Lieferant, Start date of current invoice's period,Startdatum der laufenden Rechnungsperiode, End date of current invoice's period,Schlußdatum der laufenden Eingangsrechnungsperiode, @@ -5466,6 +5468,8 @@ Tracking,Verfolgung, Ref SQ,Ref-SQ, Inter Company Order Reference,Inter Company Bestellreferenz, Supplier Part Number,Lieferanten-Artikelnummer, +Supplier Primary Contact,Hauptkontakt des Lieferanten, +Supplier Primary Address,Hauptadresse des Lieferanten, Billed Amt,Rechnungsbetrag, Warehouse and Reference,Lager und Referenz, To be delivered to customer,Zur Auslieferung an den Kunden, @@ -7532,7 +7536,7 @@ Accounts Manager,Buchhalter, Allow Sales Invoice Creation Without Sales Order,Ermöglichen Sie die Erstellung von Kundenrechnungen ohne Auftrag, Allow Sales Invoice Creation Without Delivery Note,Ermöglichen Sie die Erstellung einer Ausgangsrechnung ohne Lieferschein, Default Price List,Standardpreisliste, -Primary Address and Contact Detail,Primäre Adresse und Kontaktdetails, +Primary Address and Contact,Hauptadresse und -kontakt, "Select, to make the customer searchable with these fields","Wählen Sie, um den Kunden mit diesen Feldern durchsuchbar zu machen", Customer Primary Contact,Hauptkontakt des Kunden, "Reselect, if the chosen contact is edited after save","Wählen Sie erneut, wenn der ausgewählte Kontakt nach dem Speichern bearbeitet wird", From f9fa34ff4058316af87fc03eb4131e5f58524408 Mon Sep 17 00:00:00 2001 From: Ashish Shah Date: Fri, 28 Jul 2023 11:10:51 +0530 Subject: [PATCH 3/4] fix: in payment_entry 'Unallocated Amount' cal is broken --- erpnext/accounts/doctype/payment_entry/payment_entry.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index ed18feaf57d..44474d976c8 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -903,12 +903,12 @@ frappe.ui.form.on('Payment Entry', { if(frm.doc.payment_type == "Receive" && frm.doc.base_total_allocated_amount < frm.doc.base_received_amount + total_deductions && frm.doc.total_allocated_amount < frm.doc.paid_amount + (total_deductions / frm.doc.source_exchange_rate)) { - unallocated_amount = (frm.doc.base_received_amount + total_deductions + frm.doc.base_total_taxes_and_charges + unallocated_amount = (frm.doc.base_received_amount + total_deductions + flt(frm.doc.base_total_taxes_and_charges) - frm.doc.base_total_allocated_amount) / frm.doc.source_exchange_rate; } else if (frm.doc.payment_type == "Pay" && frm.doc.base_total_allocated_amount < frm.doc.base_paid_amount - total_deductions && frm.doc.total_allocated_amount < frm.doc.received_amount + (total_deductions / frm.doc.target_exchange_rate)) { - unallocated_amount = (frm.doc.base_paid_amount + frm.doc.base_total_taxes_and_charges - (total_deductions + unallocated_amount = (frm.doc.base_paid_amount + flt(frm.doc.base_total_taxes_and_charges) - (total_deductions + frm.doc.base_total_allocated_amount)) / frm.doc.target_exchange_rate; } } From bc470591ac615552bad5a5d370045ed0b68937ba Mon Sep 17 00:00:00 2001 From: xdlumertz Date: Fri, 28 Jul 2023 12:31:29 -0300 Subject: [PATCH 4/4] fix: translate fix: translate --- erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 974a876429c..f5ee2285d29 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1833,7 +1833,7 @@ def validate_inter_company_party(doctype, party, company, inter_company_referenc doc = frappe.get_doc(ref_doc, inter_company_reference) ref_party = doc.supplier if doctype in ["Sales Invoice", "Sales Order"] else doc.customer if not frappe.db.get_value(partytype, {"represents_company": doc.company}, "name") == party: - frappe.throw(_("Invalid {0} for Inter Company Transaction.").format(partytype)) + frappe.throw(_("Invalid {0} for Inter Company Transaction.").format(_(partytype))) if not frappe.get_cached_value(ref_partytype, ref_party, "represents_company") == company: frappe.throw(_("Invalid Company for Inter Company Transaction.")) @@ -1847,7 +1847,7 @@ def validate_inter_company_party(doctype, party, company, inter_company_referenc if not company in companies: frappe.throw( _("{0} not allowed to transact with {1}. Please change the Company.").format( - partytype, company + _(partytype), company ) )