Compare commits

...

82 Commits

Author SHA1 Message Date
Ivan Ray Altomera
1d6bb3953d fix: Customer Ledger Summary report not working on python 3 (#23957) 2021-01-04 11:54:19 +05:30
rohitwaghchaure
78d0a11d09 Merge pull request #23327 from iRaySpace/stock-controller-fix
fix(stock_controller): precision based on `debit_in_account_currency`
2020-10-12 17:38:00 +05:30
Ivan Ray Altomera
ccf62886e4 fix(stock_controller): precision based on debit_in_account_currency 2020-09-15 15:36:31 +08:00
rohitwaghchaure
40747e1b49 Merge pull request #22459 from britlog/version-11-hotfix
fix product_info
2020-06-26 15:55:24 +05:30
britlog
87f8d66b79 fix product_info 2020-06-25 16:18:58 +02:00
Revant Nandgaonkar
d075399ecd ci: github release action for v11 (#22408) 2020-06-24 10:45:18 +05:30
mergify[bot]
c4ff9c72dd fix:status error in purchase invoice (#22390)
(cherry picked from commit 8a1f2ed65a)

Co-authored-by: Kenneth Sequeira <seq.kenneth@gmail.com>
2020-06-23 10:35:18 +05:30
Mangesh-Khairnar
97ccb0eec2 fix: update shopify api version (#22311) 2020-06-18 15:50:16 +05:30
mergify[bot]
2382312d41 fix: fetch tax lines within the shipping lines (#22138) (#22140)
(cherry picked from commit 3031128167)

Co-authored-by: Mangesh-Khairnar <mkhairnar10@gmail.com>
2020-06-07 18:59:14 +05:30
rohitwaghchaure
348d10cad8 Merge pull request #22078 from rohitwaghchaure/show-disabled-items-stock-balance-v11-hotfix
fix: show disabled items in the stock balance
2020-06-02 12:41:24 +05:30
Rohit Waghchaure
47f030b1bf fix: show disabled items in the stock balance 2020-06-02 12:39:51 +05:30
Mangesh-Khairnar
d839c46f10 fix: make transaction date of the oldest transaction as the last integration date (#22015)
* fix: make transaction date of the oldest transaction as the last integration date

* fix: only save end date when transactions are returned
2020-05-29 10:16:59 +05:30
Suraj Shetty
6d45dfd6e8 Merge pull request #21217 from gavindsouza/freeze-v11 2020-05-26 11:49:41 +05:30
sahil28297
a611cc5916 fix(patch): use translated string while setting notification template (#21680) 2020-05-11 19:28:30 +05:30
sahil28297
c6466c7d97 fix(item): patch to rename duplicate item_code values to name (#21621) 2020-05-07 12:11:42 +05:30
Sun Howwrongbum
fdd93cba03 fix: alter 'other_charges_calculation' to Long Text (#21304) 2020-04-16 22:45:12 +05:30
Gavin D'souza
10f53f04d7 chore: pinned python requirements
dependencies from pip freeze of version-11 production environment
2020-04-09 12:26:32 +05:30
Don-Leopardo
3e2fe12c9d Fix: sql injection (#20816) 2020-03-16 22:36:19 +05:30
Saqib
5b2ca9e133 fix: is_pos gets reset on making s_inv from s_ord (#20888)
* s_inv has is_pos default set as 1
2020-03-16 17:50:35 +05:30
Chinmay Pai
f8dc7b32d5 fix: use ERPNext in welcome email when default company is not set (#20837)
Signed-off-by: Chinmay D. Pai <chinmaydpai@gmail.com>
2020-03-16 13:50:09 +05:30
RJPvT
0393cb5c43 fix: smaller then instead of bigger then :-( dumb mistake (#20693)
* fix: smaller then instead of bigger then :-( dumb mistake

* fix: comment on get_all

* Update erpnext/projects/doctype/task/task.py

Co-Authored-By: Himanshu <himanshuwarekar@yahoo.com>

* Update erpnext/projects/doctype/task/task.py

Co-Authored-By: Himanshu <himanshuwarekar@yahoo.com>

Co-authored-by: Himanshu <himanshuwarekar@yahoo.com>
2020-02-26 12:49:48 +05:30
Mathieu Brunot
39c71e26b9 chore(ci-coverage): Pin coverage 4.5.4 #20646 (#20649)
* chore(ci-coverage): Pin coveralls 4.5.4 #20646

Signed-off-by: mathieu.brunot <mathieu.brunot@monogramm.io>

* chore: Fix coverage

Signed-off-by: mathieu.brunot <mathieu.brunot@monogramm.io>
2020-02-20 12:51:32 +05:30
Deepesh Garg
77285317c0 Merge pull request #20665 from marination/stock-settings-query-v11-hotfix
fix: Set Query on warehouse fields in Stock Settings
2020-02-19 18:59:37 +05:30
marination
a95c09bef6 fix: Server side validation for Warehouses 2020-02-19 11:30:47 +05:30
marination
6b901d0c1a fix: Set Query on warehouse fields in Stock Settings 2020-02-18 21:51:00 +05:30
rohitwaghchaure
8a7ccd9874 Merge pull request #20656 from marination/precision-mr-item-v11-hotfix
fix: Stock Quantity not calculated on client side in Material Request Items.
2020-02-18 12:34:45 +05:30
marination
2f2e748b7a fix: Stock Quantity not calculated on client side in Material Request Items. 2020-02-18 11:19:37 +05:30
Deepesh Garg
549ab68eb0 Merge pull request #20503 from sunhoww/patch-4
fix: [v11] negative stock error at landed cost voucher
2020-02-02 17:35:54 +05:30
Sun Howwrongbum
0b9bf4d0ac fix: negative stock error at landed cost voucher 2020-02-02 16:45:57 +05:30
Nabin Hait
1c5df5dede cannot close task if dependent task are not closed / cancelled (#20433) 2020-01-28 14:08:31 +05:30
Deepesh Garg
41d2357dc4 Merge pull request #20442 from fproldan/fix_sqlinjection_hotfix_v11
fix: SQL Injection in get_product_list_for_group method
2020-01-28 09:17:39 +05:30
NahuelOperto
af79714f40 Fix sql injection 2020-01-27 08:55:35 -03:00
Marica
8a5f31da34 fix: Applied query on PO Supplier popup field in Material Request. (#20233) 2020-01-15 19:24:39 +05:30
Marica
d973fb8823 fix: Added description and title to supplier selection popup in Material Request (#20181)
* fix: Added description and title to supplier selection popup in Material Request

* Update material_request.js

cleanup

Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com>
2020-01-07 13:04:56 +05:30
Marica
a649414419 fix: Remove unnecessary Duplicate Entry Error (#20122) 2019-12-27 16:53:00 +05:30
rohitwaghchaure
270f23b966 Merge pull request #20080 from nabinhait/rounding-adjustment
fix: rounding adjustment while both inclusive tax and discount amount present
2019-12-27 11:52:24 +05:30
Nabin Hait
4d745a39e0 fix: rounding adjustment while both inclusive tax and discount amount present 2019-12-25 13:59:24 +05:30
Don-Leopardo
5e0b5cb283 perf: Asset Depreciations and Balances report (#18455) 2019-12-24 17:35:57 +05:30
Sun Howwrongbum
69358cfd40 feat: consider expiry_date during Batch queries (#19972) 2019-12-24 12:30:20 +05:30
RJPvT
ad1ba2bb76 fix: sc object not loaded (#19892)
fix for object not loaded and errors in auto-generate :

Traceback (most recent call last):
  File "/home/frappe/frappe-bench/apps/frappe/frappe/utils/background_jobs.py", line 103, in execute_job
    method(**kwargs)
  File "/home/frappe/frappe-bench/apps/erpnext/erpnext/buying/doctype/supplier_scorecard/supplier_scorecard.py", line 141, in refresh_scorecards
    sc.save()
TypeError: 'NoneType' object is not callable
2019-12-24 12:20:41 +05:30
DeeMysterio
c44abd2f78 fix(employee onboarding): stop showing irrelevant job offer links for a job applicant (#20055) 2019-12-23 19:02:59 +05:30
Deepesh Garg
0bcada8f3c Merge pull request #20016 from marination/valuation_rate_company_v11_hotfix
fix: Company None not found in get_valuation_rate
2019-12-20 11:56:24 +05:30
marination
a6b110a7d3 fix: Company None not found in get_valuation_rate 2019-12-19 14:50:17 +05:30
Deepesh Garg
f9297416f2 fix: Append expense account only if expense account exists (#19882) 2019-12-10 12:14:58 +05:30
Nabin Hait
a8d2916e61 Merge branch 'version-11' into version-11-hotfix 2019-12-09 18:08:05 +05:30
Deepesh Garg
c4756e938f fix: Rounding Adjustment GL entry fix (#19840)
* fix: Rounding Adjustment GL entry fix

* fix: Spacing in tab

* fix: Comment fix
2019-12-09 13:03:18 +05:30
Deepesh Garg
faa5d90f1b fix: NoneType' object has no attribute '__getitem__' (#19861) 2019-12-09 11:28:38 +05:30
rohitwaghchaure
3b37a109c5 Merge pull request #19852 from rohitwaghchaure/fixed_timesheet_overlap_issue_v11_hotfix
fix: timesheet overlap error
2019-12-07 14:10:35 +05:30
Rohit Waghchaure
ab4aa53f52 fix: timesheet overlap error 2019-12-07 13:28:09 +05:30
Nabin Hait
3483426fe7 optimize: Optimization of Receivable report filtered based on sales person (#19795) 2019-12-04 15:30:48 +05:30
Deepesh Garg
3039094737 fix: Party name field in trial balacne for party report (#19791) 2019-12-03 16:30:16 +05:30
Nabin Hait
e21602d432 Update accounts_receivable_summary.py 2019-12-03 16:22:22 +05:30
Marica
6067ef3c49 fix: Item qty cannot be zero in Purchase Receipt (#19781) 2019-12-03 12:45:28 +05:30
Deepesh Garg
b78128a7fe Merge pull request #19767 from deepeshgarg007/avaiable_stock_for_v11
fix: Available stock for packing item report
2019-12-02 11:57:07 +05:30
deepeshgarg007
c8cbb87168 fix: Available stock for packing item report 2019-12-01 22:17:46 +05:30
Deepesh Garg
aed8aeb83a fix: Account type in Handling Difference in Inventory account (#19675)
* fix: Account type in Handling Difference in Inventory account

* fix: Add Stock Adjustment account

* fix: Rename account to stock adjustment
2019-11-28 18:29:26 +05:30
Saqib
fa47445e11 fix: due date before posting date for items added to cart yesterday (#19680) 2019-11-28 18:27:55 +05:30
Marica
0220acf100 fix: Changed type of column 'serial_no' in Stock Ledger Entry (#19705) 2019-11-28 18:20:57 +05:30
Marica
0fe8f8e6d9 fix: get_batch_qty_and_serial_no() requires argument 'stock_qty' (#19699) 2019-11-27 15:51:12 +05:30
rohitwaghchaure
f87b766a26 Merge pull request #19688 from deepeshgarg007/sales_invoice_serial_no
fix: Serial no validation against sales invoice
2019-11-27 11:59:46 +05:30
deepeshgarg007
2262e5d443 fix: Validation msg 2019-11-26 16:15:05 +05:30
deepeshgarg007
b9cad8d891 fix: Serial no validation against sales invoice 2019-11-26 15:27:54 +05:30
Marica
dafdc6035a fix: Validation Error message on Prepared Report. (#19640)
Give the user the reason why he has to use filters.
2019-11-22 14:38:53 +05:30
Marica
c8369c10ff fix: Get Current Stock button in Purhase Receipt not working (#19653)
- Current Stock visible in grid view within Supplied Items table of Purchase Receipt
2019-11-22 13:33:11 +05:30
Deepesh Garg
08b8ed5ca6 Merge pull request #19635 from ruchamahabal/fix_cash_entry_v11
fix(minor): default Cash Entry account not getting fetched in Journal Entry (v11)
2019-11-20 22:02:48 +05:30
Rucha Mahabal
6cefdb40d1 fix(Journal Entry): default Cash Entry account not getting fetched 2019-11-20 20:13:04 +05:30
rohitwaghchaure
d87d644dc2 Merge pull request #19621 from rohitwaghchaure/not_able_to_select_item_in_the_sales_order_hotfix
fix: not able to select item in sales order
2019-11-19 19:40:29 +05:30
rohitwaghchaure
eeab3128aa Merge pull request #19623 from rohitwaghchaure/code_cleanup_sales_invoice_credit_note_hotfix
fix: code cleanup
2019-11-19 19:39:36 +05:30
Rohit Waghchaure
7b2cec8da2 fix: code cleanup 2019-11-19 19:27:31 +05:30
rohitwaghchaure
6e3cbd8698 Update queries.py 2019-11-19 19:26:31 +05:30
Rohit Waghchaure
b5e1f846ce fix: not able to select item in sales order 2019-11-19 19:08:44 +05:30
rohitwaghchaure
9c7a33405d Merge pull request #19024 from Alchez/v11-work-order-bugs
fix: Work Order operating cost re-calculation on client-side (v11)
2019-11-15 11:18:39 +05:30
Rohan
1b9a55e766 Merge branch 'version-11-hotfix' into v11-work-order-bugs 2019-11-13 13:08:59 +05:30
Rohan
4a79072c71 Merge branch 'version-11-hotfix' into v11-work-order-bugs 2019-11-06 11:39:11 +05:30
Rohan
f2dc89c7a0 Merge branch 'version-11-hotfix' into v11-work-order-bugs 2019-10-29 11:25:40 +05:30
Rohan
dd3cd6e2ba Merge branch 'version-11-hotfix' into v11-work-order-bugs 2019-10-22 17:11:39 +05:30
Rohan
529b465337 Merge branch 'version-11-hotfix' into v11-work-order-bugs 2019-10-16 15:11:45 +05:30
Rohan
85be3ec796 Merge branch 'version-11-hotfix' into v11-work-order-bugs 2019-10-11 12:50:28 +05:30
Rohan
43a0161257 Merge branch 'version-11-hotfix' into v11-work-order-bugs 2019-10-04 13:13:06 +05:30
Rohan
ce60dc3ea3 Merge branch 'version-11-hotfix' into v11-work-order-bugs 2019-09-25 14:45:21 +05:30
Rohan
b23da53fee Merge branch 'version-11-hotfix' into v11-work-order-bugs 2019-09-18 13:24:25 +05:30
Rohan
d37a30fc47 fix: operating cost calculation in JS 2019-09-12 16:12:48 +05:30
63 changed files with 2101 additions and 1762 deletions

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

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

View File

@@ -76,5 +76,6 @@ install:
- bench --site test_site reinstall --yes
after_script:
- pip install coverage==4.5.4
- pip install python-coveralls
- coveralls -b apps/erpnext -d ../../sites/.coverage

View File

@@ -1,465 +1,466 @@
{
"country_code": "ae",
"name": "U.A.E - Chart of Accounts",
"country_code": "ae",
"name": "U.A.E - Chart of Accounts",
"tree": {
"Assets": {
"Current Assets": {
"Accounts Receivable": {
"Corporate Credit Cards": {
"account_type": "Receivable"
},
},
"Other Receivable": {
"Accrued Rebates Due from Suppliers": {
"account_type": "Receivable"
},
"Accured Income from Suppliers": {
},
"Accrued Income from Suppliers": {
"account_type": "Receivable"
},
},
"Other Debtors": {
"account_type": "Receivable"
},
},
"account_type": "Receivable"
},
},
"Post Dated Cheques Received": {
"account_type": "Receivable"
},
},
"Staff Receivable": {
"account_type": "Receivable"
},
},
"Trade Receivable": {
"account_type": "Receivable"
},
},
"Trade in Opening Fees": {
"account_type": "Receivable"
},
},
"account_type": "Receivable"
},
},
"Cash in Hand & Banks": {
"Banks": {
"Bank Margin On LC & LG": {},
"Banks Blocked Deposits": {},
"Banks Call Deposit Accounts": {},
"Bank Margin On LC & LG": {},
"Banks Blocked Deposits": {},
"Banks Call Deposit Accounts": {},
"Banks Current Accounts": {
"account_type": "Bank"
},
},
"account_type": "Bank"
},
},
"Cash in Hand": {
"Cash in Safe": {
"Main Safe": {
"account_type": "Cash"
},
},
"Main Safe - Foreign Currency": {
"account_type": "Cash"
}
},
},
"Petty Cash": {
"Petty Cash - Admininistration": {
"account_type": "Cash"
},
},
"Petty Cash - Others": {
"account_type": "Cash"
}
},
},
"account_type": "Cash"
},
},
"Cash in Transit": {
"Credit Cards": {
"Gateway Credit Cards": {
"account_type": "Bank"
},
},
"Manual Visa & Master Cards": {
"account_type": "Bank"
},
},
"PayPal Account": {
"account_type": "Bank"
},
},
"Visa & Master Credit Cards": {
"account_type": "Bank"
}
}
}
},
},
"Inventory": {
"Consigned Stock": {
"Handling Difference in Inventory": {
"account_type": "Stock Adjustment"
},
"Items Delivered to Customs on temprary Base": {}
},
"Handling Difference in Inventory": {},
"Items Delivered to Customs on temporary Base": {}
},
"Stock in Hand": {
"account_type": "Stock"
}
},
"Perliminary and Preoperating Expenses": {
},
"Preliminary and Preoperating Expenses": {
"Preoperating Expenses": {}
},
},
"Prepayments & Deposits": {
"Deposits": {
"Deposit - Office Rent": {},
"Deposit Others": {},
"Deposit to Immigration (Visa)": {},
"Deposit - Office Rent": {},
"Deposit Others": {},
"Deposit to Immigration (Visa)": {},
"Deposits - Customs": {}
},
},
"Prepaid Taxes": {
"Sales Taxes Receivables": {},
"Sales Taxes Receivables": {},
"Withholding Tax Receivables": {}
},
},
"Prepayments": {
"Other Prepayments": {},
"PrePaid Advertisement Expenses": {},
"Prepaid Bank Guarantee": {},
"Prepaid Consultancy Fees": {},
"Prepaid Employees Housing": {},
"Prepaid Finance charge for Loans": {},
"Prepaid Legal Fees": {},
"Prepaid License Fees": {},
"Prepaid Life Insurance": {},
"Prepaid Maintenance": {},
"Prepaid Medical Insurance": {},
"Prepaid Office Rent": {},
"Prepaid Other Insurance": {},
"Prepaid Schooling Fees": {},
"Prepaid Site Hosting Fees": {},
"Other Prepayments": {},
"PrePaid Advertisement Expenses": {},
"Prepaid Bank Guarantee": {},
"Prepaid Consultancy Fees": {},
"Prepaid Employees Housing": {},
"Prepaid Finance charge for Loans": {},
"Prepaid Legal Fees": {},
"Prepaid License Fees": {},
"Prepaid Life Insurance": {},
"Prepaid Maintenance": {},
"Prepaid Medical Insurance": {},
"Prepaid Office Rent": {},
"Prepaid Other Insurance": {},
"Prepaid Schooling Fees": {},
"Prepaid Site Hosting Fees": {},
"Prepaid Sponsorship Fees": {}
}
}
},
},
"Long Term Assets": {
"Fixed Assets": {
"Accumulated Depreciation": {
"Acc. Depreciation of Motor Vehicles": {
"account_type": "Accumulated Depreciation"
},
},
"Acc. Deprn.Computer Hardware & Software": {
"account_type": "Accumulated Depreciation"
},
},
"Acc.Deprn.of Furniture & Office Equipment": {
"account_type": "Accumulated Depreciation"
},
},
"Amortisation on Leasehold Improvement": {
"account_type": "Accumulated Depreciation"
},
},
"account_type": "Accumulated Depreciation"
},
},
"Fixed Assets (Cost Price)": {
"Computer Hardware & Software": {
"account_type": "Fixed Asset"
},
},
"Furniture and Equipment": {
"account_type": "Fixed Asset"
},
"Leasehold Improvement": {},
"Motor Vehicules": {
},
"Leasehold Improvement": {},
"Motor Vehicles": {
"account_type": "Fixed Asset"
},
"Work In Progrees": {},
},
"Work In Progress": {},
"account_type": "Fixed Asset"
}
},
},
"Intangible Assets": {
"Computer Card Renewal": {},
"Dispoal of Outlets": {},
"Computer Card Renewal": {},
"Disposal of Outlets": {},
"Registration of Trademarks": {}
},
"Intercompany Accounts": {},
},
"Intercompany Accounts": {},
"Investments": {
"Investments in Subsidiaries": {}
}
},
},
"root_type": "Asset"
},
},
"Closing And Temporary Accounts": {
"Closing Accounts": {
"Closing Account": {}
},
},
"root_type": "Liability"
},
},
"Expenses": {
"Commercial Expenses": {
"Consultancy Fees": {},
"Consultancy Fees": {},
"Provision for Doubtful Debts": {}
},
},
"Cost of Sale": {
"Cost Of Goods Sold": {
"Cost Of Goods Sold I/C Sales": {},
"Cost Of Goods Sold I/C Sales": {},
"Cost of Goods Sold in Trading": {
"account_type": "Cost of Goods Sold"
},
},
"account_type": "Cost of Goods Sold"
},
},
"Expenses Included In Valuation": {
"account_type": "Expenses Included In Valuation"
},
"Stock Adjustment": {
"account_type": "Stock Adjustment"
}
},
},
"Depreciation": {
"Depreciation & Amortization": {
"Amortization on Leasehold Improvement": {},
"Amortization on Leasehold Improvement": {},
"Depreciation Of Computer Hard & Soft": {
"account_type": "Depreciation"
},
},
"Depreciation Of Furniture & Office Equipment\n\t\t\t": {
"account_type": "Depreciation"
},
},
"Depreciation Of Motor Vehicles": {
"account_type": "Depreciation"
}
}
},
},
"Direct Expenses": {
"Financial Charges": {
"Air Miles Card Charges": {},
"Amex Credit Cards Charges": {},
"Bank Finance & Loan Charges": {},
"Credit Card Charges": {},
"Credit Card Swipe Charges": {},
"Air Miles Card Charges": {},
"Amex Credit Cards Charges": {},
"Bank Finance & Loan Charges": {},
"Credit Card Charges": {},
"Credit Card Swipe Charges": {},
"PayPal Charges": {}
}
},
},
"MISC Charges": {
"Other Charges": {
"Captial Loss": {
"Disposal of Business Branch": {},
"Loss On Fixed Assets Disposal": {},
"Capital Loss": {
"Disposal of Business Branch": {},
"Loss On Fixed Assets Disposal": {},
"Loss on Difference on Exchange": {}
},
},
"Other Non Operating Exp": {
"Other Non Operating Expenses": {}
},
},
"Previous Year Adjustments": {
"Previous Year Adjustments Account": {}
},
},
"Royalty Fees": {
"Royalty to Parent Co.": {}
},
},
"Tax / Zakat Expenses": {
"Income Tax": {
"account_type": "Tax"
},
"Zakat": {},
},
"Zakat": {},
"account_type": "Tax"
}
}
},
},
"Share Resources": {
"Share Resource Expenses Account": {}
},
},
"Store Operating Expenses": {
"Selling, General & Admin Expenses": {
"Advertising Expenses": {
"Other - Advertising Expenses": {}
},
},
"Bank & Finance Charges": {
"Other Bank Charges": {}
},
},
"Communications": {
"Courrier": {},
"Others - Communication": {},
"Telephone": {},
"Courier": {},
"Others - Communication": {},
"Telephone": {},
"Web Site Hosting Fees": {}
},
},
"Office & Various Expenses": {
"Cleaning": {},
"Convoyance Expenses": {},
"Gifts & Donations": {},
"Insurance": {},
"Kitchen and Buffet Expenses": {},
"Maintenance": {},
"Others - Office Various Expenses": {},
"Security & Guard": {},
"Stationary From Suppliers": {},
"Stationary Out Of Stock": {},
"Subscriptions": {},
"Training": {},
"Cleaning": {},
"Conveyance Expenses": {},
"Gifts & Donations": {},
"Insurance": {},
"Kitchen and Buffet Expenses": {},
"Maintenance": {},
"Others - Office Various Expenses": {},
"Security & Guard": {},
"Stationary From Suppliers": {},
"Stationary Out Of Stock": {},
"Subscriptions": {},
"Training": {},
"Vehicle Expenses": {}
},
},
"Personnel Cost": {
"Basic Salary": {},
"End Of Service Indemnity": {},
"Housing Allowance": {},
"Leave Salary": {},
"Leave Ticket": {},
"Life Insurance": {},
"Medical Insurance": {},
"Personnel Cost Others": {},
"Sales Commission": {},
"Staff School Allowances": {},
"Transportation Allowance": {},
"Uniform": {},
"Basic Salary": {},
"End Of Service Indemnity": {},
"Housing Allowance": {},
"Leave Salary": {},
"Leave Ticket": {},
"Life Insurance": {},
"Medical Insurance": {},
"Personnel Cost Others": {},
"Sales Commission": {},
"Staff School Allowances": {},
"Transportation Allowance": {},
"Uniform": {},
"Visa Expenses": {}
},
},
"Professional & Legal Fees": {
"Audit Fees": {},
"Legal fees": {},
"Others - Professional Fees": {},
"Sponsorship Fees": {},
"Audit Fees": {},
"Legal fees": {},
"Others - Professional Fees": {},
"Sponsorship Fees": {},
"Trade License Fees": {}
},
},
"Provision & Write Off": {
"Amortisation of Preoperating Expenses": {},
"Cash Shortage": {},
"Others - Provision & Write off": {},
"Write Off Inventory": {},
"Amortisation of Preoperating Expenses": {},
"Cash Shortage": {},
"Others - Provision & Write off": {},
"Write Off Inventory": {},
"Write Off Receivables & Payables": {}
},
},
"Rent Expenses": {
"Office Rent": {},
"Office Rent": {},
"Warehouse Rent": {}
},
},
"Travel Expenses": {
"Air tickets": {},
"Hotel": {},
"Meals": {},
"Others": {},
"Air tickets": {},
"Hotel": {},
"Meals": {},
"Others": {},
"Per Diem": {}
},
},
"Utilities": {
"Other Utility Cahrges": {},
"Other Utility Cahrges": {},
"Water & Electricity": {}
}
}
},
},
"root_type": "Expense"
},
},
"Liabilities": {
"Current Liabilities": {
"Accounts Payable": {
"Payables": {
"Advance Paybale to Suppliers": {
"account_type": "Payable"
},
},
"Consigned Payable": {
"account_type": "Payable"
},
},
"Other Payable": {
"account_type": "Payable"
},
},
"Post Dated Cheques Paid": {
"account_type": "Payable"
},
"Staff Payable": {},
},
"Staff Payable": {},
"Suppliers Price Protection": {
"account_type": "Payable"
},
},
"Trade Payable": {
"account_type": "Payable"
},
},
"account_type": "Payable"
}
},
},
"Accruals & Provisions": {
"Accruals": {
"Accrued Personnel Cost": {
"Accrued - Commissions": {},
"Accrued - Leave Salary": {},
"Accrued - Leave Tickets": {},
"Accrued - Salaries": {},
"Accrued Other Personnel Cost": {},
"Accrued Salaries Increment": {},
"Accrued - Commissions": {},
"Accrued - Leave Salary": {},
"Accrued - Leave Tickets": {},
"Accrued - Salaries": {},
"Accrued Other Personnel Cost": {},
"Accrued Salaries Increment": {},
"Accrued-Staff Bonus": {}
}
},
},
"Accrued Expenses": {
"Accrued Other Expenses": {
"Accrued - Audit Fees": {},
"Accrued - Office Rent": {},
"Accrued - Sponsorship": {},
"Accrued - Telephone": {},
"Accrued - Utilities": {},
"Accrued - Audit Fees": {},
"Accrued - Office Rent": {},
"Accrued - Sponsorship": {},
"Accrued - Telephone": {},
"Accrued - Utilities": {},
"Accrued Others": {}
}
},
},
"Other Current Liabilities": {
"Accrued Dubai Customs": {},
"Deferred income": {},
"Accrued Dubai Customs": {},
"Deferred income": {},
"Shipping & Handling": {}
},
},
"Provisions": {
"Tax Payables": {
"Income Tax Payable": {},
"Sales Tax Payable": {},
"Income Tax Payable": {},
"Sales Tax Payable": {},
"Withholding Tax Payable": {}
}
},
},
"Short Term Loan": {}
},
},
"Duties and Taxes": {
"account_type": "Tax",
"account_type": "Tax",
"is_group": 1
},
},
"Reservations & Credit Notes": {
"Credit Notes": {
"Credit Notes to Customers": {},
"Credit Notes to Customers": {},
"Reservations": {}
}
},
},
"Stock Liabilities": {
"Stock Received But Not Billed": {
"account_type": "Stock Received But Not Billed"
}
},
},
"Unearned Income": {}
},
},
"Long Term Liabilities": {
"Long Term Loans & Provisions": {}
},
},
"root_type": "Liability"
},
},
"Revenue": {
"Direct Revenue": {
"Other Direct Revenue": {
"Other Revenue - Operating": {
"Advertising Income": {},
"Branding Income": {},
"Early Setmt Margin from Suppliers": {},
"Marketing Rebate from Suppliers": {},
"Rebate from Suppliers": {},
"Service Income": {},
"Advertising Income": {},
"Branding Income": {},
"Early Setmt Margin from Suppliers": {},
"Marketing Rebate from Suppliers": {},
"Rebate from Suppliers": {},
"Service Income": {},
"Space Rental Income": {}
}
}
},
},
"Indirect Revenue": {
"Other Indirect Revenue": {
"Capital Gain": {},
"Excess In Till": {},
"Gain On Difference Of Exchange": {},
"Management Consultancy Fees": {},
"Capital Gain": {},
"Excess In Till": {},
"Gain On Difference Of Exchange": {},
"Management Consultancy Fees": {},
"Other Income": {}
},
},
"Other Revenue - Non Operating": {
"Interest Revenue": {},
"Interest from FD": {},
"Products Listing Fees from Suppliers": {},
"Interest Revenue": {},
"Interest from FD": {},
"Products Listing Fees from Suppliers": {},
"Trade Opening Fees from suppliers": {}
}
},
},
"Sales": {
"Sales from Other Regions": {
"Sales from Other Region": {}
},
},
"Sales of same region": {
"Management Consultancy Fees 1": {},
"Sales Account": {},
"Management Consultancy Fees 1": {},
"Sales Account": {},
"Sales of I/C": {}
}
},
},
"root_type": "Income"
},
},
"Share Holder Equity": {
"Capital": {
"Contributed Capital": {},
"Share Capital": {},
"Shareholders Current A/c": {},
"Sub Ordinated Loan": {},
"Contributed Capital": {},
"Share Capital": {},
"Shareholders Current A/c": {},
"Sub Ordinated Loan": {},
"Treasury Stocks": {}
},
},
"Retained Earnings": {
"Current Year Results": {},
"Dividends Paid": {},
"Current Year Results": {},
"Dividends Paid": {},
"Previous Years Results": {}
},
"account_type": "Equity",
},
"account_type": "Equity",
"root_type": "Equity"
}
}

