Merge pull request #43067 from frappe/mergify/bp/version-15-hotfix/pr-41721

fix: distributed discounts on si (backport #41721)
This commit is contained in:
Sagar Vora
2025-04-19 16:35:12 +05:30
committed by GitHub
21 changed files with 161 additions and 18 deletions

View File

@@ -37,6 +37,7 @@
"column_break_19",
"discount_percentage",
"discount_amount",
"distributed_discount_amount",
"base_rate_with_margin",
"section_break1",
"rate",
@@ -847,11 +848,17 @@
{
"fieldname": "column_break_ciit",
"fieldtype": "Column Break"
},
{
"fieldname": "distributed_discount_amount",
"fieldtype": "Currency",
"label": "Distributed Discount Amount",
"options": "currency"
}
],
"istable": 1,
"links": [],
"modified": "2024-05-07 15:56:53.343317",
"modified": "2024-05-07 15:56:54.343317",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Invoice Item",

View File

@@ -39,6 +39,7 @@ class POSInvoiceItem(Document):
description: DF.TextEditor
discount_amount: DF.Currency
discount_percentage: DF.Percent
distributed_discount_amount: DF.Currency
dn_detail: DF.Data | None
enable_deferred_revenue: DF.Check
expense_account: DF.Link | None

View File

@@ -38,6 +38,7 @@
"column_break_30",
"discount_percentage",
"discount_amount",
"distributed_discount_amount",
"base_rate_with_margin",
"sec_break2",
"rate",
@@ -840,7 +841,7 @@
},
{
"collapsible": 1,
"collapsible_depends_on": "eval: doc.margin_type || doc.discount_amount",
"collapsible_depends_on": "eval: doc.margin_type || doc.discount_amount || doc.distributed_discount_amount",
"fieldname": "section_break_26",
"fieldtype": "Section Break",
"label": "Discount and Margin"
@@ -971,12 +972,18 @@
"no_copy": 1,
"options": "Company:company:default_currency",
"print_hide": 1
},
{
"fieldname": "distributed_discount_amount",
"fieldtype": "Currency",
"label": "Distributed Discount Amount",
"options": "currency"
}
],
"idx": 1,
"istable": 1,
"links": [],
"modified": "2025-03-12 16:33:12.453290",
"modified": "2025-03-12 16:33:13.453290",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",

View File

@@ -34,6 +34,7 @@ class PurchaseInvoiceItem(Document):
description: DF.TextEditor | None
discount_amount: DF.Currency
discount_percentage: DF.Percent
distributed_discount_amount: DF.Currency
enable_deferred_expense: DF.Check
expense_account: DF.Link | None
from_warehouse: DF.Link | None

View File

