Landed Cost on_submit and gl entries for PR
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
index 55e3247..3b6ad82 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -387,7 +387,7 @@
self.update_prevdoc_status()
self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
- self.make_cancel_gl_entries()
+ self.make_gl_entries_on_cancel()
def on_update(self):
pass
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 1205646..481ae09 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -121,7 +121,7 @@
self.update_prevdoc_status()
self.update_billing_status_for_zero_amount_refdoc("Sales Order")
- self.make_cancel_gl_entries()
+ self.make_gl_entries_on_cancel()
def update_status_updater_args(self):
if cint(self.update_stock):
diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py
index 85d7a9e..9f2b78e 100644
--- a/erpnext/controllers/buying_controller.py
+++ b/erpnext/controllers/buying_controller.py
@@ -193,9 +193,13 @@
"UOM Conversion Detail", {"parent": item.item_code, "uom": item.uom},
"conversion_factor")) or 1
qty_in_stock_uom = flt(item.qty * item.conversion_factor)
- rm_supp_cost = item.rm_supp_cost if self.doctype=="Purchase Receipt" else 0.0
- item.valuation_rate = ((item.base_amount + item.item_tax_amount + rm_supp_cost)
- / qty_in_stock_uom)
+ rm_supp_cost = flt(item.rm_supp_cost) if self.doctype=="Purchase Receipt" else 0.0
+
+ landed_cost_voucher_amount = flt(item.landed_cost_voucher_amount) \
+ if self.doctype == "Purchase Receipt" else 0.0
+
+ item.valuation_rate = ((item.base_amount + item.item_tax_amount + rm_supp_cost
+ + landed_cost_voucher_amount) / qty_in_stock_uom)
else:
item.valuation_rate = 0.0
diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py
index 27437a3..a1d9a5b 100644
--- a/erpnext/controllers/stock_controller.py
+++ b/erpnext/controllers/stock_controller.py
@@ -274,7 +274,7 @@
from erpnext.stock.stock_ledger import make_sl_entries
make_sl_entries(sl_entries, is_amended)
- def make_cancel_gl_entries(self):
+ def make_gl_entries_on_cancel(self):
if frappe.db.sql("""select name from `tabGL Entry` where voucher_type=%s
and voucher_no=%s""", (self.doctype, self.name)):
self.make_gl_entries()
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index e831c47..864329d 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -196,7 +196,7 @@
frappe.db.set(self, 'status', 'Cancelled')
self.cancel_packing_slips()
- self.make_cancel_gl_entries()
+ self.make_gl_entries_on_cancel()
def validate_packed_qty(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 79e25b3..9653242 100644
--- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
+++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
@@ -16,7 +16,10 @@
for pr in self.get("landed_cost_purchase_receipts"):
pr_items = frappe.db.sql("""select pr_tem.item_code, pr_tem.description,
pr_tem.qty, pr_tem.rate, pr_tem.amount, pr_tem.name
- from `tabPurchase Receipt Item` where parent = %s""", pr.purchase_receipt, as_dict=True)
+ from `tabPurchase Receipt Item` pr_item where parent = %s
+ and (select name form tabItem where name = pr_item.item_code and is_stock_item = 'Yes')""",
+ pr.purchase_receipt, as_dict=True)
+
for d in pr_items:
item = self.append("landed_cost_items")
item.item_code = d.item_code
@@ -73,7 +76,14 @@
def on_submit(self):
purchase_receipts = list(set([d.purchase_receipt for d in self.get("landed_cost_items")]))
-
+ self.delete_sle_and_gle(purchase_receipts)
for purchase_receipt in purchase_receipts:
pr = frappe.get_doc("Purchase Receipt", purchase_receipt)
-
\ No newline at end of file
+ pr.update_valuation_rate()
+ pr.update_stock()
+ pr.make_gl_entries()
+
+ def delete_sle_and_gle(self, purchase_receipts):
+ for doctype in ["Stock Ledger Entry", "GL Entry"]:
+ frappe.db.sql("""delete from `tab%s` where voucher_type='Purchase Receipt'
+ and voucher_no in (%s)""" % (doctype, ', '.join(['%s']*len(purchase_receipts))), purchase_receipts)
\ No newline at end of file
diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
index 5f56149..d627386 100644
--- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -67,9 +67,16 @@
# sub-contracting
self.validate_for_subcontracting()
self.create_raw_materials_supplied("pr_raw_material_details")
-
+ self.set_landed_cost_voucher_amount()
self.update_valuation_rate("purchase_receipt_details")
-
+
+ def set_landed_cost_voucher_amount(self, voucher_detail):
+ for d in self.get("purchase_receipt_details"):
+ lc_voucher_amount = frappe.db.sql("""select sum(ifnull(applicable_charges))
+ from `tabLanded Cost Item`
+ where docstatus = 1 and pr_item_row_id = %s""", voucher_detail)
+ d.landed_cost_voucher_amount = lc_voucher_amount[0][0] if lc_voucher_amount else 0.0
+
def validate_rejected_warehouse(self):
for d in self.get("purchase_receipt_details"):
if flt(d.rejected_qty) and not d.rejected_warehouse:
@@ -265,7 +272,7 @@
self.update_prevdoc_status()
pc_obj.update_last_purchase_rate(self, 0)
- self.make_cancel_gl_entries()
+ self.make_gl_entries_on_cancel()
def get_current_stock(self):
for d in self.get('pr_raw_material_details'):
@@ -277,10 +284,88 @@
return frappe.get_doc('Purchase Common').get_rate(arg,self)
def get_gl_entries(self, warehouse_account=None):
- against_stock_account = self.get_company_default("stock_received_but_not_billed")
+ from erpnext.accounts.general_ledger import process_gl_map
+
+ stock_rbnb = self.get_company_default("stock_received_but_not_billed")
+ expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
+ default_cost_center = self.get_company_default("cost_center")
+ against_expense_account = None
+
+ gl_entries = []
+ warehouse_with_no_account = []
+ stock_items = self.get_stock_items()
+ for d in self.get("purchase_receipt_details"):
+ if d.item_code in stock_items and flt(d.valuation_rate):
+ if warehouse_account.get(d.warehouse) or warehouse_account.get(d.rejected_warehouse):
+ self.check_expense_account(d)
+
+ # warehouse account
+ if flt(d.qty):
+ gl_list.append(self.get_gl_dict({
+ "account": warehouse_account[d.warehouse],
+ "against": against_expense_account,
+ "cost_center": default_cost_center,
+ "remarks": self.get("remarks") or "Accounting Entry for Stock",
+ "debit": flt(d.valuation_rate) * flt(d.qty) * flt(d.conversion_factor)
+ }))
+
+ # rejected warehouse
+ if flt(d.rejected_qty):
+ gl_list.append(self.get_gl_dict({
+ "account": warehouse_account[d.rejected_warehouse],
+ "against": against_expense_account,
+ "cost_center": default_cost_center,
+ "remarks": self.get("remarks") or "Accounting Entry for Stock",
+ "debit": flt(d.valuation_rate) * flt(d.rejected_qty) * flt(d.conversion_factor)
+ }))
- gl_entries = super(PurchaseReceipt, self).get_gl_entries(warehouse_account, against_stock_account)
- return gl_entries
+ # stock received but not billed
+ gl_list.append(self.get_gl_dict({
+ "account": stock_rbnb,
+ "against": warehouse_account[d.warehouse],
+ "cost_center": default_cost_center,
+ "remarks": self.get("remarks") or "Accounting Entry for Stock",
+ "credit": flt(d.base_amount, 2)
+ }))
+
+ if flt(d.landed_cost_voucher_amount):
+ gl_list.append(self.get_gl_dict({
+ "account": expenses_included_in_valuation,
+ "against": warehouse_account[d.warehouse],
+ "cost_center": default_cost_center,
+ "remarks": self.get("remarks") or "Accounting Entry for Stock",
+ "credit": flt(d.landed_cost_voucher_amount)
+ }))
+
+ elif d.warehouse not in warehouse_with_no_account or \
+ d.rejected_warehouse not in warehouse_with_no_account:
+ warehouse_with_no_account.append(d.warehouse)
+
+ if warehouse_with_no_account:
+ msgprint(_("No accounting entries for the following warehouses") + ": \n" +
+ "\n".join(warehouse_with_no_account))
+
+ valuation_tax = {}
+ for tax in self.get("other_charges"):
+ if tax.category in ("Valuation", "Valuation and Total") and flt(tax.tax_amount):
+ if not tax.cost_center:
+ frappe.throw(_("Cost Center is required in row {0} in Taxes table for type {1}").format(tax.idx, _(tax.category)))
+ valuation_tax.setdefault(tax.cost_center, 0)
+ valuation_tax[tax.cost_center] += \
+ (tax.add_deduct_tax == "Add" and 1 or -1) * flt(tax.tax_amount)
+
+ for cost_center, amount in valuation_tax.items():
+ gl_entries.append(
+ self.get_gl_dict({
+ "account": expenses_included_in_valuation,
+ "cost_center": cost_center,
+ # "against": ,
+ "credit": amount,
+ "remarks": self.remarks or "Accounting Entry for Stock"
+ })
+ )
+
+ return process_gl_map(gl_entries)
@frappe.whitelist()
diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
index 8c5e732..76d6294 100755
--- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
+++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
@@ -502,6 +502,13 @@
"width": "150px"
},
{
+ "fieldname": "landed_cost_voucher_amount",
+ "fieldtype": "Currency",
+ "label": "Landed Cost Voucher Amount",
+ "permlevel": 0,
+ "read_only": 1
+ },
+ {
"fieldname": "valuation_rate",
"fieldtype": "Currency",
"hidden": 1,
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index 1da2ad5..bdd760b 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -65,7 +65,7 @@
def on_cancel(self):
self.update_stock_ledger()
self.update_production_order()
- self.make_cancel_gl_entries()
+ self.make_gl_entries_on_cancel()
def validate_fiscal_year(self):
from erpnext.accounts.utils import validate_fiscal_year
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
index bb1e3e2..8b32211 100644
--- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
+++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
@@ -27,7 +27,7 @@
def on_cancel(self):
self.delete_and_repost_sle()
- self.make_cancel_gl_entries()
+ self.make_gl_entries_on_cancel()
def validate_data(self):
if not self.reconciliation_json: