fix: reposting not working for internal transferred purchase receipt
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index 51d914d..f85c478 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -362,6 +362,12 @@
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_supplier and d.valuation_rate:
+ outgoing_amount = d.valuation_rate * d.stock_qty
+ credit_amount = outgoing_amount
+
if credit_amount:
account = warehouse_account[d.from_warehouse]["account"] if d.from_warehouse else stock_rbnb
@@ -369,7 +375,7 @@
gl_entries=gl_entries,
account=account,
cost_center=d.cost_center,
- debit=-1 * flt(d.base_net_amount, d.precision("base_net_amount")),
+ debit=-1 * flt(outgoing_amount, d.precision("base_net_amount")),
credit=0.0,
remarks=remarks,
against_account=warehouse_account_name,
@@ -456,7 +462,7 @@
# divisional loss adjustment
valuation_amount_as_per_doc = (
- flt(d.base_net_amount, d.precision("base_net_amount"))
+ flt(outgoing_amount, d.precision("base_net_amount"))
+ flt(d.landed_cost_voucher_amount)
+ flt(d.rm_supp_cost)
+ flt(d.item_tax_amount)
diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
index d0d115d..b77c3a5 100644
--- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
@@ -5,6 +5,7 @@
import frappe
from frappe.tests.utils import FrappeTestCase, change_settings
from frappe.utils import add_days, cint, cstr, flt, today
+from pypika import functions as fn
import erpnext
from erpnext.accounts.doctype.account.test_account import get_inventory_account
@@ -1156,6 +1157,125 @@
if gle.account == account:
self.assertEqual(gle.credit, 50)
+ def test_backdated_transaction_for_internal_transfer(self):
+ from erpnext.stock.doctype.delivery_note.delivery_note import make_inter_company_purchase_receipt
+ from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
+
+ prepare_data_for_internal_transfer()
+ customer = "_Test Internal Customer 2"
+ company = "_Test Company with perpetual inventory"
+
+ from_warehouse = create_warehouse("_Test Internal From Warehouse New", company=company)
+ to_warehouse = create_warehouse("_Test Internal To Warehouse New", company=company)
+ item_doc = create_item("Test Internal Transfer Item")
+
+ target_warehouse = create_warehouse("_Test Internal GIT Warehouse New", company=company)
+
+ make_purchase_receipt(
+ item_code=item_doc.name,
+ company=company,
+ posting_date=add_days(today(), -1),
+ warehouse=from_warehouse,
+ qty=1,
+ rate=100,
+ )
+
+ dn1 = create_delivery_note(
+ item_code=item_doc.name,
+ company=company,
+ customer=customer,
+ cost_center="Main - TCP1",
+ expense_account="Cost of Goods Sold - TCP1",
+ qty=1,
+ rate=500,
+ warehouse=from_warehouse,
+ target_warehouse=target_warehouse,
+ )
+
+ self.assertEqual(dn1.items[0].rate, 100)
+
+ pr1 = make_inter_company_purchase_receipt(dn1.name)
+ pr1.items[0].warehouse = to_warehouse
+ self.assertEqual(pr1.items[0].rate, 100)
+ pr1.submit()
+
+ # Backdated purchase receipt entry, the valuation rate should be updated for DN1 and PR1
+ make_purchase_receipt(
+ item_code=item_doc.name,
+ company=company,
+ posting_date=add_days(today(), -2),
+ warehouse=from_warehouse,
+ qty=1,
+ rate=200,
+ )
+
+ dn_value = frappe.db.get_value(
+ "Stock Ledger Entry",
+ {"voucher_type": "Delivery Note", "voucher_no": dn1.name, "warehouse": target_warehouse},
+ "stock_value_difference",
+ )
+
+ self.assertEqual(abs(dn_value), 200.00)
+
+ pr_value = frappe.db.get_value(
+ "Stock Ledger Entry",
+ {"voucher_type": "Purchase Receipt", "voucher_no": pr1.name, "warehouse": to_warehouse},
+ "stock_value_difference",
+ )
+
+ self.assertEqual(abs(pr_value), 200.00)
+ pr1.load_from_db()
+
+ self.assertEqual(pr1.items[0].valuation_rate, 200)
+ self.assertEqual(pr1.items[0].rate, 100)
+
+ Gl = frappe.qb.DocType("GL Entry")
+
+ query = (
+ frappe.qb.from_(Gl)
+ .select(
+ (fn.Sum(Gl.debit) - fn.Sum(Gl.credit)).as_("value"),
+ )
+ .where((Gl.voucher_type == pr1.doctype) & (Gl.voucher_no == pr1.name))
+ ).run(as_dict=True)
+
+ self.assertEqual(query[0].value, 0)
+
+
+def prepare_data_for_internal_transfer():
+ from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier
+ from erpnext.selling.doctype.customer.test_customer import create_internal_customer
+
+ company = "_Test Company with perpetual inventory"
+
+ create_internal_customer(
+ "_Test Internal Customer 2",
+ company,
+ company,
+ )
+
+ create_internal_supplier(
+ "_Test Internal Supplier 2",
+ company,
+ company,
+ )
+
+ if not frappe.db.get_value("Company", company, "unrealized_profit_loss_account"):
+ account = "Unrealized Profit and Loss - TCP1"
+ if not frappe.db.exists("Account", account):
+ frappe.get_doc(
+ {
+ "doctype": "Account",
+ "account_name": "Unrealized Profit and Loss",
+ "parent_account": "Direct Income - TCP1",
+ "company": company,
+ "is_group": 0,
+ "account_type": "Income Account",
+ }
+ ).insert()
+
+ frappe.db.set_value("Company", company, "unrealized_profit_loss_account", account)
+
def get_sl_entries(voucher_type, voucher_no):
return frappe.db.sql(
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index 3524a47..5030964 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -649,21 +649,25 @@
elif (
sle.voucher_type in ["Purchase Receipt", "Purchase Invoice"]
- and sle.actual_qty > 0
+ and sle.voucher_detail_no
and frappe.get_cached_value(sle.voucher_type, sle.voucher_no, "is_internal_supplier")
):
- sle_details = frappe.db.get_value(
- "Stock Ledger Entry",
- {
- "voucher_type": sle.voucher_type,
- "voucher_no": sle.voucher_no,
- "dependant_sle_voucher_detail_no": sle.voucher_detail_no,
- },
- ["stock_value_difference", "actual_qty"],
- as_dict=1,
+ field = (
+ "delivery_note_item" if sle.voucher_type == "Purchase Receipt" else "sales_invoice_item"
+ )
+ doctype = (
+ "Delivery Note Item" if sle.voucher_type == "Purchase Receipt" else "Sales Invoice Item"
+ )
+ refernce_name = frappe.get_cached_value(
+ sle.voucher_type + " Item", sle.voucher_detail_no, field
)
- rate = abs(sle_details.stock_value_difference / sle.actual_qty)
+ if refernce_name:
+ rate = frappe.get_cached_value(
+ doctype,
+ refernce_name,
+ "incoming_rate",
+ )
else:
if sle.voucher_type in ("Purchase Receipt", "Purchase Invoice"):
rate_field = "valuation_rate"
@@ -745,7 +749,12 @@
def update_rate_on_purchase_receipt(self, sle, outgoing_rate):
if frappe.db.exists(sle.voucher_type + " Item", sle.voucher_detail_no):
frappe.db.set_value(
- sle.voucher_type + " Item", sle.voucher_detail_no, "base_net_rate", outgoing_rate
+ sle.voucher_type + " Item",
+ sle.voucher_detail_no,
+ {
+ "base_net_rate": outgoing_rate,
+ "valuation_rate": outgoing_rate,
+ },
)
else:
frappe.db.set_value(