Merge pull request #34235 from rohitwaghchaure/feat-adjust-valuation-rate
feat: adjust purchase receipt valuation rate as per purchase invoice rate
This commit is contained in:
commit
2942cee31e
@ -1485,11 +1485,17 @@ class PurchaseInvoice(BuyingController):
|
|||||||
if po_details:
|
if po_details:
|
||||||
updated_pr += update_billed_amount_based_on_po(po_details, update_modified)
|
updated_pr += update_billed_amount_based_on_po(po_details, update_modified)
|
||||||
|
|
||||||
|
adjust_incoming_rate = frappe.db.get_single_value(
|
||||||
|
"Buying Settings", "set_landed_cost_based_on_purchase_invoice_rate"
|
||||||
|
)
|
||||||
|
|
||||||
for pr in set(updated_pr):
|
for pr in set(updated_pr):
|
||||||
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import update_billing_percentage
|
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import update_billing_percentage
|
||||||
|
|
||||||
pr_doc = frappe.get_doc("Purchase Receipt", pr)
|
pr_doc = frappe.get_doc("Purchase Receipt", pr)
|
||||||
update_billing_percentage(pr_doc, update_modified=update_modified)
|
update_billing_percentage(
|
||||||
|
pr_doc, update_modified=update_modified, adjust_incoming_rate=adjust_incoming_rate
|
||||||
|
)
|
||||||
|
|
||||||
def get_pr_details_billed_amt(self):
|
def get_pr_details_billed_amt(self):
|
||||||
# Get billed amount based on purchase receipt item reference (pr_detail) in purchase invoice
|
# Get billed amount based on purchase receipt item reference (pr_detail) in purchase invoice
|
||||||
|
@ -1523,6 +1523,94 @@ class TestPurchaseInvoice(unittest.TestCase, StockTestMixin):
|
|||||||
company.enable_provisional_accounting_for_non_stock_items = 0
|
company.enable_provisional_accounting_for_non_stock_items = 0
|
||||||
company.save()
|
company.save()
|
||||||
|
|
||||||
|
def test_adjust_incoming_rate(self):
|
||||||
|
frappe.db.set_single_value("Buying Settings", "maintain_same_rate", 0)
|
||||||
|
|
||||||
|
frappe.db.set_single_value(
|
||||||
|
"Buying Settings", "set_landed_cost_based_on_purchase_invoice_rate", 1
|
||||||
|
)
|
||||||
|
|
||||||
|
# Increase the cost of the item
|
||||||
|
|
||||||
|
pr = make_purchase_receipt(qty=1, rate=100)
|
||||||
|
|
||||||
|
stock_value_difference = frappe.db.get_value(
|
||||||
|
"Stock Ledger Entry",
|
||||||
|
{"voucher_type": "Purchase Receipt", "voucher_no": pr.name},
|
||||||
|
"stock_value_difference",
|
||||||
|
)
|
||||||
|
self.assertEqual(stock_value_difference, 100)
|
||||||
|
|
||||||
|
pi = create_purchase_invoice_from_receipt(pr.name)
|
||||||
|
for row in pi.items:
|
||||||
|
row.rate = 150
|
||||||
|
|
||||||
|
pi.save()
|
||||||
|
pi.submit()
|
||||||
|
|
||||||
|
stock_value_difference = frappe.db.get_value(
|
||||||
|
"Stock Ledger Entry",
|
||||||
|
{"voucher_type": "Purchase Receipt", "voucher_no": pr.name},
|
||||||
|
"stock_value_difference",
|
||||||
|
)
|
||||||
|
self.assertEqual(stock_value_difference, 150)
|
||||||
|
|
||||||
|
# Reduce the cost of the item
|
||||||
|
|
||||||
|
pr = make_purchase_receipt(qty=1, rate=100)
|
||||||
|
|
||||||
|
stock_value_difference = frappe.db.get_value(
|
||||||
|
"Stock Ledger Entry",
|
||||||
|
{"voucher_type": "Purchase Receipt", "voucher_no": pr.name},
|
||||||
|
"stock_value_difference",
|
||||||
|
)
|
||||||
|
self.assertEqual(stock_value_difference, 100)
|
||||||
|
|
||||||
|
pi = create_purchase_invoice_from_receipt(pr.name)
|
||||||
|
for row in pi.items:
|
||||||
|
row.rate = 50
|
||||||
|
|
||||||
|
pi.save()
|
||||||
|
pi.submit()
|
||||||
|
|
||||||
|
stock_value_difference = frappe.db.get_value(
|
||||||
|
"Stock Ledger Entry",
|
||||||
|
{"voucher_type": "Purchase Receipt", "voucher_no": pr.name},
|
||||||
|
"stock_value_difference",
|
||||||
|
)
|
||||||
|
self.assertEqual(stock_value_difference, 50)
|
||||||
|
|
||||||
|
frappe.db.set_single_value(
|
||||||
|
"Buying Settings", "set_landed_cost_based_on_purchase_invoice_rate", 0
|
||||||
|
)
|
||||||
|
|
||||||
|
# Don't adjust incoming rate
|
||||||
|
|
||||||
|
pr = make_purchase_receipt(qty=1, rate=100)
|
||||||
|
|
||||||
|
stock_value_difference = frappe.db.get_value(
|
||||||
|
"Stock Ledger Entry",
|
||||||
|
{"voucher_type": "Purchase Receipt", "voucher_no": pr.name},
|
||||||
|
"stock_value_difference",
|
||||||
|
)
|
||||||
|
self.assertEqual(stock_value_difference, 100)
|
||||||
|
|
||||||
|
pi = create_purchase_invoice_from_receipt(pr.name)
|
||||||
|
for row in pi.items:
|
||||||
|
row.rate = 50
|
||||||
|
|
||||||
|
pi.save()
|
||||||
|
pi.submit()
|
||||||
|
|
||||||
|
stock_value_difference = frappe.db.get_value(
|
||||||
|
"Stock Ledger Entry",
|
||||||
|
{"voucher_type": "Purchase Receipt", "voucher_no": pr.name},
|
||||||
|
"stock_value_difference",
|
||||||
|
)
|
||||||
|
self.assertEqual(stock_value_difference, 100)
|
||||||
|
|
||||||
|
frappe.db.set_single_value("Buying Settings", "maintain_same_rate", 1)
|
||||||
|
|
||||||
def test_item_less_defaults(self):
|
def test_item_less_defaults(self):
|
||||||
|
|
||||||
pi = frappe.new_doc("Purchase Invoice")
|
pi = frappe.new_doc("Purchase Invoice")
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
"pr_required",
|
"pr_required",
|
||||||
"column_break_12",
|
"column_break_12",
|
||||||
"maintain_same_rate",
|
"maintain_same_rate",
|
||||||
|
"set_landed_cost_based_on_purchase_invoice_rate",
|
||||||
"allow_multiple_items",
|
"allow_multiple_items",
|
||||||
"bill_for_rejected_quantity_in_purchase_invoice",
|
"bill_for_rejected_quantity_in_purchase_invoice",
|
||||||
"disable_last_purchase_rate",
|
"disable_last_purchase_rate",
|
||||||
@ -147,6 +148,14 @@
|
|||||||
"fieldname": "show_pay_button",
|
"fieldname": "show_pay_button",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Show Pay Button in Purchase Order Portal"
|
"label": "Show Pay Button in Purchase Order Portal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"depends_on": "eval: !doc.maintain_same_rate",
|
||||||
|
"description": "Users can enable the checkbox If they want to adjust the incoming rate (set using purchase receipt) based on the purchase invoice rate.",
|
||||||
|
"fieldname": "set_landed_cost_based_on_purchase_invoice_rate",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Set Landed Cost Based on Purchase Invoice Rate"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-cog",
|
"icon": "fa fa-cog",
|
||||||
@ -154,7 +163,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-02-15 14:42:10.200679",
|
"modified": "2023-02-28 15:41:32.686805",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Buying Settings",
|
"name": "Buying Settings",
|
||||||
|
@ -21,3 +21,10 @@ class BuyingSettings(Document):
|
|||||||
self.get("supp_master_name") == "Naming Series",
|
self.get("supp_master_name") == "Naming Series",
|
||||||
hide_name_field=False,
|
hide_name_field=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def before_save(self):
|
||||||
|
self.check_maintain_same_rate()
|
||||||
|
|
||||||
|
def check_maintain_same_rate(self):
|
||||||
|
if self.maintain_same_rate:
|
||||||
|
self.set_landed_cost_based_on_purchase_invoice_rate = 0
|
||||||
|
@ -265,7 +265,10 @@ class BuyingController(SubcontractingController):
|
|||||||
) / qty_in_stock_uom
|
) / qty_in_stock_uom
|
||||||
else:
|
else:
|
||||||
item.valuation_rate = (
|
item.valuation_rate = (
|
||||||
item.base_net_amount + item.item_tax_amount + flt(item.landed_cost_voucher_amount)
|
item.base_net_amount
|
||||||
|
+ item.item_tax_amount
|
||||||
|
+ flt(item.landed_cost_voucher_amount)
|
||||||
|
+ flt(item.get("rate_difference_with_purchase_invoice"))
|
||||||
) / qty_in_stock_uom
|
) / qty_in_stock_uom
|
||||||
else:
|
else:
|
||||||
item.valuation_rate = 0.0
|
item.valuation_rate = 0.0
|
||||||
|
@ -293,6 +293,7 @@ class PurchaseReceipt(BuyingController):
|
|||||||
get_purchase_document_details,
|
get_purchase_document_details,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
stock_rbnb = None
|
||||||
if erpnext.is_perpetual_inventory_enabled(self.company):
|
if erpnext.is_perpetual_inventory_enabled(self.company):
|
||||||
stock_rbnb = self.get_company_default("stock_received_but_not_billed")
|
stock_rbnb = self.get_company_default("stock_received_but_not_billed")
|
||||||
landed_cost_entries = get_item_account_wise_additional_cost(self.name)
|
landed_cost_entries = get_item_account_wise_additional_cost(self.name)
|
||||||
@ -450,6 +451,21 @@ class PurchaseReceipt(BuyingController):
|
|||||||
item=d,
|
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,
|
||||||
|
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,
|
||||||
|
)
|
||||||
|
|
||||||
# sub-contracting warehouse
|
# sub-contracting warehouse
|
||||||
if flt(d.rm_supp_cost) and warehouse_account.get(self.supplier_warehouse):
|
if flt(d.rm_supp_cost) and warehouse_account.get(self.supplier_warehouse):
|
||||||
self.add_gl_entry(
|
self.add_gl_entry(
|
||||||
@ -470,6 +486,7 @@ class PurchaseReceipt(BuyingController):
|
|||||||
+ flt(d.landed_cost_voucher_amount)
|
+ flt(d.landed_cost_voucher_amount)
|
||||||
+ flt(d.rm_supp_cost)
|
+ flt(d.rm_supp_cost)
|
||||||
+ flt(d.item_tax_amount)
|
+ flt(d.item_tax_amount)
|
||||||
|
+ flt(d.rate_difference_with_purchase_invoice)
|
||||||
)
|
)
|
||||||
|
|
||||||
divisional_loss = flt(
|
divisional_loss = flt(
|
||||||
@ -765,7 +782,7 @@ class PurchaseReceipt(BuyingController):
|
|||||||
updated_pr += update_billed_amount_based_on_po(po_details, update_modified)
|
updated_pr += update_billed_amount_based_on_po(po_details, update_modified)
|
||||||
|
|
||||||
for pr in set(updated_pr):
|
for pr in set(updated_pr):
|
||||||
pr_doc = self if (pr == self.name) else frappe.get_cached_doc("Purchase Receipt", pr)
|
pr_doc = self if (pr == self.name) else frappe.get_doc("Purchase Receipt", pr)
|
||||||
update_billing_percentage(pr_doc, update_modified=update_modified)
|
update_billing_percentage(pr_doc, update_modified=update_modified)
|
||||||
|
|
||||||
self.load_from_db()
|
self.load_from_db()
|
||||||
@ -881,7 +898,7 @@ def get_billed_amount_against_po(po_items):
|
|||||||
return {d.po_detail: flt(d.billed_amt) for d in query}
|
return {d.po_detail: flt(d.billed_amt) for d in query}
|
||||||
|
|
||||||
|
|
||||||
def update_billing_percentage(pr_doc, update_modified=True):
|
def update_billing_percentage(pr_doc, update_modified=True, adjust_incoming_rate=False):
|
||||||
# Reload as billed amount was set in db directly
|
# Reload as billed amount was set in db directly
|
||||||
pr_doc.load_from_db()
|
pr_doc.load_from_db()
|
||||||
|
|
||||||
@ -897,6 +914,12 @@ def update_billing_percentage(pr_doc, update_modified=True):
|
|||||||
|
|
||||||
total_amount += total_billable_amount
|
total_amount += total_billable_amount
|
||||||
total_billed_amount += flt(item.billed_amt)
|
total_billed_amount += flt(item.billed_amt)
|
||||||
|
if adjust_incoming_rate:
|
||||||
|
adjusted_amt = 0.0
|
||||||
|
if item.billed_amt and item.amount:
|
||||||
|
adjusted_amt = flt(item.billed_amt) - flt(item.amount)
|
||||||
|
|
||||||
|
item.db_set("rate_difference_with_purchase_invoice", adjusted_amt, update_modified=False)
|
||||||
|
|
||||||
percent_billed = round(100 * (total_billed_amount / (total_amount or 1)), 6)
|
percent_billed = round(100 * (total_billed_amount / (total_amount or 1)), 6)
|
||||||
pr_doc.db_set("per_billed", percent_billed)
|
pr_doc.db_set("per_billed", percent_billed)
|
||||||
@ -906,6 +929,26 @@ def update_billing_percentage(pr_doc, update_modified=True):
|
|||||||
pr_doc.set_status(update=True)
|
pr_doc.set_status(update=True)
|
||||||
pr_doc.notify_update()
|
pr_doc.notify_update()
|
||||||
|
|
||||||
|
if adjust_incoming_rate:
|
||||||
|
adjust_incoming_rate_for_pr(pr_doc)
|
||||||
|
|
||||||
|
|
||||||
|
def adjust_incoming_rate_for_pr(doc):
|
||||||
|
doc.update_valuation_rate(reset_outgoing_rate=False)
|
||||||
|
|
||||||
|
for item in doc.get("items"):
|
||||||
|
item.db_update()
|
||||||
|
|
||||||
|
doc.docstatus = 2
|
||||||
|
doc.update_stock_ledger(allow_negative_stock=True, via_landed_cost_voucher=True)
|
||||||
|
doc.make_gl_entries_on_cancel()
|
||||||
|
|
||||||
|
# update stock & gl entries for submit state of PR
|
||||||
|
doc.docstatus = 1
|
||||||
|
doc.update_stock_ledger(allow_negative_stock=True, via_landed_cost_voucher=True)
|
||||||
|
doc.make_gl_entries()
|
||||||
|
doc.repost_future_sle_and_gle()
|
||||||
|
|
||||||
|
|
||||||
def get_item_wise_returned_qty(pr_doc):
|
def get_item_wise_returned_qty(pr_doc):
|
||||||
items = [d.name for d in pr_doc.items]
|
items = [d.name for d in pr_doc.items]
|
||||||
|
@ -69,6 +69,7 @@
|
|||||||
"item_tax_amount",
|
"item_tax_amount",
|
||||||
"rm_supp_cost",
|
"rm_supp_cost",
|
||||||
"landed_cost_voucher_amount",
|
"landed_cost_voucher_amount",
|
||||||
|
"rate_difference_with_purchase_invoice",
|
||||||
"billed_amt",
|
"billed_amt",
|
||||||
"warehouse_and_reference",
|
"warehouse_and_reference",
|
||||||
"warehouse",
|
"warehouse",
|
||||||
@ -1007,12 +1008,20 @@
|
|||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Has Item Scanned",
|
"label": "Has Item Scanned",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "rate_difference_with_purchase_invoice",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"label": "Rate Difference with Purchase Invoice",
|
||||||
|
"no_copy": 1,
|
||||||
|
"print_hide": 1,
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-01-18 15:48:58.114923",
|
"modified": "2023-02-28 15:43:04.470104",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Purchase Receipt Item",
|
"name": "Purchase Receipt Item",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user