Merge pull request #30642 from rahib-hassan/separate-discount-account

feat: separate discount accounting for buying and selling
This commit is contained in:
Deepesh Garg 2022-04-25 14:07:20 +05:30 committed by GitHub
commit f064e0b15e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 171 additions and 110 deletions

View File

@ -18,7 +18,6 @@
"automatically_fetch_payment_terms",
"column_break_17",
"enable_common_party_accounting",
"enable_discount_accounting",
"report_setting_section",
"use_custom_cash_flow",
"deferred_accounting_settings_section",
@ -272,13 +271,6 @@
"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"
},
{
"default": "0",
"description": "Learn about <a href=\"https://docs.erpnext.com/docs/v13/user/manual/en/accounts/articles/common_party_accounting#:~:text=Common%20Party%20Accounting%20in%20ERPNext,Invoice%20against%20a%20primary%20Supplier.\">Common Party</a>",
@ -354,7 +346,7 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2022-02-04 12:32:36.805652",
"modified": "2022-04-08 14:45:06.796418",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",

View File

@ -28,7 +28,6 @@ class AccountsSettings(Document):
self.validate_stale_days()
self.enable_payment_schedule_in_print()
self.toggle_discount_accounting_fields()
self.validate_pending_reposts()
def validate_stale_days(self):
@ -52,74 +51,6 @@ class AccountsSettings(Document):
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,
)
def validate_pending_reposts(self):
if self.acc_frozen_upto:
check_pending_reposting(self.acc_frozen_upto)

View File

@ -669,7 +669,7 @@ class PurchaseInvoice(BuyingController):
exchange_rate_map, net_rate_map = get_purchase_document_details(self)
enable_discount_accounting = cint(
frappe.db.get_single_value("Accounts Settings", "enable_discount_accounting")
frappe.db.get_single_value("Buying Settings", "enable_discount_accounting")
)
provisional_accounting_for_non_stock_items = cint(
frappe.db.get_value(
@ -1159,7 +1159,7 @@ class PurchaseInvoice(BuyingController):
# tax table gl entries
valuation_tax = {}
enable_discount_accounting = cint(
frappe.db.get_single_value("Accounts Settings", "enable_discount_accounting")
frappe.db.get_single_value("Buying Settings", "enable_discount_accounting")
)
for tax in self.get("taxes"):
@ -1252,7 +1252,7 @@ class PurchaseInvoice(BuyingController):
def enable_discount_accounting(self):
if not hasattr(self, "_enable_discount_accounting"):
self._enable_discount_accounting = cint(
frappe.db.get_single_value("Accounts Settings", "enable_discount_accounting")
frappe.db.get_single_value("Buying Settings", "enable_discount_accounting")
)
return self._enable_discount_accounting

View File

@ -5,6 +5,7 @@
import unittest
import frappe
from frappe.tests.utils import change_settings
from frappe.utils import add_days, cint, flt, getdate, nowdate, today
import erpnext
@ -336,8 +337,8 @@ class TestPurchaseInvoice(unittest.TestCase):
self.assertEqual(discrepancy_caused_by_exchange_rate_diff, amount)
@change_settings("Buying Settings", {"enable_discount_accounting": 1})
def test_purchase_invoice_with_discount_accounting_enabled(self):
enable_discount_accounting()
discount_account = create_account(
account_name="Discount Account",
@ -353,10 +354,10 @@ class TestPurchaseInvoice(unittest.TestCase):
]
check_gl_entries(self, pi.name, expected_gle, nowdate())
enable_discount_accounting(enable=0)
@change_settings("Buying Settings", {"enable_discount_accounting": 1})
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",
@ -1588,12 +1589,6 @@ def unlink_payment_on_cancel_of_invoice(enable=1):
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)

View File

@ -1051,7 +1051,7 @@ 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")
frappe.db.get_single_value("Selling Settings", "enable_discount_accounting")
)
for tax in self.get("taxes"):
@ -1097,7 +1097,7 @@ 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")
frappe.db.get_single_value("Selling Settings", "enable_discount_accounting")
)
for item in self.get("items"):
@ -1276,7 +1276,7 @@ class SalesInvoice(SellingController):
def enable_discount_accounting(self):
if not hasattr(self, "_enable_discount_accounting"):
self._enable_discount_accounting = cint(
frappe.db.get_single_value("Accounts Settings", "enable_discount_accounting")
frappe.db.get_single_value("Selling Settings", "enable_discount_accounting")
)
return self._enable_discount_accounting

