Beispiel #1
0
    def add_asset_gl_entries(self, item, gl_entries):
        arbnb_account = self.get_company_default(
            "asset_received_but_not_billed")
        # This returns category's cwip account if not then fallback to company's default cwip account
        cwip_account = get_asset_account("capital_work_in_progress_account", asset_category = item.asset_category, \
         company = self.company)

        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)

        cwip_account_currency = get_account_currency(cwip_account)
        # debit cwip account
        gl_entries.append(
            self.get_gl_dict(
                {
                    "account":
                    cwip_account,
                    "against":
                    arbnb_account,
                    "cost_center":
                    item.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)
                },
                item=item))

        asset_rbnb_currency = get_account_currency(arbnb_account)
        # credit arbnb account
        gl_entries.append(
            self.get_gl_dict(
                {
                    "account":
                    arbnb_account,
                    "against":
                    cwip_account,
                    "cost_center":
                    item.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)
                },
                item=item))
Beispiel #2
0
def set_account_currency(filters):
	if filters.get("account") or (filters.get('party') and len(filters.party) == 1):
		filters["company_currency"] = frappe.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 = frappe.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
					frappe.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
Beispiel #3
0
def make_regional_gl_entries(gl_entries, doc):
	country = frappe.get_cached_value('Company', doc.company, 'country')

	if country != 'India':
		return gl_entries

	if doc.reverse_charge == 'Y':
		gst_accounts = get_gst_accounts(doc.company)
		gst_account_list = gst_accounts.get('cgst_account') + gst_accounts.get('sgst_account') \
			+ gst_accounts.get('igst_account')

		for tax in doc.get('taxes'):
			if tax.category not in ("Total", "Valuation and Total"):
				continue

			dr_or_cr = "credit" if tax.add_deduct_tax == "Add" else "debit"
			if flt(tax.base_tax_amount_after_discount_amount) and tax.account_head in gst_account_list:
				account_currency = get_account_currency(tax.account_head)

				gl_entries.append(doc.get_gl_dict(
					{
						"account": tax.account_head,
						"cost_center": tax.cost_center,
						"posting_date": doc.posting_date,
						"against": doc.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==doc.company_currency \
							else tax.tax_amount_after_discount_amount
					}, account_currency, item=tax)
				)

	return gl_entries
Beispiel #4
0
    def create_payment_entry(self, submit=True):
        """create entry"""
        frappe.flags.ignore_account_permission = True

        ref_doc = frappe.get_doc(self.reference_doctype, self.reference_name)

        if self.reference_doctype in ["Sales Invoice", "POS 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
Beispiel #5
0
    def _book_deferred_revenue_or_expense(item, via_journal_entry,
                                          submit_journal_entry,
                                          book_deferred_entries_based_on):
        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

        if book_deferred_entries_based_on == 'Months':
            amount, base_amount = calculate_monthly_amount(
                doc, item, last_gl_entry, start_date, end_date, total_days,
                total_booking_days, account_currency)
        else:
            amount, base_amount = calculate_amount(doc, item, last_gl_entry,
                                                   total_days,
                                                   total_booking_days,
                                                   account_currency)

        if via_journal_entry:
            book_revenue_via_journal_entry(doc, credit_account, debit_account,
                                           against, amount, base_amount,
                                           end_date, project, account_currency,
                                           item.cost_center, item,
                                           deferred_process,
                                           submit_journal_entry)
        else:
            make_gl_entries(doc, credit_account, debit_account, against,
                            amount, base_amount, end_date, project,
                            account_currency, item.cost_center, item,
                            deferred_process)

        # Returned in case of any errors because it tries to submit the same record again and again in case of errors
        if frappe.flags.deferred_accounting_error:
            return

        if getdate(end_date) < getdate(posting_date) and not last_gl_entry:
            _book_deferred_revenue_or_expense(item, via_journal_entry,
                                              submit_journal_entry,
                                              book_deferred_entries_based_on)
    def validate_account_head(self):
        closing_account_type = frappe.db.get_value("Account",
                                                   self.closing_account_head,
                                                   "root_type")

        if closing_account_type not in ["Liability", "Equity"]:
            frappe.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 = frappe.get_cached_value('Company', self.company,
                                                   "default_currency")
        if account_currency != company_currency:
            frappe.throw(
                _("Currency of the Closing Account must be {0}").format(
                    company_currency))
Beispiel #7
0
    def validate_currency(self):
        company_currency = erpbee.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:
            frappe.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)
Beispiel #8
0
    def get_gl_entries(self, warehouse_account=None):
        from erpbee.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")
        auto_accounting_for_non_stock_items = cint(
            frappe.db.get_value(
                'Company', self.company,
                'enable_perpetual_inventory_for_non_stock_items'))

        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

                    # If PR is sub-contracted and fg item rate is zero
                    # in that case if account for shource and target warehouse are same,
                    # then GL entries should not be posted
                    if flt(stock_value_diff) == flt(d.rm_supp_cost) \
                     and warehouse_account.get(self.supplier_warehouse) \
                     and warehouse_account[d.warehouse]["account"] == warehouse_account[self.supplier_warehouse]["account"]:
                        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))

                    # GL Entry for from warehouse or Stock Received but not billed
                    # Intentionally passed negative debit amount to avoid incorrect GL Entry validation
                    credit_currency = get_account_currency(warehouse_account[d.from_warehouse]['account']) \
                     if d.from_warehouse else get_account_currency(stock_rbnb)

                    credit_amount = flt(d.base_net_amount, d.precision("base_net_amount")) \
                     if credit_currency == self.company_currency else flt(d.net_amount, d.precision("net_amount"))
                    if credit_amount:
                        gl_entries.append(self.get_gl_dict({
                         "account":  warehouse_account[d.from_warehouse]['account'] \
                          if d.from_warehouse else stock_rbnb,
                         "against": warehouse_account[d.warehouse]["account"],
                         "cost_center": d.cost_center,
                         "remarks": self.get("remarks") or _("Accounting Entry for Stock"),
                         "debit": -1 * flt(d.base_net_amount, d.precision("base_net_amount")),
                         "debit_in_account_currency": -1 * credit_amount
                        }, credit_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 = self.get_company_default(
                                "default_expense_account")

                        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
                                },
                                credit_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)
            elif d.item_code not in stock_items and not d.is_fixed_asset and flt(
                    d.qty) and auto_accounting_for_non_stock_items:

                service_received_but_not_billed_account = self.get_company_default(
                    "service_received_but_not_billed")
                credit_currency = get_account_currency(
                    service_received_but_not_billed_account)

                gl_entries.append(
                    self.get_gl_dict(
                        {
                            "account":
                            service_received_but_not_billed_account,
                            "against":
                            d.expense_account,
                            "cost_center":
                            d.cost_center,
                            "remarks":
                            self.get("remarks")
                            or _("Accounting Entry for Service"),
                            "project":
                            d.project,
                            "credit":
                            d.amount,
                            "voucher_detail_no":
                            d.name
                        },
                        credit_currency,
                        item=d))

                debit_currency = get_account_currency(d.expense_account)

                gl_entries.append(
                    self.get_gl_dict(
                        {
                            "account":
                            d.expense_account,
                            "against":
                            service_received_but_not_billed_account,
                            "cost_center":
                            d.cost_center,
                            "remarks":
                            self.get("remarks")
                            or _("Accounting Entry for Service"),
                            "project":
                            d.project,
                            "debit":
                            d.amount,
                            "voucher_detail_no":
                            d.name
                        },
                        debit_currency,
                        item=d))

        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)