From 725a7f90e9a873335caaa588d73ddb3de7383c33 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 25 Sep 2023 19:45:19 +0530 Subject: [PATCH 001/205] fix: use dynamic link for against field --- erpnext/accounts/doctype/gl_entry/gl_entry.json | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.json b/erpnext/accounts/doctype/gl_entry/gl_entry.json index 5063ec6076..1adeaa54d8 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.json +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.json @@ -17,6 +17,7 @@ "account_currency", "debit_in_account_currency", "credit_in_account_currency", + "against_type", "against", "against_voucher_type", "against_voucher", @@ -128,13 +129,21 @@ "label": "Credit Amount in Account Currency", "options": "account_currency" }, + { + "fieldname": "against_type", + "fieldtype": "Link", + "in_filter": 1, + "label": "Against Type", + "options": "DocType" + }, { "fieldname": "against", - "fieldtype": "Text", + "fieldtype": "Dynamic Link", "in_filter": 1, "label": "Against", "oldfieldname": "against", - "oldfieldtype": "Text" + "oldfieldtype": "Text", + "options": "against_type" }, { "fieldname": "against_voucher_type", @@ -286,7 +295,7 @@ "idx": 1, "in_create": 1, "links": [], - "modified": "2023-08-16 21:38:44.072267", + "modified": "2023-09-25 12:03:23.031733", "modified_by": "Administrator", "module": "Accounts", "name": "GL Entry", From 19b220f39ca3596e416d99f3aef7c2485019b9fd Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 25 Sep 2023 19:49:17 +0530 Subject: [PATCH 002/205] fix: set against type in inv gl dict --- .../purchase_invoice/purchase_invoice.py | 29 +++++++++++++++++++ .../doctype/sales_invoice/sales_invoice.py | 14 +++++++++ 2 files changed, 43 insertions(+) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 55972719f8..1dc67ef689 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -623,6 +623,7 @@ class PurchaseInvoice(BuyingController): "party_type": "Supplier", "party": self.supplier, "due_date": self.due_date, + "against_type": "Account", "against": self.against_expense_account, "credit": base_grand_total, "credit_in_account_currency": base_grand_total @@ -692,6 +693,7 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict( { "account": warehouse_account[item.warehouse]["account"], + "against_type": "Account", "against": warehouse_account[item.from_warehouse]["account"], "cost_center": item.cost_center, "project": item.project or self.project, @@ -712,6 +714,7 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict( { "account": warehouse_account[item.from_warehouse]["account"], + "against_type": "Account", "against": warehouse_account[item.warehouse]["account"], "cost_center": item.cost_center, "project": item.project or self.project, @@ -729,6 +732,7 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict( { "account": item.expense_account, + "against_type": "Supplier", "against": self.supplier, "debit": flt(item.base_net_amount, item.precision("base_net_amount")), "remarks": self.get("remarks") or _("Accounting Entry for Stock"), @@ -746,6 +750,7 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict( { "account": item.expense_account, + "against_type": "Supplier", "against": self.supplier, "debit": warehouse_debit_amount, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), @@ -765,6 +770,7 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict( { "account": account, + "against_type": "Account", "against": item.expense_account, "cost_center": item.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), @@ -785,6 +791,7 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict( { "account": supplier_warehouse_account, + "against_type": "Account", "against": item.expense_account, "cost_center": item.cost_center, "project": item.project or self.project, @@ -842,6 +849,7 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict( { "account": expense_account, + "against_type": "Supplier", "against": self.supplier, "debit": amount, "cost_center": item.cost_center, @@ -868,6 +876,7 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict( { "account": expense_account, + "against_type": "Supplier", "against": self.supplier, "debit": discrepancy_caused_by_exchange_rate_difference, "cost_center": item.cost_center, @@ -881,6 +890,7 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict( { "account": self.get_company_default("exchange_gain_loss_account"), + "against_type": "Supplier", "against": self.supplier, "credit": discrepancy_caused_by_exchange_rate_difference, "cost_center": item.cost_center, @@ -901,6 +911,7 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict( { "account": expenses_included_in_asset_valuation, + "against_type": "Account", "against": expense_account, "cost_center": item.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), @@ -915,6 +926,7 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict( { "account": expense_account, + "against_type": "Account", "against": expenses_included_in_asset_valuation, "cost_center": item.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), @@ -954,6 +966,7 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict( { "account": self.stock_received_but_not_billed, + "against_type": "Supplier", "against": self.supplier, "debit": flt(item.item_tax_amount, item.precision("item_tax_amount")), "remarks": self.remarks or _("Accounting Entry for Stock"), @@ -993,6 +1006,7 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict( { "account": item.expense_account, + "against_type": "Supplier", "against": self.supplier, "remarks": self.get("remarks") or _("Accounting Entry for Asset"), "debit": base_asset_amount, @@ -1015,6 +1029,7 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict( { "account": eiiav_account, + "against_type": "Supplier", "against": self.supplier, "remarks": self.get("remarks") or _("Accounting Entry for Asset"), "cost_center": item.cost_center, @@ -1039,6 +1054,7 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict( { "account": cwip_account, + "against_type": "Supplier", "against": self.supplier, "remarks": self.get("remarks") or _("Accounting Entry for Asset"), "debit": base_asset_amount, @@ -1061,6 +1077,7 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict( { "account": eiiav_account, + "against_type": "Supplier", "against": self.supplier, "remarks": self.get("remarks") or _("Accounting Entry for Asset"), "cost_center": item.cost_center, @@ -1085,6 +1102,7 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict( { "account": eiiav_account, + "against_type": "Account", "against": cwip_account, "cost_center": item.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), @@ -1099,6 +1117,7 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict( { "account": cwip_account, + "against_type": "Account", "against": eiiav_account, "cost_center": item.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), @@ -1146,6 +1165,7 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict( { "account": cost_of_goods_sold_account, + "against_type": "Account", "against": item.expense_account, "debit": stock_adjustment_amt, "remarks": self.get("remarks") or _("Stock Adjustment"), @@ -1176,6 +1196,7 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict( { "account": tax.account_head, + "against_type": "Supplier", "against": self.supplier, dr_or_cr: base_amount, dr_or_cr + "_in_account_currency": base_amount @@ -1224,6 +1245,7 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict( { "account": tax.account_head, + "against_type": "Supplier", "cost_center": tax.cost_center, "against": self.supplier, "credit": applicable_amount, @@ -1243,6 +1265,7 @@ class PurchaseInvoice(BuyingController): { "account": tax.account_head, "cost_center": tax.cost_center, + "against_type": "Supplier", "against": self.supplier, "credit": valuation_tax[tax.name], "remarks": self.remarks or _("Accounting Entry for Stock"), @@ -1258,6 +1281,7 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict( { "account": self.unrealized_profit_loss_account, + "against_type": "Supplier", "against": self.supplier, "credit": flt(self.total_taxes_and_charges), "credit_in_account_currency": flt(self.base_total_taxes_and_charges), @@ -1279,6 +1303,7 @@ class PurchaseInvoice(BuyingController): "account": self.credit_to, "party_type": "Supplier", "party": self.supplier, + "against_type": "Account", "against": self.cash_bank_account, "debit": self.base_paid_amount, "debit_in_account_currency": self.base_paid_amount @@ -1300,6 +1325,7 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict( { "account": self.cash_bank_account, + "against_type": "Supplier", "against": self.supplier, "credit": self.base_paid_amount, "credit_in_account_currency": self.base_paid_amount @@ -1324,6 +1350,7 @@ class PurchaseInvoice(BuyingController): "account": self.credit_to, "party_type": "Supplier", "party": self.supplier, + "against_type": "Account", "against": self.write_off_account, "debit": self.base_write_off_amount, "debit_in_account_currency": self.base_write_off_amount @@ -1344,6 +1371,7 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict( { "account": self.write_off_account, + "against_type": "Supplier", "against": self.supplier, "credit": flt(self.base_write_off_amount), "credit_in_account_currency": self.base_write_off_amount @@ -1371,6 +1399,7 @@ class PurchaseInvoice(BuyingController): self.get_gl_dict( { "account": round_off_account, + "against_type": "Supplier", "against": self.supplier, "debit_in_account_currency": self.rounding_adjustment, "debit": self.base_rounding_adjustment, diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 7bdb2b49ce..db3d5c666f 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1101,6 +1101,7 @@ class SalesInvoice(SellingController): "party_type": "Customer", "party": self.customer, "due_date": self.due_date, + "against_type": "Account", "against": self.against_income_account, "debit": base_grand_total, "debit_in_account_currency": base_grand_total @@ -1130,6 +1131,7 @@ class SalesInvoice(SellingController): self.get_gl_dict( { "account": tax.account_head, + "against_type": "Customer", "against": self.customer, "credit": flt(base_amount, tax.precision("tax_amount_after_discount_amount")), "credit_in_account_currency": ( @@ -1151,6 +1153,7 @@ class SalesInvoice(SellingController): self.get_gl_dict( { "account": self.unrealized_profit_loss_account, + "against_type": "Customer", "against": self.customer, "debit": flt(self.total_taxes_and_charges), "debit_in_account_currency": flt(self.base_total_taxes_and_charges), @@ -1219,6 +1222,7 @@ class SalesInvoice(SellingController): add_asset_activity(asset.name, _("Asset sold")) for gle in fixed_asset_gl_entries: + gle["against_type"] = "Customer" gle["against"] = self.customer gl_entries.append(self.get_gl_dict(gle, item=item)) @@ -1240,6 +1244,7 @@ class SalesInvoice(SellingController): self.get_gl_dict( { "account": income_account, + "against_type": "Customer", "against": self.customer, "credit": flt(base_amount, item.precision("base_net_amount")), "credit_in_account_currency": ( @@ -1294,6 +1299,7 @@ class SalesInvoice(SellingController): "account": self.debit_to, "party_type": "Customer", "party": self.customer, + "against_type": "Account", "against": "Expense account - " + cstr(self.loyalty_redemption_account) + " for the Loyalty Program", @@ -1310,6 +1316,7 @@ class SalesInvoice(SellingController): { "account": self.loyalty_redemption_account, "cost_center": self.cost_center or self.loyalty_redemption_cost_center, + "against_type": "Customer", "against": self.customer, "debit": self.loyalty_amount, "remark": "Loyalty Points redeemed by the customer", @@ -1337,6 +1344,7 @@ class SalesInvoice(SellingController): "account": self.debit_to, "party_type": "Customer", "party": self.customer, + "against_type": "Account", "against": payment_mode.account, "credit": payment_mode.base_amount, "credit_in_account_currency": payment_mode.base_amount @@ -1358,6 +1366,7 @@ class SalesInvoice(SellingController): self.get_gl_dict( { "account": payment_mode.account, + "against_type": "Customer", "against": self.customer, "debit": payment_mode.base_amount, "debit_in_account_currency": payment_mode.base_amount @@ -1382,6 +1391,7 @@ class SalesInvoice(SellingController): "account": self.debit_to, "party_type": "Customer", "party": self.customer, + "against_type": "Account", "against": self.account_for_change_amount, "debit": flt(self.base_change_amount), "debit_in_account_currency": flt(self.base_change_amount) @@ -1403,6 +1413,7 @@ class SalesInvoice(SellingController): self.get_gl_dict( { "account": self.account_for_change_amount, + "against_type": "Customer", "against": self.customer, "credit": self.base_change_amount, "cost_center": self.cost_center, @@ -1429,6 +1440,7 @@ class SalesInvoice(SellingController): "account": self.debit_to, "party_type": "Customer", "party": self.customer, + "against_type": "Account", "against": self.write_off_account, "credit": flt(self.base_write_off_amount, self.precision("base_write_off_amount")), "credit_in_account_currency": ( @@ -1449,6 +1461,7 @@ class SalesInvoice(SellingController): self.get_gl_dict( { "account": self.write_off_account, + "against_type": "Customer", "against": self.customer, "debit": flt(self.base_write_off_amount, self.precision("base_write_off_amount")), "debit_in_account_currency": ( @@ -1477,6 +1490,7 @@ class SalesInvoice(SellingController): self.get_gl_dict( { "account": round_off_account, + "against_type": "Customer", "against": self.customer, "credit_in_account_currency": flt( self.rounding_adjustment, self.precision("rounding_adjustment") From 82774f89b106a56c4754536b1c0cf5eb695a3c15 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 25 Sep 2023 19:50:47 +0530 Subject: [PATCH 003/205] fix: set against type in deferred revenue --- erpnext/accounts/deferred_revenue.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/erpnext/accounts/deferred_revenue.py b/erpnext/accounts/deferred_revenue.py index d0940c7df2..00d5ea3245 100644 --- a/erpnext/accounts/deferred_revenue.py +++ b/erpnext/accounts/deferred_revenue.py @@ -358,9 +358,11 @@ def book_deferred_income_or_expense(doc, deferred_process, posting_date=None): account_currency = get_account_currency(item.expense_account or item.income_account) if doc.doctype == "Sales Invoice": + against_type = "Customer" against, project = doc.customer, doc.project credit_account, debit_account = item.income_account, item.deferred_revenue_account else: + against_type = "Supplier" against, project = doc.supplier, item.project credit_account, debit_account = item.deferred_expense_account, item.expense_account @@ -413,6 +415,7 @@ def book_deferred_income_or_expense(doc, deferred_process, posting_date=None): doc, credit_account, debit_account, + against_type, against, amount, base_amount, @@ -494,6 +497,7 @@ def make_gl_entries( doc, credit_account, debit_account, + against_type, against, amount, base_amount, @@ -515,6 +519,7 @@ def make_gl_entries( doc.get_gl_dict( { "account": credit_account, + "against_type": against_type, "against": against, "credit": base_amount, "credit_in_account_currency": amount, @@ -534,6 +539,7 @@ def make_gl_entries( doc.get_gl_dict( { "account": debit_account, + "against_type": against_type, "against": against, "debit": base_amount, "debit_in_account_currency": amount, From 4c5a83d6cf7e4b39a403b1e99a2b1c443f854ac9 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 25 Sep 2023 19:55:40 +0530 Subject: [PATCH 004/205] fix: set against type in controllers --- erpnext/accounts/doctype/journal_entry/journal_entry.py | 1 + erpnext/accounts/doctype/payment_entry/payment_entry.py | 7 +++++++ erpnext/controllers/accounts_controller.py | 7 +++++++ 3 files changed, 15 insertions(+) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 85ef6f76d2..0616643a68 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -906,6 +906,7 @@ class JournalEntry(AccountsController): "party_type": d.party_type, "due_date": self.due_date, "party": d.party, + "against_type": "Account", "against": d.against_account, "debit": flt(d.debit, d.precision("debit")), "credit": flt(d.credit, d.precision("credit")), diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 38a520996c..6cfc072aea 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -1074,6 +1074,7 @@ class PaymentEntry(AccountsController): "account": self.party_account, "party_type": self.party_type, "party": self.party, + "against_type": "Account", "against": against_account, "account_currency": self.party_account_currency, "cost_center": self.cost_center, @@ -1232,6 +1233,7 @@ class PaymentEntry(AccountsController): { "account": self.paid_from, "account_currency": self.paid_from_account_currency, + "against_type": self.party_type if self.payment_type == "Pay" else "Account", "against": self.party if self.payment_type == "Pay" else self.paid_to, "credit_in_account_currency": self.paid_amount, "credit": self.base_paid_amount, @@ -1247,6 +1249,7 @@ class PaymentEntry(AccountsController): { "account": self.paid_to, "account_currency": self.paid_to_account_currency, + "against_type": self.party_type if self.payment_type == "Receive" else "Account", "against": self.party if self.payment_type == "Receive" else self.paid_from, "debit_in_account_currency": self.received_amount, "debit": self.base_received_amount, @@ -1271,6 +1274,7 @@ class PaymentEntry(AccountsController): rev_dr_or_cr = "credit" if dr_or_cr == "debit" else "debit" against = self.party or self.paid_to + against_type = self.party_type or "Account" payment_account = self.get_party_account_for_taxes() tax_amount = d.tax_amount base_tax_amount = d.base_tax_amount @@ -1279,6 +1283,7 @@ class PaymentEntry(AccountsController): self.get_gl_dict( { "account": d.account_head, + "against_type": against_type, "against": against, dr_or_cr: tax_amount, dr_or_cr + "_in_account_currency": base_tax_amount @@ -1304,6 +1309,7 @@ class PaymentEntry(AccountsController): self.get_gl_dict( { "account": payment_account, + "against_type": against_type, "against": against, rev_dr_or_cr: tax_amount, rev_dr_or_cr + "_in_account_currency": base_tax_amount @@ -1329,6 +1335,7 @@ class PaymentEntry(AccountsController): { "account": d.account, "account_currency": account_currency, + "against_type": self.party_type or "Account", "against": self.party or self.paid_from, "debit_in_account_currency": d.amount, "debit": d.amount, diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index e635aa7924..d77b8a3c7f 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1040,6 +1040,7 @@ class AccountsController(TransactionBase): ) credit_or_debit = "credit" if self.doctype == "Purchase Invoice" else "debit" + against_type = "Supplier" if self.doctype == "Purchase Invoice" else "Customer" against = self.supplier if self.doctype == "Purchase Invoice" else self.customer if precision_loss: @@ -1047,6 +1048,7 @@ class AccountsController(TransactionBase): self.get_gl_dict( { "account": round_off_account, + "against_type": against_type, "against": against, credit_or_debit: precision_loss, "cost_center": round_off_cost_center @@ -1394,11 +1396,13 @@ class AccountsController(TransactionBase): if self.doctype == "Purchase Invoice": dr_or_cr = "credit" rev_dr_cr = "debit" + against_type = "Supplier" supplier_or_customer = self.supplier else: dr_or_cr = "debit" rev_dr_cr = "credit" + against_type = "Customer" supplier_or_customer = self.customer if enable_discount_accounting: @@ -1423,6 +1427,7 @@ class AccountsController(TransactionBase): self.get_gl_dict( { "account": item.discount_account, + "against_type": against_type, "against": supplier_or_customer, dr_or_cr: flt( discount_amount * self.get("conversion_rate"), item.precision("discount_amount") @@ -1441,6 +1446,7 @@ class AccountsController(TransactionBase): self.get_gl_dict( { "account": income_or_expense_account, + "against_type": against_type, "against": supplier_or_customer, rev_dr_cr: flt( discount_amount * self.get("conversion_rate"), item.precision("discount_amount") @@ -1464,6 +1470,7 @@ class AccountsController(TransactionBase): self.get_gl_dict( { "account": self.additional_discount_account, + "against_type": against_type, "against": supplier_or_customer, dr_or_cr: self.base_discount_amount, "cost_center": self.cost_center, From f292a0cc4c89814607fec0bb66d1c458d6624750 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 25 Sep 2023 19:58:12 +0530 Subject: [PATCH 005/205] fix: set against type in utils --- .../accounts/doctype/invoice_discounting/invoice_discounting.py | 2 ++ erpnext/regional/united_arab_emirates/utils.py | 1 + erpnext/stock/doctype/stock_entry/stock_entry.py | 2 ++ 3 files changed, 5 insertions(+) diff --git a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py index 5bd4585a9a..744dff4670 100644 --- a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py +++ b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py @@ -125,6 +125,7 @@ class InvoiceDiscounting(AccountsController): "account": inv.debit_to, "party_type": "Customer", "party": d.customer, + "against_type": "Account", "against": self.accounts_receivable_credit, "credit": outstanding_in_company_currency, "credit_in_account_currency": outstanding_in_company_currency @@ -145,6 +146,7 @@ class InvoiceDiscounting(AccountsController): "account": self.accounts_receivable_credit, "party_type": "Customer", "party": d.customer, + "against_type": "Account", "against": inv.debit_to, "debit": outstanding_in_company_currency, "debit_in_account_currency": outstanding_in_company_currency diff --git a/erpnext/regional/united_arab_emirates/utils.py b/erpnext/regional/united_arab_emirates/utils.py index a910af6a1d..d70d5466e0 100644 --- a/erpnext/regional/united_arab_emirates/utils.py +++ b/erpnext/regional/united_arab_emirates/utils.py @@ -153,6 +153,7 @@ def make_gl_entry(tax, gl_entries, doc, tax_accounts): "account": tax.account_head, "cost_center": tax.cost_center, "posting_date": doc.posting_date, + "against_type": "Supplier", "against": doc.supplier, dr_or_cr: tax.base_tax_amount_after_discount_amount, dr_or_cr + "_in_account_currency": tax.base_tax_amount_after_discount_amount diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index a2cae7ff8d..2124168b62 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -1360,6 +1360,7 @@ class StockEntry(StockController): self.get_gl_dict( { "account": account, + "against_type": "Account", "against": d.expense_account, "cost_center": d.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), @@ -1374,6 +1375,7 @@ class StockEntry(StockController): self.get_gl_dict( { "account": d.expense_account, + "against_type": "Account", "against": account, "cost_center": d.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), From 4ea43ebc5dadc35e66cec30d36a9578118f01622 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 25 Sep 2023 20:01:13 +0530 Subject: [PATCH 006/205] fix: set against type in stock controller --- erpnext/controllers/stock_controller.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index ae54b801f1..5a04f71002 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -164,6 +164,7 @@ class StockController(AccountsController): self.get_gl_dict( { "account": warehouse_account[sle.warehouse]["account"], + "against_type": "Account", "against": expense_account, "cost_center": item_row.cost_center, "project": item_row.project or self.get("project"), @@ -180,6 +181,7 @@ class StockController(AccountsController): self.get_gl_dict( { "account": expense_account, + "against_type": "Account", "against": warehouse_account[sle.warehouse]["account"], "cost_center": item_row.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), @@ -212,6 +214,7 @@ class StockController(AccountsController): self.get_gl_dict( { "account": expense_account, + "against_type": "Account", "against": warehouse_asset_account, "cost_center": item_row.cost_center, "project": item_row.project or self.get("project"), @@ -228,6 +231,7 @@ class StockController(AccountsController): self.get_gl_dict( { "account": warehouse_asset_account, + "against_type": "Account", "against": expense_account, "cost_center": item_row.cost_center, "remarks": _("Rounding gain/loss Entry for Stock Transfer"), @@ -834,6 +838,7 @@ class StockController(AccountsController): "cost_center": cost_center, "debit": debit, "credit": credit, + "against_type": "Account", "against": against_account, "remarks": remarks, } From 6e1565c32c41a5d8bb5cffc4a74c861b0592ece6 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 25 Sep 2023 20:08:42 +0530 Subject: [PATCH 007/205] fix: set against type in asset --- erpnext/assets/doctype/asset/asset.py | 2 ++ erpnext/assets/doctype/asset_repair/asset_repair.py | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 0dbed87cf2..a732dec08b 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -606,6 +606,7 @@ class Asset(AccountsController): self.get_gl_dict( { "account": cwip_account, + "against_type": "Account", "against": fixed_asset_account, "remarks": self.get("remarks") or _("Accounting Entry for Asset"), "posting_date": self.available_for_use_date, @@ -621,6 +622,7 @@ class Asset(AccountsController): self.get_gl_dict( { "account": fixed_asset_account, + "against_type": "Account", "against": cwip_account, "remarks": self.get("remarks") or _("Accounting Entry for Asset"), "posting_date": self.available_for_use_date, diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.py b/erpnext/assets/doctype/asset_repair/asset_repair.py index 7e95cb2a1b..30c0371ae6 100644 --- a/erpnext/assets/doctype/asset_repair/asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/asset_repair.py @@ -241,6 +241,7 @@ class AssetRepair(AccountsController): "account": fixed_asset_account, "debit": self.repair_cost, "debit_in_account_currency": self.repair_cost, + "against_type": "Account", "against": pi_expense_account, "voucher_type": self.doctype, "voucher_no": self.name, @@ -260,6 +261,7 @@ class AssetRepair(AccountsController): "account": pi_expense_account, "credit": self.repair_cost, "credit_in_account_currency": self.repair_cost, + "against_type": "Account", "against": fixed_asset_account, "voucher_type": self.doctype, "voucher_no": self.name, @@ -294,6 +296,7 @@ class AssetRepair(AccountsController): "account": item.expense_account or default_expense_account, "credit": item.amount, "credit_in_account_currency": item.amount, + "against_type": "Account", "against": fixed_asset_account, "voucher_type": self.doctype, "voucher_no": self.name, @@ -311,6 +314,7 @@ class AssetRepair(AccountsController): "account": fixed_asset_account, "debit": item.amount, "debit_in_account_currency": item.amount, + "against_type": "Account", "against": item.expense_account or default_expense_account, "voucher_type": self.doctype, "voucher_no": self.name, From f705bf2efe7bf079bb9b8af200f4c8cadfddd4ee Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 25 Sep 2023 20:10:01 +0530 Subject: [PATCH 008/205] fix: remove multiple accounts from against in capitalization --- .../asset_capitalization.py | 62 ++++++++++--------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py index 662e4b983b..ad91edc038 100644 --- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py +++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py @@ -390,6 +390,7 @@ class AssetCapitalization(StockController): self.get_gl_dict( { "account": account, + "against_type": "Account", "against": target_account, "cost_center": item_row.cost_center, "project": item_row.get("project") or self.get("project"), @@ -431,6 +432,7 @@ class AssetCapitalization(StockController): self.set_consumed_asset_status(asset) for gle in fixed_asset_gl_entries: + gle["against_type"] = "Account" gle["against"] = target_account gl_entries.append(self.get_gl_dict(gle, item=item)) target_against.add(gle["account"]) @@ -447,6 +449,7 @@ class AssetCapitalization(StockController): self.get_gl_dict( { "account": item_row.expense_account, + "against_type": "Account", "against": target_account, "cost_center": item_row.cost_center, "project": item_row.get("project") or self.get("project"), @@ -458,41 +461,44 @@ class AssetCapitalization(StockController): ) def get_gl_entries_for_target_item(self, gl_entries, target_against, precision): - if self.target_is_fixed_asset: - # Capitalization - gl_entries.append( - self.get_gl_dict( - { - "account": self.target_fixed_asset_account, - "against": ", ".join(target_against), - "remarks": self.get("remarks") or _("Accounting Entry for Asset"), - "debit": flt(self.total_value, precision), - "cost_center": self.get("cost_center"), - }, - item=self, - ) - ) - else: - # Target Stock Item - sle_list = self.sle_map.get(self.name) - for sle in sle_list: - stock_value_difference = flt(sle.stock_value_difference, precision) - account = self.warehouse_account[sle.warehouse]["account"] - + for target_account in target_against: + if self.target_is_fixed_asset: + # Capitalization gl_entries.append( self.get_gl_dict( { - "account": account, - "against": ", ".join(target_against), - "cost_center": self.cost_center, - "project": self.get("project"), - "remarks": self.get("remarks") or "Accounting Entry for Stock", - "debit": stock_value_difference, + "account": self.target_fixed_asset_account, + "against_type": "Account", + "against": target_account, + "remarks": self.get("remarks") or _("Accounting Entry for Asset"), + "debit": flt(self.total_value, precision) / len(target_against), + "cost_center": self.get("cost_center"), }, - self.warehouse_account[sle.warehouse]["account_currency"], item=self, ) ) + else: + # Target Stock Item + sle_list = self.sle_map.get(self.name) + for sle in sle_list: + stock_value_difference = flt(sle.stock_value_difference, precision) + account = self.warehouse_account[sle.warehouse]["account"] + + gl_entries.append( + self.get_gl_dict( + { + "account": account, + "against_type": "Account", + "against": target_account, + "cost_center": self.cost_center, + "project": self.get("project"), + "remarks": self.get("remarks") or "Accounting Entry for Stock", + "debit": stock_value_difference / len(target_against), + }, + self.warehouse_account[sle.warehouse]["account_currency"], + item=self, + ) + ) def create_target_asset(self): total_target_asset_value = flt(self.total_value, self.precision("total_value")) From fcfdb9b5667755b2846e834d70d3f9b444743d2b Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Tue, 3 Oct 2023 15:19:33 +0530 Subject: [PATCH 009/205] fix: purchase receipt tests --- erpnext/controllers/stock_controller.py | 3 ++- .../purchase_receipt/purchase_receipt.py | 25 +++++++++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 5a04f71002..d816780053 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -824,6 +824,7 @@ class StockController(AccountsController): credit, remarks, against_account, + against_type="Account", debit_in_account_currency=None, credit_in_account_currency=None, account_currency=None, @@ -838,7 +839,7 @@ class StockController(AccountsController): "cost_center": cost_center, "debit": debit, "credit": credit, - "against_type": "Account", + "against_type": against_type, "against": against_account, "remarks": remarks, } diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 04eff54c43..836dda7811 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -449,6 +449,7 @@ class PurchaseReceipt(BuyingController): debit=0.0, credit=discrepancy_caused_by_exchange_rate_difference, remarks=remarks, + against_type="Supplier", against_account=self.supplier, debit_in_account_currency=-1 * discrepancy_caused_by_exchange_rate_difference, account_currency=credit_currency, @@ -462,6 +463,7 @@ class PurchaseReceipt(BuyingController): debit=discrepancy_caused_by_exchange_rate_difference, credit=0.0, remarks=remarks, + against_type="Supplier", against_account=self.supplier, debit_in_account_currency=-1 * discrepancy_caused_by_exchange_rate_difference, account_currency=credit_currency, @@ -666,7 +668,7 @@ class PurchaseReceipt(BuyingController): (self.name, expenses_included_in_valuation), ) - against_account = ", ".join([d.account for d in gl_entries if flt(d.debit) > 0]) + against_accounts = [d.account for d in gl_entries if flt(d.debit) > 0] total_valuation_amount = sum(valuation_tax.values()) amount_including_divisional_loss = negative_expense_to_be_booked stock_rbnb = self.get_company_default("stock_received_but_not_billed") @@ -687,16 +689,17 @@ class PurchaseReceipt(BuyingController): ) amount_including_divisional_loss -= applicable_amount - self.add_gl_entry( - gl_entries=gl_entries, - account=account, - cost_center=tax.cost_center, - debit=0.0, - credit=applicable_amount, - remarks=self.remarks or _("Accounting Entry for Stock"), - against_account=against_account, - item=tax, - ) + for against in against_accounts: + self.add_gl_entry( + gl_entries=gl_entries, + account=account, + cost_center=tax.cost_center, + debit=0.0, + credit=flt(applicable_amount) / len(against_accounts), + remarks=self.remarks or _("Accounting Entry for Stock"), + against_account=against, + item=tax, + ) i += 1 From 952e8cf60ca138ddb5941221421d87c2d00800c4 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Tue, 3 Oct 2023 15:55:34 +0530 Subject: [PATCH 010/205] fix: asset capitalization tests --- .../asset_capitalization/test_asset_capitalization.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py index 6e0a6856f5..1c445da20d 100644 --- a/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py +++ b/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py @@ -97,12 +97,12 @@ class TestAssetCapitalization(unittest.TestCase): # Test General Ledger Entries expected_gle = { - "_Test Fixed Asset - TCP1": 3000, + "_Test Fixed Asset - TCP1": 2999.99, "Expenses Included In Asset Valuation - TCP1": -1000, "_Test Warehouse - TCP1": -2000, + "Round Off - TCP1": 0.01, } actual_gle = get_actual_gle_dict(asset_capitalization.name) - self.assertEqual(actual_gle, expected_gle) # Test Stock Ledger Entries @@ -187,9 +187,10 @@ class TestAssetCapitalization(unittest.TestCase): # Test General Ledger Entries default_expense_account = frappe.db.get_value("Company", company, "default_expense_account") expected_gle = { - "_Test Fixed Asset - _TC": 3000, + "_Test Fixed Asset - _TC": 2999.99, "Expenses Included In Asset Valuation - _TC": -1000, default_expense_account: -2000, + "Round Off - _TC": 0.01, } actual_gle = get_actual_gle_dict(asset_capitalization.name) @@ -303,9 +304,10 @@ class TestAssetCapitalization(unittest.TestCase): # Test General Ledger Entries expected_gle = { - "_Test Warehouse - TCP1": consumed_asset_value_before_disposal, "_Test Accumulated Depreciations - TCP1": accumulated_depreciation, "_Test Fixed Asset - TCP1": -consumed_asset_purchase_value, + "_Test Warehouse - TCP1": consumed_asset_value_before_disposal - 0.01, + "Round Off - TCP1": 0.01, } actual_gle = get_actual_gle_dict(asset_capitalization.name) self.assertEqual(actual_gle, expected_gle) From aab5737ff3b95cd38de9240666854805bbb272a4 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Wed, 11 Oct 2023 15:55:02 +0530 Subject: [PATCH 011/205] fix: make JV account against field a dynamic link --- .../journal_entry_account.json | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json index 3ba8cea94b..0e5dde0e3a 100644 --- a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json +++ b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json @@ -37,6 +37,7 @@ "col_break3", "is_advance", "user_remark", + "against_type", "against_account" ], "fields": [ @@ -249,12 +250,13 @@ }, { "fieldname": "against_account", - "fieldtype": "Text", + "fieldtype": "Dynamic Link", "hidden": 1, "label": "Against Account", "no_copy": 1, "oldfieldname": "against_account", "oldfieldtype": "Text", + "options": "against_type", "print_hide": 1 }, { @@ -279,12 +281,20 @@ "hidden": 1, "label": "Reference Detail No", "no_copy": 1 + }, + { + "fieldname": "against_type", + "fieldtype": "Link", + "hidden": 1, + "label": "Against Type", + "options": "DocType", + "print_hide": 1 } ], "idx": 1, "istable": 1, "links": [], - "modified": "2023-06-16 14:11:13.507807", + "modified": "2023-10-11 13:05:21.489496", "modified_by": "Administrator", "module": "Accounts", "name": "Journal Entry Account", From 28445058ef4a9c9a6b4831f5223ffda2f1a4bfaf Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Wed, 11 Oct 2023 15:56:13 +0530 Subject: [PATCH 012/205] fix: split exchange gain loss account entries --- .../exchange_rate_revaluation.py | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py index 3b5698b118..bace7bfd30 100644 --- a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py +++ b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py @@ -467,6 +467,16 @@ class ExchangeRateRevaluation(Document): else "credit_in_account_currency" ) + balance_in_account_currency = flt( + abs(d.get("balance_in_account_currency")), d.precision("balance_in_account_currency") + ) + difference_amount = ( + flt(d.get("new_exchange_rate"), d.precision("new_exchange_rate")) * balance_in_account_currency + ) + difference_amount -= ( + flt(d.get("current_exchange_rate"), d.precision("current_exchange_rate")) + * balance_in_account_currency + ) journal_entry_accounts.append( { "account": d.get("account"), @@ -503,28 +513,26 @@ class ExchangeRateRevaluation(Document): "reference_name": self.name, } ) + journal_entry_accounts.append( + { + "party_type": d.get("party_type"), + "party": d.get("party"), + "account": unrealized_exchange_gain_loss_account, + "balance": get_balance_on(unrealized_exchange_gain_loss_account), + "debit_in_account_currency": abs(difference_amount) if difference_amount < 0 else 0, + "credit_in_account_currency": difference_amount if difference_amount > 0 else 0, + "cost_center": erpnext.get_default_cost_center(self.company), + "exchange_rate": 1, + "reference_type": "Exchange Rate Revaluation", + "reference_name": self.name, + } + ) journal_entry.set("accounts", journal_entry_accounts) journal_entry.set_amounts_in_company_currency() journal_entry.set_total_debit_credit() self.gain_loss_unbooked += journal_entry.difference - self.gain_loss_unbooked - journal_entry.append( - "accounts", - { - "account": unrealized_exchange_gain_loss_account, - "balance": get_balance_on(unrealized_exchange_gain_loss_account), - "debit_in_account_currency": abs(self.gain_loss_unbooked) - if self.gain_loss_unbooked < 0 - else 0, - "credit_in_account_currency": self.gain_loss_unbooked if self.gain_loss_unbooked > 0 else 0, - "cost_center": erpnext.get_default_cost_center(self.company), - "exchange_rate": 1, - "reference_type": "Exchange Rate Revaluation", - "reference_name": self.name, - }, - ) - journal_entry.set_amounts_in_company_currency() journal_entry.set_total_debit_credit() journal_entry.save() From 35d92abe731b5d3d6b091297defaafc76ecc2af5 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Wed, 11 Oct 2023 15:56:59 +0530 Subject: [PATCH 013/205] fix: remove multiple against account values from gle --- .../doctype/journal_entry/journal_entry.py | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 0616643a68..e4a89395d0 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -680,23 +680,39 @@ class JournalEntry(AccountsController): if self.voucher_type in ("Deferred Revenue", "Deferred Expense"): for d in self.get("accounts"): if d.reference_type == "Sales Invoice": - field = "customer" + against_type = "Customer" else: - field = "supplier" + against_type = "Supplier" - d.against_account = frappe.db.get_value(d.reference_type, d.reference_name, field) + d.against_type = against_type + d.against_account = frappe.db.get_value( + d.reference_type, d.reference_name, against_type.lower() + ) else: for d in self.get("accounts"): if flt(d.debit) > 0: - accounts_debited.append(d.party or d.account) + accounts_debited.append(d) if flt(d.credit) > 0: - accounts_credited.append(d.party or d.account) + accounts_credited.append(d) for d in self.get("accounts"): - if flt(d.debit) > 0: - d.against_account = ", ".join(list(set(accounts_credited))) - if flt(d.credit) > 0: - d.against_account = ", ".join(list(set(accounts_debited))) + if d.exchange_rate != 1.0: + d.against_type = d.party_type + d.against_account = d.party + elif flt(d.debit) > 0: + for acc in accounts_credited: + if acc.party == d.party: + d.against_type = "Account" + d.against_account = d.account + d.party_type = "" + d.party = "" + elif flt(d.credit) > 0: + for acc in accounts_debited: + if acc.party == d.party: + d.against_type = "Account" + d.against_account = d.account + d.party_type = "" + d.party = "" def validate_debit_credit_amount(self): if not (self.voucher_type == "Exchange Gain Or Loss" and self.multi_currency): @@ -906,7 +922,7 @@ class JournalEntry(AccountsController): "party_type": d.party_type, "due_date": self.due_date, "party": d.party, - "against_type": "Account", + "against_type": d.against_type, "against": d.against_account, "debit": flt(d.debit, d.precision("debit")), "credit": flt(d.credit, d.precision("credit")), From 3d00d74fed4ce065118bedce886972bb6c43b614 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 6 Nov 2023 16:45:56 +0530 Subject: [PATCH 014/205] fix: combine jv entries for rate revaluation --- .../exchange_rate_revaluation.py | 40 ++++++++----------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py index bace7bfd30..3b5698b118 100644 --- a/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py +++ b/erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py @@ -467,16 +467,6 @@ class ExchangeRateRevaluation(Document): else "credit_in_account_currency" ) - balance_in_account_currency = flt( - abs(d.get("balance_in_account_currency")), d.precision("balance_in_account_currency") - ) - difference_amount = ( - flt(d.get("new_exchange_rate"), d.precision("new_exchange_rate")) * balance_in_account_currency - ) - difference_amount -= ( - flt(d.get("current_exchange_rate"), d.precision("current_exchange_rate")) - * balance_in_account_currency - ) journal_entry_accounts.append( { "account": d.get("account"), @@ -513,26 +503,28 @@ class ExchangeRateRevaluation(Document): "reference_name": self.name, } ) - journal_entry_accounts.append( - { - "party_type": d.get("party_type"), - "party": d.get("party"), - "account": unrealized_exchange_gain_loss_account, - "balance": get_balance_on(unrealized_exchange_gain_loss_account), - "debit_in_account_currency": abs(difference_amount) if difference_amount < 0 else 0, - "credit_in_account_currency": difference_amount if difference_amount > 0 else 0, - "cost_center": erpnext.get_default_cost_center(self.company), - "exchange_rate": 1, - "reference_type": "Exchange Rate Revaluation", - "reference_name": self.name, - } - ) journal_entry.set("accounts", journal_entry_accounts) journal_entry.set_amounts_in_company_currency() journal_entry.set_total_debit_credit() self.gain_loss_unbooked += journal_entry.difference - self.gain_loss_unbooked + journal_entry.append( + "accounts", + { + "account": unrealized_exchange_gain_loss_account, + "balance": get_balance_on(unrealized_exchange_gain_loss_account), + "debit_in_account_currency": abs(self.gain_loss_unbooked) + if self.gain_loss_unbooked < 0 + else 0, + "credit_in_account_currency": self.gain_loss_unbooked if self.gain_loss_unbooked > 0 else 0, + "cost_center": erpnext.get_default_cost_center(self.company), + "exchange_rate": 1, + "reference_type": "Exchange Rate Revaluation", + "reference_name": self.name, + }, + ) + journal_entry.set_amounts_in_company_currency() journal_entry.set_total_debit_credit() journal_entry.save() From ff0343d2cc9e1818beaf4047b8232183858d09d6 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 6 Nov 2023 16:46:43 +0530 Subject: [PATCH 015/205] fix: auto separate against accounts --- .../doctype/journal_entry/journal_entry.py | 147 +++++++++++------- 1 file changed, 95 insertions(+), 52 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index e4a89395d0..1b7b82bafc 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -676,7 +676,6 @@ class JournalEntry(AccountsController): ) def set_against_account(self): - accounts_debited, accounts_credited = [], [] if self.voucher_type in ("Deferred Revenue", "Deferred Expense"): for d in self.get("accounts"): if d.reference_type == "Sales Invoice": @@ -689,30 +688,40 @@ class JournalEntry(AccountsController): d.reference_type, d.reference_name, against_type.lower() ) else: - for d in self.get("accounts"): - if flt(d.debit) > 0: - accounts_debited.append(d) - if flt(d.credit) > 0: - accounts_credited.append(d) + self.get_against_accounts() - for d in self.get("accounts"): - if d.exchange_rate != 1.0: - d.against_type = d.party_type - d.against_account = d.party - elif flt(d.debit) > 0: - for acc in accounts_credited: - if acc.party == d.party: - d.against_type = "Account" - d.against_account = d.account - d.party_type = "" - d.party = "" - elif flt(d.credit) > 0: - for acc in accounts_debited: - if acc.party == d.party: - d.against_type = "Account" - d.against_account = d.account - d.party_type = "" - d.party = "" + def get_against_accounts(self): + accounts_debited, accounts_credited, against_accounts = [], [], [] + split_account = {} + separate_against_account_entries = 1 + for d in self.get("accounts"): + if flt(d.debit) > 0 or flt(d.debit_in_account_currency) > 0: + accounts_debited.append(d) + elif flt(d.credit) > 0 or flt(d.credit_in_account_currency) > 0: + accounts_credited.append(d) + + if d.against_account: + separate_against_account_entries = 0 + break + + if separate_against_account_entries: + if len(accounts_credited) > 1 and len(accounts_debited) > 1: + frappe.msgprint( + _( + "Unable to automatically determine {0} accounts. Set them up in the {1} table if needed.".format( + frappe.bold("against"), frappe.bold("Accounting Entries") + ) + ), + alert=True, + ) + elif len(accounts_credited) == 1: + against_accounts = accounts_debited + split_account = accounts_credited[0] + elif len(accounts_debited) == 1: + against_accounts = accounts_credited + split_account = accounts_debited[0] + + return separate_against_account_entries, against_accounts, split_account def validate_debit_credit_amount(self): if not (self.voucher_type == "Exchange Gain Or Loss" and self.multi_currency): @@ -909,41 +918,75 @@ class JournalEntry(AccountsController): def build_gl_map(self): gl_map = [] + separate_against_account_entries, against_accounts, split_account = self.get_against_accounts() for d in self.get("accounts"): if d.debit or d.credit or (self.voucher_type == "Exchange Gain Or Loss"): r = [d.user_remark, self.remark] r = [x for x in r if x] remarks = "\n".join(r) - gl_map.append( - self.get_gl_dict( - { - "account": d.account, - "party_type": d.party_type, - "due_date": self.due_date, - "party": d.party, - "against_type": d.against_type, - "against": d.against_account, - "debit": flt(d.debit, d.precision("debit")), - "credit": flt(d.credit, d.precision("credit")), - "account_currency": d.account_currency, - "debit_in_account_currency": flt( - d.debit_in_account_currency, d.precision("debit_in_account_currency") - ), - "credit_in_account_currency": flt( - d.credit_in_account_currency, d.precision("credit_in_account_currency") - ), - "against_voucher_type": d.reference_type, - "against_voucher": d.reference_name, - "remarks": remarks, - "voucher_detail_no": d.reference_detail_no, - "cost_center": d.cost_center, - "project": d.project, - "finance_book": self.finance_book, - }, - item=d, - ) + gl_dict = self.get_gl_dict( + { + "account": d.account, + "party_type": d.party_type, + "due_date": self.due_date, + "party": d.party, + "debit": flt(d.debit, d.precision("debit")), + "credit": flt(d.credit, d.precision("credit")), + "account_currency": d.account_currency, + "debit_in_account_currency": flt( + d.debit_in_account_currency, d.precision("debit_in_account_currency") + ), + "credit_in_account_currency": flt( + d.credit_in_account_currency, d.precision("credit_in_account_currency") + ), + "against_voucher_type": d.reference_type, + "against_voucher": d.reference_name, + "remarks": remarks, + "voucher_detail_no": d.reference_detail_no, + "cost_center": d.cost_center, + "project": d.project, + "finance_book": self.finance_book, + }, + item=d, ) + + if not separate_against_account_entries: + gl_dict.update({"against_type": d.against_type, "against_account": d.against_account}) + gl_map.append(gl_dict) + + elif d in against_accounts: + gl_dict.update( + { + "against_type": split_account.party_type or "Account", + "against_account": split_account.party or split_account.account, + } + ) + gl_map.append(gl_dict) + + else: + for against_account in against_accounts: + against_account = against_account.as_dict() + debit = against_account.credit or against_account.credit_in_account_currency + credit = against_account.debit or against_account.debit_in_account_currency + gl_dict = gl_dict.copy() + gl_dict.update( + { + "against_type": against_account.party_type or "Account", + "against": against_account.party or against_account.account, + "debit": flt(debit, d.precision("debit")), + "credit": flt(credit, d.precision("credit")), + "account_currency": d.account_currency, + "debit_in_account_currency": flt( + debit / d.exchange_rate, d.precision("debit_in_account_currency") + ), + "credit_in_account_currency": flt( + credit / d.exchange_rate, d.precision("credit_in_account_currency") + ), + } + ) + gl_map.append(gl_dict) + return gl_map def make_gl_entries(self, cancel=0, adv_adj=0): From 758ec720deb78507f4972b8b71cb3731f6ee43c4 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 6 Nov 2023 17:14:55 +0530 Subject: [PATCH 016/205] fix: remove join for against in purchase receipt --- erpnext/stock/doctype/purchase_receipt/purchase_receipt.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 6874044a6c..72a2465526 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -411,7 +411,7 @@ class PurchaseReceipt(BuyingController): account_currency=account_currency, item=item, ) - + self.add_gl_entry( gl_entries=gl_entries, account=self.get_company_default("exchange_gain_loss_account"), @@ -684,7 +684,7 @@ class PurchaseReceipt(BuyingController): # Backward compatibility: # and charges added via Landed Cost Voucher, # post valuation related charges on "Stock Received But Not Billed" - against_account = ", ".join([d.account for d in gl_entries if flt(d.debit) > 0]) + against_accounts = [d.account for d in gl_entries if flt(d.debit) > 0] total_valuation_amount = sum(valuation_tax.values()) amount_including_divisional_loss = negative_expense_to_be_booked stock_rbnb = ( From a1f8595a6a78ef94d1c82fefc44f4294d38cb856 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 6 Nov 2023 17:20:11 +0530 Subject: [PATCH 017/205] chore: linting issue --- erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 99b9c4ef44..cf89b333c6 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -920,7 +920,7 @@ class PurchaseInvoice(BuyingController): item=item, ) ) - + # update gross amount of asset bought through this document assets = frappe.db.get_all( "Asset", filters={"purchase_invoice": self.name, "item_code": item.item_code} From e845b63228baffb3165aee6c24f038477cfb71bf Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 6 Nov 2023 20:37:05 +0530 Subject: [PATCH 018/205] fix: single dr cr entries --- .../doctype/journal_entry/journal_entry.py | 79 ++++++++++++------- 1 file changed, 51 insertions(+), 28 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 1b7b82bafc..da6c8cf7cd 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -691,21 +691,13 @@ class JournalEntry(AccountsController): self.get_against_accounts() def get_against_accounts(self): - accounts_debited, accounts_credited, against_accounts = [], [], [] - split_account = {} - separate_against_account_entries = 1 - for d in self.get("accounts"): - if flt(d.debit) > 0 or flt(d.debit_in_account_currency) > 0: - accounts_debited.append(d) - elif flt(d.credit) > 0 or flt(d.credit_in_account_currency) > 0: - accounts_credited.append(d) + self.against_accounts = [] + self.split_account = {} + self.get_debited_credited_accounts() - if d.against_account: - separate_against_account_entries = 0 - break - - if separate_against_account_entries: - if len(accounts_credited) > 1 and len(accounts_debited) > 1: + if self.separate_against_account_entries: + no_of_credited_acc, no_of_debited_acc = len(self.accounts_credited), len(self.accounts_debited) + if no_of_credited_acc > 1 and no_of_debited_acc > 1: frappe.msgprint( _( "Unable to automatically determine {0} accounts. Set them up in the {1} table if needed.".format( @@ -714,14 +706,37 @@ class JournalEntry(AccountsController): ), alert=True, ) - elif len(accounts_credited) == 1: - against_accounts = accounts_debited - split_account = accounts_credited[0] - elif len(accounts_debited) == 1: - against_accounts = accounts_credited - split_account = accounts_debited[0] + elif no_of_credited_acc == 1 and no_of_debited_acc == 1: + self.set_against_accounts_for_single_dr_cr() + self.separate_against_account_entries = 0 + elif no_of_credited_acc == 1: + self.against_accounts = self.accounts_debited + self.split_account = self.accounts_credited[0] + elif no_of_debited_acc == 1: + self.against_accounts = self.accounts_credited + self.split_account = self.accounts_debited[0] - return separate_against_account_entries, against_accounts, split_account + def get_debited_credited_accounts(self): + self.accounts_debited, self.accounts_credited = [], [] + self.separate_against_account_entries = 1 + for d in self.get("accounts"): + if has_debit_amount(d): + self.accounts_debited.append(d) + elif has_credit_amount(d): + self.accounts_credited.append(d) + + if d.against_account: + self.separate_against_account_entries = 0 + break + + def set_against_accounts_for_single_dr_cr(self): + for d in self.accounts: + if has_debit_amount(d): + against_account = self.accounts_credited[0] + elif has_credit_amount(d): + against_account = self.accounts_debited[0] + d.against_type = against_account.party_type or "Account" + d.against_account = against_account.party or against_account.account def validate_debit_credit_amount(self): if not (self.voucher_type == "Exchange Gain Or Loss" and self.multi_currency): @@ -918,7 +933,7 @@ class JournalEntry(AccountsController): def build_gl_map(self): gl_map = [] - separate_against_account_entries, against_accounts, split_account = self.get_against_accounts() + self.get_against_accounts() for d in self.get("accounts"): if d.debit or d.credit or (self.voucher_type == "Exchange Gain Or Loss"): r = [d.user_remark, self.remark] @@ -951,21 +966,21 @@ class JournalEntry(AccountsController): item=d, ) - if not separate_against_account_entries: - gl_dict.update({"against_type": d.against_type, "against_account": d.against_account}) + if not self.separate_against_account_entries: + gl_dict.update({"against_type": d.against_type, "against": d.against_account}) gl_map.append(gl_dict) - elif d in against_accounts: + elif d in self.against_accounts: gl_dict.update( { - "against_type": split_account.party_type or "Account", - "against_account": split_account.party or split_account.account, + "against_type": self.split_account.get("party_type") or "Account", + "against": self.split_account.get("party") or self.split_account.get("account"), } ) gl_map.append(gl_dict) else: - for against_account in against_accounts: + for against_account in self.against_accounts: against_account = against_account.as_dict() debit = against_account.credit or against_account.credit_in_account_currency credit = against_account.debit or against_account.debit_in_account_currency @@ -1611,3 +1626,11 @@ def make_reverse_journal_entry(source_name, target_doc=None): ) return doclist + + +def has_credit_amount(account): + return flt(account.credit) > 0 or flt(account.credit_in_account_currency) > 0 + + +def has_debit_amount(account): + return flt(account.debit) > 0 or flt(account.debit_in_account_currency) > 0 From 5ce395a60a0ebace32382343110e0ceccac4880e Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Tue, 7 Nov 2023 12:52:49 +0530 Subject: [PATCH 019/205] fix: purchase receipt test --- erpnext/stock/doctype/purchase_receipt/purchase_receipt.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 72a2465526..1fcde44053 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -406,6 +406,7 @@ class PurchaseReceipt(BuyingController): debit=0.0, credit=discrepancy_caused_by_exchange_rate_difference, remarks=remarks, + against_type="Supplier", against_account=self.supplier, debit_in_account_currency=-1 * discrepancy_caused_by_exchange_rate_difference, account_currency=account_currency, @@ -419,6 +420,7 @@ class PurchaseReceipt(BuyingController): debit=discrepancy_caused_by_exchange_rate_difference, credit=0.0, remarks=remarks, + against_type="Supplier", against_account=self.supplier, debit_in_account_currency=-1 * discrepancy_caused_by_exchange_rate_difference, account_currency=account_currency, From ea4b6ff27bc9406c5c2abd4519938bb7942aa3f4 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Tue, 7 Nov 2023 13:05:38 +0530 Subject: [PATCH 020/205] fix: remove string from against field in loyalty point entry --- erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 8033dbff09..a059c32dfa 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -7,7 +7,7 @@ from frappe import _, msgprint, throw from frappe.contacts.doctype.address.address import get_address_display from frappe.model.mapper import get_mapped_doc from frappe.model.utils import get_fetch_values -from frappe.utils import add_days, cint, cstr, flt, formatdate, get_link_to_form, getdate, nowdate +from frappe.utils import add_days, cint, flt, formatdate, get_link_to_form, getdate, nowdate import erpnext from erpnext.accounts.deferred_revenue import validate_service_stop_date @@ -1239,9 +1239,7 @@ class SalesInvoice(SellingController): "party_type": "Customer", "party": self.customer, "against_type": "Account", - "against": "Expense account - " - + cstr(self.loyalty_redemption_account) - + " for the Loyalty Program", + "against": self.loyalty_redemption_account, "credit": self.loyalty_amount, "against_voucher": self.return_against if cint(self.is_return) else self.name, "against_voucher_type": self.doctype, From 68c6ad6036ad9ce1f40ea4f20568988c5bbe5deb Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Tue, 7 Nov 2023 15:31:52 +0530 Subject: [PATCH 021/205] fix: test for balance in forex account after revaluation --- .../doctype/journal_entry/journal_entry.py | 24 +++++++------------ erpnext/accounts/general_ledger.py | 4 ++-- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index da6c8cf7cd..27d14c2e3f 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -706,7 +706,7 @@ class JournalEntry(AccountsController): ), alert=True, ) - elif no_of_credited_acc == 1 and no_of_debited_acc == 1: + elif no_of_credited_acc <= 1 and no_of_debited_acc <= 1: self.set_against_accounts_for_single_dr_cr() self.separate_against_account_entries = 0 elif no_of_credited_acc == 1: @@ -720,9 +720,9 @@ class JournalEntry(AccountsController): self.accounts_debited, self.accounts_credited = [], [] self.separate_against_account_entries = 1 for d in self.get("accounts"): - if has_debit_amount(d): + if flt(d.debit) > 0: self.accounts_debited.append(d) - elif has_credit_amount(d): + elif flt(d.credit) > 0: self.accounts_credited.append(d) if d.against_account: @@ -730,13 +730,15 @@ class JournalEntry(AccountsController): break def set_against_accounts_for_single_dr_cr(self): + against_account = None for d in self.accounts: - if has_debit_amount(d): + if flt(d.debit) > 0: against_account = self.accounts_credited[0] - elif has_credit_amount(d): + elif flt(d.credit) > 0: against_account = self.accounts_debited[0] - d.against_type = against_account.party_type or "Account" - d.against_account = against_account.party or against_account.account + if against_account: + d.against_type = against_account.party_type or "Account" + d.against_account = against_account.party or against_account.account def validate_debit_credit_amount(self): if not (self.voucher_type == "Exchange Gain Or Loss" and self.multi_currency): @@ -1626,11 +1628,3 @@ def make_reverse_journal_entry(source_name, target_doc=None): ) return doclist - - -def has_credit_amount(account): - return flt(account.credit) > 0 or flt(account.credit_in_account_currency) > 0 - - -def has_debit_amount(account): - return flt(account.debit) > 0 or flt(account.debit_in_account_currency) > 0 diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index 70a8470614..2f721c8013 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -356,7 +356,7 @@ def save_entries(gl_map, adv_adj, update_outstanding, from_repost=False): process_debit_credit_difference(gl_map) if gl_map: - check_freezing_date(gl_map[0]["posting_date"], adv_adj) + # check_freezing_date(gl_map[0]["posting_date"], adv_adj) is_opening = any(d.get("is_opening") == "Yes" for d in gl_map) if gl_map[0]["voucher_type"] != "Period Closing Voucher": validate_against_pcv(is_opening, gl_map[0]["posting_date"], gl_map[0]["company"]) @@ -593,7 +593,7 @@ def make_reverse_gl_entries( partial_cancel=partial_cancel, ) validate_accounting_period(gl_entries) - check_freezing_date(gl_entries[0]["posting_date"], adv_adj) + # check_freezing_date(gl_entries[0]["posting_date"], adv_adj) is_opening = any(d.get("is_opening") == "Yes" for d in gl_entries) validate_against_pcv(is_opening, gl_entries[0]["posting_date"], gl_entries[0]["company"]) From 291a4991246b5a53491066eb46efda0de2a8002f Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Wed, 8 Nov 2023 00:46:52 +0530 Subject: [PATCH 022/205] fix: split expected jv entries for scrap asset --- erpnext/accounts/general_ledger.py | 4 ++-- erpnext/assets/doctype/asset/test_asset.py | 13 +++++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index 2f721c8013..70a8470614 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -356,7 +356,7 @@ def save_entries(gl_map, adv_adj, update_outstanding, from_repost=False): process_debit_credit_difference(gl_map) if gl_map: - # check_freezing_date(gl_map[0]["posting_date"], adv_adj) + check_freezing_date(gl_map[0]["posting_date"], adv_adj) is_opening = any(d.get("is_opening") == "Yes" for d in gl_map) if gl_map[0]["voucher_type"] != "Period Closing Voucher": validate_against_pcv(is_opening, gl_map[0]["posting_date"], gl_map[0]["company"]) @@ -593,7 +593,7 @@ def make_reverse_gl_entries( partial_cancel=partial_cancel, ) validate_accounting_period(gl_entries) - # check_freezing_date(gl_entries[0]["posting_date"], adv_adj) + check_freezing_date(gl_entries[0]["posting_date"], adv_adj) is_opening = any(d.get("is_opening") == "Yes" for d in gl_entries) validate_against_pcv(is_opening, gl_entries[0]["posting_date"], gl_entries[0]["company"]) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 9e3ec6faa8..536845ed26 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -256,7 +256,16 @@ class TestAsset(AssetSetup): flt(18000.0 + pro_rata_amount, asset.precision("gross_purchase_amount")), 0.0, ), - ("_Test Fixed Asset - _TC", 0.0, 100000.0), + ( + "_Test Fixed Asset - _TC", + 0.0, + flt(18000.0 + pro_rata_amount, asset.precision("gross_purchase_amount")), + ), + ( + "_Test Fixed Asset - _TC", + 0.0, + flt(82000.0 - pro_rata_amount, asset.precision("gross_purchase_amount")), + ), ( "_Test Gain/Loss on Asset Disposal - _TC", flt(82000.0 - pro_rata_amount, asset.precision("gross_purchase_amount")), @@ -267,7 +276,7 @@ class TestAsset(AssetSetup): gle = frappe.db.sql( """select account, debit, credit from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no = %s - order by account""", + order by account, credit""", asset.journal_entry_for_scrap, ) self.assertSequenceEqual(gle, expected_gle) From 5f5d75a0bbce2e28411ca79e7eaeca669933692a Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Wed, 8 Nov 2023 11:19:45 +0530 Subject: [PATCH 023/205] chore: linting issues --- erpnext/accounts/doctype/journal_entry/journal_entry.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 27d14c2e3f..1c737fc543 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -700,10 +700,8 @@ class JournalEntry(AccountsController): if no_of_credited_acc > 1 and no_of_debited_acc > 1: frappe.msgprint( _( - "Unable to automatically determine {0} accounts. Set them up in the {1} table if needed.".format( - frappe.bold("against"), frappe.bold("Accounting Entries") - ) - ), + "Unable to automatically determine {0} accounts. Set them up in the {1} table if needed." + ).format(frappe.bold("against"), frappe.bold("Accounting Entries")), alert=True, ) elif no_of_credited_acc <= 1 and no_of_debited_acc <= 1: From f9c88ea7bc96837ece6c477e4dc9a324985d98ac Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Wed, 8 Nov 2023 12:55:41 +0530 Subject: [PATCH 024/205] refactor: keep old against fields intact --- .../accounts/doctype/gl_entry/gl_entry.json | 23 ++++++++++++------- .../journal_entry_account.json | 23 ++++++++++++------- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.json b/erpnext/accounts/doctype/gl_entry/gl_entry.json index 1adeaa54d8..16df40f435 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.json +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.json @@ -19,6 +19,7 @@ "credit_in_account_currency", "against_type", "against", + "against_link", "against_voucher_type", "against_voucher", "voucher_type", @@ -137,13 +138,19 @@ "options": "DocType" }, { - "fieldname": "against", - "fieldtype": "Dynamic Link", - "in_filter": 1, - "label": "Against", - "oldfieldname": "against", - "oldfieldtype": "Text", - "options": "against_type" + "fieldname": "against", + "fieldtype": "Text", + "in_filter": 1, + "label": "Against", + "oldfieldname": "against", + "oldfieldtype": "Text" + }, + { + "fieldname": "against_link", + "fieldtype": "Dynamic Link", + "in_filter": 1, + "label": "Against", + "options": "against_type" }, { "fieldname": "against_voucher_type", @@ -295,7 +302,7 @@ "idx": 1, "in_create": 1, "links": [], - "modified": "2023-09-25 12:03:23.031733", + "modified": "2023-11-08 12:20:23.031733", "modified_by": "Administrator", "module": "Accounts", "name": "GL Entry", diff --git a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json index 0e5dde0e3a..8d8c83751b 100644 --- a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json +++ b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json @@ -38,7 +38,8 @@ "is_advance", "user_remark", "against_type", - "against_account" + "against_account", + "against_account_link" ], "fields": [ { @@ -249,15 +250,21 @@ "print_hide": 1 }, { - "fieldname": "against_account", + "fieldname": "against_account", + "fieldtype": "Text", + "hidden": 1, + "label": "Against Account", + "no_copy": 1, + "oldfieldname": "against_account", + "oldfieldtype": "Text", + "print_hide": 1 + }, + { + "fieldname": "against_account_link", "fieldtype": "Dynamic Link", - "hidden": 1, "label": "Against Account", "no_copy": 1, - "oldfieldname": "against_account", - "oldfieldtype": "Text", - "options": "against_type", - "print_hide": 1 + "options": "against_type" }, { "collapsible": 1, @@ -294,7 +301,7 @@ "idx": 1, "istable": 1, "links": [], - "modified": "2023-10-11 13:05:21.489496", + "modified": "2023-11-08 12:20:21.489496", "modified_by": "Administrator", "module": "Accounts", "name": "Journal Entry Account", From 09439334cae6a7306dad8e54a9f81f9ffa483f8b Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Wed, 8 Nov 2023 12:57:00 +0530 Subject: [PATCH 025/205] refactor: use both fields to store against values --- erpnext/accounts/deferred_revenue.py | 2 ++ .../invoice_discounting.py | 2 ++ .../doctype/journal_entry/journal_entry.py | 17 +++++++++++---- .../doctype/payment_entry/payment_entry.py | 6 ++++++ .../purchase_invoice/purchase_invoice.py | 21 +++++++++++++++++++ .../doctype/sales_invoice/sales_invoice.py | 14 +++++++++++++ erpnext/assets/doctype/asset/asset.py | 2 ++ .../asset_capitalization.py | 5 +++++ .../doctype/asset_repair/asset_repair.py | 4 ++++ erpnext/controllers/accounts_controller.py | 4 ++++ erpnext/controllers/stock_controller.py | 5 +++++ .../regional/united_arab_emirates/utils.py | 1 + .../stock/doctype/stock_entry/stock_entry.py | 2 ++ 13 files changed, 81 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/deferred_revenue.py b/erpnext/accounts/deferred_revenue.py index 00d5ea3245..c2188c0da1 100644 --- a/erpnext/accounts/deferred_revenue.py +++ b/erpnext/accounts/deferred_revenue.py @@ -521,6 +521,7 @@ def make_gl_entries( "account": credit_account, "against_type": against_type, "against": against, + "against_link": against, "credit": base_amount, "credit_in_account_currency": amount, "cost_center": cost_center, @@ -541,6 +542,7 @@ def make_gl_entries( "account": debit_account, "against_type": against_type, "against": against, + "against_link": against, "debit": base_amount, "debit_in_account_currency": amount, "cost_center": cost_center, diff --git a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py index 744dff4670..ebfa0de3ae 100644 --- a/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py +++ b/erpnext/accounts/doctype/invoice_discounting/invoice_discounting.py @@ -127,6 +127,7 @@ class InvoiceDiscounting(AccountsController): "party": d.customer, "against_type": "Account", "against": self.accounts_receivable_credit, + "against_link": self.accounts_receivable_credit, "credit": outstanding_in_company_currency, "credit_in_account_currency": outstanding_in_company_currency if inv.party_account_currency == company_currency @@ -148,6 +149,7 @@ class InvoiceDiscounting(AccountsController): "party": d.customer, "against_type": "Account", "against": inv.debit_to, + "against_link": inv.debit_to, "debit": outstanding_in_company_currency, "debit_in_account_currency": outstanding_in_company_currency if ar_credit_account_currency == company_currency diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 1c737fc543..9f76d9df19 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -683,10 +683,10 @@ class JournalEntry(AccountsController): else: against_type = "Supplier" + against_account = frappe.db.get_value(d.reference_type, d.reference_name, against_type.lower()) d.against_type = against_type - d.against_account = frappe.db.get_value( - d.reference_type, d.reference_name, against_type.lower() - ) + d.against_account = against_account + d.against_account_link = against_account else: self.get_against_accounts() @@ -737,6 +737,7 @@ class JournalEntry(AccountsController): if against_account: d.against_type = against_account.party_type or "Account" d.against_account = against_account.party or against_account.account + d.against_account_link = against_account.party or against_account.account def validate_debit_credit_amount(self): if not (self.voucher_type == "Exchange Gain Or Loss" and self.multi_currency): @@ -967,7 +968,13 @@ class JournalEntry(AccountsController): ) if not self.separate_against_account_entries: - gl_dict.update({"against_type": d.against_type, "against": d.against_account}) + gl_dict.update( + { + "against_type": d.against_type, + "against": d.against_account, + "against_link": d.against_account, + } + ) gl_map.append(gl_dict) elif d in self.against_accounts: @@ -975,6 +982,7 @@ class JournalEntry(AccountsController): { "against_type": self.split_account.get("party_type") or "Account", "against": self.split_account.get("party") or self.split_account.get("account"), + "against_link": self.split_account.get("party") or self.split_account.get("account"), } ) gl_map.append(gl_dict) @@ -989,6 +997,7 @@ class JournalEntry(AccountsController): { "against_type": against_account.party_type or "Account", "against": against_account.party or against_account.account, + "against_link": against_account.party or against_account.account, "debit": flt(debit, d.precision("debit")), "credit": flt(credit, d.precision("credit")), "account_currency": d.account_currency, diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index ff558b2f48..ff8695f770 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -1078,6 +1078,7 @@ class PaymentEntry(AccountsController): "party": self.party, "against_type": "Account", "against": against_account, + "against_link": against_account, "account_currency": self.party_account_currency, "cost_center": self.cost_center, }, @@ -1237,6 +1238,7 @@ class PaymentEntry(AccountsController): "account_currency": self.paid_from_account_currency, "against_type": self.party_type if self.payment_type == "Pay" else "Account", "against": self.party if self.payment_type == "Pay" else self.paid_to, + "against_link": self.party if self.payment_type == "Pay" else self.paid_to, "credit_in_account_currency": self.paid_amount, "credit": self.base_paid_amount, "cost_center": self.cost_center, @@ -1253,6 +1255,7 @@ class PaymentEntry(AccountsController): "account_currency": self.paid_to_account_currency, "against_type": self.party_type if self.payment_type == "Receive" else "Account", "against": self.party if self.payment_type == "Receive" else self.paid_from, + "against_link": self.party if self.payment_type == "Receive" else self.paid_from, "debit_in_account_currency": self.received_amount, "debit": self.base_received_amount, "cost_center": self.cost_center, @@ -1287,6 +1290,7 @@ class PaymentEntry(AccountsController): "account": d.account_head, "against_type": against_type, "against": against, + "against_link": against, dr_or_cr: tax_amount, dr_or_cr + "_in_account_currency": base_tax_amount if account_currency == self.company_currency @@ -1313,6 +1317,7 @@ class PaymentEntry(AccountsController): "account": payment_account, "against_type": against_type, "against": against, + "against_link": against, rev_dr_or_cr: tax_amount, rev_dr_or_cr + "_in_account_currency": base_tax_amount if account_currency == self.company_currency @@ -1339,6 +1344,7 @@ class PaymentEntry(AccountsController): "account_currency": account_currency, "against_type": self.party_type or "Account", "against": self.party or self.paid_from, + "against_link": self.party or self.paid_from, "debit_in_account_currency": d.amount, "debit": d.amount, "cost_center": d.cost_center, diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index cf89b333c6..53c131a507 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -643,6 +643,7 @@ class PurchaseInvoice(BuyingController): "due_date": self.due_date, "against_type": "Account", "against": self.against_expense_account, + "against_link": self.against_expense_account, "credit": base_grand_total, "credit_in_account_currency": base_grand_total if self.party_account_currency == self.company_currency @@ -717,6 +718,7 @@ class PurchaseInvoice(BuyingController): "account": warehouse_account[item.warehouse]["account"], "against_type": "Account", "against": warehouse_account[item.from_warehouse]["account"], + "against_link": warehouse_account[item.from_warehouse]["account"], "cost_center": item.cost_center, "project": item.project or self.project, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), @@ -738,6 +740,7 @@ class PurchaseInvoice(BuyingController): "account": warehouse_account[item.from_warehouse]["account"], "against_type": "Account", "against": warehouse_account[item.warehouse]["account"], + "against_link": warehouse_account[item.warehouse]["account"], "cost_center": item.cost_center, "project": item.project or self.project, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), @@ -756,6 +759,7 @@ class PurchaseInvoice(BuyingController): "account": item.expense_account, "against_type": "Supplier", "against": self.supplier, + "against_link": self.supplier, "debit": flt(item.base_net_amount, item.precision("base_net_amount")), "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "cost_center": item.cost_center, @@ -774,6 +778,7 @@ class PurchaseInvoice(BuyingController): "account": item.expense_account, "against_type": "Supplier", "against": self.supplier, + "against_link": self.supplier, "debit": warehouse_debit_amount, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "cost_center": item.cost_center, @@ -794,6 +799,7 @@ class PurchaseInvoice(BuyingController): "account": account, "against_type": "Account", "against": item.expense_account, + "against_link": item.expense_account, "cost_center": item.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "credit": flt(amount["base_amount"]), @@ -815,6 +821,7 @@ class PurchaseInvoice(BuyingController): "account": supplier_warehouse_account, "against_type": "Account", "against": item.expense_account, + "against_link": item.expense_account, "cost_center": item.cost_center, "project": item.project or self.project, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), @@ -871,6 +878,7 @@ class PurchaseInvoice(BuyingController): "account": expense_account, "against_type": "Supplier", "against": self.supplier, + "against_link": self.supplier, "debit": amount, "cost_center": item.cost_center, "project": item.project or self.project, @@ -898,6 +906,7 @@ class PurchaseInvoice(BuyingController): "account": expense_account, "against_type": "Supplier", "against": self.supplier, + "against_link": self.supplier, "debit": discrepancy_caused_by_exchange_rate_difference, "cost_center": item.cost_center, "project": item.project or self.project, @@ -912,6 +921,7 @@ class PurchaseInvoice(BuyingController): "account": self.get_company_default("exchange_gain_loss_account"), "against_type": "Supplier", "against": self.supplier, + "against_link": self.supplier, "credit": discrepancy_caused_by_exchange_rate_difference, "cost_center": item.cost_center, "project": item.project or self.project, @@ -958,6 +968,7 @@ class PurchaseInvoice(BuyingController): "account": stock_rbnb, "against_type": "Supplier", "against": self.supplier, + "against_link": self.supplier, "debit": flt(item.item_tax_amount, item.precision("item_tax_amount")), "remarks": self.remarks or _("Accounting Entry for Stock"), "cost_center": self.cost_center, @@ -1007,6 +1018,7 @@ class PurchaseInvoice(BuyingController): "account": cost_of_goods_sold_account, "against_type": "Account", "against": item.expense_account, + "against_link": item.expense_account, "debit": stock_adjustment_amt, "remarks": self.get("remarks") or _("Stock Adjustment"), "cost_center": item.cost_center, @@ -1038,6 +1050,7 @@ class PurchaseInvoice(BuyingController): "account": tax.account_head, "against_type": "Supplier", "against": self.supplier, + "against_link": self.supplier, dr_or_cr: base_amount, dr_or_cr + "_in_account_currency": base_amount if account_currency == self.company_currency @@ -1088,6 +1101,7 @@ class PurchaseInvoice(BuyingController): "against_type": "Supplier", "cost_center": tax.cost_center, "against": self.supplier, + "against_link": self.supplier, "credit": applicable_amount, "remarks": self.remarks or _("Accounting Entry for Stock"), }, @@ -1107,6 +1121,7 @@ class PurchaseInvoice(BuyingController): "cost_center": tax.cost_center, "against_type": "Supplier", "against": self.supplier, + "against_link": self.supplier, "credit": valuation_tax[tax.name], "remarks": self.remarks or _("Accounting Entry for Stock"), }, @@ -1123,6 +1138,7 @@ class PurchaseInvoice(BuyingController): "account": self.unrealized_profit_loss_account, "against_type": "Supplier", "against": self.supplier, + "against_link": self.supplier, "credit": flt(self.total_taxes_and_charges), "credit_in_account_currency": flt(self.base_total_taxes_and_charges), "cost_center": self.cost_center, @@ -1145,6 +1161,7 @@ class PurchaseInvoice(BuyingController): "party": self.supplier, "against_type": "Account", "against": self.cash_bank_account, + "against_link": self.cash_bank_account, "debit": self.base_paid_amount, "debit_in_account_currency": self.base_paid_amount if self.party_account_currency == self.company_currency @@ -1167,6 +1184,7 @@ class PurchaseInvoice(BuyingController): "account": self.cash_bank_account, "against_type": "Supplier", "against": self.supplier, + "against_link": self.supplier, "credit": self.base_paid_amount, "credit_in_account_currency": self.base_paid_amount if bank_account_currency == self.company_currency @@ -1192,6 +1210,7 @@ class PurchaseInvoice(BuyingController): "party": self.supplier, "against_type": "Account", "against": self.write_off_account, + "against_link": self.write_off_account, "debit": self.base_write_off_amount, "debit_in_account_currency": self.base_write_off_amount if self.party_account_currency == self.company_currency @@ -1213,6 +1232,7 @@ class PurchaseInvoice(BuyingController): "account": self.write_off_account, "against_type": "Supplier", "against": self.supplier, + "against_link": self.supplier, "credit": flt(self.base_write_off_amount), "credit_in_account_currency": self.base_write_off_amount if write_off_account_currency == self.company_currency @@ -1241,6 +1261,7 @@ class PurchaseInvoice(BuyingController): "account": round_off_account, "against_type": "Supplier", "against": self.supplier, + "against_link": self.supplier, "debit_in_account_currency": self.rounding_adjustment, "debit": self.base_rounding_adjustment, "cost_center": round_off_cost_center diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index a059c32dfa..87b40c09bd 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1042,6 +1042,7 @@ class SalesInvoice(SellingController): "due_date": self.due_date, "against_type": "Account", "against": self.against_income_account, + "against_link": self.against_income_account, "debit": base_grand_total, "debit_in_account_currency": base_grand_total if self.party_account_currency == self.company_currency @@ -1072,6 +1073,7 @@ class SalesInvoice(SellingController): "account": tax.account_head, "against_type": "Customer", "against": self.customer, + "against_link": self.customer, "credit": flt(base_amount, tax.precision("tax_amount_after_discount_amount")), "credit_in_account_currency": ( flt(base_amount, tax.precision("base_tax_amount_after_discount_amount")) @@ -1094,6 +1096,7 @@ class SalesInvoice(SellingController): "account": self.unrealized_profit_loss_account, "against_type": "Customer", "against": self.customer, + "against_link": self.customer, "debit": flt(self.total_taxes_and_charges), "debit_in_account_currency": flt(self.base_total_taxes_and_charges), "cost_center": self.cost_center, @@ -1163,6 +1166,7 @@ class SalesInvoice(SellingController): for gle in fixed_asset_gl_entries: gle["against_type"] = "Customer" gle["against"] = self.customer + gle["against_link"] = self.customer gl_entries.append(self.get_gl_dict(gle, item=item)) self.set_asset_status(asset) @@ -1185,6 +1189,7 @@ class SalesInvoice(SellingController): "account": income_account, "against_type": "Customer", "against": self.customer, + "against_link": self.customer, "credit": flt(base_amount, item.precision("base_net_amount")), "credit_in_account_currency": ( flt(base_amount, item.precision("base_net_amount")) @@ -1240,6 +1245,7 @@ class SalesInvoice(SellingController): "party": self.customer, "against_type": "Account", "against": self.loyalty_redemption_account, + "against_link": self.loyalty_redemption_account, "credit": self.loyalty_amount, "against_voucher": self.return_against if cint(self.is_return) else self.name, "against_voucher_type": self.doctype, @@ -1255,6 +1261,7 @@ class SalesInvoice(SellingController): "cost_center": self.cost_center or self.loyalty_redemption_cost_center, "against_type": "Customer", "against": self.customer, + "against_link": self.customer, "debit": self.loyalty_amount, "remark": "Loyalty Points redeemed by the customer", }, @@ -1283,6 +1290,7 @@ class SalesInvoice(SellingController): "party": self.customer, "against_type": "Account", "against": payment_mode.account, + "against_link": payment_mode.account, "credit": payment_mode.base_amount, "credit_in_account_currency": payment_mode.base_amount if self.party_account_currency == self.company_currency @@ -1305,6 +1313,7 @@ class SalesInvoice(SellingController): "account": payment_mode.account, "against_type": "Customer", "against": self.customer, + "against_link": self.customer, "debit": payment_mode.base_amount, "debit_in_account_currency": payment_mode.base_amount if payment_mode_account_currency == self.company_currency @@ -1330,6 +1339,7 @@ class SalesInvoice(SellingController): "party": self.customer, "against_type": "Account", "against": self.account_for_change_amount, + "against_link": self.account_for_change_amount, "debit": flt(self.base_change_amount), "debit_in_account_currency": flt(self.base_change_amount) if self.party_account_currency == self.company_currency @@ -1352,6 +1362,7 @@ class SalesInvoice(SellingController): "account": self.account_for_change_amount, "against_type": "Customer", "against": self.customer, + "against_link": self.customer, "credit": self.base_change_amount, "cost_center": self.cost_center, }, @@ -1379,6 +1390,7 @@ class SalesInvoice(SellingController): "party": self.customer, "against_type": "Account", "against": self.write_off_account, + "against_link": self.write_off_account, "credit": flt(self.base_write_off_amount, self.precision("base_write_off_amount")), "credit_in_account_currency": ( flt(self.base_write_off_amount, self.precision("base_write_off_amount")) @@ -1400,6 +1412,7 @@ class SalesInvoice(SellingController): "account": self.write_off_account, "against_type": "Customer", "against": self.customer, + "against_link": self.customer, "debit": flt(self.base_write_off_amount, self.precision("base_write_off_amount")), "debit_in_account_currency": ( flt(self.base_write_off_amount, self.precision("base_write_off_amount")) @@ -1429,6 +1442,7 @@ class SalesInvoice(SellingController): "account": round_off_account, "against_type": "Customer", "against": self.customer, + "against_link": self.customer, "credit_in_account_currency": flt( self.rounding_adjustment, self.precision("rounding_adjustment") ), diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 32518a109a..8908d8e5d0 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -610,6 +610,7 @@ class Asset(AccountsController): "account": cwip_account, "against_type": "Account", "against": fixed_asset_account, + "against_link": fixed_asset_account, "remarks": self.get("remarks") or _("Accounting Entry for Asset"), "posting_date": self.available_for_use_date, "credit": self.purchase_receipt_amount, @@ -626,6 +627,7 @@ class Asset(AccountsController): "account": fixed_asset_account, "against_type": "Account", "against": cwip_account, + "against_link": cwip_account, "remarks": self.get("remarks") or _("Accounting Entry for Asset"), "posting_date": self.available_for_use_date, "debit": self.purchase_receipt_amount, diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py index 229c16d18a..31aee3386d 100644 --- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py +++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py @@ -432,6 +432,7 @@ class AssetCapitalization(StockController): "account": account, "against_type": "Account", "against": target_account, + "against_link": target_account, "cost_center": item_row.cost_center, "project": item_row.get("project") or self.get("project"), "remarks": self.get("remarks") or "Accounting Entry for Stock", @@ -474,6 +475,7 @@ class AssetCapitalization(StockController): for gle in fixed_asset_gl_entries: gle["against_type"] = "Account" gle["against"] = target_account + gle["against_link"] = target_account gl_entries.append(self.get_gl_dict(gle, item=item)) target_against.add(gle["account"]) @@ -491,6 +493,7 @@ class AssetCapitalization(StockController): "account": item_row.expense_account, "against_type": "Account", "against": target_account, + "against_link": target_account, "cost_center": item_row.cost_center, "project": item_row.get("project") or self.get("project"), "remarks": self.get("remarks") or "Accounting Entry for Stock", @@ -510,6 +513,7 @@ class AssetCapitalization(StockController): "account": self.target_fixed_asset_account, "against_type": "Account", "against": target_account, + "against_link": target_account, "remarks": self.get("remarks") or _("Accounting Entry for Asset"), "debit": flt(self.total_value, precision) / len(target_against), "cost_center": self.get("cost_center"), @@ -530,6 +534,7 @@ class AssetCapitalization(StockController): "account": account, "against_type": "Account", "against": target_account, + "against_link": target_account, "cost_center": self.cost_center, "project": self.get("project"), "remarks": self.get("remarks") or "Accounting Entry for Stock", diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.py b/erpnext/assets/doctype/asset_repair/asset_repair.py index 65d2f8ef18..0b072b2a69 100644 --- a/erpnext/assets/doctype/asset_repair/asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/asset_repair.py @@ -243,6 +243,7 @@ class AssetRepair(AccountsController): "debit_in_account_currency": self.repair_cost, "against_type": "Account", "against": pi_expense_account, + "against_link": pi_expense_account, "voucher_type": self.doctype, "voucher_no": self.name, "cost_center": self.cost_center, @@ -263,6 +264,7 @@ class AssetRepair(AccountsController): "credit_in_account_currency": self.repair_cost, "against_type": "Account", "against": fixed_asset_account, + "against_link": fixed_asset_account, "voucher_type": self.doctype, "voucher_no": self.name, "cost_center": self.cost_center, @@ -298,6 +300,7 @@ class AssetRepair(AccountsController): "credit_in_account_currency": item.amount, "against_type": "Account", "against": fixed_asset_account, + "against_link": fixed_asset_account, "voucher_type": self.doctype, "voucher_no": self.name, "cost_center": self.cost_center, @@ -316,6 +319,7 @@ class AssetRepair(AccountsController): "debit_in_account_currency": item.amount, "against_type": "Account", "against": item.expense_account or default_expense_account, + "against_link": item.expense_account or default_expense_account, "voucher_type": self.doctype, "voucher_no": self.name, "cost_center": self.cost_center, diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index e984730d74..c9c248c3ea 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1098,6 +1098,7 @@ class AccountsController(TransactionBase): "account": round_off_account, "against_type": against_type, "against": against, + "against_link": against, credit_or_debit: precision_loss, "cost_center": round_off_cost_center if self.use_company_roundoff_cost_center @@ -1479,6 +1480,7 @@ class AccountsController(TransactionBase): "account": item.discount_account, "against_type": against_type, "against": supplier_or_customer, + "against_link": supplier_or_customer, dr_or_cr: flt( discount_amount * self.get("conversion_rate"), item.precision("discount_amount") ), @@ -1498,6 +1500,7 @@ class AccountsController(TransactionBase): "account": income_or_expense_account, "against_type": against_type, "against": supplier_or_customer, + "against_link": supplier_or_customer, rev_dr_cr: flt( discount_amount * self.get("conversion_rate"), item.precision("discount_amount") ), @@ -1522,6 +1525,7 @@ class AccountsController(TransactionBase): "account": self.additional_discount_account, "against_type": against_type, "against": supplier_or_customer, + "against_link": supplier_or_customer, dr_or_cr: self.base_discount_amount, "cost_center": self.cost_center or erpnext.get_default_cost_center(self.company), }, diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 335f2b0ea6..a005c8cb8a 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -164,6 +164,7 @@ class StockController(AccountsController): "account": warehouse_account[sle.warehouse]["account"], "against_type": "Account", "against": expense_account, + "against_link": expense_account, "cost_center": item_row.cost_center, "project": item_row.project or self.get("project"), "remarks": self.get("remarks") or _("Accounting Entry for Stock"), @@ -181,6 +182,7 @@ class StockController(AccountsController): "account": expense_account, "against_type": "Account", "against": warehouse_account[sle.warehouse]["account"], + "against_link": warehouse_account[sle.warehouse]["account"], "cost_center": item_row.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "debit": -1 * flt(sle.stock_value_difference, precision), @@ -214,6 +216,7 @@ class StockController(AccountsController): "account": expense_account, "against_type": "Account", "against": warehouse_asset_account, + "against_link": warehouse_asset_account, "cost_center": item_row.cost_center, "project": item_row.project or self.get("project"), "remarks": _("Rounding gain/loss Entry for Stock Transfer"), @@ -231,6 +234,7 @@ class StockController(AccountsController): "account": warehouse_asset_account, "against_type": "Account", "against": expense_account, + "against_link": expense_account, "cost_center": item_row.cost_center, "remarks": _("Rounding gain/loss Entry for Stock Transfer"), "credit": sle_rounding_diff, @@ -847,6 +851,7 @@ class StockController(AccountsController): "credit": credit, "against_type": against_type, "against": against_account, + "against_link": against_account, "remarks": remarks, } diff --git a/erpnext/regional/united_arab_emirates/utils.py b/erpnext/regional/united_arab_emirates/utils.py index a850d5be7c..250a4b1495 100644 --- a/erpnext/regional/united_arab_emirates/utils.py +++ b/erpnext/regional/united_arab_emirates/utils.py @@ -155,6 +155,7 @@ def make_gl_entry(tax, gl_entries, doc, tax_accounts): "posting_date": doc.posting_date, "against_type": "Supplier", "against": doc.supplier, + "against_link": doc.supplier, dr_or_cr: tax.base_tax_amount_after_discount_amount, dr_or_cr + "_in_account_currency": tax.base_tax_amount_after_discount_amount if account_currency == doc.company_currency diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 1ed2f98a9d..e87658bc98 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -1388,6 +1388,7 @@ class StockEntry(StockController): "account": account, "against_type": "Account", "against": d.expense_account, + "against_link": d.expense_account, "cost_center": d.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "credit_in_account_currency": flt(amount["amount"]), @@ -1403,6 +1404,7 @@ class StockEntry(StockController): "account": d.expense_account, "against_type": "Account", "against": account, + "against_link": account, "cost_center": d.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Stock"), "credit": -1 From 450c2470e959f4d705afc3212546249ad406bee3 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Wed, 8 Nov 2023 14:08:57 +0530 Subject: [PATCH 026/205] refactor: set against account link for jv --- erpnext/accounts/doctype/journal_entry/journal_entry.py | 3 ++- erpnext/accounts/utils.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 9f76d9df19..c70ad2fdaa 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -230,6 +230,7 @@ class JournalEntry(AccountsController): "account": tax_withholding_details.get("account_head"), rev_debit_or_credit: tax_withholding_details.get("tax_amount"), "against_account": parties[0], + "against_account_link": parties[0], }, ) @@ -723,7 +724,7 @@ class JournalEntry(AccountsController): elif flt(d.credit) > 0: self.accounts_credited.append(d) - if d.against_account: + if d.against_account_link: self.separate_against_account_entries = 0 break diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index e0adac412b..0edfc2ad5a 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -629,6 +629,7 @@ def update_reference_in_journal_entry(d, journal_entry, do_not_save=False): new_row.set("reference_name", d["against_voucher"]) new_row.against_account = cstr(jv_detail.against_account) + new_row.against_account_link = cstr(jv_detail.against_account) new_row.is_advance = cstr(jv_detail.is_advance) new_row.docstatus = 1 From 96f31847b203eb58cc92e04747700de859e8eb97 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Wed, 29 Nov 2023 16:04:36 +0530 Subject: [PATCH 027/205] fix: set cwip account for company before tests --- .../asset_value_adjustment/test_asset_value_adjustment.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/assets/doctype/asset_value_adjustment/test_asset_value_adjustment.py b/erpnext/assets/doctype/asset_value_adjustment/test_asset_value_adjustment.py index 5d49759727..2c97baece5 100644 --- a/erpnext/assets/doctype/asset_value_adjustment/test_asset_value_adjustment.py +++ b/erpnext/assets/doctype/asset_value_adjustment/test_asset_value_adjustment.py @@ -18,6 +18,9 @@ from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_pu class TestAssetValueAdjustment(unittest.TestCase): def setUp(self): create_asset_data() + frappe.db.set_value( + "Company", "_Test Company", "capital_work_in_progress_account", "CWIP Account - _TC" + ) def test_current_asset_value(self): pr = make_purchase_receipt( From eb4c476490ea32cd94e0b6cc3715abe99f1d4e0a Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 15 Sep 2023 21:24:53 +0530 Subject: [PATCH 028/205] refactor: primitive summary for p&l and balance sheet --- erpnext/accounts/report/balance_sheet/balance_sheet.py | 6 +++--- .../profit_and_loss_statement/profit_and_loss_statement.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/report/balance_sheet/balance_sheet.py b/erpnext/accounts/report/balance_sheet/balance_sheet.py index b225aac7b5..5d6ca23a6b 100644 --- a/erpnext/accounts/report/balance_sheet/balance_sheet.py +++ b/erpnext/accounts/report/balance_sheet/balance_sheet.py @@ -97,11 +97,11 @@ def execute(filters=None): chart = get_chart_data(filters, columns, asset, liability, equity) - report_summary = get_report_summary( + report_summary, primitive_summary = get_report_summary( period_list, asset, liability, equity, provisional_profit_loss, currency, filters ) - return columns, data, message, chart, report_summary + return columns, data, message, chart, report_summary, primitive_summary def get_provisional_profit_loss( @@ -217,7 +217,7 @@ def get_report_summary( "datatype": "Currency", "currency": currency, }, - ] + ], (net_asset - net_liability + net_equity) def get_chart_data(filters, columns, asset, liability, equity): diff --git a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py index 66353358a0..002c05c9e3 100644 --- a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py +++ b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py @@ -66,11 +66,11 @@ def execute(filters=None): currency = filters.presentation_currency or frappe.get_cached_value( "Company", filters.company, "default_currency" ) - report_summary = get_report_summary( + report_summary, primitive_summary = get_report_summary( period_list, filters.periodicity, income, expense, net_profit_loss, currency, filters ) - return columns, data, None, chart, report_summary + return columns, data, None, chart, report_summary, primitive_summary def get_report_summary( @@ -112,7 +112,7 @@ def get_report_summary( "datatype": "Currency", "currency": currency, }, - ] + ], net_profit def get_net_profit_loss(income, expense, period_list, company, currency=None, consolidated=False): From decdbd278200bb83baa7c5f08bd706c1c7c5406a Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 15 Sep 2023 21:38:15 +0530 Subject: [PATCH 029/205] feat: bisect doctype --- .../bisect_accounting_statements/__init__.py | 0 .../bisect_accounting_statements.js | 8 +++ .../bisect_accounting_statements.json | 54 +++++++++++++++++++ .../bisect_accounting_statements.py | 9 ++++ .../test_bisect_accounting_statements.py | 9 ++++ 5 files changed, 80 insertions(+) create mode 100644 erpnext/accounts/doctype/bisect_accounting_statements/__init__.py create mode 100644 erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js create mode 100644 erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json create mode 100644 erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py create mode 100644 erpnext/accounts/doctype/bisect_accounting_statements/test_bisect_accounting_statements.py diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/__init__.py b/erpnext/accounts/doctype/bisect_accounting_statements/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js new file mode 100644 index 0000000000..7e1fb48fe3 --- /dev/null +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js @@ -0,0 +1,8 @@ +// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +// frappe.ui.form.on("Bisect Accounting Statements", { +// refresh(frm) { + +// }, +// }); diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json new file mode 100644 index 0000000000..1ffa3adcb3 --- /dev/null +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json @@ -0,0 +1,54 @@ +{ + "actions": [], + "allow_rename": 1, + "creation": "2023-09-15 21:28:28.054773", + "default_view": "List", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "from", + "column_break_qxbi", + "to" + ], + "fields": [ + { + "fieldname": "from", + "fieldtype": "Date", + "label": "From" + }, + { + "fieldname": "to", + "fieldtype": "Date", + "label": "To" + }, + { + "fieldname": "column_break_qxbi", + "fieldtype": "Column Break" + } + ], + "hide_toolbar": 1, + "index_web_pages_for_search": 1, + "issingle": 1, + "links": [], + "modified": "2023-09-15 21:36:21.516679", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Bisect Accounting Statements", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py new file mode 100644 index 0000000000..8ab97b47a8 --- /dev/null +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py @@ -0,0 +1,9 @@ +# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class BisectAccountingStatements(Document): + pass diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/test_bisect_accounting_statements.py b/erpnext/accounts/doctype/bisect_accounting_statements/test_bisect_accounting_statements.py new file mode 100644 index 0000000000..56ecc94a18 --- /dev/null +++ b/erpnext/accounts/doctype/bisect_accounting_statements/test_bisect_accounting_statements.py @@ -0,0 +1,9 @@ +# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt + +# import frappe +from frappe.tests.utils import FrappeTestCase + + +class TestBisectAccountingStatements(FrappeTestCase): + pass From 4c8a8c3bcd9bf21918a78de244789c7de76cede9 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 18 Sep 2023 12:35:24 +0530 Subject: [PATCH 030/205] refactor: some logic --- .../bisect_accounting_statements.js | 22 +++++++-- .../bisect_accounting_statements.json | 48 ++++++++++++++----- .../bisect_accounting_statements.py | 17 ++++++- 3 files changed, 67 insertions(+), 20 deletions(-) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js index 7e1fb48fe3..96b9709bee 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js @@ -1,8 +1,20 @@ // Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors // For license information, please see license.txt -// frappe.ui.form.on("Bisect Accounting Statements", { -// refresh(frm) { - -// }, -// }); +frappe.ui.form.on("Bisect Accounting Statements", { + refresh(frm) { + frm.add_custom_button(__('Bisect'), () => + frm.trigger("bisect") + ); + frm.change_custom_button_type(__('Bisect'), null, 'primary'); + }, + bisect(frm) { + frm.call({ + doc: frm.doc, + method: 'bisect', + callback: (r) => { + console.log(r); + } + }); + } +}); diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json index 1ffa3adcb3..de7eba7c63 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json @@ -7,31 +7,53 @@ "editable_grid": 1, "engine": "InnoDB", "field_order": [ - "from", + "from_date", "column_break_qxbi", - "to" + "to_date", + "section_break_3x70", + "period_from", + "column_break_5ett", + "period_to" ], "fields": [ - { - "fieldname": "from", - "fieldtype": "Date", - "label": "From" - }, - { - "fieldname": "to", - "fieldtype": "Date", - "label": "To" - }, { "fieldname": "column_break_qxbi", "fieldtype": "Column Break" + }, + { + "fieldname": "from_date", + "fieldtype": "Date", + "label": "From Date" + }, + { + "fieldname": "to_date", + "fieldtype": "Date", + "label": "To Date" + }, + { + "fieldname": "section_break_3x70", + "fieldtype": "Section Break" + }, + { + "fieldname": "period_from", + "fieldtype": "Date", + "label": "Period From" + }, + { + "fieldname": "column_break_5ett", + "fieldtype": "Column Break" + }, + { + "fieldname": "period_to", + "fieldtype": "Date", + "label": "Period To" } ], "hide_toolbar": 1, "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-09-15 21:36:21.516679", + "modified": "2023-09-16 08:02:33.472406", "modified_by": "Administrator", "module": "Accounts", "name": "Bisect Accounting Statements", diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py index 8ab97b47a8..2e209d2a63 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py @@ -1,9 +1,22 @@ # Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -# import frappe +from math import ceil, floor + +import frappe +from dateutil.relativedelta import relativedelta from frappe.model.document import Document +from frappe.utils import getdate class BisectAccountingStatements(Document): - pass + @frappe.whitelist() + def bisect(self): + cur_frm_date, cur_to_date = getdate(self.from_date), getdate(self.to_date) + while True: + delta = cur_to_date - cur_frm_date + if delta.days == 0: + return + cur_floor = floor(delta.days / 2) + cur_to_date = cur_frm_date + relativedelta(days=+cur_floor) + print((cur_frm_date, cur_to_date), delta, cur_floor) From 5a25c80f2eb434313b65b1b3b08bd0ea5e393461 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 25 Sep 2023 10:35:54 +0530 Subject: [PATCH 031/205] refactor: Depth First Search(DFS) --- .../bisect_accounting_statements.py | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py index 2e209d2a63..6be28c87bc 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py @@ -1,7 +1,7 @@ # Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt -from math import ceil, floor +from math import floor import frappe from dateutil.relativedelta import relativedelta @@ -12,11 +12,18 @@ from frappe.utils import getdate class BisectAccountingStatements(Document): @frappe.whitelist() def bisect(self): - cur_frm_date, cur_to_date = getdate(self.from_date), getdate(self.to_date) - while True: + period_list = [(getdate(self.from_date), getdate(self.to_date))] + dates = [] + while period_list: + cur_frm_date, cur_to_date = period_list.pop() delta = cur_to_date - cur_frm_date - if delta.days == 0: - return + if not delta.days > 0: + continue + cur_floor = floor(delta.days / 2) - cur_to_date = cur_frm_date + relativedelta(days=+cur_floor) - print((cur_frm_date, cur_to_date), delta, cur_floor) + next_to_date = cur_frm_date + relativedelta(days=+cur_floor) + left = (cur_frm_date, next_to_date) + period_list.append(left) + next_frm_date = cur_frm_date + relativedelta(days=+(cur_floor + 1)) + right = (next_frm_date, cur_to_date) + period_list.append(right) From 26503a205f07a80f124c3dc5a59c039ed8ea708b Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 25 Sep 2023 10:39:39 +0530 Subject: [PATCH 032/205] refactor: simplify DFS --- .../bisect_accounting_statements.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py index 6be28c87bc..73a9e71960 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py @@ -21,9 +21,7 @@ class BisectAccountingStatements(Document): continue cur_floor = floor(delta.days / 2) - next_to_date = cur_frm_date + relativedelta(days=+cur_floor) - left = (cur_frm_date, next_to_date) + left = (cur_frm_date, (cur_frm_date + relativedelta(days=+cur_floor))) + right = ((cur_frm_date + relativedelta(days=+(cur_floor + 1))), cur_to_date) period_list.append(left) - next_frm_date = cur_frm_date + relativedelta(days=+(cur_floor + 1)) - right = (next_frm_date, cur_to_date) period_list.append(right) From 03a38ed0257cdee5ae1ec645877691ed1292ba9c Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 25 Sep 2023 11:05:30 +0530 Subject: [PATCH 033/205] refactor: support for BFS and DFS --- .../bisect_accounting_statements.json | 27 ++++------ .../bisect_accounting_statements.py | 50 +++++++++++++++---- 2 files changed, 50 insertions(+), 27 deletions(-) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json index de7eba7c63..b2f3c4bb90 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json @@ -10,10 +10,8 @@ "from_date", "column_break_qxbi", "to_date", - "section_break_3x70", - "period_from", - "column_break_5ett", - "period_to" + "column_break_iwny", + "algorithm" ], "fields": [ { @@ -31,29 +29,22 @@ "label": "To Date" }, { - "fieldname": "section_break_3x70", - "fieldtype": "Section Break" + "default": "BFS", + "fieldname": "algorithm", + "fieldtype": "Select", + "label": "Algorithm", + "options": "BFS\nDFS" }, { - "fieldname": "period_from", - "fieldtype": "Date", - "label": "Period From" - }, - { - "fieldname": "column_break_5ett", + "fieldname": "column_break_iwny", "fieldtype": "Column Break" - }, - { - "fieldname": "period_to", - "fieldtype": "Date", - "label": "Period To" } ], "hide_toolbar": 1, "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-09-16 08:02:33.472406", + "modified": "2023-09-25 10:50:53.887235", "modified_by": "Administrator", "module": "Accounts", "name": "Bisect Accounting Statements", diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py index 73a9e71960..bdd1809535 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py @@ -1,6 +1,7 @@ # Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt +from collections import deque from math import floor import frappe @@ -10,18 +11,49 @@ from frappe.utils import getdate class BisectAccountingStatements(Document): - @frappe.whitelist() - def bisect(self): - period_list = [(getdate(self.from_date), getdate(self.to_date))] + def bfs(self): + period_list = deque([(getdate(self.from_date), getdate(self.to_date))]) + periods = [] dates = [] + while period_list: + cur_frm_date, cur_to_date = period_list.popleft() + delta = cur_to_date - cur_frm_date + periods.append((cur_frm_date, cur_to_date, delta)) + if delta.days == 0: + continue + else: + cur_floor = floor(delta.days / 2) + left = (cur_frm_date, (cur_frm_date + relativedelta(days=+cur_floor))) + right = ((cur_frm_date + relativedelta(days=+(cur_floor + 1))), cur_to_date) + period_list.append(left) + period_list.append(right) + return periods + + def dfs(self): + period_list = [(getdate(self.from_date), getdate(self.to_date))] + periods = [] while period_list: cur_frm_date, cur_to_date = period_list.pop() delta = cur_to_date - cur_frm_date - if not delta.days > 0: + periods.append((cur_frm_date, cur_to_date, delta)) + if delta.days == 0: continue + else: + cur_floor = floor(delta.days / 2) + left = (cur_frm_date, (cur_frm_date + relativedelta(days=+cur_floor))) + right = ((cur_frm_date + relativedelta(days=+(cur_floor + 1))), cur_to_date) + period_list.append(left) + period_list.append(right) + return periods - cur_floor = floor(delta.days / 2) - left = (cur_frm_date, (cur_frm_date + relativedelta(days=+cur_floor))) - right = ((cur_frm_date + relativedelta(days=+(cur_floor + 1))), cur_to_date) - period_list.append(left) - period_list.append(right) + @frappe.whitelist() + def bisect(self): + if self.algorithm == "BFS": + periods = self.bfs() + + if self.algorithm == "DFS": + periods = self.dfs() + + print("Periods: ", len(periods)) + for x in periods: + print(x) From 2de3e6ce6d38cfc8b520365de79044d616fbd24b Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 25 Sep 2023 11:13:50 +0530 Subject: [PATCH 034/205] refactor: date validation --- .../bisect_accounting_statements.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py index bdd1809535..e032083f90 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py @@ -6,6 +6,7 @@ from math import floor import frappe from dateutil.relativedelta import relativedelta +from frappe import _ from frappe.model.document import Document from frappe.utils import getdate @@ -57,3 +58,14 @@ class BisectAccountingStatements(Document): print("Periods: ", len(periods)) for x in periods: print(x) + + def validate(self): + self.validate_dates() + + def validate_dates(self): + if getdate(self.from_date) > getdate(self.to_date): + frappe.throw( + _("From Date: {0} cannot be greater than To date: {1}").format( + frappe.bold(self.from_date), frappe.bold(self.to_date) + ) + ) From a4270291511954b0e68fc126626967f4939c7617 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 25 Sep 2023 12:16:27 +0530 Subject: [PATCH 035/205] refactor: more buttons --- .../bisect_accounting_statements.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js index 96b9709bee..69bd56e73f 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js @@ -3,10 +3,21 @@ frappe.ui.form.on("Bisect Accounting Statements", { refresh(frm) { + frm.add_custom_button(__('Bisect Left'), () => + frm.trigger("bisect_left") + ); + + frm.add_custom_button(__('Bisect Right'), () => + frm.trigger("bisect_right") + ); + + frm.add_custom_button(__('Up'), () => + frm.trigger("move_up") + ); frm.add_custom_button(__('Bisect'), () => frm.trigger("bisect") ); - frm.change_custom_button_type(__('Bisect'), null, 'primary'); + // frm.change_custom_button_type(__('Bisect'), null, 'primary'); }, bisect(frm) { frm.call({ From d53b34c0ce9f469fec79b0cbc08e4cbc47344b46 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 25 Sep 2023 12:16:47 +0530 Subject: [PATCH 036/205] refactor: introduce `node` class --- .../bisect_accounting_statements.py | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py index e032083f90..3582033abc 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py @@ -1,6 +1,7 @@ # Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors # For license information, please see license.txt +import datetime from collections import deque from math import floor @@ -11,6 +12,36 @@ from frappe.model.document import Document from frappe.utils import getdate +class Node(object): + def __init__(self): + self.parent = None + self.left_child = None + self.right_child = None + + self.current_period = None + self.difference = 0.0 + self.profit_and_loss_summary = 0.0 + self.balance_sheet_summary = 0.0 + + def update_parent(self): + pass + + def update_left_child(self): + pass + + def update_right_child(self): + pass + + def make_node( + self, + parent: int = None, + period: (datetime, datetime) = None, + left: int = None, + right: int = None, + ): + current_period = period + + class BisectAccountingStatements(Document): def bfs(self): period_list = deque([(getdate(self.from_date), getdate(self.to_date))]) From b2dde55f2ccf337e2b07aac8b62c24791c4975c9 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 25 Sep 2023 20:59:39 +0530 Subject: [PATCH 037/205] refactor: ability to build and load tree from DB --- .../bisect_accounting_statements.js | 8 +- .../bisect_accounting_statements.json | 43 +++- .../bisect_accounting_statements.py | 227 ++++++++++++------ 3 files changed, 205 insertions(+), 73 deletions(-) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js index 69bd56e73f..732b2b0f9c 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js @@ -14,15 +14,15 @@ frappe.ui.form.on("Bisect Accounting Statements", { frm.add_custom_button(__('Up'), () => frm.trigger("move_up") ); - frm.add_custom_button(__('Bisect'), () => - frm.trigger("bisect") + frm.add_custom_button(__('Build Tree'), () => + frm.trigger("build_tree") ); // frm.change_custom_button_type(__('Bisect'), null, 'primary'); }, - bisect(frm) { + build_tree(frm) { frm.call({ doc: frm.doc, - method: 'bisect', + method: 'build_tree', callback: (r) => { console.log(r); } diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json index b2f3c4bb90..e0b84adeeb 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json @@ -11,7 +11,14 @@ "column_break_qxbi", "to_date", "column_break_iwny", - "algorithm" + "algorithm", + "section_break_lwr2", + "current_from_date", + "column_break_uuic", + "current_to_date", + "section_break_zbty", + "current_node", + "tree" ], "fields": [ { @@ -38,13 +45,45 @@ { "fieldname": "column_break_iwny", "fieldtype": "Column Break" + }, + { + "fieldname": "section_break_zbty", + "fieldtype": "Section Break" + }, + { + "fieldname": "tree", + "fieldtype": "JSON", + "label": "Tree" + }, + { + "fieldname": "current_node", + "fieldtype": "JSON", + "label": "Current Node" + }, + { + "fieldname": "section_break_lwr2", + "fieldtype": "Section Break" + }, + { + "fieldname": "current_from_date", + "fieldtype": "Date", + "label": "Current From Date" + }, + { + "fieldname": "current_to_date", + "fieldtype": "Date", + "label": "Current To Date" + }, + { + "fieldname": "column_break_uuic", + "fieldtype": "Column Break" } ], "hide_toolbar": 1, "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-09-25 10:50:53.887235", + "modified": "2023-09-25 17:05:13.384320", "modified_by": "Administrator", "module": "Accounts", "name": "Bisect Accounting Statements", diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py index 3582033abc..7c68f18775 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py @@ -2,6 +2,7 @@ # For license information, please see license.txt import datetime +import json from collections import deque from math import floor @@ -10,85 +11,162 @@ from dateutil.relativedelta import relativedelta from frappe import _ from frappe.model.document import Document from frappe.utils import getdate +from frappe.utils.data import DATETIME_FORMAT, guess_date_format class Node(object): - def __init__(self): - self.parent = None - self.left_child = None - self.right_child = None - - self.current_period = None - self.difference = 0.0 - self.profit_and_loss_summary = 0.0 - self.balance_sheet_summary = 0.0 - - def update_parent(self): - pass - - def update_left_child(self): - pass - - def update_right_child(self): - pass - - def make_node( + def __init__( self, parent: int = None, period: (datetime, datetime) = None, left: int = None, right: int = None, ): - current_period = period + self.parent = parent + self.left_child = left + self.right_child = right + + self.period = period + self.difference = 0.0 + self.profit_and_loss_summary = 0.0 + self.balance_sheet_summary = 0.0 + + def as_dict(self): + return dict( + parent=self.parent, + left_child=self.left_child, + right_child=self.right_child, + period=(self.period[0].strftime(DATETIME_FORMAT), self.period[1].strftime(DATETIME_FORMAT)), + difference=self.difference, + profit_and_loss_summary=self.profit_and_loss_summary, + balance_sheet_summary=self.balance_sheet_summary, + ) + + def __repr__(self): + return f"Node (parent: {self.parent}, left_child: {self.left_child}, right_child: {self.right_child}, period: {self.period})" + + +class BTree(object): + def __init__(self): + self.btree = [] + self.current_node = None + + def as_list(self): + lst = [] + for x in self.btree: + lst.append(x.as_dict()) + return lst + + def bfs(self, from_date: datetime, to_date: datetime): + root_node = Node(parent=None, period=(getdate(from_date), getdate(to_date))) + root_node.parent = None + + # add root node to tree + self.btree.append(root_node) + cur_node = root_node + period_list = deque([root_node]) + + periods = [] + while period_list: + cur_node = period_list.popleft() + cur_node_index = len(self.btree) - 1 + + delta = cur_node.period[1] - cur_node.period[0] + if delta.days == 0: + continue + else: + cur_floor = floor(delta.days / 2) + left = (cur_node.period[0], (cur_node.period[0] + relativedelta(days=+cur_floor))) + left_node = Node(parent=cur_node_index, period=left) + self.btree.append(left_node) + cur_node.left_child = len(self.btree) - 1 + period_list.append(left_node) + + right = ((cur_node.period[0] + relativedelta(days=+(cur_floor + 1))), cur_node.period[1]) + right_node = Node(parent=cur_node_index, period=right) + self.btree.append(right_node) + cur_node.right_child = len(self.btree) - 1 + period_list.append(right_node) + + def dfs(self, from_date: datetime, to_date: datetime): + root_node = Node(parent=None, period=(getdate(from_date), getdate(to_date))) + root_node.parent = None + + # add root node to tree + self.btree.append(root_node) + cur_node = root_node + period_list = [root_node] + + periods = [] + while period_list: + cur_node = period_list.pop() + cur_node_index = len(self.btree) - 1 + + delta = cur_node.period[1] - cur_node.period[0] + if delta.days == 0: + continue + else: + cur_floor = floor(delta.days / 2) + left = (cur_node.period[0], (cur_node.period[0] + relativedelta(days=+cur_floor))) + left_node = Node(parent=cur_node_index, period=left) + self.btree.append(left_node) + cur_node.left_child = len(self.btree) - 1 + period_list.append(left_node) + + right = ((cur_node.period[0] + relativedelta(days=+(cur_floor + 1))), cur_node.period[1]) + right_node = Node(parent=cur_node_index, period=right) + self.btree.append(right_node) + cur_node.right_child = len(self.btree) - 1 + period_list.append(right_node) + + def load_tree(self, tree: list, current_node: dict): + self.btree = [] + tree = json.loads(tree) + for x in tree: + x = frappe._dict(x) + n = Node(x.parent, x.period, x.left_child, x.right_child) + n.period = x.period + n.difference = x.difference + x.profit_and_loss_summary = x.profit_and_loss_summary + x.balance_sheet_summary = x.balance_sheet_summary + self.btree.append(n) + + current_node = frappe._dict(json.loads(current_node)) + n = Node( + current_node.parent, current_node.period, current_node.left_child, current_node.right_child + ) + n.period = current_node.period + n.difference = current_node.difference + n.profit_and_loss_summary = current_node.profit_and_loss_summary + n.balance_sheet_summary = current_node.balance_sheet_summary + self.current_node = n + + def build_tree(self, from_date: datetime, to_date: datetime, alogrithm: str): + if alogrithm == "BFS": + self.bfs(from_date, to_date) + + if alogrithm == "DFS": + self.dfs(from_date, to_date) + + # set root as current node + self.current_node = self.btree[0] + + def bisec_left(self): + pass + + def bisect_right(self): + pass + + def move_up(self): + pass class BisectAccountingStatements(Document): - def bfs(self): - period_list = deque([(getdate(self.from_date), getdate(self.to_date))]) - periods = [] - dates = [] - while period_list: - cur_frm_date, cur_to_date = period_list.popleft() - delta = cur_to_date - cur_frm_date - periods.append((cur_frm_date, cur_to_date, delta)) - if delta.days == 0: - continue - else: - cur_floor = floor(delta.days / 2) - left = (cur_frm_date, (cur_frm_date + relativedelta(days=+cur_floor))) - right = ((cur_frm_date + relativedelta(days=+(cur_floor + 1))), cur_to_date) - period_list.append(left) - period_list.append(right) - return periods - - def dfs(self): - period_list = [(getdate(self.from_date), getdate(self.to_date))] - periods = [] - while period_list: - cur_frm_date, cur_to_date = period_list.pop() - delta = cur_to_date - cur_frm_date - periods.append((cur_frm_date, cur_to_date, delta)) - if delta.days == 0: - continue - else: - cur_floor = floor(delta.days / 2) - left = (cur_frm_date, (cur_frm_date + relativedelta(days=+cur_floor))) - right = ((cur_frm_date + relativedelta(days=+(cur_floor + 1))), cur_to_date) - period_list.append(left) - period_list.append(right) - return periods - - @frappe.whitelist() - def bisect(self): - if self.algorithm == "BFS": - periods = self.bfs() - - if self.algorithm == "DFS": - periods = self.dfs() - - print("Periods: ", len(periods)) - for x in periods: - print(x) + def __init__(self, *args, **kwargs): + super(BisectAccountingStatements, self).__init__(*args, **kwargs) + if self.tree and self.current_node: + self.tree_instance = BTree() + self.tree_instance.load_tree(self.tree, self.current_node) def validate(self): self.validate_dates() @@ -100,3 +178,18 @@ class BisectAccountingStatements(Document): frappe.bold(self.from_date), frappe.bold(self.to_date) ) ) + + @frappe.whitelist() + def build_tree(self): + self.tree_instance = BTree() + self.tree_instance.build_tree(self.from_date, self.to_date, self.algorithm) + print("printing tree") + for x in self.tree_instance.btree: + print(x) + + print("Root", self.tree_instnace.current_node) + + self.tree = json.dumps(self.tree_instance.as_list()) + self.current_node = json.dumps(self.tree_intance.btree[0].as_dict()) + + print(guess_date_format(json.loads(self.current_node)["period"][0])) From 705ef4f5a31aac60ac879adecbede33ffd573588 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 25 Sep 2023 21:16:18 +0530 Subject: [PATCH 038/205] refactor: add basic navigation 1. remove unnecessary columns 2. added basic tree navigation --- .../bisect_accounting_statements.js | 27 ++++++++++++ .../bisect_accounting_statements.json | 24 +---------- .../bisect_accounting_statements.py | 42 ++++++++++++++++--- 3 files changed, 65 insertions(+), 28 deletions(-) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js index 732b2b0f9c..4e478ee4ab 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js @@ -19,6 +19,33 @@ frappe.ui.form.on("Bisect Accounting Statements", { ); // frm.change_custom_button_type(__('Bisect'), null, 'primary'); }, + bisect_left(frm) { + frm.call({ + doc: frm.doc, + method: 'bisect_left', + callback: (r) => { + console.log(r); + } + }); + }, + bisect_right(frm) { + frm.call({ + doc: frm.doc, + method: 'bisect_right', + callback: (r) => { + console.log(r); + } + }); + }, + move_up(frm) { + frm.call({ + doc: frm.doc, + method: 'move_up', + callback: (r) => { + console.log(r); + } + }); + }, build_tree(frm) { frm.call({ doc: frm.doc, diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json index e0b84adeeb..c5715fe2ea 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json @@ -12,10 +12,6 @@ "to_date", "column_break_iwny", "algorithm", - "section_break_lwr2", - "current_from_date", - "column_break_uuic", - "current_to_date", "section_break_zbty", "current_node", "tree" @@ -59,31 +55,13 @@ "fieldname": "current_node", "fieldtype": "JSON", "label": "Current Node" - }, - { - "fieldname": "section_break_lwr2", - "fieldtype": "Section Break" - }, - { - "fieldname": "current_from_date", - "fieldtype": "Date", - "label": "Current From Date" - }, - { - "fieldname": "current_to_date", - "fieldtype": "Date", - "label": "Current To Date" - }, - { - "fieldname": "column_break_uuic", - "fieldtype": "Column Break" } ], "hide_toolbar": 1, "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-09-25 17:05:13.384320", + "modified": "2023-09-25 21:15:47.905386", "modified_by": "Administrator", "module": "Accounts", "name": "Bisect Accounting Statements", diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py index 7c68f18775..accc8a9b42 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py @@ -124,8 +124,12 @@ class BTree(object): tree = json.loads(tree) for x in tree: x = frappe._dict(x) - n = Node(x.parent, x.period, x.left_child, x.right_child) - n.period = x.period + n = Node(x.parent, None, x.left_child, x.right_child) + date_format = guess_date_format(x.period[0]) + n.period = ( + datetime.datetime.strptime(x.period[0], date_format), + datetime.datetime.strptime(x.period[1], date_format), + ) n.difference = x.difference x.profit_and_loss_summary = x.profit_and_loss_summary x.balance_sheet_summary = x.balance_sheet_summary @@ -187,9 +191,37 @@ class BisectAccountingStatements(Document): for x in self.tree_instance.btree: print(x) - print("Root", self.tree_instnace.current_node) + print("Root", self.tree_instance.current_node) self.tree = json.dumps(self.tree_instance.as_list()) - self.current_node = json.dumps(self.tree_intance.btree[0].as_dict()) + self.current_node = json.dumps(self.tree_instance.btree[0].as_dict()) - print(guess_date_format(json.loads(self.current_node)["period"][0])) + @frappe.whitelist() + def bisect_left(self): + if self.tree_instance.current_node is not None: + if self.tree_instance.current_node.left_child is not None: + self.current_node = self.tree_instance.btree[self.tree_instance.current_node.left_child] + self.current_node = json.dumps(self.current_node.as_dict()) + self.save() + else: + frappe.msgprint("No more children on Left") + + @frappe.whitelist() + def bisect_right(self): + if self.tree_instance.current_node is not None: + if self.tree_instance.current_node.right_child is not None: + self.current_node = self.tree_instance.btree[self.tree_instance.current_node.right_child] + self.current_node = json.dumps(self.current_node.as_dict()) + self.save() + else: + frappe.msgprint("No more children on Right") + + @frappe.whitelist() + def move_up(self): + if self.tree_instance.current_node is not None: + if self.tree_instance.current_node.parent is not None: + self.current_node = self.tree_instance.btree[self.tree_instance.current_node.parent] + self.current_node = json.dumps(self.current_node.as_dict()) + self.save() + else: + frappe.msgprint("Reached Root") From de2eba0d98409083c43affb485f4a44241e79b87 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 25 Sep 2023 22:01:07 +0530 Subject: [PATCH 039/205] chore: remove unwanted code --- .../bisect_accounting_statements.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py index accc8a9b42..950d5afab3 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py @@ -66,7 +66,6 @@ class BTree(object): cur_node = root_node period_list = deque([root_node]) - periods = [] while period_list: cur_node = period_list.popleft() cur_node_index = len(self.btree) - 1 @@ -97,7 +96,6 @@ class BTree(object): cur_node = root_node period_list = [root_node] - periods = [] while period_list: cur_node = period_list.pop() cur_node_index = len(self.btree) - 1 From 85f2a6dd545a6e55d3c4d7fe64bea39a3122598c Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 25 Sep 2023 22:06:05 +0530 Subject: [PATCH 040/205] feat: nodes doctype --- erpnext/accounts/doctype/nodes/__init__.py | 0 erpnext/accounts/doctype/nodes/nodes.js | 8 ++ erpnext/accounts/doctype/nodes/nodes.json | 89 ++++++++++++++++++++ erpnext/accounts/doctype/nodes/nodes.py | 9 ++ erpnext/accounts/doctype/nodes/test_nodes.py | 9 ++ 5 files changed, 115 insertions(+) create mode 100644 erpnext/accounts/doctype/nodes/__init__.py create mode 100644 erpnext/accounts/doctype/nodes/nodes.js create mode 100644 erpnext/accounts/doctype/nodes/nodes.json create mode 100644 erpnext/accounts/doctype/nodes/nodes.py create mode 100644 erpnext/accounts/doctype/nodes/test_nodes.py diff --git a/erpnext/accounts/doctype/nodes/__init__.py b/erpnext/accounts/doctype/nodes/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/accounts/doctype/nodes/nodes.js b/erpnext/accounts/doctype/nodes/nodes.js new file mode 100644 index 0000000000..bd74d68637 --- /dev/null +++ b/erpnext/accounts/doctype/nodes/nodes.js @@ -0,0 +1,8 @@ +// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors +// For license information, please see license.txt + +// frappe.ui.form.on("Nodes", { +// refresh(frm) { + +// }, +// }); diff --git a/erpnext/accounts/doctype/nodes/nodes.json b/erpnext/accounts/doctype/nodes/nodes.json new file mode 100644 index 0000000000..1238c8136a --- /dev/null +++ b/erpnext/accounts/doctype/nodes/nodes.json @@ -0,0 +1,89 @@ +{ + "actions": [], + "autoname": "autoincrement", + "creation": "2023-09-25 22:01:33.961832", + "default_view": "List", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "root", + "left_child", + "right_child", + "period_from_date", + "period_to_date", + "difference", + "balance_sheet_summary", + "profit_loss_summary" + ], + "fields": [ + { + "fieldname": "root", + "fieldtype": "Link", + "label": "Root", + "options": "Nodes" + }, + { + "fieldname": "left_child", + "fieldtype": "Link", + "label": "Left Child", + "options": "Nodes" + }, + { + "fieldname": "right_child", + "fieldtype": "Link", + "label": "Right Child", + "options": "Nodes" + }, + { + "fieldname": "period_from_date", + "fieldtype": "Datetime", + "label": "Period_from_date" + }, + { + "fieldname": "period_to_date", + "fieldtype": "Datetime", + "label": "Period To Date" + }, + { + "fieldname": "difference", + "fieldtype": "Float", + "label": "Difference" + }, + { + "fieldname": "balance_sheet_summary", + "fieldtype": "Float", + "label": "Balance Sheet Summary" + }, + { + "fieldname": "profit_loss_summary", + "fieldtype": "Float", + "label": "Profit and Loss Summary" + } + ], + "index_web_pages_for_search": 1, + "links": [], + "modified": "2023-09-25 22:05:49.577861", + "modified_by": "Administrator", + "module": "Accounts", + "name": "Nodes", + "naming_rule": "Autoincrement", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/erpnext/accounts/doctype/nodes/nodes.py b/erpnext/accounts/doctype/nodes/nodes.py new file mode 100644 index 0000000000..67d5d69bfe --- /dev/null +++ b/erpnext/accounts/doctype/nodes/nodes.py @@ -0,0 +1,9 @@ +# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + + +class Nodes(Document): + pass diff --git a/erpnext/accounts/doctype/nodes/test_nodes.py b/erpnext/accounts/doctype/nodes/test_nodes.py new file mode 100644 index 0000000000..feeef765e0 --- /dev/null +++ b/erpnext/accounts/doctype/nodes/test_nodes.py @@ -0,0 +1,9 @@ +# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors +# See license.txt + +# import frappe +from frappe.tests.utils import FrappeTestCase + + +class TestNodes(FrappeTestCase): + pass From 9d2025636689cf0c6f44f9784537d9eb132b820c Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 26 Sep 2023 08:43:59 +0530 Subject: [PATCH 041/205] chore: use doctype as btree --- .../bisect_accounting_statements.py | 51 +++++++++++++------ 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py index 950d5afab3..53319b3c58 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py @@ -58,33 +58,51 @@ class BTree(object): return lst def bfs(self, from_date: datetime, to_date: datetime): - root_node = Node(parent=None, period=(getdate(from_date), getdate(to_date))) - root_node.parent = None + node = frappe.new_doc("Nodes") + node.period_from_date = from_date + node.period_to_date = to_date + node.root = None + node.insert() - # add root node to tree - self.btree.append(root_node) - cur_node = root_node - period_list = deque([root_node]) + period_list = deque([node]) while period_list: cur_node = period_list.popleft() - cur_node_index = len(self.btree) - 1 - delta = cur_node.period[1] - cur_node.period[0] + print(cur_node.as_dict()) + delta = cur_node.period_to_date - cur_node.period_from_date if delta.days == 0: continue else: cur_floor = floor(delta.days / 2) - left = (cur_node.period[0], (cur_node.period[0] + relativedelta(days=+cur_floor))) - left_node = Node(parent=cur_node_index, period=left) - self.btree.append(left_node) - cur_node.left_child = len(self.btree) - 1 + left = ( + cur_node.period_from_date, + (cur_node.period_from_date + relativedelta(days=+cur_floor)), + ) + left_node = frappe.get_doc( + { + "doctype": "Nodes", + "period_from_date": cur_node.period_from_date, + "period_to_date": left, + "root": cur_node.name, + } + ).insert() + cur_node.left_child = left_node.name period_list.append(left_node) - right = ((cur_node.period[0] + relativedelta(days=+(cur_floor + 1))), cur_node.period[1]) - right_node = Node(parent=cur_node_index, period=right) - self.btree.append(right_node) - cur_node.right_child = len(self.btree) - 1 + right = ( + (cur_node.period_from_date + relativedelta(days=+(cur_floor + 1))), + cur_node.period_to_date, + ) + right_node = frappe.get_doc( + { + "doctype": "Nodes", + "period_from_date": right, + "period_to_date": cur_node.period_to_date, + "root": cur_node.name, + } + ).insert() + cur_node.right_child = right_node period_list.append(right_node) def dfs(self, from_date: datetime, to_date: datetime): @@ -144,6 +162,7 @@ class BTree(object): self.current_node = n def build_tree(self, from_date: datetime, to_date: datetime, alogrithm: str): + frappe.db.delete("Nodes") if alogrithm == "BFS": self.bfs(from_date, to_date) From 99fbd8ad186c989faa86863d5902a3b4d2015505 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 26 Sep 2023 12:28:38 +0530 Subject: [PATCH 042/205] refactor: use DB to store tree and state --- .../bisect_accounting_statements.json | 19 +- .../bisect_accounting_statements.py | 304 +++++++----------- 2 files changed, 115 insertions(+), 208 deletions(-) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json index c5715fe2ea..0de820a80f 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json @@ -13,8 +13,7 @@ "column_break_iwny", "algorithm", "section_break_zbty", - "current_node", - "tree" + "current_node" ], "fields": [ { @@ -23,12 +22,12 @@ }, { "fieldname": "from_date", - "fieldtype": "Date", + "fieldtype": "Datetime", "label": "From Date" }, { "fieldname": "to_date", - "fieldtype": "Date", + "fieldtype": "Datetime", "label": "To Date" }, { @@ -46,22 +45,18 @@ "fieldname": "section_break_zbty", "fieldtype": "Section Break" }, - { - "fieldname": "tree", - "fieldtype": "JSON", - "label": "Tree" - }, { "fieldname": "current_node", - "fieldtype": "JSON", - "label": "Current Node" + "fieldtype": "Link", + "label": "Current Node", + "options": "Nodes" } ], "hide_toolbar": 1, "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-09-25 21:15:47.905386", + "modified": "2023-09-26 12:09:23.649156", "modified_by": "Administrator", "module": "Accounts", "name": "Bisect Accounting Statements", diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py index 53319b3c58..8730772e29 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py @@ -2,7 +2,6 @@ # For license information, please see license.txt import datetime -import json from collections import deque from math import floor @@ -11,184 +10,10 @@ from dateutil.relativedelta import relativedelta from frappe import _ from frappe.model.document import Document from frappe.utils import getdate -from frappe.utils.data import DATETIME_FORMAT, guess_date_format - - -class Node(object): - def __init__( - self, - parent: int = None, - period: (datetime, datetime) = None, - left: int = None, - right: int = None, - ): - self.parent = parent - self.left_child = left - self.right_child = right - - self.period = period - self.difference = 0.0 - self.profit_and_loss_summary = 0.0 - self.balance_sheet_summary = 0.0 - - def as_dict(self): - return dict( - parent=self.parent, - left_child=self.left_child, - right_child=self.right_child, - period=(self.period[0].strftime(DATETIME_FORMAT), self.period[1].strftime(DATETIME_FORMAT)), - difference=self.difference, - profit_and_loss_summary=self.profit_and_loss_summary, - balance_sheet_summary=self.balance_sheet_summary, - ) - - def __repr__(self): - return f"Node (parent: {self.parent}, left_child: {self.left_child}, right_child: {self.right_child}, period: {self.period})" - - -class BTree(object): - def __init__(self): - self.btree = [] - self.current_node = None - - def as_list(self): - lst = [] - for x in self.btree: - lst.append(x.as_dict()) - return lst - - def bfs(self, from_date: datetime, to_date: datetime): - node = frappe.new_doc("Nodes") - node.period_from_date = from_date - node.period_to_date = to_date - node.root = None - node.insert() - - period_list = deque([node]) - - while period_list: - cur_node = period_list.popleft() - - print(cur_node.as_dict()) - delta = cur_node.period_to_date - cur_node.period_from_date - if delta.days == 0: - continue - else: - cur_floor = floor(delta.days / 2) - left = ( - cur_node.period_from_date, - (cur_node.period_from_date + relativedelta(days=+cur_floor)), - ) - left_node = frappe.get_doc( - { - "doctype": "Nodes", - "period_from_date": cur_node.period_from_date, - "period_to_date": left, - "root": cur_node.name, - } - ).insert() - cur_node.left_child = left_node.name - period_list.append(left_node) - - right = ( - (cur_node.period_from_date + relativedelta(days=+(cur_floor + 1))), - cur_node.period_to_date, - ) - right_node = frappe.get_doc( - { - "doctype": "Nodes", - "period_from_date": right, - "period_to_date": cur_node.period_to_date, - "root": cur_node.name, - } - ).insert() - cur_node.right_child = right_node - period_list.append(right_node) - - def dfs(self, from_date: datetime, to_date: datetime): - root_node = Node(parent=None, period=(getdate(from_date), getdate(to_date))) - root_node.parent = None - - # add root node to tree - self.btree.append(root_node) - cur_node = root_node - period_list = [root_node] - - while period_list: - cur_node = period_list.pop() - cur_node_index = len(self.btree) - 1 - - delta = cur_node.period[1] - cur_node.period[0] - if delta.days == 0: - continue - else: - cur_floor = floor(delta.days / 2) - left = (cur_node.period[0], (cur_node.period[0] + relativedelta(days=+cur_floor))) - left_node = Node(parent=cur_node_index, period=left) - self.btree.append(left_node) - cur_node.left_child = len(self.btree) - 1 - period_list.append(left_node) - - right = ((cur_node.period[0] + relativedelta(days=+(cur_floor + 1))), cur_node.period[1]) - right_node = Node(parent=cur_node_index, period=right) - self.btree.append(right_node) - cur_node.right_child = len(self.btree) - 1 - period_list.append(right_node) - - def load_tree(self, tree: list, current_node: dict): - self.btree = [] - tree = json.loads(tree) - for x in tree: - x = frappe._dict(x) - n = Node(x.parent, None, x.left_child, x.right_child) - date_format = guess_date_format(x.period[0]) - n.period = ( - datetime.datetime.strptime(x.period[0], date_format), - datetime.datetime.strptime(x.period[1], date_format), - ) - n.difference = x.difference - x.profit_and_loss_summary = x.profit_and_loss_summary - x.balance_sheet_summary = x.balance_sheet_summary - self.btree.append(n) - - current_node = frappe._dict(json.loads(current_node)) - n = Node( - current_node.parent, current_node.period, current_node.left_child, current_node.right_child - ) - n.period = current_node.period - n.difference = current_node.difference - n.profit_and_loss_summary = current_node.profit_and_loss_summary - n.balance_sheet_summary = current_node.balance_sheet_summary - self.current_node = n - - def build_tree(self, from_date: datetime, to_date: datetime, alogrithm: str): - frappe.db.delete("Nodes") - if alogrithm == "BFS": - self.bfs(from_date, to_date) - - if alogrithm == "DFS": - self.dfs(from_date, to_date) - - # set root as current node - self.current_node = self.btree[0] - - def bisec_left(self): - pass - - def bisect_right(self): - pass - - def move_up(self): - pass +from frappe.utils.data import guess_date_format class BisectAccountingStatements(Document): - def __init__(self, *args, **kwargs): - super(BisectAccountingStatements, self).__init__(*args, **kwargs) - if self.tree and self.current_node: - self.tree_instance = BTree() - self.tree_instance.load_tree(self.tree, self.current_node) - def validate(self): self.validate_dates() @@ -200,45 +25,132 @@ class BisectAccountingStatements(Document): ) ) + def bfs(self, from_date: datetime, to_date: datetime): + # Make Root node + node = frappe.new_doc("Nodes") + node.root = None + node.period_from_date = from_date + node.period_to_date = to_date + node.insert() + + period_queue = deque([node]) + while period_queue: + cur_node = period_queue.popleft() + delta = cur_node.period_to_date - cur_node.period_from_date + if delta.days == 0: + continue + else: + cur_floor = floor(delta.days / 2) + next_to_date = cur_node.period_from_date + relativedelta(days=+cur_floor) + left_node = frappe.new_doc("Nodes") + left_node.period_from_date = cur_node.period_from_date + left_node.period_to_date = next_to_date + left_node.root = cur_node.name + left_node.insert() + cur_node.left_child = left_node.name + period_queue.append(left_node) + + next_from_date = cur_node.period_from_date + relativedelta(days=+(cur_floor + 1)) + right_node = frappe.new_doc("Nodes") + right_node.period_from_date = next_from_date + right_node.period_to_date = cur_node.period_to_date + right_node.root = cur_node.name + right_node.insert() + cur_node.right_child = right_node.name + period_queue.append(right_node) + + cur_node.save() + + def dfs(self, from_date: datetime, to_date: datetime): + # Make Root node + node = frappe.new_doc("Nodes") + node.root = None + node.period_from_date = from_date + node.period_to_date = to_date + node.insert() + + period_stack = [node] + while period_stack: + cur_node = period_stack.pop() + delta = cur_node.period_to_date - cur_node.period_from_date + if delta.days == 0: + continue + else: + cur_floor = floor(delta.days / 2) + next_to_date = cur_node.period_from_date + relativedelta(days=+cur_floor) + left_node = frappe.new_doc("Nodes") + left_node.period_from_date = cur_node.period_from_date + left_node.period_to_date = next_to_date + left_node.root = cur_node.name + left_node.insert() + cur_node.left_child = left_node.name + period_stack.append(left_node) + + next_from_date = cur_node.period_from_date + relativedelta(days=+(cur_floor + 1)) + right_node = frappe.new_doc("Nodes") + right_node.period_from_date = next_from_date + right_node.period_to_date = cur_node.period_to_date + right_node.root = cur_node.name + right_node.insert() + cur_node.right_child = right_node.name + period_stack.append(right_node) + + cur_node.save() + @frappe.whitelist() def build_tree(self): - self.tree_instance = BTree() - self.tree_instance.build_tree(self.from_date, self.to_date, self.algorithm) - print("printing tree") - for x in self.tree_instance.btree: - print(x) + frappe.db.delete("Nodes") - print("Root", self.tree_instance.current_node) + # Convert str to datetime format + dt_format = guess_date_format(self.from_date) + from_date = datetime.datetime.strptime(self.from_date, dt_format) + to_date = datetime.datetime.strptime(self.to_date, dt_format) - self.tree = json.dumps(self.tree_instance.as_list()) - self.current_node = json.dumps(self.tree_instance.btree[0].as_dict()) + if self.algorithm == "BFS": + self.bfs(from_date, to_date) + + if self.algorithm == "DFS": + self.dfs(from_date, to_date) + + # set root as current node + root = frappe.db.get_all("Nodes", filters={"root": ["is", "not set"]})[0] + frappe.db.set_single_value("Bisect Accounting Statements", "current_node", root.name) @frappe.whitelist() def bisect_left(self): - if self.tree_instance.current_node is not None: - if self.tree_instance.current_node.left_child is not None: - self.current_node = self.tree_instance.btree[self.tree_instance.current_node.left_child] - self.current_node = json.dumps(self.current_node.as_dict()) + if self.current_node is not None: + cur_node = frappe.get_doc("Nodes", self.current_node) + if cur_node.left_child is not None: + lft_node = frappe.get_doc("Nodes", cur_node.left_child) + self.current_node = cur_node.left_child + self.from_date = lft_node.period_from_date + self.to_date = lft_node.period_to_date self.save() else: frappe.msgprint("No more children on Left") @frappe.whitelist() def bisect_right(self): - if self.tree_instance.current_node is not None: - if self.tree_instance.current_node.right_child is not None: - self.current_node = self.tree_instance.btree[self.tree_instance.current_node.right_child] - self.current_node = json.dumps(self.current_node.as_dict()) + if self.current_node is not None: + cur_node = frappe.get_doc("Nodes", self.current_node) + if cur_node.right_child is not None: + rgt_node = frappe.get_doc("Nodes", cur_node.right_child) + self.current_node = cur_node.right_child + self.from_date = rgt_node.period_from_date + self.to_date = rgt_node.period_to_date self.save() else: frappe.msgprint("No more children on Right") @frappe.whitelist() def move_up(self): - if self.tree_instance.current_node is not None: - if self.tree_instance.current_node.parent is not None: - self.current_node = self.tree_instance.btree[self.tree_instance.current_node.parent] - self.current_node = json.dumps(self.current_node.as_dict()) + if self.current_node is not None: + cur_node = frappe.get_doc("Nodes", self.current_node) + if cur_node.root is not None: + root = frappe.get_doc("Nodes", cur_node.root) + self.current_node = cur_node.root + self.from_date = root.period_from_date + self.to_date = root.period_to_date self.save() else: frappe.msgprint("Reached Root") From f7b7b2b438c3c5496097de1a740d6d4ede09605b Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 26 Sep 2023 20:33:13 +0530 Subject: [PATCH 043/205] refactor: calculate summary on tree navigation --- .../bisect_accounting_statements.js | 3 +- .../bisect_accounting_statements.json | 77 ++++++++++++++++++- .../bisect_accounting_statements.py | 29 +++++-- 3 files changed, 99 insertions(+), 10 deletions(-) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js index 4e478ee4ab..7abe4f87ae 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js @@ -17,7 +17,6 @@ frappe.ui.form.on("Bisect Accounting Statements", { frm.add_custom_button(__('Build Tree'), () => frm.trigger("build_tree") ); - // frm.change_custom_button_type(__('Bisect'), null, 'primary'); }, bisect_left(frm) { frm.call({ @@ -54,5 +53,5 @@ frappe.ui.form.on("Bisect Accounting Statements", { console.log(r); } }); - } + }, }); diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json index 0de820a80f..c76ef4d06f 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json @@ -7,13 +7,26 @@ "editable_grid": 1, "engine": "InnoDB", "field_order": [ + "company", + "column_break_hcam", "from_date", "column_break_qxbi", "to_date", "column_break_iwny", "algorithm", "section_break_zbty", - "current_node" + "current_node", + "sandbox", + "section_break_hmsy", + "current_from_date", + "column_break_uqyd", + "current_to_date", + "section_break_hbyo", + "p_l_summary", + "column_break_aivo", + "b_s_summary", + "column_break_gvwx", + "difference" ], "fields": [ { @@ -50,13 +63,73 @@ "fieldtype": "Link", "label": "Current Node", "options": "Nodes" + }, + { + "fieldname": "sandbox", + "fieldtype": "HTML", + "label": "sandbox" + }, + { + "fieldname": "section_break_hmsy", + "fieldtype": "Section Break" + }, + { + "fieldname": "current_from_date", + "fieldtype": "Datetime", + "label": "Current From Date" + }, + { + "fieldname": "current_to_date", + "fieldtype": "Datetime", + "label": "Current To Date" + }, + { + "fieldname": "column_break_uqyd", + "fieldtype": "Column Break" + }, + { + "fieldname": "section_break_hbyo", + "fieldtype": "Section Break" + }, + { + "fieldname": "p_l_summary", + "fieldtype": "Data", + "label": "P&L Summary" + }, + { + "fieldname": "b_s_summary", + "fieldtype": "Data", + "label": "Balance Sheet Summary" + }, + { + "fieldname": "difference", + "fieldtype": "Data", + "label": "Difference" + }, + { + "fieldname": "column_break_aivo", + "fieldtype": "Column Break" + }, + { + "fieldname": "column_break_gvwx", + "fieldtype": "Column Break" + }, + { + "fieldname": "company", + "fieldtype": "Link", + "label": "Company", + "options": "Company" + }, + { + "fieldname": "column_break_hcam", + "fieldtype": "Column Break" } ], "hide_toolbar": 1, "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-09-26 12:09:23.649156", + "modified": "2023-09-26 21:07:14.290963", "modified_by": "Administrator", "module": "Accounts", "name": "Bisect Accounting Statements", diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py index 8730772e29..d2b60a4225 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py @@ -116,6 +116,20 @@ class BisectAccountingStatements(Document): root = frappe.db.get_all("Nodes", filters={"root": ["is", "not set"]})[0] frappe.db.set_single_value("Bisect Accounting Statements", "current_node", root.name) + def get_report_summary(self): + filters = { + "company": self.company, + "filter_based_on": "Date Range", + "period_start_date": self.current_from_date, + "period_end_date": self.current_to_date, + "periodicity": "Yearly", + } + pl_summary = frappe.get_doc("Report", "Profit and Loss Statement") + self.p_l_summary = pl_summary.execute_script_report(filters=filters)[5] + bs_summary = frappe.get_doc("Report", "Balance Sheet") + self.b_s_summary = bs_summary.execute_script_report(filters=filters)[5] + self.difference = abs(self.p_l_summary - self.b_s_summary) + @frappe.whitelist() def bisect_left(self): if self.current_node is not None: @@ -123,8 +137,9 @@ class BisectAccountingStatements(Document): if cur_node.left_child is not None: lft_node = frappe.get_doc("Nodes", cur_node.left_child) self.current_node = cur_node.left_child - self.from_date = lft_node.period_from_date - self.to_date = lft_node.period_to_date + self.current_from_date = lft_node.period_from_date + self.current_to_date = lft_node.period_to_date + self.get_report_summary() self.save() else: frappe.msgprint("No more children on Left") @@ -136,8 +151,9 @@ class BisectAccountingStatements(Document): if cur_node.right_child is not None: rgt_node = frappe.get_doc("Nodes", cur_node.right_child) self.current_node = cur_node.right_child - self.from_date = rgt_node.period_from_date - self.to_date = rgt_node.period_to_date + self.current_from_date = rgt_node.period_from_date + self.current_to_date = rgt_node.period_to_date + self.get_report_summary() self.save() else: frappe.msgprint("No more children on Right") @@ -149,8 +165,9 @@ class BisectAccountingStatements(Document): if cur_node.root is not None: root = frappe.get_doc("Nodes", cur_node.root) self.current_node = cur_node.root - self.from_date = root.period_from_date - self.to_date = root.period_to_date + self.current_from_date = root.period_from_date + self.current_to_date = root.period_to_date + self.get_report_summary() self.save() else: frappe.msgprint("Reached Root") From bd3dc6482e9621132a64fecc7e2f203b64812068 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 26 Sep 2023 21:29:54 +0530 Subject: [PATCH 044/205] chore: hide some internal fields --- .../bisect_accounting_statements.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json index c76ef4d06f..d413f70c15 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json @@ -61,12 +61,14 @@ { "fieldname": "current_node", "fieldtype": "Link", + "hidden": 1, "label": "Current Node", "options": "Nodes" }, { "fieldname": "sandbox", "fieldtype": "HTML", + "hidden": 1, "label": "sandbox" }, { @@ -129,7 +131,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-09-26 21:07:14.290963", + "modified": "2023-09-26 21:25:48.779453", "modified_by": "Administrator", "module": "Accounts", "name": "Bisect Accounting Statements", From 16db6c2f47ec7b803c765d9e04c5f50c4bd6b95f Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 27 Sep 2023 09:35:25 +0530 Subject: [PATCH 045/205] refactor: working heatmap --- .../bisect_accounting_statements.js | 58 +++++++++++++++---- .../bisect_accounting_statements.json | 30 +++++----- 2 files changed, 63 insertions(+), 25 deletions(-) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js index 7abe4f87ae..1c1e3cc6ca 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js @@ -2,27 +2,58 @@ // For license information, please see license.txt frappe.ui.form.on("Bisect Accounting Statements", { + onload(frm) { + frm.trigger("render_heatmap"); + }, refresh(frm) { - frm.add_custom_button(__('Bisect Left'), () => - frm.trigger("bisect_left") - ); + frm.add_custom_button(__('Bisect Left'), () => { + frm.trigger("bisect_left"); + }); - frm.add_custom_button(__('Bisect Right'), () => - frm.trigger("bisect_right") - ); + frm.add_custom_button(__('Bisect Right'), () => { + frm.trigger("bisect_right"); + }); - frm.add_custom_button(__('Up'), () => - frm.trigger("move_up") - ); - frm.add_custom_button(__('Build Tree'), () => - frm.trigger("build_tree") - ); + frm.add_custom_button(__('Up'), () => { + frm.trigger("move_up"); + }); + frm.add_custom_button(__('Build Tree'), () => { + frm.trigger("build_tree"); + }); + }, + render_heatmap(frm) { + let bisect_heatmap = frm.get_field("bisect_heatmap").$wrapper; + bisect_heatmap.addClass("bisect_heatmap_location"); + + // milliseconds in a day + let msiad=24*60*60*1000; + let datapoints = {}; + let fr_dt = new Date(frm.doc.current_from_date).getTime(); + let to_dt = new Date(frm.doc.current_to_date).getTime(); + for(let x=fr_dt; x <= to_dt; x+=msiad){ + let epoch_in_seconds = x/1000; + datapoints[epoch_in_seconds] = 1; + } + console.log(datapoints); + + new frappe.Chart(".bisect_heatmap_location", { + type: "heatmap", + title: "Bisecting On", + data: { + dataPoints: datapoints, + start: new Date(frm.doc.from_date), + end: new Date(frm.doc.to_date), + }, + countLabel: 'Difference', + discreteDomains: 1 + }); }, bisect_left(frm) { frm.call({ doc: frm.doc, method: 'bisect_left', callback: (r) => { + frm.trigger("render_heatmap"); console.log(r); } }); @@ -32,6 +63,7 @@ frappe.ui.form.on("Bisect Accounting Statements", { doc: frm.doc, method: 'bisect_right', callback: (r) => { + frm.trigger("render_heatmap"); console.log(r); } }); @@ -41,6 +73,7 @@ frappe.ui.form.on("Bisect Accounting Statements", { doc: frm.doc, method: 'move_up', callback: (r) => { + frm.trigger("render_heatmap"); console.log(r); } }); @@ -50,6 +83,7 @@ frappe.ui.form.on("Bisect Accounting Statements", { doc: frm.doc, method: 'build_tree', callback: (r) => { + frm.trigger("render_heatmap"); console.log(r); } }); diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json index d413f70c15..9a7242fe92 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json @@ -14,13 +14,14 @@ "to_date", "column_break_iwny", "algorithm", - "section_break_zbty", + "section_break_8ph9", "current_node", - "sandbox", "section_break_hmsy", "current_from_date", "column_break_uqyd", "current_to_date", + "section_break_ngid", + "bisect_heatmap", "section_break_hbyo", "p_l_summary", "column_break_aivo", @@ -54,10 +55,6 @@ "fieldname": "column_break_iwny", "fieldtype": "Column Break" }, - { - "fieldname": "section_break_zbty", - "fieldtype": "Section Break" - }, { "fieldname": "current_node", "fieldtype": "Link", @@ -65,12 +62,6 @@ "label": "Current Node", "options": "Nodes" }, - { - "fieldname": "sandbox", - "fieldtype": "HTML", - "hidden": 1, - "label": "sandbox" - }, { "fieldname": "section_break_hmsy", "fieldtype": "Section Break" @@ -125,13 +116,26 @@ { "fieldname": "column_break_hcam", "fieldtype": "Column Break" + }, + { + "fieldname": "section_break_ngid", + "fieldtype": "Section Break" + }, + { + "fieldname": "section_break_8ph9", + "fieldtype": "Section Break" + }, + { + "fieldname": "bisect_heatmap", + "fieldtype": "HTML", + "label": "Heatmap" } ], "hide_toolbar": 1, "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-09-26 21:25:48.779453", + "modified": "2023-09-27 12:10:40.044935", "modified_by": "Administrator", "module": "Accounts", "name": "Bisect Accounting Statements", From f6831fba1370e569299c63f592fcd2a09a1dbc76 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 27 Sep 2023 14:40:57 +0530 Subject: [PATCH 046/205] chore: hide internal fields and better painting logic for heatmap --- .../bisect_accounting_statements.js | 15 ++++++++---- .../bisect_accounting_statements.json | 24 ++++++++++++------- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js index 1c1e3cc6ca..c00e49d380 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js @@ -28,11 +28,18 @@ frappe.ui.form.on("Bisect Accounting Statements", { // milliseconds in a day let msiad=24*60*60*1000; let datapoints = {}; - let fr_dt = new Date(frm.doc.current_from_date).getTime(); - let to_dt = new Date(frm.doc.current_to_date).getTime(); + let fr_dt = new Date(frm.doc.from_date).getTime(); + let to_dt = new Date(frm.doc.to_date).getTime(); + let bisect_start = new Date(frm.doc.current_from_date).getTime(); + let bisect_end = new Date(frm.doc.current_to_date).getTime(); + for(let x=fr_dt; x <= to_dt; x+=msiad){ let epoch_in_seconds = x/1000; - datapoints[epoch_in_seconds] = 1; + if ((bisect_start <= x) && (x <= bisect_end )) { + datapoints[epoch_in_seconds] = 1.0; + } else { + datapoints[epoch_in_seconds] = 0.0; + } } console.log(datapoints); @@ -45,7 +52,7 @@ frappe.ui.form.on("Bisect Accounting Statements", { end: new Date(frm.doc.to_date), }, countLabel: 'Difference', - discreteDomains: 1 + discreteDomains: 1, }); }, bisect_left(frm) { diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json index 9a7242fe92..84d021d7da 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json @@ -58,23 +58,25 @@ { "fieldname": "current_node", "fieldtype": "Link", - "hidden": 1, "label": "Current Node", "options": "Nodes" }, { "fieldname": "section_break_hmsy", - "fieldtype": "Section Break" + "fieldtype": "Section Break", + "hidden": 1 }, { "fieldname": "current_from_date", "fieldtype": "Datetime", - "label": "Current From Date" + "label": "Current From Date", + "read_only": 1 }, { "fieldname": "current_to_date", "fieldtype": "Datetime", - "label": "Current To Date" + "label": "Current To Date", + "read_only": 1 }, { "fieldname": "column_break_uqyd", @@ -87,17 +89,20 @@ { "fieldname": "p_l_summary", "fieldtype": "Data", - "label": "P&L Summary" + "label": "P&L Summary", + "read_only": 1 }, { "fieldname": "b_s_summary", "fieldtype": "Data", - "label": "Balance Sheet Summary" + "label": "Balance Sheet Summary", + "read_only": 1 }, { "fieldname": "difference", "fieldtype": "Data", - "label": "Difference" + "label": "Difference", + "read_only": 1 }, { "fieldname": "column_break_aivo", @@ -123,7 +128,8 @@ }, { "fieldname": "section_break_8ph9", - "fieldtype": "Section Break" + "fieldtype": "Section Break", + "hidden": 1 }, { "fieldname": "bisect_heatmap", @@ -135,7 +141,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-09-27 12:10:40.044935", + "modified": "2023-09-27 14:32:09.962067", "modified_by": "Administrator", "module": "Accounts", "name": "Bisect Accounting Statements", From 6492019383a56669869457d3b6b8cdb2083f7df7 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 27 Sep 2023 14:44:48 +0530 Subject: [PATCH 047/205] chore: rename btree and remove debugging statements --- .../bisect_accounting_statements.js | 5 ---- .../bisect_accounting_statements.json | 7 ++--- .../bisect_accounting_statements.py | 28 +++++++++---------- .../{nodes => bisect_nodes}/__init__.py | 0 .../nodes.js => bisect_nodes/bisect_nodes.js} | 2 +- .../bisect_nodes.json} | 12 ++++---- .../nodes.py => bisect_nodes/bisect_nodes.py} | 2 +- .../test_bisect_nodes.py} | 2 +- 8 files changed, 26 insertions(+), 32 deletions(-) rename erpnext/accounts/doctype/{nodes => bisect_nodes}/__init__.py (100%) rename erpnext/accounts/doctype/{nodes/nodes.js => bisect_nodes/bisect_nodes.js} (80%) rename erpnext/accounts/doctype/{nodes/nodes.json => bisect_nodes/bisect_nodes.json} (88%) rename erpnext/accounts/doctype/{nodes/nodes.py => bisect_nodes/bisect_nodes.py} (86%) rename erpnext/accounts/doctype/{nodes/test_nodes.py => bisect_nodes/test_bisect_nodes.py} (80%) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js index c00e49d380..e9fc330a70 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js @@ -41,7 +41,6 @@ frappe.ui.form.on("Bisect Accounting Statements", { datapoints[epoch_in_seconds] = 0.0; } } - console.log(datapoints); new frappe.Chart(".bisect_heatmap_location", { type: "heatmap", @@ -61,7 +60,6 @@ frappe.ui.form.on("Bisect Accounting Statements", { method: 'bisect_left', callback: (r) => { frm.trigger("render_heatmap"); - console.log(r); } }); }, @@ -71,7 +69,6 @@ frappe.ui.form.on("Bisect Accounting Statements", { method: 'bisect_right', callback: (r) => { frm.trigger("render_heatmap"); - console.log(r); } }); }, @@ -81,7 +78,6 @@ frappe.ui.form.on("Bisect Accounting Statements", { method: 'move_up', callback: (r) => { frm.trigger("render_heatmap"); - console.log(r); } }); }, @@ -91,7 +87,6 @@ frappe.ui.form.on("Bisect Accounting Statements", { method: 'build_tree', callback: (r) => { frm.trigger("render_heatmap"); - console.log(r); } }); }, diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json index 84d021d7da..f62d39377e 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json @@ -59,7 +59,7 @@ "fieldname": "current_node", "fieldtype": "Link", "label": "Current Node", - "options": "Nodes" + "options": "Bisect Nodes" }, { "fieldname": "section_break_hmsy", @@ -128,8 +128,7 @@ }, { "fieldname": "section_break_8ph9", - "fieldtype": "Section Break", - "hidden": 1 + "fieldtype": "Section Break" }, { "fieldname": "bisect_heatmap", @@ -141,7 +140,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-09-27 14:32:09.962067", + "modified": "2023-09-27 15:05:44.285832", "modified_by": "Administrator", "module": "Accounts", "name": "Bisect Accounting Statements", diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py index d2b60a4225..58b8748628 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py @@ -27,7 +27,7 @@ class BisectAccountingStatements(Document): def bfs(self, from_date: datetime, to_date: datetime): # Make Root node - node = frappe.new_doc("Nodes") + node = frappe.new_doc("Bisect Nodes") node.root = None node.period_from_date = from_date node.period_to_date = to_date @@ -42,7 +42,7 @@ class BisectAccountingStatements(Document): else: cur_floor = floor(delta.days / 2) next_to_date = cur_node.period_from_date + relativedelta(days=+cur_floor) - left_node = frappe.new_doc("Nodes") + left_node = frappe.new_doc("Bisect Nodes") left_node.period_from_date = cur_node.period_from_date left_node.period_to_date = next_to_date left_node.root = cur_node.name @@ -51,7 +51,7 @@ class BisectAccountingStatements(Document): period_queue.append(left_node) next_from_date = cur_node.period_from_date + relativedelta(days=+(cur_floor + 1)) - right_node = frappe.new_doc("Nodes") + right_node = frappe.new_doc("Bisect Nodes") right_node.period_from_date = next_from_date right_node.period_to_date = cur_node.period_to_date right_node.root = cur_node.name @@ -63,7 +63,7 @@ class BisectAccountingStatements(Document): def dfs(self, from_date: datetime, to_date: datetime): # Make Root node - node = frappe.new_doc("Nodes") + node = frappe.new_doc("Bisect Nodes") node.root = None node.period_from_date = from_date node.period_to_date = to_date @@ -78,7 +78,7 @@ class BisectAccountingStatements(Document): else: cur_floor = floor(delta.days / 2) next_to_date = cur_node.period_from_date + relativedelta(days=+cur_floor) - left_node = frappe.new_doc("Nodes") + left_node = frappe.new_doc("Bisect Nodes") left_node.period_from_date = cur_node.period_from_date left_node.period_to_date = next_to_date left_node.root = cur_node.name @@ -87,7 +87,7 @@ class BisectAccountingStatements(Document): period_stack.append(left_node) next_from_date = cur_node.period_from_date + relativedelta(days=+(cur_floor + 1)) - right_node = frappe.new_doc("Nodes") + right_node = frappe.new_doc("Bisect Nodes") right_node.period_from_date = next_from_date right_node.period_to_date = cur_node.period_to_date right_node.root = cur_node.name @@ -99,7 +99,7 @@ class BisectAccountingStatements(Document): @frappe.whitelist() def build_tree(self): - frappe.db.delete("Nodes") + frappe.db.delete("Bisect Nodes") # Convert str to datetime format dt_format = guess_date_format(self.from_date) @@ -113,7 +113,7 @@ class BisectAccountingStatements(Document): self.dfs(from_date, to_date) # set root as current node - root = frappe.db.get_all("Nodes", filters={"root": ["is", "not set"]})[0] + root = frappe.db.get_all("Bisect Nodes", filters={"root": ["is", "not set"]})[0] frappe.db.set_single_value("Bisect Accounting Statements", "current_node", root.name) def get_report_summary(self): @@ -133,9 +133,9 @@ class BisectAccountingStatements(Document): @frappe.whitelist() def bisect_left(self): if self.current_node is not None: - cur_node = frappe.get_doc("Nodes", self.current_node) + cur_node = frappe.get_doc("Bisect Nodes", self.current_node) if cur_node.left_child is not None: - lft_node = frappe.get_doc("Nodes", cur_node.left_child) + lft_node = frappe.get_doc("Bisect Nodes", cur_node.left_child) self.current_node = cur_node.left_child self.current_from_date = lft_node.period_from_date self.current_to_date = lft_node.period_to_date @@ -147,9 +147,9 @@ class BisectAccountingStatements(Document): @frappe.whitelist() def bisect_right(self): if self.current_node is not None: - cur_node = frappe.get_doc("Nodes", self.current_node) + cur_node = frappe.get_doc("Bisect Nodes", self.current_node) if cur_node.right_child is not None: - rgt_node = frappe.get_doc("Nodes", cur_node.right_child) + rgt_node = frappe.get_doc("Bisect Nodes", cur_node.right_child) self.current_node = cur_node.right_child self.current_from_date = rgt_node.period_from_date self.current_to_date = rgt_node.period_to_date @@ -161,9 +161,9 @@ class BisectAccountingStatements(Document): @frappe.whitelist() def move_up(self): if self.current_node is not None: - cur_node = frappe.get_doc("Nodes", self.current_node) + cur_node = frappe.get_doc("Bisect Nodes", self.current_node) if cur_node.root is not None: - root = frappe.get_doc("Nodes", cur_node.root) + root = frappe.get_doc("Bisect Nodes", cur_node.root) self.current_node = cur_node.root self.current_from_date = root.period_from_date self.current_to_date = root.period_to_date diff --git a/erpnext/accounts/doctype/nodes/__init__.py b/erpnext/accounts/doctype/bisect_nodes/__init__.py similarity index 100% rename from erpnext/accounts/doctype/nodes/__init__.py rename to erpnext/accounts/doctype/bisect_nodes/__init__.py diff --git a/erpnext/accounts/doctype/nodes/nodes.js b/erpnext/accounts/doctype/bisect_nodes/bisect_nodes.js similarity index 80% rename from erpnext/accounts/doctype/nodes/nodes.js rename to erpnext/accounts/doctype/bisect_nodes/bisect_nodes.js index bd74d68637..6dea25fc92 100644 --- a/erpnext/accounts/doctype/nodes/nodes.js +++ b/erpnext/accounts/doctype/bisect_nodes/bisect_nodes.js @@ -1,7 +1,7 @@ // Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors // For license information, please see license.txt -// frappe.ui.form.on("Nodes", { +// frappe.ui.form.on("Bisect Nodes", { // refresh(frm) { // }, diff --git a/erpnext/accounts/doctype/nodes/nodes.json b/erpnext/accounts/doctype/bisect_nodes/bisect_nodes.json similarity index 88% rename from erpnext/accounts/doctype/nodes/nodes.json rename to erpnext/accounts/doctype/bisect_nodes/bisect_nodes.json index 1238c8136a..db41704795 100644 --- a/erpnext/accounts/doctype/nodes/nodes.json +++ b/erpnext/accounts/doctype/bisect_nodes/bisect_nodes.json @@ -1,7 +1,7 @@ { "actions": [], "autoname": "autoincrement", - "creation": "2023-09-25 22:01:33.961832", + "creation": "2023-09-27 14:56:38.112462", "default_view": "List", "doctype": "DocType", "editable_grid": 1, @@ -21,19 +21,19 @@ "fieldname": "root", "fieldtype": "Link", "label": "Root", - "options": "Nodes" + "options": "Bisect Nodes" }, { "fieldname": "left_child", "fieldtype": "Link", "label": "Left Child", - "options": "Nodes" + "options": "Bisect Nodes" }, { "fieldname": "right_child", "fieldtype": "Link", "label": "Right Child", - "options": "Nodes" + "options": "Bisect Nodes" }, { "fieldname": "period_from_date", @@ -63,10 +63,10 @@ ], "index_web_pages_for_search": 1, "links": [], - "modified": "2023-09-25 22:05:49.577861", + "modified": "2023-09-27 15:09:27.715523", "modified_by": "Administrator", "module": "Accounts", - "name": "Nodes", + "name": "Bisect Nodes", "naming_rule": "Autoincrement", "owner": "Administrator", "permissions": [ diff --git a/erpnext/accounts/doctype/nodes/nodes.py b/erpnext/accounts/doctype/bisect_nodes/bisect_nodes.py similarity index 86% rename from erpnext/accounts/doctype/nodes/nodes.py rename to erpnext/accounts/doctype/bisect_nodes/bisect_nodes.py index 67d5d69bfe..0d176f974a 100644 --- a/erpnext/accounts/doctype/nodes/nodes.py +++ b/erpnext/accounts/doctype/bisect_nodes/bisect_nodes.py @@ -5,5 +5,5 @@ from frappe.model.document import Document -class Nodes(Document): +class BisectNodes(Document): pass diff --git a/erpnext/accounts/doctype/nodes/test_nodes.py b/erpnext/accounts/doctype/bisect_nodes/test_bisect_nodes.py similarity index 80% rename from erpnext/accounts/doctype/nodes/test_nodes.py rename to erpnext/accounts/doctype/bisect_nodes/test_bisect_nodes.py index feeef765e0..5399df139f 100644 --- a/erpnext/accounts/doctype/nodes/test_nodes.py +++ b/erpnext/accounts/doctype/bisect_nodes/test_bisect_nodes.py @@ -5,5 +5,5 @@ from frappe.tests.utils import FrappeTestCase -class TestNodes(FrappeTestCase): +class TestBisectNodes(FrappeTestCase): pass From c4c3090f46af16f52b34dab116b49856b9da2025 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 27 Sep 2023 15:10:42 +0530 Subject: [PATCH 048/205] chore: hide internal variables section --- .../bisect_accounting_statements.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json index f62d39377e..4ad03528c5 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json @@ -128,7 +128,8 @@ }, { "fieldname": "section_break_8ph9", - "fieldtype": "Section Break" + "fieldtype": "Section Break", + "hidden": 1 }, { "fieldname": "bisect_heatmap", @@ -140,7 +141,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-09-27 15:05:44.285832", + "modified": "2023-09-27 15:10:36.394474", "modified_by": "Administrator", "module": "Accounts", "name": "Bisect Accounting Statements", From 5e2d21c033fdf6147ec58286d08cac75d6fedf23 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 27 Sep 2023 15:27:27 +0530 Subject: [PATCH 049/205] chore: code cleanup --- .../bisect_accounting_statements.js | 2 +- .../bisect_accounting_statements.py | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js index e9fc330a70..486630e162 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js @@ -50,7 +50,7 @@ frappe.ui.form.on("Bisect Accounting Statements", { start: new Date(frm.doc.from_date), end: new Date(frm.doc.to_date), }, - countLabel: 'Difference', + countLabel: 'Bisecting', discreteDomains: 1, }); }, diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py index 58b8748628..0a1de6414f 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py @@ -114,7 +114,11 @@ class BisectAccountingStatements(Document): # set root as current node root = frappe.db.get_all("Bisect Nodes", filters={"root": ["is", "not set"]})[0] - frappe.db.set_single_value("Bisect Accounting Statements", "current_node", root.name) + self.get_report_summary() + self.current_node = root.name + self.current_from_date = self.from_date + self.current_to_date = self.to_date + self.save() def get_report_summary(self): filters = { From 395299803f3d5818fa0e17bac95f515fe06b2a09 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 27 Sep 2023 15:41:53 +0530 Subject: [PATCH 050/205] chore: add screen freeze on wait --- .../bisect_accounting_statements.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js index 486630e162..519246b9bb 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js @@ -58,6 +58,8 @@ frappe.ui.form.on("Bisect Accounting Statements", { frm.call({ doc: frm.doc, method: 'bisect_left', + freeze: true, + freeze_message: __("Bisecting Left ..."), callback: (r) => { frm.trigger("render_heatmap"); } @@ -66,6 +68,8 @@ frappe.ui.form.on("Bisect Accounting Statements", { bisect_right(frm) { frm.call({ doc: frm.doc, + freeze: true, + freeze_message: __("Bisecting Right ..."), method: 'bisect_right', callback: (r) => { frm.trigger("render_heatmap"); @@ -75,6 +79,8 @@ frappe.ui.form.on("Bisect Accounting Statements", { move_up(frm) { frm.call({ doc: frm.doc, + freeze: true, + freeze_message: __("Moving up in tree ..."), method: 'move_up', callback: (r) => { frm.trigger("render_heatmap"); @@ -84,6 +90,8 @@ frappe.ui.form.on("Bisect Accounting Statements", { build_tree(frm) { frm.call({ doc: frm.doc, + freeze: true, + freeze_message: __("Rebuilding BTree for period ..."), method: 'build_tree', callback: (r) => { frm.trigger("render_heatmap"); From ea3071db6643f7802611e7a0ae8857d75583dd96 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 27 Sep 2023 15:53:19 +0530 Subject: [PATCH 051/205] chore: UI cleanup --- .../bisect_accounting_statements.json | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json index 4ad03528c5..a9fa7f0695 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json @@ -16,12 +16,12 @@ "algorithm", "section_break_8ph9", "current_node", + "section_break_ngid", + "bisect_heatmap", "section_break_hmsy", "current_from_date", "column_break_uqyd", "current_to_date", - "section_break_ngid", - "bisect_heatmap", "section_break_hbyo", "p_l_summary", "column_break_aivo", @@ -63,19 +63,18 @@ }, { "fieldname": "section_break_hmsy", - "fieldtype": "Section Break", - "hidden": 1 + "fieldtype": "Section Break" }, { "fieldname": "current_from_date", "fieldtype": "Datetime", - "label": "Current From Date", + "label": "Bisecting From", "read_only": 1 }, { "fieldname": "current_to_date", "fieldtype": "Datetime", - "label": "Current To Date", + "label": "Bisecting To", "read_only": 1 }, { @@ -141,7 +140,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-09-27 15:10:36.394474", + "modified": "2023-09-27 15:52:14.083727", "modified_by": "Administrator", "module": "Accounts", "name": "Bisect Accounting Statements", From 993e2bfbf9f75958d5283fcbbcaa5e6f80e88f86 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 27 Sep 2023 16:05:14 +0530 Subject: [PATCH 052/205] refactor: adding labels to important section --- .../bisect_accounting_statements.js | 1 - .../bisect_accounting_statements.json | 37 ++++++++++++++++--- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js index 519246b9bb..ece0fb33e5 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.js @@ -44,7 +44,6 @@ frappe.ui.form.on("Bisect Accounting Statements", { new frappe.Chart(".bisect_heatmap_location", { type: "heatmap", - title: "Bisecting On", data: { dataPoints: datapoints, start: new Date(frm.doc.from_date), diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json index a9fa7f0695..b66c17b648 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json @@ -19,14 +19,19 @@ "section_break_ngid", "bisect_heatmap", "section_break_hmsy", + "bisecting_from", "current_from_date", "column_break_uqyd", + "bisecting_to", "current_to_date", "section_break_hbyo", + "heading_cppb", "p_l_summary", "column_break_aivo", + "balance_sheet_summary", "b_s_summary", "column_break_gvwx", + "difference_heading", "difference" ], "fields": [ @@ -68,13 +73,11 @@ { "fieldname": "current_from_date", "fieldtype": "Datetime", - "label": "Bisecting From", "read_only": 1 }, { "fieldname": "current_to_date", "fieldtype": "Datetime", - "label": "Bisecting To", "read_only": 1 }, { @@ -88,19 +91,16 @@ { "fieldname": "p_l_summary", "fieldtype": "Data", - "label": "P&L Summary", "read_only": 1 }, { "fieldname": "b_s_summary", "fieldtype": "Data", - "label": "Balance Sheet Summary", "read_only": 1 }, { "fieldname": "difference", "fieldtype": "Data", - "label": "Difference", "read_only": 1 }, { @@ -134,13 +134,38 @@ "fieldname": "bisect_heatmap", "fieldtype": "HTML", "label": "Heatmap" + }, + { + "fieldname": "heading_cppb", + "fieldtype": "Heading", + "label": "Profit and Loss Summary" + }, + { + "fieldname": "balance_sheet_summary", + "fieldtype": "Heading", + "label": "Balance Sheet Summary" + }, + { + "fieldname": "difference_heading", + "fieldtype": "Heading", + "label": "Difference" + }, + { + "fieldname": "bisecting_from", + "fieldtype": "Heading", + "label": "Bisecting From" + }, + { + "fieldname": "bisecting_to", + "fieldtype": "Heading", + "label": "Bisecting To" } ], "hide_toolbar": 1, "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-09-27 15:52:14.083727", + "modified": "2023-09-27 16:08:18.155873", "modified_by": "Administrator", "module": "Accounts", "name": "Bisect Accounting Statements", From 228aa1a244632505bb466f1252c14ce5950b1ef7 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 27 Sep 2023 16:22:20 +0530 Subject: [PATCH 053/205] chore: change data type for summary fields --- .../bisect_accounting_statements.json | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json index b66c17b648..d70ae1f90e 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json @@ -7,6 +7,7 @@ "editable_grid": 1, "engine": "InnoDB", "field_order": [ + "section_break_cvfg", "company", "column_break_hcam", "from_date", @@ -90,17 +91,17 @@ }, { "fieldname": "p_l_summary", - "fieldtype": "Data", + "fieldtype": "Float", "read_only": 1 }, { "fieldname": "b_s_summary", - "fieldtype": "Data", + "fieldtype": "Float", "read_only": 1 }, { "fieldname": "difference", - "fieldtype": "Data", + "fieldtype": "Float", "read_only": 1 }, { @@ -159,13 +160,17 @@ "fieldname": "bisecting_to", "fieldtype": "Heading", "label": "Bisecting To" + }, + { + "fieldname": "section_break_cvfg", + "fieldtype": "Section Break" } ], "hide_toolbar": 1, "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-09-27 16:08:18.155873", + "modified": "2023-09-27 16:22:10.670836", "modified_by": "Administrator", "module": "Accounts", "name": "Bisect Accounting Statements", From 90c6d4dc85701902ad9d12b31716db098831dc10 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 1 Dec 2023 16:50:17 +0530 Subject: [PATCH 054/205] chore: restrict only to administrator and type info --- .../bisect_accounting_statements.json | 5 +++-- .../bisect_accounting_statements.py | 20 +++++++++++++++++++ .../doctype/bisect_nodes/bisect_nodes.json | 5 +++-- .../doctype/bisect_nodes/bisect_nodes.py | 19 ++++++++++++++++++ 4 files changed, 45 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json index d70ae1f90e..e129fa60c2 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json @@ -170,7 +170,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-09-27 16:22:10.670836", + "modified": "2023-12-01 16:49:54.073890", "modified_by": "Administrator", "module": "Accounts", "name": "Bisect Accounting Statements", @@ -182,11 +182,12 @@ "email": 1, "print": 1, "read": 1, - "role": "System Manager", + "role": "Administrator", "share": 1, "write": 1 } ], + "read_only": 1, "sort_field": "modified", "sort_order": "DESC", "states": [] diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py index 0a1de6414f..e2a67d14b7 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py @@ -14,6 +14,26 @@ from frappe.utils.data import guess_date_format class BisectAccountingStatements(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + algorithm: DF.Literal["BFS", "DFS"] + b_s_summary: DF.Float + company: DF.Link | None + current_from_date: DF.Datetime | None + current_node: DF.Link | None + current_to_date: DF.Datetime | None + difference: DF.Float + from_date: DF.Datetime | None + p_l_summary: DF.Float + to_date: DF.Datetime | None + # end: auto-generated types + def validate(self): self.validate_dates() diff --git a/erpnext/accounts/doctype/bisect_nodes/bisect_nodes.json b/erpnext/accounts/doctype/bisect_nodes/bisect_nodes.json index db41704795..f352d7a31a 100644 --- a/erpnext/accounts/doctype/bisect_nodes/bisect_nodes.json +++ b/erpnext/accounts/doctype/bisect_nodes/bisect_nodes.json @@ -63,7 +63,7 @@ ], "index_web_pages_for_search": 1, "links": [], - "modified": "2023-09-27 15:09:27.715523", + "modified": "2023-12-01 16:49:57.146867", "modified_by": "Administrator", "module": "Accounts", "name": "Bisect Nodes", @@ -78,11 +78,12 @@ "print": 1, "read": 1, "report": 1, - "role": "System Manager", + "role": "Administrator", "share": 1, "write": 1 } ], + "read_only": 1, "sort_field": "modified", "sort_order": "DESC", "states": [] diff --git a/erpnext/accounts/doctype/bisect_nodes/bisect_nodes.py b/erpnext/accounts/doctype/bisect_nodes/bisect_nodes.py index 0d176f974a..e49eabbff5 100644 --- a/erpnext/accounts/doctype/bisect_nodes/bisect_nodes.py +++ b/erpnext/accounts/doctype/bisect_nodes/bisect_nodes.py @@ -6,4 +6,23 @@ from frappe.model.document import Document class BisectNodes(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + balance_sheet_summary: DF.Float + difference: DF.Float + left_child: DF.Link | None + name: DF.Int | None + period_from_date: DF.Datetime | None + period_to_date: DF.Datetime | None + profit_loss_summary: DF.Float + right_child: DF.Link | None + root: DF.Link | None + # end: auto-generated types + pass From ca14ae8f1bc69539ca3a2f49f92e2b6c667a40b3 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 1 Dec 2023 17:07:39 +0530 Subject: [PATCH 055/205] refactor: save results in node --- .../bisect_accounting_statements.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py index e2a67d14b7..216f553084 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py @@ -154,6 +154,13 @@ class BisectAccountingStatements(Document): self.b_s_summary = bs_summary.execute_script_report(filters=filters)[5] self.difference = abs(self.p_l_summary - self.b_s_summary) + def update_node(self): + current_node = frappe.get_doc("Bisect Nodes", self.current_node) + current_node.balance_sheet_summary = self.b_s_summary + current_node.profit_loss_summary = self.p_l_summary + current_node.difference = self.difference + current_node.save() + @frappe.whitelist() def bisect_left(self): if self.current_node is not None: @@ -164,6 +171,7 @@ class BisectAccountingStatements(Document): self.current_from_date = lft_node.period_from_date self.current_to_date = lft_node.period_to_date self.get_report_summary() + self.update_node() self.save() else: frappe.msgprint("No more children on Left") @@ -178,6 +186,7 @@ class BisectAccountingStatements(Document): self.current_from_date = rgt_node.period_from_date self.current_to_date = rgt_node.period_to_date self.get_report_summary() + self.update_node() self.save() else: frappe.msgprint("No more children on Right") @@ -192,6 +201,7 @@ class BisectAccountingStatements(Document): self.current_from_date = root.period_from_date self.current_to_date = root.period_to_date self.get_report_summary() + self.update_node() self.save() else: frappe.msgprint("Reached Root") From 0925706d5efac2cbdfe5240e0310c1a9738a3560 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 1 Dec 2023 17:46:28 +0530 Subject: [PATCH 056/205] refactor: flag to differentiate generated and default values --- .../accounts/doctype/bisect_nodes/bisect_nodes.json | 11 +++++++++-- erpnext/accounts/doctype/bisect_nodes/bisect_nodes.py | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/bisect_nodes/bisect_nodes.json b/erpnext/accounts/doctype/bisect_nodes/bisect_nodes.json index f352d7a31a..03fad261c3 100644 --- a/erpnext/accounts/doctype/bisect_nodes/bisect_nodes.json +++ b/erpnext/accounts/doctype/bisect_nodes/bisect_nodes.json @@ -14,7 +14,8 @@ "period_to_date", "difference", "balance_sheet_summary", - "profit_loss_summary" + "profit_loss_summary", + "generated" ], "fields": [ { @@ -59,11 +60,17 @@ "fieldname": "profit_loss_summary", "fieldtype": "Float", "label": "Profit and Loss Summary" + }, + { + "default": "0", + "fieldname": "generated", + "fieldtype": "Check", + "label": "Generated" } ], "index_web_pages_for_search": 1, "links": [], - "modified": "2023-12-01 16:49:57.146867", + "modified": "2023-12-01 17:46:12.437996", "modified_by": "Administrator", "module": "Accounts", "name": "Bisect Nodes", diff --git a/erpnext/accounts/doctype/bisect_nodes/bisect_nodes.py b/erpnext/accounts/doctype/bisect_nodes/bisect_nodes.py index e49eabbff5..f50776641d 100644 --- a/erpnext/accounts/doctype/bisect_nodes/bisect_nodes.py +++ b/erpnext/accounts/doctype/bisect_nodes/bisect_nodes.py @@ -16,6 +16,7 @@ class BisectNodes(Document): balance_sheet_summary: DF.Float difference: DF.Float + generated: DF.Check left_child: DF.Link | None name: DF.Int | None period_from_date: DF.Datetime | None From 14c8c8c33d8f8df636ed5b3de589cc872f6aaf7b Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 1 Dec 2023 17:52:36 +0530 Subject: [PATCH 057/205] refactor: cache results --- .../bisect_accounting_statements.py | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py index 216f553084..1d6fd621aa 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py @@ -66,6 +66,7 @@ class BisectAccountingStatements(Document): left_node.period_from_date = cur_node.period_from_date left_node.period_to_date = next_to_date left_node.root = cur_node.name + left_node.generated = False left_node.insert() cur_node.left_child = left_node.name period_queue.append(left_node) @@ -75,6 +76,7 @@ class BisectAccountingStatements(Document): right_node.period_from_date = next_from_date right_node.period_to_date = cur_node.period_to_date right_node.root = cur_node.name + right_node.generated = False right_node.insert() cur_node.right_child = right_node.name period_queue.append(right_node) @@ -102,6 +104,7 @@ class BisectAccountingStatements(Document): left_node.period_from_date = cur_node.period_from_date left_node.period_to_date = next_to_date left_node.root = cur_node.name + left_node.generated = False left_node.insert() cur_node.left_child = left_node.name period_stack.append(left_node) @@ -111,6 +114,7 @@ class BisectAccountingStatements(Document): right_node.period_from_date = next_from_date right_node.period_to_date = cur_node.period_to_date right_node.root = cur_node.name + right_node.generated = False right_node.insert() cur_node.right_child = right_node.name period_stack.append(right_node) @@ -159,8 +163,26 @@ class BisectAccountingStatements(Document): current_node.balance_sheet_summary = self.b_s_summary current_node.profit_loss_summary = self.p_l_summary current_node.difference = self.difference + current_node.generated = True current_node.save() + def current_node_has_summary_info(self): + "Assertion method" + return frappe.db.get_value("Bisect Nodes", self.current_node, "generated") + + def fetch_summary_info_from_current_node(self): + current_node = frappe.get_doc("Bisect Nodes", self.current_node) + self.p_l_summary = current_node.balance_sheet_summary + self.b_s_summary = current_node.profit_loss_summary + self.difference = abs(self.p_l_summary - self.b_s_summary) + + def fetch_or_calculate(self): + if self.current_node_has_summary_info(): + self.fetch_summary_info_from_current_node() + else: + self.get_report_summary() + self.update_node() + @frappe.whitelist() def bisect_left(self): if self.current_node is not None: @@ -170,8 +192,7 @@ class BisectAccountingStatements(Document): self.current_node = cur_node.left_child self.current_from_date = lft_node.period_from_date self.current_to_date = lft_node.period_to_date - self.get_report_summary() - self.update_node() + self.fetch_or_calculate() self.save() else: frappe.msgprint("No more children on Left") @@ -185,8 +206,7 @@ class BisectAccountingStatements(Document): self.current_node = cur_node.right_child self.current_from_date = rgt_node.period_from_date self.current_to_date = rgt_node.period_to_date - self.get_report_summary() - self.update_node() + self.fetch_or_calculate() self.save() else: frappe.msgprint("No more children on Right") @@ -200,8 +220,7 @@ class BisectAccountingStatements(Document): self.current_node = cur_node.root self.current_from_date = root.period_from_date self.current_to_date = root.period_to_date - self.get_report_summary() - self.update_node() + self.fetch_or_calculate() self.save() else: frappe.msgprint("Reached Root") From 9aeb3932d0f7dbf3daf5f8ba2e6e9f02082a0f54 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Sat, 2 Dec 2023 19:50:16 +0530 Subject: [PATCH 058/205] fix: fetch against link value in gl report --- erpnext/accounts/general_ledger.py | 1 + erpnext/accounts/report/general_ledger/general_ledger.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index 70a8470614..6e4cc128a4 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -280,6 +280,7 @@ def check_if_in_list(gle, gl_map, dimensions=None): "project", "finance_book", "voucher_no", + "against_link", ] if dimensions: diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index fa557a133f..08be4319e4 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -203,7 +203,7 @@ def get_gl_entries(filters, accounting_dimensions): voucher_type, voucher_no, {dimension_fields} cost_center, project, {transaction_currency_fields} against_voucher_type, against_voucher, account_currency, - against, is_opening, creation {select_fields} + against_link, against, is_opening, creation {select_fields} from `tabGL Entry` where company=%(company)s {conditions} {order_by_statement} @@ -391,6 +391,7 @@ def initialize_gle_map(gl_entries, filters): group_by = group_by_field(filters.get("group_by")) for gle in gl_entries: + gle.against = gle.get("against_link") or gle.get("against") gle_map.setdefault(gle.get(group_by), _dict(totals=get_totals_dict(), entries=[])) return gle_map From b2d8a4419903830220b3aa7228de641e59606e67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernd=20Oliver=20S=C3=BCnderhauf?= <46800703+bosue@users.noreply.github.com> Date: Sun, 3 Dec 2023 15:10:00 +0100 Subject: [PATCH 059/205] test: Add, expand and refine test-cases for zero-quantity transactions. --- .../purchase_invoice/test_purchase_invoice.py | 16 ++++++++--- .../sales_invoice/test_sales_invoice.py | 16 ++++++++--- .../purchase_order/test_purchase_order.py | 10 ++++++- .../test_request_for_quotation.py | 18 +++++++++++-- .../test_supplier_quotation.py | 13 +++++++++ erpnext/buying/utils.py | 5 +++- erpnext/controllers/selling_controller.py | 5 ++-- erpnext/manufacturing/doctype/bom/test_bom.py | 22 +++++++++++++++ .../doctype/quotation/test_quotation.py | 14 +++++++++- .../doctype/sales_order/test_sales_order.py | 27 +++++++++++++++++-- .../delivery_note/test_delivery_note.py | 15 +++++++++-- .../material_request/test_material_request.py | 12 +++++++++ .../purchase_receipt/test_purchase_receipt.py | 21 ++++++++++++++- .../stock/doctype/stock_entry/stock_entry.py | 4 ++- .../doctype/stock_entry/test_stock_entry.py | 13 +++++++++ 15 files changed, 192 insertions(+), 19 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index e43ea6ecbe..8ff9f9002c 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -14,7 +14,7 @@ from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_ent from erpnext.buying.doctype.purchase_order.purchase_order import get_mapped_purchase_invoice from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order from erpnext.buying.doctype.supplier.test_supplier import create_supplier -from erpnext.controllers.accounts_controller import get_payment_terms +from erpnext.controllers.accounts_controller import InvalidQtyError, get_payment_terms from erpnext.controllers.buying_controller import QtyMismatchError from erpnext.exceptions import InvalidCurrency from erpnext.projects.doctype.project.test_project import make_project @@ -51,6 +51,16 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin): def tearDown(self): frappe.db.rollback() + def test_purchase_invoice_qty(self): + pi = make_purchase_invoice(qty=0, do_not_save=True) + with self.assertRaises(InvalidQtyError): + pi.save() + + # No error with qty=1 + pi.items[0].qty = 1 + pi.save() + self.assertEqual(pi.items[0].qty, 1) + def test_purchase_invoice_received_qty(self): """ 1. Test if received qty is validated against accepted + rejected @@ -2094,7 +2104,7 @@ def make_purchase_invoice(**args): bundle_id = None if args.get("batch_no") or args.get("serial_no"): batches = {} - qty = args.qty or 5 + qty = args.qty if args.qty is not None else 5 item_code = args.item or args.item_code or "_Test Item" if args.get("batch_no"): batches = frappe._dict({args.batch_no: qty}) @@ -2122,7 +2132,7 @@ def make_purchase_invoice(**args): { "item_code": args.item or args.item_code or "_Test Item", "warehouse": args.warehouse or "_Test Warehouse - _TC", - "qty": args.qty or 5, + "qty": args.qty if args.qty is not None else 5, "received_qty": args.received_qty or 0, "rejected_qty": args.rejected_qty or 0, "rate": args.rate or 50, diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index e9b71ddffd..01b5e28ea4 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -23,7 +23,7 @@ from erpnext.assets.doctype.asset.test_asset import create_asset, create_asset_d from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import ( get_depr_schedule, ) -from erpnext.controllers.accounts_controller import update_invoice_status +from erpnext.controllers.accounts_controller import InvalidQtyError, update_invoice_status from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_data from erpnext.exceptions import InvalidAccountCurrency, InvalidCurrency from erpnext.selling.doctype.customer.test_customer import get_customer_dict @@ -72,6 +72,16 @@ class TestSalesInvoice(FrappeTestCase): def tearDownClass(self): unlink_payment_on_cancel_of_invoice(0) + def test_sales_invoice_qty(self): + si = create_sales_invoice(qty=0, do_not_save=True) + with self.assertRaises(InvalidQtyError): + si.save() + + # No error with qty=1 + si.items[0].qty = 1 + si.save() + self.assertEqual(si.items[0].qty, 1) + def test_timestamp_change(self): w = frappe.copy_doc(test_records[0]) w.docstatus = 0 @@ -3629,7 +3639,7 @@ def create_sales_invoice(**args): bundle_id = None if si.update_stock and (args.get("batch_no") or args.get("serial_no")): batches = {} - qty = args.qty or 1 + qty = args.qty if args.qty is not None else 1 item_code = args.item or args.item_code or "_Test Item" if args.get("batch_no"): batches = frappe._dict({args.batch_no: qty}) @@ -3661,7 +3671,7 @@ def create_sales_invoice(**args): "description": args.description or "_Test Item", "warehouse": args.warehouse or "_Test Warehouse - _TC", "target_warehouse": args.target_warehouse, - "qty": args.qty or 1, + "qty": args.qty if args.qty is not None else 1, "uom": args.uom or "Nos", "stock_uom": args.uom or "Nos", "rate": args.rate if args.get("rate") is not None else 100, diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py index f80a00a95f..9b382bbd7e 100644 --- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py @@ -29,6 +29,8 @@ from erpnext.stock.doctype.purchase_receipt.purchase_receipt import ( class TestPurchaseOrder(FrappeTestCase): def test_purchase_order_qty(self): po = create_purchase_order(qty=1, do_not_save=True) + + # NonNegativeError with qty=-1 po.append( "items", { @@ -39,9 +41,15 @@ class TestPurchaseOrder(FrappeTestCase): ) self.assertRaises(frappe.NonNegativeError, po.save) + # InvalidQtyError with qty=0 po.items[1].qty = 0 self.assertRaises(InvalidQtyError, po.save) + # No error with qty=1 + po.items[1].qty = 1 + po.save() + self.assertEqual(po.items[1].qty, 1) + def test_make_purchase_receipt(self): po = create_purchase_order(do_not_submit=True) self.assertRaises(frappe.ValidationError, make_purchase_receipt, po.name) @@ -1108,7 +1116,7 @@ def create_purchase_order(**args): "item_code": args.item or args.item_code or "_Test Item", "warehouse": args.warehouse or "_Test Warehouse - _TC", "from_warehouse": args.from_warehouse, - "qty": args.qty or 10, + "qty": args.qty if args.qty is not None else 10, "rate": args.rate or 500, "schedule_date": add_days(nowdate(), 1), "include_exploded_items": args.get("include_exploded_items", 1), diff --git a/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py index 42fa1d923e..05a604f0cc 100644 --- a/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py +++ b/erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py @@ -14,6 +14,7 @@ from erpnext.buying.doctype.request_for_quotation.request_for_quotation import ( get_pdf, make_supplier_quotation_from_rfq, ) +from erpnext.controllers.accounts_controller import InvalidQtyError from erpnext.crm.doctype.opportunity.opportunity import make_request_for_quotation as make_rfq from erpnext.crm.doctype.opportunity.test_opportunity import make_opportunity from erpnext.stock.doctype.item.test_item import make_item @@ -21,6 +22,16 @@ from erpnext.templates.pages.rfq import check_supplier_has_docname_access class TestRequestforQuotation(FrappeTestCase): + def test_rfq_qty(self): + rfq = make_request_for_quotation(qty=0, do_not_save=True) + with self.assertRaises(InvalidQtyError): + rfq.save() + + # No error with qty=1 + rfq.items[0].qty = 1 + rfq.save() + self.assertEqual(rfq.items[0].qty, 1) + def test_quote_status(self): rfq = make_request_for_quotation() @@ -161,14 +172,17 @@ def make_request_for_quotation(**args) -> "RequestforQuotation": "description": "_Test Item", "uom": args.uom or "_Test UOM", "stock_uom": args.stock_uom or "_Test UOM", - "qty": args.qty or 5, + "qty": args.qty if args.qty is not None else 5, "conversion_factor": args.conversion_factor or 1.0, "warehouse": args.warehouse or "_Test Warehouse - _TC", "schedule_date": nowdate(), }, ) - rfq.submit() + if not args.do_not_save: + rfq.insert() + if not args.do_not_submit: + rfq.submit() return rfq diff --git a/erpnext/buying/doctype/supplier_quotation/test_supplier_quotation.py b/erpnext/buying/doctype/supplier_quotation/test_supplier_quotation.py index 13c851c735..33465700f4 100644 --- a/erpnext/buying/doctype/supplier_quotation/test_supplier_quotation.py +++ b/erpnext/buying/doctype/supplier_quotation/test_supplier_quotation.py @@ -5,8 +5,21 @@ import frappe from frappe.tests.utils import FrappeTestCase +from erpnext.controllers.accounts_controller import InvalidQtyError + class TestPurchaseOrder(FrappeTestCase): + def test_supplier_quotation_qty(self): + sq = frappe.copy_doc(test_records[0]) + sq.items[0].qty = 0 + with self.assertRaises(InvalidQtyError): + sq.save() + + # No error with qty=1 + sq.items[0].qty = 1 + sq.save() + self.assertEqual(sq.items[0].qty, 1) + def test_make_purchase_order(self): from erpnext.buying.doctype.supplier_quotation.supplier_quotation import make_purchase_order diff --git a/erpnext/buying/utils.py b/erpnext/buying/utils.py index e904af0dce..8b7b6940ca 100644 --- a/erpnext/buying/utils.py +++ b/erpnext/buying/utils.py @@ -42,12 +42,15 @@ def update_last_purchase_rate(doc, is_submit) -> None: def validate_for_items(doc) -> None: + from erpnext.controllers.accounts_controller import InvalidQtyError + items = [] for d in doc.get("items"): if not d.qty: if doc.doctype == "Purchase Receipt" and d.rejected_qty: continue - frappe.throw(_("Please enter quantity for Item {0}").format(d.item_code)) + message = _("Please enter quantity for Item {0}").format(d.item_code) + frappe.throw(message, InvalidQtyError) set_stock_levels(row=d) # update with latest quantities item = validate_item_and_get_basic_data(row=d) diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index fdadb30e93..d6e3ee25a9 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -7,7 +7,7 @@ from frappe import _, bold, throw from frappe.utils import cint, flt, get_link_to_form, nowtime from erpnext.accounts.party import render_address -from erpnext.controllers.accounts_controller import get_taxes_and_charges +from erpnext.controllers.accounts_controller import InvalidQtyError, get_taxes_and_charges from erpnext.controllers.sales_and_purchase_return import get_rate_for_return from erpnext.controllers.stock_controller import StockController from erpnext.stock.doctype.item.item import set_item_default @@ -296,7 +296,8 @@ class SellingController(StockController): il = [] for d in self.get("items"): if d.qty is None: - frappe.throw(_("Row {0}: Qty is mandatory").format(d.idx)) + message = _("Row {0}: Qty is mandatory").format(d.idx) + frappe.throw(message, InvalidQtyError) if self.has_product_bundle(d.item_code): for p in self.get("packed_items"): diff --git a/erpnext/manufacturing/doctype/bom/test_bom.py b/erpnext/manufacturing/doctype/bom/test_bom.py index 051b475bcc..3611bb469d 100644 --- a/erpnext/manufacturing/doctype/bom/test_bom.py +++ b/erpnext/manufacturing/doctype/bom/test_bom.py @@ -27,6 +27,28 @@ test_dependencies = ["Item", "Quality Inspection Template"] class TestBOM(FrappeTestCase): + @timeout + def test_bom_qty(self): + from erpnext.stock.doctype.item.test_item import make_item + + # No error. + bom = frappe.new_doc("BOM") + item = make_item(properties={"is_stock_item": 1}) + bom.item = fg_item.item_code + bom.quantity = 1 + bom.append( + "items", + { + "item_code": bom_item.item_code, + "qty": 0, + "uom": bom_item.stock_uom, + "stock_uom": bom_item.stock_uom, + "rate": 100.0, + }, + ) + bom.save() + self.assertEqual(bom.items[0].qty, 0) + @timeout def test_get_items(self): from erpnext.manufacturing.doctype.bom.bom import get_bom_items_as_dict diff --git a/erpnext/selling/doctype/quotation/test_quotation.py b/erpnext/selling/doctype/quotation/test_quotation.py index 590cd3d0cf..ecb7d097b8 100644 --- a/erpnext/selling/doctype/quotation/test_quotation.py +++ b/erpnext/selling/doctype/quotation/test_quotation.py @@ -5,10 +5,22 @@ import frappe from frappe.tests.utils import FrappeTestCase from frappe.utils import add_days, add_months, flt, getdate, nowdate +from erpnext.controllers.accounts_controller import InvalidQtyError + test_dependencies = ["Product Bundle"] class TestQuotation(FrappeTestCase): + def test_quotation_qty(self): + qo = make_quotation(qty=0, do_not_save=True) + with self.assertRaises(InvalidQtyError): + qo.save() + + # No error with qty=1 + qo.items[0].qty = 1 + qo.save() + self.assertEqual(qo.items[0].qty, 1) + def test_make_quotation_without_terms(self): quotation = make_quotation(do_not_save=1) self.assertFalse(quotation.get("payment_schedule")) @@ -629,7 +641,7 @@ def make_quotation(**args): { "item_code": args.item or args.item_code or "_Test Item", "warehouse": args.warehouse, - "qty": args.qty or 10, + "qty": args.qty if args.qty is not None else 10, "uom": args.uom or None, "rate": args.rate or 100, }, diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index a518597aa6..a6c86a670d 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -9,7 +9,7 @@ from frappe.core.doctype.user_permission.test_user_permission import create_user from frappe.tests.utils import FrappeTestCase, change_settings from frappe.utils import add_days, flt, getdate, nowdate, today -from erpnext.controllers.accounts_controller import update_child_qty_rate +from erpnext.controllers.accounts_controller import InvalidQtyError, update_child_qty_rate from erpnext.maintenance.doctype.maintenance_schedule.test_maintenance_schedule import ( make_maintenance_schedule, ) @@ -80,6 +80,29 @@ class TestSalesOrder(FrappeTestCase): ) update_child_qty_rate("Sales Order", trans_item, so.name) + def test_sales_order_qty(self): + so = make_sales_order(qty=1, do_not_save=True) + + # NonNegativeError with qty=-1 + so.append( + "items", + { + "item_code": "_Test Item", + "qty": -1, + "rate": 10, + }, + ) + self.assertRaises(frappe.NonNegativeError, so.save) + + # InvalidQtyError with qty=0 + so.items[1].qty = 0 + self.assertRaises(InvalidQtyError, so.save) + + # No error with qty=1 + so.items[1].qty = 1 + so.save() + self.assertEqual(so.items[0].qty, 1) + def test_make_material_request(self): so = make_sales_order(do_not_submit=True) @@ -2015,7 +2038,7 @@ def make_sales_order(**args): { "item_code": args.item or args.item_code or "_Test Item", "warehouse": args.warehouse, - "qty": args.qty or 10, + "qty": args.qty if args.qty is not None else 10, "uom": args.uom or None, "price_list_rate": args.price_list_rate or None, "discount_percentage": args.discount_percentage or None, diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index 94655747e4..376b970222 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -10,6 +10,7 @@ from frappe.utils import add_days, cstr, flt, nowdate, nowtime, today from erpnext.accounts.doctype.account.test_account import get_inventory_account from erpnext.accounts.utils import get_balance_on +from erpnext.controllers.accounts_controller import InvalidQtyError from erpnext.selling.doctype.product_bundle.test_product_bundle import make_product_bundle from erpnext.selling.doctype.sales_order.test_sales_order import ( automatically_fetch_payment_terms, @@ -42,6 +43,16 @@ from erpnext.stock.stock_ledger import get_previous_sle class TestDeliveryNote(FrappeTestCase): + def test_delivery_note_qty(self): + dn = create_delivery_note(qty=0, do_not_save=True) + with self.assertRaises(InvalidQtyError): + dn.save() + + # No error with qty=1 + dn.items[0].qty = 1 + dn.save() + self.assertEqual(dn.items[0].qty, 1) + def test_over_billing_against_dn(self): frappe.db.set_single_value("Stock Settings", "allow_negative_stock", 1) @@ -1287,7 +1298,7 @@ def create_delivery_note(**args): if dn.is_return: type_of_transaction = "Inward" - qty = args.get("qty") or 1 + qty = args.qty if args.get("qty") is not None else 1 qty *= -1 if type_of_transaction == "Outward" else 1 batches = {} if args.get("batch_no"): @@ -1315,7 +1326,7 @@ def create_delivery_note(**args): { "item_code": args.item or args.item_code or "_Test Item", "warehouse": args.warehouse or "_Test Warehouse - _TC", - "qty": args.qty or 1, + "qty": args.qty if args.get("qty") is not None else 1, "rate": args.rate if args.get("rate") is not None else 100, "conversion_factor": 1.0, "serial_and_batch_bundle": bundle_id, diff --git a/erpnext/stock/doctype/material_request/test_material_request.py b/erpnext/stock/doctype/material_request/test_material_request.py index e5aff38c52..3e440497f0 100644 --- a/erpnext/stock/doctype/material_request/test_material_request.py +++ b/erpnext/stock/doctype/material_request/test_material_request.py @@ -9,6 +9,7 @@ import frappe from frappe.tests.utils import FrappeTestCase from frappe.utils import flt, today +from erpnext.controllers.accounts_controller import InvalidQtyError from erpnext.stock.doctype.item.test_item import create_item from erpnext.stock.doctype.material_request.material_request import ( make_in_transit_stock_entry, @@ -20,6 +21,17 @@ from erpnext.stock.doctype.material_request.material_request import ( class TestMaterialRequest(FrappeTestCase): + def test_material_request_qty(self): + mr = frappe.copy_doc(test_records[0]) + mr.items[0].qty = 0 + with self.assertRaises(InvalidQtyError): + mr.insert() + + # No error with qty=1 + mr.items[0].qty = 1 + mr.save() + self.assertEqual(mr.items[0].qty, 1) + def test_make_purchase_order(self): mr = frappe.copy_doc(test_records[0]).insert() diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index 146cbff1aa..57ba5bb0a5 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -8,6 +8,7 @@ from pypika import functions as fn import erpnext from erpnext.accounts.doctype.account.test_account import get_inventory_account +from erpnext.controllers.accounts_controller import InvalidQtyError from erpnext.controllers.buying_controller import QtyMismatchError from erpnext.stock.doctype.item.test_item import create_item, make_item from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_purchase_invoice @@ -29,6 +30,23 @@ class TestPurchaseReceipt(FrappeTestCase): def setUp(self): frappe.db.set_single_value("Buying Settings", "allow_multiple_items", 1) + def test_purchase_receipt_qty(self): + pr = make_purchase_receipt(qty=0, rejected_qty=0, do_not_save=True) + with self.assertRaises(InvalidQtyError): + pr.save() + + # No error with qty=1 + pr.items[0].qty = 1 + pr.save() + self.assertEqual(pr.items[0].qty, 1) + + # No error with rejected_qty=1 + pr.items[0].rejected_warehouse = "_Test Rejected Warehouse - _TC" + pr.items[0].rejected_qty = 1 + pr.items[0].qty = 0 + pr.save() + self.assertEqual(pr.items[0].rejected_qty, 1) + def test_purchase_receipt_received_qty(self): """ 1. Test if received qty is validated against accepted + rejected @@ -2348,7 +2366,8 @@ def make_purchase_receipt(**args): pr.is_return = args.is_return pr.return_against = args.return_against pr.apply_putaway_rule = args.apply_putaway_rule - qty = args.qty or 5 + + qty = args.qty if args.qty is not None else 5 rejected_qty = args.rejected_qty or 0 received_qty = args.received_qty or flt(rejected_qty) + flt(qty) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 3baafd77ba..37a80be0e3 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -24,6 +24,7 @@ from frappe.utils import ( import erpnext from erpnext.accounts.general_ledger import process_gl_map +from erpnext.controllers.accounts_controller import InvalidQtyError from erpnext.controllers.taxes_and_totals import init_landed_taxes_and_totals from erpnext.manufacturing.doctype.bom.bom import add_additional_cost, validate_bom_no from erpnext.setup.doctype.brand.brand import get_brand_defaults @@ -390,7 +391,8 @@ class StockEntry(StockController): def set_transfer_qty(self): for item in self.get("items"): if not flt(item.qty): - frappe.throw(_("Row {0}: Qty is mandatory").format(item.idx), title=_("Zero quantity")) + message = _("Row {0}: Qty is mandatory").format(item.idx) + frappe.throw(message, InvalidQtyError, title=_("Zero quantity")) if not flt(item.conversion_factor): frappe.throw(_("Row {0}: UOM Conversion Factor is mandatory").format(item.idx)) item.transfer_qty = flt( diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index eb1c7a85eb..5ebf7c92da 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -8,6 +8,7 @@ from frappe.tests.utils import FrappeTestCase, change_settings from frappe.utils import add_days, add_to_date, flt, nowdate, nowtime, today from erpnext.accounts.doctype.account.test_account import get_inventory_account +from erpnext.controllers.accounts_controller import InvalidQtyError from erpnext.stock.doctype.item.test_item import ( create_item, make_item, @@ -54,6 +55,18 @@ class TestStockEntry(FrappeTestCase): frappe.db.rollback() frappe.set_user("Administrator") + def test_stock_entry_qty(self): + item_code = "_Test Item 2" + warehouse = "_Test Warehouse - _TC" + se = make_stock_entry(item_code=item_code, target=warehouse, qty=0, do_not_save=True) + with self.assertRaises(InvalidQtyError): + se.save() + + # No error with qty=1 + se.items[0].qty = 1 + se.save() + self.assertEqual(se.items[0].qty, 1) + def test_fifo(self): frappe.db.set_single_value("Stock Settings", "allow_negative_stock", 1) item_code = "_Test Item 2" From 6d31563920a8daeac7a782b070e6c44fd01a9f17 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Sun, 3 Dec 2023 22:33:21 +0530 Subject: [PATCH 060/205] feat: auto set against accounts for value pairs --- .../doctype/journal_entry/journal_entry.py | 43 ++++++++++++++----- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index fb7ede3e89..eb9c7c74ca 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -686,11 +686,40 @@ class JournalEntry(AccountsController): against_account = frappe.db.get_value(d.reference_type, d.reference_name, against_type.lower()) d.against_type = against_type - d.against_account = against_account d.against_account_link = against_account else: + self.get_debited_credited_accounts() + if len(self.accounts_credited) > 1 and len(self.accounts_debited) > 1: + self.auto_set_against_accounts() + return self.get_against_accounts() + def auto_set_against_accounts(self): + for i in range(0, len(self.accounts), 2): + acc = self.accounts[i] + against_acc = self.accounts[i + 1] + if acc.debit_in_account_currency > 0: + current_val = acc.debit_in_account_currency * flt(acc.exchange_rate) + against_val = against_acc.credit_in_account_currency * flt(against_acc.exchange_rate) + else: + current_val = acc.credit_in_account_currency * flt(acc.exchange_rate) + against_val = against_acc.debit_in_account_currency * flt(against_acc.exchange_rate) + + if current_val == against_val: + acc.against_type = against_acc.party_type or "Account" + against_acc.against_type = acc.party_type or "Account" + + acc.against_account_link = against_acc.party or against_acc.account + against_acc.against_account_link = acc.party or acc.account + else: + frappe.msgprint( + _( + "Unable to automatically determine {0} accounts. Set them up in the {1} table if needed." + ).format(frappe.bold("against"), frappe.bold("Accounting Entries")), + alert=True, + ) + break + def get_against_accounts(self): self.against_accounts = [] self.split_account = {} @@ -698,14 +727,7 @@ class JournalEntry(AccountsController): if self.separate_against_account_entries: no_of_credited_acc, no_of_debited_acc = len(self.accounts_credited), len(self.accounts_debited) - if no_of_credited_acc > 1 and no_of_debited_acc > 1: - frappe.msgprint( - _( - "Unable to automatically determine {0} accounts. Set them up in the {1} table if needed." - ).format(frappe.bold("against"), frappe.bold("Accounting Entries")), - alert=True, - ) - elif no_of_credited_acc <= 1 and no_of_debited_acc <= 1: + if no_of_credited_acc <= 1 and no_of_debited_acc <= 1: self.set_against_accounts_for_single_dr_cr() self.separate_against_account_entries = 0 elif no_of_credited_acc == 1: @@ -972,8 +994,7 @@ class JournalEntry(AccountsController): gl_dict.update( { "against_type": d.against_type, - "against": d.against_account, - "against_link": d.against_account, + "against_link": d.against_account_link, } ) gl_map.append(gl_dict) From 11190aac4c8ac6897c989dd4478b05d85d08fe4c Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Sun, 3 Dec 2023 22:35:01 +0530 Subject: [PATCH 061/205] fix: unhide against type field --- .../journal_entry_account/journal_entry_account.json | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json index 2b423ac51d..01006bd3db 100644 --- a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json +++ b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json @@ -294,16 +294,14 @@ { "fieldname": "against_type", "fieldtype": "Link", - "hidden": 1, "label": "Against Type", - "options": "DocType", - "print_hide": 1 + "options": "DocType" } ], "idx": 1, "istable": 1, "links": [], - "modified": "2023-11-23 11:44:25.841187", + "modified": "2023-12-02 23:21:22.205409", "modified_by": "Administrator", "module": "Accounts", "name": "Journal Entry Account", From 262cafc430cc55ac08ac5dc5bd297e94b06ad126 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Sun, 3 Dec 2023 22:36:54 +0530 Subject: [PATCH 062/205] fix: query for against types --- .../doctype/journal_entry/journal_entry.js | 25 +++++++++++++++++++ .../doctype/journal_entry/journal_entry.py | 7 ++++++ 2 files changed, 32 insertions(+) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.js b/erpnext/accounts/doctype/journal_entry/journal_entry.js index 9684a0d9d1..e1b436106a 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.js +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.js @@ -220,6 +220,16 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro return erpnext.journal_entry.account_query(me.frm); }); + me.frm.set_query("against_account_link", "accounts", function(doc, cdt, cdn) { + return erpnext.journal_entry.against_account_query(me.frm); + }); + + me.frm.set_query("against_type", "accounts", function(){ + return { + query: "erpnext.accounts.doctype.journal_entry.journal_entry.get_against_type", + } + }) + me.frm.set_query("party_type", "accounts", function(doc, cdt, cdn) { const row = locals[cdt][cdn]; @@ -591,6 +601,21 @@ $.extend(erpnext.journal_entry, { return { filters: filters }; }, + against_account_query: function(frm) { + if (frm.doc.against_type != "Account"){ + return { filters: {} }; + } + else { + let filters = { company: frm.doc.company, is_group: 0 }; + if(!frm.doc.multi_currency) { + $.extend(filters, { + account_currency: ['in', [frappe.get_doc(":Company", frm.doc.company).default_currency, null]] + }); + } + return { filters: filters }; + } + }, + reverse_journal_entry: function() { frappe.model.open_mapped_doc({ method: "erpnext.accounts.doctype.journal_entry.journal_entry.make_reverse_journal_entry", diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index eb9c7c74ca..e30e780bb6 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -1657,3 +1657,10 @@ def make_reverse_journal_entry(source_name, target_doc=None): ) return doclist + + +@frappe.whitelist() +def get_against_type(doctype, txt, searchfield, start, page_len, filters): + against_types = frappe.db.get_list("Party Type", pluck="name") + ["Account"] + doctype = frappe.qb.DocType("DocType") + return frappe.qb.from_(doctype).select(doctype.name).where(doctype.name.isin(against_types)).run() From 4918aeb4c64b22c8e6a09fac1661cf7e96114ce2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernd=20Oliver=20S=C3=BCnderhauf?= <46800703+bosue@users.noreply.github.com> Date: Tue, 14 Nov 2023 19:43:26 +0100 Subject: [PATCH 063/205] refactor: Consolidate duplicate zero-quantity transaction Items checks. --- .../request_for_quotation/request_for_quotation.py | 1 + erpnext/buying/utils.py | 8 -------- erpnext/controllers/accounts_controller.py | 12 +++++++----- erpnext/controllers/selling_controller.py | 6 +----- erpnext/stock/doctype/stock_entry/stock_entry.py | 5 +---- 5 files changed, 10 insertions(+), 22 deletions(-) diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py index eea8cd5cc8..e4479ef608 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py @@ -65,6 +65,7 @@ class RequestforQuotation(BuyingController): def validate(self): self.validate_duplicate_supplier() self.validate_supplier_list() + super(RequestforQuotation, self).validate_qty_is_not_zero() validate_for_items(self) super(RequestforQuotation, self).set_qty_as_per_stock_uom() self.update_email_id() diff --git a/erpnext/buying/utils.py b/erpnext/buying/utils.py index 8b7b6940ca..61e5e6a1c7 100644 --- a/erpnext/buying/utils.py +++ b/erpnext/buying/utils.py @@ -42,16 +42,8 @@ def update_last_purchase_rate(doc, is_submit) -> None: def validate_for_items(doc) -> None: - from erpnext.controllers.accounts_controller import InvalidQtyError - items = [] for d in doc.get("items"): - if not d.qty: - if doc.doctype == "Purchase Receipt" and d.rejected_qty: - continue - message = _("Please enter quantity for Item {0}").format(d.item_code) - frappe.throw(message, InvalidQtyError) - set_stock_levels(row=d) # update with latest quantities item = validate_item_and_get_basic_data(row=d) validate_stock_item_warehouse(row=d, item=item) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 1b8f66c897..09bcea97ea 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -915,13 +915,15 @@ class AccountsController(TransactionBase): return flt(args.get(field, 0) / self.get("conversion_rate", 1)) def validate_qty_is_not_zero(self): - if self.doctype == "Purchase Receipt": - return - for item in self.items: + if self.doctype == "Purchase Receipt" and item.rejected_qty: + continue + if not flt(item.qty): frappe.throw( - msg=_("Row #{0}: Item quantity cannot be zero").format(item.idx), + msg=_("Row #{0}: Quantity for Item {1} cannot be zero.").format( + item.idx, frappe.bold(item.item_code) + ), title=_("Invalid Quantity"), exc=InvalidQtyError, ) @@ -3019,7 +3021,7 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil def validate_quantity(child_item, new_data): if not flt(new_data.get("qty")): frappe.throw( - _("Row # {0}: Quantity for Item {1} cannot be zero").format( + _("Row #{0}: Quantity for Item {1} cannot be zero.").format( new_data.get("idx"), frappe.bold(new_data.get("item_code")) ), title=_("Invalid Qty"), diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index d6e3ee25a9..3bc054f099 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -7,7 +7,7 @@ from frappe import _, bold, throw from frappe.utils import cint, flt, get_link_to_form, nowtime from erpnext.accounts.party import render_address -from erpnext.controllers.accounts_controller import InvalidQtyError, get_taxes_and_charges +from erpnext.controllers.accounts_controller import get_taxes_and_charges from erpnext.controllers.sales_and_purchase_return import get_rate_for_return from erpnext.controllers.stock_controller import StockController from erpnext.stock.doctype.item.item import set_item_default @@ -295,10 +295,6 @@ class SellingController(StockController): def get_item_list(self): il = [] for d in self.get("items"): - if d.qty is None: - message = _("Row {0}: Qty is mandatory").format(d.idx) - frappe.throw(message, InvalidQtyError) - if self.has_product_bundle(d.item_code): for p in self.get("packed_items"): if p.parent_detail_docname == d.name and p.parent_item == d.item_code: diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 37a80be0e3..e69489890f 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -24,7 +24,6 @@ from frappe.utils import ( import erpnext from erpnext.accounts.general_ledger import process_gl_map -from erpnext.controllers.accounts_controller import InvalidQtyError from erpnext.controllers.taxes_and_totals import init_landed_taxes_and_totals from erpnext.manufacturing.doctype.bom.bom import add_additional_cost, validate_bom_no from erpnext.setup.doctype.brand.brand import get_brand_defaults @@ -389,10 +388,8 @@ class StockEntry(StockController): frappe.delete_doc("Stock Entry", d.name) def set_transfer_qty(self): + self.validate_qty_is_not_zero() for item in self.get("items"): - if not flt(item.qty): - message = _("Row {0}: Qty is mandatory").format(item.idx) - frappe.throw(message, InvalidQtyError, title=_("Zero quantity")) if not flt(item.conversion_factor): frappe.throw(_("Row {0}: UOM Conversion Factor is mandatory").format(item.idx)) item.transfer_qty = flt( From 3688d9412e03a993f1d4067ac4f95d787379460d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernd=20Oliver=20S=C3=BCnderhauf?= <46800703+bosue@users.noreply.github.com> Date: Sun, 3 Dec 2023 22:45:38 +0100 Subject: [PATCH 064/205] chore: Adapt translations to reworded message. --- erpnext/translations/af.csv | 3 +-- erpnext/translations/am.csv | 3 +-- erpnext/translations/ar.csv | 3 +-- erpnext/translations/bg.csv | 3 +-- erpnext/translations/bn.csv | 3 +-- erpnext/translations/bs.csv | 3 +-- erpnext/translations/ca.csv | 3 +-- erpnext/translations/cs.csv | 3 +-- erpnext/translations/cz.csv | 1 - erpnext/translations/da.csv | 3 +-- erpnext/translations/de.csv | 3 +-- erpnext/translations/el.csv | 3 +-- erpnext/translations/es-PE.csv | 1 - erpnext/translations/es.csv | 3 +-- erpnext/translations/es_pe.csv | 1 - erpnext/translations/et.csv | 3 +-- erpnext/translations/fa.csv | 3 +-- erpnext/translations/fi.csv | 3 +-- erpnext/translations/fr.csv | 3 +-- erpnext/translations/gu.csv | 3 +-- erpnext/translations/he.csv | 3 +-- erpnext/translations/hi.csv | 3 +-- erpnext/translations/hr.csv | 3 +-- erpnext/translations/hu.csv | 3 +-- erpnext/translations/id.csv | 3 +-- erpnext/translations/is.csv | 3 +-- erpnext/translations/it.csv | 3 +-- erpnext/translations/ja.csv | 3 +-- erpnext/translations/km.csv | 3 +-- erpnext/translations/kn.csv | 3 +-- erpnext/translations/ko.csv | 3 +-- erpnext/translations/ku.csv | 3 +-- erpnext/translations/lo.csv | 3 +-- erpnext/translations/lt.csv | 3 +-- erpnext/translations/lv.csv | 3 +-- erpnext/translations/mk.csv | 3 +-- erpnext/translations/ml.csv | 3 +-- erpnext/translations/mr.csv | 3 +-- erpnext/translations/ms.csv | 3 +-- erpnext/translations/my.csv | 3 +-- erpnext/translations/nl.csv | 3 +-- erpnext/translations/no.csv | 3 +-- erpnext/translations/pl.csv | 3 +-- erpnext/translations/ps.csv | 3 +-- erpnext/translations/pt-BR.csv | 2 -- erpnext/translations/pt.csv | 3 +-- erpnext/translations/ro.csv | 3 +-- erpnext/translations/ru.csv | 3 +-- erpnext/translations/rw.csv | 3 +-- erpnext/translations/si.csv | 3 +-- erpnext/translations/sk.csv | 3 +-- erpnext/translations/sl.csv | 3 +-- erpnext/translations/sq.csv | 3 +-- erpnext/translations/sr.csv | 3 +-- erpnext/translations/sv.csv | 3 +-- erpnext/translations/sw.csv | 3 +-- erpnext/translations/ta.csv | 3 +-- erpnext/translations/te.csv | 3 +-- erpnext/translations/th.csv | 3 +-- erpnext/translations/tr.csv | 3 +-- erpnext/translations/uk.csv | 3 +-- erpnext/translations/ur.csv | 3 +-- erpnext/translations/uz.csv | 3 +-- erpnext/translations/vi.csv | 3 +-- erpnext/translations/zh-TW.csv | 1 - erpnext/translations/zh.csv | 3 +-- erpnext/translations/zh_tw.csv | 3 +-- 67 files changed, 62 insertions(+), 130 deletions(-) diff --git a/erpnext/translations/af.csv b/erpnext/translations/af.csv index ee77d98948..9c995e1185 100644 --- a/erpnext/translations/af.csv +++ b/erpnext/translations/af.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Ry {0}: Stel asb. Belastingvrystelling in verkoopsbelasting en heffings in, Row {0}: Please set the Mode of Payment in Payment Schedule,Ry {0}: Stel die modus van betaling in die betalingskedule in, Row {0}: Please set the correct code on Mode of Payment {1},Ry {0}: Stel die korrekte kode in op die manier van betaling {1}, -Row {0}: Qty is mandatory,Ry {0}: Aantal is verpligtend, Row {0}: Quality Inspection rejected for item {1},Ry {0}: Gehalte-inspeksie verwerp vir item {1}, Row {0}: UOM Conversion Factor is mandatory,Ry {0}: UOM Gesprekfaktor is verpligtend, Row {0}: select the workstation against the operation {1},Ry {0}: kies die werkstasie teen die operasie {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Uitgawe tipe., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Dit lyk asof daar 'n probleem met die bediener se streepkonfigurasie is. In geval van versuim, sal die bedrag terugbetaal word na u rekening.", Item Reported,Item Gerapporteer, Item listing removed,Itemlys is verwyder, -Item quantity can not be zero,Item hoeveelheid kan nie nul wees nie, Item taxes updated,Itembelasting opgedateer, Item {0}: {1} qty produced. ,Item {0}: {1} hoeveelheid geproduseer., Joining Date can not be greater than Leaving Date,Aansluitingsdatum kan nie groter wees as die vertrekdatum nie, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Ry # {0}: Kostesentrum {1} behoort nie aan die maatskappy {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Ry # {0}: Bewerking {1} is nie voltooi vir {2} aantal voltooide goedere in werkorde {3}. Opdateer asseblief operasionele status via Job Card {4}., Row #{0}: Payment document is required to complete the transaction,Ry # {0}: Betaaldokument is nodig om die transaksie te voltooi, +Row #{0}: Quantity for Item {1} cannot be zero.,Ry # {0}: Hoeveelheid vir item {1} kan nie nul wees nie., Row #{0}: Serial No {1} does not belong to Batch {2},Ry # {0}: reeksnommer {1} behoort nie aan groep {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Ry # {0}: Die einddatum van die diens kan nie voor die inhandigingsdatum van die faktuur wees nie, Row #{0}: Service Start Date cannot be greater than Service End Date,Ry # {0}: Diens se begindatum kan nie groter wees as die einddatum van die diens nie, diff --git a/erpnext/translations/am.csv b/erpnext/translations/am.csv index a5f09a7488..4abdf7b0c2 100644 --- a/erpnext/translations/am.csv +++ b/erpnext/translations/am.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,ረድፍ {0}: እባክዎ በሽያጭ ግብሮች እና ክፍያዎች ውስጥ ባለው የግብር ነጻነት ምክንያት ያዘጋጁ።, Row {0}: Please set the Mode of Payment in Payment Schedule,ረድፍ {0}: - እባክዎ የክፍያ አፈፃፀም ሁኔታን በክፍያ መርሃግብር ያዘጋጁ።, Row {0}: Please set the correct code on Mode of Payment {1},ረድፍ {0}: እባክዎን ትክክለኛውን ኮድ በክፍያ ሁኔታ ላይ ያቀናብሩ {1}, -Row {0}: Qty is mandatory,ረድፍ {0}: ብዛት የግዴታ ነው, Row {0}: Quality Inspection rejected for item {1},ረድፍ {0}: የጥራት ምርመራ ለንጥል ውድቅ ተደርጓል {1}, Row {0}: UOM Conversion Factor is mandatory,ረድፍ {0}: UOM የልወጣ ምክንያት የግዴታ ነው, Row {0}: select the workstation against the operation {1},ረድፍ {0}: ከግዜው ላይ {1}, @@ -3461,7 +3460,6 @@ Issue Type.,የጉዳይ ዓይነት።, "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","በአገልጋዩ የሽቦ ውቅር ላይ ችግር ያለ ይመስላል. ካልተሳካ, ገንዘቡ ወደ ሂሳብዎ ተመላሽ ይደረጋል.", Item Reported,ንጥል ሪፖርት ተደርጓል።, Item listing removed,የንጥል ዝርዝር ተወግ removedል, -Item quantity can not be zero,የንጥል ብዛት ዜሮ መሆን አይችልም።, Item taxes updated,የንጥል ግብሮች ዘምነዋል, Item {0}: {1} qty produced. ,ንጥል {0}: {1} ኪቲ ተመርቷል።, Joining Date can not be greater than Leaving Date,የመቀላቀል ቀን ከቀናት ቀን በላይ መሆን አይችልም, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},ረድፍ # {0}: የዋጋ ማእከል {1} የኩባንያው አካል አይደለም {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,ረድፍ # {0}: ክወና {1} በስራ ትእዛዝ ውስጥ ለተጠናቀቁ ዕቃዎች {2} ኪራይ አልተጠናቀቀም {3}። እባክዎን የአሠራር ሁኔታን በ Job Card በኩል ያዘምኑ {4}።, Row #{0}: Payment document is required to complete the transaction,ረድፍ # {0}: - ግብይቱን ለማጠናቀቅ የክፍያ ሰነድ ያስፈልጋል።, +Row #{0}: Quantity for Item {1} cannot be zero.,ረድፍ # {0}: የንጥል {1} ብዛት ዜሮ መሆን አይችልም።, Row #{0}: Serial No {1} does not belong to Batch {2},ረድፍ # {0}: መለያ ቁጥር {1} የጡብ አካል አይደለም {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,ረድፍ # {0} የአገልግሎት የአገልግሎት ቀን የክፍያ መጠየቂያ መጠየቂያ ቀን ከማስታወቂያ በፊት መሆን አይችልም, Row #{0}: Service Start Date cannot be greater than Service End Date,ረድፍ # {0} የአገልግሎት የአገልግሎት ቀን ከአገልግሎት ማብቂያ ቀን በላይ መሆን አይችልም, diff --git a/erpnext/translations/ar.csv b/erpnext/translations/ar.csv index 195b9c7963..eac5186eda 100644 --- a/erpnext/translations/ar.csv +++ b/erpnext/translations/ar.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,الصف {0}: يرجى تعيين سبب الإعفاء الضريبي في ضرائب ورسوم المبيعات, Row {0}: Please set the Mode of Payment in Payment Schedule,الصف {0}: يرجى ضبط طريقة الدفع في جدول الدفع, Row {0}: Please set the correct code on Mode of Payment {1},الصف {0}: يرجى ضبط الكود الصحيح على طريقة الدفع {1}, -Row {0}: Qty is mandatory,الصف {0}: الكمية إلزامي, Row {0}: Quality Inspection rejected for item {1},الصف {0}: تم رفض فحص الجودة للعنصر {1}, Row {0}: UOM Conversion Factor is mandatory,الصف {0}: عامل تحويل UOM إلزامي\n
\nRow {0}: UOM Conversion Factor is mandatory, Row {0}: select the workstation against the operation {1},الصف {0}: حدد محطة العمل مقابل العملية {1}, @@ -3461,7 +3460,6 @@ Issue Type.,نوع القضية., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.",يبدو أن هناك مشكلة في تكوين شريطية للخادم. في حالة الفشل ، سيتم رد المبلغ إلى حسابك., Item Reported,البند المبلغ عنها, Item listing removed,إزالة عنصر القائمة, -Item quantity can not be zero,كمية البند لا يمكن أن يكون صفرا, Item taxes updated,الضرائب البند المحدثة, Item {0}: {1} qty produced. ,العنصر {0}: {1} الكمية المنتجة., Joining Date can not be greater than Leaving Date,تاريخ الانضمام لا يمكن أن يكون أكبر من تاريخ المغادرة, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},الصف # {0}: مركز التكلفة {1} لا ينتمي لشركة {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,الصف # {0}: العملية {1} لم تكتمل لـ {2} الكمية من السلع تامة الصنع في أمر العمل {3}. يرجى تحديث حالة التشغيل عبر بطاقة العمل {4}., Row #{0}: Payment document is required to complete the transaction,الصف # {0}: مطلوب مستند الدفع لإكمال الاجراء النهائي\n
\nRow #{0}: Payment document is required to complete the transaction, +Row #{0}: Quantity for Item {1} cannot be zero.,الصف # {0}: كمية البند {1} لا يمكن أن يكون صفرا, Row #{0}: Serial No {1} does not belong to Batch {2},الصف # {0}: الرقم التسلسلي {1} لا ينتمي إلى الدُفعة {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,الصف # {0}: لا يمكن أن يكون تاريخ انتهاء الخدمة قبل تاريخ ترحيل الفاتورة, Row #{0}: Service Start Date cannot be greater than Service End Date,الصف # {0}: لا يمكن أن يكون تاريخ بدء الخدمة أكبر من تاريخ انتهاء الخدمة, diff --git a/erpnext/translations/bg.csv b/erpnext/translations/bg.csv index c2bacf4f93..e29df96d34 100644 --- a/erpnext/translations/bg.csv +++ b/erpnext/translations/bg.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,"Ред {0}: Моля, задайте Причината за освобождаване от данъци в данъците и таксите върху продажбите", Row {0}: Please set the Mode of Payment in Payment Schedule,"Ред {0}: Моля, задайте Начин на плащане в Схема за плащане", Row {0}: Please set the correct code on Mode of Payment {1},"Ред {0}: Моля, задайте правилния код на Начин на плащане {1}", -Row {0}: Qty is mandatory,Row {0}: Кол е задължително, Row {0}: Quality Inspection rejected for item {1},Ред {0}: Проверка на качеството е отхвърлена за елемент {1}, Row {0}: UOM Conversion Factor is mandatory,Row {0}: мерна единица реализациите Factor е задължително, Row {0}: select the workstation against the operation {1},Ред {0}: изберете работната станция срещу операцията {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Тип издание, "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Изглежда, че има проблем с конфигурацията на лентата на сървъра. В случай на неуспех, сумата ще бъде възстановена в профила Ви.", Item Reported,Елементът е отчетен, Item listing removed,Списъкът на артикулите е премахнат, -Item quantity can not be zero,Количеството на артикула не може да бъде нула, Item taxes updated,Актуализираните данъци върху артикулите, Item {0}: {1} qty produced. ,Елемент {0}: {1} брой произведени., Joining Date can not be greater than Leaving Date,Дата на присъединяване не може да бъде по-голяма от Дата на напускане, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Ред № {0}: Център за разходи {1} не принадлежи на компания {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,"Ред № {0}: Операция {1} не е завършена за {2} количество готови продукти в работна поръчка {3}. Моля, актуализирайте състоянието на работа чрез Job Card {4}.", Row #{0}: Payment document is required to complete the transaction,Ред № {0}: За извършване на транзакцията е необходим платежен документ, +Row #{0}: Quantity for Item {1} cannot be zero.,Ред № {0}: Количеството на артикула {1} не може да бъде нула., Row #{0}: Serial No {1} does not belong to Batch {2},Ред № {0}: Пореден номер {1} не принадлежи на партида {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Ред № {0}: Крайната дата на услугата не може да бъде преди датата на публикуване на фактура, Row #{0}: Service Start Date cannot be greater than Service End Date,Ред № {0}: Началната дата на услугата не може да бъде по-голяма от крайната дата на услугата, diff --git a/erpnext/translations/bn.csv b/erpnext/translations/bn.csv index d7366e14ab..79e3704ed0 100644 --- a/erpnext/translations/bn.csv +++ b/erpnext/translations/bn.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,সারি {0}: বিক্রয় কর এবং চার্জে কর ছাড়ের কারণ নির্ধারণ করুন, Row {0}: Please set the Mode of Payment in Payment Schedule,সারি {0}: অনুগ্রহ করে অর্থ প্রদানের সময়সূচীতে অর্থের মোড সেট করুন, Row {0}: Please set the correct code on Mode of Payment {1},সারি {0}: অনুগ্রহ করে প্রদানের পদ্ধতিতে সঠিক কোডটি সেট করুন {1}, -Row {0}: Qty is mandatory,সারি {0}: Qty বাধ্যতামূলক, Row {0}: Quality Inspection rejected for item {1},সারি {0}: আইটেমের জন্য গুণ পরিদর্শন প্রত্যাখ্যান {1}, Row {0}: UOM Conversion Factor is mandatory,সারি {0}: UOM রূপান্তর ফ্যাক্টর বাধ্যতামূলক, Row {0}: select the workstation against the operation {1},সারি {0}: অপারেশন {1} বিরুদ্ধে ওয়ার্কস্টেশন নির্বাচন করুন, @@ -3461,7 +3460,6 @@ Issue Type.,ইস্যু প্রকার।, "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","মনে হচ্ছে যে সার্ভারের স্ট্রাপ কনফিগারেশনের সাথে একটি সমস্যা আছে ব্যর্থতার ক্ষেত্রে, এই পরিমাণটি আপনার অ্যাকাউন্টে ফেরত পাঠানো হবে।", Item Reported,আইটেম প্রতিবেদন করা, Item listing removed,আইটেমের তালিকা সরানো হয়েছে, -Item quantity can not be zero,আইটেম পরিমাণ শূন্য হতে পারে না, Item taxes updated,আইটেম ট্যাক্স আপডেট হয়েছে, Item {0}: {1} qty produced. ,আইটেম {0}: produced 1} কিউটি উত্পাদিত।, Joining Date can not be greater than Leaving Date,যোগদানের তারিখ ত্যাগের তারিখের চেয়ে বড় হতে পারে না, @@ -3632,6 +3630,7 @@ Row #{0}: Cannot delete item {1} which is assigned to customer's purchase order. Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subcontractor,সারি # {0}: সাবকন্ট্রাক্টরে কাঁচামাল সরবরাহ করার সময় সরবরাহকারী গুদাম নির্বাচন করতে পারবেন না, Row #{0}: Cost Center {1} does not belong to company {2},সারি # {0}: মূল্য কেন্দ্র {1 company সংস্থার নয়} 2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,সারি # {0}: কার্য অর্ডার {3 in সমাপ্ত পণ্যগুলির {2} কিউটির জন্য অপারেশন {1} সম্পন্ন হয় না} জব কার্ড {4 via এর মাধ্যমে ক্রিয়াকলাপের স্থিতি আপডেট করুন}, +Row #{0}: Quantity for Item {1} cannot be zero.,সারি # {0}: আইটেম {1} এর পরিমাণ শূন্য হতে পারে না, Row #{0}: Payment document is required to complete the transaction,সারি # {0}: লেনদেনটি সম্পূর্ণ করতে পেমেন্ট ডকুমেন্টের প্রয়োজন, Row #{0}: Serial No {1} does not belong to Batch {2},সারি # {0}: ক্রমিক নং {1 B ব্যাচ belong 2 belong এর সাথে সম্পর্কিত নয়, Row #{0}: Service End Date cannot be before Invoice Posting Date,সারি # {0}: পরিষেবা শেষ হওয়ার তারিখ চালানের পোস্টের তারিখের আগে হতে পারে না, diff --git a/erpnext/translations/bs.csv b/erpnext/translations/bs.csv index df4083eed6..a3027db93d 100644 --- a/erpnext/translations/bs.csv +++ b/erpnext/translations/bs.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Red {0}: Podesite razlog oslobađanja od poreza u porezima i naknadama na promet, Row {0}: Please set the Mode of Payment in Payment Schedule,Red {0}: Molimo postavite Način plaćanja u Rasporedu plaćanja, Row {0}: Please set the correct code on Mode of Payment {1},Red {0}: Molimo postavite ispravan kod na Način plaćanja {1}, -Row {0}: Qty is mandatory,Red {0}: Količina je obvezno, Row {0}: Quality Inspection rejected for item {1},Red {0}: Odbačena inspekcija kvaliteta za stavku {1}, Row {0}: UOM Conversion Factor is mandatory,Red {0}: UOM Faktor konverzije je obavezno, Row {0}: select the workstation against the operation {1},Red {0}: izaberite radnu stanicu protiv operacije {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Vrsta izdanja, "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Čini se da postoji problem sa konfiguracijom trake servera. U slučaju neuspeha, iznos će biti vraćen na vaš račun.", Item Reported,Stavka prijavljena, Item listing removed,Popis predmeta je uklonjen, -Item quantity can not be zero,Količina predmeta ne može biti jednaka nuli, Item taxes updated,Ažurirani su porezi na artikle, Item {0}: {1} qty produced. ,Stavka {0}: {1} proizvedeno., Joining Date can not be greater than Leaving Date,Datum pridruživanja ne može biti veći od Datum napuštanja, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Redak # {0}: Troškovi {1} ne pripada kompaniji {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Red # {0}: Operacija {1} nije dovršena za {2} broj gotovih proizvoda u radnom nalogu {3}. Ažurirajte status rada putem Job Card {4}., Row #{0}: Payment document is required to complete the transaction,Redak broj {0}: Za završetak transakcije potreban je dokument o plaćanju, +Row #{0}: Quantity for Item {1} cannot be zero.,Redak broj {0}: Količina predmeta {1} ne može biti jednaka nuli., Row #{0}: Serial No {1} does not belong to Batch {2},Red # {0}: Serijski br. {1} ne pripada grupi {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Redak broj {0}: Datum završetka usluge ne može biti prije datuma knjiženja fakture, Row #{0}: Service Start Date cannot be greater than Service End Date,Redak broj {0}: Datum početka usluge ne može biti veći od datuma završetka usluge, diff --git a/erpnext/translations/ca.csv b/erpnext/translations/ca.csv index b3cf2c5fe1..1c07e67ff5 100644 --- a/erpnext/translations/ca.csv +++ b/erpnext/translations/ca.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Fila {0}: especifiqueu la raó d’exempció d’impostos en els impostos i els càrrecs de venda, Row {0}: Please set the Mode of Payment in Payment Schedule,Fila {0}: estableix el mode de pagament a la planificació de pagaments, Row {0}: Please set the correct code on Mode of Payment {1},Fila {0}: configureu el codi correcte al mode de pagament {1}, -Row {0}: Qty is mandatory,Fila {0}: Quantitat és obligatori, Row {0}: Quality Inspection rejected for item {1},Fila {0}: s'ha rebutjat la inspecció de qualitat per a l'element {1}, Row {0}: UOM Conversion Factor is mandatory,Fila {0}: UOM factor de conversió és obligatori, Row {0}: select the workstation against the operation {1},Fila {0}: seleccioneu l'estació de treball contra l'operació {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Tipus de problema., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Sembla que hi ha un problema amb la configuració de la xarxa del servidor. En cas de fracàs, l'import es reemborsarà al vostre compte.", Item Reported,Article reportat, Item listing removed,S'ha eliminat la llista d'elements, -Item quantity can not be zero,La quantitat d’element no pot ser zero, Item taxes updated,Impostos d’articles actualitzats, Item {0}: {1} qty produced. ,Element {0}: {1} quantitat produïda., Joining Date can not be greater than Leaving Date,La data de combinació no pot ser superior a la data de sortida, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Fila # {0}: el centre de cost {1} no pertany a l'empresa {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Fila # {0}: L'operació {1} no es completa per a {2} la quantitat de productes acabats en l'Ordre de Treball {3}. Actualitzeu l'estat de l'operació mitjançant la targeta de treball {4}., Row #{0}: Payment document is required to complete the transaction,Fila # {0}: el document de pagament és necessari per completar la transacció, +Row #{0}: Quantity for Item {1} cannot be zero.,Fila # {0}: La quantitat d'element {1} no pot ser zero., Row #{0}: Serial No {1} does not belong to Batch {2},Fila # {0}: el número de sèrie {1} no pertany a la llista de lots {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Fila # {0}: la data de finalització del servei no pot ser anterior a la data de publicació de la factura, Row #{0}: Service Start Date cannot be greater than Service End Date,Fila # {0}: la data d'inici del servei no pot ser superior a la data de finalització del servei, diff --git a/erpnext/translations/cs.csv b/erpnext/translations/cs.csv index b6deaa46d8..2e28cec8ce 100644 --- a/erpnext/translations/cs.csv +++ b/erpnext/translations/cs.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Řádek {0}: Nastavte prosím na důvod osvobození od daně v daních z prodeje a poplatcích, Row {0}: Please set the Mode of Payment in Payment Schedule,Řádek {0}: Nastavte prosím platební režim v plánu plateb, Row {0}: Please set the correct code on Mode of Payment {1},Řádek {0}: Nastavte prosím správný kód v platebním režimu {1}, -Row {0}: Qty is mandatory,Row {0}: Množství je povinný, Row {0}: Quality Inspection rejected for item {1},Řádek {0}: Inspekce kvality zamítnuta pro položku {1}, Row {0}: UOM Conversion Factor is mandatory,Řádek {0}: UOM Konverzní faktor je povinné, Row {0}: select the workstation against the operation {1},Řádek {0}: vyberte pracovní stanici proti operaci {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Typ problému., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Zdá se, že je problém s konfigurací proužku serveru. V případě selhání bude částka vrácena na váš účet.", Item Reported,Hlášená položka, Item listing removed,Seznam položek byl odstraněn, -Item quantity can not be zero,Množství položky nemůže být nula, Item taxes updated,Daň z položek byla aktualizována, Item {0}: {1} qty produced. ,Položka {0}: {1} vyrobeno množství., Joining Date can not be greater than Leaving Date,Datum připojení nesmí být větší než datum opuštění, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Řádek # {0}: Nákladové středisko {1} nepatří společnosti {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Řádek # {0}: Operace {1} není dokončena pro {2} množství hotového zboží v objednávce {3}. Aktualizujte prosím provozní stav pomocí Job Card {4}., Row #{0}: Payment document is required to complete the transaction,Řádek # {0}: K dokončení transakce je vyžadován platební doklad, +Row #{0}: Quantity for Item {1} cannot be zero.,Řádek # {0}: Množství položky {1} nemůže být nula., Row #{0}: Serial No {1} does not belong to Batch {2},Řádek # {0}: Sériové číslo {1} nepatří do dávky {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Řádek # {0}: Datum ukončení služby nesmí být před datem účtování faktury, Row #{0}: Service Start Date cannot be greater than Service End Date,Řádek # {0}: Datum zahájení služby nesmí být větší než datum ukončení služby, diff --git a/erpnext/translations/cz.csv b/erpnext/translations/cz.csv index 96de062059..a356a0721a 100644 --- a/erpnext/translations/cz.csv +++ b/erpnext/translations/cz.csv @@ -1101,7 +1101,6 @@ Contract,Smlouva, Disabled,Vypnuto, UOM coversion factor required for UOM: {0} in Item: {1},UOM coversion faktor potřebný k nerozpuštěných: {0} v bodě: {1} Indirect Expenses,Nepřímé náklady, -Row {0}: Qty is mandatory,Row {0}: Množství je povinny, Agriculture,Zemědělstvy, Your Products or Services,Vaše Produkty nebo Služby, Mode of Payment,Způsob platby, diff --git a/erpnext/translations/da.csv b/erpnext/translations/da.csv index 4bcc307583..2550f351d4 100644 --- a/erpnext/translations/da.csv +++ b/erpnext/translations/da.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Række {0}: Angiv venligst skattefritagelsesårsag i moms og afgifter, Row {0}: Please set the Mode of Payment in Payment Schedule,Række {0}: Angiv betalingsmåde i betalingsplan, Row {0}: Please set the correct code on Mode of Payment {1},Række {0}: Angiv den korrekte kode på betalingsmetode {1}, -Row {0}: Qty is mandatory,Række {0}: Antal er obligatorisk, Row {0}: Quality Inspection rejected for item {1},Række {0}: Kvalitetskontrol afvist for vare {1}, Row {0}: UOM Conversion Factor is mandatory,Række {0}: Enhedskode-konverteringsfaktor er obligatorisk, Row {0}: select the workstation against the operation {1},Række {0}: Vælg arbejdsstationen imod operationen {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Udgavetype., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.",Det ser ud som om der er et problem med serverens stribekonfiguration. I tilfælde af fejl bliver beløbet refunderet til din konto., Item Reported,Emne rapporteret, Item listing removed,Elementlisten er fjernet, -Item quantity can not be zero,Varemængde kan ikke være nul, Item taxes updated,Vareafgift opdateret, Item {0}: {1} qty produced. ,Vare {0}: {1} produceret antal., Joining Date can not be greater than Leaving Date,Deltagelsesdato kan ikke være større end forladelsesdato, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Række nr. {0}: Omkostningscenter {1} hører ikke til firmaet {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Række nr. {0}: Betjening {1} er ikke afsluttet for {2} antal færdige varer i arbejdsordre {3}. Opdater driftsstatus via Jobkort {4}., Row #{0}: Payment document is required to complete the transaction,Række nr. {0}: Betalingsdokument er påkrævet for at gennemføre transaktionen, +Row #{0}: Quantity for Item {1} cannot be zero.,Række nr. {0}: Varemængde for vare {1} kan ikke være nul., Row #{0}: Serial No {1} does not belong to Batch {2},Række nr. {0}: Serienummer {1} hører ikke til batch {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Række nr. {0}: Service-slutdato kan ikke være før fakturaens udgivelsesdato, Row #{0}: Service Start Date cannot be greater than Service End Date,Række nr. {0}: Service-startdato kan ikke være større end service-slutdato, diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv index 2745d4da12..f6fc993200 100644 --- a/erpnext/translations/de.csv +++ b/erpnext/translations/de.csv @@ -2287,7 +2287,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Zeile {0}: Bitte setzen Sie den Steuerbefreiungsgrund in den Umsatzsteuern und -gebühren, Row {0}: Please set the Mode of Payment in Payment Schedule,Zeile {0}: Bitte legen Sie die Zahlungsart im Zahlungsplan fest, Row {0}: Please set the correct code on Mode of Payment {1},Zeile {0}: Bitte geben Sie den richtigen Code für die Zahlungsweise ein {1}, -Row {0}: Qty is mandatory,Zeile {0}: Menge ist zwingend erforderlich, Row {0}: Quality Inspection rejected for item {1},Zeile {0}: Qualitätsprüfung für Artikel {1} abgelehnt, Row {0}: UOM Conversion Factor is mandatory,Zeile {0}: Umrechnungsfaktor für Maßeinheit ist zwingend erforderlich, Row {0}: select the workstation against the operation {1},Zeile {0}: Wählen Sie die Arbeitsstation für die Operation {1} aus., @@ -3481,7 +3480,6 @@ Issue Type.,Problemtyp., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Es scheint, dass ein Problem mit der Stripe-Konfiguration des Servers vorliegt. Im Falle eines Fehlers wird der Betrag Ihrem Konto gutgeschrieben.", Item Reported,Gegenstand gemeldet, Item listing removed,Objektliste entfernt, -Item quantity can not be zero,Artikelmenge kann nicht Null sein, Item taxes updated,Artikelsteuern aktualisiert, Item {0}: {1} qty produced. ,Artikel {0}: {1} produzierte Menge., Joining Date can not be greater than Leaving Date,Das Beitrittsdatum darf nicht größer als das Austrittsdatum sein, @@ -3655,6 +3653,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Zeile {0}: Kostenstelle {1} gehört nicht zu Firma {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Zeile {0}: Vorgang {1} ist für {2} Fertigwarenmenge im Fertigungsauftrag {3} nicht abgeschlossen. Bitte aktualisieren Sie den Betriebsstatus über die Jobkarte {4}., Row #{0}: Payment document is required to complete the transaction,"Zeile {0}: Der Zahlungsbeleg ist erforderlich, um die Transaktion abzuschließen", +Row #{0}: Quantity for Item {1} cannot be zero.,Zeile {0}: Artikelmenge {1} kann nicht Null sein., Row #{0}: Serial No {1} does not belong to Batch {2},Zeile {0}: Seriennummer {1} gehört nicht zu Charge {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Zeile {0}: Das Service-Enddatum darf nicht vor dem Rechnungsbuchungsdatum liegen, Row #{0}: Service Start Date cannot be greater than Service End Date,Zeile {0}: Das Servicestartdatum darf nicht höher als das Serviceenddatum sein, diff --git a/erpnext/translations/el.csv b/erpnext/translations/el.csv index e67eaffc69..b90a10dd6f 100644 --- a/erpnext/translations/el.csv +++ b/erpnext/translations/el.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Σειρά {0}: Ρυθμίστε τον Φορολογικής Εξαίρεσης για τους Φόρους Πώλησης και τα Τέλη, Row {0}: Please set the Mode of Payment in Payment Schedule,Σειρά {0}: Ρυθμίστε τον τρόπο πληρωμής στο χρονοδιάγραμμα πληρωμών, Row {0}: Please set the correct code on Mode of Payment {1},Σειρά {0}: Ρυθμίστε τον σωστό κώδικα στη μέθοδο πληρωμής {1}, -Row {0}: Qty is mandatory,Γραμμή {0}: η ποσότητα είναι απαραίτητη, Row {0}: Quality Inspection rejected for item {1},Σειρά {0}: Η επιθεώρηση ποιότητας απορρίφθηκε για το στοιχείο {1}, Row {0}: UOM Conversion Factor is mandatory,Σειρά {0}: UOM Συντελεστής μετατροπής είναι υποχρεωτική, Row {0}: select the workstation against the operation {1},Γραμμή {0}: επιλέξτε τη θέση εργασίας σε σχέση με τη λειτουργία {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Τύπος έκδοσης., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Φαίνεται ότι υπάρχει ένα πρόβλημα με τη διαμόρφωση της λωρίδας του διακομιστή. Σε περίπτωση αποτυχίας, το ποσό θα επιστραφεί στο λογαριασμό σας.", Item Reported,Στοιχείο Αναφέρεται, Item listing removed,Η καταχώριση αντικειμένου καταργήθηκε, -Item quantity can not be zero,Η ποσότητα του στοιχείου δεν μπορεί να είναι μηδέν, Item taxes updated,Οι φόροι των στοιχείων ενημερώθηκαν, Item {0}: {1} qty produced. ,Στοιχείο {0}: {1} παράγεται., Joining Date can not be greater than Leaving Date,Η ημερομηνία σύνδεσης δεν μπορεί να είναι μεγαλύτερη από την ημερομηνία λήξης, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Σειρά # {0}: Το κέντρο κόστους {1} δεν ανήκει στην εταιρεία {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Σειρά # {0}: Η λειτουργία {1} δεν έχει ολοκληρωθεί για {2} ποσότητα τελικών προϊόντων στην Παραγγελία Εργασίας {3}. Ενημερώστε την κατάσταση λειτουργίας μέσω της κάρτας εργασίας {4}., Row #{0}: Payment document is required to complete the transaction,Γραμμή # {0}: Απαιτείται το έγγραφο πληρωμής για την ολοκλήρωση της συναλλαγής, +Row #{0}: Quantity for Item {1} cannot be zero.,Γραμμή # {0}: Η ποσότητα του στοιχείου {1} δεν μπορεί να είναι μηδέν, Row #{0}: Serial No {1} does not belong to Batch {2},Σειρά # {0}: Ο σειριακός αριθμός {1} δεν ανήκει στην Παρτίδα {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Σειρά # {0}: Η ημερομηνία λήξης υπηρεσίας δεν μπορεί να είναι πριν από την ημερομηνία αποστολής τιμολογίου, Row #{0}: Service Start Date cannot be greater than Service End Date,Σειρά # {0}: Η Ημερομηνία Έναρξης Υπηρεσίας δεν μπορεί να είναι μεγαλύτερη από την Ημερομηνία Λήξης Υπηρεσίας, diff --git a/erpnext/translations/es-PE.csv b/erpnext/translations/es-PE.csv index ed5d065b00..2e28e78d79 100644 --- a/erpnext/translations/es-PE.csv +++ b/erpnext/translations/es-PE.csv @@ -388,7 +388,6 @@ Maintenance Visit Purpose,Propósito de la Visita de Mantenimiento, No of Sent SMS,No. de SMS enviados, Stock Received But Not Billed,Inventario Recibido pero no facturados, Stores,Tiendas, -Row {0}: Qty is mandatory,Fila {0}: Cantidad es obligatorio, Report Type is mandatory,Tipo de informe es obligatorio, "System User (login) ID. If set, it will become default for all HR forms.","Usuario del Sistema (login )ID. Si se establece , será por defecto para todas las formas de Recursos Humanos." UOM Conversion factor is required in row {0},"El factor de conversión de la (UdM) Unidad de medida, es requerida en la linea {0}" diff --git a/erpnext/translations/es.csv b/erpnext/translations/es.csv index 0c90694f8f..681972e549 100644 --- a/erpnext/translations/es.csv +++ b/erpnext/translations/es.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Fila {0}: establezca el Motivo de exención de impuestos en Impuestos y cargos de ventas, Row {0}: Please set the Mode of Payment in Payment Schedule,Fila {0}: establezca el modo de pago en el calendario de pagos, Row {0}: Please set the correct code on Mode of Payment {1},Fila {0}: establezca el código correcto en Modo de pago {1}, -Row {0}: Qty is mandatory,Línea {0}: La cantidad es obligatoria, Row {0}: Quality Inspection rejected for item {1},Fila {0}: Inspección de calidad rechazada para el artículo {1}, Row {0}: UOM Conversion Factor is mandatory,Línea {0}: El factor de conversión de (UdM) es obligatorio, Row {0}: select the workstation against the operation {1},Fila {0}: seleccione la estación de trabajo contra la operación {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Tipo de problema., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Parece que hay un problema con la configuración de la banda del servidor. En caso de falla, la cantidad será reembolsada a su cuenta.", Item Reported,Artículo reportado, Item listing removed,Listado de artículos eliminado, -Item quantity can not be zero,La cantidad del artículo no puede ser cero, Item taxes updated,Impuestos de artículos actualizados, Item {0}: {1} qty produced. ,Elemento {0}: {1} cantidad producida., Joining Date can not be greater than Leaving Date,La fecha de incorporación no puede ser mayor que la fecha de salida, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Fila # {0}: el centro de costos {1} no pertenece a la compañía {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Fila # {0}: la operación {1} no se completa para {2} cantidad de productos terminados en la orden de trabajo {3}. Actualice el estado de la operación a través de la Tarjeta de trabajo {4}., Row #{0}: Payment document is required to complete the transaction,Fila # {0}: se requiere un documento de pago para completar la transacción, +Row #{0}: Quantity for Item {1} cannot be zero.,Fila # {0}: La cantidad del artículo {1} no puede ser cero., Row #{0}: Serial No {1} does not belong to Batch {2},Fila # {0}: El número de serie {1} no pertenece al lote {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Fila n.º {0}: la fecha de finalización del servicio no puede ser anterior a la fecha de contabilización de facturas, Row #{0}: Service Start Date cannot be greater than Service End Date,Fila n.º {0}: la fecha de inicio del servicio no puede ser mayor que la fecha de finalización del servicio, diff --git a/erpnext/translations/es_pe.csv b/erpnext/translations/es_pe.csv index 9b801e5882..405c02827b 100644 --- a/erpnext/translations/es_pe.csv +++ b/erpnext/translations/es_pe.csv @@ -310,7 +310,6 @@ Row {0}: Debit entry can not be linked with a {1},Fila {0}: Débito no puede vin Row {0}: Party Type and Party is required for Receivable / Payable account {1},Fila {0}: el tipo de entidad se requiere para las cuentas por cobrar/pagar {1}, Row {0}: Payment against Sales/Purchase Order should always be marked as advance,Fila {0}: El pago de Compra/Venta siempre debe estar marcado como anticipo, Row {0}: Please check 'Is Advance' against Account {1} if this is an advance entry.,"Fila {0}: Por favor, consulte ""¿Es Avance 'contra la Cuenta {1} si se trata de una entrada con antelación.", -Row {0}: Qty is mandatory,Fila {0}: Cantidad es obligatorio, Row {0}: {1} {2} does not match with {3},Fila {0}: {1} {2} no coincide con {3}, Row {0}:Start Date must be before End Date,Fila {0}: Fecha de inicio debe ser anterior Fecha de finalización, Rules for adding shipping costs.,Reglas para la adición de los gastos de envío ., diff --git a/erpnext/translations/et.csv b/erpnext/translations/et.csv index 69a89d9d22..4cd6753574 100644 --- a/erpnext/translations/et.csv +++ b/erpnext/translations/et.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Rida {0}: palun määrake käibemaksu ja lõivude maksuvabastuse põhjus, Row {0}: Please set the Mode of Payment in Payment Schedule,Rida {0}: määrake maksegraafikus makseviis, Row {0}: Please set the correct code on Mode of Payment {1},Rida {0}: seadke makserežiimis {1} õige kood, -Row {0}: Qty is mandatory,Row {0}: Kogus on kohustuslikuks, Row {0}: Quality Inspection rejected for item {1},Rida {0}: üksuse {1} kvaliteedikontroll lükati tagasi, Row {0}: UOM Conversion Factor is mandatory,Row {0}: UOM Conversion Factor on kohustuslik, Row {0}: select the workstation against the operation {1},Rida {0}: valige tööjaam operatsiooni vastu {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Väljaande tüüp., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Tundub, et serveri riba konfiguratsiooniga on probleem. Ebaõnnestumise korral tagastatakse summa teie kontole.", Item Reported,Teatatud üksusest, Item listing removed,Üksuse kirje eemaldati, -Item quantity can not be zero,Toote kogus ei saa olla null, Item taxes updated,Üksuse maksud värskendatud, Item {0}: {1} qty produced. ,Toode {0}: {1} toodetud kogus., Joining Date can not be greater than Leaving Date,Liitumiskuupäev ei saa olla suurem kui lahkumiskuupäev, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Rida # 0: kulukeskus {1} ei kuulu ettevõttele {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Rida # 0: operatsioon {1} ei ole lõpule viidud {2} töökäsus {3} olevate valmistoodete osas. Värskendage töö olekut töökaardi {4} kaudu., Row #{0}: Payment document is required to complete the transaction,Rida # 0: tehingu lõpuleviimiseks on vaja maksedokumenti, +Row #{0}: Quantity for Item {1} cannot be zero.,Rida # {0}: Toote {1} kogus ei saa olla null., Row #{0}: Serial No {1} does not belong to Batch {2},Rida # 0: seerianumber {1} ei kuulu partiisse {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Rida # {0}: teenuse lõppkuupäev ei saa olla enne arve saatmise kuupäeva, Row #{0}: Service Start Date cannot be greater than Service End Date,Rida # 0: teenuse alguskuupäev ei saa olla suurem kui teenuse lõppkuupäev, diff --git a/erpnext/translations/fa.csv b/erpnext/translations/fa.csv index cddabfb448..5f8fbd558a 100644 --- a/erpnext/translations/fa.csv +++ b/erpnext/translations/fa.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,ردیف {0}: لطفاً دلیل معافیت مالیاتی در مالیات و عوارض فروش را تعیین کنید, Row {0}: Please set the Mode of Payment in Payment Schedule,ردیف {0}: لطفاً نحوه پرداخت را در جدول پرداخت تنظیم کنید, Row {0}: Please set the correct code on Mode of Payment {1},ردیف {0}: لطفا کد صحیح را در حالت پرداخت {1} تنظیم کنید, -Row {0}: Qty is mandatory,ردیف {0}: تعداد الزامی است, Row {0}: Quality Inspection rejected for item {1},ردیف {0}: بازرسی کیفیت برای آیتم {1} رد شد, Row {0}: UOM Conversion Factor is mandatory,ردیف {0}: UOM عامل تبدیل الزامی است, Row {0}: select the workstation against the operation {1},ردیف {0}: ایستگاه کاری را در برابر عملیات انتخاب کنید {1}, @@ -3461,7 +3460,6 @@ Issue Type.,نوع مقاله., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.",به نظر می رسد یک مشکل با پیکربندی نوار خط سرور وجود دارد. در صورت خرابی، مقدار به حساب شما بازپرداخت خواهد شد., Item Reported,گزارش مورد, Item listing removed,لیست موارد حذف شد, -Item quantity can not be zero,مقدار کالا نمی تواند صفر باشد, Item taxes updated,مالیات مورد به روز شد, Item {0}: {1} qty produced. ,مورد {0}: {1 ty تولید شده است., Joining Date can not be greater than Leaving Date,تاریخ عضویت نمی تواند بیشتر از تاریخ ترک باشد, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},ردیف شماره {0: مرکز هزینه 1} متعلق به شرکت {2, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,ردیف شماره {0: عملیات {1 for برای کالاهای {2 پوند در سفارش کار 3 {کامل نشده است. لطفاً وضعیت عملکرد را از طریق کارت کار 4 update به روز کنید., Row #{0}: Payment document is required to complete the transaction,ردیف # {0}: برای تکمیل معامله ، سند پرداخت لازم است, +Row #{0}: Quantity for Item {1} cannot be zero.,ردیف # {0}: مقدار کالای {1} نمی تواند صفر باشد, Row #{0}: Serial No {1} does not belong to Batch {2},ردیف شماره {0: سریال شماره {1} متعلق به دسته {2 نیست, Row #{0}: Service End Date cannot be before Invoice Posting Date,ردیف شماره {0}: تاریخ پایان خدمت نمی تواند قبل از تاریخ ارسال فاکتور باشد, Row #{0}: Service Start Date cannot be greater than Service End Date,ردیف شماره {0}: تاریخ شروع سرویس نمی تواند بیشتر از تاریخ پایان سرویس باشد, diff --git a/erpnext/translations/fi.csv b/erpnext/translations/fi.csv index eae6053915..f412731777 100644 --- a/erpnext/translations/fi.csv +++ b/erpnext/translations/fi.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Rivi {0}: aseta verovapautusperusteeksi myyntiverot ja maksut, Row {0}: Please set the Mode of Payment in Payment Schedule,Rivi {0}: Aseta maksutapa maksuaikataulussa, Row {0}: Please set the correct code on Mode of Payment {1},Rivi {0}: Aseta oikea koodi Maksutilaan {1}, -Row {0}: Qty is mandatory,Rivillä {0}: Yksikkömäärä vaaditaan, Row {0}: Quality Inspection rejected for item {1},Rivi {0}: Tuotteen {1} laatutarkastus hylätty, Row {0}: UOM Conversion Factor is mandatory,Rivi {0}: UOM Muuntokerroin on pakollinen, Row {0}: select the workstation against the operation {1},Rivi {0}: valitse työasema operaatiota vastaan {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Julkaisutyyppi., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Näyttää siltä, että palvelimen raidakokoonpano on ongelma. Vahingossa summa palautetaan tilillesi.", Item Reported,Kohde ilmoitettu, Item listing removed,Tuotetiedot poistettu, -Item quantity can not be zero,Tuotteen määrä ei voi olla nolla, Item taxes updated,Tuoteverot päivitetty, Item {0}: {1} qty produced. ,Tuote {0}: {1} määrä tuotettu., Joining Date can not be greater than Leaving Date,Liittymispäivä ei voi olla suurempi kuin lähtöpäivä, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Rivi # {0}: Kustannuskeskus {1} ei kuulu yritykseen {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Rivi # {0}: Operaatiota {1} ei suoriteta {2} määrälle työjärjestyksessä {3} olevia valmiita tuotteita. Päivitä toimintatila työkortilla {4}., Row #{0}: Payment document is required to complete the transaction,Rivi # {0}: Maksutodistus vaaditaan tapahtuman suorittamiseksi, +Row #{0}: Quantity for Item {1} cannot be zero.,Rivi # {0}: Tuotteen {1} määrä ei voi olla nolla., Row #{0}: Serial No {1} does not belong to Batch {2},Rivi # {0}: Sarjanumero {1} ei kuulu erään {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Rivi # {0}: Palvelun lopetuspäivä ei voi olla ennen laskun lähettämispäivää, Row #{0}: Service Start Date cannot be greater than Service End Date,Rivi # {0}: Palvelun aloituspäivä ei voi olla suurempi kuin palvelun lopetuspäivä, diff --git a/erpnext/translations/fr.csv b/erpnext/translations/fr.csv index a7111234af..53a9027f9f 100644 --- a/erpnext/translations/fr.csv +++ b/erpnext/translations/fr.csv @@ -2111,7 +2111,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Ligne {0}: Définissez le motif d'exemption de taxe dans les taxes de vente et les frais., Row {0}: Please set the Mode of Payment in Payment Schedule,Ligne {0}: Veuillez définir le mode de paiement dans le calendrier de paiement., Row {0}: Please set the correct code on Mode of Payment {1},Ligne {0}: définissez le code correct sur le mode de paiement {1}., -Row {0}: Qty is mandatory,Ligne {0} : Qté obligatoire, Row {0}: Quality Inspection rejected for item {1},Ligne {0}: le contrôle qualité a été rejeté pour l'élément {1}., Row {0}: UOM Conversion Factor is mandatory,Ligne {0} : Facteur de Conversion nomenclature est obligatoire, Row {0}: select the workstation against the operation {1},Ligne {0}: sélectionnez le poste de travail en fonction de l'opération {1}, @@ -3152,7 +3151,6 @@ Issue Type.,Type de probleme., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Il semble qu'il y a un problème avec la configuration de Stripe sur le serveur. En cas d'erreur, le montant est remboursé sur votre compte.", Item Reported,Article rapporté, Item listing removed,Liste d'articles supprimée, -Item quantity can not be zero,La quantité d'article ne peut être nulle, Item taxes updated,Taxes sur les articles mises à jour, Item {0}: {1} qty produced. ,Article {0}: {1} quantité produite., Joining Date can not be greater than Leaving Date,La date d'adhésion ne peut pas être supérieure à la date de départ, @@ -3299,6 +3297,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Ligne # {0}: le centre de coûts {1} n'appartient pas à l'entreprise {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Ligne n ° {0}: l'opération {1} n'est pas terminée pour {2} quantité de produits finis dans l'ordre de fabrication {3}. Veuillez mettre à jour le statut de l'opération via la carte de travail {4}., Row #{0}: Payment document is required to complete the transaction,Ligne n ° {0}: Un document de paiement est requis pour effectuer la transaction., +Row #{0}: Quantity for Item {1} cannot be zero.,Ligne n° {0}: La quantité de l'article {1} ne peut être nulle, Row #{0}: Serial No {1} does not belong to Batch {2},Ligne # {0}: le numéro de série {1} n'appartient pas au lot {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Ligne # {0}: la date de fin du service ne peut pas être antérieure à la date de validation de la facture, Row #{0}: Service Start Date cannot be greater than Service End Date,Ligne # {0}: la date de début du service ne peut pas être supérieure à la date de fin du service, diff --git a/erpnext/translations/gu.csv b/erpnext/translations/gu.csv index 604ec411c4..c26adbd89d 100644 --- a/erpnext/translations/gu.csv +++ b/erpnext/translations/gu.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,પંક્તિ {0}: કૃપા કરીને વેચાણ વેરા અને શુલ્કમાં કર મુક્તિ કારણને સેટ કરો, Row {0}: Please set the Mode of Payment in Payment Schedule,પંક્તિ {0}: કૃપા કરીને ચુકવણી સૂચિમાં ચુકવણીનું મોડ સેટ કરો, Row {0}: Please set the correct code on Mode of Payment {1},પંક્તિ {0}: કૃપા કરીને ચુકવણીના મોડ પર સાચો કોડ સેટ કરો {1}, -Row {0}: Qty is mandatory,રો {0}: Qty ફરજિયાત છે, Row {0}: Quality Inspection rejected for item {1},પંક્તિ {0}: આઇટમ માટે જાત નિરીક્ષણ નકારેલ {1}, Row {0}: UOM Conversion Factor is mandatory,રો {0}: UOM રૂપાંતર ફેક્ટર ફરજિયાત છે, Row {0}: select the workstation against the operation {1},રો {0}: ઓપરેશન સામે વર્કસ્ટેશન પસંદ કરો {1}, @@ -3461,7 +3460,6 @@ Issue Type.,ઇશ્યુનો પ્રકાર., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","એવું લાગે છે કે સર્વરની પટ્ટી ગોઠવણી સાથે સમસ્યા છે. નિષ્ફળતાના કિસ્સામાં, રકમ તમારા એકાઉન્ટમાં પરત કરાશે.", Item Reported,આઇટમની જાણ થઈ, Item listing removed,આઇટમ સૂચિ દૂર કરી, -Item quantity can not be zero,આઇટમનો જથ્થો શૂન્ય હોઈ શકતો નથી, Item taxes updated,આઇટમ ટેક્સ અપડેટ કરાયો, Item {0}: {1} qty produced. ,આઇટમ {0}: produced 1} ક્યુટી ઉત્પન્ન., Joining Date can not be greater than Leaving Date,જોડાવાની તારીખ એ તારીખ છોડવાની તારીખ કરતા મોટી ન હોઇ શકે, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},પંક્તિ # {0}: કિંમત કેન્દ્ર {1 company કંપની to 2 belong નું નથી, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,પંક્તિ # {0}: Orderપરેશન {1 ty વર્ક ઓર્ડર finished 3 finished માં તૈયાર માલના {2} ક્યુટી માટે પૂર્ણ થયું નથી. કૃપા કરીને જોબ કાર્ડ via 4 via દ્વારા ઓપરેશનની સ્થિતિને અપડેટ કરો., Row #{0}: Payment document is required to complete the transaction,પંક્તિ # {0}: ટ્રાંઝેક્શન પૂર્ણ કરવા માટે ચુકવણી દસ્તાવેજ આવશ્યક છે, +Row #{0}: Quantity for Item {1} cannot be zero.,પંક્તિ # {0}: આઇટમનો {1} જથ્થો શૂન્ય હોઈ શકતો નથી, Row #{0}: Serial No {1} does not belong to Batch {2},પંક્તિ # {0}: સીરીયલ નંબર {1 B બેચ belong 2 to સાથે સંબંધિત નથી, Row #{0}: Service End Date cannot be before Invoice Posting Date,પંક્તિ # {0}: સેવાની સમાપ્તિ તારીખ ઇન્વoiceઇસ પોસ્ટિંગ તારીખ પહેલાંની હોઈ શકતી નથી, Row #{0}: Service Start Date cannot be greater than Service End Date,"પંક્તિ # {0}: સેવા પ્રારંભ તારીખ, સેવાની સમાપ્તિ તારીખ કરતા મોટી ન હોઇ શકે", diff --git a/erpnext/translations/he.csv b/erpnext/translations/he.csv index 5407578f2b..695fa37801 100644 --- a/erpnext/translations/he.csv +++ b/erpnext/translations/he.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,שורה {0}: הגדר את סיבת הפטור ממס במסים ובחיובים, Row {0}: Please set the Mode of Payment in Payment Schedule,שורה {0}: הגדר את אופן התשלום בלוח הזמנים לתשלום, Row {0}: Please set the correct code on Mode of Payment {1},שורה {0}: הגדר את הקוד הנכון במצב התשלום {1}, -Row {0}: Qty is mandatory,שורת {0}: הכמות היא חובה, Row {0}: Quality Inspection rejected for item {1},שורה {0}: בדיקת האיכות נדחתה לפריט {1}, Row {0}: UOM Conversion Factor is mandatory,שורת {0}: יחידת מידת המרת פקטור הוא חובה, Row {0}: select the workstation against the operation {1},שורה {0}: בחר את תחנת העבודה כנגד הפעולה {1}, @@ -3461,7 +3460,6 @@ Issue Type.,סוג הבעיה., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","נראה שיש בעיה בתצורת הפס של השרת. במקרה של כישלון, הסכום יוחזר לחשבונך.", Item Reported,פריט דווח, Item listing removed,רישום הפריט הוסר, -Item quantity can not be zero,כמות הפריט לא יכולה להיות אפס, Item taxes updated,מיסי הפריט עודכנו, Item {0}: {1} qty produced. ,פריט {0}: {1} כמות המיוצרת., Joining Date can not be greater than Leaving Date,תאריך ההצטרפות לא יכול להיות גדול מתאריך העזיבה, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},שורה מספר {0}: מרכז העלות {1} אינו שייך לחברה {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,שורה מספר {0}: פעולה {1} לא הושלמה עבור {2} כמות מוצרים מוגמרים בהזמנת עבודה {3}. אנא עדכן את מצב הפעולה באמצעות כרטיס עבודה {4}., Row #{0}: Payment document is required to complete the transaction,שורה מספר {0}: נדרש מסמך תשלום להשלמת העסקה, +Row #{0}: Quantity for Item {1} cannot be zero.,שורה מספר {0}: כמות הפריט {1} לא יכולה להיות אפס, Row #{0}: Serial No {1} does not belong to Batch {2},שורה מספר {0}: מספר סידורי {1} אינו שייך לאצווה {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,שורה מספר {0}: תאריך סיום השירות לא יכול להיות לפני תאריך פרסום החשבונית, Row #{0}: Service Start Date cannot be greater than Service End Date,שורה מס '{0}: תאריך התחלת השירות לא יכול להיות גדול מתאריך סיום השירות, diff --git a/erpnext/translations/hi.csv b/erpnext/translations/hi.csv index 00532df0f1..5d6dab3545 100644 --- a/erpnext/translations/hi.csv +++ b/erpnext/translations/hi.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,पंक्ति {0}: कृपया बिक्री कर और शुल्क में कर छूट का कारण निर्धारित करें, Row {0}: Please set the Mode of Payment in Payment Schedule,पंक्ति {0}: कृपया भुगतान अनुसूची में भुगतान का तरीका निर्धारित करें, Row {0}: Please set the correct code on Mode of Payment {1},पंक्ति {0}: कृपया भुगतान विधि पर सही कोड सेट करें {1}, -Row {0}: Qty is mandatory,पंक्ति {0}: मात्रा अनिवार्य है, Row {0}: Quality Inspection rejected for item {1},पंक्ति {0}: गुणवत्ता निरीक्षण आइटम {1} के लिए अस्वीकार कर दिया गया, Row {0}: UOM Conversion Factor is mandatory,पंक्ति {0}: UoM रूपांतरण कारक है अनिवार्य है, Row {0}: select the workstation against the operation {1},पंक्ति {0}: ऑपरेशन के खिलाफ वर्कस्टेशन का चयन करें {1}, @@ -3461,7 +3460,6 @@ Issue Type.,समस्या का प्रकार।, "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","ऐसा लगता है कि सर्वर की पट्टी विन्यास के साथ कोई समस्या है। विफलता के मामले में, राशि आपके खाते में वापस कर दी जाएगी।", Item Reported,आइटम रिपोर्ट की गई, Item listing removed,आइटम सूची निकाली गई, -Item quantity can not be zero,आइटम की मात्रा शून्य नहीं हो सकती, Item taxes updated,आइटम कर अद्यतन किए गए, Item {0}: {1} qty produced. ,आइटम {0}: {1} मात्रा का उत्पादन किया।, Joining Date can not be greater than Leaving Date,ज्वाइनिंग डेट लीविंग डेट से बड़ी नहीं हो सकती, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},पंक्ति # {0}: लागत केंद्र {1} कंपनी {2} से संबंधित नहीं है, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,पंक्ति # {0}: ऑपरेशन {1} कार्य क्रम {3} में तैयार माल की मात्रा {2} के लिए पूरा नहीं हुआ है। कृपया जॉब कार्ड {4} के माध्यम से संचालन की स्थिति को अपडेट करें।, Row #{0}: Payment document is required to complete the transaction,पंक्ति # {0}: लेन-देन को पूरा करने के लिए भुगतान दस्तावेज़ आवश्यक है, +Row #{0}: Quantity for Item {1} cannot be zero.,पंक्ति # {0}: आइटम {1} की मात्रा शून्य नहीं हो सकती, Row #{0}: Serial No {1} does not belong to Batch {2},पंक्ति # {0}: सीरियल नंबर {1} बैच {2} से संबंधित नहीं है, Row #{0}: Service End Date cannot be before Invoice Posting Date,पंक्ति # {0}: सेवा समाप्ति तिथि चालान पोस्टिंग तिथि से पहले नहीं हो सकती, Row #{0}: Service Start Date cannot be greater than Service End Date,पंक्ति # {0}: सेवा प्रारंभ तिथि सेवा समाप्ति तिथि से अधिक नहीं हो सकती, diff --git a/erpnext/translations/hr.csv b/erpnext/translations/hr.csv index 3cc9ef3be2..ddc5b593c6 100644 --- a/erpnext/translations/hr.csv +++ b/erpnext/translations/hr.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Redak {0}: Postavite razlog oslobađanja od poreza u porezima i naknadama na promet, Row {0}: Please set the Mode of Payment in Payment Schedule,Redak {0}: Postavite Način plaćanja u Raspored plaćanja, Row {0}: Please set the correct code on Mode of Payment {1},Redak {0}: postavite ispravan kôd na način plaćanja {1}, -Row {0}: Qty is mandatory,Red {0}: Količina je obvezno, Row {0}: Quality Inspection rejected for item {1},Redak {0}: Odbačena inspekcija kvalitete za stavku {1}, Row {0}: UOM Conversion Factor is mandatory,Red {0}: UOM pretvorbe faktor je obavezno, Row {0}: select the workstation against the operation {1},Red {0}: odaberite radnu stanicu protiv operacije {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Vrsta izdanja, "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Čini se da postoji problem s konfiguracijom trake poslužitelja. U slučaju neuspjeha, iznos će biti vraćen na vaš račun.", Item Reported,Stavka prijavljena, Item listing removed,Popis predmeta uklonjen je, -Item quantity can not be zero,Količina predmeta ne može biti jednaka nuli, Item taxes updated,Ažurirani su porezi na stavke, Item {0}: {1} qty produced. ,Stavka {0}: {1} Količina proizvedena., Joining Date can not be greater than Leaving Date,Datum pridruživanja ne može biti veći od Datum napuštanja, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Redak # {0}: Troškovno mjesto {1} ne pripada tvrtki {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Redak # {0}: Operacija {1} nije dovršena za {2} količinu gotovih proizvoda u radnom nalogu {3}. Ažurirajte status rada putem Job Card {4}., Row #{0}: Payment document is required to complete the transaction,Redak # {0}: Dokument za plaćanje potreban je za dovršavanje transakcije, +Row #{0}: Quantity for Item {1} cannot be zero.,Redak #{0}: Količina predmeta {1} ne može biti jednaka nuli., Row #{0}: Serial No {1} does not belong to Batch {2},Redak br. {0}: Serijski br. {1} ne pripada grupi {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Redak broj {0}: datum završetka usluge ne može biti prije datuma knjiženja fakture, Row #{0}: Service Start Date cannot be greater than Service End Date,Redak broj {0}: Datum početka usluge ne može biti veći od datuma završetka usluge, diff --git a/erpnext/translations/hu.csv b/erpnext/translations/hu.csv index 42175bbe34..a793937e62 100644 --- a/erpnext/translations/hu.csv +++ b/erpnext/translations/hu.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,"{0} sor: Kérjük, állítsa az adómentesség okához a forgalmi adókat és díjakat", Row {0}: Please set the Mode of Payment in Payment Schedule,"{0} sor: Kérjük, állítsa be a fizetési módot a fizetési ütemezésben", Row {0}: Please set the correct code on Mode of Payment {1},"{0} sor: Kérjük, állítsa be a helyes kódot a Fizetési módban {1}", -Row {0}: Qty is mandatory,Sor {0}: Menny. kötelező, Row {0}: Quality Inspection rejected for item {1},{0} sor: A (z) {1} tételnél a minőségellenőrzést elutasították, Row {0}: UOM Conversion Factor is mandatory,Sor {0}: UOM átváltási arányra is kötelező, Row {0}: select the workstation against the operation {1},{0} sor: válassza ki a munkaállomást a művelet ellen {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Probléma típus., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Úgy tűnik, hogy probléma van a kiszolgáló sávszélesség konfigurációjával. Hiba esetén az összeg visszafizetésre kerül a számlájára.", Item Reported,Jelentés tárgya, Item listing removed,Az elemlista eltávolítva, -Item quantity can not be zero,A cikk mennyisége nem lehet nulla, Item taxes updated,A cikk adóit frissítettük, Item {0}: {1} qty produced. ,{0} tétel: {1} mennyiség előállítva., Joining Date can not be greater than Leaving Date,"A csatlakozási dátum nem lehet nagyobb, mint a távozási dátum", @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},{0} sor: A (z) {1} költségközpont nem tartozik a (z) {2} vállalathoz, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,"{0} sor: A (z) {1} művelet a (z) {3} munkarenden lévő {2} mennyiségű készterméknél nem fejeződött be. Kérjük, frissítse a működési állapotot a (z) {4} Job Card segítségével.", Row #{0}: Payment document is required to complete the transaction,{0} sor: A tranzakció teljesítéséhez fizetési dokumentum szükséges, +Row #{0}: Quantity for Item {1} cannot be zero.,{0} sor: A cikk {1} mennyisége nem lehet nulla., Row #{0}: Serial No {1} does not belong to Batch {2},{0} sor: A (z) {1} sorszám nem tartozik a {2} tételhez, Row #{0}: Service End Date cannot be before Invoice Posting Date,{0} sor: A szolgáltatás befejezési dátuma nem lehet a számla feladásának dátuma előtt, Row #{0}: Service Start Date cannot be greater than Service End Date,"{0} sor: A szolgáltatás kezdési dátuma nem lehet nagyobb, mint a szolgáltatás befejezési dátuma", diff --git a/erpnext/translations/id.csv b/erpnext/translations/id.csv index d69eef389d..14a13f09d5 100644 --- a/erpnext/translations/id.csv +++ b/erpnext/translations/id.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Baris {0}: Harap atur di Alasan Pembebasan Pajak dalam Pajak Penjualan dan Biaya, Row {0}: Please set the Mode of Payment in Payment Schedule,Baris {0}: Silakan tetapkan Mode Pembayaran dalam Jadwal Pembayaran, Row {0}: Please set the correct code on Mode of Payment {1},Baris {0}: Silakan tetapkan kode yang benar pada Mode Pembayaran {1}, -Row {0}: Qty is mandatory,Row {0}: Qty adalah wajib, Row {0}: Quality Inspection rejected for item {1},Baris {0}: Pemeriksaan Kualitas ditolak untuk barang {1}, Row {0}: UOM Conversion Factor is mandatory,Row {0}: UOM Faktor Konversi adalah wajib, Row {0}: select the workstation against the operation {1},Baris {0}: pilih workstation terhadap operasi {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Jenis Masalah., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Tampaknya ada masalah dengan konfigurasi strip server. Jika terjadi kegagalan, jumlah itu akan dikembalikan ke akun Anda.", Item Reported,Barang Dilaporkan, Item listing removed,Daftar item dihapus, -Item quantity can not be zero,Kuantitas barang tidak boleh nol, Item taxes updated,Pajak barang diperbarui, Item {0}: {1} qty produced. ,Item {0}: {1} jumlah diproduksi., Joining Date can not be greater than Leaving Date,Tanggal Bergabung tidak boleh lebih dari Tanggal Meninggalkan, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Baris # {0}: Pusat Biaya {1} bukan milik perusahaan {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Baris # {0}: Operasi {1} tidak selesai untuk {2} jumlah barang jadi dalam Perintah Kerja {3}. Harap perbarui status operasi melalui Kartu Pekerjaan {4}., Row #{0}: Payment document is required to complete the transaction,Baris # {0}: Dokumen pembayaran diperlukan untuk menyelesaikan transaksi, +Row #{0}: Quantity for Item {1} cannot be zero.,Baris # {0}: Kuantitas barang {1} tidak boleh nol., Row #{0}: Serial No {1} does not belong to Batch {2},Baris # {0}: Nomor Seri {1} bukan milik Kelompok {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Baris # {0}: Tanggal Berakhir Layanan tidak boleh sebelum Tanggal Posting Faktur, Row #{0}: Service Start Date cannot be greater than Service End Date,Baris # {0}: Tanggal Mulai Layanan tidak boleh lebih besar dari Tanggal Akhir Layanan, diff --git a/erpnext/translations/is.csv b/erpnext/translations/is.csv index 1acefbb3ee..95920151f8 100644 --- a/erpnext/translations/is.csv +++ b/erpnext/translations/is.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Röð {0}: Vinsamlegast stillið á skattfrelsisástæða í söluskatti og gjöldum, Row {0}: Please set the Mode of Payment in Payment Schedule,Röð {0}: Vinsamlegast stilltu greiðslumáta í greiðsluáætlun, Row {0}: Please set the correct code on Mode of Payment {1},Röð {0}: Vinsamlegast stilltu réttan kóða á greiðslumáta {1}, -Row {0}: Qty is mandatory,Row {0}: Magn er nauðsynlegur, Row {0}: Quality Inspection rejected for item {1},Röð {0}: Gæðaeftirlit hafnað fyrir hlut {1}, Row {0}: UOM Conversion Factor is mandatory,Row {0}: UOM viðskipta Factor er nauðsynlegur, Row {0}: select the workstation against the operation {1},Rú {0}: veldu vinnustöðina gegn aðgerðinni {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Útgáfutegund., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.",Það virðist sem það er vandamál með rétta stillingu miðlarans. Ef bilun er fyrir hendi verður fjárhæðin endurgreitt á reikninginn þinn., Item Reported,Liður tilkynntur, Item listing removed,Atriðaskráning fjarlægð, -Item quantity can not be zero,Magn vöru getur ekki verið núll, Item taxes updated,Atvinnuskattar uppfærðir, Item {0}: {1} qty produced. ,Liður {0}: {1} fjöldi framleiddur., Joining Date can not be greater than Leaving Date,Tengingardagur má ekki vera stærri en dagsetningardagur, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Röð # {0}: Kostnaðarmiðstöð {1} tilheyrir ekki fyrirtæki {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Röð # {0}: Aðgerð {1} er ekki lokið fyrir {2} magn fullunnar vöru í vinnuskipan {3}. Vinsamlegast uppfærðu stöðu starfsins með Job Card {4}., Row #{0}: Payment document is required to complete the transaction,Lína # {0}: Greiðslu skjal er nauðsynlegt til að ljúka viðskiptunum, +Row #{0}: Quantity for Item {1} cannot be zero.,Röð #{0}: Magn vöru {1} getur ekki verið núll., Row #{0}: Serial No {1} does not belong to Batch {2},Röð # {0}: Raðnúmer {1} tilheyrir ekki hópi {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Lína # {0}: Lokadagsetning þjónustu má ekki vera fyrir dagsetningu reiknings, Row #{0}: Service Start Date cannot be greater than Service End Date,Röð # {0}: Upphafsdagsetning þjónustu má ekki vera meiri en lokadagur þjónustu, diff --git a/erpnext/translations/it.csv b/erpnext/translations/it.csv index e6e64254bb..50f07bb101 100644 --- a/erpnext/translations/it.csv +++ b/erpnext/translations/it.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Riga {0}: impostare il motivo dell'esenzione fiscale in Imposte e addebiti, Row {0}: Please set the Mode of Payment in Payment Schedule,Riga {0}: imposta la Modalità di pagamento in Pianificazione pagamenti, Row {0}: Please set the correct code on Mode of Payment {1},Riga {0}: imposta il codice corretto su Modalità di pagamento {1}, -Row {0}: Qty is mandatory,Riga {0}: Quantità è obbligatorio, Row {0}: Quality Inspection rejected for item {1},Riga {0}: Ispezione di qualità rifiutata per l'articolo {1}, Row {0}: UOM Conversion Factor is mandatory,Riga {0}: UOM fattore di conversione è obbligatoria, Row {0}: select the workstation against the operation {1},Riga {0}: seleziona la workstation rispetto all'operazione {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Tipo di problema., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Sembra che ci sia un problema con la configurazione delle strisce del server. In caso di fallimento, l'importo verrà rimborsato sul tuo conto.", Item Reported,Articolo segnalato, Item listing removed,Elenco degli articoli rimosso, -Item quantity can not be zero,La quantità dell'articolo non può essere zero, Item taxes updated,Imposte sugli articoli aggiornate, Item {0}: {1} qty produced. ,Articolo {0}: {1} qtà prodotta., Joining Date can not be greater than Leaving Date,La data di iscrizione non può essere superiore alla data di fine, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Riga # {0}: Cost Center {1} non appartiene alla società {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Riga n. {0}: l'operazione {1} non è stata completata per {2} quantità di prodotti finiti nell'ordine di lavoro {3}. Aggiorna lo stato dell'operazione tramite la Job Card {4}., Row #{0}: Payment document is required to complete the transaction,Riga # {0}: per completare la transazione è richiesto un documento di pagamento, +Row #{0}: Quantity for Item {1} cannot be zero.,Riga # {0}: La quantità dell'articolo {1} non può essere zero., Row #{0}: Serial No {1} does not belong to Batch {2},Riga # {0}: il numero di serie {1} non appartiene a Batch {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Riga n. {0}: la data di fine del servizio non può essere precedente alla data di registrazione della fattura, Row #{0}: Service Start Date cannot be greater than Service End Date,Riga # {0}: la data di inizio del servizio non può essere superiore alla data di fine del servizio, diff --git a/erpnext/translations/ja.csv b/erpnext/translations/ja.csv index dd5820ae77..468866fb6f 100644 --- a/erpnext/translations/ja.csv +++ b/erpnext/translations/ja.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,行{0}:売上税および消費税の免税理由で設定してください, Row {0}: Please set the Mode of Payment in Payment Schedule,行{0}:支払いスケジュールに支払い方法を設定してください, Row {0}: Please set the correct code on Mode of Payment {1},行{0}:支払い方法{1}に正しいコードを設定してください, -Row {0}: Qty is mandatory,行{0}:数量は必須です, Row {0}: Quality Inspection rejected for item {1},行{0}:品質検査が品目{1}に対して拒否されました, Row {0}: UOM Conversion Factor is mandatory,行{0}:数量単位(UOM)換算係数は必須です, Row {0}: select the workstation against the operation {1},行{0}:操作{1}に対するワークステーションを選択します。, @@ -3461,7 +3460,6 @@ Issue Type.,問題の種類。, "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.",サーバーのストライプ構成に問題があるようです。不具合が発生した場合、その金額はお客様のアカウントに払い戻されます。, Item Reported,報告されたアイテム, Item listing removed,商品リストを削除しました, -Item quantity can not be zero,品目数量はゼロにできません, Item taxes updated,アイテム税が更新されました, Item {0}: {1} qty produced. ,アイテム{0}:生産された{1}個。, Joining Date can not be greater than Leaving Date,参加日は出発日よりも大きくすることはできません, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},行#{0}:コストセンター{1}は会社{2}に属していません, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,行#{0}:作業オーダー{3}の{2}個の完成品に対して、操作{1}が完了していません。ジョブカード{4}を介して操作状況を更新してください。, Row #{0}: Payment document is required to complete the transaction,行#{0}:支払い文書は取引を完了するために必要です, +Row #{0}: Quantity for Item {1} cannot be zero.,行 # {0}: 品目 {1} の数量はゼロにできません, Row #{0}: Serial No {1} does not belong to Batch {2},行#{0}:シリアル番号{1}はバッチ{2}に属していません, Row #{0}: Service End Date cannot be before Invoice Posting Date,行#{0}:サービス終了日は請求書転記日より前にはできません, Row #{0}: Service Start Date cannot be greater than Service End Date,行#{0}:サービス開始日はサービス終了日より後にすることはできません, diff --git a/erpnext/translations/km.csv b/erpnext/translations/km.csv index 2740d7fc8a..dc97fbf15d 100644 --- a/erpnext/translations/km.csv +++ b/erpnext/translations/km.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,ជួរដេក {0}៖ សូមកំណត់នៅហេតុផលលើកលែងពន្ធក្នុងពន្ធលក់និងការគិតថ្លៃ។, Row {0}: Please set the Mode of Payment in Payment Schedule,ជួរដេក {0}៖ សូមកំណត់របៀបបង់ប្រាក់ក្នុងកាលវិភាគទូទាត់។, Row {0}: Please set the correct code on Mode of Payment {1},ជួរដេក {0}៖ សូមកំណត់លេខកូដត្រឹមត្រូវលើរបៀបបង់ប្រាក់ {1}, -Row {0}: Qty is mandatory,ជួរដេក {0}: Qty គឺជាការចាំបាច់, Row {0}: Quality Inspection rejected for item {1},ជួរដេក {0}: ការត្រួតពិនិត្យគុណភាពត្រូវបានច្រានចោលចំពោះធាតុ {1}, Row {0}: UOM Conversion Factor is mandatory,ជួរដេក {0}: UOM ការប្រែចិត្តជឿកត្តាគឺជាការចាំបាច់, Row {0}: select the workstation against the operation {1},ជួរដេក {0}: ជ្រើសកន្លែងធ្វើការប្រឆាំងនឹងប្រតិបត្តិការ {1}, @@ -3461,7 +3460,6 @@ Issue Type.,ប្រភេទបញ្ហា។, "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.",វាហាក់បីដូចជាមានបញ្ហាជាមួយការកំណត់រចនាសម្ព័ន្ធឆ្នូតរបស់ម៉ាស៊ីនមេ។ ក្នុងករណីមានការខកខានចំនួនទឹកប្រាក់នឹងត្រូវបានសងប្រាក់វិញទៅក្នុងគណនីរបស់អ្នក។, Item Reported,បានរាយការណ៍អំពីធាតុ។, Item listing removed,បានលុបបញ្ជីធាតុ, -Item quantity can not be zero,បរិមាណធាតុមិនអាចជាសូន្យ។, Item taxes updated,បានធ្វើបច្ចុប្បន្នភាពធាតុពន្ធ, Item {0}: {1} qty produced. ,ធាតុ {0}: {1} qty ផលិត។, Joining Date can not be greater than Leaving Date,កាលបរិច្ឆេទចូលរួមមិនអាចធំជាងកាលបរិច្ឆេទចាកចេញឡើយ, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},ជួរទី # {០}៖ មជ្ឈមណ្ឌលតម្លៃ {១} មិនមែនជារបស់ក្រុមហ៊ុន {២}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,ជួរទី # {០}៖ ប្រតិបត្តិការ {១} មិនត្រូវបានបញ្ចប់សម្រាប់ {២} នៃទំនិញបញ្ចប់ក្នុងលំដាប់ការងារ {៣} ទេ។ សូមធ្វើបច្ចុប្បន្នភាពស្ថានភាពប្រតិបត្តិការតាមរយៈកាតការងារ {៤} ។, Row #{0}: Payment document is required to complete the transaction,ជួរទី # {០}៖ ឯកសារទូទាត់ត្រូវបានទាមទារដើម្បីបញ្ចប់ប្រតិបត្តិការ, +Row #{0}: Quantity for Item {1} cannot be zero.,ជួរទី # {០}៖ បរិមាណធាតុ {1} មិនអាចជាសូន្យ។, Row #{0}: Serial No {1} does not belong to Batch {2},ជួរទី # {០}៖ សៀរៀលលេខ {១} មិនមែនជាកម្មសិទ្ធិរបស់បាច់ឡើយ {២}, Row #{0}: Service End Date cannot be before Invoice Posting Date,ជួរទី # {០}៖ កាលបរិច្ឆេទបញ្ចប់សេវាកម្មមិនអាចមុនកាលបរិច្ឆេទប្រកាសវិក្កយបត្រ, Row #{0}: Service Start Date cannot be greater than Service End Date,ជួរដេក # {0}៖ កាលបរិច្ឆេទចាប់ផ្តើមសេវាកម្មមិនអាចធំជាងកាលបរិច្ឆេទបញ្ចប់សេវាកម្មឡើយ, diff --git a/erpnext/translations/kn.csv b/erpnext/translations/kn.csv index 8b271682eb..21180365f5 100644 --- a/erpnext/translations/kn.csv +++ b/erpnext/translations/kn.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,ಸಾಲು {0}: ದಯವಿಟ್ಟು ಮಾರಾಟ ತೆರಿಗೆಗಳು ಮತ್ತು ಶುಲ್ಕಗಳಲ್ಲಿ ತೆರಿಗೆ ವಿನಾಯಿತಿ ಕಾರಣವನ್ನು ಹೊಂದಿಸಿ, Row {0}: Please set the Mode of Payment in Payment Schedule,ಸಾಲು {0}: ದಯವಿಟ್ಟು ಪಾವತಿ ವೇಳಾಪಟ್ಟಿಯಲ್ಲಿ ಪಾವತಿ ಮೋಡ್ ಅನ್ನು ಹೊಂದಿಸಿ, Row {0}: Please set the correct code on Mode of Payment {1},ಸಾಲು {0}: ದಯವಿಟ್ಟು ಸರಿಯಾದ ಕೋಡ್ ಅನ್ನು ಪಾವತಿ ಮೋಡ್‌ನಲ್ಲಿ ಹೊಂದಿಸಿ {1}, -Row {0}: Qty is mandatory,ರೋ {0}: ಪ್ರಮಾಣ ಕಡ್ಡಾಯ, Row {0}: Quality Inspection rejected for item {1},ಸಾಲು {0}: ಐಟಂಗೆ ಗುಣಮಟ್ಟ ಪರೀಕ್ಷೆ ತಿರಸ್ಕರಿಸಲಾಗಿದೆ {1}, Row {0}: UOM Conversion Factor is mandatory,ಸಾಲು {0}: ಮೈಸೂರು ವಿಶ್ವವಿದ್ಯಾನಿಲದ ಪರಿವರ್ತನಾ ಕಾರಕ ಕಡ್ಡಾಯ, Row {0}: select the workstation against the operation {1},ಸಾಲು {0}: ಕಾರ್ಯಾಚರಣೆ ವಿರುದ್ಧ ಕಾರ್ಯಕ್ಷೇತ್ರವನ್ನು ಆಯ್ಕೆಮಾಡಿ {1}, @@ -3461,7 +3460,6 @@ Issue Type.,ಸಂಚಿಕೆ ಪ್ರಕಾರ., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","ಸರ್ವರ್ನ ಸ್ಟ್ರೈಪ್ ಕಾನ್ಫಿಗರೇಶನ್ನಲ್ಲಿ ಸಮಸ್ಯೆ ಇದೆ ಎಂದು ತೋರುತ್ತದೆ. ವೈಫಲ್ಯದ ಸಂದರ್ಭದಲ್ಲಿ, ನಿಮ್ಮ ಖಾತೆಗೆ ಹಣವನ್ನು ಮರುಪಾವತಿಸಲಾಗುತ್ತದೆ.", Item Reported,ಐಟಂ ವರದಿ ಮಾಡಲಾಗಿದೆ, Item listing removed,ಐಟಂ ಪಟ್ಟಿಯನ್ನು ತೆಗೆದುಹಾಕಲಾಗಿದೆ, -Item quantity can not be zero,ಐಟಂ ಪ್ರಮಾಣ ಶೂನ್ಯವಾಗಿರಬಾರದು, Item taxes updated,ಐಟಂ ತೆರಿಗೆಗಳನ್ನು ನವೀಕರಿಸಲಾಗಿದೆ, Item {0}: {1} qty produced. ,ಐಟಂ {0}: {1} qty ಉತ್ಪಾದಿಸಲಾಗಿದೆ., Joining Date can not be greater than Leaving Date,ಸೇರುವ ದಿನಾಂಕವು ಬಿಡುವ ದಿನಾಂಕಕ್ಕಿಂತ ಹೆಚ್ಚಿರಬಾರದು, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},ಸಾಲು # {0}: ವೆಚ್ಚ ಕೇಂದ್ರ {1 company ಕಂಪನಿಗೆ ಸೇರಿಲ್ಲ {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,ಸಾಲು # {0}: ಕೆಲಸದ ಆದೇಶ {3 in ನಲ್ಲಿ finished 2} ಕ್ವಿಟಿ ಮುಗಿದ ಸರಕುಗಳಿಗೆ ಕಾರ್ಯಾಚರಣೆ {1 complete ಪೂರ್ಣಗೊಂಡಿಲ್ಲ. ದಯವಿಟ್ಟು ಜಾಬ್ ಕಾರ್ಡ್ {4 via ಮೂಲಕ ಕಾರ್ಯಾಚರಣೆಯ ಸ್ಥಿತಿಯನ್ನು ನವೀಕರಿಸಿ., Row #{0}: Payment document is required to complete the transaction,ಸಾಲು # {0}: ವಹಿವಾಟನ್ನು ಪೂರ್ಣಗೊಳಿಸಲು ಪಾವತಿ ಡಾಕ್ಯುಮೆಂಟ್ ಅಗತ್ಯವಿದೆ, +Row #{0}: Quantity for Item {1} cannot be zero.,ಸಾಲು # {0}: ಐಟಂ {1} ಪ್ರಮಾಣ ಶೂನ್ಯವಾಗಿರಬಾರದು, Row #{0}: Serial No {1} does not belong to Batch {2},ಸಾಲು # {0}: ಸರಣಿ ಸಂಖ್ಯೆ {1 B ಬ್ಯಾಚ್ {2 to ಗೆ ಸೇರಿಲ್ಲ, Row #{0}: Service End Date cannot be before Invoice Posting Date,ಸಾಲು # {0}: ಸರಕುಪಟ್ಟಿ ಪೋಸ್ಟ್ ಮಾಡುವ ದಿನಾಂಕಕ್ಕಿಂತ ಮೊದಲು ಸೇವೆಯ ಅಂತಿಮ ದಿನಾಂಕ ಇರಬಾರದು, Row #{0}: Service Start Date cannot be greater than Service End Date,ಸಾಲು # {0}: ಸೇವೆಯ ಪ್ರಾರಂಭ ದಿನಾಂಕವು ಸೇವಾ ಅಂತಿಮ ದಿನಾಂಕಕ್ಕಿಂತ ಹೆಚ್ಚಿರಬಾರದು, diff --git a/erpnext/translations/ko.csv b/erpnext/translations/ko.csv index edd3f2731f..4e10a6c21d 100644 --- a/erpnext/translations/ko.csv +++ b/erpnext/translations/ko.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,행 {0} : 세금 면제 사유로 판매 세 및 수수료로 설정하십시오., Row {0}: Please set the Mode of Payment in Payment Schedule,행 {0} : 지급 일정에 지급 방식을 설정하십시오., Row {0}: Please set the correct code on Mode of Payment {1},행 {0} : 결제 방법 {1}에 올바른 코드를 설정하십시오., -Row {0}: Qty is mandatory,행 {0} : 수량은 필수입니다, Row {0}: Quality Inspection rejected for item {1},행 {0} : 항목 {1}에 대해 품질 검사가 거부되었습니다., Row {0}: UOM Conversion Factor is mandatory,행 {0} : UOM 변환 계수는 필수입니다, Row {0}: select the workstation against the operation {1},행 {0} : 작업 {1}에 대한 워크 스테이션을 선택하십시오., @@ -3461,7 +3460,6 @@ Issue Type.,문제 유형., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.",서버의 스트라이프 구성에 문제가있는 것으로 보입니다. 실패한 경우 귀하의 계좌로 금액이 환급됩니다., Item Reported,보고 된 품목, Item listing removed,상품 목록이 삭제되었습니다., -Item quantity can not be zero,항목 수량은 0 일 수 없습니다., Item taxes updated,상품 세금 업데이트, Item {0}: {1} qty produced. ,항목 {0} : {1} 수량이 생산되었습니다., Joining Date can not be greater than Leaving Date,가입 날짜는 떠나는 날짜보다 클 수 없습니다, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},행 # {0} : 코스트 센터 {1}이 (가) 회사 {2}에 속하지 않습니다, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,행 # {0} : {2} 작업 주문 {3}의 완제품 수량에 대해 {1} 작업이 완료되지 않았습니다. 작업 카드 {4}를 통해 작업 상태를 업데이트하십시오., Row #{0}: Payment document is required to complete the transaction,행 번호 {0} : 거래를 완료하려면 지불 문서가 필요합니다., +Row #{0}: Quantity for Item {1} cannot be zero.,행 # {0}: 항목 {1}의 수량은 0일 수 없습니다., Row #{0}: Serial No {1} does not belong to Batch {2},행 # {0} : 일련 번호 {1}이 (가) 배치 {2}에 속하지 않습니다, Row #{0}: Service End Date cannot be before Invoice Posting Date,행 # {0} : 서비스 종료 날짜는 송장 전기 일 이전 일 수 없습니다, Row #{0}: Service Start Date cannot be greater than Service End Date,행 # {0} : 서비스 시작 날짜는 서비스 종료 날짜보다 클 수 없습니다., diff --git a/erpnext/translations/ku.csv b/erpnext/translations/ku.csv index e18ce45132..8b7db2a740 100644 --- a/erpnext/translations/ku.csv +++ b/erpnext/translations/ku.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Row {0}: Ji kerema xwe Sedemek Tişta Qebûlkirina Bacê Li Bac û Firotên Firotanê, Row {0}: Please set the Mode of Payment in Payment Schedule,Row {0}: Ji kerema xwe Modela Pêvekirinê di Pêveka Pevçûnê de bicîh bikin, Row {0}: Please set the correct code on Mode of Payment {1},Row {0}: Ji kerema xwe koda rastê li ser Mode-ya Peymana {1}, -Row {0}: Qty is mandatory,Row {0}: Qty wêneke e, Row {0}: Quality Inspection rejected for item {1},Row {0}: Teftîşa Kalîteya ji bo hilbijêre {1}, Row {0}: UOM Conversion Factor is mandatory,Row {0}: UOM Factor Converter wêneke e, Row {0}: select the workstation against the operation {1},Row {0}: Li dijî xebatê {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Cureya pirsgirêkê., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Ew xuya dike ku pirsgirêkek bi sazkirina pergala serverê heye. Di rewşeke neyê de, hejmar dê dê hesabê we vegerîne.", Item Reported,Babetê Hatiye rapor kirin, Item listing removed,Lîsteya kêr hatî rakirin, -Item quantity can not be zero,Hêjmara tiştên ne dikare bibe zero, Item taxes updated,Bacê tiştên nûvekirî, Item {0}: {1} qty produced. ,Babetê {0}: {1} qty hilberandin., Joining Date can not be greater than Leaving Date,Tevlêbûna Dîrokê nikare ji Dîroka Veqetînê mezintir be, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Row # {0}: Navenda Cost {1} nabe ku pargîdaniya} 2, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Row # {0}: Operasyon {1} ji bo {2} qty ya tiştên qedandî di Fermana Kar {3 not de temam nabe. Ji kerema xwe rewşa karûbarê bi Karta Kar Job 4 update nûve bikin., Row #{0}: Payment document is required to complete the transaction,Row # {0}: Ji bo temamkirina danûstendinê belgeya dayînê hewce ye, +Row #{0}: Quantity for Item {1} cannot be zero.,Rêz # {0}: Hêjmara tiştên {1} ne dikare bibe zero., Row #{0}: Serial No {1} does not belong to Batch {2},Row # {0}: Serial No {1} ne Batch {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Row # {0}: Dîroka Dawiya Xizmet nikare Berî Dîroka ingandina Tevneyê be, Row #{0}: Service Start Date cannot be greater than Service End Date,Row # {0}: Dîroka Destpêkirina Karûbarê ji Dîroka Dawiya Xizmet nikare mezin be, diff --git a/erpnext/translations/lo.csv b/erpnext/translations/lo.csv index 46acd22939..4658f6d0ab 100644 --- a/erpnext/translations/lo.csv +++ b/erpnext/translations/lo.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,ແຖວ {0}: ກະລຸນາ ກຳ ນົດຢູ່ໃນເຫດຜົນການຍົກເວັ້ນພາສີໃນການເກັບອາກອນແລະຄ່າບໍລິການ, Row {0}: Please set the Mode of Payment in Payment Schedule,ແຖວ {0}: ກະລຸນາ ກຳ ນົດຮູບແບບການຈ່າຍເງິນໃນຕາຕະລາງການຈ່າຍເງິນ, Row {0}: Please set the correct code on Mode of Payment {1},ແຖວ {0}: ກະລຸນາຕັ້ງລະຫັດທີ່ຖືກຕ້ອງໃນຮູບແບບການຈ່າຍເງິນ {1}, -Row {0}: Qty is mandatory,ຕິດຕໍ່ກັນ {0}: ຈໍານວນເປັນການບັງຄັບ, Row {0}: Quality Inspection rejected for item {1},ແຖວ {0}: ການກວດກາຄຸນນະພາບຖືກປະຕິເສດ ສຳ ລັບສິນຄ້າ {1}, Row {0}: UOM Conversion Factor is mandatory,ຕິດຕໍ່ກັນ {0}: UOM ປັດໄຈການແປງເປັນການບັງຄັບ, Row {0}: select the workstation against the operation {1},ແຖວ {0}: ເລືອກເອົາສະຖານທີ່ເຮັດວຽກຕໍ່ການດໍາເນີນງານ {1}, @@ -3461,7 +3460,6 @@ Issue Type.,ປະເພດອອກ., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","ມັນເບິ່ງຄືວ່າມີບັນຫາກັບການກໍານົດເສັ້ນດ່າງຂອງເຄື່ອງແມ່ຂ່າຍ. ໃນກໍລະນີຂອງຄວາມລົ້ມເຫຼວ, ຈໍານວນເງິນຈະໄດ້ຮັບການຊໍາລະກັບບັນຊີຂອງທ່ານ.", Item Reported,ລາຍງານລາຍການ, Item listing removed,ລາຍການຖືກລຶບອອກແລ້ວ, -Item quantity can not be zero,ປະລິມານສິນຄ້າບໍ່ສາມາດເປັນສູນ, Item taxes updated,ພາສີລາຍການຖືກປັບປຸງ, Item {0}: {1} qty produced. ,ລາຍການ {0}: {1} qty ຜະລິດ., Joining Date can not be greater than Leaving Date,ວັນເຂົ້າຮ່ວມບໍ່ສາມາດໃຫຍ່ກວ່າວັນທີ່ອອກຈາກວັນທີ, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},ແຖວ # {0}: ສູນຄ່າໃຊ້ຈ່າຍ {1} ບໍ່ຂຶ້ນກັບບໍລິສັດ {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,ແຖວ # {0}: ການ ດຳ ເນີນງານ {1} ບໍ່ໄດ້ ສຳ ເລັດ ສຳ ລັບ {2} ສິນຄ້າ ສຳ ເລັດຮູບ ຈຳ ນວນຫຼາຍໃນ ຄຳ ສັ່ງເຮັດວຽກ {3}. ກະລຸນາປັບປຸງສະຖານະການ ດຳ ເນີນງານຜ່ານບັດວຽກ {4}., Row #{0}: Payment document is required to complete the transaction,ແຖວ # {0}: ຕ້ອງມີເອກະສານຈ່າຍເງິນເພື່ອເຮັດການເຮັດທຸລະ ກຳ ສຳ ເລັດ, +Row #{0}: Quantity for Item {1} cannot be zero.,ແຖວ # {0}: ປະລິມານສິນຄ້າ {1} ບໍ່ສາມາດເປັນສູນ, Row #{0}: Serial No {1} does not belong to Batch {2},ແຖວ # {0}: Serial No {1} ບໍ່ຂຶ້ນກັບ Batch {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,ແຖວ # {0}: ວັນສິ້ນສຸດການບໍລິການບໍ່ສາມາດກ່ອນວັນທີອອກໃບເກັບເງິນ, Row #{0}: Service Start Date cannot be greater than Service End Date,ແຖວ # {0}: ວັນທີເລີ່ມການບໍລິການບໍ່ສາມາດໃຫຍ່ກວ່າວັນສິ້ນສຸດການບໍລິການ, diff --git a/erpnext/translations/lt.csv b/erpnext/translations/lt.csv index 292c9d88e2..721be8d064 100644 --- a/erpnext/translations/lt.csv +++ b/erpnext/translations/lt.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,{0} eilutė: nustatykite pardavimo mokesčių ir rinkliavų atleidimo nuo mokesčių priežastį, Row {0}: Please set the Mode of Payment in Payment Schedule,{0} eilutė: nurodykite mokėjimo režimą mokėjimo grafike, Row {0}: Please set the correct code on Mode of Payment {1},{0} eilutė: nurodykite teisingą kodą Mokėjimo būde {1}, -Row {0}: Qty is mandatory,Eilutės {0}: Kiekis yra privalomi, Row {0}: Quality Inspection rejected for item {1},{0} eilutė: {1} elemento kokybės inspekcija atmesta, Row {0}: UOM Conversion Factor is mandatory,Eilutės {0}: UOM konversijos faktorius yra privalomas, Row {0}: select the workstation against the operation {1},Eilutė {0}: pasirinkite darbo vietą prieš operaciją {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Išleidimo tipas., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Atrodo, kad yra problema dėl serverio juostos konfigūracijos. Nepavykus, suma bus grąžinta į jūsų sąskaitą.", Item Reported,Elementas praneštas, Item listing removed,Elementų sąrašas pašalintas, -Item quantity can not be zero,Prekės kiekis negali būti lygus nuliui, Item taxes updated,Prekės mokesčiai atnaujinti, Item {0}: {1} qty produced. ,Prekė {0}: {1} kiekis pagamintas., Joining Date can not be greater than Leaving Date,Prisijungimo data negali būti didesnė nei išvykimo data, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},{0} eilutė: Išlaidų centras {1} nepriklauso įmonei {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,"Nr. {0}: {1} operacija {1} neužbaigta, kai užsakytas {3} kiekis paruoštų prekių. Atnaujinkite operacijos būseną naudodamiesi darbo kortele {4}.", Row #{0}: Payment document is required to complete the transaction,# 0 eilutė: mokėjimo operacijai atlikti reikalingas mokėjimo dokumentas, +Row #{0}: Quantity for Item {1} cannot be zero.,# {0} eilutė: Prekės {1} kiekis negali būti lygus nuliui., Row #{0}: Serial No {1} does not belong to Batch {2},{0} eilutė: serijos Nr. {1} nepriklauso {2} siuntai, Row #{0}: Service End Date cannot be before Invoice Posting Date,# 0 eilutė: Paslaugos pabaigos data negali būti anksčiau nei sąskaitos faktūros paskelbimo data, Row #{0}: Service Start Date cannot be greater than Service End Date,# 0 eilutė: Paslaugos pradžios data negali būti didesnė už paslaugos pabaigos datą, diff --git a/erpnext/translations/lv.csv b/erpnext/translations/lv.csv index 52641b25af..46e577ba52 100644 --- a/erpnext/translations/lv.csv +++ b/erpnext/translations/lv.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,"{0} rinda: lūdzu, iestatiet pārdošanas nodokļa un nodevu atbrīvojuma no nodokļa iemeslu", Row {0}: Please set the Mode of Payment in Payment Schedule,"{0} rinda: lūdzu, maksājuma grafikā iestatiet maksājuma režīmu", Row {0}: Please set the correct code on Mode of Payment {1},"{0} rinda: lūdzu, maksājuma režīmā {1} iestatiet pareizo kodu.", -Row {0}: Qty is mandatory,Rinda {0}: Daudz ir obligāta, Row {0}: Quality Inspection rejected for item {1},{0} rinda: {1} vienumam noraidīta kvalitātes pārbaude, Row {0}: UOM Conversion Factor is mandatory,Row {0}: UOM Conversion Factor ir obligāta, Row {0}: select the workstation against the operation {1},Rinda {0}: izvēlieties darbstaciju pret operāciju {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Izdošanas veids., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Šķiet, ka pastāv servera joslas konfigurācijas problēma. Neveiksmes gadījumā summa tiks atmaksāta jūsu kontā.", Item Reported,Paziņots vienums, Item listing removed,Vienumu saraksts ir noņemts, -Item quantity can not be zero,Vienības daudzums nedrīkst būt nulle, Item taxes updated,Vienumu nodokļi ir atjaunināti, Item {0}: {1} qty produced. ,Vienība {0}: {1} saražots, Joining Date can not be greater than Leaving Date,Pievienošanās datums nevar būt lielāks par aiziešanas datumu, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},{0}. Rinda: izmaksu centrs {1} nepieder uzņēmumam {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,"{0}. Rinda: operācija {1} nav pabeigta {2} darba pasūtījumā norādīto gatavo preču daudzumam. Lūdzu, atjauniniet darbības statusu, izmantojot darba karti {4}.", Row #{0}: Payment document is required to complete the transaction,"# 0. Rinda: maksājuma dokuments ir nepieciešams, lai pabeigtu darījumu", +Row #{0}: Quantity for Item {1} cannot be zero.,# {0}. Rinda: Vienības {1} daudzums nedrīkst būt nulle., Row #{0}: Serial No {1} does not belong to Batch {2},{0}. Rinda: kārtas numurs {1} nepieder pie {2} partijas, Row #{0}: Service End Date cannot be before Invoice Posting Date,# 0. Rinda: pakalpojuma beigu datums nevar būt pirms rēķina nosūtīšanas datuma, Row #{0}: Service Start Date cannot be greater than Service End Date,# 0. Rinda: pakalpojuma sākuma datums nevar būt lielāks par pakalpojuma beigu datumu, diff --git a/erpnext/translations/mk.csv b/erpnext/translations/mk.csv index 0a290198cc..3742ad2522 100644 --- a/erpnext/translations/mk.csv +++ b/erpnext/translations/mk.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,"Ред {0}: Ве молиме, поставете ја причината за ослободување од данок во даноците на продажба и наплата", Row {0}: Please set the Mode of Payment in Payment Schedule,Ред {0}: Поставете го начинот на плаќање во распоредот за плаќање, Row {0}: Please set the correct code on Mode of Payment {1},Ред {0}: Ве молиме поставете го точниот код на начинот на плаќање {1}, -Row {0}: Qty is mandatory,Ред {0}: Количина е задолжително, Row {0}: Quality Inspection rejected for item {1},Ред {0}: Инспекција за квалитет одбиена за ставка {1}, Row {0}: UOM Conversion Factor is mandatory,Ред {0}: UOM конверзија фактор е задолжително, Row {0}: select the workstation against the operation {1},Ред {0}: изберете работна станица против операцијата {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Тип на издание., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Се чини дека постои проблем со конфигурацијата на шаблонот на серверот. Во случај на неуспех, износот ќе ви биде вратен на вашата сметка.", Item Reported,Објавено на точка, Item listing removed,Листата со предмети е отстранета, -Item quantity can not be zero,Количината на артикалот не може да биде нула, Item taxes updated,Ажурираат даноците за артиклите, Item {0}: {1} qty produced. ,Ставка {0}: {1} количество произведено., Joining Date can not be greater than Leaving Date,Датумот на пристапување не може да биде поголем од датумот на напуштање, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Ред # {0}: Центар за трошоци {1} не припаѓа на компанијата {2, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,"Ред # {0}: Операцијата {1} не е завршена за {2 ty количина на готови производи во редот на работа {3. Ве молиме, ажурирајте го статусот на работењето преку Job 4 Card картичка за работа.", Row #{0}: Payment document is required to complete the transaction,Ред # {0}: Потребен е документ за плаќање за да се заврши трансакцијата, +Row #{0}: Quantity for Item {1} cannot be zero.,Ред # {0}: Количината на артикалот {1} не може да биде нула, Row #{0}: Serial No {1} does not belong to Batch {2},Ред # {0}: Сериски бр {1} не припаѓа на Серија {2, Row #{0}: Service End Date cannot be before Invoice Posting Date,Ред # {0}: Датумот на завршување на услугата не може да биде пред датумот на објавување на фактурата, Row #{0}: Service Start Date cannot be greater than Service End Date,Ред # {0}: Датумот на започнување со услугата не може да биде поголем од датумот на завршување на услугата, diff --git a/erpnext/translations/ml.csv b/erpnext/translations/ml.csv index 04af8ab1ad..bc3df86b57 100644 --- a/erpnext/translations/ml.csv +++ b/erpnext/translations/ml.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,വരി {0}: വിൽപ്പന നികുതികളിലും നിരക്കുകളിലും നികുതി ഇളവ് കാരണം സജ്ജമാക്കുക, Row {0}: Please set the Mode of Payment in Payment Schedule,വരി {0}: പേയ്‌മെന്റ് ഷെഡ്യൂളിൽ പേയ്‌മെന്റ് മോഡ് സജ്ജമാക്കുക, Row {0}: Please set the correct code on Mode of Payment {1},വരി {0}: പേയ്‌മെന്റ് മോഡിൽ ശരിയായ കോഡ് ദയവായി സജ്ജമാക്കുക {1}, -Row {0}: Qty is mandatory,വരി {0}: Qty നിർബന്ധമായും, Row {0}: Quality Inspection rejected for item {1},വരി {0}: ഇനം {1} എന്നതിനുള്ള ക്വാളിറ്റി ഇൻസെക്ഷൻ നിരസിച്ചു, Row {0}: UOM Conversion Factor is mandatory,വരി {0}: UOM പരിവർത്തന ഫാക്ടർ നിർബന്ധമായും, Row {0}: select the workstation against the operation {1},വരി {0}: against 1 operation പ്രവർത്തനത്തിനെതിരെ വർക്ക്സ്റ്റേഷൻ തിരഞ്ഞെടുക്കുക, @@ -3461,7 +3460,6 @@ Issue Type.,ലക്കം തരം., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","സെർവറിന്റെ സ്ട്രൈക്ക് കോൺഫിഗറേഷനിൽ ഒരു പ്രശ്നമുണ്ടെന്ന് തോന്നുന്നു. പരാജയപ്പെട്ടാൽ, നിങ്ങളുടെ അക്കൗണ്ടിലേക്ക് തുക തിരികെ നൽകും.", Item Reported,ഇനം റിപ്പോർട്ടുചെയ്‌തു, Item listing removed,ഇന ലിസ്റ്റിംഗ് നീക്കംചെയ്‌തു, -Item quantity can not be zero,ഇനത്തിന്റെ അളവ് പൂജ്യമാകരുത്, Item taxes updated,ഇന നികുതികൾ അപ്‌ഡേറ്റുചെയ്‌തു, Item {0}: {1} qty produced. ,ഇനം {0}: {1} qty നിർമ്മിച്ചു., Joining Date can not be greater than Leaving Date,ചേരുന്ന തീയതി വിടുന്ന തീയതിയെക്കാൾ വലുതായിരിക്കരുത്, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},വരി # {0}: കോസ്റ്റ് സെന്റർ {1 company കമ്പനിയുടേതല്ല {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,വരി # {0}: വർക്ക് ഓർഡർ {3 in ലെ finished 2} qty പൂർത്തിയായ സാധനങ്ങൾക്കായി {1 operation പ്രവർത്തനം പൂർത്തിയായിട്ടില്ല. ജോബ് കാർഡ് via 4 via വഴി പ്രവർത്തന നില അപ്‌ഡേറ്റുചെയ്യുക., Row #{0}: Payment document is required to complete the transaction,വരി # {0}: ഇടപാട് പൂർത്തിയാക്കാൻ പേയ്‌മെന്റ് പ്രമാണം ആവശ്യമാണ്, +Row #{0}: Quantity for Item {1} cannot be zero.,വരി # {0}: ഇനം {1} ന്റെ അളവ് പൂജ്യമാകരുത്, Row #{0}: Serial No {1} does not belong to Batch {2},വരി # {0}: സീരിയൽ നമ്പർ {1 B ബാച്ച് {2 to ൽ ഉൾപ്പെടുന്നില്ല, Row #{0}: Service End Date cannot be before Invoice Posting Date,വരി # {0}: സേവന അവസാന തീയതി ഇൻവോയ്സ് പോസ്റ്റുചെയ്യുന്ന തീയതിക്ക് മുമ്പായിരിക്കരുത്, Row #{0}: Service Start Date cannot be greater than Service End Date,വരി # {0}: സേവന ആരംഭ തീയതി സേവന അവസാന തീയതിയേക്കാൾ കൂടുതലാകരുത്, diff --git a/erpnext/translations/mr.csv b/erpnext/translations/mr.csv index 785ab65c54..3059182401 100644 --- a/erpnext/translations/mr.csv +++ b/erpnext/translations/mr.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,पंक्ती {0}: कृपया विक्री कर आणि शुल्कामध्ये कर सूट कारण सेट करा, Row {0}: Please set the Mode of Payment in Payment Schedule,पंक्ती {0}: कृपया देय वेळापत्रकात देय मोड सेट करा, Row {0}: Please set the correct code on Mode of Payment {1},पंक्ती {0}: कृपया देयक मोडवर योग्य कोड सेट करा {1}, -Row {0}: Qty is mandatory,रो {0}: Qty अनिवार्य आहे, Row {0}: Quality Inspection rejected for item {1},पंक्ती {0}: आयटमसाठी गुणवत्ता तपासणी नाकारली {1}, Row {0}: UOM Conversion Factor is mandatory,रो {0}: UOM रुपांतर फॅक्टर अनिवार्य आहे, Row {0}: select the workstation against the operation {1},पंक्ती {0}: कार्याच्या विरूद्ध वर्कस्टेशन निवडा {1}, @@ -3461,7 +3460,6 @@ Issue Type.,इश्यूचा प्रकार, "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","असे दिसते की सर्व्हरच्या स्ट्रीप कॉन्फिगरेशनमध्ये एक समस्या आहे. अयशस्वी झाल्यास, रक्कम आपल्या खात्यात परत केली जाईल.", Item Reported,आयटम नोंदविला, Item listing removed,आयटम सूची काढली, -Item quantity can not be zero,आयटमचे प्रमाण शून्य असू शकत नाही, Item taxes updated,आयटम कर अद्यतनित केला, Item {0}: {1} qty produced. ,आयटम {0}: produced 1} क्विट उत्पादन केले., Joining Date can not be greater than Leaving Date,सामील होण्याची तारीख सोडण्याची तारीख सोडून जास्त असू शकत नाही, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},पंक्ती # {0}: किंमत केंद्र {1 company कंपनी to 2 belong चे नाही, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,पंक्ती # {0}: कार्य ऑर्डर {3 in मध्ये तयार केलेल्या वस्तूंच्या {2} क्वाइटीसाठी ऑपरेशन {1} पूर्ण झाले नाही. कृपया जॉब कार्ड via 4 via द्वारे ऑपरेशन स्थिती अद्यतनित करा., Row #{0}: Payment document is required to complete the transaction,पंक्ती # {0}: व्यवहार पूर्ण करण्यासाठी पेमेंट दस्तऐवज आवश्यक आहे, +Row #{0}: Quantity for Item {1} cannot be zero.,पंक्ती # {0}: आयटम {1} चे प्रमाण शून्य असू शकत नाही, Row #{0}: Serial No {1} does not belong to Batch {2},पंक्ती # {0}: अनुक्रमांक {1 B बॅच belong 2 belong चे नाही, Row #{0}: Service End Date cannot be before Invoice Posting Date,पंक्ती # {0}: सेवा समाप्ती तारीख चलन पोस्टिंग तारखेच्या आधीची असू शकत नाही, Row #{0}: Service Start Date cannot be greater than Service End Date,पंक्ती # {0}: सेवा प्रारंभ तारीख सेवा समाप्तीच्या तारखेपेक्षा मोठी असू शकत नाही, diff --git a/erpnext/translations/ms.csv b/erpnext/translations/ms.csv index db20d3c054..d33f9b8ca4 100644 --- a/erpnext/translations/ms.csv +++ b/erpnext/translations/ms.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Baris {0}: Sila tetapkan pada Alasan Pengecualian Cukai dalam Cukai Jualan dan Caj, Row {0}: Please set the Mode of Payment in Payment Schedule,Baris {0}: Sila tetapkan Mod Pembayaran dalam Jadual Pembayaran, Row {0}: Please set the correct code on Mode of Payment {1},Baris {0}: Sila tetapkan kod yang betul pada Mod Pembayaran {1}, -Row {0}: Qty is mandatory,Row {0}: Qty adalah wajib, Row {0}: Quality Inspection rejected for item {1},Baris {0}: Pemeriksaan Kualiti ditolak untuk item {1}, Row {0}: UOM Conversion Factor is mandatory,Row {0}: Faktor Penukaran UOM adalah wajib, Row {0}: select the workstation against the operation {1},Baris {0}: pilih stesen kerja terhadap operasi {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Jenis Terbitan., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Nampaknya terdapat masalah dengan tatarajah jalur pelayan. Sekiranya gagal, amaun akan dikembalikan ke akaun anda.", Item Reported,Item Dilaporkan, Item listing removed,Penyenaraian item dibuang, -Item quantity can not be zero,Kuantiti item tidak boleh menjadi sifar, Item taxes updated,Cukai item dikemas kini, Item {0}: {1} qty produced. ,Perkara {0}: {1} qty dihasilkan., Joining Date can not be greater than Leaving Date,Tarikh Bergabung tidak boleh lebih besar daripada Tarikh Meninggalkan, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Baris # {0}: Pusat Kos {1} tidak tergolong dalam syarikat {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Baris # {0}: Operasi {1} tidak siap untuk {2} qty barangan siap dalam Perintah Kerja {3}. Sila kemas kini status operasi melalui Job Job {4}., Row #{0}: Payment document is required to complete the transaction,Baris # {0}: Dokumen pembayaran diperlukan untuk menyelesaikan transaksi, +Row #{0}: Quantity for Item {1} cannot be zero.,Baris # {0}: Kuantiti item {1} tidak boleh menjadi sifar., Row #{0}: Serial No {1} does not belong to Batch {2},Baris # {0}: Siri Tidak {1} tidak tergolong dalam Batch {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Baris # {0}: Tarikh Akhir Perkhidmatan tidak boleh sebelum Tarikh Penyerahan Invois, Row #{0}: Service Start Date cannot be greater than Service End Date,Baris # {0}: Tarikh Mula Perkhidmatan tidak boleh melebihi Tarikh Akhir Perkhidmatan, diff --git a/erpnext/translations/my.csv b/erpnext/translations/my.csv index f4b8676fee..c447e663d4 100644 --- a/erpnext/translations/my.csv +++ b/erpnext/translations/my.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,အတန်း {0}: အရောင်းအခွန်နှင့်စွပ်စွဲချက်အတွက်အခွန်ကင်းလွတ်ခွင့်အကြောင်းပြချက်မှာသတ်မှတ်ထား ကျေးဇူးပြု., Row {0}: Please set the Mode of Payment in Payment Schedule,အတန်း {0}: ငွေပေးချေမှုရမည့်ဇယားများတွင်ငွေပေးချေ၏ Mode ကိုသတ်မှတ်ပေးပါ, Row {0}: Please set the correct code on Mode of Payment {1},အတန်း {0}: ငွေပေးချေမှုရမည့်၏ Mode ကို {1} အပေါ်မှန်ကန်သောကုဒ်သတ်မှတ်ပေးပါ, -Row {0}: Qty is mandatory,row {0}: Qty မသင်မနေရ, Row {0}: Quality Inspection rejected for item {1},အတန်း {0}: အရည်အသွေးစစ်ဆေးရေးကို item များအတွက် {1} ပယ်ချ, Row {0}: UOM Conversion Factor is mandatory,row {0}: UOM ကူးပြောင်းခြင်း Factor နဲ့မဖြစ်မနေဖြစ်ပါသည်, Row {0}: select the workstation against the operation {1},အတန်း {0}: စစ်ဆင်ရေး {1} ဆန့်ကျင်ကို Workstation ကို select, @@ -3461,7 +3460,6 @@ Issue Type.,ပြဿနာအမျိုးအစား။, "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","ဒါဟာဆာဗာ၏အစင်း configuration နဲ့အတူပြဿနာရှိကွောငျးပုံရသည်။ ကျရှုံးခြင်း၏အမှု၌, ပမာဏကိုသင့်အကောင့်ပြန်အမ်းရပါလိမ့်မယ်။", Item Reported,item နားဆင်နိုင်ပါတယ်, Item listing removed,စာရင်းစာရင်းဖယ်ရှားခဲ့သည်, -Item quantity can not be zero,item အရေအတွက်သုညမဖွစျနိုငျ, Item taxes updated,ပစ္စည်းအခွန် updated, Item {0}: {1} qty produced. ,item {0}: ထုတ်လုပ် {1} အရေအတွက်။, Joining Date can not be greater than Leaving Date,ရက်စွဲတွဲထားခြင်းသည်ထွက်ခွာသည့်နေ့ထက်မကြီးနိုင်ပါ, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},တန်း # {0} - ကုန်ကျစရိတ်စင်တာ {1} သည်ကုမ္ပဏီ {2} နှင့်မသက်ဆိုင်ပါ။, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,အတန်း # {0}: စစ်ဆင်ရေး {1} လုပ်ငန်းခွင်အမိန့် {3} အတွက်ချောကုန်စည် {2} အရည်အတွက်အဘို့အပြီးစီးခဲ့သည်မဟုတ်။ ယောဘသည် Card ကို {4} ကနေတဆင့်စစ်ဆင်ရေး status ကို update လုပ်ပါ။, Row #{0}: Payment document is required to complete the transaction,အတန်း # {0}: ငွေပေးချေမှုရမည့်စာရွက်စာတမ်းငွေပေးငွေယူဖြည့်စွက်ရန်လိုအပ်ပါသည်, +Row #{0}: Quantity for Item {1} cannot be zero.,အတန်း # {0}: item {1} အရေအတွက်သုညမဖွစျနိုငျ, Row #{0}: Serial No {1} does not belong to Batch {2},Row # {0} - Serial No {1} သည် Batch {2} နှင့်မသက်ဆိုင်ပါ။, Row #{0}: Service End Date cannot be before Invoice Posting Date,တန်း # {0} - ငွေတောင်းခံလွှာတင်သည့်နေ့မတိုင်မီဝန်ဆောင်မှုအဆုံးနေ့မဖြစ်နိုင်ပါ, Row #{0}: Service Start Date cannot be greater than Service End Date,Row # {0}: Service Start Date သည် Service End Date ထက်မကြီးနိုင်ပါ, diff --git a/erpnext/translations/nl.csv b/erpnext/translations/nl.csv index 1778c8044a..83632dfe5b 100644 --- a/erpnext/translations/nl.csv +++ b/erpnext/translations/nl.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Rij {0}: Stel in op Belastingvrijstellingsreden in omzetbelasting en kosten, Row {0}: Please set the Mode of Payment in Payment Schedule,Rij {0}: stel de Betalingswijze in Betalingsschema in, Row {0}: Please set the correct code on Mode of Payment {1},Rij {0}: stel de juiste code in op Betalingswijze {1}, -Row {0}: Qty is mandatory,Rij {0}: aantal is verplicht, Row {0}: Quality Inspection rejected for item {1},Rij {0}: kwaliteitscontrole afgewezen voor artikel {1}, Row {0}: UOM Conversion Factor is mandatory,Rij {0}: Verpakking Conversie Factor is verplicht, Row {0}: select the workstation against the operation {1},Rij {0}: selecteer het werkstation tegen de bewerking {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Soort probleem., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Het lijkt erop dat er een probleem is met de streepconfiguratie van de server. In het geval van een fout, wordt het bedrag teruggestort op uw account.", Item Reported,Artikel gemeld, Item listing removed,Itemvermelding verwijderd, -Item quantity can not be zero,Artikelhoeveelheid kan niet nul zijn, Item taxes updated,Artikelbelastingen bijgewerkt, Item {0}: {1} qty produced. ,Artikel {0}: {1} aantal geproduceerd., Joining Date can not be greater than Leaving Date,Inschrijvingsdatum kan niet groter zijn dan de uittredingsdatum, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Rij # {0}: Kostenplaats {1} hoort niet bij bedrijf {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Rij # {0}: bewerking {1} is niet voltooid voor {2} aantal voltooide goederen in werkorder {3}. Werk de bedieningsstatus bij via opdrachtkaart {4}., Row #{0}: Payment document is required to complete the transaction,Rij # {0}: Betalingsdocument is vereist om de transactie te voltooien, +Row #{0}: Quantity for Item {1} cannot be zero.,Rij # {0}: Artikelhoeveelheid voor item {1} kan niet nul zijn., Row #{0}: Serial No {1} does not belong to Batch {2},Rij # {0}: Serienummer {1} hoort niet bij Batch {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Rij # {0}: Einddatum van de service kan niet vóór de boekingsdatum van de factuur liggen, Row #{0}: Service Start Date cannot be greater than Service End Date,Rij # {0}: Service startdatum kan niet groter zijn dan service einddatum, diff --git a/erpnext/translations/no.csv b/erpnext/translations/no.csv index 542217afe7..50af62ff4b 100644 --- a/erpnext/translations/no.csv +++ b/erpnext/translations/no.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Rad {0}: Vennligst angi grunn for skattefritak i moms og avgifter, Row {0}: Please set the Mode of Payment in Payment Schedule,Rad {0}: Angi betalingsmåte i betalingsplanen, Row {0}: Please set the correct code on Mode of Payment {1},Rad {0}: Angi riktig kode på betalingsmåte {1}, -Row {0}: Qty is mandatory,Rad {0}: Antall er obligatorisk, Row {0}: Quality Inspection rejected for item {1},Rad {0}: Kvalitetskontroll avvist for varen {1}, Row {0}: UOM Conversion Factor is mandatory,Rad {0}: målenheter omregningsfaktor er obligatorisk, Row {0}: select the workstation against the operation {1},Row {0}: velg arbeidsstasjonen mot operasjonen {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Utgavetype., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.",Det ser ut til at det er et problem med serverens stripekonfigurasjon. I tilfelle feil blir beløpet refundert til kontoen din., Item Reported,Artikkel rapportert, Item listing removed,Vareoppføringen er fjernet, -Item quantity can not be zero,Varenummer kan ikke være null, Item taxes updated,Vareskatter oppdatert, Item {0}: {1} qty produced. ,Vare {0}: {1} antall produsert., Joining Date can not be greater than Leaving Date,Deltagelsesdato kan ikke være større enn Leaving Date, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Rad # {0}: Kostnadssenter {1} tilhører ikke selskapet {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Rad # {0}: Betjening {1} er ikke fullført for {2} antall ferdige varer i arbeidsordre {3}. Oppdater driftsstatus via Jobbkort {4}., Row #{0}: Payment document is required to complete the transaction,Rad # {0}: Betalingsdokument er påkrevd for å fullføre transaksjonen, +Row #{0}: Quantity for Item {1} cannot be zero.,Rad #{0}: Varenummer {1} kan ikke være null., Row #{0}: Serial No {1} does not belong to Batch {2},Rad # {0}: Serienummer {1} hører ikke til gruppe {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Rad nr. {0}: Sluttdato for service kan ikke være før faktureringsdato, Row #{0}: Service Start Date cannot be greater than Service End Date,Rad # {0}: Service-startdato kan ikke være større enn sluttidspunkt for tjeneste, diff --git a/erpnext/translations/pl.csv b/erpnext/translations/pl.csv index 247d0bae11..9d1f528aa2 100644 --- a/erpnext/translations/pl.csv +++ b/erpnext/translations/pl.csv @@ -2258,7 +2258,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Wiersz {0}: należy ustawić w Powodzie zwolnienia z podatku w podatkach od sprzedaży i opłatach, Row {0}: Please set the Mode of Payment in Payment Schedule,Wiersz {0}: ustaw tryb płatności w harmonogramie płatności, Row {0}: Please set the correct code on Mode of Payment {1},Wiersz {0}: ustaw prawidłowy kod w trybie płatności {1}, -Row {0}: Qty is mandatory,Wiersz {0}: Ilość jest obowiązkowe, Row {0}: Quality Inspection rejected for item {1},Wiersz {0}: Kontrola jakości odrzucona dla elementu {1}, Row {0}: UOM Conversion Factor is mandatory,Wiersz {0}: JM Współczynnik konwersji jest obowiązkowe, Row {0}: select the workstation against the operation {1},Wiersz {0}: wybierz stację roboczą w stosunku do operacji {1}, @@ -3435,7 +3434,6 @@ Issue Type.,Typ problemu., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Wygląda na to, że istnieje problem z konfiguracją pasków serwera. W przypadku niepowodzenia kwota zostanie zwrócona na Twoje konto.", Item Reported,Zgłoszony element, Item listing removed,Usunięto listę produktów, -Item quantity can not be zero,Ilość towaru nie może wynosić zero, Item taxes updated,Zaktualizowano podatki od towarów, Item {0}: {1} qty produced. ,Produkt {0}: wyprodukowano {1} sztuk., Joining Date can not be greater than Leaving Date,Data dołączenia nie może być większa niż Data opuszczenia, @@ -3607,6 +3605,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Wiersz # {0}: Centrum kosztów {1} nie należy do firmy {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Wiersz # {0}: operacja {1} nie została zakończona dla {2} ilości gotowych produktów w zleceniu pracy {3}. Zaktualizuj status operacji za pomocą karty pracy {4}., Row #{0}: Payment document is required to complete the transaction,Wiersz # {0}: dokument płatności jest wymagany do zakończenia transakcji, +Row #{0}: Quantity for Item {1} cannot be zero.,Wiersz # {0}: Ilość towaru {1} nie może wynosić zero, Row #{0}: Serial No {1} does not belong to Batch {2},Wiersz # {0}: numer seryjny {1} nie należy do partii {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Wiersz # {0}: data zakończenia usługi nie może być wcześniejsza niż data księgowania faktury, Row #{0}: Service Start Date cannot be greater than Service End Date,Wiersz # {0}: data rozpoczęcia usługi nie może być większa niż data zakończenia usługi, diff --git a/erpnext/translations/ps.csv b/erpnext/translations/ps.csv index 09d4df31ff..23480b5426 100644 --- a/erpnext/translations/ps.csv +++ b/erpnext/translations/ps.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,قطار {0}: مهرباني وکړئ د پلور مالیات او لګښتونو کې د مالیې معافیت دلیل تنظیم کړئ, Row {0}: Please set the Mode of Payment in Payment Schedule,قطار {0}: مهرباني وکړئ د تادیې مهال ویش کې د تادیې حالت تنظیم کړئ, Row {0}: Please set the correct code on Mode of Payment {1},قطار {0}: مهرباني وکړئ د تادیې په حالت کې سم کوډ تنظیم کړئ {1}, -Row {0}: Qty is mandatory,د کتارونو تر {0}: Qty الزامی دی, Row {0}: Quality Inspection rejected for item {1},قطار {0}: د توکي {1} لپاره د کیفیت تفتیش رد شو, Row {0}: UOM Conversion Factor is mandatory,د کتارونو تر {0}: UOM د تغیر فکتور الزامی دی, Row {0}: select the workstation against the operation {1},Row {0}: د عملیات په وړاندې د کارسټنشن غوره کول {1}, @@ -3461,7 +3460,6 @@ Issue Type.,د مسلې ډول., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.",داسې ښکاري چې د سرور د پټې ترتیب سره یو مسله شتون لري. د ناکامۍ په صورت کې، ستاسو د حساب رقم به بیرته ترلاسه شي., Item Reported,توکی راپور شوی, Item listing removed,د توکو لیست ایستل شوی, -Item quantity can not be zero,د توکو مقدار صفر نشي کیدی, Item taxes updated,د توکو مالیه تازه شوه, Item {0}: {1} qty produced. ,توکی {0}: {1} Qty تولید شو., Joining Date can not be greater than Leaving Date,د نیټې ایښودل د نیټې نیولو څخه لوی نشي, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},قطار # {0}: د لګښت مرکز {1 company د شرکت {2 belong پورې اړه نلري., Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,قطار # {0}: په Order 3} کاري ترتیب کې د goods 2} Qty بشپړ شوي توکو لپاره عملیات {1} ندي بشپړ شوي. مهرباني وکړئ د دندو کارت via 4 via له لارې د عملیاتو حالت تازه کړئ., Row #{0}: Payment document is required to complete the transaction,قطار # {0}: د معاملې بشپړولو لپاره د تادیې سند اړین دی, +Row #{0}: Quantity for Item {1} cannot be zero.,قطار # {0}: د {1} توکو مقدار صفر نشي کیدی, Row #{0}: Serial No {1} does not belong to Batch {2},قطار # {0}: سیریل {1} د بیچ {2 belong سره تړاو نه لري, Row #{0}: Service End Date cannot be before Invoice Posting Date,قطار # {0}: د خدمت پای پای نیټه د انوائس پوسټ کولو نیټې څخه مخکې نشي کیدی, Row #{0}: Service Start Date cannot be greater than Service End Date,قطار # {0}: د خدماتو د پیل نیټه د خدمت پای نیټې څخه لوی نشي, diff --git a/erpnext/translations/pt-BR.csv b/erpnext/translations/pt-BR.csv index 92845b0a40..c904e5e149 100644 --- a/erpnext/translations/pt-BR.csv +++ b/erpnext/translations/pt-BR.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Linha {0}: Por Favor Defina o Motivo da Isenção de Impostos Em Impostos e Taxas de Vendas, Row {0}: Please set the Mode of Payment in Payment Schedule,Linha {0}: Por Favor Defina o Modo de Pagamento na Programação de Pagamento, Row {0}: Please set the correct code on Mode of Payment {1},Linha {0}: Por favor defina o código correto em Modo de pagamento {1}, -Row {0}: Qty is mandatory,Linha {0}: Qtde é obrigatória, Row {0}: Quality Inspection rejected for item {1},Linha {0}: inspeção de qualidade rejeitada para o item {1}, Row {0}: UOM Conversion Factor is mandatory,Linha {0}: Fator de Conversão da Unidade de Medida é obrigatório, Row {0}: select the workstation against the operation {1},Linha {0}: selecione a estação de trabalho contra a operação {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Tipo de Incidente., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Parece que há um problema com a configuração de distribuição do servidor. Em caso de falha, o valor será reembolsado em sua conta.", Item Reported,Item Relatado, Item listing removed,Lista de itens removidos, -Item quantity can not be zero,Quantidade de item não pode ser zero, Item taxes updated,Impostos sobre itens atualizados, Item {0}: {1} qty produced. ,Item {0}: {1} quantidade produzida., Joining Date can not be greater than Leaving Date,A data de ingresso não pode ser maior que a data de saída, diff --git a/erpnext/translations/pt.csv b/erpnext/translations/pt.csv index 58cf6c8316..c8c5d061dc 100644 --- a/erpnext/translations/pt.csv +++ b/erpnext/translations/pt.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,"Linha {0}: Por favor, defina o Motivo da Isenção de Impostos em Impostos e Taxas de Vendas", Row {0}: Please set the Mode of Payment in Payment Schedule,"Linha {0}: Por favor, defina o modo de pagamento na programação de pagamento", Row {0}: Please set the correct code on Mode of Payment {1},"Linha {0}: Por favor, defina o código correto em Modo de pagamento {1}", -Row {0}: Qty is mandatory,Linha {0}: É obrigatório colocar a qtd, Row {0}: Quality Inspection rejected for item {1},Linha {0}: inspeção de qualidade rejeitada para o item {1}, Row {0}: UOM Conversion Factor is mandatory,Linha {0}: É obrigatório colocar o Fator de Conversão de UNID, Row {0}: select the workstation against the operation {1},Linha {0}: selecione a estação de trabalho contra a operação {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Tipo de problema., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Parece que há um problema com a configuração de distribuição do servidor. Em caso de falha, o valor será reembolsado em sua conta.", Item Reported,Item relatado, Item listing removed,Lista de itens removidos, -Item quantity can not be zero,Quantidade de item não pode ser zero, Item taxes updated,Impostos sobre itens atualizados, Item {0}: {1} qty produced. ,Item {0}: {1} quantidade produzida., Joining Date can not be greater than Leaving Date,A data de ingresso não pode ser maior que a data de saída, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Linha # {0}: o centro de custo {1} não pertence à empresa {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,"Linha # {0}: A operação {1} não está concluída para {2} quantidade de produtos acabados na Ordem de Serviço {3}. Por favor, atualize o status da operação através do Job Card {4}.", Row #{0}: Payment document is required to complete the transaction,Linha # {0}: documento de pagamento é necessário para concluir a transação, +Row #{0}: Quantity for Item {1} cannot be zero.,Linha # {0}: Quantidade de item {1} não pode ser zero., Row #{0}: Serial No {1} does not belong to Batch {2},Linha # {0}: o número de série {1} não pertence ao lote {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Linha # {0}: a data de término do serviço não pode ser anterior à data de lançamento da fatura, Row #{0}: Service Start Date cannot be greater than Service End Date,Linha # {0}: a data de início do serviço não pode ser maior que a data de término do serviço, diff --git a/erpnext/translations/ro.csv b/erpnext/translations/ro.csv index 935b1e66fd..d26b80379e 100644 --- a/erpnext/translations/ro.csv +++ b/erpnext/translations/ro.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Rândul {0}: Vă rugăm să setați motivul scutirii de taxe în impozitele și taxele de vânzare, Row {0}: Please set the Mode of Payment in Payment Schedule,Rândul {0}: Vă rugăm să setați modul de plată în programul de plată, Row {0}: Please set the correct code on Mode of Payment {1},Rândul {0}: Vă rugăm să setați codul corect pe Modul de plată {1}, -Row {0}: Qty is mandatory,Rând {0}: Cant este obligatorie, Row {0}: Quality Inspection rejected for item {1},Rândul {0}: Inspecția de calitate a fost respinsă pentru articolul {1}, Row {0}: UOM Conversion Factor is mandatory,Row {0}: Factorul de conversie UOM este obligatorie, Row {0}: select the workstation against the operation {1},Rând {0}: selectați stația de lucru pentru operația {1}, @@ -3460,7 +3459,6 @@ Issue Type.,Tipul problemei., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Se pare că există o problemă cu configurația benzii serverului. În caz de eșec, suma va fi rambursată în cont.", Item Reported,Articol raportat, Item listing removed,Elementul de articol a fost eliminat, -Item quantity can not be zero,Cantitatea articolului nu poate fi zero, Item taxes updated,Impozitele pe articol au fost actualizate, Item {0}: {1} qty produced. ,Articol {0}: {1} cantitate produsă., Joining Date can not be greater than Leaving Date,Data de înscriere nu poate fi mai mare decât Data de plecare, @@ -3632,6 +3630,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Rândul {{0}: Centrul de costuri {1} nu aparține companiei {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Rândul # {0}: Operația {1} nu este finalizată pentru {2} cantitate de mărfuri finite în Ordinul de lucru {3}. Vă rugăm să actualizați starea operației prin intermediul cărții de lucru {4}., Row #{0}: Payment document is required to complete the transaction,Rândul # {0}: documentul de plată este necesar pentru a finaliza tranzacția, +Row #{0}: Quantity for Item {1} cannot be zero.,Rândul # {0}: Cantitatea articolului {1} nu poate fi zero., Row #{0}: Serial No {1} does not belong to Batch {2},Rândul # {0}: nr. De serie {1} nu aparține lotului {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Rândul # {0}: Data de încheiere a serviciului nu poate fi înainte de Data de înregistrare a facturii, Row #{0}: Service Start Date cannot be greater than Service End Date,Rândul # {0}: Data de începere a serviciului nu poate fi mai mare decât Data de încheiere a serviciului, diff --git a/erpnext/translations/ru.csv b/erpnext/translations/ru.csv index 2f6f361b10..ec5421e444 100644 --- a/erpnext/translations/ru.csv +++ b/erpnext/translations/ru.csv @@ -2271,7 +2271,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Строка {0}: Укажите причину освобождения от уплаты налогов в разделе Налоги и сборы, Row {0}: Please set the Mode of Payment in Payment Schedule,"Строка {0}: пожалуйста, установите способ оплаты в графике платежей", Row {0}: Please set the correct code on Mode of Payment {1},Строка {0}: установите правильный код в способе оплаты {1}, -Row {0}: Qty is mandatory,Строка {0}: Кол-во является обязательным, Row {0}: Quality Inspection rejected for item {1},Строка {0}: проверка качества отклонена для элемента {1}, Row {0}: UOM Conversion Factor is mandatory,Строка {0}: Коэффициент преобразования единиц измерения является обязательным, Row {0}: select the workstation against the operation {1},Строка {0}: выберите рабочее место для операции {1}, @@ -3459,7 +3458,6 @@ Issue Type.,Тип проблемы., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Кажется, что существует проблема с конфигурацией полосок сервера. В случае сбоя сумма будет возвращена на ваш счет.", Item Reported,Товар сообщен, Item listing removed,Список товаров удален, -Item quantity can not be zero,Количество товара не может быть нулевым, Item taxes updated,Товарные налоги обновлены, Item {0}: {1} qty produced. ,Элемент {0}: произведено {1} кол-во. , Joining Date can not be greater than Leaving Date,"Дата вступления не может быть больше, чем Дата отъезда", @@ -3635,6 +3633,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Строка #{0}: МВЗ {1} не принадлежит компании {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,"Строка #{0}: операция {1} не завершена для {2} количества готовой продукции в рабочем задании {3}. Пожалуйста, обновите статус операции с помощью Карточки работ {4}.", Row #{0}: Payment document is required to complete the transaction,Строка #{0}: для завершения транзакции требуется платежный документ, +Row #{0}: Quantity for Item {1} cannot be zero.,Строка #{0}: Количество товара {1} не может быть нулевым, Row #{0}: Serial No {1} does not belong to Batch {2},Строка #{0}: серийный номер {1} не принадлежит партии {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Строка #{0}: дата окончания обслуживания не может быть раньше даты проводки счета, Row #{0}: Service Start Date cannot be greater than Service End Date,Строка #{0}: дата начала обслуживания не может быть больше даты окончания обслуживания, diff --git a/erpnext/translations/rw.csv b/erpnext/translations/rw.csv index 59362a1e29..66a530c996 100644 --- a/erpnext/translations/rw.csv +++ b/erpnext/translations/rw.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Umurongo {0}: Nyamuneka shyira kumpamvu yo gusonerwa imisoro mumisoro yagurishijwe, Row {0}: Please set the Mode of Payment in Payment Schedule,Umurongo {0}: Nyamuneka shiraho uburyo bwo Kwishura muri Gahunda yo Kwishura, Row {0}: Please set the correct code on Mode of Payment {1},Umurongo {0}: Nyamuneka shyira kode yukuri kuri Mode yo Kwishura {1}, -Row {0}: Qty is mandatory,Umurongo {0}: Qty ni itegeko, Row {0}: Quality Inspection rejected for item {1},Umurongo {0}: Igenzura ryiza ryanze kubintu {1}, Row {0}: UOM Conversion Factor is mandatory,Umurongo {0}: Ikintu cya UOM Guhindura ni itegeko, Row {0}: select the workstation against the operation {1},Umurongo {0}: hitamo ahakorerwa kurwanya ibikorwa {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Ubwoko bw'Ibibazo., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Birasa nkaho hari ikibazo hamwe na seriveri iboneza. Mugihe byananiranye, amafaranga azasubizwa kuri konte yawe.", Item Reported,Ingingo Yatanzwe, Item listing removed,Urutonde rwibintu rwakuweho, -Item quantity can not be zero,Ingano yikintu ntishobora kuba zeru, Item taxes updated,Imisoro yikintu ivugururwa, Item {0}: {1} qty produced. ,Ingingo {0}: {1} qty yakozwe., Joining Date can not be greater than Leaving Date,Kwinjira Itariki ntishobora kurenza Kureka Itariki, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Umurongo # {0}: Ikigo Centre {1} ntabwo ari icya sosiyete {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Umurongo # {0}: Igikorwa {1} nticyarangiye kuri {2} qty yibicuruzwa byarangiye murutonde rwakazi {3}. Nyamuneka vugurura imikorere ukoresheje ikarita y'akazi {4}., Row #{0}: Payment document is required to complete the transaction,Umurongo # {0}: Inyandiko yo kwishyura irasabwa kurangiza ibikorwa, +Row #{0}: Quantity for Item {1} cannot be zero.,Umurongo # {0}: Ingano yikintu {1} ntishobora kuba zeru., Row #{0}: Serial No {1} does not belong to Batch {2},Umurongo # {0}: Serial No {1} ntabwo ari iya Batch {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Umurongo # {0}: Itariki yo kurangiriraho ya serivisi ntishobora kuba mbere yitariki yo kohereza, Row #{0}: Service Start Date cannot be greater than Service End Date,Umurongo # {0}: Itariki yo Gutangiriraho Serivisi ntishobora kuba irenze Itariki yo kurangiriraho, diff --git a/erpnext/translations/si.csv b/erpnext/translations/si.csv index dd2acc45a2..168da5aded 100644 --- a/erpnext/translations/si.csv +++ b/erpnext/translations/si.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,පේළිය {0}: කරුණාකර විකුණුම් බදු සහ ගාස්තු සඳහා බදු නිදහස් කිරීමේ හේතුව සකසන්න, Row {0}: Please set the Mode of Payment in Payment Schedule,පේළිය {0}: කරුණාකර ගෙවීම් ක්‍රමය ගෙවීම් කාලසටහනට සකසන්න, Row {0}: Please set the correct code on Mode of Payment {1},පේළිය {0}: කරුණාකර නිවැරදි කේතය ගෙවීම් ක්‍රමයට සකසන්න {1}, -Row {0}: Qty is mandatory,ෙරෝ {0}: යවන ලද අනිවාර්ය වේ, Row {0}: Quality Inspection rejected for item {1},පේළිය {0}: තත්ත්ව පරීක්ෂාව අයිතමය සඳහා {1}, Row {0}: UOM Conversion Factor is mandatory,ෙරෝ {0}: UOM පරිවර්තන සාධකය අනිවාර්ය වේ, Row {0}: select the workstation against the operation {1},පේළිය {0}: මෙහෙයුමට එරෙහිව පරිගණකය තෝරා ගන්න {1}, @@ -3461,7 +3460,6 @@ Issue Type.,නිකුත් කිරීමේ වර්ගය., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","සර්වරයේ තීරු වින්යාසය සමඟ ගැටළුවක් පවතින බව පෙනේ. අසාර්ථකත්වයේ දී, එම මුදල ඔබේ ගිණුමට නැවත ලබා දෙනු ඇත.", Item Reported,අයිතමය වාර්තා කර ඇත, Item listing removed,අයිතම ලැයිස්තුගත කිරීම ඉවත් කරන ලදි, -Item quantity can not be zero,අයිතමයේ ප්‍රමාණය ශුන්‍ය විය නොහැක, Item taxes updated,අයිතම බදු යාවත්කාලීන කරන ලදි, Item {0}: {1} qty produced. ,අයිතමය {0}: {1} qty නිෂ්පාදනය., Joining Date can not be greater than Leaving Date,සම්බන්ධ වන දිනය නිවාඩු දිනයට වඩා වැඩි විය නොහැක, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},පේළිය # {0}: පිරිවැය මධ්‍යස්ථානය {1 company සමාගමට අයත් නොවේ {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,පේළිය # {0}: වැඩ ඇණවුමේ {3 in හි නිමි භාණ්ඩ {2} qty සඳහා {1 operation මෙහෙයුම සම්පූර්ණ නොවේ. කරුණාකර ජොබ් කාඩ් {4 via හරහා මෙහෙයුම් තත්ත්වය යාවත්කාලීන කරන්න., Row #{0}: Payment document is required to complete the transaction,පේළිය # {0}: ගනුදෙනුව සම්පූර්ණ කිරීම සඳහා ගෙවීම් ලේඛනය අවශ්‍ය වේ, +Row #{0}: Quantity for Item {1} cannot be zero.,පේළිය # {0}: අයිතමයේ {1} ප්‍රමාණය ශුන්‍ය විය නොහැක, Row #{0}: Serial No {1} does not belong to Batch {2},පේළිය # {0}: අනුක්‍රමික අංකය {1 B කණ්ඩායම {2 to ට අයත් නොවේ, Row #{0}: Service End Date cannot be before Invoice Posting Date,පේළිය # {0}: ඉන්වොයිසිය පළ කිරීමේ දිනයට පෙර සේවා අවසන් දිනය විය නොහැක, Row #{0}: Service Start Date cannot be greater than Service End Date,පේළිය # {0}: සේවා ආරම්භක දිනය සේවා අවසන් දිනයට වඩා වැඩි විය නොහැක, diff --git a/erpnext/translations/sk.csv b/erpnext/translations/sk.csv index 025c8b788f..e3323ddc9e 100644 --- a/erpnext/translations/sk.csv +++ b/erpnext/translations/sk.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Riadok {0}: V Dane z obratu a poplatkoch nastavte prosím na dôvod oslobodenia od dane, Row {0}: Please set the Mode of Payment in Payment Schedule,Riadok {0}: Nastavte si spôsob platby v pláne platieb, Row {0}: Please set the correct code on Mode of Payment {1},Riadok {0}: Nastavte správny kód v platobnom režime {1}, -Row {0}: Qty is mandatory,Row {0}: Množství je povinný, Row {0}: Quality Inspection rejected for item {1},Riadok {0}: Kontrola kvality zamietnutá pre položku {1}, Row {0}: UOM Conversion Factor is mandatory,Riadok {0}: Konverzný faktor MJ je povinný, Row {0}: select the workstation against the operation {1},Riadok {0}: vyberte pracovnú stanicu proti operácii {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Typ vydania., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Zdá sa, že existuje problém s konfiguráciou pásma servera. V prípade zlyhania bude suma vrátená na váš účet.", Item Reported,Položka bola nahlásená, Item listing removed,Zoznam položiek bol odstránený, -Item quantity can not be zero,Množstvo položky nemôže byť nula, Item taxes updated,Dane z tovaru boli aktualizované, Item {0}: {1} qty produced. ,Položka {0}: {1} vyprodukované množstvo., Joining Date can not be greater than Leaving Date,Dátum vstupu nemôže byť väčší ako dátum odchodu, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Riadok # {0}: Nákladové stredisko {1} nepatrí spoločnosti {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Riadok # {0}: Operácia {1} nie je dokončená pre {2} množstvo hotového tovaru v objednávke {3}. Aktualizujte prevádzkový stav prostredníctvom Job Card {4}., Row #{0}: Payment document is required to complete the transaction,Riadok # {0}: Na dokončenie transakcie je potrebný platobný doklad, +Row #{0}: Quantity for Item {1} cannot be zero.,Riadok # {0}: Množstvo položky {1} nemôže byť nula., Row #{0}: Serial No {1} does not belong to Batch {2},Riadok # {0}: Poradové číslo {1} nepatrí do šarže {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Riadok # {0}: Dátum ukončenia služby nemôže byť pred dátumom zaúčtovania faktúry, Row #{0}: Service Start Date cannot be greater than Service End Date,Riadok # {0}: Dátum začatia služby nemôže byť väčší ako dátum ukončenia služby, diff --git a/erpnext/translations/sl.csv b/erpnext/translations/sl.csv index 86b5e58129..2937afd703 100644 --- a/erpnext/translations/sl.csv +++ b/erpnext/translations/sl.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,"Vrstica {0}: Prosimo, nastavite Razlog oprostitve plačila davkov na promet in davkov", Row {0}: Please set the Mode of Payment in Payment Schedule,Vrstica {0}: v plačilni shemi nastavite način plačila, Row {0}: Please set the correct code on Mode of Payment {1},Vrstica {0}: nastavite pravilno kodo na način plačila {1}, -Row {0}: Qty is mandatory,Vrstica {0}: Kol je obvezna, Row {0}: Quality Inspection rejected for item {1},Vrstica {0}: pregled izdelka je zavrnjen za postavko {1}, Row {0}: UOM Conversion Factor is mandatory,Vrstica {0}: UOM Conversion Factor je obvezna, Row {0}: select the workstation against the operation {1},Vrstica {0}: izberite delovno postajo proti operaciji {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Vrsta izdaje, "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Zdi se, da obstaja težava s strežniško konfiguracijo črtne kode. V primeru neuspeha bo znesek povrnjen na vaš račun.", Item Reported,Element je prijavljen, Item listing removed,Seznam elementov je odstranjen, -Item quantity can not be zero,Količina artikla ne more biti nič, Item taxes updated,Davki na postavke so posodobljeni, Item {0}: {1} qty produced. ,Postavka {0}: {1} proizvedeno., Joining Date can not be greater than Leaving Date,Datum pridružitve ne sme biti večji od datuma zapustitve, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Vrstica # {0}: stroškovno središče {1} ne pripada podjetju {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Vrstica # {0}: Postopek {1} ni končan za {2} količino končnih izdelkov v delovnem naročilu {3}. Posodobite stanje delovanja s Job Card {4}., Row #{0}: Payment document is required to complete the transaction,Vrstica # {0}: Za dokončanje transakcije je potreben plačilni dokument, +Row #{0}: Quantity for Item {1} cannot be zero.,Vrstica # {0}: Količina artikla {1} ne more biti nič., Row #{0}: Serial No {1} does not belong to Batch {2},Vrstica # {0}: Serijska št. {1} ne spada v serijo {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Vrstica # {0}: Končni datum storitve ne sme biti pred datumom objave računa, Row #{0}: Service Start Date cannot be greater than Service End Date,Vrstica # {0}: datum začetka storitve ne sme biti večji od končnega datuma storitve, diff --git a/erpnext/translations/sq.csv b/erpnext/translations/sq.csv index 3cfa4297df..f3e68062b0 100644 --- a/erpnext/translations/sq.csv +++ b/erpnext/translations/sq.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Rreshti {0}: Ju lutemi vendosni arsyen e përjashtimit nga taksat në taksat dhe tarifat e shitjeve, Row {0}: Please set the Mode of Payment in Payment Schedule,Rreshti {0}: Ju lutemi vendosni Mënyrën e Pagesës në Programin e Pagesave, Row {0}: Please set the correct code on Mode of Payment {1},Rresht {0}: Ju lutemi vendosni kodin e saktë në mënyrën e pagesës {1}, -Row {0}: Qty is mandatory,Row {0}: Qty është e detyrueshme, Row {0}: Quality Inspection rejected for item {1},Rreshti {0}: Inspektimi i Cilësisë i refuzuar për artikullin {1}, Row {0}: UOM Conversion Factor is mandatory,Row {0}: UOM Konvertimi Faktori është i detyrueshëm, Row {0}: select the workstation against the operation {1},Rresht {0}: zgjidhni stacionin e punës kundër operacionit {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Lloji i çështjes., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Duket se ka një problem me konfigurimin e shiritit të serverit. Në rast të dështimit, shuma do të kthehet në llogarinë tuaj.", Item Reported,Njoftimi i raportuar, Item listing removed,Lista e sendeve u hoq, -Item quantity can not be zero,Sasia e sendit nuk mund të jetë zero, Item taxes updated,Taksat e sendeve azhurnohen, Item {0}: {1} qty produced. ,Artikulli {0}: {1} prodhohet., Joining Date can not be greater than Leaving Date,Data e anëtarësimit nuk mund të jetë më e madhe se data e largimit, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Rreshti # {0}: Qendra e Kostos {1} nuk i përket kompanisë {2, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Rreshti # {0}: Operacioni {1} nuk është përfunduar për 2 {sasi të mallrave të gatshëm në Rendin e Punës {3. Ju lutemi azhurnoni statusin e funksionimit përmes Kartës së Punës {4., Row #{0}: Payment document is required to complete the transaction,Rreshti # {0}: Dokumenti i pagesës kërkohet për të përfunduar transaksionin, +Row #{0}: Quantity for Item {1} cannot be zero.,Rreshti # {0}: Sasia e sendit {1} nuk mund të jetë zero., Row #{0}: Serial No {1} does not belong to Batch {2},Rreshti # {0}: Seriali Nr {1} nuk i përket Batch {2, Row #{0}: Service End Date cannot be before Invoice Posting Date,Rreshti # {0}: Data e mbarimit të shërbimit nuk mund të jetë përpara datës së postimit të faturës, Row #{0}: Service Start Date cannot be greater than Service End Date,Rreshti # {0}: Data e fillimit të shërbimit nuk mund të jetë më e madhe se data e përfundimit të shërbimit, diff --git a/erpnext/translations/sr.csv b/erpnext/translations/sr.csv index 621772f39f..d22a101a2a 100644 --- a/erpnext/translations/sr.csv +++ b/erpnext/translations/sr.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Ред {0}: Подесите разлог ослобађања од пореза у порезима и накнадама на промет, Row {0}: Please set the Mode of Payment in Payment Schedule,Ред {0}: Молимо вас да подесите Начин плаћања у Распореду плаћања, Row {0}: Please set the correct code on Mode of Payment {1},Ред {0}: Молимо поставите тачан код на Начин плаћања {1}, -Row {0}: Qty is mandatory,Ред {0}: Кол је обавезно, Row {0}: Quality Inspection rejected for item {1},Ред {0}: Инспекција квалитета одбијена за ставку {1}, Row {0}: UOM Conversion Factor is mandatory,Ред {0}: УОМ фактор конверзије је обавезна, Row {0}: select the workstation against the operation {1},Ред {0}: изаберите радну станицу против операције {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Врста издања., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Чини се да постоји проблем са конфигурацијом стрипе сервера. У случају неуспеха, износ ће бити враћен на ваш рачун.", Item Reported,Ставка пријављена, Item listing removed,Попис предмета је уклоњен, -Item quantity can not be zero,Количина предмета не може бити једнака нули, Item taxes updated,Ажурирани су порези на артикле, Item {0}: {1} qty produced. ,Ставка {0}: {1} Количина произведена., Joining Date can not be greater than Leaving Date,Датум придруживања не може бити већи од Датум напуштања, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Ред # {0}: Трошкови {1} не припада компанији {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Ред # {0}: Операција {1} није завршена за {2} Количина готових производа у радном налогу {3}. Ажурирајте статус рада путем Јоб Цард {4}., Row #{0}: Payment document is required to complete the transaction,Ред # {0}: За завршетак трансакције потребан је документ о плаћању, +Row #{0}: Quantity for Item {1} cannot be zero.,Ред # {0}: Количина предмета {1} не може бити једнака нули., Row #{0}: Serial No {1} does not belong to Batch {2},Ред # {0}: Серијски број {1} не припада групи {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Ред број # 0: Датум завршетка услуге не може бити прије датума књижења фактуре, Row #{0}: Service Start Date cannot be greater than Service End Date,Ред број # {0}: Датум почетка услуге не може бити већи од датума завршетка услуге, diff --git a/erpnext/translations/sv.csv b/erpnext/translations/sv.csv index 4fef88b7f4..66f707dabe 100644 --- a/erpnext/translations/sv.csv +++ b/erpnext/translations/sv.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Rad {0}: Vänligen ange skattefrihetsskäl i moms och avgifter, Row {0}: Please set the Mode of Payment in Payment Schedule,Rad {0}: Ange betalningsmetod i betalningsschema, Row {0}: Please set the correct code on Mode of Payment {1},Rad {0}: Ange rätt kod på betalningsmetod {1}, -Row {0}: Qty is mandatory,Rad {0}: Antal är obligatoriskt, Row {0}: Quality Inspection rejected for item {1},Rad {0}: Kvalitetskontroll avvisad för artikel {1}, Row {0}: UOM Conversion Factor is mandatory,Rad {0}: UOM Omvandlingsfaktor är obligatorisk, Row {0}: select the workstation against the operation {1},Rad {0}: välj arbetsstation mot operationen {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Problemtyp., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.",Det verkar som om det finns ett problem med serverns randkonfiguration. Vid fel kommer beloppet att återbetalas till ditt konto., Item Reported,Objekt rapporterat, Item listing removed,Objektlistan har tagits bort, -Item quantity can not be zero,Artikelkvantitet kan inte vara noll, Item taxes updated,Produktskatter uppdaterade, Item {0}: {1} qty produced. ,Objekt {0}: {1} producerad antal., Joining Date can not be greater than Leaving Date,Anslutningsdatum kan inte vara större än Leaving Date, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Rad # {0}: Cost Center {1} tillhör inte företaget {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Rad # {0}: Drift {1} är inte slutfört för {2} antal färdigvaror i arbetsordern {3}. Uppdatera driftsstatus via Jobbkort {4}., Row #{0}: Payment document is required to complete the transaction,Rad # {0}: Betalningsdokument krävs för att slutföra transaktionen, +Row #{0}: Quantity for Item {1} cannot be zero.,Rad # {0}: Artikelkvantitet för artikel {1} kan inte vara noll., Row #{0}: Serial No {1} does not belong to Batch {2},Rad # {0}: Serienummer {1} tillhör inte batch {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Rad nr {0}: Service slutdatum kan inte vara före fakturadatum, Row #{0}: Service Start Date cannot be greater than Service End Date,Rad # {0}: Service-startdatum kan inte vara större än slutdatum för service, diff --git a/erpnext/translations/sw.csv b/erpnext/translations/sw.csv index 3b4d8aee64..83ff58a738 100644 --- a/erpnext/translations/sw.csv +++ b/erpnext/translations/sw.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Row {0}: Tafadhali weka kwa Sababu ya Msamaha wa Ushuru katika Ushuru na Uuzaji, Row {0}: Please set the Mode of Payment in Payment Schedule,Njia {0}: Tafadhali seti Njia ya Malipo katika Ratiba ya Malipo, Row {0}: Please set the correct code on Mode of Payment {1},Safu {0}: Tafadhali seti nambari sahihi kwenye Njia ya Malipo {1}, -Row {0}: Qty is mandatory,Row {0}: Uchina ni lazima, Row {0}: Quality Inspection rejected for item {1},Safu {0}: Ukaguzi wa Ubora uliokataliwa kwa bidhaa {1}, Row {0}: UOM Conversion Factor is mandatory,Row {0}: Kipengele cha kubadilisha UOM ni lazima, Row {0}: select the workstation against the operation {1},Row {0}: chagua kituo cha kazi dhidi ya uendeshaji {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Aina ya Toleo., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Inaonekana kwamba kuna suala la usanidi wa stripe ya seva. Katika hali ya kushindwa, kiasi hicho kitarejeshwa kwa akaunti yako.", Item Reported,Bidhaa Imeripotiwa, Item listing removed,Orodha ya bidhaa imeondolewa, -Item quantity can not be zero,Wingi wa kitu hauwezi kuwa sifuri, Item taxes updated,Kodi ya bidhaa iliyosasishwa, Item {0}: {1} qty produced. ,Bidhaa {0}: {1} qty imetolewa, Joining Date can not be greater than Leaving Date,Kujiunga Tarehe haiwezi kuwa kubwa kuliko Tarehe ya Kuondoka, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Njia # {0}: Kituo cha Gharama {1} sio ya kampuni {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Njia # {0}: Operesheni {1} haijakamilika kwa {2} qty ya bidhaa kumaliza katika Agizo la Kazi {3}. Tafadhali sasisha hali ya operesheni kupitia Kadi ya kazi {4}., Row #{0}: Payment document is required to complete the transaction,Njia # {0}: Hati ya malipo inahitajika kukamilisha ununuzi, +Row #{0}: Quantity for Item {1} cannot be zero.,Njia # {0}: Wingi wa kitu {1} hauwezi kuwa sifuri, Row #{0}: Serial No {1} does not belong to Batch {2},Safu ya # {0}: Nambari ya Hapana {1} sio ya Kundi {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Njia # {0}: Tarehe ya Mwisho wa Huduma haiwezi kuwa kabla ya Tarehe ya Kutuma ankara, Row #{0}: Service Start Date cannot be greater than Service End Date,Safu # {0}: Tarehe ya Kuanza kwa Huduma haiwezi kuwa kubwa kuliko Tarehe ya Mwisho wa Huduma, diff --git a/erpnext/translations/ta.csv b/erpnext/translations/ta.csv index f40e512427..246fc9aa8f 100644 --- a/erpnext/translations/ta.csv +++ b/erpnext/translations/ta.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,வரிசை {0}: விற்பனை வரி மற்றும் கட்டணங்களில் வரி விலக்கு காரணத்தை அமைக்கவும், Row {0}: Please set the Mode of Payment in Payment Schedule,வரிசை {0}: கட்டணம் செலுத்தும் முறையை கட்டண அட்டவணையில் அமைக்கவும், Row {0}: Please set the correct code on Mode of Payment {1},வரிசை {0}: கட்டண முறையின் சரியான குறியீட்டை அமைக்கவும் {1}, -Row {0}: Qty is mandatory,ரோ {0}: அளவு கட்டாய ஆகிறது, Row {0}: Quality Inspection rejected for item {1},வரிசை {0}: உருப்படியை {1} க்கான தர ஆய்வு நிராகரிக்கப்பட்டது, Row {0}: UOM Conversion Factor is mandatory,ரோ {0}: UOM மாற்றக் காரணி கட்டாயமாகும், Row {0}: select the workstation against the operation {1},வரிசை {0}: நடவடிக்கைக்கு எதிராக பணிநிலையத்தைத் தேர்ந்தெடுக்கவும் {1}, @@ -3461,7 +3460,6 @@ Issue Type.,வெளியீட்டு வகை., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","சர்வர் ஸ்ட்ரீப் கட்டமைப்பில் சிக்கல் இருப்பதாகத் தோன்றுகிறது. தோல்வி ஏற்பட்டால், உங்கள் கணக்கில் பணம் திரும்பப்பெறப்படும்.", Item Reported,பொருள் புகாரளிக்கப்பட்டது, Item listing removed,உருப்படி பட்டியல் நீக்கப்பட்டது, -Item quantity can not be zero,பொருளின் அளவு பூஜ்ஜியமாக இருக்க முடியாது, Item taxes updated,பொருள் வரி புதுப்பிக்கப்பட்டது, Item {0}: {1} qty produced. ,பொருள் {0}: {1} qty தயாரிக்கப்பட்டது., Joining Date can not be greater than Leaving Date,சேரும் தேதியை விட்டு வெளியேறுவதை விட அதிகமாக இருக்க முடியாது, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},வரிசை # {0}: செலவு மையம் {1 company நிறுவனத்திற்கு சொந்தமில்லை {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,வரிசை # {0}: பணி ஆணை {3 in இல் finished 2} qty முடிக்கப்பட்ட பொருட்களுக்கு {1 operation செயல்பாடு முடிக்கப்படவில்லை. வேலை அட்டை {4 via வழியாக செயல்பாட்டு நிலையை புதுப்பிக்கவும்., Row #{0}: Payment document is required to complete the transaction,வரிசை # {0}: பரிவர்த்தனையை முடிக்க கட்டண ஆவணம் தேவை, +Row #{0}: Quantity for Item {1} cannot be zero.,வரிசை # {0}: பொருளின் {1} அளவு பூஜ்ஜியமாக இருக்க முடியாது, Row #{0}: Serial No {1} does not belong to Batch {2},வரிசை # {0}: வரிசை எண் {1 B தொகுதி {2 to க்கு சொந்தமானது அல்ல, Row #{0}: Service End Date cannot be before Invoice Posting Date,வரிசை # {0}: விலைப்பட்டியல் இடுகையிடும் தேதிக்கு முன் சேவை முடிவு தேதி இருக்கக்கூடாது, Row #{0}: Service Start Date cannot be greater than Service End Date,வரிசை # {0}: சேவை தொடக்க தேதி சேவை முடிவு தேதியை விட அதிகமாக இருக்கக்கூடாது, diff --git a/erpnext/translations/te.csv b/erpnext/translations/te.csv index 22fd7d7d1d..278a222999 100644 --- a/erpnext/translations/te.csv +++ b/erpnext/translations/te.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,వరుస {0}: దయచేసి అమ్మకపు పన్నులు మరియు ఛార్జీలలో పన్ను మినహాయింపు కారణాన్ని సెట్ చేయండి, Row {0}: Please set the Mode of Payment in Payment Schedule,వరుస {0}: దయచేసి చెల్లింపు షెడ్యూల్‌లో చెల్లింపు మోడ్‌ను సెట్ చేయండి, Row {0}: Please set the correct code on Mode of Payment {1},అడ్డు వరుస {0}: దయచేసి సరైన కోడ్‌ను చెల్లింపు మోడ్ {1 on లో సెట్ చేయండి, -Row {0}: Qty is mandatory,రో {0}: Qty తప్పనిసరి, Row {0}: Quality Inspection rejected for item {1},అడ్డు వరుస {0}: అంశం {1 item కోసం నాణ్యత తనిఖీ తిరస్కరించబడింది, Row {0}: UOM Conversion Factor is mandatory,రో {0}: UoM మార్పిడి ఫాక్టర్ తప్పనిసరి, Row {0}: select the workstation against the operation {1},అడ్డు వరుస {0}: ఆపరేషన్‌కు వ్యతిరేకంగా వర్క్‌స్టేషన్‌ను ఎంచుకోండి {1}, @@ -3461,7 +3460,6 @@ Issue Type.,ఇష్యూ రకం., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","ఇది సర్వర్ యొక్క చారల కాన్ఫిగరేషన్తో సమస్య ఉన్నట్లు తెలుస్తోంది. వైఫల్యం విషయంలో, మీ ఖాతాకు మొత్తం తిరిగి చెల్లించబడుతుంది.", Item Reported,అంశం నివేదించబడింది, Item listing removed,అంశం జాబితా తీసివేయబడింది, -Item quantity can not be zero,అంశం పరిమాణం సున్నా కాదు, Item taxes updated,అంశం పన్నులు నవీకరించబడ్డాయి, Item {0}: {1} qty produced. ,అంశం {0}: {1} qty ఉత్పత్తి., Joining Date can not be greater than Leaving Date,చేరిన తేదీ లీవింగ్ డేట్ కంటే ఎక్కువ కాదు, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},అడ్డు వరుస # {0}: వ్యయ కేంద్రం {1 company కంపెనీ {2} కు చెందినది కాదు, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,అడ్డు వరుస # {0}: వర్క్ ఆర్డర్ {3 in లో పూర్తయిన వస్తువుల {2} qty కోసం ఆపరేషన్ {1 complete పూర్తి కాలేదు. దయచేసి జాబ్ కార్డ్ {4 via ద్వారా ఆపరేషన్ స్థితిని నవీకరించండి., Row #{0}: Payment document is required to complete the transaction,అడ్డు వరుస # {0}: లావాదేవీని పూర్తి చేయడానికి చెల్లింపు పత్రం అవసరం, +Row #{0}: Quantity for Item {1} cannot be zero.,అడ్డు వరుస # {0}: అంశం {1} యొక్క పరిమాణం సున్నా కాదు, Row #{0}: Serial No {1} does not belong to Batch {2},అడ్డు వరుస # {0}: సీరియల్ సంఖ్య {1 B బ్యాచ్ {2 to కి చెందినది కాదు, Row #{0}: Service End Date cannot be before Invoice Posting Date,అడ్డు వరుస # {0}: ఇన్వాయిస్ పోస్టింగ్ తేదీకి ముందు సేవ ముగింపు తేదీ ఉండకూడదు, Row #{0}: Service Start Date cannot be greater than Service End Date,అడ్డు వరుస # {0}: సేవా ప్రారంభ తేదీ సేవ ముగింపు తేదీ కంటే ఎక్కువగా ఉండకూడదు, diff --git a/erpnext/translations/th.csv b/erpnext/translations/th.csv index 5dfb93c585..997af56999 100644 --- a/erpnext/translations/th.csv +++ b/erpnext/translations/th.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,แถว {0}: โปรดตั้งค่าที่เหตุผลการยกเว้นภาษีในภาษีขายและค่าธรรมเนียม, Row {0}: Please set the Mode of Payment in Payment Schedule,แถว {0}: โปรดตั้งค่าโหมดการชำระเงินในกำหนดการชำระเงิน, Row {0}: Please set the correct code on Mode of Payment {1},แถว {0}: โปรดตั้งรหัสที่ถูกต้องในโหมดการชำระเงิน {1}, -Row {0}: Qty is mandatory,แถว {0}: จำนวนมีผลบังคับใช้, Row {0}: Quality Inspection rejected for item {1},แถว {0}: การตรวจสอบคุณภาพถูกปฏิเสธสำหรับรายการ {1}, Row {0}: UOM Conversion Factor is mandatory,แถว {0}: UOM ปัจจัยการแปลงมีผลบังคับใช้, Row {0}: select the workstation against the operation {1},แถว {0}: เลือกเวิร์กสเตชั่นจากการดำเนินงาน {1}, @@ -3461,7 +3460,6 @@ Issue Type.,ประเภทของปัญหา, "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.",ดูเหมือนว่ามีปัญหากับการกำหนดค่าแถบของเซิร์ฟเวอร์ ในกรณีที่เกิดความล้มเหลวจำนวนเงินจะได้รับคืนไปยังบัญชีของคุณ, Item Reported,รายการที่รายงาน, Item listing removed,ลบรายการออกแล้ว, -Item quantity can not be zero,ปริมาณสินค้าไม่สามารถเป็นศูนย์ได้, Item taxes updated,อัปเดตภาษีสินค้าแล้ว, Item {0}: {1} qty produced. ,รายการ {0}: {1} จำนวนที่ผลิต, Joining Date can not be greater than Leaving Date,วันที่เข้าร่วมต้องไม่เกินวันที่ออก, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},แถว # {0}: ศูนย์ต้นทุน {1} ไม่ได้เป็นของ บริษัท {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,แถว # {0}: การดำเนินการ {1} ไม่เสร็จสมบูรณ์สำหรับ {2} จำนวนสินค้าสำเร็จรูปในใบสั่งงาน {3} โปรดอัพเดทสถานะการทำงานผ่าน Job Card {4}, Row #{0}: Payment document is required to complete the transaction,แถว # {0}: ต้องใช้เอกสารการชำระเงินเพื่อทำธุรกรรมให้สมบูรณ์, +Row #{0}: Quantity for Item {1} cannot be zero.,แถว # {0}: ปริมาณสินค้า {1} ไม่สามารถเป็นศูนย์ได้, Row #{0}: Serial No {1} does not belong to Batch {2},แถว # {0}: หมายเลขลำดับ {1} ไม่ได้อยู่ในแบทช์ {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Row # {0}: วันที่สิ้นสุดการบริการไม่สามารถอยู่ก่อนวันที่ผ่านรายการใบแจ้งหนี้, Row #{0}: Service Start Date cannot be greater than Service End Date,แถว # {0}: วันที่เริ่มบริการไม่สามารถมากกว่าวันที่สิ้นสุดการให้บริการ, diff --git a/erpnext/translations/tr.csv b/erpnext/translations/tr.csv index 82d28240c1..3a6f48ddc9 100644 --- a/erpnext/translations/tr.csv +++ b/erpnext/translations/tr.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,{0} Satırı: Lütfen Satış Vergileri ve Masraflarında Vergi Muafiyeti Nedeni ayarını yapın, Row {0}: Please set the Mode of Payment in Payment Schedule,{0} Satırı: Lütfen Ödeme Planında Ödeme Modu ayarı, Row {0}: Please set the correct code on Mode of Payment {1},{0} Satırı: Lütfen {1} Ödeme Modunda doğru kodu ayarı, -Row {0}: Qty is mandatory,Satır {0}: Miktar cezaları, Row {0}: Quality Inspection rejected for item {1},{0} Satırı: {1} kalem için Kalite Denetimi reddedildi, Row {0}: UOM Conversion Factor is mandatory,Satır {0}: Ölçü Birimi Dönüşüm Faktörü Hizmetleri, Row {0}: select the workstation against the operation {1},{0} bilgisi: {1} işlemine karşı iş istasyonunu seçin, @@ -3460,7 +3459,6 @@ Issue Type.,Sorun Tipi., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Sunucunun şerit çevresinde bir sorun var gibi görünüyor. Arıza durumunda, tutarları iade edilir.", Item Reported,Öğe Bildirildi, Item listing removed,öğe listesi kaldırıldı, -Item quantity can not be zero,Ürün miktarı sıfır olamaz, Item taxes updated,Öğe vergileri güncellendi, Item {0}: {1} qty produced. ,Öğe {0}: {1} adet oluşturma., Joining Date can not be greater than Leaving Date,Katılım Tarihi Ayrılık Tarihinden daha büyük olamaz, @@ -3632,6 +3630,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},"Satır # {0}: Maliyet Merkezi {1}, {2} işletme ait değil", Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Satır # {0}: {3} İş Emri'nde {2} işlenmiş ürün adedi için {1} işlemi tamamlanmadı. Lütfen çalışma halindeyken {4} Job Card ile güncelleyin., Row #{0}: Payment document is required to complete the transaction,Satır # {0}: İşlemi gizlemek için ödeme belgesi gereklidir, +Row #{0}: Quantity for Item {1} cannot be zero.,Satır # {0}: Ürün {1} miktarı sıfır olamaz., Row #{0}: Serial No {1} does not belong to Batch {2},"Satır # {0}: Seri No {1}, Parti {2} 'ye ait değil", Row #{0}: Service End Date cannot be before Invoice Posting Date,"Satır # {0}: Hizmet Bitiş Tarihi, Fatura Kayıt Tarihinden önce olamaz", Row #{0}: Service Start Date cannot be greater than Service End Date,"Satır # {0}: Hizmet Başlangıç Tarihi, Hizmet Bitiş Tarihinden fazla olamaz", diff --git a/erpnext/translations/uk.csv b/erpnext/translations/uk.csv index f77c6da35e..4fc5d9b828 100644 --- a/erpnext/translations/uk.csv +++ b/erpnext/translations/uk.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,"Рядок {0}: Будь ласка, встановіть Причини звільнення від оподаткування податками та зборами з продажу", Row {0}: Please set the Mode of Payment in Payment Schedule,"Рядок {0}: Будь ласка, встановіть Спосіб оплати у Платіжному графіку", Row {0}: Please set the correct code on Mode of Payment {1},Рядок {0}: Введіть правильний код у спосіб оплати {1}, -Row {0}: Qty is mandatory,Ряд {0}: Кількість обов'язково, Row {0}: Quality Inspection rejected for item {1},Рядок {0}: перевірку якості відхилено для елемента {1}, Row {0}: UOM Conversion Factor is mandatory,Ряд {0}: Коефіцієнт перетворення Одиниця виміру є обов'язковим, Row {0}: select the workstation against the operation {1},Рядок {0}: виберіть робочу станцію проти операції {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Тип випуску, "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Здається, існує проблема з конфігурацією смуги сервера. У випадку невдачі сума повернеться на ваш рахунок.", Item Reported,Елемент повідомлено, Item listing removed,Список елементів видалено, -Item quantity can not be zero,Кількість предмета не може дорівнювати нулю, Item taxes updated,Податки на предмет оновлено, Item {0}: {1} qty produced. ,Пункт {0}: {1} кількість створено., Joining Date can not be greater than Leaving Date,Дата приєднання не може перевищувати дату відпуску, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Рядок № {0}: Центр витрат {1} не належить компанії {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Рядок № {0}: Операція {1} не завершена для {2} кількості готової продукції в робочому порядку {3}. Оновіть стан роботи за допомогою Job Card {4}., Row #{0}: Payment document is required to complete the transaction,Рядок № {0}: для здійснення транзакції потрібно платіжний документ, +Row #{0}: Quantity for Item {1} cannot be zero.,Рядок № {0}: Кількість предмета {1} не може дорівнювати нулю., Row #{0}: Serial No {1} does not belong to Batch {2},Рядок № {0}: Серійний номер {1} не належить до партії {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Рядок № {0}: Дата закінчення послуги не може бути до дати опублікування рахунка-фактури, Row #{0}: Service Start Date cannot be greater than Service End Date,"Рядок № {0}: дата початку служби не може бути більшою, ніж дата закінчення служби", diff --git a/erpnext/translations/ur.csv b/erpnext/translations/ur.csv index 4dc872be5d..0d7841bd5b 100644 --- a/erpnext/translations/ur.csv +++ b/erpnext/translations/ur.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,قطار {0}: برائے کرم سیل ٹیکس اور محصولات میں ٹیکس چھوٹ کی وجہ مقرر کریں۔, Row {0}: Please set the Mode of Payment in Payment Schedule,قطار {0}: براہ کرم ادائیگی کے نظام الاوقات میں ادائیگی کا انداز وضع کریں۔, Row {0}: Please set the correct code on Mode of Payment {1},صف {0}: براہ کرم درست کوڈ کو ادائیگی کے موڈ پر مقرر کریں {1}, -Row {0}: Qty is mandatory,صف {0}: مقدار لازمی ہے, Row {0}: Quality Inspection rejected for item {1},قطار {0}: معیار معائنہ شے کے لئے مسترد کر دیا {1}, Row {0}: UOM Conversion Factor is mandatory,صف {0}: UOM تبادلوں فیکٹر لازمی ہے, Row {0}: select the workstation against the operation {1},قطار {0}: آپریشن کے خلاف ورکشاپ کا انتخاب کریں {1}, @@ -3461,7 +3460,6 @@ Issue Type.,مسئلہ کی قسم, "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.",ایسا لگتا ہے کہ سرور کی پٹی ترتیب کے ساتھ ایک مسئلہ ہے. ناکامی کی صورت میں، رقم آپ کے اکاؤنٹ میں واپس کی جائے گی., Item Reported,آئٹم کی اطلاع دی گئی۔, Item listing removed,آئٹم کی فہرست ختم کردی گئی, -Item quantity can not be zero,آئٹم کی مقدار صفر نہیں ہوسکتی ہے۔, Item taxes updated,آئٹم ٹیکس کی تازہ کاری, Item {0}: {1} qty produced. ,آئٹم {0}: {1} کیوٹی تیار کی گئی۔, Joining Date can not be greater than Leaving Date,تاریخ میں شامل ہونا تاریخ چھوڑنے سے زیادہ نہیں ہوسکتا ہے, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},قطار # {0}: لاگت سنٹر {1 company کا تعلق کمپنی {2 to سے نہیں ہے۔, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,قطار # {0}: ورک آرڈر {3 in میں تیار شدہ سامان کی {2} مقدار کے لئے آپریشن {1 not مکمل نہیں ہوا ہے۔ براہ کرم جاب کارڈ via 4 via کے ذریعے آپریشن کی حیثیت کو اپ ڈیٹ کریں۔, Row #{0}: Payment document is required to complete the transaction,قطار # {0}: ٹرانزیکشن کو مکمل کرنے کے لئے ادائیگی دستاویز کی ضرورت ہے۔, +Row #{0}: Quantity for Item {1} cannot be zero.,قطار # {0}: آئٹم {1} کی مقدار صفر نہیں ہوسکتی ہے۔, Row #{0}: Serial No {1} does not belong to Batch {2},قطار # {0}: سیریل نمبر {1 B بیچ {2 to سے تعلق نہیں رکھتی ہے۔, Row #{0}: Service End Date cannot be before Invoice Posting Date,قطار # {0}: خدمت کی اختتامی تاریخ انوائس پوسٹ کرنے کی تاریخ سے پہلے نہیں ہوسکتی ہے, Row #{0}: Service Start Date cannot be greater than Service End Date,قطار # {0}: سروس شروع ہونے کی تاریخ سروس اختتامی تاریخ سے زیادہ نہیں ہوسکتی ہے, diff --git a/erpnext/translations/uz.csv b/erpnext/translations/uz.csv index c09aa895e9..3f2654b9ad 100644 --- a/erpnext/translations/uz.csv +++ b/erpnext/translations/uz.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,"{0} qatori: Iltimos, soliqlarni to'lash va soliqlarni to'lashda soliqdan ozod qilish sababini belgilang", Row {0}: Please set the Mode of Payment in Payment Schedule,"{0} qatori: Iltimos, to'lov jadvalida to'lov usulini o'rnating", Row {0}: Please set the correct code on Mode of Payment {1},"{0} qator: Iltimos, to'lash rejimida to'g'ri kodni o'rnating {1}", -Row {0}: Qty is mandatory,Row {0}: Miqdor majburiydir, Row {0}: Quality Inspection rejected for item {1},{0} qator: {1} elementi uchun sifat nazorati rad qilindi, Row {0}: UOM Conversion Factor is mandatory,Row {0}: UOM Conversion Factor majburiydir, Row {0}: select the workstation against the operation {1},Row {0}: ish stantsiyasini {1} operatsiyasidan qarshi tanlang, @@ -3461,7 +3460,6 @@ Issue Type.,Muammo turi., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.",Serverning chiziqli konfiguratsiyasi bilan bog'liq muammo mavjud. Muvaffaqiyatsiz bo'lgan taqdirda sizning hisobingizga mablag 'qaytariladi., Item Reported,Xabar berilgan, Item listing removed,Elementlar ro‘yxati olib tashlandi, -Item quantity can not be zero,Mahsulot miqdori nolga teng bo'lolmaydi, Item taxes updated,Soliqlar yangilandi, Item {0}: {1} qty produced. ,{0}: {1} qty ishlab chiqarildi., Joining Date can not be greater than Leaving Date,Qo'shilish sanasi qoldirilgan kundan katta bo'lishi mumkin emas, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},# {0} qator: {1} Xarajatlar markazi {2} kompaniyasiga tegishli emas., Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,"# {0} qator: {3} ish tartibidagi {2} qt tayyor mahsulot uchun {1} operatsiyasi tugallanmagan. Iltimos, ish holatini {4} ish kartasi orqali yangilang.", Row #{0}: Payment document is required to complete the transaction,# {0} qator: tranzaktsiyani yakunlash uchun to'lov hujjati talab qilinadi, +Row #{0}: Quantity for Item {1} cannot be zero.,# {0} qator: Mahsulot {1} miqdori nolga teng bo'lolmaydi., Row #{0}: Serial No {1} does not belong to Batch {2},# {0} qator: {1} seriya {2} to'plamiga tegishli emas., Row #{0}: Service End Date cannot be before Invoice Posting Date,# {0} qator: xizmatni tugatish sanasi fakturani yuborish sanasidan oldin bo'lishi mumkin emas, Row #{0}: Service Start Date cannot be greater than Service End Date,# {0} qator: xizmatni boshlash sanasi xizmatning tugash sanasidan oshib ketmasligi kerak, diff --git a/erpnext/translations/vi.csv b/erpnext/translations/vi.csv index eb251a5978..dfd2083dcf 100644 --- a/erpnext/translations/vi.csv +++ b/erpnext/translations/vi.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,Hàng {0}: Vui lòng đặt tại Lý do miễn thuế trong Thuế và phí bán hàng, Row {0}: Please set the Mode of Payment in Payment Schedule,Hàng {0}: Vui lòng đặt Chế độ thanh toán trong Lịch thanh toán, Row {0}: Please set the correct code on Mode of Payment {1},Hàng {0}: Vui lòng đặt mã chính xác cho Phương thức thanh toán {1}, -Row {0}: Qty is mandatory,Hàng {0}: Số lượng là bắt buộc, Row {0}: Quality Inspection rejected for item {1},Hàng {0}: Kiểm tra chất lượng bị từ chối cho mục {1}, Row {0}: UOM Conversion Factor is mandatory,Hàng {0}: Nhân tố thay đổi UOM là bắt buộc, Row {0}: select the workstation against the operation {1},Hàng {0}: chọn máy trạm chống lại hoạt động {1}, @@ -3461,7 +3460,6 @@ Issue Type.,Các loại vấn đề., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Dường như có sự cố với cấu hình sọc của máy chủ. Trong trường hợp thất bại, số tiền sẽ được hoàn trả vào tài khoản của bạn.", Item Reported,Mục báo cáo, Item listing removed,Danh sách mục bị xóa, -Item quantity can not be zero,Số lượng mặt hàng không thể bằng không, Item taxes updated,Mục thuế được cập nhật, Item {0}: {1} qty produced. ,Mục {0}: {1} qty được sản xuất., Joining Date can not be greater than Leaving Date,Ngày tham gia không thể lớn hơn Ngày rời, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},Hàng # {0}: Trung tâm chi phí {1} không thuộc về công ty {2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,Hàng # {0}: Thao tác {1} chưa được hoàn thành cho {2} qty hàng thành phẩm trong Đơn hàng công việc {3}. Vui lòng cập nhật trạng thái hoạt động thông qua Thẻ công việc {4}., Row #{0}: Payment document is required to complete the transaction,Hàng # {0}: Cần có chứng từ thanh toán để hoàn thành giao dịch, +Row #{0}: Quantity for Item {1} cannot be zero.,Hàng # {0}: Số lượng mặt hàng {1} không thể bằng không., Row #{0}: Serial No {1} does not belong to Batch {2},Hàng # {0}: Số thứ tự {1} không thuộc về Batch {2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,Hàng # {0}: Ngày kết thúc dịch vụ không thể trước Ngày đăng hóa đơn, Row #{0}: Service Start Date cannot be greater than Service End Date,Hàng # {0}: Ngày bắt đầu dịch vụ không thể lớn hơn Ngày kết thúc dịch vụ, diff --git a/erpnext/translations/zh-TW.csv b/erpnext/translations/zh-TW.csv index 0f76e97f97..bbdbe80d78 100644 --- a/erpnext/translations/zh-TW.csv +++ b/erpnext/translations/zh-TW.csv @@ -1650,7 +1650,6 @@ Laboratory Testing Datetime,實驗室測試日期時間 Add Quote,添加報價 UOM coversion factor required for UOM: {0} in Item: {1},所需的計量單位計量單位:丁文因素:{0}項:{1} Indirect Expenses,間接費用 -Row {0}: Qty is mandatory,列#{0}:數量是強制性的 Agriculture,農業 Create Sales Order,創建銷售訂單 Accounting Entry for Asset,資產會計分錄 diff --git a/erpnext/translations/zh.csv b/erpnext/translations/zh.csv index 08f8d33578..604fcc0edc 100644 --- a/erpnext/translations/zh.csv +++ b/erpnext/translations/zh.csv @@ -2273,7 +2273,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,行{0}:请设置销售税和费用中的免税原因, Row {0}: Please set the Mode of Payment in Payment Schedule,行{0}:请在付款时间表中设置付款方式, Row {0}: Please set the correct code on Mode of Payment {1},行{0}:请在付款方式{1}上设置正确的代码, -Row {0}: Qty is mandatory,第{0}行的数量字段必填, Row {0}: Quality Inspection rejected for item {1},行{0}:项目{1}的质量检验被拒绝, Row {0}: UOM Conversion Factor is mandatory,行{0}:计量单位转换系数是必需的, Row {0}: select the workstation against the operation {1},行{0}:根据操作{1}选择工作站, @@ -3461,7 +3460,6 @@ Issue Type.,问题类型。, "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.",看起来服务器的条带配置存在问题。如果失败,这笔款项将退还给您的账户。, Item Reported,项目报告, Item listing removed,项目清单已删除, -Item quantity can not be zero,物品数量不能为零, Item taxes updated,物品税已更新, Item {0}: {1} qty produced. ,项目{0}:产生了{1}数量。, Joining Date can not be greater than Leaving Date,加入日期不能大于离开日期, @@ -3633,6 +3631,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},第{0}行:成本中心{1}不属于公司{2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,行#{0}:对于工作订单{3}中的{2}数量的成品,未完成操作{1}。请通过工作卡{4}更新操作状态。, Row #{0}: Payment document is required to complete the transaction,行#{0}:完成交易需要付款文件, +Row #{0}: Quantity for Item {1} cannot be zero.,行 # {0}: 商品 {1} 的数量不能为零。 Row #{0}: Serial No {1} does not belong to Batch {2},行#{0}:序列号{1}不属于批次{2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,行#{0}:服务终止日期不能早于发票过帐日期, Row #{0}: Service Start Date cannot be greater than Service End Date,行#{0}:服务开始日期不能大于服务结束日期, diff --git a/erpnext/translations/zh_tw.csv b/erpnext/translations/zh_tw.csv index dd683c5a27..634662f770 100644 --- a/erpnext/translations/zh_tw.csv +++ b/erpnext/translations/zh_tw.csv @@ -2324,7 +2324,6 @@ Row {0}: Please check 'Is Advance' against Account {1} if this is an advance ent Row {0}: Please set at Tax Exemption Reason in Sales Taxes and Charges,行{0}:請設置銷售稅和費用中的免稅原因, Row {0}: Please set the Mode of Payment in Payment Schedule,行{0}:請在付款時間表中設置付款方式, Row {0}: Please set the correct code on Mode of Payment {1},行{0}:請在付款方式{1}上設置正確的代碼, -Row {0}: Qty is mandatory,列#{0}:數量是強制性的, Row {0}: Quality Inspection rejected for item {1},行{0}:項目{1}的質量檢驗被拒絕, Row {0}: UOM Conversion Factor is mandatory,行{0}:計量單位轉換係數是必需的, Row {0}: select the workstation against the operation {1},行{0}:根據操作{1}選擇工作站, @@ -3556,7 +3555,6 @@ Issue Type.,問題類型。, "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.",看起來服務器的條帶配置存在問題。如果失敗,這筆款項將退還給您的賬戶。, Item Reported,項目報告, Item listing removed,項目清單已刪除, -Item quantity can not be zero,物品數量不能為零, Item taxes updated,物品稅已更新, Item {0}: {1} qty produced. ,項目{0}:產生了{1}數量。, Joining Date can not be greater than Leaving Date,加入日期不能大於離開日期, @@ -3752,6 +3750,7 @@ Row #{0}: Cannot select Supplier Warehouse while suppling raw materials to subco Row #{0}: Cost Center {1} does not belong to company {2},第{0}行:成本中心{1}不屬於公司{2}, Row #{0}: Operation {1} is not completed for {2} qty of finished goods in Work Order {3}. Please update operation status via Job Card {4}.,行#{0}:對於工作訂單{3}中的{2}數量的成品,未完成操作{1}。請通過工作卡{4}更新操作狀態。, Row #{0}: Payment document is required to complete the transaction,第{0}行:需要付款憑證才能完成交易, +Row #{0}: Quantity for Item {1} cannot be zero.,行 # {0}: 商品 {1} 的數量不能為零。 Row #{0}: Serial No {1} does not belong to Batch {2},行#{0}:序列號{1}不屬於批次{2}, Row #{0}: Service End Date cannot be before Invoice Posting Date,行#{0}:服務終止日期不能早於發票過帳日期, Row #{0}: Service Start Date cannot be greater than Service End Date,行#{0}:服務開始日期不能大於服務結束日期, From 9471d8fff94f84a627957c5ff2c7f8f1ed53a098 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Mon, 4 Dec 2023 17:56:32 +0530 Subject: [PATCH 065/205] feat: provision to update items in Stock Reservation dialog --- .../doctype/sales_order/sales_order.js | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index 97b214e33e..be02877a1b 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -182,7 +182,7 @@ frappe.ui.form.on("Sales Order", { create_stock_reservation_entries(frm) { const dialog = new frappe.ui.Dialog({ title: __("Stock Reservation"), - size: "large", + size: "extra-large", fields: [ { fieldname: "set_warehouse", @@ -218,10 +218,33 @@ frappe.ui.form.on("Sales Order", { fields: [ { fieldname: "sales_order_item", - fieldtype: "Data", + fieldtype: "Link", label: __("Sales Order Item"), + options: "Sales Order Item", reqd: 1, - read_only: 1, + in_list_view: 1, + get_query: () => { + return { + filters: { + "parenttype": frm.doc.doctype, + "parent": frm.doc.name, + "reserve_stock": 1, + } + } + }, + onchange: (event) => { + if (event) { + let name = $(event.currentTarget).closest(".grid-row").attr("data-name"); + let item_row = dialog.fields_dict.items.grid.grid_rows_by_docname[name].doc; + + frm.doc.items.forEach(item => { + if (item.name === item_row.sales_order_item) { + item_row.item_code = item.item_code; + } + }); + dialog.fields_dict.items.grid.refresh(); + } + } }, { fieldname: "item_code", From 00261094c8ce0663f953b73ae17a5e7f3f494b59 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Mon, 4 Dec 2023 18:00:06 +0530 Subject: [PATCH 066/205] fix(ux): show row index and field label while selecting the Sales Order Item --- erpnext/controllers/queries.py | 28 +++++++++++++++++++ .../doctype/sales_order/sales_order.js | 1 + 2 files changed, 29 insertions(+) diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index 199732b152..e858820965 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -891,3 +891,31 @@ def get_payment_terms_for_references(doctype, txt, searchfield, start, page_len, as_list=1, ) return terms + + +@frappe.whitelist() +@frappe.validate_and_sanitize_search_inputs +def get_filtered_child_rows(doctype, txt, searchfield, start, page_len, filters) -> list: + table = frappe.qb.DocType(doctype) + query = ( + frappe.qb.from_(table) + .select( + table.name, + Concat("#", table.idx, ", ", table.item_code), + ) + .orderby(table.idx) + .offset(start) + .limit(page_len) + ) + + if filters: + for field, value in filters.items(): + query = query.where(table[field] == value) + + if txt: + txt += "%" + query = query.where( + ((table.idx.like(txt.replace("#", ""))) | (table.item_code.like(txt))) | (table.name.like(txt)) + ) + + return query.run(as_dict=False) diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index be02877a1b..0d36f23695 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -225,6 +225,7 @@ frappe.ui.form.on("Sales Order", { in_list_view: 1, get_query: () => { return { + query: "erpnext.controllers.queries.get_filtered_child_rows", filters: { "parenttype": frm.doc.doctype, "parent": frm.doc.name, From 8d5045ef4caf695dbfdc087b78c8f68a79976813 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Mon, 4 Dec 2023 18:03:22 +0530 Subject: [PATCH 067/205] feat: provision to add items in Stock Reservation dialog --- .../doctype/sales_order/sales_order.js | 48 ++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index 0d36f23695..b206e3fe33 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -207,6 +207,50 @@ frappe.ui.form.on("Sales Order", { }, }, {fieldtype: "Column Break"}, + { + fieldname: "add_item", + fieldtype: "Link", + label: __("Add Item"), + options: "Sales Order Item", + get_query: () => { + return { + query: "erpnext.controllers.queries.get_filtered_child_rows", + filters: { + "parenttype": frm.doc.doctype, + "parent": frm.doc.name, + "reserve_stock": 1, + } + } + }, + onchange: () => { + let sales_order_item = dialog.get_value("add_item"); + + if (sales_order_item) { + frm.doc.items.forEach(item => { + if (item.name === sales_order_item) { + let unreserved_qty = (flt(item.stock_qty) - (item.stock_reserved_qty ? flt(item.stock_reserved_qty) : (flt(item.delivered_qty) * flt(item.conversion_factor)))) / flt(item.conversion_factor); + + if (unreserved_qty > 0) { + dialog.fields_dict.items.df.data.forEach((row) => { + if (row.sales_order_item === sales_order_item) { + unreserved_qty -= row.qty_to_reserve; + } + }); + } + + dialog.fields_dict.items.df.data.push({ + 'sales_order_item': item.name, + 'item_code': item.item_code, + 'warehouse': dialog.get_value("set_warehouse") || item.warehouse, + 'qty_to_reserve': Math.max(unreserved_qty, 0) + }); + dialog.fields_dict.items.grid.refresh(); + dialog.set_value("add_item", undefined); + } + }); + } + }, + }, {fieldtype: "Section Break"}, { fieldname: "items", @@ -308,14 +352,14 @@ frappe.ui.form.on("Sales Order", { frm.doc.items.forEach(item => { if (item.reserve_stock) { - let unreserved_qty = (flt(item.stock_qty) - (item.stock_reserved_qty ? flt(item.stock_reserved_qty) : (flt(item.delivered_qty) * flt(item.conversion_factor)))) + let unreserved_qty = (flt(item.stock_qty) - (item.stock_reserved_qty ? flt(item.stock_reserved_qty) : (flt(item.delivered_qty) * flt(item.conversion_factor)))) / flt(item.conversion_factor); if (unreserved_qty > 0) { dialog.fields_dict.items.df.data.push({ 'sales_order_item': item.name, 'item_code': item.item_code, 'warehouse': item.warehouse, - 'qty_to_reserve': (unreserved_qty / flt(item.conversion_factor)) + 'qty_to_reserve': unreserved_qty }); } } From a56b79cc72241f6a4540cb93b1b0f39926137cdc Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Tue, 5 Dec 2023 12:46:22 +0530 Subject: [PATCH 068/205] fix: check for split entries in stock entry test --- erpnext/stock/doctype/stock_entry/test_stock_entry.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index b640983a09..186ea27335 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -504,7 +504,14 @@ class TestStockEntry(FrappeTestCase): self.check_gl_entries( "Stock Entry", repack.name, - sorted([[stock_in_hand_account, 1200, 0.0], ["Cost of Goods Sold - TCP1", 0.0, 1200.0]]), + sorted( + [ + ["Cost of Goods Sold - TCP1", 0.0, 1200.0], + ["Stock Adjustment - TCP1", 0.0, 1200.0], + ["Stock Adjustment - TCP1", 1200.0, 0.0], + [stock_in_hand_account, 1200.0, 0.0], + ] + ), ) def check_stock_ledger_entries(self, voucher_type, voucher_no, expected_sle): From 24ccb3eb78f2bf88efed26e268039c38e6baf536 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Tue, 5 Dec 2023 12:47:06 +0530 Subject: [PATCH 069/205] fix: subcontracting receipt gle test --- .../test_subcontracting_receipt.py | 27 +++++++------------ 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py index f0e4e00074..22a679a1ed 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py @@ -365,24 +365,17 @@ class TestSubcontractingReceipt(FrappeTestCase): fg_warehouse_ac = get_inventory_account(scr.company, scr.items[0].warehouse) supplier_warehouse_ac = get_inventory_account(scr.company, scr.supplier_warehouse) expense_account = scr.items[0].expense_account + expected_values = [ + [fg_warehouse_ac, 2100.0, 0.0], # FG Amount (D) + [supplier_warehouse_ac, 0.0, 1000.0], # RM Cost (C) + [additional_costs_expense_account, 0.0, 100.0], # Additional Cost (C) + [expense_account, 0.0, 1000.0], # Service Cost (C) + ] - if fg_warehouse_ac == supplier_warehouse_ac: - expected_values = { - fg_warehouse_ac: [2100.0, 1000.0], # FG Amount (D), RM Cost (C) - expense_account: [0.0, 1000.0], # Service Cost (C) - additional_costs_expense_account: [0.0, 100.0], # Additional Cost (C) - } - else: - expected_values = { - fg_warehouse_ac: [2100.0, 0.0], # FG Amount (D) - supplier_warehouse_ac: [0.0, 1000.0], # RM Cost (C) - expense_account: [0.0, 1000.0], # Service Cost (C) - additional_costs_expense_account: [0.0, 100.0], # Additional Cost (C) - } - - for gle in gl_entries: - self.assertEqual(expected_values[gle.account][0], gle.debit) - self.assertEqual(expected_values[gle.account][1], gle.credit) + for i in range(len(expected_values)): + self.assertEqual(expected_values[i][0], gl_entries[i]["account"]) + self.assertEqual(expected_values[i][1], gl_entries[i]["debit"]) + self.assertEqual(expected_values[i][2], gl_entries[i]["credit"]) scr.reload() scr.cancel() From 47c78a5a7324cdea5fde7f4e269c933572ccaf56 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Tue, 5 Dec 2023 12:48:25 +0530 Subject: [PATCH 070/205] fix: check for unmerged gle in purchase receipt test --- erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index 146cbff1aa..e418aadfaa 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -990,7 +990,7 @@ class TestPurchaseReceipt(FrappeTestCase): gl_entries = get_gl_entries("Purchase Receipt", pr.name) sl_entries = get_sl_entries("Purchase Receipt", pr.name) - self.assertFalse(gl_entries) + self.assertEqual(len(gl_entries), 2) expected_sle = {"Work In Progress - TCP1": -5, "Stores - TCP1": 5} From 005c5a587ff7322a6f3fb1099aa0c94e6873c7fe Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Tue, 5 Dec 2023 13:16:54 +0530 Subject: [PATCH 071/205] chore: orderby in gle --- .../purchase_receipt/test_purchase_receipt.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index e418aadfaa..d2740694b3 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -4,6 +4,7 @@ import frappe from frappe.tests.utils import FrappeTestCase, change_settings from frappe.utils import add_days, cint, cstr, flt, nowtime, today +from pypika import Order from pypika import functions as fn import erpnext @@ -2235,13 +2236,13 @@ def get_sl_entries(voucher_type, voucher_no): def get_gl_entries(voucher_type, voucher_no): - return frappe.db.sql( - """select account, debit, credit, cost_center, is_cancelled - from `tabGL Entry` where voucher_type=%s and voucher_no=%s - order by account desc""", - (voucher_type, voucher_no), - as_dict=1, - ) + gle = frappe.qb.DocType("GL Entry") + return ( + frappe.qb.from_(gle) + .select(gle.account, gle.debit, gle.credit, gle.cost_center, gle.is_cancelled) + .where((gle.voucher_type == voucher_type) & (gle.voucher_no == voucher_no)) + .orderby(gle.account, gle.debit, order=Order.desc) + ).run(as_dict=True) def get_taxes(**args): From fa1c7b663c2e3f433190d29017eaebbe15d4c604 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Fri, 15 Dec 2023 22:00:01 +0530 Subject: [PATCH 072/205] fix: Reset SLA on issue doesn't work (#38789) This was broken since last refactor where it was spun off to work with all types of doctypes but client side code was never adapted. --- erpnext/support/doctype/issue/issue.js | 4 +++- .../service_level_agreement/service_level_agreement.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js index f96823b290..9f91dc1726 100644 --- a/erpnext/support/doctype/issue/issue.js +++ b/erpnext/support/doctype/issue/issue.js @@ -58,7 +58,9 @@ frappe.ui.form.on("Issue", { frappe.call("erpnext.support.doctype.service_level_agreement.service_level_agreement.reset_service_level_agreement", { reason: values.reason, - user: frappe.session.user_email + user: frappe.session.user_email, + doctype: frm.doc.doctype, + docname: frm.doc.name, }, () => { reset_sla.enable_primary_action(); frm.refresh(); diff --git a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py index 8b37c9478c..f6b3a1311b 100644 --- a/erpnext/support/doctype/service_level_agreement/service_level_agreement.py +++ b/erpnext/support/doctype/service_level_agreement/service_level_agreement.py @@ -774,10 +774,12 @@ def get_response_and_resolution_duration(doc): return priority -def reset_service_level_agreement(doc, reason, user): +@frappe.whitelist() +def reset_service_level_agreement(doctype: str, docname: str, reason, user): if not frappe.db.get_single_value("Support Settings", "allow_resetting_service_level_agreement"): frappe.throw(_("Allow Resetting Service Level Agreement from Support Settings.")) + doc = frappe.get_doc(doctype, docname) frappe.get_doc( { "doctype": "Comment", From 5cb5e09dbbac878906023c07423d5d8233279790 Mon Sep 17 00:00:00 2001 From: Dany Robert Date: Sat, 16 Dec 2023 04:35:43 +0000 Subject: [PATCH 073/205] fix: wrong paid and cn amount on pos invoice --- .../report/accounts_receivable/accounts_receivable.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index 7948e5f465..6826c5c982 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -244,8 +244,12 @@ class ReceivablePayableReport(object): row.invoiced_in_account_currency += amount_in_account_currency else: if self.is_invoice(ple): - row.credit_note -= amount - row.credit_note_in_account_currency -= amount_in_account_currency + if row.voucher_no == ple.voucher_no == ple.against_voucher_no: + row.paid -= amount + row.paid_in_account_currency -= amount_in_account_currency + else: + row.credit_note -= amount + row.credit_note_in_account_currency -= amount_in_account_currency else: row.paid -= amount row.paid_in_account_currency -= amount_in_account_currency From 259f313af75c3cbdcc1af75a8e7d2ad1a3a90c0c Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Sat, 16 Dec 2023 21:11:54 +0100 Subject: [PATCH 074/205] fix: groups for current accounts in German CoAs --- .../verified/de_kontenplan_SKR03_gnucash.json | 14 +++++++++++-- ..._kontenplan_SKR04_with_account_number.json | 20 +++++++------------ 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR03_gnucash.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR03_gnucash.json index 741d4283e2..daf2e21d78 100644 --- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR03_gnucash.json +++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR03_gnucash.json @@ -53,8 +53,13 @@ }, "II. Forderungen und sonstige Vermögensgegenstände": { "is_group": 1, - "Ford. a. Lieferungen und Leistungen": { + "Forderungen aus Lieferungen und Leistungen mit Kontokorrent": { "account_number": "1400", + "account_type": "Receivable", + "is_group": 1 + }, + "Forderungen aus Lieferungen und Leistungen ohne Kontokorrent": { + "account_number": "1410", "account_type": "Receivable" }, "Durchlaufende Posten": { @@ -180,8 +185,13 @@ }, "IV. Verbindlichkeiten aus Lieferungen und Leistungen": { "is_group": 1, - "Verbindlichkeiten aus Lieferungen u. Leistungen": { + "Verbindlichkeiten aus Lieferungen und Leistungen mit Kontokorrent": { "account_number": "1600", + "account_type": "Payable", + "is_group": 1 + }, + "Verbindlichkeiten aus Lieferungen und Leistungen ohne Kontokorrent": { + "account_number": "1610", "account_type": "Payable" } }, diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04_with_account_number.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04_with_account_number.json index 2bf55cfcd0..000ef80ee3 100644 --- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04_with_account_number.json +++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04_with_account_number.json @@ -407,13 +407,10 @@ "Bewertungskorrektur zu Forderungen aus Lieferungen und Leistungen": { "account_number": "9960" }, - "Debitoren": { - "is_group": 1, - "account_number": "10000" - }, - "Forderungen aus Lieferungen und Leistungen": { + "Forderungen aus Lieferungen und Leistungen mit Kontokorrent": { "account_number": "1200", - "account_type": "Receivable" + "account_type": "Receivable", + "is_group": 1 }, "Forderungen aus Lieferungen und Leistungen ohne Kontokorrent": { "account_number": "1210" @@ -1138,18 +1135,15 @@ "Bewertungskorrektur zu Verb. aus Lieferungen und Leistungen": { "account_number": "9964" }, - "Kreditoren": { - "account_number": "70000", + "Verb. aus Lieferungen und Leistungen mit Kontokorrent": { + "account_number": "3300", + "account_type": "Payable", "is_group": 1, - "Wareneingangs-­Verrechnungskonto" : { + "Wareneingangs-Verrechnungskonto" : { "account_number": "70001", "account_type": "Stock Received But Not Billed" } }, - "Verb. aus Lieferungen und Leistungen": { - "account_number": "3300", - "account_type": "Payable" - }, "Verb. aus Lieferungen und Leistungen ohne Kontokorrent": { "account_number": "3310" }, From baa1978128d9c829033296df90c1f03f67748ce0 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Sat, 16 Dec 2023 21:27:09 +0100 Subject: [PATCH 075/205] feat: remove german CoA "SKR04 ohne Kontonummern" To the best of my knwoledge, this is outdated, unused and not maintained. --- .../verified/de_kontenplan_SKR04.json | 1711 ----------------- 1 file changed, 1711 deletions(-) delete mode 100644 erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04.json diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04.json deleted file mode 100644 index 57e8bdd9dc..0000000000 --- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04.json +++ /dev/null @@ -1,1711 +0,0 @@ -{ - "country_code": "de", - "name": "SKR04 ohne Kontonummern", - "tree": { - "Bilanz - Aktiva": { - "Anlageverm\u00f6gen": { - "Anlageverm\u00f6gen Immaterielle Verm\u00f6gensgegenst\u00e4nde": { - "Geleistete Anzahlungen 1": { - "Anzahlungen auf Gesch\u00e4fts- oder Firmenwert": {}, - "Geleistete Anzahlungen auf immaterielle Verm\u00f6gensgegenst\u00e4nde": {} - }, - "Gesch\u00e4fts- oder Firmenwert": { - "Gesch\u00e4fts- oder Firmenwert 1": {} - }, - "Konzessionen- gewerbliche Schutzrechte und \u00e4hnliche Rechte und Werte sowie Lizenzen an solchen Rechten und Werten": { - "Konzessionen- gewerbliche Schutzrechte und \u00e4hnliche Rechte und Werte sowie Lizenzen an solchen Rechten und Werten 1": { - "EDV-Software": {}, - "Gewerbliche Schutzrechte": {}, - "Konzessionen ": {}, - "Lizenzen an gewerblichen Schutzrechten und \u00e4hnlichen Rechten und Werten ": {}, - "\u00e4hnliche Rechte und Werte ": {} - } - }, - "Verschmelzungsmehrwert": { - "Verschmelzungsmehrwert 1": {} - } - }, - "Aufwendungen f\u00fcr die Ingangsetzung und Erweiterung des Gesch\u00e4ftsbetriebs": { - "Aufwendungen f\u00fcr die Ingangsetzung und Erweiterung des Gesch\u00e4ftsbetriebs 1": { - "Aufwendungen f\u00fcr die Ingangsetzung und Erweiterung des Gesch\u00e4ftsbetriebs 2": {} - }, - "Aufwendungen f\u00fcr die W\u00e4hrungsumstellung auf den Euro": { - "Aufwendungen f\u00fcr die W\u00e4hrungsumstellung auf den Euro 1": {} - } - }, - "Ausstehende Einlagen auf das gezeichnete Kapital": { - "Ausstehende Einlagen auf das gezeichnete Kapital 1": { - "Ausstehende Einlagen auf das gezeichnete Kapital- eingefordert (Aktivausweis)": {}, - "Ausstehende Einlagen auf das gezeichnete Kapital- nichteingefordert (Aktivausweis)": {} - }, - "Sonstige Aktiva oder sonstige Passiva": { - "Ausstehende Einlagen auf das Kommandit-Kapital- eingefordert": {}, - "Ausstehende Einlagen auf das Kommandit-Kapital- nicht eingefordert": {}, - "Ausstehende Einlagen auf das Komplement\u00e4r-Kapital- eingefordert": {}, - "Ausstehende Einlagen auf das Komplement\u00e4r-Kapital- nicht eingefordert": {} - } - }, - "Finanzanlagen": { - "Anteile an verbundenen Unternehmen 1": { - "Anteile an herrschender oder mit Mehrheit beteiligter Gesellschaft 1": {}, - "Anteile an verbundenen Unternehmen 2": {} - }, - "Ausleihungen an Unternehmen- mit denen ein Beteiligungsverh\u00e4ltnis besteht": { - "Ausleihungen an Unternehmen- mit denen ein Beteiligungsverh\u00e4ltnis besteht 1": {} - }, - "Ausleihungen an verbundene Unternehmen": { - "Ausleihungen an verbundene Unternehmen 1": {} - }, - "Beteiligungen": { - "Beteiligungen 1": { - "Andere Beteilgungen an Personengesellschaften": {}, - "Andere Beteiligungen an Kapitalgesellschaften": {}, - "Atypisch stille Beteiligungen": {}, - "Beteiligungen einer GmbH Co. KG an einer Komplement\u00e4r GmbH": {}, - "Typisch stille Beteiligungen": {} - } - }, - "Genossenschaftsanteile": { - "Genossenschaftsanteile zum langfristigen Verbleib": {} - }, - "R\u00fcckdeckungsanspr\u00fcche aus Lebensversicherungen": { - "R\u00fcckdeckungsanspr\u00fcche aus Lebensversicherungen zum langfristigen Verbleib": {} - }, - "Sonstige Ausleihungen": { - "Sonstige Ausleihungen 1": { - "Ausleihungen an Gesellschafter": {}, - "Ausleihungen an nahe stehende Personen": {}, - "Darlehen 1": {} - } - }, - "Wertpapiere des Anlageverm\u00f6gens": { - "Wertpapiere des Anlageverm\u00f6gens 1": { - "Festverzinsliche Wertpapiere": {}, - "Wertpapiere mit Gewinnbeteiligungsanspr\u00fcchen- die dem Halbeink\u00fcnfteverfahren unterliegen": {} - } - } - }, - "Sachanlagen": { - "Andere Anlagen- Betriebs- und Gesch\u00e4ftsaustattung": { - "Andere Anlagen- Betriebs- und Gesch\u00e4ftsaustattung 1": { - "Andere Anlagen ": { - "account_type": "Fixed Asset" - }, - "B\u00fcroeinrichtungen": {}, - "Einbauten in fremde Grundst\u00fccke": {}, - "Geringwertige Wirtschaftsg\u00fcter bis 410 Euro": {}, - "Ger\u00fcst- und Schalungsmaterial": {}, - "Ladeneinrichtungen": {}, - "Lkw": {}, - "Pkw": {}, - "Sonstige Betriebs- und Gesch\u00e4ftsausstattung": {}, - "Sonstige Transportmittel": {}, - "Werkzeuge": {} - } - }, - "Geleistete Anzahlungen und Anlagen im Bau": { - "Geleistete Anzahlungen und Anlagen im Bau 1": { - "Andere Anlagen- Betriebs- und Gesch\u00e4ftsaustattung im Bau": {}, - "Anzahlungen auf Gesch\u00e4fts- Fabrik- und andere Bauten auf fremden Grundst\u00fccken": {}, - "Anzahlungen auf Gesch\u00e4fts- Fabrik-und andere Bauten auf eigenen Grundst\u00fccken und grundst\u00fccksgleichen Rechten ": {}, - "Anzahlungen auf Grundst\u00fccke und grundst\u00fccksgleiche Rechte ohne Bauten": {}, - "Anzahlungen auf Wohnbauten auf eigenen Grundst\u00fccken und grundst\u00fccksgleichen Rechten": {}, - "Anzahlungen auf Wohnbauten auf fremden Grundst\u00fccken ": {}, - "Anzahlungen auf andere Anlagen- Betriebs und Gesch\u00e4ftsausstattung": {}, - "Anzahlungen auf technische Anlagen und Maschinen": {}, - "Gesch\u00e4fts- Fabrik- und andere Bauten im Bau auf eingenen Grundst\u00fccken": {}, - "Gesch\u00e4fts- Fabrik- und andere Bauten im Bau auf fremden Grundst\u00fccken": {}, - "Technische Anlagen und Maschinen im Bau ": {}, - "Wohnbauten im Bau": {} - } - }, - "Grundst\u00fccke- grundst\u00fccksgleiche Rechte und Bauten einschlie\u00dflich der Bauten auf fremden Grundst\u00fccken": { - "Grundst\u00fccke- grundst\u00fccksgleiche Rechte und Bauten einschlie\u00dflich der Bauten auf fremden Grundst\u00fccken 1": { - "Andere Bauten": {}, - "Au\u00dfenanlagen ": {}, - "Au\u00dfenanlagen 1": {}, - "Au\u00dfenanlagen f\u00fcr Gesch\u00e4fts- Fabrik- und andere Bauten ": {}, - "Bauten auf eigenen Grundst\u00fccken und grundst\u00fccksgleichen Rechten": {}, - "Bauten auf fremden Grundst\u00fccken": {}, - "Einrichtungen f\u00fcr Gesch\u00e4fts-Fabrik und andere Bauten": {}, - "Einrichtungen f\u00fcr Wohnbauten": {}, - "Fabrikbauten": { - "account_type": "Fixed Asset" - }, - "Garagen": {}, - "Geb\u00e4udeteile des h\u00e4uslischen Arbeitszimmers": {}, - "Gesch\u00e4ftsbauten": {}, - "Grundst\u00fccke mit Substanzverzehr": {}, - "Grundst\u00fccke und grundst\u00fccksgleiche Rechte ohne Bauten": {}, - "Grundst\u00fccksanteil des h\u00e4uslichen Arbeitszimmers": {}, - "Grundst\u00fccksgleiche Rechte (Erbbaurecht- Dauerwohnrecht)": {}, - "Grundst\u00fcckswerte eigener bebauter Grundst\u00fccke": {}, - "Hof- und Wegebefestigungen": {}, - "Unbebaute Grundst\u00fccke": {}, - "Wohnbauten": {} - } - }, - "Technische Anlagen und Maschinen": { - "Technische Anlagen und Maschinen 1": { - "Betriebsvorrichtungen": {}, - "Maschinen": { - "account_type": "Fixed Asset" - }, - "Maschinen gebundene Werkzeuge": {}, - "Technische Anlagen ": {} - } - } - }, - "account_type": "Fixed Asset" - }, - "Umlaufverm\u00f6gen": { - "Abgrenzungsposten": { - "Abgrenzung latenter Steuern": { - "Abgrenzung aktive latente Steuern ": {} - }, - "Rechnungsabgrenzungsposten": { - "Aktive Rechnungsabgrenzung": { - "Als Aufwand ber\u00fccksichtigte Umstazsteuer auf Anzahlungen": {}, - "Als Aufwand ber\u00fccksichtigte Z\u00f6lle und Verbrauchsteuern auf Vorr\u00e4te": {}, - "Damnum/Disagio": {} - } - } - }, - "Forderungen und sonstige Verm\u00f6gensgegenst\u00e4nde": { - "Eingeforderte Nachsch\u00fcsse": { - "Eingeforderte Nachsch\u00fcsse (gegenkonto 2929)": {} - }, - "Eingeforderte- noch ausstehende Kapitaleinlagen": { - "Ausstehende Einlagen auf das gezeichnete Kapital- eingefordert": {} - }, - "Forderungen aus Lieferungen und Leistungen H-Saldo": { - "Einzelwertberechtigungen zu Forderungen mit einer Restlaufzeit bis zu 1 Jahr": {}, - "Einzelwertberechtigungen zu Forderungen mit einer Restlaufzeit von mehr als 1 Jahr": {}, - "Gegenkonto zu sonstigen Verm\u00f6gensgegenst\u00e4nden bei Buchungen \u00fcber Debitorenkonto": {}, - "Pauschalwertberichtigung zu Forderung mit einer Restlaufzeit bis zu 1 Jahr": {}, - "Pauschalwertberichtigung zu Forderung mit einer Restlaufzeit von mehr als 1 Jahr": {} - }, - "Forderungen aus Lieferungen und Leistungen H-Saldo oder sonstige Verbindlichkeiten S-Saldo": { - "Gegenkonto 1221-1229- 1240-1245- 1250-1257- 1270-1279- 1290-1297 bei Aufteilung Debitorenkonto": {} - }, - "Forderungen aus Lieferungen und Leistungen oder sonstige Verbindlichkeiten": { - "Forderungen aus Lieferungen und Leistungen ": { - "Forderungen aus Dienstleistungen": { - "account_type": "Receivable" - }, - "Forderungen aus Lieferungen und Leistungen nach Durchschnittss\u00e4tzen gem\u00e4\u00df \u00a724 UStG (E\u00fcR)": { - "account_type": "Receivable" - }, - "Forderungen aus Lieferungen und Leistungen ohne Kontokorent": {}, - "Forderungen aus Lieferungen und Leistungen ohne Kontokorent - Restlaufzeit bis 1 Jahr": {}, - "Forderungen aus Lieferungen und Leistungen ohne Kontokorent - Restlaufzeit gr\u00f6\u00dfer 1 Jahr.": {}, - "Forderungen aus Lieferungen und Leistungen zum allgemeinen Umsatzsteuersatz oder eines Kleinunternehmers (E\u00fcR)": { - "account_type": "Receivable" - }, - "Forderungen aus Lieferungen und Leistungen zum erm\u00e4\u00dfigten Umsatzsteuersatz (E\u00fcR)": { - "account_type": "Receivable" - }, - "Forderungen aus steuerfreien oder nicht steuerbaren Lieferungen und Leistungen (E\u00fcR)": { - "account_type": "Receivable" - }, - "Forderungen nach \u00a711 Abs. 1 Satz 2 EStG f\u00fcr \u00a7 4/3 EStG": { - "account_type": "Receivable" - }, - "Gegenkonto 1215-1218 bei Aufteilung der Forderungen nach Steuers\u00e4tzen (E\u00fcR)": { - "account_type": "Receivable" - }, - "Wechsel aus Lieferungen und Leistungen": {}, - "Wechsel aus Lieferungen und Leistungen Restlaufzeit bis 1 Jahr": {}, - "Wechsel aus Lieferungen und Leistungen Restlaufzeit gr\u00f6\u00dfer 1 Jahr": {}, - "Wechsel aus Lieferungen und Leistungen- bundesbankf\u00e4hig.": {}, - "Zweifelhafte Forderungen": {}, - "Zweifelhafte Forderungen - Restlaufzeit bis 1 Jahr": {}, - "Zweifelhafte Forderungen - Restlaufzeit gr\u00f6\u00dfer 1 Jahr": {} - }, - "Forderungen aus Lieferungen und Leistungen gegen Gesellschafter": { - "account_type": "Receivable" - }, - "Forderungen aus Lieferungen und Leistungen gegen Gesellschafter - Restlaufzeit bis 1 Jahr": {}, - "Forderungen aus Lieferungen und Leistungen gegen Gesellschafter - Restlaufzeit gr\u00f6\u00dfer 1 Jahr": {} - }, - "Forderungen gegen Unternehmen- mit denen ein Beteiligungsverh\u00e4ltnis besteht H-Saldo": { - "is_group": 1 - }, - "Forderungen gegen verbundene Unternehmen H-Saldo": { - "Wertberichtigungen zu Forderungen mit einer Restlaufzeit bis zu 1 Jahr gegen verbundene Unternehmen": {}, - "Wertberichtigungen zu Forderungen mit einer Restlaufzeit von mehr als 1 Jahr gegen verbundene Unternehmen": {} - }, - "Forderungen gegen verbundene Unternehmen oder Verbindlichkeiten gegen\u00fcber verbundenen Unternehmen": { - "Forderungen gegen verbundene Unternehmen ": { - "Besitzwechsel gegen verbundene Unternehmen": {}, - "Besitzwechsel gegen verbundene Unternehmen - Restlaufzeit bis 1 Jahr": {}, - "Besitzwechsel gegen verbundene Unternehmen - Restlaufzeit gr\u00f6\u00dfer Jahr": {}, - "Besitzwechsel gegen verbundene Unternehmen- bundesbankf\u00e4hig": {}, - "Forderungen aus Lieferungen und Leistungen gegen verbundenen Unternehmen": { - "account_type": "Receivable" - }, - "Forderungen aus Lieferungen und Leistungen gegen verbundenen Unternehmen - Restlaufzeit bis 1 Jahr": {}, - "Forderungen aus Lieferungen und Leistungen gegen verbundenen Unternehmen - Restlaufzeit gr\u00f6\u00dfer 1 Jahr": {}, - "Forderungen gegen verbundene Unternehmen - Restlaufzeit bis 1 Jahr. ": {}, - "Forderungen gegen verbundene Unternehmen - Restlaufzeit gr\u00f6\u00dfer 1 Jahr. ": {} - } - }, - "Sonstige Verbindlichkeiten S-Saldo": { - "Verrechnungskonto erhaltene Anzahlungen bei Buchungen \u00fcber Debitorenkonto": {} - }, - "Sonstige Verm\u00f6gensgegenst\u00e4nde": { - "Agenturwarenabrechnung": {}, - "Anspr\u00fcche aus R\u00fcckdeckungsversicherungen": {}, - "Forderungen an das Finanzamt aus abgef\u00fchrtem Bauabzugsbetrag": {}, - "Forderungen aus einrichteten Verbrauchsteuern": {}, - "Genossenschaftsanteile zum kurzfristigen Verbleib": {}, - "GmbH-Anteile zum kurzfristigen Verbleib": {}, - "K\u00f6rperschaftsteuerguthaben nach \u00a7 37 KStG - Restlaufzeit bis 1 Jahr": {}, - "K\u00f6rperschaftsteuerguthaben nach \u00a7 37 KStG - Restlaufzeit gr\u00f6\u00dfer 1 Jahr": {}, - "K\u00f6rperschaftsteuerr\u00fcckforderung": {}, - "Sonstige Verm\u00f6gensgegenst\u00e4nde 1": { - "Darlehen": {}, - "Darlehen - Restlaufzeit bis 1 jahr": {}, - "Darlehen - Restlaufzeit gr\u00f6\u00dfer 1 jahr": {}, - "Forderung gegen Aufsichtsrats- und Beirats- Mitglieder": {}, - "Forderung gegen Aufsichtsrats- und Beirats- Mitglieder - Restlaufzeit bis 1 Jahr": {}, - "Forderung gegen Aufsichtsrats- und Beirats- Mitglieder - Restlaufzeit gr\u00f6\u00dfer 1 Jahr": {}, - "Forderungen gegen Gesellschafter": {}, - "Forderungen gegen Gesellschafter - Restlaufzeit bis 1 Jahr": {}, - "Forderungen gegen Gesellschafter - Restlaufzeit gr\u00f6\u00dfer 1 Jahr": {}, - "Forderungen gegen Personal aus Lohn- und Gehaltsabrechnung": {}, - "Forderungen gegen Personal aus Lohn- und Gehaltsabrechnung - Restlaufzeit bis 1 Jahr": {}, - "Forderungen gegen Personal aus Lohn- und Gehaltsabrechnung - Restlaufzeit gr\u00f6\u00dfer 1 Jahr": {}, - "Forderungen gegen Vorstandsmitglieder und Gesch\u00e4ftsf\u00fchrer": {}, - "Forderungen gegen Vorstandsmitglieder und Gesch\u00e4ftsf\u00fchrer - Restlaufzeit bis 1 Jahr": {}, - "Forderungen gegen Vorstandsmitglieder und Gesch\u00e4ftsf\u00fchrer - Restlaufzeit gr\u00f6\u00dfer 1 Jahr": {}, - "Kautionen ": {}, - "Kautionen - Restlaufzeit bis 1 Jahr": {}, - "Kautionen - Restlaufzeit gr\u00f6\u00dfer 1 Jar": {}, - "Sonstige Verm\u00f6gensgegenst\u00e4nde - Restlaufzeit bis 1 Jahr": {}, - "Sonstige Verm\u00f6gensgegenst\u00e4nde - Restlaufzeit gr\u00f6\u00dfer 1 Jahr": {} - }, - "Steuererstattungsanspruch gegen\u00fcber andere EG-L\u00e4ndern": {}, - "Steuer\u00fcberzahlungen": {}, - "Umsatzsteuerforderung": {}, - "Umsatzsteuerforderungen Vorjahr": {}, - "Umsatzsteuerforderungen fr\u00fchere Jahre": {} - }, - "Sonstige Verm\u00f6gensgegenst\u00e4nde oder sonstige Verbindlichkeiten": { - "Abziehbare Vorsteuer": { - "account_type": "Tax", - "is_group": 1, - "Abziehbare Vorsteuer 16%": {}, - "Abziehbare Vorsteuer 19%": {}, - "Abziehbare Vorsteuer 7%": {}, - "Abziehbare Vorsteuer aus der Auslagerung von Gegenst\u00e4nden aus einem Unsatzsteuerlager": {}, - "Abziehbare Vorsteuer aus innergemeinschaftlichem Erwerb": {}, - "Abziehbare Vorsteuer aus innergemeinschaftlichem Erwerb 16%": {}, - "Abziehbare Vorsteuer aus innergemeinschaftlichem Erwerb 19%": {}, - "Abziehbare Vorsteuer aus innergemeinschaftlichem Erwerb von Neufahrzeugen von Lieferanten ohne Ust-Identifikationsnummer": {}, - "Abziehbare Vorsteuer nach \u00a7 13b UStG ": {}, - "Abziehbare Vorsteuer nach \u00a7 13b UStG 16%": {}, - "Abziehbare Vorsteuer nach \u00a7 13b UStG 19%": {} - }, - "Aufl\u00f6sung Vorsteuer aus Vorjahr \u00a7 4/3 EStG": {}, - "Aufzuteilende Vorsteuer": {}, - "Aufzuteilende Vorsteuer 16%": {}, - "Aufzuteilende Vorsteuer 19%": {}, - "Aufzuteilende Vorsteuer 7%": {}, - "Aufzuteilende Vorsteuer aus innergemeinschaftlichem Erwerb": {}, - "Aufzuteilende Vorsteuer aus innergemeinschaftlichem Erwerb 19%": {}, - "Aufzuteilende Vorsteuer nach \u00a7\u00a7 13a/13b UStG": {}, - "Aufzuteilende Vorsteuer nach \u00a7\u00a7 13a/13b UStG 16%": {}, - "Aufzuteilende Vorsteuer nach \u00a7\u00a7 13a/13b UStG 19%": {}, - "Bezahlte Einfuhrumsatzsteuer": {}, - "Durchlaufende Posten": {}, - "Fremdgeld": {}, - "Gegenkonto Vorsteuer \u00a7 4/3 EStG": {}, - "Gegenkonto f\u00fcr Vorsteuer nach Durchschnittss\u00e4tzen f\u00fcr \u00a7 4 Abs. 3 EStG": {}, - "Geldtransit": {}, - "Nachtr\u00e4glich abziehbare Vorsteuer- \u00a7 15a Abs. 1 UStG- bewegliche Wirtschaftsg\u00fcter": {}, - "Nachtr\u00e4glich abziehbare Vorsteuer- \u00a7 15a Abs. 2 UStG": {}, - "Nat\u00fcrlich abziehbare Vorsteuer- \u00a7 15a Abs. 1 UStG- unbewegliche Wirtschaftsg\u00fcter": {}, - "Umsatzsteuerforderungen laufendes Jahr": {}, - "Verrechnungskonto Gewinnermittlung \u00a7 4/3 EStG- ergebniswirksam": {}, - "Verrechnungskonto Gewinnermittlung \u00a7 4/3 EStG- nicht ergebniswirksam": {}, - "Verrechnungskonto Ist-Versteuerung": {}, - "Vorsteuer aus Investitionen \u00a7 4/3 EStG": {}, - "Vorsteuer im Folgejahr abziehbar": {}, - "Vorsteuer nach allgemeinen Durchschnittss\u00e4tzen UStVA Kz. 63": {}, - "Wirtschaftsg\u00fcter des Umlaufverm\u00f6gens gem\u00e4\u00df \u00a74 Abs. 3 Satz 4 EStG": {}, - "Zur\u00fcckzahlende Vorsteuer- \u00a7 15a Abs. 1 UStG- unbewegliche Wirtschaftsg\u00fcter": {}, - "Zur\u00fcckzuzahlende Vorsteuer- \u00a7 15a Abs. 1 UStG- bewegliche Wirtschaftsg\u00fcter": {}, - "Zur\u00fcckzuzahlende Vorsteuer- \u00a7 15a Abs. 2 UStG": {}, - "\u00fcberleitungskonto Kostenstellen": {} - } - }, - "Kassenbestand- Bundesbankguthaben- Guthaben bei Kreditinstituten und Schecks": { - "Kassenbestand - Bundesbankguthaben - Guthaben b. Kreditinstit. u. Schecks o. Verbindlichk. geg. Kreditinstituten": { - "Bank": {}, - "Bank 1": {}, - "Bank 2": {}, - "Bank 3": {}, - "Bank 4": {}, - "Bank 5": {}, - "Bundesbankguthaben": {}, - "Finanzmittelanlagen im Rahmen der Kurzfristigen Finanzdisposition": {}, - "LZB-Guthaben": {}, - "Postbank": {}, - "Postbank 1": {}, - "Postbank 2": {}, - "Postbank 3": {}, - "Verbindlichkeiten gegen\u00fcber Kreditinstituten (nicht im Finanzmittelfonds enthalten)": {}, - "account_type": "Bank" - }, - "Kassenbestand- Bundesbankguthaben- Guthaben bei Kreditinstituten und Schecks 1": { - "Kasse ": { - "Nebenkasse 1": {}, - "Nebenkasse 2": {}, - "account_type": "Cash" - }, - "Schecks": {} - } - }, - "Vorr\u00e4te": { - "Erhaltene Anzahlungen auf Bestellungen": { - "Erhaltene Anzahlungen auf Bestellungen (": {} - }, - "Fertige Erzeugnisse und Waren": { - "* Lager Bestand Zwischenkonto": { - "account_type": "Stock Adjustment" - }, - "* Lager Bestandswert Korrektur": { - "account_type": "Expenses Included In Valuation" - }, - "* Lager Differenzkorrektur Gewinn / Verlust": {}, - "* Lager Differenzkorrektur Marktwert": {}, - "Fertige Erzeugnisse (Bestand)": {}, - "Fertige Erzeugnisse und Waren (Bestand)": {}, - "Waren (Bestand)": {} - }, - "Geleistete Anzahlungen ": { - "Geleistete Anzahlungen auf Vorr\u00e4te": { - "Geleistete Anzahlungen 15% Vorsteuer": {}, - "Geleistete Anzahlungen 16% Vorsteuer": {}, - "Geleistete Anzahlungen 19% Vorsteuer": {}, - "Geleistete Anzahlungen 7% Vorsteuer": {} - } - }, - "In Arbeit befindliche Auftr\u00e4ge ": { - "In Arbeit befindliche Auftr\u00e4ge 1": {} - }, - "In Ausf\u00fchrung befindliche Bauauftr\u00e4ge": { - "In Ausf\u00fchrung befindliche Bauauftr\u00e4ge 1": {} - }, - "Roh- Hilfs- und Betriebsstoffe": { - "Roh- Hilfs- und Betriebsstoffe (Bestand)": { - "account_type": "Cost of Goods Sold" - } - }, - "Unfertige Erzeugnisse- unfertige Leistungen": { - "Unfertige Erzeugnisse": {}, - "Unfertige Erzeugnisse- unfertige Leistungen (Bestand)": {}, - "Unfertige Leistungen": {} - }, - "account_type": "Stock" - }, - "Wertpapiere": { - "Anteile an verbundenen Unternehmen": { - "Anteile an herrschender oder mit Mehrheit beteiligter Gesellschaft": {}, - "Anteile an verbundenen Unternehmen (Umlaufverm\u00f6gen)": {} - }, - "Eigene Anteile ": { - "Eigene Anteile 1": {} - }, - "Sonstige Wertpapiere": { - "Sonstige Wertpapiere 1": { - "Andere Wertpapiere mit unwesentlichen Wertschwankungen im Sinne Textziffer 18 DRS 2": {}, - "Finanzwechsel": {}, - "Wertpapieranlagen im Rahmen der Kurzfristigen Finanzdisposition ": {} - } - } - } - }, - "root_type": "Asset" - }, - "Bilanz - Passiva": { - "Eigenkapital": { - "Gewinnr\u00fccklagen": { - "Andere Gewinnr\u00fccklagen": { - "Andere Gewinnr\u00fccklagen 1": { - "Eigenkapitalanteil von Wertaufholungen": {} - } - }, - "Gesetzliche R\u00fccklagen": { - "Gesetzliche R\u00fccklagen 1": {} - }, - "R\u00fccklage f\u00fcr Eigene Anteile": { - "R\u00fccklage f\u00fcr Eigene Anteile 1": {} - }, - "Satzungsm\u00e4\u00dfige R\u00fccklagen": { - "Satzungsm\u00e4\u00dfige R\u00fccklagen 1": {} - } - }, - "Gewinnvortrag / Verlustvortrag vor Verwendung": { - "Gewinnvortrag / Verlustvortrag": { - "Gewinnvortrag vor Verwendung": {}, - "Verlustvortrag vor Verwendung": {} - }, - "Vortrag auf neue Rechnung ": { - "Vortrag auf neue Rechnung (Bilanz)": {} - } - }, - "Gezeichnetes Kapital": { - "Gezeichnetes Kapital 1": { - "Gezeichnetes Kapital 2": {} - }, - "Nicht eingeforderte ausstehende Einlagen": { - "is_group": 1 - } - }, - "Kapital Teilhaber": { - "(zur freien Verf\u00fcgung ) 1": {}, - "Gesellschafter-Darlehen 3": {}, - "Kommandit-Kapital": {}, - "Verlustausgleichskonto": {} - }, - "Kapital Vollhafter / Einzelunternehmer": { - "(zur freien Verf\u00fcgung )": {}, - "Festkapital": {}, - "Gesellschafter-Darlehen 2": {}, - "Variables Kapital": {} - }, - "Kapitalr\u00fccklage": { - "Kapitalr\u00fccklage 1": { - "Kapitalr\u00fccklage 2": { - "Andere Zuzahlungen in das Eigenkapital ": {}, - "Eingefordertes Nachschusskapital (Gegenkonto 1299)": {}, - "Kapitalr\u00fccklage durch Ausgabe von Anteilen \u00fcber Nennbetrag": {}, - "Kapitalr\u00fccklage durch Ausgabe von Schuldverschreibungen f\u00fcr Wandlungsrechte und Optionsrechte zum Erwerb von Anteilen": {}, - "Kapitalr\u00fccklage durch Zuzahlungen gegen Gew\u00e4hrung eines Vorzugs f\u00fcr Anteile": {} - } - } - }, - "Privat Teilhafter": { - "Ausgew\u00f6hnliche Belastungen": {}, - "Grundst\u00fccksaufwand 1": {}, - "Grundst\u00fccksertrag 1": {}, - "Privateinlagen 1": {}, - "Privatentnahmen allgemein 1": {}, - "Privatsteuern 1": {}, - "Sonderausgaben beschr\u00e4nkt abzugsf\u00e4hig 1": {}, - "Sonderausgaben unbeschr\u00e4nkt abzugsf\u00e4hig 1": {}, - "Unentgeltliche Wertabgaben 1": {}, - "Zuwendungen- Spenden 1": {} - }, - "Privat Vollhafter/ Einzelunternehmer": { - "Ausgew\u00f6hnliche Belastungen 1": {}, - "Grundst\u00fccksaufwand (Umsatzsteuerschl\u00fcssel m\u00f6glich)": {}, - "Grundst\u00fccksaufwand 2": {}, - "Grundst\u00fccksertrag ( Umsatzsteuerschl\u00fcssel m\u00f6glich)": {}, - "Grundst\u00fccksertrag 2": {}, - "Privateinlagen 2": {}, - "Privatentnahmen allgemein 2": {}, - "Privatsteuern 2": {}, - "Sonderausgaben beschr\u00e4nkt abzugsf\u00e4hig 2": {}, - "Sonderausgaben unbeschr\u00e4nkt abzugsf\u00e4hig 2": {}, - "Unentgeltliche Wertabgaben 2": {}, - "Zuwendungen- Spenden 2": {} - }, - "Sonderposten mit R\u00fccklageanteil": { - "Sonderposten aus der W\u00e4hrungsumstellung auf den Euro": { - "Sonderposten aus der W\u00e4hrungsumstellung auf den Euro 1": {} - }, - "Sonderposten f\u00fcr Zusch\u00fcsse und Zulagen": { - "Sonderposten f\u00fcr Zusch\u00fcsse und Zulagen 1": {} - }, - "Sonderposten mit R\u00fccklageanteil 1": { - "Sonderposten mit R\u00fccklageanteil f\u00fcr F\u00f6rderung nach \u00a7 3 ZonenRFG / \u00a74-6 F\u00f6rdergebietsG": {}, - "Sonderposten mit R\u00fccklageanteil nach Abschnitt 35 EStG": {}, - "Sonderposten mit R\u00fccklageanteil nach \u00a7 1 EntwLStG": {}, - "Sonderposten mit R\u00fccklageanteil nach \u00a7 14 BerlinFG": {}, - "Sonderposten mit R\u00fccklageanteil nach \u00a7 4d EStG": {}, - "Sonderposten mit R\u00fccklageanteil nach \u00a7 52 Abs. 16 EStG": {}, - "Sonderposten mit R\u00fccklageanteil nach \u00a7 6b EStG": {}, - "Sonderposten mit R\u00fccklageanteil nach \u00a7 6d EStG": {}, - "Sonderposten mit R\u00fccklageanteil nach \u00a7 79 EStDV": {}, - "Sonderposten mit R\u00fccklageanteil nach \u00a7 7d EStG": {}, - "Sonderposten mit R\u00fccklageanteil nach \u00a7 7g Abs. 1 EStG": {}, - "Sonderposten mit R\u00fccklageanteil nach \u00a7 7g Abs. 3 u. 7 EStG": {}, - "Sonderposten mit R\u00fccklageanteil nach \u00a7 80 EStDV": {}, - "Sonderposten mit R\u00fccklageanteil nach \u00a7 82a EStDV": {}, - "Sonderposten mit R\u00fccklageanteil nach \u00a7 82d EStDV": {}, - "Sonderposten mit R\u00fccklageanteil nach \u00a7 82e EStDV": {}, - "Sonderposten mit R\u00fccklageanteil steuerfreie R\u00fccklagen": {}, - "Sonderposten mit R\u00fccklageanteil- Sonderabschreibung": {} - } - } - }, - "Fremdkapital": { - "Rechnungsabgrenzungsposten 1": { - "Rechnungsabgrenzungsposten 2": { - "Passive Rechnungsabgrenzung 1": {} - }, - "Sonstige Passiva oder sontige Aktiva": { - "Abgrenzungen zur unterj\u00e4hrigen Kostenverrechnung f\u00fcr BWA": {} - } - }, - "R\u00fcckstellungen ": { - "R\u00fcckstellungen f\u00fcr Pensionen und \u00e4hnliche Verpflichtungen": { - "R\u00fcckstellungen f\u00fcr Pensionen und \u00e4hnliche Verpflichtungen 1": { - "Pensionsr\u00fcckstellungen": {}, - "R\u00fcckstellungen f\u00fcr Pensions\u00e4hnliche Verpflichtungen": {} - } - }, - "Sonstige R\u00fcckstellungen": { - "Sonstige R\u00fcckstellungen 1": { - "Aufwandsr\u00fcckstellungen gem\u00e4\u00df \u00a7 249 Abs. 2 HGB": {}, - "R\u00fcckstellungen f\u00fcr Abraum- und Abfallbeseitigung": {}, - "R\u00fcckstellungen f\u00fcr Abschluss- und Pr\u00fcfungskosten": {}, - "R\u00fcckstellungen f\u00fcr Gew\u00e4hrleistungen (Gegenkonto 6790)": {}, - "R\u00fcckstellungen f\u00fcr Personelkosten": {}, - "R\u00fcckstellungen f\u00fcr Umweltschutz": {}, - "R\u00fcckstellungen f\u00fcr drohende Verluste aus schwebenden Gesch\u00e4ften": {}, - "R\u00fcckstellungen f\u00fcr unterlassene Aufwendungenn f\u00fcr Instandhaltung- Nachholung in den ersten drei Monaten": {}, - "R\u00fcckstellungen f\u00fcr unterlassene Aufwendungenn f\u00fcr Instandhaltung- Nachholung innerhalb des 4. bis 12. Monats": {}, - "R\u00fcckstellungen zur Erf\u00fcllung der Aufbewahrungspflichten": {} - } - }, - "Steuerr\u00fcckstellungen": { - "Steuerr\u00fcckstellungen 1": { - "Gewerbesteuerr\u00fcckstellung": {}, - "K\u00f6rperschaftsteuerr\u00fcckstellung": {}, - "R\u00fcckstellung f\u00fcr latente Steuern ": {} - } - } - }, - "Verbindlichkeiten ": { - "Anleihen": { - "Anleihen- nicht konvertibel": { - "Anleihen- konvertibel": {}, - "Anleihen- konvertibel Restlaufzeit 1 bis 5 Jahre": {}, - "Anleihen- konvertibel Restlaufzeit bis 1 Jahr": {}, - "Anleihen- konvertibel Restlaufzeit gr\u00f6\u00dfer 5 Jahr": {}, - "Anleihen- nicht konvertibel Restlaufzeit 1 bis 5 Jahre": {}, - "Anleihen- nicht konvertibel Restlaufzeit bis 1 Jahr": {}, - "Anleihen- nicht konvertibel Restlaufzeit gr\u00f6\u00dfer 5 Jahre ": {} - } - }, - "Erhaltene Anzahlungen auf Bestellungen 1": { - "Erhaltene Anzahlungen auf Bestellungen 2": { - "Erhaltene Anzahlungen 15% USt": {}, - "Erhaltene Anzahlungen 16% USt": {}, - "Erhaltene Anzahlungen 7% USt": {}, - "Erhaltene Anzahlungen Restlaufzeit 1 bis 5 Jahre": {}, - "Erhaltene Anzahlungen Restlaufzeit bis 1 Jahr": {}, - "Erhaltene Anzahlungen Restlaufzeit gr\u00f6\u00dfer 5 Jahre": {}, - "Erhaltene- versteuerte Anzahlungen 19% Ust (Verbindlichkeiten)": {} - } - }, - "Sonstige Verbindlichkeiten ": { - "Sonstige Verbindlichkeiten 1": { - "(frei- in Bilanz kein Restlaufzeit vermerkt)": {}, - "Agenturwarenabrechnungen": {}, - "Darlehen - Restlaufzeit 1 bis 5 jahre": {}, - "Darlehen - Restlaufzeit bis 1 jahr 1": {}, - "Darlehen - Restlaufzeit gr\u00f6\u00dfer 5 jahre": {}, - "Darlehen 2": {}, - "Darlehen atypisch stiller Gesellschaftler ": {}, - "Darlehen atypisch stiller Gesellschaftler - Restlaufzeit 1 bis 5 Jahre": {}, - "Darlehen atypisch stiller Gesellschaftler - Restlaufzeit bis 1 Jahr": {}, - "Darlehen atypisch stiller Gesellschaftler - Restlaufzeit gr\u00f6\u00dfer 5 Jahre": {}, - "Darlehen typisch stiller Gesellschaftler": {}, - "Darlehen typisch stiller Gesellschaftler - Restlaufzeit 1 bis 5 Jahre": {}, - "Darlehen typisch stiller Gesellschaftler - Restlaufzeit bis 1 Jahr": {}, - "Darlehen typisch stiller Gesellschaftler - Restlaufzeit gr\u00f6\u00dfer 5 Jahre": {}, - "Erhaltene Kautionen": {}, - "Erhaltene Kautionen - Restlaufzeit 1 bis 5 Jahre": {}, - "Erhaltene Kautionen - Restlaufzeit bis 1 Jahr": {}, - "Erhaltene Kautionen - Restlaufzeit gr\u00f6\u00dfer 5 Jahre": {}, - "Gegenkonto 3500-3569 bei Aufteilung der Konten 3570-3598": {}, - "Kreditkartenabrechnung": {}, - "Partiarische Darlehen": {}, - "Partiarische Darlehen - Restlaufzeit 1 bis 5 Jahre": {}, - "Partiarische Darlehen - Restlaufzeit bis 1 Jahr": {}, - "Partiarische Darlehen - Restlaufzeit gr\u00f6\u00dfer 5 Jahre": {}, - "Sonstige Verbindlichkeiten - Restlaufzeit 1 bis 5 Jahre": {}, - "Sonstige Verbindlichkeiten - Restlaufzeit bis 1 Jahr": {}, - "Sonstige Verbindlichkeiten - Restlaufzeit gr\u00f6\u00dfer 5 Jahre": {}, - "Sonstige Verbindlichkeiten z.B. nach \u00a7 11 Abs. 2 Satz 2 EStG f\u00fcr \u00a7 4/3 EStG": {}, - "Verbindlichkeiten gegen\u00fcber Gesellschaftern ": {}, - "Verbindlichkeiten gegen\u00fcber Gesellschaftern - Restlaufzeit 1 bis 5 Jahre": {}, - "Verbindlichkeiten gegen\u00fcber Gesellschaftern - Restlaufzeit bis 1 Jahr": {}, - "Verbindlichkeiten gegen\u00fcber Gesellschaftern - Restlaufzeit gr\u00f6\u00dfer 5 Jahre": {}, - "Verbindlichkeiten gegen\u00fcber Gesellschaftern f\u00fcr offene Aussch\u00fcttungen": {} - }, - "Steuerzahlungen an andere EG-L\u00e4nder": {}, - "Umsatzsteuer aus im anderen EG-Land steuerpflichtigen Lieferungen": {}, - "Umsatzsteuer aus im anderen EG-Land steuerpflichtigen sonstigen Leistungen/Werlieferungen": {}, - "Verbindlichkeiten an das Finanzamt aus abzuf\u00fchrendem Bauabzugsbetrag": {}, - "Verbindlichkeiten aus Betriebssteuern und -abgaben": {}, - "Verbindlichkeiten aus Betriebssteuern und -abgaben - Restlaufzeit 1 bis 5 Jahre": {}, - "Verbindlichkeiten aus Betriebssteuern und -abgaben - Restlaufzeit bis 1 Jahr": {}, - "Verbindlichkeiten aus Betriebssteuern und -abgaben - Restlaufzeit gr\u00f6\u00dfer 5 Jahre": {}, - "Verbindlichkeiten aus Einbehaltungen (KapESt und Solz auf KapESt)": {}, - "Verbindlichkeiten aus Lohn und Gehalt": {}, - "Verbindlichkeiten aus Verm\u00f6gensbildung ": {}, - "Verbindlichkeiten aus Verm\u00f6gensbildung - Restlaufzeit 1 bis 5 Jahre": {}, - "Verbindlichkeiten aus Verm\u00f6gensbildung - Restlaufzeit bis 1 Jahr": {}, - "Verbindlichkeiten aus Verm\u00f6gensbildung - Restlaufzeit gr\u00f6\u00dfer 5 Jahre": {}, - "Verbindlichkeiten f\u00fcr Einbehaltungen von Arbeitnehmern": {}, - "Verbindlichkeiten f\u00fcr Verbrauchsteuern": {}, - "Verbindlichkeiten im Rahmen der sozialen Sicherheit": {}, - "Verbindlichkeiten im Rahmen der sozialen Sicherheit (f\u00fcr \u00a7 4/3 EStG)": {}, - "Verbindlichkeiten im Rahmen der sozialen Sicherheit - Restlaufzeit 1 bis 5 Jahre": {}, - "Verbindlichkeiten im Rahmen der sozialen Sicherheit - Restlaufzeit bis 1 Jahr": {}, - "Verbindlichkeiten im Rahmen der sozialen Sicherheit - Restlaufzeit gr\u00f6\u00dfer 5 Jahre": {}, - "Voraussichtliche Beitragsschuld gegen\u00fcber den Sozialversicherungstr\u00e4gern": {} - }, - "Sonstige Verm\u00f6gensgegenst\u00e4nde H-Saldo": { - "Verrechnungskonto geleistete Anzahlungen bei Buchung \u00fcber Kreditorenkonto": {} - }, - "Sonstige Verm\u00f6gensgegenst\u00e4nde oder sonstige Verbindlichkeiten 1": { - "Einfuhrumsatzsteuer aufgeschoben bis": {}, - "Gewinnverf\u00fcgungskonto stille Gesellschafter": {}, - "In Rechnung unrichtig oder unberechtigt ausgewiesene Steuerbetr\u00e4ge- UStVA Kz. 69": {}, - "Lohn- und Gehaltsverrechnungskonto": { - "Lohn- und Gehaltsverrechnung \u00a7 11 Abs. 2 EStG f\u00fcr \u00a7 a Abs. 3 EStG": {} - }, - "Nachsteuer- UStVA Kz. 65": {}, - "Sonstige Verrechnungskonten (Interimskonto)": { - "account_type": "Stock Received But Not Billed" - }, - "Umsatzsteuer": { - "account_type": "Tax", - "is_group": 1, - "Umsatzsteuer 16%": {}, - "Umsatzsteuer 19%": {}, - "Umsatzsteuer 7%": {}, - "Umsatzsteuer Vorjahr": {}, - "Umsatzsteuer aus der Auslagerung von Gegenst\u00e4nden aus einem Umsatzsteuerlager": {}, - "Umsatzsteuer aus im Inland steuerpflichtigen EG-Lieferungen": {}, - "Umsatzsteuer aus im Inland steuerpflichtigen EG-Lieferungen 19%": {}, - "Umsatzsteuer aus innergemeinschaftlichem Erwerb ": {}, - "Umsatzsteuer aus innergemeinschaftlichem Erwerb 16%": {}, - "Umsatzsteuer aus innergemeinschaftlichem Erwerb 19%": {}, - "Umsatzsteuer aus innergemeinschaftlichem Erwerb ohne Vorsteuerabzug": {}, - "Umsatzsteuer fr\u00fchere Jahre": {}, - "Umsatzsteuer laufendes Jahr": {}, - "Umsatzsteuer nach \u00a713b UStG": {}, - "Umsatzsteuer nach \u00a713b UStG 16%": {}, - "Umsatzsteuer nach \u00a713b UStG 19%": {} - }, - "Umsatzsteuer- Vorauszahlungen": {}, - "Umsatzsteuer- Vorauszahlungen 1/11": {}, - "Verbindlichkeiten aus Lohn- und Kirchensteuer": {} - }, - "Steuerr\u00fcckstellungen oder sonstige Verm\u00f6gensgegenst\u00e4nde ": { - "Umsatzsteuer nicht f\u00e4llig": {}, - "Umsatzsteuer nicht f\u00e4llig 16%": {}, - "Umsatzsteuer nicht f\u00e4llig 19%": {}, - "Umsatzsteuer nicht f\u00e4llig 7%": {}, - "Umsatzsteuer nicht f\u00e4llig aus im Inland steuerpflichtigen EG-Lieferungen": {}, - "Umsatzsteuer nicht f\u00e4llig aus im Inland steuerpflichtigen EG-Lieferungen 16%": {}, - "Umsatzsteuer nicht f\u00e4llig aus im Inland steuerpflichtigen EG-Lieferungen 19%": {} - }, - "Verbindlichkeiten aus Lieferungen und Leistungen S-Saldo oder sonstige Verm\u00f6gensgegenst\u00e4nde H-Saldo": { - "Gegenkonto 3335-3348- 3420-3449- 3470-3499 bei Aufteilung Kreditorenkonto": {} - }, - "Verbindlichkeiten aus Lieferungen und Leistungen oder sonstige Verm\u00f6gensgegenst\u00e4nde": { - "Verbindlichkeiten aus Lieferungen und Leistungen ": { - "Gegenkonto 3305-3307 bei Aufteilung der Verbindlichkeiten nach Steuers\u00e4tzen (E\u00fcR)": {}, - "Lieferanten Verbindlichkeiten Dienstleistungen": { - "account_type": "Payable" - }, - "Verbindlichkeiten aus Lieferungen und Leistungen f\u00fcr Investitionen f\u00fcr \u00a7 4/3 EStG": { - "account_type": "Payable" - }, - "Verbindlichkeiten aus Lieferungen und Leistungen gegen\u00fcber Gesellschaftern ": { - "account_type": "Payable" - }, - "Verbindlichkeiten aus Lieferungen und Leistungen gegen\u00fcber Gesellschaftern Restlaufzeit 1 bis 5 Jahre": {}, - "Verbindlichkeiten aus Lieferungen und Leistungen gegen\u00fcber Gesellschaftern Restlaufzeit bis 1 Jahr": {}, - "Verbindlichkeiten aus Lieferungen und Leistungen gegen\u00fcber Gesellschaftern Restlaufzeit gr\u00f6\u00dfer 5 Jahre": {}, - "Verbindlichkeiten aus Lieferungen und Leistungen ohne Kontokorrent ": {}, - "Verbindlichkeiten aus Lieferungen und Leistungen ohne Kontokorrent Restlaufzeit 1 bis 5 Jahre": {}, - "Verbindlichkeiten aus Lieferungen und Leistungen ohne Kontokorrent Restlaufzeit bis 1 Jahr": {}, - "Verbindlichkeiten aus Lieferungen und Leistungen ohne Kontokorrent Restlaufzeit gr\u00f6\u00dfer 5 Jahre": {}, - "Verbindlichkeiten aus Lieferungen und Leistungen ohne Vorsteuer (E\u00fcR)": { - "account_type": "Payable" - }, - "Verbindlichkeiten aus Lieferungen und Leistungen zum allgemeinen Umsatzsteuersatz (E\u00fcR)": { - "account_type": "Payable" - }, - "Verbindlichkeiten aus Lieferungen und Leistungen zum erm\u00e4\u00dfigten Umsatzsteuersatz (E\u00fcR)": { - "account_type": "Payable" - } - } - }, - "Verbindlichkeiten aus der Annahme gezogener Wechsel und aus der Ausstellung eigener Wechsel": { - "Verbindlichkeiten aus der Annahme gezogener Wechsel und aus der Ausstellung eigener Wechsel 1": { - "Verbindlichkeiten aus der Annahme gezogener Wechsel und aus der Ausstellung eigener Wechsel Restlaufzeit 1 bis 5 Jahre": {}, - "Verbindlichkeiten aus der Annahme gezogener Wechsel und aus der Ausstellung eigener Wechsel Restlaufzeit bis 1 Jahr": {}, - "Verbindlichkeiten aus der Annahme gezogener Wechsel und aus der Ausstellung eigener Wechsel Restlaufzeit gr\u00f6\u00dfer 5 Jahre": {} - } - }, - "Verbindlichkeiten gegen\u00fcber Kreditinstituten ": { - "Gegenkonto 3159-3209 bei Aufteilung der Konten 3210-3248": {} - }, - "Verbindlichkeiten gegen\u00fcber Kreditinstituten - Bundesbankguthaben- Guthaben bei Kreditinstituten und Schecks": { - "Verbindlichkeiten gegen\u00fcber Kreditinstituten 1": { - "(frei- in Bilanz kein Restlaufzeit vermerkt) 1": {}, - "Verbindlichkeiten gegen\u00fcber Kreditinstituten Restlaufzeit 1 bis 5 Jahre": {}, - "Verbindlichkeiten gegen\u00fcber Kreditinstituten Restlaufzeit bis 1 Jahr": {}, - "Verbindlichkeiten gegen\u00fcber Kreditinstituten Restlaufzeit gr\u00f6\u00dfer 5 Jahre": {}, - "Verbindlichkeiten gegen\u00fcber Kreditinstituten aus Teilzahlungsvertr\u00e4gen": {}, - "Verbindlichkeiten gegen\u00fcber Kreditinstituten aus Teilzahlungsvertr\u00e4gen Restlaufzeit 1 bis 5 Jahre": {}, - "Verbindlichkeiten gegen\u00fcber Kreditinstituten aus Teilzahlungsvertr\u00e4gen Restlaufzeit bis 1 Jahr": {}, - "Verbindlichkeiten gegen\u00fcber Kreditinstituten aus Teilzahlungsvertr\u00e4gen Restlaufzeit gr\u00f6\u00dfer 5 Jahre": {} - } - }, - "Verbindlichkeiten gegen\u00fcber verbundenen Unternehmen oder Forderungen gegen verbundene Unternehmen": { - "Verbindlichkeiten gegen\u00fcber verbundenen Unternehmen": { - "Verbindlichkeiten aus Lieferungen und Leistungen gegen\u00fcber verbundenen Unternehmen": { - "account_type": "Payable" - }, - "Verbindlichkeiten aus Lieferungen und Leistungen gegen\u00fcber verbundenen Unternehmen Restlaufzeit 1 bis 5 Jahre": {}, - "Verbindlichkeiten aus Lieferungen und Leistungen gegen\u00fcber verbundenen Unternehmen Restlaufzeit bis 1 Jahr": {}, - "Verbindlichkeiten aus Lieferungen und Leistungen gegen\u00fcber verbundenen Unternehmen Restlaufzeit gr\u00f6\u00dfer 5 Jahre": {}, - "Verbindlichkeiten gegen\u00fcber verbundenen Unternehmen Restlaufzeit 1 bis 5 Jahre": {}, - "Verbindlichkeiten gegen\u00fcber verbundenen Unternehmen Restlaufzeit bis 1 Jahr": {}, - "Verbindlichkeiten gegen\u00fcber verbundenen Unternehmen Restlaufzeit gr\u00f6\u00dfer 5 Jahre": {} - } - } - } - }, - "root_type": "Liability" - }, - "Gewinn u. Verlust - Aufwendungen": { - "Betriebliche Aufwendungen": { - "Abschreibungen a. Verm\u00f6gensgeg. d. Umlaufverm\u00f6gens- soweit diese die in der Abschreibungen \u00fcberschreiten": { - "Abschreibungen a. Verm\u00f6gensgeg. d. Umlaufverm\u00f6gens- soweit diese die in der Abschreibungen \u00fcberschreiten": { - "Abschreibungen auf Umlaufverm\u00f6gen- steuerrechtlich bedingt (soweit un\u00fcblich hoch)": {}, - "Abschreibungen auf Verm\u00f6gensgegenst\u00e4nde des Umlaufverm\u00f6gens (soweit un\u00fcblich hoch)": {}, - "Forderungsverluste (soweit un\u00fcblich hoch)": {}, - "Forderungsverluste 15% USt (soweit un\u00fcblich hoch)": {}, - "Forderungsverluste 16% USt (soweit un\u00fcblich hoch)": {}, - "Forderungsverluste 19% USt (soweit un\u00fcblich hoch)": {}, - "Forderungsverluste 7% USt (soweit un\u00fcblich hoch)": {}, - "Vorwegnahme k\u00fcnftiger Wertschwankungen im Umlaufverm\u00f6gen (soweit un\u00fcblich hoch)": {} - } - }, - "Kalkulatorische Kosten": { - "Sonstige betriebliche Aufwendungen 2": { - "Kalkulatorische Abschreibungen": {}, - "Kalkulatorische Miete/Pacht": {}, - "Kalkulatorische Wagnisse": {}, - "Kalkulatorische Zinsen": {}, - "Kalkulatorischer Lohn f\u00fcr unentgeltliche Mitarbeiter": {}, - "Kalkulatorischer Unternehmerlohn": {}, - "Verrechnete kalkulatorische Abschreibungen": {}, - "Verrechnete kalkulatorische Miete/Pacht": {}, - "Verrechnete kalkulatorische Wagnisse": {}, - "Verrechnete kalkulatorische Zinsen": {}, - "Verrechneter kalkulatorischer Lohn f\u00fcr unentgeltliche Mitarbeiter": {}, - "Verrechneter kalkulatorischer Unternehmerlohn": {} - } - }, - "Kosten bei Anwendung des Umsatzkostenverfahrens": { - "Sonstige betriebliche Aufwendungen 1": { - "Gegenkonto 6990-6998": {}, - "Herstellungskosten": {}, - "Vertriebskosten": {}, - "Verwaltungskosten": {} - } - }, - "Personalaufwand": { - "L\u00f6hne und Geh\u00e4lter": { - "Aushilfsl\u00f6hne": {}, - "Bedienungsgelder": {}, - "Ehegattengehalt": {}, - "Fahrkostenerstattung Wohnung/Arbeitsst\u00e4tte": {}, - "Freiwillige soziale Aufwendungen- lohnsteuerpflichtig": {}, - "Geh\u00e4lter": {}, - "Gesch\u00e4ftsf\u00fchrergeh\u00e4lter ": {}, - "Gesch\u00e4ftsf\u00fchrergeh\u00e4lter der GmbH-Gesellschafter": {}, - "Krankengeldzusch\u00fcsse": {}, - "L\u00f6hne ": {}, - "L\u00f6hne und Geh\u00e4lter 1": {}, - "Pauschale Steuer auf sonstige Bez\u00fcge (z.B. Fahrkosten Zusch\u00fcsse)": {}, - "Pauschale Steuer f\u00fcr Aushilfen": {}, - "Tantiemen": {}, - "Verg\u00fctungen an angestellte Mitunternehmer \u00a7 15 EStG": {}, - "Verm\u00f6genswirksame Leistungen": {}, - "Zusch\u00fcsse der Agenturen f\u00fcr Arbeit (Haben)": {} - }, - "Soziale Abgaben und Aufwendungen f\u00fcr Altersversorgung und f\u00fcr Unterst\u00fctzung": { - "Soziale Abgaben und Aufwendungen f\u00fcr Altersversorgung und f\u00fcr Unterst\u00fctzung 1": { - "Aufwendungen f\u00fcr Altersversorgung": {}, - "Aufwendungen f\u00fcr Altersversorgung f\u00fcr Mitunternehmer \u00a7 15 EStG": {}, - "Aufwendungen f\u00fcr Unterst\u00fctzung": {}, - "Beitr\u00e4ge zur Berufsgenossenschaft": {}, - "Freiwillige soziale Aufwendungen- lohnsteuerfrei": {}, - "Gesetzliche soziale Aufwendungen": {}, - "Gesetzliche soziale Aufwendungen f\u00fcr Mitunternehmer \u00a7 15 EStG": {}, - "Pauschale Steuer auf sonstige Bez\u00fcge (z.B. Direktversicherungen)": {}, - "Sonstige soziale Abgaben": {}, - "Versorgungskassen": {} - } - } - }, - "Sonstige betriebliche Aufwendungen 3": { - "Sonstige betriebliche Aufwendungen 4": { - "Abgaben f\u00fcr betrieblich genutzten Grundbesitz": {}, - "Abgang von Wirtschaftsg\u00fctern des Umlaufverm\u00f6gens 100% / 50% nicht abzugsf\u00e4hig (inlandische Kap. Ges.) nach": {}, - "Abgang von Wirtschaftsg\u00fctern des Umlaufverm\u00f6gens nach \u00a7 4 Abs. 3 Satz 4 EStG": {}, - "Abschluss- und Pr\u00fcfungskosten": {}, - "Abschreibung auf Umlaufverm\u00f6gen au\u00dfer Vorr\u00e4te und Wertpapieren des UV (\u00fcbliche H\u00f6he)": {}, - "Abschreibung auf Umlaufverm\u00f6gen au\u00dfer Vorr\u00e4te und Wertpapieren des UV- steuerlich bedingt (\u00fcbliche H\u00f6he)": {}, - "Abziehbare Aufsichtsratsverg\u00fctungen": {}, - "Anlagenabg\u00e4nge Finanzanlagen (Restbuchwert bei Buchverlust)": {}, - "Anlagenabg\u00e4nge Finanzanlagen 100% / 50% steuerfrei (inl\u00e4ndische Kap. Ges.)(Restbuchwert bei Buchverlust)": {}, - "Anlagenabg\u00e4nge Sachanlagen (Restbuchwert bei Buchverlust)": {}, - "Anlagenabg\u00e4nge immaterielle Verm\u00f6gensgegenst\u00e4nde (Restbuchwert bei Buchverlust)": {}, - "Aufmerksamkeiten": {}, - "Aufwand f\u00fcr Gew\u00e4hrleistung": {}, - "Aufwendungen aus Anteilen an Kapitalgesellschaften 100% / 50% nicht abzugsf\u00e4hig (inlandische Kap. Ges.)": {}, - "Aufwendungen aus Bewertung Finanzmittelfonds": {}, - "Aufwendungen aus Kursdifferenzen": {}, - "Aufwendungen aus der Ver\u00e4u\u00dferung von Anteilen an Kapitalgesellschaften 100% / 50% nicht abzugsf\u00e4hig": {}, - "Aufwendungen aus der Zuschreibung von steuertlich niedriger bewerteten R\u00fcckstellungen": {}, - "Aufwendungen aus der Zuschreibung von steuertlich niedriger bewerteten Verbindlichkeiten": {}, - "Aufwendungen f\u00fcr Abraum- und Abfallbeseitigung": {}, - "Aufwendungen f\u00fcr ein h\u00e4usliches Arbeitszimmer (abziehbarer Anteil)": {}, - "Aufwendungen f\u00fcr ein h\u00e4usliches Arbeitszimmer (nicht abziehbarer Anteil)": {}, - "Ausgangsfrachten": {}, - "Ausgleichsabgabe i. S. d. Schwerbehindertengesetzes": {}, - "Beitr\u00e4ge ": {}, - "Bewirtungskosten": {}, - "Buchf\u00fchrungskosten": {}, - "B\u00fcrobedarf": {}, - "Einstellungen in Sonderposten mit R\u00fccklageanteil (Ansparabschreibungen)": {}, - "Einstellungen in Sonderposten mit R\u00fccklageanteil (Existenzgr\u00fcnderr\u00fccklage)": {}, - "Einstellungen in Sonderposten mit R\u00fccklageanteil (Sonderabschreibungen)": {}, - "Einstellungen in Sonderposten mit R\u00fccklageanteil (Steuerfreie R\u00fccklagen)": {}, - "Einstellungen in Sonderposten mit R\u00fccklageanteil (\u00a7 52 Abs. 16 EStG)": {}, - "Einstellungen in die Einzelwertberichtigung zu Forderungen": {}, - "Einstellungen in die Pauschalwertberichtigung zu Forderungen": {}, - "Erl\u00f6se aus Verk\u00e4ufen Finanzanlagen (bei Buchverlust)": {}, - "Erl\u00f6se aus Verk\u00e4ufen Finanzanlagen 100% / 50% steuerfrei (inlandische Kap.Ges.)(bei Buchverlust)": {}, - "Erl\u00f6se aus Verk\u00e4ufen Sachanlageverm\u00f6gen (bei Buchverlust)": {}, - "Erl\u00f6se aus Verk\u00e4ufen Sachanlageverm\u00f6gen 16% USt (bei Buchverlust)": {}, - "Erl\u00f6se aus Verk\u00e4ufen Sachanlageverm\u00f6gen 19% USt (bei Buchverlust)": {}, - "Erl\u00f6se aus Verk\u00e4ufen Sachanlageverm\u00f6gen steuerfrei \u00a7 4 Nr. 1a UStG (bei Buchverlust)": {}, - "Erl\u00f6se aus Verk\u00e4ufen Sachanlageverm\u00f6gen steuerfrei \u00a7 4 Nr. 1b UStG (bei Buchverlust)": {}, - "Erl\u00f6se aus Verk\u00e4ufen immaterieller Verm\u00f6gensgegenst\u00e4nde (bei Buchverlust)": {}, - "Fahrten zwischen Wohnung und Arbeitsst\u00e4tte (Haben)": {}, - "Fahrten zwischen Wohnung und Arbeitsst\u00e4tte (abziehbarer Anteil)": {}, - "Fahrten zwischen Wohnung und Arbeitsst\u00e4tte (nicht abziehbarer Anteil)": {}, - "Fahrzeugkosten": {}, - "Forderungsverluste (\u00fcbliche H\u00f6he)": {}, - "Forderungsverluste 15% USt (\u00fcbliche H\u00f6he)": {}, - "Forderungsverluste 16% USt (\u00fcbliche H\u00f6he)": {}, - "Forderungsverluste 19% USt (\u00fcbliche H\u00f6he)": {}, - "Forderungsverluste 7 % USt (\u00fcbliche H\u00f6he)": {}, - "Forderungsverluste aus im Inland steuerpflichtigen EG-Lieferungen 15% USt (\u00fcbliche H\u00f6he)": {}, - "Forderungsverluste aus im Inland steuerpflichtigen EG-Lieferungen 16% USt (\u00fcbliche H\u00f6he)": {}, - "Forderungsverluste aus im Inland steuerpflichtigen EG-Lieferungen 19% USt (\u00fcbliche H\u00f6he)": {}, - "Forderungsverluste aus im Inland steuerpflichtigen EG-Lieferungen 7% USt (\u00fcbliche H\u00f6he)": {}, - "Forderungsverluste aus steuerfreien EG-Lieferungen (\u00fcbliche H\u00f6he)": {}, - "Fortbildungskosten": {}, - "Freiwillige Sozialleistungen": {}, - "Fremdarbeiten (Vertrieb)": {}, - "Fremdfahrzeugkosten": {}, - "Fremdleistungen / Fremdarbeiten": {}, - "Garagenmiete": {}, - "Gas- Strom- Wasser": {}, - "Geschenke abzugsf\u00e4hig": {}, - "Geschenke ausschlie\u00dflich betrieblich genutzt": {}, - "Geschenke nicht abzugsf\u00e4hig": {}, - "Gewerbesteuerlich zu ber\u00fccksichtigende Miete f\u00fcr Einrichtungen \u00a7 8 GewStG": {}, - "Gewerbesteuerlich zu ber\u00fccksichtigende Miete \u00a7 8 GewStG": {}, - "Gewerbesteuerlich zu ber\u00fccksichtigende Pacht \u00a7 8 GewStG": {}, - "Gewerbesteuerlich zu ber\u00fccksichtigendes Mietleasing \u00a7 8 GewStG": {}, - "Grundst\u00fcckaufwendungen- betrieblich": {}, - "Grundst\u00fcckaufwendungen- sonstige neutrale": {}, - "Haftungsverg\u00fctung an Mitunternehmer \u00a7 15 EStG": {}, - "Heizung": {}, - "Instandhaltung betrieblicher R\u00e4ume": {}, - "Kfz-Kosten f\u00fcr betrieblich genutzte zum Privatverm\u00f6gen geh\u00f6rende Kraftfahrzeuge": {}, - "Kfz-Versicherungen": {}, - "Kilometergelderstattung Arbeitnehmer": {}, - "Kosten der Warenabgabe": {}, - "Laufende Kfz-Betriebskosten": {}, - "Leasingfahrzeugkosten": {}, - "Mautgeb\u00fchren": {}, - "Mietekosten": {}, - "Mieten f\u00fcr Einrichtungen": {}, - "Mietleasing": {}, - "Nebenkosten des Geldverkehrs": {}, - "Netto-Pr\u00e4mie f\u00fcr R\u00fcckdeckung k\u00fcnftiger Versorgungsleistungen": {}, - "Nicht Abzugsf\u00e4hige Betriebsausgaben aus Werbe- und Repr\u00e4sentationskosten (nicht abziehbarer Anteil)": {}, - "Nicht Abzugsf\u00e4hige Bewirtungskosten": {}, - "Nicht abziehbare H\u00e4lfte der Aufsichtsratsverg\u00fctungen": {}, - "Nicht abziehbare Vorsteuer": {}, - "Nicht abziehbare Vorsteuer 16% ": {}, - "Nicht abziehbare Vorsteuer 19% ": {}, - "Nicht abziehbare Vorsteuer 7% ": {}, - "Pacht": {}, - "Periodenfremde Aufwendungen soweit nicht au\u00dferordentlich": {}, - "Porto": {}, - "Raumkosten": {}, - "Rechts- und Beratungskosten": {}, - "Reinigung": {}, - "Reisekosten Arbeitnehmer": {}, - "Reisekosten Arbeitnehmer (nicht abziehbarer Anteil)": {}, - "Reisekosten Arbeitnehmer Fahrkosten": {}, - "Reisekosten Arbeitnehmer Verpflegungsmehraufwand": {}, - "Reisekosten Arbeitnehmer \u00fcbernachtungsaufwand": {}, - "Reisekosten Unternehmer": {}, - "Reisekosten Unternehmer (nicht abziehbarer anteil)": {}, - "Reisekosten Unternehmer Fahrkosten": {}, - "Reisekosten Unternehmer Verpflegungsmehraufwand": {}, - "Reisekosten Unternehmer \u00fcbernachtungsaufwand": {}, - "Reparaturen und Instandhaltung von Bauten": {}, - "Reparaturen und Instandhaltung von Betriebs- und Gesch\u00e4ftsausstattung": {}, - "Reparaturen und Instandhaltung von anderen Anlagen": {}, - "Reparaturen und Instandhaltung von technischen Anlagen und Maschinen": {}, - "Repr\u00e4sentationskosten": {}, - "Sonstige Abgaben": {}, - "Sonstige Aufwendungen betrieblich und Regelm\u00e4\u00dfig 1": {}, - "Sonstige Aufwendungen betrieblich und regelm\u00e4\u00dfig": {}, - "Sonstige Aufwendungen unregelm\u00e4\u00dfig": {}, - "Sonstige Kfz-kosten": {}, - "Sonstige Raumkosten": {}, - "Sonstige Reparaturen und Instandhaltung ": {}, - "Sonstige betriebliche Aufwendungen 5": {}, - "Sonstige eingeschr\u00e4nkt abziehbare Betriebsausgaben (abziehbarer Anteil)": {}, - "Sonstige eingeschr\u00e4nkt abziehbare Betriebsausgaben (nicht abziehbarer Anteil)": {}, - "Sonstiger Betriebsbedarf": {}, - "Steuerlich abzugsf\u00e4hige Versp\u00e4tungszuschl\u00e4ge und Zwangsgelder": {}, - "Telefax und Internetkosten": {}, - "Telefon": {}, - "Transportversicherungen": {}, - "Verg\u00fctungen an Mitunternehmer f\u00fcr die Pachtweise \u00fcberlassung ihrer Wirtschaftsg\u00fcter \u00a7 15 EStG": {}, - "Verg\u00fctungen an Mitunternehmer f\u00fcr die mietweise \u00fcberlassung ihrer Wirtschaftsg\u00fcter \u00a7 15 EStG": {}, - "Verg\u00fctungen an Mitunternehmer \u00a7 15 EStG": {}, - "Verkaufsprovisionen": {}, - "Verluste aus dem Abgang von Gegenst\u00e4nden des Anlageverm\u00f6gens": {}, - "Verluste aus dem Abgang von Gegenst\u00e4nden des Umlaufverm\u00f6gens (au\u00dfer Vorr\u00e4te) 100%/50% nicht anzugsf\u00e4hig": {}, - "Verluste aus dem Abgang von Gegenst\u00e4nden des Umlaufverm\u00f6gens au\u00dfer Vorr\u00e4te": {}, - "Verluste aus der Ver\u00e4u\u00dferung von Anteilen an Kapitalgesellschaften 100% / 50% nicht abzugsf\u00e4hig": {}, - "Verpackungsmaterial": {}, - "Versicherungen": {}, - "Versicherungen f\u00fcr Geb\u00e4ude": {}, - "Vorwegnahme k\u00fcnftiger Wertschwankungen im Umlaufverm\u00f6gen au\u00dfer Vorr\u00e4te und Wertpapiere": {}, - "Wartungskosten f\u00fcr Hard- und Software": {}, - "Werbekosten": {}, - "Werkzeuge und Kleinger\u00e4te": {}, - "Zeitschriften und B\u00fccher": {}, - "Zuwendungen- Spenden an Stiftungen f\u00fcr Kirchliche- religi\u00f6se und gemeinn\u00fctzige Zwecke": {}, - "Zuwendungen- Spenden an Stiftungen f\u00fcr gemeinn\u00fctzige Zwecke i. S. d. \u00a7 52 Abs. 2 Nr. 1-3 AO": {}, - "Zuwendungen- Spenden an Stiftungen f\u00fcr gemeinn\u00fctzige Zwecke i. S. d. \u00a7 52 Abs. 2 Nr. 4 AO": {}, - "Zuwendungen- Spenden an Stiftungen f\u00fcr wissenschaftliche- mitdt\u00e4tige- kulturelle Zwecke": {}, - "Zuwendungen- Spenden an politische Parteien": {}, - "Zuwendungen- Spenden f\u00fcr kirchliche- religi\u00f6se und gemeinn\u00fctzige Zwecke": {}, - "Zuwendungen- Spenden f\u00fcr mildt\u00e4tige Zwecke": {}, - "Zuwendungen- Spenden f\u00fcr wissenschaftliche und kulturelle Zwecke": {}, - "Zuwendungen- Spenden- steuerlich nicht abziehbar": {}, - "kfz-Reparaturen": {}, - "steuerlich nicht abzugsf\u00e4hige Versp\u00e4tungszuschl\u00e4ge und Zwangsgelder": {} - } - } - }, - "Weitere Aufwendungen": { - "Abschreibungen auf Finanzanlagen und auf Wertpapiere des Umlaufverm\u00f6gens": { - "Abschreibungen auf Finanzanlagen und auf Wertpapiere des Umlaufverm\u00f6gens 1": { - "Abschreibungen auf Finanzanlagen ": { - "account_type": "Depreciation" - }, - "Abschreibungen auf Finanzanlagen 100% / 50% nicht abzugsf\u00e4hig (inl\u00e4ndische Kap. Ges.)": {}, - "Abschreibungen auf Finanzanlagen auf Grund steuerlicher Sondervorschriften": {}, - "Abschreibungen auf Finanzanlagen auf Grund steuerlicher Sondervorschriften 100% / 50% nicht abzugsf\u00e4hig": {}, - "Abschreibungen auf Grund von Verlustanteilen an Mitunternehmerschaften \u00a7 8 GewStG": {}, - "Abschreibungen auf Wertpapiere des Umlaufverm\u00f6gens": {}, - "Abschreibungen auf Wertpapiere des Umlaufverm\u00f6gens 100% / 50% nicht abzugsf\u00e4hig": {}, - "Vorwegnahme k\u00fcnftiger Wertschwankungen bei Wertpapieren des Umlaufverm\u00f6gens": {} - }, - "account_type": "Depreciation" - }, - "Au\u00dferordentliche Aufwendungen": { - "Au\u00dferordentliche Aufwendungen 1": { - "Au\u00dferordentliche Aufwendungen 2": {}, - "Au\u00dferordentliche Aufwendungen finanzwirksam": {}, - "Au\u00dferordentliche Aufwendungen nicht finanzwirksam": {} - } - }, - "Einstellung in Gewinnr\u00fccklagen ": { - "Aussch\u00fcttung": { - "Vorabaussch\u00fcttung": {} - }, - "Einstellung in Gewinnr\u00fccklagen in andere Gewinnr\u00fccklagen ": { - "Einstellung in andere Gewinnr\u00fccklagen ": {} - }, - "Einstellung in Gewinnr\u00fccklagen in die R\u00fccklage f\u00fcr eigene Anteile": { - "Einstellung in die R\u00fccklage f\u00fcr eigene Anteile": {} - }, - "Einstellung in Gewinnr\u00fccklagen in die gesetzliche R\u00fccklage ": { - "Einstellung in die gesetzliche R\u00fccklage ": {} - }, - "Einstellung in Gewinnr\u00fccklagen in satzungm\u00e4\u00dfige R\u00fccklage ": { - "Einstellung in satzungm\u00e4\u00dfige R\u00fccklage ": {} - }, - "Sonstige betriebliche Aufwendungen": { - "(zu freien Verf\u00fcgung)": {} - }, - "Sonstige betriebliche Ertr\u00e4ge oder sonstige betriebliche Aufwendungen": { - "Aufwendungen/Ertr\u00e4ge aus Umrechnungsdifferenzen": {} - }, - "Vortrag auf neue Rechnung 1": { - "Vortrag auf neue Rechnung (GuV)": {} - } - }, - "Steuern vom Einkommen und Ertrag": { - "Steuern vom Einkommen und Ertrag 1": { - "Anrechenbarer Solidarit\u00e4tszuschlag auf Kapitalertragsteuer 20%": {}, - "Anrechenbarer Solidarit\u00e4tszuschlag auf Kapitalertragsteuer 25%": {}, - "Anrechenbarer Solidarit\u00e4tszuschlag auf Zinsabschlagsteuer": {}, - "Anzurechnende ausl\u00e4ndische Quellensteuer": {}, - "Ertr\u00e4ge aus der Aufl\u00f6sung von R\u00fcckstellungen f\u00fcr Steuern vom Einkommen und Ertrag": {}, - "Gewerbesteuer ": {}, - "Kapitalertragsteuer 20%": {}, - "Kapitalertragsteuer 25%": {}, - "K\u00f6rperschaftssteuer": {}, - "K\u00f6rperschaftssteuer f\u00fcr Vorjahr": {}, - "K\u00f6rperschaftssteuererstattung f\u00fcr Vorjahre nach \u00a737 KStG": {}, - "K\u00f6rperschaftssteuererstattungen f\u00fcr Vorjahre": {}, - "Solidarit\u00e4tszuschlag": {}, - "Solidarit\u00e4tszuschlag f\u00fcr Vorjahre": {}, - "Solidarit\u00e4tszuschlagerstattungen f\u00fcr Vorjahre": {}, - "Steuererstattungen Vorjahre f\u00fcr Steuern vom Einkommen und Ertrag": {}, - "Steuernachzahlungen Vorjahre f\u00fcr Steuern vom Einkommen und Ertrag": {}, - "Zinsabschlagsteuer": {} - } - }, - "Verlustvortrag": { - "Verlustvortrag nach Verwendung": {} - }, - "Zinsen und \u00e4hnliche Aufwendungen": { - "Zinsen und \u00e4hnliche Aufwendungen 1": { - "Diskontaufwendungen": {}, - "Diskontaufwendungen an verbundene Unternehmen": {}, - "In Dauerschuldzinsen unqualifizierte Zinsen auf kurzfristige Verbindlichkeiten": {}, - "Nicht abzugsf\u00e4hige Schuldzinsen gem\u00e4\u00df \u00a7 4 Abs. 4a EStG (Hinzurechnungsbetrag)": {}, - "Renten und dauernde Lasten aus Gr\u00fcndung/Erwerb \u00a78 GewStG": {}, - "Steuerlich abzugsf\u00e4hige- andere Nebenleistungen zu steuern ": {}, - "Steuerlich nicht abzugsf\u00e4hige- andere Nebenleistungen zu steuern ": {}, - "Zinsaufwendungen an Mitunternehmer f\u00fcr die Hingabe von Kapital \u00a7 15 EStG": {}, - "Zinsaufwendungen f\u00fcr Geb\u00e4ude- die zum Betriebsverm\u00f6gen geh\u00f6ren": {}, - "Zinsaufwendungen f\u00fcr kurzfristige Verbindlichkeiten": {}, - "Zinsaufwendungen f\u00fcr kurzfristige Verbindlichkeiten an verbundene Unternehmen": {}, - "Zinsaufwendungen f\u00fcr langfristige Verbindlichkeiten": {}, - "Zinsaufwendungen f\u00fcr langfristige Verbindlichkeiten an verbundene Unternehmen": {}, - "Zinsaufwendungen \u00a7\u00a7 233a AO betriebliche Steuern": {}, - "Zinsaufwendungen \u00a7\u00a7 233a bis 237 AO Personensteuern": {}, - "Zinsen und \u00e4hnliche Aufwendungen 100% / 50% nicht abzugsf\u00e4hig (inl\u00e4ndische Kap. Ges.)": {}, - "Zinsen und \u00e4hnliche Aufwendungen 2": {}, - "Zinsen und \u00e4hnliche Aufwendungen an verbundene Unternehmen": {}, - "Zinsen und \u00e4hnliche Aufwendungen an verbundene Unternehmen 100% / 50% nicht abzugsf\u00e4hig (inl\u00e4ndische Kap. Ges.)": {}, - "Zinsen zur Finanzierung des Anlageverm\u00f6gens": {}, - "Zins\u00e4hnliche Aufwendungen": {}, - "Zins\u00e4hnliche Aufwendungen an verbundene Unternehmen": {} - } - } - }, - "root_type": "Expense" - }, - "Gewinn u. Verlust - Ertr\u00e4ge": { - "Betriebliche Ertr\u00e4ge": { - "Andere aktivierte Eigenleistungen": { - "Andere aktivierte Eigenleistungen 1": { - "Andere aktivierte Eigenleistungen 2": {} - } - }, - "Erh\u00f6hung oder Verminderung des Bestands an fertigen und unfertige Erzeugnissen": { - "Erh\u00f6hung / Verminderung des Bestands an fertigen und unfertigen Erzeugnissen": { - "Bestandsver\u00e4nderungen - fertige Erzeugnisse": {}, - "Bestandsver\u00e4nderungen - unfertige Erzeugnisse": {}, - "Bestandsver\u00e4nderungen - unfertige Leistungen": {} - }, - "Erh\u00f6hung / Verminderung des Bestands in Arbeit befindlicher Auftr\u00e4ge": { - "Bestandsver\u00e4nderungen in Arbeit befindlicher Auftr\u00e4ge": {} - }, - "Erh\u00f6hung / Verminderung des Bestands in Ausf\u00fchrung befindlicher Bauaftr\u00e4ge": { - "Bestandsver\u00e4nderungen in Ausf\u00fchrung befindliche Bauauftr\u00e4ge": {} - } - }, - "Sonstige betriebliche Ertr\u00e4ge 1": { - "Sonstige betriebliche Ertr\u00e4ge 2": { - "Anlagenabg\u00e4nge Finanzanlagen (Restbuchwert bei Buchgewinn)": {}, - "Anlagenabg\u00e4nge Finanzanlagen 100% / 50% steuerfrei (inl\u00e4ndische Kap. Ges.)(Restbuchwert bei Buchgewinn)": {}, - "Anlagenabg\u00e4nge Sachanlagen (Restbuchwert bei Buchgewinn)": {}, - "Anlagenabg\u00e4nge immaterielle Verm\u00f6gensgegenst\u00e4nde (Restbuchwert bei Buchgewinn)": {}, - "Bank Bewertungsertrag": {}, - "Bank Waehrungsverlust (Konto)": {}, - "Erl\u00f6se aus Verkauf immaterieller Verm\u00f6gensgegenst\u00e4nde (bei Buchgewinn)": {}, - "Erl\u00f6se aus Verk\u00e4ufen Finanzanlagen (bei Buchgewinn)": {}, - "Erl\u00f6se aus Verk\u00e4ufen Sachanlageverm\u00f6gen (bei Buchgewinn)": {}, - "Erl\u00f6se aus Verk\u00e4ufen Sachanlageverm\u00f6gen 16% USt (bei Buchgewinn)": {}, - "Erl\u00f6se aus Verk\u00e4ufen Sachanlageverm\u00f6gen 19% USt (bei Buchgewinn)": {}, - "Erl\u00f6se aus Verk\u00e4ufen Sachanlageverm\u00f6gen steuerfrei \u00a7 4 Nr. 1a UStG (bei Buchgewinn)": {}, - "Erl\u00f6se aus Verk\u00e4ufen Sachanlageverm\u00f6gen steuerfrei \u00a7 4 Nr. 1b UStG (bei Buchgewinn)": {}, - "Ertraege a. Waehrungsumstellung auf Euro": {}, - "Ertr\u00e4ge aus Bewertung Finanzmittelfonds": {}, - "Ertr\u00e4ge aus Kursdifferenzen": {}, - "Ertr\u00e4ge aus Zuschreibungen des Finanzanlageverm\u00f6gens": {}, - "Ertr\u00e4ge aus Zuschreibungen des Finanzanlageverm\u00f6gens 100% / 50% steuerfrei (inl\u00e4ndische Kap. Ges.)": {}, - "Ertr\u00e4ge aus Zuschreibungen des Sachanlageverm\u00f6gens": {}, - "Ertr\u00e4ge aus Zuschreibungen des Umlaufverm\u00f6gens 100% / 50% steuerfrei (inlandische Kap. Ges.)": {}, - "Ertr\u00e4ge aus Zuschreibungen des Umlaufverm\u00f6gens au\u00dfer Vorr\u00e4ten": {}, - "Ertr\u00e4ge aus Zuschreibungen des anderen Anlageverm\u00f6gens 100% / 50% steuerfrei (inl\u00e4ndische Kap. Ges.)": {}, - "Ertr\u00e4ge aus Zuschreibungen des immateriellen Anlageverm\u00f6gens": {}, - "Ertr\u00e4ge aus abgeschriebenen Forderungen": {}, - "Ertr\u00e4ge aus dem Abgang von Gegenst\u00e4nden des Anlageverm\u00f6gens": {}, - "Ertr\u00e4ge aus dem abgang von Gegenst\u00e4nden des Umlaufverm\u00f6gens (au\u00dfer Vorr\u00e4te) 100% / 50%steuerfrei (inlandische Kap.Ges.)": {}, - "Ertr\u00e4ge aus dem abgang von Gegenst\u00e4nden des Umlaufverm\u00f6gens au\u00dfer Vorr\u00e4te": {}, - "Ertr\u00e4ge aus der Aufl\u00f6sung von R\u00fcckstellungen": {}, - "Ertr\u00e4ge aus der Aufl\u00f6sung von Sonderposten mit R\u00fccklageanteil (Ansparabschreibungen)": {}, - "Ertr\u00e4ge aus der Aufl\u00f6sung von Sonderposten mit R\u00fccklageanteil (Existenzgr\u00fcnderr\u00fccklage)": {}, - "Ertr\u00e4ge aus der Aufl\u00f6sung von Sonderposten mit R\u00fccklageanteil (Sonderabschreibungen)": {}, - "Ertr\u00e4ge aus der Aufl\u00f6sung von Sonderposten mit R\u00fccklageanteil (aus der W\u00e4hrungsumstellung auf den Euro)": {}, - "Ertr\u00e4ge aus der Aufl\u00f6sung von Sonderposten mit R\u00fccklageanteil (steuerfreie R\u00fccklage)": {}, - "Ertr\u00e4ge aus der Aufl\u00f6sung von Sonderposten mit R\u00fccklageanteil nach \u00a7 52 Abs. 16 EStG": {}, - "Ertr\u00e4ge aus der Herabsetzung der Einzelwertberichtigung zu Forderungen": {}, - "Ertr\u00e4ge aus der Herabsetzung der Pauschalwertberichtigung zu Forderungen": {}, - "Ertr\u00e4ge aus der Ver\u00e4u\u00dferung vo Anteilen an Kapitalgesellschaften 100% / 50% steuerfrei (inlandische Kap. Ges.)": {}, - "Ertr\u00e4ge aus der steuerlich niedrigeren Bewertung von R\u00fcckstellungen": {}, - "Ertr\u00e4ge aus der steuerlich niedrigeren Bewertung von Verbindlichkeiten": {}, - "Grundst\u00fccksertr\u00e4ge": {}, - "Investitionszulagen (steuerfrei)": {}, - "Investitionszusch\u00fcsse (steuerpflichtig)": {}, - "Kassendifferenzen": {}, - "Nicht realisierbare Waehrungsdifferenzen": {}, - "Periodenfremde Ertr\u00e4ge (soweit nicht au\u00dferordentlich)": {}, - "Produkt Rechnung Preisdifferenz": {}, - "Realisierte Waehrungsdifferenzen": {}, - "Rundungsdifferenzen": {}, - "Sachbez\u00fcge 16% USt (Waren)": {}, - "Sachbez\u00fcge 19% USt (Waren)": {}, - "Sachbez\u00fcge 7% USt (Waren)": {}, - "Sonstige Ertr\u00e4ge betrieblich und regelm\u00e4\u00dfig ": {}, - "Sonstige Ertr\u00e4ge betrieblich und regelm\u00e4\u00dfig 16% USt": {}, - "Sonstige Ertr\u00e4ge betrieblich und regelm\u00e4\u00dfig 19% USt ": {}, - "Sonstige Ertr\u00e4ge betriebsfremd und regelm\u00e4\u00dfig": {}, - "Sonstige Ertr\u00e4ge unregelm\u00dfig": {}, - "Sonstige betriebliche Ertr\u00e4ge 3": {}, - "Sonstige steuerfreie Betriebseinnahmen": {}, - "Verrechnete sonstige Sachbez\u00fcge ": {}, - "Verrechnete sonstige Sachbez\u00fcge (keine Waren)": {}, - "Verrechnete sonstige Sachbez\u00fcge 16 % USt ( z.B. Kfz-Gestellung)": {}, - "Verrechnete sonstige Sachbez\u00fcge 19 % USt ( z.B. Kfz-Gestellung)": {}, - "Verrechnete sonstige Sachbez\u00fcge ohne Umsatzsteuer": {}, - "Versicherungsentsch\u00e4digungen": {}, - "Waehrungsdifferenz zum Kontenausgleich": {}, - "steuerfreie Ertr\u00e4ge aus der Aufl\u00f6sung von Sonderposten mit R\u00fccklageanteil": {} - } - }, - "Statistische Konten E\u00fcR": { - "Sonstige betriebliche Ertr\u00e4ge": { - "Unentgeltliche Erbringung einer sonstigen Leistung 7% USt": {}, - "Unentgeltliche Erbringung einer sostigen Leistung 16% USt": {}, - "Unentgeltliche Erbringung einer sostigen Leistung 19% USt": {}, - "Unentgeltliche Erbringung einer sostigen Leistung ohne USt": {}, - "Unentgeltliche Zuwendung von Gegenst\u00e4nden 16% USt": {}, - "Unentgeltliche Zuwendung von Gegenst\u00e4nden 19% USt": {}, - "Unentgeltliche Zuwendung von Gegenst\u00e4nden ohne USt": {}, - "Verwendung von Gegenst\u00e4nden f\u00fcr Zwecke au\u00dferhalb des Unternehmens 16% USt": {}, - "Verwendung von Gegenst\u00e4nden f\u00fcr Zwecke au\u00dferhalb des Unternehmens 16% USt (Kfz-Nutzung)": {}, - "Verwendung von Gegenst\u00e4nden f\u00fcr Zwecke au\u00dferhalb des Unternehmens 16% USt (Telefon-Nutzung)": {}, - "Verwendung von Gegenst\u00e4nden f\u00fcr Zwecke au\u00dferhalb des Unternehmens 19% USt": {}, - "Verwendung von Gegenst\u00e4nden f\u00fcr Zwecke au\u00dferhalb des Unternehmens 19% USt (Kfz-Nutzung)": {}, - "Verwendung von Gegenst\u00e4nden f\u00fcr Zwecke au\u00dferhalb des Unternehmens 19% USt (Telefon-Nutzung)": {}, - "Verwendung von Gegenst\u00e4nden f\u00fcr Zwecke au\u00dferhalb des Unternehmens 7% USt": {}, - "Verwendung von Gegenst\u00e4nden f\u00fcr Zwecke au\u00dferhalb des Unternehmens ohne USt": {}, - "Verwendung von Gegenst\u00e4nden f\u00fcr Zwecke au\u00dferhalb des Unternehmens ohne USt (Kfz-Nutzung)": {}, - "Verwendung von Gegenst\u00e4nden f\u00fcr Zwecke au\u00dferhalb des Unternehmens ohne USt (Telefon-Nutzung)": {} - }, - "Umsatzerl\u00f6se": { - "Entnahme durch Unternehmer f\u00fcr Zwecke au\u00dferhalb des Unternehmens (Waren) ohne USt": {}, - "Entnahme durch den Unternehmer f\u00fcr Zwecke au\u00dferhalb des Unternehmens (Waren) 16% USt": {}, - "Entnahme durch den Unternehmer f\u00fcr Zwecke au\u00dferhalb des Unternehmens (Waren) 19% USt": {}, - "Entnahme durh Unternehmer f\u00fcr Zwecke au\u00dferhalb des Unternehmens (Waren) 7% USt": {}, - "Entnahme von Gegens\u00e4nden ohne USt": {}, - "Erl\u00f6sschm\u00e4lerung aus im Inland steuerpflichtigen EG-lieferungen 16% USt": {}, - "Erl\u00f6sschm\u00e4lerung aus im Inland steuerpflichtigen EG-lieferungen 19% USt": {}, - "Erl\u00f6sschm\u00e4lerung aus im Inland steuerpflichtigen EG-lieferungen 7 % USt": {}, - "Erl\u00f6sschm\u00e4lerung aus im anderen EG-lieferungen steuerpflichtigen Lieferungen": {}, - "Erl\u00f6sschm\u00e4lerungen": {}, - "Erl\u00f6sschm\u00e4lerungen 16 % USt": {}, - "Erl\u00f6sschm\u00e4lerungen 19 % USt": {}, - "Erl\u00f6sschm\u00e4lerungen 7 % USt": {}, - "Erl\u00f6sschm\u00e4lerungen aus steuerfreien Ums\u00e4tzen \u00a7 4 Nr. 1a UStG": {}, - "Erl\u00f6sschm\u00e4lerungen aus steuerfreien innergemeinschaftlichen Lieferungen": {}, - "Gegenkonto 4580-4582 bei Aufteilung der Erl\u00f6se nach Steuers\u00e4tzen (E\u00fcR)": {}, - "Gew\u00e4hrte Boni ": {}, - "Gew\u00e4hrte Boni 16 % USt": {}, - "Gew\u00e4hrte Boni 19 % USt": {}, - "Gew\u00e4hrte Boni 7 % USt": {}, - "Gew\u00e4hrte Rabatte": {}, - "Gew\u00e4hrte Rabatte 16 % USt": {}, - "Gew\u00e4hrte Rabatte 19 % USt": {}, - "Gew\u00e4hrte Rabatte 7 % USt": {}, - "Gew\u00e4hrte Skonti": {}, - "Gew\u00e4hrte Skonti 16 % USt": {}, - "Gew\u00e4hrte Skonti 19 % USt": {}, - "Gew\u00e4hrte Skonti 7 % USt": {}, - "Gew\u00e4hrte Skonti aus Leistungen- f\u00fcr die der Leistungsempf\u00e4nger die umsatzsteuer nach \u00a7 13b UStG schuldet": {}, - "Gew\u00e4hrte Skonti aus im Inland steuerpflichtigen EG-Lieferungen": {}, - "Gew\u00e4hrte Skonti aus im Inland steuerpflichtigen EG-Lieferungen 16 % USt": {}, - "Gew\u00e4hrte Skonti aus im Inland steuerpflichtigen EG-Lieferungen 19 % USt": {}, - "Gew\u00e4hrte Skonti aus im Inland steuerpflichtigen EG-Lieferungen 7 % USt": {}, - "Gew\u00e4hrte Skonti aus steuerfreien innergemeinschaftlichen Lieferungen \u00a7 4 Nr. 1b UStG": {}, - "Nicht steuerbare ums\u00e4tze (Innenums\u00e4tze)": {}, - "Statistisches Konto Erl\u00f6se zum allgemeinen Umsatzsteuersatz (E\u00fcR)": {}, - "Statistisches Konto Erl\u00f6se zum erm\u00e4\u00dfigten Umsatzsteuersatz (E\u00fcR)": {}, - "Statistisches konto Erl\u00f6se steuerfrei und nicht steuerbar (E\u00fcR)": {}, - "Umsatzsteuerverg\u00fctung": {}, - "Unentgeltliche Wertabgaben 3": {}, - "Unentgeltliche Zuwendung von Waren 16% USt": {}, - "Unentgeltliche Zuwendung von Waren 19% USt": {}, - "Unentgeltliche Zuwendung von Waren 7% USt": {}, - "Unentgeltliche Zuwendung von Waren ohne USt": {} - } - }, - "Umsatzerl\u00f6se 1": { - "Sotige betriebliche Ertr\u00e4ge": { - "Provision- sonstige Ertr\u00e4ge": {}, - "Provision- sonstige Ertr\u00e4ge 16% USt": {}, - "Provision- sonstige Ertr\u00e4ge 19% USt": {}, - "Provision- sonstige Ertr\u00e4ge 7% USt": {}, - "Provision- sonstige Ertr\u00e4ge steuerfrei (\u00a7 4 Nr. 5 UStG)": {}, - "Provision- sonstige Ertr\u00e4ge steuerfrei (\u00a7 4 Nr. 8 ff. UStG)": {} - }, - "Umsatzerl\u00f6se 2": { - "* Konto Kasse Ertrag": {}, - "* Sonstige Einnahmen": {}, - "* Vorausberechnete Einnahmen": {}, - "Erl\u00f6se": {}, - "Erl\u00f6se 16% USt": {}, - "Erl\u00f6se 19% USt": {}, - "Erl\u00f6se 7% USt": {}, - "Erl\u00f6se Abfallverwertung": {}, - "Erl\u00f6se Leergut": {}, - "Erl\u00f6se als Kleinunternehmer i.S.d. \u00a7 19 Abs. 1 UStG": {}, - "Erl\u00f6se aus Geldspielautomaten 16% USt": {}, - "Erl\u00f6se aus Geldspielautomaten 19% USt": {}, - "Erl\u00f6se aus Leistungen- f\u00fcr die der Leistungsempf\u00e4nger die Umsatzsteuer nach \u00a7 13b UStG schuldet": {}, - "Erl\u00f6se aus im Drittland steuerbaren Leistungen- im Inland ncht steuerbare Ums\u00e4tze": {}, - "Erl\u00f6se aus im Inland steuerpflichtigen EG-Lieferungen 16% USt": {}, - "Erl\u00f6se aus im Inland steuerpflichtigen EG-Lieferungen 19% USt": {}, - "Erl\u00f6se aus im Inland steuerpflichtigen EG-Lieferungen 7% USt": {}, - "Erl\u00f6se aus im anderen EG-Land steuerbaren Leistungen- im Inland nicht steuerbare Ums\u00e4tze": {}, - "Erl\u00f6se aus im anderen EG-Land steuerpflichtigen Lieferungen": {}, - "Erl\u00f6se. Die mit den Durchschnittss\u00e4tzen des \u00a7 24 UStG versteuert werden": {}, - "Lieferungen des ersten Abnehmers bei innergemeinschaftlichen Dreiecksgesch\u00e4ften \u00a7 25b abs. UStG": {}, - "Nicht abgerechnete Einnahmen": {}, - "Provisionsums\u00e4tze": {}, - "Provisionsums\u00e4tze 16% USt": {}, - "Provisionsums\u00e4tze 19% USt": {}, - "Provisionsums\u00e4tze 7% USt": {}, - "Provisionsums\u00e4tze- steuerfrei (\u00a74 Nr. 5 UStG)": {}, - "Provisionsums\u00e4tze- steuerfrei (\u00a74 Nr. 8 ff. UStG)": {}, - "Sonstige steuerfreie Ums\u00e4tze (z.B. \u00a7 4 Nr. 2-7 UStG)": {}, - "Sonstige steuerfreie Ums\u00e4tze Inland": {}, - "Steuerfreie Ums\u00e4tze nach \u00a7 4 Nr. 12 UStG (Vermietung und Verpackung)": {}, - "Steuerfreie Ums\u00e4tze offshore etc.": {}, - "Steuerfreie Ums\u00e4tze ohne Vorsteuerabzug zum Gesamtumsatz geh\u00f6rend": {}, - "Steuerfreie Ums\u00e4tze \u00a74 Nr. 1a UStG": {}, - "Steuerfreie Ums\u00e4tze \u00a74 Nr. 8 ff. UStG": {}, - "Steuerfreie innergemeinschaftliche Lieferungen von Neufahrzeugen an Abnehmer ohne Umsatzsteuer-Identifikationsnummer": {}, - "Steuerfreie innergemeinschaftliche Lieferungen \u00a74 Nr. 1b UStG": {}, - "Umsatzerl\u00f6se (zur fr. Verf\u00fcgung)": {} - } - } - }, - "Weitere Ertr\u00e4ge": { - "Au\u00dferordentliche Ertr\u00e4ge": { - "Au\u00dferordentliche Ertr\u00e4ge 1": { - "Au\u00dferordentliche Ertr\u00e4ge 2": {}, - "Au\u00dferordentliche Ertr\u00e4ge finanzwirksam": {}, - "Au\u00dferordentliche Ertr\u00e4ge nicht finanzwirksam": {} - } - }, - "Entnahme aus Gewinnr\u00fccklagen": { - "Einstellungen in die Kapitalr\u00fccklage nach den Vorschriften \u00fcber die Vereinfachte Kapitalherabsetzung": { - "Einstellungen in die Kapitalr\u00fccklage nach den Vorschriften \u00fcber die Vereinfachte Kapitalherabsetzung 1": {} - }, - "Entnahme aus Gewinnr\u00fccklagen aus anderen Gewinnr\u00fccklagen": { - "Entnahme aus Gewinnr\u00fccklagen aus anderen Gewinnr\u00fccklagen 1": {} - }, - "Entnahme aus Gewinnr\u00fccklagen aus der R\u00fccklage f\u00fcr eigene Anteile ": { - "Entnahme aus Gewinnr\u00fccklagen aus der R\u00fccklage f\u00fcr eigene Anteile 1": {} - }, - "Entnahme aus Gewinnr\u00fccklagen aus der gesetzlichen R\u00fccklage": { - "Entnahme aus Gewinnr\u00fccklagen aus der gesetzlichen R\u00fccklage 1": {} - }, - "Entnahme aus Gewinnr\u00fccklagen aus satzungsm\u00e4\u00dfigen R\u00fccklage ": { - "Entnahme aus Gewinnr\u00fccklagen aus satzungsm\u00e4\u00dfigen R\u00fccklage 1": {} - }, - "Ertr\u00e4ge aus Kapitalherabsetzung": { - "Ertr\u00e4ge aus Kapitalherabsetzung 1": {} - } - }, - "Entnahme aus der Kapitalr\u00fccklage": { - "Entnahme aus der Kapitalr\u00fccklage 1": {} - }, - "Ertr\u00e4ge aus Beteiligungen": { - "Ertr\u00e4ge aus Beteiligungen 1": { - "Ertr\u00e4ge aus Beteiligungen 2": {}, - "Ertr\u00e4ge aus Beteiligungen an verbundenen Unternehmen": {}, - "Gewinnanteile aus Mitunternehmerschaften \u00a7 9 GewStG": {}, - "Gewinne aus Anteilen an nicht steuerbefreiten inl\u00e4ndischen Kapitalgesellschaften \u00a7 9 Nr. 2a GewStG": {} - } - }, - "Ertr\u00e4ge aus anderen Wertpapieren und Ausleihungen des Finanzanlageverm\u00f6gens": { - "Ertr\u00e4ge aus anderen Wertpapieren und Ausleihungen des Finanzanlageverm\u00f6gens 1": {} - }, - "Gewinnvortrag": { - "Gewinnvortrag nach Verwendung": {} - }, - "Sonstige Steuern ": { - "Sonstige Steuern 1": { - "Ertr\u00e4ge aus der Aufl\u00f6sung von R\u00fcckstellungen f\u00fcr sonstige Steuern": {}, - "Grundsteuer": {}, - "Kfz-Steuer": {}, - "Sonstige Steuern 2": {}, - "Steuererstattungen Vorjahre f\u00fcr sonstige Steuern ": {}, - "Steuernachzahkungen Vorjahre f\u00fcr sonstige Steuern ": {}, - "Verbrauchsteuer": {}, - "\u00f6kosteuer": {} - } - }, - "Sonstige Zinsen und \u00e4hnliche Ertr\u00e4ge": { - "Sonstige Zinsen und \u00e4hnliche Ertr\u00e4ge 1": { - "Diskontertr\u00e4ge": {}, - "Diskontertr\u00e4ge aus verbundenen Unternehmen": {}, - "Laufende Ertr\u00e4ge aus Anteilen an Kapitalgesellschaften 100% / 50% steuerfrei": {}, - "Sonstige Zinsen und \u00e4hnliche Ertr\u00e4ge 2": {}, - "Sonstige Zinsen und \u00e4hnliche Ertr\u00e4ge aus verbundenen Unternehmen": {}, - "Sonstige Zinsertr\u00e4ge": {}, - "Sonstige Zinsertr\u00e4ge aus verbundenen Unternehmen": {}, - "Steuerfreie Aufzinsung des K\u00f6rperschaftsteuerguthabens nach \u00a737 KStG": {}, - "Zinsertr\u00e4ge \u00a7 233a AO": {}, - "Zinsertr\u00e4ge \u00a7 233a AO Sonderfall anlage A KSt": {}, - "Zins\u00e4hnliche Ertr\u00e4ge": {}, - "Zins\u00e4hnliche Ertr\u00e4ge aus verbundenen Unternehmen": {} - } - } - }, - "root_type": "Income" - }, - "Vortrags- Kapital- und Statistische Konten": { - "Aufgliederung der R\u00fcckstellungen": { - "Gegenkonto zu Konto 9260 - 9268": {}, - "Kurzfristige R\u00fcckstellungen": {}, - "Langfristige R\u00fcckstellungen- au\u00dfer Pensionen": {}, - "Mittelfristige R\u00fcckstellungen": {} - }, - "Ausgleichsposten f\u00fcr aktivierte eigene Anteile und Bilanzierungshilfen": { - "Ausgleichsposten f\u00fcr aktivierte Bilanzierungshilfen": {}, - "Ausgleichsposten f\u00fcr aktivierte eigene Anteile ": {} - }, - "Eigenkapitalersetzende Gesellschafterdarlehen ": { - "Eigenkapitalersetzende Gesellschafterdarlehen 1": {}, - "Gegenkonto zu 9250 und 9255": {}, - "Ungesicherte Gesellschafterdarlehen mit Restlaufzeit gr\u00f6\u00dfer 5 Jahre": {} - }, - "Einzahlungsverpflichtungen im Bereich der Forderungen": { - "Einzahlungsverpflichtungen Kommanditisten": {}, - "Einzahlungsverpflichtungen pers\u00f6nlich haftender Gesellschafter": {} - }, - "Kapital Personenhandelsgesellschaft Teilhafter": { - "Gesellschafter-Darlehen 1": {}, - "Verrechnungskonto f\u00fcr Einzahlungsverpflichtungen 1": {} - }, - "Kapital Personenhandelsgesellschaft Vollhafter": { - "Gesellschafter-Darlehen": {}, - "Verlust-/ Vortragskonto": {}, - "Verrechnungskonto f\u00fcr Einzahlungsverpflichtungen": {} - }, - "Nicht durch Verm\u00f6genseinlagen gedeckte Entnahmen": { - "Nicht durch Verm\u00f6genseinlagen gedeckte Entnahmen Kommanditisten": {}, - "Nicht durch Verm\u00f6genseinlagen gedeckte Entnahmen pers\u00f6nlich haftender Gesellschafter": {} - }, - "Passive Rechnungsabgrenzung": { - "Baukostenzusch\u00fcsse": {}, - "Forderungen aus Sachanlagenverk\u00e4ufen bei sonstigen Verm\u00f6gensgegenst\u00e4nden": {}, - "Forderungen aus Verk\u00e4ufen immaterielle Verm\u00f6gensgegenst\u00e4nde bei sonstigen Verm\u00f6gensgegenst\u00e4nden": {}, - "Forderungen aus Verk\u00e4ufen von Finanzanlagen bei sonstigen Verm\u00f6gensgegenst\u00e4nden": {}, - "Gegenkonto zu Konten 9230- 9238": {}, - "Gegenkonto zu Konto 9240-43": {}, - "Gegenkonto zu Konto 9245-47": {}, - "Investitionsverbindlichkeiten aus K\u00e4ufen von Finanzanlagen bei Leistungsverbindlichkeiten": {}, - "Investitionsverbindlichkeiten aus K\u00e4ufen von immateriellen Verm\u00f6gensgegenst\u00e4nden bei Leistungsverbindlichkeiten": {}, - "Investitionsverbindlichkeiten aus Sachanlagenk\u00e4ufen bei Leistungsverbindlichkeiten": {}, - "Investitionsverbindlichkeiten bei den Leistungsverbindlichkeiten": {}, - "Investitionszulagen ": {}, - "Investitionszusch\u00fcsse ": {} - }, - "Privat Teilhafter (f\u00fcr Verrechnung Gesellschafterdarlehen mit Eigenkapitalcharakter- Konto 9840-9849)": { - "Au\u00dfergew\u00f6hnliche Belastungen": {}, - "Grundst\u00fccksaufwand": {}, - "Grundst\u00fccksertrag": {}, - "Privateinlagen": {}, - "Privatentnahmen allgemein": {}, - "Privatsteuern": {}, - "Sonderausgaben beschr\u00e4nkt abzugsf\u00e4hig": {}, - "Sonderausgaben unbeschr\u00e4nkt abzugsf\u00e4hig": {}, - "Unentgeltliche Wertabgaben": {}, - "Zuwendungen- Spenden": {} - }, - "Statistische Konten f\u00fcr 4 Abs. 3 EStG": { - "Einlagen stiller Gesellschafter": { - "Einlagen stiller Gesellschafter 1": {} - }, - "Gegenkonto zu 9287 und 9288": {}, - "Gegenkonto zu 9290": {}, - "Gegenkonto zu 9292": {}, - "Mahngeb\u00fchren bei Buchungen \u00fcber Debitoren bei \u00a7 4 Abs. 3 EStG": {}, - "Statistisches Konto Fremdgeld": {}, - "Statistisches Konto steuerfreie Auslagen": {}, - "Steuerrechtlicher Ausgleichsposten": { - "Steuerrechtlicher Ausgleichsposten 1": {} - }, - "Zinsen bei Buchungen \u00fcber Debitoren bei \u00a7 4 Abs. 3 EStG": {} - }, - "Statistische Konten f\u00fcr Betriebswirtschaftliche Auswertungen (BWA)": { - "Anzahl Kreditkunden aufgelaufen": {}, - "Anzahl Kreditkunden monatlich": {}, - "Anzahl Rechnungen": {}, - "Anzahl der Barkunden": {}, - "Auftragsbestand": {}, - "Auftragseingang im Gesch\u00e4ftsjahr": {}, - "Besch\u00e4ftigte Personen 1": {}, - "Erweiterungsinvestitionen": {}, - "Gegenkonto f\u00fcr statistische Mengeneinheiten Konten 9101-9107 und Konten 9116-9118": {}, - "Gegenkonto zu Konten 9120- 9135-9140": {}, - "Gesch\u00e4ftsraum m2": {}, - "Unbezahlte Personen": {}, - "Verkaufskr\u00e4fte": {}, - "Verkaufsraum m2": {}, - "Verkaufstage": {} - }, - "Statistische Konten f\u00fcr Gewinnzuschlag": { - "Statistische Konten f\u00fcr den Gewinnzuschlag nach \u00a7\u00a7 6b- 6c und 7g EStG (Haben-Buchung)": {}, - "Statistische Konten f\u00fcr den Gewinnzuschlag- Gegenkonto zu 9890": {} - }, - "Statistische Konten f\u00fcr den Kennziffernteil der Bilanz": { - "Besch\u00e4ftigte Personen": {}, - "Gegenkonto zu 9200": {}, - "Gegenkonto zu 9210": {}, - "Produktive L\u00f6hne": {} - }, - "Statistische Konten f\u00fcr die Kapitalkontenentwicklung": { - "Anteil f\u00fcr Konto 9840-49 Teilhafter": {}, - "Anteil f\u00fcr Konto Teilhafter 0080 ": {}, - "Anteil f\u00fcr Konto Teilhafter 0081": {}, - "Anteil f\u00fcr Konto Teilhafter 0082": {}, - "Anteil f\u00fcr Konto Teilhafter 0083": {}, - "Anteil f\u00fcr Konto Teilhafter 0084": {}, - "Anteil f\u00fcr Konto Teilhafter 0085": {}, - "Anteil f\u00fcr Konto Teilhafter 0086": {}, - "Anteil f\u00fcr Konto Teilhafter 0087": {}, - "Anteil f\u00fcr Konto Teilhafter 0088": {}, - "Anteil f\u00fcr Konto Teilhafter 0089": {}, - "Anteil f\u00fcr Konto Teilhafter 2050": {}, - "Anteil f\u00fcr Konto Teilhafter 2051": {}, - "Anteil f\u00fcr Konto Teilhafter 2052": {}, - "Anteil f\u00fcr Konto Teilhafter 2053": {}, - "Anteil f\u00fcr Konto Teilhafter 2054": {}, - "Anteil f\u00fcr Konto Teilhafter 2055": {}, - "Anteil f\u00fcr Konto Teilhafter 2056": {}, - "Anteil f\u00fcr Konto Teilhafter 2057": {}, - "Anteil f\u00fcr Konto Teilhafter 2058": {}, - "Anteil f\u00fcr Konto Teilhafter 2059": {}, - "Anteil f\u00fcr Konto Teilhafter 2060": {}, - "Anteil f\u00fcr Konto Teilhafter 2061": {}, - "Anteil f\u00fcr Konto Teilhafter 2062": {}, - "Anteil f\u00fcr Konto Teilhafter 2063": {}, - "Anteil f\u00fcr Konto Teilhafter 2064": {}, - "Anteil f\u00fcr Konto Teilhafter 2065": {}, - "Anteil f\u00fcr Konto Teilhafter 2066": {}, - "Anteil f\u00fcr Konto Teilhafter 2067": {}, - "Anteil f\u00fcr Konto Teilhafter 2068": {}, - "Anteil f\u00fcr Konto Teilhafter 2069": {}, - "Anteil f\u00fcr Konto Teilhafter 2070 ": {}, - "Anteil f\u00fcr Konto Teilhafter 2071": {}, - "Anteil f\u00fcr Konto Teilhafter 2072": {}, - "Anteil f\u00fcr Konto Teilhafter 2073": {}, - "Anteil f\u00fcr Konto Teilhafter 2074": {}, - "Anteil f\u00fcr Konto Teilhafter 2075": {}, - "Anteil f\u00fcr Konto Teilhafter 2076": {}, - "Anteil f\u00fcr Konto Teilhafter 2077": {}, - "Anteil f\u00fcr Konto Teilhafter 2078": {}, - "Anteil f\u00fcr Konto Teilhafter 2079": {}, - "Anteil f\u00fcr Konto Vollhafter 0060": {}, - "Anteil f\u00fcr Konto Vollhafter 0061": {}, - "Anteil f\u00fcr Konto Vollhafter 0062": {}, - "Anteil f\u00fcr Konto Vollhafter 0063": {}, - "Anteil f\u00fcr Konto Vollhafter 0064": {}, - "Anteil f\u00fcr Konto Vollhafter 0065": {}, - "Anteil f\u00fcr Konto Vollhafter 0066": {}, - "Anteil f\u00fcr Konto Vollhafter 0067": {}, - "Anteil f\u00fcr Konto Vollhafter 0068": {}, - "Anteil f\u00fcr Konto Vollhafter 0069": {}, - "Anteil f\u00fcr Konto Vollhafter 2000": {}, - "Anteil f\u00fcr Konto Vollhafter 2001": {}, - "Anteil f\u00fcr Konto Vollhafter 2002": {}, - "Anteil f\u00fcr Konto Vollhafter 2003": {}, - "Anteil f\u00fcr Konto Vollhafter 2004": {}, - "Anteil f\u00fcr Konto Vollhafter 2005": {}, - "Anteil f\u00fcr Konto Vollhafter 2006": {}, - "Anteil f\u00fcr Konto Vollhafter 2007": {}, - "Anteil f\u00fcr Konto Vollhafter 2008": {}, - "Anteil f\u00fcr Konto Vollhafter 2009": {}, - "Anteil f\u00fcr Konto Vollhafter 2010": {}, - "Anteil f\u00fcr Konto Vollhafter 2011": {}, - "Anteil f\u00fcr Konto Vollhafter 2012": {}, - "Anteil f\u00fcr Konto Vollhafter 2013": {}, - "Anteil f\u00fcr Konto Vollhafter 2014": {}, - "Anteil f\u00fcr Konto Vollhafter 2015": {}, - "Anteil f\u00fcr Konto Vollhafter 2016": {}, - "Anteil f\u00fcr Konto Vollhafter 2017": {}, - "Anteil f\u00fcr Konto Vollhafter 2018": {}, - "Anteil f\u00fcr Konto Vollhafter 2019": {}, - "Anteil f\u00fcr Konto Vollhafter 2020": {}, - "Anteil f\u00fcr Konto Vollhafter 2021": {}, - "Anteil f\u00fcr Konto Vollhafter 2022": {}, - "Anteil f\u00fcr Konto Vollhafter 2023": {}, - "Anteil f\u00fcr Konto Vollhafter 2024": {}, - "Anteil f\u00fcr Konto Vollhafter 2025": {}, - "Anteil f\u00fcr Konto Vollhafter 2026": {}, - "Anteil f\u00fcr Konto Vollhafter 2027": {}, - "Anteil f\u00fcr Konto Vollhafter 2028": {}, - "Anteil f\u00fcr Konto Vollhafter 2029": {}, - "Anteil f\u00fcr Konto Vollhafter 9810": {}, - "Anteil f\u00fcr Konto Vollhafter 9811": {}, - "Anteil f\u00fcr Konto Vollhafter 9812": {}, - "Anteil f\u00fcr Konto Vollhafter 9813": {}, - "Anteil f\u00fcr Konto Vollhafter 9814": {}, - "Anteil f\u00fcr Konto Vollhafter 9815": {}, - "Anteil f\u00fcr Konto Vollhafter 9816": {}, - "Anteil f\u00fcr Konto Vollhafter 9817": {}, - "Anteil f\u00fcr Konto Vollhafter 9818": {}, - "Anteil f\u00fcr Konto Vollhafter 9819": {}, - "Anteil f\u00fcr Konto Vollhafter 9820 ": {}, - "Anteil f\u00fcr Konto Vollhafter 9821": {}, - "Anteil f\u00fcr Konto Vollhafter 9822": {}, - "Anteil f\u00fcr Konto Vollhafter 9823": {}, - "Anteil f\u00fcr Konto Vollhafter 9824": {}, - "Anteil f\u00fcr Konto Vollhafter 9825": {}, - "Anteil f\u00fcr Konto Vollhafter 9826": {}, - "Anteil f\u00fcr Konto Vollhafter 9827": {}, - "Anteil f\u00fcr Konto Vollhafter 9828": {}, - "Anteil f\u00fcr Konto Vollhafter 9829": {}, - "Darlehensverzinsung Teillhafter": {}, - "Darlehensverzinsung Vollhafter": {}, - "Gebrauchs\u00fcberlassung Teillhafter": {}, - "Gebrauchs\u00fcberlassung Vollhafter": {}, - "L\u00f6sch- und Korrekturschl\u00fcssel": {}, - "Name des Gesellschafters Teillhafter": {}, - "Name des Gesellschafters Vollhafter": {}, - "Restanteil Teillhafter": {}, - "Restanteil Vollhafter": {}, - "Sonstige Verg\u00fctungen Teillhafter": {}, - "Sonstige Verg\u00fctungen Vollhafter": {}, - "Tantieme Teillhafter": {}, - "Tantieme Vollhafter": {}, - "T\u00e4tigkeitsverg\u00fctung Teillhafter": {}, - "T\u00e4tigkeitsverg\u00fctung Vollhafter": {} - }, - "Statistische Konten f\u00fcr die im Anhang anzugebenden sonstigen finanziellen Verpflichtungen": { - "Andere Verpflichtungen gem\u00e4\u00df \u00a7 285 Nr. 3 HGB": {}, - "Andere Verpflichtungen gem\u00e4\u00df \u00a7 285 Nr. 3 HGB gegen\u00fcber verbundenen Unternehmen": {}, - "Gegenkonto zu 9281-9284": {}, - "Verpflichtungen aus Miet- und Leasingsvertr\u00e4gen": {}, - "Verpflichtungen aus Miet- und Leasingsvertr\u00e4gen gegen\u00fcber verbundenen Unternehmen": {} - }, - "Statistische Konten f\u00fcr in der Bilanz auszuweisende Haftungsverh\u00e4ltnisse": { - "Gegenkonto zu 9271 - 9279 (Soll-Buchung)": {}, - "Haftung aus der Bestellung von Sicherheiten f\u00fcr fremde Verbindlichkeiten": {}, - "Haftung aus der Bestellung von Sicherheiten f\u00fcr fremde Verbindlichkeiten gegen\u00fcber verbundenen Unternehmen": {}, - "Verbindlichkeiten aus B\u00fcrgschaften- Wechsel- und Scheckb\u00fcrgschaften": {}, - "Verbindlichkeiten aus B\u00fcrgschaften- Wechsel- und Scheckb\u00fcrgschaften gegen\u00fcber verbundenen Unternehmen": {}, - "Verbindlichkeiten aus Gew\u00e4hrleistungsvertr\u00e4gen": {}, - "Verbindlichkeiten aus Gew\u00e4hrleistungsvertr\u00e4gen gegen\u00fcber verbundenen Unternehmen": {}, - "Verbindlichkeiten aus der Begebung und \u00fcbertragung von Wechseln": {}, - "Verpflichtungen aus Treuhandverm\u00f6gen": {} - }, - "Statistische Konten zu \u00a7 4 (4a) EStG": { - "Erh\u00f6hung der Entnahmen \u00a74 (4a) EStG": {}, - "Gegenkonto zur Erh\u00f6hung der Entnahmen \u00a74 (4a) EStG (Haben)": {}, - "Gegenkonto zur Minderung der Entnahmen \u00a74 (4a) EStG": {}, - "Minderung der Entnahmen \u00a74 (4a) EStG (Haben)": {} - }, - "Statistische Konten zur informativen Angabe des gezeichneten Kapitals in anderer W\u00e4hrung": { - "Gezeichnetes Kapital in DM": { - "Gezeichnetes Kapital in DM (Art. 42 Abs. 3 S. 1 EGHGB)": {} - }, - "Gezeichnetes Kapital in Euro": { - "Gegenkonto zu 9220-9221": {}, - "Gezeichnetes Kapital in Euro (Art. 42 Abs. 3 S. 2 EGHGB)": {} - } - }, - "Statistische konten f\u00fcr Kinderbetreuungskosten": { - "Gegenkonto zu 9918 (Haben)": {}, - "Kinderbetreuungskosten (wie Betriebsausgaben steuerlich anzusetzender Betrag)": {} - }, - "Steueraufwand der Gesellschafter": { - "Gegenkonto zu 9887": {}, - "Steueraufwand der Gesellschafter 1": {} - }, - "Verrechnungskonto f\u00fcr nicht durch Verm\u00f6genseinlagen gedeckte Entnahmen": { - "Verrechnungskonto f\u00fcr nicht durch Verm\u00f6genseinlagen gedeckte Entnahmen Kommanditisten": {}, - "Verrechnungskonto f\u00fcr nicht durch Verm\u00f6genseinlagen gedeckte Entnahmen pers\u00f6nlich haftender Gesellschafter": {} - }, - "Vorsteuer-/Umsatzsteuerkonten zur Korrektur der Forderungen/ Verbindlichkeiten (E\u00fcR)": { - "Gegenkonto 9893-9894 f\u00fcr die Aufteilung der Umsatzsteuersatz (E\u00fcR)": {}, - "Gegenkonto 9896-9897 f\u00fcr die Aufteilung der Vorsteuer (E\u00fcR)": {}, - "SO Commitment": {}, - "Umsatzsteuer in den Forderungen zum allgemeinen Umsatzsteuersatz (E\u00fcR)": {}, - "Umsatzsteuer in den Forderungen zum erm\u00e4\u00dfigten Umsatzsteuersatz (E\u00fcR)": {}, - "Vorsteuer in den Verbindlichkeiten zum allgemeinen Umsatzsteuersatz (E\u00fcR)": {}, - "Vorsteuer in den Verbindlichkeiten zum erm\u00e4\u00dfigten Umsatzsteuersatz (E\u00fcR)": {} - }, - "Vortragskonten": { - "Offene Posten aus 1990": {}, - "Offene Posten aus 1991": {}, - "Offene Posten aus 1992": {}, - "Offene Posten aus 1993": {}, - "Offene Posten aus 1994": {}, - "Offene Posten aus 1995": {}, - "Offene Posten aus 1996": {}, - "Offene Posten aus 1997": {}, - "Offene Posten aus 1998": {}, - "Offene Posten aus 1999": {}, - "Offene Posten aus 2000": {}, - "Offene Posten aus 2001": {}, - "Offene Posten aus 2002": {}, - "Offene Posten aus 2003": {}, - "Offene Posten aus 2004": {}, - "Offene Posten aus 2005": {}, - "Offene Posten aus 2006": {}, - "Offene Posten aus 2007": {}, - "Offene Posten aus 2008": {}, - "Offene Posten aus 2009": {}, - "Saldenvortr\u00e4ge": {}, - "Saldenvortr\u00e4ge Debitoren": {}, - "Saldenvortr\u00e4ge Kreditoren": {}, - "Saldenvortr\u00e4ge- Sachkonten": {}, - "Summenvortragskonto": {} - }, - "root_type": "Asset" - } - } -} From 4d75159247e012745bbfdc309d49a52adf00998f Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Sat, 16 Dec 2023 21:27:38 +0100 Subject: [PATCH 076/205] chore: consistent naming for German CoA files --- ...{de_kontenplan_SKR03_gnucash.json => de_kontenplan_SKR03.json} | 0 ...an_SKR04_with_account_number.json => de_kontenplan_SKR04.json} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename erpnext/accounts/doctype/account/chart_of_accounts/verified/{de_kontenplan_SKR03_gnucash.json => de_kontenplan_SKR03.json} (100%) rename erpnext/accounts/doctype/account/chart_of_accounts/verified/{de_kontenplan_SKR04_with_account_number.json => de_kontenplan_SKR04.json} (100%) diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR03_gnucash.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR03.json similarity index 100% rename from erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR03_gnucash.json rename to erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR03.json diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04_with_account_number.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04.json similarity index 100% rename from erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04_with_account_number.json rename to erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04.json From 0743289925d0866a16373c05cfb81825b58e35ba Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Sun, 17 Dec 2023 12:42:07 +0530 Subject: [PATCH 077/205] fix: serial and batch bundle return not working (#38754) * fix: serial and batch bundle return not working * test: added test case for delivery note return against denormalized serial no --- .../controllers/sales_and_purchase_return.py | 191 ++++++++++++------ erpnext/controllers/selling_controller.py | 4 + erpnext/controllers/stock_controller.py | 6 + erpnext/public/js/controllers/buying.js | 14 +- erpnext/public/js/utils/sales_common.js | 7 +- .../js/utils/serial_no_batch_selector.js | 49 +++-- .../delivery_note/test_delivery_note.py | 109 ++++++++++ .../serial_and_batch_bundle.py | 107 +++++++++- .../stock/doctype/serial_no/serial_no.json | 28 +-- erpnext/stock/doctype/serial_no/serial_no.py | 22 +- .../stock_ledger_entry/stock_ledger_entry.py | 3 + erpnext/stock/serial_batch_bundle.py | 53 ++++- 12 files changed, 460 insertions(+), 133 deletions(-) diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py index 81e71e3aa2..81080f0266 100644 --- a/erpnext/controllers/sales_and_purchase_return.py +++ b/erpnext/controllers/sales_and_purchase_return.py @@ -8,6 +8,8 @@ from frappe.model.meta import get_field_precision from frappe.utils import flt, format_datetime, get_datetime import erpnext +from erpnext.stock.serial_batch_bundle import get_batches_from_bundle +from erpnext.stock.serial_batch_bundle import get_serial_nos as get_serial_nos_from_bundle from erpnext.stock.utils import get_incoming_rate @@ -69,8 +71,6 @@ def validate_return_against(doc): def validate_returned_items(doc): - from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos - valid_items = frappe._dict() select_fields = "item_code, qty, stock_qty, rate, parenttype, conversion_factor" @@ -123,26 +123,6 @@ def validate_returned_items(doc): ) ) - elif ref.batch_no and d.batch_no not in ref.batch_no: - frappe.throw( - _("Row # {0}: Batch No must be same as {1} {2}").format( - d.idx, doc.doctype, doc.return_against - ) - ) - - elif ref.serial_no: - if d.qty and not d.serial_no: - frappe.throw(_("Row # {0}: Serial No is mandatory").format(d.idx)) - else: - serial_nos = get_serial_nos(d.serial_no) - for s in serial_nos: - if s not in ref.serial_no: - frappe.throw( - _("Row # {0}: Serial No {1} does not match with {2} {3}").format( - d.idx, s, doc.doctype, doc.return_against - ) - ) - if ( warehouse_mandatory and not d.get("warehouse") @@ -397,71 +377,92 @@ def make_return_doc( else: doc.run_method("calculate_taxes_and_totals") - def update_item(source_doc, target_doc, source_parent): + def update_serial_batch_no(source_doc, target_doc, source_parent, item_details, qty_field): + from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos from erpnext.stock.serial_batch_bundle import SerialBatchCreation - target_doc.qty = -1 * source_doc.qty - item_details = frappe.get_cached_value( - "Item", source_doc.item_code, ["has_batch_no", "has_serial_no"], as_dict=1 - ) - returned_serial_nos = [] - if source_doc.get("serial_and_batch_bundle"): - if item_details.has_serial_no: - returned_serial_nos = get_returned_serial_nos(source_doc, source_parent) + returned_batches = frappe._dict() + serial_and_batch_field = ( + "serial_and_batch_bundle" if qty_field == "stock_qty" else "rejected_serial_and_batch_bundle" + ) + old_serial_no_field = "serial_no" if qty_field == "stock_qty" else "rejected_serial_no" + old_batch_no_field = "batch_no" - type_of_transaction = "Inward" - if ( - frappe.db.get_value( - "Serial and Batch Bundle", source_doc.serial_and_batch_bundle, "type_of_transaction" - ) - == "Inward" - ): - type_of_transaction = "Outward" - - cls_obj = SerialBatchCreation( - { - "type_of_transaction": type_of_transaction, - "serial_and_batch_bundle": source_doc.serial_and_batch_bundle, - "returned_against": source_doc.name, - "item_code": source_doc.item_code, - "returned_serial_nos": returned_serial_nos, - } - ) - - cls_obj.duplicate_package() - if cls_obj.serial_and_batch_bundle: - target_doc.serial_and_batch_bundle = cls_obj.serial_and_batch_bundle - - if source_doc.get("rejected_serial_and_batch_bundle"): + if ( + source_doc.get(serial_and_batch_field) + or source_doc.get(old_serial_no_field) + or source_doc.get(old_batch_no_field) + ): if item_details.has_serial_no: returned_serial_nos = get_returned_serial_nos( - source_doc, source_parent, serial_no_field="rejected_serial_and_batch_bundle" + source_doc, source_parent, serial_no_field=serial_and_batch_field + ) + else: + returned_batches = get_returned_batches( + source_doc, source_parent, batch_no_field=serial_and_batch_field ) type_of_transaction = "Inward" - if ( + if source_doc.get(serial_and_batch_field) and ( frappe.db.get_value( - "Serial and Batch Bundle", source_doc.rejected_serial_and_batch_bundle, "type_of_transaction" + "Serial and Batch Bundle", source_doc.get(serial_and_batch_field), "type_of_transaction" ) == "Inward" ): type_of_transaction = "Outward" + elif source_parent.doctype in [ + "Purchase Invoice", + "Purchase Receipt", + "Subcontracting Receipt", + ]: + type_of_transaction = "Outward" cls_obj = SerialBatchCreation( { "type_of_transaction": type_of_transaction, - "serial_and_batch_bundle": source_doc.rejected_serial_and_batch_bundle, + "serial_and_batch_bundle": source_doc.get(serial_and_batch_field), "returned_against": source_doc.name, "item_code": source_doc.item_code, "returned_serial_nos": returned_serial_nos, + "voucher_type": source_parent.doctype, + "do_not_submit": True, + "warehouse": source_doc.warehouse, + "has_serial_no": item_details.has_serial_no, + "has_batch_no": item_details.has_batch_no, } ) - cls_obj.duplicate_package() - if cls_obj.serial_and_batch_bundle: - target_doc.serial_and_batch_bundle = cls_obj.serial_and_batch_bundle + serial_nos = [] + batches = frappe._dict() + if source_doc.get(old_batch_no_field): + batches = frappe._dict({source_doc.batch_no: source_doc.get(qty_field)}) + elif source_doc.get(old_serial_no_field): + serial_nos = get_serial_nos(source_doc.get(old_serial_no_field)) + elif source_doc.get(serial_and_batch_field): + if item_details.has_serial_no: + serial_nos = get_serial_nos_from_bundle(source_doc.get(serial_and_batch_field)) + else: + batches = get_batches_from_bundle(source_doc.get(serial_and_batch_field)) + if serial_nos: + cls_obj.serial_nos = sorted(list(set(serial_nos) - set(returned_serial_nos))) + elif batches: + for batch in batches: + if batch in returned_batches: + batches[batch] -= flt(returned_batches.get(batch)) + + cls_obj.batches = batches + + if source_doc.get(serial_and_batch_field): + cls_obj.duplicate_package() + if cls_obj.serial_and_batch_bundle: + target_doc.set(serial_and_batch_field, cls_obj.serial_and_batch_bundle) + else: + target_doc.set(serial_and_batch_field, cls_obj.make_serial_and_batch_bundle().name) + + def update_item(source_doc, target_doc, source_parent): + target_doc.qty = -1 * source_doc.qty if doctype in ["Purchase Receipt", "Subcontracting Receipt"]: returned_qty_map = get_returned_qty_map_for_row( source_parent.name, source_parent.supplier, source_doc.name, doctype @@ -561,6 +562,17 @@ def make_return_doc( if default_warehouse_for_sales_return: target_doc.warehouse = default_warehouse_for_sales_return + item_details = frappe.get_cached_value( + "Item", source_doc.item_code, ["has_batch_no", "has_serial_no"], as_dict=1 + ) + + if not item_details.has_batch_no and not item_details.has_serial_no: + return + + for qty_field in ["stock_qty", "rejected_qty"]: + if target_doc.get(qty_field): + update_serial_batch_no(source_doc, target_doc, source_parent, item_details, qty_field) + def update_terms(source_doc, target_doc, source_parent): target_doc.payment_amount = -source_doc.payment_amount @@ -716,6 +728,9 @@ def get_returned_serial_nos( [parent_doc.doctype, "docstatus", "=", 1], ] + if serial_no_field == "rejected_serial_and_batch_bundle": + filters.append([child_doc.doctype, "rejected_qty", ">", 0]) + # Required for POS Invoice if ignore_voucher_detail_no: filters.append([child_doc.doctype, "name", "!=", ignore_voucher_detail_no]) @@ -723,9 +738,57 @@ def get_returned_serial_nos( ids = [] for row in frappe.get_all(parent_doc.doctype, fields=fields, filters=filters): ids.append(row.get("serial_and_batch_bundle")) - if row.get(old_field): + if row.get(old_field) and not row.get(serial_no_field): serial_nos.extend(get_serial_nos_from_serial_no(row.get(old_field))) - serial_nos.extend(get_serial_nos(ids)) + if ids: + serial_nos.extend(get_serial_nos(ids)) return serial_nos + + +def get_returned_batches( + child_doc, parent_doc, batch_no_field=None, ignore_voucher_detail_no=None +): + from erpnext.stock.serial_batch_bundle import get_batches_from_bundle + + batches = frappe._dict() + + old_field = "batch_no" + if not batch_no_field: + batch_no_field = "serial_and_batch_bundle" + + return_ref_field = frappe.scrub(child_doc.doctype) + if child_doc.doctype == "Delivery Note Item": + return_ref_field = "dn_detail" + + fields = [ + f"`{'tab' + child_doc.doctype}`.`{batch_no_field}`", + f"`{'tab' + child_doc.doctype}`.`batch_no`", + f"`{'tab' + child_doc.doctype}`.`stock_qty`", + ] + + filters = [ + [parent_doc.doctype, "return_against", "=", parent_doc.name], + [parent_doc.doctype, "is_return", "=", 1], + [child_doc.doctype, return_ref_field, "=", child_doc.name], + [parent_doc.doctype, "docstatus", "=", 1], + ] + + if batch_no_field == "rejected_serial_and_batch_bundle": + filters.append([child_doc.doctype, "rejected_qty", ">", 0]) + + # Required for POS Invoice + if ignore_voucher_detail_no: + filters.append([child_doc.doctype, "name", "!=", ignore_voucher_detail_no]) + + ids = [] + for row in frappe.get_all(parent_doc.doctype, fields=fields, filters=filters): + ids.append(row.get("serial_and_batch_bundle")) + if row.get(old_field) and not row.get(batch_no_field): + batches.setdefault(row.get(old_field), row.get("stock_qty")) + + if ids: + batches.update(get_batches_from_bundle(ids)) + + return batches diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index fdadb30e93..e8bae8cda5 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -308,6 +308,8 @@ class SellingController(StockController): "warehouse": p.warehouse or d.warehouse, "item_code": p.item_code, "qty": flt(p.qty), + "serial_no": p.serial_no if self.docstatus == 2 else None, + "batch_no": p.batch_no if self.docstatus == 2 else None, "uom": p.uom, "serial_and_batch_bundle": p.serial_and_batch_bundle or get_serial_and_batch_bundle(p, self), @@ -330,6 +332,8 @@ class SellingController(StockController): "warehouse": d.warehouse, "item_code": d.item_code, "qty": d.stock_qty, + "serial_no": d.serial_no if self.docstatus == 2 else None, + "batch_no": d.batch_no if self.docstatus == 2 else None, "uom": d.uom, "stock_uom": d.stock_uom, "conversion_factor": d.conversion_factor, diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 2a8420418a..671d2fb7a5 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -463,6 +463,12 @@ class StockController(AccountsController): sl_dict.update(args) self.update_inventory_dimensions(d, sl_dict) + if self.docstatus == 2: + # To handle denormalized serial no records, will br deprecated in v16 + for field in ["serial_no", "batch_no"]: + if d.get(field): + sl_dict[field] = d.get(field) + return sl_dict def update_inventory_dimensions(self, row, sl_dict) -> None: diff --git a/erpnext/public/js/controllers/buying.js b/erpnext/public/js/controllers/buying.js index 3ed7fc75cf..77ecf75e0c 100644 --- a/erpnext/public/js/controllers/buying.js +++ b/erpnext/public/js/controllers/buying.js @@ -361,9 +361,14 @@ erpnext.buying = { new erpnext.SerialBatchPackageSelector( me.frm, item, (r) => { if (r) { + let qty = Math.abs(r.total_qty); + if (doc.is_return) { + qty = qty * -1; + } + let update_values = { "serial_and_batch_bundle": r.name, - "qty": Math.abs(r.total_qty) + "qty": qty } if (r.warehouse) { @@ -396,9 +401,14 @@ erpnext.buying = { new erpnext.SerialBatchPackageSelector( me.frm, item, (r) => { if (r) { + let qty = Math.abs(r.total_qty); + if (doc.is_return) { + qty = qty * -1; + } + let update_values = { "serial_and_batch_bundle": r.name, - "rejected_qty": Math.abs(r.total_qty) + "rejected_qty": qty } if (r.warehouse) { diff --git a/erpnext/public/js/utils/sales_common.js b/erpnext/public/js/utils/sales_common.js index 5514963c96..084cca7db5 100644 --- a/erpnext/public/js/utils/sales_common.js +++ b/erpnext/public/js/utils/sales_common.js @@ -317,9 +317,14 @@ erpnext.sales_common = { new erpnext.SerialBatchPackageSelector( me.frm, item, (r) => { if (r) { + let qty = Math.abs(r.total_qty); + if (doc.is_return) { + qty = qty * -1; + } + frappe.model.set_value(item.doctype, item.name, { "serial_and_batch_bundle": r.name, - "qty": Math.abs(r.total_qty) + "qty": qty }); } } diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js index 7b9cdfef2a..4abc8fa395 100644 --- a/erpnext/public/js/utils/serial_no_batch_selector.js +++ b/erpnext/public/js/utils/serial_no_batch_selector.js @@ -32,22 +32,39 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { }); this.dialog.show(); - - let qty = this.item.stock_qty || this.item.transfer_qty || this.item.qty; - this.dialog.set_value("qty", qty).then(() => { - if (this.item.serial_no) { - this.dialog.set_value("scan_serial_no", this.item.serial_no); - frappe.model.set_value(this.item.doctype, this.item.name, 'serial_no', ''); - } else if (this.item.batch_no) { - this.dialog.set_value("scan_batch_no", this.item.batch_no); - frappe.model.set_value(this.item.doctype, this.item.name, 'batch_no', ''); - } - - this.dialog.fields_dict.entries.grid.refresh(); - }); - this.$scan_btn = this.dialog.$wrapper.find(".link-btn"); this.$scan_btn.css("display", "inline"); + + let qty = this.item.stock_qty || this.item.transfer_qty || this.item.qty; + + if (this.item?.is_rejected) { + qty = this.item.rejected_qty; + } + + qty = Math.abs(qty); + if (qty > 0) { + this.dialog.set_value("qty", qty).then(() => { + if (this.item.serial_no && !this.item.serial_and_batch_bundle) { + let serial_nos = this.item.serial_no.split('\n'); + if (serial_nos.length > 1) { + serial_nos.forEach(serial_no => { + this.dialog.fields_dict.entries.df.data.push({ + serial_no: serial_no, + batch_no: this.item.batch_no + }); + }); + } else { + this.dialog.set_value("scan_serial_no", this.item.serial_no); + } + frappe.model.set_value(this.item.doctype, this.item.name, 'serial_no', ''); + } else if (this.item.batch_no && !this.item.serial_and_batch_bundle) { + this.dialog.set_value("scan_batch_no", this.item.batch_no); + frappe.model.set_value(this.item.doctype, this.item.name, 'batch_no', ''); + } + + this.dialog.fields_dict.entries.grid.refresh(); + }); + } } get_serial_no_filters() { @@ -467,13 +484,13 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { } render_data() { - if (!this.frm.is_new() && this.bundle) { + if (this.bundle) { frappe.call({ method: 'erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.get_serial_batch_ledgers', args: { item_code: this.item.item_code, name: this.bundle, - voucher_no: this.item.parent, + voucher_no: !this.frm.is_new() ? this.item.parent : "", } }).then(r => { if (r.message) { diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index 94655747e4..3a581226ca 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -174,6 +174,115 @@ class TestDeliveryNote(FrappeTestCase): for field, value in field_values.items(): self.assertEqual(cstr(serial_no.get(field)), value) + def test_delivery_note_return_against_denormalized_serial_no(self): + from erpnext.stock.doctype.delivery_note.delivery_note import make_sales_return + from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos + + frappe.flags.ignore_serial_batch_bundle_validation = True + sn_item = "Old Serial NO Item Return Test - 1" + make_item( + sn_item, + { + "has_serial_no": 1, + "serial_no_series": "OSN-.####", + "is_stock_item": 1, + }, + ) + + frappe.flags.ignore_serial_batch_bundle_validation = True + serial_nos = [ + "OSN-1", + "OSN-2", + "OSN-3", + "OSN-4", + "OSN-5", + "OSN-6", + "OSN-7", + "OSN-8", + "OSN-9", + "OSN-10", + "OSN-11", + "OSN-12", + ] + + for sn in serial_nos: + if not frappe.db.exists("Serial No", sn): + sn_doc = frappe.get_doc( + { + "doctype": "Serial No", + "item_code": sn_item, + "serial_no": sn, + } + ) + sn_doc.insert() + + warehouse = "_Test Warehouse - _TC" + company = frappe.db.get_value("Warehouse", warehouse, "company") + se_doc = make_stock_entry( + item_code=sn_item, + company=company, + target="_Test Warehouse - _TC", + qty=12, + basic_rate=100, + do_not_submit=1, + ) + + se_doc.items[0].serial_no = "\n".join(serial_nos) + se_doc.submit() + + self.assertEqual(sorted(get_serial_nos(se_doc.items[0].serial_no)), sorted(serial_nos)) + + dn = create_delivery_note( + item_code=sn_item, + qty=12, + rate=500, + warehouse=warehouse, + company=company, + expense_account="Cost of Goods Sold - _TC", + cost_center="Main - _TC", + do_not_submit=1, + ) + + dn.items[0].serial_no = "\n".join(serial_nos) + dn.submit() + dn.reload() + + self.assertTrue(dn.items[0].serial_no) + + frappe.flags.ignore_serial_batch_bundle_validation = False + + # return entry + dn1 = make_sales_return(dn.name) + + dn1.items[0].qty = -2 + + bundle_doc = frappe.get_doc("Serial and Batch Bundle", dn1.items[0].serial_and_batch_bundle) + bundle_doc.set("entries", bundle_doc.entries[:2]) + bundle_doc.save() + + dn1.save() + dn1.submit() + + returned_serial_nos1 = get_serial_nos_from_bundle(dn1.items[0].serial_and_batch_bundle) + for serial_no in returned_serial_nos1: + self.assertTrue(serial_no in serial_nos) + + dn2 = make_sales_return(dn.name) + + dn2.items[0].qty = -2 + + bundle_doc = frappe.get_doc("Serial and Batch Bundle", dn2.items[0].serial_and_batch_bundle) + bundle_doc.set("entries", bundle_doc.entries[:2]) + bundle_doc.save() + + dn2.save() + dn2.submit() + + returned_serial_nos2 = get_serial_nos_from_bundle(dn2.items[0].serial_and_batch_bundle) + for serial_no in returned_serial_nos2: + self.assertTrue(serial_no in serial_nos) + self.assertFalse(serial_no in returned_serial_nos1) + def test_sales_return_for_non_bundled_items_partial(self): company = frappe.db.get_value("Warehouse", "Stores - TCP1", "company") diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index ecb9314fbb..52ef26e641 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -23,7 +23,11 @@ from frappe.utils import ( ) from frappe.utils.csvutils import build_csv_response -from erpnext.stock.serial_batch_bundle import BatchNoValuation, SerialNoValuation +from erpnext.stock.serial_batch_bundle import ( + BatchNoValuation, + SerialNoValuation, + get_batches_from_bundle, +) from erpnext.stock.serial_batch_bundle import get_serial_nos as get_serial_nos_from_bundle @@ -123,6 +127,11 @@ class SerialandBatchBundle(Document): ) def validate_serial_nos_duplicate(self): + # Don't inward same serial number multiple times + + if not self.warehouse: + return + if self.voucher_type in ["Stock Reconciliation", "Stock Entry"] and self.docstatus != 1: return @@ -146,7 +155,6 @@ class SerialandBatchBundle(Document): kwargs["voucher_no"] = self.voucher_no available_serial_nos = get_available_serial_nos(kwargs) - for data in available_serial_nos: if data.serial_no in serial_nos: self.throw_error_message( @@ -327,6 +335,19 @@ class SerialandBatchBundle(Document): ): values_to_set["posting_time"] = parent.posting_time + if parent.doctype in [ + "Delivery Note", + "Purchase Receipt", + "Purchase Invoice", + "Sales Invoice", + ] and parent.get("is_return"): + return_ref_field = frappe.scrub(parent.doctype) + "_item" + if parent.doctype == "Delivery Note": + return_ref_field = "dn_detail" + + if row.get(return_ref_field): + values_to_set["returned_against"] = row.get(return_ref_field) + if values_to_set: self.db_set(values_to_set) @@ -509,7 +530,6 @@ class SerialandBatchBundle(Document): batch_nos = [] serial_batches = {} - for row in self.entries: if self.has_serial_no and not row.serial_no: frappe.throw( @@ -590,6 +610,67 @@ class SerialandBatchBundle(Document): f"Batch Nos {bold(incorrect_batch_nos)} does not belong to Item {bold(self.item_code)}" ) + def validate_serial_and_batch_no_for_returned(self): + from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos + + if not self.returned_against: + return + + if self.voucher_type not in [ + "Purchase Receipt", + "Purchase Invoice", + "Sales Invoice", + "Delivery Note", + ]: + return + + data = self.get_orignal_document_data() + if not data: + return + + serial_nos, batches = [], [] + current_serial_nos = [d.serial_no for d in self.entries if d.serial_no] + current_batches = [d.batch_no for d in self.entries if d.batch_no] + + for d in data: + if self.has_serial_no: + if d.serial_and_batch_bundle: + serial_nos = get_serial_nos_from_bundle(d.serial_and_batch_bundle) + else: + serial_nos = get_serial_nos(d.serial_no) + + elif self.has_batch_no: + if d.serial_and_batch_bundle: + batches = get_batches_from_bundle(d.serial_and_batch_bundle) + else: + batches = frappe._dict({d.batch_no: d.stock_qty}) + + if batches: + batches = [d for d in batches if batches[d] > 0] + + if serial_nos: + if not set(current_serial_nos).issubset(set(serial_nos)): + self.throw_error_message( + f"Serial Nos {bold(', '.join(serial_nos))} are not part of the original document." + ) + + if batches: + if not set(current_batches).issubset(set(batches)): + self.throw_error_message( + f"Batch Nos {bold(', '.join(batches))} are not part of the original document." + ) + + def get_orignal_document_data(self): + fields = ["serial_and_batch_bundle", "stock_qty"] + if self.has_serial_no: + fields.append("serial_no") + + elif self.has_batch_no: + fields.append("batch_no") + + child_doc = self.voucher_type + " Item" + return frappe.get_all(child_doc, fields=fields, filters={"name": self.returned_against}) + def validate_duplicate_serial_and_batch_no(self): serial_nos = [] batch_nos = [] @@ -688,9 +769,29 @@ class SerialandBatchBundle(Document): for batch in batches: frappe.db.set_value("Batch", batch.name, {"reference_name": None, "reference_doctype": None}) + def before_submit(self): + self.validate_serial_and_batch_no_for_returned() + self.set_purchase_document_no() + def on_submit(self): self.validate_serial_nos_inventory() + def set_purchase_document_no(self): + if not self.has_serial_no: + return + + if self.total_qty > 0: + serial_nos = [d.serial_no for d in self.entries if d.serial_no] + sn_table = frappe.qb.DocType("Serial No") + ( + frappe.qb.update(sn_table) + .set( + sn_table.purchase_document_no, + self.voucher_no if not sn_table.purchase_document_no else self.voucher_no, + ) + .where(sn_table.name.isin(serial_nos)) + ).run() + def validate_serial_and_batch_inventory(self): self.check_future_entries_exists() self.validate_batch_inventory() diff --git a/erpnext/stock/doctype/serial_no/serial_no.json b/erpnext/stock/doctype/serial_no/serial_no.json index b4ece00fe6..2d7fcac89a 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.json +++ b/erpnext/stock/doctype/serial_no/serial_no.json @@ -27,8 +27,6 @@ "column_break_24", "location", "employee", - "delivery_details", - "delivery_document_type", "warranty_amc_details", "column_break6", "warranty_expiry_date", @@ -39,7 +37,8 @@ "more_info", "company", "column_break_2cmm", - "work_order" + "work_order", + "purchase_document_no" ], "fields": [ { @@ -153,20 +152,6 @@ "options": "Employee", "read_only": 1 }, - { - "fieldname": "delivery_details", - "fieldtype": "Section Break", - "label": "Delivery Details", - "oldfieldtype": "Column Break" - }, - { - "fieldname": "delivery_document_type", - "fieldtype": "Link", - "label": "Delivery Document Type", - "no_copy": 1, - "options": "DocType", - "read_only": 1 - }, { "fieldname": "warranty_amc_details", "fieldtype": "Section Break", @@ -275,12 +260,19 @@ { "fieldname": "column_break_2cmm", "fieldtype": "Column Break" + }, + { + "fieldname": "purchase_document_no", + "fieldtype": "Data", + "label": "Creation Document No", + "no_copy": 1, + "read_only": 1 } ], "icon": "fa fa-barcode", "idx": 1, "links": [], - "modified": "2023-11-28 15:37:59.489945", + "modified": "2023-12-17 10:52:55.767839", "modified_by": "Administrator", "module": "Stock", "name": "Serial No", diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py index d562560da1..122664c2dd 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.py +++ b/erpnext/stock/doctype/serial_no/serial_no.py @@ -41,7 +41,6 @@ class SerialNo(StockController): batch_no: DF.Link | None brand: DF.Link | None company: DF.Link - delivery_document_type: DF.Link | None description: DF.Text | None employee: DF.Link | None item_code: DF.Link @@ -51,6 +50,7 @@ class SerialNo(StockController): maintenance_status: DF.Literal[ "", "Under Warranty", "Out of Warranty", "Under AMC", "Out of AMC" ] + purchase_document_no: DF.Data | None purchase_rate: DF.Float serial_no: DF.Data status: DF.Literal["", "Active", "Inactive", "Delivered", "Expired"] @@ -231,26 +231,6 @@ def auto_fetch_serial_number( return sorted([d.get("name") for d in serial_numbers]) -def get_delivered_serial_nos(serial_nos): - """ - Returns serial numbers that delivered from the list of serial numbers - """ - from frappe.query_builder.functions import Coalesce - - SerialNo = frappe.qb.DocType("Serial No") - serial_nos = get_serial_nos(serial_nos) - query = ( - frappe.qb.select(SerialNo.name) - .from_(SerialNo) - .where((SerialNo.name.isin(serial_nos)) & (Coalesce(SerialNo.delivery_document_type, "") != "")) - ) - - result = query.run() - if result and len(result) > 0: - delivered_serial_nos = [row[0] for row in result] - return delivered_serial_nos - - @frappe.whitelist() def get_pos_reserved_serial_nos(filters): if isinstance(filters, str): diff --git a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py index 23788cf46b..6e7af6815f 100644 --- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py +++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py @@ -181,6 +181,9 @@ class StockLedgerEntry(Document): frappe.throw(_("Actual Qty is mandatory")) def validate_serial_batch_no_bundle(self): + if self.is_cancelled == 1: + return + item_detail = frappe.get_cached_value( "Item", self.item_code, diff --git a/erpnext/stock/serial_batch_bundle.py b/erpnext/stock/serial_batch_bundle.py index 0c187923e3..a1874b84dc 100644 --- a/erpnext/stock/serial_batch_bundle.py +++ b/erpnext/stock/serial_batch_bundle.py @@ -218,15 +218,16 @@ class SerialBatchBundle: ).validate_serial_and_batch_inventory() def post_process(self): - if not self.sle.serial_and_batch_bundle: + if not self.sle.serial_and_batch_bundle and not self.sle.serial_no and not self.sle.batch_no: return - docstatus = frappe.get_cached_value( - "Serial and Batch Bundle", self.sle.serial_and_batch_bundle, "docstatus" - ) + if self.sle.serial_and_batch_bundle: + docstatus = frappe.get_cached_value( + "Serial and Batch Bundle", self.sle.serial_and_batch_bundle, "docstatus" + ) - if docstatus != 1: - self.submit_serial_and_batch_bundle() + if docstatus != 1: + self.submit_serial_and_batch_bundle() if self.item_details.has_serial_no == 1: self.set_warehouse_and_status_in_serial_nos() @@ -249,7 +250,12 @@ class SerialBatchBundle: doc.submit() def set_warehouse_and_status_in_serial_nos(self): + from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos as get_parsed_serial_nos + serial_nos = get_serial_nos(self.sle.serial_and_batch_bundle) + if not self.sle.serial_and_batch_bundle and self.sle.serial_no: + serial_nos = get_parsed_serial_nos(self.sle.serial_no) + warehouse = self.warehouse if self.sle.actual_qty > 0 else None if not serial_nos: @@ -263,7 +269,14 @@ class SerialBatchBundle: ( frappe.qb.update(sn_table) .set(sn_table.warehouse, warehouse) - .set(sn_table.status, "Active" if warehouse else status) + .set( + sn_table.status, + "Active" + if warehouse + else status + if (sn_table.purchase_document_no != self.sle.voucher_no and self.sle.is_cancelled != 1) + else "Inactive", + ) .where(sn_table.name.isin(serial_nos)) ).run() @@ -290,6 +303,8 @@ class SerialBatchBundle: from erpnext.stock.doctype.batch.batch import get_available_batches batches = get_batch_nos(self.sle.serial_and_batch_bundle) + if not self.sle.serial_and_batch_bundle and self.sle.batch_no: + batches = frappe._dict({self.sle.batch_no: self.sle.actual_qty}) batches_qty = get_available_batches( frappe._dict( @@ -312,13 +327,35 @@ def get_serial_nos(serial_and_batch_bundle, serial_nos=None): if serial_nos: filters["serial_no"] = ("in", serial_nos) - entries = frappe.get_all("Serial and Batch Entry", fields=["serial_no"], filters=filters) + entries = frappe.get_all( + "Serial and Batch Entry", fields=["serial_no"], filters=filters, order_by="idx" + ) if not entries: return [] return [d.serial_no for d in entries if d.serial_no] +def get_batches_from_bundle(serial_and_batch_bundle, batches=None): + if not serial_and_batch_bundle: + return [] + + filters = {"parent": serial_and_batch_bundle, "batch_no": ("is", "set")} + if isinstance(serial_and_batch_bundle, list): + filters = {"parent": ("in", serial_and_batch_bundle)} + + if batches: + filters["batch_no"] = ("in", batches) + + entries = frappe.get_all( + "Serial and Batch Entry", fields=["batch_no", "qty"], filters=filters, order_by="idx", as_list=1 + ) + if not entries: + return frappe._dict({}) + + return frappe._dict(entries) + + def get_serial_nos_from_bundle(serial_and_batch_bundle, serial_nos=None): return get_serial_nos(serial_and_batch_bundle, serial_nos=serial_nos) From c9fd1822681420868923fd53aa1df3e3c776a4a6 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 17 Dec 2023 13:36:58 +0530 Subject: [PATCH 078/205] fix(demo): Demo setup for canadian COA --- ...plan_comptable_pour_les_provinces_francophones.json | 10 +++++++--- erpnext/setup/demo.py | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/ca_plan_comptable_pour_les_provinces_francophones.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/ca_plan_comptable_pour_les_provinces_francophones.json index 2811fc5fb6..2a30cbcbc9 100644 --- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/ca_plan_comptable_pour_les_provinces_francophones.json +++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/ca_plan_comptable_pour_les_provinces_francophones.json @@ -33,7 +33,9 @@ }, "Stocks": { "Mati\u00e8res premi\u00e8res": {}, - "Stock de produits fini": {}, + "Stock de produits fini": { + "account_type": "Stock" + }, "Stock exp\u00e9di\u00e9 non-factur\u00e9": {}, "Travaux en cours": {}, "account_type": "Stock" @@ -395,9 +397,11 @@ }, "Produits": { "Revenus de ventes": { - " Escomptes de volume sur ventes": {}, + "Escomptes de volume sur ventes": {}, "Autres produits d'exploitation": {}, - "Ventes": {}, + "Ventes": { + "account_type": "Income Account" + }, "Ventes avec des provinces harmonis\u00e9es": {}, "Ventes avec des provinces non-harmonis\u00e9es": {}, "Ventes \u00e0 l'\u00e9tranger": {} diff --git a/erpnext/setup/demo.py b/erpnext/setup/demo.py index 926283ff1c..4bc98b91bd 100644 --- a/erpnext/setup/demo.py +++ b/erpnext/setup/demo.py @@ -112,9 +112,9 @@ def create_transaction(doctype, company, start_date): warehouse = get_warehouse(company) if document_type == "Purchase Order": - posting_date = get_random_date(start_date, 1, 30) + posting_date = get_random_date(start_date, 1, 25) else: - posting_date = get_random_date(start_date, 31, 364) + posting_date = get_random_date(start_date, 31, 350) doctype.update( { From 39ef75e2d0f18aa8d7434297be596b9223aa7910 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 18 Dec 2023 13:39:26 +0530 Subject: [PATCH 079/205] refactor: ignore ERR journals in Statment of Accounts --- .../process_statement_of_accounts.json | 9 ++++++++- .../process_statement_of_accounts.py | 15 +++++++++++++++ .../report/general_ledger/general_ledger.py | 3 +++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json index a3a953f910..ae6059c005 100644 --- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json +++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json @@ -15,6 +15,7 @@ "group_by", "cost_center", "territory", + "ignore_exchange_rate_revaluation_journals", "column_break_14", "to_date", "finance_book", @@ -376,10 +377,16 @@ "fieldname": "pdf_name", "fieldtype": "Data", "label": "PDF Name" + }, + { + "default": "0", + "fieldname": "ignore_exchange_rate_revaluation_journals", + "fieldtype": "Check", + "label": "Ignore Exchange Rate Revaluation Journals" } ], "links": [], - "modified": "2023-08-28 12:59:53.071334", + "modified": "2023-12-18 12:20:08.965120", "modified_by": "Administrator", "module": "Accounts", "name": "Process Statement Of Accounts", diff --git a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py index 9ad25483e3..c03b18a871 100644 --- a/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py +++ b/erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.py @@ -56,6 +56,7 @@ class ProcessStatementOfAccounts(Document): frequency: DF.Literal["Weekly", "Monthly", "Quarterly"] from_date: DF.Date | None group_by: DF.Literal["", "Group by Voucher", "Group by Voucher (Consolidated)"] + ignore_exchange_rate_revaluation_journals: DF.Check include_ageing: DF.Check include_break: DF.Check letter_head: DF.Link | None @@ -119,6 +120,18 @@ def get_statement_dict(doc, get_statement_dict=False): statement_dict = {} ageing = "" + err_journals = None + if doc.report == "General Ledger" and doc.ignore_exchange_rate_revaluation_journals: + err_journals = frappe.db.get_all( + "Journal Entry", + filters={ + "company": doc.company, + "docstatus": 1, + "voucher_type": ("in", ["Exchange Rate Revaluation", "Exchange Gain Or Loss"]), + }, + as_list=True, + ) + for entry in doc.customers: if doc.include_ageing: ageing = set_ageing(doc, entry) @@ -131,6 +144,8 @@ def get_statement_dict(doc, get_statement_dict=False): ) filters = get_common_filters(doc) + if err_journals: + filters.update({"voucher_no_not_in": [x[0] for x in err_journals]}) if doc.report == "General Ledger": filters.update(get_gl_filters(doc, entry, tax_id, presentation_currency)) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index ac06a1227e..896c4c9800 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -238,6 +238,9 @@ def get_conditions(filters): if filters.get("voucher_no"): conditions.append("voucher_no=%(voucher_no)s") + if filters.get("voucher_no_not_in"): + conditions.append("voucher_no not in %(voucher_no_not_in)s") + if filters.get("group_by") == "Group by Party" and not filters.get("party_type"): conditions.append("party_type in ('Customer', 'Supplier')") From 71e833c3f2323873953c3ad7ab4a9403ebbdeb0a Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 17:56:05 +0530 Subject: [PATCH 080/205] fix: not able to cancel SCR with Batch (backport #38817) (#38821) * fix: not able to cancel SCR with Batch (#38817) (cherry picked from commit fb5090fd3f23ada507fe8abc5a899f4b06e48d7e) # Conflicts: # erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py * chore: fix test case * chore: fix test case * chore: fix test case * chore: fix test case --------- Co-authored-by: rohitwaghchaure --- .../serial_and_batch_bundle.py | 2 +- .../subcontracting_receipt.py | 2 +- .../test_subcontracting_receipt.py | 85 +++++++++++++++++++ 3 files changed, 87 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index 52ef26e641..37916e21c8 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -459,7 +459,7 @@ class SerialandBatchBundle(Document): qty_field = "qty" precision = row.precision - if self.voucher_type in ["Subcontracting Receipt"]: + if row.get("doctype") in ["Subcontracting Receipt Supplied Item"]: qty_field = "consumed_qty" if abs(abs(flt(self.total_qty, precision)) - abs(flt(row.get(qty_field), precision))) > 0.01: diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index 1a5deb68df..52bf13c78d 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -167,13 +167,13 @@ class SubcontractingReceipt(SubcontractingController): ) self.update_status_updater_args() self.update_prevdoc_status() - self.delete_auto_created_batches() self.set_consumed_qty_in_subcontract_order() self.set_subcontracting_order_status() self.update_stock_ledger() self.make_gl_entries_on_cancel() self.repost_future_sle_and_gle() self.update_status() + self.delete_auto_created_batches() def validate_items_qty(self): for item in self.items: diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py index f4af21d7c4..9d7be36adb 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py @@ -946,6 +946,91 @@ class TestSubcontractingReceipt(FrappeTestCase): scr.submit() + def test_subcontracting_receipt_cancel_with_batch(self): + from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom + + # Step - 1: Set Backflush Based On as "BOM" + set_backflush_based_on("BOM") + + # Step - 2: Create FG and RM Items + fg_item = make_item( + properties={"is_stock_item": 1, "is_sub_contracted_item": 1, "has_batch_no": 1} + ).name + rm_item1 = make_item(properties={"is_stock_item": 1}).name + rm_item2 = make_item(properties={"is_stock_item": 1}).name + make_item("Subcontracted Service Item Test For Batch 1", {"is_stock_item": 0}) + + # Step - 3: Create BOM for FG Item + bom = make_bom(item=fg_item, raw_materials=[rm_item1, rm_item2]) + for rm_item in bom.items: + self.assertEqual(rm_item.rate, 0) + self.assertEqual(rm_item.amount, 0) + bom = bom.name + + # Step - 4: Create PO and SCO + service_items = [ + { + "warehouse": "_Test Warehouse - _TC", + "item_code": "Subcontracted Service Item Test For Batch 1", + "qty": 100, + "rate": 100, + "fg_item": fg_item, + "fg_item_qty": 100, + }, + ] + sco = get_subcontracting_order(service_items=service_items) + for rm_item in sco.supplied_items: + self.assertEqual(rm_item.rate, 0) + self.assertEqual(rm_item.amount, 0) + + # Step - 5: Inward Raw Materials + rm_items = get_rm_items(sco.supplied_items) + for rm_item in rm_items: + rm_item["rate"] = 100 + itemwise_details = make_stock_in_entry(rm_items=rm_items) + + # Step - 6: Transfer RM's to Subcontractor + se = make_stock_transfer_entry( + sco_no=sco.name, + rm_items=rm_items, + itemwise_details=copy.deepcopy(itemwise_details), + ) + for item in se.items: + self.assertEqual(item.qty, 100) + self.assertEqual(item.basic_rate, 100) + self.assertEqual(item.amount, item.qty * item.basic_rate) + + batch_doc = frappe.get_doc( + { + "doctype": "Batch", + "item": fg_item, + "batch_id": frappe.generate_hash(length=10), + } + ).insert(ignore_permissions=True) + + serial_batch_bundle = frappe.get_doc( + { + "doctype": "Serial and Batch Bundle", + "item_code": fg_item, + "warehouse": sco.items[0].warehouse, + "has_batch_no": 1, + "type_of_transaction": "Inward", + "voucher_type": "Subcontracting Receipt", + "entries": [{"batch_no": batch_doc.name, "qty": 100}], + } + ).insert(ignore_permissions=True) + + # Step - 7: Create Subcontracting Receipt + scr = make_subcontracting_receipt(sco.name) + scr.items[0].serial_and_batch_bundle = serial_batch_bundle.name + scr.save() + scr.submit() + scr.load_from_db() + + # Step - 8: Cancel Subcontracting Receipt + scr.cancel() + self.assertTrue(scr.docstatus == 2) + @change_settings("Buying Settings", {"auto_create_purchase_receipt": 1}) def test_auto_create_purchase_receipt(self): fg_item = "Subcontracted Item SA1" From 8d79365e0ddef42e788f97c668a64c479a803617 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 18 Dec 2023 18:06:44 +0530 Subject: [PATCH 081/205] perf: index `return_against` on delivery note (#38827) There's a multi-column index but that's useful IFF all parts of column are part of query. return against on it's own is VERY unique because it's a primary key, we don't need a multi-column index here. --- erpnext/patches.txt | 1 + .../doctype/delivery_note/delivery_note.json | 5 +++-- .../stock/doctype/delivery_note/delivery_note.py | 4 ---- .../doctype/delivery_note/patches/__init__.py | 0 .../patches/drop_unused_return_against_index.py | 15 +++++++++++++++ .../purchase_receipt/purchase_receipt.json | 5 +++-- .../doctype/purchase_receipt/purchase_receipt.py | 4 ---- 7 files changed, 22 insertions(+), 12 deletions(-) create mode 100644 erpnext/stock/doctype/delivery_note/patches/__init__.py create mode 100644 erpnext/stock/doctype/delivery_note/patches/drop_unused_return_against_index.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 9b070bdaf7..56f6347693 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -354,3 +354,4 @@ execute:frappe.db.set_single_value("Buying Settings", "project_update_frequency" execute:frappe.db.set_default("date_format", frappe.db.get_single_value("System Settings", "date_format")) # below migration patch should always run last erpnext.patches.v14_0.migrate_gl_to_payment_ledger +erpnext.stock.doctype.delivery_note.patches.drop_unused_return_against_index diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.json b/erpnext/stock/doctype/delivery_note/delivery_note.json index b85f296d0b..7873d3e6de 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.json +++ b/erpnext/stock/doctype/delivery_note/delivery_note.json @@ -301,7 +301,8 @@ "no_copy": 1, "options": "Delivery Note", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "search_index": 1 }, { "collapsible": 1, @@ -1401,7 +1402,7 @@ "idx": 146, "is_submittable": 1, "links": [], - "modified": "2023-09-04 14:15:28.363184", + "modified": "2023-12-18 17:19:39.368239", "modified_by": "Administrator", "module": "Stock", "name": "Delivery Note", diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index a101bdf244..675f8e9158 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -1294,7 +1294,3 @@ def make_inter_company_transaction(doctype, source_name, target_doc=None): ) return doclist - - -def on_doctype_update(): - frappe.db.add_index("Delivery Note", ["customer", "is_return", "return_against"]) diff --git a/erpnext/stock/doctype/delivery_note/patches/__init__.py b/erpnext/stock/doctype/delivery_note/patches/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/stock/doctype/delivery_note/patches/drop_unused_return_against_index.py b/erpnext/stock/doctype/delivery_note/patches/drop_unused_return_against_index.py new file mode 100644 index 0000000000..8fe4ffb58f --- /dev/null +++ b/erpnext/stock/doctype/delivery_note/patches/drop_unused_return_against_index.py @@ -0,0 +1,15 @@ +import frappe + + +def execute(): + """Drop unused return_against index""" + + try: + frappe.db.sql_ddl( + "ALTER TABLE `tabDelivery Note` DROP INDEX `customer_is_return_return_against_index`" + ) + frappe.db.sql_ddl( + "ALTER TABLE `tabPurchase Receipt` DROP INDEX `supplier_is_return_return_against_index`" + ) + except Exception: + frappe.log_error("Failed to drop unused index") diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json index c7ad660497..a181022121 100755 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json @@ -289,7 +289,8 @@ "no_copy": 1, "options": "Purchase Receipt", "print_hide": 1, - "read_only": 1 + "read_only": 1, + "search_index": 1 }, { "fieldname": "section_addresses", @@ -1251,7 +1252,7 @@ "idx": 261, "is_submittable": 1, "links": [], - "modified": "2023-11-28 13:14:15.243474", + "modified": "2023-12-18 17:26:41.279663", "modified_by": "Administrator", "module": "Stock", "name": "Purchase Receipt", diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index aa479ee999..10d9eaa3db 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -1360,10 +1360,6 @@ def get_item_account_wise_additional_cost(purchase_document): return item_account_wise_cost -def on_doctype_update(): - frappe.db.add_index("Purchase Receipt", ["supplier", "is_return", "return_against"]) - - @erpnext.allow_regional def update_regional_gl_entries(gl_list, doc): return From 32a608f94848564806d6254d11c6c0655fbcaa9a Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 18:13:47 +0530 Subject: [PATCH 082/205] fix: not able to make inter-company po from so (backport #38826) (#38828) fix: not able to make inter-company po from so (#38826) (cherry picked from commit 23042dfc3c0d02374c5710ed679731b1910f9b9a) Co-authored-by: rohitwaghchaure --- .../accounts/doctype/sales_invoice/sales_invoice.py | 11 ++++++++++- erpnext/controllers/buying_controller.py | 6 +++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index f9d9cb5091..c0228e6b0b 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -2382,9 +2382,18 @@ def make_inter_company_transaction(doctype, source_name, target_doc=None): def get_received_items(reference_name, doctype, reference_fieldname): + reference_field = "inter_company_invoice_reference" + if doctype == "Purchase Order": + reference_field = "inter_company_order_reference" + + filters = { + reference_field: reference_name, + "docstatus": 1, + } + target_doctypes = frappe.get_all( doctype, - filters={"inter_company_invoice_reference": reference_name, "docstatus": 1}, + filters=filters, as_list=True, ) diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 3d863e9b87..572fa519e1 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -381,7 +381,11 @@ class BuyingController(SubcontractingController): rate = flt(outgoing_rate * (d.conversion_factor or 1), d.precision("rate")) else: - field = "incoming_rate" if self.get("is_internal_supplier") else "rate" + field = ( + "incoming_rate" + if self.get("is_internal_supplier") and not self.doctype == "Purchase Order" + else "rate" + ) rate = flt( frappe.db.get_value(ref_doctype, d.get(frappe.scrub(ref_doctype)), field) * (d.conversion_factor or 1), From c7b961ffa27c611a1e0a45750b38f1f23b0b0c7f Mon Sep 17 00:00:00 2001 From: Devin Slauenwhite Date: Mon, 18 Dec 2023 18:03:53 +0000 Subject: [PATCH 083/205] fix: use party account currency when party account is specified --- .../report/accounts_receivable/accounts_receivable.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index 50d5eae407..376c9ba4c3 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -225,7 +225,7 @@ class ReceivablePayableReport(object): if not row: return - if self.filters.get("in_party_currency"): + if self.filters.get("in_party_currency") or self.filters.get("party_account"): amount = ple.amount_in_account_currency else: amount = ple.amount @@ -451,7 +451,7 @@ class ReceivablePayableReport(object): party_details = self.get_party_details(row.party) or {} row.update(party_details) - if self.filters.get("in_party_currency"): + if self.filters.get("in_party_currency") or self.filters.get("party_account"): row.currency = row.account_currency else: row.currency = self.company_currency From a09241e3c763882a0a0e06b21ccaa0b06f60bc75 Mon Sep 17 00:00:00 2001 From: Devin Slauenwhite Date: Mon, 18 Dec 2023 19:09:25 +0000 Subject: [PATCH 084/205] fix(test): expect account currency when party account is specified. --- .../report/accounts_receivable/test_accounts_receivable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py index dd0842df04..6da007788e 100644 --- a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py @@ -544,7 +544,7 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase): filters.update({"party_account": self.debtors_usd}) report = execute(filters)[1] self.assertEqual(len(report), 1) - expected_data = [8000.0, 8000.0, self.debtors_usd, si2.currency] + expected_data = [100.0, 100.0, self.debtors_usd, si2.currency] row = report[0] self.assertEqual( expected_data, [row.invoiced, row.outstanding, row.party_account, row.account_currency] From a99d0a65b028b05b5c3bcb46a48a16771d00861f Mon Sep 17 00:00:00 2001 From: Gughan Ravikumar Date: Tue, 19 Dec 2023 07:54:57 +0530 Subject: [PATCH 085/205] fix: set `fg-itm-qty` based on `qty` instead of the other way round --- erpnext/buying/doctype/purchase_order/purchase_order.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js index 88faeee982..3b671bb239 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.js +++ b/erpnext/buying/doctype/purchase_order/purchase_order.js @@ -214,7 +214,7 @@ frappe.ui.form.on("Purchase Order Item", { } }, - fg_item_qty: async function(frm, cdt, cdn) { + qty: async function (frm, cdt, cdn) { if (frm.doc.is_subcontracted && !frm.doc.is_old_subcontracting_flow) { var row = locals[cdt][cdn]; @@ -222,7 +222,7 @@ frappe.ui.form.on("Purchase Order Item", { var result = await frm.events.get_subcontracting_boms_for_finished_goods(row.fg_item) if (result.message && row.item_code == result.message.service_item && row.uom == result.message.service_item_uom) { - frappe.model.set_value(cdt, cdn, "qty", flt(row.fg_item_qty) * flt(result.message.conversion_factor)); + frappe.model.set_value(cdt, cdn, "fg_item_qty", flt(row.qty) / flt(result.message.conversion_factor)); } } } From 877262891235b21447c5b74684fb7173910427e1 Mon Sep 17 00:00:00 2001 From: Dany Robert Date: Sat, 16 Dec 2023 05:34:43 +0000 Subject: [PATCH 086/205] test: partial payment for pos invoice --- .../test_accounts_receivable.py | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py index dd0842df04..fbfaed6dfd 100644 --- a/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py @@ -76,6 +76,41 @@ class TestAccountsReceivable(AccountsTestMixin, FrappeTestCase): return credit_note + def test_pos_receivable(self): + filters = { + "company": self.company, + "party_type": "Customer", + "party": [self.customer], + "report_date": add_days(today(), 2), + "based_on_payment_terms": 0, + "range1": 30, + "range2": 60, + "range3": 90, + "range4": 120, + "show_remarks": False, + } + + pos_inv = self.create_sales_invoice(no_payment_schedule=True, do_not_submit=True) + pos_inv.posting_date = add_days(today(), 2) + pos_inv.is_pos = 1 + pos_inv.append( + "payments", + frappe._dict( + mode_of_payment="Cash", + amount=flt(pos_inv.grand_total / 2), + ), + ) + pos_inv.disable_rounded_total = 1 + pos_inv.save() + pos_inv.submit() + + report = execute(filters) + expected_data = [[pos_inv.grand_total, pos_inv.paid_amount, 0]] + + row = report[1][-1] + self.assertEqual(expected_data[0], [row.invoiced, row.paid, row.credit_note]) + pos_inv.cancel() + def test_accounts_receivable(self): filters = { "company": self.company, From 4aa960b744c289b0cda9acfae7911b1ef6ffe5d6 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 19 Dec 2023 14:59:33 +0530 Subject: [PATCH 087/205] fix: item variant with manufacturer (backport #38845) (#38847) * fix: item variant with manufacturer (#38845) (cherry picked from commit e0c8ff10daeed0829266aea9142805f68ceedb2b) * chore: fix test case --------- Co-authored-by: rohitwaghchaure --- erpnext/controllers/item_variant.py | 20 +++++++++-- erpnext/stock/doctype/item/test_item.py | 44 +++++++++---------------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/erpnext/controllers/item_variant.py b/erpnext/controllers/item_variant.py index c8785a5a72..ea7fb23cb6 100644 --- a/erpnext/controllers/item_variant.py +++ b/erpnext/controllers/item_variant.py @@ -56,10 +56,24 @@ def make_variant_based_on_manufacturer(template, manufacturer, manufacturer_part copy_attributes_to_variant(template, variant) - variant.manufacturer = manufacturer - variant.manufacturer_part_no = manufacturer_part_no - variant.item_code = append_number_if_name_exists("Item", template.name) + variant.flags.ignore_mandatory = True + variant.save() + + if not frappe.db.exists( + "Item Manufacturer", {"item_code": variant.name, "manufacturer": manufacturer} + ): + manufacturer_doc = frappe.new_doc("Item Manufacturer") + manufacturer_doc.update( + { + "item_code": variant.name, + "manufacturer": manufacturer, + "manufacturer_part_no": manufacturer_part_no, + } + ) + + manufacturer_doc.flags.ignore_mandatory = True + manufacturer_doc.save(ignore_permissions=True) return variant diff --git a/erpnext/stock/doctype/item/test_item.py b/erpnext/stock/doctype/item/test_item.py index a942f58bd6..b237f73026 100644 --- a/erpnext/stock/doctype/item/test_item.py +++ b/erpnext/stock/doctype/item/test_item.py @@ -522,39 +522,25 @@ class TestItem(FrappeTestCase): self.assertEqual(factor, 1.0) def test_item_variant_by_manufacturer(self): - fields = [{"field_name": "description"}, {"field_name": "variant_based_on"}] - set_item_variant_settings(fields) + template = make_item( + "_Test Item Variant By Manufacturer", {"has_variants": 1, "variant_based_on": "Manufacturer"} + ).name - if frappe.db.exists("Item", "_Test Variant Mfg"): - frappe.delete_doc("Item", "_Test Variant Mfg") - if frappe.db.exists("Item", "_Test Variant Mfg-1"): - frappe.delete_doc("Item", "_Test Variant Mfg-1") - if frappe.db.exists("Manufacturer", "MSG1"): - frappe.delete_doc("Manufacturer", "MSG1") + for manufacturer in ["DFSS", "DASA", "ASAAS"]: + if not frappe.db.exists("Manufacturer", manufacturer): + m_doc = frappe.new_doc("Manufacturer") + m_doc.short_name = manufacturer + m_doc.insert() - template = frappe.get_doc( - dict( - doctype="Item", - item_code="_Test Variant Mfg", - has_variant=1, - item_group="Products", - variant_based_on="Manufacturer", - ) - ).insert() + self.assertFalse(frappe.db.exists("Item Manufacturer", {"manufacturer": "DFSS"})) + variant = get_variant(template, manufacturer="DFSS", manufacturer_part_no="DFSS-123") - manufacturer = frappe.get_doc(dict(doctype="Manufacturer", short_name="MSG1")).insert() + item_manufacturer = frappe.db.exists( + "Item Manufacturer", {"manufacturer": "DFSS", "item_code": variant.name} + ) + self.assertTrue(item_manufacturer) - variant = get_variant(template.name, manufacturer=manufacturer.name) - self.assertEqual(variant.item_code, "_Test Variant Mfg-1") - self.assertEqual(variant.description, "_Test Variant Mfg") - self.assertEqual(variant.manufacturer, "MSG1") - variant.insert() - - variant = get_variant(template.name, manufacturer=manufacturer.name, manufacturer_part_no="007") - self.assertEqual(variant.item_code, "_Test Variant Mfg-2") - self.assertEqual(variant.description, "_Test Variant Mfg") - self.assertEqual(variant.manufacturer, "MSG1") - self.assertEqual(variant.manufacturer_part_no, "007") + frappe.delete_doc("Item Manufacturer", item_manufacturer) def test_stock_exists_against_template_item(self): stock_item = frappe.get_all("Stock Ledger Entry", fields=["item_code"], limit=1) From 5e68b7e3a6cea0001ad1275300a019c0db9e8e13 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 19 Dec 2023 18:01:37 +0530 Subject: [PATCH 088/205] fix: on closed unreserved the production plan qty (backport #38848) (#38859) fix: on closed unreserved the production plan qty (#38848) (cherry picked from commit 2184e8ef58379f53ef8f1d069afa26e64796b073) Co-authored-by: rohitwaghchaure --- .../production_plan/production_plan.py | 4 ++ .../production_plan/test_production_plan.py | 41 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index c201c4f7be..4b72a83b05 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -583,6 +583,7 @@ class ProductionPlan(Document): if close: self.db_set("status", "Closed") + self.update_bin_qty() return if self.total_produced_qty > 0: @@ -597,6 +598,9 @@ class ProductionPlan(Document): if close is not None: self.db_set("status", self.status) + if self.docstatus == 1 and self.status != "Completed": + self.update_bin_qty() + def update_ordered_status(self): update_status = False for d in self.po_items: diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py index cc9d9a0311..f86725d601 100644 --- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py @@ -1458,6 +1458,47 @@ class TestProductionPlan(FrappeTestCase): self.assertEqual(row.get("uom"), "Nos") self.assertEqual(row.get("conversion_factor"), 10.0) + def test_unreserve_qty_on_closing_of_pp(self): + from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse + from erpnext.stock.utils import get_or_make_bin + + fg_item = make_item(properties={"is_stock_item": 1, "stock_uom": "_Test UOM 1"}).name + rm_item = make_item(properties={"is_stock_item": 1, "stock_uom": "_Test UOM 1"}).name + + store_warehouse = create_warehouse("Store Warehouse", company="_Test Company") + rm_warehouse = create_warehouse("RM Warehouse", company="_Test Company") + + make_bom(item=fg_item, raw_materials=[rm_item], source_warehouse="_Test Warehouse - _TC") + + pln = create_production_plan( + item_code=fg_item, planned_qty=10, stock_uom="_Test UOM 1", do_not_submit=1 + ) + + pln.for_warehouse = rm_warehouse + mr_items = get_items_for_material_requests(pln.as_dict()) + for d in mr_items: + pln.append("mr_items", d) + + pln.save() + pln.submit() + + bin_name = get_or_make_bin(rm_item, rm_warehouse) + before_qty = flt(frappe.db.get_value("Bin", bin_name, "reserved_qty_for_production_plan")) + + pln.reload() + pln.set_status(close=True) + + bin_name = get_or_make_bin(rm_item, rm_warehouse) + after_qty = flt(frappe.db.get_value("Bin", bin_name, "reserved_qty_for_production_plan")) + self.assertAlmostEqual(after_qty, before_qty - 10) + + pln.reload() + pln.set_status(close=False) + + bin_name = get_or_make_bin(rm_item, rm_warehouse) + after_qty = flt(frappe.db.get_value("Bin", bin_name, "reserved_qty_for_production_plan")) + self.assertAlmostEqual(after_qty, before_qty) + def create_production_plan(**args): """ From 4057682c878bd6abffa63e7343ba33bd220bc88c Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 19 Dec 2023 18:29:56 +0530 Subject: [PATCH 089/205] fix: incoming rate for sales return with Moving Average valuation method (backport #38849) (#38863) * fix: incoming rate for sales return with Moving Average valuation method (#38849) (cherry picked from commit 7fdac62393ee1e96969cca38a4ce0c07993dce7e) # Conflicts: # erpnext/stock/doctype/delivery_note/test_delivery_note.py * chore: fix conflicts --------- Co-authored-by: rohitwaghchaure --- erpnext/controllers/selling_controller.py | 8 +-- .../delivery_note/test_delivery_note.py | 50 +++++++++++++++++++ 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index e8bae8cda5..4489d60131 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -12,7 +12,7 @@ from erpnext.controllers.sales_and_purchase_return import get_rate_for_return from erpnext.controllers.stock_controller import StockController from erpnext.stock.doctype.item.item import set_item_default from erpnext.stock.get_item_details import get_bin_details, get_conversion_factor -from erpnext.stock.utils import get_incoming_rate +from erpnext.stock.utils import get_incoming_rate, get_valuation_method class SellingController(StockController): @@ -432,11 +432,13 @@ class SellingController(StockController): items = self.get("items") + (self.get("packed_items") or []) for d in items: - if not self.get("return_against"): + if not self.get("return_against") or ( + get_valuation_method(d.item_code) == "Moving Average" and self.get("is_return") + ): # Get incoming rate based on original item cost based on valuation method qty = flt(d.get("stock_qty") or d.get("actual_qty")) - if not (self.get("is_return") and d.incoming_rate): + if not d.incoming_rate: d.incoming_rate = get_incoming_rate( { "item_code": d.item_code, diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index 3a581226ca..da8ee022f9 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -1375,6 +1375,56 @@ class TestDeliveryNote(FrappeTestCase): dn.reload() self.assertEqual(frappe.db.get_value("Serial No", serial_no, "status"), "Delivered") + def test_sales_return_valuation_for_moving_average(self): + item_code = make_item( + "_Test Item Sales Return with MA", {"is_stock_item": 1, "valuation_method": "Moving Average"} + ).name + + make_stock_entry( + item_code=item_code, + target="_Test Warehouse - _TC", + qty=5, + basic_rate=100.0, + posting_date=add_days(nowdate(), -5), + ) + dn = create_delivery_note( + item_code=item_code, qty=5, rate=500, posting_date=add_days(nowdate(), -4) + ) + self.assertEqual(dn.items[0].incoming_rate, 100.0) + + make_stock_entry( + item_code=item_code, + target="_Test Warehouse - _TC", + qty=5, + basic_rate=200.0, + posting_date=add_days(nowdate(), -3), + ) + make_stock_entry( + item_code=item_code, + target="_Test Warehouse - _TC", + qty=5, + basic_rate=300.0, + posting_date=add_days(nowdate(), -2), + ) + + dn1 = create_delivery_note( + is_return=1, + item_code=item_code, + return_against=dn.name, + qty=-5, + rate=500, + company=dn.company, + expense_account="Cost of Goods Sold - _TC", + cost_center="Main - _TC", + do_not_submit=1, + posting_date=add_days(nowdate(), -1), + ) + + # (300 * 5) + (200 * 5) = 2500 + # 2500 / 10 = 250 + + self.assertAlmostEqual(dn1.items[0].incoming_rate, 250.0) + def create_delivery_note(**args): dn = frappe.new_doc("Delivery Note") From 793e3ad78e9c79800920e93b3eb95377fa155ea0 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 19 Dec 2023 18:31:18 +0530 Subject: [PATCH 090/205] fix: if not budget then don't validate (backport #38861) (#38864) fix: if not budget then don't validate (#38861) (cherry picked from commit d375164100158db9b974742caa3e05062c481d7d) Co-authored-by: rohitwaghchaure --- erpnext/stock/doctype/material_request/material_request.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index 3e90ed5a3b..ad9b34c9ac 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -169,7 +169,9 @@ class MaterialRequest(BuyingController): def on_submit(self): self.update_requested_qty_in_production_plan() self.update_requested_qty() - if self.material_request_type == "Purchase": + if self.material_request_type == "Purchase" and frappe.db.exists( + "Budget", {"applicable_on_material_request": 1, "docstatus": 1} + ): self.validate_budget() def before_save(self): From 6d5bdc6c68dfda915972f3747de752b8fad7cdb5 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 20 Dec 2023 12:30:10 +0530 Subject: [PATCH 091/205] fix: typerror on tree doctypes - Item Group, Customer Group, Supplier Group and Territory (#38870) * refactor: typerror on set_root_readonly * refactor: remove 'cur_frm' usage in supplier_group * refactor: remove 'cur_frm' usage in territory.js * refactor: remove 'cur_frm' from sales_person.js --- .../doctype/customer_group/customer_group.js | 29 +++++++++---------- .../doctype/sales_person/sales_person.js | 23 +++++++-------- .../doctype/supplier_group/supplier_group.js | 27 ++++++++--------- erpnext/setup/doctype/territory/territory.js | 27 +++++++++-------- 4 files changed, 48 insertions(+), 58 deletions(-) diff --git a/erpnext/setup/doctype/customer_group/customer_group.js b/erpnext/setup/doctype/customer_group/customer_group.js index 3c81b0283c..e3528189dc 100644 --- a/erpnext/setup/doctype/customer_group/customer_group.js +++ b/erpnext/setup/doctype/customer_group/customer_group.js @@ -1,21 +1,6 @@ // Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors // License: GNU General Public License v3. See license.txt - -cur_frm.cscript.refresh = function(doc, cdt, cdn) { - cur_frm.cscript.set_root_readonly(doc); -} - -cur_frm.cscript.set_root_readonly = function(doc) { - // read-only for root customer group - if(!doc.parent_customer_group && !doc.__islocal) { - cur_frm.set_read_only(); - cur_frm.set_intro(__("This is a root customer group and cannot be edited.")); - } else { - cur_frm.set_intro(null); - } -} - frappe.ui.form.on("Customer Group", { setup: function(frm){ frm.set_query('parent_customer_group', function (doc) { @@ -48,5 +33,17 @@ frappe.ui.form.on("Customer Group", { } } }); - } + }, + refresh: function(frm) { + frm.trigger("set_root_readonly"); + }, + set_root_readonly: function(frm) { + // read-only for root customer group + if(!frm.doc.parent_customer_group && !frm.doc.__islocal) { + frm.set_read_only(); + frm.set_intro(__("This is a root customer group and cannot be edited.")); + } else { + frm.set_intro(null); + } + }, }); diff --git a/erpnext/setup/doctype/sales_person/sales_person.js b/erpnext/setup/doctype/sales_person/sales_person.js index d86a8f3d98..f0d9aa87bc 100644 --- a/erpnext/setup/doctype/sales_person/sales_person.js +++ b/erpnext/setup/doctype/sales_person/sales_person.js @@ -11,6 +11,7 @@ frappe.ui.form.on('Sales Person', { frm.dashboard.add_indicator(__('Total Contribution Amount Against Invoices: {0}', [format_currency(info.allocated_amount_against_invoice, info.currency)]), 'blue'); } + frm.trigger("set_root_readonly"); }, setup: function(frm) { @@ -27,22 +28,18 @@ frappe.ui.form.on('Sales Person', { 'Sales Order': () => frappe.new_doc("Sales Order") .then(() => frm.add_child("sales_team", {"sales_person": frm.doc.name})) } + }, + set_root_readonly: function(frm) { + // read-only for root + if(!frm.doc.parent_sales_person && !frm.doc.__islocal) { + frm.set_read_only(); + frm.set_intro(__("This is a root sales person and cannot be edited.")); + } else { + frm.set_intro(null); + } } }); -cur_frm.cscript.refresh = function(doc, cdt, cdn) { - cur_frm.cscript.set_root_readonly(doc); -} - -cur_frm.cscript.set_root_readonly = function(doc) { - // read-only for root - if(!doc.parent_sales_person && !doc.__islocal) { - cur_frm.set_read_only(); - cur_frm.set_intro(__("This is a root sales person and cannot be edited.")); - } else { - cur_frm.set_intro(null); - } -} //get query select sales person cur_frm.fields_dict['parent_sales_person'].get_query = function(doc, cdt, cdn) { diff --git a/erpnext/setup/doctype/supplier_group/supplier_group.js b/erpnext/setup/doctype/supplier_group/supplier_group.js index 33629297ff..c697a99cb4 100644 --- a/erpnext/setup/doctype/supplier_group/supplier_group.js +++ b/erpnext/setup/doctype/supplier_group/supplier_group.js @@ -1,21 +1,6 @@ // Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors // For license information, please see license.txt -cur_frm.cscript.refresh = function(doc) { - cur_frm.set_intro(doc.__islocal ? "" : __("There is nothing to edit.")); - cur_frm.cscript.set_root_readonly(doc); -}; - -cur_frm.cscript.set_root_readonly = function(doc) { - // read-only for root customer group - if(!doc.parent_supplier_group && !doc.__islocal) { - cur_frm.set_read_only(); - cur_frm.set_intro(__("This is a root supplier group and cannot be edited.")); - } else { - cur_frm.set_intro(null); - } -}; - frappe.ui.form.on("Supplier Group", { setup: function(frm){ frm.set_query('parent_supplier_group', function (doc) { @@ -48,5 +33,17 @@ frappe.ui.form.on("Supplier Group", { } } }); + }, + refresh: function(frm) { + frm.set_intro(frm.doc.__islocal ? "" : __("There is nothing to edit.")); + frm.trigger("set_root_readonly"); + }, + set_root_readonly: function(frm) { + if(!frm.doc.parent_supplier_group && !frm.doc.__islocal) { + frm.trigger("set_read_only"); + frm.set_intro(__("This is a root supplier group and cannot be edited.")); + } else { + frm.set_intro(null); + } } }); diff --git a/erpnext/setup/doctype/territory/territory.js b/erpnext/setup/doctype/territory/territory.js index 3caf814c90..e11d20b7bf 100644 --- a/erpnext/setup/doctype/territory/territory.js +++ b/erpnext/setup/doctype/territory/territory.js @@ -11,23 +11,22 @@ frappe.ui.form.on("Territory", { } } }; + }, + refresh: function(frm) { + frm.trigger("set_root_readonly"); + }, + set_root_readonly: function(frm) { + // read-only for root territory + if(!frm.doc.parent_territory && !frm.doc.__islocal) { + frm.set_read_only(); + frm.set_intro(__("This is a root territory and cannot be edited.")); + } else { + frm.set_intro(null); + } } + }); -cur_frm.cscript.refresh = function(doc, cdt, cdn) { - cur_frm.cscript.set_root_readonly(doc); -} - -cur_frm.cscript.set_root_readonly = function(doc) { - // read-only for root territory - if(!doc.parent_territory && !doc.__islocal) { - cur_frm.set_read_only(); - cur_frm.set_intro(__("This is a root territory and cannot be edited.")); - } else { - cur_frm.set_intro(null); - } -} - //get query select territory cur_frm.fields_dict['parent_territory'].get_query = function(doc,cdt,cdn) { return{ From 9983283f95753e7523cf30cc258df0572f88081d Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Wed, 20 Dec 2023 13:16:09 +0530 Subject: [PATCH 092/205] perf: use estimated rows instead of actual rows (#38830) --- .../batch_wise_balance_history.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py b/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py index 176a21566a..7f2608e0fb 100644 --- a/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py +++ b/erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py @@ -4,7 +4,7 @@ import frappe from frappe import _ -from frappe.utils import cint, flt, getdate +from frappe.utils import cint, flt, get_table_name, getdate from frappe.utils.deprecations import deprecated from pypika import functions as fn @@ -13,11 +13,22 @@ from erpnext.stock.doctype.warehouse.warehouse import apply_warehouse_filter SLE_COUNT_LIMIT = 10_000 +def _estimate_table_row_count(doctype: str): + table = get_table_name(doctype) + return cint( + frappe.db.sql( + f"""select table_rows + from information_schema.tables + where table_name = '{table}' ;""" + )[0][0] + ) + + def execute(filters=None): if not filters: filters = {} - sle_count = frappe.db.count("Stock Ledger Entry") + sle_count = _estimate_table_row_count("Stock Ledger Entry") if sle_count > SLE_COUNT_LIMIT and not filters.get("item_code") and not filters.get("warehouse"): frappe.throw(_("Please select either the Item or Warehouse filter to generate the report.")) From ae353398d96746e9e89640b586d1bbd6afbbce77 Mon Sep 17 00:00:00 2001 From: NIYAZ RAZAK <76736615+niyazrazak@users.noreply.github.com> Date: Wed, 20 Dec 2023 12:04:38 +0300 Subject: [PATCH 093/205] fix: local reference error in BOM (#38850) fix: local reference error --- erpnext/manufacturing/doctype/bom/bom.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index f0381d2cef..762747645b 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -1017,6 +1017,8 @@ def get_bom_item_rate(args, bom_doc): item_doc = frappe.get_cached_doc("Item", args.get("item_code")) price_list_data = get_price_list_rate(bom_args, item_doc) rate = price_list_data.price_list_rate + elif bom_doc.rm_cost_as_per == "Manual": + return return flt(rate) From 9a00edb03115b72afb4274e6fcf2dc7d5b431657 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 20 Dec 2023 17:22:30 +0530 Subject: [PATCH 094/205] fix: incorrect price list in customer-wise item price report --- .../customer_wise_item_price.py | 50 +++++++++++++++++-- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py b/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py index a58f40362b..40aa9acc3c 100644 --- a/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py +++ b/erpnext/selling/report/customer_wise_item_price/customer_wise_item_price.py @@ -3,11 +3,11 @@ import frappe -from frappe import _ +from frappe import _, qb +from frappe.query_builder import Criterion from erpnext import get_default_company from erpnext.accounts.party import get_party_details -from erpnext.stock.get_item_details import get_price_list_rate_for def execute(filters=None): @@ -50,6 +50,42 @@ def get_columns(filters=None): ] +def fetch_item_prices( + customer: str = None, price_list: str = None, selling_price_list: str = None, items: list = None +): + price_list_map = frappe._dict() + ip = qb.DocType("Item Price") + and_conditions = [] + or_conditions = [] + if items: + and_conditions.append(ip.item_code.isin([x.item_code for x in items])) + and_conditions.append(ip.selling == True) + + or_conditions.append(ip.customer == None) + or_conditions.append(ip.price_list == None) + + if customer: + or_conditions.append(ip.customer == customer) + + if price_list: + or_conditions.append(ip.price_list == price_list) + + if selling_price_list: + or_conditions.append(ip.price_list == selling_price_list) + + res = ( + qb.from_(ip) + .select(ip.item_code, ip.price_list, ip.price_list_rate) + .where(Criterion.all(and_conditions)) + .where(Criterion.any(or_conditions)) + .run(as_dict=True) + ) + for x in res: + price_list_map.update({(x.item_code, x.price_list): x.price_list_rate}) + + return price_list_map + + def get_data(filters=None): data = [] customer_details = get_customer_details(filters) @@ -59,9 +95,17 @@ def get_data(filters=None): "Bin", fields=["item_code", "sum(actual_qty) AS available"], group_by="item_code" ) item_stock_map = {item.item_code: item.available for item in item_stock_map} + price_list_map = fetch_item_prices( + customer_details.customer, + customer_details.price_list, + customer_details.selling_price_list, + items, + ) for item in items: - price_list_rate = get_price_list_rate_for(customer_details, item.item_code) or 0.0 + price_list_rate = price_list_map.get( + (item.item_code, customer_details.price_list or customer_details.selling_price_list), 0.0 + ) available_stock = item_stock_map.get(item.item_code) data.append( From a6ab53236e08cb57fc8a45496ee4c9ccfbc53e10 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 20 Dec 2023 18:33:26 +0530 Subject: [PATCH 095/205] fix: allow to set rate manually for service item in BOM (backport #38880) (#38882) fix: allow to set rate manually for service item in BOM (#38880) (cherry picked from commit c2f692a4e4f3dd5089fe4949c6cd74574282fdb1) Co-authored-by: rohitwaghchaure --- erpnext/manufacturing/doctype/bom/bom.py | 3 ++ erpnext/manufacturing/doctype/bom/test_bom.py | 29 +++++++++++++++++++ .../doctype/bom_item/bom_item.json | 13 +++++++-- erpnext/patches.txt | 1 + .../v14_0/set_maintain_stock_for_bom_item.py | 19 ++++++++++++ 5 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 erpnext/patches/v14_0/set_maintain_stock_for_bom_item.py diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 762747645b..d86b6d426e 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -744,6 +744,9 @@ class BOM(WebsiteGenerator): base_total_rm_cost = 0 for d in self.get("items"): + if not d.is_stock_item and self.rm_cost_as_per == "Valuation Rate": + continue + old_rate = d.rate if self.rm_cost_as_per != "Manual": d.rate = self.get_rm_rate( diff --git a/erpnext/manufacturing/doctype/bom/test_bom.py b/erpnext/manufacturing/doctype/bom/test_bom.py index 051b475bcc..2debf9191e 100644 --- a/erpnext/manufacturing/doctype/bom/test_bom.py +++ b/erpnext/manufacturing/doctype/bom/test_bom.py @@ -698,6 +698,35 @@ class TestBOM(FrappeTestCase): bom.update_cost() self.assertFalse(bom.flags.cost_updated) + def test_bom_with_service_item_cost(self): + from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry + + rm_item = make_item(properties={"is_stock_item": 1, "valuation_rate": 1000.0}).name + + service_item = make_item(properties={"is_stock_item": 0}).name + + fg_item = make_item(properties={"is_stock_item": 1}).name + + from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom + + bom = make_bom(item=fg_item, raw_materials=[rm_item, service_item], do_not_save=True) + bom.rm_cost_as_per = "Valuation Rate" + + for row in bom.items: + if row.item_code == service_item: + row.rate = 566.00 + else: + row.rate = 800.00 + + bom.save() + + for row in bom.items: + if row.item_code == service_item: + self.assertEqual(row.is_stock_item, 0) + self.assertEqual(row.rate, 566.00) + else: + self.assertEqual(row.is_stock_item, 1) + def test_do_not_include_manufacturing_and_fixed_items(self): from erpnext.manufacturing.doctype.bom.bom import item_query diff --git a/erpnext/manufacturing/doctype/bom_item/bom_item.json b/erpnext/manufacturing/doctype/bom_item/bom_item.json index cb58af1f29..dfd6612098 100644 --- a/erpnext/manufacturing/doctype/bom_item/bom_item.json +++ b/erpnext/manufacturing/doctype/bom_item/bom_item.json @@ -14,6 +14,7 @@ "bom_no", "source_warehouse", "allow_alternative_item", + "is_stock_item", "section_break_5", "description", "col_break1", @@ -185,7 +186,7 @@ "in_list_view": 1, "label": "Rate", "options": "currency", - "read_only": 1, + "read_only_depends_on": "eval:doc.is_stock_item == 1", "reqd": 1 }, { @@ -284,13 +285,21 @@ "fieldname": "do_not_explode", "fieldtype": "Check", "label": "Do Not Explode" + }, + { + "default": "0", + "fetch_from": "item_code.is_stock_item", + "fieldname": "is_stock_item", + "fieldtype": "Check", + "label": "Is Stock Item", + "read_only": 1 } ], "idx": 1, "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2023-11-14 18:35:51.378513", + "modified": "2023-12-20 16:21:55.477883", "modified_by": "Administrator", "module": "Manufacturing", "name": "BOM Item", diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 56f6347693..d5cd4da77a 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -355,3 +355,4 @@ execute:frappe.db.set_default("date_format", frappe.db.get_single_value("System # below migration patch should always run last erpnext.patches.v14_0.migrate_gl_to_payment_ledger erpnext.stock.doctype.delivery_note.patches.drop_unused_return_against_index +erpnext.patches.v14_0.set_maintain_stock_for_bom_item \ No newline at end of file diff --git a/erpnext/patches/v14_0/set_maintain_stock_for_bom_item.py b/erpnext/patches/v14_0/set_maintain_stock_for_bom_item.py new file mode 100644 index 0000000000..f0b618f32d --- /dev/null +++ b/erpnext/patches/v14_0/set_maintain_stock_for_bom_item.py @@ -0,0 +1,19 @@ +import frappe + + +def execute(): + if not frappe.db.exists("BOM", {"docstatus": 1}): + return + + # Added is_stock_item to handle Read Only based on condition for the rate field + frappe.db.sql( + """ + UPDATE + `tabBOM Item` boi, + `tabItem` i + SET + boi.is_stock_item = i.is_stock_item + WHERE + boi.item_code = i.name + """ + ) From d370c60a6c840be23ec4094593b9bbf1d1dca88b Mon Sep 17 00:00:00 2001 From: Anand Baburajan Date: Wed, 20 Dec 2023 19:02:32 +0530 Subject: [PATCH 096/205] feat: total_asset_cost field (#38879) --- erpnext/assets/doctype/asset/asset.json | 11 ++++++++++- erpnext/assets/doctype/asset/asset.py | 1 + .../assets/doctype/asset_repair/asset_repair.py | 6 ++++++ erpnext/patches.txt | 1 + .../v14_0/update_total_asset_cost_field.py | 17 +++++++++++++++++ 5 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 erpnext/patches/v14_0/update_total_asset_cost_field.py diff --git a/erpnext/assets/doctype/asset/asset.json b/erpnext/assets/doctype/asset/asset.json index 540a4f5549..ea72b3cf84 100644 --- a/erpnext/assets/doctype/asset/asset.json +++ b/erpnext/assets/doctype/asset/asset.json @@ -35,6 +35,7 @@ "purchase_receipt", "purchase_invoice", "available_for_use_date", + "total_asset_cost", "column_break_23", "gross_purchase_amount", "asset_quantity", @@ -529,6 +530,14 @@ "label": "Capitalized In", "options": "Asset Capitalization", "read_only": 1 + }, + { + "depends_on": "eval:doc.docstatus > 0", + "fieldname": "total_asset_cost", + "fieldtype": "Currency", + "label": "Total Asset Cost", + "options": "Company:company:default_currency", + "read_only": 1 } ], "idx": 72, @@ -572,7 +581,7 @@ "link_fieldname": "target_asset" } ], - "modified": "2023-11-20 20:57:37.010467", + "modified": "2023-12-20 16:50:21.128595", "modified_by": "Administrator", "module": "Assets", "name": "Asset", diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 3b3ed0ac75..3ea6ec7c4d 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -111,6 +111,7 @@ class Asset(AccountsController): "Decapitalized", ] supplier: DF.Link | None + total_asset_cost: DF.Currency total_number_of_depreciations: DF.Int value_after_depreciation: DF.Currency # end: auto-generated types diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.py b/erpnext/assets/doctype/asset_repair/asset_repair.py index 31dd63d2f8..b7fce91b1d 100644 --- a/erpnext/assets/doctype/asset_repair/asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/asset_repair.py @@ -93,6 +93,9 @@ class AssetRepair(AccountsController): self.increase_asset_value() + if self.capitalize_repair_cost: + self.asset_doc.total_asset_cost += self.repair_cost + if self.get("stock_consumption"): self.check_for_stock_items_and_warehouse() self.decrease_stock_quantity() @@ -128,6 +131,9 @@ class AssetRepair(AccountsController): self.decrease_asset_value() + if self.capitalize_repair_cost: + self.asset_doc.total_asset_cost -= self.repair_cost + if self.get("stock_consumption"): self.increase_stock_quantity() if self.get("capitalize_repair_cost"): diff --git a/erpnext/patches.txt b/erpnext/patches.txt index d5cd4da77a..952875c293 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -352,6 +352,7 @@ erpnext.patches.v14_0.create_accounting_dimensions_in_supplier_quotation erpnext.patches.v14_0.update_zero_asset_quantity_field execute:frappe.db.set_single_value("Buying Settings", "project_update_frequency", "Each Transaction") execute:frappe.db.set_default("date_format", frappe.db.get_single_value("System Settings", "date_format")) +erpnext.patches.v14_0.update_total_asset_cost_field # below migration patch should always run last erpnext.patches.v14_0.migrate_gl_to_payment_ledger erpnext.stock.doctype.delivery_note.patches.drop_unused_return_against_index diff --git a/erpnext/patches/v14_0/update_total_asset_cost_field.py b/erpnext/patches/v14_0/update_total_asset_cost_field.py new file mode 100644 index 0000000000..57cf71b613 --- /dev/null +++ b/erpnext/patches/v14_0/update_total_asset_cost_field.py @@ -0,0 +1,17 @@ +import frappe + + +def execute(): + asset = frappe.qb.DocType("Asset") + frappe.qb.update(asset).set(asset.total_asset_cost, asset.gross_purchase_amount).run() + + asset_repair_list = frappe.db.get_all( + "Asset Repair", + filters={"docstatus": 1, "repair_status": "Completed", "capitalize_repair_cost": 1}, + fields=["asset", "repair_cost"], + ) + + for asset_repair in asset_repair_list: + frappe.qb.update(asset).set( + asset.total_asset_cost, asset.total_asset_cost + asset_repair.repair_cost + ).where(asset.name == asset_repair.asset).run() From 6a0a08b59c5b1eadbfdc657a131531d0e7461b11 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 21 Dec 2023 12:13:33 +0530 Subject: [PATCH 097/205] fix: typeerror on pos order summary to new order screen --- erpnext/selling/page/point_of_sale/pos_item_cart.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/selling/page/point_of_sale/pos_item_cart.js b/erpnext/selling/page/point_of_sale/pos_item_cart.js index 193048f676..bd8579203c 100644 --- a/erpnext/selling/page/point_of_sale/pos_item_cart.js +++ b/erpnext/selling/page/point_of_sale/pos_item_cart.js @@ -520,7 +520,7 @@ erpnext.PointOfSale.ItemCart = class { } render_taxes(taxes) { - if (taxes.length) { + if (taxes && taxes.length) { const currency = this.events.get_frm().doc.currency; const taxes_html = taxes.map(t => { if (t.tax_amount_after_discount_amount == 0.0) return; From 61219ca4ce069421d909f8e170672f791e9c478d Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 21 Dec 2023 14:23:08 +0530 Subject: [PATCH 098/205] fix: do not reset the basic rate for the material receipt stock entry (backport #38896) (#38898) fix: do not reset the basic rate for the material receipt stock entry (#38896) (cherry picked from commit 98bfcc4c758b61f714c53ea0f00246731a30fdaf) Co-authored-by: rohitwaghchaure --- erpnext/stock/doctype/stock_entry/stock_entry.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index 7af5d1aa37..8da3e8fdd0 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -512,7 +512,12 @@ frappe.ui.form.on('Stock Entry', { }, callback: function(r) { if (!r.exc) { - ["actual_qty", "basic_rate"].forEach((field) => { + let fields = ["actual_qty", "basic_rate"]; + if (frm.doc.purpose == "Material Receipt") { + fields = ["actual_qty"]; + } + + fields.forEach((field) => { frappe.model.set_value(cdt, cdn, field, (r.message[field] || 0.0)); }); frm.events.calculate_basic_amount(frm, child); From 07175367d8158355e5f699c7c66a2a6743a85c29 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 21 Dec 2023 14:40:52 +0530 Subject: [PATCH 099/205] =?UTF-8?q?fix:=20reposting=20not=20fixing=20valua?= =?UTF-8?q?tion=20rate=20for=20sales=20return=20using=20movin=E2=80=A6=20(?= =?UTF-8?q?backport=20#38895)=20(#38897)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: reposting not fixing valuation rate for sales return using movin… (#38895) fix: reposting not fixing valuation rate for sales return using moving average method (cherry picked from commit 3a668bbe9694fdd6e8265869c6943e42f889ac41) # Conflicts: # erpnext/stock/stock_ledger.py * chore: fix conflicts --------- Co-authored-by: rohitwaghchaure --- erpnext/controllers/selling_controller.py | 4 +- .../delivery_note/test_delivery_note.py | 53 +++++++++++++++++++ erpnext/stock/stock_ledger.py | 34 +++++++++--- 3 files changed, 83 insertions(+), 8 deletions(-) diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index 4489d60131..919e459c9e 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -438,7 +438,9 @@ class SellingController(StockController): # Get incoming rate based on original item cost based on valuation method qty = flt(d.get("stock_qty") or d.get("actual_qty")) - if not d.incoming_rate: + if not d.incoming_rate or ( + get_valuation_method(d.item_code) == "Moving Average" and self.get("is_return") + ): d.incoming_rate = get_incoming_rate( { "item_code": d.item_code, diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index da8ee022f9..933be53b07 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -1425,6 +1425,59 @@ class TestDeliveryNote(FrappeTestCase): self.assertAlmostEqual(dn1.items[0].incoming_rate, 250.0) + def test_sales_return_valuation_for_moving_average_case2(self): + # Make DN return + # Make Bakcdated Purchase Receipt and check DN return valuation rate + # The rate should be recalculate based on the backdated purchase receipt + frappe.flags.print_debug_messages = False + item_code = make_item( + "_Test Item Sales Return with MA Case2", + {"is_stock_item": 1, "valuation_method": "Moving Average", "stock_uom": "Nos"}, + ).name + + make_stock_entry( + item_code=item_code, + target="_Test Warehouse - _TC", + qty=5, + basic_rate=100.0, + posting_date=add_days(nowdate(), -5), + ) + + dn = create_delivery_note( + item_code=item_code, + warehouse="_Test Warehouse - _TC", + qty=5, + rate=500, + posting_date=add_days(nowdate(), -4), + ) + + returned_dn = create_delivery_note( + is_return=1, + item_code=item_code, + return_against=dn.name, + qty=-5, + rate=500, + company=dn.company, + warehouse="_Test Warehouse - _TC", + expense_account="Cost of Goods Sold - _TC", + cost_center="Main - _TC", + posting_date=add_days(nowdate(), -1), + ) + + self.assertAlmostEqual(returned_dn.items[0].incoming_rate, 100.0) + + # Make backdated purchase receipt + make_stock_entry( + item_code=item_code, + target="_Test Warehouse - _TC", + qty=5, + basic_rate=200.0, + posting_date=add_days(nowdate(), -3), + ) + + returned_dn.reload() + self.assertAlmostEqual(returned_dn.items[0].incoming_rate, 200.0) + def create_delivery_note(**args): dn = frappe.new_doc("Delivery Note") diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index 9203f4570a..a6206ac8dc 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -25,6 +25,7 @@ from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry impor ) from erpnext.stock.utils import ( get_incoming_outgoing_rate_for_cancel, + get_incoming_rate, get_or_make_bin, get_stock_balance, get_valuation_method, @@ -841,14 +842,33 @@ class update_entries_after(object): get_rate_for_return, # don't move this import to top ) - rate = get_rate_for_return( - sle.voucher_type, - sle.voucher_no, - sle.item_code, - voucher_detail_no=sle.voucher_detail_no, - sle=sle, - ) + if self.valuation_method == "Moving Average": + rate = get_incoming_rate( + { + "item_code": sle.item_code, + "warehouse": sle.warehouse, + "posting_date": sle.posting_date, + "posting_time": sle.posting_time, + "qty": sle.actual_qty, + "serial_no": sle.get("serial_no"), + "batch_no": sle.get("batch_no"), + "serial_and_batch_bundle": sle.get("serial_and_batch_bundle"), + "company": sle.company, + "voucher_type": sle.voucher_type, + "voucher_no": sle.voucher_no, + "allow_zero_valuation": self.allow_zero_rate, + "sle": sle.name, + } + ) + else: + rate = get_rate_for_return( + sle.voucher_type, + sle.voucher_no, + sle.item_code, + voucher_detail_no=sle.voucher_detail_no, + sle=sle, + ) elif ( sle.voucher_type in ["Purchase Receipt", "Purchase Invoice"] and sle.voucher_detail_no From 283763dfb2affa6a0b7bb29e19123c3e1fb27f30 Mon Sep 17 00:00:00 2001 From: Anand Baburajan Date: Thu, 21 Dec 2023 16:52:25 +0530 Subject: [PATCH 100/205] chore: additional_asset_cost field (#38904) --- erpnext/assets/doctype/asset/asset.json | 11 ++++++++++- erpnext/assets/doctype/asset/asset.py | 2 ++ erpnext/assets/doctype/asset_repair/asset_repair.py | 2 ++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/erpnext/assets/doctype/asset/asset.json b/erpnext/assets/doctype/asset/asset.json index ea72b3cf84..ac712d4431 100644 --- a/erpnext/assets/doctype/asset/asset.json +++ b/erpnext/assets/doctype/asset/asset.json @@ -36,6 +36,7 @@ "purchase_invoice", "available_for_use_date", "total_asset_cost", + "additional_asset_cost", "column_break_23", "gross_purchase_amount", "asset_quantity", @@ -538,6 +539,14 @@ "label": "Total Asset Cost", "options": "Company:company:default_currency", "read_only": 1 + }, + { + "depends_on": "eval:doc.docstatus > 0", + "fieldname": "additional_asset_cost", + "fieldtype": "Currency", + "label": "Additional Asset Cost", + "options": "Company:company:default_currency", + "read_only": 1 } ], "idx": 72, @@ -581,7 +590,7 @@ "link_fieldname": "target_asset" } ], - "modified": "2023-12-20 16:50:21.128595", + "modified": "2023-12-21 16:46:20.732869", "modified_by": "Administrator", "module": "Assets", "name": "Asset", diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 3ea6ec7c4d..dd34189391 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -50,6 +50,7 @@ class Asset(AccountsController): from erpnext.assets.doctype.asset_finance_book.asset_finance_book import AssetFinanceBook + additional_asset_cost: DF.Currency amended_from: DF.Link | None asset_category: DF.Link | None asset_name: DF.Data @@ -145,6 +146,7 @@ class Asset(AccountsController): ).format(asset_depr_schedules_links) ) + self.total_asset_cost = self.gross_purchase_amount self.status = self.get_status() def on_submit(self): diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.py b/erpnext/assets/doctype/asset_repair/asset_repair.py index b7fce91b1d..bb627d408c 100644 --- a/erpnext/assets/doctype/asset_repair/asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/asset_repair.py @@ -95,6 +95,7 @@ class AssetRepair(AccountsController): if self.capitalize_repair_cost: self.asset_doc.total_asset_cost += self.repair_cost + self.asset_doc.additional_asset_cost += self.repair_cost if self.get("stock_consumption"): self.check_for_stock_items_and_warehouse() @@ -133,6 +134,7 @@ class AssetRepair(AccountsController): if self.capitalize_repair_cost: self.asset_doc.total_asset_cost -= self.repair_cost + self.asset_doc.additional_asset_cost -= self.repair_cost if self.get("stock_consumption"): self.increase_stock_quantity() From 787333896c3710d16b1fa72432db0fe59c74dfa8 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Thu, 21 Dec 2023 20:09:10 +0530 Subject: [PATCH 101/205] perf: Drop unused/duplicate/sub-optimal indexes (#38884) * ci: enable more checks * perf: Drop unused/duplicate indexes --- .pre-commit-config.yaml | 6 +++- .../accounts/doctype/gl_entry/gl_entry.json | 8 ++---- .../purchase_invoice/purchase_invoice.py | 4 --- .../doctype/sales_invoice/sales_invoice.py | 4 --- .../purchase_order_item.json | 3 +- erpnext/patches.txt | 4 +-- erpnext/stock/doctype/bin/bin.json | 3 +- .../drop_unused_return_against_index.py | 28 +++++++++++++------ erpnext/tests/test_perf.py | 24 ++++++++++++++++ 9 files changed, 56 insertions(+), 28 deletions(-) create mode 100644 erpnext/tests/test_perf.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 30be903ae8..6ea121f298 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ fail_fast: false repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.0.1 + rev: v4.3.0 hooks: - id: trailing-whitespace files: "erpnext.*" @@ -15,6 +15,10 @@ repos: args: ['--branch', 'develop'] - id: check-merge-conflict - id: check-ast + - id: check-json + - id: check-toml + - id: check-yaml + - id: debug-statements - repo: https://github.com/pre-commit/mirrors-eslint rev: v8.44.0 diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.json b/erpnext/accounts/doctype/gl_entry/gl_entry.json index 16df40f435..c4492be367 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.json +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.json @@ -158,8 +158,7 @@ "label": "Against Voucher Type", "oldfieldname": "against_voucher_type", "oldfieldtype": "Data", - "options": "DocType", - "search_index": 1 + "options": "DocType" }, { "fieldname": "against_voucher", @@ -178,8 +177,7 @@ "label": "Voucher Type", "oldfieldname": "voucher_type", "oldfieldtype": "Select", - "options": "DocType", - "search_index": 1 + "options": "DocType" }, { "fieldname": "voucher_no", @@ -337,4 +335,4 @@ "sort_field": "modified", "sort_order": "DESC", "states": [] -} \ No newline at end of file +} diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 931b48d905..f40824dff4 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -1858,10 +1858,6 @@ def make_inter_company_sales_invoice(source_name, target_doc=None): return make_inter_company_transaction("Purchase Invoice", source_name, target_doc) -def on_doctype_update(): - frappe.db.add_index("Purchase Invoice", ["supplier", "is_return", "return_against"]) - - @frappe.whitelist() def make_purchase_receipt(source_name, target_doc=None): def update_item(obj, target, source_parent): diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index c0228e6b0b..2cddb863c6 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -2575,10 +2575,6 @@ def get_loyalty_programs(customer): return lp_details -def on_doctype_update(): - frappe.db.add_index("Sales Invoice", ["customer", "is_return", "return_against"]) - - @frappe.whitelist() def create_invoice_discounting(source_name, target_doc=None): invoice = frappe.get_doc("Sales Invoice", source_name) diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json index 98c1b388c1..5a24cc2e92 100644 --- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json +++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json @@ -123,8 +123,7 @@ "oldfieldname": "item_code", "oldfieldtype": "Link", "options": "Item", - "reqd": 1, - "search_index": 1 + "reqd": 1 }, { "fieldname": "supplier_part_no", diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 952875c293..7ade21df60 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -355,5 +355,5 @@ execute:frappe.db.set_default("date_format", frappe.db.get_single_value("System erpnext.patches.v14_0.update_total_asset_cost_field # below migration patch should always run last erpnext.patches.v14_0.migrate_gl_to_payment_ledger -erpnext.stock.doctype.delivery_note.patches.drop_unused_return_against_index -erpnext.patches.v14_0.set_maintain_stock_for_bom_item \ No newline at end of file +erpnext.stock.doctype.delivery_note.patches.drop_unused_return_against_index # 2023-12-20 +erpnext.patches.v14_0.set_maintain_stock_for_bom_item diff --git a/erpnext/stock/doctype/bin/bin.json b/erpnext/stock/doctype/bin/bin.json index 312470d50e..10d9511357 100644 --- a/erpnext/stock/doctype/bin/bin.json +++ b/erpnext/stock/doctype/bin/bin.json @@ -52,8 +52,7 @@ "oldfieldtype": "Link", "options": "Item", "read_only": 1, - "reqd": 1, - "search_index": 1 + "reqd": 1 }, { "default": "0.00", diff --git a/erpnext/stock/doctype/delivery_note/patches/drop_unused_return_against_index.py b/erpnext/stock/doctype/delivery_note/patches/drop_unused_return_against_index.py index 8fe4ffb58f..cc29e67fa7 100644 --- a/erpnext/stock/doctype/delivery_note/patches/drop_unused_return_against_index.py +++ b/erpnext/stock/doctype/delivery_note/patches/drop_unused_return_against_index.py @@ -1,15 +1,27 @@ +import click import frappe +UNUSED_INDEXES = [ + ("Delivery Note", ["customer", "is_return", "return_against"]), + ("Sales Invoice", ["customer", "is_return", "return_against"]), + ("Purchase Invoice", ["supplier", "is_return", "return_against"]), + ("Purchase Receipt", ["supplier", "is_return", "return_against"]), +] + def execute(): - """Drop unused return_against index""" + for doctype, index_fields in UNUSED_INDEXES: + table = f"tab{doctype}" + index_name = frappe.db.get_index_name(index_fields) + drop_index_if_exists(table, index_name) + + +def drop_index_if_exists(table: str, index: str): + if not frappe.db.has_index(table, index): + return try: - frappe.db.sql_ddl( - "ALTER TABLE `tabDelivery Note` DROP INDEX `customer_is_return_return_against_index`" - ) - frappe.db.sql_ddl( - "ALTER TABLE `tabPurchase Receipt` DROP INDEX `supplier_is_return_return_against_index`" - ) + frappe.db.sql_ddl(f"ALTER TABLE `{table}` DROP INDEX `{index}`") + click.echo(f"✓ dropped {index} index from {table}") except Exception: - frappe.log_error("Failed to drop unused index") + frappe.log_error("Failed to drop index") diff --git a/erpnext/tests/test_perf.py b/erpnext/tests/test_perf.py new file mode 100644 index 0000000000..fc17b1dcbd --- /dev/null +++ b/erpnext/tests/test_perf.py @@ -0,0 +1,24 @@ +import frappe +from frappe.tests.utils import FrappeTestCase + +INDEXED_FIELDS = { + "Bin": ["item_code"], + "GL Entry": ["voucher_type", "against_voucher_type"], + "Purchase Order Item": ["item_code"], + "Stock Ledger Entry": ["warehouse"], +} + + +class TestPerformance(FrappeTestCase): + def test_ensure_indexes(self): + # These fields are not explicitly indexed BUT they are prefix in some + # other composite index. If those are removed this test should be + # updated accordingly. + for doctype, fields in INDEXED_FIELDS.items(): + for field in fields: + self.assertTrue( + frappe.db.sql( + f"""SHOW INDEX FROM `tab{doctype}` + WHERE Column_name = "{field}" AND Seq_in_index = 1""" + ) + ) From 2dc49c834a0cab620465fafa555d239092107864 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Fri, 22 Dec 2023 07:36:27 +0530 Subject: [PATCH 102/205] chore: fixup broken JSON files (#38915) --- .../unverified/at_austria_chart_template.json | 69 ++++--- .../doctype/journal_entry/test_records.json | 187 +++++++++--------- erpnext/setup/demo_data/journal_entry.json | 30 +-- 3 files changed, 141 insertions(+), 145 deletions(-) diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/unverified/at_austria_chart_template.json b/erpnext/accounts/doctype/account/chart_of_accounts/unverified/at_austria_chart_template.json index 58d67beb67..bd7228ec41 100644 --- a/erpnext/accounts/doctype/account/chart_of_accounts/unverified/at_austria_chart_template.json +++ b/erpnext/accounts/doctype/account/chart_of_accounts/unverified/at_austria_chart_template.json @@ -26,7 +26,7 @@ "0360 Bauliche Investitionen in fremden (gepachteten) Betriebs- und Geschäftsgebäuden": {"account_type": "Fixed Asset"}, "0370 Bauliche Investitionen in fremden (gepachteten) Wohn- und Sozialgebäuden": {"account_type": "Fixed Asset"}, "0390 Kumulierte Abschreibungen zu Grundstücken ": {"account_type": "Fixed Asset"}, - "0400 Maschinen und Geräte ": {"account_type": "Fixed Asset"}, + "0400 Maschinen und Geräte ": {"account_type": "Fixed Asset"}, "0500 Maschinenwerkzeuge ": {"account_type": "Fixed Asset"}, "0510 Allgemeine Werkzeuge und Handwerkzeuge ": {"account_type": "Fixed Asset"}, "0520 Prototypen, Formen, Modelle ": {"account_type": "Fixed Asset"}, @@ -65,42 +65,41 @@ "0980 Geleistete Anzahlungen auf Finanzanlagen ": {"account_type": "Fixed Asset"}, "0990 Kumulierte Abschreibungen zu Finanzanlagen ": {"account_type": "Fixed Asset"}, "root_type": "Asset" - }, + }, "Klasse 1 Aktiva: Vorr\u00e4te": { "1000 Bezugsverrechnung": {"account_type": "Stock"}, "1100 Rohstoffe": {"account_type": "Stock"}, "1200 Bezogene Teile": {"account_type": "Stock"}, "1300 Hilfsstoffe": {"account_type": "Stock"}, "1350 Betriebsstoffe": {"account_type": "Stock"}, - "1360 Vorrat Energietraeger": {"account_type": "Stock"}, + "1360 Vorrat Energietraeger": {"account_type": "Stock"}, "1400 Unfertige Erzeugnisse": {"account_type": "Stock"}, "1500 Fertige Erzeugnisse": {"account_type": "Stock"}, "1600 Handelswarenvorrat": {"account_type": "Stock Received But Not Billed"}, "1700 Noch nicht abrechenbare Leistungen": {"account_type": "Stock"}, - "1900 Wertberichtigungen": {"account_type": "Stock"}, "1800 Geleistete Anzahlungen": {"account_type": "Stock"}, "1900 Wertberichtigungen": {"account_type": "Stock"}, "root_type": "Asset" - }, + }, "Klasse 3 Passiva: Verbindlichkeiten": { "3000 Allgemeine Verbindlichkeiten (Schuld)": {"account_type": "Payable"}, "3010 R\u00fcckstellungen f\u00fcr Pensionen": {"account_type": "Payable"}, "3020 Steuerr\u00fcckstellungen": {"account_type": "Tax"}, - "3041 Sonstige R\u00fcckstellungen": {"account_type": "Payable"}, + "3041 Sonstige R\u00fcckstellungen": {"account_type": "Payable"}, "3110 Verbindlichkeiten gegen\u00fcber Bank": {"account_type": "Payable"}, "3150 Verbindlichkeiten Darlehen": {"account_type": "Payable"}, - "3185 Verbindlichkeiten Kreditkarte": {"account_type": "Payable"}, + "3185 Verbindlichkeiten Kreditkarte": {"account_type": "Payable"}, "3380 Verbindlichkeiten aus der Annahme gezogener Wechsel u. d. Ausstellungen eigener Wechsel": { "account_type": "Payable" }, "3400 Verbindlichkeiten gegen\u00fc. verb. Untern., Verbindl. gegen\u00fc. Untern., mit denen eine Beteiligungsverh\u00e4lnis besteht": {}, "3460 Verbindlichkeiten gegenueber Gesellschaftern": {"account_type": "Payable"}, "3470 Einlagen stiller Gesellschafter": {"account_type": "Payable"}, - "3585 Verbindlichkeiten Lohnsteuer": {"account_type": "Tax"}, - "3590 Verbindlichkeiten Kommunalabgaben": {"account_type": "Tax"}, - "3595 Verbindlichkeiten Dienstgeberbeitrag": {"account_type": "Tax"}, + "3585 Verbindlichkeiten Lohnsteuer": {"account_type": "Tax"}, + "3590 Verbindlichkeiten Kommunalabgaben": {"account_type": "Tax"}, + "3595 Verbindlichkeiten Dienstgeberbeitrag": {"account_type": "Tax"}, "3600 Verbindlichkeiten Sozialversicherung": {"account_type": "Payable"}, - "3640 Verbindlichkeiten Loehne und Gehaelter": {"account_type": "Payable"}, + "3640 Verbindlichkeiten Loehne und Gehaelter": {"account_type": "Payable"}, "3700 Sonstige Verbindlichkeiten": {"account_type": "Payable"}, "3900 Passive Rechnungsabgrenzungsposten": {"account_type": "Payable"}, "3100 Anleihen (einschlie\u00dflich konvertibler)": {"account_type": "Payable"}, @@ -119,13 +118,13 @@ }, "3515 Umsatzsteuer Inland 10%": { "account_type": "Tax" - }, + }, "3520 Umsatzsteuer aus i.g. Erwerb 20%": { "account_type": "Tax" }, "3525 Umsatzsteuer aus i.g. Erwerb 10%": { "account_type": "Tax" - }, + }, "3560 Umsatzsteuer-Evidenzkonto f\u00fcr erhaltene Anzahlungen auf Bestellungen": {}, "3360 Verbindlichkeiten aus Lieferungen u. Leistungen EU": { "account_type": "Payable" @@ -141,7 +140,7 @@ "account_type": "Tax" }, "root_type": "Liability" - }, + }, "Klasse 2 Aktiva: Umlaufverm\u00f6gen, Rechnungsabgrenzungen": { "2030 Forderungen aus Lieferungen und Leistungen Inland (0% USt, umsatzsteuerfrei)": { "account_type": "Receivable" @@ -154,7 +153,7 @@ }, "2040 Forderungen aus Lieferungen und Leistungen Inland (sonstiger USt-Satz)": { "account_type": "Receivable" - }, + }, "2100 Forderungen aus Lieferungen und Leistungen EU": { "account_type": "Receivable" }, @@ -192,7 +191,7 @@ "account_type": "Receivable" }, "2570 Einfuhrumsatzsteuer (bezahlt)": {"account_type": "Tax"}, - + "2460 Eingeforderte aber noch nicht eingezahlte Einlagen": { "account_type": "Receivable" }, @@ -243,10 +242,10 @@ }, "2800 Guthaben bei Bank": { "account_type": "Bank" - }, + }, "2801 Guthaben bei Bank - Sparkonto": { "account_type": "Bank" - }, + }, "2810 Guthaben bei Paypal": { "account_type": "Bank" }, @@ -264,19 +263,19 @@ }, "2895 Schwebende Geldbewegugen": { "account_type": "Bank" - }, + }, "2513 Vorsteuer Inland 5%": { "account_type": "Tax" }, "2515 Vorsteuer Inland 20%": { "account_type": "Tax" - }, + }, "2520 Vorsteuer aus innergemeinschaftlichem Erwerb 10%": { "account_type": "Tax" }, "2525 Vorsteuer aus innergemeinschaftlichem Erwerb 20%": { "account_type": "Tax" - }, + }, "2530 Vorsteuer \u00a719/Art 19 ( reverse charge ) ": { "account_type": "Tax" }, @@ -286,16 +285,16 @@ "root_type": "Asset" }, "Klasse 4: Betriebliche Erträge": { - "4000 Erlöse 20 %": {"account_type": "Income Account"}, - "4020 Erl\u00f6se 0 % steuerbefreit": {"account_type": "Income Account"}, + "4000 Erlöse 20 %": {"account_type": "Income Account"}, + "4020 Erl\u00f6se 0 % steuerbefreit": {"account_type": "Income Account"}, "4010 Erl\u00f6se 10 %": {"account_type": "Income Account"}, - "4030 Erl\u00f6se 13 %": {"account_type": "Income Account"}, - "4040 Erl\u00f6se 0 % innergemeinschaftliche Lieferungen": {"account_type": "Income Account"}, - "4400 Erl\u00f6sreduktion 0 % steuerbefreit": {"account_type": "Expense Account"}, + "4030 Erl\u00f6se 13 %": {"account_type": "Income Account"}, + "4040 Erl\u00f6se 0 % innergemeinschaftliche Lieferungen": {"account_type": "Income Account"}, + "4400 Erl\u00f6sreduktion 0 % steuerbefreit": {"account_type": "Expense Account"}, "4410 Erl\u00f6sreduktion 10 %": {"account_type": "Expense Account"}, "4420 Erl\u00f6sreduktion 20 %": {"account_type": "Expense Account"}, - "4430 Erl\u00f6sreduktion 13 %": {"account_type": "Expense Account"}, - "4440 Erl\u00f6sreduktion 0 % innergemeinschaftliche Lieferungen": {"account_type": "Expense Account"}, + "4430 Erl\u00f6sreduktion 13 %": {"account_type": "Expense Account"}, + "4440 Erl\u00f6sreduktion 0 % innergemeinschaftliche Lieferungen": {"account_type": "Expense Account"}, "4500 Ver\u00e4nderungen des Bestandes an fertigen und unfertigen Erzeugn. sowie an noch nicht abrechenbaren Leistungen": {"account_type": "Income Account"}, "4580 Aktivierte Eigenleistungen": {"account_type": "Income Account"}, "4600 Erl\u00f6se aus dem Abgang vom Anlageverm\u00f6gen, ausgen. Finanzanlagen": {"account_type": "Income Account"}, @@ -304,15 +303,15 @@ "4700 Ertr\u00e4ge aus der Aufl\u00f6sung von R\u00fcckstellungen": {"account_type": "Income Account"}, "4800 \u00dcbrige betriebliche Ertr\u00e4ge": {"account_type": "Income Account"}, "root_type": "Income" - }, + }, "Klasse 5: Aufwand f\u00fcr Material und Leistungen": { - "5000 Einkauf Partnerleistungen": {"account_type": "Cost of Goods Sold"}, + "5000 Einkauf Partnerleistungen": {"account_type": "Cost of Goods Sold"}, "5100 Verbrauch an Rohstoffen": {"account_type": "Cost of Goods Sold"}, "5200 Verbrauch von bezogenen Fertig- und Einzelteilen": {"account_type": "Cost of Goods Sold"}, "5300 Verbrauch von Hilfsstoffen": {"account_type": "Cost of Goods Sold"}, "5340 Verbrauch Verpackungsmaterial": {"account_type": "Cost of Goods Sold"}, "5470 Verbrauch von Kleinmaterial": {"account_type": "Cost of Goods Sold"}, - "5450 Verbrauch von Reinigungsmaterial": {"account_type": "Cost of Goods Sold"}, + "5450 Verbrauch von Reinigungsmaterial": {"account_type": "Cost of Goods Sold"}, "5400 Verbrauch von Betriebsstoffen": {"account_type": "Cost of Goods Sold"}, "5500 Verbrauch von Werkzeugen und anderen Erzeugungshilfsmittel": {"account_type": "Cost of Goods Sold"}, "5600 Verbrauch von Brenn- und Treibstoffen, Energie und Wasser": {"account_type": "Cost of Goods Sold"}, @@ -340,7 +339,7 @@ "6700 Sonstige Sozialaufwendungen": {"account_type": "Payable"}, "6900 Aufwandsstellenrechnung Personal": {"account_type": "Payable"}, "root_type": "Expense" - }, + }, "Klasse 7: Abschreibungen und sonstige betriebliche Aufwendungen": { "7010 Abschreibungen auf das Anlageverm\u00f6gen (ausgenommen Finanzanlagen)": {"account_type": "Depreciation"}, "7100 Sonstige Steuern und Geb\u00fchren": {"account_type": "Tax"}, @@ -349,7 +348,7 @@ "7310 Fahrrad - Aufwand": {"account_type": "Expense Account"}, "7320 Kfz - Aufwand": {"account_type": "Expense Account"}, "7330 LKW - Aufwand": {"account_type": "Expense Account"}, - "7340 Lastenrad - Aufwand": {"account_type": "Expense Account"}, + "7340 Lastenrad - Aufwand": {"account_type": "Expense Account"}, "7350 Reise- und Fahraufwand": {"account_type": "Expense Account"}, "7360 Tag- und N\u00e4chtigungsgelder": {"account_type": "Expense Account"}, "7380 Nachrichtenaufwand": {"account_type": "Expense Account"}, @@ -409,7 +408,7 @@ "8990 Gewinnabfuhr bzw. Verlust\u00fcberrechnung aus Ergebnisabf\u00fchrungsvertr\u00e4gen": {"account_type": "Expense Account"}, "8350 nicht ausgenutzte Lieferantenskonti": {"account_type": "Expense Account"}, "root_type": "Income" - }, + }, "Klasse 9 Passiva: Eigenkapital, R\u00fccklagen, stille Einlagen, Abschlusskonten": { "9000 Gezeichnetes bzw. gewidmetes Kapital": { "account_type": "Equity" @@ -435,5 +434,5 @@ }, "root_type": "Equity" } - } + } } diff --git a/erpnext/accounts/doctype/journal_entry/test_records.json b/erpnext/accounts/doctype/journal_entry/test_records.json index dafcf56abd..717c579c7a 100644 --- a/erpnext/accounts/doctype/journal_entry/test_records.json +++ b/erpnext/accounts/doctype/journal_entry/test_records.json @@ -1,97 +1,94 @@ [ - { - "cheque_date": "2013-03-14", - "cheque_no": "33", - "company": "_Test Company", - "doctype": "Journal Entry", - "accounts": [ - { - "account": "Debtors - _TC", - "party_type": "Customer", - "party": "_Test Customer", - "credit_in_account_currency": 400.0, - "debit_in_account_currency": 0.0, - "doctype": "Journal Entry Account", - "parentfield": "accounts", - "cost_center": "_Test Cost Center - _TC" - }, - { - "account": "_Test Bank - _TC", - "credit_in_account_currency": 0.0, - "debit_in_account_currency": 400.0, - "doctype": "Journal Entry Account", - "parentfield": "accounts", - "cost_center": "_Test Cost Center - _TC" - } - ], - "naming_series": "_T-Journal Entry-", - "posting_date": "2013-02-14", - "user_remark": "test", - "voucher_type": "Bank Entry" - }, - - - { - "cheque_date": "2013-02-14", - "cheque_no": "33", - "company": "_Test Company", - "doctype": "Journal Entry", - "accounts": [ - { - "account": "_Test Payable - _TC", - "party_type": "Supplier", - "party": "_Test Supplier", - "credit_in_account_currency": 0.0, - "debit_in_account_currency": 400.0, - "doctype": "Journal Entry Account", - "parentfield": "accounts", - "cost_center": "_Test Cost Center - _TC" - }, - { - "account": "_Test Bank - _TC", - "credit_in_account_currency": 400.0, - "debit_in_account_currency": 0.0, - "doctype": "Journal Entry Account", - "parentfield": "accounts", - "cost_center": "_Test Cost Center - _TC" - } - ], - "naming_series": "_T-Journal Entry-", - "posting_date": "2013-02-14", - "user_remark": "test", - "voucher_type": "Bank Entry" - }, - - - { - "cheque_date": "2013-02-14", - "cheque_no": "33", - "company": "_Test Company", - "doctype": "Journal Entry", - "accounts": [ - { - "account": "Debtors - _TC", - "party_type": "Customer", - "party": "_Test Customer", - "credit_in_account_currency": 0.0, - "debit_in_account_currency": 400.0, - "doctype": "Journal Entry Account", - "parentfield": "accounts", - "cost_center": "_Test Cost Center - _TC" - }, - { - "account": "Sales - _TC", - "cost_center": "_Test Cost Center - _TC", - "credit_in_account_currency": 400.0, - "debit_in_account_currency": 0.0, - "doctype": "Journal Entry Account", - "parentfield": "accounts", - "cost_center": "_Test Cost Center - _TC" - } - ], - "naming_series": "_T-Journal Entry-", - "posting_date": "2013-02-14", - "user_remark": "test", - "voucher_type": "Bank Entry" - } + { + "cheque_date": "2013-03-14", + "cheque_no": "33", + "company": "_Test Company", + "doctype": "Journal Entry", + "accounts": [ + { + "account": "Debtors - _TC", + "party_type": "Customer", + "party": "_Test Customer", + "credit_in_account_currency": 400.0, + "debit_in_account_currency": 0.0, + "doctype": "Journal Entry Account", + "parentfield": "accounts", + "cost_center": "_Test Cost Center - _TC" + }, + { + "account": "_Test Bank - _TC", + "credit_in_account_currency": 0.0, + "debit_in_account_currency": 400.0, + "doctype": "Journal Entry Account", + "parentfield": "accounts", + "cost_center": "_Test Cost Center - _TC" + } + ], + "naming_series": "_T-Journal Entry-", + "posting_date": "2013-02-14", + "user_remark": "test", + "voucher_type": "Bank Entry" + }, + + { + "cheque_date": "2013-02-14", + "cheque_no": "33", + "company": "_Test Company", + "doctype": "Journal Entry", + "accounts": [ + { + "account": "_Test Payable - _TC", + "party_type": "Supplier", + "party": "_Test Supplier", + "credit_in_account_currency": 0.0, + "debit_in_account_currency": 400.0, + "doctype": "Journal Entry Account", + "parentfield": "accounts", + "cost_center": "_Test Cost Center - _TC" + }, + { + "account": "_Test Bank - _TC", + "credit_in_account_currency": 400.0, + "debit_in_account_currency": 0.0, + "doctype": "Journal Entry Account", + "parentfield": "accounts", + "cost_center": "_Test Cost Center - _TC" + } + ], + "naming_series": "_T-Journal Entry-", + "posting_date": "2013-02-14", + "user_remark": "test", + "voucher_type": "Bank Entry" + }, + + { + "cheque_date": "2013-02-14", + "cheque_no": "33", + "company": "_Test Company", + "doctype": "Journal Entry", + "accounts": [ + { + "account": "Debtors - _TC", + "party_type": "Customer", + "party": "_Test Customer", + "credit_in_account_currency": 0.0, + "debit_in_account_currency": 400.0, + "doctype": "Journal Entry Account", + "parentfield": "accounts", + "cost_center": "_Test Cost Center - _TC" + }, + { + "account": "Sales - _TC", + "credit_in_account_currency": 400.0, + "debit_in_account_currency": 0.0, + "doctype": "Journal Entry Account", + "parentfield": "accounts", + "cost_center": "_Test Cost Center - _TC" + } + ], + "naming_series": "_T-Journal Entry-", + "posting_date": "2013-02-14", + "user_remark": "test", + "voucher_type": "Bank Entry" + } ] diff --git a/erpnext/setup/demo_data/journal_entry.json b/erpnext/setup/demo_data/journal_entry.json index b751c7cf24..a681be4f5b 100644 --- a/erpnext/setup/demo_data/journal_entry.json +++ b/erpnext/setup/demo_data/journal_entry.json @@ -4,22 +4,22 @@ "cheque_no": "33", "doctype": "Journal Entry", "accounts": [ - { - "party_type": "Customer", - "party": "ABC Enterprises", - "credit_in_account_currency": 40000.0, - "debit_in_account_currency": 0.0, - "doctype": "Journal Entry Account", - "parentfield": "accounts", - }, - { - "credit_in_account_currency": 0.0, - "debit_in_account_currency": 40000.0, - "doctype": "Journal Entry Account", - "parentfield": "accounts", - } + { + "party_type": "Customer", + "party": "ABC Enterprises", + "credit_in_account_currency": 40000.0, + "debit_in_account_currency": 0.0, + "doctype": "Journal Entry Account", + "parentfield": "accounts" + }, + { + "credit_in_account_currency": 0.0, + "debit_in_account_currency": 40000.0, + "doctype": "Journal Entry Account", + "parentfield": "accounts" + } ], "user_remark": "test", "voucher_type": "Bank Entry" } -] \ No newline at end of file +] From 0773f66febb7547873607f6e6be0a7669b8dd00a Mon Sep 17 00:00:00 2001 From: hyaray Date: Fri, 22 Dec 2023 11:11:51 +0800 Subject: [PATCH 103/205] chore: Update company.py (#38660) chore: Update company.py --- erpnext/setup/doctype/company/company.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index 0e8ee2dda4..9897847896 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -274,7 +274,7 @@ class Company(NestedSet): "parent_warehouse": "{0} - {1}".format(_("All Warehouses"), self.abbr) if not wh_detail["is_group"] else "", - "warehouse_type": wh_detail["warehouse_type"] if "warehouse_type" in wh_detail else None, + "warehouse_type": wh_detail.get("warehouse_type"), } ) warehouse.flags.ignore_permissions = True From 1a1629196d0daedef3db4f73191e21321689306d Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Fri, 22 Dec 2023 15:29:56 +0530 Subject: [PATCH 104/205] chore: improve `Allowed Qty` error msg --- .../stock_reservation_entry.py | 47 ++++++++++++------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py index 24650fde5f..7e03ac3357 100644 --- a/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py +++ b/erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py @@ -9,7 +9,7 @@ from frappe.model.document import Document from frappe.query_builder.functions import Sum from frappe.utils import cint, flt -from erpnext.stock.utils import get_or_make_bin +from erpnext.stock.utils import get_or_make_bin, get_stock_balance class StockReservationEntry(Document): @@ -151,7 +151,7 @@ class StockReservationEntry(Document): """Validates `Reserved Qty` when `Reservation Based On` is `Qty`.""" if self.reservation_based_on == "Qty": - self.validate_with_max_reserved_qty(self.reserved_qty) + self.validate_with_allowed_qty(self.reserved_qty) def auto_reserve_serial_and_batch(self, based_on: str = None) -> None: """Auto pick Serial and Batch Nos to reserve when `Reservation Based On` is `Serial and Batch`.""" @@ -324,7 +324,7 @@ class StockReservationEntry(Document): frappe.throw(msg) # Should be called after validating Serial and Batch Nos. - self.validate_with_max_reserved_qty(qty_to_be_reserved) + self.validate_with_allowed_qty(qty_to_be_reserved) self.db_set("reserved_qty", qty_to_be_reserved) def update_reserved_qty_in_voucher( @@ -429,7 +429,7 @@ class StockReservationEntry(Document): msg = _("Stock Reservation Entry cannot be updated as it has been delivered.") frappe.throw(msg) - def validate_with_max_reserved_qty(self, qty_to_be_reserved: float) -> None: + def validate_with_allowed_qty(self, qty_to_be_reserved: float) -> None: """Validates `Reserved Qty` with `Max Reserved Qty`.""" self.db_set( @@ -448,12 +448,12 @@ class StockReservationEntry(Document): ) voucher_delivered_qty = flt(delivered_qty) * flt(conversion_factor) - max_reserved_qty = min( + allowed_qty = min( self.available_qty, (self.voucher_qty - voucher_delivered_qty - total_reserved_qty) ) - if max_reserved_qty <= 0 and self.voucher_type == "Sales Order": - msg = _("Item {0} is already delivered for Sales Order {1}.").format( + if self.get("_action") != "submit" and self.voucher_type == "Sales Order" and allowed_qty <= 0: + msg = _("Item {0} is already reserved/delivered against Sales Order {1}.").format( frappe.bold(self.item_code), frappe.bold(self.voucher_no) ) @@ -463,19 +463,33 @@ class StockReservationEntry(Document): else: frappe.throw(msg) - if qty_to_be_reserved > max_reserved_qty: + if qty_to_be_reserved > allowed_qty: + actual_qty = get_stock_balance(self.item_code, self.warehouse) msg = """ - Cannot reserve more than Max Reserved Qty {0} {1}.

- The Max Reserved Qty is calculated as follows:
+ Cannot reserve more than Allowed Qty {0} {1} for Item {2} against {3} {4}.

+ The Allowed Qty is calculated as follows:
    -
  • Available Qty To Reserve = (Actual Stock Qty - Reserved Stock Qty)
  • -
  • Voucher Qty = Voucher Item Qty
  • -
  • Delivered Qty = Qty delivered against the Voucher Item
  • -
  • Total Reserved Qty = Qty reserved against the Voucher Item
  • -
  • Max Reserved Qty = Minimum of (Available Qty To Reserve, (Voucher Qty - Delivered Qty - Total Reserved Qty))
  • +
  • Actual Qty [Available Qty at Warehouse] = {5}
  • +
  • Reserved Stock [Ignore current SRE] = {6}
  • +
  • Available Qty To Reserve [Actual Qty - Reserved Stock] = {7}
  • +
  • Voucher Qty [Voucher Item Qty] = {8}
  • +
  • Delivered Qty [Qty delivered against the Voucher Item] = {9}
  • +
  • Total Reserved Qty [Qty reserved against the Voucher Item] = {10}
  • +
  • Allowed Qty [Minimum of (Available Qty To Reserve, (Voucher Qty - Delivered Qty - Total Reserved Qty))] = {11}
""".format( - frappe.bold(max_reserved_qty), self.stock_uom + frappe.bold(allowed_qty), + self.stock_uom, + frappe.bold(self.item_code), + self.voucher_type, + frappe.bold(self.voucher_no), + actual_qty, + actual_qty - self.available_qty, + self.available_qty, + self.voucher_qty, + voucher_delivered_qty, + total_reserved_qty, + allowed_qty, ) frappe.throw(msg) @@ -509,7 +523,6 @@ def get_available_qty_to_reserve( """Returns `Available Qty to Reserve (Actual Qty - Reserved Qty)` for Item, Warehouse and Batch combination.""" from erpnext.stock.doctype.batch.batch import get_batch_qty - from erpnext.stock.utils import get_stock_balance if batch_no: return get_batch_qty( From a5d5223c0e7f85a64f70288ec6e0048864b2ffd7 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Fri, 22 Dec 2023 15:46:06 +0530 Subject: [PATCH 105/205] fix: `Reserved Stock` report --- .../report/reserved_stock/reserved_stock.js | 48 ++++++++++--------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/erpnext/stock/report/reserved_stock/reserved_stock.js b/erpnext/stock/report/reserved_stock/reserved_stock.js index 68727411d5..2b075e2276 100644 --- a/erpnext/stock/report/reserved_stock/reserved_stock.js +++ b/erpnext/stock/report/reserved_stock/reserved_stock.js @@ -149,34 +149,36 @@ frappe.query_reports["Reserved Stock"] = { formatter: (value, row, column, data, default_formatter) => { value = default_formatter(value, row, column, data); - if (column.fieldname == "status") { - switch (data.status) { - case "Partially Reserved": - value = "" + value + ""; - break; - case "Reserved": - value = "" + value + ""; - break; - case "Partially Delivered": - value = "" + value + ""; - break; - case "Delivered": - value = "" + value + ""; - break; + if (data) { + if (column.fieldname == "status") { + switch (data.status) { + case "Partially Reserved": + value = "" + value + ""; + break; + case "Reserved": + value = "" + value + ""; + break; + case "Partially Delivered": + value = "" + value + ""; + break; + case "Delivered": + value = "" + value + ""; + break; + } } - } - else if (column.fieldname == "delivered_qty") { - if (data.delivered_qty > 0) { - if (data.reserved_qty > data.delivered_qty) { - value = "" + value + ""; + else if (column.fieldname == "delivered_qty") { + if (data.delivered_qty > 0) { + if (data.reserved_qty > data.delivered_qty) { + value = "" + value + ""; + } + else { + value = "" + value + ""; + } } else { - value = "" + value + ""; + value = "" + value + ""; } } - else { - value = "" + value + ""; - } } return value; From 161ae1edd1ebcafd14d7a302ad1adde238e43426 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Fri, 22 Dec 2023 17:37:17 +0530 Subject: [PATCH 106/205] fix: reset the incoming rate on changing of the warehouse (#38925) --- erpnext/public/js/utils/sales_common.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/erpnext/public/js/utils/sales_common.js b/erpnext/public/js/utils/sales_common.js index 084cca7db5..b92b02e826 100644 --- a/erpnext/public/js/utils/sales_common.js +++ b/erpnext/public/js/utils/sales_common.js @@ -184,6 +184,12 @@ erpnext.sales_common = { refresh_field("incentives",row.name,row.parentfield); } + warehouse(doc, cdt, cdn) { + if (doc.docstatus === 0 && doc.is_return && !doc.return_against) { + frappe.model.set_value(cdt, cdn, "incoming_rate", 0.0); + } + } + toggle_editable_price_list_rate() { var df = frappe.meta.get_docfield(this.frm.doc.doctype + " Item", "price_list_rate", this.frm.doc.name); var editable_price_list_rate = cint(frappe.defaults.get_default("editable_price_list_rate")); From 47f7b65058e860e91c58dd12da6e48bd70ae60f6 Mon Sep 17 00:00:00 2001 From: Gursheen Kaur Anand <40693548+GursheenK@users.noreply.github.com> Date: Sun, 24 Dec 2023 16:13:31 +0530 Subject: [PATCH 107/205] feat: voucher subtype for general ledger (#38822) * feat: add voucher subtype column to gle * feat: add logic to set voucher subtypes * feat: fetch voucher subtype in ledger report * fix: order of conditions --- .../accounts/doctype/gl_entry/gl_entry.json | 30 +++++++++++-------- erpnext/accounts/doctype/gl_entry/gl_entry.py | 3 ++ .../report/general_ledger/general_ledger.py | 8 ++++- erpnext/controllers/accounts_controller.py | 20 +++++++++++++ 4 files changed, 48 insertions(+), 13 deletions(-) diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.json b/erpnext/accounts/doctype/gl_entry/gl_entry.json index c4492be367..09912e9896 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.json +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.json @@ -23,6 +23,7 @@ "against_voucher_type", "against_voucher", "voucher_type", + "voucher_subtype", "voucher_no", "voucher_detail_no", "project", @@ -138,19 +139,19 @@ "options": "DocType" }, { - "fieldname": "against", - "fieldtype": "Text", - "in_filter": 1, - "label": "Against", - "oldfieldname": "against", - "oldfieldtype": "Text" + "fieldname": "against", + "fieldtype": "Text", + "in_filter": 1, + "label": "Against", + "oldfieldname": "against", + "oldfieldtype": "Text" }, { - "fieldname": "against_link", - "fieldtype": "Dynamic Link", - "in_filter": 1, - "label": "Against", - "options": "against_type" + "fieldname": "against_link", + "fieldtype": "Dynamic Link", + "in_filter": 1, + "label": "Against", + "options": "against_type" }, { "fieldname": "against_voucher_type", @@ -294,13 +295,18 @@ "fieldtype": "Currency", "label": "Credit Amount in Transaction Currency", "options": "transaction_currency" + }, + { + "fieldname": "voucher_subtype", + "fieldtype": "Small Text", + "label": "Voucher Subtype" } ], "icon": "fa fa-list", "idx": 1, "in_create": 1, "links": [], - "modified": "2023-11-08 12:20:23.031733", + "modified": "2023-12-18 15:38:14.006208", "modified_by": "Administrator", "module": "Accounts", "name": "GL Entry", diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py index f7dd29ab1c..139f52696b 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py @@ -39,6 +39,8 @@ class GLEntry(Document): account: DF.Link | None account_currency: DF.Link | None against: DF.Text | None + against_link: DF.DynamicLink | None + against_type: DF.Link | None against_voucher: DF.DynamicLink | None against_voucher_type: DF.Link | None company: DF.Link | None @@ -66,6 +68,7 @@ class GLEntry(Document): transaction_exchange_rate: DF.Float voucher_detail_no: DF.Data | None voucher_no: DF.DynamicLink | None + voucher_subtype: DF.SmallText | None voucher_type: DF.Link | None # end: auto-generated types diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index b45ff60f1b..4054dca360 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -200,7 +200,7 @@ def get_gl_entries(filters, accounting_dimensions): """ select name as gl_entry, posting_date, account, party_type, party, - voucher_type, voucher_no, {dimension_fields} + voucher_type, voucher_subtype, voucher_no, {dimension_fields} cost_center, project, {transaction_currency_fields} against_voucher_type, against_voucher, account_currency, against_link, against, is_opening, creation {select_fields} @@ -609,6 +609,12 @@ def get_columns(filters): columns += [ {"label": _("Voucher Type"), "fieldname": "voucher_type", "width": 120}, + { + "label": _("Voucher Subtype"), + "fieldname": "voucher_subtype", + "fieldtype": "Data", + "width": 180, + }, { "label": _("Voucher No"), "fieldname": "voucher_no", diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index d88424b7e7..febad18058 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -874,6 +874,7 @@ class AccountsController(TransactionBase): "project": self.get("project"), "post_net_value": args.get("post_net_value"), "voucher_detail_no": args.get("voucher_detail_no"), + "voucher_subtype": self.get_voucher_subtype(), } ) @@ -929,6 +930,25 @@ class AccountsController(TransactionBase): return gl_dict + def get_voucher_subtype(self): + voucher_subtypes = { + "Journal Entry": "voucher_type", + "Payment Entry": "payment_type", + "Stock Entry": "stock_entry_type", + "Asset Capitalization": "entry_type", + } + if self.doctype in voucher_subtypes: + return self.get(voucher_subtypes[self.doctype]) + elif self.doctype == "Purchase Receipt" and self.is_return: + return "Purchase Return" + elif self.doctype == "Delivery Note" and self.is_return: + return "Sales Return" + elif (self.doctype == "Sales Invoice" and self.is_return) or self.doctype == "Purchase Invoice": + return "Credit Note" + elif (self.doctype == "Purchase Invoice" and self.is_return) or self.doctype == "Sales Invoice": + return "Debit Note" + return self.doctype + def get_value_in_transaction_currency(self, account_currency, args, field): if account_currency == self.get("currency"): return args.get(field + "_in_account_currency") From 87ba3b64f78989d9807c2a03cf7c715171b4499e Mon Sep 17 00:00:00 2001 From: Wolfram Schmidt Date: Sun, 24 Dec 2023 11:52:26 +0100 Subject: [PATCH 108/205] chore: german translation for actual time (#38837) chore: german translation for actual time --- erpnext/translations/de.csv | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv index 2745d4da12..d05d0d96c3 100644 --- a/erpnext/translations/de.csv +++ b/erpnext/translations/de.csv @@ -103,6 +103,7 @@ Actual Qty is mandatory,Die tatsächliche Menge ist zwingend erforderlich, Actual Qty {0} / Waiting Qty {1},Tatsächliche Menge {0} / Wartezeit {1}, Actual Qty: Quantity available in the warehouse.,Tatsächliche Menge: Menge verfügbar im Lager., Actual qty in stock,Tatsächliche Menge auf Lager, +Actual Time (in Hours via Time Sheet), IST Zeit (in Stunden aus Zeiterfassung), Actual type tax cannot be included in Item rate in row {0},Tatsächliche Steuerart kann nicht im Artikelpreis in Zeile {0} beinhaltet sein, Add,Hinzufügen, Add / Edit Prices,Preise hinzufügen / bearbeiten, From eb5bb9f9a99e54be71c7ae5e24235b5b44692444 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Mon, 25 Dec 2023 22:05:02 +0530 Subject: [PATCH 109/205] fix(ux): make PI Item rate field editable --- .../doctype/purchase_invoice_item/purchase_invoice_item.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json index 7cad3ae1c0..9cf4e4fd7c 100644 --- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json +++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json @@ -288,7 +288,6 @@ "oldfieldname": "import_rate", "oldfieldtype": "Currency", "options": "currency", - "read_only_depends_on": "eval: (!parent.is_return && doc.purchase_receipt && doc.pr_detail)", "reqd": 1 }, { @@ -919,7 +918,7 @@ "idx": 1, "istable": 1, "links": [], - "modified": "2023-11-30 16:26:05.629780", + "modified": "2023-12-25 22:00:28.043555", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice Item", From cb9114442b936f03c9c975900282b3b9db62e453 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Mon, 25 Dec 2023 22:16:41 +0530 Subject: [PATCH 110/205] fix(ux): make PI Item rate field readonly based on `Maintain Same Rate` --- .../doctype/purchase_invoice/purchase_invoice.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js index cebd61a6f5..215d8ec215 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -163,6 +163,18 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying. } }) }, __("Get Items From")); + + if (!this.frm.doc.is_return) { + frappe.db.get_single_value("Buying Settings", "maintain_same_rate").then((value) => { + if (value) { + this.frm.doc.items.forEach((item) => { + this.frm.fields_dict.items.grid.update_docfield_property( + "rate", "read_only", (item.purchase_receipt && item.pr_detail) + ); + }); + } + }); + } } this.frm.toggle_reqd("supplier_warehouse", this.frm.doc.is_subcontracted); From b1ba2103323c8bfe066c288b4c285cf1f3c5b20b Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Mon, 25 Dec 2023 22:41:18 +0530 Subject: [PATCH 111/205] fix(ux): make PR Item rate field readonly based on `Maintain Same Rate` --- .../doctype/purchase_receipt/purchase_receipt.js | 14 ++++++++++++++ .../purchase_receipt_item.json | 3 +-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js index 6c9d3392e3..2cbccb0774 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js @@ -88,6 +88,20 @@ frappe.ui.form.on("Purchase Receipt", { }, __('Create')); } + if (frm.doc.docstatus === 0) { + if (!frm.doc.is_return) { + frappe.db.get_single_value("Buying Settings", "maintain_same_rate").then((value) => { + if (value) { + frm.doc.items.forEach((item) => { + frm.fields_dict.items.grid.update_docfield_property( + "rate", "read_only", (item.purchase_order && item.purchase_order_item) + ); + }); + } + }); + } + } + frm.events.add_custom_buttons(frm); }, diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json index 7344d2a599..9bd692ad61 100644 --- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json +++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json @@ -359,7 +359,6 @@ "oldfieldtype": "Currency", "options": "currency", "print_width": "100px", - "read_only_depends_on": "eval: (!parent.is_return && doc.purchase_order && doc.purchase_order_item)", "width": "100px" }, { @@ -1104,7 +1103,7 @@ "idx": 1, "istable": 1, "links": [], - "modified": "2023-11-30 16:12:02.364608", + "modified": "2023-12-25 22:32:09.801965", "modified_by": "Administrator", "module": "Stock", "name": "Purchase Receipt Item", From 06d6220a2aa2f7855db2c2f985d046280e26f13a Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Tue, 26 Dec 2023 15:23:32 +0530 Subject: [PATCH 112/205] fix: do not make serial batch bundle for zero qty (#38949) --- .../serial_and_batch_bundle.py | 21 +++++++ .../stock_reconciliation.py | 5 +- .../test_stock_reconciliation.py | 60 +++++++++++++++++++ 3 files changed, 85 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index 37916e21c8..9a3f7e5b46 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -85,6 +85,7 @@ class SerialandBatchBundle(Document): # end: auto-generated types def validate(self): + self.set_batch_no() self.validate_serial_and_batch_no() self.validate_duplicate_serial_and_batch_no() self.validate_voucher_no() @@ -99,6 +100,26 @@ class SerialandBatchBundle(Document): self.set_incoming_rate() self.calculate_qty_and_amount() + def set_batch_no(self): + if self.has_serial_no and self.has_batch_no: + serial_nos = [d.serial_no for d in self.entries if d.serial_no] + has_no_batch = any(not d.batch_no for d in self.entries) + if not has_no_batch: + return + + serial_no_batch = frappe._dict( + frappe.get_all( + "Serial No", + filters={"name": ("in", serial_nos)}, + fields=["name", "batch_no"], + as_list=True, + ) + ) + + for row in self.entries: + if not row.batch_no: + row.batch_no = serial_no_batch.get(row.serial_no) + def validate_serial_nos_inventory(self): if not (self.has_serial_no and self.type_of_transaction == "Outward"): return diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py index e8d652e2b2..6819968394 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py @@ -171,7 +171,7 @@ class StockReconciliation(StockController): }, ) - if item_details.has_batch_no: + elif item_details.has_batch_no: batch_nos_details = get_available_batches( frappe._dict( { @@ -228,6 +228,9 @@ class StockReconciliation(StockController): def set_new_serial_and_batch_bundle(self): for item in self.items: + if not item.qty: + continue + if item.current_serial_and_batch_bundle and not item.serial_and_batch_bundle: current_doc = frappe.get_doc("Serial and Batch Bundle", item.current_serial_and_batch_bundle) diff --git a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py index 1ec99bf9a5..70e9fb2205 100644 --- a/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py +++ b/erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py @@ -865,6 +865,66 @@ class TestStockReconciliation(FrappeTestCase, StockTestMixin): sr1.load_from_db() self.assertEqual(sr1.difference_amount, 10000) + def test_make_stock_zero_for_serial_batch_item(self): + from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry + + serial_item = self.make_item( + properties={"is_stock_item": 1, "has_serial_no": 1, "serial_no_series": "DJJ.####"} + ).name + batch_item = self.make_item( + properties={ + "is_stock_item": 1, + "has_batch_no": 1, + "batch_number_series": "BDJJ.####", + "create_new_batch": 1, + } + ).name + + serial_batch_item = self.make_item( + properties={ + "is_stock_item": 1, + "has_batch_no": 1, + "batch_number_series": "ADJJ.####", + "create_new_batch": 1, + "has_serial_no": 1, + "serial_no_series": "SN-ADJJ.####", + } + ).name + + warehouse = "_Test Warehouse - _TC" + + for item_code in [serial_item, batch_item, serial_batch_item]: + make_stock_entry( + item_code=item_code, + target=warehouse, + qty=10, + basic_rate=100, + ) + + _reco = create_stock_reconciliation( + item_code=item_code, + warehouse=warehouse, + qty=0.0, + ) + + serial_batch_bundle = frappe.get_all( + "Stock Ledger Entry", + {"item_code": item_code, "warehouse": warehouse, "is_cancelled": 0, "voucher_no": _reco.name}, + "serial_and_batch_bundle", + ) + + self.assertEqual(len(serial_batch_bundle), 1) + + _reco.cancel() + + serial_batch_bundle = frappe.get_all( + "Stock Ledger Entry", + {"item_code": item_code, "warehouse": warehouse, "is_cancelled": 0, "voucher_no": _reco.name}, + "serial_and_batch_bundle", + ) + + self.assertEqual(len(serial_batch_bundle), 0) + def create_batch_item_with_batch(item_name, batch_id): batch_item_doc = create_item(item_name, is_stock_item=1) From d00f6672a8d9db1e28f9a86ff8efbedcdc95c41a Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Tue, 26 Dec 2023 15:24:04 +0530 Subject: [PATCH 113/205] fix: not able to import serial batch bundle using csv (#38950) --- .../serial_and_batch_bundle/serial_and_batch_bundle.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index 9a3f7e5b46..afb53fb112 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -1185,7 +1185,7 @@ def create_serial_batch_no_ledgers(entries, child_row, parent_doc, warehouse=Non doc.append( "entries", { - "qty": (row.qty or 1.0) * (1 if type_of_transaction == "Inward" else -1), + "qty": (flt(row.qty) or 1.0) * (1 if type_of_transaction == "Inward" else -1), "warehouse": warehouse, "batch_no": row.batch_no, "serial_no": row.serial_no, @@ -1213,7 +1213,7 @@ def update_serial_batch_no_ledgers(entries, child_row, parent_doc, warehouse=Non doc.append( "entries", { - "qty": (d.get("qty") or 1.0) * (1 if doc.type_of_transaction == "Inward" else -1), + "qty": (flt(d.get("qty")) or 1.0) * (1 if doc.type_of_transaction == "Inward" else -1), "warehouse": warehouse or d.get("warehouse"), "batch_no": d.get("batch_no"), "serial_no": d.get("serial_no"), From b09c9354fb621c4283d6ebde91f3d061ea88f7f6 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Tue, 26 Dec 2023 20:11:58 +0530 Subject: [PATCH 114/205] fix: min order qty optional in production plan (#38956) * fix: min order qty optional in production plan * fix: test cases --- erpnext/manufacturing/doctype/bom/bom.json | 3 ++- .../production_plan/production_plan.js | 2 ++ .../production_plan/production_plan.json | 9 +++++++- .../production_plan/production_plan.py | 19 +++++++++++++-- .../production_plan/test_production_plan.py | 23 +++++++++++++++++++ 5 files changed, 52 insertions(+), 4 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.json b/erpnext/manufacturing/doctype/bom/bom.json index e8d3542835..5083873681 100644 --- a/erpnext/manufacturing/doctype/bom/bom.json +++ b/erpnext/manufacturing/doctype/bom/bom.json @@ -218,6 +218,7 @@ "options": "\nWork Order\nJob Card" }, { + "default": "1", "fieldname": "conversion_rate", "fieldtype": "Float", "label": "Conversion Rate", @@ -636,7 +637,7 @@ "image_field": "image", "is_submittable": 1, "links": [], - "modified": "2023-08-07 11:38:08.152294", + "modified": "2023-12-26 19:34:08.159312", "modified_by": "Administrator", "module": "Manufacturing", "name": "BOM", diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.js b/erpnext/manufacturing/doctype/production_plan/production_plan.js index dd102b0fae..cd92263543 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.js +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.js @@ -305,6 +305,8 @@ frappe.ui.form.on('Production Plan', { frappe.throw(__("Select the Warehouse")); } + frm.set_value("consider_minimum_order_qty", 0); + if (frm.doc.ignore_existing_ordered_qty) { frm.events.get_items_for_material_requests(frm); } else { diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.json b/erpnext/manufacturing/doctype/production_plan/production_plan.json index 49386c4ebc..257b60c486 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.json +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.json @@ -48,6 +48,7 @@ "material_request_planning", "include_non_stock_items", "include_subcontracted_items", + "consider_minimum_order_qty", "include_safety_stock", "ignore_existing_ordered_qty", "column_break_25", @@ -423,13 +424,19 @@ "fieldtype": "Link", "label": "Sub Assembly Warehouse", "options": "Warehouse" + }, + { + "default": "0", + "fieldname": "consider_minimum_order_qty", + "fieldtype": "Check", + "label": "Consider Minimum Order Qty" } ], "icon": "fa fa-calendar", "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2023-11-03 14:08:11.928027", + "modified": "2023-12-26 16:31:13.740777", "modified_by": "Administrator", "module": "Manufacturing", "name": "Production Plan", diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index 4b72a83b05..2bfd4be53a 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -67,6 +67,7 @@ class ProductionPlan(Document): combine_items: DF.Check combine_sub_items: DF.Check company: DF.Link + consider_minimum_order_qty: DF.Check customer: DF.Link | None for_warehouse: DF.Link | None from_date: DF.Date | None @@ -1211,7 +1212,14 @@ def get_subitems( def get_material_request_items( - row, sales_order, company, ignore_existing_ordered_qty, include_safety_stock, warehouse, bin_dict + doc, + row, + sales_order, + company, + ignore_existing_ordered_qty, + include_safety_stock, + warehouse, + bin_dict, ): total_qty = row["qty"] @@ -1220,8 +1228,14 @@ def get_material_request_items( required_qty = total_qty elif total_qty > bin_dict.get("projected_qty", 0): required_qty = total_qty - bin_dict.get("projected_qty", 0) - if required_qty > 0 and required_qty < row["min_order_qty"]: + + if ( + doc.get("consider_minimum_order_qty") + and required_qty > 0 + and required_qty < row["min_order_qty"] + ): required_qty = row["min_order_qty"] + item_group_defaults = get_item_group_defaults(row.item_code, company) if not row["purchase_uom"]: @@ -1559,6 +1573,7 @@ def get_items_for_material_requests(doc, warehouses=None, get_parent_warehouse_d if details.qty > 0: items = get_material_request_items( + doc, details, sales_order, company, diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py index f86725d601..cb99b8845a 100644 --- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py @@ -1499,6 +1499,29 @@ class TestProductionPlan(FrappeTestCase): after_qty = flt(frappe.db.get_value("Bin", bin_name, "reserved_qty_for_production_plan")) self.assertAlmostEqual(after_qty, before_qty) + def test_min_order_qty_in_pp(self): + from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse + from erpnext.stock.utils import get_or_make_bin + + fg_item = make_item(properties={"is_stock_item": 1}).name + rm_item = make_item(properties={"is_stock_item": 1, "min_order_qty": 1000}).name + + rm_warehouse = create_warehouse("RM Warehouse", company="_Test Company") + + make_bom(item=fg_item, raw_materials=[rm_item], source_warehouse="_Test Warehouse - _TC") + + pln = create_production_plan(item_code=fg_item, planned_qty=10, do_not_submit=1) + + pln.for_warehouse = rm_warehouse + mr_items = get_items_for_material_requests(pln.as_dict()) + for d in mr_items: + self.assertEqual(d.get("quantity"), 10.0) + + pln.consider_minimum_order_qty = 1 + mr_items = get_items_for_material_requests(pln.as_dict()) + for d in mr_items: + self.assertEqual(d.get("quantity"), 1000.0) + def create_production_plan(**args): """ From 722310641700ce767cc2dd132e5ee41610d2e525 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 27 Dec 2023 10:27:11 +0530 Subject: [PATCH 115/205] fix: use `Stock Qty` while getting `POS Reserved Qty` --- erpnext/accounts/doctype/pos_invoice/pos_invoice.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py index bfb51da58b..e542d3cc63 100644 --- a/erpnext/accounts/doctype/pos_invoice/pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/pos_invoice.py @@ -765,7 +765,7 @@ def get_pos_reserved_qty(item_code, warehouse): reserved_qty = ( frappe.qb.from_(p_inv) .from_(p_item) - .select(Sum(p_item.qty).as_("qty")) + .select(Sum(p_item.stock_qty).as_("stock_qty")) .where( (p_inv.name == p_item.parent) & (IfNull(p_inv.consolidated_invoice, "") == "") @@ -775,7 +775,7 @@ def get_pos_reserved_qty(item_code, warehouse): ) ).run(as_dict=True) - return reserved_qty[0].qty or 0 if reserved_qty else 0 + return flt(reserved_qty[0].stock_qty) if reserved_qty else 0 @frappe.whitelist() From 47ee801d373058a2739c2fd42d971d624c42d5a7 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Wed, 27 Dec 2023 13:09:23 +0530 Subject: [PATCH 116/205] fix: incorrect qty in serial batch bundle against pick list (#38964) --- .../js/utils/serial_no_batch_selector.js | 1 + .../doctype/delivery_note/delivery_note.py | 17 ++- erpnext/stock/doctype/pick_list/pick_list.js | 38 ++++++ erpnext/stock/doctype/pick_list/pick_list.py | 15 ++- .../stock/doctype/pick_list/test_pick_list.py | 118 +++++++++++++++++- .../serial_and_batch_bundle.py | 109 +++++++++++++++- 6 files changed, 289 insertions(+), 9 deletions(-) diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js index 4abc8fa395..4cd1243413 100644 --- a/erpnext/public/js/utils/serial_no_batch_selector.js +++ b/erpnext/public/js/utils/serial_no_batch_selector.js @@ -502,6 +502,7 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { set_data(data) { data.forEach(d => { + d.qty = Math.abs(d.qty); this.dialog.fields_dict.entries.df.data.push(d); }); diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index 675f8e9158..132f8f2e29 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -311,11 +311,13 @@ class DeliveryNote(SellingController): ) def set_serial_and_batch_bundle_from_pick_list(self): + from erpnext.stock.serial_batch_bundle import SerialBatchCreation + if not self.pick_list: return for item in self.items: - if item.pick_list_item: + if item.pick_list_item and not item.serial_and_batch_bundle: filters = { "item_code": item.item_code, "voucher_type": "Pick List", @@ -326,7 +328,17 @@ class DeliveryNote(SellingController): bundle_id = frappe.db.get_value("Serial and Batch Bundle", filters, "name") if bundle_id: - item.serial_and_batch_bundle = bundle_id + cls_obj = SerialBatchCreation( + { + "type_of_transaction": "Outward", + "serial_and_batch_bundle": bundle_id, + "item_code": item.get("item_code"), + } + ) + + cls_obj.duplicate_package() + + item.serial_and_batch_bundle = cls_obj.serial_and_batch_bundle def validate_proj_cust(self): """check for does customer belong to same project as entered..""" @@ -408,6 +420,7 @@ class DeliveryNote(SellingController): self.update_stock_ledger() self.cancel_packing_slips() + self.update_pick_list_status() self.make_gl_entries_on_cancel() self.repost_future_sle_and_gle() diff --git a/erpnext/stock/doctype/pick_list/pick_list.js b/erpnext/stock/doctype/pick_list/pick_list.js index 7cd171ea92..afd6ce8138 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.js +++ b/erpnext/stock/doctype/pick_list/pick_list.js @@ -283,6 +283,7 @@ frappe.ui.form.on('Pick List Item', { }); } }, + uom: (frm, cdt, cdn) => { let row = frappe.get_doc(cdt, cdn); if (row.uom) { @@ -291,13 +292,50 @@ frappe.ui.form.on('Pick List Item', { }); } }, + qty: (frm, cdt, cdn) => { let row = frappe.get_doc(cdt, cdn); frappe.model.set_value(cdt, cdn, 'stock_qty', row.qty * row.conversion_factor); }, + conversion_factor: (frm, cdt, cdn) => { let row = frappe.get_doc(cdt, cdn); frappe.model.set_value(cdt, cdn, 'stock_qty', row.qty * row.conversion_factor); + }, + + pick_serial_and_batch(frm, cdt, cdn) { + let item = locals[cdt][cdn]; + let path = "assets/erpnext/js/utils/serial_no_batch_selector.js"; + + frappe.db.get_value("Item", item.item_code, ["has_batch_no", "has_serial_no"]) + .then((r) => { + if (r.message && (r.message.has_batch_no || r.message.has_serial_no)) { + item.has_serial_no = r.message.has_serial_no; + item.has_batch_no = r.message.has_batch_no; + item.type_of_transaction = item.qty > 0 ? "Outward":"Inward"; + + item.title = item.has_serial_no ? + __("Select Serial No") : __("Select Batch No"); + + if (item.has_serial_no && item.has_batch_no) { + item.title = __("Select Serial and Batch"); + } + + frappe.require(path, function() { + new erpnext.SerialBatchPackageSelector( + frm, item, (r) => { + if (r) { + let qty = Math.abs(r.total_qty); + frappe.model.set_value(item.doctype, item.name, { + "serial_and_batch_bundle": r.name, + "qty": qty + }); + } + } + ); + }); + } + }); } }); diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py index 545e45f3d8..758448af79 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.py +++ b/erpnext/stock/doctype/pick_list/pick_list.py @@ -21,6 +21,7 @@ from erpnext.selling.doctype.sales_order.sales_order import ( ) from erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle import ( get_auto_batch_nos, + get_picked_serial_nos, ) from erpnext.stock.get_item_details import get_conversion_factor from erpnext.stock.serial_batch_bundle import SerialBatchCreation @@ -167,6 +168,9 @@ class PickList(Document): "Serial and Batch Bundle", row.serial_and_batch_bundle ).set_serial_and_batch_values(self, row) + def on_trash(self): + self.remove_serial_and_batch_bundle() + def remove_serial_and_batch_bundle(self): for row in self.locations: if row.serial_and_batch_bundle: @@ -723,13 +727,14 @@ def get_available_item_locations( def get_available_item_locations_for_serialized_item( item_code, from_warehouses, required_qty, company, total_picked_qty=0 ): + picked_serial_nos = get_picked_serial_nos(item_code, from_warehouses) + sn = frappe.qb.DocType("Serial No") query = ( frappe.qb.from_(sn) .select(sn.name, sn.warehouse) .where((sn.item_code == item_code) & (sn.company == company)) .orderby(sn.creation) - .limit(cint(required_qty + total_picked_qty)) ) if from_warehouses: @@ -742,6 +747,9 @@ def get_available_item_locations_for_serialized_item( warehouse_serial_nos_map = frappe._dict() picked_qty = required_qty for serial_no, warehouse in serial_nos: + if serial_no in picked_serial_nos: + continue + if picked_qty <= 0: break @@ -786,7 +794,8 @@ def get_available_item_locations_for_batched_item( { "item_code": item_code, "warehouse": from_warehouses, - "qty": required_qty + total_picked_qty, + "qty": required_qty, + "is_pick_list": True, } ) ) @@ -1050,7 +1059,7 @@ def get_pending_work_orders(doctype, txt, searchfield, start, page_length, filte @frappe.whitelist() def target_document_exists(pick_list_name, purpose): if purpose == "Delivery": - return frappe.db.exists("Delivery Note", {"pick_list": pick_list_name}) + return frappe.db.exists("Delivery Note", {"pick_list": pick_list_name, "docstatus": 1}) return stock_entry_exists(pick_list_name) diff --git a/erpnext/stock/doctype/pick_list/test_pick_list.py b/erpnext/stock/doctype/pick_list/test_pick_list.py index 56c44bfd25..322b0b46ba 100644 --- a/erpnext/stock/doctype/pick_list/test_pick_list.py +++ b/erpnext/stock/doctype/pick_list/test_pick_list.py @@ -644,6 +644,122 @@ class TestPickList(FrappeTestCase): so.reload() self.assertEqual(so.per_picked, 50) + def test_picklist_for_batch_item(self): + warehouse = "_Test Warehouse - _TC" + item = make_item( + properties={"is_stock_item": 1, "has_batch_no": 1, "batch_no_series": "PICKLT-.######"} + ).name + + # create batch + for batch_id in ["PICKLT-000001", "PICKLT-000002"]: + if not frappe.db.exists("Batch", batch_id): + frappe.get_doc( + { + "doctype": "Batch", + "batch_id": batch_id, + "item": item, + } + ).insert() + + make_stock_entry( + item=item, + to_warehouse=warehouse, + qty=50, + basic_rate=100, + batches=frappe._dict({"PICKLT-000001": 30, "PICKLT-000002": 20}), + ) + + so = make_sales_order(item_code=item, qty=25.0, rate=100) + pl = create_pick_list(so.name) + # pick half the qty + for loc in pl.locations: + self.assertEqual(loc.qty, 25.0) + self.assertTrue(loc.serial_and_batch_bundle) + + data = frappe.get_all( + "Serial and Batch Entry", + fields=["qty", "batch_no"], + filters={"parent": loc.serial_and_batch_bundle}, + ) + + for d in data: + self.assertEqual(d.batch_no, "PICKLT-000001") + self.assertEqual(d.qty, 25.0 * -1) + + pl.save() + pl.submit() + + so1 = make_sales_order(item_code=item, qty=10.0, rate=100) + pl = create_pick_list(so1.name) + # pick half the qty + for loc in pl.locations: + self.assertEqual(loc.qty, 10.0) + self.assertTrue(loc.serial_and_batch_bundle) + + data = frappe.get_all( + "Serial and Batch Entry", + fields=["qty", "batch_no"], + filters={"parent": loc.serial_and_batch_bundle}, + ) + + for d in data: + self.assertTrue(d.batch_no in ["PICKLT-000001", "PICKLT-000002"]) + if d.batch_no == "PICKLT-000001": + self.assertEqual(d.qty, 5.0 * -1) + elif d.batch_no == "PICKLT-000002": + self.assertEqual(d.qty, 5.0 * -1) + + pl.save() + pl.submit() + pl.cancel() + + def test_picklist_for_serial_item(self): + warehouse = "_Test Warehouse - _TC" + item = make_item( + properties={"is_stock_item": 1, "has_serial_no": 1, "serial_no_series": "SN-PICKLT-.######"} + ).name + + make_stock_entry(item=item, to_warehouse=warehouse, qty=50, basic_rate=100) + + so = make_sales_order(item_code=item, qty=25.0, rate=100) + pl = create_pick_list(so.name) + picked_serial_nos = [] + # pick half the qty + for loc in pl.locations: + self.assertEqual(loc.qty, 25.0) + self.assertTrue(loc.serial_and_batch_bundle) + + data = frappe.get_all( + "Serial and Batch Entry", fields=["serial_no"], filters={"parent": loc.serial_and_batch_bundle} + ) + + picked_serial_nos = [d.serial_no for d in data] + self.assertEqual(len(picked_serial_nos), 25) + + pl.save() + pl.submit() + + so1 = make_sales_order(item_code=item, qty=10.0, rate=100) + pl = create_pick_list(so1.name) + # pick half the qty + for loc in pl.locations: + self.assertEqual(loc.qty, 10.0) + self.assertTrue(loc.serial_and_batch_bundle) + + data = frappe.get_all( + "Serial and Batch Entry", + fields=["qty", "batch_no"], + filters={"parent": loc.serial_and_batch_bundle}, + ) + + self.assertEqual(len(data), 10) + for d in data: + self.assertTrue(d.serial_no not in picked_serial_nos) + + pl.save() + pl.submit() + pl.cancel() + def test_picklist_with_bundles(self): warehouse = "_Test Warehouse - _TC" @@ -732,7 +848,7 @@ class TestPickList(FrappeTestCase): dn.cancel() pl.reload() - self.assertEqual(pl.status, "Completed") + self.assertEqual(pl.status, "Open") pl.cancel() pl.reload() diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index afb53fb112..dd38e1127f 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -936,7 +936,7 @@ def parse_csv_file_to_get_serial_batch(reader): if index == 0: has_serial_no = row[0] == "Serial No" has_batch_no = row[0] == "Batch No" - if not has_batch_no: + if not has_batch_no and len(row) > 1: has_batch_no = row[1] == "Batch No" continue @@ -1611,10 +1611,17 @@ def get_auto_batch_nos(kwargs): stock_ledgers_batches = get_stock_ledgers_batches(kwargs) pos_invoice_batches = get_reserved_batches_for_pos(kwargs) sre_reserved_batches = get_reserved_batches_for_sre(kwargs) + picked_batches = frappe._dict() + if kwargs.get("is_pick_list"): + picked_batches = get_picked_batches(kwargs) - if stock_ledgers_batches or pos_invoice_batches or sre_reserved_batches: + if stock_ledgers_batches or pos_invoice_batches or sre_reserved_batches or picked_batches: update_available_batches( - available_batches, stock_ledgers_batches, pos_invoice_batches, sre_reserved_batches + available_batches, + stock_ledgers_batches, + pos_invoice_batches, + sre_reserved_batches, + picked_batches, ) if not kwargs.consider_negative_batches: @@ -1771,6 +1778,102 @@ def get_voucher_wise_serial_batch_from_bundle(**kwargs) -> Dict[str, Dict]: return group_by_voucher +def get_picked_batches(kwargs) -> dict[str, dict]: + picked_batches = frappe._dict() + + table = frappe.qb.DocType("Serial and Batch Bundle") + child_table = frappe.qb.DocType("Serial and Batch Entry") + pick_list_table = frappe.qb.DocType("Pick List") + + query = ( + frappe.qb.from_(table) + .inner_join(child_table) + .on(table.name == child_table.parent) + .inner_join(pick_list_table) + .on(table.voucher_no == pick_list_table.name) + .select( + child_table.batch_no, + child_table.warehouse, + Sum(child_table.qty).as_("qty"), + ) + .where( + (table.docstatus != 2) + & (pick_list_table.status != "Completed") + & (table.type_of_transaction == "Outward") + & (table.is_cancelled == 0) + & (table.voucher_type == "Pick List") + & (table.voucher_no.isnotnull()) + ) + ) + + if kwargs.get("item_code"): + query = query.where(table.item_code == kwargs.get("item_code")) + + if kwargs.get("warehouse"): + if isinstance(kwargs.warehouse, list): + query = query.where(table.warehouse.isin(kwargs.warehouse)) + else: + query = query.where(table.warehouse == kwargs.get("warehouse")) + + data = query.run(as_dict=True) + for row in data: + if not row.qty: + continue + + key = (row.batch_no, row.warehouse) + if key not in picked_batches: + picked_batches[key] = frappe._dict( + { + "qty": row.qty, + "warehouse": row.warehouse, + } + ) + else: + picked_batches[key].qty += row.qty + + return picked_batches + + +def get_picked_serial_nos(item_code, warehouse=None) -> list[str]: + table = frappe.qb.DocType("Serial and Batch Bundle") + child_table = frappe.qb.DocType("Serial and Batch Entry") + pick_list_table = frappe.qb.DocType("Pick List") + + query = ( + frappe.qb.from_(table) + .inner_join(child_table) + .on(table.name == child_table.parent) + .inner_join(pick_list_table) + .on(table.voucher_no == pick_list_table.name) + .select( + child_table.serial_no, + ) + .where( + (table.docstatus != 2) + & (pick_list_table.status != "Completed") + & (table.type_of_transaction == "Outward") + & (table.is_cancelled == 0) + & (table.voucher_type == "Pick List") + & (table.voucher_no.isnotnull()) + ) + ) + + if item_code: + query = query.where(table.item_code == item_code) + + if warehouse: + if isinstance(warehouse, list): + query = query.where(table.warehouse.isin(warehouse)) + else: + query = query.where(table.warehouse == warehouse) + + data = query.run(as_dict=True) + if not data: + return [] + + return [row.serial_no for row in data if row.serial_no] + + def get_ledgers_from_serial_batch_bundle(**kwargs) -> List[frappe._dict]: bundle_table = frappe.qb.DocType("Serial and Batch Bundle") serial_batch_table = frappe.qb.DocType("Serial and Batch Entry") From fe77b9d633dcd168bef6f7c106ec1bd6d1a6591c Mon Sep 17 00:00:00 2001 From: VihangT <151990347+VihangT@users.noreply.github.com> Date: Wed, 27 Dec 2023 16:11:29 +0530 Subject: [PATCH 117/205] fix : correct logic for overlap error (#38967) fixing overlap error logic with taking care of sequential time job cards in overlap job card list --- .../doctype/job_card/job_card.py | 58 ++++++++++--------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py index d696cc4082..23650b6873 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.py +++ b/erpnext/manufacturing/doctype/job_card/job_card.py @@ -273,35 +273,39 @@ class JobCard(Document): def has_overlap(self, production_capacity, time_logs): overlap = False - if production_capacity == 1 and len(time_logs) > 0: + if production_capacity == 1 and len(time_logs) >= 1: return True + if not len(time_logs): + return False - # Check overlap exists or not between the overlapping time logs with the current Job Card - for row in time_logs: - count = 1 - for next_row in time_logs: - if row.name == next_row.name: - continue - - if ( - ( - get_datetime(next_row.from_time) >= get_datetime(row.from_time) - and get_datetime(next_row.from_time) <= get_datetime(row.to_time) - ) - or ( - get_datetime(next_row.to_time) >= get_datetime(row.from_time) - and get_datetime(next_row.to_time) <= get_datetime(row.to_time) - ) - or ( - get_datetime(next_row.from_time) <= get_datetime(row.from_time) - and get_datetime(next_row.to_time) >= get_datetime(row.to_time) - ) - ): - count += 1 - - if count > production_capacity: - return True - + # sorting overlapping job cards as per from_time + time_logs = sorted(time_logs, key=lambda x: x.get("from_time")) + # alloted_capacity has key number starting from 1. Key number will increment by 1 if non sequential job card found + # if key number reaches/crosses to production_capacity means capacity is full and overlap error generated + # this will store last to_time of sequential job cards + alloted_capacity = {1: time_logs[0]["to_time"]} + # flag for sequential Job card found + sequential_job_card_found = False + for i in range(1, len(time_logs)): + # scanning for all Existing keys + for key in alloted_capacity.keys(): + # if current Job Card from time is greater than last to_time in that key means these job card are sequential + if alloted_capacity[key] <= time_logs[i]["from_time"]: + # So update key's value with last to_time + alloted_capacity[key] = time_logs[i]["to_time"] + # flag is true as we get sequential Job Card for that key + sequential_job_card_found = True + # Immediately break so that job card to time is not added with any other key except this + break + # if sequential job card not found above means it is overlapping so increment key number to alloted_capacity + if not sequential_job_card_found: + # increment key number + key = key + 1 + # for that key last to time is assigned. + alloted_capacity[key] = time_logs[i]["to_time"] + if len(alloted_capacity) >= production_capacity: + # if number of keys greater or equal to production caoacity means full capacity is utilized and we should throw overlap error + return True return overlap def get_time_logs(self, args, doctype, check_next_available_slot=False): From d54f8318fba2b60eaad4a93a811a5b569c3344dc Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 27 Dec 2023 16:32:57 +0530 Subject: [PATCH 118/205] fix: incorrect total when Accumulating values --- .../accounts/report/financial_statements.py | 20 ++++++++++++++---- .../profit_and_loss_statement.py | 21 ++++++++++++++----- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py index 7355c4b8a1..004a9299ea 100644 --- a/erpnext/accounts/report/financial_statements.py +++ b/erpnext/accounts/report/financial_statements.py @@ -211,7 +211,13 @@ def get_data( ignore_accumulated_values_for_fy, ) accumulate_values_into_parents(accounts, accounts_by_name, period_list) - out = prepare_data(accounts, balance_must_be, period_list, company_currency) + out = prepare_data( + accounts, + balance_must_be, + period_list, + company_currency, + accumulated_values=filters.accumulated_values, + ) out = filter_out_zero_value_rows(out, parent_children_map) if out and total: @@ -270,7 +276,7 @@ def accumulate_values_into_parents(accounts, accounts_by_name, period_list): ) + d.get("opening_balance", 0.0) -def prepare_data(accounts, balance_must_be, period_list, company_currency): +def prepare_data(accounts, balance_must_be, period_list, company_currency, accumulated_values): data = [] year_start_date = period_list[0]["year_start_date"].strftime("%Y-%m-%d") year_end_date = period_list[-1]["year_end_date"].strftime("%Y-%m-%d") @@ -310,8 +316,14 @@ def prepare_data(accounts, balance_must_be, period_list, company_currency): has_value = True total += flt(row[period.key]) - row["has_value"] = has_value - row["total"] = total + if accumulated_values: + # when 'accumulated_values' is enabled, periods have running balance. + # so, last period will have the net amount. + row["has_value"] = has_value + row["total"] = flt(d.get(period_list[-1].key, 0.0), 3) + else: + row["has_value"] = has_value + row["total"] = total data.append(row) return data diff --git a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py index 66353358a0..0b7ce51891 100644 --- a/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py +++ b/erpnext/accounts/report/profit_and_loss_statement/profit_and_loss_statement.py @@ -82,14 +82,25 @@ def get_report_summary( if filters.get("accumulated_in_group_company"): period_list = get_filtered_list_for_consolidated_report(filters, period_list) - for period in period_list: - key = period if consolidated else period.key + if filters.accumulated_values: + # when 'accumulated_values' is enabled, periods have running balance. + # so, last period will have the net amount. + key = period_list[-1].key if income: - net_income += income[-2].get(key) + net_income = income[-2].get(key) if expense: - net_expense += expense[-2].get(key) + net_expense = expense[-2].get(key) if net_profit_loss: - net_profit += net_profit_loss.get(key) + net_profit = net_profit_loss.get(key) + else: + for period in period_list: + key = period if consolidated else period.key + if income: + net_income += income[-2].get(key) + if expense: + net_expense += expense[-2].get(key) + if net_profit_loss: + net_profit += net_profit_loss.get(key) if len(period_list) == 1 and periodicity == "Yearly": profit_label = _("Profit This Year") From 0890b414b14d67803abe2ee5be72ebdcf9f6bee4 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 27 Dec 2023 17:31:34 +0530 Subject: [PATCH 119/205] chore: resolve linter issues --- .../bisect_accounting_statements.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py index 1d6fd621aa..da273b9f89 100644 --- a/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py +++ b/erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py @@ -195,7 +195,7 @@ class BisectAccountingStatements(Document): self.fetch_or_calculate() self.save() else: - frappe.msgprint("No more children on Left") + frappe.msgprint(_("No more children on Left")) @frappe.whitelist() def bisect_right(self): @@ -209,7 +209,7 @@ class BisectAccountingStatements(Document): self.fetch_or_calculate() self.save() else: - frappe.msgprint("No more children on Right") + frappe.msgprint(_("No more children on Right")) @frappe.whitelist() def move_up(self): @@ -223,4 +223,4 @@ class BisectAccountingStatements(Document): self.fetch_or_calculate() self.save() else: - frappe.msgprint("Reached Root") + frappe.msgprint(_("Reached Root")) From 4feecb69d8f313b62b97807f6004704fa0faaa56 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Wed, 27 Dec 2023 19:31:45 +0530 Subject: [PATCH 120/205] ci: lock old resolved issue/PRs --- .github/workflows/lock.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/workflows/lock.yml diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml new file mode 100644 index 0000000000..e990228185 --- /dev/null +++ b/.github/workflows/lock.yml @@ -0,0 +1,21 @@ +name: 'Lock threads' + +on: + schedule: + - cron: '0 0 * * *' + workflow_dispatch: + +permissions: + issues: write + pull-requests: write + + +jobs: + lock: + runs-on: ubuntu-latest + steps: + - uses: dessant/lock-threads@v5 + with: + github-token: ${{ github.token }} + issue-inactive-days: 14 + pr-inactive-days: 14 From 9b1c22250f1da37a563ba0885fbbd732b176816c Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Wed, 27 Dec 2023 22:37:01 +0530 Subject: [PATCH 121/205] feat: Merge taxes from mapped docs (#38346) * feat: Merge taxes from mapped docs * chore: ci failures --- erpnext/public/js/utils.js | 12 +++--- .../purchase_receipt/purchase_receipt.py | 43 ++++++++++++++++++- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index b0ea56833b..866e94f95a 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -843,7 +843,7 @@ erpnext.utils.map_current_doc = function(opts) { freeze_message: __("Mapping {0} ...", [opts.source_doctype]), callback: function(r) { if(!r.exc) { - var doc = frappe.model.sync(r.message); + frappe.model.sync(r.message); cur_frm.dirty(); cur_frm.refresh(); } @@ -870,6 +870,11 @@ erpnext.utils.map_current_doc = function(opts) { target: opts.target, date_field: opts.date_field || undefined, setters: opts.setters, + data_fields: [{ + fieldname: 'merge_taxes', + fieldtype: 'Check', + label: __('Merge taxes from multiple documents'), + }], get_query: opts.get_query, add_filters_group: 1, allow_child_item_selection: opts.allow_child_item_selection, @@ -883,10 +888,7 @@ erpnext.utils.map_current_doc = function(opts) { return; } opts.source_name = values; - if (opts.allow_child_item_selection) { - // args contains filtered child docnames - opts.args = args; - } + opts.args = args; d.dialog.hide(); _map(); }, diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 10d9eaa3db..c7e36e9904 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -1124,8 +1124,39 @@ def get_item_wise_returned_qty(pr_doc): ) +def merge_taxes(source_taxes, target_doc): + from erpnext.accounts.doctype.pos_invoice_merge_log.pos_invoice_merge_log import ( + update_item_wise_tax_detail, + ) + + existing_taxes = target_doc.get("taxes") or [] + idx = 1 + for tax in source_taxes: + found = False + for t in existing_taxes: + if t.account_head == tax.account_head and t.cost_center == tax.cost_center: + t.tax_amount = flt(t.tax_amount) + flt(tax.tax_amount_after_discount_amount) + t.base_tax_amount = flt(t.base_tax_amount) + flt(tax.base_tax_amount_after_discount_amount) + update_item_wise_tax_detail(t, tax) + found = True + + if not found: + tax.charge_type = "Actual" + tax.idx = idx + idx += 1 + tax.included_in_print_rate = 0 + tax.dont_recompute_tax = 1 + tax.row_id = "" + tax.tax_amount = tax.tax_amount_after_discount_amount + tax.base_tax_amount = tax.base_tax_amount_after_discount_amount + tax.item_wise_tax_detail = tax.item_wise_tax_detail + existing_taxes.append(tax) + + target_doc.set("taxes", existing_taxes) + + @frappe.whitelist() -def make_purchase_invoice(source_name, target_doc=None): +def make_purchase_invoice(source_name, target_doc=None, args=None): from erpnext.accounts.party import get_payment_terms_template doc = frappe.get_doc("Purchase Receipt", source_name) @@ -1142,6 +1173,10 @@ def make_purchase_invoice(source_name, target_doc=None): ) doc.run_method("onload") doc.run_method("set_missing_values") + + if args and args.get("merge_taxes"): + merge_taxes(source.get("taxes") or [], doc) + doc.run_method("calculate_taxes_and_totals") doc.set_payment_schedule() @@ -1205,7 +1240,11 @@ def make_purchase_invoice(source_name, target_doc=None): if not doc.get("is_return") else get_pending_qty(d)[0] > 0, }, - "Purchase Taxes and Charges": {"doctype": "Purchase Taxes and Charges", "add_if_empty": True}, + "Purchase Taxes and Charges": { + "doctype": "Purchase Taxes and Charges", + "add_if_empty": True, + "ignore": args.get("merge_taxes") if args else 0, + }, }, target_doc, set_missing_values, From a117ef3cb88223f0a9f94f863e232b2771b277c8 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Thu, 28 Dec 2023 11:14:27 +0530 Subject: [PATCH 122/205] fix: not able to cancel sales invoice (#38979) --- .../accounts/doctype/purchase_invoice/purchase_invoice.js | 4 +++- erpnext/accounts/doctype/sales_invoice/sales_invoice.js | 5 ++++- erpnext/public/js/controllers/transaction.js | 5 +++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js index 215d8ec215..44d4d81643 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -35,7 +35,7 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying. super.onload(); // Ignore linked advances - this.frm.ignore_doctypes_on_cancel_all = ['Journal Entry', 'Payment Entry', 'Purchase Invoice', "Repost Payment Ledger", "Repost Accounting Ledger", "Unreconcile Payment", "Unreconcile Payment Entries"]; + this.frm.ignore_doctypes_on_cancel_all = ['Journal Entry', 'Payment Entry', 'Purchase Invoice', "Repost Payment Ledger", "Repost Accounting Ledger", "Unreconcile Payment", "Unreconcile Payment Entries", "Serial and Batch Bundle"]; if(!this.frm.doc.__islocal) { // show credit_to in print format @@ -408,6 +408,8 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying. } on_submit() { + super.on_submit(); + $.each(this.frm.doc["items"] || [], function(i, row) { if(row.purchase_receipt) frappe.model.clear_doc("Purchase Receipt", row.purchase_receipt) }) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index 6763e446a5..c8d92d0d70 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -37,7 +37,9 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends e super.onload(); this.frm.ignore_doctypes_on_cancel_all = ['POS Invoice', 'Timesheet', 'POS Invoice Merge Log', - 'POS Closing Entry', 'Journal Entry', 'Payment Entry', "Repost Payment Ledger", "Repost Accounting Ledger", "Unreconcile Payment", "Unreconcile Payment Entries"]; + 'POS Closing Entry', 'Journal Entry', 'Payment Entry', "Repost Payment Ledger", "Repost Accounting Ledger", "Unreconcile Payment", "Unreconcile Payment Entries", + 'Serial and Batch Bundle' + ]; if(!this.frm.doc.__islocal && !this.frm.doc.customer && this.frm.doc.debit_to) { // show debit_to in print format @@ -197,6 +199,7 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends e on_submit(doc, dt, dn) { var me = this; + super.on_submit(); if (frappe.get_route()[0] != 'Form') { return } diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 39357834ed..9427c38064 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -715,6 +715,11 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe } on_submit() { + if (in_list(["Purchase Invoice", "Sales Invoice"], this.frm.doc.doctype) + && !this.frm.doc.update_stock) { + return; + } + this.refresh_serial_batch_bundle_field(); } From b71b0d599775cd445acb555f7df6f849056a7a9b Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Thu, 28 Dec 2023 14:15:40 +0530 Subject: [PATCH 123/205] fix: remove bad defaults (#38986) Child tables can't have a default. --- .../cashier_closing/cashier_closing.json | 371 ++---------------- .../selling/doctype/customer/customer.json | 3 +- erpnext/stock/tests/test_valuation.py | 1 - 3 files changed, 34 insertions(+), 341 deletions(-) diff --git a/erpnext/accounts/doctype/cashier_closing/cashier_closing.json b/erpnext/accounts/doctype/cashier_closing/cashier_closing.json index 1b38f0d36d..051b44b586 100644 --- a/erpnext/accounts/doctype/cashier_closing/cashier_closing.json +++ b/erpnext/accounts/doctype/cashier_closing/cashier_closing.json @@ -1,457 +1,152 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, + "actions": [], "autoname": "naming_series:", - "beta": 0, "creation": "2018-06-18 16:51:49.994750", - "custom": 0, - "docstatus": 0, "doctype": "DocType", - "document_type": "", "editable_grid": 1, "engine": "InnoDB", + "field_order": [ + "naming_series", + "user", + "date", + "from_time", + "time", + "expense", + "custody", + "returns", + "outstanding_amount", + "payments", + "net_amount", + "amended_from" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "POS-CLO-", "fieldname": "naming_series", "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, "in_filter": 1, "in_global_search": 1, - "in_list_view": 0, "in_standard_filter": 1, "label": "Series", - "length": 0, - "no_copy": 0, "options": "POS-CLO-", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "user", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, "in_filter": 1, - "in_global_search": 0, "in_list_view": 1, "in_standard_filter": 1, "label": "User", - "length": 0, - "no_copy": 0, "options": "User", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "Today", "fieldname": "date", "fieldtype": "Date", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, "in_filter": 1, - "in_global_search": 0, - "in_list_view": 0, "in_standard_filter": 1, "label": "Date", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "from_time", "fieldtype": "Time", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, "in_filter": 1, - "in_global_search": 0, - "in_list_view": 0, "in_standard_filter": 1, "label": "From Time", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "", "fieldname": "time", "fieldtype": "Time", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, "in_filter": 1, - "in_global_search": 0, - "in_list_view": 0, "in_standard_filter": 1, "label": "To Time", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "reqd": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "0.00", "fieldname": "expense", "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, "in_filter": 1, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Expense", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Expense" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "0.00", "fieldname": "custody", "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, "in_filter": 1, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Custody", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "label": "Custody" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "0.00", "fieldname": "returns", "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, "in_filter": 1, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Returns", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "2", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 + "precision": "2" }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "default": "0.00", "fieldname": "outstanding_amount", "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Outstanding Amount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "0.0", "fieldname": "payments", "fieldtype": "Table", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, "in_filter": 1, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Payments", - "length": 0, - "no_copy": 0, - "options": "Cashier Closing Payments", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "options": "Cashier Closing Payments" }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "net_amount", "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, "in_filter": 1, - "in_global_search": 0, "in_list_view": 1, "in_standard_filter": 1, "label": "Net Amount", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, "fieldname": "amended_from", "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, "label": "Amended From", - "length": 0, "no_copy": 1, "options": "Cashier Closing", - "permlevel": 0, "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "read_only": 1 } ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, "is_submittable": 1, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2019-02-19 08:35:24.157327", + "links": [], + "modified": "2023-12-28 13:15:46.858427", "modified_by": "Administrator", "module": "Accounts", "name": "Cashier Closing", - "name_case": "", + "naming_rule": "By \"Naming Series\" field", "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, "create": 1, "delete": 1, "email": 1, "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, "print": 1, "read": 1, "report": 1, "role": "System Manager", - "set_user_permissions": 0, "share": 1, "submit": 1, "write": 1 } ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, "sort_field": "modified", "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 -} + "states": [], + "track_changes": 1 +} \ No newline at end of file diff --git a/erpnext/selling/doctype/customer/customer.json b/erpnext/selling/doctype/customer/customer.json index 31bbbcf51b..db712d96b5 100644 --- a/erpnext/selling/doctype/customer/customer.json +++ b/erpnext/selling/doctype/customer/customer.json @@ -448,7 +448,6 @@ "report_hide": 1 }, { - "default": "0", "fieldname": "credit_limits", "fieldtype": "Table", "label": "Credit Limit", @@ -584,7 +583,7 @@ "link_fieldname": "party" } ], - "modified": "2023-10-19 16:56:27.327035", + "modified": "2023-12-28 13:15:36.298369", "modified_by": "Administrator", "module": "Selling", "name": "Customer", diff --git a/erpnext/stock/tests/test_valuation.py b/erpnext/stock/tests/test_valuation.py index 05f153b4a0..4d8990ae40 100644 --- a/erpnext/stock/tests/test_valuation.py +++ b/erpnext/stock/tests/test_valuation.py @@ -195,7 +195,6 @@ class TestFIFOValuation(unittest.TestCase): total_value -= sum(q * r for q, r in consumed) self.assertTotalQty(total_qty) self.assertTotalValue(total_value) - self.assertGreaterEqual(total_value, 0) class TestLIFOValuation(unittest.TestCase): From 855561729544770d77106bc1e4e4a964884377ea Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Thu, 28 Dec 2023 11:39:55 +0530 Subject: [PATCH 124/205] test: profit and loss report output --- .../test_profit_and_loss_statement.py | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 erpnext/accounts/report/profit_and_loss_statement/test_profit_and_loss_statement.py diff --git a/erpnext/accounts/report/profit_and_loss_statement/test_profit_and_loss_statement.py b/erpnext/accounts/report/profit_and_loss_statement/test_profit_and_loss_statement.py new file mode 100644 index 0000000000..b4423abc7f --- /dev/null +++ b/erpnext/accounts/report/profit_and_loss_statement/test_profit_and_loss_statement.py @@ -0,0 +1,94 @@ +# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors +# MIT License. See license.txt + +import frappe +from frappe.tests.utils import FrappeTestCase +from frappe.utils import add_days, getdate, today + +from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice +from erpnext.accounts.report.financial_statements import get_period_list +from erpnext.accounts.report.profit_and_loss_statement.profit_and_loss_statement import execute +from erpnext.accounts.test.accounts_mixin import AccountsTestMixin + + +class TestProfitAndLossStatement(AccountsTestMixin, FrappeTestCase): + def setUp(self): + self.create_company() + self.create_customer() + self.create_item() + + def tearDown(self): + frappe.db.rollback() + + def create_sales_invoice(self, qty=1, rate=150, no_payment_schedule=False, do_not_submit=False): + frappe.set_user("Administrator") + si = create_sales_invoice( + item=self.item, + company=self.company, + customer=self.customer, + debit_to=self.debit_to, + posting_date=today(), + parent_cost_center=self.cost_center, + cost_center=self.cost_center, + rate=rate, + price_list_rate=rate, + qty=qty, + do_not_save=1, + ) + si = si.save() + if not do_not_submit: + si = si.submit() + return si + + def get_fiscal_year(self): + active_fy = frappe.db.get_all( + "Fiscal Year", + filters={"disabled": 0, "year_start_date": ("<=", today()), "year_end_date": (">=", today())}, + )[0] + return frappe.get_doc("Fiscal Year", active_fy.name) + + def get_report_filters(self): + fy = self.get_fiscal_year() + return frappe._dict( + company=self.company, + from_fiscal_year=fy.name, + to_fiscal_year=fy.name, + period_start_date=fy.year_start_date, + period_end_date=fy.year_end_date, + filter_based_on="Fiscal Year", + periodicity="Monthly", + accumulated_vallues=True, + ) + + def test_profit_and_loss_output_and_summary(self): + si = self.create_sales_invoice(qty=1, rate=150) + + filters = self.get_report_filters() + period_list = get_period_list( + filters.from_fiscal_year, + filters.to_fiscal_year, + filters.period_start_date, + filters.period_end_date, + filters.filter_based_on, + filters.periodicity, + company=filters.company, + ) + + result = execute(filters)[1] + current_period = [x for x in period_list if x.from_date <= getdate() and x.to_date >= getdate()][ + 0 + ] + current_period_key = current_period.key + without_current_period = [x for x in period_list if x.key != current_period.key] + # all period except current period(whence invoice was posted), should be '0' + for acc in result: + if acc: + with self.subTest(acc=acc): + for period in without_current_period: + self.assertEqual(acc[period.key], 0) + + for acc in result: + if acc: + with self.subTest(current_period_key=current_period_key): + self.assertEqual(acc[current_period_key], 150) + self.assertEqual(acc["total"], 150) From bbee9b56377f24109217515360789558566f6aa1 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 28 Dec 2023 17:50:16 +0530 Subject: [PATCH 125/205] fix: Opening balance in bank reconciliation tool (#38977) --- .../bank_reconciliation_tool/bank_reconciliation_tool.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.js b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.js index d961ead642..1f2d6ce59a 100644 --- a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.js +++ b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.js @@ -137,7 +137,7 @@ frappe.ui.form.on("Bank Reconciliation Tool", { "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_account_balance", args: { bank_account: frm.doc.bank_account, - till_date: frm.doc.bank_statement_from_date, + till_date: frappe.datetime.add_days(frm.doc.bank_statement_from_date, -1) }, callback: (response) => { frm.set_value("account_opening_balance", response.message); From 10074e9980c8f2a1473827c61c888d970da4b73a Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Thu, 28 Dec 2023 17:56:24 +0530 Subject: [PATCH 126/205] fix: serial and batch bundle company mandatory error (#38994) --- .../serial_and_batch_bundle.py | 12 +++--- .../test_serial_and_batch_bundle.py | 40 +++++++++++++++++++ 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index dd38e1127f..a4fb5324ee 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -1145,15 +1145,16 @@ def add_serial_batch_ledgers(entries, child_row, doc, warehouse) -> object: if isinstance(entries, str): entries = parse_json(entries) - if doc and isinstance(doc, str): - parent_doc = parse_json(doc) + parent_doc = doc + if parent_doc and isinstance(parent_doc, str): + parent_doc = parse_json(parent_doc) if frappe.db.exists("Serial and Batch Bundle", child_row.serial_and_batch_bundle): - doc = update_serial_batch_no_ledgers(entries, child_row, parent_doc, warehouse) + sb_doc = update_serial_batch_no_ledgers(entries, child_row, parent_doc, warehouse) else: - doc = create_serial_batch_no_ledgers(entries, child_row, parent_doc, warehouse) + sb_doc = create_serial_batch_no_ledgers(entries, child_row, parent_doc, warehouse) - return doc + return sb_doc def create_serial_batch_no_ledgers(entries, child_row, parent_doc, warehouse=None) -> object: @@ -1177,6 +1178,7 @@ def create_serial_batch_no_ledgers(entries, child_row, parent_doc, warehouse=Non "type_of_transaction": type_of_transaction, "posting_date": parent_doc.get("posting_date"), "posting_time": parent_doc.get("posting_time"), + "company": parent_doc.get("company"), } ) diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py index d74d657f38..478cfa4d1c 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py @@ -8,6 +8,9 @@ from frappe.tests.utils import FrappeTestCase from frappe.utils import add_days, add_to_date, flt, nowdate, nowtime, today from erpnext.stock.doctype.item.test_item import make_item +from erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle import ( + add_serial_batch_ledgers, +) from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry @@ -420,6 +423,43 @@ class TestSerialandBatchBundle(FrappeTestCase): ste.delete() self.assertFalse(frappe.db.exists("Serial and Batch Bundle", bundle_doc.name)) + def test_serial_and_batch_bundle_company(self): + from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt + + item = make_item( + properties={ + "has_serial_no": 1, + "serial_no_series": "TT-SER-VAL-.#####", + } + ) + + pr = make_purchase_receipt( + item_code=item, + warehouse="_Test Warehouse - _TC", + qty=3, + rate=500, + do_not_submit=True, + ) + + entries = [] + for serial_no in ["TT-SER-VAL-00001", "TT-SER-VAL-00002", "TT-SER-VAL-00003"]: + entries.append(frappe._dict({"serial_no": serial_no, "qty": 1})) + + if not frappe.db.exists("Serial No", serial_no): + frappe.get_doc( + { + "doctype": "Serial No", + "serial_no": serial_no, + "item_code": item, + } + ).insert(ignore_permissions=True) + + item_row = pr.items[0] + item_row.type_of_transaction = "Inward" + item_row.is_rejected = 0 + sn_doc = add_serial_batch_ledgers(entries, item_row, pr, "_Test Warehouse - _TC") + self.assertEqual(sn_doc.company, "_Test Company") + def get_batch_from_bundle(bundle): from erpnext.stock.serial_batch_bundle import get_batch_nos From b5340c5ec0d418dcf764efa961f743f88b660a24 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Thu, 28 Dec 2023 18:32:27 +0530 Subject: [PATCH 127/205] fix: auto fetch not working if bundle exists (#39002) --- erpnext/public/js/utils/serial_no_batch_selector.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/erpnext/public/js/utils/serial_no_batch_selector.js b/erpnext/public/js/utils/serial_no_batch_selector.js index 4cd1243413..bf362e338e 100644 --- a/erpnext/public/js/utils/serial_no_batch_selector.js +++ b/erpnext/public/js/utils/serial_no_batch_selector.js @@ -337,16 +337,18 @@ erpnext.SerialBatchPackageSelector = class SerialNoBatchBundleUpdate { } get_auto_data() { + let { qty, based_on } = this.dialog.get_values(); + if (this.item.serial_and_batch_bundle || this.item.rejected_serial_and_batch_bundle) { - return; + if (qty === this.qty) { + return; + } } if (this.item.serial_no || this.item.batch_no) { return; } - let { qty, based_on } = this.dialog.get_values(); - if (!based_on) { based_on = 'FIFO'; } From 3b4b2275de7a49ba48b09f7229bee45f1e890ac9 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Fri, 29 Dec 2023 08:25:38 +0530 Subject: [PATCH 128/205] fix: Multiple subscription fixes (#39005) --- .../doctype/subscription/subscription.json | 6 +++--- .../doctype/subscription/subscription.py | 19 ++++++++++++------- erpnext/controllers/accounts_controller.py | 5 +++++ 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/erpnext/accounts/doctype/subscription/subscription.json b/erpnext/accounts/doctype/subscription/subscription.json index 187b7abce1..97fd4d040f 100644 --- a/erpnext/accounts/doctype/subscription/subscription.json +++ b/erpnext/accounts/doctype/subscription/subscription.json @@ -148,13 +148,13 @@ { "fieldname": "additional_discount_percentage", "fieldtype": "Percent", - "label": "Additional DIscount Percentage" + "label": "Additional Discount Percentage" }, { "collapsible": 1, "fieldname": "additional_discount_amount", "fieldtype": "Currency", - "label": "Additional DIscount Amount" + "label": "Additional Discount Amount" }, { "collapsible": 1, @@ -267,7 +267,7 @@ "link_fieldname": "subscription" } ], - "modified": "2023-09-18 17:48:21.900252", + "modified": "2023-12-28 17:20:42.687789", "modified_by": "Administrator", "module": "Accounts", "name": "Subscription", diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py index aba1b64930..72e574c299 100644 --- a/erpnext/accounts/doctype/subscription/subscription.py +++ b/erpnext/accounts/doctype/subscription/subscription.py @@ -356,18 +356,20 @@ class Subscription(Document): self, from_date: Optional[Union[str, datetime.date]] = None, to_date: Optional[Union[str, datetime.date]] = None, + posting_date: Optional[Union[str, datetime.date]] = None, ) -> Document: """ Creates a `Invoice` for the `Subscription`, updates `self.invoices` and saves the `Subscription`. Backwards compatibility """ - return self.create_invoice(from_date=from_date, to_date=to_date) + return self.create_invoice(from_date=from_date, to_date=to_date, posting_date=posting_date) def create_invoice( self, from_date: Optional[Union[str, datetime.date]] = None, to_date: Optional[Union[str, datetime.date]] = None, + posting_date: Optional[Union[str, datetime.date]] = None, ) -> Document: """ Creates a `Invoice`, submits it and returns it @@ -385,11 +387,13 @@ class Subscription(Document): invoice = frappe.new_doc(self.invoice_document_type) invoice.company = company invoice.set_posting_time = 1 - invoice.posting_date = ( - self.current_invoice_start - if self.generate_invoice_at == "Beginning of the current subscription period" - else self.current_invoice_end - ) + + if self.generate_invoice_at == "Beginning of the current subscription period": + invoice.posting_date = self.current_invoice_start + elif self.generate_invoice_at == "Days before the current subscription period": + invoice.posting_date = posting_date or self.current_invoice_start + else: + invoice.posting_date = self.current_invoice_end invoice.cost_center = self.cost_center @@ -413,6 +417,7 @@ class Subscription(Document): # Subscription is better suited for service items. I won't update `update_stock` # for that reason items_list = self.get_items_from_plans(self.plans, is_prorate()) + for item in items_list: item["cost_center"] = self.cost_center invoice.append("items", item) @@ -556,7 +561,7 @@ class Subscription(Document): if not self.is_current_invoice_generated( self.current_invoice_start, self.current_invoice_end ) and self.can_generate_new_invoice(posting_date): - self.generate_invoice() + self.generate_invoice(posting_date=posting_date) self.update_subscription_period(add_days(self.current_invoice_end, 1)) if self.cancel_at_period_end and ( diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index febad18058..cb0cac6cad 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -225,6 +225,11 @@ class AccountsController(TransactionBase): apply_pricing_rule_on_transaction(self) self.set_total_in_words() + self.set_default_letter_head() + + def set_default_letter_head(self): + if hasattr(self, "letter_head") and not self.letter_head: + self.letter_head = frappe.db.get_value("Company", self.company, "default_letter_head") def init_internal_values(self): # init all the internal values as 0 on sa From f983e09f92c6fb179e8e8a972b1cb969b40c8fd5 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Fri, 29 Dec 2023 12:06:04 +0530 Subject: [PATCH 129/205] fix: purchase return without item code not working (#39014) --- .../purchase_invoice/test_purchase_invoice.py | 21 +++++++++++++++++++ .../controllers/sales_and_purchase_return.py | 17 ++++++++------- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index e43ea6ecbe..e41cec7eee 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -1985,6 +1985,26 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin): self.assertEqual(pi.items[0].cost_center, "_Test Cost Center Buying - _TC") + def test_debit_note_without_item(self): + pi = make_purchase_invoice(item_name="_Test Item", qty=10, do_not_submit=True) + pi.items[0].item_code = "" + pi.save() + + self.assertFalse(pi.items[0].item_code) + pi.submit() + + return_pi = make_purchase_invoice( + item_name="_Test Item", + is_return=1, + return_against=pi.name, + qty=-10, + do_not_save=True, + ) + return_pi.items[0].item_code = "" + return_pi.save() + return_pi.submit() + self.assertEqual(return_pi.docstatus, 1) + def set_advance_flag(company, flag, default_account): frappe.db.set_value( @@ -2121,6 +2141,7 @@ def make_purchase_invoice(**args): "items", { "item_code": args.item or args.item_code or "_Test Item", + "item_name": args.item_name, "warehouse": args.warehouse or "_Test Warehouse - _TC", "qty": args.qty or 5, "received_qty": args.received_qty or 0, diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py index 81080f0266..e7bd2a7265 100644 --- a/erpnext/controllers/sales_and_purchase_return.py +++ b/erpnext/controllers/sales_and_purchase_return.py @@ -562,16 +562,17 @@ def make_return_doc( if default_warehouse_for_sales_return: target_doc.warehouse = default_warehouse_for_sales_return - item_details = frappe.get_cached_value( - "Item", source_doc.item_code, ["has_batch_no", "has_serial_no"], as_dict=1 - ) + if source_doc.item_code: + item_details = frappe.get_cached_value( + "Item", source_doc.item_code, ["has_batch_no", "has_serial_no"], as_dict=1 + ) - if not item_details.has_batch_no and not item_details.has_serial_no: - return + if not item_details.has_batch_no and not item_details.has_serial_no: + return - for qty_field in ["stock_qty", "rejected_qty"]: - if target_doc.get(qty_field): - update_serial_batch_no(source_doc, target_doc, source_parent, item_details, qty_field) + for qty_field in ["stock_qty", "rejected_qty"]: + if target_doc.get(qty_field): + update_serial_batch_no(source_doc, target_doc, source_parent, item_details, qty_field) def update_terms(source_doc, target_doc, source_parent): target_doc.payment_amount = -source_doc.payment_amount From cd37fd790b9d7a28b9df8697c9b40c5477a580ec Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Fri, 29 Dec 2023 12:52:22 +0530 Subject: [PATCH 130/205] fix: Validate account in Sales/Purchase Taxes and Charges Template (#39013) --- erpnext/controllers/accounts_controller.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index cb0cac6cad..729bb67182 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -2431,6 +2431,7 @@ def validate_taxes_and_charges(tax): def validate_account_head(idx, account, company, context=""): account_company = frappe.get_cached_value("Account", account, "company") + is_group = frappe.get_cached_value("Account", account, "is_group") if account_company != company: frappe.throw( @@ -2440,6 +2441,12 @@ def validate_account_head(idx, account, company, context=""): title=_("Invalid Account"), ) + if is_group: + frappe.throw( + _("Row {0}: Account {1} is a Group Account").format(idx, frappe.bold(account)), + title=_("Invalid Account"), + ) + def validate_cost_center(tax, doc): if not tax.cost_center: From b7f283b2f039b97997d938f9159ae045de44aba1 Mon Sep 17 00:00:00 2001 From: Gursheen Kaur Anand <40693548+GursheenK@users.noreply.github.com> Date: Fri, 29 Dec 2023 12:55:37 +0530 Subject: [PATCH 131/205] feat: skip disabled accounts in COA (#38551) * feat: skip disabled accounts in coa * fix: add parameter to other tree doctype utils --- erpnext/accounts/utils.py | 6 +++++- erpnext/setup/doctype/department/department.py | 7 ++++++- erpnext/stock/doctype/warehouse/warehouse.py | 7 ++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index adec0ab4e0..f9208f051e 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -1116,12 +1116,16 @@ def get_companies(): @frappe.whitelist() -def get_children(doctype, parent, company, is_root=False): +def get_children(doctype, parent, company, is_root=False, include_disabled=False): + if isinstance(include_disabled, str): + include_disabled = frappe.json.loads(include_disabled) from erpnext.accounts.report.financial_statements import sort_accounts parent_fieldname = "parent_" + doctype.lower().replace(" ", "_") fields = ["name as value", "is_group as expandable"] filters = [["docstatus", "<", 2]] + if frappe.db.has_column(doctype, "disabled") and not include_disabled: + filters.append(["disabled", "=", False]) filters.append(['ifnull(`{0}`,"")'.format(parent_fieldname), "=", "" if is_root else parent]) diff --git a/erpnext/setup/doctype/department/department.py b/erpnext/setup/doctype/department/department.py index 16f6fbfba4..b36f032d4c 100644 --- a/erpnext/setup/doctype/department/department.py +++ b/erpnext/setup/doctype/department/department.py @@ -69,7 +69,9 @@ def get_abbreviated_name(name, company): @frappe.whitelist() -def get_children(doctype, parent=None, company=None, is_root=False): +def get_children(doctype, parent=None, company=None, is_root=False, include_disabled=False): + if isinstance(include_disabled, str): + include_disabled = frappe.json.loads(include_disabled) fields = ["name as value", "is_group as expandable"] filters = {} @@ -81,6 +83,9 @@ def get_children(doctype, parent=None, company=None, is_root=False): else: filters["parent_department"] = parent + if frappe.db.has_column(doctype, "disabled") and not include_disabled: + filters["disabled"] = False + return frappe.get_all("Department", fields=fields, filters=filters, order_by="name") diff --git a/erpnext/stock/doctype/warehouse/warehouse.py b/erpnext/stock/doctype/warehouse/warehouse.py index ef9b12eca2..07b354a4df 100644 --- a/erpnext/stock/doctype/warehouse/warehouse.py +++ b/erpnext/stock/doctype/warehouse/warehouse.py @@ -183,15 +183,20 @@ class Warehouse(NestedSet): @frappe.whitelist() -def get_children(doctype, parent=None, company=None, is_root=False): +def get_children(doctype, parent=None, company=None, is_root=False, include_disabled=False): if is_root: parent = "" + if isinstance(include_disabled, str): + include_disabled = frappe.json.loads(include_disabled) + fields = ["name as value", "is_group as expandable"] filters = [ ["ifnull(`parent_warehouse`, '')", "=", parent], ["company", "in", (company, None, "")], ] + if frappe.db.has_column(doctype, "disabled") and not include_disabled: + filters.append(["disabled", "=", False]) return frappe.get_list(doctype, fields=fields, filters=filters, order_by="name") From a517125d64a48b61a9b2d943b3a01bfe8ae87f41 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 29 Dec 2023 13:35:18 +0530 Subject: [PATCH 132/205] refactor(perf): replace account subquery with 'in' condition --- .../customer_ledger_summary.py | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py index 4765e3b318..0464f99d20 100644 --- a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py +++ b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py @@ -3,7 +3,7 @@ import frappe -from frappe import _, scrub +from frappe import _, qb, scrub from frappe.utils import getdate, nowdate @@ -38,7 +38,6 @@ class PartyLedgerSummaryReport(object): """ Additional Columns for 'User Permission' based access control """ - from frappe import qb if self.filters.party_type == "Customer": self.territories = frappe._dict({}) @@ -365,13 +364,29 @@ class PartyLedgerSummaryReport(object): def get_party_adjustment_amounts(self): conditions = self.prepare_conditions() - income_or_expense = ( - "Expense Account" if self.filters.party_type == "Customer" else "Income Account" + account_type = "Expense Account" if self.filters.party_type == "Customer" else "Income Account" + income_or_expense_accounts = frappe.db.get_all( + "Account", filters={"account_type": account_type, "company": self.filters.company}, pluck="name" ) invoice_dr_or_cr = "debit" if self.filters.party_type == "Customer" else "credit" reverse_dr_or_cr = "credit" if self.filters.party_type == "Customer" else "debit" round_off_account = frappe.get_cached_value("Company", self.filters.company, "round_off_account") + gl = qb.DocType("GL Entry") + if not income_or_expense_accounts: + # prevent empty 'in' condition + income_or_expense_accounts.append("") + + accounts_query = ( + qb.from_(gl) + .select(gl.voucher_type, gl.voucher_no) + .where( + (gl.account.isin(income_or_expense_accounts)) + & (gl.posting_date.gte(self.filters.from_date)) + & (gl.posting_date.lte(self.filters.to_date)) + ) + ) + gl_entries = frappe.db.sql( """ select @@ -381,16 +396,15 @@ class PartyLedgerSummaryReport(object): where docstatus < 2 and is_cancelled = 0 and (voucher_type, voucher_no) in ( - select voucher_type, voucher_no from `tabGL Entry` gle, `tabAccount` acc - where acc.name = gle.account and acc.account_type = '{income_or_expense}' - and gle.posting_date between %(from_date)s and %(to_date)s and gle.docstatus < 2 + {accounts_query} ) and (voucher_type, voucher_no) in ( select voucher_type, voucher_no from `tabGL Entry` gle where gle.party_type=%(party_type)s and ifnull(party, '') != '' and gle.posting_date between %(from_date)s and %(to_date)s and gle.docstatus < 2 {conditions} ) - """.format( - conditions=conditions, income_or_expense=income_or_expense + """.format( + accounts_query=accounts_query, + conditions=conditions, ), self.filters, as_dict=True, @@ -414,7 +428,7 @@ class PartyLedgerSummaryReport(object): elif gle.party: parties.setdefault(gle.party, 0) parties[gle.party] += gle.get(reverse_dr_or_cr) - gle.get(invoice_dr_or_cr) - elif frappe.get_cached_value("Account", gle.account, "account_type") == income_or_expense: + elif frappe.get_cached_value("Account", gle.account, "account_type") == account_type: accounts.setdefault(gle.account, 0) accounts[gle.account] += gle.get(invoice_dr_or_cr) - gle.get(reverse_dr_or_cr) else: From 0c6de4ecb299daf5359fcd51041942a26f94693d Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Fri, 29 Dec 2023 16:50:01 +0530 Subject: [PATCH 133/205] fix: non stock uom validation for serial and batch (#39018) * fix: non stock uom validation for serial and batch * test: delivery note for batch with non stock uom --- .../doctype/sales_invoice/sales_invoice.py | 2 + .../sales_invoice/test_sales_invoice.py | 5 ++- .../sales_invoice_item.json | 9 ++++- .../doctype/delivery_note/delivery_note.py | 2 + .../delivery_note/test_delivery_note.py | 40 +++++++++++++++++++ .../serial_and_batch_bundle.py | 6 ++- 6 files changed, 60 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 2cddb863c6..649b3f7ad4 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -586,6 +586,8 @@ class SalesInvoice(SellingController): "Serial and Batch Bundle", ) + self.delete_auto_created_batches() + def update_status_updater_args(self): if cint(self.update_stock): self.status_updater.append( diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 6163749c4f..1fc3f795b8 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -1414,10 +1414,11 @@ class TestSalesInvoice(FrappeTestCase): def test_serialized_cancel(self): si = self.test_serialized() - si.cancel() - + si.reload() serial_nos = get_serial_nos_from_bundle(si.get("items")[0].serial_and_batch_bundle) + si.cancel() + self.assertEqual( frappe.db.get_value("Serial No", serial_nos[0], "warehouse"), "_Test Warehouse - _TC" ) diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json index a403b14c54..ec9e792d7d 100644 --- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json +++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json @@ -81,6 +81,7 @@ "warehouse", "target_warehouse", "quality_inspection", + "pick_serial_and_batch", "serial_and_batch_bundle", "batch_no", "incoming_rate", @@ -897,12 +898,18 @@ "options": "Serial and Batch Bundle", "print_hide": 1, "search_index": 1 + }, + { + "depends_on": "eval:parent.update_stock === 1", + "fieldname": "pick_serial_and_batch", + "fieldtype": "Button", + "label": "Pick Serial / Batch No" } ], "idx": 1, "istable": 1, "links": [], - "modified": "2023-11-14 18:34:10.479329", + "modified": "2023-12-29 13:03:14.121298", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice Item", diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index 132f8f2e29..7d7b0cd476 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -431,6 +431,8 @@ class DeliveryNote(SellingController): "Serial and Batch Bundle", ) + self.delete_auto_created_batches() + def update_stock_reservation_entries(self) -> None: """Updates Delivered Qty in Stock Reservation Entries.""" diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index 933be53b07..3abd1d9e5e 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -1478,6 +1478,46 @@ class TestDeliveryNote(FrappeTestCase): returned_dn.reload() self.assertAlmostEqual(returned_dn.items[0].incoming_rate, 200.0) + def test_batch_with_non_stock_uom(self): + frappe.db.set_single_value( + "Stock Settings", "auto_create_serial_and_batch_bundle_for_outward", 1 + ) + + item = make_item( + properties={ + "has_batch_no": 1, + "create_new_batch": 1, + "batch_number_series": "TESTBATCH.#####", + "stock_uom": "Nos", + } + ) + if not frappe.db.exists("UOM Conversion Detail", {"parent": item.name, "uom": "Kg"}): + item.append("uoms", {"uom": "Kg", "conversion_factor": 5.0}) + item.save() + + item_code = item.name + + make_stock_entry(item_code=item_code, target="_Test Warehouse - _TC", qty=5, basic_rate=100.0) + dn = create_delivery_note( + item_code=item_code, qty=1, rate=500, warehouse="_Test Warehouse - _TC", do_not_save=True + ) + dn.items[0].uom = "Kg" + dn.items[0].conversion_factor = 5.0 + + dn.save() + dn.submit() + + self.assertEqual(dn.items[0].stock_qty, 5.0) + voucher_detail_no = dn.items[0].name + delivered_batch_qty = frappe.db.get_value( + "Serial and Batch Bundle", {"voucher_detail_no": voucher_detail_no}, "total_qty" + ) + self.assertEqual(abs(delivered_batch_qty), 5.0) + + frappe.db.set_single_value( + "Stock Settings", "auto_create_serial_and_batch_bundle_for_outward", 0 + ) + def create_delivery_note(**args): dn = frappe.new_doc("Delivery Note") diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index a4fb5324ee..774e5c657d 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -483,7 +483,11 @@ class SerialandBatchBundle(Document): if row.get("doctype") in ["Subcontracting Receipt Supplied Item"]: qty_field = "consumed_qty" - if abs(abs(flt(self.total_qty, precision)) - abs(flt(row.get(qty_field), precision))) > 0.01: + qty = row.get(qty_field) + if qty_field == "qty" and row.get("stock_qty"): + qty = row.get("stock_qty") + + if abs(abs(flt(self.total_qty, precision)) - abs(flt(qty, precision))) > 0.01: self.throw_error_message( f"Total quantity {abs(flt(self.total_qty))} in the Serial and Batch Bundle {bold(self.name)} does not match with the quantity {abs(flt(row.get(qty_field)))} for the Item {bold(self.item_code)} in the {self.voucher_type} # {self.voucher_no}" ) From 70abedc57ad2147719c23537ab9aaf348d6e9182 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Fri, 29 Dec 2023 16:50:31 +0530 Subject: [PATCH 134/205] fix: work order with multi level, fetch operting cost from sub-assembly (#38992) --- erpnext/manufacturing/doctype/bom/bom.py | 44 ++++++++++ .../manufacturing_settings.json | 11 ++- .../manufacturing_settings.py | 1 + .../production_plan/test_production_plan.py | 4 + .../doctype/work_order/test_work_order.py | 88 +++++++++++++++++++ .../stock/doctype/stock_entry/stock_entry.py | 37 ++++++-- 6 files changed, 178 insertions(+), 7 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index d86b6d426e..f034ed2b1a 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -1491,3 +1491,47 @@ def make_variant_bom(source_name, bom_no, item, variant_items, target_doc=None): ) return doc + + +def get_op_cost_from_sub_assemblies(bom_no, op_cost=0): + # Get operating cost from sub-assemblies + + bom_items = frappe.get_all( + "BOM Item", filters={"parent": bom_no, "docstatus": 1}, fields=["bom_no"], order_by="idx asc" + ) + + for row in bom_items: + if not row.bom_no: + continue + + if cost := frappe.get_cached_value("BOM", row.bom_no, "operating_cost_per_bom_quantity"): + op_cost += flt(cost) + get_op_cost_from_sub_assemblies(row.bom_no, op_cost) + + return op_cost + + +def get_scrap_items_from_sub_assemblies(bom_no, company, qty, scrap_items=None): + if not scrap_items: + scrap_items = {} + + bom_items = frappe.get_all( + "BOM Item", + filters={"parent": bom_no, "docstatus": 1}, + fields=["bom_no", "qty"], + order_by="idx asc", + ) + + for row in bom_items: + if not row.bom_no: + continue + + qty = flt(row.qty) * flt(qty) + items = get_bom_items_as_dict( + row.bom_no, company, qty=qty, fetch_exploded=0, fetch_scrap_items=1 + ) + scrap_items.update(items) + + get_scrap_items_from_sub_assemblies(row.bom_no, company, qty, scrap_items) + + return scrap_items diff --git a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json index 01647d56c9..d3ad51f723 100644 --- a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json +++ b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json @@ -31,6 +31,7 @@ "job_card_excess_transfer", "other_settings_section", "update_bom_costs_automatically", + "set_op_cost_and_scrape_from_sub_assemblies", "column_break_23", "make_serial_no_batch_from_work_order" ], @@ -194,13 +195,20 @@ "fieldname": "job_card_excess_transfer", "fieldtype": "Check", "label": "Allow Excess Material Transfer" + }, + { + "default": "0", + "description": "In the case of 'Use Multi-Level BOM' in a work order, if the user wishes to add sub-assembly costs to Finished Goods items without using a job card as well the scrap items, then this option needs to be enable.", + "fieldname": "set_op_cost_and_scrape_from_sub_assemblies", + "fieldtype": "Check", + "label": "Set Operating Cost / Scrape Items From Sub-assemblies" } ], "icon": "icon-wrench", "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2021-09-13 22:09:09.401559", + "modified": "2023-12-28 16:37:44.874096", "modified_by": "Administrator", "module": "Manufacturing", "name": "Manufacturing Settings", @@ -216,5 +224,6 @@ ], "sort_field": "modified", "sort_order": "DESC", + "states": [], "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py index bfc8f4e915..463ba9fe4b 100644 --- a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py +++ b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.py @@ -32,6 +32,7 @@ class ManufacturingSettings(Document): mins_between_operations: DF.Int overproduction_percentage_for_sales_order: DF.Percent overproduction_percentage_for_work_order: DF.Percent + set_op_cost_and_scrape_from_sub_assemblies: DF.Check update_bom_costs_automatically: DF.Check # end: auto-generated types diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py index cb99b8845a..f6dfaa5058 100644 --- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py @@ -1602,6 +1602,10 @@ def make_bom(**args): } ) + if args.operating_cost_per_bom_quantity: + bom.fg_based_operating_cost = 1 + bom.operating_cost_per_bom_quantity = args.operating_cost_per_bom_quantity + for item in args.raw_materials: item_doc = frappe.get_doc("Item", item) bom.append( diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py index e2c8f07980..07c253b232 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -1732,6 +1732,93 @@ class TestWorkOrder(FrappeTestCase): job_card2.time_logs = [] job_card2.save() + def test_op_cost_and_scrap_based_on_sub_assemblies(self): + # Make Sub Assembly BOM 1 + + frappe.db.set_single_value( + "Manufacturing Settings", "set_op_cost_and_scrape_from_sub_assemblies", 1 + ) + + items = { + "Test Final FG Item": 0, + "Test Final SF Item 1": 0, + "Test Final SF Item 2": 0, + "Test Final RM Item 1": 100, + "Test Final RM Item 2": 200, + "Test Final Scrap Item 1": 50, + "Test Final Scrap Item 2": 60, + } + + for item in items: + if not frappe.db.exists("Item", item): + item_properties = {"is_stock_item": 1, "valuation_rate": items[item]} + + make_item(item_code=item, properties=item_properties), + + prepare_boms_for_sub_assembly_test() + + wo_order = make_wo_order_test_record( + production_item="Test Final FG Item", + qty=10, + use_multi_level_bom=1, + skip_transfer=1, + from_wip_warehouse=1, + ) + + se_doc = frappe.get_doc(make_stock_entry(wo_order.name, "Manufacture", 10)) + se_doc.save() + + self.assertTrue(se_doc.additional_costs) + scrap_items = [] + for item in se_doc.items: + if item.is_scrap_item: + scrap_items.append(item.item_code) + + self.assertEqual( + sorted(scrap_items), sorted(["Test Final Scrap Item 1", "Test Final Scrap Item 2"]) + ) + for row in se_doc.additional_costs: + self.assertEqual(row.amount, 3000) + + frappe.db.set_single_value( + "Manufacturing Settings", "set_op_cost_and_scrape_from_sub_assemblies", 0 + ) + + +def prepare_boms_for_sub_assembly_test(): + if not frappe.db.exists("BOM", {"item": "Test Final SF Item 1"}): + bom = make_bom( + item="Test Final SF Item 1", + source_warehouse="Stores - _TC", + raw_materials=["Test Final RM Item 1"], + operating_cost_per_bom_quantity=100, + do_not_submit=True, + ) + + bom.append("scrap_items", {"item_code": "Test Final Scrap Item 1", "qty": 1}) + + bom.submit() + + if not frappe.db.exists("BOM", {"item": "Test Final SF Item 2"}): + bom = make_bom( + item="Test Final SF Item 2", + source_warehouse="Stores - _TC", + raw_materials=["Test Final RM Item 2"], + operating_cost_per_bom_quantity=200, + do_not_submit=True, + ) + + bom.append("scrap_items", {"item_code": "Test Final Scrap Item 2", "qty": 1}) + + bom.submit() + + if not frappe.db.exists("BOM", {"item": "Test Final FG Item"}): + bom = make_bom( + item="Test Final FG Item", + source_warehouse="Stores - _TC", + raw_materials=["Test Final SF Item 1", "Test Final SF Item 2"], + ) + def prepare_data_for_workstation_type_check(): from erpnext.manufacturing.doctype.operation.test_operation import make_operation @@ -1978,6 +2065,7 @@ def make_wo_order_test_record(**args): wo_order.sales_order = args.sales_order or None wo_order.planned_start_date = args.planned_start_date or now() wo_order.transfer_material_against = args.transfer_material_against or "Work Order" + wo_order.from_wip_warehouse = args.from_wip_warehouse or 0 if args.source_warehouse: for item in wo_order.get("required_items"): diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 6521394eef..2ccee94078 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -25,7 +25,12 @@ from frappe.utils import ( import erpnext from erpnext.accounts.general_ledger import process_gl_map from erpnext.controllers.taxes_and_totals import init_landed_taxes_and_totals -from erpnext.manufacturing.doctype.bom.bom import add_additional_cost, validate_bom_no +from erpnext.manufacturing.doctype.bom.bom import ( + add_additional_cost, + get_op_cost_from_sub_assemblies, + get_scrap_items_from_sub_assemblies, + validate_bom_no, +) from erpnext.setup.doctype.brand.brand import get_brand_defaults from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults from erpnext.stock.doctype.batch.batch import get_batch_qty @@ -1908,11 +1913,22 @@ class StockEntry(StockController): def get_bom_scrap_material(self, qty): from erpnext.manufacturing.doctype.bom.bom import get_bom_items_as_dict - # item dict = { item_code: {qty, description, stock_uom} } - item_dict = ( - get_bom_items_as_dict(self.bom_no, self.company, qty=qty, fetch_exploded=0, fetch_scrap_items=1) - or {} - ) + if ( + frappe.db.get_single_value( + "Manufacturing Settings", "set_op_cost_and_scrape_from_sub_assemblies" + ) + and self.work_order + and frappe.get_cached_value("Work Order", self.work_order, "use_multi_level_bom") + ): + item_dict = get_scrap_items_from_sub_assemblies(self.bom_no, self.company, qty) + else: + # item dict = { item_code: {qty, description, stock_uom} } + item_dict = ( + get_bom_items_as_dict( + self.bom_no, self.company, qty=qty, fetch_exploded=0, fetch_scrap_items=1 + ) + or {} + ) for item in item_dict.values(): item.from_warehouse = "" @@ -2663,6 +2679,15 @@ def get_work_order_details(work_order, company): def get_operating_cost_per_unit(work_order=None, bom_no=None): operating_cost_per_unit = 0 if work_order: + if ( + bom_no + and frappe.db.get_single_value( + "Manufacturing Settings", "set_op_cost_and_scrape_from_sub_assemblies" + ) + and frappe.get_cached_value("Work Order", work_order, "use_multi_level_bom") + ): + return get_op_cost_from_sub_assemblies(bom_no) + if not bom_no: bom_no = work_order.bom_no From 877cc7255dfc80cbdd0dab971bcde81f5ebf57ba Mon Sep 17 00:00:00 2001 From: Smit Vora Date: Sun, 31 Dec 2023 10:54:07 +0530 Subject: [PATCH 135/205] fix: enqueue demo data setup on setup complete (#39043) --- erpnext/hooks.py | 1 + erpnext/setup/setup_wizard/setup_wizard.py | 5 ----- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index f6b6802d58..78bb2d2c27 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -37,6 +37,7 @@ welcome_email = "erpnext.setup.utils.welcome_email" # setup wizard setup_wizard_requires = "assets/erpnext/js/setup_wizard.js" setup_wizard_stages = "erpnext.setup.setup_wizard.setup_wizard.get_setup_stages" +setup_wizard_complete = "erpnext.setup.setup_wizard.setup_wizard.setup_demo" setup_wizard_test = "erpnext.setup.setup_wizard.test_setup_wizard.run_setup_wizard_test" before_install = [ diff --git a/erpnext/setup/setup_wizard/setup_wizard.py b/erpnext/setup/setup_wizard/setup_wizard.py index 2da107e4e9..9a49af2b10 100644 --- a/erpnext/setup/setup_wizard/setup_wizard.py +++ b/erpnext/setup/setup_wizard/setup_wizard.py @@ -37,11 +37,6 @@ def get_setup_stages(args=None): {"fn": setup_defaults, "args": args, "fail_msg": _("Failed to setup defaults")}, ], }, - { - "status": _("Setting up demo data"), - "fail_msg": _("Failed to setup demo data"), - "tasks": [{"fn": setup_demo, "args": args, "fail_msg": _("Failed to setup demo data")}], - }, { "status": _("Wrapping up"), "fail_msg": _("Failed to login"), From 3f9693b31f7cf36cbdf95006d81a23da594bd28a Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 31 Dec 2023 20:00:03 +0530 Subject: [PATCH 136/205] fix: GL values in transaction currency via JV (#38914) --- .../doctype/journal_entry/journal_entry.py | 24 +++++++++++++++++++ erpnext/controllers/accounts_controller.py | 6 ++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index 79f1ab063d..ddf6460842 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -1031,6 +1031,10 @@ class JournalEntry(AccountsController): def build_gl_map(self): gl_map = [] + conversion_rate_map = self.get_conversion_rate_map() + transaction_currency_map = self.get_transaction_currency_map() + company_currency = erpnext.get_company_currency(self.company) + self.get_against_accounts() for d in self.get("accounts"): if d.debit or d.credit or (self.voucher_type == "Exchange Gain Or Loss"): @@ -1060,6 +1064,12 @@ class JournalEntry(AccountsController): "cost_center": d.cost_center, "project": d.project, "finance_book": self.finance_book, + "conversion_rate": conversion_rate_map.get(d.against_account_link, 1) + if d.account_currency == company_currency + else 1, + "currency": transaction_currency_map.get(d.against_account_link, d.account_currency) + if d.account_currency == company_currency + else d.account_currency, }, item=d, ) @@ -1109,6 +1119,20 @@ class JournalEntry(AccountsController): return gl_map + def get_transaction_currency_map(self): + transaction_currency_map = {} + for account in self.get("accounts"): + transaction_currency_map.setdefault(account.party or account.account, account.account_currency) + + return transaction_currency_map + + def get_conversion_rate_map(self): + conversion_rate_map = {} + for account in self.get("accounts"): + conversion_rate_map.setdefault(account.party or account.account, account.exchange_rate) + + return conversion_rate_map + def make_gl_entries(self, cancel=0, adv_adj=0): from erpnext.accounts.general_ledger import make_gl_entries diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 729bb67182..13df9d591c 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -922,7 +922,7 @@ class AccountsController(TransactionBase): # Update details in transaction currency gl_dict.update( { - "transaction_currency": self.get("currency") or self.company_currency, + "transaction_currency": args.get("currency") or self.get("currency") or self.company_currency, "transaction_exchange_rate": self.get("conversion_rate", 1), "debit_in_transaction_currency": self.get_value_in_transaction_currency( account_currency, args, "debit" @@ -955,10 +955,10 @@ class AccountsController(TransactionBase): return self.doctype def get_value_in_transaction_currency(self, account_currency, args, field): - if account_currency == self.get("currency"): + if account_currency == args.get("currency") or self.get("currency"): return args.get(field + "_in_account_currency") else: - return flt(args.get(field, 0) / self.get("conversion_rate", 1)) + return flt(args.get(field, 0) / (args.get("conversion_rate") or self.get("conversion_rate", 1))) def validate_qty_is_not_zero(self): if self.doctype == "Purchase Receipt": From 0346f47c1d25e1d60de21dd0dc04e8c7c0b23938 Mon Sep 17 00:00:00 2001 From: Anand Baburajan Date: Mon, 1 Jan 2024 11:24:42 +0530 Subject: [PATCH 137/205] fix: take quantity into account when setting asset's gross purchase amt (#39056) fix: take quantity into account when setting asset's gross purchase amount --- .../doctype/purchase_invoice/purchase_invoice.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index f40824dff4..e676560c5c 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -1157,11 +1157,17 @@ class PurchaseInvoice(BuyingController): ) assets = frappe.db.get_all( - "Asset", filters={"purchase_invoice": self.name, "item_code": item.item_code} + "Asset", + filters={"purchase_invoice": self.name, "item_code": item.item_code}, + fields=["name", "asset_quantity"], ) for asset in assets: - frappe.db.set_value("Asset", asset.name, "gross_purchase_amount", flt(item.valuation_rate)) - frappe.db.set_value("Asset", asset.name, "purchase_receipt_amount", flt(item.valuation_rate)) + frappe.db.set_value( + "Asset", asset.name, "gross_purchase_amount", flt(item.valuation_rate) * asset.asset_quantity + ) + frappe.db.set_value( + "Asset", asset.name, "purchase_receipt_amount", flt(item.valuation_rate) * asset.asset_quantity + ) def make_stock_adjustment_entry( self, gl_entries, item, voucher_wise_stock_value, account_currency From 510fdf7bf651788e549184c23d89c2387c1c2f10 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 1 Jan 2024 13:10:03 +0530 Subject: [PATCH 138/205] fix(DX): capture tracebacks with context (#39060) --- .../process_payment_reconciliation.py | 2 +- .../doctype/repost_payment_ledger/repost_payment_ledger.py | 2 +- erpnext/manufacturing/doctype/bom_creator/bom_creator.py | 2 +- .../doctype/closing_stock_balance/closing_stock_balance.py | 4 +--- .../doctype/repost_item_valuation/repost_item_valuation.py | 2 +- erpnext/stock/reorder_item.py | 2 +- erpnext/utilities/bulk_transaction.py | 4 ++-- 7 files changed, 8 insertions(+), 10 deletions(-) diff --git a/erpnext/accounts/doctype/process_payment_reconciliation/process_payment_reconciliation.py b/erpnext/accounts/doctype/process_payment_reconciliation/process_payment_reconciliation.py index f44b14caed..761c2bc1e3 100644 --- a/erpnext/accounts/doctype/process_payment_reconciliation/process_payment_reconciliation.py +++ b/erpnext/accounts/doctype/process_payment_reconciliation/process_payment_reconciliation.py @@ -440,7 +440,7 @@ def reconcile(doc: None | str = None) -> None: # Update the parent doc about the exception frappe.db.rollback() - traceback = frappe.get_traceback() + traceback = frappe.get_traceback(with_context=True) if traceback: message = "Traceback:
" + traceback frappe.db.set_value("Process Payment Reconciliation Log", log, "error_log", message) diff --git a/erpnext/accounts/doctype/repost_payment_ledger/repost_payment_ledger.py b/erpnext/accounts/doctype/repost_payment_ledger/repost_payment_ledger.py index 38bc1a6fb8..2d10f7c762 100644 --- a/erpnext/accounts/doctype/repost_payment_ledger/repost_payment_ledger.py +++ b/erpnext/accounts/doctype/repost_payment_ledger/repost_payment_ledger.py @@ -43,7 +43,7 @@ def start_payment_ledger_repost(docname=None): except Exception as e: frappe.db.rollback() - traceback = frappe.get_traceback() + traceback = frappe.get_traceback(with_context=True) if traceback: message = "Traceback:
" + traceback frappe.db.set_value(repost_doc.doctype, repost_doc.name, "repost_error_log", message) diff --git a/erpnext/manufacturing/doctype/bom_creator/bom_creator.py b/erpnext/manufacturing/doctype/bom_creator/bom_creator.py index bd010d9f9a..1709a1f71a 100644 --- a/erpnext/manufacturing/doctype/bom_creator/bom_creator.py +++ b/erpnext/manufacturing/doctype/bom_creator/bom_creator.py @@ -251,7 +251,7 @@ class BOMCreator(Document): frappe.msgprint(_("BOMs created successfully")) except Exception: - traceback = frappe.get_traceback() + traceback = frappe.get_traceback(with_context=True) self.db_set( { "status": "Failed", diff --git a/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.py b/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.py index 7db8522f63..f71d21dd0b 100644 --- a/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.py +++ b/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.py @@ -149,6 +149,4 @@ def prepare_closing_stock_balance(name): doc.db_set("status", "Completed") except Exception as e: doc.db_set("status", "Failed") - traceback = frappe.get_traceback() - - frappe.log_error("Closing Stock Balance Failed", traceback, doc.doctype, doc.name) + doc.log_error(title="Closing Stock Balance Failed") diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py index 97ada06e1d..79b8ee30cf 100644 --- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py +++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py @@ -294,7 +294,7 @@ def repost(doc): raise frappe.db.rollback() - traceback = frappe.get_traceback() + traceback = frappe.get_traceback(with_context=True) doc.log_error("Unable to repost item valuation") message = frappe.message_log.pop() if frappe.message_log else "" diff --git a/erpnext/stock/reorder_item.py b/erpnext/stock/reorder_item.py index 907560826b..a6f52f3731 100644 --- a/erpnext/stock/reorder_item.py +++ b/erpnext/stock/reorder_item.py @@ -141,7 +141,7 @@ def create_material_request(material_requests): exceptions_list.extend(frappe.local.message_log) frappe.local.message_log = [] else: - exceptions_list.append(frappe.get_traceback()) + exceptions_list.append(frappe.get_traceback(with_context=True)) mr.log_error("Unable to create material request") diff --git a/erpnext/utilities/bulk_transaction.py b/erpnext/utilities/bulk_transaction.py index df21b61139..679d5bd348 100644 --- a/erpnext/utilities/bulk_transaction.py +++ b/erpnext/utilities/bulk_transaction.py @@ -62,7 +62,7 @@ def retry_failed_transactions(failed_docs: list | None): task(log.transaction_name, log.from_doctype, log.to_doctype) except Exception as e: frappe.db.rollback(save_point="before_creation_state") - update_log(log.name, "Failed", 1, str(frappe.get_traceback())) + update_log(log.name, "Failed", 1, str(frappe.get_traceback(with_context=True))) else: update_log(log.name, "Success", 1) @@ -86,7 +86,7 @@ def job(deserialized_data, from_doctype, to_doctype): fail_count += 1 create_log( doc_name, - str(frappe.get_traceback()), + str(frappe.get_traceback(with_context=True)), from_doctype, to_doctype, status="Failed", From 34d8bc47017a41ac473868bfbc704ed9d8184c3d Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 1 Jan 2024 13:13:25 +0530 Subject: [PATCH 139/205] chore: disable v13 auto releases --- .github/workflows/initiate_release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/initiate_release.yml b/.github/workflows/initiate_release.yml index e51c1943fd..321d6f5b40 100644 --- a/.github/workflows/initiate_release.yml +++ b/.github/workflows/initiate_release.yml @@ -15,7 +15,7 @@ jobs: strategy: fail-fast: false matrix: - version: ["13", "14", "15"] + version: ["14", "15"] steps: - uses: octokit/request-action@v2.x From bacf2b74312a4dfeb95ccc697047df2bc4d5f92e Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 1 Jan 2024 13:23:26 +0530 Subject: [PATCH 140/205] fix: Unable to save Sales Invoice (#39059) --- erpnext/regional/united_arab_emirates/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/regional/united_arab_emirates/utils.py b/erpnext/regional/united_arab_emirates/utils.py index 250a4b1495..3e9f76132c 100644 --- a/erpnext/regional/united_arab_emirates/utils.py +++ b/erpnext/regional/united_arab_emirates/utils.py @@ -25,7 +25,7 @@ def update_itemised_tax_data(doc): # dont even bother checking in item tax template as it contains both input and output accounts - double the tax rate item_code = row.item_code or row.item_name if itemised_tax.get(item_code): - for tax in itemised_tax.get(row.item_code).values(): + for tax in itemised_tax.get(item_code).values(): _tax_rate = flt(tax.get("tax_rate", 0), row.precision("tax_rate")) tax_amount += flt((row.net_amount * _tax_rate) / 100, row.precision("tax_amount")) tax_rate += _tax_rate From 4f8a16848f68040f4a94f693881a8af6b536d2f6 Mon Sep 17 00:00:00 2001 From: David Arnold Date: Mon, 1 Jan 2024 09:04:36 +0100 Subject: [PATCH 141/205] chore: default_roles hook doesn't exist anymore (#39032) --- erpnext/hooks.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 78bb2d2c27..0f80d5ee88 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -258,11 +258,6 @@ standard_portal_menu_items = [ {"title": "Appointment Booking", "route": "/book_appointment"}, ] -default_roles = [ - {"role": "Customer", "doctype": "Contact", "email_field": "email_id"}, - {"role": "Supplier", "doctype": "Contact", "email_field": "email_id"}, -] - sounds = [ {"name": "incoming-call", "src": "/assets/erpnext/sounds/incoming-call.mp3", "volume": 0.2}, {"name": "call-disconnect", "src": "/assets/erpnext/sounds/call-disconnect.mp3", "volume": 0.2}, From a9576f0cf6c7c2eb0711c3c8ffb0e1095c6da69e Mon Sep 17 00:00:00 2001 From: Anand Baburajan Date: Mon, 1 Jan 2024 15:03:21 +0530 Subject: [PATCH 142/205] feat: group by Asset in Asset Depreciations and Balances report (#38923) feat: group by asset in asset depreciations and balances report --- .../asset_depreciations_and_balances.js | 19 +- .../asset_depreciations_and_balances.py | 210 +++++++++++++++++- 2 files changed, 215 insertions(+), 14 deletions(-) diff --git a/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.js b/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.js index 5f78b77934..06fa9f3175 100644 --- a/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.js +++ b/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.js @@ -25,11 +25,26 @@ frappe.query_reports["Asset Depreciations and Balances"] = { "default": erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[2], "reqd": 1 }, + { + "fieldname":"group_by", + "label": __("Group By"), + "fieldtype": "Select", + "options": ["Asset Category", "Asset"], + "default": "Asset Category", + }, { "fieldname":"asset_category", "label": __("Asset Category"), "fieldtype": "Link", - "options": "Asset Category" - } + "options": "Asset Category", + "depends_on": "eval: doc.group_by == 'Asset Category'", + }, + { + "fieldname":"asset", + "label": __("Asset"), + "fieldtype": "Link", + "options": "Asset", + "depends_on": "eval: doc.group_by == 'Asset'", + }, ] } diff --git a/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py b/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py index bdc8d8504f..48da17ab62 100644 --- a/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py +++ b/erpnext/accounts/report/asset_depreciations_and_balances/asset_depreciations_and_balances.py @@ -14,10 +14,17 @@ def execute(filters=None): def get_data(filters): + if filters.get("group_by") == "Asset Category": + return get_group_by_asset_category_data(filters) + elif filters.get("group_by") == "Asset": + return get_group_by_asset_data(filters) + + +def get_group_by_asset_category_data(filters): data = [] - asset_categories = get_asset_categories(filters) - assets = get_assets(filters) + asset_categories = get_asset_categories_for_grouped_by_category(filters) + assets = get_assets_for_grouped_by_category(filters) for asset_category in asset_categories: row = frappe._dict() @@ -38,6 +45,7 @@ def get_data(filters): if asset["asset_category"] == asset_category.get("asset_category", "") ) ) + row.accumulated_depreciation_as_on_to_date = ( flt(row.accumulated_depreciation_as_on_from_date) + flt(row.depreciation_amount_during_the_period) @@ -57,7 +65,7 @@ def get_data(filters): return data -def get_asset_categories(filters): +def get_asset_categories_for_grouped_by_category(filters): condition = "" if filters.get("asset_category"): condition += " and asset_category = %(asset_category)s" @@ -116,7 +124,105 @@ def get_asset_categories(filters): ) -def get_assets(filters): +def get_asset_details_for_grouped_by_category(filters): + condition = "" + if filters.get("asset"): + condition += " and name = %(asset)s" + return frappe.db.sql( + """ + SELECT name, + ifnull(sum(case when purchase_date < %(from_date)s then + case when ifnull(disposal_date, 0) = 0 or disposal_date >= %(from_date)s then + gross_purchase_amount + else + 0 + end + else + 0 + end), 0) as cost_as_on_from_date, + ifnull(sum(case when purchase_date >= %(from_date)s then + gross_purchase_amount + else + 0 + end), 0) as cost_of_new_purchase, + ifnull(sum(case when ifnull(disposal_date, 0) != 0 + and disposal_date >= %(from_date)s + and disposal_date <= %(to_date)s then + case when status = "Sold" then + gross_purchase_amount + else + 0 + end + else + 0 + end), 0) as cost_of_sold_asset, + ifnull(sum(case when ifnull(disposal_date, 0) != 0 + and disposal_date >= %(from_date)s + and disposal_date <= %(to_date)s then + case when status = "Scrapped" then + gross_purchase_amount + else + 0 + end + else + 0 + end), 0) as cost_of_scrapped_asset + from `tabAsset` + where docstatus=1 and company=%(company)s and purchase_date <= %(to_date)s {} + group by name + """.format( + condition + ), + { + "to_date": filters.to_date, + "from_date": filters.from_date, + "company": filters.company, + "asset": filters.get("asset"), + }, + as_dict=1, + ) + + +def get_group_by_asset_data(filters): + data = [] + + asset_details = get_asset_details_for_grouped_by_category(filters) + assets = get_assets_for_grouped_by_asset(filters) + + for asset_detail in asset_details: + row = frappe._dict() + # row.asset_category = asset_category + row.update(asset_detail) + + row.cost_as_on_to_date = ( + flt(row.cost_as_on_from_date) + + flt(row.cost_of_new_purchase) + - flt(row.cost_of_sold_asset) + - flt(row.cost_of_scrapped_asset) + ) + + row.update(next(asset for asset in assets if asset["asset"] == asset_detail.get("name", ""))) + + row.accumulated_depreciation_as_on_to_date = ( + flt(row.accumulated_depreciation_as_on_from_date) + + flt(row.depreciation_amount_during_the_period) + - flt(row.depreciation_eliminated_during_the_period) + ) + + row.net_asset_value_as_on_from_date = flt(row.cost_as_on_from_date) - flt( + row.accumulated_depreciation_as_on_from_date + ) + + row.net_asset_value_as_on_to_date = flt(row.cost_as_on_to_date) - flt( + row.accumulated_depreciation_as_on_to_date + ) + + data.append(row) + + return data + + +def get_assets_for_grouped_by_category(filters): condition = "" if filters.get("asset_category"): condition = " and a.asset_category = '{}'".format(filters.get("asset_category")) @@ -178,15 +284,93 @@ def get_assets(filters): ) +def get_assets_for_grouped_by_asset(filters): + condition = "" + if filters.get("asset"): + condition = " and a.name = '{}'".format(filters.get("asset")) + return frappe.db.sql( + """ + SELECT results.name as asset, + sum(results.accumulated_depreciation_as_on_from_date) as accumulated_depreciation_as_on_from_date, + sum(results.depreciation_eliminated_during_the_period) as depreciation_eliminated_during_the_period, + sum(results.depreciation_amount_during_the_period) as depreciation_amount_during_the_period + from (SELECT a.name as name, + ifnull(sum(case when gle.posting_date < %(from_date)s and (ifnull(a.disposal_date, 0) = 0 or a.disposal_date >= %(from_date)s) then + gle.debit + else + 0 + end), 0) as accumulated_depreciation_as_on_from_date, + ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 and a.disposal_date >= %(from_date)s + and a.disposal_date <= %(to_date)s and gle.posting_date <= a.disposal_date then + gle.debit + else + 0 + end), 0) as depreciation_eliminated_during_the_period, + ifnull(sum(case when gle.posting_date >= %(from_date)s and gle.posting_date <= %(to_date)s + and (ifnull(a.disposal_date, 0) = 0 or gle.posting_date <= a.disposal_date) then + gle.debit + else + 0 + end), 0) as depreciation_amount_during_the_period + from `tabGL Entry` gle + join `tabAsset` a on + gle.against_voucher = a.name + join `tabAsset Category Account` aca on + aca.parent = a.asset_category and aca.company_name = %(company)s + join `tabCompany` company on + company.name = %(company)s + where a.docstatus=1 and a.company=%(company)s and a.purchase_date <= %(to_date)s and gle.debit != 0 and gle.is_cancelled = 0 and gle.account = ifnull(aca.depreciation_expense_account, company.depreciation_expense_account) {0} + group by a.name + union + SELECT a.name as name, + ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 and (a.disposal_date < %(from_date)s or a.disposal_date > %(to_date)s) then + 0 + else + a.opening_accumulated_depreciation + end), 0) as accumulated_depreciation_as_on_from_date, + ifnull(sum(case when a.disposal_date >= %(from_date)s and a.disposal_date <= %(to_date)s then + a.opening_accumulated_depreciation + else + 0 + end), 0) as depreciation_eliminated_during_the_period, + 0 as depreciation_amount_during_the_period + from `tabAsset` a + where a.docstatus=1 and a.company=%(company)s and a.purchase_date <= %(to_date)s {0} + group by a.name) as results + group by results.name + """.format( + condition + ), + {"to_date": filters.to_date, "from_date": filters.from_date, "company": filters.company}, + as_dict=1, + ) + + def get_columns(filters): - return [ - { - "label": _("Asset Category"), - "fieldname": "asset_category", - "fieldtype": "Link", - "options": "Asset Category", - "width": 120, - }, + columns = [] + + if filters.get("group_by") == "Asset Category": + columns.append( + { + "label": _("Asset Category"), + "fieldname": "asset_category", + "fieldtype": "Link", + "options": "Asset Category", + "width": 120, + } + ) + elif filters.get("group_by") == "Asset": + columns.append( + { + "label": _("Asset"), + "fieldname": "asset", + "fieldtype": "Link", + "options": "Asset", + "width": 120, + } + ) + + columns += [ { "label": _("Cost as on") + " " + formatdate(filters.day_before_from_date), "fieldname": "cost_as_on_from_date", @@ -254,3 +438,5 @@ def get_columns(filters): "width": 200, }, ] + + return columns From 92bc962f60adb3967a2ef378511822d53ff2f4a8 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 1 Jan 2024 14:46:15 +0530 Subject: [PATCH 143/205] fix: undefined error in Budget Variance and Profitability report 'Budget' and 'Budget Account' doesn't have support for dynamic dimension. It only supports hard-coded ones - Project and Cost Center --- .../report/budget_variance_report/budget_variance_report.js | 4 ---- .../report/profitability_analysis/profitability_analysis.js | 5 ----- 2 files changed, 9 deletions(-) diff --git a/erpnext/accounts/report/budget_variance_report/budget_variance_report.js b/erpnext/accounts/report/budget_variance_report/budget_variance_report.js index 15aa265b56..15088335e5 100644 --- a/erpnext/accounts/report/budget_variance_report/budget_variance_report.js +++ b/erpnext/accounts/report/budget_variance_report/budget_variance_report.js @@ -88,7 +88,3 @@ frappe.query_reports["Budget Variance Report"] = { return value; } } - -erpnext.dimension_filters.forEach((dimension) => { - frappe.query_reports["Budget Variance Report"].filters[4].options.push(dimension["document_type"]); -}); diff --git a/erpnext/accounts/report/profitability_analysis/profitability_analysis.js b/erpnext/accounts/report/profitability_analysis/profitability_analysis.js index b6bbd979ed..5dd3617a92 100644 --- a/erpnext/accounts/report/profitability_analysis/profitability_analysis.js +++ b/erpnext/accounts/report/profitability_analysis/profitability_analysis.js @@ -117,8 +117,3 @@ frappe.query_reports["Profitability Analysis"] = { "parent_field": "parent_account", "initial_depth": 3 } - -erpnext.dimension_filters.forEach((dimension) => { - frappe.query_reports["Profitability Analysis"].filters[1].options.push(dimension["document_type"]); -}); - From 1a9e091d12f9149638f3774b9def0fa80370b59b Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 1 Jan 2024 17:32:33 +0530 Subject: [PATCH 144/205] fix: select options should dynamically load dimensions --- .../budget_variance_report.js | 63 ++++++++++++++----- 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/erpnext/accounts/report/budget_variance_report/budget_variance_report.js b/erpnext/accounts/report/budget_variance_report/budget_variance_report.js index 15088335e5..9c356bf28e 100644 --- a/erpnext/accounts/report/budget_variance_report/budget_variance_report.js +++ b/erpnext/accounts/report/budget_variance_report/budget_variance_report.js @@ -2,7 +2,44 @@ // License: GNU General Public License v3. See license.txt frappe.query_reports["Budget Variance Report"] = { - "filters": [ + "filters": get_filters(), + "formatter": function (value, row, column, data, default_formatter) { + value = default_formatter(value, row, column, data); + + if (column.fieldname.includes(__("variance"))) { + + if (data[column.fieldname] < 0) { + value = "" + value + ""; + } + else if (data[column.fieldname] > 0) { + value = "" + value + ""; + } + } + + return value; + } +} +function get_filters() { + function get_dimensions() { + let result = []; + frappe.call({ + method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.get_dimensions", + args: { + 'with_cost_center_and_project': true + }, + async: false, + callback: function(r) { + if(!r.exc) { + result = r.message[0].map(elem => elem.document_type); + } + } + }); + return result; + } + + let budget_against_options = get_dimensions(); + + let filters = [ { fieldname: "from_fiscal_year", label: __("From Fiscal Year"), @@ -44,9 +81,13 @@ frappe.query_reports["Budget Variance Report"] = { fieldname: "budget_against", label: __("Budget Against"), fieldtype: "Select", - options: ["Cost Center", "Project"], + options: budget_against_options, default: "Cost Center", reqd: 1, + get_data: function() { + console.log(this.options); + return ["Emacs", "Rocks"]; + }, on_change: function() { frappe.query_report.set_filter_value("budget_against_filter", []); frappe.query_report.refresh(); @@ -71,20 +112,8 @@ frappe.query_reports["Budget Variance Report"] = { fieldtype: "Check", default: 0, }, - ], - "formatter": function (value, row, column, data, default_formatter) { - value = default_formatter(value, row, column, data); + ] - if (column.fieldname.includes(__("variance"))) { - - if (data[column.fieldname] < 0) { - value = "" + value + ""; - } - else if (data[column.fieldname] > 0) { - value = "" + value + ""; - } - } - - return value; - } + return filters; } + From 6e5484ea031027de4e6a897b02bd0f2e7b8adda9 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Tue, 2 Jan 2024 12:54:18 +0530 Subject: [PATCH 145/205] fix: on cancellation of document cancel the serial and batch bundle (#39076) --- .../doctype/work_order/test_work_order.py | 2 -- .../serial_and_batch_bundle.py | 16 +++++++++++- .../test_serial_and_batch_bundle.py | 25 +++++++++++++++++-- erpnext/stock/serial_batch_bundle.py | 6 +++++ 4 files changed, 44 insertions(+), 5 deletions(-) diff --git a/erpnext/manufacturing/doctype/work_order/test_work_order.py b/erpnext/manufacturing/doctype/work_order/test_work_order.py index 07c253b232..aa5db57fa8 100644 --- a/erpnext/manufacturing/doctype/work_order/test_work_order.py +++ b/erpnext/manufacturing/doctype/work_order/test_work_order.py @@ -921,11 +921,9 @@ class TestWorkOrder(FrappeTestCase): "Test RM Item 2 for Scrap Item Test", ] - from_time = add_days(now(), -1) job_cards = frappe.get_all( "Job Card Time Log", fields=["distinct parent as name", "docstatus"], - filters={"from_time": (">", from_time)}, order_by="creation asc", ) diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index 774e5c657d..218406f56f 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -85,6 +85,7 @@ class SerialandBatchBundle(Document): # end: auto-generated types def validate(self): + self.reset_serial_batch_bundle() self.set_batch_no() self.validate_serial_and_batch_no() self.validate_duplicate_serial_and_batch_no() @@ -100,6 +101,15 @@ class SerialandBatchBundle(Document): self.set_incoming_rate() self.calculate_qty_and_amount() + def reset_serial_batch_bundle(self): + if self.is_new() and self.amended_from: + for field in ["is_cancelled", "is_rejected"]: + if self.get(field): + self.set(field, 0) + + if self.voucher_detail_no: + self.voucher_detail_no = None + def set_batch_no(self): if self.has_serial_no and self.has_batch_no: serial_nos = [d.serial_no for d in self.entries if d.serial_no] @@ -914,7 +924,11 @@ def upload_csv_file(item_code, file_path): def get_serial_batch_from_csv(item_code, file_path): - file_path = frappe.get_site_path() + file_path + if "private" in file_path: + file_path = frappe.get_site_path() + file_path + else: + file_path = frappe.get_site_path() + "/public" + file_path + serial_nos = [] batch_nos = [] diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py index 478cfa4d1c..19757479a5 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py @@ -427,11 +427,12 @@ class TestSerialandBatchBundle(FrappeTestCase): from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt item = make_item( + "Test Serial and Batch Bundle Company Item", properties={ "has_serial_no": 1, "serial_no_series": "TT-SER-VAL-.#####", - } - ) + }, + ).name pr = make_purchase_receipt( item_code=item, @@ -460,6 +461,26 @@ class TestSerialandBatchBundle(FrappeTestCase): sn_doc = add_serial_batch_ledgers(entries, item_row, pr, "_Test Warehouse - _TC") self.assertEqual(sn_doc.company, "_Test Company") + def test_auto_cancel_serial_and_batch(self): + item_code = make_item( + properties={"has_serial_no": 1, "serial_no_series": "ATC-TT-SER-VAL-.#####"} + ).name + + se = make_stock_entry( + item_code=item_code, + target="_Test Warehouse - _TC", + qty=5, + rate=500, + ) + + bundle = se.items[0].serial_and_batch_bundle + docstatus = frappe.db.get_value("Serial and Batch Bundle", bundle, "docstatus") + self.assertEqual(docstatus, 1) + + se.cancel() + docstatus = frappe.db.get_value("Serial and Batch Bundle", bundle, "docstatus") + self.assertEqual(docstatus, 2) + def get_batch_from_bundle(bundle): from erpnext.stock.serial_batch_bundle import get_batch_nos diff --git a/erpnext/stock/serial_batch_bundle.py b/erpnext/stock/serial_batch_bundle.py index a1874b84dc..39df2279cd 100644 --- a/erpnext/stock/serial_batch_bundle.py +++ b/erpnext/stock/serial_batch_bundle.py @@ -242,6 +242,12 @@ class SerialBatchBundle: if self.item_details.has_batch_no == 1: self.update_batch_qty() + if self.sle.is_cancelled and self.sle.serial_and_batch_bundle: + self.cancel_serial_and_batch_bundle() + + def cancel_serial_and_batch_bundle(self): + frappe.get_cached_doc("Serial and Batch Bundle", self.sle.serial_and_batch_bundle).cancel() + def submit_serial_and_batch_bundle(self): doc = frappe.get_doc("Serial and Batch Bundle", self.sle.serial_and_batch_bundle) self.validate_actual_qty(doc) From 9ea963bfe9cf75e140558f123350b89d806e937e Mon Sep 17 00:00:00 2001 From: Parameshwari Palanisamy <101092028+creative-paramu@users.noreply.github.com> Date: Tue, 2 Jan 2024 14:04:56 +0530 Subject: [PATCH 146/205] fix: Variant Items, List View Enabled to Variant Status Change (#38468) * feat: Purchase Register Report Supplier Group filter Adding * fix: Variant Items, List View Enabled to Variant Status Change * Update purchase_register.js * Update purchase_register.py --- erpnext/stock/doctype/item/item_list.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/item/item_list.js b/erpnext/stock/doctype/item/item_list.js index 22d38e8893..1b57102d71 100644 --- a/erpnext/stock/doctype/item/item_list.js +++ b/erpnext/stock/doctype/item/item_list.js @@ -1,6 +1,6 @@ frappe.listview_settings['Item'] = { add_fields: ["item_name", "stock_uom", "item_group", "image", - "has_variants", "end_of_life", "disabled"], + "has_variants", "end_of_life", "disabled", "variant_of"], filters: [["disabled", "=", "0"]], get_indicator: function(doc) { From 739434b72779fe12aed86a0a61d352948c81b680 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 2 Jan 2024 14:31:41 +0530 Subject: [PATCH 147/205] perf: index item_code in bom explosion item (#39085) --- .../doctype/bom_explosion_item/bom_explosion_item.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.json b/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.json index c75ac32cd1..27ecd57b87 100644 --- a/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.json +++ b/erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.json @@ -37,7 +37,8 @@ "oldfieldname": "item_code", "oldfieldtype": "Link", "options": "Item", - "read_only": 1 + "read_only": 1, + "search_index": 1 }, { "fieldname": "item_name", @@ -170,7 +171,7 @@ "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2023-11-14 18:35:40.856895", + "modified": "2024-01-02 13:49:36.211586", "modified_by": "Administrator", "module": "Manufacturing", "name": "BOM Explosion Item", From 4e28b5a199bacbb3ac5cb1616e1bfe34e99c4f12 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Tue, 2 Jan 2024 15:27:41 +0530 Subject: [PATCH 148/205] fix(minor): Rename "ERPNext Settings" to "Settings" and remove "ERPNext Integrations" workspace --- .../workspace/accounting/accounting.json | 86 ++- .../erpnext_integrations.json | 228 -------- .../erpnext_settings/erpnext_settings.json | 500 ------------------ .../setup/workspace/settings/settings.json | 500 ++++++++++++++++++ 4 files changed, 576 insertions(+), 738 deletions(-) delete mode 100644 erpnext/erpnext_integrations/workspace/erpnext_integrations/erpnext_integrations.json delete mode 100644 erpnext/setup/workspace/erpnext_settings/erpnext_settings.json create mode 100644 erpnext/setup/workspace/settings/settings.json diff --git a/erpnext/accounts/workspace/accounting/accounting.json b/erpnext/accounts/workspace/accounting/accounting.json index dfdae1dec6..f4aced2f9d 100644 --- a/erpnext/accounts/workspace/accounting/accounting.json +++ b/erpnext/accounts/workspace/accounting/accounting.json @@ -5,7 +5,7 @@ "label": "Profit and Loss" } ], - "content": "[{\"id\":\"MmUf9abwxg\",\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Accounts\",\"col\":12}},{\"id\":\"VVvJ1lUcfc\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Outgoing Bills\",\"col\":3}},{\"id\":\"Vlj2FZtlHV\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Incoming Bills\",\"col\":3}},{\"id\":\"VVVjQVAhPf\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Incoming Payment\",\"col\":3}},{\"id\":\"DySNdlysIW\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Outgoing Payment\",\"col\":3}},{\"id\":\"i0EtSjDAXq\",\"type\":\"chart\",\"data\":{\"chart_name\":\"Profit and Loss\",\"col\":12}},{\"id\":\"X78jcbq1u3\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"vikWSkNm6_\",\"type\":\"header\",\"data\":{\"text\":\"Your Shortcuts\",\"col\":12}},{\"id\":\"pMywM0nhlj\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Chart of Accounts\",\"col\":3}},{\"id\":\"_pRdD6kqUG\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Invoice\",\"col\":3}},{\"id\":\"G984SgVRJN\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Invoice\",\"col\":3}},{\"id\":\"1ArNvt9qhz\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Journal Entry\",\"col\":3}},{\"id\":\"F9f4I1viNr\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Payment Entry\",\"col\":3}},{\"id\":\"4IBBOIxfqW\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Receivable\",\"col\":3}},{\"id\":\"El2anpPaFY\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"General Ledger\",\"col\":3}},{\"id\":\"1nwcM9upJo\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Trial Balance\",\"col\":3}},{\"id\":\"OF9WOi1Ppc\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"id\":\"iAwpe-Chra\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Learn Accounting\",\"col\":3}},{\"id\":\"B7-uxs8tkU\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"tHb3yxthkR\",\"type\":\"header\",\"data\":{\"text\":\"Reports & Masters\",\"col\":12}},{\"id\":\"DnNtsmxpty\",\"type\":\"card\",\"data\":{\"card_name\":\"Accounting Masters\",\"col\":4}},{\"id\":\"nKKr6fjgjb\",\"type\":\"card\",\"data\":{\"card_name\":\"General Ledger\",\"col\":4}},{\"id\":\"xOHTyD8b5l\",\"type\":\"card\",\"data\":{\"card_name\":\"Accounts Receivable\",\"col\":4}},{\"id\":\"_Cb7C8XdJJ\",\"type\":\"card\",\"data\":{\"card_name\":\"Accounts Payable\",\"col\":4}},{\"id\":\"p7NY6MHe2Y\",\"type\":\"card\",\"data\":{\"card_name\":\"Financial Statements\",\"col\":4}},{\"id\":\"KlqilF5R_V\",\"type\":\"card\",\"data\":{\"card_name\":\"Taxes\",\"col\":4}},{\"id\":\"jTUy8LB0uw\",\"type\":\"card\",\"data\":{\"card_name\":\"Cost Center and Budgeting\",\"col\":4}},{\"id\":\"Wn2lhs7WLn\",\"type\":\"card\",\"data\":{\"card_name\":\"Multi Currency\",\"col\":4}},{\"id\":\"PAQMqqNkBM\",\"type\":\"card\",\"data\":{\"card_name\":\"Bank Statement\",\"col\":4}},{\"id\":\"Q_hBCnSeJY\",\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}},{\"id\":\"3AK1Zf0oew\",\"type\":\"card\",\"data\":{\"card_name\":\"Profitability\",\"col\":4}},{\"id\":\"kxhoaiqdLq\",\"type\":\"card\",\"data\":{\"card_name\":\"Opening and Closing\",\"col\":4}},{\"id\":\"q0MAlU2j_Z\",\"type\":\"card\",\"data\":{\"card_name\":\"Subscription Management\",\"col\":4}},{\"id\":\"ptm7T6Hwu-\",\"type\":\"card\",\"data\":{\"card_name\":\"Share Management\",\"col\":4}},{\"id\":\"OX7lZHbiTr\",\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}}]", + "content": "[{\"id\":\"MmUf9abwxg\",\"type\":\"onboarding\",\"data\":{\"onboarding_name\":\"Accounts\",\"col\":12}},{\"id\":\"VVvJ1lUcfc\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Outgoing Bills\",\"col\":3}},{\"id\":\"Vlj2FZtlHV\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Incoming Bills\",\"col\":3}},{\"id\":\"VVVjQVAhPf\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Incoming Payment\",\"col\":3}},{\"id\":\"DySNdlysIW\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Outgoing Payment\",\"col\":3}},{\"id\":\"i0EtSjDAXq\",\"type\":\"chart\",\"data\":{\"chart_name\":\"Profit and Loss\",\"col\":12}},{\"id\":\"X78jcbq1u3\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"vikWSkNm6_\",\"type\":\"header\",\"data\":{\"text\":\"Your Shortcuts\",\"col\":12}},{\"id\":\"pMywM0nhlj\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Chart of Accounts\",\"col\":3}},{\"id\":\"_pRdD6kqUG\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Sales Invoice\",\"col\":3}},{\"id\":\"G984SgVRJN\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Purchase Invoice\",\"col\":3}},{\"id\":\"1ArNvt9qhz\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Journal Entry\",\"col\":3}},{\"id\":\"F9f4I1viNr\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Payment Entry\",\"col\":3}},{\"id\":\"4IBBOIxfqW\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Receivable\",\"col\":3}},{\"id\":\"El2anpPaFY\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"General Ledger\",\"col\":3}},{\"id\":\"1nwcM9upJo\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Trial Balance\",\"col\":3}},{\"id\":\"OF9WOi1Ppc\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Dashboard\",\"col\":3}},{\"id\":\"iAwpe-Chra\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Learn Accounting\",\"col\":3}},{\"id\":\"B7-uxs8tkU\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"tHb3yxthkR\",\"type\":\"header\",\"data\":{\"text\":\"Reports & Masters\",\"col\":12}},{\"id\":\"DnNtsmxpty\",\"type\":\"card\",\"data\":{\"card_name\":\"Accounting Masters\",\"col\":4}},{\"id\":\"nKKr6fjgjb\",\"type\":\"card\",\"data\":{\"card_name\":\"General Ledger\",\"col\":4}},{\"id\":\"xOHTyD8b5l\",\"type\":\"card\",\"data\":{\"card_name\":\"Accounts Receivable\",\"col\":4}},{\"id\":\"_Cb7C8XdJJ\",\"type\":\"card\",\"data\":{\"card_name\":\"Accounts Payable\",\"col\":4}},{\"id\":\"p7NY6MHe2Y\",\"type\":\"card\",\"data\":{\"card_name\":\"Financial Statements\",\"col\":4}},{\"id\":\"KlqilF5R_V\",\"type\":\"card\",\"data\":{\"card_name\":\"Taxes\",\"col\":4}},{\"id\":\"jTUy8LB0uw\",\"type\":\"card\",\"data\":{\"card_name\":\"Cost Center and Budgeting\",\"col\":4}},{\"id\":\"Wn2lhs7WLn\",\"type\":\"card\",\"data\":{\"card_name\":\"Multi Currency\",\"col\":4}},{\"id\":\"PAQMqqNkBM\",\"type\":\"card\",\"data\":{\"card_name\":\"Banking\",\"col\":4}},{\"id\":\"Q_hBCnSeJY\",\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}},{\"id\":\"3AK1Zf0oew\",\"type\":\"card\",\"data\":{\"card_name\":\"Profitability\",\"col\":4}},{\"id\":\"kxhoaiqdLq\",\"type\":\"card\",\"data\":{\"card_name\":\"Opening and Closing\",\"col\":4}},{\"id\":\"q0MAlU2j_Z\",\"type\":\"card\",\"data\":{\"card_name\":\"Subscription Management\",\"col\":4}},{\"id\":\"ptm7T6Hwu-\",\"type\":\"card\",\"data\":{\"card_name\":\"Share Management\",\"col\":4}},{\"id\":\"OX7lZHbiTr\",\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}}]", "creation": "2020-03-02 15:41:59.515192", "custom_blocks": [], "docstatus": 0, @@ -652,14 +652,6 @@ "onboard": 0, "type": "Link" }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Bank Statement", - "link_count": 0, - "onboard": 0, - "type": "Card Break" - }, { "dependencies": "", "hidden": 0, @@ -1059,9 +1051,83 @@ "link_type": "Report", "onboard": 0, "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Banking", + "link_count": 6, + "link_type": "DocType", + "onboard": 0, + "type": "Card Break" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Bank", + "link_count": 0, + "link_to": "Bank", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Bank Account", + "link_count": 0, + "link_to": "Bank Account", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Bank Clearance", + "link_count": 0, + "link_to": "Bank Clearance", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Bank Reconciliation Tool", + "link_count": 0, + "link_to": "Bank Reconciliation Tool", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "GL Entry", + "hidden": 0, + "is_query_report": 1, + "label": "Bank Reconciliation Statement", + "link_count": 0, + "link_to": "Bank Reconciliation Statement", + "link_type": "Report", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Plaid Settings", + "link_count": 0, + "link_to": "Plaid Settings", + "link_type": "DocType", + "onboard": 0, + "type": "Link" } ], - "modified": "2023-08-10 17:41:14.059005", + "modified": "2024-01-02 15:21:09.895531", "modified_by": "Administrator", "module": "Accounts", "name": "Accounting", diff --git a/erpnext/erpnext_integrations/workspace/erpnext_integrations/erpnext_integrations.json b/erpnext/erpnext_integrations/workspace/erpnext_integrations/erpnext_integrations.json deleted file mode 100644 index dfef223c43..0000000000 --- a/erpnext/erpnext_integrations/workspace/erpnext_integrations/erpnext_integrations.json +++ /dev/null @@ -1,228 +0,0 @@ -{ - "charts": [], - "content": "[{\"id\":\"e88ADOJ7WC\",\"type\":\"header\",\"data\":{\"text\":\"Integrations\",\"col\":12}},{\"id\":\"pZEYOOCdB0\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Browse Apps\",\"col\":3}},{\"id\":\"St7AHbhVOr\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"nu4oSjH5Rd\",\"type\":\"card\",\"data\":{\"card_name\":\"Authentication\",\"col\":4}},{\"id\":\"G0tyx9WOfm\",\"type\":\"card\",\"data\":{\"card_name\":\"Backup\",\"col\":4}},{\"id\":\"nG8cdkpzoc\",\"type\":\"card\",\"data\":{\"card_name\":\"Google Services\",\"col\":4}},{\"id\":\"4hwuQn6E95\",\"type\":\"card\",\"data\":{\"card_name\":\"Communication Channels\",\"col\":4}},{\"id\":\"sEGAzTJRmq\",\"type\":\"card\",\"data\":{\"card_name\":\"Payments\",\"col\":4}}]", - "creation": "2020-08-20 19:30:48.138801", - "custom_blocks": [], - "docstatus": 0, - "doctype": "Workspace", - "for_user": "", - "hide_custom": 0, - "icon": "integration", - "idx": 0, - "is_hidden": 0, - "label": "ERPNext Integrations", - "links": [ - { - "hidden": 0, - "is_query_report": 0, - "label": "Backup", - "link_count": 3, - "onboard": 0, - "type": "Card Break" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Dropbox Settings", - "link_count": 0, - "link_to": "Dropbox Settings", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "S3 Backup Settings", - "link_count": 0, - "link_to": "S3 Backup Settings", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Google Drive", - "link_count": 0, - "link_to": "Google Drive", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Authentication", - "link_count": 4, - "onboard": 0, - "type": "Card Break" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Social Login", - "link_count": 0, - "link_to": "Social Login Key", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "LDAP Settings", - "link_count": 0, - "link_to": "LDAP Settings", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "OAuth Client", - "link_count": 0, - "link_to": "OAuth Client", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "OAuth Provider Settings", - "link_count": 0, - "link_to": "OAuth Provider Settings", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Communication Channels", - "link_count": 3, - "onboard": 0, - "type": "Card Break" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Webhook", - "link_count": 0, - "link_to": "Webhook", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "SMS Settings", - "link_count": 0, - "link_to": "SMS Settings", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Slack Webhook URL", - "link_count": 0, - "link_to": "Slack Webhook URL", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Google Services", - "link_count": 4, - "onboard": 0, - "type": "Card Break" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Google Settings", - "link_count": 0, - "link_to": "Google Settings", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Google Contacts", - "link_count": 0, - "link_to": "Google Contacts", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Google Calendar", - "link_count": 0, - "link_to": "Google Calendar", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Google Drive", - "link_count": 0, - "link_to": "Google Drive", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Payments", - "link_count": 3, - "onboard": 0, - "type": "Card Break" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Plaid Settings", - "link_count": 0, - "link_to": "Plaid Settings", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - } - ], - "modified": "2023-10-31 19:57:32.748726", - "modified_by": "Administrator", - "module": "ERPNext Integrations", - "name": "ERPNext Integrations", - "number_cards": [], - "owner": "Administrator", - "parent_page": "", - "public": 1, - "quick_lists": [], - "restrict_to_domain": "", - "roles": [], - "sequence_id": 21.0, - "shortcuts": [ - { - "color": "Grey", - "doc_view": "List", - "label": "Browse Apps", - "type": "URL", - "url": "https://frappecloud.com/marketplace" - } - ], - "title": "ERPNext Integrations" -} \ No newline at end of file diff --git a/erpnext/setup/workspace/erpnext_settings/erpnext_settings.json b/erpnext/setup/workspace/erpnext_settings/erpnext_settings.json deleted file mode 100644 index 2f9cec40b0..0000000000 --- a/erpnext/setup/workspace/erpnext_settings/erpnext_settings.json +++ /dev/null @@ -1,500 +0,0 @@ -{ - "charts": [], - "content": "[{\"id\":\"NO5yYHJopc\",\"type\":\"header\",\"data\":{\"text\":\"Your Shortcuts\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\",\"col\":12}},{\"id\":\"CDxIM-WuZ9\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"System Settings\",\"col\":3}},{\"id\":\"-Uh7DKJNJX\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Settings\",\"col\":3}},{\"id\":\"K9ST9xcDXh\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Stock Settings\",\"col\":3}},{\"id\":\"27IdVHVQMb\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Selling Settings\",\"col\":3}},{\"id\":\"Rwp5zff88b\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Buying Settings\",\"col\":3}},{\"id\":\"hkfnQ2sevf\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Global Defaults\",\"col\":3}},{\"id\":\"jjxI_PDawD\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Print Settings\",\"col\":3}},{\"id\":\"R3CoYYFXye\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"yynbm1J_VO\",\"type\":\"header\",\"data\":{\"text\":\"Settings\",\"col\":12}},{\"id\":\"KDCv2MvSg3\",\"type\":\"card\",\"data\":{\"card_name\":\"Module Settings\",\"col\":4}},{\"id\":\"Q0_bqT7cxQ\",\"type\":\"card\",\"data\":{\"card_name\":\"Email / Notifications\",\"col\":4}},{\"id\":\"UnqK5haBnh\",\"type\":\"card\",\"data\":{\"card_name\":\"Website\",\"col\":4}},{\"id\":\"kp7u1H5hCd\",\"type\":\"card\",\"data\":{\"card_name\":\"Core\",\"col\":4}},{\"id\":\"Ufc3jycgy9\",\"type\":\"card\",\"data\":{\"card_name\":\"Printing\",\"col\":4}},{\"id\":\"89bSNzv3Yh\",\"type\":\"card\",\"data\":{\"card_name\":\"Workflow\",\"col\":4}}]", - "creation": "2022-01-27 13:14:47.349433", - "custom_blocks": [], - "docstatus": 0, - "doctype": "Workspace", - "for_user": "", - "hide_custom": 0, - "icon": "setting", - "idx": 0, - "is_hidden": 0, - "label": "ERPNext Settings", - "links": [ - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Import Data", - "link_count": 0, - "link_to": "Data Import", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Export Data", - "link_count": 0, - "link_to": "Data Export", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Bulk Update", - "link_count": 0, - "link_to": "Bulk Update", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Download Backups", - "link_count": 0, - "link_to": "backups", - "link_type": "Page", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Deleted Documents", - "link_count": 0, - "link_to": "Deleted Document", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Email / Notifications", - "link_count": 0, - "onboard": 0, - "type": "Card Break" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Email Account", - "link_count": 0, - "link_to": "Email Account", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Email Domain", - "link_count": 0, - "link_to": "Email Domain", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Notification", - "link_count": 0, - "link_to": "Notification", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Email Template", - "link_count": 0, - "link_to": "Email Template", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Auto Email Report", - "link_count": 0, - "link_to": "Auto Email Report", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Newsletter", - "link_count": 0, - "link_to": "Newsletter", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Notification Settings", - "link_count": 0, - "link_to": "Notification Settings", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Website", - "link_count": 0, - "onboard": 0, - "type": "Card Break" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Website Settings", - "link_count": 0, - "link_to": "Website Settings", - "link_type": "DocType", - "onboard": 1, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Website Theme", - "link_count": 0, - "link_to": "Website Theme", - "link_type": "DocType", - "onboard": 1, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Website Script", - "link_count": 0, - "link_to": "Website Script", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "About Us Settings", - "link_count": 0, - "link_to": "About Us Settings", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Contact Us Settings", - "link_count": 0, - "link_to": "Contact Us Settings", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Printing", - "link_count": 0, - "onboard": 0, - "type": "Card Break" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Print Format Builder", - "link_count": 0, - "link_to": "print-format-builder", - "link_type": "Page", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Print Settings", - "link_count": 0, - "link_to": "Print Settings", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Print Format", - "link_count": 0, - "link_to": "Print Format", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Print Style", - "link_count": 0, - "link_to": "Print Style", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Workflow", - "link_count": 0, - "onboard": 0, - "type": "Card Break" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Workflow", - "link_count": 0, - "link_to": "Workflow", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Workflow State", - "link_count": 0, - "link_to": "Workflow State", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Workflow Action", - "link_count": 0, - "link_to": "Workflow Action", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Core", - "link_count": 3, - "onboard": 0, - "type": "Card Break" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "System Settings", - "link_count": 0, - "link_to": "System Settings", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "dependencies": "", - "hidden": 0, - "is_query_report": 0, - "label": "Domain Settings", - "link_count": 0, - "link_to": "Domain Settings", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Global Defaults", - "link_count": 0, - "link_to": "Global Defaults", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Module Settings", - "link_count": 8, - "onboard": 0, - "type": "Card Break" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Accounts Settings", - "link_count": 0, - "link_to": "Accounts Settings", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Stock Settings", - "link_count": 0, - "link_to": "Stock Settings", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Selling Settings", - "link_count": 0, - "link_to": "Selling Settings", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Buying Settings", - "link_count": 0, - "link_to": "Buying Settings", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Manufacturing Settings", - "link_count": 0, - "link_to": "Manufacturing Settings", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "CRM Settings", - "link_count": 0, - "link_to": "CRM Settings", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Projects Settings", - "link_count": 0, - "link_to": "Projects Settings", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - }, - { - "hidden": 0, - "is_query_report": 0, - "label": "Support Settings", - "link_count": 0, - "link_to": "Support Settings", - "link_type": "DocType", - "onboard": 0, - "type": "Link" - } - ], - "modified": "2023-05-24 14:47:25.356531", - "modified_by": "Administrator", - "module": "Setup", - "name": "ERPNext Settings", - "number_cards": [], - "owner": "Administrator", - "parent_page": "", - "public": 1, - "quick_lists": [], - "restrict_to_domain": "", - "roles": [], - "sequence_id": 19.0, - "shortcuts": [ - { - "color": "Grey", - "doc_view": "List", - "label": "Print Settings", - "link_to": "Print Settings", - "type": "DocType" - }, - { - "color": "Grey", - "doc_view": "List", - "label": "System Settings", - "link_to": "System Settings", - "type": "DocType" - }, - { - "icon": "accounting", - "label": "Accounts Settings", - "link_to": "Accounts Settings", - "type": "DocType" - }, - { - "color": "Grey", - "doc_view": "List", - "label": "Global Defaults", - "link_to": "Global Defaults", - "type": "DocType" - }, - { - "icon": "stock", - "label": "Stock Settings", - "link_to": "Stock Settings", - "type": "DocType" - }, - { - "icon": "sell", - "label": "Selling Settings", - "link_to": "Selling Settings", - "type": "DocType" - }, - { - "icon": "buying", - "label": "Buying Settings", - "link_to": "Buying Settings", - "type": "DocType" - } - ], - "title": "ERPNext Settings" - } \ No newline at end of file diff --git a/erpnext/setup/workspace/settings/settings.json b/erpnext/setup/workspace/settings/settings.json new file mode 100644 index 0000000000..5d95ee5efb --- /dev/null +++ b/erpnext/setup/workspace/settings/settings.json @@ -0,0 +1,500 @@ +{ + "charts": [], + "content": "[{\"id\":\"NO5yYHJopc\",\"type\":\"header\",\"data\":{\"text\":\"Your Shortcuts\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\",\"col\":12}},{\"id\":\"CDxIM-WuZ9\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"System Settings\",\"col\":3}},{\"id\":\"-Uh7DKJNJX\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Accounts Settings\",\"col\":3}},{\"id\":\"K9ST9xcDXh\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Stock Settings\",\"col\":3}},{\"id\":\"27IdVHVQMb\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Selling Settings\",\"col\":3}},{\"id\":\"Rwp5zff88b\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Buying Settings\",\"col\":3}},{\"id\":\"hkfnQ2sevf\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Global Defaults\",\"col\":3}},{\"id\":\"jjxI_PDawD\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Print Settings\",\"col\":3}},{\"id\":\"R3CoYYFXye\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"yynbm1J_VO\",\"type\":\"header\",\"data\":{\"text\":\"Settings\",\"col\":12}},{\"id\":\"KDCv2MvSg3\",\"type\":\"card\",\"data\":{\"card_name\":\"Module Settings\",\"col\":4}},{\"id\":\"Q0_bqT7cxQ\",\"type\":\"card\",\"data\":{\"card_name\":\"Email / Notifications\",\"col\":4}},{\"id\":\"UnqK5haBnh\",\"type\":\"card\",\"data\":{\"card_name\":\"Website\",\"col\":4}},{\"id\":\"kp7u1H5hCd\",\"type\":\"card\",\"data\":{\"card_name\":\"Core\",\"col\":4}},{\"id\":\"Ufc3jycgy9\",\"type\":\"card\",\"data\":{\"card_name\":\"Printing\",\"col\":4}},{\"id\":\"89bSNzv3Yh\",\"type\":\"card\",\"data\":{\"card_name\":\"Workflow\",\"col\":4}}]", + "creation": "2022-01-27 13:14:47.349433", + "custom_blocks": [], + "docstatus": 0, + "doctype": "Workspace", + "for_user": "", + "hide_custom": 0, + "icon": "setting", + "idx": 0, + "is_hidden": 0, + "label": "Settings", + "links": [ + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Import Data", + "link_count": 0, + "link_to": "Data Import", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Export Data", + "link_count": 0, + "link_to": "Data Export", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Bulk Update", + "link_count": 0, + "link_to": "Bulk Update", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Download Backups", + "link_count": 0, + "link_to": "backups", + "link_type": "Page", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Deleted Documents", + "link_count": 0, + "link_to": "Deleted Document", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Email / Notifications", + "link_count": 0, + "onboard": 0, + "type": "Card Break" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Email Account", + "link_count": 0, + "link_to": "Email Account", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Email Domain", + "link_count": 0, + "link_to": "Email Domain", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Notification", + "link_count": 0, + "link_to": "Notification", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Email Template", + "link_count": 0, + "link_to": "Email Template", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Auto Email Report", + "link_count": 0, + "link_to": "Auto Email Report", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Newsletter", + "link_count": 0, + "link_to": "Newsletter", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Notification Settings", + "link_count": 0, + "link_to": "Notification Settings", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Website", + "link_count": 0, + "onboard": 0, + "type": "Card Break" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Website Settings", + "link_count": 0, + "link_to": "Website Settings", + "link_type": "DocType", + "onboard": 1, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Website Theme", + "link_count": 0, + "link_to": "Website Theme", + "link_type": "DocType", + "onboard": 1, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Website Script", + "link_count": 0, + "link_to": "Website Script", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "About Us Settings", + "link_count": 0, + "link_to": "About Us Settings", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Contact Us Settings", + "link_count": 0, + "link_to": "Contact Us Settings", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Printing", + "link_count": 0, + "onboard": 0, + "type": "Card Break" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Print Format Builder", + "link_count": 0, + "link_to": "print-format-builder", + "link_type": "Page", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Print Settings", + "link_count": 0, + "link_to": "Print Settings", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Print Format", + "link_count": 0, + "link_to": "Print Format", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Print Style", + "link_count": 0, + "link_to": "Print Style", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Workflow", + "link_count": 0, + "onboard": 0, + "type": "Card Break" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Workflow", + "link_count": 0, + "link_to": "Workflow", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Workflow State", + "link_count": 0, + "link_to": "Workflow State", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Workflow Action", + "link_count": 0, + "link_to": "Workflow Action", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Core", + "link_count": 3, + "onboard": 0, + "type": "Card Break" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "System Settings", + "link_count": 0, + "link_to": "System Settings", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "dependencies": "", + "hidden": 0, + "is_query_report": 0, + "label": "Domain Settings", + "link_count": 0, + "link_to": "Domain Settings", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Global Defaults", + "link_count": 0, + "link_to": "Global Defaults", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Module Settings", + "link_count": 8, + "onboard": 0, + "type": "Card Break" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Accounts Settings", + "link_count": 0, + "link_to": "Accounts Settings", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Stock Settings", + "link_count": 0, + "link_to": "Stock Settings", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Selling Settings", + "link_count": 0, + "link_to": "Selling Settings", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Buying Settings", + "link_count": 0, + "link_to": "Buying Settings", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Manufacturing Settings", + "link_count": 0, + "link_to": "Manufacturing Settings", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "CRM Settings", + "link_count": 0, + "link_to": "CRM Settings", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Projects Settings", + "link_count": 0, + "link_to": "Projects Settings", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + }, + { + "hidden": 0, + "is_query_report": 0, + "label": "Support Settings", + "link_count": 0, + "link_to": "Support Settings", + "link_type": "DocType", + "onboard": 0, + "type": "Link" + } + ], + "modified": "2024-01-02 15:17:30.421357", + "modified_by": "Administrator", + "module": "Setup", + "name": "Settings", + "number_cards": [], + "owner": "Administrator", + "parent_page": "", + "public": 1, + "quick_lists": [], + "restrict_to_domain": "", + "roles": [], + "sequence_id": 19.0, + "shortcuts": [ + { + "color": "Grey", + "doc_view": "List", + "label": "Print Settings", + "link_to": "Print Settings", + "type": "DocType" + }, + { + "color": "Grey", + "doc_view": "List", + "label": "System Settings", + "link_to": "System Settings", + "type": "DocType" + }, + { + "icon": "accounting", + "label": "Accounts Settings", + "link_to": "Accounts Settings", + "type": "DocType" + }, + { + "color": "Grey", + "doc_view": "List", + "label": "Global Defaults", + "link_to": "Global Defaults", + "type": "DocType" + }, + { + "icon": "stock", + "label": "Stock Settings", + "link_to": "Stock Settings", + "type": "DocType" + }, + { + "icon": "sell", + "label": "Selling Settings", + "link_to": "Selling Settings", + "type": "DocType" + }, + { + "icon": "buying", + "label": "Buying Settings", + "link_to": "Buying Settings", + "type": "DocType" + } + ], + "title": "Settings" +} \ No newline at end of file From b250a21a2b5b34031c5b326406a4135e9f82db71 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Tue, 2 Jan 2024 15:50:54 +0530 Subject: [PATCH 149/205] fix(minor): remove "hide_workspaces" from erpnext/install.py --- erpnext/setup/install.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/erpnext/setup/install.py b/erpnext/setup/install.py index 7a1d5e284e..6239864c23 100644 --- a/erpnext/setup/install.py +++ b/erpnext/setup/install.py @@ -31,7 +31,6 @@ def after_install(): add_company_to_session_defaults() add_standard_navbar_items() add_app_name() - hide_workspaces() update_roles() frappe.db.commit() @@ -218,11 +217,6 @@ def add_app_name(): frappe.db.set_single_value("System Settings", "app_name", "ERPNext") -def hide_workspaces(): - for ws in ["Integration", "Settings"]: - frappe.db.set_value("Workspace", ws, "public", 0) - - def update_roles(): website_user_roles = ("Customer", "Supplier") for role in website_user_roles: From 1bc74bde291f92f450497fef6d30c86a0c0209d2 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 2 Jan 2024 15:18:15 +0530 Subject: [PATCH 150/205] refactor: flag to control loyalty point creation at invoice level --- .../doctype/sales_invoice/sales_invoice.json | 14 +++++++++++--- .../doctype/sales_invoice/sales_invoice.py | 8 +++++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json index f2094874e0..5e2187e91f 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.json +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.json @@ -138,6 +138,7 @@ "loyalty_amount", "column_break_77", "loyalty_program", + "dont_create_loyalty_points", "loyalty_redemption_account", "loyalty_redemption_cost_center", "contact_and_address_tab", @@ -1041,8 +1042,7 @@ "label": "Loyalty Program", "no_copy": 1, "options": "Loyalty Program", - "print_hide": 1, - "read_only": 1 + "print_hide": 1 }, { "allow_on_submit": 1, @@ -2162,6 +2162,14 @@ "fieldname": "update_billed_amount_in_delivery_note", "fieldtype": "Check", "label": "Update Billed Amount in Delivery Note" + }, + { + "default": "0", + "depends_on": "loyalty_program", + "fieldname": "dont_create_loyalty_points", + "fieldtype": "Check", + "label": "Don't Create Loyalty Points", + "no_copy": 1 } ], "icon": "fa fa-file-text", @@ -2174,7 +2182,7 @@ "link_fieldname": "consolidated_invoice" } ], - "modified": "2023-11-23 16:56:29.679499", + "modified": "2024-01-02 17:25:46.027523", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice", diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index c0228e6b0b..ed7f790426 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -117,6 +117,7 @@ class SalesInvoice(SellingController): discount_amount: DF.Currency dispatch_address: DF.SmallText | None dispatch_address_name: DF.Link | None + dont_create_loyalty_points: DF.Check due_date: DF.Date | None from_date: DF.Date | None grand_total: DF.Currency @@ -471,7 +472,12 @@ class SalesInvoice(SellingController): update_linked_doc(self.doctype, self.name, self.inter_company_invoice_reference) # create the loyalty point ledger entry if the customer is enrolled in any loyalty program - if not self.is_return and not self.is_consolidated and self.loyalty_program: + if ( + not self.is_return + and not self.is_consolidated + and self.loyalty_program + and not self.dont_create_loyalty_points + ): self.make_loyalty_point_entry() elif ( self.is_return and self.return_against and not self.is_consolidated and self.loyalty_program From beee98da6d46732b7ab0cd324a75b9262473a444 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Wed, 3 Jan 2024 10:03:27 +0530 Subject: [PATCH 151/205] feat: Against voucher filter in General Ledger (#39100) --- erpnext/accounts/report/general_ledger/general_ledger.js | 5 +++++ erpnext/accounts/report/general_ledger/general_ledger.py | 3 +++ erpnext/controllers/accounts_controller.py | 6 ++++++ 3 files changed, 14 insertions(+) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js index 4cb443cf92..79b5e4d9ec 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.js +++ b/erpnext/accounts/report/general_ledger/general_ledger.js @@ -52,6 +52,11 @@ frappe.query_reports["General Ledger"] = { frappe.query_report.set_filter_value('group_by', "Group by Voucher (Consolidated)"); } }, + { + "fieldname":"against_voucher_no", + "label": __("Against Voucher No"), + "fieldtype": "Data", + }, { "fieldtype": "Break", }, diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 4054dca360..6636b8e042 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -238,6 +238,9 @@ def get_conditions(filters): if filters.get("voucher_no"): conditions.append("voucher_no=%(voucher_no)s") + if filters.get("against_voucher_no"): + conditions.append("against_voucher=%(against_voucher_no)s") + if filters.get("voucher_no_not_in"): conditions.append("voucher_no not in %(voucher_no_not_in)s") diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 13df9d591c..de7a7f9da4 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -933,6 +933,12 @@ class AccountsController(TransactionBase): } ) + if not args.get("against_voucher_type") and self.get("against_voucher_type"): + gl_dict.update({"against_voucher_type": self.get("against_voucher_type")}) + + if not args.get("against_voucher") and self.get("against_voucher"): + gl_dict.update({"against_voucher": self.get("against_voucher")}) + return gl_dict def get_voucher_subtype(self): From 6401908f419a7d34d7d42d2083fe9f7cd82e7b87 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Wed, 3 Jan 2024 11:15:34 +0530 Subject: [PATCH 152/205] fix: Ignore UP on "allowed to transact with" (#39103) If a customer is allowed to transact with some company it usually doesn't imply that customer is somehow "linked with" that company. --- .../allowed_to_transact_with/allowed_to_transact_with.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/allowed_to_transact_with/allowed_to_transact_with.json b/erpnext/accounts/doctype/allowed_to_transact_with/allowed_to_transact_with.json index e3f2d59c06..234ffc8a87 100644 --- a/erpnext/accounts/doctype/allowed_to_transact_with/allowed_to_transact_with.json +++ b/erpnext/accounts/doctype/allowed_to_transact_with/allowed_to_transact_with.json @@ -11,6 +11,7 @@ { "fieldname": "company", "fieldtype": "Link", + "ignore_user_permissions": 1, "in_list_view": 1, "label": "Company", "options": "Company", @@ -19,7 +20,7 @@ ], "istable": 1, "links": [], - "modified": "2020-05-01 12:32:34.044911", + "modified": "2024-01-03 11:13:02.669632", "modified_by": "Administrator", "module": "Accounts", "name": "Allowed To Transact With", @@ -28,5 +29,6 @@ "quick_entry": 1, "sort_field": "modified", "sort_order": "DESC", + "states": [], "track_changes": 1 } \ No newline at end of file From 4415212a2d5fbcc0f201a995efc0b8a4e0cc273c Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Wed, 3 Jan 2024 12:50:25 +0530 Subject: [PATCH 153/205] chore: use diff secret --- .github/workflows/backport.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index bd622275d6..3c5ad071dc 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -21,6 +21,6 @@ jobs: - name: Run backport uses: ./actions/backport with: - token: ${{secrets.BACKPORT_BOT_TOKEN}} + token: ${{secrets.RELEASE_TOKEN}} labelsToAdd: "backport" title: "{{originalTitle}}" From 7da9ffa3bd072fbfc9627e6eb5afb3dd3078f560 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 3 Jan 2024 17:59:15 +0530 Subject: [PATCH 154/205] fix: typerror on multi select dialog --- erpnext/public/js/utils.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index 866e94f95a..598167b337 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -865,16 +865,20 @@ erpnext.utils.map_current_doc = function(opts) { } if (opts.source_doctype) { + let data_fields = []; + if(opts.source_doctype == "Purchase Receipt") { + data_fields.push({ + fieldname: 'merge_taxes', + fieldtype: 'Check', + label: __('Merge taxes from multiple documents'), + }); + } const d = new frappe.ui.form.MultiSelectDialog({ doctype: opts.source_doctype, target: opts.target, date_field: opts.date_field || undefined, setters: opts.setters, - data_fields: [{ - fieldname: 'merge_taxes', - fieldtype: 'Check', - label: __('Merge taxes from multiple documents'), - }], + data_fields: data_fields, get_query: opts.get_query, add_filters_group: 1, allow_child_item_selection: opts.allow_child_item_selection, @@ -888,7 +892,10 @@ erpnext.utils.map_current_doc = function(opts) { return; } opts.source_name = values; - opts.args = args; + if (opts.allow_child_item_selection || opts.source_doctype == "Purchase Receipt") { + // args contains filtered child docnames + opts.args = args; + } d.dialog.hide(); _map(); }, From e84c9f7c51fc6e8c5c631c74131f9290624b2a05 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Wed, 3 Jan 2024 20:10:19 +0530 Subject: [PATCH 155/205] fix(UX): dont override framework's permission check messages (#39118) --- erpnext/accounts/party.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index 008614e6d3..caa1d8583b 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -114,14 +114,12 @@ def _get_party_details( set_account_and_due_date(party, account, party_type, company, posting_date, bill_date, doctype) ) party = party_details[party_type.lower()] - - if not ignore_permissions and not ( - frappe.has_permission(party_type, "read", party) - or frappe.has_permission(party_type, "select", party) - ): - frappe.throw(_("Not permitted for {0}").format(party), frappe.PermissionError) - party = frappe.get_doc(party_type, party) + + if not ignore_permissions: + ptype = "select" if frappe.only_has_select_perm(party_type) else "read" + frappe.has_permission(party_type, ptype, party, throw=True) + currency = party.get("default_currency") or currency or get_company_currency(company) party_address, shipping_address = set_address_details( From 0f1be03faf96aaf83063e28dc57a5e016944683c Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 3 Jan 2024 20:56:12 +0530 Subject: [PATCH 156/205] fix: ignore cancelled payments in Sales/Purchase Register --- erpnext/accounts/report/utils.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/report/utils.py b/erpnext/accounts/report/utils.py index 9f96449ba7..0912c7270d 100644 --- a/erpnext/accounts/report/utils.py +++ b/erpnext/accounts/report/utils.py @@ -251,6 +251,7 @@ def get_journal_entries(filters, args): ) .where( (je.voucher_type == "Journal Entry") + & (je.docstatus == 1) & (journal_account.party == filters.get(args.party)) & (journal_account.account.isin(args.party_account)) ) @@ -281,7 +282,9 @@ def get_payment_entries(filters, args): pe.cost_center, ) .where( - (pe.party == filters.get(args.party)) & (pe[args.account_fieldname].isin(args.party_account)) + (pe.docstatus == 1) + & (pe.party == filters.get(args.party)) + & (pe[args.account_fieldname].isin(args.party_account)) ) .orderby(pe.posting_date, pe.name, order=Order.desc) ) From 5e2669f4b6e8ed917cc8e882b49a4a617a854464 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 3 Jan 2024 21:43:38 +0530 Subject: [PATCH 157/205] feat: provision to close SCO --- .../subcontracting_order.js | 23 +++++++++++++++++++ .../subcontracting_order.json | 4 ++-- .../subcontracting_order.py | 5 ++-- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js index 587a3b4ebf..ae9a3252ef 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js +++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js @@ -101,9 +101,32 @@ frappe.ui.form.on('Subcontracting Order', { }, refresh: function (frm) { + if (frm.has_perm("submit")) { + if (frm.doc.status == "Closed") { + frm.add_custom_button(__('Re-open'), () => frm.events.update_subcontracting_order_status(frm), __("Status")); + } else if(flt(frm.doc.per_received, 2) < 100) { + frm.add_custom_button(__('Close'), () => frm.events.update_subcontracting_order_status(frm, "Closed"), __("Status")); + } + } + frm.trigger('get_materials_from_supplier'); }, + update_subcontracting_order_status(frm, status) { + frappe.call({ + method: "erpnext.subcontracting.doctype.subcontracting_order.subcontracting_order.update_subcontracting_order_status", + args: { + sco: frm.doc.name, + status: status, + }, + callback: function (r) { + if (!r.exc) { + frm.reload_doc(); + } + }, + }); + }, + get_materials_from_supplier: function (frm) { let sco_rm_details = []; diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.json b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.json index 28c52c9272..507e23365c 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.json +++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.json @@ -370,7 +370,7 @@ "in_standard_filter": 1, "label": "Status", "no_copy": 1, - "options": "Draft\nOpen\nPartially Received\nCompleted\nMaterial Transferred\nPartial Material Transferred\nCancelled", + "options": "Draft\nOpen\nPartially Received\nCompleted\nMaterial Transferred\nPartial Material Transferred\nCancelled\nClosed", "print_hide": 1, "read_only": 1, "reqd": 1, @@ -454,7 +454,7 @@ "icon": "fa fa-file-text", "is_submittable": 1, "links": [], - "modified": "2023-06-03 16:18:17.782538", + "modified": "2024-01-03 20:56:04.670380", "modified_by": "Administrator", "module": "Subcontracting", "name": "Subcontracting Order", diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py index 0fe8c13efb..6690244325 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py +++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py @@ -68,6 +68,7 @@ class SubcontractingOrder(SubcontractingController): "Material Transferred", "Partial Material Transferred", "Cancelled", + "Closed", ] supplied_items: DF.Table[SubcontractingOrderSuppliedItem] supplier: DF.Link @@ -357,8 +358,8 @@ def get_mapped_subcontracting_receipt(source_name, target_doc=None): @frappe.whitelist() -def update_subcontracting_order_status(sco): +def update_subcontracting_order_status(sco, status=None): if isinstance(sco, str): sco = frappe.get_doc("Subcontracting Order", sco) - sco.update_status() + sco.update_status(status) From 9e973476b2a925d4557b3a6b17517e46d652ac20 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 3 Jan 2024 22:13:37 +0530 Subject: [PATCH 158/205] fix: don't allow to submit/cancel SCR against a closed SCO --- .../subcontracting_receipt/subcontracting_receipt.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py index 52bf13c78d..7c2a1f12e2 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py @@ -8,6 +8,7 @@ from frappe.utils import cint, flt, get_link_to_form, getdate, nowdate import erpnext from erpnext.accounts.utils import get_account_currency +from erpnext.buying.utils import check_on_hold_or_closed_status from erpnext.controllers.subcontracting_controller import SubcontractingController from erpnext.stock.stock_ledger import get_valuation_rate @@ -142,6 +143,7 @@ class SubcontractingReceipt(SubcontractingController): self.get_current_stock() def on_submit(self): + self.validate_closed_subcontracting_order() self.validate_available_qty_for_consumption() self.update_status_updater_args() self.update_prevdoc_status() @@ -165,6 +167,7 @@ class SubcontractingReceipt(SubcontractingController): "Repost Item Valuation", "Serial and Batch Bundle", ) + self.validate_closed_subcontracting_order() self.update_status_updater_args() self.update_prevdoc_status() self.set_consumed_qty_in_subcontract_order() @@ -175,6 +178,11 @@ class SubcontractingReceipt(SubcontractingController): self.update_status() self.delete_auto_created_batches() + def validate_closed_subcontracting_order(self): + for item in self.items: + if item.subcontracting_order: + check_on_hold_or_closed_status("Subcontracting Order", item.subcontracting_order) + def validate_items_qty(self): for item in self.items: if not (item.qty or item.rejected_qty): From 5bc2035bd082001e2552138a5df55554f2e6f8de Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 3 Jan 2024 22:20:06 +0530 Subject: [PATCH 159/205] fix: don't allow to submit/cancel SE against a closed SCO --- .../stock/doctype/stock_entry/stock_entry.py | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 2ccee94078..bccbc28087 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -24,6 +24,7 @@ from frappe.utils import ( import erpnext from erpnext.accounts.general_ledger import process_gl_map +from erpnext.buying.utils import check_on_hold_or_closed_status from erpnext.controllers.taxes_and_totals import init_landed_taxes_and_totals from erpnext.manufacturing.doctype.bom.bom import ( add_additional_cost, @@ -208,7 +209,6 @@ class StockEntry(StockController): self.validate_bom() self.set_process_loss_qty() self.validate_purchase_order() - self.validate_subcontracting_order() if self.purpose in ("Manufacture", "Repack"): self.mark_finished_and_scrap_items() @@ -274,6 +274,7 @@ class StockEntry(StockController): return False def on_submit(self): + self.validate_closed_subcontracting_order() self.update_stock_ledger() self.update_work_order() self.validate_subcontract_order() @@ -294,6 +295,7 @@ class StockEntry(StockController): self.set_material_request_transfer_status("Completed") def on_cancel(self): + self.validate_closed_subcontracting_order() self.update_subcontract_order_supplied_items() self.update_subcontracting_order_status() @@ -1203,19 +1205,9 @@ class StockEntry(StockController): ) ) - def validate_subcontracting_order(self): - if self.get("subcontracting_order") and self.purpose in [ - "Send to Subcontractor", - "Material Transfer", - ]: - sco_status = frappe.db.get_value("Subcontracting Order", self.subcontracting_order, "status") - - if sco_status == "Closed": - frappe.throw( - _("Cannot create Stock Entry against a closed Subcontracting Order {0}.").format( - self.subcontracting_order - ) - ) + def validate_closed_subcontracting_order(self): + if self.get("subcontracting_order"): + check_on_hold_or_closed_status("Subcontracting Order", self.subcontracting_order) def mark_finished_and_scrap_items(self): if self.purpose != "Repack" and any( From bb839b2924c2dd4c2a06b087d7624ca7aac08f04 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Wed, 3 Jan 2024 22:22:21 +0530 Subject: [PATCH 160/205] fix(ux): filter closed SCO in `Get Items From` dialog --- .../doctype/subcontracting_order/subcontracting_order_list.js | 2 +- .../doctype/subcontracting_receipt/subcontracting_receipt.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order_list.js b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order_list.js index 7ca12642c5..ec54944a84 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order_list.js +++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order_list.js @@ -10,7 +10,7 @@ frappe.listview_settings['Subcontracting Order'] = { "Completed": "green", "Partial Material Transferred": "purple", "Material Transferred": "blue", - "Closed": "red", + "Closed": "green", "Cancelled": "red", }; return [__(doc.status), status_colors[doc.status], "status,=," + doc.status]; diff --git a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js index 575c4eda73..05357999a1 100644 --- a/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js +++ b/erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.js @@ -93,7 +93,8 @@ frappe.ui.form.on('Subcontracting Receipt', { get_query_filters: { docstatus: 1, per_received: ['<', 100], - company: frm.doc.company + company: frm.doc.company, + status: ['!=', 'Closed'], } }); }, __('Get Items From')); From 5b1571879cdb7859725bda2b0d32d9a4f57676e8 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 4 Jan 2024 10:48:01 +0530 Subject: [PATCH 161/205] fix: flaky demo test case --- erpnext/accounts/party.py | 4 +--- erpnext/controllers/accounts_controller.py | 6 ------ erpnext/setup/demo.py | 5 +++++ 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index caa1d8583b..fc9034b2ee 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -635,9 +635,7 @@ def get_due_date_from_template(template_name, posting_date, bill_date): return due_date -def validate_due_date( - posting_date, due_date, party_type, party, company=None, bill_date=None, template_name=None -): +def validate_due_date(posting_date, due_date, bill_date=None, template_name=None): if getdate(due_date) < getdate(posting_date): frappe.throw(_("Due Date cannot be before Posting / Supplier Invoice Date")) else: diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index de7a7f9da4..0409c68535 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -561,18 +561,12 @@ class AccountsController(TransactionBase): validate_due_date( self.posting_date, self.due_date, - "Customer", - self.customer, - self.company, self.payment_terms_template, ) elif self.doctype == "Purchase Invoice": validate_due_date( self.bill_date or self.posting_date, self.due_date, - "Supplier", - self.supplier, - self.company, self.bill_date, self.payment_terms_template, ) diff --git a/erpnext/setup/demo.py b/erpnext/setup/demo.py index 4bc98b91bd..df2c49b2b6 100644 --- a/erpnext/setup/demo.py +++ b/erpnext/setup/demo.py @@ -149,6 +149,11 @@ def convert_order_to_invoices(): invoice.set_posting_time = 1 invoice.posting_date = order.transaction_date invoice.due_date = order.transaction_date + invoice.bill_date = order.transaction_date + + if invoice.get("payment_schedule"): + invoice.payment_schedule[0].due_date = order.transaction_date + invoice.update_stock = 1 invoice.submit() From 277dade9f9a0a439d435dd6a53474aae67cd8f24 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 4 Jan 2024 11:22:42 +0530 Subject: [PATCH 162/205] fix: Subscription update patch --- .../patches/v14_0/update_invoicing_period_in_subscription.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/patches/v14_0/update_invoicing_period_in_subscription.py b/erpnext/patches/v14_0/update_invoicing_period_in_subscription.py index 2879e57e1a..b70548ccb7 100644 --- a/erpnext/patches/v14_0/update_invoicing_period_in_subscription.py +++ b/erpnext/patches/v14_0/update_invoicing_period_in_subscription.py @@ -4,5 +4,5 @@ import frappe def execute(): subscription = frappe.qb.DocType("Subscription") frappe.qb.update(subscription).set( - subscription.generate_invoice_at, "Beginning of the currency subscription period" + subscription.generate_invoice_at, "Beginning of the current subscription period" ).where(subscription.generate_invoice_at_period_start == 1).run() From e1b0fffd0c934d376562e3ba8707b38426ea09a1 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 4 Jan 2024 11:43:02 +0530 Subject: [PATCH 163/205] fix: don't set rate for non-stock item in Internal Transfer --- erpnext/controllers/selling_controller.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index 919e459c9e..22b0d08c92 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -432,6 +432,9 @@ class SellingController(StockController): items = self.get("items") + (self.get("packed_items") or []) for d in items: + if not frappe.get_cached_value("Item", d.item_code, "is_stock_item"): + continue + if not self.get("return_against") or ( get_valuation_method(d.item_code) == "Moving Average" and self.get("is_return") ): From 57b6a987034522266caca853d4ee26316526e526 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 4 Jan 2024 12:20:53 +0530 Subject: [PATCH 164/205] test: internal transfer for non-stock item --- .../delivery_note/test_delivery_note.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/erpnext/stock/doctype/delivery_note/test_delivery_note.py b/erpnext/stock/doctype/delivery_note/test_delivery_note.py index 3abd1d9e5e..dae42895ed 100644 --- a/erpnext/stock/doctype/delivery_note/test_delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/test_delivery_note.py @@ -1518,6 +1518,25 @@ class TestDeliveryNote(FrappeTestCase): "Stock Settings", "auto_create_serial_and_batch_bundle_for_outward", 0 ) + def test_internal_transfer_for_non_stock_item(self): + from erpnext.selling.doctype.customer.test_customer import create_internal_customer + from erpnext.selling.doctype.sales_order.sales_order import make_delivery_note + + item = make_item(properties={"is_stock_item": 0}).name + warehouse = "_Test Warehouse - _TC" + target = "Stores - _TC" + company = "_Test Company" + customer = create_internal_customer(represents_company=company) + rate = 100 + + so = make_sales_order(item_code=item, qty=1, rate=rate, customer=customer, warehouse=warehouse) + dn = make_delivery_note(so.name) + dn.items[0].target_warehouse = target + dn.save().submit() + + self.assertEqual(so.items[0].rate, rate) + self.assertEqual(dn.items[0].rate, so.items[0].rate) + def create_delivery_note(**args): dn = frappe.new_doc("Delivery Note") From 0d01bd8a5a49f5bba80ef797d5823f762e0fc86a Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 4 Jan 2024 12:34:25 +0530 Subject: [PATCH 165/205] fix: don't close PO on SCO close --- .../doctype/subcontracting_order/subcontracting_order.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py index 6690244325..bc3061169a 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py +++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py @@ -7,7 +7,6 @@ from frappe.model.mapper import get_mapped_doc from frappe.utils import flt from erpnext.buying.doctype.purchase_order.purchase_order import is_subcontracting_order_created -from erpnext.buying.doctype.purchase_order.purchase_order import update_status as update_po_status from erpnext.controllers.subcontracting_controller import SubcontractingController from erpnext.stock.stock_balance import update_bin_qty from erpnext.stock.utils import get_bin @@ -310,9 +309,6 @@ class SubcontractingOrder(SubcontractingController): "Subcontracting Order", self.name, "status", status, update_modified=update_modified ) - if status == "Closed": - update_po_status("Closed", self.purchase_order) - @frappe.whitelist() def make_subcontracting_receipt(source_name, target_doc=None): From 245effcccd3866bac2974023d37cd48b89849aeb Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 4 Jan 2024 12:48:36 +0530 Subject: [PATCH 166/205] fix: update qty on SCO status change --- .../subcontracting_order/subcontracting_order.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py index bc3061169a..14f9bfd5dc 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py +++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py @@ -112,16 +112,10 @@ class SubcontractingOrder(SubcontractingController): def on_submit(self): self.update_prevdoc_status() - self.update_requested_qty() - self.update_ordered_qty_for_subcontracting() - self.update_reserved_qty_for_subcontracting() self.update_status() def on_cancel(self): self.update_prevdoc_status() - self.update_requested_qty() - self.update_ordered_qty_for_subcontracting() - self.update_reserved_qty_for_subcontracting() self.update_status() def validate_purchase_order_for_subcontracting(self): @@ -305,9 +299,11 @@ class SubcontractingOrder(SubcontractingController): status = "Cancelled" if status: - frappe.db.set_value( - "Subcontracting Order", self.name, "status", status, update_modified=update_modified - ) + self.db_set("status", status, update_modified=update_modified) + + self.update_requested_qty() + self.update_ordered_qty_for_subcontracting() + self.update_reserved_qty_for_subcontracting() @frappe.whitelist() From 784b6dcfea2aa9eb3fe557bb4f87cdc1f7341560 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 4 Jan 2024 13:05:17 +0530 Subject: [PATCH 167/205] fix: don't allow to reopen SCO if PO is closed --- .../doctype/subcontracting_order/subcontracting_order.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py index 14f9bfd5dc..3daa6335f3 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py +++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py @@ -7,6 +7,7 @@ from frappe.model.mapper import get_mapped_doc from frappe.utils import flt from erpnext.buying.doctype.purchase_order.purchase_order import is_subcontracting_order_created +from erpnext.buying.utils import check_on_hold_or_closed_status from erpnext.controllers.subcontracting_controller import SubcontractingController from erpnext.stock.stock_balance import update_bin_qty from erpnext.stock.utils import get_bin @@ -271,6 +272,9 @@ class SubcontractingOrder(SubcontractingController): self.set_missing_values() def update_status(self, status=None, update_modified=True): + if self.status == "Closed": + check_on_hold_or_closed_status("Purchase Order", self.purchase_order) + if self.docstatus >= 1 and not status: if self.docstatus == 1: if self.status == "Draft": From 0819675fce1cffe3a930fe2cbd015998e4e7c00d Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 4 Jan 2024 13:44:53 +0530 Subject: [PATCH 168/205] fix: auto close and reopen SCO based on PO status --- .../buying/doctype/purchase_order/purchase_order.py | 12 ++++++++++++ .../subcontracting_order/subcontracting_order.py | 4 ++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 2efb46e9d3..b830e7d204 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -452,6 +452,7 @@ class PurchaseOrder(BuyingController): self.update_requested_qty() self.update_ordered_qty() self.update_reserved_qty_for_subcontract() + self.update_subcontracting_order_status() self.notify_update() clear_doctype_notifications(self) @@ -627,6 +628,17 @@ class PurchaseOrder(BuyingController): if frappe.db.get_single_value("Buying Settings", "auto_create_subcontracting_order"): make_subcontracting_order(self.name, save=True, notify=True) + def update_subcontracting_order_status(self): + from erpnext.subcontracting.doctype.subcontracting_order.subcontracting_order import ( + update_subcontracting_order_status as update_sco_status, + ) + + if self.is_subcontracted and not self.is_old_subcontracting_flow: + sco = frappe.db.get_value("Subcontracting Order", {"purchase_order": self.name, "docstatus": 1}) + + if sco: + update_sco_status(sco, "Closed" if self.status == "Closed" else None) + def item_last_purchase_rate(name, conversion_rate, item_code, conversion_factor=1.0): """get last purchase rate for an item""" diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py index 3daa6335f3..309e4fe643 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py +++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py @@ -272,7 +272,7 @@ class SubcontractingOrder(SubcontractingController): self.set_missing_values() def update_status(self, status=None, update_modified=True): - if self.status == "Closed": + if self.status == "Closed" and self.status != status: check_on_hold_or_closed_status("Purchase Order", self.purchase_order) if self.docstatus >= 1 and not status: @@ -302,7 +302,7 @@ class SubcontractingOrder(SubcontractingController): elif self.docstatus == 2: status = "Cancelled" - if status: + if status and self.status != status: self.db_set("status", status, update_modified=update_modified) self.update_requested_qty() From f09e2130a1a3ca999247f89f76c20efcc003b450 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Thu, 4 Jan 2024 14:58:02 +0530 Subject: [PATCH 169/205] fix: serial / batch barcode scanner (#39114) --- erpnext/controllers/accounts_controller.py | 14 ++ erpnext/public/js/controllers/transaction.js | 30 ++- erpnext/public/js/utils/barcode_scanner.js | 237 ++++++++++++++---- .../serial_and_batch_bundle.py | 63 ++++- erpnext/stock/serial_batch_bundle.py | 2 +- erpnext/stock/utils.py | 7 + 6 files changed, 286 insertions(+), 67 deletions(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 0409c68535..82b5416ef5 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -129,6 +129,17 @@ class AccountsController(TransactionBase): if self.doctype in relevant_docs: self.set_payment_schedule() + def remove_bundle_for_non_stock_invoices(self): + has_sabb = False + if self.doctype in ("Sales Invoice", "Purchase Invoice") and not self.update_stock: + for item in self.get("items"): + if item.serial_and_batch_bundle: + item.serial_and_batch_bundle = None + has_sabb = True + + if has_sabb: + self.remove_serial_and_batch_bundle() + def ensure_supplier_is_not_blocked(self): is_supplier_payment = self.doctype == "Payment Entry" and self.party_type == "Supplier" is_buying_invoice = self.doctype in ["Purchase Invoice", "Purchase Order"] @@ -156,6 +167,9 @@ class AccountsController(TransactionBase): if self.get("_action") and self._action != "update_after_submit": self.set_missing_values(for_validate=True) + if self.get("_action") == "submit": + self.remove_bundle_for_non_stock_invoices() + self.ensure_supplier_is_not_blocked() self.validate_date_with_fiscal_year() diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 9427c38064..4d8f6839b4 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -454,7 +454,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe item.weight_uom = ''; item.conversion_factor = 0; - if(['Sales Invoice'].includes(this.frm.doc.doctype)) { + if(['Sales Invoice', 'Purchase Invoice'].includes(this.frm.doc.doctype)) { update_stock = cint(me.frm.doc.update_stock); show_batch_dialog = update_stock; @@ -545,7 +545,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe }, () => me.toggle_conversion_factor(item), () => { - if (show_batch_dialog) + if (show_batch_dialog && !frappe.flags.trigger_from_barcode_scanner) return frappe.db.get_value("Item", item.item_code, ["has_batch_no", "has_serial_no"]) .then((r) => { if (r.message && @@ -1239,6 +1239,20 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe } } + sync_bundle_data() { + let doctypes = ["Sales Invoice", "Purchase Invoice", "Delivery Note", "Purchase Receipt"]; + + if (this.frm.is_new() && doctypes.includes(this.frm.doc.doctype)) { + const barcode_scanner = new erpnext.utils.BarcodeScanner({frm:this.frm}); + barcode_scanner.sync_bundle_data(); + barcode_scanner.remove_item_from_localstorage(); + } + } + + before_save(doc) { + this.sync_bundle_data(); + } + service_start_date(frm, cdt, cdn) { var child = locals[cdt][cdn]; @@ -1576,6 +1590,18 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe return item_list; } + items_delete() { + this.update_localstorage_scanned_data(); + } + + update_localstorage_scanned_data() { + let doctypes = ["Sales Invoice", "Purchase Invoice", "Delivery Note", "Purchase Receipt"]; + if (this.frm.is_new() && doctypes.includes(this.frm.doc.doctype)) { + const barcode_scanner = new erpnext.utils.BarcodeScanner({frm:this.frm}); + barcode_scanner.update_localstorage_scanned_data(); + } + } + _set_values_for_item_list(children) { const items_rule_dict = {}; diff --git a/erpnext/public/js/utils/barcode_scanner.js b/erpnext/public/js/utils/barcode_scanner.js index a1ebfe9aa4..cf7fab89ff 100644 --- a/erpnext/public/js/utils/barcode_scanner.js +++ b/erpnext/public/js/utils/barcode_scanner.js @@ -7,8 +7,6 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner { this.scan_barcode_field = this.frm.fields_dict[this.scan_field_name]; this.barcode_field = opts.barcode_field || "barcode"; - this.serial_no_field = opts.serial_no_field || "serial_no"; - this.batch_no_field = opts.batch_no_field || "batch_no"; this.uom_field = opts.uom_field || "uom"; this.qty_field = opts.qty_field || "qty"; // field name on row which defines max quantity to be scanned e.g. picklist @@ -84,6 +82,7 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner { update_table(data) { return new Promise((resolve, reject) => { let cur_grid = this.frm.fields_dict[this.items_table_name].grid; + frappe.flags.trigger_from_barcode_scanner = true; const {item_code, barcode, batch_no, serial_no, uom} = data; @@ -106,50 +105,38 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner { this.frm.has_items = false; } - if (this.is_duplicate_serial_no(row, serial_no)) { + if (serial_no && this.is_duplicate_serial_no(row, item_code, serial_no)) { this.clean_up(); reject(); return; } frappe.run_serially([ - () => this.set_selector_trigger_flag(data), - () => this.set_serial_no(row, serial_no), - () => this.set_batch_no(row, batch_no), + () => this.set_serial_and_batch(row, item_code, serial_no, batch_no), () => this.set_barcode(row, barcode), () => this.set_item(row, item_code, barcode, batch_no, serial_no).then(qty => { this.show_scan_message(row.idx, row.item_code, qty); }), () => this.set_barcode_uom(row, uom), () => this.clean_up(), - () => this.revert_selector_flag(), - () => resolve(row) + () => resolve(row), + () => { + if (row.serial_and_batch_bundle && !this.frm.is_new()) { + this.frm.save(); + } + + frappe.flags.trigger_from_barcode_scanner = false; + } ]); }); } - // batch and serial selector is reduandant when all info can be added by scan - // this flag on item row is used by transaction.js to avoid triggering selector - set_selector_trigger_flag(data) { - const {has_batch_no, has_serial_no} = data; - - const require_selecting_batch = has_batch_no; - const require_selecting_serial = has_serial_no; - - if (!(require_selecting_batch || require_selecting_serial)) { - frappe.flags.hide_serial_batch_dialog = true; - } - } - - revert_selector_flag() { - frappe.flags.hide_serial_batch_dialog = false; - } - set_item(row, item_code, barcode, batch_no, serial_no) { return new Promise(resolve => { const increment = async (value = 1) => { const item_data = {item_code: item_code}; item_data[this.qty_field] = Number((row[this.qty_field] || 0)) + Number(value); + frappe.flags.trigger_from_barcode_scanner = true; await frappe.model.set_value(row.doctype, row.name, item_data); return value; }; @@ -158,8 +145,6 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner { frappe.prompt(__("Please enter quantity for item {0}", [item_code]), ({value}) => { increment(value).then((value) => resolve(value)); }); - } else if (this.frm.has_items) { - this.prepare_item_for_scan(row, item_code, barcode, batch_no, serial_no); } else { increment().then((value) => resolve(value)); } @@ -182,9 +167,8 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner { frappe.model.set_value(row.doctype, row.name, item_data); frappe.run_serially([ - () => this.set_batch_no(row, this.dialog.get_value("batch_no")), () => this.set_barcode(row, this.dialog.get_value("barcode")), - () => this.set_serial_no(row, this.dialog.get_value("serial_no")), + () => this.set_serial_and_batch(row, item_code, this.dialog.get_value("serial_no"), this.dialog.get_value("batch_no")), () => this.add_child_for_remaining_qty(row), () => this.clean_up() ]); @@ -338,32 +322,144 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner { } } - async set_serial_no(row, serial_no) { - if (serial_no && frappe.meta.has_field(row.doctype, this.serial_no_field)) { - const existing_serial_nos = row[this.serial_no_field]; - let new_serial_nos = ""; - - if (!!existing_serial_nos) { - new_serial_nos = existing_serial_nos + "\n" + serial_no; - } else { - new_serial_nos = serial_no; - } - await frappe.model.set_value(row.doctype, row.name, this.serial_no_field, new_serial_nos); + async set_serial_and_batch(row, item_code, serial_no, batch_no) { + if (this.frm.is_new() || !row.serial_and_batch_bundle) { + this.set_bundle_in_localstorage(row, item_code, serial_no, batch_no); + } else if(row.serial_and_batch_bundle) { + frappe.call({ + method: "erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.update_serial_or_batch", + args: { + bundle_id: row.serial_and_batch_bundle, + serial_no: serial_no, + batch_no: batch_no, + }, + }) } } + get_key_for_localstorage() { + let parts = this.frm.doc.name.split("-"); + return parts[parts.length - 1] + this.frm.doc.doctype; + } + + update_localstorage_scanned_data() { + let docname = this.frm.doc.name + if (localStorage[docname]) { + let items = JSON.parse(localStorage[docname]); + let existing_items = this.frm.doc.items.map(d => d.item_code); + if (!existing_items.length) { + localStorage.removeItem(docname); + return; + } + + for (let item_code in items) { + if (!existing_items.includes(item_code)) { + delete items[item_code]; + } + } + + localStorage[docname] = JSON.stringify(items); + } + } + + async set_bundle_in_localstorage(row, item_code, serial_no, batch_no) { + let docname = this.frm.doc.name + + let entries = JSON.parse(localStorage.getItem(docname)); + if (!entries) { + entries = {}; + } + + let key = item_code; + if (!entries[key]) { + entries[key] = []; + } + + let existing_row = []; + if (!serial_no && batch_no) { + existing_row = entries[key].filter((e) => e.batch_no === batch_no); + if (existing_row.length) { + existing_row[0].qty += 1; + } + } else if (serial_no) { + existing_row = entries[key].filter((e) => e.serial_no === serial_no); + if (existing_row.length) { + frappe.throw(__("Serial No {0} has already scanned.", [serial_no])); + } + } + + if (!existing_row.length) { + entries[key].push({ + "serial_no": serial_no, + "batch_no": batch_no, + "qty": 1 + }); + } + + localStorage.setItem(docname, JSON.stringify(entries)); + + // Auto remove from localstorage after 1 hour + setTimeout(() => { + localStorage.removeItem(docname); + }, 3600000) + } + + remove_item_from_localstorage() { + let docname = this.frm.doc.name; + if (localStorage[docname]) { + localStorage.removeItem(docname); + } + } + + async sync_bundle_data() { + let docname = this.frm.doc.name; + + if (localStorage[docname]) { + let entries = JSON.parse(localStorage[docname]); + if (entries) { + for (let entry in entries) { + let row = this.frm.doc.items.filter((item) => { + if (item.item_code === entry) { + return true; + } + })[0]; + + if (row) { + this.create_serial_and_batch_bundle(row, entries, entry) + .then(() => { + if (!entries) { + localStorage.removeItem(docname); + } + }); + } + } + } + } + } + + async create_serial_and_batch_bundle(row, entries, key) { + frappe.call({ + method: "erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.add_serial_batch_ledgers", + args: { + entries: entries[key], + child_row: row, + doc: this.frm.doc, + warehouse: row.warehouse, + do_not_save: 1 + }, + callback: function(r) { + row.serial_and_batch_bundle = r.message.name; + delete entries[key]; + } + }) + } + async set_barcode_uom(row, uom) { if (uom && frappe.meta.has_field(row.doctype, this.uom_field)) { await frappe.model.set_value(row.doctype, row.name, this.uom_field, uom); } } - async set_batch_no(row, batch_no) { - if (batch_no && frappe.meta.has_field(row.doctype, this.batch_no_field)) { - await frappe.model.set_value(row.doctype, row.name, this.batch_no_field, batch_no); - } - } - async set_barcode(row, barcode) { if (barcode && frappe.meta.has_field(row.doctype, this.barcode_field)) { await frappe.model.set_value(row.doctype, row.name, this.barcode_field, barcode); @@ -379,13 +475,52 @@ erpnext.utils.BarcodeScanner = class BarcodeScanner { } } - is_duplicate_serial_no(row, serial_no) { - const is_duplicate = row[this.serial_no_field]?.includes(serial_no); + is_duplicate_serial_no(row, item_code, serial_no) { + if (this.frm.is_new() || !row.serial_and_batch_bundle) { + let is_duplicate = this.check_duplicate_serial_no_in_localstorage(item_code, serial_no); + if (is_duplicate) { + this.show_alert(__("Serial No {0} is already added", [serial_no]), "orange"); + } - if (is_duplicate) { - this.show_alert(__("Serial No {0} is already added", [serial_no]), "orange"); + return is_duplicate; + } else if (row.serial_and_batch_bundle) { + this.check_duplicate_serial_no_in_db(row, serial_no, (r) => { + if (r.message) { + this.show_alert(__("Serial No {0} is already added", [serial_no]), "orange"); + } + + return r.message; + }) } - return is_duplicate; + } + + async check_duplicate_serial_no_in_db(row, serial_no, response) { + frappe.call({ + method: "erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle.is_duplicate_serial_no", + args: { + serial_no: serial_no, + bundle_id: row.serial_and_batch_bundle + }, + callback(r) { + response(r); + } + }) + } + + check_duplicate_serial_no_in_localstorage(item_code, serial_no) { + let docname = this.frm.doc.name + let entries = JSON.parse(localStorage.getItem(docname)); + + if (!entries) { + return false; + } + + let existing_row = []; + if (entries[item_code]) { + existing_row = entries[item_code].filter((e) => e.serial_no === serial_no); + } + + return existing_row.length; } get_row_to_modify_on_scan(item_code, batch_no, uom, barcode) { diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index 218406f56f..eede928827 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -729,19 +729,13 @@ class SerialandBatchBundle(Document): def before_cancel(self): self.delink_serial_and_batch_bundle() - self.clear_table() def delink_serial_and_batch_bundle(self): - self.voucher_no = None - sles = frappe.get_all("Stock Ledger Entry", filters={"serial_and_batch_bundle": self.name}) for sle in sles: frappe.db.set_value("Stock Ledger Entry", sle.name, "serial_and_batch_bundle", None) - def clear_table(self): - self.set("entries", []) - @property def child_table(self): if self.voucher_type == "Job Card": @@ -876,7 +870,6 @@ class SerialandBatchBundle(Document): self.validate_voucher_no_docstatus() self.delink_refernce_from_voucher() self.delink_reference_from_batch() - self.clear_table() @frappe.whitelist() def add_serial_batch(self, data): @@ -1156,7 +1149,7 @@ def get_filters_for_bundle(item_code=None, docstatus=None, voucher_no=None, name @frappe.whitelist() -def add_serial_batch_ledgers(entries, child_row, doc, warehouse) -> object: +def add_serial_batch_ledgers(entries, child_row, doc, warehouse, do_not_save=False) -> object: if isinstance(child_row, str): child_row = frappe._dict(parse_json(child_row)) @@ -1170,20 +1163,23 @@ def add_serial_batch_ledgers(entries, child_row, doc, warehouse) -> object: if frappe.db.exists("Serial and Batch Bundle", child_row.serial_and_batch_bundle): sb_doc = update_serial_batch_no_ledgers(entries, child_row, parent_doc, warehouse) else: - sb_doc = create_serial_batch_no_ledgers(entries, child_row, parent_doc, warehouse) + sb_doc = create_serial_batch_no_ledgers( + entries, child_row, parent_doc, warehouse, do_not_save=do_not_save + ) return sb_doc -def create_serial_batch_no_ledgers(entries, child_row, parent_doc, warehouse=None) -> object: +def create_serial_batch_no_ledgers( + entries, child_row, parent_doc, warehouse=None, do_not_save=False +) -> object: warehouse = warehouse or ( child_row.rejected_warehouse if child_row.is_rejected else child_row.warehouse ) - type_of_transaction = child_row.type_of_transaction + type_of_transaction = get_type_of_transaction(parent_doc, child_row) if parent_doc.get("doctype") == "Stock Entry": - type_of_transaction = "Outward" if child_row.s_warehouse else "Inward" warehouse = warehouse or child_row.s_warehouse or child_row.t_warehouse doc = frappe.get_doc( @@ -1214,13 +1210,30 @@ def create_serial_batch_no_ledgers(entries, child_row, parent_doc, warehouse=Non doc.save() - frappe.db.set_value(child_row.doctype, child_row.name, "serial_and_batch_bundle", doc.name) + if do_not_save: + frappe.db.set_value(child_row.doctype, child_row.name, "serial_and_batch_bundle", doc.name) frappe.msgprint(_("Serial and Batch Bundle created"), alert=True) return doc +def get_type_of_transaction(parent_doc, child_row): + type_of_transaction = child_row.type_of_transaction + if parent_doc.get("doctype") == "Stock Entry": + type_of_transaction = "Outward" if child_row.s_warehouse else "Inward" + + if not type_of_transaction: + type_of_transaction = "Outward" + if parent_doc.get("doctype") in ["Purchase Receipt", "Purchase Invoice"]: + type_of_transaction = "Inward" + + if parent_doc.get("is_return"): + type_of_transaction = "Inward" if type_of_transaction == "Outward" else "Outward" + + return type_of_transaction + + def update_serial_batch_no_ledgers(entries, child_row, parent_doc, warehouse=None) -> object: doc = frappe.get_doc("Serial and Batch Bundle", child_row.serial_and_batch_bundle) doc.voucher_detail_no = child_row.name @@ -1247,6 +1260,25 @@ def update_serial_batch_no_ledgers(entries, child_row, parent_doc, warehouse=Non return doc +@frappe.whitelist() +def update_serial_or_batch(bundle_id, serial_no=None, batch_no=None): + if batch_no and not serial_no: + if qty := frappe.db.get_value( + "Serial and Batch Entry", {"parent": bundle_id, "batch_no": batch_no}, "qty" + ): + frappe.db.set_value( + "Serial and Batch Entry", {"parent": bundle_id, "batch_no": batch_no}, "qty", qty + 1 + ) + return + + doc = frappe.get_cached_doc("Serial and Batch Bundle", bundle_id) + if not serial_no and not batch_no: + return + + doc.append("entries", {"serial_no": serial_no, "batch_no": batch_no, "qty": 1}) + doc.save(ignore_permissions=True) + + def get_serial_and_batch_ledger(**kwargs): kwargs = frappe._dict(kwargs) @@ -2032,3 +2064,8 @@ def get_stock_ledgers_batches(kwargs): @frappe.whitelist() def get_batch_no_from_serial_no(serial_no): return frappe.get_cached_value("Serial No", serial_no, "batch_no") + + +@frappe.whitelist() +def is_duplicate_serial_no(bundle_id, serial_no): + return frappe.db.exists("Serial and Batch Entry", {"parent": bundle_id, "serial_no": serial_no}) diff --git a/erpnext/stock/serial_batch_bundle.py b/erpnext/stock/serial_batch_bundle.py index 39df2279cd..4cfe5d817e 100644 --- a/erpnext/stock/serial_batch_bundle.py +++ b/erpnext/stock/serial_batch_bundle.py @@ -209,7 +209,7 @@ class SerialBatchBundle: frappe.db.set_value( "Serial and Batch Bundle", {"voucher_no": self.sle.voucher_no, "voucher_type": self.sle.voucher_type}, - {"is_cancelled": 1, "voucher_no": ""}, + {"is_cancelled": 1}, ) if self.sle.serial_and_batch_bundle: diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py index bd0d4697c9..4b0e2845c4 100644 --- a/erpnext/stock/utils.py +++ b/erpnext/stock/utils.py @@ -591,6 +591,13 @@ def scan_barcode(search_value: str) -> BarcodeScanResult: as_dict=True, ) if batch_no_data: + if frappe.get_cached_value("Item", batch_no_data.item_code, "has_serial_no"): + frappe.throw( + _( + "Batch No {0} is linked with Item {1} which has serial no. Please scan serial no instead." + ).format(search_value, batch_no_data.item_code) + ) + _update_item_info(batch_no_data) set_cache(batch_no_data) return batch_no_data From cdd5441435ee448d3efb2155a93865ec29bbf8ab Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Thu, 4 Jan 2024 15:15:55 +0530 Subject: [PATCH 170/205] fix(text): test_update_status --- .../subcontracting_order/subcontracting_order.js | 2 +- .../subcontracting_order/subcontracting_order.py | 5 ----- .../test_subcontracting_order.py | 13 ++++++------- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js index ae9a3252ef..4c8a0ad60e 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js +++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js @@ -101,7 +101,7 @@ frappe.ui.form.on('Subcontracting Order', { }, refresh: function (frm) { - if (frm.has_perm("submit")) { + if (frm.doc.docstatus == 1 && frm.has_perm("submit")) { if (frm.doc.status == "Closed") { frm.add_custom_button(__('Re-open'), () => frm.events.update_subcontracting_order_status(frm), __("Status")); } else if(flt(frm.doc.per_received, 2) < 100) { diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py index 309e4fe643..daccbbbd0f 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py +++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py @@ -283,11 +283,6 @@ class SubcontractingOrder(SubcontractingController): status = "Completed" elif self.per_received > 0 and self.per_received < 100: status = "Partially Received" - for item in self.supplied_items: - if not item.returned_qty or (item.supplied_qty - item.consumed_qty - item.returned_qty) > 0: - break - else: - status = "Closed" else: total_required_qty = total_supplied_qty = 0 for item in self.supplied_items: diff --git a/erpnext/subcontracting/doctype/subcontracting_order/test_subcontracting_order.py b/erpnext/subcontracting/doctype/subcontracting_order/test_subcontracting_order.py index 37dabf1bfb..6c0ee45d9c 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/test_subcontracting_order.py +++ b/erpnext/subcontracting/doctype/subcontracting_order/test_subcontracting_order.py @@ -95,14 +95,14 @@ class TestSubcontractingOrder(FrappeTestCase): self.assertEqual(sco.status, "Partially Received") # Closed - ste = get_materials_from_supplier(sco.name, [d.name for d in sco.supplied_items]) - ste.save() - ste.submit() - sco.load_from_db() + sco.update_status("Closed") self.assertEqual(sco.status, "Closed") - ste.cancel() - sco.load_from_db() + scr = make_subcontracting_receipt(sco.name) + scr.save() + self.assertRaises(frappe.exceptions.ValidationError, scr.submit) + sco.update_status() self.assertEqual(sco.status, "Partially Received") + scr.cancel() # Completed scr = make_subcontracting_receipt(sco.name) @@ -564,7 +564,6 @@ class TestSubcontractingOrder(FrappeTestCase): sco.load_from_db() - self.assertEqual(sco.status, "Closed") self.assertEqual(sco.supplied_items[0].returned_qty, 5) def test_ordered_qty_for_subcontracting_order(self): From e912e9597dbd83724afbcd00f3b2acd75b50a8f0 Mon Sep 17 00:00:00 2001 From: Raffael Meyer <14891507+barredterra@users.noreply.github.com> Date: Thu, 4 Jan 2024 13:33:28 +0100 Subject: [PATCH 171/205] fix(Employee): treeview (#39126) --- erpnext/setup/doctype/employee/employee.json | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/erpnext/setup/doctype/employee/employee.json b/erpnext/setup/doctype/employee/employee.json index 1143ccb7b1..daf2df5a59 100644 --- a/erpnext/setup/doctype/employee/employee.json +++ b/erpnext/setup/doctype/employee/employee.json @@ -616,8 +616,8 @@ "fieldname": "relieving_date", "fieldtype": "Date", "label": "Relieving Date", - "no_copy": 1, "mandatory_depends_on": "eval:doc.status == \"Left\"", + "no_copy": 1, "oldfieldname": "relieving_date", "oldfieldtype": "Date" }, @@ -822,12 +822,14 @@ "icon": "fa fa-user", "idx": 24, "image_field": "image", + "is_tree": 1, "links": [], - "modified": "2023-10-04 10:57:05.174592", + "modified": "2024-01-03 17:36:20.984421", "modified_by": "Administrator", "module": "Setup", "name": "Employee", "naming_rule": "By \"Naming Series\" field", + "nsm_parent_field": "reports_to", "owner": "Administrator", "permissions": [ { @@ -860,7 +862,6 @@ "read": 1, "report": 1, "role": "HR Manager", - "set_user_permissions": 1, "share": 1, "write": 1 } @@ -871,4 +872,4 @@ "sort_order": "DESC", "states": [], "title_field": "employee_name" -} +} \ No newline at end of file From 68c0e188e8a8e6adcce629ce9abc407fe4ae3a86 Mon Sep 17 00:00:00 2001 From: Raffael Meyer <14891507+barredterra@users.noreply.github.com> Date: Thu, 4 Jan 2024 13:42:41 +0100 Subject: [PATCH 172/205] fix: remove `parent_field` parameter from calls to `rebuild_tree` (#39146) fix: remove parent_field parameter from calls to rebuild_tree The parent_field parameter became redundant with https://github.com/frappe/frappe/pull/24107 --- .../doctype/account/chart_of_accounts/chart_of_accounts.py | 2 +- .../v11_0/create_department_records_for_each_company.py | 2 +- erpnext/patches/v11_0/make_location_from_warehouse.py | 2 +- erpnext/patches/v11_0/rebuild_tree_for_company.py | 2 +- .../patches/v11_0/rename_supplier_type_to_supplier_group.py | 2 +- erpnext/patches/v11_0/update_department_lft_rgt.py | 2 +- erpnext/setup/doctype/company/company.py | 4 ++-- erpnext/setup/doctype/item_group/test_item_group.py | 2 +- erpnext/stock/__init__.py | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py b/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py index 9e67c4cf0d..9f56455990 100644 --- a/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py +++ b/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py @@ -74,7 +74,7 @@ def create_charts( # after all accounts are already inserted. frappe.local.flags.ignore_update_nsm = True _import_accounts(chart, None, None, root_account=True) - rebuild_tree("Account", "parent_account") + rebuild_tree("Account") frappe.local.flags.ignore_update_nsm = False diff --git a/erpnext/patches/v11_0/create_department_records_for_each_company.py b/erpnext/patches/v11_0/create_department_records_for_each_company.py index 84be2bee9d..7a0641d7c8 100644 --- a/erpnext/patches/v11_0/create_department_records_for_each_company.py +++ b/erpnext/patches/v11_0/create_department_records_for_each_company.py @@ -35,7 +35,7 @@ def execute(): # append list of new department for each company comp_dict[company.name][department.name] = copy_doc.name - rebuild_tree("Department", "parent_department") + rebuild_tree("Department") doctypes = ["Asset", "Employee", "Payroll Entry", "Staffing Plan", "Job Opening"] for d in doctypes: diff --git a/erpnext/patches/v11_0/make_location_from_warehouse.py b/erpnext/patches/v11_0/make_location_from_warehouse.py index c863bb7ecf..8d9c8d8ef6 100644 --- a/erpnext/patches/v11_0/make_location_from_warehouse.py +++ b/erpnext/patches/v11_0/make_location_from_warehouse.py @@ -27,7 +27,7 @@ def execute(): except frappe.DuplicateEntryError: continue - rebuild_tree("Location", "parent_location") + rebuild_tree("Location") def get_parent_warehouse_name(warehouse): diff --git a/erpnext/patches/v11_0/rebuild_tree_for_company.py b/erpnext/patches/v11_0/rebuild_tree_for_company.py index fc06c5d30d..a9b23445e9 100644 --- a/erpnext/patches/v11_0/rebuild_tree_for_company.py +++ b/erpnext/patches/v11_0/rebuild_tree_for_company.py @@ -4,4 +4,4 @@ from frappe.utils.nestedset import rebuild_tree def execute(): frappe.reload_doc("setup", "doctype", "company") - rebuild_tree("Company", "parent_company") + rebuild_tree("Company") diff --git a/erpnext/patches/v11_0/rename_supplier_type_to_supplier_group.py b/erpnext/patches/v11_0/rename_supplier_type_to_supplier_group.py index 96daba7d36..67eb915902 100644 --- a/erpnext/patches/v11_0/rename_supplier_type_to_supplier_group.py +++ b/erpnext/patches/v11_0/rename_supplier_type_to_supplier_group.py @@ -41,4 +41,4 @@ def build_tree(): } ).insert(ignore_permissions=True) - rebuild_tree("Supplier Group", "parent_supplier_group") + rebuild_tree("Supplier Group") diff --git a/erpnext/patches/v11_0/update_department_lft_rgt.py b/erpnext/patches/v11_0/update_department_lft_rgt.py index 778392ec5f..380ca4d47a 100644 --- a/erpnext/patches/v11_0/update_department_lft_rgt.py +++ b/erpnext/patches/v11_0/update_department_lft_rgt.py @@ -18,4 +18,4 @@ def execute(): ) ) - rebuild_tree("Department", "parent_department") + rebuild_tree("Department") diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index 9897847896..ec953b885e 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -249,7 +249,7 @@ class Company(NestedSet): if frappe.flags.parent_company_changed: from frappe.utils.nestedset import rebuild_tree - rebuild_tree("Company", "parent_company") + rebuild_tree("Company") frappe.clear_cache() @@ -397,7 +397,7 @@ class Company(NestedSet): frappe.local.flags.ignore_update_nsm = True make_records(records) frappe.local.flags.ignore_update_nsm = False - rebuild_tree("Department", "parent_department") + rebuild_tree("Department") def validate_coa_input(self): if self.create_chart_of_accounts_based_on == "Existing Company": diff --git a/erpnext/setup/doctype/item_group/test_item_group.py b/erpnext/setup/doctype/item_group/test_item_group.py index 11bc9b92c1..d95199d151 100644 --- a/erpnext/setup/doctype/item_group/test_item_group.py +++ b/erpnext/setup/doctype/item_group/test_item_group.py @@ -79,7 +79,7 @@ class TestItem(unittest.TestCase): group_b.save() def test_rebuild_tree(self): - rebuild_tree("Item Group", "parent_item_group") + rebuild_tree("Item Group") self.test_basic_tree() def move_it_back(self): diff --git a/erpnext/stock/__init__.py b/erpnext/stock/__init__.py index 45bf012be8..bd16d69df7 100644 --- a/erpnext/stock/__init__.py +++ b/erpnext/stock/__init__.py @@ -59,7 +59,7 @@ def get_warehouse_account(warehouse, warehouse_account=None): else: from frappe.utils.nestedset import rebuild_tree - rebuild_tree("Warehouse", "parent_warehouse") + rebuild_tree("Warehouse") else: account = frappe.db.sql( """ From bae7c6496402466df3af15c6bffcf51b97ae2037 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Thu, 4 Jan 2024 18:47:06 +0530 Subject: [PATCH 173/205] fix: inventory dimension negative stock validation (#39149) --- .../inventory_dimension/inventory_dimension.py | 2 +- .../test_inventory_dimension.py | 8 ++++++++ .../stock_ledger_entry/stock_ledger_entry.py | 14 +++++++++----- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py b/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py index 60624d4164..d5eef5ad22 100644 --- a/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py +++ b/erpnext/stock/doctype/inventory_dimension/inventory_dimension.py @@ -305,7 +305,7 @@ def get_evaluated_inventory_dimension(doc, sl_dict, parent_doc=None): dimensions = get_document_wise_inventory_dimensions(doc.doctype) filter_dimensions = [] for row in dimensions: - if row.type_of_transaction: + if row.type_of_transaction and row.type_of_transaction != "Both": if ( row.type_of_transaction == "Inward" if doc.docstatus == 1 diff --git a/erpnext/stock/doctype/inventory_dimension/test_inventory_dimension.py b/erpnext/stock/doctype/inventory_dimension/test_inventory_dimension.py index 33394e5a11..361c2f8cd9 100644 --- a/erpnext/stock/doctype/inventory_dimension/test_inventory_dimension.py +++ b/erpnext/stock/doctype/inventory_dimension/test_inventory_dimension.py @@ -429,6 +429,14 @@ class TestInventoryDimension(FrappeTestCase): ) warehouse = create_warehouse("Negative Stock Warehouse") + + doc = make_stock_entry(item_code=item_code, source=warehouse, qty=10, do_not_submit=True) + doc.items[0].inv_site = "Site 1" + self.assertRaises(frappe.ValidationError, doc.submit) + doc.reload() + if doc.docstatus == 1: + doc.cancel() + doc = make_stock_entry(item_code=item_code, target=warehouse, qty=10, do_not_submit=True) doc.items[0].to_inv_site = "Site 1" diff --git a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py index 6e7af6815f..277ca01320 100644 --- a/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py +++ b/erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py @@ -111,16 +111,20 @@ class StockLedgerEntry(Document): "posting_date": self.posting_date, "posting_time": self.posting_time, "company": self.company, + "sle": self.name, } ) sle = get_previous_sle(kwargs, extra_cond=extra_cond) + qty_after_transaction = 0.0 + flt_precision = cint(frappe.db.get_default("float_precision")) or 2 if sle: - flt_precision = cint(frappe.db.get_default("float_precision")) or 2 - diff = sle.qty_after_transaction + flt(self.actual_qty) - diff = flt(diff, flt_precision) - if diff < 0 and abs(diff) > 0.0001: - self.throw_validation_error(diff, dimensions) + qty_after_transaction = sle.qty_after_transaction + + diff = qty_after_transaction + flt(self.actual_qty) + diff = flt(diff, flt_precision) + if diff < 0 and abs(diff) > 0.0001: + self.throw_validation_error(diff, dimensions) def throw_validation_error(self, diff, dimensions): dimension_msg = _(", with the inventory {0}: {1}").format( From 3fb78864184135c67e290599f5c5a257744ec2f2 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Fri, 5 Jan 2024 10:50:49 +0530 Subject: [PATCH 174/205] fix: Creating Asset Activity while Importing Asset (backport #39113) (#39156) fix: Creating Asset Activity while Importing Asset (#39113) * fix: import asset not working on activity * chore: fix linting issue in asset_activity.py --------- Co-authored-by: Anand Baburajan (cherry picked from commit 5e4693763ae7f8dde2013093d926d6abd39fd174) Co-authored-by: Aulia Bismar --- erpnext/assets/doctype/asset_activity/asset_activity.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/assets/doctype/asset_activity/asset_activity.py b/erpnext/assets/doctype/asset_activity/asset_activity.py index a64cb1aba3..7177223b4f 100644 --- a/erpnext/assets/doctype/asset_activity/asset_activity.py +++ b/erpnext/assets/doctype/asset_activity/asset_activity.py @@ -3,6 +3,7 @@ import frappe from frappe.model.document import Document +from frappe.utils import now_datetime class AssetActivity(Document): @@ -30,5 +31,6 @@ def add_asset_activity(asset, subject): "asset": asset, "subject": subject, "user": frappe.session.user, + "date": now_datetime(), } ).insert(ignore_permissions=True, ignore_links=True) From e05bf9d32a00aac55021faaacbfa914ee9f7275a Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Fri, 5 Jan 2024 15:35:14 +0530 Subject: [PATCH 175/205] fix: add read permission to Buying Settings --- .../buying_settings/buying_settings.json | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.json b/erpnext/buying/doctype/buying_settings/buying_settings.json index 3f8559e63f..b05de7d0b2 100644 --- a/erpnext/buying/doctype/buying_settings/buying_settings.json +++ b/erpnext/buying/doctype/buying_settings/buying_settings.json @@ -214,7 +214,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-11-28 13:01:18.403492", + "modified": "2024-01-05 15:26:02.320942", "modified_by": "Administrator", "module": "Buying", "name": "Buying Settings", @@ -238,6 +238,41 @@ "role": "Purchase Manager", "share": 1, "write": 1 + }, + { + "email": 1, + "print": 1, + "read": 1, + "role": "Accounts User", + "share": 1 + }, + { + "email": 1, + "print": 1, + "read": 1, + "role": "Accounts Manager", + "share": 1 + }, + { + "email": 1, + "print": 1, + "read": 1, + "role": "Stock Manager", + "share": 1 + }, + { + "email": 1, + "print": 1, + "read": 1, + "role": "Stock User", + "share": 1 + }, + { + "email": 1, + "print": 1, + "read": 1, + "role": "Purchase User", + "share": 1 } ], "sort_field": "modified", From 15dc5c7e9966e3bf06ec0aa951d7185fb6cf6d0e Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 5 Jan 2024 14:32:05 +0530 Subject: [PATCH 176/205] refactor: prevent permissions by always processing in background --- erpnext/utilities/bulk_transaction.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/erpnext/utilities/bulk_transaction.py b/erpnext/utilities/bulk_transaction.py index 679d5bd348..9678488a26 100644 --- a/erpnext/utilities/bulk_transaction.py +++ b/erpnext/utilities/bulk_transaction.py @@ -15,18 +15,15 @@ def transaction_processing(data, from_doctype, to_doctype): length_of_data = len(deserialized_data) - if length_of_data > 10: - frappe.msgprint( - _("Started a background job to create {1} {0}").format(to_doctype, length_of_data) - ) - frappe.enqueue( - job, - deserialized_data=deserialized_data, - from_doctype=from_doctype, - to_doctype=to_doctype, - ) - else: - job(deserialized_data, from_doctype, to_doctype) + frappe.msgprint( + _("Started a background job to create {1} {0}").format(to_doctype, length_of_data) + ) + frappe.enqueue( + job, + deserialized_data=deserialized_data, + from_doctype=from_doctype, + to_doctype=to_doctype, + ) @frappe.whitelist() From b69cdeb4a6c881642fd2e3a081f13b65191d44bc Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 5 Jan 2024 15:56:04 +0530 Subject: [PATCH 177/205] refactor: allow sales invoice in Bank Reconciliation tool --- .../bank_transaction/bank_transaction.py | 18 ++++++++++-------- erpnext/hooks.py | 1 + 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py index 629ed1cf75..57f7c0eca3 100644 --- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py +++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py @@ -366,15 +366,17 @@ def set_voucher_clearance(doctype, docname, clearance_date, self): and len(get_reconciled_bank_transactions(doctype, docname)) < 2 ): return - frappe.db.set_value(doctype, docname, "clearance_date", clearance_date) - elif doctype == "Sales Invoice": - frappe.db.set_value( - "Sales Invoice Payment", - dict(parenttype=doctype, parent=docname), - "clearance_date", - clearance_date, - ) + if doctype == "Sales Invoice": + frappe.db.set_value( + "Sales Invoice Payment", + dict(parenttype=doctype, parent=docname), + "clearance_date", + clearance_date, + ) + return + + frappe.db.set_value(doctype, docname, "clearance_date", clearance_date) elif doctype == "Bank Transaction": # For when a second bank transaction has fixed another, e.g. refund diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 0f80d5ee88..6efb893e63 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -489,6 +489,7 @@ bank_reconciliation_doctypes = [ "Payment Entry", "Journal Entry", "Purchase Invoice", + "Sales Invoice", ] accounting_dimension_doctypes = [ From fe43dab4d78091e626ddfb6432b2d69f84793d92 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 5 Jan 2024 17:12:08 +0530 Subject: [PATCH 178/205] fix: improved validation message --- erpnext/assets/doctype/asset_category/asset_category.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/assets/doctype/asset_category/asset_category.py b/erpnext/assets/doctype/asset_category/asset_category.py index 034ec555dc..d401b81c2e 100644 --- a/erpnext/assets/doctype/asset_category/asset_category.py +++ b/erpnext/assets/doctype/asset_category/asset_category.py @@ -86,12 +86,12 @@ class AssetCategory(Document): if selected_key_type not in expected_key_types: frappe.throw( _( - "Row #{}: {} of {} should be {}. Please modify the account or select a different account." + "Row #{0}: {1} of {2} should be {3}. Please update the {1} or select a different account." ).format( d.idx, frappe.unscrub(key_to_match), frappe.bold(selected_account), - frappe.bold(expected_key_types), + frappe.bold(" or ".join(expected_key_types)), ), title=_("Invalid Account"), ) From c34f09c503b367f6ea1eee5e24f8aa6e94976e01 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 5 Jan 2024 17:38:51 +0530 Subject: [PATCH 179/205] fix: Purchase date and amount is not mandatory for composite asset creation --- erpnext/assets/doctype/asset/asset.json | 12 ++++++------ erpnext/assets/doctype/asset/asset.py | 13 +++++++++---- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.json b/erpnext/assets/doctype/asset/asset.json index ac712d4431..d0c9350d77 100644 --- a/erpnext/assets/doctype/asset/asset.json +++ b/erpnext/assets/doctype/asset/asset.json @@ -202,9 +202,9 @@ "fieldname": "purchase_date", "fieldtype": "Date", "label": "Purchase Date", + "mandatory_depends_on": "eval:!doc.is_existing_asset", "read_only": 1, - "read_only_depends_on": "eval:!doc.is_existing_asset && !doc.is_composite_asset", - "reqd": 1 + "read_only_depends_on": "eval:!doc.is_existing_asset && !doc.is_composite_asset" }, { "fieldname": "disposal_date", @@ -227,15 +227,15 @@ "fieldname": "gross_purchase_amount", "fieldtype": "Currency", "label": "Gross Purchase Amount", + "mandatory_depends_on": "eval:(!doc.is_composite_asset || doc.docstatus==1)", "options": "Company:company:default_currency", - "read_only_depends_on": "eval:!doc.is_existing_asset", - "reqd": 1 + "read_only_depends_on": "eval:!doc.is_existing_asset" }, { "fieldname": "available_for_use_date", "fieldtype": "Date", "label": "Available-for-use Date", - "reqd": 1 + "mandatory_depends_on": "eval:(!doc.is_composite_asset || doc.docstatus==1)" }, { "default": "0", @@ -590,7 +590,7 @@ "link_fieldname": "target_asset" } ], - "modified": "2023-12-21 16:46:20.732869", + "modified": "2024-01-05 17:36:53.131512", "modified_by": "Administrator", "module": "Assets", "name": "Asset", diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index dd34189391..5f448987a5 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -57,7 +57,7 @@ class Asset(AccountsController): asset_owner: DF.Literal["", "Company", "Supplier", "Customer"] asset_owner_company: DF.Link | None asset_quantity: DF.Int - available_for_use_date: DF.Date + available_for_use_date: DF.Date | None booked_fixed_asset: DF.Check calculate_depreciation: DF.Check capitalized_in: DF.Link | None @@ -92,7 +92,7 @@ class Asset(AccountsController): number_of_depreciations_booked: DF.Int opening_accumulated_depreciation: DF.Currency policy_number: DF.Data | None - purchase_date: DF.Date + purchase_date: DF.Date | None purchase_invoice: DF.Link | None purchase_receipt: DF.Link | None purchase_receipt_amount: DF.Currency @@ -316,7 +316,12 @@ class Asset(AccountsController): frappe.throw(_("Gross Purchase Amount is mandatory"), frappe.MandatoryError) if is_cwip_accounting_enabled(self.asset_category): - if not self.is_existing_asset and not self.purchase_receipt and not self.purchase_invoice: + if ( + not self.is_existing_asset + and not self.is_composite_asset + and not self.purchase_receipt + and not self.purchase_invoice + ): frappe.throw( _("Please create purchase receipt or purchase invoice for the item {0}").format( self.item_code @@ -329,7 +334,7 @@ class Asset(AccountsController): and not frappe.db.get_value("Purchase Invoice", self.purchase_invoice, "update_stock") ): frappe.throw( - _("Update stock must be enable for the purchase invoice {0}").format(self.purchase_invoice) + _("Update stock must be enabled for the purchase invoice {0}").format(self.purchase_invoice) ) if not self.calculate_depreciation: From 4d56f725fe23495fa2392be01545c5d2fa8889b3 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Fri, 5 Jan 2024 18:44:06 +0530 Subject: [PATCH 180/205] fix: make `Sales Person` non-mandatory --- .../doctype/maintenance_schedule/maintenance_schedule.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py index 6100756a6a..19f57223b1 100644 --- a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py +++ b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py @@ -117,7 +117,7 @@ class MaintenanceSchedule(TransactionBase): self.update_amc_date(serial_nos, d.end_date) no_email_sp = [] - if d.sales_person not in email_map: + if d.sales_person and d.sales_person not in email_map: sp = frappe.get_doc("Sales Person", d.sales_person) try: email_map[d.sales_person] = sp.get_email_id() @@ -133,9 +133,9 @@ class MaintenanceSchedule(TransactionBase): scheduled_date = frappe.db.sql( """select scheduled_date from - `tabMaintenance Schedule Detail` where sales_person=%s and item_code=%s and + `tabMaintenance Schedule Detail` where item_code=%s and parent=%s""", - (d.sales_person, d.item_code, self.name), + (d.item_code, self.name), as_dict=1, ) @@ -232,8 +232,6 @@ class MaintenanceSchedule(TransactionBase): throw(_("Please select Start Date and End Date for Item {0}").format(d.item_code)) elif not d.no_of_visits: throw(_("Please mention no of visits required")) - elif not d.sales_person: - throw(_("Please select a Sales Person for item: {0}").format(d.item_name)) if getdate(d.start_date) >= getdate(d.end_date): throw(_("Start date should be less than end date for Item {0}").format(d.item_code)) From 4cc3c1b76529b99e1f0ed2594c0edc3152cc6534 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 5 Jan 2024 20:42:38 +0530 Subject: [PATCH 181/205] fix: incorrect outstanding amt validation on advance as liability --- erpnext/accounts/doctype/payment_entry/payment_entry.js | 4 ++++ erpnext/accounts/doctype/payment_entry/payment_entry.py | 8 +++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.js b/erpnext/accounts/doctype/payment_entry/payment_entry.js index 26112409b7..81ffee3f6e 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.js +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.js @@ -747,6 +747,10 @@ frappe.ui.form.on('Payment Entry', { args["get_orders_to_be_billed"] = true; } + if (frm.doc.book_advance_payments_in_separate_party_account) { + args["book_advance_payments_in_separate_party_account"] = true; + } + frappe.flags.allocate_payment_amount = filters['allocate_payment_amount']; return frappe.call({ diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 11c7c179b6..052eff393e 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -256,6 +256,7 @@ class PaymentEntry(AccountsController): "get_outstanding_invoices": True, "get_orders_to_be_billed": True, "vouchers": vouchers, + "book_advance_payments_in_separate_party_account": self.book_advance_payments_in_separate_party_account, }, validate=True, ) @@ -1628,11 +1629,16 @@ def get_outstanding_reference_documents(args, validate=False): outstanding_invoices = [] negative_outstanding_invoices = [] + if args.get("book_advance_payments_in_separate_party_account"): + party_account = get_party_account(args.get("party_type"), args.get("party"), args.get("company")) + else: + party_account = args.get("party_account") + if args.get("get_outstanding_invoices"): outstanding_invoices = get_outstanding_invoices( args.get("party_type"), args.get("party"), - get_party_account(args.get("party_type"), args.get("party"), args.get("company")), + party_account, common_filter=common_filter, posting_date=posting_and_due_date, min_outstanding=args.get("outstanding_amt_greater_than"), From 07b605a2873f796ef576f21bc30748c78b32a34e Mon Sep 17 00:00:00 2001 From: Raffael Meyer <14891507+barredterra@users.noreply.github.com> Date: Fri, 5 Jan 2024 19:03:42 +0100 Subject: [PATCH 182/205] fix: make Dr/Cr in CoA translatable (#39033) * fix: make Dr/Cr in CoA translatable * fix: german translations --- erpnext/accounts/doctype/account/account_tree.js | 2 +- erpnext/translations/de.csv | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/account/account_tree.js b/erpnext/accounts/doctype/account/account_tree.js index f240aa6e95..0b29769293 100644 --- a/erpnext/accounts/doctype/account/account_tree.js +++ b/erpnext/accounts/doctype/account/account_tree.js @@ -77,7 +77,7 @@ frappe.treeview_settings["Account"] = { // show Dr if positive since balance is calculated as debit - credit else show Cr const balance = account.balance_in_account_currency || account.balance; - const dr_or_cr = balance > 0 ? "Dr": "Cr"; + const dr_or_cr = balance > 0 ? __("Dr"): __("Cr"); const format = (value, currency) => format_currency(Math.abs(value), currency); if (account.balance!==undefined) { diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv index d05d0d96c3..84c71ba367 100644 --- a/erpnext/translations/de.csv +++ b/erpnext/translations/de.csv @@ -600,7 +600,7 @@ Course Code: ,Kurscode:, Course Enrollment {0} does not exists,Die Kursanmeldung {0} existiert nicht, Course Schedule,Kurstermine, Course: ,Kurs:, -Cr,Haben, +Cr,H, Create,Erstellen, Create BOM,Stückliste anlegen, Create Delivery Trip,Erstelle Auslieferungsfahrt, @@ -3401,7 +3401,7 @@ Do you want to submit the material request,Möchten Sie die Materialanfrage einr Doctype,DocType, Document {0} successfully uncleared,Dokument {0} wurde nicht erfolgreich gelöscht, Download Template,Vorlage herunterladen, -Dr,Soll, +Dr,S, Due Date,Fälligkeitsdatum, Duplicate,Duplizieren, Duplicate Project with Tasks,Projekt mit Aufgaben duplizieren, @@ -7370,6 +7370,7 @@ Default Stock UOM,Standardlagermaßeinheit, Sample Retention Warehouse,Beispiel Retention Warehouse, Default Valuation Method,Standard-Bewertungsmethode, Show Barcode Field,Anzeigen Barcode-Feld, +Show Balances in Chart Of Accounts,Saldo in Kontenplan anzeigen, Convert Item Description to Clean HTML,Elementbeschreibung in HTML bereinigen, Allow Negative Stock,Negativen Lagerbestand zulassen, Automatically Set Serial Nos based on FIFO,Automatisch Seriennummern auf Basis FIFO einstellen, @@ -8812,7 +8813,6 @@ Column {0},Spalte {0}, Field Mapping,Feldzuordnung, Not Specified,Keine Angabe, Update Type,Aktualisierungsart, -Dr,Soll, End Time,Endzeit, Fetching...,Abrufen ..., "It seems that there is an issue with the server's stripe configuration. In case of failure, the amount will get refunded to your account.","Es scheint, dass ein Problem mit der Stripe-Konfiguration des Servers vorliegt. Im Falle eines Fehlers wird der Betrag Ihrem Konto gutgeschrieben.", From cd293a5173aaec693afee23e9b874b1db649a267 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Fri, 5 Jan 2024 22:58:04 +0530 Subject: [PATCH 183/205] fix: update Maintenance Schedule status on Maintenance Visit submit --- .../maintenance_schedule.py | 46 +++++++++------ .../maintenance_visit/maintenance_visit.py | 59 +++++++++++++++---- .../maintenance_visit_purpose.json | 15 ++++- .../maintenance_visit_purpose.py | 3 +- 4 files changed, 89 insertions(+), 34 deletions(-) diff --git a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py index 19f57223b1..ceb4406170 100644 --- a/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py +++ b/erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py @@ -131,12 +131,11 @@ class MaintenanceSchedule(TransactionBase): ).format(self.owner, "
" + "
".join(no_email_sp)) ) - scheduled_date = frappe.db.sql( - """select scheduled_date from - `tabMaintenance Schedule Detail` where item_code=%s and - parent=%s""", - (d.item_code, self.name), - as_dict=1, + scheduled_date = frappe.db.get_all( + "Maintenance Schedule Detail", + {"parent": self.name, "item_code": d.item_code}, + ["scheduled_date"], + as_list=False, ) for key in scheduled_date: @@ -450,20 +449,28 @@ def get_serial_nos_from_schedule(item_code, schedule=None): def make_maintenance_visit(source_name, target_doc=None, item_name=None, s_id=None): from frappe.model.mapper import get_mapped_doc + def condition(doc): + if s_id: + return doc.name == s_id + elif item_name: + return doc.item_name == item_name + + return True + def update_status_and_detail(source, target, parent): target.maintenance_type = "Scheduled" - target.maintenance_schedule_detail = s_id def update_serial(source, target, parent): - if source.serial_and_batch_bundle: - serial_nos = frappe.get_doc( - "Serial and Batch Bundle", source.serial_and_batch_bundle - ).get_serial_nos() + if source.item_reference: + if sbb := frappe.db.get_value( + "Maintenance Schedule Item", source.item_reference, "serial_and_batch_bundle" + ): + serial_nos = frappe.get_doc("Serial and Batch Bundle", sbb).get_serial_nos() - if len(serial_nos) == 1: - target.serial_no = serial_nos[0] - else: - target.serial_no = "" + if len(serial_nos) == 1: + target.serial_no = serial_nos[0] + else: + target.serial_no = "" doclist = get_mapped_doc( "Maintenance Schedule", @@ -475,10 +482,13 @@ def make_maintenance_visit(source_name, target_doc=None, item_name=None, s_id=No "validation": {"docstatus": ["=", 1]}, "postprocess": update_status_and_detail, }, - "Maintenance Schedule Item": { + "Maintenance Schedule Detail": { "doctype": "Maintenance Visit Purpose", - "condition": lambda doc: doc.item_name == item_name if item_name else True, - "field_map": {"sales_person": "service_person"}, + "condition": condition, + "field_map": { + "sales_person": "service_person", + "name": "maintenance_schedule_detail", + }, "postprocess": update_serial, }, }, diff --git a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py index e7df4847dd..d2511b8cbc 100644 --- a/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py +++ b/erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py @@ -56,20 +56,39 @@ class MaintenanceVisit(TransactionBase): frappe.throw(_("Add Items in the Purpose Table"), title=_("Purposes Required")) def validate_maintenance_date(self): - if self.maintenance_type == "Scheduled" and self.maintenance_schedule_detail: - item_ref = frappe.db.get_value( - "Maintenance Schedule Detail", self.maintenance_schedule_detail, "item_reference" - ) - if item_ref: - start_date, end_date = frappe.db.get_value( - "Maintenance Schedule Item", item_ref, ["start_date", "end_date"] + if self.maintenance_type == "Scheduled": + if self.maintenance_schedule_detail: + item_ref = frappe.db.get_value( + "Maintenance Schedule Detail", self.maintenance_schedule_detail, "item_reference" ) - if get_datetime(self.mntc_date) < get_datetime(start_date) or get_datetime( - self.mntc_date - ) > get_datetime(end_date): - frappe.throw( - _("Date must be between {0} and {1}").format(format_date(start_date), format_date(end_date)) + if item_ref: + start_date, end_date = frappe.db.get_value( + "Maintenance Schedule Item", item_ref, ["start_date", "end_date"] ) + if get_datetime(self.mntc_date) < get_datetime(start_date) or get_datetime( + self.mntc_date + ) > get_datetime(end_date): + frappe.throw( + _("Date must be between {0} and {1}").format(format_date(start_date), format_date(end_date)) + ) + else: + for purpose in self.purposes: + if purpose.maintenance_schedule_detail: + item_ref = frappe.db.get_value( + "Maintenance Schedule Detail", purpose.maintenance_schedule_detail, "item_reference" + ) + if item_ref: + start_date, end_date = frappe.db.get_value( + "Maintenance Schedule Item", item_ref, ["start_date", "end_date"] + ) + if get_datetime(self.mntc_date) < get_datetime(start_date) or get_datetime( + self.mntc_date + ) > get_datetime(end_date): + frappe.throw( + _("Date must be between {0} and {1}").format( + format_date(start_date), format_date(end_date) + ) + ) def validate(self): self.validate_serial_no() @@ -82,6 +101,7 @@ class MaintenanceVisit(TransactionBase): if not cancel: status = self.completion_status actual_date = self.mntc_date + if self.maintenance_schedule_detail: frappe.db.set_value( "Maintenance Schedule Detail", self.maintenance_schedule_detail, "completion_status", status @@ -89,6 +109,21 @@ class MaintenanceVisit(TransactionBase): frappe.db.set_value( "Maintenance Schedule Detail", self.maintenance_schedule_detail, "actual_date", actual_date ) + else: + for purpose in self.purposes: + if purpose.maintenance_schedule_detail: + frappe.db.set_value( + "Maintenance Schedule Detail", + purpose.maintenance_schedule_detail, + "completion_status", + status, + ) + frappe.db.set_value( + "Maintenance Schedule Detail", + purpose.maintenance_schedule_detail, + "actual_date", + actual_date, + ) def update_customer_issue(self, flag): if not self.maintenance_schedule: diff --git a/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.json b/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.json index ba05355553..a5a63c4c4d 100644 --- a/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.json +++ b/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.json @@ -17,7 +17,8 @@ "work_details", "work_done", "prevdoc_doctype", - "prevdoc_docname" + "prevdoc_docname", + "maintenance_schedule_detail" ], "fields": [ { @@ -49,6 +50,8 @@ "options": "Serial No" }, { + "fetch_from": "item_code.description", + "fetch_if_empty": 1, "fieldname": "description", "fieldtype": "Text Editor", "in_list_view": 1, @@ -56,7 +59,6 @@ "oldfieldname": "description", "oldfieldtype": "Small Text", "print_width": "300px", - "reqd": 1, "width": "300px" }, { @@ -103,12 +105,19 @@ { "fieldname": "section_break_6", "fieldtype": "Section Break" + }, + { + "fieldname": "maintenance_schedule_detail", + "fieldtype": "Data", + "hidden": 1, + "label": "Maintenance Schedule Detail", + "options": "Maintenance Schedule Detail" } ], "idx": 1, "istable": 1, "links": [], - "modified": "2023-02-27 11:09:33.114458", + "modified": "2024-01-05 21:46:53.239830", "modified_by": "Administrator", "module": "Maintenance", "name": "Maintenance Visit Purpose", diff --git a/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.py b/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.py index 3686941c64..1d4dab2873 100644 --- a/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.py +++ b/erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.py @@ -14,9 +14,10 @@ class MaintenanceVisitPurpose(Document): if TYPE_CHECKING: from frappe.types import DF - description: DF.TextEditor + description: DF.TextEditor | None item_code: DF.Link | None item_name: DF.Data | None + maintenance_schedule_detail: DF.Data | None parent: DF.Data parentfield: DF.Data parenttype: DF.Data From b96c063c93532b8910b910b04750b3de367954cc Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Mon, 8 Jan 2024 12:51:14 +0530 Subject: [PATCH 184/205] fix: duplicate entry for serial / batch creation (#39188) --- .../serial_and_batch_bundle.py | 19 ++++++++--- .../test_serial_and_batch_bundle.py | 34 +++++++++++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py index eede928827..620b9606a7 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py @@ -1004,13 +1004,17 @@ def make_serial_nos(item_code, serial_nos): item = frappe.get_cached_value("Item", item_code, ["description", "item_code"], as_dict=1) serial_nos = [d.get("serial_no") for d in serial_nos if d.get("serial_no")] + existing_serial_nos = frappe.get_all("Serial No", filters={"name": ("in", serial_nos)}) + + existing_serial_nos = [d.get("name") for d in existing_serial_nos if d.get("name")] + serial_nos = list(set(serial_nos) - set(existing_serial_nos)) + + if not serial_nos: + return serial_nos_details = [] user = frappe.session.user for serial_no in serial_nos: - if frappe.db.exists("Serial No", serial_no): - continue - serial_nos_details.append( ( serial_no, @@ -1046,9 +1050,16 @@ def make_serial_nos(item_code, serial_nos): def make_batch_nos(item_code, batch_nos): item = frappe.get_cached_value("Item", item_code, ["description", "item_code"], as_dict=1) - batch_nos = [d.get("batch_no") for d in batch_nos if d.get("batch_no")] + existing_batches = frappe.get_all("Batch", filters={"name": ("in", batch_nos)}) + + existing_batches = [d.get("name") for d in existing_batches if d.get("name")] + + batch_nos = list(set(batch_nos) - set(existing_batches)) + if not batch_nos: + return + batch_nos_details = [] user = frappe.session.user for batch_no in batch_nos: diff --git a/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py b/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py index 19757479a5..0d453fb841 100644 --- a/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py +++ b/erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py @@ -10,6 +10,8 @@ from frappe.utils import add_days, add_to_date, flt, nowdate, nowtime, today from erpnext.stock.doctype.item.test_item import make_item from erpnext.stock.doctype.serial_and_batch_bundle.serial_and_batch_bundle import ( add_serial_batch_ledgers, + make_batch_nos, + make_serial_nos, ) from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry @@ -481,6 +483,38 @@ class TestSerialandBatchBundle(FrappeTestCase): docstatus = frappe.db.get_value("Serial and Batch Bundle", bundle, "docstatus") self.assertEqual(docstatus, 2) + def test_batch_duplicate_entry(self): + item_code = make_item(properties={"has_batch_no": 1}).name + + batch_id = "TEST-BATTCCH-VAL-00001" + batch_nos = [{"batch_no": batch_id, "qty": 1}] + + make_batch_nos(item_code, batch_nos) + self.assertTrue(frappe.db.exists("Batch", batch_id)) + + batch_id = "TEST-BATTCCH-VAL-00001" + batch_nos = [{"batch_no": batch_id, "qty": 1}] + + # Shouldn't throw duplicate entry error + make_batch_nos(item_code, batch_nos) + self.assertTrue(frappe.db.exists("Batch", batch_id)) + + def test_serial_no_duplicate_entry(self): + item_code = make_item(properties={"has_serial_no": 1}).name + + serial_no_id = "TEST-SNID-VAL-00001" + serial_nos = [{"serial_no": serial_no_id, "qty": 1}] + + make_serial_nos(item_code, serial_nos) + self.assertTrue(frappe.db.exists("Serial No", serial_no_id)) + + serial_no_id = "TEST-SNID-VAL-00001" + serial_nos = [{"batch_no": serial_no_id, "qty": 1}] + + # Shouldn't throw duplicate entry error + make_serial_nos(item_code, serial_nos) + self.assertTrue(frappe.db.exists("Serial No", serial_no_id)) + def get_batch_from_bundle(bundle): from erpnext.stock.serial_batch_bundle import get_batch_nos From 7d264696f3da3d2345588fa391aece975ec82b09 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 8 Jan 2024 13:07:42 +0530 Subject: [PATCH 185/205] fix: account currency from existing company coa --- .../doctype/account/chart_of_accounts/chart_of_accounts.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py b/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py index 9f56455990..05ff2a178a 100644 --- a/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py +++ b/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py @@ -231,6 +231,8 @@ def build_account_tree(tree, parent, all_accounts): tree[child.account_name]["account_type"] = child.account_type if child.tax_rate: tree[child.account_name]["tax_rate"] = child.tax_rate + if child.account_currency: + tree[child.account_name]["account_currency"] = child.account_currency if not parent: tree[child.account_name]["root_type"] = child.root_type From 5923b48edefd2bdb4624abddc1d626e3c8228ee6 Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 8 Jan 2024 13:18:01 +0530 Subject: [PATCH 186/205] fix: avoid copying party balance --- .../doctype/payment_entry/payment_entry.json | 3 +- .../doctype/payment_entry/payment_entry.py | 82 +++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.json b/erpnext/accounts/doctype/payment_entry/payment_entry.json index aa181564b0..3a1e1ea9ad 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.json +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.json @@ -223,6 +223,7 @@ "fieldname": "party_balance", "fieldtype": "Currency", "label": "Party Balance", + "no_copy": 1, "print_hide": 1, "read_only": 1 }, @@ -759,7 +760,7 @@ "table_fieldname": "payment_entries" } ], - "modified": "2023-11-23 12:07:20.887885", + "modified": "2024-01-08 13:17:15.744754", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Entry", diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 052eff393e..37bd8e6fcd 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -50,6 +50,88 @@ class InvalidPaymentEntry(ValidationError): class PaymentEntry(AccountsController): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + from erpnext.accounts.doctype.advance_taxes_and_charges.advance_taxes_and_charges import ( + AdvanceTaxesandCharges, + ) + from erpnext.accounts.doctype.payment_entry_deduction.payment_entry_deduction import ( + PaymentEntryDeduction, + ) + from erpnext.accounts.doctype.payment_entry_reference.payment_entry_reference import ( + PaymentEntryReference, + ) + + amended_from: DF.Link | None + apply_tax_withholding_amount: DF.Check + auto_repeat: DF.Link | None + bank: DF.ReadOnly | None + bank_account: DF.Link | None + bank_account_no: DF.ReadOnly | None + base_paid_amount: DF.Currency + base_paid_amount_after_tax: DF.Currency + base_received_amount: DF.Currency + base_received_amount_after_tax: DF.Currency + base_total_allocated_amount: DF.Currency + base_total_taxes_and_charges: DF.Currency + book_advance_payments_in_separate_party_account: DF.Check + clearance_date: DF.Date | None + company: DF.Link + contact_email: DF.Data | None + contact_person: DF.Link | None + cost_center: DF.Link | None + custom_remarks: DF.Check + deductions: DF.Table[PaymentEntryDeduction] + difference_amount: DF.Currency + letter_head: DF.Link | None + mode_of_payment: DF.Link | None + naming_series: DF.Literal["ACC-PAY-.YYYY.-"] + paid_amount: DF.Currency + paid_amount_after_tax: DF.Currency + paid_from: DF.Link + paid_from_account_balance: DF.Currency + paid_from_account_currency: DF.Link + paid_from_account_type: DF.Data | None + paid_to: DF.Link + paid_to_account_balance: DF.Currency + paid_to_account_currency: DF.Link + paid_to_account_type: DF.Data | None + party: DF.DynamicLink | None + party_balance: DF.Currency + party_bank_account: DF.Link | None + party_name: DF.Data | None + party_type: DF.Link | None + payment_order: DF.Link | None + payment_order_status: DF.Literal["Initiated", "Payment Ordered"] + payment_type: DF.Literal["Receive", "Pay", "Internal Transfer"] + posting_date: DF.Date + print_heading: DF.Link | None + project: DF.Link | None + purchase_taxes_and_charges_template: DF.Link | None + received_amount: DF.Currency + received_amount_after_tax: DF.Currency + reference_date: DF.Date | None + reference_no: DF.Data | None + references: DF.Table[PaymentEntryReference] + remarks: DF.SmallText | None + sales_taxes_and_charges_template: DF.Link | None + source_exchange_rate: DF.Float + status: DF.Literal["", "Draft", "Submitted", "Cancelled"] + target_exchange_rate: DF.Float + tax_withholding_category: DF.Link | None + taxes: DF.Table[AdvanceTaxesandCharges] + title: DF.Data | None + total_allocated_amount: DF.Currency + total_taxes_and_charges: DF.Currency + unallocated_amount: DF.Currency + # end: auto-generated types + def __init__(self, *args, **kwargs): super(PaymentEntry, self).__init__(*args, **kwargs) if not self.is_new(): From 6de8c18f9803c055c17e220f8f8d7eed5dfb45c6 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 8 Jan 2024 13:18:29 +0530 Subject: [PATCH 187/205] fix: bank transction status upon reconciliation --- .../bank_reconciliation_tool.py | 4 ++++ .../doctype/bank_transaction/bank_transaction.py | 16 ++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py index 0779a09e2f..9e6b51d2c1 100644 --- a/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py +++ b/erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.py @@ -444,6 +444,10 @@ def reconcile_vouchers(bank_transaction_name, vouchers): vouchers = json.loads(vouchers) transaction = frappe.get_doc("Bank Transaction", bank_transaction_name) transaction.add_payment_entries(vouchers) + transaction.validate_duplicate_references() + transaction.allocate_payment_entries() + transaction.update_allocated_amount() + transaction.set_status() transaction.save() return transaction diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py index 57f7c0eca3..8d82123989 100644 --- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py +++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py @@ -3,12 +3,11 @@ import frappe from frappe import _ +from frappe.model.document import Document from frappe.utils import flt -from erpnext.controllers.status_updater import StatusUpdater - -class BankTransaction(StatusUpdater): +class BankTransaction(Document): # begin: auto-generated types # This code is auto-generated. Do not modify anything in this block. @@ -50,6 +49,15 @@ class BankTransaction(StatusUpdater): def validate(self): self.validate_duplicate_references() + def set_status(self): + if self.docstatus == 2: + self.db_set("status", "Cancelled") + elif self.docstatus == 1: + if self.unallocated_amount > 0: + self.db_set("status", "Unreconciled") + elif self.unallocated_amount <= 0: + self.db_set("status", "Reconciled") + def validate_duplicate_references(self): """Make sure the same voucher is not allocated twice within the same Bank Transaction""" if not self.payment_entries: @@ -88,7 +96,7 @@ class BankTransaction(StatusUpdater): for payment_entry in self.payment_entries: self.clear_linked_payment_entry(payment_entry, for_cancel=True) - self.set_status(update=True) + self.set_status() def add_payment_entries(self, vouchers): "Add the vouchers with zero allocation. Save() will perform the allocations and clearance" From d0ea598cdfb203882fca887d2ba34938c4c75b8e Mon Sep 17 00:00:00 2001 From: Gursheen Anand Date: Mon, 8 Jan 2024 15:50:50 +0530 Subject: [PATCH 188/205] fix: fetch name for fy --- erpnext/accounts/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index f9208f051e..25fbe170b8 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -1280,7 +1280,7 @@ def parse_naming_series_variable(doc, variable): else: date = getdate() company = None - return get_fiscal_year(date=date, company=company)[0] + return get_fiscal_year(date=date, company=company).name @frappe.whitelist() From 3d54fd8389c41b14e8002518b111ebd71fd94186 Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Mon, 8 Jan 2024 16:04:40 +0530 Subject: [PATCH 189/205] fix: add expected_start_date in sort by --- erpnext/projects/doctype/project/project.json | 3 +- erpnext/projects/doctype/project/project.py | 53 +++++++++++++++++++ erpnext/projects/doctype/task/task.json | 3 +- erpnext/projects/doctype/task/task.py | 7 +-- 4 files changed, 59 insertions(+), 7 deletions(-) diff --git a/erpnext/projects/doctype/project/project.json b/erpnext/projects/doctype/project/project.json index 715b09c64b..5917e9b5d2 100644 --- a/erpnext/projects/doctype/project/project.json +++ b/erpnext/projects/doctype/project/project.json @@ -131,6 +131,7 @@ "set_only_once": 1 }, { + "bold": 1, "fieldname": "expected_start_date", "fieldtype": "Date", "label": "Expected Start Date", @@ -453,7 +454,7 @@ "index_web_pages_for_search": 1, "links": [], "max_attachments": 4, - "modified": "2023-08-28 22:27:28.370849", + "modified": "2024-01-08 16:01:34.598258", "modified_by": "Administrator", "module": "Projects", "name": "Project", diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py index 751dcbd06a..6bd0b756d9 100644 --- a/erpnext/projects/doctype/project/project.py +++ b/erpnext/projects/doctype/project/project.py @@ -19,6 +19,59 @@ from erpnext.setup.doctype.holiday_list.holiday_list import is_holiday class Project(Document): + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from erpnext.projects.doctype.project_user.project_user import ProjectUser + from frappe.types import DF + + actual_end_date: DF.Date | None + actual_start_date: DF.Date | None + actual_time: DF.Float + collect_progress: DF.Check + company: DF.Link + copied_from: DF.Data | None + cost_center: DF.Link | None + customer: DF.Link | None + daily_time_to_send: DF.Time | None + day_to_send: DF.Literal["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] + department: DF.Link | None + estimated_costing: DF.Currency + expected_end_date: DF.Date | None + expected_start_date: DF.Date | None + first_email: DF.Time | None + frequency: DF.Literal["Hourly", "Twice Daily", "Daily", "Weekly"] + from_time: DF.Time | None + gross_margin: DF.Currency + holiday_list: DF.Link | None + is_active: DF.Literal["Yes", "No"] + message: DF.Text | None + naming_series: DF.Literal["PROJ-.####"] + notes: DF.TextEditor | None + per_gross_margin: DF.Percent + percent_complete: DF.Percent + percent_complete_method: DF.Literal["Manual", "Task Completion", "Task Progress", "Task Weight"] + priority: DF.Literal["Medium", "Low", "High"] + project_name: DF.Data + project_template: DF.Link | None + project_type: DF.Link | None + sales_order: DF.Link | None + second_email: DF.Time | None + status: DF.Literal["Open", "Completed", "Cancelled"] + to_time: DF.Time | None + total_billable_amount: DF.Currency + total_billed_amount: DF.Currency + total_consumed_material_cost: DF.Currency + total_costing_amount: DF.Currency + total_purchase_cost: DF.Currency + total_sales_amount: DF.Currency + users: DF.Table[ProjectUser] + weekly_time_to_send: DF.Time | None + # end: auto-generated types + def onload(self): self.set_onload( "activity_summary", diff --git a/erpnext/projects/doctype/task/task.json b/erpnext/projects/doctype/task/task.json index 4d2d225242..cc9832b584 100644 --- a/erpnext/projects/doctype/task/task.json +++ b/erpnext/projects/doctype/task/task.json @@ -153,6 +153,7 @@ "label": "Timeline" }, { + "bold": 1, "fieldname": "exp_start_date", "fieldtype": "Date", "label": "Expected Start Date", @@ -398,7 +399,7 @@ "is_tree": 1, "links": [], "max_attachments": 5, - "modified": "2023-11-20 11:42:41.884069", + "modified": "2024-01-08 16:00:41.296203", "modified_by": "Administrator", "module": "Projects", "name": "Task", diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py index 22df846e39..e96b8e4fc6 100755 --- a/erpnext/projects/doctype/task/task.py +++ b/erpnext/projects/doctype/task/task.py @@ -24,9 +24,8 @@ class Task(NestedSet): from typing import TYPE_CHECKING if TYPE_CHECKING: - from frappe.types import DF - from erpnext.projects.doctype.task_depends_on.task_depends_on import TaskDependsOn + from frappe.types import DF act_end_date: DF.Date | None act_start_date: DF.Date | None @@ -57,9 +56,7 @@ class Task(NestedSet): review_date: DF.Date | None rgt: DF.Int start: DF.Int - status: DF.Literal[ - "Open", "Working", "Pending Review", "Overdue", "Template", "Completed", "Cancelled" - ] + status: DF.Literal["Open", "Working", "Pending Review", "Overdue", "Template", "Completed", "Cancelled"] subject: DF.Data task_weight: DF.Float template_task: DF.Data | None From eab22eb2822055e0e04adf853879237c00988572 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 8 Jan 2024 16:35:45 +0530 Subject: [PATCH 190/205] fix: Introduced company field to show amounts in company currency --- .../asset_depreciation_schedule.json | 11 ++++++++++- .../asset_depreciation_schedule.py | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json index be35914251..73838163d3 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json @@ -9,6 +9,7 @@ "field_order": [ "asset", "naming_series", + "company", "column_break_2", "gross_purchase_amount", "opening_accumulated_depreciation", @@ -193,12 +194,20 @@ "fieldtype": "Check", "label": "Depreciate based on shifts", "read_only": 1 + }, + { + "fetch_from": "asset.company", + "fieldname": "company", + "fieldtype": "Link", + "label": "Company", + "options": "Company", + "read_only": 1 } ], "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2023-11-29 00:57:00.461998", + "modified": "2024-01-08 16:31:04.533928", "modified_by": "Administrator", "module": "Assets", "name": "Asset Depreciation Schedule", diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py index 67234ccd84..4c94be5320 100644 --- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py +++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py @@ -35,6 +35,7 @@ class AssetDepreciationSchedule(Document): amended_from: DF.Link | None asset: DF.Link + company: DF.Link | None daily_prorata_based: DF.Check depreciation_method: DF.Literal[ "", "Straight Line", "Double Declining Balance", "Written Down Value", "Manual" From 9ba6ff67d5727ee97f12a9cbee120e78c20d6cec Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 8 Jan 2024 17:11:26 +0530 Subject: [PATCH 191/205] fix: project filters on Delivery Note and Sales Order --- erpnext/public/js/utils/dimension_tree_filter.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/public/js/utils/dimension_tree_filter.js b/erpnext/public/js/utils/dimension_tree_filter.js index bb23f1512b..3f70c09f66 100644 --- a/erpnext/public/js/utils/dimension_tree_filter.js +++ b/erpnext/public/js/utils/dimension_tree_filter.js @@ -16,6 +16,8 @@ erpnext.accounts.dimensions = { }, callback: function(r) { me.accounting_dimensions = r.message[0]; + // Ignoring "Project" as it is already handled specifically in Sales Order and Delivery Note + me.accounting_dimensions = me.accounting_dimensions.filter(x=>{return x.document_type != "Project"}); me.default_dimensions = r.message[1]; me.setup_filters(frm, doctype); } From 466625213b6355b53b7af3ee1682cee6fc8649a4 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Mon, 8 Jan 2024 17:18:29 +0530 Subject: [PATCH 192/205] fix: FG Item incorrect qty in the work order (#39200) --- .../production_plan/production_plan.py | 11 ++--- .../production_plan/test_production_plan.py | 41 ++++++++++++++++++- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index 2bfd4be53a..f64af50188 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -646,6 +646,10 @@ class ProductionPlan(Document): "project": self.project, } + key = (d.item_code, d.sales_order, d.warehouse) + if not d.sales_order: + key = (d.name, d.item_code, d.warehouse) + if not item_details["project"] and d.sales_order: item_details["project"] = frappe.get_cached_value("Sales Order", d.sales_order, "project") @@ -654,12 +658,9 @@ class ProductionPlan(Document): item_dict[(d.item_code, d.material_request_item, d.warehouse)] = item_details else: item_details.update( - { - "qty": flt(item_dict.get((d.item_code, d.sales_order, d.warehouse), {}).get("qty")) - + (flt(d.planned_qty) - flt(d.ordered_qty)) - } + {"qty": flt(item_dict.get(key, {}).get("qty")) + (flt(d.planned_qty) - flt(d.ordered_qty))} ) - item_dict[(d.item_code, d.sales_order, d.warehouse)] = item_details + item_dict[key] = item_details return item_dict diff --git a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py index f6dfaa5058..fedeb7a477 100644 --- a/erpnext/manufacturing/doctype/production_plan/test_production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/test_production_plan.py @@ -672,7 +672,7 @@ class TestProductionPlan(FrappeTestCase): items_data = pln.get_production_items() # Update qty - items_data[(item, None, None)]["qty"] = qty + items_data[(pln.po_items[0].name, item, None)]["qty"] = qty # Create and Submit Work Order for each item in items_data for key, item in items_data.items(): @@ -1522,6 +1522,45 @@ class TestProductionPlan(FrappeTestCase): for d in mr_items: self.assertEqual(d.get("quantity"), 1000.0) + def test_fg_item_quantity(self): + from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse + from erpnext.stock.utils import get_or_make_bin + + fg_item = make_item(properties={"is_stock_item": 1}).name + rm_item = make_item(properties={"is_stock_item": 1}).name + + make_bom(item=fg_item, raw_materials=[rm_item], source_warehouse="_Test Warehouse - _TC") + + pln = create_production_plan(item_code=fg_item, planned_qty=10, do_not_submit=1) + + pln.append( + "po_items", + { + "item_code": rm_item, + "planned_qty": 20, + "bom_no": pln.po_items[0].bom_no, + "warehouse": pln.po_items[0].warehouse, + "planned_start_date": add_to_date(nowdate(), days=1), + }, + ) + pln.submit() + wo_qty = {} + + for row in pln.po_items: + wo_qty[row.name] = row.planned_qty + + pln.make_work_order() + + work_orders = frappe.get_all( + "Work Order", + fields=["qty", "production_plan_item as name"], + filters={"production_plan": pln.name}, + ) + self.assertEqual(len(work_orders), 2) + + for row in work_orders: + self.assertEqual(row.qty, wo_qty[row.name]) + def create_production_plan(**args): """ From cf988434e9e4fd7f7c6df2b024902f8df9942ca3 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 8 Jan 2024 17:32:22 +0530 Subject: [PATCH 193/205] refactor: remove 'Bank Trasaction' logic from status_update --- erpnext/controllers/status_updater.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py index d09001c8fc..297f8c26be 100644 --- a/erpnext/controllers/status_updater.py +++ b/erpnext/controllers/status_updater.py @@ -131,11 +131,6 @@ status_map = { "eval:self.status != 'Stopped' and self.per_ordered == 100 and self.docstatus == 1 and self.material_request_type == 'Manufacture'", ], ], - "Bank Transaction": [ - ["Unreconciled", "eval:self.docstatus == 1 and self.unallocated_amount>0"], - ["Reconciled", "eval:self.docstatus == 1 and self.unallocated_amount<=0"], - ["Cancelled", "eval:self.docstatus == 2"], - ], "POS Opening Entry": [ ["Draft", None], ["Open", "eval:self.docstatus == 1 and not self.pos_closing_entry"], From 498bf15ecd63af122ba8740536c89cd1275ad4d1 Mon Sep 17 00:00:00 2001 From: Shariq Ansari <30859809+shariquerik@users.noreply.github.com> Date: Mon, 8 Jan 2024 17:58:59 +0530 Subject: [PATCH 194/205] chore: linter fix --- erpnext/projects/doctype/task/task.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py index e96b8e4fc6..22df846e39 100755 --- a/erpnext/projects/doctype/task/task.py +++ b/erpnext/projects/doctype/task/task.py @@ -24,9 +24,10 @@ class Task(NestedSet): from typing import TYPE_CHECKING if TYPE_CHECKING: - from erpnext.projects.doctype.task_depends_on.task_depends_on import TaskDependsOn from frappe.types import DF + from erpnext.projects.doctype.task_depends_on.task_depends_on import TaskDependsOn + act_end_date: DF.Date | None act_start_date: DF.Date | None actual_time: DF.Float @@ -56,7 +57,9 @@ class Task(NestedSet): review_date: DF.Date | None rgt: DF.Int start: DF.Int - status: DF.Literal["Open", "Working", "Pending Review", "Overdue", "Template", "Completed", "Cancelled"] + status: DF.Literal[ + "Open", "Working", "Pending Review", "Overdue", "Template", "Completed", "Cancelled" + ] subject: DF.Data task_weight: DF.Float template_task: DF.Data | None From be8bb235dc3dc6157507d59089c43146eb38ea6a Mon Sep 17 00:00:00 2001 From: Shariq Ansari <30859809+shariquerik@users.noreply.github.com> Date: Mon, 8 Jan 2024 18:00:02 +0530 Subject: [PATCH 195/205] chore: linter fix --- erpnext/projects/doctype/project/project.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py index 6bd0b756d9..d17d21cf27 100644 --- a/erpnext/projects/doctype/project/project.py +++ b/erpnext/projects/doctype/project/project.py @@ -25,9 +25,10 @@ class Project(Document): from typing import TYPE_CHECKING if TYPE_CHECKING: - from erpnext.projects.doctype.project_user.project_user import ProjectUser from frappe.types import DF + from erpnext.projects.doctype.project_user.project_user import ProjectUser + actual_end_date: DF.Date | None actual_start_date: DF.Date | None actual_time: DF.Float @@ -37,7 +38,9 @@ class Project(Document): cost_center: DF.Link | None customer: DF.Link | None daily_time_to_send: DF.Time | None - day_to_send: DF.Literal["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] + day_to_send: DF.Literal[ + "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" + ] department: DF.Link | None estimated_costing: DF.Currency expected_end_date: DF.Date | None From c14986f9e6e617b67e97c8d25843a4dc33b77dcf Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 8 Jan 2024 18:15:55 +0530 Subject: [PATCH 196/205] fix: Show maintain-stock and is-fixed-asset checkbox in item quick entry dialog --- erpnext/stock/doctype/item/item.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json index 13f3be8c36..6529bb2806 100644 --- a/erpnext/stock/doctype/item/item.json +++ b/erpnext/stock/doctype/item/item.json @@ -202,6 +202,7 @@ "label": "Allow Alternative Item" }, { + "allow_in_quick_entry": 1, "bold": 1, "default": "1", "depends_on": "eval:!doc.is_fixed_asset", @@ -239,6 +240,7 @@ "label": "Standard Selling Rate" }, { + "allow_in_quick_entry": 1, "default": "0", "fieldname": "is_fixed_asset", "fieldtype": "Check", @@ -246,6 +248,7 @@ "set_only_once": 1 }, { + "allow_in_quick_entry": 1, "depends_on": "is_fixed_asset", "fieldname": "asset_category", "fieldtype": "Link", @@ -888,7 +891,7 @@ "index_web_pages_for_search": 1, "links": [], "make_attachments_public": 1, - "modified": "2023-09-18 15:41:32.688051", + "modified": "2024-01-08 18:09:30.225085", "modified_by": "Administrator", "module": "Stock", "name": "Item", @@ -961,4 +964,4 @@ "states": [], "title_field": "item_name", "track_changes": 1 -} +} \ No newline at end of file From b498094a9759bb95a3c77c6ec6877aafc6daa0ea Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 9 Jan 2024 12:40:41 +0530 Subject: [PATCH 197/205] fix: total allocated percentage for sales team issue --- .../selling/doctype/quotation/quotation.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index 00b79e3aad..ab74f7f738 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -370,15 +370,16 @@ def _make_sales_order(source_name, target_doc=None, customer_group=None, ignore_ ) # sales team - for d in customer.get("sales_team") or []: - target.append( - "sales_team", - { - "sales_person": d.sales_person, - "allocated_percentage": d.allocated_percentage or None, - "commission_rate": d.commission_rate, - }, - ) + if not target.get("sales_team"): + for d in customer.get("sales_team") or []: + target.append( + "sales_team", + { + "sales_person": d.sales_person, + "allocated_percentage": d.allocated_percentage or None, + "commission_rate": d.commission_rate, + }, + ) target.flags.ignore_permissions = ignore_permissions target.delivery_date = nowdate() From 5e0d017497ef7afaaa70abffbd3d3924f9e56063 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Tue, 9 Jan 2024 15:32:45 +0530 Subject: [PATCH 198/205] fix: BOM replace tool does not update exploded items of root (#39244) --- .../bom_update_log/bom_updation_utils.py | 6 +- .../bom_update_log/test_bom_update_log.py | 62 +++++++++++++++++++ 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/erpnext/manufacturing/doctype/bom_update_log/bom_updation_utils.py b/erpnext/manufacturing/doctype/bom_update_log/bom_updation_utils.py index a2919b79b8..f013b88e94 100644 --- a/erpnext/manufacturing/doctype/bom_update_log/bom_updation_utils.py +++ b/erpnext/manufacturing/doctype/bom_update_log/bom_updation_utils.py @@ -86,10 +86,12 @@ def get_ancestor_boms(new_bom: str, bom_list: Optional[List] = None) -> List: if new_bom == d.parent: frappe.throw(_("BOM recursion: {0} cannot be child of {1}").format(new_bom, d.parent)) - bom_list.append(d.parent) + if d.parent not in tuple(bom_list): + bom_list.append(d.parent) + get_ancestor_boms(d.parent, bom_list) - return list(set(bom_list)) + return bom_list def update_new_bom_in_bom_items(unit_cost: float, current_bom: str, new_bom: str) -> None: diff --git a/erpnext/manufacturing/doctype/bom_update_log/test_bom_update_log.py b/erpnext/manufacturing/doctype/bom_update_log/test_bom_update_log.py index b38fc8976b..30e6f5e209 100644 --- a/erpnext/manufacturing/doctype/bom_update_log/test_bom_update_log.py +++ b/erpnext/manufacturing/doctype/bom_update_log/test_bom_update_log.py @@ -57,6 +57,68 @@ class TestBOMUpdateLog(FrappeTestCase): log.reload() self.assertEqual(log.status, "Completed") + def test_bom_replace_for_root_bom(self): + """ + - B-Item A (Root Item) + - B-Item B + - B-Item C + - B-Item D + - B-Item E + - B-Item F + + Create New BOM for B-Item E with B-Item G and replace it in the above BOM. + """ + + from erpnext.manufacturing.doctype.bom.test_bom import create_nested_bom + from erpnext.stock.doctype.item.test_item import make_item + + items = ["B-Item A", "B-Item B", "B-Item C", "B-Item D", "B-Item E", "B-Item F", "B-Item G"] + + for item_code in items: + if not frappe.db.exists("Item", item_code): + make_item(item_code) + + for item_code in items: + remove_bom(item_code) + + bom_tree = { + "B-Item A": {"B-Item B": {"B-Item C": {}}, "B-Item D": {"B-Item E": {"B-Item F": {}}}} + } + + root_bom = create_nested_bom(bom_tree, prefix="") + + exploded_items = frappe.get_all( + "BOM Explosion Item", filters={"parent": root_bom.name}, fields=["item_code"] + ) + + exploded_items = [item.item_code for item in exploded_items] + expected_exploded_items = ["B-Item C", "B-Item F"] + self.assertEqual(sorted(exploded_items), sorted(expected_exploded_items)) + + old_bom = frappe.db.get_value("BOM", {"item": "B-Item E"}, "name") + bom_tree = {"B-Item E": {"B-Item G": {}}} + + new_bom = create_nested_bom(bom_tree, prefix="") + enqueue_replace_bom(boms=frappe._dict(current_bom=old_bom, new_bom=new_bom.name)) + + exploded_items = frappe.get_all( + "BOM Explosion Item", filters={"parent": root_bom.name}, fields=["item_code"] + ) + + exploded_items = [item.item_code for item in exploded_items] + expected_exploded_items = ["B-Item C", "B-Item G"] + self.assertEqual(sorted(exploded_items), sorted(expected_exploded_items)) + + +def remove_bom(item_code): + boms = frappe.get_all("BOM", fields=["docstatus", "name"], filters={"item": item_code}) + + for row in boms: + if row.docstatus == 1: + frappe.get_doc("BOM", row.name).cancel() + + frappe.delete_doc("BOM", row.name) + def update_cost_in_all_boms_in_test(): """ From d32a407e08609737fa0bc880d5ef737ebf2b3e4c Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 9 Jan 2024 15:35:42 +0530 Subject: [PATCH 199/205] fix: update status on manual allocation --- erpnext/accounts/doctype/bank_transaction/bank_transaction.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py index 8d82123989..1d6cb8e2c0 100644 --- a/erpnext/accounts/doctype/bank_transaction/bank_transaction.py +++ b/erpnext/accounts/doctype/bank_transaction/bank_transaction.py @@ -91,6 +91,7 @@ class BankTransaction(Document): self.validate_duplicate_references() self.allocate_payment_entries() self.update_allocated_amount() + self.set_status() def on_cancel(self): for payment_entry in self.payment_entries: From 2d2ff7cf52a548b8e880cd212cbbe6ef4569ea28 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Tue, 9 Jan 2024 15:37:46 +0530 Subject: [PATCH 200/205] fix: incorrect indicator title for portal sales order (#39247) --- .../doctype/sales_order/sales_order.py | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 09941eaa82..95423612c8 100755 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -582,17 +582,17 @@ class SalesOrder(SellingController): def set_indicator(self): """Set indicator for portal""" - if self.per_billed < 100 and self.per_delivered < 100: - self.indicator_color = "orange" - self.indicator_title = _("Not Paid and Not Delivered") + self.indicator_color = { + "Draft": "red", + "On Hold": "orange", + "To Deliver and Bill": "orange", + "To Bill": "orange", + "To Deliver": "orange", + "Completed": "green", + "Cancelled": "red", + }.get(self.status, "blue") - elif self.per_billed == 100 and self.per_delivered < 100: - self.indicator_color = "orange" - self.indicator_title = _("Paid and Not Delivered") - - else: - self.indicator_color = "green" - self.indicator_title = _("Paid") + self.indicator_title = _(self.status) def on_recurring(self, reference_doc, auto_repeat_doc): def _get_delivery_date(ref_doc_delivery_date, red_doc_transaction_date, transaction_date): From 274c65c451ccc71f11f29a2abc6d13b2b49b776c Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Tue, 9 Jan 2024 16:20:42 +0530 Subject: [PATCH 201/205] fix: TypeError is pricing rules (#39252) --- erpnext/accounts/doctype/pricing_rule/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py index 18aa6820a3..17293adb95 100644 --- a/erpnext/accounts/doctype/pricing_rule/utils.py +++ b/erpnext/accounts/doctype/pricing_rule/utils.py @@ -527,7 +527,7 @@ def get_qty_amount_data_for_cumulative(pr_doc, doc, items=None): values.extend(warehouses) if items: - condition = " and `tab{child_doc}`.{apply_on} in ({items})".format( + condition += " and `tab{child_doc}`.{apply_on} in ({items})".format( child_doc=child_doctype, apply_on=apply_on, items=",".join(["%s"] * len(items)) ) From b15795392bdf8165e7ddfb60451353ebefa177d2 Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Tue, 9 Jan 2024 19:01:21 +0530 Subject: [PATCH 202/205] fix: Duplicate Closing Stock Balance --- .../doctype/closing_stock_balance/closing_stock_balance.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.py b/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.py index f71d21dd0b..1c7018366a 100644 --- a/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.py +++ b/erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.py @@ -65,7 +65,7 @@ class ClosingStockBalance(Document): & ( (table.from_date.between(self.from_date, self.to_date)) | (table.to_date.between(self.from_date, self.to_date)) - | (table.from_date >= self.from_date and table.to_date <= self.to_date) + | (table.from_date >= self.from_date and table.to_date >= self.to_date) ) ) ) From e0ad52b50036e689247f23090a5de89a7fb4abfa Mon Sep 17 00:00:00 2001 From: s-aga-r Date: Tue, 9 Jan 2024 21:05:00 +0530 Subject: [PATCH 203/205] fix: skip rate validation for return `DN Items` with `Moving Average` valuation --- erpnext/controllers/sales_and_purchase_return.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/erpnext/controllers/sales_and_purchase_return.py b/erpnext/controllers/sales_and_purchase_return.py index e7bd2a7265..6e50279d04 100644 --- a/erpnext/controllers/sales_and_purchase_return.py +++ b/erpnext/controllers/sales_and_purchase_return.py @@ -10,7 +10,7 @@ from frappe.utils import flt, format_datetime, get_datetime import erpnext from erpnext.stock.serial_batch_bundle import get_batches_from_bundle from erpnext.stock.serial_batch_bundle import get_serial_nos as get_serial_nos_from_bundle -from erpnext.stock.utils import get_incoming_rate +from erpnext.stock.utils import get_incoming_rate, get_valuation_method class StockOverReturnError(frappe.ValidationError): @@ -116,7 +116,12 @@ def validate_returned_items(doc): ref = valid_items.get(d.item_code, frappe._dict()) validate_quantity(doc, d, ref, valid_items, already_returned_items) - if ref.rate and doc.doctype in ("Delivery Note", "Sales Invoice") and flt(d.rate) > ref.rate: + if ( + ref.rate + and flt(d.rate) > ref.rate + and doc.doctype in ("Delivery Note", "Sales Invoice") + and get_valuation_method(ref.item_code) != "Moving Average" + ): frappe.throw( _("Row # {0}: Rate cannot be greater than the rate used in {1} {2}").format( d.idx, doc.doctype, doc.return_against From bb18ae82cfd235ca0dc6b85059df77cf7d002f48 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 9 Jan 2024 21:56:47 +0530 Subject: [PATCH 204/205] refactor: use db.get_single_value --- erpnext/accounts/doctype/account/account.py | 4 ++-- erpnext/accounts/doctype/gl_entry/gl_entry.py | 4 ++-- .../accounts/doctype/purchase_invoice/purchase_invoice.py | 4 ++-- .../doctype/purchase_invoice/test_purchase_invoice.py | 4 ++-- erpnext/accounts/general_ledger.py | 6 +++--- .../report/accounts_receivable/accounts_receivable.py | 4 ++-- .../accounts_receivable_summary.py | 4 ++-- .../customer_ledger_summary/customer_ledger_summary.py | 4 ++-- erpnext/assets/doctype/asset/depreciation.py | 2 +- .../doctype/request_for_quotation/request_for_quotation.py | 6 +++--- .../doctype/tally_migration/tally_migration.py | 4 +--- erpnext/manufacturing/doctype/workstation/workstation.py | 2 +- .../patches/v13_0/modify_invalid_gain_loss_gl_entries.py | 2 +- erpnext/patches/v14_0/migrate_crm_settings.py | 3 +-- erpnext/selling/doctype/sales_order/test_sales_order.py | 4 ++-- .../customer_credit_balance/customer_credit_balance.py | 2 +- erpnext/startup/boot.py | 2 +- erpnext/stock/doctype/item/item.py | 4 ++-- erpnext/stock/doctype/price_list/price_list.py | 4 ++-- erpnext/stock/doctype/purchase_receipt/purchase_receipt.py | 2 +- .../doctype/repost_item_valuation/repost_item_valuation.py | 7 ++----- erpnext/stock/reorder_item.py | 4 ++-- erpnext/stock/stock_balance.py | 4 ++-- erpnext/stock/utils.py | 2 +- erpnext/support/doctype/issue/issue.py | 2 +- erpnext/utilities/doctype/video/video.py | 4 ++-- 26 files changed, 44 insertions(+), 50 deletions(-) diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py index 82af85d702..651599dafd 100644 --- a/erpnext/accounts/doctype/account/account.py +++ b/erpnext/accounts/doctype/account/account.py @@ -91,8 +91,8 @@ class Account(NestedSet): super(Account, self).on_update() def onload(self): - frozen_accounts_modifier = frappe.db.get_value( - "Accounts Settings", "Accounts Settings", "frozen_accounts_modifier" + frozen_accounts_modifier = frappe.db.get_single_value( + "Accounts Settings", "frozen_accounts_modifier" ) if not frozen_accounts_modifier or frozen_accounts_modifier in frappe.get_roles(): self.set_onload("can_freeze_account", True) diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py index 139f52696b..777a5bb91c 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py @@ -435,8 +435,8 @@ def update_outstanding_amt( def validate_frozen_account(account, adv_adj=None): frozen_account = frappe.get_cached_value("Account", account, "freeze_account") if frozen_account == "Yes" and not adv_adj: - frozen_accounts_modifier = frappe.db.get_value( - "Accounts Settings", None, "frozen_accounts_modifier" + frozen_accounts_modifier = frappe.db.get_single_value( + "Accounts Settings", "frozen_accounts_modifier" ) if not frozen_accounts_modifier: diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index e676560c5c..7f145c569e 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -552,7 +552,7 @@ class PurchaseInvoice(BuyingController): self.against_expense_account = ",".join(against_accounts) def po_required(self): - if frappe.db.get_value("Buying Settings", None, "po_required") == "Yes": + if frappe.db.get_single_value("Buying Settings", "po_required") == "Yes": if frappe.get_value( "Supplier", self.supplier, "allow_purchase_invoice_creation_without_purchase_order" @@ -572,7 +572,7 @@ class PurchaseInvoice(BuyingController): def pr_required(self): stock_items = self.get_stock_items() - if frappe.db.get_value("Buying Settings", None, "pr_required") == "Yes": + if frappe.db.get_single_value("Buying Settings", "pr_required") == "Yes": if frappe.get_value( "Supplier", self.supplier, "allow_purchase_invoice_creation_without_purchase_receipt" diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index 8aa95bfa44..5acd8b074b 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -1237,8 +1237,8 @@ class TestPurchaseInvoice(FrappeTestCase, StockTestMixin): @change_settings("Accounts Settings", {"unlink_payment_on_cancellation_of_invoice": 1}) def test_gain_loss_with_advance_entry(self): - unlink_enabled = frappe.db.get_value( - "Accounts Settings", "Accounts Settings", "unlink_payment_on_cancel_of_invoice" + unlink_enabled = frappe.db.get_single_value( + "Accounts Settings", "unlink_payment_on_cancel_of_invoice" ) frappe.db.set_single_value("Accounts Settings", "unlink_payment_on_cancel_of_invoice", 1) diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index 91ba239f33..b48a8e6115 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -654,10 +654,10 @@ def check_freezing_date(posting_date, adv_adj=False): Hence stop admin to bypass if accounts are freezed """ if not adv_adj: - acc_frozen_upto = frappe.db.get_value("Accounts Settings", None, "acc_frozen_upto") + acc_frozen_upto = frappe.db.get_single_value("Accounts Settings", "acc_frozen_upto") if acc_frozen_upto: - frozen_accounts_modifier = frappe.db.get_value( - "Accounts Settings", None, "frozen_accounts_modifier" + frozen_accounts_modifier = frappe.db.get_single_value( + "Accounts Settings", "frozen_accounts_modifier" ) if getdate(posting_date) <= getdate(acc_frozen_upto) and ( frozen_accounts_modifier not in frappe.get_roles() or frappe.session.user == "Administrator" diff --git a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py index 9feda11d3f..3a70afc3f0 100644 --- a/erpnext/accounts/report/accounts_receivable/accounts_receivable.py +++ b/erpnext/accounts/report/accounts_receivable/accounts_receivable.py @@ -55,8 +55,8 @@ class ReceivablePayableReport(object): def run(self, args): self.filters.update(args) self.set_defaults() - self.party_naming_by = frappe.db.get_value( - args.get("naming_by")[0], None, args.get("naming_by")[1] + self.party_naming_by = frappe.db.get_single_value( + args.get("naming_by")[0], args.get("naming_by")[1] ) self.get_columns() self.get_data() diff --git a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py index 22b5c6ba76..0947cffc9f 100644 --- a/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py +++ b/erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py @@ -24,8 +24,8 @@ class AccountsReceivableSummary(ReceivablePayableReport): def run(self, args): self.account_type = args.get("account_type") self.party_type = get_party_types_from_account_type(self.account_type) - self.party_naming_by = frappe.db.get_value( - args.get("naming_by")[0], None, args.get("naming_by")[1] + self.party_naming_by = frappe.db.get_single_value( + args.get("naming_by")[0], args.get("naming_by")[1] ) self.get_columns() self.get_data(args) diff --git a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py index 0464f99d20..a2c0f86f6c 100644 --- a/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py +++ b/erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py @@ -21,8 +21,8 @@ class PartyLedgerSummaryReport(object): frappe.throw(_("From Date must be before To Date")) self.filters.party_type = args.get("party_type") - self.party_naming_by = frappe.db.get_value( - args.get("naming_by")[0], None, args.get("naming_by")[1] + self.party_naming_by = frappe.db.get_single_value( + args.get("naming_by")[0], args.get("naming_by")[1] ) self.get_gl_entries() diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py index 66930c0e7c..017df90d41 100644 --- a/erpnext/assets/doctype/asset/depreciation.py +++ b/erpnext/assets/doctype/asset/depreciation.py @@ -35,7 +35,7 @@ from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_sched def post_depreciation_entries(date=None): # Return if automatic booking of asset depreciation is disabled if not cint( - frappe.db.get_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically") + frappe.db.get_single_value("Accounts Settings", "book_asset_depreciation_entry_automatically") ): return diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py index 9aaf86b3ab..eec996c6a9 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py @@ -358,8 +358,8 @@ def make_supplier_quotation_from_rfq(source_name, target_doc=None, for_supplier= target_doc.currency = args.currency or get_party_account_currency( "Supplier", for_supplier, source.company ) - target_doc.buying_price_list = args.buying_price_list or frappe.db.get_value( - "Buying Settings", None, "buying_price_list" + target_doc.buying_price_list = args.buying_price_list or frappe.db.get_single_value( + "Buying Settings", "buying_price_list" ) set_missing_values(source, target_doc) @@ -399,7 +399,7 @@ def create_supplier_quotation(doc): "currency": doc.get("currency") or get_party_account_currency("Supplier", doc.get("supplier"), doc.get("company")), "buying_price_list": doc.get("buying_price_list") - or frappe.db.get_value("Buying Settings", None, "buying_price_list"), + or frappe.db.get_single_value("Buying Settings", "buying_price_list"), } ) add_items(sq_doc, doc.get("supplier"), doc.get("items")) diff --git a/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py b/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py index 8ebca549a0..ba1fae925e 100644 --- a/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py +++ b/erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py @@ -129,9 +129,7 @@ class TallyMigration(Document): self.default_cost_center, self.default_round_off_account = frappe.db.get_value( "Company", self.erpnext_company, ["cost_center", "round_off_account"] ) - self.default_warehouse = frappe.db.get_value( - "Stock Settings", "Stock Settings", "default_warehouse" - ) + self.default_warehouse = frappe.db.get_single_value("Stock Settings", "default_warehouse") def _process_master_data(self): def get_company_name(collection): diff --git a/erpnext/manufacturing/doctype/workstation/workstation.py b/erpnext/manufacturing/doctype/workstation/workstation.py index 0a247fc431..0f05eaac00 100644 --- a/erpnext/manufacturing/doctype/workstation/workstation.py +++ b/erpnext/manufacturing/doctype/workstation/workstation.py @@ -156,7 +156,7 @@ def check_if_within_operating_hours(workstation, operation, from_datetime, to_da if not frappe.db.get_single_value("Manufacturing Settings", "allow_production_on_holidays"): check_workstation_for_holiday(workstation, from_datetime, to_datetime) - if not cint(frappe.db.get_value("Manufacturing Settings", None, "allow_overtime")): + if not cint(frappe.db.get_single_value("Manufacturing Settings", "allow_overtime")): is_within_operating_hours(workstation, operation, from_datetime, to_datetime) diff --git a/erpnext/patches/v13_0/modify_invalid_gain_loss_gl_entries.py b/erpnext/patches/v13_0/modify_invalid_gain_loss_gl_entries.py index 0f77afda78..8e58d79b92 100644 --- a/erpnext/patches/v13_0/modify_invalid_gain_loss_gl_entries.py +++ b/erpnext/patches/v13_0/modify_invalid_gain_loss_gl_entries.py @@ -45,7 +45,7 @@ def execute(): message=json.dumps(purchase_invoices + sales_invoices, indent=2), ) - acc_frozen_upto = frappe.db.get_value("Accounts Settings", None, "acc_frozen_upto") + acc_frozen_upto = frappe.db.get_single_value("Accounts Settings", "acc_frozen_upto") if acc_frozen_upto: frappe.db.set_single_value("Accounts Settings", "acc_frozen_upto", None) diff --git a/erpnext/patches/v14_0/migrate_crm_settings.py b/erpnext/patches/v14_0/migrate_crm_settings.py index 24772553d9..d093bc386e 100644 --- a/erpnext/patches/v14_0/migrate_crm_settings.py +++ b/erpnext/patches/v14_0/migrate_crm_settings.py @@ -2,8 +2,7 @@ import frappe def execute(): - settings = frappe.db.get_value( - "Selling Settings", + settings = frappe.db.get_single_value( "Selling Settings", ["campaign_naming_by", "close_opportunity_after_days", "default_valid_till"], as_dict=True, diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index a6c86a670d..ac7fdb1b45 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -35,8 +35,8 @@ class TestSalesOrder(FrappeTestCase): def setUpClass(cls): super().setUpClass() cls.unlink_setting = int( - frappe.db.get_value( - "Accounts Settings", "Accounts Settings", "unlink_advance_payment_on_cancelation_of_order" + frappe.db.get_single_value( + "Accounts Settings", "unlink_advance_payment_on_cancelation_of_order" ) ) diff --git a/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py b/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py index 98633cb719..a584d3ae53 100644 --- a/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py +++ b/erpnext/selling/report/customer_credit_balance/customer_credit_balance.py @@ -13,7 +13,7 @@ def execute(filters=None): if not filters: filters = {} # Check if customer id is according to naming series or customer name - customer_naming_type = frappe.db.get_value("Selling Settings", None, "cust_master_name") + customer_naming_type = frappe.db.get_single_value("Selling Settings", "cust_master_name") columns = get_columns(customer_naming_type) data = [] diff --git a/erpnext/startup/boot.py b/erpnext/startup/boot.py index 4b4d14f89e..4cd0ef4eef 100644 --- a/erpnext/startup/boot.py +++ b/erpnext/startup/boot.py @@ -9,7 +9,7 @@ from frappe.utils import cint def boot_session(bootinfo): """boot session - send website info if guest""" - bootinfo.custom_css = frappe.db.get_value("Style Settings", None, "custom_css") or "" + bootinfo.custom_css = frappe.db.get_single_value("Style Settings", "custom_css") or "" if frappe.session["user"] != "Guest": update_page_info(bootinfo) diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index 2d9e11ab84..feb4583436 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -635,8 +635,8 @@ class Item(Document): def recalculate_bin_qty(self, new_name): from erpnext.stock.stock_balance import repost_stock - existing_allow_negative_stock = frappe.db.get_value( - "Stock Settings", None, "allow_negative_stock" + existing_allow_negative_stock = frappe.db.get_single_value( + "Stock Settings", "allow_negative_stock" ) frappe.db.set_single_value("Stock Settings", "allow_negative_stock", 1) diff --git a/erpnext/stock/doctype/price_list/price_list.py b/erpnext/stock/doctype/price_list/price_list.py index 580c7c00b1..882c3f5c9c 100644 --- a/erpnext/stock/doctype/price_list/price_list.py +++ b/erpnext/stock/doctype/price_list/price_list.py @@ -39,11 +39,11 @@ class PriceList(Document): def set_default_if_missing(self): if cint(self.selling): - if not frappe.db.get_value("Selling Settings", None, "selling_price_list"): + if not frappe.db.get_single_value("Selling Settings", "selling_price_list"): frappe.set_value("Selling Settings", "Selling Settings", "selling_price_list", self.name) elif cint(self.buying): - if not frappe.db.get_value("Buying Settings", None, "buying_price_list"): + if not frappe.db.get_single_value("Buying Settings", "buying_price_list"): frappe.set_value("Buying Settings", "Buying Settings", "buying_price_list", self.name) def update_item_price(self): diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index c7e36e9904..5cfa739242 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -302,7 +302,7 @@ class PurchaseReceipt(BuyingController): ) def po_required(self): - if frappe.db.get_value("Buying Settings", None, "po_required") == "Yes": + if frappe.db.get_single_value("Buying Settings", "po_required") == "Yes": for d in self.get("items"): if not d.purchase_order: frappe.throw(_("Purchase Order number required for Item {0}").format(d.item_code)) diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py index 79b8ee30cf..909aa36710 100644 --- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py +++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py @@ -140,11 +140,8 @@ class RepostItemValuation(Document): return query[0][0] if query else None def validate_accounts_freeze(self): - acc_settings = frappe.db.get_value( - "Accounts Settings", - "Accounts Settings", - ["acc_frozen_upto", "frozen_accounts_modifier"], - as_dict=1, + acc_settings = frappe.db.get_single_value( + "Accounts Settings", ["acc_frozen_upto", "frozen_accounts_modifier"], as_dict=1 ) if not acc_settings.acc_frozen_upto: return diff --git a/erpnext/stock/reorder_item.py b/erpnext/stock/reorder_item.py index a6f52f3731..4cd9cbb9d5 100644 --- a/erpnext/stock/reorder_item.py +++ b/erpnext/stock/reorder_item.py @@ -18,7 +18,7 @@ def reorder_item(): if not (frappe.db.a_row_exists("Company") and frappe.db.a_row_exists("Fiscal Year")): return - if cint(frappe.db.get_value("Stock Settings", None, "auto_indent")): + if cint(frappe.db.get_single_value("Stock Settings", "auto_indent")): return _reorder_item() @@ -212,7 +212,7 @@ def create_material_request(material_requests): if mr_list: if getattr(frappe.local, "reorder_email_notify", None) is None: frappe.local.reorder_email_notify = cint( - frappe.db.get_value("Stock Settings", None, "reorder_email_notify") + frappe.db.get_single_value("Stock Settings", "reorder_email_notify") ) if frappe.local.reorder_email_notify: diff --git a/erpnext/stock/stock_balance.py b/erpnext/stock/stock_balance.py index a4fe2ee52f..ba03ff2ad7 100644 --- a/erpnext/stock/stock_balance.py +++ b/erpnext/stock/stock_balance.py @@ -15,8 +15,8 @@ def repost(only_actual=False, allow_negative_stock=False, allow_zero_rate=False, frappe.db.auto_commit_on_many_writes = 1 if allow_negative_stock: - existing_allow_negative_stock = frappe.db.get_value( - "Stock Settings", None, "allow_negative_stock" + existing_allow_negative_stock = frappe.db.get_single_value( + "Stock Settings", "allow_negative_stock" ) frappe.db.set_single_value("Stock Settings", "allow_negative_stock", 1) diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py index 4b0e2845c4..f29e7ea6a1 100644 --- a/erpnext/stock/utils.py +++ b/erpnext/stock/utils.py @@ -338,7 +338,7 @@ def get_valuation_method(item_code): val_method = frappe.db.get_value("Item", item_code, "valuation_method", cache=True) if not val_method: val_method = ( - frappe.db.get_value("Stock Settings", None, "valuation_method", cache=True) or "FIFO" + frappe.db.get_single_value("Stock Settings", "valuation_method", cache=True) or "FIFO" ) return val_method diff --git a/erpnext/support/doctype/issue/issue.py b/erpnext/support/doctype/issue/issue.py index c03fb3ea1f..dc1529b26f 100644 --- a/erpnext/support/doctype/issue/issue.py +++ b/erpnext/support/doctype/issue/issue.py @@ -230,7 +230,7 @@ def set_status(name, status): def auto_close_tickets(): """Auto-close replied support tickets after 7 days""" auto_close_after_days = ( - frappe.db.get_value("Support Settings", "Support Settings", "close_issue_after_days") or 7 + frappe.db.get_single_value("Support Settings", "close_issue_after_days") or 7 ) table = frappe.qb.DocType("Issue") diff --git a/erpnext/utilities/doctype/video/video.py b/erpnext/utilities/doctype/video/video.py index 1a9fe19732..7a04329cb9 100644 --- a/erpnext/utilities/doctype/video/video.py +++ b/erpnext/utilities/doctype/video/video.py @@ -78,8 +78,8 @@ def get_frequency(value): def update_youtube_data(): # Called every 30 minutes via hooks - enable_youtube_tracking, frequency = frappe.db.get_value( - "Video Settings", "Video Settings", ["enable_youtube_tracking", "frequency"] + enable_youtube_tracking, frequency = frappe.db.get_single_value( + "Video Settings", ["enable_youtube_tracking", "frequency"] ) if not cint(enable_youtube_tracking): From b897225136cdbbb0a8369343a589dabb3a556b0a Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Tue, 9 Jan 2024 22:04:24 +0530 Subject: [PATCH 205/205] fix: Remove reference to non-existing doctype --- erpnext/crm/doctype/appointment/appointment.py | 2 +- erpnext/startup/boot.py | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/erpnext/crm/doctype/appointment/appointment.py b/erpnext/crm/doctype/appointment/appointment.py index a735510d7d..541f77b1ba 100644 --- a/erpnext/crm/doctype/appointment/appointment.py +++ b/erpnext/crm/doctype/appointment/appointment.py @@ -76,7 +76,7 @@ class Appointment(Document): self.create_calendar_event() else: # Set status to unverified - self.status = "Unverified" + self.db_set("status", "Unverified") # Send email to confirm self.send_confirmation_email() diff --git a/erpnext/startup/boot.py b/erpnext/startup/boot.py index 4cd0ef4eef..d2be1a0242 100644 --- a/erpnext/startup/boot.py +++ b/erpnext/startup/boot.py @@ -9,8 +9,6 @@ from frappe.utils import cint def boot_session(bootinfo): """boot session - send website info if guest""" - bootinfo.custom_css = frappe.db.get_single_value("Style Settings", "custom_css") or "" - if frappe.session["user"] != "Guest": update_page_info(bootinfo)