From cfee6501b4f3598899c636f73cc8fa623923edb6 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 17 Oct 2023 13:28:56 +0530 Subject: [PATCH 01/23] fix: GL Entries for receiving non CWIP assets using Purchase Receipt --- .../purchase_receipt/purchase_receipt.py | 509 ++++++++---------- 1 file changed, 235 insertions(+), 274 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index c793529e843c..82473f5468ee 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -146,8 +146,8 @@ def validate_cwip_accounts(self): if item.is_fixed_asset and is_cwip_accounting_enabled(item.asset_category): # check cwip accounts before making auto assets # Improves UX by not giving messages of "Assets Created" before throwing error of not finding arbnb account - arbnb_account = self.get_company_default("asset_received_but_not_billed") - cwip_account = get_asset_account( + self.get_company_default("asset_received_but_not_billed") + get_asset_account( "capital_work_in_progress_account", asset_category=item.asset_category, company=self.company ) break @@ -315,7 +315,7 @@ def get_gl_entries(self, warehouse_account=None): self.make_item_gl_entries(gl_entries, warehouse_account=warehouse_account) self.make_tax_gl_entries(gl_entries) - self.get_asset_gl_entry(gl_entries) + # self.get_asset_gl_entry(gl_entries) return process_gl_map(gl_entries) @@ -324,11 +324,20 @@ def make_item_gl_entries(self, gl_entries, warehouse_account=None): get_purchase_document_details, ) - stock_rbnb = None + is_asset_pr = any(d.is_fixed_asset for d in self.get("items")) + stock_asset_rbnb = None + stock_asset_account_name = None + remarks = self.get("remarks") or _("Accounting Entry for {0}").format( + "Asset" if is_asset_pr else "Stock" + ) + if erpnext.is_perpetual_inventory_enabled(self.company): - stock_rbnb = self.get_company_default("stock_received_but_not_billed") + stock_asset_rbnb = ( + self.get_company_default("asset_received_but_not_billed") + if is_asset_pr + else self.get_company_default("stock_received_but_not_billed") + ) landed_cost_entries = get_item_account_wise_additional_cost(self.name) - expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation") warehouse_with_no_account = [] stock_items = self.get_stock_items() @@ -338,229 +347,263 @@ def make_item_gl_entries(self, gl_entries, warehouse_account=None): ) ) + supplier_warehouse_account = warehouse_account.get(self.supplier_warehouse, {}).get("account") + supplier_warehouse_account_currency = warehouse_account.get(self.supplier_warehouse, {}).get( + "account_currency" + ) exchange_rate_map, net_rate_map = get_purchase_document_details(self) - for d in self.get("items"): - if d.item_code in stock_items and flt(d.valuation_rate) and flt(d.qty): - if warehouse_account.get(d.warehouse): - stock_value_diff = frappe.db.get_value( + def make_item_asset_inward_entries(item): + if d.is_fixed_asset: + stock_asset_account_name = ( + get_asset_category_account( + asset_category=item.asset_category, + fieldname="capital_work_in_progress_account", + company=self.company, + ) + if is_cwip_accounting_enabled(d.asset_category) + else get_asset_category_account( + asset_category=item.asset_category, fieldname="fixed_asset_account", company=self.company + ) + ) + + stock_value_diff = flt(item.net_amount) + flt(item.item_tax_amount / self.conversion_rate) + elif flt(item.valuation_rate) and flt(item.qty): + # If PR is sub-contracted and fg item rate is zero + # in that case if account for source and target warehouse are same, + # then GL entries should not be posted + if ( + flt(stock_value_diff) == flt(d.rm_supp_cost) + and warehouse_account.get(self.supplier_warehouse) + and stock_asset_account_name == supplier_warehouse_account + ): + return + + stock_asset_account_name = warehouse_account[item.warehouse]["account"] + + account_currency = get_account_currency(stock_asset_account_name) + self.add_gl_entry( + gl_entries=gl_entries, + account=stock_asset_account_name, + cost_center=d.cost_center, + debit=stock_value_diff, + credit=0.0, + remarks=remarks, + against_account=stock_asset_rbnb, + account_currency=account_currency, + item=item, + ) + + def make_stock_received_but_not_billed_entry(item, outgoing_amount): + # GL Entry for from warehouse or Stock Received but not billed + # Intentionally passed negative debit amount to avoid incorrect GL Entry validation + credit_amount = ( + flt(item.base_net_amount, item.precision("base_net_amount")) + if credit_currency == self.company_currency + else flt(item.net_amount, item.precision("net_amount")) + ) + + if self.is_internal_transfer() and item.valuation_rate: + outgoing_amount = abs( + frappe.db.get_value( "Stock Ledger Entry", { "voucher_type": "Purchase Receipt", "voucher_no": self.name, - "voucher_detail_no": d.name, - "warehouse": d.warehouse, + "voucher_detail_no": item.name, + "warehouse": item.from_warehouse, "is_cancelled": 0, }, "stock_value_difference", ) + ) + credit_amount = outgoing_amount - warehouse_account_name = warehouse_account[d.warehouse]["account"] - warehouse_account_currency = warehouse_account[d.warehouse]["account_currency"] - supplier_warehouse_account = warehouse_account.get(self.supplier_warehouse, {}).get("account") - supplier_warehouse_account_currency = warehouse_account.get(self.supplier_warehouse, {}).get( - "account_currency" - ) - remarks = self.get("remarks") or _("Accounting Entry for Stock") + if credit_amount: + account = ( + warehouse_account[item.from_warehouse]["account"] if item.from_warehouse else stock_asset_rbnb + ) + + self.add_gl_entry( + gl_entries=gl_entries, + account=account, + cost_center=item.cost_center, + debit=-1 * flt(outgoing_amount, item.precision("base_net_amount")), + credit=0.0, + remarks=remarks, + against_account=stock_asset_account_name, + debit_in_account_currency=-1 * credit_amount, + account_currency=credit_currency, + item=item, + ) - # If PR is sub-contracted and fg item rate is zero - # in that case if account for source and target warehouse are same, - # then GL entries should not be posted + # check if the exchange rate has changed + if d.get("purchase_invoice"): if ( - flt(stock_value_diff) == flt(d.rm_supp_cost) - and warehouse_account.get(self.supplier_warehouse) - and warehouse_account_name == supplier_warehouse_account + exchange_rate_map[item.purchase_invoice] + and self.conversion_rate != exchange_rate_map[item.purchase_invoice] + and item.net_rate == net_rate_map[item.purchase_invoice_item] ): - continue - - self.add_gl_entry( - gl_entries=gl_entries, - account=warehouse_account_name, - cost_center=d.cost_center, - debit=stock_value_diff, - credit=0.0, - remarks=remarks, - against_account=stock_rbnb, - account_currency=warehouse_account_currency, - item=d, - ) - - # GL Entry for from warehouse or Stock Received but not billed - # Intentionally passed negative debit amount to avoid incorrect GL Entry validation - credit_currency = ( - get_account_currency(warehouse_account[d.from_warehouse]["account"]) - if d.from_warehouse - else get_account_currency(stock_rbnb) - ) - - credit_amount = ( - flt(d.base_net_amount, d.precision("base_net_amount")) - if credit_currency == self.company_currency - else flt(d.net_amount, d.precision("net_amount")) - ) - outgoing_amount = d.base_net_amount - if self.is_internal_transfer() and d.valuation_rate: - outgoing_amount = abs( - frappe.db.get_value( - "Stock Ledger Entry", - { - "voucher_type": "Purchase Receipt", - "voucher_no": self.name, - "voucher_detail_no": d.name, - "warehouse": d.from_warehouse, - "is_cancelled": 0, - }, - "stock_value_difference", - ) + discrepancy_caused_by_exchange_rate_difference = (item.qty * item.net_rate) * ( + exchange_rate_map[item.purchase_invoice] - self.conversion_rate ) - credit_amount = outgoing_amount - - if credit_amount: - account = warehouse_account[d.from_warehouse]["account"] if d.from_warehouse else stock_rbnb self.add_gl_entry( gl_entries=gl_entries, account=account, - cost_center=d.cost_center, - debit=-1 * flt(outgoing_amount, d.precision("base_net_amount")), - credit=0.0, + cost_center=item.cost_center, + debit=0.0, + credit=discrepancy_caused_by_exchange_rate_difference, remarks=remarks, - against_account=warehouse_account_name, - debit_in_account_currency=-1 * credit_amount, + against_account=self.supplier, + debit_in_account_currency=-1 * discrepancy_caused_by_exchange_rate_difference, account_currency=credit_currency, - item=d, + item=item, ) - # check if the exchange rate has changed - if d.get("purchase_invoice"): - if ( - exchange_rate_map[d.purchase_invoice] - and self.conversion_rate != exchange_rate_map[d.purchase_invoice] - and d.net_rate == net_rate_map[d.purchase_invoice_item] - ): - - discrepancy_caused_by_exchange_rate_difference = (d.qty * d.net_rate) * ( - exchange_rate_map[d.purchase_invoice] - self.conversion_rate - ) - - self.add_gl_entry( - gl_entries=gl_entries, - account=account, - cost_center=d.cost_center, - debit=0.0, - credit=discrepancy_caused_by_exchange_rate_difference, - remarks=remarks, - against_account=self.supplier, - debit_in_account_currency=-1 * discrepancy_caused_by_exchange_rate_difference, - account_currency=credit_currency, - item=d, - ) - - self.add_gl_entry( - gl_entries=gl_entries, - account=self.get_company_default("exchange_gain_loss_account"), - cost_center=d.cost_center, - debit=discrepancy_caused_by_exchange_rate_difference, - credit=0.0, - remarks=remarks, - against_account=self.supplier, - debit_in_account_currency=-1 * discrepancy_caused_by_exchange_rate_difference, - account_currency=credit_currency, - item=d, - ) - - # Amount added through landed-cos-voucher - if d.landed_cost_voucher_amount and landed_cost_entries: - for account, amount in landed_cost_entries[(d.item_code, d.name)].items(): - account_currency = get_account_currency(account) - credit_amount = ( - flt(amount["base_amount"]) - if (amount["base_amount"] or account_currency != self.company_currency) - else flt(amount["amount"]) - ) - - self.add_gl_entry( - gl_entries=gl_entries, - account=account, - cost_center=d.cost_center, - debit=0.0, - credit=credit_amount, - remarks=remarks, - against_account=warehouse_account_name, - credit_in_account_currency=flt(amount["amount"]), - account_currency=account_currency, - project=d.project, - item=d, - ) - - if d.rate_difference_with_purchase_invoice and stock_rbnb: - account_currency = get_account_currency(stock_rbnb) self.add_gl_entry( gl_entries=gl_entries, - account=stock_rbnb, + account=self.get_company_default("exchange_gain_loss_account"), cost_center=d.cost_center, - debit=0.0, - credit=flt(d.rate_difference_with_purchase_invoice), - remarks=_("Adjustment based on Purchase Invoice rate"), - against_account=warehouse_account_name, - account_currency=account_currency, - project=d.project, - item=d, + debit=discrepancy_caused_by_exchange_rate_difference, + credit=0.0, + remarks=remarks, + against_account=self.supplier, + debit_in_account_currency=-1 * discrepancy_caused_by_exchange_rate_difference, + account_currency=credit_currency, + item=item, + ) + + def make_landed_cost_gl_entries(item): + # Amount added through landed-cos-voucher + if item.landed_cost_voucher_amount and landed_cost_entries: + if (item.item_code, item.name) in landed_cost_entries: + for account, amount in landed_cost_entries[(item.item_code, item.name)].items(): + account_currency = get_account_currency(account) + credit_amount = ( + flt(amount["base_amount"]) + if (amount["base_amount"] or account_currency != self.company_currency) + else flt(amount["amount"]) ) - # sub-contracting warehouse - if flt(d.rm_supp_cost) and warehouse_account.get(self.supplier_warehouse): self.add_gl_entry( gl_entries=gl_entries, - account=supplier_warehouse_account, - cost_center=d.cost_center, + account=account, + cost_center=item.cost_center, debit=0.0, - credit=flt(d.rm_supp_cost), + credit=credit_amount, remarks=remarks, - against_account=warehouse_account_name, - account_currency=supplier_warehouse_account_currency, - item=d, + against_account=stock_asset_account_name, + credit_in_account_currency=flt(amount["amount"]), + account_currency=account_currency, + project=item.project, + item=item, ) - # divisional loss adjustment - valuation_amount_as_per_doc = ( - flt(outgoing_amount, d.precision("base_net_amount")) - + flt(d.landed_cost_voucher_amount) - + flt(d.rm_supp_cost) - + flt(d.item_tax_amount) - + flt(d.rate_difference_with_purchase_invoice) - ) + def make_rate_difference_entry(item): + if item.rate_difference_with_purchase_invoice and stock_asset_rbnb: + account_currency = get_account_currency(stock_asset_rbnb) + self.add_gl_entry( + gl_entries=gl_entries, + account=stock_asset_rbnb, + cost_center=item.cost_center, + debit=0.0, + credit=flt(item.rate_difference_with_purchase_invoice), + remarks=_("Adjustment based on Purchase Invoice rate"), + against_account=stock_asset_account_name, + account_currency=account_currency, + project=item.project, + item=item, + ) - divisional_loss = flt( - valuation_amount_as_per_doc - flt(stock_value_diff), d.precision("base_net_amount") + def make_sub_contracting_gl_entries(item): + # sub-contracting warehouse + if flt(item.rm_supp_cost) and warehouse_account.get(self.supplier_warehouse): + self.add_gl_entry( + gl_entries=gl_entries, + account=supplier_warehouse_account, + cost_center=item.cost_center, + debit=0.0, + credit=flt(item.rm_supp_cost), + remarks=remarks, + against_account=stock_asset_account_name, + account_currency=supplier_warehouse_account_currency, + item=item, + ) + + def make_divisional_loss_gl_entry(item): + if item.is_fixed_asset: + return + + # divisional loss adjustment + expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation") + valuation_amount_as_per_doc = ( + flt(outgoing_amount, d.precision("base_net_amount")) + + flt(item.landed_cost_voucher_amount) + + flt(item.rm_supp_cost) + + flt(item.item_tax_amount) + + flt(item.rate_difference_with_purchase_invoice) + ) + + divisional_loss = flt( + valuation_amount_as_per_doc - flt(stock_value_diff), item.precision("base_net_amount") + ) + + if divisional_loss: + if self.is_return or flt(item.item_tax_amount): + loss_account = expenses_included_in_valuation + else: + loss_account = ( + self.get_company_default("default_expense_account", ignore_validation=True) + or stock_asset_rbnb ) - if divisional_loss: - if self.is_return or flt(d.item_tax_amount): - loss_account = expenses_included_in_valuation - else: - loss_account = ( - self.get_company_default("default_expense_account", ignore_validation=True) or stock_rbnb - ) + cost_center = item.cost_center or frappe.get_cached_value( + "Company", self.company, "cost_center" + ) - cost_center = d.cost_center or frappe.get_cached_value( - "Company", self.company, "cost_center" - ) + self.add_gl_entry( + gl_entries=gl_entries, + account=loss_account, + cost_center=cost_center, + debit=divisional_loss, + credit=0.0, + remarks=remarks, + against_account=stock_asset_account_name, + account_currency=credit_currency, + project=item.project, + item=item, + ) - self.add_gl_entry( - gl_entries=gl_entries, - account=loss_account, - cost_center=cost_center, - debit=divisional_loss, - credit=0.0, - remarks=remarks, - against_account=warehouse_account_name, - account_currency=credit_currency, - project=d.project, - item=d, - ) + for d in self.get("items"): + if d.item_code in stock_items or d.is_fixed_asset: + credit_currency = ( + get_account_currency(warehouse_account[d.from_warehouse]["account"]) + if d.from_warehouse + else get_account_currency(stock_asset_rbnb) + ) + + if warehouse_account.get(d.warehouse): + stock_value_diff = frappe.db.get_value( + "Stock Ledger Entry", + { + "voucher_type": "Purchase Receipt", + "voucher_no": self.name, + "voucher_detail_no": d.name, + "warehouse": d.warehouse, + "is_cancelled": 0, + }, + "stock_value_difference", + ) + outgoing_amount = d.base_net_amount + d.item_tax_amount + make_item_asset_inward_entries(d) + make_stock_received_but_not_billed_entry(d, outgoing_amount) + make_landed_cost_gl_entries(d) + make_rate_difference_entry(d) + make_sub_contracting_gl_entries(d) + make_divisional_loss_gl_entry(d) elif ( d.warehouse not in warehouse_with_no_account or d.rejected_warehouse not in warehouse_with_no_account @@ -577,6 +620,9 @@ def make_item_gl_entries(self, gl_entries, warehouse_account=None): d, gl_entries, self.posting_date, d.get("provisional_expense_account") ) + if d.is_fixed_asset: + self.update_assets(d, d.valuation_rate) + if warehouse_with_no_account: frappe.msgprint( _("No accounting entries for the following warehouses") @@ -710,93 +756,8 @@ def get_asset_gl_entry(self, gl_entries): self.add_lcv_gl_entries(item, gl_entries) # update assets gross amount by its valuation rate # valuation rate is total of net rate, raw mat supp cost, tax amount, lcv amount per item - self.update_assets(item, item.valuation_rate) - return gl_entries - - def add_asset_gl_entries(self, item, gl_entries): - arbnb_account = self.get_company_default("asset_received_but_not_billed") - # This returns category's cwip account if not then fallback to company's default cwip account - cwip_account = get_asset_account( - "capital_work_in_progress_account", asset_category=item.asset_category, company=self.company - ) - - asset_amount = flt(item.net_amount) + flt(item.item_tax_amount / self.conversion_rate) - base_asset_amount = flt(item.base_net_amount + item.item_tax_amount) - remarks = self.get("remarks") or _("Accounting Entry for Asset") - - cwip_account_currency = get_account_currency(cwip_account) - # debit cwip account - debit_in_account_currency = ( - base_asset_amount if cwip_account_currency == self.company_currency else asset_amount - ) - - self.add_gl_entry( - gl_entries=gl_entries, - account=cwip_account, - cost_center=item.cost_center, - debit=base_asset_amount, - credit=0.0, - remarks=remarks, - against_account=arbnb_account, - debit_in_account_currency=debit_in_account_currency, - item=item, - ) - asset_rbnb_currency = get_account_currency(arbnb_account) - # credit arbnb account - credit_in_account_currency = ( - base_asset_amount if asset_rbnb_currency == self.company_currency else asset_amount - ) - - self.add_gl_entry( - gl_entries=gl_entries, - account=arbnb_account, - cost_center=item.cost_center, - debit=0.0, - credit=base_asset_amount, - remarks=remarks, - against_account=cwip_account, - credit_in_account_currency=credit_in_account_currency, - item=item, - ) - - def add_lcv_gl_entries(self, item, gl_entries): - expenses_included_in_asset_valuation = self.get_company_default( - "expenses_included_in_asset_valuation" - ) - if not is_cwip_accounting_enabled(item.asset_category): - asset_account = get_asset_category_account( - asset_category=item.asset_category, fieldname="fixed_asset_account", company=self.company - ) - else: - # This returns company's default cwip account - asset_account = get_asset_account("capital_work_in_progress_account", company=self.company) - - remarks = self.get("remarks") or _("Accounting Entry for Stock") - - self.add_gl_entry( - gl_entries=gl_entries, - account=expenses_included_in_asset_valuation, - cost_center=item.cost_center, - debit=0.0, - credit=flt(item.landed_cost_voucher_amount), - remarks=remarks, - against_account=asset_account, - project=item.project, - item=item, - ) - - self.add_gl_entry( - gl_entries=gl_entries, - account=asset_account, - cost_center=item.cost_center, - debit=flt(item.landed_cost_voucher_amount), - credit=0.0, - remarks=remarks, - against_account=expenses_included_in_asset_valuation, - project=item.project, - item=item, - ) + return gl_entries def update_assets(self, item, valuation_rate): assets = frappe.db.get_all( From 45426267b25fa1563e67d8e28ce746c1c0fcb3ed Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 17 Oct 2023 20:36:09 +0530 Subject: [PATCH 02/23] fix: rearrange functions --- erpnext/controllers/stock_controller.py | 5 - .../purchase_receipt/purchase_receipt.py | 114 +++++++----------- 2 files changed, 46 insertions(+), 73 deletions(-) diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 4f0c8a9a54f0..c702e3a767d4 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -73,11 +73,6 @@ def make_gl_entries(self, gl_entries=None, from_repost=False): gl_entries = self.get_gl_entries(warehouse_account) make_gl_entries(gl_entries, from_repost=from_repost) - elif self.doctype in ["Purchase Receipt", "Purchase Invoice"] and self.docstatus == 1: - gl_entries = [] - gl_entries = self.get_asset_gl_entry(gl_entries) - make_gl_entries(gl_entries, from_repost=from_repost) - def validate_serialized_batch(self): from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 82473f5468ee..bd61e8d349ef 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -315,7 +315,6 @@ def get_gl_entries(self, warehouse_account=None): self.make_item_gl_entries(gl_entries, warehouse_account=warehouse_account) self.make_tax_gl_entries(gl_entries) - # self.get_asset_gl_entry(gl_entries) return process_gl_map(gl_entries) @@ -353,34 +352,7 @@ def make_item_gl_entries(self, gl_entries, warehouse_account=None): ) exchange_rate_map, net_rate_map = get_purchase_document_details(self) - def make_item_asset_inward_entries(item): - if d.is_fixed_asset: - stock_asset_account_name = ( - get_asset_category_account( - asset_category=item.asset_category, - fieldname="capital_work_in_progress_account", - company=self.company, - ) - if is_cwip_accounting_enabled(d.asset_category) - else get_asset_category_account( - asset_category=item.asset_category, fieldname="fixed_asset_account", company=self.company - ) - ) - - stock_value_diff = flt(item.net_amount) + flt(item.item_tax_amount / self.conversion_rate) - elif flt(item.valuation_rate) and flt(item.qty): - # If PR is sub-contracted and fg item rate is zero - # in that case if account for source and target warehouse are same, - # then GL entries should not be posted - if ( - flt(stock_value_diff) == flt(d.rm_supp_cost) - and warehouse_account.get(self.supplier_warehouse) - and stock_asset_account_name == supplier_warehouse_account - ): - return - - stock_asset_account_name = warehouse_account[item.warehouse]["account"] - + def make_item_asset_inward_entries(item, stock_value_diff, stock_asset_account_name): account_currency = get_account_currency(stock_asset_account_name) self.add_gl_entry( gl_entries=gl_entries, @@ -404,20 +376,7 @@ def make_stock_received_but_not_billed_entry(item, outgoing_amount): ) if self.is_internal_transfer() and item.valuation_rate: - outgoing_amount = abs( - frappe.db.get_value( - "Stock Ledger Entry", - { - "voucher_type": "Purchase Receipt", - "voucher_no": self.name, - "voucher_detail_no": item.name, - "warehouse": item.from_warehouse, - "is_cancelled": 0, - }, - "stock_value_difference", - ) - ) - credit_amount = outgoing_amount + credit_amount = abs(get_stock_value_difference(self.name, item.name, item.from_warehouse) or 0) if credit_amount: account = ( @@ -585,20 +544,37 @@ def make_divisional_loss_gl_entry(item): ) if warehouse_account.get(d.warehouse): - stock_value_diff = frappe.db.get_value( - "Stock Ledger Entry", - { - "voucher_type": "Purchase Receipt", - "voucher_no": self.name, - "voucher_detail_no": d.name, - "warehouse": d.warehouse, - "is_cancelled": 0, - }, - "stock_value_difference", - ) - + stock_value_diff = get_stock_value_difference(self.name, d.name, d.warehouse) outgoing_amount = d.base_net_amount + d.item_tax_amount - make_item_asset_inward_entries(d) + + if d.is_fixed_asset: + stock_asset_account_name = ( + get_asset_category_account( + asset_category=d.asset_category, + fieldname="capital_work_in_progress_account", + company=self.company, + ) + if is_cwip_accounting_enabled(d.asset_category) + else get_asset_category_account( + asset_category=d.asset_category, fieldname="fixed_asset_account", company=self.company + ) + ) + + stock_value_diff = flt(d.net_amount) + flt(d.item_tax_amount / self.conversion_rate) + elif (flt(d.valuation_rate) or self.is_return) and flt(d.qty): + stock_asset_account_name = warehouse_account[d.warehouse]["account"] + + # If PR is sub-contracted and fg item rate is zero + # in that case if account for source and target warehouse are same, + # then GL entries should not be posted + if ( + flt(stock_value_diff) == flt(d.rm_supp_cost) + and warehouse_account.get(self.supplier_warehouse) + and stock_asset_account_name == supplier_warehouse_account + ): + continue + + make_item_asset_inward_entries(d, stock_value_diff, stock_asset_account_name) make_stock_received_but_not_billed_entry(d, outgoing_amount) make_landed_cost_gl_entries(d) make_rate_difference_entry(d) @@ -747,18 +723,6 @@ def make_tax_gl_entries(self, gl_entries): i += 1 - def get_asset_gl_entry(self, gl_entries): - for item in self.get("items"): - if item.is_fixed_asset: - if is_cwip_accounting_enabled(item.asset_category): - self.add_asset_gl_entries(item, gl_entries) - if flt(item.landed_cost_voucher_amount): - self.add_lcv_gl_entries(item, gl_entries) - # update assets gross amount by its valuation rate - # valuation rate is total of net rate, raw mat supp cost, tax amount, lcv amount per item - - return gl_entries - def update_assets(self, item, valuation_rate): assets = frappe.db.get_all( "Asset", filters={"purchase_receipt": self.name, "item_code": item.item_code} @@ -792,6 +756,20 @@ def update_billing_status(self, update_modified=True): self.load_from_db() +def get_stock_value_difference(voucher_no, voucher_detail_no, warehouse): + frappe.db.get_value( + "Stock Ledger Entry", + { + "voucher_type": "Purchase Receipt", + "voucher_no": voucher_no, + "voucher_detail_no": voucher_detail_no, + "warehouse": warehouse, + "is_cancelled": 0, + }, + "stock_value_difference", + ) + + def update_billed_amount_based_on_po(po_details, update_modified=True): po_billed_amt_details = get_billed_amount_against_po(po_details) From 857932561401c2b58e4c1975ec1b552a6f78ceff Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 17 Oct 2023 21:28:59 +0530 Subject: [PATCH 03/23] chore: rearrange functions --- .../purchase_receipt/purchase_receipt.py | 61 +++++++++---------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index bd61e8d349ef..d30f9edec792 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -346,10 +346,6 @@ def make_item_gl_entries(self, gl_entries, warehouse_account=None): ) ) - supplier_warehouse_account = warehouse_account.get(self.supplier_warehouse, {}).get("account") - supplier_warehouse_account_currency = warehouse_account.get(self.supplier_warehouse, {}).get( - "account_currency" - ) exchange_rate_map, net_rate_map = get_purchase_document_details(self) def make_item_asset_inward_entries(item, stock_value_diff, stock_asset_account_name): @@ -367,22 +363,26 @@ def make_item_asset_inward_entries(item, stock_value_diff, stock_asset_account_n ) def make_stock_received_but_not_billed_entry(item, outgoing_amount): + account = ( + warehouse_account[item.from_warehouse]["account"] if item.from_warehouse else stock_asset_rbnb + ) + account_currency = get_account_currency(account) + # GL Entry for from warehouse or Stock Received but not billed # Intentionally passed negative debit amount to avoid incorrect GL Entry validation credit_amount = ( flt(item.base_net_amount, item.precision("base_net_amount")) - if credit_currency == self.company_currency + if account_currency == self.company_currency else flt(item.net_amount, item.precision("net_amount")) ) if self.is_internal_transfer() and item.valuation_rate: - credit_amount = abs(get_stock_value_difference(self.name, item.name, item.from_warehouse) or 0) - - if credit_amount: - account = ( - warehouse_account[item.from_warehouse]["account"] if item.from_warehouse else stock_asset_rbnb + outgoing_amount = abs( + get_stock_value_difference(self.name, item.name, item.from_warehouse) or 0 ) + credit_amount = outgoing_amount + if credit_amount: self.add_gl_entry( gl_entries=gl_entries, account=account, @@ -392,7 +392,7 @@ def make_stock_received_but_not_billed_entry(item, outgoing_amount): remarks=remarks, against_account=stock_asset_account_name, debit_in_account_currency=-1 * credit_amount, - account_currency=credit_currency, + account_currency=account_currency, item=item, ) @@ -417,7 +417,7 @@ def make_stock_received_but_not_billed_entry(item, outgoing_amount): remarks=remarks, against_account=self.supplier, debit_in_account_currency=-1 * discrepancy_caused_by_exchange_rate_difference, - account_currency=credit_currency, + account_currency=account_currency, item=item, ) @@ -430,7 +430,7 @@ def make_stock_received_but_not_billed_entry(item, outgoing_amount): remarks=remarks, against_account=self.supplier, debit_in_account_currency=-1 * discrepancy_caused_by_exchange_rate_difference, - account_currency=credit_currency, + account_currency=account_currency, item=item, ) @@ -521,7 +521,7 @@ def make_divisional_loss_gl_entry(item): cost_center = item.cost_center or frappe.get_cached_value( "Company", self.company, "cost_center" ) - + account_currency = get_account_currency(loss_account) self.add_gl_entry( gl_entries=gl_entries, account=loss_account, @@ -530,23 +530,32 @@ def make_divisional_loss_gl_entry(item): credit=0.0, remarks=remarks, against_account=stock_asset_account_name, - account_currency=credit_currency, + account_currency=account_currency, project=item.project, item=item, ) for d in self.get("items"): if d.item_code in stock_items or d.is_fixed_asset: - credit_currency = ( - get_account_currency(warehouse_account[d.from_warehouse]["account"]) - if d.from_warehouse - else get_account_currency(stock_asset_rbnb) - ) - if warehouse_account.get(d.warehouse): stock_value_diff = get_stock_value_difference(self.name, d.name, d.warehouse) outgoing_amount = d.base_net_amount + d.item_tax_amount + supplier_warehouse_account = warehouse_account.get(self.supplier_warehouse, {}).get("account") + supplier_warehouse_account_currency = warehouse_account.get(self.supplier_warehouse, {}).get( + "account_currency" + ) + + # If PR is sub-contracted and fg item rate is zero + # in that case if account for source and target warehouse are same, + # then GL entries should not be posted + if ( + flt(stock_value_diff) == flt(d.rm_supp_cost) + and warehouse_account.get(self.supplier_warehouse) + and stock_asset_account_name == supplier_warehouse_account + ): + continue + if d.is_fixed_asset: stock_asset_account_name = ( get_asset_category_account( @@ -564,16 +573,6 @@ def make_divisional_loss_gl_entry(item): elif (flt(d.valuation_rate) or self.is_return) and flt(d.qty): stock_asset_account_name = warehouse_account[d.warehouse]["account"] - # If PR is sub-contracted and fg item rate is zero - # in that case if account for source and target warehouse are same, - # then GL entries should not be posted - if ( - flt(stock_value_diff) == flt(d.rm_supp_cost) - and warehouse_account.get(self.supplier_warehouse) - and stock_asset_account_name == supplier_warehouse_account - ): - continue - make_item_asset_inward_entries(d, stock_value_diff, stock_asset_account_name) make_stock_received_but_not_billed_entry(d, outgoing_amount) make_landed_cost_gl_entries(d) From 249b4325bbdcb4e9e074eb2f2a68d9319985a2b9 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Wed, 18 Oct 2023 08:59:28 +0530 Subject: [PATCH 04/23] chore: rearrange functions --- .../purchase_receipt/purchase_receipt.py | 91 +++++++++---------- 1 file changed, 44 insertions(+), 47 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index d30f9edec792..22d4e3c2fc43 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -325,7 +325,6 @@ def make_item_gl_entries(self, gl_entries, warehouse_account=None): is_asset_pr = any(d.is_fixed_asset for d in self.get("items")) stock_asset_rbnb = None - stock_asset_account_name = None remarks = self.get("remarks") or _("Accounting Entry for {0}").format( "Asset" if is_asset_pr else "Stock" ) @@ -362,12 +361,13 @@ def make_item_asset_inward_entries(item, stock_value_diff, stock_asset_account_n item=item, ) - def make_stock_received_but_not_billed_entry(item, outgoing_amount): + def make_stock_received_but_not_billed_entry(item): account = ( warehouse_account[item.from_warehouse]["account"] if item.from_warehouse else stock_asset_rbnb ) account_currency = get_account_currency(account) + outgoing_amount = item.base_net_amount # GL Entry for from warehouse or Stock Received but not billed # Intentionally passed negative debit amount to avoid incorrect GL Entry validation credit_amount = ( @@ -377,9 +377,7 @@ def make_stock_received_but_not_billed_entry(item, outgoing_amount): ) if self.is_internal_transfer() and item.valuation_rate: - outgoing_amount = abs( - get_stock_value_difference(self.name, item.name, item.from_warehouse) or 0 - ) + outgoing_amount = abs(get_stock_value_difference(self.name, item.name, item.from_warehouse)) credit_amount = outgoing_amount if credit_amount: @@ -498,7 +496,7 @@ def make_divisional_loss_gl_entry(item): # divisional loss adjustment expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation") valuation_amount_as_per_doc = ( - flt(outgoing_amount, d.precision("base_net_amount")) + flt(item.base_net_amount, d.precision("base_net_amount")) + flt(item.landed_cost_voucher_amount) + flt(item.rm_supp_cost) + flt(item.item_tax_amount) @@ -536,11 +534,37 @@ def make_divisional_loss_gl_entry(item): ) for d in self.get("items"): - if d.item_code in stock_items or d.is_fixed_asset: - if warehouse_account.get(d.warehouse): - stock_value_diff = get_stock_value_difference(self.name, d.name, d.warehouse) - outgoing_amount = d.base_net_amount + d.item_tax_amount + if ( + d.item_code not in stock_items + and flt(d.qty) + and provisional_accounting_for_non_stock_items + and d.get("provisional_expense_account") + ): + self.add_provisional_gl_entry( + d, gl_entries, self.posting_date, d.get("provisional_expense_account") + ) + elif flt(d.qty) and (flt(d.valuation_rate) or self.is_return): + if d.is_fixed_asset: + stock_asset_account_name = ( + get_asset_category_account( + asset_category=d.asset_category, + fieldname="capital_work_in_progress_account", + company=self.company, + ) + if is_cwip_accounting_enabled(d.asset_category) + else get_asset_category_account( + asset_category=d.asset_category, fieldname="fixed_asset_account", company=self.company + ) + ) + stock_value_diff = flt(d.net_amount) + flt(d.item_tax_amount / self.conversion_rate) + elif ( + (flt(d.valuation_rate) or self.is_return) + and flt(d.qty) + and warehouse_account.get(d.warehouse) + ): + stock_value_diff = get_stock_value_difference(self.name, d.name, d.warehouse) + stock_asset_account_name = warehouse_account[d.warehouse]["account"] supplier_warehouse_account = warehouse_account.get(self.supplier_warehouse, {}).get("account") supplier_warehouse_account_currency = warehouse_account.get(self.supplier_warehouse, {}).get( "account_currency" @@ -556,44 +580,17 @@ def make_divisional_loss_gl_entry(item): ): continue - if d.is_fixed_asset: - stock_asset_account_name = ( - get_asset_category_account( - asset_category=d.asset_category, - fieldname="capital_work_in_progress_account", - company=self.company, - ) - if is_cwip_accounting_enabled(d.asset_category) - else get_asset_category_account( - asset_category=d.asset_category, fieldname="fixed_asset_account", company=self.company - ) - ) - - stock_value_diff = flt(d.net_amount) + flt(d.item_tax_amount / self.conversion_rate) - elif (flt(d.valuation_rate) or self.is_return) and flt(d.qty): - stock_asset_account_name = warehouse_account[d.warehouse]["account"] - - make_item_asset_inward_entries(d, stock_value_diff, stock_asset_account_name) - make_stock_received_but_not_billed_entry(d, outgoing_amount) - make_landed_cost_gl_entries(d) - make_rate_difference_entry(d) - make_sub_contracting_gl_entries(d) - make_divisional_loss_gl_entry(d) - elif ( - d.warehouse not in warehouse_with_no_account - or d.rejected_warehouse not in warehouse_with_no_account - ): - warehouse_with_no_account.append(d.warehouse) + make_item_asset_inward_entries(d, stock_value_diff, stock_asset_account_name) + make_stock_received_but_not_billed_entry(d) + make_landed_cost_gl_entries(d) + make_rate_difference_entry(d) + make_sub_contracting_gl_entries(d) + make_divisional_loss_gl_entry(d) elif ( - d.item_code not in stock_items - and not d.is_fixed_asset - and flt(d.qty) - and provisional_accounting_for_non_stock_items - and d.get("provisional_expense_account") + d.warehouse not in warehouse_with_no_account + or d.rejected_warehouse not in warehouse_with_no_account ): - self.add_provisional_gl_entry( - d, gl_entries, self.posting_date, d.get("provisional_expense_account") - ) + warehouse_with_no_account.append(d.warehouse) if d.is_fixed_asset: self.update_assets(d, d.valuation_rate) @@ -756,7 +753,7 @@ def update_billing_status(self, update_modified=True): def get_stock_value_difference(voucher_no, voucher_detail_no, warehouse): - frappe.db.get_value( + return frappe.db.get_value( "Stock Ledger Entry", { "voucher_type": "Purchase Receipt", From acf96d7f9b2f52f4afd33afc8bb43394b661a8ba Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Fri, 20 Oct 2023 19:49:41 +0530 Subject: [PATCH 05/23] fix: Purchase Invoice GL entires for assets --- .../purchase_invoice/purchase_invoice.py | 214 +++--------------- erpnext/accounts/general_ledger.py | 2 +- 2 files changed, 32 insertions(+), 184 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 6d905a37cde3..010ce2ec11f0 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -30,7 +30,7 @@ ) from erpnext.accounts.party import get_due_date, get_party_account from erpnext.accounts.utils import get_account_currency, get_fiscal_year -from erpnext.assets.doctype.asset.asset import get_asset_account, is_cwip_accounting_enabled +from erpnext.assets.doctype.asset.asset import is_cwip_accounting_enabled from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account from erpnext.buying.utils import check_on_hold_or_closed_status from erpnext.controllers.accounts_controller import validate_account_head @@ -283,9 +283,6 @@ def set_expense_account(self, for_validate=False): # in case of auto inventory accounting, # expense account is always "Stock Received But Not Billed" for a stock item # except opening entry, drop-ship entry and fixed asset items - if item.item_code: - asset_category = frappe.get_cached_value("Item", item.item_code, "asset_category") - if ( auto_accounting_for_stock and item.item_code in stock_items @@ -352,20 +349,26 @@ def set_expense_account(self, for_validate=False): frappe.msgprint(msg, title=_("Expense Head Changed")) item.expense_account = stock_not_billed_account - - elif item.is_fixed_asset and not is_cwip_accounting_enabled(asset_category): + elif item.is_fixed_asset and item.pr_detail: + if not asset_received_but_not_billed: + asset_received_but_not_billed = self.get_company_default("asset_received_but_not_billed") + item.expense_account = asset_received_but_not_billed + elif item.is_fixed_asset: + account_type = ( + "capital_work_in_progress_account" + if is_cwip_accounting_enabled(item.asset_category) + else "fixed_asset_account" + ) asset_category_account = get_asset_category_account( - "fixed_asset_account", item=item.item_code, company=self.company + account_type, item=item.item_code, company=self.company ) if not asset_category_account: - form_link = get_link_to_form("Asset Category", asset_category) + form_link = get_link_to_form("Asset Category", item.asset_category) throw( _("Please set Fixed Asset Account in {} against {}.").format(form_link, self.company), title=_("Missing Account"), ) item.expense_account = asset_category_account - elif item.is_fixed_asset and item.pr_detail: - item.expense_account = asset_received_but_not_billed elif not item.expense_account and for_validate: throw(_("Expense account is mandatory for item {0}").format(item.item_code or item.item_name)) @@ -572,6 +575,7 @@ def get_gl_entries(self, warehouse_account=None): if self.auto_accounting_for_stock: self.stock_received_but_not_billed = self.get_company_default("stock_received_but_not_billed") self.expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation") + self.asset_received_but_not_billed = self.get_company_default("asset_received_but_not_billed") else: self.stock_received_but_not_billed = None self.expenses_included_in_valuation = None @@ -583,9 +587,6 @@ def get_gl_entries(self, warehouse_account=None): self.make_item_gl_entries(gl_entries) self.make_precision_loss_gl_entry(gl_entries) - if self.check_asset_cwip_enabled(): - self.get_asset_gl_entry(gl_entries) - self.make_tax_gl_entries(gl_entries) self.make_exchange_gain_loss_gl_entries(gl_entries) self.make_internal_transfer_gl_entries(gl_entries) @@ -690,7 +691,11 @@ def make_item_gl_entries(self, gl_entries): if item.item_code: asset_category = frappe.get_cached_value("Item", item.item_code, "asset_category") - if self.update_stock and self.auto_accounting_for_stock and item.item_code in stock_items: + if ( + self.update_stock + and self.auto_accounting_for_stock + and (item.item_code in stock_items or item.is_fixed_asset) + ): # warehouse account warehouse_debit_amount = self.make_stock_adjustment_entry( gl_entries, item, voucher_wise_stock_value, account_currency @@ -804,9 +809,7 @@ def make_item_gl_entries(self, gl_entries): ) ) - elif not item.is_fixed_asset or ( - item.is_fixed_asset and not is_cwip_accounting_enabled(asset_category) - ): + else: expense_account = ( item.expense_account if (not item.enable_deferred_expense or self.is_return) @@ -957,11 +960,16 @@ def make_item_gl_entries(self, gl_entries): (item.purchase_receipt, valuation_tax_accounts), ) + stock_rbnb = ( + self.asset_received_but_not_billed + if item.is_fixed_asset + else self.stock_received_but_not_billed + ) if not negative_expense_booked_in_pr: gl_entries.append( self.get_gl_dict( { - "account": self.stock_received_but_not_billed, + "account": stock_rbnb, "against": self.supplier, "debit": flt(item.item_tax_amount, item.precision("item_tax_amount")), "remarks": self.remarks or _("Accounting Entry for Stock"), @@ -976,172 +984,12 @@ def make_item_gl_entries(self, gl_entries): item.item_tax_amount, item.precision("item_tax_amount") ) - def make_precision_loss_gl_entry(self, gl_entries): - round_off_account, round_off_cost_center = get_round_off_account_and_cost_center( - self.company, "Purchase Invoice", self.name, self.use_company_roundoff_cost_center + assets = frappe.db.get_all( + "Asset", filters={"purchase_invoice": self.name, "item_code": item.item_code} ) - - precision_loss = self.get("base_net_total") - flt( - self.get("net_total") * self.conversion_rate, self.precision("net_total") - ) - - if precision_loss: - gl_entries.append( - self.get_gl_dict( - { - "account": round_off_account, - "against": self.supplier, - "credit": precision_loss, - "cost_center": round_off_cost_center - if self.use_company_roundoff_cost_center - else self.cost_center or round_off_cost_center, - "remarks": _("Net total calculation precision loss"), - } - ) - ) - - def get_asset_gl_entry(self, gl_entries): - arbnb_account = self.get_company_default("asset_received_but_not_billed") - eiiav_account = self.get_company_default("expenses_included_in_asset_valuation") - - for item in self.get("items"): - if item.is_fixed_asset: - asset_amount = flt(item.net_amount) + flt(item.item_tax_amount / self.conversion_rate) - base_asset_amount = flt(item.base_net_amount + item.item_tax_amount) - - item_exp_acc_type = frappe.db.get_value("Account", item.expense_account, "account_type") - if not item.expense_account or item_exp_acc_type not in [ - "Asset Received But Not Billed", - "Fixed Asset", - ]: - item.expense_account = arbnb_account - - if not self.update_stock: - arbnb_currency = get_account_currency(item.expense_account) - gl_entries.append( - self.get_gl_dict( - { - "account": item.expense_account, - "against": self.supplier, - "remarks": self.get("remarks") or _("Accounting Entry for Asset"), - "debit": base_asset_amount, - "debit_in_account_currency": ( - base_asset_amount if arbnb_currency == self.company_currency else asset_amount - ), - "cost_center": item.cost_center, - "project": item.project or self.project, - }, - item=item, - ) - ) - - if item.item_tax_amount: - asset_eiiav_currency = get_account_currency(eiiav_account) - gl_entries.append( - self.get_gl_dict( - { - "account": eiiav_account, - "against": self.supplier, - "remarks": self.get("remarks") or _("Accounting Entry for Asset"), - "cost_center": item.cost_center, - "project": item.project or self.project, - "credit": item.item_tax_amount, - "credit_in_account_currency": ( - item.item_tax_amount - if asset_eiiav_currency == self.company_currency - else item.item_tax_amount / self.conversion_rate - ), - }, - item=item, - ) - ) - else: - cwip_account = get_asset_account( - "capital_work_in_progress_account", asset_category=item.asset_category, company=self.company - ) - - cwip_account_currency = get_account_currency(cwip_account) - gl_entries.append( - self.get_gl_dict( - { - "account": cwip_account, - "against": self.supplier, - "remarks": self.get("remarks") or _("Accounting Entry for Asset"), - "debit": base_asset_amount, - "debit_in_account_currency": ( - base_asset_amount if cwip_account_currency == self.company_currency else asset_amount - ), - "cost_center": self.cost_center, - "project": item.project or self.project, - }, - item=item, - ) - ) - - if item.item_tax_amount and not cint(erpnext.is_perpetual_inventory_enabled(self.company)): - asset_eiiav_currency = get_account_currency(eiiav_account) - gl_entries.append( - self.get_gl_dict( - { - "account": eiiav_account, - "against": self.supplier, - "remarks": self.get("remarks") or _("Accounting Entry for Asset"), - "cost_center": item.cost_center, - "credit": item.item_tax_amount, - "project": item.project or self.project, - "credit_in_account_currency": ( - item.item_tax_amount - if asset_eiiav_currency == self.company_currency - else item.item_tax_amount / self.conversion_rate - ), - }, - item=item, - ) - ) - - # When update stock is checked - # Assets are bought through this document then it will be linked to this document - if self.update_stock: - if flt(item.landed_cost_voucher_amount): - gl_entries.append( - self.get_gl_dict( - { - "account": eiiav_account, - "against": cwip_account, - "cost_center": item.cost_center, - "remarks": self.get("remarks") or _("Accounting Entry for Stock"), - "credit": flt(item.landed_cost_voucher_amount), - "project": item.project or self.project, - }, - item=item, - ) - ) - - gl_entries.append( - self.get_gl_dict( - { - "account": cwip_account, - "against": eiiav_account, - "cost_center": item.cost_center, - "remarks": self.get("remarks") or _("Accounting Entry for Stock"), - "debit": flt(item.landed_cost_voucher_amount), - "project": item.project or self.project, - }, - item=item, - ) - ) - - # update gross amount of assets bought through this document - assets = frappe.db.get_all( - "Asset", filters={"purchase_invoice": self.name, "item_code": item.item_code} - ) - for asset in assets: - frappe.db.set_value("Asset", asset.name, "gross_purchase_amount", flt(item.valuation_rate)) - frappe.db.set_value( - "Asset", asset.name, "purchase_receipt_amount", flt(item.valuation_rate) - ) - - return gl_entries + for asset in assets: + frappe.db.set_value("Asset", asset.name, "gross_purchase_amount", flt(item.valuation_rate)) + frappe.db.set_value("Asset", asset.name, "purchase_receipt_amount", flt(item.valuation_rate)) def make_stock_adjustment_entry( self, gl_entries, item, voucher_wise_stock_value, account_currency diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index 16b61236dbaf..3573b129ef23 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -40,7 +40,7 @@ def make_gl_entries( from_repost=from_repost, ) save_entries(gl_map, adv_adj, update_outstanding, from_repost) - # Post GL Map proccess there may no be any GL Entries + # Post GL Map process there may no be any GL Entries elif gl_map: frappe.throw( _( From ff75be6018d438511b9a82e20a0491fc6076a5ba Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sat, 21 Oct 2023 17:45:45 +0530 Subject: [PATCH 06/23] test: cwip accounting unit tests --- erpnext/assets/doctype/asset/test_asset.py | 2 +- erpnext/controllers/stock_controller.py | 3 ++ .../purchase_receipt/purchase_receipt.py | 29 +++++++++---------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index fea6ed3d2bd0..7bb205fe2a9b 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -487,7 +487,7 @@ def test_expense_head(self): self.assertEqual("Asset Received But Not Billed - _TC", doc.items[0].expense_account) - # CWIP: Capital Work In Progress + # Capital Work In Progress def test_cwip_accounting(self): pr = make_purchase_receipt( item_code="Macbook Pro", qty=1, rate=5000, do_not_submit=True, location="Test Location" diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index c702e3a767d4..be44975e2e8b 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -62,9 +62,12 @@ def make_gl_entries(self, gl_entries=None, from_repost=False): ) ) + is_asset_pr = any(d.is_fixed_asset for d in self.get("items")) + if ( cint(erpnext.is_perpetual_inventory_enabled(self.company)) or provisional_accounting_for_non_stock_items + or is_asset_pr ): warehouse_account = get_warehouse_account_map(self.company) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 22d4e3c2fc43..b56e3ddc4393 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -329,7 +329,7 @@ def make_item_gl_entries(self, gl_entries, warehouse_account=None): "Asset" if is_asset_pr else "Stock" ) - if erpnext.is_perpetual_inventory_enabled(self.company): + if erpnext.is_perpetual_inventory_enabled(self.company) or is_asset_pr: stock_asset_rbnb = ( self.get_company_default("asset_received_but_not_billed") if is_asset_pr @@ -648,11 +648,8 @@ def add_provisional_gl_entry( ) def make_tax_gl_entries(self, gl_entries): - - if erpnext.is_perpetual_inventory_enabled(self.company): - expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation") - negative_expense_to_be_booked = sum([flt(d.item_tax_amount) for d in self.get("items")]) + is_asset_pr = any(d.is_fixed_asset for d in self.get("items")) # Cost center-wise amount breakup for other charges included for valuation valuation_tax = {} for tax in self.get("taxes"): @@ -676,22 +673,24 @@ def make_tax_gl_entries(self, gl_entries): # and charges added via Landed Cost Voucher, # post valuation related charges on "Stock Received But Not Billed" # introduced in 2014 for backward compatibility of expenses already booked in expenses_included_in_valuation account - - negative_expense_booked_in_pi = frappe.db.sql( - """select name from `tabPurchase Invoice Item` pi - where docstatus = 1 and purchase_receipt=%s - and exists(select name from `tabGL Entry` where voucher_type='Purchase Invoice' - and voucher_no=pi.parent and account=%s)""", - (self.name, expenses_included_in_valuation), - ) - against_account = ", ".join([d.account for d in gl_entries if flt(d.debit) > 0]) total_valuation_amount = sum(valuation_tax.values()) amount_including_divisional_loss = negative_expense_to_be_booked - stock_rbnb = self.get_company_default("stock_received_but_not_billed") + stock_rbnb = ( + self.get("asset_received_but_not_billed") + if is_asset_pr + else self.get_company_default("stock_received_but_not_billed") + ) i = 1 for tax in self.get("taxes"): if valuation_tax.get(tax.name): + negative_expense_booked_in_pi = frappe.db.sql( + """select name from `tabPurchase Invoice Item` pi + where docstatus = 1 and purchase_receipt=%s + and exists(select name from `tabGL Entry` where voucher_type='Purchase Invoice' + and voucher_no=pi.parent and account=%s)""", + (self.name, tax.account_head), + ) if negative_expense_booked_in_pi: account = stock_rbnb From ab654140ef74d1a5f7e72506ac2e4de2caa77361 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sat, 21 Oct 2023 17:53:20 +0530 Subject: [PATCH 07/23] chore: Attribute error --- erpnext/controllers/stock_controller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index be44975e2e8b..0d36871507e7 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -62,7 +62,7 @@ def make_gl_entries(self, gl_entries=None, from_repost=False): ) ) - is_asset_pr = any(d.is_fixed_asset for d in self.get("items")) + is_asset_pr = any(d.get("is_fixed_asset") for d in self.get("items")) if ( cint(erpnext.is_perpetual_inventory_enabled(self.company)) From b1d178ce7462d9f5c70fcfe458d95995cc31947a Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sat, 21 Oct 2023 20:00:45 +0530 Subject: [PATCH 08/23] chore: Purchase Invoice tests --- .../purchase_receipt/purchase_receipt.py | 75 +++++++++++-------- 1 file changed, 44 insertions(+), 31 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index b56e3ddc4393..8ec6c3cce4cd 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -323,22 +323,6 @@ def make_item_gl_entries(self, gl_entries, warehouse_account=None): get_purchase_document_details, ) - is_asset_pr = any(d.is_fixed_asset for d in self.get("items")) - stock_asset_rbnb = None - remarks = self.get("remarks") or _("Accounting Entry for {0}").format( - "Asset" if is_asset_pr else "Stock" - ) - - if erpnext.is_perpetual_inventory_enabled(self.company) or is_asset_pr: - stock_asset_rbnb = ( - self.get_company_default("asset_received_but_not_billed") - if is_asset_pr - else self.get_company_default("stock_received_but_not_billed") - ) - landed_cost_entries = get_item_account_wise_additional_cost(self.name) - - warehouse_with_no_account = [] - stock_items = self.get_stock_items() provisional_accounting_for_non_stock_items = cint( frappe.db.get_value( "Company", self.company, "enable_provisional_accounting_for_non_stock_items" @@ -347,8 +331,15 @@ def make_item_gl_entries(self, gl_entries, warehouse_account=None): exchange_rate_map, net_rate_map = get_purchase_document_details(self) + def validate_account(account_type): + frappe.throw(_("{0} account not found while submitting purchase receipt").format(account_type)) + def make_item_asset_inward_entries(item, stock_value_diff, stock_asset_account_name): account_currency = get_account_currency(stock_asset_account_name) + + if not stock_asset_account_name: + validate_account("Asset or warehouse account") + self.add_gl_entry( gl_entries=gl_entries, account=stock_asset_account_name, @@ -381,6 +372,9 @@ def make_stock_received_but_not_billed_entry(item): credit_amount = outgoing_amount if credit_amount: + if not account: + validate_account("Stock or Asset Received But Not Billed") + self.add_gl_entry( gl_entries=gl_entries, account=account, @@ -433,7 +427,7 @@ def make_stock_received_but_not_billed_entry(item): ) def make_landed_cost_gl_entries(item): - # Amount added through landed-cos-voucher + # Amount added through landed-cost-voucher if item.landed_cost_voucher_amount and landed_cost_entries: if (item.item_code, item.name) in landed_cost_entries: for account, amount in landed_cost_entries[(item.item_code, item.name)].items(): @@ -444,6 +438,9 @@ def make_landed_cost_gl_entries(item): else flt(amount["amount"]) ) + if not account: + validate_account("Landed Cost Account") + self.add_gl_entry( gl_entries=gl_entries, account=account, @@ -533,17 +530,36 @@ def make_divisional_loss_gl_entry(item): item=item, ) + stock_items = self.get_stock_items() + warehouse_with_no_account = [] + for d in self.get("items"): if ( - d.item_code not in stock_items + provisional_accounting_for_non_stock_items + and d.item_code not in stock_items and flt(d.qty) - and provisional_accounting_for_non_stock_items and d.get("provisional_expense_account") + and not d.is_fixed_asset ): self.add_provisional_gl_entry( d, gl_entries, self.posting_date, d.get("provisional_expense_account") ) elif flt(d.qty) and (flt(d.valuation_rate) or self.is_return): + is_asset_pr = any(d.is_fixed_asset for d in self.get("items")) + remarks = self.get("remarks") or _("Accounting Entry for {0}").format( + "Asset" if is_asset_pr else "Stock" + ) + + if not (erpnext.is_perpetual_inventory_enabled(self.company) or is_asset_pr): + return + + stock_asset_rbnb = ( + self.get_company_default("asset_received_but_not_billed") + if is_asset_pr + else self.get_company_default("stock_received_but_not_billed") + ) + landed_cost_entries = get_item_account_wise_additional_cost(self.name) + if d.is_fixed_asset: stock_asset_account_name = ( get_asset_category_account( @@ -558,11 +574,7 @@ def make_divisional_loss_gl_entry(item): ) stock_value_diff = flt(d.net_amount) + flt(d.item_tax_amount / self.conversion_rate) - elif ( - (flt(d.valuation_rate) or self.is_return) - and flt(d.qty) - and warehouse_account.get(d.warehouse) - ): + elif warehouse_account.get(d.warehouse): stock_value_diff = get_stock_value_difference(self.name, d.name, d.warehouse) stock_asset_account_name = warehouse_account[d.warehouse]["account"] supplier_warehouse_account = warehouse_account.get(self.supplier_warehouse, {}).get("account") @@ -580,12 +592,13 @@ def make_divisional_loss_gl_entry(item): ): continue - make_item_asset_inward_entries(d, stock_value_diff, stock_asset_account_name) - make_stock_received_but_not_billed_entry(d) - make_landed_cost_gl_entries(d) - make_rate_difference_entry(d) - make_sub_contracting_gl_entries(d) - make_divisional_loss_gl_entry(d) + if (flt(d.valuation_rate) or self.is_return or d.is_fixed_asset) and flt(d.qty): + make_item_asset_inward_entries(d, stock_value_diff, stock_asset_account_name) + make_stock_received_but_not_billed_entry(d) + make_landed_cost_gl_entries(d) + make_rate_difference_entry(d) + make_sub_contracting_gl_entries(d) + make_divisional_loss_gl_entry(d) elif ( d.warehouse not in warehouse_with_no_account or d.rejected_warehouse not in warehouse_with_no_account @@ -606,8 +619,8 @@ def add_provisional_gl_entry( self, item, gl_entries, posting_date, provisional_account, reverse=0 ): credit_currency = get_account_currency(provisional_account) - debit_currency = get_account_currency(item.expense_account) expense_account = item.expense_account + debit_currency = get_account_currency(item.expense_account) remarks = self.get("remarks") or _("Accounting Entry for Service") multiplication_factor = 1 From d986347d320bc3b4a69ff7320f6172ba49c520fb Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sat, 21 Oct 2023 21:46:58 +0530 Subject: [PATCH 09/23] chore: Missing asset account --- .../doctype/purchase_receipt/purchase_receipt.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 8ec6c3cce4cd..c1a5798637f9 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -12,8 +12,11 @@ import erpnext from erpnext.accounts.utils import get_account_currency -from erpnext.assets.doctype.asset.asset import get_asset_account, is_cwip_accounting_enabled -from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account +from erpnext.assets.doctype.asset.asset import ( + get_asset_account, + get_asset_category_account, + is_cwip_accounting_enabled, +) from erpnext.buying.utils import check_on_hold_or_closed_status from erpnext.controllers.buying_controller import BuyingController from erpnext.stock.doctype.delivery_note.delivery_note import make_inter_company_transaction @@ -568,9 +571,11 @@ def make_divisional_loss_gl_entry(item): company=self.company, ) if is_cwip_accounting_enabled(d.asset_category) - else get_asset_category_account( - asset_category=d.asset_category, fieldname="fixed_asset_account", company=self.company - ) + else "fixed_asset_account" + ) + + stock_asset_account_name = get_asset_account( + "account_type", asset_category=d.asset_category, company=self.company ) stock_value_diff = flt(d.net_amount) + flt(d.item_tax_amount / self.conversion_rate) From 22a19e92fdd7953d43154f011b520cb48ddfe54f Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sat, 21 Oct 2023 22:08:17 +0530 Subject: [PATCH 10/23] chore: Missing asset account --- erpnext/stock/doctype/purchase_receipt/purchase_receipt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index c1a5798637f9..d07fc45600d3 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -575,7 +575,7 @@ def make_divisional_loss_gl_entry(item): ) stock_asset_account_name = get_asset_account( - "account_type", asset_category=d.asset_category, company=self.company + account_type, asset_category=d.asset_category, company=self.company ) stock_value_diff = flt(d.net_amount) + flt(d.item_tax_amount / self.conversion_rate) From 71247ef965ec252e5dc786d2d5184775ec3e7440 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 22 Oct 2023 20:47:31 +0530 Subject: [PATCH 11/23] chore: update tests --- erpnext/assets/doctype/asset/test_asset.py | 7 ++++--- .../doctype/purchase_receipt/purchase_receipt.py | 14 +++++++++----- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 7bb205fe2a9b..ae7a2afc2751 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -186,6 +186,7 @@ def test_purchase_of_grouped_asset(self): def test_is_fixed_asset_set(self): asset = create_asset(is_existing_asset=1) doc = frappe.new_doc("Purchase Invoice") + doc.company = "_Test Company" doc.supplier = "_Test Supplier" doc.append("items", {"item_code": "Macbook Pro", "qty": 1, "asset": asset.name}) @@ -520,7 +521,8 @@ def test_cwip_accounting(self): pr.submit() expected_gle = ( - ("Asset Received But Not Billed - _TC", 0.0, 5250.0), + ("_Test Account Shipping Charges - _TC", 0.0, 250.0), + ("Asset Received But Not Billed - _TC", 0.0, 5000.0), ("CWIP Account - _TC", 5250.0, 0.0), ) @@ -539,9 +541,8 @@ def test_cwip_accounting(self): expected_gle = ( ("_Test Account Service Tax - _TC", 250.0, 0.0), ("_Test Account Shipping Charges - _TC", 250.0, 0.0), - ("Asset Received But Not Billed - _TC", 5250.0, 0.0), + ("Asset Received But Not Billed - _TC", 5000.0, 0.0), ("Creditors - _TC", 0.0, 5500.0), - ("Expenses Included In Asset Valuation - _TC", 0.0, 250.0), ) pi_gle = frappe.db.sql( diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index d07fc45600d3..5b5f9be7d6d9 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -337,7 +337,7 @@ def make_item_gl_entries(self, gl_entries, warehouse_account=None): def validate_account(account_type): frappe.throw(_("{0} account not found while submitting purchase receipt").format(account_type)) - def make_item_asset_inward_entries(item, stock_value_diff, stock_asset_account_name): + def make_item_asset_inward_gl_entry(item, stock_value_diff, stock_asset_account_name): account_currency = get_account_currency(stock_asset_account_name) if not stock_asset_account_name: @@ -361,7 +361,6 @@ def make_stock_received_but_not_billed_entry(item): ) account_currency = get_account_currency(account) - outgoing_amount = item.base_net_amount # GL Entry for from warehouse or Stock Received but not billed # Intentionally passed negative debit amount to avoid incorrect GL Entry validation credit_amount = ( @@ -370,6 +369,7 @@ def make_stock_received_but_not_billed_entry(item): else flt(item.net_amount, item.precision("net_amount")) ) + outgoing_amount = item.base_net_amount if self.is_internal_transfer() and item.valuation_rate: outgoing_amount = abs(get_stock_value_difference(self.name, item.name, item.from_warehouse)) credit_amount = outgoing_amount @@ -386,7 +386,7 @@ def make_stock_received_but_not_billed_entry(item): credit=0.0, remarks=remarks, against_account=stock_asset_account_name, - debit_in_account_currency=-1 * credit_amount, + debit_in_account_currency=-1 * flt(outgoing_amount, item.precision("base_net_amount")), account_currency=account_currency, item=item, ) @@ -578,7 +578,11 @@ def make_divisional_loss_gl_entry(item): account_type, asset_category=d.asset_category, company=self.company ) - stock_value_diff = flt(d.net_amount) + flt(d.item_tax_amount / self.conversion_rate) + stock_value_diff = ( + flt(d.net_amount) + + flt(d.item_tax_amount / self.conversion_rate) + + flt(d.landed_cost_voucher_amount) + ) elif warehouse_account.get(d.warehouse): stock_value_diff = get_stock_value_difference(self.name, d.name, d.warehouse) stock_asset_account_name = warehouse_account[d.warehouse]["account"] @@ -598,7 +602,7 @@ def make_divisional_loss_gl_entry(item): continue if (flt(d.valuation_rate) or self.is_return or d.is_fixed_asset) and flt(d.qty): - make_item_asset_inward_entries(d, stock_value_diff, stock_asset_account_name) + make_item_asset_inward_gl_entry(d, stock_value_diff, stock_asset_account_name) make_stock_received_but_not_billed_entry(d) make_landed_cost_gl_entries(d) make_rate_difference_entry(d) From 0ea4c98aa67ea9d73849670e82b3deff62a00b3c Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 22 Oct 2023 22:06:25 +0530 Subject: [PATCH 12/23] fix: Internal transfer GL Entries --- .../stock/doctype/purchase_receipt/purchase_receipt.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 5b5f9be7d6d9..40bc8f5d8e8a 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -429,6 +429,8 @@ def make_stock_received_but_not_billed_entry(item): item=item, ) + return outgoing_amount + def make_landed_cost_gl_entries(item): # Amount added through landed-cost-voucher if item.landed_cost_voucher_amount and landed_cost_entries: @@ -489,14 +491,14 @@ def make_sub_contracting_gl_entries(item): item=item, ) - def make_divisional_loss_gl_entry(item): + def make_divisional_loss_gl_entry(item, outgoing_amount): if item.is_fixed_asset: return # divisional loss adjustment expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation") valuation_amount_as_per_doc = ( - flt(item.base_net_amount, d.precision("base_net_amount")) + flt(outgoing_amount, d.precision("base_net_amount")) + flt(item.landed_cost_voucher_amount) + flt(item.rm_supp_cost) + flt(item.item_tax_amount) @@ -603,11 +605,11 @@ def make_divisional_loss_gl_entry(item): if (flt(d.valuation_rate) or self.is_return or d.is_fixed_asset) and flt(d.qty): make_item_asset_inward_gl_entry(d, stock_value_diff, stock_asset_account_name) - make_stock_received_but_not_billed_entry(d) + outgoing_amount = make_stock_received_but_not_billed_entry(d) make_landed_cost_gl_entries(d) make_rate_difference_entry(d) make_sub_contracting_gl_entries(d) - make_divisional_loss_gl_entry(d) + make_divisional_loss_gl_entry(d, outgoing_amount) elif ( d.warehouse not in warehouse_with_no_account or d.rejected_warehouse not in warehouse_with_no_account From edd4550ae18e44a9dcbec15883acda19db9c847a Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 23 Oct 2023 13:17:39 +0530 Subject: [PATCH 13/23] test: Deprecate tests --- erpnext/controllers/stock_controller.py | 23 ++++-- .../purchase_receipt/test_purchase_receipt.py | 82 ------------------- .../doctype/stock_entry/test_stock_entry.py | 4 +- 3 files changed, 17 insertions(+), 92 deletions(-) diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 0d36871507e7..35e201735908 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -667,13 +667,22 @@ def set_rate_of_stock_uom(self): d.stock_uom_rate = d.rate / (d.conversion_factor or 1) def validate_internal_transfer(self): - if ( - self.doctype in ("Sales Invoice", "Delivery Note", "Purchase Invoice", "Purchase Receipt") - and self.is_internal_transfer() - ): - self.validate_in_transit_warehouses() - self.validate_multi_currency() - self.validate_packed_items() + if self.doctype in ("Sales Invoice", "Delivery Note", "Purchase Invoice", "Purchase Receipt"): + if self.is_internal_transfer(): + print("Inininininin") + self.validate_in_transit_warehouses() + self.validate_multi_currency() + self.validate_packed_items() + else: + self.validate_internal_transfer_warehouse() + + def validate_internal_transfer_warehouse(self): + for row in self.items: + if row.get("target_warehouse"): + row.target_warehouse = None + + if row.get("from_warehouse"): + row.from_warehouse = None def validate_in_transit_warehouses(self): if ( diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index 585871cf3910..344ac78ac76b 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -927,88 +927,6 @@ def test_make_purchase_invoice_from_pr_with_returned_qty_duplicate_items(self): pr1.reload() pr1.cancel() - def test_stock_transfer_from_purchase_receipt(self): - pr1 = make_purchase_receipt( - warehouse="Work In Progress - TCP1", company="_Test Company with perpetual inventory" - ) - - pr = make_purchase_receipt( - company="_Test Company with perpetual inventory", warehouse="Stores - TCP1", do_not_save=1 - ) - - pr.supplier_warehouse = "" - pr.items[0].from_warehouse = "Work In Progress - TCP1" - - pr.submit() - - gl_entries = get_gl_entries("Purchase Receipt", pr.name) - sl_entries = get_sl_entries("Purchase Receipt", pr.name) - - self.assertFalse(gl_entries) - - expected_sle = {"Work In Progress - TCP1": -5, "Stores - TCP1": 5} - - for sle in sl_entries: - self.assertEqual(expected_sle[sle.warehouse], sle.actual_qty) - - pr.cancel() - pr1.cancel() - - def test_stock_transfer_from_purchase_receipt_with_valuation(self): - create_warehouse( - "_Test Warehouse for Valuation", - company="_Test Company with perpetual inventory", - properties={"account": "_Test Account Stock In Hand - TCP1"}, - ) - - pr1 = make_purchase_receipt( - warehouse="_Test Warehouse for Valuation - TCP1", - company="_Test Company with perpetual inventory", - ) - - pr = make_purchase_receipt( - company="_Test Company with perpetual inventory", warehouse="Stores - TCP1", do_not_save=1 - ) - - pr.items[0].from_warehouse = "_Test Warehouse for Valuation - TCP1" - pr.supplier_warehouse = "" - - pr.append( - "taxes", - { - "charge_type": "On Net Total", - "account_head": "_Test Account Shipping Charges - TCP1", - "category": "Valuation and Total", - "cost_center": "Main - TCP1", - "description": "Test", - "rate": 9, - }, - ) - - pr.submit() - - gl_entries = get_gl_entries("Purchase Receipt", pr.name) - sl_entries = get_sl_entries("Purchase Receipt", pr.name) - - expected_gle = [ - ["Stock In Hand - TCP1", 272.5, 0.0], - ["_Test Account Stock In Hand - TCP1", 0.0, 250.0], - ["_Test Account Shipping Charges - TCP1", 0.0, 22.5], - ] - - expected_sle = {"_Test Warehouse for Valuation - TCP1": -5, "Stores - TCP1": 5} - - for sle in sl_entries: - self.assertEqual(expected_sle[sle.warehouse], sle.actual_qty) - - for i, gle in enumerate(gl_entries): - self.assertEqual(gle.account, expected_gle[i][0]) - self.assertEqual(gle.debit, expected_gle[i][1]) - self.assertEqual(gle.credit, expected_gle[i][2]) - - pr.cancel() - pr1.cancel() - def test_po_to_pi_and_po_to_pr_worflow_full(self): """Test following behaviour: - Create PO diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index de74fda687de..dd15031b30e8 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -504,9 +504,7 @@ def test_repack_with_additional_costs(self): self.check_gl_entries( "Stock Entry", repack.name, - sorted( - [[stock_in_hand_account, 1200, 0.0], ["Expenses Included In Valuation - TCP1", 0.0, 1200.0]] - ), + sorted([[stock_in_hand_account, 1200, 0.0], ["Cost of Goods Sold - TCP1", 0.0, 1200.0]]), ) def check_stock_ledger_entries(self, voucher_type, voucher_no, expected_sle): From 2bbd3dcdda375ab4e5de29217aee683bf6efc9b5 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 23 Oct 2023 14:44:18 +0530 Subject: [PATCH 14/23] test: Depricate tests --- erpnext/controllers/stock_controller.py | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 35e201735908..b9e30584d671 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -669,7 +669,6 @@ def set_rate_of_stock_uom(self): def validate_internal_transfer(self): if self.doctype in ("Sales Invoice", "Delivery Note", "Purchase Invoice", "Purchase Receipt"): if self.is_internal_transfer(): - print("Inininininin") self.validate_in_transit_warehouses() self.validate_multi_currency() self.validate_packed_items() From e86647e5b4d49ea1d4c84fa940cb9ae327908c35 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 23 Oct 2023 16:30:52 +0530 Subject: [PATCH 15/23] test: Depricate tests --- .../sales_invoice/test_sales_invoice.py | 30 ------------------- 1 file changed, 30 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index f9fb6232ac96..4e5830ddea8f 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -2506,36 +2506,6 @@ def test_inter_company_transaction_without_default_warehouse(self): frappe.local.enable_perpetual_inventory["_Test Company 1"] = old_perpetual_inventory frappe.db.set_value("Stock Settings", None, "allow_negative_stock", old_negative_stock) - def test_sle_for_target_warehouse(self): - se = make_stock_entry( - item_code="138-CMS Shoe", - target="Finished Goods - _TC", - company="_Test Company", - qty=1, - basic_rate=500, - ) - - si = frappe.copy_doc(test_records[0]) - si.update_stock = 1 - si.set_warehouse = "Finished Goods - _TC" - si.set_target_warehouse = "Stores - _TC" - si.get("items")[0].warehouse = "Finished Goods - _TC" - si.get("items")[0].target_warehouse = "Stores - _TC" - si.insert() - si.submit() - - sles = frappe.get_all( - "Stock Ledger Entry", filters={"voucher_no": si.name}, fields=["name", "actual_qty"] - ) - - # check if both SLEs are created - self.assertEqual(len(sles), 2) - self.assertEqual(sum(d.actual_qty for d in sles), 0.0) - - # tear down - si.cancel() - se.cancel() - def test_internal_transfer_gl_entry(self): si = create_sales_invoice( company="_Test Company with perpetual inventory", From c9edac1df6b67cf61c178c80be56796d8c8db9b4 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 18 Oct 2023 12:01:22 +0530 Subject: [PATCH 16/23] chore: make `Reserve Stock` checkbox visible in SO --- erpnext/selling/doctype/sales_order/sales_order.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json index 4f498fb20d56..490bd7a98308 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.json +++ b/erpnext/selling/doctype/sales_order/sales_order.json @@ -1631,7 +1631,7 @@ "idx": 105, "is_submittable": 1, "links": [], - "modified": "2023-04-20 11:14:01.036202", + "modified": "2023-10-18 12:41:54.813462", "modified_by": "Administrator", "module": "Selling", "name": "Sales Order", From c8fb2cf01b40e88d2266772639fbfa61f421d2c2 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 18 Oct 2023 12:38:42 +0530 Subject: [PATCH 17/23] refactor: rename field `Auto Reserve Stock for Sales Order` From 19a45176732a47fbc616130ddfeee6bcbce4d91b Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 19 Oct 2023 14:43:29 +0530 Subject: [PATCH 18/23] feat: add fields to hold SO and SO Item ref in PR Item --- .../doctype/purchase_order/purchase_order.py | 2 ++ .../purchase_receipt_item.json | 26 +++++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 06b9d29e69c7..d87a855febf1 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -522,6 +522,8 @@ def update_item(obj, target, source_parent): "bom": "bom", "material_request": "material_request", "material_request_item": "material_request_item", + "sales_order": "sales_order", + "sales_order_item": "sales_order_item", }, "postprocess": update_item, "condition": lambda doc: abs(doc.received_qty) < abs(doc.qty) diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json index 4911523e7ed4..d7b1660c55ff 100644 --- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json +++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json @@ -118,7 +118,9 @@ "dimension_col_break", "cost_center", "section_break_80", - "page_break" + "page_break", + "sales_order", + "sales_order_item" ], "fields": [ { @@ -1025,12 +1027,32 @@ "fieldtype": "Link", "label": "WIP Composite Asset", "options": "Asset" + }, + { + "fieldname": "sales_order", + "fieldtype": "Link", + "label": "Sales Order", + "no_copy": 1, + "options": "Sales Order", + "print_hide": 1, + "read_only": 1, + "search_index": 1 + }, + { + "fieldname": "sales_order_item", + "fieldtype": "Data", + "hidden": 1, + "label": "Sales Order Item", + "no_copy": 1, + "print_hide": 1, + "read_only": 1, + "search_index": 1 } ], "idx": 1, "istable": 1, "links": [], - "modified": "2023-10-03 21:11:50.547261", + "modified": "2023-10-19 10:50:58.071735", "modified_by": "Administrator", "module": "Stock", "name": "Purchase Receipt Item", From 3fc856e422ac6145889c7d1df5f6f6c974092c72 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 23 Oct 2023 13:17:39 +0530 Subject: [PATCH 19/23] test: Deprecate tests --- erpnext/controllers/stock_controller.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index a72cc667399a..62b4fa42d4c7 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -670,6 +670,7 @@ def set_rate_of_stock_uom(self): def validate_internal_transfer(self): if self.doctype in ("Sales Invoice", "Delivery Note", "Purchase Invoice", "Purchase Receipt"): if self.is_internal_transfer(): + print("Inininininin") self.validate_in_transit_warehouses() self.validate_multi_currency() self.validate_packed_items() From 662b6ec944272d9e3b8a20ab950d453dc26d7b8d Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 23 Oct 2023 14:44:18 +0530 Subject: [PATCH 20/23] test: Depricate tests --- erpnext/controllers/stock_controller.py | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 62b4fa42d4c7..a72cc667399a 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -670,7 +670,6 @@ def set_rate_of_stock_uom(self): def validate_internal_transfer(self): if self.doctype in ("Sales Invoice", "Delivery Note", "Purchase Invoice", "Purchase Receipt"): if self.is_internal_transfer(): - print("Inininininin") self.validate_in_transit_warehouses() self.validate_multi_currency() self.validate_packed_items() From af8beb3714798f7aec99cbc517bf4ada97c9562b Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 23 Oct 2023 16:30:52 +0530 Subject: [PATCH 21/23] test: Depricate tests --- erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 96338fe1081a..a2eef7109043 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -2540,7 +2540,7 @@ def test_inter_company_transaction_without_default_warehouse(self): # tear down frappe.local.enable_perpetual_inventory["_Test Company 1"] = old_perpetual_inventory - frappe.db.set_value("Stock Settings", None, "allow_negative_stock", old_negative_stock) + frappe.db.set_single_value("Stock Settings", "allow_negative_stock", old_negative_stock) def test_internal_transfer_gl_entry(self): si = create_sales_invoice( From c58185cd97894071855c04b79de8ba9598e4a6af Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 23 Oct 2023 10:42:23 +0530 Subject: [PATCH 22/23] refactor: Remove expense included in valuation accounts --- .../purchase_invoice/purchase_invoice.py | 39 +---------------- .../sales_invoice/test_sales_invoice.py | 6 --- erpnext/manufacturing/doctype/bom/bom.py | 8 ++-- ...se_account_in_landed_cost_voucher_taxes.py | 42 ------------------- erpnext/setup/doctype/company/company.js | 3 -- erpnext/setup/doctype/company/company.json | 19 +-------- erpnext/setup/doctype/company/company.py | 3 -- .../purchase_receipt/purchase_receipt.py | 14 ++----- .../doctype/stock_entry/test_stock_entry.py | 8 ++-- .../subcontracting_receipt.py | 6 +-- 10 files changed, 15 insertions(+), 133 deletions(-) delete mode 100644 erpnext/patches/v12_0/set_expense_account_in_landed_cost_voucher_taxes.py diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 13eb7589eced..306208603c0e 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -592,13 +592,12 @@ def make_gl_entries(self, gl_entries=None, from_repost=False): def get_gl_entries(self, warehouse_account=None): self.auto_accounting_for_stock = erpnext.is_perpetual_inventory_enabled(self.company) + self.asset_received_but_not_billed = self.get_company_default("asset_received_but_not_billed") + if self.auto_accounting_for_stock: self.stock_received_but_not_billed = self.get_company_default("stock_received_but_not_billed") - self.expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation") - self.asset_received_but_not_billed = self.get_company_default("asset_received_but_not_billed") else: self.stock_received_but_not_billed = None - self.expenses_included_in_valuation = None self.negative_expense_to_be_booked = 0.0 gl_entries = [] @@ -922,40 +921,6 @@ def make_item_gl_entries(self, gl_entries): ) ) - # If asset is bought through this document and not linked to PR - if self.update_stock and item.landed_cost_voucher_amount: - expenses_included_in_asset_valuation = self.get_company_default( - "expenses_included_in_asset_valuation" - ) - # Amount added through landed-cost-voucher - gl_entries.append( - self.get_gl_dict( - { - "account": expenses_included_in_asset_valuation, - "against": expense_account, - "cost_center": item.cost_center, - "remarks": self.get("remarks") or _("Accounting Entry for Stock"), - "credit": flt(item.landed_cost_voucher_amount), - "project": item.project or self.project, - }, - item=item, - ) - ) - - gl_entries.append( - self.get_gl_dict( - { - "account": expense_account, - "against": expenses_included_in_asset_valuation, - "cost_center": item.cost_center, - "remarks": self.get("remarks") or _("Accounting Entry for Stock"), - "debit": flt(item.landed_cost_voucher_amount), - "project": item.project or self.project, - }, - item=item, - ) - ) - # update gross amount of asset bought through this document assets = frappe.db.get_all( "Asset", filters={"purchase_invoice": self.name, "item_code": item.item_code} diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 2db3963fdda6..79363dbeb1b5 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -2497,12 +2497,6 @@ def test_inter_company_transaction_without_default_warehouse(self): "stock_received_but_not_billed", "Stock Received But Not Billed - _TC1", ) - frappe.db.set_value( - "Company", - "_Test Company 1", - "expenses_included_in_valuation", - "Expenses Included In Valuation - _TC1", - ) # begin test si = create_sales_invoice( diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 8058a5f8b752..8d593d129636 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -1172,12 +1172,12 @@ def get_children(parent=None, is_root=False, **filters): def add_additional_cost(stock_entry, work_order): # Add non stock items cost in the additional cost stock_entry.additional_costs = [] - expenses_included_in_valuation = frappe.get_cached_value( - "Company", work_order.company, "expenses_included_in_valuation" + default_expense_account = frappe.get_cached_value( + "Company", work_order.company, "default_expense_account" ) - add_non_stock_items_cost(stock_entry, work_order, expenses_included_in_valuation) - add_operations_cost(stock_entry, work_order, expenses_included_in_valuation) + add_non_stock_items_cost(stock_entry, work_order, default_expense_account) + add_operations_cost(stock_entry, work_order, default_expense_account) def add_non_stock_items_cost(stock_entry, work_order, expense_account): diff --git a/erpnext/patches/v12_0/set_expense_account_in_landed_cost_voucher_taxes.py b/erpnext/patches/v12_0/set_expense_account_in_landed_cost_voucher_taxes.py deleted file mode 100644 index 9588e026d34c..000000000000 --- a/erpnext/patches/v12_0/set_expense_account_in_landed_cost_voucher_taxes.py +++ /dev/null @@ -1,42 +0,0 @@ -import frappe - - -def execute(): - frappe.reload_doctype("Landed Cost Taxes and Charges") - - company_account_map = frappe._dict( - frappe.db.sql( - """ - SELECT name, expenses_included_in_valuation from `tabCompany` - """ - ) - ) - - for company, account in company_account_map.items(): - frappe.db.sql( - """ - UPDATE - `tabLanded Cost Taxes and Charges` t, `tabLanded Cost Voucher` l - SET - t.expense_account = %s - WHERE - l.docstatus = 1 - AND l.company = %s - AND t.parent = l.name - """, - (account, company), - ) - - frappe.db.sql( - """ - UPDATE - `tabLanded Cost Taxes and Charges` t, `tabStock Entry` s - SET - t.expense_account = %s - WHERE - s.docstatus = 1 - AND s.company = %s - AND t.parent = s.name - """, - (account, company), - ) diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js index 6aa400a53c70..15f32b15c5eb 100644 --- a/erpnext/setup/doctype/company/company.js +++ b/erpnext/setup/doctype/company/company.js @@ -223,7 +223,6 @@ erpnext.company.setup_queries = function(frm) { ["cost_center", {}], ["round_off_cost_center", {}], ["depreciation_cost_center", {}], - ["expenses_included_in_asset_valuation", {"account_type": "Expenses Included In Asset Valuation"}], ["capital_work_in_progress_account", {"account_type": "Capital Work in Progress"}], ["asset_received_but_not_billed", {"account_type": "Asset Received But Not Billed"}], ["unrealized_profit_loss_account", {"root_type": ["in", ["Liability", "Asset"]]}], @@ -236,8 +235,6 @@ erpnext.company.setup_queries = function(frm) { $.each([ ["stock_adjustment_account", {"root_type": "Expense", "account_type": "Stock Adjustment"}], - ["expenses_included_in_valuation", - {"root_type": "Expense", "account_type": "Expenses Included in Valuation"}], ["stock_received_but_not_billed", {"root_type": "Liability", "account_type": "Stock Received But Not Billed"}], ["service_received_but_not_billed", diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json index 38f1c0bcdb24..785cab5d08f8 100644 --- a/erpnext/setup/doctype/company/company.json +++ b/erpnext/setup/doctype/company/company.json @@ -75,16 +75,13 @@ "enable_provisional_accounting_for_non_stock_items", "default_inventory_account", "stock_adjustment_account", - "default_in_transit_warehouse", "column_break_32", "stock_received_but_not_billed", "default_provisional_account", - "expenses_included_in_valuation", "fixed_asset_defaults", "accumulated_depreciation_account", "depreciation_expense_account", "series_for_depreciation_entry", - "expenses_included_in_asset_valuation", "column_break_40", "disposal_account", "depreciation_cost_center", @@ -466,14 +463,6 @@ "no_copy": 1, "options": "Account" }, - { - "fieldname": "expenses_included_in_valuation", - "fieldtype": "Link", - "ignore_user_permissions": 1, - "label": "Expenses Included In Valuation", - "no_copy": 1, - "options": "Account" - }, { "fieldname": "accumulated_depreciation_account", "fieldtype": "Link", @@ -493,12 +482,6 @@ "fieldtype": "Data", "label": "Series for Asset Depreciation Entry (Journal Entry)" }, - { - "fieldname": "expenses_included_in_asset_valuation", - "fieldtype": "Link", - "label": "Expenses Included In Asset Valuation", - "options": "Account" - }, { "fieldname": "column_break_40", "fieldtype": "Column Break" @@ -728,7 +711,7 @@ "image_field": "company_logo", "is_tree": 1, "links": [], - "modified": "2023-07-07 05:41:41.537256", + "modified": "2023-10-23 10:19:24.322898", "modified_by": "Administrator", "module": "Setup", "name": "Company", diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index fcdf245659bb..bea76f19412b 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -92,7 +92,6 @@ def validate_default_accounts(self): ["Default Income Account", "default_income_account"], ["Stock Received But Not Billed Account", "stock_received_but_not_billed"], ["Stock Adjustment Account", "stock_adjustment_account"], - ["Expense Included In Valuation Account", "expenses_included_in_valuation"], ] for account in accounts: @@ -384,7 +383,6 @@ def set_default_accounts(self): "depreciation_expense_account": "Depreciation", "capital_work_in_progress_account": "Capital Work in Progress", "asset_received_but_not_billed": "Asset Received But Not Billed", - "expenses_included_in_asset_valuation": "Expenses Included In Asset Valuation", "default_expense_account": "Cost of Goods Sold", } @@ -394,7 +392,6 @@ def set_default_accounts(self): "stock_received_but_not_billed": "Stock Received But Not Billed", "default_inventory_account": "Stock", "stock_adjustment_account": "Stock Adjustment", - "expenses_included_in_valuation": "Expenses Included In Valuation", } ) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 04b372fb05af..964ce0b7218c 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -492,7 +492,6 @@ def make_divisional_loss_gl_entry(item, outgoing_amount): return # divisional loss adjustment - expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation") valuation_amount_as_per_doc = ( flt(outgoing_amount, d.precision("base_net_amount")) + flt(item.landed_cost_voucher_amount) @@ -506,13 +505,10 @@ def make_divisional_loss_gl_entry(item, outgoing_amount): ) if divisional_loss: - if self.is_return or flt(item.item_tax_amount): - loss_account = expenses_included_in_valuation - else: - loss_account = ( - self.get_company_default("default_expense_account", ignore_validation=True) - or stock_asset_rbnb - ) + loss_account = ( + self.get_company_default("default_expense_account", ignore_validation=True) + or stock_asset_rbnb + ) cost_center = item.cost_center or frappe.get_cached_value( "Company", self.company, "cost_center" @@ -685,10 +681,8 @@ def make_tax_gl_entries(self, gl_entries): if negative_expense_to_be_booked and valuation_tax: # Backward compatibility: - # If expenses_included_in_valuation account has been credited in against PI # and charges added via Landed Cost Voucher, # post valuation related charges on "Stock Received But Not Billed" - # introduced in 2014 for backward compatibility of expenses already booked in expenses_included_in_valuation account against_account = ", ".join([d.account for d in gl_entries if flt(d.debit) > 0]) total_valuation_amount = sum(valuation_tax.values()) amount_including_divisional_loss = negative_expense_to_be_booked diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index dd15031b30e8..72f6bcdddf27 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -447,9 +447,7 @@ def test_repack_with_additional_costs(self): repack.posting_date = nowdate() repack.posting_time = nowtime() - expenses_included_in_valuation = frappe.get_value( - "Company", company, "expenses_included_in_valuation" - ) + default_expense_account = frappe.get_value("Company", company, "default_expense_account") items = get_multiple_items() repack.items = [] @@ -460,12 +458,12 @@ def test_repack_with_additional_costs(self): "additional_costs", [ { - "expense_account": expenses_included_in_valuation, + "expense_account": default_expense_account, "description": "Actual Operating Cost", "amount": 1000, }, { - "expense_account": expenses_included_in_valuation, + "expense_account": default_expense_account, "description": "Additional Operating Cost", "amount": 200, }, diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index 130f38fb8091..a83068f73fd8 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -299,7 +299,6 @@ def get_gl_entries(self, warehouse_account=None): def make_item_gl_entries(self, gl_entries, warehouse_account=None): stock_rbnb = self.get_company_default("stock_received_but_not_billed") - expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation") warehouse_with_no_account = [] @@ -371,10 +370,7 @@ def make_item_gl_entries(self, gl_entries, warehouse_account=None): divisional_loss = flt(item.amount - stock_value_diff, item.precision("amount")) if divisional_loss: - if self.is_return: - loss_account = expenses_included_in_valuation - else: - loss_account = item.expense_account + loss_account = item.expense_account self.add_gl_entry( gl_entries=gl_entries, From bbb243355124685f535697d5d5f7240d24b51cbb Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 24 Oct 2023 21:33:43 +0530 Subject: [PATCH 23/23] chore: Add back default in transit warehousefield --- erpnext/setup/doctype/company/company.json | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/setup/doctype/company/company.json b/erpnext/setup/doctype/company/company.json index 785cab5d08f8..349c328c06c8 100644 --- a/erpnext/setup/doctype/company/company.json +++ b/erpnext/setup/doctype/company/company.json @@ -75,6 +75,7 @@ "enable_provisional_accounting_for_non_stock_items", "default_inventory_account", "stock_adjustment_account", + "default_in_transit_warehouse", "column_break_32", "stock_received_but_not_billed", "default_provisional_account",