Compare commits

..

1 Commits

Author SHA1 Message Date
mahsem
4c643c7591 fix: add doc.status to translation from POS
(cherry picked from commit 94d7e5964b)

# Conflicts:
#	.editorconfig
#	.git-blame-ignore-revs
#	.github/helper/documentation.py
#	.github/helper/install.sh
#	.github/stale.yml
#	.github/workflows/linters.yml
#	.github/workflows/patch.yml
#	.github/workflows/release.yml
#	.github/workflows/release_notes.yml
#	.github/workflows/server-tests-mariadb.yml
#	.github/workflows/server-tests-postgres.yml
#	.gitignore
#	.mergify.yml
#	.releaserc
#	CODEOWNERS
#	README.md
#	erpnext/__init__.py
#	erpnext/accounts/deferred_revenue.py
#	erpnext/accounts/doctype/account/account.json
#	erpnext/accounts/doctype/account/account.py
#	erpnext/accounts/doctype/account/account_tree.js
#	erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py
#	erpnext/accounts/doctype/account/chart_of_accounts/verified/de_kontenplan_SKR04.json
#	erpnext/accounts/doctype/account/chart_of_accounts/verified/hu_chart_of_accounts_for_microenterprises_with_account_number.json
#	erpnext/accounts/doctype/account/chart_of_accounts/verified/in_standard_chart_of_accounts.json
#	erpnext/accounts/doctype/account/chart_of_accounts/verified/ni_catalogo_de_cuentas.json
#	erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts.py
#	erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts_with_account_number.py
#	erpnext/accounts/doctype/account/test_account.py
#	erpnext/accounts/doctype/account_closing_balance/account_closing_balance.json
#	erpnext/accounts/doctype/account_closing_balance/test_account_closing_balance.py
#	erpnext/accounts/doctype/accounting_dimension/accounting_dimension.json
#	erpnext/accounts/doctype/accounting_dimension/test_accounting_dimension.py
#	erpnext/accounts/doctype/accounting_dimension_detail/accounting_dimension_detail.json
#	erpnext/accounts/doctype/accounting_dimension_filter/accounting_dimension_filter.json
#	erpnext/accounts/doctype/accounting_dimension_filter/accounting_dimension_filter.py
#	erpnext/accounts/doctype/accounting_dimension_filter/test_accounting_dimension_filter.py
#	erpnext/accounts/doctype/accounting_period/accounting_period.json
#	erpnext/accounts/doctype/accounting_period/test_accounting_period.py
#	erpnext/accounts/doctype/accounts_settings/accounts_settings.json
#	erpnext/accounts/doctype/accounts_settings/test_accounts_settings.py
#	erpnext/accounts/doctype/advance_payment_ledger_entry/test_advance_payment_ledger_entry.py
#	erpnext/accounts/doctype/advance_tax/advance_tax.json
#	erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.json
#	erpnext/accounts/doctype/advance_taxes_and_charges/advance_taxes_and_charges.py
#	erpnext/accounts/doctype/allowed_dimension/allowed_dimension.json
#	erpnext/accounts/doctype/allowed_to_transact_with/allowed_to_transact_with.json
#	erpnext/accounts/doctype/applicable_on_account/applicable_on_account.json
#	erpnext/accounts/doctype/bank/bank.json
#	erpnext/accounts/doctype/bank/test_bank.py
#	erpnext/accounts/doctype/bank_account/bank_account.json
#	erpnext/accounts/doctype/bank_account/bank_account.py
#	erpnext/accounts/doctype/bank_account/test_bank_account.py
#	erpnext/accounts/doctype/bank_account_subtype/bank_account_subtype.json
#	erpnext/accounts/doctype/bank_account_subtype/test_bank_account_subtype.py
#	erpnext/accounts/doctype/bank_account_type/bank_account_type.json
#	erpnext/accounts/doctype/bank_account_type/test_bank_account_type.py
#	erpnext/accounts/doctype/bank_clearance/bank_clearance.json
#	erpnext/accounts/doctype/bank_clearance/test_bank_clearance.py
#	erpnext/accounts/doctype/bank_clearance_detail/bank_clearance_detail.json
#	erpnext/accounts/doctype/bank_guarantee/bank_guarantee.json
#	erpnext/accounts/doctype/bank_guarantee/bank_guarantee.py
#	erpnext/accounts/doctype/bank_guarantee/test_bank_guarantee.py
#	erpnext/accounts/doctype/bank_reconciliation_tool/bank_reconciliation_tool.json
#	erpnext/accounts/doctype/bank_reconciliation_tool/test_bank_reconciliation_tool.py
#	erpnext/accounts/doctype/bank_statement_import/bank_statement_import.js
#	erpnext/accounts/doctype/bank_statement_import/bank_statement_import.json
#	erpnext/accounts/doctype/bank_statement_import/bank_statement_import.py
#	erpnext/accounts/doctype/bank_statement_import/test_bank_statement_import.py
#	erpnext/accounts/doctype/bank_transaction/auto_match_party.py
#	erpnext/accounts/doctype/bank_transaction/test_auto_match_party.py
#	erpnext/accounts/doctype/bank_transaction/test_bank_transaction.py
#	erpnext/accounts/doctype/bank_transaction_mapping/bank_transaction_mapping.json
#	erpnext/accounts/doctype/bank_transaction_payments/bank_transaction_payments.json
#	erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.json
#	erpnext/accounts/doctype/bisect_accounting_statements/bisect_accounting_statements.py
#	erpnext/accounts/doctype/bisect_accounting_statements/test_bisect_accounting_statements.py
#	erpnext/accounts/doctype/bisect_nodes/bisect_nodes.json
#	erpnext/accounts/doctype/bisect_nodes/test_bisect_nodes.py
#	erpnext/accounts/doctype/budget/budget.json
#	erpnext/accounts/doctype/budget/test_budget.py
#	erpnext/accounts/doctype/budget_account/budget_account.json
#	erpnext/accounts/doctype/campaign_item/campaign_item.json
#	erpnext/accounts/doctype/cashier_closing/cashier_closing.json
#	erpnext/accounts/doctype/cashier_closing/test_cashier_closing.py
#	erpnext/accounts/doctype/cashier_closing_payments/cashier_closing_payments.json
#	erpnext/accounts/doctype/chart_of_accounts_importer/chart_of_accounts_importer.json
#	erpnext/accounts/doctype/chart_of_accounts_importer/test_chart_of_accounts_importer.py
#	erpnext/accounts/doctype/cheque_print_template/cheque_print_template.json
#	erpnext/accounts/doctype/cheque_print_template/test_cheque_print_template.py
#	erpnext/accounts/doctype/closed_document/closed_document.json
#	erpnext/accounts/doctype/cost_center/cost_center.json
#	erpnext/accounts/doctype/cost_center/test_cost_center.py
#	erpnext/accounts/doctype/cost_center_allocation/cost_center_allocation.json
#	erpnext/accounts/doctype/cost_center_allocation/test_cost_center_allocation.py
#	erpnext/accounts/doctype/cost_center_allocation_percentage/cost_center_allocation_percentage.json
#	erpnext/accounts/doctype/coupon_code/coupon_code.json
#	erpnext/accounts/doctype/coupon_code/coupon_code.py
#	erpnext/accounts/doctype/coupon_code/test_coupon_code.py
#	erpnext/accounts/doctype/currency_exchange_settings/currency_exchange_settings.json
#	erpnext/accounts/doctype/currency_exchange_settings/test_currency_exchange_settings.py
#	erpnext/accounts/doctype/currency_exchange_settings_details/currency_exchange_settings_details.json
#	erpnext/accounts/doctype/currency_exchange_settings_result/currency_exchange_settings_result.json
#	erpnext/accounts/doctype/customer_group_item/customer_group_item.json
#	erpnext/accounts/doctype/customer_item/customer_item.json
#	erpnext/accounts/doctype/discounted_invoice/discounted_invoice.json
#	erpnext/accounts/doctype/dunning/dunning.json
#	erpnext/accounts/doctype/dunning/dunning.py
#	erpnext/accounts/doctype/dunning/test_dunning.py
#	erpnext/accounts/doctype/dunning_letter_text/dunning_letter_text.json
#	erpnext/accounts/doctype/dunning_type/dunning_type.json
#	erpnext/accounts/doctype/dunning_type/test_dunning_type.py
#	erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.js
#	erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.json
#	erpnext/accounts/doctype/exchange_rate_revaluation/exchange_rate_revaluation.py
#	erpnext/accounts/doctype/exchange_rate_revaluation/test_exchange_rate_revaluation.py
#	erpnext/accounts/doctype/exchange_rate_revaluation_account/exchange_rate_revaluation_account.json
#	erpnext/accounts/doctype/finance_book/finance_book.json
#	erpnext/accounts/doctype/finance_book/test_finance_book.py
#	erpnext/accounts/doctype/fiscal_year/fiscal_year.json
#	erpnext/accounts/doctype/fiscal_year/test_fiscal_year.py
#	erpnext/accounts/doctype/fiscal_year_company/fiscal_year_company.json
#	erpnext/accounts/doctype/gl_entry/test_gl_entry.py
#	erpnext/accounts/doctype/invoice_discounting/invoice_discounting.js
#	erpnext/accounts/doctype/invoice_discounting/invoice_discounting.json
#	erpnext/accounts/doctype/invoice_discounting/test_invoice_discounting.py
#	erpnext/accounts/doctype/item_tax_template/item_tax_template.json
#	erpnext/accounts/doctype/item_tax_template/test_item_tax_template.py
#	erpnext/accounts/doctype/item_tax_template_detail/item_tax_template_detail.json
#	erpnext/accounts/doctype/journal_entry/journal_entry.js
#	erpnext/accounts/doctype/journal_entry/journal_entry.json
#	erpnext/accounts/doctype/journal_entry/journal_entry.py
#	erpnext/accounts/doctype/journal_entry/journal_entry_list.js
#	erpnext/accounts/doctype/journal_entry/test_journal_entry.py
#	erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json
#	erpnext/accounts/doctype/journal_entry_template/journal_entry_template.json
#	erpnext/accounts/doctype/journal_entry_template/test_journal_entry_template.py
#	erpnext/accounts/doctype/journal_entry_template_account/journal_entry_template_account.json
#	erpnext/accounts/doctype/ledger_health/test_ledger_health.py
#	erpnext/accounts/doctype/ledger_health_monitor/test_ledger_health_monitor.py
#	erpnext/accounts/doctype/ledger_merge/ledger_merge.json
#	erpnext/accounts/doctype/ledger_merge/test_ledger_merge.py
#	erpnext/accounts/doctype/ledger_merge_accounts/ledger_merge_accounts.json
#	erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.json
#	erpnext/accounts/doctype/loyalty_point_entry/loyalty_point_entry.py
#	erpnext/accounts/doctype/loyalty_point_entry/test_loyalty_point_entry.py
#	erpnext/accounts/doctype/loyalty_point_entry_redemption/loyalty_point_entry_redemption.json
#	erpnext/accounts/doctype/loyalty_program/loyalty_program.json
#	erpnext/accounts/doctype/loyalty_program/loyalty_program.py
#	erpnext/accounts/doctype/loyalty_program/test_loyalty_program.py
#	erpnext/accounts/doctype/loyalty_program_collection/loyalty_program_collection.json
#	erpnext/accounts/doctype/mode_of_payment/mode_of_payment.json
#	erpnext/accounts/doctype/mode_of_payment/test_mode_of_payment.py
#	erpnext/accounts/doctype/mode_of_payment_account/mode_of_payment_account.json
#	erpnext/accounts/doctype/monthly_distribution/monthly_distribution.json
#	erpnext/accounts/doctype/monthly_distribution/test_monthly_distribution.py
#	erpnext/accounts/doctype/monthly_distribution_percentage/monthly_distribution_percentage.json
#	erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.json
#	erpnext/accounts/doctype/opening_invoice_creation_tool/opening_invoice_creation_tool.py
#	erpnext/accounts/doctype/opening_invoice_creation_tool/test_opening_invoice_creation_tool.py
#	erpnext/accounts/doctype/opening_invoice_creation_tool_item/opening_invoice_creation_tool_item.json
#	erpnext/accounts/doctype/overdue_payment/overdue_payment.json
#	erpnext/accounts/doctype/party_account/party_account.json
#	erpnext/accounts/doctype/party_link/party_link.json
#	erpnext/accounts/doctype/party_link/test_party_link.py
#	erpnext/accounts/doctype/payment_entry/payment_entry.js
#	erpnext/accounts/doctype/payment_entry/payment_entry.json
#	erpnext/accounts/doctype/payment_entry/payment_entry.py
#	erpnext/accounts/doctype/payment_entry/test_payment_entry.py
#	erpnext/accounts/doctype/payment_entry_deduction/payment_entry_deduction.json
#	erpnext/accounts/doctype/payment_entry_reference/payment_entry_reference.json
#	erpnext/accounts/doctype/payment_gateway_account/payment_gateway_account.json
#	erpnext/accounts/doctype/payment_gateway_account/test_payment_gateway_account.py
#	erpnext/accounts/doctype/payment_ledger_entry/payment_ledger_entry.json
#	erpnext/accounts/doctype/payment_ledger_entry/test_payment_ledger_entry.py
#	erpnext/accounts/doctype/payment_order/payment_order.json
#	erpnext/accounts/doctype/payment_order/test_payment_order.py
#	erpnext/accounts/doctype/payment_order_reference/payment_order_reference.json
#	erpnext/accounts/doctype/payment_reconciliation/payment_reconciliation.json
#	erpnext/accounts/doctype/payment_reconciliation/test_payment_reconciliation.py
#	erpnext/accounts/doctype/payment_reconciliation_allocation/payment_reconciliation_allocation.json
#	erpnext/accounts/doctype/payment_reconciliation_invoice/payment_reconciliation_invoice.json
#	erpnext/accounts/doctype/payment_reconciliation_payment/payment_reconciliation_payment.json
#	erpnext/accounts/doctype/payment_request/payment_request.js
#	erpnext/accounts/doctype/payment_request/payment_request.json
#	erpnext/accounts/doctype/payment_request/payment_request.py
#	erpnext/accounts/doctype/payment_request/test_payment_request.py
#	erpnext/accounts/doctype/payment_schedule/payment_schedule.json
#	erpnext/accounts/doctype/payment_term/payment_term.json
#	erpnext/accounts/doctype/payment_term/test_payment_term.py
#	erpnext/accounts/doctype/payment_terms_template/payment_terms_template.json
#	erpnext/accounts/doctype/payment_terms_template/test_payment_terms_template.py
#	erpnext/accounts/doctype/payment_terms_template_detail/payment_terms_template_detail.json
#	erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.json
#	erpnext/accounts/doctype/period_closing_voucher/test_period_closing_voucher.py
#	erpnext/accounts/doctype/pos_closing_entry/pos_closing_entry.json
#	erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py
#	erpnext/accounts/doctype/pos_closing_entry_detail/pos_closing_entry_detail.json
#	erpnext/accounts/doctype/pos_closing_entry_taxes/pos_closing_entry_taxes.json
#	erpnext/accounts/doctype/pos_customer_group/pos_customer_group.json
#	erpnext/accounts/doctype/pos_field/pos_field.json
#	erpnext/accounts/doctype/pos_invoice/pos_invoice.js
#	erpnext/accounts/doctype/pos_invoice/pos_invoice.json
#	erpnext/accounts/doctype/pos_invoice/pos_invoice.py
#	erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py
#	erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.json
#	erpnext/accounts/doctype/pos_invoice_item/pos_invoice_item.py
#	erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.json
#	erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py
#	erpnext/accounts/doctype/pos_invoice_merge_log/test_pos_invoice_merge_log.py
#	erpnext/accounts/doctype/pos_invoice_reference/pos_invoice_reference.json
#	erpnext/accounts/doctype/pos_item_group/pos_item_group.json
#	erpnext/accounts/doctype/pos_opening_entry/pos_opening_entry.json
#	erpnext/accounts/doctype/pos_opening_entry/test_pos_opening_entry.py
#	erpnext/accounts/doctype/pos_opening_entry_detail/pos_opening_entry_detail.json
#	erpnext/accounts/doctype/pos_payment_method/pos_payment_method.json
#	erpnext/accounts/doctype/pos_profile/pos_profile.json
#	erpnext/accounts/doctype/pos_profile/pos_profile.py
#	erpnext/accounts/doctype/pos_profile/test_pos_profile.py
#	erpnext/accounts/doctype/pos_profile_user/pos_profile_user.json
#	erpnext/accounts/doctype/pos_profile_user/test_pos_profile_user.py
#	erpnext/accounts/doctype/pos_search_fields/pos_search_fields.json
#	erpnext/accounts/doctype/pos_settings/pos_settings.json
#	erpnext/accounts/doctype/pos_settings/test_pos_settings.py
#	erpnext/accounts/doctype/pricing_rule/pricing_rule.json
#	erpnext/accounts/doctype/pricing_rule/pricing_rule.py
#	erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py
#	erpnext/accounts/doctype/pricing_rule/utils.py
#	erpnext/accounts/doctype/pricing_rule_brand/pricing_rule_brand.json
#	erpnext/accounts/doctype/pricing_rule_detail/pricing_rule_detail.json
#	erpnext/accounts/doctype/pricing_rule_item_code/pricing_rule_item_code.json
#	erpnext/accounts/doctype/pricing_rule_item_group/pricing_rule_item_group.json
#	erpnext/accounts/doctype/process_deferred_accounting/process_deferred_accounting.json
#	erpnext/accounts/doctype/process_deferred_accounting/test_process_deferred_accounting.py
#	erpnext/accounts/doctype/process_payment_reconciliation/process_payment_reconciliation.json
#	erpnext/accounts/doctype/process_payment_reconciliation/process_payment_reconciliation.py
#	erpnext/accounts/doctype/process_payment_reconciliation/test_process_payment_reconciliation.py
#	erpnext/accounts/doctype/process_payment_reconciliation_log/process_payment_reconciliation_log.json
#	erpnext/accounts/doctype/process_payment_reconciliation_log/test_process_payment_reconciliation_log.py
#	erpnext/accounts/doctype/process_payment_reconciliation_log_allocations/process_payment_reconciliation_log_allocations.json
#	erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.html
#	erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts.json
#	erpnext/accounts/doctype/process_statement_of_accounts/process_statement_of_accounts_accounts_receivable.html
#	erpnext/accounts/doctype/process_statement_of_accounts/test_process_statement_of_accounts.py
#	erpnext/accounts/doctype/process_statement_of_accounts_customer/process_statement_of_accounts_customer.json
#	erpnext/accounts/doctype/process_subscription/process_subscription.json
#	erpnext/accounts/doctype/process_subscription/test_process_subscription.py
#	erpnext/accounts/doctype/promotional_scheme/promotional_scheme.json
#	erpnext/accounts/doctype/promotional_scheme/test_promotional_scheme.py
#	erpnext/accounts/doctype/promotional_scheme_price_discount/promotional_scheme_price_discount.json
#	erpnext/accounts/doctype/promotional_scheme_product_discount/promotional_scheme_product_discount.json
#	erpnext/accounts/doctype/psoa_cost_center/psoa_cost_center.json
#	erpnext/accounts/doctype/psoa_project/psoa_project.json
#	erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
#	erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json
#	erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py
#	erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py
#	erpnext/accounts/doctype/purchase_invoice_advance/purchase_invoice_advance.json
#	erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json
#	erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.py
#	erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.json
#	erpnext/accounts/doctype/purchase_taxes_and_charges/purchase_taxes_and_charges.py
#	erpnext/accounts/doctype/purchase_taxes_and_charges_template/purchase_taxes_and_charges_template.json
#	erpnext/accounts/doctype/purchase_taxes_and_charges_template/test_purchase_taxes_and_charges_template.py
#	erpnext/accounts/doctype/repost_accounting_ledger/repost_accounting_ledger.json
#	erpnext/accounts/doctype/repost_accounting_ledger/test_repost_accounting_ledger.py
#	erpnext/accounts/doctype/repost_accounting_ledger_items/repost_accounting_ledger_items.json
#	erpnext/accounts/doctype/repost_accounting_ledger_settings/repost_accounting_ledger_settings.json
#	erpnext/accounts/doctype/repost_accounting_ledger_settings/test_repost_accounting_ledger_settings.py
#	erpnext/accounts/doctype/repost_allowed_types/repost_allowed_types.json
#	erpnext/accounts/doctype/repost_payment_ledger/repost_payment_ledger.json
#	erpnext/accounts/doctype/repost_payment_ledger/test_repost_payment_ledger.py
#	erpnext/accounts/doctype/repost_payment_ledger_items/repost_payment_ledger_items.json
#	erpnext/accounts/doctype/sales_invoice/sales_invoice.js
#	erpnext/accounts/doctype/sales_invoice/sales_invoice.json
#	erpnext/accounts/doctype/sales_invoice/sales_invoice.py
#	erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py
#	erpnext/accounts/doctype/sales_invoice_advance/sales_invoice_advance.json
#	erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json
#	erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.py
#	erpnext/accounts/doctype/sales_invoice_payment/sales_invoice_payment.json
#	erpnext/accounts/doctype/sales_invoice_timesheet/sales_invoice_timesheet.json
#	erpnext/accounts/doctype/sales_partner_item/sales_partner_item.json
#	erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json
#	erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.py
#	erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.json
#	erpnext/accounts/doctype/sales_taxes_and_charges_template/sales_taxes_and_charges_template.py
#	erpnext/accounts/doctype/sales_taxes_and_charges_template/test_sales_taxes_and_charges_template.py
#	erpnext/accounts/doctype/share_balance/share_balance.json
#	erpnext/accounts/doctype/share_transfer/share_transfer.json
#	erpnext/accounts/doctype/share_transfer/test_share_transfer.py
#	erpnext/accounts/doctype/share_type/share_type.json
#	erpnext/accounts/doctype/share_type/test_share_type.py
#	erpnext/accounts/doctype/shareholder/shareholder.json
#	erpnext/accounts/doctype/shareholder/test_shareholder.py
#	erpnext/accounts/doctype/shipping_rule/shipping_rule.json
#	erpnext/accounts/doctype/shipping_rule/shipping_rule.py
#	erpnext/accounts/doctype/shipping_rule/test_shipping_rule.py
#	erpnext/accounts/doctype/shipping_rule_condition/shipping_rule_condition.json
#	erpnext/accounts/doctype/shipping_rule_country/shipping_rule_country.json
#	erpnext/accounts/doctype/south_africa_vat_account/south_africa_vat_account.json
#	erpnext/accounts/doctype/subscription/subscription.json
#	erpnext/accounts/doctype/subscription/subscription.py
#	erpnext/accounts/doctype/subscription/subscription_list.js
#	erpnext/accounts/doctype/subscription/test_subscription.py
#	erpnext/accounts/doctype/subscription_invoice/subscription_invoice.json
#	erpnext/accounts/doctype/subscription_invoice/test_subscription_invoice.py
#	erpnext/accounts/doctype/subscription_plan/subscription_plan.json
#	erpnext/accounts/doctype/subscription_plan/test_subscription_plan.py
#	erpnext/accounts/doctype/subscription_plan_detail/subscription_plan_detail.json
#	erpnext/accounts/doctype/subscription_settings/subscription_settings.json
#	erpnext/accounts/doctype/subscription_settings/test_subscription_settings.py
#	erpnext/accounts/doctype/supplier_group_item/supplier_group_item.json
#	erpnext/accounts/doctype/supplier_item/supplier_item.json
#	erpnext/accounts/doctype/tax_category/tax_category.json
#	erpnext/accounts/doctype/tax_category/test_tax_category.py
#	erpnext/accounts/doctype/tax_rule/tax_rule.json
#	erpnext/accounts/doctype/tax_rule/tax_rule.py
#	erpnext/accounts/doctype/tax_rule/test_tax_rule.py
#	erpnext/accounts/doctype/tax_withheld_vouchers/tax_withheld_vouchers.json
#	erpnext/accounts/doctype/tax_withholding_account/tax_withholding_account.json
#	erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.json
#	erpnext/accounts/doctype/tax_withholding_category/test_tax_withholding_category.py
#	erpnext/accounts/doctype/tax_withholding_rate/tax_withholding_rate.json
#	erpnext/accounts/doctype/territory_item/territory_item.json
#	erpnext/accounts/doctype/transaction_deletion_record_details/transaction_deletion_record_details.json
#	erpnext/accounts/doctype/unreconcile_payment/test_unreconcile_payment.py
#	erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.json
#	erpnext/accounts/doctype/unreconcile_payment/unreconcile_payment.py
#	erpnext/accounts/doctype/unreconcile_payment_entries/unreconcile_payment_entries.json
#	erpnext/accounts/general_ledger.py
#	erpnext/accounts/notification/notification_for_new_fiscal_year/notification_for_new_fiscal_year.json
#	erpnext/accounts/number_card/total_incoming_bills/total_incoming_bills.json
#	erpnext/accounts/number_card/total_incoming_payment/total_incoming_payment.json
#	erpnext/accounts/number_card/total_outgoing_bills/total_outgoing_bills.json
#	erpnext/accounts/number_card/total_outgoing_payment/total_outgoing_payment.json
#	erpnext/accounts/party.py
#	erpnext/accounts/print_format/dunning_letter/dunning_letter.json
#	erpnext/accounts/print_format/sales_invoice_return/sales_invoice_return.html
#	erpnext/accounts/report/account_balance/account_balance.js
#	erpnext/accounts/report/account_balance/account_balance.py
#	erpnext/accounts/report/account_balance/test_account_balance.py
#	erpnext/accounts/report/accounts_payable/accounts_payable.js
#	erpnext/accounts/report/accounts_payable/test_accounts_payable.py
#	erpnext/accounts/report/accounts_receivable/accounts_receivable.js
#	erpnext/accounts/report/accounts_receivable/accounts_receivable.py
#	erpnext/accounts/report/accounts_receivable/test_accounts_receivable.py
#	erpnext/accounts/report/accounts_receivable_summary/accounts_receivable_summary.py
#	erpnext/accounts/report/accounts_receivable_summary/test_accounts_receivable_summary.py
#	erpnext/accounts/report/balance_sheet/test_balance_sheet.py
#	erpnext/accounts/report/bank_reconciliation_statement/test_bank_reconciliation_statement.py
#	erpnext/accounts/report/cash_flow/cash_flow.py
#	erpnext/accounts/report/consolidated_financial_statement/consolidated_financial_statement.py
#	erpnext/accounts/report/customer_ledger_summary/customer_ledger_summary.py
#	erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.py
#	erpnext/accounts/report/deferred_revenue_and_expense/test_deferred_revenue_and_expense.py
#	erpnext/accounts/report/general_and_payment_ledger_comparison/test_general_and_payment_ledger_comparison.py
#	erpnext/accounts/report/general_ledger/general_ledger.html
#	erpnext/accounts/report/general_ledger/general_ledger.py
#	erpnext/accounts/report/general_ledger/test_general_ledger.py
#	erpnext/accounts/report/gross_and_net_profit_report/gross_and_net_profit_report.py
#	erpnext/accounts/report/gross_profit/test_gross_profit.py
#	erpnext/accounts/report/item_wise_purchase_register/test_item_wise_purchase_register.py
#	erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.js
#	erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py
#	erpnext/accounts/report/item_wise_sales_register/test_item_wise_sales_register.py
#	erpnext/accounts/report/payment_ledger/test_payment_ledger.py
#	erpnext/accounts/report/profit_and_loss_statement/test_profit_and_loss_statement.py
#	erpnext/accounts/report/purchase_register/test_purchase_register.py
#	erpnext/accounts/report/sales_payment_summary/test_sales_payment_summary.py
#	erpnext/accounts/report/sales_register/test_sales_register.py
#	erpnext/accounts/report/tax_withholding_details/tax_withholding_details.py
#	erpnext/accounts/report/tax_withholding_details/test_tax_withholding_details.py
#	erpnext/accounts/report/trial_balance/test_trial_balance.py
#	erpnext/accounts/test/accounts_mixin.py
#	erpnext/accounts/test/test_reports.py
#	erpnext/accounts/test/test_utils.py
#	erpnext/accounts/test_party.py
#	erpnext/accounts/utils.py
#	erpnext/assets/doctype/asset/asset.js
#	erpnext/assets/doctype/asset/asset.json
#	erpnext/assets/doctype/asset/asset.py
#	erpnext/assets/doctype/asset/depreciation.py
#	erpnext/assets/doctype/asset/test_asset.py
#	erpnext/assets/doctype/asset_activity/asset_activity.json
#	erpnext/assets/doctype/asset_activity/test_asset_activity.py
#	erpnext/assets/doctype/asset_capitalization/asset_capitalization.js
#	erpnext/assets/doctype/asset_capitalization/asset_capitalization.json
#	erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
#	erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py
#	erpnext/assets/doctype/asset_capitalization_asset_item/asset_capitalization_asset_item.json
#	erpnext/assets/doctype/asset_capitalization_service_item/asset_capitalization_service_item.json
#	erpnext/assets/doctype/asset_capitalization_stock_item/asset_capitalization_stock_item.json
#	erpnext/assets/doctype/asset_category/asset_category.json
#	erpnext/assets/doctype/asset_category/test_asset_category.py
#	erpnext/assets/doctype/asset_category_account/asset_category_account.json
#	erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.json
#	erpnext/assets/doctype/asset_depreciation_schedule/test_asset_depreciation_schedule.py
#	erpnext/assets/doctype/asset_finance_book/asset_finance_book.json
#	erpnext/assets/doctype/asset_maintenance/asset_maintenance.json
#	erpnext/assets/doctype/asset_maintenance/asset_maintenance.py
#	erpnext/assets/doctype/asset_maintenance/test_asset_maintenance.py
#	erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.json
#	erpnext/assets/doctype/asset_maintenance_log/test_asset_maintenance_log.py
#	erpnext/assets/doctype/asset_maintenance_task/asset_maintenance_task.json
#	erpnext/assets/doctype/asset_maintenance_team/asset_maintenance_team.json
#	erpnext/assets/doctype/asset_maintenance_team/test_asset_maintenance_team.py
#	erpnext/assets/doctype/asset_movement/asset_movement.json
#	erpnext/assets/doctype/asset_movement/asset_movement.py
#	erpnext/assets/doctype/asset_movement/test_asset_movement.py
#	erpnext/assets/doctype/asset_movement_item/asset_movement_item.json
#	erpnext/assets/doctype/asset_repair/asset_repair.js
#	erpnext/assets/doctype/asset_repair/asset_repair.json
#	erpnext/assets/doctype/asset_repair/asset_repair.py
#	erpnext/assets/doctype/asset_repair/test_asset_repair.py
#	erpnext/assets/doctype/asset_repair_consumed_item/asset_repair_consumed_item.json
#	erpnext/assets/doctype/asset_shift_allocation/asset_shift_allocation.json
#	erpnext/assets/doctype/asset_shift_allocation/test_asset_shift_allocation.py
#	erpnext/assets/doctype/asset_shift_factor/asset_shift_factor.json
#	erpnext/assets/doctype/asset_shift_factor/test_asset_shift_factor.py
#	erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.js
#	erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.json
#	erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py
#	erpnext/assets/doctype/asset_value_adjustment/test_asset_value_adjustment.py
#	erpnext/assets/doctype/depreciation_schedule/depreciation_schedule.json
#	erpnext/assets/doctype/linked_location/linked_location.json
#	erpnext/assets/doctype/location/location.json
#	erpnext/assets/doctype/location/test_location.py
#	erpnext/assets/doctype/maintenance_team_member/maintenance_team_member.json
#	erpnext/assets/doctype/maintenance_team_member/test_maintenance_team_member.py
#	erpnext/assets/number_card/new_assets_(this_year)/new_assets_(this_year).json
#	erpnext/assets/report/fixed_asset_register/fixed_asset_register.py
#	erpnext/bulk_transaction/doctype/bulk_transaction_log/bulk_transaction_log.json
#	erpnext/bulk_transaction/doctype/bulk_transaction_log/test_bulk_transaction_log.py
#	erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/bulk_transaction_log_detail.json
#	erpnext/bulk_transaction/doctype/bulk_transaction_log_detail/test_bulk_transaction_log_detail.py
#	erpnext/buying/dashboard_chart/material_request_analysis/material_request_analysis.json
#	erpnext/buying/doctype/buying_settings/buying_settings.json
#	erpnext/buying/doctype/buying_settings/test_buying_settings.py
#	erpnext/buying/doctype/purchase_order/purchase_order.js
#	erpnext/buying/doctype/purchase_order/purchase_order.json
#	erpnext/buying/doctype/purchase_order/purchase_order.py
#	erpnext/buying/doctype/purchase_order/purchase_order_list.js
#	erpnext/buying/doctype/purchase_order/test_purchase_order.py
#	erpnext/buying/doctype/purchase_order_item/purchase_order_item.json
#	erpnext/buying/doctype/purchase_order_item/purchase_order_item.py
#	erpnext/buying/doctype/purchase_order_item_supplied/purchase_order_item_supplied.json
#	erpnext/buying/doctype/purchase_receipt_item_supplied/purchase_receipt_item_supplied.json
#	erpnext/buying/doctype/request_for_quotation/request_for_quotation.js
#	erpnext/buying/doctype/request_for_quotation/request_for_quotation.json
#	erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
#	erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py
#	erpnext/buying/doctype/request_for_quotation_item/request_for_quotation_item.json
#	erpnext/buying/doctype/request_for_quotation_supplier/request_for_quotation_supplier.json
#	erpnext/buying/doctype/supplier/supplier.json
#	erpnext/buying/doctype/supplier/supplier_dashboard.py
#	erpnext/buying/doctype/supplier/test_supplier.py
#	erpnext/buying/doctype/supplier_quotation/supplier_quotation.js
#	erpnext/buying/doctype/supplier_quotation/supplier_quotation.json
#	erpnext/buying/doctype/supplier_quotation/supplier_quotation.py
#	erpnext/buying/doctype/supplier_quotation/test_supplier_quotation.py
#	erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.json
#	erpnext/buying/doctype/supplier_quotation_item/supplier_quotation_item.py
#	erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.json
#	erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.py
#	erpnext/buying/doctype/supplier_scorecard/test_supplier_scorecard.py
#	erpnext/buying/doctype/supplier_scorecard_criteria/supplier_scorecard_criteria.json
#	erpnext/buying/doctype/supplier_scorecard_criteria/test_supplier_scorecard_criteria.py
#	erpnext/buying/doctype/supplier_scorecard_period/supplier_scorecard_period.json
#	erpnext/buying/doctype/supplier_scorecard_period/test_supplier_scorecard_period.py
#	erpnext/buying/doctype/supplier_scorecard_scoring_criteria/supplier_scorecard_scoring_criteria.json
#	erpnext/buying/doctype/supplier_scorecard_scoring_standing/supplier_scorecard_scoring_standing.json
#	erpnext/buying/doctype/supplier_scorecard_scoring_variable/supplier_scorecard_scoring_variable.json
#	erpnext/buying/doctype/supplier_scorecard_standing/supplier_scorecard_standing.json
#	erpnext/buying/doctype/supplier_scorecard_standing/test_supplier_scorecard_standing.py
#	erpnext/buying/doctype/supplier_scorecard_variable/supplier_scorecard_variable.json
#	erpnext/buying/doctype/supplier_scorecard_variable/supplier_scorecard_variable.py
#	erpnext/buying/doctype/supplier_scorecard_variable/test_supplier_scorecard_variable.py
#	erpnext/buying/number_card/annual_purchase/annual_purchase.json
#	erpnext/buying/number_card/purchase_orders_to_bill/purchase_orders_to_bill.json
#	erpnext/buying/number_card/purchase_orders_to_receive/purchase_orders_to_receive.json
#	erpnext/buying/report/procurement_tracker/test_procurement_tracker.py
#	erpnext/buying/report/purchase_order_analysis/purchase_order_analysis.js
#	erpnext/buying/report/requested_items_to_order_and_receive/test_requested_items_to_order_and_receive.py
#	erpnext/buying/report/subcontracted_item_to_be_received/test_subcontracted_item_to_be_received.py
#	erpnext/buying/report/subcontracted_raw_materials_to_be_transferred/test_subcontracted_raw_materials_to_be_transferred.py
#	erpnext/buying/utils.py
#	erpnext/communication/doctype/communication_medium/communication_medium.json
#	erpnext/communication/doctype/communication_medium_timeslot/communication_medium_timeslot.json
#	erpnext/controllers/accounts_controller.py
#	erpnext/controllers/buying_controller.py
#	erpnext/controllers/queries.py
#	erpnext/controllers/sales_and_purchase_return.py
#	erpnext/controllers/selling_controller.py
#	erpnext/controllers/status_updater.py
#	erpnext/controllers/stock_controller.py
#	erpnext/controllers/subcontracting_controller.py
#	erpnext/controllers/taxes_and_totals.py
#	erpnext/controllers/tests/test_accounts_controller.py
#	erpnext/controllers/tests/test_item_variant.py
#	erpnext/controllers/tests/test_mapper.py
#	erpnext/controllers/tests/test_qty_based_taxes.py
#	erpnext/controllers/tests/test_queries.py
#	erpnext/controllers/tests/test_subcontracting_controller.py
#	erpnext/controllers/tests/test_transaction_base.py
#	erpnext/controllers/website_list_for_contact.py
#	erpnext/crm/dashboard_chart/lead_source/lead_source.json
#	erpnext/crm/dashboard_chart/opportunities_via_campaigns/opportunities_via_campaigns.json
#	erpnext/crm/dashboard_chart/territory_wise_sales/territory_wise_sales.json
#	erpnext/crm/dashboard_chart/won_opportunities/won_opportunities.json
#	erpnext/crm/doctype/appointment/appointment.json
#	erpnext/crm/doctype/appointment/appointment.py
#	erpnext/crm/doctype/appointment/test_appointment.py
#	erpnext/crm/doctype/appointment_booking_settings/appointment_booking_settings.json
#	erpnext/crm/doctype/appointment_booking_settings/test_appointment_booking_settings.py
#	erpnext/crm/doctype/appointment_booking_slots/appointment_booking_slots.json
#	erpnext/crm/doctype/availability_of_slots/availability_of_slots.json
#	erpnext/crm/doctype/campaign/campaign.js
#	erpnext/crm/doctype/campaign/campaign.json
#	erpnext/crm/doctype/campaign/campaign.py
#	erpnext/crm/doctype/campaign/test_campaign.py
#	erpnext/crm/doctype/campaign_email_schedule/campaign_email_schedule.json
#	erpnext/crm/doctype/competitor/competitor.json
#	erpnext/crm/doctype/competitor/test_competitor.py
#	erpnext/crm/doctype/competitor_detail/competitor_detail.json
#	erpnext/crm/doctype/contract/contract.json
#	erpnext/crm/doctype/contract/test_contract.py
#	erpnext/crm/doctype/contract_fulfilment_checklist/contract_fulfilment_checklist.json
#	erpnext/crm/doctype/contract_fulfilment_checklist/test_contract_fulfilment_checklist.py
#	erpnext/crm/doctype/contract_template/contract_template.json
#	erpnext/crm/doctype/contract_template/test_contract_template.py
#	erpnext/crm/doctype/contract_template_fulfilment_terms/contract_template_fulfilment_terms.json
#	erpnext/crm/doctype/crm_note/crm_note.json
#	erpnext/crm/doctype/crm_settings/crm_settings.json
#	erpnext/crm/doctype/crm_settings/test_crm_settings.py
#	erpnext/crm/doctype/email_campaign/email_campaign.json
#	erpnext/crm/doctype/email_campaign/email_campaign.py
#	erpnext/crm/doctype/email_campaign/test_email_campaign.py
#	erpnext/crm/doctype/lead/lead.json
#	erpnext/crm/doctype/lead/lead.py
#	erpnext/crm/doctype/lead/test_lead.py
#	erpnext/crm/doctype/lost_reason_detail/lost_reason_detail.json
#	erpnext/crm/doctype/market_segment/market_segment.json
#	erpnext/crm/doctype/market_segment/test_market_segment.py
#	erpnext/crm/doctype/opportunity/opportunity.js
#	erpnext/crm/doctype/opportunity/opportunity.json
#	erpnext/crm/doctype/opportunity/opportunity.py
#	erpnext/crm/doctype/opportunity/test_opportunity.py
#	erpnext/crm/doctype/opportunity_item/opportunity_item.json
#	erpnext/crm/doctype/opportunity_lost_reason/opportunity_lost_reason.json
#	erpnext/crm/doctype/opportunity_lost_reason_detail/opportunity_lost_reason_detail.json
#	erpnext/crm/doctype/opportunity_type/opportunity_type.json
#	erpnext/crm/doctype/opportunity_type/test_opportunity_type.py
#	erpnext/crm/doctype/prospect/prospect.json
#	erpnext/crm/doctype/prospect/test_prospect.py
#	erpnext/crm/doctype/prospect_lead/prospect_lead.json
#	erpnext/crm/doctype/prospect_opportunity/prospect_opportunity.json
#	erpnext/crm/doctype/sales_stage/sales_stage.json
#	erpnext/crm/doctype/sales_stage/test_sales_stage.py
#	erpnext/crm/doctype/utils.py
#	erpnext/crm/number_card/new_lead_(last_1_month)/new_lead_(last_1_month).json
#	erpnext/crm/number_card/new_opportunity_(last_1_month)/new_opportunity_(last_1_month).json
#	erpnext/crm/number_card/open_opportunity/open_opportunity.json
#	erpnext/crm/number_card/won_opportunity_(last_1_month)/won_opportunity_(last_1_month).json
#	erpnext/crm/report/campaign_efficiency/campaign_efficiency.py
#	erpnext/crm/report/opportunity_summary_by_sales_stage/opportunity_summary_by_sales_stage.js
#	erpnext/crm/report/opportunity_summary_by_sales_stage/opportunity_summary_by_sales_stage.py
#	erpnext/crm/report/opportunity_summary_by_sales_stage/test_opportunity_summary_by_sales_stage.py
#	erpnext/crm/report/sales_pipeline_analytics/sales_pipeline_analytics.js
#	erpnext/crm/report/sales_pipeline_analytics/sales_pipeline_analytics.py
#	erpnext/crm/report/sales_pipeline_analytics/test_sales_pipeline_analytics.py
#	erpnext/crm/workspace/crm/crm.json
#	erpnext/edi/doctype/code_list/code_list_import.py
#	erpnext/erpnext_integrations/doctype/plaid_settings/plaid_settings.json
#	erpnext/erpnext_integrations/doctype/plaid_settings/test_plaid_settings.py
#	erpnext/erpnext_integrations/doctype/quickbooks_migrator/quickbooks_migrator.json
#	erpnext/erpnext_integrations/doctype/quickbooks_migrator/test_quickbooks_migrator.py
#	erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.json
#	erpnext/erpnext_integrations/doctype/tally_migration/tally_migration.py
#	erpnext/erpnext_integrations/doctype/tally_migration/test_tally_migration.py
#	erpnext/erpnext_integrations/utils.py
#	erpnext/hooks.py
#	erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.json
#	erpnext/maintenance/doctype/maintenance_schedule/maintenance_schedule.py
#	erpnext/maintenance/doctype/maintenance_schedule/test_maintenance_schedule.py
#	erpnext/maintenance/doctype/maintenance_schedule_detail/maintenance_schedule_detail.json
#	erpnext/maintenance/doctype/maintenance_schedule_item/maintenance_schedule_item.json
#	erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.json
#	erpnext/maintenance/doctype/maintenance_visit/maintenance_visit.py
#	erpnext/maintenance/doctype/maintenance_visit/test_maintenance_visit.py
#	erpnext/maintenance/doctype/maintenance_visit_purpose/maintenance_visit_purpose.json
#	erpnext/manufacturing/dashboard_chart/completed_operation/completed_operation.json
#	erpnext/manufacturing/dashboard_chart/produced_quantity/produced_quantity.json
#	erpnext/manufacturing/doctype/blanket_order/blanket_order.json
#	erpnext/manufacturing/doctype/blanket_order/blanket_order.py
#	erpnext/manufacturing/doctype/blanket_order/test_blanket_order.py
#	erpnext/manufacturing/doctype/blanket_order_item/blanket_order_item.json
#	erpnext/manufacturing/doctype/bom/bom.js
#	erpnext/manufacturing/doctype/bom/bom.json
#	erpnext/manufacturing/doctype/bom/bom.py
#	erpnext/manufacturing/doctype/bom/test_bom.py
#	erpnext/manufacturing/doctype/bom_creator/bom_creator.js
#	erpnext/manufacturing/doctype/bom_creator/bom_creator.json
#	erpnext/manufacturing/doctype/bom_creator/bom_creator.py
#	erpnext/manufacturing/doctype/bom_creator/test_bom_creator.py
#	erpnext/manufacturing/doctype/bom_creator_item/bom_creator_item.json
#	erpnext/manufacturing/doctype/bom_creator_item/bom_creator_item.py
#	erpnext/manufacturing/doctype/bom_explosion_item/bom_explosion_item.json
#	erpnext/manufacturing/doctype/bom_item/bom_item.json
#	erpnext/manufacturing/doctype/bom_item/bom_item.py
#	erpnext/manufacturing/doctype/bom_operation/bom_operation.json
#	erpnext/manufacturing/doctype/bom_operation/bom_operation.py
#	erpnext/manufacturing/doctype/bom_scrap_item/bom_scrap_item.json
#	erpnext/manufacturing/doctype/bom_update_batch/bom_update_batch.json
#	erpnext/manufacturing/doctype/bom_update_log/bom_update_log.json
#	erpnext/manufacturing/doctype/bom_update_log/bom_update_log.py
#	erpnext/manufacturing/doctype/bom_update_log/test_bom_update_log.py
#	erpnext/manufacturing/doctype/bom_update_tool/bom_update_tool.json
#	erpnext/manufacturing/doctype/bom_update_tool/test_bom_update_tool.py
#	erpnext/manufacturing/doctype/bom_website_item/bom_website_item.json
#	erpnext/manufacturing/doctype/bom_website_operation/bom_website_operation.json
#	erpnext/manufacturing/doctype/downtime_entry/downtime_entry.json
#	erpnext/manufacturing/doctype/downtime_entry/test_downtime_entry.py
#	erpnext/manufacturing/doctype/job_card/job_card.js
#	erpnext/manufacturing/doctype/job_card/job_card.json
#	erpnext/manufacturing/doctype/job_card/job_card.py
#	erpnext/manufacturing/doctype/job_card/job_card_dashboard.py
#	erpnext/manufacturing/doctype/job_card/test_job_card.py
#	erpnext/manufacturing/doctype/job_card_item/job_card_item.json
#	erpnext/manufacturing/doctype/job_card_operation/job_card_operation.json
#	erpnext/manufacturing/doctype/job_card_scheduled_time/job_card_scheduled_time.json
#	erpnext/manufacturing/doctype/job_card_scrap_item/job_card_scrap_item.json
#	erpnext/manufacturing/doctype/job_card_time_log/job_card_time_log.json
#	erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json
#	erpnext/manufacturing/doctype/manufacturing_settings/test_manufacturing_settings.py
#	erpnext/manufacturing/doctype/material_request_plan_item/material_request_plan_item.json
#	erpnext/manufacturing/doctype/material_request_plan_item/test_material_request_plan_item.py
#	erpnext/manufacturing/doctype/operation/operation.json
#	erpnext/manufacturing/doctype/operation/test_operation.py
#	erpnext/manufacturing/doctype/plant_floor/plant_floor.js
#	erpnext/manufacturing/doctype/plant_floor/plant_floor.json
#	erpnext/manufacturing/doctype/plant_floor/test_plant_floor.py
#	erpnext/manufacturing/doctype/production_plan/production_plan.json
#	erpnext/manufacturing/doctype/production_plan/test_production_plan.py
#	erpnext/manufacturing/doctype/production_plan_item/production_plan_item.json
#	erpnext/manufacturing/doctype/production_plan_item_reference/production_plan_item_reference.json
#	erpnext/manufacturing/doctype/production_plan_material_request/production_plan_material_request.json
#	erpnext/manufacturing/doctype/production_plan_material_request_warehouse/production_plan_material_request_warehouse.json
#	erpnext/manufacturing/doctype/production_plan_material_request_warehouse/test_production_plan_material_request_warehouse.py
#	erpnext/manufacturing/doctype/production_plan_sales_order/production_plan_sales_order.json
#	erpnext/manufacturing/doctype/production_plan_sub_assembly_item/production_plan_sub_assembly_item.json
#	erpnext/manufacturing/doctype/routing/routing.json
#	erpnext/manufacturing/doctype/routing/routing.py
#	erpnext/manufacturing/doctype/routing/test_routing.py
#	erpnext/manufacturing/doctype/sub_operation/sub_operation.json
#	erpnext/manufacturing/doctype/sub_operation/test_sub_operation.py
#	erpnext/manufacturing/doctype/work_order/test_work_order.py
#	erpnext/manufacturing/doctype/work_order/work_order.js
#	erpnext/manufacturing/doctype/work_order/work_order.json
#	erpnext/manufacturing/doctype/work_order/work_order.py
#	erpnext/manufacturing/doctype/work_order_item/work_order_item.json
#	erpnext/manufacturing/doctype/work_order_operation/work_order_operation.json
#	erpnext/manufacturing/doctype/work_order_operation/work_order_operation.py
#	erpnext/manufacturing/doctype/workstation/test_workstation.py
#	erpnext/manufacturing/doctype/workstation/workstation.js
#	erpnext/manufacturing/doctype/workstation/workstation.json
#	erpnext/manufacturing/doctype/workstation/workstation.py
#	erpnext/manufacturing/doctype/workstation/workstation_job_card.html
#	erpnext/manufacturing/doctype/workstation_type/test_workstation_type.py
#	erpnext/manufacturing/doctype/workstation_type/workstation_type.json
#	erpnext/manufacturing/doctype/workstation_working_hour/workstation_working_hour.json
#	erpnext/manufacturing/notification/material_request_receipt_notification/material_request_receipt_notification.json
#	erpnext/manufacturing/report/bom_stock_calculated/test_bom_stock_calculated.py
#	erpnext/manufacturing/report/bom_stock_report/test_bom_stock_report.py
#	erpnext/manufacturing/report/test_reports.py
#	erpnext/patches.txt
#	erpnext/patches/v11_0/create_department_records_for_each_company.py
#	erpnext/patches/v11_0/make_location_from_warehouse.py
#	erpnext/patches/v11_0/rebuild_tree_for_company.py
#	erpnext/patches/v11_0/rename_supplier_type_to_supplier_group.py
#	erpnext/patches/v11_0/update_department_lft_rgt.py
#	erpnext/patches/v13_0/modify_invalid_gain_loss_gl_entries.py
#	erpnext/patches/v14_0/migrate_crm_settings.py
#	erpnext/patches/v14_0/migrate_gl_to_payment_ledger.py
#	erpnext/patches/v15_0/create_advance_payment_ledger_records.py
#	erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py
#	erpnext/patches/v15_0/update_gpa_and_ndb_for_assdeprsch.py
#	erpnext/portal/doctype/website_attribute/website_attribute.json
#	erpnext/portal/doctype/website_filter_field/website_filter_field.json
#	erpnext/portal/utils.py
#	erpnext/projects/doctype/activity_cost/activity_cost.json
#	erpnext/projects/doctype/activity_cost/test_activity_cost.py
#	erpnext/projects/doctype/activity_type/activity_type.json
#	erpnext/projects/doctype/activity_type/test_activity_type.py
#	erpnext/projects/doctype/dependent_task/dependent_task.json
#	erpnext/projects/doctype/project/project.json
#	erpnext/projects/doctype/project/project.py
#	erpnext/projects/doctype/project/test_project.py
#	erpnext/projects/doctype/project_template/project_template.json
#	erpnext/projects/doctype/project_template/test_project_template.py
#	erpnext/projects/doctype/project_template_task/project_template_task.json
#	erpnext/projects/doctype/project_type/project_type.json
#	erpnext/projects/doctype/project_type/test_project_type.py
#	erpnext/projects/doctype/project_update/project_update.json
#	erpnext/projects/doctype/project_update/test_project_update.py
#	erpnext/projects/doctype/project_user/project_user.json
#	erpnext/projects/doctype/projects_settings/projects_settings.json
#	erpnext/projects/doctype/projects_settings/test_projects_settings.py
#	erpnext/projects/doctype/task/task.js
#	erpnext/projects/doctype/task/task.json
#	erpnext/projects/doctype/task/task.py
#	erpnext/projects/doctype/task/test_task.py
#	erpnext/projects/doctype/task_depends_on/task_depends_on.json
#	erpnext/projects/doctype/task_type/task_type.json
#	erpnext/projects/doctype/task_type/test_task_type.py
#	erpnext/projects/doctype/timesheet/test_timesheet.py
#	erpnext/projects/doctype/timesheet/timesheet.js
#	erpnext/projects/doctype/timesheet/timesheet.json
#	erpnext/projects/doctype/timesheet/timesheet.py
#	erpnext/projects/doctype/timesheet_detail/timesheet_detail.json
#	erpnext/projects/doctype/timesheet_detail/timesheet_detail.py
#	erpnext/projects/report/delayed_tasks_summary/test_delayed_tasks_summary.py
#	erpnext/projects/workspace/projects/projects.json
#	erpnext/public/images/erpnext-logo.svg
#	erpnext/public/js/bom_configurator/bom_configurator.bundle.js
#	erpnext/public/js/bulk_transaction_processing.js
#	erpnext/public/js/controllers/accounts.js
#	erpnext/public/js/controllers/taxes_and_totals.js
#	erpnext/public/js/controllers/transaction.js
#	erpnext/public/js/financial_statements.js
#	erpnext/public/js/plant_floor_visual/visual_plant.js
#	erpnext/public/js/projects/timer.js
#	erpnext/public/js/setup_wizard.js
#	erpnext/public/js/templates/visual_plant_floor_template.html
#	erpnext/public/js/utils.js
#	erpnext/public/js/utils/dimension_tree_filter.js
#	erpnext/public/scss/erpnext.scss
#	erpnext/quality_management/doctype/non_conformance/non_conformance.json
#	erpnext/quality_management/doctype/non_conformance/test_non_conformance.py
#	erpnext/quality_management/doctype/quality_action/quality_action.json
#	erpnext/quality_management/doctype/quality_action/test_quality_action.py
#	erpnext/quality_management/doctype/quality_action_resolution/quality_action_resolution.json
#	erpnext/quality_management/doctype/quality_feedback/quality_feedback.json
#	erpnext/quality_management/doctype/quality_feedback/test_quality_feedback.py
#	erpnext/quality_management/doctype/quality_feedback_parameter/quality_feedback_parameter.json
#	erpnext/quality_management/doctype/quality_feedback_template/quality_feedback_template.json
#	erpnext/quality_management/doctype/quality_feedback_template/test_quality_feedback_template.py
#	erpnext/quality_management/doctype/quality_feedback_template_parameter/quality_feedback_template_parameter.json
#	erpnext/quality_management/doctype/quality_goal/quality_goal.json
#	erpnext/quality_management/doctype/quality_goal/test_quality_goal.py
#	erpnext/quality_management/doctype/quality_goal_objective/quality_goal_objective.json
#	erpnext/quality_management/doctype/quality_meeting/quality_meeting.json
#	erpnext/quality_management/doctype/quality_meeting/test_quality_meeting.py
#	erpnext/quality_management/doctype/quality_meeting_agenda/quality_meeting_agenda.json
#	erpnext/quality_management/doctype/quality_meeting_agenda/test_quality_meeting_agenda.py
#	erpnext/quality_management/doctype/quality_meeting_minutes/quality_meeting_minutes.json
#	erpnext/quality_management/doctype/quality_procedure/quality_procedure.json
#	erpnext/quality_management/doctype/quality_procedure/test_quality_procedure.py
#	erpnext/quality_management/doctype/quality_procedure_process/quality_procedure_process.json
#	erpnext/quality_management/doctype/quality_review/quality_review.json
#	erpnext/quality_management/doctype/quality_review/test_quality_review.py
#	erpnext/quality_management/doctype/quality_review_objective/quality_review_objective.json
#	erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.json
#	erpnext/regional/doctype/import_supplier_invoice/import_supplier_invoice.py
#	erpnext/regional/doctype/import_supplier_invoice/test_import_supplier_invoice.py
#	erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.json
#	erpnext/regional/doctype/lower_deduction_certificate/lower_deduction_certificate.py
#	erpnext/regional/doctype/lower_deduction_certificate/test_lower_deduction_certificate.py
#	erpnext/regional/doctype/south_africa_vat_settings/south_africa_vat_settings.json
#	erpnext/regional/doctype/south_africa_vat_settings/test_south_africa_vat_settings.py
#	erpnext/regional/doctype/uae_vat_account/uae_vat_account.json
#	erpnext/regional/doctype/uae_vat_settings/test_uae_vat_settings.py
#	erpnext/regional/doctype/uae_vat_settings/uae_vat_settings.json
#	erpnext/regional/italy/utils.py
#	erpnext/regional/print_format/detailed_tax_invoice/detailed_tax_invoice.json
#	erpnext/regional/print_format/tax_invoice/tax_invoice.json
#	erpnext/regional/report/uae_vat_201/test_uae_vat_201.py
#	erpnext/regional/report/vat_audit_report/vat_audit_report.py
#	erpnext/regional/united_states/test_united_states.py
#	erpnext/selling/doctype/customer/customer.js
#	erpnext/selling/doctype/customer/customer.json
#	erpnext/selling/doctype/customer/customer.py
#	erpnext/selling/doctype/customer/customer_dashboard.py
#	erpnext/selling/doctype/customer/test_customer.py
#	erpnext/selling/doctype/customer_credit_limit/customer_credit_limit.json
#	erpnext/selling/doctype/industry_type/industry_type.json
#	erpnext/selling/doctype/industry_type/test_industry_type.py
#	erpnext/selling/doctype/installation_note/installation_note.json
#	erpnext/selling/doctype/installation_note/installation_note.py
#	erpnext/selling/doctype/installation_note/test_installation_note.py
#	erpnext/selling/doctype/installation_note_item/installation_note_item.json
#	erpnext/selling/doctype/party_specific_item/party_specific_item.json
#	erpnext/selling/doctype/party_specific_item/test_party_specific_item.py
#	erpnext/selling/doctype/product_bundle/product_bundle.js
#	erpnext/selling/doctype/product_bundle/product_bundle.json
#	erpnext/selling/doctype/product_bundle/test_product_bundle.py
#	erpnext/selling/doctype/product_bundle_item/product_bundle_item.json
#	erpnext/selling/doctype/quotation/quotation.json
#	erpnext/selling/doctype/quotation/quotation.py
#	erpnext/selling/doctype/quotation/test_quotation.py
#	erpnext/selling/doctype/quotation_item/quotation_item.json
#	erpnext/selling/doctype/quotation_item/quotation_item.py
#	erpnext/selling/doctype/sales_order/sales_order.js
#	erpnext/selling/doctype/sales_order/sales_order.json
#	erpnext/selling/doctype/sales_order/sales_order.py
#	erpnext/selling/doctype/sales_order/sales_order_list.js
#	erpnext/selling/doctype/sales_order/test_sales_order.py
#	erpnext/selling/doctype/sales_order_item/sales_order_item.json
#	erpnext/selling/doctype/sales_order_item/sales_order_item.py
#	erpnext/selling/doctype/sales_partner_type/sales_partner_type.json
#	erpnext/selling/doctype/sales_partner_type/test_sales_partner_type.py
#	erpnext/selling/doctype/sales_team/sales_team.json
#	erpnext/selling/doctype/selling_settings/selling_settings.json
#	erpnext/selling/doctype/selling_settings/selling_settings.py
#	erpnext/selling/doctype/selling_settings/test_selling_settings.py
#	erpnext/selling/doctype/sms_center/sms_center.json
#	erpnext/selling/number_card/annual_sales/annual_sales.json
#	erpnext/selling/number_card/sales_orders_to_bill/sales_orders_to_bill.json
#	erpnext/selling/number_card/sales_orders_to_deliver/sales_orders_to_deliver.json
#	erpnext/selling/page/point_of_sale/pos_controller.js
#	erpnext/selling/page/point_of_sale/pos_past_order_summary.js
#	erpnext/selling/page/point_of_sale/pos_payment.js
#	erpnext/selling/page/sales_funnel/sales_funnel.js
#	erpnext/selling/page/sales_funnel/sales_funnel.py
#	erpnext/selling/report/address_and_contacts/address_and_contacts.py
#	erpnext/selling/report/customer_credit_balance/customer_credit_balance.py
#	erpnext/selling/report/payment_terms_status_for_sales_order/payment_terms_status_for_sales_order.py
#	erpnext/selling/report/payment_terms_status_for_sales_order/test_payment_terms_status_for_sales_order.py
#	erpnext/selling/report/pending_so_items_for_purchase_request/test_pending_so_items_for_purchase_request.py
#	erpnext/selling/report/sales_analytics/sales_analytics.js
#	erpnext/selling/report/sales_analytics/sales_analytics.py
#	erpnext/selling/report/sales_analytics/test_analytics.py
#	erpnext/selling/report/sales_order_analysis/sales_order_analysis.js
#	erpnext/selling/report/sales_order_analysis/test_sales_order_analysis.py
#	erpnext/selling/report/sales_partner_target_variance_based_on_item_group/test_sales_partner_target_variance_based_on_item_group.py
#	erpnext/selling/report/sales_person_target_variance_based_on_item_group/test_sales_person_target_variance_based_on_item_group.py
#	erpnext/selling/workspace/selling/selling.json
#	erpnext/setup/doctype/authorization_control/authorization_control.json
#	erpnext/setup/doctype/authorization_control/authorization_control.py
#	erpnext/setup/doctype/authorization_rule/authorization_rule.json
#	erpnext/setup/doctype/authorization_rule/test_authorization_rule.py
#	erpnext/setup/doctype/branch/branch.json
#	erpnext/setup/doctype/branch/test_branch.py
#	erpnext/setup/doctype/brand/brand.json
#	erpnext/setup/doctype/brand/test_brand.py
#	erpnext/setup/doctype/company/company.js
#	erpnext/setup/doctype/company/company.json
#	erpnext/setup/doctype/company/company.py
#	erpnext/setup/doctype/company/test_company.py
#	erpnext/setup/doctype/currency_exchange/test_currency_exchange.py
#	erpnext/setup/doctype/customer_group/customer_group.json
#	erpnext/setup/doctype/customer_group/customer_group.py
#	erpnext/setup/doctype/customer_group/test_customer_group.py
#	erpnext/setup/doctype/department/department.json
#	erpnext/setup/doctype/department/department.py
#	erpnext/setup/doctype/department/test_department.py
#	erpnext/setup/doctype/designation/designation.json
#	erpnext/setup/doctype/designation/test_designation.py
#	erpnext/setup/doctype/driver/driver.json
#	erpnext/setup/doctype/driver/driver.py
#	erpnext/setup/doctype/driver/test_driver.py
#	erpnext/setup/doctype/driving_license_category/driving_license_category.json
#	erpnext/setup/doctype/email_digest/email_digest.json
#	erpnext/setup/doctype/email_digest/email_digest.py
#	erpnext/setup/doctype/email_digest/test_email_digest.py
#	erpnext/setup/doctype/email_digest_recipient/email_digest_recipient.json
#	erpnext/setup/doctype/employee/employee.json
#	erpnext/setup/doctype/employee/employee.py
#	erpnext/setup/doctype/employee/test_employee.py
#	erpnext/setup/doctype/employee_education/employee_education.json
#	erpnext/setup/doctype/employee_external_work_history/employee_external_work_history.json
#	erpnext/setup/doctype/employee_group/employee_group.json
#	erpnext/setup/doctype/employee_group/test_employee_group.py
#	erpnext/setup/doctype/employee_group_table/employee_group_table.json
#	erpnext/setup/doctype/employee_internal_work_history/employee_internal_work_history.json
#	erpnext/setup/doctype/global_defaults/global_defaults.json
#	erpnext/setup/doctype/global_defaults/test_global_defaults.py
#	erpnext/setup/doctype/holiday/holiday.json
#	erpnext/setup/doctype/holiday_list/holiday_list.json
#	erpnext/setup/doctype/holiday_list/test_holiday_list.py
#	erpnext/setup/doctype/incoterm/test_incoterm.py
#	erpnext/setup/doctype/item_group/item_group.json
#	erpnext/setup/doctype/item_group/test_item_group.py
#	erpnext/setup/doctype/party_type/party_type.json
#	erpnext/setup/doctype/party_type/test_party_type.py
#	erpnext/setup/doctype/print_heading/print_heading.json
#	erpnext/setup/doctype/print_heading/test_print_heading.py
#	erpnext/setup/doctype/quotation_lost_reason/quotation_lost_reason.json
#	erpnext/setup/doctype/quotation_lost_reason/test_quotation_lost_reason.py
#	erpnext/setup/doctype/quotation_lost_reason_detail/quotation_lost_reason_detail.json
#	erpnext/setup/doctype/sales_partner/sales_partner.json
#	erpnext/setup/doctype/sales_partner/sales_partner.py
#	erpnext/setup/doctype/sales_partner/test_sales_partner.py
#	erpnext/setup/doctype/sales_person/sales_person.json
#	erpnext/setup/doctype/sales_person/test_sales_person.py
#	erpnext/setup/doctype/supplier_group/supplier_group.js
#	erpnext/setup/doctype/supplier_group/supplier_group.json
#	erpnext/setup/doctype/supplier_group/test_supplier_group.py
#	erpnext/setup/doctype/target_detail/target_detail.json
#	erpnext/setup/doctype/terms_and_conditions/terms_and_conditions.json
#	erpnext/setup/doctype/terms_and_conditions/test_terms_and_conditions.py
#	erpnext/setup/doctype/territory/territory.json
#	erpnext/setup/doctype/territory/test_territory.py
#	erpnext/setup/doctype/transaction_deletion_record/test_transaction_deletion_record.py
#	erpnext/setup/doctype/transaction_deletion_record/transaction_deletion_record.json
#	erpnext/setup/doctype/transaction_deletion_record_item/transaction_deletion_record_item.json
#	erpnext/setup/doctype/uom/test_uom.py
#	erpnext/setup/doctype/uom/uom.json
#	erpnext/setup/doctype/uom/uom.py
#	erpnext/setup/doctype/uom_conversion_factor/test_uom_conversion_factor.py
#	erpnext/setup/doctype/uom_conversion_factor/uom_conversion_factor.json
#	erpnext/setup/doctype/vehicle/test_vehicle.py
#	erpnext/setup/doctype/vehicle/vehicle.json
#	erpnext/setup/doctype/website_item_group/website_item_group.json
#	erpnext/setup/install.py
#	erpnext/setup/setup_wizard/data/country_wise_tax.json
#	erpnext/setup/setup_wizard/data/uom_data.json
#	erpnext/setup/setup_wizard/operations/defaults_setup.py
#	erpnext/setup/setup_wizard/operations/install_fixtures.py
#	erpnext/setup/utils.py
#	erpnext/startup/boot.py
#	erpnext/startup/leaderboard.py
#	erpnext/stock/__init__.py
#	erpnext/stock/deprecated_serial_batch.py
#	erpnext/stock/doctype/batch/batch.json
#	erpnext/stock/doctype/batch/test_batch.py
#	erpnext/stock/doctype/bin/bin.json
#	erpnext/stock/doctype/bin/test_bin.py
#	erpnext/stock/doctype/closing_stock_balance/closing_stock_balance.json
#	erpnext/stock/doctype/closing_stock_balance/test_closing_stock_balance.py
#	erpnext/stock/doctype/customs_tariff_number/customs_tariff_number.json
#	erpnext/stock/doctype/customs_tariff_number/test_customs_tariff_number.py
#	erpnext/stock/doctype/delivery_note/delivery_note.json
#	erpnext/stock/doctype/delivery_note/delivery_note.py
#	erpnext/stock/doctype/delivery_note/delivery_note_list.js
#	erpnext/stock/doctype/delivery_note/test_delivery_note.py
#	erpnext/stock/doctype/delivery_note_item/delivery_note_item.json
#	erpnext/stock/doctype/delivery_note_item/delivery_note_item.py
#	erpnext/stock/doctype/delivery_settings/delivery_settings.json
#	erpnext/stock/doctype/delivery_settings/test_delivery_settings.py
#	erpnext/stock/doctype/delivery_stop/delivery_stop.json
#	erpnext/stock/doctype/delivery_trip/delivery_trip.js
#	erpnext/stock/doctype/delivery_trip/delivery_trip.json
#	erpnext/stock/doctype/delivery_trip/delivery_trip.py
#	erpnext/stock/doctype/delivery_trip/test_delivery_trip.py
#	erpnext/stock/doctype/inventory_dimension/inventory_dimension.json
#	erpnext/stock/doctype/inventory_dimension/test_inventory_dimension.py
#	erpnext/stock/doctype/item/item.js
#	erpnext/stock/doctype/item/item.json
#	erpnext/stock/doctype/item/item.py
#	erpnext/stock/doctype/item/item_list.js
#	erpnext/stock/doctype/item/test_item.py
#	erpnext/stock/doctype/item_alternative/item_alternative.json
#	erpnext/stock/doctype/item_alternative/test_item_alternative.py
#	erpnext/stock/doctype/item_attribute/item_attribute.json
#	erpnext/stock/doctype/item_attribute/item_attribute.py
#	erpnext/stock/doctype/item_attribute/test_item_attribute.py
#	erpnext/stock/doctype/item_attribute_value/item_attribute_value.json
#	erpnext/stock/doctype/item_barcode/item_barcode.json
#	erpnext/stock/doctype/item_customer_detail/item_customer_detail.json
#	erpnext/stock/doctype/item_default/item_default.json
#	erpnext/stock/doctype/item_manufacturer/item_manufacturer.json
#	erpnext/stock/doctype/item_manufacturer/test_item_manufacturer.py
#	erpnext/stock/doctype/item_price/item_price.json
#	erpnext/stock/doctype/item_price/item_price.py
#	erpnext/stock/doctype/item_price/test_item_price.py
#	erpnext/stock/doctype/item_quality_inspection_parameter/item_quality_inspection_parameter.json
#	erpnext/stock/doctype/item_reorder/item_reorder.json
#	erpnext/stock/doctype/item_supplier/item_supplier.json
#	erpnext/stock/doctype/item_tax/item_tax.json
#	erpnext/stock/doctype/item_variant/item_variant.json
#	erpnext/stock/doctype/item_variant_attribute/item_variant_attribute.json
#	erpnext/stock/doctype/item_variant_settings/item_variant_settings.js
#	erpnext/stock/doctype/item_variant_settings/item_variant_settings.json
#	erpnext/stock/doctype/item_variant_settings/test_item_variant_settings.py
#	erpnext/stock/doctype/item_website_specification/item_website_specification.json
#	erpnext/stock/doctype/landed_cost_item/landed_cost_item.json
#	erpnext/stock/doctype/landed_cost_purchase_receipt/landed_cost_purchase_receipt.json
#	erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.json
#	erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.json
#	erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
#	erpnext/stock/doctype/landed_cost_voucher/test_landed_cost_voucher.py
#	erpnext/stock/doctype/manufacturer/manufacturer.json
#	erpnext/stock/doctype/manufacturer/test_manufacturer.py
#	erpnext/stock/doctype/material_request/material_request.js
#	erpnext/stock/doctype/material_request/material_request.json
#	erpnext/stock/doctype/material_request/material_request.py
#	erpnext/stock/doctype/material_request/material_request_list.js
#	erpnext/stock/doctype/material_request/test_material_request.py
#	erpnext/stock/doctype/material_request_item/material_request_item.json
#	erpnext/stock/doctype/packed_item/packed_item.json
#	erpnext/stock/doctype/packed_item/packed_item.py
#	erpnext/stock/doctype/packed_item/test_packed_item.py
#	erpnext/stock/doctype/packing_slip/packing_slip.json
#	erpnext/stock/doctype/packing_slip/test_packing_slip.py
#	erpnext/stock/doctype/packing_slip_item/packing_slip_item.json
#	erpnext/stock/doctype/pick_list/pick_list.json
#	erpnext/stock/doctype/pick_list/test_pick_list.py
#	erpnext/stock/doctype/pick_list_item/pick_list_item.json
#	erpnext/stock/doctype/price_list/price_list.json
#	erpnext/stock/doctype/price_list/price_list.py
#	erpnext/stock/doctype/price_list/test_price_list.py
#	erpnext/stock/doctype/price_list_country/price_list_country.json
#	erpnext/stock/doctype/purchase_receipt/purchase_receipt.json
#	erpnext/stock/doctype/purchase_receipt/purchase_receipt.py
#	erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py
#	erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json
#	erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.py
#	erpnext/stock/doctype/putaway_rule/putaway_rule.json
#	erpnext/stock/doctype/putaway_rule/putaway_rule.py
#	erpnext/stock/doctype/putaway_rule/test_putaway_rule.py
#	erpnext/stock/doctype/quality_inspection/quality_inspection.json
#	erpnext/stock/doctype/quality_inspection/test_quality_inspection.py
#	erpnext/stock/doctype/quality_inspection_parameter/quality_inspection_parameter.json
#	erpnext/stock/doctype/quality_inspection_parameter/test_quality_inspection_parameter.py
#	erpnext/stock/doctype/quality_inspection_parameter_group/quality_inspection_parameter_group.json
#	erpnext/stock/doctype/quality_inspection_parameter_group/test_quality_inspection_parameter_group.py
#	erpnext/stock/doctype/quality_inspection_reading/quality_inspection_reading.json
#	erpnext/stock/doctype/quality_inspection_template/quality_inspection_template.json
#	erpnext/stock/doctype/quality_inspection_template/test_quality_inspection_template.py
#	erpnext/stock/doctype/quick_stock_balance/quick_stock_balance.json
#	erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.json
#	erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py
#	erpnext/stock/doctype/repost_item_valuation/test_repost_item_valuation.py
#	erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.json
#	erpnext/stock/doctype/serial_and_batch_bundle/serial_and_batch_bundle.py
#	erpnext/stock/doctype/serial_and_batch_bundle/test_serial_and_batch_bundle.py
#	erpnext/stock/doctype/serial_and_batch_entry/serial_and_batch_entry.json
#	erpnext/stock/doctype/serial_no/serial_no.json
#	erpnext/stock/doctype/serial_no/test_serial_no.py
#	erpnext/stock/doctype/shipment/shipment.json
#	erpnext/stock/doctype/shipment/test_shipment.py
#	erpnext/stock/doctype/shipment_delivery_note/shipment_delivery_note.json
#	erpnext/stock/doctype/shipment_parcel/shipment_parcel.json
#	erpnext/stock/doctype/shipment_parcel_template/shipment_parcel_template.json
#	erpnext/stock/doctype/shipment_parcel_template/test_shipment_parcel_template.py
#	erpnext/stock/doctype/stock_entry/stock_entry.json
#	erpnext/stock/doctype/stock_entry/stock_entry.py
#	erpnext/stock/doctype/stock_entry/test_stock_entry.py
#	erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
#	erpnext/stock/doctype/stock_entry_type/stock_entry_type.json
#	erpnext/stock/doctype/stock_entry_type/stock_entry_type.py
#	erpnext/stock/doctype/stock_entry_type/test_stock_entry_type.py
#	erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.json
#	erpnext/stock/doctype/stock_ledger_entry/stock_ledger_entry.py
#	erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py
#	erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
#	erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.json
#	erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.py
#	erpnext/stock/doctype/stock_reconciliation/test_stock_reconciliation.py
#	erpnext/stock/doctype/stock_reconciliation_item/stock_reconciliation_item.json
#	erpnext/stock/doctype/stock_reposting_settings/stock_reposting_settings.json
#	erpnext/stock/doctype/stock_reposting_settings/test_stock_reposting_settings.py
#	erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.json
#	erpnext/stock/doctype/stock_reservation_entry/stock_reservation_entry.py
#	erpnext/stock/doctype/stock_reservation_entry/test_stock_reservation_entry.py
#	erpnext/stock/doctype/stock_settings/stock_settings.json
#	erpnext/stock/doctype/stock_settings/test_stock_settings.py
#	erpnext/stock/doctype/uom_category/test_uom_category.py
#	erpnext/stock/doctype/uom_category/uom_category.json
#	erpnext/stock/doctype/uom_conversion_detail/uom_conversion_detail.json
#	erpnext/stock/doctype/variant_field/test_variant_field.py
#	erpnext/stock/doctype/variant_field/variant_field.json
#	erpnext/stock/doctype/warehouse/test_warehouse.py
#	erpnext/stock/doctype/warehouse/warehouse.json
#	erpnext/stock/doctype/warehouse/warehouse.py
#	erpnext/stock/doctype/warehouse_type/test_warehouse_type.py
#	erpnext/stock/doctype/warehouse_type/warehouse_type.json
#	erpnext/stock/get_item_details.py
#	erpnext/stock/page/warehouse_capacity_summary/warehouse_capacity_summary.js
#	erpnext/stock/page/warehouse_capacity_summary/warehouse_capacity_summary_header.html
#	erpnext/stock/print_format/purchase_receipt_serial_and_batch_bundle_print/purchase_receipt_serial_and_batch_bundle_print.json
#	erpnext/stock/reorder_item.py
#	erpnext/stock/report/batch_wise_balance_history/batch_wise_balance_history.py
#	erpnext/stock/report/item_shortage_report/test_item_shortage_report.py
#	erpnext/stock/report/reserved_stock/test_reserved_stock.py
#	erpnext/stock/report/stock_ageing/test_stock_ageing.py
#	erpnext/stock/report/stock_analytics/test_stock_analytics.py
#	erpnext/stock/report/stock_balance/test_stock_balance.py
#	erpnext/stock/report/stock_ledger/test_stock_ledger_report.py
#	erpnext/stock/report/test_reports.py
#	erpnext/stock/stock_balance.py
#	erpnext/stock/stock_ledger.py
#	erpnext/stock/tests/test_get_item_details.py
#	erpnext/stock/tests/test_utils.py
#	erpnext/stock/tests/test_valuation.py
#	erpnext/stock/utils.py
#	erpnext/subcontracting/doctype/subcontracting_bom/subcontracting_bom.json
#	erpnext/subcontracting/doctype/subcontracting_bom/subcontracting_bom.py
#	erpnext/subcontracting/doctype/subcontracting_bom/test_subcontracting_bom.py
#	erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.json
#	erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py
#	erpnext/subcontracting/doctype/subcontracting_order/test_subcontracting_order.py
#	erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json
#	erpnext/subcontracting/doctype/subcontracting_order_service_item/subcontracting_order_service_item.json
#	erpnext/subcontracting/doctype/subcontracting_order_supplied_item/subcontracting_order_supplied_item.json
#	erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.json
#	erpnext/subcontracting/doctype/subcontracting_receipt/subcontracting_receipt.py
#	erpnext/subcontracting/doctype/subcontracting_receipt/test_subcontracting_receipt.py
#	erpnext/subcontracting/doctype/subcontracting_receipt_item/subcontracting_receipt_item.json
#	erpnext/subcontracting/doctype/subcontracting_receipt_supplied_item/subcontracting_receipt_supplied_item.json
#	erpnext/support/doctype/issue/issue.json
#	erpnext/support/doctype/issue/issue.py
#	erpnext/support/doctype/issue/test_issue.py
#	erpnext/support/doctype/issue_priority/issue_priority.json
#	erpnext/support/doctype/issue_priority/test_issue_priority.py
#	erpnext/support/doctype/issue_type/issue_type.json
#	erpnext/support/doctype/issue_type/test_issue_type.py
#	erpnext/support/doctype/pause_sla_on_status/pause_sla_on_status.json
#	erpnext/support/doctype/service_day/service_day.json
#	erpnext/support/doctype/service_level_agreement/service_level_agreement.json
#	erpnext/support/doctype/service_level_agreement/service_level_agreement.py
#	erpnext/support/doctype/service_level_agreement/test_service_level_agreement.py
#	erpnext/support/doctype/service_level_priority/service_level_priority.json
#	erpnext/support/doctype/sla_fulfilled_on_status/sla_fulfilled_on_status.json
#	erpnext/support/doctype/support_search_source/support_search_source.json
#	erpnext/support/doctype/support_settings/support_settings.json
#	erpnext/support/doctype/support_settings/test_support_settings.py
#	erpnext/support/doctype/warranty_claim/test_warranty_claim.py
#	erpnext/support/doctype/warranty_claim/warranty_claim.json
#	erpnext/support/doctype/warranty_claim/warranty_claim.py
#	erpnext/support/report/issue_analytics/test_issue_analytics.py
#	erpnext/telephony/doctype/call_log/test_call_log.py
#	erpnext/telephony/doctype/incoming_call_handling_schedule/incoming_call_handling_schedule.json
#	erpnext/telephony/doctype/incoming_call_settings/incoming_call_settings.json
#	erpnext/telephony/doctype/incoming_call_settings/test_incoming_call_settings.py
#	erpnext/telephony/doctype/telephony_call_type/telephony_call_type.json
#	erpnext/telephony/doctype/telephony_call_type/test_telephony_call_type.py
#	erpnext/telephony/doctype/voice_call_settings/test_voice_call_settings.py
#	erpnext/telephony/doctype/voice_call_settings/voice_call_settings.json
#	erpnext/templates/form_grid/includes/visible_cols.html
#	erpnext/templates/generators/sales_partner.html
#	erpnext/templates/includes/macros.html
#	erpnext/templates/pages/order.html
#	erpnext/templates/pages/order.py
#	erpnext/templates/print_formats/includes/total.html
#	erpnext/tests/test_activation.py
#	erpnext/tests/test_init.py
#	erpnext/tests/test_notifications.py
#	erpnext/tests/test_perf.py
#	erpnext/tests/test_point_of_sale.py
#	erpnext/tests/test_regional.py
#	erpnext/tests/test_webform.py
#	erpnext/tests/test_zform_loads.py
#	erpnext/utilities/activation.py
#	erpnext/utilities/bulk_transaction.py
#	erpnext/utilities/doctype/portal_user/portal_user.json
#	erpnext/utilities/doctype/rename_tool/rename_tool.json
#	erpnext/utilities/doctype/video/test_video.py
#	erpnext/utilities/doctype/video/video.json
#	erpnext/utilities/doctype/video/video.py
#	erpnext/utilities/doctype/video_settings/test_video_settings.py
#	erpnext/utilities/doctype/video_settings/video_settings.json
#	erpnext/www/support/index.py
#	pyproject.toml
2024-12-13 04:59:47 +00:00
1593 changed files with 1629503 additions and 38300 deletions

