Merge branch 'develop' into fix/github-issue/32559
This commit is contained in:
commit
7dfd741ced
@ -705,6 +705,10 @@ class PurchaseInvoice(BuyingController):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
credit_amount = item.base_net_amount
|
||||||
|
if self.is_internal_supplier and item.valuation_rate:
|
||||||
|
credit_amount = flt(item.valuation_rate * item.stock_qty)
|
||||||
|
|
||||||
# Intentionally passed negative debit amount to avoid incorrect GL Entry validation
|
# Intentionally passed negative debit amount to avoid incorrect GL Entry validation
|
||||||
gl_entries.append(
|
gl_entries.append(
|
||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
@ -714,7 +718,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
"cost_center": item.cost_center,
|
"cost_center": item.cost_center,
|
||||||
"project": item.project or self.project,
|
"project": item.project or self.project,
|
||||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||||
"debit": -1 * flt(item.base_net_amount, item.precision("base_net_amount")),
|
"debit": -1 * flt(credit_amount, item.precision("base_net_amount")),
|
||||||
},
|
},
|
||||||
warehouse_account[item.from_warehouse]["account_currency"],
|
warehouse_account[item.from_warehouse]["account_currency"],
|
||||||
item=item,
|
item=item,
|
||||||
|
|||||||
@ -711,6 +711,7 @@
|
|||||||
"label": "Valuation Rate",
|
"label": "Valuation Rate",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "Company:company:default_currency",
|
"options": "Company:company:default_currency",
|
||||||
|
"precision": "6",
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
@ -870,7 +871,7 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2022-09-27 10:54:23.980713",
|
"modified": "2022-10-12 03:37:29.032732",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Purchase Invoice Item",
|
"name": "Purchase Invoice Item",
|
||||||
|
|||||||
@ -32,10 +32,20 @@ from erpnext.stock.doctype.stock_entry.test_stock_entry import (
|
|||||||
get_qty_after_transaction,
|
get_qty_after_transaction,
|
||||||
make_stock_entry,
|
make_stock_entry,
|
||||||
)
|
)
|
||||||
from erpnext.stock.utils import get_incoming_rate
|
from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import (
|
||||||
|
create_stock_reconciliation,
|
||||||
|
)
|
||||||
|
from erpnext.stock.utils import get_incoming_rate, get_stock_balance
|
||||||
|
|
||||||
|
|
||||||
class TestSalesInvoice(unittest.TestCase):
|
class TestSalesInvoice(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
from erpnext.stock.doctype.stock_ledger_entry.test_stock_ledger_entry import create_items
|
||||||
|
|
||||||
|
create_items(["_Test Internal Transfer Item"], uoms=[{"uom": "Box", "conversion_factor": 10}])
|
||||||
|
create_internal_parties()
|
||||||
|
setup_accounts()
|
||||||
|
|
||||||
def make(self):
|
def make(self):
|
||||||
w = frappe.copy_doc(test_records[0])
|
w = frappe.copy_doc(test_records[0])
|
||||||
w.is_pos = 0
|
w.is_pos = 0
|
||||||
@ -1705,7 +1715,7 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
si.save()
|
si.save()
|
||||||
self.assertEqual(si.get("items")[0].rate, flt((price_list_rate * 25) / 100 + price_list_rate))
|
self.assertEqual(si.get("items")[0].rate, flt((price_list_rate * 25) / 100 + price_list_rate))
|
||||||
|
|
||||||
def test_outstanding_amount_after_advance_jv_cancelation(self):
|
def test_outstanding_amount_after_advance_jv_cancellation(self):
|
||||||
from erpnext.accounts.doctype.journal_entry.test_journal_entry import (
|
from erpnext.accounts.doctype.journal_entry.test_journal_entry import (
|
||||||
test_records as jv_test_records,
|
test_records as jv_test_records,
|
||||||
)
|
)
|
||||||
@ -1749,7 +1759,7 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
flt(si.rounded_total + si.total_advance, si.precision("outstanding_amount")),
|
flt(si.rounded_total + si.total_advance, si.precision("outstanding_amount")),
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_outstanding_amount_after_advance_payment_entry_cancelation(self):
|
def test_outstanding_amount_after_advance_payment_entry_cancellation(self):
|
||||||
pe = frappe.get_doc(
|
pe = frappe.get_doc(
|
||||||
{
|
{
|
||||||
"doctype": "Payment Entry",
|
"doctype": "Payment Entry",
|
||||||
@ -2367,29 +2377,6 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
acc_settings.save()
|
acc_settings.save()
|
||||||
|
|
||||||
def test_inter_company_transaction(self):
|
def test_inter_company_transaction(self):
|
||||||
from erpnext.selling.doctype.customer.test_customer import create_internal_customer
|
|
||||||
|
|
||||||
create_internal_customer(
|
|
||||||
customer_name="_Test Internal Customer",
|
|
||||||
represents_company="_Test Company 1",
|
|
||||||
allowed_to_interact_with="Wind Power LLC",
|
|
||||||
)
|
|
||||||
|
|
||||||
if not frappe.db.exists("Supplier", "_Test Internal Supplier"):
|
|
||||||
supplier = frappe.get_doc(
|
|
||||||
{
|
|
||||||
"supplier_group": "_Test Supplier Group",
|
|
||||||
"supplier_name": "_Test Internal Supplier",
|
|
||||||
"doctype": "Supplier",
|
|
||||||
"is_internal_supplier": 1,
|
|
||||||
"represents_company": "Wind Power LLC",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
supplier.append("companies", {"company": "_Test Company 1"})
|
|
||||||
|
|
||||||
supplier.insert()
|
|
||||||
|
|
||||||
si = create_sales_invoice(
|
si = create_sales_invoice(
|
||||||
company="Wind Power LLC",
|
company="Wind Power LLC",
|
||||||
customer="_Test Internal Customer",
|
customer="_Test Internal Customer",
|
||||||
@ -2440,38 +2427,6 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
"Expenses Included In Valuation - _TC1",
|
"Expenses Included In Valuation - _TC1",
|
||||||
)
|
)
|
||||||
|
|
||||||
if not frappe.db.exists("Customer", "_Test Internal Customer"):
|
|
||||||
customer = frappe.get_doc(
|
|
||||||
{
|
|
||||||
"customer_group": "_Test Customer Group",
|
|
||||||
"customer_name": "_Test Internal Customer",
|
|
||||||
"customer_type": "Individual",
|
|
||||||
"doctype": "Customer",
|
|
||||||
"territory": "_Test Territory",
|
|
||||||
"is_internal_customer": 1,
|
|
||||||
"represents_company": "_Test Company 1",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
customer.append("companies", {"company": "Wind Power LLC"})
|
|
||||||
|
|
||||||
customer.insert()
|
|
||||||
|
|
||||||
if not frappe.db.exists("Supplier", "_Test Internal Supplier"):
|
|
||||||
supplier = frappe.get_doc(
|
|
||||||
{
|
|
||||||
"supplier_group": "_Test Supplier Group",
|
|
||||||
"supplier_name": "_Test Internal Supplier",
|
|
||||||
"doctype": "Supplier",
|
|
||||||
"is_internal_supplier": 1,
|
|
||||||
"represents_company": "Wind Power LLC",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
supplier.append("companies", {"company": "_Test Company 1"})
|
|
||||||
|
|
||||||
supplier.insert()
|
|
||||||
|
|
||||||
# begin test
|
# begin test
|
||||||
si = create_sales_invoice(
|
si = create_sales_invoice(
|
||||||
company="Wind Power LLC",
|
company="Wind Power LLC",
|
||||||
@ -2541,34 +2496,9 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
se.cancel()
|
se.cancel()
|
||||||
|
|
||||||
def test_internal_transfer_gl_entry(self):
|
def test_internal_transfer_gl_entry(self):
|
||||||
## Create internal transfer account
|
|
||||||
from erpnext.selling.doctype.customer.test_customer import create_internal_customer
|
|
||||||
|
|
||||||
account = create_account(
|
|
||||||
account_name="Unrealized Profit",
|
|
||||||
parent_account="Current Liabilities - TCP1",
|
|
||||||
company="_Test Company with perpetual inventory",
|
|
||||||
)
|
|
||||||
|
|
||||||
frappe.db.set_value(
|
|
||||||
"Company", "_Test Company with perpetual inventory", "unrealized_profit_loss_account", account
|
|
||||||
)
|
|
||||||
|
|
||||||
customer = create_internal_customer(
|
|
||||||
"_Test Internal Customer 2",
|
|
||||||
"_Test Company with perpetual inventory",
|
|
||||||
"_Test Company with perpetual inventory",
|
|
||||||
)
|
|
||||||
|
|
||||||
create_internal_supplier(
|
|
||||||
"_Test Internal Supplier 2",
|
|
||||||
"_Test Company with perpetual inventory",
|
|
||||||
"_Test Company with perpetual inventory",
|
|
||||||
)
|
|
||||||
|
|
||||||
si = create_sales_invoice(
|
si = create_sales_invoice(
|
||||||
company="_Test Company with perpetual inventory",
|
company="_Test Company with perpetual inventory",
|
||||||
customer=customer,
|
customer="_Test Internal Customer 2",
|
||||||
debit_to="Debtors - TCP1",
|
debit_to="Debtors - TCP1",
|
||||||
warehouse="Stores - TCP1",
|
warehouse="Stores - TCP1",
|
||||||
income_account="Sales - TCP1",
|
income_account="Sales - TCP1",
|
||||||
@ -2582,7 +2512,7 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
si.update_stock = 1
|
si.update_stock = 1
|
||||||
si.items[0].target_warehouse = "Work In Progress - TCP1"
|
si.items[0].target_warehouse = "Work In Progress - TCP1"
|
||||||
|
|
||||||
# Add stock to stores for succesful stock transfer
|
# Add stock to stores for successful stock transfer
|
||||||
make_stock_entry(
|
make_stock_entry(
|
||||||
target="Stores - TCP1", company="_Test Company with perpetual inventory", qty=1, basic_rate=100
|
target="Stores - TCP1", company="_Test Company with perpetual inventory", qty=1, basic_rate=100
|
||||||
)
|
)
|
||||||
@ -2638,6 +2568,77 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
check_gl_entries(self, target_doc.name, pi_gl_entries, add_days(nowdate(), -1))
|
check_gl_entries(self, target_doc.name, pi_gl_entries, add_days(nowdate(), -1))
|
||||||
|
|
||||||
|
def test_internal_transfer_gl_precision_issues(self):
|
||||||
|
# Make a stock queue of an item with two valuations
|
||||||
|
|
||||||
|
# Remove all existing stock for this
|
||||||
|
if get_stock_balance("_Test Internal Transfer Item", "Stores - TCP1", "2022-04-10"):
|
||||||
|
create_stock_reconciliation(
|
||||||
|
item_code="_Test Internal Transfer Item",
|
||||||
|
warehouse="Stores - TCP1",
|
||||||
|
qty=0,
|
||||||
|
rate=0,
|
||||||
|
company="_Test Company with perpetual inventory",
|
||||||
|
expense_account="Stock Adjustment - TCP1"
|
||||||
|
if frappe.get_all("Stock Ledger Entry")
|
||||||
|
else "Temporary Opening - TCP1",
|
||||||
|
posting_date="2020-04-10",
|
||||||
|
posting_time="14:00",
|
||||||
|
)
|
||||||
|
|
||||||
|
make_stock_entry(
|
||||||
|
item_code="_Test Internal Transfer Item",
|
||||||
|
target="Stores - TCP1",
|
||||||
|
qty=9000000,
|
||||||
|
basic_rate=52.0,
|
||||||
|
posting_date="2020-04-10",
|
||||||
|
posting_time="14:00",
|
||||||
|
)
|
||||||
|
make_stock_entry(
|
||||||
|
item_code="_Test Internal Transfer Item",
|
||||||
|
target="Stores - TCP1",
|
||||||
|
qty=60000000,
|
||||||
|
basic_rate=52.349777,
|
||||||
|
posting_date="2020-04-10",
|
||||||
|
posting_time="14:00",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Make an internal transfer Sales Invoice Stock in non stock uom to check
|
||||||
|
# for rounding errors while converting to stock uom
|
||||||
|
si = create_sales_invoice(
|
||||||
|
company="_Test Company with perpetual inventory",
|
||||||
|
customer="_Test Internal Customer 2",
|
||||||
|
item_code="_Test Internal Transfer Item",
|
||||||
|
qty=5000000,
|
||||||
|
uom="Box",
|
||||||
|
debit_to="Debtors - TCP1",
|
||||||
|
warehouse="Stores - TCP1",
|
||||||
|
income_account="Sales - TCP1",
|
||||||
|
expense_account="Cost of Goods Sold - TCP1",
|
||||||
|
cost_center="Main - TCP1",
|
||||||
|
currency="INR",
|
||||||
|
do_not_save=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check GL Entries with precision
|
||||||
|
si.update_stock = 1
|
||||||
|
si.items[0].target_warehouse = "Work In Progress - TCP1"
|
||||||
|
si.items[0].conversion_factor = 10
|
||||||
|
si.save()
|
||||||
|
si.submit()
|
||||||
|
|
||||||
|
# Check if adjustment entry is created
|
||||||
|
self.assertTrue(
|
||||||
|
frappe.db.exists(
|
||||||
|
"GL Entry",
|
||||||
|
{
|
||||||
|
"voucher_type": "Sales Invoice",
|
||||||
|
"voucher_no": si.name,
|
||||||
|
"remarks": "Rounding gain/loss Entry for Stock Transfer",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def test_item_tax_net_range(self):
|
def test_item_tax_net_range(self):
|
||||||
item = create_item("T Shirt")
|
item = create_item("T Shirt")
|
||||||
|
|
||||||
@ -3077,7 +3078,7 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
[deferred_account, 2022.47, 0.0, "2019-03-15"],
|
[deferred_account, 2022.47, 0.0, "2019-03-15"],
|
||||||
]
|
]
|
||||||
|
|
||||||
gl_entries = gl_entries = frappe.db.sql(
|
gl_entries = frappe.db.sql(
|
||||||
"""select account, debit, credit, posting_date
|
"""select account, debit, credit, posting_date
|
||||||
from `tabGL Entry`
|
from `tabGL Entry`
|
||||||
where voucher_type='Journal Entry' and voucher_detail_no=%s and posting_date <= %s
|
where voucher_type='Journal Entry' and voucher_detail_no=%s and posting_date <= %s
|
||||||
@ -3306,6 +3307,7 @@ def create_sales_invoice(**args):
|
|||||||
"item_name": args.item_name or "_Test Item",
|
"item_name": args.item_name or "_Test Item",
|
||||||
"description": args.description or "_Test Item",
|
"description": args.description or "_Test Item",
|
||||||
"warehouse": args.warehouse or "_Test Warehouse - _TC",
|
"warehouse": args.warehouse or "_Test Warehouse - _TC",
|
||||||
|
"target_warehouse": args.target_warehouse,
|
||||||
"qty": args.qty or 1,
|
"qty": args.qty or 1,
|
||||||
"uom": args.uom or "Nos",
|
"uom": args.uom or "Nos",
|
||||||
"stock_uom": args.uom or "Nos",
|
"stock_uom": args.uom or "Nos",
|
||||||
@ -3431,6 +3433,34 @@ def get_taxes_and_charges():
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def create_internal_parties():
|
||||||
|
from erpnext.selling.doctype.customer.test_customer import create_internal_customer
|
||||||
|
|
||||||
|
create_internal_customer(
|
||||||
|
customer_name="_Test Internal Customer",
|
||||||
|
represents_company="_Test Company 1",
|
||||||
|
allowed_to_interact_with="Wind Power LLC",
|
||||||
|
)
|
||||||
|
|
||||||
|
create_internal_customer(
|
||||||
|
customer_name="_Test Internal Customer 2",
|
||||||
|
represents_company="_Test Company with perpetual inventory",
|
||||||
|
allowed_to_interact_with="_Test Company with perpetual inventory",
|
||||||
|
)
|
||||||
|
|
||||||
|
create_internal_supplier(
|
||||||
|
supplier_name="_Test Internal Supplier",
|
||||||
|
represents_company="Wind Power LLC",
|
||||||
|
allowed_to_interact_with="_Test Company 1",
|
||||||
|
)
|
||||||
|
|
||||||
|
create_internal_supplier(
|
||||||
|
supplier_name="_Test Internal Supplier 2",
|
||||||
|
represents_company="_Test Company with perpetual inventory",
|
||||||
|
allowed_to_interact_with="_Test Company with perpetual inventory",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def create_internal_supplier(supplier_name, represents_company, allowed_to_interact_with):
|
def create_internal_supplier(supplier_name, represents_company, allowed_to_interact_with):
|
||||||
if not frappe.db.exists("Supplier", supplier_name):
|
if not frappe.db.exists("Supplier", supplier_name):
|
||||||
supplier = frappe.get_doc(
|
supplier = frappe.get_doc(
|
||||||
@ -3453,6 +3483,19 @@ def create_internal_supplier(supplier_name, represents_company, allowed_to_inter
|
|||||||
return supplier_name
|
return supplier_name
|
||||||
|
|
||||||
|
|
||||||
|
def setup_accounts():
|
||||||
|
## Create internal transfer account
|
||||||
|
account = create_account(
|
||||||
|
account_name="Unrealized Profit",
|
||||||
|
parent_account="Current Liabilities - TCP1",
|
||||||
|
company="_Test Company with perpetual inventory",
|
||||||
|
)
|
||||||
|
|
||||||
|
frappe.db.set_value(
|
||||||
|
"Company", "_Test Company with perpetual inventory", "unrealized_profit_loss_account", account
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def add_taxes(doc):
|
def add_taxes(doc):
|
||||||
doc.append(
|
doc.append(
|
||||||
"taxes",
|
"taxes",
|
||||||
|
|||||||
@ -820,6 +820,7 @@
|
|||||||
"label": "Incoming Rate (Costing)",
|
"label": "Incoming Rate (Costing)",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "Company:company:default_currency",
|
"options": "Company:company:default_currency",
|
||||||
|
"precision": "6",
|
||||||
"print_hide": 1
|
"print_hide": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -875,7 +876,7 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2022-09-06 14:17:43.394309",
|
"modified": "2022-10-10 20:57:38.340026",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Sales Invoice Item",
|
"name": "Sales Invoice Item",
|
||||||
|
|||||||
@ -442,11 +442,17 @@ class SellingController(StockController):
|
|||||||
# For internal transfers use incoming rate as the valuation rate
|
# For internal transfers use incoming rate as the valuation rate
|
||||||
if self.is_internal_transfer():
|
if self.is_internal_transfer():
|
||||||
if d.doctype == "Packed Item":
|
if d.doctype == "Packed Item":
|
||||||
incoming_rate = flt(d.incoming_rate * d.conversion_factor, d.precision("incoming_rate"))
|
incoming_rate = flt(
|
||||||
|
flt(d.incoming_rate, d.precision("incoming_rate")) * d.conversion_factor,
|
||||||
|
d.precision("incoming_rate"),
|
||||||
|
)
|
||||||
if d.incoming_rate != incoming_rate:
|
if d.incoming_rate != incoming_rate:
|
||||||
d.incoming_rate = incoming_rate
|
d.incoming_rate = incoming_rate
|
||||||
else:
|
else:
|
||||||
rate = flt(d.incoming_rate * d.conversion_factor, d.precision("rate"))
|
rate = flt(
|
||||||
|
flt(d.incoming_rate, d.precision("incoming_rate")) * d.conversion_factor,
|
||||||
|
d.precision("rate"),
|
||||||
|
)
|
||||||
if d.rate != rate:
|
if d.rate != rate:
|
||||||
d.rate = rate
|
d.rate = rate
|
||||||
frappe.msgprint(
|
frappe.msgprint(
|
||||||
|
|||||||
@ -142,13 +142,15 @@ class StockController(AccountsController):
|
|||||||
warehouse_with_no_account = []
|
warehouse_with_no_account = []
|
||||||
precision = self.get_debit_field_precision()
|
precision = self.get_debit_field_precision()
|
||||||
for item_row in voucher_details:
|
for item_row in voucher_details:
|
||||||
|
|
||||||
sle_list = sle_map.get(item_row.name)
|
sle_list = sle_map.get(item_row.name)
|
||||||
|
sle_rounding_diff = 0.0
|
||||||
if sle_list:
|
if sle_list:
|
||||||
for sle in sle_list:
|
for sle in sle_list:
|
||||||
if warehouse_account.get(sle.warehouse):
|
if warehouse_account.get(sle.warehouse):
|
||||||
# from warehouse account
|
# from warehouse account
|
||||||
|
|
||||||
|
sle_rounding_diff += flt(sle.stock_value_difference)
|
||||||
|
|
||||||
self.check_expense_account(item_row)
|
self.check_expense_account(item_row)
|
||||||
|
|
||||||
# expense account/ target_warehouse / source_warehouse
|
# expense account/ target_warehouse / source_warehouse
|
||||||
@ -191,6 +193,46 @@ class StockController(AccountsController):
|
|||||||
elif sle.warehouse not in warehouse_with_no_account:
|
elif sle.warehouse not in warehouse_with_no_account:
|
||||||
warehouse_with_no_account.append(sle.warehouse)
|
warehouse_with_no_account.append(sle.warehouse)
|
||||||
|
|
||||||
|
if abs(sle_rounding_diff) > (1.0 / (10**precision)) and self.is_internal_transfer():
|
||||||
|
warehouse_asset_account = ""
|
||||||
|
if self.get("is_internal_customer"):
|
||||||
|
warehouse_asset_account = warehouse_account[item_row.get("target_warehouse")]["account"]
|
||||||
|
elif self.get("is_internal_supplier"):
|
||||||
|
warehouse_asset_account = warehouse_account[item_row.get("warehouse")]["account"]
|
||||||
|
|
||||||
|
expense_account = frappe.db.get_value("Company", self.company, "default_expense_account")
|
||||||
|
|
||||||
|
gl_list.append(
|
||||||
|
self.get_gl_dict(
|
||||||
|
{
|
||||||
|
"account": expense_account,
|
||||||
|
"against": warehouse_asset_account,
|
||||||
|
"cost_center": item_row.cost_center,
|
||||||
|
"project": item_row.project or self.get("project"),
|
||||||
|
"remarks": _("Rounding gain/loss Entry for Stock Transfer"),
|
||||||
|
"debit": sle_rounding_diff,
|
||||||
|
"is_opening": item_row.get("is_opening") or self.get("is_opening") or "No",
|
||||||
|
},
|
||||||
|
warehouse_account[sle.warehouse]["account_currency"],
|
||||||
|
item=item_row,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
gl_list.append(
|
||||||
|
self.get_gl_dict(
|
||||||
|
{
|
||||||
|
"account": warehouse_asset_account,
|
||||||
|
"against": expense_account,
|
||||||
|
"cost_center": item_row.cost_center,
|
||||||
|
"remarks": _("Rounding gain/loss Entry for Stock Transfer"),
|
||||||
|
"credit": sle_rounding_diff,
|
||||||
|
"project": item_row.get("project") or self.get("project"),
|
||||||
|
"is_opening": item_row.get("is_opening") or self.get("is_opening") or "No",
|
||||||
|
},
|
||||||
|
item=item_row,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if warehouse_with_no_account:
|
if warehouse_with_no_account:
|
||||||
for wh in warehouse_with_no_account:
|
for wh in warehouse_with_no_account:
|
||||||
if frappe.db.get_value("Warehouse", wh, "company"):
|
if frappe.db.get_value("Warehouse", wh, "company"):
|
||||||
|
|||||||
@ -753,6 +753,7 @@
|
|||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Incoming Rate",
|
"label": "Incoming Rate",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
|
"precision": "6",
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
@ -813,7 +814,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2022-09-06 14:19:42.876357",
|
"modified": "2022-10-12 03:36:05.344847",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Delivery Note Item",
|
"name": "Delivery Note Item",
|
||||||
|
|||||||
@ -32,7 +32,7 @@ test_ignore = ["BOM"]
|
|||||||
test_dependencies = ["Warehouse", "Item Group", "Item Tax Template", "Brand", "Item Attribute"]
|
test_dependencies = ["Warehouse", "Item Group", "Item Tax Template", "Brand", "Item Attribute"]
|
||||||
|
|
||||||
|
|
||||||
def make_item(item_code=None, properties=None):
|
def make_item(item_code=None, properties=None, uoms=None):
|
||||||
if not item_code:
|
if not item_code:
|
||||||
item_code = frappe.generate_hash(length=16)
|
item_code = frappe.generate_hash(length=16)
|
||||||
|
|
||||||
@ -56,6 +56,11 @@ def make_item(item_code=None, properties=None):
|
|||||||
for item_default in [doc for doc in item.get("item_defaults") if not doc.default_warehouse]:
|
for item_default in [doc for doc in item.get("item_defaults") if not doc.default_warehouse]:
|
||||||
item_default.default_warehouse = "_Test Warehouse - _TC"
|
item_default.default_warehouse = "_Test Warehouse - _TC"
|
||||||
item_default.company = "_Test Company"
|
item_default.company = "_Test Company"
|
||||||
|
|
||||||
|
if uoms:
|
||||||
|
for uom in uoms:
|
||||||
|
item.append("uoms", uom)
|
||||||
|
|
||||||
item.insert()
|
item.insert()
|
||||||
|
|
||||||
return item
|
return item
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
# License: GNU General Public License v3. See license.txt
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.tests.utils import FrappeTestCase, change_settings
|
from frappe.tests.utils import FrappeTestCase, change_settings
|
||||||
from frappe.utils import add_days, cint, cstr, flt, today
|
from frappe.utils import add_days, cint, cstr, flt, today
|
||||||
@ -1199,6 +1198,8 @@ class TestPurchaseReceipt(FrappeTestCase):
|
|||||||
self.assertEqual(pr1.items[0].rate, 100)
|
self.assertEqual(pr1.items[0].rate, 100)
|
||||||
pr1.submit()
|
pr1.submit()
|
||||||
|
|
||||||
|
self.assertEqual(pr1.is_internal_supplier, 1)
|
||||||
|
|
||||||
# Backdated purchase receipt entry, the valuation rate should be updated for DN1 and PR1
|
# Backdated purchase receipt entry, the valuation rate should be updated for DN1 and PR1
|
||||||
make_purchase_receipt(
|
make_purchase_receipt(
|
||||||
item_code=item_doc.name,
|
item_code=item_doc.name,
|
||||||
@ -1241,6 +1242,234 @@ class TestPurchaseReceipt(FrappeTestCase):
|
|||||||
|
|
||||||
self.assertEqual(query[0].value, 0)
|
self.assertEqual(query[0].value, 0)
|
||||||
|
|
||||||
|
def test_backdated_transaction_for_internal_transfer_in_trasit_warehouse_for_purchase_receipt(
|
||||||
|
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,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Keep stock in advance and make sure that systen won't pick this stock while reposting backdated transaction
|
||||||
|
for i in range(1, 4):
|
||||||
|
make_purchase_receipt(
|
||||||
|
item_code=item_doc.name,
|
||||||
|
company=company,
|
||||||
|
posting_date=add_days(today(), -1 * i),
|
||||||
|
warehouse=target_warehouse,
|
||||||
|
qty=1,
|
||||||
|
rate=320 * i,
|
||||||
|
)
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
stk_ledger = frappe.db.get_value(
|
||||||
|
"Stock Ledger Entry",
|
||||||
|
{"voucher_type": "Purchase Receipt", "voucher_no": pr1.name, "warehouse": target_warehouse},
|
||||||
|
["stock_value_difference", "outgoing_rate"],
|
||||||
|
as_dict=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(abs(stk_ledger.stock_value_difference), 100)
|
||||||
|
self.assertEqual(stk_ledger.outgoing_rate, 100)
|
||||||
|
|
||||||
|
# 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 test_backdated_transaction_for_internal_transfer_in_trasit_warehouse_for_purchase_invoice(
|
||||||
|
self,
|
||||||
|
):
|
||||||
|
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import (
|
||||||
|
make_purchase_invoice as make_purchase_invoice_for_si,
|
||||||
|
)
|
||||||
|
from erpnext.accounts.doctype.sales_invoice.sales_invoice import (
|
||||||
|
make_inter_company_purchase_invoice,
|
||||||
|
)
|
||||||
|
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||||
|
|
||||||
|
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_invoice_for_si(
|
||||||
|
item_code=item_doc.name,
|
||||||
|
company=company,
|
||||||
|
posting_date=add_days(today(), -1),
|
||||||
|
warehouse=from_warehouse,
|
||||||
|
qty=1,
|
||||||
|
update_stock=1,
|
||||||
|
expense_account="Cost of Goods Sold - TCP1",
|
||||||
|
cost_center="Main - TCP1",
|
||||||
|
rate=100,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Keep stock in advance and make sure that systen won't pick this stock while reposting backdated transaction
|
||||||
|
for i in range(1, 4):
|
||||||
|
make_purchase_invoice_for_si(
|
||||||
|
item_code=item_doc.name,
|
||||||
|
company=company,
|
||||||
|
posting_date=add_days(today(), -1 * i),
|
||||||
|
warehouse=target_warehouse,
|
||||||
|
update_stock=1,
|
||||||
|
qty=1,
|
||||||
|
expense_account="Cost of Goods Sold - TCP1",
|
||||||
|
cost_center="Main - TCP1",
|
||||||
|
rate=320 * i,
|
||||||
|
)
|
||||||
|
|
||||||
|
si1 = create_sales_invoice(
|
||||||
|
item_code=item_doc.name,
|
||||||
|
company=company,
|
||||||
|
customer=customer,
|
||||||
|
cost_center="Main - TCP1",
|
||||||
|
income_account="Sales - TCP1",
|
||||||
|
qty=1,
|
||||||
|
rate=500,
|
||||||
|
update_stock=1,
|
||||||
|
warehouse=from_warehouse,
|
||||||
|
target_warehouse=target_warehouse,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(si1.items[0].rate, 100)
|
||||||
|
|
||||||
|
pi1 = make_inter_company_purchase_invoice(si1.name)
|
||||||
|
pi1.items[0].warehouse = to_warehouse
|
||||||
|
self.assertEqual(pi1.items[0].rate, 100)
|
||||||
|
pi1.update_stock = 1
|
||||||
|
pi1.save()
|
||||||
|
pi1.submit()
|
||||||
|
|
||||||
|
stk_ledger = frappe.db.get_value(
|
||||||
|
"Stock Ledger Entry",
|
||||||
|
{"voucher_type": pi1.doctype, "voucher_no": pi1.name, "warehouse": target_warehouse},
|
||||||
|
["stock_value_difference", "outgoing_rate"],
|
||||||
|
as_dict=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(abs(stk_ledger.stock_value_difference), 100)
|
||||||
|
self.assertEqual(stk_ledger.outgoing_rate, 100)
|
||||||
|
|
||||||
|
# Backdated purchase receipt entry, the valuation rate should be updated for si1 and pi1
|
||||||
|
make_purchase_receipt(
|
||||||
|
item_code=item_doc.name,
|
||||||
|
company=company,
|
||||||
|
posting_date=add_days(today(), -2),
|
||||||
|
warehouse=from_warehouse,
|
||||||
|
qty=1,
|
||||||
|
rate=200,
|
||||||
|
)
|
||||||
|
|
||||||
|
si_value = frappe.db.get_value(
|
||||||
|
"Stock Ledger Entry",
|
||||||
|
{"voucher_type": si1.doctype, "voucher_no": si1.name, "warehouse": target_warehouse},
|
||||||
|
"stock_value_difference",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(abs(si_value), 200.00)
|
||||||
|
|
||||||
|
pi_value = frappe.db.get_value(
|
||||||
|
"Stock Ledger Entry",
|
||||||
|
{"voucher_type": pi1.doctype, "voucher_no": pi1.name, "warehouse": to_warehouse},
|
||||||
|
"stock_value_difference",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(abs(pi_value), 200.00)
|
||||||
|
pi1.load_from_db()
|
||||||
|
|
||||||
|
self.assertEqual(pi1.items[0].valuation_rate, 200)
|
||||||
|
self.assertEqual(pi1.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 == pi1.doctype) & (Gl.voucher_no == pi1.name))
|
||||||
|
).run(as_dict=True)
|
||||||
|
|
||||||
|
self.assertEqual(query[0].value, 0)
|
||||||
|
|
||||||
def test_batch_expiry_for_purchase_receipt(self):
|
def test_batch_expiry_for_purchase_receipt(self):
|
||||||
from erpnext.controllers.sales_and_purchase_return import make_return_doc
|
from erpnext.controllers.sales_and_purchase_return import make_return_doc
|
||||||
|
|
||||||
|
|||||||
@ -744,6 +744,7 @@
|
|||||||
"oldfieldname": "valuation_rate",
|
"oldfieldname": "valuation_rate",
|
||||||
"oldfieldtype": "Currency",
|
"oldfieldtype": "Currency",
|
||||||
"options": "Company:company:default_currency",
|
"options": "Company:company:default_currency",
|
||||||
|
"precision": "6",
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"print_width": "80px",
|
"print_width": "80px",
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
@ -999,7 +1000,7 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2022-07-28 19:27:54.880781",
|
"modified": "2022-10-12 03:37:59.516609",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Purchase Receipt Item",
|
"name": "Purchase Receipt Item",
|
||||||
|
|||||||
@ -1323,13 +1323,15 @@ def create_product_bundle_item(new_item_code, packed_items):
|
|||||||
item.save()
|
item.save()
|
||||||
|
|
||||||
|
|
||||||
def create_items():
|
def create_items(items=None, uoms=None):
|
||||||
|
if not items:
|
||||||
items = [
|
items = [
|
||||||
"_Test Item for Reposting",
|
"_Test Item for Reposting",
|
||||||
"_Test Finished Item for Reposting",
|
"_Test Finished Item for Reposting",
|
||||||
"_Test Subcontracted Item for Reposting",
|
"_Test Subcontracted Item for Reposting",
|
||||||
"_Test Bundled Item for Reposting",
|
"_Test Bundled Item for Reposting",
|
||||||
]
|
]
|
||||||
|
|
||||||
for d in items:
|
for d in items:
|
||||||
properties = {"valuation_method": "FIFO"}
|
properties = {"valuation_method": "FIFO"}
|
||||||
if d == "_Test Bundled Item for Reposting":
|
if d == "_Test Bundled Item for Reposting":
|
||||||
@ -1337,7 +1339,7 @@ def create_items():
|
|||||||
elif d == "_Test Subcontracted Item for Reposting":
|
elif d == "_Test Subcontracted Item for Reposting":
|
||||||
properties.update({"is_sub_contracted_item": 1})
|
properties.update({"is_sub_contracted_item": 1})
|
||||||
|
|
||||||
make_item(d, properties=properties)
|
make_item(d, properties=properties, uoms=uoms)
|
||||||
|
|
||||||
return items
|
return items
|
||||||
|
|
||||||
|
|||||||
@ -132,7 +132,9 @@ class StockReconciliation(StockController):
|
|||||||
key.append(row.get(field))
|
key.append(row.get(field))
|
||||||
|
|
||||||
if key in item_warehouse_combinations:
|
if key in item_warehouse_combinations:
|
||||||
self.validation_messages.append(_get_msg(row_num, _("Duplicate entry")))
|
self.validation_messages.append(
|
||||||
|
_get_msg(row_num, _("Same item and warehouse combination already entered."))
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
item_warehouse_combinations.append(key)
|
item_warehouse_combinations.append(key)
|
||||||
|
|
||||||
|
|||||||
@ -542,6 +542,14 @@ class update_entries_after(object):
|
|||||||
if not self.args.get("sle_id"):
|
if not self.args.get("sle_id"):
|
||||||
self.get_dynamic_incoming_outgoing_rate(sle)
|
self.get_dynamic_incoming_outgoing_rate(sle)
|
||||||
|
|
||||||
|
if (
|
||||||
|
sle.voucher_type in ["Purchase Receipt", "Purchase Invoice"]
|
||||||
|
and sle.voucher_detail_no
|
||||||
|
and sle.actual_qty < 0
|
||||||
|
and frappe.get_cached_value(sle.voucher_type, sle.voucher_no, "is_internal_supplier")
|
||||||
|
):
|
||||||
|
sle.outgoing_rate = get_incoming_rate_for_inter_company_transfer(sle)
|
||||||
|
|
||||||
if get_serial_nos(sle.serial_no):
|
if get_serial_nos(sle.serial_no):
|
||||||
self.get_serialized_values(sle)
|
self.get_serialized_values(sle)
|
||||||
self.wh_data.qty_after_transaction += flt(sle.actual_qty)
|
self.wh_data.qty_after_transaction += flt(sle.actual_qty)
|
||||||
@ -589,6 +597,7 @@ class update_entries_after(object):
|
|||||||
sle.stock_queue = json.dumps(self.wh_data.stock_queue)
|
sle.stock_queue = json.dumps(self.wh_data.stock_queue)
|
||||||
sle.stock_value_difference = stock_value_difference
|
sle.stock_value_difference = stock_value_difference
|
||||||
sle.doctype = "Stock Ledger Entry"
|
sle.doctype = "Stock Ledger Entry"
|
||||||
|
|
||||||
frappe.get_doc(sle).db_update()
|
frappe.get_doc(sle).db_update()
|
||||||
|
|
||||||
if not self.args.get("sle_id"):
|
if not self.args.get("sle_id"):
|
||||||
@ -652,22 +661,7 @@ class update_entries_after(object):
|
|||||||
and sle.voucher_detail_no
|
and sle.voucher_detail_no
|
||||||
and frappe.get_cached_value(sle.voucher_type, sle.voucher_no, "is_internal_supplier")
|
and frappe.get_cached_value(sle.voucher_type, sle.voucher_no, "is_internal_supplier")
|
||||||
):
|
):
|
||||||
field = (
|
rate = get_incoming_rate_for_inter_company_transfer(sle)
|
||||||
"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
|
|
||||||
)
|
|
||||||
|
|
||||||
if refernce_name:
|
|
||||||
rate = frappe.get_cached_value(
|
|
||||||
doctype,
|
|
||||||
refernce_name,
|
|
||||||
"incoming_rate",
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
if sle.voucher_type in ("Purchase Receipt", "Purchase Invoice"):
|
if sle.voucher_type in ("Purchase Receipt", "Purchase Invoice"):
|
||||||
rate_field = "valuation_rate"
|
rate_field = "valuation_rate"
|
||||||
@ -748,13 +742,11 @@ class update_entries_after(object):
|
|||||||
|
|
||||||
def update_rate_on_purchase_receipt(self, sle, outgoing_rate):
|
def update_rate_on_purchase_receipt(self, sle, outgoing_rate):
|
||||||
if frappe.db.exists(sle.voucher_type + " Item", sle.voucher_detail_no):
|
if frappe.db.exists(sle.voucher_type + " Item", sle.voucher_detail_no):
|
||||||
|
if sle.voucher_type in ["Purchase Receipt", "Purchase Invoice"] and frappe.get_cached_value(
|
||||||
|
sle.voucher_type, sle.voucher_no, "is_internal_supplier"
|
||||||
|
):
|
||||||
frappe.db.set_value(
|
frappe.db.set_value(
|
||||||
sle.voucher_type + " Item",
|
f"{sle.voucher_type} Item", sle.voucher_detail_no, "valuation_rate", sle.outgoing_rate
|
||||||
sle.voucher_detail_no,
|
|
||||||
{
|
|
||||||
"base_net_rate": outgoing_rate,
|
|
||||||
"valuation_rate": outgoing_rate,
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
frappe.db.set_value(
|
frappe.db.set_value(
|
||||||
@ -1546,3 +1538,25 @@ def is_negative_stock_allowed(*, item_code: Optional[str] = None) -> bool:
|
|||||||
if item_code and cint(frappe.db.get_value("Item", item_code, "allow_negative_stock", cache=True)):
|
if item_code and cint(frappe.db.get_value("Item", item_code, "allow_negative_stock", cache=True)):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def get_incoming_rate_for_inter_company_transfer(sle) -> float:
|
||||||
|
"""
|
||||||
|
For inter company transfer, incoming rate is the average of the outgoing rate
|
||||||
|
"""
|
||||||
|
rate = 0.0
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
reference_name = frappe.get_cached_value(sle.voucher_type + " Item", sle.voucher_detail_no, field)
|
||||||
|
|
||||||
|
if reference_name:
|
||||||
|
rate = frappe.get_cached_value(
|
||||||
|
doctype,
|
||||||
|
reference_name,
|
||||||
|
"incoming_rate",
|
||||||
|
)
|
||||||
|
|
||||||
|
return rate
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user