fix: Accounting for internal transfer invoices within same company
This commit is contained in:
@@ -15,6 +15,16 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
|
|||||||
return (doc.qty<=doc.received_qty) ? "green" : "orange";
|
return (doc.qty<=doc.received_qty) ? "green" : "orange";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.frm.set_query("inter_company_account", function() {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
company: doc.company,
|
||||||
|
is_group: 0,
|
||||||
|
root_type: "Liability",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
company: function() {
|
company: function() {
|
||||||
|
|||||||
@@ -126,6 +126,7 @@
|
|||||||
"write_off_cost_center",
|
"write_off_cost_center",
|
||||||
"advances_section",
|
"advances_section",
|
||||||
"allocate_advances_automatically",
|
"allocate_advances_automatically",
|
||||||
|
"adjust_advance_taxes",
|
||||||
"get_advances",
|
"get_advances",
|
||||||
"advances",
|
"advances",
|
||||||
"payment_schedule_section",
|
"payment_schedule_section",
|
||||||
@@ -151,9 +152,11 @@
|
|||||||
"is_opening",
|
"is_opening",
|
||||||
"against_expense_account",
|
"against_expense_account",
|
||||||
"column_break_63",
|
"column_break_63",
|
||||||
|
"inter_company_account",
|
||||||
"status",
|
"status",
|
||||||
"inter_company_invoice_reference",
|
"inter_company_invoice_reference",
|
||||||
"is_internal_supplier",
|
"is_internal_supplier",
|
||||||
|
"represents_company",
|
||||||
"remarks",
|
"remarks",
|
||||||
"subscription_section",
|
"subscription_section",
|
||||||
"from_date",
|
"from_date",
|
||||||
@@ -1222,7 +1225,7 @@
|
|||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "Status",
|
"label": "Status",
|
||||||
"options": "\nDraft\nReturn\nDebit Note Issued\nSubmitted\nPaid\nUnpaid\nOverdue\nCancelled",
|
"options": "\nDraft\nReturn\nDebit Note Issued\nSubmitted\nPaid\nUnpaid\nOverdue\nCancelled\nInternal Transfer",
|
||||||
"print_hide": 1
|
"print_hide": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1329,12 +1332,35 @@
|
|||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Project",
|
"label": "Project",
|
||||||
"options": "Project"
|
"options": "Project"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"description": "Taxes paid while advance payment will be adjusted against this invoice",
|
||||||
|
"fieldname": "adjust_advance_taxes",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Adjust Advance Taxes"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:doc.is_internal_supplier",
|
||||||
|
"fieldname": "inter_company_account",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Inter Company Account",
|
||||||
|
"options": "Account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:doc.is_internal_supplier",
|
||||||
|
"fetch_from": "supplier.represents_company",
|
||||||
|
"fieldname": "represents_company",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Represents Company",
|
||||||
|
"options": "Company"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-file-text",
|
"icon": "fa fa-file-text",
|
||||||
"idx": 204,
|
"idx": 204,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"modified": "2020-09-21 12:22:09.164068",
|
"links": [],
|
||||||
|
"modified": "2020-11-27 19:47:04.827315",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Purchase Invoice",
|
"name": "Purchase Invoice",
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.set_status()
|
self.set_status()
|
||||||
self.validate_purchase_receipt_if_update_stock()
|
self.validate_purchase_receipt_if_update_stock()
|
||||||
validate_inter_company_party(self.doctype, self.supplier, self.company, self.inter_company_invoice_reference)
|
validate_inter_company_party(self.doctype, self.supplier, self.company, self.inter_company_invoice_reference)
|
||||||
|
self.set_inter_company_account()
|
||||||
|
|
||||||
def validate_release_date(self):
|
def validate_release_date(self):
|
||||||
if self.release_date and getdate(nowdate()) >= getdate(self.release_date):
|
if self.release_date and getdate(nowdate()) >= getdate(self.release_date):
|
||||||
@@ -371,6 +372,26 @@ class PurchaseInvoice(BuyingController):
|
|||||||
where name=`tabPurchase Invoice Item`.parent and update_stock=1 and is_return=1)"""
|
where name=`tabPurchase Invoice Item`.parent and update_stock=1 and is_return=1)"""
|
||||||
})
|
})
|
||||||
|
|
||||||
|
def set_inter_company_account(self):
|
||||||
|
"""
|
||||||
|
Set intercompany account for inter warehouse transactions
|
||||||
|
This account will be used in case billing company and internal supplier's
|
||||||
|
representation company is same
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.is_internal_transfer() and not self.inter_company_account:
|
||||||
|
self.inter_company_account = frappe.get_cached_value('Company', self.company, 'default_inter_company_account')
|
||||||
|
|
||||||
|
def is_internal_transfer(self):
|
||||||
|
"""
|
||||||
|
It will an internal transfer if its an internal supplier and representation
|
||||||
|
company is same as billing company
|
||||||
|
"""
|
||||||
|
if self.is_internal_supplier and (self.represents_company == self.company):
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
def validate_purchase_receipt_if_update_stock(self):
|
def validate_purchase_receipt_if_update_stock(self):
|
||||||
if self.update_stock:
|
if self.update_stock:
|
||||||
for item in self.get("items"):
|
for item in self.get("items"):
|
||||||
@@ -444,6 +465,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.get_asset_gl_entry(gl_entries)
|
self.get_asset_gl_entry(gl_entries)
|
||||||
|
|
||||||
self.make_tax_gl_entries(gl_entries)
|
self.make_tax_gl_entries(gl_entries)
|
||||||
|
self.make_internal_transfer_gl_entries(gl_entries)
|
||||||
|
|
||||||
gl_entries = make_regional_gl_entries(gl_entries, self)
|
gl_entries = make_regional_gl_entries(gl_entries, self)
|
||||||
|
|
||||||
@@ -469,211 +491,212 @@ class PurchaseInvoice(BuyingController):
|
|||||||
# because rounded_total had value even before introcution of posting GLE based on rounded total
|
# because rounded_total had value even before introcution of posting GLE based on rounded total
|
||||||
grand_total = self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total
|
grand_total = self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total
|
||||||
|
|
||||||
if grand_total:
|
if grand_total and not self.is_internal_transfer():
|
||||||
# Didnot use base_grand_total to book rounding loss gle
|
# Didnot use base_grand_total to book rounding loss gle
|
||||||
grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
|
grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
|
||||||
self.precision("grand_total"))
|
self.precision("grand_total"))
|
||||||
gl_entries.append(
|
gl_entries.append(
|
||||||
self.get_gl_dict({
|
self.get_gl_dict({
|
||||||
"account": self.credit_to,
|
"account": self.credit_to,
|
||||||
"party_type": "Supplier",
|
"party_type": "Supplier",
|
||||||
"party": self.supplier,
|
"party": self.supplier,
|
||||||
"due_date": self.due_date,
|
"due_date": self.due_date,
|
||||||
"against": self.against_expense_account,
|
"against": self.against_expense_account,
|
||||||
"credit": grand_total_in_company_currency,
|
"credit": grand_total_in_company_currency,
|
||||||
"credit_in_account_currency": grand_total_in_company_currency \
|
"credit_in_account_currency": grand_total_in_company_currency \
|
||||||
if self.party_account_currency==self.company_currency else grand_total,
|
if self.party_account_currency==self.company_currency else grand_total,
|
||||||
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
|
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
|
||||||
"against_voucher_type": self.doctype,
|
"against_voucher_type": self.doctype,
|
||||||
"project": self.project,
|
"project": self.project,
|
||||||
"cost_center": self.cost_center
|
"cost_center": self.cost_center
|
||||||
}, self.party_account_currency, item=self)
|
}, self.party_account_currency, item=self)
|
||||||
)
|
)
|
||||||
|
|
||||||
def make_item_gl_entries(self, gl_entries):
|
def make_item_gl_entries(self, gl_entries):
|
||||||
# item gl entries
|
# item gl entries
|
||||||
stock_items = self.get_stock_items()
|
if not self.is_internal_transfer():
|
||||||
expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
|
stock_items = self.get_stock_items()
|
||||||
if self.update_stock and self.auto_accounting_for_stock:
|
expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
|
||||||
warehouse_account = get_warehouse_account_map(self.company)
|
if self.update_stock and self.auto_accounting_for_stock:
|
||||||
|
warehouse_account = get_warehouse_account_map(self.company)
|
||||||
|
|
||||||
landed_cost_entries = get_item_account_wise_additional_cost(self.name)
|
landed_cost_entries = get_item_account_wise_additional_cost(self.name)
|
||||||
|
|
||||||
voucher_wise_stock_value = {}
|
voucher_wise_stock_value = {}
|
||||||
if self.update_stock:
|
if self.update_stock:
|
||||||
for d in frappe.get_all('Stock Ledger Entry',
|
for d in frappe.get_all('Stock Ledger Entry',
|
||||||
fields = ["voucher_detail_no", "stock_value_difference"], filters={'voucher_no': self.name}):
|
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)
|
voucher_wise_stock_value.setdefault(d.voucher_detail_no, d.stock_value_difference)
|
||||||
|
|
||||||
valuation_tax_accounts = [d.account_head for d in self.get("taxes")
|
valuation_tax_accounts = [d.account_head for d in self.get("taxes")
|
||||||
if d.category in ('Valuation', 'Total and Valuation')
|
if d.category in ('Valuation', 'Total and Valuation')
|
||||||
and flt(d.base_tax_amount_after_discount_amount)]
|
and flt(d.base_tax_amount_after_discount_amount)]
|
||||||
|
|
||||||
for item in self.get("items"):
|
for item in self.get("items"):
|
||||||
if flt(item.base_net_amount):
|
if flt(item.base_net_amount):
|
||||||
account_currency = get_account_currency(item.expense_account)
|
account_currency = get_account_currency(item.expense_account)
|
||||||
if item.item_code:
|
if item.item_code:
|
||||||
asset_category = frappe.get_cached_value("Item", item.item_code, "asset_category")
|
asset_category = frappe.get_cached_value("Item", item.item_code, "asset_category")
|
||||||
|
|
||||||
if self.update_stock and self.auto_accounting_for_stock and item.item_code in stock_items:
|
if self.update_stock and self.auto_accounting_for_stock and item.item_code in stock_items:
|
||||||
# warehouse account
|
# warehouse account
|
||||||
warehouse_debit_amount = self.make_stock_adjustment_entry(gl_entries,
|
warehouse_debit_amount = self.make_stock_adjustment_entry(gl_entries,
|
||||||
item, voucher_wise_stock_value, account_currency)
|
item, voucher_wise_stock_value, account_currency)
|
||||||
|
|
||||||
if item.from_warehouse:
|
if item.from_warehouse:
|
||||||
|
|
||||||
gl_entries.append(self.get_gl_dict({
|
|
||||||
"account": warehouse_account[item.warehouse]['account'],
|
|
||||||
"against": warehouse_account[item.from_warehouse]["account"],
|
|
||||||
"cost_center": item.cost_center,
|
|
||||||
"project": item.project or self.project,
|
|
||||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
|
||||||
"debit": warehouse_debit_amount,
|
|
||||||
}, warehouse_account[item.warehouse]["account_currency"], item=item))
|
|
||||||
|
|
||||||
# Intentionally passed negative debit amount to avoid incorrect GL Entry validation
|
|
||||||
gl_entries.append(self.get_gl_dict({
|
|
||||||
"account": warehouse_account[item.from_warehouse]['account'],
|
|
||||||
"against": warehouse_account[item.warehouse]["account"],
|
|
||||||
"cost_center": item.cost_center,
|
|
||||||
"project": item.project or self.project,
|
|
||||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
|
||||||
"debit": -1 * flt(item.base_net_amount, item.precision("base_net_amount")),
|
|
||||||
}, warehouse_account[item.from_warehouse]["account_currency"], item=item))
|
|
||||||
|
|
||||||
gl_entries.append(
|
|
||||||
self.get_gl_dict({
|
|
||||||
"account": item.expense_account,
|
|
||||||
"against": self.supplier,
|
|
||||||
"debit": flt(item.base_net_amount, item.precision("base_net_amount")),
|
|
||||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
|
||||||
"cost_center": item.cost_center,
|
|
||||||
"project": item.project
|
|
||||||
}, account_currency, item=item)
|
|
||||||
)
|
|
||||||
|
|
||||||
else:
|
|
||||||
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 or self.project
|
|
||||||
}, account_currency, item=item)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Amount added through landed-cost-voucher
|
|
||||||
if landed_cost_entries:
|
|
||||||
for account, amount in iteritems(landed_cost_entries[(item.item_code, item.name)]):
|
|
||||||
gl_entries.append(self.get_gl_dict({
|
gl_entries.append(self.get_gl_dict({
|
||||||
"account": account,
|
"account": warehouse_account[item.warehouse]['account'],
|
||||||
|
"against": warehouse_account[item.from_warehouse]["account"],
|
||||||
|
"cost_center": item.cost_center,
|
||||||
|
"project": item.project or self.project,
|
||||||
|
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||||
|
"debit": warehouse_debit_amount,
|
||||||
|
}, warehouse_account[item.warehouse]["account_currency"], item=item))
|
||||||
|
|
||||||
|
# Intentionally passed negative debit amount to avoid incorrect GL Entry validation
|
||||||
|
gl_entries.append(self.get_gl_dict({
|
||||||
|
"account": warehouse_account[item.from_warehouse]['account'],
|
||||||
|
"against": warehouse_account[item.warehouse]["account"],
|
||||||
|
"cost_center": item.cost_center,
|
||||||
|
"project": item.project or self.project,
|
||||||
|
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||||
|
"debit": -1 * flt(item.base_net_amount, item.precision("base_net_amount")),
|
||||||
|
}, warehouse_account[item.from_warehouse]["account_currency"], item=item))
|
||||||
|
|
||||||
|
gl_entries.append(
|
||||||
|
self.get_gl_dict({
|
||||||
|
"account": item.expense_account,
|
||||||
|
"against": self.supplier,
|
||||||
|
"debit": flt(item.base_net_amount, item.precision("base_net_amount")),
|
||||||
|
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||||
|
"cost_center": item.cost_center,
|
||||||
|
"project": item.project
|
||||||
|
}, account_currency, item=item)
|
||||||
|
)
|
||||||
|
|
||||||
|
else:
|
||||||
|
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 or self.project
|
||||||
|
}, account_currency, item=item)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Amount added through landed-cost-voucher
|
||||||
|
if landed_cost_entries:
|
||||||
|
for account, amount in iteritems(landed_cost_entries[(item.item_code, item.name)]):
|
||||||
|
gl_entries.append(self.get_gl_dict({
|
||||||
|
"account": account,
|
||||||
|
"against": item.expense_account,
|
||||||
|
"cost_center": item.cost_center,
|
||||||
|
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||||
|
"credit": flt(amount),
|
||||||
|
"project": item.project or self.project
|
||||||
|
}, item=item))
|
||||||
|
|
||||||
|
# sub-contracting warehouse
|
||||||
|
if flt(item.rm_supp_cost):
|
||||||
|
supplier_warehouse_account = warehouse_account[self.supplier_warehouse]["account"]
|
||||||
|
if not supplier_warehouse_account:
|
||||||
|
frappe.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,
|
"against": item.expense_account,
|
||||||
"cost_center": item.cost_center,
|
"cost_center": item.cost_center,
|
||||||
|
"project": item.project or self.project,
|
||||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||||
"credit": flt(amount),
|
"credit": flt(item.rm_supp_cost)
|
||||||
|
}, warehouse_account[self.supplier_warehouse]["account_currency"], item=item))
|
||||||
|
|
||||||
|
elif not item.is_fixed_asset or (item.is_fixed_asset and not is_cwip_accounting_enabled(asset_category)):
|
||||||
|
expense_account = (item.expense_account
|
||||||
|
if (not item.enable_deferred_expense or self.is_return) else item.deferred_expense_account)
|
||||||
|
|
||||||
|
if not item.is_fixed_asset:
|
||||||
|
amount = flt(item.base_net_amount, item.precision("base_net_amount"))
|
||||||
|
else:
|
||||||
|
amount = flt(item.base_net_amount + item.item_tax_amount, item.precision("base_net_amount"))
|
||||||
|
|
||||||
|
auto_accounting_for_non_stock_items = cint(frappe.db.get_value('Company', self.company, 'enable_perpetual_inventory_for_non_stock_items'))
|
||||||
|
|
||||||
|
if auto_accounting_for_non_stock_items:
|
||||||
|
service_received_but_not_billed_account = self.get_company_default("service_received_but_not_billed")
|
||||||
|
|
||||||
|
if item.purchase_receipt:
|
||||||
|
# Post reverse entry for Stock-Received-But-Not-Billed if it is booked in Purchase Receipt
|
||||||
|
expense_booked_in_pr = frappe.db.get_value('GL Entry', {'is_cancelled': 0,
|
||||||
|
'voucher_type': 'Purchase Receipt', 'voucher_no': item.purchase_receipt, 'voucher_detail_no': item.pr_detail,
|
||||||
|
'account':service_received_but_not_billed_account}, ['name'])
|
||||||
|
|
||||||
|
if expense_booked_in_pr:
|
||||||
|
expense_account = service_received_but_not_billed_account
|
||||||
|
|
||||||
|
gl_entries.append(self.get_gl_dict({
|
||||||
|
"account": expense_account,
|
||||||
|
"against": self.supplier,
|
||||||
|
"debit": amount,
|
||||||
|
"cost_center": item.cost_center,
|
||||||
|
"project": item.project or self.project
|
||||||
|
}, account_currency, item=item))
|
||||||
|
|
||||||
|
# If asset is bought through this document and not linked to PR
|
||||||
|
if self.update_stock and item.landed_cost_voucher_amount:
|
||||||
|
expenses_included_in_asset_valuation = self.get_company_default("expenses_included_in_asset_valuation")
|
||||||
|
# Amount added through landed-cost-voucher
|
||||||
|
gl_entries.append(self.get_gl_dict({
|
||||||
|
"account": expenses_included_in_asset_valuation,
|
||||||
|
"against": 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 or self.project
|
"project": item.project or self.project
|
||||||
}, item=item))
|
}, item=item))
|
||||||
|
|
||||||
# sub-contracting warehouse
|
gl_entries.append(self.get_gl_dict({
|
||||||
if flt(item.rm_supp_cost):
|
"account": expense_account,
|
||||||
supplier_warehouse_account = warehouse_account[self.supplier_warehouse]["account"]
|
"against": expenses_included_in_asset_valuation,
|
||||||
if not supplier_warehouse_account:
|
"cost_center": item.cost_center,
|
||||||
frappe.throw(_("Please set account in Warehouse {0}")
|
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
||||||
.format(self.supplier_warehouse))
|
"debit": flt(item.landed_cost_voucher_amount),
|
||||||
gl_entries.append(self.get_gl_dict({
|
"project": item.project or self.project
|
||||||
"account": supplier_warehouse_account,
|
}, item=item))
|
||||||
"against": item.expense_account,
|
|
||||||
"cost_center": item.cost_center,
|
|
||||||
"project": item.project or self.project,
|
|
||||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
|
||||||
"credit": flt(item.rm_supp_cost)
|
|
||||||
}, warehouse_account[self.supplier_warehouse]["account_currency"], item=item))
|
|
||||||
|
|
||||||
elif not item.is_fixed_asset or (item.is_fixed_asset and not is_cwip_accounting_enabled(asset_category)):
|
# update gross amount of asset bought through this document
|
||||||
expense_account = (item.expense_account
|
assets = frappe.db.get_all('Asset',
|
||||||
if (not item.enable_deferred_expense or self.is_return) else item.deferred_expense_account)
|
filters={ 'purchase_invoice': self.name, 'item_code': item.item_code }
|
||||||
|
|
||||||
if not item.is_fixed_asset:
|
|
||||||
amount = flt(item.base_net_amount, item.precision("base_net_amount"))
|
|
||||||
else:
|
|
||||||
amount = flt(item.base_net_amount + item.item_tax_amount, item.precision("base_net_amount"))
|
|
||||||
|
|
||||||
auto_accounting_for_non_stock_items = cint(frappe.db.get_value('Company', self.company, 'enable_perpetual_inventory_for_non_stock_items'))
|
|
||||||
|
|
||||||
if auto_accounting_for_non_stock_items:
|
|
||||||
service_received_but_not_billed_account = self.get_company_default("service_received_but_not_billed")
|
|
||||||
|
|
||||||
if item.purchase_receipt:
|
|
||||||
# Post reverse entry for Stock-Received-But-Not-Billed if it is booked in Purchase Receipt
|
|
||||||
expense_booked_in_pr = frappe.db.get_value('GL Entry', {'is_cancelled': 0,
|
|
||||||
'voucher_type': 'Purchase Receipt', 'voucher_no': item.purchase_receipt, 'voucher_detail_no': item.pr_detail,
|
|
||||||
'account':service_received_but_not_billed_account}, ['name'])
|
|
||||||
|
|
||||||
if expense_booked_in_pr:
|
|
||||||
expense_account = service_received_but_not_billed_account
|
|
||||||
|
|
||||||
gl_entries.append(self.get_gl_dict({
|
|
||||||
"account": expense_account,
|
|
||||||
"against": self.supplier,
|
|
||||||
"debit": amount,
|
|
||||||
"cost_center": item.cost_center,
|
|
||||||
"project": item.project or self.project
|
|
||||||
}, account_currency, item=item))
|
|
||||||
|
|
||||||
# If asset is bought through this document and not linked to PR
|
|
||||||
if self.update_stock and item.landed_cost_voucher_amount:
|
|
||||||
expenses_included_in_asset_valuation = self.get_company_default("expenses_included_in_asset_valuation")
|
|
||||||
# Amount added through landed-cost-voucher
|
|
||||||
gl_entries.append(self.get_gl_dict({
|
|
||||||
"account": expenses_included_in_asset_valuation,
|
|
||||||
"against": 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 or self.project
|
|
||||||
}, item=item))
|
|
||||||
|
|
||||||
gl_entries.append(self.get_gl_dict({
|
|
||||||
"account": expense_account,
|
|
||||||
"against": expenses_included_in_asset_valuation,
|
|
||||||
"cost_center": item.cost_center,
|
|
||||||
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
|
|
||||||
"debit": flt(item.landed_cost_voucher_amount),
|
|
||||||
"project": item.project or self.project
|
|
||||||
}, item=item))
|
|
||||||
|
|
||||||
# update gross amount of asset bought through this document
|
|
||||||
assets = frappe.db.get_all('Asset',
|
|
||||||
filters={ 'purchase_invoice': self.name, 'item_code': item.item_code }
|
|
||||||
)
|
|
||||||
for asset in assets:
|
|
||||||
frappe.db.set_value("Asset", asset.name, "gross_purchase_amount", flt(item.valuation_rate))
|
|
||||||
frappe.db.set_value("Asset", asset.name, "purchase_receipt_amount", flt(item.valuation_rate))
|
|
||||||
|
|
||||||
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 and valuation_tax_accounts:
|
|
||||||
negative_expense_booked_in_pr = frappe.db.sql("""select name from `tabGL Entry`
|
|
||||||
where voucher_type='Purchase Receipt' and voucher_no=%s and account in %s""",
|
|
||||||
(item.purchase_receipt, valuation_tax_accounts))
|
|
||||||
|
|
||||||
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,
|
|
||||||
"project": item.project or self.project
|
|
||||||
}, item=item)
|
|
||||||
)
|
)
|
||||||
|
for asset in assets:
|
||||||
|
frappe.db.set_value("Asset", asset.name, "gross_purchase_amount", flt(item.valuation_rate))
|
||||||
|
frappe.db.set_value("Asset", asset.name, "purchase_receipt_amount", flt(item.valuation_rate))
|
||||||
|
|
||||||
self.negative_expense_to_be_booked += flt(item.item_tax_amount, \
|
if self.auto_accounting_for_stock and self.is_opening == "No" and \
|
||||||
item.precision("item_tax_amount"))
|
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 and valuation_tax_accounts:
|
||||||
|
negative_expense_booked_in_pr = frappe.db.sql("""select name from `tabGL Entry`
|
||||||
|
where voucher_type='Purchase Receipt' and voucher_no=%s and account in %s""",
|
||||||
|
(item.purchase_receipt, valuation_tax_accounts))
|
||||||
|
|
||||||
|
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,
|
||||||
|
"project": item.project or self.project
|
||||||
|
}, item=item)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.negative_expense_to_be_booked += flt(item.item_tax_amount, \
|
||||||
|
item.precision("item_tax_amount"))
|
||||||
|
|
||||||
def get_asset_gl_entry(self, gl_entries):
|
def get_asset_gl_entry(self, gl_entries):
|
||||||
arbnb_account = self.get_company_default("asset_received_but_not_billed")
|
arbnb_account = self.get_company_default("asset_received_but_not_billed")
|
||||||
@@ -827,7 +850,8 @@ class PurchaseInvoice(BuyingController):
|
|||||||
}, account_currency, item=tax)
|
}, account_currency, item=tax)
|
||||||
)
|
)
|
||||||
# accumulate valuation tax
|
# 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.is_opening == "No" and tax.category in ("Valuation", "Valuation and Total") and flt(tax.base_tax_amount_after_discount_amount) \
|
||||||
|
and not self.is_internal_transfer():
|
||||||
if self.auto_accounting_for_stock and not tax.cost_center:
|
if self.auto_accounting_for_stock and not tax.cost_center:
|
||||||
frappe.throw(_("Cost Center is required in row {0} in Taxes table for type {1}").format(tax.idx, _(tax.category)))
|
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.setdefault(tax.name, 0)
|
||||||
@@ -871,8 +895,19 @@ class PurchaseInvoice(BuyingController):
|
|||||||
"against": self.supplier,
|
"against": self.supplier,
|
||||||
"credit": valuation_tax[tax.name],
|
"credit": valuation_tax[tax.name],
|
||||||
"remarks": self.remarks or "Accounting Entry for Stock"
|
"remarks": self.remarks or "Accounting Entry for Stock"
|
||||||
}, item=tax)
|
}, item=tax))
|
||||||
)
|
|
||||||
|
def make_internal_transfer_gl_entries(self, gl_entries):
|
||||||
|
if self.is_internal_transfer() and flt(self.base_total_taxes_and_charges):
|
||||||
|
account_currency = get_account_currency(self.inter_company_account)
|
||||||
|
gl_entries.append(
|
||||||
|
self.get_gl_dict({
|
||||||
|
"account": self.inter_company_account,
|
||||||
|
"against": self.supplier,
|
||||||
|
"credit": flt(self.total_taxes_and_charges),
|
||||||
|
"credit_in_account_currency": flt(self.base_total_taxes_and_charges),
|
||||||
|
"cost_center": self.cost_center
|
||||||
|
}, account_currency, item=self))
|
||||||
|
|
||||||
def make_payment_gl_entries(self, gl_entries):
|
def make_payment_gl_entries(self, gl_entries):
|
||||||
# Make Cash GL Entries
|
# Make Cash GL Entries
|
||||||
@@ -1088,7 +1123,9 @@ class PurchaseInvoice(BuyingController):
|
|||||||
if self.docstatus == 2:
|
if self.docstatus == 2:
|
||||||
status = "Cancelled"
|
status = "Cancelled"
|
||||||
elif self.docstatus == 1:
|
elif self.docstatus == 1:
|
||||||
if outstanding_amount > 0 and due_date < nowdate:
|
if self.is_internal_transfer():
|
||||||
|
self.status = 'Internal Transfer'
|
||||||
|
elif outstanding_amount > 0 and due_date < nowdate:
|
||||||
self.status = "Overdue"
|
self.status = "Overdue"
|
||||||
elif outstanding_amount > 0 and due_date >= nowdate:
|
elif outstanding_amount > 0 and due_date >= nowdate:
|
||||||
self.status = "Unpaid"
|
self.status = "Unpaid"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
// render
|
// render
|
||||||
frappe.listview_settings['Purchase Invoice'] = {
|
frappe.listview_settings['Purchase Invoice'] = {
|
||||||
add_fields: ["supplier", "supplier_name", "base_grand_total", "outstanding_amount", "due_date", "company",
|
add_fields: ["supplier", "supplier_name", "base_grand_total", "outstanding_amount", "due_date", "company",
|
||||||
"currency", "is_return", "release_date", "on_hold"],
|
"currency", "is_return", "release_date", "on_hold", "represents_company", "is_internal_supplier"],
|
||||||
get_indicator: function(doc) {
|
get_indicator: function(doc) {
|
||||||
if( (flt(doc.outstanding_amount) <= 0) && doc.docstatus == 1 && doc.status == 'Debit Note Issued') {
|
if( (flt(doc.outstanding_amount) <= 0) && doc.docstatus == 1 && doc.status == 'Debit Note Issued') {
|
||||||
return [__("Debit Note Issued"), "darkgrey", "outstanding_amount,<=,0"];
|
return [__("Debit Note Issued"), "darkgrey", "outstanding_amount,<=,0"];
|
||||||
@@ -20,6 +20,8 @@ frappe.listview_settings['Purchase Invoice'] = {
|
|||||||
}
|
}
|
||||||
} else if(cint(doc.is_return)) {
|
} else if(cint(doc.is_return)) {
|
||||||
return [__("Return"), "darkgrey", "is_return,=,Yes"];
|
return [__("Return"), "darkgrey", "is_return,=,Yes"];
|
||||||
|
} else if(doc.company == doc.represents_company && doc.is_internal_supplier) {
|
||||||
|
return [__("Internal Transfer"), "darkgrey", "outstanding_amount,=,0"];
|
||||||
} else if(flt(doc.outstanding_amount)==0 && doc.docstatus==1) {
|
} else if(flt(doc.outstanding_amount)==0 && doc.docstatus==1) {
|
||||||
return [__("Paid"), "green", "outstanding_amount,=,0"];
|
return [__("Paid"), "green", "outstanding_amount,=,0"];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -575,6 +575,25 @@ frappe.ui.form.on('Sales Invoice', {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
frm.set_query("cost_center", function() {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
company: frm.doc.company,
|
||||||
|
is_group: 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
frm.set_query("inter_company_account", function() {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
company: frm.doc.company,
|
||||||
|
is_group: 0,
|
||||||
|
root_type: "Liability",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
frm.custom_make_buttons = {
|
frm.custom_make_buttons = {
|
||||||
'Delivery Note': 'Delivery',
|
'Delivery Note': 'Delivery',
|
||||||
'Sales Invoice': 'Sales Return',
|
'Sales Invoice': 'Sales Return',
|
||||||
@@ -1075,7 +1094,7 @@ var get_drugs_to_invoice = function(frm) {
|
|||||||
description:'Quantity will be calculated only for items which has "Nos" as UoM. You may change as required for each invoice item.',
|
description:'Quantity will be calculated only for items which has "Nos" as UoM. You may change as required for each invoice item.',
|
||||||
get_query: function(doc) {
|
get_query: function(doc) {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
patient: dialog.get_value("patient"),
|
patient: dialog.get_value("patient"),
|
||||||
company: frm.doc.company,
|
company: frm.doc.company,
|
||||||
docstatus: 1
|
docstatus: 1
|
||||||
|
|||||||
@@ -157,6 +157,7 @@
|
|||||||
"more_information",
|
"more_information",
|
||||||
"inter_company_invoice_reference",
|
"inter_company_invoice_reference",
|
||||||
"is_internal_customer",
|
"is_internal_customer",
|
||||||
|
"represents_company",
|
||||||
"customer_group",
|
"customer_group",
|
||||||
"campaign",
|
"campaign",
|
||||||
"is_discounted",
|
"is_discounted",
|
||||||
@@ -170,6 +171,7 @@
|
|||||||
"c_form_applicable",
|
"c_form_applicable",
|
||||||
"c_form_no",
|
"c_form_no",
|
||||||
"column_break8",
|
"column_break8",
|
||||||
|
"inter_company_account",
|
||||||
"remarks",
|
"remarks",
|
||||||
"sales_team_section_break",
|
"sales_team_section_break",
|
||||||
"sales_partner",
|
"sales_partner",
|
||||||
@@ -1654,7 +1656,7 @@
|
|||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "Status",
|
"label": "Status",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "\nDraft\nReturn\nCredit Note Issued\nSubmitted\nPaid\nUnpaid\nUnpaid and Discounted\nOverdue and Discounted\nOverdue\nCancelled",
|
"options": "\nDraft\nReturn\nCredit Note Issued\nSubmitted\nPaid\nUnpaid\nUnpaid and Discounted\nOverdue and Discounted\nOverdue\nCancelled\nInternal Transfer",
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
@@ -1949,13 +1951,29 @@
|
|||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Company Tax ID",
|
"label": "Company Tax ID",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:doc.is_internal_customer",
|
||||||
|
"fieldname": "inter_company_account",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Inter Company Account",
|
||||||
|
"options": "Account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:doc.is_internal_customer",
|
||||||
|
"fetch_from": "cusstomer.represents_company",
|
||||||
|
"fieldname": "represents_company",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Represents Company",
|
||||||
|
"options": "Company",
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-file-text",
|
"icon": "fa fa-file-text",
|
||||||
"idx": 181,
|
"idx": 181,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-10-09 15:59:57.544736",
|
"modified": "2020-11-27 18:48:15.012300",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Sales Invoice",
|
"name": "Sales Invoice",
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ class SalesInvoice(SellingController):
|
|||||||
self.set_income_account_for_fixed_assets()
|
self.set_income_account_for_fixed_assets()
|
||||||
self.validate_item_cost_centers()
|
self.validate_item_cost_centers()
|
||||||
validate_inter_company_party(self.doctype, self.customer, self.company, self.inter_company_invoice_reference)
|
validate_inter_company_party(self.doctype, self.customer, self.company, self.inter_company_invoice_reference)
|
||||||
|
self.set_inter_company_account()
|
||||||
|
|
||||||
if cint(self.is_pos):
|
if cint(self.is_pos):
|
||||||
self.validate_pos()
|
self.validate_pos()
|
||||||
@@ -570,6 +571,26 @@ class SalesInvoice(SellingController):
|
|||||||
if not res:
|
if not res:
|
||||||
throw(_("Customer {0} does not belong to project {1}").format(self.customer,self.project))
|
throw(_("Customer {0} does not belong to project {1}").format(self.customer,self.project))
|
||||||
|
|
||||||
|
def set_inter_company_account(self):
|
||||||
|
"""
|
||||||
|
Set intercompany account for inter warehouse transactions
|
||||||
|
This account will be used in case billing company and internal customer's
|
||||||
|
representation company is same
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.is_internal_transfer() and not self.inter_company_account:
|
||||||
|
self.inter_company_account = frappe.get_cached_value('Company', self.company, 'default_inter_company_account')
|
||||||
|
|
||||||
|
def is_internal_transfer(self):
|
||||||
|
"""
|
||||||
|
It will an internal transfer if its an internal customer and representation
|
||||||
|
company is same as billing company
|
||||||
|
"""
|
||||||
|
if self.is_internal_customer and (self.represents_company == self.company):
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
def validate_pos(self):
|
def validate_pos(self):
|
||||||
if self.is_return:
|
if self.is_return:
|
||||||
invoice_total = self.rounded_total or self.grand_total
|
invoice_total = self.rounded_total or self.grand_total
|
||||||
@@ -751,6 +772,7 @@ class SalesInvoice(SellingController):
|
|||||||
self.make_customer_gl_entry(gl_entries)
|
self.make_customer_gl_entry(gl_entries)
|
||||||
|
|
||||||
self.make_tax_gl_entries(gl_entries)
|
self.make_tax_gl_entries(gl_entries)
|
||||||
|
self.make_internal_transfer_gl_entries(gl_entries)
|
||||||
|
|
||||||
self.make_item_gl_entries(gl_entries)
|
self.make_item_gl_entries(gl_entries)
|
||||||
|
|
||||||
@@ -770,7 +792,7 @@ class SalesInvoice(SellingController):
|
|||||||
# Checked both rounding_adjustment and rounded_total
|
# Checked both rounding_adjustment and rounded_total
|
||||||
# because rounded_total had value even before introcution of posting GLE based on rounded total
|
# because rounded_total had value even before introcution of posting GLE based on rounded total
|
||||||
grand_total = self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total
|
grand_total = self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total
|
||||||
if grand_total:
|
if grand_total and not self.is_internal_transfer():
|
||||||
# Didnot use base_grand_total to book rounding loss gle
|
# Didnot use base_grand_total to book rounding loss gle
|
||||||
grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
|
grand_total_in_company_currency = flt(grand_total * self.conversion_rate,
|
||||||
self.precision("grand_total"))
|
self.precision("grand_total"))
|
||||||
@@ -809,44 +831,57 @@ class SalesInvoice(SellingController):
|
|||||||
}, account_currency, item=tax)
|
}, account_currency, item=tax)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def make_internal_transfer_gl_entries(self, gl_entries):
|
||||||
|
if self.is_internal_transfer() and flt(self.base_total_taxes_and_charges):
|
||||||
|
account_currency = get_account_currency(self.inter_company_account)
|
||||||
|
gl_entries.append(
|
||||||
|
self.get_gl_dict({
|
||||||
|
"account": self.inter_company_account,
|
||||||
|
"against": self.customer,
|
||||||
|
"debit": flt(self.total_taxes_and_charges),
|
||||||
|
"debit_in_account_currency": flt(self.base_total_taxes_and_charges),
|
||||||
|
"cost_center": self.cost_center
|
||||||
|
}, account_currency, item=self))
|
||||||
|
|
||||||
def make_item_gl_entries(self, gl_entries):
|
def make_item_gl_entries(self, gl_entries):
|
||||||
# income account gl entries
|
# income account gl entries
|
||||||
for item in self.get("items"):
|
if not self.is_internal_transfer():
|
||||||
if flt(item.base_net_amount, item.precision("base_net_amount")):
|
for item in self.get("items"):
|
||||||
if item.is_fixed_asset:
|
if flt(item.base_net_amount, item.precision("base_net_amount")):
|
||||||
asset = frappe.get_doc("Asset", item.asset)
|
if item.is_fixed_asset:
|
||||||
|
asset = frappe.get_doc("Asset", item.asset)
|
||||||
|
|
||||||
if (len(asset.finance_books) > 1 and not item.finance_book
|
if (len(asset.finance_books) > 1 and not item.finance_book
|
||||||
and asset.finance_books[0].finance_book):
|
and asset.finance_books[0].finance_book):
|
||||||
frappe.throw(_("Select finance book for the item {0} at row {1}")
|
frappe.throw(_("Select finance book for the item {0} at row {1}")
|
||||||
.format(item.item_code, item.idx))
|
.format(item.item_code, item.idx))
|
||||||
|
|
||||||
fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(asset,
|
fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(asset,
|
||||||
item.base_net_amount, item.finance_book)
|
item.base_net_amount, item.finance_book)
|
||||||
|
|
||||||
for gle in fixed_asset_gl_entries:
|
for gle in fixed_asset_gl_entries:
|
||||||
gle["against"] = self.customer
|
gle["against"] = self.customer
|
||||||
gl_entries.append(self.get_gl_dict(gle, item=item))
|
gl_entries.append(self.get_gl_dict(gle, item=item))
|
||||||
|
|
||||||
asset.db_set("disposal_date", self.posting_date)
|
asset.db_set("disposal_date", self.posting_date)
|
||||||
asset.set_status("Sold" if self.docstatus==1 else None)
|
asset.set_status("Sold" if self.docstatus==1 else None)
|
||||||
else:
|
else:
|
||||||
income_account = (item.income_account
|
income_account = (item.income_account
|
||||||
if (not item.enable_deferred_revenue or self.is_return) else item.deferred_revenue_account)
|
if (not item.enable_deferred_revenue or self.is_return) else item.deferred_revenue_account)
|
||||||
|
|
||||||
account_currency = get_account_currency(income_account)
|
account_currency = get_account_currency(income_account)
|
||||||
gl_entries.append(
|
gl_entries.append(
|
||||||
self.get_gl_dict({
|
self.get_gl_dict({
|
||||||
"account": income_account,
|
"account": income_account,
|
||||||
"against": self.customer,
|
"against": self.customer,
|
||||||
"credit": flt(item.base_net_amount, item.precision("base_net_amount")),
|
"credit": flt(item.base_net_amount, item.precision("base_net_amount")),
|
||||||
"credit_in_account_currency": (flt(item.base_net_amount, item.precision("base_net_amount"))
|
"credit_in_account_currency": (flt(item.base_net_amount, item.precision("base_net_amount"))
|
||||||
if account_currency==self.company_currency
|
if account_currency==self.company_currency
|
||||||
else flt(item.net_amount, item.precision("net_amount"))),
|
else flt(item.net_amount, item.precision("net_amount"))),
|
||||||
"cost_center": item.cost_center,
|
"cost_center": item.cost_center,
|
||||||
"project": item.project or self.project
|
"project": item.project or self.project
|
||||||
}, account_currency, item=item)
|
}, account_currency, item=item)
|
||||||
)
|
)
|
||||||
|
|
||||||
# expense account gl entries
|
# expense account gl entries
|
||||||
if cint(self.update_stock) and \
|
if cint(self.update_stock) and \
|
||||||
@@ -1258,7 +1293,9 @@ class SalesInvoice(SellingController):
|
|||||||
if self.docstatus == 2:
|
if self.docstatus == 2:
|
||||||
status = "Cancelled"
|
status = "Cancelled"
|
||||||
elif self.docstatus == 1:
|
elif self.docstatus == 1:
|
||||||
if outstanding_amount > 0 and due_date < nowdate and self.is_discounted and discountng_status=='Disbursed':
|
if self.is_internal_transfer():
|
||||||
|
self.status = 'Internal Transfer'
|
||||||
|
elif outstanding_amount > 0 and due_date < nowdate and self.is_discounted and discountng_status=='Disbursed':
|
||||||
self.status = "Overdue and Discounted"
|
self.status = "Overdue and Discounted"
|
||||||
elif outstanding_amount > 0 and due_date < nowdate:
|
elif outstanding_amount > 0 and due_date < nowdate:
|
||||||
self.status = "Overdue"
|
self.status = "Overdue"
|
||||||
@@ -1522,9 +1559,13 @@ def make_inter_company_transaction(doctype, source_name, target_doc=None):
|
|||||||
if doctype in ["Sales Invoice", "Sales Order"]:
|
if doctype in ["Sales Invoice", "Sales Order"]:
|
||||||
source_doc = frappe.get_doc(doctype, source_name)
|
source_doc = frappe.get_doc(doctype, source_name)
|
||||||
target_doctype = "Purchase Invoice" if doctype == "Sales Invoice" else "Purchase Order"
|
target_doctype = "Purchase Invoice" if doctype == "Sales Invoice" else "Purchase Order"
|
||||||
|
source_document_warehouse_field = 'target_warehouse'
|
||||||
|
target_document_warehouse_field = 'from_warehouse'
|
||||||
else:
|
else:
|
||||||
source_doc = frappe.get_doc(doctype, source_name)
|
source_doc = frappe.get_doc(doctype, source_name)
|
||||||
target_doctype = "Sales Invoice" if doctype == "Purchase Invoice" else "Sales Order"
|
target_doctype = "Sales Invoice" if doctype == "Purchase Invoice" else "Sales Order"
|
||||||
|
source_document_warehouse_field = 'from_warehouse'
|
||||||
|
target_document_warehouse_field = 'target_warehouse'
|
||||||
|
|
||||||
validate_inter_company_transaction(source_doc, doctype)
|
validate_inter_company_transaction(source_doc, doctype)
|
||||||
details = get_inter_company_details(source_doc, doctype)
|
details = get_inter_company_details(source_doc, doctype)
|
||||||
@@ -1551,6 +1592,24 @@ def make_inter_company_transaction(doctype, source_name, target_doc=None):
|
|||||||
if currency:
|
if currency:
|
||||||
target_doc.currency = currency
|
target_doc.currency = currency
|
||||||
|
|
||||||
|
item_field_map = {
|
||||||
|
"doctype": target_doctype + " Item",
|
||||||
|
"field_no_map": [
|
||||||
|
"income_account",
|
||||||
|
"expense_account",
|
||||||
|
"cost_center",
|
||||||
|
"warehouse"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
if source_doc.get('update_stock'):
|
||||||
|
item_field_map.update({
|
||||||
|
'field_map': {
|
||||||
|
source_document_warehouse_field: target_document_warehouse_field
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
doclist = get_mapped_doc(doctype, source_name, {
|
doclist = get_mapped_doc(doctype, source_name, {
|
||||||
doctype: {
|
doctype: {
|
||||||
"doctype": target_doctype,
|
"doctype": target_doctype,
|
||||||
@@ -1559,15 +1618,7 @@ def make_inter_company_transaction(doctype, source_name, target_doc=None):
|
|||||||
"taxes_and_charges"
|
"taxes_and_charges"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
doctype +" Item": {
|
doctype +" Item": item_field_map
|
||||||
"doctype": target_doctype + " Item",
|
|
||||||
"field_no_map": [
|
|
||||||
"income_account",
|
|
||||||
"expense_account",
|
|
||||||
"cost_center",
|
|
||||||
"warehouse"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
}, target_doc, set_missing_values)
|
}, target_doc, set_missing_values)
|
||||||
|
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ frappe.listview_settings['Sales Invoice'] = {
|
|||||||
"Credit Note Issued": "darkgrey",
|
"Credit Note Issued": "darkgrey",
|
||||||
"Unpaid and Discounted": "orange",
|
"Unpaid and Discounted": "orange",
|
||||||
"Overdue and Discounted": "red",
|
"Overdue and Discounted": "red",
|
||||||
"Overdue": "red"
|
"Overdue": "red",
|
||||||
|
"Internal Transfer": "darkgrey"
|
||||||
};
|
};
|
||||||
return [__(doc.status), status_color[doc.status], "status,=,"+doc.status];
|
return [__(doc.status), status_color[doc.status], "status,=,"+doc.status];
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ class StockController(AccountsController):
|
|||||||
if sle_list:
|
if sle_list:
|
||||||
for sle in sle_list:
|
for sle in sle_list:
|
||||||
if warehouse_account.get(sle.warehouse):
|
if warehouse_account.get(sle.warehouse):
|
||||||
# from warehouse account/ target warehouse account
|
# from warehouse account
|
||||||
|
|
||||||
self.check_expense_account(item_row)
|
self.check_expense_account(item_row)
|
||||||
|
|
||||||
@@ -102,9 +102,14 @@ class StockController(AccountsController):
|
|||||||
"is_opening": item_row.get("is_opening") or self.get("is_opening") or "No",
|
"is_opening": item_row.get("is_opening") or self.get("is_opening") or "No",
|
||||||
}, warehouse_account[sle.warehouse]["account_currency"], item=item_row))
|
}, warehouse_account[sle.warehouse]["account_currency"], item=item_row))
|
||||||
|
|
||||||
# expense account
|
# expense account/ target_warehouse / source_warehouse
|
||||||
|
if item_row.target_warehouse:
|
||||||
|
expense_account = warehouse_account[item_row.target_warehouse]["account"]
|
||||||
|
else:
|
||||||
|
expense_account = item_row.expense_account
|
||||||
|
|
||||||
gl_list.append(self.get_gl_dict({
|
gl_list.append(self.get_gl_dict({
|
||||||
"account": item_row.expense_account,
|
"account": expense_account,
|
||||||
"against": warehouse_account[sle.warehouse]["account"],
|
"against": warehouse_account[sle.warehouse]["account"],
|
||||||
"cost_center": item_row.cost_center,
|
"cost_center": item_row.cost_center,
|
||||||
"project": item_row.project or self.get('project'),
|
"project": item_row.project or self.get('project'),
|
||||||
|
|||||||
@@ -519,6 +519,17 @@ class calculate_taxes_and_totals(object):
|
|||||||
if self.doc.docstatus == 0:
|
if self.doc.docstatus == 0:
|
||||||
self.calculate_outstanding_amount()
|
self.calculate_outstanding_amount()
|
||||||
|
|
||||||
|
def is_internal_invoice(self):
|
||||||
|
"""
|
||||||
|
Checks if its an internal transfer invoice
|
||||||
|
and decides if to calculate any out standing amount or not
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.doc.doctype in ('Sales Invoice', 'Purchase Invoice') and self.doc.is_internal_transfer():
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
def calculate_outstanding_amount(self):
|
def calculate_outstanding_amount(self):
|
||||||
# NOTE:
|
# NOTE:
|
||||||
# write_off_amount is only for POS Invoice
|
# write_off_amount is only for POS Invoice
|
||||||
@@ -526,7 +537,8 @@ class calculate_taxes_and_totals(object):
|
|||||||
if self.doc.doctype == "Sales Invoice":
|
if self.doc.doctype == "Sales Invoice":
|
||||||
self.calculate_paid_amount()
|
self.calculate_paid_amount()
|
||||||
|
|
||||||
if self.doc.is_return and self.doc.return_against and not self.doc.get('is_pos'): return
|
if self.doc.is_return and self.doc.return_against and not self.doc.get('is_pos') or \
|
||||||
|
self.is_internal_invoice(): return
|
||||||
|
|
||||||
self.doc.round_floats_in(self.doc, ["grand_total", "total_advance", "write_off_amount"])
|
self.doc.round_floats_in(self.doc, ["grand_total", "total_advance", "write_off_amount"])
|
||||||
self._set_in_company_currency(self.doc, ['write_off_amount'])
|
self._set_in_company_currency(self.doc, ['write_off_amount'])
|
||||||
|
|||||||
@@ -609,6 +609,15 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
|
|||||||
this.calculate_outstanding_amount(update_paid_amount);
|
this.calculate_outstanding_amount(update_paid_amount);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
is_internal_invoice: function() {
|
||||||
|
if (['Sales Invoice', 'Purchase Invoice'].includes(this.frm.doc.doctype)) {
|
||||||
|
if (this.frm.doc.company === this.frm.doc.represents_company) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
|
||||||
calculate_outstanding_amount: function(update_paid_amount) {
|
calculate_outstanding_amount: function(update_paid_amount) {
|
||||||
// NOTE:
|
// NOTE:
|
||||||
// paid_amount and write_off_amount is only for POS/Loyalty Point Redemption Invoice
|
// paid_amount and write_off_amount is only for POS/Loyalty Point Redemption Invoice
|
||||||
@@ -617,7 +626,7 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
|
|||||||
this.calculate_paid_amount();
|
this.calculate_paid_amount();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.frm.doc.is_return || this.frm.doc.docstatus > 0) return;
|
if(this.frm.doc.is_return || (this.frm.doc.docstatus > 0) || this.is_internal_invoice()) return;
|
||||||
|
|
||||||
frappe.model.round_floats_in(this.frm.doc, ["grand_total", "total_advance", "write_off_amount"]);
|
frappe.model.round_floats_in(this.frm.doc, ["grand_total", "total_advance", "write_off_amount"]);
|
||||||
|
|
||||||
|
|||||||
@@ -262,7 +262,8 @@ erpnext.company.setup_queries = function(frm) {
|
|||||||
["default_employee_advance_account", {"root_type": "Asset"}],
|
["default_employee_advance_account", {"root_type": "Asset"}],
|
||||||
["expenses_included_in_asset_valuation", {"account_type": "Expenses Included In Asset Valuation"}],
|
["expenses_included_in_asset_valuation", {"account_type": "Expenses Included In Asset Valuation"}],
|
||||||
["capital_work_in_progress_account", {"account_type": "Capital Work in Progress"}],
|
["capital_work_in_progress_account", {"account_type": "Capital Work in Progress"}],
|
||||||
["asset_received_but_not_billed", {"account_type": "Asset Received But Not Billed"}]
|
["asset_received_but_not_billed", {"account_type": "Asset Received But Not Billed"}],
|
||||||
|
["default_inter_company_account", {"root_type": "Liability"}]
|
||||||
], function(i, v) {
|
], function(i, v) {
|
||||||
erpnext.company.set_custom_query(frm, v);
|
erpnext.company.set_custom_query(frm, v);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -46,10 +46,9 @@
|
|||||||
"round_off_account",
|
"round_off_account",
|
||||||
"round_off_cost_center",
|
"round_off_cost_center",
|
||||||
"write_off_account",
|
"write_off_account",
|
||||||
"discount_allowed_account",
|
|
||||||
"discount_received_account",
|
|
||||||
"exchange_gain_loss_account",
|
"exchange_gain_loss_account",
|
||||||
"unrealized_exchange_gain_loss_account",
|
"unrealized_exchange_gain_loss_account",
|
||||||
|
"default_inter_company_account",
|
||||||
"column_break0",
|
"column_break0",
|
||||||
"allow_account_creation_against_child_company",
|
"allow_account_creation_against_child_company",
|
||||||
"default_payable_account",
|
"default_payable_account",
|
||||||
@@ -261,14 +260,14 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "create_chart_of_accounts_based_on",
|
"fieldname": "create_chart_of_accounts_based_on",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"label": "Create Chart of Accounts Based on",
|
"label": "Create Chart Of Accounts Based On",
|
||||||
"options": "\nStandard Template\nExisting Company"
|
"options": "\nStandard Template\nExisting Company"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval:doc.create_chart_of_accounts_based_on===\"Standard Template\"",
|
"depends_on": "eval:doc.create_chart_of_accounts_based_on===\"Standard Template\"",
|
||||||
"fieldname": "chart_of_accounts",
|
"fieldname": "chart_of_accounts",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"label": "Chart of Accounts Template",
|
"label": "Chart Of Accounts Template",
|
||||||
"no_copy": 1
|
"no_copy": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -345,18 +344,6 @@
|
|||||||
"label": "Write Off Account",
|
"label": "Write Off Account",
|
||||||
"options": "Account"
|
"options": "Account"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "discount_allowed_account",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Discount Allowed Account",
|
|
||||||
"options": "Account"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "discount_received_account",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Discount Received Account",
|
|
||||||
"options": "Account"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "exchange_gain_loss_account",
|
"fieldname": "exchange_gain_loss_account",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
@@ -740,6 +727,12 @@
|
|||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Default In Transit Warehouse",
|
"label": "Default In Transit Warehouse",
|
||||||
"options": "Warehouse"
|
"options": "Warehouse"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "default_inter_company_account",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Default Inter Company Account",
|
||||||
|
"options": "Account"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-building",
|
"icon": "fa fa-building",
|
||||||
@@ -747,7 +740,7 @@
|
|||||||
"image_field": "company_logo",
|
"image_field": "company_logo",
|
||||||
"is_tree": 1,
|
"is_tree": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-08-06 00:38:08.311216",
|
"modified": "2020-11-26 18:20:48.184507",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Setup",
|
"module": "Setup",
|
||||||
"name": "Company",
|
"name": "Company",
|
||||||
@@ -808,4 +801,4 @@
|
|||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "ASC",
|
"sort_order": "ASC",
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user