View File

@@ -18,4 +18,8 @@ max_line_length = 110
[{*.json}]
insert_final_newline = false
indent_style = space
<<<<<<< HEAD
indent_size = 2
=======
indent_size = 1
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)

View File

@@ -30,5 +30,20 @@ b147b85e6ac19a9220cd1e2958a6ebd99373283a
# bulk format python code with black
baec607ff5905b1c67531096a9cf50ec7ff00a5d
<<<<<<< HEAD
# ruff
960ef14b7a68cfec9e309ec12845f521cb6a721c
=======
# bulk refactor with sourcery
eb9ee3f79b94e594fc6dfa4f6514580e125eee8c
# js formatting
ec74a5e56617bbd76ac402451468fd4668af543d
# ruff formatting
a308792ee7fda18a681e9181f4fd00b36385bc23
# noisy typing refactoring of get_item_details
7b7211ac79c248a79ba8a999ff34e734d874c0ae
d827ed21adc7b36047e247cbb0dc6388d048a7f9
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)

View File

@@ -1,7 +1,13 @@
import sys
<<<<<<< HEAD
import requests
from urllib.parse import urlparse
=======
from urllib.parse import urlparse
import requests
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
WEBSITE_REPOS = [
"erpnext_com",
@@ -10,7 +16,6 @@ WEBSITE_REPOS = [
DOCUMENTATION_DOMAINS = [
"docs.erpnext.com",
"docs.frappe.io",
"frappeframework.com",
]
@@ -37,11 +42,15 @@ def is_documentation_link(word: str) -> bool:
def contains_documentation_link(body: str) -> bool:
<<<<<<< HEAD
return any(
is_documentation_link(word)
for line in body.splitlines()
for word in line.split()
)
=======
return any(is_documentation_link(word) for line in body.splitlines() for word in line.split())
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
def check_pull_request(number: str) -> "tuple[int, str]":
@@ -54,12 +63,16 @@ def check_pull_request(number: str) -> "tuple[int, str]":
head_sha = (payload.get("head") or {}).get("sha")
body = (payload.get("body") or "").lower()
<<<<<<< HEAD
if (
not title.startswith("feat")
or not head_sha
or "no-docs" in body
or "backport" in body
):
=======
if not title.startswith("feat") or not head_sha or "no-docs" in body or "backport" in body:
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
return 0, "Skipping documentation checks... 🏃"
if contains_documentation_link(body):

View File

@@ -6,15 +6,28 @@ cd ~ || exit
sudo apt update
sudo apt remove mysql-server mysql-client
sudo apt install libcups2-dev redis-server mariadb-client
sudo apt install libcups2-dev redis-server mariadb-client-10.6
pip install frappe-bench
githubbranch=${GITHUB_BASE_REF:-${GITHUB_REF##*/}}
frappeuser=${FRAPPE_USER:-"frappe"}
<<<<<<< HEAD
frappebranch=${FRAPPE_BRANCH:-$githubbranch}
git clone "https://github.com/${frappeuser}/frappe" --branch "${frappebranch}" --depth 1
=======
frappecommitish=${FRAPPE_BRANCH:-$githubbranch}
mkdir frappe
pushd frappe
git init
git remote add origin "https://github.com/${frappeuser}/frappe"
git fetch origin "${frappecommitish}" --depth 1
git checkout FETCH_HEAD
popd
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
bench init --skip-assets --frappe-path ~/frappe --python "$(which python)" frappe-bench
mkdir ~/frappe-bench/sites/test_site
@@ -44,9 +57,13 @@ fi
install_whktml() {
wget -O /tmp/wkhtmltox.deb https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-2/wkhtmltox_0.12.6.1-2.jammy_amd64.deb
sudo apt install /tmp/wkhtmltox.deb
if [ "$(lsb_release -rs)" = "22.04" ]; then
wget -O /tmp/wkhtmltox.deb https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-2/wkhtmltox_0.12.6.1-2.jammy_amd64.deb
sudo apt install /tmp/wkhtmltox.deb
else
echo "Please update this script to support wkhtmltopdf for $(lsb_release -ds)"
exit 1
fi
}
install_whktml &
wkpid=$!

68
.github/helper/translation.py vendored Normal file
View File

@@ -0,0 +1,68 @@
import re
import sys
errors_encounter = 0
pattern = re.compile(
r"_\(([\"']{,3})(?P<message>((?!\1).)*)\1(\s*,\s*context\s*=\s*([\"'])(?P<py_context>((?!\5).)*)\5)*(\s*,(\s*?.*?\n*?)*(,\s*([\"'])(?P<js_context>((?!\11).)*)\11)*)*\)"
)
words_pattern = re.compile(r"_{1,2}\([\"'`]{1,3}.*?[a-zA-Z]")
start_pattern = re.compile(r"_{1,2}\([f\"'`]{1,3}")
f_string_pattern = re.compile(r"_\(f[\"']")
starts_with_f_pattern = re.compile(r"_\(f")
# skip first argument
files = sys.argv[1:]
files_to_scan = [_file for _file in files if _file.endswith((".py", ".js"))]
for _file in files_to_scan:
with open(_file) as f:
print(f"Checking: {_file}")
file_lines = f.readlines()
for line_number, line in enumerate(file_lines, 1):
if "frappe-lint: disable-translate" in line:
continue
start_matches = start_pattern.search(line)
if start_matches:
starts_with_f = starts_with_f_pattern.search(line)
if starts_with_f:
has_f_string = f_string_pattern.search(line)
if has_f_string:
errors_encounter += 1
print(
f"\nF-strings are not supported for translations at line number {line_number}\n{line.strip()[:100]}"
)
continue
else:
continue
match = pattern.search(line)
error_found = False
if not match and line.endswith((",\n", "[\n")):
# concat remaining text to validate multiline pattern
line = "".join(file_lines[line_number - 1 :])
line = line[start_matches.start() + 1 :]
match = pattern.match(line)
if not match:
error_found = True
print(f"\nTranslation syntax error at line number {line_number}\n{line.strip()[:100]}")
if not error_found and not words_pattern.search(line):
error_found = True
print(
f"\nTranslation is useless because it has no words at line number {line_number}\n{line.strip()[:100]}"
)
if error_found:
errors_encounter += 1
if errors_encounter > 0:
print(
'\nVisit "https://frappeframework.com/docs/user/en/translations" to learn about valid translation strings.'
)
sys.exit(1)
else:
print("\nGood To Go!")

40
.github/helper/update_pot_file.sh vendored Normal file
View File

@@ -0,0 +1,40 @@
#!/bin/bash
set -e
cd ~ || exit
echo "Setting Up Bench..."
pip install frappe-bench
bench -v init frappe-bench --skip-assets --skip-redis-config-generation --python "$(which python)"
cd ./frappe-bench || exit
echo "Get ERPNext..."
bench get-app --skip-assets erpnext "${GITHUB_WORKSPACE}"
echo "Generating POT file..."
bench generate-pot-file --app erpnext
cd ./apps/erpnext || exit
echo "Configuring git user..."
git config user.email "developers@erpnext.com"
git config user.name "frappe-pr-bot"
echo "Setting the correct git remote..."
# Here, the git remote is a local file path by default. Let's change it to the upstream repo.
git remote set-url upstream https://github.com/frappe/erpnext.git
echo "Creating a new branch..."
isodate=$(date -u +"%Y-%m-%d")
branch_name="pot_${BASE_BRANCH}_${isodate}"
git checkout -b "${branch_name}"
echo "Commiting changes..."
git add erpnext/locale/main.pot
git commit -m "chore: update POT file"
gh auth setup-git
git push -u upstream "${branch_name}"
echo "Creating a PR..."
gh pr create --fill --base "${BASE_BRANCH}" --head "${branch_name}" --reviewer ${PR_REVIEWER} -R frappe/erpnext

4
.github/release.yml vendored
View File

@@ -1,4 +0,0 @@
changelog:
exclude:
labels:
- skip-release-notes

11
.github/stale.yml vendored
View File

@@ -12,6 +12,17 @@ exemptProjects: true
# Set to true to ignore issues in a milestone (defaults to false)
exemptMilestones: true
<<<<<<< HEAD
=======
# Skip the stale action for draft PRs
exemptDraftPr: true
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
exemptLabels:
- hotfix
- no-stale
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
pulls:
daysUntilStale: 15
daysUntilClose: 3

26
.github/workflows/backport.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
name: Backport
on:
pull_request_target:
types:
- closed
- labeled
jobs:
main:
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Checkout Actions
uses: actions/checkout@v2
with:
repository: "frappe/backport"
path: ./actions
ref: develop
- name: Install Actions
run: npm install --production --prefix ./actions
- name: Run backport
uses: ./actions/backport
with:
token: ${{secrets.RELEASE_TOKEN}}
labelsToAdd: "backport"
title: "{{originalTitle}}"

39
.github/workflows/generate-pot-file.yml vendored Normal file
View File

@@ -0,0 +1,39 @@
# This workflow is agnostic to branches. Only maintain on develop branch.
# To add/remove branches just modify the matrix.
name: Regenerate POT file (translatable strings)
on:
schedule:
# 9:30 UTC => 3 PM IST Sunday
- cron: "30 9 * * 0"
workflow_dispatch:
jobs:
regenerate-pot-file:
name: Regenerate POT file
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
branch: ["develop"]
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ matrix.branch }}
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Run script to update POT file
run: |
bash ${GITHUB_WORKSPACE}/.github/helper/update_pot_file.sh
env:
GH_TOKEN: ${{ secrets.RELEASE_TOKEN }}
BASE_BRANCH: ${{ matrix.branch }}
PR_REVIEWER: barredterra # change to your GitHub username if you copied this file

32
.github/workflows/initiate_release.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
# This workflow is agnostic to branches. Only maintain on develop branch.
# To add/remove versions just modify the matrix.
name: Create weekly release pull requests
on:
schedule:
# 9:30 UTC => 3 PM IST Tuesday
- cron: "30 9 * * 2"
workflow_dispatch:
jobs:
stable-release:
name: Release
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
version: ["14", "15"]
steps:
- uses: octokit/request-action@v2.x
with:
route: POST /repos/{owner}/{repo}/pulls
owner: frappe
repo: erpnext
title: |-
"chore: release v${{ matrix.version }}"
body: "Automated weekly release."
base: version-${{ matrix.version }}
head: version-${{ matrix.version }}-hotfix
env:
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}

View File

@@ -1,30 +0,0 @@
name: "Auto-label PRs based on title"
on:
pull_request_target:
types: [opened, reopened]
jobs:
add-label-if-prefix-matches:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- name: Check PR title and add label if it matches prefixes
uses: actions/github-script@v7
continue-on-error: true
with:
script: |
const title = context.payload.pull_request.title.toLowerCase();
const prefixes = ['chore', 'ci', 'style', 'test', 'refactor'];
// Check if the PR title starts with any of the prefixes
if (prefixes.some(prefix => title.startsWith(prefix))) {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
labels: ['skip-release-notes']
});
}

