Compare commits

..

237 Commits

Author SHA1 Message Date
Rohit Waghchaure
73666982c7 Merge branch 'v12-pre-release' into version-12 2021-08-19 20:20:08 +05:30
Rohit Waghchaure
48bd1965e4 bumped to version 12.24.0 2021-08-19 20:40:07 +05:50
rohitwaghchaure
ab84579b0e Merge pull request #27041 from rohitwaghchaure/change-log-v12-24
chore: change log for v12.24.0
2021-08-19 20:18:05 +05:30
Rohit Waghchaure
8064792b8c chore: change log for v12.24.0 2021-08-19 18:46:16 +05:30
rohitwaghchaure
fe6c96cab9 Merge pull request #27037 from rohitwaghchaure/merge-v12-hotfix-to-pre-release
chore: merge v12 hotfix to v12 pre-release
2021-08-19 17:44:46 +05:30
Frappe PR Bot
f8fa3860d9 fix: equality check instead of assignment (#27029)
* Merge pull request #27026 from ankush/eq_assign

fix: equality check instead of assignment

[skip ci]

(cherry picked from commit 993b0532f8)

* fix: equality check instead of assignment in cart

port of https://github.com/frappe/erpnext/pull/25372

Co-authored-by: Ankush Menat <ankush@iwebnotes.com>
2021-08-19 15:48:51 +05:30
Türker Tunalı
d8a7abcd02 fix: date_unchanged calculation in "Update Items" (#26992)
Branch corrected https://github.com/frappe/erpnext/pull/26058

  ERPNext generates "Cannot set quantity less than delivered quantity" error even the delivered qty is zero when user clicks "Update Items".
  "date_unchanged" variable gets false value because of new_date is string. 
  
  "getdate(new_date)" corrects the date comparison.
  
  ![ERPNext_PR](https://user-images.githubusercontent.com/710051/121928377-c0263180-cd48-11eb-8cd9-eda7dace09d6.gif)
2021-08-18 17:43:58 +05:30
Ankush Menat
5bb9de8614 ci: backport action on v12 (#27009)
[skip ci]
2021-08-18 17:00:07 +05:30
Ankush Menat
0fd50e0426 fix(deps): pin plaid-python to 7.2.x (#26996)
* fix(deps): pin plaid-python to 7.2.x

Old requirement.txt was allowing next major version which has breaking
changes and causes failure in installation.

* fix(deps): remove frappe from requirements.txt
2021-08-18 08:02:22 +00:00
HENRY Florian
bdfc300896 fix: item name is missing into job card (#26956) 2021-08-17 15:33:26 +05:30
Sagar Vora
14292456cf Merge pull request #26978 from frappe-pr-bot/backport/version-12-hotfix/26976
fix: Incorrect `modified` time in documents that inherit from `StatusUpdater`
2021-08-17 13:21:16 +05:30
Sagar Vora
24d67c35b7 Merge pull request #26976 from resilient-tech/fix-incorrect-modified
fix: Incorrect `modified` time in documents that inherit from `StatusUpdater`
(cherry picked from commit d932cba38a)
2021-08-17 07:48:25 +00:00
Frappe PR Bot
8d71fcb948 fix: fix Payment references from disappearing on adding Cost Center in Payment Entry (#26939)
* fix: payment references from disappearing on selecting cost center (#24831)

Co-authored-by: Afshan <33727827+AfshanKhan@users.noreply.github.com>
(cherry picked from commit 9bf1083d9e)

# Conflicts:
#	erpnext/accounts/doctype/payment_entry/payment_entry.js

* fix: conflicts

* fix: conflicts

Co-authored-by: Anuja Pawar <60467153+Anuja-pawar@users.noreply.github.com>
Co-authored-by: Afshan <33727827+AfshanKhan@users.noreply.github.com>
2021-08-13 17:45:16 +05:30
Frappe PR Bot
2945e604aa fix: remove limit from stock balance report (bp #26773)
(cherry picked from commit b3740e9afc)

Co-authored-by: Ankush <ankush@iwebnotes.com>
2021-08-13 15:44:13 +05:30
Deepesh Garg
ea085b3a76 Merge pull request #26674 from deepeshgarg007/gl_entry_deadlock
fix: Deadlock while doing payment reconciliation
2021-08-12 11:29:34 +05:30
Saqib
611966c139 fix(e-invoicing): cannot cancel invoice if IRN cancelled on portal (#26880) 2021-08-10 17:19:24 +05:30
Ahmad
8eca908365 perf: speed up validate_account_for_perpetual_inventory (#26730) 2021-08-09 12:17:11 +05:30
Anupam Kumar
09d5ddc42b fix: bank remittance report issue (#26398) (#26767) 2021-08-04 14:03:01 +05:30
Nabin Hait
abd53b114c Merge pull request #25722 from rtdany10/patch-3
feat: Increase number of supported currency exchanges
2021-07-31 11:33:49 +05:30
Ankush
b1e932a6f8 fix: remove incorrect condition in GLE comparison (#26713) 2021-07-29 19:56:36 +05:30
Dany Robert
e6a3e6beb7 Merge branch 'version-12-hotfix' into patch-3 2021-07-29 16:48:12 +05:30
Dany Robert
239974c73e fix issue with cache.setex 2021-07-29 16:00:35 +05:30
Deepesh Garg
27ecb54b8c fix: Deadlock while doing payment reconciliation 2021-07-27 17:49:48 +05:30
Deepesh Garg
6b4b80a4a4 Merge pull request #26629 from deepeshgarg007/exchange_rate_reval_fixes_v12
fix: Exchange rate revaluation posting date and precision fixes
2021-07-27 16:40:11 +05:30
Jannat Patel
68225bbcad Merge pull request #25995 from hasnain2808/fix-issue-priorirty
fix: do not translate issue priority
2021-07-26 10:56:22 +05:30
Deepesh Garg
b549287b94 fix: Convert null values to empty string on grouping 2021-07-25 21:28:40 +05:30
Deepesh Garg
12c3e5dfd6 fix: Remove unintended changes 2021-07-25 21:27:56 +05:30
Deepesh Garg
c908add82e fix: Exchange rate revaluation posting date and precision fixes 2021-07-25 20:03:12 +05:30
Jannat Patel
c74f0f3530 Merge branch 'version-12-hotfix' into fix-issue-priorirty 2021-07-24 18:28:02 +05:30
pateljannat
2e5a358e96 fix: salary component account filter 2021-07-23 13:06:57 +05:30
Subin Tom
01f8833bd1 fix: Fixed clearing issue of payment references on setting cost center (#26548)
Co-authored-by: Subin Tom <subin-home@Subins-MacBook-Air.local>
Co-authored-by: Afshan <33727827+AfshanKhan@users.noreply.github.com>
2021-07-20 21:04:10 +05:30
Nabin Hait
5e37949411 Merge branch 'v12-pre-release' into version-12 2021-07-16 16:10:30 +05:30
Nabin Hait
c5a0c22352 Merge branch 'version-12' into version-12-hotfix 2021-07-16 16:10:30 +05:30
Nabin Hait
fc0459fba9 bumped to version 12.23.0 2021-07-16 16:30:30 +05:50
Nabin Hait
9a1caddacc chore: added change log for v12.23.0 2021-07-16 16:08:40 +05:30
Noah Jacob
b22cbb3122 fix: validation check when no conversion_factor (#26528) 2021-07-16 15:01:14 +05:30
rohitwaghchaure
f4a9e52cbe Merge pull request #26501 from rohitwaghchaure/fixed-taxes-not-working
fix: taxes not set correctly when items pulled from PO to PI
2021-07-16 11:40:56 +05:30
Rohit Waghchaure
24e1786e49 fix: taxes not set correctly when items pulled from PO to PI 2021-07-14 22:52:40 +05:30
Jannat Patel
5399891b25 fix: task status loop (#26007) 2021-07-14 14:43:59 +05:30
Jannat Patel
1b8670b263 fix: Removed company filter for Loan Type (#26463) 2021-07-13 15:29:58 +05:30
Jannat Patel
23db6a8e3a fix: added company filter while fetching loans (#26296)
Co-authored-by: Rucha Mahabal <ruchamahabal2@gmail.com>
2021-07-12 13:17:27 +05:30
Saqib
4c58fb40a8 fix: omit item discount amount for e-invoicing (#26408) 2021-07-12 11:05:37 +05:30
rohitwaghchaure
df045a61ed Merge pull request #26423 from rohitwaghchaure/fixed-serial-no-in-purchase-receipt
fix: serial no issue in subcontract purchase receipt
2021-07-11 10:25:51 +05:30
Rohit Waghchaure
6f7410073f fix: serial no issue in purchase receipt 2021-07-10 22:54:15 +05:30
Saqib
0ecf8f5d66 fix(e-invoicing): allow export invoice even if no taxes applied (#26406) 2021-07-09 15:33:40 +05:30
Jannat Patel
dfc68950c1 fix: lms progress issue (#26254)
Co-authored-by: Rucha Mahabal <ruchamahabal2@gmail.com>
2021-07-02 13:08:38 +05:30
Mohammed Yusuf Shaikh
ee7de6b107 fix: half day to be accounted in its leave type (#26267) 2021-07-02 12:31:59 +05:30
Mohammed Yusuf Shaikh
b2a090f073 fix: Added Permissions for employee to book an appointment (#26246)
Co-authored-by: Rucha Mahabal <ruchamahabal2@gmail.com>
2021-07-02 12:28:43 +05:30
Saqib
704f7b57b8 fix(plaid): cannot reset plaid link for a bank account (#26282) 2021-07-02 11:18:55 +05:30
meike289
8070d76450 feat: add check field for subscription invoice (#25560)
Co-authored-by: Meike Nedwidek <nedwidek@kk-software.de>
2021-06-28 18:35:03 +05:30
Noah Jacob
266563a99a fix: fixed rounding off ordered percent to 100 in condition (#26153) 2021-06-24 21:21:22 +05:30
Saqib
7270b89133 fix: invoices can alter profit and loss of a closed year (#26161) 2021-06-23 19:00:10 +05:30
Jannat Patel
57a68c317e fix: Staffing plan vacancies data type issue (#25940)
* fix: staffing plan vacancies data type issue

* fix: translation issue

* fix: removed greater than 0 condition

Co-authored-by: Rucha Mahabal <ruchamahabal2@gmail.com>
2021-06-23 14:38:18 +05:30
Jannat Patel
fc44712976 fix: job applicant link issue (#25935)
Co-authored-by: Rucha Mahabal <ruchamahabal2@gmail.com>
2021-06-23 12:30:30 +05:30
Saqib
a80d9d81c8 fix(e-invoicing): service item check (#26141) 2021-06-22 14:25:53 +05:30
rohitwaghchaure
6a30025209 Merge pull request #26117 from rohitwaghchaure/fixed-linking-between-mr-and-sq-v12
fix: material request and supplier quotation not linked if supplier quotation created from supplier portal
2021-06-20 19:43:13 +05:30
Rohit Waghchaure
b9fb2349d6 fix: material request and supplier quotation not linked if sq created from supplier portal against rfq 2021-06-20 15:18:35 +05:30
Nabin Hait
2c30ad9465 Merge pull request #26089 from pateljannat/material-request-status-issue-backport
fix: material request status issue
2021-06-18 17:19:41 +05:30
Nabin Hait
67f80216fa Merge branch 'v12-pre-release' into version-12 2021-06-17 19:00:32 +05:30
Nabin Hait
2a8b3841bf Merge branch 'version-12' into version-12-hotfix 2021-06-17 19:00:32 +05:30
Nabin Hait
83b6746cd1 bumped to version 12.22.0 2021-06-17 19:20:32 +05:50
Nabin Hait
94f0aae625 chore: Added change log for v12.22.0 2021-06-17 18:56:13 +05:30
Deepesh Garg
0c4f67b884 Merge pull request #26091 from deepeshgarg007/cash_flow_position
fix: Update positions in default cashflow mappers
2021-06-17 17:17:22 +05:30
Deepesh Garg
fe1d985432 fix: Update positions in default cashflow mappers 2021-06-17 17:15:05 +05:30
pateljannat
57832fc9f8 fix: material request status issue 2021-06-17 10:53:45 +05:30
gavin
56a21343f4 Merge pull request #26001 from frappe/gavindsouza-patch-1
ci: Use only compatible version of bench CLI
2021-06-10 13:33:29 +05:30
gavin
bda432303c ci: Use only compatible version of bench CLI
bench CLI has dropped support for < PY3.6
2021-06-10 13:25:44 +05:30
hasnain2808
371d124a0e fix: do not translate issue priority 2021-06-09 18:40:15 +05:30
Anuja Pawar
3c5b33c241 fix: update cost center in SI (#25972) 2021-06-07 21:15:27 +05:30
Rucha Mahabal
85dca013ee fix: update employee field on renaming employee (#25958) 2021-06-07 15:02:49 +05:30
Saqib
d789dd3897 fix: wrong round off gl entry posted in case of purchase invoice (#25952) 2021-06-06 10:56:01 +05:30
Rucha Mahabal
a1a3f674a2 fix: invalid 'depends_on' expression in opportunity (#25954) 2021-06-04 11:15:55 +05:30
Saqib
7bb95f0a80 feat: cost-center wise period closing entry (#25930) 2021-06-03 17:33:00 +05:30
Ankush Menat
5c450cd13f fix: sync shopify customer addresses (#25937) 2021-06-03 16:48:08 +05:30
Ankush Menat
1c3c2b3006 fix: update shopify api version (#25939) 2021-06-03 16:46:30 +05:30
Deepesh Garg
688a5ac048 Merge pull request #25913 from deepeshgarg007/gst_freight_taxable_value
fix: Backward compatibility for GSTR-1 report
2021-06-02 11:30:57 +05:30
Deepesh Garg
21c15b89ab fix: Add taxable value in Purchase Invoice Item 2021-06-01 21:03:33 +05:30
Deepesh Garg
6a1ccf94a2 fix: Taxable value in GSTR-1 report 2021-06-01 21:02:50 +05:30
Dany Robert
3302ed4658 Merge branch 'version-12-hotfix' into patch-3 2021-05-26 15:51:43 +05:30
Anupam Kumar
fa3ca02557 fix: student invalid password reset link (#25827) 2021-05-26 12:16:25 +05:30
Deepesh Garg
1853f5da80 Merge pull request #25739 from deepeshgarg007/cash_flow_mapper_fix
fix: Cashlfow mapper not showing data
2021-05-24 20:39:59 +05:30
Deepesh Garg
dd82bbf78d Merge branch 'version-12-hotfix' into cash_flow_mapper_fix 2021-05-24 19:56:08 +05:30
Dany Robert
5271ce36de fix: Update test values 2021-05-22 11:22:02 +05:30
Dany Robert
88bab1e3ad fix: update test suite 2021-05-21 23:02:55 +05:30
Dany Robert
6ec804d77f fix: Update hard coded exchange rate values for testing 2021-05-21 18:16:21 +05:30
Nabin Hait
7fa3132a66 Merge branch 'v12-pre-release' into version-12 2021-05-20 18:51:42 +05:30
Nabin Hait
3d3ee778ed Merge branch 'version-12' into version-12-hotfix 2021-05-20 18:51:42 +05:30
Nabin Hait
65b7b57c70 bumped to version 12.21.0 2021-05-20 19:11:42 +05:50
Nabin Hait
4d9c9db295 chore: Added change log for v12.21.0 2021-05-20 18:49:42 +05:30
Deepesh Garg
13927e35cf Merge pull request #25662 from CaseSolvedUK/plaid-24675-v12
fix: plaid NoneType error
2021-05-20 17:03:02 +05:30
Deepesh Garg
18913756eb Merge pull request #25715 from deepeshgarg007/ignore_rouding_diff
fix: Ignore rounding diff while importing JV using data import
2021-05-19 18:26:11 +05:30
Nabin Hait
ccbdf25d44 Merge branch 'version-12-hotfix' into v12-pre-release 2021-05-18 20:30:46 +05:30
Deepesh Garg
ad1f1e000b fix: Cashlfow mapper not showing data 2021-05-18 08:38:49 +05:30
Dany Robert
5cced71ce4 fix: Get the exchange rate based on date. 2021-05-16 12:43:57 +05:30
Dany Robert
aea8773503 feat: Increase number of supported currency exchanges
Switch from frankfurter.app to exchangerate.host to accomodate more currency usage.
Closes #25603
2021-05-15 12:23:05 +05:30
Deepesh Garg
df51aa3087 fix: Ignore rounding diff while importig JV using data import 2021-05-14 21:31:22 +05:30
rohitwaghchaure
2ded94c338 Merge pull request #25693 from rohitwaghchaure/fixed-warehouse-tree-time-out-error
fix: timeout error while loading warehouse tree
2021-05-13 17:21:41 +05:30
Rohit Waghchaure
0b45d5e1ec fix: timeout error while loading warehouse tree 2021-05-13 15:51:39 +05:30
casesolved-co-uk
5946c2f28e fix: plaid NoneType error #24675 2021-05-11 12:36:07 +00:00
rohitwaghchaure
cb2f2d9e73 Merge pull request #25589 from 18alantom/backport-fix-check-schedule-date
fix: check for None in item.schedule_date before setting
2021-05-09 16:57:39 +05:30
Anuja Pawar
39bbc7a245 fix: update item level cost center from POS profile (#25612) 2021-05-08 14:11:06 +05:30
18alantom
062520f1b9 fix: check for None in item.schedule_date before setting 2021-05-05 12:07:18 +05:30
Rucha Mahabal
f644f6feba fix: Employee Separation (#25504)
* fix: Employee Separation

- add ignore_mandatory flag for project creation

- form clean-up

* fix: Employee Separation test
2021-05-03 18:37:13 +05:30
rohitwaghchaure
9de5fe2105 Merge pull request #25552 from rohitwaghchaure/fixed-total-stock-summary-report-12-hotfix
fix: total stock summary report not working
2021-05-03 10:24:34 +05:30
Rohit Waghchaure
e163cb89bf fix: total stock summary report not working 2021-05-02 18:03:29 +05:30
Deepesh Garg
9d38a0eede Merge pull request #25422 from finbyz/patch-2
fix: state code for Other Territory
2021-04-30 11:11:50 +05:30
rohitwaghchaure
c0b66b8203 Merge pull request #25443 from rohitwaghchaure/fixed-incorrect-qty-calculated-for-sub-contracted-raw-materials
fix: incorrect qty calculated for sub-contracted raw materials in purchase receipt
2021-04-27 15:14:03 +05:30
Saqib
96c099c609 fix: remove invalid changes added due to merge conflicts (#25404)
* fix: merge conflicts

* fix: merge conflict

* fix: recover lost method
2021-04-26 15:40:29 +05:30
Jannat Patel
b5be828f3a fix: issue in project custom status (#25453) 2021-04-26 15:36:01 +05:30
Saqib
059b8b567e feat(italy): add document type field for e-invoicing (#25420) 2021-04-26 13:09:04 +05:30
Deepesh Garg
cfdaf7c4aa Merge pull request #25419 from deepeshgarg007/composition_v12_hotfix
fix: Purchase from registered composition dealer
2021-04-24 17:24:18 +05:30
Rohit Waghchaure
5b80679ede fix: incorrect qty calculated for sub-contracted raw materials in purchase receipt 2021-04-22 17:03:02 +05:30
Saqib
a0783de232 fix: remove invalid changes added due to merge conflict (#25405)
* fix: merge conflict

* fix: recover lost method
2021-04-22 14:31:46 +05:30
Saqib
98d90f4e36 fix: remove invalid changes added due to merge conflict (#25437)
* fix: merge conflicts

* fix: recover lost method
2021-04-22 14:14:48 +05:30
Alan
c843da04a4 fix: filter using purpose, make requested changes (#25388)
backported from https://github.com/frappe/erpnext/pull/25352
2021-04-21 21:40:39 +05:30
Alan
34f1d3a88e fix: change subcontracted item display (#25426) 2021-04-21 21:04:28 +05:30
FinByz Tech Pvt. Ltd
bd4461b8cb Update __init__.py
Other Territory state code should be 97.

It's already corrected in version-13 but missed in version-12
2021-04-21 15:46:58 +05:30
Deepesh Garg
06063f7aa6 fix: Test case for GSTR 3b report 2021-04-21 14:14:55 +05:30
Deepesh Garg
472c9e534a fix: Purchase from registered composition dealer 2021-04-21 14:14:45 +05:30
Deepesh Garg
54c9704fe2 Merge pull request #25410 from deepeshgarg007/rcm_rounding_precision
fix: RCM rounding precision
2021-04-20 18:51:24 +05:30
Deepesh Garg
673dcb855d fix: RCM rounding precision 2021-04-20 18:48:50 +05:30
Alan
e3ebe4b33b fix: can't multiply sequence by non-int of type 'float' (#25385)
Co-authored-by: Rohit Waghchaure <rohitw1991@gmail.com>
2021-04-19 15:30:34 +05:30
Saqib
baefc6fd26 fix(e-invoicing): variable scoping (#25368) 2021-04-16 16:22:40 +05:30
Nabin Hait
b95b4e8064 fix: merge conflict 2021-04-16 12:55:46 +05:30
Nabin Hait
08399f9015 bumped to version 12.20.0 2021-04-16 13:11:07 +05:50
Nabin Hait
4481d4e965 chore: added change log 2021-04-16 12:48:27 +05:30
Nabin Hait
3f459c500f Merge branch 'version-12-hotfix' into v12-pre-release 2021-04-16 12:42:36 +05:30
Saqib
e787d05f66 fix(e-invoicing): validations & tax calculation fixes (#25315)
* fix: GST on freight charge in e-invoicing

* fix: cannot fetch e invoice settings

* fix: address validations & cancel eway bill dialog

* fix: except einvoice loading error seperately

* fix: sider

* fix: import format_date

* fix: imports

* fix: test

* fix: test

* fix: test

* fix: validate total condition

* feat: add company link to e-invoice settings

* fix: remove extra condition

* fix: test

Co-authored-by: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com>
2021-04-15 18:57:08 +05:30
Deepesh Garg
4eab67347f Merge pull request #25318 from deepeshgarg007/zero_ref_doc_billing_v12
fix: Zero amount completed delivery notes being shown in Sales Invoice get items
2021-04-14 15:28:49 +05:30
Deepesh Garg
cfe20cf610 Merge pull request #25226 from deepeshgarg007/rcm_total_calculation_fix_v12
fix: RCM tax calculation
2021-04-13 20:07:35 +05:30
Ankush Menat
73a7bb88fb fix: remove gst name validation for purch Invoice (#25236)
Co-authored-by: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com>
2021-04-13 19:00:38 +05:30
Ankush Menat
d2d025b586 fix: round total quantity in job card (#25246)
Co-authored-by: Marica <maricadsouza221197@gmail.com>
2021-04-13 18:58:42 +05:30
Ankush Menat
061c82a5cf fix: patch fixes for property setter (#25313)
partial backport of #25220
2021-04-13 18:58:19 +05:30
Ankush Menat
e6eab3b5f8 fix: incorrect status creating PR from PO after creating PI (#25203)
* test: add tests for PO->PI, PO->PR workflow

Add failing test cases for PR status and PR percent billed.

* fix: update PR status in database

* fix: do not copy percent billed from PO to PR

* fix: patch for purchase receipt status

* fix: remove logging in patch for v12 compatibility
2021-04-13 18:57:03 +05:30
Deepesh Garg
16c3a76c49 fix: Applly single transaction threshold on net_total instead of supplier credit amount (#25208) 2021-04-13 18:54:42 +05:30
Shariq Ansari
dd78ffb176 fix: Assignment Rule Unassign Condition doesn't work (#24890) 2021-04-13 18:52:37 +05:30
Shariq Ansari
583a8bf580 fix: Added parent task expected end date validation (#24889) 2021-04-13 18:51:46 +05:30
Jannat Patel
2c63f833b6 fix: serial no refresh issue (#25130)
Co-authored-by: Nabin Hait <nabinhait@gmail.com>
2021-04-13 18:51:05 +05:30
Deepesh Garg
d5d7ef7349 fix: Zero amount completed delivery notes being shown in Sales Invocie get items 2021-04-13 18:45:40 +05:30
Deepesh Garg
ad2d74576b Merge pull request #25165 from KaviyaPeriyasamy/version-12-hotfix-error-log-issue
fix: object referencing same memory address issue
2021-04-13 15:41:15 +05:30
Deepesh Garg
4ced989169 Merge pull request #25204 from ankush/invoice-name-12
fix(India): create property setters for shorter naming series (#25134)
2021-04-13 15:40:14 +05:30
Mohammad Hasnain Mohsin Rajan
a59523970b chore: add sider config (#24892)
Co-authored-by: Sagar Vora <sagar@resilient.tech>
2021-04-13 11:06:01 +05:30
Deepesh Garg
9f2b5ba565 Merge branch 'version-12-hotfix' into rcm_total_calculation_fix_v12 2021-04-12 18:59:30 +05:30
Anupam Kumar
878b10eff5 fix: don't delete mode of payment account details while deleting company transactions (#25218) 2021-04-12 10:37:12 +05:30
Deepesh Garg
83df26197b fix: Rounding adjustment for RCM 2021-04-11 18:45:22 +05:30
Rucha Mahabal
fb87ed3f62 Merge pull request #25216 from anupamvs/hr-compensatory-leave-request-err-msg-v12
fix: error message compensatory leave request
2021-04-08 09:52:24 +05:30
Deepesh Garg
2541ab178a fix: RCM tax calculation 2021-04-06 23:40:46 +05:30
Anupam
ac58e05bbb fix: error message compensatory leave request 2021-04-06 11:40:21 +05:30
Abdullah Abouzekry
34b6f9389c fix: sales order not saving due type mismatch in promo scheme (#24748) (#25056)
Co-authored-by: Ankush Menat <ankush@iwebnotes.com>
2021-04-06 10:14:51 +05:30
Sagar Vora
6678450ba0 fix(India): create property setters for shorter naming series (#25134) 2021-04-05 16:09:41 +05:30
Saqib
fa98c4b8d7 fix(e-invoice): mandatory pincode field not set in e-invoice (#25201) 2021-04-05 14:45:21 +05:30
Saqib
79c7be770c fix(india): critical e-invoicing fixes (#25166)
Co-authored-by: bhavesh95863 <34086262+bhavesh95863@users.noreply.github.com>
2021-04-05 11:01:46 +05:30
rohitwaghchaure
8acc3fbbf4 Merge pull request #25169 from rohitwaghchaure/fixed-incorrect-batch-selected-in-purchase-rceipt
fix: incorrect batch picked in subcontracted purchase receipt
2021-04-03 14:25:10 +05:30
Rohit Waghchaure
2e04026fd6 fix: incorrect batch picked in subcontracted purchase receipt 2021-04-03 14:20:30 +05:30
Kaviya Periyasamy
3707b004c4 fix: object referencing same memory address issue 2021-04-03 12:18:19 +05:30
Saqib
f8dcd06dad fix: santize_for_json is not defined (#25157) 2021-04-02 16:47:50 +05:30
bhavesh95863
15af590482 fix(regional): remove shipping address GSTIN validation for e-invoice (#25133)
Co-authored-by: Saqib <nextchamp.saqib@gmail.com>
2021-04-02 15:05:07 +05:30
Marica
9cc129c400 Merge pull request #25110 from ankush/mr_stopped_validation_v12
fix: do not fetch stopped MR in production plan
2021-04-02 13:16:13 +05:30
Marica
35c4a7a05d Merge branch 'version-12-hotfix' into mr_stopped_validation_v12 2021-04-02 13:15:11 +05:30
Saqib
883598890d fix: place of supply of e-invoicing (#25149) 2021-04-02 12:16:09 +05:30
Afshan
2479e070c4 fix: validation msg for TransDocNo e-invoicing (#25120) 2021-04-01 19:27:41 +05:30
Ankush Menat
8d31d21b88 fix: do not fetch stopped MR in production plan
- Ignore stopped MR while using fetch button
- Add filter on field inside child table.

Related issue: ISS-20-21-10757
2021-03-31 21:21:13 +05:30
Rohan
53a32fecdb fix: commit individual SLE rename for large datasets (#25085) 2021-03-31 15:23:04 +05:30
Sagar Vora
b904304268 fix: revert removed field; not standard in v12 2021-03-29 21:26:53 +05:30
Sagar Vora
bd742d7ad9 fix(Italy): setup, validations, optimisations 2021-03-29 21:21:19 +05:30
Marica
2a1365a278 Merge pull request #24986 from ankush/allow_zero_valuation_SR_v12
fix: Allow zero valuation in stock reconciliation
2021-03-26 12:52:52 +05:30
Deepesh Garg
56531908aa Merge pull request #24974 from deepeshgarg007/tds_check_fix_v12
fix: TDS check getting checked after reload
2021-03-26 12:37:06 +05:30
Marica
f2bede6275 Merge branch 'version-12-hotfix' into allow_zero_valuation_SR_v12 2021-03-25 20:06:51 +05:30
Jannat Patel
a52ea48a21 fix: serial no trim issue (#24950)
* fix: serial no trim issue

* fix: valid serial nos
2021-03-25 15:23:19 +05:30
Anupam Kumar
5bd58ef85c fix: opportunity-quotation mapping order status (#25002) 2021-03-25 11:46:20 +05:30
Ankush Menat
19193e8f1c fix: set valuation rate for customer items to zero
- In stock reconciliation always set valuation rate of customer provided
items to zero during validation.
- Let user know the valuation has been changed.
2021-03-23 14:29:12 +05:30
Ankush Menat
ebd230e748 test: customer item in stock reconciliation 2021-03-23 14:26:41 +05:30
Ankush Menat
bf91ee9b99 fix: Allow zero valuation in stock reconciliation
Stock reconciliation can not be done for customer provided item as they
have zero valuation. This change adds a checkbox in item table to allow
such items.

Related issue: ISS-20-21-10248
2021-03-23 14:24:54 +05:30
Deepesh Garg
bb3c44dbb3 fix: TDS check getting checked after reload 2021-03-22 19:42:02 +05:30
Marica
7a61696a25 Merge pull request #24935 from ankush/alt_tags_item_image_v12
feat: allow Item image alt
2021-03-22 11:43:46 +05:30
Marica
28432128be Merge branch 'version-12-hotfix' into alt_tags_item_image_v12 2021-03-22 11:28:50 +05:30
Saurabh
ce3a680324 Merge branch 'v12-pre-release' into version-12 2021-03-19 19:24:51 +05:30
Saurabh
786d78bce2 bumped to version 12.19.0 2021-03-19 19:44:51 +05:50
rohitwaghchaure
9e3e09f701 Merge pull request #24955 from rohitwaghchaure/revert-stock-balance-value-calculation-pre
fix: revert stock balance value calculation
2021-03-19 16:22:35 +05:30
Rohit Waghchaure
c2e2cf4933 fix: revert stock balance value calculation 2021-03-19 16:07:48 +05:30
rohitwaghchaure
ea50ab8696 Merge pull request #24868 from rohitwaghchaure/revert-stock-balance-value-calculation
fix: revert stock balance value calculation
2021-03-19 16:06:48 +05:30
Deepesh Garg
c22785877d Merge pull request #24952 from nextchamp-saqib/e-invoice-valdiation-fix
fix: NoneType object has no attribute len()
2021-03-19 12:55:30 +05:30
Saqib Ansari
14eeee5592 fix: NoneType object has no attribute len() 2021-03-19 12:51:15 +05:30
Deepesh Garg
4f4f60942c Merge pull request #24919 from deepeshgarg007/nil_exempt_gstr_3b_v12
fix(India): Incorrect Nil Exempt and Non GST amount in GSTR3B report
2021-03-18 21:02:12 +05:30
Shivam Mishra
437c771701 refactor: update confusing label 2021-03-18 12:39:42 +05:30
Shivam Mishra
f29cdb39a1 feat: add alt value in product page 2021-03-18 12:39:00 +05:30
Shivam Mishra
063ab520d3 feat: add image alt argument for product_image macros 2021-03-18 12:38:38 +05:30
Shivam Mishra
b2ae422ed7 feat: add image alt field in items 2021-03-18 12:37:59 +05:30
Deepesh Garg
6da7f65848 fix: Remove print statement 2021-03-17 18:15:24 +05:30
Deepesh Garg
4c6d068a73 fix: Group nil exempted and non gst items separately 2021-03-17 18:15:15 +05:30
Deepesh Garg
ef09599a9f fix(India): Incorrect Nil Exempt and Non GST amount in GSTR3B report 2021-03-17 16:16:33 +05:30
Marica
a1104f040d Merge pull request #24887 from shariquerik/item-attribute-fix-backport
fix: item attributes not editable until refresh
2021-03-16 15:39:36 +05:30
Anurag Mishra
c6a1e3b450 Merge pull request #24228 from YogendrasinhChavda/erpnext_fix_v12
[IMP][version-12] Improved code by adding operator to check condition.
2021-03-16 13:28:31 +05:30
Nabin Hait
238df8b3ec Merge branch 'version-12-hotfix' into v12-pre-release 2021-03-16 11:03:25 +05:30
shariquerik
4db8d13900 fix: item attributes not editable until refresh 2021-03-15 19:10:43 +05:30
Deepesh Garg
6cf37d58f1 fix: Unequal debit and credit issue on RCM Invoice (#24839)
* fix: Unequal debit and credit issue on RCM Invoice

* fix: Travis
2021-03-15 18:04:22 +05:30
Prssanna Desai
386b7fd2c3 fix: use method name as title in error log (#24880) 2021-03-15 18:03:03 +05:30
Ankush
f9f10ed743 fix: Add warning for invalid GST invoice numbers (#24837)
* fix: Add warning for invalid GST invoice numbers

GST Invoice numbers should be 16 characters alphanumeric with dash(/) or
slash(-) only. Add check for doc.name before saving and warn about
naming series.

* refactor: move regex patterns to global variables

Co-authored-by: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com>
2021-03-15 17:58:17 +05:30
Devin Slauenwhite
2e2f3f9578 fix: stock move dialog duplicate submit actions (#24859)
* fix: duplicate submit actions

* fix sider errors.
2021-03-15 17:57:37 +05:30
HENRY Florian
55d45532b4 fix: UOM length unit in global setup list is empty (#24853)
* When ERPNext is installed in localized language the category of UOM Conversion Factor is tranlasted into installed languaes. Filter must be locallized

* fix

* fix
2021-03-15 17:54:50 +05:30
Deepesh Garg
07e7f73488 Merge pull request #24874 from GangaManoj/filter-bank-reconciliation-v12
fix(Bank Reconciliation): Filter Bank Account drop-down list
2021-03-15 10:20:05 +05:30
Ganga Manoj
017d168b03 fix(Bank Reconciliation): Filter Bank Account drop-down list 2021-03-13 23:38:30 +05:30
Rohit Waghchaure
a9d48e5fbf fix: revert stock balance value calculation 2021-03-13 12:48:14 +05:30
Ankush Menat
5ae40871d8 fix: do not update PE title during data import (#24835)
* fix: do not update PE title during data import

Related issue: ISS-20-21-10132

* fix: make title field read only
2021-03-11 16:08:40 +05:30
Ankush Menat
86a163fce5 fix: use account_name only in consolidated report (#24834)
Don't use account_number and only rely on account_name for preparing
consolidated financial statement.

Related issue: ISS-20-21-10217
2021-03-11 16:07:35 +05:30
Rohan
aa90dc6aa3 fix: do not send emails to disabled users from Employee Onboarding (#24796) 2021-03-09 21:02:57 +05:30
HENRY Florian
5eb8eb8aa7 fix: Add french chart accounts with account number (#24763)
* add new franch account chart with numbers

* add new franch account chart with numbers

* add chart of account with code

* change name chart of accounte

* fix json unicode

* account format

* feat: add french accounting chart with account number

* remove debug
2021-03-09 20:32:30 +05:30
Marica
a69b8aa18d Merge pull request #24790 from ankush/track_settings_v12
fix: track setting changes
2021-03-09 13:30:28 +05:30
Marica
4450a075bd Merge branch 'version-12-hotfix' into track_settings_v12 2021-03-09 11:56:06 +05:30
rohitwaghchaure
3aede7da61 Merge pull request #24709 from rohitwaghchaure/fixed-stock-reco-incorrect-serial-no-issue
fix: incorrect serial no issue in the stock reco
2021-03-07 14:29:02 +05:30
Ankush Menat
2e8b06cf9f fix: track setting changes 2021-03-02 18:20:47 +05:30
Saqib
27f120bc7c fix(india): inflated item tax rate for e-invoicing (#24766)
* fix(india): inflated item tax rate for e-invoicing

* fix: credit note discount on net total
2021-03-01 10:46:17 +05:30
Ankush Menat
5feb20d94b feat: track changes to HR settings (#24740)
related issue: FR-ISS-259927
2021-02-25 19:05:25 +05:30
Afshan
27fbfbf34e fix: reference variable in pricing rule (#24714) 2021-02-25 19:01:58 +05:30
Ankush Menat
d389261230 fix(india): escape for special characters in JSON (bp #24695) (#24705) 2021-02-25 18:04:58 +05:30
Deepesh Garg
e9f8e5814a Merge pull request #24736 from ankush/opening_round_gl12
fix: make round off GLE always non-opening (bp #24723)
2021-02-25 15:17:55 +05:30
Ankush Menat
16193a614e fix: make round off GLE always non-opening
Opening GL entries can not be for profit and loss accounts. Round off
accounts are by default P&L account. Hence when making opening entry,
make round off entries as non-opening.

Related issue: ISS-20-21-09677
2021-02-25 10:22:49 +05:30
Afshan
2b2e205b74 fix: check if customer provided item while setting opening stock (#24633) 2021-02-24 19:05:29 +05:30
Afshan
9272ea838f fix: show custom button for saved projects (#24732)
* fix: show custom button for saved projects

* fix: slider
2021-02-24 18:13:29 +05:30
Afshan
80d9576bb9 fix: currency symbol in update items (#24727) 2021-02-24 16:51:35 +05:30
Afshan
c18a8c58dd fix: column names (#24713) 2021-02-24 14:39:00 +05:30
Rucha Mahabal
473fb55724 Merge pull request #24717 from pateljannat/issue-custom-button-v12
fix: custom buttons in issue
2021-02-24 11:48:06 +05:30
pateljannat
05a3c5a6bc fix: custom buttons in issue 2021-02-23 18:15:50 +05:30
Rohit Waghchaure
c39e206fc7 fix: incorrect serial no issue in the stock reco 2021-02-23 14:26:55 +05:30
Afshan
33539d49f1 fix: error message when making reverse journal entry (#24666) 2021-02-22 19:26:02 +05:30
Deepesh Garg
91a929df84 Merge pull request #24668 from pateljannat/gstr-1-unidentified-accounts-issue-v12
fix: excluding unidentified accounts from gstr-1
2021-02-20 17:28:13 +05:30
Deepesh Garg
e34f73c60b Merge pull request #24670 from deepeshgarg007/transaction_delete_fix_v12
fix: Do not delete GST Accounts from GST Settings on clearing transactions from Company Master
2021-02-19 10:58:13 +05:30
Deepesh Garg
a49ea67f16 fix: Do not delete GST Accounts from GST Settings on clearing transactions from Company Master 2021-02-19 10:56:54 +05:30
pateljannat
4f0c5e2cc7 fix: excluding unidentified accounts from gstr-1 2021-02-18 19:31:11 +05:30
Deepesh Garg
b0e53230bd fix: Prorata factor fixes in subscription (#24637)
* fix: Prorata factor fixes in subscription

* fix: Test Case
2021-02-16 07:49:59 +05:30
Deepesh Garg
1eb3d16667 Merge pull request #24634 from ankush/ladakh_gst_addition-v12hf
fix(India): Add GST state code for Ladakh
2021-02-15 21:12:14 +05:30
Ankush Menat
211a4cb833 fix(India): Add GST state code for Ladakh 2021-02-15 15:30:20 +05:30
rohitwaghchaure
b96c7e0a0f Merge pull request #24618 from rohitwaghchaure/fixed-incorrect-incoming-rate-for-sales-return
fix: incorrect incoming rate for the sales return
2021-02-12 14:20:02 +05:30
Rohit Waghchaure
37604c8d99 fix: incorrect incoming rate for the sales return 2021-02-12 13:17:10 +05:30
Afshan
edfbb5d3be fix: NoneType object has no attribute len() (#24617) 2021-02-12 12:40:52 +05:30
Nabin Hait
81ae1f363c Removed debug flag 2021-02-12 09:53:30 +05:30
Yogendrasinh Chavda
eb88b63ddd [IMP][version-12] Improved code by adding operator to check condition. 2020-12-28 17:40:52 +05:30
144 changed files with 5050 additions and 1646 deletions

32
.flake8 Normal file
View File

@@ -0,0 +1,32 @@
[flake8]
ignore =
E121,
E126,
E127,
E128,
E203,
E225,
E226,
E231,
E241,
E251,
E261,
E265,
E302,
E303,
E305,
E402,
E501,
E741,
W291,
W292,
W293,
W391,
W503,
W504,
F403,
B007,
B950,
W191,
max-line-length = 200

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

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

View File

@@ -40,8 +40,7 @@ install:
- cd ~
- nvm install 10
- git clone https://github.com/frappe/bench --depth 1
- pip install -e ./bench
- pip install -U frappe-bench --only-binary='all'
- git clone https://github.com/frappe/frappe --branch $TRAVIS_BRANCH --depth 1
- bench init --skip-assets --frappe-path ~/frappe --python $(which python) frappe-bench

View File

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

View File

@@ -72,16 +72,14 @@
"138-Autres subventions d'investissement (m\u00eame ventilation que celle du compte 131)": {},
"139-Subventions d'investissement inscrites au compte de r\u00e9sultat": {
"1391-Subventions d'\u00e9quipement": {
"13911-Subventions d'\u00e9quipement": {
"13911-Etat": {},
"13912-R\u00e9gions": {},
"13913-D\u00e9partements": {},
"13914-Communes": {},
"13915-Collectivit\u00e9s publiques": {},
"13916-Entreprises publiques": {},
"13917-Entreprises et organismes priv\u00e9s": {},
"13918-Autres": {}
}
"13911-Etat": {},
"13912-R\u00e9gions": {},
"13913-D\u00e9partements": {},
"13914-Communes": {},
"13915-Collectivit\u00e9s publiques": {},
"13916-Entreprises publiques": {},
"13917-Entreprises et organismes priv\u00e9s": {},
"13918-Autres": {}
},
"1398-Autres subventions d'investissement (m\u00eame ventilation que celle du compte 1391)": {}
}
@@ -536,8 +534,8 @@
"3312-Produits en cours P2": {}
},
"335-Travaux en cours": {
"Travaux en cours T1": {},
"Travaux en cours T2": {}
"3351-Travaux en cours T1": {},
"3352-Travaux en cours T2": {}
}
},
"34-En-cours de production de services": {
@@ -595,7 +593,9 @@
"371-Marchandises (ou groupe) A": {},
"372-Marchandises (ou groupe) B": {}
},
"38-Stocks en voie d'acheminement, mis en d\u00e9p\u00f4t ou donn\u00e9s en consignation (en cas d'inventaire permanent en comptabilit\u00e9 g\u00e9n\u00e9rale)": {},
"38-Stocks en voie d'acheminement, mis en d\u00e9p\u00f4t ou donn\u00e9s en consignation (en cas d'inventaire permanent en comptabilit\u00e9 g\u00e9n\u00e9rale)": {
"account_type": "Stock"
},
"39-D\u00e9pr\u00e9ciations des stocks et en-cours": {
"391-D\u00e9pr\u00e9ciations des mati\u00e8res premi\u00e8res (et fournitures)": {
"3911-Mati\u00e8res (ou groupe) A": {},

View File

@@ -109,5 +109,4 @@ erpnext.integrations.refreshPlaidLink = class refreshPlaidLink {
plaid_success(token, response) {
frappe.show_alert({ message: __('Plaid Link Updated'), indicator: 'green' });
}
};
};

View File

@@ -21,6 +21,14 @@ frappe.ui.form.on("Bank Reconciliation", {
};
});
frm.set_query("bank_account", function() {
return {
"filters": {
"is_company_account": 1
}
};
});
frm.set_value("from_date", frappe.datetime.month_start());
frm.set_value("to_date", frappe.datetime.month_end());
},

View File

@@ -7,19 +7,19 @@ DEFAULT_MAPPERS = [
'section_header': 'Cash flows from operating activities',
'section_leader': 'Adjustments for',
'section_name': 'Operating Activities',
'position': 0,
'position': 1,
'section_subtotal': 'Cash generated from operations',
},
{
'doctype': 'Cash Flow Mapper',
'position': 1,
'position': 2,
'section_footer': 'Net cash used in investing activities',
'section_header': 'Cash flows from investing activities',
'section_name': 'Investing Activities'
},
{
'doctype': 'Cash Flow Mapper',
'position': 2,
'position': 3,
'section_footer': 'Net cash used in financing activites',
'section_header': 'Cash flows from financing activities',
'section_name': 'Financing Activities',

View File

@@ -81,10 +81,11 @@ class ExchangeRateRevaluation(Document):
sum(debit) - sum(credit) as balance
from `tabGL Entry`
where account in (%s)
group by account, party_type, party
and posting_date <= %s
group by account, NULLIF(party_type,''), NULLIF(party,'')
having sum(debit) != sum(credit)
order by account
""" % ', '.join(['%s']*len(accounts)), tuple(accounts), as_dict=1)
""" % (', '.join(['%s']*len(accounts)), '%s'), tuple(accounts + [self.posting_date]), as_dict=1)
return account_details
@@ -124,9 +125,9 @@ class ExchangeRateRevaluation(Document):
"party_type": d.get("party_type"),
"party": d.get("party"),
"account_currency": d.get("account_currency"),
"balance": d.get("balance_in_account_currency"),
dr_or_cr: abs(d.get("balance_in_account_currency")),
"exchange_rate":d.get("new_exchange_rate"),
"balance": flt(d.get("balance_in_account_currency"), d.precision("balance_in_account_currency")),
dr_or_cr: flt(abs(d.get("balance_in_account_currency")), d.precision("balance_in_account_currency")),
"exchange_rate": flt(d.get("new_exchange_rate"), d.precision("new_exchange_rate")),
"reference_type": "Exchange Rate Revaluation",
"reference_name": self.name,
})
@@ -135,9 +136,9 @@ class ExchangeRateRevaluation(Document):
"party_type": d.get("party_type"),
"party": d.get("party"),
"account_currency": d.get("account_currency"),
"balance": d.get("balance_in_account_currency"),
reverse_dr_or_cr: abs(d.get("balance_in_account_currency")),
"exchange_rate": d.get("current_exchange_rate"),
"balance": flt(d.get("balance_in_account_currency"), d.precision("balance_in_account_currency")),
reverse_dr_or_cr: flt(abs(d.get("balance_in_account_currency")), d.precision("balance_in_account_currency")),
"exchange_rate": flt(d.get("current_exchange_rate"), d.precision("current_exchange_rate")),
"reference_type": "Exchange Rate Revaluation",
"reference_name": self.name
})
@@ -166,9 +167,9 @@ def get_account_details(account, company, posting_date, party_type=None, party=N
account_details = {}
company_currency = erpnext.get_company_currency(company)
balance = get_balance_on(account, party_type=party_type, party=party, in_account_currency=False)
balance = get_balance_on(account, date=posting_date, party_type=party_type, party=party, in_account_currency=False)
if balance:
balance_in_account_currency = get_balance_on(account, party_type=party_type, party=party)
balance_in_account_currency = get_balance_on(account, date=posting_date, party_type=party_type, party=party)
current_exchange_rate = balance / balance_in_account_currency if balance_in_account_currency else 0
new_exchange_rate = get_exchange_rate(account_currency, company_currency, posting_date)
new_balance_in_base_currency = balance_in_account_currency * new_exchange_rate

View File

@@ -97,8 +97,7 @@ class GLEntry(Document):
def check_pl_account(self):
if self.is_opening=='Yes' and \
frappe.db.get_value("Account", self.account, "report_type")=="Profit and Loss" and \
self.voucher_type not in ['Purchase Invoice', 'Sales Invoice']:
frappe.db.get_value("Account", self.account, "report_type")=="Profit and Loss":
frappe.throw(_("{0} {1}: 'Profit and Loss' type account {2} not allowed in Opening Entry")
.format(self.voucher_type, self.voucher_no, self.account))
@@ -294,4 +293,8 @@ def rename_temporarily_named_docs(doctype):
oldname = doc.name
set_name_from_naming_options(frappe.get_meta(doctype).autoname, doc)
newname = doc.name
frappe.db.sql("""UPDATE `tab{}` SET name = %s, to_rename = 0 where name = %s""".format(doctype), (newname, oldname))
frappe.db.sql(
"UPDATE `tab{}` SET name = %s, to_rename = 0 where name = %s".format(doctype),
(newname, oldname),
auto_commit=True
)

View File

@@ -29,7 +29,11 @@ class JournalEntry(AccountsController):
self.validate_entries_for_advance()
self.validate_multi_currency()
self.set_amounts_in_company_currency()
self.validate_total_debit_and_credit()
# Do not validate while importing via data import
if not frappe.flags.in_import:
self.validate_total_debit_and_credit()
self.validate_against_jv()
self.validate_reference_doc()
self.set_against_account()
@@ -207,11 +211,11 @@ class JournalEntry(AccountsController):
if d.reference_type=="Journal Entry":
account_root_type = frappe.db.get_value("Account", d.account, "root_type")
if account_root_type == "Asset" and flt(d.debit) > 0:
frappe.throw(_("For {0}, only credit accounts can be linked against another debit entry")
.format(d.account))
frappe.throw(_("Row #{0}: For {1}, you can select reference document only if account gets credited")
.format(d.idx, d.account))
elif account_root_type == "Liability" and flt(d.credit) > 0:
frappe.throw(_("For {0}, only debit accounts can be linked against another credit entry")
.format(d.account))
frappe.throw(_("Row #{0}: For {1}, you can select reference document only if account gets debited")
.format(d.idx, d.account))
if d.reference_name == self.name:
frappe.throw(_("You can not enter current voucher in 'Against Journal Entry' column"))
@@ -1047,4 +1051,4 @@ def make_reverse_journal_entry(source_name, target_doc=None):
},
}, target_doc)
return doclist
return doclist

View File

@@ -593,12 +593,22 @@ frappe.ui.form.on('Payment Entry', {
{fieldtype:"Column Break"},
{fieldtype:"Float", label: __("Less Than Amount"), fieldname:"outstanding_amt_less_than"},
{fieldtype:"Section Break"},
{fieldtype:"Link", label:__("Cost Center"), fieldname:"cost_center", options:"Cost Center",
"get_query": function() {
return {
"filters": {"company": frm.doc.company}
}
}
},
{fieldtype:"Column Break"},
{fieldtype:"Section Break"},
{fieldtype:"Check", label: __("Allocate Payment Amount"), fieldname:"allocate_payment_amount", default:1},
];
frappe.prompt(fields, function(filters){
frappe.flags.allocate_payment_amount = true;
frm.events.validate_filters_data(frm, filters);
frm.doc.cost_center = filters.cost_center;
frm.events.get_outstanding_documents(frm, filters);
}, __("Filters"), __("Get Outstanding Documents"));
},
@@ -1041,18 +1051,10 @@ frappe.ui.form.on('Payment Entry', {
},
callback: function(r, rt) {
if(r.message) {
frappe.run_serially([
() => {
frm.set_value("paid_from_account_balance", r.message.paid_from_account_balance);
frm.set_value("paid_to_account_balance", r.message.paid_to_account_balance);
frm.set_value("party_balance", r.message.party_balance);
},
() => {
if(frm.doc.payment_type != "Internal") {
frm.clear_table("references");
}
}
]);
}
}

View File

@@ -531,7 +531,8 @@
"fieldtype": "Data",
"hidden": 1,
"label": "Title",
"print_hide": 1
"print_hide": 1,
"read_only": 1
},
{
"depends_on": "party",
@@ -575,7 +576,7 @@
}
],
"is_submittable": 1,
"modified": "2019-11-06 12:59:43.151721",
"modified": "2021-03-10 13:05:16.958866",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Entry",
@@ -619,4 +620,4 @@
"sort_order": "DESC",
"title_field": "title",
"track_changes": 1
}
}

View File

@@ -441,6 +441,10 @@ class PaymentEntry(AccountsController):
.format(total_negative_outstanding), InvalidPaymentEntry)
def set_title(self):
if frappe.flags.in_import and self.title:
# do not set title dynamically if title exists during data import.
return
if self.payment_type in ("Receive", "Pay"):
self.title = self.party
else:

View File

@@ -1,283 +1,95 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "ACC-PCV-.YYYY.-.#####",
"beta": 0,
"creation": "2013-01-10 16:34:07",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"editable_grid": 0,
"engine": "InnoDB",
"actions": [],
"autoname": "ACC-PCV-.YYYY.-.#####",
"creation": "2013-01-10 16:34:07",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"transaction_date",
"posting_date",
"fiscal_year",
"amended_from",
"company",
"cost_center_wise_pnl",
"column_break1",
"closing_account_head",
"remarks"
],
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "transaction_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": "Transaction Date",
"length": 0,
"no_copy": 0,
"oldfieldname": "transaction_date",
"oldfieldtype": "Date",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "transaction_date",
"fieldtype": "Date",
"label": "Transaction Date",
"oldfieldname": "transaction_date",
"oldfieldtype": "Date"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "posting_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": "Posting Date",
"length": 0,
"no_copy": 0,
"oldfieldname": "posting_date",
"oldfieldtype": "Date",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "posting_date",
"fieldtype": "Date",
"label": "Posting Date",
"oldfieldname": "posting_date",
"oldfieldtype": "Date",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "fiscal_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": "Closing Fiscal Year",
"length": 0,
"no_copy": 0,
"oldfieldname": "fiscal_year",
"oldfieldtype": "Select",
"options": "Fiscal Year",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "fiscal_year",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Closing Fiscal Year",
"oldfieldname": "fiscal_year",
"oldfieldtype": "Select",
"options": "Fiscal Year",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "amended_from",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 1,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Amended From",
"length": 0,
"no_copy": 1,
"oldfieldname": "amended_from",
"oldfieldtype": "Data",
"options": "Period Closing Voucher",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "amended_from",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "Amended From",
"no_copy": 1,
"oldfieldname": "amended_from",
"oldfieldtype": "Data",
"options": "Period Closing Voucher",
"read_only": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Company",
"length": 0,
"no_copy": 0,
"oldfieldname": "company",
"oldfieldtype": "Select",
"options": "Company",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "company",
"fieldtype": "Link",
"label": "Company",
"oldfieldname": "company",
"oldfieldtype": "Select",
"options": "Company",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break1",
"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,
"oldfieldtype": "Column Break",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "column_break1",
"fieldtype": "Column Break",
"oldfieldtype": "Column Break"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"description": "The account head under Liability or Equity, in which Profit/Loss will be booked",
"fieldname": "closing_account_head",
"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": "Closing Account Head",
"length": 0,
"no_copy": 0,
"oldfieldname": "closing_account_head",
"oldfieldtype": "Link",
"options": "Account",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"description": "The account head under Liability or Equity, in which Profit/Loss will be booked",
"fieldname": "closing_account_head",
"fieldtype": "Link",
"label": "Closing Account Head",
"oldfieldname": "closing_account_head",
"oldfieldtype": "Link",
"options": "Account",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "remarks",
"fieldtype": "Small Text",
"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": "Remarks",
"length": 0,
"no_copy": 0,
"oldfieldname": "remarks",
"oldfieldtype": "Small Text",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"fieldname": "remarks",
"fieldtype": "Small Text",
"label": "Remarks",
"oldfieldname": "remarks",
"oldfieldtype": "Small Text",
"reqd": 1
},
{
"default": "0",
"fieldname": "cost_center_wise_pnl",
"fieldtype": "Check",
"label": "Book Cost Center-Wise Profit/Loss"
}
],
"has_web_view": 0,
@@ -291,60 +103,43 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-08-21 16:15:49.089450",
"modified": "2021-05-20 15:27:37.210458",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Period Closing Voucher",
"owner": "jai@webnotestech.com",
"permissions": [
{
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 1,
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"submit": 1,
"write": 1
},
},
{
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 1,
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"share": 1,
"submit": 1,
"write": 1
}
],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"search_fields": "posting_date, fiscal_year",
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "closing_account_head",
"track_changes": 0,
"track_seen": 0,
"track_views": 0
],
"search_fields": "posting_date, fiscal_year",
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "closing_account_head"
}

View File

@@ -50,63 +50,96 @@ class PeriodClosingVoucher(AccountsController):
def make_gl_entries(self):
gl_entries = []
net_pl_balance = 0
dimension_fields = ['t1.cost_center']
net_pl_balance = 0
accounting_dimensions = get_accounting_dimensions()
for dimension in accounting_dimensions:
dimension_fields.append('t1.{0}'.format(dimension))
dimension_filters, default_dimensions = get_dimension_filters()
pl_accounts = self.get_pl_balances(dimension_fields)
pl_accounts = self.get_pl_balances()
for acc in pl_accounts:
if flt(acc.balance_in_company_currency):
if flt(acc.bal_in_company_currency):
gl_entries.append(self.get_gl_dict({
"account": acc.account,
"cost_center": acc.cost_center,
"account_currency": acc.account_currency,
"debit_in_account_currency": abs(flt(acc.balance_in_account_currency)) \
if flt(acc.balance_in_account_currency) < 0 else 0,
"debit": abs(flt(acc.balance_in_company_currency)) \
if flt(acc.balance_in_company_currency) < 0 else 0,
"credit_in_account_currency": abs(flt(acc.balance_in_account_currency)) \
if flt(acc.balance_in_account_currency) > 0 else 0,
"credit": abs(flt(acc.balance_in_company_currency)) \
if flt(acc.balance_in_company_currency) > 0 else 0
"debit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) < 0 else 0,
"debit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) < 0 else 0,
"credit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) > 0 else 0,
"credit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) > 0 else 0
}, item=acc))
net_pl_balance += flt(acc.balance_in_company_currency)
net_pl_balance += flt(acc.bal_in_company_currency)
if net_pl_balance:
cost_center = frappe.db.get_value("Company", self.company, "cost_center")
gl_entry = self.get_gl_dict({
"account": self.closing_account_head,
"debit_in_account_currency": abs(net_pl_balance) if net_pl_balance > 0 else 0,
"debit": abs(net_pl_balance) if net_pl_balance > 0 else 0,
"credit_in_account_currency": abs(net_pl_balance) if net_pl_balance < 0 else 0,
"credit": abs(net_pl_balance) if net_pl_balance < 0 else 0,
"cost_center": cost_center
})
for dimension in accounting_dimensions:
gl_entry.update({
dimension: default_dimensions.get(self.company, {}).get(dimension)
})
gl_entries.append(gl_entry)
if self.cost_center_wise_pnl:
costcenter_wise_gl_entries = self.get_costcenter_wise_pnl_gl_entries(pl_accounts)
gl_entries += costcenter_wise_gl_entries
else:
gl_entry = self.get_pnl_gl_entry(net_pl_balance)
gl_entries.append(gl_entry)
from erpnext.accounts.general_ledger import make_gl_entries
make_gl_entries(gl_entries)
def get_pnl_gl_entry(self, net_pl_balance):
cost_center = frappe.db.get_value("Company", self.company, "cost_center")
gl_entry = self.get_gl_dict({
"account": self.closing_account_head,
"debit_in_account_currency": abs(net_pl_balance) if net_pl_balance > 0 else 0,
"debit": abs(net_pl_balance) if net_pl_balance > 0 else 0,
"credit_in_account_currency": abs(net_pl_balance) if net_pl_balance < 0 else 0,
"credit": abs(net_pl_balance) if net_pl_balance < 0 else 0,
"cost_center": cost_center
})
self.update_default_dimensions(gl_entry)
return gl_entry
def get_costcenter_wise_pnl_gl_entries(self, pl_accounts):
company_cost_center = frappe.db.get_value("Company", self.company, "cost_center")
gl_entries = []
for acc in pl_accounts:
if flt(acc.bal_in_company_currency):
gl_entry = self.get_gl_dict({
"account": self.closing_account_head,
"cost_center": acc.cost_center or company_cost_center,
"account_currency": acc.account_currency,
"debit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) > 0 else 0,
"debit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) > 0 else 0,
"credit_in_account_currency": abs(flt(acc.bal_in_account_currency)) if flt(acc.bal_in_account_currency) < 0 else 0,
"credit": abs(flt(acc.bal_in_company_currency)) if flt(acc.bal_in_company_currency) < 0 else 0
}, item=acc)
self.update_default_dimensions(gl_entry)
gl_entries.append(gl_entry)
return gl_entries
def update_default_dimensions(self, gl_entry):
if not self.accounting_dimensions:
self.accounting_dimensions = get_accounting_dimensions()
_, default_dimensions = get_dimension_filters()
for dimension in self.accounting_dimensions:
gl_entry.update({
dimension: default_dimensions.get(self.company, {}).get(dimension)
})
def get_pl_balances(self):
"""Get balance for dimension-wise pl accounts"""
dimension_fields = ['t1.cost_center']
self.accounting_dimensions = get_accounting_dimensions()
for dimension in self.accounting_dimensions:
dimension_fields.append('t1.{0}'.format(dimension))
def get_pl_balances(self, dimension_fields):
"""Get balance for pl accounts"""
return frappe.db.sql("""
select
t1.account, t2.account_currency, {dimension_fields},
sum(t1.debit_in_account_currency) - sum(t1.credit_in_account_currency) as balance_in_account_currency,
sum(t1.debit) - sum(t1.credit) as balance_in_company_currency
sum(t1.debit_in_account_currency) - sum(t1.credit_in_account_currency) as bal_in_account_currency,
sum(t1.debit) - sum(t1.credit) as bal_in_company_currency
from `tabGL Entry` t1, `tabAccount` t2
where t1.account = t2.name and t2.report_type = 'Profit and Loss'
and t2.docstatus < 2 and t2.company = %s

View File

@@ -8,6 +8,7 @@ import frappe
from frappe.utils import flt, today
from erpnext.accounts.utils import get_fiscal_year, now
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
class TestPeriodClosingVoucher(unittest.TestCase):
def test_closing_entry(self):
@@ -65,6 +66,58 @@ class TestPeriodClosingVoucher(unittest.TestCase):
self.assertEqual(gle_for_random_expense_account[0].amount_in_account_currency,
-1*random_expense_account[0].balance_in_account_currency)
def test_cost_center_wise_posting(self):
frappe.db.sql("delete from `tabGL Entry` where company='Test PCV Company'")
company = create_company()
surplus_account = create_account()
cost_center1 = create_cost_center("Test Cost Center 1")
cost_center2 = create_cost_center("Test Cost Center 2")
create_sales_invoice(
company=company,
cost_center=cost_center1,
income_account="Sales - TPC",
expense_account="Cost of Goods Sold - TPC",
rate=400,
debit_to="Debtors - TPC"
)
create_sales_invoice(
company=company,
cost_center=cost_center2,
income_account="Sales - TPC",
expense_account="Cost of Goods Sold - TPC",
rate=200,
debit_to="Debtors - TPC"
)
pcv = frappe.get_doc({
"transaction_date": today(),
"posting_date": today(),
"fiscal_year": get_fiscal_year(today())[0],
"company": "Test PCV Company",
"cost_center_wise_pnl": 1,
"closing_account_head": surplus_account,
"remarks": "Test",
"doctype": "Period Closing Voucher"
})
pcv.insert()
pcv.submit()
expected_gle = (
('Sales - TPC', 200.0, 0.0, cost_center2),
(surplus_account, 0.0, 200.0, cost_center2),
('Sales - TPC', 400.0, 0.0, cost_center1),
(surplus_account, 0.0, 400.0, cost_center1)
)
pcv_gle = frappe.db.sql("""
select account, debit, credit, cost_center from `tabGL Entry` where voucher_no=%s
""", (pcv.name))
self.assertTrue(pcv_gle, expected_gle)
def make_period_closing_voucher(self):
pcv = frappe.get_doc({
"doctype": "Period Closing Voucher",
@@ -80,6 +133,38 @@ class TestPeriodClosingVoucher(unittest.TestCase):
return pcv
def create_company():
company = frappe.get_doc({
'doctype': 'Company',
'company_name': "Test PCV Company",
'country': 'United States',
'default_currency': 'USD'
})
company.insert(ignore_if_duplicate = True)
return company.name
def create_account():
account = frappe.get_doc({
"account_name": "Reserve and Surplus",
"is_group": 0,
"company": "Test PCV Company",
"root_type": "Liability",
"report_type": "Balance Sheet",
"account_currency": "USD",
"parent_account": "Current Liabilities - TPC",
"doctype": "Account"
}).insert(ignore_if_duplicate = True)
return account.name
def create_cost_center(cc_name):
costcenter = frappe.get_doc({
"company": "Test PCV Company",
"cost_center_name": cc_name,
"doctype": "Cost Center",
"parent_cost_center": "Test PCV Company - TPC"
})
costcenter.insert(ignore_if_duplicate = True)
return costcenter.name
test_dependencies = ["Customer", "Cost Center"]
test_records = frappe.get_test_records("Period Closing Voucher")

View File

@@ -131,7 +131,7 @@ class PricingRule(Document):
for d in self.items:
max_discount = frappe.get_cached_value("Item", d.item_code, "max_discount")
if max_discount and flt(self.discount_percentage) > flt(max_discount):
throw(_("Max discount allowed for item: {0} is {1}%").format(self.item_code, max_discount))
throw(_("Max discount allowed for item: {0} is {1}%").format(d.item_code, max_discount))
def validate_price_list_with_currency(self):
if self.currency and self.for_price_list:

View File

@@ -467,7 +467,7 @@ def apply_pricing_rule_on_transaction(doc):
if not d.get(pr_field): continue
if d.validate_applied_rule and doc.get(field) < d.get(pr_field):
if d.validate_applied_rule and doc.get(field) is not None and doc.get(field) < d.get(pr_field):
frappe.msgprint(_("User has not applied rule on the invoice {0}")
.format(doc.name))
else:

View File

@@ -509,7 +509,7 @@ frappe.ui.form.on("Purchase Invoice", {
},
onload: function(frm) {
if(frm.doc.__onload) {
if(frm.doc.__onload && frm.is_new()) {
if(frm.doc.supplier) {
frm.doc.apply_tds = frm.doc.__onload.supplier_tds ? 1 : 0;
}

View File

@@ -43,7 +43,7 @@
}
],
"grand_total": 0,
"naming_series": "_T-BILL",
"naming_series": "T-PINV-",
"taxes": [
{
"account_head": "_Test Account Shipping Charges - _TC",
@@ -168,7 +168,7 @@
}
],
"grand_total": 0,
"naming_series": "_T-Purchase Invoice-",
"naming_series": "T-PINV-",
"taxes": [
{
"account_head": "_Test Account Shipping Charges - _TC",

View File

@@ -450,7 +450,7 @@ class SalesInvoice(SellingController):
# set pos values in items
for item in self.get("items"):
if item.get('item_code'):
profile_details = get_pos_profile_item_details(pos, frappe._dict(item.as_dict()), pos)
profile_details = get_pos_profile_item_details(pos, frappe._dict(item.as_dict()), pos, update_data=True)
for fname, val in iteritems(profile_details):
if (not for_validate) or (for_validate and not item.get(fname)):
item.set(fname, val)
@@ -539,7 +539,7 @@ class SalesInvoice(SellingController):
def add_remarks(self):
if not self.remarks:
if self.po_no and self.po_date:
self.remarks = _("Against Customer Order {0} dated {1}").format(self.po_no,
self.remarks = _("Against Customer Order {0} dated {1}").format(self.po_no,
formatdate(self.po_date))
else:
self.remarks = _("No Remarks")

View File

@@ -30,7 +30,7 @@
"base_grand_total": 561.8,
"grand_total": 561.8,
"is_pos": 0,
"naming_series": "_T-Sales Invoice-",
"naming_series": "T-SINV-",
"base_net_total": 500.0,
"taxes": [
{
@@ -103,7 +103,7 @@
"base_grand_total": 630.0,
"grand_total": 630.0,
"is_pos": 0,
"naming_series": "_T-Sales Invoice-",
"naming_series": "T-SINV-",
"base_net_total": 500.0,
"taxes": [
{
@@ -174,7 +174,7 @@
],
"grand_total": 0,
"is_pos": 0,
"naming_series": "_T-Sales Invoice-",
"naming_series": "T-SINV-",
"taxes": [
{
"account_head": "_Test Account Shipping Charges - _TC",
@@ -300,7 +300,7 @@
],
"grand_total": 0,
"is_pos": 0,
"naming_series": "_T-Sales Invoice-",
"naming_series": "T-SINV-",
"taxes": [
{
"account_head": "_Test Account Excise Duty - _TC",

View File

@@ -1860,7 +1860,17 @@ class TestSalesInvoice(unittest.TestCase):
def test_einvoice_submission_without_irn(self):
# init
frappe.db.set_value('E Invoice Settings', 'E Invoice Settings', 'enable', 1)
einvoice_settings = frappe.get_doc('E Invoice Settings')
einvoice_settings.enable = 1
einvoice_settings.applicable_from = nowdate()
einvoice_settings.append('credentials', {
'company': '_Test Company',
'gstin': '27AAECE4835E1ZR',
'username': 'test',
'password': 'test'
})
einvoice_settings.save()
country = frappe.flags.country
frappe.flags.country = 'India'
@@ -1871,7 +1881,8 @@ class TestSalesInvoice(unittest.TestCase):
si.submit()
# reset
frappe.db.set_value('E Invoice Settings', 'E Invoice Settings', 'enable', 0)
einvoice_settings = frappe.get_doc('E Invoice Settings')
einvoice_settings.enable = 0
frappe.flags.country = country
def test_einvoice_json(self):
@@ -2063,6 +2074,7 @@ def create_sales_invoice(**args):
si.return_against = args.return_against
si.currency=args.currency or "INR"
si.conversion_rate = args.conversion_rate or 1
si.naming_series = args.naming_series or "T-SINV-"
si.append("items", {
"item_code": args.item or args.item_code or "_Test Item",

View File

@@ -169,7 +169,7 @@ class ShareTransfer(Document):
def folio_no_validation(self):
shareholders = ['from_shareholder', 'to_shareholder']
shareholders = [shareholder for shareholder in shareholders if self.get(shareholder) is not '']
shareholders = [shareholder for shareholder in shareholders if self.get(shareholder) != '']
for shareholder in shareholders:
doc = self.get_shareholder_doc(self.get(shareholder))
if doc.company != self.company:

View File

@@ -30,6 +30,7 @@
"additional_discount_percentage",
"additional_discount_amount",
"sb_3",
"submit_invoice",
"invoices",
"accounting_dimensions_section",
"dimension_col_break"
@@ -202,9 +203,15 @@
"fieldname": "generate_new_invoices_past_due_date",
"fieldtype": "Check",
"label": "Generate New Invoices Past Due Date"
},
{
"default": "1",
"fieldname": "submit_invoice",
"fieldtype": "Check",
"label": "Submit Invoice Automatically"
}
],
"modified": "2020-11-29 22:46:14.879289",
"modified": "2021-05-03 13:35:21.422940",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Subscription",

View File

@@ -289,7 +289,9 @@ class Subscription(Document):
invoice.flags.ignore_mandatory = True
invoice.save()
invoice.submit()
if self.submit_invoice:
invoice.submit()
return invoice

View File

@@ -163,7 +163,7 @@ def get_tds_amount(suppliers, net_total, company, tax_details, fiscal_year_detai
debit_note_amount = get_debit_note_amount(suppliers, year_start_date, year_end_date)
supplier_credit_amount -= debit_note_amount
if ((tax_details.get('threshold', 0) and supplier_credit_amount >= tax_details.threshold)
if ((tax_details.get('threshold', 0) and net_total >= tax_details.threshold)
or (tax_details.get('cumulative_threshold', 0) and supplier_credit_amount >= tax_details.cumulative_threshold)):
if ldc and is_valid_certificate(ldc.valid_from, ldc.valid_upto, posting_date, tds_deducted, net_total,

View File

@@ -83,47 +83,6 @@ class TestTaxWithholdingCategory(unittest.TestCase):
for d in invoices:
d.cancel()
def test_single_threshold_tds_with_previous_vouchers(self):
invoices = []
frappe.db.set_value("Supplier", "Test TDS Supplier2", "tax_withholding_category", "Single Threshold TDS")
pi = create_purchase_invoice(supplier="Test TDS Supplier2")
pi.submit()
invoices.append(pi)
pi = create_purchase_invoice(supplier="Test TDS Supplier2")
pi.submit()
invoices.append(pi)
self.assertEqual(pi.taxes_and_charges_deducted, 2000)
self.assertEqual(pi.grand_total, 8000)
# delete invoices to avoid clashing
for d in invoices:
d.cancel()
def test_single_threshold_tds_with_previous_vouchers_and_no_tds(self):
invoices = []
frappe.db.set_value("Supplier", "Test TDS Supplier2", "tax_withholding_category", "Single Threshold TDS")
pi = create_purchase_invoice(supplier="Test TDS Supplier2")
pi.submit()
invoices.append(pi)
# TDS not applied
pi = create_purchase_invoice(supplier="Test TDS Supplier2", do_not_apply_tds=True)
pi.submit()
invoices.append(pi)
pi = create_purchase_invoice(supplier="Test TDS Supplier2")
pi.submit()
invoices.append(pi)
self.assertEqual(pi.taxes_and_charges_deducted, 2000)
self.assertEqual(pi.grand_total, 8000)
# delete invoices to avoid clashing
for d in invoices:
d.cancel()
def create_purchase_invoice(**args):
# return sales invoice doc object
item = frappe.get_doc('Item', {'item_name': 'TDS Item'})

View File

@@ -147,7 +147,7 @@ def make_entry(args, adv_adj, update_outstanding, from_repost=False):
gle.submit()
def validate_account_for_perpetual_inventory(gl_map):
if cint(erpnext.is_perpetual_inventory_enabled(gl_map[0].company)):
if cint(erpnext.is_perpetual_inventory_enabled(gl_map[0].company)) and gl_map[0].voucher_type=="Journal Entry":
account_list = [gl_entries.account for gl_entries in gl_map]
aii_accounts = [d.name for d in frappe.get_all("Account",
@@ -160,13 +160,12 @@ def validate_account_for_perpetual_inventory(gl_map):
account_bal, stock_bal, warehouse_list = get_stock_and_account_balance(account,
gl_map[0].posting_date, gl_map[0].company)
if gl_map[0].voucher_type=="Journal Entry":
# In case of Journal Entry, there are no corresponding SL entries,
# hence deducting currency amount
account_bal -= flt(gl_map[0].debit) - flt(gl_map[0].credit)
if account_bal == stock_bal:
frappe.throw(_("Account: {0} can only be updated via Stock Transactions")
.format(account), StockAccountInvalidTransaction)
# In case of Journal Entry, there are no corresponding SL entries,
# hence deducting currency amount
account_bal -= flt(gl_map[0].debit) - flt(gl_map[0].credit)
if account_bal == stock_bal:
frappe.throw(_("Account: {0} can only be updated via Stock Transactions")
.format(account), StockAccountInvalidTransaction)
# This has been comment for a temporary, will add this code again on release of immutable ledger
# elif account_bal != stock_bal:
@@ -240,10 +239,10 @@ def make_round_off_gle(gl_map, debit_credit_diff, precision):
for d in gl_map:
if d.account == round_off_account:
round_off_gle = d
if d.debit_in_account_currency:
debit_credit_diff -= flt(d.debit_in_account_currency)
if d.debit:
debit_credit_diff -= flt(d.debit)
else:
debit_credit_diff += flt(d.credit_in_account_currency)
debit_credit_diff += flt(d.credit)
round_off_account_exists = True
if round_off_account_exists and abs(debit_credit_diff) <= (1.0 / (10**precision)):
@@ -252,7 +251,7 @@ def make_round_off_gle(gl_map, debit_credit_diff, precision):
if not round_off_gle:
for k in ["voucher_type", "voucher_no", "company",
"posting_date", "remarks", "is_opening"]:
"posting_date", "remarks"]:
round_off_gle[k] = gl_map[0][k]
round_off_gle.update({
@@ -264,6 +263,7 @@ def make_round_off_gle(gl_map, debit_credit_diff, precision):
"cost_center": round_off_cost_center,
"party_type": None,
"party": None,
"is_opening": "No",
"against_voucher_type": None,
"against_voucher": None
})
@@ -293,7 +293,8 @@ def delete_gl_entries(gl_entries=None, voucher_type=None, voucher_no=None,
select account, posting_date, party_type, party, cost_center, fiscal_year,voucher_type,
voucher_no, against_voucher_type, against_voucher, cost_center, company
from `tabGL Entry`
where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no), as_dict=True)
where voucher_type=%s and voucher_no=%s
for update""", (voucher_type, voucher_no), as_dict=True)
if gl_entries:
validate_accounting_period(gl_entries)

View File

@@ -165,7 +165,7 @@ def add_data_for_operating_activities(
if profit_data:
profit_data.update({
"indent": 1,
"parent_account": get_mapper_for(light_mappers, position=0)['section_header']
"parent_account": get_mapper_for(light_mappers, position=1)['section_header']
})
data.append(profit_data)
section_data.append(profit_data)
@@ -312,10 +312,10 @@ def add_data_for_other_activities(
def compute_data(filters, company_currency, profit_data, period_list, light_mappers, full_mapper):
data = []
operating_activities_mapper = get_mapper_for(light_mappers, position=0)
operating_activities_mapper = get_mapper_for(light_mappers, position=1)
other_mappers = [
get_mapper_for(light_mappers, position=1),
get_mapper_for(light_mappers, position=2)
get_mapper_for(light_mappers, position=2),
get_mapper_for(light_mappers, position=3)
]
if operating_activities_mapper:
@@ -396,7 +396,7 @@ def _get_account_type_based_data(filters, account_names, period_list, accumulate
gl_sum = frappe.db.sql_list("""
select sum(credit) - sum(debit)
from `tabGL Entry`
where company=%s and posting_date >= %s and posting_date <= %s
where company=%s and posting_date >= %s and posting_date <= %s
and voucher_type != 'Period Closing Voucher'
and account in ( SELECT name FROM tabAccount WHERE name IN (%s)
OR parent_account IN (%s))
@@ -405,7 +405,7 @@ def _get_account_type_based_data(filters, account_names, period_list, accumulate
gl_sum = frappe.db.sql_list("""
select sum(credit) - sum(debit)
from `tabGL Entry`
where company=%s and posting_date >= %s and posting_date <= %s
where company=%s and posting_date >= %s and posting_date <= %s
and voucher_type != 'Period Closing Voucher'
and account in ( SELECT name FROM tabAccount WHERE name IN (%s)
OR parent_account IN (%s))

View File

@@ -224,8 +224,7 @@ def get_company_currency(filters=None):
def calculate_values(accounts_by_name, gl_entries_by_account, companies, fiscal_year, filters):
for entries in gl_entries_by_account.values():
for entry in entries:
key = entry.account_number or entry.account_name
d = accounts_by_name.get(key)
d = accounts_by_name.get(entry.account_name)
if d:
for company in companies:
# check if posting date is within the period
@@ -240,7 +239,8 @@ def accumulate_values_into_parents(accounts, accounts_by_name, companies):
"""accumulate children's values in parent accounts"""
for d in reversed(accounts):
if d.parent_account:
account = d.parent_account.split('-')[0].strip()
account = d.parent_account_name
if not accounts_by_name.get(account):
continue
@@ -251,16 +251,34 @@ def accumulate_values_into_parents(accounts, accounts_by_name, companies):
accounts_by_name[account]["opening_balance"] = \
accounts_by_name[account].get("opening_balance", 0.0) + d.get("opening_balance", 0.0)
def get_account_heads(root_type, companies, filters):
accounts = get_accounts(root_type, filters)
if not accounts:
return None, None
accounts = update_parent_account_names(accounts)
accounts, accounts_by_name, parent_children_map = filter_accounts(accounts)
return accounts, accounts_by_name
def update_parent_account_names(accounts):
"""Update parent_account_name in accounts list.
parent_name is `name` of parent account which could have other prefix
of account_number and suffix of company abbr. This function adds key called
`parent_account_name` which does not have such prefix/suffix.
"""
name_to_account_map = { d.name : d.account_name for d in accounts }
for account in accounts:
if account.parent_account:
account["parent_account_name"] = name_to_account_map[account.parent_account]
return accounts
def get_companies(filters):
companies = {}
all_companies = get_subsidiary_companies(filters.get('company'))
@@ -367,9 +385,9 @@ def set_gl_entries_by_account(from_date, to_date, root_lft, root_rgt, filters, g
convert_to_presentation_currency(gl_entries, currency_info)
for entry in gl_entries:
key = entry.account_number or entry.account_name
validate_entries(key, entry, accounts_by_name, accounts)
gl_entries_by_account.setdefault(key, []).append(entry)
account_name = entry.account_name
validate_entries(account_name, entry, accounts_by_name, accounts)
gl_entries_by_account.setdefault(account_name, []).append(entry)
return gl_entries_by_account
@@ -438,8 +456,7 @@ def filter_accounts(accounts, depth=10):
parent_children_map = {}
accounts_by_name = {}
for d in accounts:
key = d.account_number or d.account_name
accounts_by_name[key] = d
accounts_by_name[d.account_name] = d
parent_children_map.setdefault(d.parent_account or None, []).append(d)
filtered_accounts = []

View File

@@ -3,6 +3,7 @@
"description": "Settings for Buying Module",
"doctype": "DocType",
"document_type": "Other",
"engine": "InnoDB",
"field_order": [
"supp_master_name",
"supplier_group",
@@ -92,7 +93,7 @@
"icon": "fa fa-cog",
"idx": 1,
"issingle": 1,
"modified": "2019-08-20 13:13:09.055189",
"modified": "2021-03-02 18:16:03.947813",
"modified_by": "Administrator",
"module": "Buying",
"name": "Buying Settings",
@@ -107,5 +108,8 @@
"share": 1,
"write": 1
}
]
],
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@@ -355,7 +355,7 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
material_request_type: "Purchase",
docstatus: 1,
status: ["!=", "Stopped"],
per_ordered: ["<", 99.99],
per_ordered: ["<", 100],
}
})
}, __("Get items from"));

View File

@@ -366,7 +366,6 @@ def make_purchase_receipt(source_name, target_doc=None):
"Purchase Order": {
"doctype": "Purchase Receipt",
"field_map": {
"per_billed": "per_billed",
"supplier_warehouse":"supplier_warehouse"
},
"validation": {

View File

@@ -271,7 +271,7 @@ erpnext.buying.RequestforQuotationController = erpnext.buying.BuyingController.e
material_request_type: "Purchase",
docstatus: 1,
status: ["!=", "Stopped"],
per_ordered: ["<", 99.99]
per_ordered: ["<", 100]
}
})
}, __("Get items from"));
@@ -316,7 +316,7 @@ erpnext.buying.RequestforQuotationController = erpnext.buying.BuyingController.e
material_request_type: "Purchase",
docstatus: 1,
status: ["!=", "Stopped"],
per_ordered: ["<", 99.99]
per_ordered: ["<", 100]
}
});
$(btn).done_working();

View File

@@ -279,19 +279,21 @@ def add_items(sq_doc, supplier, items):
create_rfq_items(sq_doc, supplier, data)
def create_rfq_items(sq_doc, supplier, data):
sq_doc.append('items', {
"item_code": data.item_code,
"item_name": data.item_name,
"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 '',
args = {}
for field in ['item_code', 'item_name', 'description', 'qty', 'rate', 'conversion_factor',
'warehouse', 'material_request', 'material_request_item', 'stock_qty']:
args[field] = data.get(field)
args.update({
"request_for_quotation_item": data.name,
"request_for_quotation": data.parent
"request_for_quotation": data.parent,
"supplier_part_no": frappe.db.get_value("Item Supplier",
{'parent': data.item_code, 'supplier': supplier}, "supplier_part_no")
})
sq_doc.append('items', args)
@frappe.whitelist()
def get_pdf(doctype, name, supplier_idx):
doc = get_rfq_doc(doctype, name, supplier_idx)

View File

@@ -46,7 +46,7 @@ erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.ext
material_request_type: "Purchase",
docstatus: 1,
status: ["!=", "Stopped"],
per_ordered: ["<", 99.99]
per_ordered: ["<", 100]
}
})
}, __("Get items from"));

View File

@@ -0,0 +1,34 @@
## Version 12.20.0 Release Notes
### Fixes & Enhancements
- E-invoicing - Validations & tax calculation fixes ([#25315](https://github.com/frappe/erpnext/pull/25315))
- Allow zero valuation in stock reconciliation ([#24986](https://github.com/frappe/erpnext/pull/24986))
- Remove shipping address GSTIN validation for e-invoice ([#25133](https://github.com/frappe/erpnext/pull/25133))
- Allow Item image alt ([#24935](https://github.com/frappe/erpnext/pull/24935))
- Added parent task expected end date validation ([#24889](https://github.com/frappe/erpnext/pull/24889))
- Incorrect Nil Exempt and Non GST amount in GSTR3B report ([#24919](https://github.com/frappe/erpnext/pull/24919))
- Item attributes not editable until refresh ([#24887](https://github.com/frappe/erpnext/pull/24887))
- Create property setters for shorter naming series ([#25134](https://github.com/frappe/erpnext/pull/25134))
- Serial no refresh issue ([#25130](https://github.com/frappe/erpnext/pull/25130))
- Sales Order not saving due type mismatch in promo scheme (#24748) ([#25056](https://github.com/frappe/erpnext/pull/25056))
- TDS check getting checked after reload ([#24974](https://github.com/frappe/erpnext/pull/24974))
- Round total quantity in job card ([#25246](https://github.com/frappe/erpnext/pull/25246))
- santize_for_json is not defined ([#25157](https://github.com/frappe/erpnext/pull/25157))
- Apply single transaction threshold on net_total instead of supplier credit amount ([#25208](https://github.com/frappe/erpnext/pull/25208))
- Zero amount completed delivery notes being shown in Sales Invoice get items ([#25318](https://github.com/frappe/erpnext/pull/25318))
- Error message compensatory leave request ([#25216](https://github.com/frappe/erpnext/pull/25216))
- RCM tax calculation ([#25226](https://github.com/frappe/erpnext/pull/25226))
- Don't delete mode of payment account details while deleting comp… ([#25218](https://github.com/frappe/erpnext/pull/25218))
- Opportunity-quotation mapping order status ([#25002](https://github.com/frappe/erpnext/pull/25002))
- Object referencing same memory address issue ([#25165](https://github.com/frappe/erpnext/pull/25165))
- Validation msg for TransDocNo e-invoicing ([#25120](https://github.com/frappe/erpnext/pull/25120))
- Do not fetch stopped MR in production plan ([#25110](https://github.com/frappe/erpnext/pull/25110))
- Incorrect status creating PR from PO after creating PI ([#25203](https://github.com/frappe/erpnext/pull/25203))
- Remove gst name validation for purchase Invoice ([#25236](https://github.com/frappe/erpnext/pull/25236))
- Assignment Rule Unassign Condition doesn't work ([#24890](https://github.com/frappe/erpnext/pull/24890))
- Place of supply for e-invoicing ([#25149](https://github.com/frappe/erpnext/pull/25149))
- Serial no trim issue ([#24950](https://github.com/frappe/erpnext/pull/24950))
- Commit individual SLE rename for large datasets (v12) ([#25085](https://github.com/frappe/erpnext/pull/25085))
- Incorrect batch picked in subcontracted purchase receipt ([#25169](https://github.com/frappe/erpnext/pull/25169))

View File

@@ -0,0 +1,21 @@
## Version 12.21.0 Release Notes
### Fixes & Enhancements
- Incorrect qty calculated for sub-contracted raw materials in purchase receipt ([#25443](https://github.com/frappe/erpnext/pull/25443))
- Update cost center in the item table fetched from POS Profile in v12 ([#25612](https://github.com/frappe/erpnext/pull/25612))
- Total stock summary report not working ([#25552](https://github.com/frappe/erpnext/pull/25552))
- Timeout error while loading warehouse tree ([#25693](https://github.com/frappe/erpnext/pull/25693))
- RCM rounding precision ([#25410](https://github.com/frappe/erpnext/pull/25410))
- Change subcontracted item display ([#25426](https://github.com/frappe/erpnext/pull/25426))
- Remove invalid changes added due to merge conflict ([#25437](https://github.com/frappe/erpnext/pull/25437))
- Add document type field for e-invoicing (Italy) ([#25420](https://github.com/frappe/erpnext/pull/25420))
- Issue in project custom status ([#25453](https://github.com/frappe/erpnext/pull/25453))
- Employee Separation ([#25504](https://github.com/frappe/erpnext/pull/25504))
- State code for Other Territory ([#25422](https://github.com/frappe/erpnext/pull/25422))
- Remove invalid changes added due to merge conflict ([#25405](https://github.com/frappe/erpnext/pull/25405))
- Check for None in item.schedule_date before setting ([#25589](https://github.com/frappe/erpnext/pull/25589))
- Can't multiply sequence by non-int of type 'float' ([#25385](https://github.com/frappe/erpnext/pull/25385))
- Filter using purpose, make requested changes ([#25388](https://github.com/frappe/erpnext/pull/25388))
- Purchase from registered composition dealer ([#25419](https://github.com/frappe/erpnext/pull/25419))

View File

@@ -0,0 +1,16 @@
## Version 12.22.0 Release Notes
### Fixes & Enhancements
- Cost-center wise period closing entry ([#25930](https://github.com/frappe/erpnext/pull/25930))
- Wrong round off gl entry posted in case of purchase invoice ([#25952](https://github.com/frappe/erpnext/pull/25952))
- Sync shopify customer addresses (#25481) ([#25937](https://github.com/frappe/erpnext/pull/25937))
- Plaid NoneType error ([#25662](https://github.com/frappe/erpnext/pull/25662))
- Cashlfow mapper not showing data ([#25739](https://github.com/frappe/erpnext/pull/25739))
- Update shopify api version (#25600) ([#25939](https://github.com/frappe/erpnext/pull/25939))
- Invalid 'depends_on' expression in opportunity ([#25954](https://github.com/frappe/erpnext/pull/25954))
- Ignore rounding diff while importing JV using data import ([#25715](https://github.com/frappe/erpnext/pull/25715))
- update cost center from POS ([#25972](https://github.com/frappe/erpnext/pull/25972))
- update employee field on renaming employee ([#25958](https://github.com/frappe/erpnext/pull/25958))
- student invalid password reset link ([#25827](https://github.com/frappe/erpnext/pull/25827))
- Backward compatibility for GSTR-1 report ([#25913](https://github.com/frappe/erpnext/pull/25913))

View File

@@ -0,0 +1,20 @@
## Version 12.23.0 Release Notes
### Fixes & Enhancements
- Added Permissions for employee to book an appointment ([#26246](https://github.com/frappe/erpnext/pull/26246))
- New check field in subscriptions for (not) submitting invoices (BP #25394) ([#25560](https://github.com/frappe/erpnext/pull/25560))
- fix(e-invoicing): allow export invoice even if no taxes applied (#26363) ([#26406](https://github.com/frappe/erpnext/pull/26406))
- Omit item discount amount for e-invoicing (#26353) ([#26408](https://github.com/frappe/erpnext/pull/26408))
- fix(plaid): cannot reset plaid link for a bank account ([#26282](https://github.com/frappe/erpnext/pull/26282))
- Job applicant link issue ([#25935](https://github.com/frappe/erpnext/pull/25935))
- LMS progress issue ([#26254](https://github.com/frappe/erpnext/pull/26254))
- Half day to be accounted in its leave type ([#26267](https://github.com/frappe/erpnext/pull/26267))
- Material request status issue ([#26089](https://github.com/frappe/erpnext/pull/26089))
- fix(e-invoicing): service item check ([#26141](https://github.com/frappe/erpnext/pull/26141))
- Invoices can alter profit and loss of a closed year ([#26161](https://github.com/frappe/erpnext/pull/26161))
- Material request and supplier quotation not linked if supplier quotation created from supplier portal ([#26117](https://github.com/frappe/erpnext/pull/26117))
- Update positions in default cashflow mappers ([#26091](https://github.com/frappe/erpnext/pull/26091))
- Staffing plan vacancies data type issue ([#25940](https://github.com/frappe/erpnext/pull/25940))
- Added company filter while fetching loans ([#26296](https://github.com/frappe/erpnext/pull/26296))
- Serial no issue in subcontract purchase receipt ([#26423](https://github.com/frappe/erpnext/pull/26423))
- Fixed rounding off ordered percent to 100 in condition ([#26153](https://github.com/frappe/erpnext/pull/26153))

View File

@@ -0,0 +1,13 @@
## Version 12.24.0 Release Notes
### Fixes & Enhancements
- Sales order qty update fails in "Update Items" button ([#26992](https://github.com/frappe/erpnext/pull/26992))
- Speed up validate_account_for_perpetual_inventory ([#26730](https://github.com/frappe/erpnext/pull/26730))
- Deadlock while doing payment reconciliation ([#26674](https://github.com/frappe/erpnext/pull/26674))
- Remove incorrect condition in GLE comparison ([#26713](https://github.com/frappe/erpnext/pull/26713))
- Cannot cancel invoice if IRN cancelled on portal ([#26880](https://github.com/frappe/erpnext/pull/26880))
- Item name is missing into job card ([#26956](https://github.com/frappe/erpnext/pull/26956))
- Removed company filter for Loan Type ([#26463](https://github.com/frappe/erpnext/pull/26463))
- Exchange rate revaluation posting date and precision fixes ([#26629](https://github.com/frappe/erpnext/pull/26629))
- Fixed clearing issue of payment references on setting cost center ([#26548](https://github.com/frappe/erpnext/pull/26548))
- Increase number of supported currency exchanges ([#25722](https://github.com/frappe/erpnext/pull/25722))

View File

@@ -1312,7 +1312,7 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
qty_unchanged = prev_qty == new_qty
uom_unchanged = prev_uom == new_uom
conversion_factor_unchanged = prev_con_fac == new_con_fac
date_unchanged = prev_date == new_date if prev_date and new_date else False # in case of delivery note etc
date_unchanged = prev_date == getdate(new_date) if prev_date and new_date else False # in case of delivery note etc
if rate_unchanged and qty_unchanged and conversion_factor_unchanged and uom_unchanged and date_unchanged:
continue

View File

@@ -6,6 +6,7 @@ import frappe
from frappe import _, msgprint
from frappe.utils import flt,cint, cstr, getdate
from six import iteritems
from collections import OrderedDict
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
@@ -294,6 +295,9 @@ class BuyingController(StockController):
for raw_material in transferred_raw_materials + non_stock_items:
rm_item_key = (raw_material.rm_item_code, item.item_code, item.purchase_order)
raw_material_data = backflushed_raw_materials_map.get(rm_item_key, {})
if not raw_material_data and raw_material.get('batch_nos'):
backflushed_raw_materials_map.setdefault(rm_item_key, {'consumed_batch': {}})
raw_material_data = backflushed_raw_materials_map.get(rm_item_key, {})
consumed_qty = raw_material_data.get('qty', 0)
consumed_serial_nos = raw_material_data.get('serial_no', '')
@@ -325,14 +329,17 @@ class BuyingController(StockController):
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, item.purchase_order)
for batch_data in batches_qty:
qty = batch_data['qty']
raw_material.batch_no = batch_data['batch']
self.append_raw_material_to_be_backflushed(item, raw_material, qty)
if qty > 0:
self.append_raw_material_to_be_backflushed(item, raw_material, qty)
else:
self.append_raw_material_to_be_backflushed(item, raw_material, qty)
def append_raw_material_to_be_backflushed(self, fg_item_doc, raw_material_data, qty):
qty = flt(qty, fg_item_doc.precision('qty'))
rm = self.append('supplied_items', {})
rm.update(raw_material_data)
@@ -790,9 +797,10 @@ class BuyingController(StockController):
if not self.get("items"):
return
earliest_schedule_date = min([d.schedule_date for d in self.get("items")])
if earliest_schedule_date:
self.schedule_date = earliest_schedule_date
if any(d.schedule_date for d in self.get("items")):
# Select earliest schedule_date.
self.schedule_date = min(d.schedule_date for d in self.get("items")
if d.schedule_date is not None)
if self.schedule_date:
for d in self.get('items'):
@@ -973,8 +981,16 @@ def get_non_stock_items(purchase_order, fg_item_code):
def set_serial_nos(raw_material, consumed_serial_nos, qty):
serial_nos = set(get_serial_nos(raw_material.serial_nos)) - \
set(get_serial_nos(consumed_serial_nos))
consumed_serial_nos_list = []
if isinstance(consumed_serial_nos, list):
for row in consumed_serial_nos:
consumed_serial_nos_list.extend(get_serial_nos(row))
else:
consumed_serial_nos_list = get_serial_nos(row)
serial_nos = set(get_serial_nos(raw_material.serial_nos)) - set(consumed_serial_nos_list)
if serial_nos and qty <= len(serial_nos):
raw_material.serial_no = '\n'.join(list(serial_nos)[0:frappe.utils.cint(qty)])
@@ -1009,7 +1025,7 @@ def get_transferred_batch_qty_map(purchase_order, fg_item):
for batch_data in transferred_batches:
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.setdefault(key, OrderedDict())
transferred_batch_qty_map[key][batch_data.batch_no] = batch_data.qty
return transferred_batch_qty_map
@@ -1062,8 +1078,14 @@ def get_batches_with_qty(item_code, fg_item, required_qty, transferred_batch_qty
if available_qty >= required_qty:
available_batches.append({'batch': batch, 'qty': required_qty})
break
else:
elif available_qty != 0:
available_batches.append({'batch': batch, 'qty': available_qty})
required_qty -= available_qty
for row in available_batches:
if backflushed_batches.get(row.get('batch'), 0) > 0:
backflushed_batches[row.get('batch')] += row.get('qty')
else:
backflushed_batches.setdefault(row.get('batch'), row.get('qty'))
return available_batches

View File

@@ -320,7 +320,7 @@ def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len,
and status not in ("Stopped", "Closed") %(fcond)s
and (
(`tabDelivery Note`.is_return = 0 and `tabDelivery Note`.per_billed < 100)
or `tabDelivery Note`.grand_total = 0
or (`tabDelivery Note`.grand_total = 0 and `tabDelivery Note`.per_billed < 100)
or (
`tabDelivery Note`.is_return = 1
and return_against in (select name from `tabDelivery Note` where per_billed < 100)

View File

@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import flt, comma_or, nowdate, getdate
from frappe.utils import flt, comma_or, nowdate, getdate, now
from frappe import _
from frappe.model.document import Document
@@ -307,10 +307,14 @@ class StatusUpdater(Document):
target.notify_update()
def _update_modified(self, args, update_modified):
args['update_modified'] = ''
if update_modified:
args['update_modified'] = ', modified = now(), modified_by = {0}'\
.format(frappe.db.escape(frappe.session.user))
if not update_modified:
args['update_modified'] = ''
return
args['update_modified'] = ', modified = {0}, modified_by = {1}'.format(
frappe.db.escape(now()),
frappe.db.escape(frappe.session.user)
)
def update_billing_status_for_zero_amount_refdoc(self, ref_dt):
ref_fieldname = frappe.scrub(ref_dt)

View File

@@ -418,7 +418,7 @@ def compare_existing_and_expected_gle(existing_gle, expected_gle):
for e in existing_gle:
if entry.account == e.account:
account_existed = True
if entry.account == e.account and entry.against_account == e.against_account \
if entry.account == e.account \
and (not entry.cost_center or not e.cost_center or entry.cost_center == e.cost_center) \
and (entry.debit != e.debit or entry.credit != e.credit):
matched = False

View File

@@ -93,7 +93,7 @@
"fieldtype": "Column Break"
}
],
"modified": "2019-10-14 15:23:54.630731",
"modified": "2021-06-28 16:27:53.235714",
"modified_by": "Administrator",
"module": "CRM",
"name": "Appointment",
@@ -144,6 +144,18 @@
"role": "Sales User",
"share": 1,
"write": 1
},
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Employee",
"share": 1,
"write": 1
}
],
"quick_entry": 1,

View File

@@ -277,7 +277,6 @@
"read_only": 1
},
{
"depends_on": "eval:",
"fieldname": "territory",
"fieldtype": "Link",
"label": "Territory",
@@ -413,7 +412,7 @@
],
"icon": "fa fa-info-sign",
"idx": 195,
"modified": "2020-08-12 23:34:39.665513",
"modified": "2021-06-04 10:11:22.831139",
"modified_by": "Administrator",
"module": "CRM",
"name": "Opportunity",

View File

@@ -244,7 +244,6 @@ def make_quotation(source_name, target_doc=None):
"doctype": "Quotation",
"field_map": {
"opportunity_from": "quotation_to",
"opportunity_type": "order_type",
"name": "enq_no",
}
},

View File

@@ -58,7 +58,6 @@ class Student(Document):
student_user.flags.ignore_permissions = True
student_user.add_roles("Student")
student_user.save()
update_password_link = student_user.reset_password()
def update_applicant_status(self):
"""Updates Student Applicant status to Admitted"""

View File

@@ -345,11 +345,11 @@ def get_or_create_course_enrollment(course, program):
student = get_current_student()
course_enrollment = get_enrollment("course", course, student.name)
if not course_enrollment:
program_enrollment = get_enrollment('program', program, student.name)
program_enrollment = get_enrollment('program', program.name, student.name)
if not program_enrollment:
frappe.throw(_("You are not enrolled in program {0}".format(program)))
return
return student.enroll_in_course(course_name=course, program_enrollment=get_enrollment('program', program, student.name))
return student.enroll_in_course(course_name=course, program_enrollment=get_enrollment('program', program.name, student.name))
else:
return frappe.get_doc('Course Enrollment', course_enrollment)

View File

@@ -117,7 +117,7 @@ def call_mws_method(mws_method, *args, **kwargs):
return response
except Exception as e:
delay = math.pow(4, x) * 125
frappe.log_error(message=e, title=str(mws_method))
frappe.log_error(message=e, title="Method {} failed".format(mws_method.__name__))
time.sleep(delay)
continue

View File

@@ -99,5 +99,7 @@ class PlaidConnector():
response = self.client.Transactions.get(self.access_token, start_date=start_date, end_date=end_date, offset=len(transactions))
transactions.extend(response["transactions"])
return transactions
except ItemError as e:
raise e
except Exception:
frappe.log_error(frappe.get_traceback(), _("Plaid transactions sync error"))

View File

@@ -15,6 +15,10 @@ frappe.ui.form.on('Plaid Settings', {
frm.add_custom_button(__('Link a new bank account'), () => {
new erpnext.integrations.plaidLink(frm);
});
frm.add_custom_button(__('Reset Plaid Link'), () => {
new erpnext.integrations.plaidLink(frm);
});
}
}
});

View File

@@ -1,5 +1,4 @@
{
"actions": [],
"creation": "2018-10-25 10:02:48.656165",
"doctype": "DocType",
"editable_grid": 1,
@@ -69,8 +68,7 @@
}
],
"issingle": 1,
"links": [],
"modified": "2020-10-29 20:24:56.916104",
"modified": "2021-03-02 18:05:50.794105",
"modified_by": "Administrator",
"module": "ERPNext Integrations",
"name": "Plaid Settings",
@@ -88,5 +86,6 @@
}
],
"sort_field": "modified",
"sort_order": "DESC"
"sort_order": "DESC",
"track_changes": 1
}

View File

@@ -12,6 +12,7 @@ from frappe.desk.doctype.tag.tag import add_tag
from frappe.model.document import Document
from frappe.utils import add_months, formatdate, getdate, today
from plaid.errors import ItemError
class PlaidSettings(Document):
@staticmethod
@@ -50,7 +51,7 @@ def add_institution(token, response):
})
bank.insert()
except Exception:
frappe.throw(frappe.get_traceback())
frappe.log_error(frappe.get_traceback(), title=_('Plaid Link Error'))
else:
bank = frappe.get_doc("Bank", response["institution"]["name"])
bank.plaid_access_token = access_token
@@ -82,7 +83,12 @@ def add_bank_accounts(response, bank, company):
if not acc_subtype:
add_account_subtype(account["subtype"])
if not frappe.db.exists("Bank Account", dict(integration_id=account["id"])):
existing_bank_account = frappe.db.exists("Bank Account", {
'account_name': account["name"],
'bank': bank["bank_name"]
})
if not existing_bank_account:
try:
new_account = frappe.get_doc({
"doctype": "Bank Account",
@@ -102,10 +108,27 @@ def add_bank_accounts(response, bank, company):
except frappe.UniqueValidationError:
frappe.msgprint(_("Bank account {0} already exists and could not be created again").format(account["name"]))
except Exception:
frappe.throw(frappe.get_traceback())
frappe.log_error(frappe.get_traceback(), title=_("Plaid Link Error"))
frappe.throw(_("There was an error creating Bank Account while linking with Plaid."),
title=_("Plaid Link Failed"))
else:
result.append(frappe.db.get_value("Bank Account", dict(integration_id=account["id"]), "name"))
try:
existing_account = frappe.get_doc('Bank Account', existing_bank_account)
existing_account.update({
"bank": bank["bank_name"],
"account_name": account["name"],
"account_type": account.get("type", ""),
"account_subtype": account.get("subtype", ""),
"mask": account.get("mask", ""),
"integration_id": account["id"]
})
existing_account.save()
result.append(existing_bank_account)
except Exception:
frappe.log_error(frappe.get_traceback(), title=_("Plaid Link Error"))
frappe.throw(_("There was an error updating Bank Account {} while linking with Plaid.").format(
existing_bank_account), title=_("Plaid Link Failed"))
return result
@@ -146,8 +169,9 @@ def sync_transactions(bank, bank_account):
transactions = get_transactions(bank=bank, bank_account=bank_account, start_date=start_date, end_date=end_date)
result = []
for transaction in reversed(transactions):
result += new_bank_transaction(transaction)
if transactions:
for transaction in reversed(transactions):
result += new_bank_transaction(transaction)
if result:
last_transaction_date = frappe.db.get_value('Bank Transaction', result.pop(), 'date')
@@ -173,9 +197,16 @@ def get_transactions(bank, bank_account=None, start_date=None, end_date=None):
account_id = None
plaid = PlaidConnector(access_token)
transactions = plaid.get_transactions(start_date=start_date, end_date=end_date, account_id=account_id)
return transactions
try:
transactions = plaid.get_transactions(start_date=start_date, end_date=end_date, account_id=account_id)
except ItemError as e:
if e.code == "ITEM_LOGIN_REQUIRED":
msg = _("There was an error syncing transactions.") + " "
msg += _("Please refresh or reset the Plaid linking of the Bank {}.").format(bank) + " "
frappe.log_error(msg, title=_("Plaid Link Refresh Required"))
return transactions or []
def new_bank_transaction(transaction):

View File

@@ -2,6 +2,7 @@
"creation": "2015-05-18 05:21:07.270859",
"doctype": "DocType",
"document_type": "System",
"engine": "InnoDB",
"field_order": [
"status_html",
"enable_shopify",
@@ -258,8 +259,8 @@
}
],
"issingle": 1,
"modified": "2020-05-28 12:32:11.384757",
"modified_by": "umair@erpnext.com",
"modified": "2021-03-02 18:06:00.868688",
"modified_by": "Administrator",
"module": "ERPNext Integrations",
"name": "Shopify Settings",
"owner": "Administrator",
@@ -276,5 +277,6 @@
}
],
"sort_field": "modified",
"sort_order": "DESC"
}
"sort_order": "DESC",
"track_changes": 1
}

View File

@@ -30,7 +30,7 @@ class ShopifySettings(Document):
webhooks = ["orders/create", "orders/paid", "orders/fulfilled"]
# url = get_shopify_url('admin/webhooks.json', self)
created_webhooks = [d.method for d in self.webhooks]
url = get_shopify_url('admin/api/2020-04/webhooks.json', self)
url = get_shopify_url('admin/api/2021-04/webhooks.json', self)
for method in webhooks:
session = get_request_session()
try:
@@ -56,7 +56,7 @@ class ShopifySettings(Document):
deleted_webhooks = []
for d in self.webhooks:
url = get_shopify_url('admin/api/2020-04/webhooks/{0}.json'.format(d.webhook_id), self)
url = get_shopify_url('admin/api/2021-04/webhooks/{0}.json'.format(d.webhook_id), self)
try:
res = session.delete(url, headers=get_header(self))
res.raise_for_status()

View File

@@ -32,10 +32,12 @@ def create_customer(shopify_customer, shopify_settings):
raise e
def create_customer_address(customer, shopify_customer):
if not shopify_customer.get("addresses"):
return
addresses = shopify_customer.get("addresses", [])
for i, address in enumerate(shopify_customer.get("addresses")):
if not addresses and "default_address" in shopify_customer:
addresses.append(shopify_customer["default_address"])
for i, address in enumerate(addresses):
address_title, address_type = get_address_title_and_type(customer.customer_name, i)
try :
frappe.get_doc({

View File

@@ -8,7 +8,7 @@ from erpnext.erpnext_integrations.doctype.shopify_settings.shopify_settings impo
shopify_variants_attr_list = ["option1", "option2", "option3"]
def sync_item_from_shopify(shopify_settings, item):
url = get_shopify_url("admin/api/2020-04/products/{0}.json".format(item.get("product_id")), shopify_settings)
url = get_shopify_url("admin/api/2021-04/products/{0}.json".format(item.get("product_id")), shopify_settings)
session = get_request_session()
try:

View File

@@ -17,8 +17,7 @@ class ShopifySettings(unittest.TestCase):
frappe.set_user("Administrator")
# use the fixture data
import_doc(path=frappe.get_app_path("erpnext", "erpnext_integrations/doctype/shopify_settings/test_data/custom_field.json"),
ignore_links=True, overwrite=True)
import_doc(path=frappe.get_app_path("erpnext", "erpnext_integrations/doctype/shopify_settings/test_data/custom_field.json"))
frappe.reload_doctype("Customer")
frappe.reload_doctype("Sales Order")

View File

@@ -246,7 +246,7 @@ doc_events = {
"on_submit": ["erpnext.regional.create_transaction_log", "erpnext.regional.italy.utils.sales_invoice_on_submit"],
"on_cancel": "erpnext.regional.italy.utils.sales_invoice_on_cancel",
"on_trash": "erpnext.regional.check_deletion_permission",
"validate": "erpnext.regional.india.utils.set_transporter_address"
"validate": ["erpnext.regional.india.utils.set_transporter_address", "erpnext.regional.india.utils.update_taxable_values", "erpnext.regional.india.utils.validate_document_name"]
},
"Purchase Invoice": {
"validate": "erpnext.regional.india.utils.update_grand_total_for_rcm"

View File

@@ -78,7 +78,7 @@
"search_index": 1
},
{
"depends_on": "eval:doc.status==\"On Leave\"",
"depends_on": "eval:doc.status==\"On Leave\" || doc.status==\"Half Day\"",
"fieldname": "leave_type",
"fieldtype": "Link",
"in_standard_filter": 1,
@@ -174,7 +174,7 @@
"icon": "fa fa-ok",
"idx": 1,
"is_submittable": 1,
"modified": "2020-02-19 14:25:32.945842",
"modified": "2021-06-30 14:42:39.162146",
"modified_by": "Administrator",
"module": "HR",
"name": "Attendance",

View File

@@ -5,7 +5,7 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import date_diff, add_days, getdate, cint
from frappe.utils import date_diff, add_days, getdate, cint, formatdate as format_date
from frappe.model.document import Document
from erpnext.hr.utils import validate_dates, validate_overlap, get_leave_period, \
get_holidays_for_employee, create_additional_leave_ledger_entry
@@ -40,7 +40,12 @@ class CompensatoryLeaveRequest(Document):
def validate_holidays(self):
holidays = get_holidays_for_employee(self.employee, self.work_from_date, self.work_end_date)
if len(holidays) < date_diff(self.work_end_date, self.work_from_date) + 1:
frappe.throw(_("Compensatory leave request days not in valid holidays"))
if date_diff(self.work_end_date, self.work_from_date):
msg = _("The days between {0} to {1} are not valid holidays.").format(frappe.bold(format_date(self.work_from_date)), frappe.bold(format_date(self.work_end_date)))
else:
msg = _("{0} is not a holiday.").format(frappe.bold(format_date(self.work_from_date)))
frappe.throw(msg)
def on_submit(self):
company = frappe.db.get_value("Employee", self.employee, "company")
@@ -63,7 +68,7 @@ class CompensatoryLeaveRequest(Document):
leave_allocation = self.create_leave_allocation(leave_period, date_difference)
self.leave_allocation=leave_allocation.name
else:
frappe.throw(_("There is no leave period in between {0} and {1}").format(self.work_from_date, self.work_end_date))
frappe.throw(_("There is no leave period in between {0} and {1}").format(format_date(self.work_from_date), format_date(self.work_end_date)))
def on_cancel(self):
if self.leave_allocation:

View File

@@ -57,6 +57,9 @@ class Employee(NestedSet):
remove_user_permission(
"Employee", self.name, existing_user_id)
def after_rename(self, old, new, merge):
self.db_set("employee", new)
def set_employee_name(self):
self.employee_name = ' '.join(filter(lambda x: x, [self.first_name, self.middle_name, self.last_name]))

View File

@@ -1,626 +1,177 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "HR-EMP-SEP-.YYYY.-.#####",
"beta": 0,
"creation": "2018-05-10 02:29:16.740490",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"actions": [],
"autoname": "HR-EMP-SEP-.YYYY.-.#####",
"creation": "2018-05-10 02:29:16.740490",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"employee",
"employee_name",
"department",
"designation",
"employee_grade",
"column_break_7",
"company",
"boarding_status",
"resignation_letter_date",
"project",
"table_for_activity",
"employee_separation_template",
"activities",
"notify_users_by_email",
"section_break_14",
"exit_interview",
"amended_from"
],
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "employee",
"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": "Employee",
"length": 0,
"no_copy": 0,
"options": "Employee",
"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
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_from": "employee.employee_name",
"fieldname": "employee_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Employee Name",
"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
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_from": "employee.resignation_letter_date",
"fieldname": "resignation_letter_date",
"fieldtype": "Date",
"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": "Resignation Letter Date",
"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
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "boarding_status",
"fieldtype": "Select",
"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": "Status",
"length": 0,
"no_copy": 0,
"options": "\nPending\nIn Process\nCompleted",
"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": "employee",
"fieldtype": "Link",
"label": "Employee",
"options": "Employee",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_bulk_edit": 0,
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_in_quick_entry": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "notify_users_by_email",
"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": "Notify users by email",
"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
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_7",
"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
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "employee_separation_template",
"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": "Employee Separation Template",
"length": 0,
"no_copy": 0,
"options": "Employee Separation Template",
"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
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_from": "employee.company",
"fieldname": "company",
"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": "Company",
"length": 0,
"no_copy": 0,
"options": "Company",
"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": "employee.employee_name",
"fieldname": "employee_name",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Employee Name",
"read_only": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "project",
"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": "Project",
"length": 0,
"no_copy": 0,
"options": "Project",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fetch_from": "employee.resignation_letter_date",
"fieldname": "resignation_letter_date",
"fieldtype": "Date",
"in_list_view": 1,
"label": "Resignation Letter Date",
"read_only": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_from": "employee.department",
"fieldname": "department",
"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": "Department",
"length": 0,
"no_copy": 0,
"options": "Department",
"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
},
"allow_on_submit": 1,
"fieldname": "boarding_status",
"fieldtype": "Select",
"label": "Status",
"options": "\nPending\nIn Process\nCompleted",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_from": "employee.designation",
"fieldname": "designation",
"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": "Designation",
"length": 0,
"no_copy": 0,
"options": "Designation",
"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
},
"allow_on_submit": 1,
"default": "0",
"fieldname": "notify_users_by_email",
"fieldtype": "Check",
"label": "Notify users by email"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_from": "employee.grade",
"fieldname": "employee_grade",
"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": "Employee Grade",
"length": 0,
"no_copy": 0,
"options": "Employee Grade",
"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_7",
"fieldtype": "Column Break"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "table_for_activity",
"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": "",
"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": "employee_separation_template",
"fieldtype": "Link",
"label": "Employee Separation Template",
"options": "Employee Separation Template"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "activities",
"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": "Activities",
"length": 0,
"no_copy": 0,
"options": "Employee Boarding Activity",
"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": "employee.company",
"fieldname": "company",
"fieldtype": "Link",
"label": "Company",
"options": "Company",
"reqd": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_14",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
"fieldname": "project",
"fieldtype": "Link",
"label": "Project",
"options": "Project",
"read_only": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "exit_interview",
"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": "Exit Interview Summary",
"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
},
"fetch_from": "employee.department",
"fieldname": "department",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Department",
"options": "Department",
"read_only": 1
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "amended_from",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Amended From",
"length": 0,
"no_copy": 1,
"options": "Employee Separation",
"permlevel": 0,
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
"fetch_from": "employee.designation",
"fieldname": "designation",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Designation",
"options": "Designation",
"read_only": 1
},
{
"fetch_from": "employee.grade",
"fieldname": "employee_grade",
"fieldtype": "Link",
"label": "Employee Grade",
"options": "Employee Grade",
"read_only": 1
},
{
"fieldname": "table_for_activity",
"fieldtype": "Section Break",
"label": "Separation Activities"
},
{
"allow_on_submit": 1,
"fieldname": "activities",
"fieldtype": "Table",
"label": "Activities",
"options": "Employee Boarding Activity"
},
{
"fieldname": "section_break_14",
"fieldtype": "Section Break"
},
{
"fieldname": "exit_interview",
"fieldtype": "Text Editor",
"label": "Exit Interview Summary"
},
{
"fieldname": "amended_from",
"fieldtype": "Link",
"label": "Amended From",
"no_copy": 1,
"options": "Employee Separation",
"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": 1,
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2019-08-03 16:15:39.025898",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee Separation",
"name_case": "",
"owner": "Administrator",
],
"is_submittable": 1,
"links": [],
"modified": "2021-04-28 15:58:36.020196",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee Separation",
"owner": "Administrator",
"permissions": [
{
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 1,
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"submit": 1,
"write": 1
}
],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "employee_name",
"track_changes": 1,
"track_seen": 0,
"track_views": 0
],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "employee_name",
"track_changes": 1
}

View File

@@ -18,7 +18,7 @@ class TestEmployeeSeparation(unittest.TestCase):
'activity_name': 'Deactivate Employee',
'role': 'HR User'
})
separation.status = 'Pending'
separation.boarding_status = 'Pending'
separation.insert()
separation.submit()
self.assertEqual(separation.docstatus, 1)

View File

@@ -175,7 +175,7 @@
"idx": 1,
"issingle": 1,
"links": [],
"modified": "2019-12-31 14:28:32.004121",
"modified": "2021-02-25 13:06:37.978785",
"modified_by": "Administrator",
"module": "HR",
"name": "HR Settings",
@@ -192,5 +192,6 @@
}
],
"sort_field": "modified",
"sort_order": "ASC"
"sort_order": "ASC",
"track_changes": 1
}

View File

@@ -2,7 +2,7 @@
// MIT License. See license.txt
frappe.listview_settings['Job Applicant'] = {
add_fields: ["company", "designation", "job_applicant", "status"],
add_fields: ["status"],
get_indicator: function (doc) {
if (doc.status == "Accepted") {
return [__(doc.status), "green", "status,=," + doc.status];

View File

@@ -5,8 +5,8 @@
frappe.ui.form.on('Loan Application', {
refresh: function(frm) {
frm.trigger("toggle_fields")
frm.trigger("add_toolbar_buttons")
frm.trigger("toggle_fields");
frm.trigger("add_toolbar_buttons");
},
repayment_method: function(frm) {
frm.doc.repayment_amount = frm.doc.repayment_periods = ""

View File

@@ -5,10 +5,17 @@ frappe.ui.form.on('Salary Component', {
setup: function(frm) {
frm.set_query("default_account", "accounts", function(doc, cdt, cdn) {
var d = locals[cdt][cdn];
var root_type = "Liability";
if (frm.doc.type == "Deduction") {
root_type = "Expense";
}
return {
filters: {
"is_group": 0,
"company": d.company
"company": d.company,
"root_type": root_type
}
};
});

View File

@@ -869,8 +869,8 @@ class SalarySlip(TransactionBase):
`tabRepayment Schedule` as rps, `tabLoan` as l
where
l.name = rps.parent and rps.payment_date between %s and %s and
l.repay_from_salary = 1 and l.docstatus = 1 and l.applicant = %s""",
(self.start_date, self.end_date, self.employee), as_dict=True) or []
l.repay_from_salary = 1 and l.docstatus = 1 and l.applicant = %s and l.company = %s""",
(self.start_date, self.end_date, self.employee, self.company), as_dict=True) or []
def update_salary_slip_in_additional_salary(self):
salary_slip = self.name if self.docstatus==1 else None

View File

@@ -40,7 +40,7 @@ class StaffingPlan(Document):
detail.current_openings = designation_counts['job_openings']
if detail.number_of_positions > 0:
if detail.vacancies > 0 and detail.estimated_cost_per_position:
if detail.vacancies and detail.estimated_cost_per_position:
detail.total_estimated_cost = cint(detail.vacancies) * flt(detail.estimated_cost_per_position)
self.total_estimated_budget += detail.total_estimated_cost
@@ -57,8 +57,7 @@ class StaffingPlan(Document):
and sp.to_date >= %s and sp.from_date <= %s and sp.company = %s
""", (staffing_plan_detail.designation, self.from_date, self.to_date, self.company))
if overlap and overlap [0][0]:
frappe.throw(_("Staffing Plan {0} already exist for designation {1}"
.format(overlap[0][0], staffing_plan_detail.designation)))
frappe.throw(_("Staffing Plan {0} already exist for designation {1}").format(overlap[0][0], staffing_plan_detail.designation))
def validate_with_parent_plan(self, staffing_plan_detail):
if not frappe.get_cached_value('Company', self.company, "parent_company"):
@@ -75,12 +74,12 @@ class StaffingPlan(Document):
if cint(staffing_plan_detail.vacancies) > cint(parent_plan_details[0].vacancies) or \
flt(staffing_plan_detail.total_estimated_cost) > flt(parent_plan_details[0].total_estimated_cost):
frappe.throw(_("You can only plan for upto {0} vacancies and budget {1} \
for {2} as per staffing plan {3} for parent company {4}."
.format(cint(parent_plan_details[0].vacancies),
for {2} as per staffing plan {3} for parent company {4}.").format(
cint(parent_plan_details[0].vacancies),
parent_plan_details[0].total_estimated_cost,
frappe.bold(staffing_plan_detail.designation),
parent_plan_details[0].name,
parent_company)), ParentCompanyError)
parent_company), ParentCompanyError)
#Get vacanices already planned for all companies down the hierarchy of Parent Company
lft, rgt = frappe.get_cached_value('Company', parent_company, ["lft", "rgt"])
@@ -97,14 +96,14 @@ class StaffingPlan(Document):
(flt(parent_plan_details[0].total_estimated_cost) < \
(flt(staffing_plan_detail.total_estimated_cost) + flt(all_sibling_details.total_estimated_cost))):
frappe.throw(_("{0} vacancies and {1} budget for {2} already planned for subsidiary companies of {3}. \
You can only plan for upto {4} vacancies and and budget {5} as per staffing plan {6} for parent company {3}."
.format(cint(all_sibling_details.vacancies),
You can only plan for upto {4} vacancies and and budget {5} as per staffing plan {6} for parent company {3}.").format(
cint(all_sibling_details.vacancies),
all_sibling_details.total_estimated_cost,
frappe.bold(staffing_plan_detail.designation),
parent_company,
cint(parent_plan_details[0].vacancies),
parent_plan_details[0].total_estimated_cost,
parent_plan_details[0].name)))
parent_plan_details[0].name))
def validate_with_subsidiary_plans(self, staffing_plan_detail):
#Valdate this plan with all child company plan
@@ -120,11 +119,11 @@ class StaffingPlan(Document):
cint(staffing_plan_detail.vacancies) < cint(children_details.vacancies) or \
flt(staffing_plan_detail.total_estimated_cost) < flt(children_details.total_estimated_cost):
frappe.throw(_("Subsidiary companies have already planned for {1} vacancies at a budget of {2}. \
Staffing Plan for {0} should allocate more vacancies and budget for {3} than planned for its subsidiary companies"
.format(self.company,
Staffing Plan for {0} should allocate more vacancies and budget for {3} than planned for its subsidiary companies").format(
self.company,
cint(children_details.vacancies),
children_details.total_estimated_cost,
frappe.bold(staffing_plan_detail.designation))), SubsidiaryCompanyError)
frappe.bold(staffing_plan_detail.designation)), SubsidiaryCompanyError)
@frappe.whitelist()
def get_designation_counts(designation, company):

View File

@@ -89,6 +89,7 @@ def execute(filters=None):
"amount": salary.net_pay,
}
data.append(row)
return columns, data
def get_bank_accounts():
@@ -110,7 +111,7 @@ def get_payroll_entries(accounts, filters):
entries = get_all("Payroll Entry", payroll_filter, ["name", "payment_account"])
payment_accounts = [d.payment_account for d in entries]
set_company_account(payment_accounts, entries)
entries = set_company_account(payment_accounts, entries)
return entries
def get_salary_slips(payroll_entries):

View File

@@ -1,16 +1,19 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe, erpnext
from frappe import _
from frappe.utils import formatdate, format_datetime, getdate, get_datetime, nowdate, flt, cstr, add_days, today
from frappe.model.document import Document
from frappe.desk.form import assign_to
import erpnext
import frappe
from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee
from frappe import _
from frappe.desk.form import assign_to
from frappe.model.document import Document
from frappe.utils import (add_days, cstr, flt, format_datetime, formatdate,
get_datetime, getdate, nowdate, today, unique)
class DuplicateDeclarationError(frappe.ValidationError): pass
class EmployeeBoardingController(Document):
'''
Create the project and the task for the boarding process
@@ -29,13 +32,15 @@ class EmployeeBoardingController(Document):
project_name += self.job_applicant
else:
project_name += self.employee
project = frappe.get_doc({
"doctype": "Project",
"project_name": project_name,
"expected_start_date": self.date_of_joining if self.doctype == "Employee Onboarding" else self.resignation_letter_date,
"department": self.department,
"company": self.company
}).insert(ignore_permissions=True)
}).insert(ignore_permissions=True, ignore_mandatory=True)
self.db_set("project", project.name)
self.db_set("boarding_status", "Pending")
self.reload()
@@ -48,27 +53,38 @@ class EmployeeBoardingController(Document):
continue
task = frappe.get_doc({
"doctype": "Task",
"project": self.project,
"subject": activity.activity_name + " : " + self.employee_name,
"description": activity.description,
"department": self.department,
"company": self.company,
"task_weight": activity.task_weight
}).insert(ignore_permissions=True)
"doctype": "Task",
"project": self.project,
"subject": activity.activity_name + " : " + self.employee_name,
"description": activity.description,
"department": self.department,
"company": self.company,
"task_weight": activity.task_weight
}).insert(ignore_permissions=True)
activity.db_set("task", task.name)
users = [activity.user] if activity.user else []
if activity.role:
user_list = frappe.db.sql_list('''select distinct(parent) from `tabHas Role`
where parenttype='User' and role=%s''', activity.role)
users = users + user_list
user_list = frappe.db.sql_list('''
SELECT
DISTINCT(has_role.parent)
FROM
`tabHas Role` has_role
LEFT JOIN `tabUser` user
ON has_role.parent = user.name
WHERE
has_role.parenttype = 'User'
AND user.enabled = 1
AND has_role.role = %s
''', activity.role)
users = unique(users + user_list)
if "Administrator" in users:
users.remove("Administrator")
# assign the task the users
if users:
self.assign_task_to_users(task, set(users))
self.assign_task_to_users(task, users)
def assign_task_to_users(self, task, users):
for user in users:
@@ -453,4 +469,4 @@ def get_previous_claimed_amount(employee, payroll_period, non_pro_rata=False, co
}, as_dict=True)
if sum_of_claimed_amount and flt(sum_of_claimed_amount[0].total_amount) > 0:
total_claimed_amount = sum_of_claimed_amount[0].total_amount
return total_claimed_amount
return total_claimed_amount

View File

@@ -39,6 +39,8 @@ class JobCard(Document):
if d.completed_qty:
self.total_completed_qty += d.completed_qty
self.total_completed_qty = flt(self.total_completed_qty, self.precision("total_completed_qty"))
def get_overlap_for(self, args):
existing = frappe.db.sql("""select jc.name as name from
`tabJob Card Time Log` jctl, `tabJob Card` jc where jctl.parent = jc.name and

View File

@@ -24,6 +24,16 @@ frappe.ui.form.on('Production Plan', {
}
});
frm.set_query('material_request', 'material_requests', function() {
return {
filters: {
material_request_type: "Manufacture",
docstatus: 1,
status: ["!=", "Stopped"],
}
};
});
frm.fields_dict['po_items'].grid.get_field('item_code').get_query = function(doc) {
return {
query: "erpnext.controllers.queries.item_query",

View File

@@ -68,7 +68,7 @@ class ProductionPlan(Document):
from `tabMaterial Request` mr, `tabMaterial Request Item` mr_item
where mr_item.parent = mr.name
and mr.material_request_type = "Manufacture"
and mr.docstatus = 1 and mr.company = %(company)s
and mr.docstatus = 1 and mr.status != "Stopped" and mr.company = %(company)s
and mr_item.qty > ifnull(mr_item.ordered_qty,0) {0} {1}
and (exists (select name from `tabBOM` bom where bom.item=mr_item.item_code
and bom.is_active = 1))

View File

@@ -107,6 +107,8 @@
},
{
"depends_on": "eval:doc.production_item",
"fetch_from": "production_item.item_name",
"fetch_if_empty": 1,
"fieldname": "item_name",
"fieldtype": "Data",
"label": "Item Name",
@@ -470,7 +472,7 @@
"image_field": "image",
"is_submittable": 1,
"links": [],
"modified": "2019-12-04 11:20:04.695123",
"modified": "2021-08-16 11:20:04.695123",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Work Order",

View File

@@ -88,7 +88,7 @@ def get_bom_stock(filters):
GROUP BY bom_item.item_code""".format(qty_field=qty_field, table=table, conditions=conditions, bom=bom), as_dict=1)
def get_manufacturer_records():
details = frappe.get_list('Item Manufacturer', fields = ["manufacturer", "manufacturer_part_no, parent"])
details = frappe.get_list('Item Manufacturer', fields = ["manufacturer", "manufacturer_part_no", "parent"])
manufacture_details = frappe._dict()
for detail in details:
dic = manufacture_details.setdefault(detail.get('parent'), {})

View File

@@ -681,3 +681,9 @@ erpnext.patches.v12_0.update_payment_entry_status
erpnext.patches.v12_0.add_transporter_address_field #2020-10-27
erpnext.patches.v12_0.setup_einvoice_fields #2020-12-02
erpnext.patches.v12_0.add_state_code_for_ladakh
erpnext.patches.v12_0.create_taxable_value_field
erpnext.patches.v12_0.purchase_receipt_status
erpnext.patches.v12_0.add_company_link_to_einvoice_settings
erpnext.patches.v12_0.add_document_type_field_for_italy_einvoicing
erpnext.patches.v12_0.create_taxable_value_field_in_purchase_invoice
erpnext.patches.v12_0.show_einvoice_irn_cancelled_field

View File

@@ -0,0 +1,16 @@
from __future__ import unicode_literals
import frappe
def execute():
company = frappe.get_all('Company', filters = {'country': 'India'})
if not company or not frappe.db.count('E Invoice User'):
return
frappe.reload_doc("regional", "doctype", "e_invoice_user")
for creds in frappe.db.get_all('E Invoice User', fields=['name', 'gstin']):
company_name = frappe.db.sql("""
select dl.link_name from `tabAddress` a, `tabDynamic Link` dl
where a.gstin = %s and dl.parent = a.name and dl.link_doctype = 'Company'
""", (creds.get('gstin')))
if company_name and len(company_name) > 0:
frappe.db.set_value('E Invoice User', creds.get('name'), 'company', company_name[0][0])

View File

@@ -0,0 +1,18 @@
from __future__ import unicode_literals
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
import frappe
def execute():
company = frappe.get_all('Company', filters = {'country': 'Italy'})
if not company:
return
custom_fields = {
'Sales Invoice': [
dict(fieldname='type_of_document', label='Type of Document',
fieldtype='Select', insert_after='customer_fiscal_code',
options='\nTD01\nTD02\nTD03\nTD04\nTD05\nTD06\nTD16\nTD17\nTD18\nTD19\nTD20\nTD21\nTD22\nTD23\nTD24\nTD25\nTD26\nTD27'),
]
}
create_custom_fields(custom_fields, update=True)

View File

@@ -0,0 +1,18 @@
from __future__ import unicode_literals
import frappe
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
def execute():
company = frappe.get_all('Company', filters = {'country': 'India'})
if not company:
return
custom_fields = {
'Sales Invoice Item': [
dict(fieldname='taxable_value', label='Taxable Value',
fieldtype='Currency', insert_after='base_net_amount', hidden=1, options="Company:company:default_currency",
print_hide=1)
]
}
create_custom_fields(custom_fields, update=True)

View File

@@ -0,0 +1,18 @@
from __future__ import unicode_literals
import frappe
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
def execute():
company = frappe.get_all('Company', filters = {'country': 'India'})
if not company:
return
custom_fields = {
'Purchase Invoice Item': [
dict(fieldname='taxable_value', label='Taxable Value',
fieldtype='Currency', insert_after='base_net_amount', hidden=1, options="Company:company:default_currency",
print_hide=1)
]
}
create_custom_fields(custom_fields, update=True)

View File

@@ -0,0 +1,24 @@
""" This patch fixes old purchase receipts (PR) where even after submitting
the PR, the `status` remains "Draft". `per_billed` field was copied over from previous
doc (PO), hence it is recalculated for setting new correct status of PR.
"""
import frappe
def execute():
affected_purchase_receipts = frappe.db.sql(
"""select name from `tabPurchase Receipt`
where status = 'Draft' and per_billed = 100 and docstatus = 1"""
)
if not affected_purchase_receipts:
return
for pr in affected_purchase_receipts:
pr_name = pr[0]
pr_doc = frappe.get_doc("Purchase Receipt", pr_name)
pr_doc.update_billing_status(update_modified=False)
pr_doc.set_status(update=True, update_modified=False)

View File

@@ -0,0 +1,12 @@
from __future__ import unicode_literals
import frappe
def execute():
company = frappe.get_all('Company', filters = {'country': 'India'})
if not company:
return
irn_cancelled_field = frappe.db.exists('Custom Field', {'dt': 'Sales Invoice', 'fieldname': 'irn_cancelled'})
if irn_cancelled_field:
frappe.db.set_value('Custom Field', irn_cancelled_field, 'depends_on', 'eval: doc.irn')
frappe.db.set_value('Custom Field', irn_cancelled_field, 'read_only', 0)

View File

@@ -75,23 +75,23 @@ frappe.ui.form.on("Project", {
frm.add_custom_button(__('Cancelled'), () => {
frm.events.set_status(frm, 'Cancelled');
}, __('Set Status'));
}
if (frappe.model.can_read("Task")) {
frm.add_custom_button(__("Gantt Chart"), function () {
frappe.route_options = {
"project": frm.doc.name
};
frappe.set_route("List", "Task", "Gantt");
});
frm.add_custom_button(__("Kanban Board"), () => {
frappe.call('erpnext.projects.doctype.project.project.create_kanban_board_if_not_exists', {
project: frm.doc.project_name
}).then(() => {
frappe.set_route('List', 'Task', 'Kanban', frm.doc.project_name);
if (frappe.model.can_read("Task")) {
frm.add_custom_button(__("Gantt Chart"), function () {
frappe.route_options = {
"project": frm.doc.name
};
frappe.set_route("List", "Task", "Gantt");
});
});
frm.add_custom_button(__("Kanban Board"), () => {
frappe.call('erpnext.projects.doctype.project.project.create_kanban_board_if_not_exists', {
project: frm.doc.project_name
}).then(() => {
frappe.set_route('List', 'Task', 'Kanban', frm.doc.project_name);
});
});
}
}
},

View File

@@ -125,9 +125,6 @@ class Project(Document):
if self.percent_complete == 100:
self.status = "Completed"
else:
self.status = "Open"
def update_costing(self):
from_time_sheet = frappe.db.sql("""select
sum(costing_amount) as costing_amount,

View File

@@ -30,6 +30,7 @@ class Task(NestedSet):
def validate(self):
self.validate_dates()
self.validate_parent_expected_end_date()
self.validate_parent_project_dates()
self.validate_progress()
self.validate_status()
@@ -44,6 +45,12 @@ class Task(NestedSet):
frappe.throw(_("{0} can not be greater than {1}").format(frappe.bold("Actual Start Date"), \
frappe.bold("Actual End Date")))
def validate_parent_expected_end_date(self):
if self.parent_task:
parent_exp_end_date = frappe.db.get_value("Task", self.parent_task, "exp_end_date")
if parent_exp_end_date and getdate(self.get("exp_end_date")) > getdate(parent_exp_end_date):
frappe.throw(_("Expected End Date should be less than or equal to parent task's Expected End Date {0}.").format(getdate(parent_exp_end_date)))
def validate_parent_project_dates(self):
if not self.project or frappe.flags.in_test:
return
@@ -66,9 +73,6 @@ class Task(NestedSet):
if (self.progress or 0) > 100:
frappe.throw(_("Progress % for a task cannot be more than 100."))
if self.progress == 100:
self.status = 'Completed'
if self.status == 'Completed':
self.progress = 100

View File

@@ -635,34 +635,34 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
this.frm.trigger("item_code", cdt, cdn);
}
else {
var valid_serial_nos = [];
// Replacing all occurences of comma with carriage return
var serial_nos = item.serial_no.trim().replace(/,/g, '\n');
serial_nos = serial_nos.trim().split('\n');
// Trim each string and push unique string to new list
for (var x=0; x<=serial_nos.length - 1; x++) {
if (serial_nos[x].trim() != "" && valid_serial_nos.indexOf(serial_nos[x].trim()) == -1) {
valid_serial_nos.push(serial_nos[x].trim());
}
}
// Add the new list to the serial no. field in grid with each in new line
item.serial_no = valid_serial_nos.join('\n');
item.serial_no = item.serial_no.replace(/,/g, '\n');
item.conversion_factor = item.conversion_factor || 1;
refresh_field("serial_no", item.name, item.parentfield);
if(!doc.is_return && cint(user_defaults.set_qty_in_transactions_based_on_serial_no_input)) {
frappe.model.set_value(item.doctype, item.name,
"qty", valid_serial_nos.length / item.conversion_factor);
frappe.model.set_value(item.doctype, item.name, "stock_qty", valid_serial_nos.length);
if (!doc.is_return && cint(frappe.user_defaults.set_qty_in_transactions_based_on_serial_no_input)) {
setTimeout(() => {
me.update_qty(cdt, cdn);
}, 10000);
}
}
}
},
update_qty: function(cdt, cdn) {
var valid_serial_nos = [];
var serialnos = [];
var item = frappe.get_doc(cdt, cdn);
serialnos = item.serial_no.split("\n");
for (var i = 0; i < serialnos.length; i++) {
if (serialnos[i] != "") {
valid_serial_nos.push(serialnos[i]);
}
}
frappe.model.set_value(item.doctype, item.name,
"qty", valid_serial_nos.length / item.conversion_factor);
frappe.model.set_value(item.doctype, item.name, "stock_qty", valid_serial_nos.length);
},
validate: function() {
this.calculate_taxes_and_totals(false);
},

View File

@@ -507,6 +507,7 @@ erpnext.utils.update_child_items = function(opts) {
}, {
fieldtype:'Currency',
fieldname:"rate",
options: "currency",
default: 0,
read_only: 0,
in_list_view: 1,
@@ -693,7 +694,7 @@ erpnext.utils.map_current_doc = function(opts) {
}
frappe.form.link_formatters['Item'] = function(value, doc) {
if (doc && value && doc.item_name && doc.item_name !== value) {
if (doc && value && doc.item_name && doc.item_name !== value && doc.item_code === value) {
return value + ': ' + doc.item_name;
} else if (!value && doc.doctype && doc.item_name) {
// format blank value in child table

View File

@@ -5,6 +5,7 @@
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"company",
"gstin",
"username",
"password"
@@ -30,12 +31,20 @@
"in_list_view": 1,
"label": "Password",
"reqd": 1
},
{
"fieldname": "company",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Company",
"options": "Company",
"reqd": 1
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2020-12-22 15:10:53.466205",
"modified": "2021-03-22 12:16:56.365616",
"modified_by": "Administrator",
"module": "Regional",
"name": "E Invoice User",

View File

@@ -109,7 +109,7 @@
</td>
</tr>
<tr>
<td>{{__("Suppliies made to Composition Taxable Persons")}}</td>
<td>{{__("Supplies made to Composition Taxable Persons")}}</td>
<td class="right">
{% for row in data.inter_sup.comp_details %}
{% if row %}

View File

@@ -172,7 +172,6 @@ class GSTR3BReport(Document):
self.json_output = frappe.as_json(self.report_dict)
def set_inward_nil_exempt(self, inward_nil_exempt):
self.report_dict["inward_sup"]["isup_details"][0]["inter"] = flt(inward_nil_exempt.get("gst").get("inter"), 2)
self.report_dict["inward_sup"]["isup_details"][0]["intra"] = flt(inward_nil_exempt.get("gst").get("intra"), 2)
self.report_dict["inward_sup"]["isup_details"][1]["inter"] = flt(inward_nil_exempt.get("non_gst").get("inter"), 2)
@@ -238,7 +237,6 @@ class GSTR3BReport(Document):
self.report_dict[supply_type][supply_category]["txval"] += flt(txval, 2)
def set_inter_state_supply(self, inter_state_supply):
osup_det = self.report_dict["sup_details"]["osup_det"]
for key, value in iteritems(inter_state_supply):
@@ -350,13 +348,20 @@ class GSTR3BReport(Document):
return inter_state_supply_details
def get_inward_nil_exempt(self, state):
inward_nil_exempt = frappe.db.sql(""" select p.place_of_supply, sum(i.base_amount) as base_amount,
i.is_nil_exempt, i.is_non_gst from `tabPurchase Invoice` p , `tabPurchase Invoice Item` i
where p.docstatus = 1 and p.name = i.parent
and i.is_nil_exempt = 1 or i.is_non_gst = 1 and
and p.gst_category != 'Registered Composition'
and (i.is_nil_exempt = 1 or i.is_non_gst = 1) and
month(p.posting_date) = %s and year(p.posting_date) = %s and p.company = %s and p.company_gstin = %s
group by p.place_of_supply """, (self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1)
group by p.place_of_supply, i.is_nil_exempt, i.is_non_gst""", (self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1)
inward_nil_exempt += frappe.db.sql("""SELECT sum(base_net_total) as base_amount, gst_category, place_of_supply
FROM `tabPurchase Invoice`
WHERE docstatus = 1 and gst_category = 'Registered Composition'
and month(posting_date) = %s and year(posting_date) = %s
and company = %s and company_gstin = %s
group by place_of_supply""", (self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1)
inward_nil_exempt_details = {
"gst": {
@@ -371,9 +376,11 @@ class GSTR3BReport(Document):
for d in inward_nil_exempt:
if d.place_of_supply:
if d.is_nil_exempt == 1 and state == d.place_of_supply.split("-")[1]:
if (d.is_nil_exempt == 1 or d.get('gst_category') == 'Registered Composition') \
and state == d.place_of_supply.split("-")[1]:
inward_nil_exempt_details["gst"]["intra"] += d.base_amount
elif d.is_nil_exempt == 1 and state != d.place_of_supply.split("-")[1]:
elif (d.is_nil_exempt == 1 or d.get('gst_category') == 'Registered Composition') \
and state != d.place_of_supply.split("-")[1]:
inward_nil_exempt_details["gst"]["inter"] += d.base_amount
elif d.is_non_gst == 1 and state == d.place_of_supply.split("-")[1]:
inward_nil_exempt_details["non_gst"]["intra"] += d.base_amount

View File

@@ -63,7 +63,7 @@ class TestGSTR3BReport(unittest.TestCase):
self.assertEqual(output["sup_details"]["osup_zero"]["iamt"], 18),
self.assertEqual(output["inter_sup"]["unreg_details"][0]["iamt"], 18),
self.assertEqual(output["sup_details"]["osup_nil_exmp"]["txval"], 100),
self.assertEqual(output["inward_sup"]["isup_details"][0]["inter"], 250)
self.assertEqual(output["inward_sup"]["isup_details"][0]["intra"], 250)
self.assertEqual(output["itc_elg"]["itc_avl"][4]["samt"], 22.50)
self.assertEqual(output["itc_elg"]["itc_avl"][4]["camt"], 22.50)
@@ -190,6 +190,19 @@ def create_purchase_invoices():
pi1.submit()
pi2 = make_purchase_invoice(company="_Test Company GST",
customer = '_Test Registered Supplier',
currency = 'INR',
item = 'Milk',
warehouse = 'Finished Goods - _GST',
expense_account = 'Cost of Goods Sold - _GST',
cost_center = 'Main - _GST',
rate=250,
qty=1,
do_not_save=1
)
pi2.submit()
def make_suppliers():
if not frappe.db.exists("Supplier", "_Test Registered Supplier"):

View File

@@ -69,7 +69,7 @@ state_numbers = {
"Mizoram": "15",
"Nagaland": "13",
"Odisha": "21",
"Other Territory": "98",
"Other Territory": "97",
"Pondicherry": "34",
"Punjab": "03",
"Rajasthan": "08",

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