Compare commits

..

1099 Commits

Author SHA1 Message Date
Ankush Menat
d3117cca0c perf: add indexes on payment entry reference
Adds index on:
1. reference doctype
2. reference name

*Why not composite index?*

There are three type of queries on this doctype

- filtering ref_doctype - doctype index helps here
- filtering ref_name - name index helps here
- filtering both - name index helps here too. Since it has sufficiently
  high cardinality. Composite index wont help in case where ref_doctype
  isn't specfied.
2022-12-12 12:32:14 +05:30
rohitwaghchaure
7cbb6c4de9 Merge pull request #33236 from rohitwaghchaure/feat-warehouse-wise-stock-balance
feat: warehouse wise stock balance
2022-12-06 17:58:31 +05:30
Deepesh Garg
b602a0dcb0 Merge pull request #33146 from barredterra/reload-currency-exchange-settings
fix: reload Currency Exchange Settings in patch
2022-12-06 17:38:13 +05:30
Deepesh Garg
26adbc6282 Merge pull request #33192 from deepeshgarg007/bundle_item_rates
fix: Bundle item rates
2022-12-06 17:37:22 +05:30
Rohit Waghchaure
861aa9e08a feat: warehouse wise stock balance 2022-12-06 17:33:33 +05:30
Deepesh Garg
c1a82dc9e5 Merge pull request #33191 from ruthra-kumar/key_error_in_profit_loss_report
fix: key error while filtering on date range and reporting on foreign currency
2022-12-06 15:42:53 +05:30
Deepesh Garg
b1242bc56c chore: Update tests 2022-12-06 15:14:48 +05:30
Deepesh Garg
af1f98e188 Merge branch 'develop' of https://github.com/frappe/erpnext into bundle_item_rates 2022-12-06 13:59:51 +05:30
Deepesh Garg
e5566b31d5 chore: Consider bundle qty as well 2022-12-06 13:59:45 +05:30
ruthra kumar
a6794c3606 fix: key error on p/l and balance sheet reports on foreign currency 2022-12-06 13:48:46 +05:30
ruthra kumar
19db7e2989 fix: replace sql code with fields list in get_cached_value 2022-12-06 13:48:46 +05:30
Ankush Menat
d23b5d8f2f ci: use mariadb 10.6 (#33220)
https://github.com/frappe/frappe/pull/19116

[skip ci]
2022-12-06 12:58:07 +05:30
Deepesh Garg
01b84a9751 Merge pull request #33194 from barredterra/validate-employee-dates
refactor: validate dates in Employee
2022-12-06 12:34:15 +05:30
Deepesh Garg
3aa6f97420 Merge pull request #33216 from barredterra/validate-accounts-dates
refactor: validate dates in accounts module
2022-12-06 12:33:01 +05:30
Deepesh Garg
63393fa503 Merge pull request #33217 from barredterra/validate-project-dates
refactor: validate dates in project and task
2022-12-06 12:32:27 +05:30
Deepesh Garg
921f8edde8 Merge pull request #33219 from deepeshgarg007/internal_transfer_editable_rate
fix: Allow item rate updates for non-stock invoices
2022-12-06 09:12:24 +05:30
Raffael Meyer
5853b80d25 Merge branch 'develop' into reload-currency-exchange-settings 2022-12-06 02:30:55 +01:00
Raffael Meyer
8301d3b13f Merge branch 'develop' into key_error_in_profit_loss_report 2022-12-06 02:08:47 +01:00
barredterra
a26a29f33b fix: incorrect dates in test records 2022-12-05 19:49:05 +01:00
Raffael Meyer
a074ffa880 Merge branch 'develop' into validate-employee-dates 2022-12-05 19:38:01 +01:00
Raffael Meyer
e526a0e282 Merge branch 'develop' into validate-accounts-dates 2022-12-05 19:37:54 +01:00
Raffael Meyer
a2abc879c9 Merge branch 'develop' into validate-project-dates 2022-12-05 19:37:46 +01:00
rohitwaghchaure
d0478ec3b8 Merge pull request #33224 from rohitwaghchaure/fixed-partial-work-order-incorrect-batch-picked
fix: non empty FG batch picked while completing work order
2022-12-05 20:29:19 +05:30
Rohit Waghchaure
713330cbf6 fix: non empty FG batch picked while completing work order 2022-12-05 18:15:13 +05:30
ruthra kumar
7bd0e977bf Merge pull request #33222 from ruthra-kumar/data_import_errors_for_sales_invoice
fix: data import mandatory account_head, charge_type
2022-12-05 16:56:43 +05:30
ruthra kumar
3814db02eb fix: data import mandatory account_head, charge_type 2022-12-05 16:24:05 +05:30
Deepesh Garg
ef9d126254 fix: Allow item rate udpates for non-stock invoices 2022-12-05 10:17:19 +05:30
barredterra
31db0e7c79 refactor: validate parent_expected_end_date in Task 2022-12-04 15:28:38 +01:00
barredterra
2c4eb371a6 refactor: validate dates in project and task 2022-12-04 15:15:07 +01:00
barredterra
eb66b749b2 refactor: validate dates in accounts module 2022-12-04 14:41:21 +01:00
Raffael Meyer
083a954b5d Merge branch 'develop' into validate-employee-dates 2022-12-04 14:30:51 +01:00
rohitwaghchaure
66dbf94151 Merge pull request #33199 from s-aga-r/refactor/warehouse-tree
refactor: remove `balance` from `Warehouse Tree`
2022-12-02 14:24:07 +05:30
rohitwaghchaure
295ce0e8e9 Merge pull request #33193 from rohitwaghchaure/clear-repost-logs
fix: clear repost logs using Log Settings
2022-12-02 13:55:59 +05:30
Rohit Waghchaure
2cce6f2a34 fix: test case 2022-12-02 12:43:31 +05:30
Sagar Sharma
b3ae6cc4b9 Merge branch 'develop' into refactor/warehouse-tree 2022-12-02 10:58:33 +05:30
Deepesh Garg
2058fac177 Merge pull request #33195 from ruthra-kumar/type_error_on_sales_pipeline_report
fix: type error on Sales Pipeline Analytics
2022-12-02 10:10:36 +05:30
Rohit Waghchaure
5949a7ecff fix: default clear repost logs 2022-12-01 23:35:21 +05:30
s-aga-r
3ce8386ca3 refactor: remove balance from Warehouse Tree 2022-12-01 19:44:49 +05:30
Deepesh Garg
2106de0fa5 Merge pull request #33170 from deepeshgarg007/se_alert_develop
fix(UX): Alert on change of item rate in Stock Entry
2022-12-01 18:16:55 +05:30
Deepesh Garg
9ddd838f2d Merge pull request #33183 from deepeshgarg007/month_end_due_date
fix: Due date for month end payment term
2022-12-01 18:16:13 +05:30
Deepesh Garg
8d36328544 Merge pull request #33182 from deepeshgarg007/invalid_message_fix
fix: Error on making stock entry from material request
2022-12-01 18:15:29 +05:30
ruthra kumar
4856e750f9 fix: type error on Sales Pipeline Analytics 2022-12-01 18:08:32 +05:30
barredterra
03f7bfbbde refactor: validate dates 2022-12-01 12:42:03 +01:00
Deepesh Garg
826f45ad60 fix: Bundle item rates 2022-12-01 16:11:10 +05:30
ruthra kumar
9b8d6fe411 fix: key error while filtering on date range and different currency 2022-12-01 13:38:41 +05:30
Anand Baburajan
5b1743330d Merge branch 'develop' into invalid_message_fix 2022-12-01 12:35:04 +05:30
Anand Baburajan
2886d8ab5a Merge branch 'develop' into month_end_due_date 2022-12-01 12:34:51 +05:30
Deepesh Garg
5b1798363c Merge pull request #33091 from ssiyad/fix/pos/partial_return_amount
fix(pos): partial return amount update
2022-12-01 11:41:53 +05:30
Sagar Sharma
d892e27289 Merge branch 'develop' into se_alert_develop 2022-12-01 10:37:52 +05:30
Sagar Sharma
93f29d8f08 Merge branch 'develop' into invalid_message_fix 2022-12-01 09:24:40 +05:30
Sagar Sharma
9a8f3f4280 Merge pull request #33185 from AnandBaburajan/asset_last_day_test_bug
fix: use is_last_day_of_the_month in test_scrap_asset
2022-12-01 09:23:13 +05:30
anandbaburajan
827ad01d4f chore: style 2022-11-30 23:57:26 +05:30
Anand Baburajan
ba38001116 Merge branch 'develop' into asset_last_day_test_bug 2022-11-30 23:53:21 +05:30
anandbaburajan
25522444b8 fix: use is_last_day_of_the_month in test_scrap_asset 2022-11-30 23:25:40 +05:30
Sagar Sharma
0e8edd1ee9 Merge branch 'develop' into se_alert_develop 2022-11-30 22:03:31 +05:30
Deepesh Garg
bfb81ef56f fix: Due date for month end payment term 2022-11-30 20:53:41 +05:30
Deepesh Garg
64e5a79a91 fix: Error on making stock entry from material request 2022-11-30 19:35:30 +05:30
Sabu Siyad
c5edbe2e2f fix(lint): trailing whitespace
Signed-off-by: Sabu Siyad <hello@ssiyad.com>
2022-11-30 17:12:06 +05:30
Deepesh Garg
12637cda84 Merge pull request #33174 from s-aga-r/fix/github-issue/33102
fix: add company filter in RFQ Items
2022-11-30 10:36:18 +05:30
Sagar Sharma
43d08b4c74 Merge branch 'develop' into se_alert_develop 2022-11-30 10:15:31 +05:30
s-aga-r
ca0485a503 fix: add company filter in RFQ Items 2022-11-30 10:03:36 +05:30
Deepesh Garg
4bd9289d7d fix(UX): Alert on change of item rate in Stock Entry 2022-11-29 19:21:48 +05:30
Deepesh Garg
2e2590b224 Merge pull request #33162 from deepeshgarg007/tds_report_updates
fix: Tax withholding net total for PI in reports
2022-11-29 18:50:21 +05:30
Deepesh Garg
3eb1ed19a1 fix: Tax withholding net total for PI in reports 2022-11-29 13:10:31 +05:30
Sagar Sharma
bfd7a97ea9 Merge pull request #33136 from s-aga-r/repost-item-valuation
fix: reset `voucher_type` and `voucher_no` if `based_on` is set to `Transaction`
2022-11-29 12:13:46 +05:30
Sagar Sharma
ce7720b14c Merge branch 'develop' into repost-item-valuation 2022-11-29 11:03:22 +05:30
rohitwaghchaure
6dd84cb977 Merge pull request #33013 from rtdany10/riv-validation
fix: validate repost item valuation against accounts freeze date
2022-11-29 10:40:48 +05:30
Deepesh Garg
a7b7d0d99d Merge pull request #33116 from shariquerik/show-batch-selector-only-once
fix: only show serial no batch selector only once
2022-11-29 10:20:30 +05:30
Deepesh Garg
8253f4379f Merge pull request #33098 from ssiyad/fix/pos/warehouse_selection
fix(pos): warehouse selection
2022-11-29 10:15:31 +05:30
Deepesh Garg
56b96f0a9c Merge branch 'develop' into fix/pos/partial_return_amount 2022-11-29 10:12:29 +05:30
Deepesh Garg
bdb15c3331 Merge pull request #33112 from ssiyad/fix/pos/customer_group_filter
fix(pos): filter on customer groups
2022-11-29 09:55:56 +05:30
Deepesh Garg
8287fb5104 Merge pull request #33143 from deepeshgarg007/auto_repeat_dates
fix: Auto repeat date validations
2022-11-29 09:28:19 +05:30
Deepesh Garg
8112493c3c Merge pull request #33138 from deepeshgarg007/bank_reco_button_fix
fix(ux): Action buttons in Bank Reconciliation
2022-11-29 09:23:21 +05:30
rohitwaghchaure
a222b0a6ae Merge pull request #33144 from rohitwaghchaure/fixed-incorrect-stock-balance-qty
fix: incorrect balance qty
2022-11-29 08:48:03 +05:30
barredterra
06e094b5fc fix: reload currency exchange settings 2022-11-28 22:58:31 +01:00
Rohit Waghchaure
b606a9684b test: test case for serialized batched item 2022-11-29 00:08:07 +05:30
Rohit Waghchaure
b2105a8be7 fix: incorrect balance qty 2022-11-28 23:13:30 +05:30
Deepesh Garg
6a47fb6c9e chore: Update condition 2022-11-28 22:47:44 +05:30
Sagar Sharma
4750bfaeab Merge branch 'develop' into repost-item-valuation 2022-11-28 22:06:49 +05:30
Deepesh Garg
a9cf9e5a88 Merge pull request #33107 from barredterra/german-tax-templates
feat: german tax templates
2022-11-28 21:54:08 +05:30
Sagar Sharma
ec95a9b760 Merge branch 'develop' into repost-item-valuation 2022-11-28 21:33:58 +05:30
Sagar Sharma
7a887cf8ba Merge pull request #33139 from s-aga-r/fix/repost-item-valuation
fix: reposting error `AttributeError: 'datetime.timedelta' object has no attribute 'replace'`
2022-11-28 21:31:14 +05:30
Sagar Sharma
8948e42a6d Merge branch 'develop' into repost-item-valuation 2022-11-28 21:29:35 +05:30
s-aga-r
4e10352b48 chore: make posting_date and posting_time read-only if based_on is set to Transaction 2022-11-28 21:22:22 +05:30
s-aga-r
eeec008547 fix: reset voucher_type and voucher_no if based_on is set to Item and Warehouse 2022-11-28 21:22:20 +05:30
Sagar Sharma
6868b4d7c3 Merge branch 'develop' into fix/repost-item-valuation 2022-11-28 21:00:46 +05:30
s-aga-r
eeda264eb6 fix: reposting error AttributeError: 'datetime.timedelta' object has no attribute 'replace' 2022-11-28 20:59:14 +05:30
Deepesh Garg
fa15221455 fix: Auto repeat date validations 2022-11-28 19:22:35 +05:30
s-aga-r
ba77da0874 fix: validation msg in stock entry 2022-11-28 18:01:30 +05:30
Deepesh Garg
6ebe8ad60d fix(ux): Action buttons in Bank Reconciliation 2022-11-28 17:37:41 +05:30
rohitwaghchaure
b8b9d1b0a8 Merge pull request #33135 from rohitwaghchaure/feat-provision-to-make-mr-for-sub-assembly-items
feat: make Material Request for sub-assembly items
2022-11-28 16:53:38 +05:30
Rohit Waghchaure
e02f35c8ff feat: make Material Request for sub-assembly items 2022-11-28 16:20:46 +05:30
ruthra kumar
9fd70a6827 Merge pull request #33115 from ruthra-kumar/duplicate_schema_block
fix: remove product schema block from additional info section on item template
2022-11-28 15:28:50 +05:30
Deepesh Garg
f6126069ee Merge pull request #33129 from deepeshgarg007/accounts_settings_fix
chore: Supplier invoice no field description
2022-11-28 13:05:12 +05:30
Ankush Menat
63b9795d41 fix: opportunity list doesn't show assigned user (#33110)
Because `db_update` is performed `_assign` property is not updated and
hence lead -> opportunity conversion makes it disappear from list view.

Steps to reproduce:

1. Create lead
2. Assign anyone
3. Create opportunity from lead.
4. Form view shows assigned user, list view wont.
2022-11-28 10:58:35 +05:30
Deepesh Garg
4f2ece34df chore: Supplier invoice no field description 2022-11-27 21:50:26 +05:30
Deepesh Garg
dedd722aef Merge pull request #33022 from barredterra/incoterms
feat: Incoterms in buying and selling
2022-11-27 20:52:25 +05:30
rohitwaghchaure
397a0e2a3a Merge pull request #33118 from rohitwaghchaure/production-plan-ux-issues
fix: production plan UX
2022-11-27 08:46:39 +05:30
Sagar Sharma
0919976414 Merge pull request #33120 from s-aga-r/fix/github-issue/32955
fix: `Work Order Summary` and `Job Card Summary` Report
2022-11-26 21:54:00 +05:30
s-aga-r
ef7fd670fc fix: production_item filter in Job Card Summary Report 2022-11-26 16:57:38 +05:30
s-aga-r
481149814e fix: company name with , in Job Card Summary Report 2022-11-26 16:55:45 +05:30
s-aga-r
2e4f3e9317 fix: Work Order filter typo in Job Card Summary Report 2022-11-26 16:54:53 +05:30
s-aga-r
87b39f045c fix: company name with , in Work Order Summary Report 2022-11-26 16:39:32 +05:30
Rohit Waghchaure
8cb7112e72 fix: production plan UX 2022-11-26 15:02:27 +05:30
Sagar Sharma
10a2121361 Merge branch 'develop' into show-batch-selector-only-once 2022-11-26 10:09:10 +05:30
Raffael Meyer
905a50cbb2 Merge branch 'develop' into incoterms 2022-11-25 16:50:55 +01:00
Shariq Ansari
0f87d329d6 fix: only show serial no batch selector only once 2022-11-25 17:03:00 +05:30
ruthra kumar
2c18a95115 fix: remove duplicate schema 2022-11-25 16:23:45 +05:30
Deepesh Garg
c6984cd1c4 Merge pull request #33111 from abhinavxd/fix-disbursable-amount
fix: Loan disbursable amount on current security price
2022-11-25 15:17:54 +05:30
Sabu Siyad
cc63415887 fix(pos): filter on customer groups
Signed-off-by: Sabu Siyad <hello@ssiyad.com>
2022-11-25 15:10:01 +05:30
Abhinav Raut
fe87c27acd fix: disbursable amount on currrent security price 2022-11-25 13:20:01 +05:30
Sagar Sharma
722e29df5c Merge pull request #33090 from s-aga-r/fix/github-issue/20496
fix: MR Item `item_name` and `description` gets reset on `qty` change
2022-11-25 11:19:01 +05:30
barredterra
7fd2639e68 feat: german tax templates 2022-11-25 00:21:33 +01:00
Sagar Sharma
4e7613d4ce Merge branch 'develop' into fix/github-issue/20496 2022-11-24 20:43:52 +05:30
s-aga-r
df0fee2312 fix: MR Item description and item_name gets reset on qty change 2022-11-24 20:42:57 +05:30
rohitwaghchaure
b0c8643517 Merge pull request #33103 from rohitwaghchaure/fixed-job-card-for-qty-ux
fix: job card "Qty to Manufacture" UX
2022-11-24 19:24:05 +05:30
Deepesh Garg
541eb7e43b Merge pull request #33100 from deepeshgarg007/dispatch_address_display
fix: Dispatch address display
2022-11-24 18:00:26 +05:30
Rohit Waghchaure
87d37e90a2 fix: job card for quantity UX 2022-11-24 17:29:50 +05:30
Deepesh Garg
104fdcb9f9 fix: Dispatch address display 2022-11-24 16:41:40 +05:30
Sabu Siyad
80813c66e3 Merge branch 'develop' into fix/pos/warehouse_selection 2022-11-24 16:21:54 +05:30
Deepesh Garg
93f6ea1e55 Merge pull request #33097 from AnandBaburajan/fix_precision_in_asset_tests_again
fix: precision in asset test_scrap_asset
2022-11-24 16:13:41 +05:30
Sabu Siyad
4ad0e2ed7e feat(pos): invoice: fitler warehouse by company
Signed-off-by: Sabu Siyad <hello@ssiyad.com>
2022-11-24 16:11:26 +05:30
Sabu Siyad
95a620a30d fix(pos): warehouse should be in company
Signed-off-by: Sabu Siyad <hello@ssiyad.com>
2022-11-24 15:40:05 +05:30
anandbaburajan
0e726609f1 fix: precision in asset test_scrap_asset 2022-11-24 15:38:05 +05:30
Deepesh Garg
3724f2287c Merge pull request #33092 from deepeshgarg007/debit_credit_issue
fix: Debit and Credit not equal while submitting PI containing asset item
2022-11-24 14:42:56 +05:30
Deepesh Garg
dc8d635120 fix: Debit and Credit not equal while submitting PI containing asset item 2022-11-23 20:29:12 +05:30
Dany Robert
88a0aa4077 chore: pre-commit 2022-11-23 19:04:11 +05:30
Dany Robert
b482e3876d fix: check for session user rather than owner 2022-11-23 18:59:15 +05:30
Deepesh Garg
60740baf3b Merge pull request #33066 from deepeshgarg007/move_taxjar_integration_new
refactor!: Move TaxJar integration from ERPNext
2022-11-23 18:21:55 +05:30
Deepesh Garg
7a7b8c2284 Merge pull request #32836 from resilient-tech/perf-fix-get-cached-value-for-accounts
perf: use `get_cached_value` instead of `db.get_value` in accounts module
2022-11-23 18:20:48 +05:30
Saurabh
5e4a287624 Merge pull request #33065 from saurabh6790/task-view-fix
fix: project website view
2022-11-23 18:17:55 +05:30
Sabu Siyad
a378619c9a fix(pos): partial return amount update
Signed-off-by: Sabu Siyad <hello@ssiyad.com>
2022-11-23 17:52:12 +05:30
Deepesh Garg
0e3438db10 Merge branch 'develop' of https://github.com/frappe/erpnext into move_taxjar_integration_new 2022-11-23 17:47:22 +05:30
Deepesh Garg
f448a077b8 chore: Cleanup patches 2022-11-23 17:47:05 +05:30
rohitwaghchaure
bbfa644475 Merge pull request #33088 from rohitwaghchaure/fixed-ux-for-valuation-rate
fix: Valuation Rate column UX in stock ledger report
2022-11-23 17:29:51 +05:30
Rohit Waghchaure
be19e4f621 fix: Valuation Rate column UX in stock ledger report 2022-11-23 16:44:18 +05:30
Deepesh Garg
a3c81da890 Merge pull request #33062 from nabinhait/pcv-rounding-issue
fix: create rounding gl entry for PCV during gle post processing
2022-11-23 10:36:04 +05:30
rohitwaghchaure
68424887e4 Merge pull request #33077 from rohitwaghchaure/ux-for-inventory-dimension
fix: UX for inventory dimension
2022-11-23 09:53:49 +05:30
Deepesh Garg
06c9c679e6 Merge pull request #33063 from niralisatapara/tds_purchase_order
feat: item wise tds in purchase order
2022-11-23 09:52:00 +05:30
Deepesh Garg
34e775136d Merge pull request #33069 from deepeshgarg007/jv_filter
fix: Remove unnecessary filters from Journal Entry
2022-11-22 20:15:12 +05:30
Deepesh Garg
eb74362263 Merge pull request #33068 from deepeshgarg007/payment_button_visibility
fix: Don't show payment button for invoices on hold
2022-11-22 20:14:41 +05:30
Deepesh Garg
0fffe61e3c Merge pull request #33072 from deepeshgarg007/move_section
chore: Rearrange supplier invoice section in Purchase Invoice
2022-11-22 20:14:14 +05:30
niralisatapara
0fdde2e5c0 feat: item wise tds calculation for purchase order 2022-11-22 14:36:30 +05:30
niralisatapara
46e8cdf31a feat: item wise tds calculation for purchase order. 2022-11-22 14:15:36 +05:30
ruthra kumar
31f463dd83 Merge pull request #33071 from ruthra-kumar/advance_paid_in_account_currency
fix: advance paid updated in account currency for SO/PO
2022-11-22 13:45:04 +05:30
Deepesh Garg
454b598718 chore: Update requirements 2022-11-22 13:00:00 +05:30
Deepesh Garg
e96be712b8 chore: Rearrange supplier invoice section in Purchase Invoice 2022-11-22 12:50:00 +05:30
ruthra kumar
541cf153f7 test: fix test case for SO/PO advance amount 2022-11-22 12:33:29 +05:30
ruthra kumar
bf76b85dfd fix: update advace paid in SO/PO in account currency 2022-11-22 12:33:18 +05:30
Deepesh Garg
cd88a53533 fix: Remove unnecessary filters from Journal Entry 2022-11-21 22:21:03 +05:30
Deepesh Garg
1b9e83251f fix: Don't show payment button for invoices on hold 2022-11-21 21:50:55 +05:30
Deepesh Garg
81c856ccb8 chore: Remove unwanted patch 2022-11-21 21:00:31 +05:30
Deepesh Garg
1100816d7a refactor!: Move TaxJar integration from ERPNext 2022-11-21 20:18:06 +05:30
Saurabh
5d9960ae5b feat: handle empty state 2022-11-21 19:37:57 +05:30
Saurabh
80e45828ae fix: ux for project view on web 2022-11-21 18:16:57 +05:30
Saurabh
7cc99ab63b fix: update tasks route under website route rules 2022-11-21 18:13:54 +05:30
niralisatapara
b9d0b4e2d3 feat: item wise tds in purchase order 2022-11-21 15:43:03 +05:30
Nabin Hait
022d8d5d79 fix: create rounding gl entry for PCV during gle post processing 2022-11-21 15:16:53 +05:30
Deepesh Garg
e25d0ead1a Merge pull request #33051 from deepeshgarg007/timesheet_timer_button
fix: Timesheet timer button
2022-11-21 11:15:02 +05:30
Deepesh Garg
c2b3c3a29d Merge pull request #33052 from deepeshgarg007/soa_routing
fix: Viewing account ledger from party master
2022-11-21 11:14:21 +05:30
Deepesh Garg
15e74c5d7b fix: Viewing account ledger from party master 2022-11-20 20:30:24 +05:30
Deepesh Garg
64802d1220 fix: Timesheet timer button 2022-11-20 19:45:51 +05:30
Deepesh Garg
89631fa744 Merge pull request #32958 from pps190/fix-item-price-brand
fix: link `Item Price` brand to `Brand` doctype.
2022-11-19 19:14:39 +05:30
Deepesh Garg
26dcde2931 Merge pull request #32999 from ruthra-kumar/exchange_rate_reval_company_currency
fix: incorrect currency in Exchange rate revaluation
2022-11-19 18:30:03 +05:30
Deepesh Garg
f96c66bbc0 Merge pull request #33032 from deepeshgarg007/dimension_report_filtering
fix: Accounting Dimension filtering for Sales and Purchase Report
2022-11-19 18:19:37 +05:30
gavin
dd2493a541 fix(realtime): Restrict updates to only last modified or current user (#33034) 2022-11-18 17:17:54 +05:30
ruthra kumar
5caaccc94b fix: always send account currency in response 2022-11-18 17:10:39 +05:30
ruthra kumar
68b04e2577 fix: incorrect currency in Exchange rate revaluation 2022-11-18 17:10:39 +05:30
Raffael Meyer
491857b3c8 fix: remove obsolete comment 2022-11-18 10:57:52 +01:00
Deepesh Garg
df096688f7 Merge pull request #33014 from deepeshgarg007/multi_invoice_payment
fix: Bulk payment generation against invoices
2022-11-18 15:10:35 +05:30
Deepesh Garg
8b394afaa9 fix: Accounting Dimension filtering for Sales and Purchase Report 2022-11-18 15:07:12 +05:30
Sagar Sharma
985ce0dc42 Merge pull request #32986 from s-aga-r/fix/scr-return-rejected-qty
fix: hide rejected-fields in return SCR
2022-11-18 15:00:22 +05:30
Sagar Sharma
602a13b0ac Merge pull request #32905 from vishdha/internal_transfer
fix: Internal Transfer Material Request cycle and tracking fixed till purchase receipt
2022-11-18 13:15:27 +05:30
Daizy Modi
62c0210463 Merge branch 'develop' into perf-fix-get-cached-value-for-accounts 2022-11-18 12:07:52 +05:30
Sagar Sharma
29132609ff Merge branch 'develop' into fix/scr-return-rejected-qty 2022-11-18 12:06:59 +05:30
s-aga-r
12d7b7e9c2 chore: linters 2022-11-18 11:42:44 +05:30
Sagar Sharma
cbfd8da848 Merge branch 'develop' into internal_transfer 2022-11-18 10:38:37 +05:30
Sagar Sharma
d1f85dd9fc Merge pull request #33019 from ssiyad/fix/mutate_iter_list
fix: use `list()` on self mutating iteration
2022-11-18 10:25:13 +05:30
barredterra
a5966b6f84 feat: add connections to Incoterm doctype 2022-11-17 22:37:04 +01:00
barredterra
ffd287d5a6 feat: add german translations for incoterm titles 2022-11-17 22:18:53 +01:00
barredterra
77105306f2 feat: add incoterm to purchasing transactions 2022-11-17 22:18:26 +01:00
barredterra
029f22c549 feat: add incoterm to sales transactions 2022-11-17 22:17:59 +01:00
barredterra
ce83f02f24 feat: create Incoterm records after install 2022-11-17 22:17:19 +01:00
barredterra
d2563ee973 feat: create incoterms and migrate shipments 2022-11-17 22:16:43 +01:00
barredterra
1a1bfc8db9 feat: add doctype Incoterm 2022-11-17 22:14:30 +01:00
Sagar Vora
48413b0778 fix: reduce function call 2022-11-18 02:22:43 +05:30
Sagar Vora
66ac65482d fix: add missing comma 2022-11-18 02:16:56 +05:30
Sagar Vora
8ae58ed427 fix: use doc_before_save and other changes 2022-11-18 02:13:16 +05:30
Daizy Modi
fdfe5cbf93 fix: use get_cached_value to avoid db call with db.exists 2022-11-17 19:14:10 +05:30
Daizy Modi
678a4c33da fix: resolved merge conflicts 2022-11-17 19:13:10 +05:30
Sabu Siyad
0b5584a54a Merge branch 'develop' into fix/mutate_iter_list 2022-11-17 17:58:49 +05:30
Sabu Siyad
546c809cbe fix: use list() on self mutating iteration
https://github.com/frappe/erpnext/issues/30325

Signed-off-by: Sabu Siyad <hello@ssiyad.com>
2022-11-17 17:46:49 +05:30
Deepesh Garg
cbe8fa7fd2 Merge pull request #33009 from ssiyad/fix/pos/item_img_border
fix(pos): item selector image border radius
2022-11-17 17:31:29 +05:30
Sagar Sharma
29a8d9a9b4 Merge branch 'develop' into internal_transfer 2022-11-17 16:42:18 +05:30
Deepesh Garg
2dfe849c7d fix: Bulk payment generation against invoices 2022-11-17 15:53:56 +05:30
Dany Robert
be15419bd5 chore: pre-commit 2022-11-17 11:00:34 +01:00
Dany Robert
61f05132db feat: validate repost item valuation against accounts freeze date 2022-11-17 11:00:01 +01:00
Ankush Menat
fd3c7903ba chore: typo 2022-11-17 14:18:05 +05:30
Sagar Sharma
da4c20f7be Merge branch 'develop' into fix/scr-return-rejected-qty 2022-11-17 14:15:16 +05:30
Sagar Sharma
40f90d3e95 Merge pull request #33006 from s-aga-r/purchase-order/internal-supplier
fix: make `is_internal_supplier` read-only in PO
2022-11-17 14:08:34 +05:30
Sagar Sharma
1349d24514 Merge branch 'develop' into purchase-order/internal-supplier 2022-11-17 14:08:07 +05:30
Sabu Siyad
2f4940cc26 fix(pos): item selector image border radius
Signed-off-by: Sabu Siyad <hello@ssiyad.com>
2022-11-17 13:21:47 +05:30
Ankush Menat
34e4903ed7 refactor: search queries (#33004)
- guard clauses for readability
- use values or format
2022-11-17 13:04:42 +05:30
Sagar Sharma
f71f27462d Merge branch 'develop' into fix/scr-return-rejected-qty 2022-11-17 13:04:15 +05:30
Sagar Sharma
e13b9e839d Merge branch 'develop' into purchase-order/internal-supplier 2022-11-17 13:04:07 +05:30
ruthra kumar
7f6e447d45 Merge pull request #33003 from AnandBaburajan/fix_precision_in_asset_tests
fix: precision in asset tests
2022-11-17 12:54:06 +05:30
s-aga-r
5efbc2cbf8 fix: make is_internal_supplier read-only 2022-11-17 12:36:44 +05:30
anandbaburajan
218da1217a fix: add missing commas and brackets 2022-11-17 12:23:38 +05:30
Anand Baburajan
538da9a58e Merge branch 'develop' into fix_precision_in_asset_tests 2022-11-17 12:17:27 +05:30
anandbaburajan
b5e5d3b3af fix: precision in asset tests 2022-11-17 12:13:06 +05:30
Ritwik Puri
b03b568e6c chore(patch): remove reload_doc from post model sync update_exchange_rate_settings patch (#32994)
[skip ci]
2022-11-17 11:59:42 +05:30
Ankush Menat
1bd886387b chore: hardcode doctype 2022-11-17 11:58:35 +05:30
Sagar Sharma
5083c22490 Merge branch 'develop' into fix/scr-return-rejected-qty 2022-11-17 10:15:23 +05:30
rohitwaghchaure
c460141f0d Merge pull request #32911 from rohitwaghchaure/workstation-type-feat-for-bom
feat: Workstation Type for BOM
2022-11-17 00:00:17 +05:30
rohitwaghchaure
31afae3e75 Merge branch 'develop' into workstation-type-feat-for-bom 2022-11-16 23:26:08 +05:30
Rohit Waghchaure
ffa30127e7 fix: linters failing 2022-11-16 23:23:06 +05:30
Rohit Waghchaure
7bd06e6fbc test: test case to check workstation type 2022-11-16 23:19:04 +05:30
Deepesh Garg
9154d08b89 Merge pull request #32882 from ernestoruiz89/patch-9
fix: add translation function to doctype name on message
2022-11-16 20:41:34 +05:30
Deepesh Garg
3a523b56bf Merge pull request #32983 from deepeshgarg007/journal_entry_template_fix
fix: Opening journal entry templates
2022-11-16 20:41:07 +05:30
Sagar Sharma
aae2408f70 Merge branch 'develop' into fix/scr-return-rejected-qty 2022-11-16 18:40:01 +05:30
Deepesh Garg
aac1f4923b Merge pull request #32989 from deepeshgarg007/flake8
ci: fix flake8 URL
2022-11-16 16:25:46 +05:30
Deepesh Garg
e81bec5fc9 ci: fix flake8 URL 2022-11-16 16:24:28 +05:30
Sagar Sharma
399ee80d80 Merge branch 'develop' into fix/scr-return-rejected-qty 2022-11-16 15:02:55 +05:30
s-aga-r
7dd7617ec7 fix: hide reject-fields in return SCR 2022-11-16 14:28:54 +05:30
s-aga-r
8a73e963ce fix: don't set rejected-qty in return SCR 2022-11-16 14:28:32 +05:30
Vishal
e5dfd53e6f chore: minor fix 2022-11-16 14:25:35 +05:30
Vishal
ba6189d054 fix: minor change 2022-11-16 13:58:29 +05:30
Vishal
343b414b40 fix: test case updated for mr 2022-11-16 13:53:21 +05:30
Vishal
89aabdaaaa fix: test case added for MR internal Transfer 2022-11-16 13:53:21 +05:30
Vishal
d86afddb60 fix: minor issue fixed 2022-11-16 13:53:21 +05:30
Vishal
71412f6877 fix: Internal Transfer Material Request cycle and tracking fixed till purchase receipt 2022-11-16 13:53:21 +05:30
Deepesh Garg
0486078ba9 Merge pull request #32984 from nabinhait/si-needs-repost
fix: Validate for deferred revenue only if sales invoice needs repost
2022-11-16 13:12:09 +05:30
Nabin Hait
b89b07d0ff fix: Validate for deferred revenue only if sales invoice needs repost 2022-11-16 12:16:23 +05:30
Deepesh Garg
33b61aef5a fix: Opening journal entry templates 2022-11-16 11:57:17 +05:30
Devin Slauenwhite
3a35651441 fix: naming 2022-11-15 08:26:16 -05:00
Ankush Menat
c013db6ea1 fix: cast POS query inputs to integers (#32975)
fix: cast POS query inputs to integers
2022-11-15 18:10:45 +05:30
Deepesh Garg
b3bc1c66a3 Merge pull request #32968 from frappe/mergify/bp/develop/pr-32953
chore(payment_entry): Remove dead validations (backport #32953)
2022-11-15 16:32:40 +05:30
Rohit Waghchaure
0a69523940 fix: UX for inventory dimension 2022-11-15 15:57:30 +05:30
Sagar Sharma
6f2989c7f2 Merge pull request #32971 from s-aga-r/revert-32867-fix/scr/rejected-qty
Revert "fix: get `consumed_qty` based on `received_qty` in SCR"
2022-11-15 15:17:15 +05:30
s-aga-r
369db4eacc test: fix test cases for supplied-items consumed_qty 2022-11-15 14:39:43 +05:30
s-aga-r
01f56c621c Revert "fix: get consumed_qty based on received_qty in SCR"
This reverts commit 70c9b8dc50.
2022-11-15 14:32:16 +05:30
s-aga-r
3706a9b4dc Revert "fix: set received_qty before_validate SCR"
This reverts commit c447dfaa9c.
2022-11-15 14:30:13 +05:30
Gavin D'souza
35088bb4c4 chore(payment_entry): Remove dead validations
(cherry picked from commit e1ecc9a819)
2022-11-15 08:34:08 +00:00
Deepesh Garg
a0d9e1bd57 Merge pull request #32962 from deepeshgarg007/return_write_off
fix: Write Off section visibility for non POS Invoices
2022-11-15 13:01:06 +05:30
rohitwaghchaure
91fad1935e Merge pull request #32947 from rohitwaghchaure/incorrect-fix-of-conversion-factor-in-pp
fix: incorrect fix of conversion factor in PP
2022-11-15 10:30:23 +05:30
Deepesh Garg
9f5d613c78 fix: Write Off section visibility for non POS Invoices 2022-11-15 09:45:39 +05:30
Deepesh Garg
a1a992b0dd Merge pull request #32956 from deepeshgarg007/acc_dimension_filter_label
fix: Label for applicable dimension table
2022-11-15 09:24:30 +05:30
Devin Slauenwhite
cee069d426 fix: link to brand doctype. 2022-11-14 17:38:46 -05:00
Deepesh Garg
8c13f70fc5 fix: Label for applicable dimension table 2022-11-14 20:39:40 +05:30
Ernesto Ruiz
01cc58db83 Merge branch 'develop' into patch-9 2022-11-14 07:44:01 -06:00
Rohit Waghchaure
105c272816 feat: Workstation Type for BOM 2022-11-14 13:03:03 +05:30
rohitwaghchaure
ab1722d78e Merge pull request #32937 from s-aga-r/refactor/qb/job-card
refactor: rewrite `job_card.py` queries in QB
2022-11-14 11:25:47 +05:30
Rohit Waghchaure
490b0e3cdf fix: incorrect fix of conversion factor in PP 2022-11-14 10:10:49 +05:30
Sagar Sharma
a191ce6200 Merge branch 'develop' into refactor/qb/job-card 2022-11-13 22:31:35 +05:30
Deepesh Garg
7ba8350089 Merge branch 'develop' into patch-9 2022-11-13 20:42:48 +05:30
Deepesh Garg
22598a09de Merge pull request #32938 from deepeshgarg007/bg_query
chore: Remove raw SQL query
2022-11-13 20:41:08 +05:30
Sagar Vora
b06345af46 fix: check type for reference name 2022-11-13 19:58:49 +05:30
Deepesh Garg
a2260a3dc2 Merge branch 'develop' into bg_query 2022-11-13 19:47:43 +05:30
Deepesh Garg
6b93b3f12a Merge pull request #32866 from ruthra-kumar/gross_profit_fix_buying_amount
fix: incorrect buying amount on Gross Profit
2022-11-13 19:15:03 +05:30
Deepesh Garg
4b9921782b chore: Remove qb doc reference 2022-11-13 18:48:32 +05:30
s-aga-r
7df2921d38 refactor: rewrite job_card.py queries in QB 2022-11-12 22:03:56 +05:30
Deepesh Garg
42a59d5c17 chore: Remove raw SQL query 2022-11-12 17:32:04 +05:30
Sagar Sharma
4e9a63423f Merge pull request #32913 from resilient-tech/fix-item-price-fetch
fix: set stock UOM in args to ensure item price is fetched
2022-11-12 10:08:44 +05:30
Deepesh Garg
d03979eef9 Merge pull request #32878 from abhinavxd/fix-repayment-schedule
fix: repayment schedule regeneration
2022-11-11 14:22:40 +05:30
ruthra kumar
2c8b0b17a7 test: buying amount of invoices
1. Invoice with unset `update_stock`, with and without Delivery Notes
2022-11-11 08:33:54 +05:30
ruthra kumar
e4d16c31da fix: GP incorrect buying amount if no upd on SI and Delivery Note 2022-11-11 08:33:48 +05:30
rohitwaghchaure
8ae9c1d192 Merge pull request #32895 from rohitwaghchaure/fixed-performance-issue-for-purchase-receipt
fix: Purchase Receipt timeout error
2022-11-10 22:41:54 +05:30
Deepesh Garg
902e1ab74b Merge branch 'develop' into patch-9 2022-11-10 20:08:27 +05:30
Deepesh Garg
f4920d6475 Merge pull request #32880 from ernestoruiz89/patch-7
fix: add translate function to valitate company msg in chart of accounts importer
2022-11-10 20:07:52 +05:30
Deepesh Garg
9d5c8d9d6b Merge branch 'develop' into fix-repayment-schedule 2022-11-10 19:52:59 +05:30
Deepesh Garg
06a42caa5b Merge pull request #32923 from deepeshgarg007/rate_quotation
fix: Maintain same rate between Quotation and Sales Order
2022-11-10 19:52:27 +05:30
Deepesh Garg
e559fea8ff Merge pull request #32921 from deepeshgarg007/netvalues_psoa
feat: Add net value filter on PSOA
2022-11-10 19:51:56 +05:30
Deepesh Garg
8f65677cb4 Merge pull request #32912 from nabinhait/customer-supplier-tab-break
fix(ux): Tab break in Customer and Supplier form
2022-11-10 18:30:14 +05:30
Deepesh Garg
362ec7b673 fix: Maintain same rate between Quotation and Sales Order 2022-11-10 18:28:08 +05:30
Deepesh Garg
51521fc19f feat: Add net value filter on PSOA 2022-11-10 17:48:25 +05:30
Sagar Sharma
e9306f3c75 Merge pull request #32918 from s-aga-r/fix/github-issue/28336
fix: WO Skip Material Transfer to WIP Warehouse
2022-11-10 17:12:00 +05:30
Sagar Sharma
e7fa2e08ad fix: set WIP Warehouse in Job Card 2022-11-10 16:40:53 +05:30
Sagar Sharma
9730cd0aec fix: don't set WIP Warehouse if is checked in WO 2022-11-10 16:18:10 +05:30
Ankush Menat
c16553626f build: python 3.11 support (#32843)
ci: use python 3.11 in tests

[skip ci]
2022-11-10 14:22:05 +05:30
Deepesh Garg
1283c5b7a5 Merge branch 'develop' into fix-repayment-schedule 2022-11-10 09:39:39 +05:30
Ernesto Ruiz
a007f1da9d Merge branch 'develop' into patch-7 2022-11-09 15:53:36 -06:00
Ernesto Ruiz
499dfee2d4 Merge branch 'develop' into patch-9 2022-11-09 15:52:35 -06:00
Ankush Menat
7e1742956c refactor: Remove usage of deprecated methods (#32914)
Warn: Just used regex to replace all usage.
```regex
s/frappe.db.set(\(.*\),\(.*\),\(.*\))/\1.db_set(\2, \3)/g
```

Required after: https://github.com/frappe/frappe/pull/18815
2022-11-09 20:09:06 +05:30
Sagar Vora
57038c3969 fix: set stock UOM in args to ensure item price is fetched 2022-11-09 18:56:09 +05:30
Nabin Hait
fb7ee301b5 fix(ux): Tab break in Customer and Supplier form 2022-11-09 18:03:23 +05:30
Deepesh Garg
ff51f3b95e Merge branch 'develop' into patch-7 2022-11-09 14:34:39 +05:30
Deepesh Garg
5f1b226362 Merge pull request #32742 from ruthra-kumar/ple_repost
feat: Tool to repost PLE manually
2022-11-09 14:26:37 +05:30
Deepesh Garg
077f3c515f Merge branch 'develop' into patch-9 2022-11-09 09:19:28 +05:30
Rohit Waghchaure
7278387879 fix: test cases 2022-11-09 01:28:40 +05:30
Sagar Sharma
438f2ac1a8 Merge pull request #32888 from s-aga-r/fix/scr/return-scr-ref
chore: link SCR Return in SCR Dashboard
2022-11-08 21:36:43 +05:30
Sagar Sharma
030ef6da25 Merge branch 'develop' into fix/scr/return-scr-ref 2022-11-08 21:36:00 +05:30
Rohit Waghchaure
4082149f0e fix: Purchase Receipt timeout error 2022-11-08 20:59:20 +05:30
Deepesh Garg
c8619284bc Merge pull request #32883 from deepeshgarg007/timesheet_project_filter
fix: Project filter in timesheet
2022-11-08 14:54:49 +05:30
Sagar Sharma
47248251e2 chore: link SCR Return in SCR Dashboard 2022-11-08 12:29:41 +05:30
Sagar Sharma
a863f59cf0 Merge pull request #32886 from s-aga-r/fix/stock-entry-list
chore: remove `debugger` from `stock_entry_list.js`
2022-11-08 12:10:05 +05:30
Sagar Sharma
84ab100d86 chore: remove debugger from stock_entry_list.js 2022-11-08 12:05:15 +05:30
Deepesh Garg
55d6773be6 Merge branch 'develop' of https://github.com/frappe/erpnext into timesheet_project_filter 2022-11-08 11:02:01 +05:30
Deepesh Garg
7b5cf6978e chore: Linting Issues 2022-11-08 11:00:48 +05:30
ruthra kumar
0448c0fa36 feat: Repost Payment Ledger entries for vouchers
primarily intended to manually correct PLE entries for vouchers
affected by Item Value repost-https://github.com/frappe/erpnext/pull/32567
2022-11-08 07:47:47 +05:30
Sagar Sharma
b5d64bc7c5 Merge pull request #32877 from s-aga-r/fix/ux/scr/supplied-items/consumed-qty
fix: make `consumed_qty` read-only in SCR Supplied Items
2022-11-07 22:58:54 +05:30
Deepesh Garg
2b65b22aa2 fix: Project filter in timesheet 2022-11-07 22:48:52 +05:30
Sagar Sharma
1d52084b05 Merge branch 'develop' into fix/ux/scr/supplied-items/consumed-qty 2022-11-07 21:58:11 +05:30
Sagar Sharma
5e8a22be24 fix: linter 2022-11-07 21:54:12 +05:30
Ernesto Ruiz
1f13bc906b fix: add translation functuinon to doctype name on message in bulk_transaction_processing 2022-11-07 09:43:28 -06:00
Ernesto Ruiz
637c08d189 fix: add translate function to valitate company msg in chart of accounts importer 2022-11-07 09:22:38 -06:00
Deepesh Garg
404662e794 Merge pull request #32625 from deepeshgarg007/editable_inovice
feat: Editable Sales Invoice
2022-11-07 18:29:21 +05:30
Abhinav Raut
d6ab2b3b87 fix: repayment schedule regeneration 2022-11-07 17:43:08 +05:30
Sagar Sharma
734db5b722 Merge branch 'develop' into fix/ux/scr/supplied-items/consumed-qty 2022-11-07 17:36:42 +05:30
Sagar Sharma
bf4b012cec fix: make consumed_qty editable when backflush based on Material Transfer 2022-11-07 17:23:33 +05:30
Sagar Sharma
f8d2e276a5 fix: make consumed_qty read-only in SCR Supplied Items 2022-11-07 17:19:03 +05:30
Deepesh Garg
e29f756146 chore: Validate for deferred revenue invoices 2022-11-07 16:42:45 +05:30
Deepesh Garg
5fe55176ec chore: Enable no-copy for repost required field 2022-11-07 16:42:12 +05:30
Ankush Menat
30daeb90a8 fix: incorrect single valeu fetch
refer https://github.com/frappe/frappe/pull/18787

[skip ci]
2022-11-07 15:38:38 +05:30
Deepesh Garg
eb4820b68b Merge pull request #32874 from SolufyPrivateLimited/incr-clm-wwibav
fix: Increase columns width in Warehouse wise Item Balance Age and Value
2022-11-07 13:34:47 +05:30
Nihantra C. Patel
8355c1092c fix: Increase columns width in Warehouse wise Item Balance Age and Value 2022-11-07 11:45:47 +05:30
rohitwaghchaure
5e7a69e649 Merge pull request #32802 from s-aga-r/fix/github-issue/29006
fix: `Material Consumption` option in case of `Skip Transfer to WIP` in WO
2022-11-07 09:35:39 +05:30
Daizy Modi
4efc947f14 perf: use get_cached_value instead of db.get_value in controllers (#32776) 2022-11-07 09:21:03 +05:30
Sagar Sharma
8859e6f1bb Merge pull request #32867 from s-aga-r/fix/scr/rejected-qty
fix: get `consumed_qty` based on `received_qty` in SCR
2022-11-06 16:18:08 +05:30
Sagar Sharma
4d8da4420e test: add test case for consumed-qty 2022-11-06 14:55:33 +05:30
Sagar Sharma
70c9b8dc50 fix: get consumed_qty based on received_qty in SCR 2022-11-06 13:33:47 +05:30
Sagar Sharma
c447dfaa9c fix: set received_qty before_validate SCR 2022-11-06 13:32:15 +05:30
ruthra kumar
9209ec59c2 refactor: split delete gl utility function into two 2022-11-06 11:39:44 +05:30
Raffael Meyer
d2b6490bca chore: add german translations (#32846)
Mostly for balance sheet
2022-11-06 10:22:33 +05:30
Deepesh Garg
8d30ebb12b fix: Disable tax included prices for internal transfers (#32794)
* fix: Disable tax-included prices for internal transfers
2022-11-05 20:51:15 +05:30
Sagar Sharma
0394080898 Merge branch 'develop' into fix/github-issue/29006 2022-11-05 20:11:55 +05:30
Ankush Menat
75983ce809 fix: remove global _("translation") calls (#32828)
This is not how it works. Translations are dynamic based on language
sets during request (using header, user's preferences etc)

Calling them on global variables makes no sense.

Ref: https://github.com/frappe/frappe/pull/18733
2022-11-05 18:49:15 +05:30
Sagar Sharma
e820629f83 Merge pull request #32850 from s-aga-r/fix/scr/return
fix: wrong consumed items in SCR return
2022-11-05 17:23:04 +05:30
Sagar Sharma
cc8d540943 Merge branch 'develop' into fix/scr/return 2022-11-05 16:48:59 +05:30
Deepesh Garg
90fbab4b1e Merge pull request #32847 from maharshivpatel/fix-pos-opening-entry-profile-filter
fix: Create POS Opening Entry POS Profile filter.
2022-11-05 16:44:39 +05:30
Sagar Sharma
5665d1afa0 Merge branch 'develop' into fix/scr/return 2022-11-05 16:36:07 +05:30
Deepesh Garg
be0f6b3e6e Merge branch 'develop' of https://github.com/frappe/erpnext into editable_inovice 2022-11-05 16:35:55 +05:30
Deepesh Garg
0966867c08 chore: Reset repost_required_flag on cancel 2022-11-05 16:35:43 +05:30
Deepesh Garg
4ff06a9d79 Merge pull request #32844 from deepeshgarg007/auto_allocate_advances
fix: Auto advance allocation against partial invoices
2022-11-05 16:27:59 +05:30
Sagar Sharma
b5221a5c74 Merge branch 'develop' into fix/scr/return 2022-11-05 16:23:58 +05:30
Sagar Sharma
324bfa9fde test: fix test case 2022-11-05 16:18:31 +05:30
Sagar Sharma
760c26e9c0 fix: make BOM required in SCR Item 2022-11-05 15:52:14 +05:30
Sagar Sharma
761e9df1bf test: add test case 2022-11-05 15:52:14 +05:30
Sagar Sharma
611d827e0b fix: rename test method 2022-11-05 15:51:29 +05:30
Sagar Sharma
54072ec9cd fix: map BOM while mapping the return SCR 2022-11-05 15:51:29 +05:30
Sagar Sharma
4a4abf9b64 Merge pull request #32849 from frappe/mergify/bp/develop/pr-32831
fix: mysql syntax issue (backport #32831)
2022-11-05 12:40:34 +05:30
Sagar Sharma
3ca9d53d1b refactor: rewrite query in QB
(cherry picked from commit 2f145f9912)
2022-11-05 06:12:40 +00:00
Bhavesh Maheshwari
f4779df9b3 fix: mysql syntax issue
(cherry picked from commit 4d9bbd4c9c)
2022-11-05 06:12:40 +00:00
Deepesh Garg
428971f127 test: Check parital payment allocation 2022-11-04 15:50:39 +05:30
Deepesh Garg
181df2fe63 fix: Auto advance allocation against partial invoices 2022-11-04 15:49:37 +05:30
Maharshi Patel
1328a45f2a fix: Create POS Opening Entry POS Profile filter.
pos_profile_query was variable instead of function.
2022-11-04 15:29:17 +05:30
Deepesh Garg
cbf82872fb Merge pull request #32646 from niralisatapara/tds_purchase_invoice
feat: Item Wise TDS Calculation
2022-11-04 13:08:10 +05:30
Deepesh Garg
159b511d16 Merge pull request #32809 from monolithon/develop
feat: Optional Hungarian COA for microenterprises
2022-11-04 13:00:13 +05:30
rohitwaghchaure
441f082fcb Merge pull request #32799 from rohitwaghchaure/fix-scan-qrcode-functionality
fix: Scan Barcode UX
2022-11-04 11:04:40 +05:30
Deepesh Garg
f6a61b999f chore: fix patch 2022-11-04 08:11:38 +05:30
Ernesto Ruiz
ad0dd693ac chore: add translation function to Bank Reconciliation Tool related files
chore: add translation  function to Bank Reconciliation Tool related files
2022-11-04 01:06:01 +05:30
Deepesh Garg
153675e52a chore: Update patch 2022-11-04 01:03:45 +05:30
Deepesh Garg
e2ad785422 chore: Hide tax withholding net total field 2022-11-04 01:03:20 +05:30
rohitwaghchaure
0caa35a251 Merge branch 'develop' into fix/github-issue/29006 2022-11-03 16:12:53 +05:30
Rohit Waghchaure
e5b19e3f70 fix: auto increment qty if item table has no items 2022-11-03 14:57:36 +05:30
Daizy Modi
010bd9c558 fix: remove cache param 2022-11-03 14:36:48 +05:30
Daizy Modi
27df455b98 perf: use get_cached_value instead of db.get_value in accounts module 2022-11-03 13:38:48 +05:30
rohitwaghchaure
7a5a500d29 Merge pull request #32832 from rohitwaghchaure/fixed-customer-supplier-not-able-to-select
fix: not able to select customer / supplier
2022-11-03 11:54:58 +05:30
Rohit Waghchaure
b0fc568c80 fix: not able to select customer / supplier 2022-11-03 11:24:58 +05:30
niralisatapara
12456f9850 feat: item wise tds calculation 2022-11-03 10:46:30 +05:30
Deepesh Garg
f5478c871c Merge pull request #32773 from AnandBaburajan/asset_bill_date_new
fix: for asset's purchase_date, if bill_date is set, use that instead of posting_date
2022-11-03 09:51:44 +05:30
Deepesh Garg
8581b7820d Merge pull request #32713 from ernestoruiz89/patch-9
fix: add missing translation function on report related documents
2022-11-03 09:46:43 +05:30
Anand Baburajan
c95f05a3dc Merge branch 'develop' into asset_bill_date_new 2022-11-02 21:30:40 +05:30
Sagar Sharma
cd5836243d Merge branch 'develop' into fix/github-issue/29006 2022-11-02 19:07:47 +05:30
ruthra kumar
c3dc1c272b Merge pull request #32816 from ruthra-kumar/advance_paid_in_so_and_po
fix: update advance paid in SO/PO from Payment Ledger
2022-11-02 16:27:56 +05:30
Sagar Sharma
25a2c8ab82 Merge pull request #32788 from s-aga-r/fix/github-issue/30339
fix: use `flt` instead of `cint` in `get_batch_no`
2022-11-02 15:54:41 +05:30
ruthra kumar
721ac6b847 test: SO advance paid on Payment submission and cancellation 2022-11-02 15:54:23 +05:30
ruthra kumar
1a0a8ac7e2 test: PO advance paid on payment submission and cancellation 2022-11-02 15:53:52 +05:30
ruthra kumar
81d791eea0 test: refactor use @change_settings decorator when possible 2022-11-02 15:40:56 +05:30
Rohit Waghchaure
e1f9ba78e5 fix: Scan Barcode UX 2022-11-02 15:37:46 +05:30
niralisatapara
ea387937d0 feat: item wise tds calculation 2022-11-02 12:30:58 +05:30
niralisatapara
2ca0cf6fc4 feat: item wise tds calculation 2022-11-02 12:19:51 +05:30
Sagar Sharma
be4593c1d9 Merge branch 'develop' into fix/github-issue/30339 2022-11-02 11:50:51 +05:30
Sagar Sharma
aa6e8c9ec0 Merge branch 'develop' into fix/github-issue/29006 2022-11-02 11:50:44 +05:30
niralisatapara
4aff2a32ad Merge branch 'develop' of https://github.com/niralisatapara/erpnext into develop 2022-11-02 11:21:02 +05:30
Muvuk
579afed460 feat: Optional Hungarian COA for microenterprises #32688 2022-11-01 19:36:42 +01:00
rohitwaghchaure
a6a280669c Merge pull request #32800 from rohitwaghchaure/test-cases-failing
fix: test cases
2022-11-01 22:51:31 +05:30
Rohit Waghchaure
3f2728e3f7 test: run tmate 2022-11-01 22:20:13 +05:30
Deepesh Garg
e0a705afe7 Merge pull request #32779 from deepeshgarg007/sales_invoice_default_mop
fix: Mode of payment for returns in POS Sales Invoice
2022-11-01 21:28:54 +05:30
Deepesh Garg
62ae329be3 Merge pull request #32801 from deepeshgarg007/purchase_invoice_cancel_amend
fix: Issues while cancel/amending Purchase Invoice with TDS enabled
2022-11-01 20:47:55 +05:30
Sagar Sharma
31f95da947 Merge branch 'develop' into fix/github-issue/30339 2022-11-01 20:30:55 +05:30
Deepesh Garg
a4f7079270 Merge branch 'develop' of https://github.com/frappe/erpnext into sales_invoice_default_mop 2022-11-01 20:17:43 +05:30
Deepesh Garg
5b74161195 chore: Update tests 2022-11-01 20:17:34 +05:30
Deepesh Garg
f7c9258770 fix: Issues while cancel/amending Purchase Invoice with TDS enabled 2022-11-01 19:54:41 +05:30
Sagar Sharma
8ea6983734 fix: Material Consumption option in case of Skip Transfer to WIP in WO 2022-11-01 19:43:06 +05:30
Rohit Waghchaure
ddd1b4be3f fix: test cases 2022-11-01 19:30:37 +05:30
Anand Baburajan
05d2c7f9ae Merge branch 'develop' into asset_bill_date_new 2022-11-01 17:45:23 +05:30
Dany Robert
1d83fb20d6 feat(pricing rule): free qty rounding and recursion qty (#32577)
Option to specify recursion start qty and repeating qty

Co-authored-by: Deepesh Garg <deepeshgarg6@gmail.com>
2022-11-01 16:39:32 +05:30
Deepesh Garg
9c57f3d339 Merge pull request #32639 from maharshivpatel/fix-pricing-rule-item-group-uom
fix: Pricing rule item group consider UOM
2022-11-01 16:20:53 +05:30
Maharshi Patel
6b0178e9fb Merge branch 'develop' into fix-pricing-rule-item-group-uom 2022-11-01 15:21:41 +05:30
rohitwaghchaure
790b371e47 Merge pull request #32790 from AnandBaburajan/asset_scrap_and_sale_tests_fix
fix: pro_rata_amount calculation in assets tests
2022-11-01 15:16:06 +05:30
Maharshi Patel
cc6dfd91cf Merge branch 'develop' into fix-pricing-rule-item-group-uom 2022-11-01 15:06:22 +05:30
anandbaburajan
672fbd3849 chore: empty commit to try fixing stuck test 2022-11-01 14:25:38 +05:30
Maharshi Patel
935f31eff9 fix: test cases added for item group 2022-11-01 12:55:46 +05:30
anandbaburajan
65e855bfff fix: pro_rata_amount calculation in assets tests 2022-11-01 12:45:28 +05:30
Sagar Sharma
9fb3fb4c83 fix: use flt instead of cint in get_batch_no 2022-11-01 10:45:13 +05:30
ruthra kumar
4487065b67 fix: update advance paid in SO/PO from Payment Ledger 2022-11-01 10:29:31 +05:30
rohitwaghchaure
1033d34964 Merge pull request #32730 from rohitwaghchaure/duplicate-custom-fields-inventory-dimension
fix: duplicate custom fields for inventory dimension
2022-10-31 22:25:29 +05:30
Deepesh Garg
5b150abdcb Merge pull request #32768 from deepeshgarg007/cc_main_allocation
fix: Budget validation for main cost center
2022-10-31 22:18:50 +05:30
Deepesh Garg
b98d25dafb Merge pull request #32777 from deepeshgarg007/sales_order_advance_paid_amount
fix: Reset advance paid amount on Order cancel and amend
2022-10-31 21:38:43 +05:30
Deepesh Garg
06e8e28531 fix: Mode of payment for returns in POS Sales Invoice 2022-10-31 19:58:46 +05:30
Deepesh Garg
92f37ca111 fix: Reset advance paid amount on Oreder cancel and amend 2022-10-31 19:01:54 +05:30
Deepesh Garg
3a420ec808 Merge pull request #32772 from gn306029/develop
chore: Update zh-TW translations (#31775)
2022-10-31 17:43:36 +05:30
Rohit Waghchaure
45ededbed5 fix: duplicate custom fields for inventory dimension 2022-10-31 15:33:23 +05:30
anandbaburajan
f322c608cf fix: for asset's purchase_date, if bill_date is set, use that instead of posting_date 2022-10-31 12:41:37 +05:30
gn306029
a612a666f3 chore: Update zh-TW translations (#31775) 2022-10-31 12:32:57 +08:00
Deepesh Garg
4e26d42d17 fix: Budget validation for main cost center 2022-10-30 19:33:27 +05:30
Hossein Yousefian
54c2ffc36b fix: Pass project to stock entry items
fix: Pass project to stock entry items
2022-10-29 22:24:59 +05:30
Sagar Sharma
16a8bcc77d Merge pull request #32754 from s-aga-r/fix/github-issue/32734
fix: add `Sales Order` reference in Material Request Dashboard
2022-10-29 12:36:37 +05:30
Sagar Sharma
15ebf4a0cf fix: add Sales Order reference in Material Request Dashboard 2022-10-29 12:01:37 +05:30
Deepesh Garg
cca36cab70 Merge pull request #32744 from ruthra-kumar/so_terms_report_enhancement
refactor: additional filters on Payment Terms status report
2022-10-29 11:09:43 +05:30
Deepesh Garg
49343e9f68 chore: column name 2022-10-28 22:03:09 +05:30
Deepesh Garg
b6ade62211 Merge pull request #32662 from s-aga-r/refactor/stock/remaining-reports
refactor: rewrite stock reports queries in qb
2022-10-28 21:05:15 +05:30
Deepesh Garg
323e45374f Merge pull request #32620 from rtdany10/psa_pdf_issue
feat: page break in SoA pdf
2022-10-28 21:00:01 +05:30
Deepesh Garg
aee4fe9f7b Merge pull request #32722 from deepeshgarg007/reference_due_date
fix: Reference due date field type in Journal Entry Accounts table
2022-10-28 20:55:36 +05:30
Deepesh Garg
50652be6e3 Merge branch 'develop' of https://github.com/frappe/erpnext into editable_inovice 2022-10-28 20:48:26 +05:30
Deepesh Garg
92f2d9f99f Merge pull request #32725 from ernestoruiz89/patch-10
fix: add translate function on remark text on  asset_value_adjustment.py
2022-10-28 20:47:00 +05:30
Deepesh Garg
25eac80ae6 Merge pull request #32718 from deepeshgarg007/total_sales_amount_project
fix: Total Sales amount update in project via Sales Order
2022-10-28 20:46:00 +05:30
Deepesh Garg
9ac1c4bc4f Merge pull request #32699 from deepeshgarg007/general_ledeger_print
fix: Curreny in SOA print for multi-currency party
2022-10-28 20:41:49 +05:30
Deepesh Garg
c3275c3f3c Merge pull request #32692 from deepeshgarg007/opening_invoice_creation_tool_ux
fix: Clear invoice table post importing invoices
2022-10-28 20:40:52 +05:30
Deepesh Garg
d9eda45b0b chore: Minor updates 2022-10-28 20:19:13 +05:30
Deepesh Garg
b9d497c61c chore: Update patch 2022-10-28 20:18:55 +05:30
ruthra kumar
fed39a53cb test: due date filter on Payment Terms report 2022-10-28 18:15:58 +05:30
ruthra kumar
4765f937ea fix: key error in filter access 2022-10-28 17:50:01 +05:30
ruthra kumar
aadb6b1772 feat: additional filters on Payment terms report
Filter on Status and Due dates
2022-10-28 17:46:06 +05:30
Deepesh Garg
fb41bdd700 Merge branch 'develop' of https://github.com/frappe/erpnext into tds_purchase_invoice 2022-10-28 17:18:11 +05:30
Sagar Sharma
c71f805667 Merge pull request #32738 from vishdha/pr_dashboard
fix: Added Material Request Reference in Purchase Recipt Dashboard for Tracking
2022-10-28 14:23:54 +05:30
Vishal Dhayagude
db0f2c0b10 Merge branch 'develop' into pr_dashboard 2022-10-28 13:36:43 +05:30
Deepesh Garg
09fa2298ba Merge pull request #32716 from deepeshgarg007/bank_account_filter
fix: Company bank account filter in Bank Clearance
2022-10-28 12:53:53 +05:30
Vishal
e8c0157017 chore: minor linting issue fixed 2022-10-28 11:59:10 +05:30
Vishal
a04c44fe34 chore: Added Material Request Reference in Purchase Recipt Dashboard for Tracking 2022-10-28 11:36:14 +05:30
Sagar Sharma
334b158f0b Merge branch 'develop' into refactor/stock/remaining-reports 2022-10-28 11:27:42 +05:30
Deepesh Garg
16959c0a8c Merge pull request #32717 from deepeshgarg007/discount_section_collapse
fix: Add condition for discount section collapse
2022-10-28 11:24:25 +05:30
Deepesh Garg
591291caee Merge pull request #32724 from deepeshgarg007/ap_report_filter_fixes
fix: Filter fixes in Accounts Payable report
2022-10-28 11:23:52 +05:30
Dany Robert
de20dfe459 chore: remove commented line 2022-10-27 09:33:49 +05:30
Ernesto Ruiz
8f0e63cd27 fix: add translate function on remark text on make_depreciation_entry in asset_value_adjustment.py 2022-10-26 13:56:35 -06:00
Deepesh Garg
a5a73ba857 fix: Filter fixes in Accounts Payable report 2022-10-26 21:18:50 +05:30
Deepesh Garg
e7caa48e2f fix: Reference due date field type in Journal Entry Accounts table 2022-10-26 20:21:36 +05:30
Deepesh Garg
6063c4e3c0 fix: Total Sales amount update in project via Sales Order 2022-10-26 18:01:39 +05:30
Deepesh Garg
4cd65027c4 fix: Add condition for discount section collapse 2022-10-26 16:48:24 +05:30
Deepesh Garg
f9f78c1086 fix: Company bank account filter in Bank Clearance 2022-10-26 11:02:14 +05:30
Ernesto Ruiz
4c7fa9482d fix: correct linters 2022-10-25 22:39:05 -06:00
Ernesto Ruiz
9c529c61bb fix: correct linters 2022-10-25 22:35:37 -06:00
Ernesto Ruiz
b7b53b5857 fix: correct linters 2022-10-25 22:34:21 -06:00
Ernesto Ruiz
2012bdf4bd fix: add translate function to string on budget_variance_report.js to match the variance word translated 2022-10-25 22:24:33 -06:00
Ernesto Ruiz
48ed6381b3 fix: add translate function to name of chart labels in budget_variance_report.py 2022-10-25 22:18:47 -06:00
Ernesto Ruiz
083a78135c fix: add translate function to period in sales_analytics.py 2022-10-25 22:17:06 -06:00
Ernesto Ruiz
c1e608d9ef fix: add translate function to period in stock_analytics.py 2022-10-25 22:09:02 -06:00
Ernesto Ruiz
71a0ae2e59 fix: refactor code for better translatable string in stock_ageing.py 2022-10-25 22:05:25 -06:00
Ernesto Ruiz
a671652ab2 fix: refactor code for better translatable string 2022-10-25 22:00:46 -06:00
Ernesto Ruiz
a963618b08 fix: add translate function to name of chart labels in deferred_revenue_and_expense.py 2022-10-25 21:54:55 -06:00
niralisatapara
397e3b1ade feat: item wise tds calculation
item wise tds calculation
2022-10-25 15:09:59 +05:30
Deepesh Garg
a18a715bb4 chore: Use account currency as fallback 2022-10-24 19:13:02 +05:30
Deepesh Garg
49ee873655 fix: Curreny in SOA print for multi-currency party 2022-10-24 17:34:12 +05:30
rohitwaghchaure
183662c0e2 Merge pull request #32693 from rohitwaghchaure/searchfield-not-working-for-customer-supplier
fix: Search field not working for customer, supplier
2022-10-24 17:11:27 +05:30
Rohit Waghchaure
5f84993bae test: added test case to validate seachfields for customer, supplier 2022-10-24 16:10:47 +05:30
Rohit Waghchaure
46d148defd fix: searchfield not working for cuctsomer, supplier as per customize form 2022-10-24 15:48:34 +05:30
Deepesh Garg
267e7c3a90 fix: Clear invoice table post importing invoices 2022-10-24 11:45:24 +05:30
Deepesh Garg
1a980123a2 chore: Update tests 2022-10-24 10:08:55 +05:30
Deepesh Garg
ed98015a56 test: Add unit tests 2022-10-23 23:03:50 +05:30
Deepesh Garg
1105e52031 chore: Update allow on submit fields 2022-10-23 22:55:08 +05:30
Deepesh Garg
48808aeb8a Merge pull request #32424 from deepeshgarg007/loan_schedule_types
feat: Repayment schedule types for term loans
2022-10-23 19:37:40 +05:30
Deepesh Garg
e59b147a62 chore: Update tests 2022-10-23 18:51:51 +05:30
Deepesh Garg
77d509eb9a Merge pull request #32650 from barredterra/unset-contact-details
fix: unset contact details
2022-10-23 18:21:01 +05:30
Deepesh Garg
ef0cb17faf chore: Add repayment date on option 2022-10-22 23:46:01 +05:30
Sagar Sharma
26c00f8dd3 Merge branch 'develop' into refactor/stock/remaining-reports 2022-10-21 15:19:23 +05:30
Sagar Sharma
40bd121593 refactor: rewrite Itemwise Recommended Reorder Level Report queries in QB 2022-10-21 14:49:12 +05:30
Sagar Sharma
cde785f1bb refactor: rewrite Product Bundle Balance Report queries in QB 2022-10-21 14:49:09 +05:30
Sagar Sharma
feaa2dbba8 refactor: rewrite Stock Ledger Report queries in QB 2022-10-21 13:12:34 +05:30
ruthra kumar
eedf7e44a2 Merge pull request #32651 from ruthra-kumar/report_payment_ledger
feat: Payment Ledger report
2022-10-21 11:25:24 +05:30
Deepesh Garg
51d8e9dc5e Merge branch 'develop' of https://github.com/frappe/erpnext into loan_schedule_types 2022-10-20 18:35:16 +05:30
Deepesh Garg
2a50a0ce69 Merge pull request #32551 from codezart/subscription-plan-fix-months
fix: number of months subscription plan
2022-10-20 17:24:24 +05:30
Ankush Menat
11207c4e56 fix: dont update item info twice
[skip ci]
2022-10-20 16:18:48 +05:30
Devin Slauenwhite
b88e850d55 perf: cache barcode scan result (#32629)
* perf: cache barcode scan result

* feat: BarcodeScanResult type

* fix: use safe `get_value` `set_value`

Co-authored-by: Ankush Menat <ankushmenat@gmail.com>
2022-10-20 15:56:07 +05:30
rohitwaghchaure
adeb1f92c8 Merge pull request #32667 from rohitwaghchaure/fixed-bom-cost-update-message
fix: BOM cost update message
2022-10-20 14:36:43 +05:30
Rohit Waghchaure
9cfe527492 fix: BOM cost update message 2022-10-20 13:49:46 +05:30
Deepesh Garg
1ca472cc8a chore: Linting issues 2022-10-20 12:09:42 +05:30
Deepesh Garg
b4d008b743 Merge branch 'develop' into subscription-plan-fix-months 2022-10-20 12:07:44 +05:30
Deepesh Garg
ae54610b2a Merge pull request #32659 from deepeshgarg007/inter_company_purchase_doc_address
fix: Billing Address for inter-company purchase docs
2022-10-20 11:58:53 +05:30
rohitwaghchaure
873502c95d Merge pull request #32654 from rohitwaghchaure/fixed-conversion-issue-in-material-request
fix: incorrect qty in material request created from PP
2022-10-20 09:59:19 +05:30
Deepesh Garg
796f2d3c09 fix: Billing Address for inter-company purchase docs 2022-10-19 23:50:39 +05:30
FinByz Tech Pvt. Ltd
c52b41d311 feat(report): added account wise redirection
* feat(report):added account wise redirection

Co-authored-by: Deepesh Garg <deepeshgarg6@gmail.com>
2022-10-19 23:14:10 +05:30
Raffael Meyer
4ad3002861 fix: allow to create Sales Order from expired Quotation (#32641) 2022-10-19 22:07:02 +05:30
ruthra kumar
6e55b419a6 test: invoice outstandings and payments 2022-10-19 21:49:13 +05:30
ruthra kumar
8f60f0a0cf feat: Basic Payment Ledger report 2022-10-19 21:49:08 +05:30
Rohit Waghchaure
4d5ef721f7 test: validate qty and purchase uom in material request which is created from PP 2022-10-19 19:08:27 +05:30
Rohit Waghchaure
ad278b2007 fix: incorrect qty in material request 2022-10-19 18:38:34 +05:30
rohitwaghchaure
de4c0528f9 Merge pull request #32645 from rohitwaghchaure/fixed-capacity-planning-error
fix: overlap error not raised for job card in case of workstation with production capacity
2022-10-19 17:04:48 +05:30
barredterra
23f0bb45b0 fix: unset contact details 2022-10-19 12:26:56 +02:00
Deepesh Garg
430492152f fix: Advance paid amount in orders (#32642) 2022-10-19 15:37:13 +05:30
niralisatapara
4a35a224e2 feat: Item Wise TDS Calculation 2022-10-19 15:34:41 +05:30
niralisatapara
21d09c5bf2 Item Wise TDS Calculation 2022-10-19 14:33:02 +05:30
Rohit Waghchaure
8b2165e0d1 fix: overlap error not raised for job card in case of workstation with production capacity 2022-10-19 14:19:50 +05:30
Maharshi Patel
d100e68fd0 Merge branch 'frappe:develop' into fix-pricing-rule-item-group-uom 2022-10-19 11:08:05 +05:30
ruthra kumar
f844097f8e Merge pull request #32635 from ruthra-kumar/fix_tax_or_charges_acc_updating_voucher_outstanding
fix: Integrity Error on PLE while submitting sales invoice
2022-10-19 09:43:24 +05:30
Maharshi Patel
96b4211ea1 fix: pricing rule for non stock UOM and conversions
* fix: pricing rule for non stock UOM and conversions
2022-10-18 22:26:11 +05:30
ruthra kumar
8f42e7f703 test: use payable account in tax and to trigger party validation 2022-10-18 17:27:46 +05:30
rohitwaghchaure
f08c42e920 Merge pull request #32520 from s-aga-r/refactor/stock/reports
refactor: rewrite stock reports queries in qb
2022-10-18 13:48:15 +05:30
Sagar Sharma
ae8a63827d Merge branch 'develop' into refactor/stock/reports 2022-10-18 10:48:52 +05:30
Deepesh Garg
7184330acd Merge pull request #32527 from s-aga-r/refactor/buying/reports
refactor: rewrite buying reports queries in qb
2022-10-18 10:06:10 +05:30
ruthra kumar
43b80683eb fix: party type and party mandatory on updating outstanding 2022-10-18 09:33:37 +05:30
Deepesh Garg
42e4c37f15 chore: Break into smaller functions 2022-10-17 20:09:07 +05:30
Deepesh Garg
32117c030a Merge pull request #32622 from deepeshgarg007/ignore_pi_reference
fix: Ignore linked purchase invoice on cancel
2022-10-17 19:38:26 +05:30
Dany Robert
9df9915600 fix: query condition change 2022-10-17 15:54:46 +02:00
Deepesh Garg
faadf78332 fix: Ignore linked purchase invoice on cancel 2022-10-17 18:50:54 +05:30
ruthra kumar
aab325eca5 Merge pull request #32598 from ruthra-kumar/refactor_create_payment_ledger_function
refactor: split ple creation function into two
2022-10-17 18:44:36 +05:30
ruthra kumar
9b50221bf0 refactor: split ple creation function into two
refactor create_payment_ledger_entry function into 2.
one for generating ple map and one for DB entry creation
2022-10-17 18:02:52 +05:30
Dany Robert
2665d7d293 feat: page break in SoA pdf 2022-10-17 14:29:03 +02:00
Deepesh Garg
98b695984b Merge branch 'develop' into refactor/buying/reports 2022-10-17 17:15:27 +05:30
Deepesh Garg
8b16ba7f3a Merge branch 'develop' into refactor/stock/reports 2022-10-17 17:15:18 +05:30
Deepesh Garg
d794b834fd Merge pull request #32618 from ruthra-kumar/fix_failing_github_unit_test_workflow
test: lead creation and deletion restricted to dummy company
2022-10-17 17:11:51 +05:30
Deepesh Garg
e626107d3d chore: Update allow on submit for Sales Invoice fields 2022-10-17 16:48:13 +05:30
Sagar Sharma
582e1bf10c Merge branch 'develop' into refactor/stock/reports 2022-10-17 16:30:43 +05:30
ruthra kumar
ced8d2a537 test: lead creation and deletion restricted to dummy company 2022-10-17 16:26:07 +05:30
Sagar Sharma
cda0baa7fe Merge branch 'develop' into refactor/buying/reports 2022-10-17 16:10:52 +05:30
rohitwaghchaure
0f358e3ca1 Merge pull request #32613 from rohitwaghchaure/group-warehouse-filter
fix: group warehouse filter not working for Batch-wise Balance history report
2022-10-17 15:12:42 +05:30
Rohit Waghchaure
2481574a28 chore: seperate function to apply filter for warehouse in case of QB 2022-10-17 14:25:23 +05:30
Rohit Waghchaure
6381e75fa5 fix: group warehouse filter not working for Batchwise Balance history report 2022-10-17 12:17:05 +05:30
Sagar Sharma
484b115b09 Merge branch 'develop' into refactor/stock/reports 2022-10-17 12:08:44 +05:30
Sagar Sharma
309fc6db43 Merge branch 'develop' into refactor/buying/reports 2022-10-17 12:08:37 +05:30
Deepesh Garg
dc3fe85921 chore: Remove HRMS related code (#32607)
Co-authored-by: Rucha Mahabal <ruchamahabal2@gmail.com>
2022-10-17 11:37:50 +05:30
Deepesh Garg
30da6ab2c1 feat: Editable Sales Invoice 2022-10-17 11:10:38 +05:30
Sagar Sharma
682fb171cb Merge branch 'develop' into refactor/buying/reports 2022-10-16 11:50:31 +05:30
Sagar Sharma
177c9c93e8 Merge branch 'develop' into refactor/stock/reports 2022-10-16 11:50:26 +05:30
Deepesh Garg
40b3d8ec1b Merge pull request #32591 from nabinhait/crm-notes-to-comments
fix: Renamed Notes section to Comments
2022-10-15 17:42:45 +05:30
Deepesh Garg
fc795275f2 Merge pull request #32594 from deepeshgarg007/order_account
fix: Party account for multi-order invoices
2022-10-15 16:58:51 +05:30
Sagar Sharma
5f3796f6ea Merge branch 'develop' into refactor/buying/reports 2022-10-14 11:57:11 +05:30
Sagar Sharma
3c1bd90d0d Merge branch 'develop' into refactor/stock/reports 2022-10-14 11:57:04 +05:30
Anand Baburajan
9127b96033 fix: add project settings to projects workspace (#32568) 2022-10-13 18:27:11 +05:30
Ankush Menat
50e9698932 chore: drop dead code (#32595)
[skip ci]
2022-10-13 15:25:22 +05:30
Deepesh Garg
fd49503ba2 fix: Party account for multi-order invoices 2022-10-13 15:08:34 +05:30
ruthra kumar
2d0217abd5 Merge pull request #32567 from ruthra-kumar/remove_duplicate_ple_on_item_value_repost
fix: deduplicate Payment Ledger on Item value repost
2022-10-13 14:01:59 +05:30
Nabin Hait
f561d8f689 fix: Renamed Dashboard tab label to Connections 2022-10-13 12:43:08 +05:30
Nabin Hait
56a4a77398 fix: Renamed Notes section to Comments 2022-10-13 12:35:04 +05:30
Maharshi Patel
edc93ab6aa fix: pricing rule item group uom
Handle use case where pricing rule is applied on item group and user have selected UOM. pricing rule was applied on all UOM's even after specifying UOM. i have added condition in sql to fix this.
2022-10-13 12:00:30 +05:30
Raffael Meyer
e543dca6a0 fix: don't try to update youtube data if disabled in settings (#32588)
fix: cast value from db

[skip ci]
2022-10-13 11:53:52 +05:30
Sagar Sharma
d6c28aa64d Merge pull request #32576 from s-aga-r/fix/github-issue/32559
fix: `Brand Defaults` filters
2022-10-12 19:22:47 +05:30
Sagar Sharma
bb7897caab Merge branch 'develop' into refactor/stock/reports 2022-10-12 19:21:15 +05:30
Sagar Sharma
610d18cc25 Merge branch 'develop' into refactor/buying/reports 2022-10-12 19:21:10 +05:30
Sagar Sharma
7dfd741ced Merge branch 'develop' into fix/github-issue/32559 2022-10-12 19:20:39 +05:30
rohitwaghchaure
e583d17062 Merge pull request #32583 from rohitwaghchaure/removed-unnecessary-imports
fix: removed unnecessary imports
2022-10-12 17:09:08 +05:30
Rohit Waghchaure
692462d7c8 fix: removed unnecessary imports 2022-10-12 16:30:48 +05:30
Deepesh Garg
43c2bd1351 Merge pull request #32272 from deepeshgarg007/internal_transfer_precision_fixes
fix: Incoming rate precision fixes for intra company transfer
2022-10-12 16:23:16 +05:30
Deepesh Garg
ab137472b0 Merge pull request #32563 from rohitwaghchaure/fixed-source-stock-reposting-for-purchase-flow
fix: consider sales rate as incoming rate for transit warehouse in purchase flow
2022-10-12 16:20:12 +05:30
ruthra kumar
eb819368aa test: dedeplication on payment ledger upon repost 2022-10-12 16:08:59 +05:30
Deepesh Garg
9aa5e20ef7 chore: check only for inter-company transfers 2022-10-12 15:53:28 +05:30
Rohit Waghchaure
98bf8e1304 fix: test case 2022-10-12 15:45:36 +05:30
Rohit Waghchaure
3266e54e33 fix: consider outgoingrate while valuation rate calculate 2022-10-12 15:44:53 +05:30
Rohit Waghchaure
683a47f7a1 fix: consider sales rate as incoming rate for transit warehouse in purchase flow 2022-10-12 15:44:53 +05:30
ruthra kumar
65992304bc fix: delete old ple's on item value repost 2022-10-12 15:34:50 +05:30
Deepesh Garg
49601558c6 chore: fix precision condition 2022-10-12 14:57:16 +05:30
Deepesh Garg
1c05c004cd chore: Use proper accounts 2022-10-12 14:19:09 +05:30
Deepesh Garg
c8d2181498 chore: Increase precision for other doc fields 2022-10-12 14:17:55 +05:30
Sagar Sharma
59edf64951 Merge branch 'develop' into refactor/stock/reports 2022-10-12 13:30:00 +05:30
Sagar Sharma
0af385d73f Merge branch 'develop' into refactor/buying/reports 2022-10-12 13:29:50 +05:30
Sagar Sharma
d2755c0106 Merge branch 'develop' into fix/github-issue/32559 2022-10-12 13:28:35 +05:30
Rohan
43037d893d fix: type-cast while saving an item (#32549) 2022-10-12 13:07:58 +05:30
Sagar Sharma
3426d91140 Merge branch 'develop' into refactor/stock/reports 2022-10-12 12:17:53 +05:30
Sagar Sharma
ef60c533a0 Merge branch 'develop' into refactor/buying/reports 2022-10-12 12:17:48 +05:30
Sagar Sharma
7da32c7db3 fix: Brand Defaults filters 2022-10-12 12:15:07 +05:30
Ankush Menat
6ce3ce758c ci: disable orchestrator (#32571) 2022-10-12 10:57:58 +05:30
Sagar Sharma
16aef53470 Merge branch 'develop' into refactor/stock/reports 2022-10-12 00:38:40 +05:30
Sagar Sharma
a161048a9d Merge branch 'develop' into refactor/buying/reports 2022-10-12 00:38:37 +05:30
Deepesh Garg
38b34f2a45 Merge pull request #32408 from nabinhait/sales-purchase-tab-break
feat: Tab Breaks in all Sales and Purchase cycle transactions
2022-10-11 16:02:45 +05:30
Deepesh Garg
df2a0e265b chore: GL Entries for SLE diff 2022-10-11 14:55:09 +05:30
Deepesh Garg
dc20b21fb5 test: Internal tranfer precision loss test 2022-10-11 14:54:27 +05:30
Deepesh Garg
b31c3bd35d chore: Increase incoming_rate field precision to 6 2022-10-11 14:53:26 +05:30
ruthra kumar
633c2a289e Merge pull request #32557 from ruthra-kumar/value_error_on_pos_save
fix: Value error on validation of POS invoices with Serial Nos
2022-10-11 14:42:47 +05:30
Nabin Hait
e71c417f7e fix: minor cleanup 2022-10-11 13:21:27 +05:30
Nabin Hait
5389a35798 fix: more fields reordering related to Tab Break 2022-10-11 13:21:07 +05:30
Nabin Hait
aaf3c2b329 feat: Tab Break in Purchase Invoice 2022-10-11 13:20:41 +05:30
Nabin Hait
35f836c4b7 feat: Tab Break in Purchase Receipt 2022-10-11 13:18:21 +05:30
Nabin Hait
3d9263bf86 feat: Tab Break in Supplier Quotation 2022-10-11 13:18:21 +05:30
Nabin Hait
2172c5034a feat: Tab Break in Material Request 2022-10-11 13:18:21 +05:30
Nabin Hait
10a25603ac feat: Tab Break in Purchase Order 2022-10-11 13:18:21 +05:30
Nabin Hait
7546562139 feat: Tab Break in Quotation 2022-10-11 13:18:21 +05:30
Nabin Hait
f6613e1e4c feat: Tab Break in Sales Order, Delivery Note, Sales Invoice and Purchase Order 2022-10-11 13:18:21 +05:30
ruthra kumar
9e2bd10d03 test: value error on serial no validation on pos 2022-10-11 12:54:50 +05:30
Deepesh Garg
dddbc130db Merge branch 'develop' of https://github.com/frappe/erpnext into internal_transfer_precision_fixes 2022-10-11 12:54:11 +05:30
ruthra kumar
4b908ebcd6 fix: value error on pos submit 2022-10-11 11:21:11 +05:30
Deepesh Garg
b99b2b75ca Merge pull request #32477 from rasos/patch-1
Austria chart of accounts update
2022-10-11 10:20:49 +05:30
Deepesh Garg
6a2edab6eb Merge pull request #32554 from AnandBaburajan/fix_budget_autoname
fix: use naming_series in budget
2022-10-11 10:15:17 +05:30
Anand Baburajan
ba754825b9 Merge branch 'develop' into fix_budget_autoname 2022-10-10 23:17:18 +05:30
anandbaburajan
e4d7d8c42d fix: use naming_series in budget 2022-10-10 23:04:34 +05:30
codezart
2d30b36cca fix: number of months subscription plan 2022-10-10 11:24:42 -04:00
ruthra kumar
65194efa97 Merge pull request #32548 from ruthra-kumar/suppress_linked_doc_valdiation_on_delete
fix: allow deletion of cancelled Invoices once payments are unlinked
2022-10-10 16:41:07 +05:30
ruthra kumar
143f905838 test: update ple on payment unlink for SI's and SO's 2022-10-10 15:57:38 +05:30
Deepesh Garg
a14c5dbcc4 Merge branch 'develop' of https://github.com/frappe/erpnext into internal_transfer_precision_fixes 2022-10-10 15:08:15 +05:30
rohitwaghchaure
be1ebd348b Merge pull request #32497 from s-aga-r/fix/quality-inspection/status
chore: set `Quality Inspection` status based on readings status
2022-10-10 10:49:56 +05:30
ruthra kumar
537d953f4c fix: unlink payment on invoice cancellation 2022-10-10 10:17:19 +05:30
Deepesh Garg
0f033bf8f6 Merge pull request #32536 from deepeshgarg007/po_cancel
fix: PO cancel post advance payment cancel against PO
2022-10-09 18:34:55 +05:30
Deepesh Garg
d806e32030 fix: PO cancel post advance payment cancel against PO 2022-10-08 21:25:11 +05:30
Deepesh Garg
4b828dd276 Merge branch 'develop' of https://github.com/frappe/erpnext into loan_schedule_types 2022-10-08 18:41:39 +05:30
Sagar Sharma
60befcd8a8 Merge branch 'develop' into fix/quality-inspection/status 2022-10-08 13:34:21 +05:30
Sagar Sharma
4992e4a2b8 fix(test): test_rejected_qi_validation 2022-10-08 13:33:36 +05:30
Sagar Sharma
fcc1272d42 test: add test cases for Quality Inspection status 2022-10-08 13:33:36 +05:30
Sagar Sharma
2657ece2cd fix: set Quality Inspection status based on readings status 2022-10-08 13:33:22 +05:30
Sagar Sharma
ce20b05ed0 Merge branch 'develop' into refactor/buying/reports 2022-10-08 10:48:03 +05:30
Sagar Sharma
e78a706994 refactor: rewrite Procurement Tracker Report queries in QB 2022-10-08 10:47:10 +05:30
rohitwaghchaure
ce5a792e34 Merge pull request #32393 from rohitwaghchaure/provision-to-return-components
feat: provision to return non consumed components against the work order
2022-10-08 08:24:36 +05:30
rohitwaghchaure
73a9791401 Merge branch 'develop' into provision-to-return-components 2022-10-07 23:50:05 +05:30
Rohit Waghchaure
d59ed24e6c feat: provision to return non consumed components against the work order 2022-10-07 22:45:53 +05:30
Sagar Sharma
a14b9c7bac refactor: rewrite Supplier Quotation Comparison Report queries in QB 2022-10-07 18:07:53 +05:30
Sagar Sharma
a5b3f8cae9 refactor: rewrite Purchase Order Analysis Report queries in QB 2022-10-07 17:30:01 +05:30
Deepesh Garg
17201facf1 Merge pull request #32522 from deepeshgarg007/tax_withholding_related_fixes
fix: Tax withholding related fixes
2022-10-07 16:32:18 +05:30
Deepesh Garg
781d160c68 fix: Do not add tax withheld vouchers post tax withheding in one document 2022-10-07 14:22:40 +05:30
Deepesh Garg
abf5b6be3e fix: Tax withholding related fixes 2022-10-07 14:04:36 +05:30
Sagar Sharma
f0f2413932 Merge branch 'develop' into refactor/stock/reports 2022-10-07 09:59:56 +05:30
Sagar Sharma
8103856a41 refactor: rewrite Warehouse wise Item Balance Age and Value Report queries in QB 2022-10-07 09:59:35 +05:30
Sagar Sharma
7c759b193c refactor: rewrite Total Stock Summary Report queries in QB 2022-10-07 09:59:28 +05:30
Sagar Sharma
d7c3b7633a fix: make readings status mandatory in Quality Inspection 2022-10-06 22:36:37 +05:30
Ankush Menat
8376fbc982 fix: Explicitly update modified (#32519)
* fix: Explicitly update modified

required after https://github.com/frappe/frappe/pull/18301

* chore: fix broken translations
2022-10-06 20:35:33 +05:30
Sagar Sharma
d3c073dc25 refactor: rewrite Supplier-Wise Sales Analytics Report queries in QB 2022-10-06 17:42:31 +05:30
Sagar Sharma
c18f13a45b refactor: rewrite Stock Projected Qty Report queries in QB 2022-10-06 17:04:50 +05:30
Ankush Menat
07c4a74838 chore: drop stale demo page (#32515) 2022-10-06 13:01:53 +05:30
Ankush Menat
8d1db0ea3d fix: single column indexes (#32425)
refactor: move single column indexes to doctypes
2022-10-06 11:28:26 +05:30
HENRY Florian
0e4017cbe5 chore: update fr translation (#32385) 2022-10-05 18:19:44 +05:30
Deepesh Garg
0235901614 Merge pull request #32478 from rtdany10/patch-23
feat(JE): trigger account field when fetched from template
2022-10-05 16:07:59 +05:30
Deepesh Garg
fbdd1f39e7 Merge pull request #32499 from rohitwaghchaure/fixed-TooManyWritesError-for-reposting
fix: TooManyWritesError during reposting of stock
2022-10-05 16:05:12 +05:30
Deepesh Garg
777ed10e21 Merge pull request #32491 from ruthra-kumar/performance_issue_on_migrate_remarks_patch
refactor: remove duplicate entries on remarks migration patch
2022-10-05 16:04:23 +05:30
Rohit Waghchaure
aaabba9b1e fix: TooManyWritesError during reposting of stock 2022-10-05 10:58:21 +05:30
Sagar Sharma
39707757a6 chore: add Manual Inspection field in Quality Inspection DocType 2022-10-04 23:16:16 +05:30
Dany Robert
74505a116f Merge branch 'develop' into patch-23 2022-10-04 17:17:30 +05:30
ruthra kumar
518ab93e03 refactor: remove duplicate entries on remarks migration patch 2022-10-04 12:39:34 +05:30
Summayya Hashmani
da43a5e371 refactor(UI): clean up portal pages (#29018)
* refactor: list view for portal pages

* refactor: add align center class

* refactor: change footer btn class(primary)

* refactor: add order style page

* refactor: import order page in website

* refactor: remove table elements

* fix: preview image height

* fix: make string translatable

* refactor: change font variables

* refactor: order preview bg white

* refactor: center align items

* fix: breadcrumb padding

* refactor: make preview image rounded

* refactor: add condition for image container

* refactor: change alignment for mobile view

* fix: make footer button secondary

* refactor: clean code

* refactor: code indentantion

* refactor: remove space

* fix: Payment section cleanup

Co-authored-by: Summayya <frappe@Summayyas-MacBook-Air.local>
Co-authored-by: Marica <maricadsouza221197@gmail.com>
Co-authored-by: Deepesh Garg <deepeshgarg6@gmail.com>
2022-10-04 09:57:07 +05:30
Dany Robert
c35adcf5a1 feat(JE): trigger account field when fetched from template
Closes #32409
2022-10-03 19:31:20 +05:30
Roland
7d84cca431 Austria chart of accounts update
improved mapping of VAT accounts
2022-10-03 14:13:27 +02:00
niralisatapara
e758a753f8 Item Wise TDS Calculation
For calculating Item wise TDS in Purchase Invoice.
2022-10-03 16:39:35 +05:30
Sagar Sharma
ccf2952b76 Merge pull request #32472 from s-aga-r/fix/pick-list/picked-qty
fix: pick list picked-qty for batch item
2022-10-03 14:45:29 +05:30
Sagar Sharma
e295d0c091 Merge branch 'develop' into fix/pick-list/picked-qty 2022-10-03 14:20:05 +05:30
Sagar Sharma
ba02209f1d fix: pick list picked-qty for batch item 2022-10-03 14:12:42 +05:30
rohitwaghchaure
1c5ae80029 Merge pull request #32466 from rohitwaghchaure/allow-to-return-expired-batches
fix: not able to return sold expired batches
2022-10-03 13:14:59 +05:30
Deepesh Garg
8c23b19da1 Merge pull request #32394 from maharshivpatel/fix-payment-request-fetch-swift-number
fix: fetch swift number in payment request from bank doctype
2022-10-03 12:55:02 +05:30
Rohit Waghchaure
0b1727cf79 fix: not able to return sold expired batches 2022-10-03 12:06:32 +05:30
Shridhar Patil
69efd2ee24 fix: fixes query builder order by issue in postgres (#32441)
* fix: fixes query builder order by issue in postgres

* fix: linter
2022-10-03 11:07:24 +05:30
Dany Robert
91055151ce fix: (bulk transaction) key error and better error logging (#32445)
* fix: (bulk transaction) key error and better error logging

* chore: pre-commit

* chore: linter - missing comma
2022-10-03 10:59:53 +05:30
Muvuk
73e5a7d671 fix: update with new Frappe color. fix #32455 (#32456)
* Update with new Frappe color.

* refactor: use css variables

Co-authored-by: Ankush Menat <ankushmenat@gmail.com>
2022-10-02 22:30:36 +05:30
Deepesh Garg
601880f1ce Merge pull request #32454 from AnandBaburajan/fix_test_scrap_asset
fix: test_scrap_asset not working on end of month
2022-10-02 17:44:46 +05:30
Deepesh Garg
28772bc9a4 Merge pull request #32405 from AnandBaburajan/fix_asset_sold_status
fix: status of assets with maintenance_required changing back to 'Partially Depreciated' some time after being sold
2022-10-02 17:41:31 +05:30
Anand Baburajan
04f9e7fa73 Merge branch 'develop' into fix_test_scrap_asset 2022-10-01 17:12:24 +05:30
anandbaburajan
47bd4be71b fix: test_scrap_asset 2022-10-01 17:04:22 +05:30
Deepesh Garg
1c560a967c Merge branch 'develop' into fix-payment-request-fetch-swift-number 2022-10-01 16:14:27 +05:30
Maharshi Patel
62c5b28690 fix: typo in sales_register's filter mode_of_payment (#32371)
* fix: typo in sales_register's filter mode_of_payment
2022-10-01 11:04:53 +05:30
Sagar Sharma
c9275f156e Merge pull request #32439 from s-aga-r/purchase-order/item/fg-item
fix: add non-stock item filter for `fg_item` in PO
2022-09-30 23:59:12 +05:30
Sagar Sharma
e71b25107d Merge branch 'develop' into purchase-order/item/fg-item 2022-09-30 19:10:07 +05:30
Sagar Sharma
793295cfe9 Merge pull request #32428 from s-aga-r/fix/item/update-stock
fix: don't allow to update `Maintain Stock` if the item has a `BOM`
2022-09-30 19:08:19 +05:30
Sagar Sharma
128c4bb7cb Merge branch 'develop' into purchase-order/item/fg-item 2022-09-30 17:06:35 +05:30
Sagar Sharma
f95ed7dca2 fix: add non-stock item filter for fg_item in PO 2022-09-30 17:05:16 +05:30
Sagar Sharma
1f4e4db50d Merge branch 'develop' into fix/item/update-stock 2022-09-30 16:55:26 +05:30
Sagar Sharma
c7d808a560 Merge pull request #32436 from s-aga-r/fix/scr/non-stock-item
fix: add validation for non-stock item in SCR
2022-09-30 16:53:07 +05:30
Sagar Sharma
ca2958a999 Merge branch 'develop' into fix/item/update-stock 2022-09-30 16:36:46 +05:30
Maharshi Patel
dc8d49260c fix: payment request make bank field Link instead of Read Only 2022-09-30 16:22:57 +05:30
Sagar Sharma
eedaf9cd26 Merge branch 'develop' into fix/scr/non-stock-item 2022-09-30 16:19:23 +05:30
Sagar Sharma
fa2290657a fix: add validation for non-stock item in SCR 2022-09-30 16:18:15 +05:30
Deepesh Garg
cceb29c005 Merge pull request #32412 from deepeshgarg007/tcs_deduction_issue
fix: Incorrect TCS amount deducted in Sales Invoice
2022-09-30 16:05:30 +05:30
Deepesh Garg
a79d074436 Merge pull request #32368 from ruthra-kumar/remove_code_for_buying_side_discount_accounting
chore: remove discount accounting logic from PI and PI Item
2022-09-30 15:58:35 +05:30
Deepesh Garg
429303bbb7 Merge pull request #32402 from deepeshgarg007/item_dashboard_create_new
fix: Item details fetching on making transaction from item dashboard
2022-09-30 15:56:32 +05:30
Nabin Hait
fe891aa488 fix: Create accounting dimension fields in asset capitalization 2022-09-30 15:55:41 +05:30
Maharshi Patel
9245d3b5cd Revert "fix: fetch swift_number in payment_request"
This reverts commit f42a8e4e03.
2022-09-30 15:35:12 +05:30
Deepesh Garg
bf7a51791a chore: label post save 2022-09-30 15:29:07 +05:30
Sagar Sharma
6d0842465b fix: don't allow to update Maintain Stock if the item has a BOM 2022-09-30 15:18:10 +05:30
Deepesh Garg
679b5ed551 chore: Add patch to update repayment schedule type in loan documents 2022-09-30 14:06:06 +05:30
Sagar Sharma
b1edd911f9 Merge branch 'develop' into remove_code_for_buying_side_discount_accounting 2022-09-30 12:39:29 +05:30
Sagar Sharma
774097bd10 Merge branch 'develop' into item_dashboard_create_new 2022-09-30 12:37:58 +05:30
Deepesh Garg
2ddee50f27 chore: Update labels as per repayment type 2022-09-30 10:39:45 +05:30
Deepesh Garg
3466461eb3 chore: Remove print statements 2022-09-30 10:19:58 +05:30
Deepesh Garg
76c6ccab5d feat: Repayment schedule types for term loans 2022-09-30 10:13:17 +05:30
anandbaburajan
eadcd8e614 Merge branch 'fix_asset_sold_status' of https://github.com/AnandBaburajan/erpnext into fix_asset_sold_status 2022-09-29 15:34:48 +05:30
anandbaburajan
28952eda87 chore: remove unused function 2022-09-29 15:33:45 +05:30
Anand Baburajan
990514ae6d Merge branch 'develop' into fix_asset_sold_status 2022-09-29 15:32:37 +05:30
anandbaburajan
f1169fb213 chore: refactor by just using a filter 2022-09-29 15:32:01 +05:30
Sagar Sharma
f04ae7a112 Merge pull request #32404 from s-aga-r/fix/supplier-portal/make-pi-btn
fix(ux): show `Make Purchase Invoice` button based on permission
2022-09-29 14:56:02 +05:30
Sagar Sharma
ffef659782 Merge branch 'develop' into fix/supplier-portal/make-pi-btn 2022-09-29 14:54:29 +05:30
rohitwaghchaure
10b7592d14 Merge pull request #32414 from rohitwaghchaure/consider-searchfields-as-per-customize-form
fix: searchfields as per customize form not working for Item
2022-09-29 14:51:55 +05:30
Rohit Waghchaure
3656f7d06f test: added test case 2022-09-29 14:01:51 +05:30
anandbaburajan
469a97ddd2 Merge branch 'fix_asset_sold_status' of https://github.com/AnandBaburajan/erpnext into fix_asset_sold_status 2022-09-29 08:55:30 +05:30
anandbaburajan
0b3b4c99e6 Merge branch 'develop' of https://github.com/frappe/erpnext into fix_asset_sold_status 2022-09-29 08:55:00 +05:30
anandbaburajan
b734f9d237 chore: refactor by creating is_sold 2022-09-29 08:54:35 +05:30
Rohit Waghchaure
fd889fd29a fix: searchfields as per customize form not working for Item 2022-09-28 23:00:45 +05:30
Anand Baburajan
b3c4305fa2 Merge branch 'develop' into fix_asset_sold_status 2022-09-28 21:36:43 +05:30
Deepesh Garg
369a343fb2 Merge pull request #32363 from ernestoruiz89/patch-7
fix: add translate function to strings in www/book appoinment
2022-09-28 20:15:05 +05:30
Deepesh Garg
bff3cd9068 chore: Remove print statements 2022-09-28 20:13:24 +05:30
Deepesh Garg
08443c6421 fix: Incorrect TCS amount deducted in Sales Invoice 2022-09-28 20:11:00 +05:30
Deepesh Garg
84ab5d45fd Merge pull request #32403 from deepeshgarg007/loan_type_patch_fix
fix: Disbursement Account in patch to update old loans
2022-09-28 19:35:42 +05:30
Anand Baburajan
d4242de699 Merge branch 'develop' into fix_asset_sold_status 2022-09-28 18:20:46 +05:30
anandbaburajan
f4bf9c672f chore: rewrite query using frappe.qb 2022-09-28 18:20:20 +05:30
Sagar Sharma
9743add40e Merge pull request #32406 from s-aga-r/fix/stock-entry/supplied-items
fix: supplied items added twice in Stock Entry
2022-09-28 17:50:16 +05:30
Sagar Sharma
a145d1065a Merge branch 'develop' into fix/stock-entry/supplied-items 2022-09-28 16:55:57 +05:30
Sagar Sharma
ac7409bbf3 fix: supplied items added twice in Stock Entry 2022-09-28 16:46:48 +05:30
Anand Baburajan
0618f606b2 Merge branch 'develop' into fix_asset_sold_status 2022-09-28 16:42:21 +05:30
anandbaburajan
a8dd3c3a7c chore: adding missing asset statuses 2022-09-28 16:39:14 +05:30
anandbaburajan
1725672168 chore: adding missing asset statuses 2022-09-28 16:22:35 +05:30
anandbaburajan
f9f68005a5 fix: asset requiring maintenance sold status 2022-09-28 16:21:31 +05:30
Sagar Sharma
e63e017d20 Merge branch 'develop' into fix/supplier-portal/make-pi-btn 2022-09-28 15:46:52 +05:30
Sagar Sharma
80080a3d7b fix: show Make Purchase Invoice button based on permission 2022-09-28 15:40:07 +05:30
Deepesh Garg
be623ce8e8 fix: Disbursement Account in patch to update old loans 2022-09-28 15:36:59 +05:30
Deepesh Garg
0439e41a44 fix: Item details fetching on making transaction from item dashboard 2022-09-28 14:54:53 +05:30
Nabin Hait
dde8b2afff Merge pull request #32226 from AnandBaburajan/fix_asset_scrap_and_sale_dep
fix: calculate depreciation properly on asset sale entry and scrap entry
2022-09-28 14:28:52 +05:30
Maharshi Patel
f42a8e4e03 fix: fetch swift_number in payment_request
There isn't direct link between payment_request and bank so swift_number wasn't fetched using Fetch form. I fixed it by fetching swift_number on_change of bank_account.
2022-09-28 12:54:00 +05:30
Anand Baburajan
c1e3498a2a Merge branch 'develop' into fix_asset_scrap_and_sale_dep 2022-09-28 12:18:38 +05:30
Saqib Ansari
d5359bbdc2 Merge pull request #32379 from maharshivpatel/fix-pos-validate-qty-if-is_stock_item
fix(pos): validate available quantity only if stock item
2022-09-28 12:00:03 +05:30
Deepesh Garg
0c869251ce Merge branch 'develop' into fix_asset_scrap_and_sale_dep 2022-09-28 08:38:52 +05:30
Maharshi Patel
d850b0adb1 Merge branch 'develop' into fix-pos-validate-qty-if-is_stock_item 2022-09-27 23:45:50 +05:30
Maharshi Patel
e392ea1104 fix: POS properly validate stock for bundle products
Stock availability was not calculated properly for Product Bundle with non stock item so i have added logic to properly calculate that as well.
2022-09-27 23:44:56 +05:30
Deepesh Garg
dbe4fdc73d Merge pull request #32382 from deepeshgarg007/subscription_process
fix: Move subscription process to hourly long queue
2022-09-27 23:39:12 +05:30
Deepesh Garg
4c8617e1bb Merge pull request #32378 from deepeshgarg007/add_index_return_against
fix: Add return against indexes for POS Invoice
2022-09-27 22:22:03 +05:30
Deepesh Garg
82a2f31ada fix: Move subscription process to hourly long quque 2022-09-27 22:12:32 +05:30
Anand Baburajan
cf72931816 Merge branch 'develop' into fix_asset_scrap_and_sale_dep 2022-09-27 20:43:53 +05:30
anandbaburajan
c6a7de0e54 chore: add blank lines 2022-09-27 20:43:08 +05:30
anandbaburajan
14e2d31619 test: adding test_asset_with_maintenance_required_status_after_sale 2022-09-27 20:19:01 +05:30
rohitwaghchaure
f95de1fd4d Merge pull request #32377 from s-aga-r/fix/work-order/finish-button
fix: consider overproduction percentage for WO finish button
2022-09-27 17:44:41 +05:30
Deepesh Garg
cbfe28286a fix: Add return against indexes for POS Invoice 2022-09-27 16:22:59 +05:30
Nabin Hait
6145013f30 Merge branch 'develop' into fix_asset_scrap_and_sale_dep 2022-09-27 15:56:39 +05:30
Maharshi Patel
e39e088f18 fix: POS only validate QTY if is_stock_item
POS invoice raised " Item not available " validation error even though item is non_stock.
2022-09-27 15:44:38 +05:30
Deepesh Garg
1f6205e1ea fix: Add return against indexes for POS Invoice 2022-09-27 15:37:41 +05:30
Sagar Sharma
376febb9d1 Merge branch 'develop' into fix/work-order/finish-button 2022-09-27 15:36:15 +05:30
Maharshi Patel
c760ca2323 fix: Scrap Asset Accounting Dimensions (#31949)
* fix: Scrap Asset Accounting Dimensions
2022-09-27 15:31:36 +05:30
Sagar Sharma
05392e0918 fix: consider overproduction percentage for WO finish button 2022-09-27 15:30:08 +05:30
rohitwaghchaure
c917d716f7 Merge pull request #32370 from rohitwaghchaure/fixed-allow-expied-batch-return-using-pr-pi
fix: Not allowing to return expired batches using purchase return
2022-09-27 14:20:40 +05:30
Rohit Waghchaure
a4a86ee23f fix: allow to return expired batches using purchase return 2022-09-27 13:55:27 +05:30
Sagar Sharma
9049db41ae fix: For Quantity error msg in Stock Entry 2022-09-27 12:00:50 +05:30
ruthra kumar
21095502b9 chore: clean up purchase invoice and purchase invoice item
1. remove discount accounting related fields from purchase invoice and
purchase invoice item
2. clean buying settings doctype
2022-09-27 11:10:41 +05:30
Deepesh Garg
ce80b9fa0e Merge branch 'develop' of https://github.com/frappe/erpnext into internal_transfer_precision_fixes 2022-09-26 21:16:25 +05:30
Deepesh Garg
6e47fd54a0 fix: Hanlde rounding loss for internal transfer 2022-09-26 21:15:57 +05:30
rohitwaghchaure
106ee1bf4d Merge pull request #32339 from rohitwaghchaure/fixed-opening-entry-trial-balance-issue
fix: opening entry causing discrepancy between stock and trial balance
2022-09-26 20:32:41 +05:30
rohitwaghchaure
6a67cc96d0 Merge pull request #32049 from djpalshikar/patch-1
Allow Item Templates in Work Order Items
2022-09-26 20:27:33 +05:30
Ernesto Ruiz
499ce5139c fix: add translate function to book appointment verify html 2022-09-26 08:04:14 -06:00
Ernesto Ruiz
728ef46048 fix: add translate function to book appointment index.js 2022-09-26 08:01:48 -06:00
Ernesto Ruiz
e683cccf35 fix: add translate function to book appointment html 2022-09-26 07:59:13 -06:00
Sagar Sharma
e312d17eae refactor: rewrite Item Prices Report queries in QB 2022-09-26 17:50:17 +05:30
hendrik
f41d1500b0 fix: report chart field type
* fix: report chart field type

Co-authored-by: Sagar Sharma <sagarsharma.s312@gmail.com>
Co-authored-by: Deepesh Garg <deepeshgarg6@gmail.com>
2022-09-26 17:47:24 +05:30
Sagar Sharma
a80e8726e7 Merge pull request #32347 from s-aga-r/refactor/stock/report/incorrect-stock-value
refactor: rewrite `Incorrect Stock Value Report` queries in `QB`
2022-09-26 17:09:40 +05:30
Sagar Sharma
afb323b01c Merge branch 'develop' into refactor/stock/report/incorrect-stock-value 2022-09-26 17:09:22 +05:30
Sagar Sharma
2647018870 Merge pull request #32346 from s-aga-r/refactor/stock/report/item-price-stock-report
refactor: rewrite `Item Price Stock Report` queries in `QB`
2022-09-26 17:08:44 +05:30
Sagar Sharma
9a1fa53791 Merge branch 'develop' into refactor/stock/report/item-price-stock-report 2022-09-26 17:08:30 +05:30
Deepesh Garg
d84fd6c925 Merge pull request #32245 from pps190/feat_scan_sound
feat(stock): Audible indication of barcode scan status.
2022-09-26 17:02:37 +05:30
Deepesh Garg
9b38a372fb Merge pull request #32262 from shashankshirke/develop
fix: broken link for item valuation updated
2022-09-26 16:59:36 +05:30
Deepesh Garg
389fa180c8 Merge pull request #32276 from ernestoruiz89/patch-4
fix: add some strings to translate function
2022-09-26 16:39:04 +05:30
Deepesh Garg
539f8550c7 Merge pull request #32336 from ernestoruiz89/patch-6
fix: typo on opportunity summary by sales stage report
2022-09-26 16:37:58 +05:30
ruthra kumar
8b21d27f04 Merge pull request #32310 from nishibakabeer/patch-4
fix: total value in all keys
2022-09-26 11:27:47 +05:30
nishibakabeer
6919f389aa fix: total value in all keys
Gross and net profit report showing wrong values in monthly quarterly and half yearly filters which is the total value
@ruthra-kumar added in develop branch as suggested ( https://github.com/frappe/erpnext/pull/32020)
2022-09-26 10:40:55 +05:30
ruthra kumar
b33fb26b84 Merge pull request #32303 from ruthra-kumar/fix_difference_amount_calculation_on_payment_reconciliation
fix: difference amount calculation and popup on payment reconciliation
2022-09-26 10:25:12 +05:30
Sagar Sharma
b93331e844 refactor: rewrite Incorrect Stock Value Report queries in QB 2022-09-26 09:44:29 +05:30
Sagar Sharma
22299d2382 refactor: rewrite Item Price Stock Report queries in QB 2022-09-26 09:40:49 +05:30
Sagar Sharma
bb59346651 refactor: rewrite Delayed Item Report queries in QB 2022-09-23 15:47:26 +05:30
Rohit Waghchaure
bc3ab45af2 fix: opening entry causing discepancy between stock and trial balance 2022-09-23 15:21:09 +05:30
Sagar Sharma
1c1f991d2f refactor: rewrite Batch-Wise Balance History Report queries in QB 2022-09-23 14:57:44 +05:30
Sagar Sharma
2c9d9577e3 refactor: rewrite Batch Item Expiry Status Report queries in QB 2022-09-23 14:06:37 +05:30
Ernesto Ruiz
c4919cf5ec fix: typo on opportunity summary by sales stage report 2022-09-22 15:42:46 -06:00
Sagar Sharma
4efb8b142c Merge pull request #32324 from s-aga-r/refactor/report/production-planning-report
refactor: rewrite `Production Planning Report` queries in `QB`
2022-09-22 18:12:52 +05:30
Sagar Sharma
729193aca8 Merge branch 'develop' into refactor/report/production-planning-report 2022-09-22 11:18:02 +05:30
Sagar Sharma
8417b9b99c refactor: rewrite Production Planning Report queries in QB 2022-09-22 11:17:11 +05:30
rohitwaghchaure
d7e699ea1a Merge pull request #32309 from rohitwaghchaure/fixed-item-code-key-error
fix: item_code key error in production plan
2022-09-21 15:27:43 +05:30
Rohit Waghchaure
caf23e6b8e fix: item_code key error in production plan 2022-09-21 13:11:51 +05:30
Sagar Sharma
07f87b9147 Merge pull request #32304 from s-aga-r/refactor/report/exponential-smoothing-forecasting
refactor: rewrite `Exponential Smoothing Forecasting` queries in `QB`
2022-09-21 11:47:39 +05:30
Sagar Sharma
86c9ce9c20 Merge branch 'develop' into refactor/report/exponential-smoothing-forecasting 2022-09-21 10:25:47 +05:30
Sagar Sharma
5aff9e999e Merge pull request #32297 from s-aga-r/refactor/report/bom-variance-report
refactor: rewrite `BOM Variance Report` queries in `QB`
2022-09-21 10:00:04 +05:30
Sagar Sharma
1c0f1a2831 Merge branch 'develop' into refactor/report/exponential-smoothing-forecasting 2022-09-21 09:55:28 +05:30
Sagar Sharma
56f9c1b6f7 refactor: rewrite Exponential Smoothing Forecasting queries in QB 2022-09-21 09:54:38 +05:30
ruthra kumar
122d5f2729 fix: difference amount calculation on payment reconciliation 2022-09-21 08:36:09 +05:30
Sagar Sharma
d3a6881737 Merge branch 'develop' into refactor/report/bom-variance-report 2022-09-20 23:11:08 +05:30
Sagar Sharma
2235f31ffe Merge pull request #32295 from s-aga-r/refactor/report/bom-stock-report
refactor: rewrite `BOM Stock Report` queries in `QB`
2022-09-20 23:06:57 +05:30
Sagar Sharma
0048f58500 Merge branch 'develop' into refactor/report/bom-variance-report 2022-09-20 20:21:49 +05:30
Sagar Sharma
92e03e2c22 Merge branch 'develop' into refactor/report/bom-stock-report 2022-09-20 20:21:38 +05:30
ruthra kumar
6e65f01ede Merge pull request #32296 from ruthra-kumar/amount_in_words_for_debit_note
fix: get amount in words for debit note
2022-09-20 18:09:33 +05:30
Sagar Sharma
19e64eb247 refactor: rewrite BOM Variance Report queries in QB 2022-09-20 17:56:47 +05:30
ruthra kumar
70f6484d9d fix: get amount in words for debit note 2022-09-20 17:32:23 +05:30
Sagar Sharma
000c538d65 Merge branch 'develop' into refactor/report/bom-stock-report 2022-09-20 16:27:00 +05:30
Sagar Sharma
390ce5719d fix: warehouse filter in BOM Stock Calculated Report 2022-09-20 16:25:20 +05:30
Sagar Sharma
8fd7c04920 refactor: rewrite BOM Stock Report queries in QB 2022-09-20 16:23:14 +05:30
Deepesh Garg
4f2486a67a Merge pull request #32284 from maharshivpatel/fix-remove-no-copy-for-ignore_pricing_rule
fix: remove no_copy for ignore_pricing_rule
2022-09-20 16:19:16 +05:30
Deepesh Garg
d4b01f6ffd Merge branch 'develop' of https://github.com/frappe/erpnext into fix-remove-no-copy-for-ignore_pricing_rule 2022-09-20 14:58:48 +05:30
Nabin Hait
ecb5fff2ec Merge pull request #32264 from deepeshgarg007/asset_depreciation_date
fix: Depreciation posting date only when calculate depreciation is checked
2022-09-20 14:48:03 +05:30
Deepesh Garg
ef7d7e7d71 Merge pull request #32204 from deepeshgarg007/pending_tds_vouchers
fix(UX): More predictable tax withholding application in invoices
2022-09-20 14:35:16 +05:30
Sagar Sharma
2186a89781 Merge pull request #32280 from s-aga-r/refactor/report/item-shortage-report
refactor: rewrite `Item Shortage Report` queries in QB
2022-09-20 11:14:32 +05:30
Sagar Sharma
dad40b8d51 Merge branch 'develop' into refactor/report/item-shortage-report 2022-09-20 10:48:29 +05:30
Sagar Sharma
3dc754cac2 test: add test cases for Item Shortage Report 2022-09-20 10:48:05 +05:30
Sagar Sharma
f0a78aa559 refactor: rewrite Item Shortage Report queries in QB 2022-09-20 10:47:55 +05:30
Deepesh Garg
3d356763d0 Merge pull request #32217 from ruthra-kumar/bug_in_tax_on_multi_currency_payment_entry
fix: incorrect gl if tax on multi currency payment entry
2022-09-20 09:59:47 +05:30
Deepesh Garg
49538e81de Merge pull request #32235 from maharshivpatel/fix-payment-schedule-description
fix: fetch description only if empty on the payment schedule
2022-09-20 09:13:43 +05:30
Deepesh Garg
1f4932966a Merge branch 'develop' of https://github.com/frappe/erpnext into pending_tds_vouchers 2022-09-20 09:06:35 +05:30
Deepesh Garg
9aa1f84d45 chore: fix tests 2022-09-20 09:06:18 +05:30
Ernesto Ruiz
94199b7867 fix: add translate function to strings 2022-09-19 11:56:42 -06:00
Ernesto Ruiz
aa49ec815a fix: add translate function to strings 2022-09-19 11:55:13 -06:00
Ernesto Ruiz
9decebe6e1 fix: Add strings to translate function 2022-09-19 10:13:30 -06:00
Sagar Sharma
377576f131 Merge pull request #32274 from s-aga-r/fix/stock-entry/subcontract-order-item-reference
fix: `po_detail` or `sco_rm_detail` not getting set while while mapping SE
2022-09-19 19:18:54 +05:30
Sagar Sharma
a4db9abcb4 Merge branch 'develop' into fix/stock-entry/subcontract-order-item-reference 2022-09-19 18:52:27 +05:30
Sagar Sharma
3a9c08e7c9 fix: po_detail or sco_rm_detail not getting set while while mapping SE 2022-09-19 18:47:46 +05:30
Deepesh Garg
083309c056 fix: Incoming rate precision fixes for intra company transfer 2022-09-19 15:06:06 +05:30
ruthra kumar
efc9553561 Merge pull request #32251 from ruthra-kumar/set_default_supplier_currency_for_po_created_from_so
fix: use default supplier currency if default supplier is enabled
2022-09-19 12:44:51 +05:30
Deepesh Garg
fac82cf69b fix: Depreciation posting date only when calculate depreciation is checked 2022-09-18 19:41:05 +05:30
Shashank Shirke
785eaf8e8f fix: broken link for item valuation updated
Old URL (404 Not Found): https://docs.erpnext.com/docs/v13/user/manual/en/stock/item/item-valuation-fifo-and-moving-average

Updated URL: https://docs.erpnext.com/docs/v13/user/manual/en/stock/articles/calculation-of-valuation-rate-in-fifo-and-moving-average
2022-09-18 05:42:47 -07:00
Sagar Sharma
b944849bd4 Merge pull request #32250 from s-aga-r/fix/stock-entry/supplied-item-reference
fix: make `po_detail` or `sco_rm_detail` mandatory for SE Send to Subcontractor
2022-09-18 14:54:08 +05:30
Sagar Sharma
b747d9d05e Merge branch 'develop' into fix/stock-entry/supplied-item-reference 2022-09-18 11:37:38 +05:30
Sagar Sharma
b90875575c fix: make po_detail or sco_rm_detail mandatory for SE Send to Subcontractor 2022-09-18 11:37:07 +05:30
Deepesh Garg
110840aa98 Merge pull request #32244 from deepeshgarg007/project_po_linking
fix: Parent Level project linkning on creating PO from project
2022-09-17 20:29:40 +05:30
ruthra kumar
77fdc37cb7 fix: use default supplier currency if default supplier is enabled 2022-09-17 16:34:33 +05:30
Sagar Sharma
3b5284ec2b Merge pull request #32247 from s-aga-r/fix/stock-entry/sco-rm-detail
fix: add SCO supplied item reference while mapping the Stock Entry
2022-09-17 15:42:03 +05:30
Sagar Sharma
2f97370b8e fix: sco_rm_detail in Stock Entry 2022-09-17 14:29:42 +05:30
rohitwaghchaure
3c01bf3a12 Merge pull request #32238 from rohitwaghchaure/fix-pricing-rules-issues
fix: suggestion threshold label and rule was not working for other item with min and max amount
2022-09-17 12:11:24 +05:30
Devin Slauenwhite
32e75ff808 feat: audible indication of scan status. 2022-09-16 17:58:01 -04:00
Devin Slauenwhite
613c8158a8 fix: actually reject process_scan when update_table fails. 2022-09-16 17:49:00 -04:00
Deepesh Garg
93e134aab0 fix: Parent Level project linkning on creating PO from project 2022-09-16 22:44:23 +05:30
Sagar Sharma
43ebfa7982 Merge pull request #32236 from s-aga-r/fix/production-plan/pending-qty
fix: production plan pending-qty
2022-09-16 18:29:46 +05:30
Maharshi Patel
8c5b420aea fix: remove no_copy for ignore_pricing_rule 2022-09-16 18:26:00 +05:30
Sagar Sharma
bd6af7c613 test: update test case for production plan pending-qty 2022-09-16 18:00:26 +05:30
ruthra kumar
5bd5dd7262 test: gl entries of payments with advance tax 2022-09-16 16:22:21 +05:30
Rohit Waghchaure
f5bd3fa952 fix: suggestion threshold label and rule was not working for other items with min and max amount 2022-09-16 16:03:08 +05:30
Sagar Sharma
5be7d42dfd fix: production plan pending-qty 2022-09-16 14:39:39 +05:30
Maharshi Patel
f4b64686ae fix: fetch description only if empty on the payment schedule
added fetch_if_empty on description field of payment_schedule.
2022-09-16 14:14:14 +05:30
Deepesh Garg
36d0906ea2 fix: TDS deduction via journal entry 2022-09-16 13:50:37 +05:30
Sagar Sharma
487d825ede Merge pull request #32233 from s-aga-r/refactor/file/production_plan.py
refactor: rewrite Production Plan queries in QB
2022-09-16 13:28:54 +05:30
ruthra kumar
f0ae77b23b fix: incorrect gl if tax on multi currency payment entry 2022-09-16 12:40:40 +05:30
Deepesh Garg
0a6462e627 Merge branch 'develop' of https://github.com/frappe/erpnext into pending_tds_vouchers 2022-09-16 12:35:39 +05:30
Sagar Sharma
be0d9d8c13 Merge branch 'develop' into refactor/file/production_plan.py 2022-09-16 12:28:48 +05:30
Sagar Sharma
b8cf3b4c77 refactor: rewrite Production Plan queries in QB 2022-09-16 12:23:43 +05:30
Deepesh Garg
38d00f407e Merge pull request #32225 from nabinhait/dunning-fix
fix: create dunning from sales invoice
2022-09-16 11:04:55 +05:30
Deepesh Garg
e4ef6c9645 Merge pull request #32219 from nabinhait/bank-clearnance-perm-issue
fix: No permission to read doctype
2022-09-16 11:04:42 +05:30
Nabin Hait
0286f2da78 Merge branch 'develop' into dunning-fix 2022-09-16 09:40:18 +05:30
Nabin Hait
a1fcabee0e Merge pull request #32221 from rohitwaghchaure/consider-posting-time-for-internal-po
fix: consider posting time for internal transfer PO
2022-09-16 09:37:45 +05:30
Nabin Hait
9c96cd6090 Merge pull request #32222 from nabinhait/cost-center-renaming
fix: abbreviation issue on renaming cost center
2022-09-16 09:36:55 +05:30
anandbaburajan
43a3400221 fix: fix restore asset value after depreciation 2022-09-15 23:25:04 +05:30
anandbaburajan
5a8b28c194 fix: refactor asset capitilization 2022-09-15 22:52:25 +05:30
anandbaburajan
11ac20e5ee fix: asset tests 2022-09-15 22:43:18 +05:30
Nabin Hait
786891c600 Merge branch 'develop' into bank-clearnance-perm-issue 2022-09-15 17:42:37 +05:30
Nabin Hait
0d732609f0 Merge branch 'develop' into consider-posting-time-for-internal-po 2022-09-15 17:42:26 +05:30
Nabin Hait
c5c6a69269 Merge branch 'develop' into cost-center-renaming 2022-09-15 17:42:13 +05:30
Nabin Hait
73f6c5fe35 Merge branch 'develop' into dunning-fix 2022-09-15 17:42:00 +05:30
Nabin Hait
5fa3450a9c Merge pull request #32218 from nabinhait/asset-cap-tests
fix: Fixed asset capitalization test cases
2022-09-15 17:41:39 +05:30
anandbaburajan
ff5cad1cd6 fix: calculate depreciation properly on asset sale entry and scrap entry 2022-09-15 13:15:34 +05:30
Nabin Hait
29db084dc3 fix: create dunning from sales invoice 2022-09-15 13:11:53 +05:30
Nabin Hait
af21a11e1e fix: abbreviation issue on renaming cost center 2022-09-15 12:09:18 +05:30
Rohit Waghchaure
cb763938dc fix: consider posting time for internal transfer PO 2022-09-15 11:48:43 +05:30
Nabin Hait
c0da948a4e fix: No permission to read doctype 2022-09-15 11:27:35 +05:30
Nabin Hait
3457105504 fix: test cases 2022-09-15 11:19:33 +05:30
Nabin Hait
a5b5885933 fix: test cases 2022-09-15 11:19:14 +05:30
Nabin Hait
cbf973d90f fix: always set default expense account in company 2022-09-15 11:19:06 +05:30
Ankush Menat
97977cdb4b fix: correct sql output format in CRM patch (#32213) 2022-09-14 19:19:05 +05:30
Deepesh Garg
87160c8d2f Merge pull request #32208 from abhinavxd/fix-pending-accrual-entries
fix: Loans pending accrual entries
2022-09-14 14:14:44 +05:30
Abhinav Raut
f2209045f8 fix: pending accrual entries 2022-09-14 11:55:03 +05:30
Deepesh Garg
b6184ce471 test: Add tests 2022-09-14 09:13:02 +05:30
Sagar Sharma
444fda5d82 Merge pull request #32205 from s-aga-r/fix/issue/31557
fix: unknown column error while updating value of maintain-stock in item master
2022-09-14 08:14:21 +05:30
Deepesh Garg
b6d87ae25b Merge branch 'develop' of https://github.com/frappe/erpnext into pending_tds_vouchers 2022-09-13 22:31:21 +05:30
Sagar Sharma
bf1fa014f4 test: add test case for item master maintain-stock 2022-09-13 22:12:56 +05:30
Sagar Sharma
7b878ea3d8 fix: unknown column error while updating value of maintain-stock in item master 2022-09-13 21:52:58 +05:30
Deepesh Garg
3fb1595a4e fix: Fetch vouchers to show in Invoice 2022-09-13 20:31:31 +05:30
Deepesh Garg
246c1a9380 fix: Add child table for tax withheld vouchers 2022-09-13 20:05:20 +05:30
Ankush Menat
8043f4fc10 chore: let frappe pr bot raise stable branch PRs
[skip ci]
2022-09-13 15:14:53 +05:30
Nabin Hait
e24a4b18c4 Merge branch 'SaiFi0102-asset-capitalization' into develop 2022-09-13 15:00:21 +05:30
Nabin Hait
58d430fe3e feat: Asset Capitalization
- manual selection of entry type
- GLE cleanup with smaller functions
- GLE considering periodical inventory
- test cases
2022-09-13 14:56:21 +05:30
Deepesh Garg
dc985e0e83 Merge pull request #32190 from maharshivpatel/fix-item-wise-sales-register
fix: item wise sales register taxes and charges
2022-09-13 13:53:51 +05:30
Shadrak Gurupnor
f2b7c9ee66 fix: validate for active sla (#32132) 2022-09-13 13:42:45 +05:30
Ankush Menat
fffc245922 fix(UX): make Item attachments public by default (#32196) 2022-09-13 13:41:00 +05:30
Deepesh Garg
f8bee0e75f Merge pull request #32091 from nabinhait/lead-notes-patch
fix: Migrate old lead notes as per the new format
2022-09-13 12:20:50 +05:30
Rucha Mahabal
eb01f9729d fix(Employee): shorter tab titles (#32192) 2022-09-13 10:34:35 +05:30
Deepesh Garg
51c37aeee3 Merge branch 'develop' into lead-notes-patch 2022-09-13 09:42:07 +05:30
Raffael Meyer
e00ece7a78 fix: remove EmployeeBoardingController (#32139)
fix: remove employee boarding controller

Co-authored-by: Rucha Mahabal <ruchamahabal2@gmail.com>
2022-09-13 02:00:04 +05:30
Maharshi Patel
62163ab3d3 fix: item wise sales register taxes and charges
i have added separate column for other charges. Instead of adding all values to tax_total, it checks if account_type is tax, and then only it adds to total_tax otherwise it adds to the total_other_charges.
2022-09-12 23:44:56 +05:30
Sagar Sharma
2ecd2a3c44 Merge pull request #32188 from frappe/mergify/bp/develop/pr-32179
fix: pick_list - picked qty getting set to 1 (backport #32179)
2022-09-12 23:15:54 +05:30
Ahmad
4f1cc41b86 fix: pick_list - picked qty getting set to 1
(cherry picked from commit 3256e2b8b7)
2022-09-12 16:49:45 +00:00
Sagar Sharma
d4071575a4 Merge pull request #32150 from s-aga-r/refactor/report/bom-stock-calculated
refactor: BOM Stock Calculated report, fix required-qty
2022-09-12 19:21:18 +05:30
Sagar Sharma
2336bcfe20 Merge branch 'develop' into refactor/report/bom-stock-calculated 2022-09-12 19:20:58 +05:30
rohitwaghchaure
b3b1df7184 Merge pull request #32181 from rohitwaghchaure/fix-min-max-amount-configuration
fix: promotional scheme min and max amount configuration
2022-09-12 18:30:01 +05:30
Sagar Sharma
d3cd3bc5ef Merge branch 'develop' into refactor/report/bom-stock-calculated 2022-09-12 17:23:15 +05:30
Sagar Sharma
e1a98c1ff7 test: add test cases for BOM Stock Calculated report 2022-09-12 17:11:00 +05:30
Rohit Waghchaure
a8fd92ddc1 fix: promotional scheme min and max amount configuration 2022-09-12 16:53:52 +05:30
rohitwaghchaure
8f787c08a2 fix: customer code max characters limit issue (#32177) 2022-09-12 16:48:53 +05:30
Sagar Sharma
7a968a5f0d fix: add missing warehouse filter in BOM Stock Calculated report 2022-09-12 16:12:51 +05:30
Sagar Sharma
56192daabf fix: required_qty in BOM Stock Calculated report 2022-09-12 16:12:49 +05:30
ruthra kumar
ce0676ac70 Merge pull request #32175 from SolufyPrivateLimited/filter_AR
fix: Set filter condition and spell in AR
2022-09-12 15:00:36 +05:30
Nihantra C. Patel
e2b4ae13fa fix: Set filter condition and spell in AR 2022-09-12 14:09:42 +05:30
Ankush Menat
a30f38481d chore: correct license text for GPLv3 (#32170)
[skip ci]
2022-09-12 13:54:08 +05:30
Ankush Menat
12d99b3292 refactor: use util method for checking if job is queued 2022-09-12 13:14:48 +05:30
Deepesh Garg
6b94b5334c Merge pull request #32144 from deepeshgarg007/internal_purchase_invoice_rate
fix: Rate for internal PI have non stock UOM items
2022-09-12 09:09:43 +05:30
Sagar Sharma
ada1ab3509 Merge pull request #32161 from s-aga-r/refactor/report/process-loss-report
refactor: rewrite Process Loss Report queries in QB
2022-09-11 19:47:38 +05:30
Sagar Sharma
a86023eb09 Merge branch 'develop' into refactor/report/process-loss-report 2022-09-11 19:15:16 +05:30
Sagar Sharma
5245928648 refactor: rewrite Process Loss Report queries in QB 2022-09-11 19:03:59 +05:30
ruthra kumar
0aeb7c6484 Merge pull request #32156 from ruthra-kumar/bug_multiple_call_to_ple_creation
fix: remove duplicate call to ple creation
2022-09-11 12:21:01 +05:30
ruthra kumar
4adc372f9a fix: remove multiple call to ple creation 2022-09-11 11:52:17 +05:30
ruthra kumar
4576c1ebc3 Merge pull request #32137 from ruthra-kumar/delete_payment_ledger_entries_on_src_doc_delete
refactor(minor): delete linked payment ledger entries on source doc deletion
2022-09-11 11:21:24 +05:30
Sagar Sharma
e4a1cf0cd2 Merge pull request #32153 from s-aga-r/refactor/report/work-order-stock-report
refactor: rewrite Work Order Stock Report queries in QB
2022-09-10 16:51:00 +05:30
Sagar Sharma
5558191a2a Merge branch 'develop' into refactor/report/work-order-stock-report 2022-09-10 16:30:15 +05:30
Sagar Sharma
d4c4dddfc3 refactor: rewrite Work Order Stock Report queries in QB 2022-09-10 16:29:47 +05:30
ruthra kumar
70313df531 fix: delete linked payment ledger entries no source doc deletion 2022-09-10 09:30:45 +05:30
Sagar Sharma
723fa9eebc refactor: BOM Stock Calculated report 2022-09-09 19:11:36 +05:30
Sagar Sharma
1dce3c98d8 Merge pull request #32145 from s-aga-r/fix/stock-entry/sco
fix: validate Subcontracting Order Status in Stock Entry
2022-09-09 14:55:26 +05:30
Nabin Hait
fefe95052d fix: resolved merge conflict 2022-09-09 14:40:36 +05:30
Sagar Sharma
2e314a20f1 Merge branch 'develop' into fix/stock-entry/sco 2022-09-09 13:48:14 +05:30
Sagar Sharma
9a3dcb9ad1 fix: validate Subcontracting Order in Stock Entry 2022-09-09 13:46:50 +05:30
Sagar Sharma
30909a9b79 fix: status filter for Subcontracting Order in Stock Entry 2022-09-09 13:45:31 +05:30
Deepesh Garg
0f655e4430 fix: Rate for internal PI have non stock UOM items 2022-09-09 12:40:57 +05:30
Sagar Sharma
659d007bf0 Merge pull request #32102 from s-aga-r/fix/v14/stock-entry/send-to-subcontractor
fix: consider Stock Entry purpose while getting total supplied qty
2022-09-09 12:13:42 +05:30
Sagar Sharma
b49caf170c Merge branch 'develop' into fix/v14/stock-entry/send-to-subcontractor 2022-09-09 11:37:12 +05:30
Deepesh Garg
33d0e09497 Merge pull request #32117 from deepeshgarg007/psoa_fontsize
fix: Reduce font size for Process Statement of accounts print/pdf
2022-09-09 11:18:13 +05:30
rohitwaghchaure
6da45144d0 Merge pull request #32135 from rohitwaghchaure/fixed-incorrect-gl-entries-for-internal-transfer
fix: reposting not working for internal transferred purchase receipt
2022-09-09 09:30:21 +05:30
Rohit Waghchaure
a03b4ce213 fix: reposting not working for internal transferred purchase receipt 2022-09-08 19:16:00 +05:30
Sagar Sharma
9d453c91f1 Merge pull request #32128 from s-aga-r/fix/subcontracting-order/returned-qty
fix: SCO Supplied Items returned-qty
2022-09-08 19:00:59 +05:30
Sagar Sharma
61110dbfe4 Merge branch 'develop' into fix/subcontracting-order/returned-qty 2022-09-08 18:26:50 +05:30
Sagar Sharma
3585daab95 fix: hide "Return of Components" button in closed SCO (#32130) 2022-09-08 18:23:56 +05:30
Sagar Sharma
aea7188304 test: add test case for returned-qty 2022-09-08 18:15:48 +05:30
Sagar Sharma
ccb2889cac fix: SCO Supplied Items returned-qty 2022-09-08 18:15:45 +05:30
rohitwaghchaure
72d5366e96 Merge pull request #31918 from s-aga-r/fix/subcontracting-receipt/gl-entries
fix: Subcontracting Receipt GL Entries
2022-09-08 10:17:12 +05:30
rohitwaghchaure
448c5ff3dc Merge pull request #32118 from rohitwaghchaure/provision-to-manual-reposting
fix: option to start reposting from repost item valuation
2022-09-07 16:57:43 +05:30
rohitwaghchaure
7dc8ab4069 Merge pull request #32115 from rohitwaghchaure/fixed-label-not-showing-for-filter
fix: inventory dimension filter's label not showing in the report
2022-09-07 16:38:59 +05:30
Rohit Waghchaure
f1c4aea7b5 fix: option to start reposting from repost item valuation 2022-09-07 16:38:17 +05:30
Deepesh Garg
6bfd193b0d fix: Reduce font size for Process Statement of accounts print/pdf 2022-09-07 16:34:10 +05:30
ruthra kumar
741b5b4978 Merge pull request #32110 from ruthra-kumar/bank_import_statement_bug
fix: error on bank statement import
2022-09-07 15:22:14 +05:30
Sagar Sharma
f19049e643 Merge branch 'develop' into fix/subcontracting-receipt/gl-entries 2022-09-07 14:55:56 +05:30
Sagar Sharma
01c2e4d2cf Merge branch 'develop' into fix/v14/stock-entry/send-to-subcontractor 2022-09-07 14:52:16 +05:30
Rohit Waghchaure
ef7def8f1d fix: inventory dimension filter's label not showing in the reort 2022-09-07 14:43:12 +05:30
rohitwaghchaure
5b02adbd33 Merge pull request #32113 from rohitwaghchaure/fixed-internal-transfer-flow
fix: internal transfer flow
2022-09-07 14:26:14 +05:30
Rohit Waghchaure
9d1be48bd2 test: added test case for internal transfer 2022-09-07 13:51:52 +05:30
Devin Slauenwhite
aab2c9c682 fix: require barcode item barcode. (#31957)
* fix: require barcode item barcode.

* fix: make supplier mandatory in Item Supplier DocType

Co-authored-by: Sagar Sharma <sagarsharma.s312@gmail.com>
2022-09-07 12:59:46 +05:30
Rohit Waghchaure
b4a102d119 fix: internal transfer flow 2022-09-07 12:48:18 +05:30
ruthra kumar
a6fbb80b94 fix: import error on bank statement import
Name collision between frameworks file importer's internal log and
doctype fieldname - import_log.

Frameworks internal log overrode, doctypes field which caused failure
in basic fieldtype validation.
2022-09-07 11:19:54 +05:30
Sagar Sharma
008542b715 fix: AD not getting copied from SCO while creating a Material Transfer (#32106) 2022-09-07 10:15:43 +05:30
Deepesh Garg
8efd305afd Merge pull request #32089 from frappe/mergify/bp/develop/pr-32086
fix: QR Code multi currency issue (backport #32086)
2022-09-07 07:46:55 +05:30
Ankush Menat
506b289b2a ci: auto create release PRs
[skip ci]
2022-09-06 19:05:53 +05:30
Sagar Sharma
2f00413864 fix: consider Stock Entry purpose while getting total supplied qty 2022-09-06 16:42:15 +05:30
rohitwaghchaure
c6380a25d6 Merge pull request #32063 from rohitwaghchaure/fixed-fetch-from-parent
fix: inventory dimension issues
2022-09-06 10:45:36 +05:30
Rucha Mahabal
5ab5811770 feat: tabbed view for Employee form (#31940) 2022-09-06 10:18:14 +05:30
Rohit Waghchaure
75fcab04b1 test: test cases for PI and DN 2022-09-06 01:42:57 +05:30
Nabin Hait
4b13452022 fix: drop old notes column from lead and prospect 2022-09-05 18:28:09 +05:30
Nabin Hait
2a100abef1 perf: lesser SQL queries and no validation
Co-authored-by: Sagar Vora <sagar@resilient.tech>
2022-09-05 18:16:34 +05:30
Nabin Hait
3abd00f3bb fix: Migrate old lead notes as per the new format 2022-09-05 18:10:53 +05:30
Sagar Sharma
fb54277484 Merge pull request #32082 from s-aga-r/t3
fix: validate available qty for consumption in SCR
2022-09-05 14:19:39 +05:30
Sagar Sharma
74c2458bdb Merge branch 'develop' into t3 2022-09-05 13:56:21 +05:30
Sagar Sharma
a349b58306 refactor(test): test_update_reserved_qty_for_subcontracting 2022-09-05 13:55:55 +05:30
Sagar Sharma
4a7add2169 fix: validate available qty for consumption in SCR 2022-09-05 13:27:03 +05:30
hamzaali15
987ac513c8 fix: QR Code multi currency issue
When try to scan qr code on app it is showing correct values for multi currencies because it is not getting base amount

(cherry picked from commit b10a2b87b6)
2022-09-05 07:13:32 +00:00
Nabin Hait
57257a1795 Merge pull request #32061 from resilient-tech/fix-appointment-creation
fix(Appointment): create lead notes as child table
2022-09-05 12:25:45 +05:30
Deepesh Garg
3c055f94e1 Merge pull request #31982 from FHenry/dev_enhance_upgrade_process
fix: upgrade process to version-14 when currency opportunity was not set
2022-09-04 19:03:43 +05:30
Deepesh Garg
118b0c0f86 chore: fix message 2022-09-04 19:03:16 +05:30
Deepesh Garg
10d94ed539 Merge pull request #32045 from SolufyPrivateLimited/Solufy-JET
fix: Naming series in Journal Entry Template
2022-09-04 16:34:05 +05:30
HENRY Florian
86395c6adb feat: better Item Price list view (#31954)
* feat: better Item Price list view
2022-09-04 16:25:03 +05:30
Deepesh Garg
acb88e5c57 Merge pull request #31850 from HarryPaulo/add-two-new-filters-gross-profit
feat: two new filters for gross profit
2022-09-04 15:56:54 +05:30
Deepesh Garg
78d1b83d11 Merge pull request #31822 from nextchamp-saqib/fix-consolidation-precision-error
fix(pos): error while consolidating pos invoices
2022-09-04 13:25:20 +05:30
Deepesh Garg
1a61d4e8a8 Merge branch 'develop' into fix-consolidation-precision-error 2022-09-04 13:18:10 +05:30
Deepesh Garg
ad8d0efa29 chore: Linting Issues 2022-09-04 13:15:59 +05:30
Rohit Waghchaure
237299948a fix: fetch from parent not working for custom field 2022-09-03 17:27:00 +05:30
rohitwaghchaure
0efc6a9abe Merge pull request #32065 from rohitwaghchaure/not-able-to-make-variant-item
fix: not able to make variant item
2022-09-03 11:52:56 +05:30
Rohit Waghchaure
92b0f9cd7e fix: not able to make variant item 2022-09-03 11:42:04 +05:30
Sagar Vora
875ff15109 test: dont create lead manually, add coverage for notes 2022-09-02 18:30:39 +05:30
Sagar Vora
58e553151e fix(Appointment): create lead notes as child table 2022-09-02 12:42:37 +00:00
HENRY Florian
7919513c8a Merge branch 'develop' into dev_enhance_upgrade_process 2022-09-02 13:01:06 +02:00
ruthra kumar
e424ad5ff2 Merge pull request #32054 from ruthra-kumar/bug_in_process_deferred_accounting
fix: type error on cancellation of Process Deferred Accounting
2022-09-02 16:20:31 +05:30
ruthra kumar
64f8010a25 Merge pull request #32052 from ruthra-kumar/key_error_on_consolidate_financial_report
fix: key error on consolidated financial report
2022-09-02 16:13:19 +05:30
ruthra kumar
1c385541fa test: pda document submission and cancellation 2022-09-02 12:34:02 +05:30
ruthra kumar
08f2e4edc3 fix: incorrect import parameter for cancel PDA 2022-09-02 10:51:51 +05:30
ruthra kumar
6e8395cccd fix: key error on consolidated financial report
accounts with same name but different account number will throw key
error on consolidated report
2022-09-02 09:55:24 +05:30
Sagar Sharma
68907ca783 chore: set BOM as default value for Backflush Raw Materials of Subcontract Based On (#32048)
chore: set BOM as default value for Backflush Raw Materials of Subcontract Based On in Buying Settings
2022-09-01 19:31:55 +05:30
Dhananjay Palshikar
75396c02d2 Allow Item Templates in Work Order Items
Item Variants can be a part of the items tables, however, when BOM items are fetched to be a part of the Work Order items, item variants were being filtered out.
The filtering out does not serve a purpose. Having Item variants in BOMs allows for template like behaviour.
2022-09-01 19:07:13 +05:30
HENRY Florian
069cb10d6f Merge branch 'develop' into dev_enhance_upgrade_process 2022-09-01 11:28:49 +02:00
Sagar Vora
2e9f531e2c chore(deps): specify PyPNG as a dependency 2022-09-01 11:54:08 +05:30
Solufyin
2085626390 fix: Naming series in Journal Entry Template 2022-09-01 11:49:13 +05:30
HENRY Florian
b05fdb28ff Merge branch 'develop' into dev_enhance_upgrade_process 2022-08-31 13:52:28 +02:00
Ankush Menat
30039e8e62 fix: encode thumbnail URL
If it contains space the URL won't load
2022-08-31 17:06:20 +05:30
Ankush Menat
4a38ce659d refactor!: drop redisearch
incr: replace text and tag fields

incr: use rediswrapper's make key

incr: indexDefinition from redis

incr: replace index creation

incr: replace AutoCompleter

incr: replace product search ac

incr: replace client querying

fix: broken redisearch load test

fix: pass actual query to get suggestion
2022-08-31 17:06:20 +05:30
Deepesh Garg
8f51ccd002 Merge pull request #32030 from deepeshgarg007/zero_interest_loan
fix: Loan Interest accruals for 0 rated loans
2022-08-30 21:15:15 +05:30
Deepesh Garg
a76d3827ec chore: Add check for principal amount 2022-08-30 19:24:57 +05:30
Deepesh Garg
eefc9b7172 fix: Loan Interest accruals for 0 rated loans 2022-08-30 19:16:36 +05:30
Ankush Menat
ffa3071d36 fix: force delete old report docs (#32026) 2022-08-30 15:43:57 +05:30
Deepesh Garg
9e0e308a44 Merge pull request #32005 from niyazrazak/patch-4
fix: lost quotation not to expired
2022-08-30 10:33:01 +05:30
Raffael Meyer
73f4d5931d fix: permissions for Task Type (#32016) 2022-08-29 21:56:07 +05:30
Ankush Menat
2d41704424 fix(patch): update sla doctype directly (#32014)
fix: update sla doctype directly
2022-08-29 20:50:27 +05:30
ruthra kumar
25072e5d32 Merge pull request #32009 from ruthra-kumar/add_remarks_to_payment_ledger
refactor: readd remarks field to payment ledger
2022-08-29 19:48:36 +05:30
ruthra kumar
d522f13d55 chore: add remarks migration to patches.txt 2022-08-29 15:59:56 +05:30
ruthra kumar
3a6b095ed4 chore: patch for migrating remarks to payment ledger 2022-08-29 15:59:56 +05:30
ruthra kumar
5782c4469a refactor: re-add remarks field to payment ledger and AR/AP report 2022-08-29 15:59:37 +05:30
Deepesh Garg
6881b68ed7 Merge pull request #32006 from deepeshgarg007/cash_and_non_trade_discount_rounded_total
fix: Rounded total for cash and non trade discount invoices
2022-08-29 15:35:23 +05:30
Sagar Sharma
9dbaaa33f5 fix: AD not getting copied from SCO while creating a SE (#32004) 2022-08-29 15:07:20 +05:30
MOHAMMED NIYAS
69ffef8c0e fix: lost quotation not to expired 2022-08-29 14:47:43 +05:30
HENRY Florian
61c143cb82 Merge branch 'develop' into dev_enhance_upgrade_process 2022-08-29 10:49:11 +02:00
Deepesh Garg
318da16b99 fix: Rounded total for cash and non trade discount invoices 2022-08-29 14:18:39 +05:30
Sagar Sharma
af5cbc881f chore: allow return of components in SCO (#31994)
chore: allow return of components in sco
2022-08-26 22:49:40 +05:30
Deepesh Garg
7da39c3ff3 Merge pull request #31991 from frappe/codeowners
chore: Update code owners
2022-08-26 17:39:18 +05:30
Deepesh Garg
ac57101833 chore: Update code owners 2022-08-26 17:37:13 +05:30
Deepesh Garg
87ca23736d Merge pull request #31988 from ruthra-kumar/remove_precision_discount_percentage
chore: remove precision on discount_percentage of Sales Invoice Item
2022-08-26 16:03:57 +05:30
HENRY Florian
6cd7ef9cc3 Merge branch 'develop' into dev_enhance_upgrade_process 2022-08-26 11:33:22 +02:00
ruthra kumar
c42fef541a chore: remove precision on discount_percentage of Sales Invoice Item 2022-08-26 13:15:55 +05:30
rohitwaghchaure
5ac27100a5 Merge pull request #31984 from SolufyPrivateLimited/Solufy-so-to-po
fix: Purchase Order creation from Sales Order
2022-08-26 12:00:52 +05:30
Solufyin
bd4b4ddd8b fix: Purchase Order creation from Sales Order 2022-08-26 11:18:56 +05:30
Florian HENRY
d19b664ba9 chore: better text 2022-08-25 22:35:44 +02:00
Florian HENRY
ac66538651 chore: remove debug 2022-08-25 22:35:08 +02:00
Florian HENRY
9d02fbadb4 fix: upgrade process to version-14 when currency opportunity wass not set 2022-08-25 20:45:35 +02:00
ruthra kumar
902797d0f0 Merge pull request #31977 from ruthra-kumar/ar_ap_report_filter_on_party_type
fix: restrict party types to Supplier/Customer for AR/AP report
2022-08-25 16:19:50 +05:30
ruthra kumar
6aa8fd0f7b fix: restrict party types to Supplier/Customer for AR/AP report 2022-08-25 15:50:06 +05:30
Sagar Sharma
8566832dd5 fix: add validation for PO in Stock Entry (#31974) 2022-08-25 15:05:13 +05:30
Deepesh Garg
9e43c9cff3 Merge pull request #31943 from nabinhait/asset-repair
fix: gl entries for asset repair
2022-08-25 13:24:26 +05:30
rohitwaghchaure
b27f3ab327 Merge pull request #31967 from rohitwaghchaure/connection-added-for-work-order
fix: material request connection on work order
2022-08-25 12:29:10 +05:30
rohitwaghchaure
dae112eed2 Merge pull request #31966 from rohitwaghchaure/set-default-supplier-from-item
fix: default supplier not set in the PP
2022-08-25 12:25:00 +05:30
Rohit Waghchaure
9ab10def49 fix: material request connection on work order 2022-08-25 12:13:17 +05:30
Deepesh Garg
c1f6dd46d1 chore: fix against account 2022-08-25 12:10:52 +05:30
Rohit Waghchaure
5fd468d9ec fix: default supplier not set in the PP 2022-08-25 11:44:12 +05:30
Deepesh Garg
e9b0c7177f Merge branch 'develop' into fix-consolidation-precision-error 2022-08-25 11:41:20 +05:30
Samuel Danieli
915102a400 chore: german translations (#31463) 2022-08-25 11:23:38 +05:30
Deepesh Garg
5187a9a5ad Merge pull request #31776 from HarryPaulo/fix-net-amout-sales-analytics
fix: for Tree Type item and item group show net amout
2022-08-25 11:05:18 +05:30
Deepesh Garg
9b626d06fc Merge pull request #31909 from s-aga-r/filters/repost-item-valuation/voucher-no
fix: Add docstatus filter for voucher_no in Repost Item Valuation
2022-08-25 10:49:29 +05:30
rohitwaghchaure
1af22e5312 Merge pull request #31951 from rohitwaghchaure/maintenance-visit-issue
fix: Purposes not set in Maintenance Visit
2022-08-25 10:48:41 +05:30
Deepesh Garg
77906ea4ab Merge pull request #31934 from ruthra-kumar/disable_discount_accounting_for_buying
refactor: disable discount accounting on Buying module(PI)
2022-08-25 10:34:30 +05:30
Deepesh Garg
40bf1a50fd Merge pull request #31950 from ruthra-kumar/party_currency_or_multi_currency
fix: display amount in account currency if party is supplied
2022-08-25 10:33:49 +05:30
Deepesh Garg
91d6454f87 Merge pull request #31955 from FHenry/dev_fr_translation
chore: update french translation
2022-08-25 10:26:17 +05:30
ruthra kumar
e5b04d54ff fix: display amount in account currency if party is supplied 2022-08-25 10:05:25 +05:30
ruthra kumar
ee889afd4c Merge pull request #31942 from ruthra-kumar/bug_ar_ap_report_include_payment_against_po
fix: include payment against PO in AR/AP report
2022-08-25 09:40:45 +05:30
Florian HENRY
299da5d596 chore: update fr translation 2022-08-24 21:29:22 +02:00
Florian HENRY
1f6f2747d4 chore: update fr translation 2022-08-24 21:20:23 +02:00
Florian HENRY
264f98af14 chore: update french translation 2022-08-24 15:52:00 +02:00
Suraj Shetty
122f1c0ced fix: Explicitly commit "log_error" since its getting called during GET request (#31952) 2022-08-24 18:24:39 +05:30
Rohit Waghchaure
f9a7b31b5b fix: Purposes not set 2022-08-24 17:16:01 +05:30
ruthra kumar
36f5883dda test: payments against so/po will show up as outstanding amount
1. Class will use FrappeTestCase fixture
2. setup and teardown methods are introduced
3. test for payments against SO
2022-08-24 13:59:42 +05:30
Solufyin
0e26df331c fix: Route condition set for stock ledger (#31935) 2022-08-24 13:28:55 +05:30
Nabin Hait
b4a2eb2e65 fix: gl entries for asset repair 2022-08-24 12:29:15 +05:30
ruthra kumar
fdd167cac1 fix: include payment against PO in AR/AP report 2022-08-24 12:24:55 +05:30
HENRY Florian
fe73d55f70 chore: add Work Order test dependencies (#31936) 2022-08-23 16:07:10 +05:30
ruthra kumar
277ef04b60 test: remove discount accounting tests 2022-08-23 15:17:27 +05:30
ruthra kumar
a956e20f29 refactor: disable discount accounting on Buying module(PI) 2022-08-23 11:36:00 +05:30
Deepesh Garg
9fd0c25c9f Merge pull request #31910 from deepeshgarg007/cash_and_non_trade_discount_fix
fix: Cash and non trade discount calculation
2022-08-23 10:19:09 +05:30
Deepesh Garg
1cb7ae16ab chore: Linting issues 2022-08-23 09:12:20 +05:30
Sagar Sharma
2effbb55ae test: Add test case for Subcontracting Receipt GL Entries 2022-08-22 22:14:56 +05:30
Sagar Sharma
bf5c43322a fix: don't allow to create SCR directly (#31924) 2022-08-22 18:36:42 +05:30
Sagar Sharma
e888639c7e fix: Subcontracting Receipt GL Entries 2022-08-22 10:48:21 +05:30
Deepesh Garg
8cb7567fd3 Merge pull request #31914 from frappe/mergify/bp/develop/pr-31894
fix: TDS calculation for advance payment (backport #31894)
2022-08-22 10:31:30 +05:30
Maharshi Patel
42de9ca49e fix: TDS calculation for advance payment
"against_voucher": ["is", "not set"] was used in query due to which if TDS was added on "advance" payment vouchers and then reconciled against purchase invoice. it will not find those vouchers and consider this as first-time threshold due to which it will calculate Tax for all transactions.

(cherry picked from commit a452143782)
2022-08-22 03:29:46 +00:00
Deepesh Garg
ae3dce0cbd fix: Test cases 2022-08-22 08:57:58 +05:30
Sagar Sharma
f4673941e0 chore: move function "add_gl_entry" from purchase_receipt.py to stock_controller.py 2022-08-21 21:26:06 +05:30
Deepesh Garg
3b15966cc9 fix: Cash and non trade discount calculation 2022-08-21 17:51:05 +05:30
Sagar Sharma
520306dc87 fix: Add docstatus filter for voucher_no in Repost Item Valuation 2022-08-21 12:09:08 +05:30
Sagar Sharma
588ca68171 fix: make rate field read-only in subcontracting receipt item (#31905) 2022-08-20 17:50:47 +05:30
Sagar Sharma
3b51874da5 Merge pull request #31899 from s-aga-r/subcontracting-receipt/reposting
fix: repost item valuation for subcontracting receipt
2022-08-19 22:01:22 +05:30
Sagar Sharma
f92f3e0208 chore: add option for "Subcontracting Receipt" in "Voucher Type" 2022-08-19 20:52:26 +05:30
Sagar Sharma
f8c11847bb chore: allow subcontracting receipt backdated entry 2022-08-19 20:44:13 +05:30
Sagar Sharma
1d28ea5458 Merge pull request #31890 from s-aga-r/fix/subcontracting/additional-cost
fix: additional-costs in SCO and SCR
2022-08-19 15:26:00 +05:30
Sagar Sharma
dd719099bc Merge branch 'develop' into fix/subcontracting/additional-cost 2022-08-19 11:47:23 +05:30
Sagar Sharma
c247cf728c chore: add test for additional-cost 2022-08-19 11:46:36 +05:30
Sagar Sharma
addd7347d8 fix: test "test_pending_and_received_qty" 2022-08-19 11:46:27 +05:30
Saqib Ansari
756fe4b375 fix(pos): edge case while closing pos (#31748)
* fix(pos): edge case while closing pos

* fix: linter

* fix: setting posting_time in pos invoice merge log
2022-08-19 10:22:00 +05:30
Sagar Vora
aafb735283 perf: use create_custom_fields (#31853)
* perf: use `create_custom_fields`

* fix: default must be a string
2022-08-18 21:01:20 +05:30
Sagar Sharma
256b4245d5 chore: add additional-cost table in SCR 2022-08-18 20:59:30 +05:30
Sagar Sharma
2fc6833684 fix: recalculate rate of items based on "Recalculate Rate" checkbox 2022-08-18 19:50:00 +05:30
Sagar Sharma
7e88eb549f chore: remove unwanted field "provisional_expense_account" from SCR (#31847) 2022-08-18 17:39:00 +05:30
Sagar Sharma
ea82fe5bc2 chore: move "set_missing_values_in_additional_costs" from SCO to SC" 2022-08-18 17:20:22 +05:30
Sagar Sharma
eabd3135f0 fix: base_amount and exchange_rate in additional-cost table 2022-08-18 17:16:29 +05:30
Sagar Sharma
d7ed4093d8 fix: additional-cost in items table 2022-08-18 16:45:11 +05:30
ruthra kumar
72a7ed5b58 Merge pull request #31871 from ruthra-kumar/fix_gross_profit_valuation_rate
fix: incorrect buying amount in Gross Profit rpt
2022-08-18 16:08:19 +05:30
Deepesh Garg
86bdddd1b8 Merge pull request #31875 from adityahase/fix-projects-typo
fix(projects): Add missing comma
2022-08-18 11:18:51 +05:30
Deepesh Garg
1a6508972e fix: Make expense account editable in Purchase Receipt Item (#31730)
Co-authored-by: Sagar Sharma <sagarsharma.s312@gmail.com>
2022-08-18 10:59:39 +05:30
Sagar Sharma
8704ca783d fix: Add dimension section in subcontracting doctypes (#31849) 2022-08-18 10:58:33 +05:30
Aditya Hase
d38778e400 fix(projects): Add missing comma
Added with https://github.com/frappe/erpnext/pull/31360
2022-08-17 18:21:43 +05:30
Sagar Sharma
f1a612245c fix: Transit filter for Default Target Warehouse in SE (#31839) 2022-08-17 16:44:12 +05:30
ruthra kumar
967dd398e7 fix: incorrect buying amount in Gross Profit rpt 2022-08-17 16:21:03 +05:30
Sagar Sharma
2d04e71412 fix: Make expense account editable in Subcontracting Receipt Item (#31848) 2022-08-17 15:57:41 +05:30
rohitwaghchaure
396667b702 Merge pull request #31860 from rohitwaghchaure/delete-custom-fields-on-dimension-delete
fix: delete custom fields on deletion of inventory dimension
2022-08-17 15:43:54 +05:30
ruthra kumar
ea84c157e0 Merge pull request #31856 from ruthra-kumar/incorrect_tax_due_to_exchange_rate
fix: incorrect tax amt due to different exchange rate in PR and PI
2022-08-17 15:05:57 +05:30
Rohit Waghchaure
0b39a0123e fix: delete custom fields on deletion of inventory dimension 2022-08-17 14:55:02 +05:30
rohitwaghchaure
dd08045f28 Merge pull request #31863 from rohitwaghchaure/allow-to-make-material-issue
fix: not able to issue expired batches
2022-08-17 14:45:14 +05:30
Rohit Waghchaure
795c94384a fix: not able to issue expired batches 2022-08-17 14:03:55 +05:30
Sagar Sharma
313625c349 fix: incorrect rate in BOM exploded items (#31513) 2022-08-17 13:51:53 +05:30
Sagar Sharma
538cd6fdcf fix: incorrect produced-qty in production-plan-item (#31706) 2022-08-17 13:01:56 +05:30
ruthra kumar
5fd0770372 fix: incorrect tax amt due to different exchange rate in PR and PI 2022-08-16 16:41:33 +05:30
ruthra kumar
3b4c0a3fc0 fix(minor): don't print tax rate if its '0' (#31838) 2022-08-16 16:35:46 +05:30
hrzzz
3ef551872a fix: remove spaces and order import 2022-08-15 09:23:56 -03:00
hrzzz
27891ecb77 feat: two new filters for gross profit 2022-08-15 09:14:23 -03:00
Sagar Sharma
0047e18a9b fix: check item_code in all rows of po_items (#31741)
fix: check item-code in each row of po-items
2022-08-13 11:07:22 +05:30
Sagar Sharma
e5e88bb9f1 fix: contact search in request for quotation (#31828) 2022-08-13 11:05:48 +05:30
Deepesh Garg
4ff1cba522 Merge pull request #31830 from deepeshgarg007/fees_payment
fix: Unable to make payment entry against Fees using education app
2022-08-11 20:46:26 +05:30
Deepesh Garg
79ac50d0f7 fix: Unable to make payment entry against Fees using education app 2022-08-11 19:31:31 +05:30
Deepesh Garg
72869ed197 Merge pull request #31799 from abhinavxd/fix-process-loan-interest-accrual
fix: process loan interest accrual
2022-08-11 15:47:18 +05:30
ruthra kumar
5018472840 Merge pull request #31817 from ruthra-kumar/fix_pos_recent_order_crash_due_to_large_data
fix: limit pos recent order page result
2022-08-10 15:48:28 +05:30
Saqib Ansari
33762dbbac fix(pos): error while consolidating pos invoices 2022-08-10 14:17:28 +05:30
Nabin Hait
eb25eddc22 Merge pull request #31816 from nabinhait/crm-no-of-employees
fix: limited options for no-of-employees in the crm documents
2022-08-09 20:47:52 +05:30
Nabin Hait
909945c0ac fix: map old data as per new options of no-of-employees 2022-08-09 20:47:18 +05:30
ruthra kumar
bb40e38451 fix: limit pos recent order page result 2022-08-09 19:35:43 +05:30
Nabin Hait
7ecd67605f fix: limited options for no-of-employees in crm 2022-08-09 19:06:57 +05:30
Ankush Menat
08d7c48dc7 refactor: use browser native lazy loading (#31814) 2022-08-09 18:49:14 +05:30
Akash Krishna
32b30bc5de Tds report (#31801)
* fix: TDS Computation Summary Report not loading, too many values to unpack
2022-08-09 17:41:02 +05:30
Sagar Vora
a2252c9236 ci: ensure unique group ID to prevent workflows from getting cancelled (#31806)
ci: ensure unique group ID to prevent workflows from cancelling
2022-08-09 17:19:48 +05:30
rohitwaghchaure
e93a1cc02e Merge pull request #31804 from rohitwaghchaure/fixed-incorret-incoming-rate-for-internal-suppliier
fix: incorrect incoming rate set for inter transfer purchase receipt
2022-08-09 16:00:31 +05:30
Raffael Meyer
6b510546ae fix: german translations (#31732) 2022-08-09 15:11:52 +05:30
Rohit Waghchaure
ddd24ea8c8 fix: incorrect incoming rate set for inter transfer purchase receipt 2022-08-09 14:50:20 +05:30
Abhinav Raut
534d7ce64b fix: term loan interest calculation 2022-08-08 17:35:31 +05:30
Deepesh Garg
5c4cc5ae5b Merge pull request #31779 from ruthra-kumar/bug_add_accouting_dimension_in_asset_repair
Bug add accouting dimension in asset repair
2022-08-08 16:39:21 +05:30
Abhinav Raut
9ef8d5c5c3 fix: process loan interest accrual 2022-08-08 16:29:13 +05:30
Deepesh Garg
b85dbdc3c1 Merge pull request #31777 from ruthra-kumar/intercompany_po_bug
fix: intercompany SO created from Purchase Order throws exception
2022-08-08 16:06:09 +05:30
Deepesh Garg
e5a68b2dcb Merge pull request #31733 from resilient-tech/fix-party-details
fix: set `billing_address` for purchases in `get_party_details`
2022-08-08 13:00:02 +05:30
Sagar Vora
d05082987f fix: set company_address for purchases in party.js 2022-08-08 06:04:10 +00:00
Sagar Vora
a3625b3817 fix: set billing_address for purchases in get_party_details 2022-08-08 06:04:10 +00:00
Deepesh Garg
03002f7431 Merge pull request #31780 from abhinavxd/fix-loan-pending-principal
Fix: Loan pending principal amount
2022-08-05 16:04:30 +05:30
ruthra kumar
80f508c4b1 chore: patch for creating existing dimensions in asset repair 2022-08-05 15:22:38 +05:30
Abhinav Raut
a272d73dd9 fix: pending principal- amount 2022-08-04 19:04:34 +05:30
ruthra kumar
452584c4bd fix: add asset repair to accounting dimension list 2022-08-04 14:09:26 +05:30
ruthra kumar
c95b986414 Merge pull request #31737 from ruthra-kumar/fix_invoice_outstanding_in_reconciliation_tool
fix: incorrect invoice outstanding in reconciliation tool
2022-08-04 14:07:15 +05:30
ruthra kumar
af0a353b79 fix: intercompany SO throws exception 2022-08-04 14:01:23 +05:30
ruthra kumar
ef312b8fc4 test: posting_date should not affect outstanding amount calculation 2022-08-04 09:38:01 +05:30
ruthra kumar
5f1562c5b2 fix: posting_date of linked vouchers should not affect outstanding
posting_date filter should not be applied for linked vouchers.
2022-08-04 09:38:01 +05:30
hrzzz
91762097a5 fix: for Tree Type item and item group show net amout 2022-08-03 13:09:23 -03:00
Ankush Menat
17b9bfd249 fix(ecommerce): remove query to non-existing field (#31771) 2022-08-03 16:48:27 +05:30
HarryPaulo
ea88451875 fix: getting error to show sales invoice group or print rep… (#31756)
fix: formatter getting error to show sales invoice group or print report.

1 - When I view the Gross Profit report in Sales Invoice mode, the table is all broken.
Error on browser console:
TypeError: Cannot read properties of undefined (reading 'indent')

2 - When I try to print, no matter the Group (Sales Invoice, Item Code, Item Group...) nothing happens. in browser log console I have the following error:
TypeError: Cannot read properties of undefined (reading 'content')

i fixed both errors and all working perfectly.
2022-08-03 11:21:30 +05:30
Devin Slauenwhite
9c580dde39 fix: linter (#31763) 2022-08-03 11:16:59 +05:30
Sagar Vora
9baa222976 fix: specify allowed doctype in queries (#31761) 2022-08-03 11:12:30 +05:30
Ankush Menat
0ef9c03f05 chore: CODEOWNERS
[skip ci]
2022-08-02 16:13:51 +05:30
1880 changed files with 100852 additions and 105535 deletions

View File

@@ -9,13 +9,6 @@ trim_trailing_whitespace = true
charset = utf-8
# python, js indentation settings
[{*.py,*.js,*.vue,*.css,*.scss,*.html}]
[{*.py,*.js}]
indent_style = tab
indent_size = 4
max_line_length = 110
# JSON files - mostly doctype schema files
[{*.json}]
insert_final_newline = false
indent_style = space
indent_size = 2

View File

@@ -156,7 +156,6 @@
"onScan": true,
"html2canvas": true,
"extend_cscript": true,
"localforage": true,
"Plaid": true
"localforage": true
}
}

View File

@@ -28,7 +28,4 @@ b147b85e6ac19a9220cd1e2958a6ebd99373283a
494bd9ef78313436f0424b918f200dab8fc7c20b
# bulk format python code with black
baec607ff5905b1c67531096a9cf50ec7ff00a5d
# ruff
4d34b1ead73baf4c5430a2ecbe44b9e8468d7626
baec607ff5905b1c67531096a9cf50ec7ff00a5d

View File

@@ -66,8 +66,7 @@ ignore =
F841,
E713,
E712,
B023,
B028
B023
max-line-length = 200

View File

@@ -3,72 +3,52 @@ import requests
from urllib.parse import urlparse
WEBSITE_REPOS = [
docs_repos = [
"frappe_docs",
"erpnext_documentation",
"erpnext_com",
"frappe_io",
]
DOCUMENTATION_DOMAINS = [
"docs.erpnext.com",
"docs.frappe.io",
"frappeframework.com",
]
def uri_validator(x):
result = urlparse(x)
return all([result.scheme, result.netloc, result.path])
def is_valid_url(url: str) -> bool:
parts = urlparse(url)
return all((parts.scheme, parts.netloc, parts.path))
def is_documentation_link(word: str) -> bool:
if not word.startswith("http") or not is_valid_url(word):
return False
parsed_url = urlparse(word)
if parsed_url.netloc in DOCUMENTATION_DOMAINS:
return True
if parsed_url.netloc == "github.com":
parts = parsed_url.path.split("/")
if len(parts) == 5 and parts[1] == "frappe" and parts[2] in WEBSITE_REPOS:
return True
return False
def contains_documentation_link(body: str) -> bool:
return any(
is_documentation_link(word)
for line in body.splitlines()
for word in line.split()
)
def check_pull_request(number: str) -> "tuple[int, str]":
response = requests.get(f"https://api.github.com/repos/frappe/erpnext/pulls/{number}")
if not response.ok:
return 1, "Pull Request Not Found! ⚠️"
payload = response.json()
title = (payload.get("title") or "").lower().strip()
head_sha = (payload.get("head") or {}).get("sha")
body = (payload.get("body") or "").lower()
if (
not title.startswith("feat")
or not head_sha
or "no-docs" in body
or "backport" in body
):
return 0, "Skipping documentation checks... 🏃"
if contains_documentation_link(body):
return 0, "Documentation Link Found. You're Awesome! 🎉"
return 1, "Documentation Link Not Found! ⚠️"
def docs_link_exists(body):
for line in body.splitlines():
for word in line.split():
if word.startswith('http') and uri_validator(word):
parsed_url = urlparse(word)
if parsed_url.netloc == "github.com":
parts = parsed_url.path.split('/')
if len(parts) == 5 and parts[1] == "frappe" and parts[2] in docs_repos:
return True
elif parsed_url.netloc == "docs.erpnext.com":
return True
if __name__ == "__main__":
exit_code, message = check_pull_request(sys.argv[1])
print(message)
sys.exit(exit_code)
pr = sys.argv[1]
response = requests.get("https://api.github.com/repos/frappe/erpnext/pulls/{}".format(pr))
if response.ok:
payload = response.json()
title = (payload.get("title") or "").lower().strip()
head_sha = (payload.get("head") or {}).get("sha")
body = (payload.get("body") or "").lower()
if (title.startswith("feat")
and head_sha
and "no-docs" not in body
and "backport" not in body
):
if docs_link_exists(body):
print("Documentation Link Found. You're Awesome! 🎉")
else:
print("Documentation Link Not Found! ⚠️")
sys.exit(1)
else:
print("Skipping documentation checks... 🏃")

View File

@@ -8,9 +8,8 @@ sudo apt update && sudo apt install redis-server libcups2-dev
pip install frappe-bench
githubbranch=${GITHUB_BASE_REF:-${GITHUB_REF##*/}}
frappeuser=${FRAPPE_USER:-"frappe"}
frappebranch=${FRAPPE_BRANCH:-$githubbranch}
frappebranch=${FRAPPE_BRANCH:-${GITHUB_BASE_REF:-${GITHUB_REF##*/}}}
git clone "https://github.com/${frappeuser}/frappe" --branch "${frappebranch}" --depth 1
bench init --skip-assets --frappe-path ~/frappe --python "$(which python)" frappe-bench
@@ -25,15 +24,14 @@ fi
if [ "$DB" == "mariadb" ];then
mysql --host 127.0.0.1 --port 3306 -u root -e "SET GLOBAL character_set_server = 'utf8mb4'"
mysql --host 127.0.0.1 --port 3306 -u root -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'"
mysql --host 127.0.0.1 --port 3306 -u root -proot -e "SET GLOBAL character_set_server = 'utf8mb4'"
mysql --host 127.0.0.1 --port 3306 -u root -proot -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'"
mysql --host 127.0.0.1 --port 3306 -u root -e "CREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe'"
mysql --host 127.0.0.1 --port 3306 -u root -e "CREATE DATABASE test_frappe"
mysql --host 127.0.0.1 --port 3306 -u root -e "GRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost'"
mysql --host 127.0.0.1 --port 3306 -u root -proot -e "CREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe'"
mysql --host 127.0.0.1 --port 3306 -u root -proot -e "CREATE DATABASE test_frappe"
mysql --host 127.0.0.1 --port 3306 -u root -proot -e "GRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost'"
mysql --host 127.0.0.1 --port 3306 -u root -e "UPDATE mysql.user SET Password=PASSWORD('travis') WHERE User='root'"
mysql --host 127.0.0.1 --port 3306 -u root -e "FLUSH PRIVILEGES"
mysql --host 127.0.0.1 --port 3306 -u root -proot -e "FLUSH PRIVILEGES"
fi
if [ "$DB" == "postgres" ];then
@@ -57,7 +55,7 @@ sed -i 's/schedule:/# schedule:/g' Procfile
sed -i 's/socketio:/# socketio:/g' Procfile
sed -i 's/redis_socketio:/# redis_socketio:/g' Procfile
bench get-app payments --branch ${githubbranch%"-hotfix"}
bench get-app payments
bench get-app erpnext "${GITHUB_WORKSPACE}"
if [ "$TYPE" == "server" ]; then bench setup requirements --dev; fi

View File

@@ -9,8 +9,8 @@
"mail_password": "test",
"admin_password": "admin",
"root_login": "root",
"root_password": "travis",
"root_password": "root",
"host_name": "http://test_site:8000",
"install_apps": ["payments", "erpnext"],
"install_apps": ["erpnext"],
"throttle_user_limit": 100
}

4
.github/release.yml vendored
View File

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

2
.github/stale.yml vendored
View File

@@ -13,7 +13,7 @@ exemptProjects: true
exemptMilestones: true
pulls:
daysUntilStale: 14
daysUntilStale: 15
daysUntilClose: 3
exemptLabels:
- hotfix

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:
release:
name: Release
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
version: ["13", "14"]
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

@@ -9,22 +9,21 @@ jobs:
name: linters
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
- name: Set up Python 3.10
uses: actions/setup-python@v4
uses: actions/setup-python@v2
with:
python-version: '3.10'
cache: pip
- name: Install and Run Pre-commit
uses: pre-commit/action@v3.0.0
uses: pre-commit/action@v2.0.3
- name: Download Semgrep rules
run: git clone --depth 1 https://github.com/frappe/semgrep-rules.git frappe-semgrep-rules
- name: Download semgrep
run: pip install semgrep
run: pip install semgrep==0.97.0
- name: Run Semgrep rules
run: semgrep ci --config ./frappe-semgrep-rules/rules --config r/python.lang.correctness

View File

@@ -11,12 +11,12 @@ on:
workflow_dispatch:
concurrency:
group: patch-develop-${{ github.event.number }}
group: patch-develop-${{ github.event_name }}-${{ github.event.number || github.event_name == 'workflow_dispatch' && github.run_id || '' }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
timeout-minutes: 60
name: Patch Test
@@ -25,7 +25,7 @@ jobs:
mysql:
image: mariadb:10.3
env:
MYSQL_ALLOW_EMPTY_PASSWORD: YES
MARIADB_ROOT_PASSWORD: 'root'
ports:
- 3306:3306
options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
@@ -43,11 +43,9 @@ jobs:
fi
- name: Setup Python
uses: "actions/setup-python@v4"
uses: "gabrielfalcao/pyenv-action@v9"
with:
python-version: |
3.7
3.10
versions: 3.10:latest, 3.7:latest
- name: Setup Node
uses: actions/setup-node@v2
@@ -59,7 +57,7 @@ jobs:
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
- name: Cache pip
uses: actions/cache@v4
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml') }}
@@ -68,7 +66,7 @@ jobs:
${{ runner.os }}-
- name: Cache node modules
uses: actions/cache@v4
uses: actions/cache@v2
env:
cache-name: cache-node-modules
with:
@@ -83,7 +81,7 @@ jobs:
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v4
- uses: actions/cache@v2
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
@@ -94,6 +92,7 @@ jobs:
- name: Install
run: |
pip install frappe-bench
pyenv global $(pyenv versions | grep '3.10')
bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
env:
DB: mariadb
@@ -108,6 +107,7 @@ jobs:
git -C "apps/frappe" remote set-url upstream https://github.com/frappe/frappe.git
git -C "apps/erpnext" remote set-url upstream https://github.com/frappe/erpnext.git
pyenv global $(pyenv versions | grep '3.7')
for version in $(seq 12 13)
do
echo "Updating to v$version"
@@ -120,7 +120,7 @@ jobs:
git -C "apps/erpnext" checkout -q -f $branch_name
rm -rf ~/frappe-bench/env
bench setup env --python python3.7
bench setup env
bench pip install -e ./apps/payments
bench pip install -e ./apps/erpnext
@@ -132,8 +132,9 @@ jobs:
git -C "apps/frappe" checkout -q -f "${GITHUB_BASE_REF:-${GITHUB_REF##*/}}"
git -C "apps/erpnext" checkout -q -f "$GITHUB_SHA"
pyenv global $(pyenv versions | grep '3.10')
rm -rf ~/frappe-bench/env
bench -v setup env --python python3.10
bench -v setup env
bench pip install -e ./apps/payments
bench pip install -e ./apps/erpnext

View File

@@ -2,7 +2,7 @@ name: Generate Semantic Release
on:
push:
branches:
- version-14
- version-13
jobs:
release:
name: Release
@@ -13,12 +13,10 @@ jobs:
with:
fetch-depth: 0
persist-credentials: false
- name: Setup Node.js
- name: Setup Node.js v14
uses: actions/setup-node@v2
with:
node-version: 20
node-version: 14
- name: Setup dependencies
run: |
npm install @semantic-release/git @semantic-release/exec --no-save
@@ -30,4 +28,4 @@ jobs:
GIT_AUTHOR_EMAIL: "developers@frappe.io"
GIT_COMMITTER_NAME: "Frappe PR Bot"
GIT_COMMITTER_EMAIL: "developers@frappe.io"
run: npx semantic-release
run: npx semantic-release

View File

@@ -1,38 +0,0 @@
# This action:
#
# 1. Generates release notes using github API.
# 2. Strips unnecessary info like chore/style etc from notes.
# 3. Updates release info.
# This action needs to be maintained on all branches that do releases.
name: 'Release Notes'
on:
workflow_dispatch:
inputs:
tag_name:
description: 'Tag of release like v13.0.0'
required: true
type: string
release:
types: [released]
permissions:
contents: read
jobs:
regen-notes:
name: 'Regenerate release notes'
runs-on: ubuntu-latest
steps:
- name: Update notes
run: |
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' )
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"
env:
GH_TOKEN: ${{ secrets.RELEASE_TOKEN }}
RELEASE_TAG: ${{ github.event.inputs.tag_name || github.event.release.tag_name }}

View File

@@ -21,7 +21,7 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: 20
node-version: 14
check-latest: true
- name: Check commit titles

View File

@@ -27,7 +27,7 @@ on:
type: string
concurrency:
group: server-mariadb-develop-${{ github.event.number }}
group: server-mariadb-develop-${{ github.event_name }}-${{ github.event.number || github.event_name == 'workflow_dispatch' && github.run_id || '' }}
cancel-in-progress: true
jobs:
@@ -39,15 +39,15 @@ jobs:
fail-fast: false
matrix:
container: [1, 2, 3]
container: [1, 2, 3, 4]
name: Python Unit Tests
services:
mysql:
image: mariadb:10.3
image: mariadb:10.6
env:
MYSQL_ALLOW_EMPTY_PASSWORD: YES
MARIADB_ROOT_PASSWORD: 'root'
ports:
- 3306:3306
options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
@@ -59,7 +59,7 @@ jobs:
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.10'
python-version: '3.11'
- name: Check for valid Python & Merge Conflicts
run: |
@@ -79,7 +79,7 @@ jobs:
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
- name: Cache pip
uses: actions/cache@v4
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml') }}
@@ -88,7 +88,7 @@ jobs:
${{ runner.os }}-
- name: Cache node modules
uses: actions/cache@v4
uses: actions/cache@v2
env:
cache-name: cache-node-modules
with:
@@ -103,7 +103,7 @@ jobs:
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v4
- uses: actions/cache@v2
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
@@ -120,7 +120,32 @@ jobs:
FRAPPE_BRANCH: ${{ github.event.inputs.branch }}
- name: Run Tests
run: 'cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --app erpnext --total-builds 3 --build-number ${{ matrix.container }}'
run: 'cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --app erpnext --with-coverage --total-builds 4 --build-number ${{ matrix.container }}'
env:
TYPE: server
CI_BUILD_ID: ${{ github.run_id }}
ORCHESTRATOR_URL: http://test-orchestrator.frappe.io
- name: Upload coverage data
uses: actions/upload-artifact@v3
with:
name: coverage-${{ matrix.container }}
path: /home/runner/frappe-bench/sites/coverage.xml
coverage:
name: Coverage Wrap Up
needs: test
runs-on: ubuntu-latest
steps:
- name: Clone
uses: actions/checkout@v2
- name: Download artifacts
uses: actions/download-artifact@v3
- name: Upload coverage data
uses: codecov/codecov-action@v2
with:
name: MariaDB
fail_ci_if_error: true
verbose: true

View File

@@ -9,7 +9,7 @@ on:
types: [opened, labelled, synchronize, reopened]
concurrency:
group: server-postgres-develop-${{ github.event.number }}
group: server-postgres-develop-${{ github.event_name }}-${{ github.event.number || github.event_name == 'workflow_dispatch' && github.run_id || '' }}
cancel-in-progress: true
jobs:
@@ -66,7 +66,7 @@ jobs:
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
- name: Cache pip
uses: actions/cache@v4
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml') }}
@@ -75,7 +75,7 @@ jobs:
${{ runner.os }}-
- name: Cache node modules
uses: actions/cache@v4
uses: actions/cache@v2
env:
cache-name: cache-node-modules
with:
@@ -90,7 +90,7 @@ jobs:
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v4
- uses: actions/cache@v2
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}

View File

@@ -9,6 +9,7 @@ pull_request_rules:
- author!=nabinhait
- author!=ankush
- author!=deepeshgarg007
- author!=frappe-pr-bot
- author!=mergify[bot]
- or:

View File

@@ -1,11 +1,11 @@
exclude: 'node_modules|.git'
default_stages: [pre-commit]
default_stages: [commit]
fail_fast: false
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
rev: v4.0.1
hooks:
- id: trailing-whitespace
files: "erpnext.*"
@@ -15,68 +15,29 @@ repos:
args: ['--branch', 'develop']
- id: check-merge-conflict
- id: check-ast
- id: check-json
- id: check-toml
- id: check-yaml
- id: debug-statements
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.7.1
- repo: https://github.com/PyCQA/flake8
rev: 5.0.4
hooks:
- id: prettier
types_or: [javascript, vue, scss]
# Ignore any files that might contain jinja / bundles
exclude: |
(?x)^(
erpnext/public/dist/.*|
cypress/.*|
.*node_modules.*|
.*boilerplate.*|
erpnext/public/js/controllers/.*|
erpnext/templates/pages/order.js|
erpnext/templates/includes/.*|
.*/supplier_quotation.js|
.*/sales_taxes_and_charges_template.js|
.*/purchase_taxes_and_charges_template.js|
.*/subcontracting_order.js|
.*/landed_cost_voucher.js|
.*/payment_entry.js|
.*/loan_interest_accrual.js|
.*/loan_disbursement.js|
.*/loan_application.js|
.*/italy.js|
.*/sales_invoice.js|
.*/subcontracting_receipt.js|
.*/request_for_quotation.js|
.*/pos_profile.js|
.*/opportunity.js|
.*/quotation.js|
.*/sales_common.js|
.*/sales_order.js|
.*/pos_invoice.js|
.*/purchase_invoice.js|
.*/loan_repayment.js|
.*/material_request.js|
.*/purchase_receipt.js|
.*/delivery_note.js|
.*/loan.js|
.*/stock_entry.js|
.*/purchase_order.js|
.*/loan_write_off.js
)$
- id: flake8
additional_dependencies: [
'flake8-bugbear',
]
args: ['--config', '.github/helper/.flake8_strict']
exclude: ".*setup.py$"
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.2.0
- repo: https://github.com/adityahase/black
rev: 9cb0a69f4d0030cdf687eddf314468b39ed54119
hooks:
- id: ruff
name: "Run ruff import sorter"
args: ["--select=I", "--fix"]
- id: black
additional_dependencies: ['click==8.0.4']
- id: ruff
name: "Run ruff linter"
- repo: https://github.com/timothycrosley/isort
rev: 5.9.1
hooks:
- id: isort
exclude: ".*setup.py$"
- id: ruff-format
name: "Run ruff formatter"
ci:
autoupdate_schedule: weekly

View File

@@ -1,5 +1,5 @@
{
"branches": ["version-14"],
"branches": ["version-13"],
"plugins": [
"@semantic-release/commit-analyzer", {
"preset": "angular",
@@ -10,7 +10,7 @@
"@semantic-release/release-notes-generator",
[
"@semantic-release/exec", {
"prepareCmd": 'sed -ir -E "s/\"[0-9]+\.[0-9]+\.[0-9]+\"/\"${nextRelease.version}\"/" erpnext/__init__.py'
"prepareCmd": 'sed -ir "s/[0-9]*\.[0-9]*\.[0-9]*/${nextRelease.version}/" erpnext/__init__.py'
}
],
[
@@ -21,4 +21,4 @@
],
"@semantic-release/github"
]
}
}

View File

@@ -3,23 +3,26 @@
# These owners will be the default owners for everything in
# the repo. Unless a later match takes precedence,
erpnext/accounts/ @deepeshgarg007 @ruthra-kumar
erpnext/assets/ @khushi8112 @deepeshgarg007
erpnext/loan_management/ @deepeshgarg007
erpnext/regional @deepeshgarg007 @ruthra-kumar
erpnext/selling @deepeshgarg007 @ruthra-kumar
erpnext/support/ @deepeshgarg007
pos*
erpnext/accounts/ @nextchamp-saqib @deepeshgarg007 @ruthra-kumar
erpnext/assets/ @nextchamp-saqib @deepeshgarg007 @ruthra-kumar
erpnext/loan_management/ @nextchamp-saqib @deepeshgarg007
erpnext/regional @nextchamp-saqib @deepeshgarg007 @ruthra-kumar
erpnext/selling @nextchamp-saqib @deepeshgarg007 @ruthra-kumar
erpnext/support/ @nextchamp-saqib @deepeshgarg007
pos* @nextchamp-saqib
erpnext/buying/ @rohitwaghchaure
erpnext/maintenance/ @rohitwaghchaure
erpnext/manufacturing/ @rohitwaghchaure
erpnext/quality_management/ @rohitwaghchaure
erpnext/stock/ @rohitwaghchaure
erpnext/subcontracting @rohitwaghchaure
erpnext/buying/ @rohitwaghchaure @s-aga-r
erpnext/maintenance/ @rohitwaghchaure @s-aga-r
erpnext/manufacturing/ @rohitwaghchaure @s-aga-r
erpnext/quality_management/ @rohitwaghchaure @s-aga-r
erpnext/stock/ @rohitwaghchaure @s-aga-r
erpnext/controllers/ @deepeshgarg007 @rohitwaghchaure
erpnext/patches/ @deepeshgarg007
erpnext/crm/ @NagariaHussain
erpnext/education/ @rutwikhdev
erpnext/projects/ @ruchamahabal
.github/ @deepeshgarg007
pyproject.toml @akhilnarang
erpnext/controllers/ @deepeshgarg007 @nextchamp-saqib @rohitwaghchaure
erpnext/patches/ @deepeshgarg007 @nextchamp-saqib
.github/ @ankush
pyproject.toml @ankush

View File

@@ -1,13 +1,25 @@
module.exports = {
parserPreset: "conventional-changelog-conventionalcommits",
parserPreset: 'conventional-changelog-conventionalcommits',
rules: {
"subject-empty": [2, "never"],
"type-case": [2, "always", "lower-case"],
"type-empty": [2, "never"],
"type-enum": [
'subject-empty': [2, 'never'],
'type-case': [2, 'always', 'lower-case'],
'type-empty': [2, 'never'],
'type-enum': [
2,
"always",
["build", "chore", "ci", "docs", "feat", "fix", "perf", "refactor", "revert", "style", "test"],
'always',
[
'build',
'chore',
'ci',
'docs',
'feat',
'fix',
'perf',
'refactor',
'revert',
'style',
'test',
],
],
},
};

View File

@@ -1,9 +1,8 @@
import functools
import inspect
import frappe
__version__ = "14.86.2"
__version__ = "14.0.0-dev"
def get_default_company(user=None):
@@ -13,7 +12,7 @@ def get_default_company(user=None):
if not user:
user = frappe.session.user
companies = get_user_default_as_list("company", user)
companies = get_user_default_as_list(user, "company")
if companies:
default_company = companies[0]
else:
@@ -36,8 +35,10 @@ def get_default_cost_center(company):
if not frappe.flags.company_cost_center:
frappe.flags.company_cost_center = {}
if company not in frappe.flags.company_cost_center:
frappe.flags.company_cost_center[company] = frappe.get_cached_value("Company", company, "cost_center")
if not company in frappe.flags.company_cost_center:
frappe.flags.company_cost_center[company] = frappe.get_cached_value(
"Company", company, "cost_center"
)
return frappe.flags.company_cost_center[company]
@@ -45,7 +46,7 @@ def get_company_currency(company):
"""Returns the default company currency"""
if not frappe.flags.company_currency:
frappe.flags.company_currency = {}
if company not in frappe.flags.company_currency:
if not company in frappe.flags.company_currency:
frappe.flags.company_currency[company] = frappe.db.get_value(
"Company", company, "default_currency", cache=True
)
@@ -79,7 +80,7 @@ def is_perpetual_inventory_enabled(company):
if not hasattr(frappe.local, "enable_perpetual_inventory"):
frappe.local.enable_perpetual_inventory = {}
if company not in frappe.local.enable_perpetual_inventory:
if not company in frappe.local.enable_perpetual_inventory:
frappe.local.enable_perpetual_inventory[company] = (
frappe.get_cached_value("Company", company, "enable_perpetual_inventory") or 0
)
@@ -94,7 +95,7 @@ def get_default_finance_book(company=None):
if not hasattr(frappe.local, "default_finance_book"):
frappe.local.default_finance_book = {}
if company not in frappe.local.default_finance_book:
if not company in frappe.local.default_finance_book:
frappe.local.default_finance_book[company] = frappe.get_cached_value(
"Company", company, "default_finance_book"
)
@@ -106,7 +107,7 @@ def get_party_account_type(party_type):
if not hasattr(frappe.local, "party_account_types"):
frappe.local.party_account_types = {}
if party_type not in frappe.local.party_account_types:
if not party_type in frappe.local.party_account_types:
frappe.local.party_account_types[party_type] = (
frappe.db.get_value("Party Type", party_type, "account_type") or ""
)
@@ -119,14 +120,12 @@ def get_region(company=None):
You can also set global company flag in `frappe.flags.company`
"""
if not company:
company = frappe.local.flags.company
if company:
return frappe.get_cached_value("Company", company, "country")
return frappe.flags.country or frappe.get_system_settings("country")
if company or frappe.flags.company:
return frappe.get_cached_value("Company", company or frappe.flags.company, "country")
elif frappe.flags.country:
return frappe.flags.country
else:
return frappe.get_system_settings("country")
def allow_regional(fn):
@@ -137,7 +136,6 @@ def allow_regional(fn):
def myfunction():
pass"""
@functools.wraps(fn)
def caller(*args, **kwargs):
overrides = frappe.get_hooks("regional_overrides", {}).get(get_region())
function_path = f"{inspect.getmodule(fn).__name__}.{fn.__name__}"

View File

@@ -11,14 +11,14 @@ class ERPNextAddress(Address):
def validate(self):
self.validate_reference()
self.update_compnay_address()
super().validate()
super(ERPNextAddress, self).validate()
def link_address(self):
"""Link address based on owner"""
if self.is_your_company_address:
return
return super().link_address()
return super(ERPNextAddress, self).link_address()
def update_compnay_address(self):
for link in self.get("links"):
@@ -26,11 +26,11 @@ class ERPNextAddress(Address):
self.is_your_company_address = 1
def validate_reference(self):
if self.is_your_company_address and not [row for row in self.links if row.link_doctype == "Company"]:
if self.is_your_company_address and not [
row for row in self.links if row.link_doctype == "Company"
]:
frappe.throw(
_(
"Address needs to be linked to a Company. Please add a row for Company in the Links table."
),
_("Address needs to be linked to a Company. Please add a row for Company in the Links table."),
title=_("Company Not Linked"),
)

View File

@@ -4,19 +4,18 @@
"creation": "2020-07-17 11:25:34.593061",
"docstatus": 0,
"doctype": "Dashboard Chart",
"dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"from_fiscal_year\":\"erpnext.utils.get_fiscal_year()\",\"to_fiscal_year\":\"erpnext.utils.get_fiscal_year()\"}",
"dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"from_fiscal_year\":\"frappe.sys_defaults.fiscal_year\",\"to_fiscal_year\":\"frappe.sys_defaults.fiscal_year\"}",
"filters_json": "{\"period\":\"Monthly\",\"budget_against\":\"Cost Center\",\"show_cumulative\":0}",
"idx": 0,
"is_public": 1,
"is_standard": 1,
"modified": "2023-07-19 13:13:13.307073",
"modified": "2020-07-22 12:24:49.144210",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Budget Variance",
"number_of_groups": 0,
"owner": "Administrator",
"report_name": "Budget Variance Report",
"roles": [],
"timeseries": 0,
"type": "Bar",
"use_report_chart": 1,

View File

@@ -4,19 +4,18 @@
"creation": "2020-07-17 11:25:34.448572",
"docstatus": 0,
"doctype": "Dashboard Chart",
"dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"from_fiscal_year\":\"erpnext.utils.get_fiscal_year()\",\"to_fiscal_year\":\"erpnext.utils.get_fiscal_year()\"}",
"dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"from_fiscal_year\":\"frappe.sys_defaults.fiscal_year\",\"to_fiscal_year\":\"frappe.sys_defaults.fiscal_year\"}",
"filters_json": "{\"filter_based_on\":\"Fiscal Year\",\"period_start_date\":\"2020-04-01\",\"period_end_date\":\"2021-03-31\",\"periodicity\":\"Yearly\",\"include_default_book_entries\":1}",
"idx": 0,
"is_public": 1,
"is_standard": 1,
"modified": "2023-07-19 13:08:56.470390",
"modified": "2020-07-22 12:33:48.888943",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Profit and Loss",
"number_of_groups": 0,
"owner": "Administrator",
"report_name": "Profit and Loss Statement",
"roles": [],
"timeseries": 0,
"type": "Bar",
"use_report_chart": 1,

View File

@@ -1,4 +1,4 @@
frappe.provide("frappe.dashboards.chart_sources");
frappe.provide('frappe.dashboards.chart_sources');
frappe.dashboards.chart_sources["Account Balance Timeline"] = {
method: "erpnext.accounts.dashboard_chart_source.account_balance_timeline.account_balance_timeline.get",
@@ -9,14 +9,14 @@ frappe.dashboards.chart_sources["Account Balance Timeline"] = {
fieldtype: "Link",
options: "Company",
default: frappe.defaults.get_user_default("Company"),
reqd: 1,
reqd: 1
},
{
fieldname: "account",
label: __("Account"),
fieldtype: "Link",
options: "Account",
reqd: 1,
reqd: 1
},
],
]
};

View File

@@ -37,7 +37,7 @@ def get(
filters = frappe.parse_json(filters) or frappe.parse_json(chart.filters_json)
account = filters.get("account")
filters.get("company")
company = filters.get("company")
if not account and chart_name:
frappe.throw(
@@ -76,13 +76,14 @@ def get(
def build_result(account, dates, gl_entries):
result = [[getdate(date), 0.0] for date in dates]
root_type = frappe.db.get_value("Account", account, "root_type")
root_type = frappe.get_cached_value("Account", account, "root_type")
# start with the first date
date_index = 0
# get balances in debit
for entry in gl_entries:
# entry date is after the current pointer, so move the pointer forward
while getdate(entry.posting_date) > result[date_index][0]:
date_index += 1
@@ -132,6 +133,8 @@ def get_dates_from_timegrain(from_date, to_date, timegrain):
dates = [get_period_ending(from_date, timegrain)]
while getdate(dates[-1]) < getdate(to_date):
date = get_period_ending(add_to_date(dates[-1], years=years, months=months, days=days), timegrain)
date = get_period_ending(
add_to_date(dates[-1], years=years, months=months, days=days), timegrain
)
dates.append(date)
return dates

View File

@@ -24,10 +24,14 @@ from erpnext.accounts.utils import get_account_currency
def validate_service_stop_date(doc):
"""Validates service_stop_date for Purchase Invoice and Sales Invoice"""
enable_check = "enable_deferred_revenue" if doc.doctype == "Sales Invoice" else "enable_deferred_expense"
enable_check = (
"enable_deferred_revenue" if doc.doctype == "Sales Invoice" else "enable_deferred_expense"
)
old_stop_dates = {}
old_doc = frappe.db.get_all(f"{doc.doctype} Item", {"parent": doc.name}, ["name", "service_stop_date"])
old_doc = frappe.db.get_all(
"{0} Item".format(doc.doctype), {"parent": doc.name}, ["name", "service_stop_date"]
)
for d in old_doc:
old_stop_dates[d.name] = d.service_stop_date or ""
@@ -58,14 +62,16 @@ def build_conditions(process_type, account, company):
)
if account:
conditions += f"AND {deferred_account}={frappe.db.escape(account)}"
conditions += "AND %s='%s'" % (deferred_account, account)
elif company:
conditions += f"AND p.company = {frappe.db.escape(company)}"
return conditions
def convert_deferred_expense_to_expense(deferred_process, start_date=None, end_date=None, conditions=""):
def convert_deferred_expense_to_expense(
deferred_process, start_date=None, end_date=None, conditions=""
):
# book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
if not start_date:
@@ -75,14 +81,16 @@ def convert_deferred_expense_to_expense(deferred_process, start_date=None, end_d
# check for the purchase invoice for which GL entries has to be done
invoices = frappe.db.sql_list(
f"""
"""
select distinct item.parent
from `tabPurchase Invoice Item` item, `tabPurchase Invoice` p
where item.service_start_date<=%s and item.service_end_date>=%s
and item.enable_deferred_expense = 1 and item.parent=p.name
and item.docstatus = 1 and ifnull(item.amount, 0) > 0
{conditions}
""",
{0}
""".format(
conditions
),
(end_date, start_date),
) # nosec
@@ -95,7 +103,9 @@ def convert_deferred_expense_to_expense(deferred_process, start_date=None, end_d
send_mail(deferred_process)
def convert_deferred_revenue_to_income(deferred_process, start_date=None, end_date=None, conditions=""):
def convert_deferred_revenue_to_income(
deferred_process, start_date=None, end_date=None, conditions=""
):
# book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
if not start_date:
@@ -105,14 +115,16 @@ def convert_deferred_revenue_to_income(deferred_process, start_date=None, end_da
# check for the sales invoice for which GL entries has to be done
invoices = frappe.db.sql_list(
f"""
"""
select distinct item.parent
from `tabSales Invoice Item` item, `tabSales Invoice` p
where item.service_start_date<=%s and item.service_end_date>=%s
and item.enable_deferred_revenue = 1 and item.parent=p.name
and item.docstatus = 1 and ifnull(item.amount, 0) > 0
{conditions}
""",
{0}
""".format(
conditions
),
(end_date, start_date),
) # nosec
@@ -124,7 +136,7 @@ def convert_deferred_revenue_to_income(deferred_process, start_date=None, end_da
send_mail(deferred_process)
def get_booking_dates(doc, item, posting_date=None, prev_posting_date=None):
def get_booking_dates(doc, item, posting_date=None):
if not posting_date:
posting_date = add_days(today(), -1)
@@ -134,42 +146,39 @@ def get_booking_dates(doc, item, posting_date=None, prev_posting_date=None):
"deferred_revenue_account" if doc.doctype == "Sales Invoice" else "deferred_expense_account"
)
if not prev_posting_date:
prev_gl_entry = frappe.db.sql(
"""
select name, posting_date from `tabGL Entry` where company=%s and account=%s and
voucher_type=%s and voucher_no=%s and voucher_detail_no=%s
and is_cancelled = 0
order by posting_date desc limit 1
""",
(doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name),
as_dict=True,
)
prev_gl_entry = frappe.db.sql(
"""
select name, posting_date from `tabGL Entry` where company=%s and account=%s and
voucher_type=%s and voucher_no=%s and voucher_detail_no=%s
and is_cancelled = 0
order by posting_date desc limit 1
""",
(doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name),
as_dict=True,
)
prev_gl_via_je = frappe.db.sql(
"""
SELECT p.name, p.posting_date FROM `tabJournal Entry` p, `tabJournal Entry Account` c
WHERE p.name = c.parent and p.company=%s and c.account=%s
and c.reference_type=%s and c.reference_name=%s
and c.reference_detail_no=%s and c.docstatus < 2 order by posting_date desc limit 1
""",
(doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name),
as_dict=True,
)
prev_gl_via_je = frappe.db.sql(
"""
SELECT p.name, p.posting_date FROM `tabJournal Entry` p, `tabJournal Entry Account` c
WHERE p.name = c.parent and p.company=%s and c.account=%s
and c.reference_type=%s and c.reference_name=%s
and c.reference_detail_no=%s and c.docstatus < 2 order by posting_date desc limit 1
""",
(doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name),
as_dict=True,
)
if prev_gl_via_je:
if (not prev_gl_entry) or (
prev_gl_entry and prev_gl_entry[0].posting_date < prev_gl_via_je[0].posting_date
):
prev_gl_entry = prev_gl_via_je
if prev_gl_entry:
start_date = getdate(add_days(prev_gl_entry[0].posting_date, 1))
else:
start_date = item.service_start_date
if prev_gl_via_je:
if (not prev_gl_entry) or (
prev_gl_entry and prev_gl_entry[0].posting_date < prev_gl_via_je[0].posting_date
):
prev_gl_entry = prev_gl_via_je
if prev_gl_entry:
start_date = getdate(add_days(prev_gl_entry[0].posting_date, 1))
else:
start_date = getdate(add_days(prev_posting_date, 1))
start_date = item.service_start_date
end_date = get_last_day(start_date)
if end_date >= item.service_end_date:
end_date = item.service_end_date
@@ -231,7 +240,9 @@ def calculate_monthly_amount(
already_booked_amount, already_booked_amount_in_account_currency = get_already_booked_amount(
doc, item
)
base_amount = flt(item.base_net_amount - already_booked_amount, item.precision("base_net_amount"))
base_amount = flt(
item.base_net_amount - already_booked_amount, item.precision("base_net_amount")
)
if account_currency == doc.company_currency:
amount = base_amount
else:
@@ -251,13 +262,17 @@ def calculate_amount(doc, item, last_gl_entry, total_days, total_booking_days, a
if account_currency == doc.company_currency:
amount = base_amount
else:
amount = flt(item.net_amount * total_booking_days / flt(total_days), item.precision("net_amount"))
amount = flt(
item.net_amount * total_booking_days / flt(total_days), item.precision("net_amount")
)
else:
already_booked_amount, already_booked_amount_in_account_currency = get_already_booked_amount(
doc, item
)
base_amount = flt(item.base_net_amount - already_booked_amount, item.precision("base_net_amount"))
base_amount = flt(
item.base_net_amount - already_booked_amount, item.precision("base_net_amount")
)
if account_currency == doc.company_currency:
amount = base_amount
else:
@@ -278,22 +293,26 @@ def get_already_booked_amount(doc, item):
gl_entries_details = frappe.db.sql(
"""
select sum({}) as total_credit, sum({}) as total_credit_in_account_currency, voucher_detail_no
select sum({0}) as total_credit, sum({1}) as total_credit_in_account_currency, voucher_detail_no
from `tabGL Entry` where company=%s and account=%s and voucher_type=%s and voucher_no=%s and voucher_detail_no=%s
and is_cancelled = 0
group by voucher_detail_no
""".format(total_credit_debit, total_credit_debit_currency),
""".format(
total_credit_debit, total_credit_debit_currency
),
(doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name),
as_dict=True,
)
journal_entry_details = frappe.db.sql(
"""
SELECT sum(c.{}) as total_credit, sum(c.{}) as total_credit_in_account_currency, reference_detail_no
SELECT sum(c.{0}) as total_credit, sum(c.{1}) as total_credit_in_account_currency, reference_detail_no
FROM `tabJournal Entry` p , `tabJournal Entry Account` c WHERE p.name = c.parent and
p.company = %s and c.account=%s and c.reference_type=%s and c.reference_name=%s and c.reference_detail_no=%s
and p.docstatus < 2 group by reference_detail_no
""".format(total_credit_debit, total_credit_debit_currency),
""".format(
total_credit_debit, total_credit_debit_currency
),
(doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name),
as_dict=True,
)
@@ -315,20 +334,16 @@ def get_already_booked_amount(doc, item):
def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
enable_check = "enable_deferred_revenue" if doc.doctype == "Sales Invoice" else "enable_deferred_expense"
enable_check = (
"enable_deferred_revenue" if doc.doctype == "Sales Invoice" else "enable_deferred_expense"
)
accounts_frozen_upto = frappe.db.get_single_value("Accounts Settings", "acc_frozen_upto")
accounts_frozen_upto = frappe.get_cached_value("Accounts Settings", "None", "acc_frozen_upto")
def _book_deferred_revenue_or_expense(
item,
via_journal_entry,
submit_journal_entry,
book_deferred_entries_based_on,
prev_posting_date=None,
item, via_journal_entry, submit_journal_entry, book_deferred_entries_based_on
):
start_date, end_date, last_gl_entry = get_booking_dates(
doc, item, posting_date=posting_date, prev_posting_date=prev_posting_date
)
start_date, end_date, last_gl_entry = get_booking_dates(doc, item, posting_date=posting_date)
if not (start_date and end_date):
return
@@ -360,45 +375,42 @@ def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
)
if not amount:
prev_posting_date = end_date
else:
gl_posting_date = end_date
prev_posting_date = None
# check if books nor frozen till endate:
if accounts_frozen_upto and getdate(end_date) <= getdate(accounts_frozen_upto):
gl_posting_date = get_last_day(add_days(accounts_frozen_upto, 1))
prev_posting_date = end_date
return
if via_journal_entry:
book_revenue_via_journal_entry(
doc,
credit_account,
debit_account,
amount,
base_amount,
gl_posting_date,
project,
account_currency,
item.cost_center,
item,
deferred_process,
submit_journal_entry,
)
else:
make_gl_entries(
doc,
credit_account,
debit_account,
against,
amount,
base_amount,
gl_posting_date,
project,
account_currency,
item.cost_center,
item,
deferred_process,
)
# check if books nor frozen till endate:
if accounts_frozen_upto and (end_date) <= getdate(accounts_frozen_upto):
end_date = get_last_day(add_days(accounts_frozen_upto, 1))
if via_journal_entry:
book_revenue_via_journal_entry(
doc,
credit_account,
debit_account,
amount,
base_amount,
end_date,
project,
account_currency,
item.cost_center,
item,
deferred_process,
submit_journal_entry,
)
else:
make_gl_entries(
doc,
credit_account,
debit_account,
against,
amount,
base_amount,
end_date,
project,
account_currency,
item.cost_center,
item,
deferred_process,
)
# Returned in case of any errors because it tries to submit the same record again and again in case of errors
if frappe.flags.deferred_accounting_error:
@@ -406,17 +418,15 @@ def book_deferred_income_or_expense(doc, deferred_process, posting_date=None):
if getdate(end_date) < getdate(posting_date) and not last_gl_entry:
_book_deferred_revenue_or_expense(
item,
via_journal_entry,
submit_journal_entry,
book_deferred_entries_based_on,
prev_posting_date,
item, via_journal_entry, submit_journal_entry, book_deferred_entries_based_on
)
via_journal_entry = cint(
frappe.db.get_singles_value("Accounts Settings", "book_deferred_entries_via_journal_entry")
)
submit_journal_entry = cint(frappe.db.get_singles_value("Accounts Settings", "submit_journal_entries"))
submit_journal_entry = cint(
frappe.db.get_singles_value("Accounts Settings", "submit_journal_entries")
)
book_deferred_entries_based_on = frappe.db.get_singles_value(
"Accounts Settings", "book_deferred_entries_based_on"
)
@@ -436,7 +446,9 @@ def process_deferred_accounting(posting_date=None):
posting_date = today()
if not cint(
frappe.db.get_singles_value("Accounts Settings", "automatically_process_deferred_accounting_entry")
frappe.db.get_singles_value(
"Accounts Settings", "automatically_process_deferred_accounting_entry"
)
):
return
@@ -559,13 +571,16 @@ def book_revenue_via_journal_entry(
deferred_process=None,
submit="No",
):
if amount == 0:
return
journal_entry = frappe.new_doc("Journal Entry")
journal_entry.posting_date = posting_date
journal_entry.company = doc.company
journal_entry.voucher_type = "Deferred Revenue" if doc.doctype == "Sales Invoice" else "Deferred Expense"
journal_entry.voucher_type = (
"Deferred Revenue" if doc.doctype == "Sales Invoice" else "Deferred Expense"
)
journal_entry.process_deferred_accounting = deferred_process
debit_entry = {
@@ -614,6 +629,7 @@ def book_revenue_via_journal_entry(
def get_deferred_booking_accounts(doctype, voucher_detail_no, dr_or_cr):
if doctype == "Sales Invoice":
credit_account, debit_account = frappe.db.get_value(
"Sales Invoice Item",

View File

@@ -1,32 +1,33 @@
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.ui.form.on("Account", {
setup: function (frm) {
frm.add_fetch("parent_account", "report_type", "report_type");
frm.add_fetch("parent_account", "root_type", "root_type");
frappe.ui.form.on('Account', {
setup: function(frm) {
frm.add_fetch('parent_account', 'report_type', 'report_type');
frm.add_fetch('parent_account', 'root_type', 'root_type');
},
onload: function (frm) {
frm.set_query("parent_account", function (doc) {
onload: function(frm) {
frm.set_query('parent_account', function(doc) {
return {
filters: {
is_group: 1,
company: doc.company,
},
"is_group": 1,
"company": doc.company
}
};
});
},
refresh: function (frm) {
frm.toggle_display("account_name", frm.is_new());
refresh: function(frm) {
frm.toggle_display('account_name', frm.is_new());
// hide fields if group
frm.toggle_display(["account_type", "tax_rate"], cint(frm.doc.is_group) == 0);
frm.toggle_display(['account_type', 'tax_rate'], cint(frm.doc.is_group) == 0);
// disable fields
frm.toggle_enable(["is_group", "company"], false);
frm.toggle_enable(['is_group', 'company'], false);
if (cint(frm.doc.is_group) == 0) {
frm.toggle_display("freeze_account", frm.doc.__onload && frm.doc.__onload.can_freeze_account);
frm.toggle_display('freeze_account', frm.doc.__onload
&& frm.doc.__onload.can_freeze_account);
}
// read-only for root accounts
@@ -37,147 +38,125 @@ frappe.ui.form.on("Account", {
} else {
// credit days and type if customer or supplier
frm.set_intro(null);
frm.trigger("account_type");
frm.trigger('account_type');
// show / hide convert buttons
frm.trigger("add_toolbar_buttons");
frm.trigger('add_toolbar_buttons');
}
if (frm.has_perm("write")) {
frm.add_custom_button(
__("Merge Account"),
function () {
frm.trigger("merge_account");
},
__("Actions")
);
frm.add_custom_button(
__("Update Account Name / Number"),
function () {
frm.trigger("update_account_number");
},
__("Actions")
);
if (frm.has_perm('write')) {
frm.add_custom_button(__('Merge Account'), function () {
frm.trigger("merge_account");
}, __('Actions'));
frm.add_custom_button(__('Update Account Name / Number'), function () {
frm.trigger("update_account_number");
}, __('Actions'));
}
}
},
account_type: function (frm) {
if (frm.doc.is_group == 0) {
frm.toggle_display(["tax_rate"], frm.doc.account_type == "Tax");
frm.toggle_display("warehouse", frm.doc.account_type == "Stock");
frm.toggle_display(['tax_rate'], frm.doc.account_type == 'Tax');
frm.toggle_display('warehouse', frm.doc.account_type == 'Stock');
}
},
add_toolbar_buttons: function (frm) {
frm.add_custom_button(
__("Chart of Accounts"),
() => {
frappe.set_route("Tree", "Account");
},
__("View")
);
add_toolbar_buttons: function(frm) {
frm.add_custom_button(__('Chart of Accounts'), () => {
frappe.set_route("Tree", "Account");
}, __('View'));
if (frm.doc.is_group == 1) {
frm.add_custom_button(
__("Convert to Non-Group"),
function () {
return frappe.call({
doc: frm.doc,
method: "convert_group_to_ledger",
callback: function () {
frm.refresh();
},
});
},
__("Actions")
);
} else if (cint(frm.doc.is_group) == 0 && frappe.boot.user.can_read.indexOf("GL Entry") !== -1) {
frm.add_custom_button(
__("General Ledger"),
function () {
frappe.route_options = {
account: frm.doc.name,
from_date: erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[1],
to_date: erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[2],
company: frm.doc.company,
};
frappe.set_route("query-report", "General Ledger");
},
__("View")
);
frm.add_custom_button(__('Convert to Non-Group'), function () {
return frappe.call({
doc: frm.doc,
method: 'convert_group_to_ledger',
callback: function() {
frm.refresh();
}
});
}, __('Actions'));
frm.add_custom_button(
__("Convert to Group"),
function () {
return frappe.call({
doc: frm.doc,
method: "convert_ledger_to_group",
callback: function () {
frm.refresh();
},
});
},
__("Actions")
);
} else if (cint(frm.doc.is_group) == 0
&& frappe.boot.user.can_read.indexOf("GL Entry") !== -1) {
frm.add_custom_button(__('General Ledger'), function () {
frappe.route_options = {
"account": frm.doc.name,
"from_date": frappe.sys_defaults.year_start_date,
"to_date": frappe.sys_defaults.year_end_date,
"company": frm.doc.company
};
frappe.set_route("query-report", "General Ledger");
}, __('View'));
frm.add_custom_button(__('Convert to Group'), function () {
return frappe.call({
doc: frm.doc,
method: 'convert_ledger_to_group',
callback: function() {
frm.refresh();
}
});
}, __('Actions'));
}
},
merge_account: function (frm) {
merge_account: function(frm) {
var d = new frappe.ui.Dialog({
title: __("Merge with Existing Account"),
title: __('Merge with Existing Account'),
fields: [
{
label: "Name",
fieldname: "name",
fieldtype: "Data",
reqd: 1,
default: frm.doc.name,
},
"label" : "Name",
"fieldname": "name",
"fieldtype": "Data",
"reqd": 1,
"default": frm.doc.name
}
],
primary_action: function () {
primary_action: function() {
var data = d.get_values();
frappe.call({
method: "erpnext.accounts.doctype.account.account.merge_account",
args: {
old: frm.doc.name,
new: data.name,
is_group: frm.doc.is_group,
root_type: frm.doc.root_type,
company: frm.doc.company
},
callback: function (r) {
if (!r.exc) {
if (r.message) {
callback: function(r) {
if(!r.exc) {
if(r.message) {
frappe.set_route("Form", "Account", r.message);
}
d.hide();
}
},
}
});
},
primary_action_label: __("Merge"),
primary_action_label: __('Merge')
});
d.show();
},
update_account_number: function (frm) {
update_account_number: function(frm) {
var d = new frappe.ui.Dialog({
title: __("Update Account Number / Name"),
title: __('Update Account Number / Name'),
fields: [
{
label: "Account Name",
fieldname: "account_name",
fieldtype: "Data",
reqd: 1,
default: frm.doc.account_name,
"label": "Account Name",
"fieldname": "account_name",
"fieldtype": "Data",
"reqd": 1,
"default": frm.doc.account_name
},
{
label: "Account Number",
fieldname: "account_number",
fieldtype: "Data",
default: frm.doc.account_number,
},
"label": "Account Number",
"fieldname": "account_number",
"fieldtype": "Data",
"default": frm.doc.account_number
}
],
primary_action: function () {
primary_action: function() {
var data = d.get_values();
if (
data.account_number === frm.doc.account_number &&
data.account_name === frm.doc.account_name
) {
if(data.account_number === frm.doc.account_number && data.account_name === frm.doc.account_name) {
d.hide();
return;
}
@@ -187,11 +166,11 @@ frappe.ui.form.on("Account", {
args: {
account_number: data.account_number,
account_name: data.account_name,
name: frm.doc.name,
name: frm.doc.name
},
callback: function (r) {
if (!r.exc) {
if (r.message) {
callback: function(r) {
if(!r.exc) {
if(r.message) {
frappe.set_route("Form", "Account", r.message);
} else {
frm.set_value("account_number", data.account_number);
@@ -199,11 +178,11 @@ frappe.ui.form.on("Account", {
}
d.hide();
}
},
}
});
},
primary_action_label: __("Update"),
primary_action_label: __('Update')
});
d.show();
},
}
});

View File

@@ -18,6 +18,7 @@
"root_type",
"report_type",
"account_currency",
"inter_company_account",
"column_break1",
"parent_account",
"account_type",
@@ -33,11 +34,15 @@
{
"fieldname": "properties",
"fieldtype": "Section Break",
"oldfieldtype": "Section Break"
"oldfieldtype": "Section Break",
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "column_break0",
"fieldtype": "Column Break",
"show_days": 1,
"show_seconds": 1,
"width": "50%"
},
{
@@ -48,7 +53,9 @@
"no_copy": 1,
"oldfieldname": "account_name",
"oldfieldtype": "Data",
"reqd": 1
"reqd": 1,
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "account_number",
@@ -56,13 +63,17 @@
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Account Number",
"read_only": 1
"read_only": 1,
"show_days": 1,
"show_seconds": 1
},
{
"default": "0",
"fieldname": "is_group",
"fieldtype": "Check",
"label": "Is Group"
"label": "Is Group",
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "company",
@@ -74,7 +85,9 @@
"options": "Company",
"read_only": 1,
"remember_last_selected_value": 1,
"reqd": 1
"reqd": 1,
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "root_type",
@@ -82,7 +95,9 @@
"in_standard_filter": 1,
"label": "Root Type",
"options": "\nAsset\nLiability\nIncome\nExpense\nEquity",
"read_only": 1
"read_only": 1,
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "report_type",
@@ -90,18 +105,32 @@
"in_standard_filter": 1,
"label": "Report Type",
"options": "\nBalance Sheet\nProfit and Loss",
"read_only": 1
"read_only": 1,
"show_days": 1,
"show_seconds": 1
},
{
"depends_on": "eval:doc.is_group==0",
"fieldname": "account_currency",
"fieldtype": "Link",
"label": "Currency",
"options": "Currency"
"options": "Currency",
"show_days": 1,
"show_seconds": 1
},
{
"default": "0",
"fieldname": "inter_company_account",
"fieldtype": "Check",
"label": "Inter Company Account",
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "column_break1",
"fieldtype": "Column Break",
"show_days": 1,
"show_seconds": 1,
"width": "50%"
},
{
@@ -113,7 +142,9 @@
"oldfieldtype": "Link",
"options": "Account",
"reqd": 1,
"search_index": 1
"search_index": 1,
"show_days": 1,
"show_seconds": 1
},
{
"description": "Setting Account Type helps in selecting this Account in transactions.",
@@ -123,7 +154,9 @@
"label": "Account Type",
"oldfieldname": "account_type",
"oldfieldtype": "Select",
"options": "\nAccumulated Depreciation\nAsset Received But Not Billed\nBank\nCash\nChargeable\nCapital Work in Progress\nCost of Goods Sold\nDepreciation\nEquity\nExpense Account\nExpenses Included In Asset Valuation\nExpenses Included In Valuation\nFixed Asset\nIncome Account\nPayable\nReceivable\nRound Off\nStock\nStock Adjustment\nStock Received But Not Billed\nService Received But Not Billed\nTax\nTemporary"
"options": "\nAccumulated Depreciation\nAsset Received But Not Billed\nBank\nCash\nChargeable\nCapital Work in Progress\nCost of Goods Sold\nDepreciation\nEquity\nExpense Account\nExpenses Included In Asset Valuation\nExpenses Included In Valuation\nFixed Asset\nIncome Account\nPayable\nReceivable\nRound Off\nStock\nStock Adjustment\nStock Received But Not Billed\nService Received But Not Billed\nTax\nTemporary",
"show_days": 1,
"show_seconds": 1
},
{
"description": "Rate at which this tax is applied",
@@ -131,7 +164,9 @@
"fieldtype": "Float",
"label": "Rate",
"oldfieldname": "tax_rate",
"oldfieldtype": "Currency"
"oldfieldtype": "Currency",
"show_days": 1,
"show_seconds": 1
},
{
"description": "If the account is frozen, entries are allowed to restricted users.",
@@ -140,13 +175,17 @@
"label": "Frozen",
"oldfieldname": "freeze_account",
"oldfieldtype": "Select",
"options": "No\nYes"
"options": "No\nYes",
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "balance_must_be",
"fieldtype": "Select",
"label": "Balance must be",
"options": "\nDebit\nCredit"
"options": "\nDebit\nCredit",
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "lft",
@@ -155,7 +194,9 @@
"label": "Lft",
"print_hide": 1,
"read_only": 1,
"search_index": 1
"search_index": 1,
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "rgt",
@@ -164,7 +205,9 @@
"label": "Rgt",
"print_hide": 1,
"read_only": 1,
"search_index": 1
"search_index": 1,
"show_days": 1,
"show_seconds": 1
},
{
"fieldname": "old_parent",
@@ -172,27 +215,33 @@
"hidden": 1,
"label": "Old Parent",
"print_hide": 1,
"read_only": 1
"read_only": 1,
"show_days": 1,
"show_seconds": 1
},
{
"default": "0",
"depends_on": "eval:(doc.report_type == 'Profit and Loss' && !doc.is_group)",
"fieldname": "include_in_gross",
"fieldtype": "Check",
"label": "Include in gross"
"label": "Include in gross",
"show_days": 1,
"show_seconds": 1
},
{
"default": "0",
"fieldname": "disabled",
"fieldtype": "Check",
"label": "Disable"
"label": "Disable",
"show_days": 1,
"show_seconds": 1
}
],
"icon": "fa fa-money",
"idx": 1,
"is_tree": 1,
"links": [],
"modified": "2023-04-11 16:08:46.983677",
"modified": "2020-06-11 15:15:54.338622",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Account",
@@ -252,6 +301,5 @@
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "ASC",
"states": [],
"track_changes": 1
}

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
@@ -18,10 +18,6 @@ class BalanceMismatchError(frappe.ValidationError):
pass
class InvalidAccountMergeError(frappe.ValidationError):
pass
class Account(NestedSet):
nsm_parent_field = "parent_account"
@@ -29,7 +25,7 @@ class Account(NestedSet):
if frappe.local.flags.ignore_update_nsm:
return
else:
super().on_update()
super(Account, self).on_update()
def onload(self):
frozen_accounts_modifier = frappe.db.get_value(
@@ -58,12 +54,11 @@ class Account(NestedSet):
self.validate_balance_must_be_debit_or_credit()
self.validate_account_currency()
self.validate_root_company_and_sync_account_to_children()
self.validate_receivable_payable_account_type()
def validate_parent(self):
"""Fetch Parent Details and validate parent account"""
if self.parent_account:
par = frappe.db.get_value(
par = frappe.get_cached_value(
"Account", self.parent_account, ["name", "is_group", "company"], as_dict=1
)
if not par:
@@ -87,7 +82,9 @@ class Account(NestedSet):
def set_root_and_report_type(self):
if self.parent_account:
par = frappe.db.get_value("Account", self.parent_account, ["report_type", "root_type"], as_dict=1)
par = frappe.get_cached_value(
"Account", self.parent_account, ["report_type", "root_type"], as_dict=1
)
if par.report_type:
self.report_type = par.report_type
@@ -95,7 +92,7 @@ class Account(NestedSet):
self.root_type = par.root_type
if self.is_group:
db_value = frappe.db.get_value("Account", self.name, ["report_type", "root_type"], as_dict=1)
db_value = self.get_doc_before_save()
if db_value:
if self.report_type != db_value.report_type:
frappe.db.sql(
@@ -113,40 +110,26 @@ class Account(NestedSet):
"Balance Sheet" if self.root_type in ("Asset", "Liability", "Equity") else "Profit and Loss"
)
def validate_receivable_payable_account_type(self):
doc_before_save = self.get_doc_before_save()
receivable_payable_types = ["Receivable", "Payable"]
if (
doc_before_save
and doc_before_save.account_type in receivable_payable_types
and doc_before_save.account_type != self.account_type
):
# check for ledger entries
if frappe.db.get_all("GL Entry", filters={"account": self.name, "is_cancelled": 0}, limit=1):
msg = _(
"There are ledger entries against this account. Changing {0} to non-{1} in live system will cause incorrect output in 'Accounts {2}' report"
).format(
frappe.bold("Account Type"), doc_before_save.account_type, doc_before_save.account_type
)
frappe.msgprint(msg)
self.add_comment("Comment", msg)
def validate_root_details(self):
# does not exists parent
if frappe.db.exists("Account", self.name):
if not frappe.db.get_value("Account", self.name, "parent_account"):
throw(_("Root cannot be edited."), RootNotEditable)
doc_before_save = self.get_doc_before_save()
if doc_before_save and not doc_before_save.parent_account:
throw(_("Root cannot be edited."), RootNotEditable)
if not self.parent_account and not self.is_group:
frappe.throw(_("The root account {0} must be a group").format(frappe.bold(self.name)))
throw(_("The root account {0} must be a group").format(frappe.bold(self.name)))
def validate_root_company_and_sync_account_to_children(self):
# ignore validation while creating new compnay or while syncing to child companies
if frappe.local.flags.ignore_root_company_validation or self.flags.ignore_root_company_validation:
if (
frappe.local.flags.ignore_root_company_validation or self.flags.ignore_root_company_validation
):
return
ancestors = get_root_company(self.company)
if ancestors:
if frappe.get_value("Company", self.company, "allow_account_creation_against_child_company"):
if frappe.get_cached_value(
"Company", self.company, "allow_account_creation_against_child_company"
):
return
if not frappe.db.get_value(
"Account", {"account_name": self.account_name, "company": ancestors[0]}, "name"
@@ -157,7 +140,7 @@ class Account(NestedSet):
if not descendants:
return
parent_acc_name_map = {}
parent_acc_name, parent_acc_number = frappe.db.get_value(
parent_acc_name, parent_acc_number = frappe.get_cached_value(
"Account", self.parent_account, ["account_name", "account_number"]
)
filters = {
@@ -178,27 +161,28 @@ class Account(NestedSet):
self.create_account_for_child_company(parent_acc_name_map, descendants, parent_acc_name)
def validate_group_or_ledger(self):
if self.get("__islocal"):
doc_before_save = self.get_doc_before_save()
if not doc_before_save or cint(doc_before_save.is_group) == cint(self.is_group):
return
existing_is_group = frappe.db.get_value("Account", self.name, "is_group")
if cint(self.is_group) != cint(existing_is_group):
if self.check_gle_exists():
throw(_("Account with existing transaction cannot be converted to ledger"))
elif self.is_group:
if self.account_type and not self.flags.exclude_account_type_check:
throw(_("Cannot covert to Group because Account Type is selected."))
elif self.check_if_child_exists():
throw(_("Account with child nodes cannot be set as ledger"))
if self.check_gle_exists():
throw(_("Account with existing transaction cannot be converted to ledger"))
elif self.is_group:
if self.account_type and not self.flags.exclude_account_type_check:
throw(_("Cannot covert to Group because Account Type is selected."))
elif self.check_if_child_exists():
throw(_("Account with child nodes cannot be set as ledger"))
def validate_frozen_accounts_modifier(self):
old_value = frappe.db.get_value("Account", self.name, "freeze_account")
if old_value and old_value != self.freeze_account:
frozen_accounts_modifier = frappe.db.get_value(
"Accounts Settings", None, "frozen_accounts_modifier"
)
if not frozen_accounts_modifier or frozen_accounts_modifier not in frappe.get_roles():
throw(_("You are not authorized to set Frozen value"))
doc_before_save = self.get_doc_before_save()
if not doc_before_save or doc_before_save.freeze_account == self.freeze_account:
return
frozen_accounts_modifier = frappe.get_cached_value(
"Accounts Settings", "Accounts Settings", "frozen_accounts_modifier"
)
if not frozen_accounts_modifier or frozen_accounts_modifier not in frappe.get_roles():
throw(_("You are not authorized to set Frozen value"))
def validate_balance_must_be_debit_or_credit(self):
from erpnext.accounts.utils import get_balance_on
@@ -220,11 +204,8 @@ class Account(NestedSet):
)
def validate_account_currency(self):
self.currency_explicitly_specified = True
if not self.account_currency:
self.account_currency = frappe.get_cached_value("Company", self.company, "default_currency")
self.currency_explicitly_specified = False
gl_currency = frappe.db.get_value("GL Entry", {"account": self.name}, "account_currency")
@@ -245,9 +226,9 @@ class Account(NestedSet):
)
# validate if parent of child company account to be added is a group
if frappe.db.get_value("Account", self.parent_account, "is_group") and not frappe.db.get_value(
"Account", parent_acc_name_map[company], "is_group"
):
if frappe.get_cached_value(
"Account", self.parent_account, "is_group"
) and not frappe.get_cached_value("Account", parent_acc_name_map[company], "is_group"):
msg = _(
"While creating account for Child Company {0}, parent account {1} found as a ledger account."
).format(company_bold, parent_acc_name_bold)
@@ -270,10 +251,8 @@ class Account(NestedSet):
{
"company": company,
# parent account's currency should be passed down to child account's curreny
# if currency explicitly specified by user, child will inherit. else, default currency will be used.
"account_currency": self.account_currency
if self.currency_explicitly_specified
else erpnext.get_company_currency(company),
# if it is None, it picks it up from default company currency, which might be unintended
"account_currency": erpnext.get_company_currency(company),
"parent_account": parent_acc_name_map[company],
}
)
@@ -337,7 +316,7 @@ class Account(NestedSet):
if self.check_gle_exists():
throw(_("Account with existing transaction can not be deleted"))
super().on_trash(True)
super(Account, self).on_trash(True)
@frappe.whitelist()
@@ -345,8 +324,9 @@ class Account(NestedSet):
def get_parent_account(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql(
"""select name from tabAccount
where is_group = 1 and docstatus != 2 and company = {}
and {} like {} order by name limit {} offset {}""".format("%s", searchfield, "%s", "%s", "%s"),
where is_group = 1 and docstatus != 2 and company = %s
and %s like %s order by name limit %s offset %s"""
% ("%s", searchfield, "%s", "%s", "%s"),
(filters["company"], "%%%s%%" % txt, page_len, start),
as_list=1,
)
@@ -400,28 +380,21 @@ def validate_account_number(name, account_number, company):
@frappe.whitelist()
def update_account_number(name, account_name, account_number=None, from_descendant=False):
_ensure_idle_system()
account = frappe.db.get_value("Account", name, "company", as_dict=True)
account = frappe.get_cached_doc("Account", name)
if not account:
return
old_acc_name, old_acc_number = frappe.db.get_value("Account", name, ["account_name", "account_number"])
old_acc_name, old_acc_number = account.account_name, account.account_number
# check if account exists in parent company
ancestors = get_ancestors_of("Company", account.company)
allow_independent_account_creation = frappe.get_value(
allow_independent_account_creation = frappe.get_cached_value(
"Company", account.company, "allow_account_creation_against_child_company"
)
if ancestors and not allow_independent_account_creation:
for ancestor in ancestors:
old_name = frappe.db.get_value(
"Account",
{"account_number": old_acc_number, "account_name": old_acc_name, "company": ancestor},
"name",
)
if old_name and not from_descendant:
if frappe.db.get_value("Account", {"account_name": old_acc_name, "company": ancestor}, "name"):
# same account in parent company exists
allow_child_account_creation = _("Allow Account Creation Against Child Company")
@@ -461,35 +434,25 @@ def update_account_number(name, account_name, account_number=None, from_descenda
@frappe.whitelist()
def merge_account(old, new):
_ensure_idle_system()
def merge_account(old, new, is_group, root_type, company):
# Validate properties before merging
new_account = frappe.get_cached_doc("Account", new)
old_account = frappe.get_cached_doc("Account", old)
if not new_account:
throw(_("Account {0} does not exist").format(new))
if (
cint(new_account.is_group),
new_account.root_type,
new_account.company,
cstr(new_account.account_currency),
) != (
cint(old_account.is_group),
old_account.root_type,
old_account.company,
cstr(old_account.account_currency),
if (new_account.is_group, new_account.root_type, new_account.company) != (
cint(is_group),
root_type,
company,
):
throw(
msg=_(
"""Merging is only possible if following properties are same in both records. Is Group, Root Type, Company and Account Currency"""
),
title=("Invalid Accounts"),
exc=InvalidAccountMergeError,
_(
"""Merging is only possible if following properties are same in both records. Is Group, Root Type, Company"""
)
)
if old_account.is_group and new_account.parent_account == old:
if is_group and new_account.parent_account == old:
new_account.db_set("parent_account", frappe.get_cached_value("Account", old, "parent_account"))
frappe.rename_doc("Account", old, new, merge=1, force=1)
@@ -514,29 +477,7 @@ def sync_update_account_number_in_child(
if old_acc_number:
filters["account_number"] = old_acc_number
for d in frappe.db.get_values("Account", filters=filters, fieldname=["company", "name"], as_dict=True):
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
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 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

@@ -1,4 +1,4 @@
frappe.provide("frappe.treeview_settings");
frappe.provide("frappe.treeview_settings")
frappe.treeview_settings["Account"] = {
breadcrumb: "Accounts",
@@ -7,12 +7,12 @@ frappe.treeview_settings["Account"] = {
filters: [
{
fieldname: "company",
fieldtype: "Select",
fieldtype:"Select",
options: erpnext.utils.get_tree_options("company"),
label: __("Company"),
default: erpnext.utils.get_tree_default("company"),
on_change: function () {
var me = frappe.treeview_settings["Account"].treeview;
on_change: function() {
var me = frappe.treeview_settings['Account'].treeview;
var company = me.page.fields_dict.company.get_value();
if (!company) {
frappe.throw(__("Please set a Company"));
@@ -22,36 +22,30 @@ frappe.treeview_settings["Account"] = {
args: {
company: company,
},
callback: function (r) {
if (r.message) {
callback: function(r) {
if(r.message) {
let root_company = r.message.length ? r.message[0] : "";
me.page.fields_dict.root_company.set_value(root_company);
frappe.db.get_value(
"Company",
{ name: company },
"allow_account_creation_against_child_company",
(r) => {
frappe.flags.ignore_root_company_validation =
r.allow_account_creation_against_child_company;
}
);
frappe.db.get_value("Company", {"name": company}, "allow_account_creation_against_child_company", (r) => {
frappe.flags.ignore_root_company_validation = r.allow_account_creation_against_child_company;
});
}
},
}
});
},
}
},
{
fieldname: "root_company",
fieldtype: "Data",
fieldtype:"Data",
label: __("Root Company"),
hidden: true,
disable_onchange: true,
},
disable_onchange: true
}
],
root_label: "Accounts",
get_tree_nodes: "erpnext.accounts.utils.get_children",
on_get_node: function (nodes, deep = false) {
get_tree_nodes: 'erpnext.accounts.utils.get_children',
on_get_node: function(nodes, deep=false) {
if (frappe.boot.user.can_read.indexOf("GL Entry") == -1) return;
let accounts = [];
@@ -62,232 +56,147 @@ frappe.treeview_settings["Account"] = {
accounts = nodes;
}
frappe.db.get_single_value("Accounts Settings", "show_balance_in_coa").then((value) => {
if (value) {
const get_balances = frappe.call({
method: "erpnext.accounts.utils.get_account_balances",
args: {
accounts: accounts,
company: cur_tree.args.company,
},
});
const get_balances = frappe.call({
method: 'erpnext.accounts.utils.get_account_balances',
args: {
accounts: accounts,
company: cur_tree.args.company
},
});
get_balances.then((r) => {
if (!r.message || r.message.length == 0) return;
get_balances.then(r => {
if (!r.message || r.message.length == 0) return;
for (let account of r.message) {
const node = cur_tree.nodes && cur_tree.nodes[account.value];
if (!node || node.is_root) continue;
for (let account of r.message) {
// show Dr if positive since balance is calculated as debit - credit else show Cr
const balance = account.balance_in_account_currency || account.balance;
const dr_or_cr = balance > 0 ? "Dr" : "Cr";
const format = (value, currency) => format_currency(Math.abs(value), currency);
const node = cur_tree.nodes && cur_tree.nodes[account.value];
if (!node || node.is_root) continue;
if (account.balance !== undefined) {
node.parent && node.parent.find(".balance-area").remove();
$(
'<span class="balance-area pull-right">' +
(account.balance_in_account_currency
? format(
account.balance_in_account_currency,
account.account_currency
) + " / "
: "") +
format(account.balance, account.company_currency) +
" " +
dr_or_cr +
"</span>"
).insertBefore(node.$ul);
}
}
});
// show Dr if positive since balance is calculated as debit - credit else show Cr
const balance = account.balance_in_account_currency || account.balance;
const dr_or_cr = balance > 0 ? "Dr": "Cr";
const format = (value, currency) => format_currency(Math.abs(value), currency);
if (account.balance!==undefined) {
node.parent && node.parent.find('.balance-area').remove();
$('<span class="balance-area pull-right">'
+ (account.balance_in_account_currency ?
(format(account.balance_in_account_currency, account.account_currency) + " / ") : "")
+ format(account.balance, account.company_currency)
+ " " + dr_or_cr
+ '</span>').insertBefore(node.$ul);
}
}
});
},
add_tree_node: "erpnext.accounts.utils.add_ac",
menu_items: [
add_tree_node: 'erpnext.accounts.utils.add_ac',
menu_items:[
{
label: __("New Company"),
action: function () {
frappe.new_doc("Company", true);
},
condition: 'frappe.boot.user.can_create.indexOf("Company") !== -1',
},
label: __('New Company'),
action: function() { frappe.new_doc("Company", true) },
condition: 'frappe.boot.user.can_create.indexOf("Company") !== -1'
}
],
fields: [
{
fieldtype: "Data",
fieldname: "account_name",
label: __("New Account Name"),
reqd: true,
description: __(
"Name of new Account. Note: Please don't create accounts for Customers and Suppliers"
),
},
{
fieldtype: "Data",
fieldname: "account_number",
label: __("Account Number"),
description: __("Number of new Account, it will be included in the account name as a prefix"),
},
{
fieldtype: "Check",
fieldname: "is_group",
label: __("Is Group"),
description: __(
"Further accounts can be made under Groups, but entries can be made against non-Groups"
),
},
{
fieldtype: "Select",
fieldname: "root_type",
label: __("Root Type"),
options: ["Asset", "Liability", "Equity", "Income", "Expense"].join("\n"),
depends_on: "eval:doc.is_group && !doc.parent_account",
},
{
fieldtype: "Select",
fieldname: "account_type",
label: __("Account Type"),
options: frappe.get_meta("Account").fields.filter((d) => d.fieldname == "account_type")[0]
.options,
description: __("Optional. This setting will be used to filter in various transactions."),
},
{
fieldtype: "Float",
fieldname: "tax_rate",
label: __("Tax Rate"),
depends_on: 'eval:doc.is_group==0&&doc.account_type=="Tax"',
},
{
fieldtype: "Link",
fieldname: "account_currency",
label: __("Currency"),
options: "Currency",
description: __("Optional. Sets company's default currency, if not specified."),
{fieldtype:'Data', fieldname:'account_name', label:__('New Account Name'), reqd:true,
description: __("Name of new Account. Note: Please don't create accounts for Customers and Suppliers")},
{fieldtype:'Data', fieldname:'account_number', label:__('Account Number'),
description: __("Number of new Account, it will be included in the account name as a prefix")},
{fieldtype:'Check', fieldname:'is_group', label:__('Is Group'),
description: __('Further accounts can be made under Groups, but entries can be made against non-Groups')},
{fieldtype:'Select', fieldname:'root_type', label:__('Root Type'),
options: ['Asset', 'Liability', 'Equity', 'Income', 'Expense'].join('\n'),
depends_on: 'eval:doc.is_group && !doc.parent_account'},
{fieldtype:'Select', fieldname:'account_type', label:__('Account Type'),
options: frappe.get_meta("Account").fields.filter(d => d.fieldname=='account_type')[0].options,
description: __("Optional. This setting will be used to filter in various transactions.")
},
{fieldtype:'Float', fieldname:'tax_rate', label:__('Tax Rate'),
depends_on: 'eval:doc.is_group==0&&doc.account_type=="Tax"'},
{fieldtype:'Link', fieldname:'account_currency', label:__('Currency'), options:"Currency",
description: __("Optional. Sets company's default currency, if not specified.")}
],
ignore_fields: ["parent_account"],
onload: function (treeview) {
frappe.treeview_settings["Account"].treeview = {};
$.extend(frappe.treeview_settings["Account"].treeview, treeview);
ignore_fields:["parent_account"],
onload: function(treeview) {
frappe.treeview_settings['Account'].treeview = {};
$.extend(frappe.treeview_settings['Account'].treeview, treeview);
function get_company() {
return treeview.page.fields_dict.company.get_value();
}
// tools
treeview.page.add_inner_button(
__("Chart of Cost Centers"),
function () {
frappe.set_route("Tree", "Cost Center", { company: get_company() });
},
__("View")
);
treeview.page.add_inner_button(__("Chart of Cost Centers"), function() {
frappe.set_route('Tree', 'Cost Center', {company: get_company()});
}, __('View'));
treeview.page.add_inner_button(
__("Opening Invoice Creation Tool"),
function () {
frappe.set_route("Form", "Opening Invoice Creation Tool", { company: get_company() });
},
__("View")
);
treeview.page.add_inner_button(__("Opening Invoice Creation Tool"), function() {
frappe.set_route('Form', 'Opening Invoice Creation Tool', {company: get_company()});
}, __('View'));
treeview.page.add_inner_button(
__("Period Closing Voucher"),
function () {
frappe.set_route("List", "Period Closing Voucher", { company: get_company() });
},
__("View")
);
treeview.page.add_inner_button(__("Period Closing Voucher"), function() {
frappe.set_route('List', 'Period Closing Voucher', {company: get_company()});
}, __('View'));
treeview.page.add_inner_button(
__("Journal Entry"),
function () {
frappe.new_doc("Journal Entry", { company: get_company() });
},
__("Create")
);
treeview.page.add_inner_button(
__("Company"),
function () {
frappe.new_doc("Company");
},
__("Create")
);
treeview.page.add_inner_button(__("Journal Entry"), function() {
frappe.new_doc('Journal Entry', {company: get_company()});
}, __('Create'));
treeview.page.add_inner_button(__("Company"), function() {
frappe.new_doc('Company');
}, __('Create'));
// financial statements
for (let report of [
"Trial Balance",
"General Ledger",
"Balance Sheet",
"Profit and Loss Statement",
"Cash Flow Statement",
"Accounts Payable",
"Accounts Receivable",
]) {
treeview.page.add_inner_button(
__(report),
function () {
frappe.set_route("query-report", report, { company: get_company() });
},
__("Financial Statements")
);
for (let report of ['Trial Balance', 'General Ledger', 'Balance Sheet',
'Profit and Loss Statement', 'Cash Flow Statement', 'Accounts Payable', 'Accounts Receivable']) {
treeview.page.add_inner_button(__(report), function() {
frappe.set_route('query-report', report, {company: get_company()});
}, __('Financial Statements'));
}
},
post_render: function (treeview) {
frappe.treeview_settings["Account"].treeview["tree"] = treeview.tree;
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"
);
},
post_render: function(treeview) {
frappe.treeview_settings['Account'].treeview["tree"] = treeview.tree;
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: [
{
label: __("Add Child"),
condition: function (node) {
return (
frappe.boot.user.can_create.indexOf("Account") !== -1 &&
(!frappe.treeview_settings[
"Account"
].treeview.page.fields_dict.root_company.get_value() ||
frappe.flags.ignore_root_company_validation) &&
node.expandable &&
!node.hide_add
);
label:__("Add Child"),
condition: function(node) {
return frappe.boot.user.can_create.indexOf("Account") !== -1
&& (!frappe.treeview_settings['Account'].treeview.page.fields_dict.root_company.get_value()
|| frappe.flags.ignore_root_company_validation)
&& node.expandable && !node.hide_add;
},
click: function () {
var me = frappe.views.trees["Account"];
click: function() {
var me = frappe.views.trees['Account'];
me.new_node();
},
btnClass: "hidden-xs",
btnClass: "hidden-xs"
},
{
condition: function (node) {
return !node.root && frappe.boot.user.can_read.indexOf("GL Entry") !== -1;
condition: function(node) {
return !node.root && frappe.boot.user.can_read.indexOf("GL Entry") !== -1
},
label: __("View Ledger"),
click: function (node, btn) {
click: function(node, btn) {
frappe.route_options = {
account: node.label,
from_date: erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[1],
to_date: erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[2],
company:
frappe.treeview_settings["Account"].treeview.page.fields_dict.company.get_value(),
"account": node.label,
"from_date": frappe.sys_defaults.year_start_date,
"to_date": frappe.sys_defaults.year_end_date,
"company": frappe.treeview_settings['Account'].treeview.page.fields_dict.company.get_value()
};
frappe.set_route("query-report", "General Ledger");
},
btnClass: "hidden-xs",
},
btnClass: "hidden-xs"
}
],
extend_toolbar: true,
};
extend_toolbar: true
}

View File

@@ -29,8 +29,8 @@ def create_charts(
"root_type",
"is_group",
"tax_rate",
"account_currency",
]:
account_number = cstr(child.get("account_number")).strip()
account_name, account_name_in_db = add_suffix_if_duplicate(
account_name, account_number, accounts
@@ -38,9 +38,7 @@ def create_charts(
is_group = identify_is_group(child)
report_type = (
"Balance Sheet"
if root_type in ["Asset", "Liability", "Equity"]
else "Profit and Loss"
"Balance Sheet" if root_type in ["Asset", "Liability", "Equity"] else "Profit and Loss"
)
account = frappe.get_doc(
@@ -55,7 +53,7 @@ def create_charts(
"account_number": account_number,
"account_type": child.get("account_type"),
"account_currency": child.get("account_currency")
or frappe.db.get_value("Company", company, "default_currency"),
or frappe.get_cached_value("Company", company, "default_currency"),
"tax_rate": child.get("tax_rate"),
}
)
@@ -97,17 +95,7 @@ def identify_is_group(child):
is_group = child.get("is_group")
elif len(
set(child.keys())
- set(
[
"account_name",
"account_type",
"root_type",
"is_group",
"tax_rate",
"account_number",
"account_currency",
]
)
- set(["account_name", "account_type", "root_type", "is_group", "tax_rate", "account_number"])
):
is_group = 1
else:
@@ -142,7 +130,7 @@ def get_chart(chart_template, existing_company=None):
for fname in os.listdir(path):
fname = frappe.as_unicode(fname)
if fname.endswith(".json"):
with open(os.path.join(path, fname)) as f:
with open(os.path.join(path, fname), "r") as f:
chart = f.read()
if chart and json.loads(chart).get("name") == chart_template:
return json.loads(chart).get("tree")
@@ -160,7 +148,7 @@ def get_charts_for_country(country, with_standard=False):
) or frappe.local.flags.allow_unverified_charts:
charts.append(content["name"])
country_code = frappe.db.get_value("Country", country, "code")
country_code = frappe.get_cached_value("Country", country, "code")
if country_code:
folders = ("verified",)
if frappe.local.flags.allow_unverified_charts:
@@ -174,7 +162,7 @@ def get_charts_for_country(country, with_standard=False):
for fname in os.listdir(path):
fname = frappe.as_unicode(fname)
if (fname.startswith(country_code) or fname.startswith(country)) and fname.endswith(".json"):
with open(os.path.join(path, fname)) as f:
with open(os.path.join(path, fname), "r") as f:
_get_chart_name(f.read())
# if more than one charts, returned then add the standard
@@ -197,7 +185,6 @@ def get_account_tree_from_existing_company(existing_company):
"root_type",
"tax_rate",
"account_number",
"account_currency",
],
order_by="lft, rgt",
)
@@ -248,13 +235,7 @@ def validate_bank_account(coa, bank_account):
def _get_account_names(account_master):
for account_name, child in account_master.items():
if account_name not in [
"account_number",
"account_type",
"root_type",
"is_group",
"tax_rate",
]:
if account_name not in ["account_number", "account_type", "root_type", "is_group", "tax_rate"]:
accounts.append(account_name)
_get_account_names(child)
@@ -286,7 +267,6 @@ def build_tree_from_json(chart_template, chart_data=None, from_coa_importer=Fals
"root_type",
"is_group",
"tax_rate",
"account_currency",
]:
continue

View File

@@ -26,7 +26,7 @@ def go():
default_account_types = get_default_account_types()
country_dirs = []
for basepath, _folders, _files in os.walk(path):
for basepath, folders, files in os.walk(path):
basename = os.path.basename(basepath)
if basename.startswith("l10n_"):
country_dirs.append(basename)
@@ -35,7 +35,9 @@ def go():
accounts, charts = {}, {}
country_path = os.path.join(path, country_dir)
manifest = ast.literal_eval(open(os.path.join(country_path, "__openerp__.py")).read())
data_files = manifest.get("data", []) + manifest.get("init_xml", []) + manifest.get("update_xml", [])
data_files = (
manifest.get("data", []) + manifest.get("init_xml", []) + manifest.get("update_xml", [])
)
files_path = [os.path.join(country_path, d) for d in data_files]
xml_roots = get_xml_roots(files_path)
csv_content = get_csv_contents(files_path)
@@ -88,10 +90,10 @@ def get_csv_contents(files_path):
fname = os.path.basename(filepath)
for file_type in ["account.account.template", "account.account.type", "account.chart.template"]:
if fname.startswith(file_type) and fname.endswith(".csv"):
with open(filepath) as csvfile:
with open(filepath, "r") as csvfile:
try:
csv_content.setdefault(file_type, []).append(read_csv_content(csvfile.read()))
except Exception:
except Exception as e:
continue
return csv_content
@@ -136,7 +138,7 @@ def get_account_types(root_list, csv_content, prefix=None):
if csv_content and csv_content[0][0] == "id":
for row in csv_content[1:]:
row_dict = dict(zip(csv_content[0], row, strict=False))
row_dict = dict(zip(csv_content[0], row))
data = {}
if row_dict.get("code") and account_type_map.get(row_dict["code"]):
data["account_type"] = account_type_map[row_dict["code"]]
@@ -148,7 +150,7 @@ def get_account_types(root_list, csv_content, prefix=None):
def make_maps_for_xml(xml_roots, account_types, country_dir):
"""make maps for `charts` and `accounts`"""
for _model, root_list in xml_roots.items():
for model, root_list in xml_roots.items():
for root in root_list:
for node in root[0].findall("record"):
if node.get("model") == "account.account.template":
@@ -184,7 +186,7 @@ def make_maps_for_xml(xml_roots, account_types, country_dir):
def make_maps_for_csv(csv_content, account_types, country_dir):
for content in csv_content.get("account.account.template", []):
for row in content[1:]:
data = dict(zip(content[0], row, strict=False))
data = dict(zip(content[0], row))
account = {
"name": data.get("name"),
"parent_id": data.get("parent_id:id") or data.get("parent_id/id"),
@@ -204,7 +206,7 @@ def make_maps_for_csv(csv_content, account_types, country_dir):
for content in csv_content.get("account.chart.template", []):
for row in content[1:]:
if row:
data = dict(zip(content[0], row, strict=False))
data = dict(zip(content[0], row))
charts.setdefault(data.get("id"), {}).update(
{
"account_root_id": data.get("account_root_id:id") or data.get("account_root_id/id"),
@@ -239,7 +241,7 @@ def make_charts():
if not src.get("name") or not src.get("account_root_id"):
continue
if src["account_root_id"] not in accounts:
if not src["account_root_id"] in accounts:
continue
filename = src["id"][5:] + "_" + chart_id
@@ -253,20 +255,14 @@ def make_charts():
for key, val in chart["tree"].items():
if key in ["name", "parent_id"]:
chart["tree"].pop(key)
if isinstance(val, dict):
if type(val) == dict:
val["root_type"] = ""
if chart:
fpath = os.path.join(
"erpnext",
"erpnext",
"accounts",
"doctype",
"account",
"chart_of_accounts",
filename + ".json",
"erpnext", "erpnext", "accounts", "doctype", "account", "chart_of_accounts", filename + ".json"
)
with open(fpath) as chartfile:
with open(fpath, "r") as chartfile:
old_content = chartfile.read()
if not old_content or (
json.loads(old_content).get("is_active", "No") == "No"

View File

@@ -2,397 +2,438 @@
"country_code": "at",
"name": "Austria - Chart of Accounts",
"tree": {
"Summe Abschreibungen und Aufwendungen": {
"7010 bis 7080 Abschreibungen auf das Anlageverm\u00f6gen (ausgenommen Finanzanlagen)": {},
"7100 bis 7190 Sonstige Steuern": {
"account_type": "Tax"
},
"7200 bis 7290 Instandhaltung u. Reinigung durh Dritte, Entsorgung, Beleuchtung": {},
"7300 bis 7310 Transporte durch Dritte": {},
"7320 bis 7330 Kfz - Aufwand": {},
"7340 bis 7350 Reise- und Fahraufwand": {},
"7360 bis 7370 Tag- und N\u00e4chtigungsgelder": {},
"7380 bis 7390 Nachrichtenaufwand": {},
"7400 bis 7430 Miet- und Pachtaufwand": {},
"7440 bis 7470 Leasingaufwand": {},
"7480 bis 7490 Lizenzaufwand": {},
"7500 bis 7530 Aufwand f\u00fcr beigestelltes Personal": {},
"7540 bis 7570 Provisionen an Dritte": {},
"7580 bis 7590 Aufsichtsratsverg\u00fctungen": {},
"7610 bis 7620 Druckerzeugnisse und Vervielf\u00e4ltigungen": {},
"7650 bis 7680 Werbung und Repr\u00e4sentationen": {},
"7700 bis 7740 Versicherungen": {},
"7750 bis 7760 Beratungs- und Pr\u00fcfungsaufwand": {},
"7800 bis 7810 Schadensf\u00e4lle": {},
"7840 bis 7880 Verschiedene betriebliche Aufwendungen": {},
"7910 bis 7950 Aufwandsstellenrechung der Hersteller": {},
"Abschreibungen auf aktivierte Aufwendungen f\u00fcr das Ingangs. u. Erweitern des Betriebes": {},
"Abschreibungen vom Umlaufverm\u00f6gen, soweit diese die im Unternehmen \u00fcblichen Abschreibungen \u00fcbersteigen": {},
"Aufwandsstellenrechnung": {},
"Aus- und Fortbildung": {},
"Buchwert abgegangener Anlagen, ausgenommen Finanzanlagen": {},
"B\u00fcromaterial und Drucksorten": {},
"Fachliteratur und Zeitungen ": {},
"Herstellungskosten der zur Erzielung der Umsatzerl\u00f6se erbrachten Leistungen": {},
"Mitgliedsbeitr\u00e4ge": {},
"Skontoertr\u00e4ge auf sonstige betriebliche Aufwendungen": {},
"Sonstige betrieblichen Aufwendungen": {},
"Spenden und Trinkgelder": {},
"Spesen des Geldverkehrs": {},
"Verluste aus dem Abgang vom Anlageverm\u00f6gen, ausgenommen Finanzanlagen": {},
"Vertriebskosten": {},
"Verwaltungskosten": {},
"root_type": "Expense"
},
"Summe Betriebliche Ertr\u00e4ge": {
"4400 bis 4490 Erl\u00f6sschm\u00e4lerungen": {},
"4500 bis 4570 Ver\u00e4nderungen des Bestandes an fertigen und unfertigen Erzeugn. sowie an noch nicht abrechenbaren Leistungen": {},
"4580 bis 4590 andere aktivierte Eigenleistungen": {},
"4600 bis 4620 Erl\u00f6se aus dem Abgang vom Anlageverm\u00f6gen, ausgen. Finanzanlagen": {},
"4630 bis 4650 Ertr\u00e4ge aus dem Abgang vom Anlageverm\u00f6gen, ausgen. Finanzanlagen": {},
"4660 bis 4670 Ertr\u00e4ge aus der Zuschreibung zum Anlageverm\u00f6gen, ausgen. Finanzanlagen": {},
"4700 bis 4790 Ertr\u00e4ge aus der Aufl\u00f6sung von R\u00fcckstellungen": {},
"4800 bis 4990 \u00dcbrige betriebliche Ertr\u00e4ge": {},
"Erl\u00f6se 0 % Ausfuhrlieferungen/Drittl\u00e4nder": {},
"Erl\u00f6se 10 %": {},
"Erl\u00f6se 20 %": {},
"Erl\u00f6se aus im Inland stpfl. EG Lieferungen 10 % USt": {},
"Erl\u00f6se aus im Inland stpfl. EG Lieferungen 20 % USt": {},
"Erl\u00f6se i.g. Lieferungen (stfr)": {},
"root_type": "Income"
},
"Summe Eigenkapital R\u00fccklagen Abschlusskonten": {
"9000 bis 9180 Gezeichnetes bzw. gewidmetes Kapital": {
"account_type": "Equity"
},
"9200 bis 9290 Kapitalr\u00fccklagen": {
"account_type": "Equity"
},
"9300 bis 9380 Gewinnr\u00fccklagen": {
"account_type": "Equity"
},
"9400 bis 9590 Bewertungsreserven uns sonst. unversteuerte R\u00fccklagen": {
"account_type": "Equity"
},
"9600 bis 9690 Privat und Verrechnungskonten bei Einzelunternehmen und Personengesellschaften": {},
"9700 bis 9790 Einlagen stiller Gesellschafter ": {},
"9900 bis 9999 Evidenzkonten": {},
"Bilanzgewinn (-verlust )": {
"account_type": "Equity"
},
"Er\u00f6ffnungsbilanz": {},
"Gewinn- und Verlustrechnung": {},
"Schlussbilanz": {},
"nicht eingeforderte ausstehende Einlagen": {
"account_type": "Equity"
},
"root_type": "Equity"
},
"Summe Finanzertr\u00e4ge und Aufwendungen": {
"8000 bis 8040 Ertr\u00e4ge aus Beteiligungen": {},
"8050 bis 8090 Ertr\u00e4ge aus anderen Wertpapieren und Ausleihungen des Finanzanlageverm\u00f6gens": {},
"8100 bis 8130 Sonstige Zinsen und \u00e4hnliche Ertr\u00e4ge": {},
"8220 bis 8250 Aufwendungen aus Beteiligungen": {},
"8260 bis 8270 Aufwendungen aus sonst. Fiananzanlagen und aus Wertpapieren des Umlaufverm\u00f6gens": {},
"8280 bis 8340 Zinsen und \u00e4hnliche Aufwendungem": {},
"8400 bis 8440 Au\u00dferordentliche Ertr\u00e4ge": {},
"8450 bis 8490 Au\u00dferordentliche Aufwendungen": {},
"8500 bis 8590 Steuern vom Einkommen und vom Ertrag": {
"account_type": "Tax"
},
"8600 bis 8690 Aufl\u00f6sung unversteuerten R\u00fccklagen": {},
"8700 bis 8740 Aufl\u00f6sung von Kapitalr\u00fccklagen": {},
"8750 bis 8790 Aufl\u00f6sung von Gewinnr\u00fccklagen": {},
"8800 bis 8890 Zuweisung von unversteuerten R\u00fccklagen": {},
"Buchwert abgegangener Beteiligungen": {},
"Buchwert abgegangener Wertpapiere des Umlaufverm\u00f6gens": {},
"Buchwert abgegangener sonstiger Finanzanlagen": {},
"Erl\u00f6se aus dem Abgang von Beteiligungen": {},
"Erl\u00f6se aus dem Abgang von Wertpapieren des Umlaufverm\u00f6gens": {},
"Erl\u00f6se aus dem Abgang von sonstigen Finanzanlagen": {},
"Ertr\u00e4ge aus dem Abgang von und der Zuschreibung zu Finanzanlagen": {},
"Ertr\u00e4ge aus dem Abgang von und der Zuschreibung zu Wertpapieren des Umlaufverm\u00f6gens": {},
"Gewinabfuhr bzw. Verlust\u00fcberrechnung aus Ergebnisabf\u00fchrungsvertr\u00e4gen": {},
"nicht ausgenutzte Lieferantenskonti": {},
"root_type": "Income"
},
"Summe Fremdkapital": {
"3020 bis 3030 Steuerr\u00fcckstellungen": {},
"3040 bis 3090 Sonstige R\u00fcckstellungen": {},
"3110 bis 3170 Verbindlichkeiten gegen\u00fcber Kredidinstituten": {},
"3180 bis 3190 Verbindlichkeiten gegen\u00fcber Finanzinstituten": {},
"3380 bis 3390 Verbindlichkeiten aus der Annahme gezogener Wechsel u. d. Ausstellungen eigener Wechsel": {
"Klasse 0 Aktiva: Anlageverm\u00f6gen": {
"0100 Konzessionen ": {"account_type": "Fixed Asset"},
"0110 Patentrechte und Lizenzen ": {"account_type": "Fixed Asset"},
"0120 Datenverarbeitungsprogramme ": {"account_type": "Fixed Asset"},
"0130 Marken, Warenzeichen und Musterschutzrechte, sonstige Urheberrechte ": {"account_type": "Fixed Asset"},
"0140 Pacht- und Mietrechte ": {"account_type": "Fixed Asset"},
"0150 Bezugs- und ähnliche Rechte ": {"account_type": "Fixed Asset"},
"0160 Geschäfts-/Firmenwert ": {"account_type": "Fixed Asset"},
"0170 Umgründungsmehrwert ": {"account_type": "Fixed Asset"},
"0180 Geleistete Anzahlungen auf immaterielle Vermögensgegenstände": {"account_type": "Fixed Asset"},
"0190 Kumulierte Abschreibungen zu immateriellen Vermögensgegenständen ": {"account_type": "Fixed Asset"},
"0200 Unbebaute Grundstücke, soweit nicht landwirtschaftlich genutzt ": {"account_type": "Fixed Asset"},
"0210 Bebaute Grundstücke (Grundwert) ": {"account_type": "Fixed Asset"},
"0220 Landwirtschaftlich genutzte Grundstücke ": {"account_type": "Fixed Asset"},
"0230 Grundstücksgleiche Rechte ": {"account_type": "Fixed Asset"},
"0300 Betriebs- und Geschäftsgebäude auf eigenem Grund ": {"account_type": "Fixed Asset"},
"0310 Wohn- und Sozialgebäude auf eigenem Grund ": {"account_type": "Fixed Asset"},
"0320 Betriebs- und Geschäftsgebäude auf fremdem Grund ": {"account_type": "Fixed Asset"},
"0330 Wohn- und Sozialgebäude auf fremdem Grund ": {"account_type": "Fixed Asset"},
"0340 Grundstückseinrichtungen auf eigenem Grund ": {"account_type": "Fixed Asset"},
"0350 Grundstückseinrichtungen auf fremdem Grund ": {"account_type": "Fixed Asset"},
"0360 Bauliche Investitionen in fremden (gepachteten) Betriebs- und Geschäftsgebäuden": {"account_type": "Fixed Asset"},
"0370 Bauliche Investitionen in fremden (gepachteten) Wohn- und Sozialgebäuden": {"account_type": "Fixed Asset"},
"0390 Kumulierte Abschreibungen zu Grundstücken ": {"account_type": "Fixed Asset"},
"0400 Maschinen und Geräte ": {"account_type": "Fixed Asset"},
"0500 Maschinenwerkzeuge ": {"account_type": "Fixed Asset"},
"0510 Allgemeine Werkzeuge und Handwerkzeuge ": {"account_type": "Fixed Asset"},
"0520 Prototypen, Formen, Modelle ": {"account_type": "Fixed Asset"},
"0530 Andere Erzeugungshilfsmittel (auch Softwarewerkzeuge)": {"account_type": "Fixed Asset"},
"0540 Hebezeuge und Montageanlagen ": {"account_type": "Fixed Asset"},
"0550 Geringwertige Vermögensgegenstände, soweit im Erzeugungsprozess ": {"account_type": "Fixed Asset"},
"0560 Festwerte technische Anlagen und Maschinen ": {"account_type": "Fixed Asset"},
"0590 Kumulierte Abschreibungen zu technischen Anlagen und Maschinen ": {"account_type": "Fixed Asset"},
"0600 Betriebs- und Geschäftsausstattung, soweit nicht gesondert angeführt ": {"account_type": "Fixed Asset"},
"0610 Andere Anlagen, soweit nicht gesondert angeführt ": {"account_type": "Fixed Asset"},
"0620 Büromaschinen, EDV-Anlagen ": {"account_type": "Fixed Asset"},
"0630 PKW und Kombis ": {"account_type": "Fixed Asset"},
"0640 LKW ": {"account_type": "Fixed Asset"},
"0650 Andere Beförderungsmittel ": {"account_type": "Fixed Asset"},
"0660 Gebinde ": {"account_type": "Fixed Asset"},
"0670 Geringwertige Vermögensgegenstände, soweit nicht im Erzeugungssprozess verwendet": {"account_type": "Fixed Asset"},
"0680 Festwerte außer technische Anlagen und Maschinen ": {"account_type": "Fixed Asset"},
"0690 Kumulierte Abschreibungen zu anderen Anlagen, Betriebs- und Geschäftsausstattung": {"account_type": "Fixed Asset"},
"0700 Geleistete Anzahlungen auf Sachanlagen ": {"account_type": "Fixed Asset"},
"0710 Anlagen in Bau ": {"account_type": "Fixed Asset"},
"0790 Kumulierte Abschreibungen zu geleisteten Anzahlungen auf Sachanlagen ": {"account_type": "Fixed Asset"},
"0800 Anteile an verbundenen Unternehmen ": {"account_type": "Fixed Asset"},
"0810 Beteiligungen an Gemeinschaftsunternehmen ": {"account_type": "Fixed Asset"},
"0820 Beteiligungen an angeschlossenen (assoziierten) Unternehmen ": {"account_type": "Fixed Asset"},
"0830 Eigene Anteile, Anteile an herrschenden oder mit Mehrheit beteiligten ": {"account_type": "Fixed Asset"},
"0840 Sonstige Beteiligungen ": {"account_type": "Fixed Asset"},
"0850 Ausleihungen an verbundene Unternehmen ": {"account_type": "Fixed Asset"},
"0860 Ausleihungen an Unternehmen mit Beteiligungsverhältnis": {"account_type": "Fixed Asset"},
"0870 Ausleihungen an Gesellschafter ": {"account_type": "Fixed Asset"},
"0880 Sonstige Ausleihungen ": {"account_type": "Fixed Asset"},
"0890 Anteile an Kapitalgesellschaften ohne Beteiligungscharakter ": {"account_type": "Fixed Asset"},
"0900 Anteile an Personengesellschaften ohne Beteiligungscharakter ": {"account_type": "Fixed Asset"},
"0910 Genossenschaftsanteile ohne Beteiligungscharakter ": {"account_type": "Fixed Asset"},
"0920 Anteile an Investmentfonds ": {"account_type": "Fixed Asset"},
"0930 Festverzinsliche Wertpapiere des Anlagevermögens ": {"account_type": "Fixed Asset"},
"0980 Geleistete Anzahlungen auf Finanzanlagen ": {"account_type": "Fixed Asset"},
"0990 Kumulierte Abschreibungen zu Finanzanlagen ": {"account_type": "Fixed Asset"},
"root_type": "Asset"
},
"Klasse 1 Aktiva: Vorr\u00e4te": {
"1000 Bezugsverrechnung": {"account_type": "Stock"},
"1100 Rohstoffe": {"account_type": "Stock"},
"1200 Bezogene Teile": {"account_type": "Stock"},
"1300 Hilfsstoffe": {"account_type": "Stock"},
"1350 Betriebsstoffe": {"account_type": "Stock"},
"1360 Vorrat Energietraeger": {"account_type": "Stock"},
"1400 Unfertige Erzeugnisse": {"account_type": "Stock"},
"1500 Fertige Erzeugnisse": {"account_type": "Stock"},
"1600 Handelswarenvorrat": {"account_type": "Stock Received But Not Billed"},
"1700 Noch nicht abrechenbare Leistungen": {"account_type": "Stock"},
"1900 Wertberichtigungen": {"account_type": "Stock"},
"1800 Geleistete Anzahlungen": {"account_type": "Stock"},
"1900 Wertberichtigungen": {"account_type": "Stock"},
"root_type": "Asset"
},
"Klasse 3 Passiva: Verbindlichkeiten": {
"3000 Allgemeine Verbindlichkeiten (Schuld)": {"account_type": "Payable"},
"3010 R\u00fcckstellungen f\u00fcr Pensionen": {"account_type": "Payable"},
"3020 Steuerr\u00fcckstellungen": {"account_type": "Tax"},
"3041 Sonstige R\u00fcckstellungen": {"account_type": "Payable"},
"3110 Verbindlichkeiten gegen\u00fcber Bank": {"account_type": "Payable"},
"3150 Verbindlichkeiten Darlehen": {"account_type": "Payable"},
"3185 Verbindlichkeiten Kreditkarte": {"account_type": "Payable"},
"3380 Verbindlichkeiten aus der Annahme gezogener Wechsel u. d. Ausstellungen eigener Wechsel": {
"account_type": "Payable"
},
"3400 bis 3470 Verbindlichkeiten gegen\u00fc. verb. Untern., Verbindl. gegen\u00fc. Untern., mit denen eine Beteiligungsverh\u00e4lnis besteht": {},
"3600 bis 3690 Verbindlichkeiten im Rahmen der sozialen Sicherheit": {},
"3700 bis 3890 \u00dcbrige sonstige Verbindlichkeiten": {},
"3900 bis 3990 Passive Rechnungsabgrenzungsposten": {},
"Anleihen (einschlie\u00dflich konvertibler)": {},
"Erhaltene Anzahlungenauf Bestellungen": {},
"R\u00fcckstellungen f\u00fcr Abfertigung": {},
"R\u00fcckstellungen f\u00fcr Pensionen": {},
"USt. \u00a719 /art (reverse charge)": {
"3400 Verbindlichkeiten gegen\u00fc. verb. Untern., Verbindl. gegen\u00fc. Untern., mit denen eine Beteiligungsverh\u00e4lnis besteht": {},
"3460 Verbindlichkeiten gegenueber Gesellschaftern": {"account_type": "Payable"},
"3470 Einlagen stiller Gesellschafter": {"account_type": "Payable"},
"3585 Verbindlichkeiten Lohnsteuer": {"account_type": "Tax"},
"3590 Verbindlichkeiten Kommunalabgaben": {"account_type": "Tax"},
"3595 Verbindlichkeiten Dienstgeberbeitrag": {"account_type": "Tax"},
"3600 Verbindlichkeiten Sozialversicherung": {"account_type": "Payable"},
"3640 Verbindlichkeiten Loehne und Gehaelter": {"account_type": "Payable"},
"3700 Sonstige Verbindlichkeiten": {"account_type": "Payable"},
"3900 Passive Rechnungsabgrenzungsposten": {"account_type": "Payable"},
"3100 Anleihen (einschlie\u00dflich konvertibler)": {"account_type": "Payable"},
"3200 Erhaltene Anzahlungen auf Bestellungen": {"account_type": "Payable"},
"3040 R\u00fcckstellungen f\u00fcr Abfertigung": {"account_type": "Payable"},
"3530 USt. \u00a719 (reverse charge)": {
"account_type": "Tax"
},
"Umsatzsteuer": {},
"Umsatzsteuer Zahllast": {
"3500 Verbindlichkeiten aus Umsatzsteuer": {"account_type": "Tax"},
"3580 Umsatzsteuer Zahllast": {
"account_type": "Tax"
},
"Umsatzsteuer aus i.g. Erwerb 10%": {
"3510 Umsatzsteuer Inland 20%": {
"account_type": "Tax"
},
"Umsatzsteuer aus i.g. Erwerb 20%": {
"3515 Umsatzsteuer Inland 10%": {
"account_type": "Tax"
},
"3520 Umsatzsteuer aus i.g. Erwerb 20%": {
"account_type": "Tax"
},
"Umsatzsteuer aus i.g. Lieferungen 10%": {
"3525 Umsatzsteuer aus i.g. Erwerb 10%": {
"account_type": "Tax"
},
"Umsatzsteuer aus i.g. Lieferungen 20%": {
"account_type": "Tax"
},
"Umsatzsteuer-Evidenzkonto f\u00fcr erhaltene Anzahlungen auf Bestellungen": {},
"Verbindlichkeiten aus Lieferungen u. Leistungen EU": {
},
"3560 Umsatzsteuer-Evidenzkonto f\u00fcr erhaltene Anzahlungen auf Bestellungen": {},
"3360 Verbindlichkeiten aus Lieferungen u. Leistungen EU": {
"account_type": "Payable"
},
"Verbindlichkeiten aus Lieferungen u. Leistungen Inland": {
"3000 Verbindlichkeiten aus Lieferungen u. Leistungen Inland": {
"account_type": "Payable"
},
"Verbindlichkeiten aus Lieferungen u. Leistungen sonst. Ausland": {
"3370 Verbindlichkeiten aus Lieferungen u. Leistungen sonst. Ausland": {
"account_type": "Payable"
},
"Verbindlichkeiten gegen\u00fcber Gesellschaften": {},
"Verrechnung Finanzamt": {
"3400 Verbindlichkeiten gegen\u00fcber verbundenen Unternehmen": {},
"3570 Verrechnung Finanzamt": {
"account_type": "Tax"
},
"root_type": "Liability"
},
"Summe Kontoklasse 0 Anlageverm\u00f6gen": {
"44 bis 49 Sonstige Maschinen und maschinelle Anlagen": {},
"920 bis 930 Festverzinsliche Wertpapiere des Anlageverm\u00f6gens": {},
"940 bis 970 Sonstige Finanzanlagen, Wertrechte": {},
"Allgemeine Werkzeuge und Handwerkzeuge": {},
"Andere Bef\u00f6rderungsmittel": {},
"Andere Betriebs- und Gesch\u00e4ftsausstattung": {},
"Andere Erzeugungshilfsmittel": {},
"Anlagen im Bau": {},
"Anteile an Investmentfonds": {},
"Anteile an Kapitalgesellschaften ohne Beteiligungscharakter": {},
"Anteile an Personengesellschaften ohne Beteiligungscharakter": {},
"Anteile an verbundenen Unternehmen": {},
"Antriebsmaschinen": {},
"Aufwendungen f\u00fcs das Ingangssetzen u. Erweitern eines Betriebes": {},
"Ausleihungen an verbundene Unternehmen": {},
"Ausleihungen an verbundene Unternehmen, mit denen ein Beteiligungsverh\u00e4lnis besteht": {},
"Bauliche Investitionen in fremden (gepachteten) Betriebs- und Gesch\u00e4ftsgeb\u00e4uden": {},
"Bauliche Investitionen in fremden (gepachteten) Wohn- und Sozialgeb\u00e4uden": {},
"Bebaute Grundst\u00fccke (Grundwert)": {},
"Beheizungs- und Beleuchtungsanlagen": {},
"Beteiligungen an Gemeinschaftunternehmen": {},
"Beteiligungen an angeschlossenen (assoziierten) Unternehmen": {},
"Betriebs- und Gesch\u00e4ftsgeb\u00e4ude auf eigenem Grund": {},
"Betriebs- und Gesch\u00e4ftsgeb\u00e4ude auf fremdem Grund": {},
"B\u00fcromaschinen, EDV - Anlagen": {},
"Datenverarbeitungsprogramme": {},
"Energieversorgungsanlagen": {},
"Fertigungsmaschinen": {},
"Gebinde": {},
"Geleistete Anzahlungen": {},
"Genossenschaften ohne Beteiligungscharakter": {},
"Geringwertige Verm\u00f6gensgegenst\u00e4nde, soweit im Erzeugerprozess verwendet": {},
"Geringwertige Verm\u00f6gensgegenst\u00e4nde, soweit nicht im Erzeugungsprozess verwendet": {},
"Gesch\u00e4fts(Firmen)wert": {},
"Grundst\u00fcckseinrichtunten auf eigenem Grund": {},
"Grundst\u00fcckseinrichtunten auf fremdem Grund": {},
"Grundst\u00fccksgleiche Rechte": {},
"Hebezeuge und Montageanlagen": {},
"Konzessionen": {},
"Kumulierte Abschreibungen": {},
"LKW": {},
"Marken, Warenzeichen und Musterschutzrechte": {},
"Maschinenwerkzeuge": {},
"Nachrichten- und Kontrollanlagen": {},
"PKW": {},
"Pacht- und Mietrechte": {},
"Patentrechte und Lizenzen": {},
"Sonstige Ausleihungen": {},
"Sonstige Beteiligungen": {},
"Transportanlagen": {},
"Unbebaute Grundst\u00fccke": {},
"Vorrichtungen, Formen und Modelle": {},
"Wohn- und Sozialgeb\u00e4ude auf eigenem Grund": {},
"Wohn- und Sozialgeb\u00e4ude auf fremdem Grund": {},
},
"Klasse 2 Aktiva: Umlaufverm\u00f6gen, Rechnungsabgrenzungen": {
"2030 Forderungen aus Lieferungen und Leistungen Inland (0% USt, umsatzsteuerfrei)": {
"account_type": "Receivable"
},
"2010 Forderungen aus Lieferungen und Leistungen Inland (10% USt, umsatzsteuerfrei)": {
"account_type": "Receivable"
},
"2000 Forderungen aus Lieferungen und Leistungen Inland (20% USt, umsatzsteuerfrei)": {
"account_type": "Receivable"
},
"2040 Forderungen aus Lieferungen und Leistungen Inland (sonstiger USt-Satz)": {
"account_type": "Receivable"
},
"2100 Forderungen aus Lieferungen und Leistungen EU": {
"account_type": "Receivable"
},
"2150 Forderungen aus Lieferungen und Leistungen Ausland (Nicht-EU)": {
"account_type": "Receivable"
},
"2200 Forderungen gegen\u00fcber verbundenen Unternehmen": {
"account_type": "Receivable"
},
"2250 Forderungen gegen\u00fcber Unternehmen, mit denen ein Beteiligungsverh\u00e4ltnis besteht": {
"account_type": "Receivable"
},
"2300 Sonstige Forderungen und Verm\u00f6gensgegenst\u00e4nde": {
"account_type": "Receivable"
},
"2630 Sonstige Wertpapiere": {
"account_type": "Stock"
},
"2750 Kassenbest\u00e4nde in Fremdw\u00e4hrung": {
"account_type": "Cash"
},
"2900 Aktive Rechnungsabrenzungsposten": {
"account_type": "Receivable"
},
"2600 Anteile an verbundenen Unternehmen": {
"account_type": "Equity"
},
"2680 Besitzwechsel ohne Forderungen": {
"account_type": "Receivable"
},
"2950 Aktiviertes Disagio": {
"account_type": "Receivable"
},
"2610 Eigene Anteile und Wertpapiere an mit Mehrheit beteiligten Unternehmen": {
"account_type": "Receivable"
},
"2570 Einfuhrumsatzsteuer (bezahlt)": {"account_type": "Tax"},
"2460 Eingeforderte aber noch nicht eingezahlte Einlagen": {
"account_type": "Receivable"
},
"2180 Einzelwertberichtigungen zu Forderungen aus Lief. und Leist. Ausland": {
"account_type": "Receivable"
},
"2130 Einzelwertberichtigungen zu Forderungen aus Lief. und Leist. EU": {
"account_type": "Receivable"
},
"2080 Einzelwertberichtigungen zu Forderungen aus Lief. und Leist. Inland ": {
"account_type": "Receivable"
},
"2270 Einzelwertberichtigungen zu Forderungen gegen\u00fcber Unternehmen mit denen ein Beteiligungsverh\u00e4ltnis besteht": {
"account_type": "Receivable"
},
"2230 Einzelwertberichtigungen zu Forderungen gegen\u00fcber verbundenen Unternehmen": {
"account_type": "Receivable"
},
"2470 Einzelwertberichtigungen zu sonstigen Forderungen und Verm\u00f6gensgegenst\u00e4nden": {
"account_type": "Receivable"
},
"2700 Kassenbestand": {
"account_type": "Cash"
},
"2190 Pauschalwertberichtigungen zu Forderungen aus Lief. und Leist. sonstiges Ausland": {
"account_type": "Receivable"
},
"2130 Pauschalwertberichtigungen zu Forderungen aus Lief. und Leist. EU": {
"account_type": "Receivable"
},
"2100 Pauschalwertberichtigungen zu Forderungen aus Lief. und Leist. Inland ": {
"account_type": "Receivable"
},
"2280 Pauschalwertberichtigungen zu Forderungen gegen\u00fcber Unternehmen mit denen ein Beteiligungsverh\u00e4ltnis besteht": {
"account_type": "Receivable"
},
"2240 Pauschalwertberichtigungen zu Forderungen gegen\u00fcber verbundenen Unternehmen": {
"account_type": "Receivable"
},
"2480 Pauschalwertberichtigungen zu sonstigen Forderungen und Verm\u00f6gensgegenst\u00e4nden": {
"account_type": "Receivable"
},
"2740 Postwertzeichen": {
"account_type": "Cash"
},
"2780 Schecks in Euro": {
"account_type": "Cash"
},
"2800 Guthaben bei Bank": {
"account_type": "Bank"
},
"2801 Guthaben bei Bank - Sparkonto": {
"account_type": "Bank"
},
"2810 Guthaben bei Paypal": {
"account_type": "Bank"
},
"2930 Mietvorauszahlungen": {
"account_type": "Receivable"
},
"2980 Abgrenzung latenter Steuern": {
"account_type": "Receivable"
},
"2500 Vorsteuer": {
"account_type": "Receivable"
},
"2510 Vorsteuer Inland 10%": {
"account_type": "Tax"
},
"2895 Schwebende Geldbewegugen": {
"account_type": "Bank"
},
"2513 Vorsteuer Inland 5%": {
"account_type": "Tax"
},
"2515 Vorsteuer Inland 20%": {
"account_type": "Tax"
},
"2520 Vorsteuer aus innergemeinschaftlichem Erwerb 10%": {
"account_type": "Tax"
},
"2525 Vorsteuer aus innergemeinschaftlichem Erwerb 20%": {
"account_type": "Tax"
},
"2530 Vorsteuer \u00a719/Art 19 ( reverse charge ) ": {
"account_type": "Tax"
},
"2690 Wertberichtigungen zu Wertpapieren und Anteilen": {
"account_type": "Receivable"
},
"root_type": "Asset"
},
"Summe Personalaufwand": {
"6000 bis 6190 L\u00f6hne": {},
"6200 bis 6390 Geh\u00e4lter": {},
"6400 bis 6440 Aufwendungen f\u00fcr Abfertigungen": {},
"6450 bis 6490 Aufwendungen f\u00fcr Altersversorgung": {},
"6500 bis 6550 Gesetzlicher Sozialaufwand Arbeiter": {},
"6560 bis 6590 Gesetzlicher Sozialaufwand Angestellte": {},
"6600 bis 6650 Lohnabh\u00e4ngige Abgaben und Pflichtbeitr\u00e4gte": {},
"6660 bis 6690 Gehaltsabh\u00e4ngige Abgaben und Pflichtbeitr\u00e4gte": {},
"6700 bis 6890 Sonstige Sozialaufwendungen": {},
"Aufwandsstellenrechnung": {},
"Klasse 4: Betriebliche Erträge": {
"4000 Erlöse 20 %": {"account_type": "Income Account"},
"4020 Erl\u00f6se 0 % steuerbefreit": {"account_type": "Income Account"},
"4010 Erl\u00f6se 10 %": {"account_type": "Income Account"},
"4030 Erl\u00f6se 13 %": {"account_type": "Income Account"},
"4040 Erl\u00f6se 0 % innergemeinschaftliche Lieferungen": {"account_type": "Income Account"},
"4400 Erl\u00f6sreduktion 0 % steuerbefreit": {"account_type": "Expense Account"},
"4410 Erl\u00f6sreduktion 10 %": {"account_type": "Expense Account"},
"4420 Erl\u00f6sreduktion 20 %": {"account_type": "Expense Account"},
"4430 Erl\u00f6sreduktion 13 %": {"account_type": "Expense Account"},
"4440 Erl\u00f6sreduktion 0 % innergemeinschaftliche Lieferungen": {"account_type": "Expense Account"},
"4500 Ver\u00e4nderungen des Bestandes an fertigen und unfertigen Erzeugn. sowie an noch nicht abrechenbaren Leistungen": {"account_type": "Income Account"},
"4580 Aktivierte Eigenleistungen": {"account_type": "Income Account"},
"4600 Erl\u00f6se aus dem Abgang vom Anlageverm\u00f6gen, ausgen. Finanzanlagen": {"account_type": "Income Account"},
"4630 Ertr\u00e4ge aus dem Abgang vom Anlageverm\u00f6gen, ausgen. Finanzanlagen": {"account_type": "Income Account"},
"4660 Ertr\u00e4ge aus der Zuschreibung zum Anlageverm\u00f6gen, ausgen. Finanzanlagen": {"account_type": "Income Account"},
"4700 Ertr\u00e4ge aus der Aufl\u00f6sung von R\u00fcckstellungen": {"account_type": "Income Account"},
"4800 \u00dcbrige betriebliche Ertr\u00e4ge": {"account_type": "Income Account"},
"root_type": "Income"
},
"Klasse 5: Aufwand f\u00fcr Material und Leistungen": {
"5000 Einkauf Partnerleistungen": {"account_type": "Cost of Goods Sold"},
"5100 Verbrauch an Rohstoffen": {"account_type": "Cost of Goods Sold"},
"5200 Verbrauch von bezogenen Fertig- und Einzelteilen": {"account_type": "Cost of Goods Sold"},
"5300 Verbrauch von Hilfsstoffen": {"account_type": "Cost of Goods Sold"},
"5340 Verbrauch Verpackungsmaterial": {"account_type": "Cost of Goods Sold"},
"5470 Verbrauch von Kleinmaterial": {"account_type": "Cost of Goods Sold"},
"5450 Verbrauch von Reinigungsmaterial": {"account_type": "Cost of Goods Sold"},
"5400 Verbrauch von Betriebsstoffen": {"account_type": "Cost of Goods Sold"},
"5500 Verbrauch von Werkzeugen und anderen Erzeugungshilfsmittel": {"account_type": "Cost of Goods Sold"},
"5600 Verbrauch von Brenn- und Treibstoffen, Energie und Wasser": {"account_type": "Cost of Goods Sold"},
"5700 Bearbeitung durch Dritte": {"account_type": "Cost of Goods Sold"},
"5900 Aufwandsstellenrechnung Material": {"account_type": "Cost of Goods Sold"},
"5820 Skontoertr\u00e4ge (20% USt.)": {"account_type": "Income Account"},
"5810 Skontoertr\u00e4ge (10% USt.)": {"account_type": "Income Account"},
"5010 Handelswareneinkauf 10 %": {"account_type": "Cost of Goods Sold"},
"5020 Handelswareneinkauf 20 %": {"account_type": "Cost of Goods Sold"},
"5040 Handelswareneinkauf innergemeinschaftlicher Erwerb 10 % VSt/10 % USt": {"account_type": "Cost of Goods Sold"},
"5050 Handelswareneinkauf innergemeinschaftlicher Erwerb 20 % VSt/20 % USt": {"account_type": "Cost of Goods Sold"},
"5070 Handelswareneinkauf innergemeinschaftlicher Erwerb ohne Vorsteuerabzug und 10 % USt": {"account_type": "Cost of Goods Sold"},
"5080 Handelswareneinkauf innergemeinschaftlicher Erwerb ohne Vorsteuerabzug und 20 % USt": {"account_type": "Cost of Goods Sold"},
"root_type": "Expense"
},
"Summe Umlaufverm\u00f6gen": {
"2000 bis 2007 Forderungen aus Lief. und Leist. Inland": {
"account_type": "Receivable"
},
"2100 bis 2120 Forderungen aus Lief. und Leist. EU": {
"account_type": "Receivable"
},
"2150 bis 2170 Forderungen aus Lief. und Leist. Ausland": {
"account_type": "Receivable"
},
"2200 bis 2220 Forderungen gegen\u00fcber verbundenen Unternehmen": {
"account_type": "Receivable"
},
"2250 bis 2270 Forderungen gegen\u00fcber Unternehmen, mit denen ein Beteiligungsverh\u00e4ltnis besteht": {
"account_type": "Receivable"
},
"2300 bis 2460 Sonstige Forderungen und Verm\u00f6gensgegenst\u00e4nde": {
"account_type": "Receivable"
},
"2630 bis 2670 Sonstige Wertpapiere": {
"account_type": "Receivable"
},
"2750 bis 2770 Kassenbest\u00e4nde in Fremdw\u00e4hrung": {
"account_type": "Receivable"
},
"Aktive Rechnungsabrenzungsposten": {
"account_type": "Receivable"
},
"Anteile an verbundenen Unternehmen": {
"account_type": "Receivable"
},
"Bank / Guthaben bei Kreditinstituten": {
"account_type": "Receivable"
},
"Besitzwechsel ...": {
"account_type": "Receivable"
},
"Disagio": {
"account_type": "Receivable"
},
"Eigene Anteile (Wertpapiere)": {
"account_type": "Receivable"
},
"Einfuhrumsatzsteuer (bezahlt)": {},
"Eingeforderte aber noch nicht eingezahlte Einlagen": {
"account_type": "Receivable"
},
"Einzelwertberichtigungen zu Forderungen aus Lief. und Leist. Ausland": {
"account_type": "Receivable"
},
"Einzelwertberichtigungen zu Forderungen aus Lief. und Leist. EU": {
"account_type": "Receivable"
},
"Einzelwertberichtigungen zu Forderungen aus Lief. und Leist. Inland ": {
"account_type": "Receivable"
},
"Einzelwertberichtigungen zu Forderungen gegen\u00fcber Unternehmen mit denen ein Beteiligungsverh\u00e4ltnis besteht": {
"account_type": "Receivable"
},
"Einzelwertberichtigungen zu Forderungen gegen\u00fcber verbundenen Unternehmen": {
"account_type": "Receivable"
},
"Einzelwertberichtigungen zu sonstigen Forderungen und Verm\u00f6gensgegenst\u00e4nden": {
"account_type": "Receivable"
},
"Kassenbestand": {
"account_type": "Receivable"
},
"Pauschalwertberichtigungen zu Forderungen aus Lief. und Leist. Ausland": {
"account_type": "Receivable"
},
"Pauschalwertberichtigungen zu Forderungen aus Lief. und Leist. EU": {
"account_type": "Receivable"
},
"Pauschalwertberichtigungen zu Forderungen aus Lief. und Leist. Inland ": {
"account_type": "Receivable"
},
"Pauschalwertberichtigungen zu Forderungen gegen\u00fcber Unternehmen mit denen ein Beteiligungsverh\u00e4ltnis besteht": {
"account_type": "Receivable"
},
"Pauschalwertberichtigungen zu Forderungen gegen\u00fcber verbundenen Unternehmen": {
"account_type": "Receivable"
},
"Pauschalwertberichtigungen zu sonstigen Forderungen und Verm\u00f6gensgegenst\u00e4nden": {
"account_type": "Receivable"
},
"Postwertzeichen": {
"account_type": "Receivable"
},
"Schecks in Inlandsw\u00e4hrung": {
"account_type": "Receivable"
},
"Sonstige Anteile": {
"account_type": "Receivable"
},
"Stempelmarken": {
"account_type": "Receivable"
},
"Steuerabgrenzung": {
"account_type": "Receivable"
},
"Unterschiedsbetrag gem. Abschnitt XII Pensionskassengesetz": {
"account_type": "Receivable"
},
"Unterschiedsbetrag zur gebotenen Pensionsr\u00fcckstellung": {
"account_type": "Receivable"
},
"Vorsteuer": {
"account_type": "Receivable"
},
"Vorsteuer aus ig. Erwerb 10%": {
"account_type": "Tax"
},
"Vorsteuer aus ig. Erwerb 20%": {
"account_type": "Tax"
},
"Vorsteuer \u00a719/Art 19 ( reverse charge ) ": {
"account_type": "Tax"
},
"Wertberichtigungen": {
"account_type": "Receivable"
},
"root_type": "Asset"
},
"Summe Vorr\u00e4te": {
"1000 bis 1090 Bezugsverrechnung": {},
"1100 bis 1190 Rohstoffe": {},
"1200 bis 1290 Bezogene Teile": {},
"1300 bis 1340 Hilfsstoffe": {},
"1350 bis 1390 Betriebsstoffe": {},
"1400 bis 1490 Unfertige Erzeugniss": {},
"1500 bis 1590 Fertige Erzeugniss": {},
"1600 bis 1690 Waren": {},
"1700 bis 1790 Noch nicht abgerechenbare Leistungen": {},
"1900 bis 1990 Wertberichtigungen": {},
"geleistete Anzahlungen": {},
"root_type": "Asset"
},
"Summe Wareneinsatz": {
"5100 bis 5190 Verbrauch an Rohstoffen": {},
"5200 bis 5290 Verbrauch von bezogenen Fertig- und Einzelteilen": {},
"5300 bis 5390 Verbrauch von Hilfsstoffen": {},
"5400 bis 5490 Verbrauch von Betriebsstoffen": {},
"5500 bis 5590 Verbrauch von Werkzeugen und anderen Erzeugungshilfsmittel": {},
"5600 bis 5690 Verbrauch von Brenn- und Treibstoffen, Energie und Wasser": {},
"5700 bis 5790 Sonstige bezogene Herstellungsleistungen": {},
"Aufwandsstellenrechnung": {},
"Skontoertr\u00e4ge auf Materialaufwand": {},
"Skontoertr\u00e4ge auf sonstige bezogene Herstellungsleistungen": {},
"Wareneinkauf 10 %": {},
"Wareneinkauf 20 %": {},
"Wareneinkauf igErwerb 10 % VSt/10 % USt": {},
"Wareneinkauf igErwerb 20 % VSt/20 % USt": {},
"Wareneinkauf igErwerb ohne Vorsteuerabzug und 10 % USt": {},
"Wareneinkauf igErwerb ohne Vorsteuerabzug und 20 % USt": {},
"Klasse 6: Personalaufwand": {
"6000 L\u00f6hne": {"account_type": "Payable"},
"6200 Geh\u00e4lter": {"account_type": "Payable"},
"6400 Aufwendungen f\u00fcr Abfertigungen": {"account_type": "Payable"},
"6450 Aufwendungen f\u00fcr Altersversorgung": {"account_type": "Payable"},
"6500 Gesetzlicher Sozialaufwand Arbeiter": {"account_type": "Payable"},
"6560 Gesetzlicher Sozialaufwand Angestellte": {"account_type": "Payable"},
"6600 Lohnabh\u00e4ngige Abgaben und Pflichtbeitr\u00e4gte": {"account_type": "Payable"},
"6660 Gehaltsabh\u00e4ngige Abgaben und Pflichtbeitr\u00e4gte": {"account_type": "Payable"},
"6700 Sonstige Sozialaufwendungen": {"account_type": "Payable"},
"6900 Aufwandsstellenrechnung Personal": {"account_type": "Payable"},
"root_type": "Expense"
},
"Klasse 7: Abschreibungen und sonstige betriebliche Aufwendungen": {
"7010 Abschreibungen auf das Anlageverm\u00f6gen (ausgenommen Finanzanlagen)": {"account_type": "Depreciation"},
"7100 Sonstige Steuern und Geb\u00fchren": {"account_type": "Tax"},
"7200 Instandhaltung u. Reinigung durch Dritte, Entsorgung, Energie": {"account_type": "Expense Account"},
"7300 Transporte durch Dritte": {"account_type": "Expense Account"},
"7310 Fahrrad - Aufwand": {"account_type": "Expense Account"},
"7320 Kfz - Aufwand": {"account_type": "Expense Account"},
"7330 LKW - Aufwand": {"account_type": "Expense Account"},
"7340 Lastenrad - Aufwand": {"account_type": "Expense Account"},
"7350 Reise- und Fahraufwand": {"account_type": "Expense Account"},
"7360 Tag- und N\u00e4chtigungsgelder": {"account_type": "Expense Account"},
"7380 Nachrichtenaufwand": {"account_type": "Expense Account"},
"7400 Miet- und Pachtaufwand": {"account_type": "Expense Account"},
"7440 Leasingaufwand": {"account_type": "Expense Account"},
"7480 Lizenzaufwand": {"account_type": "Expense Account"},
"7500 Aufwand f\u00fcr beigestelltes Personal": {"account_type": "Expense Account"},
"7540 Provisionen an Dritte": {"account_type": "Expense Account"},
"7580 Aufsichtsratsverg\u00fctungen": {"account_type": "Expense Account"},
"7610 Druckerzeugnisse und Vervielf\u00e4ltigungen": {"account_type": "Expense Account"},
"7650 Werbung und Repr\u00e4sentationen": {"account_type": "Expense Account"},
"7700 Versicherungen": {"account_type": "Expense Account"},
"7750 Beratungs- und Pr\u00fcfungsaufwand": {"account_type": "Expense Account"},
"7800 Forderungsverluste und Schadensf\u00e4lle": {"account_type": "Expense Account"},
"7840 Verschiedene betriebliche Aufwendungen": {"account_type": "Expense Account"},
"7910 Aufwandsstellenrechung der Hersteller": {"account_type": "Expense Account"},
"7060 Sofortabschreibungen geringwertig": {"account_type": "Expense Account"},
"7070 Abschreibungen vom Umlaufverm\u00f6gen, soweit diese die im Unternehmen \u00fcblichen Abschreibungen \u00fcbersteigen": {"account_type": "Depreciation"},
"7900 Aufwandsstellenrechnung": {"account_type": "Expense Account"},
"7770 Aus- und Fortbildung": {"account_type": "Expense Account"},
"7820 Buchwert abgegangener Anlagen, ausgenommen Finanzanlagen": {"account_type": "Expense Account"},
"7600 B\u00fcromaterial und Drucksorten": {"account_type": "Expense Account"},
"7630 Fachliteratur und Zeitungen ": {"account_type": "Expense Account"},
"7960 Herstellungskosten der zur Erzielung der Umsatzerl\u00f6se erbrachten Leistungen": {"account_type": "Expense Account"},
"7780 Mitgliedsbeitr\u00e4ge": {"account_type": "Expense Account"},
"7880 Skontoertr\u00e4ge auf sonstige betriebliche Aufwendungen": {"account_type": "Expense Account"},
"7990 Sonstige betrieblichen Aufwendungen": {"account_type": "Expense Account"},
"7680 Spenden und Trinkgelder": {"account_type": "Expense Account"},
"7790 Spesen des Geldverkehrs": {"account_type": "Expense Account"},
"7830 Verluste aus dem Abgang vom Anlageverm\u00f6gen, ausgenommen Finanzanlagen": {"account_type": "Expense Account"},
"7970 Vertriebskosten": {"account_type": "Expense Account"},
"7980 Verwaltungskosten": {"account_type": "Expense Account"},
"root_type": "Expense"
},
"Klasse 8: Finanz- und ausserordentliche Ertr\u00e4ge und Aufwendungen": {
"8000 Ertr\u00e4ge aus Beteiligungen": {"account_type": "Income Account"},
"8050 Ertr\u00e4ge aus anderen Wertpapieren und Ausleihungen des Finanzanlageverm\u00f6gens": {"account_type": "Income Account"},
"8100 Zinsen aus Bankguthaben": {"account_type": "Income Account"},
"8110 Zinsen aus gewaehrten Darlehen": {"account_type": "Income Account"},
"8130 Verzugszinsenertraege": {"account_type": "Income Account"},
"8220 Aufwendungen aus Beteiligungen": {"account_type": "Expense Account"},
"8260 Aufwendungen aus sonst. Fiananzanlagen und aus Wertpapieren des Umlaufverm\u00f6gens": {},
"8280 Zinsen und \u00e4hnliche Aufwendungem": {"account_type": "Expense Account"},
"8400 Au\u00dferordentliche Ertr\u00e4ge": {"account_type": "Income Account"},
"8450 Au\u00dferordentliche Aufwendungen": {"account_type": "Expense Account"},
"8500 Steuern vom Einkommen und vom Ertrag": {
"account_type": "Tax"
},
"8600 Aufl\u00f6sung unversteuerten R\u00fccklagen": {"account_type": "Income Account"},
"8700 Aufl\u00f6sung von Kapitalr\u00fccklagen": {"account_type": "Income Account"},
"8750 Aufl\u00f6sung von Gewinnr\u00fccklagen": {"account_type": "Income Account"},
"8800 Zuweisung zu unversteuerten R\u00fccklagen": {"account_type": "Expense Account"},
"8900 Zuweisung zu Gewinnr\u00fccklagen": {"account_type": "Expense Account"},
"8100 Buchwert abgegangener Beteiligungen": {"account_type": "Expense Account"},
"8130 Buchwert abgegangener Wertpapiere des Umlaufverm\u00f6gens": {"account_type": "Expense Account"},
"8120 Buchwert abgegangener sonstiger Finanzanlagen": {"account_type": "Expense Account"},
"8990 Gewinnabfuhr bzw. Verlust\u00fcberrechnung aus Ergebnisabf\u00fchrungsvertr\u00e4gen": {"account_type": "Expense Account"},
"8350 nicht ausgenutzte Lieferantenskonti": {"account_type": "Expense Account"},
"root_type": "Income"
},
"Klasse 9 Passiva: Eigenkapital, R\u00fccklagen, stille Einlagen, Abschlusskonten": {
"9000 Gezeichnetes bzw. gewidmetes Kapital": {
"account_type": "Equity"
},
"9200 Kapitalr\u00fccklagen": {
"account_type": "Equity"
},
"9300 Gewinnr\u00fccklagen": {
"account_type": "Equity"
},
"9400 Bewertungsreserven uns sonst. unversteuerte R\u00fccklagen": {
"account_type": "Equity"
},
"9600 Private Entnahmen": {"account_type": "Equity"},
"9610 Privatsteuern": {"account_type": "Equity"},
"9700 Einlagen stiller Gesellschafter ": {"account_type": "Equity"},
"9900 Evidenzkonto": {"account_type": "Equity"},
"9800 Er\u00f6ffnungsbilanzkonto (EBK)": {"account_type": "Equity"},
"9880 Jahresergebnis laut Gewinn- und Verlustrechnung (G+V)": {"account_type": "Equity"},
"9850 Schlussbilanzkonto (SBK)": {"account_type": "Round Off"},
"9190 nicht eingeforderte ausstehende Einlagen und berechtigte Entnahmen von Gesellschaftern": {
"account_type": "Equity"
},
"root_type": "Equity"
}
}
}
}
}

View File

@@ -1,38 +1,38 @@
{
"country_code": "de",
"name": "SKR03 mit Kontonummern",
"tree": {
"Aktiva": {
"is_group": 1,
"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"
"A - Anlagevermögen": {
"is_group": 1,
"EDV-Software": {
"account_number": "0027",
"account_type": "Fixed Asset"
},
"Gesch\u00e4ftsausstattung": {
"account_number": "0410",
"account_type": "Fixed Asset"
},
"B\u00fcroeinrichtung": {
"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"
@@ -53,58 +53,43 @@
},
"II. Forderungen und sonstige Vermögensgegenstände": {
"is_group": 1,
"Forderungen aus Lieferungen und Leistungen mit Kontokorrent": {
"Ford. a. Lieferungen und Leistungen": {
"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": {
"Gewinnermittlung \u00a74/3 nicht Ergebniswirksam": {
"account_number": "1371"
},
"Abziehbare Vorsteuer": {
"account_type": "Tax",
"is_group": 1,
"Abziehbare Vorsteuer 7 %": {
"account_number": "1571",
"account_type": "Tax",
"tax_rate": 7.0
"Abziehbare Vorsteuer 7%": {
"account_number": "1571"
},
"Abziehbare Vorsteuer 19 %": {
"account_number": "1576",
"account_type": "Tax",
"tax_rate": 19.0
"Abziehbare Vorsteuer 19%": {
"account_number": "1576"
},
"Abziehbare Vorsteuer nach § 13b UStG 19 %": {
"account_number": "1577",
"account_type": "Tax",
"tax_rate": 19.0
"Abziehbare Vorsteuer nach \u00a713b UStG 19%": {
"account_number": "1577"
},
"Leistungen \u00a713b UStG 19% Vorsteuer, 19% Umsatzsteuer": {
"account_number": "3120"
}
}
},
"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"
}
"is_group": 1
},
"IV. Kassenbestand, Bundesbankguthaben, Guthaben bei Kreditinstituten und Schecks.": {
"is_group": 1,
"Kasse": {
"is_group": 1,
"account_type": "Cash",
"is_group": 1,
"Kasse": {
"is_group": 1,
"account_number": "1000",
"account_type": "Cash"
}
@@ -126,21 +111,21 @@
"C - Rechnungsabgrenzungsposten": {
"is_group": 1,
"Aktive Rechnungsabgrenzung": {
"account_number": "0980"
"account_number": "0980"
}
},
"D - Aktive latente Steuern": {
"is_group": 1,
"Aktive latente Steuern": {
"account_number": "0983"
"account_number": "0983"
}
},
"E - Aktiver Unterschiedsbetrag aus der Vermögensverrechnung": {
"is_group": 1
}
},
"Passiva": {
"is_group": 1,
},
"Passiva": {
"is_group": 1,
"root_type": "Liability",
"A. Eigenkapital": {
"is_group": 1,
@@ -185,13 +170,8 @@
},
"IV. Verbindlichkeiten aus Lieferungen und Leistungen": {
"is_group": 1,
"Verbindlichkeiten aus Lieferungen und Leistungen mit Kontokorrent": {
"Verbindlichkeiten aus Lieferungen u. Leistungen": {
"account_number": "1600",
"account_type": "Payable",
"is_group": 1
},
"Verbindlichkeiten aus Lieferungen und Leistungen ohne Kontokorrent": {
"account_number": "1610",
"account_type": "Payable"
}
},
@@ -220,32 +200,26 @@
},
"Umsatzsteuer": {
"is_group": 1,
"Umsatzsteuer 7 %": {
"account_number": "1771",
"account_type": "Tax",
"tax_rate": 7.0
"account_type": "Tax",
"Umsatzsteuer 7%": {
"account_number": "1771"
},
"Umsatzsteuer 19 %": {
"account_number": "1776",
"account_type": "Tax",
"tax_rate": 19.0
"Umsatzsteuer 19%": {
"account_number": "1776"
},
"Umsatzsteuer-Vorauszahlung": {
"account_number": "1780",
"account_type": "Tax"
"account_number": "1780"
},
"Umsatzsteuer-Vorauszahlung 1/11": {
"account_number": "1781"
},
"Umsatzsteuer nach § 13b UStG 19 %": {
"account_number": "1787",
"account_type": "Tax",
"tax_rate": 19.0
"Umsatzsteuer \u00a7 13b UStG 19%": {
"account_number": "1787"
},
"Umsatzsteuer Vorjahr": {
"account_number": "1790"
},
"Umsatzsteuer frühere Jahre": {
"Umsatzsteuer fr\u00fchere Jahre": {
"account_number": "1791"
}
}
@@ -260,56 +234,44 @@
"E. Passive latente Steuern": {
"is_group": 1
}
},
"Erlöse u. Erträge 2/8": {
"is_group": 1,
"root_type": "Income",
"Erlöskonten 8": {
},
"Erl\u00f6se u. Ertr\u00e4ge 2/8": {
"is_group": 1,
"root_type": "Income",
"Erl\u00f6skonten 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,
"Erl\u00f6se": {
"account_number": "8200",
"account_type": "Income Account"
},
"Erl\u00f6se USt. 19%": {
"account_number": "8400",
"account_type": "Income Account"
},
"Erl\u00f6se USt. 7%": {
"account_number": "8300",
"account_type": "Income Account"
}
},
"Ertragskonten 2": {
"is_group": 1,
"sonstige Zinsen und \u00e4hnliche Ertr\u00e4ge": {
"account_number": "2650",
"account_type": "Income Account"
},
"Au\u00dferordentliche Ertr\u00e4ge": {
"account_number": "2500",
"account_type": "Income Account"
},
"Sonstige Ertr\u00e4ge": {
"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"
},
@@ -336,234 +298,234 @@
"Gegenkonto 4996-4998": {
"account_number": "4999"
},
"Abschreibungen": {
"is_group": 1,
"Abschreibungen": {
"is_group": 1,
"Abschreibungen auf Sachanlagen (ohne AfA auf Kfz und Gebäude)": {
"account_number": "4830",
"account_type": "Accumulated Depreciation"
"account_number": "4830",
"account_type": "Accumulated Depreciation"
},
"Abschreibungen auf Gebäude": {
"account_number": "4831",
"account_type": "Depreciation"
"account_number": "4831",
"account_type": "Depreciation"
},
"Abschreibungen auf Kfz": {
"account_number": "4832",
"account_type": "Depreciation"
"account_number": "4832",
"account_type": "Depreciation"
},
"Sofortabschreibung GWG": {
"account_number": "4855",
"account_type": "Expense Account"
"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"
}
}
}
}
},
"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\u00e4lter": {
"account_number": "4120",
"account_type": "Expense Account"
},
"gesetzliche soziale Aufwendungen": {
"account_number": "4130",
"account_type": "Expense Account"
},
"Aufwendungen f\u00fcr Altersvorsorge": {
"account_number": "4165",
"account_type": "Expense Account"
},
"Verm\u00f6genswirksame Leistungen": {
"account_number": "4170",
"account_type": "Expense Account"
},
"Aushilfsl\u00f6hne": {
"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,
"Reparatur u. Instandh. von Anlagen/Maschinen u. Betriebs- u. Gesch\u00e4ftsausst.": {
"account_number": "4805",
"account_type": "Expense Account"
}
},
"Versicherungsbeitr\u00e4ge": {
"is_group": 1,
"Versicherungen": {
"account_number": "4360",
"account_type": "Expense Account"
},
"Beitr\u00e4ge": {
"account_number": "4380",
"account_type": "Expense Account"
},
"sonstige Ausgaben": {
"account_number": "4390",
"account_type": "Expense Account"
},
"steuerlich abzugsf\u00e4hige Versp\u00e4tungszuschl\u00e4ge 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\u00e4hige Betriebsausg. aus Werbe-, Repr\u00e4s.- 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\u00fcrobedarf": {
"account_number": "4930",
"account_type": "Expense Account"
},
"Zeitschriften, B\u00fccher": {
"account_number": "4940",
"account_type": "Expense Account"
},
"Fortbildungskosten": {
"account_number": "4945",
"account_type": "Expense Account"
},
"Buchf\u00fchrungskosten": {
"account_number": "4955",
"account_type": "Expense Account"
},
"Abschlu\u00df- u. Pr\u00fcfungskosten": {
"account_number": "4957",
"account_type": "Expense Account"
},
"Nebenkosten des Geldverkehrs": {
"account_number": "4970",
"account_type": "Expense Account"
},
"Werkzeuge und Kleinger\u00e4te": {
"account_number": "4985",
"account_type": "Expense Account"
}
},
"Zinsaufwendungen": {
"is_group": 1,
"Zinsaufwendungen f\u00fcr kurzfristige Verbindlichkeiten": {
"account_number": "2110",
"account_type": "Expense Account"
},
"Zinsaufwendungen f\u00fcr 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\u00e4ge Debitoren": {
"account_number": "9008"
},
"Saldenvortr\u00e4ge 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\u00e4nkt abzugsf\u00e4hig": {
"account_number": "1820"
},
"Sonderausgaben unbeschr\u00e4nkt abzugsf\u00e4hig": {
"account_number": "1830"
},
"Au\u00dfergew\u00f6hnliche Belastungen": {
"account_number": "1850"
},
"Privateinlagen": {
"account_number": "1890"
}
}
}
}
}

View File

@@ -407,10 +407,13 @@
"Bewertungskorrektur zu Forderungen aus Lieferungen und Leistungen": {
"account_number": "9960"
},
"Forderungen aus Lieferungen und Leistungen mit Kontokorrent": {
"Debitoren": {
"is_group": 1,
"account_number": "10000"
},
"Forderungen aus Lieferungen und Leistungen": {
"account_number": "1200",
"account_type": "Receivable",
"is_group": 1
"account_type": "Receivable"
},
"Forderungen aus Lieferungen und Leistungen ohne Kontokorrent": {
"account_number": "1210"
@@ -1135,15 +1138,18 @@
"Bewertungskorrektur zu Verb. aus Lieferungen und Leistungen": {
"account_number": "9964"
},
"Verb. aus Lieferungen und Leistungen mit Kontokorrent": {
"account_number": "3300",
"account_type": "Payable",
"Kreditoren": {
"account_number": "70000",
"is_group": 1,
"Wareneingangs-Verrechnungskonto" : {
"Wareneingangs-­Verrechnungskonto" : {
"account_number": "70001",
"account_type": "Stock Received But Not Billed"
}
},
"Verb. aus Lieferungen und Leistungen": {
"account_number": "3300",
"account_type": "Payable"
},
"Verb. aus Lieferungen und Leistungen ohne Kontokorrent": {
"account_number": "3310"
},

View File

@@ -98,7 +98,7 @@
"Office Maintenance Expenses": {},
"Office Rent": {},
"Postal Expenses": {},
"Print and Stationery": {},
"Print and Stationary": {},
"Rounded Off": {
"account_type": "Round Off"
},

View File

@@ -2,13 +2,75 @@
"country_code": "nl",
"name": "Netherlands - Grootboekschema",
"tree": {
"FABRIKAGEREKENINGEN": {
"is_group": 1,
"root_type": "Expense"
},
"FINANCIELE REKENINGEN, KORTLOPENDE VORDERINGEN EN SCHULDEN": {
"Bank": {
"RABO Bank": {
"account_type": "Bank"
},
"account_type": "Bank"
},
},
"KORTLOPENDE SCHULDEN": {
"Af te dragen Btw-verlegd": {
"account_type": "Tax"
},
"Afdracht loonheffing": {},
"Btw af te dragen hoog": {
"account_type": "Tax"
},
"Btw af te dragen laag": {
"account_type": "Tax"
},
"Btw af te dragen overig": {
"account_type": "Tax"
},
"Btw oude jaren": {
"account_type": "Tax"
},
"Btw te vorderen hoog": {
"account_type": "Tax"
},
"Btw te vorderen laag": {
"account_type": "Tax"
},
"Btw te vorderen overig": {
"account_type": "Tax"
},
"Btw-afdracht": {
"account_type": "Tax"
},
"Crediteuren": {
"account_type": "Payable"
},
"Dividend": {},
"Dividendbelasting": {},
"Energiekosten 1": {},
"Investeringsaftrek": {},
"Loonheffing": {},
"Overige te betalen posten": {},
"Pensioenpremies 1": {},
"Premie WIR": {},
"Rekening-courant inkoopvereniging": {},
"Rente": {},
"Sociale lasten 1": {},
"Stock Recieved niet gefactureerd": {
"account_type": "Stock Received But Not Billed"
},
"Tanti\u00e8mes 1": {},
"Te vorderen Btw-verlegd": {
"account_type": "Tax"
},
"Telefoon/telefax 1": {},
"Termijnen onderh. werk": {},
"Vakantiedagen": {},
"Vakantiegeld 1": {},
"Vakantiezegels": {},
"Vennootschapsbelasting": {},
"Vooruit ontvangen bedr.": {}
},
"LIQUIDE MIDDELEN": {
"ABN-AMRO bank": {},
"Bankbetaalkaarten": {},
@@ -29,110 +91,6 @@
},
"account_type": "Cash"
},
"TUSSENREKENINGEN": {
"Betaalwijze cadeaubonnen": {
"account_type": "Cash"
},
"Betaalwijze chipknip": {
"account_type": "Cash"
},
"Betaalwijze contant": {
"account_type": "Cash"
},
"Betaalwijze pin": {
"account_type": "Cash"
},
"Inkopen Nederland hoog": {
"account_type": "Cash"
},
"Inkopen Nederland laag": {
"account_type": "Cash"
},
"Inkopen Nederland onbelast": {
"account_type": "Cash"
},
"Inkopen Nederland overig": {
"account_type": "Cash"
},
"Inkopen Nederland verlegd": {
"account_type": "Cash"
},
"Inkopen binnen EU hoog": {
"account_type": "Cash"
},
"Inkopen binnen EU laag": {
"account_type": "Cash"
},
"Inkopen binnen EU overig": {
"account_type": "Cash"
},
"Inkopen buiten EU hoog": {
"account_type": "Cash"
},
"Inkopen buiten EU laag": {
"account_type": "Cash"
},
"Inkopen buiten EU overig": {
"account_type": "Cash"
},
"Kassa 1": {
"account_type": "Cash"
},
"Kassa 2": {
"account_type": "Cash"
},
"Netto lonen": {
"account_type": "Cash"
},
"Tegenrekening Inkopen": {
"account_type": "Cash"
},
"Tussenrek. autom. betalingen": {
"account_type": "Cash"
},
"Tussenrek. autom. loonbetalingen": {
"account_type": "Cash"
},
"Tussenrek. cadeaubonbetalingen": {
"account_type": "Cash"
},
"Tussenrekening balans": {
"account_type": "Cash"
},
"Tussenrekening chipknip": {
"account_type": "Cash"
},
"Tussenrekening correcties": {
"account_type": "Cash"
},
"Tussenrekening pin": {
"account_type": "Cash"
},
"Vraagposten": {
"account_type": "Cash"
},
"VOORRAAD GRONDSTOFFEN, HULPMATERIALEN EN HANDELSGOEDEREN": {
"Emballage": {},
"Gereed product 1": {},
"Gereed product 2": {},
"Goederen 1": {},
"Goederen 2": {},
"Goederen in consignatie": {},
"Goederen onderweg": {},
"Grondstoffen 1": {},
"Grondstoffen 2": {},
"Halffabrikaten 1": {},
"Halffabrikaten 2": {},
"Hulpstoffen 1": {},
"Hulpstoffen 2": {},
"Kantoorbenodigdheden": {},
"Onderhanden werk": {},
"Verpakkingsmateriaal": {},
"Zegels": {},
"root_type": "Asset"
},
"root_type": "Asset"
},
"VORDERINGEN": {
"Debiteuren": {
"account_type": "Receivable"
@@ -146,299 +104,278 @@
"Voorziening dubieuze debiteuren": {}
},
"root_type": "Asset"
},
"KORTLOPENDE SCHULDEN": {
"Af te dragen Btw-verlegd": {
"account_type": "Tax"
},
"Afdracht loonheffing": {},
"Btw af te dragen hoog": {
"account_type": "Tax"
},
"Btw af te dragen laag": {
"account_type": "Tax"
},
"Btw af te dragen overig": {
"account_type": "Tax"
},
"Btw oude jaren": {
"account_type": "Tax"
},
"Btw te vorderen hoog": {
"account_type": "Tax"
},
"Btw te vorderen laag": {
"account_type": "Tax"
},
"Btw te vorderen overig": {
"account_type": "Tax"
},
"Btw-afdracht": {
"account_type": "Tax"
},
"Crediteuren": {
"account_type": "Payable"
},
"Dividend": {},
"Dividendbelasting": {},
"Energiekosten 1": {},
"Investeringsaftrek": {},
"Loonheffing": {},
"Overige te betalen posten": {},
"Pensioenpremies 1": {},
"Premie WIR": {},
"Rekening-courant inkoopvereniging": {},
"Rente": {},
"Sociale lasten 1": {},
"Stock Recieved niet gefactureerd": {
"account_type": "Stock Received But Not Billed"
},
"Tanti\u00e8mes 1": {},
"Te vorderen Btw-verlegd": {
"account_type": "Tax"
},
"Telefoon/telefax 1": {},
"Termijnen onderh. werk": {},
"Vakantiedagen": {},
"Vakantiegeld 1": {},
"Vakantiezegels": {},
"Vennootschapsbelasting": {},
"Vooruit ontvangen bedr.": {},
"is_group": 1,
"root_type": "Liability"
},
"FABRIKAGEREKENINGEN": {
},
"INDIRECTE KOSTEN": {
"is_group": 1,
"root_type": "Expense",
"INDIRECTE KOSTEN": {
"is_group": 1,
"root_type": "Expense"
},
"KOSTENREKENINGEN": {
"AFSCHRIJVINGEN": {
"Aanhangwagens": {},
"Aankoopkosten": {},
"Aanloopkosten": {},
"Auteursrechten": {},
"Bedrijfsgebouwen": {},
"Bedrijfsinventaris": {
"account_type": "Depreciation"
},
"Drankvergunningen": {},
"Fabrieksinventaris": {
"account_type": "Depreciation"
},
"Gebouwen": {},
"Gereedschappen": {},
"Goodwill": {},
"Grondverbetering": {},
"Heftrucks": {},
"Kantine-inventaris": {},
"Kantoorinventaris": {
"account_type": "Depreciation"
},
"Kantoormachines": {},
"Licenties": {},
"Machines 1": {},
"Magazijninventaris": {},
"Octrooien": {},
"Ontwikkelingskosten": {},
"Pachtersinvestering": {},
"Parkeerplaats": {},
"Personenauto's": {
"account_type": "Depreciation"
},
"Rijwielen en bromfietsen": {},
"Tonnagevergunningen": {},
"Verbouwingen": {},
"Vergunningen": {},
"Voorraadverschillen": {},
"Vrachtauto's": {},
"Winkels": {},
"Woon-winkelhuis": {},
"root_type": "Expense"
},
"KOSTENREKENINGEN": {
"AFSCHRIJVINGEN": {
"Aanhangwagens": {},
"Aankoopkosten": {},
"Aanloopkosten": {},
"Auteursrechten": {},
"Bedrijfsgebouwen": {},
"Bedrijfsinventaris": {
"account_type": "Depreciation"
},
"ALGEMENE KOSTEN": {
"Accountantskosten": {},
"Advieskosten": {},
"Assuranties 1": {},
"Bankkosten": {},
"Juridische kosten": {},
"Overige algemene kosten": {},
"Toev. Ass. eigen risico": {}
"Drankvergunningen": {},
"Fabrieksinventaris": {
"account_type": "Depreciation"
},
"BEDRIJFSKOSTEN": {
"Assuranties 2": {},
"Energie (krachtstroom)": {},
"Gereedschappen 1": {},
"Hulpmaterialen 1": {},
"Huur inventaris": {},
"Huur machines": {},
"Leasing invent.operational": {},
"Leasing mach. operational": {},
"Onderhoud inventaris": {},
"Onderhoud machines": {},
"Ophalen/vervoer afval": {},
"Overige bedrijfskosten": {}
"Gebouwen": {},
"Gereedschappen": {},
"Goodwill": {},
"Grondverbetering": {},
"Heftrucks": {},
"Kantine-inventaris": {},
"Kantoorinventaris": {
"account_type": "Depreciation"
},
"FINANCIERINGSKOSTEN 1": {
"Overige rentebaten": {},
"Overige rentelasten": {},
"Rente bankkrediet": {},
"Rente huurkoopcontracten": {},
"Rente hypotheek": {},
"Rente leasecontracten": {},
"Rente lening o/g": {},
"Rente lening u/g": {}
"Kantoormachines": {},
"Licenties": {},
"Machines 1": {},
"Magazijninventaris": {},
"Octrooien": {},
"Ontwikkelingskosten": {},
"Pachtersinvestering": {},
"Parkeerplaats": {},
"Personenauto's": {
"account_type": "Depreciation"
},
"HUISVESTINGSKOSTEN": {
"Assurantie onroerend goed": {},
"Belastingen onr. Goed": {},
"Energiekosten": {},
"Groot onderhoud onr. Goed": {},
"Huur": {},
"Huurwaarde woongedeelte": {},
"Onderhoud onroerend goed": {},
"Ontvangen huren": {},
"Overige huisvestingskosten": {},
"Pacht": {},
"Schoonmaakkosten": {},
"Toevoeging egalisatieres. Groot onderhoud": {}
},
"KANTOORKOSTEN": {
"Administratiekosten": {},
"Contributies/abonnementen": {},
"Huur kantoorapparatuur": {},
"Internetaansluiting": {},
"Kantoorbenodigdh./drukw.": {},
"Onderhoud kantoorinvent.": {},
"Overige kantoorkosten": {},
"Porti": {},
"Telefoon/telefax": {}
},
"OVERIGE BATEN EN LASTEN": {
"Betaalde schadevergoed.": {},
"Boekverlies vaste activa": {},
"Boekwinst van vaste activa": {},
"K.O. regeling OB": {},
"Kasverschillen": {},
"Kosten loonbelasting": {},
"Kosten omzetbelasting": {},
"Nadelige koersverschillen": {},
"Naheffing bedrijfsver.": {},
"Ontvangen schadevergoed.": {},
"Overige baten": {},
"Overige lasten": {},
"Voordelige koersverschil.": {}
},
"PERSONEELSKOSTEN": {
"Autokostenvergoeding": {},
"Bedrijfskleding": {},
"Belastingvrije uitkeringen": {},
"Bijzondere beloningen": {},
"Congressen, seminars en symposia": {},
"Gereedschapsgeld": {},
"Geschenken personeel": {},
"Gratificaties": {},
"Inhouding pensioenpremies": {},
"Inhouding sociale lasten": {},
"Kantinekosten": {},
"Lonen en salarissen": {},
"Loonwerk": {},
"Managementvergoedingen": {},
"Opleidingskosten": {},
"Oprenting stamrechtverpl.": {},
"Overhevelingstoeslag": {},
"Overige kostenverg.": {},
"Overige personeelskosten": {},
"Overige uitkeringen": {},
"Pensioenpremies": {},
"Provisie 1": {},
"Reiskosten": {},
"Rijwielvergoeding": {},
"Sociale lasten": {},
"Tanti\u00e8mes": {},
"Thuiswerkers": {},
"Toev. Backservice pens.verpl.": {},
"Toevoeging pensioenverpl.": {},
"Uitkering ziekengeld": {},
"Uitzendkrachten": {},
"Vakantiebonnen": {},
"Vakantiegeld": {},
"Vergoeding studiekosten": {},
"Wervingskosten personeel": {}
},
"VERKOOPKOSTEN": {
"Advertenties": {},
"Afschrijving dubieuze deb.": {},
"Beurskosten": {},
"Etalagekosten": {},
"Exportkosten": {},
"Kascorrecties": {},
"Overige verkoopkosten": {},
"Provisie": {},
"Reclame": {},
"Reis en verblijfkosten": {},
"Relatiegeschenken": {},
"Representatiekosten": {},
"Uitgaande vrachten": {},
"Veilingkosten": {},
"Verpakkingsmateriaal 1": {},
"Websitekosten": {}
},
"VERVOERSKOSTEN": {
"Assuranties auto's": {},
"Brandstoffen": {},
"Leasing auto's": {},
"Onderhoud personenauto's": {},
"Onderhoud vrachtauto's": {},
"Overige vervoerskosten": {},
"Priv\u00e9-gebruik auto's": {},
"Wegenbelasting": {}
},
"VOORRAAD GEREED PRODUCT EN ONDERHANDEN WERK": {
"Betalingskort. crediteuren": {},
"Garantiekosten": {},
"Hulpmaterialen": {},
"Inkomende vrachten": {
"account_type": "Expenses Included In Valuation"
},
"Inkoop import buiten EU hoog": {},
"Inkoop import buiten EU laag": {},
"Inkoop import buiten EU overig": {},
"Inkoopbonussen": {},
"Inkoopkosten": {},
"Inkoopprovisie": {},
"Inkopen BTW verlegd": {},
"Inkopen EU hoog tarief": {},
"Inkopen EU laag tarief": {},
"Inkopen EU overig": {},
"Inkopen hoog": {},
"Inkopen laag": {},
"Inkopen nul": {},
"Inkopen overig": {},
"Invoerkosten": {},
"Kosten inkoopvereniging": {},
"Kostprijs omzet grondstoffen": {
"account_type": "Cost of Goods Sold"
},
"Kostprijs omzet handelsgoederen": {},
"Onttrekking uitgev.garantie": {},
"Priv\u00e9-gebruik goederen": {},
"Stock aanpassing": {
"account_type": "Stock Adjustment"
},
"Tegenrekening inkoop": {},
"Toev. Voorz. incour. grondst.": {},
"Toevoeging garantieverpl.": {},
"Toevoeging voorz. incour. handelsgoed.": {},
"Uitbesteed werk": {},
"Voorz. Incourourant grondst.": {},
"Voorz.incour. handelsgoed.": {},
"root_type": "Expense"
},
"root_type": "Expense"
}
"Rijwielen en bromfietsen": {},
"Tonnagevergunningen": {},
"Verbouwingen": {},
"Vergunningen": {},
"Voorraadverschillen": {},
"Vrachtauto's": {},
"Winkels": {},
"Woon-winkelhuis": {},
"account_type": "Depreciation"
},
"ALGEMENE KOSTEN": {
"Accountantskosten": {},
"Advieskosten": {},
"Assuranties 1": {},
"Bankkosten": {},
"Juridische kosten": {},
"Overige algemene kosten": {},
"Toev. Ass. eigen risico": {}
},
"BEDRIJFSKOSTEN": {
"Assuranties 2": {},
"Energie (krachtstroom)": {},
"Gereedschappen 1": {},
"Hulpmaterialen 1": {},
"Huur inventaris": {},
"Huur machines": {},
"Leasing invent.operational": {},
"Leasing mach. operational": {},
"Onderhoud inventaris": {},
"Onderhoud machines": {},
"Ophalen/vervoer afval": {},
"Overige bedrijfskosten": {}
},
"FINANCIERINGSKOSTEN 1": {
"Overige rentebaten": {},
"Overige rentelasten": {},
"Rente bankkrediet": {},
"Rente huurkoopcontracten": {},
"Rente hypotheek": {},
"Rente leasecontracten": {},
"Rente lening o/g": {},
"Rente lening u/g": {}
},
"HUISVESTINGSKOSTEN": {
"Assurantie onroerend goed": {},
"Belastingen onr. Goed": {},
"Energiekosten": {},
"Groot onderhoud onr. Goed": {},
"Huur": {},
"Huurwaarde woongedeelte": {},
"Onderhoud onroerend goed": {},
"Ontvangen huren": {},
"Overige huisvestingskosten": {},
"Pacht": {},
"Schoonmaakkosten": {},
"Toevoeging egalisatieres. Groot onderhoud": {}
},
"KANTOORKOSTEN": {
"Administratiekosten": {},
"Contributies/abonnementen": {},
"Huur kantoorapparatuur": {},
"Internetaansluiting": {},
"Kantoorbenodigdh./drukw.": {},
"Onderhoud kantoorinvent.": {},
"Overige kantoorkosten": {},
"Porti": {},
"Telefoon/telefax": {}
},
"OVERIGE BATEN EN LASTEN": {
"Betaalde schadevergoed.": {},
"Boekverlies vaste activa": {},
"Boekwinst van vaste activa": {},
"K.O. regeling OB": {},
"Kasverschillen": {},
"Kosten loonbelasting": {},
"Kosten omzetbelasting": {},
"Nadelige koersverschillen": {},
"Naheffing bedrijfsver.": {},
"Ontvangen schadevergoed.": {},
"Overige baten": {},
"Overige lasten": {},
"Voordelige koersverschil.": {}
},
"PERSONEELSKOSTEN": {
"Autokostenvergoeding": {},
"Bedrijfskleding": {},
"Belastingvrije uitkeringen": {},
"Bijzondere beloningen": {},
"Congressen, seminars en symposia": {},
"Gereedschapsgeld": {},
"Geschenken personeel": {},
"Gratificaties": {},
"Inhouding pensioenpremies": {},
"Inhouding sociale lasten": {},
"Kantinekosten": {},
"Lonen en salarissen": {},
"Loonwerk": {},
"Managementvergoedingen": {},
"Opleidingskosten": {},
"Oprenting stamrechtverpl.": {},
"Overhevelingstoeslag": {},
"Overige kostenverg.": {},
"Overige personeelskosten": {},
"Overige uitkeringen": {},
"Pensioenpremies": {},
"Provisie 1": {},
"Reiskosten": {},
"Rijwielvergoeding": {},
"Sociale lasten": {},
"Tanti\u00e8mes": {},
"Thuiswerkers": {},
"Toev. Backservice pens.verpl.": {},
"Toevoeging pensioenverpl.": {},
"Uitkering ziekengeld": {},
"Uitzendkrachten": {},
"Vakantiebonnen": {},
"Vakantiegeld": {},
"Vergoeding studiekosten": {},
"Wervingskosten personeel": {}
},
"VERKOOPKOSTEN": {
"Advertenties": {},
"Afschrijving dubieuze deb.": {},
"Beurskosten": {},
"Etalagekosten": {},
"Exportkosten": {},
"Kascorrecties": {},
"Overige verkoopkosten": {},
"Provisie": {},
"Reclame": {},
"Reis en verblijfkosten": {},
"Relatiegeschenken": {},
"Representatiekosten": {},
"Uitgaande vrachten": {},
"Veilingkosten": {},
"Verpakkingsmateriaal 1": {},
"Websitekosten": {}
},
"VERVOERSKOSTEN": {
"Assuranties auto's": {},
"Brandstoffen": {},
"Leasing auto's": {},
"Onderhoud personenauto's": {},
"Onderhoud vrachtauto's": {},
"Overige vervoerskosten": {},
"Priv\u00e9-gebruik auto's": {},
"Wegenbelasting": {}
},
"root_type": "Expense"
},
"TUSSENREKENINGEN": {
"Betaalwijze cadeaubonnen": {
"account_type": "Cash"
},
"Betaalwijze chipknip": {
"account_type": "Cash"
},
"Betaalwijze contant": {
"account_type": "Cash"
},
"Betaalwijze pin": {
"account_type": "Cash"
},
"Inkopen Nederland hoog": {
"account_type": "Cash"
},
"Inkopen Nederland laag": {
"account_type": "Cash"
},
"Inkopen Nederland onbelast": {
"account_type": "Cash"
},
"Inkopen Nederland overig": {
"account_type": "Cash"
},
"Inkopen Nederland verlegd": {
"account_type": "Cash"
},
"Inkopen binnen EU hoog": {
"account_type": "Cash"
},
"Inkopen binnen EU laag": {
"account_type": "Cash"
},
"Inkopen binnen EU overig": {
"account_type": "Cash"
},
"Inkopen buiten EU hoog": {
"account_type": "Cash"
},
"Inkopen buiten EU laag": {
"account_type": "Cash"
},
"Inkopen buiten EU overig": {
"account_type": "Cash"
},
"Kassa 1": {
"account_type": "Cash"
},
"Kassa 2": {
"account_type": "Cash"
},
"Netto lonen": {
"account_type": "Cash"
},
"Tegenrekening Inkopen": {
"account_type": "Cash"
},
"Tussenrek. autom. betalingen": {
"account_type": "Cash"
},
"Tussenrek. autom. loonbetalingen": {
"account_type": "Cash"
},
"Tussenrek. cadeaubonbetalingen": {
"account_type": "Cash"
},
"Tussenrekening balans": {
"account_type": "Cash"
},
"Tussenrekening chipknip": {
"account_type": "Cash"
},
"Tussenrekening correcties": {
"account_type": "Cash"
},
"Tussenrekening pin": {
"account_type": "Cash"
},
"Vraagposten": {
"account_type": "Cash"
},
"root_type": "Asset"
},
"VASTE ACTIVA, EIGEN VERMOGEN, LANGLOPEND VREEMD VERMOGEN EN VOORZIENINGEN": {
"EIGEN VERMOGEN": {
@@ -665,7 +602,7 @@
"account_type": "Equity"
}
},
"root_type": "Equity"
"root_type": "Asset"
},
"VERKOOPRESULTATEN": {
"Diensten fabric. 0% niet-EU": {},
@@ -690,6 +627,67 @@
"Verleende Kredietbep. fabricage": {},
"Verleende Kredietbep. handel": {},
"root_type": "Income"
},
"VOORRAAD GEREED PRODUCT EN ONDERHANDEN WERK": {
"Betalingskort. crediteuren": {},
"Garantiekosten": {},
"Hulpmaterialen": {},
"Inkomende vrachten": {
"account_type": "Expenses Included In Valuation"
},
"Inkoop import buiten EU hoog": {},
"Inkoop import buiten EU laag": {},
"Inkoop import buiten EU overig": {},
"Inkoopbonussen": {},
"Inkoopkosten": {},
"Inkoopprovisie": {},
"Inkopen BTW verlegd": {},
"Inkopen EU hoog tarief": {},
"Inkopen EU laag tarief": {},
"Inkopen EU overig": {},
"Inkopen hoog": {},
"Inkopen laag": {},
"Inkopen nul": {},
"Inkopen overig": {},
"Invoerkosten": {},
"Kosten inkoopvereniging": {},
"Kostprijs omzet grondstoffen": {
"account_type": "Cost of Goods Sold"
},
"Kostprijs omzet handelsgoederen": {},
"Onttrekking uitgev.garantie": {},
"Priv\u00e9-gebruik goederen": {},
"Stock aanpassing": {
"account_type": "Stock Adjustment"
},
"Tegenrekening inkoop": {},
"Toev. Voorz. incour. grondst.": {},
"Toevoeging garantieverpl.": {},
"Toevoeging voorz. incour. handelsgoed.": {},
"Uitbesteed werk": {},
"Voorz. Incourourant grondst.": {},
"Voorz.incour. handelsgoed.": {},
"root_type": "Expense"
},
"VOORRAAD GRONDSTOFFEN, HULPMATERIALEN EN HANDELSGOEDEREN": {
"Emballage": {},
"Gereed product 1": {},
"Gereed product 2": {},
"Goederen 1": {},
"Goederen 2": {},
"Goederen in consignatie": {},
"Goederen onderweg": {},
"Grondstoffen 1": {},
"Grondstoffen 2": {},
"Halffabrikaten 1": {},
"Halffabrikaten 2": {},
"Hulpstoffen 1": {},
"Hulpstoffen 2": {},
"Kantoorbenodigdheden": {},
"Onderhanden werk": {},
"Verpakkingsmateriaal": {},
"Zegels": {},
"root_type": "Asset"
}
}
}

View File

@@ -5,17 +5,10 @@
import unittest
import frappe
from frappe.test_runner import make_test_records
from erpnext.accounts.doctype.account.account import (
InvalidAccountMergeError,
merge_account,
update_account_number,
)
from erpnext.accounts.doctype.account.account import merge_account, update_account_number
from erpnext.stock import get_company_default_inventory_account, get_warehouse_account
test_dependencies = ["Company"]
class TestAccount(unittest.TestCase):
def test_rename_account(self):
@@ -51,53 +44,49 @@ class TestAccount(unittest.TestCase):
frappe.delete_doc("Account", "1211-11-4 - 6 - Debtors 1 - Test - - _TC")
def test_merge_account(self):
create_account(
account_name="Current Assets",
is_group=1,
parent_account="Application of Funds (Assets) - _TC",
company="_Test Company",
)
create_account(
account_name="Securities and Deposits",
is_group=1,
parent_account="Current Assets - _TC",
company="_Test Company",
)
create_account(
account_name="Earnest Money",
parent_account="Securities and Deposits - _TC",
company="_Test Company",
)
create_account(
account_name="Cash In Hand",
is_group=1,
parent_account="Current Assets - _TC",
company="_Test Company",
)
create_account(
account_name="Receivable INR",
parent_account="Current Assets - _TC",
company="_Test Company",
account_currency="INR",
)
create_account(
account_name="Receivable USD",
parent_account="Current Assets - _TC",
company="_Test Company",
account_currency="USD",
)
if not frappe.db.exists("Account", "Current Assets - _TC"):
acc = frappe.new_doc("Account")
acc.account_name = "Current Assets"
acc.is_group = 1
acc.parent_account = "Application of Funds (Assets) - _TC"
acc.company = "_Test Company"
acc.insert()
if not frappe.db.exists("Account", "Securities and Deposits - _TC"):
acc = frappe.new_doc("Account")
acc.account_name = "Securities and Deposits"
acc.parent_account = "Current Assets - _TC"
acc.is_group = 1
acc.company = "_Test Company"
acc.insert()
if not frappe.db.exists("Account", "Earnest Money - _TC"):
acc = frappe.new_doc("Account")
acc.account_name = "Earnest Money"
acc.parent_account = "Securities and Deposits - _TC"
acc.company = "_Test Company"
acc.insert()
if not frappe.db.exists("Account", "Cash In Hand - _TC"):
acc = frappe.new_doc("Account")
acc.account_name = "Cash In Hand"
acc.is_group = 1
acc.parent_account = "Current Assets - _TC"
acc.company = "_Test Company"
acc.insert()
if not frappe.db.exists("Account", "Accumulated Depreciation - _TC"):
acc = frappe.new_doc("Account")
acc.account_name = "Accumulated Depreciation"
acc.parent_account = "Fixed Assets - _TC"
acc.company = "_Test Company"
acc.account_type = "Accumulated Depreciation"
acc.insert()
doc = frappe.get_doc("Account", "Securities and Deposits - _TC")
parent = frappe.db.get_value("Account", "Earnest Money - _TC", "parent_account")
self.assertEqual(parent, "Securities and Deposits - _TC")
merge_account("Securities and Deposits - _TC", "Cash In Hand - _TC")
merge_account(
"Securities and Deposits - _TC", "Cash In Hand - _TC", doc.is_group, doc.root_type, doc.company
)
parent = frappe.db.get_value("Account", "Earnest Money - _TC", "parent_account")
# Parent account of the child account changes after merging
@@ -106,28 +95,30 @@ class TestAccount(unittest.TestCase):
# Old account doesn't exist after merging
self.assertFalse(frappe.db.exists("Account", "Securities and Deposits - _TC"))
doc = frappe.get_doc("Account", "Current Assets - _TC")
# Raise error as is_group property doesn't match
self.assertRaises(
InvalidAccountMergeError,
frappe.ValidationError,
merge_account,
"Current Assets - _TC",
"Accumulated Depreciation - _TC",
doc.is_group,
doc.root_type,
doc.company,
)
doc = frappe.get_doc("Account", "Capital Stock - _TC")
# Raise error as root_type property doesn't match
self.assertRaises(
InvalidAccountMergeError,
frappe.ValidationError,
merge_account,
"Capital Stock - _TC",
"Softwares - _TC",
)
# Raise error as currency doesn't match
self.assertRaises(
InvalidAccountMergeError,
merge_account,
"Receivable INR - _TC",
"Receivable USD - _TC",
doc.is_group,
doc.root_type,
doc.company,
)
def test_account_sync(self):
@@ -197,58 +188,6 @@ class TestAccount(unittest.TestCase):
frappe.delete_doc("Account", "1234 - Test Rename Sync Account - _TC4")
frappe.delete_doc("Account", "1234 - Test Rename Sync Account - _TC5")
def test_account_currency_sync(self):
"""
In a parent->child company setup, child should inherit parent account currency if explicitly specified.
"""
make_test_records("Company")
frappe.local.flags.pop("ignore_root_company_validation", None)
def create_bank_account():
acc = frappe.new_doc("Account")
acc.account_name = "_Test Bank JPY"
acc.parent_account = "Temporary Accounts - _TC6"
acc.company = "_Test Company 6"
return acc
acc = create_bank_account()
# Explicitly set currency
acc.account_currency = "JPY"
acc.insert()
self.assertTrue(
frappe.db.exists(
{
"doctype": "Account",
"account_name": "_Test Bank JPY",
"account_currency": "JPY",
"company": "_Test Company 7",
}
)
)
frappe.delete_doc("Account", "_Test Bank JPY - _TC6")
frappe.delete_doc("Account", "_Test Bank JPY - _TC7")
acc = create_bank_account()
# default currency is used
acc.insert()
self.assertTrue(
frappe.db.exists(
{
"doctype": "Account",
"account_name": "_Test Bank JPY",
"account_currency": "USD",
"company": "_Test Company 7",
}
)
)
frappe.delete_doc("Account", "_Test Bank JPY - _TC6")
frappe.delete_doc("Account", "_Test Bank JPY - _TC7")
def test_child_company_account_rename_sync(self):
frappe.local.flags.pop("ignore_root_company_validation", None)
@@ -260,20 +199,28 @@ class TestAccount(unittest.TestCase):
acc.insert()
self.assertTrue(
frappe.db.exists("Account", {"account_name": "Test Group Account", "company": "_Test Company 4"})
frappe.db.exists(
"Account", {"account_name": "Test Group Account", "company": "_Test Company 4"}
)
)
self.assertTrue(
frappe.db.exists("Account", {"account_name": "Test Group Account", "company": "_Test Company 5"})
frappe.db.exists(
"Account", {"account_name": "Test Group Account", "company": "_Test Company 5"}
)
)
# Try renaming child company account
acc_tc_5 = frappe.db.get_value(
"Account", {"account_name": "Test Group Account", "company": "_Test Company 5"}
)
self.assertRaises(frappe.ValidationError, update_account_number, acc_tc_5, "Test Modified Account")
self.assertRaises(
frappe.ValidationError, update_account_number, acc_tc_5, "Test Modified Account"
)
# Rename child company account with allow_account_creation_against_child_company enabled
frappe.db.set_value("Company", "_Test Company 5", "allow_account_creation_against_child_company", 1)
frappe.db.set_value(
"Company", "_Test Company 5", "allow_account_creation_against_child_company", 1
)
update_account_number(acc_tc_5, "Test Modified Account")
self.assertTrue(
@@ -282,7 +229,9 @@ class TestAccount(unittest.TestCase):
)
)
frappe.db.set_value("Company", "_Test Company 5", "allow_account_creation_against_child_company", 0)
frappe.db.set_value(
"Company", "_Test Company 5", "allow_account_creation_against_child_company", 0
)
to_delete = [
"Test Group Account - _TC3",
@@ -307,7 +256,9 @@ class TestAccount(unittest.TestCase):
self.assertEqual(acc.account_currency, "INR")
# Make a JV against this account
make_journal_entry("Test Currency Account - _TC", "Miscellaneous Expenses - _TC", 100, submit=True)
make_journal_entry(
"Test Currency Account - _TC", "Miscellaneous Expenses - _TC", 100, submit=True
)
acc.account_currency = "USD"
self.assertRaises(frappe.ValidationError, acc.save)
@@ -346,7 +297,7 @@ def _make_test_records(verbose=None):
# fixed asset depreciation
["_Test Fixed Asset", "Current Assets", 0, "Fixed Asset", None],
["_Test Accumulated Depreciations", "Current Assets", 0, "Accumulated Depreciation", None],
["_Test Depreciations", "Expenses", 0, "Depreciation", None],
["_Test Depreciations", "Expenses", 0, None, None],
["_Test Gain/Loss on Asset Disposal", "Expenses", 0, None, None],
# Receivable / Payable Account
["_Test Receivable", "Current Assets", 0, "Receivable", None],
@@ -394,20 +345,11 @@ def create_account(**kwargs):
"Account", filters={"account_name": kwargs.get("account_name"), "company": kwargs.get("company")}
)
if account:
account = frappe.get_doc("Account", account)
account.update(
dict(
is_group=kwargs.get("is_group", 0),
parent_account=kwargs.get("parent_account"),
)
)
account.save()
return account.name
return account
else:
account = frappe.get_doc(
dict(
doctype="Account",
is_group=kwargs.get("is_group", 0),
account_name=kwargs.get("account_name"),
account_type=kwargs.get("account_type"),
parent_account=kwargs.get("parent_account"),

View File

@@ -1,8 +0,0 @@
// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
// frappe.ui.form.on("Account Closing Balance", {
// refresh(frm) {
// },
// });

View File

@@ -1,164 +0,0 @@
{
"actions": [],
"creation": "2023-02-21 15:20:59.586811",
"default_view": "List",
"doctype": "DocType",
"document_type": "Document",
"engine": "InnoDB",
"field_order": [
"closing_date",
"account",
"cost_center",
"debit",
"credit",
"account_currency",
"debit_in_account_currency",
"credit_in_account_currency",
"project",
"company",
"finance_book",
"period_closing_voucher",
"is_period_closing_voucher_entry"
],
"fields": [
{
"fieldname": "closing_date",
"fieldtype": "Date",
"in_filter": 1,
"in_list_view": 1,
"label": "Closing Date",
"oldfieldname": "posting_date",
"oldfieldtype": "Date",
"search_index": 1
},
{
"fieldname": "account",
"fieldtype": "Link",
"in_filter": 1,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Account",
"oldfieldname": "account",
"oldfieldtype": "Link",
"options": "Account",
"search_index": 1
},
{
"fieldname": "cost_center",
"fieldtype": "Link",
"in_filter": 1,
"in_list_view": 1,
"label": "Cost Center",
"oldfieldname": "cost_center",
"oldfieldtype": "Link",
"options": "Cost Center"
},
{
"fieldname": "debit",
"fieldtype": "Currency",
"label": "Debit Amount",
"oldfieldname": "debit",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency"
},
{
"fieldname": "credit",
"fieldtype": "Currency",
"label": "Credit Amount",
"oldfieldname": "credit",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency"
},
{
"fieldname": "account_currency",
"fieldtype": "Link",
"label": "Account Currency",
"options": "Currency"
},
{
"fieldname": "debit_in_account_currency",
"fieldtype": "Currency",
"label": "Debit Amount in Account Currency",
"options": "account_currency"
},
{
"fieldname": "credit_in_account_currency",
"fieldtype": "Currency",
"label": "Credit Amount in Account Currency",
"options": "account_currency"
},
{
"fieldname": "project",
"fieldtype": "Link",
"label": "Project",
"options": "Project"
},
{
"fieldname": "company",
"fieldtype": "Link",
"in_filter": 1,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Company",
"oldfieldname": "company",
"oldfieldtype": "Link",
"options": "Company",
"search_index": 1
},
{
"fieldname": "finance_book",
"fieldtype": "Link",
"label": "Finance Book",
"options": "Finance Book"
},
{
"fieldname": "period_closing_voucher",
"fieldtype": "Link",
"in_standard_filter": 1,
"label": "Period Closing Voucher",
"options": "Period Closing Voucher",
"search_index": 1
},
{
"default": "0",
"fieldname": "is_period_closing_voucher_entry",
"fieldtype": "Check",
"label": "Is Period Closing Voucher Entry"
}
],
"icon": "fa fa-list",
"in_create": 1,
"links": [],
"modified": "2023-03-06 08:56:36.393237",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Account Closing Balance",
"owner": "Administrator",
"permissions": [
{
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts User"
},
{
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager"
},
{
"export": 1,
"read": 1,
"report": 1,
"role": "Auditor"
}
],
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}

View File

@@ -1,123 +0,0 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
import frappe
from frappe.model.document import Document
from frappe.utils import cint, cstr
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
get_accounting_dimensions,
)
class AccountClosingBalance(Document):
pass
def make_closing_entries(closing_entries, voucher_name, company, closing_date):
accounting_dimensions = get_accounting_dimensions()
previous_closing_entries = get_previous_closing_entries(company, closing_date, accounting_dimensions)
combined_entries = closing_entries + previous_closing_entries
merged_entries = aggregate_with_last_account_closing_balance(combined_entries, accounting_dimensions)
for _key, value in merged_entries.items():
cle = frappe.new_doc("Account Closing Balance")
cle.update(value)
cle.update(value["dimensions"])
cle.update(
{
"period_closing_voucher": voucher_name,
"closing_date": closing_date,
}
)
cle.flags.ignore_permissions = True
cle.flags.ignore_links = True
cle.submit()
def aggregate_with_last_account_closing_balance(entries, accounting_dimensions):
merged_entries = {}
for entry in entries:
key, key_values = generate_key(entry, accounting_dimensions)
merged_entries.setdefault(
key,
{
"debit": 0,
"credit": 0,
"debit_in_account_currency": 0,
"credit_in_account_currency": 0,
},
)
merged_entries[key]["dimensions"] = key_values
merged_entries[key]["debit"] += entry.get("debit")
merged_entries[key]["credit"] += entry.get("credit")
merged_entries[key]["debit_in_account_currency"] += entry.get("debit_in_account_currency")
merged_entries[key]["credit_in_account_currency"] += entry.get("credit_in_account_currency")
return merged_entries
def generate_key(entry, accounting_dimensions):
key = [
cstr(entry.get("account")),
cstr(entry.get("account_currency")),
cstr(entry.get("cost_center")),
cstr(entry.get("project")),
cstr(entry.get("finance_book")),
cint(entry.get("is_period_closing_voucher_entry")),
]
key_values = {
"company": cstr(entry.get("company")),
"account": cstr(entry.get("account")),
"account_currency": cstr(entry.get("account_currency")),
"cost_center": cstr(entry.get("cost_center")),
"project": cstr(entry.get("project")),
"finance_book": cstr(entry.get("finance_book")),
"is_period_closing_voucher_entry": cint(entry.get("is_period_closing_voucher_entry")),
}
for dimension in accounting_dimensions:
key.append(cstr(entry.get(dimension)))
key_values[dimension] = cstr(entry.get(dimension))
return tuple(key), key_values
def get_previous_closing_entries(company, closing_date, accounting_dimensions):
entries = []
last_period_closing_voucher = frappe.db.get_all(
"Period Closing Voucher",
filters={"docstatus": 1, "company": company, "posting_date": ("<", closing_date)},
fields=["name"],
order_by="posting_date desc",
limit=1,
)
if last_period_closing_voucher:
account_closing_balance = frappe.qb.DocType("Account Closing Balance")
query = frappe.qb.from_(account_closing_balance).select(
account_closing_balance.company,
account_closing_balance.account,
account_closing_balance.account_currency,
account_closing_balance.debit,
account_closing_balance.credit,
account_closing_balance.debit_in_account_currency,
account_closing_balance.credit_in_account_currency,
account_closing_balance.cost_center,
account_closing_balance.project,
account_closing_balance.finance_book,
account_closing_balance.is_period_closing_voucher_entry,
)
for dimension in accounting_dimensions:
query = query.select(account_closing_balance[dimension])
query = query.where(
account_closing_balance.period_closing_voucher == last_period_closing_voucher[0].name
)
entries = query.run(as_dict=1)
return entries

View File

@@ -1,9 +0,0 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestAccountClosingBalance(FrappeTestCase):
pass

View File

@@ -1,86 +1,63 @@
// Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Accounting Dimension", {
refresh: function (frm) {
frm.set_query("document_type", () => {
frappe.ui.form.on('Accounting Dimension', {
refresh: function(frm) {
frm.set_query('document_type', () => {
let invalid_doctypes = frappe.model.core_doctypes_list;
invalid_doctypes.push(
"Accounting Dimension",
"Project",
"Cost Center",
"Accounting Dimension Detail",
"Company"
);
invalid_doctypes.push('Accounting Dimension', 'Project',
'Cost Center', 'Accounting Dimension Detail', 'Company');
return {
filters: {
name: ["not in", invalid_doctypes],
},
};
});
frm.set_query("offsetting_account", "dimension_defaults", function (doc, cdt, cdn) {
let d = locals[cdt][cdn];
return {
filters: {
company: d.company,
root_type: ["in", ["Asset", "Liability"]],
is_group: 0,
},
name: ['not in', invalid_doctypes]
}
};
});
if (!frm.is_new()) {
frm.add_custom_button(__("Show {0}", [frm.doc.document_type]), function () {
frm.add_custom_button(__('Show {0}', [frm.doc.document_type]), function () {
frappe.set_route("List", frm.doc.document_type);
});
let button = frm.doc.disabled ? "Enable" : "Disable";
frm.add_custom_button(__(button), function () {
frm.set_value("disabled", 1 - frm.doc.disabled);
frm.add_custom_button(__(button), function() {
frm.set_value('disabled', 1 - frm.doc.disabled);
frappe.call({
method: "erpnext.accounts.doctype.accounting_dimension.accounting_dimension.disable_dimension",
args: {
doc: frm.doc,
doc: frm.doc
},
freeze: true,
callback: function (r) {
callback: function(r) {
let message = frm.doc.disabled ? "Dimension Disabled" : "Dimension Enabled";
frm.save();
frappe.show_alert({ message: __(message), indicator: "green" });
},
frappe.show_alert({message:__(message), indicator:'green'});
}
});
});
}
},
document_type: function (frm) {
frm.set_value("label", frm.doc.document_type);
frm.set_value("fieldname", frappe.model.scrub(frm.doc.document_type));
document_type: function(frm) {
frappe.db.get_value(
"Accounting Dimension",
{ document_type: frm.doc.document_type },
"document_type",
(r) => {
if (r && r.document_type) {
frm.set_df_property(
"document_type",
"description",
"Document type is already set as dimension"
);
}
frm.set_value('label', frm.doc.document_type);
frm.set_value('fieldname', frappe.model.scrub(frm.doc.document_type));
frappe.db.get_value('Accounting Dimension', {'document_type': frm.doc.document_type}, 'document_type', (r) => {
if (r && r.document_type) {
frm.set_df_property('document_type', 'description', "Document type is already set as dimension");
}
);
});
},
});
frappe.ui.form.on("Accounting Dimension Detail", {
dimension_defaults_add: function (frm, cdt, cdn) {
frappe.ui.form.on('Accounting Dimension Detail', {
dimension_defaults_add: function(frm, cdt, cdn) {
let row = locals[cdt][cdn];
row.reference_document = frm.doc.document_type;
},
}
});

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",

View File

@@ -17,20 +17,21 @@ class AccountingDimension(Document):
self.set_fieldname_and_label()
def validate(self):
if self.document_type in (
*core_doctypes_list,
if self.document_type in core_doctypes_list + (
"Accounting Dimension",
"Project",
"Cost Center",
"Accounting Dimension Detail",
"Company",
"Account",
"Finance Book",
):
msg = _("Not allowed to create accounting dimension for {0}").format(self.document_type)
frappe.throw(msg)
exists = frappe.db.get_value("Accounting Dimension", {"document_type": self.document_type}, ["name"])
exists = frappe.db.get_value(
"Accounting Dimension", {"document_type": self.document_type}, ["name"]
)
if exists and self.is_new():
frappe.throw(_("Document Type already used as a dimension"))
@@ -38,8 +39,6 @@ class AccountingDimension(Document):
if not self.is_new():
self.validate_document_type_change()
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:
@@ -47,27 +46,17 @@ class AccountingDimension(Document):
message += _("Please create a new Accounting Dimension if required.")
frappe.throw(message)
def validate_dimension_defaults(self):
companies = []
for default in self.get("dimension_defaults"):
if default.company not in companies:
companies.append(default.company)
else:
frappe.throw(_("Company {0} is added more than once").format(frappe.bold(default.company)))
def after_insert(self):
if frappe.flags.in_test:
make_dimension_in_accounting_doctypes(doc=self)
else:
frappe.enqueue(
make_dimension_in_accounting_doctypes, doc=self, queue="long", enqueue_after_commit=True
)
frappe.enqueue(make_dimension_in_accounting_doctypes, doc=self, queue="long")
def on_trash(self):
if frappe.flags.in_test:
delete_accounting_dimension(doc=self)
else:
frappe.enqueue(delete_accounting_dimension, doc=self, queue="long", enqueue_after_commit=True)
frappe.enqueue(delete_accounting_dimension, doc=self, queue="long")
def set_fieldname_and_label(self):
if not self.label:
@@ -88,6 +77,7 @@ def make_dimension_in_accounting_doctypes(doc, doclist=None):
count = 0
for doctype in doclist:
if (doc_count + 1) % 2 == 0:
insert_after_field = "dimension_col_break"
else:
@@ -121,7 +111,7 @@ def add_dimension_to_budget_doctype(df, doc):
df.update(
{
"insert_after": "cost_center",
"depends_on": f"eval:doc.budget_against == '{doc.document_type}'",
"depends_on": "eval:doc.budget_against == '{0}'".format(doc.document_type),
}
)
@@ -155,17 +145,19 @@ def delete_accounting_dimension(doc):
frappe.db.sql(
"""
DELETE FROM `tabCustom Field`
WHERE fieldname = {}
AND dt IN ({})""".format("%s", ", ".join(["%s"] * len(doclist))), # nosec
tuple([doc.fieldname, *doclist]),
WHERE fieldname = %s
AND dt IN (%s)"""
% ("%s", ", ".join(["%s"] * len(doclist))), # nosec
tuple([doc.fieldname] + doclist),
)
frappe.db.sql(
"""
DELETE FROM `tabProperty Setter`
WHERE field_name = {}
AND doc_type IN ({})""".format("%s", ", ".join(["%s"] * len(doclist))), # nosec
tuple([doc.fieldname, *doclist]),
WHERE field_name = %s
AND doc_type IN (%s)"""
% ("%s", ", ".join(["%s"] * len(doclist))), # nosec
tuple([doc.fieldname] + doclist),
)
budget_against_property = frappe.get_doc("Property Setter", "Budget-budget_against-options")
@@ -214,6 +206,7 @@ def get_doctypes_with_dimensions():
def get_accounting_dimensions(as_list=True, filters=None):
if not filters:
filters = {"disabled": 0}
@@ -231,19 +224,18 @@ def get_accounting_dimensions(as_list=True, filters=None):
def get_checks_for_pl_and_bs_accounts():
if frappe.flags.accounting_dimensions_details is None:
# nosemgrep
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""",
as_dict=1,
)
dimensions = 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""",
as_dict=1,
)
return frappe.flags.accounting_dimensions_details
return dimensions
def get_dimension_with_children(doctype, dimensions):
if isinstance(dimensions, str):
dimensions = [dimensions]
@@ -251,7 +243,9 @@ def get_dimension_with_children(doctype, dimensions):
for dimension in dimensions:
lft, rgt = frappe.db.get_value(doctype, dimension, ["lft", "rgt"])
children = frappe.get_all(doctype, filters={"lft": [">=", lft], "rgt": ["<=", rgt]}, order_by="lft")
children = frappe.get_all(
doctype, filters={"lft": [">=", lft], "rgt": ["<=", rgt]}, order_by="lft"
)
all_dimensions += [c.name for c in children]
return all_dimensions
@@ -275,12 +269,6 @@ def get_dimensions(with_cost_center_and_project=False):
as_dict=1,
)
if isinstance(with_cost_center_and_project, str):
if with_cost_center_and_project.lower().strip() == "true":
with_cost_center_and_project = True
else:
with_cost_center_and_project = False
if with_cost_center_and_project:
dimension_filters.extend(
[
@@ -295,30 +283,3 @@ def get_dimensions(with_cost_center_and_project=False):
default_dimensions_map[dimension.company][dimension.fieldname] = dimension.default_dimension
return dimension_filters, default_dimensions_map
def create_accounting_dimensions_for_doctype(doctype):
accounting_dimensions = frappe.db.get_all(
"Accounting Dimension", fields=["fieldname", "label", "document_type", "disabled"]
)
if not accounting_dimensions:
return
for d in accounting_dimensions:
field = frappe.db.get_value("Custom Field", {"dt": doctype, "fieldname": d.fieldname})
if field:
continue
df = {
"fieldname": d.fieldname,
"label": d.label,
"fieldtype": "Link",
"options": d.document_type,
"insert_after": "accounting_dimensions_section",
}
create_custom_field(doctype, df, ignore_validate=True)
frappe.clear_cache(doctype=doctype)

View File

@@ -78,8 +78,6 @@ class TestAccountingDimension(unittest.TestCase):
def tearDown(self):
disable_dimension()
frappe.flags.accounting_dimensions_details = None
frappe.flags.dimension_filter_map = None
def create_dimension():

View File

@@ -8,10 +8,7 @@
"reference_document",
"default_dimension",
"mandatory_for_bs",
"mandatory_for_pl",
"column_break_lqns",
"automatically_post_balancing_accounting_entry",
"offsetting_account"
"mandatory_for_pl"
],
"fields": [
{
@@ -53,23 +50,6 @@
"fieldtype": "Check",
"in_list_view": 1,
"label": "Mandatory For Profit and Loss Account"
},
{
"default": "0",
"fieldname": "automatically_post_balancing_accounting_entry",
"fieldtype": "Check",
"label": "Automatically post balancing accounting entry"
},
{
"fieldname": "offsetting_account",
"fieldtype": "Link",
"label": "Offsetting Account",
"mandatory_depends_on": "eval: doc.automatically_post_balancing_accounting_entry",
"options": "Account"
},
{
"fieldname": "column_break_lqns",
"fieldtype": "Column Break"
}
],
"istable": 1,

View File

@@ -1,9 +1,10 @@
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Accounting Dimension Filter", {
refresh: function (frm, cdt, cdn) {
let help_content = `<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
frappe.ui.form.on('Accounting Dimension Filter', {
refresh: function(frm, cdt, cdn) {
let help_content =
`<table class="table table-bordered" style="background-color: var(--scrollbar-track-color);">
<tr><td>
<p>
<i class="fa fa-hand-right"></i>
@@ -12,70 +13,67 @@ frappe.ui.form.on("Accounting Dimension Filter", {
</td></tr>
</table>`;
frm.set_df_property("dimension_filter_help", "options", help_content);
frm.set_df_property('dimension_filter_help', 'options', help_content);
},
onload: function (frm) {
frm.set_query("applicable_on_account", "accounts", function () {
onload: function(frm) {
frm.set_query('applicable_on_account', 'accounts', function() {
return {
filters: {
company: frm.doc.company,
},
'company': frm.doc.company
}
};
});
frappe.db.get_list("Accounting Dimension", { fields: ["document_type"] }).then((res) => {
let options = ["Cost Center", "Project"];
frappe.db.get_list('Accounting Dimension',
{fields: ['document_type']}).then((res) => {
let options = ['Cost Center', 'Project'];
res.forEach((dimension) => {
options.push(dimension.document_type);
});
frm.set_df_property("accounting_dimension", "options", options);
frm.set_df_property('accounting_dimension', 'options', options);
});
frm.trigger("setup_filters");
frm.trigger('setup_filters');
},
setup_filters: function (frm) {
setup_filters: function(frm) {
let filters = {};
if (frm.doc.accounting_dimension) {
frappe.model.with_doctype(frm.doc.accounting_dimension, function () {
frappe.model.with_doctype(frm.doc.accounting_dimension, function() {
if (frappe.model.is_tree(frm.doc.accounting_dimension)) {
filters["is_group"] = 0;
filters['is_group'] = 0;
}
if (frappe.meta.has_field(frm.doc.accounting_dimension, "company")) {
filters["company"] = frm.doc.company;
if (frappe.meta.has_field(frm.doc.accounting_dimension, 'company')) {
filters['company'] = frm.doc.company;
}
frm.set_query("dimension_value", "dimensions", function () {
frm.set_query('dimension_value', 'dimensions', function() {
return {
filters: filters,
filters: filters
};
});
});
}
},
accounting_dimension: function (frm) {
accounting_dimension: function(frm) {
frm.clear_table("dimensions");
let row = frm.add_child("dimensions");
row.accounting_dimension = frm.doc.accounting_dimension;
frm.fields_dict["dimensions"].grid.update_docfield_property(
"dimension_value",
"label",
frm.doc.accounting_dimension
);
frm.fields_dict["dimensions"].grid.update_docfield_property("dimension_value", "label", frm.doc.accounting_dimension);
frm.refresh_field("dimensions");
frm.trigger("setup_filters");
frm.trigger('setup_filters');
},
});
frappe.ui.form.on("Allowed Dimension", {
dimensions_add: function (frm, cdt, cdn) {
frappe.ui.form.on('Allowed Dimension', {
dimensions_add: function(frm, cdt, cdn) {
let row = locals[cdt][cdn];
row.accounting_dimension = frm.doc.accounting_dimension;
frm.refresh_field("dimensions");
},
}
});

View File

@@ -38,41 +38,37 @@ class AccountingDimensionFilter(Document):
def get_dimension_filter_map():
if not frappe.flags.get("dimension_filter_map"):
# nosemgrep
filters = frappe.db.sql(
"""
SELECT
a.applicable_on_account, d.dimension_value, p.accounting_dimension,
p.allow_or_restrict, a.is_mandatory
FROM
`tabApplicable On Account` a, `tabAllowed Dimension` d,
`tabAccounting Dimension Filter` p
WHERE
p.name = a.parent
AND p.disabled = 0
AND p.name = d.parent
""",
as_dict=1,
filters = frappe.db.sql(
"""
SELECT
a.applicable_on_account, d.dimension_value, p.accounting_dimension,
p.allow_or_restrict, a.is_mandatory
FROM
`tabApplicable On Account` a, `tabAllowed Dimension` d,
`tabAccounting Dimension Filter` p
WHERE
p.name = a.parent
AND p.disabled = 0
AND p.name = d.parent
""",
as_dict=1,
)
dimension_filter_map = {}
for f in filters:
f.fieldname = scrub(f.accounting_dimension)
build_map(
dimension_filter_map,
f.fieldname,
f.applicable_on_account,
f.dimension_value,
f.allow_or_restrict,
f.is_mandatory,
)
dimension_filter_map = {}
for f in filters:
f.fieldname = scrub(f.accounting_dimension)
build_map(
dimension_filter_map,
f.fieldname,
f.applicable_on_account,
f.dimension_value,
f.allow_or_restrict,
f.is_mandatory,
)
frappe.flags.dimension_filter_map = dimension_filter_map
return frappe.flags.dimension_filter_map
return dimension_filter_map
def build_map(map_object, dimension, account, filter_value, allow_or_restrict, is_mandatory):

View File

@@ -47,8 +47,6 @@ class TestAccountingDimensionFilter(unittest.TestCase):
def tearDown(self):
disable_dimension_filter()
disable_dimension()
frappe.flags.accounting_dimensions_details = None
frappe.flags.dimension_filter_map = None
for si in self.invoice_list:
si.load_from_db()
@@ -57,7 +55,9 @@ class TestAccountingDimensionFilter(unittest.TestCase):
def create_accounting_dimension_filter():
if not frappe.db.get_value("Accounting Dimension Filter", {"accounting_dimension": "Cost Center"}):
if not frappe.db.get_value(
"Accounting Dimension Filter", {"accounting_dimension": "Cost Center"}
):
frappe.get_doc(
{
"doctype": "Accounting Dimension Filter",

View File

@@ -1,33 +1,24 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Accounting Period", {
onload: function (frm) {
if (
frm.doc.closed_documents.length === 0 ||
(frm.doc.closed_documents.length === 1 && frm.doc.closed_documents[0].document_type == undefined)
) {
frappe.ui.form.on('Accounting Period', {
onload: function(frm) {
if(frm.doc.closed_documents.length === 0 || (frm.doc.closed_documents.length === 1 && frm.doc.closed_documents[0].document_type == undefined)) {
frappe.call({
method: "get_doctypes_for_closing",
doc: frm.doc,
callback: function (r) {
if (r.message) {
doc:frm.doc,
callback: function(r) {
if(r.message) {
cur_frm.clear_table("closed_documents");
r.message.forEach(function (element) {
r.message.forEach(function(element) {
var c = frm.add_child("closed_documents");
c.document_type = element.document_type;
c.closed = element.closed;
});
refresh_field("closed_documents");
}
},
}
});
}
frm.set_query("document_type", "closed_documents", () => {
return {
query: "erpnext.controllers.queries.get_doctypes_for_closing",
};
});
},
}
});

View File

@@ -11,10 +11,6 @@ class OverlapError(frappe.ValidationError):
pass
class ClosedAccountingPeriod(frappe.ValidationError):
pass
class AccountingPeriod(Document):
def validate(self):
self.validate_overlap()
@@ -67,47 +63,5 @@ class AccountingPeriod(Document):
for doctype_for_closing in self.get_doctypes_for_closing():
self.append(
"closed_documents",
{
"document_type": doctype_for_closing.document_type,
"closed": doctype_for_closing.closed,
},
{"document_type": doctype_for_closing.document_type, "closed": doctype_for_closing.closed},
)
def validate_accounting_period_on_doc_save(doc, method=None):
if doc.doctype == "Bank Clearance":
return
elif doc.doctype == "Asset":
if doc.is_existing_asset:
return
else:
date = doc.available_for_use_date
elif doc.doctype == "Asset Repair":
date = doc.completion_date
else:
date = doc.posting_date
ap = frappe.qb.DocType("Accounting Period")
cd = frappe.qb.DocType("Closed Document")
accounting_period = (
frappe.qb.from_(ap)
.from_(cd)
.select(ap.name)
.where(
(ap.name == cd.parent)
& (ap.company == doc.company)
& (cd.closed == 1)
& (cd.document_type == doc.doctype)
& (date >= ap.start_date)
& (date <= ap.end_date)
)
).run(as_dict=1)
if accounting_period:
frappe.throw(
_("You cannot create a {0} within the closed Accounting Period {1}").format(
doc.doctype, frappe.bold(accounting_period[0]["name"])
),
ClosedAccountingPeriod,
)

View File

@@ -6,11 +6,9 @@ import unittest
import frappe
from frappe.utils import add_months, nowdate
from erpnext.accounts.doctype.accounting_period.accounting_period import (
ClosedAccountingPeriod,
OverlapError,
)
from erpnext.accounts.doctype.accounting_period.accounting_period import OverlapError
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.accounts.general_ledger import ClosedAccountingPeriod
test_dependencies = ["Item"]
@@ -34,8 +32,10 @@ class TestAccountingPeriod(unittest.TestCase):
ap1 = create_accounting_period(period_name="Test Accounting Period 2")
ap1.save()
doc = create_sales_invoice(do_not_save=1, cost_center="_Test Company - _TC", warehouse="Stores - _TC")
self.assertRaises(ClosedAccountingPeriod, doc.save)
doc = create_sales_invoice(
do_not_submit=1, cost_center="_Test Company - _TC", warehouse="Stores - _TC"
)
self.assertRaises(ClosedAccountingPeriod, doc.submit)
def tearDown(self):
for d in frappe.get_all("Accounting Period"):

View File

@@ -1,6 +1,8 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Accounts Settings", {
refresh: function (frm) {},
frappe.ui.form.on('Accounts Settings', {
refresh: function(frm) {
}
});

View File

@@ -19,8 +19,6 @@
"column_break_17",
"enable_common_party_accounting",
"allow_multi_currency_invoices_against_single_party_account",
"journals_section",
"merge_similar_account_heads",
"report_setting_section",
"use_custom_cash_flow",
"deferred_accounting_settings_section",
@@ -33,18 +31,13 @@
"determine_address_tax_category_from",
"column_break_19",
"add_taxes_from_item_tax_template",
"book_tax_discount_loss",
"print_settings",
"show_inclusive_tax_in_print",
"show_taxes_as_table_in_print",
"column_break_12",
"show_payment_schedule_in_print",
"currency_exchange_section",
"allow_stale",
"section_break_jpd0",
"auto_reconcile_payments",
"stale_days",
"exchange_gain_loss_posting_date",
"invoicing_settings_tab",
"accounts_transactions_settings_section",
"over_billing_allowance",
@@ -61,24 +54,9 @@
"closing_settings_tab",
"period_closing_settings_section",
"acc_frozen_upto",
"ignore_account_closing_balance",
"column_break_25",
"frozen_accounts_modifier",
"report_settings_sb",
"banking_tab",
"enable_party_matching",
"enable_fuzzy_matching",
"tab_break_dpet",
"show_balance_in_coa",
"reports_tab",
"remarks_section",
"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"
"report_settings_sb"
],
"fields": [
{
@@ -189,6 +167,11 @@
"fieldtype": "Int",
"label": "Stale Days"
},
{
"fieldname": "report_settings_sb",
"fieldtype": "Section Break",
"label": "Report Settings"
},
{
"default": "0",
"description": "Only select this if you have set up the Cash Flow Mapper documents",
@@ -198,7 +181,6 @@
},
{
"default": "0",
"description": "Payment Terms from orders will be fetched into the invoices as is",
"fieldname": "automatically_fetch_payment_terms",
"fieldtype": "Check",
"label": "Automatically Fetch Payment Terms from Order"
@@ -365,140 +347,6 @@
"fieldname": "allow_multi_currency_invoices_against_single_party_account",
"fieldtype": "Check",
"label": "Allow multi-currency invoices against single party account "
},
{
"default": "0",
"description": "Split Early Payment Discount Loss into Income and Tax Loss",
"fieldname": "book_tax_discount_loss",
"fieldtype": "Check",
"label": "Book Tax Loss on Early Payment Discount"
},
{
"fieldname": "journals_section",
"fieldtype": "Section Break",
"label": "Journals"
},
{
"default": "0",
"description": "Rows with Same Account heads will be merged on Ledger",
"fieldname": "merge_similar_account_heads",
"fieldtype": "Check",
"label": "Merge Similar Account Heads"
},
{
"fieldname": "section_break_jpd0",
"fieldtype": "Section Break",
"label": "Payment Reconciliation Settings"
},
{
"default": "0",
"fieldname": "auto_reconcile_payments",
"fieldtype": "Check",
"label": "Auto Reconcile Payments"
},
{
"default": "0",
"fieldname": "show_taxes_as_table_in_print",
"fieldtype": "Check",
"label": "Show Taxes as Table in Print"
},
{
"fieldname": "banking_tab",
"fieldtype": "Tab Break",
"label": "Banking"
},
{
"default": "0",
"description": "Auto match and set the Party in Bank Transactions",
"fieldname": "enable_party_matching",
"fieldtype": "Check",
"label": "Enable Automatic Party Matching"
},
{
"default": "0",
"depends_on": "enable_party_matching",
"description": "Approximately match the description/party name against parties",
"fieldname": "enable_fuzzy_matching",
"fieldtype": "Check",
"label": "Enable Fuzzy Matching"
},
{
"default": "0",
"description": "Financial reports will be generated using GL Entry doctypes (should be enabled if Period Closing Voucher is not posted for all years sequentially or missing) ",
"fieldname": "ignore_account_closing_balance",
"fieldtype": "Check",
"label": "Ignore Account Closing Balance"
},
{
"fieldname": "tab_break_dpet",
"fieldtype": "Tab Break",
"label": "Chart Of Accounts"
},
{
"default": "1",
"fieldname": "show_balance_in_coa",
"fieldtype": "Check",
"label": "Show Balances in Chart Of Accounts"
},
{
"fieldname": "reports_tab",
"fieldtype": "Tab Break",
"label": "Reports"
},
{
"default": "0",
"description": "Truncates 'Remarks' column to set character length",
"fieldname": "general_ledger_remarks_length",
"fieldtype": "Int",
"label": "General Ledger"
},
{
"default": "0",
"description": "Truncates 'Remarks' column to set character length",
"fieldname": "receivable_payable_remarks_length",
"fieldtype": "Int",
"label": "Accounts Receivable/Payable"
},
{
"fieldname": "column_break_lvjk",
"fieldtype": "Column Break"
},
{
"fieldname": "remarks_section",
"fieldtype": "Section Break",
"label": "Remarks Column Length"
},
{
"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"
},
{
"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": "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"
}
],
"icon": "icon-cog",
@@ -506,7 +354,7 @@
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2025-05-05 12:29:38.302027",
"modified": "2022-11-27 21:49:52.538655",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",
@@ -535,4 +383,4 @@
"sort_order": "ASC",
"states": [],
"track_changes": 1
}
}

View File

@@ -14,32 +14,21 @@ from erpnext.stock.utils import check_pending_reposting
class AccountsSettings(Document):
def on_update(self):
frappe.clear_cache()
def validate(self):
old_doc = self.get_doc_before_save()
clear_cache = False
frappe.db.set_default(
"add_taxes_from_item_tax_template", self.get("add_taxes_from_item_tax_template", 0)
)
if old_doc.add_taxes_from_item_tax_template != self.add_taxes_from_item_tax_template:
frappe.db.set_default(
"add_taxes_from_item_tax_template", self.get("add_taxes_from_item_tax_template", 0)
)
clear_cache = True
if old_doc.enable_common_party_accounting != self.enable_common_party_accounting:
frappe.db.set_default(
"enable_common_party_accounting", self.get("enable_common_party_accounting", 0)
)
clear_cache = True
frappe.db.set_default(
"enable_common_party_accounting", self.get("enable_common_party_accounting", 0)
)
self.validate_stale_days()
if old_doc.show_payment_schedule_in_print != self.show_payment_schedule_in_print:
self.enable_payment_schedule_in_print()
if old_doc.acc_frozen_upto != self.acc_frozen_upto:
self.validate_pending_reposts()
if clear_cache:
frappe.clear_cache()
self.enable_payment_schedule_in_print()
self.validate_pending_reposts()
def validate_stale_days(self):
if not self.allow_stale and cint(self.stale_days) <= 0:

View File

@@ -1,11 +1,8 @@
frappe.ui.form.on("Accounts Settings", {
refresh: function (frm) {
frappe.ui.form.on('Accounts Settings', {
refresh: function(frm) {
frm.set_df_property("acc_frozen_upto", "label", "Books Closed Through");
frm.set_df_property(
"frozen_accounts_modifier",
"label",
"Role Allowed to Close Books & Make Changes to Closed Periods"
);
frm.set_df_property("frozen_accounts_modifier", "label", "Role Allowed to Close Books & Make Changes to Closed Periods");
frm.set_df_property("credit_controller", "label", "Credit Manager");
},
}
});

View File

@@ -11,7 +11,6 @@
{
"fieldname": "company",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"in_list_view": 1,
"label": "Company",
"options": "Company",
@@ -20,7 +19,7 @@
],
"istable": 1,
"links": [],
"modified": "2024-01-03 11:13:02.669632",
"modified": "2020-05-01 12:32:34.044911",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Allowed To Transact With",
@@ -29,6 +28,5 @@
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"states": [],
"track_changes": 1
}

View File

@@ -1,39 +1,41 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.provide("erpnext.integrations");
frappe.provide('erpnext.integrations');
frappe.ui.form.on("Bank", {
onload: function (frm) {
frappe.ui.form.on('Bank', {
onload: function(frm) {
add_fields_to_mapping_table(frm);
},
refresh: function (frm) {
refresh: function(frm) {
add_fields_to_mapping_table(frm);
frappe.dynamic_link = { doc: frm.doc, fieldname: "name", doctype: "Bank" };
frappe.dynamic_link = { doc: frm.doc, fieldname: 'name', doctype: 'Bank' };
frm.toggle_display(["address_html", "contact_html"], !frm.doc.__islocal);
frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal);
if (frm.doc.__islocal) {
frm.set_df_property("address_and_contact", "hidden", 1);
frm.set_df_property('address_and_contact', 'hidden', 1);
frappe.contacts.clear_address_and_contact(frm);
} else {
frm.set_df_property("address_and_contact", "hidden", 0);
}
else {
frm.set_df_property('address_and_contact', 'hidden', 0);
frappe.contacts.render_address_and_contact(frm);
}
if (frm.doc.plaid_access_token) {
frm.add_custom_button(__("Refresh Plaid Link"), () => {
frm.add_custom_button(__('Refresh Plaid Link'), () => {
new erpnext.integrations.refreshPlaidLink(frm.doc.plaid_access_token);
});
}
},
}
});
let add_fields_to_mapping_table = function (frm) {
let options = [];
frappe.model.with_doctype("Bank Transaction", function () {
frappe.model.with_doctype("Bank Transaction", function() {
let meta = frappe.get_meta("Bank Transaction");
meta.fields.forEach((value) => {
meta.fields.forEach(value => {
if (!["Section Break", "Column Break"].includes(value.fieldtype)) {
options.push(value.fieldname);
}
@@ -41,32 +43,30 @@ let add_fields_to_mapping_table = function (frm) {
});
frm.fields_dict.bank_transaction_mapping.grid.update_docfield_property(
"bank_transaction_field",
"options",
options
'bank_transaction_field', 'options', options
);
};
erpnext.integrations.refreshPlaidLink = class refreshPlaidLink {
constructor(access_token) {
this.access_token = access_token;
this.plaidUrl = "https://cdn.plaid.com/link/v2/stable/link-initialize.js";
this.plaidUrl = 'https://cdn.plaid.com/link/v2/stable/link-initialize.js';
this.init_config();
}
async init_config() {
this.plaid_env = await frappe.db.get_single_value("Plaid Settings", "plaid_env");
this.plaid_env = await frappe.db.get_single_value('Plaid Settings', 'plaid_env');
this.token = await this.get_link_token_for_update();
this.init_plaid();
}
async get_link_token_for_update() {
const token = frappe.xcall(
"erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.get_link_token_for_update",
'erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.get_link_token_for_update',
{ access_token: this.access_token }
);
)
if (!token) {
frappe.throw(__("Cannot retrieve link token for update. Check Error Log for more information"));
frappe.throw(__('Cannot retrieve link token for update. Check Error Log for more information'));
}
return token;
}
@@ -93,13 +93,13 @@ erpnext.integrations.refreshPlaidLink = class refreshPlaidLink {
resolve();
return;
}
const el = document.createElement("script");
el.type = "text/javascript";
const el = document.createElement('script');
el.type = 'text/javascript';
el.async = true;
el.src = src;
el.addEventListener("load", resolve);
el.addEventListener("error", reject);
el.addEventListener("abort", reject);
el.addEventListener('load', resolve);
el.addEventListener('error', reject);
el.addEventListener('abort', reject);
document.head.appendChild(el);
});
}
@@ -108,29 +108,16 @@ erpnext.integrations.refreshPlaidLink = class refreshPlaidLink {
me.linkHandler = Plaid.create({
env: me.plaid_env,
token: me.token,
onSuccess: me.plaid_success,
onSuccess: me.plaid_success
});
}
onScriptError(error) {
frappe.msgprint(
__(
"There was an issue connecting to Plaid's authentication server. Check browser console for more information"
)
);
frappe.msgprint(__("There was an issue connecting to Plaid's authentication server. Check browser console for more information"));
console.log(error);
}
plaid_success(token, response) {
frappe
.xcall(
"erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.update_bank_account_ids",
{
response: response,
}
)
.then(() => {
frappe.show_alert({ message: __("Plaid Link Updated"), indicator: "green" });
});
frappe.show_alert({ message: __('Plaid Link Updated'), indicator: 'green' });
}
};

View File

@@ -1,49 +1,45 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Bank Account", {
setup: function (frm) {
frm.set_query("account", function () {
frappe.ui.form.on('Bank Account', {
setup: function(frm) {
frm.set_query("account", function() {
return {
filters: {
account_type: "Bank",
company: frm.doc.company,
is_group: 0,
},
'account_type': 'Bank',
'company': frm.doc.company,
'is_group': 0
}
};
});
frm.set_query("party_type", function () {
frm.set_query("party_type", function() {
return {
query: "erpnext.setup.doctype.party_type.party_type.get_party_type",
};
});
},
refresh: function (frm) {
frappe.dynamic_link = { doc: frm.doc, fieldname: "name", doctype: "Bank Account" };
refresh: function(frm) {
frappe.dynamic_link = { doc: frm.doc, fieldname: 'name', doctype: 'Bank Account' }
frm.toggle_display(["address_html", "contact_html"], !frm.doc.__islocal);
frm.toggle_display(['address_html','contact_html'], !frm.doc.__islocal);
if (frm.doc.__islocal) {
frappe.contacts.clear_address_and_contact(frm);
} else {
}
else {
frappe.contacts.render_address_and_contact(frm);
}
if (frm.doc.integration_id) {
frm.add_custom_button(__("Unlink external integrations"), function () {
frappe.confirm(
__(
"This action will unlink this account from any external service integrating ERPNext with your bank accounts. It cannot be undone. Are you certain ?"
),
function () {
frm.set_value("integration_id", "");
}
);
frm.add_custom_button(__("Unlink external integrations"), function() {
frappe.confirm(__("This action will unlink this account from any external service integrating ERPNext with your bank accounts. It cannot be undone. Are you certain ?"), function() {
frm.set_value("integration_id", "");
});
});
}
},
is_company_account: function (frm) {
frm.set_df_property("account", "reqd", frm.doc.is_company_account);
},
is_company_account: function(frm) {
frm.set_df_property('account', 'reqd', frm.doc.is_company_account);
}
});

View File

@@ -13,7 +13,6 @@
"account_type",
"account_subtype",
"column_break_7",
"disabled",
"is_default",
"is_company_account",
"company",
@@ -200,57 +199,10 @@
"fieldtype": "Data",
"in_global_search": 1,
"label": "Branch Code"
},
{
"default": "0",
"fieldname": "disabled",
"fieldtype": "Check",
"label": "Disabled"
}
],
"links": [
{
"group": "Transactions",
"link_doctype": "Payment Request",
"link_fieldname": "bank_account"
},
{
"group": "Transactions",
"link_doctype": "Payment Order",
"link_fieldname": "bank_account"
},
{
"group": "Transactions",
"link_doctype": "Bank Guarantee",
"link_fieldname": "bank_account"
},
{
"group": "Transactions",
"link_doctype": "Bank Transaction",
"link_fieldname": "bank_account"
},
{
"group": "Accounting",
"link_doctype": "Payment Entry",
"link_fieldname": "bank_account"
},
{
"group": "Accounting",
"link_doctype": "Journal Entry",
"link_fieldname": "bank_account"
},
{
"group": "Party",
"link_doctype": "Customer",
"link_fieldname": "default_bank_account"
},
{
"group": "Party",
"link_doctype": "Supplier",
"link_fieldname": "default_bank_account"
}
],
"modified": "2024-10-30 09:41:14.113414",
"links": [],
"modified": "2022-05-04 15:49:42.620630",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Account",
@@ -287,4 +239,4 @@
"sort_order": "DESC",
"states": [],
"track_changes": 1
}
}

View File

@@ -9,7 +9,6 @@ from frappe.contacts.address_and_contact import (
load_address_and_contact,
)
from frappe.model.document import Document
from frappe.utils import comma_and, get_link_to_form
class BankAccount(Document):
@@ -21,24 +20,11 @@ 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()
self.validate_iban()
self.validate_account()
def validate_account(self):
if self.account:
if accounts := frappe.db.get_all(
"Bank Account", filters={"account": self.account, "name": ["!=", self.name]}, as_list=1
):
frappe.throw(
_("'{0}' account is already used by {1}. Use another account.").format(
frappe.bold(self.account),
frappe.bold(comma_and([get_link_to_form(self.doctype, x[0]) for x in accounts])),
)
)
def validate_company(self):
if self.is_company_account and not self.company:
@@ -91,6 +77,6 @@ def get_party_bank_account(party_type, party):
@frappe.whitelist()
def get_bank_account_details(bank_account):
return frappe.db.get_value(
return frappe.get_cached_value(
"Bank Account", bank_account, ["account", "bank", "bank_account_no"], as_dict=1
)

View File

@@ -0,0 +1,20 @@
from frappe import _
def get_data():
return {
"fieldname": "bank_account",
"non_standard_fieldnames": {
"Customer": "default_bank_account",
"Supplier": "default_bank_account",
},
"transactions": [
{
"label": _("Payments"),
"items": ["Payment Entry", "Payment Request", "Payment Order", "Payroll Entry"],
},
{"label": _("Party"), "items": ["Customer", "Supplier"]},
{"items": ["Bank Guarantee"]},
{"items": ["Journal Entry"]},
],
}

View File

@@ -37,11 +37,11 @@ class TestBankAccount(unittest.TestCase):
try:
bank_account.validate_iban()
except ValidationError:
msg = f"BankAccount.validate_iban() failed for valid IBAN {iban}"
msg = "BankAccount.validate_iban() failed for valid IBAN {}".format(iban)
self.fail(msg=msg)
for not_iban in invalid_ibans:
bank_account.iban = not_iban
msg = f"BankAccount.validate_iban() accepted invalid IBAN {not_iban}"
msg = "BankAccount.validate_iban() accepted invalid IBAN {}".format(not_iban)
with self.assertRaises(ValidationError, msg=msg):
bank_account.validate_iban()

View File

@@ -1,6 +1,8 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Bank Account Subtype", {
refresh: function () {},
frappe.ui.form.on('Bank Account Subtype', {
refresh: function() {
}
});

View File

@@ -1,7 +1,8 @@
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Bank Account Type", {
frappe.ui.form.on('Bank Account Type', {
// refresh: function(frm) {
// }
});

View File

@@ -2,65 +2,83 @@
// License: GNU General Public License v3. See license.txt
frappe.ui.form.on("Bank Clearance", {
setup: function (frm) {
setup: function(frm) {
frm.add_fetch("account", "account_currency", "account_currency");
frm.set_query("account", function () {
frm.set_query("account", function() {
return {
filters: {
account_type: ["in", ["Bank", "Cash"]],
is_group: 0,
},
"filters": {
"account_type": ["in",["Bank","Cash"]],
"is_group": 0,
}
};
});
frm.set_query("bank_account", function () {
return {
filters: {
is_company_account: 1,
'is_company_account': 1
},
};
});
},
onload: function (frm) {
let default_bank_account = frappe.defaults.get_user_default("Company")
? locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"]
: "";
onload: function(frm) {
let default_bank_account = frappe.defaults.get_user_default("Company")?
locals[":Company"][frappe.defaults.get_user_default("Company")]["default_bank_account"]: "";
frm.set_value("account", default_bank_account);
frm.set_value("from_date", frappe.datetime.month_start());
frm.set_value("to_date", frappe.datetime.month_end());
},
refresh: function (frm) {
refresh: function(frm) {
frm.disable_save();
frm.add_custom_button(__("Get Payment Entries"), () => frm.trigger("get_payment_entries"));
frm.change_custom_button_type(__("Get Payment Entries"), null, "primary");
if (frm.doc.payment_entries.length) {
frm.add_custom_button(__("Update Clearance Date"), () => frm.trigger("update_clearance_date"));
frm.change_custom_button_type(__("Get Payment Entries"), null, "default");
frm.change_custom_button_type(__("Update Clearance Date"), null, "primary");
if (frm.doc.account && frm.doc.from_date && frm.doc.to_date) {
frm.add_custom_button(__('Get Payment Entries'), () =>
frm.trigger("get_payment_entries")
);
frm.change_custom_button_type('Get Payment Entries', null, 'primary');
}
},
update_clearance_date: function (frm) {
update_clearance_date: function(frm) {
return frappe.call({
method: "update_clearance_date",
doc: frm.doc,
callback: function (r, rt) {
frm.refresh();
},
callback: function(r, rt) {
frm.refresh_field("payment_entries");
frm.refresh_fields();
if (!frm.doc.payment_entries.length) {
frm.change_custom_button_type('Get Payment Entries', null, 'primary');
frm.change_custom_button_type('Update Clearance Date', null, 'default');
}
}
});
},
get_payment_entries: function (frm) {
get_payment_entries: function(frm) {
return frappe.call({
method: "get_payment_entries",
doc: frm.doc,
callback: function () {
frm.refresh();
},
callback: function(r, rt) {
frm.refresh_field("payment_entries");
if (frm.doc.payment_entries.length) {
frm.add_custom_button(__('Update Clearance Date'), () =>
frm.trigger("update_clearance_date")
);
frm.change_custom_button_type('Get Payment Entries', null, 'default');
frm.change_custom_button_type('Update Clearance Date', null, 'primary');
}
}
});
},
}
});

View File

@@ -6,7 +6,7 @@ import frappe
from frappe import _, msgprint
from frappe.model.document import Document
from frappe.query_builder.custom import ConstantColumn
from frappe.utils import flt, fmt_money, get_link_to_form, getdate
from frappe.utils import flt, fmt_money, getdate
import erpnext
@@ -27,7 +27,7 @@ class BankClearance(Document):
condition = "and (clearance_date IS NULL or clearance_date='0000-00-00')"
journal_entries = frappe.db.sql(
f"""
"""
select
"Journal Entry" as payment_document, t1.name as payment_entry,
t1.cheque_no as cheque_number, t1.cheque_date,
@@ -41,18 +41,23 @@ class BankClearance(Document):
and ifnull(t1.is_opening, 'No') = 'No' {condition}
group by t2.account, t1.name
order by t1.posting_date ASC, t1.name DESC
""",
""".format(
condition=condition
),
{"account": self.account, "from": self.from_date, "to": self.to_date},
as_dict=1,
)
if self.bank_account:
condition += "and bank_account = %(bank_account)s"
payment_entries = frappe.db.sql(
f"""
"""
select
"Payment Entry" as payment_document, name as payment_entry,
reference_no as cheque_number, reference_date as cheque_date,
if(paid_from=%(account)s, paid_amount + total_taxes_and_charges, 0) as credit,
if(paid_from=%(account)s, 0, received_amount + total_taxes_and_charges) as debit,
if(paid_from=%(account)s, paid_amount, 0) as credit,
if(paid_from=%(account)s, 0, received_amount) as debit,
posting_date, ifnull(party,if(paid_from=%(account)s,paid_to,paid_from)) as against_account, clearance_date,
if(paid_to=%(account)s, paid_to_account_currency, paid_from_account_currency) as account_currency
from `tabPayment Entry`
@@ -62,18 +67,21 @@ class BankClearance(Document):
{condition}
order by
posting_date ASC, name DESC
""",
""".format(
condition=condition
),
{
"account": self.account,
"from": self.from_date,
"to": self.to_date,
"bank_account": self.bank_account,
},
as_dict=1,
)
loan_disbursement = frappe.qb.DocType("Loan Disbursement")
query = (
loan_disbursements = (
frappe.qb.from_(loan_disbursement)
.select(
ConstantColumn("Loan Disbursement").as_("payment_document"),
@@ -82,22 +90,17 @@ class BankClearance(Document):
ConstantColumn(0).as_("debit"),
loan_disbursement.reference_number.as_("cheque_number"),
loan_disbursement.reference_date.as_("cheque_date"),
loan_disbursement.clearance_date.as_("clearance_date"),
loan_disbursement.disbursement_date.as_("posting_date"),
loan_disbursement.applicant.as_("against_account"),
)
.where(loan_disbursement.docstatus == 1)
.where(loan_disbursement.disbursement_date >= self.from_date)
.where(loan_disbursement.disbursement_date <= self.to_date)
.where(loan_disbursement.disbursement_account == self.account)
.where(loan_disbursement.clearance_date.isnull())
.where(loan_disbursement.disbursement_account.isin([self.bank_account, self.account]))
.orderby(loan_disbursement.disbursement_date)
.orderby(loan_disbursement.name, order=frappe.qb.desc)
)
if not self.include_reconciled_entries:
query = query.where(loan_disbursement.clearance_date.isnull())
loan_disbursements = query.run(as_dict=1)
).run(as_dict=1)
loan_repayment = frappe.qb.DocType("Loan Repayment")
@@ -110,23 +113,22 @@ class BankClearance(Document):
ConstantColumn(0).as_("credit"),
loan_repayment.reference_number.as_("cheque_number"),
loan_repayment.reference_date.as_("cheque_date"),
loan_repayment.clearance_date.as_("clearance_date"),
loan_repayment.applicant.as_("against_account"),
loan_repayment.posting_date,
)
.where(loan_repayment.docstatus == 1)
.where(loan_repayment.clearance_date.isnull())
.where(loan_repayment.posting_date >= self.from_date)
.where(loan_repayment.posting_date <= self.to_date)
.where(loan_repayment.payment_account == self.account)
.where(loan_repayment.payment_account.isin([self.bank_account, self.account]))
)
if not self.include_reconciled_entries:
query = query.where(loan_repayment.clearance_date.isnull())
if frappe.db.has_column("Loan Repayment", "repay_from_salary"):
query = query.where(loan_repayment.repay_from_salary == 0)
query = query.where((loan_repayment.repay_from_salary == 0))
query = query.orderby(loan_repayment.posting_date).orderby(loan_repayment.name, order=frappe.qb.desc)
query = query.orderby(loan_repayment.posting_date).orderby(
loan_repayment.name, order=frappe.qb.desc
)
loan_repayments = query.run(as_dict=True)
@@ -206,11 +208,8 @@ class BankClearance(Document):
if d.cheque_date and getdate(d.clearance_date) < getdate(d.cheque_date):
frappe.throw(
_("Row #{0}: For {1} Clearance date {2} cannot be before Cheque Date {3}").format(
d.idx,
get_link_to_form(d.payment_document, d.payment_entry),
d.clearance_date,
d.cheque_date,
_("Row #{0}: Clearance date {1} cannot be before Cheque Date {2}").format(
d.idx, d.clearance_date, d.cheque_date
)
)

View File

@@ -1,39 +1,39 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
cur_frm.add_fetch("bank_account", "account", "account");
cur_frm.add_fetch("bank_account", "bank_account_no", "bank_account_no");
cur_frm.add_fetch("bank_account", "iban", "iban");
cur_frm.add_fetch("bank_account", "branch_code", "branch_code");
cur_frm.add_fetch("bank", "swift_number", "swift_number");
cur_frm.add_fetch('bank_account','account','account');
cur_frm.add_fetch('bank_account','bank_account_no','bank_account_no');
cur_frm.add_fetch('bank_account','iban','iban');
cur_frm.add_fetch('bank_account','branch_code','branch_code');
cur_frm.add_fetch('bank','swift_number','swift_number');
frappe.ui.form.on("Bank Guarantee", {
setup: function (frm) {
frm.set_query("bank", function () {
frappe.ui.form.on('Bank Guarantee', {
setup: function(frm) {
frm.set_query("bank", function() {
return {
filters: {
company: frm.doc.company
}
};
});
frm.set_query("bank_account", function() {
return {
filters: {
company: frm.doc.company,
},
};
bank: frm.doc.bank
}
}
});
frm.set_query("bank_account", function () {
frm.set_query("project", function() {
return {
filters: {
company: frm.doc.company,
bank: frm.doc.bank,
},
};
});
frm.set_query("project", function () {
return {
filters: {
customer: frm.doc.customer,
},
customer: frm.doc.customer
}
};
});
},
bg_type: function (frm) {
bg_type: function(frm) {
if (frm.doc.bg_type == "Receiving") {
frm.set_value("reference_doctype", "Sales Order");
} else if (frm.doc.bg_type == "Providing") {
@@ -41,33 +41,34 @@ frappe.ui.form.on("Bank Guarantee", {
}
},
reference_docname: function (frm) {
reference_docname: function(frm) {
if (frm.doc.reference_docname && frm.doc.reference_doctype) {
let party_field = frm.doc.reference_doctype == "Sales Order" ? "customer" : "supplier";
frappe.call({
method: "erpnext.accounts.doctype.bank_guarantee.bank_guarantee.get_voucher_details",
args: {
bank_guarantee_type: frm.doc.bg_type,
reference_name: frm.doc.reference_docname,
"bank_guarantee_type": frm.doc.bg_type,
"reference_name": frm.doc.reference_docname
},
callback: function (r) {
callback: function(r) {
if (r.message) {
if (r.message[party_field]) frm.set_value(party_field, r.message[party_field]);
if (r.message.project) frm.set_value("project", r.message.project);
if (r.message.grand_total) frm.set_value("amount", r.message.grand_total);
}
},
}
});
}
},
start_date: function (frm) {
start_date: function(frm) {
var end_date = frappe.datetime.add_days(cur_frm.doc.start_date, cur_frm.doc.validity - 1);
cur_frm.set_value("end_date", end_date);
},
validity: function (frm) {
validity: function(frm) {
var end_date = frappe.datetime.add_days(cur_frm.doc.start_date, cur_frm.doc.validity - 1);
cur_frm.set_value("end_date", end_date);
},
}
});

View File

@@ -8,88 +8,70 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
return {
filters: {
company: frm.doc.company,
is_company_account: 1,
'is_company_account': 1
},
};
});
let no_bank_transactions_text = `<div class="text-muted text-center">${__(
"No Matching Bank Transactions Found"
)}</div>`;
let no_bank_transactions_text =
`<div class="text-muted text-center">${__("No Matching Bank Transactions Found")}</div>`
set_field_options("no_bank_transactions", no_bank_transactions_text);
},
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");
},
filter_by_reference_date: function (frm) {
if (frm.doc.filter_by_reference_date) {
frm.set_value("bank_statement_from_date", "");
frm.set_value("bank_statement_to_date", "");
} else {
frm.set_value("from_reference_date", "");
frm.set_value("to_reference_date", "");
}
frm.trigger('bank_account');
},
refresh: function (frm) {
frm.disable_save();
frappe.require("bank-reconciliation-tool.bundle.js", () => frm.trigger("make_reconciliation_tool"));
frm.add_custom_button(__("Upload Bank Statement"), () =>
frappe.call({
method: "erpnext.accounts.doctype.bank_statement_import.bank_statement_import.upload_bank_statement",
args: {
dt: frm.doc.doctype,
dn: frm.doc.name,
company: frm.doc.company,
bank_account: frm.doc.bank_account,
},
callback: function (r) {
if (!r.exc) {
var doc = frappe.model.sync(r.message);
frappe.set_route("Form", doc[0].doctype, doc[0].name);
}
},
})
frappe.require("bank-reconciliation-tool.bundle.js", () =>
frm.trigger("make_reconciliation_tool")
);
frm.upload_statement_button = frm.page.set_secondary_action(
__("Upload Bank Statement"),
() =>
frappe.call({
method:
"erpnext.accounts.doctype.bank_statement_import.bank_statement_import.upload_bank_statement",
args: {
dt: frm.doc.doctype,
dn: frm.doc.name,
company: frm.doc.company,
bank_account: frm.doc.bank_account,
},
callback: function (r) {
if (!r.exc) {
var doc = frappe.model.sync(r.message);
frappe.set_route(
"Form",
doc[0].doctype,
doc[0].name
);
}
},
})
);
},
frm.add_custom_button(__("Auto Reconcile"), function () {
frappe.call({
method: "erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.auto_reconcile_vouchers",
args: {
bank_account: frm.doc.bank_account,
from_date: frm.doc.bank_statement_from_date,
to_date: frm.doc.bank_statement_to_date,
filter_by_reference_date: frm.doc.filter_by_reference_date,
from_reference_date: frm.doc.from_reference_date,
to_reference_date: frm.doc.to_reference_date,
},
});
});
frm.add_custom_button(__("Get Unreconciled Entries"), function () {
frm.trigger("make_reconciliation_tool");
});
frm.change_custom_button_type("Get Unreconciled Entries", null, "primary");
after_save: function (frm) {
frm.trigger("make_reconciliation_tool");
},
bank_account: function (frm) {
frappe.db.get_value("Bank Account", frm.doc.bank_account, "account", (r) => {
frappe.db.get_value("Account", r.account, "account_currency", (r) => {
frm.doc.account_currency = r.account_currency;
frm.trigger("render_chart");
});
});
frappe.db.get_value(
"Bank Account",
frm.doc.bank_account,
"account",
(r) => {
frappe.db.get_value(
"Account",
r.account,
"account_currency",
(r) => {
frm.currency = r.account_currency;
frm.trigger("render_chart");
}
);
}
);
frm.trigger("get_account_opening_balance");
},
@@ -99,7 +81,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 &&
@@ -108,19 +90,24 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
) {
frm.trigger("render_chart");
frm.trigger("render");
frappe.utils.scroll_to(frm.get_field("reconciliation_tool_cards").$wrapper, true, 30);
frappe.utils.scroll_to(
frm.get_field("reconciliation_tool_cards").$wrapper,
true,
30
);
}
});
}
},
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",
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),
till_date: frm.doc.bank_statement_from_date,
},
callback: (response) => {
frm.set_value("account_opening_balance", response.message);
@@ -130,9 +117,10 @@ 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",
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,
@@ -144,31 +132,39 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
}
},
render_chart(frm) {
frm.cards_manager = new erpnext.accounts.bank_reconciliation.NumberCardManager({
$reconciliation_tool_cards: frm.get_field("reconciliation_tool_cards").$wrapper,
bank_statement_closing_balance: frm.doc.bank_statement_closing_balance,
cleared_balance: frm.cleared_balance,
currency: frm.doc.account_currency,
});
},
render_chart: frappe.utils.debounce((frm) => {
frm.cards_manager = new erpnext.accounts.bank_reconciliation.NumberCardManager(
{
$reconciliation_tool_cards: frm.get_field(
"reconciliation_tool_cards"
).$wrapper,
bank_statement_closing_balance:
frm.doc.bank_statement_closing_balance,
cleared_balance: frm.cleared_balance,
currency: frm.currency,
}
);
}, 500),
render(frm) {
if (frm.doc.bank_account) {
frm.bank_reconciliation_data_table_manager =
new erpnext.accounts.bank_reconciliation.DataTableManager({
frm.bank_reconciliation_data_table_manager = new erpnext.accounts.bank_reconciliation.DataTableManager(
{
company: frm.doc.company,
bank_account: frm.doc.bank_account,
$reconciliation_tool_dt: frm.get_field("reconciliation_tool_dt").$wrapper,
$no_bank_transactions: frm.get_field("no_bank_transactions").$wrapper,
$reconciliation_tool_dt: frm.get_field(
"reconciliation_tool_dt"
).$wrapper,
$no_bank_transactions: frm.get_field(
"no_bank_transactions"
).$wrapper,
bank_statement_from_date: frm.doc.bank_statement_from_date,
bank_statement_to_date: frm.doc.bank_statement_to_date,
filter_by_reference_date: frm.doc.filter_by_reference_date,
from_reference_date: frm.doc.from_reference_date,
to_reference_date: frm.doc.to_reference_date,
bank_statement_closing_balance: frm.doc.bank_statement_closing_balance,
bank_statement_closing_balance:
frm.doc.bank_statement_closing_balance,
cards_manager: frm.cards_manager,
});
}
);
}
},
});

View File

@@ -10,11 +10,7 @@
"column_break_1",
"bank_statement_from_date",
"bank_statement_to_date",
"from_reference_date",
"to_reference_date",
"filter_by_reference_date",
"column_break_2",
"account_currency",
"account_opening_balance",
"bank_statement_closing_balance",
"section_break_1",
@@ -40,13 +36,13 @@
"fieldtype": "Column Break"
},
{
"depends_on": "eval: doc.bank_account && !doc.filter_by_reference_date",
"depends_on": "eval: doc.bank_account",
"fieldname": "bank_statement_from_date",
"fieldtype": "Date",
"label": "From Date"
},
{
"depends_on": "eval: doc.bank_account && !doc.filter_by_reference_date",
"depends_on": "eval: doc.bank_statement_from_date",
"fieldname": "bank_statement_to_date",
"fieldtype": "Date",
"label": "To Date"
@@ -60,7 +56,7 @@
"fieldname": "account_opening_balance",
"fieldtype": "Currency",
"label": "Account Opening Balance",
"options": "account_currency",
"options": "Currency",
"read_only": 1
},
{
@@ -68,7 +64,7 @@
"fieldname": "bank_statement_closing_balance",
"fieldtype": "Currency",
"label": "Closing Balance",
"options": "account_currency"
"options": "Currency"
},
{
"fieldname": "section_break_1",
@@ -85,40 +81,14 @@
},
{
"fieldname": "no_bank_transactions",
"fieldtype": "HTML",
"options": "<div class=\"text-muted text-center\">No Matching Bank Transactions Found</div>"
},
{
"depends_on": "eval:doc.filter_by_reference_date",
"fieldname": "from_reference_date",
"fieldtype": "Date",
"label": "From Reference Date"
},
{
"depends_on": "eval:doc.filter_by_reference_date",
"fieldname": "to_reference_date",
"fieldtype": "Date",
"label": "To Reference Date"
},
{
"default": "0",
"fieldname": "filter_by_reference_date",
"fieldtype": "Check",
"label": "Filter by Reference Date"
},
{
"fieldname": "account_currency",
"fieldtype": "Link",
"hidden": 1,
"label": "Account Currency",
"options": "Currency"
"fieldtype": "HTML"
}
],
"hide_toolbar": 1,
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2023-03-07 11:02:24.535714",
"modified": "2021-04-21 11:13:49.831769",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Reconciliation Tool",
@@ -137,6 +107,5 @@
],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}
"sort_order": "DESC"
}

View File

@@ -8,17 +8,14 @@ import frappe
from frappe import _
from frappe.model.document import Document
from frappe.query_builder.custom import ConstantColumn
from frappe.utils import cint, flt
from frappe.utils import 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.doctype.bank_transaction.bank_transaction import get_paid_amount
from erpnext.accounts.report.bank_reconciliation_statement.bank_reconciliation_statement import (
get_amounts_not_reflected_in_system,
get_entries,
)
from erpnext.accounts.utils import get_balance_on
from erpnext.setup.utils import get_exchange_rate
class BankReconciliationTool(Document):
@@ -31,7 +28,7 @@ def get_bank_transactions(bank_account, from_date=None, to_date=None):
filters = []
filters.append(["bank_account", "=", bank_account])
filters.append(["docstatus", "=", 1])
filters.append(["unallocated_amount", ">", 0.0])
filters.append(["unallocated_amount", ">", 0])
if to_date:
filters.append(["date", "<=", to_date])
if from_date:
@@ -53,7 +50,6 @@ def get_bank_transactions(bank_account, from_date=None, to_date=None):
"party",
],
filters=filters,
order_by="date",
)
return transactions
@@ -61,13 +57,15 @@ def get_bank_transactions(bank_account, from_date=None, to_date=None):
@frappe.whitelist()
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})
account = frappe.get_cached_value("Bank Account", bank_account, "account")
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"])
total_debit, total_credit = 0.0, 0.0
total_debit, total_credit = 0, 0
for d in data:
total_debit += flt(d.debit)
total_credit += flt(d.credit)
@@ -75,7 +73,10 @@ def get_account_balance(bank_account, till_date):
amounts_not_reflected_in_system = get_amounts_not_reflected_in_system(filters)
bank_bal = (
flt(balance_as_per_system) - flt(total_debit) + flt(total_credit) + amounts_not_reflected_in_system
flt(balance_as_per_system)
- flt(total_debit)
+ flt(total_credit)
+ amounts_not_reflected_in_system
)
return bank_bal
@@ -126,11 +127,13 @@ def create_journal_entry_bts(
bank_transaction = frappe.db.get_values(
"Bank Transaction",
bank_transaction_name,
fieldname=["name", "deposit", "withdrawal", "bank_account", "currency"],
fieldname=["name", "deposit", "withdrawal", "bank_account"],
as_dict=True,
)[0]
company_account = frappe.get_value("Bank Account", bank_transaction.bank_account, "account")
account_type = frappe.db.get_value("Account", second_account, "account_type")
company_account = frappe.get_cached_value(
"Bank Account", bank_transaction.bank_account, "account"
)
account_type = frappe.get_cached_value("Account", second_account, "account_type")
if account_type in ["Receivable", "Payable"]:
if not (party_type and party):
frappe.throw(
@@ -138,96 +141,32 @@ def create_journal_entry_bts(
second_account
)
)
company = frappe.get_value("Account", company_account, "company")
company_default_currency = frappe.get_cached_value("Company", company, "default_currency")
company_account_currency = frappe.get_cached_value("Account", company_account, "account_currency")
second_account_currency = frappe.get_cached_value("Account", second_account, "account_currency")
# determine if multi-currency Journal or not
is_multi_currency = (
True
if company_default_currency != company_account_currency
or company_default_currency != second_account_currency
or company_default_currency != bank_transaction.currency
else False
accounts = []
# Multi Currency?
accounts.append(
{
"account": second_account,
"credit_in_account_currency": bank_transaction.deposit if bank_transaction.deposit > 0 else 0,
"debit_in_account_currency": bank_transaction.withdrawal
if bank_transaction.withdrawal > 0
else 0,
"party_type": party_type,
"party": party,
}
)
accounts = []
second_account_dict = {
"account": second_account,
"account_currency": second_account_currency,
"credit_in_account_currency": bank_transaction.deposit,
"debit_in_account_currency": bank_transaction.withdrawal,
"party_type": party_type,
"party": party,
"cost_center": get_default_cost_center(company),
}
accounts.append(
{
"account": company_account,
"bank_account": bank_transaction.bank_account,
"credit_in_account_currency": bank_transaction.withdrawal
if bank_transaction.withdrawal > 0
else 0,
"debit_in_account_currency": bank_transaction.deposit if bank_transaction.deposit > 0 else 0,
}
)
company_account_dict = {
"account": company_account,
"account_currency": company_account_currency,
"bank_account": bank_transaction.bank_account,
"credit_in_account_currency": bank_transaction.withdrawal,
"debit_in_account_currency": bank_transaction.deposit,
"cost_center": get_default_cost_center(company),
}
# convert transaction amount to company currency
if is_multi_currency:
exc_rate = get_exchange_rate(bank_transaction.currency, company_default_currency, posting_date)
withdrawal_in_company_currency = flt(exc_rate * abs(bank_transaction.withdrawal))
deposit_in_company_currency = flt(exc_rate * abs(bank_transaction.deposit))
else:
withdrawal_in_company_currency = bank_transaction.withdrawal
deposit_in_company_currency = bank_transaction.deposit
# if second account is of foreign currency, convert and set debit and credit fields.
if second_account_currency != company_default_currency:
exc_rate = get_exchange_rate(second_account_currency, company_default_currency, posting_date)
second_account_dict.update(
{
"exchange_rate": exc_rate,
"credit": deposit_in_company_currency,
"debit": withdrawal_in_company_currency,
"credit_in_account_currency": flt(deposit_in_company_currency / exc_rate) or 0,
"debit_in_account_currency": flt(withdrawal_in_company_currency / exc_rate) or 0,
}
)
else:
second_account_dict.update(
{
"exchange_rate": 1,
"credit": deposit_in_company_currency,
"debit": withdrawal_in_company_currency,
"credit_in_account_currency": deposit_in_company_currency,
"debit_in_account_currency": withdrawal_in_company_currency,
}
)
# if company account is of foreign currency, convert and set debit and credit fields.
if company_account_currency != company_default_currency:
exc_rate = get_exchange_rate(company_account_currency, company_default_currency, posting_date)
company_account_dict.update(
{
"exchange_rate": exc_rate,
"credit": withdrawal_in_company_currency,
"debit": deposit_in_company_currency,
}
)
else:
company_account_dict.update(
{
"exchange_rate": 1,
"credit": withdrawal_in_company_currency,
"debit": deposit_in_company_currency,
"credit_in_account_currency": withdrawal_in_company_currency,
"debit_in_account_currency": deposit_in_company_currency,
}
)
accounts.append(second_account_dict)
accounts.append(company_account_dict)
company = frappe.get_cached_value("Account", company_account, "company")
journal_entry_dict = {
"voucher_type": entry_type,
@@ -237,9 +176,6 @@ def create_journal_entry_bts(
"cheque_no": reference_number,
"mode_of_payment": mode_of_payment,
}
if is_multi_currency:
journal_entry_dict.update({"multi_currency": True})
journal_entry = frappe.new_doc("Journal Entry")
journal_entry.update(journal_entry_dict)
journal_entry.set("accounts", accounts)
@@ -250,22 +186,16 @@ def create_journal_entry_bts(
journal_entry.insert()
journal_entry.submit()
if bank_transaction.deposit > 0.0:
if bank_transaction.deposit > 0:
paid_amount = bank_transaction.deposit
else:
paid_amount = bank_transaction.withdrawal
vouchers = json.dumps(
[
{
"payment_doctype": "Journal Entry",
"payment_name": journal_entry.name,
"amount": paid_amount,
}
]
[{"payment_doctype": "Journal Entry", "payment_name": journal_entry.name, "amount": paid_amount}]
)
return reconcile_vouchers(bank_transaction_name, vouchers)
return reconcile_vouchers(bank_transaction.name, vouchers)
@frappe.whitelist()
@@ -285,135 +215,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 else "Pay"
payment_type = "Receive" if bank_transaction.deposit > 0.0 else "Pay"
company_account = frappe.get_cached_value(
"Bank Account", bank_transaction.bank_account, "account"
)
company = frappe.get_cached_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_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)
payment_entry.update(payment_entry_dict)
bank_currency = bank_transaction.currency
party_currency = frappe.get_cached_value("Account", party_account, "account_currency")
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
exc_rate = get_exchange_rate(bank_currency, party_currency, posting_date)
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_doctype": "Payment Entry", "payment_name": payment_entry.name, "amount": paid_amount}]
)
return reconcile_vouchers(bank_transaction_name, vouchers)
@frappe.whitelist()
def auto_reconcile_vouchers(
bank_account,
from_date=None,
to_date=None,
filter_by_reference_date=None,
from_reference_date=None,
to_reference_date=None,
):
frappe.flags.auto_reconcile_vouchers = True
document_types = ["payment_entry", "journal_entry"]
bank_transactions = get_bank_transactions(bank_account)
matched_transaction = []
for transaction in bank_transactions:
linked_payments = get_linked_payments(
transaction.name,
document_types,
from_date,
to_date,
filter_by_reference_date,
from_reference_date,
to_reference_date,
)
vouchers = []
for r in linked_payments:
vouchers.append(
{
"payment_doctype": r[1],
"payment_name": r[2],
"amount": r[4],
}
)
transaction = frappe.get_doc("Bank Transaction", transaction.name)
account = frappe.db.get_value("Bank Account", transaction.bank_account, "account")
for voucher in vouchers:
gl_entry = frappe.db.get_value(
"GL Entry",
dict(
account=account,
voucher_type=voucher["payment_doctype"],
voucher_no=voucher["payment_name"],
),
["credit", "debit"],
as_dict=1,
)
gl_amount, transaction_amount = (
(gl_entry.credit, transaction.deposit)
if gl_entry.credit > 0
else (gl_entry.debit, transaction.withdrawal)
)
allocated_amount = gl_amount if gl_amount >= transaction_amount else transaction_amount
transaction.append(
"payment_entries",
{
"payment_document": voucher["payment_doctype"],
"payment_entry": voucher["payment_name"],
"allocated_amount": allocated_amount,
},
)
matched_transaction.append(str(transaction.name))
transaction.save()
transaction.update_allocations()
matched_transaction_len = len(set(matched_transaction))
if matched_transaction_len == 0:
frappe.msgprint(_("No matching references found for auto reconciliation"))
elif matched_transaction_len == 1:
frappe.msgprint(_("{0} transaction is reconcilied").format(matched_transaction_len))
else:
frappe.msgprint(_("{0} transactions are reconcilied").format(matched_transaction_len))
frappe.flags.auto_reconcile_vouchers = False
return frappe.get_doc("Bank Transaction", transaction.name)
return reconcile_vouchers(bank_transaction.name, vouchers)
@frappe.whitelist()
@@ -421,92 +270,80 @@ def reconcile_vouchers(bank_transaction_name, vouchers):
# updated clear date of all the vouchers based on the bank transaction
vouchers = json.loads(vouchers)
transaction = frappe.get_doc("Bank Transaction", bank_transaction_name)
transaction.add_payment_entries(vouchers)
company_account = frappe.get_cached_value("Bank Account", transaction.bank_account, "account")
if transaction.unallocated_amount == 0:
frappe.throw(_("This bank transaction is already fully reconciled"))
total_amount = 0
for voucher in vouchers:
voucher["payment_entry"] = frappe.get_doc(voucher["payment_doctype"], voucher["payment_name"])
total_amount += get_paid_amount(
frappe._dict(
{
"payment_document": voucher["payment_doctype"],
"payment_entry": voucher["payment_name"],
}
),
transaction.currency,
company_account,
)
if total_amount > transaction.unallocated_amount:
frappe.throw(
_(
"The sum total of amounts of all selected vouchers should be less than the unallocated amount of the bank transaction"
)
)
account = frappe.get_cached_value("Bank Account", transaction.bank_account, "account")
for voucher in vouchers:
gl_entry = frappe.db.get_value(
"GL Entry",
dict(
account=account, voucher_type=voucher["payment_doctype"], voucher_no=voucher["payment_name"]
),
["credit", "debit"],
as_dict=1,
)
gl_amount, transaction_amount = (
(gl_entry.credit, transaction.deposit)
if gl_entry.credit > 0
else (gl_entry.debit, transaction.withdrawal)
)
allocated_amount = gl_amount if gl_amount >= transaction_amount else transaction_amount
transaction.append(
"payment_entries",
{
"payment_document": voucher["payment_entry"].doctype,
"payment_entry": voucher["payment_entry"].name,
"allocated_amount": allocated_amount,
},
)
transaction.save()
transaction.update_allocations()
return frappe.get_doc("Bank Transaction", bank_transaction_name)
@frappe.whitelist()
def get_linked_payments(
bank_transaction_name,
document_types=None,
from_date=None,
to_date=None,
filter_by_reference_date=None,
from_reference_date=None,
to_reference_date=None,
):
def get_linked_payments(bank_transaction_name, document_types=None):
# get all matching payments for a bank transaction
transaction = frappe.get_doc("Bank Transaction", bank_transaction_name)
bank_account = frappe.db.get_values(
"Bank Account", transaction.bank_account, ["account", "company"], as_dict=True
)[0]
(gl_account, company) = (bank_account.account, bank_account.company)
matching = check_matching(
gl_account,
company,
transaction,
document_types,
from_date,
to_date,
filter_by_reference_date,
from_reference_date,
to_reference_date,
)
return subtract_allocations(gl_account, matching)
(account, company) = (bank_account.account, bank_account.company)
matching = check_matching(account, company, transaction, document_types)
return matching
def subtract_allocations(gl_account, vouchers):
"Look up & subtract any existing Bank Transaction allocations"
copied = []
voucher_docs = [(voucher[1], voucher[2]) for voucher in vouchers]
voucher_allocated_amounts = get_total_allocated_amount(voucher_docs)
for voucher in vouchers:
rows = voucher_allocated_amounts.get((voucher[1], voucher[2])) or []
amount = None
for row in rows:
if row["gl_account"] == gl_account:
amount = row["total"]
break
if amount:
l = list(voucher)
l[3] -= amount
copied.append(tuple(l))
else:
copied.append(voucher)
return copied
def check_matching(
bank_account,
company,
transaction,
document_types,
from_date,
to_date,
filter_by_reference_date,
from_reference_date,
to_reference_date,
):
exact_match = True if "exact_match" in document_types else False
def check_matching(bank_account, company, transaction, document_types):
# combine all types of vouchers
subquery = get_queries(
bank_account,
company,
transaction,
document_types,
from_date,
to_date,
filter_by_reference_date,
from_reference_date,
to_reference_date,
exact_match,
)
subquery = get_queries(bank_account, company, transaction, document_types)
filters = {
"amount": transaction.unallocated_amount,
"payment_type": "Receive" if transaction.deposit > 0.0 else "Pay",
"payment_type": "Receive" if transaction.deposit > 0 else "Pay",
"reference_no": transaction.reference_number,
"party_type": transaction.party_type,
"party": transaction.party,
@@ -515,9 +352,7 @@ def check_matching(
matching_vouchers = []
matching_vouchers.extend(
get_loan_vouchers(bank_account, transaction, document_types, filters, exact_match)
)
matching_vouchers.extend(get_loan_vouchers(bank_account, transaction, document_types, filters))
for query in subquery:
matching_vouchers.extend(
@@ -526,23 +361,14 @@ def check_matching(
filters,
)
)
return sorted(matching_vouchers, key=lambda x: x[0], reverse=True) if matching_vouchers else []
def get_queries(
bank_account,
company,
transaction,
document_types,
from_date,
to_date,
filter_by_reference_date,
from_reference_date,
to_reference_date,
exact_match,
):
def get_queries(bank_account, company, transaction, document_types):
# get queries to get matching vouchers
account_from_to = "paid_to" if transaction.deposit > 0.0 else "paid_from"
amount_condition = "=" if "exact_match" in document_types else "<="
account_from_to = "paid_to" if transaction.deposit > 0 else "paid_from"
queries = []
# get matching queries from all the apps
@@ -553,13 +379,8 @@ def get_queries(
company,
transaction,
document_types,
exact_match,
amount_condition,
account_from_to,
from_date,
to_date,
filter_by_reference_date,
from_reference_date,
to_reference_date,
)
or []
)
@@ -568,106 +389,43 @@ def get_queries(
def get_matching_queries(
bank_account,
company,
transaction,
document_types,
exact_match,
account_from_to,
from_date,
to_date,
filter_by_reference_date,
from_reference_date,
to_reference_date,
bank_account, company, transaction, document_types, amount_condition, account_from_to
):
queries = []
if "payment_entry" in document_types:
query = get_pe_matching_query(
exact_match,
account_from_to,
transaction,
from_date,
to_date,
filter_by_reference_date,
from_reference_date,
to_reference_date,
)
queries.append(query)
pe_amount_matching = get_pe_matching_query(amount_condition, account_from_to, transaction)
queries.extend([pe_amount_matching])
if "journal_entry" in document_types:
query = get_je_matching_query(
exact_match,
transaction,
from_date,
to_date,
filter_by_reference_date,
from_reference_date,
to_reference_date,
)
queries.append(query)
je_amount_matching = get_je_matching_query(amount_condition, transaction)
queries.extend([je_amount_matching])
if transaction.deposit > 0.0 and "sales_invoice" in document_types:
query = get_si_matching_query(exact_match)
queries.append(query)
if transaction.deposit > 0 and "sales_invoice" in document_types:
si_amount_matching = get_si_matching_query(amount_condition)
queries.extend([si_amount_matching])
if transaction.withdrawal > 0.0:
if transaction.withdrawal > 0:
if "purchase_invoice" in document_types:
query = get_pi_matching_query(exact_match)
queries.append(query)
if "bank_transaction" in document_types:
query = get_bt_matching_query(exact_match, transaction)
queries.append(query)
pi_amount_matching = get_pi_matching_query(amount_condition)
queries.extend([pi_amount_matching])
return queries
def get_loan_vouchers(bank_account, transaction, document_types, filters, exact_match):
def get_loan_vouchers(bank_account, transaction, document_types, filters):
vouchers = []
amount_condition = True if "exact_match" in document_types else False
if transaction.withdrawal > 0.0 and "loan_disbursement" in document_types:
vouchers.extend(get_ld_matching_query(bank_account, exact_match, filters))
if transaction.withdrawal > 0 and "loan_disbursement" in document_types:
vouchers.extend(get_ld_matching_query(bank_account, amount_condition, filters))
if transaction.deposit > 0.0 and "loan_repayment" in document_types:
vouchers.extend(get_lr_matching_query(bank_account, exact_match, filters))
if transaction.deposit > 0 and "loan_repayment" in document_types:
vouchers.extend(get_lr_matching_query(bank_account, amount_condition, filters))
return vouchers
def get_bt_matching_query(exact_match, transaction):
# get matching bank transaction query
# find bank transactions in the same bank account with opposite sign
# same bank account must have same company and currency
field = "deposit" if transaction.withdrawal > 0.0 else "withdrawal"
return f"""
SELECT
(CASE WHEN reference_number = %(reference_no)s THEN 1 ELSE 0 END
+ CASE WHEN {field} = %(amount)s THEN 1 ELSE 0 END
+ CASE WHEN ( party_type = %(party_type)s AND party = %(party)s ) THEN 1 ELSE 0 END
+ CASE WHEN unallocated_amount = %(amount)s THEN 1 ELSE 0 END
+ 1) AS rank,
'Bank Transaction' AS doctype,
name,
unallocated_amount AS paid_amount,
reference_number AS reference_no,
date AS reference_date,
party,
party_type,
date AS posting_date,
currency
FROM
`tabBank Transaction`
WHERE
status != 'Reconciled'
AND name != '{transaction.name}'
AND bank_account = '{transaction.bank_account}'
AND {field} {'= %(amount)s' if exact_match else '> 0.0'}
"""
def get_ld_matching_query(bank_account, exact_match, filters):
def get_ld_matching_query(bank_account, amount_condition, filters):
loan_disbursement = frappe.qb.DocType("Loan Disbursement")
matching_reference = loan_disbursement.reference_number == filters.get("reference_number")
matching_party = loan_disbursement.applicant_type == filters.get(
@@ -695,17 +453,17 @@ def get_ld_matching_query(bank_account, exact_match, filters):
.where(loan_disbursement.disbursement_account == bank_account)
)
if exact_match:
if amount_condition:
query.where(loan_disbursement.disbursed_amount == filters.get("amount"))
else:
query.where(loan_disbursement.disbursed_amount > 0.0)
query.where(loan_disbursement.disbursed_amount <= filters.get("amount"))
vouchers = query.run(as_list=True)
return vouchers
def get_lr_matching_query(bank_account, exact_match, filters):
def get_lr_matching_query(bank_account, amount_condition, filters):
loan_repayment = frappe.qb.DocType("Loan Repayment")
matching_reference = loan_repayment.reference_number == filters.get("reference_number")
matching_party = loan_repayment.applicant_type == filters.get(
@@ -734,131 +492,90 @@ def get_lr_matching_query(bank_account, exact_match, filters):
)
if frappe.db.has_column("Loan Repayment", "repay_from_salary"):
query = query.where(loan_repayment.repay_from_salary == 0)
query = query.where((loan_repayment.repay_from_salary == 0))
if exact_match:
if amount_condition:
query.where(loan_repayment.amount_paid == filters.get("amount"))
else:
query.where(loan_repayment.amount_paid > 0.0)
query.where(loan_repayment.amount_paid <= filters.get("amount"))
vouchers = query.run()
return vouchers
def get_pe_matching_query(
exact_match,
account_from_to,
transaction,
from_date,
to_date,
filter_by_reference_date,
from_reference_date,
to_reference_date,
):
def get_pe_matching_query(amount_condition, account_from_to, transaction):
# get matching payment entries query
if transaction.deposit > 0.0:
if transaction.deposit > 0:
currency_field = "paid_to_account_currency as currency"
else:
currency_field = "paid_from_account_currency as currency"
filter_by_date = f"AND posting_date between '{from_date}' and '{to_date}'"
order_by = " posting_date"
filter_by_reference_no = ""
if cint(filter_by_reference_date):
filter_by_date = f"AND reference_date between '{from_reference_date}' and '{to_reference_date}'"
order_by = " reference_date"
if frappe.flags.auto_reconcile_vouchers is True:
filter_by_reference_no = f"AND reference_no = '{transaction.reference_number}'"
return f"""
SELECT
(CASE WHEN reference_no=%(reference_no)s THEN 1 ELSE 0 END
+ CASE WHEN (party_type = %(party_type)s AND party = %(party)s ) THEN 1 ELSE 0 END
+ CASE WHEN paid_amount = %(amount)s THEN 1 ELSE 0 END
+ 1 ) AS rank,
'Payment Entry' as doctype,
name,
paid_amount,
reference_no,
reference_date,
party,
party_type,
posting_date,
{currency_field}
FROM
`tabPayment Entry`
WHERE
docstatus = 1
AND payment_type IN (%(payment_type)s, 'Internal Transfer')
AND ifnull(clearance_date, '') = ""
AND {account_from_to} = %(bank_account)s
AND paid_amount {'= %(amount)s' if exact_match else '> 0.0'}
{filter_by_date}
{filter_by_reference_no}
order by{order_by}
SELECT
(CASE WHEN reference_no=%(reference_no)s THEN 1 ELSE 0 END
+ CASE WHEN (party_type = %(party_type)s AND party = %(party)s ) THEN 1 ELSE 0 END
+ 1 ) AS rank,
'Payment Entry' as doctype,
name,
paid_amount,
reference_no,
reference_date,
party,
party_type,
posting_date,
{currency_field}
FROM
`tabPayment Entry`
WHERE
paid_amount {amount_condition} %(amount)s
AND docstatus = 1
AND payment_type IN (%(payment_type)s, 'Internal Transfer')
AND ifnull(clearance_date, '') = ""
AND {account_from_to} = %(bank_account)s
"""
def get_je_matching_query(
exact_match,
transaction,
from_date,
to_date,
filter_by_reference_date,
from_reference_date,
to_reference_date,
):
def get_je_matching_query(amount_condition, transaction):
# get matching journal entry query
# We have mapping at the bank level
# So one bank could have both types of bank accounts like asset and liability
# So cr_or_dr should be judged only on basis of withdrawal and deposit and not account type
cr_or_dr = "credit" if transaction.withdrawal > 0.0 else "debit"
filter_by_date = f"AND je.posting_date between '{from_date}' and '{to_date}'"
order_by = " je.posting_date"
filter_by_reference_no = ""
if cint(filter_by_reference_date):
filter_by_date = f"AND je.cheque_date between '{from_reference_date}' and '{to_reference_date}'"
order_by = " je.cheque_date"
if frappe.flags.auto_reconcile_vouchers is True:
filter_by_reference_no = f"AND je.cheque_no = '{transaction.reference_number}'"
cr_or_dr = "credit" if transaction.withdrawal > 0 else "debit"
return f"""
SELECT
(CASE WHEN je.cheque_no=%(reference_no)s THEN 1 ELSE 0 END
+ CASE WHEN jea.{cr_or_dr}_in_account_currency = %(amount)s THEN 1 ELSE 0 END
+ 1) AS rank ,
'Journal Entry' AS doctype,
'Journal Entry' as doctype,
je.name,
jea.{cr_or_dr}_in_account_currency AS paid_amount,
je.cheque_no AS reference_no,
je.cheque_date AS reference_date,
je.pay_to_recd_from AS party,
jea.{cr_or_dr}_in_account_currency as paid_amount,
je.cheque_no as reference_no,
je.cheque_date as reference_date,
je.pay_to_recd_from as party,
jea.party_type,
je.posting_date,
jea.account_currency AS currency
jea.account_currency as currency
FROM
`tabJournal Entry Account` AS jea
`tabJournal Entry Account` as jea
JOIN
`tabJournal Entry` AS je
`tabJournal Entry` as je
ON
jea.parent = je.name
WHERE
je.docstatus = 1
AND je.voucher_type NOT IN ('Opening Entry')
AND (je.clearance_date IS NULL OR je.clearance_date='0000-00-00')
(je.clearance_date is null or je.clearance_date='0000-00-00')
AND jea.account = %(bank_account)s
AND jea.{cr_or_dr}_in_account_currency {'= %(amount)s' if exact_match else '> 0.0'}
AND jea.{cr_or_dr}_in_account_currency {amount_condition} %(amount)s
AND je.docstatus = 1
{filter_by_date}
{filter_by_reference_no}
order by {order_by}
"""
def get_si_matching_query(exact_match):
# get matching sales invoice query
def get_si_matching_query(amount_condition):
# get matchin sales invoice query
return f"""
SELECT
( CASE WHEN si.customer = %(party)s THEN 1 ELSE 0 END
+ CASE WHEN sip.amount = %(amount)s THEN 1 ELSE 0 END
( CASE WHEN si.customer = %(party)s THEN 1 ELSE 0 END
+ 1 ) AS rank,
'Sales Invoice' as doctype,
si.name,
@@ -876,20 +593,18 @@ def get_si_matching_query(exact_match):
`tabSales Invoice` as si
ON
sip.parent = si.name
WHERE
si.docstatus = 1
AND (sip.clearance_date is null or sip.clearance_date='0000-00-00')
WHERE (sip.clearance_date is null or sip.clearance_date='0000-00-00')
AND sip.account = %(bank_account)s
AND sip.amount {'= %(amount)s' if exact_match else '> 0.0'}
AND sip.amount {amount_condition} %(amount)s
AND si.docstatus = 1
"""
def get_pi_matching_query(exact_match):
# get matching purchase invoice query when they are also used as payment entries (is_paid)
def get_pi_matching_query(amount_condition):
# get matching purchase invoice query
return f"""
SELECT
( CASE WHEN supplier = %(party)s THEN 1 ELSE 0 END
+ CASE WHEN paid_amount = %(amount)s THEN 1 ELSE 0 END
+ 1 ) AS rank,
'Purchase Invoice' as doctype,
name,
@@ -903,9 +618,9 @@ def get_pi_matching_query(exact_match):
FROM
`tabPurchase Invoice`
WHERE
docstatus = 1
paid_amount {amount_condition} %(amount)s
AND docstatus = 1
AND is_paid = 1
AND ifnull(clearance_date, '') = ""
AND cash_bank_account = %(bank_account)s
AND paid_amount {'= %(amount)s' if exact_match else '> 0.0'}
AND cash_bank_account = %(bank_account)s
"""

View File

@@ -2,24 +2,16 @@
// For license information, please see license.txt
frappe.ui.form.on("Bank Statement Import", {
onload(frm) {
frm.set_query("bank_account", function (doc) {
return {
filters: {
company: doc.company,
},
};
});
},
setup(frm) {
frappe.realtime.on("data_import_refresh", ({ data_import }) => {
frm.import_in_progress = false;
if (data_import !== frm.doc.name) return;
frappe.model.clear_doc("Bank Statement Import", frm.doc.name);
frappe.model.with_doc("Bank Statement Import", frm.doc.name).then(() => {
frm.refresh();
});
frappe.model
.with_doc("Bank Statement Import", frm.doc.name)
.then(() => {
frm.refresh();
});
});
frappe.realtime.on("data_import_progress", (data) => {
frm.import_in_progress = true;
@@ -46,9 +38,20 @@ frappe.ui.form.on("Bank Statement Import", {
: __("Updating {0} of {1}, {2}", message_args);
}
if (data.skipping) {
message = __("Skipping {0} of {1}, {2}", [data.current, data.total, eta_message]);
message = __(
"Skipping {0} of {1}, {2}",
[
data.current,
data.total,
eta_message,
]
);
}
frm.dashboard.show_progress(__("Import Progress"), percent, message);
frm.dashboard.show_progress(
__("Import Progress"),
percent,
message
);
frm.page.set_indicator(__("In Progress"), "orange");
// hide progress when complete
@@ -90,12 +93,15 @@ frappe.ui.form.on("Bank Statement Import", {
frm.trigger("show_report_error_button");
if (frm.doc.status === "Partial Success") {
frm.add_custom_button(__("Export Errored Rows"), () => frm.trigger("export_errored_rows"));
frm.add_custom_button(__("Export Errored Rows"), () =>
frm.trigger("export_errored_rows")
);
}
if (frm.doc.status.includes("Success")) {
frm.add_custom_button(__("Go to {0} List", [__(frm.doc.reference_doctype)]), () =>
frappe.set_route("List", frm.doc.reference_doctype)
frm.add_custom_button(
__("Go to {0} List", [__(frm.doc.reference_doctype)]),
() => frappe.set_route("List", frm.doc.reference_doctype)
);
}
},
@@ -112,8 +118,13 @@ frappe.ui.form.on("Bank Statement Import", {
frm.disable_save();
if (frm.doc.status !== "Success") {
if (!frm.is_new() && frm.has_import_file()) {
let label = frm.doc.status === "Pending" ? __("Start Import") : __("Retry");
frm.page.set_primary_action(label, () => frm.events.start_import(frm));
let label =
frm.doc.status === "Pending"
? __("Start Import")
: __("Retry");
frm.page.set_primary_action(label, () =>
frm.events.start_import(frm)
);
} else {
frm.page.set_primary_action(__("Save"), () => frm.save());
}
@@ -155,24 +166,24 @@ frappe.ui.form.on("Bank Statement Import", {
message =
successful_records.length > 1
? __(
"Successfully imported {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
)
"Successfully imported {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
)
: __(
"Successfully imported {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
);
"Successfully imported {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
);
} else {
message =
successful_records.length > 1
? __(
"Successfully updated {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
)
"Successfully updated {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
)
: __(
"Successfully updated {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
);
"Successfully updated {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.",
message_args
);
}
}
frm.dashboard.set_headline(message);
@@ -215,7 +226,8 @@ frappe.ui.form.on("Bank Statement Import", {
},
download_template() {
let method = "/api/method/frappe.core.doctype.data_import.data_import.download_template";
let method =
"/api/method/frappe.core.doctype.data_import.data_import.download_template";
open_url_post(method, {
doctype: "Bank Transaction",
@@ -228,7 +240,7 @@ frappe.ui.form.on("Bank Statement Import", {
"description",
"reference_number",
"bank_account",
"currency",
"currency"
],
},
});
@@ -299,7 +311,10 @@ frappe.ui.form.on("Bank Statement Import", {
show_import_preview(frm, preview_data) {
let import_log = JSON.parse(frm.doc.statement_import_log || "[]");
if (frm.import_preview && frm.import_preview.doctype === frm.doc.reference_doctype) {
if (
frm.import_preview &&
frm.import_preview.doctype === frm.doc.reference_doctype
) {
frm.import_preview.preview_data = preview_data;
frm.import_preview.import_log = import_log;
frm.import_preview.refresh();
@@ -315,10 +330,19 @@ frappe.ui.form.on("Bank Statement Import", {
frm,
events: {
remap_column(changed_map) {
let template_options = JSON.parse(frm.doc.template_options || "{}");
template_options.column_to_field_map = template_options.column_to_field_map || {};
Object.assign(template_options.column_to_field_map, changed_map);
frm.set_value("template_options", JSON.stringify(template_options));
let template_options = JSON.parse(
frm.doc.template_options || "{}"
);
template_options.column_to_field_map =
template_options.column_to_field_map || {};
Object.assign(
template_options.column_to_field_map,
changed_map
);
frm.set_value(
"template_options",
JSON.stringify(template_options)
);
frm.save().then(() => frm.trigger("import_file"));
},
},
@@ -328,11 +352,10 @@ frappe.ui.form.on("Bank Statement Import", {
export_errored_rows(frm) {
open_url_post(
"/api/method/erpnext.accounts.doctype.bank_statement_import.bank_statement_import.download_errored_template",
"/api/method/frappe.core.doctype.data_import.data_import.download_errored_template",
{
data_import_name: frm.doc.name,
},
true
}
);
},
@@ -352,7 +375,8 @@ frappe.ui.form.on("Bank Statement Import", {
let other_warnings = [];
for (let warning of warnings) {
if (warning.row) {
warnings_by_row[warning.row] = warnings_by_row[warning.row] || [];
warnings_by_row[warning.row] =
warnings_by_row[warning.row] || [];
warnings_by_row[warning.row].push(warning);
} else {
other_warnings.push(warning);
@@ -367,7 +391,9 @@ frappe.ui.form.on("Bank Statement Import", {
if (w.field) {
let label =
w.field.label +
(w.field.parent !== frm.doc.reference_doctype ? ` (${w.field.parent})` : "");
(w.field.parent !== frm.doc.reference_doctype
? ` (${w.field.parent})`
: "");
return `<li>${label}: ${w.message}</li>`;
}
return `<li>${w.message}</li>`;
@@ -386,9 +412,10 @@ frappe.ui.form.on("Bank Statement Import", {
.map((warning) => {
let header = "";
if (warning.col) {
let column_number = `<span class="text-uppercase">${__("Column {0}", [
warning.col,
])}</span>`;
let column_number = `<span class="text-uppercase">${__(
"Column {0}",
[warning.col]
)}</span>`;
let column_header = columns[warning.col].header_title;
header = `${column_number} (${column_header})`;
}
@@ -427,28 +454,36 @@ frappe.ui.form.on("Bank Statement Import", {
let html = "";
if (log.success) {
if (frm.doc.import_type === "Insert New Records") {
html = __("Successfully imported {0}", [
`<span class="underline">${frappe.utils.get_form_link(
frm.doc.reference_doctype,
log.docname,
true
)}<span>`,
]);
html = __(
"Successfully imported {0}", [
`<span class="underline">${frappe.utils.get_form_link(
frm.doc.reference_doctype,
log.docname,
true
)}<span>`,
]
);
} else {
html = __("Successfully updated {0}", [
`<span class="underline">${frappe.utils.get_form_link(
frm.doc.reference_doctype,
log.docname,
true
)}<span>`,
]);
html = __(
"Successfully updated {0}", [
`<span class="underline">${frappe.utils.get_form_link(
frm.doc.reference_doctype,
log.docname,
true
)}<span>`,
]
);
}
} else {
let messages = log.messages
.map(JSON.parse)
.map((m) => {
let title = m.title ? `<strong>${m.title}</strong>` : "";
let message = m.message ? `<div>${m.message}</div>` : "";
let title = m.title
? `<strong>${m.title}</strong>`
: "";
let message = m.message
? `<div>${m.message}</div>`
: "";
return title + message;
})
.join("");

View File

@@ -21,7 +21,7 @@ INVALID_VALUES = ("", None)
class BankStatementImport(DataImport):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
super(BankStatementImport, self).__init__(*args, **kwargs)
def validate(self):
doc_before_save = self.get_doc_before_save()
@@ -30,6 +30,7 @@ class BankStatementImport(DataImport):
or (doc_before_save and doc_before_save.import_file != self.import_file)
or (doc_before_save and doc_before_save.google_sheets_url != self.google_sheets_url)
):
template_options_dict = {}
column_to_field_map = {}
bank = frappe.get_doc("Bank", self.bank)
@@ -44,6 +45,7 @@ class BankStatementImport(DataImport):
self.validate_google_sheets_url()
def start_import(self):
preview = frappe.get_doc("Bank Statement Import", self.name).get_preview_from_template(
self.import_file, self.google_sheets_url
)
@@ -51,15 +53,13 @@ class BankStatementImport(DataImport):
if "Bank Account" not in json.dumps(preview["columns"]):
frappe.throw(_("Please add the Bank Account column"))
from frappe.core.page.background_jobs.background_jobs import get_info
from frappe.utils.background_jobs import is_job_queued
from frappe.utils.scheduler import is_scheduler_inactive
if is_scheduler_inactive() and not frappe.flags.in_test:
frappe.throw(_("Scheduler is inactive. Cannot import data."), title=_("Scheduler Inactive"))
enqueued_jobs = [d.get("job_name") for d in get_info()]
if self.name not in enqueued_jobs:
if not is_job_queued(self.name):
enqueue(
start_import,
queue="default",
@@ -100,7 +100,7 @@ def download_errored_template(data_import_name):
def parse_data_from_template(raw_data):
data = []
for _i, row in enumerate(raw_data):
for i, row in enumerate(raw_data):
if all(v in INVALID_VALUES for v in row):
# empty row
continue
@@ -110,7 +110,9 @@ def parse_data_from_template(raw_data):
return data
def start_import(data_import, bank_account, import_file_path, google_sheets_url, bank, template_options):
def start_import(
data_import, bank_account, import_file_path, google_sheets_url, bank, template_options
):
"""This method runs in background job"""
update_mapping_db(bank, template_options)

View File

@@ -1,34 +1,36 @@
let imports_in_progress = [];
frappe.listview_settings["Bank Statement Import"] = {
frappe.listview_settings['Bank Statement Import'] = {
onload(listview) {
frappe.realtime.on("data_import_progress", (data) => {
frappe.realtime.on('data_import_progress', data => {
if (!imports_in_progress.includes(data.data_import)) {
imports_in_progress.push(data.data_import);
}
});
frappe.realtime.on("data_import_refresh", (data) => {
imports_in_progress = imports_in_progress.filter((d) => d !== data.data_import);
frappe.realtime.on('data_import_refresh', data => {
imports_in_progress = imports_in_progress.filter(
d => d !== data.data_import
);
listview.refresh();
});
},
get_indicator: function (doc) {
get_indicator: function(doc) {
var colors = {
Pending: "orange",
"Not Started": "orange",
"Partial Success": "orange",
Success: "green",
"In Progress": "orange",
Error: "red",
'Pending': 'orange',
'Not Started': 'orange',
'Partial Success': 'orange',
'Success': 'green',
'In Progress': 'orange',
'Error': 'red'
};
let status = doc.status;
if (imports_in_progress.includes(doc.name)) {
status = "In Progress";
status = 'In Progress';
}
if (status == "Pending") {
status = "Not Started";
if (status == 'Pending') {
status = 'Not Started';
}
return [__(status), colors[status], "status,=," + doc.status];
return [__(status), colors[status], 'status,=,' + doc.status];
},
hide_name_column: true,
hide_name_column: true
};

View File

@@ -1,173 +0,0 @@
import frappe
from frappe.utils import flt
from rapidfuzz import fuzz, process
class AutoMatchParty:
"""
Matches by Account/IBAN and then by Party Name/Description sequentially.
Returns when a result is obtained.
Result (if present) is of the form: (Party Type, Party,)
"""
def __init__(self, **kwargs) -> None:
self.__dict__.update(kwargs)
def get(self, key):
return self.__dict__.get(key, None)
def match(self) -> tuple | None:
result = None
result = AutoMatchbyAccountIBAN(
bank_party_account_number=self.bank_party_account_number,
bank_party_iban=self.bank_party_iban,
deposit=self.deposit,
).match()
fuzzy_matching_enabled = frappe.db.get_single_value("Accounts Settings", "enable_fuzzy_matching")
if not result and fuzzy_matching_enabled:
result = AutoMatchbyPartyNameDescription(
bank_party_name=self.bank_party_name, description=self.description, deposit=self.deposit
).match()
return result
class AutoMatchbyAccountIBAN:
def __init__(self, **kwargs) -> None:
self.__dict__.update(kwargs)
def get(self, key):
return self.__dict__.get(key, None)
def match(self):
if not (self.bank_party_account_number or self.bank_party_iban):
return None
return self.match_account_in_party()
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
# 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"])
# 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])
def get_or_filters(self, party: str | None = None) -> dict:
"""Return OR filters for Bank Account and IBAN"""
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
if self.bank_party_iban:
or_filters["iban"] = self.bank_party_iban
return or_filters
class AutoMatchbyPartyNameDescription:
def __init__(self, **kwargs) -> None:
self.__dict__.update(kwargs)
def get(self, key):
return self.__dict__.get(key, None)
def match(self) -> tuple | None:
# fuzzy search by customer/supplier & employee
if not (self.bank_party_name or self.description):
return None
return self.match_party_name_desc_in_party()
def match_party_name_desc_in_party(self) -> tuple | None:
"""Fuzzy search party name and/or description against parties in the system"""
result = None
parties = get_parties_in_order(self.deposit)
for party in parties:
filters = {"status": "Active"} if party == "Employee" else {"disabled": 0}
field = f"{party.lower()}_name"
names = frappe.get_all(party, filters=filters, fields=[f"{field} as party_name", "name"])
for field in ["bank_party_name", "description"]:
if not self.get(field):
continue
result, skip = self.fuzzy_search_and_return_result(party, names, field)
if result or skip:
break
if result or skip:
# Skip If: It was hard to distinguish between close matches and so match is None
# OR if the right match was found
break
return result
def fuzzy_search_and_return_result(self, party, names, field) -> tuple | None:
skip = False
result = process.extract(
query=self.get(field),
choices={row.get("name"): row.get("party_name") for row in names},
scorer=fuzz.token_set_ratio,
)
party_name, skip = self.process_fuzzy_result(result)
return ((party, party_name), skip) if party_name else (None, skip)
def process_fuzzy_result(self, result: list | None):
"""
If there are multiple valid close matches return None as result may be faulty.
Return the result only if one accurate match stands out.
Returns: Result, Skip (whether or not to discontinue matching)
"""
SCORE, PARTY_ID, CUTOFF = 1, 2, 80
if not result or not len(result):
return None, False
first_result = result[0]
if len(result) == 1:
return (first_result[PARTY_ID] if first_result[SCORE] > CUTOFF else None), True
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
return first_result[PARTY_ID], True
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
)

View File

@@ -3,7 +3,7 @@
frappe.ui.form.on("Bank Transaction", {
onload(frm) {
frm.set_query("payment_document", "payment_entries", function () {
frm.set_query("payment_document", "payment_entries", function() {
const payment_doctypes = frm.events.get_payment_doctypes(frm);
return {
filters: {
@@ -12,18 +12,12 @@ frappe.ui.form.on("Bank Transaction", {
};
});
},
refresh(frm) {
if (!frm.is_dirty() && frm.doc.payment_entries.length > 0) {
frm.add_custom_button(__("Unreconcile Transaction"), () => {
frm.call("remove_payment_entries").then(() => frm.refresh());
});
}
},
bank_account: function (frm) {
bank_account: function(frm) {
set_bank_statement_filter(frm);
},
setup: function (frm) {
setup: function(frm) {
frm.set_query("party_type", function () {
return {
filters: {
@@ -33,10 +27,15 @@ frappe.ui.form.on("Bank Transaction", {
});
},
get_payment_doctypes: function () {
get_payment_doctypes: function() {
// get payment doctypes from all the apps
return ["Payment Entry", "Journal Entry", "Sales Invoice", "Purchase Invoice", "Bank Transaction"];
},
return [
"Payment Entry",
"Journal Entry",
"Sales Invoice",
"Purchase Invoice",
];
}
});
frappe.ui.form.on("Bank Transaction Payments", {
@@ -48,11 +47,10 @@ frappe.ui.form.on("Bank Transaction Payments", {
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,
})
.xcall(
"erpnext.accounts.doctype.bank_transaction.bank_transaction.unclear_reference_payment",
{ doctype: cdt, docname: cdn }
)
.then((e) => {
if (e == "success") {
frappe.show_alert({

View File

@@ -20,11 +20,9 @@
"currency",
"section_break_10",
"description",
"reference_number",
"column_break_10",
"transaction_id",
"transaction_type",
"section_break_14",
"reference_number",
"transaction_id",
"payment_entries",
"section_break_18",
"allocated_amount",
@@ -33,11 +31,7 @@
"unallocated_amount",
"party_section",
"party_type",
"party",
"column_break_3czf",
"bank_party_name",
"bank_party_account_number",
"bank_party_iban"
"party"
],
"fields": [
{
@@ -67,7 +61,7 @@
"fieldtype": "Select",
"in_standard_filter": 1,
"label": "Status",
"options": "\nPending\nSettled\nUnreconciled\nReconciled\nCancelled"
"options": "\nPending\nSettled\nUnreconciled\nReconciled"
},
{
"fieldname": "bank_account",
@@ -196,40 +190,11 @@
"label": "Withdrawal",
"oldfieldname": "credit",
"options": "currency"
},
{
"fieldname": "column_break_10",
"fieldtype": "Column Break"
},
{
"fieldname": "transaction_type",
"fieldtype": "Data",
"label": "Transaction Type",
"length": 50
},
{
"fieldname": "column_break_3czf",
"fieldtype": "Column Break"
},
{
"fieldname": "bank_party_name",
"fieldtype": "Data",
"label": "Party Name/Account Holder (Bank Statement)"
},
{
"fieldname": "bank_party_iban",
"fieldtype": "Data",
"label": "Party IBAN (Bank Statement)"
},
{
"fieldname": "bank_party_account_number",
"fieldtype": "Data",
"label": "Party Account No. (Bank Statement)"
}
],
"is_submittable": 1,
"links": [],
"modified": "2023-06-06 13:58:12.821411",
"modified": "2022-03-21 19:05:04.208222",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Transaction",

View File

@@ -1,9 +1,10 @@
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from functools import reduce
import frappe
from frappe import _
from frappe.model.docstatus import DocStatus
from frappe.utils import flt
from erpnext.controllers.status_updater import StatusUpdater
@@ -17,169 +18,73 @@ class BankTransaction(StatusUpdater):
self.clear_linked_payment_entries()
self.set_status()
if frappe.db.get_single_value("Accounts Settings", "enable_party_matching"):
self.auto_set_party()
_saving_flag = False
# nosemgrep: frappe-semgrep-rules.rules.frappe-modifying-but-not-comitting
def on_update_after_submit(self):
"Run on save(). Avoid recursion caused by multiple saves"
if not self._saving_flag:
self._saving_flag = True
self.clear_linked_payment_entries()
self.update_allocations()
self._saving_flag = False
self.update_allocations()
self.clear_linked_payment_entries()
self.set_status(update=True)
def on_cancel(self):
self.clear_linked_payment_entries(for_cancel=True)
self.set_status(update=True)
def update_allocations(self):
"The doctype does not allow modifications after submission, so write to the db direct"
if self.payment_entries:
allocated_amount = sum(p.allocated_amount for p in self.payment_entries)
allocated_amount = reduce(
lambda x, y: flt(x) + flt(y), [x.allocated_amount for x in self.payment_entries]
)
else:
allocated_amount = 0.0
allocated_amount = 0
unallocated_amount = abs(flt(self.withdrawal) - flt(self.deposit)) - allocated_amount
if allocated_amount:
frappe.db.set_value(self.doctype, self.name, "allocated_amount", flt(allocated_amount))
frappe.db.set_value(
self.doctype,
self.name,
"unallocated_amount",
abs(flt(self.withdrawal) - flt(self.deposit)) - flt(allocated_amount),
)
self.db_set("allocated_amount", flt(allocated_amount, self.precision("allocated_amount")))
self.db_set("unallocated_amount", flt(unallocated_amount, self.precision("unallocated_amount")))
self.reload()
self.set_status(update=True)
else:
frappe.db.set_value(self.doctype, self.name, "allocated_amount", 0)
frappe.db.set_value(
self.doctype, self.name, "unallocated_amount", abs(flt(self.withdrawal) - flt(self.deposit))
)
def add_payment_entries(self, vouchers):
"Add the vouchers with zero allocation. Save() will perform the allocations and clearance"
if 0.0 >= self.unallocated_amount:
frappe.throw(frappe._("Bank Transaction {0} is already fully reconciled").format(self.name))
added = False
for voucher in vouchers:
# Can't add same voucher twice
found = False
for pe in self.payment_entries:
if (
pe.payment_document == voucher["payment_doctype"]
and pe.payment_entry == voucher["payment_name"]
):
found = True
if not found:
pe = {
"payment_document": voucher["payment_doctype"],
"payment_entry": voucher["payment_name"],
"allocated_amount": 0.0, # Temporary
}
self.append("payment_entries", pe)
added = True
# runs on_update_after_submit
if added:
self.save()
def allocate_payment_entries(self):
"""Refactored from bank reconciliation tool.
Non-zero allocations must be amended/cleared manually
Get the bank transaction amount (b) and remove as we allocate
For each payment_entry if allocated_amount == 0:
- get the amount already allocated against all transactions (t), need latest date
- get the voucher amount (from gl) (v)
- allocate (a = v - t)
- a = 0: should already be cleared, so clear & remove payment_entry
- 0 < a <= u: allocate a & clear
- 0 < a, a > u: allocate u
- 0 > a: Error: already over-allocated
- clear means: set the latest transaction date as clearance date
"""
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)
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,
pe_bt_allocations.get((payment_entry.payment_document, payment_entry.payment_entry))
or [],
)
if 0.0 == unallocated_amount:
if should_clear:
latest_transaction.clear_linked_payment_entry(payment_entry)
self.db_delete_payment_entry(payment_entry)
elif remaining_amount <= 0.0:
self.db_delete_payment_entry(payment_entry)
elif 0.0 < unallocated_amount and unallocated_amount <= remaining_amount:
payment_entry.db_set("allocated_amount", unallocated_amount)
remaining_amount -= unallocated_amount
if should_clear:
latest_transaction.clear_linked_payment_entry(payment_entry)
elif 0.0 < unallocated_amount and unallocated_amount > remaining_amount:
payment_entry.db_set("allocated_amount", remaining_amount)
remaining_amount = 0.0
elif 0.0 > unallocated_amount:
self.db_delete_payment_entry(payment_entry)
frappe.throw(frappe._("Voucher {0} is over-allocated by {1}").format(unallocated_amount))
amount = self.deposit or self.withdrawal
if amount == self.allocated_amount:
frappe.db.set_value(self.doctype, self.name, "status", "Reconciled")
self.reload()
def db_delete_payment_entry(self, payment_entry):
frappe.db.delete("Bank Transaction Payments", {"name": payment_entry.name})
@frappe.whitelist()
def remove_payment_entries(self):
for payment_entry in self.payment_entries:
self.remove_payment_entry(payment_entry)
# runs on_update_after_submit
self.save()
def remove_payment_entry(self, payment_entry):
"Clear payment entry and clearance"
self.clear_linked_payment_entry(payment_entry, for_cancel=True)
self.remove(payment_entry)
def clear_linked_payment_entries(self, for_cancel=False):
if for_cancel:
for payment_entry in self.payment_entries:
self.clear_linked_payment_entry(payment_entry, for_cancel)
else:
self.allocate_payment_entries()
for payment_entry in self.payment_entries:
if payment_entry.payment_document == "Sales Invoice":
self.clear_sales_invoice(payment_entry, for_cancel=for_cancel)
elif payment_entry.payment_document in get_doctypes_for_bank_reconciliation():
self.clear_simple_entry(payment_entry, for_cancel=for_cancel)
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 clear_simple_entry(self, payment_entry, for_cancel=False):
if payment_entry.payment_document == "Payment Entry":
if (
frappe.db.get_value("Payment Entry", payment_entry.payment_entry, "payment_type")
== "Internal Transfer"
):
if len(get_reconciled_bank_transactions(payment_entry)) < 2:
return
clearance_date = self.date if not for_cancel else None
frappe.db.set_value(
payment_entry.payment_document, payment_entry.payment_entry, "clearance_date", clearance_date
)
def auto_set_party(self):
from erpnext.accounts.doctype.bank_transaction.auto_match_party import AutoMatchParty
if self.party_type and self.party:
return
result = None
try:
result = AutoMatchParty(
bank_party_account_number=self.bank_party_account_number,
bank_party_iban=self.bank_party_iban,
bank_party_name=self.bank_party_name,
description=self.description,
deposit=self.deposit,
).match()
except Exception:
frappe.log_error(title=_("Error in party matching for Bank Transaction {0}").format(self.name))
if result:
party_type, party = result
frappe.db.set_value(
"Bank Transaction", self.name, field={"party_type": party_type, "party": party}
)
def clear_sales_invoice(self, payment_entry, for_cancel=False):
clearance_date = self.date if not for_cancel else None
frappe.db.set_value(
"Sales Invoice Payment",
dict(parenttype=payment_entry.payment_document, parent=payment_entry.payment_entry),
"clearance_date",
clearance_date,
)
@frappe.whitelist()
@@ -188,120 +93,40 @@ def get_doctypes_for_bank_reconciliation():
return frappe.get_hooks("bank_reconciliation_doctypes")
def get_clearance_details(transaction, payment_entry, bt_allocations):
"""
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)
unallocated_amount = min(
transaction.unallocated_amount,
get_paid_amount(payment_entry, transaction.currency, gl_bank_account),
def get_reconciled_bank_transactions(payment_entry):
reconciled_bank_transactions = frappe.get_all(
"Bank Transaction Payments",
filters={"payment_entry": payment_entry.payment_entry},
fields=["parent"],
)
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(
frappe._("Voucher {0} value is broken: {1}").format(
payment_entry.payment_entry, gle["amount"]
)
)
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
return unallocated_amount, unmatched_gles == 0, latest_transaction
return reconciled_bank_transactions
def get_related_bank_gl_entries(doctype, docname):
# nosemgrep: frappe-semgrep-rules.rules.frappe-using-db-sql
result = frappe.db.sql(
def get_total_allocated_amount(payment_entry):
return frappe.db.sql(
"""
SELECT
ABS(gle.credit_in_account_currency - gle.debit_in_account_currency) AS amount,
gle.account AS gl_account
SUM(btp.allocated_amount) as allocated_amount,
bt.name
FROM
`tabGL Entry` gle
`tabBank Transaction Payments` as btp
LEFT JOIN
`tabAccount` ac ON ac.name=gle.account
`tabBank Transaction` bt ON bt.name=btp.parent
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,
)
return result
def get_total_allocated_amount(docs):
"""
Gets the sum of allocations for a voucher on each bank GL account
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_name, latest_date, gl_account, payment_document, payment_entry 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,
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
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
AND bt.docstatus = 1
WINDOW w AS (PARTITION BY ba.account, btp.payment_document, btp.payment_entry ORDER BY bt.date DESC)
) temp
WHERE
rownum = 1
""",
dict(docs=docs),
btp.payment_document = %s
AND
btp.payment_entry = %s
AND
bt.docstatus = 1""",
(payment_entry.payment_document, payment_entry.payment_entry),
as_dict=True,
)
payment_allocation_details = {}
for row in result:
# 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"])
payment_allocation_details.setdefault((row["payment_document"], row["payment_entry"]), []).append(row)
return payment_allocation_details
def get_paid_amount(payment_entry, currency, gl_bank_account):
def get_paid_amount(payment_entry, currency, 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)
@@ -312,7 +137,7 @@ def get_paid_amount(payment_entry, currency, gl_bank_account):
)
elif doc.payment_type == "Pay":
paid_amount_field = (
"paid_amount" if doc.paid_from_account_currency == currency else "base_paid_amount"
"paid_amount" if doc.paid_to_account_currency == currency else "base_paid_amount"
)
return frappe.db.get_value(
@@ -320,13 +145,10 @@ def get_paid_amount(payment_entry, currency, gl_bank_account):
)
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
return frappe.db.get_value(
"Journal Entry Account",
{"parent": payment_entry.payment_entry, "account": bank_account},
"sum(credit_in_account_currency)",
)
elif payment_entry.payment_document == "Expense Claim":
@@ -340,87 +162,30 @@ def get_paid_amount(payment_entry, currency, gl_bank_account):
)
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 frappe.db.get_value(
payment_entry.payment_document, payment_entry.payment_entry, "amount_paid"
)
return abs(flt(wth) - flt(dep))
else:
frappe.throw(
f"Please reconcile {payment_entry.payment_document}: {payment_entry.payment_entry} manually"
"Please reconcile {0}: {1} manually".format(
payment_entry.payment_document, payment_entry.payment_entry
)
)
def set_voucher_clearance(doctype, docname, clearance_date, self):
if doctype in [
"Payment Entry",
"Journal Entry",
"Purchase Invoice",
"Expense Claim",
"Loan Repayment",
"Loan Disbursement",
]:
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
frappe.db.set_value(doctype, docname, "clearance_date", clearance_date)
elif doctype == "Sales Invoice":
frappe.db.set_value(
"Sales Invoice Payment",
dict(parenttype=doctype, parent=docname),
"clearance_date",
clearance_date,
)
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)
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):
return frappe.get_all(
"Bank Transaction Payments",
filters={"payment_document": doctype, "payment_entry": docname},
pluck="parent",
)
@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 unclear_reference_payment(doctype, docname):
if frappe.db.exists(doctype, docname):
doc = frappe.get_doc(doctype, docname)
if doctype == "Sales Invoice":
frappe.db.set_value(
"Sales Invoice Payment",
dict(parenttype=doc.payment_document, parent=doc.payment_entry),
"clearance_date",
None,
)
else:
frappe.db.set_value(doc.payment_document, doc.payment_entry, "clearance_date", None)
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):
bt = frappe.get_doc("Bank Transaction", bt_name)
if bt.docstatus == DocStatus.cancelled():
continue
modified = False
for pe in bt.payment_entries:
if pe.payment_document == doctype and pe.payment_entry == docname:
bt.remove(pe)
modified = True
if modified:
bt.save()
return doc.payment_entry

View File

@@ -1,15 +1,15 @@
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.listview_settings["Bank Transaction"] = {
frappe.listview_settings['Bank Transaction'] = {
add_fields: ["unallocated_amount"],
get_indicator: function (doc) {
if (doc.docstatus == 2) {
get_indicator: function(doc) {
if(doc.docstatus == 2) {
return [__("Cancelled"), "red", "docstatus,=,2"];
} else if (flt(doc.unallocated_amount) <= 0) {
} else if(flt(doc.unallocated_amount)<=0) {
return [__("Reconciled"), "green", "unallocated_amount,=,0"];
} else if (flt(doc.unallocated_amount) > 0) {
} else if(flt(doc.unallocated_amount)>0) {
return [__("Unreconciled"), "orange", "unallocated_amount,>,0"];
}
},
}
};

View File

@@ -18,12 +18,12 @@ def upload_bank_statement():
fcontent = frappe.local.uploaded_file
fname = frappe.local.uploaded_filename
if frappe.safe_encode(fname).lower().endswith(b"csv"):
if frappe.safe_encode(fname).lower().endswith("csv".encode("utf-8")):
from frappe.utils.csvutils import read_csv_content
rows = read_csv_content(fcontent, False)
elif frappe.safe_encode(fname).lower().endswith(b"xlsx"):
elif frappe.safe_encode(fname).lower().endswith("xlsx".encode("utf-8")):
from frappe.utils.xlsxutils import read_xlsx_file_from_attached_file
rows = read_xlsx_file_from_attached_file(fcontent=fcontent)
@@ -74,7 +74,7 @@ def get_header_mapping(columns, bank_account):
def get_bank_mapping(bank_account):
bank_name = frappe.db.get_value("Bank Account", bank_account, "bank")
bank_name = frappe.get_cached_value("Bank Account", bank_account, "bank")
bank = frappe.get_doc("Bank", bank_name)
mapping = {row.file_field: row.bank_transaction_field for row in bank.bank_transaction_mapping}

View File

@@ -1,151 +0,0 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import frappe
from frappe.tests.utils import FrappeTestCase
from frappe.utils import nowdate
from erpnext.accounts.doctype.bank_transaction.test_bank_transaction import create_bank_account
class TestAutoMatchParty(FrappeTestCase):
@classmethod
def setUpClass(cls):
create_bank_account()
frappe.db.set_single_value("Accounts Settings", "enable_party_matching", 1)
frappe.db.set_single_value("Accounts Settings", "enable_fuzzy_matching", 1)
return super().setUpClass()
@classmethod
def tearDownClass(cls):
frappe.db.set_single_value("Accounts Settings", "enable_party_matching", 0)
frappe.db.set_single_value("Accounts Settings", "enable_fuzzy_matching", 0)
def test_match_by_account_number(self):
create_supplier_for_match(account_no="000000003716541159")
doc = create_bank_transaction(
withdrawal=1200,
transaction_id="562213b0ca1bf838dab8f2c6a39bbc3b",
account_no="000000003716541159",
iban="DE02000000003716541159",
)
self.assertEqual(doc.party_type, "Supplier")
self.assertEqual(doc.party, "John Doe & Co.")
def test_match_by_iban(self):
create_supplier_for_match(iban="DE02000000003716541159")
doc = create_bank_transaction(
withdrawal=1200,
transaction_id="c5455a224602afaa51592a9d9250600d",
account_no="000000003716541159",
iban="DE02000000003716541159",
)
self.assertEqual(doc.party_type, "Supplier")
self.assertEqual(doc.party, "John Doe & Co.")
def test_match_by_party_name(self):
create_supplier_for_match(supplier_name="Jackson Ella W.")
doc = create_bank_transaction(
withdrawal=1200,
transaction_id="1f6f661f347ff7b1ea588665f473adb1",
party_name="Ella Jackson",
iban="DE04000000003716545346",
)
self.assertEqual(doc.party_type, "Supplier")
self.assertEqual(doc.party, "Jackson Ella W.")
def test_match_by_description(self):
create_supplier_for_match(supplier_name="Microsoft")
doc = create_bank_transaction(
description="Auftraggeber: microsoft payments Buchungstext: msft ..e3006b5hdy. ref. j375979555927627/5536",
withdrawal=1200,
transaction_id="8df880a2d09c3bed3fea358ca5168c5a",
party_name="",
)
self.assertEqual(doc.party_type, "Supplier")
self.assertEqual(doc.party, "Microsoft")
def test_skip_match_if_multiple_close_results(self):
create_supplier_for_match(supplier_name="Adithya Medical & General Stores")
create_supplier_for_match(supplier_name="Adithya Medical And General Stores")
doc = create_bank_transaction(
description="Paracetamol Consignment, SINV-0009",
withdrawal=24.85,
transaction_id="3a1da4ee2dc5a980138d56ef3460cbd9",
party_name="Adithya Medical & General",
)
# Mapping is skipped as both Supplier names have the same match score
self.assertEqual(doc.party_type, None)
self.assertEqual(doc.party, None)
def create_supplier_for_match(supplier_name="John Doe & Co.", iban=None, account_no=None):
if frappe.db.exists("Supplier", {"supplier_name": supplier_name}):
# Update related Bank Account details
if not (iban or account_no):
return
frappe.db.set_value(
dt="Bank Account",
dn={"party": supplier_name},
field={"iban": iban, "bank_account_no": account_no},
)
return
# Create Supplier and Bank Account for the same
supplier = frappe.new_doc("Supplier")
supplier.supplier_name = supplier_name
supplier.supplier_group = "Services"
supplier.supplier_type = "Company"
supplier.insert()
if not frappe.db.exists("Bank", "TestBank"):
bank = frappe.new_doc("Bank")
bank.bank_name = "TestBank"
bank.insert(ignore_if_duplicate=True)
if not frappe.db.exists("Bank Account", supplier.name + " - " + "TestBank"):
bank_account = frappe.new_doc("Bank Account")
bank_account.account_name = supplier.name
bank_account.bank = "TestBank"
bank_account.iban = iban
bank_account.bank_account_no = account_no
bank_account.party_type = "Supplier"
bank_account.party = supplier.name
bank_account.insert()
def create_bank_transaction(
description=None,
withdrawal=0,
deposit=0,
transaction_id=None,
party_name=None,
account_no=None,
iban=None,
):
doc = frappe.new_doc("Bank Transaction")
doc.update(
{
"doctype": "Bank Transaction",
"description": description or "1512567 BG/000002918 OPSKATTUZWXXX AT776000000098709837 Herr G",
"date": nowdate(),
"withdrawal": withdrawal,
"deposit": deposit,
"currency": "INR",
"bank_account": "Checking Account - Citi Bank",
"transaction_id": transaction_id,
"bank_party_name": party_name,
"bank_party_account_number": account_no,
"bank_party_iban": iban,
}
)
doc.insert()
doc.submit()
doc.reload()
return doc

View File

@@ -2,10 +2,9 @@
# See license.txt
import json
import unittest
import frappe
from frappe import utils
from frappe.model.docstatus import DocStatus
from frappe.tests.utils import FrappeTestCase
from erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool import (
@@ -32,16 +31,8 @@ class TestBankTransaction(FrappeTestCase):
frappe.db.delete(dt)
make_pos_profile()
# generate and use a uniq hash identifier for 'Bank Account' and it's linked GL 'Account' to avoid validation error
uniq_identifier = frappe.generate_hash(length=10)
gl_account = create_gl_account("_Test Bank " + uniq_identifier)
bank_account = create_bank_account(
gl_account=gl_account, bank_account_name="Checking Account " + uniq_identifier
)
add_transactions(bank_account=bank_account)
add_vouchers(gl_account=gl_account)
add_transactions()
add_vouchers()
# This test checks if ERPNext is able to provide a linked payment for a bank transaction based on the amount of the bank transaction.
def test_linked_payments(self):
@@ -49,12 +40,7 @@ class TestBankTransaction(FrappeTestCase):
"Bank Transaction",
dict(description="Re 95282925234 FE/000002917 AT171513000281183046 Conrad Electronic"),
)
linked_payments = get_linked_payments(
bank_transaction.name,
["payment_entry", "exact_match"],
from_date=bank_transaction.date,
to_date=utils.today(),
)
linked_payments = get_linked_payments(bank_transaction.name, ["payment_entry", "exact_match"])
self.assertTrue(linked_payments[0][6] == "Conrad Electronic")
# This test validates a simple reconciliation leading to the clearance of the bank transaction and the payment
@@ -89,41 +75,13 @@ class TestBankTransaction(FrappeTestCase):
clearance_date = frappe.db.get_value("Payment Entry", payment.name, "clearance_date")
self.assertFalse(clearance_date)
def test_cancel_voucher(self):
bank_transaction = frappe.get_doc(
"Bank Transaction",
dict(description="1512567 BG/000003025 OPSKATTUZWXXX AT776000000098709849 Herr G"),
)
payment = frappe.get_doc("Payment Entry", dict(party="Mr G", paid_amount=1700))
vouchers = json.dumps(
[
{
"payment_doctype": "Payment Entry",
"payment_name": payment.name,
"amount": bank_transaction.unallocated_amount,
}
]
)
reconcile_vouchers(bank_transaction.name, vouchers)
payment.reload()
payment.cancel()
bank_transaction.reload()
self.assertEqual(bank_transaction.docstatus, DocStatus.submitted())
self.assertEqual(bank_transaction.unallocated_amount, 1700)
self.assertEqual(bank_transaction.payment_entries, [])
# Check if ERPNext can correctly filter a linked payments based on the debit/credit amount
def test_debit_credit_output(self):
bank_transaction = frappe.get_doc(
"Bank Transaction",
dict(description="Auszahlung Karte MC/000002916 AUTOMAT 698769 K002 27.10. 14:07"),
)
linked_payments = get_linked_payments(
bank_transaction.name,
["payment_entry", "exact_match"],
from_date=bank_transaction.date,
to_date=utils.today(),
)
linked_payments = get_linked_payments(bank_transaction.name, ["payment_entry", "exact_match"])
self.assertTrue(linked_payments[0][3])
# Check error if already reconciled
@@ -221,9 +179,7 @@ class TestBankTransaction(FrappeTestCase):
self.assertEqual(linked_payments[0][2], repayment_entry.name)
def create_bank_account(
bank_name="Citi Bank", gl_account="_Test Bank - _TC", bank_account_name="Checking Account"
):
def create_bank_account(bank_name="Citi Bank", account_name="_Test Bank - _TC"):
try:
frappe.get_doc(
{
@@ -235,35 +191,21 @@ def create_bank_account(
pass
try:
bank_account = frappe.get_doc(
frappe.get_doc(
{
"doctype": "Bank Account",
"account_name": bank_account_name,
"account_name": "Checking Account",
"bank": bank_name,
"account": gl_account,
"account": account_name,
}
).insert(ignore_if_duplicate=True)
except frappe.DuplicateEntryError:
pass
return bank_account.name
def add_transactions():
create_bank_account()
def create_gl_account(gl_account_name="_Test Bank - _TC"):
gl_account = frappe.get_doc(
{
"doctype": "Account",
"company": "_Test Company",
"parent_account": "Current Assets - _TC",
"account_type": "Bank",
"is_group": 0,
"account_name": gl_account_name,
}
).insert()
return gl_account.name
def add_transactions(bank_account="_Test Bank - _TC"):
doc = frappe.get_doc(
{
"doctype": "Bank Transaction",
@@ -271,7 +213,7 @@ def add_transactions(bank_account="_Test Bank - _TC"):
"date": "2018-10-23",
"deposit": 1200,
"currency": "INR",
"bank_account": bank_account,
"bank_account": "Checking Account - Citi Bank",
}
).insert()
doc.submit()
@@ -283,7 +225,7 @@ def add_transactions(bank_account="_Test Bank - _TC"):
"date": "2018-10-23",
"deposit": 1700,
"currency": "INR",
"bank_account": bank_account,
"bank_account": "Checking Account - Citi Bank",
}
).insert()
doc.submit()
@@ -295,7 +237,7 @@ def add_transactions(bank_account="_Test Bank - _TC"):
"date": "2018-10-26",
"withdrawal": 690,
"currency": "INR",
"bank_account": bank_account,
"bank_account": "Checking Account - Citi Bank",
}
).insert()
doc.submit()
@@ -307,7 +249,7 @@ def add_transactions(bank_account="_Test Bank - _TC"):
"date": "2018-10-27",
"deposit": 3900,
"currency": "INR",
"bank_account": bank_account,
"bank_account": "Checking Account - Citi Bank",
}
).insert()
doc.submit()
@@ -319,13 +261,13 @@ def add_transactions(bank_account="_Test Bank - _TC"):
"date": "2018-10-27",
"withdrawal": 109080,
"currency": "INR",
"bank_account": bank_account,
"bank_account": "Checking Account - Citi Bank",
}
).insert()
doc.submit()
def add_vouchers(gl_account="_Test Bank - _TC"):
def add_vouchers():
try:
frappe.get_doc(
{
@@ -341,7 +283,7 @@ def add_vouchers(gl_account="_Test Bank - _TC"):
pi = make_purchase_invoice(supplier="Conrad Electronic", qty=1, rate=690)
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account=gl_account)
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
pe.reference_no = "Conrad Oct 18"
pe.reference_date = "2018-10-24"
pe.insert()
@@ -360,14 +302,14 @@ def add_vouchers(gl_account="_Test Bank - _TC"):
pass
pi = make_purchase_invoice(supplier="Mr G", qty=1, rate=1200)
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account=gl_account)
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
pe.reference_no = "Herr G Oct 18"
pe.reference_date = "2018-10-24"
pe.insert()
pe.submit()
pi = make_purchase_invoice(supplier="Mr G", qty=1, rate=1700)
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account=gl_account)
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
pe.reference_no = "Herr G Nov 18"
pe.reference_date = "2018-11-01"
pe.insert()
@@ -398,10 +340,10 @@ def add_vouchers(gl_account="_Test Bank - _TC"):
pass
pi = make_purchase_invoice(supplier="Poore Simon's", qty=1, rate=3900, is_paid=1, do_not_save=1)
pi.cash_bank_account = gl_account
pi.cash_bank_account = "_Test Bank - _TC"
pi.insert()
pi.submit()
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account=gl_account)
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
pe.reference_no = "Poore Simon's Oct 18"
pe.reference_date = "2018-10-28"
pe.paid_amount = 690
@@ -410,7 +352,7 @@ def add_vouchers(gl_account="_Test Bank - _TC"):
pe.submit()
si = create_sales_invoice(customer="Poore Simon's", qty=1, rate=3900)
pe = get_payment_entry("Sales Invoice", si.name, bank_account=gl_account)
pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank - _TC")
pe.reference_no = "Poore Simon's Oct 18"
pe.reference_date = "2018-10-28"
pe.insert()
@@ -430,13 +372,19 @@ def add_vouchers(gl_account="_Test Bank - _TC"):
mode_of_payment = frappe.get_doc({"doctype": "Mode of Payment", "name": "Cash"})
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})
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": "_Test Bank - _TC"}
)
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": "Cash", "account": gl_account, "amount": 109080})
si.append(
"payments", {"mode_of_payment": "Cash", "account": "_Test Bank - _TC", "amount": 109080}
)
si.insert()
si.submit()

View File

@@ -1,100 +0,0 @@
// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on("Bisect Accounting Statements", {
onload(frm) {
frm.trigger("render_heatmap");
},
refresh(frm) {
frm.add_custom_button(__("Bisect Left"), () => {
frm.trigger("bisect_left");
});
frm.add_custom_button(__("Bisect Right"), () => {
frm.trigger("bisect_right");
});
frm.add_custom_button(__("Up"), () => {
frm.trigger("move_up");
});
frm.add_custom_button(__("Build Tree"), () => {
frm.trigger("build_tree");
});
},
render_heatmap(frm) {
let bisect_heatmap = frm.get_field("bisect_heatmap").$wrapper;
bisect_heatmap.addClass("bisect_heatmap_location");
// milliseconds in a day
let msiad = 24 * 60 * 60 * 1000;
let datapoints = {};
let fr_dt = new Date(frm.doc.from_date).getTime();
let to_dt = new Date(frm.doc.to_date).getTime();
let bisect_start = new Date(frm.doc.current_from_date).getTime();
let bisect_end = new Date(frm.doc.current_to_date).getTime();
for (let x = fr_dt; x <= to_dt; x += msiad) {
let epoch_in_seconds = x / 1000;
if (bisect_start <= x && x <= bisect_end) {
datapoints[epoch_in_seconds] = 1.0;
} else {
datapoints[epoch_in_seconds] = 0.0;
}
}
new frappe.Chart(".bisect_heatmap_location", {
type: "heatmap",
data: {
dataPoints: datapoints,
start: new Date(frm.doc.from_date),
end: new Date(frm.doc.to_date),
},
countLabel: "Bisecting",
discreteDomains: 1,
});
},
bisect_left(frm) {
frm.call({
doc: frm.doc,
method: "bisect_left",
freeze: true,
freeze_message: __("Bisecting Left ..."),
callback: (r) => {
frm.trigger("render_heatmap");
},
});
},
bisect_right(frm) {
frm.call({
doc: frm.doc,
freeze: true,
freeze_message: __("Bisecting Right ..."),
method: "bisect_right",
callback: (r) => {
frm.trigger("render_heatmap");
},
});
},
move_up(frm) {
frm.call({
doc: frm.doc,
freeze: true,
freeze_message: __("Moving up in tree ..."),
method: "move_up",
callback: (r) => {
frm.trigger("render_heatmap");
},
});
},
build_tree(frm) {
frm.call({
doc: frm.doc,
freeze: true,
freeze_message: __("Rebuilding BTree for period ..."),
method: "build_tree",
callback: (r) => {
frm.trigger("render_heatmap");
},
});
},
});

View File

@@ -1,194 +0,0 @@
{
"actions": [],
"allow_rename": 1,
"creation": "2023-09-15 21:28:28.054773",
"default_view": "List",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"section_break_cvfg",
"company",
"column_break_hcam",
"from_date",
"column_break_qxbi",
"to_date",
"column_break_iwny",
"algorithm",
"section_break_8ph9",
"current_node",
"section_break_ngid",
"bisect_heatmap",
"section_break_hmsy",
"bisecting_from",
"current_from_date",
"column_break_uqyd",
"bisecting_to",
"current_to_date",
"section_break_hbyo",
"heading_cppb",
"p_l_summary",
"column_break_aivo",
"balance_sheet_summary",
"b_s_summary",
"column_break_gvwx",
"difference_heading",
"difference"
],
"fields": [
{
"fieldname": "column_break_qxbi",
"fieldtype": "Column Break"
},
{
"fieldname": "from_date",
"fieldtype": "Datetime",
"label": "From Date"
},
{
"fieldname": "to_date",
"fieldtype": "Datetime",
"label": "To Date"
},
{
"default": "BFS",
"fieldname": "algorithm",
"fieldtype": "Select",
"label": "Algorithm",
"options": "BFS\nDFS"
},
{
"fieldname": "column_break_iwny",
"fieldtype": "Column Break"
},
{
"fieldname": "current_node",
"fieldtype": "Link",
"label": "Current Node",
"options": "Bisect Nodes"
},
{
"fieldname": "section_break_hmsy",
"fieldtype": "Section Break"
},
{
"fieldname": "current_from_date",
"fieldtype": "Datetime",
"read_only": 1
},
{
"fieldname": "current_to_date",
"fieldtype": "Datetime",
"read_only": 1
},
{
"fieldname": "column_break_uqyd",
"fieldtype": "Column Break"
},
{
"fieldname": "section_break_hbyo",
"fieldtype": "Section Break"
},
{
"fieldname": "p_l_summary",
"fieldtype": "Float",
"read_only": 1
},
{
"fieldname": "b_s_summary",
"fieldtype": "Float",
"read_only": 1
},
{
"fieldname": "difference",
"fieldtype": "Float",
"read_only": 1
},
{
"fieldname": "column_break_aivo",
"fieldtype": "Column Break"
},
{
"fieldname": "column_break_gvwx",
"fieldtype": "Column Break"
},
{
"fieldname": "company",
"fieldtype": "Link",
"label": "Company",
"options": "Company"
},
{
"fieldname": "column_break_hcam",
"fieldtype": "Column Break"
},
{
"fieldname": "section_break_ngid",
"fieldtype": "Section Break"
},
{
"fieldname": "section_break_8ph9",
"fieldtype": "Section Break",
"hidden": 1
},
{
"fieldname": "bisect_heatmap",
"fieldtype": "HTML",
"label": "Heatmap"
},
{
"fieldname": "heading_cppb",
"fieldtype": "Heading",
"label": "Profit and Loss Summary"
},
{
"fieldname": "balance_sheet_summary",
"fieldtype": "Heading",
"label": "Balance Sheet Summary"
},
{
"fieldname": "difference_heading",
"fieldtype": "Heading",
"label": "Difference"
},
{
"fieldname": "bisecting_from",
"fieldtype": "Heading",
"label": "Bisecting From"
},
{
"fieldname": "bisecting_to",
"fieldtype": "Heading",
"label": "Bisecting To"
},
{
"fieldname": "section_break_cvfg",
"fieldtype": "Section Break"
}
],
"hide_toolbar": 1,
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2023-12-01 16:49:54.073890",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bisect Accounting Statements",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"print": 1,
"read": 1,
"role": "Administrator",
"share": 1,
"write": 1
}
],
"read_only": 1,
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}

View File

@@ -1,206 +0,0 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
import datetime
from collections import deque
from math import floor
import frappe
from dateutil.relativedelta import relativedelta
from frappe import _
from frappe.model.document import Document
from frappe.utils import getdate
from frappe.utils.data import guess_date_format
class BisectAccountingStatements(Document):
def validate(self):
self.validate_dates()
def validate_dates(self):
if getdate(self.from_date) > getdate(self.to_date):
frappe.throw(
_("From Date: {0} cannot be greater than To date: {1}").format(
frappe.bold(self.from_date), frappe.bold(self.to_date)
)
)
def bfs(self, from_date: datetime, to_date: datetime):
# Make Root node
node = frappe.new_doc("Bisect Nodes")
node.root = None
node.period_from_date = from_date
node.period_to_date = to_date
node.insert()
period_queue = deque([node])
while period_queue:
cur_node = period_queue.popleft()
delta = cur_node.period_to_date - cur_node.period_from_date
if delta.days == 0:
continue
else:
cur_floor = floor(delta.days / 2)
next_to_date = cur_node.period_from_date + relativedelta(days=+cur_floor)
left_node = frappe.new_doc("Bisect Nodes")
left_node.period_from_date = cur_node.period_from_date
left_node.period_to_date = next_to_date
left_node.root = cur_node.name
left_node.generated = False
left_node.insert()
cur_node.left_child = left_node.name
period_queue.append(left_node)
next_from_date = cur_node.period_from_date + relativedelta(days=+(cur_floor + 1))
right_node = frappe.new_doc("Bisect Nodes")
right_node.period_from_date = next_from_date
right_node.period_to_date = cur_node.period_to_date
right_node.root = cur_node.name
right_node.generated = False
right_node.insert()
cur_node.right_child = right_node.name
period_queue.append(right_node)
cur_node.save()
def dfs(self, from_date: datetime, to_date: datetime):
# Make Root node
node = frappe.new_doc("Bisect Nodes")
node.root = None
node.period_from_date = from_date
node.period_to_date = to_date
node.insert()
period_stack = [node]
while period_stack:
cur_node = period_stack.pop()
delta = cur_node.period_to_date - cur_node.period_from_date
if delta.days == 0:
continue
else:
cur_floor = floor(delta.days / 2)
next_to_date = cur_node.period_from_date + relativedelta(days=+cur_floor)
left_node = frappe.new_doc("Bisect Nodes")
left_node.period_from_date = cur_node.period_from_date
left_node.period_to_date = next_to_date
left_node.root = cur_node.name
left_node.generated = False
left_node.insert()
cur_node.left_child = left_node.name
period_stack.append(left_node)
next_from_date = cur_node.period_from_date + relativedelta(days=+(cur_floor + 1))
right_node = frappe.new_doc("Bisect Nodes")
right_node.period_from_date = next_from_date
right_node.period_to_date = cur_node.period_to_date
right_node.root = cur_node.name
right_node.generated = False
right_node.insert()
cur_node.right_child = right_node.name
period_stack.append(right_node)
cur_node.save()
@frappe.whitelist()
def build_tree(self):
frappe.db.delete("Bisect Nodes")
# Convert str to datetime format
dt_format = guess_date_format(self.from_date)
from_date = datetime.datetime.strptime(self.from_date, dt_format)
to_date = datetime.datetime.strptime(self.to_date, dt_format)
if self.algorithm == "BFS":
self.bfs(from_date, to_date)
if self.algorithm == "DFS":
self.dfs(from_date, to_date)
# set root as current node
root = frappe.db.get_all("Bisect Nodes", filters={"root": ["is", "not set"]})[0]
self.get_report_summary()
self.current_node = root.name
self.current_from_date = self.from_date
self.current_to_date = self.to_date
self.save()
def get_report_summary(self):
filters = {
"company": self.company,
"filter_based_on": "Date Range",
"period_start_date": self.current_from_date,
"period_end_date": self.current_to_date,
"periodicity": "Yearly",
}
pl_summary = frappe.get_doc("Report", "Profit and Loss Statement")
self.p_l_summary = pl_summary.execute_script_report(filters=filters)[5]
bs_summary = frappe.get_doc("Report", "Balance Sheet")
self.b_s_summary = bs_summary.execute_script_report(filters=filters)[5]
self.difference = abs(self.p_l_summary - self.b_s_summary)
def update_node(self):
current_node = frappe.get_doc("Bisect Nodes", self.current_node)
current_node.balance_sheet_summary = self.b_s_summary
current_node.profit_loss_summary = self.p_l_summary
current_node.difference = self.difference
current_node.generated = True
current_node.save()
def current_node_has_summary_info(self):
"Assertion method"
return frappe.db.get_value("Bisect Nodes", self.current_node, "generated")
def fetch_summary_info_from_current_node(self):
current_node = frappe.get_doc("Bisect Nodes", self.current_node)
self.p_l_summary = current_node.balance_sheet_summary
self.b_s_summary = current_node.profit_loss_summary
self.difference = abs(self.p_l_summary - self.b_s_summary)
def fetch_or_calculate(self):
if self.current_node_has_summary_info():
self.fetch_summary_info_from_current_node()
else:
self.get_report_summary()
self.update_node()
@frappe.whitelist()
def bisect_left(self):
if self.current_node is not None:
cur_node = frappe.get_doc("Bisect Nodes", self.current_node)
if cur_node.left_child is not None:
lft_node = frappe.get_doc("Bisect Nodes", cur_node.left_child)
self.current_node = cur_node.left_child
self.current_from_date = lft_node.period_from_date
self.current_to_date = lft_node.period_to_date
self.fetch_or_calculate()
self.save()
else:
frappe.msgprint(_("No more children on Left"))
@frappe.whitelist()
def bisect_right(self):
if self.current_node is not None:
cur_node = frappe.get_doc("Bisect Nodes", self.current_node)
if cur_node.right_child is not None:
rgt_node = frappe.get_doc("Bisect Nodes", cur_node.right_child)
self.current_node = cur_node.right_child
self.current_from_date = rgt_node.period_from_date
self.current_to_date = rgt_node.period_to_date
self.fetch_or_calculate()
self.save()
else:
frappe.msgprint(_("No more children on Right"))
@frappe.whitelist()
def move_up(self):
if self.current_node is not None:
cur_node = frappe.get_doc("Bisect Nodes", self.current_node)
if cur_node.root is not None:
root = frappe.get_doc("Bisect Nodes", cur_node.root)
self.current_node = cur_node.root
self.current_from_date = root.period_from_date
self.current_to_date = root.period_to_date
self.fetch_or_calculate()
self.save()
else:
frappe.msgprint(_("Reached Root"))

View File

@@ -1,9 +0,0 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestBisectAccountingStatements(FrappeTestCase):
pass

View File

@@ -1,8 +0,0 @@
// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
// frappe.ui.form.on("Bisect Nodes", {
// refresh(frm) {
// },
// });

View File

@@ -1,97 +0,0 @@
{
"actions": [],
"autoname": "autoincrement",
"creation": "2023-09-27 14:56:38.112462",
"default_view": "List",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"root",
"left_child",
"right_child",
"period_from_date",
"period_to_date",
"difference",
"balance_sheet_summary",
"profit_loss_summary",
"generated"
],
"fields": [
{
"fieldname": "root",
"fieldtype": "Link",
"label": "Root",
"options": "Bisect Nodes"
},
{
"fieldname": "left_child",
"fieldtype": "Link",
"label": "Left Child",
"options": "Bisect Nodes"
},
{
"fieldname": "right_child",
"fieldtype": "Link",
"label": "Right Child",
"options": "Bisect Nodes"
},
{
"fieldname": "period_from_date",
"fieldtype": "Datetime",
"label": "Period_from_date"
},
{
"fieldname": "period_to_date",
"fieldtype": "Datetime",
"label": "Period To Date"
},
{
"fieldname": "difference",
"fieldtype": "Float",
"label": "Difference"
},
{
"fieldname": "balance_sheet_summary",
"fieldtype": "Float",
"label": "Balance Sheet Summary"
},
{
"fieldname": "profit_loss_summary",
"fieldtype": "Float",
"label": "Profit and Loss Summary"
},
{
"default": "0",
"fieldname": "generated",
"fieldtype": "Check",
"label": "Generated"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2023-12-01 17:46:12.437996",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bisect Nodes",
"naming_rule": "Autoincrement",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Administrator",
"share": 1,
"write": 1
}
],
"read_only": 1,
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}

View File

@@ -1,29 +0,0 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class BisectNodes(Document):
# begin: auto-generated types
# This code is auto-generated. Do not modify anything in this block.
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from frappe.types import DF
balance_sheet_summary: DF.Float
difference: DF.Float
generated: DF.Check
left_child: DF.Link | None
name: DF.Int | None
period_from_date: DF.Datetime | None
period_to_date: DF.Datetime | None
profit_loss_summary: DF.Float
right_child: DF.Link | None
root: DF.Link | None
# end: auto-generated types
pass

View File

@@ -1,9 +0,0 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestBisectNodes(FrappeTestCase):
pass

View File

@@ -2,48 +2,48 @@
// For license information, please see license.txt
frappe.provide("erpnext.accounts.dimensions");
frappe.ui.form.on("Budget", {
onload: function (frm) {
frm.set_query("account", "accounts", function () {
frappe.ui.form.on('Budget', {
onload: function(frm) {
frm.set_query("account", "accounts", function() {
return {
filters: {
company: frm.doc.company,
report_type: "Profit and Loss",
is_group: 0,
},
is_group: 0
}
};
});
frm.set_query("monthly_distribution", function () {
frm.set_query("monthly_distribution", function() {
return {
filters: {
fiscal_year: frm.doc.fiscal_year,
},
fiscal_year: frm.doc.fiscal_year
}
};
});
erpnext.accounts.dimensions.setup_dimension_filters(frm, frm.doctype);
},
refresh: function (frm) {
frm.trigger("toggle_reqd_fields");
refresh: function(frm) {
frm.trigger("toggle_reqd_fields")
},
budget_against: function (frm) {
frm.trigger("set_null_value");
frm.trigger("toggle_reqd_fields");
budget_against: function(frm) {
frm.trigger("set_null_value")
frm.trigger("toggle_reqd_fields")
},
set_null_value: function (frm) {
if (frm.doc.budget_against == "Cost Center") {
frm.set_value("project", null);
set_null_value: function(frm) {
if(frm.doc.budget_against == 'Cost Center') {
frm.set_value('project', null)
} else {
frm.set_value("cost_center", null);
frm.set_value('cost_center', null)
}
},
toggle_reqd_fields: function (frm) {
frm.toggle_reqd("cost_center", frm.doc.budget_against == "Cost Center");
frm.toggle_reqd("project", frm.doc.budget_against == "Project");
},
toggle_reqd_fields: function(frm) {
frm.toggle_reqd("cost_center", frm.doc.budget_against=="Cost Center");
frm.toggle_reqd("project", frm.doc.budget_against=="Project");
}
});

View File

@@ -40,11 +40,10 @@ class Budget(Document):
select
b.name, ba.account from `tabBudget` b, `tabBudget Account` ba
where
ba.parent = b.name and b.docstatus < 2 and b.company = {} and {}={} and
b.fiscal_year={} and b.name != {} and ba.account in ({}) """.format(
"%s", budget_against_field, "%s", "%s", "%s", ",".join(["%s"] * len(accounts))
),
(self.company, budget_against, self.fiscal_year, self.name, *tuple(accounts)),
ba.parent = b.name and b.docstatus < 2 and b.company = %s and %s=%s and
b.fiscal_year=%s and b.name != %s and ba.account in (%s) """
% ("%s", budget_against_field, "%s", "%s", "%s", ",".join(["%s"] * len(accounts))),
(self.company, budget_against, self.fiscal_year, self.name) + tuple(accounts),
as_dict=1,
)
@@ -60,21 +59,19 @@ class Budget(Document):
account_list = []
for d in self.get("accounts"):
if d.account:
account_details = frappe.db.get_value(
account_details = frappe.get_cached_value(
"Account", d.account, ["is_group", "company", "report_type"], as_dict=1
)
if account_details.is_group:
frappe.throw(_("Budget cannot be assigned against Group Account {0}").format(d.account))
elif account_details.company != self.company:
frappe.throw(
_("Account {0} does not belongs to company {1}").format(d.account, self.company)
)
frappe.throw(_("Account {0} does not belongs to company {1}").format(d.account, self.company))
elif account_details.report_type != "Profit and Loss":
frappe.throw(
_(
"Budget cannot be assigned against {0}, as it's not an Income or Expense account"
).format(d.account)
_("Budget cannot be assigned against {0}, as it's not an Income or Expense account").format(
d.account
)
)
if d.account in account_list:
@@ -112,8 +109,6 @@ class Budget(Document):
def validate_expense_against_budget(args, expense_amount=0):
args = frappe._dict(args)
if not frappe.get_all("Budget", limit=1):
return
if args.get("company") and not args.fiscal_year:
args.fiscal_year = get_fiscal_year(args.get("posting_date"), company=args.get("company"))[0]
@@ -121,9 +116,6 @@ def validate_expense_against_budget(args, expense_amount=0):
"Company", args.get("company"), "exception_budget_approver_role"
)
if not frappe.get_cached_value("Budget", {"fiscal_year": args.fiscal_year, "company": args.company}): # nosec
return
if not args.account:
args.account = args.get("expense_account")
@@ -133,43 +125,36 @@ def validate_expense_against_budget(args, expense_amount=0):
if not args.account:
return
default_dimensions = [
{
"fieldname": "project",
"document_type": "Project",
},
{
"fieldname": "cost_center",
"document_type": "Cost Center",
},
]
for dimension in default_dimensions + get_accounting_dimensions(as_list=False):
budget_against = dimension.get("fieldname")
for budget_against in ["project", "cost_center"] + get_accounting_dimensions():
if (
args.get(budget_against)
and args.account
and (frappe.get_cached_value("Account", args.account, "root_type") == "Expense")
and frappe.db.get_value("Account", {"name": args.account, "root_type": "Expense"})
):
doctype = dimension.get("document_type")
doctype = frappe.unscrub(budget_against)
if frappe.get_cached_value("DocType", doctype, "is_tree"):
lft, rgt = frappe.get_cached_value(doctype, args.get(budget_against), ["lft", "rgt"])
condition = f"""and exists(select name from `tab{doctype}`
where lft<={lft} and rgt>={rgt} and name=b.{budget_against})""" # nosec
lft, rgt = frappe.db.get_value(doctype, args.get(budget_against), ["lft", "rgt"])
condition = """and exists(select name from `tab%s`
where lft<=%s and rgt>=%s and name=b.%s)""" % (
doctype,
lft,
rgt,
budget_against,
) # nosec
args.is_tree = True
else:
condition = f"and b.{budget_against}={frappe.db.escape(args.get(budget_against))}"
condition = "and b.%s=%s" % (budget_against, frappe.db.escape(args.get(budget_against)))
args.is_tree = False
args.budget_against_field = budget_against
args.budget_against_doctype = doctype
budget_records = frappe.db.sql(
f"""
"""
select
b.{budget_against} as budget_against, ba.budget_amount, b.monthly_distribution,
b.{budget_against_field} as budget_against, ba.budget_amount, b.monthly_distribution,
ifnull(b.applicable_on_material_request, 0) as for_material_request,
ifnull(applicable_on_purchase_order, 0) as for_purchase_order,
ifnull(applicable_on_booking_actual_expenses,0) as for_actual_expenses,
@@ -182,7 +167,9 @@ def validate_expense_against_budget(args, expense_amount=0):
b.name=ba.parent and b.fiscal_year=%s
and ba.account=%s and b.docstatus=1
{condition}
""",
""".format(
condition=condition, budget_against_field=budget_against
),
(args.fiscal_year, args.account),
as_dict=True,
) # nosec
@@ -194,19 +181,8 @@ def validate_expense_against_budget(args, expense_amount=0):
def validate_budget_records(args, budget_records, expense_amount):
for budget in budget_records:
if flt(budget.budget_amount):
amount = expense_amount or get_amount(args, budget)
yearly_action, monthly_action = get_actions(args, budget)
args["for_material_request"] = budget.for_material_request
args["for_purchase_order"] = budget.for_purchase_order
if yearly_action in ("Stop", "Warn"):
compare_expense_with_budget(
args,
flt(budget.budget_amount),
_("Annual"),
yearly_action,
budget.budget_against,
expense_amount,
)
if monthly_action in ["Stop", "Warn"]:
budget_amount = get_accumulated_monthly_budget(
@@ -216,136 +192,44 @@ def validate_budget_records(args, budget_records, expense_amount):
args["month_end_date"] = get_last_day(args.posting_date)
compare_expense_with_budget(
args,
budget_amount,
_("Accumulated Monthly"),
monthly_action,
budget.budget_against,
expense_amount,
args, budget_amount, _("Accumulated Monthly"), monthly_action, budget.budget_against, amount
)
if (
yearly_action in ("Stop", "Warn")
and monthly_action != "Stop"
and yearly_action != monthly_action
):
compare_expense_with_budget(
args, flt(budget.budget_amount), _("Annual"), yearly_action, budget.budget_against, amount
)
def compare_expense_with_budget(args, budget_amount, action_for, action, budget_against, amount=0):
args.actual_expense, args.requested_amount, args.ordered_amount = get_actual_expense(args), 0, 0
if not amount:
args.requested_amount, args.ordered_amount = get_requested_amount(args), get_ordered_amount(args)
if args.get("doctype") == "Material Request" and args.for_material_request:
amount = args.requested_amount + args.ordered_amount
elif args.get("doctype") == "Purchase Order" and args.for_purchase_order:
amount = args.ordered_amount
total_expense = args.actual_expense + amount
if total_expense > budget_amount:
if args.actual_expense > budget_amount:
error_tense = _("is already")
diff = args.actual_expense - budget_amount
else:
error_tense = _("will be")
diff = total_expense - budget_amount
actual_expense = amount or get_actual_expense(args)
if actual_expense > budget_amount:
diff = actual_expense - budget_amount
currency = frappe.get_cached_value("Company", args.company, "default_currency")
msg = _("{0} Budget for Account {1} against {2} {3} is {4}. It {5} exceed by {6}").format(
msg = _("{0} Budget for Account {1} against {2} {3} is {4}. It will exceed by {5}").format(
_(action_for),
frappe.bold(args.account),
frappe.unscrub(args.budget_against_field),
args.budget_against_field,
frappe.bold(budget_against),
frappe.bold(fmt_money(budget_amount, currency=currency)),
error_tense,
frappe.bold(fmt_money(diff, currency=currency)),
)
msg += get_expense_breakup(args, currency, budget_against)
if frappe.flags.exception_approver_role and frappe.flags.exception_approver_role in frappe.get_roles(
frappe.session.user
if (
frappe.flags.exception_approver_role
and frappe.flags.exception_approver_role in frappe.get_roles(frappe.session.user)
):
action = "Warn"
if action == "Stop":
frappe.throw(msg, BudgetError, title=_("Budget Exceeded"))
frappe.throw(msg, BudgetError)
else:
frappe.msgprint(msg, indicator="orange", title=_("Budget Exceeded"))
def get_expense_breakup(args, currency, budget_against):
msg = "<hr>Total Expenses booked through - <ul>"
common_filters = frappe._dict(
{
args.budget_against_field: budget_against,
"account": args.account,
"company": args.company,
}
)
msg += (
"<li>"
+ frappe.utils.get_link_to_report(
"General Ledger",
label="Actual Expenses",
filters=common_filters.copy().update(
{
"from_date": frappe.get_cached_value("Fiscal Year", args.fiscal_year, "year_start_date"),
"to_date": frappe.get_cached_value("Fiscal Year", args.fiscal_year, "year_end_date"),
"is_cancelled": 0,
}
),
)
+ " - "
+ frappe.bold(fmt_money(args.actual_expense, currency=currency))
+ "</li>"
)
msg += (
"<li>"
+ frappe.utils.get_link_to_report(
"Material Request",
label="Material Requests",
report_type="Report Builder",
doctype="Material Request",
filters=common_filters.copy().update(
{
"status": [["!=", "Stopped"]],
"docstatus": 1,
"material_request_type": "Purchase",
"schedule_date": [["fiscal year", "2023-2024"]],
"item_code": args.item_code,
"per_ordered": [["<", 100]],
}
),
)
+ " - "
+ frappe.bold(fmt_money(args.requested_amount, currency=currency))
+ "</li>"
)
msg += (
"<li>"
+ frappe.utils.get_link_to_report(
"Purchase Order",
label="Unbilled Orders",
report_type="Report Builder",
doctype="Purchase Order",
filters=common_filters.copy().update(
{
"status": [["!=", "Closed"]],
"docstatus": 1,
"transaction_date": [["fiscal year", "2023-2024"]],
"item_code": args.item_code,
"per_billed": [["<", 100]],
}
),
)
+ " - "
+ frappe.bold(fmt_money(args.ordered_amount, currency=currency))
+ "</li></ul>"
)
return msg
frappe.msgprint(msg, indicator="orange")
def get_actions(args, budget):
@@ -363,15 +247,31 @@ def get_actions(args, budget):
return yearly_action, monthly_action
def get_requested_amount(args):
def get_amount(args, budget):
amount = 0
if args.get("doctype") == "Material Request" and budget.for_material_request:
amount = (
get_requested_amount(args, budget) + get_ordered_amount(args, budget) + get_actual_expense(args)
)
elif args.get("doctype") == "Purchase Order" and budget.for_purchase_order:
amount = get_ordered_amount(args, budget) + get_actual_expense(args)
return amount
def get_requested_amount(args, budget):
item_code = args.get("item_code")
condition = get_other_condition(args, "Material Request")
condition = get_other_condition(args, budget, "Material Request")
data = frappe.db.sql(
""" select ifnull((sum(child.stock_qty - child.ordered_qty) * rate), 0) as amount
from `tabMaterial Request Item` child, `tabMaterial Request` parent where parent.name = child.parent and
child.item_code = %s and parent.docstatus = 1 and child.stock_qty > child.ordered_qty and {} and
parent.material_request_type = 'Purchase' and parent.status != 'Stopped'""".format(condition),
child.item_code = %s and parent.docstatus = 1 and child.stock_qty > child.ordered_qty and {0} and
parent.material_request_type = 'Purchase' and parent.status != 'Stopped'""".format(
condition
),
item_code,
as_list=1,
)
@@ -379,15 +279,17 @@ def get_requested_amount(args):
return data[0][0] if data else 0
def get_ordered_amount(args):
def get_ordered_amount(args, budget):
item_code = args.get("item_code")
condition = get_other_condition(args, "Purchase Order")
condition = get_other_condition(args, budget, "Purchase Order")
data = frappe.db.sql(
f""" select ifnull(sum(child.amount - child.billed_amt), 0) as amount
""" select ifnull(sum(child.amount - child.billed_amt), 0) as amount
from `tabPurchase Order Item` child, `tabPurchase Order` parent where
parent.name = child.parent and child.item_code = %s and parent.docstatus = 1 and child.amount > child.billed_amt
and parent.status != 'Closed' and {condition}""",
and parent.status != 'Closed' and {0}""".format(
condition
),
item_code,
as_list=1,
)
@@ -395,21 +297,25 @@ def get_ordered_amount(args):
return data[0][0] if data else 0
def get_other_condition(args, for_doc):
def get_other_condition(args, budget, for_doc):
condition = "expense_account = '%s'" % (args.expense_account)
budget_against_field = args.get("budget_against_field")
if budget_against_field and args.get(budget_against_field):
condition += f" and child.{budget_against_field} = '{args.get(budget_against_field)}'"
condition += " and child.%s = '%s'" % (budget_against_field, args.get(budget_against_field))
if args.get("fiscal_year"):
date_field = "schedule_date" if for_doc == "Material Request" else "transaction_date"
start_date, end_date = frappe.db.get_value(
start_date, end_date = frappe.get_cached_value(
"Fiscal Year", args.get("fiscal_year"), ["year_start_date", "year_end_date"]
)
condition += f""" and parent.{date_field}
between '{start_date}' and '{end_date}' """
condition += """ and parent.%s
between '%s' and '%s' """ % (
date_field,
start_date,
end_date,
)
return condition
@@ -428,28 +334,32 @@ def get_actual_expense(args):
args.update(lft_rgt)
condition2 = f"""and exists(select name from `tab{args.budget_against_doctype}`
condition2 = """and exists(select name from `tab{doctype}`
where lft>=%(lft)s and rgt<=%(rgt)s
and name=gle.{budget_against_field})"""
and name=gle.{budget_against_field})""".format(
doctype=args.budget_against_doctype, budget_against_field=budget_against_field # nosec
)
else:
condition2 = f"""and exists(select name from `tab{args.budget_against_doctype}`
where name=gle.{budget_against_field} and
gle.{budget_against_field} = %({budget_against_field})s)"""
condition2 = """and exists(select name from `tab{doctype}`
where name=gle.{budget_against} and
gle.{budget_against} = %({budget_against})s)""".format(
doctype=args.budget_against_doctype, budget_against=budget_against_field
)
amount = flt(
frappe.db.sql(
f"""
"""
select sum(gle.debit) - sum(gle.credit)
from `tabGL Entry` gle
where
is_cancelled = 0
and gle.account=%(account)s
where gle.account=%(account)s
{condition1}
and gle.fiscal_year=%(fiscal_year)s
and gle.company=%(company)s
and gle.docstatus=1
{condition2}
""",
""".format(
condition1=condition1, condition2=condition2
),
(args),
)[0][0]
) # nosec
@@ -460,23 +370,16 @@ def get_actual_expense(args):
def get_accumulated_monthly_budget(monthly_distribution, posting_date, fiscal_year, annual_budget):
distribution = {}
if monthly_distribution:
mdp = frappe.qb.DocType("Monthly Distribution Percentage")
md = frappe.qb.DocType("Monthly Distribution")
res = (
frappe.qb.from_(mdp)
.join(md)
.on(mdp.parent == md.name)
.select(mdp.month, mdp.percentage_allocation)
.where(md.fiscal_year == fiscal_year)
.where(md.name == monthly_distribution)
.run(as_dict=True)
)
for d in res:
for d in frappe.db.sql(
"""select mdp.month, mdp.percentage_allocation
from `tabMonthly Distribution Percentage` mdp, `tabMonthly Distribution` md
where mdp.parent=md.name and md.fiscal_year=%s""",
fiscal_year,
as_dict=1,
):
distribution.setdefault(d.month, d.percentage_allocation)
dt = frappe.db.get_value("Fiscal Year", fiscal_year, "year_start_date")
dt = frappe.get_cached_value("Fiscal Year", fiscal_year, "year_start_date")
accumulated_percentage = 0.0
while dt <= getdate(posting_date):

View File

@@ -41,7 +41,9 @@ class TestBudget(unittest.TestCase):
budget = make_budget(budget_against="Cost Center")
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
frappe.db.set_value(
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
)
jv = make_journal_entry(
"_Test Account Cost for Goods Sold - _TC",
@@ -61,7 +63,9 @@ class TestBudget(unittest.TestCase):
budget = make_budget(budget_against="Cost Center")
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
frappe.db.set_value(
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
)
jv = make_journal_entry(
"_Test Account Cost for Goods Sold - _TC",
@@ -93,7 +97,9 @@ class TestBudget(unittest.TestCase):
)
fiscal_year = get_fiscal_year(nowdate())[0]
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
frappe.db.set_value(
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
)
frappe.db.set_value("Budget", budget.name, "fiscal_year", fiscal_year)
mr = frappe.get_doc(
@@ -132,7 +138,9 @@ class TestBudget(unittest.TestCase):
)
fiscal_year = get_fiscal_year(nowdate())[0]
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
frappe.db.set_value(
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
)
frappe.db.set_value("Budget", budget.name, "fiscal_year", fiscal_year)
po = create_purchase_order(transaction_date=nowdate(), do_not_submit=True)
@@ -150,7 +158,9 @@ class TestBudget(unittest.TestCase):
budget = make_budget(budget_against="Project")
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
frappe.db.set_value(
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
)
project = frappe.get_value("Project", {"project_name": "_Test Project"})
@@ -213,7 +223,7 @@ class TestBudget(unittest.TestCase):
if month > 9:
month = 9
for _i in range(month + 1):
for i in range(month + 1):
jv = make_journal_entry(
"_Test Account Cost for Goods Sold - _TC",
"_Test Bank - _TC",
@@ -227,7 +237,9 @@ class TestBudget(unittest.TestCase):
frappe.db.get_value("GL Entry", {"voucher_type": "Journal Entry", "voucher_no": jv.name})
)
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
frappe.db.set_value(
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
)
self.assertRaises(BudgetError, jv.cancel)
@@ -243,7 +255,7 @@ class TestBudget(unittest.TestCase):
month = 9
project = frappe.get_value("Project", {"project_name": "_Test Project"})
for _i in range(month + 1):
for i in range(month + 1):
jv = make_journal_entry(
"_Test Account Cost for Goods Sold - _TC",
"_Test Bank - _TC",
@@ -258,7 +270,9 @@ class TestBudget(unittest.TestCase):
frappe.db.get_value("GL Entry", {"voucher_type": "Journal Entry", "voucher_no": jv.name})
)
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
frappe.db.set_value(
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
)
self.assertRaises(BudgetError, jv.cancel)
@@ -270,7 +284,9 @@ class TestBudget(unittest.TestCase):
set_total_expense_zero(nowdate(), "cost_center", "_Test Cost Center 2 - _TC")
budget = make_budget(budget_against="Cost Center", cost_center="_Test Company - _TC")
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
frappe.db.set_value(
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
)
jv = make_journal_entry(
"_Test Account Cost for Goods Sold - _TC",
@@ -300,7 +316,9 @@ class TestBudget(unittest.TestCase):
).insert(ignore_permissions=True)
budget = make_budget(budget_against="Cost Center", cost_center=cost_center)
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
frappe.db.set_value(
"Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop"
)
jv = make_journal_entry(
"_Test Account Cost for Goods Sold - _TC",
@@ -405,11 +423,13 @@ def make_budget(**args):
fiscal_year = get_fiscal_year(nowdate())[0]
if budget_against == "Project":
project_name = "{}%".format("_Test Project/" + fiscal_year)
project_name = "{0}%".format("_Test Project/" + fiscal_year)
budget_list = frappe.get_all("Budget", fields=["name"], filters={"name": ("like", project_name)})
else:
cost_center_name = "{}%".format(cost_center or "_Test Cost Center - _TC/" + fiscal_year)
budget_list = frappe.get_all("Budget", fields=["name"], filters={"name": ("like", cost_center_name)})
cost_center_name = "{0}%".format(cost_center or "_Test Cost Center - _TC/" + fiscal_year)
budget_list = frappe.get_all(
"Budget", fields=["name"], filters={"name": ("like", cost_center_name)}
)
for d in budget_list:
frappe.db.sql("delete from `tabBudget` where name = %(name)s", d)
frappe.db.sql("delete from `tabBudget Account` where parent = %(name)s", d)
@@ -431,18 +451,24 @@ def make_budget(**args):
budget.action_if_annual_budget_exceeded = "Stop"
budget.action_if_accumulated_monthly_budget_exceeded = "Ignore"
budget.budget_against = budget_against
budget.append("accounts", {"account": "_Test Account Cost for Goods Sold - _TC", "budget_amount": 200000})
budget.append(
"accounts", {"account": "_Test Account Cost for Goods Sold - _TC", "budget_amount": 200000}
)
if args.applicable_on_material_request:
budget.applicable_on_material_request = 1
budget.action_if_annual_budget_exceeded_on_mr = args.action_if_annual_budget_exceeded_on_mr or "Warn"
budget.action_if_annual_budget_exceeded_on_mr = (
args.action_if_annual_budget_exceeded_on_mr or "Warn"
)
budget.action_if_accumulated_monthly_budget_exceeded_on_mr = (
args.action_if_accumulated_monthly_budget_exceeded_on_mr or "Warn"
)
if args.applicable_on_purchase_order:
budget.applicable_on_purchase_order = 1
budget.action_if_annual_budget_exceeded_on_po = args.action_if_annual_budget_exceeded_on_po or "Warn"
budget.action_if_annual_budget_exceeded_on_po = (
args.action_if_annual_budget_exceeded_on_po or "Warn"
)
budget.action_if_accumulated_monthly_budget_exceeded_on_po = (
args.action_if_accumulated_monthly_budget_exceeded_on_po or "Warn"
)

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