diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 41085181720..1fcde1119da 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -51,7 +51,37 @@ class StockController(AccountsController): self.validate_internal_transfer() self.validate_putaway_capacity() +<<<<<<< HEAD def make_gl_entries(self, gl_entries=None, from_repost=False): +======= + def validate_duplicate_serial_and_batch_bundle(self): + if sbb_list := [ + item.get("serial_and_batch_bundle") + for item in self.items + if item.get("serial_and_batch_bundle") + ]: + SLE = frappe.qb.DocType("Stock Ledger Entry") + data = ( + frappe.qb.from_(SLE) + .select(SLE.voucher_type, SLE.voucher_no, SLE.serial_and_batch_bundle) + .where( + (SLE.docstatus == 1) + & (SLE.serial_and_batch_bundle.notnull()) + & (SLE.serial_and_batch_bundle.isin(sbb_list)) + ) + .limit(1) + ).run(as_dict=True) + + if data: + data = data[0] + frappe.throw( + _("Serial and Batch Bundle {0} is already used in {1} {2}.").format( + frappe.bold(data.serial_and_batch_bundle), data.voucher_type, data.voucher_no + ) + ) + + def make_gl_entries(self, gl_entries=None, from_repost=False, via_landed_cost_voucher=False): +>>>>>>> baa3fee1bf (fix: add LCV flag to determine negative expenses) if self.docstatus == 2: make_reverse_gl_entries(voucher_type=self.doctype, voucher_no=self.name) @@ -72,7 +102,7 @@ class StockController(AccountsController): if self.docstatus == 1: if not gl_entries: - gl_entries = self.get_gl_entries(warehouse_account) + gl_entries = self.get_gl_entries(warehouse_account, via_landed_cost_voucher) make_gl_entries(gl_entries, from_repost=from_repost) def validate_serialized_batch(self): diff --git a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py index f6b7e0d8435..77f3d2ba2b3 100644 --- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py +++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py @@ -224,7 +224,7 @@ class LandedCostVoucher(Document): # 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.make_gl_entries(via_landed_cost_voucher=True) doc.repost_future_sle_and_gle() def validate_asset_qty_and_status(self, receipt_document_type, receipt_document): diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index a6fd929ea34..7bbe7b9ff75 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -307,13 +307,13 @@ class PurchaseReceipt(BuyingController): self.delete_auto_created_batches() self.set_consumed_qty_in_subcontract_order() - def get_gl_entries(self, warehouse_account=None): + def get_gl_entries(self, warehouse_account=None, via_landed_cost_voucher=False): from erpnext.accounts.general_ledger import process_gl_map gl_entries = [] self.make_item_gl_entries(gl_entries, warehouse_account=warehouse_account) - self.make_tax_gl_entries(gl_entries) + self.make_tax_gl_entries(gl_entries, via_landed_cost_voucher) update_regional_gl_entries(gl_entries, self) return process_gl_map(gl_entries) @@ -661,7 +661,7 @@ class PurchaseReceipt(BuyingController): posting_date=posting_date, ) - def make_tax_gl_entries(self, gl_entries): + def make_tax_gl_entries(self, gl_entries, via_landed_cost_voucher=False): 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 @@ -696,18 +696,17 @@ class PurchaseReceipt(BuyingController): 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 - else: + if via_landed_cost_voucher: account = tax.account_head + else: + 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), + ) + account = stock_rbnb if negative_expense_booked_in_pi else tax.account_head if i == len(valuation_tax): applicable_amount = amount_including_divisional_loss