fix: Item valuation for internal stocktransfers
This commit is contained in:
@@ -508,7 +508,7 @@ class PurchaseInvoice(BuyingController):
|
||||
grand_total = self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total
|
||||
|
||||
if grand_total and not self.is_internal_transfer():
|
||||
# Didnot use base_grand_total to book rounding loss gle
|
||||
# Did not use base_grand_total to book rounding loss gle
|
||||
grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
|
||||
self.precision("grand_total"))
|
||||
gl_entries.append(
|
||||
@@ -539,8 +539,8 @@ class PurchaseInvoice(BuyingController):
|
||||
voucher_wise_stock_value = {}
|
||||
if self.update_stock:
|
||||
for d in frappe.get_all('Stock Ledger Entry',
|
||||
fields = ["voucher_detail_no", "stock_value_difference"], filters={'voucher_no': self.name}):
|
||||
voucher_wise_stock_value.setdefault(d.voucher_detail_no, d.stock_value_difference)
|
||||
fields = ["voucher_detail_no", "stock_value_difference", "warehouse"], filters={'voucher_no': self.name}):
|
||||
voucher_wise_stock_value.setdefault((d.voucher_detail_no, d.warehouse), d.stock_value_difference)
|
||||
|
||||
valuation_tax_accounts = [d.account_head for d in self.get("taxes")
|
||||
if d.category in ('Valuation', 'Total and Valuation')
|
||||
@@ -823,10 +823,10 @@ class PurchaseInvoice(BuyingController):
|
||||
|
||||
# Stock ledger value is not matching with the warehouse amount
|
||||
if (self.update_stock and voucher_wise_stock_value.get(item.name) and
|
||||
warehouse_debit_amount != flt(voucher_wise_stock_value.get(item.name), net_amt_precision)):
|
||||
warehouse_debit_amount != flt(voucher_wise_stock_value.get((item.name, item.warehouse)), net_amt_precision)):
|
||||
|
||||
cost_of_goods_sold_account = self.get_company_default("default_expense_account")
|
||||
stock_amount = flt(voucher_wise_stock_value.get(item.name), net_amt_precision)
|
||||
stock_amount = flt(voucher_wise_stock_value.get((item.name, item.warehouse)), net_amt_precision)
|
||||
stock_adjustment_amt = warehouse_debit_amount - stock_amount
|
||||
|
||||
gl_entries.append(
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"actions": [],
|
||||
"autoname": "hash",
|
||||
"creation": "2013-05-22 12:43:10",
|
||||
"doctype": "DocType",
|
||||
@@ -46,6 +47,7 @@
|
||||
"column_break_25",
|
||||
"base_net_rate",
|
||||
"base_net_amount",
|
||||
"outgoing_rate",
|
||||
"valuation_rate",
|
||||
"item_tax_amount",
|
||||
"landed_cost_voucher_amount",
|
||||
@@ -553,8 +555,8 @@
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
"label": "Brand",
|
||||
"print_hide": 1,
|
||||
"options": "Brand"
|
||||
"options": "Brand",
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"fetch_from": "item_code.item_group",
|
||||
@@ -562,9 +564,9 @@
|
||||
"fieldname": "item_group",
|
||||
"fieldtype": "Link",
|
||||
"label": "Item Group",
|
||||
"options": "Item Group",
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
"options": "Item Group"
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"description": "Tax detail table fetched from item master as a string and stored in this field.\nUsed for Taxes and Charges",
|
||||
@@ -779,11 +781,18 @@
|
||||
"no_copy": 1,
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "outgoing_rate",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Outgoing Rate",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"modified": "2020-08-20 11:48:01.398356",
|
||||
"links": [],
|
||||
"modified": "2020-12-23 17:30:57.458876",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice Item",
|
||||
|
||||
@@ -1770,59 +1770,59 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
self.assertEqual(target_doc.company, "_Test Company 1")
|
||||
self.assertEqual(target_doc.supplier, "_Test Internal Supplier")
|
||||
|
||||
# def test_internal_transfer_gl_entry(self):
|
||||
# ## Create internal transfer account
|
||||
# account = create_account(account_name="Unrealized Profit",
|
||||
# parent_account="Current Liabilities - TCP1", company="_Test Company with perpetual inventory")
|
||||
def test_internal_transfer_gl_entry(self):
|
||||
## 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)
|
||||
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")
|
||||
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")
|
||||
create_internal_supplier("_Test Internal Supplier 2", "_Test Company with perpetual inventory",
|
||||
"_Test Company with perpetual inventory")
|
||||
|
||||
# si = create_sales_invoice(
|
||||
# company = "_Test Company with perpetual inventory",
|
||||
# customer = customer,
|
||||
# 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
|
||||
# )
|
||||
si = create_sales_invoice(
|
||||
company = "_Test Company with perpetual inventory",
|
||||
customer = customer,
|
||||
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
|
||||
)
|
||||
|
||||
# si.selling_price_list = "_Test Price List Rest of the World"
|
||||
# si.update_stock = 1
|
||||
# si.items[0].target_warehouse = 'Work In Progress - TCP1'
|
||||
# add_taxes(si)
|
||||
# si.save()
|
||||
# si.submit()
|
||||
si.selling_price_list = "_Test Price List Rest of the World"
|
||||
si.update_stock = 1
|
||||
si.items[0].target_warehouse = 'Work In Progress - TCP1'
|
||||
add_taxes(si)
|
||||
si.save()
|
||||
si.submit()
|
||||
|
||||
# target_doc = make_inter_company_transaction("Sales Invoice", si.name)
|
||||
# target_doc.company = '_Test Company with perpetual inventory'
|
||||
# target_doc.items[0].warehouse = 'Finished Goods - TCP1'
|
||||
# add_taxes(target_doc)
|
||||
# target_doc.save()
|
||||
# target_doc.submit()
|
||||
target_doc = make_inter_company_transaction("Sales Invoice", si.name)
|
||||
target_doc.company = '_Test Company with perpetual inventory'
|
||||
target_doc.items[0].warehouse = 'Finished Goods - TCP1'
|
||||
add_taxes(target_doc)
|
||||
target_doc.save()
|
||||
target_doc.submit()
|
||||
|
||||
# si_gl_entries = [
|
||||
# ["_Test Account Excise Duty - TCP1", 0.0, 12.0, nowdate()],
|
||||
# ["Unrealized Profit - TCP1", 12.0, 0.0, nowdate()]
|
||||
# ]
|
||||
si_gl_entries = [
|
||||
["_Test Account Excise Duty - TCP1", 0.0, 12.0, nowdate()],
|
||||
["Unrealized Profit - TCP1", 12.0, 0.0, nowdate()]
|
||||
]
|
||||
|
||||
# check_gl_entries(self, si.name, si_gl_entries, add_days(nowdate(), -1))
|
||||
check_gl_entries(self, si.name, si_gl_entries, add_days(nowdate(), -1))
|
||||
|
||||
# pi_gl_entries = [
|
||||
# ["_Test Account Excise Duty - TCP1", 12.0 , 0.0, nowdate()],
|
||||
# ["Unrealized Profit - TCP1", 0.0, 12.0, nowdate()]
|
||||
# ]
|
||||
pi_gl_entries = [
|
||||
["_Test Account Excise Duty - TCP1", 12.0 , 0.0, nowdate()],
|
||||
["Unrealized Profit - TCP1", 0.0, 12.0, nowdate()]
|
||||
]
|
||||
|
||||
# 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_eway_bill_json(self):
|
||||
si = make_sales_invoice_for_ewaybill()
|
||||
|
||||
@@ -44,7 +44,6 @@ class BuyingController(StockController):
|
||||
self.validate_items()
|
||||
self.set_qty_as_per_stock_uom()
|
||||
self.validate_stock_or_nonstock_items()
|
||||
self.update_tax_category_for_internal_transfer()
|
||||
self.validate_warehouse()
|
||||
self.validate_from_warehouse()
|
||||
self.set_supplier_address()
|
||||
@@ -67,6 +66,8 @@ class BuyingController(StockController):
|
||||
if self.doctype in ("Purchase Receipt", "Purchase Invoice"):
|
||||
self.update_valuation_rate()
|
||||
|
||||
self.set_out_going_rate()
|
||||
|
||||
def set_missing_values(self, for_validate=False):
|
||||
super(BuyingController, self).set_missing_values(for_validate)
|
||||
|
||||
@@ -100,11 +101,6 @@ class BuyingController(StockController):
|
||||
msg = _('Tax Category has been changed to "Total" because all the Items are non-stock items')
|
||||
self.update_tax_category(msg)
|
||||
|
||||
def update_tax_category_for_internal_transfer(self):
|
||||
if self.doctype == 'Purchase Invoice' and self.is_internal_transfer():
|
||||
msg = _('Tax Category has been changed to "Total" as its an internal purchase.')
|
||||
self.update_tax_category(msg)
|
||||
|
||||
def update_tax_category(self, msg):
|
||||
tax_for_valuation = [d for d in self.get("taxes")
|
||||
if d.category in ["Valuation", "Valuation and Total"]]
|
||||
@@ -224,6 +220,32 @@ class BuyingController(StockController):
|
||||
else:
|
||||
item.valuation_rate = 0.0
|
||||
|
||||
def set_out_going_rate(self):
|
||||
if self.doctype not in ("Purchase Receipt", "Purchase Invoice"):
|
||||
return
|
||||
|
||||
items = self.get("items")
|
||||
for d in items:
|
||||
if not cint(self.get("is_return")) and d.get("target_warehouse"):
|
||||
# Get outgoing rate based on original item cost based on valuation method
|
||||
d.outgoing_rate = get_incoming_rate({
|
||||
"item_code": d.item_code,
|
||||
"warehouse": d.target_warehouse,
|
||||
"posting_date": self.posting_date,
|
||||
"posting_time": self.posting_time,
|
||||
"qty": -1 * flt(d.qty),
|
||||
"serial_no": d.serial_no,
|
||||
"company": self.company,
|
||||
"voucher_type": self.doctype,
|
||||
"voucher_no": self.name,
|
||||
"allow_zero_valuation": d.get("allow_zero_valuation")
|
||||
}, raise_error_if_no_rate=False)
|
||||
|
||||
elif self.get("return_against"):
|
||||
# Get incoming rate of return entry from reference document
|
||||
# based on original item cost as per valuation method
|
||||
d.outgoing_rate = get_rate_for_return(self.doctype, self.name, d.item_code, self.return_against, item_row=d)
|
||||
|
||||
def get_supplied_items_cost(self, item_row_id, reset_outgoing_rate=True):
|
||||
supplied_items_cost = 0.0
|
||||
for d in self.get("supplied_items"):
|
||||
@@ -559,6 +581,7 @@ class BuyingController(StockController):
|
||||
from_warehouse_sle = self.get_sl_entries(d, {
|
||||
"actual_qty": -1 * pr_qty,
|
||||
"warehouse": d.from_warehouse,
|
||||
"outgoing_rate": d.outgoing_rate,
|
||||
"dependant_sle_voucher_detail_no": d.name
|
||||
})
|
||||
|
||||
@@ -569,10 +592,8 @@ class BuyingController(StockController):
|
||||
"serial_no": cstr(d.serial_no).strip()
|
||||
})
|
||||
if self.is_return:
|
||||
outgoing_rate = get_rate_for_return(self.doctype, self.name, d.item_code, self.return_against, item_row=d)
|
||||
|
||||
sle.update({
|
||||
"outgoing_rate": outgoing_rate,
|
||||
"outgoing_rate": d.outgoing_rate,
|
||||
"recalculate_rate": 1
|
||||
})
|
||||
if d.from_warehouse:
|
||||
|
||||
@@ -331,6 +331,12 @@ class SellingController(StockController):
|
||||
"voucher_no": self.name,
|
||||
"allow_zero_valuation": d.get("allow_zero_valuation")
|
||||
}, raise_error_if_no_rate=False)
|
||||
|
||||
# For internal transfers use incoming rate as the valuation rate
|
||||
if self.get('is_internal_customer') and d.get('target_warehouse'):
|
||||
d.rate = d.incoming_rate
|
||||
frappe.msgprint(_("Row {0}: Item rate updated as the valuation rate since its an internal transfer").format(d.idx))
|
||||
|
||||
elif self.get("return_against"):
|
||||
# Get incoming rate of return entry from reference document
|
||||
# based on original item cost as per valuation method
|
||||
|
||||
@@ -72,7 +72,7 @@ class StockController(AccountsController):
|
||||
warehouse_with_no_account = []
|
||||
precision = frappe.get_precision("GL Entry", "debit_in_account_currency")
|
||||
for item_row in voucher_details:
|
||||
sle_list = sle_map.get(item_row.name)
|
||||
sle_list = sle_map.get((item_row.name, item_row.warehouse))
|
||||
if sle_list:
|
||||
for sle in sle_list:
|
||||
if warehouse_account.get(sle.warehouse):
|
||||
@@ -216,7 +216,7 @@ class StockController(AccountsController):
|
||||
""", (self.doctype, self.name), as_dict=True)
|
||||
|
||||
for sle in stock_ledger_entries:
|
||||
stock_ledger.setdefault(sle.voucher_detail_no, []).append(sle)
|
||||
stock_ledger.setdefault((sle.voucher_detail_no, sle.warehouse), []).append(sle)
|
||||
return stock_ledger
|
||||
|
||||
def make_batches(self, warehouse_field):
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
"column_break_32",
|
||||
"base_net_rate",
|
||||
"base_net_amount",
|
||||
"outgoing_rate",
|
||||
"valuation_rate",
|
||||
"item_tax_amount",
|
||||
"rm_supp_cost",
|
||||
@@ -861,12 +862,18 @@
|
||||
"fieldtype": "Float",
|
||||
"label": "Received Qty in Stock UOM",
|
||||
"print_hide": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "outgoing_rate",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Outgoing Rate",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-12-07 10:00:38.204294",
|
||||
"modified": "2020-12-23 17:33:19.479325",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Purchase Receipt Item",
|
||||
|
||||
Reference in New Issue
Block a user