Compare commits

...

435 Commits

Author SHA1 Message Date
Saurabh
3e0f488083 Merge branch 'v12-pre-release' into version-12 2020-10-01 12:54:23 +05:30
Saurabh
db4178b1e8 bumped to version 12.12.1 2020-10-01 13:14:23 +05:50
Saurabh
080ef5a2bc fix: validate theme_scss attribute (#23466) 2020-09-30 18:11:37 +05:30
Marica
7c0056be9d Merge pull request #23461 from marination/cost-center-validation-pre-release
fix: Avoid validation of group cost center on repost
2020-09-30 12:58:13 +05:30
Marica
146575b176 Merge pull request #23459 from marination/update-items-perm-v12-pre-release
fix: Check only Read and Write Permission in Update Items
2020-09-30 12:55:48 +05:30
marination
374fa69c54 fix: Only validate group cost center if not from repost 2020-09-29 20:48:47 +05:30
marination
2949d1c355 fix: Check only Read and Write Permission in Update Items 2020-09-29 18:29:00 +05:30
Saurabh
24e5a6172a Merge branch 'v12-pre-release' into version-12 2020-09-25 11:47:15 +05:30
Saurabh
c7689d8796 bumped to version 12.12.0 2020-09-25 12:07:15 +05:50
Nabin Hait
5e7bfa37ef chore: Added change log for v12.12.0 (#23435) 2020-09-25 10:07:07 +05:30
Anurag Mishra
257927a18b fix:dash board for pre-release test (#23428) 2020-09-24 16:32:39 +05:30
Saqib
0847f257e6 chore: make asset movement transaction date match with purchase date & time (#23425) 2020-09-24 15:09:48 +05:30
Marica
e45aeab291 fix: Check Company in Payment Entry before selecting values (#23421) 2020-09-24 12:07:49 +05:30
rohitwaghchaure
d7bce62c60 Merge pull request #23414 from rohitwaghchaure/book-loss-amount-in-cogs-pre-release
refactor: book loss amount in the COGS instead of stock received but not billed
2020-09-23 20:32:27 +05:30
Rohit Waghchaure
4220f1e759 refactor: book loss amount in the COGS instead of stock received but not billed 2020-09-23 20:30:26 +05:30
rohitwaghchaure
76fdc9faaa Merge pull request #23391 from anupamvs/leave-application-status-fix
fix: leave application status fix
2020-09-23 19:06:17 +05:30
Anupam
960229793b fix: conflict resolved 2020-09-23 18:58:38 +05:30
Anupam
ecfc4b3fd4 fix: review changes 2020-09-23 18:53:40 +05:30
Prssanna Desai
2984f42e2b fix: ignore permission while creating supplier scorecard period in supplier scorecard (#23405) 2020-09-23 17:16:59 +05:30
Saqib
7d9dd8601a fix: failed workflow condition error message in update items (#23394) 2020-09-23 13:01:58 +05:30
rohitwaghchaure
4a154098cc Merge pull request #23404 from rohitwaghchaure/download-required-materials-not-working-pre
fix: Download Required Materials not working for production plan
2020-09-23 01:32:42 +05:30
Rohit Waghchaure
0d4fb93d71 fix: Download Required Materials not working for production plan 2020-09-23 01:31:03 +05:30
Anupam
d5a33f4604 fix: leave application status fix 2020-09-22 11:29:17 +05:30
rohitwaghchaure
14175a2f47 Merge pull request #23390 from rohitwaghchaure/fixed-subcontract-issue-for-bacthed-raw-material-pre
fix: incorrect consumed qty if raw material with batch
2020-09-22 10:51:46 +05:30
Rohit Waghchaure
be97f1fe7c fix: incorrect consumed qty if raw material with batch 2020-09-22 10:50:23 +05:30
rohitwaghchaure
8a776fdad4 Merge pull request #23378 from rohitwaghchaure/online-pos-print-not-working-pre
fix: online pos print not working
2020-09-22 10:30:53 +05:30
Rohit Waghchaure
3bebc58357 fix: online pos print not working 2020-09-21 18:32:08 +05:30
Saurabh
3599024c3e Merge pull request #23372 from abhishekbalam/version-12
fix(activation): Added New DocTypes in get_level()
2020-09-21 15:38:02 +05:30
Abhishek Balam
ad5721cbf4 fix: add doctypes to activation 2020-09-21 15:28:13 +05:30
rohitwaghchaure
2ea0263221 Merge pull request #23371 from rohitwaghchaure/enabled-no-copy-for-bill-date-pre
refactor: enabled no copy property for Supplier Invoice Date to avoid…
2020-09-21 14:25:19 +05:30
Rohit Waghchaure
70fc3de817 refactor: enabled no copy property for Supplier Invoice Date to avoid due date validation 2020-09-21 14:23:46 +05:30
rohitwaghchaure
06ecf99609 Merge pull request #23368 from rohitwaghchaure/fix-stock-reco-with-serial-nos-pre-release
fix: stock reconciliation, incorrect serial nos fetched in the current serial no field
2020-09-21 12:55:33 +05:30
Rohit Waghchaure
b07cfd2aec fix: stock reconciliation, incorrect serial nos fetched in the current serial no field 2020-09-21 12:50:47 +05:30
Nabin Hait
c9b5d78993 Merge branch 'version-12-hotfix' into v12-pre-release 2020-09-15 19:43:21 +05:30
rohitwaghchaure
783a4c7f48 fix: set_taxes() missing 1 required positional argument: 'company' (#23329) 2020-09-15 19:42:56 +05:30
Nabin Hait
5750f317c5 Merge branch 'version-12-hotfix' into v12-pre-release 2020-09-15 19:42:05 +05:30
rohitwaghchaure
bea5e5b1bc fix: consumed qty logic for subcontracted raw materials (#23314)
* fix: consumed qty logic for subcontracted raw materials

* added test case

* fix: sales order workflow test case
2020-09-15 19:40:37 +05:30
Saqib
812033b782 fix: purchase order updates are not tracked (#23325) 2020-09-15 11:21:16 +05:30
rohitwaghchaure
bb905ca4b0 fix: incorrect calculation for consumed qty for subcontract item (#23257)
* fix: incorrect calculation for consumed qty for subcontract item

* added test case
2020-09-14 21:12:16 +05:30
Rucha Mahabal
a951a59094 fix: get_transaction_entries function arguments in Bank Statement Transaction Entry (#23052) 2020-09-14 21:05:54 +05:30
rohitwaghchaure
444f657d25 fix: production plan incorrect work order qty (#23264)
* fix: production plan incorrect work order qty

* added test case

* Update test_production_plan.py
2020-09-14 20:51:20 +05:30
Saqib
1e981b50d5 Update items with workflow v12 (#23324)
* feat: validate workflow before so/po update items

* fix: incorrect workflow validation on so/po update items
2020-09-14 19:53:52 +05:30
rohitwaghchaure
279ccc56ee Merge pull request #23320 from marination/quality-inspection-fields-fix
fix: Make Reference fields mandatory in Quality Inspection
2020-09-14 14:11:35 +05:30
Marica
b67996ec42 Merge branch 'version-12-hotfix' into quality-inspection-fields-fix 2020-09-14 12:01:26 +05:30
Marica
fbee0804c3 Merge pull request #23321 from marination/pr-dn-get-items-fix
fix: Make sure Supplier/Customer is selected before fetching Items.
2020-09-14 11:37:25 +05:30
marination
a34a490e0c fix: Make sure Supplier/Customer is selected before fetching Items. 2020-09-14 11:11:39 +05:30
marination
815416adc5 fix: Make Reference fields mandatory in Quality Inspection 2020-09-14 11:07:26 +05:30
Saqib
d409f91469 fix: asset movement date for backdated asset entry (#23300) 2020-09-09 10:53:48 +05:30
rohitwaghchaure
dad5bbdaa2 Merge pull request #23131 from Anurag810/leave_application_form_dashboard_fixes
fix: Form dashboard showing wrong balance
2020-09-08 16:58:11 +05:30
Anurag Mishra
e5fbebf946 fix: update filters 2020-09-08 15:55:07 +05:30
Marica
245cd21c31 Merge pull request #23295 from AfshanKhan/reverse-je-ignore-flag-v12
fix: removed ignore permission flag
2020-09-08 14:52:19 +05:30
Marica
4d9b511bb4 Merge branch 'version-12-hotfix' into reverse-je-ignore-flag-v12 2020-09-08 13:52:54 +05:30
Afshan
f1471ecbd4 fix: removed ignore permission flag 2020-09-08 13:50:54 +05:30
Marica
00a8e2226a Merge pull request #23292 from AfshanKhan/irs-v12
fix: returned empty list if non US based company
2020-09-08 13:45:44 +05:30
Afshan
d44052441b fix: returned empty list if non US based company 2020-09-08 13:03:37 +05:30
rohitwaghchaure
8e21738238 Merge pull request #23192 from marination/batch-source-reference
fix: Unlink and delete batch created from stock reco on cancel
2020-09-08 12:12:30 +05:30
Rucha Mahabal
5096639591 fix: Lock row in subquery while setting delivered qty (#23101) 2020-09-08 11:58:07 +05:30
rohitwaghchaure
810c4250b8 Merge pull request #23286 from rohitwaghchaure/fixed-payment-entry-status-issue
fix: incorrect payment entry status
2020-09-08 10:35:52 +05:30
Deepesh Garg
47c535399c fix: Check if subscription is already created for current invoicing period (#23143)
* fix: Check if subscription is already created for current invoicing period

* fix: Test for duplicate subscription

* fix: invoice generation at the begining of period fix

* fix: invoice generation at the begining of period fix

* fix: Remove unwanted file

* fix: Generate new invoices even though current invoices are unpaid

* fix: Make invoices table read-only

* fix: Update test cases
2020-09-08 10:30:02 +05:30
rohitwaghchaure
b06c618585 Merge pull request #23247 from Anurag810/attendance_calendar_map_v12
fix: Attendance calendar map fix
2020-09-08 10:15:01 +05:30
Rohit Waghchaure
785b7b3359 fix: incorrect payment entry status 2020-09-07 21:54:57 +05:30
Marica
32179293ee Merge branch 'version-12-hotfix' into batch-source-reference 2020-09-07 19:30:36 +05:30
rohitwaghchaure
8dd72018c2 Merge pull request #23262 from rohitwaghchaure/not-able-to-make-material-request-from-so
fix: not able to make material request from SO
2020-09-06 20:49:03 +05:30
rohitwaghchaure
b2bf54cc33 Merge pull request #23260 from anupamvs/se-quantity-v12
fix: SE quantity data type issue
2020-09-04 16:07:32 +05:30
Rohit Waghchaure
4f3eb3fceb fix: not able to make material request from SO 2020-09-04 15:24:56 +05:30
Anupam K
9260cf11b6 fix: SE quantity data type issue 2020-09-04 15:10:50 +05:30
Deepesh Garg
84077676f7 Merge pull request #23254 from anupamvs/profit-loss-fix
fix: profit and loss report not working
2020-09-04 13:23:57 +05:30
Anupam K
5519824414 fix: profit and loss report not working 2020-09-04 11:09:26 +05:30
Deepesh Garg
cce13aaa65 Merge pull request #23252 from deepeshgarg007/hsn_wise_summary
fix: Stock qty in HSN wise outward summary
2020-09-03 21:29:58 +05:30
Deepesh Garg
b78d35ae1d fix: Stock qty in HSN wise outward summary 2020-09-03 21:16:31 +05:30
Marica
7c963a03cb Merge branch 'version-12-hotfix' into batch-source-reference 2020-09-03 18:01:09 +05:30
Marica
4a67da2b0b Merge pull request #23246 from marination/item-tax-query-fix
fix: Misleading filters on Item tax Template Link field
2020-09-03 17:51:42 +05:30
Anurag Mishra
053fdd91da fix: data was not properly maped 2020-09-03 17:11:59 +05:30
marination
c407bb2385 fix: Misleading filters on Item tax Template Link field 2020-09-03 16:54:43 +05:30
Marica
271c550e96 Merge pull request #23244 from marination/purchase-over-receipt-subcontracted-hotfix
fix: Raise Error on over receipt/consumption for sub-contracted PR
2020-09-03 16:45:13 +05:30
marination
8781e77132 fix: Test for Over Receipt via PRs on a PO 2020-09-03 15:48:18 +05:30
marination
5c1f11e561 fix: Raise Error on over receipt/consumption for sub-contrcated PR 2020-09-03 15:47:38 +05:30
Marica
203f78cf97 Merge branch 'version-12-hotfix' into batch-source-reference 2020-09-03 15:39:44 +05:30
rohitwaghchaure
e212537a5f Merge pull request #23186 from rohitwaghchaure/incorrect-stock-balance-issue-for-batched-item
fix: Incorrect stock balance issue for batched item
2020-09-03 15:02:38 +05:30
marination
e33b9628d3 Merge branch 'batch-source-reference' of https://github.com/marination/erpnext into batch-source-reference 2020-09-03 14:42:05 +05:30
marination
44717e3b4a fix: Item Alternative Test 2020-09-03 14:41:05 +05:30
Marica
1dbffa6ccc Merge branch 'version-12-hotfix' into batch-source-reference 2020-09-02 20:24:07 +05:30
marination
9b6326f5d4 chore: Tests for Stock Reconciliation 2020-09-02 19:21:16 +05:30
rohitwaghchaure
bd70dd02c1 Merge pull request #23236 from rohitwaghchaure/fix-pos-special-char-escape-issue
fix: pos item name special character issue
2020-09-02 17:20:43 +05:30
Rohit Waghchaure
f30181527f fix: pos item name special character issue 2020-09-02 17:08:28 +05:30
marination
6b785cf522 chore: Tests for Stock Entry 2020-09-02 15:45:02 +05:30
rohitwaghchaure
ba867d48f7 Merge pull request #23020 from prssanna/gross-profit-total-v12
feat: enable total row in Gross Profit Report
2020-09-02 12:17:33 +05:30
rohitwaghchaure
a0099a3c63 Merge pull request #23124 from ruchamahabal/fix-pos-return
fix: Update paid amount for pos return (#20543)
2020-09-02 12:16:25 +05:30
Marica
3992ddedd0 fix: General Ledger filter validation (#23230) 2020-09-02 11:10:46 +05:30
Shivam Mishra
457a909784 fix: events not deleted on cancelling maintenance schedule (#23219)
* feat: add participant to event_participant child table

* feat: add tests

* chore: update function name

Co-authored-by: Marica <maricadsouza221197@gmail.com>

Co-authored-by: Marica <maricadsouza221197@gmail.com>
2020-09-01 16:30:34 +05:30
Marica
96882f599e Merge pull request #23206 from marination/party-details-hotfix
fix: Check for Company before trying to fetch party details
2020-09-01 16:29:43 +05:30
Marica
c50b296f2d Merge branch 'version-12-hotfix' into party-details-hotfix 2020-09-01 15:36:26 +05:30
Marica
05a90baddd fix: Don't overwrite doctype while setting attributes in child row (#23228) 2020-09-01 15:29:27 +05:30
rohitwaghchaure
14ea8928f5 Merge pull request #23226 from rohitwaghchaure/fixed-job-card-time-log-issue
fix: incorrect job card timer issue
2020-09-01 14:08:29 +05:30
Rohit Waghchaure
ee4e725b37 fix: incorrect job card timer issue 2020-09-01 14:02:34 +05:30
Afshan
ab6f761753 fix:reverse journal entry (#23224) 2020-08-31 22:01:54 +05:30
Rucha Mahabal
b574353c00 fix(Payroll Entry): Set cost center for payroll payable account (#23223) 2020-08-31 20:09:48 +05:30
Deepesh Garg
3bf5820236 Merge pull request #23081 from deepeshgarg007/hsn_wise_json_v12_hotfix
feat: JSON download for HSN wise outward summary
2020-08-31 17:15:45 +05:30
Marica
0ff376fa4a fix: Better error feedback on creating SO from Quotation (#23214) 2020-08-31 13:54:10 +05:30
rohitwaghchaure
dc8de013c9 Merge pull request #23215 from rohitwaghchaure/fixed-different-workstation-not-update-qty
fix: incorrect completed qty against operation in work order if workstation is different in job card
2020-08-31 13:29:44 +05:30
Rohit Waghchaure
b73879056f fix: incorrect completed qty against operation in work order if workstation is different in job card 2020-08-31 12:27:49 +05:30
rohitwaghchaure
a2c4cc1252 Merge pull request #23126 from rohitwaghchaure/multi-operation-job-card-issue
fix: user created manual job card not linking job card operation with work order operation
2020-08-31 11:52:20 +05:30
marination
17a3af47d9 fix: Check for Company before trying to fetch party details 2020-08-29 19:28:51 +05:30
Rohit Waghchaure
e352706330 fix: user created manual job card not linking job card operations with work order operations 2020-08-28 12:29:27 +05:30
rohitwaghchaure
8dc7a43cc9 Merge pull request #23169 from ruchamahabal/fix-appointment-duration-v12
fix: don't overwrite patient appointment duration if already specified
2020-08-28 10:39:59 +05:30
rohitwaghchaure
aa795efe15 Merge pull request #23171 from anupamvs/product-contact-us
feat: Added phone field in product Inquiry
2020-08-28 10:38:07 +05:30
rohitwaghchaure
89d1990d79 Merge pull request #23179 from marination/pricing-rule-missing-fix-version-12-hotfix
fix: Pricing rule encoding missing line
2020-08-28 10:36:24 +05:30
rohitwaghchaure
c8f695c0da Merge pull request #23191 from ruchamahabal/fix-bom-update-v12
fix: BOM Update Tool failing due to Too Many Writes error
2020-08-28 10:35:47 +05:30
marination
eab2d25c6a fix: Unlink and delete batch created from stock reco on cancel 2020-08-27 20:34:51 +05:30
Rucha Mahabal
00dbbc9f5c fix: BOM Update Tool failing due to Too Many Writes error 2020-08-27 19:00:07 +05:30
Rohit Waghchaure
09cb0f33b2 added test cases 2020-08-27 14:57:37 +05:30
Rohit Waghchaure
dcd80a3f48 fix: incorrect stock balance issue 2020-08-27 13:24:33 +05:30
Saurabh
8bd9bf2be6 Merge branch 'v12-pre-release' into version-12 2020-08-27 10:04:32 +05:30
Saurabh
fc7121e38f bumped to version 12.11.2 2020-08-27 10:24:32 +05:50
rohitwaghchaure
03488f8285 Merge pull request #23177 from marination/pricing-rule-missing-fix-v12-pre-release
fix: Pricing Rule encoding missing line
2020-08-27 10:00:48 +05:30
marination
4cce4a7712 fix: get_applied_pricing_rule in taxes_and_totals 2020-08-26 20:18:37 +05:30
marination
4e3bbb8e74 fix: get_applied_pricing_rule in taxes_and_totals 2020-08-26 20:09:11 +05:30
Rucha Mahabal
a3907e1329 fix: don't overwrite appointment duration if already specified 2020-08-26 15:15:05 +05:30
Anupam K
759282651b feat: Added phone field in product Inquiry 2020-08-26 14:23:56 +05:30
rohitwaghchaure
3bae6328c5 Merge pull request #23153 from ruchamahabal/fix-conversion-factor-v12
fix: conversion factor for BOM exploded item rate
2020-08-26 13:02:48 +05:30
Deepesh Garg
45d615887a fix: Codacy fixes 2020-08-26 12:12:06 +05:30
Rucha Mahabal
ed6cbc1239 Merge pull request #23164 from frappe/michellealva-sales_invoice_dashboard
fix: Add Delivery Note link in Sales Invoice Dashboard
2020-08-25 21:09:50 +05:30
Michelle Alva
deb741bea5 fix:Add Delivery Note link in Sales Invoice Dashboard 2020-08-25 21:00:41 +05:30
Saurabh
271f8b5cfd Merge branch 'v12-pre-release' into version-12 2020-08-25 20:01:54 +05:30
Saurabh
f26e66b2b5 bumped to version 12.11.1 2020-08-25 20:21:54 +05:50
Saurabh
020534046c Merge pull request #23162 from rohitwaghchaure/pricing-rule-not-working-js-side-v12-pre-release
fix: mixed condition pricing rule not working on js side
2020-08-25 20:01:02 +05:30
Rohit Waghchaure
0407a435d7 fix: mixed condition pricing rule not working on js side 2020-08-25 19:59:17 +05:30
Saurabh
1c19050aa4 Merge pull request #23160 from rohitwaghchaure/pricing-rule-not-working-js-side
fix: mixed condition pricing rule not working on js side
2020-08-25 19:40:54 +05:30
Rohit Waghchaure
62876c708b fix: mixed condition pricing rule not working on js side 2020-08-25 18:32:46 +05:30
Rucha Mahabal
3fc00a5bfe fix: conversion factor for BOM exploded item rate 2020-08-25 18:09:14 +05:30
Saurabh
8245640ca2 Merge pull request #23149 from rohitwaghchaure/pricing-rule-encoding-pre-release-v12
fix(hot): Pricing Rule encoding fixed
2020-08-25 17:24:56 +05:30
Rohit Waghchaure
29d24cddcf fix(hot): Pricing Rule encoding fixed 2020-08-25 17:22:20 +05:30
Saurabh
9aa230c1b8 Merge pull request #23146 from rohitwaghchaure/pricing-rule-encoding-hotfix
fix(hot): Pricing Rule encoding fixed
2020-08-25 17:19:17 +05:30
Rohit Waghchaure
d223d4b829 fix(hot): Pricing Rule encoding fixed 2020-08-25 16:18:44 +05:30
Anurag Mishra
69bb85d1d0 fix: Form dashboard showing wrong balance 2020-08-25 06:55:02 +05:30
rohitwaghchaure
51c29cafee Merge pull request #23082 from ruchamahabal/fix-pos-print-v12
fix: Print Language for Customer not set for POS Invoice
2020-08-24 16:11:26 +05:30
rohitwaghchaure
6594d127cb Merge pull request #23113 from wojosc/patch-12
refactor: allow to rename lead
2020-08-24 16:09:14 +05:30
rohitwaghchaure
65d16d1ef6 Merge pull request #23117 from nabinhait/subcontracted-pr-gle-v12
fix: GLE for subcontracted PR is fg item rate is zero
2020-08-24 16:06:59 +05:30
Deepesh Garg
9b4cc0b6e9 fix: Update paid amount for pos return (#20543)
* fix: Paid amount updation for pos return

* fix: Remove console

* fix: Styling

* fix: get  default mode of payment from POS profile

* fix: Add test cases

* fix: Codacy
2020-08-24 15:01:57 +05:30
Saurabh
f843d6aa53 Merge branch 'v12-pre-release' into version-12 2020-08-24 10:11:45 +05:30
Saurabh
c6ed332903 bumped to version 12.11.0 2020-08-24 10:25:29 +05:50
Nabin Hait
ad07abeb3f chore: Added change log 2020-08-23 11:27:05 +05:30
Nabin Hait
a82d9d3182 test: Test case for GLE in subcontracted PR if FG item rate is zero 2020-08-22 20:07:19 +05:30
Nabin Hait
98fda4b8c3 fix: GLE for subcontracted PR is fg item rate is zero 2020-08-22 20:07:05 +05:30
Wolfram Schmidt
572d150925 Update lead_source.json
as requested in https://github.com/frappe/erpnext/pull/22872
2020-08-21 20:02:29 +02:00
Saqib
6c6175200c fix: cannot search items in offline pos (#23083) 2020-08-21 15:40:29 +05:30
rohitwaghchaure
6bb2038323 Merge pull request #23084 from nextchamp-saqib/pos-search-fix-pre-release
fix: cannot search items in offline pos
2020-08-21 13:13:50 +05:30
Nabin Hait
3d1df94ad2 fix:Validate Job offer against vacancies (#23108) 2020-08-20 19:39:03 +05:30
Nabin Hait
fa36a06188 fix:Validate Job offer against vacancies (#23107) 2020-08-20 19:38:55 +05:30
Deepesh Garg
c3c06c36a5 Merge pull request #23103 from deepeshgarg007/rcm_submit
fix: Unable to submit reverse charge invoice
2020-08-20 19:36:02 +05:30
Deepesh Garg
53aee98103 Merge pull request #23104 from deepeshgarg007/rcm_submit_v12
fix: Unable to submit reverse charge invoice
2020-08-20 19:35:48 +05:30
Marica
e52bd5c699 fix: Create Opoortunity without Default Company from Email (#23099)
* fix: Create Opoortunity without Default Company from Email

* fix: Add Prompt to Select Company

* Update communication.js

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2020-08-20 19:11:59 +05:30
Marica
685ca83b5e fix: Create Opoortunity without Default Company from Email (#23098)
* fix: Create Opoortunity without Default Company from Email

* fix: Add Prompt to Select Company

* Update communication.js

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2020-08-20 19:11:40 +05:30
Deepesh Garg
e1f9148351 Merge branch 'v12-pre-release' of https://github.com/frappe/erpnext into rcm_submit_v12 2020-08-20 16:49:43 +05:30
Deepesh Garg
093fb84377 fix: Unable to submit reverse charge invoice 2020-08-20 16:44:08 +05:30
Deepesh Garg
8c5bc5631a fix: Unable to submit reverse charge invoice 2020-08-20 16:31:38 +05:30
Rucha Mahabal
46456fdc19 Merge pull request #23095 from nextchamp-saqib/sr-no-selector-fix-hotfix
fix: val is not defined
2020-08-20 15:01:58 +05:30
Rucha Mahabal
737d305f45 Merge pull request #23094 from nextchamp-saqib/sr-no-selector-fix-pre-release
fix: val is not defined
2020-08-20 15:01:28 +05:30
Deepesh Garg
2aa23f91b1 Merge pull request #23092 from rohitwaghchaure/not-able-to-submit-dn-hotfix
fix: not able to submit delivery note
2020-08-20 13:35:40 +05:30
Saqib Ansari
2cc0ad51f5 fix: val is not defined 2020-08-20 12:54:36 +05:30
Saqib Ansari
193222a336 fix: val is not defined 2020-08-20 12:53:43 +05:30
rohitwaghchaure
46bea91469 Merge pull request #23093 from rohitwaghchaure/not-able-to-submit-dn
fix: not able to submit delivery note
2020-08-20 12:28:35 +05:30
Rohit Waghchaure
5e32ee8457 fix: not able to submit delivery note 2020-08-20 12:21:09 +05:30
Rohit Waghchaure
f09d472fcd fix: not able to submit delivery note 2020-08-20 12:20:23 +05:30
Suraj Shetty
4ff1a4361d refactor: Format and sanitise user inputs to search queries. (#23091)
* refactor: Sanitize whitelisted method inputs

Co-authored-by: Prssanna Desai <prssud@gmail.com>
Co-authored-by: Shivam Mishra <scmmishra@users.noreply.github.com>

* refactor: Format and sanitize tax_account_query inputs

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
Co-authored-by: Prssanna Desai <prssud@gmail.com>
Co-authored-by: Shivam Mishra <scmmishra@users.noreply.github.com>

* refactor: Validate and sanitize search inputs via decorator

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
Co-authored-by: Prssanna Desai <prssud@gmail.com>
Co-authored-by: Shivam Mishra <scmmishra@users.noreply.github.com>

* style: Minor formatting fix

* refactor: Validate and sanitize search inputs using decorator

* fix: Typo

* fix: Remove unwanted import statement

* refactor: Repalce validate_and_sanitize_search_inputs() with validate_and_sanitize_search_inputs

Co-authored-by: Prssanna Desai <prssud@gmail.com>
Co-authored-by: Shivam Mishra <scmmishra@users.noreply.github.com>

Co-authored-by: Prssanna Desai <prssud@gmail.com>
Co-authored-by: Shivam Mishra <scmmishra@users.noreply.github.com>
Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2020-08-20 11:27:19 +05:30
Suraj Shetty
bf7adb8b38 refactor: Format and sanitise user inputs to search queries. (#23064)
* refactor: Sanitize whitelisted method inputs

Co-authored-by: Prssanna Desai <prssud@gmail.com>
Co-authored-by: Shivam Mishra <scmmishra@users.noreply.github.com>

* refactor: Format and sanitize tax_account_query inputs

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
Co-authored-by: Prssanna Desai <prssud@gmail.com>
Co-authored-by: Shivam Mishra <scmmishra@users.noreply.github.com>

* refactor: Validate and sanitize search inputs via decorator

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
Co-authored-by: Prssanna Desai <prssud@gmail.com>
Co-authored-by: Shivam Mishra <scmmishra@users.noreply.github.com>

* style: Minor formatting fix

* refactor: Validate and sanitize search inputs using decorator

* fix: Typo

* fix: Remove unwanted import statement

* refactor: Repalce validate_and_sanitize_search_inputs() with validate_and_sanitize_search_inputs

Co-authored-by: Prssanna Desai <prssud@gmail.com>
Co-authored-by: Shivam Mishra <scmmishra@users.noreply.github.com>

Co-authored-by: Prssanna Desai <prssud@gmail.com>
Co-authored-by: Shivam Mishra <scmmishra@users.noreply.github.com>
Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2020-08-20 11:17:30 +05:30
Deepesh Garg
c7c72b76c6 Merge pull request #23087 from deepeshgarg007/rcm_deduction_hotfix
fix: Do not update total for RCM invvoices if net taxes are zero
2020-08-19 18:39:09 +05:30
Deepesh Garg
6aa3191cad fix: Do not update total for RCM invvoices if net taxes are zero 2020-08-19 18:36:43 +05:30
Deepesh Garg
848288ed36 Merge pull request #23086 from deepeshgarg007/rcm_deduction
fix: Do not update total for RCM invvoices if net taxes are zero
2020-08-19 18:34:27 +05:30
Deepesh Garg
1c29da32fc fix: Do not update total for RCM invvoices if net taxes are zero 2020-08-19 18:30:18 +05:30
Saqib Ansari
1fdfcc00d6 fix: cannot search items in offline pos 2020-08-19 17:26:38 +05:30
Rucha Mahabal
f61a8bc889 fix: Print Language for Customer not set for POS Invoice 2020-08-19 16:18:06 +05:30
Deepesh Garg
1bf9de1527 feat: JSON download for HSN wise outward summary 2020-08-19 15:46:15 +05:30
Deepesh Garg
dae1fad1a6 fix: Total calculations for multicurrency RCM invoices (#23070) 2020-08-18 19:32:38 +05:30
Deepesh Garg
af45eceeb2 fix: Total calculations for multicurrency RCM invoices (#23071) 2020-08-18 19:32:00 +05:30
Anupam Kumar
09b6628e53 fix: Leave application status (#23043)
* fix: leave application status update fix

* fix:adding patch
2020-08-18 14:43:34 +05:30
Deepesh Garg
693bf1309a Merge pull request #23021 from prssanna/expense-claim-list-currency-v12
fix: add company in list fields to fetch for Expense Claim
2020-08-17 23:08:27 +05:30
Afshan
df42df5246 fix: handled condition if staffing isn't created (#23057)
Co-authored-by: Marica <maricadsouza221197@gmail.com>
2020-08-17 13:48:07 +05:30
Afshan
4b6d5ef6aa fix: the JSON object must be str, bytes or bytearray, not "list" (#23053) 2020-08-17 12:25:34 +05:30
Rucha Mahabal
5e51a1fe9b Merge pull request #23037 from aakvatech/patch-5
fix: AttributeError: 'ProgramFee' object has no attribute 'course'
2020-08-14 13:21:45 +05:30
aakvatech
2cdc0c3f2d fix: AttributeError: 'ProgramFee' object has no attribute 'course'
Error occurs while program enrollment on new student.

This happens on version 12 and not on version 13.

Version 12 uses
course_list = [course.course for course in program.get_all_children()]

where as version 13 uses
course_list = [course.course for course in program.courses]

erpnext/erpnext/education/doctype/program_enrollment/program_enrollment.py
2020-08-14 10:26:54 +03:00
Rucha Mahabal
7234330db9 Merge pull request #23032 from frappe/revert-23031-patch-4
Revert "fix: AttributeError: 'ProgramFee' object has no attribute 'course'"
2020-08-14 11:21:49 +05:30
Rucha Mahabal
2fa9b3a713 Revert "fix: AttributeError: 'ProgramFee' object has no attribute 'course'" 2020-08-14 11:21:23 +05:30
Rucha Mahabal
1aec8f57f2 Merge pull request #23031 from aakvatech/patch-4
fix: AttributeError: 'ProgramFee' object has no attribute 'course'
2020-08-14 11:21:18 +05:30
aakvatech
24f350a1a8 fix: AttributeError: 'ProgramFee' object has no attribute 'course'
Error occurs while program enrollment on new student.

This happens on version 12 and not on version 13.

Version 12 uses
course_list = [course.course for course in program.get_all_children()]

where as version 13 uses
course_list = [course.course for course in program.courses]

erpnext/erpnext/education/doctype/program_enrollment/program_enrollment.py
2020-08-14 06:59:44 +03:00
prssanna
c28e37781a fix: add company in list fields to fetch for Expense Claim 2020-08-13 11:56:30 +05:30
prssanna
4d8340d7b9 feat: enable total row in Gross Profit Report 2020-08-13 11:40:56 +05:30
Nabin Hait
387e0878b6 Merge branch 'version-12-hotfix' into v12-pre-release 2020-08-13 09:28:27 +05:30
Saqib
6c536bb6e0 fix: cannot change customer fields if credit exhausted (#22838)
* fix: cannot change customer fields if credit exhausted

* fix: order based on company

* fix: sort current limits w.r.t company before compare

* fix: CustomerCreditLimit Object is not subscriptable
2020-08-13 09:27:50 +05:30
Nabin Hait
0a061d4082 Merge branch 'version-12-hotfix' into v12-pre-release 2020-08-13 09:23:22 +05:30
Nabin Hait
af9d653fb4 Inclusive tax based on item quantity v12 (#23015)
* fix: Calculate taxes if tax is based on item quantity and inclusive on item price

* git commit -m "fix: Add missing semicolon"

* fix: Calculate taxes if tax is based on item quantity

Co-authored-by: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com>
2020-08-13 09:22:05 +05:30
Anupam Kumar
8969e19594 fix: Opportunity/Quotation Lost Reason Fix (#23016) 2020-08-13 09:19:53 +05:30
Deepesh Garg
a979fcc25b fix: Project link not set in accounts other than profit and loss accounts (#22049)
* fix: project link not set in accounts other than profilt and loss accounts

* fix: cannot find get_allow_cost_center_in_entry_of_bs_account

* fix: remove enable_allow_cost_center_in_entry_of_bs_account

* chore: add tests and remove test based on allow_cost_center_for_bs_accounts

* fix: travis

* fix: Test Cases

* fix: Patch to remove Property Setter

* fix: Test Cases

* fix: Remove v13 patch

* fix: Procurement Tracker test case

* fix: Proccurement tracker report test

* fix: Codacy

* fix: Remove duplicate project field

Co-authored-by: Saqib Ansari <nextchamp.saqib@gmail.com>
Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2020-08-12 21:06:25 +05:30
Rucha Mahabal
9bd041c14c fix: don't set asset maintenance log status as Overdue when Completed or Cancelled (#23012)
* fix: don't set maintenance log status as Overdue when Completed or Cancelled

* fix: set draft indicators for Asset Maintenance Log listview
2020-08-12 19:34:54 +05:30
Deepesh Garg
1bb6ef3356 fix: Update state code and union territory for Daman and Diu (#22989)
Co-authored-by: Rucha Mahabal <ruchamahabal2@gmail.com>
2020-08-12 19:34:23 +05:30
Deepesh Garg
5cc5bc246a fix: Cancellation of accounting transactions within closed accounting period (#22986) 2020-08-12 17:56:57 +05:30
Rucha Mahabal
2a0ed798aa fix: TypeError while setting transfer_qty in Stock Entry (#22931)
Co-authored-by: Marica <maricadsouza221197@gmail.com>
2020-08-12 14:32:23 +05:30
Marica
033d98cd68 Merge pull request #23002 from AfshanKhan/fix-duplicate-dropdown-PO-v12
fix: moved custom_make_buttons to PurchaseOrderController to avoid duplication of dropdown options
2020-08-11 20:57:11 +05:30
Afshan
ec3dc95e6e fix: moved custom_make_buttons to PurchaseOrderController to avoid duplication of dropdown options 2020-08-11 20:42:16 +05:30
Deepesh Garg
57d86a3bc1 Merge pull request #22973 from marination/opportunity-from-email-fix
fix: Creating opportunity from email
2020-08-10 16:12:00 +05:30
marination
265916543d fix: Creating opportunity from email 2020-08-10 14:42:30 +05:30
Deepesh Garg
f63182df5a Merge pull request #22968 from deepeshgarg007/gst_export_wopay_v12
fix: GSTR 1 report for exports without payment of Tax
2020-08-10 11:29:56 +05:30
Deepesh Garg
9d455cf4a6 fix: GSTR 1 report for exports without payment of Tax 2020-08-10 09:57:28 +05:30
Deepesh Garg
ff9c40fde6 Merge pull request #22730 from deepeshgarg007/gstr3b_cess_v12_hotfix
fix: Multiple GST fixes
2020-08-08 22:15:25 +05:30
Deepesh Garg
f0f20bb434 fix: RCM taxable value in GSTR3b report 2020-08-08 20:58:01 +05:30
Deepesh Garg
bbfd5a4cc8 fix: Test Cases 2020-08-08 19:46:09 +05:30
Deepesh Garg
3ae4a83504 fix: Add print for debug 2020-08-08 17:52:45 +05:30
Deepesh Garg
1da33f4129 fix: Test case 2020-08-07 22:51:33 +05:30
Deepesh Garg
b8eff8d141 fix: Test case 2020-08-07 22:02:14 +05:30
Deepesh Garg
67e07b69dd fix: More print statements for debugging 2020-08-07 15:59:03 +05:30
Deepesh Garg
7d262d1a08 Merge pull request #22928 from deepeshgarg007/paymemnt_reco_multi_v12
fix: Multi currency payment reconciliation
2020-08-07 15:36:37 +05:30
Deepesh Garg
5f8e8a3c29 fix: Add debug print statement 2020-08-07 10:05:22 +05:30
Deepesh Garg
2169bb7640 fix: Add print 2020-08-06 23:16:33 +05:30
Deepesh Garg
33754b9dc8 fix: add print for debug 2020-08-06 22:17:37 +05:30
Deepesh Garg
bb451360ba Merge branch 'version-12-hotfix' of https://github.com/frappe/erpnext into gstr3b_cess_v12_hotfix 2020-08-06 21:50:27 +05:30
Afshan
2cf4168009 fix: show or hide section or attributes depending on other attributes… (#22933)
* fix: show or hide section or attributes depending on other attributes for better UI

* fix:depends on: batch_no for retain sample

Co-authored-by: Marica <maricadsouza221197@gmail.com>
2020-08-06 19:04:35 +05:30
Shivam Mishra
80c016a1ad Merge pull request #22935 from scmmishra/fix-product-configurator
fix: handle product_info null in item_configure
2020-08-06 11:39:32 +00:00
Shivam Mishra
3619628e60 fix: handle product_info null 2020-08-06 17:08:14 +05:30
Marica
e2e9633ee1 Merge pull request #22927 from deepeshgarg007/price_rule_fix_v12
fix: Error due to comma in Pricing rule name
2020-08-06 16:57:18 +05:30
Shivam Mishra
abd111331e Merge pull request #22934 from scmmishra/fix-product-configurator
fix: unbound error in product configurator 61b9727
2020-08-06 11:22:39 +00:00
Shivam Mishra
61b9727fa2 fix: unbound error in product configurator 2020-08-06 16:47:43 +05:30
Marica
74643c804d Merge branch 'version-12-hotfix' into price_rule_fix_v12 2020-08-06 14:38:59 +05:30
Marica
e7162a86c6 Merge pull request #22930 from deepeshgarg007/payment_reco_cost_center_fix_v12
fix: Add default cost center in payment reconciliation JV
2020-08-06 14:31:52 +05:30
Deepesh Garg
b3cdd91d65 fix: Tests 2020-08-06 13:18:42 +05:30
Deepesh Garg
dd64cd1512 fix: Add default cost center in payment reconciliation JV 2020-08-06 11:46:25 +05:30
Deepesh Garg
024c78f522 fix: Hide currency link fields 2020-08-06 11:31:00 +05:30
Deepesh Garg
e6ec549c81 fix: Multi currency payment reconciliation 2020-08-06 11:30:46 +05:30
Deepesh Garg
579167d1de fix: Remove print statement 2020-08-06 11:27:27 +05:30
Deepesh Garg
10604664d4 fix: Error due to commma in Pricing rule name 2020-08-06 11:27:18 +05:30
Marica
97e96cec51 fix: get_regional_address_details missing positional arg 'company' (#22920) 2020-08-05 17:10:50 +05:30
Anurag Mishra
d2593f0af5 fix: set half day date None if half day is unchecked (#22905) 2020-08-04 19:29:56 +05:30
Rucha Mahabal
02fcf569e6 fix: SQL query in accounts receivable, payable reports (#22891) 2020-08-03 20:41:37 +05:30
Marica
9afebd311f fix: Reposition description in Warehouse (#22896) 2020-08-03 20:39:41 +05:30
Rucha Mahabal
4f6a25539a fix: TypeError while concatenating account number and name in COA (#22886) 2020-08-03 15:51:39 +05:30
Nabin Hait
ec46b8c73b fix: Bank Clearance of POS purchase invoice (#22884) 2020-08-03 15:39:29 +05:30
Marica
a9cfe0c95c fix: Misleading description in Warehouse (#22879) 2020-08-03 14:56:46 +05:30
Rucha Mahabal
3d2fa59e6d fix(Education): course wise assessment report labels (#22805)
* fix: add labels to chart datasets in course wise assessment

* fix: change label for final grade

Co-authored-by: Marica <maricadsouza221197@gmail.com>
2020-07-30 13:27:47 +05:30
Rucha Mahabal
b2eddedfb1 fix: change owner fieldtype to Link in Lead Owner Efficiency Report (#22840) 2020-07-29 17:19:11 +05:30
Marica
b7efef79dc fix: Exploded Item Rate (#22816) 2020-07-27 14:54:59 +05:30
bhavesh95863
ca6ec72ade fix: Add missing translation function for freeze message (#22812)
* fix[missing translation function]

missing translation function

* fix[missing translation function for message]

missing translation function for message

* fix[add missing translation function]

add missing translation function

* Update payroll_entry.js

Co-authored-by: Rucha Mahabal <ruchamahabal2@gmail.com>
2020-07-26 14:03:03 +05:30
Deepesh Garg
680f2600be Merge pull request #22303 from P-Froggy/fix-payment-entry-wrong-bank-account-fetch-v12
fix: Set Value of wrong Bank Account Field in Payment Entry
2020-07-24 19:04:51 +05:30
Mangesh-Khairnar
af9e44f059 fix(payment-request): do not set guest as administrator (#22803) 2020-07-24 18:18:49 +05:30
Deepesh Garg
dde92e0fdb Merge branch 'version-12-hotfix' of https://github.com/frappe/erpnext into gstr3b_cess_v12_hotfix 2020-07-24 14:09:02 +05:30
Deepesh Garg
d9aa115aaf fix: Remove print and add Cess account 2020-07-24 14:08:05 +05:30
rohitwaghchaure
6a48988c76 fix: incorrect stock value in return case (#22528)
Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2020-07-24 10:46:55 +05:30
Nabin Hait
e62da1455c fix: Other charges on income tax (#22798) 2020-07-24 09:20:41 +05:30
Anupam Kumar
45a3580c20 Unable to change link from new lead to existing customer (#22795) 2020-07-24 08:53:24 +05:30
Rucha Mahabal
9abb8e309e fix(Education): descriptions not copied while creating fees from fee structure (#22793) 2020-07-24 08:52:53 +05:30
Rucha Mahabal
c5b6ba7556 Merge pull request #22794 from Mangesh-Khairnar/maintainance-visit-fixes
fix(maintenance-visit): change fieldtype of status to select
2020-07-24 00:10:09 +05:30
Mangesh-Khairnar
cf902a1e2d fix(maintenance-visit): change fieldtype of status to select 2020-07-23 23:55:58 +05:30
Sun Howwrongbum
4e3df334db fix: [v12] incorrect available_qty being set (#22541)
* fix: incorrect available_qty being set

* style: descriptive variables
2020-07-23 20:06:15 +05:30
Deepesh Garg
9067adf141 fix: Add print for debug 2020-07-23 19:48:18 +05:30
Deepesh Garg
d18eb0e63e Merge pull request #22702 from pipech/v12-hotfix-transaction_pricing_rule
fix(pricing): transaction pricing rule
2020-07-23 19:19:55 +05:30
aakvatech
3adeab45ce Update transaction.js (#22788)
Added frappe.flags.hide_serial_batch_dialog = true that was missing in version-12
2020-07-23 12:14:36 +05:30
Marica
0fee76f409 fix: Dont merge items if both exist in stock reco (#22784)
* fix: incorrect stock after merging items

* fix: Readability fix

Co-authored-by: Rohit Waghchaure <rohitw1991@gmail.com>
2020-07-22 18:53:40 +05:30
Marica
74963e9711 fix: Serial No Rename does not affect Stock Ledger Entry (#22780) 2020-07-22 18:17:25 +05:30
Deepesh Garg
7d8887916e Merge pull request #22755 from deepeshgarg007/hsn_code_report_v12
fix: Tax amounts in HSN Wise Outward summary
2020-07-22 16:26:38 +05:30
Deepesh Garg
e077c0a270 fix: Randomly failing test (#22773)
* fix(travis): Item Tax tempate template test

* fix: Update tests

* fix: Test

* fix: Do not use random customers

* fix: Remove every bit of randomness from this test
2020-07-22 16:12:12 +05:30
Afshan
517108d10a fix: added set query for filters in MR (#22770)
Co-authored-by: Marica <maricadsouza221197@gmail.com>
2020-07-22 15:51:48 +05:30
Afshan
a7094641d4 style: moved parent warehouse to top section also added a section break for better look (#22772)
Co-authored-by: Marica <maricadsouza221197@gmail.com>
2020-07-22 15:45:37 +05:30
Deepesh Garg
ad94f7516b Merge pull request #22763 from DeeMysterio/fs-hotfix
fix(report): fix alignment in script report that extends financial_statements.js
2020-07-22 14:46:08 +05:30
Diksha Jadhav
1943d413a4 fix(report): fix alignment in script report that extends financial_statements.js 2020-07-21 17:59:12 +05:30
Deepesh Garg
82fbef4163 fix: Remove print statements 2020-07-21 14:54:21 +05:30
Deepesh Garg
83ad6df229 fix: Tax amounts in HSN Wise Outward summary 2020-07-21 14:25:51 +05:30
Deepesh Garg
b9ba63b0d8 fix: Test Case 2020-07-20 18:08:56 +05:30
Marica
bc248bfaed Merge pull request #22646 from rohitwaghchaure/incorrect-qty-after-transaction-stock-reco
fix: incorrect qty after transaction in stock ledger entry
2020-07-20 15:51:37 +05:30
Deepesh Garg
0b31d6f630 fix: Test Case 2020-07-20 13:34:46 +05:30
Marica
7e461ce860 Merge branch 'version-12-hotfix' into incorrect-qty-after-transaction-stock-reco 2020-07-20 11:34:29 +05:30
Deepesh Garg
6946796047 fix: Tests 2020-07-19 22:23:13 +05:30
Deepesh Garg
6d39066d86 fix: Multiple fixes in GST 2020-07-17 22:20:04 +05:30
Deepesh Garg
b6da70efec fix: Cess amount in GSTR 3B report 2020-07-17 22:19:34 +05:30
rohitwaghchaure
3068fe43c6 Merge branch 'version-12-hotfix' into v12-hotfix-transaction_pricing_rule 2020-07-17 14:46:45 +05:30
rohitwaghchaure
7709c640b5 Merge pull request #22720 from rohitwaghchaure/fixed-incorrect-currency-symbol-in-stock-balance-report
fix: currency symbol not showing as per company currency in stock bal…
2020-07-17 14:35:13 +05:30
rohitwaghchaure
8558e26648 Merge pull request #22716 from rohitwaghchaure/fixed-actual-qty-showing-as-zero
Fix: Stock Reconciliation Invalid Quantity for Batched Item
2020-07-17 12:07:45 +05:30
Rohit Waghchaure
34a91bd7e6 fix: currency symbol not showing as per company currency in stock balance 2020-07-17 11:24:40 +05:30
rohitwaghchaure
785462b513 Update stock_reconciliation.js 2020-07-17 10:55:05 +05:30
Rohit Waghchaure
0d5f8c5050 fix: for past dated stock reco, batched item showing the current available qty instead of quantity as per posting date 2020-07-17 08:57:31 +05:30
Deepesh Garg
13088173eb Merge pull request #22703 from deepeshgarg007/rcm_ountry_fix
fix: Update RCM only for indian countries
2020-07-15 23:58:16 +05:30
Deepesh Garg
c10dd29282 fix: Update RCM only for indian countries 2020-07-15 23:57:03 +05:30
Deepesh Garg
95da4157a9 Merge pull request #22699 from rohitwaghchaure/fixed-not-able-to-submit-si-hotfix
fix: not able to submit sales invoice
2020-07-15 21:50:45 +05:30
Poranut Chollavorn
1411d002f6 fix(pricing): transaction pricing rule
add tranasction type to transaction pricing rule selector
2020-07-15 14:55:20 +00:00
rohitwaghchaure
0f2601a6a6 Merge pull request #22649 from rohitwaghchaure/fixed-incorrect-balance-qty-in-stock-ledger
fix: incorrect balance qty in stock ledger report
2020-07-15 17:20:04 +05:30
Rohit Waghchaure
c785ff9874 fix: not able to submit sales invoice 2020-07-15 17:17:23 +05:30
rohitwaghchaure
ab9cbc1e2c Merge pull request #22690 from marination/pr-project-stock-ledger-fix
fix: Added Project Field in Purchase Receipt for Stock Ledger Tagging
2020-07-15 15:42:58 +05:30
rohitwaghchaure
237dc4250a Merge pull request #22667 from ruchamahabal/fix-healthcare-setup-v12
fix(Healthcare): set company in Healthcare Service Unit setup
2020-07-15 14:33:42 +05:30
marination
71fa045ba4 fix: Added Project Field in Purchase Receipt for Stock Ledger Tagging 2020-07-15 12:54:19 +05:30
rohitwaghchaure
5e5e82a9f6 Merge pull request #22684 from nabinhait/company-abbr-replace
fix: Replace company abbr
2020-07-15 12:31:19 +05:30
Deepesh Garg
898dafe748 fix: Period list fixes in financial statements (#22679) 2020-07-15 12:17:23 +05:30
Deepesh Garg
1f7e941d68 fix(GST): Do not add tax amount in grand total for reverse charge invoices (#22686)
* fix(GST): Do not add tax amount in grand total for reverse charge invoices

* fix: Code cleanup

* fix: Remove print statements
2020-07-14 22:05:45 +05:30
Nabin Hait
395f44c8b7 fix: Replace company abbr 2020-07-14 20:46:25 +05:30
Rucha Mahabal
ea1662c15b Merge pull request #22659 from bhavesh95863/patch-3
fix: Quotation list view blank if quotation_to field not set as a standard filter
2020-07-13 19:55:54 +05:30
bhavesh95863
fd8c856af2 fix:whitespace missing
Co-authored-by: Rucha Mahabal <ruchamahabal2@gmail.com>
2020-07-13 18:48:47 +05:30
Rucha Mahabal
672497ba63 Merge branch 'version-12-hotfix' into fix-healthcare-setup-v12 2020-07-13 16:39:05 +05:30
Rucha Mahabal
9c410d8a27 fix(Healthcare): set company in Healthcare Service Unit setup 2020-07-13 16:27:59 +05:30
Deepesh Garg
8317ff8bb2 Merge branch 'version-12-hotfix' into fixed-incorrect-balance-qty-in-stock-ledger 2020-07-12 17:21:25 +05:30
bhavesh95863
70eb94280e fix: Quotation list view blank if quotation_to field not set as a standard filter
fix: Quotation list view  blank if quotation_to field not set as a standard filter
2020-07-12 02:59:00 +05:30
Deepesh Garg
fef3a79bf5 Merge pull request #22656 from sagarvora/fix-ewaybill-json
fix: ewaybill json had json dump of json dump, and other related fixes
2020-07-11 21:41:44 +05:30
Sagar Vora
9bcf4eb5bc fix: ewaybill json had json dump of json dump, and other related fixes 2020-07-11 17:44:20 +05:30
Marica
1696a8982c fix: Pricing Rule breaks if no item_code (#22653) 2020-07-10 22:51:32 +05:30
Rohit Waghchaure
671fc7b919 fix: incorrect balance qty in stock ledger report 2020-07-10 18:11:04 +05:30
Rohit Waghchaure
335815a75d fix: incorrect qty after transaction in stock ledger entry 2020-07-10 14:23:12 +05:30
rohitwaghchaure
b856548d47 fix: incorrect delivered qty in Supplier-Wise Sales Analytics (#22642)
Co-authored-by: Marica <maricadsouza221197@gmail.com>
2020-07-10 13:19:57 +05:30
rohitwaghchaure
1c26bf5b07 fix: Due to decimal issue make purchase receipt button not showing from PO (#22643)
Co-authored-by: Marica <maricadsouza221197@gmail.com>
2020-07-10 13:17:22 +05:30
Anurag Mishra
b3041ea7cd fix: fix: not working without from_amount and percentage_deduction (#22399) 2020-07-10 13:09:21 +05:30
Marica
ea7625556c fix: General Message in previous doc validation for buying and selling (#22639) 2020-07-10 12:36:47 +05:30
Marica
8e887f39a2 fix: Skip Progress and Completed by fields on Task Duplication (#22640) 2020-07-10 12:31:08 +05:30
Marica
8f038aa832 fix: Error message in Product Bundle (#22638) 2020-07-10 12:13:14 +05:30
Rohan
fda2633e40 fix: fetch project-related info in Timesheet (#22422)
Co-authored-by: Marica <maricadsouza221197@gmail.com>
2020-07-09 11:38:20 +05:30
Rohan
817040b986 fix: setup status indicators for Job Offer and Job Applicant (#22444)
Co-authored-by: Marica <maricadsouza221197@gmail.com>
2020-07-08 15:59:44 +05:30
rohitwaghchaure
45624cae77 Merge pull request #22599 from frappe/shopping-cart-issue
refactor: shopping cart
2020-07-08 13:09:59 +05:30
Anupam K
8c48a6a865 upating shopping_cart.js 2020-07-08 12:22:45 +05:30
Deepesh Garg
adb7c16349 Merge pull request #22604 from frappe/mergify/bp/version-12-hotfix/pr-22601
fix: Payment reco error in multi-company setup (bp #22601)
2020-07-07 18:41:44 +05:30
Marica
aafd674c07 Merge pull request #22606 from Thunderbottom/whitelist-query-v12
fix: whitelist all query functions for search widget
2020-07-07 16:51:45 +05:30
Chinmay D. Pai
75c2e28788 fix: whitelist all query functions for search widget
Signed-off-by: Chinmay D. Pai <chinmaydpai@gmail.com>
2020-07-07 16:46:04 +05:30
Anupam K
321aba642d shopping cart issue fixes 2020-07-07 15:46:44 +05:30
Deepesh Garg
402b273d9b fix: Pass company
(cherry picked from commit ca351e3549)
2020-07-07 10:06:49 +00:00
Deepesh Garg
e0a9ae612e fix: Payment reco error in multicompany setup
(cherry picked from commit e2fdff5777)
2020-07-07 10:06:49 +00:00
bhavesh95863
b9e4df557b fix: Message field mandtory even after unchecking collect progress checkbox (#22594)
Message field mandtory even after unchecking collect progress checkbox
2020-07-06 18:29:37 +05:30
rohitwaghchaure
632bd3b310 Merge pull request #22587 from frappe/mergify/bp/version-12-hotfix/pr-22577
fix: Consider company fiscal year for getting balance (bp #22577)
2020-07-06 13:20:54 +05:30
Deepesh Garg
735d7f732d fix: Consider company fiscal for getting balalnce
(cherry picked from commit 96d40ec9da)
2020-07-06 07:09:00 +00:00
Deepesh Garg
455c1dda7a Merge pull request #22575 from deepeshgarg007/uae_item_tax_fix_v12
fix: Update item tax only if item code available
2020-07-03 21:33:35 +05:30
Deepesh Garg
1b18bf0388 fix: Update item tax only if item code available 2020-07-03 21:28:40 +05:30
Faris Ansari
336ca33a98 fix: Set label if domains is set (#22523) 2020-07-02 14:58:20 +05:30
Afshan
3c0f38fa02 fix: made "Subscription Section", "Auto Repeat" and Hub Publishing" collapsible by default (#22535) 2020-07-02 14:52:50 +05:30
Marica
0c12c7339c Merge pull request #22538 from frappe/mergify/bp/version-12-hotfix/pr-22496
fix: take parent cost center for child if no cost center at child (bp #22496)
2020-07-01 17:00:22 +05:30
Anurag Mishra
bf8a26c31e fix: take parent cost center for child if no cost center at child (#22496)
(cherry picked from commit ba5f571b0d)
2020-07-01 11:07:57 +00:00
Marica
fb36d01dd2 Merge pull request #22534 from frappe/mergify/bp/version-12-hotfix/pr-22512
feat: Autofill Supplier pop-up when only 1 Supplier in RFQ (bp #22512)
2020-07-01 12:09:46 +05:30
Afshan
c8d6e8f19d feat: Autofill Supplier pop-up when only 1 Supplier in RFQ
(cherry picked from commit 06f11aba0b)
2020-07-01 06:32:19 +00:00
mergify[bot]
4e17c40589 fix: Refactor dashboard links in leave policy (bp #22519) (#22529)
* fix: Refactor dashboard links in leave policy (#22519)

* fix: refactor dashboard links in leave policy

* fx: code fix

* fix: add labels to links

* fix: code change

(cherry picked from commit ec84afa86d)

* fix: remove extra lines

Co-authored-by: Michelle Alva <50285544+michellealva@users.noreply.github.com>
Co-authored-by: Rucha Mahabal <ruchamahabal2@gmail.com>
2020-06-30 18:12:47 +05:30
Marica
5d5cb0ac28 fix: Set Root as Parent if no parent in new tree view node (#22507) 2020-06-30 08:21:07 +05:30
mergify[bot]
a20957d355 fix: handle nonetype issue for packed items (#22493) (#22494)
(cherry picked from commit 73edba0e10)

Co-authored-by: Mangesh-Khairnar <mkhairnar10@gmail.com>
2020-06-29 17:36:43 +05:30
rohitwaghchaure
f8efa0508a Merge pull request #22490 from frappe/mergify/bp/version-12-hotfix/pr-22488
fix: letter head not found in opening invoice creation tool (bp #22488)
2020-06-28 21:22:04 +05:30
Rohit Waghchaure
6aa7c404f8 fix: letter head not found in opening invoice creation tool
(cherry picked from commit 04cf2e029f)
2020-06-28 14:36:56 +00:00
rohitwaghchaure
105a44e0d2 Merge pull request #22484 from frappe/mergify/bp/version-12-hotfix/pr-22450
fix: Disable Renaming in Serial No (bp #22450)
2020-06-28 16:29:45 +05:30
rohitwaghchaure
7919ced975 Merge pull request #22372 from rohitwaghchaure/fixed-completed-qty-not-updated-in-wo
fix: completed qty not updated in work order
2020-06-28 15:22:56 +05:30
rohitwaghchaure
848e7c2e0e Merge pull request #22485 from frappe/mergify/bp/version-12-hotfix/pr-22478
fix: apply filters in all transactions (bp #22478)
2020-06-28 15:17:59 +05:30
rohitwaghchaure
104b317929 fix: indentation
(cherry picked from commit d5736711ce)
2020-06-28 09:45:01 +00:00
michellealva
ad0aca2fc6 fix: apply filters in all transactions
(cherry picked from commit 08f842d12e)
2020-06-28 09:45:01 +00:00
marination
584a8f52a5 fix: Disable Renaming in Serial No
(cherry picked from commit f311f52f6e)
2020-06-28 05:48:56 +00:00
rohitwaghchaure
48e2baa903 Merge pull request #22475 from frappe/mergify/bp/version-12-hotfix/pr-22468
fix: enable show_configure_button when shopping cart is enabled (bp #22468)
2020-06-28 11:13:34 +05:30
rohitwaghchaure
43d539f321 Merge pull request #22460 from britlog/version-12-hotfix
fix: product_info
2020-06-28 11:05:55 +05:30
britlog
0e7ab9526c fix: product_info 2020-06-26 15:24:23 +02:00
rohitwaghchaure
8a542bc9df Update shopping_cart_settings.js
(cherry picked from commit 13e8c32172)
2020-06-26 11:54:16 +00:00
Anupam K
e73dec158b enable show_configure_button when shopping cart is enabled
(cherry picked from commit 27d27c924d)
2020-06-26 11:54:16 +00:00
Deepesh Garg
2155916001 Merge pull request #22457 from frappe/clarkejj-patch-2
fix: stock_ageing.py report convert string numeric to flt value
2020-06-26 17:03:56 +05:30
rohitwaghchaure
78383c3133 Merge pull request #22469 from marination/production-plan-ux-hotfix
fix: Handling Empty tables in Production Plan
2020-06-26 15:06:14 +05:30
marination
cfc47bc011 fix: Sales Order to MR test failing
- Items to Manufacture can come as doc.items from Sales Order
2020-06-26 14:06:04 +05:30
marination
6bd8c048b6 fix: Handling Empty tables in Production Plan 2020-06-26 12:53:05 +05:30
mergify[bot]
6089023df7 fix: grammatical fix on error message (#22464)
Before:

Fiscal Year: 2020 does not exists

After:

Fiscal Year 2020 Does Not Exist

(cherry picked from commit 978722621f)

Co-authored-by: Michelle Alva <50285544+michellealva@users.noreply.github.com>
2020-06-26 09:23:36 +05:30
John Clarke
3cb8173034 fix: stock_ageing.py report convert string numeric to flt value
This PR combines these two PRs below applied to develop, to be applied to version-12-hotfix

(The mergifyio process failed for some reason.)

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

https://github.com/frappe/erpnext/pull/22206
2020-06-25 07:30:10 -06:00
mergify[bot]
d9e7b480eb fix: cannot cancel assets with repair pending (#22440) (#22453)
* fix: cannot cancel assets with repair pending

* fix: message

* Update asset.py

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
(cherry picked from commit 40847aeac3)

Co-authored-by: Saqib <nextchamp.saqib@gmail.com>
2020-06-25 17:11:36 +05:30
Marica
7691937e59 Merge pull request #22437 from sunhoww/patch-2
fix: [v12] UnboundLocalError when setting product_info
2020-06-25 14:23:13 +05:30
Sun Howwrongbum
99a9f98688 fix: UnboundLocalError when setting product_info 2020-06-25 10:05:00 +05:30
Deepesh Garg
7b23cb27ce Merge pull request #22435 from frappe/mergify/bp/version-12-hotfix/pr-22434
fix: change error messages in RFQ (bp #22434)
2020-06-25 09:29:10 +05:30
Michelle Alva
c28adea2d0 fix: change error messages in RFQ
Before:
1. Row {0}: For supplier {0} Email Address is required to send email
2. Email sent to supplier
3. Request for Quotation is disabled to access from portal, for more check portal settings.
4. Supplier Quotation created.


After:
1. Row {0}: For Supplier {0} Email Address is Required to Send Email
2. Email sent to Supplier
3. The Access to Request for Quotation From Portal is Disabled. To Allow Access, Enable it in Portal Settings.
4. Supplier Quotation Created.

(cherry picked from commit da0385cd39)
2020-06-25 03:52:13 +00:00
Marica
57804e9d87 Merge pull request #22427 from frappe/mergify/bp/version-12-hotfix/pr-22410
fix: add error prompt for wrong date range (bp #22410)
2020-06-24 21:32:18 +05:30
Kenneth Sequeira
bf81b42219 fix: add error prompt for wrong date range
(cherry picked from commit f5b7bd9dcb)
2020-06-24 14:06:59 +00:00
gavin
1a3fd763ac Merge pull request #22409 from revant/release-action-on-v12
ci: github release action for v12
2020-06-23 21:33:56 +05:30
Revant Nandgaonkar
0a6b5bc83f ci: github release action for v12 2020-06-23 20:11:35 +05:30
Marica
fb18f78b77 fix: Update Packed Items via Update Items in SO (#22404)
Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2020-06-23 19:19:08 +05:30
mergify[bot]
835b1b4f0d fix: Insert Supplier Group via List View (#22403) (#22407)
(cherry picked from commit 7af7bb8311)

Co-authored-by: Marica <maricadsouza221197@gmail.com>
2020-06-23 19:18:18 +05:30
mergify[bot]
3c18669057 fix: staffing Plan validation (#22379) (#22396)
(cherry picked from commit 36560c8406)

Co-authored-by: Anurag Mishra <32095923+Anurag810@users.noreply.github.com>
2020-06-23 10:49:48 +05:30
mergify[bot]
57a0fa5e87 fix: resetting lost reason in opportunity and quotation (#22378) (#22381)
(cherry picked from commit 71da90034d)

Co-authored-by: Anupam Kumar <anupamvns0099@gmail.com>
2020-06-23 10:45:08 +05:30
rohitwaghchaure
578bdff141 fix: offline pos not working for special character item (#22391) 2020-06-23 10:34:52 +05:30
rohitwaghchaure
c20b962842 Merge pull request #22389 from kennethsequeira/purchase_inv_due_12
fix: status error in purchase invoice
2020-06-22 23:47:32 +05:30
Deepesh Garg
5c4b738833 Merge pull request #22387 from AfshanKhan/V12_ISS_20_21_02455
fix: Set default reference Id for "On Previous Row Amount" and "On Previous Row Total"
2020-06-22 23:09:44 +05:30
Kenneth Sequeira
8a1f2ed65a fix:status error in purchase invoice 2020-06-22 22:40:04 +05:30
Afshan
def13f14a3 style: formate according to Codacy/PR Quality Review 2020-06-22 21:58:27 +05:30
Afshan
7e04dcae0a style: formate according to Codacy/PR Quality Review 2020-06-22 21:58:04 +05:30
Afshan
21a75eb2ba fix: set row_id by default as previous row for On Previous Row Amount and On Previous Row Total 2020-06-22 21:57:34 +05:30
rohitwaghchaure
290dbf470a Merge pull request #22384 from rohitwaghchaure/fixed-subcontract-item-for-alternative-item
fix: alternative item not working for subcontract
2020-06-22 21:52:26 +05:30
Rohit Waghchaure
171699537c fix: alternative item not working for subcontract 2020-06-22 20:48:28 +05:30
Deepesh Garg
91346d5e9e Merge pull request #22340 from frappe/mergify/bp/version-12-hotfix/pr-22312
fix: Email digest html view fix (bp #22312)
2020-06-22 19:08:56 +05:30
Marica
06ca3b5112 Purchase receipt to invoice hotfix (#22146)
* fix: Handle rows with same item code from Purchase Receipt to Invoice.

* fix: Handle rows with same item code from Purchase Receipt to Invoice.

* fix: Added patch, fixed tests, fixed delivery note behaviour

* chore: Added comments amd fixed typo

* fix: Added patch to patches.txt

* fix: Patch fix and simplification, json timestamp updation.

* fix: Set Purchase Receipt and Delivery Note detail patch (#21607)

* fix: Set Purchase Receipt and Delievry Note detail patch

* fix: Reload purchase receipt item

* fix(set_purchase_receipt_delivery_note_detail): commit after every 100 sql updates (#22016)

Co-authored-by: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com>
Co-authored-by: sahil28297 <37302950+sahil28297@users.noreply.github.com>
Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2020-06-22 18:04:48 +05:30
Kenneth Sequeira
e220be5415 fix: Batch No label in Purchase Receipt (#22360) 2020-06-22 17:33:04 +05:30
mergify[bot]
413c2b229a fix: 'Last Purchase Rate' taking wrong on BOM (#20689) (#22370)
* fix: 'Last Purchase Rate' taking wrong on BOM. #20228

* fix: Added condition for None purchase order and purchase receipt (#20689)

* fix: fetch last purchase rate

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
(cherry picked from commit 2866617c82)

Co-authored-by: Lokesh Waingankar <59611773+lokesh-indictrans@users.noreply.github.com>
2020-06-22 17:26:42 +05:30
Anurag Mishra
1039079e37 fix: set cost center in child table (#22373) 2020-06-22 17:25:53 +05:30
rohitwaghchaure
60cb5ac419 Merge pull request #22330 from pipech/v12-hotfix-clear_pricing_rule_value
fix(pricing_rule): apply_on logic dont get cleanup
2020-06-22 14:47:29 +05:30
Rohit Waghchaure
ebbbc85fc0 added validation and clear fields for Apply Rule On Other 2020-06-22 13:44:11 +05:30
rohitwaghchaure
7f6d36cdc9 Merge pull request #22369 from frappe/mergify/bp/version-12-hotfix/pr-22241
fix: Minor fixes in cost center (bp #22241)
2020-06-22 13:00:19 +05:30
Marica
4a9de4dc07 Merge branch 'version-12-hotfix' into v12-hotfix-clear_pricing_rule_value 2020-06-22 12:48:55 +05:30
Marica
cb555ae825 Merge pull request #22368 from frappe/mergify/bp/version-12-hotfix/pr-21582
feat: Enabled translation on html files in LMS [Proposal] (bp #21582)
2020-06-22 12:45:18 +05:30
Rohit Waghchaure
e5ffe3fea4 fix: completed qty not updated in work order 2020-06-22 12:36:23 +05:30
Marica
7fcf958d08 Merge branch 'version-12-hotfix' into mergify/bp/version-12-hotfix/pr-21582 2020-06-22 12:07:39 +05:30
Deepesh Garg
cfe9ed0dfa fix: Test
(cherry picked from commit bef80b7981)
2020-06-22 05:54:53 +00:00
Deepesh Garg
f2fe8053dc fix: Validation for group cost center
(cherry picked from commit 0d880079b1)
2020-06-22 05:54:53 +00:00
Deepesh Garg
aa22cca67a fix: Minor fixes in cost center
(cherry picked from commit 817cbc4b48)
2020-06-22 05:54:52 +00:00
rohitwaghchaure
c4893df048 Merge pull request #22088 from deepeshgarg007/rcm_version-12-hotfix
fix(India): Reverse charge mechanism for GST
2020-06-22 11:20:38 +05:30
Alvaro
b16b24fd10 feat: Enabled translation on html files in LMS [Proposal] (#21582)
* :fix:  translation fix for html files in LMS

* fix: typo in translation

* Update content.html

* Update content.html

* Update profile.html

Co-authored-by: Shivam Mishra <scmmishra@users.noreply.github.com>
Co-authored-by: Marica <maricadsouza221197@gmail.com>
(cherry picked from commit 43be163b32)
2020-06-22 05:39:42 +00:00
Deepesh Garg
2f2385b354 Merge pull request #22365 from frappe/mergify/bp/version-12-hotfix/pr-22350
fix: Skipping total row for tree-view reports (bp #22350)
2020-06-21 22:11:32 +05:30
Afshan
8a2a32820a fix: adding json for checked add total row
(cherry picked from commit 84c6973742)
2020-06-21 13:59:25 +00:00
Afshan
41462f3c36 fix: test case
(cherry picked from commit 3fbe6e9e4b)
2020-06-21 13:59:25 +00:00
Afshan
a9ff40db67 fix: Skipping*
(cherry picked from commit 65f00cea15)
2020-06-21 13:59:24 +00:00
Afshan
0d95f56474 Skiping total row for tree-view reports
(cherry picked from commit fbd66574ad)
2020-06-21 13:59:24 +00:00
rohitwaghchaure
da65ddc68a Merge pull request #22362 from rohitwaghchaure/fixed-popup-is-coming-for-non-serialized-items
fix: Serial no / batch no Popup is coming for the non serialized items
2020-06-20 20:54:55 +05:30
Rohit Waghchaure
368f5e29d2 fix: Serial no / batch no Popup is coming for the non serialized items 2020-06-20 20:48:28 +05:30
Deepesh Garg
92f97b6a68 Merge pull request #22347 from frappe/revert-21743-payment-remark-fix-v12
Revert "fix: update remark on submitting payment entry"
2020-06-19 17:29:20 +05:30
Deepesh Garg
7d035fac36 Revert "fix: update remark on submitting payment entry" 2020-06-19 17:28:58 +05:30
Marica
6c1a5e8a44 Merge branch 'version-12-hotfix' into v12-hotfix-clear_pricing_rule_value 2020-06-19 14:28:06 +05:30
rohitwaghchaure
995bdd3c48 Merge pull request #22250 from marination/rfq-multi-uom-hotfix
feat: Multi UOM support in Request for Quotation
2020-06-19 13:17:36 +05:30
mergify[bot]
5acc06dfe6 fix: Student Admission (#22280)
* Student Admission fix

* adding check for application

* adding check for application

* updating error message

* added date_diff for date comparision

(cherry picked from commit c6592c880a)

Co-authored-by: Anupam Kumar <anupamvns0099@gmail.com>
Co-authored-by: Anurag Mishra <32095923+Anurag810@users.noreply.github.com>
2020-06-19 11:58:51 +05:30
Anupam K
168d070d73 email digest html fix
(cherry picked from commit bd449c8d07)
2020-06-19 06:09:49 +00:00
mergify[bot]
6f3e5e1891 refactor: show service instead of services (#22339)
(cherry picked from commit 25702a1c55)

Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
2020-06-19 11:10:42 +05:30
rohitwaghchaure
a3e92489c2 Merge pull request #22337 from frappe/mergify/bp/version-12-hotfix/pr-22334
fix: Customer Group label in Item-wise Sales History report (bp #22334)
2020-06-19 11:00:17 +05:30
rohitwaghchaure
dd8dcd29c3 Merge pull request #22332 from marination/item-edit-hotfix
fix: Unabled to create batched item
2020-06-19 10:57:25 +05:30
Kenneth Sequeira
10624f3fa6 fix: Customer Group label in Itemwise Sales report
(cherry picked from commit 766f978858)
2020-06-19 05:26:23 +00:00
Marica
a0aa16c68c Merge branch 'version-12-hotfix' into item-edit-hotfix 2020-06-18 22:02:32 +05:30
marination
67361bef73 fix: Unabled to create batched item 2020-06-18 21:47:36 +05:30
Poranut Chollavorn
acf399c4e0 fix(pricing_rule): apply_on logic dont get cleanup 2020-06-18 14:41:26 +00:00
Marica
cce1116b4e fix: Quality procedure fixes (#22287)
* fix: Quality Procedure Fixes

- Dont prompt error message if parent is the same in child
- filter child procedure field
- Disable New button in tree view
- Editable grid for Quality Procedure Proces table.

* chore: Remove unnecessary get_doc

* fix: Codacy

Co-authored-by: Anurag Mishra <32095923+Anurag810@users.noreply.github.com>
2020-06-18 19:15:49 +05:30
mergify[bot]
531ef15e30 refactor: handle exceptions when updating addresses (#22307) (#22315)
* refactor: handle exceptions when updating addresses

* refactor: fold common statements in a loop

(cherry picked from commit 34d2bfbb3e)

Co-authored-by: Shivam Mishra <scmmishra@users.noreply.github.com>
2020-06-18 17:04:36 +05:30
Deepesh Garg
6dc6da1ce2 Merge pull request #22324 from deepeshgarg007/item_tax_map_v12
fix: Do not copy Item Tax template from SO to PO
2020-06-18 17:02:56 +05:30
Deepesh Garg
f9dbcef5c9 fix: Do not copy Item Tax template from SO to PO 2020-06-18 17:01:32 +05:30
mergify[bot]
1ca4370033 fix: asset maintenance fixes (#21277) (#22294)
* fix: asset maintenance fixes

* fix: tests

(cherry picked from commit 9c494d3e72)

Co-authored-by: Saqib <nextchamp.saqib@gmail.com>
2020-06-18 15:39:13 +05:30
mergify[bot]
0c08324fab chore: add standard queries hooks to whitelist (#21939) (#22305)
standard queries are used within the search widget, and now require to
be whitelisted before they can be executed through the search widget.

Signed-off-by: Chinmay D. Pai <chinmaydpai@gmail.com>

Co-authored-by: sahil28297 <37302950+sahil28297@users.noreply.github.com>
(cherry picked from commit 96100e9507)

Co-authored-by: Chinmay Pai <chinmaydpai@gmail.com>
2020-06-18 15:29:46 +05:30
Marica
c6886e28f2 Merge branch 'version-12-hotfix' into rfq-multi-uom-hotfix 2020-06-18 14:42:27 +05:30
marination
b865d58b81 fix: Patch simplification
- Also, apply patch to all docs
2020-06-18 14:43:31 +05:30
Kenneth Sequeira
af6a0f3a9d fix(HR): typo in error message in Employee Balance Report (#22306)
* fix: typo in date error message

* fix: error message cleanup in Leave Balance report
2020-06-18 14:34:11 +05:30
rohitwaghchaure
f635a1739e Merge pull request #22308 from rohitwaghchaure/fixed-incorrect-variable-used
fix: incorrect variable used while adding new item in the submitted Sales Order
2020-06-18 14:00:51 +05:30
Rohit Waghchaure
c75236579f fix: incorrect variable used while adding items in the submitted sales order 2020-06-18 13:59:23 +05:30
mergify[bot]
5d042ad496 fix: update shopify api version (#22284) (#22299)
Co-authored-by: Saurabh <saurabh@erpnext.com>
(cherry picked from commit 53b601523b)

Co-authored-by: Mangesh-Khairnar <mkhairnar10@gmail.com>
2020-06-18 09:47:15 +05:30
mergify[bot]
59938a46eb fix: typo for language in Terms description (#22270) (#22272)
(cherry picked from commit c159556c24)

Co-authored-by: Kenneth Sequeira <33246109+kennethsequeira@users.noreply.github.com>
2020-06-18 09:46:03 +05:30
P-Froggy
1284b9b17d fix: Set Value of wrong Bank Account Field in Payment Entry
Company bank account was wrongly inserted into the field "Party Bank Account" in payment entry, instead of "Bank Account".
Adds filters for "Party Bank Account" based on selected Party (I forgot to create a PR for version-12 back in February, see commit #393a626).
Also changes the label of "Default Bank Account" to "Default Company Bank Account", like suggested in PR #20632

#### Please Note
This is kind of a revert of PR #19390. However, it seems like the function "get_party_bank_account" in Bank Account doctype changed how it worked since it is clearly pulling the default company bank account.
2020-06-18 02:11:15 +02:00
Marica
1345bc2f82 Merge pull request #22291 from marination/variant-error-msg-hotfix
fix: Typo in Item Variant error message
2020-06-17 19:23:42 +05:30
marination
e67195b0b9 fix: Typo 2020-06-17 19:06:56 +05:30
Deepesh Garg
e4eb353065 Merge branch 'version-12-hotfix' into rcm_version-12-hotfix 2020-06-17 15:33:45 +05:30
Marica
41dadba990 Merge pull request #22281 from marination/expense-account-message
fix: Message Formatting for missing Expense Account
2020-06-17 13:51:09 +05:30
marination
17ec1d6b28 fix: Message Formatting 2020-06-17 13:46:21 +05:30
rohitwaghchaure
fd3ff6be18 refactor: hide company currency fields in the routing (#22267) 2020-06-17 09:37:41 +05:30
rohitwaghchaure
03f688acd9 fix: pos, serial no popup comin two times (#22268) 2020-06-17 09:36:23 +05:30
rohitwaghchaure
fd5c577b40 Merge pull request #22248 from rohitwaghchaure/fixed-version-12-hotfix-travis
fix: v12 travis
2020-06-16 09:55:26 +05:30
Rohit Waghchaure
e4834d2a37 fix: travis 2020-06-15 22:24:56 +05:30
marination
1e76bdcc3c feat: Multi UOM support in Request for Quotation 2020-06-15 17:53:47 +05:30
Deepesh Garg
e4cd23746b fix: Consider Overseas category in RCM 2020-06-14 13:20:09 +05:30
Deepesh Garg
c417cf079c fix(India): Reverse charge mechanism for GST 2020-06-03 11:31:26 +05:30
285 changed files with 5479 additions and 4460 deletions

14
.github/workflows/docker-release.yml vendored Normal file
View File

@@ -0,0 +1,14 @@
name: Trigger Docker build on release
on:
release:
types: [released]
jobs:
curl:
runs-on: ubuntu-latest
container:
image: alpine:latest
steps:
- name: curl
run: |
apk add curl bash
curl -s -X POST -H "Content-Type: application/json" -H "Accept: application/json" -H "Travis-API-Version: 3" -H "Authorization: token ${{ secrets.TRAVIS_CI_TOKEN }}" -d '{"request":{"branch":"master"}}' https://api.travis-ci.com/repo/frappe%2Ffrappe_docker/requests

View File

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

View File

@@ -244,6 +244,8 @@ class Account(NestedSet):
super(Account, self).on_trash(True)
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_parent_account(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql("""select name from tabAccount
where is_group = 1 and docstatus != 2 and company = %s

View File

@@ -225,7 +225,7 @@ def build_tree_from_json(chart_template, chart_data=None):
account['parent_account'] = parent
account['expandable'] = True if identify_is_group(child) else False
account['value'] = (child.get('account_number') + ' - ' + account_name) \
account['value'] = (cstr(child.get('account_number')).strip() + ' - ' + account_name) \
if child.get('account_number') else account_name
accounts.append(account)
_import_accounts(child, account['value'])

View File

@@ -1,210 +1,210 @@
{
"creation": "2013-06-24 15:49:57",
"description": "Settings for Accounts",
"doctype": "DocType",
"document_type": "Other",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"auto_accounting_for_stock",
"acc_frozen_upto",
"frozen_accounts_modifier",
"determine_address_tax_category_from",
"over_billing_allowance",
"column_break_4",
"credit_controller",
"check_supplier_invoice_uniqueness",
"make_payment_via_journal_entry",
"unlink_payment_on_cancellation_of_invoice",
"unlink_advance_payment_on_cancelation_of_order",
"book_asset_depreciation_entry_automatically",
"allow_cost_center_in_entry_of_bs_account",
"add_taxes_from_item_tax_template",
"automatically_fetch_payment_terms",
"print_settings",
"show_inclusive_tax_in_print",
"column_break_12",
"show_payment_schedule_in_print",
"currency_exchange_section",
"allow_stale",
"stale_days",
"report_settings_sb",
"use_custom_cash_flow"
],
"fields": [
{
"default": "1",
"description": "If enabled, the system will post accounting entries for inventory automatically.",
"fieldname": "auto_accounting_for_stock",
"fieldtype": "Check",
"hidden": 1,
"in_list_view": 1,
"label": "Make Accounting Entry For Every Stock Movement"
},
{
"description": "Accounting entry frozen up to this date, nobody can do / modify entry except role specified below.",
"fieldname": "acc_frozen_upto",
"fieldtype": "Date",
"in_list_view": 1,
"label": "Accounts Frozen Upto"
},
{
"description": "Users with this role are allowed to set frozen accounts and create / modify accounting entries against frozen accounts",
"fieldname": "frozen_accounts_modifier",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Role Allowed to Set Frozen Accounts & Edit Frozen Entries",
"options": "Role"
},
{
"default": "Billing Address",
"description": "Address used to determine Tax Category in transactions.",
"fieldname": "determine_address_tax_category_from",
"fieldtype": "Select",
"label": "Determine Address Tax Category From",
"options": "Billing Address\nShipping Address"
},
{
"fieldname": "column_break_4",
"fieldtype": "Column Break"
},
{
"description": "Role that is allowed to submit transactions that exceed credit limits set.",
"fieldname": "credit_controller",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Credit Controller",
"options": "Role"
},
{
"fieldname": "check_supplier_invoice_uniqueness",
"fieldtype": "Check",
"label": "Check Supplier Invoice Number Uniqueness"
},
{
"fieldname": "make_payment_via_journal_entry",
"fieldtype": "Check",
"label": "Make Payment via Journal Entry"
},
{
"default": "1",
"fieldname": "unlink_payment_on_cancellation_of_invoice",
"fieldtype": "Check",
"label": "Unlink Payment on Cancellation of Invoice"
},
{
"default": "1",
"fieldname": "unlink_advance_payment_on_cancelation_of_order",
"fieldtype": "Check",
"label": "Unlink Advance Payment on Cancelation of Order"
},
{
"default": "1",
"fieldname": "book_asset_depreciation_entry_automatically",
"fieldtype": "Check",
"label": "Book Asset Depreciation Entry Automatically"
},
{
"fieldname": "allow_cost_center_in_entry_of_bs_account",
"fieldtype": "Check",
"label": "Allow Cost Center In Entry of Balance Sheet Account"
},
{
"default": "1",
"fieldname": "add_taxes_from_item_tax_template",
"fieldtype": "Check",
"label": "Automatically Add Taxes and Charges from Item Tax Template"
},
{
"fieldname": "print_settings",
"fieldtype": "Section Break",
"label": "Print Settings"
},
{
"fieldname": "show_inclusive_tax_in_print",
"fieldtype": "Check",
"label": "Show Inclusive Tax In Print"
},
{
"fieldname": "column_break_12",
"fieldtype": "Column Break"
},
{
"fieldname": "show_payment_schedule_in_print",
"fieldtype": "Check",
"label": "Show Payment Schedule in Print"
},
{
"fieldname": "currency_exchange_section",
"fieldtype": "Section Break",
"label": "Currency Exchange Settings"
},
{
"default": "1",
"fieldname": "allow_stale",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Allow Stale Exchange Rates"
},
{
"default": "1",
"depends_on": "eval:doc.allow_stale==0",
"fieldname": "stale_days",
"fieldtype": "Int",
"label": "Stale Days"
},
{
"fieldname": "report_settings_sb",
"fieldtype": "Section Break",
"label": "Report Settings"
},
{
"default": "0",
"description": "Only select if you have setup Cash Flow Mapper documents",
"fieldname": "use_custom_cash_flow",
"fieldtype": "Check",
"label": "Use Custom Cash Flow Format"
},
{
"fieldname": "automatically_fetch_payment_terms",
"fieldtype": "Check",
"label": "Automatically Fetch Payment Terms"
},
{
"description": "Percentage you are allowed to bill more against the amount ordered. For example: If the order value is $100 for an item and tolerance is set as 10% then you are allowed to bill for $110.",
"fieldname": "over_billing_allowance",
"fieldtype": "Currency",
"label": "Over Billing Allowance (%)"
}
],
"icon": "icon-cog",
"idx": 1,
"issingle": 1,
"modified": "2019-07-04 18:20:55.789946",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"email": 1,
"print": 1,
"read": 1,
"role": "Accounts Manager",
"share": 1,
"write": 1
},
{
"read": 1,
"role": "Sales User"
},
{
"read": 1,
"role": "Purchase User"
}
],
"quick_entry": 1,
"sort_order": "ASC",
"track_changes": 1
"creation": "2013-06-24 15:49:57",
"description": "Settings for Accounts",
"doctype": "DocType",
"document_type": "Other",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"auto_accounting_for_stock",
"acc_frozen_upto",
"frozen_accounts_modifier",
"determine_address_tax_category_from",
"over_billing_allowance",
"column_break_4",
"credit_controller",
"check_supplier_invoice_uniqueness",
"make_payment_via_journal_entry",
"unlink_payment_on_cancellation_of_invoice",
"unlink_advance_payment_on_cancelation_of_order",
"book_asset_depreciation_entry_automatically",
"add_taxes_from_item_tax_template",
"automatically_fetch_payment_terms",
"print_settings",
"show_inclusive_tax_in_print",
"column_break_12",
"show_payment_schedule_in_print",
"currency_exchange_section",
"allow_stale",
"stale_days",
"report_settings_sb",
"use_custom_cash_flow"
],
"fields": [
{
"default": "1",
"description": "If enabled, the system will post accounting entries for inventory automatically.",
"fieldname": "auto_accounting_for_stock",
"fieldtype": "Check",
"hidden": 1,
"in_list_view": 1,
"label": "Make Accounting Entry For Every Stock Movement"
},
{
"description": "Accounting entry frozen up to this date, nobody can do / modify entry except role specified below.",
"fieldname": "acc_frozen_upto",
"fieldtype": "Date",
"in_list_view": 1,
"label": "Accounts Frozen Upto"
},
{
"description": "Users with this role are allowed to set frozen accounts and create / modify accounting entries against frozen accounts",
"fieldname": "frozen_accounts_modifier",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Role Allowed to Set Frozen Accounts & Edit Frozen Entries",
"options": "Role"
},
{
"default": "Billing Address",
"description": "Address used to determine Tax Category in transactions.",
"fieldname": "determine_address_tax_category_from",
"fieldtype": "Select",
"label": "Determine Address Tax Category From",
"options": "Billing Address\nShipping Address"
},
{
"fieldname": "column_break_4",
"fieldtype": "Column Break"
},
{
"description": "Role that is allowed to submit transactions that exceed credit limits set.",
"fieldname": "credit_controller",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Credit Controller",
"options": "Role"
},
{
"default": "0",
"fieldname": "check_supplier_invoice_uniqueness",
"fieldtype": "Check",
"label": "Check Supplier Invoice Number Uniqueness"
},
{
"default": "0",
"fieldname": "make_payment_via_journal_entry",
"fieldtype": "Check",
"label": "Make Payment via Journal Entry"
},
{
"default": "1",
"fieldname": "unlink_payment_on_cancellation_of_invoice",
"fieldtype": "Check",
"label": "Unlink Payment on Cancellation of Invoice"
},
{
"default": "1",
"fieldname": "unlink_advance_payment_on_cancelation_of_order",
"fieldtype": "Check",
"label": "Unlink Advance Payment on Cancelation of Order"
},
{
"default": "1",
"fieldname": "book_asset_depreciation_entry_automatically",
"fieldtype": "Check",
"label": "Book Asset Depreciation Entry Automatically"
},
{
"default": "1",
"fieldname": "add_taxes_from_item_tax_template",
"fieldtype": "Check",
"label": "Automatically Add Taxes and Charges from Item Tax Template"
},
{
"fieldname": "print_settings",
"fieldtype": "Section Break",
"label": "Print Settings"
},
{
"default": "0",
"fieldname": "show_inclusive_tax_in_print",
"fieldtype": "Check",
"label": "Show Inclusive Tax In Print"
},
{
"fieldname": "column_break_12",
"fieldtype": "Column Break"
},
{
"default": "0",
"fieldname": "show_payment_schedule_in_print",
"fieldtype": "Check",
"label": "Show Payment Schedule in Print"
},
{
"fieldname": "currency_exchange_section",
"fieldtype": "Section Break",
"label": "Currency Exchange Settings"
},
{
"default": "1",
"fieldname": "allow_stale",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Allow Stale Exchange Rates"
},
{
"default": "1",
"depends_on": "eval:doc.allow_stale==0",
"fieldname": "stale_days",
"fieldtype": "Int",
"label": "Stale Days"
},
{
"fieldname": "report_settings_sb",
"fieldtype": "Section Break",
"label": "Report Settings"
},
{
"default": "0",
"description": "Only select if you have setup Cash Flow Mapper documents",
"fieldname": "use_custom_cash_flow",
"fieldtype": "Check",
"label": "Use Custom Cash Flow Format"
},
{
"default": "0",
"fieldname": "automatically_fetch_payment_terms",
"fieldtype": "Check",
"label": "Automatically Fetch Payment Terms"
},
{
"description": "Percentage you are allowed to bill more against the amount ordered. For example: If the order value is $100 for an item and tolerance is set as 10% then you are allowed to bill for $110.",
"fieldname": "over_billing_allowance",
"fieldtype": "Currency",
"label": "Over Billing Allowance (%)"
}
],
"icon": "icon-cog",
"idx": 1,
"issingle": 1,
"modified": "2020-03-11 13:09:26.235848",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"email": 1,
"print": 1,
"read": 1,
"role": "Accounts Manager",
"share": 1,
"write": 1
},
{
"read": 1,
"role": "Sales User"
},
{
"read": 1,
"role": "Purchase User"
}
],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "ASC",
"track_changes": 1
}

View File

@@ -20,7 +20,6 @@ class AccountsSettings(Document):
self.validate_stale_days()
self.enable_payment_schedule_in_print()
self.enable_fields_for_cost_center_settings()
def validate_stale_days(self):
if not self.allow_stale and cint(self.stale_days) <= 0:
@@ -33,8 +32,3 @@ class AccountsSettings(Document):
for doctype in ("Sales Order", "Sales Invoice", "Purchase Order", "Purchase Invoice"):
make_property_setter(doctype, "due_date", "print_hide", show_in_print, "Check")
make_property_setter(doctype, "payment_schedule", "print_hide", 0 if show_in_print else 1, "Check")
def enable_fields_for_cost_center_settings(self):
show_field = 0 if cint(self.allow_cost_center_in_entry_of_bs_account) else 1
for doctype in ("Sales Invoice", "Purchase Invoice", "Payment Entry"):
make_property_setter(doctype, "cost_center", "hidden", show_field, "Check")

View File

@@ -27,4 +27,4 @@ def get_vouchar_detials(column_list, doctype, docname):
for col in column_list:
sanitize_searchfield(col)
return frappe.db.sql(''' select {columns} from `tab{doctype}` where name=%s'''
.format(columns=", ".join(json.loads(column_list)), doctype=doctype), docname, as_dict=1)[0]
.format(columns=", ".join(column_list), doctype=doctype), docname, as_dict=1)[0]

View File

@@ -60,12 +60,13 @@ class BankReconciliation(Document):
""".format(condition=condition), {"account": self.account, "from":self.from_date,
"to": self.to_date, "bank_account": self.bank_account}, as_dict=1)
pos_entries = []
pos_sales_invoices, pos_purchase_invoices = [], []
if self.include_pos_transactions:
pos_entries = frappe.db.sql("""
pos_sales_invoices = frappe.db.sql("""
select
"Sales Invoice Payment" as payment_document, sip.name as payment_entry, sip.amount as debit,
si.posting_date, si.debit_to as against_account, sip.clearance_date,
si.posting_date, si.customer as against_account, sip.clearance_date,
account.account_currency, 0 as credit
from `tabSales Invoice Payment` sip, `tabSales Invoice` si, `tabAccount` account
where
@@ -75,7 +76,20 @@ class BankReconciliation(Document):
si.posting_date ASC, si.name DESC
""", {"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)),
pos_purchase_invoices = frappe.db.sql("""
select
"Purchase Invoice" as payment_document, pi.name as payment_entry, pi.paid_amount as credit,
pi.posting_date, pi.supplier as against_account, pi.clearance_date,
account.account_currency, 0 as debit
from `tabPurchase Invoice` pi, `tabAccount` account
where
pi.cash_bank_account=%(account)s and pi.docstatus=1 and account.name = pi.cash_bank_account
and pi.posting_date >= %(from)s and pi.posting_date <= %(to)s
order by
pi.posting_date ASC, pi.name DESC
""", {"account": self.account, "from": self.from_date, "to": self.to_date}, as_dict=1)
entries = sorted(list(payment_entries) + list(journal_entries + list(pos_sales_invoices) + list(pos_purchase_invoices)),
key=lambda k: k['posting_date'] or getdate(nowdate()))
self.set('payment_entries', [])

View File

@@ -55,7 +55,7 @@ class BankStatementTransactionEntry(Document):
def populate_payment_entries(self):
if self.bank_statement is None: return
filename = self.bank_statement.split("/")[-1]
file_url = self.bank_statement
if (len(self.new_transaction_items + self.reconciled_transaction_items) > 0):
frappe.throw(_("Transactions already retreived from the statement"))
@@ -65,7 +65,7 @@ class BankStatementTransactionEntry(Document):
if self.bank_settings:
mapped_items = frappe.get_doc("Bank Statement Settings", self.bank_settings).mapped_items
statement_headers = self.get_statement_headers()
transactions = get_transaction_entries(filename, statement_headers)
transactions = get_transaction_entries(file_url, statement_headers)
for entry in transactions:
date = entry[statement_headers["Date"]].strip()
#print("Processing entry DESC:{0}-W:{1}-D:{2}-DT:{3}".format(entry["Particulars"], entry["Withdrawals"], entry["Deposits"], entry["Date"]))
@@ -398,20 +398,21 @@ def get_transaction_info(headers, header_index, row):
transaction[header] = ""
return transaction
def get_transaction_entries(filename, headers):
def get_transaction_entries(file_url, headers):
header_index = {}
rows, transactions = [], []
if (filename.lower().endswith("xlsx")):
if (file_url.lower().endswith("xlsx")):
from frappe.utils.xlsxutils import read_xlsx_file_from_attached_file
rows = read_xlsx_file_from_attached_file(file_id=filename)
elif (filename.lower().endswith("csv")):
rows = read_xlsx_file_from_attached_file(file_url=file_url)
elif (file_url.lower().endswith("csv")):
from frappe.utils.csvutils import read_csv_content
_file = frappe.get_doc("File", {"file_name": filename})
_file = frappe.get_doc("File", {"file_url": file_url})
filepath = _file.get_full_path()
with open(filepath,'rb') as csvfile:
rows = read_csv_content(csvfile.read())
elif (filename.lower().endswith("xls")):
elif (file_url.lower().endswith("xls")):
filename = file_url.split("/")[-1]
rows = get_rows_from_xls_file(filename)
else:
frappe.throw(_("Only .csv and .xlsx files are supported currently"))

View File

@@ -60,8 +60,13 @@ frappe.ui.form.on('Cost Center', {
"label": "Cost Center Number",
"fieldname": "cost_center_number",
"fieldtype": "Data",
"reqd": 1,
"default": frm.doc.cost_center_number
},
{
"label": __("Merge with existing"),
"fieldname": "merge",
"fieldtype": "Check",
"default": 0
}
],
primary_action: function() {
@@ -76,8 +81,9 @@ frappe.ui.form.on('Cost Center', {
args: {
docname: frm.doc.name,
cost_center_name: data.cost_center_name,
cost_center_number: data.cost_center_number,
company: frm.doc.company
cost_center_number: cstr(data.cost_center_number),
company: frm.doc.company,
merge: data.merge
},
callback: function(r) {
frappe.dom.unfreeze();

View File

@@ -125,7 +125,7 @@
"idx": 1,
"is_tree": 1,
"links": [],
"modified": "2020-04-29 16:09:30.025214",
"modified": "2020-06-12 16:09:30.025214",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Cost Center",

View File

@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe, erpnext
from frappe import _
from frappe.utils import flt, fmt_money, getdate, formatdate
from frappe.utils import flt, fmt_money, getdate, formatdate, cint
from frappe.model.document import Document
from frappe.model.naming import set_name_from_naming_options
from frappe.model.meta import get_field_precision
@@ -75,12 +75,6 @@ class GLEntry(Document):
if not self.cost_center and self.voucher_type != 'Period Closing Voucher':
frappe.throw(_("{0} {1}: Cost Center is required for 'Profit and Loss' account {2}. Please set up a default Cost Center for the Company.")
.format(self.voucher_type, self.voucher_no, self.account))
else:
from erpnext.accounts.utils import get_allow_cost_center_in_entry_of_bs_account
if not get_allow_cost_center_in_entry_of_bs_account() and self.cost_center:
self.cost_center = None
if self.project:
self.project = None
def validate_dimensions_for_pl_and_bs(self):
@@ -137,10 +131,17 @@ class GLEntry(Document):
return self.cost_center_company[self.cost_center]
def _check_is_group():
return cint(frappe.get_cached_value('Cost Center', self.cost_center, 'is_group'))
if self.cost_center and _get_cost_center_company() != self.company:
frappe.throw(_("{0} {1}: Cost Center {2} does not belong to Company {3}")
.format(self.voucher_type, self.voucher_no, self.cost_center, self.company))
if not self.flags.from_repost and self.cost_center and _check_is_group():
frappe.throw(_("""{0} {1}: Cost Center {2} is a group cost center and group cost centers cannot
be used in transactions""").format(self.voucher_type, self.voucher_no, frappe.bold(self.cost_center)))
def validate_party(self):
validate_party_frozen_disabled(self.party_type, self.party)

View File

@@ -3,7 +3,7 @@
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe, json
import frappe, json, erpnext
from frappe import _
from frappe.utils import flt, getdate, nowdate, add_days
from erpnext.controllers.accounts_controller import AccountsController
@@ -134,16 +134,19 @@ class InvoiceDiscounting(AccountsController):
je.append("accounts", {
"account": self.bank_account,
"debit_in_account_currency": flt(self.total_amount) - flt(self.bank_charges),
"cost_center": erpnext.get_default_cost_center(self.company)
})
je.append("accounts", {
"account": self.bank_charges_account,
"debit_in_account_currency": flt(self.bank_charges)
"debit_in_account_currency": flt(self.bank_charges),
"cost_center": erpnext.get_default_cost_center(self.company)
})
je.append("accounts", {
"account": self.short_term_loan,
"credit_in_account_currency": flt(self.total_amount),
"cost_center": erpnext.get_default_cost_center(self.company),
"reference_type": "Invoice Discounting",
"reference_name": self.name
})
@@ -151,6 +154,7 @@ class InvoiceDiscounting(AccountsController):
je.append("accounts", {
"account": self.accounts_receivable_discounted,
"debit_in_account_currency": flt(d.outstanding_amount),
"cost_center": erpnext.get_default_cost_center(self.company),
"reference_type": "Invoice Discounting",
"reference_name": self.name,
"party_type": "Customer",
@@ -160,6 +164,7 @@ class InvoiceDiscounting(AccountsController):
je.append("accounts", {
"account": self.accounts_receivable_credit,
"credit_in_account_currency": flt(d.outstanding_amount),
"cost_center": erpnext.get_default_cost_center(self.company),
"reference_type": "Invoice Discounting",
"reference_name": self.name,
"party_type": "Customer",
@@ -177,13 +182,15 @@ class InvoiceDiscounting(AccountsController):
je.append("accounts", {
"account": self.short_term_loan,
"debit_in_account_currency": flt(self.total_amount),
"cost_center": erpnext.get_default_cost_center(self.company),
"reference_type": "Invoice Discounting",
"reference_name": self.name,
})
je.append("accounts", {
"account": self.bank_account,
"credit_in_account_currency": flt(self.total_amount)
"credit_in_account_currency": flt(self.total_amount),
"cost_center": erpnext.get_default_cost_center(self.company)
})
if getdate(self.loan_end_date) > getdate(nowdate()):
@@ -193,6 +200,7 @@ class InvoiceDiscounting(AccountsController):
je.append("accounts", {
"account": self.accounts_receivable_discounted,
"credit_in_account_currency": flt(outstanding_amount),
"cost_center": erpnext.get_default_cost_center(self.company),
"reference_type": "Invoice Discounting",
"reference_name": self.name,
"party_type": "Customer",
@@ -202,6 +210,7 @@ class InvoiceDiscounting(AccountsController):
je.append("accounts", {
"account": self.accounts_receivable_unpaid,
"debit_in_account_currency": flt(outstanding_amount),
"cost_center": erpnext.get_default_cost_center(self.company),
"reference_type": "Invoice Discounting",
"reference_name": self.name,
"party_type": "Customer",

View File

@@ -2,6 +2,7 @@
{
"doctype": "Item Tax Template",
"title": "_Test Account Excise Duty @ 10",
"company": "_Test Company",
"taxes": [
{
"doctype": "Item Tax Template Detail",
@@ -14,6 +15,7 @@
{
"doctype": "Item Tax Template",
"title": "_Test Account Excise Duty @ 12",
"company": "_Test Company",
"taxes": [
{
"doctype": "Item Tax Template Detail",
@@ -26,6 +28,7 @@
{
"doctype": "Item Tax Template",
"title": "_Test Account Excise Duty @ 15",
"company": "_Test Company",
"taxes": [
{
"doctype": "Item Tax Template Detail",
@@ -38,6 +41,7 @@
{
"doctype": "Item Tax Template",
"title": "_Test Account Excise Duty @ 20",
"company": "_Test Company",
"taxes": [
{
"doctype": "Item Tax Template Detail",
@@ -50,6 +54,7 @@
{
"doctype": "Item Tax Template",
"title": "_Test Item Tax Template 1",
"company": "_Test Company",
"taxes": [
{
"doctype": "Item Tax Template Detail",

View File

@@ -619,20 +619,12 @@ $.extend(erpnext.journal_entry, {
return { filters: filters };
},
reverse_journal_entry: function(frm) {
var me = frm.doc;
for(var i=0; i<me.accounts.length; i++) {
me.accounts[i].credit += me.accounts[i].debit;
me.accounts[i].debit = me.accounts[i].credit - me.accounts[i].debit;
me.accounts[i].credit -= me.accounts[i].debit;
me.accounts[i].credit_in_account_currency = me.accounts[i].credit;
me.accounts[i].debit_in_account_currency = me.accounts[i].debit;
me.accounts[i].reference_type = "Journal Entry";
me.accounts[i].reference_name = me.name
}
frm.copy_doc();
cur_frm.reload_doc();
}
reverse_journal_entry: function() {
frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.make_reverse_journal_entry",
frm: cur_frm
})
},
});
$.extend(erpnext.journal_entry, {

View File

@@ -836,13 +836,34 @@ def get_opening_accounts(company):
return [{"account": a, "balance": get_balance_on(a)} for a in accounts]
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_against_jv(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql("""select jv.name, jv.posting_date, jv.user_remark
from `tabJournal Entry` jv, `tabJournal Entry Account` jv_detail
where jv_detail.parent = jv.name and jv_detail.account = %s and ifnull(jv_detail.party, '') = %s
and (jv_detail.reference_type is null or jv_detail.reference_type = '')
and jv.docstatus = 1 and jv.`{0}` like %s order by jv.name desc limit %s, %s""".format(searchfield),
(filters.get("account"), cstr(filters.get("party")), "%{0}%".format(txt), start, page_len))
if not frappe.db.has_column('Journal Entry', searchfield):
return []
return frappe.db.sql("""
SELECT jv.name, jv.posting_date, jv.user_remark
FROM `tabJournal Entry` jv, `tabJournal Entry Account` jv_detail
WHERE jv_detail.parent = jv.name
AND jv_detail.account = %(account)s
AND IFNULL(jv_detail.party, '') = %(party)s
AND (
jv_detail.reference_type IS NULL
OR jv_detail.reference_type = ''
)
AND jv.docstatus = 1
AND jv.`{0}` LIKE %(txt)s
ORDER BY jv.name DESC
LIMIT %(offset)s, %(limit)s
""".format(searchfield), dict(
account=filters.get("account"),
party=cstr(filters.get("party")),
txt="%{0}%".format(txt),
offset=start,
limit=page_len
)
)
@frappe.whitelist()
@@ -996,3 +1017,34 @@ def make_inter_company_journal_entry(name, voucher_type, company):
journal_entry.posting_date = nowdate()
journal_entry.inter_company_journal_entry_reference = name
return journal_entry.as_dict()
@frappe.whitelist()
def make_reverse_journal_entry(source_name, target_doc=None):
from frappe.model.mapper import get_mapped_doc
def update_accounts(source, target, source_parent):
target.reference_type = "Journal Entry"
target.reference_name = source_parent.name
doclist = get_mapped_doc("Journal Entry", source_name, {
"Journal Entry": {
"doctype": "Journal Entry",
"validation": {
"docstatus": ["=", 1]
}
},
"Journal Entry Account": {
"doctype": "Journal Entry Account",
"field_map": {
"account_currency": "account_currency",
"exchange_rate": "exchange_rate",
"debit_in_account_currency": "credit_in_account_currency",
"debit": "credit",
"credit_in_account_currency": "debit_in_account_currency",
"credit": "debit",
},
"postprocess": update_accounts,
},
}, target_doc)
return doclist

View File

@@ -139,6 +139,49 @@ class TestJournalEntry(unittest.TestCase):
self.assertFalse(gle)
def test_reverse_journal_entry(self):
from erpnext.accounts.doctype.journal_entry.journal_entry import make_reverse_journal_entry
jv = make_journal_entry("_Test Bank USD - _TC",
"Sales - _TC", 100, exchange_rate=50, save=False)
jv.get("accounts")[1].credit_in_account_currency = 5000
jv.get("accounts")[1].exchange_rate = 1
jv.submit()
rjv = make_reverse_journal_entry(jv.name)
rjv.posting_date = nowdate()
rjv.submit()
gl_entries = frappe.db.sql("""select account, account_currency, debit, credit,
debit_in_account_currency, credit_in_account_currency
from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s
order by account asc""", rjv.name, as_dict=1)
self.assertTrue(gl_entries)
expected_values = {
"_Test Bank USD - _TC": {
"account_currency": "USD",
"debit": 0,
"debit_in_account_currency": 0,
"credit": 5000,
"credit_in_account_currency": 100,
},
"Sales - _TC": {
"account_currency": "INR",
"debit": 5000,
"debit_in_account_currency": 5000,
"credit": 0,
"credit_in_account_currency": 0,
}
}
for field in ("account_currency", "debit", "debit_in_account_currency", "credit", "credit_in_account_currency"):
for i, gle in enumerate(gl_entries):
self.assertEqual(expected_values[gle.account][field], gle[field])
def test_disallow_change_in_account_currency_for_a_party(self):
# create jv in USD
jv = make_journal_entry("_Test Bank USD - _TC",
@@ -204,11 +247,8 @@ class TestJournalEntry(unittest.TestCase):
self.assertEqual(jv.inter_company_journal_entry_reference, "")
self.assertEqual(jv1.inter_company_journal_entry_reference, "")
def test_jv_for_enable_allow_cost_center_in_entry_of_bs_account(self):
def test_jv_with_cost_centre(self):
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
accounts_settings.save()
cost_center = "_Test Cost Center for BS Account - _TC"
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
jv = make_journal_entry("_Test Cash - _TC", "_Test Bank - _TC", 100, cost_center = cost_center, save=False)
@@ -237,15 +277,45 @@ class TestJournalEntry(unittest.TestCase):
for gle in gl_entries:
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
def test_jv_with_project(self):
from erpnext.projects.doctype.project.test_project import make_project
project = make_project({
'project_name': 'Journal Entry Project',
'project_template_name': 'Test Project Template',
'start_date': '2020-01-01'
})
def test_jv_account_and_party_balance_for_enable_allow_cost_center_in_entry_of_bs_account(self):
jv = make_journal_entry("_Test Cash - _TC", "_Test Bank - _TC", 100, save=False)
for d in jv.accounts:
d.project = project.project_name
jv.voucher_type = "Bank Entry"
jv.multi_currency = 0
jv.cheque_no = "112233"
jv.cheque_date = nowdate()
jv.insert()
jv.submit()
expected_values = {
"_Test Cash - _TC": {
"project": project.project_name
},
"_Test Bank - _TC": {
"project": project.project_name
}
}
gl_entries = frappe.db.sql("""select account, project, debit, credit
from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s
order by account asc""", jv.name, as_dict=1)
self.assertTrue(gl_entries)
for gle in gl_entries:
self.assertEqual(expected_values[gle.account]["project"], gle.project)
def test_jv_account_and_party_balance_with_cost_centre(self):
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
from erpnext.accounts.utils import get_balance_on
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
accounts_settings.save()
cost_center = "_Test Cost Center for BS Account - _TC"
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
jv = make_journal_entry("_Test Cash - _TC", "_Test Bank - _TC", 100, cost_center = cost_center, save=False)
@@ -261,9 +331,6 @@ class TestJournalEntry(unittest.TestCase):
account_balance = get_balance_on(account="_Test Bank - _TC", cost_center=cost_center)
self.assertEqual(expected_account_balance, account_balance)
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
def make_journal_entry(account1, account2, amount, cost_center=None, posting_date=None, exchange_rate=1, save=True, submit=False, project=None):
if not cost_center:
cost_center = "_Test Cost Center - _TC"

View File

@@ -68,6 +68,9 @@ class OpeningInvoiceCreationTool(Document):
if not self.company:
frappe.throw(_("Please select the Company"))
company_details = frappe.get_cached_value('Company', self.company,
["default_currency", "default_letter_head"], as_dict=1) or {}
for row in self.invoices:
if not row.qty:
row.qty = 1.0
@@ -99,6 +102,12 @@ class OpeningInvoiceCreationTool(Document):
if not args:
continue
if company_details:
args.update({
"currency": company_details.get("default_currency"),
"letter_head": company_details.get("default_letter_head")
})
doc = frappe.get_doc(args).insert()
doc.submit()
names.append(doc.name)
@@ -172,8 +181,7 @@ class OpeningInvoiceCreationTool(Document):
"due_date": row.due_date,
"posting_date": row.posting_date,
frappe.scrub(party_type): row.party,
"doctype": "Sales Invoice" if self.invoice_type == "Sales" else "Purchase Invoice",
"currency": frappe.get_cached_value('Company', self.company, "default_currency")
"doctype": "Sales Invoice" if self.invoice_type == "Sales" else "Purchase Invoice"
})
accounting_dimension = get_accounting_dimensions()

View File

@@ -12,9 +12,10 @@ frappe.ui.form.on('Payment Entry', {
setup: function(frm) {
frm.set_query("paid_from", function() {
frm.events.validate_company(frm);
var account_types = in_list(["Pay", "Internal Transfer"], frm.doc.payment_type) ?
["Bank", "Cash"] : [frappe.boot.party_account_types[frm.doc.party_type]];
return {
filters: {
"account_type": ["in", account_types],
@@ -23,27 +24,34 @@ frappe.ui.form.on('Payment Entry', {
}
}
});
frm.set_query("party_type", function() {
frm.events.validate_company(frm);
return{
"filters": {
filters: {
"name": ["in", Object.keys(frappe.boot.party_account_types)],
}
}
});
frm.set_query("party_bank_account", function() {
return {
filters: {
"is_company_account":0
is_company_account: 0,
party_type: frm.doc.party_type,
party: frm.doc.party
}
}
});
frm.set_query("bank_account", function() {
return {
filters: {
"is_company_account":1
is_company_account: 1
}
}
});
frm.set_query("contact_person", function() {
if (frm.doc.party) {
return {
@@ -55,10 +63,12 @@ frappe.ui.form.on('Payment Entry', {
};
}
});
frm.set_query("paid_to", function() {
frm.events.validate_company(frm);
var account_types = in_list(["Receive", "Internal Transfer"], frm.doc.payment_type) ?
["Bank", "Cash"] : [frappe.boot.party_account_types[frm.doc.party_type]];
return {
filters: {
"account_type": ["in", account_types],
@@ -147,6 +157,12 @@ frappe.ui.form.on('Payment Entry', {
frm.events.show_general_ledger(frm);
},
validate_company: (frm) => {
if (!frm.doc.company){
frappe.throw({message:__("Please select a Company first."), title: __("Mandatory")});
}
},
company: function(frm) {
frm.events.hide_unhide_fields(frm);
frm.events.set_dynamic_labels(frm);
@@ -326,7 +342,7 @@ frappe.ui.form.on('Payment Entry', {
() => {
frm.set_party_account_based_on_party = false;
if (r.message.bank_account) {
frm.set_value("party_bank_account", r.message.bank_account);
frm.set_value("bank_account", r.message.bank_account);
}
}
]);

View File

@@ -6,7 +6,7 @@ from __future__ import unicode_literals
import frappe, erpnext, json
from frappe import _, scrub, ValidationError
from frappe.utils import flt, comma_or, nowdate, getdate
from erpnext.accounts.utils import get_outstanding_invoices, get_account_currency, get_balance_on, get_allow_cost_center_in_entry_of_bs_account
from erpnext.accounts.utils import get_outstanding_invoices, get_account_currency, get_balance_on
from erpnext.accounts.party import get_party_account
from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account
from erpnext.setup.utils import get_exchange_rate
@@ -84,7 +84,7 @@ class PaymentEntry(AccountsController):
self.delink_advance_entry_references()
self.update_payment_schedule(cancel=1)
self.set_payment_req_status()
self.set_status()
self.set_status(update=True)
def set_payment_req_status(self):
from erpnext.accounts.doctype.payment_request.payment_request import update_payment_req_status
@@ -279,7 +279,7 @@ class PaymentEntry(AccountsController):
outstanding_amount, is_return = frappe.get_cached_value(d.reference_doctype, d.reference_name, ["outstanding_amount", "is_return"])
if outstanding_amount <= 0 and not is_return:
no_oustanding_refs.setdefault(d.reference_doctype, []).append(d)
for k, v in no_oustanding_refs.items():
frappe.msgprint(_("{} - {} now have {} as they had no outstanding amount left before submitting the Payment Entry.<br><br>\
If this is undesirable please cancel the corresponding Payment Entry.")
@@ -340,7 +340,7 @@ class PaymentEntry(AccountsController):
frappe.db.sql(""" UPDATE `tabPayment Schedule` SET paid_amount = `paid_amount` + %s
WHERE parent = %s and payment_term = %s""", (amount, key[1], key[0]))
def set_status(self):
def set_status(self, update=False):
if self.docstatus == 2:
self.status = 'Cancelled'
elif self.docstatus == 1:
@@ -348,6 +348,9 @@ class PaymentEntry(AccountsController):
else:
self.status = 'Draft'
if update:
self.db_set('status', self.status)
def set_amounts(self):
self.set_amounts_in_company_currency()
self.set_total_allocated_amount()
@@ -657,7 +660,7 @@ def get_outstanding_reference_documents(args):
.format(frappe.db.escape(args["voucher_type"]), frappe.db.escape(args["voucher_no"]))
# Add cost center condition
if args.get("cost_center") and get_allow_cost_center_in_entry_of_bs_account():
if args.get("cost_center"):
condition += " and cost_center='%s'" % args.get("cost_center")
date_fields_dict = {

View File

@@ -462,11 +462,8 @@ class TestPaymentEntry(unittest.TestCase):
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"))
self.assertEqual(outstanding_amount, 0)
def test_payment_entry_against_sales_invoice_for_enable_allow_cost_center_in_entry_of_bs_account(self):
def test_payment_entry_against_sales_invoice_with_cost_centre(self):
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
accounts_settings.save()
cost_center = "_Test Cost Center for BS Account - _TC"
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
@@ -501,39 +498,8 @@ class TestPaymentEntry(unittest.TestCase):
for gle in gl_entries:
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
def test_payment_entry_against_sales_invoice_for_disable_allow_cost_center_in_entry_of_bs_account(self):
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
si = create_sales_invoice(debit_to="Debtors - _TC")
pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank - _TC")
pe.reference_no = "112211-2"
pe.reference_date = nowdate()
pe.paid_to = "_Test Bank - _TC"
pe.paid_amount = si.grand_total
pe.insert()
pe.submit()
gl_entries = frappe.db.sql("""select account, cost_center, account_currency, debit, credit,
debit_in_account_currency, credit_in_account_currency
from `tabGL Entry` where voucher_type='Payment Entry' and voucher_no=%s
order by account asc""", pe.name, as_dict=1)
self.assertTrue(gl_entries)
for gle in gl_entries:
self.assertEqual(gle.cost_center, None)
def test_payment_entry_against_purchase_invoice_for_enable_allow_cost_center_in_entry_of_bs_account(self):
def test_payment_entry_against_purchase_invoice_with_cost_center(self):
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
accounts_settings.save()
cost_center = "_Test Cost Center for BS Account - _TC"
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
@@ -568,40 +534,9 @@ class TestPaymentEntry(unittest.TestCase):
for gle in gl_entries:
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
def test_payment_entry_against_purchase_invoice_for_disable_allow_cost_center_in_entry_of_bs_account(self):
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
pi = make_purchase_invoice(credit_to="Creditors - _TC")
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
pe.reference_no = "112222-2"
pe.reference_date = nowdate()
pe.paid_from = "_Test Bank - _TC"
pe.paid_amount = pi.grand_total
pe.insert()
pe.submit()
gl_entries = frappe.db.sql("""select account, cost_center, account_currency, debit, credit,
debit_in_account_currency, credit_in_account_currency
from `tabGL Entry` where voucher_type='Payment Entry' and voucher_no=%s
order by account asc""", pe.name, as_dict=1)
self.assertTrue(gl_entries)
for gle in gl_entries:
self.assertEqual(gle.cost_center, None)
def test_payment_entry_account_and_party_balance_for_enable_allow_cost_center_in_entry_of_bs_account(self):
def test_payment_entry_account_and_party_balance_with_cost_center(self):
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
from erpnext.accounts.utils import get_balance_on
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
accounts_settings.save()
cost_center = "_Test Cost Center for BS Account - _TC"
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
@@ -632,9 +567,6 @@ class TestPaymentEntry(unittest.TestCase):
self.assertEqual(expected_party_balance, party_balance)
self.assertEqual(expected_party_account_balance, party_account_balance)
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
def create_payment_terms_template():
create_payment_term('Basic Amount Receivable')

View File

@@ -26,6 +26,8 @@ class PaymentOrder(Document):
for d in self.references:
frappe.db.set_value(self.payment_order_type, d.get(frappe.scrub(self.payment_order_type)), ref_field, status)
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_mop_query(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql(""" select mode_of_payment from `tabPayment Order Reference`
where parent = %(parent)s and mode_of_payment like %(txt)s
@@ -36,6 +38,8 @@ def get_mop_query(doctype, txt, searchfield, start, page_len, filters):
'txt': "%%%s%%" % txt
})
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_supplier_query(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql(""" select supplier from `tabPayment Order Reference`
where parent = %(parent)s and supplier like %(txt)s and
@@ -86,4 +90,4 @@ def make_journal_entry(doc, supplier, mode_of_payment=None):
je.flags.ignore_mandatory = True
je.save()
frappe.msgprint(_("{0} {1} created").format(je.doctype, je.name))
frappe.msgprint(_("{0} {1} created").format(je.doctype, je.name))

View File

@@ -73,6 +73,10 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
};
}
});
this.frm.set_value('party_type', '');
this.frm.set_value('party', '');
this.frm.set_value('receivable_payable_account', '');
},
refresh: function() {

View File

@@ -48,7 +48,8 @@ class PaymentReconciliation(Document):
select
"Journal Entry" as reference_type, t1.name as reference_name,
t1.posting_date, t1.remark as remarks, t2.name as reference_row,
{dr_or_cr} as amount, t2.is_advance
{dr_or_cr} as amount, t2.is_advance,
t2.account_currency as currency
from
`tabJournal Entry` t1, `tabJournal Entry Account` t2
where
@@ -88,7 +89,8 @@ class PaymentReconciliation(Document):
if self.party_type == 'Customer' else "Purchase Invoice")
return frappe.db.sql(""" SELECT `tab{doc}`.name as reference_name, %(voucher_type)s as reference_type,
(sum(`tabGL Entry`.{dr_or_cr}) - sum(`tabGL Entry`.{reconciled_dr_or_cr})) as amount
(sum(`tabGL Entry`.{dr_or_cr}) - sum(`tabGL Entry`.{reconciled_dr_or_cr})) as amount,
account_currency as currency
FROM `tab{doc}`, `tabGL Entry`
WHERE
(`tab{doc}`.name = `tabGL Entry`.against_voucher or `tab{doc}`.name = `tabGL Entry`.voucher_no)
@@ -101,10 +103,10 @@ class PaymentReconciliation(Document):
Having
amount > 0
""".format(
doc=voucher_type,
dr_or_cr=dr_or_cr,
reconciled_dr_or_cr=reconciled_dr_or_cr,
party_type_field=frappe.scrub(self.party_type)),
doc=voucher_type,
dr_or_cr=dr_or_cr,
reconciled_dr_or_cr=reconciled_dr_or_cr,
party_type_field=frappe.scrub(self.party_type)),
{
'party': self.party,
'party_type': self.party_type,
@@ -141,6 +143,7 @@ class PaymentReconciliation(Document):
ent.invoice_number = e.get('voucher_no')
ent.invoice_date = e.get('posting_date')
ent.amount = flt(e.get('invoice_amount'))
ent.currency = e.get('currency')
ent.outstanding_amount = e.get('outstanding_amount')
def reconcile(self, args):
@@ -170,7 +173,7 @@ class PaymentReconciliation(Document):
reconcile_against_document(lst)
if dr_or_cr_notes:
reconcile_dr_cr_note(dr_or_cr_notes)
reconcile_dr_cr_note(dr_or_cr_notes, self.company)
msgprint(_("Successfully Reconciled"))
self.get_unreconciled_entries()
@@ -261,7 +264,7 @@ class PaymentReconciliation(Document):
return cond
def reconcile_dr_cr_note(dr_cr_notes):
def reconcile_dr_cr_note(dr_cr_notes, company):
for d in dr_cr_notes:
voucher_type = ('Credit Note'
if d.voucher_type == 'Sales Invoice' else 'Debit Note')
@@ -269,10 +272,14 @@ def reconcile_dr_cr_note(dr_cr_notes):
reconcile_dr_or_cr = ('debit_in_account_currency'
if d.dr_or_cr == 'credit_in_account_currency' else 'credit_in_account_currency')
company_currency = erpnext.get_company_currency(company)
jv = frappe.get_doc({
"doctype": "Journal Entry",
"voucher_type": voucher_type,
"posting_date": today(),
"company": company,
"multi_currency": 1 if d.currency != company_currency else 0,
"accounts": [
{
'account': d.account,
@@ -280,7 +287,8 @@ def reconcile_dr_cr_note(dr_cr_notes):
'party_type': d.party_type,
d.dr_or_cr: abs(d.allocated_amount),
'reference_type': d.against_voucher_type,
'reference_name': d.against_voucher
'reference_name': d.against_voucher,
'cost_center': erpnext.get_default_cost_center(company)
},
{
'account': d.account,
@@ -289,7 +297,8 @@ def reconcile_dr_cr_note(dr_cr_notes):
reconcile_dr_or_cr: (abs(d.allocated_amount)
if abs(d.unadjusted_amount) > abs(d.allocated_amount) else abs(d.unadjusted_amount)),
'reference_type': d.voucher_type,
'reference_name': d.voucher_no
'reference_name': d.voucher_no,
'cost_center': erpnext.get_default_cost_center(company)
}
]
})

View File

@@ -1,183 +1,80 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2014-07-09 16:14:23.672922",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"actions": [],
"creation": "2014-07-09 16:14:23.672922",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"invoice_type",
"invoice_number",
"invoice_date",
"col_break1",
"amount",
"outstanding_amount",
"currency"
],
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "invoice_type",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Invoice Type",
"length": 0,
"no_copy": 0,
"options": "Sales Invoice\nPurchase Invoice\nJournal Entry",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "invoice_type",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Invoice Type",
"options": "Sales Invoice\nPurchase Invoice\nJournal Entry",
"read_only": 1
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "invoice_number",
"fieldtype": "Dynamic Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Invoice Number",
"length": 0,
"no_copy": 0,
"options": "invoice_type",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "invoice_number",
"fieldtype": "Dynamic Link",
"in_list_view": 1,
"label": "Invoice Number",
"options": "invoice_type",
"read_only": 1
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "invoice_date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Invoice Date",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "invoice_date",
"fieldtype": "Date",
"in_list_view": 1,
"label": "Invoice Date",
"read_only": 1
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "col_break1",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "col_break1",
"fieldtype": "Column Break"
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Amount",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "amount",
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Amount",
"options": "currency",
"read_only": 1
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "outstanding_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Outstanding Amount",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
"fieldname": "outstanding_amount",
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Outstanding Amount",
"options": "currency",
"read_only": 1
},
{
"fieldname": "currency",
"fieldtype": "Link",
"hidden": 1,
"label": "Currency",
"options": "Currency"
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2016-07-11 03:28:03.588476",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Reconciliation Invoice",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_seen": 0
],
"istable": 1,
"links": [],
"modified": "2020-07-19 18:12:27.964073",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Reconciliation Invoice",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@@ -1,7 +1,9 @@
{
"actions": [],
"creation": "2014-07-09 16:13:35.452759",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"reference_type",
"reference_name",
@@ -16,7 +18,8 @@
"difference_account",
"difference_amount",
"sec_break1",
"remark"
"remark",
"currency"
],
"fields": [
{
@@ -73,6 +76,7 @@
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Amount",
"options": "currency",
"read_only": 1
},
{
@@ -81,6 +85,7 @@
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Allocated amount",
"options": "currency",
"reqd": 1
},
{
@@ -106,16 +111,25 @@
"fieldname": "difference_amount",
"fieldtype": "Currency",
"label": "Difference Amount",
"options": "currency",
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "section_break_10",
"fieldtype": "Section Break"
},
{
"fieldname": "currency",
"fieldtype": "Link",
"hidden": 1,
"label": "Currency",
"options": "Currency"
}
],
"istable": 1,
"modified": "2019-06-24 00:08:11.150796",
"links": [],
"modified": "2020-07-19 18:12:41.682347",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Reconciliation Payment",

View File

@@ -140,9 +140,6 @@ class PaymentRequest(Document):
})
def set_as_paid(self):
if frappe.session.user == "Guest":
frappe.set_user("Administrator")
payment_entry = self.create_payment_entry()
self.make_invoice()
@@ -254,7 +251,7 @@ class PaymentRequest(Document):
if status in ["Authorized", "Completed"]:
redirect_to = None
self.run_method("set_as_paid")
self.set_as_paid()
# if shopping cart enabled and in session
if (shopping_cart_settings.enabled and hasattr(frappe.local, "session")

View File

@@ -115,6 +115,8 @@ def get_item_groups(pos_profile):
def get_series():
return frappe.get_meta("Sales Invoice").get_field("naming_series").options or ""
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def pos_profile_query(doctype, txt, searchfield, start, page_len, filters):
user = frappe.session['user']
company = filters.get('company') or frappe.defaults.get_user_default('company')

View File

@@ -29,27 +29,29 @@ class TestPOSProfile(unittest.TestCase):
frappe.db.sql("delete from `tabPOS Profile`")
def make_pos_profile():
def make_pos_profile(**args):
frappe.db.sql("delete from `tabPOS Profile`")
args = frappe._dict(args)
pos_profile = frappe.get_doc({
"company": "_Test Company",
"cost_center": "_Test Cost Center - _TC",
"currency": "INR",
"company": args.company or "_Test Company",
"cost_center": args.cost_center or "_Test Cost Center - _TC",
"currency": args.currency or "INR",
"doctype": "POS Profile",
"expense_account": "_Test Account Cost for Goods Sold - _TC",
"income_account": "Sales - _TC",
"name": "_Test POS Profile",
"expense_account": args.expense_account or "_Test Account Cost for Goods Sold - _TC",
"income_account": args.income_account or "Sales - _TC",
"name": args.name or "_Test POS Profile",
"naming_series": "_T-POS Profile-",
"selling_price_list": "_Test Price List",
"territory": "_Test Territory",
"selling_price_list": args.selling_price_list or "_Test Price List",
"territory": args.territory or "_Test Territory",
"customer_group": frappe.db.get_value('Customer Group', {'is_group': 0}, 'name'),
"warehouse": "_Test Warehouse - _TC",
"write_off_account": "_Test Write Off - _TC",
"write_off_cost_center": "_Test Write Off Cost Center - _TC"
"warehouse": args.warehouse or "_Test Warehouse - _TC",
"write_off_account": args.write_off_account or "_Test Write Off - _TC",
"write_off_cost_center": args.write_off_cost_center or "_Test Write Off Cost Center - _TC"
})
if not frappe.db.exists("POS Profile", "_Test POS Profile"):
if not frappe.db.exists("POS Profile", args.name or "_Test POS Profile"):
pos_profile.insert()
return pos_profile

View File

@@ -17,6 +17,8 @@ from six import string_types
apply_on_dict = {"Item Code": "items",
"Item Group": "item_groups", "Brand": "brands"}
other_fields = ["other_item_code", "other_item_group", "other_brand"]
class PricingRule(Document):
def validate(self):
self.validate_mandatory()
@@ -51,6 +53,13 @@ class PricingRule(Document):
if tocheck and not self.get(tocheck):
throw(_("{0} is required").format(self.meta.get_label(tocheck)), frappe.MandatoryError)
if self.apply_rule_on_other:
o_field = 'other_' + frappe.scrub(self.apply_rule_on_other)
if not self.get(o_field) and o_field in other_fields:
frappe.throw(_("For the 'Apply Rule On Other' condition the field {0} is mandatory")
.format(frappe.bold(self.apply_rule_on_other)))
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)
@@ -84,13 +93,27 @@ class PricingRule(Document):
for f in options:
if not f: continue
f = frappe.scrub(f)
if f!=fieldname:
self.set(f, None)
scrubbed_f = frappe.scrub(f)
if logic_field == 'apply_on':
apply_on_f = apply_on_dict.get(f, f)
else:
apply_on_f = scrubbed_f
if scrubbed_f != fieldname:
self.set(apply_on_f, None)
if self.mixed_conditions and self.get("same_item"):
self.same_item = 0
apply_rule_on_other = frappe.scrub(self.apply_rule_on_other or "")
cleanup_other_fields = (other_fields if not apply_rule_on_other
else [o_field for o_field in other_fields if o_field != 'other_' + apply_rule_on_other])
for other_field in cleanup_other_fields:
self.set(other_field, None)
def validate_rate_or_discount(self):
for field in ["Rate"]:
if flt(self.get(frappe.scrub(field))) < 0:
@@ -218,7 +241,7 @@ def get_pricing_rule_for_item(args, price_list_rate=0, doc=None, for_validate=Fa
update_args_for_pricing_rule(args)
pricing_rules = (get_applied_pricing_rules(args)
pricing_rules = (get_applied_pricing_rules(args.get('pricing_rules'))
if for_validate and args.get("pricing_rules") else get_pricing_rules(args, doc))
if pricing_rules:
@@ -248,7 +271,7 @@ 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:
if pricing_rule.price_or_product_discount == "Price":
apply_price_discount_rule(pricing_rule, item_details, args)
@@ -257,7 +280,7 @@ def get_pricing_rule_for_item(args, price_list_rate=0, doc=None, for_validate=Fa
item_details.has_pricing_rule = 1
item_details.pricing_rules = ','.join([d.pricing_rule for d in rules])
item_details.pricing_rules = frappe.as_json([d.pricing_rule for d in rules])
if not doc: return item_details
@@ -346,8 +369,10 @@ def set_discount_amount(rate, item_details):
item_details.rate = rate
def remove_pricing_rule_for_item(pricing_rules, item_details, item_code=None):
from erpnext.accounts.doctype.pricing_rule.utils import get_pricing_rule_items
for d in pricing_rules.split(','):
from erpnext.accounts.doctype.pricing_rule.utils import (get_applied_pricing_rules,
get_pricing_rule_items)
for d in get_applied_pricing_rules(pricing_rules):
if not d or not frappe.db.exists("Pricing Rule", d): continue
pricing_rule = frappe.get_cached_doc('Pricing Rule', d)
@@ -370,7 +395,8 @@ def remove_pricing_rule_for_item(pricing_rules, item_details, item_code=None):
items = get_pricing_rule_items(pricing_rule)
item_details.apply_on = (frappe.scrub(pricing_rule.apply_rule_on_other)
if pricing_rule.apply_rule_on_other else frappe.scrub(pricing_rule.get('apply_on')))
item_details.applied_on_items = ','.join(items)
item_details.applied_on_items = json.dumps(items)
item_details.price_or_product_discount = pricing_rule.price_or_product_discount
item_details.pricing_rules = ''
@@ -413,14 +439,15 @@ def make_pricing_rule(doctype, docname):
return doc
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_item_uoms(doctype, txt, searchfield, start, page_len, filters):
items = [filters.get('value')]
if filters.get('apply_on') != 'Item Code':
field = frappe.scrub(filters.get('apply_on'))
items = [d.name for d in frappe.db.get_all("Item", filters={field: filters.get('value')})]
items = frappe.db.sql_list("""select name
from `tabItem` where {0} = %s""".format(field), filters.get('value'))
return frappe.get_all('UOM Conversion Detail',
filters = {'parent': ('in', items), 'uom': ("like", "{0}%".format(txt))},
fields = ["distinct uom"], as_list=1)
return frappe.get_all('UOM Conversion Detail', filters={
'parent': ('in', items),
'uom': ("like", "{0}%".format(txt))
}, fields = ["distinct uom"], as_list=1)

View File

@@ -11,6 +11,7 @@ import json
from six import string_types
import frappe
from erpnext.accounts.doctype.pricing_rule.pricing_rule import set_transaction_type
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, get_default_income_account
@@ -322,7 +323,9 @@ def apply_internal_priority(pricing_rules, field_set, args):
filtered_rules = []
for field in field_set:
if args.get(field):
filtered_rules = filter(lambda x: x[field]==args[field], pricing_rules)
# filter function always returns a filter object even if empty
# list conversion is necessary to check for an empty result
filtered_rules = list(filter(lambda x: x.get(field)==args.get(field), pricing_rules))
if filtered_rules: break
return filtered_rules or pricing_rules
@@ -416,9 +419,28 @@ def apply_pricing_rule_on_transaction(doc):
values = {}
conditions = get_other_conditions(conditions, values, doc)
pricing_rules = frappe.db.sql(""" Select `tabPricing Rule`.* from `tabPricing Rule`
where {conditions} and `tabPricing Rule`.disable = 0
""".format(conditions = conditions), values, as_dict=1)
args = frappe._dict({
'doctype': doc.doctype,
'transaction_type': None,
})
set_transaction_type(args)
tran_type_condition = '{} = 1'.format(args.transaction_type)
sql = """
SELECT
`tabPricing Rule`.*
FROM
`tabPricing Rule`
WHERE
{conditions} and
{tran_type_condition} and
`tabPricing Rule`.disable = 0
""".format(
conditions=conditions,
tran_type_condition=tran_type_condition,
)
pricing_rules = frappe.db.sql(sql, values, as_dict=1)
if pricing_rules:
pricing_rules = filter_pricing_rules_for_qty_amount(doc.total_qty,
@@ -448,9 +470,14 @@ def apply_pricing_rule_on_transaction(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 get_applied_pricing_rules(pricing_rules):
if pricing_rules:
if pricing_rules.startswith('['):
return json.loads(pricing_rules)
else:
return pricing_rules.split(',')
return []
def get_product_discount_rule(pricing_rule, item_details, args=None, doc=None):
free_item = pricing_rule.free_item

View File

@@ -1,5 +1,4 @@
{
"actions": [],
"allow_import": 1,
"autoname": "naming_series:",
"creation": "2013-05-21 16:16:39",
@@ -26,6 +25,7 @@
"accounting_dimensions_section",
"cost_center",
"dimension_col_break",
"project",
"sb_14",
"on_hold",
"release_date",
@@ -356,6 +356,7 @@
"fieldname": "bill_date",
"fieldtype": "Date",
"label": "Supplier Invoice Date",
"no_copy": 1,
"oldfieldname": "bill_date",
"oldfieldtype": "Date",
"print_hide": 1
@@ -963,8 +964,10 @@
{
"fieldname": "clearance_date",
"fieldtype": "Date",
"hidden": 1,
"label": "Clearance Date"
"label": "Clearance Date",
"no_copy": 1,
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "col_br_payments",
@@ -1233,6 +1236,7 @@
"print_hide": 1
},
{
"collapsible": 1,
"fieldname": "subscription_section",
"fieldtype": "Section Break",
"label": "Subscription Section",
@@ -1286,6 +1290,12 @@
"fieldname": "dimension_col_break",
"fieldtype": "Column Break"
},
{
"fieldname": "project",
"fieldtype": "Link",
"label": "Project",
"options": "Project"
},
{
"fieldname": "tax_withholding_category",
"fieldtype": "Link",
@@ -1298,8 +1308,7 @@
"icon": "fa fa-file-text",
"idx": 204,
"is_submittable": 1,
"links": [],
"modified": "2020-04-18 13:05:25.199832",
"modified": "2020-09-21 12:22:09.164068",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",

View File

@@ -413,6 +413,8 @@ class PurchaseInvoice(BuyingController):
self.make_tax_gl_entries(gl_entries)
gl_entries = make_regional_gl_entries(gl_entries, self)
gl_entries = merge_similar_entries(gl_entries)
self.make_payment_gl_entries(gl_entries)
@@ -451,7 +453,8 @@ class PurchaseInvoice(BuyingController):
if self.party_account_currency==self.company_currency else grand_total,
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
"against_voucher_type": self.doctype,
"cost_center": self.cost_center
"cost_center": self.cost_center,
"project": self.project
}, self.party_account_currency, item=self)
)
@@ -492,7 +495,7 @@ class PurchaseInvoice(BuyingController):
"debit": warehouse_debit_amount,
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
"cost_center": item.cost_center,
"project": item.project
"project": item.project or self.project
}, account_currency, item=item)
)
@@ -505,7 +508,7 @@ class PurchaseInvoice(BuyingController):
"cost_center": item.cost_center,
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
"credit": flt(amount),
"project": item.project
"project": item.project or self.project
}, item=item))
# sub-contracting warehouse
@@ -518,6 +521,7 @@ class PurchaseInvoice(BuyingController):
"account": supplier_warehouse_account,
"against": item.expense_account,
"cost_center": item.cost_center,
"project": item.project or self.project,
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
"credit": flt(item.rm_supp_cost)
}, warehouse_account[self.supplier_warehouse]["account_currency"], item=item))
@@ -536,7 +540,7 @@ class PurchaseInvoice(BuyingController):
"against": self.supplier,
"debit": amount,
"cost_center": item.cost_center,
"project": item.project
"project": item.project or self.project
}, account_currency, item=item))
# If asset is bought through this document and not linked to PR
@@ -549,7 +553,7 @@ class PurchaseInvoice(BuyingController):
"cost_center": item.cost_center,
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
"credit": flt(item.landed_cost_voucher_amount),
"project": item.project
"project": item.project or self.project
}, item=item))
gl_entries.append(self.get_gl_dict({
@@ -558,7 +562,7 @@ class PurchaseInvoice(BuyingController):
"cost_center": item.cost_center,
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
"debit": flt(item.landed_cost_voucher_amount),
"project": item.project
"project": item.project or self.project
}, item=item))
# update gross amount of asset bought through this document
@@ -584,7 +588,8 @@ class PurchaseInvoice(BuyingController):
"against": self.supplier,
"debit": flt(item.item_tax_amount, item.precision("item_tax_amount")),
"remarks": self.remarks or "Accounting Entry for Stock",
"cost_center": self.cost_center
"cost_center": self.cost_center,
"project": item.project or self.project
}, item=item)
)
@@ -613,7 +618,8 @@ class PurchaseInvoice(BuyingController):
"debit": base_asset_amount,
"debit_in_account_currency": (base_asset_amount
if arbnb_currency == self.company_currency else asset_amount),
"cost_center": item.cost_center
"cost_center": item.cost_center,
"project": item.project or self.project
}, item=item))
if item.item_tax_amount:
@@ -623,6 +629,7 @@ class PurchaseInvoice(BuyingController):
"against": self.supplier,
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
"cost_center": item.cost_center,
"project": item.project or self.project,
"credit": item.item_tax_amount,
"credit_in_account_currency": (item.item_tax_amount
if asset_eiiav_currency == self.company_currency else
@@ -639,7 +646,8 @@ class PurchaseInvoice(BuyingController):
"debit": base_asset_amount,
"debit_in_account_currency": (base_asset_amount
if cwip_account_currency == self.company_currency else asset_amount),
"cost_center": self.cost_center
"cost_center": self.cost_center,
"project": item.project or self.project
}, item=item))
if item.item_tax_amount and not cint(erpnext.is_perpetual_inventory_enabled(self.company)):
@@ -650,6 +658,7 @@ class PurchaseInvoice(BuyingController):
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
"cost_center": item.cost_center,
"credit": item.item_tax_amount,
"project": item.project or self.project,
"credit_in_account_currency": (item.item_tax_amount
if asset_eiiav_currency == self.company_currency else
item.item_tax_amount / self.conversion_rate)
@@ -665,7 +674,7 @@ class PurchaseInvoice(BuyingController):
"cost_center": item.cost_center,
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
"credit": flt(item.landed_cost_voucher_amount),
"project": item.project
"project": item.project or self.project
}, item=item))
gl_entries.append(self.get_gl_dict({
@@ -674,7 +683,7 @@ class PurchaseInvoice(BuyingController):
"cost_center": item.cost_center,
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
"debit": flt(item.landed_cost_voucher_amount),
"project": item.project
"project": item.project or self.project
}, item=item))
# update gross amount of assets bought through this document
@@ -709,7 +718,7 @@ class PurchaseInvoice(BuyingController):
"debit": stock_adjustment_amt,
"remarks": self.get("remarks") or _("Stock Adjustment"),
"cost_center": item.cost_center,
"project": item.project
"project": item.project or self.project
}, account_currency, item=item)
)
@@ -801,7 +810,8 @@ class PurchaseInvoice(BuyingController):
if self.party_account_currency==self.company_currency else self.paid_amount,
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
"against_voucher_type": self.doctype,
"cost_center": self.cost_center
"cost_center": self.cost_center,
"project": self.project
}, self.party_account_currency, item=self)
)
@@ -833,7 +843,8 @@ class PurchaseInvoice(BuyingController):
if self.party_account_currency==self.company_currency else self.write_off_amount,
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
"against_voucher_type": self.doctype,
"cost_center": self.cost_center
"cost_center": self.cost_center,
"project": self.project
}, self.party_account_currency, item=self)
)
gl_entries.append(
@@ -980,7 +991,7 @@ class PurchaseInvoice(BuyingController):
# calculate totals again after applying TDS
self.calculate_taxes_and_totals()
def set_status(self, update=False, status=None, update_modified=True):
if self.is_new():
if self.get('amended_from'):
@@ -1026,6 +1037,10 @@ def get_list_context(context=None):
})
return list_context
@erpnext.allow_regional
def make_regional_gl_entries(gl_entries, doc):
return gl_entries
@frappe.whitelist()
def make_debit_note(source_name, target_doc=None):
from erpnext.controllers.sales_and_purchase_return import make_return_doc

View File

@@ -16,7 +16,7 @@ frappe.listview_settings['Purchase Invoice'] = {
} else if(frappe.datetime.get_diff(doc.due_date) < 0) {
return [__("Overdue"), "red", "outstanding_amount,>,0|due_date,<,Today"];
} else {
return [__("Unpaid"), "orange", "outstanding_amount,>,0|due,>=,Today"];
return [__("Unpaid"), "orange", "outstanding_amount,>,0|due_date,>=,Today"];
}
} else if(cint(doc.is_return)) {
return [__("Return"), "darkgrey", "is_return,=,Yes"];

View File

@@ -15,6 +15,7 @@ from erpnext.controllers.accounts_controller import get_payment_terms
from erpnext.exceptions import InvalidCurrency
from erpnext.stock.doctype.stock_entry.test_stock_entry import get_qty_after_transaction
from erpnext.accounts.doctype.account.test_account import get_inventory_account
from erpnext.projects.doctype.project.test_project import make_project
test_dependencies = ["Item", "Cost Center", "Payment Term", "Payment Terms Template"]
test_ignore = ["Serial No"]
@@ -434,6 +435,8 @@ class TestPurchaseInvoice(unittest.TestCase):
)
def test_total_purchase_cost_for_project(self):
make_project({'project_name':'_Test Project'})
existing_purchase_cost = frappe.db.sql("""select sum(base_net_amount)
from `tabPurchase Invoice Item` where project = '_Test Project' and docstatus=1""")
existing_purchase_cost = existing_purchase_cost and existing_purchase_cost[0][0] or 0
@@ -807,11 +810,8 @@ class TestPurchaseInvoice(unittest.TestCase):
pi_doc = frappe.get_doc('Purchase Invoice', pi.name)
self.assertEqual(pi_doc.outstanding_amount, 0)
def test_purchase_invoice_for_enable_allow_cost_center_in_entry_of_bs_account(self):
def test_purchase_invoice_with_cost_center(self):
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
accounts_settings.save()
cost_center = "_Test Cost Center for BS Account - _TC"
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
@@ -837,13 +837,7 @@ class TestPurchaseInvoice(unittest.TestCase):
for gle in gl_entries:
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
def test_purchase_invoice_for_disable_allow_cost_center_in_entry_of_bs_account(self):
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
def test_purchase_invoice_without_cost_center(self):
cost_center = "_Test Cost Center - _TC"
pi = make_purchase_invoice(credit_to="Creditors - _TC")
@@ -866,6 +860,42 @@ class TestPurchaseInvoice(unittest.TestCase):
for gle in gl_entries:
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
def test_purchase_invoice_with_project_link(self):
project = make_project({
'project_name': 'Purchase Invoice Project',
'project_template_name': 'Test Project Template',
'start_date': '2020-01-01'
})
item_project = make_project({
'project_name': 'Purchase Invoice Item Project',
'project_template_name': 'Test Project Template',
'start_date': '2019-06-01'
})
pi = make_purchase_invoice(credit_to="Creditors - _TC" ,do_not_save=1)
pi.items[0].project = item_project.project_name
pi.project = project.project_name
pi.submit()
expected_values = {
"Creditors - _TC": {
"project": project.project_name
},
"_Test Account Cost for Goods Sold - _TC": {
"project": item_project.project_name
}
}
gl_entries = frappe.db.sql("""select account, cost_center, project, account_currency, debit, credit,
debit_in_account_currency, credit_in_account_currency
from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s
order by account asc""", pi.name, as_dict=1)
self.assertTrue(gl_entries)
for gle in gl_entries:
self.assertEqual(expected_values[gle.account]["project"], gle.project)
def unlink_payment_on_cancel_of_invoice(enable=1):
accounts_settings = frappe.get_doc("Accounts Settings")

View File

@@ -1,5 +1,4 @@
{
"actions": [],
"autoname": "hash",
"creation": "2013-05-22 12:43:10",
"doctype": "DocType",
@@ -86,6 +85,7 @@
"item_tax_rate",
"bom",
"include_exploded_items",
"purchase_invoice_item",
"col_break6",
"purchase_order",
"po_detail",
@@ -764,12 +764,21 @@
"label": "Asset Category",
"options": "Asset Category",
"read_only": 1
},
{
"depends_on": "eval:parent.update_stock == 1",
"fieldname": "purchase_invoice_item",
"fieldtype": "Data",
"ignore_user_permissions": 1,
"label": "Purchase Invoice Item",
"no_copy": 1,
"print_hide": 1,
"read_only": 1
}
],
"idx": 1,
"istable": 1,
"links": [],
"modified": "2020-04-07 18:34:35.104178",
"modified": "2020-06-30 16:48:01.398356",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",

View File

@@ -1,5 +1,4 @@
{
"actions": [],
"allow_import": 1,
"autoname": "naming_series:",
"creation": "2013-05-24 19:29:05",
@@ -1494,6 +1493,7 @@
"print_hide": 1
},
{
"collapsible": 1,
"fieldname": "subscription_section",
"fieldtype": "Section Break",
"label": "Subscription Section"
@@ -1569,8 +1569,7 @@
"icon": "fa fa-file-text",
"idx": 181,
"is_submittable": 1,
"links": [],
"modified": "2020-05-19 17:00:57.208696",
"modified": "2020-07-01 12:41:29.484813",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",

View File

@@ -786,7 +786,8 @@ class SalesInvoice(SellingController):
if self.party_account_currency==self.company_currency else grand_total,
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
"against_voucher_type": self.doctype,
"cost_center": self.cost_center
"cost_center": self.cost_center,
"project": self.project
}, self.party_account_currency, item=self)
)
@@ -841,7 +842,8 @@ class SalesInvoice(SellingController):
"credit_in_account_currency": (flt(item.base_net_amount, item.precision("base_net_amount"))
if account_currency==self.company_currency
else flt(item.net_amount, item.precision("net_amount"))),
"cost_center": item.cost_center
"cost_center": item.cost_center,
"project": item.project or self.project
}, account_currency, item=item)
)
@@ -922,7 +924,8 @@ class SalesInvoice(SellingController):
if self.party_account_currency==self.company_currency else flt(self.change_amount),
"against_voucher": self.return_against if cint(self.is_return) and self.return_against else self.name,
"against_voucher_type": self.doctype,
"cost_center": self.cost_center
"cost_center": self.cost_center,
"project": self.project
}, self.party_account_currency, item=self)
)
@@ -955,7 +958,8 @@ class SalesInvoice(SellingController):
else flt(self.write_off_amount, self.precision("write_off_amount"))),
"against_voucher": self.return_against if cint(self.is_return) else self.name,
"against_voucher_type": self.doctype,
"cost_center": self.cost_center
"cost_center": self.cost_center,
"project": self.project
}, self.party_account_currency, item=self)
)
gl_entries.append(
@@ -1105,7 +1109,10 @@ class SalesInvoice(SellingController):
expiry_date=self.posting_date, include_expired_entry=True)
if lp_details and getdate(lp_details.from_date) <= getdate(self.posting_date) and \
(not lp_details.to_date or getdate(lp_details.to_date) >= getdate(self.posting_date)):
points_earned = cint(eligible_amount/lp_details.collection_factor)
collection_factor = lp_details.collection_factor if lp_details.collection_factor else 1.0
points_earned = cint(eligible_amount/collection_factor)
doc = frappe.get_doc({
"doctype": "Loyalty Point Entry",
"company": self.company,

View File

@@ -13,7 +13,8 @@ def get_data():
'Auto Repeat': 'reference_document',
},
'internal_links': {
'Sales Order': ['items', 'sales_order']
'Sales Order': ['items', 'sales_order'],
'Delivery Note': ['items', 'delivery_note']
},
'transactions': [
{
@@ -33,4 +34,4 @@ def get_data():
'items': ['Auto Repeat']
},
]
}
}

View File

@@ -3,6 +3,7 @@
"company": "_Test Company",
"conversion_rate": 1.0,
"currency": "INR",
"cost_center": "_Test Cost Center - _TC",
"customer": "_Test Customer",
"customer_name": "_Test Customer",
"debit_to": "_Test Receivable - _TC",
@@ -37,7 +38,8 @@
"charge_type": "On Net Total",
"description": "VAT",
"doctype": "Sales Taxes and Charges",
"parentfield": "taxes",
"parentfield": "taxes",
"cost_center": "_Test Cost Center - _TC",
"rate": 6
},
{
@@ -45,7 +47,8 @@
"charge_type": "On Net Total",
"description": "Service Tax",
"doctype": "Sales Taxes and Charges",
"parentfield": "taxes",
"parentfield": "taxes",
"cost_center": "_Test Cost Center - _TC",
"rate": 6.36
}
],
@@ -76,6 +79,7 @@
"customer_name": "_Test Customer",
"debit_to": "_Test Receivable - _TC",
"doctype": "Sales Invoice",
"cost_center": "_Test Cost Center - _TC",
"items": [
{
"amount": 500.0,
@@ -107,7 +111,8 @@
"charge_type": "On Net Total",
"description": "VAT",
"doctype": "Sales Taxes and Charges",
"parentfield": "taxes",
"parentfield": "taxes",
"cost_center": "_Test Cost Center - _TC",
"rate": 16
},
{
@@ -115,7 +120,8 @@
"charge_type": "On Net Total",
"description": "Service Tax",
"doctype": "Sales Taxes and Charges",
"parentfield": "taxes",
"parentfield": "taxes",
"cost_center": "_Test Cost Center - _TC",
"rate": 10
}
],
@@ -132,6 +138,7 @@
"customer_name": "_Test Customer",
"debit_to": "_Test Receivable - _TC",
"doctype": "Sales Invoice",
"cost_center": "_Test Cost Center - _TC",
"items": [
{
"cost_center": "_Test Cost Center - _TC",
@@ -259,6 +266,7 @@
"customer_name": "_Test Customer",
"debit_to": "_Test Receivable - _TC",
"doctype": "Sales Invoice",
"cost_center": "_Test Cost Center - _TC",
"items": [
{
"cost_center": "_Test Cost Center - _TC",

View File

@@ -206,10 +206,19 @@ class TestSalesInvoice(unittest.TestCase):
"rate": 14,
'included_in_print_rate': 1
})
si.append("taxes", {
"charge_type": "On Item Quantity",
"account_head": "_Test Account Education Cess - _TC",
"cost_center": "_Test Cost Center - _TC",
"description": "CESS",
"rate": 5,
'included_in_print_rate': 1
})
si.insert()
# with inclusive tax
self.assertEqual(si.net_total, 4385.96)
self.assertEqual(si.items[0].net_amount, 3947.368421052631)
self.assertEqual(si.net_total, 3947.37)
self.assertEqual(si.grand_total, 5000)
si.reload()
@@ -222,8 +231,8 @@ class TestSalesInvoice(unittest.TestCase):
si.save()
# with inclusive tax and additional discount
self.assertEqual(si.net_total, 4285.96)
self.assertEqual(si.grand_total, 4885.99)
self.assertEqual(si.net_total, 3847.37)
self.assertEqual(si.grand_total, 4886)
si.reload()
@@ -235,7 +244,7 @@ class TestSalesInvoice(unittest.TestCase):
si.save()
# with inclusive tax and additional discount
self.assertEqual(si.net_total, 4298.25)
self.assertEqual(si.net_total, 3859.65)
self.assertEqual(si.grand_total, 4900.00)
def test_sales_invoice_discount_amount(self):
@@ -705,6 +714,64 @@ class TestSalesInvoice(unittest.TestCase):
self.pos_gl_entry(si, pos, 50)
def test_pos_returns_without_repayment(self):
pos_profile = make_pos_profile()
pos = create_sales_invoice(qty = 10, do_not_save=True)
pos.is_pos = 1
pos.pos_profile = pos_profile.name
pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 500})
pos.append("payments", {'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 500})
pos.insert()
pos.submit()
pos_return = create_sales_invoice(is_return=1,
return_against=pos.name, qty=-5, do_not_save=True)
pos_return.is_pos = 1
pos_return.pos_profile = pos_profile.name
pos_return.insert()
pos_return.submit()
self.assertFalse(pos_return.is_pos)
self.assertFalse(pos_return.get('payments'))
def test_pos_returns_with_repayment(self):
pos_profile = make_pos_profile()
pos_profile.append('payments', {
'default': 1,
'mode_of_payment': 'Cash',
'amount': 0.0
})
pos_profile.save()
pos = create_sales_invoice(qty = 10, do_not_save=True)
pos.is_pos = 1
pos.pos_profile = pos_profile.name
pos.append("payments", {'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 500})
pos.append("payments", {'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 500})
pos.insert()
pos.submit()
pos_return = create_sales_invoice(is_return=1,
return_against=pos.name, qty=-5, do_not_save=True)
pos_return.is_pos = 1
pos_return.pos_profile = pos_profile.name
pos_return.insert()
pos_return.submit()
self.assertEqual(pos_return.get('payments')[0].amount, -500)
pos_profile.payments = []
pos_profile.save()
def test_pos_change_amount(self):
make_pos_profile()
@@ -1575,11 +1642,8 @@ class TestSalesInvoice(unittest.TestCase):
si_doc = frappe.get_doc('Sales Invoice', si.name)
self.assertEqual(si_doc.outstanding_amount, 0)
def test_sales_invoice_for_enable_allow_cost_center_in_entry_of_bs_account(self):
def test_sales_invoice_with_cost_center(self):
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
accounts_settings.save()
cost_center = "_Test Cost Center for BS Account - _TC"
create_cost_center(cost_center_name="_Test Cost Center for BS Account", company="_Test Company")
@@ -1604,14 +1668,47 @@ class TestSalesInvoice(unittest.TestCase):
for gle in gl_entries:
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
def test_sales_invoice_with_project_link(self):
from erpnext.projects.doctype.project.test_project import make_project
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
project = make_project({
'project_name': 'Sales Invoice Project',
'project_template_name': 'Test Project Template',
'start_date': '2020-01-01'
})
item_project = make_project({
'project_name': 'Sales Invoice Item Project',
'project_template_name': 'Test Project Template',
'start_date': '2019-06-01'
})
def test_sales_invoice_for_disable_allow_cost_center_in_entry_of_bs_account(self):
accounts_settings = frappe.get_doc('Accounts Settings', 'Accounts Settings')
accounts_settings.allow_cost_center_in_entry_of_bs_account = 1
accounts_settings.save()
sales_invoice = create_sales_invoice(do_not_save=1)
sales_invoice.items[0].project = item_project.project_name
sales_invoice.project = project.project_name
sales_invoice.submit()
expected_values = {
"Debtors - _TC": {
"project": project.project_name
},
"Sales - _TC": {
"project": item_project.project_name
}
}
gl_entries = frappe.db.sql("""select account, cost_center, project, account_currency, debit, credit,
debit_in_account_currency, credit_in_account_currency
from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
order by account asc""", sales_invoice.name, as_dict=1)
self.assertTrue(gl_entries)
for gle in gl_entries:
self.assertEqual(expected_values[gle.account]["project"], gle.project)
def test_sales_invoice_without_cost_center(self):
cost_center = "_Test Cost Center - _TC"
si = create_sales_invoice(debit_to="Debtors - _TC")
@@ -1634,9 +1731,6 @@ class TestSalesInvoice(unittest.TestCase):
for gle in gl_entries:
self.assertEqual(expected_values[gle.account]["cost_center"], gle.cost_center)
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
def test_deferred_revenue(self):
deferred_account = create_account(account_name="Deferred Revenue",
parent_account="Current Liabilities - _TC", company="_Test Company")

View File

@@ -1,5 +1,4 @@
{
"actions": [],
"autoname": "hash",
"creation": "2013-06-04 11:02:19",
"doctype": "DocType",
@@ -87,6 +86,7 @@
"edit_references",
"sales_order",
"so_detail",
"sales_invoice_item",
"column_break_74",
"delivery_note",
"dn_detail",
@@ -94,6 +94,7 @@
"accounting_dimensions_section",
"cost_center",
"dimension_col_break",
"project",
"section_break_54",
"page_break"
],
@@ -783,12 +784,28 @@
"fieldtype": "Link",
"label": "Finance Book",
"options": "Finance Book"
},
{
"fieldname": "project",
"fieldtype": "Link",
"label": "Project",
"options": "Project"
},
{
"depends_on": "eval:parent.update_stock == 1",
"fieldname": "sales_invoice_item",
"fieldtype": "Data",
"ignore_user_permissions": 1,
"label": "Sales Invoice Item",
"no_copy": 1,
"print_hide": 1,
"read_only": 1
}
],
"idx": 1,
"istable": 1,
"links": [],
"modified": "2019-12-04 12:22:38.517710",
"modified": "2020-08-20 11:24:41.749986",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Item",

View File

@@ -1,314 +1,89 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2016-05-08 23:49:38.842621",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"creation": "2016-05-08 23:49:38.842621",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"default",
"mode_of_payment",
"amount",
"column_break_3",
"account",
"type",
"base_amount",
"clearance_date"
],
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval:parent.doctype == 'POS Profile'",
"fetch_if_empty": 0,
"fieldname": "default",
"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": "Default",
"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
},
"default": "0",
"depends_on": "eval:parent.doctype == 'POS Profile'",
"fieldname": "default",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Default"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "mode_of_payment",
"fieldtype": "Link",
"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": "Mode of Payment",
"length": 0,
"no_copy": 0,
"options": "Mode of Payment",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "mode_of_payment",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Mode of Payment",
"options": "Mode of Payment",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0",
"depends_on": "eval:parent.doctype == 'Sales Invoice'",
"fetch_if_empty": 0,
"fieldname": "amount",
"fieldtype": "Currency",
"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": "Amount",
"length": 0,
"no_copy": 0,
"options": "currency",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"default": "0",
"depends_on": "eval:parent.doctype == 'Sales Invoice'",
"fieldname": "amount",
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Amount",
"options": "currency",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_3",
"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
},
"fieldname": "column_break_3",
"fieldtype": "Column Break"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "account",
"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": "Account",
"length": 0,
"no_copy": 0,
"options": "Account",
"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
},
"fieldname": "account",
"fieldtype": "Link",
"label": "Account",
"options": "Account",
"print_hide": 1,
"read_only": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_from": "mode_of_payment.type",
"fetch_if_empty": 0,
"fieldname": "type",
"fieldtype": "Read Only",
"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": "Type",
"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
},
"fetch_from": "mode_of_payment.type",
"fieldname": "type",
"fieldtype": "Read Only",
"label": "Type"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_amount",
"fieldtype": "Currency",
"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": "Base Amount (Company Currency)",
"length": 0,
"no_copy": 1,
"options": "Company:company:default_currency",
"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
},
"fieldname": "base_amount",
"fieldtype": "Currency",
"label": "Base Amount (Company Currency)",
"no_copy": 1,
"options": "Company:company:default_currency",
"print_hide": 1,
"read_only": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "clearance_date",
"fieldtype": "Date",
"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": "Clearance Date",
"length": 0,
"no_copy": 0,
"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
"fieldname": "clearance_date",
"fieldtype": "Date",
"label": "Clearance Date",
"no_copy": 1,
"print_hide": 1,
"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": 1,
"max_attachments": 0,
"modified": "2019-03-19 14:54:56.524556",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Payment",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 0,
"track_seen": 0,
"track_views": 0
],
"istable": 1,
"modified": "2020-08-03 13:07:49.260534",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Payment",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC"
}

View File

@@ -1,5 +1,4 @@
{
"actions": [],
"autoname": "ACC-SUB-.YYYY.-.#####",
"creation": "2017-07-18 17:50:43.967266",
"doctype": "DocType",
@@ -184,7 +183,8 @@
"fieldname": "invoices",
"fieldtype": "Table",
"label": "Invoices",
"options": "Subscription Invoice"
"options": "Subscription Invoice",
"read_only": 1
},
{
"collapsible": 1,
@@ -197,8 +197,7 @@
"fieldtype": "Column Break"
}
],
"links": [],
"modified": "2020-01-27 14:37:32.845173",
"modified": "2020-08-27 23:30:02.504042",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Subscription",

View File

@@ -326,8 +326,7 @@ class Subscription(Document):
def is_postpaid_to_invoice(self):
return getdate(nowdate()) > getdate(self.current_invoice_end) or \
(getdate(nowdate()) >= getdate(self.current_invoice_end) and getdate(self.current_invoice_end) == getdate(self.current_invoice_start)) and \
not self.has_outstanding_invoice()
(getdate(nowdate()) >= getdate(self.current_invoice_end) and getdate(self.current_invoice_end) == getdate(self.current_invoice_start))
def is_prepaid_to_invoice(self):
if not self.generate_invoice_at_period_start:
@@ -337,8 +336,16 @@ class Subscription(Document):
return True
# 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()
return getdate(nowdate()) >= getdate(self.current_invoice_start)
def is_current_invoice_generated(self):
invoice = self.get_current_invoice()
if invoice and getdate(self.current_invoice_start) <= getdate(invoice.posting_date) <= getdate(self.current_invoice_end):
return True
return False
def is_current_invoice_paid(self):
if self.is_new_subscription():
return False
@@ -346,7 +353,7 @@ class Subscription(Document):
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):
@@ -358,7 +365,8 @@ class Subscription(Document):
2. Change the `Subscription` status to 'Past Due Date'
3. Change the `Subscription` status to 'Cancelled'
"""
if not self.is_current_invoice_paid() and (self.is_postpaid_to_invoice() or self.is_prepaid_to_invoice()):
if not self.is_current_invoice_generated() and 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'
@@ -369,6 +377,9 @@ class Subscription(Document):
if self.cancel_at_period_end and getdate(nowdate()) > getdate(self.current_invoice_end):
self.cancel_subscription_at_period_end()
if self.is_current_invoice_generated() and getdate() > getdate(self.current_invoice_end):
self.update_subscription_period(add_days(self.current_invoice_end, 1))
def cancel_subscription_at_period_end(self):
"""
Called when `Subscription.cancel_at_period_end` is truthy

View File

@@ -101,19 +101,19 @@ class TestSubscription(unittest.TestCase):
subscription.delete()
def test_invoice_is_generated_at_end_of_billing_period(self):
start_date = add_to_date(nowdate(), months=-1)
subscription = frappe.new_doc('Subscription')
subscription.customer = '_Test Customer'
subscription.start = '2018-01-01'
subscription.start = start_date
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
subscription.insert()
self.assertEqual(subscription.status, 'Active')
self.assertEqual(subscription.current_invoice_start, '2018-01-01')
self.assertEqual(subscription.current_invoice_end, '2018-01-31')
self.assertEqual(subscription.current_invoice_start, start_date)
self.assertEqual(subscription.current_invoice_end, add_days(nowdate(), -1))
subscription.process()
self.assertEqual(len(subscription.invoices), 1)
self.assertEqual(subscription.current_invoice_start, '2018-01-01')
self.assertEqual(subscription.status, 'Past Due Date')
subscription.delete()
@@ -137,7 +137,6 @@ class TestSubscription(unittest.TestCase):
subscription.process()
self.assertEqual(subscription.status, 'Active')
self.assertEqual(subscription.current_invoice_start, add_months(subscription.start, 1))
self.assertEqual(len(subscription.invoices), 1)
subscription.delete()
@@ -538,3 +537,23 @@ class TestSubscription(unittest.TestCase):
settings.save()
subscription.delete()
def test_duplicate_invoice_check(self):
subscription = frappe.new_doc('Subscription')
subscription.customer = '_Test Customer'
subscription.generate_invoice_at_period_start = True
subscription.append('plans', {'plan': '_Test Plan Name', 'qty': 1})
subscription.start = nowdate()
subscription.save()
# Generate invoice for the current invoicing period
subscription.process()
subscription.load_from_db()
self.assertEqual(len(subscription.invoices), 1)
# Proccess subscription again for the same period
subscription.process()
subscription.load_from_db()
# No new invoice should be created for current period
self.assertEqual(len(subscription.invoices), 1)

View File

@@ -45,8 +45,8 @@ def validate_accounting_period(gl_map):
}, as_dict=1)
if accounting_periods:
frappe.throw(_("You can't create accounting entries in the closed accounting period {0}")
.format(accounting_periods[0].name), ClosedAccountingPeriod)
frappe.throw(_("You cannot create or cancel any accounting entries within in the closed Accounting Period {0}")
.format(frappe.bold(accounting_periods[0].name)), ClosedAccountingPeriod)
def process_gl_map(gl_map, merge_entries=True):
if merge_entries:
@@ -296,6 +296,7 @@ def delete_gl_entries(gl_entries=None, voucher_type=None, voucher_no=None,
where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no), as_dict=True)
if gl_entries:
validate_accounting_period(gl_entries)
check_freezing_date(gl_entries[0]["posting_date"], adv_adj)
frappe.db.sql("""delete from `tabGL Entry` where voucher_type=%s and voucher_no=%s""",

View File

@@ -285,6 +285,8 @@ def get_matching_transactions_payments(description_matching):
else:
return []
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def payment_entry_query(doctype, txt, searchfield, start, page_len, filters):
account = frappe.db.get_value("Bank Account", filters.get("bank_account"), "account")
if not account:
@@ -313,6 +315,8 @@ def payment_entry_query(doctype, txt, searchfield, start, page_len, filters):
}
)
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def journal_entry_query(doctype, txt, searchfield, start, page_len, filters):
account = frappe.db.get_value("Bank Account", filters.get("bank_account"), "account")
@@ -348,6 +352,8 @@ def journal_entry_query(doctype, txt, searchfield, start, page_len, filters):
}
)
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def sales_invoices_query(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql("""
SELECT
@@ -373,4 +379,4 @@ def sales_invoices_query(doctype, txt, searchfield, start, page_len, filters):
'start': start,
'page_len': page_len
}
)
)

View File

@@ -1062,8 +1062,9 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
}
if(index < me.page_len) {
$(frappe.render_template("pos_item", {
item_code: obj.name,
item_code: escape(obj.name),
item_price: item_price,
title: obj.name || obj.item_name,
item_name: obj.name === obj.item_name ? "" : obj.item_name,
item_image: obj.image,
item_stock: __('Stock Qty') + ": " + me.get_actual_qty(obj),
@@ -1098,7 +1099,8 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
get_items: function (item_code) {
// To search item as per the key enter
item_code = unescape(item_code);
item_code = item_code === "undefined" ? undefined : item_code;
var me = this;
this.item_serial_no = {};
this.item_batch_no = {};
@@ -1164,7 +1166,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
$(this).addClass('active');
me.numeric_val = "";
me.numeric_id = ""
me.item_code = $(this).attr("data-item-code");
me.item_code = unescape($(this).attr("data-item-code"));
me.render_selected_item()
me.bind_qty_event()
me.update_rate()
@@ -1176,33 +1178,33 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
var me = this;
$(this.wrapper).on("change", ".pos-item-qty", function () {
var item_code = $(this).parents(".pos-selected-item-action").attr("data-item-code");
var item_code = unescape($(this).parents(".pos-selected-item-action").attr("data-item-code"));
var qty = $(this).val();
me.update_qty(item_code, qty);
me.update_value();
})
$(this.wrapper).on("focusout", ".pos-item-qty", function () {
var item_code = $(this).parents(".pos-selected-item-action").attr("data-item-code");
var item_code = unescape($(this).parents(".pos-selected-item-action").attr("data-item-code"));
var qty = $(this).val();
me.update_qty(item_code, qty, true);
me.update_value();
})
$(this.wrapper).find("[data-action='increase-qty']").on("click", function () {
var item_code = $(this).parents(".pos-bill-item").attr("data-item-code");
var item_code = unescape($(this).parents(".pos-bill-item").attr("data-item-code"));
var qty = flt($(this).parents(".pos-bill-item").find('.pos-item-qty').val()) + 1;
me.update_qty(item_code, qty);
})
$(this.wrapper).find("[data-action='decrease-qty']").on("click", function () {
var item_code = $(this).parents(".pos-bill-item").attr("data-item-code");
var item_code = unescape($(this).parents(".pos-bill-item").attr("data-item-code"));
var qty = flt($(this).parents(".pos-bill-item").find('.pos-item-qty').val()) - 1;
me.update_qty(item_code, qty);
})
$(this.wrapper).on("change", ".pos-item-disc", function () {
var item_code = $(this).parents(".pos-selected-item-action").attr("data-item-code");
var item_code = unescape($(this).parents(".pos-selected-item-action").attr("data-item-code"));
var discount = $(this).val();
if(discount > 100){
discount = $(this).val('');
@@ -1253,7 +1255,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
update_rate: function () {
var me = this;
$(this.wrapper).on("change", ".pos-item-price", function () {
var item_code = $(this).parents(".pos-selected-item-action").attr("data-item-code");
var item_code = unescape($(this).parents(".pos-selected-item-action").attr("data-item-code"));
me.set_item_details(item_code, "rate", $(this).val());
me.update_value()
})
@@ -1282,9 +1284,17 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
this.child_doc = this.get_child_item(this.item_code);
$(this.wrapper).find('.selected-item').empty();
if(this.child_doc.length) {
this.child_doc[0]["allow_user_to_edit_rate"] = this.pos_profile_data["allow_user_to_edit_rate"] ? true : false,
this.child_doc[0]["allow_user_to_edit_discount"] = this.pos_profile_data["allow_user_to_edit_discount"] ? true : false;
this.selected_row = $(frappe.render_template("pos_selected_item", this.child_doc[0]))
this.selected_row = $(frappe.render_template("pos_selected_item", {
idx: this.child_doc[0].idx,
item_code: escape(this.child_doc[0].item_code),
qty: this.child_doc[0].qty,
price_list_rate: this.child_doc[0].price_list_rate,
allow_user_to_edit_rate: this.pos_profile_data["allow_user_to_edit_rate"] ? true : false,
allow_user_to_edit_discount: this.pos_profile_data["allow_user_to_edit_discount"] ? true : false,
discount_percentage: this.child_doc[0].discount_percentage,
rate: this.child_doc[0].rate,
amount: this.child_doc[0].amount
}))
$(this.wrapper).find('.selected-item').html(this.selected_row)
}
@@ -1535,7 +1545,8 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
$.each(this.frm.doc.items || [], function (i, d) {
$(frappe.render_template("pos_bill_item_new", {
item_code: d.item_code,
item_code: escape(d.item_code),
title: d.item_code || d.item_name,
item_name: (d.item_name === d.item_code || !d.item_name) ? "" : ("<br>" + d.item_name),
qty: d.qty,
discount_percentage: d.discount_percentage || 0.0,

View File

@@ -391,7 +391,7 @@ def set_taxes(party, party_type, posting_date, company, customer_group=None, sup
from erpnext.accounts.doctype.tax_rule.tax_rule import get_tax_template, get_party_details
args = {
party_type.lower(): party,
"company": company
"company": company
}
if tax_category:

View File

@@ -61,7 +61,7 @@ def make_sales_invoice():
debit_to = 'Debtors - _TC2',
income_account = 'Sales - _TC2',
expense_account = 'Cost of Goods Sold - _TC2',
cost_center = '_Test Company 2 - _TC2')
cost_center = 'Main - _TC2')

View File

@@ -643,8 +643,10 @@ class ReceivablePayableReport(object):
account_type = "Receivable" if self.party_type == "Customer" else "Payable"
accounts = [d.name for d in frappe.get_all("Account",
filters={"account_type": account_type, "company": self.filters.company})]
conditions.append("account in (%s)" % ','.join(['%s'] *len(accounts)))
values += accounts
if accounts:
conditions.append("account in (%s)" % ','.join(['%s'] *len(accounts)))
values += accounts
def add_customer_filters(self, conditions, values):
if self.filters.get("customer_group"):

View File

@@ -63,7 +63,7 @@ def make_sales_invoice():
debit_to = 'Debtors - _TC2',
income_account = 'Sales - _TC2',
expense_account = 'Cost of Goods Sold - _TC2',
cost_center = '_Test Company 2 - _TC2',
cost_center = 'Main - _TC2',
do_not_save=1)
si.append('payment_schedule', dict(due_date=getdate(add_days(today(), 30)), invoice_portion=30.00, payment_amount=30))
@@ -83,14 +83,14 @@ def make_payment(docname):
def make_credit_note(docname):
create_sales_invoice(company="_Test Company 2",
customer = '_Test Customer 2',
currency = 'EUR',
qty = -1,
warehouse = 'Finished Goods - _TC2',
debit_to = 'Debtors - _TC2',
income_account = 'Sales - _TC2',
expense_account = 'Cost of Goods Sold - _TC2',
cost_center = '_Test Company 2 - _TC2',
is_return = 1,
return_against = docname)
customer = '_Test Customer 2',
currency = 'EUR',
qty = -1,
warehouse = 'Finished Goods - _TC2',
debit_to = 'Debtors - _TC2',
income_account = 'Sales - _TC2',
expense_account = 'Cost of Goods Sold - _TC2',
cost_center = 'Main - _TC2',
is_return = 1,
return_against = docname)

View File

@@ -8,12 +8,13 @@ from __future__ import unicode_literals
import re
from past.builtins import cmp
import functools
import math
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, cstr)
from frappe.utils import (flt, getdate, get_first_day, add_months, add_days, formatdate, cstr, cint)
from six import itervalues
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions, get_dimension_with_children
@@ -42,7 +43,7 @@ def get_period_list(from_fiscal_year, to_fiscal_year, periodicity, accumulated_v
start_date = year_start_date
months = get_months(year_start_date, year_end_date)
for i in range(months // months_to_add):
for i in range(cint(math.ceil(months / months_to_add))):
period = frappe._dict({
"from_date": start_date
})

View File

@@ -43,8 +43,11 @@ def execute(filters=None):
def validate_filters(filters, account_details):
if not filters.get('company'):
frappe.throw(_('{0} is mandatory').format(_('Company')))
if not filters.get("company"):
frappe.throw(_("{0} is mandatory").format(_("Company")))
if not filters.get("from_date") and not filters.get("to_date"):
frappe.throw(_("{0} and {1} are mandatory").format(frappe.bold(_("From Date")), frappe.bold(_("To Date"))))
if filters.get("account") and not account_details.get(filters.account):
frappe.throw(_("Account {0} does not exists").format(filters.account))

View File

@@ -1,24 +1,23 @@
{
"add_total_row": 0,
"apply_user_permissions": 1,
"creation": "2013-02-25 17:03:34",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 3,
"is_standard": "Yes",
"modified": "2017-02-24 20:12:22.464240",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Gross Profit",
"owner": "Administrator",
"ref_doctype": "Sales Invoice",
"report_name": "Gross Profit",
"report_type": "Script Report",
"add_total_row": 1,
"creation": "2013-02-25 17:03:34",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 3,
"is_standard": "Yes",
"modified": "2020-08-13 11:26:39.112352",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Gross Profit",
"owner": "Administrator",
"ref_doctype": "Sales Invoice",
"report_name": "Gross Profit",
"report_type": "Script Report",
"roles": [
{
"role": "Accounts Manager"
},
},
{
"role": "Accounts User"
}

View File

@@ -113,7 +113,7 @@ def get_balance_on(account=None, date=None, party_type=None, party=None, company
acc = frappe.get_doc("Account", account)
try:
year_start_date = get_fiscal_year(date, verbose=0)[1]
year_start_date = get_fiscal_year(date, company=company, verbose=0)[1]
except FiscalYearError:
if getdate(date) > getdate(nowdate()):
# if fiscal year not found and the date is greater than today
@@ -124,14 +124,12 @@ def get_balance_on(account=None, date=None, party_type=None, party=None, company
# hence, assuming balance as 0.0
return 0.0
allow_cost_center_in_entry_of_bs_account = get_allow_cost_center_in_entry_of_bs_account()
if account:
report_type = acc.report_type
else:
report_type = ""
if cost_center and (allow_cost_center_in_entry_of_bs_account or report_type =='Profit and Loss'):
if cost_center and report_type == 'Profit and Loss':
cc = frappe.get_doc("Cost Center", cost_center)
if cc.is_group:
cond.append(""" exists (
@@ -658,7 +656,8 @@ def get_outstanding_invoices(party_type, party, account, condition=None, filters
invoice_list = frappe.db.sql("""
select
voucher_no, voucher_type, posting_date, due_date,
ifnull(sum({dr_or_cr}), 0) as invoice_amount
ifnull(sum({dr_or_cr}), 0) as invoice_amount,
account_currency as currency
from
`tabGL Entry`
where
@@ -715,7 +714,8 @@ def get_outstanding_invoices(party_type, party, account, condition=None, filters
'invoice_amount': flt(d.invoice_amount),
'payment_amount': payment_amount,
'outstanding_amount': outstanding_amount,
'due_date': d.due_date
'due_date': d.due_date,
'currency': d.currency
})
)
@@ -767,10 +767,10 @@ def get_children(doctype, parent, company, is_root=False):
company_currency = frappe.get_cached_value('Company', company, "default_currency")
for each in acc:
each["company_currency"] = company_currency
each["balance"] = flt(get_balance_on(each.get("value"), in_account_currency=False))
each["balance"] = flt(get_balance_on(each.get("value"), in_account_currency=False, company=company))
if each.account_currency != company_currency:
each["balance_in_account_currency"] = flt(get_balance_on(each.get("value")))
each["balance_in_account_currency"] = flt(get_balance_on(each.get("value"), company=company))
return acc
@@ -817,7 +817,7 @@ def create_payment_gateway_account(gateway):
pass
@frappe.whitelist()
def update_cost_center(docname, cost_center_name, cost_center_number, company):
def update_cost_center(docname, cost_center_name, cost_center_number, company, merge):
'''
Renames the document by adding the number as a prefix to the current name and updates
all transaction where it was present.
@@ -833,7 +833,7 @@ def update_cost_center(docname, cost_center_name, cost_center_number, company):
new_name = get_autoname_with_number(cost_center_number, cost_center_name, docname, company)
if docname != new_name:
frappe.rename_doc("Cost Center", docname, new_name, force=1)
frappe.rename_doc("Cost Center", docname, new_name, force=1, merge=merge)
return new_name
def validate_field_number(doctype_name, docname, number_value, company, field_name):
@@ -877,11 +877,6 @@ def get_coa(doctype, parent, is_root, chart=None):
return accounts
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",

View File

@@ -6,7 +6,7 @@ from __future__ import unicode_literals
import frappe, erpnext, math, json
from frappe import _
from six import string_types
from frappe.utils import flt, add_months, cint, nowdate, getdate, today, date_diff, month_diff, add_days
from frappe.utils import flt, add_months, cint, nowdate, getdate, today, date_diff, month_diff, add_days, get_last_day, get_datetime
from frappe.model.document import Document
from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
from erpnext.assets.doctype.asset.depreciation \
@@ -149,6 +149,10 @@ class Asset(AccountsController):
def make_asset_movement(self):
reference_doctype = 'Purchase Receipt' if self.purchase_receipt else 'Purchase Invoice'
reference_docname = self.purchase_receipt or self.purchase_invoice
transaction_date = getdate(self.purchase_date)
if reference_docname:
posting_date, posting_time = frappe.db.get_value(reference_doctype, reference_docname, ["posting_date", "posting_time"])
transaction_date = get_datetime("{} {}".format(posting_date, posting_time))
assets = [{
'asset': self.name,
'asset_name': self.asset_name,
@@ -160,7 +164,7 @@ class Asset(AccountsController):
'assets': assets,
'purpose': 'Receipt',
'company': self.company,
'transaction_date': getdate(nowdate()),
'transaction_date': transaction_date,
'reference_doctype': reference_doctype,
'reference_name': reference_docname
}).insert()
@@ -407,6 +411,8 @@ class Asset(AccountsController):
row.expected_value_after_useful_life = asset_value_after_full_schedule
def validate_cancellation(self):
if self.status in ("In Maintenance", "Out of Order"):
frappe.throw(_("There are active maintenance or repairs against the asset. You must complete all of them before cancelling the asset."))
if self.status not in ("Submitted", "Partially Depreciated", "Fully Depreciated"):
frappe.throw(_("Asset cannot be cancelled, as it is already {0}").format(self.status))

View File

@@ -58,7 +58,8 @@ def make_depreciation_entry(asset_name, date=None):
"account": accumulated_depreciation_account,
"credit_in_account_currency": d.depreciation_amount,
"reference_type": "Asset",
"reference_name": asset.name
"reference_name": asset.name,
"cost_center": ""
}
debit_entry = {
@@ -196,12 +197,14 @@ def get_gl_entries_on_asset_disposal(asset, selling_amount=0, finance_book=None)
{
"account": fixed_asset_account,
"credit_in_account_currency": asset.gross_purchase_amount,
"credit": asset.gross_purchase_amount
"credit": asset.gross_purchase_amount,
"cost_center": depreciation_cost_center
},
{
"account": accumulated_depr_account,
"debit_in_account_currency": accumulated_depr_amount,
"debit": accumulated_depr_amount
"debit": accumulated_depr_amount,
"cost_center": depreciation_cost_center
}
]

View File

@@ -106,6 +106,7 @@ def update_maintenance_log(asset_maintenance, item_code, item_name, task):
maintenance_log.save()
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_team_members(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.get_values('Maintenance Team Member', { 'parent': filters.get("maintenance_team") })

View File

@@ -11,7 +11,7 @@ from erpnext.assets.doctype.asset_maintenance.asset_maintenance import calculate
class AssetMaintenanceLog(Document):
def validate(self):
if getdate(self.due_date) < getdate(nowdate()):
if getdate(self.due_date) < getdate(nowdate()) and self.maintenance_status not in ["Completed", "Cancelled"]:
self.maintenance_status = "Overdue"
if self.maintenance_status == "Completed" and not self.completion_date:
@@ -41,6 +41,7 @@ class AssetMaintenanceLog(Document):
asset_maintenance_doc.save()
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_maintenance_tasks(doctype, txt, searchfield, start, page_len, filters):
asset_maintenance_tasks = frappe.db.get_values('Asset Maintenance Task', {'parent':filters.get("asset_maintenance")}, 'maintenance_task')
return asset_maintenance_tasks

View File

@@ -1,14 +1,15 @@
frappe.listview_settings['Asset Maintenance Log'] = {
add_fields: ["maintenance_status"],
has_indicator_for_draft: 1,
get_indicator: function(doc) {
if(doc.maintenance_status=="Pending") {
return [__("Pending"), "orange"];
} else if(doc.maintenance_status=="Completed") {
return [__("Completed"), "green"];
} else if(doc.maintenance_status=="Cancelled") {
return [__("Cancelled"), "red"];
} else if(doc.maintenance_status=="Overdue") {
return [__("Overdue"), "red"];
if (doc.maintenance_status=="Planned") {
return [__(doc.maintenance_status), "orange", "status,=," + doc.maintenance_status];
} else if (doc.maintenance_status=="Completed") {
return [__(doc.maintenance_status), "green", "status,=," + doc.maintenance_status];
} else if (doc.maintenance_status=="Cancelled") {
return [__(doc.maintenance_status), "red", "status,=," + doc.maintenance_status];
} else if (doc.maintenance_status=="Overdue") {
return [__(doc.maintenance_status), "red", "status,=," + doc.maintenance_status];
}
}
};

View File

@@ -7,12 +7,6 @@ frappe.provide("erpnext.buying");
frappe.ui.form.on("Purchase Order", {
setup: function(frm) {
frm.custom_make_buttons = {
'Purchase Receipt': 'Receipt',
'Purchase Invoice': 'Invoice',
'Stock Entry': 'Material to Supplier',
'Payment Entry': 'Payment'
}
frm.set_query("reserve_warehouse", "supplied_items", function() {
return {
@@ -36,20 +30,6 @@ frappe.ui.form.on("Purchase Order", {
},
refresh: function(frm) {
if(frm.doc.docstatus === 1 && frm.doc.status !== 'Closed'
&& flt(frm.doc.per_received) < 100 && flt(frm.doc.per_billed) < 100) {
frm.add_custom_button(__('Update Items'), () => {
erpnext.utils.update_child_items({
frm: frm,
child_docname: "items",
child_doctype: "Purchase Order Detail",
cannot_add_row: false,
})
});
}
},
onload: function(frm) {
set_schedule_date(frm);
if (!frm.doc.transaction_date){
@@ -76,6 +56,18 @@ frappe.ui.form.on("Purchase Order Item", {
});
erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend({
setup: function() {
this.frm.custom_make_buttons = {
'Purchase Receipt': 'Receipt',
'Purchase Invoice': 'Invoice',
'Stock Entry': 'Material to Supplier',
'Payment Entry': 'Payment',
}
this._super();
},
refresh: function(doc, cdt, cdn) {
var me = this;
this._super();
@@ -99,6 +91,16 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
if(doc.docstatus == 1) {
if(!in_list(["Closed", "Delivered"], doc.status)) {
if(this.frm.doc.status !== 'Closed' && flt(this.frm.doc.per_received) < 100 && flt(this.frm.doc.per_billed) < 100) {
this.frm.add_custom_button(__('Update Items'), () => {
erpnext.utils.update_child_items({
frm: this.frm,
child_docname: "items",
child_doctype: "Purchase Order Detail",
cannot_add_row: false,
})
});
}
if (this.frm.has_perm("submit")) {
if(flt(doc.per_billed, 6) < 100 || flt(doc.per_received, 6) < 100) {
if (doc.status != "On Hold") {
@@ -123,14 +125,14 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
}
if(doc.status != "Closed") {
if (doc.status != "On Hold") {
if(flt(doc.per_received, 2) < 100 && allow_receipt) {
if(flt(doc.per_received) < 100 && allow_receipt) {
cur_frm.add_custom_button(__('Receipt'), this.make_purchase_receipt, __('Create'));
if(doc.is_subcontracted==="Yes" && me.has_unsupplied_items()) {
cur_frm.add_custom_button(__('Material to Supplier'),
function() { me.make_stock_entry(); }, __("Transfer"));
}
}
if(flt(doc.per_billed, 2) < 100)
if(flt(doc.per_billed) < 100)
cur_frm.add_custom_button(__('Invoice'),
this.make_purchase_invoice, __('Create'));

View File

@@ -1,5 +1,4 @@
{
"actions": [],
"allow_import": 1,
"autoname": "naming_series:",
"creation": "2013-05-21 16:16:39",
@@ -998,6 +997,7 @@
"print_hide": 1
},
{
"collapsible": 1,
"fieldname": "subscription_section",
"fieldtype": "Section Break",
"label": "Subscription Section"
@@ -1056,7 +1056,7 @@
"idx": 105,
"is_submittable": 1,
"links": [],
"modified": "2020-06-12 14:08:11.777120",
"modified": "2020-09-14 14:36:12.418690",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",
@@ -1113,5 +1113,6 @@
"sort_field": "modified",
"sort_order": "DESC",
"timeline_field": "supplier",
"title_field": "title"
"title_field": "supplier",
"track_changes": 1
}

View File

@@ -17,6 +17,8 @@ from erpnext.stock.doctype.material_request.material_request import make_purchas
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
from erpnext.controllers.accounts_controller import update_child_qty_rate
from erpnext.controllers.status_updater import OverAllowanceError
from erpnext.stock.doctype.batch.test_batch import make_new_batch
from erpnext.controllers.buying_controller import get_backflushed_subcontracted_raw_materials
class TestPurchaseOrder(unittest.TestCase):
def test_make_purchase_receipt(self):
@@ -580,7 +582,7 @@ class TestPurchaseOrder(unittest.TestCase):
def test_exploded_items_in_subcontracted(self):
item_code = "_Test Subcontracted FG Item 1"
make_subcontracted_item(item_code)
make_subcontracted_item(item_code=item_code)
po = create_purchase_order(item_code=item_code, qty=1,
is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC")
@@ -602,7 +604,7 @@ 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_subcontracted_item(item_code=item_code)
make_item('Sub Contracted Raw Material 1', {
'is_stock_item': 1,
'is_sub_contracted_item': 1
@@ -661,6 +663,76 @@ class TestPurchaseOrder(unittest.TestCase):
update_backflush_based_on("BOM")
def test_backflushed_based_on_for_multiple_batches(self):
item_code = "_Test Subcontracted FG Item 2"
make_item('Sub Contracted Raw Material 2', {
'is_stock_item': 1,
'is_sub_contracted_item': 1
})
make_subcontracted_item(item_code=item_code, has_batch_no=1, create_new_batch=1,
raw_materials=["Sub Contracted Raw Material 2"])
update_backflush_based_on("Material Transferred for Subcontract")
order_qty = 500
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",
item_code = "Sub Contracted Raw Material 2", qty=552, basic_rate=100)
rm_items = [
{"item_code":item_code,"rm_item_code":"Sub Contracted Raw Material 2","item_name":"_Test Item",
"qty":552,"warehouse":"_Test Warehouse - _TC", "stock_uom":"Nos"}]
rm_item_string = json.dumps(rm_items)
se = frappe.get_doc(make_subcontract_transfer_entry(po.name, rm_item_string))
se.submit()
for batch in ["ABCD1", "ABCD2", "ABCD3", "ABCD4"]:
make_new_batch(batch_id=batch, item_code=item_code)
pr = make_purchase_receipt(po.name)
# partial receipt
pr.get('items')[0].qty = 30
pr.get('items')[0].batch_no = "ABCD1"
purchase_order = po.name
purchase_order_item = po.items[0].name
for batch_no, qty in {"ABCD2": 60, "ABCD3": 70, "ABCD4":40}.items():
pr.append("items", {
"item_code": pr.get('items')[0].item_code,
"item_name": pr.get('items')[0].item_name,
"uom": pr.get('items')[0].uom,
"stock_uom": pr.get('items')[0].stock_uom,
"warehouse": pr.get('items')[0].warehouse,
"conversion_factor": pr.get('items')[0].conversion_factor,
"cost_center": pr.get('items')[0].cost_center,
"rate": pr.get('items')[0].rate,
"qty": qty,
"batch_no": batch_no,
"purchase_order": purchase_order,
"purchase_order_item": purchase_order_item
})
pr.submit()
pr1 = make_purchase_receipt(po.name)
pr1.get('items')[0].qty = 300
pr1.get('items')[0].batch_no = "ABCD1"
pr1.save()
pr_key = ("Sub Contracted Raw Material 2", po.name)
consumed_qty = get_backflushed_subcontracted_raw_materials([po.name]).get(pr_key)
self.assertTrue(pr1.supplied_items[0].consumed_qty > 0)
self.assertTrue(pr1.supplied_items[0].consumed_qty, flt(552.0) - flt(consumed_qty))
update_backflush_based_on("BOM")
def test_advance_payment_entry_unlink_against_purchase_order(self):
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
frappe.db.set_value("Accounts Settings", "Accounts Settings",
@@ -712,27 +784,33 @@ def make_pr_against_po(po, received_qty=0):
pr.submit()
return pr
def make_subcontracted_item(item_code):
def make_subcontracted_item(**args):
from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
if not frappe.db.exists('Item', item_code):
make_item(item_code, {
args = frappe._dict(args)
if not frappe.db.exists('Item', args.item_code):
make_item(args.item_code, {
'is_stock_item': 1,
'is_sub_contracted_item': 1
'is_sub_contracted_item': 1,
'has_batch_no': args.get("has_batch_no") or 0
})
if not frappe.db.exists('Item', "Test Extra Item 1"):
make_item("Test Extra Item 1", {
'is_stock_item': 1,
})
if not args.raw_materials:
if not frappe.db.exists('Item', "Test Extra Item 1"):
make_item("Test Extra Item 1", {
'is_stock_item': 1,
})
if not frappe.db.exists('Item', "Test Extra Item 2"):
make_item("Test Extra Item 2", {
'is_stock_item': 1,
})
if not frappe.db.exists('Item', "Test Extra Item 2"):
make_item("Test Extra Item 2", {
'is_stock_item': 1,
})
if not frappe.db.get_value('BOM', {'item': item_code}, 'name'):
make_bom(item = item_code, raw_materials = ['_Test FG Item', 'Test Extra Item 1'])
args.raw_materials = ['_Test FG Item', 'Test Extra Item 1']
if not frappe.db.get_value('BOM', {'item': args.item_code}, 'name'):
make_bom(item = args.item_code, raw_materials = args.get("raw_materials"))
def update_backflush_based_on(based_on):
doc = frappe.get_doc('Buying Settings')

View File

@@ -166,7 +166,8 @@ frappe.ui.form.on("Request for Quotation",{
{ "fieldtype": "Select", "label": __("Supplier"),
"fieldname": "supplier",
"options": doc.suppliers.map(d => d.supplier),
"reqd": 1 },
"reqd": 1,
"default": doc.suppliers.length === 1 ? doc.suppliers[0].supplier_name : "" },
{ "fieldtype": "Button", "label": __('Create Supplier Quotation'),
"fieldname": "make_supplier_quotation", "cssClass": "btn-primary" },
]

View File

@@ -25,6 +25,7 @@ class RequestforQuotation(BuyingController):
self.validate_duplicate_supplier()
self.validate_supplier_list()
validate_for_items(self)
super(RequestforQuotation, self).set_qty_as_per_stock_uom()
self.update_email_id()
def validate_duplicate_supplier(self):
@@ -50,7 +51,7 @@ class RequestforQuotation(BuyingController):
def validate_email_id(self, args):
if not args.email_id:
frappe.throw(_("Row {0}: For supplier {0} Email Address is required to send email").format(args.idx, args.supplier))
frappe.throw(_("Row {0}: For Supplier {0}, Email Address is Required to Send Email").format(args.idx, args.supplier))
def on_submit(self):
frappe.db.set(self, 'status', 'Submitted')
@@ -153,7 +154,7 @@ class RequestforQuotation(BuyingController):
sender=sender,attachments = attachments, send_email=True,
doctype=self.doctype, name=self.name)["name"]
frappe.msgprint(_("Email sent to supplier {0}").format(data.supplier))
frappe.msgprint(_("Email Sent to Supplier {0}").format(data.supplier))
def get_attachments(self):
attachments = [d.name for d in get_attachments(self.doctype, self.name)]
@@ -192,7 +193,7 @@ def send_supplier_emails(rfq_name):
def check_portal_enabled(reference_doctype):
if not frappe.db.get_value('Portal Menu Item',
{'reference_doctype': reference_doctype}, 'enabled'):
frappe.throw(_("Request for Quotation is disabled to access from portal, for more check portal settings."))
frappe.throw(_("The Access to Request for Quotation From Portal is Disabled. To Allow Access, Enable it in Portal Settings."))
def get_list_context(context=None):
from erpnext.controllers.website_list_for_contact import get_list_context
@@ -205,6 +206,8 @@ def get_list_context(context=None):
})
return list_context
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_supplier_contacts(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql("""select `tabContact`.name from `tabContact`, `tabDynamic Link`
where `tabDynamic Link`.link_doctype = 'Supplier' and (`tabDynamic Link`.link_name=%(name)s
@@ -258,7 +261,7 @@ def create_supplier_quotation(doc):
sq_doc.flags.ignore_permissions = True
sq_doc.run_method("set_missing_values")
sq_doc.save()
frappe.msgprint(_("Supplier Quotation {0} created").format(sq_doc.name))
frappe.msgprint(_("Supplier Quotation {0} Created").format(sq_doc.name))
return sq_doc.name
except Exception:
return None
@@ -278,6 +281,7 @@ def create_rfq_items(sq_doc, supplier, data):
"description": data.description,
"qty": data.qty,
"rate": data.rate,
"conversion_factor": data.conversion_factor if data.conversion_factor else None,
"supplier_part_no": frappe.db.get_value("Item Supplier", {'parent': data.item_code, 'supplier': supplier}, "supplier_part_no"),
"warehouse": data.warehouse or '',
"request_for_quotation_item": data.name,

View File

@@ -6,12 +6,14 @@ from __future__ import unicode_literals
import unittest
import frappe
from erpnext.templates.pages.rfq import check_supplier_has_docname_access
from frappe.utils import nowdate
from erpnext.stock.doctype.item.test_item import make_item
from erpnext.templates.pages.rfq import check_supplier_has_docname_access
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import create_supplier_quotation
class TestRequestforQuotation(unittest.TestCase):
def test_quote_status(self):
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation
rfq = make_request_for_quotation()
self.assertEqual(rfq.get('suppliers')[0].quote_status, 'Pending')
@@ -31,7 +33,6 @@ class TestRequestforQuotation(unittest.TestCase):
self.assertEqual(rfq.get('suppliers')[1].quote_status, 'No Quote')
def test_make_supplier_quotation(self):
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation
rfq = make_request_for_quotation()
sq = make_supplier_quotation(rfq.name, rfq.get('suppliers')[0].supplier)
@@ -51,15 +52,13 @@ class TestRequestforQuotation(unittest.TestCase):
self.assertEqual(sq1.get('items')[0].qty, 5)
def test_make_supplier_quotation_with_special_characters(self):
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import make_supplier_quotation
frappe.delete_doc_if_exists("Supplier", "_Test Supplier '1", force=1)
supplier = frappe.new_doc("Supplier")
supplier.supplier_name = "_Test Supplier '1"
supplier.supplier_group = "_Test Supplier Group"
supplier.insert()
rfq = make_request_for_quotation(supplier_wt_appos)
rfq = make_request_for_quotation(supplier_data=supplier_wt_appos)
sq = make_supplier_quotation(rfq.name, supplier_wt_appos[0].get("supplier"))
sq.submit()
@@ -76,7 +75,6 @@ class TestRequestforQuotation(unittest.TestCase):
frappe.form_dict.name = None
def test_make_supplier_quotation_from_portal(self):
from erpnext.buying.doctype.request_for_quotation.request_for_quotation import create_supplier_quotation
rfq = make_request_for_quotation()
rfq.get('items')[0].rate = 100
rfq.supplier = rfq.suppliers[0].supplier
@@ -90,12 +88,34 @@ class TestRequestforQuotation(unittest.TestCase):
self.assertEqual(supplier_quotation_doc.get('items')[0].qty, 5)
self.assertEqual(supplier_quotation_doc.get('items')[0].amount, 500)
def test_make_multi_uom_supplier_quotation(self):
item_code = "_Test Multi UOM RFQ Item"
if not frappe.db.exists('Item', item_code):
item = make_item(item_code, {'stock_uom': '_Test UOM'})
row = item.append('uoms', {
'uom': 'Kg',
'conversion_factor': 2
})
row.db_update()
def make_request_for_quotation(supplier_data=None):
rfq = make_request_for_quotation(item_code="_Test Multi UOM RFQ Item", uom="Kg", conversion_factor=2)
rfq.get('items')[0].rate = 100
rfq.supplier = rfq.suppliers[0].supplier
self.assertEqual(rfq.items[0].stock_qty, 10)
supplier_quotation_name = create_supplier_quotation(rfq)
supplier_quotation = frappe.get_doc('Supplier Quotation', supplier_quotation_name)
self.assertEqual(supplier_quotation.items[0].qty, 5)
self.assertEqual(supplier_quotation.items[0].stock_qty, 10)
def make_request_for_quotation(**args):
"""
:param supplier_data: List containing supplier data
"""
supplier_data = supplier_data if supplier_data else get_supplier_data()
args = frappe._dict(args)
supplier_data = args.get("supplier_data") if args.get("supplier_data") else get_supplier_data()
rfq = frappe.new_doc('Request for Quotation')
rfq.transaction_date = nowdate()
rfq.status = 'Draft'
@@ -106,11 +126,13 @@ def make_request_for_quotation(supplier_data=None):
rfq.append('suppliers', data)
rfq.append("items", {
"item_code": "_Test Item",
"item_code": args.item_code or "_Test Item",
"description": "_Test Item",
"uom": "_Test UOM",
"qty": 5,
"warehouse": "_Test Warehouse - _TC",
"uom": args.uom or "_Test UOM",
"stock_uom": args.stock_uom or "_Test UOM",
"qty": args.qty or 5,
"conversion_factor": args.conversion_factor or 1.0,
"warehouse": args.warehouse or "_Test Warehouse - _TC",
"schedule_date": nowdate()
})

View File

@@ -1,4 +1,5 @@
{
"actions": [],
"autoname": "hash",
"creation": "2016-02-25 08:04:02.452958",
"doctype": "DocType",
@@ -9,6 +10,7 @@
"supplier_part_no",
"column_break_3",
"item_name",
"schedule_date",
"section_break_5",
"description",
"item_group",
@@ -18,9 +20,11 @@
"image_view",
"quantity",
"qty",
"stock_uom",
"col_break2",
"schedule_date",
"uom",
"conversion_factor",
"stock_qty",
"warehouse_and_reference",
"warehouse",
"project_name",
@@ -33,7 +37,7 @@
"fields": [
{
"bold": 1,
"columns": 3,
"columns": 2,
"fieldname": "item_code",
"fieldtype": "Link",
"in_list_view": 1,
@@ -98,7 +102,7 @@
{
"fieldname": "quantity",
"fieldtype": "Section Break",
"label": "Quantity"
"label": "Quantity & Stock"
},
{
"bold": 1,
@@ -129,12 +133,12 @@
{
"fieldname": "uom",
"fieldtype": "Link",
"in_list_view": 1,
"label": "UOM",
"oldfieldname": "uom",
"oldfieldtype": "Link",
"options": "UOM",
"print_width": "100px",
"read_only": 1,
"reqd": 1,
"width": "100px"
},
@@ -144,7 +148,7 @@
"label": "Warehouse and Reference"
},
{
"columns": 3,
"columns": 2,
"fieldname": "warehouse",
"fieldtype": "Link",
"in_list_view": 1,
@@ -202,6 +206,7 @@
},
{
"allow_on_submit": 1,
"default": "0",
"fieldname": "page_break",
"fieldtype": "Check",
"label": "Page Break",
@@ -219,10 +224,36 @@
{
"fieldname": "section_break_23",
"fieldtype": "Section Break"
},
{
"fieldname": "stock_uom",
"fieldtype": "Link",
"label": "Stock UOM",
"options": "UOM",
"print_hide": 1,
"read_only": 1,
"reqd": 1
},
{
"fieldname": "conversion_factor",
"fieldtype": "Float",
"label": "UOM Conversion Factor",
"print_hide": 1,
"read_only": 1,
"reqd": 1
},
{
"fieldname": "stock_qty",
"fieldtype": "Float",
"label": "Qty as per Stock UOM",
"no_copy": 1,
"print_hide": 1,
"read_only": 1
}
],
"istable": 1,
"modified": "2019-05-01 17:50:23.703801",
"links": [],
"modified": "2020-06-12 19:10:36.333441",
"modified_by": "Administrator",
"module": "Buying",
"name": "Request for Quotation Item",

View File

@@ -97,7 +97,7 @@
{
"fieldname": "default_bank_account",
"fieldtype": "Link",
"label": "Default Bank Account",
"label": "Default Company Bank Account",
"options": "Bank Account"
},
{
@@ -385,7 +385,7 @@
"idx": 370,
"image_field": "image",
"links": [],
"modified": "2020-03-17 09:48:30.578242",
"modified": "2020-06-17 23:28:30",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier",

View File

@@ -178,6 +178,7 @@ def make_all_scorecards(docname):
period_card = make_supplier_scorecard(docname, None)
period_card.start_date = start_date
period_card.end_date = end_date
period_card.insert(ignore_permissions=True)
period_card.submit()
scp_count = scp_count + 1
if start_date < first_start_date:

View File

@@ -106,7 +106,7 @@ def make_supplier_scorecard(source_name, target_doc=None):
"doctype": "Supplier Scorecard Scoring Criteria",
"postprocess": update_criteria_fields,
}
}, target_doc, post_process)
}, target_doc, post_process, ignore_permissions=True)
return doc

View File

@@ -67,4 +67,5 @@ class TestProcurementTracker(unittest.TestCase):
"expected_delivery_date": date_obj,
"actual_delivery_date": date_obj
}
return expected_data

View File

@@ -12,7 +12,6 @@ from erpnext.stock.doctype.item.item import validate_end_of_life
def update_last_purchase_rate(doc, is_submit):
"""updates last_purchase_rate in item table for each item"""
import frappe.utils
this_purchase_date = frappe.utils.getdate(doc.get('posting_date') or doc.get('transaction_date'))
@@ -23,7 +22,7 @@ def update_last_purchase_rate(doc, is_submit):
# compare last purchase date and this transaction's date
last_purchase_rate = None
if last_purchase_details and \
(last_purchase_details.purchase_date > this_purchase_date):
(doc.get('docstatus') == 2 or last_purchase_details.purchase_date > this_purchase_date):
last_purchase_rate = last_purchase_details['base_net_rate']
elif is_submit == 1:
# even if this transaction is the latest one, it should be submitted

View File

@@ -0,0 +1,66 @@
## ERPNext v12.11.0 Release Note
- Enabled translation on html files in LMS [Proposal] ([#21582](https://github.com/frappe/erpnext/pull/21582))
- Multi UOM support in Request for Quotation ([#22250](https://github.com/frappe/erpnext/pull/22250))
- Exploded Item Rate ([#22816](https://github.com/frappe/erpnext/pull/22816))
- asset maintenance fixes ([#21277](https://github.com/frappe/erpnext/pull/21277))
- Error due to comma in Pricing rule name ([#22927](https://github.com/frappe/erpnext/pull/22927))
- Set default reference Id for "On Previous Row Amount" and "On Previous Row Total" ([#22387](https://github.com/frappe/erpnext/pull/22387))
- fix(Education): course wise assessment report labels ([#22805](https://github.com/frappe/erpnext/pull/22805))
- ewaybill json had json dump of json dump, and other related fixes ([#22656](https://github.com/frappe/erpnext/pull/22656))
- Unable to change link from new lead to existing customer ([#22795](https://github.com/frappe/erpnext/pull/22795))
- Incorrect delivered qty in Supplier-Wise Sales Analytics ([#22642](https://github.com/frappe/erpnext/pull/22642))
- Dont merge items if both exist in stock reco ([#22784](https://github.com/frappe/erpnext/pull/22784))
- Status error in purchase invoice ([#22389](https://github.com/frappe/erpnext/pull/22389))
- Whitelist all query functions for search widget ([#22606](https://github.com/frappe/erpnext/pull/22606))
- SQL query in accounts receivable, payable reports ([#22891](https://github.com/frappe/erpnext/pull/22891))
- In POS serial no popup coming two times ([#22268](https://github.com/frappe/erpnext/pull/22268))
- Cannot cancel assets with repair pending (bp #22440) ([#22453](https://github.com/frappe/erpnext/pull/22453))
- Take parent cost center for child if no cost center at child ([#22496](https://github.com/frappe/erpnext/pull/22496))
- Handle nonetype issue for packed items ([#22493](https://github.com/frappe/erpnext/pull/22493))
- Cannot cancel assets with repair pending ([#22440](https://github.com/frappe/erpnext/pull/22440))
- Show or hide section or attributes depending on other attributes… ([#22933](https://github.com/frappe/erpnext/pull/22933))
- Insert Supplier Group via List View (bp #22403) ([#22407](https://github.com/frappe/erpnext/pull/22407))
- Skip Progress and Completed by fields on Task Duplication ([#22640](https://github.com/frappe/erpnext/pull/22640))
- Incorrect variable used while adding new item in the submitted Sales Order ([#22308](https://github.com/frappe/erpnext/pull/22308))
- Incorrect stock value in return case ([#22528](https://github.com/frappe/erpnext/pull/22528))
- staffing Plan validation ([#22379](https://github.com/frappe/erpnext/pull/22379))
- Cancellation of accounting transactions within closed accounting period ([#22986](https://github.com/frappe/erpnext/pull/22986))
- Not able to submit sales invoice ([#22699](https://github.com/frappe/erpnext/pull/22699))
- Offline pos not working for special character item ([#22391](https://github.com/frappe/erpnext/pull/22391))
- Due to decimal issue make purchase receipt button not showing in Purchase Order ([#22643](https://github.com/frappe/erpnext/pull/22643))
- Stock Reconciliation Invalid Quantity for Batched Item ([#22716](https://github.com/frappe/erpnext/pull/22716))
- Quality procedure fixes ([#22287](https://github.com/frappe/erpnext/pull/22287))
- Set label if domains is set ([#22523](https://github.com/frappe/erpnext/pull/22523))
- Update item tax only if item code available ([#22575](https://github.com/frappe/erpnext/pull/22575))
- Inclusive tax based on item quantity ([#23015](https://github.com/frappe/erpnext/pull/23015))
- Quotation lost reason options fix ([#23016](https://github.com/frappe/erpnext/pull/23016))
- GSTR 1 report for exports without payment of Tax ([#22968](https://github.com/frappe/erpnext/pull/22968))
- Period list fixes in financial statements ([#22679](https://github.com/frappe/erpnext/pull/22679))
- Don't set asset maintenance log status as Overdue when Completed or Cancelled ([#23012](https://github.com/frappe/erpnext/pull/23012))
- Update state code and union territory for Daman and Diu ([#22989](https://github.com/frappe/erpnext/pull/22989))
- Set Root as Parent if no parent in new tree view node ([#22507](https://github.com/frappe/erpnext/pull/22507))
- Serial no / batch no Popup is coming for the non serialized items ([#22362](https://github.com/frappe/erpnext/pull/22362))
- update shopify api version ([#22284](https://github.com/frappe/erpnext/pull/22284))
- Unable to create batched item ([#22332](https://github.com/frappe/erpnext/pull/22332))
- Incorrect balance qty in stock ledger report ([#22649](https://github.com/frappe/erpnext/pull/22649))
- Setup status indicators for Job Offer and Job Applicant (v12) ([#22444](https://github.com/frappe/erpnext/pull/22444))
- Set half day date None if half day is unchecked ([#22905](https://github.com/frappe/erpnext/pull/22905))
- Completed qty not updated in work order ([#22372](https://github.com/frappe/erpnext/pull/22372))
- Handling Empty tables in Production Plan ([#22469](https://github.com/frappe/erpnext/pull/22469))
- Fetch project-related info in Timesheet (v12) ([#22422](https://github.com/frappe/erpnext/pull/22422))
- Pricing Rule breaks if no item_code ([#22653](https://github.com/frappe/erpnext/pull/22653))
- Made "Subscription Section", "Auto Repeat" and Hub Publishing" c… ([#22535](https://github.com/frappe/erpnext/pull/22535))
- Update Packed Items via Update Items in SO ([#22404](https://github.com/frappe/erpnext/pull/22404))
- Do not add tax amount in grand total for reverse charge invoices ([#22686](https://github.com/frappe/erpnext/pull/22686))
- Other charges on income tax in salary slip ([#22798](https://github.com/frappe/erpnext/pull/22798))
- Serial No Rename does not affect Stock Ledger Entry ([#22780](https://github.com/frappe/erpnext/pull/22780))
- Quotation list view blank if quotation_to field not set as a standard filter ([#22659](https://github.com/frappe/erpnext/pull/22659))
- cannot change customer fields if credit exhausted ([#22838](https://github.com/frappe/erpnext/pull/22838))
- Project link not set in accounts other than profit and loss accounts ([#22049](https://github.com/frappe/erpnext/pull/22049))
- Bank Clearance of POS purchase invoice ([#22884](https://github.com/frappe/erpnext/pull/22884))
- Multiple GST fixes ([#22730](https://github.com/frappe/erpnext/pull/22730))
- Add default cost center in payment reconciliation JV ([#22930](https://github.com/frappe/erpnext/pull/22930))
- Do not copy Item Tax template from SO to PO ([#22324](https://github.com/frappe/erpnext/pull/22324))
- Tax amounts in HSN Wise Outward summary ([#22755](https://github.com/frappe/erpnext/pull/22755))
- Multi currency payment reconciliation ([#22928](https://github.com/frappe/erpnext/pull/22928))

View File

@@ -0,0 +1,50 @@
## ERPNext v12.12.0 Release Note
### Fixes and Enhancements
- Unable to submit reverse charge invoice ([#23103](https://github.com/frappe/erpnext/pull/23103))
- Total calculations for multi-currency RCM invoices ([#23070](https://github.com/frappe/erpnext/pull/23070))
- Cannot search items in offline pos ([#23083](https://github.com/frappe/erpnext/pull/23083))
- Check Company in Payment Entry before selecting values ([#23421](https://github.com/frappe/erpnext/pull/23421))
- Set cost center for payroll payable account ([#23223](https://github.com/frappe/erpnext/pull/23223))
- Download Required Materials not working for production plan ([#23404](https://github.com/frappe/erpnext/pull/23404))
- Not able to make material request from SO ([#23262](https://github.com/frappe/erpnext/pull/23262))
- Profit and loss report not working ([#23254](https://github.com/frappe/erpnext/pull/23254))
- Get Items from Product Bundle in Purchase Order ([#23228](https://github.com/frappe/erpnext/pull/23228))
- Pricing Rule encoding fixed ([#23146](https://github.com/frappe/erpnext/pull/23146))
- Create Opoortunity without Default Company from Email ([#23098](https://github.com/frappe/erpnext/pull/23098))
- Incorrect consumed qty if raw material with batch ([#23390](https://github.com/frappe/erpnext/pull/23390))
- Book loss amount in the COGS instead of stock received but not billed ([#23414](https://github.com/frappe/erpnext/pull/23414))
- Conversion factor for BOM exploded item rate ([#23153](https://github.com/frappe/erpnext/pull/23153))
- Don't overwrite patient appointment duration if already specified ([#23169](https://github.com/frappe/erpnext/pull/23169))
- General Ledger filter validation ([#23230](https://github.com/frappe/erpnext/pull/23230))
- BOM Update Tool failing due to Too Many Writes error ([#23191](https://github.com/frappe/erpnext/pull/23191))
- Check for Company before trying to fetch party details ([#23206](https://github.com/frappe/erpnext/pull/23206))
- Handled condition if staffing isn't created ([#23057](https://github.com/frappe/erpnext/pull/23057))
- Unlink and delete batch created from stock reconciliation on cancel ([#23192](https://github.com/frappe/erpnext/pull/23192))
- Mixed condition pricing rule not working on js side ([#23160](https://github.com/frappe/erpnext/pull/23160))
- Form dashboard showing wrong balance ([#23131](https://github.com/frappe/erpnext/pull/23131))
- Attendance calendar map fix ([#23247](https://github.com/frappe/erpnext/pull/23247))
- Misleading filters on Item tax Template Link field ([#23246](https://github.com/frappe/erpnext/pull/23246))
- Leave application status fix ([#23043](https://github.com/frappe/erpnext/pull/23043))
- Stock qty in HSN wise outward summary ([#23252](https://github.com/frappe/erpnext/pull/23252))
- Online pos print not working ([#23378](https://github.com/frappe/erpnext/pull/23378))
- GLE for subcontracted PR is fg item rate is zero ([#23117](https://github.com/frappe/erpnext/pull/23117))
- User-created manual job card not linking job card operation with work order operation ([#23126](https://github.com/frappe/erpnext/pull/23126))
- Stock reconciliation, incorrect serial nos fetched in the current serial no field ([#23368](https://github.com/frappe/erpnext/pull/23368))
- Incorrect stock balance issue for batched item ([#23186](https://github.com/frappe/erpnext/pull/23186))
- Showing a negative balance in expired leaves ([#23428](https://github.com/frappe/erpnext/pull/23428))
- Production plan incorrect work order qty ([#23264](https://github.com/frappe/erpnext/pull/23264))
- Validate Job offer against vacancies ([#23107](https://github.com/frappe/erpnext/pull/23107))
- Incorrect completed qty against the operation in a work order if the workstation is different in job card ([#23215](https://github.com/frappe/erpnext/pull/23215))
- Incorrect job card timer issue ([#23226](https://github.com/frappe/erpnext/pull/23226))
- Consumed qty logic for subcontracted raw materials ([#23314](https://github.com/frappe/erpnext/pull/23314))
- Update paid amount for pos return ([#23124](https://github.com/frappe/erpnext/pull/23124))
- Asset movement date for backdated asset entry ([#23300](https://github.com/frappe/erpnext/pull/23300))
- JSON download for HSN wise outward summary ([#23081](https://github.com/frappe/erpnext/pull/23081))
- Purchase order updates are not tracked ([#23325](https://github.com/frappe/erpnext/pull/23325))
- Allowed to rename lead ([#23113](https://github.com/frappe/erpnext/pull/23113))
- Add company in list fields to fetch for Expense Claim ([#23021](https://github.com/frappe/erpnext/pull/23021))
- Events not deleted on canceling maintenance schedule ([#23219](https://github.com/frappe/erpnext/pull/23219))
- Update items in Sales/Purchase Order with workflow ([#23324](https://github.com/frappe/erpnext/pull/23324))
- Lock row in subquery while setting delivered qty ([#23101](https://github.com/frappe/erpnext/pull/23101))

View File

@@ -7,6 +7,7 @@ import json
from frappe import _, throw
from frappe.utils import (today, flt, cint, fmt_money, formatdate,
getdate, add_days, add_months, get_last_day, nowdate, get_link_to_form)
from frappe.model.workflow import get_workflow_name, is_transition_condition_satisfied, WorkflowPermissionError
from erpnext.stock.get_item_details import get_conversion_factor, get_item_details
from erpnext.setup.utils import get_exchange_rate
from erpnext.accounts.utils import get_fiscal_years, validate_fiscal_year, get_account_currency
@@ -20,6 +21,7 @@ from erpnext.exceptions import InvalidCurrency
from six import text_type
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_accounting_dimensions
from erpnext.stock.get_item_details import get_item_warehouse
from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
force_item_fields = ("item_group", "brand", "stock_uom", "is_fixed_asset", "item_tax_rate", "pricing_rules")
@@ -324,7 +326,7 @@ class AccountsController(TransactionBase):
apply_pricing_rule_for_free_items(self, pricing_rule_args.get('free_item_data'))
elif pricing_rule_args.get("validate_applied_rule"):
for pricing_rule in get_applied_pricing_rules(item):
for pricing_rule in get_applied_pricing_rules(item.get('pricing_rules')):
pricing_rule_doc = frappe.get_cached_doc("Pricing Rule", pricing_rule)
for field in ['discount_percentage', 'discount_amount', 'rate']:
if item.get(field) < pricing_rule_doc.get(field):
@@ -953,7 +955,7 @@ def validate_inclusive_tax(tax, doc):
# all rows about the reffered tax should be inclusive
_on_previous_row_error("1 - %d" % (tax.row_id,))
elif tax.get("category") == "Valuation":
frappe.throw(_("Valuation type charges can not marked as Inclusive"))
frappe.throw(_("Valuation type charges can not be marked as Inclusive"))
def set_balance_in_account_currency(gl_dict, account_currency=None, conversion_rate=None, company_currency=None):
@@ -1010,6 +1012,7 @@ def get_advance_journal_entries(party_type, party, party_account, amount_field,
def get_advance_payment_entries(party_type, party, party_account, order_doctype,
order_list=None, include_unallocated=True, against_all_orders=False, limit=None):
party_account_field = "paid_from" if party_type == "Customer" else "paid_to"
currency_field = "paid_from_account_currency" if party_type == "Customer" else "paid_to_account_currency"
payment_type = "Receive" if party_type == "Customer" else "Pay"
payment_entries_against_order, unallocated_payment_entries = [], []
limit_cond = "limit %s" % limit if limit else ""
@@ -1026,14 +1029,15 @@ def get_advance_payment_entries(party_type, party, party_account, order_doctype,
select
"Payment Entry" as reference_type, t1.name as reference_name,
t1.remarks, t2.allocated_amount as amount, t2.name as reference_row,
t2.reference_name as against_order, t1.posting_date
t2.reference_name as against_order, t1.posting_date,
t1.{0} as currency
from `tabPayment Entry` t1, `tabPayment Entry Reference` t2
where
t1.name = t2.parent and t1.{0} = %s and t1.payment_type = %s
t1.name = t2.parent and t1.{1} = %s and t1.payment_type = %s
and t1.party_type = %s and t1.party = %s and t1.docstatus = 1
and t2.reference_doctype = %s {1}
order by t1.posting_date {2}
""".format(party_account_field, reference_condition, limit_cond),
and t2.reference_doctype = %s {2}
order by t1.posting_date {3}
""".format(currency_field, party_account_field, reference_condition, limit_cond),
[party_account, payment_type, party_type, party,
order_doctype] + order_list, as_dict=1)
@@ -1160,7 +1164,7 @@ def set_purchase_order_defaults(parent_doctype, parent_doctype_name, child_docna
child_item.base_amount = 1 # Initiallize value will update in parent validation
return child_item
def check_and_delete_children(parent, data):
def validate_and_delete_children(parent, data):
deleted_children = []
updated_item_names = [d.get("docname") for d in data]
for item in parent.items:
@@ -1187,18 +1191,40 @@ def check_and_delete_children(parent, data):
@frappe.whitelist()
def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, child_docname="items"):
def check_permissions(doc, perm_type='create'):
def check_doc_permissions(doc, perm_type='create'):
try:
doc.check_permission(perm_type)
except:
action = "add" if perm_type == 'create' else "update"
frappe.throw(_("You do not have permissions to {} items in a Sales Order.").format(action), title=_("Insufficient Permissions"))
except frappe.PermissionError:
actions = { 'create': 'add', 'write': 'update'}
frappe.throw(_("You do not have permissions to {} items in a {}.")
.format(actions[perm_type], parent_doctype), title=_("Insufficient Permissions"))
def validate_workflow_conditions(doc):
workflow = get_workflow_name(doc.doctype)
if not workflow:
return
workflow_doc = frappe.get_doc("Workflow", workflow)
current_state = doc.get(workflow_doc.workflow_state_field)
roles = frappe.get_roles()
transitions = []
for transition in workflow_doc.transitions:
if transition.next_state == current_state and transition.allowed in roles:
if not is_transition_condition_satisfied(transition, doc):
continue
transitions.append(transition.as_dict())
if not transitions:
frappe.throw(
_("You are not allowed to update as per the conditions set in {} Workflow.").format(get_link_to_form("Workflow", workflow)),
title=_("Insufficient Permissions")
)
def get_new_child_item(item_row):
if parent_doctype == "Sales Order":
return set_sales_order_defaults(parent_doctype, parent_doctype_name, child_docname, item_row)
if parent_doctype == "Purchase Order":
return set_purchase_order_defaults(parent_doctype, parent_doctype_name, child_docname, item_row)
new_child_function = set_sales_order_defaults if parent_doctype == "Sales Order" else set_purchase_order_defaults
return new_child_function(parent_doctype, parent_doctype_name, child_docname, item_row)
def validate_quantity(child_item, d):
if parent_doctype == "Sales Order" and flt(d.get("qty")) < flt(child_item.delivered_qty):
@@ -1212,16 +1238,17 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
sales_doctypes = ['Sales Order', 'Sales Invoice', 'Delivery Note', 'Quotation']
parent = frappe.get_doc(parent_doctype, parent_doctype_name)
check_and_delete_children(parent, data)
check_doc_permissions(parent, 'write')
validate_and_delete_children(parent, data)
for d in data:
new_child_flag = False
if not d.get("docname"):
new_child_flag = True
check_permissions(parent, 'create')
check_doc_permissions(parent, 'create')
child_item = get_new_child_item(d)
else:
check_permissions(parent, 'write')
check_doc_permissions(parent, 'write')
child_item = frappe.get_doc(parent_doctype + ' Item', d.get("docname"))
prev_rate, new_rate = flt(child_item.get("rate")), flt(d.get("rate"))
@@ -1298,6 +1325,7 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
parent.set_qty_as_per_stock_uom()
parent.calculate_taxes_and_totals()
if parent_doctype == "Sales Order":
make_packing_list(parent)
parent.set_gross_profit()
frappe.get_doc('Authorization Control').validate_approving_authority(parent.doctype,
parent.company, parent.base_grand_total)
@@ -1327,6 +1355,9 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
parent.update_prevdoc_status('submit')
parent.update_delivery_status()
parent.reload()
validate_workflow_conditions(parent)
parent.update_blanket_order()
parent.update_billing_percentage()
parent.set_status()

View File

@@ -5,7 +5,7 @@ from __future__ import unicode_literals
import frappe
from frappe import _, msgprint
from frappe.utils import flt,cint, cstr, getdate
from six import iteritems
from erpnext.accounts.party import get_party_details
from erpnext.stock.get_item_details import get_conversion_factor
from erpnext.buying.utils import validate_for_items, update_last_purchase_rate
@@ -182,7 +182,7 @@ class BuyingController(StockController):
if item.item_code and item.qty and item.item_code in stock_and_asset_items:
item_proportion = flt(item.base_net_amount) / stock_and_asset_items_amount if stock_and_asset_items_amount \
else flt(item.qty) / stock_and_asset_items_qty
if i == (last_item_idx - 1):
item.item_tax_amount = flt(valuation_amount_adjustment,
self.precision("item_tax_amount", item))
@@ -267,6 +267,9 @@ class BuyingController(StockController):
qty_to_be_received_map = get_qty_to_be_received(purchase_orders)
for item in self.get('items'):
if not item.purchase_order:
continue
# reset raw_material cost
item.rm_supp_cost = 0
@@ -279,11 +282,17 @@ class BuyingController(StockController):
fg_yet_to_be_received = qty_to_be_received_map.get(item_key)
if not fg_yet_to_be_received:
frappe.throw(_("Row #{0}: Item {1} is already fully received in Purchase Order {2}")
.format(item.idx, frappe.bold(item.item_code),
frappe.utils.get_link_to_form("Purchase Order", item.purchase_order)),
title=_("Limit Crossed"))
transferred_batch_qty_map = get_transferred_batch_qty_map(item.purchase_order, item.item_code)
backflushed_batch_qty_map = get_backflushed_batch_qty_map(item.purchase_order, item.item_code)
# backflushed_batch_qty_map = get_backflushed_batch_qty_map(item.purchase_order, item.item_code)
for raw_material in transferred_raw_materials + non_stock_items:
rm_item_key = '{}{}'.format(raw_material.rm_item_code, item.purchase_order)
rm_item_key = (raw_material.rm_item_code, item.purchase_order)
raw_material_data = backflushed_raw_materials_map.get(rm_item_key, {})
consumed_qty = raw_material_data.get('qty', 0)
@@ -312,8 +321,10 @@ class BuyingController(StockController):
set_serial_nos(raw_material, consumed_serial_nos, qty)
if raw_material.batch_nos:
backflushed_batch_qty_map = raw_material_data.get('consumed_batch', {})
batches_qty = get_batches_with_qty(raw_material.rm_item_code, raw_material.main_item_code,
qty, transferred_batch_qty_map, backflushed_batch_qty_map)
qty, transferred_batch_qty_map, backflushed_batch_qty_map, item.purchase_order)
for batch_data in batches_qty:
qty = batch_data['qty']
raw_material.batch_no = batch_data['batch']
@@ -325,6 +336,10 @@ class BuyingController(StockController):
rm = self.append('supplied_items', {})
rm.update(raw_material_data)
if not rm.main_item_code:
rm.main_item_code = fg_item_doc.item_code
rm.reference_name = fg_item_doc.name
rm.required_qty = qty
rm.consumed_qty = qty
@@ -540,9 +555,19 @@ class BuyingController(StockController):
"serial_no": cstr(d.serial_no).strip()
})
if self.is_return:
original_incoming_rate = frappe.db.get_value("Stock Ledger Entry",
{"voucher_type": "Purchase Receipt", "voucher_no": self.return_against,
"item_code": d.item_code}, "incoming_rate")
filters = {
"voucher_type": self.doctype,
"voucher_no": self.return_against,
"item_code": d.item_code
}
if (self.doctype == "Purchase Invoice" and self.update_stock
and d.get("purchase_invoice_item")):
filters["voucher_detail_no"] = d.purchase_invoice_item
elif self.doctype == "Purchase Receipt" and d.get("purchase_receipt_item"):
filters["voucher_detail_no"] = d.purchase_receipt_item
original_incoming_rate = frappe.db.get_value("Stock Ledger Entry", filters, "incoming_rate")
sle.update({
"outgoing_rate": original_incoming_rate
@@ -728,7 +753,7 @@ class BuyingController(StockController):
if delete_asset and is_auto_create_enabled:
# need to delete movements to delete assets otherwise throws link exists error
movements = frappe.db.sql(
"""SELECT asm.name
"""SELECT asm.name
FROM `tabAsset Movement` asm, `tabAsset Movement Item` asm_item
WHERE asm_item.parent=asm.name and asm_item.asset=%s""", asset.name, as_dict=1)
for movement in movements:
@@ -825,7 +850,7 @@ def get_subcontracted_raw_materials_from_se(purchase_order, fg_item):
AND se.purpose='Send to Subcontractor'
AND se.purchase_order = %s
AND IFNULL(sed.t_warehouse, '') != ''
AND sed.subcontracted_item = %s
AND IFNULL(sed.subcontracted_item, '') in ('', %s)
GROUP BY sed.item_code, sed.subcontracted_item
"""
raw_materials = frappe.db.multisql({
@@ -842,39 +867,49 @@ def get_subcontracted_raw_materials_from_se(purchase_order, fg_item):
return raw_materials
def get_backflushed_subcontracted_raw_materials(purchase_orders):
common_query = """
SELECT
CONCAT(prsi.rm_item_code, pri.purchase_order) AS item_key,
SUM(prsi.consumed_qty) AS qty,
{serial_no_concat_syntax} AS serial_nos,
{batch_no_concat_syntax} AS batch_nos
FROM `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pri, `tabPurchase Receipt Item Supplied` prsi
WHERE
pr.name = pri.parent
AND pr.name = prsi.parent
AND pri.purchase_order IN %s
AND pri.item_code = prsi.main_item_code
AND pr.docstatus = 1
GROUP BY prsi.rm_item_code, pri.purchase_order
"""
purchase_receipts = frappe.get_all("Purchase Receipt Item",
fields = ["purchase_order", "item_code", "name", "parent"],
filters={"docstatus": 1, "purchase_order": ("in", list(purchase_orders))})
backflushed_raw_materials = frappe.db.multisql({
'mariadb': common_query.format(
serial_no_concat_syntax="GROUP_CONCAT(prsi.serial_no)",
batch_no_concat_syntax="GROUP_CONCAT(prsi.batch_no)"
),
'postgres': common_query.format(
serial_no_concat_syntax="STRING_AGG(prsi.serial_no, ',')",
batch_no_concat_syntax="STRING_AGG(prsi.batch_no, ',')"
)
}, (purchase_orders, ), as_dict=1)
distinct_purchase_receipts = {}
for pr in purchase_receipts:
key = (pr.purchase_order, pr.item_code, pr.parent)
distinct_purchase_receipts.setdefault(key, []).append(pr.name)
backflushed_raw_materials_map = frappe._dict()
for item in backflushed_raw_materials:
backflushed_raw_materials_map.setdefault(item.item_key, item)
for args, references in iteritems(distinct_purchase_receipts):
purchase_receipt_supplied_items = get_supplied_items(args[1], args[2], references)
for data in purchase_receipt_supplied_items:
pr_key = (data.rm_item_code, args[0])
if pr_key not in backflushed_raw_materials_map:
backflushed_raw_materials_map.setdefault(pr_key, frappe._dict({
"qty": 0.0,
"serial_no": [],
"batch_no": [],
"consumed_batch": {}
}))
row = backflushed_raw_materials_map.get(pr_key)
row.qty += data.consumed_qty
for field in ["serial_no", "batch_no"]:
if data.get(field):
row[field].append(data.get(field))
if data.get("batch_no"):
if data.get("batch_no") in row.consumed_batch:
row.consumed_batch[data.get("batch_no")] += data.consumed_qty
else:
row.consumed_batch[data.get("batch_no")] = data.consumed_qty
return backflushed_raw_materials_map
def get_supplied_items(item_code, purchase_receipt, references):
return frappe.get_all("Purchase Receipt Item Supplied",
fields=["rm_item_code", "consumed_qty", "serial_no", "batch_no"],
filters={"main_item_code": item_code, "parent": purchase_receipt, "reference_name": ("in", references)})
def get_asset_item_details(asset_items):
asset_items_data = {}
for d in frappe.get_all('Item', fields = ["name", "auto_create_assets", "asset_naming_series"],
@@ -956,14 +991,15 @@ def get_transferred_batch_qty_map(purchase_order, fg_item):
SELECT
sed.batch_no,
SUM(sed.qty) AS qty,
sed.item_code
sed.item_code,
sed.subcontracted_item
FROM `tabStock Entry` se,`tabStock Entry Detail` sed
WHERE
se.name = sed.parent
AND se.docstatus=1
AND se.purpose='Send to Subcontractor'
AND se.purchase_order = %s
AND sed.subcontracted_item = %s
AND ifnull(sed.subcontracted_item, '') in ('', %s)
AND sed.batch_no IS NOT NULL
GROUP BY
sed.batch_no,
@@ -971,8 +1007,10 @@ def get_transferred_batch_qty_map(purchase_order, fg_item):
""", (purchase_order, fg_item), as_dict=1)
for batch_data in transferred_batches:
transferred_batch_qty_map.setdefault((batch_data.item_code, fg_item), {})
transferred_batch_qty_map[(batch_data.item_code, fg_item)][batch_data.batch_no] = batch_data.qty
key = ((batch_data.item_code, fg_item)
if batch_data.subcontracted_item else (batch_data.item_code, purchase_order))
transferred_batch_qty_map.setdefault(key, {})
transferred_batch_qty_map[key][batch_data.batch_no] = batch_data.qty
return transferred_batch_qty_map
@@ -1009,10 +1047,11 @@ def get_backflushed_batch_qty_map(purchase_order, fg_item):
return backflushed_batch_qty_map
def get_batches_with_qty(item_code, fg_item, required_qty, transferred_batch_qty_map, backflushed_batch_qty_map):
def get_batches_with_qty(item_code, fg_item, required_qty, transferred_batch_qty_map, backflushed_batches, po):
# Returns available batches to be backflushed based on requirements
transferred_batches = transferred_batch_qty_map.get((item_code, fg_item), {})
backflushed_batches = backflushed_batch_qty_map.get((item_code, fg_item), {})
if not transferred_batches:
transferred_batches = transferred_batch_qty_map.get((item_code, po), {})
available_batches = []

View File

@@ -10,7 +10,9 @@ from collections import defaultdict
from erpnext.stock.get_item_details import _get_item_tax_template
from frappe.utils import unique
# searches for active employees
# searches for active employees
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def employee_query(doctype, txt, searchfield, start, page_len, filters):
conditions = []
fields = get_fields("Employee", ["name", "employee_name"])
@@ -40,6 +42,8 @@ def employee_query(doctype, txt, searchfield, start, page_len, filters):
# searches for leads which are not converted
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def lead_query(doctype, txt, searchfield, start, page_len, filters):
fields = get_fields("Lead", ["name", "lead_name", "company_name"])
@@ -68,7 +72,9 @@ def lead_query(doctype, txt, searchfield, start, page_len, filters):
})
# searches for customer
# searches for customer
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def customer_query(doctype, txt, searchfield, start, page_len, filters):
conditions = []
cust_master_name = frappe.defaults.get_user_default("cust_master_name")
@@ -106,8 +112,11 @@ def customer_query(doctype, txt, searchfield, start, page_len, filters):
# searches for supplier
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def supplier_query(doctype, txt, searchfield, start, page_len, filters):
supp_master_name = frappe.defaults.get_user_default("supp_master_name")
if supp_master_name == "Supplier Name":
fields = ["name", "supplier_group"]
else:
@@ -137,31 +146,50 @@ def supplier_query(doctype, txt, searchfield, start, page_len, filters):
})
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def tax_account_query(doctype, txt, searchfield, start, page_len, filters):
company_currency = erpnext.get_company_currency(filters.get('company'))
tax_accounts = frappe.db.sql("""select name, parent_account from tabAccount
where tabAccount.docstatus!=2
and account_type in (%s)
and is_group = 0
and company = %s
and account_currency = %s
and `%s` LIKE %s
order by idx desc, name
limit %s, %s""" %
(", ".join(['%s']*len(filters.get("account_type"))), "%s", "%s", searchfield, "%s", "%s", "%s"),
tuple(filters.get("account_type") + [filters.get("company"), company_currency, "%%%s%%" % txt,
start, page_len]))
def get_accounts(with_account_type_filter):
account_type_condition = ''
if with_account_type_filter:
account_type_condition = "AND account_type in %(account_types)s"
accounts = frappe.db.sql("""
SELECT name, parent_account
FROM `tabAccount`
WHERE `tabAccount`.docstatus!=2
{account_type_condition}
AND is_group = 0
AND company = %(company)s
AND account_currency = %(currency)s
AND `{searchfield}` LIKE %(txt)s
ORDER BY idx DESC, name
LIMIT %(offset)s, %(limit)s
""".format(account_type_condition=account_type_condition, searchfield=searchfield),
dict(
account_types=filters.get("account_type"),
company=filters.get("company"),
currency=company_currency,
txt="%{}%".format(txt),
offset=start,
limit=page_len
)
)
return accounts
tax_accounts = get_accounts(True)
if not tax_accounts:
tax_accounts = frappe.db.sql("""select name, parent_account from tabAccount
where tabAccount.docstatus!=2 and is_group = 0
and company = %s and account_currency = %s and `%s` LIKE %s limit %s, %s""" #nosec
% ("%s", "%s", searchfield, "%s", "%s", "%s"),
(filters.get("company"), company_currency, "%%%s%%" % txt, start, page_len))
tax_accounts = get_accounts(False)
return tax_accounts
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=False):
conditions = []
@@ -209,7 +237,6 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
idx desc,
name, item_name
limit %(start)s, %(page_len)s """.format(
key=searchfield,
columns=columns,
scond=searchfields,
fcond=get_filters_cond(doctype, filters, conditions).replace('%', '%%'),
@@ -224,6 +251,8 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
}, as_dict=as_dict)
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def bom(doctype, txt, searchfield, start, page_len, filters):
conditions = []
fields = get_fields("BOM", ["name", "item"])
@@ -250,6 +279,8 @@ def bom(doctype, txt, searchfield, start, page_len, filters):
})
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_project_name(doctype, txt, searchfield, start, page_len, filters):
cond = ''
if filters.get('customer'):
@@ -276,6 +307,8 @@ def get_project_name(doctype, txt, searchfield, start, page_len, filters):
})
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len, filters, as_dict):
fields = get_fields("Delivery Note", ["name", "customer", "posting_date"])
@@ -305,6 +338,8 @@ def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len,
}, {"txt": ("%%%s%%" % txt)}, as_dict=as_dict)
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
cond = ""
if filters.get("posting_date"):
@@ -362,6 +397,8 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
limit %(start)s, %(page_len)s""".format(cond, match_conditions=get_match_cond(doctype)), args)
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_account_list(doctype, txt, searchfield, start, page_len, filters):
filter_list = []
@@ -384,7 +421,8 @@ def get_account_list(doctype, txt, searchfield, start, page_len, filters):
fields = ["name", "parent_account"],
limit_start=start, limit_page_length=page_len, as_list=True)
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_blanket_orders(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql("""select distinct bo.name, bo.blanket_order_type, bo.to_date
from `tabBlanket Order` bo, `tabBlanket Order Item` boi
@@ -401,6 +439,7 @@ def get_blanket_orders(doctype, txt, searchfield, start, page_len, filters):
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_income_account(doctype, txt, searchfield, start, page_len, filters):
from erpnext.controllers.queries import get_match_cond
@@ -427,6 +466,7 @@ def get_income_account(doctype, txt, searchfield, start, page_len, filters):
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_expense_account(doctype, txt, searchfield, start, page_len, filters):
from erpnext.controllers.queries import get_match_cond
@@ -451,6 +491,7 @@ def get_expense_account(doctype, txt, searchfield, start, page_len, filters):
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def warehouse_query(doctype, txt, searchfield, start, page_len, filters):
# Should be used when item code is passed in filters.
conditions, bin_conditions = [], []
@@ -494,6 +535,7 @@ def get_doctype_wise_filters(filters):
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_batch_numbers(doctype, txt, searchfield, start, page_len, filters):
query = """select batch_id from `tabBatch`
where disabled = 0
@@ -507,6 +549,7 @@ def get_batch_numbers(doctype, txt, searchfield, start, page_len, filters):
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def item_manufacturer_query(doctype, txt, searchfield, start, page_len, filters):
item_filters = [
['manufacturer', 'like', '%' + txt + '%'],
@@ -525,6 +568,7 @@ def item_manufacturer_query(doctype, txt, searchfield, start, page_len, filters)
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_purchase_receipts(doctype, txt, searchfield, start, page_len, filters):
query = """
select pr.name
@@ -539,6 +583,7 @@ def get_purchase_receipts(doctype, txt, searchfield, start, page_len, filters):
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_purchase_invoices(doctype, txt, searchfield, start, page_len, filters):
query = """
select pi.name
@@ -553,6 +598,7 @@ def get_purchase_invoices(doctype, txt, searchfield, start, page_len, filters):
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_tax_template(doctype, txt, searchfield, start, page_len, filters):
item_doc = frappe.get_cached_doc('Item', filters.get('item_code'))
@@ -567,9 +613,12 @@ def get_tax_template(doctype, txt, searchfield, start, page_len, filters):
if not taxes:
return frappe.db.sql(""" SELECT name FROM `tabItem Tax Template` """)
else:
valid_from = filters.get('valid_from')
valid_from = valid_from[1] if isinstance(valid_from, list) else valid_from
args = {
'item_code': filters.get('item_code'),
'posting_date': filters.get('valid_from'),
'posting_date': valid_from,
'tax_category': filters.get('tax_category')
}

View File

@@ -74,7 +74,7 @@ def validate_returned_items(doc):
for d in doc.get("items"):
if d.item_code and (flt(d.qty) < 0 or flt(d.get('received_qty')) < 0):
if d.item_code not in valid_items:
frappe.throw(_("Row # {0}: Returned Item {1} does not exists in {2} {3}")
frappe.throw(_("Row # {0}: Returned Item {1} does not exist in {2} {3}")
.format(d.idx, d.item_code, doc.doctype, doc.return_against))
else:
ref = valid_items.get(d.item_code, frappe._dict())
@@ -266,6 +266,8 @@ def make_return_doc(doctype, source_name, target_doc=None):
target_doc.purchase_order = source_doc.purchase_order
target_doc.purchase_order_item = source_doc.purchase_order_item
target_doc.rejected_warehouse = source_doc.rejected_warehouse
target_doc.purchase_receipt_item = source_doc.name
elif doctype == "Purchase Invoice":
target_doc.received_qty = -1* source_doc.received_qty
target_doc.rejected_qty = -1* source_doc.rejected_qty
@@ -276,20 +278,25 @@ def make_return_doc(doctype, source_name, target_doc=None):
target_doc.rejected_warehouse = source_doc.rejected_warehouse
target_doc.po_detail = source_doc.po_detail
target_doc.pr_detail = source_doc.pr_detail
target_doc.purchase_invoice_item = source_doc.name
elif doctype == "Delivery Note":
target_doc.against_sales_order = source_doc.against_sales_order
target_doc.against_sales_invoice = source_doc.against_sales_invoice
target_doc.so_detail = source_doc.so_detail
target_doc.si_detail = source_doc.si_detail
target_doc.expense_account = source_doc.expense_account
target_doc.dn_detail = source_doc.name
if default_warehouse_for_sales_return:
target_doc.warehouse = default_warehouse_for_sales_return
elif doctype == "Sales Invoice":
target_doc.sales_order = source_doc.sales_order
target_doc.delivery_note = source_doc.delivery_note
target_doc.so_detail = source_doc.so_detail
target_doc.dn_detail = source_doc.dn_detail
target_doc.expense_account = source_doc.expense_account
target_doc.sales_invoice_item = source_doc.name
if default_warehouse_for_sales_return:
target_doc.warehouse = default_warehouse_for_sales_return

View File

@@ -216,7 +216,9 @@ class SellingController(StockController):
'target_warehouse': p.target_warehouse,
'company': self.company,
'voucher_type': self.doctype,
'allow_zero_valuation': d.allow_zero_valuation_rate
'allow_zero_valuation': d.allow_zero_valuation_rate,
'sales_invoice_item': d.get("sales_invoice_item"),
'delivery_note_item': d.get("dn_detail")
}))
else:
il.append(frappe._dict({
@@ -232,7 +234,9 @@ class SellingController(StockController):
'target_warehouse': d.target_warehouse,
'company': self.company,
'voucher_type': self.doctype,
'allow_zero_valuation': d.allow_zero_valuation_rate
'allow_zero_valuation': d.allow_zero_valuation_rate,
'sales_invoice_item': d.get("sales_invoice_item"),
'delivery_note_item': d.get("dn_detail")
}))
return il
@@ -301,7 +305,11 @@ class SellingController(StockController):
d.conversion_factor = get_conversion_factor(d.item_code, d.uom).get("conversion_factor") or 1.0
return_rate = 0
if cint(self.is_return) and self.return_against and self.docstatus==1:
return_rate = self.get_incoming_rate_for_sales_return(d.item_code, self.return_against)
against_document_no = (d.get("sales_invoice_item")
if self.doctype == "Sales Invoice" else d.get("delivery_note_item"))
return_rate = self.get_incoming_rate_for_sales_return(d.item_code,
self.return_against, against_document_no)
# On cancellation or if return entry submission, make stock ledger entry for
# target warehouse first, to update serial no values properly

View File

@@ -249,7 +249,7 @@ class StatusUpdater(Document):
args['second_source_condition'] = """ + ifnull((select sum(%(second_source_field)s)
from `tab%(second_source_dt)s`
where `%(second_join_field)s`="%(detail_id)s"
and (`tab%(second_source_dt)s`.docstatus=1) %(second_source_extra_cond)s), 0) """ % args
and (`tab%(second_source_dt)s`.docstatus=1) %(second_source_extra_cond)s FOR UPDATE), 0) """ % args
if args['detail_id']:
if not args.get("extra_cond"): args["extra_cond"] = ""

View File

@@ -94,6 +94,7 @@ class StockController(AccountsController):
"account": warehouse_account[sle.warehouse]["account"],
"against": item_row.expense_account,
"cost_center": item_row.cost_center,
"project": item_row.get("project") or self.get("project"),
"remarks": self.get("remarks") or "Accounting Entry for Stock",
"debit": flt(sle.stock_value_difference, precision),
"is_opening": item_row.get("is_opening") or self.get("is_opening") or "No",
@@ -104,6 +105,7 @@ class StockController(AccountsController):
"account": item_row.expense_account,
"against": warehouse_account[sle.warehouse]["account"],
"cost_center": item_row.cost_center,
"project": item_row.get("project") or self.get("project"),
"remarks": self.get("remarks") or "Accounting Entry for Stock",
"credit": flt(sle.stock_value_difference, precision),
"project": item_row.get("project") or self.get("project"),
@@ -240,10 +242,11 @@ class StockController(AccountsController):
_(self.doctype), self.name, item.get("item_code")))
def delete_auto_created_batches(self):
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
for d in self.items:
if not d.batch_no: continue
serial_nos = [sr.name for sr in frappe.get_all("Serial No", {'batch_no': d.batch_no})]
serial_nos = get_serial_nos(d.serial_no)
if serial_nos:
frappe.db.set_value("Serial No", { 'name': ['in', serial_nos] }, "batch_no", None)
@@ -297,14 +300,19 @@ class StockController(AccountsController):
return serialized_items
def get_incoming_rate_for_sales_return(self, item_code, against_document):
def get_incoming_rate_for_sales_return(self, item_code, against_document, against_document_no=None):
incoming_rate = 0.0
cond = ''
if against_document and item_code:
if against_document_no:
cond = " and voucher_detail_no = %s" %(frappe.db.escape(against_document_no))
incoming_rate = frappe.db.sql("""select abs(stock_value_difference / actual_qty)
from `tabStock Ledger Entry`
where voucher_type = %s and voucher_no = %s
and item_code = %s limit 1""",
and item_code = %s {0} limit 1""".format(cond),
(self.doctype, against_document, item_code))
incoming_rate = incoming_rate[0][0] if incoming_rate else 0.0
return incoming_rate

View File

@@ -9,6 +9,7 @@ from frappe.utils import cint, flt, round_based_on_smallest_currency_fraction
from erpnext.controllers.accounts_controller import validate_conversion_rate, \
validate_taxes_and_charges, validate_inclusive_tax
from erpnext.stock.get_item_details import _get_item_tax_template
from erpnext.accounts.doctype.pricing_rule.utils import get_applied_pricing_rules
class calculate_taxes_and_totals(object):
def __init__(self, doc):
@@ -160,8 +161,9 @@ class calculate_taxes_and_totals(object):
for item in self.doc.get("items"):
item_tax_map = self._load_item_tax_rate(item.item_tax_rate)
cumulated_tax_fraction = 0
total_inclusive_tax_amount_per_qty = 0
for i, tax in enumerate(self.doc.get("taxes")):
tax.tax_fraction_for_current_item = self.get_current_tax_fraction(tax, item_tax_map)
tax.tax_fraction_for_current_item, inclusive_tax_amount_per_qty = self.get_current_tax_fraction(tax, item_tax_map)
if i==0:
tax.grand_total_fraction_for_current_item = 1 + tax.tax_fraction_for_current_item
@@ -171,9 +173,12 @@ class calculate_taxes_and_totals(object):
+ tax.tax_fraction_for_current_item
cumulated_tax_fraction += tax.tax_fraction_for_current_item
total_inclusive_tax_amount_per_qty += inclusive_tax_amount_per_qty * flt(item.qty)
if cumulated_tax_fraction and not self.discount_amount_applied and item.qty:
item.net_amount = flt(item.amount / (1 + cumulated_tax_fraction))
if not self.discount_amount_applied and item.qty and (cumulated_tax_fraction or total_inclusive_tax_amount_per_qty):
amount = flt(item.amount) - total_inclusive_tax_amount_per_qty
item.net_amount = flt(amount / (1 + cumulated_tax_fraction))
item.net_rate = flt(item.net_amount / item.qty, item.precision("net_rate"))
item.discount_percentage = flt(item.discount_percentage,
item.precision("discount_percentage"))
@@ -189,6 +194,7 @@ class calculate_taxes_and_totals(object):
from tax inclusive amount
"""
current_tax_fraction = 0
inclusive_tax_amount_per_qty = 0
if cint(tax.included_in_print_rate):
tax_rate = self._get_tax_rate(tax, item_tax_map)
@@ -204,9 +210,14 @@ class calculate_taxes_and_totals(object):
current_tax_fraction = (tax_rate / 100.0) * \
self.doc.get("taxes")[cint(tax.row_id) - 1].grand_total_fraction_for_current_item
if getattr(tax, "add_deduct_tax", None):
current_tax_fraction *= -1.0 if (tax.add_deduct_tax == "Deduct") else 1.0
return current_tax_fraction
elif tax.charge_type == "On Item Quantity":
inclusive_tax_amount_per_qty = flt(tax_rate)
if getattr(tax, "add_deduct_tax", None) and tax.add_deduct_tax == "Deduct":
current_tax_fraction *= -1.0
inclusive_tax_amount_per_qty *= -1.0
return current_tax_fraction, inclusive_tax_amount_per_qty
def _get_tax_rate(self, tax, item_tax_map):
if tax.account_head in item_tax_map:
@@ -320,7 +331,7 @@ class calculate_taxes_and_totals(object):
current_tax_amount = (tax_rate / 100.0) * \
self.doc.get("taxes")[cint(tax.row_id) - 1].grand_total_for_current_item
elif tax.charge_type == "On Item Quantity":
current_tax_amount = tax_rate * item.stock_qty
current_tax_amount = tax_rate * item.qty
self.set_item_wise_tax(item, tax, tax_rate, current_tax_amount)
@@ -471,7 +482,7 @@ class calculate_taxes_and_totals(object):
actual_taxes_dict = {}
for tax in self.doc.get("taxes"):
if tax.charge_type == "Actual":
if tax.charge_type in ["Actual", "On Item Quantity"]:
tax_amount = self.get_tax_amount_if_for_valuation_or_deduction(tax.tax_amount, tax)
actual_taxes_dict.setdefault(tax.idx, tax_amount)
elif tax.row_id in actual_taxes_dict:
@@ -514,7 +525,7 @@ class calculate_taxes_and_totals(object):
if self.doc.doctype == "Sales Invoice":
self.calculate_paid_amount()
if self.doc.is_return and self.doc.return_against: return
if self.doc.is_return and self.doc.return_against and not self.doc.get('is_pos'): return
self.doc.round_floats_in(self.doc, ["grand_total", "total_advance", "write_off_amount"])
self._set_in_company_currency(self.doc, ['write_off_amount'])
@@ -532,7 +543,7 @@ class calculate_taxes_and_totals(object):
self.doc.round_floats_in(self.doc, ["paid_amount"])
change_amount = 0
if self.doc.doctype == "Sales Invoice":
if self.doc.doctype == "Sales Invoice" and not self.doc.get('is_return'):
self.calculate_write_off_amount()
self.calculate_change_amount()
change_amount = self.doc.change_amount \
@@ -544,6 +555,9 @@ class calculate_taxes_and_totals(object):
self.doc.outstanding_amount = flt(total_amount_to_pay - flt(paid_amount) + flt(change_amount),
self.doc.precision("outstanding_amount"))
if self.doc.doctype == 'Sales Invoice' and self.doc.get('is_pos') and self.doc.get('is_return'):
self.update_paid_amount_for_return(total_amount_to_pay)
def calculate_paid_amount(self):
paid_amount = base_paid_amount = 0.0
@@ -593,7 +607,7 @@ class calculate_taxes_and_totals(object):
base_rate_with_margin = 0.0
if item.price_list_rate:
if item.pricing_rules and not self.doc.ignore_pricing_rule:
for d in item.pricing_rules.split(','):
for d in get_applied_pricing_rules(item.pricing_rules):
pricing_rule = frappe.get_cached_doc('Pricing Rule', d)
if (pricing_rule.margin_type == 'Amount' and pricing_rule.currency == self.doc.currency)\
@@ -614,6 +628,27 @@ class calculate_taxes_and_totals(object):
def set_item_wise_tax_breakup(self):
self.doc.other_charges_calculation = get_itemised_tax_breakup_html(self.doc)
def update_paid_amount_for_return(self, total_amount_to_pay):
default_mode_of_payment = frappe.db.get_value('Sales Invoice Payment',
{'parent': self.doc.pos_profile, 'default': 1},
['mode_of_payment', 'type', 'account'], as_dict=1)
self.doc.payments = []
if default_mode_of_payment:
self.doc.append('payments', {
'mode_of_payment': default_mode_of_payment.mode_of_payment,
'type': default_mode_of_payment.type,
'account': default_mode_of_payment.account,
'amount': total_amount_to_pay
})
else:
self.doc.is_pos = 0
self.doc.pos_profile = ''
self.calculate_paid_amount()
def get_itemised_tax_breakup_html(doc):
if not doc.taxes:
return

View File

@@ -13,14 +13,12 @@ class TestMapper(unittest.TestCase):
'''Test mapping of multiple source docs on a single target doc'''
make_test_records("Item")
items = frappe.get_all("Item", fields = ["name", "item_code"], filters = {'is_sales_item': 1, 'has_variants': 0})
customers = frappe.get_all("Customer")
if items and customers:
# Make source docs (quotations) and a target doc (sales order)
customer = random.choice(customers).name
qtn1, item_list_1 = self.make_quotation(items, customer)
qtn2, item_list_2 = self.make_quotation(items, customer)
so, item_list_3 = self.make_sales_order()
items = ['_Test Item', '_Test Item 2', '_Test FG Item']
# Make source docs (quotations) and a target doc (sales order)
qtn1, item_list_1 = self.make_quotation(items, '_Test Customer')
qtn2, item_list_2 = self.make_quotation(items, '_Test Customer')
so, item_list_3 = self.make_sales_order()
# Map source docs to target with corresponding mapper method
method = "erpnext.selling.doctype.quotation.quotation.make_sales_order"
@@ -28,18 +26,12 @@ class TestMapper(unittest.TestCase):
# Assert that all inserted items are present in updated sales order
src_items = item_list_1 + item_list_2 + item_list_3
self.assertEqual(set([d.item_code for d in src_items]),
self.assertEqual(set([d for d in src_items]),
set([d.item_code for d in updated_so.items]))
def get_random_items(self, items, limit):
'''Get a number of random items from a list of given items'''
random_items = []
for i in range(0, limit):
random_items.append(random.choice(items))
return random_items
def make_quotation(self, items, customer):
item_list = self.get_random_items(items, 3)
def make_quotation(self, item_list, customer):
qtn = frappe.get_doc({
"doctype": "Quotation",
"quotation_to": "Customer",
@@ -49,7 +41,7 @@ class TestMapper(unittest.TestCase):
"valid_till" : add_months(nowdate(), 1)
})
for item in item_list:
qtn.append("items", {"qty": "2", "item_code": item.item_code})
qtn.append("items", {"qty": "2", "item_code": item})
qtn.submit()
return qtn, item_list
@@ -60,7 +52,7 @@ class TestMapper(unittest.TestCase):
"base_rate": 100.0,
"description": "CPU",
"doctype": "Sales Order Item",
"item_code": "_Test Item Home Desktop 100",
"item_code": "_Test Item",
"item_name": "CPU",
"parentfield": "items",
"qty": 10.0,
@@ -72,4 +64,4 @@ class TestMapper(unittest.TestCase):
})
so = frappe.get_doc(frappe.get_test_records('Sales Order')[0])
so.insert(ignore_permissions=True)
return so, [item]
return so, [item.item_code]

View File

@@ -30,6 +30,7 @@ class TestTaxes(unittest.TestCase):
self.item_tax_template = frappe.get_doc({
'doctype': 'Item Tax Template',
'title': uuid4(),
'company': self.company.name,
'taxes': [
{
'tax_type': self.account.name,

View File

@@ -33,7 +33,7 @@ def validate_filters(filters):
frappe.throw(_("{0} is mandatory").format(f))
if not frappe.db.exists("Fiscal Year", filters.get("fiscal_year")):
frappe.throw(_("Fiscal Year: {0} does not exists").format(filters.get("fiscal_year")))
frappe.throw(_("Fiscal Year {0} Does Not Exist").format(filters.get("fiscal_year")))
if filters.get("based_on") == filters.get("group_by"):
frappe.throw(_("'Based On' and 'Group By' can not be same"))

View File

@@ -60,12 +60,18 @@ frappe.ui.form.on("Opportunity", {
opportunity_from: function(frm) {
frm.toggle_reqd("party_name", frm.doc.opportunity_from);
frm.trigger("setup_opportunity_from");
frm.set_value("party_name","");
},
setup_opportunity_from: function(frm) {
frm.trigger('setup_queries');
frm.trigger("set_dynamic_field_label");
},
refresh: function(frm) {
var doc = frm.doc;
frm.events.opportunity_from(frm);
frm.trigger("setup_opportunity_from");
frm.trigger('toggle_mandatory');
erpnext.toggle_naming_series();
@@ -95,6 +101,7 @@ frappe.ui.form.on("Opportunity", {
});
} else {
frm.add_custom_button(__("Reopen"), function() {
frm.set_value("lost_reasons",[])
frm.set_value("status", "Open");
frm.save();
});

View File

@@ -1,5 +1,4 @@
{
"actions": [],
"allow_import": 1,
"allow_rename": 1,
"autoname": "naming_series:",
@@ -402,7 +401,7 @@
"fieldname": "lost_reasons",
"fieldtype": "Table MultiSelect",
"label": "Lost Reasons",
"options": "Lost Reason Detail",
"options": "Opportunity Lost Reason Detail",
"read_only": 1
},
{
@@ -414,8 +413,7 @@
],
"icon": "fa fa-info-sign",
"idx": 195,
"links": [],
"modified": "2020-03-20 12:28:45.228994",
"modified": "2020-08-12 23:34:39.665513",
"modified_by": "Administrator",
"module": "CRM",
"name": "Opportunity",

View File

@@ -321,7 +321,7 @@ def auto_close_opportunity():
doc.save()
@frappe.whitelist()
def make_opportunity_from_communication(communication, ignore_communication_links=False):
def make_opportunity_from_communication(communication, company, ignore_communication_links=False):
from erpnext.crm.doctype.lead.lead import make_lead_from_communication
doc = frappe.get_doc("Communication", communication)
@@ -333,8 +333,9 @@ def make_opportunity_from_communication(communication, ignore_communication_link
opportunity = frappe.get_doc({
"doctype": "Opportunity",
"company": company,
"opportunity_from": opportunity_from,
"lead": lead
"party_name": lead
}).insert(ignore_permissions=True)
link_communication_to_document(doc, "Opportunity", opportunity.name, ignore_communication_links)

View File

@@ -0,0 +1,29 @@
{
"creation": "2020-07-16 16:11:39.830389",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"lost_reason"
],
"fields": [
{
"fieldname": "lost_reason",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Opportunity Lost Reason",
"options": "Opportunity Lost Reason"
}
],
"istable": 1,
"modified": "2020-08-12 23:32:55.930406",
"modified_by": "Administrator",
"module": "CRM",
"name": "Opportunity Lost Reason Detail",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
# import frappe
from frappe.model.document import Document
class OpportunityLostReasonDetail(Document):
pass

View File

@@ -17,7 +17,8 @@ def get_columns():
{
"fieldname": "lead_owner",
"label": _("Lead Owner"),
"fieldtype": "Data",
"fieldtype": "Link",
"options": "User",
"width": "130"
},
{

View File

@@ -151,7 +151,7 @@ def get_fee_components(fee_structure):
:param fee_structure: Fee Structure.
"""
if fee_structure:
fs = frappe.get_list("Fee Component", fields=["fees_category", "amount"] , filters={"parent": fee_structure}, order_by= "idx")
fs = frappe.get_list("Fee Component", fields=["fees_category", "description", "amount"] , filters={"parent": fee_structure}, order_by= "idx")
return fs
@@ -363,9 +363,9 @@ def get_current_enrollment(student, academic_year=None):
select
name as program_enrollment, student_name, program, student_batch_name as student_batch,
student_category, academic_term, academic_year
from
from
`tabProgram Enrollment`
where
where
student = %s and academic_year = %s
order by creation''', (student, current_academic_year), as_dict=1)

View File

@@ -161,6 +161,7 @@ frappe.ui.form.on("Fees", {
$.each(r.message, function(i, d) {
var row = frappe.model.add_child(frm.doc, "Fee Component", "components");
row.fees_category = d.fees_category;
row.description = d.description;
row.amount = d.amount;
});
}

View File

@@ -71,7 +71,7 @@ class ProgramEnrollment(Document):
def create_course_enrollments(self):
student = frappe.get_doc("Student", self.student)
program = frappe.get_doc("Program", self.program)
course_list = [course.course for course in program.get_all_children()]
course_list = [course.course for course in program.courses]
for course_name in course_list:
student.enroll_in_course(course_name=course_name, program_enrollment=self.name)
@@ -97,6 +97,7 @@ class ProgramEnrollment(Document):
return quiz_progress
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_program_courses(doctype, txt, searchfield, start, page_len, filters):
if filters.get('program'):
return frappe.db.sql("""select course, course_name from `tabProgram Course`
@@ -115,6 +116,7 @@ def get_program_courses(doctype, txt, searchfield, start, page_len, filters):
})
@frappe.whitelist()
@frappe.validate_and_sanitize_search_inputs
def get_students(doctype, txt, searchfield, start, page_len, filters):
if not filters.get("academic_term"):
filters["academic_term"] = frappe.defaults.get_defaults().academic_term

View File

@@ -1,398 +1,119 @@
{
"allow_copy": 0,
"allow_guest_to_view": 1,
"allow_import": 0,
"allow_rename": 1,
"autoname": "",
"beta": 0,
"creation": "2016-09-13 03:05:27.154713",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Document",
"editable_grid": 1,
"actions": [],
"allow_guest_to_view": 1,
"allow_rename": 1,
"creation": "2016-09-13 03:05:27.154713",
"doctype": "DocType",
"document_type": "Document",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"title",
"route",
"column_break_3",
"academic_year",
"admission_start_date",
"admission_end_date",
"published",
"enable_admission_application",
"section_break_5",
"program_details",
"introduction"
],
"fields": [
{
"allow_bulk_edit": 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,
"unique": 0
},
"fieldname": "title",
"fieldtype": "Data",
"label": "Title"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fieldname": "route",
"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": "Route",
"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": 0,
"search_index": 0,
"set_only_once": 0,
"fieldname": "route",
"fieldtype": "Data",
"label": "Route",
"no_copy": 1,
"unique": 1
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "application_form_route",
"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": "Application Form Route",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "column_break_3",
"fieldtype": "Column Break"
},
{
"allow_bulk_edit": 0,
"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_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,
"unique": 0
},
"fieldname": "academic_year",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Academic Year",
"no_copy": 1,
"options": "Academic Year",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "academic_year",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Academic Year",
"length": 0,
"no_copy": 1,
"options": "Academic Year",
"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,
"unique": 0
},
"fieldname": "admission_start_date",
"fieldtype": "Date",
"label": "Admission Start Date",
"no_copy": 1
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "admission_start_date",
"fieldtype": "Date",
"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": "Admission Start Date",
"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": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"fieldname": "admission_end_date",
"fieldtype": "Date",
"label": "Admission End Date",
"no_copy": 1
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "admission_end_date",
"fieldtype": "Date",
"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": "Admission End Date",
"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": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
"default": "0",
"fieldname": "published",
"fieldtype": "Check",
"label": "Publish on website"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "published",
"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": "Publish on website",
"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_break_5",
"fieldtype": "Section Break",
"label": "Eligibility and Details"
},
{
"allow_bulk_edit": 0,
"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_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Eligibility and 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,
"unique": 0
},
"fieldname": "program_details",
"fieldtype": "Table",
"label": "Eligibility and Details",
"options": "Student Admission Program"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "program_details",
"fieldtype": "Table",
"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": "Eligibility and Details",
"length": 0,
"no_copy": 0,
"options": "Student Admission Program",
"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": "introduction",
"fieldtype": "Text Editor",
"label": "Introduction"
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "introduction",
"fieldtype": "Text Editor",
"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": "Introduction",
"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": "enable_admission_application",
"fieldtype": "Check",
"label": "Enable Admission Application"
}
],
"has_web_view": 1,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_published_field": "published",
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-11-10 18:57:34.570376",
"modified_by": "Administrator",
"module": "Education",
"name": "Student Admission",
"name_case": "",
"owner": "Administrator",
],
"has_web_view": 1,
"is_published_field": "published",
"links": [],
"modified": "2020-06-15 20:18:38.591626",
"modified_by": "Administrator",
"module": "Education",
"name": "Student Admission",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 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": "Academics User",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Academics User",
"share": 1,
"write": 1
}
],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"restrict_to_domain": "Education",
"route": "admissions",
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "title",
"track_changes": 0,
"track_seen": 0
],
"restrict_to_domain": "Education",
"route": "admissions",
"show_name_in_global_search": 1,
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "title"
}

View File

@@ -43,8 +43,8 @@
<thead>
<tr class="active">
<th style="width: 90px">Program/Std.</th>
<th style="width: 170px">Minumum Age(DOB)</th>
<th style="width: 170px">Maximum Age(DOB)</th>
<th style="width: 170px">Minumum Age</th>
<th style="width: 170px">Maximum Age</th>
<th style="width: 100px">Application Fee</th>
</tr>
</thead>
@@ -52,8 +52,8 @@
{% for row in program_details %}
<tr>
<td>{{ row.program }}</td>
<td>{{ row.minimum_age }}</td>
<td>{{ row.maximum_age }}</td>
<td>{{ row.min_age }}</td>
<td>{{ row.max_age }}</td>
<td>{{ row.application_fee }}</td>
</tr>
{% endfor %}
@@ -61,12 +61,11 @@
</table>
</div>
{% endif %}
{%- if application_form_route -%}
{%- if doc.enable_admission_application -%}
<br>
<p>
<a class='btn btn-primary'
href='/{{ doc.application_form_route }}?new=1'>
href='/student-applicant?new=1&student_admission={{doc.name}}'>
{{ _("Apply Now") }}</a>
</p>
{% endif %}

View File

@@ -11,7 +11,7 @@ QUnit.test('Test: Student Admission', function(assert) {
{admission_start_date: '2016-04-20'},
{admission_end_date: '2016-05-31'},
{title: '2016-17 Admissions'},
{application_form_route: 'student-applicant'},
{enable_admission_application: 1},
{introduction: 'Test intro'},
{program_details: [
[
@@ -28,7 +28,7 @@ QUnit.test('Test: Student Admission', function(assert) {
assert.ok(cur_frm.doc.admission_start_date == '2016-04-20');
assert.ok(cur_frm.doc.admission_end_date == '2016-05-31');
assert.ok(cur_frm.doc.title == '2016-17 Admissions');
assert.ok(cur_frm.doc.application_form_route == 'student-applicant');
assert.ok(cur_frm.doc.enable_admission_application == 1);
assert.ok(cur_frm.doc.introduction == 'Test intro');
assert.ok(cur_frm.doc.program_details[0].program == 'Standard Test', 'Program correctly selected');
assert.ok(cur_frm.doc.program_details[0].application_fee == 1000);

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