diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 277e584aeaf..34f35af5d57 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -3316,6 +3316,66 @@ class TestSalesInvoice(unittest.TestCase): ) self.assertRaises(frappe.ValidationError, si.submit) +<<<<<<< HEAD +======= + def test_advance_entries_as_liability(self): + from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_payment_entry + + account = create_account( + parent_account="Current Liabilities - _TC", + account_name="Advances Received", + company="_Test Company", + account_type="Receivable", + ) + + set_advance_flag(company="_Test Company", flag=1, default_account=account) + + pe = create_payment_entry( + company="_Test Company", + payment_type="Receive", + party_type="Customer", + party="_Test Customer", + paid_from="Debtors - _TC", + paid_to="Cash - _TC", + paid_amount=1000, + ) + pe.submit() + + si = create_sales_invoice( + company="_Test Company", + customer="_Test Customer", + do_not_save=True, + do_not_submit=True, + rate=500, + price_list_rate=500, + ) + si.base_grand_total = 500 + si.grand_total = 500 + si.set_advances() + for advance in si.advances: + advance.allocated_amount = 500 if advance.reference_name == pe.name else 0 + si.save() + si.submit() + + self.assertEqual(si.advances[0].allocated_amount, 500) + + # Check GL Entry against payment doctype + expected_gle = [ + ["Advances Received - _TC", 500, 0.0, nowdate()], + ["Cash - _TC", 1000, 0.0, nowdate()], + ["Debtors - _TC", 0.0, 1000, nowdate()], + ["Debtors - _TC", 0.0, 500, nowdate()], + ] + + check_gl_entries(self, pe.name, expected_gle, nowdate(), voucher_type="Payment Entry") + + si.load_from_db() + self.assertEqual(si.outstanding_amount, 0) + + set_advance_flag(company="_Test Company", flag=0, default_account="") + + @change_settings("Selling Settings", {"allow_negative_rates_for_items": 0}) +>>>>>>> a0fc68538f (refactor: toggle for negative rates in Selling Settings) def test_sales_return_negative_rate(self): si = create_sales_invoice(is_return=1, qty=-2, rate=-10, do_not_save=True) self.assertRaises(frappe.ValidationError, si.save) diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py index f3663cc5271..73a248fb531 100644 --- a/erpnext/controllers/status_updater.py +++ b/erpnext/controllers/status_updater.py @@ -5,7 +5,7 @@ import frappe from frappe import _ from frappe.model.document import Document -from frappe.utils import comma_or, flt, getdate, now, nowdate +from frappe.utils import comma_or, flt, get_link_to_form, getdate, now, nowdate class OverAllowanceError(frappe.ValidationError): @@ -233,8 +233,17 @@ class StatusUpdater(Document): if hasattr(d, "qty") and d.qty > 0 and self.get("is_return"): frappe.throw(_("For an item {0}, quantity must be negative number").format(d.item_code)) - if hasattr(d, "item_code") and hasattr(d, "rate") and flt(d.rate) < 0: - frappe.throw(_("For an item {0}, rate must be a positive number").format(d.item_code)) + if not frappe.db.get_single_value("Selling Settings", "allow_negative_rates_for_items"): + if hasattr(d, "item_code") and hasattr(d, "rate") and flt(d.rate) < 0: + frappe.throw( + _( + "For item {0}, rate must be a positive number. To Allow negative rates, enable {1} in {2}" + ).format( + frappe.bold(d.item_code), + frappe.bold(_("`Allow Negative rates for Items`")), + get_link_to_form("Selling Settings", "Selling Settings"), + ), + ) if d.doctype == args["source_dt"] and d.get(args["join_field"]): args["name"] = d.get(args["join_field"]) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 75f728afa88..0215f0830f3 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -328,13 +328,32 @@ erpnext.patches.v14_0.set_pick_list_status erpnext.patches.v13_0.update_docs_link erpnext.patches.v14_0.enable_all_leads execute:frappe.db.set_single_value("Accounts Settings", "merge_similar_account_heads", 0) +<<<<<<< HEAD # below migration patches should always run last erpnext.patches.v14_0.migrate_gl_to_payment_ledger +======= +erpnext.patches.v14_0.update_reference_type_in_journal_entry_accounts +erpnext.patches.v14_0.update_subscription_details +execute:frappe.delete_doc_if_exists("Report", "Tax Detail") +erpnext.patches.v15_0.enable_all_leads +>>>>>>> a0fc68538f (refactor: toggle for negative rates in Selling Settings) erpnext.patches.v14_0.update_company_in_ldc erpnext.patches.v14_0.set_packed_qty_in_draft_delivery_notes erpnext.patches.v14_0.cleanup_workspaces +<<<<<<< HEAD erpnext.patches.v14_0.enable_allow_existing_serial_no erpnext.patches.v14_0.set_report_in_process_SOA erpnext.patches.v14_0.create_accounting_dimensions_for_closing_balance erpnext.patches.v14_0.update_closing_balances #15-07-2023 -execute:frappe.defaults.clear_default("fiscal_year") \ No newline at end of file +execute:frappe.defaults.clear_default("fiscal_year") +======= +erpnext.patches.v15_0.remove_loan_management_module #2023-07-03 +erpnext.patches.v14_0.set_report_in_process_SOA +erpnext.buying.doctype.supplier.patches.migrate_supplier_portal_users +execute:frappe.defaults.clear_default("fiscal_year") +erpnext.patches.v15_0.remove_exotel_integration +erpnext.patches.v14_0.single_to_multi_dunning +execute:frappe.db.set_single_value('Selling Settings', 'allow_negative_rates_for_items', 0) +# below migration patch should always run last +erpnext.patches.v14_0.migrate_gl_to_payment_ledger +>>>>>>> a0fc68538f (refactor: toggle for negative rates in Selling Settings) diff --git a/erpnext/selling/doctype/selling_settings/selling_settings.json b/erpnext/selling/doctype/selling_settings/selling_settings.json index af148c51fb9..3417afa1282 100644 --- a/erpnext/selling/doctype/selling_settings/selling_settings.json +++ b/erpnext/selling/doctype/selling_settings/selling_settings.json @@ -20,6 +20,7 @@ "editable_price_list_rate", "validate_selling_price", "editable_bundle_item_rates", + "allow_negative_rates_for_items", "sales_transactions_settings_section", "so_required", "dn_required", @@ -186,6 +187,21 @@ "fieldname": "over_order_allowance", "fieldtype": "Float", "label": "Over Order Allowance (%)" +<<<<<<< HEAD +======= + }, + { + "default": "0", + "fieldname": "dont_reserve_sales_order_qty_on_sales_return", + "fieldtype": "Check", + "label": "Don't Reserve Sales Order Qty on Sales Return" + }, + { + "default": "0", + "fieldname": "allow_negative_rates_for_items", + "fieldtype": "Check", + "label": "Allow Negative rates for Items" +>>>>>>> a0fc68538f (refactor: toggle for negative rates in Selling Settings) } ], "icon": "fa fa-cog", @@ -193,7 +209,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-08-09 15:35:42.914354", + "modified": "2023-08-14 20:33:05.693667", "modified_by": "Administrator", "module": "Selling", "name": "Selling Settings",