View File

@@ -6,6 +6,7 @@ from __future__ import unicode_literals
import frappe, json
from frappe.model.document import Document
from frappe import _
from frappe.desk.search import sanitize_searchfield
class BankGuarantee(Document):
def validate(self):
@@ -22,5 +23,8 @@ class BankGuarantee(Document):
@frappe.whitelist()
def get_vouchar_detials(column_list, doctype, docname):
column_list = json.loads(column_list)
for col in column_list:
sanitize_searchfield(col)
return frappe.db.sql(''' select {columns} from `tab{doctype}` where name=%s'''
.format(columns=", ".join(json.loads(column_list)), doctype=doctype), docname, as_dict=1)[0]

View File

@@ -92,10 +92,10 @@ frappe.ui.form.on("Journal Entry", {
multi_currency: function(frm) {
erpnext.journal_entry.toggle_fields_based_on_currency(frm);
},
posting_date: function(frm) {
if(!frm.doc.multi_currency || !frm.doc.posting_date) return;
$.each(frm.doc.accounts || [], function(i, row) {
erpnext.journal_entry.set_exchange_rate(frm, row.doctype, row.name);
})
@@ -234,7 +234,7 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
out.filters.push([jvd.reference_type, "per_billed", "<", 100]);
}
if(jvd.party_type && jvd.party) {
var party_field = "";
if(jvd.reference_type.indexOf("Sales")===0) {
@@ -382,7 +382,7 @@ cur_frm.cscript.voucher_type = function(doc, cdt, cdn) {
});
refresh_field("accounts");
}
if((!(doc.accounts || []).length) || ((doc.accounts || []).length==1 && !doc.accounts[0].account)) {
if(in_list(["Bank Entry", "Cash Entry"], doc.voucher_type)) {
return frappe.call({
@@ -390,7 +390,7 @@ cur_frm.cscript.voucher_type = function(doc, cdt, cdn) {
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_default_bank_cash_account",
args: {
"account_type": (doc.voucher_type=="Bank Entry" ?
"Bank" : (doc.voucher_type=="Cash" ? "Cash" : null)),
"Bank" : (doc.voucher_type=="Cash Entry" ? "Cash" : null)),
"company": doc.company
},
callback: function(r) {
@@ -442,7 +442,7 @@ frappe.ui.form.on("Journal Entry Account", {
account: function(frm, dt, dn) {
erpnext.journal_entry.set_account_balance(frm, dt, dn);
},
debit_in_account_currency: function(frm, cdt, cdn) {
erpnext.journal_entry.set_exchange_rate(frm, cdt, cdn);
},

View File

@@ -2454,7 +2454,7 @@
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "other_charges_calculation",
"fieldtype": "Text",
"fieldtype": "Long Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -4903,7 +4903,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2019-04-22 12:45:49.728359",
"modified": "2020-04-16 19:04:18.599264",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",

View File

@@ -250,7 +250,7 @@ class PurchaseInvoice(BuyingController):
def set_against_expense_account(self):
against_accounts = []
for item in self.get("items"):
if item.expense_account not in against_accounts:
if item.expense_account and (item.expense_account not in against_accounts):
against_accounts.append(item.expense_account)
self.against_expense_account = ",".join(against_accounts)
@@ -750,7 +750,11 @@ class PurchaseInvoice(BuyingController):
)
def make_gle_for_rounding_adjustment(self, gl_entries):
if self.rounding_adjustment:
# if rounding adjustment in small and conversion rate is also small then
# base_rounding_adjustment may become zero due to small precision
# eg: rounding_adjustment = 0.01 and exchange rate = 0.05 and precision of base_rounding_adjustment is 2
# then base_rounding_adjustment becomes zero and error is thrown in GL Entry
if self.rounding_adjustment and self.base_rounding_adjustment:
round_off_account, round_off_cost_center = \
get_round_off_account_and_cost_center(self.company)

View File

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

View File

@@ -2544,7 +2544,7 @@
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "other_charges_calculation",
"fieldtype": "Text",
"fieldtype": "Long Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -5816,7 +5816,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2019-04-22 12:45:41.109345",
"modified": "2020-04-16 19:05:00.498772",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",

View File

@@ -944,7 +944,7 @@ class SalesInvoice(SellingController):
)
def make_gle_for_rounding_adjustment(self, gl_entries):
if flt(self.rounding_adjustment, self.precision("rounding_adjustment")):
if flt(self.rounding_adjustment, self.precision("rounding_adjustment")) and self.base_rounding_adjustment:
round_off_account, round_off_cost_center = \
get_round_off_account_and_cost_center(self.company)
@@ -1039,13 +1039,18 @@ class SalesInvoice(SellingController):
continue
for serial_no in item.serial_no.split("\n"):
sales_invoice, item_code = frappe.db.get_value("Serial No", serial_no,
["sales_invoice", "item_code"])
if sales_invoice and item_code == item.item_code and self.name != sales_invoice:
sales_invoice_company = frappe.db.get_value("Sales Invoice", sales_invoice, "company")
serial_no_details = frappe.db.get_value("Serial No", serial_no,
["sales_invoice", "item_code"], as_dict=1)
if not serial_no_details:
continue
if serial_no_details.sales_invoice and serial_no_details.item_code == item.item_code \
and self.name != serial_no_details.sales_invoice:
sales_invoice_company = frappe.db.get_value("Sales Invoice", serial_no_details.sales_invoice, "company")
if sales_invoice_company == self.company:
frappe.throw(_("Serial Number: {0} is already referenced in Sales Invoice: {1}"
.format(serial_no, sales_invoice)))
.format(serial_no, serial_no_details.sales_invoice)))
def update_project(self):
if self.project:

View File

@@ -59,6 +59,7 @@ class ReceivablePayableReport(object):
def get_data(self):
self.get_gl_entries()
self.get_sales_invoices_or_customers_based_on_sales_person()
self.voucher_balance = OrderedDict()
self.init_voucher_balance() # invoiced, paid, credit_note, outstanding
@@ -102,12 +103,18 @@ class ReceivablePayableReport(object):
def get_invoices(self, gle):
if gle.voucher_type in ('Sales Invoice', 'Purchase Invoice'):
self.invoices.add(gle.voucher_no)
if self.filters.get("sales_person"):
if gle.voucher_no in self.sales_person_records.get("Sales Invoice", []) \
or gle.party in self.sales_person_records.get("Customer", []):
self.invoices.add(gle.voucher_no)
else:
self.invoices.add(gle.voucher_no)
def update_voucher_balance(self, gle):
# get the row where this balance needs to be updated
# if its a payment, it will return the linked invoice or will be considered as advance
row = self.get_voucher_balance(gle)
if not row: return
# gle_balance will be the total "debit - credit" for receivable type reports and
# and vice-versa for payable type reports
gle_balance = self.get_gle_balance(gle)
@@ -128,8 +135,13 @@ class ReceivablePayableReport(object):
row.paid -= gle_balance
def get_voucher_balance(self, gle):
voucher_balance = None
if self.filters.get("sales_person"):
against_voucher = gle.against_voucher or gle.voucher_no
if not (gle.party in self.sales_person_records.get("Customer", []) or \
against_voucher in self.sales_person_records.get("Sales Invoice", [])):
return
voucher_balance = None
if gle.against_voucher:
# find invoice
against_voucher = gle.against_voucher
@@ -511,6 +523,22 @@ class ReceivablePayableReport(object):
order by posting_date, party"""
.format(select_fields, conditions), values, as_dict=True)
def get_sales_invoices_or_customers_based_on_sales_person(self):
if self.filters.get("sales_person"):
lft, rgt = frappe.db.get_value("Sales Person",
self.filters.get("sales_person"), ["lft", "rgt"])
records = frappe.db.sql("""
select distinct parent, parenttype
from `tabSales Team` steam
where parenttype in ('Customer', 'Sales Invoice')
and exists(select name from `tabSales Person` where lft >= %s and rgt <= %s and name = steam.sales_person)
""", (lft, rgt), as_dict=1)
self.sales_person_records = frappe._dict()
for d in records:
self.sales_person_records.setdefault(d.parenttype, set()).add(d.parent)
def prepare_conditions(self):
conditions = [""]
values = [self.party_type, self.filters.report_date]
@@ -561,16 +589,6 @@ class ReceivablePayableReport(object):
conditions.append("party in (select name from tabCustomer where default_sales_partner=%s)")
values.append(self.filters.get("sales_partner"))
if self.filters.get("sales_person"):
lft, rgt = frappe.db.get_value("Sales Person",
self.filters.get("sales_person"), ["lft", "rgt"])
conditions.append("""exists(select name from `tabSales Team` steam where
steam.sales_person in (select name from `tabSales Person` where lft >= {0} and rgt <= {1})
and ((steam.parent = voucher_no and steam.parenttype = voucher_type)
or (steam.parent = against_voucher and steam.parenttype = against_voucher_type)
or (steam.parent = party and steam.parenttype = 'Customer')))""".format(lft, rgt))
def add_supplier_filters(self, conditions, values):
if self.filters.get("supplier_group"):
conditions.append("""party in (select name from tabSupplier

View File

@@ -36,7 +36,7 @@ class AccountsReceivableSummary(ReceivablePayableReport):
self.filters.report_date) or {}
for party, party_dict in iteritems(self.party_total):
if party_dict.outstanding <= 0:
if party_dict.outstanding == 0:
continue
row = frappe._dict()
@@ -135,4 +135,4 @@ class AccountsReceivableSummary(ReceivablePayableReport):
"{range2}-{range3}".format(range2=cint(self.filters["range2"])+ 1, range3=self.filters["range3"]),
"{range3}-{range4}".format(range3=cint(self.filters["range3"])+ 1, range4=self.filters["range4"]),
"{range4}-{above}".format(range4=cint(self.filters["range4"])+ 1, above=_("Above"))]):
self.add_column(label=label, fieldname='range' + str(i+1))
self.add_column(label=label, fieldname='range' + str(i+1))

View File

@@ -4,126 +4,141 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import formatdate, getdate, flt, add_days
from frappe.utils import formatdate, flt, add_days
def execute(filters=None):
filters.day_before_from_date = add_days(filters.from_date, -1)
columns, data = get_columns(filters), get_data(filters)
return columns, data
def get_data(filters):
data = []
asset_categories = get_asset_categories(filters)
assets = get_assets(filters)
asset_costs = get_asset_costs(assets, filters)
asset_depreciations = get_accumulated_depreciations(assets, filters)
for asset_category in asset_categories:
row = frappe._dict()
row.asset_category = asset_category
row.update(asset_costs.get(asset_category))
# row.asset_category = asset_category
row.update(asset_category)
row.cost_as_on_to_date = (flt(row.cost_as_on_from_date) + flt(row.cost_of_new_purchase) -
flt(row.cost_of_sold_asset) - flt(row.cost_of_scrapped_asset))
row.update(next(asset for asset in assets if asset["asset_category"] == asset_category.get("asset_category", "")))
row.accumulated_depreciation_as_on_to_date = (flt(row.accumulated_depreciation_as_on_from_date) +
flt(row.depreciation_amount_during_the_period) - flt(row.depreciation_eliminated))
row.net_asset_value_as_on_from_date = (flt(row.cost_as_on_from_date) -
flt(row.accumulated_depreciation_as_on_from_date))
row.net_asset_value_as_on_to_date = (flt(row.cost_as_on_to_date) -
flt(row.accumulated_depreciation_as_on_to_date))
row.cost_as_on_to_date = (flt(row.cost_as_on_from_date) + flt(row.cost_of_new_purchase)
- flt(row.cost_of_sold_asset) - flt(row.cost_of_scrapped_asset))
row.update(asset_depreciations.get(asset_category))
row.accumulated_depreciation_as_on_to_date = (flt(row.accumulated_depreciation_as_on_from_date) +
flt(row.depreciation_amount_during_the_period) - flt(row.depreciation_eliminated))
row.net_asset_value_as_on_from_date = (flt(row.cost_as_on_from_date) -
flt(row.accumulated_depreciation_as_on_from_date))
row.net_asset_value_as_on_to_date = (flt(row.cost_as_on_to_date) -
flt(row.accumulated_depreciation_as_on_to_date))
data.append(row)
return data
def get_asset_categories(filters):
return frappe.db.sql_list("""
select distinct asset_category from `tabAsset`
where docstatus=1 and company=%s and purchase_date <= %s
""", (filters.company, filters.to_date))
return frappe.db.sql("""
SELECT asset_category,
ifnull(sum(case when purchase_date < %(from_date)s then
case when ifnull(disposal_date, 0) = 0 or disposal_date >= %(from_date)s then
gross_purchase_amount
else
0
end
else
0
end), 0) as cost_as_on_from_date,
ifnull(sum(case when purchase_date >= %(from_date)s then
gross_purchase_amount
else
0
end), 0) as cost_of_new_purchase,
ifnull(sum(case when ifnull(disposal_date, 0) != 0
and disposal_date >= %(from_date)s
and disposal_date <= %(to_date)s then
case when status = "Sold" then
gross_purchase_amount
else
0
end
else
0
end), 0) as cost_of_sold_asset,
ifnull(sum(case when ifnull(disposal_date, 0) != 0
and disposal_date >= %(from_date)s
and disposal_date <= %(to_date)s then
case when status = "Scrapped" then
gross_purchase_amount
else
0
end
else
0
end), 0) as cost_of_scrapped_asset
from `tabAsset`
where docstatus=1 and company=%(company)s and purchase_date <= %(to_date)s
group by asset_category
""", {"to_date": filters.to_date, "from_date": filters.from_date, "company": filters.company}, as_dict=1)
def get_assets(filters):
return frappe.db.sql("""
select name, asset_category, purchase_date, gross_purchase_amount, disposal_date, status
from `tabAsset`
where docstatus=1 and company=%s and purchase_date <= %s""",
(filters.company, filters.to_date), as_dict=1)
def get_asset_costs(assets, filters):
asset_costs = frappe._dict()
for d in assets:
asset_costs.setdefault(d.asset_category, frappe._dict({
"cost_as_on_from_date": 0,
"cost_of_new_purchase": 0,
"cost_of_sold_asset": 0,
"cost_of_scrapped_asset": 0
}))
costs = asset_costs[d.asset_category]
if getdate(d.purchase_date) < getdate(filters.from_date):
if not d.disposal_date or getdate(d.disposal_date) >= getdate(filters.from_date):
costs.cost_as_on_from_date += flt(d.gross_purchase_amount)
else:
costs.cost_of_new_purchase += flt(d.gross_purchase_amount)
if d.disposal_date and getdate(d.disposal_date) >= getdate(filters.from_date) \
and getdate(d.disposal_date) <= getdate(filters.to_date):
if d.status == "Sold":
costs.cost_of_sold_asset += flt(d.gross_purchase_amount)
elif d.status == "Scrapped":
costs.cost_of_scrapped_asset += flt(d.gross_purchase_amount)
return asset_costs
def get_accumulated_depreciations(assets, filters):
asset_depreciations = frappe._dict()
for d in assets:
asset = frappe.get_doc("Asset", d.name)
if d.asset_category in asset_depreciations:
asset_depreciations[d.asset_category]['accumulated_depreciation_as_on_from_date'] += asset.opening_accumulated_depreciation
else:
asset_depreciations.setdefault(d.asset_category, frappe._dict({
"accumulated_depreciation_as_on_from_date": asset.opening_accumulated_depreciation,
"depreciation_amount_during_the_period": 0,
"depreciation_eliminated_during_the_period": 0
}))
SELECT results.asset_category,
sum(results.accumulated_depreciation_as_on_from_date) as accumulated_depreciation_as_on_from_date,
sum(results.depreciation_eliminated_during_the_period) as depreciation_eliminated_during_the_period,
sum(results.depreciation_amount_during_the_period) as depreciation_amount_during_the_period
from (SELECT a.asset_category,
ifnull(sum(a.opening_accumulated_depreciation +
case when ds.schedule_date < %(from_date)s and
(ifnull(a.disposal_date, 0) = 0 or a.disposal_date >= %(from_date)s) then
ds.depreciation_amount
else
0
end), 0) as accumulated_depreciation_as_on_from_date,
ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 and a.disposal_date >= %(from_date)s
and a.disposal_date <= %(to_date)s and ds.schedule_date <= a.disposal_date then
ds.depreciation_amount
else
0
end), 0) as depreciation_eliminated_during_the_period,
depr = asset_depreciations[d.asset_category]
ifnull(sum(case when ds.schedule_date >= %(from_date)s and ds.schedule_date <= %(to_date)s
and (ifnull(a.disposal_date, 0) = 0 or ds.schedule_date <= a.disposal_date) then
ds.depreciation_amount
else
0
end), 0) as depreciation_amount_during_the_period
from `tabAsset` a, `tabDepreciation Schedule` ds
where a.docstatus=1 and a.company=%(company)s and a.purchase_date <= %(to_date)s and a.name = ds.parent
group by a.asset_category
union
SELECT a.asset_category,
ifnull(sum(case when ifnull(a.disposal_date, 0) != 0
and (a.disposal_date < %(from_date)s or a.disposal_date > %(to_date)s) then
0
else
a.opening_accumulated_depreciation
end), 0) as accumulated_depreciation_as_on_from_date,
ifnull(sum(case when a.disposal_date >= %(from_date)s and a.disposal_date <= %(to_date)s then
a.opening_accumulated_depreciation
else
0
end), 0) as depreciation_eliminated_during_the_period,
0 as depreciation_amount_during_the_period
from `tabAsset` a
where a.docstatus=1 and a.company=%(company)s and a.purchase_date <= %(to_date)s
and not exists(select * from `tabDepreciation Schedule` ds where a.name = ds.parent)
group by a.asset_category) as results
group by results.asset_category
""", {"to_date": filters.to_date, "from_date": filters.from_date, "company": filters.company}, as_dict=1)
if not asset.schedules: # if no schedule,
if asset.disposal_date:
# and disposal is NOT within the period, then opening accumulated depreciation not included
if getdate(asset.disposal_date) < getdate(filters.from_date) or getdate(asset.disposal_date) > getdate(filters.to_date):
asset_depreciations[d.asset_category]['accumulated_depreciation_as_on_from_date'] = 0
# if no schedule, and disposal is within period, accumulated dep is the amount eliminated
if getdate(asset.disposal_date) >= getdate(filters.from_date) and getdate(asset.disposal_date) <= getdate(filters.to_date):
depr.depreciation_eliminated_during_the_period += asset.opening_accumulated_depreciation
for schedule in asset.get("schedules"):
if getdate(schedule.schedule_date) < getdate(filters.from_date):
if not asset.disposal_date or getdate(asset.disposal_date) >= getdate(filters.from_date):
depr.accumulated_depreciation_as_on_from_date += flt(schedule.depreciation_amount)
elif getdate(schedule.schedule_date) <= getdate(filters.to_date):
if not asset.disposal_date:
depr.depreciation_amount_during_the_period += flt(schedule.depreciation_amount)
else:
if getdate(schedule.schedule_date) <= getdate(asset.disposal_date):
depr.depreciation_amount_during_the_period += flt(schedule.depreciation_amount)
if asset.disposal_date and getdate(asset.disposal_date) >= getdate(filters.from_date) and getdate(asset.disposal_date) <= getdate(filters.to_date):
if getdate(schedule.schedule_date) <= getdate(asset.disposal_date):
depr.depreciation_eliminated_during_the_period += flt(schedule.depreciation_amount)
return asset_depreciations
def get_columns(filters):
return [
{

View File

@@ -286,14 +286,14 @@ class PartyLedgerSummaryReport(object):
if parties and accounts:
if len(parties) == 1:
party = parties.keys()[0]
party = list(parties.keys())[0]
for account, amount in iteritems(accounts):
self.party_adjustment_accounts.add(account)
self.party_adjustment_details.setdefault(party, {})
self.party_adjustment_details[party].setdefault(account, 0)
self.party_adjustment_details[party][account] += amount
elif len(accounts) == 1 and not has_irrelevant_entry:
account = accounts.keys()[0]
account = list(accounts.keys())[0]
self.party_adjustment_accounts.add(account)
for party, amount in iteritems(parties):
self.party_adjustment_details.setdefault(party, {})

View File

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

View File

@@ -2176,7 +2176,7 @@
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "other_charges_calculation",
"fieldtype": "Text",
"fieldtype": "Long Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -3948,7 +3948,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2019-06-24 20:55:03.466766",
"modified": "2020-04-16 18:54:54.840653",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",

View File

@@ -1395,7 +1395,7 @@
"collapsible": 0,
"columns": 0,
"fieldname": "other_charges_calculation",
"fieldtype": "Text",
"fieldtype": "Long Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -2845,7 +2845,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2019-01-07 16:52:01.505553",
"modified": "2020-04-16 19:05:41.924303",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Quotation",

View File

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

View File

@@ -375,9 +375,10 @@ class AccountsController(TransactionBase):
return gl_dict
def validate_qty_is_not_zero(self):
for item in self.items:
if not item.qty:
frappe.throw(_("Item quantity can not be zero"))
if self.doctype != "Purchase Receipt":
for item in self.items:
if not item.qty:
frappe.throw(_("Item quantity can not be zero"))
def validate_account_currency(self, account, account_currency=None):
valid_currency = [self.company_currency]

View File

@@ -311,6 +311,7 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
and sle.item_code = %(item_code)s
and sle.warehouse = %(warehouse)s
and (sle.batch_no like %(txt)s
or batch.expiry_date like %(txt)s
or batch.manufacturing_date like %(txt)s)
and batch.docstatus < 2
{cond}
@@ -329,6 +330,7 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
where batch.disabled = 0
and item = %(item_code)s
and (name like %(txt)s
or expiry_date like %(txt)s
or manufacturing_date like %(txt)s)
and docstatus < 2
{0}

View File

@@ -54,6 +54,7 @@ class StockController(AccountsController):
gl_list = []
warehouse_with_no_account = []
precision = frappe.get_precision('GL Entry', 'debit_in_account_currency')
for item_row in voucher_details:
sle_list = sle_map.get(item_row.name)
if sle_list:
@@ -79,7 +80,7 @@ class StockController(AccountsController):
"against": item_row.expense_account,
"cost_center": item_row.cost_center,
"remarks": self.get("remarks") or "Accounting Entry for Stock",
"debit": flt(sle.stock_value_difference, 2),
"debit": flt(sle.stock_value_difference, precision),
"is_opening": item_row.get("is_opening") or self.get("is_opening") or "No",
}, warehouse_account[sle.warehouse]["account_currency"]))
@@ -89,7 +90,7 @@ class StockController(AccountsController):
"against": warehouse_account[sle.warehouse]["account"],
"cost_center": item_row.cost_center,
"remarks": self.get("remarks") or "Accounting Entry for Stock",
"credit": flt(sle.stock_value_difference, 2),
"credit": flt(sle.stock_value_difference, precision),
"project": item_row.get("project") or self.get("project"),
"is_opening": item_row.get("is_opening") or self.get("is_opening") or "No"
}))

View File

@@ -305,11 +305,19 @@ class calculate_taxes_and_totals(object):
last_tax = self.doc.get("taxes")[-1]
non_inclusive_tax_amount = sum([flt(d.tax_amount_after_discount_amount)
for d in self.doc.get("taxes") if not d.included_in_print_rate])
diff = self.doc.total + non_inclusive_tax_amount \
- flt(last_tax.total, last_tax.precision("total"))
# If discount amount applied, deduct the discount amount
# because self.doc.total is always without discount, but last_tax.total is after discount
if self.discount_amount_applied and self.doc.discount_amount:
diff -= flt(self.doc.discount_amount)
diff = flt(diff, self.doc.precision("rounding_adjustment"))
if diff and abs(diff) <= (5.0 / 10**last_tax.precision("tax_amount")):
self.doc.rounding_adjustment = flt(flt(self.doc.rounding_adjustment) +
flt(diff), self.doc.precision("rounding_adjustment"))
self.doc.rounding_adjustment = diff
def calculate_totals(self):
self.doc.grand_total = flt(self.doc.get("taxes")[-1].total) + flt(self.doc.rounding_adjustment) \

View File

@@ -234,14 +234,17 @@ def get_order_taxes(shopify_order, shopify_settings):
return taxes
def update_taxes_with_shipping_lines(taxes, shipping_lines, shopify_settings):
"""Shipping lines represents the shipping details,
each such shipping detail consists of a list of tax_lines"""
for shipping_charge in shipping_lines:
taxes.append({
"charge_type": _("Actual"),
"account_head": get_tax_account_head(shipping_charge),
"description": shipping_charge["title"],
"tax_amount": shipping_charge["price"],
"cost_center": shopify_settings.cost_center
})
for tax in shipping_charge.get("tax_lines"):
taxes.append({
"charge_type": _("Actual"),
"account_head": get_tax_account_head(tax),
"description": tax["title"],
"tax_amount": tax["price"],
"cost_center": shopify_settings.cost_center
})
return taxes

View File

@@ -114,10 +114,11 @@ def add_account_subtype(account_subtype):
@frappe.whitelist()
def sync_transactions(bank, bank_account):
last_sync_date = frappe.db.get_value("Bank Account", bank_account, "last_integration_date")
if last_sync_date:
start_date = formatdate(last_sync_date, "YYYY-MM-dd")
'''Sync transactions based on the last integration date as the start date, after sync is completed
add the transaction date of the oldest transaction as the last integration date'''
last_transaction_date = frappe.db.get_value("Bank Account", bank_account, "last_integration_date")
if last_transaction_date:
start_date = formatdate(last_transaction_date, "YYYY-MM-dd")
else:
start_date = formatdate(add_months(today(), -12), "YYYY-MM-dd")
end_date = formatdate(today(), "YYYY-MM-dd")
@@ -125,13 +126,17 @@ def sync_transactions(bank, bank_account):
try:
transactions = get_transactions(bank=bank, bank_account=bank_account, start_date=start_date, end_date=end_date)
result = []
if transactions:
for transaction in transactions:
result.append(new_bank_transaction(transaction))
for transaction in reversed(transactions):
result += new_bank_transaction(transaction)
frappe.db.set_value("Bank Account", bank_account, "last_integration_date", getdate(end_date))
if result:
last_transaction_date = frappe.db.get_value('Bank Transaction', result.pop(), 'date')
frappe.logger().info("Plaid added {} new Bank Transactions from '{}' between {} and {}".format(
len(result), bank_account, start_date, end_date))
frappe.db.set_value("Bank Account", bank_account, "last_integration_date", last_transaction_date)
return result
except Exception:
frappe.log_error(frappe.get_traceback(), _("Plaid transactions sync error"))

View File

@@ -8,6 +8,7 @@ import json
from frappe import _
from frappe.model.document import Document
from frappe.utils import get_request_session
from requests.exceptions import HTTPError
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
from erpnext.erpnext_integrations.utils import get_webhook_address
from erpnext.erpnext_integrations.doctype.shopify_log.shopify_log import make_shopify_log
@@ -39,24 +40,28 @@ class ShopifySettings(Document):
def register_webhooks(self):
webhooks = ["orders/create", "orders/paid", "orders/fulfilled"]
url = get_shopify_url('admin/webhooks.json', self)
url = get_shopify_url('admin/api/2020-04/webhooks.json', self)
created_webhooks = [d.method for d in self.webhooks]
for method in webhooks:
if method in created_webhooks:
continue
session = get_request_session()
try:
d = session.post(url, data=json.dumps({
res = session.post(url, data=json.dumps({
"webhook": {
"topic": method,
"address": get_webhook_address(connector_name='shopify_connection', method='store_request_data'),
"format": "json"
}
}), headers=get_header(self))
d.raise_for_status()
self.update_webhook_table(method, d.json())
res.raise_for_status()
self.update_webhook_table(method, res.json())
except HTTPError as e:
error_message = res.json().get('errors', e)
make_shopify_log(status="Warning", exception=error_message, rollback=True)
except Exception as e:
make_shopify_log(status="Warning", message=e.message, exception=False)
@@ -65,13 +70,18 @@ class ShopifySettings(Document):
deleted_webhooks = []
for d in self.webhooks:
url = get_shopify_url('admin/webhooks/{0}.json'.format(d.webhook_id), self)
url = get_shopify_url('admin/api/2020-04/webhooks/{0}.json'.format(d.webhook_id), self)
try:
res = session.delete(url, headers=get_header(self))
res.raise_for_status()
deleted_webhooks.append(d)
except HTTPError as e:
error_message = res.json().get('errors', e)
make_shopify_log(status="Warning", exception=error_message, rollback=True)
except Exception as e:
frappe.log_error(message=frappe.get_traceback(), title=e.message[:140])
frappe.log_error(message=e, title='Shopify Webhooks Issue')
for d in deleted_webhooks:
self.remove(d)
@@ -144,4 +154,3 @@ def setup_custom_fields():
}
create_custom_fields(custom_fields)

View File

@@ -7,7 +7,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/products/{0}.json".format(item.get("product_id")), shopify_settings)
url = get_shopify_url("admin/api/2020-04/products/{0}.json".format(item.get("product_id")), shopify_settings)
session = get_request_session()
try:

View File

@@ -386,5 +386,5 @@ def get_procedure_prescribed(patient):
return frappe.db.sql("""select pp.name, pp.procedure, pp.parent, ct.practitioner,
ct.encounter_date, pp.practitioner, pp.date, pp.department
from `tabPatient Encounter` ct, `tabProcedure Prescription` pp
where ct.patient='{0}' and pp.parent=ct.name and pp.appointment_booked=0
order by ct.creation desc""".format(patient))
where ct.patient=%(patient)s and pp.parent=ct.name and pp.appointment_booked=0
order by ct.creation desc""", {"patient": patient})