@@ -37,6 +37,7 @@
"column_break_19",
"discount_percentage",
"discount_amount",
"distributed_discount_amount",
"base_rate_with_margin",
"section_break1",
"rate",
@@ -259,7 +260,7 @@
},
{
"collapsible": 1,
"collapsible_depends_on": "eval: doc.margin_type || doc.discount_amount",
"collapsible_depends_on": "eval: doc.margin_type || doc.discount_amount || doc.distributed_discount_amount",
"fieldname": "discount_and_margin",
"fieldtype": "Section Break",
"label": "Discount and Margin"
@@ -932,6 +933,12 @@
"fieldname": "column_break_ytgd",
"fieldtype": "Column Break"
},
{
"fieldname": "distributed_discount_amount",
"fieldtype": "Currency",
"label": "Distributed Discount Amount",
"options": "currency"
},
{
"fieldname": "available_quantity_section",
"fieldtype": "Section Break",
@@ -976,7 +983,7 @@
"idx": 1,
"istable": 1,
"links": [],
"modified": "2025-03-12 16:33:52.503777",
"modified": "2025-03-12 16:33:55.503777",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Item",

View File

@@ -40,6 +40,7 @@ class SalesInvoiceItem(Document):
discount_account: DF.Link | None
discount_amount: DF.Currency
discount_percentage: DF.Percent
distributed_discount_amount: DF.Currency
dn_detail: DF.Data | None
enable_deferred_revenue: DF.Check
expense_account: DF.Link | None

View File

@@ -43,6 +43,7 @@
"column_break_28",
"discount_percentage",
"discount_amount",
"distributed_discount_amount",
"base_rate_with_margin",
"sec_break2",
"rate",
@@ -781,7 +782,7 @@
},
{
"collapsible": 1,
"collapsible_depends_on": "eval: doc.margin_type || doc.discount_amount",
"collapsible_depends_on": "eval: doc.margin_type || doc.discount_amount || doc.distributed_discount_amount",
"fieldname": "discount_and_margin_section",
"fieldtype": "Section Break",
"label": "Discount and Margin"
@@ -911,6 +912,12 @@
"fieldname": "column_break_fyqr",
"fieldtype": "Column Break"
},
{
"fieldname": "distributed_discount_amount",
"fieldtype": "Currency",
"label": "Distributed Discount Amount",
"options": "currency"
},
{
"allow_on_submit": 1,
"depends_on": "eval:parent.is_subcontracted && !parent.is_old_subcontracting_flow",
@@ -927,7 +934,7 @@
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2025-03-13 17:27:43.468602",
"modified": "2025-03-13 17:27:44.468602",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order Item",

View File

@@ -37,6 +37,7 @@ class PurchaseOrderItem(Document):
description: DF.TextEditor | None
discount_amount: DF.Currency
discount_percentage: DF.Percent
distributed_discount_amount: DF.Currency
expected_delivery_date: DF.Date | None
expense_account: DF.Link | None
fg_item: DF.Link | None

View File

@@ -32,6 +32,7 @@
"price_list_rate",
"discount_percentage",
"discount_amount",
"distributed_discount_amount",
"col_break_price_list",
"base_price_list_rate",
"sec_break1",
@@ -565,13 +566,19 @@
{
"fieldname": "dimension_col_break",
"fieldtype": "Column Break"
},
{
"fieldname": "distributed_discount_amount",
"fieldtype": "Currency",
"label": "Distributed Discount Amount",
"options": "currency"
}
],
"idx": 1,
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2023-11-17 12:25:26.235367",
"modified": "2024-06-02 06:22:18.864822",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Quotation Item",

View File

@@ -26,6 +26,7 @@ class SupplierQuotationItem(Document):
description: DF.TextEditor | None
discount_amount: DF.Currency
discount_percentage: DF.Percent
distributed_discount_amount: DF.Currency
expected_delivery_date: DF.Date | None
image: DF.Attach | None
is_free_item: DF.Check

View File

@@ -1841,8 +1841,11 @@ class AccountsController(TransactionBase):
and self.get("discount_amount")
and self.get("additional_discount_account")
):
amount = item.amount
base_amount = item.base_amount
amount += item.distributed_discount_amount
base_amount += flt(
item.distributed_discount_amount * self.get("conversion_rate"),
item.precision("distributed_discount_amount"),
)
return amount, base_amount

View File