View File

@ -7,6 +7,7 @@ import unittest
import frappe
from frappe.model.dynamic_links import get_dynamic_link_map
from frappe.model.naming import make_autoname
from frappe.tests.utils import change_settings
from frappe.utils import add_days, flt, getdate, nowdate
import erpnext
@ -2684,12 +2685,8 @@ class TestSalesInvoice(unittest.TestCase):
sales_invoice.items[0].item_tax_template, "_Test Account Excise Duty @ 10 - _TC"
)
@change_settings("Selling Settings", {"enable_discount_accounting": 1})
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",
@ -2705,14 +2702,10 @@ class TestSalesInvoice(unittest.TestCase):
]
check_gl_entries(self, si.name, expected_gle, add_days(nowdate(), -1))
enable_discount_accounting(enable=0)
@change_settings("Selling Settings", {"enable_discount_accounting": 1})
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",
@ -2743,7 +2736,6 @@ class TestSalesInvoice(unittest.TestCase):
]
check_gl_entries(self, si.name, expected_gle, add_days(nowdate(), -1))
enable_discount_accounting(enable=0)
def test_asset_depreciation_on_sale_with_pro_rata(self):
"""

View File

@ -20,6 +20,7 @@
"maintain_same_rate",
"allow_multiple_items",
"bill_for_rejected_quantity_in_purchase_invoice",
"enable_discount_accounting",
"subcontract",
"backflush_raw_materials_of_subcontract_based_on",
"column_break_11",
@ -133,6 +134,13 @@
{
"fieldname": "column_break_12",
"fieldtype": "Column Break"
},
{
"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 for Buying"
}
],
"icon": "fa fa-cog",
@ -140,7 +148,7 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2022-01-27 17:57:58.367048",
"modified": "2022-04-14 15:56:42.340223",
"modified_by": "Administrator",
"module": "Buying",
"name": "Buying Settings",

View File

@ -5,10 +5,15 @@
import frappe
from frappe.custom.doctype.property_setter.property_setter import make_property_setter
from frappe.model.document import Document
from frappe.utils import cint
class BuyingSettings(Document):
def on_update(self):
self.toggle_discount_accounting_fields()
def validate(self):
for key in ["supplier_group", "supp_master_name", "maintain_same_rate", "buying_price_list"]:
frappe.db.set_default(key, self.get(key, ""))
@ -21,3 +26,60 @@ class BuyingSettings(Document):
self.get("supp_master_name") == "Naming Series",
hide_name_field=False,
)
def toggle_discount_accounting_fields(self):
enable_discount_accounting = cint(self.enable_discount_accounting)
make_property_setter(
"Purchase Invoice Item",
"discount_account",
"hidden",
not (enable_discount_accounting),
"Check",
validate_fields_for_doctype=False,
)
if enable_discount_accounting:
make_property_setter(
"Purchase Invoice Item",
"discount_account",
"mandatory_depends_on",
"eval: doc.discount_amount",
"Code",
validate_fields_for_doctype=False,
)
else:
make_property_setter(
"Purchase Invoice Item",
"discount_account",
"mandatory_depends_on",
"",
"Code",
validate_fields_for_doctype=False,
)
make_property_setter(
"Purchase Invoice",
"additional_discount_account",
"hidden",
not (enable_discount_accounting),
"Check",
validate_fields_for_doctype=False,
)
if enable_discount_accounting:
make_property_setter(
"Purchase Invoice",
"additional_discount_account",
"mandatory_depends_on",
"eval: doc.discount_amount",
"Code",
validate_fields_for_doctype=False,
)
else:
make_property_setter(
"Purchase Invoice",
"additional_discount_account",
"mandatory_depends_on",
"",
"Code",
validate_fields_for_doctype=False,
)

View File

@ -1079,9 +1079,14 @@ class AccountsController(TransactionBase):
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 self.doctype == "Purchase Invoice":
enable_discount_accounting = cint(
frappe.db.get_single_value("Buying Settings", "enable_discount_accounting")
)
elif self.doctype == "Sales Invoice":
enable_discount_accounting = cint(
frappe.db.get_single_value("Selling Settings", "enable_discount_accounting")
)
if enable_discount_accounting:
if self.doctype == "Purchase Invoice":

View File

@ -365,4 +365,5 @@ erpnext.patches.v13_0.remove_unknown_links_to_prod_plan_items # 24-03-2022
erpnext.patches.v13_0.update_expense_claim_status_for_paid_advances
erpnext.patches.v13_0.create_gst_custom_fields_in_quotation
erpnext.patches.v13_0.copy_custom_field_filters_to_website_item
erpnext.patches.v14_0.discount_accounting_separation
erpnext.patches.v14_0.delete_employee_transfer_property_doctype

View File

@ -0,0 +1,9 @@
import frappe
def execute():
doc = frappe.get_doc("Accounts Settings")
discount_account = doc.enable_discount_accounting
if discount_account:
for doctype in ["Buying Settings", "Selling Settings"]:
frappe.db.set_value(doctype, doctype, "enable_discount_accounting", 1, update_modified=False)

View File

@ -27,7 +27,8 @@
"column_break_5",
"allow_multiple_items",
"allow_against_multiple_purchase_orders",
"hide_tax_id"
"hide_tax_id",
"enable_discount_accounting"
],
"fields": [
{
@ -164,6 +165,13 @@
"fieldname": "editable_bundle_item_rates",
"fieldtype": "Check",
"label": "Calculate Product Bundle Price based on Child Items' Rates"
},
{
"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 for Selling"
}
],
"icon": "fa fa-cog",
@ -171,7 +179,7 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2022-02-04 15:41:59.939261",
"modified": "2022-04-14 16:01:29.405642",
"modified_by": "Administrator",
"module": "Selling",
"name": "Selling Settings",

View File

@ -14,6 +14,7 @@ class SellingSettings(Document):
def on_update(self):
self.toggle_hide_tax_id()
self.toggle_editable_rate_for_bundle_items()
self.toggle_discount_accounting_fields()
def validate(self):
for key in [
@ -58,3 +59,60 @@ class SellingSettings(Document):
"Check",
validate_fields_for_doctype=False,
)
def toggle_discount_accounting_fields(self):
enable_discount_accounting = cint(self.enable_discount_accounting)
make_property_setter(
"Sales Invoice Item",
"discount_account",
"hidden",
not (enable_discount_accounting),
"Check",
validate_fields_for_doctype=False,
)
if enable_discount_accounting:
make_property_setter(
"Sales Invoice Item",
"discount_account",
"mandatory_depends_on",
"eval: doc.discount_amount",
"Code",
validate_fields_for_doctype=False,
)
else:
make_property_setter(
"Sales Invoice Item",
"discount_account",
"mandatory_depends_on",
"",
"Code",
validate_fields_for_doctype=False,
)
make_property_setter(
"Sales Invoice",
"additional_discount_account",
"hidden",
not (enable_discount_accounting),
"Check",
validate_fields_for_doctype=False,
)
if enable_discount_accounting:
make_property_setter(
"Sales Invoice",
"additional_discount_account",
"mandatory_depends_on",
"eval: doc.discount_amount",
"Code",
validate_fields_for_doctype=False,
)
else:
make_property_setter(
"Sales Invoice",
"additional_discount_account",
"mandatory_depends_on",
"",
"Code",
validate_fields_for_doctype=False,
)