View File

@@ -48,12 +48,17 @@ def get_abbreviated_name(name, company):
@frappe.whitelist()
def get_children(doctype, parent=None, company=None, is_root=False):
condition = ''
var_dict = {
"name": get_root_of("Department"),
"parent": parent,
"company": company,
}
if company == parent:
condition = "name='{0}'".format(get_root_of("Department"))
condition = "name=%(name)s"
elif company:
condition = "parent_department='{0}' and company='{1}'".format(parent, company)
condition = "parent_department=%(parent)s and company=%(company)s"
else:
condition = "parent_department = '{0}'".format(parent)
condition = "parent_department = %(parent)s"
return frappe.db.sql("""
select
@@ -62,7 +67,7 @@ def get_children(doctype, parent=None, company=None, is_root=False):
from `tab{doctype}`
where
{condition}
order by name""".format(doctype=doctype, condition=condition), as_dict=1)
order by name""".format(doctype=doctype, condition=condition), var_dict, as_dict=1)
@frappe.whitelist()
def add_node():

View File

@@ -7,6 +7,14 @@ frappe.ui.form.on('Employee Onboarding', {
frm.add_fetch("employee_onboarding_template", "department", "department");
frm.add_fetch("employee_onboarding_template", "designation", "designation");
frm.add_fetch("employee_onboarding_template", "employee_grade", "employee_grade");
frm.set_query('job_offer', function () {
return {
filters: {
'job_applicant': frm.doc.job_applicant
}
};
});
},
refresh: function(frm) {

View File

@@ -371,6 +371,11 @@ frappe.ui.form.on("Work Order", {
}
});
}
},
additional_operating_cost: function(frm) {
erpnext.work_order.calculate_cost(frm.doc);
erpnext.work_order.calculate_total_cost(frm);
}
});
@@ -507,8 +512,7 @@ erpnext.work_order = {
},
calculate_total_cost: function(frm) {
var variable_cost = frm.doc.actual_operating_cost ?
flt(frm.doc.actual_operating_cost) : flt(frm.doc.planned_operating_cost)
let variable_cost = flt(frm.doc.actual_operating_cost) || flt(frm.doc.planned_operating_cost);
frm.set_value("total_operating_cost", (flt(frm.doc.additional_operating_cost) + variable_cost))
},

View File

@@ -496,6 +496,7 @@ erpnext.patches.v10_0.rename_offer_letter_to_job_offer
execute:frappe.delete_doc('DocType', 'Production Planning Tool', ignore_missing=True)
erpnext.patches.v10_0.migrate_daily_work_summary_settings_to_daily_work_summary_group # 24-12-2018
erpnext.patches.v10_0.add_default_cash_flow_mappers
erpnext.patches.v11_0.rename_duplicate_item_code_values
erpnext.patches.v11_0.make_quality_inspection_template
erpnext.patches.v10_0.update_status_for_multiple_source_in_po
erpnext.patches.v10_0.set_auto_created_serial_no_in_stock_entry

View File

@@ -0,0 +1,8 @@
import frappe
def execute():
items = []
items = frappe.db.sql("""select item_code from `tabItem` group by item_code having count(*) > 1""", as_dict=True)
if items:
for item in items:
frappe.db.sql("""update `tabItem` set item_code=name where item_code = %s""", (item.item_code))

View File

@@ -1,9 +1,10 @@
from __future__ import unicode_literals
from frappe import _
import frappe
def execute():
hr_settings = frappe.get_single("HR Settings")
hr_settings.leave_approval_notification_template = "Leave Approval Notification"
hr_settings.leave_status_notification_template = "Leave Status Notification"
hr_settings.save()
hr_settings.leave_approval_notification_template = _("Leave Approval Notification")
hr_settings.leave_status_notification_template = _("Leave Status Notification")
hr_settings.save()

View File

@@ -47,8 +47,8 @@ class Task(NestedSet):
def validate_status(self):
if self.status!=self.get_db_value("status") and self.status == "Closed":
for d in self.depends_on:
if frappe.db.get_value("Task", d.task, "status") != "Closed":
frappe.throw(_("Cannot close task as its dependant task {0} is not closed.").format(d.task))
if frappe.db.get_value("Task", d.task, "status") not in ("Closed", "Cancelled"):
frappe.throw(_("Cannot close task as its dependant task {0} is not closed/cancelled.").format(d.task))
from frappe.desk.form.assign_to import clear
clear(self.doctype, self.name)
@@ -199,10 +199,10 @@ def set_multiple_status(names, status):
task.save()
def set_tasks_as_overdue():
tasks = frappe.get_all("Task", filters={'status':['not in',['Cancelled', 'Closed']]})
tasks = frappe.get_all("Task", filters={"status": ["not in", ["Cancelled", "Closed"]]}, fields=["name", "status", "review_date"])
for task in tasks:
if frappe.db.get_value("Task", task.name, "status") in 'Pending Review':
if getdate(frappe.db.get_value("Task", task.name, "review_date")) < getdate(today()):
if task.status == "Pending Review":
if getdate(task.review_date) > getdate(today()):
continue
frappe.get_doc("Task", task.name).update_status()

View File

@@ -191,6 +191,9 @@ class Timesheet(Document):
}, as_dict=True)
# check internal overlap
for time_log in self.time_logs:
if not (time_log.from_time and time_log.to_time
and args.from_time and args.to_time): continue
if (fieldname != 'workstation' or args.get(fieldname) == time_log.get(fieldname)) and \
args.idx != time_log.idx and ((args.from_time > time_log.from_time and args.from_time < time_log.to_time) or
(args.to_time > time_log.from_time and args.to_time < time_log.to_time) or

View File

@@ -387,9 +387,14 @@ erpnext.taxes_and_totals = erpnext.payments.extend({
var diff = me.frm.doc.total + non_inclusive_tax_amount
- flt(last_tax.total, precision("grand_total"));
if(me.discount_amount_applied && me.frm.doc.discount_amount) {
diff -= flt(me.frm.doc.discount_amount);
}
diff = flt(diff, precision("rounding_adjustment"));
if ( diff && Math.abs(diff) <= (5.0 / Math.pow(10, precision("tax_amount", last_tax))) ) {
this.frm.doc.rounding_adjustment = flt(flt(this.frm.doc.rounding_adjustment) + diff,
precision("rounding_adjustment"));
me.frm.doc.rounding_adjustment = diff;
}
}
}

View File

@@ -853,15 +853,19 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
},
conversion_factor: function(doc, cdt, cdn, dont_fetch_price_list_rate) {
if(doc.doctype != 'Material Request' && frappe.meta.get_docfield(cdt, "stock_qty", cdn)) {
if(frappe.meta.get_docfield(cdt, "stock_qty", cdn)) {
var item = frappe.get_doc(cdt, cdn);
frappe.model.round_floats_in(item, ["qty", "conversion_factor"]);
item.stock_qty = flt(item.qty * item.conversion_factor, precision("stock_qty", item));
item.total_weight = flt(item.stock_qty * item.weight_per_unit);
refresh_field("stock_qty", item.name, item.parentfield);
refresh_field("total_weight", item.name, item.parentfield);
this.toggle_conversion_factor(item);
this.calculate_net_weight();
if(doc.doctype != "Material Request") {
item.total_weight = flt(item.stock_qty * item.weight_per_unit);
refresh_field("total_weight", item.name, item.parentfield);
this.calculate_net_weight();
}
if (!dont_fetch_price_list_rate &&
frappe.meta.has_field(doc.doctype, "price_list_currency")) {
this.apply_price_list(item, true);

View File

@@ -379,7 +379,7 @@ def get_gstins_for_company(company):
`tabDynamic Link`.parent = `tabAddress`.name and
`tabDynamic Link`.parenttype = 'Address' and
`tabDynamic Link`.link_doctype = 'Company' and
`tabDynamic Link`.link_name = '{0}'""".format(company))
`tabDynamic Link`.link_name = %(company)s""", {"company": company})
return company_gstins
def get_address_details(data, doc, company_address, billing_address):

View File

@@ -1687,7 +1687,7 @@
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "other_charges_calculation",
"fieldtype": "Text",
"fieldtype": "Long Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -3224,7 +3224,7 @@
"istable": 0,
"max_attachments": 1,
"menu_index": 0,
"modified": "2019-06-25 15:31:04.724730",
"modified": "2020-04-16 19:05:32.197858",
"modified_by": "Administrator",
"module": "Selling",
"name": "Quotation",

View File

@@ -1981,7 +1981,7 @@
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "other_charges_calculation",
"fieldtype": "Text",
"fieldtype": "Long Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -4204,7 +4204,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2019-04-05 03:44:46.037178",
"modified": "2020-04-16 19:05:14.867404",
"modified_by": "Administrator",
"module": "Selling",
"name": "Sales Order",

View File

@@ -622,7 +622,6 @@ def make_sales_invoice(source_name, target_doc=None, ignore_permissions=False):
target.set_advances()
def set_missing_values(source, target):
target.is_pos = 0
target.ignore_pricing_rule = 1
target.flags.ignore_permissions = True
target.run_method("set_missing_values")

View File

@@ -7,7 +7,7 @@ from frappe.utils import flt
def execute(filters=None):
if not filters: filters = {}
columns = get_columns()
iwq_map = get_item_warehouse_quantity_map()
item_map = get_item_details()
@@ -15,22 +15,23 @@ def execute(filters=None):
for sbom, warehouse in iwq_map.items():
total = 0
total_qty = 0
for wh, item_qty in warehouse.items():
total += 1
row = [sbom, item_map.get(sbom).item_name, item_map.get(sbom).description,
item_map.get(sbom).stock_uom, wh]
available_qty = item_qty
total_qty += flt(available_qty)
row += [available_qty]
if available_qty:
data.append(row)
if (total == len(warehouse)):
row = ["", "", "Total", "", "", total_qty]
if item_map.get(sbom):
row = [sbom, item_map.get(sbom).item_name, item_map.get(sbom).description,
item_map.get(sbom).stock_uom, wh]
available_qty = item_qty
total_qty += flt(available_qty)
row += [available_qty]
if available_qty:
data.append(row)
if (total == len(warehouse)):
row = ["", "", "Total", "", "", total_qty]
data.append(row)
return columns, data
def get_columns():
columns = ["Item Code:Link/Item:100", "Item Name::100", "Description::120", \
"UOM:Link/UOM:80", "Warehouse:Link/Warehouse:100", "Quantity::100"]

View File

@@ -284,7 +284,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
child: item,
args: {
"batch_no": item.batch_no,
"stock_qty": item.stock_qty,
"stock_qty": item.stock_qty || item.qty, //if stock_qty field is not available, fetch qty (in case of Packed Items table)
"warehouse": item.warehouse,
"item_code": item.item_code,
"has_serial_no": has_serial_no

View File

@@ -109,7 +109,7 @@ def get_product_list_for_group(product_group=None, start=0, limit=10, search=Non
or I.name like %(search)s)"""
search = "%" + cstr(search) + "%"
query += """order by I.weightage desc, in_stock desc, I.modified desc limit %s, %s""" % (start, limit)
query += """order by I.weightage desc, in_stock desc, I.modified desc limit %s, %s""" % (cint(start), cint(limit))
data = frappe.db.sql(query, {"product_group": product_group,"search": search, "today": nowdate()}, as_dict=1)
data = adjust_qty_for_expired_items(data)

