feat: Item-wise provisional accounting for service items

(cherry picked from commit 3ce64170db)
This commit is contained in:
Deepesh Garg
2022-04-11 14:35:22 +05:30
committed by mergify-bot
parent 0b62784f6f
commit 5776881f34
8 changed files with 65 additions and 31 deletions

View File

@@ -801,7 +801,9 @@ class PurchaseInvoice(BuyingController):
if provisional_accounting_for_non_stock_items: if provisional_accounting_for_non_stock_items:
if item.purchase_receipt: if item.purchase_receipt:
provisional_account = self.get_company_default("default_provisional_account") provisional_account = frappe.db.get_value(
"Purchase Receipt Item", item.pr_detail, "provisional_expense_account"
) or self.get_company_default("default_provisional_account")
purchase_receipt_doc = purchase_receipt_doc_map.get(item.purchase_receipt) purchase_receipt_doc = purchase_receipt_doc_map.get(item.purchase_receipt)
if not purchase_receipt_doc: if not purchase_receipt_doc:
@@ -824,7 +826,7 @@ class PurchaseInvoice(BuyingController):
if expense_booked_in_pr: if expense_booked_in_pr:
# Intentionally passing purchase invoice item to handle partial billing # Intentionally passing purchase invoice item to handle partial billing
purchase_receipt_doc.add_provisional_gl_entry( purchase_receipt_doc.add_provisional_gl_entry(
item, gl_entries, self.posting_date, reverse=1 item, gl_entries, self.posting_date, provisional_account, reverse=1
) )
if not self.is_internal_transfer(): if not self.is_internal_transfer():

View File

@@ -233,7 +233,8 @@ erpnext.company.setup_queries = function(frm) {
["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"}],
["unrealized_profit_loss_account", {"root_type": ["in", ["Liability", "Asset"]]}] ["unrealized_profit_loss_account", {"root_type": ["in", ["Liability", "Asset"]]}],
["default_provisional_account", {"root_type": ["in", ["Liability", "Asset"]]}]
], function(i, v) { ], function(i, v) {
erpnext.company.set_custom_query(frm, v); erpnext.company.set_custom_query(frm, v);
}); });

View File

@@ -377,6 +377,17 @@ $.extend(erpnext.item, {
} }
} }
frm.set_query('default_provisional_account', 'item_defaults', (doc, cdt, cdn) => {
let row = locals[cdt][cdn];
return {
filters: {
"company": row.company,
"root_type": ["in", ["Liability", "Asset"]],
"is_group": 0
}
}
})
}, },
make_dashboard: function(frm) { make_dashboard: function(frm) {

View File

@@ -15,6 +15,7 @@
"default_supplier", "default_supplier",
"column_break_8", "column_break_8",
"expense_account", "expense_account",
"default_provisional_account",
"selling_defaults", "selling_defaults",
"selling_cost_center", "selling_cost_center",
"column_break_12", "column_break_12",
@@ -101,11 +102,17 @@
"fieldtype": "Link", "fieldtype": "Link",
"label": "Default Discount Account", "label": "Default Discount Account",
"options": "Account" "options": "Account"
},
{
"fieldname": "default_provisional_account",
"fieldtype": "Link",
"label": "Default Provisional Account",
"options": "Account"
} }
], ],
"istable": 1, "istable": 1,
"links": [], "links": [],
"modified": "2021-07-13 01:26:03.860065", "modified": "2022-04-10 20:18:54.148195",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Stock", "module": "Stock",
"name": "Item Default", "name": "Item Default",
@@ -114,5 +121,6 @@
"quick_entry": 1, "quick_entry": 1,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC", "sort_order": "DESC",
"states": [],
"track_changes": 1 "track_changes": 1
} }

View File

@@ -106,8 +106,6 @@
"terms", "terms",
"bill_no", "bill_no",
"bill_date", "bill_date",
"accounting_details_section",
"provisional_expense_account",
"more_info", "more_info",
"project", "project",
"status", "status",
@@ -1146,26 +1144,13 @@
"label": "Represents Company", "label": "Represents Company",
"options": "Company", "options": "Company",
"read_only": 1 "read_only": 1
},
{
"collapsible": 1,
"fieldname": "accounting_details_section",
"fieldtype": "Section Break",
"label": "Accounting Details"
},
{
"fieldname": "provisional_expense_account",
"fieldtype": "Link",
"hidden": 1,
"label": "Provisional Expense Account",
"options": "Account"
} }
], ],
"icon": "fa fa-truck", "icon": "fa fa-truck",
"idx": 261, "idx": 261,
"is_submittable": 1, "is_submittable": 1,
"links": [], "links": [],
"modified": "2022-03-10 11:40:52.690984", "modified": "2022-04-10 22:50:37.761362",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Stock", "module": "Stock",
"name": "Purchase Receipt", "name": "Purchase Receipt",

View File

