def get_gl_entries(self, warehouse_account=None, default_expense_account=None, default_cost_center=None): if not warehouse_account: warehouse_account = get_warehouse_account_map() sle_map = self.get_stock_ledger_details() voucher_details = self.get_voucher_details(default_expense_account, default_cost_center, sle_map) gl_list = [] warehouse_with_no_account = [] for item_row in voucher_details: sle_list = sle_map.get(item_row.name) if sle_list: for sle in sle_list: if warehouse_account.get(sle.warehouse): # from warehouse account self.check_expense_account(item_row) # If the item does not have the allow zero valuation rate flag set # and ( valuation rate not mentioned in an incoming entry # or incoming entry not found while delivering the item), # try to pick valuation rate from previous sle or Item master and update in SLE # Otherwise, throw an exception if not sle.stock_value_difference and self.doctype != "Stock Reconciliation" \ and not item_row.get("allow_zero_valuation_rate"): sle = self.update_stock_ledger_entries(sle) gl_list.append(self.get_gl_dict({ "account": warehouse_account[sle.warehouse]["account"], "against": item_row.expense_account, "cost_center": item_row.cost_center, "remarks": self.get("remarks") or "Accounting Entry for Stock", "debit": flt(sle.stock_value_difference, 2), }, warehouse_account[sle.warehouse]["account_currency"])) # to target warehouse / expense account gl_list.append(self.get_gl_dict({ "account": item_row.expense_account, "against": warehouse_account[sle.warehouse]["account"], "cost_center": item_row.cost_center, "remarks": self.get("remarks") or "Accounting Entry for Stock", "credit": flt(sle.stock_value_difference, 2), "project": item_row.get("project") or self.get("project") })) elif sle.warehouse not in warehouse_with_no_account: warehouse_with_no_account.append(sle.warehouse) if warehouse_with_no_account: for wh in warehouse_with_no_account: if frappe.db.get_value("Warehouse", wh, "company"): frappe.throw(_("Warehouse {0} is not linked to any account, please mention the account in the warehouse record or set default inventory account in company {1}.").format(wh, self.company)) return process_gl_map(gl_list)
def get_gl_entries(self, warehouse_account=None, default_expense_account=None, default_cost_center=None): if not warehouse_account: warehouse_account = get_warehouse_account() sle_map = self.get_stock_ledger_details() voucher_details = self.get_voucher_details(default_expense_account, default_cost_center, sle_map) gl_list = [] warehouse_with_no_account = [] for detail in voucher_details: sle_list = sle_map.get(detail.name) if sle_list: for sle in sle_list: if warehouse_account.get(sle.warehouse): # from warehouse account self.check_expense_account(detail) gl_list.append( self.get_gl_dict( { "account": warehouse_account[sle.warehouse]["name"], "against": detail.expense_account, "cost_center": detail.cost_center, "remarks": self.get("remarks") or "Accounting Entry for Stock", "debit": flt(sle.stock_value_difference, 2), }, warehouse_account[sle.warehouse]["account_currency"], ) ) # to target warehouse / expense account gl_list.append( self.get_gl_dict( { "account": detail.expense_account, "against": warehouse_account[sle.warehouse]["name"], "cost_center": detail.cost_center, "remarks": self.get("remarks") or "Accounting Entry for Stock", "credit": flt(sle.stock_value_difference, 2), "project": detail.get("project") or self.get("project"), } ) ) elif sle.warehouse not in warehouse_with_no_account: warehouse_with_no_account.append(sle.warehouse) if warehouse_with_no_account: msgprint( _("No accounting entries for the following warehouses") + ": \n" + "\n".join(warehouse_with_no_account) ) return process_gl_map(gl_list)
def get_gl_entries(self, warehouse_account=None, default_expense_account=None, default_cost_center=None): if not warehouse_account: warehouse_account = get_warehouse_account() sle_map = self.get_stock_ledger_details() voucher_details = self.get_voucher_details(default_expense_account, default_cost_center, sle_map) gl_list = [] warehouse_with_no_account = [] for item_row in voucher_details: sle_list = sle_map.get(item_row.name) if sle_list: for sle in sle_list: if warehouse_account.get(sle.warehouse): # from warehouse account self.check_expense_account(item_row) if not sle.stock_value_difference: self.update_stock_ledger_entries(sle) self.validate_negative_stock(sle) gl_list.append(self.get_gl_dict({ "account": warehouse_account[sle.warehouse]["name"], "against": item_row.expense_account, "cost_center": item_row.cost_center, "remarks": self.get("remarks") or "Accounting Entry for Stock", "debit": flt(sle.stock_value_difference, 2), }, warehouse_account[sle.warehouse]["account_currency"])) # to target warehouse / expense account gl_list.append(self.get_gl_dict({ "account": item_row.expense_account, "against": warehouse_account[sle.warehouse]["name"], "cost_center": item_row.cost_center, "remarks": self.get("remarks") or "Accounting Entry for Stock", "credit": flt(sle.stock_value_difference, 2), "project": item_row.get("project") or self.get("project") })) elif sle.warehouse not in warehouse_with_no_account: warehouse_with_no_account.append(sle.warehouse) if warehouse_with_no_account: for wh in warehouse_with_no_account: if frappe.db.get_value("Warehouse", wh, "company"): frappe.throw(_("Warehouse {0} is not linked to any account, please create/link the corresponding (Asset) account for the warehouse.").format(wh)) msgprint(_("No accounting entries for the following warehouses") + ": \n" + "\n".join(warehouse_with_no_account)) return process_gl_map(gl_list)
def get_gl_entries(self, warehouse_account=None, default_expense_account=None, default_cost_center=None, allow_negative_stock=False): # block_negative_stock(allow_negative_stock) if not warehouse_account: warehouse_account = get_warehouse_account() sle_map = self.get_stock_ledger_details() voucher_details = self.get_voucher_details(default_expense_account, default_cost_center, sle_map) gl_list = [] warehouse_with_no_account = [] for detail in voucher_details: sle_list = sle_map.get(detail.name) if sle_list: for sle in sle_list: if warehouse_account.get(sle.warehouse): # from warehouse account self.check_expense_account(detail) stock_value_difference = flt(sle.stock_value_difference, 2) if not stock_value_difference: valuation_rate = get_valuation_rate(sle.item_code, sle.warehouse) stock_value_difference = flt(sle.actual_qty)*flt(valuation_rate) gl_list.append(self.get_gl_dict({ "account": warehouse_account[sle.warehouse], "against": detail.expense_account, "cost_center": detail.cost_center, "remarks": self.get("remarks") or "Accounting Entry for Stock", "debit": stock_value_difference })) # to target warehouse / expense account gl_list.append(self.get_gl_dict({ "account": detail.expense_account, "against": warehouse_account[sle.warehouse], "cost_center": detail.cost_center, "remarks": self.get("remarks") or "Accounting Entry for Stock", "credit": stock_value_difference })) elif sle.warehouse not in warehouse_with_no_account: warehouse_with_no_account.append(sle.warehouse) if warehouse_with_no_account: msgprint(_("No accounting entries for the following warehouses") + ": \n" + "\n".join(warehouse_with_no_account)) return process_gl_map(gl_list)
def get_gl_entries(self, warehouse_account=None): 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") gl_entries = [] warehouse_with_no_account = [] negative_expense_to_be_booked = 0.0 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) and flt(d.qty): if warehouse_account.get(d.warehouse): # warehouse account gl_entries.append(self.get_gl_dict({ "account": warehouse_account[d.warehouse], "against": stock_rbnb, "cost_center": d.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "debit": flt(flt(d.valuation_rate) * flt(d.qty) * flt(d.conversion_factor), self.precision("valuation_rate", d)) })) # stock received but not billed gl_entries.append(self.get_gl_dict({ "account": stock_rbnb, "against": warehouse_account[d.warehouse], "cost_center": d.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "credit": flt(d.base_amount, self.precision("base_amount", d)) })) negative_expense_to_be_booked += flt(d.item_tax_amount) # Amount added through landed-cost-voucher if flt(d.landed_cost_voucher_amount): gl_entries.append(self.get_gl_dict({ "account": expenses_included_in_valuation, "against": warehouse_account[d.warehouse], "cost_center": d.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "credit": flt(d.landed_cost_voucher_amount) })) # sub-contracting warehouse if flt(d.rm_supp_cost) and warehouse_account.get(self.supplier_warehouse): gl_entries.append(self.get_gl_dict({ "account": warehouse_account[self.supplier_warehouse], "against": warehouse_account[d.warehouse], "cost_center": d.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "credit": flt(d.rm_supp_cost) })) 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) # Cost center-wise amount breakup for other charges included for valuation 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) if negative_expense_to_be_booked and valuation_tax: # Backward compatibility: # If expenses_included_in_valuation account has been credited in against PI # and charges added via Landed Cost Voucher, # post valuation related charges on "Stock Received But Not Billed" 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, expenses_included_in_valuation)) if negative_expense_booked_in_pi: expenses_included_in_valuation = stock_rbnb against_account = ", ".join([d.account for d in gl_entries if flt(d.debit) > 0]) total_valuation_amount = sum(valuation_tax.values()) amount_including_divisional_loss = negative_expense_to_be_booked i = 1 for cost_center, amount in valuation_tax.items(): if i == len(valuation_tax): applicable_amount = amount_including_divisional_loss else: applicable_amount = negative_expense_to_be_booked * (amount / total_valuation_amount) amount_including_divisional_loss -= applicable_amount gl_entries.append( self.get_gl_dict({ "account": expenses_included_in_valuation, "cost_center": cost_center, "credit": applicable_amount, "remarks": self.remarks or _("Accounting Entry for Stock"), "against": against_account }) ) i += 1 if warehouse_with_no_account: frappe.msgprint(_("No accounting entries for the following warehouses") + ": \n" + "\n".join(warehouse_with_no_account)) return process_gl_map(gl_entries)
def get_gl_entries(self, warehouse_account=None): from erpnext.accounts.general_ledger import process_gl_map stock_rbnb = self.get_company_default("stock_received_but_not_billed") landed_cost_entries = get_item_account_wise_additional_cost(self.name) expenses_included_in_valuation = self.get_company_default( "expenses_included_in_valuation") gl_entries = [] warehouse_with_no_account = [] negative_expense_to_be_booked = 0.0 stock_items = self.get_stock_items() for d in self.get("items"): if d.item_code in stock_items and flt(d.valuation_rate) and flt( d.qty): if warehouse_account.get(d.warehouse): stock_value_diff = frappe.db.get_value( "Stock Ledger Entry", { "voucher_type": "Purchase Receipt", "voucher_no": self.name, "voucher_detail_no": d.name, "warehouse": d.warehouse }, "stock_value_difference") if not stock_value_diff: continue gl_entries.append( self.get_gl_dict( { "account": warehouse_account[d.warehouse]["account"], "against": stock_rbnb, "cost_center": d.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "debit": stock_value_diff }, warehouse_account[d.warehouse]["account_currency"], item=d)) # stock received but not billed stock_rbnb_currency = get_account_currency(stock_rbnb) gl_entries.append(self.get_gl_dict({ "account": stock_rbnb, "against": warehouse_account[d.warehouse]["account"], "cost_center": d.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "credit": flt(d.base_net_amount, d.precision("base_net_amount")), "credit_in_account_currency": flt(d.base_net_amount, d.precision("base_net_amount")) \ if stock_rbnb_currency==self.company_currency else flt(d.net_amount, d.precision("net_amount")) }, stock_rbnb_currency, item=d)) negative_expense_to_be_booked += flt(d.item_tax_amount) # Amount added through landed-cost-voucher if d.landed_cost_voucher_amount and landed_cost_entries: for account, amount in iteritems( landed_cost_entries[(d.item_code, d.name)]): gl_entries.append( self.get_gl_dict( { "account": account, "against": warehouse_account[ d.warehouse]["account"], "cost_center": d.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "credit": flt(amount), "project": d.project }, item=d)) # sub-contracting warehouse if flt(d.rm_supp_cost) and warehouse_account.get( self.supplier_warehouse): gl_entries.append( self.get_gl_dict( { "account": warehouse_account[ self.supplier_warehouse]["account"], "against": warehouse_account[d.warehouse]["account"], "cost_center": d.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "credit": flt(d.rm_supp_cost) }, warehouse_account[self.supplier_warehouse] ["account_currency"], item=d)) # divisional loss adjustment valuation_amount_as_per_doc = flt(d.base_net_amount, d.precision("base_net_amount")) + \ flt(d.landed_cost_voucher_amount) + flt(d.rm_supp_cost) + flt(d.item_tax_amount) divisional_loss = flt( valuation_amount_as_per_doc - stock_value_diff, d.precision("base_net_amount")) if divisional_loss: if self.is_return or flt(d.item_tax_amount): loss_account = expenses_included_in_valuation else: loss_account = stock_rbnb gl_entries.append( self.get_gl_dict( { "account": loss_account, "against": warehouse_account[d.warehouse]["account"], "cost_center": d.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "debit": divisional_loss, "project": d.project }, stock_rbnb_currency, item=d)) 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) self.get_asset_gl_entry(gl_entries) # Cost center-wise amount breakup for other charges included for valuation valuation_tax = {} for tax in self.get("taxes"): if tax.category in ("Valuation", "Valuation and Total") and flt( tax.base_tax_amount_after_discount_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.name, 0) valuation_tax[tax.name] += \ (tax.add_deduct_tax == "Add" and 1 or -1) * flt(tax.base_tax_amount_after_discount_amount) if negative_expense_to_be_booked and valuation_tax: # Backward compatibility: # If expenses_included_in_valuation account has been credited in against PI # and charges added via Landed Cost Voucher, # post valuation related charges on "Stock Received But Not Billed" # introduced in 2014 for backward compatibility of expenses already booked in expenses_included_in_valuation account 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, expenses_included_in_valuation)) against_account = ", ".join( [d.account for d in gl_entries if flt(d.debit) > 0]) total_valuation_amount = sum(valuation_tax.values()) amount_including_divisional_loss = negative_expense_to_be_booked i = 1 for tax in self.get("taxes"): if valuation_tax.get(tax.name): if negative_expense_booked_in_pi: account = stock_rbnb else: account = tax.account_head if i == len(valuation_tax): applicable_amount = amount_including_divisional_loss else: applicable_amount = negative_expense_to_be_booked * ( valuation_tax[tax.name] / total_valuation_amount) amount_including_divisional_loss -= applicable_amount gl_entries.append( self.get_gl_dict( { "account": account, "cost_center": tax.cost_center, "credit": applicable_amount, "remarks": self.remarks or _("Accounting Entry for Stock"), "against": against_account }, item=tax)) i += 1 if warehouse_with_no_account: frappe.msgprint( _("No accounting entries for the following warehouses") + ": \n" + "\n".join(warehouse_with_no_account)) return process_gl_map(gl_entries)
def get_gl_entries(self, warehouse_account=None, default_expense_account=None, default_cost_center=None): if not warehouse_account: warehouse_account = get_warehouse_account_map(self.company) sle_map = self.get_stock_ledger_details() voucher_details = self.get_voucher_details(default_expense_account, default_cost_center, sle_map) gl_list = [] warehouse_with_no_account = [] for item_row in voucher_details: sle_list = sle_map.get(item_row.name) if sle_list: for sle in sle_list: if warehouse_account.get(sle.warehouse): # from warehouse account self.check_expense_account(item_row) # If the item does not have the allow zero valuation rate flag set # and ( valuation rate not mentioned in an incoming entry # or incoming entry not found while delivering the item), # try to pick valuation rate from previous sle or Item master and update in SLE # Otherwise, throw an exception if not sle.stock_value_difference and self.doctype != "Stock Reconciliation" \ and not item_row.get("allow_zero_valuation_rate"): sle = self.update_stock_ledger_entries(sle) gl_list.append( self.get_gl_dict( { "account": warehouse_account[ sle.warehouse]["account"], "against": item_row.expense_account, "cost_center": item_row.cost_center, "remarks": self.get("remarks") or "Accounting Entry for Stock", "debit": flt(sle.stock_value_difference, 2), }, warehouse_account[sle.warehouse] ["account_currency"])) # to target warehouse / expense account gl_list.append( self.get_gl_dict({ "account": item_row.expense_account, "against": warehouse_account[sle.warehouse]["account"], "cost_center": item_row.cost_center, "remarks": self.get("remarks") or "Accounting Entry for Stock", "credit": flt(sle.stock_value_difference, 2), "project": item_row.get("project") or self.get("project") })) elif sle.warehouse not in warehouse_with_no_account: warehouse_with_no_account.append(sle.warehouse) if warehouse_with_no_account: for wh in warehouse_with_no_account: if frappe.db.get_value("Warehouse", wh, "company"): frappe.throw( _("Warehouse {0} is not linked to any account, please mention the account in the warehouse record or set default inventory account in company {1}." ).format(wh, self.company)) return process_gl_map(gl_list)
def get_gl_entries(self, warehouse_account=None, default_expense_account=None, default_cost_center=None): if not warehouse_account: warehouse_account = get_warehouse_account() sle_map = self.get_stock_ledger_details() voucher_details = self.get_voucher_details(default_expense_account, default_cost_center, sle_map) gl_list = [] warehouse_with_no_account = [] for detail in voucher_details: sle_list = sle_map.get(detail.name) if sle_list: for sle in sle_list: if warehouse_account.get(sle.warehouse): # from warehouse account self.check_expense_account(detail) gl_list.append( self.get_gl_dict({ "account": warehouse_account[sle.warehouse], "against": detail.expense_account, "cost_center": detail.cost_center, "remarks": self.get("remarks") or "Accounting Entry for Stock", "debit": flt(sle.stock_value_difference, 2) })) # to target warehouse / expense account gl_list.append( self.get_gl_dict({ "account": detail.expense_account, "against": warehouse_account[sle.warehouse], "cost_center": detail.cost_center, "remarks": self.get("remarks") or "Accounting Entry for Stock", "credit": flt(sle.stock_value_difference, 2) })) elif sle.warehouse not in warehouse_with_no_account: warehouse_with_no_account.append(sle.warehouse) if warehouse_with_no_account: msgprint( _("No accounting entries for the following warehouses") + ": \n" + "\n".join(warehouse_with_no_account)) return process_gl_map(gl_list)
def get_gl_entries(self, warehouse_account=None): 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") gl_entries = [] warehouse_with_no_account = [] negative_expense_to_be_booked = 0.0 stock_items = self.get_stock_items() for d in self.get("items"): if d.item_code in stock_items and flt(d.valuation_rate) and flt( d.qty): if warehouse_account.get(d.warehouse): # warehouse account gl_entries.append( self.get_gl_dict({ "account": warehouse_account[d.warehouse], "against": stock_rbnb, "cost_center": d.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "debit": flt( flt(d.valuation_rate) * flt(d.qty) * flt(d.conversion_factor), self.precision("valuation_rate", d)) })) # stock received but not billed gl_entries.append( self.get_gl_dict({ "account": stock_rbnb, "against": warehouse_account[d.warehouse], "cost_center": d.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "credit": flt(d.base_amount, self.precision("base_amount", d)) })) negative_expense_to_be_booked += flt(d.item_tax_amount) # Amount added through landed-cost-voucher if flt(d.landed_cost_voucher_amount): gl_entries.append( self.get_gl_dict({ "account": expenses_included_in_valuation, "against": warehouse_account[d.warehouse], "cost_center": d.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "credit": flt(d.landed_cost_voucher_amount) })) # sub-contracting warehouse if flt(d.rm_supp_cost) and warehouse_account.get( self.supplier_warehouse): gl_entries.append( self.get_gl_dict({ "account": warehouse_account[self.supplier_warehouse], "against": warehouse_account[d.warehouse], "cost_center": d.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "credit": flt(d.rm_supp_cost) })) 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) # Cost center-wise amount breakup for other charges included for valuation valuation_tax = {} for tax in self.get("taxes"): 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) if negative_expense_to_be_booked and valuation_tax: # Backward compatibility: # If expenses_included_in_valuation account has been credited in against PI # and charges added via Landed Cost Voucher, # post valuation related charges on "Stock Received But Not Billed" 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, expenses_included_in_valuation)) if negative_expense_booked_in_pi: expenses_included_in_valuation = stock_rbnb against_account = ", ".join( [d.account for d in gl_entries if flt(d.debit) > 0]) total_valuation_amount = sum(valuation_tax.values()) amount_including_divisional_loss = negative_expense_to_be_booked i = 1 for cost_center, amount in valuation_tax.items(): if i == len(valuation_tax): applicable_amount = amount_including_divisional_loss else: applicable_amount = negative_expense_to_be_booked * ( amount / total_valuation_amount) amount_including_divisional_loss -= applicable_amount gl_entries.append( self.get_gl_dict({ "account": expenses_included_in_valuation, "cost_center": cost_center, "credit": applicable_amount, "remarks": self.remarks or _("Accounting Entry for Stock"), "against": against_account })) i += 1 if warehouse_with_no_account: frappe.msgprint( _("No accounting entries for the following warehouses") + ": \n" + "\n".join(warehouse_with_no_account)) return process_gl_map(gl_entries)
def get_gl_entries(self, warehouse_account=None, default_expense_account=None, default_cost_center=None): if not warehouse_account: warehouse_account = get_warehouse_account() sle_map = self.get_stock_ledger_details() voucher_details = self.get_voucher_details(default_expense_account, default_cost_center, sle_map) gl_list = [] warehouse_with_no_account = [] for item_row in voucher_details: sle_list = sle_map.get(item_row.name) if sle_list: for sle in sle_list: if warehouse_account.get(sle.warehouse): # from warehouse account self.check_expense_account(item_row) if not sle.stock_value_difference: self.update_stock_ledger_entries(sle) self.validate_negative_stock(sle) gl_list.append( self.get_gl_dict( { "account": warehouse_account[sle.warehouse]["name"], "against": item_row.expense_account, "cost_center": item_row.cost_center, "remarks": self.get("remarks") or "Accounting Entry for Stock", "debit": flt(sle.stock_value_difference, 2), }, warehouse_account[sle.warehouse] ["account_currency"])) # to target warehouse / expense account gl_list.append( self.get_gl_dict({ "account": item_row.expense_account, "against": warehouse_account[sle.warehouse]["name"], "cost_center": item_row.cost_center, "remarks": self.get("remarks") or "Accounting Entry for Stock", "credit": flt(sle.stock_value_difference, 2), "project": item_row.get("project") or self.get("project") })) elif sle.warehouse not in warehouse_with_no_account: warehouse_with_no_account.append(sle.warehouse) if warehouse_with_no_account: for wh in warehouse_with_no_account: if frappe.db.get_value("Warehouse", wh, "company"): frappe.throw( _("Warehouse {0} is not linked to any account, please create/link the corresponding (Asset) account for the warehouse." ).format(wh)) msgprint( _("No accounting entries for the following warehouses") + ": \n" + "\n".join(warehouse_with_no_account)) return process_gl_map(gl_list)
def get_gl_entries(self, warehouse_account=None, default_expense_account=None, default_cost_center=None): if not warehouse_account: warehouse_account = get_warehouse_account() sle_map = self.get_stock_ledger_details() voucher_details = self.get_voucher_details(default_expense_account, default_cost_center, sle_map) gl_list = [] warehouse_with_no_account = [] for item_row in voucher_details: sle_list = sle_map.get(item_row.name) if sle_list: for sle in sle_list: if warehouse_account.get(sle.warehouse): # from warehouse account self.check_expense_account(item_row) # If item is not a sample item # and ( valuation rate not mentioned in an incoming entry # or incoming entry not found while delivering the item), # try to pick valuation rate from previous sle or Item master and update in SLE # Otherwise, throw an exception if not sle.stock_value_difference and self.doctype != "Stock Reconciliation" \ and not item_row.get("is_sample_item"): sle = self.update_stock_ledger_entries(sle) gl_list.append(self.get_gl_dict({ "account": warehouse_account[sle.warehouse]["name"], "against": item_row.expense_account, "cost_center": item_row.cost_center, "remarks": self.get("remarks") or "Accounting Entry for Stock", "debit": flt(sle.stock_value_difference, 2), }, warehouse_account[sle.warehouse]["account_currency"])) # to target warehouse / expense account gl_list.append(self.get_gl_dict({ "account": item_row.expense_account, "against": warehouse_account[sle.warehouse]["name"], "cost_center": item_row.cost_center, "remarks": self.get("remarks") or "Accounting Entry for Stock", "credit": flt(sle.stock_value_difference, 2), "project": item_row.get("project") or self.get("project") })) elif sle.warehouse not in warehouse_with_no_account: warehouse_with_no_account.append(sle.warehouse) if warehouse_with_no_account: for wh in warehouse_with_no_account: if frappe.db.get_value("Warehouse", wh, "company"): frappe.throw(_("Warehouse {0} is not linked to any account, please create/link the corresponding (Asset) account for the warehouse.").format(wh)) msgprint(_("No accounting entries for the following warehouses") + ": \n" + "\n".join(warehouse_with_no_account)) return process_gl_map(gl_list)
def get_gl_entries(self, warehouse_account=None, default_expense_account=None, default_cost_center=None): if not warehouse_account: warehouse_account = get_warehouse_account_map(self.company) sle_map = self.get_stock_ledger_details() voucher_details = self.get_voucher_details(default_expense_account, default_cost_center, sle_map) gl_list = [] warehouse_with_no_account = [] precision = self.get_debit_field_precision() for item_row in voucher_details: sle_list = sle_map.get(item_row.name) if sle_list: for sle in sle_list: if warehouse_account.get(sle.warehouse): # from warehouse account self.check_expense_account(item_row) # expense account/ target_warehouse / source_warehouse if item_row.get("target_warehouse"): warehouse = item_row.get("target_warehouse") expense_account = warehouse_account[warehouse][ "account"] else: expense_account = item_row.expense_account gl_list.append( self.get_gl_dict( { "account": warehouse_account[ sle.warehouse]["account"], "against": expense_account, "cost_center": item_row.cost_center, "project": item_row.project or self.get("project"), "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "debit": flt(sle.stock_value_difference, precision), "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": expense_account, "against": warehouse_account[ sle.warehouse]["account"], "cost_center": item_row.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "credit": flt(sle.stock_value_difference, precision), "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, )) elif sle.warehouse not in warehouse_with_no_account: warehouse_with_no_account.append(sle.warehouse) if warehouse_with_no_account: for wh in warehouse_with_no_account: if frappe.db.get_value("Warehouse", wh, "company"): frappe.throw( _("Warehouse {0} is not linked to any account, please mention the account in the warehouse record or set default inventory account in company {1}." ).format(wh, self.company)) return process_gl_map(gl_list, precision=precision)
def validate_with_delivery_note(self): # We are only doing this: # Make SLEs for changed qtys # Make the GL wrt abv # make_sl_entries & make_gl_entries handles cancellation # not stable return if self.update_stock == 1: # do nothing if updating stock return sl_entries = [] changed_rows = [] # everything wrt stock_qty for d in [ x for x in self.items if x.validate_with_delivery_note and x.warehouse ]: if frappe.db.get_value("Item", d.item_code, "is_stock_item") == 1 and flt(d.stock_qty): delivered_qty = 0 if d.dn_detail: delivered_qty = frappe.get_value("Delivery Note Item", d.dn_detail, "stock_qty") qty_change = d.stock_qty - delivered_qty # qty_change # -ve : got return # +ve : gave more # 0 : continue if qty_change == 0: continue # return rate- code copied from selling_controller.py return_rate = 0 if cint(self.is_return ) and self.return_against and self.docstatus == 1: return_rate = self.get_incoming_rate_for_sales_return( d.item_code, self.return_against) sl_entries.append( self.get_sl_entries( d, { "actual_qty": -1 * flt(qty_change), "incoming_rate": return_rate, "parent": "consoleerp-{}".format(self.name) })) changed_rows.append(d) self.make_sl_entries(sl_entries) # above method inserts the SLEs # stock_value_difference is made only after the above method # STOCK GL ENTRIES # Proceed if perpetual inventory is enabled import erpnext if not erpnext.is_perpetual_inventory_enabled(self.company): return #--- get stock ledger entries just made from erpnext.stock import get_warehouse_account_map warehouse_account = get_warehouse_account_map() sle_map = {} stock_ledger_entries = frappe.db.sql(""" select name, warehouse, stock_value_difference, valuation_rate, voucher_detail_no, item_code, posting_date, posting_time, actual_qty, qty_after_transaction from `tabStock Ledger Entry` where voucher_type=%s and voucher_no=%s and parent=%s """, (self.doctype, self.name, "consoleerp-{}".format(self.name)), as_dict=True) for sle in stock_ledger_entries: sle_map.setdefault(sle.voucher_detail_no, []).append(sle) warehouse_with_no_account = [] gl_list = [] # loop it again # stock_controller.get_gl_entries() for item_row in changed_rows: sle_list = sle_map.get(item_row.name) if sle_list: for sle in sle_list: if warehouse_account.get(sle.warehouse): # from warehouse account self.check_expense_account(item_row) # If the item does not have the allow zero valuation rate flag set # and ( valuation rate not mentioned in an incoming entry # or incoming entry not found while delivering the item), # try to pick valuation rate from previous sle or Item master and update in SLE # Otherwise, throw an exception if not sle.stock_value_difference and self.doctype != "Stock Reconciliation" \ and not item_row.get("allow_zero_valuation_rate"): sle = self.update_stock_ledger_entries(sle) gl_list.append( self.get_gl_dict( { "account": warehouse_account[sle.warehouse]["account"], "against": item_row.expense_account, "cost_center": item_row.cost_center, "remarks": "Delivery Note Validation Entry", "debit": flt(sle.stock_value_difference, 2), }, warehouse_account[sle.warehouse] ["account_currency"])) # to target warehouse / expense account gl_list.append( self.get_gl_dict({ "account": item_row.expense_account, "against": warehouse_account[sle.warehouse]["account"], "cost_center": item_row.cost_center, "remarks": "Delivery Note Validation Entry", "credit": flt(sle.stock_value_difference, 2), "project": item_row.get("project") or self.get("project") })) elif sle.warehouse not in warehouse_with_no_account: warehouse_with_no_account.append(sle.warehouse) if warehouse_with_no_account: for wh in warehouse_with_no_account: if frappe.db.get_value("Warehouse", wh, "company"): frappe.throw( _("Warehouse {0} is not linked to any account, please mention the account in the warehouse record or set default inventory account in company {1}." ).format(wh, self.company)) from erpnext.accounts.general_ledger import process_gl_map gl_list = process_gl_map(gl_list) from erpnext.accounts.general_ledger import merge_similar_entries gl_list = merge_similar_entries(gl_list) self.make_gl_entries(gl_list)