View File

@@ -141,6 +141,6 @@ def insert_record(records):
raise
def welcome_email():
site_name = get_default_company()
title = _("Welcome to {0}".format(site_name))
return title
site_name = get_default_company() or "ERPNext"
title = _("Welcome to {0}").format(site_name)
return title

View File

@@ -66,6 +66,7 @@ def place_order():
from erpnext.selling.doctype.quotation.quotation import _make_sales_order
sales_order = frappe.get_doc(_make_sales_order(quotation.name, ignore_permissions=True))
sales_order.payment_schedule = []
if not cart_settings.allow_items_not_in_stock:
for item in sales_order.get("items"):

View File

@@ -48,7 +48,7 @@ def get_product_info_for_website(item_code):
def set_product_info_for_website(item):
"""set product price uom for website"""
product_info = get_product_info_for_website(item.item_code)
product_info = get_product_info_for_website(item.item_code).get("product_info")
if product_info:
item.update(product_info)

View File

@@ -2156,7 +2156,7 @@
"collapsible": 0,
"columns": 0,
"fieldname": "other_charges_calculation",
"fieldtype": "Text",
"fieldtype": "Long Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -4296,7 +4296,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2019-01-07 16:51:52.357859",
"modified": "2020-04-16 19:05:56.439204",
"modified_by": "Administrator",
"module": "Stock",
"name": "Delivery Note",

