def get_asset_gl_entry(self, gl_entries): for d in self.get("items"): if d.is_fixed_asset: arbnb_account = self.get_company_default( "asset_received_but_not_billed") # CWIP entry cwip_account = get_asset_account( "capital_work_in_progress_account", d.asset, company=self.company) asset_amount = flt(d.net_amount) + flt( d.item_tax_amount / self.conversion_rate) base_asset_amount = flt(d.base_net_amount + d.item_tax_amount) cwip_account_currency = get_account_currency(cwip_account) gl_entries.append( self.get_gl_dict({ "account": cwip_account, "against": arbnb_account, "cost_center": d.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Asset"), "debit": base_asset_amount, "debit_in_account_currency": (base_asset_amount if cwip_account_currency == self.company_currency else asset_amount) })) # Asset received but not billed asset_rbnb_currency = get_account_currency(arbnb_account) gl_entries.append( self.get_gl_dict({ "account": arbnb_account, "against": cwip_account, "cost_center": d.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Asset"), "credit": base_asset_amount, "credit_in_account_currency": (base_asset_amount if asset_rbnb_currency == self.company_currency else asset_amount) })) return gl_entries
def make_write_off_gl_entry(self, gl_entries): # writeoff account includes petty difference in the invoice amount # and the amount that is paid if self.write_off_account and flt(self.write_off_amount): write_off_account_currency = get_account_currency(self.write_off_account) gl_entries.append( self.get_gl_dict({ "account": self.credit_to, "party_type": "Supplier", "party": self.supplier, "against": self.write_off_account, "debit": self.base_write_off_amount, "debit_in_account_currency": self.base_write_off_amount \ if self.party_account_currency==self.company_currency else self.write_off_amount, "against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name, "against_voucher_type": self.doctype, "cost_center": self.cost_center }, self.party_account_currency) ) gl_entries.append( self.get_gl_dict({ "account": self.write_off_account, "against": self.supplier, "credit": flt(self.base_write_off_amount), "credit_in_account_currency": self.base_write_off_amount \ if write_off_account_currency==self.company_currency else self.write_off_amount, "cost_center": self.cost_center or self.write_off_cost_center }) )
def make_payment_gl_entries(self, gl_entries): # Make Cash GL Entries if cint(self.is_paid) and self.cash_bank_account and self.paid_amount: bank_account_currency = get_account_currency(self.cash_bank_account) # CASH, make payment entries gl_entries.append( self.get_gl_dict({ "account": self.credit_to, "party_type": "Supplier", "party": self.supplier, "against": self.cash_bank_account, "debit": self.base_paid_amount, "debit_in_account_currency": self.base_paid_amount \ if self.party_account_currency==self.company_currency else self.paid_amount, "against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name, "against_voucher_type": self.doctype, "cost_center": self.cost_center }, self.party_account_currency) ) gl_entries.append( self.get_gl_dict({ "account": self.cash_bank_account, "against": self.supplier, "credit": self.base_paid_amount, "credit_in_account_currency": self.base_paid_amount \ if bank_account_currency==self.company_currency else self.paid_amount, "cost_center": self.cost_center }, bank_account_currency) )
def set_account_currency(filters): if filters.get("account") or (filters.get('party') and len(filters.party) == 1): filters["company_currency"] = dataent.get_cached_value( 'Company', filters.company, "default_currency") account_currency = None if filters.get("account"): account_currency = get_account_currency(filters.account) elif filters.get("party"): gle_currency = dataent.db.get_value( "GL Entry", { "party_type": filters.party_type, "party": filters.party[0], "company": filters.company }, "account_currency") if gle_currency: account_currency = gle_currency else: account_currency = (None if filters.party_type in [ "Employee", "Student", "Shareholder", "Member" ] else dataent.db.get_value( filters.party_type, filters.party[0], "default_currency")) filters[ "account_currency"] = account_currency or filters.company_currency if filters.account_currency != filters.company_currency and not filters.presentation_currency: filters.presentation_currency = filters.account_currency return filters
def create_payment_entry(self, submit=True): """create entry""" dataent.flags.ignore_account_permission = True ref_doc = dataent.get_doc(self.reference_doctype, self.reference_name) if self.reference_doctype == "Sales Invoice": party_account = ref_doc.debit_to elif self.reference_doctype == "Purchase Invoice": party_account = ref_doc.credit_to else: party_account = get_party_account("Customer", ref_doc.get("customer"), ref_doc.company) party_account_currency = ref_doc.get( "party_account_currency") or get_account_currency(party_account) bank_amount = self.grand_total if party_account_currency == ref_doc.company_currency and party_account_currency != self.currency: party_amount = ref_doc.base_grand_total else: party_amount = self.grand_total payment_entry = get_payment_entry(self.reference_doctype, self.reference_name, party_amount=party_amount, bank_account=self.payment_account, bank_amount=bank_amount) payment_entry.update({ "reference_no": self.name, "reference_date": nowdate(), "remarks": "Payment Entry against {0} {1} via Payment Request {2}".format( self.reference_doctype, self.reference_name, self.name) }) if payment_entry.difference_amount: company_details = get_company_defaults(ref_doc.company) payment_entry.append( "deductions", { "account": company_details.exchange_gain_loss_account, "cost_center": company_details.cost_center, "amount": payment_entry.difference_amount }) if submit: payment_entry.insert(ignore_permissions=True) payment_entry.submit() return payment_entry
def validate_currency(self): company_currency = epaas.get_company_currency(self.company) account_currency = get_account_currency(self.account) if not self.account_currency: self.account_currency = company_currency if account_currency != self.account_currency: dataent.throw(_("{0} {1}: Accounting Entry for {2} can only be made in currency: {3}") .format(self.voucher_type, self.voucher_no, self.account, (account_currency or company_currency)), InvalidAccountCurrency) if self.party_type and self.party: validate_party_gle_currency(self.party_type, self.party, self.company, self.account_currency)
def validate_account_head(self): closing_account_type = dataent.db.get_value("Account", self.closing_account_head, "root_type") if closing_account_type not in ["Liability", "Equity"]: dataent.throw( _("Closing Account {0} must be of type Liability / Equity"). format(self.closing_account_head)) account_currency = get_account_currency(self.closing_account_head) company_currency = dataent.get_cached_value('Company', self.company, "default_currency") if account_currency != company_currency: dataent.throw( _("Currency of the Closing Account must be {0}").format( company_currency))
def _book_deferred_revenue_or_expense(item): start_date, end_date, last_gl_entry = get_booking_dates(doc, item, posting_date=posting_date) if not (start_date and end_date): return account_currency = get_account_currency(item.expense_account) if doc.doctype == "Sales Invoice": against, project = doc.customer, doc.project credit_account, debit_account = item.income_account, item.deferred_revenue_account else: against, project = doc.supplier, item.project credit_account, debit_account = item.deferred_expense_account, item.expense_account total_days = date_diff(item.service_end_date, item.service_start_date) + 1 total_booking_days = date_diff(end_date, start_date) + 1 amount, base_amount = calculate_amount(doc, item, last_gl_entry, total_days, total_booking_days, account_currency) make_gl_entries(doc, credit_account, debit_account, against, amount, base_amount, end_date, project, account_currency, item.cost_center, item.name) if getdate(end_date) < getdate(posting_date) and not last_gl_entry: _book_deferred_revenue_or_expense(item)
def make_tax_gl_entries(self, gl_entries): # tax table gl entries valuation_tax = {} for tax in self.get("taxes"): if tax.category in ("Total", "Valuation and Total") and flt(tax.base_tax_amount_after_discount_amount): account_currency = get_account_currency(tax.account_head) dr_or_cr = "debit" if tax.add_deduct_tax == "Add" else "credit" gl_entries.append( self.get_gl_dict({ "account": tax.account_head, "against": self.supplier, dr_or_cr: tax.base_tax_amount_after_discount_amount, dr_or_cr + "_in_account_currency": tax.base_tax_amount_after_discount_amount \ if account_currency==self.company_currency \ else tax.tax_amount_after_discount_amount, "cost_center": tax.cost_center }, account_currency) ) # accumulate valuation tax if self.is_opening == "No" and tax.category in ("Valuation", "Valuation and Total") and flt(tax.base_tax_amount_after_discount_amount): if self.auto_accounting_for_stock and not tax.cost_center: dataent.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.base_tax_amount_after_discount_amount) if self.is_opening == "No" and self.negative_expense_to_be_booked and valuation_tax: # credit valuation tax amount in "Expenses Included In Valuation" # this will balance out valuation amount included in cost of goods sold total_valuation_amount = sum(valuation_tax.values()) amount_including_divisional_loss = self.negative_expense_to_be_booked i = 1 for cost_center, amount in iteritems(valuation_tax): if i == len(valuation_tax): applicable_amount = amount_including_divisional_loss else: applicable_amount = self.negative_expense_to_be_booked * (amount / total_valuation_amount) amount_including_divisional_loss -= applicable_amount gl_entries.append( self.get_gl_dict({ "account": self.expenses_included_in_valuation, "cost_center": cost_center, "against": self.supplier, "credit": applicable_amount, "remarks": self.remarks or "Accounting Entry for Stock" }) ) i += 1 if self.auto_accounting_for_stock and self.update_stock and valuation_tax: for cost_center, amount in iteritems(valuation_tax): gl_entries.append( self.get_gl_dict({ "account": self.expenses_included_in_valuation, "cost_center": cost_center, "against": self.supplier, "credit": amount, "remarks": self.remarks or "Accounting Entry for Stock" }) )
def get_asset_gl_entry(self, gl_entries): for item in self.get("items"): if item.is_fixed_asset: eiiav_account = self.get_company_default("expenses_included_in_asset_valuation") asset_amount = flt(item.net_amount) + flt(item.item_tax_amount/self.conversion_rate) base_asset_amount = flt(item.base_net_amount + item.item_tax_amount) if (not item.expense_account or dataent.db.get_value('Account', item.expense_account, 'account_type') not in ['Asset Received But Not Billed', 'Fixed Asset']): arbnb_account = self.get_company_default("asset_received_but_not_billed") item.expense_account = arbnb_account if not self.update_stock: asset_rbnb_currency = get_account_currency(item.expense_account) gl_entries.append(self.get_gl_dict({ "account": item.expense_account, "against": self.supplier, "remarks": self.get("remarks") or _("Accounting Entry for Asset"), "debit": base_asset_amount, "debit_in_account_currency": (base_asset_amount if asset_rbnb_currency == self.company_currency else asset_amount), "cost_center": item.cost_center })) if item.item_tax_amount: asset_eiiav_currency = get_account_currency(eiiav_account) gl_entries.append(self.get_gl_dict({ "account": eiiav_account, "against": self.supplier, "remarks": self.get("remarks") or _("Accounting Entry for Asset"), "cost_center": item.cost_center, "credit": item.item_tax_amount, "credit_in_account_currency": (item.item_tax_amount if asset_eiiav_currency == self.company_currency else item.item_tax_amount / self.conversion_rate) })) else: cwip_account = get_asset_account("capital_work_in_progress_account", item.asset, company = self.company) cwip_account_currency = get_account_currency(cwip_account) gl_entries.append(self.get_gl_dict({ "account": cwip_account, "against": self.supplier, "remarks": self.get("remarks") or _("Accounting Entry for Asset"), "debit": base_asset_amount, "debit_in_account_currency": (base_asset_amount if cwip_account_currency == self.company_currency else asset_amount), "cost_center": self.cost_center })) if item.item_tax_amount and not cint(epaas.is_perpetual_inventory_enabled(self.company)): asset_eiiav_currency = get_account_currency(eiiav_account) gl_entries.append(self.get_gl_dict({ "account": eiiav_account, "against": self.supplier, "remarks": self.get("remarks") or _("Accounting Entry for Asset"), "cost_center": item.cost_center, "credit": item.item_tax_amount, "credit_in_account_currency": (item.item_tax_amount if asset_eiiav_currency == self.company_currency else item.item_tax_amount / self.conversion_rate) })) return gl_entries
def make_item_gl_entries(self, gl_entries): # item gl entries stock_items = self.get_stock_items() expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation") if self.update_stock and self.auto_accounting_for_stock: warehouse_account = get_warehouse_account_map(self.company) voucher_wise_stock_value = {} if self.update_stock: for d in dataent.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) for item in self.get("items"): if flt(item.base_net_amount): account_currency = get_account_currency(item.expense_account) if self.update_stock and self.auto_accounting_for_stock and item.item_code in stock_items: # warehouse account warehouse_debit_amount = self.make_stock_adjustment_entry(gl_entries, item, voucher_wise_stock_value, account_currency) gl_entries.append( self.get_gl_dict({ "account": item.expense_account, "against": self.supplier, "debit": warehouse_debit_amount, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "cost_center": item.cost_center, "project": item.project }, account_currency) ) # Amount added through landed-cost-voucher if flt(item.landed_cost_voucher_amount): gl_entries.append(self.get_gl_dict({ "account": expenses_included_in_valuation, "against": item.expense_account, "cost_center": item.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "credit": flt(item.landed_cost_voucher_amount), "project": item.project })) # sub-contracting warehouse if flt(item.rm_supp_cost): supplier_warehouse_account = warehouse_account[self.supplier_warehouse]["account"] if not supplier_warehouse_account: dataent.throw(_("Please set account in Warehouse {0}") .format(self.supplier_warehouse)) gl_entries.append(self.get_gl_dict({ "account": supplier_warehouse_account, "against": item.expense_account, "cost_center": item.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "credit": flt(item.rm_supp_cost) }, warehouse_account[self.supplier_warehouse]["account_currency"])) elif not item.is_fixed_asset or (item.is_fixed_asset and is_cwip_accounting_disabled()): gl_entries.append( self.get_gl_dict({ "account": item.expense_account if not item.enable_deferred_expense else item.deferred_expense_account, "against": self.supplier, "debit": flt(item.base_net_amount, item.precision("base_net_amount")), "debit_in_account_currency": (flt(item.base_net_amount, item.precision("base_net_amount")) if account_currency==self.company_currency else flt(item.net_amount, item.precision("net_amount"))), "cost_center": item.cost_center, "project": item.project }, account_currency) ) if self.auto_accounting_for_stock and self.is_opening == "No" and \ item.item_code in stock_items and item.item_tax_amount: # Post reverse entry for Stock-Received-But-Not-Billed if it is booked in Purchase Receipt if item.purchase_receipt: negative_expense_booked_in_pr = dataent.db.sql("""select name from `tabGL Entry` where voucher_type='Purchase Receipt' and voucher_no=%s and account=%s""", (item.purchase_receipt, self.expenses_included_in_valuation)) if not negative_expense_booked_in_pr: gl_entries.append( self.get_gl_dict({ "account": self.stock_received_but_not_billed, "against": self.supplier, "debit": flt(item.item_tax_amount, item.precision("item_tax_amount")), "remarks": self.remarks or "Accounting Entry for Stock", "cost_center": self.cost_center }) ) self.negative_expense_to_be_booked += flt(item.item_tax_amount, \ item.precision("item_tax_amount"))
def get_gl_entries(self, warehouse_account=None): from epaas.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): stock_value_diff = dataent.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"])) # 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)) 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]["account"], "cost_center": d.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "credit": flt(d.landed_cost_voucher_amount), "project": d.project })) # 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"])) # 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)) 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 not is_cwip_accounting_disabled(): 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: dataent.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.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" negative_expense_booked_in_pi = dataent.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 iteritems(valuation_tax): 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: dataent.msgprint( _("No accounting entries for the following warehouses") + ": \n" + "\n".join(warehouse_with_no_account)) return process_gl_map(gl_entries)