Merge branch 'develop' into revert-bu-schluessel
This commit is contained in:
commit
9fde0f0a9c
@ -7,35 +7,30 @@
|
|||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
"accounts_transactions_settings_section",
|
"invoice_and_billing_tab",
|
||||||
"over_billing_allowance",
|
"enable_features_section",
|
||||||
"role_allowed_to_over_bill",
|
|
||||||
"credit_controller",
|
|
||||||
"make_payment_via_journal_entry",
|
|
||||||
"column_break_11",
|
|
||||||
"check_supplier_invoice_uniqueness",
|
|
||||||
"unlink_payment_on_cancellation_of_invoice",
|
"unlink_payment_on_cancellation_of_invoice",
|
||||||
"automatically_fetch_payment_terms",
|
|
||||||
"delete_linked_ledger_entries",
|
|
||||||
"book_asset_depreciation_entry_automatically",
|
|
||||||
"unlink_advance_payment_on_cancelation_of_order",
|
"unlink_advance_payment_on_cancelation_of_order",
|
||||||
|
"column_break_13",
|
||||||
|
"delete_linked_ledger_entries",
|
||||||
|
"invoicing_features_section",
|
||||||
|
"check_supplier_invoice_uniqueness",
|
||||||
|
"automatically_fetch_payment_terms",
|
||||||
|
"column_break_17",
|
||||||
"enable_common_party_accounting",
|
"enable_common_party_accounting",
|
||||||
"post_change_gl_entries",
|
|
||||||
"enable_discount_accounting",
|
"enable_discount_accounting",
|
||||||
"tax_settings_section",
|
"report_setting_section",
|
||||||
"determine_address_tax_category_from",
|
"use_custom_cash_flow",
|
||||||
"column_break_19",
|
|
||||||
"add_taxes_from_item_tax_template",
|
|
||||||
"period_closing_settings_section",
|
|
||||||
"acc_frozen_upto",
|
|
||||||
"frozen_accounts_modifier",
|
|
||||||
"column_break_4",
|
|
||||||
"deferred_accounting_settings_section",
|
"deferred_accounting_settings_section",
|
||||||
"book_deferred_entries_based_on",
|
"book_deferred_entries_based_on",
|
||||||
"column_break_18",
|
"column_break_18",
|
||||||
"automatically_process_deferred_accounting_entry",
|
"automatically_process_deferred_accounting_entry",
|
||||||
"book_deferred_entries_via_journal_entry",
|
"book_deferred_entries_via_journal_entry",
|
||||||
"submit_journal_entries",
|
"submit_journal_entries",
|
||||||
|
"tax_settings_section",
|
||||||
|
"determine_address_tax_category_from",
|
||||||
|
"column_break_19",
|
||||||
|
"add_taxes_from_item_tax_template",
|
||||||
"print_settings",
|
"print_settings",
|
||||||
"show_inclusive_tax_in_print",
|
"show_inclusive_tax_in_print",
|
||||||
"column_break_12",
|
"column_break_12",
|
||||||
@ -43,8 +38,25 @@
|
|||||||
"currency_exchange_section",
|
"currency_exchange_section",
|
||||||
"allow_stale",
|
"allow_stale",
|
||||||
"stale_days",
|
"stale_days",
|
||||||
"report_settings_sb",
|
"invoicing_settings_tab",
|
||||||
"use_custom_cash_flow"
|
"accounts_transactions_settings_section",
|
||||||
|
"over_billing_allowance",
|
||||||
|
"column_break_11",
|
||||||
|
"role_allowed_to_over_bill",
|
||||||
|
"credit_controller",
|
||||||
|
"make_payment_via_journal_entry",
|
||||||
|
"pos_tab",
|
||||||
|
"pos_setting_section",
|
||||||
|
"post_change_gl_entries",
|
||||||
|
"assets_tab",
|
||||||
|
"asset_settings_section",
|
||||||
|
"book_asset_depreciation_entry_automatically",
|
||||||
|
"closing_settings_tab",
|
||||||
|
"period_closing_settings_section",
|
||||||
|
"acc_frozen_upto",
|
||||||
|
"column_break_25",
|
||||||
|
"frozen_accounts_modifier",
|
||||||
|
"report_settings_sb"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@ -70,10 +82,6 @@
|
|||||||
"label": "Determine Address Tax Category From",
|
"label": "Determine Address Tax Category From",
|
||||||
"options": "Billing Address\nShipping Address"
|
"options": "Billing Address\nShipping Address"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "column_break_4",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "credit_controller",
|
"fieldname": "credit_controller",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
@ -83,6 +91,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
|
"description": "Enabling ensure each Sales Invoice has a unique value in Supplier Invoice No. field",
|
||||||
"fieldname": "check_supplier_invoice_uniqueness",
|
"fieldname": "check_supplier_invoice_uniqueness",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Check Supplier Invoice Number Uniqueness"
|
"label": "Check Supplier Invoice Number Uniqueness"
|
||||||
@ -168,7 +177,7 @@
|
|||||||
"description": "Only select this if you have set up the Cash Flow Mapper documents",
|
"description": "Only select this if you have set up the Cash Flow Mapper documents",
|
||||||
"fieldname": "use_custom_cash_flow",
|
"fieldname": "use_custom_cash_flow",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Use Custom Cash Flow Format"
|
"label": "Enable Custom Cash Flow Format"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
@ -241,7 +250,7 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "accounts_transactions_settings_section",
|
"fieldname": "accounts_transactions_settings_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Transactions Settings"
|
"label": "Credit Limit Settings"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "column_break_11",
|
"fieldname": "column_break_11",
|
||||||
@ -272,9 +281,72 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
|
"description": "Learn about <a href=\"https://docs.erpnext.com/docs/v13/user/manual/en/accounts/articles/common_party_accounting#:~:text=Common%20Party%20Accounting%20in%20ERPNext,Invoice%20against%20a%20primary%20Supplier.\">Common Party</a>",
|
||||||
"fieldname": "enable_common_party_accounting",
|
"fieldname": "enable_common_party_accounting",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Enable Common Party Accounting"
|
"label": "Enable Common Party Accounting"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "enable_features_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Invoice Cancellation"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_13",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_25",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "asset_settings_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Asset Settings"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "invoicing_settings_tab",
|
||||||
|
"fieldtype": "Tab Break",
|
||||||
|
"label": "Credit Limits"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "assets_tab",
|
||||||
|
"fieldtype": "Tab Break",
|
||||||
|
"label": "Assets"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "closing_settings_tab",
|
||||||
|
"fieldtype": "Tab Break",
|
||||||
|
"label": "Accounts Closing"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "pos_setting_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "POS Setting"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "invoice_and_billing_tab",
|
||||||
|
"fieldtype": "Tab Break",
|
||||||
|
"label": "Invoice and Billing"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "invoicing_features_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Invoicing Features"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_17",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "pos_tab",
|
||||||
|
"fieldtype": "Tab Break",
|
||||||
|
"label": "POS"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "report_setting_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Report Setting"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "icon-cog",
|
"icon": "icon-cog",
|
||||||
@ -282,7 +354,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-10-11 17:42:36.427699",
|
"modified": "2022-02-04 12:32:36.805652",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Accounts Settings",
|
"name": "Accounts Settings",
|
||||||
@ -309,5 +381,6 @@
|
|||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "ASC",
|
"sort_order": "ASC",
|
||||||
|
"states": [],
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
@ -2,7 +2,7 @@
|
|||||||
"actions": [],
|
"actions": [],
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"allow_rename": 1,
|
"allow_rename": 1,
|
||||||
"creation": "2018-11-22 22:45:00.370913",
|
"creation": "2022-01-19 01:09:13.297137",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "Setup",
|
"document_type": "Setup",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
@ -10,6 +10,9 @@
|
|||||||
"field_order": [
|
"field_order": [
|
||||||
"title",
|
"title",
|
||||||
"company",
|
"company",
|
||||||
|
"column_break_3",
|
||||||
|
"disabled",
|
||||||
|
"section_break_5",
|
||||||
"taxes"
|
"taxes"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
@ -36,10 +39,24 @@
|
|||||||
"label": "Company",
|
"label": "Company",
|
||||||
"options": "Company",
|
"options": "Company",
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_3",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "disabled",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Disabled"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "section_break_5",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-03-08 19:50:21.416513",
|
"modified": "2022-01-18 21:11:23.105589",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Item Tax Template",
|
"name": "Item Tax Template",
|
||||||
@ -82,6 +99,7 @@
|
|||||||
"show_name_in_global_search": 1,
|
"show_name_in_global_search": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
"title_field": "title",
|
"title_field": "title",
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
@ -8,6 +8,7 @@ frappe.provide("erpnext.journal_entry");
|
|||||||
frappe.ui.form.on("Journal Entry", {
|
frappe.ui.form.on("Journal Entry", {
|
||||||
setup: function(frm) {
|
setup: function(frm) {
|
||||||
frm.add_fetch("bank_account", "account", "account");
|
frm.add_fetch("bank_account", "account", "account");
|
||||||
|
frm.ignore_doctypes_on_cancel_all = ['Sales Invoice', 'Purchase Invoice'];
|
||||||
},
|
},
|
||||||
|
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
|
@ -537,8 +537,11 @@ class PurchaseInvoice(BuyingController):
|
|||||||
|
|
||||||
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',
|
stock_ledger_entries = frappe.get_all("Stock Ledger Entry",
|
||||||
fields = ["voucher_detail_no", "stock_value_difference", "warehouse"], filters={'voucher_no': self.name}):
|
fields = ["voucher_detail_no", "stock_value_difference", "warehouse"],
|
||||||
|
filters={"voucher_no": self.name, "voucher_type": self.doctype, "is_cancelled": 0}
|
||||||
|
)
|
||||||
|
for d in stock_ledger_entries:
|
||||||
voucher_wise_stock_value.setdefault((d.voucher_detail_no, d.warehouse), d.stock_value_difference)
|
voucher_wise_stock_value.setdefault((d.voucher_detail_no, d.warehouse), 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")
|
||||||
|
@ -2,12 +2,13 @@
|
|||||||
"actions": [],
|
"actions": [],
|
||||||
"allow_rename": 1,
|
"allow_rename": 1,
|
||||||
"autoname": "field:title",
|
"autoname": "field:title",
|
||||||
"creation": "2018-11-22 23:38:39.668804",
|
"creation": "2022-01-19 01:09:28.920486",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
"title"
|
"title",
|
||||||
|
"disabled"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@ -18,14 +19,21 @@
|
|||||||
"label": "Title",
|
"label": "Title",
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"unique": 1
|
"unique": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "disabled",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Disabled"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-03-03 11:50:38.748872",
|
"modified": "2022-01-18 21:13:41.161017",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Tax Category",
|
"name": "Tax Category",
|
||||||
|
"naming_rule": "By fieldname",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
@ -65,5 +73,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
|
||||||
}
|
}
|
@ -120,11 +120,11 @@ def check_opening_balance(asset, liability, equity):
|
|||||||
opening_balance = 0
|
opening_balance = 0
|
||||||
float_precision = cint(frappe.db.get_default("float_precision")) or 2
|
float_precision = cint(frappe.db.get_default("float_precision")) or 2
|
||||||
if asset:
|
if asset:
|
||||||
opening_balance = flt(asset[0].get("opening_balance", 0), float_precision)
|
opening_balance = flt(asset[-1].get("opening_balance", 0), float_precision)
|
||||||
if liability:
|
if liability:
|
||||||
opening_balance -= flt(liability[0].get("opening_balance", 0), float_precision)
|
opening_balance -= flt(liability[-1].get("opening_balance", 0), float_precision)
|
||||||
if equity:
|
if equity:
|
||||||
opening_balance -= flt(equity[0].get("opening_balance", 0), float_precision)
|
opening_balance -= flt(equity[-1].get("opening_balance", 0), float_precision)
|
||||||
|
|
||||||
opening_balance = flt(opening_balance, float_precision)
|
opening_balance = flt(opening_balance, float_precision)
|
||||||
if opening_balance:
|
if opening_balance:
|
||||||
|
@ -282,7 +282,8 @@ def add_total_row(out, root_type, balance_must_be, period_list, company_currency
|
|||||||
total_row = {
|
total_row = {
|
||||||
"account_name": _("Total {0} ({1})").format(_(root_type), _(balance_must_be)),
|
"account_name": _("Total {0} ({1})").format(_(root_type), _(balance_must_be)),
|
||||||
"account": _("Total {0} ({1})").format(_(root_type), _(balance_must_be)),
|
"account": _("Total {0} ({1})").format(_(root_type), _(balance_must_be)),
|
||||||
"currency": company_currency
|
"currency": company_currency,
|
||||||
|
"opening_balance": 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
for row in out:
|
for row in out:
|
||||||
@ -294,6 +295,7 @@ def add_total_row(out, root_type, balance_must_be, period_list, company_currency
|
|||||||
|
|
||||||
total_row.setdefault("total", 0.0)
|
total_row.setdefault("total", 0.0)
|
||||||
total_row["total"] += flt(row["total"])
|
total_row["total"] += flt(row["total"])
|
||||||
|
total_row["opening_balance"] += row["opening_balance"]
|
||||||
row["total"] = ""
|
row["total"] = ""
|
||||||
|
|
||||||
if "total" in total_row:
|
if "total" in total_row:
|
||||||
|
@ -6,14 +6,17 @@
|
|||||||
"document_type": "Other",
|
"document_type": "Other",
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
|
"supplier_and_price_defaults_section",
|
||||||
"supp_master_name",
|
"supp_master_name",
|
||||||
"supplier_group",
|
"supplier_group",
|
||||||
|
"column_break_4",
|
||||||
"buying_price_list",
|
"buying_price_list",
|
||||||
"maintain_same_rate_action",
|
"maintain_same_rate_action",
|
||||||
"role_to_override_stop_action",
|
"role_to_override_stop_action",
|
||||||
"column_break_3",
|
"transaction_settings_section",
|
||||||
"po_required",
|
"po_required",
|
||||||
"pr_required",
|
"pr_required",
|
||||||
|
"column_break_12",
|
||||||
"maintain_same_rate",
|
"maintain_same_rate",
|
||||||
"allow_multiple_items",
|
"allow_multiple_items",
|
||||||
"bill_for_rejected_quantity_in_purchase_invoice",
|
"bill_for_rejected_quantity_in_purchase_invoice",
|
||||||
@ -42,10 +45,6 @@
|
|||||||
"label": "Default Buying Price List",
|
"label": "Default Buying Price List",
|
||||||
"options": "Price List"
|
"options": "Price List"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "column_break_3",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "po_required",
|
"fieldname": "po_required",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
@ -73,7 +72,7 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "subcontract",
|
"fieldname": "subcontract",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Subcontract"
|
"label": "Subcontracting Settings"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "Material Transferred for Subcontract",
|
"default": "Material Transferred for Subcontract",
|
||||||
@ -116,6 +115,24 @@
|
|||||||
"fieldname": "bill_for_rejected_quantity_in_purchase_invoice",
|
"fieldname": "bill_for_rejected_quantity_in_purchase_invoice",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Bill for Rejected Quantity in Purchase Invoice"
|
"label": "Bill for Rejected Quantity in Purchase Invoice"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "supplier_and_price_defaults_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Supplier and Price Defaults"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_4",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "transaction_settings_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Transaction Settings"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_12",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-cog",
|
"icon": "fa fa-cog",
|
||||||
@ -123,7 +140,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-09-08 19:26:23.548837",
|
"modified": "2022-01-27 17:57:58.367048",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Buying Settings",
|
"name": "Buying Settings",
|
||||||
@ -141,5 +158,6 @@
|
|||||||
],
|
],
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
@ -710,6 +710,7 @@ def get_tax_template(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
|
|
||||||
item_doc = frappe.get_cached_doc('Item', filters.get('item_code'))
|
item_doc = frappe.get_cached_doc('Item', filters.get('item_code'))
|
||||||
item_group = filters.get('item_group')
|
item_group = filters.get('item_group')
|
||||||
|
company = filters.get('company')
|
||||||
taxes = item_doc.taxes or []
|
taxes = item_doc.taxes or []
|
||||||
|
|
||||||
while item_group:
|
while item_group:
|
||||||
@ -718,7 +719,7 @@ def get_tax_template(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
item_group = item_group_doc.parent_item_group
|
item_group = item_group_doc.parent_item_group
|
||||||
|
|
||||||
if not taxes:
|
if not taxes:
|
||||||
return frappe.db.sql(""" SELECT name FROM `tabItem Tax Template` """)
|
return frappe.get_all('Item Tax Template', filters={'disabled': 0, 'company': company}, as_list=True)
|
||||||
else:
|
else:
|
||||||
valid_from = filters.get('valid_from')
|
valid_from = filters.get('valid_from')
|
||||||
valid_from = valid_from[1] if isinstance(valid_from, list) else valid_from
|
valid_from = valid_from[1] if isinstance(valid_from, list) else valid_from
|
||||||
@ -727,7 +728,7 @@ def get_tax_template(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
'item_code': filters.get('item_code'),
|
'item_code': filters.get('item_code'),
|
||||||
'posting_date': valid_from,
|
'posting_date': valid_from,
|
||||||
'tax_category': filters.get('tax_category'),
|
'tax_category': filters.get('tax_category'),
|
||||||
'company': filters.get('company')
|
'company': company
|
||||||
}
|
}
|
||||||
|
|
||||||
taxes = _get_item_tax_template(args, taxes, for_validate=True)
|
taxes = _get_item_tax_template(args, taxes, for_validate=True)
|
||||||
|
@ -74,7 +74,8 @@ class SellingController(StockController):
|
|||||||
doctype=self.doctype, company=self.company,
|
doctype=self.doctype, company=self.company,
|
||||||
posting_date=self.get('posting_date'),
|
posting_date=self.get('posting_date'),
|
||||||
fetch_payment_terms_template=fetch_payment_terms_template,
|
fetch_payment_terms_template=fetch_payment_terms_template,
|
||||||
party_address=self.customer_address, shipping_address=self.shipping_address_name)
|
party_address=self.customer_address, shipping_address=self.shipping_address_name,
|
||||||
|
company_address=self.get('company_address'))
|
||||||
if not self.meta.get_field("sales_team"):
|
if not self.meta.get_field("sales_team"):
|
||||||
party_details.pop("sales_team")
|
party_details.pop("sales_team")
|
||||||
self.update_if_missing(party_details)
|
self.update_if_missing(party_details)
|
||||||
|
@ -400,6 +400,16 @@ class StatusUpdater(Document):
|
|||||||
ref_doc = frappe.get_doc(ref_dt, ref_dn)
|
ref_doc = frappe.get_doc(ref_dt, ref_dn)
|
||||||
|
|
||||||
ref_doc.db_set("per_billed", per_billed)
|
ref_doc.db_set("per_billed", per_billed)
|
||||||
|
|
||||||
|
# set billling status
|
||||||
|
if hasattr(ref_doc, 'billing_status'):
|
||||||
|
if ref_doc.per_billed < 0.001:
|
||||||
|
ref_doc.db_set("billing_status", "Not Billed")
|
||||||
|
elif ref_doc.per_billed > 99.999999:
|
||||||
|
ref_doc.db_set("billing_status", "Fully Billed")
|
||||||
|
else:
|
||||||
|
ref_doc.db_set("billing_status", "Partly Billed")
|
||||||
|
|
||||||
ref_doc.set_status(update=True)
|
ref_doc.set_status(update=True)
|
||||||
|
|
||||||
def get_allowance_for(item_code, item_allowance=None, global_qty_allowance=None, global_amount_allowance=None, qty_or_amount="qty"):
|
def get_allowance_for(item_code, item_allowance=None, global_qty_allowance=None, global_amount_allowance=None, qty_or_amount="qty"):
|
||||||
|
@ -46,7 +46,7 @@ frappe.ui.form.on('Loan', {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$.each(["payment_account", "loan_account"], function (i, field) {
|
$.each(["payment_account", "loan_account", "disbursement_account"], function (i, field) {
|
||||||
frm.set_query(field, function () {
|
frm.set_query(field, function () {
|
||||||
return {
|
return {
|
||||||
"filters": {
|
"filters": {
|
||||||
@ -88,6 +88,10 @@ frappe.ui.form.on('Loan', {
|
|||||||
frm.add_custom_button(__('Loan Write Off'), function() {
|
frm.add_custom_button(__('Loan Write Off'), function() {
|
||||||
frm.trigger("make_loan_write_off_entry");
|
frm.trigger("make_loan_write_off_entry");
|
||||||
},__('Create'));
|
},__('Create'));
|
||||||
|
|
||||||
|
frm.add_custom_button(__('Loan Refund'), function() {
|
||||||
|
frm.trigger("make_loan_refund");
|
||||||
|
},__('Create'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
frm.trigger("toggle_fields");
|
frm.trigger("toggle_fields");
|
||||||
@ -155,6 +159,21 @@ frappe.ui.form.on('Loan', {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
make_loan_refund: function(frm) {
|
||||||
|
frappe.call({
|
||||||
|
args: {
|
||||||
|
"loan": frm.doc.name
|
||||||
|
},
|
||||||
|
method: "erpnext.loan_management.doctype.loan.loan.make_refund_jv",
|
||||||
|
callback: function (r) {
|
||||||
|
if (r.message) {
|
||||||
|
let doc = frappe.model.sync(r.message)[0];
|
||||||
|
frappe.set_route("Form", doc.doctype, doc.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
request_loan_closure: function(frm) {
|
request_loan_closure: function(frm) {
|
||||||
frappe.confirm(__("Do you really want to close this loan"),
|
frappe.confirm(__("Do you really want to close this loan"),
|
||||||
function() {
|
function() {
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"actions": [],
|
"actions": [],
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"autoname": "ACC-LOAN-.YYYY.-.#####",
|
"autoname": "ACC-LOAN-.YYYY.-.#####",
|
||||||
"creation": "2019-08-29 17:29:18.176786",
|
"creation": "2022-01-25 10:30:02.294967",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "Document",
|
"document_type": "Document",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
@ -34,6 +34,7 @@
|
|||||||
"is_term_loan",
|
"is_term_loan",
|
||||||
"account_info",
|
"account_info",
|
||||||
"mode_of_payment",
|
"mode_of_payment",
|
||||||
|
"disbursement_account",
|
||||||
"payment_account",
|
"payment_account",
|
||||||
"column_break_9",
|
"column_break_9",
|
||||||
"loan_account",
|
"loan_account",
|
||||||
@ -356,12 +357,21 @@
|
|||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"label": "Closure Date",
|
"label": "Closure Date",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "loan_type.disbursement_account",
|
||||||
|
"fieldname": "disbursement_account",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Disbursement Account",
|
||||||
|
"options": "Account",
|
||||||
|
"read_only": 1,
|
||||||
|
"reqd": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-10-12 18:10:32.360818",
|
"modified": "2022-01-25 16:29:16.325501",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Loan Management",
|
"module": "Loan Management",
|
||||||
"name": "Loan",
|
"name": "Loan",
|
||||||
@ -391,5 +401,6 @@
|
|||||||
"search_fields": "posting_date",
|
"search_fields": "posting_date",
|
||||||
"sort_field": "creation",
|
"sort_field": "creation",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
@ -10,6 +10,7 @@ from frappe import _
|
|||||||
from frappe.utils import add_months, flt, get_last_day, getdate, now_datetime, nowdate
|
from frappe.utils import add_months, flt, get_last_day, getdate, now_datetime, nowdate
|
||||||
|
|
||||||
import erpnext
|
import erpnext
|
||||||
|
from erpnext.accounts.doctype.journal_entry.journal_entry import get_payment_entry
|
||||||
from erpnext.controllers.accounts_controller import AccountsController
|
from erpnext.controllers.accounts_controller import AccountsController
|
||||||
from erpnext.loan_management.doctype.loan_repayment.loan_repayment import calculate_amounts
|
from erpnext.loan_management.doctype.loan_repayment.loan_repayment import calculate_amounts
|
||||||
from erpnext.loan_management.doctype.loan_security_unpledge.loan_security_unpledge import (
|
from erpnext.loan_management.doctype.loan_security_unpledge.loan_security_unpledge import (
|
||||||
@ -233,17 +234,15 @@ def request_loan_closure(loan, posting_date=None):
|
|||||||
loan_type = frappe.get_value('Loan', loan, 'loan_type')
|
loan_type = frappe.get_value('Loan', loan, 'loan_type')
|
||||||
write_off_limit = frappe.get_value('Loan Type', loan_type, 'write_off_amount')
|
write_off_limit = frappe.get_value('Loan Type', loan_type, 'write_off_amount')
|
||||||
|
|
||||||
# checking greater than 0 as there may be some minor precision error
|
if pending_amount and abs(pending_amount) < write_off_limit:
|
||||||
if not pending_amount:
|
|
||||||
frappe.db.set_value('Loan', loan, 'status', 'Loan Closure Requested')
|
|
||||||
elif pending_amount < write_off_limit:
|
|
||||||
# Auto create loan write off and update status as loan closure requested
|
# Auto create loan write off and update status as loan closure requested
|
||||||
write_off = make_loan_write_off(loan)
|
write_off = make_loan_write_off(loan)
|
||||||
write_off.submit()
|
write_off.submit()
|
||||||
frappe.db.set_value('Loan', loan, 'status', 'Loan Closure Requested')
|
elif pending_amount > 0:
|
||||||
else:
|
|
||||||
frappe.throw(_("Cannot close loan as there is an outstanding of {0}").format(pending_amount))
|
frappe.throw(_("Cannot close loan as there is an outstanding of {0}").format(pending_amount))
|
||||||
|
|
||||||
|
frappe.db.set_value('Loan', loan, 'status', 'Loan Closure Requested')
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_loan_application(loan_application):
|
def get_loan_application(loan_application):
|
||||||
loan = frappe.get_doc("Loan Application", loan_application)
|
loan = frappe.get_doc("Loan Application", loan_application)
|
||||||
@ -401,3 +400,38 @@ def add_single_month(date):
|
|||||||
return get_last_day(add_months(date, 1))
|
return get_last_day(add_months(date, 1))
|
||||||
else:
|
else:
|
||||||
return add_months(date, 1)
|
return add_months(date, 1)
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def make_refund_jv(loan, amount=0, reference_number=None, reference_date=None, submit=0):
|
||||||
|
loan_details = frappe.db.get_value('Loan', loan, ['applicant_type', 'applicant',
|
||||||
|
'loan_account', 'payment_account', 'posting_date', 'company', 'name',
|
||||||
|
'total_payment', 'total_principal_paid'], as_dict=1)
|
||||||
|
|
||||||
|
loan_details.doctype = 'Loan'
|
||||||
|
loan_details[loan_details.applicant_type.lower()] = loan_details.applicant
|
||||||
|
|
||||||
|
if not amount:
|
||||||
|
amount = flt(loan_details.total_principal_paid - loan_details.total_payment)
|
||||||
|
|
||||||
|
if amount < 0:
|
||||||
|
frappe.throw(_('No excess amount pending for refund'))
|
||||||
|
|
||||||
|
refund_jv = get_payment_entry(loan_details, {
|
||||||
|
"party_type": loan_details.applicant_type,
|
||||||
|
"party_account": loan_details.loan_account,
|
||||||
|
"amount_field_party": 'debit_in_account_currency',
|
||||||
|
"amount_field_bank": 'credit_in_account_currency',
|
||||||
|
"amount": amount,
|
||||||
|
"bank_account": loan_details.payment_account
|
||||||
|
})
|
||||||
|
|
||||||
|
if reference_number:
|
||||||
|
refund_jv.cheque_no = reference_number
|
||||||
|
|
||||||
|
if reference_date:
|
||||||
|
refund_jv.cheque_date = reference_date
|
||||||
|
|
||||||
|
if submit:
|
||||||
|
refund_jv.submit()
|
||||||
|
|
||||||
|
return refund_jv
|
@ -42,16 +42,17 @@ class TestLoan(unittest.TestCase):
|
|||||||
create_loan_type("Personal Loan", 500000, 8.4,
|
create_loan_type("Personal Loan", 500000, 8.4,
|
||||||
is_term_loan=1,
|
is_term_loan=1,
|
||||||
mode_of_payment='Cash',
|
mode_of_payment='Cash',
|
||||||
|
disbursement_account='Disbursement Account - _TC',
|
||||||
payment_account='Payment Account - _TC',
|
payment_account='Payment Account - _TC',
|
||||||
loan_account='Loan Account - _TC',
|
loan_account='Loan Account - _TC',
|
||||||
interest_income_account='Interest Income Account - _TC',
|
interest_income_account='Interest Income Account - _TC',
|
||||||
penalty_income_account='Penalty Income Account - _TC')
|
penalty_income_account='Penalty Income Account - _TC')
|
||||||
|
|
||||||
create_loan_type("Stock Loan", 2000000, 13.5, 25, 1, 5, 'Cash', 'Payment Account - _TC', 'Loan Account - _TC',
|
create_loan_type("Stock Loan", 2000000, 13.5, 25, 1, 5, 'Cash', 'Disbursement Account - _TC',
|
||||||
'Interest Income Account - _TC', 'Penalty Income Account - _TC')
|
'Payment Account - _TC', 'Loan Account - _TC', 'Interest Income Account - _TC', 'Penalty Income Account - _TC')
|
||||||
|
|
||||||
create_loan_type("Demand Loan", 2000000, 13.5, 25, 0, 5, 'Cash', 'Payment Account - _TC', 'Loan Account - _TC',
|
create_loan_type("Demand Loan", 2000000, 13.5, 25, 0, 5, 'Cash', 'Disbursement Account - _TC',
|
||||||
'Interest Income Account - _TC', 'Penalty Income Account - _TC')
|
'Payment Account - _TC', 'Loan Account - _TC', 'Interest Income Account - _TC', 'Penalty Income Account - _TC')
|
||||||
|
|
||||||
create_loan_security_type()
|
create_loan_security_type()
|
||||||
create_loan_security()
|
create_loan_security()
|
||||||
@ -679,6 +680,29 @@ class TestLoan(unittest.TestCase):
|
|||||||
loan.load_from_db()
|
loan.load_from_db()
|
||||||
self.assertEqual(loan.status, "Loan Closure Requested")
|
self.assertEqual(loan.status, "Loan Closure Requested")
|
||||||
|
|
||||||
|
def test_loan_repayment_against_partially_disbursed_loan(self):
|
||||||
|
pledge = [{
|
||||||
|
"loan_security": "Test Security 1",
|
||||||
|
"qty": 4000.00
|
||||||
|
}]
|
||||||
|
|
||||||
|
loan_application = create_loan_application('_Test Company', self.applicant2, 'Demand Loan', pledge)
|
||||||
|
create_pledge(loan_application)
|
||||||
|
|
||||||
|
loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date='2019-10-01')
|
||||||
|
loan.submit()
|
||||||
|
|
||||||
|
first_date = '2019-10-01'
|
||||||
|
last_date = '2019-10-30'
|
||||||
|
|
||||||
|
make_loan_disbursement_entry(loan.name, loan.loan_amount/2, disbursement_date=first_date)
|
||||||
|
|
||||||
|
loan.load_from_db()
|
||||||
|
|
||||||
|
self.assertEqual(loan.status, "Partially Disbursed")
|
||||||
|
create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 5),
|
||||||
|
flt(loan.loan_amount/3))
|
||||||
|
|
||||||
def test_loan_amount_write_off(self):
|
def test_loan_amount_write_off(self):
|
||||||
pledge = [{
|
pledge = [{
|
||||||
"loan_security": "Test Security 1",
|
"loan_security": "Test Security 1",
|
||||||
@ -790,6 +814,18 @@ def create_loan_accounts():
|
|||||||
"account_type": "Bank",
|
"account_type": "Bank",
|
||||||
}).insert(ignore_permissions=True)
|
}).insert(ignore_permissions=True)
|
||||||
|
|
||||||
|
if not frappe.db.exists("Account", "Disbursement Account - _TC"):
|
||||||
|
frappe.get_doc({
|
||||||
|
"doctype": "Account",
|
||||||
|
"company": "_Test Company",
|
||||||
|
"account_name": "Disbursement Account",
|
||||||
|
"root_type": "Asset",
|
||||||
|
"report_type": "Balance Sheet",
|
||||||
|
"currency": "INR",
|
||||||
|
"parent_account": "Bank Accounts - _TC",
|
||||||
|
"account_type": "Bank",
|
||||||
|
}).insert(ignore_permissions=True)
|
||||||
|
|
||||||
if not frappe.db.exists("Account", "Interest Income Account - _TC"):
|
if not frappe.db.exists("Account", "Interest Income Account - _TC"):
|
||||||
frappe.get_doc({
|
frappe.get_doc({
|
||||||
"doctype": "Account",
|
"doctype": "Account",
|
||||||
@ -815,7 +851,7 @@ def create_loan_accounts():
|
|||||||
}).insert(ignore_permissions=True)
|
}).insert(ignore_permissions=True)
|
||||||
|
|
||||||
def create_loan_type(loan_name, maximum_loan_amount, rate_of_interest, penalty_interest_rate=None, is_term_loan=None, grace_period_in_days=None,
|
def create_loan_type(loan_name, maximum_loan_amount, rate_of_interest, penalty_interest_rate=None, is_term_loan=None, grace_period_in_days=None,
|
||||||
mode_of_payment=None, payment_account=None, loan_account=None, interest_income_account=None, penalty_income_account=None,
|
mode_of_payment=None, disbursement_account=None, payment_account=None, loan_account=None, interest_income_account=None, penalty_income_account=None,
|
||||||
repayment_method=None, repayment_periods=None):
|
repayment_method=None, repayment_periods=None):
|
||||||
|
|
||||||
if not frappe.db.exists("Loan Type", loan_name):
|
if not frappe.db.exists("Loan Type", loan_name):
|
||||||
@ -829,6 +865,7 @@ def create_loan_type(loan_name, maximum_loan_amount, rate_of_interest, penalty_i
|
|||||||
"penalty_interest_rate": penalty_interest_rate,
|
"penalty_interest_rate": penalty_interest_rate,
|
||||||
"grace_period_in_days": grace_period_in_days,
|
"grace_period_in_days": grace_period_in_days,
|
||||||
"mode_of_payment": mode_of_payment,
|
"mode_of_payment": mode_of_payment,
|
||||||
|
"disbursement_account": disbursement_account,
|
||||||
"payment_account": payment_account,
|
"payment_account": payment_account,
|
||||||
"loan_account": loan_account,
|
"loan_account": loan_account,
|
||||||
"interest_income_account": interest_income_account,
|
"interest_income_account": interest_income_account,
|
||||||
|
@ -15,7 +15,7 @@ from erpnext.payroll.doctype.salary_structure.test_salary_structure import (
|
|||||||
class TestLoanApplication(unittest.TestCase):
|
class TestLoanApplication(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
create_loan_accounts()
|
create_loan_accounts()
|
||||||
create_loan_type("Home Loan", 500000, 9.2, 0, 1, 0, 'Cash', 'Payment Account - _TC', 'Loan Account - _TC',
|
create_loan_type("Home Loan", 500000, 9.2, 0, 1, 0, 'Cash', 'Disbursement Account - _TC', 'Payment Account - _TC', 'Loan Account - _TC',
|
||||||
'Interest Income Account - _TC', 'Penalty Income Account - _TC', 'Repay Over Number of Periods', 18)
|
'Interest Income Account - _TC', 'Penalty Income Account - _TC', 'Repay Over Number of Periods', 18)
|
||||||
self.applicant = make_employee("kate_loan@loan.com", "_Test Company")
|
self.applicant = make_employee("kate_loan@loan.com", "_Test Company")
|
||||||
make_salary_structure("Test Salary Structure Loan", "Monthly", employee=self.applicant, currency='INR')
|
make_salary_structure("Test Salary Structure Loan", "Monthly", employee=self.applicant, currency='INR')
|
||||||
|
@ -122,7 +122,7 @@ class LoanDisbursement(AccountsController):
|
|||||||
gle_map.append(
|
gle_map.append(
|
||||||
self.get_gl_dict({
|
self.get_gl_dict({
|
||||||
"account": loan_details.loan_account,
|
"account": loan_details.loan_account,
|
||||||
"against": loan_details.payment_account,
|
"against": loan_details.disbursement_account,
|
||||||
"debit": self.disbursed_amount,
|
"debit": self.disbursed_amount,
|
||||||
"debit_in_account_currency": self.disbursed_amount,
|
"debit_in_account_currency": self.disbursed_amount,
|
||||||
"against_voucher_type": "Loan",
|
"against_voucher_type": "Loan",
|
||||||
@ -137,7 +137,7 @@ class LoanDisbursement(AccountsController):
|
|||||||
|
|
||||||
gle_map.append(
|
gle_map.append(
|
||||||
self.get_gl_dict({
|
self.get_gl_dict({
|
||||||
"account": loan_details.payment_account,
|
"account": loan_details.disbursement_account,
|
||||||
"against": loan_details.loan_account,
|
"against": loan_details.loan_account,
|
||||||
"credit": self.disbursed_amount,
|
"credit": self.disbursed_amount,
|
||||||
"credit_in_account_currency": self.disbursed_amount,
|
"credit_in_account_currency": self.disbursed_amount,
|
||||||
|
@ -44,8 +44,8 @@ class TestLoanDisbursement(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
create_loan_accounts()
|
create_loan_accounts()
|
||||||
|
|
||||||
create_loan_type("Demand Loan", 2000000, 13.5, 25, 0, 5, 'Cash', 'Payment Account - _TC', 'Loan Account - _TC',
|
create_loan_type("Demand Loan", 2000000, 13.5, 25, 0, 5, 'Cash', 'Disbursement Account - _TC',
|
||||||
'Interest Income Account - _TC', 'Penalty Income Account - _TC')
|
'Payment Account - _TC', 'Loan Account - _TC', 'Interest Income Account - _TC', 'Penalty Income Account - _TC')
|
||||||
|
|
||||||
create_loan_security_type()
|
create_loan_security_type()
|
||||||
create_loan_security()
|
create_loan_security()
|
||||||
|
@ -30,8 +30,8 @@ class TestLoanInterestAccrual(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
create_loan_accounts()
|
create_loan_accounts()
|
||||||
|
|
||||||
create_loan_type("Demand Loan", 2000000, 13.5, 25, 0, 5, 'Cash', 'Payment Account - _TC', 'Loan Account - _TC',
|
create_loan_type("Demand Loan", 2000000, 13.5, 25, 0, 5, 'Cash', 'Disbursement Account - _TC',
|
||||||
'Interest Income Account - _TC', 'Penalty Income Account - _TC')
|
'Payment Account - _TC', 'Loan Account - _TC', 'Interest Income Account - _TC', 'Penalty Income Account - _TC')
|
||||||
|
|
||||||
create_loan_security_type()
|
create_loan_security_type()
|
||||||
create_loan_security()
|
create_loan_security()
|
||||||
|
@ -125,7 +125,7 @@ class LoanRepayment(AccountsController):
|
|||||||
|
|
||||||
def update_paid_amount(self):
|
def update_paid_amount(self):
|
||||||
loan = frappe.get_value("Loan", self.against_loan, ['total_amount_paid', 'total_principal_paid',
|
loan = frappe.get_value("Loan", self.against_loan, ['total_amount_paid', 'total_principal_paid',
|
||||||
'status', 'is_secured_loan', 'total_payment', 'loan_amount', 'total_interest_payable',
|
'status', 'is_secured_loan', 'total_payment', 'loan_amount', 'disbursed_amount', 'total_interest_payable',
|
||||||
'written_off_amount'], as_dict=1)
|
'written_off_amount'], as_dict=1)
|
||||||
|
|
||||||
loan.update({
|
loan.update({
|
||||||
@ -153,7 +153,7 @@ class LoanRepayment(AccountsController):
|
|||||||
|
|
||||||
def mark_as_unpaid(self):
|
def mark_as_unpaid(self):
|
||||||
loan = frappe.get_value("Loan", self.against_loan, ['total_amount_paid', 'total_principal_paid',
|
loan = frappe.get_value("Loan", self.against_loan, ['total_amount_paid', 'total_principal_paid',
|
||||||
'status', 'is_secured_loan', 'total_payment', 'loan_amount', 'total_interest_payable',
|
'status', 'is_secured_loan', 'total_payment', 'loan_amount', 'disbursed_amount', 'total_interest_payable',
|
||||||
'written_off_amount'], as_dict=1)
|
'written_off_amount'], as_dict=1)
|
||||||
|
|
||||||
no_of_repayments = len(self.repayment_details)
|
no_of_repayments = len(self.repayment_details)
|
||||||
|
@ -15,7 +15,7 @@ frappe.ui.form.on('Loan Type', {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$.each(["payment_account", "loan_account"], function (i, field) {
|
$.each(["payment_account", "loan_account", "disbursement_account"], function (i, field) {
|
||||||
frm.set_query(field, function () {
|
frm.set_query(field, function () {
|
||||||
return {
|
return {
|
||||||
"filters": {
|
"filters": {
|
||||||
|
@ -19,9 +19,10 @@
|
|||||||
"description",
|
"description",
|
||||||
"account_details_section",
|
"account_details_section",
|
||||||
"mode_of_payment",
|
"mode_of_payment",
|
||||||
|
"disbursement_account",
|
||||||
"payment_account",
|
"payment_account",
|
||||||
"loan_account",
|
|
||||||
"column_break_12",
|
"column_break_12",
|
||||||
|
"loan_account",
|
||||||
"interest_income_account",
|
"interest_income_account",
|
||||||
"penalty_income_account",
|
"penalty_income_account",
|
||||||
"amended_from"
|
"amended_from"
|
||||||
@ -79,7 +80,7 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "payment_account",
|
"fieldname": "payment_account",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Payment Account",
|
"label": "Repayment Account",
|
||||||
"options": "Account",
|
"options": "Account",
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
@ -149,15 +150,23 @@
|
|||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Auto Write Off Amount ",
|
"label": "Auto Write Off Amount ",
|
||||||
"options": "Company:company:default_currency"
|
"options": "Company:company:default_currency"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "disbursement_account",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Disbursement Account",
|
||||||
|
"options": "Account",
|
||||||
|
"reqd": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-04-19 18:10:57.368490",
|
"modified": "2022-01-25 16:23:57.009349",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Loan Management",
|
"module": "Loan Management",
|
||||||
"name": "Loan Type",
|
"name": "Loan Type",
|
||||||
|
"naming_rule": "By fieldname",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
@ -181,5 +190,6 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC"
|
"sort_order": "DESC",
|
||||||
|
"states": []
|
||||||
}
|
}
|
@ -89,10 +89,10 @@ def get_bom_stock(filters):
|
|||||||
GROUP BY bom_item.item_code""".format(qty_field=qty_field, table=table, conditions=conditions, bom=bom), as_dict=1)
|
GROUP BY bom_item.item_code""".format(qty_field=qty_field, table=table, conditions=conditions, bom=bom), as_dict=1)
|
||||||
|
|
||||||
def get_manufacturer_records():
|
def get_manufacturer_records():
|
||||||
details = frappe.get_all('Item Manufacturer', fields = ["manufacturer", "manufacturer_part_no", "parent"])
|
details = frappe.get_all('Item Manufacturer', fields = ["manufacturer", "manufacturer_part_no", "item_code"])
|
||||||
manufacture_details = frappe._dict()
|
manufacture_details = frappe._dict()
|
||||||
for detail in details:
|
for detail in details:
|
||||||
dic = manufacture_details.setdefault(detail.get('parent'), {})
|
dic = manufacture_details.setdefault(detail.get('item_code'), {})
|
||||||
dic.setdefault('manufacturer', []).append(detail.get('manufacturer'))
|
dic.setdefault('manufacturer', []).append(detail.get('manufacturer'))
|
||||||
dic.setdefault('manufacturer_part', []).append(detail.get('manufacturer_part_no'))
|
dic.setdefault('manufacturer_part', []).append(detail.get('manufacturer_part_no'))
|
||||||
|
|
||||||
|
@ -172,10 +172,15 @@ class ProductionPlanReport(object):
|
|||||||
|
|
||||||
self.purchase_details = {}
|
self.purchase_details = {}
|
||||||
|
|
||||||
for d in frappe.get_all("Purchase Order Item",
|
purchased_items = frappe.get_all("Purchase Order Item",
|
||||||
fields=["item_code", "min(schedule_date) as arrival_date", "qty as arrival_qty", "warehouse"],
|
fields=["item_code", "min(schedule_date) as arrival_date", "qty as arrival_qty", "warehouse"],
|
||||||
filters = {"item_code": ("in", self.item_codes), "warehouse": ("in", self.warehouses)},
|
filters={
|
||||||
group_by = "item_code, warehouse"):
|
"item_code": ("in", self.item_codes),
|
||||||
|
"warehouse": ("in", self.warehouses),
|
||||||
|
"docstatus": 1,
|
||||||
|
},
|
||||||
|
group_by = "item_code, warehouse")
|
||||||
|
for d in purchased_items:
|
||||||
key = (d.item_code, d.warehouse)
|
key = (d.item_code, d.warehouse)
|
||||||
if key not in self.purchase_details:
|
if key not in self.purchase_details:
|
||||||
self.purchase_details.setdefault(key, d)
|
self.purchase_details.setdefault(key, d)
|
||||||
|
@ -349,3 +349,4 @@ erpnext.patches.v12_0.add_company_link_to_einvoice_settings
|
|||||||
erpnext.patches.v14_0.migrate_cost_center_allocations
|
erpnext.patches.v14_0.migrate_cost_center_allocations
|
||||||
erpnext.patches.v13_0.convert_to_website_item_in_item_card_group_template
|
erpnext.patches.v13_0.convert_to_website_item_in_item_card_group_template
|
||||||
erpnext.patches.v13_0.shopping_cart_to_ecommerce
|
erpnext.patches.v13_0.shopping_cart_to_ecommerce
|
||||||
|
erpnext.patches.v13_0.update_disbursement_account
|
||||||
|
22
erpnext/patches/v13_0/update_disbursement_account.py
Normal file
22
erpnext/patches/v13_0/update_disbursement_account.py
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
|
||||||
|
frappe.reload_doc("loan_management", "doctype", "loan_type")
|
||||||
|
frappe.reload_doc("loan_management", "doctype", "loan")
|
||||||
|
|
||||||
|
loan_type = frappe.qb.DocType("Loan Type")
|
||||||
|
loan = frappe.qb.DocType("Loan")
|
||||||
|
|
||||||
|
frappe.qb.update(
|
||||||
|
loan_type
|
||||||
|
).set(
|
||||||
|
loan_type.disbursement_account, loan_type.payment_account
|
||||||
|
).run()
|
||||||
|
|
||||||
|
frappe.qb.update(
|
||||||
|
loan
|
||||||
|
).set(
|
||||||
|
loan.disbursement_account, loan.payment_account
|
||||||
|
).run()
|
@ -214,6 +214,7 @@ class TestPayrollEntry(unittest.TestCase):
|
|||||||
create_loan_type("Car Loan", 500000, 8.4,
|
create_loan_type("Car Loan", 500000, 8.4,
|
||||||
is_term_loan=1,
|
is_term_loan=1,
|
||||||
mode_of_payment='Cash',
|
mode_of_payment='Cash',
|
||||||
|
disbursement_account='Disbursement Account - _TC',
|
||||||
payment_account='Payment Account - _TC',
|
payment_account='Payment Account - _TC',
|
||||||
loan_account='Loan Account - _TC',
|
loan_account='Loan Account - _TC',
|
||||||
interest_income_account='Interest Income Account - _TC',
|
interest_income_account='Interest Income Account - _TC',
|
||||||
|
@ -370,6 +370,7 @@ class TestSalarySlip(unittest.TestCase):
|
|||||||
create_loan_type("Car Loan", 500000, 8.4,
|
create_loan_type("Car Loan", 500000, 8.4,
|
||||||
is_term_loan=1,
|
is_term_loan=1,
|
||||||
mode_of_payment='Cash',
|
mode_of_payment='Cash',
|
||||||
|
disbursement_account='Disbursement Account - _TC',
|
||||||
payment_account='Payment Account - _TC',
|
payment_account='Payment Account - _TC',
|
||||||
loan_account='Loan Account - _TC',
|
loan_account='Loan Account - _TC',
|
||||||
interest_income_account='Interest Income Account - _TC',
|
interest_income_account='Interest Income Account - _TC',
|
||||||
|
@ -295,6 +295,10 @@ class GSTR3BReport(Document):
|
|||||||
inter_state_supply_details = {}
|
inter_state_supply_details = {}
|
||||||
|
|
||||||
for inv, items_based_on_rate in self.items_based_on_tax_rate.items():
|
for inv, items_based_on_rate in self.items_based_on_tax_rate.items():
|
||||||
|
gst_category = self.invoice_detail_map.get(inv, {}).get('gst_category')
|
||||||
|
place_of_supply = self.invoice_detail_map.get(inv, {}).get('place_of_supply') or '00-Other Territory'
|
||||||
|
export_type = self.invoice_detail_map.get(inv, {}).get('export_type')
|
||||||
|
|
||||||
for rate, items in items_based_on_rate.items():
|
for rate, items in items_based_on_rate.items():
|
||||||
for item_code, taxable_value in self.invoice_items.get(inv).items():
|
for item_code, taxable_value in self.invoice_items.get(inv).items():
|
||||||
if item_code in items:
|
if item_code in items:
|
||||||
@ -302,9 +306,8 @@ class GSTR3BReport(Document):
|
|||||||
self.report_dict['sup_details']['osup_nil_exmp']['txval'] += taxable_value
|
self.report_dict['sup_details']['osup_nil_exmp']['txval'] += taxable_value
|
||||||
elif item_code in self.is_non_gst:
|
elif item_code in self.is_non_gst:
|
||||||
self.report_dict['sup_details']['osup_nongst']['txval'] += taxable_value
|
self.report_dict['sup_details']['osup_nongst']['txval'] += taxable_value
|
||||||
elif rate == 0:
|
elif rate == 0 or (gst_category == 'Overseas' and export_type == 'Without Payment of Tax'):
|
||||||
self.report_dict['sup_details']['osup_zero']['txval'] += taxable_value
|
self.report_dict['sup_details']['osup_zero']['txval'] += taxable_value
|
||||||
#self.report_dict['sup_details']['osup_zero'][key] += tax_amount
|
|
||||||
else:
|
else:
|
||||||
if inv in self.cgst_sgst_invoices:
|
if inv in self.cgst_sgst_invoices:
|
||||||
tax_rate = rate/2
|
tax_rate = rate/2
|
||||||
@ -315,9 +318,6 @@ class GSTR3BReport(Document):
|
|||||||
self.report_dict['sup_details']['osup_det']['iamt'] += (taxable_value * rate /100)
|
self.report_dict['sup_details']['osup_det']['iamt'] += (taxable_value * rate /100)
|
||||||
self.report_dict['sup_details']['osup_det']['txval'] += taxable_value
|
self.report_dict['sup_details']['osup_det']['txval'] += taxable_value
|
||||||
|
|
||||||
gst_category = self.invoice_detail_map.get(inv, {}).get('gst_category')
|
|
||||||
place_of_supply = self.invoice_detail_map.get(inv, {}).get('place_of_supply') or '00-Other Territory'
|
|
||||||
|
|
||||||
if gst_category in ['Unregistered', 'Registered Composition', 'UIN Holders'] and \
|
if gst_category in ['Unregistered', 'Registered Composition', 'UIN Holders'] and \
|
||||||
self.gst_details.get("gst_state") != place_of_supply.split("-")[1]:
|
self.gst_details.get("gst_state") != place_of_supply.split("-")[1]:
|
||||||
inter_state_supply_details.setdefault((gst_category, place_of_supply), {
|
inter_state_supply_details.setdefault((gst_category, place_of_supply), {
|
||||||
|
@ -1375,6 +1375,30 @@ class TestSalesOrder(ERPNextTestCase):
|
|||||||
|
|
||||||
automatically_fetch_payment_terms(enable=0)
|
automatically_fetch_payment_terms(enable=0)
|
||||||
|
|
||||||
|
def test_zero_amount_sales_order_billing_status(self):
|
||||||
|
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||||
|
|
||||||
|
so = make_sales_order(uom="Nos", do_not_save=1)
|
||||||
|
so.items[0].rate = 0
|
||||||
|
so.save()
|
||||||
|
so.submit()
|
||||||
|
|
||||||
|
self.assertEqual(so.net_total, 0)
|
||||||
|
self.assertEqual(so.billing_status, 'Not Billed')
|
||||||
|
|
||||||
|
si = create_sales_invoice(qty=10, do_not_save=1)
|
||||||
|
si.price_list = '_Test Price List'
|
||||||
|
si.items[0].rate = 0
|
||||||
|
si.items[0].price_list_rate = 0
|
||||||
|
si.items[0].sales_order = so.name
|
||||||
|
si.items[0].so_detail = so.items[0].name
|
||||||
|
si.save()
|
||||||
|
si.submit()
|
||||||
|
|
||||||
|
self.assertEqual(si.net_total, 0)
|
||||||
|
so.load_from_db()
|
||||||
|
self.assertEqual(so.billing_status, 'Fully Billed')
|
||||||
|
|
||||||
def automatically_fetch_payment_terms(enable=1):
|
def automatically_fetch_payment_terms(enable=1):
|
||||||
accounts_settings = frappe.get_doc("Accounts Settings")
|
accounts_settings = frappe.get_doc("Accounts Settings")
|
||||||
accounts_settings.automatically_fetch_payment_terms = enable
|
accounts_settings.automatically_fetch_payment_terms = enable
|
||||||
|
@ -80,7 +80,7 @@
|
|||||||
"description": "How often should Project and Company be updated based on Sales Transactions?",
|
"description": "How often should Project and Company be updated based on Sales Transactions?",
|
||||||
"fieldname": "sales_update_frequency",
|
"fieldname": "sales_update_frequency",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"label": "Sales Update Frequency",
|
"label": "Sales Update Frequency in Company and Project",
|
||||||
"options": "Each Transaction\nDaily\nMonthly",
|
"options": "Each Transaction\nDaily\nMonthly",
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
@ -171,7 +171,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-09-13 12:32:17.004404",
|
"modified": "2022-02-04 15:41:59.939261",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Selling Settings",
|
"name": "Selling Settings",
|
||||||
@ -189,5 +189,6 @@
|
|||||||
],
|
],
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
@ -4,10 +4,11 @@
|
|||||||
|
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.utils import flt
|
from frappe.utils import add_to_date, flt, now
|
||||||
|
|
||||||
from erpnext.accounts.doctype.account.test_account import create_account, get_inventory_account
|
from erpnext.accounts.doctype.account.test_account import create_account, get_inventory_account
|
||||||
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
|
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
|
||||||
|
from erpnext.accounts.utils import update_gl_entries_after
|
||||||
from erpnext.assets.doctype.asset.test_asset import create_asset_category, create_fixed_asset_item
|
from erpnext.assets.doctype.asset.test_asset import create_asset_category, create_fixed_asset_item
|
||||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import (
|
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import (
|
||||||
get_gl_entries,
|
get_gl_entries,
|
||||||
@ -28,7 +29,8 @@ class TestLandedCostVoucher(ERPNextTestCase):
|
|||||||
"voucher_type": pr.doctype,
|
"voucher_type": pr.doctype,
|
||||||
"voucher_no": pr.name,
|
"voucher_no": pr.name,
|
||||||
"item_code": "_Test Item",
|
"item_code": "_Test Item",
|
||||||
"warehouse": "Stores - TCP1"
|
"warehouse": "Stores - TCP1",
|
||||||
|
"is_cancelled": 0,
|
||||||
},
|
},
|
||||||
fieldname=["qty_after_transaction", "stock_value"], as_dict=1)
|
fieldname=["qty_after_transaction", "stock_value"], as_dict=1)
|
||||||
|
|
||||||
@ -41,14 +43,39 @@ class TestLandedCostVoucher(ERPNextTestCase):
|
|||||||
"voucher_type": pr.doctype,
|
"voucher_type": pr.doctype,
|
||||||
"voucher_no": pr.name,
|
"voucher_no": pr.name,
|
||||||
"item_code": "_Test Item",
|
"item_code": "_Test Item",
|
||||||
"warehouse": "Stores - TCP1"
|
"warehouse": "Stores - TCP1",
|
||||||
|
"is_cancelled": 0,
|
||||||
},
|
},
|
||||||
fieldname=["qty_after_transaction", "stock_value"], as_dict=1)
|
fieldname=["qty_after_transaction", "stock_value"], as_dict=1)
|
||||||
|
|
||||||
self.assertEqual(last_sle.qty_after_transaction, last_sle_after_landed_cost.qty_after_transaction)
|
self.assertEqual(last_sle.qty_after_transaction, last_sle_after_landed_cost.qty_after_transaction)
|
||||||
|
|
||||||
self.assertEqual(last_sle_after_landed_cost.stock_value - last_sle.stock_value, 25.0)
|
self.assertEqual(last_sle_after_landed_cost.stock_value - last_sle.stock_value, 25.0)
|
||||||
|
|
||||||
|
# assert after submit
|
||||||
|
self.assertPurchaseReceiptLCVGLEntries(pr)
|
||||||
|
|
||||||
|
# Mess up cancelled SLE modified timestamp to check
|
||||||
|
# if they aren't effective in any business logic.
|
||||||
|
frappe.db.set_value("Stock Ledger Entry",
|
||||||
|
{
|
||||||
|
"is_cancelled": 1,
|
||||||
|
"voucher_type": pr.doctype,
|
||||||
|
"voucher_no": pr.name
|
||||||
|
},
|
||||||
|
"is_cancelled", 1,
|
||||||
|
modified=add_to_date(now(), hours=1, as_datetime=True, as_string=True)
|
||||||
|
)
|
||||||
|
|
||||||
|
items, warehouses = pr.get_items_and_warehouses()
|
||||||
|
update_gl_entries_after(pr.posting_date, pr.posting_time,
|
||||||
|
warehouses, items, company=pr.company)
|
||||||
|
|
||||||
|
# reassert after reposting
|
||||||
|
self.assertPurchaseReceiptLCVGLEntries(pr)
|
||||||
|
|
||||||
|
|
||||||
|
def assertPurchaseReceiptLCVGLEntries(self, pr):
|
||||||
|
|
||||||
gl_entries = get_gl_entries("Purchase Receipt", pr.name)
|
gl_entries = get_gl_entries("Purchase Receipt", pr.name)
|
||||||
|
|
||||||
self.assertTrue(gl_entries)
|
self.assertTrue(gl_entries)
|
||||||
@ -74,8 +101,8 @@ class TestLandedCostVoucher(ERPNextTestCase):
|
|||||||
|
|
||||||
for gle in gl_entries:
|
for gle in gl_entries:
|
||||||
if not gle.get('is_cancelled'):
|
if not gle.get('is_cancelled'):
|
||||||
self.assertEqual(expected_values[gle.account][0], gle.debit)
|
self.assertEqual(expected_values[gle.account][0], gle.debit, msg=f"incorrect debit for {gle.account}")
|
||||||
self.assertEqual(expected_values[gle.account][1], gle.credit)
|
self.assertEqual(expected_values[gle.account][1], gle.credit, msg=f"incorrect credit for {gle.account}")
|
||||||
|
|
||||||
|
|
||||||
def test_landed_cost_voucher_against_purchase_invoice(self):
|
def test_landed_cost_voucher_against_purchase_invoice(self):
|
||||||
|
@ -286,7 +286,7 @@ class PurchaseReceipt(BuyingController):
|
|||||||
if warehouse_account.get(d.warehouse):
|
if warehouse_account.get(d.warehouse):
|
||||||
stock_value_diff = frappe.db.get_value("Stock Ledger Entry",
|
stock_value_diff = frappe.db.get_value("Stock Ledger Entry",
|
||||||
{"voucher_type": "Purchase Receipt", "voucher_no": self.name,
|
{"voucher_type": "Purchase Receipt", "voucher_no": self.name,
|
||||||
"voucher_detail_no": d.name, "warehouse": d.warehouse}, "stock_value_difference")
|
"voucher_detail_no": d.name, "warehouse": d.warehouse, "is_cancelled": 0}, "stock_value_difference")
|
||||||
|
|
||||||
if not stock_value_diff:
|
if not stock_value_diff:
|
||||||
continue
|
continue
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
"items_section",
|
"items_section",
|
||||||
"title",
|
|
||||||
"naming_series",
|
"naming_series",
|
||||||
"stock_entry_type",
|
"stock_entry_type",
|
||||||
"outgoing_stock_entry",
|
"outgoing_stock_entry",
|
||||||
@ -83,14 +82,6 @@
|
|||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"oldfieldtype": "Section Break"
|
"oldfieldtype": "Section Break"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "title",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"hidden": 1,
|
|
||||||
"label": "Title",
|
|
||||||
"no_copy": 1,
|
|
||||||
"print_hide": 1
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldname": "naming_series",
|
"fieldname": "naming_series",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
@ -353,9 +344,9 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "scan_barcode",
|
"fieldname": "scan_barcode",
|
||||||
"options": "Barcode",
|
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Scan Barcode"
|
"label": "Scan Barcode",
|
||||||
|
"options": "Barcode"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 1,
|
"allow_bulk_edit": 1,
|
||||||
@ -628,10 +619,11 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-08-20 19:19:31.514846",
|
"modified": "2022-02-07 12:55:14.614077",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Stock Entry",
|
"name": "Stock Entry",
|
||||||
|
"naming_rule": "By \"Naming Series\" field",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
@ -698,6 +690,7 @@
|
|||||||
"show_name_in_global_search": 1,
|
"show_name_in_global_search": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"title_field": "title",
|
"states": [],
|
||||||
|
"title_field": "stock_entry_type",
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
@ -76,7 +76,6 @@ class StockEntry(StockController):
|
|||||||
|
|
||||||
self.validate_posting_time()
|
self.validate_posting_time()
|
||||||
self.validate_purpose()
|
self.validate_purpose()
|
||||||
self.set_title()
|
|
||||||
self.validate_item()
|
self.validate_item()
|
||||||
self.validate_customer_provided_item()
|
self.validate_customer_provided_item()
|
||||||
self.validate_qty()
|
self.validate_qty()
|
||||||
@ -1835,14 +1834,6 @@ class StockEntry(StockController):
|
|||||||
|
|
||||||
return sorted(list(set(get_serial_nos(self.pro_doc.serial_no)) - set(used_serial_nos)))
|
return sorted(list(set(get_serial_nos(self.pro_doc.serial_no)) - set(used_serial_nos)))
|
||||||
|
|
||||||
def set_title(self):
|
|
||||||
if frappe.flags.in_import and self.title:
|
|
||||||
# Allow updating title during data import/update
|
|
||||||
return
|
|
||||||
|
|
||||||
self.title = self.purpose
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def move_sample_to_retention_warehouse(company, items):
|
def move_sample_to_retention_warehouse(company, items):
|
||||||
if isinstance(items, str):
|
if isinstance(items, str):
|
||||||
|
@ -5,35 +5,41 @@
|
|||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
|
"defaults_tab",
|
||||||
"item_defaults_section",
|
"item_defaults_section",
|
||||||
"item_naming_by",
|
"item_naming_by",
|
||||||
"item_group",
|
"item_group",
|
||||||
"stock_uom",
|
"stock_uom",
|
||||||
"default_warehouse",
|
|
||||||
"column_break_4",
|
"column_break_4",
|
||||||
"valuation_method",
|
"default_warehouse",
|
||||||
"sample_retention_warehouse",
|
"sample_retention_warehouse",
|
||||||
"use_naming_series",
|
"valuation_method",
|
||||||
"naming_series_prefix",
|
"price_list_defaults_section",
|
||||||
|
"auto_insert_price_list_rate_if_missing",
|
||||||
|
"column_break_12",
|
||||||
|
"update_existing_price_list_rate",
|
||||||
|
"stock_validations_tab",
|
||||||
"section_break_9",
|
"section_break_9",
|
||||||
"over_delivery_receipt_allowance",
|
"over_delivery_receipt_allowance",
|
||||||
"role_allowed_to_over_deliver_receive",
|
|
||||||
"mr_qty_allowance",
|
"mr_qty_allowance",
|
||||||
"column_break_12",
|
"column_break_121",
|
||||||
"auto_insert_price_list_rate_if_missing",
|
"role_allowed_to_over_deliver_receive",
|
||||||
"update_existing_price_list_rate",
|
|
||||||
"allow_negative_stock",
|
"allow_negative_stock",
|
||||||
"show_barcode_field",
|
"show_barcode_field",
|
||||||
"clean_description_html",
|
"clean_description_html",
|
||||||
"quality_inspection_settings_section",
|
"quality_inspection_settings_section",
|
||||||
"action_if_quality_inspection_is_not_submitted",
|
"action_if_quality_inspection_is_not_submitted",
|
||||||
"column_break_21",
|
"column_break_23",
|
||||||
"action_if_quality_inspection_is_rejected",
|
"action_if_quality_inspection_is_rejected",
|
||||||
|
"serial_and_batch_item_settings_tab",
|
||||||
"section_break_7",
|
"section_break_7",
|
||||||
"automatically_set_serial_nos_based_on_fifo",
|
"automatically_set_serial_nos_based_on_fifo",
|
||||||
"set_qty_in_transactions_based_on_serial_no_input",
|
"set_qty_in_transactions_based_on_serial_no_input",
|
||||||
"column_break_10",
|
"column_break_10",
|
||||||
"disable_serial_no_and_batch_selector",
|
"disable_serial_no_and_batch_selector",
|
||||||
|
"use_naming_series",
|
||||||
|
"naming_series_prefix",
|
||||||
|
"stock_planning_tab",
|
||||||
"auto_material_request",
|
"auto_material_request",
|
||||||
"auto_indent",
|
"auto_indent",
|
||||||
"column_break_27",
|
"column_break_27",
|
||||||
@ -42,6 +48,7 @@
|
|||||||
"allow_from_dn",
|
"allow_from_dn",
|
||||||
"column_break_31",
|
"column_break_31",
|
||||||
"allow_from_pr",
|
"allow_from_pr",
|
||||||
|
"stock_closing_tab",
|
||||||
"control_historical_stock_transactions_section",
|
"control_historical_stock_transactions_section",
|
||||||
"stock_frozen_upto",
|
"stock_frozen_upto",
|
||||||
"stock_frozen_upto_days",
|
"stock_frozen_upto_days",
|
||||||
@ -122,7 +129,7 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "section_break_7",
|
"fieldname": "section_break_7",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Serialised and Batch Setting"
|
"label": "Serial & Batch Item Settings"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
@ -275,10 +282,6 @@
|
|||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Quality Inspection Settings"
|
"label": "Quality Inspection Settings"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldname": "column_break_21",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"default": "Stop",
|
"default": "Stop",
|
||||||
"fieldname": "action_if_quality_inspection_is_rejected",
|
"fieldname": "action_if_quality_inspection_is_rejected",
|
||||||
@ -298,6 +301,44 @@
|
|||||||
"fieldname": "update_existing_price_list_rate",
|
"fieldname": "update_existing_price_list_rate",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Update Existing Price List Rate"
|
"label": "Update Existing Price List Rate"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "defaults_tab",
|
||||||
|
"fieldtype": "Tab Break",
|
||||||
|
"label": "Defaults"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "stock_validations_tab",
|
||||||
|
"fieldtype": "Tab Break",
|
||||||
|
"label": "Stock Validations"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "stock_planning_tab",
|
||||||
|
"fieldtype": "Tab Break",
|
||||||
|
"label": "Stock Planning"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "stock_closing_tab",
|
||||||
|
"fieldtype": "Tab Break",
|
||||||
|
"label": "Stock Closing"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "serial_and_batch_item_settings_tab",
|
||||||
|
"fieldtype": "Tab Break",
|
||||||
|
"label": "Serial & Batch Item"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_23",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "price_list_defaults_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Price List Defaults"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_121",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "icon-cog",
|
"icon": "icon-cog",
|
||||||
@ -305,7 +346,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-11-06 19:40:02.183592",
|
"modified": "2022-02-04 15:33:43.692736",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Stock Settings",
|
"name": "Stock Settings",
|
||||||
@ -324,5 +365,6 @@
|
|||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "ASC",
|
"sort_order": "ASC",
|
||||||
|
"states": [],
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user