View File

@@ -400,7 +400,6 @@ def make_sales_invoice(source_name, target_doc=None):
invoiced_qty_map = get_invoiced_qty_map(source_name)
def set_missing_values(source, target):
target.is_pos = 0
target.ignore_pricing_rule = 1
target.run_method("set_missing_values")
target.run_method("set_po_nos")

View File

@@ -518,7 +518,7 @@ class Item(WebsiteGenerator):
"""select parent from `tabItem Barcode` where barcode = %s and parent != %s""", (item_barcode.barcode, self.name))
if duplicate:
frappe.throw(_("Barcode {0} already used in Item {1}").format(
item_barcode.barcode, duplicate[0][0]), frappe.DuplicateEntryError)
item_barcode.barcode, duplicate[0][0]))
item_barcode.barcode_type = "" if item_barcode.barcode_type not in options else item_barcode.barcode_type
if item_barcode.barcode_type and item_barcode.barcode_type.upper() in ('EAN', 'UPC-A', 'EAN-13', 'EAN-8'):

View File

@@ -124,7 +124,7 @@ class LandedCostVoucher(Document):
# update stock & gl entries for submit state of PR
doc.docstatus = 1
doc.update_stock_ledger(via_landed_cost_voucher=True)
doc.update_stock_ledger(allow_negative_stock=True, via_landed_cost_voucher=True)
doc.make_gl_entries()
def update_rate_in_serial_no(self, receipt_document):