View File

@@ -20,6 +20,21 @@ jobs:
- name: Install and Run Pre-commit
uses: pre-commit/action@v3.0.0
<<<<<<< HEAD
=======
semgrep:
name: semgrep
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python 3.10
uses: actions/setup-python@v4
with:
python-version: '3.10'
cache: pip
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
- name: Download Semgrep rules
run: git clone --depth 1 https://github.com/frappe/semgrep-rules.git frappe-semgrep-rules

21
.github/workflows/lock.yml vendored Normal file
View File

@@ -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

View File

@@ -32,7 +32,11 @@ jobs:
steps:
- name: Clone
<<<<<<< HEAD
uses: actions/checkout@v2
=======
uses: actions/checkout@v4
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
- name: Check for valid Python & Merge Conflicts
run: |
@@ -43,12 +47,21 @@ jobs:
fi
- name: Setup Python
<<<<<<< HEAD
uses: "actions/setup-python@v4"
with:
python-version: '3.10'
- name: Setup Node
uses: actions/setup-node@v2
=======
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Setup Node
uses: actions/setup-node@v4
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
with:
node-version: 18
check-latest: true
@@ -57,7 +70,11 @@ jobs:
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
- name: Cache pip
<<<<<<< HEAD
uses: actions/cache@v2
=======
uses: actions/cache@v4
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml') }}
@@ -66,7 +83,11 @@ jobs:
${{ runner.os }}-
- name: Cache node modules
<<<<<<< HEAD
uses: actions/cache@v2
=======
uses: actions/cache@v4
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
env:
cache-name: cache-node-modules
with:
@@ -81,7 +102,11 @@ jobs:
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
<<<<<<< HEAD
- uses: actions/cache@v2
=======
- uses: actions/cache@v4
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
@@ -134,9 +159,17 @@ jobs:
}
update_to_version 14
<<<<<<< HEAD
echo "Updating to latest version"
git -C "apps/frappe" checkout -q -f "${GITHUB_BASE_REF:-${GITHUB_REF##*/}}"
=======
update_to_version 15
echo "Updating to latest version"
git -C "apps/frappe" fetch --depth 1 upstream "${GITHUB_BASE_REF:-${GITHUB_REF##*/}}"
git -C "apps/frappe" checkout -q -f FETCH_HEAD
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
git -C "apps/erpnext" checkout -q -f "$GITHUB_SHA"
pgrep honcho | xargs kill