@@ -695,6 +695,9 @@ class calculate_taxes_and_totals:
adjusted_net_amount = item.net_amount - distributed_amount
expected_net_total += adjusted_net_amount
item.net_amount = flt(adjusted_net_amount, item.precision("net_amount"))
item.distributed_discount_amount = flt(
distributed_amount, item.precision("distributed_discount_amount")
)
net_total += item.net_amount
# discount amount rounding adjustment
@@ -704,6 +707,10 @@ class calculate_taxes_and_totals:
item.net_amount = flt(
item.net_amount + rounding_difference, item.precision("net_amount")
)
item.distributed_discount_amount = flt(
distributed_amount + rounding_difference,
item.precision("distributed_discount_amount"),
)
net_total += rounding_difference
item.net_rate = (

View File

@@ -0,0 +1,61 @@
from frappe.tests.utils import FrappeTestCase
from erpnext.accounts.test.accounts_mixin import AccountsTestMixin
from erpnext.controllers.taxes_and_totals import calculate_taxes_and_totals
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
class TestTaxesAndTotals(AccountsTestMixin, FrappeTestCase):
def test_distributed_discount_amount(self):
so = make_sales_order(do_not_save=1)
so.apply_discount_on = "Net Total"
so.discount_amount = 100
so.items[0].qty = 5
so.items[0].rate = 100
so.append("items", so.items[0].as_dict())
so.items[1].qty = 5
so.items[1].rate = 200
so.save()
calculate_taxes_and_totals(so)
self.assertAlmostEqual(so.items[0].distributed_discount_amount, 33.33, places=2)
self.assertAlmostEqual(so.items[1].distributed_discount_amount, 66.67, places=2)
self.assertAlmostEqual(so.items[0].net_amount, 466.67, places=2)
self.assertAlmostEqual(so.items[1].net_amount, 933.33, places=2)
self.assertEqual(so.total, 1500)
self.assertEqual(so.net_total, 1400)
self.assertEqual(so.grand_total, 1400)
def test_distributed_discount_amount_with_taxes(self):
so = make_sales_order(do_not_save=1)
so.apply_discount_on = "Grand Total"
so.discount_amount = 100
so.items[0].qty = 5
so.items[0].rate = 100
so.append("items", so.items[0].as_dict())
so.items[1].qty = 5
so.items[1].rate = 200
so.append(
"taxes",
{
"charge_type": "On Net Total",
"account_head": "_Test Account VAT - _TC",
"cost_center": "_Test Cost Center - _TC",
"description": "VAT",
"included_in_print_rate": True,
"rate": 10,
},
)
so.save()
calculate_taxes_and_totals(so)
# like in test_distributed_discount_amount, but reduced by the included tax
self.assertAlmostEqual(so.items[0].distributed_discount_amount, 33.33 / 1.1, places=2)
self.assertAlmostEqual(so.items[1].distributed_discount_amount, 66.67 / 1.1, places=2)
self.assertAlmostEqual(so.items[0].net_amount, 466.67 / 1.1, places=2)
self.assertAlmostEqual(so.items[1].net_amount, 933.33 / 1.1, places=2)
self.assertEqual(so.total, 1500)
self.assertAlmostEqual(so.net_total, 1272.73, places=2)
self.assertEqual(so.grand_total, 1400)

View File

@@ -38,6 +38,7 @@
"column_break_18",
"discount_percentage",
"discount_amount",
"distributed_discount_amount",
"base_rate_with_margin",
"section_break1",
"rate",
@@ -238,7 +239,7 @@
},
{
"collapsible": 1,
"collapsible_depends_on": "eval: doc.margin_type || doc.discount_amount",
"collapsible_depends_on": "eval: doc.margin_type || doc.discount_amount || doc.distributed_discount_amount",
"fieldname": "discount_and_margin",
"fieldtype": "Section Break",
"label": "Discount and Margin"
@@ -668,6 +669,12 @@
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "distributed_discount_amount",
"fieldtype": "Currency",
"label": "Distributed Discount Amount",
"options": "currency"
},
{
"fieldname": "available_quantity_section",
"fieldtype": "Section Break",
@@ -691,7 +698,7 @@
"idx": 1,
"istable": 1,
"links": [],
"modified": "2024-12-12 13:49:17.765883",
"modified": "2024-12-12 13:49:18.765883",
"modified_by": "Administrator",
"module": "Selling",
"name": "Quotation Item",

View File

@@ -33,6 +33,7 @@ class QuotationItem(Document):
description: DF.TextEditor | None
discount_amount: DF.Currency
discount_percentage: DF.Percent
distributed_discount_amount: DF.Currency
gross_profit: DF.Currency
has_alternative_item: DF.Check
image: DF.Attach | None

View File

@@ -40,6 +40,7 @@
"column_break_19",
"discount_percentage",
"discount_amount",
"distributed_discount_amount",
"base_rate_with_margin",
"section_break_simple1",
"rate",
@@ -287,7 +288,7 @@
},
{
"collapsible": 1,
"collapsible_depends_on": "eval: doc.margin_type || doc.discount_amount",
"collapsible_depends_on": "eval: doc.margin_type || doc.discount_amount || doc.distributed_discount_amount",
"fieldname": "discount_and_margin",
"fieldtype": "Section Break",
"label": "Discount and Margin"
@@ -913,6 +914,12 @@
"print_hide": 1,
"report_hide": 1
},
{
"fieldname": "distributed_discount_amount",
"fieldtype": "Currency",
"label": "Distributed Discount Amount",
"options": "currency"
},
{
"allow_on_submit": 1,
"fieldname": "company_total_stock",
@@ -964,7 +971,7 @@
"idx": 1,
"istable": 1,
"links": [],
"modified": "2025-02-28 09:45:43.934947",
"modified": "2025-02-28 09:45:44.934947",
"modified_by": "Administrator",
"module": "Selling",
"name": "Sales Order Item",

View File

@@ -40,6 +40,7 @@ class SalesOrderItem(Document):
description: DF.TextEditor | None
discount_amount: DF.Currency
discount_percentage: DF.Percent
distributed_discount_amount: DF.Currency
ensure_delivery_based_on_produced_serial_no: DF.Check
grant_commission: DF.Check
gross_profit: DF.Currency

View File

@@ -40,6 +40,7 @@
"column_break_19",
"discount_percentage",
"discount_amount",
"distributed_discount_amount",
"base_rate_with_margin",
"section_break_1",
"rate",
@@ -277,7 +278,7 @@
},
{
"collapsible": 1,
"collapsible_depends_on": "eval: doc.margin_type || doc.discount_amount",
"collapsible_depends_on": "eval: doc.margin_type || doc.discount_amount || doc.distributed_discount_amount",
"fieldname": "discount_and_margin",
"fieldtype": "Section Break",
"label": "Discount and Margin"
@@ -912,6 +913,12 @@
"fieldname": "column_break_rxvc",
"fieldtype": "Column Break"
},
{
"fieldname": "distributed_discount_amount",
"fieldtype": "Currency",
"label": "Distributed Discount Amount",
"options": "currency"
},
{
"allow_on_submit": 1,
"fieldname": "company_total_stock",
@@ -934,7 +941,7 @@
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2025-02-05 14:28:32.322181",
"modified": "2025-02-05 14:28:33.322181",
"modified_by": "Administrator",
"module": "Stock",
"name": "Delivery Note Item",

View File

@@ -37,6 +37,7 @@ class DeliveryNoteItem(Document):
description: DF.TextEditor | None
discount_amount: DF.Currency
discount_percentage: DF.Float
distributed_discount_amount: DF.Currency
dn_detail: DF.Data | None
expense_account: DF.Link | None
grant_commission: DF.Check

View File

@@ -48,6 +48,7 @@
"column_break_37",
"discount_percentage",
"discount_amount",
"distributed_discount_amount",
"base_rate_with_margin",
"sec_break1",
"rate",
@@ -911,7 +912,7 @@
},
{
"collapsible": 1,
"collapsible_depends_on": "eval: doc.margin_type || doc.discount_amount",
"collapsible_depends_on": "eval: doc.margin_type || doc.discount_amount || doc.distributed_discount_amount",
"fieldname": "discount_and_margin_section",
"fieldtype": "Section Break",
"label": "Discount and Margin"
@@ -1128,6 +1129,12 @@
"options": "Company:company:default_currency",
"print_hide": 1
},
{
"fieldname": "distributed_discount_amount",
"fieldtype": "Currency",
"label": "Distributed Discount Amount",
"options": "currency"
},
{
"fieldname": "amount_difference_with_purchase_invoice",
"fieldtype": "Currency",
@@ -1140,7 +1147,7 @@
"idx": 1,
"istable": 1,
"links": [],
"modified": "2025-03-12 17:10:42.780622",
"modified": "2025-03-12 17:10:43.780622",
"modified_by": "Administrator",
"module": "Stock",
"name": "Purchase Receipt Item",

View File

@@ -37,6 +37,7 @@ class PurchaseReceiptItem(Document):
description: DF.TextEditor | None
discount_amount: DF.Currency
discount_percentage: DF.Percent
distributed_discount_amount: DF.Currency
expense_account: DF.Link | None
from_warehouse: DF.Link | None
has_item_scanned: DF.Check