diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json index 703e93c0757..49a2afee85f 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json @@ -19,6 +19,7 @@ "book_asset_depreciation_entry_automatically", "unlink_advance_payment_on_cancelation_of_order", "post_change_gl_entries", + "enable_discount_accounting", "tax_settings_section", "determine_address_tax_category_from", "column_break_19", @@ -261,6 +262,13 @@ "fieldname": "post_change_gl_entries", "fieldtype": "Check", "label": "Create Ledger Entries for Change Amount" + }, + { + "default": "0", + "description": "If enabled, additional ledger entries will be made for discounts in a separate Discount Account", + "fieldname": "enable_discount_accounting", + "fieldtype": "Check", + "label": "Enable Discount Accounting" } ], "icon": "icon-cog", @@ -268,7 +276,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2021-06-17 20:26:03.721202", + "modified": "2021-07-12 18:54:29.084958", "modified_by": "Administrator", "module": "Accounts", "name": "Accounts Settings", diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py index ac4a2d6f16d..55449132928 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py @@ -21,6 +21,7 @@ class AccountsSettings(Document): self.validate_stale_days() self.enable_payment_schedule_in_print() + self.toggle_discount_accounting_fields() def validate_stale_days(self): if not self.allow_stale and cint(self.stale_days) <= 0: @@ -33,3 +34,22 @@ class AccountsSettings(Document): for doctype in ("Sales Order", "Sales Invoice", "Purchase Order", "Purchase Invoice"): make_property_setter(doctype, "due_date", "print_hide", show_in_print, "Check", validate_fields_for_doctype=False) make_property_setter(doctype, "payment_schedule", "print_hide", 0 if show_in_print else 1, "Check", validate_fields_for_doctype=False) + + def toggle_discount_accounting_fields(self): + enable_discount_accounting = cint(self.enable_discount_accounting) + + for doctype in ["Sales Invoice Item", "Purchase Invoice Item"]: + make_property_setter(doctype, "discount_account", "hidden", not(enable_discount_accounting), "Check", validate_fields_for_doctype=False) + if enable_discount_accounting: + make_property_setter(doctype, "discount_account", "mandatory_depends_on", "eval: doc.discount_amount", "Code", validate_fields_for_doctype=False) + else: + make_property_setter(doctype, "discount_account", "mandatory_depends_on", "", "Code", validate_fields_for_doctype=False) + + for doctype in ["Sales Invoice", "Purchase Invoice"]: + make_property_setter(doctype, "additional_discount_account", "hidden", not(enable_discount_accounting), "Check", validate_fields_for_doctype=False) + if enable_discount_accounting: + make_property_setter(doctype, "additional_discount_account", "mandatory_depends_on", "eval: doc.discount_amount", "Code", validate_fields_for_doctype=False) + else: + make_property_setter(doctype, "additional_discount_account", "mandatory_depends_on", "", "Code", validate_fields_for_doctype=False) + + make_property_setter("Item", "default_discount_account", "hidden", not(enable_discount_accounting), "Check", validate_fields_for_doctype=False) \ No newline at end of file diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.json b/erpnext/accounts/doctype/pricing_rule/pricing_rule.json index 428989aa965..0be41b40635 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.json +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.json @@ -558,7 +558,8 @@ "description": "Simple Python Expression, Example: territory != 'All Territories'", "fieldname": "condition", "fieldtype": "Code", - "label": "Condition" + "label": "Condition", + "options": "PythonExpression" }, { "fieldname": "column_break_42", @@ -575,7 +576,7 @@ "icon": "fa fa-gift", "idx": 1, "links": [], - "modified": "2021-03-06 22:01:24.840422", + "modified": "2021-08-06 15:10:04.219321", "modified_by": "Administrator", "module": "Accounts", "name": "Pricing Rule", diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js index c588d45a9fd..4a77ef02cd8 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -275,7 +275,7 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({ // Do not update if inter company reference is there as the details will already be updated if(this.frm.updating_party_details || this.frm.doc.inter_company_invoice_reference) return; - + erpnext.utils.get_party_details(this.frm, "erpnext.accounts.party.get_party_details", { posting_date: this.frm.doc.posting_date, @@ -283,7 +283,8 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({ party: this.frm.doc.supplier, party_type: "Supplier", account: this.frm.doc.credit_to, - price_list: this.frm.doc.buying_price_list + price_list: this.frm.doc.buying_price_list, + fetch_payment_terms_template: cint(!this.frm.doc.ignore_default_payment_terms_template) }, function() { me.apply_pricing_rule(); me.frm.doc.apply_tds = me.frm.supplier_tds ? 1 : 0; @@ -365,7 +366,7 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({ items_add: function(doc, cdt, cdn) { var row = frappe.get_doc(cdt, cdn); this.frm.script_manager.copy_from_first_row("items", row, - ["expense_account", "cost_center", "project"]); + ["expense_account", "discount_account", "cost_center", "project"]); }, on_submit: function() { @@ -499,6 +500,16 @@ frappe.ui.form.on("Purchase Invoice", { 'Payment Entry': 'Payment' } + frm.set_query("additional_discount_account", function() { + return { + filters: { + company: frm.doc.company, + is_group: 0, + report_type: "Profit and Loss", + } + }; + }); + frm.fields_dict['items'].grid.get_field('deferred_expense_account').get_query = function(doc) { return { filters: { @@ -508,6 +519,16 @@ frappe.ui.form.on("Purchase Invoice", { } } } + + frm.fields_dict['items'].grid.get_field('discount_account').get_query = function(doc) { + return { + filters: { + 'report_type': 'Profit and Loss', + 'company': doc.company, + "is_group": 0 + } + } + } }, refresh: function(frm) { diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json index 00ef7d5c184..7025dd98db3 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -96,6 +96,7 @@ "section_break_44", "apply_discount_on", "base_discount_amount", + "additional_discount_account", "column_break_46", "additional_discount_percentage", "discount_amount", @@ -131,6 +132,7 @@ "advances", "payment_schedule_section", "payment_terms_template", + "ignore_default_payment_terms_template", "payment_schedule", "terms_section_break", "tc_name", @@ -175,7 +177,9 @@ "hidden": 1, "label": "Title", "no_copy": 1, - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "naming_series", @@ -187,7 +191,9 @@ "options": "ACC-PINV-.YYYY.-\nACC-PINV-RET-.YYYY.-", "print_hide": 1, "reqd": 1, - "set_only_once": 1 + "set_only_once": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "supplier", @@ -199,7 +205,9 @@ "options": "Supplier", "print_hide": 1, "reqd": 1, - "search_index": 1 + "search_index": 1, + "show_days": 1, + "show_seconds": 1 }, { "bold": 1, @@ -211,7 +219,9 @@ "label": "Supplier Name", "oldfieldname": "supplier_name", "oldfieldtype": "Data", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fetch_from": "supplier.tax_id", @@ -219,21 +229,27 @@ "fieldtype": "Read Only", "label": "Tax Id", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "due_date", "fieldtype": "Date", "label": "Due Date", "oldfieldname": "due_date", - "oldfieldtype": "Date" + "oldfieldtype": "Date", + "show_days": 1, + "show_seconds": 1 }, { "default": "0", "fieldname": "is_paid", "fieldtype": "Check", "label": "Is Paid", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "default": "0", @@ -241,19 +257,25 @@ "fieldtype": "Check", "label": "Is Return (Debit Note)", "no_copy": 1, - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "default": "0", "fieldname": "apply_tds", "fieldtype": "Check", "label": "Apply Tax Withholding Amount", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break1", "fieldtype": "Column Break", "oldfieldtype": "Column Break", + "show_days": 1, + "show_seconds": 1, "width": "50%" }, { @@ -263,13 +285,17 @@ "label": "Company", "options": "Company", "print_hide": 1, - "remember_last_selected_value": 1 + "remember_last_selected_value": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "cost_center", "fieldtype": "Link", "label": "Cost Center", - "options": "Cost Center" + "options": "Cost Center", + "show_days": 1, + "show_seconds": 1 }, { "default": "Today", @@ -281,7 +307,9 @@ "oldfieldtype": "Date", "print_hide": 1, "reqd": 1, - "search_index": 1 + "search_index": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "posting_time", @@ -290,6 +318,8 @@ "no_copy": 1, "print_hide": 1, "print_width": "100px", + "show_days": 1, + "show_seconds": 1, "width": "100px" }, { @@ -298,7 +328,9 @@ "fieldname": "set_posting_time", "fieldtype": "Check", "label": "Edit Posting Date and Time", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "amended_from", @@ -310,44 +342,58 @@ "oldfieldtype": "Link", "options": "Purchase Invoice", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, "collapsible_depends_on": "eval:doc.on_hold", "fieldname": "sb_14", "fieldtype": "Section Break", - "label": "Hold Invoice" + "label": "Hold Invoice", + "show_days": 1, + "show_seconds": 1 }, { "default": "0", "fieldname": "on_hold", "fieldtype": "Check", - "label": "Hold Invoice" + "label": "Hold Invoice", + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval:doc.on_hold", "description": "Once set, this invoice will be on hold till the set date", "fieldname": "release_date", "fieldtype": "Date", - "label": "Release Date" + "label": "Release Date", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "cb_17", - "fieldtype": "Column Break" + "fieldtype": "Column Break", + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval:doc.on_hold", "fieldname": "hold_comment", "fieldtype": "Small Text", - "label": "Reason For Putting On Hold" + "label": "Reason For Putting On Hold", + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, "collapsible_depends_on": "bill_no", "fieldname": "supplier_invoice_details", "fieldtype": "Section Break", - "label": "Supplier Invoice Details" + "label": "Supplier Invoice Details", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "bill_no", @@ -355,11 +401,15 @@ "label": "Supplier Invoice No", "oldfieldname": "bill_no", "oldfieldtype": "Data", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break_15", - "fieldtype": "Column Break" + "fieldtype": "Column Break", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "bill_date", @@ -368,13 +418,17 @@ "no_copy": 1, "oldfieldname": "bill_date", "oldfieldtype": "Date", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "return_against", "fieldname": "returns", "fieldtype": "Section Break", - "label": "Returns" + "label": "Returns", + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "return_against", @@ -384,26 +438,34 @@ "no_copy": 1, "options": "Purchase Invoice", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, "fieldname": "section_addresses", "fieldtype": "Section Break", - "label": "Address and Contact" + "label": "Address and Contact", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "supplier_address", "fieldtype": "Link", "label": "Select Supplier Address", "options": "Address", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "address_display", "fieldtype": "Small Text", "label": "Address", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "contact_person", @@ -411,51 +473,67 @@ "in_global_search": 1, "label": "Contact Person", "options": "Contact", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "contact_display", "fieldtype": "Small Text", "label": "Contact", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "contact_mobile", "fieldtype": "Small Text", "label": "Mobile No", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "contact_email", "fieldtype": "Small Text", "label": "Contact Email", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "col_break_address", - "fieldtype": "Column Break" + "fieldtype": "Column Break", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "shipping_address", "fieldtype": "Link", "label": "Select Shipping Address", "options": "Address", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "shipping_address_display", "fieldtype": "Small Text", "label": "Shipping Address", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, "fieldname": "currency_and_price_list", "fieldtype": "Section Break", "label": "Currency and Price List", - "options": "fa fa-tag" + "options": "fa fa-tag", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "currency", @@ -464,7 +542,9 @@ "oldfieldname": "currency", "oldfieldtype": "Select", "options": "Currency", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "conversion_rate", @@ -473,18 +553,24 @@ "oldfieldname": "conversion_rate", "oldfieldtype": "Currency", "precision": "9", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break2", - "fieldtype": "Column Break" + "fieldtype": "Column Break", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "buying_price_list", "fieldtype": "Link", "label": "Price List", "options": "Price List", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "price_list_currency", @@ -492,14 +578,18 @@ "label": "Price List Currency", "options": "Currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "plc_conversion_rate", "fieldtype": "Float", "label": "Price List Exchange Rate", "precision": "9", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "default": "0", @@ -508,11 +598,15 @@ "label": "Ignore Pricing Rule", "no_copy": 1, "permlevel": 1, - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "sec_warehouse", - "fieldtype": "Section Break" + "fieldtype": "Section Break", + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "update_stock", @@ -521,7 +615,9 @@ "fieldtype": "Link", "label": "Set Accepted Warehouse", "options": "Warehouse", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "update_stock", @@ -531,11 +627,15 @@ "label": "Rejected Warehouse", "no_copy": 1, "options": "Warehouse", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "col_break_warehouse", - "fieldtype": "Column Break" + "fieldtype": "Column Break", + "show_days": 1, + "show_seconds": 1 }, { "default": "No", @@ -543,25 +643,33 @@ "fieldtype": "Select", "label": "Raw Materials Supplied", "options": "No\nYes", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "items_section", "fieldtype": "Section Break", "oldfieldtype": "Section Break", - "options": "fa fa-shopping-cart" + "options": "fa fa-shopping-cart", + "show_days": 1, + "show_seconds": 1 }, { "default": "0", "fieldname": "update_stock", "fieldtype": "Check", "label": "Update Stock", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "scan_barcode", "fieldtype": "Data", - "label": "Scan Barcode" + "label": "Scan Barcode", + "show_days": 1, + "show_seconds": 1 }, { "allow_bulk_edit": 1, @@ -571,25 +679,33 @@ "oldfieldname": "entries", "oldfieldtype": "Table", "options": "Purchase Invoice Item", - "reqd": 1 + "reqd": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "pricing_rule_details", "fieldtype": "Section Break", - "label": "Pricing Rules" + "label": "Pricing Rules", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "pricing_rules", "fieldtype": "Table", "label": "Pricing Rule Detail", "options": "Pricing Rule Detail", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "collapsible_depends_on": "supplied_items", "fieldname": "raw_materials_supplied", "fieldtype": "Section Break", - "label": "Raw Materials Supplied" + "label": "Raw Materials Supplied", + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "update_stock", @@ -597,17 +713,23 @@ "fieldtype": "Table", "label": "Supplied Items", "no_copy": 1, - "options": "Purchase Receipt Item Supplied" + "options": "Purchase Receipt Item Supplied", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "section_break_26", - "fieldtype": "Section Break" + "fieldtype": "Section Break", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "total_qty", "fieldtype": "Float", "label": "Total Quantity", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "base_total", @@ -615,7 +737,9 @@ "label": "Total (Company Currency)", "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "base_net_total", @@ -625,18 +749,24 @@ "oldfieldtype": "Currency", "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break_28", - "fieldtype": "Column Break" + "fieldtype": "Column Break", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "total", "fieldtype": "Currency", "label": "Total", "options": "currency", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "net_total", @@ -646,42 +776,56 @@ "oldfieldtype": "Currency", "options": "currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "total_net_weight", "fieldtype": "Float", "label": "Total Net Weight", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "taxes_section", "fieldtype": "Section Break", "oldfieldtype": "Section Break", - "options": "fa fa-money" + "options": "fa fa-money", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "tax_category", "fieldtype": "Link", "label": "Tax Category", "options": "Tax Category", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break_49", - "fieldtype": "Column Break" + "fieldtype": "Column Break", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "shipping_rule", "fieldtype": "Link", "label": "Shipping Rule", "options": "Shipping Rule", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "section_break_51", - "fieldtype": "Section Break" + "fieldtype": "Section Break", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "taxes_and_charges", @@ -690,7 +834,9 @@ "oldfieldname": "purchase_other_charges", "oldfieldtype": "Link", "options": "Purchase Taxes and Charges Template", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "taxes", @@ -698,13 +844,17 @@ "label": "Purchase Taxes and Charges", "oldfieldname": "purchase_tax_details", "oldfieldtype": "Table", - "options": "Purchase Taxes and Charges" + "options": "Purchase Taxes and Charges", + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, "fieldname": "sec_tax_breakup", "fieldtype": "Section Break", - "label": "Tax Breakup" + "label": "Tax Breakup", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "other_charges_calculation", @@ -713,13 +863,17 @@ "no_copy": 1, "oldfieldtype": "HTML", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "totals", "fieldtype": "Section Break", "oldfieldtype": "Section Break", - "options": "fa fa-money" + "options": "fa fa-money", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "base_taxes_and_charges_added", @@ -729,7 +883,9 @@ "oldfieldtype": "Currency", "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "base_taxes_and_charges_deducted", @@ -739,7 +895,9 @@ "oldfieldtype": "Currency", "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "base_total_taxes_and_charges", @@ -749,11 +907,15 @@ "oldfieldtype": "Currency", "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break_40", - "fieldtype": "Column Break" + "fieldtype": "Column Break", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "taxes_and_charges_added", @@ -763,7 +925,9 @@ "oldfieldtype": "Currency", "options": "currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "taxes_and_charges_deducted", @@ -773,7 +937,9 @@ "oldfieldtype": "Currency", "options": "currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "total_taxes_and_charges", @@ -781,14 +947,18 @@ "label": "Total Taxes and Charges", "options": "currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, "collapsible_depends_on": "discount_amount", "fieldname": "section_break_44", "fieldtype": "Section Break", - "label": "Additional Discount" + "label": "Additional Discount", + "show_days": 1, + "show_seconds": 1 }, { "default": "Grand Total", @@ -796,7 +966,9 @@ "fieldtype": "Select", "label": "Apply Additional Discount On", "options": "\nGrand Total\nNet Total", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "base_discount_amount", @@ -804,28 +976,38 @@ "label": "Additional Discount Amount (Company Currency)", "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break_46", - "fieldtype": "Column Break" + "fieldtype": "Column Break", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "additional_discount_percentage", "fieldtype": "Float", "label": "Additional Discount Percentage", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "discount_amount", "fieldtype": "Currency", "label": "Additional Discount Amount", "options": "currency", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "section_break_49", - "fieldtype": "Section Break" + "fieldtype": "Section Break", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "base_grand_total", @@ -835,7 +1017,9 @@ "oldfieldtype": "Currency", "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval:!doc.disable_rounded_total", @@ -845,7 +1029,9 @@ "no_copy": 1, "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval:!doc.disable_rounded_total", @@ -855,7 +1041,9 @@ "no_copy": 1, "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "base_in_words", @@ -865,13 +1053,17 @@ "oldfieldname": "in_words", "oldfieldtype": "Data", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break8", "fieldtype": "Column Break", "oldfieldtype": "Column Break", "print_hide": 1, + "show_days": 1, + "show_seconds": 1, "width": "50%" }, { @@ -882,7 +1074,9 @@ "oldfieldname": "grand_total_import", "oldfieldtype": "Currency", "options": "currency", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval:!doc.disable_rounded_total", @@ -892,7 +1086,9 @@ "no_copy": 1, "options": "currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval:!doc.disable_rounded_total", @@ -902,7 +1098,9 @@ "no_copy": 1, "options": "currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "in_words", @@ -912,7 +1110,9 @@ "oldfieldname": "in_words_import", "oldfieldtype": "Data", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "total_advance", @@ -923,7 +1123,9 @@ "oldfieldtype": "Currency", "options": "party_account_currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "outstanding_amount", @@ -934,14 +1136,18 @@ "oldfieldtype": "Currency", "options": "party_account_currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "default": "0", "depends_on": "grand_total", "fieldname": "disable_rounded_total", "fieldtype": "Check", - "label": "Disable Rounded Total" + "label": "Disable Rounded Total", + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, @@ -949,20 +1155,26 @@ "depends_on": "eval:doc.is_paid===1||(doc.advances && doc.advances.length>0)", "fieldname": "payments_section", "fieldtype": "Section Break", - "label": "Payments" + "label": "Payments", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "mode_of_payment", "fieldtype": "Link", "label": "Mode of Payment", "options": "Mode of Payment", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "cash_bank_account", "fieldtype": "Link", "label": "Cash/Bank Account", - "options": "Account" + "options": "Account", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "clearance_date", @@ -970,11 +1182,15 @@ "label": "Clearance Date", "no_copy": 1, "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "col_br_payments", - "fieldtype": "Column Break" + "fieldtype": "Column Break", + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "is_paid", @@ -983,7 +1199,9 @@ "label": "Paid Amount", "no_copy": 1, "options": "currency", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "base_paid_amount", @@ -992,7 +1210,9 @@ "no_copy": 1, "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, @@ -1000,7 +1220,9 @@ "depends_on": "grand_total", "fieldname": "write_off", "fieldtype": "Section Break", - "label": "Write Off" + "label": "Write Off", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "write_off_amount", @@ -1008,7 +1230,9 @@ "label": "Write Off Amount", "no_copy": 1, "options": "currency", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "base_write_off_amount", @@ -1017,11 +1241,15 @@ "no_copy": 1, "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break_61", - "fieldtype": "Column Break" + "fieldtype": "Column Break", + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval:flt(doc.write_off_amount)!=0", @@ -1029,7 +1257,9 @@ "fieldtype": "Link", "label": "Write Off Account", "options": "Account", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval:flt(doc.write_off_amount)!=0", @@ -1037,7 +1267,9 @@ "fieldtype": "Link", "label": "Write Off Cost Center", "options": "Cost Center", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, @@ -1047,13 +1279,17 @@ "label": "Advance Payments", "oldfieldtype": "Section Break", "options": "fa fa-money", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "default": "0", "fieldname": "allocate_advances_automatically", "fieldtype": "Check", - "label": "Set Advances and Allocate (FIFO)" + "label": "Set Advances and Allocate (FIFO)", + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval:!doc.allocate_advances_automatically", @@ -1061,7 +1297,9 @@ "fieldtype": "Button", "label": "Get Advances Paid", "oldfieldtype": "Button", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "advances", @@ -1071,20 +1309,26 @@ "oldfieldname": "advance_allocation_details", "oldfieldtype": "Table", "options": "Purchase Invoice Advance", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, "collapsible_depends_on": "eval:(!doc.is_return)", "fieldname": "payment_schedule_section", "fieldtype": "Section Break", - "label": "Payment Terms" + "label": "Payment Terms", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "payment_terms_template", "fieldtype": "Link", "label": "Payment Terms Template", - "options": "Payment Terms Template" + "options": "Payment Terms Template", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "payment_schedule", @@ -1092,7 +1336,9 @@ "label": "Payment Schedule", "no_copy": 1, "options": "Payment Schedule", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, @@ -1100,25 +1346,33 @@ "fieldname": "terms_section_break", "fieldtype": "Section Break", "label": "Terms and Conditions", - "options": "fa fa-legal" + "options": "fa fa-legal", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "tc_name", "fieldtype": "Link", "label": "Terms", "options": "Terms and Conditions", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "terms", "fieldtype": "Text Editor", - "label": "Terms and Conditions1" + "label": "Terms and Conditions1", + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, "fieldname": "printing_settings", "fieldtype": "Section Break", - "label": "Printing Settings" + "label": "Printing Settings", + "show_days": 1, + "show_seconds": 1 }, { "allow_on_submit": 1, @@ -1126,7 +1380,9 @@ "fieldtype": "Link", "label": "Letter Head", "options": "Letter Head", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "allow_on_submit": 1, @@ -1134,11 +1390,15 @@ "fieldname": "group_same_items", "fieldtype": "Check", "label": "Group same items", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break_112", - "fieldtype": "Column Break" + "fieldtype": "Column Break", + "show_days": 1, + "show_seconds": 1 }, { "allow_on_submit": 1, @@ -1150,14 +1410,18 @@ "oldfieldtype": "Link", "options": "Print Heading", "print_hide": 1, - "report_hide": 1 + "report_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "language", "fieldtype": "Data", "label": "Print Language", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, @@ -1166,7 +1430,9 @@ "label": "More Information", "oldfieldtype": "Section Break", "options": "fa fa-file-text", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "credit_to", @@ -1177,7 +1443,9 @@ "options": "Account", "print_hide": 1, "reqd": 1, - "search_index": 1 + "search_index": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "party_account_currency", @@ -1187,7 +1455,9 @@ "no_copy": 1, "options": "Currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "default": "No", @@ -1197,7 +1467,9 @@ "oldfieldname": "is_opening", "oldfieldtype": "Select", "options": "No\nYes", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "against_expense_account", @@ -1207,11 +1479,15 @@ "no_copy": 1, "oldfieldname": "against_expense_account", "oldfieldtype": "Small Text", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break_63", - "fieldtype": "Column Break" + "fieldtype": "Column Break", + "show_days": 1, + "show_seconds": 1 }, { "default": "Draft", @@ -1220,7 +1496,9 @@ "in_standard_filter": 1, "label": "Status", "options": "\nDraft\nReturn\nDebit Note Issued\nSubmitted\nPaid\nUnpaid\nOverdue\nCancelled\nInternal Transfer", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "inter_company_invoice_reference", @@ -1229,7 +1507,9 @@ "no_copy": 1, "options": "Sales Invoice", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "remarks", @@ -1238,14 +1518,18 @@ "no_copy": 1, "oldfieldname": "remarks", "oldfieldtype": "Text", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, "fieldname": "subscription_section", "fieldtype": "Section Break", "label": "Subscription Section", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "allow_on_submit": 1, @@ -1254,7 +1538,9 @@ "fieldtype": "Date", "label": "From Date", "no_copy": 1, - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "allow_on_submit": 1, @@ -1263,11 +1549,15 @@ "fieldtype": "Date", "label": "To Date", "no_copy": 1, - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break_114", - "fieldtype": "Column Break" + "fieldtype": "Column Break", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "auto_repeat", @@ -1276,24 +1566,32 @@ "no_copy": 1, "options": "Auto Repeat", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "allow_on_submit": 1, "depends_on": "eval: doc.auto_repeat", "fieldname": "update_auto_repeat_reference", "fieldtype": "Button", - "label": "Update Auto Repeat Reference" + "label": "Update Auto Repeat Reference", + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, "fieldname": "accounting_dimensions_section", "fieldtype": "Section Break", - "label": "Accounting Dimensions " + "label": "Accounting Dimensions ", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "dimension_col_break", - "fieldtype": "Column Break" + "fieldtype": "Column Break", + "show_days": 1, + "show_seconds": 1 }, { "default": "0", @@ -1301,7 +1599,9 @@ "fieldname": "is_internal_supplier", "fieldtype": "Check", "label": "Is Internal Supplier", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "tax_withholding_category", @@ -1309,25 +1609,33 @@ "hidden": 1, "label": "Tax Withholding Category", "options": "Tax Withholding Category", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "billing_address", "fieldtype": "Link", "label": "Select Billing Address", - "options": "Address" + "options": "Address", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "billing_address_display", "fieldtype": "Small Text", "label": "Billing Address", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "project", "fieldtype": "Link", "label": "Project", - "options": "Project" + "options": "Project", + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval:doc.is_internal_supplier", @@ -1335,7 +1643,9 @@ "fieldname": "unrealized_profit_loss_account", "fieldtype": "Link", "label": "Unrealized Profit / Loss Account", - "options": "Account" + "options": "Account", + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval:doc.is_internal_supplier", @@ -1344,7 +1654,9 @@ "fieldname": "represents_company", "fieldtype": "Link", "label": "Represents Company", - "options": "Company" + "options": "Company", + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval:doc.update_stock && doc.is_internal_supplier", @@ -1356,6 +1668,8 @@ "options": "Warehouse", "print_hide": 1, "print_width": "50px", + "show_days": 1, + "show_seconds": 1, "width": "50px" }, { @@ -1367,6 +1681,8 @@ "options": "Warehouse", "print_hide": 1, "print_width": "50px", + "show_days": 1, + "show_seconds": 1, "width": "50px" }, { @@ -1377,13 +1693,29 @@ "no_copy": 1, "print_hide": 1, "read_only": 1 + }, + { + "fieldname": "additional_discount_account", + "fieldtype": "Link", + "label": "Additional Discount Account", + "options": "Account" + }, + { + "default": "0", + "fieldname": "ignore_default_payment_terms_template", + "fieldtype": "Check", + "hidden": 1, + "label": "Ignore Default Payment Terms Template", + "read_only": 1, + "show_days": 1, + "show_seconds": 1 } ], "icon": "fa fa-file-text", "idx": 204, "is_submittable": 1, "links": [], - "modified": "2021-06-15 18:20:56.806195", + "modified": "2021-08-07 17:53:14.351439", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice", diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index f7992797ed4..d7d9a3886a5 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -446,6 +446,7 @@ class PurchaseInvoice(BuyingController): self.make_supplier_gl_entry(gl_entries) self.make_item_gl_entries(gl_entries) + self.make_discount_gl_entries(gl_entries) if self.check_asset_cwip_enabled(): self.get_asset_gl_entry(gl_entries) @@ -518,6 +519,8 @@ class PurchaseInvoice(BuyingController): if d.category in ('Valuation', 'Total and Valuation') and flt(d.base_tax_amount_after_discount_amount)] + enable_discount_accounting = cint(frappe.db.get_single_value('Accounts Settings', 'enable_discount_accounting')) + for item in self.get("items"): if flt(item.base_net_amount): account_currency = get_account_currency(item.expense_account) @@ -608,7 +611,7 @@ class PurchaseInvoice(BuyingController): if (not item.enable_deferred_expense or self.is_return) else item.deferred_expense_account) if not item.is_fixed_asset: - amount = flt(item.base_net_amount, item.precision("base_net_amount")) + dummy, amount = self.get_amount_and_base_amount(item, enable_discount_accounting) else: amount = flt(item.base_net_amount + item.item_tax_amount, item.precision("base_net_amount")) @@ -822,8 +825,11 @@ class PurchaseInvoice(BuyingController): def make_tax_gl_entries(self, gl_entries): # tax table gl entries valuation_tax = {} + enable_discount_accounting = cint(frappe.db.get_single_value('Accounts Settings', 'enable_discount_accounting')) + for tax in self.get("taxes"): - if tax.category in ("Total", "Valuation and Total") and flt(tax.base_tax_amount_after_discount_amount): + amount, base_amount = self.get_tax_amounts(tax, enable_discount_accounting) + if tax.category in ("Total", "Valuation and Total") and flt(base_amount): account_currency = get_account_currency(tax.account_head) dr_or_cr = "debit" if tax.add_deduct_tax == "Add" else "credit" @@ -832,21 +838,21 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict({ "account": tax.account_head, "against": self.supplier, - dr_or_cr: tax.base_tax_amount_after_discount_amount, - dr_or_cr + "_in_account_currency": tax.base_tax_amount_after_discount_amount \ - if account_currency==self.company_currency \ - else tax.tax_amount_after_discount_amount, + dr_or_cr: base_amount, + dr_or_cr + "_in_account_currency": base_amount + if account_currency==self.company_currency + else amount, "cost_center": tax.cost_center }, account_currency, item=tax) ) # accumulate valuation tax - if self.is_opening == "No" and tax.category in ("Valuation", "Valuation and Total") and flt(tax.base_tax_amount_after_discount_amount) \ + if self.is_opening == "No" and tax.category in ("Valuation", "Valuation and Total") and flt(base_amount) \ and not self.is_internal_transfer(): if self.auto_accounting_for_stock and not tax.cost_center: frappe.throw(_("Cost Center is required in row {0} in Taxes table for type {1}").format(tax.idx, _(tax.category))) valuation_tax.setdefault(tax.name, 0) valuation_tax[tax.name] += \ - (tax.add_deduct_tax == "Add" and 1 or -1) * flt(tax.base_tax_amount_after_discount_amount) + (tax.add_deduct_tax == "Add" and 1 or -1) * flt(base_amount) if self.is_opening == "No" and self.negative_expense_to_be_booked and valuation_tax: # credit valuation tax amount in "Expenses Included In Valuation" diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index 4bc22a544d1..f0f5a58d153 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -230,6 +230,50 @@ class TestPurchaseInvoice(unittest.TestCase): self.assertEqual(expected_values[gle.account][1], gle.debit) self.assertEqual(expected_values[gle.account][2], gle.credit) + def test_purchase_invoice_with_discount_accounting_enabled(self): + enable_discount_accounting() + + discount_account = create_account(account_name="Discount Account", + parent_account="Indirect Expenses - _TC", company="_Test Company") + pi = make_purchase_invoice(discount_account=discount_account, rate=45) + + expected_gle = [ + ["_Test Account Cost for Goods Sold - _TC", 250.0, 0.0, nowdate()], + ["Creditors - _TC", 0.0, 225.0, nowdate()], + ["Discount Account - _TC", 0.0, 25.0, nowdate()] + ] + + check_gl_entries(self, pi.name, expected_gle, nowdate()) + enable_discount_accounting(enable=0) + + def test_additional_discount_for_purchase_invoice_with_discount_accounting_enabled(self): + enable_discount_accounting() + additional_discount_account = create_account(account_name="Discount Account", + parent_account="Indirect Expenses - _TC", company="_Test Company") + + pi = make_purchase_invoice(do_not_save=1, parent_cost_center="Main - _TC") + pi.apply_discount_on = "Grand Total" + pi.additional_discount_account = additional_discount_account + pi.additional_discount_percentage = 10 + pi.disable_rounded_total = 1 + pi.append("taxes", { + "charge_type": "On Net Total", + "account_head": "_Test Account VAT - _TC", + "cost_center": "Main - _TC", + "description": "Test", + "rate": 10 + }) + pi.submit() + + expected_gle = [ + ["_Test Account Cost for Goods Sold - _TC", 250.0, 0.0, nowdate()], + ["_Test Account VAT - _TC", 25.0, 0.0, nowdate()], + ["Creditors - _TC", 0.0, 247.5, nowdate()], + ["Discount Account - _TC", 0.0, 27.5, nowdate()] + ] + + check_gl_entries(self, pi.name, expected_gle, nowdate()) + def test_purchase_invoice_change_naming_series(self): pi = frappe.copy_doc(test_records[1]) pi.insert() @@ -1140,6 +1184,18 @@ class TestPurchaseInvoice(unittest.TestCase): self.assertEqual(expected_gle[i][0], gle.account) self.assertEqual(expected_gle[i][1], gle.amount) +def check_gl_entries(doc, voucher_no, expected_gle, posting_date): + gl_entries = frappe.db.sql("""select account, debit, credit, posting_date + from `tabGL Entry` + where voucher_type='Purchase Invoice' and voucher_no=%s and posting_date >= %s + order by posting_date asc, account asc""", (voucher_no, posting_date), as_dict=1) + + for i, gle in enumerate(gl_entries): + doc.assertEqual(expected_gle[i][0], gle.account) + doc.assertEqual(expected_gle[i][1], gle.debit) + doc.assertEqual(expected_gle[i][2], gle.credit) + doc.assertEqual(getdate(expected_gle[i][3]), gle.posting_date) + def update_tax_witholding_category(company, account, date): from erpnext.accounts.utils import get_fiscal_year @@ -1170,6 +1226,11 @@ def unlink_payment_on_cancel_of_invoice(enable=1): accounts_settings.unlink_payment_on_cancellation_of_invoice = enable accounts_settings.save() +def enable_discount_accounting(enable=1): + accounts_settings = frappe.get_doc("Accounts Settings") + accounts_settings.enable_discount_accounting = enable + accounts_settings.save() + def make_purchase_invoice(**args): pi = frappe.new_doc("Purchase Invoice") args = frappe._dict(args) @@ -1192,6 +1253,7 @@ def make_purchase_invoice(**args): pi.return_against = args.return_against pi.is_subcontracted = args.is_subcontracted or "No" pi.supplier_warehouse = args.supplier_warehouse or "_Test Warehouse 1 - _TC" + pi.cost_center = args.parent_cost_center pi.append("items", { "item_code": args.item or args.item_code or "_Test Item", @@ -1200,7 +1262,10 @@ def make_purchase_invoice(**args): "received_qty": args.received_qty or 0, "rejected_qty": args.rejected_qty or 0, "rate": args.rate or 50, - 'expense_account': args.expense_account or '_Test Account Cost for Goods Sold - _TC', + "price_list_rate": args.price_list_rate or 50, + "expense_account": args.expense_account or '_Test Account Cost for Goods Sold - _TC', + "discount_account": args.discount_account or None, + "discount_amount": args.discount_amount or 0, "conversion_factor": 1.0, "serial_no": args.serial_no, "stock_uom": args.uom or "_Test UOM", diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json index 8a55ff87e39..922b567d152 100644 --- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json +++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json @@ -73,6 +73,7 @@ "manufacturer_part_no", "accounting", "expense_account", + "discount_account", "col_break5", "is_fixed_asset", "asset_location", @@ -849,12 +850,18 @@ "options": "Company:company:default_currency", "print_hide": 1, "read_only": 1 + }, + { + "fieldname": "discount_account", + "fieldtype": "Link", + "label": "Discount Account", + "options": "Account" } ], "idx": 1, "istable": 1, "links": [], - "modified": "2021-06-16 19:57:03.101571", + "modified": "2021-07-13 02:04:37.787882", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice Item", diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index f813425e6b5..56f11650ffa 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -347,7 +347,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte items_add: function(doc, cdt, cdn) { var row = frappe.get_doc(cdt, cdn); - this.frm.script_manager.copy_from_first_row("items", row, ["income_account", "cost_center"]); + this.frm.script_manager.copy_from_first_row("items", row, ["income_account", "discount_account", "cost_center"]); }, set_dynamic_labels: function() { @@ -510,7 +510,6 @@ cur_frm.set_query("income_account", "items", function(doc) { } }); - // Cost Center in Details Table // ----------------------------- cur_frm.fields_dict["items"].grid.get_field("cost_center").get_query = function(doc) { @@ -592,6 +591,16 @@ frappe.ui.form.on('Sales Invoice', { }; }); + frm.set_query("additional_discount_account", function() { + return { + filters: { + company: frm.doc.company, + is_group: 0, + report_type: "Profit and Loss", + } + }; + }); + frm.custom_make_buttons = { 'Delivery Note': 'Delivery', 'Sales Invoice': 'Return / Credit Note', @@ -618,6 +627,17 @@ frappe.ui.form.on('Sales Invoice', { } } + // discount account + frm.fields_dict['items'].grid.get_field('discount_account').get_query = function(doc) { + return { + filters: { + 'report_type': 'Profit and Loss', + 'company': doc.company, + "is_group": 0 + } + } + } + frm.fields_dict['items'].grid.get_field('deferred_revenue_account').get_query = function(doc) { return { filters: { diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index 0a9a105b7ca..545b77a4a55 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -106,6 +106,7 @@ "section_break_49", "apply_discount_on", "base_discount_amount", + "additional_discount_account", "column_break_51", "additional_discount_percentage", "discount_amount", @@ -127,6 +128,7 @@ "get_advances", "advances", "payment_schedule_section", + "ignore_default_payment_terms_template", "payment_terms_template", "payment_schedule", "payments_section", @@ -197,7 +199,9 @@ "fieldtype": "Section Break", "hide_days": 1, "hide_seconds": 1, - "options": "fa fa-user" + "options": "fa fa-user", + "show_days": 1, + "show_seconds": 1 }, { "allow_on_submit": 1, @@ -209,7 +213,9 @@ "hide_seconds": 1, "label": "Title", "no_copy": 1, - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "bold": 1, @@ -224,7 +230,9 @@ "options": "ACC-SINV-.YYYY.-\nACC-SINV-RET-.YYYY.-", "print_hide": 1, "reqd": 1, - "set_only_once": 1 + "set_only_once": 1, + "show_days": 1, + "show_seconds": 1 }, { "bold": 1, @@ -238,7 +246,9 @@ "oldfieldtype": "Link", "options": "Customer", "print_hide": 1, - "search_index": 1 + "search_index": 1, + "show_days": 1, + "show_seconds": 1 }, { "bold": 1, @@ -252,7 +262,9 @@ "label": "Customer Name", "oldfieldname": "customer_name", "oldfieldtype": "Data", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "tax_id", @@ -261,7 +273,9 @@ "hide_seconds": 1, "label": "Tax Id", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "project", @@ -273,7 +287,9 @@ "oldfieldname": "project_name", "oldfieldtype": "Link", "options": "Project", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "default": "0", @@ -284,7 +300,9 @@ "label": "Include Payment (POS)", "oldfieldname": "is_pos", "oldfieldtype": "Check", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "is_pos", @@ -294,7 +312,9 @@ "hide_seconds": 1, "label": "POS Profile", "options": "POS Profile", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "default": "0", @@ -304,14 +324,18 @@ "hide_seconds": 1, "label": "Is Return (Credit Note)", "no_copy": 1, - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break1", "fieldtype": "Column Break", "hide_days": 1, "hide_seconds": 1, - "oldfieldtype": "Column Break" + "oldfieldtype": "Column Break", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "company", @@ -325,7 +349,9 @@ "options": "Company", "print_hide": 1, "remember_last_selected_value": 1, - "reqd": 1 + "reqd": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "cost_center", @@ -333,7 +359,9 @@ "hide_days": 1, "hide_seconds": 1, "label": "Cost Center", - "options": "Cost Center" + "options": "Cost Center", + "show_days": 1, + "show_seconds": 1 }, { "bold": 1, @@ -347,7 +375,9 @@ "oldfieldname": "posting_date", "oldfieldtype": "Date", "reqd": 1, - "search_index": 1 + "search_index": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "posting_time", @@ -358,7 +388,9 @@ "no_copy": 1, "oldfieldname": "posting_time", "oldfieldtype": "Time", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "default": "0", @@ -368,7 +400,9 @@ "hide_days": 1, "hide_seconds": 1, "label": "Edit Posting Date and Time", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "due_date", @@ -378,7 +412,9 @@ "label": "Payment Due Date", "no_copy": 1, "oldfieldname": "due_date", - "oldfieldtype": "Date" + "oldfieldtype": "Date", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "amended_from", @@ -392,7 +428,9 @@ "oldfieldtype": "Link", "options": "Sales Invoice", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval:doc.return_against || doc.is_debit_note", @@ -405,7 +443,9 @@ "options": "Sales Invoice", "print_hide": 1, "read_only_depends_on": "eval:doc.is_return", - "search_index": 1 + "search_index": 1, + "show_days": 1, + "show_seconds": 1 }, { "default": "0", @@ -414,7 +454,9 @@ "fieldtype": "Check", "hide_days": 1, "hide_seconds": 1, - "label": "Update Billed Amount in Sales Order" + "label": "Update Billed Amount in Sales Order", + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, @@ -423,7 +465,9 @@ "fieldtype": "Section Break", "hide_days": 1, "hide_seconds": 1, - "label": "Customer PO Details" + "label": "Customer PO Details", + "show_days": 1, + "show_seconds": 1 }, { "allow_on_submit": 1, @@ -433,13 +477,17 @@ "hide_seconds": 1, "label": "Customer's Purchase Order", "no_copy": 1, - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break_23", "fieldtype": "Column Break", "hide_days": 1, - "hide_seconds": 1 + "hide_seconds": 1, + "show_days": 1, + "show_seconds": 1 }, { "allow_on_submit": 1, @@ -447,7 +495,9 @@ "fieldtype": "Date", "hide_days": 1, "hide_seconds": 1, - "label": "Customer's Purchase Order Date" + "label": "Customer's Purchase Order Date", + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, @@ -455,7 +505,9 @@ "fieldtype": "Section Break", "hide_days": 1, "hide_seconds": 1, - "label": "Address and Contact" + "label": "Address and Contact", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "customer_address", @@ -464,7 +516,9 @@ "hide_seconds": 1, "label": "Customer Address", "options": "Address", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "address_display", @@ -472,7 +526,9 @@ "hide_days": 1, "hide_seconds": 1, "label": "Address", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "contact_person", @@ -482,7 +538,9 @@ "in_global_search": 1, "label": "Contact Person", "options": "Contact", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "contact_display", @@ -490,7 +548,9 @@ "hide_days": 1, "hide_seconds": 1, "label": "Contact", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "contact_mobile", @@ -499,7 +559,9 @@ "hide_days": 1, "hide_seconds": 1, "label": "Mobile No", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "contact_email", @@ -510,7 +572,9 @@ "label": "Contact Email", "options": "Email", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "territory", @@ -519,13 +583,17 @@ "hide_seconds": 1, "label": "Territory", "options": "Territory", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "col_break4", "fieldtype": "Column Break", "hide_days": 1, - "hide_seconds": 1 + "hide_seconds": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "shipping_address_name", @@ -534,7 +602,9 @@ "hide_seconds": 1, "label": "Shipping Address Name", "options": "Address", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "shipping_address", @@ -543,7 +613,9 @@ "hide_seconds": 1, "label": "Shipping Address", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "company_address", @@ -552,7 +624,9 @@ "hide_seconds": 1, "label": "Company Address Name", "options": "Address", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "company_address_display", @@ -562,7 +636,9 @@ "hide_seconds": 1, "label": "Company Address", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, @@ -571,7 +647,9 @@ "fieldtype": "Section Break", "hide_days": 1, "hide_seconds": 1, - "label": "Currency and Price List" + "label": "Currency and Price List", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "currency", @@ -583,7 +661,9 @@ "oldfieldtype": "Select", "options": "Currency", "print_hide": 1, - "reqd": 1 + "reqd": 1, + "show_days": 1, + "show_seconds": 1 }, { "description": "Rate at which Customer Currency is converted to customer's base currency", @@ -596,13 +676,17 @@ "oldfieldtype": "Currency", "precision": "9", "print_hide": 1, - "reqd": 1 + "reqd": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break2", "fieldtype": "Column Break", "hide_days": 1, "hide_seconds": 1, + "show_days": 1, + "show_seconds": 1, "width": "50%" }, { @@ -615,7 +699,9 @@ "oldfieldtype": "Select", "options": "Price List", "print_hide": 1, - "reqd": 1 + "reqd": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "price_list_currency", @@ -626,7 +712,9 @@ "options": "Currency", "print_hide": 1, "read_only": 1, - "reqd": 1 + "reqd": 1, + "show_days": 1, + "show_seconds": 1 }, { "description": "Rate at which Price list currency is converted to customer's base currency", @@ -637,7 +725,9 @@ "label": "Price List Exchange Rate", "precision": "9", "print_hide": 1, - "reqd": 1 + "reqd": 1, + "show_days": 1, + "show_seconds": 1 }, { "default": "0", @@ -648,14 +738,18 @@ "label": "Ignore Pricing Rule", "no_copy": 1, "permlevel": 1, - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "sec_warehouse", "fieldtype": "Section Break", "hide_days": 1, "hide_seconds": 1, - "label": "Warehouse" + "label": "Warehouse", + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "update_stock", @@ -665,7 +759,9 @@ "hide_seconds": 1, "label": "Source Warehouse", "options": "Warehouse", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "items_section", @@ -674,7 +770,9 @@ "hide_seconds": 1, "label": "Items", "oldfieldtype": "Section Break", - "options": "fa fa-shopping-cart" + "options": "fa fa-shopping-cart", + "show_days": 1, + "show_seconds": 1 }, { "default": "0", @@ -685,14 +783,18 @@ "label": "Update Stock", "oldfieldname": "update_stock", "oldfieldtype": "Check", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "scan_barcode", "fieldtype": "Data", "hide_days": 1, "hide_seconds": 1, - "label": "Scan Barcode" + "label": "Scan Barcode", + "show_days": 1, + "show_seconds": 1 }, { "allow_bulk_edit": 1, @@ -704,14 +806,18 @@ "oldfieldname": "entries", "oldfieldtype": "Table", "options": "Sales Invoice Item", - "reqd": 1 + "reqd": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "pricing_rule_details", "fieldtype": "Section Break", "hide_days": 1, "hide_seconds": 1, - "label": "Pricing Rules" + "label": "Pricing Rules", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "pricing_rules", @@ -720,7 +826,9 @@ "hide_seconds": 1, "label": "Pricing Rule Detail", "options": "Pricing Rule Detail", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "packing_list", @@ -729,7 +837,9 @@ "hide_seconds": 1, "label": "Packing List", "options": "fa fa-suitcase", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "packed_items", @@ -738,7 +848,9 @@ "hide_seconds": 1, "label": "Packed Items", "options": "Packed Item", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "product_bundle_help", @@ -746,7 +858,9 @@ "hide_days": 1, "hide_seconds": 1, "label": "Product Bundle Help", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, @@ -756,7 +870,9 @@ "fieldtype": "Section Break", "hide_days": 1, "hide_seconds": 1, - "label": "Time Sheet List" + "label": "Time Sheet List", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "timesheets", @@ -765,7 +881,9 @@ "hide_seconds": 1, "label": "Time Sheets", "options": "Sales Invoice Timesheet", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "default": "0", @@ -776,13 +894,17 @@ "label": "Total Billing Amount", "options": "currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "section_break_30", "fieldtype": "Section Break", "hide_days": 1, - "hide_seconds": 1 + "hide_seconds": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "total_qty", @@ -790,7 +912,9 @@ "hide_days": 1, "hide_seconds": 1, "label": "Total Quantity", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "base_total", @@ -800,7 +924,9 @@ "label": "Total (Company Currency)", "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "base_net_total", @@ -813,13 +939,17 @@ "options": "Company:company:default_currency", "print_hide": 1, "read_only": 1, - "reqd": 1 + "reqd": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break_32", "fieldtype": "Column Break", "hide_days": 1, - "hide_seconds": 1 + "hide_seconds": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "total", @@ -828,7 +958,9 @@ "hide_seconds": 1, "label": "Total", "options": "currency", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "net_total", @@ -838,7 +970,9 @@ "label": "Net Total", "options": "currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "total_net_weight", @@ -847,7 +981,9 @@ "hide_seconds": 1, "label": "Total Net Weight", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "taxes_section", @@ -855,7 +991,9 @@ "hide_days": 1, "hide_seconds": 1, "oldfieldtype": "Section Break", - "options": "fa fa-money" + "options": "fa fa-money", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "taxes_and_charges", @@ -866,13 +1004,17 @@ "oldfieldname": "charge", "oldfieldtype": "Link", "options": "Sales Taxes and Charges Template", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break_38", "fieldtype": "Column Break", "hide_days": 1, - "hide_seconds": 1 + "hide_seconds": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "shipping_rule", @@ -882,7 +1024,9 @@ "label": "Shipping Rule", "oldfieldtype": "Button", "options": "Shipping Rule", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "tax_category", @@ -891,13 +1035,17 @@ "hide_seconds": 1, "label": "Tax Category", "options": "Tax Category", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "section_break_40", "fieldtype": "Section Break", "hide_days": 1, - "hide_seconds": 1 + "hide_seconds": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "taxes", @@ -907,7 +1055,9 @@ "label": "Sales Taxes and Charges", "oldfieldname": "other_charges", "oldfieldtype": "Table", - "options": "Sales Taxes and Charges" + "options": "Sales Taxes and Charges", + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, @@ -915,7 +1065,9 @@ "fieldtype": "Section Break", "hide_days": 1, "hide_seconds": 1, - "label": "Tax Breakup" + "label": "Tax Breakup", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "other_charges_calculation", @@ -926,13 +1078,17 @@ "no_copy": 1, "oldfieldtype": "HTML", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "section_break_43", "fieldtype": "Section Break", "hide_days": 1, - "hide_seconds": 1 + "hide_seconds": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "base_total_taxes_and_charges", @@ -944,13 +1100,17 @@ "oldfieldtype": "Currency", "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break_47", "fieldtype": "Column Break", "hide_days": 1, - "hide_seconds": 1 + "hide_seconds": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "total_taxes_and_charges", @@ -960,7 +1120,9 @@ "label": "Total Taxes and Charges", "options": "currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, @@ -968,7 +1130,9 @@ "fieldtype": "Section Break", "hide_days": 1, "hide_seconds": 1, - "label": "Loyalty Points Redemption" + "label": "Loyalty Points Redemption", + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "redeem_loyalty_points", @@ -978,7 +1142,9 @@ "hide_seconds": 1, "label": "Loyalty Points", "no_copy": 1, - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "redeem_loyalty_points", @@ -990,7 +1156,9 @@ "no_copy": 1, "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "default": "0", @@ -1000,13 +1168,17 @@ "hide_seconds": 1, "label": "Redeem Loyalty Points", "no_copy": 1, - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break_77", "fieldtype": "Column Break", "hide_days": 1, - "hide_seconds": 1 + "hide_seconds": 1, + "show_days": 1, + "show_seconds": 1 }, { "fetch_from": "customer.loyalty_program", @@ -1018,7 +1190,9 @@ "no_copy": 1, "options": "Loyalty Program", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "redeem_loyalty_points", @@ -1028,7 +1202,9 @@ "hide_seconds": 1, "label": "Redemption Account", "no_copy": 1, - "options": "Account" + "options": "Account", + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "redeem_loyalty_points", @@ -1038,7 +1214,9 @@ "hide_seconds": 1, "label": "Redemption Cost Center", "no_copy": 1, - "options": "Cost Center" + "options": "Cost Center", + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, @@ -1047,7 +1225,9 @@ "fieldtype": "Section Break", "hide_days": 1, "hide_seconds": 1, - "label": "Additional Discount" + "label": "Additional Discount", + "show_days": 1, + "show_seconds": 1 }, { "default": "Grand Total", @@ -1057,7 +1237,9 @@ "hide_seconds": 1, "label": "Apply Additional Discount On", "options": "\nGrand Total\nNet Total", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "base_discount_amount", @@ -1067,13 +1249,17 @@ "label": "Additional Discount Amount (Company Currency)", "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break_51", "fieldtype": "Column Break", "hide_days": 1, - "hide_seconds": 1 + "hide_seconds": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "additional_discount_percentage", @@ -1081,7 +1267,9 @@ "hide_days": 1, "hide_seconds": 1, "label": "Additional Discount Percentage", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "discount_amount", @@ -1090,7 +1278,9 @@ "hide_seconds": 1, "label": "Additional Discount Amount", "options": "currency", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "totals", @@ -1099,7 +1289,9 @@ "hide_seconds": 1, "oldfieldtype": "Section Break", "options": "fa fa-money", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "base_grand_total", @@ -1112,7 +1304,9 @@ "options": "Company:company:default_currency", "print_hide": 1, "read_only": 1, - "reqd": 1 + "reqd": 1, + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval:!doc.disable_rounded_total", @@ -1124,7 +1318,9 @@ "no_copy": 1, "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval:!doc.disable_rounded_total", @@ -1137,7 +1333,9 @@ "oldfieldtype": "Currency", "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "description": "In Words will be visible once you save the Sales Invoice.", @@ -1150,7 +1348,9 @@ "oldfieldname": "in_words", "oldfieldtype": "Data", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break5", @@ -1159,6 +1359,8 @@ "hide_seconds": 1, "oldfieldtype": "Column Break", "print_hide": 1, + "show_days": 1, + "show_seconds": 1, "width": "50%" }, { @@ -1173,7 +1375,9 @@ "oldfieldtype": "Currency", "options": "currency", "read_only": 1, - "reqd": 1 + "reqd": 1, + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval:!doc.disable_rounded_total", @@ -1185,7 +1389,9 @@ "no_copy": 1, "options": "currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "bold": 1, @@ -1198,7 +1404,9 @@ "oldfieldname": "rounded_total_export", "oldfieldtype": "Currency", "options": "currency", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "in_words", @@ -1210,7 +1418,9 @@ "oldfieldname": "in_words_export", "oldfieldtype": "Data", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "total_advance", @@ -1222,7 +1432,9 @@ "oldfieldtype": "Currency", "options": "party_account_currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "outstanding_amount", @@ -1235,7 +1447,9 @@ "oldfieldtype": "Currency", "options": "party_account_currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, @@ -1247,7 +1461,9 @@ "label": "Advance Payments", "oldfieldtype": "Section Break", "options": "fa fa-money", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "default": "0", @@ -1255,7 +1471,9 @@ "fieldtype": "Check", "hide_days": 1, "hide_seconds": 1, - "label": "Allocate Advances Automatically (FIFO)" + "label": "Allocate Advances Automatically (FIFO)", + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval:!doc.allocate_advances_automatically", @@ -1264,7 +1482,9 @@ "hide_days": 1, "hide_seconds": 1, "label": "Get Advances Received", - "options": "set_advances" + "options": "set_advances", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "advances", @@ -1275,7 +1495,9 @@ "oldfieldname": "advance_adjustment_details", "oldfieldtype": "Table", "options": "Sales Invoice Advance", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, @@ -1284,7 +1506,9 @@ "fieldtype": "Section Break", "hide_days": 1, "hide_seconds": 1, - "label": "Payment Terms" + "label": "Payment Terms", + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval:(!doc.is_pos && !doc.is_return)", @@ -1295,7 +1519,9 @@ "label": "Payment Terms Template", "no_copy": 1, "options": "Payment Terms Template", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval:(!doc.is_pos && !doc.is_return)", @@ -1306,7 +1532,9 @@ "label": "Payment Schedule", "no_copy": 1, "options": "Payment Schedule", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval:doc.is_pos===1||(doc.advances && doc.advances.length>0)", @@ -1315,7 +1543,9 @@ "hide_days": 1, "hide_seconds": 1, "label": "Payments", - "options": "fa fa-money" + "options": "fa fa-money", + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "is_pos", @@ -1328,7 +1558,9 @@ "oldfieldname": "cash_bank_account", "oldfieldtype": "Link", "options": "Account", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval:doc.is_pos===1", @@ -1338,13 +1570,17 @@ "hide_seconds": 1, "label": "Sales Invoice Payment", "options": "Sales Invoice Payment", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "section_break_84", "fieldtype": "Section Break", "hide_days": 1, - "hide_seconds": 1 + "hide_seconds": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "base_paid_amount", @@ -1355,13 +1591,17 @@ "no_copy": 1, "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break_86", "fieldtype": "Column Break", "hide_days": 1, - "hide_seconds": 1 + "hide_seconds": 1, + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval: doc.is_pos || doc.redeem_loyalty_points", @@ -1375,13 +1615,17 @@ "oldfieldtype": "Currency", "options": "currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "section_break_88", "fieldtype": "Section Break", "hide_days": 1, - "hide_seconds": 1 + "hide_seconds": 1, + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "is_pos", @@ -1393,13 +1637,17 @@ "no_copy": 1, "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break_90", "fieldtype": "Column Break", "hide_days": 1, - "hide_seconds": 1 + "hide_seconds": 1, + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "is_pos", @@ -1410,7 +1658,9 @@ "label": "Change Amount", "no_copy": 1, "options": "currency", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "is_pos", @@ -1420,7 +1670,9 @@ "hide_seconds": 1, "label": "Account for Change Amount", "options": "Account", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, @@ -1431,6 +1683,8 @@ "hide_days": 1, "hide_seconds": 1, "label": "Write Off", + "show_days": 1, + "show_seconds": 1, "width": "50%" }, { @@ -1441,7 +1695,9 @@ "label": "Write Off Amount", "no_copy": 1, "options": "currency", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "base_write_off_amount", @@ -1452,7 +1708,9 @@ "no_copy": 1, "options": "Company:company:default_currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "default": "0", @@ -1462,13 +1720,17 @@ "hide_days": 1, "hide_seconds": 1, "label": "Write Off Outstanding Amount", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break_74", "fieldtype": "Column Break", "hide_days": 1, - "hide_seconds": 1 + "hide_seconds": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "write_off_account", @@ -1477,7 +1739,9 @@ "hide_seconds": 1, "label": "Write Off Account", "options": "Account", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "write_off_cost_center", @@ -1486,7 +1750,9 @@ "hide_seconds": 1, "label": "Write Off Cost Center", "options": "Cost Center", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, @@ -1496,7 +1762,9 @@ "hide_days": 1, "hide_seconds": 1, "label": "Terms and Conditions", - "oldfieldtype": "Section Break" + "oldfieldtype": "Section Break", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "tc_name", @@ -1507,7 +1775,9 @@ "oldfieldname": "tc_name", "oldfieldtype": "Link", "options": "Terms and Conditions", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "terms", @@ -1516,7 +1786,9 @@ "hide_seconds": 1, "label": "Terms and Conditions Details", "oldfieldname": "terms", - "oldfieldtype": "Text Editor" + "oldfieldtype": "Text Editor", + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, @@ -1524,7 +1796,9 @@ "fieldtype": "Section Break", "hide_days": 1, "hide_seconds": 1, - "label": "Printing Settings" + "label": "Printing Settings", + "show_days": 1, + "show_seconds": 1 }, { "allow_on_submit": 1, @@ -1536,7 +1810,9 @@ "oldfieldname": "letter_head", "oldfieldtype": "Select", "options": "Letter Head", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "allow_on_submit": 1, @@ -1546,7 +1822,9 @@ "hide_days": 1, "hide_seconds": 1, "label": "Group same items", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "language", @@ -1555,13 +1833,17 @@ "hide_seconds": 1, "label": "Print Language", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break_84", "fieldtype": "Column Break", "hide_days": 1, - "hide_seconds": 1 + "hide_seconds": 1, + "show_days": 1, + "show_seconds": 1 }, { "allow_on_submit": 1, @@ -1575,7 +1857,9 @@ "oldfieldtype": "Link", "options": "Print Heading", "print_hide": 1, - "report_hide": 1 + "report_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, @@ -1584,7 +1868,9 @@ "fieldtype": "Section Break", "hide_days": 1, "hide_seconds": 1, - "label": "More Information" + "label": "More Information", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "inter_company_invoice_reference", @@ -1593,7 +1879,9 @@ "hide_seconds": 1, "label": "Inter Company Invoice Reference", "options": "Purchase Invoice", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "customer_group", @@ -1603,7 +1891,9 @@ "hide_seconds": 1, "label": "Customer Group", "options": "Customer Group", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "campaign", @@ -1614,7 +1904,9 @@ "oldfieldname": "campaign", "oldfieldtype": "Link", "options": "Campaign", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "default": "0", @@ -1624,13 +1916,17 @@ "hide_seconds": 1, "label": "Is Discounted", "no_copy": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "col_break23", "fieldtype": "Column Break", "hide_days": 1, "hide_seconds": 1, + "show_days": 1, + "show_seconds": 1, "width": "50%" }, { @@ -1644,7 +1940,9 @@ "no_copy": 1, "options": "\nDraft\nReturn\nCredit Note Issued\nSubmitted\nPaid\nUnpaid\nUnpaid and Discounted\nOverdue and Discounted\nOverdue\nCancelled\nInternal Transfer", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "source", @@ -1655,7 +1953,9 @@ "oldfieldname": "source", "oldfieldtype": "Select", "options": "Lead Source", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, @@ -1666,7 +1966,9 @@ "label": "Accounting Details", "oldfieldtype": "Section Break", "options": "fa fa-file-text", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "debit_to", @@ -1679,7 +1981,9 @@ "options": "Account", "print_hide": 1, "reqd": 1, - "search_index": 1 + "search_index": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "party_account_currency", @@ -1691,7 +1995,9 @@ "no_copy": 1, "options": "Currency", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "default": "No", @@ -1703,7 +2009,9 @@ "oldfieldname": "is_opening", "oldfieldtype": "Select", "options": "No\nYes", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "c_form_applicable", @@ -1713,7 +2021,9 @@ "label": "C-Form Applicable", "no_copy": 1, "options": "No\nYes", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "c_form_no", @@ -1724,7 +2034,9 @@ "no_copy": 1, "options": "C-Form", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break8", @@ -1732,7 +2044,9 @@ "hide_days": 1, "hide_seconds": 1, "oldfieldtype": "Column Break", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "remarks", @@ -1743,7 +2057,9 @@ "no_copy": 1, "oldfieldname": "remarks", "oldfieldtype": "Text", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, @@ -1755,7 +2071,9 @@ "label": "Commission", "oldfieldtype": "Section Break", "options": "fa fa-group", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "sales_partner", @@ -1766,7 +2084,9 @@ "oldfieldname": "sales_partner", "oldfieldtype": "Link", "options": "Sales Partner", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break10", @@ -1775,6 +2095,8 @@ "hide_seconds": 1, "oldfieldtype": "Column Break", "print_hide": 1, + "show_days": 1, + "show_seconds": 1, "width": "50%" }, { @@ -1785,7 +2107,9 @@ "label": "Commission Rate (%)", "oldfieldname": "commission_rate", "oldfieldtype": "Currency", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "total_commission", @@ -1796,7 +2120,9 @@ "oldfieldname": "total_commission", "oldfieldtype": "Currency", "options": "Company:company:default_currency", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, @@ -1806,7 +2132,9 @@ "hide_days": 1, "hide_seconds": 1, "label": "Sales Team", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "allow_on_submit": 1, @@ -1818,7 +2146,9 @@ "oldfieldname": "sales_team", "oldfieldtype": "Table", "options": "Sales Team", - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, @@ -1826,7 +2156,9 @@ "fieldtype": "Section Break", "hide_days": 1, "hide_seconds": 1, - "label": "Subscription Section" + "label": "Subscription Section", + "show_days": 1, + "show_seconds": 1 }, { "allow_on_submit": 1, @@ -1836,7 +2168,9 @@ "hide_seconds": 1, "label": "From Date", "no_copy": 1, - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "allow_on_submit": 1, @@ -1846,13 +2180,17 @@ "hide_seconds": 1, "label": "To Date", "no_copy": 1, - "print_hide": 1 + "print_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break_140", "fieldtype": "Column Break", "hide_days": 1, - "hide_seconds": 1 + "hide_seconds": 1, + "show_days": 1, + "show_seconds": 1 }, { "allow_on_submit": 1, @@ -1864,7 +2202,9 @@ "no_copy": 1, "options": "Auto Repeat", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "allow_on_submit": 1, @@ -1873,7 +2213,9 @@ "fieldtype": "Button", "hide_days": 1, "hide_seconds": 1, - "label": "Update Auto Repeat Reference" + "label": "Update Auto Repeat Reference", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "against_income_account", @@ -1886,7 +2228,9 @@ "oldfieldname": "against_income_account", "oldfieldtype": "Small Text", "print_hide": 1, - "report_hide": 1 + "report_hide": 1, + "show_days": 1, + "show_seconds": 1 }, { "collapsible": 1, @@ -1894,13 +2238,17 @@ "fieldtype": "Section Break", "hide_days": 1, "hide_seconds": 1, - "label": "Accounting Dimensions" + "label": "Accounting Dimensions", + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "dimension_col_break", "fieldtype": "Column Break", "hide_days": 1, - "hide_seconds": 1 + "hide_seconds": 1, + "show_days": 1, + "show_seconds": 1 }, { "default": "0", @@ -1908,7 +2256,9 @@ "fieldname": "is_consolidated", "fieldtype": "Check", "label": "Is Consolidated", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "default": "0", @@ -1918,14 +2268,18 @@ "hide_days": 1, "hide_seconds": 1, "label": "Is Internal Customer", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fetch_from": "company.tax_id", "fieldname": "company_tax_id", "fieldtype": "Data", "label": "Company Tax ID", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval:doc.is_internal_customer", @@ -1933,7 +2287,9 @@ "fieldname": "unrealized_profit_loss_account", "fieldtype": "Link", "label": "Unrealized Profit / Loss Account", - "options": "Account" + "options": "Account", + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval:doc.is_internal_customer", @@ -1943,31 +2299,57 @@ "fieldtype": "Link", "label": "Represents Company", "options": "Company", - "read_only": 1 + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "fieldname": "column_break_55", - "fieldtype": "Column Break" + "fieldtype": "Column Break", + "show_days": 1, + "show_seconds": 1 }, { "depends_on": "eval: doc.is_internal_customer && doc.update_stock", "fieldname": "set_target_warehouse", "fieldtype": "Link", "label": "Set Target Warehouse", - "options": "Warehouse" + "options": "Warehouse", + "show_days": 1, + "show_seconds": 1 }, { "default": "0", "fieldname": "is_debit_note", "fieldtype": "Check", - "label": "Is Debit Note" + "label": "Is Debit Note", + "show_days": 1, + "show_seconds": 1 }, { "default": "0", "depends_on": "grand_total", "fieldname": "disable_rounded_total", "fieldtype": "Check", - "label": "Disable Rounded Total" + "label": "Disable Rounded Total", + "show_days": 1, + "show_seconds": 1 + }, + { + "fieldname": "additional_discount_account", + "fieldtype": "Link", + "label": "Additional Discount Account", + "options": "Account" + }, + { + "default": "0", + "fieldname": "ignore_default_payment_terms_template", + "fieldtype": "Check", + "hidden": 1, + "label": "Ignore Default Payment Terms Template", + "read_only": 1, + "show_days": 1, + "show_seconds": 1 }, { "allow_on_submit": 1, @@ -1995,7 +2377,7 @@ "link_fieldname": "consolidated_invoice" } ], - "modified": "2021-07-08 14:03:55.502522", + "modified": "2021-08-07 23:02:20.445127", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 6d1f6249c13..2539de7b124 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -846,6 +846,7 @@ class SalesInvoice(SellingController): self.allocate_advance_taxes(gl_entries) self.make_item_gl_entries(gl_entries) + self.make_discount_gl_entries(gl_entries) # merge gl entries before adding pos entries gl_entries = merge_similar_entries(gl_entries) @@ -885,18 +886,22 @@ class SalesInvoice(SellingController): ) def make_tax_gl_entries(self, gl_entries): + enable_discount_accounting = cint(frappe.db.get_single_value('Accounts Settings', 'enable_discount_accounting')) + for tax in self.get("taxes"): + amount, base_amount = self.get_tax_amounts(tax, enable_discount_accounting) + if flt(tax.base_tax_amount_after_discount_amount): account_currency = get_account_currency(tax.account_head) gl_entries.append( self.get_gl_dict({ "account": tax.account_head, "against": self.customer, - "credit": flt(tax.base_tax_amount_after_discount_amount, + "credit": flt(base_amount, tax.precision("tax_amount_after_discount_amount")), - "credit_in_account_currency": (flt(tax.base_tax_amount_after_discount_amount, + "credit_in_account_currency": (flt(base_amount, tax.precision("base_tax_amount_after_discount_amount")) if account_currency==self.company_currency else - flt(tax.tax_amount_after_discount_amount, tax.precision("tax_amount_after_discount_amount"))), + flt(amount, tax.precision("tax_amount_after_discount_amount"))), "cost_center": tax.cost_center }, account_currency, item=tax) ) @@ -915,6 +920,8 @@ class SalesInvoice(SellingController): def make_item_gl_entries(self, gl_entries): # income account gl entries + enable_discount_accounting = cint(frappe.db.get_single_value('Accounts Settings', 'enable_discount_accounting')) + for item in self.get("items"): if flt(item.base_net_amount, item.precision("base_net_amount")): if item.is_fixed_asset: @@ -940,15 +947,17 @@ class SalesInvoice(SellingController): income_account = (item.income_account if (not item.enable_deferred_revenue or self.is_return) else item.deferred_revenue_account) + amount, base_amount = self.get_amount_and_base_amount(item, enable_discount_accounting) + account_currency = get_account_currency(income_account) gl_entries.append( self.get_gl_dict({ "account": income_account, "against": self.customer, - "credit": flt(item.base_net_amount, item.precision("base_net_amount")), - "credit_in_account_currency": (flt(item.base_net_amount, item.precision("base_net_amount")) + "credit": flt(base_amount, item.precision("base_net_amount")), + "credit_in_account_currency": (flt(base_amount, item.precision("base_net_amount")) if account_currency==self.company_currency - else flt(item.net_amount, item.precision("net_amount"))), + else flt(amount, item.precision("net_amount"))), "cost_center": item.cost_center, "project": item.project or self.project }, account_currency, item=item) @@ -959,6 +968,12 @@ class SalesInvoice(SellingController): erpnext.is_perpetual_inventory_enabled(self.company): gl_entries += super(SalesInvoice, self).get_gl_entries() + def set_asset_status(self, asset): + if self.is_return: + asset.set_status() + else: + asset.set_status("Sold" if self.docstatus==1 else None) + def make_loyalty_point_redemption_gle(self, gl_entries): if cint(self.redeem_loyalty_points): gl_entries.append( diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 70bccd7166e..12f03be2881 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -1986,6 +1986,54 @@ class TestSalesInvoice(unittest.TestCase): sales_invoice.save() self.assertEqual(sales_invoice.items[0].item_tax_template, "_Test Account Excise Duty @ 10 - _TC") + def test_sales_invoice_with_discount_accounting_enabled(self): + from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import enable_discount_accounting + + enable_discount_accounting() + + discount_account = create_account(account_name="Discount Account", + parent_account="Indirect Expenses - _TC", company="_Test Company") + si = create_sales_invoice(discount_account=discount_account, discount_percentage=10, rate=90) + + expected_gle = [ + ["Debtors - _TC", 90.0, 0.0, nowdate()], + ["Discount Account - _TC", 10.0, 0.0, nowdate()], + ["Sales - _TC", 0.0, 100.0, nowdate()] + ] + + check_gl_entries(self, si.name, expected_gle, add_days(nowdate(), -1)) + enable_discount_accounting(enable=0) + + def test_additional_discount_for_sales_invoice_with_discount_accounting_enabled(self): + from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import enable_discount_accounting + + enable_discount_accounting() + additional_discount_account = create_account(account_name="Discount Account", + parent_account="Indirect Expenses - _TC", company="_Test Company") + + si = create_sales_invoice(parent_cost_center='Main - _TC', do_not_save=1) + si.apply_discount_on = "Grand Total" + si.additional_discount_account = additional_discount_account + si.additional_discount_percentage = 20 + si.append("taxes", { + "charge_type": "On Net Total", + "account_head": "_Test Account VAT - _TC", + "cost_center": "Main - _TC", + "description": "Test", + "rate": 10 + }) + si.submit() + + expected_gle = [ + ["_Test Account VAT - _TC", 0.0, 10.0, nowdate()], + ["Debtors - _TC", 88, 0.0, nowdate()], + ["Discount Account - _TC", 22.0, 0.0, nowdate()], + ["Sales - _TC", 0.0, 100.0, nowdate()] + ] + + check_gl_entries(self, si.name, expected_gle, add_days(nowdate(), -1)) + enable_discount_accounting(enable=0) + def get_sales_invoice_for_e_invoice(): si = make_sales_invoice_for_ewaybill() si.naming_series = 'INV-2020-.#####' @@ -2179,6 +2227,7 @@ def create_sales_invoice(**args): si.currency=args.currency or "INR" si.conversion_rate = args.conversion_rate or 1 si.naming_series = args.naming_series or "T-SINV-" + si.cost_center = args.parent_cost_center si.append("items", { "item_code": args.item or args.item_code or "_Test Item", @@ -2190,8 +2239,11 @@ def create_sales_invoice(**args): "uom": args.uom or "Nos", "stock_uom": args.uom or "Nos", "rate": args.rate if args.get("rate") is not None else 100, + "price_list_rate": args.price_list_rate if args.get("price_list_rate") is not None else 100, "income_account": args.income_account or "Sales - _TC", "expense_account": args.expense_account or "Cost of Goods Sold - _TC", + "discount_account": args.discount_account or None, + "discount_amount": args.discount_amount or 0, "cost_center": args.cost_center or "_Test Cost Center - _TC", "serial_no": args.serial_no, "conversion_factor": 1 diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json index 8e6952a93c4..b65903bf5e8 100644 --- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json +++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json @@ -63,6 +63,7 @@ "finance_book", "col_break4", "expense_account", + "discount_account", "deferred_revenue", "deferred_revenue_account", "service_stop_date", @@ -821,12 +822,18 @@ "no_copy": 1, "options": "currency", "read_only": 1 + }, + { + "fieldname": "discount_account", + "fieldtype": "Link", + "label": "Discount Account", + "options": "Account" } ], "idx": 1, "istable": 1, "links": [], - "modified": "2021-02-23 01:05:22.123527", + "modified": "2021-07-05 15:07:22.857128", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice Item", diff --git a/erpnext/accounts/doctype/subscription_plan/subscription_plan.json b/erpnext/accounts/doctype/subscription_plan/subscription_plan.json index 46ce0939e4f..771611a7860 100644 --- a/erpnext/accounts/doctype/subscription_plan/subscription_plan.json +++ b/erpnext/accounts/doctype/subscription_plan/subscription_plan.json @@ -78,7 +78,7 @@ "label": "Cost" }, { - "depends_on": "eval:doc.price_determination==\"Based on price list\"", + "depends_on": "eval:doc.price_determination==\"Based On Price List\"", "fieldname": "price_list", "fieldtype": "Link", "label": "Price List", @@ -147,7 +147,7 @@ } ], "links": [], - "modified": "2020-06-25 10:53:44.205774", + "modified": "2021-08-09 10:53:44.205774", "modified_by": "Administrator", "module": "Accounts", "name": "Subscription Plan", diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index b97dc401e6a..329f9a97b86 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -8,7 +8,7 @@ from frappe import _, msgprint, scrub from frappe.core.doctype.user_permission.user_permission import get_permitted_documents from frappe.model.utils import get_fetch_values from frappe.utils import (add_days, getdate, formatdate, date_diff, - add_years, get_timestamp, nowdate, flt, cstr, add_months, get_last_day) + add_years, get_timestamp, nowdate, flt, cstr, add_months, get_last_day, cint) from frappe.contacts.doctype.address.address import (get_address_display, get_default_address, get_company_address) from frappe.contacts.doctype.contact.contact import get_contact_details @@ -58,7 +58,7 @@ def _get_party_details(party=None, account=None, party_type="Customer", company= customer_group=party_details.customer_group, supplier_group=party_details.supplier_group, tax_category=party_details.tax_category, billing_address=party_address, shipping_address=shipping_address) - if fetch_payment_terms_template: + if cint(fetch_payment_terms_template): party_details["payment_terms_template"] = get_payment_terms_template(party.name, party_type, company) if not party_details.get("currency"): diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index eaa502ff7f0..a0b1e073cc6 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -447,10 +447,11 @@ def get_mapped_purchase_invoice(source_name, target_doc=None, ignore_permissions target.flags.ignore_permissions = ignore_permissions set_missing_values(source, target) #Get the advance paid Journal Entries in Purchase Invoice Advance - if target.get("allocate_advances_automatically"): target.set_advances() + target.set_payment_schedule() + def update_item(obj, target, source_parent): target.amount = flt(obj.amount) - flt(obj.billed_amt) target.base_amount = target.amount * flt(source_parent.conversion_rate) @@ -470,6 +471,7 @@ def get_mapped_purchase_invoice(source_name, target_doc=None, ignore_permissions "party_account_currency": "party_account_currency", "supplier_warehouse":"supplier_warehouse" }, + "field_no_map" : ["payment_terms_template"], "validation": { "docstatus": ["=", 1], } @@ -489,12 +491,6 @@ def get_mapped_purchase_invoice(source_name, target_doc=None, ignore_permissions }, } - if frappe.get_single("Accounts Settings").automatically_fetch_payment_terms == 1: - fields["Payment Schedule"] = { - "doctype": "Payment Schedule", - "add_if_empty": True - } - doc = get_mapped_doc("Purchase Order", source_name, fields, target_doc, postprocess, ignore_permissions=ignore_permissions) diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py index 8563b97ab74..d668c76b6b9 100644 --- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py @@ -484,6 +484,9 @@ class TestPurchaseOrder(unittest.TestCase): def test_make_purchase_invoice_with_terms(self): + from erpnext.selling.doctype.sales_order.test_sales_order import automatically_fetch_payment_terms, compare_payment_schedules + + automatically_fetch_payment_terms() po = create_purchase_order(do_not_save=True) self.assertRaises(frappe.ValidationError, make_pi_from_po, po.name) @@ -509,6 +512,7 @@ class TestPurchaseOrder(unittest.TestCase): self.assertEqual(getdate(pi.payment_schedule[0].due_date), getdate(po.transaction_date)) self.assertEqual(pi.payment_schedule[1].payment_amount, 2500.0) self.assertEqual(getdate(pi.payment_schedule[1].due_date), add_days(getdate(po.transaction_date), 30)) + automatically_fetch_payment_terms(enable=0) def test_subcontracting(self): po = create_purchase_order(item_code="_Test FG Item", is_subcontracted="Yes") @@ -632,14 +636,18 @@ class TestPurchaseOrder(unittest.TestCase): else: raise Exception - def test_terms_does_not_copy(self): - po = create_purchase_order() - - self.assertTrue(po.get('payment_schedule')) + def test_terms_are_not_copied_if_automatically_fetch_payment_terms_is_unchecked(self): + po = create_purchase_order(do_not_save=1) + po.payment_terms_template = '_Test Payment Term Template' + po.save() + po.submit() + frappe.db.set_value('Company', '_Test Company', 'payment_terms', '_Test Payment Term Template 1') pi = make_pi_from_po(po.name) + pi.save() - self.assertFalse(pi.get('payment_schedule')) + self.assertEqual(pi.get('payment_terms_template'), '_Test Payment Term Template 1') + frappe.db.set_value('Company', '_Test Company', 'payment_terms', '') def test_terms_copied(self): po = create_purchase_order(do_not_save=1) @@ -968,8 +976,27 @@ class TestPurchaseOrder(unittest.TestCase): # To test if the PO does NOT have a Blanket Order self.assertEqual(po_doc.items[0].blanket_order, None) + def test_payment_terms_are_fetched_when_creating_purchase_invoice(self): + from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_terms_template + from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice + from erpnext.selling.doctype.sales_order.test_sales_order import automatically_fetch_payment_terms, compare_payment_schedules + automatically_fetch_payment_terms() + po = create_purchase_order(qty=10, rate=100, do_not_save=1) + create_payment_terms_template() + po.payment_terms_template = 'Test Receivable Template' + po.submit() + + pi = make_purchase_invoice(qty=10, rate=100, do_not_save=1) + pi.items[0].purchase_order = po.name + pi.items[0].po_detail = po.items[0].name + pi.insert() + + # self.assertEqual(po.payment_terms_template, pi.payment_terms_template) + compare_payment_schedules(self, po, pi) + + automatically_fetch_payment_terms(enable=0) def make_pr_against_po(po, received_qty=0): pr = make_purchase_receipt(po) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index a9b7efbe980..d65efa24b4e 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -813,6 +813,89 @@ class AccountsController(TransactionBase): tax_map[tax.account_head] -= allocated_amount allocated_tax_map[tax.account_head] -= allocated_amount + def get_amount_and_base_amount(self, item, enable_discount_accounting): + amount = item.net_amount + base_amount = item.base_net_amount + + if enable_discount_accounting and self.get('discount_amount') and self.get('additional_discount_account'): + amount = item.amount + base_amount = item.base_amount + + return amount, base_amount + + def get_tax_amounts(self, tax, enable_discount_accounting): + amount = tax.tax_amount_after_discount_amount + base_amount = tax.base_tax_amount_after_discount_amount + + if enable_discount_accounting and self.get('discount_amount') and self.get('additional_discount_account') \ + and self.get('apply_discount_on') == 'Grand Total': + amount = tax.tax_amount + base_amount = tax.base_tax_amount + + return amount, base_amount + + def make_discount_gl_entries(self, gl_entries): + enable_discount_accounting = cint(frappe.db.get_single_value('Accounts Settings', 'enable_discount_accounting')) + + if enable_discount_accounting: + if self.doctype == "Purchase Invoice": + dr_or_cr = "credit" + rev_dr_cr = "debit" + supplier_or_customer = self.supplier + + else: + dr_or_cr = "debit" + rev_dr_cr = "credit" + supplier_or_customer = self.customer + + for item in self.get("items"): + if item.get('discount_amount') and item.get('discount_account'): + discount_amount = item.discount_amount * item.qty + if self.doctype == "Purchase Invoice": + income_or_expense_account = (item.expense_account + if (not item.enable_deferred_expense or self.is_return) + else item.deferred_expense_account) + else: + income_or_expense_account = (item.income_account + if (not item.enable_deferred_revenue or self.is_return) + else item.deferred_revenue_account) + + account_currency = get_account_currency(item.discount_account) + gl_entries.append( + self.get_gl_dict({ + "account": item.discount_account, + "against": supplier_or_customer, + dr_or_cr: flt(discount_amount, item.precision('discount_amount')), + dr_or_cr + "_in_account_currency": flt(discount_amount * self.get('conversion_rate'), + item.precision('discount_amount')), + "cost_center": item.cost_center, + "project": item.project + }, account_currency, item=item) + ) + + account_currency = get_account_currency(income_or_expense_account) + gl_entries.append( + self.get_gl_dict({ + "account": income_or_expense_account, + "against": supplier_or_customer, + rev_dr_cr: flt(discount_amount, item.precision('discount_amount')), + rev_dr_cr + "_in_account_currency": flt(discount_amount * self.get('conversion_rate'), + item.precision('discount_amount')), + "cost_center": item.cost_center, + "project": item.project or self.project + }, account_currency, item=item) + ) + + if self.get('discount_amount') and self.get('additional_discount_account'): + gl_entries.append( + self.get_gl_dict({ + "account": self.additional_discount_account, + "against": supplier_or_customer, + dr_or_cr: self.discount_amount, + "cost_center": self.cost_center + }, item=self) + ) + def allocate_advance_taxes(self, gl_entries): tax_map = self.get_tax_map() for pe in self.get("advances"): @@ -1096,6 +1179,8 @@ class AccountsController(TransactionBase): if self.doctype in ("Sales Invoice", "Purchase Invoice"): base_grand_total = base_grand_total - flt(self.base_write_off_amount) grand_total = grand_total - flt(self.write_off_amount) + po_or_so, doctype, fieldname = self.get_order_details() + automatically_fetch_payment_terms = cint(frappe.db.get_single_value('Accounts Settings', 'automatically_fetch_payment_terms')) if self.get("total_advance"): if party_account_currency == self.company_currency: @@ -1106,22 +1191,86 @@ class AccountsController(TransactionBase): base_grand_total = flt(grand_total * self.get("conversion_rate"), self.precision("base_grand_total")) if not self.get("payment_schedule"): - if self.get("payment_terms_template"): + if self.doctype in ["Sales Invoice", "Purchase Invoice"] and automatically_fetch_payment_terms \ + and self.linked_order_has_payment_terms(po_or_so, fieldname, doctype): + self.fetch_payment_terms_from_order(po_or_so, doctype) + if self.get('payment_terms_template'): + self.ignore_default_payment_terms_template = 1 + elif self.get("payment_terms_template"): data = get_payment_terms(self.payment_terms_template, posting_date, grand_total, base_grand_total) for item in data: self.append("payment_schedule", item) - else: + elif self.doctype not in ["Purchase Receipt"]: data = dict(due_date=due_date, invoice_portion=100, payment_amount=grand_total, base_payment_amount=base_grand_total) self.append("payment_schedule", data) - else: - for d in self.get("payment_schedule"): - if d.invoice_portion: - d.payment_amount = flt(grand_total * flt(d.invoice_portion / 100), d.precision('payment_amount')) - d.base_payment_amount = flt(base_grand_total * flt(d.invoice_portion / 100), d.precision('base_payment_amount')) - d.outstanding = d.payment_amount - elif not d.invoice_portion: - d.base_payment_amount = flt(base_grand_total * self.get("conversion_rate"), d.precision('base_payment_amount')) + for d in self.get("payment_schedule"): + if d.invoice_portion: + d.payment_amount = flt(grand_total * flt(d.invoice_portion / 100), d.precision('payment_amount')) + d.base_payment_amount = flt(base_grand_total * flt(d.invoice_portion / 100), d.precision('base_payment_amount')) + d.outstanding = d.payment_amount + elif not d.invoice_portion: + d.base_payment_amount = flt(base_grand_total * self.get("conversion_rate"), d.precision('base_payment_amount')) + + + def get_order_details(self): + if self.doctype == "Sales Invoice": + po_or_so = self.get('items')[0].get('sales_order') + po_or_so_doctype = "Sales Order" + po_or_so_doctype_name = "sales_order" + + else: + po_or_so = self.get('items')[0].get('purchase_order') + po_or_so_doctype = "Purchase Order" + po_or_so_doctype_name = "purchase_order" + + return po_or_so, po_or_so_doctype, po_or_so_doctype_name + + def linked_order_has_payment_terms(self, po_or_so, fieldname, doctype): + if po_or_so and self.all_items_have_same_po_or_so(po_or_so, fieldname): + if self.linked_order_has_payment_terms_template(po_or_so, doctype): + return True + elif self.linked_order_has_payment_schedule(po_or_so): + return True + + return False + + def all_items_have_same_po_or_so(self, po_or_so, fieldname): + for item in self.get('items'): + if item.get(fieldname) != po_or_so: + return False + + return True + + def linked_order_has_payment_terms_template(self, po_or_so, doctype): + return frappe.get_value(doctype, po_or_so, 'payment_terms_template') + + def linked_order_has_payment_schedule(self, po_or_so): + return frappe.get_all('Payment Schedule', filters={'parent': po_or_so}) + + def fetch_payment_terms_from_order(self, po_or_so, po_or_so_doctype): + """ + Fetch Payment Terms from Purchase/Sales Order on creating a new Purchase/Sales Invoice. + """ + po_or_so = frappe.get_cached_doc(po_or_so_doctype, po_or_so) + + self.payment_schedule = [] + self.payment_terms_template = po_or_so.payment_terms_template + + for schedule in po_or_so.payment_schedule: + payment_schedule = { + 'payment_term': schedule.payment_term, + 'due_date': schedule.due_date, + 'invoice_portion': schedule.invoice_portion, + 'mode_of_payment': schedule.mode_of_payment, + 'description': schedule.description + } + + if schedule.discount_type == 'Percentage': + payment_schedule['discount_type'] = schedule.discount_type + payment_schedule['discount'] = schedule.discount + + self.append("payment_schedule", payment_schedule) def set_due_date(self): due_dates = [d.due_date for d in self.get("payment_schedule") if d.due_date] @@ -1507,7 +1656,7 @@ def set_child_tax_template_and_map(item, child_item, parent_doc): if child_item.get("item_tax_template"): child_item.item_tax_rate = get_item_tax_map(parent_doc.get('company'), child_item.item_tax_template, as_json=True) -def add_taxes_from_tax_template(child_item, parent_doc): +def add_taxes_from_tax_template(child_item, parent_doc, db_insert=True): add_taxes_from_item_tax_template = frappe.db.get_single_value("Accounts Settings", "add_taxes_from_item_tax_template") if child_item.get("item_tax_rate") and add_taxes_from_item_tax_template: @@ -1530,7 +1679,8 @@ def add_taxes_from_tax_template(child_item, parent_doc): "category" : "Total", "add_deduct_tax" : "Add" }) - tax_row.db_insert() + if db_insert: + tax_row.db_insert() def set_order_defaults(parent_doctype, parent_doctype_name, child_doctype, child_docname, trans_item): """ @@ -1807,4 +1957,4 @@ def validate_regional(doc): @erpnext.allow_regional def validate_einvoice_fields(doc): - pass + pass \ No newline at end of file diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 6a550e0e975..974ade35849 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -72,7 +72,8 @@ class BuyingController(StockController, Subcontracting): # set contact and address details for supplier, if they are not mentioned if getattr(self, "supplier", None): self.update_if_missing(get_party_details(self.supplier, party_type="Supplier", ignore_permissions=self.flags.ignore_permissions, - doctype=self.doctype, company=self.company, party_address=self.supplier_address, shipping_address=self.get('shipping_address'))) + doctype=self.doctype, company=self.company, party_address=self.supplier_address, shipping_address=self.get('shipping_address'), + fetch_payment_terms_template= not self.get('ignore_default_payment_terms_template'))) self.set_missing_item_details(for_validate) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index cf5a2011b3d..b375308abbe 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -294,6 +294,7 @@ erpnext.patches.v13_0.update_level_in_bom #1234sswef erpnext.patches.v13_0.add_missing_fg_item_for_stock_entry erpnext.patches.v13_0.update_subscription_status_in_memberships erpnext.patches.v13_0.update_amt_in_work_order_required_items +erpnext.patches.v13_0.delete_orphaned_tables erpnext.patches.v13_0.update_export_type_for_gst erpnext.patches.v13_0.update_tds_check_field #3 erpnext.patches.v13_0.update_recipient_email_digest diff --git a/erpnext/patches/v13_0/delete_orphaned_tables.py b/erpnext/patches/v13_0/delete_orphaned_tables.py new file mode 100644 index 00000000000..1d6eebe0398 --- /dev/null +++ b/erpnext/patches/v13_0/delete_orphaned_tables.py @@ -0,0 +1,69 @@ +# Copyright (c) 2019, Frappe and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals + +import frappe +from frappe.utils import getdate + +def execute(): + frappe.reload_doc('setup', 'doctype', 'transaction_deletion_record') + + if has_deleted_company_transactions(): + child_doctypes = get_child_doctypes_whose_parent_doctypes_were_affected() + + for doctype in child_doctypes: + docs = frappe.get_all(doctype, fields=['name', 'parent', 'parenttype', 'creation']) + + for doc in docs: + if not frappe.db.exists(doc['parenttype'], doc['parent']): + frappe.db.delete(doctype, {'name': doc['name']}) + + elif check_for_new_doc_with_same_name_as_deleted_parent(doc): + frappe.db.delete(doctype, {'name': doc['name']}) + +def has_deleted_company_transactions(): + return frappe.get_all('Transaction Deletion Record') + +def get_child_doctypes_whose_parent_doctypes_were_affected(): + parent_doctypes = get_affected_doctypes() + child_doctypes = frappe.get_all( + 'DocField', + filters={ + 'fieldtype': 'Table', + 'parent':['in', parent_doctypes] + }, pluck='options') + + return child_doctypes + +def get_affected_doctypes(): + affected_doctypes = [] + tdr_docs = frappe.get_all('Transaction Deletion Record', pluck="name") + + for tdr in tdr_docs: + tdr_doc = frappe.get_doc("Transaction Deletion Record", tdr) + + for doctype in tdr_doc.doctypes: + if is_not_child_table(doctype.doctype_name): + affected_doctypes.append(doctype.doctype_name) + + affected_doctypes = remove_duplicate_items(affected_doctypes) + return affected_doctypes + +def is_not_child_table(doctype): + return not bool(frappe.get_value('DocType', doctype, 'istable')) + +def remove_duplicate_items(affected_doctypes): + return list(set(affected_doctypes)) + +def check_for_new_doc_with_same_name_as_deleted_parent(doc): + """ + Compares creation times of parent and child docs. + Since Transaction Deletion Record resets the naming series after deletion, + it allows the creation of new docs with the same names as the deleted ones. + """ + + parent_creation_time = frappe.db.get_value(doc['parenttype'], doc['parent'], 'creation') + child_creation_time = doc['creation'] + + return getdate(parent_creation_time) > getdate(child_creation_time) \ No newline at end of file diff --git a/erpnext/public/js/utils/party.js b/erpnext/public/js/utils/party.js index a79eadc7619..4d432e3d5cc 100644 --- a/erpnext/public/js/utils/party.js +++ b/erpnext/public/js/utils/party.js @@ -76,6 +76,7 @@ erpnext.utils.get_party_details = function(frm, method, args, callback) { if (args) { args.posting_date = frm.doc.posting_date || frm.doc.transaction_date; + args.fetch_payment_terms_template = cint(!frm.doc.ignore_default_payment_terms_template); } } if (!args || !args.party) return; diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 41f57a34d3d..bba54018aef 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -670,6 +670,7 @@ def make_sales_invoice(source_name, target_doc=None, ignore_permissions=False): "party_account_currency": "party_account_currency", "payment_terms_template": "payment_terms_template" }, + "field_no_map": ["payment_terms_template"], "validation": { "docstatus": ["=", 1] } @@ -693,6 +694,10 @@ def make_sales_invoice(source_name, target_doc=None, ignore_permissions=False): } }, target_doc, postprocess, ignore_permissions=ignore_permissions) + automatically_fetch_payment_terms = cint(frappe.db.get_single_value('Accounts Settings', 'automatically_fetch_payment_terms')) + if automatically_fetch_payment_terms: + doclist.set_payment_schedule() + return doclist @frappe.whitelist() diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index 974648d6d44..a226da75cd8 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -5,7 +5,7 @@ import json import unittest import frappe import frappe.permissions -from frappe.utils import flt, add_days, nowdate +from frappe.utils import flt, add_days, nowdate, getdate from frappe.core.doctype.user_permission.test_user_permission import create_user from erpnext.selling.doctype.sales_order.sales_order \ import make_material_request, make_delivery_note, make_sales_invoice, WarehouseRequired @@ -1229,7 +1229,38 @@ class TestSalesOrder(unittest.TestCase): self.assertRaises(frappe.ValidationError, so.cancel) + def test_payment_terms_are_fetched_when_creating_sales_invoice(self): + from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_terms_template + from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice + automatically_fetch_payment_terms() + + so = make_sales_order(uom="Nos", do_not_save=1) + create_payment_terms_template() + so.payment_terms_template = 'Test Receivable Template' + so.submit() + + si = create_sales_invoice(qty=10, do_not_save=1) + si.items[0].sales_order = so.name + si.items[0].so_detail = so.items[0].name + si.insert() + + self.assertEqual(so.payment_terms_template, si.payment_terms_template) + compare_payment_schedules(self, so, si) + + automatically_fetch_payment_terms(enable=0) + +def automatically_fetch_payment_terms(enable=1): + accounts_settings = frappe.get_doc("Accounts Settings") + accounts_settings.automatically_fetch_payment_terms = enable + accounts_settings.save() + +def compare_payment_schedules(doc, doc1, doc2): + for index, schedule in enumerate(doc1.get('payment_schedule')): + doc.assertEqual(schedule.payment_term, doc2.payment_schedule[index].payment_term) + doc.assertEqual(getdate(schedule.due_date), doc2.payment_schedule[index].due_date) + doc.assertEqual(schedule.invoice_portion, doc2.payment_schedule[index].invoice_portion) + doc.assertEqual(schedule.payment_amount, doc2.payment_schedule[index].payment_amount) def make_sales_order(**args): so = frappe.new_doc("Sales Order") diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index 4808e948fc6..f99a01b8202 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -503,6 +503,10 @@ def make_sales_invoice(source_name, target_doc=None): } }, target_doc, set_missing_values) + automatically_fetch_payment_terms = cint(frappe.db.get_single_value('Accounts Settings', 'automatically_fetch_payment_terms')) + if automatically_fetch_payment_terms: + doc.set_payment_schedule() + return doc @frappe.whitelist() diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index f981aeb13bb..756825e826d 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -17,7 +17,8 @@ from erpnext.stock.doctype.stock_entry.test_stock_entry \ from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos, SerialNoWarehouseError from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation \ import create_stock_reconciliation, set_valuation_method -from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order, create_dn_against_so +from erpnext.selling.doctype.sales_order.test_sales_order \ + import make_sales_order, create_dn_against_so, automatically_fetch_payment_terms, compare_payment_schedules from erpnext.accounts.doctype.account.test_account import get_inventory_account from erpnext.stock.doctype.warehouse.test_warehouse import get_warehouse from erpnext.stock.doctype.item.test_item import make_item @@ -759,6 +760,32 @@ class TestDeliveryNote(unittest.TestCase): self.assertTrue("TESTBATCH" in dn.packed_items[0].batch_no, "Batch number not added in packed item") + def test_payment_terms_are_fetched_when_creating_sales_invoice(self): + from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_terms_template + from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice + + automatically_fetch_payment_terms() + + so = make_sales_order(uom="Nos", do_not_save=1) + create_payment_terms_template() + so.payment_terms_template = 'Test Receivable Template' + so.submit() + + dn = create_dn_against_so(so.name, delivered_qty=10) + + si = create_sales_invoice(qty=10, do_not_save=1) + si.items[0].delivery_note= dn.name + si.items[0].dn_detail = dn.items[0].name + si.items[0].sales_order = so.name + si.items[0].so_detail = so.items[0].name + + si.insert() + si.submit() + + self.assertEqual(so.payment_terms_template, si.payment_terms_template) + compare_payment_schedules(self, so, si) + + automatically_fetch_payment_terms(enable=0) def create_delivery_note(**args): dn = frappe.new_doc("Delivery Note") diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js index d060c266b20..83dbcc12b5f 100644 --- a/erpnext/stock/doctype/item/item.js +++ b/erpnext/stock/doctype/item/item.js @@ -264,6 +264,17 @@ $.extend(erpnext.item, { } } + frm.fields_dict["item_defaults"].grid.get_field("default_discount_account").get_query = function(doc, cdt, cdn) { + const row = locals[cdt][cdn]; + return { + filters: { + 'report_type': 'Profit and Loss', + 'company': row.company, + "is_group": 0 + } + }; + }; + frm.fields_dict["item_defaults"].grid.get_field("buying_cost_center").get_query = function(doc, cdt, cdn) { const row = locals[cdt][cdn]; return { diff --git a/erpnext/stock/doctype/item_default/item_default.json b/erpnext/stock/doctype/item_default/item_default.json index 96b5dfdc8f7..bc171604f43 100644 --- a/erpnext/stock/doctype/item_default/item_default.json +++ b/erpnext/stock/doctype/item_default/item_default.json @@ -1,464 +1,118 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, - "creation": "2018-05-03 02:29:24.444341", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "actions": [], + "creation": "2018-05-03 02:29:24.444341", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "company", + "default_warehouse", + "column_break_3", + "default_price_list", + "default_discount_account", + "purchase_defaults", + "buying_cost_center", + "default_supplier", + "column_break_8", + "expense_account", + "selling_defaults", + "selling_cost_center", + "column_break_12", + "income_account" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "company", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 1, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Company", - "length": 0, - "no_copy": 0, - "options": "Company", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "company", + "fieldtype": "Link", + "ignore_user_permissions": 1, + "in_list_view": 1, + "label": "Company", + "options": "Company", + "reqd": 1 + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "default_warehouse", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Default Warehouse", - "length": 0, - "no_copy": 0, - "options": "Warehouse", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "default_warehouse", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Default Warehouse", + "options": "Warehouse" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_3", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_3", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "default_price_list", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Default Price List", - "length": 0, - "no_copy": 0, - "options": "Price List", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "default_price_list", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Default Price List", + "options": "Price List" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "purchase_defaults", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Purchase Defaults", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "purchase_defaults", + "fieldtype": "Section Break", + "label": "Purchase Defaults" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "buying_cost_center", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Default Buying Cost Center", - "length": 0, - "no_copy": 0, - "options": "Cost Center", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "buying_cost_center", + "fieldtype": "Link", + "label": "Default Buying Cost Center", + "options": "Cost Center" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "default_supplier", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Default Supplier", - "length": 0, - "no_copy": 0, - "options": "Supplier", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "default_supplier", + "fieldtype": "Link", + "label": "Default Supplier", + "options": "Supplier" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_8", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_8", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "expense_account", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Default Expense Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "expense_account", + "fieldtype": "Link", + "label": "Default Expense Account", + "options": "Account" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "selling_defaults", - "fieldtype": "Section Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Sales Defaults", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "selling_defaults", + "fieldtype": "Section Break", + "label": "Sales Defaults" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "selling_cost_center", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Default Selling Cost Center", - "length": 0, - "no_copy": 0, - "options": "Cost Center", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "selling_cost_center", + "fieldtype": "Link", + "label": "Default Selling Cost Center", + "options": "Cost Center" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_12", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_12", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "income_account", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Default Income Account", - "length": 0, - "no_copy": 0, - "options": "Account", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldname": "income_account", + "fieldtype": "Link", + "label": "Default Income Account", + "options": "Account" + }, + { + "fieldname": "default_discount_account", + "fieldtype": "Link", + "label": "Default Discount Account", + "options": "Account" } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 1, - "max_attachments": 0, - "modified": "2018-12-07 11:48:07.638935", - "modified_by": "Administrator", - "module": "Stock", - "name": "Item Default", - "name_case": "", - "owner": "Administrator", - "permissions": [], - "quick_entry": 1, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 + ], + "istable": 1, + "links": [], + "modified": "2021-07-13 01:26:03.860065", + "modified_by": "Administrator", + "module": "Stock", + "name": "Item Default", + "owner": "Administrator", + "permissions": [], + "quick_entry": 1, + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/stock/doctype/item_quality_inspection_parameter/item_quality_inspection_parameter.json b/erpnext/stock/doctype/item_quality_inspection_parameter/item_quality_inspection_parameter.json index 9b1a47eed6c..5de45cbcad9 100644 --- a/erpnext/stock/doctype/item_quality_inspection_parameter/item_quality_inspection_parameter.json +++ b/erpnext/stock/doctype/item_quality_inspection_parameter/item_quality_inspection_parameter.json @@ -47,7 +47,8 @@ "description": "Simple Python formula applied on Reading fields.
Numeric eg. 1: reading_1 > 0.2 and reading_1 < 0.5
\nNumeric eg. 2: mean > 3.5 (mean of populated fields)
\nValue based eg.: reading_value in (\"A\", \"B\", \"C\")", "fieldname": "acceptance_formula", "fieldtype": "Code", - "label": "Acceptance Criteria Formula" + "label": "Acceptance Criteria Formula", + "options": "PythonExpression" }, { "default": "0", @@ -89,7 +90,7 @@ "idx": 1, "istable": 1, "links": [], - "modified": "2021-02-04 18:50:02.056173", + "modified": "2021-08-06 15:08:20.911338", "modified_by": "Administrator", "module": "Stock", "name": "Item Quality Inspection Parameter", diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index 3ad9909ad07..026b85e26d2 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -162,8 +162,15 @@ class MaterialRequest(BuyingController): from `tabStock Entry Detail` where material_request = %s and material_request_item = %s and docstatus = 1""", (self.name, d.name))[0][0]) + mr_qty_allowance = frappe.db.get_single_value('Stock Settings', 'mr_qty_allowance') - if d.ordered_qty and d.ordered_qty > d.stock_qty: + if mr_qty_allowance: + allowed_qty = d.qty + (d.qty * (mr_qty_allowance/100)) + if d.ordered_qty and d.ordered_qty > allowed_qty: + frappe.throw(_("The total Issue / Transfer quantity {0} in Material Request {1} \ + cannot be greater than allowed requested quantity {2} for Item {3}").format(d.ordered_qty, d.parent, allowed_qty, d.item_code)) + + elif d.ordered_qty and d.ordered_qty > d.stock_qty: frappe.throw(_("The total Issue / Transfer quantity {0} in Material Request {1} \ cannot be greater than requested quantity {2} for Item {3}").format(d.ordered_qty, d.parent, d.qty, d.item_code)) diff --git a/erpnext/stock/doctype/material_request/test_material_request.py b/erpnext/stock/doctype/material_request/test_material_request.py index 72a3a5e67c7..b4776ba2492 100644 --- a/erpnext/stock/doctype/material_request/test_material_request.py +++ b/erpnext/stock/doctype/material_request/test_material_request.py @@ -329,6 +329,58 @@ class TestMaterialRequest(unittest.TestCase): self.assertEqual(current_requested_qty_item1, existing_requested_qty_item1 + 54.0) self.assertEqual(current_requested_qty_item2, existing_requested_qty_item2 + 3.0) + def test_over_transfer_qty_allowance(self): + mr = frappe.new_doc('Material Request') + mr.company = "_Test Company" + mr.scheduled_date = today() + mr.append('items',{ + "item_code": "_Test FG Item", + "item_name": "_Test FG Item", + "qty": 10, + "schedule_date": today(), + "uom": "_Test UOM 1", + "warehouse": "_Test Warehouse - _TC" + }) + + mr.material_request_type = "Material Transfer" + mr.insert() + mr.submit() + + frappe.db.set_value('Stock Settings', None, 'mr_qty_allowance', 20) + + # map a stock entry + + se_doc = make_stock_entry(mr.name) + se_doc.update({ + "posting_date": today(), + "posting_time": "00:00", + }) + se_doc.get("items")[0].update({ + "qty": 13, + "transfer_qty": 12.0, + "s_warehouse": "_Test Warehouse - _TC", + "t_warehouse": "_Test Warehouse 1 - _TC", + "basic_rate": 1.0 + }) + + # make available the qty in _Test Warehouse 1 before transfer + sr = frappe.new_doc("Stock Reconciliation") + sr.company = "_Test Company" + sr.purpose = "Opening Stock" + sr.append('items', { + "item_code": "_Test FG Item", + "warehouse": "_Test Warehouse - _TC", + "qty": 20, + "valuation_rate": 0.01 + }) + sr.insert() + sr.submit() + se = frappe.copy_doc(se_doc) + se.insert() + self.assertRaises(frappe.ValidationError) + se.items[0].qty = 12 + se.submit() + def test_completed_qty_for_over_transfer(self): existing_requested_qty_item1 = self._get_requested_qty("_Test Item Home Desktop 100", "_Test Warehouse - _TC") existing_requested_qty_item2 = self._get_requested_qty("_Test Item Home Desktop 200", "_Test Warehouse - _TC") diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 26ea11e01d9..a81eb603ab5 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -598,6 +598,7 @@ def make_purchase_invoice(source_name, target_doc=None): doc.run_method("onload") doc.run_method("set_missing_values") doc.run_method("calculate_taxes_and_totals") + doc.set_payment_schedule() def update_item(source_doc, target_doc, source_parent): target_doc.qty, returned_qty = get_pending_qty(source_doc) diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index ca6e61fe6b0..0210702250e 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -324,18 +324,7 @@ class TestPurchaseReceipt(unittest.TestCase): pr1.submit() self.assertRaises(frappe.ValidationError, pr2.submit) - - pr1.cancel() - se.cancel() - se1.cancel() - se2.cancel() - se3.cancel() - po.reload() - pr2.load_from_db() - pr2.cancel() - - po.load_from_db() - po.cancel() + frappe.db.rollback() def test_serial_no_supplier(self): pr = make_purchase_receipt(item_code="_Test Serialized Item With Series", qty=1) @@ -1040,7 +1029,7 @@ class TestPurchaseReceipt(unittest.TestCase): 'account': srbnb_account, 'voucher_detail_no': pr.items[1].name }, pluck="name") - + # check if the entries are not merged into one # seperate entries should be made since voucher_detail_no is different self.assertEqual(len(item_one_gl_entry), 1) @@ -1048,6 +1037,33 @@ class TestPurchaseReceipt(unittest.TestCase): frappe.db.set_value('Company', company, 'enable_perpetual_inventory_for_non_stock_items', before_test_value) + def test_payment_terms_are_fetched_when_creating_purchase_invoice(self): + from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_terms_template + from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice + from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order, make_pr_against_po + from erpnext.selling.doctype.sales_order.test_sales_order import automatically_fetch_payment_terms, compare_payment_schedules + + automatically_fetch_payment_terms() + + po = create_purchase_order(qty=10, rate=100, do_not_save=1) + create_payment_terms_template() + po.payment_terms_template = 'Test Receivable Template' + po.submit() + + pr = make_pr_against_po(po.name, received_qty=10) + + pi = make_purchase_invoice(qty=10, rate=100, do_not_save=1) + pi.items[0].purchase_receipt = pr.name + pi.items[0].pr_detail = pr.items[0].name + pi.items[0].purchase_order = po.name + pi.items[0].po_detail = po.items[0].name + pi.insert() + + # self.assertEqual(po.payment_terms_template, pi.payment_terms_template) + compare_payment_schedules(self, po, pi) + + automatically_fetch_payment_terms(enable=0) + def get_sl_entries(voucher_type, voucher_no): return frappe.db.sql(""" select actual_qty, warehouse, stock_value_difference from `tabStock Ledger Entry` where voucher_type=%s and voucher_no=%s diff --git a/erpnext/stock/doctype/stock_settings/stock_settings.json b/erpnext/stock/doctype/stock_settings/stock_settings.json index 2a9dcfb67ed..f75cb561385 100644 --- a/erpnext/stock/doctype/stock_settings/stock_settings.json +++ b/erpnext/stock/doctype/stock_settings/stock_settings.json @@ -18,6 +18,7 @@ "section_break_9", "over_delivery_receipt_allowance", "role_allowed_to_over_deliver_receive", + "mr_qty_allowance", "column_break_12", "auto_insert_price_list_rate_if_missing", "allow_negative_stock", @@ -283,6 +284,12 @@ "fieldtype": "Select", "label": "Action If Quality Inspection Is Rejected", "options": "Stop\nWarn" + }, + { + "description": "The percentage you are allowed to transfer more against the quantity ordered. For example, if you have ordered 100 units, and your Allowance is 10%, then you are allowed transfer 110 units.", + "fieldname": "mr_qty_allowance", + "fieldtype": "Float", + "label": "Over Transfer Allowance" } ], "icon": "icon-cog", @@ -290,7 +297,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2021-07-10 16:17:42.159829", + "modified": "2021-06-28 17:02:26.683002", "modified_by": "Administrator", "module": "Stock", "name": "Stock Settings", @@ -310,4 +317,4 @@ "sort_field": "modified", "sort_order": "ASC", "track_changes": 1 -} \ No newline at end of file +} diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index be8508a000b..a0fbcecc5de 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -286,6 +286,7 @@ def get_basic_details(args, item, overwrite_warehouse=True): "warehouse": warehouse, "income_account": get_default_income_account(args, item_defaults, item_group_defaults, brand_defaults), "expense_account": expense_account or get_default_expense_account(args, item_defaults, item_group_defaults, brand_defaults) , + "discount_account": None or get_default_discount_account(args, item_defaults), "cost_center": get_default_cost_center(args, item_defaults, item_group_defaults, brand_defaults), 'has_serial_no': item.has_serial_no, 'has_batch_no': item.has_batch_no, @@ -588,6 +589,10 @@ def get_default_expense_account(args, item, item_group, brand): or brand.get("expense_account") or args.expense_account) +def get_default_discount_account(args, item): + return (item.get("default_discount_account") + or args.discount_account) + def get_default_deferred_account(args, item, fieldname=None): if item.get("enable_deferred_revenue") or item.get("enable_deferred_expense"): return (item.get(fieldname) diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index 9c69deb6a48..e4c4af03651 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -222,6 +222,10 @@ class Issue(Document): }).insert(ignore_permissions=True) return replicated_issue.name + + def reset_issue_metrics(self): + self.db_set("resolution_time", None) + self.db_set("user_resolution_time", None) def before_insert(self): if frappe.db.get_single_value("Support Settings", "track_service_level_agreement"):