22
.github/workflows/patch_faux.yml vendored Normal file
View File

@@ -0,0 +1,22 @@
# Tests are skipped for these files but github doesn't allow "passing" hence this is required.
name: Skipped Patch Test
on:
pull_request:
paths:
- "**.js"
- "**.css"
- "**.md"
- "**.html"
- "**.csv"
jobs:
test:
runs-on: ubuntu-latest
name: Patch Test
steps:
- name: Pass skipped tests unconditionally
run: "echo Skipped"

View File

@@ -2,23 +2,37 @@ name: Generate Semantic Release
on:
push:
branches:
<<<<<<< HEAD
- version-15
=======
- version-13
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout Entire Repository
<<<<<<< HEAD
uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
=======
uses: actions/checkout@v2
with:
fetch-depth: 0
persist-credentials: false
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: 20
<<<<<<< HEAD
=======
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
- name: Setup dependencies
run: |
npm install @semantic-release/git @semantic-release/exec --no-save

View File

@@ -29,7 +29,15 @@ jobs:
steps:
- name: Update notes
run: |
<<<<<<< HEAD
NEW_NOTES=$(gh api --method POST -H "Accept: application/vnd.github+json" /repos/frappe/erpnext/releases/generate-notes -f tag_name=$RELEASE_TAG | jq -r '.body' | sed -E '/^\* (chore|ci|test|docs|style)/d' )
=======
NEW_NOTES=$(gh api --method POST -H "Accept: application/vnd.github+json" /repos/frappe/erpnext/releases/generate-notes -f tag_name=$RELEASE_TAG \
| jq -r '.body' \
| sed -E '/^\* (chore|ci|test|docs|style)/d' \
| sed -E 's/by @mergify //'
)
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
RELEASE_ID=$(gh api -H "Accept: application/vnd.github+json" /repos/frappe/erpnext/releases/tags/$RELEASE_TAG | jq -r '.id')
gh api --method PATCH -H "Accept: application/vnd.github+json" /repos/frappe/erpnext/releases/$RELEASE_ID -f body="$NEW_NOTES"

View File

@@ -0,0 +1,130 @@
name: Individual
on:
workflow_dispatch:
concurrency:
group: server-individual-tests-develop-${{ github.event_name }}-${{ github.event.number || github.event_name == 'workflow_dispatch' && github.run_id || '' }}
cancel-in-progress: false
jobs:
discover:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Clone
uses: actions/checkout@v4
- id: set-matrix
run: |
# Use grep and find to get the list of test files
matrix=$(find . -path '*/doctype/*/test_*.py' | xargs grep -l 'def test_' | awk '{
# Remove ./ prefix, file extension, and replace / with .
gsub(/^\.\//, "", $0)
gsub(/\.py$/, "", $0)
gsub(/\//, ".", $0)
# Add to array
tests[NR] = $0
}
END {
# Start JSON array
printf "{\n \"include\": [\n"
# Loop through array and create JSON objects
for (i=1; i<=NR; i++) {
printf " {\"test\": \"%s\"}", tests[i]
if (i < NR) printf ","
printf "\n"
}
# Close JSON array
printf " ]\n}"
}')
# Output the matrix
echo "matrix=$(echo "$matrix" | jq -c)" >> $GITHUB_OUTPUT
# For debugging (optional)
echo "Generated matrix:"
echo "$matrix"
test:
needs: discover
runs-on: ubuntu-latest
timeout-minutes: 60
env:
NODE_ENV: "production"
strategy:
fail-fast: false
matrix: ${{fromJson(needs.discover.outputs.matrix)}}
name: Test
services:
mysql:
image: mariadb:10.6
env:
MARIADB_ROOT_PASSWORD: 'root'
ports:
- 3306:3306
options: --health-cmd="mariadb-admin ping" --health-interval=5s --health-timeout=2s --health-retries=3
steps:
- name: Clone
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 18
check-latest: true
- name: Add to Hosts
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
- name: Cache pip
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml') }}
restore-keys: |
${{ runner.os }}-pip-
${{ runner.os }}-
- name: Cache node modules
uses: actions/cache@v4
env:
cache-name: cache-node-modules
with:
path: ~/.npm
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v4
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install
run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
env:
DB: mariadb
TYPE: server
FRAPPE_USER: ${{ github.event.inputs.user }}
FRAPPE_BRANCH: ${{ github.event.inputs.branch }}
- name: Run Tests
run: 'cd ~/frappe-bench/ && bench --site test_site run-tests --app erpnext --module ${{ matrix.test }}'

View File

@@ -0,0 +1,24 @@
# Tests are skipped for these files but github doesn't allow "passing" hence this is required.
name: Skipped Tests
on:
pull_request:
paths:
- "**.js"
- "**.css"
- "**.md"
- "**.html"
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
container: [1, 2, 3, 4]
name: Python Unit Tests
steps:
- name: Pass skipped tests unconditionally
run: "echo Skipped"

View File

@@ -1,6 +1,11 @@
name: Server (Mariadb)
on:
<<<<<<< HEAD
=======
repository_dispatch:
types: [frappe-framework-change]
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
pull_request:
paths-ignore:
- '**.js'
@@ -31,6 +36,12 @@ jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 60
<<<<<<< HEAD
=======
env:
NODE_ENV: "production"
WITH_COVERAGE: ${{ github.event_name != 'pull_request' }}
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
strategy:
fail-fast: false
@@ -51,12 +62,21 @@ jobs:
steps:
- name: Clone
<<<<<<< HEAD
uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.11'
=======
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
- name: Check for valid Python & Merge Conflicts
run: |
@@ -67,7 +87,11 @@ jobs:
fi
- name: Setup Node
<<<<<<< HEAD
uses: actions/setup-node@v2
=======
uses: actions/setup-node@v4
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
with:
node-version: 18
check-latest: true
@@ -76,7 +100,11 @@ jobs:
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
- name: Cache pip
<<<<<<< HEAD
uses: actions/cache@v2
=======
uses: actions/cache@v4
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml') }}
@@ -85,7 +113,11 @@ jobs:
${{ runner.os }}-
- name: Cache node modules
<<<<<<< HEAD
uses: actions/cache@v2
=======
uses: actions/cache@v4
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
env:
cache-name: cache-node-modules
with:
@@ -100,7 +132,11 @@ jobs:
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
<<<<<<< HEAD
- uses: actions/cache@v2
=======
- uses: actions/cache@v4
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
@@ -114,6 +150,7 @@ jobs:
DB: mariadb
TYPE: server
FRAPPE_USER: ${{ github.event.inputs.user }}
<<<<<<< HEAD
FRAPPE_BRANCH: ${{ github.event.inputs.branch }}
- name: Run Tests
@@ -122,7 +159,47 @@ jobs:
TYPE: server
CI_BUILD_ID: ${{ github.run_id }}
ORCHESTRATOR_URL: http://test-orchestrator.frappe.io
=======
FRAPPE_BRANCH: ${{ github.event.client_payload.sha || github.event.inputs.branch }}
- name: Run Tests
run: 'cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --app erpnext --total-builds ${{ strategy.job-total }} --build-number ${{ matrix.container }}'
env:
TYPE: server
CAPTURE_COVERAGE: ${{ github.event_name != 'pull_request' }}
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
- name: Show bench output
if: ${{ always() }}
run: cat ~/frappe-bench/bench_start.log || true
<<<<<<< HEAD
=======
- name: Upload coverage data
uses: actions/upload-artifact@v3
if: github.event_name != 'pull_request'
with:
name: coverage-${{ matrix.container }}
path: /home/runner/frappe-bench/sites/coverage.xml
coverage:
name: Coverage Wrap Up
needs: test
runs-on: ubuntu-latest
if: ${{ github.event_name != 'pull_request' }}
steps:
- name: Clone
uses: actions/checkout@v4
- name: Download artifacts
uses: actions/download-artifact@v3
- name: Upload coverage data
uses: codecov/codecov-action@v4
with:
name: MariaDB
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true
verbose: true
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)

View File

@@ -41,12 +41,21 @@ jobs:
steps:
- name: Clone
<<<<<<< HEAD
uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.10'
=======
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
- name: Check for valid Python & Merge Conflicts
run: |
@@ -57,7 +66,11 @@ jobs:
fi
- name: Setup Node
<<<<<<< HEAD
uses: actions/setup-node@v2
=======
uses: actions/setup-node@v4
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
with:
node-version: 18
check-latest: true
@@ -66,7 +79,11 @@ jobs:
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
- name: Cache pip
<<<<<<< HEAD
uses: actions/cache@v2
=======
uses: actions/cache@v4
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml') }}
@@ -75,7 +92,11 @@ jobs:
${{ runner.os }}-
- name: Cache node modules
<<<<<<< HEAD
uses: actions/cache@v2
=======
uses: actions/cache@v4
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
env:
cache-name: cache-node-modules
with:
@@ -90,7 +111,11 @@ jobs:
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
<<<<<<< HEAD
- uses: actions/cache@v2
=======
- uses: actions/cache@v4
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}

13
.gitignore vendored
View File

@@ -2,7 +2,10 @@
*.py~
.DS_Store
conf.py
<<<<<<< HEAD
locale
=======
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
latest_updates.json
.wnf-lang-status
*.egg-info
@@ -15,5 +18,13 @@ __pycache__
*~
.idea/
.vscode/
<<<<<<< HEAD
node_modules/
.backportrc.json
.backportrc.json
=======
.helix/
node_modules/
.backportrc.json
# Aider AI Chat
.aider*
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)

View File

@@ -17,6 +17,10 @@ pull_request_rules:
- base=version-12
- base=version-14
- base=version-15
<<<<<<< HEAD
=======
- base=version-16
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
actions:
close:
comment:
@@ -24,6 +28,7 @@ pull_request_rules:
@{{author}}, thanks for the contribution, but we do not accept pull requests on a stable branch. Please raise PR on an appropriate hotfix branch.
https://github.com/frappe/erpnext/wiki/Pull-Request-Checklist#which-branch
<<<<<<< HEAD
- name: Auto-close PRs on pre-release branch
conditions:
- base=version-13-pre-release
@@ -34,6 +39,8 @@ pull_request_rules:
@{{author}}, pre-release branch is not maintained anymore. Releases are directly done by merging hotfix branch to stable branches.
=======
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
- name: backport to develop
conditions:
- label="backport develop"
@@ -54,6 +61,7 @@ pull_request_rules:
assignees:
- "{{ author }}"
<<<<<<< HEAD
- name: backport to version-14-pre-release
conditions:
- label="backport version-14-pre-release"
@@ -61,6 +69,15 @@ pull_request_rules:
backport:
branches:
- version-14-pre-release
=======
- name: backport to version-15-hotfix
conditions:
- label="backport version-15-hotfix"
actions:
backport:
branches:
- version-15-hotfix
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
assignees:
- "{{ author }}"
@@ -74,6 +91,7 @@ pull_request_rules:
assignees:
- "{{ author }}"
<<<<<<< HEAD
- name: backport to version-13-pre-release
conditions:
- label="backport version-13-pre-release"
@@ -103,6 +121,8 @@ pull_request_rules:
- version-12-pre-release
assignees:
- "{{ author }}"
=======
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
- name: Automatic merge on CI success and review
conditions:

View File

@@ -1,5 +1,5 @@
exclude: 'node_modules|.git'
default_stages: [pre-commit]
default_stages: [commit]
fail_fast: false

View File

@@ -1,5 +1,9 @@
{
<<<<<<< HEAD
"branches": ["version-15"],
=======
"branches": ["version-13"],
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"plugins": [
"@semantic-release/commit-analyzer", {
"preset": "angular",
@@ -21,4 +25,8 @@
],
"@semantic-release/github"
]
<<<<<<< HEAD
}
=======
}
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)

View File

@@ -3,11 +3,19 @@
# These owners will be the default owners for everything in
# the repo. Unless a later match takes precedence,
<<<<<<< HEAD
erpnext/accounts/ @deepeshgarg007 @ruthra-kumar
erpnext/assets/ @khushi8112 @deepeshgarg007
erpnext/regional @deepeshgarg007 @ruthra-kumar
erpnext/selling @deepeshgarg007 @ruthra-kumar
erpnext/support/ @deepeshgarg007
=======
erpnext/accounts/ @ruthra-kumar
erpnext/assets/ @khushi8112
erpnext/regional @ruthra-kumar
erpnext/selling @ruthra-kumar
erpnext/support/ @ruthra-kumar
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
pos*
erpnext/buying/ @rohitwaghchaure
@@ -17,8 +25,15 @@ erpnext/quality_management/ @rohitwaghchaure
erpnext/stock/ @rohitwaghchaure
erpnext/subcontracting @rohitwaghchaure
<<<<<<< HEAD
erpnext/controllers/ @deepeshgarg007 @rohitwaghchaure
erpnext/patches/ @deepeshgarg007
.github/ @deepeshgarg007
=======
erpnext/controllers/ @ruthra-kumar @rohitwaghchaure
erpnext/patches/ @ruthra-kumar
.github/ @ruthra-kumar
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
pyproject.toml @akhilnarang

View File