View File

@@ -217,7 +217,19 @@ frappe.ui.form.on('Material Request', {
make_purchase_order: function(frm) {
frappe.prompt(
{fieldname:'default_supplier', label: __('For Default Supplier (optional)'), fieldtype: 'Link', options: 'Supplier'},
{
label: __('For Default Supplier (optional)'),
fieldname:'default_supplier',
fieldtype: 'Link',
options: 'Supplier',
description: __('Select a Supplier from the Default Supplier List of the items below.'),
get_query: () => {
return {
query: "erpnext.stock.doctype.material_request.material_request.get_default_supplier_query",
filters: {'doc': frm.doc.name}
}
}
},
(values) => {
frappe.model.open_mapped_doc({
method: "erpnext.stock.doctype.material_request.material_request.make_purchase_order",
@@ -225,7 +237,8 @@ frappe.ui.form.on('Material Request', {
args: { default_supplier: values.default_supplier },
run_link_triggers: true
});
}
},
__('Enter Supplier')
)
},

View File

@@ -371,6 +371,18 @@ def get_material_requests_based_on_supplier(supplier):
material_requests = []
return material_requests, supplier_items
def get_default_supplier_query(doctype, txt, searchfield, start, page_len, filters):
doc = frappe.get_doc("Material Request", filters.get("doc"))
item_list = []
for d in doc.items:
item_list.append(d.item_code)
return frappe.db.sql("""select default_supplier
from `tabItem Default`
where parent in ({0}) and
default_supplier IS NOT NULL
""".format(', '.join(['%s']*len(item_list))),tuple(item_list))
@frappe.whitelist()
def make_supplier_quotation(source_name, target_doc=None):
def postprocess(source, target_doc):

View File

@@ -1,5 +1,7 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
@@ -11,10 +13,13 @@
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "parent_item",
"fieldtype": "Link",
"hidden": 0,
@@ -39,13 +44,17 @@
"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_if_empty": 0,
"fieldname": "item_code",
"fieldtype": "Link",
"hidden": 0,
@@ -70,13 +79,17 @@
"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_if_empty": 0,
"fieldname": "item_name",
"fieldtype": "Data",
"hidden": 0,
@@ -100,13 +113,17 @@
"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_if_empty": 0,
"fieldname": "column_break_5",
"fieldtype": "Column Break",
"hidden": 0,
@@ -128,13 +145,17 @@
"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_if_empty": 0,
"fieldname": "description",
"fieldtype": "Text Editor",
"hidden": 0,
@@ -159,14 +180,18 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"width": "300px"
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_6",
"fieldtype": "Section Break",
"hidden": 0,
@@ -188,13 +213,17 @@
"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_if_empty": 0,
"fieldname": "warehouse",
"fieldtype": "Link",
"hidden": 0,
@@ -219,13 +248,17 @@
"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_if_empty": 0,
"fieldname": "target_warehouse",
"fieldtype": "Link",
"hidden": 0,
@@ -249,13 +282,17 @@
"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_if_empty": 0,
"fieldname": "column_break_9",
"fieldtype": "Column Break",
"hidden": 0,
@@ -277,13 +314,17 @@
"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_if_empty": 0,
"fieldname": "qty",
"fieldtype": "Float",
"hidden": 0,
@@ -307,13 +348,17 @@
"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_if_empty": 0,
"fieldname": "section_break_9",
"fieldtype": "Section Break",
"hidden": 0,
@@ -335,13 +380,17 @@
"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_if_empty": 0,
"fieldname": "serial_no",
"fieldtype": "Text",
"hidden": 0,
@@ -363,13 +412,17 @@
"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_if_empty": 0,
"fieldname": "column_break_11",
"fieldtype": "Column Break",
"hidden": 0,
@@ -391,13 +444,17 @@
"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_if_empty": 0,
"fieldname": "batch_no",
"fieldtype": "Link",
"hidden": 0,
@@ -420,13 +477,51 @@
"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,
"depends_on": "batch_no",
"fetch_if_empty": 0,
"fieldname": "actual_batch_qty",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Actual Batch Quantity",
"length": 0,
"no_copy": 1,
"permlevel": 0,
"precision": "",
"print_hide": 1,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_13",
"fieldtype": "Section Break",
"hidden": 0,
@@ -448,13 +543,17 @@
"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,
"fetch_if_empty": 0,
"fieldname": "actual_qty",
"fieldtype": "Float",
"hidden": 0,
@@ -478,13 +577,17 @@
"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,
"fetch_if_empty": 0,
"fieldname": "projected_qty",
"fieldtype": "Float",
"hidden": 0,
@@ -508,13 +611,17 @@
"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_if_empty": 0,
"fieldname": "column_break_16",
"fieldtype": "Column Break",
"hidden": 0,
@@ -536,13 +643,17 @@
"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_if_empty": 0,
"fieldname": "uom",
"fieldtype": "Link",
"hidden": 0,
@@ -567,13 +678,17 @@
"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,
"fetch_if_empty": 0,
"fieldname": "page_break",
"fieldtype": "Check",
"hidden": 0,
@@ -597,13 +712,17 @@
"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_if_empty": 0,
"fieldname": "prevdoc_doctype",
"fieldtype": "Data",
"hidden": 1,
@@ -627,13 +746,17 @@
"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_if_empty": 0,
"fieldname": "parent_detail_docname",
"fieldtype": "Data",
"hidden": 1,
@@ -657,20 +780,21 @@
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 1,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2017-02-20 13:27:37.569945",
"modified": "2019-11-27 11:18:18.598759",
"modified_by": "Administrator",
"module": "Stock",
"name": "Packed Item",
@@ -681,5 +805,6 @@
"read_only_onload": 0,
"show_name_in_global_search": 0,
"track_changes": 1,
"track_seen": 0
"track_seen": 0,
"track_views": 0
}

View File

@@ -65,7 +65,7 @@ def update_packing_list_item(doc, packing_item_code, qty, main_item_row, descrip
pi.actual_qty = flt(bin.get("actual_qty"))
pi.projected_qty = flt(bin.get("projected_qty"))
if old_packed_items_map:
if old_packed_items_map and old_packed_items_map.get((packing_item_code, main_item_row.item_code)):
pi.batch_no = old_packed_items_map.get((packing_item_code, main_item_row.item_code))[0].batch_no
pi.serial_no = old_packed_items_map.get((packing_item_code, main_item_row.item_code))[0].serial_no
pi.warehouse = old_packed_items_map.get((packing_item_code, main_item_row.item_code))[0].warehouse

View File

@@ -1945,7 +1945,7 @@
"collapsible": 0,
"columns": 0,
"fieldname": "other_charges_calculation",
"fieldtype": "Text",
"fieldtype": "Long Text",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -3708,7 +3708,7 @@
"istable": 0,
"max_attachments": 0,
"menu_index": 0,
"modified": "2018-11-02 19:59:01.423485",
"modified": "2020-04-16 19:06:51.546358",
"modified_by": "Administrator",
"module": "Stock",
"name": "Purchase Receipt",

View File

@@ -348,7 +348,7 @@ class StockEntry(StockController):
elif d.t_warehouse and not d.basic_rate:
d.basic_rate = get_valuation_rate(d.item_code, d.t_warehouse,
self.doctype, d.name, d.allow_zero_valuation_rate,
currency=erpnext.get_company_currency(self.company))
currency=erpnext.get_company_currency(self.company), company=self.company)
def set_actual_qty(self):
allow_negative_stock = cint(frappe.db.get_value("Stock Settings", None, "allow_negative_stock"))

View File

@@ -3,6 +3,15 @@
frappe.ui.form.on('Stock Settings', {
refresh: function(frm) {
let filters = function() {
return {
filters : {
is_group : 0
}
};
};
frm.set_query("default_warehouse", filters);
frm.set_query("sample_retention_warehouse", filters);
}
});

View File

@@ -30,9 +30,17 @@ class StockSettings(Document):
frappe.make_property_setter({'fieldname': name, 'property': 'hidden',
'value': 0 if self.show_barcode_field else 1})
self.validate_warehouses()
self.cant_change_valuation_method()
self.validate_clean_description_html()
def validate_warehouses(self):
warehouse_fields = ["default_warehouse", "sample_retention_warehouse"]
for field in warehouse_fields:
if frappe.db.get_value("Warehouse", self.get(field), "is_group"):
frappe.throw(_("Group Warehouses cannot be used in transactions. Please change the value of {0}") \
.format(frappe.bold(self.meta.get_field(field).label)), title =_("Incorrect Warehouse"))
def cant_change_valuation_method(self):
db_valuation_method = frappe.db.get_single_value("Stock Settings", "valuation_method")

View File

@@ -233,7 +233,7 @@ def get_item_details(items, sle, filters):
`tabItem` item
{cf_join}
where
item.name in ({item_codes}) and ifnull(item.disabled, 0) = 0
item.name in ({item_codes})
""".format(cf_field=cf_field, cf_join=cf_join, item_codes=item_codes), as_dict=1)
for item in res:
@@ -261,7 +261,7 @@ def validate_filters(filters):
if not (filters.get("item_code") or filters.get("warehouse")):
sle_count = flt(frappe.db.sql("""select count(name) from `tabStock Ledger Entry`""")[0][0])
if sle_count > 500000:
frappe.throw(_("Please set filter based on Item or Warehouse"))
frappe.throw(_("Please set filter based on Item or Warehouse due to a large amount of entries."))
def get_variants_attributes():
'''Return all item variant attributes.'''

View File

@@ -1,10 +1,11 @@
frappe
unidecode
pygithub
googlemaps
python-stdnum
braintree
gocardless_pro
woocommerce
pandas
plaid-python
Unidecode==1.1.1
PyGithub==1.45
googlemaps==4.2.0
python-stdnum==1.13
braintree==3.59.0;python_version<"3.6"
braintree==4.0.0;python_version>="3.6"
gocardless-pro==1.16.0
WooCommerce==2.1.1
pandas==0.24.2
plaid-python==3.7.0