@@ -146,10 +146,13 @@ class PurchaseReceipt(BuyingController):
) )
) )
if provisional_accounting_for_non_stock_items: if not provisional_accounting_for_non_stock_items:
default_provisional_account = self.get_company_default("default_provisional_account") return
if not self.provisional_expense_account:
self.provisional_expense_account = default_provisional_account default_provisional_account = self.get_company_default("default_provisional_account")
for item in self.get("items"):
if not item.get("provisional_expense_account"):
item.provisional_expense_account = default_provisional_account
def validate_with_previous_doc(self): def validate_with_previous_doc(self):
super(PurchaseReceipt, self).validate_with_previous_doc( super(PurchaseReceipt, self).validate_with_previous_doc(
@@ -475,9 +478,10 @@ class PurchaseReceipt(BuyingController):
+ "\n".join(warehouse_with_no_account) + "\n".join(warehouse_with_no_account)
) )
def add_provisional_gl_entry(self, item, gl_entries, posting_date, reverse=0): def add_provisional_gl_entry(
provisional_expense_account = self.get("provisional_expense_account") self, item, gl_entries, posting_date, provisional_account, reverse=0
credit_currency = get_account_currency(provisional_expense_account) ):
credit_currency = get_account_currency(provisional_account)
debit_currency = get_account_currency(item.expense_account) debit_currency = get_account_currency(item.expense_account)
expense_account = item.expense_account expense_account = item.expense_account
remarks = self.get("remarks") or _("Accounting Entry for Service") remarks = self.get("remarks") or _("Accounting Entry for Service")
@@ -491,7 +495,7 @@ class PurchaseReceipt(BuyingController):
self.add_gl_entry( self.add_gl_entry(
gl_entries=gl_entries, gl_entries=gl_entries,
account=provisional_expense_account, account=provisional_account,
cost_center=item.cost_center, cost_center=item.cost_center,
debit=0.0, debit=0.0,
credit=multiplication_factor * item.amount, credit=multiplication_factor * item.amount,
@@ -511,7 +515,7 @@ class PurchaseReceipt(BuyingController):
debit=multiplication_factor * item.amount, debit=multiplication_factor * item.amount,
credit=0.0, credit=0.0,
remarks=remarks, remarks=remarks,
against_account=provisional_expense_account, against_account=provisional_account,
account_currency=debit_currency, account_currency=debit_currency,
project=item.project, project=item.project,
voucher_detail_no=item.name, voucher_detail_no=item.name,

View File

@@ -96,7 +96,6 @@
"include_exploded_items", "include_exploded_items",
"batch_no", "batch_no",
"rejected_serial_no", "rejected_serial_no",
"expense_account",
"item_tax_rate", "item_tax_rate",
"item_weight_details", "item_weight_details",
"weight_per_unit", "weight_per_unit",
@@ -107,6 +106,10 @@
"manufacturer", "manufacturer",
"column_break_16", "column_break_16",
"manufacturer_part_no", "manufacturer_part_no",
"accounting_details_section",
"expense_account",
"column_break_102",
"provisional_expense_account",
"accounting_dimensions_section", "accounting_dimensions_section",
"project", "project",
"dimension_col_break", "dimension_col_break",
@@ -971,12 +974,27 @@
"label": "Product Bundle", "label": "Product Bundle",
"options": "Product Bundle", "options": "Product Bundle",
"read_only": 1 "read_only": 1
},
{
"fieldname": "provisional_expense_account",
"fieldtype": "Link",
"label": "Provisional Expense Account",
"options": "Account"
},
{
"fieldname": "accounting_details_section",
"fieldtype": "Section Break",
"label": "Accounting Details"
},
{
"fieldname": "column_break_102",
"fieldtype": "Column Break"
} }
], ],
"idx": 1, "idx": 1,
"istable": 1, "istable": 1,
"links": [], "links": [],
"modified": "2022-02-01 11:32:27.980524", "modified": "2022-04-11 13:07:32.061402",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Stock", "module": "Stock",
"name": "Purchase Receipt Item", "name": "Purchase Receipt Item",

View File

@@ -335,6 +335,7 @@ def get_basic_details(args, item, overwrite_warehouse=True):
"expense_account": expense_account "expense_account": expense_account
or get_default_expense_account(args, item_defaults, item_group_defaults, brand_defaults), or get_default_expense_account(args, item_defaults, item_group_defaults, brand_defaults),
"discount_account": get_default_discount_account(args, item_defaults), "discount_account": get_default_discount_account(args, item_defaults),
"provisional_expense_account": get_provisional_account(args, item_defaults),
"cost_center": get_default_cost_center( "cost_center": get_default_cost_center(
args, item_defaults, item_group_defaults, brand_defaults args, item_defaults, item_group_defaults, brand_defaults
), ),
@@ -689,6 +690,10 @@ def get_default_expense_account(args, item, item_group, brand):
) )
def get_provisional_account(args, item):
return item.get("default_provisional_account") or args.default_provisional_account
def get_default_discount_account(args, item): def get_default_discount_account(args, item):
return item.get("default_discount_account") or args.discount_account return item.get("default_discount_account") or args.discount_account