Compare commits

...

487 Commits

Author SHA1 Message Date
Sahil Khan
fda7cbeca4 Merge branch 'v12-pre-release' into version-12 2020-02-28 15:06:03 +05:30
Sahil Khan
2fc58b3327 bumped to version 12.5.2 2020-02-28 15:26:03 +05:50
Deepesh Garg
0cee807dfb Merge pull request #20766 from deepeshgarg007/bank_reco_release
fix: Journal Entry not being fetched in Bank Reconciliation
2020-02-28 12:35:06 +05:30
Deepesh Garg
a51c56c4b3 fix: Remove debug statement 2020-02-28 12:32:18 +05:30
Deepesh Garg
d2f26e57d2 fix: Journal Entry not being fetched in Bank Reconciliation 2020-02-28 12:32:05 +05:30
Deepesh Garg
b7790c0394 fix: Item Wise report query fix (#20765) 2020-02-28 12:30:29 +05:30
Sahil Khan
2a1e9b542e Merge branch 'v12-pre-release' into version-12 2020-02-26 18:20:16 +05:30
Sahil Khan
8f458feafc bumped to version 12.5.1 2020-02-26 18:40:16 +05:50
Deepesh Garg
e116d8f819 Merge pull request #20738 from deepeshgarg007/bank_reco_fix_v12_pre
fix: Mandatory bank account error fix
2020-02-26 17:42:14 +05:30
Deepesh Garg
f3674ccc6c fix: SQL condition 2020-02-26 17:40:13 +05:30
Deepesh Garg
6f35a63f2d fix: Mandatory bank account error fix 2020-02-26 17:40:04 +05:30
Sahil Khan
b26fd04843 Merge branch 'v12-pre-release' into version-12 2020-02-20 18:26:58 +05:30
Sahil Khan
1b78d20d3c bumped to version 12.5.0 2020-02-20 18:46:57 +05:50
sahil28297
b203406d4c fix: proper release note version 2020-02-20 18:20:33 +05:30
Saqib
8903258362 fix: mandatory on hold comment for purchase invoice (#20668)
Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2020-02-20 12:30:35 +05:30
Saqib
2d2aa7d664 fix: check for available stock in product bundle's website warehouse (#20679)
* fix: check for available stock in product bundle's website warehouse

* test: earned leaves creation

* fix: minor change

Co-authored-by: Mangesh-Khairnar <mkhairnar10@gmail.com>
2020-02-20 12:22:01 +05:30
Nabin Hait
cd6b60df70 core: Added change log 2020-02-20 12:18:21 +05:30
Nabin Hait
b18790f5c2 Merge branch 'version-12-hotfix' into v12-pre-release 2020-02-19 19:19:36 +05:30
Mangesh-Khairnar
f6d7090f07 fix: earned leaves creation for zero maximum leaves (#20677) 2020-02-19 19:16:40 +05:30
Deepesh Garg
017d280877 Merge pull request #20664 from marination/stock-settings-query-v12-hotfix
fix: Set Query on warehouse fields in Stock Settings
2020-02-19 18:58:46 +05:30
marination
0119d15adb fix: Server side validation for Warehouses 2020-02-19 11:21:55 +05:30
Deepesh Garg
df6cb3c43b Merge pull request #20633 from scmmishra/tree-fix-qms
fix: filters for quality_procedure tree
2020-02-19 09:40:52 +05:30
marination
1ed737cf64 fix: Set Query on warehouse fields in Stock Settings 2020-02-18 21:45:52 +05:30
Deepesh Garg
c64e46fe67 Merge pull request #20483 from racitup/plaid-20343-fix
fix: Plaid fixes and enhancements
2020-02-18 18:03:16 +05:30
Nabin Hait
f579b0e3de fix: merge conflict 2020-02-18 17:49:20 +05:30
Deepesh Garg
b63c041aa4 feat: Group by AR/AP report (#20574)
* feat: Group by AR/AP report

* fix: Do not consider total row in charts

* fix: Subtotal row for last party
2020-02-18 16:09:37 +05:30
rohitwaghchaure
22f9a5f09f Merge pull request #20639 from nextchamp-saqib/pos-mode-of-pay-fix-v12
fix: disabled mode of payments fetches in sales invoices
2020-02-18 12:38:14 +05:30
rohitwaghchaure
e47875340e Merge pull request #20655 from marination/precision-mr-item-hotfix
fix: Stock Quantity not calculated on client side in Material Request…
2020-02-18 12:34:27 +05:30
marination
6f28383531 fix: Stock Quantity not calculated on client side in Material Request Items. 2020-02-18 11:08:16 +05:30
Deepesh Garg
95050702f1 Merge branch veersion-12-hotfix into plaid-20343-fix 2020-02-17 22:11:14 +05:30
Deepesh Garg
ae8f717fe5 Merge pull request #20640 from gavindsouza/updated-requirements
chore(requirements): Pin requirements
2020-02-17 22:05:26 +05:30
Gavin D'souza
f95ac99baa fix(travis): add lib cups for updated frappe requirements 2020-02-17 16:52:27 +05:30
Shivam Mishra
660b4d1e2f feat: show numeric values in item configurator (#20430) 2020-02-17 15:58:31 +05:30
thefalconx33
5bfebaf1c0 fix: disabled mode of payments fetches in sales invoices 2020-02-17 14:16:49 +05:30
Deepesh Garg
980e54c5f4 Merge pull request #20570 from Er-Naren719/hotfix-user-table-columns-updated
feat: columns under user table updated
2020-02-17 11:19:23 +05:30
Shivam Mishra
efbfeb2d89 fix: filters for quality_procedure tree 2020-02-17 10:50:05 +05:30
rohitwaghchaure
0676ed08b1 Merge pull request #20540 from rohitwaghchaure/fixed_purchase_receipt_time_out_error
fix: time out error while submitting the purchase receipt
2020-02-11 19:55:04 +05:30
rohitwaghchaure
e9946672e0 Merge branch 'version-12-hotfix' into fixed_purchase_receipt_time_out_error 2020-02-11 19:54:54 +05:30
rohitwaghchaure
6124f83e6e Merge pull request #20556 from ashish-greycube/patch-3
fix: backflush raw material based on - Material Transferred for Manufacture
2020-02-11 19:50:09 +05:30
Deepesh Garg
2b83debc72 Merge pull request #20564 from govindsmenokee/patch-4
fix: get_students not respecting the program
2020-02-11 17:03:24 +05:30
Er-Naren719
fc4cc9ab42 feat: column width increased for view attachments field (#314) 2020-02-11 10:17:34 +00:00
Deepesh Garg
cd19974d7a Merge pull request #20566 from vishdha/filter_serial_based_on_batch_v12
fix: filter serial no based on batch no
2020-02-11 13:44:54 +05:30
vishal
cde48a44cf fix: filter serial no based on batch no 2020-02-11 12:39:49 +05:30
Govind S Menokee
57d33f9ce6 fix: get_students not respecting the program
The get_students function is not taking into account the program for which the fee needs to be created. If a student is enrolled for multiple programs then the fee schedule pull up the wrong count of students.
2020-02-11 11:23:16 +05:30
Deepesh Garg
90a46acc0d Merge pull request #20557 from rohitwaghchaure/added_indexing_on_columns_to_fix_performance_issue
fix: added indexing on columns to fix performace issue
2020-02-11 10:13:24 +05:30
Deepesh Garg
60634cc829 Merge pull request #20252 from deepeshgarg007/group_by_sales_v12
feat: Group by item wise sales register
2020-02-10 22:20:21 +05:30
Rohit Waghchaure
a7c27596bb fix: added indexing on columns to fix performace issue 2020-02-10 15:30:22 +05:30
Deepesh Garg
b4e3146665 Merge pull request #20550 from nextchamp-saqib/so-update-items-warehouse-fix-v12
fix: mandatory warehouse wrror while updating items after submission
2020-02-10 12:09:38 +05:30
Ashish Shah
495ab6c7f2 fix: backflush raw material based on - Material Transferred for Manufacture
Hi @nabinhait ,
 
Issue : Manufacturing setting > Backflush Raw Material Based on “Material Transferred for Manufacture” doesn't fetch the actual raw material transferred qty. It fetches qty based on "BOM"

The issue is because @creamdory in PR #https://github.com/frappe/erpnext/pull/13384
commit : https://github.com/frappe/erpnext/pull/13384/files#diff-91f0ed661ef4b6e1f167fc7961b1a79b

```
changed from: if trans_qty and manufacturing_qty >= (produced_qty + flt(self.fg_completed_qty)):
to : if trans_qty and manufacturing_qty > (produced_qty + flt(self.fg_completed_qty)):
```
**'='** was added by her in the condition, which was not there before her commit.
Kindly except the fix for the issue.


https://github.com/frappe/erpnext/blob/develop/erpnext/stock/doctype/stock_entry/stock_entry.py#L1057

https://github.com/frappe/erpnext/pull/13384

https://github.com/frappe/erpnext/pull/13384/files#diff-91f0ed661ef4b6e1f167fc7961b1a79b

**before fix gif** :  Stock Entry = Manufacture shows raw material quantity as per BOM.

![FetchTransQtyError](https://user-images.githubusercontent.com/29812965/74123824-ffdd8600-4bf5-11ea-8873-95de24a7ef09.gif)

**after fix gi**f :  Stock Entry = "Manufacture" shows raw material quantity as per "Material Transfer for Manufacture".

![FetchTransQtyFix](https://user-images.githubusercontent.com/29812965/74123836-0c61de80-4bf6-11ea-86fb-d9619fd9b02b.gif)
2020-02-10 11:13:27 +05:30
Deepesh Garg
0e396a62b1 Merge pull request #20554 from ruchamahabal/fix_regional_data_v12
fix: patch for creating irs_1099 custom field (United States)
2020-02-10 09:08:55 +05:30
Rucha Mahabal
1343a4b755 fix: patch for creating irs_1099 custom field (United States) 2020-02-10 00:31:44 +05:30
rohitwaghchaure
ec45c096a0 fix: pricing rule not working on item groups (#20546) 2020-02-09 19:45:42 +05:30
thefalconx33
c7e523cee4 fix: mandatory warehouse wrror while updating items after submission 2020-02-09 12:21:01 +05:30
rohitwaghchaure
9e436336e2 Merge pull request #20542 from rohitwaghchaure/fixed_incorrect_material_request_warehouse_in_production_plan
fix: incorrect warehouse for material request in production plan
2020-02-07 17:43:32 +05:30
Rohit Waghchaure
a9205adfbd fix: test cases 2020-02-07 15:38:56 +05:30
Deepesh Garg
f5bff5f15d fix: Styling and minor fixes 2020-02-07 15:25:43 +05:30
Rohit Waghchaure
bbeacb9acf fix: incorrect warehouse for material request in production plan 2020-02-07 15:04:37 +05:30
Rohit Waghchaure
7027584391 fix: time out error while submitting the purchase receipt which has more than 100 serial nos 2020-02-07 14:41:00 +05:30
Deepesh Garg
372d4e2e05 Merge branch 'group_by_sales_v12' of github.com:deepeshgarg007/erpnext into group_by_sales_v12 2020-02-07 11:10:10 +05:30
Deepesh Garg
bdfa2ff33a fix: Do not calculate total for rate 2020-02-07 11:09:43 +05:30
Deepesh Garg
787b31674a Merge pull request #20534 from rohitwaghchaure/procurement_tracker_not_working_for_special_char_company_name_v12_hotfix
fix: Procurement Tracker report not working
2020-02-07 10:44:13 +05:30
Rohit Waghchaure
0eb9f7408e fix: Procurement Tracker report not working 2020-02-06 14:38:51 +05:30
Deepesh Garg
5c96415eb5 Merge pull request #20530 from nextchamp-saqib/mv-fix-v12
fix: typo; serial no doesn't have amc start date
2020-02-06 13:58:29 +05:30
thefalconx33
d9f8347fc8 fix: typo; serial no doesn't have amc start date 2020-02-06 12:58:48 +05:30
Deepesh Garg
2a48fe6ce6 Merge pull request #20524 from deepeshgarg007/bank_account_label__v12
Bank account label  v12
2020-02-05 18:04:12 +05:30
deepeshgarg007
3ed574532d fix: filter 2020-02-05 18:02:31 +05:30
deepeshgarg007
9f58e59a2c fix: Label and UX fixes while creating payment entry against customer 2020-02-05 18:02:19 +05:30
Deepesh Garg
23c6d6cf16 Merge pull request #20522 from rohitwaghchaure/picklist_nonetype_error
fix: unsupported operand type(s) for += 'int' and 'NoneType'
2020-02-05 17:44:46 +05:30
Rohit Waghchaure
8e0a9e8748 fix: unsupported operand type(s) for += 'int' and 'NoneType' 2020-02-05 16:17:16 +05:30
Deepesh Garg
67dbeee7b2 fix: Add total row 2020-02-05 15:34:08 +05:30
Parth J. Kharwar
b4a0c773ae fix: half day leave date value reset (#20488)
* fix: full day leaves not tagged as half day in attendance

* chore: code cleanup for half day date value set
2020-02-05 15:00:58 +05:30
Deepesh Garg
694f57fbb4 Merge pull request #20521 from deepeshgarg007/fixnancial_query_fix_v12
fix: SQL query in financial statements
2020-02-05 12:33:06 +05:30
Deepesh Garg
0f90b870fb fix: SQL query in financial statements 2020-02-05 12:30:15 +05:30
Nabin Hait
bd5b37dbb7 Merge branch 'v12-pre-release' into version-12 2020-02-03 19:00:36 +05:30
Nabin Hait
7e93e87244 bumped to version 12.4.3 2020-02-03 19:20:36 +05:50
Deepesh Garg
02f4aa6db6 fix: Unable to submit landed cost voucher (#20494)
* fix: Unable to submit landed cost voucher

* fix: Test case for multiple landed cost voucher against a Purchase receipt

* fix: Test Case
2020-02-03 18:56:43 +05:30
Deepesh Garg
ade2c36123 fix: Unable to submit landed cost voucher (#20494)
* fix: Unable to submit landed cost voucher

* fix: Test case for multiple landed cost voucher against a Purchase receipt

* fix: Test Case
2020-02-03 18:54:35 +05:30
Pranav Nachnekar
3ef80f2d2e fix: disallow quick entry for doctypes with tree view (#20453)
* fix: imporer escaping

* fix: disallow quick entry for doctypes with tree view
2020-02-03 17:05:30 +05:30
Himanshu
85c6480b41 fix(Report): Quality Review report sql fix (#20425)
* fix: report fix

* fix: add QM permission

* fix: add QM permission
2020-02-03 16:16:42 +05:30
Saqib
f3c94315c3 feat: add tax category in pos profile (#20414)
* feat: add tax category in pos profile

* fix: review fixes
2020-02-03 15:53:22 +05:30
Saqib
a4219f1cfe fix: gst permission for gst settings & hsn code (#20501)
* fix: gst permission for gst settings & hsn code

* Fix: Typo

Co-authored-by: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com>
2020-02-03 15:40:53 +05:30
Deepesh Garg
831a7ddd6f fix: Minor fixes 2020-02-01 23:15:21 +05:30
Parth J. Kharwar
43886ca016 fix: employee checkin doctype time permissions (#20473) 2020-01-31 14:37:56 +05:30
rohitwaghchaure
61b4244837 Merge pull request #20479 from deepeshgarg007/finance-book-filter-new-v12
fix: Do not show any finance book record if no finance book filter is applied
2020-01-31 13:19:49 +05:30
Deepesh Garg
6871979acc Merge pull request #20470 from alyf-de/version-12-hotfix
fix(regional): byte strings in DATEV Report
2020-01-31 11:20:51 +05:30
Deepesh Garg
bb7cf81d52 fix: Cash flow filter fix 2020-01-31 11:18:26 +05:30
Deepesh Garg
9826291c52 fix: Filtering fixes in financial statement 2020-01-31 11:18:13 +05:30
racitup
08661250d2 Ignore codacy SQL injection warning (internal code only) and add copyright notice 2020-01-30 15:22:34 +00:00
racitup
814001a90f fix: attempt at pymysql InternalError 1054 about clearance_date in field list when removing payments from bank transactions 2020-01-30 15:22:34 +00:00
racitup
eef73a0d92 manually added patch for bank reconciliation fields since develop branch was in a different place #20380 2020-01-30 15:22:34 +00:00
racitup
a1e3202054 fix: Bank Reconciliation Bank Account and Bank Account No field names 2020-01-30 15:22:34 +00:00
racitup
bee017e17c fix: Plaid transaction import order, transaction_id duplicate check, added transaction category tags 2020-01-30 15:22:34 +00:00
racitup
a054508211 fix: Plaid automatic_synchronization TypeError on filter & add info log message #20343 2020-01-30 15:22:34 +00:00
racitup
feaa82a8ea fix: KeyError about bank_account_no due to non-existent field: #20343 2020-01-30 15:22:34 +00:00
racitup
a175e06149 fix: pymysql.err.InternalError about t2.bank_account_no due to removal of field from Journal Entry Account table: #20343 2020-01-30 15:22:34 +00:00
Deepesh Garg
ba4d9469ff fix: Do not show any finance book record if no finance book filter is applied 2020-01-30 15:41:44 +05:30
Deepesh Garg
54c6f91dde Merge pull request #20474 from ParthKharwar/hotfix-brand-breadcrumb
fix: rename breadcrumb for Brand DocType from Selling to Stock
2020-01-30 13:14:21 +05:30
Parth Kharwar
e552e958de fix: rename breadcrumb for Brand DocType from Selling to Stock 2020-01-30 12:35:02 +05:30
Raffael Meyer
7524ecbc59 fix #20469 2020-01-30 00:08:25 +01:00
Deepesh Garg
be2ca5f8cc Merge pull request #20460 from 0Pranav/fix-supplier-quotation-button-v12
fix: missing plus button in request for quotaion for supplier quotation
2020-01-29 10:45:32 +05:30
0Pranav
d4d641a07e fix: missing plus button in request for quotaion for supplier quotation 2020-01-29 09:36:48 +05:30
rohitwaghchaure
8e5b812a97 fix: incorrect work order qty for sub assembly items (#20448) 2020-01-28 14:34:54 +05:30
Nabin Hait
df94f0565e fix: cannot complete task if dependent task are not completed / cancelled (#20434) 2020-01-28 14:08:48 +05:30
Pranav Nachnekar
f2838c4a13 fix: discounting not applied on sales invoice created by subscriptions (#20432)
* fix: imporer escaping

* fix: discounting not applied on sales invoice created by subscriptions
2020-01-28 12:52:42 +05:30
Marica
fe56c7ce39 fix: Column 'project' in where clause is ambiguous (#20439)
* fix: Column 'project' in where clause is ambiguous

* fix: Fixed alias in query
2020-01-28 12:44:03 +05:30
Deepesh Garg
29ecbde445 Merge pull request #20446 from Alchez/v12-driver-address-fetch
fix: only fetch driver address if not set (v12)
2020-01-28 09:20:53 +05:30
Deepesh Garg
611f212aa4 Merge pull request #20443 from fproldan/fix_sqlinjection_hotfix_v12
fix: SQL Injection in get_product_list_for_group method
2020-01-28 09:18:11 +05:30
Rohan Bansal
6fbafa1924 fix: only fetch driver address if not set 2020-01-27 18:04:33 +05:30
NahuelOperto
875bac8bb9 Fix sql injection 2020-01-27 08:58:01 -03:00
Saqib
b4b410f1d2 refac: filters and columns of fixed asset register report (#20420) 2020-01-27 16:06:15 +05:30
deepeshgarg007
eec0ee83e2 fix: Changes in total row display 2020-01-27 15:51:20 +05:30
Deepesh Garg
148951e6f3 fix: Finance book filtering in financial statements (#20411)
* fix: Finance book filtering in financial statements

* fix: Use IS NULL instead of ifnull
2020-01-27 15:18:45 +05:30
Saqib
612e3b77fd fix: incorrect status for fraction of outstanding amount (#20370) 2020-01-27 14:23:05 +05:30
Deepesh Garg
a60849f6ab Merge pull request #20415 from hrwX/customer_primary_addr_v12
fix(Customer): Change `primary_address` fieldtype to Text
2020-01-27 12:33:38 +05:30
deepeshgarg007
6f27e97980 fix: Add group by functionality to purchase register 2020-01-27 08:49:52 +05:30
deepeshgarg007
8d9145aaac fix: Code cleanup and commonification 2020-01-27 08:49:42 +05:30
Himanshu Warekar
25a7330db0 fix: change primary addr fieldtype to Text 2020-01-24 17:36:59 +05:30
Saqib
92c999afcb fix: wrong outstanding invoices fetched against employee (#20374) 2020-01-24 16:23:05 +05:30
Anurag Mishra
9e3dc25b1c fix: Duplicate Attendance Due Wrong Date format (#20389) 2020-01-24 16:14:38 +05:30
Rucha Mahabal
2a3cd7d601 fix(Healthcare): disabled Lab Test Template shown as Enabled in List View (#20379)
* fix (Healthcare): disabled Lab Test Template shown as enabled in List View

* fix: remove custom disabled button and unhide disabled field
2020-01-24 16:11:16 +05:30
Marica
3ca67ceebb fix: Product Page non-stock item status (#20384) 2020-01-24 15:52:12 +05:30
Rucha Mahabal
245fc49089 fix: healthcare settings registration fee NoneType error (#20396) 2020-01-24 15:50:40 +05:30
rohitwaghchaure
78199dbf0a Merge pull request #20399 from rohitwaghchaure/fixed_serial_no_button_not_working_v12_hotfix
fix: add serial no button not working
2020-01-24 13:49:25 +05:30
Deepesh Garg
2ac33c9ce9 Merge pull request #20402 from deepeshgarg007/general_ledger_sort_v12
fix: Order GL entries by creation time in General ledger
2020-01-24 13:19:56 +05:30
Deepesh Garg
34cd035d8c Merge pull request #20392 from rohitwaghchaure/unlink_reference_name_from_batch_on_cancel_of_stock_transactions
fix: unlink references from batch on cancellation of stock transactions
2020-01-23 22:41:21 +05:30
deepeshgarg007
ba4f565ca3 fix: Order GL entries by creation time in General ledger 2020-01-23 17:48:41 +05:30
Rohit Waghchaure
5860427bc5 delete the auto created batch 2020-01-23 17:43:30 +05:30
Rohit Waghchaure
89f42eef49 fix: add serial no button not working 2020-01-23 15:53:45 +05:30
Deepesh Garg
eacbfa15c0 Merge pull request #20385 from rohitwaghchaure/fixed_lead_date_comparision_issue
fix: lead date comparison issue
2020-01-23 15:23:28 +05:30
Deepesh Garg
5d45c2c184 Merge pull request #20387 from rohitwaghchaure/lead_showing_two_times_in_the_report
fix: lead details duplicate entries
2020-01-23 15:21:11 +05:30
Deepesh Garg
b24b0378ea Merge pull request #20382 from nextchamp-saqib/small-fix-asset-v12
fix: tuple index out of range error
2020-01-23 15:02:29 +05:30
Rohit Waghchaure
144012a5de fix: unlink references from batch on cacnellation of stock transactions 2020-01-23 12:42:42 +05:30
rohitwaghchaure
5fb4027375 Merge pull request #20376 from rohitwaghchaure/zero_division_qty_error_while_completing_fg_entry_v12_pre_release
fix: Zero division error while making finished good entry against the…
2020-01-22 17:01:21 +05:30
rohitwaghchaure
3fa65f1363 Merge pull request #20375 from rohitwaghchaure/zero_division_qty_error_while_completing_fg_entry
fix: Zero division error while making finished good entry against the…
2020-01-22 17:00:44 +05:30
Rohit Waghchaure
79f630661a fix: lead details duplicate entries 2020-01-22 16:53:30 +05:30
Rohit Waghchaure
61b9fe6a81 fix: lead date comparison issue 2020-01-22 14:43:37 +05:30
thefalconx33
f38d9d8f0d fix: tuple index out of range error 2020-01-22 12:24:03 +05:30
Rohit Waghchaure
3a67daa1fd fix: Zero division error while making finished good entry against the work order 2020-01-21 19:25:27 +05:30
Rohit Waghchaure
813726b415 fix: Zero division error while making finished good entry against the work order 2020-01-21 19:22:27 +05:30
rohitwaghchaure
87fe2143be fix: not able to import chart of account if parent account is missing (#20367) 2020-01-21 15:32:12 +05:30
Saqib
c759b06f16 fix: account not added to child company (#20364)
* fix: account not added to child company

* fix: removed print

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2020-01-21 15:26:46 +05:30
Chinmay Pai
c32249a72f fix: Set Quotation expired if not Ordered or Lost (#20365)
Co-authored-by: Chinmay Pai <chinmaydpai@gmail.com>

Co-authored-by: KanchanChauhan <angel143.dr@gmail.com>
2020-01-21 14:12:49 +05:30
Nabin Hait
7cd6022a0b Merge branch 'v12-pre-release' into version-12 2020-01-21 13:07:27 +05:30
Nabin Hait
67274d01e8 bumped to version 12.4.2 2020-01-21 13:27:26 +05:50
Nabin Hait
19d7e43b90 fix: Don't fetch price list rate on change of qty (#20360) 2020-01-21 13:04:30 +05:30
Nabin Hait
05f4be69f4 fix: Don't fetch price list rate on change of qty (#20362) 2020-01-21 13:04:26 +05:30
Mangesh-Khairnar
541881162a fix: calculate remaining leave balance (#20342)
* fix: calculate remaining leave balance

* fix: nonetype issue in the total leaves calculation
2020-01-20 19:42:49 +05:30
Sahil Khan
c8884257b9 Merge branch 'v12-pre-release' into version-12 2020-01-20 18:02:31 +05:30
Sahil Khan
4674fec320 bumped to version 12.4.1 2020-01-20 18:22:31 +05:50
rohitwaghchaure
c7f0ab8ed6 fix: incorrect number of gl entries issue (#20351) 2020-01-20 17:53:44 +05:30
rohitwaghchaure
19c5e031a9 fix: incorrect number of gl entries issue (#20350) 2020-01-20 17:52:53 +05:30
Marica
8b943af911 fix: 'get_additonal_costs' is not defined (#20349)
* fix: 'get_additonal_costs' is not defined

* fix: Re-added get_items on Work order change.
2020-01-20 15:47:47 +05:30
Marica
863eb86a1d fix: 'get_additonal_costs' is not defined (#20345)
* fix: 'get_additonal_costs' is not defined

* fix: Re-added get_items on Work order change.
2020-01-20 15:46:50 +05:30
Nabin Hait
e5fbebe126 fix: deprecated fetching item price based on min_qty (#20348) 2020-01-20 15:45:09 +05:30
Nabin Hait
45be9fe416 fix: deprecated fetching item price based on min_qty (#20346) 2020-01-20 15:44:48 +05:30
Nabin Hait
1596352585 fix: close_opportunity_after_days field is in selling settings (#20334) 2020-01-17 15:59:02 +05:30
Nabin Hait
4b893b1d51 fix: Plaid TypeError in add_bank_accounts (#20336) 2020-01-17 15:57:43 +05:30
Parth J. Kharwar
d85e144944 chore: changed employee contact field name (#20227) 2020-01-17 11:47:49 +05:30
Rohan
4dfff5a271 fix: handle default value for batch size in BOM operation (#20327) 2020-01-17 11:46:00 +05:30
Pranav Nachnekar
c2b9598966 fix: imporer escaping (#20329) 2020-01-17 11:45:03 +05:30
Vishal Dhayagude
d16e7c096b fix: salary structure assignment filter employee based on company (#20319)
* fix: pick company from employee salary structure

* fix: Salary structure assignment fetch company from enmployee

* Revert "fix: Salary structure assignment fetch company from enmployee"

This reverts commit ab2da691c79646d6d095f347ea3e273f466ee34f.

* fix: Salary structure assignment fetch company from enmployee

* fix: filter on company for salary structure assignment

* fix: minor changes

* fix: minor changes

* fix: added company to salary strucutre assignment
2020-01-17 11:44:20 +05:30
sahil28297
d5676a87a8 Merge pull request #20331 from 0Pranav/version-12
fix: imporer escaping
2020-01-16 17:51:32 +05:30
0Pranav
73dff8993a fix: imporer escaping 2020-01-16 17:38:11 +05:30
Sahil Khan
0ef799dff8 Merge branch 'v12-pre-release' into version-12 2020-01-16 14:30:35 +05:30
Sahil Khan
e8476ef42a bumped to version 12.4.0 2020-01-16 14:50:35 +05:50
Himanshu
5511912251 fix: don't hide primary_address_and_contact_detail (#20321) 2020-01-16 13:39:03 +05:30
Saqib
514d3c37b9 fix: hide total amount field from journal entry PF (#20325) 2020-01-16 13:38:21 +05:30
Nabin Hait
9fef6e1b68 docs: Added change log for v12.4.0 (#20326) 2020-01-16 13:37:46 +05:30
Nabin Hait
37c51f5913 fix: Multiple fixes based on testing on pre-release branch (#20300)
* fix: Multiple fixes based on testing on pre-release branch

* fix: reload hr settings
2020-01-16 13:37:30 +05:30
Nabin Hait
7721954bbb fix: Multiple fixes based on testing on pre-release branch (#20303)
* fix: Multiple fixes based on testing on pre-release branch

* fix: reload hr settings
2020-01-16 13:37:20 +05:30
Nabin Hait
7e33d875e0 Revert "fix: incorrect required qty for subcontracting purchase receipt (#20288)" (#20323)
This reverts commit b65b525c44.
2020-01-16 13:02:40 +05:30
Marica
0a50088a0e fix: Applied query on PO Supplier popup field in Material Request. (#20232) 2020-01-15 19:24:10 +05:30
Marica
6ba6ba27bd fix: Missing argument in status updater (#20284) 2020-01-15 19:22:21 +05:30
Saqib
611e23c149 fix: make jv depreciations only if calculate depr is checked (#20283) 2020-01-15 19:05:42 +05:30
sahil28297
89affd8d09 fix(patch): reload tax category (#20307) 2020-01-15 18:58:09 +05:30
sahil28297
ab2e52ca07 fix(patch): reload tax category (#20309) 2020-01-15 18:57:40 +05:30
sahil28297
8dfd5535f1 fix(patch): do not append taxes to template if account name is not set (#20311) 2020-01-15 18:57:20 +05:30
sahil28297
dc0ea3fdb0 fix(patch): do not append taxes to template if account name is not set (#20310) 2020-01-15 18:57:08 +05:30
rohitwaghchaure
b65b525c44 fix: incorrect required qty for subcontracting purchase receipt (#20288) 2020-01-15 16:37:10 +05:30
Saqib
8c45ae73b3 fix: get existing payment req amount only from unpaid req (#20290) 2020-01-15 16:36:19 +05:30
rohitwaghchaure
4872417f86 fix: incorrect number of GL Entries error in stock entry (#20298) 2020-01-15 16:35:15 +05:30
rohitwaghchaure
fed9e2861c fix: incorrect number of GL Entries error in stock entry (#20297) 2020-01-15 16:35:02 +05:30
Pranav Nachnekar
c50f08a23a fix: remove debugger statement (#20294)
introduced in https://github.com/frappe/erpnext/pull/20222
2020-01-15 14:49:42 +05:30
Pranav Nachnekar
6e115638a1 fix: remove debugger statement (#20295)
backport of https://github.com/frappe/erpnext/pull/20294
2020-01-15 14:49:28 +05:30
Saqib
2d37bbedaa fix: auto cancel if movement exists (#20268)
Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2020-01-14 12:42:43 +05:30
rohitwaghchaure
00f6f114e7 Merge pull request #20278 from rohitwaghchaure/fixed_report_stock_and_account_value_comparison_v12_pre_release
fix: filter issue for the stock and account value comparision report
2020-01-14 12:19:04 +05:30
rohitwaghchaure
437be1162e Merge pull request #20277 from rohitwaghchaure/fixed_report_stock_and_account_value_comparison_v12_hotfix
fix: filter issue for the stock and account value comparision report
2020-01-14 12:18:50 +05:30
Rohit Waghchaure
ca4789c9f7 fix: filter issue for the stock and account value comparision report 2020-01-14 12:17:27 +05:30
Rohit Waghchaure
e3b6a14ab1 fix: filter issue for the stock and account value comparision report 2020-01-14 12:15:06 +05:30
Saqib
eb7893768b fix: payment entry can be created against on hold PI (#20271) 2020-01-14 12:07:30 +05:30
Saqib
6e1ef4f5c2 fix: gl not generated on manual asset creation (#20266) 2020-01-14 11:38:00 +05:30
Saqib
d56bc81daf fix: gl not generated on manual asset creation (#20267) 2020-01-14 11:36:47 +05:30
Deepesh Garg
7d7027f47c fix: Remove patch to set automatic tax fetching from item tax template (#20235)
* fix: Remove patch to set automatic tax fetching from item tax template

* fix: Remove duplicate patch
2020-01-13 15:09:21 +05:30
Deepesh Garg
a14f72590d fix: Remove patch to set automatic tax fetching from item tax template (#20236)
* fix: Remove patch to set automatic tax fetching from item tax template

* fix: Remove duplicate patch
2020-01-13 15:09:16 +05:30
Deepesh Garg
7086ecb3b0 Merge pull request #20246 from nextchamp-saqib/asset-cancel-fix-v12
fix: auto cancel if movement exists
2020-01-13 15:07:57 +05:30
Saqib
4b401f0573 Merge pull request #20263 from nextchamp-saqib/customer-jv-fix-v12-pre
fix: remove default customer as party type
2020-01-13 14:12:22 +05:30
thefalconx33
5beee8af58 fix: remove default customer as party type 2020-01-13 13:51:17 +05:30
Deepesh Garg
8508ace50e Merge pull request #20258 from nextchamp-saqib/revery-hv-v12
fix: remove default customer as party type
2020-01-13 13:49:20 +05:30
thefalconx33
c52ef56875 fix: remove default customer as party type 2020-01-13 12:45:08 +05:30
deepeshgarg007
4dfe8ab483 fix: Remove debug param 2020-01-12 22:15:25 +05:30
deepeshgarg007
ea5e0a9d5b fix: Grand total query fix 2020-01-12 21:56:31 +05:30
deepeshgarg007
30111e6403 fix: Remove group-by item 2020-01-12 21:56:22 +05:30
deepeshgarg007
e5a572a4a8 fix: Group by sales register report 2020-01-12 21:56:12 +05:30
thefalconx33
83ed7df8cd fix: auto cancel if movement exists 2020-01-11 14:20:18 +05:30
Deepesh Garg
97e93c6257 Merge pull request #20238 from deepeshgarg007/hsn_template_v12
fix: Item tax template fetching from HSN Code
2020-01-10 21:45:22 +05:30
Deepesh Garg
f7cd8c2702 Merge pull request #20239 from deepeshgarg007/hsn_template_v12
fix: Item tax template fetching from HSN Code
2020-01-10 21:43:26 +05:30
deepeshgarg007
f67b3f8a79 fix: Item tax template fetching from HSN Code 2020-01-10 15:04:34 +05:30
Nabin Hait
8356d214e1 Merge branch 'version-12-hotfix' into v12-pre-release 2020-01-09 15:09:20 +05:30
rohitwaghchaure
64f3577148 feat: report to show difference between stock and account value (#20226) 2020-01-09 15:05:26 +05:30
Marica
ff3ff9a3c2 fix: Employee name in Report trial balance for party (#20224)
* fix: Employee name in Report trial balance for party

* fix: Add account filter in trial balance for party report

Co-authored-by: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com>
2020-01-09 13:34:30 +05:30
Pranav Nachnekar
03c1396fc7 fix: Parent Item of Product Bundle should not appear in dialog (#20222)
* fix: add new delivery note button in Sales Order

* fix: parent item should not appear in raw material request dialog
2020-01-09 13:31:53 +05:30
Pranav Nachnekar
4479b93c1a fix: escape % in customer name (#20203)
* fix: add new delivery note button in Sales Order

* fix: escape % in customer name

* Update sales_order.js

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2020-01-09 12:22:11 +05:30
Anurag Mishra
da82edf711 fix: submit salary is not showing after creating slary slip in payroll (#20225) 2020-01-09 12:06:14 +05:30
Saqib
7b8bf4f4d4 Merge pull request #20213 from nextchamp-saqib/pay-entry-v12
fix: paid amount gets overwritten by get_outstanding_invoices
2020-01-07 13:33:16 +05:30
thefalconx33
07c915d00b fix: paid amount gets overwritten by get_outstanding_invoices 2020-01-07 13:14:01 +05:30
Marica
75b62cdd9f fix: Added description and title to supplier selection popup in Material Request. (#20180) 2020-01-07 13:06:13 +05:30
Don-Leopardo
54f2d53522 fix: get_item_price not working properly (#20206)
* fix: min_qty not working without party and valid_from not being used to order results

* fix: fetch price on item qty change
2020-01-07 11:35:56 +05:30
Deepesh Garg
55bdaae3ee feat: Validity for Item taxes (#20136)
* feat: Validity for Item taxes

* fix: Add HSN wise taxes

* fix: Sort taxes based on validity

* fix: Validation for item tax template and filters based on validity

* fix: Add missing semicolon

* fix: Validate tax template only if item code available

* fix: Do not validate or filter item tax template if no item taxes applied

* fix: Consider item group for validating taxes

* fix: Test cases for item tax  validation

* fix: Item tax template filtering fixes

* fix: Add missing semicolon

* fix: Remove unnecessary query
2020-01-07 11:31:19 +05:30
sahil28297
6bbfce13fe fix(item_tax_template): fetch parent account if not set (#20197) 2020-01-07 11:30:18 +05:30
Pranav Nachnekar
0980ebe93e fix: add new delivery note button in Sales Order (#20200)
* fix: add new delivery note button in Sales Order

* fix: removed debugger

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2020-01-07 11:29:45 +05:30
Rohan
ded5a255af fix: integer UOM check in transactions (#20177) 2020-01-07 11:24:02 +05:30
Anurag Mishra
13c29aeec4 fix: loan deduction during creation of bank entry in payroll (#20194) 2020-01-07 11:13:58 +05:30
rohitwaghchaure
cf261d0788 Merge pull request #20196 from rohitwaghchaure/fixed_party_type_in_payment_request_hotfix
fix: incorrect party type in payment request
2020-01-06 15:16:30 +05:30
Rohit Waghchaure
3074679d7e fix: party type in payment request 2020-01-06 15:09:09 +05:30
rohitwaghchaure
a037f9d55e Merge pull request #20171 from nabinhait/inter-company-serial-no-outgoing-rate-v12
fix: Get outgoing rate of serial no from SLE if serial no already transferred to another company
2020-01-06 12:06:08 +05:30
rohitwaghchaure
3530d0d7c9 fix: incorrect valuation rate for finished good entry (#20166) 2020-01-06 11:51:36 +05:30
Deepesh Garg
3da9967fa8 Merge pull request #20178 from Alchez/fix-v12-item-price-list-view
feat: show item name in Item Price list view (v12)
2020-01-06 08:06:07 +05:30
Himanshu
f276e8d6a1 fix(plaid): change json structure (#20190) 2020-01-06 01:01:37 +05:30
Rohan
9e0d9aa947 feat: show item name in Item Price list view (#20156) 2020-01-03 15:21:58 +05:30
Marica
df363d7dd6 Merge pull request #20173 from nextchamp-saqib/item-min-qty-v12
ux: add description for minimum purchase qty
2020-01-03 12:54:45 +05:30
thefalconx33
81e2f2a45f ux: add description for minimum purchase qty 2020-01-02 19:16:36 +05:30
Nabin Hait
255361ba92 fix: Get outgoing rate of serial no from SLE if serial no already transferred to another company 2020-01-02 19:01:48 +05:30
rohitwaghchaure
67bcfde3de Merge pull request #20168 from rohitwaghchaure/fix_pricing_rule_issue_for_ignore_pricing_rule
fix: ignore pricing rule for other item group
2020-01-02 17:32:43 +05:30
Rohit Waghchaure
b6351b4ca0 fix: ignore pricing rule for other item group 2020-01-02 17:29:50 +05:30
Deepesh Garg
c5a8d33374 Merge pull request #20162 from deepeshgarg007/general_ledger_print_v12
fix: Show closing row in general ledger print
2020-01-02 17:06:05 +05:30
deepeshgarg007
f4589da806 fix: Show closing row in general ledger print 2020-01-02 12:26:12 +05:30
Rucha Mahabal
c5cd7cd65d fix(Subscription): pass start_date while computing next_schedu… (#20160) 2019-12-31 19:15:48 +05:30
Anurag Mishra
a5e56dfb6f fix: set currency to company default currency (#20158) 2019-12-31 17:23:25 +05:30
Saqib
adb35d8703 fix: don't show transfer button if already items are supplied (#20155) 2019-12-31 17:20:07 +05:30
Deepesh Garg
db4f3d98ab Merge pull request #20150 from nextchamp-saqib/rounded-total-ss-v12
feat: added provision to disable rounded total for salary slips
2019-12-31 17:03:11 +05:30
thefalconx33
cd2899f429 feat: added provision to disable rounded total for salary slips 2019-12-31 15:29:36 +05:30
thefalconx33
8f6a6e8d2a feat: added provision to disable rounded total for salary slips 2019-12-31 14:35:03 +05:30
Anurag Mishra
fd68a682ca fix(refactor): loan in HRMS (#20023)
* fix: update laon on salary slip submission and Cancelation

* fix(refactor): Loan in HRMS

* fix: Changes requested

* Update loan.py

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2019-12-31 14:01:22 +05:30
Saqib
25fd2743a8 fix: party account currency not fetched from account for SO (#20147) 2019-12-31 13:55:34 +05:30
Saqib
826989afda fix: none type object updates AR report row (#20148) 2019-12-31 13:46:39 +05:30
Marica
10622aee7f fix: Field 'other_charges_calculation' column type changed. (#20142) 2019-12-30 22:20:27 +05:30
Anurag Mishra
26e86e7576 fix: added extra condition (#20139) 2019-12-30 16:17:10 +05:30
Rucha Mahabal
efa7d5c831 fix: format currency field in bank and cash payment voucher print format (#20138) 2019-12-30 15:18:02 +05:30
rohitwaghchaure
55cf2477cd fix: incorrect batch fetched for the serialized items (#20118) 2019-12-30 13:27:10 +05:30
ci2014
5c144c992e Skip validate_duplicate_apply_on if not necessary (#20128)
Skip the validation of duplicate fields if the type is transaction, for example.
2019-12-30 11:50:43 +05:30
rohitwaghchaure
2fcc51dece fix: service item's cost showing incorrect amount in stock entry (#20105) 2019-12-30 11:42:01 +05:30
Deepesh Garg
e76670562c Merge pull request #20124 from nextchamp-saqib/so-update-items-hfix
fix: don't allow deletion of items which has work order assigned to it
2019-12-28 21:01:47 +05:30
Deepesh Garg
e1aa48968e Merge pull request #20126 from marination/stock-module-desk-hotfix
chore: Added Reports to Stock Module Desk
2019-12-28 17:45:31 +05:30
marination
2faa8f92be chore: Added Reports to Stock Module Desk 2019-12-27 17:21:08 +05:30
thefalconx33
82c5a2bf45 fix: don't allow deletion of items which has work order assigned to it 2019-12-27 17:08:57 +05:30
Marica
ed386376dc fix: Removed unneccesary Duplicate Entry Error. (#20121) 2019-12-27 16:53:09 +05:30
Marica
65353e5590 fix: Show both warehouse columns in Stock Entry Grid view. (#20114) 2019-12-27 15:30:47 +05:30
Saqib
aab1fb0d6a fix: unpaid invoices are created even if current invoice is paid (#20082) 2019-12-27 13:02:33 +05:30
Deepesh Garg
2dec923740 fix: Patch incorrect GST category in invoices (#20085)
* fix: Patch to set GST category for unregistered invoice

* fix: Move patch up in line

* fix: Remove unwanted patch statements
2019-12-27 12:58:38 +05:30
Saqib
6ea509f7f4 feat: allow adding and deleting of items in submitted SO & PO (#19912)
* feat: allow adding of items after quotation submission

* feat: allow deletion of items from submitted SO & PO

* fix: case when items are added and deleted at once

* fix: add test cases
* For deletion of items while Updating Items after submitting PO & SO
2019-12-27 12:56:17 +05:30
Sammish Thundiyil
dfdd684fbf modified: erpnext/hr/doctype/repayment_schedule/repayment_schedule.json (#20112) 2019-12-27 12:52:40 +05:30
rohitwaghchaure
b299026280 fix: incorrect reorder level in stock balance report (#20110) 2019-12-27 12:36:14 +05:30
Rohan
3d2e61eef3 fix: Add Serial No button prompt (#20098) 2019-12-27 12:34:43 +05:30
rohitwaghchaure
47eda0fa6d fix: incorrect validation for scrap items (#20108) 2019-12-27 12:21:10 +05:30
Mangesh-Khairnar
8ec1d8d5da fix: fetch opening accumulated depreciation (#20096) 2019-12-27 12:14:27 +05:30
rohitwaghchaure
6adf617a72 Merge pull request #20078 from nabinhait/rounding-adjustment-v12
fix: rounding adjustment while both inclusive tax and discount amount present
2019-12-27 11:52:10 +05:30
Deepesh Garg
7c7291ed4f Merge pull request #20088 from nextchamp-saqib/pay-reco-hfix
fix: undefined dr_or_cr_notes in case of party type Employee
2019-12-27 08:12:33 +05:30
rohitwaghchaure
a169292f6e Merge pull request #20103 from deepeshgarg007/travis-fix-v12
fix: Travis(v12)
2019-12-26 22:51:13 +05:30
thefalconx33
5869757860 fix: travis failing for leave application test 2019-12-26 21:52:54 +05:30
Deepesh Garg
6fefdb5b18 Merge pull request #20092 from nextchamp-saqib/account-period-hfix
fix: only show doctypes which impact accounting in accounting period
2019-12-26 15:23:54 +05:30
Saqib
8c08db33d7 Merge pull request #20094 from prssanna/grid-fix-v12
fix: wrong items in table being deleted
2019-12-26 14:54:16 +05:30
prssanna
bc15ea68b8 fix: wrong items in table being deleted 2019-12-26 14:44:47 +05:30
thefalconx33
ee28663836 fix: undefined dr_or_cr_notes in case of party type Employee 2019-12-26 14:43:03 +05:30
thefalconx33
c522df8f9d fix: only show doctypes which impact accounting in accounting period 2019-12-26 13:56:36 +05:30
Himanshu
d0e39e6fac fix: remove quote (#20077) 2019-12-25 15:16:35 +05:30
Nabin Hait
4c4da06a71 fix: rounding adjustment while both inclusive tax and discount amount present 2019-12-25 14:00:51 +05:30
rohitwaghchaure
827ac91e7f fix: supplier email id field not showing in the notification for purchase cycle doctypes (#20070) 2019-12-24 13:03:41 +05:30
Deepesh Garg
379b6df361 Merge pull request #20008 from deepeshgarg007/budget_variance_dimension_v12
feat: Dynamic filters for dimensions in budget variance report
2019-12-24 12:58:22 +05:30
Deepesh Garg
2e461551d6 fix: Allow creation of multiple landed cost voucher against a Purchase Document (#20059) 2019-12-24 12:55:18 +05:30
Himanshu
2d30dc583c fix: resolve ambigious error (#20067) 2019-12-24 12:31:34 +05:30
Sun Howwrongbum
9de6083dbf feat: consider expiry_date during Batch queries (#20064) 2019-12-24 12:29:05 +05:30
RJPvT
9512e55704 Update supplier_scorecard.py (#20060) 2019-12-24 12:25:05 +05:30
rohitwaghchaure
9635df4f26 Merge pull request #20066 from rohitwaghchaure/job_card_operation_id_showing_blank
fix: Map custom job card create button with dashboard
2019-12-24 12:11:16 +05:30
Rohit Waghchaure
7bbeb31015 fix: Map custom job card create button with dashboard 2019-12-24 12:08:58 +05:30
Deepesh Garg
1f4b251f53 Merge pull request #20045 from deepeshgarg007/employee_advance_return_v12
feat: Capture return amount against Employee Advance via Journal Entry
2019-12-24 11:55:24 +05:30
Deepesh Garg
34dabc715b fix: Update return amount label 2019-12-24 11:54:04 +05:30
DeeMysterio
3881ce94ef fix(employee onboarding): stop showing irrelevant job offer links for a job applicant (#20054) 2019-12-23 19:02:44 +05:30
Marica
065bbc9cb3 enhancement: Added Set Reserve Warehouse field in Purchase Order. (#19992) 2019-12-23 18:24:28 +05:30
Pranav Nachnekar
139bb92df9 fix: wrap scheduled_time with getdate (#20046) 2019-12-23 18:19:52 +05:30
Deepesh Garg
15c8caac57 fix: Do not validate accounting dimensions if from repost (#20043)
* fix: Do not check for accounting dimensions in case of repost

* fix: Do not validate accounting dimensions if from repost
2019-12-23 17:58:44 +05:30
Saqib
7b926f228f fix: bad condition while checking last asset movement entry (#20048) 2019-12-23 16:08:40 +05:30
Saqib
dab963aac0 fix: remove mandatory purchase reference for existing asset (#19981) 2019-12-23 15:56:50 +05:30
Saqib
170c9d0ab8 fix: remove mandatory purchase reference for existing asset (#19980) 2019-12-23 15:56:44 +05:30
Saqib
f27a6528db fix: exchange rate not fetching correctly (#19985) 2019-12-23 15:52:59 +05:30
Anurag Mishra
b139f2fc0f feat: fixed party and party type in Accrual journal entry (#20022) 2019-12-23 15:50:20 +05:30
Mangesh-Khairnar
498ebfba9d fix(expense-claim): update status (#20032)
* fix(expense-claim): update status

* fix(expense-claim): compare using grandtotal precision
2019-12-23 15:48:18 +05:30
Deepesh Garg
2ebafb39ac Merge pull request #20011 from nextchamp-saqib/pi-payable-filter-hotfix
fix: bad credit to filter query in purchase invoice
2019-12-23 14:51:50 +05:30
thefalconx33
adc1b9dc0a fix: bad query for debit_to field in sales invoice 2019-12-23 13:08:46 +05:30
deepeshgarg007
b7012a47a2 fix: Remove trailing whitespace and add semicolon 2019-12-23 11:13:53 +05:30
deepeshgarg007
f1036c6985 feat: Custom button to create return entry from Employee Advance 2019-12-23 11:13:44 +05:30
deepeshgarg007
8f6e989f57 feat: Capture return amount against Employee advance via Journal Entry 2019-12-23 11:13:34 +05:30
deepeshgarg007
9609cce7b7 fix: Dashboard for employee advance doctype 2019-12-23 11:13:24 +05:30
Deepesh Garg
e14961a6c6 Merge pull request #20013 from nextchamp-saqib/share-transf-perm
fix: no role has cancelling permission for share transfer doctype
2019-12-21 17:22:15 +05:30
Deepesh Garg
f47afecc42 Merge pull request #20035 from rohitwaghchaure/fixed_patch_for_add_export_type_field_in_party_master_v12_hotfix
fix: patch
2019-12-21 17:20:28 +05:30
Sahil Khan
782f45ae5f Merge branch 'v12-pre-release' into version-12 2019-12-20 17:11:52 +05:30
Sahil Khan
f9ac8f63cf bumped to version 12.3.1 2019-12-20 17:31:52 +05:50
sahil28297
411b8e86b3 Merge pull request #20036 from rohitwaghchaure/fixed_patch_for_add_export_type_field_in_party_master_v12_pre_release
fix: patch
2019-12-20 17:09:09 +05:30
Rohit Waghchaure
2b14669b58 fix: patch 2019-12-20 17:06:57 +05:30
Rohit Waghchaure
14f624f587 fix: patch 2019-12-20 17:06:00 +05:30
Sahil Khan
98ddbf05b1 Merge branch 'v12-pre-release' into version-12 2019-12-20 15:55:12 +05:30
Sahil Khan
67d25028b2 bumped to version 12.3.0 2019-12-20 16:15:12 +05:50
Mangesh-Khairnar
328d5920bd fix(expense-claim): update status (#20033)
* fix(expense-claim): update status

* fix(expense-claim): compare using grandtotal precision
2019-12-20 15:26:49 +05:30
rohitwaghchaure
81d614b6bd Merge pull request #20007 from 0Pranav/appointment-schedulling-v12
fix: multiple issues with appointment schedulling
2019-12-20 15:17:41 +05:30
rohitwaghchaure
fdb7cec244 Merge pull request #20006 from 0Pranav/appointment-schedulling-v12
fix: multiple issues with appointment schedulling
2019-12-20 15:17:23 +05:30
thefalconx33
3aabeb88b4 fix: account manager doesn't have cancel submit perm for share transfer 2019-12-20 14:49:18 +05:30
rohitwaghchaure
b7fd9a652d Merge pull request #19929 from 0Pranav/delete-company-txn-query-v12
fix: replace sql with orm query for deleting company communications
2019-12-20 13:48:23 +05:30
rohitwaghchaure
63bc8f2d90 Merge pull request #20026 from rohitwaghchaure/subcontracting_issue_for_partial_purchase_receipt
fix: incorrect consumed qty for partial purchase receipt in subcontra…
2019-12-20 13:36:06 +05:30
rohitwaghchaure
b6d7fba936 Merge pull request #20025 from deepeshgarg007/gstr-2-fix-v12
fix: Tax amount not visible for some invoices
2019-12-20 13:35:41 +05:30
rohitwaghchaure
38540e85e8 Merge pull request #20029 from deepeshgarg007/gstr-2-fix-v12
fix: Tax amount not visible for some invoices
2019-12-20 13:35:14 +05:30
rohitwaghchaure
b3d97a560f Merge pull request #20027 from rohitwaghchaure/subcontracting_issue_for_partial_purchase_receipt_pre_release
fix: incorrect consumed qty for partial purchase receipt in subcontra…
2019-12-20 13:05:19 +05:30
Rohit Waghchaure
39436c6d38 fix: incorrect consumed qty for partial purchase receipt in subcontracting 2019-12-20 12:59:56 +05:30
Rohit Waghchaure
59cecb29a0 fix: incorrect consumed qty for partial purchase receipt in subcontracting 2019-12-20 12:56:01 +05:30
deepeshgarg007
55bf951ff5 fix: Tax amount not visible for some invoices 2019-12-20 12:43:55 +05:30
Deepesh Garg
4f543ce42a Merge pull request #20015 from marination/valuation_rate_company_hotfix
fix: Company None not found in get_valuation_rate
2019-12-20 11:56:58 +05:30
Deepesh Garg
8931b3d602 Merge pull request #19989 from deepeshgarg007/sales_register_upgrade_v12
fix: Update sales register report
2019-12-19 13:53:35 +05:30
marination
b13eebe657 fix: Company None not found in get_valuation_rate 2019-12-19 13:39:41 +05:30
thefalconx33
fcb296aafb fix: no role has cancelling permission for share transfer doctype 2019-12-19 13:19:50 +05:30
thefalconx33
5109b36689 fix: bad filter query 2019-12-19 13:12:37 +05:30
deepeshgarg007
2149d7ca4f feat: Dynamic filters for dimensions in budget variance report 2019-12-19 13:05:52 +05:30
0Pranav
220a208f4e fix: default timezone selection 2019-12-19 12:28:12 +05:30
0Pranav
0c8e46fdea fix: remove timezones in js 2019-12-19 12:25:29 +05:30
Deepesh Garg
ee4901f4a0 Merge pull request #19990 from 0Pranav/mapped-doc-for-customer-quotation-v12
fix: use open_mapped_doc instead of create_new_doc
2019-12-19 12:00:53 +05:30
Deepesh Garg
a0c847920f Merge pull request #19984 from 0Pranav/mapped-doc-for-customer-quotation-v12
fix: use open_mapped_doc instead of create_new_doc
2019-12-19 12:00:23 +05:30
rohitwaghchaure
86e5ff3cf9 Merge pull request #19997 from rohitwaghchaure/fixed_pricing_rule_issue_for_product_discount_v12_hotfix
fix: Pricing Rule Discount for Product
2019-12-19 11:12:15 +05:30
rohitwaghchaure
5dd7503516 Merge pull request #19995 from rohitwaghchaure/fixed_pricing_rule_issue_for_product_discount_pre_relesae
fix: Pricing Rule Discount for Product
2019-12-19 11:11:37 +05:30
deepeshgarg007
5cc0e08a41 fix: Use get_value instead of get_doc and formatting 2019-12-19 11:07:43 +05:30
Rohit Waghchaure
6b00d60b46 fix: Pricing Rule Discount for Product 2019-12-18 17:54:28 +05:30
Rohit Waghchaure
fecf5a9a15 fix: Pricing Rule Discount for Product 2019-12-18 17:48:39 +05:30
0Pranav
5b4050a4ff add link to appointment booking in sidebar 2019-12-18 16:30:54 +05:30
0Pranav
4d7862ef4c fix: defualt timezone not getting selected 2019-12-18 16:27:16 +05:30
0Pranav
6e41475612 fix : only set price list if it exists for customer 2019-12-18 16:05:59 +05:30
sahil28297
803e0ec27c Merge pull request #19988 from rohitwaghchaure/change_log_for_v12_3_0
feat: v12_3_0 change log
2019-12-18 15:54:37 +05:30
Rohit Waghchaure
b3addff99e v12_3_0 change log 2019-12-18 15:49:32 +05:30
deepeshgarg007
c6e098881f fix: Update sales register report 2019-12-18 15:43:14 +05:30
0Pranav
200ceb5352 use open_mapped_doc instead of create_new_doc 2019-12-18 12:34:19 +05:30
rohitwaghchaure
8c50f5c23f Merge pull request #19977 from Mangesh-Khairnar/fix-compensatory-off-pre
fix: compensatory off leave creation
2019-12-18 11:29:18 +05:30
rohitwaghchaure
6351a9395c Merge pull request #19975 from rohitwaghchaure/not_able_to_make_work_order_from_bom_v12_hotfix
fix: not able to make work order from BOM
2019-12-18 11:12:45 +05:30
Rushabh Mehta
fb2153c0eb Merge pull request #19966 from alyf-de/version-12-hotfix
fix(regional): Py3 compatibility for DATEV Export
2019-12-18 08:48:50 +05:30
Mangesh-Khairnar
86600ac8b9 fix: allow creation of additional leave ledger entry 2019-12-17 18:37:15 +05:30
Mangesh-Khairnar
b76a04b470 fix: compensatory leave request creation 2019-12-17 18:37:09 +05:30
Rohit Waghchaure
bb42fc615e fix: not able to make work order from BOM 2019-12-17 18:18:17 +05:30
rohitwaghchaure
80913994da Merge pull request #19974 from rohitwaghchaure/not_able_to_make_work_order_from_bom
fix: not able to make work order from BOM
2019-12-17 18:15:37 +05:30
Rohit Waghchaure
92ecdbe0c8 fix: not able to make work order from BOM 2019-12-17 18:13:54 +05:30
rohitwaghchaure
089dcaed70 Merge pull request #19969 from rohitwaghchaure/fixed_incorrect_outstanding_amount_showing_in_the_ap_ar_report
fix: incorrect outstanding amount showing in the AP/AR report
2019-12-17 17:15:28 +05:30
Mangesh-Khairnar
03a427a9e7 Merge pull request #19961 from Mangesh-Khairnar/compensatory-off-fix
fix: compensatory leave request creation
2019-12-17 13:32:05 +05:30
Rohit Waghchaure
764c2c7f17 fix: incorrect outstanding amount shwoing in the AP/AR report 2019-12-17 12:44:19 +05:30
Mangesh-Khairnar
b4d9b80fed fix: allow creation of additional leave ledger entry 2019-12-17 12:25:25 +05:30
Raffael Meyer
215274719e fix(regional): PY3 compatibility 2019-12-16 17:33:44 +01:00
rohitwaghchaure
c920efc156 Merge pull request #19963 from rohitwaghchaure/allow_overproduction_against_work_order_version_12_hotfix
fix: not allow to over production against work order
2019-12-16 18:04:27 +05:30
rohitwaghchaure
3b9fe1ae6f Merge pull request #19959 from rohitwaghchaure/fixed_incorrect_child_bom_fecthed
fix: incorrect child boms fetched
2019-12-16 17:00:08 +05:30
Rohit Waghchaure
c76c5e699b fix: now allow to over production against work order 2019-12-16 16:59:01 +05:30
Mangesh-Khairnar
ce6923ecb6 fix: compensatory leave request creation 2019-12-16 16:56:57 +05:30
0Pranav
03db85f3e7 fix: replace sql query by orm in delete_communications and added tests 2019-12-16 16:54:03 +05:30
Rohit Waghchaure
666fba94e2 fix: incorrect children boms fetched 2019-12-16 16:18:33 +05:30
rohitwaghchaure
48a8a40703 Merge pull request #19944 from nextchamp-saqib/gl-precision-hotfix
fix: gl entries doesn't filter based on debit precision
2019-12-16 15:29:04 +05:30
rohitwaghchaure
5646816282 Merge pull request #19870 from nextchamp-saqib/website-hotfix
fix: website showing disabled items in product list
2019-12-16 15:25:07 +05:30
thefalconx33
f8df3c7af2 fix: review changes 2019-12-16 15:03:27 +05:30
rohitwaghchaure
62d4dfa883 Merge pull request #19956 from nextchamp-saqib/pos-serial-no
fix: display serial no selection on adding items to cart
2019-12-16 14:54:23 +05:30
thefalconx33
b8f9fd023b fix: display serial no selection on adding items to cart 2019-12-16 14:49:59 +05:30
rohitwaghchaure
0df3c93737 Merge pull request #19936 from benknowles/patch-3
fix: task validation error when adding tasks to projects
2019-12-16 14:01:20 +05:30
rohitwaghchaure
e0e7dcd2f6 Merge pull request #19914 from nextchamp-saqib/cart-address-hotfix
fix: enable adding of address without enabling checkout feature
2019-12-16 13:52:48 +05:30
rohitwaghchaure
d5b1baed39 Merge pull request #19907 from 0Pranav/appointment-schedulling-v12
fix: change book-appointment route
2019-12-16 13:50:47 +05:30
rohitwaghchaure
800545ff5b Merge pull request #19947 from rohitwaghchaure/pricing_rule_not_working_for_product_discount_v12_hotfix
fix: pricing rule not working for product discount
2019-12-16 13:37:45 +05:30
rohitwaghchaure
388a177f75 Merge pull request #19939 from marination/item_manufacturer_table
fix(ui): Removed 'manufacturers' table from Item Master
2019-12-16 13:36:56 +05:30
Rohit Waghchaure
821166c628 fix: schedule date 2019-12-16 12:29:39 +05:30
marination
2b8df06f8e fix: Removed validation from non existent manufacturers table 2019-12-16 12:18:24 +05:30
Rohit Waghchaure
4e8e466a98 fix: pricing rule not working for production discount 2019-12-16 11:16:36 +05:30
Deepesh Garg
31d4482336 Merge pull request #19953 from surajshetty3416/fix-profit-and-loss-statement-version-12-hotfix
fix: Profit and Lost (financial statement) report
2019-12-15 20:23:05 +05:30
Suraj Shetty
5cd8c7c722 fix: Financial statement report
- Hidden column should note be considered in the report
- Remove hardcoded currency formatting
- Remove duplicate letterhead in the report
(print_template already adds one)
- Remove extra quotes from Total Amount text
2019-12-14 23:33:14 +05:30
Deepesh Garg
e14d9b5476 Merge pull request #19951 from deepeshgarg007/patch-and-address-fix-v12
fix: Add missing import
2019-12-14 23:03:27 +05:30
deepeshgarg007
6a8ff1bebe fix: Add missing import 2019-12-14 21:31:11 +05:30
rohitwaghchaure
a41d464198 Merge pull request #19942 from deepeshgarg007/pricing_rule_fix_v12
fix: Price rule filtering fix
2019-12-13 16:01:35 +05:30
thefalconx33
980793bde0 fix: gl entries doesn't filter based on debit precision 2019-12-13 15:42:34 +05:30
deepeshgarg007
b7329eac19 fix: Price rule filtering fix 2019-12-13 13:49:12 +05:30
marination
9ec5cb2570 fix: Removed 'manufacturers' table from Item Master 2019-12-13 13:12:10 +05:30
Deepesh Garg
44296a392d Merge pull request #19735 from marination/zero-division-v12-hotfix
fix: Division by zero error in Stock Entry
2019-12-13 09:24:31 +05:30
Ben Knowles
9097c7e11c fix: task validation error when adding tasks to projects
Related to PR #19919
2019-12-12 11:30:17 -06:00
Deepesh Garg
0256d7549c Merge pull request #19931 from deepeshgarg007/regional_address_fix_v12
fix: Get regional address details
2019-12-12 16:54:34 +05:30
marination
94d8b99ef9 fix: Distribute charges based on quantity if Total Basic Amount is Zero. 2019-12-12 16:51:11 +05:30
Deepesh Garg
3fe1335f7b Merge pull request #19926 from prssanna/file-upload-fix-v12
fix: Bank statement not getting attached in Bank Reconciliation
2019-12-12 15:19:36 +05:30
Deepesh Garg
dc7a4ac8af Merge pull request #19925 from rohitwaghchaure/not_able_to_submit_the_landed_cost_voucher_version_12
fix: not able to submit the landed cost voucher
2019-12-12 15:17:05 +05:30
Deepesh Garg
c0ff769214 Merge pull request #19924 from rohitwaghchaure/not_able_to_submit_the_landed_cost_voucher_version_12_hotfix
fix: not able to submit the landed cost voucher
2019-12-12 15:16:31 +05:30
deepeshgarg007
0a527b9f9a fix: Get regional address details fix 2019-12-12 15:13:30 +05:30
prssanna
e03871f9de fix: empty fname and fcontent of uploaded file 2019-12-12 12:22:03 +05:30
Rohit Waghchaure
c0286780bd fix: not able to submit the landed cost voucher 2019-12-12 12:14:26 +05:30
Rohit Waghchaure
9cc484650b fix: not able to submit the landed cost voucher 2019-12-12 12:13:40 +05:30
rohitwaghchaure
319f126258 Merge pull request #19901 from rohitwaghchaure/not_able_to_cancel_landed_cost_voucher_v12
fix: not able to cancel the landed cost voucher
2019-12-12 12:11:02 +05:30
0Pranav
234de12836 fix: add init files for book-appointments 2019-12-12 11:20:31 +05:30
rohitwaghchaure
4c19000ed9 Merge pull request #19918 from rohitwaghchaure/fixed_pricing_rule_working_on_other_items_v12_cherry_pick
fix: pricing rule not working
2019-12-12 10:20:05 +05:30
Deepesh Garg
a1651ca5f2 Merge pull request #19898 from hrwX/qms-int-fix-v12
fix: rename labels
2019-12-12 08:45:20 +05:30
Rohit Waghchaure
4d042cd81a Merge branch 'version-12' into fixed_pricing_rule_working_on_other_items_v12_cherry_pick 2019-12-11 22:53:27 +05:30
rohitwaghchaure
d72fae670a Merge pull request #19916 from rohitwaghchaure/fixed_pricing_rule_working_on_other_items
fix: pricing rule working on non pricing rule items
2019-12-11 22:18:07 +05:30
Rohit Waghchaure
d458e25dc5 fix: pricing rule working on non pricing rule items 2019-12-11 21:55:28 +05:30
Deepesh Garg
43474a3afa Merge pull request #19896 from hrwX/project-fix_v12
fix: Set project in child table via dashboard
2019-12-11 18:43:29 +05:30
Deepesh Garg
7daa2a2085 Merge pull request #19894 from marination/rounded_total_v12_hotfix
fix: Disable Rounded Total always showing field default value
2019-12-11 18:41:25 +05:30
Deepesh Garg
45075d8915 Merge pull request #19900 from rohitwaghchaure/not_able_to_cancel_landed_cost_voucher_v12_hotfix
fix: not able to cancel the landed cost voucher
2019-12-11 18:37:34 +05:30
thefalconx33
1de3040ecb fix: additional notes from Quotations not saved in SO 2019-12-11 18:11:48 +05:30
thefalconx33
af10f659d9 fix: enable address without checkout feature
* fix add address form country link field
2019-12-11 17:44:08 +05:30
thefalconx33
6f36691c64 fix: handle scenario with no condition 2019-12-11 16:10:56 +05:30
0Pranav
dfe629aff7 fix: change book-appointment route 2019-12-11 15:18:59 +05:30
Rohit Waghchaure
23bf2a6647 fix: not able to cancel the landed cost voucher 2019-12-11 13:52:47 +05:30
Rohit Waghchaure
b69cb8080c fix: not able to cancel the landed cost voucher 2019-12-11 13:52:18 +05:30
Himanshu Warekar
f23b5ed23b fix: rename labels 2019-12-11 13:10:31 +05:30
Himanshu Warekar
0a28387c70 fix: set project 2019-12-11 12:49:43 +05:30
marination
caae8c57bc fix: Disable Rounded Total always showing field default value 2019-12-11 12:18:51 +05:30
Nabin Hait
44ae135c36 Merge branch 'version-12' into version-12-hotfix 2019-12-11 09:12:10 +05:30
Deepesh Garg
47e786ef62 fix: Rounding Adjustment GL entry fix (#19839)
* fix: Rounding Adjustment GL entry fix

* fix: Spacing in tab

* fix: Comment fix
2019-12-11 09:06:37 +05:30
Deepesh Garg
f10be395c1 fix: NoneType' object has no attribute '__getitem_'_ (#19860) 2019-12-11 09:06:25 +05:30
rohitwaghchaure
ac967d09ec fix: Item-wise Sales History report not working (#19890) 2019-12-10 21:34:20 +05:30
Saqib
d1e8e8652f fix: incorrect account mapping for child companies (#19888)
* fix: incorrect account mapping for child companies on adding account to parent company

* Update account.py
2019-12-10 21:32:57 +05:30
Deepesh Garg
72649c207f feat(regional): Auto state wise taxation for GST India (#19877)
* feat(regional): Auto state wise taxation for GST India

* fix: Update gst category on addition of GSTIN

* fix: Codacy and travis fixes

* fix: Travis

* fix(test): Update GST category only if GSTIN field available

* fix: Test Cases

* fix: Do not skip accounts if place of supply is not present

* fix: Auto GST taxation for SEZ Party types

* fix: Automatic taxation for multi state

* fix: Codacy and travis fixes

* fix: Auto GST template selection in Sales Order

* fix: Move inter state check and source state to tax category

* fix: Remove unique check from tax template

* fix: Remove unique check from tax template

* fix: Address fetching logic in Sales

* fix: fecth tax template on company address change

* fix: fetch company gstin on address change

* fix: company_gstin set value fix

* fix: Mutiple fixes and code refactor

* fix: Add missing semicolon

* fix: Company address fetching in sales invoice

* fix: Remove print statement

* fix: Import functools

* fix: Naming fixes and code cleanup

* fix: Update patches

* fix: Remove changes in patches.txt

* fix: Iteritems compatibility for python 3
2019-12-10 15:54:29 +05:30
Deepesh Garg
d06b685fdf fix: Append expense account only if expense account exists (#19881) 2019-12-10 12:15:06 +05:30
marination
6411a56cdc fix: Changed check condition and added test 2019-12-09 21:36:02 +05:30
Saqib
34b3b04fb0 fix: error message displays asset category as None (#19874)
* fix: error message displays asset category as None

* fix: asset gl_entries doesn't considers asset category's cwip account
2019-12-09 19:06:14 +05:30
Deepesh Garg
b1a2a16f43 Merge pull request #19868 from nextchamp-saqib/report-col-hotfix
fix: column data not visible after manual selection of columns
2019-12-09 17:57:41 +05:30
thefalconx33
f092e68a58 fix: website showing disabled items in product list 2019-12-09 17:03:32 +05:30
thefalconx33
6d497ccb4c fix: column data not visible after manual selection of columns 2019-12-09 15:24:39 +05:30
Deepesh Garg
a7b97f7bac Merge pull request #19867 from nextchamp-saqib/cart-fix-hotfix
fix: Error while placing order of cart items added yesterday
2019-12-09 15:23:04 +05:30
thefalconx33
f40d3bd10f fix: due date before posting date for items added to cart yesterday 2019-12-09 14:07:25 +05:30
Deepesh Garg
1e2be32860 fix: Consistency in button positions in Sales Order and Purchase Order (#19834) 2019-12-09 13:04:58 +05:30
Deepesh Garg
6aec9e32d4 fix: Rounding Adjustment GL entry fix (#19839)
* fix: Rounding Adjustment GL entry fix

* fix: Spacing in tab

* fix: Comment fix
2019-12-09 13:03:02 +05:30
Deepesh Garg
59cc0e5029 fix: NoneType' object has no attribute '__getitem_'_ (#19860) 2019-12-09 11:28:35 +05:30
Deepesh Garg
851f39cee1 Merge pull request #19837 from deepeshgarg007/gst_1_validation_msg_v12
fix: Validation msg fix in GSTR-1 report
2019-12-07 19:53:03 +05:30
rohitwaghchaure
6822a30f8c Merge pull request #19850 from rohitwaghchaure/fixed_timsheet_overlap_issue_v12_hotfix
fix: timesheet overlap error
2019-12-07 14:10:54 +05:30
Rohit Waghchaure
495ba1618b fix: timsheet overlap error 2019-12-07 13:22:08 +05:30
deepeshgarg007
778d7595aa fix: Add missing semicolon 2019-12-06 20:00:56 +05:30
deepeshgarg007
a40dbd0384 fix: Validation msg fix in GSTR-1 report 2019-12-06 19:46:32 +05:30
Deepesh Garg
80dfb9f834 Merge pull request #19835 from deepeshgarg007/accounts_payable_terms_v12
feat: Accounts Payable report based on payment terms
2019-12-06 19:41:27 +05:30
deepeshgarg007
dabb303358 feat: Accounts Payable report based on payment terms 2019-12-06 17:52:48 +05:30
Pranav Nachnekar
d16ef54665 fix: query for finding lost quotation (#19801)
* fix:query for finding lost quotation

* Update opportunity.py
2019-12-04 15:31:25 +05:30
Nabin Hait
dc248b9458 optimize: Optimization of Receivable report filtered based on sales person (#19797) 2019-12-04 15:30:39 +05:30
Nabin Hait
bf0f26b4a4 fix: Service start and end date validation for deferred accounting (#19806) 2019-12-04 15:29:54 +05:30
Mangesh-Khairnar
929fd4ce47 enhancement(fixed-asset-register): add date filter (#19804)
* feat: add date filter in the fixed asset register

* fix: remove function from keyword argument
2019-12-04 14:10:41 +05:30
Deepesh Garg
81c895b21e Merge pull request #19793 from nabinhait/ar-summary-based-on-terms-v12
feat: Receivable / payable summary based on payment terms
2019-12-04 11:23:31 +05:30
Shivam Mishra
27a21f80d7 feat: allow searching from meta fields (#19725)
* feat: allow searching from meta fields

* feat: remove description in query based on number of items
2019-12-03 17:26:50 +05:30
sahil28297
aa7085e11c fix(patch): set proper tax_type based on company and set proper account if not already present (#19788) 2019-12-03 17:07:26 +05:30
Nabin Hait
6e5363ba48 feat: Receivable / payable summary based on payment terms 2019-12-03 16:58:02 +05:30
Deepesh Garg
53746636c3 fix: Party name field in trial balacne for party report (#19790) 2019-12-03 16:30:09 +05:30
Deepesh Garg
485d48c101 fix: Unable to see parties with negative balance in AR/AP Summary (#19777) 2019-12-03 15:12:28 +05:30
Marica
0e1ef35968 fix: Item qty cannot be zero in Purchase Receipt (#19780) 2019-12-03 12:59:15 +05:30
gavin
35effe9be0 fix: AttributeError on new Student creation (#19787) 2019-12-03 12:54:18 +05:30
Shivam Mishra
648d6e46f3 fix: query for item group listing (#19785) 2019-12-03 12:52:58 +05:30
Nabin Hait
d6d9a3ddd7 Update employee.py 2019-12-03 12:52:12 +05:30
Deepesh Garg
18f05db19a Merge pull request #19763 from Mangesh-Khairnar/fix-pr-creation-so
fix(sales-order): allow payment request creation for so that are not billed
2019-12-03 10:42:53 +05:30
Rucha Mahabal
586fecfe73 fix: render_template for subject in Email Campaign (#19771) 2019-12-02 16:25:29 +05:30
sahil28297
14018b3dea bumped to version 12.2.2 2019-12-02 13:05:27 +05:30
Deepesh Garg
1c196f958f Merge pull request #19768 from deepeshgarg007/avaiable_stock_for_v12
fix: Available stock for packing item report
2019-12-02 11:57:45 +05:30
rohitwaghchaure
91f2cfb999 Merge pull request #19769 from rohitwaghchaure/sales_invoice_none_type_error_serial_no_validation
fix: Serial no validation against sales invoice
2019-12-02 09:46:23 +05:30
deepeshgarg007
c0a0331570 fix: Validation msg 2019-12-02 09:43:11 +05:30
deepeshgarg007
4ceba43e43 fix: Serial no validation against sales invoice 2019-12-02 09:43:04 +05:30
deepeshgarg007
9b64e2e24c fix: Available stock for packing item report 2019-12-01 22:20:18 +05:30
Deepesh Garg
da5e227ad6 fix: Post GL entry fix for asset (#19752) 2019-12-01 10:06:31 +05:30
Mangesh-Khairnar
4f95e5d092 fix: show create payment request for so that are not billed 2019-11-30 20:31:18 +05:30
Deepesh Garg
6a8fd0102f fix: Serial no validation against sales invoice (#19749)
* fix: Serial no validation against sales invoice

* fix: Validation msg
2019-11-29 18:48:30 +05:30
Suraj Shetty
2b172ec4b4 fix: valuation of "finished good" item in purchase receipt (#19745)
* fix: Remove redundant purchase orders and unwanted condition

* fix: [WIP] Purchase receipt value

* fix: Add raw material cost based on transfered raw material

* fix: get_qty_to_be_received

* fix: Remove debugger statement

* fix: Reset rm_supp_cost before setting subcontracted raw_materials

* test: Fix and modify tests for backflush_based_on_stock_entry

* fix: Add non stock items to Purchase Receipt from Purchase Order

* fix: Ignore valuation rate check for non stock raw material

* fix: Rename check all rows

* fix: Remove amount from test

* test: Fix item rate error

* fix: handling of serial nos in backflush

* fix: Add serial no. of raw materials

* fix: [WIP] Handle Batch nos for purchase reciept backflushed raw material

* fix: Raw material batch number selection in purchase receipt

* Update test_purchase_order.py
2019-11-29 16:59:21 +05:30
Marica
5d2ad7fc38 fix: UOM was not fetching in purchase invoice (#19732) (#19737)
* fix: UOM was not fetching in purchase invoice

* fix: Changes requested

Co-authored-by: Marica <maricadsouza221197@gmail.com>
2019-11-28 20:00:51 +05:30
rohitwaghchaure
3347473aa1 fix: removed stock value and account balance out of sync validation (#19728) 2019-11-28 20:00:41 +05:30
Rohit Waghchaure
7f951b5595 fix: revert value out of sync feature 2019-11-28 20:00:33 +05:30
Marica
208c69f196 fix: Permission issue in Stock Entry (#19739) 2019-11-28 19:39:55 +05:30
Marica
32b69bf122 fix: UOM was not fetching in purchase invoice (#19732) (#19737)
* fix: UOM was not fetching in purchase invoice

* fix: Changes requested

Co-authored-by: Marica <maricadsouza221197@gmail.com>
2019-11-28 19:03:14 +05:30
Marica
b1fac1817c fix: Validation for Suppliers in SO to PO (#19700)
- Check if there is a Supplier against atleast one item in Sales Order
- Validation message earlier was vague
2019-11-28 18:23:11 +05:30
Marica
6516358a71 fix: Changed type of column 'serial_no' in Stock Ledger Entry (#19704) 2019-11-28 18:20:53 +05:30
marination
c6e2087673 fix: Division by zero error in Stock Entry 2019-11-28 16:54:58 +05:30
Shivam Mishra
d8469a7bfa fix: handle None case for get_shipping_amount_from_rules (#19724) 2019-11-28 16:47:14 +05:30
Marica
cf645aceae chore: Added Quick Stock Balance to Stock Module (#19727)
- Also 'Stock Balance Report' button no longer primary button
2019-11-28 16:44:56 +05:30
rohitwaghchaure
3dd72e238f fix: removed stock value and account balance out of sync validation (#19728) 2019-11-28 16:44:05 +05:30
Deepesh Garg
b74ce74ec9 Merge pull request #19718 from deepeshgarg007/status_fix_v12
fix: Path for quotation expiry method in hooks
2019-11-28 12:24:20 +05:30
deepeshgarg007
074aaa6005 fix: Path for quotation expiry method in hooks 2019-11-28 10:31:11 +05:30
Marica
9d5f43f4f0 fix: get_batch_qty_and_serial_no() requires argument 'stock_qty' (#19694) 2019-11-27 15:50:45 +05:30
rohitwaghchaure
7522aadc6e Merge pull request #19697 from rohitwaghchaure/dont_stop_submitting_entry_due_to_mismatch_issue
fix: revert value out of sync feature
2019-11-27 12:32:04 +05:30
rohitwaghchaure
326fdcb454 Merge pull request #19687 from deepeshgarg007/sales_invoice_fix_develop
fix: Serial no validation against sales invoice
2019-11-27 11:36:10 +05:30
Rohit Waghchaure
c41addec96 fix: revert value out of sync feature 2019-11-27 08:49:08 +05:30
deepeshgarg007
defed15528 fix: Validation msg 2019-11-26 16:12:29 +05:30
deepeshgarg007
cbc29989fe fix: Serial no validation against sales invoice 2019-11-26 15:13:23 +05:30
Gavin D'souza
73089470b1 chore: pinned backwards compatible dependencies 2019-11-15 17:38:32 +05:30
Gavin D'souza
3798f8bd25 style(requirements): alphabetically sorted requirements 2019-11-15 13:59:15 +05:30
Gavin D'souza
f805a76e79 chore: pinned requirements 2019-11-13 17:27:16 +05:30
284 changed files with 8950 additions and 17707 deletions

View File

@@ -63,6 +63,7 @@ install:
- tar -xf /tmp/wkhtmltox.tar.xz -C /tmp
- sudo mv /tmp/wkhtmltox/bin/wkhtmltopdf /usr/local/bin/wkhtmltopdf
- sudo chmod o+x /usr/local/bin/wkhtmltopdf
- sudo apt-get install libcups2-dev
- cd ~/frappe-bench

View File

@@ -5,7 +5,7 @@ import frappe
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
__version__ = '12.2.0'
__version__ = '12.5.2'
def get_default_company(user=None):
'''Get default company for user'''

View File

@@ -95,28 +95,29 @@ class Account(NestedSet):
# 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:
return
ancestors = get_root_company(self.company)
if ancestors:
if frappe.get_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'):
frappe.throw(_("Please add the account to root level Company - %s" % ancestors[0]))
else:
descendants = get_descendants_of('Company', self.company)
if not descendants: return
parent_acc_name_map = {}
parent_acc_name = frappe.db.get_value('Account', self.parent_account, "account_name")
for d in frappe.db.get_values('Account',
{"company": ["in", descendants], "account_name": parent_acc_name},
["company", "name"], as_dict=True):
parent_acc_name, parent_acc_number = frappe.db.get_value('Account', self.parent_account, \
["account_name", "account_number"])
filters = {
"company": ["in", descendants],
"account_name": parent_acc_name,
}
if parent_acc_number:
filters["account_number"] = parent_acc_number
for d in frappe.db.get_values('Account', filters=filters, fieldname=["company", "name"], as_dict=True):
parent_acc_name_map[d["company"]] = d["name"]
if not parent_acc_name_map: return
self.create_account_for_child_company(parent_acc_name_map, descendants, parent_acc_name)
def validate_group_or_ledger(self):
@@ -174,7 +175,6 @@ class Account(NestedSet):
filters["account_number"] = self.account_number
child_account = frappe.db.get_value("Account", filters, 'name')
if not child_account:
doc = frappe.copy_doc(self)
doc.flags.ignore_root_company_validation = True

View File

@@ -41,8 +41,8 @@ class AccountingPeriod(Document):
def get_doctypes_for_closing(self):
docs_for_closing = []
doctypes = ["Sales Invoice", "Purchase Invoice", "Journal Entry", "Payroll Entry", "Bank Reconciliation",
"Asset", "Purchase Order", "Sales Order", "Leave Application", "Leave Allocation", "Stock Entry"]
doctypes = ["Sales Invoice", "Purchase Invoice", "Journal Entry", "Payroll Entry", \
"Bank Reconciliation", "Asset", "Stock Entry"]
closed_doctypes = [{"document_type": doctype, "closed": 1} for doctype in doctypes]
for closed_doctype in closed_doctypes:
docs_for_closing.append(closed_doctype)

View File

@@ -1,4 +1,5 @@
{
"actions": [],
"allow_import": 1,
"allow_rename": 1,
"creation": "2017-05-29 21:35:13.136357",
@@ -82,7 +83,7 @@
"default": "0",
"fieldname": "is_default",
"fieldtype": "Check",
"label": "Is the Default Account"
"label": "Is Default Account"
},
{
"default": "0",
@@ -211,7 +212,8 @@
"read_only": 1
}
],
"modified": "2019-10-02 01:34:12.417601",
"links": [],
"modified": "2020-01-29 20:42:26.458316",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Account",

View File

@@ -3,16 +3,16 @@
frappe.ui.form.on("Bank Reconciliation", {
setup: function(frm) {
frm.add_fetch("bank_account", "account_currency", "account_currency");
frm.add_fetch("account", "account_currency", "account_currency");
},
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("bank_account", default_bank_account);
frm.set_value("account", default_bank_account);
frm.set_query("bank_account", function() {
frm.set_query("account", function() {
return {
"filters": {
"account_type": ["in",["Bank","Cash"]],

View File

@@ -19,10 +19,9 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "Select account head of the bank where cheque was deposited.",
"fetch_from": "bank_account_no.account",
"fetch_from": "bank_account.account",
"fetch_if_empty": 1,
"fieldname": "bank_account",
"fieldname": "account",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -31,7 +30,7 @@
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Bank Account",
"label": "Account",
"length": 0,
"no_copy": 0,
"options": "Account",
@@ -164,7 +163,6 @@
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
@@ -183,8 +181,9 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "Select the Bank Account to reconcile.",
"fetch_if_empty": 0,
"fieldname": "bank_account_no",
"fieldname": "bank_account",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -193,12 +192,11 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Bank Account No",
"label": "Bank Account",
"length": 0,
"no_copy": 0,
"options": "Bank Account",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
@@ -450,7 +448,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2019-04-09 18:41:06.110453",
"modified": "2020-01-22 00:00:00.000000",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Reconciliation",
@@ -483,4 +481,4 @@
"track_changes": 0,
"track_seen": 0,
"track_views": 0
}
}

View File

@@ -13,17 +13,15 @@ form_grid_templates = {
class BankReconciliation(Document):
def get_payment_entries(self):
if not (self.bank_account and self.from_date and self.to_date):
msgprint(_("Bank Account, From Date and To Date are Mandatory"))
return
if not (self.from_date and self.to_date):
frappe.throw(_("From Date and To Date are Mandatory"))
if not self.account:
frappe.throw(_("Account is mandatory to get payment entries"))
condition = ""
if not self.include_reconciled_entries:
condition = " and (clearance_date is null or clearance_date='0000-00-00')"
account_cond = ""
if self.bank_account_no:
account_cond = " and t2.bank_account_no = {0}".format(frappe.db.escape(self.bank_account_no))
condition = "and (clearance_date IS NULL or clearance_date='0000-00-00')"
journal_entries = frappe.db.sql("""
select
@@ -34,15 +32,16 @@ class BankReconciliation(Document):
from
`tabJournal Entry` t1, `tabJournal Entry Account` t2
where
t2.parent = t1.name and t2.account = %s and t1.docstatus=1
and t1.posting_date >= %s and t1.posting_date <= %s
and ifnull(t1.is_opening, 'No') = 'No' {0} {1}
t2.parent = t1.name and t2.account = %(account)s and t1.docstatus=1
and t1.posting_date >= %(from)s and t1.posting_date <= %(to)s
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, account_cond), (self.bank_account, self.from_date, self.to_date), as_dict=1)
""".format(condition=condition), {"account": self.account, "from": self.from_date, "to": self.to_date}, as_dict=1)
condition = ''
if self.bank_account_no:
condition = " and bank_account = %(bank_account_no)s"
if self.bank_account:
condition += 'and bank_account = %(bank_account)s'
payment_entries = frappe.db.sql("""
select
@@ -55,12 +54,12 @@ class BankReconciliation(Document):
from `tabPayment Entry`
where
(paid_from=%(account)s or paid_to=%(account)s) and docstatus=1
and posting_date >= %(from)s and posting_date <= %(to)s {0}
and posting_date >= %(from)s and posting_date <= %(to)s
{condition}
order by
posting_date ASC, name DESC
""".format(condition),
{"account":self.bank_account, "from":self.from_date,
"to":self.to_date, "bank_account_no": self.bank_account_no}, as_dict=1)
""".format(condition=condition), {"account": self.account, "from":self.from_date,
"to": self.to_date, "bank_account": self.bank_account}, as_dict=1)
pos_entries = []
if self.include_pos_transactions:
@@ -72,11 +71,10 @@ class BankReconciliation(Document):
from `tabSales Invoice Payment` sip, `tabSales Invoice` si, `tabAccount` account
where
sip.account=%(account)s and si.docstatus=1 and sip.parent = si.name
and account.name = sip.account and si.posting_date >= %(from)s and si.posting_date <= %(to)s {0}
and account.name = sip.account and si.posting_date >= %(from)s and si.posting_date <= %(to)s
order by
si.posting_date ASC, si.name DESC
""".format(condition),
{"account":self.bank_account, "from":self.from_date, "to":self.to_date}, as_dict=1)
""", {"account":self.account, "from":self.from_date, "to":self.to_date}, as_dict=1)
entries = sorted(list(payment_entries)+list(journal_entries+list(pos_entries)),
key=lambda k: k['posting_date'] or getdate(nowdate()))

View File

@@ -15,8 +15,8 @@ def upload_bank_statement():
with open(frappe.uploaded_file, "rb") as upfile:
fcontent = upfile.read()
else:
from frappe.utils.file_manager import get_uploaded_content
fname, fcontent = get_uploaded_content()
fcontent = frappe.local.uploaded_file
fname = frappe.local.uploaded_filename
if frappe.safe_encode(fname).lower().endswith("csv".encode('utf-8')):
from frappe.utils.csvutils import read_csv_content

View File

@@ -110,6 +110,15 @@
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"depends_on": "eval:doc.docstatus==1",
"fieldname": "clearance_date",
"fieldtype": "Date",
"label": "Clearance Date",
"no_copy": 1,
"print_hide": 1,
"read_only": 1
}
],
"has_web_view": 0,
@@ -122,7 +131,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2018-12-06 10:57:02.635141",
"modified": "2020-01-22 00:00:00.000000",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Transaction Payments",
@@ -138,4 +147,4 @@
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}
}

View File

@@ -210,10 +210,10 @@ def get_requested_amount(args, budget):
item_code = args.get('item_code')
condition = get_other_condition(args, budget, 'Material Request')
data = frappe.db.sql(""" select ifnull((sum(mri.stock_qty - mri.ordered_qty) * rate), 0) as amount
from `tabMaterial Request Item` mri, `tabMaterial Request` mr where mr.name = mri.parent and
mri.item_code = %s and mr.docstatus = 1 and mri.stock_qty > mri.ordered_qty and {0} and
mr.material_request_type = 'Purchase' and mr.status != 'Stopped'""".format(condition), item_code, as_list=1)
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 {0} and
parent.material_request_type = 'Purchase' and parent.status != 'Stopped'""".format(condition), item_code, as_list=1)
return data[0][0] if data else 0
@@ -221,10 +221,10 @@ def get_ordered_amount(args, budget):
item_code = args.get('item_code')
condition = get_other_condition(args, budget, 'Purchase Order')
data = frappe.db.sql(""" select ifnull(sum(poi.amount - poi.billed_amt), 0) as amount
from `tabPurchase Order Item` poi, `tabPurchase Order` po where
po.name = poi.parent and poi.item_code = %s and po.docstatus = 1 and poi.amount > poi.billed_amt
and po.status != 'Closed' and {0}""".format(condition), item_code, as_list=1)
data = frappe.db.sql(""" 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 {0}""".format(condition), item_code, as_list=1)
return data[0][0] if data else 0
@@ -233,16 +233,15 @@ def get_other_condition(args, budget, for_doc):
budget_against_field = frappe.scrub(args.get("budget_against_field"))
if budget_against_field and args.get(budget_against_field):
condition += " and %s = '%s'" %(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('Fiscal Year', args.get('fiscal_year'),
['year_start_date', 'year_end_date'])
alias = 'mr' if for_doc == 'Material Request' else 'po'
condition += """ and %s.%s
between '%s' and '%s' """ %(alias, date_field, start_date, end_date)
condition += """ and parent.%s
between '%s' and '%s' """ %(date_field, start_date, end_date)
return condition

View File

@@ -96,7 +96,11 @@ def build_forest(data):
if parent_account == account_name == child:
return [parent_account]
elif account_name == child:
return [child] + return_parent(data, parent_account)
parent_account_list = return_parent(data, parent_account)
if not parent_account_list:
frappe.throw(_("The parent account {0} does not exists")
.format(parent_account))
return [child] + parent_account_list
charts_map, paths = {}, []

View File

@@ -1,4 +1,5 @@
{
"actions": [],
"allow_copy": 1,
"allow_import": 1,
"allow_rename": 1,
@@ -123,7 +124,8 @@
],
"icon": "fa fa-money",
"idx": 1,
"modified": "2019-09-16 14:44:17.103548",
"links": [],
"modified": "2020-01-28 13:50:23.430434",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Cost Center",
@@ -162,7 +164,6 @@
"role": "Purchase User"
}
],
"quick_entry": 1,
"search_fields": "parent_cost_center, is_group",
"show_name_in_global_search": 1,
"sort_field": "modified",

File diff suppressed because it is too large Load Diff

View File

@@ -29,7 +29,6 @@ class GLEntry(Document):
self.validate_and_set_fiscal_year()
self.pl_must_have_cost_center()
self.validate_cost_center()
self.validate_dimensions_for_pl_and_bs()
if not self.flags.from_repost:
self.check_pl_account()
@@ -39,6 +38,7 @@ class GLEntry(Document):
def on_update_with_args(self, adv_adj, update_outstanding = 'Yes', from_repost=False):
if not from_repost:
self.validate_account_details(adv_adj)
self.validate_dimensions_for_pl_and_bs()
check_freezing_date(self.posting_date, adv_adj)
validate_frozen_account(self.account, adv_adj)

View File

@@ -190,7 +190,6 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
if(jvd.reference_type==="Employee Advance") {
return {
filters: {
'status': ['=', 'Unpaid'],
'docstatus': 1
}
};

File diff suppressed because it is too large Load Diff

View File

@@ -9,7 +9,6 @@ from erpnext.controllers.accounts_controller import AccountsController
from erpnext.accounts.utils import get_balance_on, get_account_currency
from erpnext.accounts.party import get_party_account
from erpnext.hr.doctype.expense_claim.expense_claim import update_reimbursed_amount
from erpnext.hr.doctype.loan.loan import update_disbursement_status, update_total_amount_paid
from erpnext.accounts.doctype.invoice_discounting.invoice_discounting import get_party_account_based_on_invoice_discounting
from six import string_types, iteritems
@@ -606,8 +605,8 @@ class JournalEntry(AccountsController):
for d in self.accounts:
if d.reference_type=="Loan" and flt(d.debit) > 0:
doc = frappe.get_doc("Loan", d.reference_name)
update_disbursement_status(doc)
update_total_amount_paid(doc)
doc.update_total_amount_paid()
doc.set_status()
def validate_expense_claim(self):
for d in self.accounts:
@@ -968,7 +967,7 @@ def get_exchange_rate(posting_date, account=None, account_currency=None, company
# The date used to retreive the exchange rate here is the date passed
# in as an argument to this function.
elif (not exchange_rate or exchange_rate==1) and account_currency and posting_date:
elif (not exchange_rate or flt(exchange_rate)==1) and account_currency and posting_date:
exchange_rate = get_exchange_rate(account_currency, company_currency, posting_date)
else:
exchange_rate = 1

View File

@@ -90,7 +90,6 @@
"fieldtype": "Column Break"
},
{
"default": "Customer",
"fieldname": "party_type",
"fieldtype": "Link",
"in_list_view": 1,
@@ -272,7 +271,7 @@
],
"idx": 1,
"istable": 1,
"modified": "2019-10-02 12:23:21.693443",
"modified": "2020-01-13 12:41:33.968025",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Journal Entry Account",

View File

@@ -11,6 +11,7 @@ class ModeofPayment(Document):
def validate(self):
self.validate_accounts()
self.validate_repeating_companies()
self.validate_pos_mode_of_payment()
def validate_repeating_companies(self):
"""Error when Same Company is entered multiple times in accounts"""
@@ -27,3 +28,15 @@ class ModeofPayment(Document):
if frappe.db.get_value("Account", entry.default_account, "company") != entry.company:
frappe.throw(_("Account {0} does not match with Company {1} in Mode of Account: {2}")
.format(entry.default_account, entry.company, self.name))
def validate_pos_mode_of_payment(self):
if not self.enabled:
pos_profiles = frappe.db.sql("""SELECT sip.parent FROM `tabSales Invoice Payment` sip
WHERE sip.parenttype = 'POS Profile' and sip.mode_of_payment = %s""", (self.name))
pos_profiles = list(map(lambda x: x[0], pos_profiles))
if pos_profiles:
message = "POS Profile " + frappe.bold(", ".join(pos_profiles)) + " contains \
Mode of Payment " + frappe.bold(str(self.name)) + ". Please remove them to disable this mode."
frappe.throw(_(message), title="Not Allowed")

View File

@@ -652,14 +652,16 @@ frappe.ui.form.on('Payment Entry', {
(frm.doc.payment_type=="Receive" && frm.doc.party_type=="Student")
) {
if(total_positive_outstanding > total_negative_outstanding)
frm.set_value("paid_amount",
total_positive_outstanding - total_negative_outstanding);
if (!frm.doc.paid_amount)
frm.set_value("paid_amount",
total_positive_outstanding - total_negative_outstanding);
} else if (
total_negative_outstanding &&
total_positive_outstanding < total_negative_outstanding
) {
frm.set_value("received_amount",
total_negative_outstanding - total_positive_outstanding);
if (!frm.doc.received_amount)
frm.set_value("received_amount",
total_negative_outstanding - total_positive_outstanding);
}
}

View File

@@ -102,7 +102,9 @@ class PaymentEntry(AccountsController):
self.bank = bank_data.bank
self.bank_account_no = bank_data.bank_account_no
self.set(field, bank_data.account)
if not self.get(field):
self.set(field, bank_data.account)
def validate_allocated_amount(self):
for d in self.get("references"):
@@ -911,7 +913,10 @@ def get_payment_entry(dt, dn, party_amount=None, bank_account=None, bank_amount=
else:
party_account = get_party_account(party_type, doc.get(party_type.lower()), doc.company)
party_account_currency = doc.get("party_account_currency") or get_account_currency(party_account)
if dt not in ("Sales Invoice", "Purchase Invoice"):
party_account_currency = get_account_currency(party_account)
else:
party_account_currency = doc.get("party_account_currency") or get_account_currency(party_account)
# payment type
if (dt == "Sales Order" or (dt in ("Sales Invoice", "Fees") and doc.outstanding_amount > 0)) \

View File

@@ -23,6 +23,8 @@ class PaymentReconciliation(Document):
if self.party_type in ["Customer", "Supplier"]:
dr_or_cr_notes = self.get_dr_or_cr_notes()
else:
dr_or_cr_notes = []
self.add_payment_entries(payment_entries + journal_entries + dr_or_cr_notes)

View File

@@ -2,6 +2,16 @@ cur_frm.add_fetch("payment_gateway_account", "payment_account", "payment_account
cur_frm.add_fetch("payment_gateway_account", "payment_gateway", "payment_gateway")
cur_frm.add_fetch("payment_gateway_account", "message", "message")
frappe.ui.form.on("Payment Request", {
setup: function(frm) {
frm.set_query("party_type", function() {
return {
query: "erpnext.setup.doctype.party_type.party_type.get_party_type",
};
});
}
})
frappe.ui.form.on("Payment Request", "onload", function(frm, dt, dn){
if (frm.doc.reference_doctype) {
frappe.call({

View File

@@ -350,13 +350,13 @@ def get_amount(ref_doc):
if dt in ["Sales Order", "Purchase Order"]:
grand_total = flt(ref_doc.grand_total) - flt(ref_doc.advance_paid)
if dt in ["Sales Invoice", "Purchase Invoice"]:
elif dt in ["Sales Invoice", "Purchase Invoice"]:
if ref_doc.party_account_currency == ref_doc.currency:
grand_total = flt(ref_doc.outstanding_amount)
else:
grand_total = flt(ref_doc.outstanding_amount) / ref_doc.conversion_rate
if dt == "Fees":
elif dt == "Fees":
grand_total = ref_doc.outstanding_amount
if grand_total > 0 :
@@ -373,6 +373,7 @@ def get_existing_payment_request_amount(ref_dt, ref_dn):
reference_doctype = %s
and reference_name = %s
and docstatus = 1
and status != 'Paid'
""", (ref_dt, ref_dn))
return flt(existing_payment_request_amount[0][0]) if existing_payment_request_amount else 0

View File

@@ -3,6 +3,7 @@
"autoname": "Prompt",
"creation": "2013-05-24 12:15:51",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"disabled",
"section_break_2",
@@ -50,6 +51,7 @@
"income_account",
"expense_account",
"taxes_and_charges",
"tax_category",
"apply_discount_on",
"accounting_dimensions_section",
"cost_center",
@@ -381,11 +383,17 @@
{
"fieldname": "dimension_col_break",
"fieldtype": "Column Break"
},
{
"fieldname": "tax_category",
"fieldtype": "Link",
"label": "Tax Category",
"options": "Tax Category"
}
],
"icon": "icon-cog",
"idx": 1,
"modified": "2019-05-25 22:56:30.352693",
"modified": "2020-01-24 15:52:03.797701",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Profile",

View File

@@ -389,8 +389,7 @@
"fieldname": "rate_or_discount",
"fieldtype": "Select",
"label": "Rate or Discount",
"options": "\nRate\nDiscount Percentage\nDiscount Amount",
"reqd": 1
"options": "\nRate\nDiscount Percentage\nDiscount Amount"
},
{
"default": "Grand Total",
@@ -439,19 +438,20 @@
},
{
"default": "0",
"depends_on": "eval:!doc.mixed_conditions",
"depends_on": "eval:!doc.mixed_conditions && doc.apply_on != 'Transaction'",
"fieldname": "same_item",
"fieldtype": "Check",
"label": "Same Item"
},
{
"depends_on": "eval:!doc.same_item || doc.mixed_conditions",
"depends_on": "eval:(!doc.same_item || doc.apply_on == 'Transaction') || doc.mixed_conditions",
"fieldname": "free_item",
"fieldtype": "Link",
"label": "Free Item",
"options": "Item"
},
{
"default": "0",
"fieldname": "free_qty",
"fieldtype": "Float",
"label": "Qty"
@@ -554,7 +554,7 @@
],
"icon": "fa fa-gift",
"idx": 1,
"modified": "2019-10-15 12:39:40.399792",
"modified": "2019-12-18 17:29:22.957077",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Pricing Rule",

View File

@@ -34,6 +34,9 @@ class PricingRule(Document):
def validate_duplicate_apply_on(self):
field = apply_on_dict.get(self.apply_on)
if not field:
return False
values = [d.get(frappe.scrub(self.apply_on)) for d in self.get(field)]
if len(values) != len(set(values)):
@@ -48,6 +51,9 @@ class PricingRule(Document):
if tocheck and not self.get(tocheck):
throw(_("{0} is required").format(self.meta.get_label(tocheck)), frappe.MandatoryError)
if self.price_or_product_discount == 'Price' and not self.rate_or_discount:
throw(_("Rate or Discount is required for the price discount."), frappe.MandatoryError)
def validate_applicable_for_selling_or_buying(self):
if not self.selling and not self.buying:
throw(_("Atleast one of the Selling or Buying must be selected"))
@@ -183,7 +189,7 @@ def get_serial_no_for_item(args):
def get_pricing_rule_for_item(args, price_list_rate=0, doc=None, for_validate=False):
from erpnext.accounts.doctype.pricing_rule.utils import (get_pricing_rules,
get_applied_pricing_rules, get_pricing_rule_items)
get_applied_pricing_rules, get_pricing_rule_items, get_product_discount_rule)
if isinstance(doc, string_types):
doc = json.loads(doc)
@@ -242,9 +248,11 @@ def get_pricing_rule_for_item(args, price_list_rate=0, doc=None, for_validate=Fa
if pricing_rule.coupon_code_based==1 and args.coupon_code==None:
return item_details
if (not pricing_rule.validate_applied_rule and
pricing_rule.price_or_product_discount == "Price"):
apply_price_discount_pricing_rule(pricing_rule, item_details, args)
if not pricing_rule.validate_applied_rule:
if pricing_rule.price_or_product_discount == "Price":
apply_price_discount_rule(pricing_rule, item_details, args)
else:
get_product_discount_rule(pricing_rule, item_details, doc)
item_details.has_pricing_rule = 1
@@ -294,7 +302,7 @@ def get_pricing_rule_details(args, pricing_rule):
'child_docname': args.get('child_docname')
})
def apply_price_discount_pricing_rule(pricing_rule, item_details, args):
def apply_price_discount_rule(pricing_rule, item_details, args):
item_details.pricing_rule_for = pricing_rule.rate_or_discount
if ((pricing_rule.margin_type == 'Amount' and pricing_rule.currency == args.currency)
@@ -414,4 +422,4 @@ def get_item_uoms(doctype, txt, searchfield, start, page_len, filters):
return frappe.get_all('UOM Conversion Detail',
filters = {'parent': ('in', items), 'uom': ("like", "{0}%".format(txt))},
fields = ["distinct uom"], as_list=1)
fields = ["distinct uom"], as_list=1)

View File

@@ -9,6 +9,8 @@ from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_orde
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.stock.get_item_details import get_item_details
from frappe import MandatoryError
from erpnext.stock.doctype.item.test_item import make_item
from erpnext.healthcare.doctype.lab_test_template.lab_test_template import make_item_price
class TestPricingRule(unittest.TestCase):
def setUp(self):
@@ -145,6 +147,52 @@ class TestPricingRule(unittest.TestCase):
self.assertEquals(details.get("margin_type"), "Percentage")
self.assertEquals(details.get("margin_rate_or_amount"), 10)
def test_mixed_conditions_for_item_group(self):
for item in ["Mixed Cond Item 1", "Mixed Cond Item 2"]:
make_item(item, {"item_group": "Products"})
make_item_price(item, "_Test Price List", 100)
test_record = {
"doctype": "Pricing Rule",
"title": "_Test Pricing Rule for Item Group",
"apply_on": "Item Group",
"item_groups": [
{
"item_group": "Products",
},
{
"item_group": "Seed",
},
],
"selling": 1,
"mixed_conditions": 1,
"currency": "USD",
"rate_or_discount": "Discount Percentage",
"discount_percentage": 10,
"applicable_for": "Customer Group",
"customer_group": "All Customer Groups",
"company": "_Test Company"
}
frappe.get_doc(test_record.copy()).insert()
args = frappe._dict({
"item_code": "Mixed Cond Item 1",
"item_group": "Products",
"company": "_Test Company",
"price_list": "_Test Price List",
"currency": "_Test Currency",
"doctype": "Sales Order",
"conversion_rate": 1,
"price_list_currency": "_Test Currency",
"plc_conversion_rate": 1,
"order_type": "Sales",
"customer": "_Test Customer",
"customer_group": "_Test Customer Group",
"name": None
})
details = get_item_details(args)
self.assertEquals(details.get("discount_percentage"), 10)
def test_pricing_rule_for_variants(self):
from erpnext.stock.get_item_details import get_item_details
from frappe import MandatoryError

View File

@@ -7,7 +7,7 @@ from __future__ import unicode_literals
import frappe, copy, json
from frappe import throw, _
from six import string_types
from frappe.utils import flt, cint, get_datetime
from frappe.utils import flt, cint, get_datetime, get_link_to_form, today
from erpnext.setup.doctype.item_group.item_group import get_child_item_groups
from erpnext.stock.doctype.warehouse.warehouse import get_child_warehouses
from erpnext.stock.get_item_details import get_conversion_factor
@@ -284,7 +284,7 @@ def filter_pricing_rules_for_qty_amount(qty, rate, pricing_rules, args=None):
status = True
# if user has created item price against the transaction UOM
if rule.get("uom") == args.get("uom"):
if args and rule.get("uom") == args.get("uom"):
conversion_factor = 1.0
if status and (flt(rate) >= (flt(rule.min_amt) * conversion_factor)
@@ -408,7 +408,8 @@ def apply_pricing_rule_on_transaction(doc):
conditions = get_other_conditions(conditions, values, doc)
pricing_rules = frappe.db.sql(""" Select `tabPricing Rule`.* from `tabPricing Rule`
where {conditions} """.format(conditions = conditions), values, as_dict=1)
where {conditions} and `tabPricing Rule`.disable = 0
""".format(conditions = conditions), values, as_dict=1)
if pricing_rules:
pricing_rules = filter_pricing_rules_for_qty_amount(doc.total_qty,
@@ -420,39 +421,65 @@ def apply_pricing_rule_on_transaction(doc):
doc.set('apply_discount_on', d.apply_discount_on)
for field in ['additional_discount_percentage', 'discount_amount']:
if not d.get(field): continue
pr_field = ('discount_percentage'
if field == 'additional_discount_percentage' else field)
if not d.get(pr_field): continue
if d.validate_applied_rule and doc.get(field) < d.get(pr_field):
frappe.msgprint(_("User has not applied rule on the invoice {0}")
.format(doc.name))
else:
doc.set(field, d.get(pr_field))
doc.calculate_taxes_and_totals()
elif d.price_or_product_discount == 'Product':
apply_pricing_rule_for_free_items(doc, d)
item_details = frappe._dict({'parenttype': doc.doctype})
get_product_discount_rule(d, item_details, doc)
apply_pricing_rule_for_free_items(doc, item_details.free_item_data)
doc.set_missing_values()
def get_applied_pricing_rules(item_row):
return (item_row.get("pricing_rules").split(',')
if item_row.get("pricing_rules") else [])
def apply_pricing_rule_for_free_items(doc, pricing_rule):
if pricing_rule.get('free_item'):
def get_product_discount_rule(pricing_rule, item_details, doc=None):
free_item = (pricing_rule.free_item
if not pricing_rule.same_item or pricing_rule.apply_on == 'Transaction' else item_details.item_code)
if not free_item:
frappe.throw(_("Free item not set in the pricing rule {0}")
.format(get_link_to_form("Pricing Rule", pricing_rule.name)))
item_details.free_item_data = {
'item_code': free_item,
'qty': pricing_rule.free_qty or 1,
'rate': pricing_rule.free_item_rate or 0,
'price_list_rate': pricing_rule.free_item_rate or 0,
'is_free_item': 1
}
item_data = frappe.get_cached_value('Item', free_item, ['item_name',
'description', 'stock_uom'], as_dict=1)
item_details.free_item_data.update(item_data)
item_details.free_item_data['uom'] = pricing_rule.free_item_uom or item_data.stock_uom
item_details.free_item_data['conversion_factor'] = get_conversion_factor(free_item,
item_details.free_item_data['uom']).get("conversion_factor", 1)
if item_details.get("parenttype") == 'Purchase Order':
item_details.free_item_data['schedule_date'] = doc.schedule_date if doc else today()
if item_details.get("parenttype") == 'Sales Order':
item_details.free_item_data['delivery_date'] = doc.delivery_date if doc else today()
def apply_pricing_rule_for_free_items(doc, pricing_rule_args, set_missing_values=False):
if pricing_rule_args.get('item_code'):
items = [d.item_code for d in doc.items
if d.item_code == (d.item_code
if pricing_rule.get('same_item') else pricing_rule.get('free_item')) and d.is_free_item]
if d.item_code == (pricing_rule_args.get("item_code")) and d.is_free_item]
if not items:
doc.append('items', {
'item_code': pricing_rule.get('free_item'),
'qty': pricing_rule.get('free_qty'),
'uom': pricing_rule.get('free_item_uom'),
'rate': pricing_rule.get('free_item_rate') or 0,
'is_free_item': 1
})
doc.set_missing_values()
doc.append('items', pricing_rule_args)
def get_pricing_rule_items(pr_doc):
apply_on_data = []
@@ -462,13 +489,13 @@ def get_pricing_rule_items(pr_doc):
for d in pr_doc.get(pricing_rule_apply_on):
if apply_on == 'item_group':
get_child_item_groups(d.get(apply_on))
apply_on_data.extend(get_child_item_groups(d.get(apply_on)))
else:
apply_on_data.append(d.get(apply_on))
if pr_doc.apply_rule_on_other:
apply_on = frappe.scrub(pr_doc.apply_rule_on_other)
apply_on_data.append(pr_doc.get(apply_on))
apply_on_data.append(pr_doc.get("other_" + apply_on))
return list(set(apply_on_data))

View File

@@ -167,8 +167,15 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
make_comment_dialog_and_block_invoice: function(){
const me = this;
const title = __('Add Comment');
const title = __('Block Invoice');
const fields = [
{
fieldname: 'release_date',
read_only: 0,
fieldtype:'Date',
label: __('Release Date'),
default: me.frm.doc.release_date
},
{
fieldname: 'hold_comment',
read_only: 0,
@@ -187,7 +194,11 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
const dialog_data = me.dialog.get_values();
frappe.call({
'method': 'erpnext.accounts.doctype.purchase_invoice.purchase_invoice.block_invoice',
'args': {'name': me.frm.doc.name, 'hold_comment': dialog_data.hold_comment},
'args': {
'name': me.frm.doc.name,
'hold_comment': dialog_data.hold_comment,
'release_date': dialog_data.release_date
},
'callback': (r) => me.frm.reload_doc()
});
me.dialog.hide();
@@ -330,23 +341,6 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
frm: cur_frm
})
},
item_code: function(frm, cdt, cdn) {
var row = locals[cdt][cdn];
if(row.item_code) {
frappe.call({
method: "erpnext.assets.doctype.asset_category.asset_category.get_asset_category_account",
args: {
"item": row.item_code,
"fieldname": "fixed_asset_account",
"company": frm.doc.company
},
callback: function(r, rt) {
frappe.model.set_value(cdt, cdn, "expense_account", r.message);
}
})
}
}
});
cur_frm.script_manager.make(erpnext.accounts.PurchaseInvoice);
@@ -399,21 +393,11 @@ cur_frm.fields_dict['items'].grid.get_field("item_code").get_query = function(do
cur_frm.fields_dict['credit_to'].get_query = function(doc) {
// filter on Account
if (doc.supplier) {
return {
filters: {
'account_type': 'Payable',
'is_group': 0,
'company': doc.company
}
}
} else {
return {
filters: {
'report_type': 'Balance Sheet',
'is_group': 0,
'company': doc.company
}
return {
filters: {
'account_type': 'Payable',
'is_group': 0,
'company': doc.company
}
}
}

View File

@@ -1,4 +1,5 @@
{
"actions": [],
"allow_import": 1,
"autoname": "naming_series:",
"creation": "2013-05-21 16:16:39",
@@ -417,6 +418,7 @@
"fieldname": "contact_email",
"fieldtype": "Small Text",
"label": "Contact Email",
"options": "Email",
"print_hide": 1,
"read_only": 1
},
@@ -705,7 +707,7 @@
},
{
"fieldname": "other_charges_calculation",
"fieldtype": "Text",
"fieldtype": "Long Text",
"label": "Taxes and Charges Calculation",
"no_copy": 1,
"oldfieldtype": "HTML",
@@ -1287,7 +1289,8 @@
"icon": "fa fa-file-text",
"idx": 204,
"is_submittable": 1,
"modified": "2019-09-17 22:31:42.666601",
"links": [],
"modified": "2019-12-30 19:13:49.610538",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",

View File

@@ -248,7 +248,7 @@ class PurchaseInvoice(BuyingController):
def set_against_expense_account(self):
against_accounts = []
for item in self.get("items"):
if item.expense_account not in against_accounts:
if item.expense_account and (item.expense_account not in against_accounts):
against_accounts.append(item.expense_account)
self.against_expense_account = ",".join(against_accounts)
@@ -830,7 +830,11 @@ class PurchaseInvoice(BuyingController):
)
def make_gle_for_rounding_adjustment(self, gl_entries):
if self.rounding_adjustment:
# if rounding adjustment in small and conversion rate is also small then
# base_rounding_adjustment may become zero due to small precision
# eg: rounding_adjustment = 0.01 and exchange rate = 0.05 and precision of base_rounding_adjustment is 2
# then base_rounding_adjustment becomes zero and error is thrown in GL Entry
if self.rounding_adjustment and self.base_rounding_adjustment:
round_off_account, round_off_cost_center = \
get_round_off_account_and_cost_center(self.company)
@@ -862,6 +866,7 @@ class PurchaseInvoice(BuyingController):
# because updating ordered qty in bin depends upon updated ordered qty in PO
if self.update_stock == 1:
self.update_stock_ledger()
self.delete_auto_created_batches()
self.make_gl_entries_on_cancel()
self.update_project()
@@ -923,9 +928,10 @@ class PurchaseInvoice(BuyingController):
def on_recurring(self, reference_doc, auto_repeat_doc):
self.due_date = None
def block_invoice(self, hold_comment=None):
def block_invoice(self, hold_comment=None, release_date=None):
self.db_set('on_hold', 1)
self.db_set('hold_comment', cstr(hold_comment))
self.db_set('release_date', release_date)
def unblock_invoice(self):
self.db_set('on_hold', 0)
@@ -1009,10 +1015,10 @@ def unblock_invoice(name):
@frappe.whitelist()
def block_invoice(name, hold_comment):
def block_invoice(name, release_date, hold_comment=None):
if frappe.db.exists('Purchase Invoice', name):
pi = frappe.get_doc('Purchase Invoice', name)
pi.block_invoice(hold_comment)
pi.block_invoice(hold_comment, release_date)
@frappe.whitelist()
def make_inter_company_sales_invoice(source_name, target_doc=None):

View File

@@ -0,0 +1,3 @@
{% include "erpnext/regional/india/taxes.js" %}
erpnext.setup_auto_gst_taxation('Purchase Invoice');

View File

@@ -1,4 +1,5 @@
{
"actions": [],
"autoname": "hash",
"creation": "2013-05-22 12:43:10",
"doctype": "DocType",
@@ -507,7 +508,8 @@
"depends_on": "enable_deferred_expense",
"fieldname": "service_stop_date",
"fieldtype": "Date",
"label": "Service Stop Date"
"label": "Service Stop Date",
"no_copy": 1
},
{
"default": "0",
@@ -523,13 +525,15 @@
"depends_on": "enable_deferred_expense",
"fieldname": "service_start_date",
"fieldtype": "Date",
"label": "Service Start Date"
"label": "Service Start Date",
"no_copy": 1
},
{
"depends_on": "enable_deferred_expense",
"fieldname": "service_end_date",
"fieldtype": "Date",
"label": "Service End Date"
"label": "Service End Date",
"no_copy": 1
},
{
"fieldname": "reference",
@@ -766,7 +770,8 @@
],
"idx": 1,
"istable": 1,
"modified": "2019-11-21 16:27:52.043744",
"links": [],
"modified": "2019-12-04 12:23:17.046413",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",

View File

@@ -1,300 +1,108 @@
{
"allow_copy": 0,
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:title",
"beta": 0,
"creation": "2013-01-10 16:34:08",
"custom": 0,
"description": "Standard tax template that can be applied to all Purchase Transactions. This template can contain list of tax heads and also other expense heads like \"Shipping\", \"Insurance\", \"Handling\" etc.\n\n#### Note\n\nThe tax rate you define here will be the standard tax rate for all **Items**. If there are **Items** that have different rates, they must be added in the **Item Tax** table in the **Item** master.\n\n#### Description of Columns\n\n1. Calculation Type: \n - This can be on **Net Total** (that is the sum of basic amount).\n - **On Previous Row Total / Amount** (for cumulative taxes or charges). If you select this option, the tax will be applied as a percentage of the previous row (in the tax table) amount or total.\n - **Actual** (as mentioned).\n2. Account Head: The Account ledger under which this tax will be booked\n3. Cost Center: If the tax / charge is an income (like shipping) or expense it needs to be booked against a Cost Center.\n4. Description: Description of the tax (that will be printed in invoices / quotes).\n5. Rate: Tax rate.\n6. Amount: Tax amount.\n7. Total: Cumulative total to this point.\n8. Enter Row: If based on \"Previous Row Total\" you can select the row number which will be taken as a base for this calculation (default is the previous row).\n9. Consider Tax or Charge for: In this section you can specify if the tax / charge is only for valuation (not a part of total) or only for total (does not add value to the item) or for both.\n10. Add or Deduct: Whether you want to add or deduct the tax.",
"docstatus": 0,
"doctype": "DocType",
"document_type": "Setup",
"editable_grid": 0,
"allow_import": 1,
"allow_rename": 1,
"creation": "2013-01-10 16:34:08",
"description": "Standard tax template that can be applied to all Purchase Transactions. This template can contain list of tax heads and also other expense heads like \"Shipping\", \"Insurance\", \"Handling\" etc.\n\n#### Note\n\nThe tax rate you define here will be the standard tax rate for all **Items**. If there are **Items** that have different rates, they must be added in the **Item Tax** table in the **Item** master.\n\n#### Description of Columns\n\n1. Calculation Type: \n - This can be on **Net Total** (that is the sum of basic amount).\n - **On Previous Row Total / Amount** (for cumulative taxes or charges). If you select this option, the tax will be applied as a percentage of the previous row (in the tax table) amount or total.\n - **Actual** (as mentioned).\n2. Account Head: The Account ledger under which this tax will be booked\n3. Cost Center: If the tax / charge is an income (like shipping) or expense it needs to be booked against a Cost Center.\n4. Description: Description of the tax (that will be printed in invoices / quotes).\n5. Rate: Tax rate.\n6. Amount: Tax amount.\n7. Total: Cumulative total to this point.\n8. Enter Row: If based on \"Previous Row Total\" you can select the row number which will be taken as a base for this calculation (default is the previous row).\n9. Consider Tax or Charge for: In this section you can specify if the tax / charge is only for valuation (not a part of total) or only for total (does not add value to the item) or for both.\n10. Add or Deduct: Whether you want to add or deduct the tax.",
"doctype": "DocType",
"document_type": "Setup",
"field_order": [
"title",
"is_default",
"disabled",
"column_break4",
"company",
"tax_category",
"section_break6",
"taxes"
],
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "title",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Title",
"length": 0,
"no_copy": 1,
"oldfieldname": "title",
"oldfieldtype": "Data",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "title",
"fieldtype": "Data",
"label": "Title",
"no_copy": 1,
"oldfieldname": "title",
"oldfieldtype": "Data",
"reqd": 1
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "is_default",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Default",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"default": "0",
"fieldname": "is_default",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Default"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "disabled",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Disabled",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"default": "0",
"fieldname": "disabled",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Disabled"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break4",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "column_break4",
"fieldtype": "Column Break"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Company",
"length": 0,
"no_copy": 0,
"options": "Company",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 1,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "company",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Company",
"options": "Company",
"remember_last_selected_value": 1,
"reqd": 1
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break6",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "section_break6",
"fieldtype": "Section Break"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "taxes",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Purchase Taxes and Charges",
"length": 0,
"no_copy": 0,
"oldfieldname": "purchase_tax_details",
"oldfieldtype": "Table",
"options": "Purchase Taxes and Charges",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
"fieldname": "taxes",
"fieldtype": "Table",
"label": "Purchase Taxes and Charges",
"oldfieldname": "purchase_tax_details",
"oldfieldtype": "Table",
"options": "Purchase Taxes and Charges"
},
{
"fieldname": "tax_category",
"fieldtype": "Link",
"label": "Tax Category",
"options": "Tax Category"
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "fa fa-money",
"idx": 1,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-11-07 05:18:44.095798",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Taxes and Charges Template",
"owner": "wasim@webnotestech.com",
],
"icon": "fa fa-money",
"idx": 1,
"modified": "2019-11-25 13:05:26.220275",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Taxes and Charges Template",
"owner": "wasim@webnotestech.com",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"is_custom": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Purchase Manager",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
},
"email": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Purchase Manager"
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"is_custom": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Purchase Master Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"create": 1,
"delete": 1,
"email": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Purchase Master Manager",
"share": 1,
"write": 1
},
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 0,
"export": 0,
"if_owner": 0,
"import": 0,
"is_custom": 0,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 0,
"role": "Purchase User",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
"read": 1,
"role": "Purchase User"
}
],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"sort_order": "DESC",
"track_seen": 0
],
"sort_order": "DESC",
"track_changes": 1
}

View File

@@ -152,8 +152,11 @@ def update_multi_mode_option(doc, pos_profile):
def get_mode_of_payment(doc):
return frappe.db.sql(""" select mpa.default_account, mpa.parent, mp.type as type from `tabMode of Payment Account` mpa, \
`tabMode of Payment` mp where mpa.parent = mp.name and mpa.company = %(company)s""", {'company': doc.company}, as_dict=1)
return frappe.db.sql("""
select mpa.default_account, mpa.parent, mp.type as type
from `tabMode of Payment Account` mpa,`tabMode of Payment` mp
where mpa.parent = mp.name and mpa.company = %(company)s and mp.enabled = 1""",
{'company': doc.company}, as_dict=1)
def update_tax_table(doc):

View File

@@ -1,3 +1,7 @@
{% include "erpnext/regional/india/taxes.js" %}
erpnext.setup_auto_gst_taxation('Sales Invoice');
frappe.ui.form.on("Sales Invoice", {
setup: function(frm) {
frm.set_query('transporter', function() {
@@ -34,5 +38,8 @@ frappe.ui.form.on("Sales Invoice", {
}
}, __("Make"));
}
}
},
});

View File

@@ -556,22 +556,11 @@ cur_frm.cscript.cost_center = function(doc, cdt, cdn) {
}
cur_frm.set_query("debit_to", function(doc) {
// filter on Account
if (doc.customer) {
return {
filters: {
'account_type': 'Receivable',
'is_group': 0,
'company': doc.company
}
}
} else {
return {
filters: {
'report_type': 'Balance Sheet',
'is_group': 0,
'company': doc.company
}
return {
filters: {
'account_type': 'Receivable',
'is_group': 0,
'company': doc.company
}
}
});
@@ -697,8 +686,8 @@ frappe.ui.form.on('Sales Invoice', {
if (frm.doc.company)
{
frappe.call({
method:"frappe.contacts.doctype.address.address.get_default_address",
args:{ doctype:'Company',name:frm.doc.company},
method:"erpnext.setup.doctype.company.company.get_default_company_address",
args:{name:frm.doc.company, existing_address: frm.doc.company_address},
callback: function(r){
if (r.message){
frm.set_value("company_address",r.message)

View File

@@ -372,7 +372,8 @@
"no_copy": 1,
"options": "Sales Invoice",
"print_hide": 1,
"read_only": 1
"read_only": 1,
"search_index": 1
},
{
"fieldname": "column_break_21",
@@ -774,7 +775,7 @@
},
{
"fieldname": "other_charges_calculation",
"fieldtype": "Text",
"fieldtype": "Long Text",
"label": "Taxes and Charges Calculation",
"no_copy": 1,
"oldfieldtype": "HTML",
@@ -1567,7 +1568,7 @@
"icon": "fa fa-file-text",
"idx": 181,
"is_submittable": 1,
"modified": "2019-10-05 21:39:49.235990",
"modified": "2020-02-10 04:57:11.221180",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",

View File

@@ -412,6 +412,9 @@ class SalesInvoice(SellingController):
if pos:
self.allow_print_before_pay = pos.allow_print_before_pay
if not for_validate:
self.tax_category = pos.get("tax_category")
if not for_validate and not self.customer:
self.customer = pos.customer
@@ -953,7 +956,7 @@ class SalesInvoice(SellingController):
)
def make_gle_for_rounding_adjustment(self, gl_entries):
if flt(self.rounding_adjustment, self.precision("rounding_adjustment")):
if flt(self.rounding_adjustment, self.precision("rounding_adjustment")) and self.base_rounding_adjustment:
round_off_account, round_off_cost_center = \
get_round_off_account_and_cost_center(self.company)
@@ -1048,13 +1051,18 @@ class SalesInvoice(SellingController):
continue
for serial_no in item.serial_no.split("\n"):
sales_invoice, item_code = frappe.db.get_value("Serial No", serial_no,
["sales_invoice", "item_code"])
if sales_invoice and item_code == item.item_code and self.name != sales_invoice:
sales_invoice_company = frappe.db.get_value("Sales Invoice", sales_invoice, "company")
serial_no_details = frappe.db.get_value("Serial No", serial_no,
["sales_invoice", "item_code"], as_dict=1)
if not serial_no_details:
continue
if serial_no_details.sales_invoice and serial_no_details.item_code == item.item_code \
and self.name != serial_no_details.sales_invoice:
sales_invoice_company = frappe.db.get_value("Sales Invoice", serial_no_details.sales_invoice, "company")
if sales_invoice_company == self.company:
frappe.throw(_("Serial Number: {0} is already referenced in Sales Invoice: {1}"
.format(serial_no, sales_invoice)))
.format(serial_no, serial_no_details.sales_invoice)))
def update_project(self):
if self.project:
@@ -1227,24 +1235,27 @@ class SalesInvoice(SellingController):
self.status = 'Draft'
return
precision = self.precision("outstanding_amount")
outstanding_amount = flt(self.outstanding_amount, precision)
if not status:
if self.docstatus == 2:
status = "Cancelled"
elif self.docstatus == 1:
if flt(self.outstanding_amount) > 0 and getdate(self.due_date) < getdate(nowdate()) and self.is_discounted and self.get_discounting_status()=='Disbursed':
if outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()) and self.is_discounted and self.get_discounting_status()=='Disbursed':
self.status = "Overdue and Discounted"
elif flt(self.outstanding_amount) > 0 and getdate(self.due_date) < getdate(nowdate()):
elif outstanding_amount > 0 and getdate(self.due_date) < getdate(nowdate()):
self.status = "Overdue"
elif flt(self.outstanding_amount) > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.is_discounted and self.get_discounting_status()=='Disbursed':
elif outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()) and self.is_discounted and self.get_discounting_status()=='Disbursed':
self.status = "Unpaid and Discounted"
elif flt(self.outstanding_amount) > 0 and getdate(self.due_date) >= getdate(nowdate()):
elif outstanding_amount > 0 and getdate(self.due_date) >= getdate(nowdate()):
self.status = "Unpaid"
#Check if outstanding amount is 0 due to credit note issued against invoice
elif flt(self.outstanding_amount) <= 0 and self.is_return == 0 and frappe.db.get_value('Sales Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1}):
elif outstanding_amount <= 0 and self.is_return == 0 and frappe.db.get_value('Sales Invoice', {'is_return': 1, 'return_against': self.name, 'docstatus': 1}):
self.status = "Credit Note Issued"
elif self.is_return == 1:
self.status = "Return"
elif flt(self.outstanding_amount)<=0:
elif outstanding_amount <=0:
self.status = "Paid"
else:
self.status = "Submitted"

View File

@@ -5,7 +5,7 @@ from __future__ import unicode_literals
import frappe
import unittest, copy, time
from frappe.utils import nowdate, flt, getdate, cint
from frappe.utils import nowdate, flt, getdate, cint, add_days
from frappe.model.dynamic_links import get_dynamic_link_map
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import unlink_payment_on_cancel_of_invoice
@@ -1847,6 +1847,26 @@ class TestSalesInvoice(unittest.TestCase):
self.assertEqual(data['billLists'][0]['vehicleNo'], 'KA12KA1234')
self.assertEqual(data['billLists'][0]['itemList'][0]['taxableAmount'], 60000)
def test_item_tax_validity(self):
item = frappe.get_doc("Item", "_Test Item 2")
if item.taxes:
item.taxes = []
item.save()
item.append("taxes", {
"item_tax_template": "_Test Item Tax Template 1",
"valid_from": add_days(nowdate(), 1)
})
item.save()
sales_invoice = create_sales_invoice(item = "_Test Item 2", do_not_save=1)
sales_invoice.items[0].item_tax_template = "_Test Item Tax Template 1"
self.assertRaises(frappe.ValidationError, sales_invoice.save)
item.taxes = []
item.save()
def create_sales_invoice(**args):
si = frappe.new_doc("Sales Invoice")

View File

@@ -1,4 +1,5 @@
{
"actions": [],
"autoname": "hash",
"creation": "2013-06-04 11:02:19",
"doctype": "DocType",
@@ -484,7 +485,8 @@
"depends_on": "enable_deferred_revenue",
"fieldname": "service_stop_date",
"fieldtype": "Date",
"label": "Service Stop Date"
"label": "Service Stop Date",
"no_copy": 1
},
{
"default": "0",
@@ -500,13 +502,15 @@
"depends_on": "enable_deferred_revenue",
"fieldname": "service_start_date",
"fieldtype": "Date",
"label": "Service Start Date"
"label": "Service Start Date",
"no_copy": 1
},
{
"depends_on": "enable_deferred_revenue",
"fieldname": "service_end_date",
"fieldtype": "Date",
"label": "Service End Date"
"label": "Service End Date",
"no_copy": 1
},
{
"collapsible": 1,
@@ -783,7 +787,8 @@
],
"idx": 1,
"istable": 1,
"modified": "2019-07-16 16:36:46.527606",
"links": [],
"modified": "2019-12-04 12:22:38.517710",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Item",

View File

@@ -1,299 +1,119 @@
{
"allow_copy": 0,
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:title",
"beta": 0,
"creation": "2013-01-10 16:34:09",
"custom": 0,
"description": "Standard tax template that can be applied to all Sales Transactions. This template can contain list of tax heads and also other expense / income heads like \"Shipping\", \"Insurance\", \"Handling\" etc.\n\n#### Note\n\nThe tax rate you define here will be the standard tax rate for all **Items**. If there are **Items** that have different rates, they must be added in the **Item Tax** table in the **Item** master.\n\n#### Description of Columns\n\n1. Calculation Type: \n - This can be on **Net Total** (that is the sum of basic amount).\n - **On Previous Row Total / Amount** (for cumulative taxes or charges). If you select this option, the tax will be applied as a percentage of the previous row (in the tax table) amount or total.\n - **Actual** (as mentioned).\n2. Account Head: The Account ledger under which this tax will be booked\n3. Cost Center: If the tax / charge is an income (like shipping) or expense it needs to be booked against a Cost Center.\n4. Description: Description of the tax (that will be printed in invoices / quotes).\n5. Rate: Tax rate.\n6. Amount: Tax amount.\n7. Total: Cumulative total to this point.\n8. Enter Row: If based on \"Previous Row Total\" you can select the row number which will be taken as a base for this calculation (default is the previous row).\n9. Is this Tax included in Basic Rate?: If you check this, it means that this tax will not be shown below the item table, but will be included in the Basic Rate in your main item table. This is useful where you want give a flat price (inclusive of all taxes) price to customers.",
"docstatus": 0,
"doctype": "DocType",
"document_type": "Setup",
"editable_grid": 0,
"allow_import": 1,
"allow_rename": 1,
"creation": "2013-01-10 16:34:09",
"description": "Standard tax template that can be applied to all Sales Transactions. This template can contain list of tax heads and also other expense / income heads like \"Shipping\", \"Insurance\", \"Handling\" etc.\n\n#### Note\n\nThe tax rate you define here will be the standard tax rate for all **Items**. If there are **Items** that have different rates, they must be added in the **Item Tax** table in the **Item** master.\n\n#### Description of Columns\n\n1. Calculation Type: \n - This can be on **Net Total** (that is the sum of basic amount).\n - **On Previous Row Total / Amount** (for cumulative taxes or charges). If you select this option, the tax will be applied as a percentage of the previous row (in the tax table) amount or total.\n - **Actual** (as mentioned).\n2. Account Head: The Account ledger under which this tax will be booked\n3. Cost Center: If the tax / charge is an income (like shipping) or expense it needs to be booked against a Cost Center.\n4. Description: Description of the tax (that will be printed in invoices / quotes).\n5. Rate: Tax rate.\n6. Amount: Tax amount.\n7. Total: Cumulative total to this point.\n8. Enter Row: If based on \"Previous Row Total\" you can select the row number which will be taken as a base for this calculation (default is the previous row).\n9. Is this Tax included in Basic Rate?: If you check this, it means that this tax will not be shown below the item table, but will be included in the Basic Rate in your main item table. This is useful where you want give a flat price (inclusive of all taxes) price to customers.",
"doctype": "DocType",
"document_type": "Setup",
"engine": "InnoDB",
"field_order": [
"title",
"is_default",
"disabled",
"column_break_3",
"company",
"tax_category",
"section_break_5",
"taxes"
],
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "title",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Title",
"length": 0,
"no_copy": 1,
"oldfieldname": "title",
"oldfieldtype": "Data",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "title",
"fieldtype": "Data",
"label": "Title",
"no_copy": 1,
"oldfieldname": "title",
"oldfieldtype": "Data",
"reqd": 1
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "is_default",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Default",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"default": "0",
"fieldname": "is_default",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Default"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "disabled",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Disabled",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"default": "0",
"fieldname": "disabled",
"fieldtype": "Check",
"label": "Disabled"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_3",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "column_break_3",
"fieldtype": "Column Break"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Company",
"length": 0,
"no_copy": 0,
"oldfieldname": "company",
"oldfieldtype": "Link",
"options": "Company",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 1,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "company",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Company",
"oldfieldname": "company",
"oldfieldtype": "Link",
"options": "Company",
"remember_last_selected_value": 1,
"reqd": 1
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_5",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "section_break_5",
"fieldtype": "Section Break"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "* Will be calculated in the transaction.",
"fieldname": "taxes",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Sales Taxes and Charges",
"length": 0,
"no_copy": 0,
"oldfieldname": "other_charges",
"oldfieldtype": "Table",
"options": "Sales Taxes and Charges",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
"description": "* Will be calculated in the transaction.",
"fieldname": "taxes",
"fieldtype": "Table",
"label": "Sales Taxes and Charges",
"oldfieldname": "other_charges",
"oldfieldtype": "Table",
"options": "Sales Taxes and Charges"
},
{
"fieldname": "tax_category",
"fieldtype": "Link",
"label": "Tax Category",
"options": "Tax Category"
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "fa fa-money",
"idx": 1,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2016-11-07 05:18:41.743257",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Taxes and Charges Template",
"owner": "Administrator",
],
"icon": "fa fa-money",
"idx": 1,
"modified": "2019-11-25 13:06:03.279099",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Taxes and Charges Template",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 1,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"is_custom": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales User",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
},
"email": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales User"
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"is_custom": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"create": 1,
"delete": 1,
"email": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"share": 1,
"write": 1
},
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"is_custom": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales Master Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"create": 1,
"delete": 1,
"email": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales Master Manager",
"share": 1,
"write": 1
}
],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"sort_order": "ASC",
"track_seen": 0
],
"sort_field": "modified",
"sort_order": "ASC",
"track_changes": 1
}

View File

@@ -188,7 +188,7 @@
}
],
"is_submittable": 1,
"modified": "2019-11-07 13:31:17.999744",
"modified": "2019-12-20 14:48:01.990600",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Share Transfer",
@@ -196,6 +196,7 @@
"permissions": [
{
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
@@ -221,6 +222,7 @@
"write": 1
},
{
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
@@ -230,6 +232,7 @@
"report": 1,
"role": "Accounts Manager",
"share": 1,
"submit": 1,
"write": 1
}
],

View File

@@ -70,7 +70,7 @@ class ShippingRule(Document):
def get_shipping_amount_from_rules(self, value):
for condition in self.get("conditions"):
if not condition.to_value or (flt(condition.from_value) <= value <= flt(condition.to_value)):
if not condition.to_value or (flt(condition.from_value) <= flt(value) <= flt(condition.to_value)):
return condition.shipping_amount
return 0.0

View File

@@ -1,4 +1,5 @@
{
"actions": [],
"autoname": "ACC-SUB-.YYYY.-.#####",
"creation": "2017-07-18 17:50:43.967266",
"doctype": "DocType",
@@ -155,7 +156,7 @@
"fieldname": "apply_additional_discount",
"fieldtype": "Select",
"label": "Apply Additional Discount On",
"options": "\nGrand Total\nNet total"
"options": "\nGrand Total\nNet Total"
},
{
"fieldname": "cb_2",
@@ -196,7 +197,8 @@
"fieldtype": "Column Break"
}
],
"modified": "2019-07-25 18:45:38.579579",
"links": [],
"modified": "2020-01-27 14:37:32.845173",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Subscription",

View File

@@ -280,7 +280,7 @@ class Subscription(Document):
if self.additional_discount_percentage or self.additional_discount_amount:
discount_on = self.apply_additional_discount
invoice.apply_additional_discount = discount_on if discount_on else 'Grand Total'
invoice.apply_discount_on = discount_on if discount_on else 'Grand Total'
# Subscription period
invoice.from_date = self.current_invoice_start
@@ -338,6 +338,16 @@ class Subscription(Document):
# Check invoice dates and make sure it doesn't have outstanding invoices
return getdate(nowdate()) >= getdate(self.current_invoice_start) and not self.has_outstanding_invoice()
def is_current_invoice_paid(self):
if self.is_new_subscription():
return False
last_invoice = frappe.get_doc('Sales Invoice', self.invoices[-1].invoice)
if getdate(last_invoice.posting_date) == getdate(self.current_invoice_start) and last_invoice.status == 'Paid':
return True
return False
def process_for_active(self):
"""
@@ -348,7 +358,7 @@ class Subscription(Document):
2. Change the `Subscription` status to 'Past Due Date'
3. Change the `Subscription` status to 'Cancelled'
"""
if self.is_postpaid_to_invoice() or self.is_prepaid_to_invoice():
if not self.is_current_invoice_paid() and (self.is_postpaid_to_invoice() or self.is_prepaid_to_invoice()):
self.generate_invoice()
if self.current_invoice_is_past_due():
self.status = 'Past Due Date'

View File

@@ -1,134 +1,134 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "field:title",
"beta": 0,
"creation": "2018-11-22 23:38:39.668804",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "field:title",
"beta": 0,
"creation": "2018-11-22 23:38:39.668804",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "title",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Title",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "title",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Title",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 1
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-11-22 23:38:39.668804",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Tax Category",
"name_case": "",
"owner": "Administrator",
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2020-01-15 17:14:28.951793",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Tax Category",
"name_case": "",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
},
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts User",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts User",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 0
}
],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0,
],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}
}

View File

@@ -90,8 +90,12 @@ def merge_similar_entries(gl_map):
else:
merged_gl_map.append(entry)
company = gl_map[0].company if gl_map else erpnext.get_default_company()
company_currency = erpnext.get_company_currency(company)
precision = get_field_precision(frappe.get_meta("GL Entry").get_field("debit"), company_currency)
# filter zero debit and credit entries
merged_gl_map = filter(lambda x: flt(x.debit, 9)!=0 or flt(x.credit, 9)!=0, merged_gl_map)
merged_gl_map = filter(lambda x: flt(x.debit, precision)!=0 or flt(x.credit, precision)!=0, merged_gl_map)
merged_gl_map = list(merged_gl_map)
return merged_gl_map
@@ -162,33 +166,34 @@ def validate_account_for_perpetual_inventory(gl_map):
frappe.throw(_("Account: {0} can only be updated via Stock Transactions")
.format(account), StockAccountInvalidTransaction)
elif account_bal != stock_bal:
precision = get_field_precision(frappe.get_meta("GL Entry").get_field("debit"),
currency=frappe.get_cached_value('Company', gl_map[0].company, "default_currency"))
# This has been comment for a temporary, will add this code again on release of immutable ledger
# elif account_bal != stock_bal:
# precision = get_field_precision(frappe.get_meta("GL Entry").get_field("debit"),
# currency=frappe.get_cached_value('Company', gl_map[0].company, "default_currency"))
diff = flt(stock_bal - account_bal, precision)
error_reason = _("Stock Value ({0}) and Account Balance ({1}) are out of sync for account {2} and it's linked warehouses.").format(
stock_bal, account_bal, frappe.bold(account))
error_resolution = _("Please create adjustment Journal Entry for amount {0} ").format(frappe.bold(diff))
stock_adjustment_account = frappe.db.get_value("Company",gl_map[0].company,"stock_adjustment_account")
# diff = flt(stock_bal - account_bal, precision)
# error_reason = _("Stock Value ({0}) and Account Balance ({1}) are out of sync for account {2} and it's linked warehouses.").format(
# stock_bal, account_bal, frappe.bold(account))
# error_resolution = _("Please create adjustment Journal Entry for amount {0} ").format(frappe.bold(diff))
# stock_adjustment_account = frappe.db.get_value("Company",gl_map[0].company,"stock_adjustment_account")
db_or_cr_warehouse_account =('credit_in_account_currency' if diff < 0 else 'debit_in_account_currency')
db_or_cr_stock_adjustment_account = ('debit_in_account_currency' if diff < 0 else 'credit_in_account_currency')
# db_or_cr_warehouse_account =('credit_in_account_currency' if diff < 0 else 'debit_in_account_currency')
# db_or_cr_stock_adjustment_account = ('debit_in_account_currency' if diff < 0 else 'credit_in_account_currency')
journal_entry_args = {
'accounts':[
{'account': account, db_or_cr_warehouse_account : abs(diff)},
{'account': stock_adjustment_account, db_or_cr_stock_adjustment_account : abs(diff) }]
}
# journal_entry_args = {
# 'accounts':[
# {'account': account, db_or_cr_warehouse_account : abs(diff)},
# {'account': stock_adjustment_account, db_or_cr_stock_adjustment_account : abs(diff) }]
# }
frappe.msgprint(msg="""{0}<br></br>{1}<br></br>""".format(error_reason, error_resolution),
raise_exception=StockValueAndAccountBalanceOutOfSync,
title=_('Values Out Of Sync'),
primary_action={
'label': _('Make Journal Entry'),
'client_action': 'erpnext.route_to_adjustment_jv',
'args': journal_entry_args
})
# frappe.msgprint(msg="""{0}<br></br>{1}<br></br>""".format(error_reason, error_resolution),
# raise_exception=StockValueAndAccountBalanceOutOfSync,
# title=_('Values Out Of Sync'),
# primary_action={
# 'label': _('Make Journal Entry'),
# 'client_action': 'erpnext.route_to_adjustment_jv',
# 'args': journal_entry_args
# })
def validate_cwip_accounts(gl_map):
cwip_enabled = any([cint(ac.enable_cwip_accounting) for ac in frappe.db.get_all("Asset Category","enable_cwip_accounting")])

View File

@@ -23,7 +23,7 @@ class DuplicatePartyAccountError(frappe.ValidationError): pass
@frappe.whitelist()
def get_party_details(party=None, account=None, party_type="Customer", company=None, posting_date=None,
bill_date=None, price_list=None, currency=None, doctype=None, ignore_permissions=False, fetch_payment_terms_template=True,
party_address=None, shipping_address=None, pos_profile=None):
party_address=None, company_address=None, shipping_address=None, pos_profile=None):
if not party:
return {}
@@ -31,14 +31,14 @@ def get_party_details(party=None, account=None, party_type="Customer", company=N
frappe.throw(_("{0}: {1} does not exists").format(party_type, party))
return _get_party_details(party, account, party_type,
company, posting_date, bill_date, price_list, currency, doctype, ignore_permissions,
fetch_payment_terms_template, party_address, shipping_address, pos_profile)
fetch_payment_terms_template, party_address, company_address, shipping_address, pos_profile)
def _get_party_details(party=None, account=None, party_type="Customer", company=None, posting_date=None,
bill_date=None, price_list=None, currency=None, doctype=None, ignore_permissions=False,
fetch_payment_terms_template=True, party_address=None, shipping_address=None, pos_profile=None):
fetch_payment_terms_template=True, party_address=None, company_address=None,shipping_address=None, pos_profile=None):
out = frappe._dict(set_account_and_due_date(party, account, party_type, company, posting_date, bill_date, doctype))
party = out[party_type.lower()]
party_details = frappe._dict(set_account_and_due_date(party, account, party_type, company, posting_date, bill_date, doctype))
party = party_details[party_type.lower()]
if not ignore_permissions and not frappe.has_permission(party_type, "read", party):
frappe.throw(_("Not permitted for {0}").format(party), frappe.PermissionError)
@@ -46,76 +46,81 @@ def _get_party_details(party=None, account=None, party_type="Customer", company=
party = frappe.get_doc(party_type, party)
currency = party.default_currency if party.get("default_currency") else get_company_currency(company)
party_address, shipping_address = set_address_details(out, party, party_type, doctype, company, party_address, shipping_address)
set_contact_details(out, party, party_type)
set_other_values(out, party, party_type)
set_price_list(out, party, party_type, price_list, pos_profile)
party_address, shipping_address = set_address_details(party_details, party, party_type, doctype, company, party_address, company_address, shipping_address)
set_contact_details(party_details, party, party_type)
set_other_values(party_details, party, party_type)
set_price_list(party_details, party, party_type, price_list, pos_profile)
out["tax_category"] = get_address_tax_category(party.get("tax_category"),
party_details["tax_category"] = get_address_tax_category(party.get("tax_category"),
party_address, shipping_address if party_type != "Supplier" else party_address)
out["taxes_and_charges"] = set_taxes(party.name, party_type, posting_date, company,
customer_group=out.customer_group, supplier_group=out.supplier_group, tax_category=out.tax_category,
billing_address=party_address, shipping_address=shipping_address)
if not party_details.get("taxes_and_charges"):
party_details["taxes_and_charges"] = set_taxes(party.name, party_type, posting_date, company,
customer_group=party_details.customer_group, supplier_group=party_details.supplier_group, tax_category=party_details.tax_category,
billing_address=party_address, shipping_address=shipping_address)
if fetch_payment_terms_template:
out["payment_terms_template"] = get_pyt_term_template(party.name, party_type, company)
party_details["payment_terms_template"] = get_pyt_term_template(party.name, party_type, company)
if not out.get("currency"):
out["currency"] = currency
if not party_details.get("currency"):
party_details["currency"] = currency
# sales team
if party_type=="Customer":
out["sales_team"] = [{
party_details["sales_team"] = [{
"sales_person": d.sales_person,
"allocated_percentage": d.allocated_percentage or None
} for d in party.get("sales_team")]
# supplier tax withholding category
if party_type == "Supplier" and party:
out["supplier_tds"] = frappe.get_value(party_type, party.name, "tax_withholding_category")
party_details["supplier_tds"] = frappe.get_value(party_type, party.name, "tax_withholding_category")
return out
return party_details
def set_address_details(out, party, party_type, doctype=None, company=None, party_address=None, shipping_address=None):
def set_address_details(party_details, party, party_type, doctype=None, company=None, party_address=None, company_address=None, shipping_address=None):
billing_address_field = "customer_address" if party_type == "Lead" \
else party_type.lower() + "_address"
out[billing_address_field] = party_address or get_default_address(party_type, party.name)
party_details[billing_address_field] = party_address or get_default_address(party_type, party.name)
if doctype:
out.update(get_fetch_values(doctype, billing_address_field, out[billing_address_field]))
party_details.update(get_fetch_values(doctype, billing_address_field, party_details[billing_address_field]))
# address display
out.address_display = get_address_display(out[billing_address_field])
party_details.address_display = get_address_display(party_details[billing_address_field])
# shipping address
if party_type in ["Customer", "Lead"]:
out.shipping_address_name = shipping_address or get_party_shipping_address(party_type, party.name)
out.shipping_address = get_address_display(out["shipping_address_name"])
party_details.shipping_address_name = shipping_address or get_party_shipping_address(party_type, party.name)
party_details.shipping_address = get_address_display(party_details["shipping_address_name"])
if doctype:
out.update(get_fetch_values(doctype, 'shipping_address_name', out.shipping_address_name))
party_details.update(get_fetch_values(doctype, 'shipping_address_name', party_details.shipping_address_name))
if doctype and doctype in ['Delivery Note', 'Sales Invoice']:
out.update(get_company_address(company))
if out.company_address:
out.update(get_fetch_values(doctype, 'company_address', out.company_address))
get_regional_address_details(out, doctype, company)
if company_address:
party_details.update({'company_address': company_address})
else:
party_details.update(get_company_address(company))
elif doctype and doctype == "Purchase Invoice":
out.update(get_company_address(company))
if out.company_address:
out["shipping_address"] = shipping_address or out["company_address"]
out.shipping_address_display = get_address_display(out["shipping_address"])
out.update(get_fetch_values(doctype, 'shipping_address', out.shipping_address))
get_regional_address_details(out, doctype, company)
if doctype and doctype in ['Delivery Note', 'Sales Invoice', 'Sales Order']:
if party_details.company_address:
party_details.update(get_fetch_values(doctype, 'company_address', party_details.company_address))
get_regional_address_details(party_details, doctype, company)
return out.get(billing_address_field), out.shipping_address_name
elif doctype and doctype in ["Purchase Invoice", "Purchase Order", "Purchase Receipt"]:
if party_details.company_address:
party_details["shipping_address"] = shipping_address or party_details["company_address"]
party_details.shipping_address_display = get_address_display(party_details["shipping_address"])
party_details.update(get_fetch_values(doctype, 'shipping_address', party_details.shipping_address))
get_regional_address_details(party_details, doctype, company)
return party_details.get(billing_address_field), party_details.shipping_address_name
@erpnext.allow_regional
def get_regional_address_details(out, doctype, company):
def get_regional_address_details(party_details, doctype, company):
pass
def set_contact_details(out, party, party_type):
out.contact_person = get_default_contact(party_type, party.name)
def set_contact_details(party_details, party, party_type):
party_details.contact_person = get_default_contact(party_type, party.name)
if not out.contact_person:
out.update({
if not party_details.contact_person:
party_details.update({
"contact_person": None,
"contact_display": None,
"contact_email": None,
@@ -125,22 +130,22 @@ def set_contact_details(out, party, party_type):
"contact_department": None
})
else:
out.update(get_contact_details(out.contact_person))
party_details.update(get_contact_details(party_details.contact_person))
def set_other_values(out, party, party_type):
def set_other_values(party_details, party, party_type):
# copy
if party_type=="Customer":
to_copy = ["customer_name", "customer_group", "territory", "language"]
else:
to_copy = ["supplier_name", "supplier_group", "language"]
for f in to_copy:
out[f] = party.get(f)
party_details[f] = party.get(f)
# fields prepended with default in Customer doctype
for f in ['currency'] \
+ (['sales_partner', 'commission_rate'] if party_type=="Customer" else []):
if party.get("default_" + f):
out[f] = party.get("default_" + f)
party_details[f] = party.get("default_" + f)
def get_default_price_list(party):
"""Return default price list for party (Document object)"""
@@ -155,7 +160,7 @@ def get_default_price_list(party):
return None
def set_price_list(out, party, party_type, given_price_list, pos=None):
def set_price_list(party_details, party, party_type, given_price_list, pos=None):
# price list
price_list = get_permitted_documents('Price List')
@@ -173,9 +178,9 @@ def set_price_list(out, party, party_type, given_price_list, pos=None):
price_list = get_default_price_list(party) or given_price_list
if price_list:
out.price_list_currency = frappe.db.get_value("Price List", price_list, "currency", cache=True)
party_details.price_list_currency = frappe.db.get_value("Price List", price_list, "currency", cache=True)
out["selling_price_list" if party.doctype=="Customer" else "buying_price_list"] = price_list
party_details["selling_price_list" if party.doctype=="Customer" else "buying_price_list"] = price_list
def set_account_and_due_date(party, account, party_type, company, posting_date, bill_date, doctype):

View File

@@ -49,7 +49,7 @@
{% endfor %}
<tr>
<td class="right" colspan="3" ><strong>Total (debit) </strong></td>
<td class="left" >{{ gl | sum(attribute='debit') }}</td>
<td class="left" >{{ frappe.format((gl | sum(attribute="debit")), {fieldtype: "Currency"}) }}</td>
</tr>
<tr>
<td class="top-bottom" colspan="5"><strong>Credit</strong></td>
@@ -69,7 +69,7 @@
{% endfor %}
<tr>
<td class="right" colspan="3"><strong>Total (credit) </strong></td>
<td class="left" >{{ gl | sum(attribute='credit') }}</td>
<td class="left" >{{ frappe.format((gl | sum(attribute="credit")), {fieldtype: "Currency"}) }}</td>
</tr>
</table>
<div>

View File

@@ -100,6 +100,16 @@ frappe.query_reports["Accounts Payable"] = {
"fieldtype": "Link",
"options": "Supplier Group"
},
{
"fieldname": "group_by_party",
"label": __("Group By Supplier"),
"fieldtype": "Check"
},
{
"fieldname":"based_on_payment_terms",
"label": __("Based On Payment Terms"),
"fieldtype": "Check",
},
{
"fieldname":"tax_id",
"label": __("Tax Id"),
@@ -107,6 +117,16 @@ frappe.query_reports["Accounts Payable"] = {
"hidden": 1
}
],
"formatter": function(value, row, column, data, default_formatter) {
value = default_formatter(value, row, column, data);
if (data && data.bold) {
value = value.bold();
}
return value;
},
onload: function(report) {
report.page.add_inner_button(__("Accounts Payable Summary"), function() {
var filters = report.get_values();

View File

@@ -88,6 +88,11 @@ frappe.query_reports["Accounts Payable Summary"] = {
"label": __("Supplier Group"),
"fieldtype": "Link",
"options": "Supplier Group"
},
{
"fieldname":"based_on_payment_terms",
"label": __("Based On Payment Terms"),
"fieldtype": "Check",
}
],

View File

@@ -87,7 +87,7 @@ frappe.query_reports["Accounts Receivable"] = {
frappe.query_report.set_filter_value('payment_terms', value["payment_terms"]);
});
frappe.db.get_value('Customer Credit Limit', {'parent': customer, 'company': company},
frappe.db.get_value('Customer Credit Limit', {'parent': customer, 'company': company},
["credit_limit"], function(value) {
if (value) {
frappe.query_report.set_filter_value('credit_limit', value["credit_limit"]);
@@ -131,6 +131,11 @@ frappe.query_reports["Accounts Receivable"] = {
"fieldtype": "Link",
"options": "Sales Person"
},
{
"fieldname": "group_by_party",
"label": __("Group By Customer"),
"fieldtype": "Check"
},
{
"fieldname":"based_on_payment_terms",
"label": __("Based On Payment Terms"),
@@ -177,6 +182,15 @@ frappe.query_reports["Accounts Receivable"] = {
}
],
"formatter": function(value, row, column, data, default_formatter) {
value = default_formatter(value, row, column, data);
if (data && data.bold) {
value = value.bold();
}
return value;
},
onload: function(report) {
report.page.add_inner_button(__("Accounts Receivable Summary"), function() {
var filters = report.get_values();

View File

@@ -46,7 +46,7 @@ class ReceivablePayableReport(object):
self.get_columns()
self.get_data()
self.get_chart_data()
return self.columns, self.data, None, self.chart
return self.columns, self.data, None, self.chart, None, self.skip_total_row
def set_defaults(self):
if not self.filters.get("company"):
@@ -57,9 +57,16 @@ class ReceivablePayableReport(object):
self.party_type = self.filters.party_type
self.party_details = {}
self.invoices = set()
self.skip_total_row = 0
if self.filters.get('group_by_party'):
self.previous_party=''
self.total_row_map = {}
self.skip_total_row = 1
def get_data(self):
self.get_gl_entries()
self.get_sales_invoices_or_customers_based_on_sales_person()
self.voucher_balance = OrderedDict()
self.init_voucher_balance() # invoiced, paid, credit_note, outstanding
@@ -101,14 +108,40 @@ class ReceivablePayableReport(object):
)
self.get_invoices(gle)
if self.filters.get('group_by_party'):
self.init_subtotal_row(gle.party)
if self.filters.get('group_by_party'):
self.init_subtotal_row('Total')
def get_invoices(self, gle):
if gle.voucher_type in ('Sales Invoice', 'Purchase Invoice'):
self.invoices.add(gle.voucher_no)
if self.filters.get("sales_person"):
if gle.voucher_no in self.sales_person_records.get("Sales Invoice", []) \
or gle.party in self.sales_person_records.get("Customer", []):
self.invoices.add(gle.voucher_no)
else:
self.invoices.add(gle.voucher_no)
def init_subtotal_row(self, party):
if not self.total_row_map.get(party):
self.total_row_map.setdefault(party, {
'party': party,
'bold': 1
})
for field in self.get_currency_fields():
self.total_row_map[party][field] = 0.0
def get_currency_fields(self):
return ['invoiced', 'paid', 'credit_note', 'outstanding', 'range1',
'range2', 'range3', 'range4', 'range5']
def update_voucher_balance(self, gle):
# get the row where this balance needs to be updated
# if its a payment, it will return the linked invoice or will be considered as advance
row = self.get_voucher_balance(gle)
if not row: return
# gle_balance will be the total "debit - credit" for receivable type reports and
# and vice-versa for payable type reports
gle_balance = self.get_gle_balance(gle)
@@ -128,9 +161,26 @@ class ReceivablePayableReport(object):
# advance / unlinked payment or other adjustment
row.paid -= gle_balance
def get_voucher_balance(self, gle):
voucher_balance = None
def update_sub_total_row(self, row, party):
total_row = self.total_row_map.get(party)
for field in self.get_currency_fields():
total_row[field] += row.get(field, 0.0)
def append_subtotal_row(self, party):
sub_total_row = self.total_row_map.get(party)
self.data.append(sub_total_row)
self.data.append({})
self.update_sub_total_row(sub_total_row, 'Total')
def get_voucher_balance(self, gle):
if self.filters.get("sales_person"):
against_voucher = gle.against_voucher or gle.voucher_no
if not (gle.party in self.sales_person_records.get("Customer", []) or \
against_voucher in self.sales_person_records.get("Sales Invoice", [])):
return
voucher_balance = None
if gle.against_voucher:
# find invoice
against_voucher = gle.against_voucher
@@ -159,7 +209,7 @@ class ReceivablePayableReport(object):
row.outstanding = flt(row.invoiced - row.paid - row.credit_note, self.currency_precision)
row.invoice_grand_total = row.invoiced
if abs(row.outstanding) > 0.1/10 ** self.currency_precision:
if abs(row.outstanding) > 1.0/10 ** self.currency_precision:
# non-zero oustanding, we must consider this row
if self.is_invoice(row) and self.filters.based_on_payment_terms:
@@ -180,11 +230,22 @@ class ReceivablePayableReport(object):
else:
self.append_row(row)
if self.filters.get('group_by_party'):
self.append_subtotal_row(self.previous_party)
self.data.append(self.total_row_map.get('Total'))
def append_row(self, row):
self.allocate_future_payments(row)
self.set_invoice_details(row)
self.set_party_details(row)
self.set_ageing(row)
if self.filters.get('group_by_party'):
self.update_sub_total_row(row, row.party)
if self.previous_party and (self.previous_party != row.party):
self.append_subtotal_row(self.previous_party)
self.previous_party = row.party
self.data.append(row)
def set_invoice_details(self, row):
@@ -273,7 +334,7 @@ class ReceivablePayableReport(object):
def set_party_details(self, row):
# customer / supplier name
party_details = self.get_party_details(row.party)
party_details = self.get_party_details(row.party) or {}
row.update(party_details)
if self.filters.get(scrub(self.filters.party_type)):
row.currency = row.account_currency
@@ -318,7 +379,7 @@ class ReceivablePayableReport(object):
self.append_payment_term(row, d, term)
def append_payment_term(self, row, d, term):
if self.filters.get("customer") and d.currency == d.party_account_currency:
if (self.filters.get("customer") or self.filters.get("supplier")) and d.currency == d.party_account_currency:
invoiced = d.payment_amount
else:
invoiced = flt(flt(d.payment_amount) * flt(d.conversion_rate), self.currency_precision)
@@ -491,6 +552,7 @@ class ReceivablePayableReport(object):
# get all the GL entries filtered by the given filters
conditions, values = self.prepare_conditions()
order_by = self.get_order_by_condition()
if self.filters.get(scrub(self.party_type)):
select_fields = "debit_in_account_currency as debit, credit_in_account_currency as credit"
@@ -508,9 +570,24 @@ class ReceivablePayableReport(object):
and party_type=%s
and (party is not null and party != '')
and posting_date <= %s
{1}
order by posting_date, party"""
.format(select_fields, conditions), values, as_dict=True)
{1} {2}"""
.format(select_fields, conditions, order_by), values, as_dict=True)
def get_sales_invoices_or_customers_based_on_sales_person(self):
if self.filters.get("sales_person"):
lft, rgt = frappe.db.get_value("Sales Person",
self.filters.get("sales_person"), ["lft", "rgt"])
records = frappe.db.sql("""
select distinct parent, parenttype
from `tabSales Team` steam
where parenttype in ('Customer', 'Sales Invoice')
and exists(select name from `tabSales Person` where lft >= %s and rgt <= %s and name = steam.sales_person)
""", (lft, rgt), as_dict=1)
self.sales_person_records = frappe._dict()
for d in records:
self.sales_person_records.setdefault(d.parenttype, set()).add(d.parent)
def prepare_conditions(self):
conditions = [""]
@@ -529,6 +606,12 @@ class ReceivablePayableReport(object):
return " and ".join(conditions), values
def get_order_by_condition(self):
if self.filters.get('group_by_party'):
return "order by party, posting_date"
else:
return "order by posting_date, party"
def add_common_filters(self, conditions, values, party_type_field):
if self.filters.company:
conditions.append("company=%s")
@@ -564,16 +647,6 @@ class ReceivablePayableReport(object):
conditions.append("party in (select name from tabCustomer where default_sales_partner=%s)")
values.append(self.filters.get("sales_partner"))
if self.filters.get("sales_person"):
lft, rgt = frappe.db.get_value("Sales Person",
self.filters.get("sales_person"), ["lft", "rgt"])
conditions.append("""exists(select name from `tabSales Team` steam where
steam.sales_person in (select name from `tabSales Person` where lft >= {0} and rgt <= {1})
and ((steam.parent = voucher_no and steam.parenttype = voucher_type)
or (steam.parent = against_voucher and steam.parenttype = against_voucher_type)
or (steam.parent = party and steam.parenttype = 'Customer')))""".format(lft, rgt))
def add_supplier_filters(self, conditions, values):
if self.filters.get("supplier_group"):
conditions.append("""party in (select name from tabSupplier
@@ -718,11 +791,13 @@ class ReceivablePayableReport(object):
def get_chart_data(self):
rows = []
for row in self.data:
values = [row.range1, row.range2, row.range3, row.range4, row.range5]
precision = cint(frappe.db.get_default("float_precision")) or 2
rows.append({
'values': [flt(val, precision) for val in values]
})
row = frappe._dict(row)
if not cint(row.bold):
values = [row.range1, row.range2, row.range3, row.range4, row.range5]
precision = cint(frappe.db.get_default("float_precision")) or 2
rows.append({
'values': [flt(val, precision) for val in values]
})
self.chart = {
"data": {

View File

@@ -106,6 +106,11 @@ frappe.query_reports["Accounts Receivable Summary"] = {
"label": __("Sales Person"),
"fieldtype": "Link",
"options": "Sales Person"
},
{
"fieldname":"based_on_payment_terms",
"label": __("Based On Payment Terms"),
"fieldtype": "Check",
}
],

View File

@@ -36,7 +36,7 @@ class AccountsReceivableSummary(ReceivablePayableReport):
self.filters.report_date) or {}
for party, party_dict in iteritems(self.party_total):
if party_dict.outstanding <= 0:
if party_dict.outstanding == 0:
continue
row = frappe._dict()

View File

@@ -14,6 +14,7 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
frappe.query_reports["Balance Sheet"]["filters"].push({
"fieldname": "include_default_book_entries",
"label": __("Include Default Book Entries"),
"fieldtype": "Check"
"fieldtype": "Check",
"default": 1
});
});

View File

@@ -46,13 +46,24 @@ frappe.query_reports["Budget Variance Report"] = {
fieldtype: "Select",
options: ["Cost Center", "Project"],
default: "Cost Center",
reqd: 1
reqd: 1,
on_change: function() {
frappe.query_report.set_filter_value("budget_against_filter", []);
frappe.query_report.refresh();
}
},
{
fieldname: "cost_center",
label: __("Cost Center"),
fieldtype: "Link",
options: "Cost Center"
fieldname:"budget_against_filter",
label: __('Dimension Filter'),
fieldtype: "MultiSelectList",
get_data: function(txt) {
if (!frappe.query_report.filters) return;
let budget_against = frappe.query_report.get_filter_value('budget_against');
if (!budget_against) return;
return frappe.db.get_link_options(budget_against, txt);
}
},
{
fieldname:"show_cumulative",

View File

@@ -12,22 +12,22 @@ from six import iteritems
from pprint import pprint
def execute(filters=None):
if not filters: filters = {}
validate_filters(filters)
columns = get_columns(filters)
if filters.get("cost_center"):
cost_centers = [filters.get("cost_center")]
if filters.get("budget_against_filter"):
dimensions = filters.get("budget_against_filter")
else:
cost_centers = get_cost_centers(filters)
dimensions = get_cost_centers(filters)
period_month_ranges = get_period_month_ranges(filters["period"], filters["from_fiscal_year"])
cam_map = get_cost_center_account_month_map(filters)
cam_map = get_dimension_account_month_map(filters)
data = []
for cost_center in cost_centers:
cost_center_items = cam_map.get(cost_center)
if cost_center_items:
for account, monthwise_data in iteritems(cost_center_items):
row = [cost_center, account]
for dimension in dimensions:
dimension_items = cam_map.get(dimension)
if dimension_items:
for account, monthwise_data in iteritems(dimension_items):
row = [dimension, account]
totals = [0, 0, 0]
for year in get_fiscal_years(filters):
last_total = 0
@@ -55,10 +55,6 @@ def execute(filters=None):
return columns, data
def validate_filters(filters):
if filters.get("budget_against") != "Cost Center" and filters.get("cost_center"):
frappe.throw(_("Filter based on Cost Center is only applicable if Budget Against is selected as Cost Center"))
def get_columns(filters):
columns = [_(filters.get("budget_against")) + ":Link/%s:150"%(filters.get("budget_against")), _("Account") + ":Link/Account:150"]
@@ -98,11 +94,12 @@ def get_cost_centers(filters):
else:
return frappe.db.sql_list("""select name from `tab{tab}`""".format(tab=filters.get("budget_against"))) #nosec
#Get cost center & target details
def get_cost_center_target_details(filters):
#Get dimension & target details
def get_dimension_target_details(filters):
cond = ""
if filters.get("cost_center"):
cond += " and b.cost_center=%s" % frappe.db.escape(filters.get("cost_center"))
if filters.get("budget_against_filter"):
cond += " and b.{budget_against} in (%s)".format(budget_against = \
frappe.scrub(filters.get('budget_against'))) % ', '.join(['%s']* len(filters.get('budget_against_filter')))
return frappe.db.sql("""
select b.{budget_against} as budget_against, b.monthly_distribution, ba.account, ba.budget_amount,b.fiscal_year
@@ -110,8 +107,8 @@ def get_cost_center_target_details(filters):
where b.name=ba.parent and b.docstatus = 1 and b.fiscal_year between %s and %s
and b.budget_against = %s and b.company=%s {cond} order by b.fiscal_year
""".format(budget_against=filters.get("budget_against").replace(" ", "_").lower(), cond=cond),
(filters.from_fiscal_year,filters.to_fiscal_year,filters.budget_against, filters.company), as_dict=True)
tuple([filters.from_fiscal_year,filters.to_fiscal_year,filters.budget_against, filters.company] + filters.get('budget_against_filter')),
as_dict=True)
#Get target distribution details of accounts of cost center
@@ -153,14 +150,14 @@ def get_actual_details(name, filters):
return cc_actual_details
def get_cost_center_account_month_map(filters):
def get_dimension_account_month_map(filters):
import datetime
cost_center_target_details = get_cost_center_target_details(filters)
dimension_target_details = get_dimension_target_details(filters)
tdd = get_target_distribution_details(filters)
cam_map = {}
for ccd in cost_center_target_details:
for ccd in dimension_target_details:
actual_details = get_actual_details(ccd.budget_against, filters)
for month_id in range(1, 13):

View File

@@ -20,7 +20,8 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
{
"fieldname": "include_default_book_entries",
"label": __("Include Default Book Entries"),
"fieldtype": "Check"
"fieldtype": "Check",
"default": 1
}
);
});

View File

@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import cint
from frappe.utils import cint, cstr
from erpnext.accounts.report.financial_statements import (get_period_list, get_columns, get_data)
from erpnext.accounts.report.profit_and_loss_statement.profit_and_loss_statement import get_net_profit_loss
from erpnext.accounts.utils import get_fiscal_year
@@ -129,13 +129,13 @@ def get_account_type_based_gl_data(company, start_date, end_date, account_type,
cond = ""
filters = frappe._dict(filters)
if filters.finance_book:
cond = " and finance_book = %s" %(frappe.db.escape(filters.finance_book))
if filters.include_default_book_entries:
company_fb = frappe.db.get_value("Company", company, 'default_finance_book')
if filters.include_default_book_entries:
company_fb = frappe.db.get_value("Company", company, 'default_finance_book')
cond = """ AND (finance_book in (%s, %s, '') OR finance_book IS NULL)
""" %(frappe.db.escape(filters.finance_book), frappe.db.escape(company_fb))
else:
cond = " AND (finance_book in (%s, '') OR finance_book IS NULL)" %(frappe.db.escape(cstr(filters.finance_book)))
cond = """ and finance_book in (%s, %s)
""" %(frappe.db.escape(filters.finance_book), frappe.db.escape(company_fb))
gl_sum = frappe.db.sql_list("""
select sum(credit) - sum(debit)

View File

@@ -58,7 +58,8 @@ frappe.query_reports["Consolidated Financial Statement"] = {
{
"fieldname": "include_default_book_entries",
"label": __("Include Default Book Entries"),
"fieldtype": "Check"
"fieldtype": "Check",
"default": 1
}
]
}

View File

@@ -387,11 +387,10 @@ def get_additional_conditions(from_date, ignore_closing_entries, filters):
if from_date:
additional_conditions.append("gl.posting_date >= %(from_date)s")
if filters.get("finance_book"):
if filters.get("include_default_book_entries"):
additional_conditions.append("finance_book in (%(finance_book)s, %(company_fb)s)")
else:
additional_conditions.append("finance_book in (%(finance_book)s)")
if filters.get("include_default_book_entries"):
additional_conditions.append("(finance_book in (%(finance_book)s, %(company_fb)s, '') OR finance_book IS NULL)")
else:
additional_conditions.append("(finance_book in (%(finance_book)s, '') OR finance_book IS NULL)")
return " and {}".format(" and ".join(additional_conditions)) if additional_conditions else ""

View File

@@ -1,5 +1,6 @@
{%
var report_columns = report.get_columns_for_print();
report_columns = report_columns.filter(col => !col.hidden);
if (report_columns.length > 8) {
frappe.throw(__("Too many columns. Export the report and print it using a spreadsheet application."));
@@ -15,34 +16,35 @@
height: 37px;
}
</style>
{% var letterhead= filters.letter_head || (frappe.get_doc(":Company", filters.company) && frappe.get_doc(":Company", filters.company).default_letter_head) %}
{% if(letterhead) { %}
<div style="margin-bottom: 7px;" class="text-center">
{%= frappe.boot.letter_heads[letterhead].header %}
</div>
{% } %}
<h2 class="text-center">{%= __(report.report_name) %}</h2>
<h3 class="text-center">{%= filters.company %}</h3>
{% if 'cost_center' in filters %}
<h3 class="text-center">{%= filters.cost_center %}</h3>
{% endif %}
<h3 class="text-center">{%= filters.fiscal_year %}</h3>
<h5 class="text-center">{%= __("Currency") %} : {%= filters.presentation_currency || erpnext.get_currency(filters.company) %} </h4>
<h5 class="text-center">
{%= __("Currency") %} : {%= filters.presentation_currency || erpnext.get_currency(filters.company) %}
</h5>
{% if (filters.from_date) { %}
<h4 class="text-center">{%= frappe.datetime.str_to_user(filters.from_date) %} - {%= frappe.datetime.str_to_user(filters.to_date) %}</h3>
<h5 class="text-center">
{%= frappe.datetime.str_to_user(filters.from_date) %} - {%= frappe.datetime.str_to_user(filters.to_date) %}
</h5>
{% } %}
<hr>
<table class="table table-bordered">
<thead>
<tr>
<th style="width: {%= 100 - (report_columns.length - 2) * 13 %}%"></th>
{% for(var i=2, l=report_columns.length; i<l; i++) { %}
<th style="width: {%= 100 - (report_columns.length - 1) * 13 %}%"></th>
{% for (let i=1, l=report_columns.length; i<l; i++) { %}
<th class="text-right">{%= report_columns[i].label %}</th>
{% } %}
</tr>
</thead>
<tbody>
{% for(var j=0, k=data.length-1; j<k; j++) { %}
{% for(let j=0, k=data.length-1; j<k; j++) { %}
{%
var row = data[j];
var row_class = data[j].parent_account ? "" : "financial-statements-important";
@@ -52,11 +54,11 @@
<td>
<span style="padding-left: {%= cint(data[j].indent) * 2 %}em">{%= row.account_name %}</span>
</td>
{% for(var i=2, l=report_columns.length; i<l; i++) { %}
{% for(let i=1, l=report_columns.length; i<l; i++) { %}
<td class="text-right">
{% var fieldname = report_columns[i].fieldname; %}
{% const fieldname = report_columns[i].fieldname; %}
{% if (!is_null(row[fieldname])) { %}
{%= format_currency(row[fieldname], filters.presentation_currency) %}
{%= frappe.format(row[fieldname], report_columns[i], {}, row) %}
{% } %}
</td>
{% } %}
@@ -64,4 +66,6 @@
{% } %}
</tbody>
</table>
<p class="text-right text-muted">Printed On {%= frappe.datetime.str_to_user(frappe.datetime.get_datetime_as_string()) %}</p>
<p class="text-right text-muted">
Printed On {%= frappe.datetime.str_to_user(frappe.datetime.get_datetime_as_string()) %}
</p>

View File

@@ -13,7 +13,7 @@ import frappe, erpnext
from erpnext.accounts.report.utils import get_currency, convert_to_presentation_currency
from erpnext.accounts.utils import get_fiscal_year
from frappe import _
from frappe.utils import (flt, getdate, get_first_day, add_months, add_days, formatdate)
from frappe.utils import (flt, getdate, get_first_day, add_months, add_days, formatdate, cstr)
from six import itervalues
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
@@ -264,8 +264,8 @@ def filter_out_zero_value_rows(data, parent_children_map, show_zero_values=False
def add_total_row(out, root_type, balance_must_be, period_list, company_currency):
total_row = {
"account_name": "'" + _("Total {0} ({1})").format(_(root_type), _(balance_must_be)) + "'",
"account": "'" + _("Total {0} ({1})").format(_(root_type), _(balance_must_be)) + "'",
"account_name": _("Total {0} ({1})").format(_(root_type), _(balance_must_be)),
"account": _("Total {0} ({1})").format(_(root_type), _(balance_must_be)),
"currency": company_currency
}
@@ -348,40 +348,42 @@ def set_gl_entries_by_account(
additional_conditions = get_additional_conditions(from_date, ignore_closing_entries, filters)
accounts = frappe.db.sql_list("""select name from `tabAccount`
where lft >= %s and rgt <= %s""", (root_lft, root_rgt))
additional_conditions += " and account in ({})"\
.format(", ".join([frappe.db.escape(d) for d in accounts]))
where lft >= %s and rgt <= %s and company = %s""", (root_lft, root_rgt, company))
gl_filters = {
"company": company,
"from_date": from_date,
"to_date": to_date,
"finance_book": filters.get("finance_book")
}
if accounts:
additional_conditions += " and account in ({})"\
.format(", ".join([frappe.db.escape(d) for d in accounts]))
if filters.get("include_default_book_entries"):
gl_filters["company_fb"] = frappe.db.get_value("Company",
company, 'default_finance_book')
gl_filters = {
"company": company,
"from_date": from_date,
"to_date": to_date,
"finance_book": cstr(filters.get("finance_book"))
}
for key, value in filters.items():
if value:
gl_filters.update({
key: value
})
if filters.get("include_default_book_entries"):
gl_filters["company_fb"] = frappe.db.get_value("Company",
company, 'default_finance_book')
gl_entries = frappe.db.sql("""select posting_date, account, debit, credit, is_opening, fiscal_year, debit_in_account_currency, credit_in_account_currency, account_currency from `tabGL Entry`
where company=%(company)s
{additional_conditions}
and posting_date <= %(to_date)s
order by account, posting_date""".format(additional_conditions=additional_conditions), gl_filters, as_dict=True) #nosec
for key, value in filters.items():
if value:
gl_filters.update({
key: value
})
if filters and filters.get('presentation_currency'):
convert_to_presentation_currency(gl_entries, get_currency(filters))
gl_entries = frappe.db.sql("""select posting_date, account, debit, credit, is_opening, fiscal_year, debit_in_account_currency, credit_in_account_currency, account_currency from `tabGL Entry`
where company=%(company)s
{additional_conditions}
and posting_date <= %(to_date)s
order by account, posting_date""".format(additional_conditions=additional_conditions), gl_filters, as_dict=True) #nosec
for entry in gl_entries:
gl_entries_by_account.setdefault(entry.account, []).append(entry)
if filters and filters.get('presentation_currency'):
convert_to_presentation_currency(gl_entries, get_currency(filters))
return gl_entries_by_account
for entry in gl_entries:
gl_entries_by_account.setdefault(entry.account, []).append(entry)
return gl_entries_by_account
def get_additional_conditions(from_date, ignore_closing_entries, filters):
@@ -406,12 +408,11 @@ def get_additional_conditions(from_date, ignore_closing_entries, filters):
filters.cost_center = get_cost_centers_with_children(filters.cost_center)
additional_conditions.append("cost_center in %(cost_center)s")
if filters.get("finance_book"):
if filters.get("include_default_book_entries"):
additional_conditions.append("finance_book in (%(finance_book)s, %(company_fb)s)")
else:
additional_conditions.append("finance_book in (%(finance_book)s)")
if filters.get("include_default_book_entries"):
additional_conditions.append("(finance_book in (%(finance_book)s, %(company_fb)s, '') OR finance_book IS NULL)")
else:
additional_conditions.append("(finance_book in (%(finance_book)s, '') OR finance_book IS NULL)")
if accounting_dimensions:
for dimension in accounting_dimensions:
if filters.get(dimension):

View File

@@ -33,7 +33,7 @@
</tr>
</thead>
<tbody>
{% for(var i=0, l=data.length-1; i<l; i++) { %}
{% for(var i=0, l=data.length; i<l; i++) { %}
<tr>
{% if(data[i].posting_date) { %}
<td>{%= frappe.datetime.str_to_user(data[i].posting_date) %}</td>

View File

@@ -154,7 +154,8 @@ frappe.query_reports["General Ledger"] = {
{
"fieldname": "include_default_book_entries",
"label": __("Include Default Book Entries"),
"fieldtype": "Check"
"fieldtype": "Check",
"default": 1
}
]
}

View File

@@ -119,7 +119,7 @@ def get_gl_entries(filters):
select_fields = """, debit, credit, debit_in_account_currency,
credit_in_account_currency """
order_by_statement = "order by posting_date, account"
order_by_statement = "order by posting_date, account, creation"
if filters.get("group_by") == _("Group by Voucher"):
order_by_statement = "order by posting_date, voucher_type, voucher_no"
@@ -184,7 +184,7 @@ def get_conditions(filters):
if filters.get("finance_book"):
if filters.get("include_default_book_entries"):
conditions.append("finance_book in (%(finance_book)s, %(company_fb)s)")
conditions.append("(finance_book in (%(finance_book)s, %(company_fb)s, '') OR finance_book IS NULL)")
else:
conditions.append("finance_book in (%(finance_book)s)")

View File

@@ -34,6 +34,20 @@ frappe.query_reports["Item-wise Purchase Register"] = {
"label": __("Mode of Payment"),
"fieldtype": "Link",
"options": "Mode of Payment"
},
{
"label": __("Group By"),
"fieldname": "group_by",
"fieldtype": "Select",
"options": ["Supplier", "Item Group", "Item", "Invoice"]
}
]
],
"formatter": function(value, row, column, data, default_formatter) {
value = default_formatter(value, row, column, data);
if (data && data.bold) {
value = value.bold();
}
return value;
}
}

View File

@@ -5,7 +5,9 @@ from __future__ import unicode_literals
import frappe, erpnext
from frappe import _
from frappe.utils import flt
from erpnext.accounts.report.item_wise_sales_register.item_wise_sales_register import get_tax_accounts
from erpnext.accounts.report.item_wise_sales_register.item_wise_sales_register import (get_tax_accounts,
get_grand_total, add_total_row, get_display_value, get_group_by_and_display_fields, add_sub_total_row,
get_group_by_conditions)
def execute(filters=None):
return _execute(filters)
@@ -13,7 +15,7 @@ def execute(filters=None):
def _execute(filters=None, additional_table_columns=None, additional_query_columns=None):
if not filters: filters = {}
filters.update({"from_date": filters.get("date_range")[0], "to_date": filters.get("date_range")[1]})
columns = get_columns(additional_table_columns)
columns = get_columns(additional_table_columns, filters)
company_currency = erpnext.get_company_currency(filters.company)
@@ -23,16 +25,16 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
itemised_tax, tax_columns = get_tax_accounts(item_list, columns, company_currency,
doctype="Purchase Invoice", tax_doctype="Purchase Taxes and Charges")
columns.append({
"fieldname": "currency",
"label": _("Currency"),
"fieldtype": "Data",
"width": 80
})
po_pr_map = get_purchase_receipts_against_purchase_order(item_list)
data = []
total_row_map = {}
skip_total_row = 0
prev_group_by_value = ''
if filters.get('group_by'):
grand_total = get_grand_total(filters, 'Purchase Invoice')
for d in item_list:
if not d.stock_qty:
continue
@@ -44,51 +46,243 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
purchase_receipt = ", ".join(po_pr_map.get(d.po_detail, []))
expense_account = d.expense_account or aii_account_map.get(d.company)
row = [d.item_code, d.item_name, d.item_group, d.description, d.parent, d.posting_date, d.supplier,
d.supplier_name]
row = {
'item_code': d.item_code,
'item_name': d.item_name,
'item_group': d.item_group,
'description': d.description,
'invoice': d.parent,
'posting_date': d.posting_date,
'customer': d.supplier,
'customer_name': d.supplier_name
}
if additional_query_columns:
for col in additional_query_columns:
row.append(d.get(col))
row.update({
col: d.get(col)
})
row += [
d.credit_to, d.mode_of_payment, d.project, d.company, d.purchase_order,
purchase_receipt, expense_account, d.stock_qty, d.stock_uom, d.base_net_amount / d.stock_qty, d.base_net_amount
]
row.update({
'credit_to': d.credit_to,
'mode_of_payment': d.mode_of_payment,
'project': d.project,
'company': d.company,
'purchase_order': d.purchase_order,
'purchase_receipt': d.purchase_receipt,
'expense_account': expense_account,
'stock_qty': d.stock_qty,
'stock_uom': d.stock_uom,
'rate': d.base_net_amount / d.stock_qty,
'amount': d.base_net_amount
})
total_tax = 0
for tax in tax_columns:
item_tax = itemised_tax.get(d.name, {}).get(tax, {})
row += [item_tax.get("tax_rate", 0), item_tax.get("tax_amount", 0)]
row.update({
frappe.scrub(tax + ' Rate'): item_tax.get("tax_rate", 0),
frappe.scrub(tax + ' Amount'): item_tax.get("tax_amount", 0),
})
total_tax += flt(item_tax.get("tax_amount"))
row += [total_tax, d.base_net_amount + total_tax, company_currency]
row.update({
'total_tax': total_tax,
'total': d.base_net_amount + total_tax,
'currency': company_currency
})
if filters.get('group_by'):
row.update({'percent_gt': flt(row['total']/grand_total) * 100})
group_by_field, subtotal_display_field = get_group_by_and_display_fields(filters)
data, prev_group_by_value = add_total_row(data, filters, prev_group_by_value, d, total_row_map,
group_by_field, subtotal_display_field, grand_total, tax_columns)
add_sub_total_row(row, total_row_map, d.get(group_by_field, ''), tax_columns)
data.append(row)
return columns, data
if filters.get('group_by'):
total_row = total_row_map.get(prev_group_by_value or d.get('item_name'))
total_row['percent_gt'] = flt(total_row['total']/grand_total * 100)
data.append(total_row)
data.append({})
add_sub_total_row(total_row, total_row_map, 'total_row', tax_columns)
data.append(total_row_map.get('total_row'))
skip_total_row = 1
return columns, data, None, None, None, skip_total_row
def get_columns(additional_table_columns):
columns = [
_("Item Code") + ":Link/Item:120", _("Item Name") + "::120",
_("Item Group") + ":Link/Item Group:100", "Description::150", _("Invoice") + ":Link/Purchase Invoice:120",
_("Posting Date") + ":Date:80", _("Supplier") + ":Link/Supplier:120",
"Supplier Name::120"
]
def get_columns(additional_table_columns, filters):
columns = []
if filters.get('group_by') != ('Item'):
columns.extend(
[
{
'label': _('Item Code'),
'fieldname': 'item_code',
'fieldtype': 'Link',
'options': 'Item',
'width': 120
},
{
'label': _('Item Name'),
'fieldname': 'item_name',
'fieldtype': 'Data',
'width': 120
}
]
)
if filters.get('group_by') not in ('Item', 'Item Group'):
columns.extend([
{
'label': _('Item Group'),
'fieldname': 'item_group',
'fieldtype': 'Link',
'options': 'Item Group',
'width': 120
}
])
columns.extend([
{
'label': _('Description'),
'fieldname': 'description',
'fieldtype': 'Data',
'width': 150
},
{
'label': _('Invoice'),
'fieldname': 'invoice',
'fieldtype': 'Link',
'options': 'Purchase Invoice',
'width': 120
},
{
'label': _('Posting Date'),
'fieldname': 'posting_date',
'fieldtype': 'Date',
'width': 120
}
])
if filters.get('group_by') != 'Supplier':
columns.extend([
{
'label': _('Supplier'),
'fieldname': 'supplier',
'fieldtype': 'Link',
'options': 'Supplier',
'width': 120
},
{
'label': _('Supplier Name'),
'fieldname': 'supplier_name',
'fieldtype': 'Data',
'width': 120
}
])
if additional_table_columns:
columns += additional_table_columns
columns += [
"Payable Account:Link/Account:120",
_("Mode of Payment") + ":Link/Mode of Payment:80", _("Project") + ":Link/Project:80",
_("Company") + ":Link/Company:100", _("Purchase Order") + ":Link/Purchase Order:100",
_("Purchase Receipt") + ":Link/Purchase Receipt:100", _("Expense Account") + ":Link/Account:140",
_("Stock Qty") + ":Float:120", _("Stock UOM") + "::100",
_("Rate") + ":Currency/currency:120", _("Amount") + ":Currency/currency:120"
{
'label': _('Payable Account'),
'fieldname': 'credit_to',
'fieldtype': 'Link',
'options': 'Account',
'width': 80
},
{
'label': _('Mode Of Payment'),
'fieldname': 'mode_of_payment',
'fieldtype': 'Data',
'width': 120
},
{
'label': _('Project'),
'fieldname': 'project',
'fieldtype': 'Link',
'options': 'Project',
'width': 80
},
{
'label': _('Company'),
'fieldname': 'company',
'fieldtype': 'Link',
'options': 'Company',
'width': 80
},
{
'label': _('Purchase Order'),
'fieldname': 'purchase_order',
'fieldtype': 'Link',
'options': 'Purchase Order',
'width': 100
},
{
'label': _("Purchase Receipt"),
'fieldname': 'Purchase Receipt',
'fieldtype': 'Link',
'options': 'Purchase Receipt',
'width': 100
},
{
'label': _('Expense Account'),
'fieldname': 'expense_account',
'fieldtype': 'Link',
'options': 'Account',
'width': 100
},
{
'label': _('Stock Qty'),
'fieldname': 'stock_qty',
'fieldtype': 'Float',
'width': 100
},
{
'label': _('Stock UOM'),
'fieldname': 'stock_uom',
'fieldtype': 'Link',
'options': 'UOM',
'width': 100
},
{
'label': _('Rate'),
'fieldname': 'rate',
'fieldtype': 'Float',
'options': 'currency',
'width': 100
},
{
'label': _('Amount'),
'fieldname': 'amount',
'fieldtype': 'Currency',
'options': 'currency',
'width': 100
},
{
'fieldname': 'currency',
'label': _('Currency'),
'fieldtype': 'Currency',
'width': 80,
'hidden': 1
}
]
if filters.get('group_by'):
columns.append({
'label': _('% Of Grand Total'),
'fieldname': 'percent_gt',
'fieldtype': 'Float',
'width': 80
})
return columns
def get_conditions(filters):
@@ -103,14 +297,15 @@ def get_conditions(filters):
if filters.get(opts[0]):
conditions += opts[1]
if not filters.get("group_by"):
conditions += "ORDER BY `tabPurchase Invoice`.posting_date desc, `tabPurchase Invoice Item`.item_code desc"
else:
conditions += get_group_by_conditions(filters, 'Purchase Invoice')
return conditions
def get_items(filters, additional_query_columns):
conditions = get_conditions(filters)
match_conditions = frappe.build_match_conditions("Purchase Invoice")
if match_conditions:
match_conditions = " and {0} ".format(match_conditions)
if additional_query_columns:
additional_query_columns = ', ' + ', '.join(additional_query_columns)
@@ -128,9 +323,8 @@ def get_items(filters, additional_query_columns):
`tabPurchase Invoice`.supplier_name, `tabPurchase Invoice`.mode_of_payment {0}
from `tabPurchase Invoice`, `tabPurchase Invoice Item`
where `tabPurchase Invoice`.name = `tabPurchase Invoice Item`.`parent` and
`tabPurchase Invoice`.docstatus = 1 %s %s
order by `tabPurchase Invoice`.posting_date desc, `tabPurchase Invoice Item`.item_code desc
""".format(additional_query_columns) % (conditions, match_conditions), filters, as_dict=1)
`tabPurchase Invoice`.docstatus = 1 %s
""".format(additional_query_columns) % (conditions), filters, as_dict=1)
def get_aii_accounts():
return dict(frappe.db.sql("select name, stock_received_but_not_billed from tabCompany"))

View File

@@ -4,48 +4,62 @@
frappe.query_reports["Item-wise Sales Register"] = {
"filters": [
{
"fieldname":"date_range",
"fieldname": "date_range",
"label": __("Date Range"),
"fieldtype": "DateRange",
"default": [frappe.datetime.add_months(frappe.datetime.get_today(),-1), frappe.datetime.get_today()],
"reqd": 1
},
{
"fieldname":"customer",
"fieldname": "customer",
"label": __("Customer"),
"fieldtype": "Link",
"options": "Customer"
},
{
"fieldname":"company",
"fieldname": "company",
"label": __("Company"),
"fieldtype": "Link",
"options": "Company",
"default": frappe.defaults.get_user_default("Company")
},
{
"fieldname":"mode_of_payment",
"fieldname": "mode_of_payment",
"label": __("Mode of Payment"),
"fieldtype": "Link",
"options": "Mode of Payment"
},
{
"fieldname":"warehouse",
"fieldname": "warehouse",
"label": __("Warehouse"),
"fieldtype": "Link",
"options": "Warehouse"
},
{
"fieldname":"brand",
"fieldname": "brand",
"label": __("Brand"),
"fieldtype": "Link",
"options": "Brand"
},
{
"fieldname":"item_group",
"fieldname": "item_group",
"label": __("Item Group"),
"fieldtype": "Link",
"options": "Item Group"
},
{
"label": __("Group By"),
"fieldname": "group_by",
"fieldtype": "Select",
"options": ["Customer Group", "Customer", "Item Group", "Item", "Territory", "Invoice"]
}
]
],
"formatter": function(value, row, column, data, default_formatter) {
value = default_formatter(value, row, column, data);
if (data && data.bold) {
value = value.bold();
}
return value;
}
}

View File

@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe, erpnext
from frappe import _
from frappe.utils import flt
from frappe.utils import flt, cstr
from frappe.model.meta import get_field_precision
from frappe.utils.xlsxutils import handle_html
from erpnext.accounts.report.sales_register.sales_register import get_mode_of_payments
@@ -15,23 +15,25 @@ def execute(filters=None):
def _execute(filters=None, additional_table_columns=None, additional_query_columns=None):
if not filters: filters = {}
filters.update({"from_date": filters.get("date_range") and filters.get("date_range")[0], "to_date": filters.get("date_range") and filters.get("date_range")[1]})
columns = get_columns(additional_table_columns)
columns = get_columns(additional_table_columns, filters)
company_currency = frappe.get_cached_value('Company', filters.get("company"), "default_currency")
item_list = get_items(filters, additional_query_columns)
if item_list:
itemised_tax, tax_columns = get_tax_accounts(item_list, columns, company_currency)
columns.append({
"fieldname": "currency",
"label": _("Currency"),
"fieldtype": "Data",
"width": 80
})
mode_of_payments = get_mode_of_payments(set([d.parent for d in item_list]))
so_dn_map = get_delivery_notes_against_sales_order(item_list)
data = []
total_row_map = {}
skip_total_row = 0
prev_group_by_value = ''
if filters.get('group_by'):
grand_total = get_grand_total(filters, 'Sales Invoice')
for d in item_list:
delivery_note = None
if d.delivery_note:
@@ -42,57 +44,285 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
if not delivery_note and d.update_stock:
delivery_note = d.parent
row = [d.item_code, d.item_name, d.item_group, d.description, d.parent, d.posting_date, d.customer, d.customer_name]
row = {
'item_code': d.item_code,
'item_name': d.item_name,
'item_group': d.item_group,
'description': d.description,
'invoice': d.parent,
'posting_date': d.posting_date,
'customer': d.customer,
'customer_name': d.customer_name,
'customer_group': d.customer_group,
}
if additional_query_columns:
for col in additional_query_columns:
row.append(d.get(col))
row.update({
col: d.get(col)
})
row += [
d.customer_group, d.debit_to, ", ".join(mode_of_payments.get(d.parent, [])),
d.territory, d.project, d.company, d.sales_order,
delivery_note, d.income_account, d.cost_center, d.stock_qty, d.stock_uom
]
row.update({
'debit_to': d.debit_to,
'mode_of_payment': ", ".join(mode_of_payments.get(d.parent, [])),
'territory': d.territory,
'project': d.project,
'company': d.company,
'sales_order': d.sales_order,
'delivery_note': d.delivery_note,
'income_account': d.income_account,
'cost_center': d.cost_center,
'stock_qty': d.stock_qty,
'stock_uom': d.stock_uom
})
if d.stock_uom != d.uom and d.stock_qty:
row += [(d.base_net_rate * d.qty)/d.stock_qty, d.base_net_amount]
row.update({
'rate': (d.base_net_rate * d.qty)/d.stock_qty,
'amount': d.base_net_amount
})
else:
row += [d.base_net_rate, d.base_net_amount]
row.update({
'rate': d.base_net_rate,
'amount': d.base_net_amount
})
total_tax = 0
for tax in tax_columns:
item_tax = itemised_tax.get(d.name, {}).get(tax, {})
row += [item_tax.get("tax_rate", 0), item_tax.get("tax_amount", 0)]
row.update({
frappe.scrub(tax + ' Rate'): item_tax.get("tax_rate", 0),
frappe.scrub(tax + ' Amount'): item_tax.get("tax_amount", 0),
})
total_tax += flt(item_tax.get("tax_amount"))
row += [total_tax, d.base_net_amount + total_tax, company_currency]
row.update({
'total_tax': total_tax,
'total': d.base_net_amount + total_tax,
'currency': company_currency
})
if filters.get('group_by'):
row.update({'percent_gt': flt(row['total']/grand_total) * 100})
group_by_field, subtotal_display_field = get_group_by_and_display_fields(filters)
data, prev_group_by_value = add_total_row(data, filters, prev_group_by_value, d, total_row_map,
group_by_field, subtotal_display_field, grand_total, tax_columns)
add_sub_total_row(row, total_row_map, d.get(group_by_field, ''), tax_columns)
data.append(row)
return columns, data
if filters.get('group_by'):
total_row = total_row_map.get(prev_group_by_value or d.get('item_name'))
total_row['percent_gt'] = flt(total_row['total']/grand_total * 100)
data.append(total_row)
data.append({})
add_sub_total_row(total_row, total_row_map, 'total_row', tax_columns)
data.append(total_row_map.get('total_row'))
skip_total_row = 1
def get_columns(additional_table_columns):
columns = [
_("Item Code") + ":Link/Item:120", _("Item Name") + "::120",
_("Item Group") + ":Link/Item Group:100", "Description::150", _("Invoice") + ":Link/Sales Invoice:120",
_("Posting Date") + ":Date:80", _("Customer") + ":Link/Customer:120",
_("Customer Name") + "::120"]
return columns, data, None, None, None, skip_total_row
def get_columns(additional_table_columns, filters):
columns = []
if filters.get('group_by') != ('Item'):
columns.extend(
[
{
'label': _('Item Code'),
'fieldname': 'item_code',
'fieldtype': 'Link',
'options': 'Item',
'width': 120
},
{
'label': _('Item Name'),
'fieldname': 'item_name',
'fieldtype': 'Data',
'width': 120
}
]
)
if filters.get('group_by') not in ('Item', 'Item Group'):
columns.extend([
{
'label': _('Item Group'),
'fieldname': 'item_group',
'fieldtype': 'Link',
'options': 'Item Group',
'width': 120
}
])
columns.extend([
{
'label': _('Description'),
'fieldname': 'description',
'fieldtype': 'Data',
'width': 150
},
{
'label': _('Invoice'),
'fieldname': 'invoice',
'fieldtype': 'Link',
'options': 'Sales Invoice',
'width': 120
},
{
'label': _('Posting Date'),
'fieldname': 'posting_date',
'fieldtype': 'Date',
'width': 120
}
])
if filters.get('group_by') != 'Customer':
columns.extend([
{
'label': _('Customer Group'),
'fieldname': 'customer_group',
'fieldtype': 'Link',
'options': 'Customer Group',
'width': 120
}
])
if filters.get('group_by') not in ('Customer', 'Customer Group'):
columns.extend([
{
'label': _('Customer'),
'fieldname': 'customer',
'fieldtype': 'Link',
'options': 'Customer',
'width': 120
},
{
'label': _('Customer Name'),
'fieldname': 'customer_name',
'fieldtype': 'Data',
'width': 120
}
])
if additional_table_columns:
columns += additional_table_columns
columns += [
_("Customer Group") + ":Link/Customer Group:120",
_("Receivable Account") + ":Link/Account:120",
_("Mode of Payment") + "::120", _("Territory") + ":Link/Territory:80",
_("Project") + ":Link/Project:80", _("Company") + ":Link/Company:100",
_("Sales Order") + ":Link/Sales Order:100", _("Delivery Note") + ":Link/Delivery Note:100",
_("Income Account") + ":Link/Account:140", _("Cost Center") + ":Link/Cost Center:140",
_("Stock Qty") + ":Float:120", _("Stock UOM") + "::100",
_("Rate") + ":Currency/currency:120",
_("Amount") + ":Currency/currency:120"
{
'label': _('Receivable Account'),
'fieldname': 'debit_to',
'fieldtype': 'Link',
'options': 'Account',
'width': 80
},
{
'label': _('Mode Of Payment'),
'fieldname': 'mode_of_payment',
'fieldtype': 'Data',
'width': 120
}
]
if filters.get('group_by') != 'Terriotory':
columns.extend([
{
'label': _("Territory"),
'fieldname': 'territory',
'fieldtype': 'Link',
'options': 'Territory',
'width': 80
}
])
columns += [
{
'label': _('Project'),
'fieldname': 'project',
'fieldtype': 'Link',
'options': 'Project',
'width': 80
},
{
'label': _('Company'),
'fieldname': 'company',
'fieldtype': 'Link',
'options': 'Company',
'width': 80
},
{
'label': _('Sales Order'),
'fieldname': 'sales_order',
'fieldtype': 'Link',
'options': 'Sales Order',
'width': 100
},
{
'label': _("Delivery Note"),
'fieldname': 'delivery_note',
'fieldtype': 'Link',
'options': 'Delivery Note',
'width': 100
},
{
'label': _('Income Account'),
'fieldname': 'income_account',
'fieldtype': 'Link',
'options': 'Account',
'width': 100
},
{
'label': _("Cost Center"),
'fieldname': 'cost_center',
'fieldtype': 'Link',
'options': 'Cost Center',
'width': 100
},
{
'label': _('Stock Qty'),
'fieldname': 'stock_qty',
'fieldtype': 'Float',
'width': 100
},
{
'label': _('Stock UOM'),
'fieldname': 'stock_uom',
'fieldtype': 'Link',
'options': 'UOM',
'width': 100
},
{
'label': _('Rate'),
'fieldname': 'rate',
'fieldtype': 'Float',
'options': 'currency',
'width': 100
},
{
'label': _('Amount'),
'fieldname': 'amount',
'fieldtype': 'Currency',
'options': 'currency',
'width': 100
},
{
'fieldname': 'currency',
'label': _('Currency'),
'fieldtype': 'Currency',
'width': 80,
'hidden': 1
}
]
if filters.get('group_by'):
columns.append({
'label': _('% Of Grand Total'),
'fieldname': 'percent_gt',
'fieldtype': 'Float',
'width': 80
})
return columns
def get_conditions(filters):
@@ -112,30 +342,34 @@ def get_conditions(filters):
and ifnull(`tabSales Invoice Payment`.mode_of_payment, '') = %(mode_of_payment)s)"""
if filters.get("warehouse"):
conditions += """ and exists(select name from `tabSales Invoice Item`
where parent=`tabSales Invoice`.name
and ifnull(`tabSales Invoice Item`.warehouse, '') = %(warehouse)s)"""
conditions += """and ifnull(`tabSales Invoice Item`.warehouse, '') = %(warehouse)s"""
if filters.get("brand"):
conditions += """ and exists(select name from `tabSales Invoice Item`
where parent=`tabSales Invoice`.name
and ifnull(`tabSales Invoice Item`.brand, '') = %(brand)s)"""
conditions += """and ifnull(`tabSales Invoice Item`.brand, '') = %(brand)s"""
if filters.get("item_group"):
conditions += """ and exists(select name from `tabSales Invoice Item`
where parent=`tabSales Invoice`.name
and ifnull(`tabSales Invoice Item`.item_group, '') = %(item_group)s)"""
conditions += """and ifnull(`tabSales Invoice Item`.item_group, '') = %(item_group)s"""
if not filters.get("group_by"):
conditions += "ORDER BY `tabSales Invoice`.posting_date desc, `tabSales Invoice Item`.item_group desc"
else:
conditions += get_group_by_conditions(filters, 'Sales Invoice')
return conditions
def get_group_by_conditions(filters, doctype):
if filters.get("group_by") == 'Invoice':
return "ORDER BY `tab{0} Item`.parent desc".format(doctype)
elif filters.get("group_by") == 'Item':
return "ORDER BY `tab{0} Item`.`item_code`".format(doctype)
elif filters.get("group_by") == 'Item Group':
return "ORDER BY `tab{0} Item`.{1}".format(doctype, frappe.scrub(filters.get('group_by')))
elif filters.get("group_by") in ('Customer', 'Customer Group', 'Territory', 'Supplier'):
return "ORDER BY `tab{0}`.{1}".format(doctype, frappe.scrub(filters.get('group_by')))
def get_items(filters, additional_query_columns):
conditions = get_conditions(filters)
match_conditions = frappe.build_match_conditions("Sales Invoice")
if match_conditions:
match_conditions = " and {0} ".format(match_conditions)
if additional_query_columns:
additional_query_columns = ', ' + ', '.join(additional_query_columns)
@@ -156,9 +390,8 @@ def get_items(filters, additional_query_columns):
`tabSales Invoice`.update_stock, `tabSales Invoice Item`.uom, `tabSales Invoice Item`.qty {0}
from `tabSales Invoice`, `tabSales Invoice Item`
where `tabSales Invoice`.name = `tabSales Invoice Item`.parent
and `tabSales Invoice`.docstatus = 1 %s %s
order by `tabSales Invoice`.posting_date desc, `tabSales Invoice Item`.item_code desc
""".format(additional_query_columns or '') % (conditions, match_conditions), filters, as_dict=1)
and `tabSales Invoice`.docstatus = 1 {1}
""".format(additional_query_columns or '', conditions), filters, as_dict=1) #nosec
def get_delivery_notes_against_sales_order(item_list):
so_dn_map = frappe._dict()
@@ -177,6 +410,15 @@ def get_delivery_notes_against_sales_order(item_list):
return so_dn_map
def get_grand_total(filters, doctype):
return frappe.db.sql(""" SELECT
SUM(`tab{0}`.base_grand_total)
FROM `tab{0}`
WHERE `tab{0}`.docstatus = 1
and posting_date between %s and %s
""".format(doctype), (filters.get('from_date'), filters.get('to_date')))[0][0] #nosec
def get_deducted_taxes():
return frappe.db.sql_list("select name from `tabPurchase Taxes and Charges` where add_deduct_tax = 'Deduct'")
@@ -264,9 +506,117 @@ def get_tax_accounts(item_list, columns, company_currency,
tax_columns.sort()
for desc in tax_columns:
columns.append(desc + " Rate:Data:80")
columns.append(desc + " Amount:Currency/currency:100")
columns.append({
'label': _(desc + ' Rate'),
'fieldname': frappe.scrub(desc + ' Rate'),
'fieldtype': 'Float',
'width': 100
})
columns += ["Total Tax:Currency/currency:80", "Total:Currency/currency:100"]
columns.append({
'label': _(desc + ' Amount'),
'fieldname': frappe.scrub(desc + ' Amount'),
'fieldtype': 'Currency',
'options': 'currency',
'width': 100
})
columns += [
{
'label': _('Total Tax'),
'fieldname': 'total_tax',
'fieldtype': 'Currency',
'options': 'currency',
'width': 100
},
{
'label': _('Total'),
'fieldname': 'total',
'fieldtype': 'Currency',
'options': 'currency',
'width': 100
}
]
return itemised_tax, tax_columns
def add_total_row(data, filters, prev_group_by_value, item, total_row_map,
group_by_field, subtotal_display_field, grand_total, tax_columns):
if prev_group_by_value != item.get(group_by_field, ''):
if prev_group_by_value:
total_row = total_row_map.get(prev_group_by_value)
data.append(total_row)
data.append({})
add_sub_total_row(total_row, total_row_map, 'total_row', tax_columns)
prev_group_by_value = item.get(group_by_field, '')
total_row_map.setdefault(item.get(group_by_field, ''), {
subtotal_display_field: get_display_value(filters, group_by_field, item),
'stock_qty': 0.0,
'amount': 0.0,
'bold': 1,
'total_tax': 0.0,
'total': 0.0,
'percent_gt': 0.0
})
total_row_map.setdefault('total_row', {
subtotal_display_field: "Total",
'stock_qty': 0.0,
'amount': 0.0,
'bold': 1,
'total_tax': 0.0,
'total': 0.0,
'percent_gt': 0.0
})
return data, prev_group_by_value
def get_display_value(filters, group_by_field, item):
if filters.get('group_by') == 'Item':
if item.get('item_code') != item.get('item_name'):
value = cstr(item.get('item_code')) + "<br><br>" + \
"<span style='font-weight: normal'>" + cstr(item.get('item_name')) + "</span>"
else:
value = item.get('item_code', '')
elif filters.get('group_by') in ('Customer', 'Supplier'):
party = frappe.scrub(filters.get('group_by'))
if item.get(party) != item.get(party+'_name'):
value = item.get(party) + "<br><br>" + \
"<span style='font-weight: normal'>" + item.get(party+'_name') + "</span>"
else:
value = item.get(party)
else:
value = item.get(group_by_field)
return value
def get_group_by_and_display_fields(filters):
if filters.get('group_by') == 'Item':
group_by_field = 'item_code'
subtotal_display_field = 'invoice'
elif filters.get('group_by') == 'Invoice':
group_by_field = 'parent'
subtotal_display_field = 'item_code'
else:
group_by_field = frappe.scrub(filters.get('group_by'))
subtotal_display_field = 'item_code'
return group_by_field, subtotal_display_field
def add_sub_total_row(item, total_row_map, group_by_value, tax_columns):
total_row = total_row_map.get(group_by_value)
total_row['stock_qty'] += item['stock_qty']
total_row['amount'] += item['amount']
total_row['total_tax'] += item['total_tax']
total_row['total'] += item['total']
total_row['percent_gt'] += item['percent_gt']
for tax in tax_columns:
total_row.setdefault(frappe.scrub(tax + ' Amount'), 0.0)
total_row[frappe.scrub(tax + ' Amount')] += flt(item[frappe.scrub(tax + ' Amount')])

View File

@@ -23,7 +23,8 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
{
"fieldname": "include_default_book_entries",
"label": __("Include Default Book Entries"),
"fieldtype": "Check"
"fieldtype": "Check",
"default": 1
}
);
});

View File

@@ -38,32 +38,46 @@ def _execute(filters, additional_table_columns=None, additional_query_columns=No
cost_center = list(set(invoice_cc_wh_map.get(inv.name, {}).get("cost_center", [])))
warehouse = list(set(invoice_cc_wh_map.get(inv.name, {}).get("warehouse", [])))
row = [
inv.name, inv.posting_date, inv.customer, inv.customer_name
]
row = {
'invoice': inv.name,
'posting_date': inv.posting_date,
'customer': inv.customer,
'customer_name': inv.customer_name
}
if additional_query_columns:
for col in additional_query_columns:
row.append(inv.get(col))
row.update({
col: inv.get(col)
})
row.update({
'customer_group': inv.get("customer_group"),
'territory': inv.get("territory"),
'tax_id': inv.get("tax_id"),
'receivable_account': inv.debit_to,
'mode_of_payment': ", ".join(mode_of_payments.get(inv.name, [])),
'project': inv.project,
'owner': inv.owner,
'remarks': inv.remarks,
'sales_order': ", ".join(sales_order),
'delivery_note': ", ".join(delivery_note),
'cost_center': ", ".join(cost_center),
'warehouse': ", ".join(warehouse),
'currency': company_currency
})
row +=[
inv.get("customer_group"),
inv.get("territory"),
inv.get("tax_id"),
inv.debit_to, ", ".join(mode_of_payments.get(inv.name, [])),
inv.project, inv.owner, inv.remarks,
", ".join(sales_order), ", ".join(delivery_note),", ".join(cost_center),
", ".join(warehouse), company_currency
]
# map income values
base_net_total = 0
for income_acc in income_accounts:
income_amount = flt(invoice_income_map.get(inv.name, {}).get(income_acc))
base_net_total += income_amount
row.append(income_amount)
row.update({
frappe.scrub(income_acc): income_amount
})
# net total
row.append(base_net_total or inv.base_net_total)
row.update({'net_total': base_net_total or inv.base_net_total})
# tax account
total_tax = 0
@@ -72,10 +86,18 @@ def _execute(filters, additional_table_columns=None, additional_query_columns=No
tax_amount_precision = get_field_precision(frappe.get_meta("Sales Taxes and Charges").get_field("tax_amount"), currency=company_currency) or 2
tax_amount = flt(invoice_tax_map.get(inv.name, {}).get(tax_acc), tax_amount_precision)
total_tax += tax_amount
row.append(tax_amount)
row.update({
frappe.scrub(tax_acc): tax_amount
})
# total tax, grand total, outstanding amount & rounded total
row += [total_tax, inv.base_grand_total, inv.base_rounded_total, inv.outstanding_amount]
row.update({
'tax_total': total_tax,
'grand_total': inv.base_grand_total,
'rounded_total': inv.base_rounded_total,
'outstanding_amount': inv.outstanding_amount
})
data.append(row)
@@ -84,19 +106,118 @@ def _execute(filters, additional_table_columns=None, additional_query_columns=No
def get_columns(invoice_list, additional_table_columns):
"""return columns based on filters"""
columns = [
_("Invoice") + ":Link/Sales Invoice:120", _("Posting Date") + ":Date:80",
_("Customer") + ":Link/Customer:120", _("Customer Name") + "::120"
{
'label': _("Invoice"),
'fieldname': 'invoice',
'fieldtype': 'Link',
'options': 'Sales Invoice',
'width': 120
},
{
'label': _("Posting Date"),
'fieldname': 'posting_date',
'fieldtype': 'Date',
'width': 80
},
{
'label': _("Customer"),
'fieldname': 'customer',
'fieldtype': 'Link',
'options': 'Customer',
'width': 120
},
{
'label': _("Customer Name"),
'fieldname': 'customer_name',
'fieldtype': 'Data',
'width': 120
},
]
if additional_table_columns:
columns += additional_table_columns
columns +=[
_("Customer Group") + ":Link/Customer Group:120", _("Territory") + ":Link/Territory:80",
_("Tax Id") + "::80", _("Receivable Account") + ":Link/Account:120", _("Mode of Payment") + "::120",
_("Project") +":Link/Project:80", _("Owner") + "::150", _("Remarks") + "::150",
_("Sales Order") + ":Link/Sales Order:100", _("Delivery Note") + ":Link/Delivery Note:100",
_("Cost Center") + ":Link/Cost Center:100", _("Warehouse") + ":Link/Warehouse:100",
{
'label': _("Customer Group"),
'fieldname': 'customer_group',
'fieldtype': 'Link',
'options': 'Customer Group',
'width': 120
},
{
'label': _("Territory"),
'fieldname': 'territory',
'fieldtype': 'Link',
'options': 'Territory',
'width': 80
},
{
'label': _("Tax Id"),
'fieldname': 'tax_id',
'fieldtype': 'Data',
'width': 120
},
{
'label': _("Receivable Account"),
'fieldname': 'receivable_account',
'fieldtype': 'Link',
'options': 'Account',
'width': 80
},
{
'label': _("Mode Of Payment"),
'fieldname': 'mode_of_payment',
'fieldtype': 'Data',
'width': 120
},
{
'label': _("Project"),
'fieldname': 'project',
'fieldtype': 'Link',
'options': 'Project',
'width': 80
},
{
'label': _("Owner"),
'fieldname': 'owner',
'fieldtype': 'Data',
'width': 150
},
{
'label': _("Remarks"),
'fieldname': 'remarks',
'fieldtype': 'Data',
'width': 150
},
{
'label': _("Sales Order"),
'fieldname': 'sales_order',
'fieldtype': 'Link',
'options': 'Sales Order',
'width': 100
},
{
'label': _("Delivery Note"),
'fieldname': 'delivery_note',
'fieldtype': 'Link',
'options': 'Delivery Note',
'width': 100
},
{
'label': _("Cost Center"),
'fieldname': 'cost_center',
'fieldtype': 'Link',
'options': 'Cost Center',
'width': 100
},
{
'label': _("Warehouse"),
'fieldname': 'warehouse',
'fieldtype': 'Link',
'options': 'Warehouse',
'width': 100
},
{
"fieldname": "currency",
"label": _("Currency"),
@@ -105,7 +226,10 @@ def get_columns(invoice_list, additional_table_columns):
}
]
income_accounts = tax_accounts = income_columns = tax_columns = []
income_accounts = []
tax_accounts = []
income_columns = []
tax_columns = []
if invoice_list:
income_accounts = frappe.db.sql_list("""select distinct income_account
@@ -119,14 +243,65 @@ def get_columns(invoice_list, additional_table_columns):
and parent in (%s) order by account_head""" %
', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]))
income_columns = [(account + ":Currency/currency:120") for account in income_accounts]
for account in income_accounts:
income_columns.append({
"label": account,
"fieldname": frappe.scrub(account),
"fieldtype": "Currency",
"options": 'currency',
"width": 120
})
for account in tax_accounts:
if account not in income_accounts:
tax_columns.append(account + ":Currency/currency:120")
tax_columns.append({
"label": account,
"fieldname": frappe.scrub(account),
"fieldtype": "Currency",
"options": 'currency',
"width": 120
})
columns = columns + income_columns + [_("Net Total") + ":Currency/currency:120"] + tax_columns + \
[_("Total Tax") + ":Currency/currency:120", _("Grand Total") + ":Currency/currency:120",
_("Rounded Total") + ":Currency/currency:120", _("Outstanding Amount") + ":Currency/currency:120"]
net_total_column = [{
"label": _("Net Total"),
"fieldname": "net_total",
"fieldtype": "Currency",
"options": 'currency',
"width": 120
}]
total_columns = [
{
"label": _("Tax Total"),
"fieldname": "tax_total",
"fieldtype": "Currency",
"options": 'currency',
"width": 120
},
{
"label": _("Grand Total"),
"fieldname": "grand_total",
"fieldtype": "Currency",
"options": 'currency',
"width": 120
},
{
"label": _("Rounded Total"),
"fieldname": "rounded_total",
"fieldtype": "Currency",
"options": 'currency',
"width": 120
},
{
"label": _("Outstanding Amount"),
"fieldname": "outstanding_amount",
"fieldtype": "Currency",
"options": 'currency',
"width": 120
}
]
columns = columns + income_columns + net_total_column + tax_columns + total_columns
return columns, income_accounts, tax_accounts

View File

@@ -85,7 +85,8 @@ frappe.require("assets/erpnext/js/financial_statements.js", function() {
{
"fieldname": "include_default_book_entries",
"label": __("Include Default Book Entries"),
"fieldtype": "Check"
"fieldtype": "Check",
"default": 1
}
],
"formatter": erpnext.financial_statements.formatter,

View File

@@ -103,9 +103,9 @@ def get_rootwise_opening_balances(filters, report_type):
where lft >= %s and rgt <= %s)""" % (lft, rgt)
if filters.finance_book:
fb_conditions = " and finance_book = %(finance_book)s"
fb_conditions = " AND finance_book = %(finance_book)s"
if filters.include_default_book_entries:
fb_conditions = " and (finance_book in (%(finance_book)s, %(company_fb)s))"
fb_conditions = " AND (finance_book in (%(finance_book)s, %(company_fb)s, '') OR finance_book IS NULL)"
additional_conditions += fb_conditions

View File

@@ -65,6 +65,21 @@ frappe.query_reports["Trial Balance for Party"] = {
return party_type;
}
},
{
"fieldname": "account",
"label": __("Account"),
"fieldtype": "Link",
"options": "Account",
"get_query": function() {
var company = frappe.query_report.get_filter_value('company');
return {
"doctype": "Account",
"filters": {
"company": company,
}
}
}
},
{
"fieldname": "show_zero_values",
"label": __("Show zero values"),

View File

@@ -18,14 +18,17 @@ def execute(filters=None):
return columns, data
def get_data(filters, show_party_name):
party_name_field = "{0}_name".format(frappe.scrub(filters.get('party_type')))
if filters.get('party_type') == 'Student':
if filters.get('party_type') in ('Customer', 'Supplier', 'Employee', 'Member'):
party_name_field = "{0}_name".format(frappe.scrub(filters.get('party_type')))
elif filters.get('party_type') == 'Student':
party_name_field = 'first_name'
elif filters.get('party_type') == 'Shareholder':
party_name_field = 'title'
else:
party_name_field = 'name'
party_filters = {"name": filters.get("party")} if filters.get("party") else {}
parties = frappe.get_all(filters.get("party_type"), fields = ["name", party_name_field],
parties = frappe.get_all(filters.get("party_type"), fields = ["name", party_name_field],
filters = party_filters, order_by="name")
company_currency = frappe.get_cached_value('Company', filters.company, "default_currency")
opening_balances = get_opening_balances(filters)
@@ -70,7 +73,7 @@ def get_data(filters, show_party_name):
# totals
for col in total_row:
total_row[col] += row.get(col)
row.update({
"currency": company_currency
})
@@ -78,7 +81,7 @@ def get_data(filters, show_party_name):
has_value = False
if (opening_debit or opening_credit or debit or credit or closing_debit or closing_credit):
has_value =True
if cint(filters.show_zero_values) or has_value:
data.append(row)
@@ -93,13 +96,19 @@ def get_data(filters, show_party_name):
return data
def get_opening_balances(filters):
account_filter = ''
if filters.get('account'):
account_filter = "and account = %s" % (frappe.db.escape(filters.get('account')))
gle = frappe.db.sql("""
select party, sum(debit) as opening_debit, sum(credit) as opening_credit
select party, sum(debit) as opening_debit, sum(credit) as opening_credit
from `tabGL Entry`
where company=%(company)s
where company=%(company)s
and ifnull(party_type, '') = %(party_type)s and ifnull(party, '') != ''
and (posting_date < %(from_date)s or ifnull(is_opening, 'No') = 'Yes')
group by party""", {
{account_filter}
group by party""".format(account_filter=account_filter), {
"company": filters.company,
"from_date": filters.from_date,
"party_type": filters.party_type
@@ -113,14 +122,20 @@ def get_opening_balances(filters):
return opening
def get_balances_within_period(filters):
account_filter = ''
if filters.get('account'):
account_filter = "and account = %s" % (frappe.db.escape(filters.get('account')))
gle = frappe.db.sql("""
select party, sum(debit) as debit, sum(credit) as credit
select party, sum(debit) as debit, sum(credit) as credit
from `tabGL Entry`
where company=%(company)s
where company=%(company)s
and ifnull(party_type, '') = %(party_type)s and ifnull(party, '') != ''
and posting_date >= %(from_date)s and posting_date <= %(to_date)s
and posting_date >= %(from_date)s and posting_date <= %(to_date)s
and ifnull(is_opening, 'No') = 'No'
group by party""", {
{account_filter}
group by party""".format(account_filter=account_filter), {
"company": filters.company,
"from_date": filters.from_date,
"to_date": filters.to_date,

View File

@@ -569,7 +569,7 @@ def get_stock_and_account_balance(account=None, posting_date=None, company=None)
warehouse_account = get_warehouse_account_map(company)
account_balance = get_balance_on(account, posting_date, in_account_currency=False)
account_balance = get_balance_on(account, posting_date, in_account_currency=False, ignore_account_permission=True)
related_warehouses = [wh for wh, wh_details in warehouse_account.items()
if wh_details.account == account and not wh_details.is_group]
@@ -640,8 +640,9 @@ def get_outstanding_invoices(party_type, party, account, condition=None, filters
precision = frappe.get_precision("Sales Invoice", "outstanding_amount") or 2
if account:
root_type = frappe.get_cached_value("Account", account, "root_type")
root_type, account_type = frappe.get_cached_value("Account", account, ["root_type", "account_type"])
party_account_type = "Receivable" if root_type == "Asset" else "Payable"
party_account_type = account_type or party_account_type
else:
party_account_type = erpnext.get_party_account_type(party_type)
@@ -891,3 +892,9 @@ def get_allow_cost_center_in_entry_of_bs_account():
def generator():
return cint(frappe.db.get_value('Accounts Settings', None, 'allow_cost_center_in_entry_of_bs_account'))
return frappe.local_cache("get_allow_cost_center_in_entry_of_bs_account", (), generator, regenerate_if_none=True)
def get_stock_accounts(company):
return frappe.get_all("Account", filters = {
"account_type": "Stock",
"company": company
})

View File

@@ -144,6 +144,10 @@ frappe.ui.form.on('Asset', {
frm.set_df_property('purchase_invoice', 'read_only', 1);
frm.set_df_property('purchase_receipt', 'read_only', 1);
}
else if (frm.doc.is_existing_asset) {
frm.toggle_reqd('purchase_receipt', 0);
frm.toggle_reqd('purchase_invoice', 0);
}
else if (frm.doc.purchase_receipt) {
// if purchase receipt link is set then set PI disabled
frm.toggle_reqd('purchase_invoice', 0);
@@ -256,6 +260,7 @@ frappe.ui.form.on('Asset', {
},
is_existing_asset: function(frm) {
frm.trigger("toggle_reference_doc");
// frm.toggle_reqd("next_depreciation_date", (!frm.doc.is_existing_asset && frm.doc.calculate_depreciation));
},
@@ -333,25 +338,12 @@ frappe.ui.form.on('Asset', {
})
},
purchase_receipt: function(frm) {
purchase_receipt: (frm) => {
frm.trigger('toggle_reference_doc');
if (frm.doc.purchase_receipt) {
if (frm.doc.item_code) {
frappe.db.get_doc('Purchase Receipt', frm.doc.purchase_receipt).then(pr_doc => {
frm.set_value('company', pr_doc.company);
frm.set_value('purchase_date', pr_doc.posting_date);
const item = pr_doc.items.find(item => item.item_code === frm.doc.item_code);
if (!item) {
frm.set_value('purchase_receipt', '');
frappe.msgprint({
title: __('Invalid Purchase Receipt'),
message: __("The selected Purchase Receipt doesn't contains selected Asset Item."),
indicator: 'red'
});
}
frm.set_value('gross_purchase_amount', item.base_net_rate);
frm.set_value('location', item.asset_location);
frm.events.set_values_from_purchase_doc(frm, 'Purchase Receipt', pr_doc)
});
} else {
frm.set_value('purchase_receipt', '');
@@ -363,24 +355,12 @@ frappe.ui.form.on('Asset', {
}
},
purchase_invoice: function(frm) {
purchase_invoice: (frm) => {
frm.trigger('toggle_reference_doc');
if (frm.doc.purchase_invoice) {
if (frm.doc.item_code) {
frappe.db.get_doc('Purchase Invoice', frm.doc.purchase_invoice).then(pi_doc => {
frm.set_value('company', pi_doc.company);
frm.set_value('purchase_date', pi_doc.posting_date);
const item = pi_doc.items.find(item => item.item_code === frm.doc.item_code);
if (!item) {
frm.set_value('purchase_invoice', '');
frappe.msgprint({
title: __('Invalid Purchase Invoice'),
message: __("The selected Purchase Invoice doesn't contains selected Asset Item."),
indicator: 'red'
});
}
frm.set_value('gross_purchase_amount', item.base_net_rate);
frm.set_value('location', item.asset_location);
frm.events.set_values_from_purchase_doc(frm, 'Purchase Invoice', pi_doc)
});
} else {
frm.set_value('purchase_invoice', '');
@@ -392,6 +372,24 @@ frappe.ui.form.on('Asset', {
}
},
set_values_from_purchase_doc: function(frm, doctype, purchase_doc) {
frm.set_value('company', purchase_doc.company);
frm.set_value('purchase_date', purchase_doc.posting_date);
const item = purchase_doc.items.find(item => item.item_code === frm.doc.item_code);
if (!item) {
doctype_field = frappe.scrub(doctype)
frm.set_value(doctype_field, '');
frappe.msgprint({
title: __(`Invalid ${doctype}`),
message: __(`The selected ${doctype} doesn't contains selected Asset Item.`),
indicator: 'red'
});
}
frm.set_value('gross_purchase_amount', item.base_net_rate + item.item_tax_amount);
frm.set_value('purchase_receipt_amount', item.base_net_rate + item.item_tax_amount);
frm.set_value('location', item.asset_location);
},
set_depreciation_rate: function(frm, row) {
if (row.total_number_of_depreciations && row.frequency_of_depreciation
&& row.expected_value_after_useful_life) {

View File

@@ -132,9 +132,10 @@ class Asset(AccountsController):
if len(movements) > 1:
frappe.throw(_('Asset has multiple Asset Movement Entries which has to be \
cancelled manually to cancel this asset.'))
movement = frappe.get_doc('Asset Movement', movements[0].get('name'))
movement.flags.ignore_validate = True
movement.cancel()
if movements:
movement = frappe.get_doc('Asset Movement', movements[0].get('name'))
movement.flags.ignore_validate = True
movement.cancel()
def make_asset_movement(self):
reference_doctype = 'Purchase Receipt' if self.purchase_receipt else 'Purchase Invoice'
@@ -517,15 +518,18 @@ def update_maintenance_status():
asset.set_status('Out of Order')
def make_post_gl_entry():
if not is_cwip_accounting_enabled(self.asset_category):
return
assets = frappe.db.sql_list(""" select name from `tabAsset`
where ifnull(booked_fixed_asset, 0) = 0 and available_for_use_date = %s""", nowdate())
asset_categories = frappe.db.get_all('Asset Category', fields = ['name', 'enable_cwip_accounting'])
for asset in assets:
doc = frappe.get_doc('Asset', asset)
doc.make_gl_entries()
for asset_category in asset_categories:
if cint(asset_category.enable_cwip_accounting):
assets = frappe.db.sql_list(""" select name from `tabAsset`
where asset_category = %s and ifnull(booked_fixed_asset, 0) = 0
and available_for_use_date = %s""", (asset_category.name, nowdate()))
for asset in assets:
doc = frappe.get_doc('Asset', asset)
doc.make_gl_entries()
def get_asset_naming_series():
meta = frappe.get_meta('Asset')
@@ -607,13 +611,19 @@ def get_asset_account(account_name, asset=None, asset_category=None, company=Non
if asset:
account = get_asset_category_account(account_name, asset=asset,
asset_category = asset_category, company = company)
if not asset and not account:
account = get_asset_category_account(account_name, asset_category = asset_category, company = company)
if not account:
account = frappe.get_cached_value('Company', company, account_name)
if not account:
frappe.throw(_("Set {0} in asset category {1} or company {2}")
.format(account_name.replace('_', ' ').title(), asset_category, company))
if not asset_category:
frappe.throw(_("Set {0} in company {1}").format(account_name.replace('_', ' ').title(), company))
else:
frappe.throw(_("Set {0} in asset category {1} or company {2}")
.format(account_name.replace('_', ' ').title(), asset_category, company))
return account

View File

@@ -22,7 +22,7 @@ def post_depreciation_entries(date=None):
def get_depreciable_assets(date):
return frappe.db.sql_list("""select a.name
from tabAsset a, `tabDepreciation Schedule` ds
where a.name = ds.parent and a.docstatus=1 and ds.schedule_date<=%s
where a.name = ds.parent and a.docstatus=1 and ds.schedule_date<=%s and a.calculate_depreciation = 1
and a.status in ('Submitted', 'Partially Depreciated')
and ifnull(ds.journal_entry, '')=''""", date)

View File

@@ -29,7 +29,8 @@ def get_asset_category_account(fieldname, item=None, asset=None, account=None, a
account=None
if not account:
asset_category, company = frappe.db.get_value("Asset", asset, ["asset_category", "company"])
asset_details = frappe.db.get_value("Asset", asset, ["asset_category", "company"])
asset_category, company = asset_details or [None, None]
account = frappe.db.get_value("Asset Category Account",
filters={"parent": asset_category, "company_name": company}, fieldname=fieldname)

View File

@@ -110,7 +110,7 @@ class AssetMovement(Document):
ORDER BY
asm.transaction_date asc
""", (d.asset, self.company, 'Receipt'), as_dict=1)
if auto_gen_movement_entry[0].get('name') == self.name:
if auto_gen_movement_entry and auto_gen_movement_entry[0].get('name') == self.name:
frappe.throw(_('{0} will be cancelled automatically on asset cancellation as it was \
auto generated for Asset {1}').format(self.name, d.asset))

View File

@@ -1,580 +1,146 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"actions": [],
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:location_name",
"beta": 0,
"creation": "2018-05-07 12:49:22.595974",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"location_name",
"parent_location",
"cb_details",
"is_container",
"is_group",
"sb_location_details",
"latitude",
"longitude",
"cb_latlong",
"area",
"area_uom",
"sb_geolocation",
"location",
"tree_details",
"lft",
"rgt",
"old_parent"
],
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "location_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Location Name",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "parent_location",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Parent Location",
"length": 0,
"no_copy": 0,
"options": "Location",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 1,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"search_index": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "cb_details",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"fieldtype": "Column Break"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0",
"description": "Check if it is a hydroponic unit",
"fieldname": "is_container",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Is Container",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"label": "Is Container"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 1,
"collapsible": 0,
"columns": 0,
"default": "0",
"fieldname": "is_group",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Is Group",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"label": "Is Group"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "sb_location_details",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Location Details",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"label": "Location Details"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_from": "parent_location.latitude",
"fieldname": "latitude",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Latitude",
"length": 0,
"no_copy": 0,
"options": "",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"label": "Latitude"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_from": "parent_location.longitude",
"fieldname": "longitude",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Longitude",
"length": 0,
"no_copy": 0,
"options": "",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"label": "Longitude"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "cb_latlong",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"fieldtype": "Column Break"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "area",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Area",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"read_only": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.area",
"fieldname": "area_uom",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Area UOM",
"length": 0,
"no_copy": 0,
"options": "UOM",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"options": "UOM"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "sb_geolocation",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"fieldtype": "Section Break"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "location",
"fieldtype": "Geolocation",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Location",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"label": "Location"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "tree_details",
"fieldtype": "Section Break",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Tree Details",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"label": "Tree Details"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "lft",
"fieldtype": "Int",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "lft",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"read_only": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "rgt",
"fieldtype": "Int",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "rgt",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"read_only": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "old_parent",
"fieldtype": "Data",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Old Parent",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"read_only": 1
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-07-11 13:36:30.999405",
"links": [],
"modified": "2020-01-28 13:52:22.513425",
"modified_by": "Administrator",
"module": "Assets",
"name": "Location",
@@ -582,127 +148,78 @@
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Stock User",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts User",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Stock Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Agriculture Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Agriculture User",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
}
],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0,
"track_views": 0
"track_changes": 1
}

View File

@@ -20,11 +20,32 @@ frappe.query_reports["Fixed Asset Register"] = {
default: 'In Location',
reqd: 1
},
{
fieldname:"purchase_date",
label: __("Purchase Date"),
fieldtype: "Date"
},
{
fieldname:"available_for_use_date",
label: __("Available For Use Date"),
fieldtype: "Date"
},
{
fieldname:"finance_book",
label: __("Finance Book"),
fieldtype: "Link",
options: "Finance Book"
},
{
fieldname:"asset_category",
label: __("Asset Category"),
fieldtype: "Link",
options: "Asset Category"
},
{
fieldname:"is_existing_asset",
label: __("Is Existing Asset"),
fieldtype: "Check"
},
]
};

View File

@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import cstr
from frappe.utils import cstr, today, flt
def execute(filters=None):
filters = frappe._dict(filters or {})
@@ -40,6 +40,42 @@ def get_columns(filters):
"fieldname": "status",
"width": 90
},
{
"label": _("Purchase Date"),
"fieldtype": "Date",
"fieldname": "purchase_date",
"width": 90
},
{
"label": _("Available For Use Date"),
"fieldtype": "Date",
"fieldname": "available_for_use_date",
"width": 90
},
{
"label": _("Gross Purchase Amount"),
"fieldname": "gross_purchase_amount",
"options": "Currency",
"width": 90
},
{
"label": _("Asset Value"),
"fieldname": "asset_value",
"options": "Currency",
"width": 90
},
{
"label": _("Opening Accumulated Depreciation"),
"fieldname": "opening_accumulated_depreciation",
"options": "Currency",
"width": 90
},
{
"label": _("Depreciated Amount"),
"fieldname": "depreciated_amount",
"options": "Currency",
"width": 90
},
{
"label": _("Cost Center"),
"fieldtype": "Link",
@@ -54,25 +90,6 @@ def get_columns(filters):
"options": "Department",
"width": 100
},
{
"label": _("Location"),
"fieldtype": "Link",
"fieldname": "location",
"options": "Location",
"width": 100
},
{
"label": _("Purchase Date"),
"fieldtype": "Date",
"fieldname": "purchase_date",
"width": 90
},
{
"label": _("Gross Purchase Amount"),
"fieldname": "gross_purchase_amount",
"options": "Currency",
"width": 90
},
{
"label": _("Vendor Name"),
"fieldtype": "Data",
@@ -80,25 +97,29 @@ def get_columns(filters):
"width": 100
},
{
"label": _("Available For Use Date"),
"fieldtype": "Date",
"fieldname": "available_for_use_date",
"width": 90
},
{
"label": _("Current Value"),
"fieldname": "current_value",
"options": "Currency",
"width": 90
"label": _("Location"),
"fieldtype": "Link",
"fieldname": "location",
"options": "Location",
"width": 100
},
]
def get_conditions(filters):
conditions = {'docstatus': 1}
conditions = { 'docstatus': 1 }
status = filters.status
date = filters.date
if filters.company:
if filters.get('company'):
conditions["company"] = filters.company
if filters.get('purchase_date'):
conditions["purchase_date"] = ('<=', filters.get('purchase_date'))
if filters.get('available_for_use_date'):
conditions["available_for_use_date"] = ('<=', filters.get('available_for_use_date'))
if filters.get('is_existing_asset'):
conditions["is_existing_asset"] = filters.get('is_existing_asset')
if filters.get('asset_category'):
conditions["asset_category"] = filters.get('asset_category')
# In Store assets are those that are not sold or scrapped
operand = 'not in'
@@ -114,7 +135,7 @@ def get_data(filters):
data = []
conditions = get_conditions(filters)
current_value_map = get_finance_book_value_map(filters.finance_book)
depreciation_amount_map = get_finance_book_value_map(filters)
pr_supplier_map = get_purchase_receipt_supplier_map()
pi_supplier_map = get_purchase_invoice_supplier_map()
@@ -122,10 +143,12 @@ def get_data(filters):
filters=conditions,
fields=["name", "asset_name", "department", "cost_center", "purchase_receipt",
"asset_category", "purchase_date", "gross_purchase_amount", "location",
"available_for_use_date", "status", "purchase_invoice"])
"available_for_use_date", "status", "purchase_invoice", "opening_accumulated_depreciation"])
for asset in assets_record:
if current_value_map.get(asset.name) is not None:
asset_value = asset.gross_purchase_amount - flt(asset.opening_accumulated_depreciation) \
- flt(depreciation_amount_map.get(asset.name))
if asset_value:
row = {
"asset_id": asset.name,
"asset_name": asset.asset_name,
@@ -134,23 +157,30 @@ def get_data(filters):
"cost_center": asset.cost_center,
"vendor_name": pr_supplier_map.get(asset.purchase_receipt) or pi_supplier_map.get(asset.purchase_invoice),
"gross_purchase_amount": asset.gross_purchase_amount,
"opening_accumulated_depreciation": asset.opening_accumulated_depreciation,
"depreciated_amount": depreciation_amount_map.get(asset.name) or 0.0,
"available_for_use_date": asset.available_for_use_date,
"location": asset.location,
"asset_category": asset.asset_category,
"purchase_date": asset.purchase_date,
"current_value": current_value_map.get(asset.name)
"asset_value": asset_value
}
data.append(row)
return data
def get_finance_book_value_map(finance_book=''):
def get_finance_book_value_map(filters):
date = filters.get('purchase_date') or filters.get('available_for_use_date') or today()
return frappe._dict(frappe.db.sql(''' Select
parent, value_after_depreciation
FROM `tabAsset Finance Book`
parent, SUM(depreciation_amount)
FROM `tabDepreciation Schedule`
WHERE
parentfield='finance_books'
AND ifnull(finance_book, '')=%s''', cstr(finance_book)))
parentfield='schedules'
AND schedule_date<=%s
AND journal_entry IS NOT NULL
AND ifnull(finance_book, '')=%s
GROUP BY parent''', (date, cstr(filters.finance_book or ''))))
def get_purchase_receipt_supplier_map():
return frappe._dict(frappe.db.sql(''' Select

View File

@@ -18,6 +18,7 @@ frappe.ui.form.on("Purchase Order", {
return {
filters: {
"company": frm.doc.company,
"name": ['!=', frm.doc.supplier_warehouse],
"is_group": 0
}
}
@@ -133,7 +134,7 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
if (doc.status != "On Hold") {
if(flt(doc.per_received, 2) < 100 && allow_receipt) {
cur_frm.add_custom_button(__('Receipt'), this.make_purchase_receipt, __('Create'));
if(doc.is_subcontracted==="Yes") {
if(doc.is_subcontracted==="Yes" && me.has_unsupplied_items()) {
cur_frm.add_custom_button(__('Material to Supplier'),
function() { me.make_stock_entry(); }, __("Transfer"));
}
@@ -190,6 +191,10 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
set_schedule_date(this.frm);
},
has_unsupplied_items: function() {
return this.frm.doc['supplied_items'].some(item => item.required_qty != item.supplied_qty)
},
make_stock_entry: function() {
var items = $.map(cur_frm.doc.items, function(d) { return d.bom ? d.item_code : false; });
var me = this;
@@ -266,7 +271,7 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
if (me.frm.doc['supplied_items']) {
me.frm.doc['supplied_items'].forEach((item, index) => {
if (item.rm_item_code && item.main_item_code) {
if (item.rm_item_code && item.main_item_code && item.required_qty - item.supplied_qty != 0) {
me.raw_material_data.push ({
'name':item.name,
'item_code': item.main_item_code,
@@ -283,6 +288,8 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
})
}
me.dialog.get_field('sub_con_rm_items').check_all_rows()
me.dialog.show()
this.dialog.set_primary_action(__('Transfer'), function() {
me.values = me.dialog.get_values();

View File

@@ -56,6 +56,7 @@
"section_break_48",
"pricing_rules",
"raw_material_details",
"set_reserve_warehouse",
"supplied_items",
"sb_last_purchase",
"total_qty",
@@ -340,6 +341,7 @@
"fieldname": "contact_email",
"fieldtype": "Small Text",
"label": "Contact Email",
"options": "Email",
"print_hide": 1,
"read_only": 1
},
@@ -607,7 +609,7 @@
},
{
"fieldname": "other_charges_calculation",
"fieldtype": "Text",
"fieldtype": "Long Text",
"label": "Taxes and Charges Calculation",
"no_copy": 1,
"oldfieldtype": "HTML",
@@ -1039,12 +1041,19 @@
"fieldtype": "Link",
"label": "Tax Category",
"options": "Tax Category"
},
{
"depends_on": "supplied_items",
"fieldname": "set_reserve_warehouse",
"fieldtype": "Link",
"label": "Set Reserve Warehouse",
"options": "Warehouse"
}
],
"icon": "fa fa-file-text",
"idx": 105,
"is_submittable": 1,
"modified": "2019-07-11 18:25:49.509343",
"modified": "2020-01-14 18:54:39.694448",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",

View File

@@ -0,0 +1,3 @@
{% include "erpnext/regional/india/taxes.js" %}
erpnext.setup_auto_gst_taxation('Purchase Order');

View File

@@ -116,6 +116,73 @@ class TestPurchaseOrder(unittest.TestCase):
self.assertEqual(po.get("items")[0].amount, 1400)
self.assertEqual(get_ordered_qty(), existing_ordered_qty + 3)
def test_add_new_item_in_update_child_qty_rate(self):
po = create_purchase_order(do_not_save=1)
po.items[0].qty = 4
po.save()
po.submit()
pr = make_pr_against_po(po.name, 2)
po.load_from_db()
first_item_of_po = po.get("items")[0]
trans_item = json.dumps([
{
'item_code': first_item_of_po.item_code,
'rate': first_item_of_po.rate,
'qty': first_item_of_po.qty,
'docname': first_item_of_po.name
},
{'item_code' : '_Test Item', 'rate' : 200, 'qty' : 7}
])
update_child_qty_rate('Purchase Order', trans_item, po.name)
po.reload()
self.assertEquals(len(po.get('items')), 2)
self.assertEqual(po.status, 'To Receive and Bill')
def test_remove_item_in_update_child_qty_rate(self):
po = create_purchase_order(do_not_save=1)
po.items[0].qty = 4
po.save()
po.submit()
pr = make_pr_against_po(po.name, 2)
po.reload()
first_item_of_po = po.get("items")[0]
# add an item
trans_item = json.dumps([
{
'item_code': first_item_of_po.item_code,
'rate': first_item_of_po.rate,
'qty': first_item_of_po.qty,
'docname': first_item_of_po.name
},
{'item_code' : '_Test Item', 'rate' : 200, 'qty' : 7}])
update_child_qty_rate('Purchase Order', trans_item, po.name)
po.reload()
# check if can remove received item
trans_item = json.dumps([{'item_code' : '_Test Item', 'rate' : 200, 'qty' : 7, 'docname': po.get("items")[1].name}])
self.assertRaises(frappe.ValidationError, update_child_qty_rate, 'Purchase Order', trans_item, po.name)
first_item_of_po = po.get("items")[0]
trans_item = json.dumps([
{
'item_code': first_item_of_po.item_code,
'rate': first_item_of_po.rate,
'qty': first_item_of_po.qty,
'docname': first_item_of_po.name
}
])
update_child_qty_rate('Purchase Order', trans_item, po.name)
po.reload()
self.assertEquals(len(po.get('items')), 1)
self.assertEqual(po.status, 'To Receive and Bill')
def test_update_qty(self):
po = create_purchase_order()
@@ -519,47 +586,62 @@ class TestPurchaseOrder(unittest.TestCase):
def test_backflush_based_on_stock_entry(self):
item_code = "_Test Subcontracted FG Item 1"
make_subcontracted_item(item_code)
make_item('Sub Contracted Raw Material 1', {
'is_stock_item': 1,
'is_sub_contracted_item': 1
})
update_backflush_based_on("Material Transferred for Subcontract")
po = create_purchase_order(item_code=item_code, qty=1,
order_qty = 5
po = create_purchase_order(item_code=item_code, qty=order_qty,
is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC")
make_stock_entry(target="_Test Warehouse - _TC", qty=10, basic_rate=100)
make_stock_entry(target="_Test Warehouse - _TC",
item_code="_Test Item Home Desktop 100", qty=10, basic_rate=100)
make_stock_entry(target="_Test Warehouse - _TC",
item_code = "Test Extra Item 1", qty=100, basic_rate=100)
make_stock_entry(target="_Test Warehouse - _TC",
item_code = "Test Extra Item 2", qty=10, basic_rate=100)
make_stock_entry(target="_Test Warehouse - _TC",
item_code = "Sub Contracted Raw Material 1", qty=10, basic_rate=100)
rm_item = [
{"item_code":item_code,"rm_item_code":"_Test Item","item_name":"_Test Item",
"qty":1,"warehouse":"_Test Warehouse - _TC","rate":100,"amount":100,"stock_uom":"Nos"},
rm_items = [
{"item_code":item_code,"rm_item_code":"Sub Contracted Raw Material 1","item_name":"_Test Item",
"qty":10,"warehouse":"_Test Warehouse - _TC", "stock_uom":"Nos"},
{"item_code":item_code,"rm_item_code":"_Test Item Home Desktop 100","item_name":"_Test Item Home Desktop 100",
"qty":2,"warehouse":"_Test Warehouse - _TC","rate":100,"amount":200,"stock_uom":"Nos"},
"qty":20,"warehouse":"_Test Warehouse - _TC", "stock_uom":"Nos"},
{"item_code":item_code,"rm_item_code":"Test Extra Item 1","item_name":"Test Extra Item 1",
"qty":1,"warehouse":"_Test Warehouse - _TC","rate":100,"amount":200,"stock_uom":"Nos"}]
"qty":10,"warehouse":"_Test Warehouse - _TC", "stock_uom":"Nos"},
{'item_code': item_code, 'rm_item_code': 'Test Extra Item 2', 'stock_uom':'Nos',
'qty': 10, 'warehouse': '_Test Warehouse - _TC', 'item_name':'Test Extra Item 2'}]
rm_item_string = json.dumps(rm_item)
rm_item_string = json.dumps(rm_items)
se = frappe.get_doc(make_subcontract_transfer_entry(po.name, rm_item_string))
se.append('items', {
'item_code': "Test Extra Item 2",
"qty": 1,
"rate": 100,
"s_warehouse": "_Test Warehouse - _TC",
"t_warehouse": "_Test Warehouse 1 - _TC"
})
se.set_missing_values()
se.submit()
pr = make_purchase_receipt(po.name)
received_qty = 2
# partial receipt
pr.get('items')[0].qty = received_qty
pr.save()
pr.submit()
se_items = sorted([d.item_code for d in se.get('items')])
supplied_items = sorted([d.rm_item_code for d in pr.get('supplied_items')])
transferred_items = sorted([d.item_code for d in se.get('items') if se.purchase_order == po.name])
issued_items = sorted([d.rm_item_code for d in pr.get('supplied_items')])
self.assertEquals(transferred_items, issued_items)
self.assertEquals(pr.get('items')[0].rm_supp_cost, 2000)
transferred_rm_map = frappe._dict()
for item in rm_items:
transferred_rm_map[item.get('rm_item_code')] = item
for item in pr.get('supplied_items'):
self.assertEqual(item.get('required_qty'), (transferred_rm_map[item.get('rm_item_code')].get('qty') / order_qty) * received_qty)
self.assertEquals(se_items, supplied_items)
update_backflush_based_on("BOM")
def test_advance_payment_entry_unlink_against_purchase_order(self):

View File

@@ -9,7 +9,7 @@ cur_frm.add_fetch('contact', 'email_id', 'email_id')
frappe.ui.form.on("Request for Quotation",{
setup: function(frm) {
frm.custom_make_buttons = {
'Supplier Quotation': 'Supplier Quotation'
'Supplier Quotation': 'Create'
}
frm.fields_dict["suppliers"].grid.get_field("contact").get_query = function(doc, cdt, cdn) {

View File

@@ -138,7 +138,7 @@ def refresh_scorecards():
# Check to see if any new scorecard periods are created
if make_all_scorecards(sc.name) > 0:
# Save the scorecard to update the score and standings
sc.save()
frappe.get_doc('Supplier Scorecard', sc.name).save()
@frappe.whitelist()

View File

@@ -141,13 +141,13 @@ def get_conditions(filters):
conditions = ""
if filters.get("company"):
conditions += " AND company='%s'"% filters.get('company')
conditions += " AND company=%s"% frappe.db.escape(filters.get('company'))
if filters.get("cost_center") or filters.get("project"):
conditions += """
AND (cost_center='%s'
OR project='%s')
"""% (filters.get('cost_center'), filters.get('project'))
AND (cost_center=%s
OR project=%s)
"""% (frappe.db.escape(filters.get('cost_center')), frappe.db.escape(filters.get('project')))
if filters.get("from_date"):
conditions += " AND transaction_date>=%s"% filters.get('from_date')

View File

@@ -0,0 +1,33 @@
# Version 12.3.0 Release Notes
### Accounting
1. Statewise GST taxation for India
- Added GST state in the tax category
- Added tax category in the address, sales/purchase tax template
- Based on the address system will fetch the tax template
2. Accounts Payable report based on payment terms
3. Trial Balance Report with filter "Party Name"
4. Fixed asset register report with date filters
### CRM
1. Appointment Scheduling
- Configure the appointment slots using Appointment Booking Settings
- Users can book the appointment through the portal based on slot availability
### HR
1. Refactored Employee Attendance Tool
2. Set allocated amount in employee advance as per total amount
### Fixes
1. Stock entry decimal issue while creating the GL entries
2. Item wise stock balance report
3. Valuation of subcontracting finished good item
4. Not able to create Instructor, Student entries
5. Pricing rule for a product discount
6. POS for serialized items
7. Not able to cancel share transfer entry
8. Ledger entries for compensatory off were not getting created

View File

@@ -0,0 +1,89 @@
# Version 12.4.0 Release Note
### Accounts
- Validity of item tax. [#20135](https://github.com/frappe/erpnext/pull/20135)
- Dynamic filters for dimensions in the budget variance report. [#19973](https://github.com/frappe/erpnext/pull/19973)
- Purchase Receipt and Purchase Invoice is not mandatory for an existing asset. [19980](https://github.com/frappe/erpnext/pull/19980)
- Allowed multiple Landed Cost Vouchers against a Purchase Receipt / Purchase Invoice. [#20058](https://github.com/frappe/erpnext/pull/20058)
- Rounding adjustment while both inclusive tax and additional discount amount are applied. [#20078](https://github.com/frappe/erpnext/pull/20078)
- Fixed an error while doing payment reconciliation for party type Employee. [#20088](https://github.com/frappe/erpnext/pull/20088)
- Show Closing row in General Ledger print. [#20161](https://github.com/frappe/erpnext/pull/20161)
- New report - Stock and Account Balance Comparison. [#20226](https://github.com/frappe/erpnext/pull/20226)
- Paid amount should not be over-written on clicking "Get Outstanding Invoices" button in Payment Entry. [#20050](https://github.com/frappe/erpnext/pull/20050)
- Currency symbol in Sales / Purchase Register report
- Currency symbol in "Bank and Cash Payment Voucher" print format.
### Human Resource
- Fixed leave allocation on the compensatory leave request submission. [#19961](https://github.com/frappe/erpnext/pull/19961)
- Create Payment Entry against Employee Advance to return any unclaimed amount and update returned amount in Employee Advance. [#19955](https://github.com/frappe/erpnext/pull/19955)
- Set Party against loan accounts in an accrual journal entry for salary. [#20022](https://github.com/frappe/erpnext/pull/20022)
- Editable loan repayment schedule after submission [#20122](https://github.com/frappe/erpnext/pull/20112)
- Update the paid amount and status of a loan after processing salary slip against it. [#20023](https://github.com/frappe/erpnext/pull/20023)
- Settings to disable rounded total in salary slip via HR Settings. [#20150](https://github.com/frappe/erpnext/pull/20150)
- Submit Salary button was not showing after creating salary slip in payroll entry. [#19753](https://github.com/frappe/erpnext/pull/19753)
- Payment Entry against payroll entry should deduct loan amount (if there are any loan deductions in salary slip). [#20194](https://github.com/frappe/erpnext/pull/20194)
- Show only relevant "Job Offer" in Employee Onboarding based on Job Applicant
- Added dashboard in Employee Advance
### Manufacturing
- Fixed backflushed qty for partial receipt against a subcontracted purchase order. [#20026](https://github.com/frappe/erpnext/pull/20026)
- Added "Set Reserve Warehouse" field in sub-contracted Purchase Order. [19992](https://github.com/frappe/erpnext/pull/19992)
- Only shows if the supplied items table is not empty
- On entering a warehouse in the field, it sets / overwrites reserve warehouse in Supplied Raw Materials table.
- In Backflush Stock Entry against Work Order, additional cost for service items (defined in BOM) should come proportionately based on finished goods qty. [#20105](https://github.com/frappe/erpnext/pull/20105)
- Hide transfer button in a subcontracted PO if full qty is already transferred. [#20155](https://github.com/frappe/erpnext/pull/20155)
- Set correct valuation rate of finished goods item in case of multiple material consumptions. [#20165](https://github.com/frappe/erpnext/pull/20165)
- Job Card creation from Work Order dashboard
### Stock
- Fixed ambiguous column name in the Batch query. Test by searching in any Batch link field.
- Fixed incorrect reorder level in Stock balance report
- Validate Batch for serialized items
- Get the outgoing rate of serial no from SLE if serial no already transferred to another company. [#20171](https://github.com/frappe/erpnext/pull/20171)
- Deliver Note creation from Sales Order dashboard. [#20199](https://github.com/frappe/erpnext/pull/20199)
### Others
- Addition and deletion of items in submitted Sales Order / Purchase Order. [#19911](https://github.com/frappe/erpnext/pull/19911)
- Get item price based on price list considering minimum qty. [#20206](https://github.com/frappe/erpnext/pull/20206)
- Product Bundle item should not appear in dialog on click of "Create Material Request" button. [#20216](https://github.com/frappe/erpnext/pull/20216)
- Delete linked communications on the deletion of company transactions. [#19928](https://github.com/frappe/erpnext/pull/19928)

View File

@@ -0,0 +1,53 @@
## Version 12.5.0 Release Note
### New Features:
- **Group by Customer / Customer Group / Item / Item Group / Territory / Invoice** option in Itemised Sales Register report [#20251](https://github.com/frappe/erpnext/pull/20251)
- **Group by Supplier / Item / Item Group / Invoice** option in Itemised Purchase Register report
- **Group by Customer / Supplier** option in Accounts Receivable / Payable report
- Enhanced Fixed Asset Register report [#20332](https://github.com/frappe/erpnext/pull/20332)
- Added tax category in pos profile [#20413](https://github.com/frappe/erpnext/pull/20413)
### Fixes
- GL Entries were not creating on manual asset creation [#20265](https://github.com/frappe/erpnext/pull/20265)
- Payment Entry should not be allowed against blocked Purchase Invoice until release date [#20270](https://github.com/frappe/erpnext/pull/20270)
- Incorrect number of GL Entries error in stock entry due to precision issue [#20297](https://github.com/frappe/erpnext/pull/20297)
- Wrong outstanding invoices fetched against employee [#20373](https://github.com/frappe/erpnext/pull/20373)
- Finance book filtering logic in financial statements and other accounting reports [#20411](https://github.com/frappe/erpnext/pull/20410)
- Additional discount was not appling on sales invoice created by subscription [#20432](https://github.com/frappe/erpnext/pull/20432)
- Deprecated fetching item price based on minimum qty [#20346](https://github.com/frappe/erpnext/pull/20346)
- Calculation of carry forwarded leaves [#20341](https://github.com/frappe/erpnext/pull/20341)
- Quotation status will be expired based on validity only if it is not Ordered or Lost [#20365](https://github.com/frappe/erpnext/pull/20354)
- Delete auto created batch on cancellation of Purchase Receipt / Stock Entry [#20392](https://github.com/frappe/erpnext/pull/20392)
- Show product bundle item's availability on website based on availability of all bundled items [#20384](https://github.com/frappe/erpnext/pull/20384)
- Show relevant suppliers on "Create Purchase Order" popup in Material Request [#20232](https://github.com/frappe/erpnext/pull/20232)
- Cannot complete task if dependent task are not completed / cancelled [#20434](https://github.com/frappe/erpnext/pull/20434)
- Show numeric values in item configurator [#20430](https://github.com/frappe/erpnext/pull/20430)
- Filter serial no based on batch no [#20566](https://github.com/frappe/erpnext/pull/20566)
- Pricing rule was not working on item groups [#20546](https://github.com/frappe/erpnext/pull/20546)
- Disabled quick entry for doctypes with tree view [#20453](https://github.com/frappe/erpnext/pull/20453)
### Optimisation
- Handling of large number of serial no creation via Purchase Receipt / Stock Entry (10 times faster than before!) [#20540](https://github.com/frappe/erpnext/pull/20540)
- Update outstanding amount on Sales Invoice on submission of invoice / payment [#20557](https://github.com/frappe/erpnext/pull/20557)

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