Merge pull request #30675 from deepeshgarg007/item_wise_provisional_accounting
feat: Item-wise provisional accounting for service items
This commit is contained in:
commit
7536da0b41
@ -811,7 +811,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:
|
||||||
@ -834,7 +836,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():
|
||||||
|
@ -1482,7 +1482,8 @@ class TestPurchaseInvoice(unittest.TestCase):
|
|||||||
self.assertEqual(payment_entry.taxes[0].allocated_amount, 0)
|
self.assertEqual(payment_entry.taxes[0].allocated_amount, 0)
|
||||||
|
|
||||||
def test_provisional_accounting_entry(self):
|
def test_provisional_accounting_entry(self):
|
||||||
item = create_item("_Test Non Stock Item", is_stock_item=0)
|
create_item("_Test Non Stock Item", is_stock_item=0)
|
||||||
|
|
||||||
provisional_account = create_account(
|
provisional_account = create_account(
|
||||||
account_name="Provision Account",
|
account_name="Provision Account",
|
||||||
parent_account="Current Liabilities - _TC",
|
parent_account="Current Liabilities - _TC",
|
||||||
@ -1505,6 +1506,8 @@ class TestPurchaseInvoice(unittest.TestCase):
|
|||||||
pi.save()
|
pi.save()
|
||||||
pi.submit()
|
pi.submit()
|
||||||
|
|
||||||
|
self.assertEquals(pr.items[0].provisional_expense_account, "Provision Account - _TC")
|
||||||
|
|
||||||
# Check GLE for Purchase Invoice
|
# Check GLE for Purchase Invoice
|
||||||
expected_gle = [
|
expected_gle = [
|
||||||
["Cost of Goods Sold - _TC", 250, 0, add_days(pr.posting_date, -1)],
|
["Cost of Goods Sold - _TC", 250, 0, add_days(pr.posting_date, -1)],
|
||||||
|
@ -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);
|
||||||
});
|
});
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
||||||
}
|
}
|
@ -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",
|
||||||
@ -1145,26 +1143,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",
|
||||||
|
@ -145,10 +145,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(
|
||||||
@ -509,7 +512,9 @@ class PurchaseReceipt(BuyingController):
|
|||||||
and flt(d.qty)
|
and flt(d.qty)
|
||||||
and provisional_accounting_for_non_stock_items
|
and provisional_accounting_for_non_stock_items
|
||||||
):
|
):
|
||||||
self.add_provisional_gl_entry(d, gl_entries, self.posting_date)
|
self.add_provisional_gl_entry(
|
||||||
|
d, gl_entries, self.posting_date, d.get("provisional_expense_account")
|
||||||
|
)
|
||||||
|
|
||||||
if warehouse_with_no_account:
|
if warehouse_with_no_account:
|
||||||
frappe.msgprint(
|
frappe.msgprint(
|
||||||
@ -518,9 +523,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")
|
||||||
@ -534,7 +540,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,
|
||||||
@ -554,7 +560,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,
|
||||||
|
@ -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",
|
||||||
|
@ -345,6 +345,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
|
||||||
),
|
),
|
||||||
@ -699,6 +700,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
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user