@@ -7,8 +7,12 @@
<p>ERP made simple</p>
</p>
<<<<<<< HEAD
[![CI](https://github.com/frappe/erpnext/actions/workflows/server-tests.yml/badge.svg?branch=develop)](https://github.com/frappe/erpnext/actions/workflows/server-tests.yml)
[![UI](https://github.com/erpnext/erpnext_ui_tests/actions/workflows/ui-tests.yml/badge.svg?branch=develop&event=schedule)](https://github.com/erpnext/erpnext_ui_tests/actions/workflows/ui-tests.yml)
=======
[![CI](https://github.com/frappe/erpnext/actions/workflows/server-tests-mariadb.yml/badge.svg?event=schedule)](https://github.com/frappe/erpnext/actions/workflows/server-tests-mariadb.yml)
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
[![Open Source Helpers](https://www.codetriage.com/frappe/erpnext/badges/users.svg)](https://www.codetriage.com/frappe/erpnext)
[![codecov](https://codecov.io/gh/frappe/erpnext/branch/develop/graph/badge.svg?token=0TwvyUg3I5)](https://codecov.io/gh/frappe/erpnext)
[![docker pulls](https://img.shields.io/docker/pulls/frappe/erpnext-worker.svg)](https://hub.docker.com/r/frappe/erpnext-worker)
@@ -62,7 +66,7 @@ New passwords will be created for the ERPNext "Administrator" user, the MariaDB
## Learning and community
1. [Frappe School](https://school.frappe.io) - Learn Frappe Framework and ERPNext from the various courses by the maintainers or from the community.
1. [Frappe School](https://frappe.school) - Learn Frappe Framework and ERPNext from the various courses by the maintainers or from the community.
2. [Official documentation](https://docs.erpnext.com/) - Extensive documentation for ERPNext.
3. [Discussion Forum](https://discuss.erpnext.com/) - Engage with community of ERPNext users and service providers.
4. [Telegram Group](https://erpnext_public.t.me) - Get instant help from huge community of users.
@@ -73,8 +77,11 @@ New passwords will be created for the ERPNext "Administrator" user, the MariaDB
1. [Issue Guidelines](https://github.com/frappe/erpnext/wiki/Issue-Guidelines)
1. [Report Security Vulnerabilities](https://erpnext.com/security)
1. [Pull Request Requirements](https://github.com/frappe/erpnext/wiki/Contribution-Guidelines)
<<<<<<< HEAD
1. [Translations](https://translate.erpnext.com)
=======
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
## License

3
babel_extractors.csv Normal file
View File

@@ -0,0 +1,3 @@
**/setup/setup_wizard/data/uom_data.json,erpnext.gettext.extractors.uom_data.extract
**/setup/doctype/incoterm/incoterms.csv,erpnext.gettext.extractors.incoterms.extract
**/setup/setup_wizard/data/*.txt,erpnext.gettext.extractors.lines_from_txt_file.extract
1 **/setup/setup_wizard/data/uom_data.json erpnext.gettext.extractors.uom_data.extract
2 **/setup/doctype/incoterm/incoterms.csv erpnext.gettext.extractors.incoterms.extract
3 **/setup/setup_wizard/data/*.txt erpnext.gettext.extractors.lines_from_txt_file.extract

10
crowdin.yml Normal file
View File

@@ -0,0 +1,10 @@
files:
- source: /erpnext/locale/main.pot
translation: /erpnext/locale/%two_letters_code%.po
pull_request_title: "fix: sync translations from crowdin"
pull_request_labels:
- translation
pull_request_reviewers:
- barredterra # change to your GitHub username if you copied this file
commit_message: "fix: %language% translations"
append_commit_message: false

View File

@@ -1,10 +1,20 @@
import functools
import inspect
<<<<<<< HEAD
import frappe
from frappe.utils.user import is_website_user
__version__ = "15.66.1"
__version__ = "15.45.4"
=======
from typing import TypeVar
import frappe
from frappe.model.document import Document
from frappe.utils.user import is_website_user
__version__ = "16.0.0-dev"
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
def get_default_company(user=None):
@@ -160,3 +170,37 @@ def check_app_permission():
return False
return True
<<<<<<< HEAD
=======
T = TypeVar("T")
def normalize_ctx_input(T: type) -> callable:
"""
Normalizes the first argument (ctx) of the decorated function by:
- Converting Document objects to dictionaries
- Parsing JSON strings
- Casting the result to the specified type T
"""
def decorator(func: callable):
# conserve annotations for frappe.utils.typing_validations
@functools.wraps(func, assigned=(a for a in functools.WRAPPER_ASSIGNMENTS if a != "__annotations__"))
def wrapper(ctx: T | Document | dict | str, *args, **kwargs):
if isinstance(ctx, Document):
ctx = T(**ctx.as_dict())
elif isinstance(ctx, dict):
ctx = T(**ctx)
else:
ctx = T(**frappe.parse_json(ctx))
return func(ctx, *args, **kwargs)
# set annotations from function
wrapper.__annotations__.update({k: v for k, v in func.__annotations__.items() if k != "ctx"})
return wrapper
return decorator
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)

View File

@@ -220,7 +220,11 @@ def calculate_monthly_amount(
if amount + already_booked_amount_in_account_currency > item.net_amount:
amount = item.net_amount - already_booked_amount_in_account_currency
<<<<<<< HEAD
if not (get_first_day(start_date) == start_date and get_last_day(end_date) == end_date):
=======
if get_first_day(start_date) != start_date or get_last_day(end_date) != end_date:
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
partial_month = flt(date_diff(end_date, start_date)) / flt(
date_diff(get_last_day(end_date), get_first_day(start_date))
)

View File

@@ -64,6 +64,11 @@
"label": "Is Group"
},
{
<<<<<<< HEAD
=======
"fetch_from": "parent_account.company",
"fetch_if_empty": 1,
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"fieldname": "company",
"fieldtype": "Link",
"in_standard_filter": 1,
@@ -106,6 +111,10 @@
"fieldname": "parent_account",
"fieldtype": "Link",
"ignore_user_permissions": 1,
<<<<<<< HEAD
=======
"in_preview": 1,
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"label": "Parent Account",
"oldfieldname": "parent_account",
"oldfieldtype": "Link",
@@ -128,7 +137,7 @@
"description": "Rate at which this tax is applied",
"fieldname": "tax_rate",
"fieldtype": "Float",
"label": "Tax Rate",
"label": "Rate",
"oldfieldname": "tax_rate",
"oldfieldtype": "Currency"
},
@@ -248,8 +257,17 @@
],
"search_fields": "account_number",
"show_name_in_global_search": 1,
<<<<<<< HEAD
"sort_field": "modified",
"sort_order": "ASC",
"states": [],
"track_changes": 1
}
=======
"show_preview_popup": 1,
"sort_field": "creation",
"sort_order": "ASC",
"states": [],
"track_changes": 1
}
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)

View File

@@ -4,7 +4,7 @@
import frappe
from frappe import _, throw
from frappe.utils import add_to_date, cint, cstr, pretty_date
from frappe.utils import cint, cstr
from frappe.utils.nestedset import NestedSet, get_ancestors_of, get_descendants_of
import erpnext
@@ -92,9 +92,13 @@ class Account(NestedSet):
super().on_update()
def onload(self):
<<<<<<< HEAD
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")
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
if not frozen_accounts_modifier or frozen_accounts_modifier in frappe.get_roles():
self.set_onload("can_freeze_account", True)
@@ -481,7 +485,6 @@ def get_account_autoname(account_number, account_name, company):
@frappe.whitelist()
def update_account_number(name, account_name, account_number=None, from_descendant=False):
_ensure_idle_system()
account = frappe.get_cached_doc("Account", name)
if not account:
return
@@ -502,7 +505,7 @@ def update_account_number(name, account_name, account_number=None, from_descenda
"name",
)
if old_name and not from_descendant:
if old_name:
# same account in parent company exists
allow_child_account_creation = _("Allow Account Creation Against Child Company")
@@ -543,7 +546,6 @@ def update_account_number(name, account_name, account_number=None, from_descenda
@frappe.whitelist()
def merge_account(old, new):
_ensure_idle_system()
# Validate properties before merging
new_account = frappe.get_cached_doc("Account", new)
old_account = frappe.get_cached_doc("Account", old)
@@ -597,31 +599,3 @@ def sync_update_account_number_in_child(
for d in frappe.db.get_values("Account", filters=filters, fieldname=["company", "name"], as_dict=True):
update_account_number(d["name"], account_name, account_number, from_descendant=True)
def _ensure_idle_system():
# Don't allow renaming if accounting entries are actively being updated, there are two main reasons:
# 1. Correctness: It's next to impossible to ensure that renamed account is not being used *right now*.
# 2. Performance: Renaming requires locking out many tables entirely and severely degrades performance.
if frappe.flags.in_test:
return
last_gl_update = None
try:
# We also lock inserts to GL entry table with for_update here.
last_gl_update = frappe.db.get_value("GL Entry", {}, "modified", for_update=True, wait=False)
except frappe.QueryTimeoutError:
# wait=False fails immediately if there's an active transaction.
last_gl_update = add_to_date(None, seconds=-1)
if not last_gl_update:
return
if last_gl_update > add_to_date(None, minutes=-5):
frappe.throw(
_(
"Last GL Entry update was done {}. This operation is not allowed while system is actively being used. Please wait for 5 minutes before retrying."
).format(pretty_date(last_gl_update)),
title=_("System In Use"),
)

View File

@@ -81,7 +81,11 @@ 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;
<<<<<<< HEAD
const dr_or_cr = balance > 0 ? "Dr" : "Cr";
=======
const dr_or_cr = balance > 0 ? __("Dr") : __("Cr");
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
const format = (value, currency) => format_currency(Math.abs(value), currency);
if (account.balance !== undefined) {
@@ -138,11 +142,6 @@ frappe.treeview_settings["Account"] = {
description: __(
"Further accounts can be made under Groups, but entries can be made against non-Groups"
),
onchange: function () {
if (!this.value) {
this.layout.set_value("root_type", "");
}
},
},
{
fieldtype: "Select",
@@ -242,22 +241,19 @@ frappe.treeview_settings["Account"] = {
},
post_render: function (treeview) {
frappe.treeview_settings["Account"].treeview["tree"] = treeview.tree;
if (treeview.can_create) {
treeview.page.set_primary_action(
__("New"),
function () {
let root_company = treeview.page.fields_dict.root_company.get_value();
if (root_company) {
frappe.throw(__("Please add the account to root level Company - {0}"), [
root_company,
]);
} else {
treeview.new_node();
}
},
"add"
);
}
treeview.page.set_primary_action(
__("New"),
function () {
let root_company = treeview.page.fields_dict.root_company.get_value();
if (root_company) {
frappe.throw(__("Please add the account to root level Company - {0}"), [root_company]);
} else {
treeview.new_node();
}
},
"add"
);
},
toolbar: [
{

View File

@@ -75,7 +75,11 @@ def create_charts(
# after all accounts are already inserted.
frappe.local.flags.ignore_update_nsm = True
_import_accounts(chart, None, None, root_account=True)
<<<<<<< HEAD
rebuild_tree("Account", "parent_account")
=======
rebuild_tree("Account")
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
frappe.local.flags.ignore_update_nsm = False
@@ -116,7 +120,6 @@ def identify_is_group(child):
return is_group
@frappe.whitelist()
def get_chart(chart_template, existing_company=None):
chart = {}
if existing_company:
@@ -233,6 +236,11 @@ 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
<<<<<<< HEAD
=======
if child.account_currency:
tree[child.account_name]["account_currency"] = child.account_currency
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
if not parent:
tree[child.account_name]["root_type"] = child.root_type

View File

@@ -1,532 +0,0 @@
{
"country_code": "ch",
"name": "240812 Schulkontenrahmen VEB - DE",
"tree": {
"Aktiven": {
"account_number": "1",
"is_group": 1,
"root_type": "Asset",
"Umlaufvermögen": {
"account_number": "10",
"is_group": 1,
"Flüssige Mittel": {
"account_number": "100",
"is_group": 1,
"Kasse": {
"account_number": "1000",
"account_type": "Cash"
},
"Bankguthaben": {
"account_number": "1020",
"account_type": "Bank"
}
},
"Kurzfristig gehaltene Aktiven mit Börsenkurs": {
"account_number": "106",
"is_group": 1,
"Wertschriften": {
"account_number": "1060"
},
"Wertberichtigungen Wertschriften": {
"account_number": "1069"
}
},
"Forderungen aus Lieferungen und Leistungen": {
"account_number": "110",
"is_group": 1,
"Forderungen aus Lieferungen und Leistungen (Debitoren)": {
"account_number": "1100"
},
"Delkredere": {
"account_number": "1109"
}
},
"Übrige kurzfristige Forderungen": {
"account_number": "114",
"is_group": 1,
"Vorschüsse und Darlehen": {
"account_number": "1140"
},
"Wertberichtigungen Vorschüsse und Darlehen": {
"account_number": "1149"
},
"Vorsteuer MWST Material, Waren, Dienstleistungen, Energie": {
"account_number": "1170"
},
"Vorsteuer MWST Investitionen, übriger Betriebsaufwand": {
"account_number": "1171"
},
"Verrechnungssteuer": {
"account_number": "1176"
},
"Forderungen gegenüber Sozialversicherungen und Vorsorgeeinrichtungen": {
"account_number": "1180"
},
"Quellensteuer": {
"account_number": "1189"
},
"Sonstige kurzfristige Forderungen": {
"account_number": "1190"
},
"Wertberichtigungen sonstige kurzfristige Forderungen": {
"account_number": "1199"
}
},
"Vorräte und nicht fakturierte Dienstleistungen": {
"account_number": "120",
"is_group": 1,
"Handelswaren": {
"account_number": "1200"
},
"Rohstoffe": {
"account_number": "1210"
},
"Werkstoffe": {
"account_number": "1220"
},
"Hilfs- und Verbrauchsmaterial": {
"account_number": "1230"
},
"Handelswaren in Konsignation": {
"account_number": "1250"
},
"Fertige Erzeugnisse": {
"account_number": "1260"
},
"Unfertige Erzeugnisse": {
"account_number": "1270"
},
"Nicht fakturierte Dienstleistungen": {
"account_number": "1280"
}
},
"Aktive Rechnungsabgrenzungen": {
"account_number": "130",
"is_group": 1,
"Bezahlter Aufwand des Folgejahres": {
"account_number": "1300"
},
"Noch nicht erhaltener Ertrag": {
"account_number": "1301"
}
}
},
"Anlagevermögen": {
"account_number": "14",
"is_group": 1,
"Finanzanlagen": {
"account_number": "140",
"is_group": 1,
"Wertschriften": {
"account_number": "1400"
},
"Wertberichtigungen Wertschriften": {
"account_number": "1409"
},
"Darlehen": {
"account_number": "1440"
},
"Hypotheken": {
"account_number": "1441"
},
"Wertberichtigungen langfristige Forderungen": {
"account_number": "1449"
}
},
"Beteiligungen": {
"account_number": "148",
"is_group": 1,
"Beteiligungen": {
"account_number": "1480"
},
"Wertberichtigungen Beteiligungen": {
"account_number": "1489"
}
},
"Mobile Sachanlagen": {
"account_number": "150",
"is_group": 1,
"Maschinen und Apparate": {
"account_number": "1500"
},
"Wertberichtigungen Maschinen und Apparate": {
"account_number": "1509"
},
"Mobiliar und Einrichtungen": {
"account_number": "1510"
},
"Wertberichtigungen Mobiliar und Einrichtungen": {
"account_number": "1519"
},
"Büromaschinen, Informatik, Kommunikationstechnologie": {
"account_number": "1520"
},
"Wertberichtigungen Büromaschinen, Informatik, Kommunikationstechnologie": {
"account_number": "1529"
},
"Fahrzeuge": {
"account_number": "1530"
},
"Wertberichtigungen Fahrzeuge": {
"account_number": "1539"
},
"Werkzeuge und Geräte": {
"account_number": "1540"
},
"Wertberichtigungen Werkzeuge und Geräte": {
"account_number": "1549"
}
},
"Immobile Sachanlagen": {
"account_number": "160",
"is_group": 1,
"Geschäftsliegenschaften": {
"account_number": "1600"
},
"Wertberichtigungen Geschäftsliegenschaften": {
"account_number": "1609"
}
},
"Immaterielle Werte": {
"account_number": "170",
"is_group": 1,
"Patente, Know-how, Lizenzen, Rechte, Entwicklungen": {
"account_number": "1700"
},
"Wertberichtigungen Patente, Know-how, Lizenzen, Rechte, Entwicklungen": {
"account_number": "1709"
},
"Goodwill": {
"account_number": "1770"
},
"Wertberichtigungen Goodwill": {
"account_number": "1779"
}
},
"Nicht einbezahltes Grund-, Gesellschafter- oder Stiftungskapital": {
"account_number": "180",
"is_group": 1,
"Nicht einbezahltes Aktien-, Stamm-, Anteilschein- oder Stiftungskapital": {
"account_number": "1850"
}
}
}
},
"Passiven": {
"account_number": "2",
"is_group": 1,
"root_type": "Liability",
"Kurzfristiges Fremdkapital": {
"account_number": "20",
"is_group": 1,
"Verbindlichkeiten aus Lieferungen und Leistungen": {
"account_number": "200",
"is_group": 1,
"Verbindlichkeiten aus Lieferungen und Leistungen (Kreditoren)": {
"account_number": "2000"
},
"Erhaltene Anzahlungen": {
"account_number": "2030"
}
},
"Kurzfristige verzinsliche Verbindlichkeiten": {
"account_number": "210",
"is_group": 1,
"Bankverbindlichkeiten": {
"account_number": "2100"
},
"Verbindlichkeiten aus Finanzierungsleasing": {
"account_number": "2120"
},
"Übrige verzinsliche Verbindlichkeiten": {
"account_number": "2140"
}
},
"Übrige kurzfristige Verbindlichkeiten": {
"account_number": "220",
"is_group": 1,
"Geschuldete MWST (Umsatzsteuer)": {
"account_number": "2200"
},
"Abrechnungskonto MWST": {
"account_number": "2201"
},
"Verrechnungssteuer": {
"account_number": "2206"
},
"Direkte Steuern": {
"account_number": "2208"
},
"Sonstige kurzfristige Verbindlichkeiten": {
"account_number": "2210"
},
"Beschlossene Ausschüttungen": {
"account_number": "2261"
},
"Sozialversicherungen und Vorsorgeeinrichtungen": {
"account_number": "2270"
},
"Quellensteuer": {
"account_number": "2279"
}
},
"Passive Rechnungsabgrenzungen und kurzfristige Rückstellungen": {
"account_number": "230",
"is_group": 1,
"Noch nicht bezahlter Aufwand": {
"account_number": "2300"
},
"Erhaltener Ertrag des Folgejahres": {
"account_number": "2301"
},
"Kurzfristige Rückstellungen": {
"account_number": "2330"
}
}
},
"Langfristiges Fremdkapital": {
"account_number": "24",
"is_group": 1,
"Langfristige verzinsliche Verbindlichkeiten": {
"account_number": "240",
"is_group": 1,
"Bankverbindlichkeiten": {
"account_number": "2400"
},
"Verbindlichkeiten aus Finanzierungsleasing": {
"account_number": "2420"
},
"Obligationenanleihen": {
"account_number": "2430"
},
"Darlehen": {
"account_number": "2450"
},
"Hypotheken": {
"account_number": "2451"
}
},
"Übrige langfristige Verbindlichkeiten": {
"account_number": "250",
"is_group": 1,
"Übrige langfristige Verbindlichkeiten (unverzinslich)": {
"account_number": "2500"
}
},
"Rückstellungen sowie vom Gesetz vorgesehene ähnliche Positionen": {
"account_number": "260",
"is_group": 1,
"Rückstellungen": {
"account_number": "2600"
}
}
},
"Eigenkapital (juristische Personen)": {
"account_number": "28",
"is_group": 1,
"Grund-, Gesellschafter- oder Stiftungskapital": {
"account_number": "280",
"is_group": 1,
"Aktien-, Stamm-, Anteilschein- oder Stiftungskapital": {
"account_number": "2800"
}
},
"Reserven und Jahresgewinn oder Jahresverlust": {
"account_number": "290",
"is_group": 1,
"Gesetzliche Kapitalreserve": {
"account_number": "2900"
},
"Reserve für eigene Kapitalanteile": {
"account_number": "2930"
},
"Aufwertungsreserve": {
"account_number": "2940"
},
"Gesetzliche Gewinnreserve": {
"account_number": "2950"
},
"Freiwillige Gewinnreserven": {
"account_number": "2960"
},
"Gewinnvortrag oder Verlustvortrag": {
"account_number": "2970"
},
"Jahresgewinn oder Jahresverlust": {
"account_number": "2979"
},
"Eigene Aktien, Stammanteile oder Anteilscheine (Minusposten)": {
"account_number": "2980"
}
}
}
},
"Betrieblicher Ertrag aus Lieferungen und Leistungen": {
"account_number": "3",
"is_group": 1,
"root_type": "Income",
"Produktionserlöse": {
"account_number": "3000"
},
"Handelserlöse": {
"account_number": "3200"
},
"Dienstleistungserlöse": {
"account_number": "3400"
},
"Übrige Erlöse aus Lieferungen und Leistungen": {
"account_number": "3600"
},
"Eigenleistungen": {
"account_number": "3700"
},
"Eigenverbrauch": {
"account_number": "3710"
},
"Erlösminderungen": {
"account_number": "3800"
},
"Verluste Forderungen (Debitoren), Veränderung Delkredere": {
"account_number": "3805"
},
"Bestandesänderungen unfertige Erzeugnisse": {
"account_number": "3900"
},
"Bestandesänderungen fertige Erzeugnisse": {
"account_number": "3901"
},
"Bestandesänderungen nicht fakturierte Dienstleistungen": {
"account_number": "3940"
}
},
"Aufwand für Material, Handelswaren, Dienstleistungen und Energie": {
"account_number": "4",
"is_group": 1,
"root_type": "Expense",
"Materialaufwand Produktion": {
"account_number": "4000"
},
"Handelswarenaufwand": {
"account_number": "4200"
},
"Aufwand für bezogene Dienstleistungen": {
"account_number": "4400"
},
"Energieaufwand zur Leistungserstellung": {
"account_number": "4500"
},
"Aufwandminderungen": {
"account_number": "4900"
}
},
"Personalaufwand": {
"account_number": "5",
"is_group": 1,
"root_type": "Expense",
"Lohnaufwand": {
"account_number": "5000"
},
"Sozialversicherungsaufwand": {
"account_number": "5700"
},
"Übriger Personalaufwand": {
"account_number": "5800"
},
"Leistungen Dritter": {
"account_number": "5900"
}
},
"Übriger betrieblicher Aufwand, Abschreibungen und Wertberichtigungen sowie Finanzergebnis": {
"account_number": "6",
"is_group": 1,
"root_type": "Expense",
"Raumaufwand": {
"account_number": "6000"
},
"Unterhalt, Reparaturen, Ersatz mobile Sachanlagen": {
"account_number": "6100"
},
"Leasingaufwand mobile Sachanlagen": {
"account_number": "6105"
},
"Fahrzeug- und Transportaufwand": {
"account_number": "6200"
},
"Fahrzeugleasing und -mieten": {
"account_number": "6260"
},
"Sachversicherungen, Abgaben, Gebühren, Bewilligungen": {
"account_number": "6300"
},
"Energie- und Entsorgungsaufwand": {
"account_number": "6400"
},
"Verwaltungsaufwand": {
"account_number": "6500"
},
"Informatikaufwand inkl. Leasing": {
"account_number": "6570"
},
"Werbeaufwand": {
"account_number": "6600"
},
"Sonstiger betrieblicher Aufwand": {
"account_number": "6700"
},
"Abschreibungen und Wertberichtigungen auf Positionen des Anlagevermögens": {
"account_number": "6800"
},
"Finanzaufwand": {
"account_number": "6900"
},
"Finanzertrag": {
"account_number": "6950"
}
},
"Betrieblicher Nebenerfolg": {
"account_number": "7",
"is_group": 1,
"root_type": "Income",
"Ertrag Nebenbetrieb": {
"account_number": "7000"
},
"Aufwand Nebenbetrieb": {
"account_number": "7010"
},
"Ertrag betriebliche Liegenschaft": {
"account_number": "7500"
},
"Aufwand betriebliche Liegenschaft": {
"account_number": "7510"
}
},
"Betriebsfremder, ausserordentlicher, einmaliger oder periodenfremder Aufwand und Ertrag": {
"account_number": "8",
"is_group": 1,
"root_type": "Expense",
"Betriebsfremder Aufwand": {
"account_number": "8000"
},
"Betriebsfremder Ertrag": {
"account_number": "8100"
},
"Ausserordentlicher, einmaliger oder periodenfremder Aufwand": {
"account_number": "8500"
},
"Ausserordentlicher, einmaliger oder periodenfremder Ertrag": {
"account_number": "8510"
},
"Direkte Steuern": {
"account_number": "8900"
}
},
"Abschluss": {
"account_number": "9",
"is_group": 1,
"root_type": "Equity",
"Jahresgewinn oder Jahresverlust": {
"account_number": "9200"
}
}
}
}

View File

@@ -0,0 +1,569 @@
{
"country_code": "de",
"name": "SKR03 mit Kontonummern",
"tree": {
"Aktiva": {
"is_group": 1,
"root_type": "Asset",
"A - Anlagevermögen": {
"is_group": 1,
"EDV-Software": {
"account_number": "0027",
"account_type": "Fixed Asset"
},
"Geschäftsausstattung": {
"account_number": "0410",
"account_type": "Fixed Asset"
},
"Büroeinrichtung": {
"account_number": "0420",
"account_type": "Fixed Asset"
},
"Darlehen": {
"account_number": "0565"
},
"Maschinen": {
"account_number": "0210",
"account_type": "Fixed Asset"
},
"Betriebsausstattung": {
"account_number": "0400",
"account_type": "Fixed Asset"
},
"Ladeneinrichtung": {
"account_number": "0430",
"account_type": "Fixed Asset"
},
"Accumulated Depreciation": {
"account_type": "Accumulated Depreciation"
}
},
"B - Umlaufvermögen": {
"is_group": 1,
"I. Vorräte": {
"is_group": 1,
"Roh-, Hilfs- und Betriebsstoffe (Bestand)": {
"account_number": "3970",
"account_type": "Stock"
},
"Waren (Bestand)": {
"account_number": "3980",
"account_type": "Stock"
}
},
"II. Forderungen und sonstige Vermögensgegenstände": {
"is_group": 1,
"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": {
"account_number": "1590"
},
"Verrechnungskonto Gewinnermittlung § 4 Abs. 3 EStG, nicht ergebniswirksam": {
"account_number": "1371"
},
"Abziehbare Vorsteuer": {
"is_group": 1,
"Abziehbare Vorsteuer 7 %": {
"account_number": "1571",
"account_type": "Tax",
"tax_rate": 7.0
},
"Abziehbare Vorsteuer 19 %": {
"account_number": "1576",
"account_type": "Tax",
"tax_rate": 19.0
},
"Abziehbare Vorsteuer nach § 13b UStG 19 %": {
"account_number": "1577",
"account_type": "Tax",
"tax_rate": 19.0
}
}
},
"III. Wertpapiere": {
"is_group": 1,
"Anteile an verbundenen Unternehmen (Umlaufvermögen)": {
"account_number": "1340"
},
"Anteile an herrschender oder mit Mehrheit beteiligter Gesellschaft": {
"account_number": "1344"
},
"Sonstige Wertpapiere": {
"account_number": "1348"
}
},
"IV. Kassenbestand, Bundesbankguthaben, Guthaben bei Kreditinstituten und Schecks.": {
"is_group": 1,
"Kasse": {
"is_group": 1,
"account_type": "Cash",
"Kasse": {
"account_number": "1000",
"account_type": "Cash"
}
},
"Bank": {
"is_group": 1,
"account_type": "Bank",
"Postbank": {
"account_number": "1100",
"account_type": "Bank"
},
"Bankkonto": {
"account_number": "1200",
"account_type": "Bank"
}
}
}
},
"C - Rechnungsabgrenzungsposten": {
"is_group": 1,
"Aktive Rechnungsabgrenzung": {
"account_number": "0980"
}
},
"D - Aktive latente Steuern": {
"is_group": 1,
"Aktive latente Steuern": {
"account_number": "0983"
}
},
"E - Aktiver Unterschiedsbetrag aus der Vermögensverrechnung": {
"is_group": 1
}
},
"Passiva": {
"is_group": 1,
"root_type": "Liability",
"A. Eigenkapital": {
"is_group": 1,
"I. Gezeichnetes Kapital": {
"is_group": 1
},
"II. Kapitalrücklage": {
"is_group": 1
},
"III. Gewinnrücklagen": {
"is_group": 1
},
"IV. Gewinnvortrag/Verlustvortrag": {
"is_group": 1
},
"V. Jahresüberschuß/Jahresfehlbetrag": {
"is_group": 1
}
},
"B. Rückstellungen": {
"is_group": 1,
"I. Rückstellungen für Pensionen und ähnliche Verpflichtungen": {
"is_group": 1
},
"II. Steuerrückstellungen": {
"is_group": 1
},
"III. sonstige Rückstellungen": {
"is_group": 1
}
},
"C. Verbindlichkeiten": {
"is_group": 1,
"I. Anleihen": {
"is_group": 1
},
"II. Verbindlichkeiten gegenüber Kreditinstituten": {
"is_group": 1
},
"III. Erhaltene Anzahlungen auf Bestellungen": {
"is_group": 1
},
"IV. Verbindlichkeiten aus Lieferungen und Leistungen": {
"is_group": 1,
"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"
}
},
"V. Verbindlichkeiten aus der Annahme gezogener Wechsel und der Ausstellung eigener Wechsel": {
"is_group": 1
},
"VI. Verbindlichkeiten gegenüber verbundenen Unternehmen": {
"is_group": 1
},
"VII. Verbindlichkeiten gegenüber Unternehmen, mit denen ein Beteiligungsverhältnis besteht": {
"is_group": 1
},
"VIII. sonstige Verbindlichkeiten": {
"is_group": 1,
"Sonstige Verbindlichkeiten": {
"account_number": "1700",
"account_type": "Asset Received But Not Billed"
},
"Sonstige Verbindlichkeiten (1 bis 5 Jahre)": {
"account_number": "1702",
"account_type": "Stock Received But Not Billed"
},
"Verbindlichkeiten aus Lohn und Gehalt": {
"account_number": "1740",
"account_type": "Payable"
},
"Umsatzsteuer": {
"is_group": 1,
"Umsatzsteuer 7 %": {
"account_number": "1771",
"account_type": "Tax",
"tax_rate": 7.0
},
"Umsatzsteuer 19 %": {
"account_number": "1776",
"account_type": "Tax",
"tax_rate": 19.0
},
"Umsatzsteuer-Vorauszahlung": {
"account_number": "1780",
"account_type": "Tax"
},
"Umsatzsteuer-Vorauszahlung 1/11": {
"account_number": "1781"
},
"Umsatzsteuer nach § 13b UStG 19 %": {
"account_number": "1787",
"account_type": "Tax",
"tax_rate": 19.0
},
"Umsatzsteuer Vorjahr": {
"account_number": "1790"
},
"Umsatzsteuer frühere Jahre": {
"account_number": "1791"
}
}
}
},
"D. Rechnungsabgrenzungsposten": {
"is_group": 1,
"Passive Rechnungsabgrenzung": {
"account_number": "0990"
}
},
"E. Passive latente Steuern": {
"is_group": 1
}
},
"Erlöse u. Erträge 2/8": {
"is_group": 1,
"root_type": "Income",
"Erlöskonten 8": {
"is_group": 1,
"Erlöse": {
"account_number": "8200",
"account_type": "Income Account"
},
"Erlöse USt. 19 %": {
"account_number": "8400",
"account_type": "Income Account"
},
"Erlöse USt. 7 %": {
"account_number": "8300",
"account_type": "Income Account"
}
},
"Ertragskonten 2": {
"is_group": 1,
"sonstige Zinsen und ähnliche Erträge": {
"account_number": "2650",
"account_type": "Income Account"
},
"Außerordentliche Erträge": {
"account_number": "2500",
"account_type": "Income Account"
},
"Sonstige Erträge": {
"account_number": "2700",
"account_type": "Income Account"
}
}
},
"Aufwendungen 2/4": {
"is_group": 1,
"root_type": "Expense",
"Fremdleistungen": {
"account_number": "3100",
"account_type": "Expense Account"
},
"Fremdleistungen ohne Vorsteuer": {
"account_number": "3109",
"account_type": "Expense Account"
},
"Bauleistungen eines im Inland ansässigen Unternehmers 19 % Vorsteuer und 19 % Umsatzsteuer": {
"account_number": "3120",
"account_type": "Expense Account"
},
"Wareneingang": {
"account_number": "3200"
},
"Bezugsnebenkosten": {
"account_number": "3800",
"account_type": "Expenses Included In Asset Valuation"
},
"Herstellungskosten": {
"account_number": "4996",
"account_type": "Cost of Goods Sold"
},
"Verluste aus dem Abgang von Gegenständen des Anlagevermögens": {
"account_number": "2320",
"account_type": "Stock Adjustment"
},
"Verwaltungskosten": {
"account_number": "4997",
"account_type": "Expenses Included In Valuation"
},
"Vertriebskosten": {
"account_number": "4998",
"account_type": "Expenses Included In Valuation"
},
"Gegenkonto 4996-4998": {
"account_number": "4999"
},
"Abschreibungen": {
"is_group": 1,
"Abschreibungen auf Sachanlagen (ohne AfA auf Kfz und Gebäude)": {
"account_number": "4830",
"account_type": "Accumulated Depreciation"
},
"Abschreibungen auf Gebäude": {
"account_number": "4831",
"account_type": "Depreciation"
},
"Abschreibungen auf Kfz": {
"account_number": "4832",
"account_type": "Depreciation"
},
"Sofortabschreibung GWG": {
"account_number": "4855",
"account_type": "Expense Account"
}
},
"Kfz-Kosten": {
"is_group": 1,
"Kfz-Steuer": {
"account_number": "4510",
"account_type": "Expense Account"
},
"Kfz-Versicherungen": {
"account_number": "4520",
"account_type": "Expense Account"
},
"laufende Kfz-Betriebskosten": {
"account_number": "4530",
"account_type": "Expense Account"
},
"Kfz-Reparaturen": {
"account_number": "4540",
"account_type": "Expense Account"
},
"Fremdfahrzeuge": {
"account_number": "4570",
"account_type": "Expense Account"
},
"sonstige Kfz-Kosten": {
"account_number": "4580",
"account_type": "Expense Account"
}
},
"Personalkosten": {
"is_group": 1,
"Gehälter": {
"account_number": "4120",
"account_type": "Expense Account"
},
"gesetzliche soziale Aufwendungen": {
"account_number": "4130",
"account_type": "Expense Account"
},
"Aufwendungen für Altersvorsorge": {
"account_number": "4165",
"account_type": "Expense Account"
},
"Vermögenswirksame Leistungen": {
"account_number": "4170",
"account_type": "Expense Account"
},
"Aushilfslöhne": {
"account_number": "4190",
"account_type": "Expense Account"
}
},
"Raumkosten": {
"is_group": 1,
"Miete und Nebenkosten": {
"account_number": "4210",
"account_type": "Expense Account"
},
"Gas, Wasser, Strom (Verwaltung, Vertrieb)": {
"account_number": "4240",
"account_type": "Expense Account"
},
"Reinigung": {
"account_number": "4250",
"account_type": "Expense Account"
}
},
"Reparatur/Instandhaltung": {
"is_group": 1,
"Reparaturen und Instandhaltungen von anderen Anlagen und Betriebs- und Geschäftsausstattung": {
"account_number": "4805",
"account_type": "Expense Account"
}
},
"Versicherungsbeiträge": {
"is_group": 1,
"Versicherungen": {
"account_number": "4360",
"account_type": "Expense Account"
},
"Beiträge": {
"account_number": "4380",
"account_type": "Expense Account"
},
"sonstige Ausgaben": {
"account_number": "4390",
"account_type": "Expense Account"
},
"steuerlich abzugsfähige Verspätungszuschläge und Zwangsgelder": {
"account_number": "4396",
"account_type": "Expense Account"
}
},
"Werbe-/Reisekosten": {
"is_group": 1,
"Werbekosten": {
"account_number": "4610",
"account_type": "Expense Account"
},
"Aufmerksamkeiten": {
"account_number": "4653",
"account_type": "Expense Account"
},
"nicht abzugsfähige Betriebsausg. aus Werbe-, Repräs.- u. Reisekosten": {
"account_number": "4665",
"account_type": "Expense Account"
},
"Reisekosten Unternehmer": {
"account_number": "4670",
"account_type": "Expense Account"
}
},
"verschiedene Kosten": {
"is_group": 1,
"Porto": {
"account_number": "4910",
"account_type": "Expense Account"
},
"Telekom": {
"account_number": "4920",
"account_type": "Expense Account"
},
"Mobilfunk D2": {
"account_number": "4921",
"account_type": "Expense Account"
},
"Internet": {
"account_number": "4922",
"account_type": "Expense Account"
},
"Bürobedarf": {
"account_number": "4930",
"account_type": "Expense Account"
},
"Zeitschriften, Bücher": {
"account_number": "4940",
"account_type": "Expense Account"
},
"Fortbildungskosten": {
"account_number": "4945",
"account_type": "Expense Account"
},
"Buchführungskosten": {
"account_number": "4955",
"account_type": "Expense Account"
},
"Abschluß- u. Prüfungskosten": {
"account_number": "4957",
"account_type": "Expense Account"
},
"Nebenkosten des Geldverkehrs": {
"account_number": "4970",
"account_type": "Expense Account"
},
"Werkzeuge und Kleingeräte": {
"account_number": "4985",
"account_type": "Expense Account"
}
},
"Zinsaufwendungen": {
"is_group": 1,
"Zinsaufwendungen für kurzfristige Verbindlichkeiten": {
"account_number": "2110",
"account_type": "Expense Account"
},
"Zinsaufwendungen für KFZ Finanzierung": {
"account_number": "2121",
"account_type": "Expense Account"
}
}
},
"Anfangsbestand 9": {
"is_group": 1,
"root_type": "Equity",
"Saldenvortragskonten": {
"is_group": 1,
"Saldenvortrag Sachkonten": {
"account_number": "9000"
},
"Saldenvorträge Debitoren": {
"account_number": "9008"
},
"Saldenvorträge Kreditoren": {
"account_number": "9009"
}
}
},
"Privatkonten 1": {
"is_group": 1,
"root_type": "Equity",
"Privatentnahmen/-einlagen": {
"is_group": 1,
"Privatentnahme allgemein": {
"account_number": "1800"
},
"Privatsteuern": {
"account_number": "1810"
},
"Sonderausgaben beschränkt abzugsfähig": {
"account_number": "1820"
},
"Sonderausgaben unbeschränkt abzugsfähig": {
"account_number": "1830"
},
"Außergewöhnliche Belastungen": {
"account_number": "1850"
},
"Privateinlagen": {
"account_number": "1890"
}
}
}
}
}

View File

@@ -1653,4 +1653,8 @@
}
}
}
}
<<<<<<< HEAD
}
=======
}
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)

View File

@@ -36,6 +36,7 @@
}
},
"Fixed Assets": {
<<<<<<< HEAD
"Capital Equipments": {
"account_type": "Fixed Asset"
},
@@ -46,6 +47,18 @@
"account_type": "Fixed Asset"
},
"Office Equipments": {
=======
"Capital Equipment": {
"account_type": "Fixed Asset"
},
"Electronic Equipment": {
"account_type": "Fixed Asset"
},
"Furniture and Fixtures": {
"account_type": "Fixed Asset"
},
"Office Equipment": {
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"account_type": "Fixed Asset"
},
"Plants and Machineries": {
@@ -98,7 +111,7 @@
"Office Maintenance Expenses": {},
"Office Rent": {},
"Postal Expenses": {},
"Print and Stationery": {},
"Print and Stationary": {},
"Rounded Off": {
"account_type": "Round Off"
},

View File

@@ -1,6 +1,10 @@
{
"country_code": "ni",
<<<<<<< HEAD
"name": "Nicaragua - Catalogo de Cuentas",
=======
"name": "Nicaragua - Catálogo de Cuentas",
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"tree": {
"Activo": {
"Activo Corriente": {
@@ -491,4 +495,8 @@
"root_type": "Liability"
}
}
}
<<<<<<< HEAD
}
=======
}
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)

View File

@@ -23,6 +23,7 @@ def get():
_("Tax Assets"): {"is_group": 1},
},
_("Fixed Assets"): {
<<<<<<< HEAD
_("Capital Equipments"): {"account_type": "Fixed Asset"},
_("Electronic Equipments"): {"account_type": "Fixed Asset"},
_("Furnitures and Fixtures"): {"account_type": "Fixed Asset"},
@@ -30,6 +31,15 @@ def get():
_("Plants and Machineries"): {"account_type": "Fixed Asset"},
_("Buildings"): {"account_type": "Fixed Asset"},
_("Softwares"): {"account_type": "Fixed Asset"},
=======
_("Capital Equipment"): {"account_type": "Fixed Asset"},
_("Electronic Equipment"): {"account_type": "Fixed Asset"},
_("Furniture and Fixtures"): {"account_type": "Fixed Asset"},
_("Office Equipment"): {"account_type": "Fixed Asset"},
_("Plants and Machineries"): {"account_type": "Fixed Asset"},
_("Buildings"): {"account_type": "Fixed Asset"},
_("Software"): {"account_type": "Fixed Asset"},
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
_("Accumulated Depreciation"): {"account_type": "Accumulated Depreciation"},
_("CWIP Account"): {
"account_type": "Capital Work in Progress",

View File

@@ -36,6 +36,7 @@ def get():
"account_number": "1100-1600",
},
_("Fixed Assets"): {
<<<<<<< HEAD
_("Capital Equipments"): {"account_type": "Fixed Asset", "account_number": "1710"},
_("Electronic Equipments"): {"account_type": "Fixed Asset", "account_number": "1720"},
_("Furnitures and Fixtures"): {"account_type": "Fixed Asset", "account_number": "1730"},
@@ -43,6 +44,15 @@ def get():
_("Plants and Machineries"): {"account_type": "Fixed Asset", "account_number": "1750"},
_("Buildings"): {"account_type": "Fixed Asset", "account_number": "1760"},
_("Softwares"): {"account_type": "Fixed Asset", "account_number": "1770"},
=======
_("Capital Equipment"): {"account_type": "Fixed Asset", "account_number": "1710"},
_("Electronic Equipment"): {"account_type": "Fixed Asset", "account_number": "1720"},
_("Furniture and Fixtures"): {"account_type": "Fixed Asset", "account_number": "1730"},
_("Office Equipment"): {"account_type": "Fixed Asset", "account_number": "1740"},
_("Plants and Machineries"): {"account_type": "Fixed Asset", "account_number": "1750"},
_("Buildings"): {"account_type": "Fixed Asset", "account_number": "1760"},
_("Software"): {"account_type": "Fixed Asset", "account_number": "1770"},
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
_("Accumulated Depreciation"): {
"account_type": "Accumulated Depreciation",
"account_number": "1780",

View File

@@ -1,11 +1,18 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
<<<<<<< HEAD
import unittest
import frappe
from frappe.test_runner import make_test_records
=======
import unittest
import frappe
from frappe.tests import IntegrationTestCase
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
from frappe.utils import nowdate
from erpnext.accounts.doctype.account.account import (
@@ -15,10 +22,17 @@ from erpnext.accounts.doctype.account.account import (
)
from erpnext.stock import get_company_default_inventory_account, get_warehouse_account
<<<<<<< HEAD
test_dependencies = ["Company"]
class TestAccount(unittest.TestCase):
=======
EXTRA_TEST_RECORD_DEPENDENCIES = ["Company"]
class TestAccount(IntegrationTestCase):
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
def test_rename_account(self):
if not frappe.db.exists("Account", "1210 - Debtors - _TC"):
acc = frappe.new_doc("Account")
@@ -120,7 +134,11 @@ class TestAccount(unittest.TestCase):
InvalidAccountMergeError,
merge_account,
"Capital Stock - _TC",
<<<<<<< HEAD
"Softwares - _TC",
=======
"Software - _TC",
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
)
# Raise error as currency doesn't match
@@ -203,8 +221,11 @@ class TestAccount(unittest.TestCase):
In a parent->child company setup, child should inherit parent account currency if explicitly specified.
"""
<<<<<<< HEAD
make_test_records("Company")
=======
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
frappe.local.flags.pop("ignore_root_company_validation", None)
def create_bank_account():
@@ -328,7 +349,11 @@ class TestAccount(unittest.TestCase):
def _make_test_records(verbose=None):
<<<<<<< HEAD
from frappe.test_runner import make_test_objects
=======
from frappe.tests.utils import make_test_objects
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
accounts = [
# [account_name, parent_account, is_group]

View File

@@ -0,0 +1,3 @@
[[Account]]
name = "_Test Account 1"

View File

@@ -129,7 +129,11 @@
"icon": "fa fa-list",
"in_create": 1,
"links": [],
<<<<<<< HEAD
"modified": "2023-03-06 08:56:36.393237",
=======
"modified": "2024-03-27 13:05:56.710541",
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"modified_by": "Administrator",
"module": "Accounts",
"name": "Account Closing Balance",
@@ -158,7 +162,11 @@
"role": "Auditor"
}
],
<<<<<<< HEAD
"sort_field": "modified",
=======
"sort_field": "creation",
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"sort_order": "DESC",
"states": []
}

View File

@@ -2,8 +2,24 @@
# See license.txt
# import frappe
<<<<<<< HEAD
from frappe.tests.utils import FrappeTestCase
class TestAccountClosingBalance(FrappeTestCase):
=======
from frappe.tests import IntegrationTestCase, UnitTestCase
class UnitTestAccountClosingBalance(UnitTestCase):
"""
Unit tests for AccountClosingBalance.
Use this class for testing individual functions and methods.
"""
pass
class TestAccountClosingBalance(IntegrationTestCase):
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
pass

View File

@@ -31,8 +31,7 @@
"label": "Reference Document Type",
"options": "DocType",
"read_only_depends_on": "eval:!doc.__islocal",
"reqd": 1,
"search_index": 1
"reqd": 1
},
{
"default": "0",
@@ -50,7 +49,11 @@
}
],
"links": [],
<<<<<<< HEAD
"modified": "2021-02-08 16:37:53.936656",
=======
"modified": "2024-03-27 13:05:56.890002",
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounting Dimension",
@@ -81,7 +84,13 @@
"write": 1
}
],
<<<<<<< HEAD
"sort_field": "modified",
"sort_order": "ASC",
=======
"sort_field": "creation",
"sort_order": "ASC",
"states": [],
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"track_changes": 1
}

View File

@@ -41,11 +41,6 @@ class AccountingDimension(Document):
self.set_fieldname_and_label()
def validate(self):
self.validate_doctype()
validate_column_name(self.fieldname)
self.validate_dimension_defaults()
def validate_doctype(self):
if self.document_type in (
*core_doctypes_list,
"Accounting Dimension",
@@ -54,7 +49,6 @@ class AccountingDimension(Document):
"Accounting Dimension Detail",
"Company",
"Account",
"Finance Book",
):
msg = _("Not allowed to create accounting dimension for {0}").format(self.document_type)
frappe.throw(msg)
@@ -67,6 +61,9 @@ class AccountingDimension(Document):
if not self.is_new():
self.validate_document_type_change()
validate_column_name(self.fieldname)
self.validate_dimension_defaults()
def validate_document_type_change(self):
doctype_before_save = frappe.db.get_value("Accounting Dimension", self.name, "document_type")
if doctype_before_save != self.document_type:
@@ -105,7 +102,6 @@ class AccountingDimension(Document):
def on_update(self):
frappe.flags.accounting_dimensions = None
frappe.flags.accounting_dimensions_details = None
def make_dimension_in_accounting_doctypes(doc, doclist=None):
@@ -266,7 +262,7 @@ def get_checks_for_pl_and_bs_accounts():
frappe.flags.accounting_dimensions_details = frappe.db.sql(
"""SELECT p.label, p.disabled, p.fieldname, c.default_dimension, c.company, c.mandatory_for_pl, c.mandatory_for_bs
FROM `tabAccounting Dimension`p ,`tabAccounting Dimension Detail` c
WHERE p.name = c.parent AND p.disabled = 0""",
WHERE p.name = c.parent""",
as_dict=1,
)

View File

@@ -1,17 +1,31 @@
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
<<<<<<< HEAD
import unittest
import frappe
=======
import unittest
import frappe
from frappe.tests import IntegrationTestCase
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
<<<<<<< HEAD
test_dependencies = ["Cost Center", "Location", "Warehouse", "Department"]
class TestAccountingDimension(unittest.TestCase):
=======
EXTRA_TEST_RECORD_DEPENDENCIES = ["Cost Center", "Location", "Warehouse", "Department"]
class TestAccountingDimension(IntegrationTestCase):
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
def setUp(self):
create_dimension()

View File

@@ -1,4 +1,8 @@
{
<<<<<<< HEAD
=======
"actions": [],
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"creation": "2019-07-16 17:53:18.718831",
"doctype": "DocType",
"editable_grid": 1,
@@ -73,13 +77,24 @@
}
],
"istable": 1,
<<<<<<< HEAD
"modified": "2019-08-15 11:59:09.389891",
=======
"links": [],
"modified": "2024-03-27 13:05:57.056874",
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounting Dimension Detail",
"owner": "Administrator",
"permissions": [],
<<<<<<< HEAD
"sort_field": "modified",
"sort_order": "DESC",
=======
"sort_field": "creation",
"sort_order": "DESC",
"states": [],
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"track_changes": 1
}

View File

@@ -94,7 +94,11 @@
],
"index_web_pages_for_search": 1,
"links": [],
<<<<<<< HEAD
"modified": "2023-06-07 14:59:41.869117",
=======
"modified": "2024-03-27 13:05:57.199186",
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounting Dimension Filter",
@@ -139,7 +143,11 @@
}
],
"quick_entry": 1,
<<<<<<< HEAD
"sort_field": "modified",
=======
"sort_field": "creation",
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"sort_order": "DESC",
"states": [],
"track_changes": 1

View File

@@ -67,7 +67,10 @@ class AccountingDimensionFilter(Document):
def get_dimension_filter_map():
if not frappe.flags.get("dimension_filter_map"):
<<<<<<< HEAD
# nosemgrep
=======
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
filters = frappe.db.sql(
"""
SELECT

View File

@@ -12,7 +12,11 @@ from erpnext.accounts.doctype.accounting_dimension.test_accounting_dimension imp
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.exceptions import InvalidAccountDimensionError, MandatoryAccountDimensionError
<<<<<<< HEAD
test_dependencies = ["Location", "Cost Center", "Department"]
=======
EXTRA_TEST_RECORD_DEPENDENCIES = ["Location", "Cost Center", "Department"]
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
class TestAccountingDimensionFilter(unittest.TestCase):

View File

@@ -1,4 +1,5 @@
{
<<<<<<< HEAD
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
@@ -314,4 +315,116 @@
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0
=======
"actions": [],
"autoname": "field:period_name",
"creation": "2018-04-13 18:50:14.672323",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"period_name",
"start_date",
"end_date",
"column_break_4",
"company",
"section_break_7",
"closed_documents"
],
"fields": [
{
"fieldname": "period_name",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Period Name",
"reqd": 1,
"unique": 1
},
{
"fieldname": "start_date",
"fieldtype": "Date",
"in_list_view": 1,
"label": "Start Date",
"reqd": 1
},
{
"fieldname": "end_date",
"fieldtype": "Date",
"in_list_view": 1,
"label": "End Date",
"reqd": 1
},
{
"fieldname": "column_break_4",
"fieldtype": "Column Break"
},
{
"fieldname": "company",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Company",
"options": "Company",
"reqd": 1
},
{
"fieldname": "section_break_7",
"fieldtype": "Section Break"
},
{
"fieldname": "closed_documents",
"fieldtype": "Table",
"label": "Closed Documents",
"options": "Closed Document",
"reqd": 1
}
],
"links": [],
"modified": "2024-03-27 13:05:57.388109",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounting Period",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
},
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"share": 1,
"write": 1
},
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts User",
"share": 1,
"write": 1
}
],
"sort_field": "creation",
"sort_order": "DESC",
"states": [],
"track_changes": 1
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
}

View File

@@ -1,9 +1,16 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
<<<<<<< HEAD
import unittest
import frappe
=======
import unittest
import frappe
from frappe.tests import IntegrationTestCase
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
from frappe.utils import add_months, nowdate
from erpnext.accounts.doctype.accounting_period.accounting_period import (
@@ -12,10 +19,17 @@ from erpnext.accounts.doctype.accounting_period.accounting_period import (
)
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
<<<<<<< HEAD
test_dependencies = ["Item"]
class TestAccountingPeriod(unittest.TestCase):
=======
EXTRA_TEST_RECORD_DEPENDENCIES = ["Item"]
class TestAccountingPeriod(IntegrationTestCase):
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
def test_overlap(self):
ap1 = create_accounting_period(
start_date="2018-04-01", end_date="2018-06-30", company="Wind Power LLC"

View File

@@ -12,7 +12,7 @@ frappe.ui.form.on("Accounts Settings", {
msg += " ";
msg += __("Please enable only if the understand the effects of enabling this.");
msg += "<br>";
msg += __("Do you still want to enable immutable ledger?");
msg += "Do you still want to enable immutable ledger?";
frappe.confirm(
msg,
@@ -22,21 +22,4 @@ frappe.ui.form.on("Accounts Settings", {
}
);
},
add_taxes_from_taxes_and_charges_template(frm) {
toggle_tax_settings(frm, "add_taxes_from_taxes_and_charges_template");
},
add_taxes_from_item_tax_template(frm) {
toggle_tax_settings(frm, "add_taxes_from_item_tax_template");
},
});
function toggle_tax_settings(frm, field_name) {
if (frm.doc[field_name]) {
const other_field =
field_name === "add_taxes_from_item_tax_template"
? "add_taxes_from_taxes_and_charges_template"
: "add_taxes_from_item_tax_template";
frm.set_value(other_field, 0);
}
}

View File

@@ -31,7 +31,6 @@
"determine_address_tax_category_from",
"column_break_19",
"add_taxes_from_item_tax_template",
"add_taxes_from_taxes_and_charges_template",
"book_tax_discount_loss",
"round_row_wise_tax",
"print_settings",
@@ -39,22 +38,11 @@
"show_taxes_as_table_in_print",
"column_break_12",
"show_payment_schedule_in_print",
"item_price_settings_section",
"maintain_same_internal_transaction_rate",
"column_break_feyo",
"maintain_same_rate_action",
"role_to_override_stop_action",
"currency_exchange_section",
"allow_stale",
"allow_pegged_currencies_exchange_rates",
"column_break_yuug",
"stale_days",
"section_break_jpd0",
"auto_reconcile_payments",
"auto_reconciliation_job_trigger",
"reconciliation_queue_size",
"column_break_resa",
"exchange_gain_loss_posting_date",
"stale_days",
"invoicing_settings_tab",
"accounts_transactions_settings_section",
"over_billing_allowance",
@@ -86,10 +74,6 @@
"general_ledger_remarks_length",
"column_break_lvjk",
"receivable_payable_remarks_length",
"accounts_receivable_payable_tuning_section",
"receivable_payable_fetch_method",
"legacy_section",
"ignore_is_opening_check_for_reporting",
"payment_request_settings",
"create_pr_in_draft_status"
],
@@ -400,7 +384,7 @@
{
"fieldname": "section_break_jpd0",
"fieldtype": "Section Break",
"label": "Payment Reconciliation Settings"
"label": "Payment Reconciliations"
},
{
"default": "0",
@@ -505,110 +489,6 @@
"fieldname": "create_pr_in_draft_status",
"fieldtype": "Check",
"label": "Create in Draft Status"
},
{
"fieldname": "column_break_yuug",
"fieldtype": "Column Break"
},
{
"fieldname": "column_break_resa",
"fieldtype": "Column Break"
},
{
"default": "15",
"description": "Interval should be between 1 to 59 MInutes",
"fieldname": "auto_reconciliation_job_trigger",
"fieldtype": "Int",
"label": "Auto Reconciliation Job Trigger"
},
{
"default": "5",
"description": "Documents Processed on each trigger. Queue Size should be between 5 and 100",
"fieldname": "reconciliation_queue_size",
"fieldtype": "Int",
"label": "Reconciliation Queue Size"
},
{
"default": "0",
"description": "Ignores legacy Is Opening field in GL Entry that allows adding opening balance post the system is in use while generating reports",
"fieldname": "ignore_is_opening_check_for_reporting",
"fieldtype": "Check",
"label": "Ignore Is Opening check for reporting"
},
{
"default": "Payment",
"description": "Only applies for Normal Payments",
"fieldname": "exchange_gain_loss_posting_date",
"fieldtype": "Select",
"label": "Posting Date Inheritance for Exchange Gain / Loss",
"options": "Invoice\nPayment\nReconciliation Date"
},
{
"fieldname": "column_break_xrnd",
"fieldtype": "Column Break"
},
{
"default": "Buffered Cursor",
"fieldname": "receivable_payable_fetch_method",
"fieldtype": "Select",
"label": "Data Fetch Method",
"options": "Buffered Cursor\nUnBuffered Cursor"
},
{
"fieldname": "accounts_receivable_payable_tuning_section",
"fieldtype": "Section Break",
"label": "Accounts Receivable / Payable Tuning"
},
{
"fieldname": "legacy_section",
"fieldtype": "Section Break",
"label": "Legacy Fields"
},
{
"default": "0",
"fieldname": "maintain_same_internal_transaction_rate",
"fieldtype": "Check",
"label": "Maintain Same Rate Throughout Internal Transaction"
},
{
"default": "Stop",
"depends_on": "maintain_same_internal_transaction_rate",
"fieldname": "maintain_same_rate_action",
"fieldtype": "Select",
"label": "Action if Same Rate is Not Maintained Throughout Internal Transaction",
"mandatory_depends_on": "maintain_same_internal_transaction_rate",
"options": "Stop\nWarn"
},
{
"depends_on": "eval: doc.maintain_same_internal_transaction_rate && doc.maintain_same_rate_action == 'Stop'",
"fieldname": "role_to_override_stop_action",
"fieldtype": "Link",
"label": "Role Allowed to Override Stop Action",
"options": "Role"
},
{
"fieldname": "item_price_settings_section",
"fieldtype": "Section Break",
"label": "Item Price Settings"
},
{
"fieldname": "column_break_feyo",
"fieldtype": "Column Break"
},
{
"default": "0",
"description": "System will do an implicit conversion using the pegged currency. <br>\nEx: Instead of AED -&gt; INR, system will do AED -&gt; USD -&gt; INR using the pegged exchange rate of AED against USD.",
"documentation_url": "/app/pegged-currencies/Pegged Currencies",
"fieldname": "allow_pegged_currencies_exchange_rates",
"fieldtype": "Check",
"label": "Allow Implicit Pegged Currency Conversion"
},
{
"default": "0",
"description": "If no taxes are set, and Taxes and Charges Template is selected, the system will automatically apply the taxes from the chosen template.",
"fieldname": "add_taxes_from_taxes_and_charges_template",
"fieldtype": "Check",
"label": "Automatically Add Taxes from Taxes and Charges Template"
}
],
"icon": "icon-cog",
@@ -616,7 +496,7 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2025-06-23 15:55:33.346398",
"modified": "2024-07-26 06:48:52.714630",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",
@@ -641,8 +521,12 @@
}
],
"quick_entry": 1,
<<<<<<< HEAD
"sort_field": "modified",
=======
"sort_field": "creation",
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"sort_order": "ASC",
"states": [],
"track_changes": 1
}
}

View File

@@ -10,7 +10,6 @@ from frappe.custom.doctype.property_setter.property_setter import make_property_
from frappe.model.document import Document
from frappe.utils import cint
from erpnext.accounts.utils import sync_auto_reconcile_config
from erpnext.stock.utils import check_pending_reposting
@@ -25,12 +24,9 @@ class AccountsSettings(Document):
acc_frozen_upto: DF.Date | None
add_taxes_from_item_tax_template: DF.Check
add_taxes_from_taxes_and_charges_template: DF.Check
allow_multi_currency_invoices_against_single_party_account: DF.Check
allow_pegged_currencies_exchange_rates: DF.Check
allow_stale: DF.Check
auto_reconcile_payments: DF.Check
auto_reconciliation_job_trigger: DF.Int
automatically_fetch_payment_terms: DF.Check
automatically_process_deferred_accounting_entry: DF.Check
book_asset_depreciation_entry_automatically: DF.Check
@@ -47,22 +43,15 @@ class AccountsSettings(Document):
enable_fuzzy_matching: DF.Check
enable_immutable_ledger: DF.Check
enable_party_matching: DF.Check
exchange_gain_loss_posting_date: DF.Literal["Invoice", "Payment", "Reconciliation Date"]
frozen_accounts_modifier: DF.Link | None
general_ledger_remarks_length: DF.Int
ignore_account_closing_balance: DF.Check
ignore_is_opening_check_for_reporting: DF.Check
maintain_same_internal_transaction_rate: DF.Check
maintain_same_rate_action: DF.Literal["Stop", "Warn"]
make_payment_via_journal_entry: DF.Check
merge_similar_account_heads: DF.Check
over_billing_allowance: DF.Currency
post_change_gl_entries: DF.Check
receivable_payable_fetch_method: DF.Literal["Buffered Cursor", "UnBuffered Cursor"]
receivable_payable_remarks_length: DF.Int
reconciliation_queue_size: DF.Int
role_allowed_to_over_bill: DF.Link | None
role_to_override_stop_action: DF.Link | None
round_row_wise_tax: DF.Check
show_balance_in_coa: DF.Check
show_inclusive_tax_in_print: DF.Check
@@ -75,7 +64,6 @@ class AccountsSettings(Document):
# end: auto-generated types
def validate(self):
self.validate_auto_tax_settings()
old_doc = self.get_doc_before_save()
clear_cache = False
@@ -102,8 +90,6 @@ class AccountsSettings(Document):
if clear_cache:
frappe.clear_cache()
self.validate_and_sync_auto_reconcile_config()
def validate_stale_days(self):
if not self.allow_stale and cint(self.stale_days) <= 0:
frappe.msgprint(
@@ -128,27 +114,3 @@ class AccountsSettings(Document):
def validate_pending_reposts(self):
if self.acc_frozen_upto:
check_pending_reposting(self.acc_frozen_upto)
def validate_and_sync_auto_reconcile_config(self):
if self.has_value_changed("auto_reconciliation_job_trigger"):
if (
cint(self.auto_reconciliation_job_trigger) > 0
and cint(self.auto_reconciliation_job_trigger) < 60
):
sync_auto_reconcile_config(self.auto_reconciliation_job_trigger)
else:
frappe.throw(_("Cron Interval should be between 1 and 59 Min"))
if self.has_value_changed("reconciliation_queue_size"):
if cint(self.reconciliation_queue_size) < 5 or cint(self.reconciliation_queue_size) > 100:
frappe.throw(_("Queue Size should be between 5 and 100"))
def validate_auto_tax_settings(self):
if self.add_taxes_from_item_tax_template and self.add_taxes_from_taxes_and_charges_template:
frappe.throw(
_("You cannot enable both the settings '{0}' and '{1}'.").format(
frappe.bold(self.meta.get_label("add_taxes_from_item_tax_template")),
frappe.bold(self.meta.get_label("add_taxes_from_taxes_and_charges_template")),
),
title=_("Auto Tax Settings Error"),
)

View File

@@ -1,9 +1,16 @@
import unittest
import frappe
<<<<<<< HEAD
class TestAccountsSettings(unittest.TestCase):
=======
from frappe.tests import IntegrationTestCase
class TestAccountsSettings(IntegrationTestCase):
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
def tearDown(self):
# Just in case `save` method succeeds, we need to take things back to default so that other tests
# don't break

View File

@@ -2,7 +2,11 @@
# See license.txt
import frappe
<<<<<<< HEAD
from frappe.tests.utils import FrappeTestCase
=======
from frappe.tests import IntegrationTestCase, UnitTestCase
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
from frappe.utils import nowdate, today
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
@@ -10,8 +14,19 @@ from erpnext.accounts.test.accounts_mixin import AccountsTestMixin
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
<<<<<<< HEAD
class TestAdvancePaymentLedgerEntry(AccountsTestMixin, FrappeTestCase):
=======
# On IntegrationTestCase, the doctype test records and all
# link-field test record depdendencies are recursively loaded
# Use these module variables to add/remove to/from that list
EXTRA_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"]
IGNORE_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"]
class TestAdvancePaymentLedgerEntry(AccountsTestMixin, IntegrationTestCase):
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"""
Integration tests for AdvancePaymentLedgerEntry.
Use this class for testing interactions between multiple components.

View File

@@ -45,12 +45,22 @@
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
<<<<<<< HEAD
"modified": "2021-11-25 10:27:51.712286",
=======
"modified": "2024-03-27 13:05:58.308002",
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"modified_by": "Administrator",
"module": "Accounts",
"name": "Advance Tax",
"owner": "Administrator",
"permissions": [],
<<<<<<< HEAD
"sort_field": "modified",
"sort_order": "DESC"
=======
"sort_field": "creation",
"sort_order": "DESC",
"states": []
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
}

View File

@@ -13,6 +13,10 @@
"col_break_1",
"description",
"included_in_paid_amount",
<<<<<<< HEAD
=======
"set_by_item_tax_template",
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"accounting_dimensions_section",
"cost_center",
"dimension_col_break",
@@ -20,11 +24,19 @@
"rate",
"section_break_9",
"currency",
<<<<<<< HEAD
=======
"net_amount",
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"tax_amount",
"total",
"allocated_amount",
"column_break_13",
"base_tax_amount",
<<<<<<< HEAD
=======
"base_net_amount",
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"base_total"
],
"fields": [
@@ -101,7 +113,7 @@
"fieldname": "rate",
"fieldtype": "Float",
"in_list_view": 1,
"label": "Tax Rate",
"label": "Rate",
"oldfieldname": "rate",
"oldfieldtype": "Currency"
},
@@ -174,17 +186,58 @@
"label": "Account Currency",
"options": "Currency",
"read_only": 1
<<<<<<< HEAD
=======
},
{
"columns": 2,
"fieldname": "net_amount",
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Net Amount",
"options": "currency",
"read_only": 1
},
{
"fieldname": "base_net_amount",
"fieldtype": "Currency",
"label": "Net Amount (Company Currency)",
"oldfieldname": "tax_amount",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"read_only": 1
},
{
"default": "0",
"fieldname": "set_by_item_tax_template",
"fieldtype": "Check",
"hidden": 1,
"label": "Set by Item Tax Template",
"print_hide": 1,
"read_only": 1,
"report_hide": 1
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
<<<<<<< HEAD
"modified": "2021-11-25 11:10:10.945027",
=======
"modified": "2024-11-22 19:16:22.346267",
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"modified_by": "Administrator",
"module": "Accounts",
"name": "Advance Taxes and Charges",
"owner": "Administrator",
"permissions": [],
<<<<<<< HEAD
"sort_field": "modified",
"sort_order": "ASC"
=======
"sort_field": "creation",
"sort_order": "ASC",
"states": []
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
}

View File

@@ -18,6 +18,10 @@ class AdvanceTaxesandCharges(Document):
account_head: DF.Link
add_deduct_tax: DF.Literal["Add", "Deduct"]
allocated_amount: DF.Currency
<<<<<<< HEAD
=======
base_net_amount: DF.Currency
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
base_tax_amount: DF.Currency
base_total: DF.Currency
charge_type: DF.Literal[
@@ -27,11 +31,19 @@ class AdvanceTaxesandCharges(Document):
currency: DF.Link | None
description: DF.SmallText
included_in_paid_amount: DF.Check
<<<<<<< HEAD
=======
net_amount: DF.Currency
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
parent: DF.Data
parentfield: DF.Data
parenttype: DF.Data
rate: DF.Float
row_id: DF.Data | None
<<<<<<< HEAD
=======
set_by_item_tax_template: DF.Check
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
tax_amount: DF.Currency
total: DF.Currency
# end: auto-generated types

View File

@@ -14,30 +14,48 @@
"fieldtype": "Link",
"label": "Accounting Dimension",
"options": "DocType",
<<<<<<< HEAD
"read_only": 1,
"show_days": 1,
"show_seconds": 1
=======
"read_only": 1
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
},
{
"fieldname": "dimension_value",
"fieldtype": "Dynamic Link",
"in_list_view": 1,
<<<<<<< HEAD
"options": "accounting_dimension",
"show_days": 1,
"show_seconds": 1
=======
"options": "accounting_dimension"
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
<<<<<<< HEAD
"modified": "2020-11-23 09:56:19.744200",
=======
"modified": "2024-03-27 13:05:58.587487",
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"modified_by": "Administrator",
"module": "Accounts",
"name": "Allowed Dimension",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
<<<<<<< HEAD
"sort_field": "modified",
"sort_order": "DESC",
=======
"sort_field": "creation",
"sort_order": "DESC",
"states": [],
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"track_changes": 1
}

View File

@@ -20,14 +20,22 @@
],
"istable": 1,
"links": [],
<<<<<<< HEAD
"modified": "2024-01-03 11:13:02.669632",
=======
"modified": "2024-03-27 13:05:58.698893",
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"modified_by": "Administrator",
"module": "Accounts",
"name": "Allowed To Transact With",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
<<<<<<< HEAD
"sort_field": "modified",
=======
"sort_field": "creation",
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"sort_order": "DESC",
"states": [],
"track_changes": 1

View File

@@ -15,9 +15,13 @@
"in_list_view": 1,
"label": "Accounts",
"options": "Account",
<<<<<<< HEAD
"reqd": 1,
"show_days": 1,
"show_seconds": 1
=======
"reqd": 1
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
},
{
"columns": 2,
@@ -25,22 +29,36 @@
"fieldname": "is_mandatory",
"fieldtype": "Check",
"in_list_view": 1,
<<<<<<< HEAD
"label": "Is Mandatory",
"show_days": 1,
"show_seconds": 1
=======
"label": "Is Mandatory"
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
<<<<<<< HEAD
"modified": "2020-11-22 19:55:13.324136",
=======
"modified": "2024-03-27 13:05:59.168897",
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"modified_by": "Administrator",
"module": "Accounts",
"name": "Applicable On Account",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
<<<<<<< HEAD
"sort_field": "modified",
"sort_order": "DESC",
=======
"sort_field": "creation",
"sort_order": "DESC",
"states": [],
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"track_changes": 1
}

View File

@@ -101,7 +101,11 @@
}
],
"links": [],
<<<<<<< HEAD
"modified": "2020-07-17 14:00:13.105433",
=======
"modified": "2024-03-27 13:06:36.896195",
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank",
@@ -121,7 +125,13 @@
}
],
"quick_entry": 1,
<<<<<<< HEAD
"sort_field": "modified",
"sort_order": "DESC",
=======
"sort_field": "creation",
"sort_order": "DESC",
"states": [],
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"track_changes": 1
}

View File

@@ -1,8 +1,17 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
<<<<<<< HEAD
import unittest
class TestBank(unittest.TestCase):
=======
import unittest
from frappe.tests import IntegrationTestCase
class TestBank(IntegrationTestCase):
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
pass

View File

@@ -283,8 +283,16 @@
}
],
"search_fields": "bank,account",
<<<<<<< HEAD
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"track_changes": 1
}
=======
"sort_field": "creation",
"sort_order": "DESC",
"states": [],
"track_changes": 1
}
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)

View File

@@ -48,7 +48,7 @@ class BankAccount(Document):
self.name = self.account_name + " - " + self.bank
def on_trash(self):
delete_contact_and_address("Bank Account", self.name)
delete_contact_and_address("BankAccount", self.name)
def validate(self):
self.validate_company()
@@ -70,7 +70,11 @@ class BankAccount(Document):
def validate_company(self):
if self.is_company_account and not self.company:
<<<<<<< HEAD
frappe.throw(_("Company is manadatory for company account"))
=======
frappe.throw(_("Company is mandatory for company account"))
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
def validate_iban(self):
"""

View File

@@ -1,15 +1,25 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
<<<<<<< HEAD
=======
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
import unittest
import frappe
from frappe import ValidationError
<<<<<<< HEAD
# test_records = frappe.get_test_records('Bank Account')
class TestBankAccount(unittest.TestCase):
=======
from frappe.tests import IntegrationTestCase
class TestBankAccount(IntegrationTestCase):
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
def test_validate_iban(self):
valid_ibans = [
"GB82 WEST 1234 5698 7654 32",

View File

@@ -1,4 +1,5 @@
{
<<<<<<< HEAD
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
@@ -67,17 +68,50 @@
{
"amend": 0,
"cancel": 0,
=======
"actions": [],
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:account_subtype",
"creation": "2018-10-25 15:46:08.054586",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"account_subtype"
],
"fields": [
{
"fieldname": "account_subtype",
"fieldtype": "Data",
"label": "Account Subtype",
"unique": 1
}
],
"links": [],
"modified": "2024-03-27 13:06:37.221876",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Account Subtype",
"owner": "Administrator",
"permissions": [
{
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
<<<<<<< HEAD
"if_owner": 0,
"import": 0,
"permlevel": 0,
=======
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
<<<<<<< HEAD
"set_user_permissions": 0,
"share": 1,
"submit": 0,
@@ -86,17 +120,27 @@
{
"amend": 0,
"cancel": 0,
=======
"share": 1,
"write": 1
},
{
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
<<<<<<< HEAD
"if_owner": 0,
"import": 0,
"permlevel": 0,
=======
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
<<<<<<< HEAD
"set_user_permissions": 0,
"share": 1,
"submit": 0,
@@ -105,24 +149,38 @@
{
"amend": 0,
"cancel": 0,
=======
"share": 1,
"write": 1
},
{
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
<<<<<<< HEAD
"if_owner": 0,
"import": 0,
"permlevel": 0,
=======
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts User",
<<<<<<< HEAD
"set_user_permissions": 0,
"share": 1,
"submit": 0,
=======
"share": 1,
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"write": 1
}
],
"quick_entry": 1,
<<<<<<< HEAD
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
@@ -131,4 +189,9 @@
"track_changes": 0,
"track_seen": 0,
"track_views": 0
=======
"sort_field": "creation",
"sort_order": "DESC",
"states": []
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
}

View File

@@ -1,8 +1,17 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
<<<<<<< HEAD
import unittest
class TestBankAccountSubtype(unittest.TestCase):
=======
import unittest
from frappe.tests import IntegrationTestCase
class TestBankAccountSubtype(IntegrationTestCase):
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
pass

View File

@@ -19,7 +19,11 @@
}
],
"links": [],
<<<<<<< HEAD
"modified": "2020-04-10 21:13:09.137898",
=======
"modified": "2024-03-27 13:06:37.347035",
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Account Type",
@@ -63,6 +67,12 @@
}
],
"quick_entry": 1,
<<<<<<< HEAD
"sort_field": "modified",
"sort_order": "DESC"
=======
"sort_field": "creation",
"sort_order": "DESC",
"states": []
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
}

View File

@@ -1,9 +1,19 @@
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
<<<<<<< HEAD
# import frappe
import unittest
class TestBankAccountType(unittest.TestCase):
=======
# import frappe
import unittest
from frappe.tests import IntegrationTestCase
class TestBankAccountType(IntegrationTestCase):
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
pass

View File

@@ -91,7 +91,11 @@
"idx": 1,
"issingle": 1,
"links": [],
<<<<<<< HEAD
"modified": "2022-11-28 17:24:13.008692",
=======
"modified": "2024-03-27 13:06:37.477927",
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Clearance",
@@ -107,7 +111,11 @@
],
"quick_entry": 1,
"read_only": 1,
<<<<<<< HEAD
"sort_field": "modified",
=======
"sort_field": "creation",
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
"sort_order": "ASC",
"states": []
}

View File

@@ -117,9 +117,9 @@ class BankClearance(Document):
)
else:
# using db_set to trigger notification
payment_entry = frappe.get_doc(d.payment_document, d.payment_entry)
payment_entry.db_set("clearance_date", d.clearance_date)
frappe.db.set_value(
d.payment_document, d.payment_entry, "clearance_date", d.clearance_date
)
clearance_date_updated = True
@@ -159,6 +159,9 @@ def get_payment_entries_for_bank_clearance(
as_dict=1,
)
if bank_account:
condition += "and bank_account = %(bank_account)s"
payment_entries = frappe.db.sql(
f"""
select
@@ -180,6 +183,7 @@ def get_payment_entries_for_bank_clearance(
"account": account,
"from": from_date,
"to": to_date,
"bank_account": bank_account,
},
as_dict=1,
)

View File

@@ -1,15 +1,19 @@
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
<<<<<<< HEAD
import unittest
import frappe
=======
import unittest
import frappe
from frappe.tests import IntegrationTestCase
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
from frappe.utils import add_months, getdate
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
from erpnext.accounts.doctype.mode_of_payment.test_mode_of_payment import (
set_default_account_for_mode_of_payment,
)
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
@@ -18,9 +22,16 @@ from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
from erpnext.tests.utils import if_lending_app_installed, if_lending_app_not_installed
<<<<<<< HEAD
class TestBankClearance(unittest.TestCase):
@classmethod
def setUpClass(cls):
=======
class TestBankClearance(IntegrationTestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
create_warehouse(
warehouse_name="_Test Warehouse",
properties={"parent_warehouse": "All Warehouses - _TC"},
@@ -29,9 +40,12 @@ class TestBankClearance(unittest.TestCase):
create_item("_Test Item")
create_cost_center(cost_center_name="_Test Cost Center", company="_Test Company")
<<<<<<< HEAD
clear_payment_entries()
clear_loan_transactions()
clear_pos_sales_invoices()
=======
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
make_bank_account()
add_transactions()
@@ -126,6 +140,7 @@ class TestBankClearance(unittest.TestCase):
self.assertEqual(si_clearance_date, date)
<<<<<<< HEAD
def clear_payment_entries():
frappe.db.delete("Payment Entry")
@@ -143,6 +158,8 @@ def clear_loan_transactions():
frappe.db.delete(dt)
=======
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
def make_bank_account():
if not frappe.db.get_value("Account", "_Test Bank Clearance - _TC"):
frappe.get_doc(
@@ -194,13 +211,11 @@ def make_pos_sales_invoice():
customer = make_customer(customer="_Test Customer")
mode_of_payment = frappe.get_doc("Mode of Payment", "Wire Transfer")
set_default_account_for_mode_of_payment(mode_of_payment, "_Test Company", "_Test Bank Clearance - _TC")
si = create_sales_invoice(customer=customer, item="_Test Item", is_pos=1, qty=1, rate=1000, do_not_save=1)
si.set("payments", [])
si.append("payments", {"mode_of_payment": "Wire Transfer", "amount": 1000})
si.append(
"payments", {"mode_of_payment": "Cash", "account": "_Test Bank Clearance - _TC", "amount": 1000}
)
si.insert()
si.submit()

View File

@@ -1,4 +1,5 @@
{
<<<<<<< HEAD
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
@@ -337,4 +338,116 @@
"track_changes": 0,
"track_seen": 0,
"track_views": 0
=======
"actions": [],
"creation": "2013-02-22 01:27:37",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"payment_document",
"payment_entry",
"against_account",
"amount",
"column_break_5",
"posting_date",
"cheque_number",
"cheque_date",
"clearance_date"
],
"fields": [
{
"fieldname": "payment_document",
"fieldtype": "Link",
"label": "Payment Document",
"options": "DocType"
},
{
"columns": 2,
"fieldname": "payment_entry",
"fieldtype": "Dynamic Link",
"in_list_view": 1,
"label": "Payment Entry",
"oldfieldname": "voucher_id",
"oldfieldtype": "Link",
"options": "payment_document",
"width": "50"
},
{
"columns": 2,
"fieldname": "against_account",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Against Account",
"oldfieldname": "against_account",
"oldfieldtype": "Data",
"read_only": 1,
"width": "15"
},
{
"columns": 2,
"fieldname": "amount",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Amount",
"oldfieldname": "debit",
"oldfieldtype": "Currency",
"read_only": 1
},
{
"fieldname": "column_break_5",
"fieldtype": "Column Break",
"width": "50%"
},
{
"columns": 2,
"fieldname": "posting_date",
"fieldtype": "Date",
"label": "Posting Date",
"oldfieldname": "posting_date",
"oldfieldtype": "Date",
"read_only": 1
},
{
"columns": 2,
"fieldname": "cheque_number",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Cheque Number",
"oldfieldname": "cheque_number",
"oldfieldtype": "Data",
"read_only": 1
},
{
"fieldname": "cheque_date",
"fieldtype": "Date",
"label": "Cheque Date",
"oldfieldname": "cheque_date",
"oldfieldtype": "Date",
"read_only": 1
},
{
"columns": 2,
"fieldname": "clearance_date",
"fieldtype": "Date",
"in_list_view": 1,
"label": "Clearance Date",
"oldfieldname": "clearance_date",
"oldfieldtype": "Date"
}
],
"idx": 1,
"istable": 1,
"links": [],
"modified": "2024-03-27 13:06:37.609319",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Clearance Detail",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"sort_field": "creation",
"sort_order": "ASC",
"states": []
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
}

View File

@@ -1,4 +1,5 @@
{
<<<<<<< HEAD
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
@@ -1053,4 +1054,262 @@
"track_changes": 0,
"track_seen": 0,
"track_views": 0
=======
"actions": [],
"autoname": "ACC-BG-.YYYY.-.#####",
"creation": "2016-12-17 10:43:35.731631",
"doctype": "DocType",
"document_type": "Document",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"bg_type",
"reference_doctype",
"reference_docname",
"customer",
"supplier",
"project",
"column_break_6",
"amount",
"start_date",
"validity",
"end_date",
"bank_account_info",
"bank",
"bank_account",
"account",
"bank_account_no",
"column_break_17",
"iban",
"branch_code",
"swift_number",
"section_break_14",
"more_information",
"margin_details",
"bank_guarantee_number",
"name_of_beneficiary",
"column_break_19",
"margin_money",
"charges",
"fixed_deposit_number",
"amended_from"
],
"fields": [
{
"fieldname": "bg_type",
"fieldtype": "Select",
"label": "Bank Guarantee Type",
"options": "\nReceiving\nProviding",
"reqd": 1
},
{
"fieldname": "reference_doctype",
"fieldtype": "Link",
"label": "Reference Document Type",
"options": "DocType",
"read_only": 1
},
{
"fieldname": "reference_docname",
"fieldtype": "Dynamic Link",
"label": "Reference Document Name",
"options": "reference_doctype"
},
{
"depends_on": "eval: doc.bg_type == \"Receiving\"",
"fieldname": "customer",
"fieldtype": "Link",
"label": "Customer",
"options": "Customer"
},
{
"depends_on": "eval: doc.bg_type == \"Providing\"",
"fieldname": "supplier",
"fieldtype": "Link",
"label": "Supplier",
"options": "Supplier"
},
{
"allow_on_submit": 1,
"fieldname": "project",
"fieldtype": "Link",
"label": "Project",
"options": "Project"
},
{
"fieldname": "column_break_6",
"fieldtype": "Column Break"
},
{
"fieldname": "amount",
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Amount",
"reqd": 1
},
{
"fieldname": "start_date",
"fieldtype": "Date",
"label": "Start Date",
"reqd": 1
},
{
"fieldname": "validity",
"fieldtype": "Int",
"label": "Validity in Days"
},
{
"fieldname": "end_date",
"fieldtype": "Date",
"label": "End Date",
"read_only": 1
},
{
"fieldname": "bank_account_info",
"fieldtype": "Section Break",
"label": "Bank Account Info"
},
{
"fieldname": "bank",
"fieldtype": "Link",
"label": "Bank",
"options": "Bank"
},
{
"fieldname": "bank_account",
"fieldtype": "Link",
"label": "Bank Account",
"options": "Bank Account"
},
{
"fieldname": "account",
"fieldtype": "Link",
"label": "Account",
"options": "Account",
"read_only": 1
},
{
"fieldname": "bank_account_no",
"fieldtype": "Data",
"label": "Bank Account No",
"read_only": 1
},
{
"fieldname": "column_break_17",
"fieldtype": "Column Break"
},
{
"fieldname": "iban",
"fieldtype": "Data",
"label": "IBAN",
"read_only": 1
},
{
"fieldname": "branch_code",
"fieldtype": "Data",
"label": "Branch Code",
"read_only": 1
},
{
"fieldname": "swift_number",
"fieldtype": "Data",
"label": "SWIFT number",
"read_only": 1
},
{
"fieldname": "section_break_14",
"fieldtype": "Section Break"
},
{
"fieldname": "more_information",
"fieldtype": "Text Editor",
"label": "Clauses and Conditions"
},
{
"fieldname": "margin_details",
"fieldtype": "Section Break",
"label": "Other Details"
},
{
"fieldname": "bank_guarantee_number",
"fieldtype": "Data",
"label": "Bank Guarantee Number",
"unique": 1
},
{
"fieldname": "name_of_beneficiary",
"fieldtype": "Data",
"label": "Name of Beneficiary"
},
{
"fieldname": "column_break_19",
"fieldtype": "Column Break"
},
{
"fieldname": "margin_money",
"fieldtype": "Currency",
"label": "Margin Money"
},
{
"fieldname": "charges",
"fieldtype": "Currency",
"label": "Charges Incurred"
},
{
"fieldname": "fixed_deposit_number",
"fieldtype": "Data",
"label": "Fixed Deposit Number"
},
{
"fieldname": "amended_from",
"fieldtype": "Link",
"label": "Amended From",
"no_copy": 1,
"options": "Bank Guarantee",
"print_hide": 1,
"read_only": 1
}
],
"is_submittable": 1,
"links": [],
"modified": "2024-03-27 13:06:37.731207",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Guarantee",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts User",
"share": 1,
"submit": 1,
"write": 1
},
{
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"share": 1,
"submit": 1,
"write": 1
}
],
"quick_entry": 1,
"search_fields": "customer",
"sort_field": "creation",
"sort_order": "DESC",
"states": [],
"title_field": "customer"
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
}

View File

@@ -48,11 +48,19 @@ class BankGuarantee(Document):
def on_submit(self):
if not self.bank_guarantee_number:
<<<<<<< HEAD
frappe.throw(_("Enter the Bank Guarantee Number before submittting."))
if not self.name_of_beneficiary:
frappe.throw(_("Enter the name of the Beneficiary before submittting."))
if not self.bank:
frappe.throw(_("Enter the name of the bank or lending institution before submittting."))
=======
frappe.throw(_("Enter the Bank Guarantee Number before submitting."))
if not self.name_of_beneficiary:
frappe.throw(_("Enter the name of the Beneficiary before submitting."))
if not self.bank:
frappe.throw(_("Enter the name of the bank or lending institution before submitting."))
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
@frappe.whitelist()

View File

@@ -1,8 +1,17 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
<<<<<<< HEAD
import unittest
class TestBankGuarantee(unittest.TestCase):
=======
import unittest
from frappe.tests import IntegrationTestCase
class TestBankGuarantee(IntegrationTestCase):
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
pass

View File

@@ -19,15 +19,10 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
},
onload: function (frm) {
if (!frm.doc.company) {
frm.set_value("company", frappe.defaults.get_default("company"));
}
// Set default filter dates
let today = frappe.datetime.get_today();
frm.doc.bank_statement_from_date = frappe.datetime.add_months(today, -1);
frm.doc.bank_statement_to_date = today;
frm.trigger("bank_account");
},
@@ -103,7 +98,7 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
make_reconciliation_tool(frm) {
frm.get_field("reconciliation_tool_cards").$wrapper.empty();
if (frm.doc.company && frm.doc.bank_account && frm.doc.bank_statement_to_date) {
if (frm.doc.bank_account && frm.doc.bank_statement_to_date) {
frm.trigger("get_cleared_balance").then(() => {
if (
frm.doc.bank_account &&
@@ -119,13 +114,12 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
},
get_account_opening_balance(frm) {
if (frm.doc.company && frm.doc.bank_account && frm.doc.bank_statement_from_date) {
if (frm.doc.bank_account && frm.doc.bank_statement_from_date) {
frappe.call({
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_account_balance",
args: {
bank_account: frm.doc.bank_account,
till_date: frappe.datetime.add_days(frm.doc.bank_statement_from_date, -1),
company: frm.doc.company,
},
callback: (response) => {
frm.set_value("account_opening_balance", response.message);
@@ -135,13 +129,12 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
},
get_cleared_balance(frm) {
if (frm.doc.company && frm.doc.bank_account && frm.doc.bank_statement_to_date) {
if (frm.doc.bank_account && frm.doc.bank_statement_to_date) {
return frappe.call({
method: "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_to_date,
company: frm.doc.company,
},
callback: (response) => {
frm.cleared_balance = response.message;

View File

@@ -137,7 +137,14 @@
}
],
"quick_entry": 1,
<<<<<<< HEAD
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}
=======
"sort_field": "creation",
"sort_order": "DESC",
"states": []
}
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)

View File

@@ -8,12 +8,10 @@ import frappe
from frappe import _
from frappe.model.document import Document
from frappe.query_builder.custom import ConstantColumn
from frappe.query_builder.functions import Sum
from frappe.utils import cint, flt
from erpnext import get_default_cost_center
from erpnext.accounts.doctype.bank_transaction.bank_transaction import get_total_allocated_amount
from erpnext.accounts.party import get_party_account
from erpnext.accounts.report.bank_reconciliation_statement.bank_reconciliation_statement import (
get_amounts_not_reflected_in_system,
get_entries,
@@ -80,17 +78,10 @@ def get_bank_transactions(bank_account, from_date=None, to_date=None):
@frappe.whitelist()
def get_account_balance(bank_account, till_date, company):
def get_account_balance(bank_account, till_date):
# returns account balance till the specified date
account = frappe.db.get_value("Bank Account", bank_account, "account")
filters = frappe._dict(
{
"account": account,
"report_date": till_date,
"include_pos_transactions": 1,
"company": company,
}
)
filters = frappe._dict({"account": account, "report_date": till_date, "include_pos_transactions": 1})
data = get_entries(filters)
balance_as_per_system = get_balance_on(filters["account"], filters["report_date"])
@@ -102,7 +93,11 @@ def get_account_balance(bank_account, till_date, company):
amounts_not_reflected_in_system = get_amounts_not_reflected_in_system(filters)
return flt(balance_as_per_system) - flt(total_debit) + flt(total_credit) + amounts_not_reflected_in_system
bank_bal = (
flt(balance_as_per_system) - flt(total_debit) + flt(total_credit) + amounts_not_reflected_in_system
)
return bank_bal
@frappe.whitelist()
@@ -309,56 +304,54 @@ def create_payment_entry_bts(
bank_transaction = frappe.db.get_values(
"Bank Transaction",
bank_transaction_name,
fieldname=["name", "unallocated_amount", "deposit", "bank_account", "currency"],
fieldname=["name", "unallocated_amount", "deposit", "bank_account"],
as_dict=True,
)[0]
paid_amount = bank_transaction.unallocated_amount
payment_type = "Receive" if bank_transaction.deposit > 0.0 else "Pay"
bank_account = frappe.get_cached_value("Bank Account", bank_transaction.bank_account, "account")
company = frappe.get_cached_value("Account", bank_account, "company")
party_account = get_party_account(party_type, party, company)
company_account = frappe.get_value("Bank Account", bank_transaction.bank_account, "account")
company = frappe.get_value("Account", company_account, "company")
payment_entry_dict = {
"company": company,
"payment_type": payment_type,
"reference_no": reference_number,
"reference_date": reference_date,
"party_type": party_type,
"party": party,
"posting_date": posting_date,
"paid_amount": paid_amount,
"received_amount": paid_amount,
}
payment_entry = frappe.new_doc("Payment Entry")
bank_currency = bank_transaction.currency
party_currency = frappe.get_cached_value("Account", party_account, "account_currency")
payment_entry.update(payment_entry_dict)
exc_rate = get_exchange_rate(bank_currency, party_currency, posting_date)
if mode_of_payment:
payment_entry.mode_of_payment = mode_of_payment
if project:
payment_entry.project = project
if cost_center:
payment_entry.cost_center = cost_center
if payment_type == "Receive":
payment_entry.paid_to = company_account
else:
payment_entry.paid_from = company_account
amt_in_bank_acc_currency = bank_transaction.unallocated_amount
amount_in_party_currency = bank_transaction.unallocated_amount * exc_rate
pe = frappe.new_doc("Payment Entry")
pe.payment_type = payment_type
pe.company = company
pe.reference_no = reference_number
pe.reference_date = reference_date
pe.party_type = party_type
pe.party = party
pe.posting_date = posting_date
pe.paid_from = party_account if payment_type == "Receive" else bank_account
pe.paid_to = party_account if payment_type == "Pay" else bank_account
pe.paid_from_account_currency = party_currency if payment_type == "Receive" else bank_currency
pe.paid_to_account_currency = party_currency if payment_type == "Pay" else bank_currency
pe.paid_amount = amount_in_party_currency if payment_type == "Receive" else amt_in_bank_acc_currency
pe.received_amount = amount_in_party_currency if payment_type == "Pay" else amt_in_bank_acc_currency
pe.mode_of_payment = mode_of_payment
pe.project = project
pe.cost_center = cost_center
pe.validate()
payment_entry.validate()
if allow_edit:
return pe
return payment_entry
pe.insert()
pe.submit()
payment_entry.insert()
payment_entry.submit()
vouchers = json.dumps(
[
{
"payment_doctype": "Payment Entry",
"payment_name": pe.name,
"amount": amt_in_bank_acc_currency,
"payment_name": payment_entry.name,
"amount": paid_amount,
}
]
)
@@ -373,38 +366,11 @@ def auto_reconcile_vouchers(
filter_by_reference_date=None,
from_reference_date=None,
to_reference_date=None,
):
bank_transactions = get_bank_transactions(bank_account)
if len(bank_transactions) > 10:
frappe.enqueue(
method="erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.start_auto_reconcile",
queue="long",
bank_transactions=bank_transactions,
from_date=from_date,
to_date=to_date,
filter_by_reference_date=filter_by_reference_date,
from_reference_date=from_reference_date,
to_reference_date=to_reference_date,
)
frappe.msgprint(_("Auto Reconciliation has started in the background"))
else:
start_auto_reconcile(
bank_transactions,
from_date,
to_date,
filter_by_reference_date,
from_reference_date,
to_reference_date,
)
def start_auto_reconcile(
bank_transactions, from_date, to_date, filter_by_reference_date, from_reference_date, to_reference_date
):
frappe.flags.auto_reconcile_vouchers = True
reconciled, partially_reconciled = set(), set()
bank_transactions = get_bank_transactions(bank_account)
for transaction in bank_transactions:
linked_payments = get_linked_payments(
transaction.name,
@@ -442,6 +408,7 @@ def start_auto_reconcile(
frappe.msgprint(title=_("Auto Reconciliation"), msg=alert_message, indicator=indicator)
frappe.flags.auto_reconcile_vouchers = False
return reconciled, partially_reconciled
def get_auto_reconcile_message(partially_reconciled, reconciled):
@@ -513,28 +480,17 @@ def get_linked_payments(
def subtract_allocations(gl_account, vouchers):
"Look up & subtract any existing Bank Transaction allocations"
copied = []
voucher_docs = [(voucher.get("doctype"), voucher.get("name")) for voucher in vouchers]
voucher_allocated_amounts = get_total_allocated_amount(voucher_docs)
for voucher in vouchers:
if amount := get_allocated_amount(voucher_allocated_amounts, voucher, gl_account):
rows = get_total_allocated_amount(voucher.get("doctype"), voucher.get("name"))
filtered_row = list(filter(lambda row: row.get("gl_account") == gl_account, rows))
if amount := None if not filtered_row else filtered_row[0]["total"]:
voucher["paid_amount"] -= amount
copied.append(voucher)
return copied
def get_allocated_amount(voucher_allocated_amounts, voucher, gl_account):
if not (voucher_details := voucher_allocated_amounts.get((voucher.get("doctype"), voucher.get("name")))):
return
if not (row := voucher_details.get(gl_account)):
return
return row.get("total")
def check_matching(
bank_account,
company,
@@ -763,7 +719,7 @@ def get_pe_matching_query(
(ref_rank + amount_rank + party_rank + 1).as_("rank"),
ConstantColumn("Payment Entry").as_("doctype"),
pe.name,
pe.base_paid_amount_after_tax.as_("paid_amount"),
pe.paid_amount_after_tax.as_("paid_amount"),
pe.reference_no,
pe.reference_date,
pe.party,
@@ -804,20 +760,26 @@ def get_je_matching_query(
je = frappe.qb.DocType("Journal Entry")
jea = frappe.qb.DocType("Journal Entry Account")
ref_condition = je.cheque_no == transaction.reference_number
ref_rank = frappe.qb.terms.Case().when(ref_condition, 1).else_(0)
amount_field = f"{cr_or_dr}_in_account_currency"
amount_equality = getattr(jea, amount_field) == transaction.unallocated_amount
amount_rank = frappe.qb.terms.Case().when(amount_equality, 1).else_(0)
filter_by_date = je.posting_date.between(from_date, to_date)
if cint(filter_by_reference_date):
filter_by_date = je.cheque_date.between(from_reference_date, to_reference_date)
subquery = (
query = (
frappe.qb.from_(jea)
.join(je)
.on(jea.parent == je.name)
.select(
Sum(getattr(jea, amount_field)).as_("paid_amount"),
(ref_rank + amount_rank + 1).as_("rank"),
ConstantColumn("Journal Entry").as_("doctype"),
je.name,
getattr(jea, amount_field).as_("paid_amount"),
je.cheque_no.as_("reference_no"),
je.cheque_date.as_("reference_date"),
je.pay_to_recd_from.as_("party"),
@@ -829,26 +791,14 @@ def get_je_matching_query(
.where(je.voucher_type != "Opening Entry")
.where(je.clearance_date.isnull())
.where(jea.account == common_filters.bank_account)
.where(amount_equality if exact_match else getattr(jea, amount_field) > 0.0)
.where(je.docstatus == 1)
.where(filter_by_date)
.groupby(je.name)
.orderby(je.cheque_date if cint(filter_by_reference_date) else je.posting_date)
)
if frappe.flags.auto_reconcile_vouchers is True:
subquery = subquery.where(je.cheque_no == transaction.reference_number)
ref_rank = frappe.qb.terms.Case().when(subquery.reference_no == transaction.reference_number, 1).else_(0)
amount_equality = subquery.paid_amount == transaction.unallocated_amount
amount_rank = frappe.qb.terms.Case().when(amount_equality, 1).else_(0)
query = (
frappe.qb.from_(subquery)
.select(
"*",
(ref_rank + amount_rank + 1).as_("rank"),
)
.where(amount_equality if exact_match else subquery.paid_amount > 0.0)
)
query = query.where(ref_condition)
return query

View File

@@ -4,7 +4,11 @@
import frappe
from frappe import qb
<<<<<<< HEAD
from frappe.tests.utils import FrappeTestCase
=======
from frappe.tests import IntegrationTestCase
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
from frappe.utils import add_days, today
from erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool import (
@@ -15,7 +19,11 @@ from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_pay
from erpnext.accounts.test.accounts_mixin import AccountsTestMixin
<<<<<<< HEAD
class TestBankReconciliationTool(AccountsTestMixin, FrappeTestCase):
=======
class TestBankReconciliationTool(AccountsTestMixin, IntegrationTestCase):
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
def setUp(self):
self.create_company()
self.create_customer()

View File

@@ -2,6 +2,19 @@
// For license information, please see license.txt
frappe.ui.form.on("Bank Statement Import", {
<<<<<<< HEAD
=======
onload(frm) {
frm.set_query("bank_account", function (doc) {
return {
filters: {
company: doc.company,
},
};
});
},
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
setup(frm) {
frappe.realtime.on("data_import_refresh", ({ data_import }) => {
frm.import_in_progress = false;

View File

@@ -230,7 +230,15 @@
"write": 1
}
],
<<<<<<< HEAD
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}
=======
"sort_field": "creation",
"sort_order": "DESC",
"states": [],
"track_changes": 1
}
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)

View File

@@ -79,7 +79,12 @@ class BankStatementImport(DataImport):
from frappe.utils.background_jobs import is_job_enqueued
from frappe.utils.scheduler import is_scheduler_inactive
<<<<<<< HEAD
if is_scheduler_inactive() and not frappe.flags.in_test:
=======
run_now = frappe.flags.in_test or frappe.conf.developer_mode
if is_scheduler_inactive() and not run_now:
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
frappe.throw(_("Scheduler is inactive. Cannot import data."), title=_("Scheduler Inactive"))
job_id = f"bank_statement_import::{self.name}"
@@ -96,7 +101,11 @@ class BankStatementImport(DataImport):
google_sheets_url=self.google_sheets_url,
bank=self.bank,
template_options=self.template_options,
<<<<<<< HEAD
now=frappe.conf.developer_mode or frappe.flags.in_test,
=======
now=run_now,
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
)
return True
@@ -277,7 +286,7 @@ def get_import_status(docname):
@frappe.whitelist()
def get_import_logs(docname: str):
frappe.has_permission("Bank Statement Import", throw=True)
frappe.has_permission("Bank Statement Import")
return frappe.get_all(
"Data Import Log",

View File

@@ -1,9 +1,19 @@
# Copyright (c) 2020, Frappe Technologies and Contributors
# See license.txt
<<<<<<< HEAD
# import frappe
import unittest
class TestBankStatementImport(unittest.TestCase):
=======
# import frappe
import unittest
from frappe.tests import IntegrationTestCase
class TestBankStatementImport(IntegrationTestCase):
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
pass

View File

@@ -1,7 +1,6 @@
import frappe
from frappe.utils import flt
from rapidfuzz import fuzz, process
from rapidfuzz.utils import default_process
class AutoMatchParty:
@@ -46,41 +45,45 @@ class AutoMatchbyAccountIBAN:
if not (self.bank_party_account_number or self.bank_party_iban):
return None
return self.match_account_in_party()
result = self.match_account_in_party()
return result
def match_account_in_party(self) -> tuple | None:
"""
Returns (Party Type, Party) if a matching account is found in Bank Account or Employee:
1. Get party from a matching (iban/account no) Bank Account
2. If not found, get party from Employee with matching bank account details (iban/account no)
"""
if not (self.bank_party_account_number or self.bank_party_iban):
# Nothing to match
return None
"""Check if there is a IBAN/Account No. match in Customer/Supplier/Employee"""
result = None
parties = get_parties_in_order(self.deposit)
or_filters = self.get_or_filters()
# Search for a matching Bank Account that has party set
party_result = frappe.db.get_all(
"Bank Account",
or_filters=self.get_or_filters(),
filters={"party_type": ("is", "set"), "party": ("is", "set")},
fields=["party", "party_type"],
limit_page_length=1,
)
if result := party_result[0] if party_result else None:
return (result["party_type"], result["party"])
for party in parties:
party_result = frappe.db.get_all(
"Bank Account", or_filters=or_filters, pluck="party", limit_page_length=1
)
# If no party is found, search in Employee (since it has bank account details)
if employee_result := frappe.db.get_all(
"Employee", or_filters=self.get_or_filters("Employee"), pluck="name", limit_page_length=1
):
return ("Employee", employee_result[0])
if party == "Employee" and not party_result:
# Search in Bank Accounts first for Employee, and then Employee record
if "bank_account_no" in or_filters:
or_filters["bank_ac_no"] = or_filters.pop("bank_account_no")
def get_or_filters(self, party: str | None = None) -> dict:
"""Return OR filters for Bank Account and IBAN"""
party_result = frappe.db.get_all(
party, or_filters=or_filters, pluck="name", limit_page_length=1
)
if "bank_ac_no" in or_filters:
or_filters["bank_account_no"] = or_filters.pop("bank_ac_no")
if party_result:
result = (
party,
party_result[0],
)
break
return result
def get_or_filters(self) -> dict:
or_filters = {}
if self.bank_party_account_number:
bank_ac_field = "bank_ac_no" if party == "Employee" else "bank_account_no"
or_filters[bank_ac_field] = self.bank_party_account_number
or_filters["bank_account_no"] = self.bank_party_account_number
if self.bank_party_iban:
or_filters["iban"] = self.bank_party_iban
@@ -100,7 +103,8 @@ class AutoMatchbyPartyNameDescription:
if not (self.bank_party_name or self.description):
return None
return self.match_party_name_desc_in_party()
result = self.match_party_name_desc_in_party()
return result
def match_party_name_desc_in_party(self) -> tuple | None:
"""Fuzzy search party name and/or description against parties in the system"""
@@ -109,8 +113,12 @@ class AutoMatchbyPartyNameDescription:
for party in parties:
filters = {"status": "Active"} if party == "Employee" else {"disabled": 0}
field = f"{party.lower()}_name"
<<<<<<< HEAD
names = frappe.get_all(party, filters=filters, pluck=party.lower() + "_name")
=======
field = party.lower() + "_name"
names = frappe.get_all(party, filters=filters, fields=[f"{field} as party_name", "name"])
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
for field in ["bank_party_name", "description"]:
if not self.get(field):
@@ -129,15 +137,24 @@ class AutoMatchbyPartyNameDescription:
def fuzzy_search_and_return_result(self, party, names, field) -> tuple | None:
skip = False
<<<<<<< HEAD
result = process.extract(query=self.get(field), choices=names, scorer=fuzz.token_set_ratio)
=======
result = process.extract(
query=self.get(field),
choices={row.get("name"): row.get("party_name") for row in names},
scorer=fuzz.token_set_ratio,
processor=default_process,
)
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
party_name, skip = self.process_fuzzy_result(result)
return ((party, party_name), skip) if party_name else (None, skip)
if not party_name:
return None, skip
return (
party,
party_name,
), skip
def process_fuzzy_result(self, result: list | None):
"""
@@ -146,30 +163,42 @@ class AutoMatchbyPartyNameDescription:
Returns: Result, Skip (whether or not to discontinue matching)
"""
<<<<<<< HEAD
PARTY, SCORE, CUTOFF = 0, 1, 80
=======
SCORE, PARTY_ID, CUTOFF = 1, 2, 80
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
if not result or not len(result):
return None, False
first_result = result[0]
if len(result) == 1:
<<<<<<< HEAD
return (first_result[PARTY] if first_result[SCORE] > CUTOFF else None), True
=======
return (first_result[PARTY_ID] if first_result[SCORE] > CUTOFF else None), True
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
second_result = result[1]
if first_result[SCORE] > CUTOFF:
second_result = result[1]
# If multiple matches with the same score, return None but discontinue matching
# Matches were found but were too close to distinguish between
if first_result[SCORE] == second_result[SCORE]:
return None, True
<<<<<<< HEAD
return first_result[PARTY], True
=======
return first_result[PARTY_ID], True
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
else:
return None, False
def get_parties_in_order(deposit: float) -> list:
return (
["Customer", "Supplier", "Employee"] # most -> least likely to pay us
if flt(deposit) > 0
else ["Supplier", "Employee", "Customer"] # most -> least likely to receive from us
)
parties = ["Supplier", "Employee", "Customer"] # most -> least likely to receive
if flt(deposit) > 0:
parties = ["Customer", "Supplier", "Employee"] # most -> least likely to pay
return parties

View File

@@ -2,21 +2,7 @@
// For license information, please see license.txt
frappe.ui.form.on("Bank Transaction", {
setup: function (frm) {
frm.set_query("party_type", function () {
return {
filters: {
name: ["in", Object.keys(frappe.boot.party_account_types)],
},
};
});
frm.set_query("bank_account", function () {
return {
filters: { is_company_account: 1 },
};
});
onload(frm) {
frm.set_query("payment_document", "payment_entries", function () {
const payment_doctypes = frm.events.get_payment_doctypes(frm);
return {
@@ -25,16 +11,7 @@ frappe.ui.form.on("Bank Transaction", {
},
};
});
frm.set_query("payment_entry", "payment_entries", function () {
return {
filters: {
docstatus: ["!=", 2],
},
};
});
},
refresh(frm) {
if (!frm.is_dirty() && frm.doc.payment_entries.length > 0) {
frm.add_custom_button(__("Unreconcile Transaction"), () => {
@@ -42,17 +19,51 @@ frappe.ui.form.on("Bank Transaction", {
});
}
},
bank_account: function (frm) {
set_bank_statement_filter(frm);
},
setup: function (frm) {
frm.set_query("party_type", function () {
return {
filters: {
name: ["in", Object.keys(frappe.boot.party_account_types)],
},
};
});
},
get_payment_doctypes: function () {
// get payment doctypes from all the apps
return ["Payment Entry", "Journal Entry", "Sales Invoice", "Purchase Invoice", "Bank Transaction"];
},
});
frappe.ui.form.on("Bank Transaction Payments", {
payment_entries_remove: function (frm, cdt, cdn) {
update_clearance_date(frm, cdt, cdn);
},
});
const update_clearance_date = (frm, cdt, cdn) => {
if (frm.doc.docstatus === 1) {
frappe
.xcall("erpnext.accounts.doctype.bank_transaction.bank_transaction.unclear_reference_payment", {
doctype: cdt,
docname: cdn,
bt_name: frm.doc.name,
})
.then((e) => {
if (e == "success") {
frappe.show_alert({
message: __("Document {0} successfully uncleared", [e]),
indicator: "green",
});
}
});
}
};
function set_bank_statement_filter(frm) {
frm.set_query("bank_statement", function () {
return {

View File

@@ -45,6 +45,7 @@
"default": "ACC-BTN-.YYYY.-",
"fieldname": "naming_series",
"fieldtype": "Select",
"hidden": 1,
"label": "Series",
"no_copy": 1,
"options": "ACC-BTN-.YYYY.-",
@@ -235,10 +236,9 @@
"fieldtype": "Column Break"
}
],
"grid_page_length": 50,
"is_submittable": 1,
"links": [],
"modified": "2025-06-18 17:24:57.044666",
"modified": "2023-11-18 18:32:47.203694",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Transaction",
@@ -287,10 +287,9 @@
"write": 1
}
],
"row_format": "Dynamic",
"sort_field": "date",
"sort_order": "DESC",
"states": [],
"title_field": "bank_account",
"track_changes": 1
}
}

View File

@@ -5,7 +5,7 @@ import frappe
from frappe import _
from frappe.model.docstatus import DocStatus
from frappe.model.document import Document
from frappe.utils import flt, getdate
from frappe.utils import flt
class BankTransaction(Document):
@@ -84,16 +84,16 @@ class BankTransaction(Document):
if not self.payment_entries:
return
references = set()
pe = []
for row in self.payment_entries:
reference = (row.payment_document, row.payment_entry)
if reference in references:
if reference in pe:
frappe.throw(
_("{0} {1} is allocated twice in this Bank Transaction").format(
row.payment_document, row.payment_entry
)
)
references.add(reference)
pe.append(reference)
def update_allocated_amount(self):
allocated_amount = (
@@ -104,19 +104,6 @@ class BankTransaction(Document):
self.allocated_amount = flt(allocated_amount, self.precision("allocated_amount"))
self.unallocated_amount = flt(unallocated_amount, self.precision("unallocated_amount"))
def delink_old_payment_entries(self):
if self.flags.updating_linked_bank_transaction:
return
old_doc = self.get_doc_before_save()
payment_entry_names = set(pe.name for pe in self.payment_entries)
for old_pe in old_doc.payment_entries:
if old_pe.name in payment_entry_names:
continue
self.delink_payment_entry(old_pe)
def before_submit(self):
self.allocate_payment_entries()
self.set_status()
@@ -126,14 +113,13 @@ class BankTransaction(Document):
def before_update_after_submit(self):
self.validate_duplicate_references()
self.update_allocated_amount()
self.delink_old_payment_entries()
self.allocate_payment_entries()
self.update_allocated_amount()
self.set_status()
def on_cancel(self):
for payment_entry in self.payment_entries:
self.delink_payment_entry(payment_entry)
self.clear_linked_payment_entry(payment_entry, for_cancel=True)
self.set_status()
@@ -166,55 +152,37 @@ class BankTransaction(Document):
- 0 > a: Error: already over-allocated
- clear means: set the latest transaction date as clearance date
"""
if self.flags.updating_linked_bank_transaction or not self.payment_entries:
return
remaining_amount = self.unallocated_amount
payment_entry_docs = [(pe.payment_document, pe.payment_entry) for pe in self.payment_entries]
pe_bt_allocations = get_total_allocated_amount(payment_entry_docs)
gl_entries = get_related_bank_gl_entries(payment_entry_docs)
gl_bank_account = frappe.db.get_value("Bank Account", self.bank_account, "account")
for payment_entry in list(self.payment_entries):
if payment_entry.allocated_amount != 0:
continue
allocable_amount, should_clear, clearance_date = get_clearance_details(
self,
payment_entry,
pe_bt_allocations.get((payment_entry.payment_document, payment_entry.payment_entry)) or {},
gl_entries.get((payment_entry.payment_document, payment_entry.payment_entry)) or {},
gl_bank_account,
)
if allocable_amount < 0:
frappe.throw(_("Voucher {0} is over-allocated by {1}").format(allocable_amount))
if remaining_amount <= 0:
self.remove(payment_entry)
continue
if allocable_amount == 0:
if should_clear:
self.clear_linked_payment_entry(payment_entry, clearance_date=clearance_date)
self.remove(payment_entry)
continue
should_clear = should_clear and allocable_amount <= remaining_amount
payment_entry.allocated_amount = min(allocable_amount, remaining_amount)
remaining_amount = flt(
remaining_amount - payment_entry.allocated_amount,
self.precision("unallocated_amount"),
)
if payment_entry.payment_document == "Bank Transaction":
self.update_linked_bank_transaction(
payment_entry.payment_entry, payment_entry.allocated_amount
to_remove = []
for payment_entry in self.payment_entries:
if payment_entry.allocated_amount == 0.0:
unallocated_amount, should_clear, latest_transaction = get_clearance_details(
self, payment_entry
)
elif should_clear:
self.clear_linked_payment_entry(payment_entry, clearance_date=clearance_date)
self.update_allocated_amount()
if 0.0 == unallocated_amount:
if should_clear:
latest_transaction.clear_linked_payment_entry(payment_entry)
to_remove.append(payment_entry)
elif remaining_amount <= 0.0:
to_remove.append(payment_entry)
elif 0.0 < unallocated_amount <= remaining_amount:
payment_entry.allocated_amount = unallocated_amount
remaining_amount -= unallocated_amount
if should_clear:
latest_transaction.clear_linked_payment_entry(payment_entry)
elif 0.0 < unallocated_amount:
payment_entry.allocated_amount = remaining_amount
remaining_amount = 0.0
elif 0.0 > unallocated_amount:
frappe.throw(_("Voucher {0} is over-allocated by {1}").format(unallocated_amount))
for payment_entry in to_remove:
self.remove(payment_entry)
@frappe.whitelist()
def remove_payment_entries(self):
@@ -225,64 +193,14 @@ class BankTransaction(Document):
def remove_payment_entry(self, payment_entry):
"Clear payment entry and clearance"
self.delink_payment_entry(payment_entry)
self.clear_linked_payment_entry(payment_entry, for_cancel=True)
self.remove(payment_entry)
def delink_payment_entry(self, payment_entry):
if payment_entry.payment_document == "Bank Transaction":
self.update_linked_bank_transaction(payment_entry.payment_entry, allocated_amount=None)
else:
self.clear_linked_payment_entry(payment_entry, clearance_date=None)
def clear_linked_payment_entry(self, payment_entry, clearance_date=None):
doctype = payment_entry.payment_document
docname = payment_entry.payment_entry
# might be a bank transaction
if doctype not in get_doctypes_for_bank_reconciliation():
return
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)
def update_linked_bank_transaction(self, bank_transaction_name, allocated_amount=None):
"""For when a second bank transaction has fixed another, e.g. refund"""
bt = frappe.get_doc(self.doctype, bank_transaction_name)
if allocated_amount:
bt.append(
"payment_entries",
{
"payment_document": self.doctype,
"payment_entry": self.name,
"allocated_amount": allocated_amount,
},
)
else:
pe = next(
(
pe
for pe in bt.payment_entries
if pe.payment_document == self.doctype and pe.payment_entry == self.name
),
None,
)
if not pe:
return
bt.flags.updating_linked_bank_transaction = True
bt.remove(pe)
bt.save()
def clear_linked_payment_entry(self, payment_entry, for_cancel=False):
clearance_date = None if for_cancel else self.date
set_voucher_clearance(
payment_entry.payment_document, payment_entry.payment_entry, clearance_date, self
)
def auto_set_party(self):
from erpnext.accounts.doctype.bank_transaction.auto_match_party import AutoMatchParty
@@ -314,147 +232,195 @@ def get_doctypes_for_bank_reconciliation():
return frappe.get_hooks("bank_reconciliation_doctypes")
def get_clearance_details(transaction, payment_entry, bt_allocations, gl_entries, gl_bank_account):
def get_clearance_details(transaction, payment_entry):
"""
There should only be one bank gl entry for a voucher, except for JE.
For JE, there can be multiple bank gl entries for the same account.
In this case, the allocable_amount will be the sum of amounts of all gl entries of the account.
There will be no gl entry for a Bank Transaction so return the unallocated amount.
Should only clear the voucher if all bank gl entries are allocated.
There should only be one bank gle for a voucher.
Could be none for a Bank Transaction.
But if a JE, could affect two banks.
Should only clear the voucher if all bank gles are allocated.
"""
gl_bank_account = frappe.db.get_value("Bank Account", transaction.bank_account, "account")
gles = get_related_bank_gl_entries(payment_entry.payment_document, payment_entry.payment_entry)
bt_allocations = get_total_allocated_amount(payment_entry.payment_document, payment_entry.payment_entry)
transaction_date = getdate(transaction.date)
if payment_entry.payment_document == "Bank Transaction":
bt = frappe.db.get_value(
"Bank Transaction",
payment_entry.payment_entry,
("unallocated_amount", "bank_account"),
as_dict=True,
)
if bt.bank_account != gl_bank_account:
frappe.throw(
_("Bank Account {} in Bank Transaction {} is not matching with Bank Account {}").format(
bt.bank_account, payment_entry.payment_entry, gl_bank_account
unallocated_amount = min(
transaction.unallocated_amount,
get_paid_amount(payment_entry, transaction.currency, gl_bank_account),
)
unmatched_gles = len(gles)
latest_transaction = transaction
for gle in gles:
if gle["gl_account"] == gl_bank_account:
if gle["amount"] <= 0.0:
frappe.throw(
_("Voucher {0} value is broken: {1}").format(payment_entry.payment_entry, gle["amount"])
)
)
return abs(bt.unallocated_amount), True, transaction_date
unmatched_gles -= 1
unallocated_amount = gle["amount"]
for a in bt_allocations:
if a["gl_account"] == gle["gl_account"]:
unallocated_amount = gle["amount"] - a["total"]
if frappe.utils.getdate(transaction.date) < a["latest_date"]:
latest_transaction = frappe.get_doc("Bank Transaction", a["latest_name"])
else:
# Must be a Journal Entry affecting more than one bank
for a in bt_allocations:
if a["gl_account"] == gle["gl_account"] and a["total"] == gle["amount"]:
unmatched_gles -= 1
if gl_bank_account not in gl_entries:
frappe.throw(
_("{} {} is not affecting bank account {}").format(
payment_entry.payment_document, payment_entry.payment_entry, gl_bank_account
)
)
allocable_amount = gl_entries.pop(gl_bank_account) or 0
if allocable_amount <= 0.0:
frappe.throw(
_("Invalid amount in accounting entries of {} {} for Account {}: {}").format(
payment_entry.payment_document, payment_entry.payment_entry, gl_bank_account, allocable_amount
)
)
matching_bt_allocaion = bt_allocations.pop(gl_bank_account, {})
allocable_amount = flt(
allocable_amount - matching_bt_allocaion.get("total", 0), transaction.precision("unallocated_amount")
)
should_clear = all(
gl_entries[gle_account] == bt_allocations.get(gle_account, {}).get("total", 0)
for gle_account in gl_entries
)
bt_allocation_date = matching_bt_allocaion.get("latest_date", None)
clearance_date = transaction_date if not bt_allocation_date else max(transaction_date, bt_allocation_date)
return allocable_amount, should_clear, clearance_date
return unallocated_amount, unmatched_gles == 0, latest_transaction
def get_related_bank_gl_entries(docs):
def get_related_bank_gl_entries(doctype, docname):
# nosemgrep: frappe-semgrep-rules.rules.frappe-using-db-sql
if not docs:
return {}
result = frappe.db.sql(
return frappe.db.sql(
"""
SELECT
gle.voucher_type AS doctype,
gle.voucher_no AS docname,
gle.account AS gl_account,
SUM(ABS(gle.credit_in_account_currency - gle.debit_in_account_currency)) AS amount
FROM
`tabGL Entry` gle
LEFT JOIN
`tabAccount` ac ON ac.name = gle.account
WHERE
ac.account_type = 'Bank'
AND (gle.voucher_type, gle.voucher_no) IN %(docs)s
AND gle.is_cancelled = 0
GROUP BY
gle.voucher_type, gle.voucher_no, gle.account
""",
{"docs": docs},
SELECT
ABS(gle.credit_in_account_currency - gle.debit_in_account_currency) AS amount,
gle.account AS gl_account
FROM
`tabGL Entry` gle
LEFT JOIN
`tabAccount` ac ON ac.name=gle.account
WHERE
ac.account_type = 'Bank'
AND gle.voucher_type = %(doctype)s
AND gle.voucher_no = %(docname)s
AND is_cancelled = 0
""",
dict(doctype=doctype, docname=docname),
as_dict=True,
)
entries = {}
for row in result:
key = (row["doctype"], row["docname"])
if key not in entries:
entries[key] = {}
entries[key][row["gl_account"]] = row["amount"]
return entries
def get_total_allocated_amount(docs):
def get_total_allocated_amount(doctype, docname):
"""
Gets the sum of allocations for a voucher on each bank GL account
along with the latest bank transaction date
along with the latest bank transaction name & date
NOTE: query may also include just saved vouchers/payments but with zero allocated_amount
"""
if not docs:
return {}
# nosemgrep: frappe-semgrep-rules.rules.frappe-using-db-sql
result = frappe.db.sql(
"""
SELECT total, latest_date, gl_account, payment_document, payment_entry FROM (
SELECT total, latest_name, latest_date, gl_account FROM (
SELECT
ROW_NUMBER() OVER w AS rownum,
SUM(btp.allocated_amount) OVER(PARTITION BY ba.account, btp.payment_document, btp.payment_entry) AS total,
SUM(btp.allocated_amount) OVER(PARTITION BY ba.account) AS total,
FIRST_VALUE(bt.name) OVER w AS latest_name,
FIRST_VALUE(bt.date) OVER w AS latest_date,
ba.account AS gl_account,
btp.payment_document,
btp.payment_entry
ba.account AS gl_account
FROM
`tabBank Transaction Payments` btp
LEFT JOIN `tabBank Transaction` bt ON bt.name=btp.parent
LEFT JOIN `tabBank Account` ba ON ba.name=bt.bank_account
WHERE
(btp.payment_document, btp.payment_entry) IN %(docs)s
btp.payment_document = %(doctype)s
AND btp.payment_entry = %(docname)s
AND bt.docstatus = 1
WINDOW w AS (PARTITION BY ba.account, btp.payment_document, btp.payment_entry ORDER BY bt.date DESC)
WINDOW w AS (PARTITION BY ba.account ORDER BY bt.date desc)
) temp
WHERE
rownum = 1
""",
dict(docs=docs),
dict(doctype=doctype, docname=docname),
as_dict=True,
)
payment_allocation_details = {}
for row in result:
row["latest_date"] = getdate(row["latest_date"])
payment_allocation_details.setdefault((row["payment_document"], row["payment_entry"]), {})[
row["gl_account"]
] = row
# Why is this *sometimes* a byte string?
if isinstance(row["latest_name"], bytes):
row["latest_name"] = row["latest_name"].decode()
row["latest_date"] = frappe.utils.getdate(row["latest_date"])
return result
return payment_allocation_details
def get_paid_amount(payment_entry, currency, gl_bank_account):
if payment_entry.payment_document in ["Payment Entry", "Sales Invoice", "Purchase Invoice"]:
paid_amount_field = "paid_amount"
if payment_entry.payment_document == "Payment Entry":
doc = frappe.get_doc("Payment Entry", payment_entry.payment_entry)
if doc.payment_type == "Receive":
paid_amount_field = (
"received_amount" if doc.paid_to_account_currency == currency else "base_received_amount"
)
elif doc.payment_type == "Pay":
paid_amount_field = (
"paid_amount" if doc.paid_from_account_currency == currency else "base_paid_amount"
)
return frappe.db.get_value(
payment_entry.payment_document, payment_entry.payment_entry, paid_amount_field
)
elif payment_entry.payment_document == "Journal Entry":
return abs(
frappe.db.get_value(
"Journal Entry Account",
{"parent": payment_entry.payment_entry, "account": gl_bank_account},
"sum(debit_in_account_currency-credit_in_account_currency)",
)
or 0
)
elif payment_entry.payment_document == "Expense Claim":
return frappe.db.get_value(
payment_entry.payment_document, payment_entry.payment_entry, "total_amount_reimbursed"
)
elif payment_entry.payment_document == "Loan Disbursement":
return frappe.db.get_value(
payment_entry.payment_document, payment_entry.payment_entry, "disbursed_amount"
)
elif payment_entry.payment_document == "Loan Repayment":
return frappe.db.get_value(payment_entry.payment_document, payment_entry.payment_entry, "amount_paid")
elif payment_entry.payment_document == "Bank Transaction":
dep, wth = frappe.db.get_value(
"Bank Transaction", payment_entry.payment_entry, ("deposit", "withdrawal")
)
return abs(flt(wth) - flt(dep))
else:
frappe.throw(
f"Please reconcile {payment_entry.payment_document}: {payment_entry.payment_entry} manually"
)
def set_voucher_clearance(doctype, docname, clearance_date, self):
if doctype in get_doctypes_for_bank_reconciliation():
if (
doctype == "Payment Entry"
and frappe.db.get_value("Payment Entry", docname, "payment_type") == "Internal Transfer"
and len(get_reconciled_bank_transactions(doctype, docname)) < 2
):
return
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
bt = frappe.get_doc(doctype, docname)
if clearance_date:
vouchers = [{"payment_doctype": "Bank Transaction", "payment_name": self.name}]
bt.add_payment_entries(vouchers)
bt.save()
else:
for pe in bt.payment_entries:
if pe.payment_document == self.doctype and pe.payment_entry == self.name:
bt.remove(pe)
bt.save()
break
def get_reconciled_bank_transactions(doctype, docname):
@@ -465,6 +431,13 @@ def get_reconciled_bank_transactions(doctype, docname):
)
@frappe.whitelist()
def unclear_reference_payment(doctype, docname, bt_name):
bt = frappe.get_doc("Bank Transaction", bt_name)
set_voucher_clearance(doctype, docname, None, bt)
return docname
def remove_from_bank_transaction(doctype, docname):
"""Remove a (cancelled) voucher from all Bank Transactions."""
for bt_name in get_reconciled_bank_transactions(doctype, docname):

View File

@@ -2,13 +2,30 @@
# License: GNU General Public License v3. See license.txt
import frappe
<<<<<<< HEAD
from frappe.tests.utils import FrappeTestCase
=======
from frappe.tests import IntegrationTestCase, UnitTestCase
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
from frappe.utils import nowdate
from erpnext.accounts.doctype.bank_transaction.test_bank_transaction import create_bank_account
<<<<<<< HEAD
class TestAutoMatchParty(FrappeTestCase):
=======
class UnitTestBankTransaction(UnitTestCase):
"""
Unit tests for BankTransaction.
Use this class for testing individual functions and methods.
"""
pass
class TestAutoMatchParty(IntegrationTestCase):
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
@classmethod
def setUpClass(cls):
create_bank_account()

View File

@@ -6,21 +6,23 @@ import json
import frappe
from frappe import utils
from frappe.model.docstatus import DocStatus
<<<<<<< HEAD
from frappe.tests.utils import FrappeTestCase
=======
from frappe.tests import IntegrationTestCase, UnitTestCase
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
from erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool import (
get_linked_payments,
reconcile_vouchers,
)
from erpnext.accounts.doctype.mode_of_payment.test_mode_of_payment import (
set_default_account_for_mode_of_payment,
)
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.tests.utils import if_lending_app_installed
<<<<<<< HEAD
test_dependencies = ["Item", "Cost Center"]
@@ -34,6 +36,22 @@ class TestBankTransaction(FrappeTestCase):
]:
frappe.db.delete(dt)
clear_loan_transactions()
=======
EXTRA_TEST_RECORD_DEPENDENCIES = ["Item", "Cost Center"]
class UnitTestBankTransaction(UnitTestCase):
"""
Unit tests for BankTransaction.
Use this class for testing individual functions and methods.
"""
pass
class TestBankTransaction(IntegrationTestCase):
def setUp(self):
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
make_pos_profile()
# generate and use a uniq hash identifier for 'Bank Account' and it's linked GL 'Account' to avoid validation error
@@ -225,11 +243,14 @@ class TestBankTransaction(FrappeTestCase):
self.assertEqual(linked_payments[0]["name"], repayment_entry.name)
<<<<<<< HEAD
@if_lending_app_installed
def clear_loan_transactions():
frappe.db.delete("Loan Repayment")
=======
>>>>>>> 94d7e5964b (fix: add doc.status to translation from POS)
def create_bank_account(
bank_name="Citi Bank", gl_account="_Test Bank - _TC", bank_account_name="Checking Account"
):
@@ -437,13 +458,15 @@ def add_vouchers(gl_account="_Test Bank - _TC"):
except frappe.DuplicateEntryError:
pass
mode_of_payment = frappe.get_doc({"doctype": "Mode of Payment", "name": "Wire Transfer"})
mode_of_payment = frappe.get_doc({"doctype": "Mode of Payment", "name": "Cash"})
set_default_account_for_mode_of_payment(mode_of_payment, "_Test Company", gl_account)
if not frappe.db.get_value("Mode of Payment Account", {"company": "_Test Company", "parent": "Cash"}):
mode_of_payment.append("accounts", {"company": "_Test Company", "default_account": gl_account})
mode_of_payment.save()
si = create_sales_invoice(customer="Fayva", qty=1, rate=109080, do_not_save=1)
si.is_pos = 1
si.append("payments", {"mode_of_payment": "Wire Transfer", "amount": 109080})
si.append("payments", {"mode_of_payment": "Cash", "account": gl_account, "amount": 109080})
si.insert()
si.submit()

Some files were not shown because too many files have changed in this diff Show More