Compare commits

..

296 Commits

Author SHA1 Message Date
Saurabh
c32f8eb0cb Merge branch 'hotfix' 2019-04-05 16:59:22 +05:30
Saurabh
63fabc3723 bumped to version 11.1.19 2019-04-05 17:29:22 +06:00
Nabin Hait
d70476fbc8 Merge pull request #17139 from hrwX/pe_supp_inv_v11
fix(Payment Entry): Return Bill No for Payment Entry
2019-04-05 15:59:43 +05:30
Nabin Hait
8cf76e74e0 Merge pull request #17133 from hrwX/validate_stock_transaction_v11
fix(Item): check transactions for batch, serial check
2019-04-05 15:41:35 +05:30
Nabin Hait
843e440191 Merge branch 'hotfix' into validate_stock_transaction_v11 2019-04-05 15:41:26 +05:30
Nabin Hait
1580e24946 Merge pull request #17137 from netchampfaris/item-group-clean-description
fix(Item Group): Don't clean description html
2019-04-05 15:39:44 +05:30
Nabin Hait
603dce428b Merge pull request #17144 from nabinhait/variant-fix
fix: Default variant Based on
2019-04-05 15:38:15 +05:30
rohitwaghchaure
e334413b34 Merge pull request #17141 from rohitwaghchaure/incorrect_pos_profile_selected_if
fix: incorrect auto POS profile selected in the sales invoice
2019-04-05 13:04:05 +05:30
Nabin Hait
a3357e4e86 fix: Default variant Based on 2019-04-05 12:10:36 +05:30
Rohit Waghchaure
4324f43a06 always set the company from the POS Profile 2019-04-05 09:54:55 +05:30
Rohit Waghchaure
f7a83cb4f5 fix: incorrect POS profile selected 2019-04-05 00:42:48 +05:30
Himanshu Warekar
6443d7dd10 refactor: declare bill_on at function start 2019-04-04 19:54:23 +05:30
Himanshu Warekar
ad32324c4c fix: get bill_no 2019-04-04 19:50:23 +05:30
Faris Ansari
7a0a05d8f1 fix(Item Group): Don't clean description html 2019-04-04 15:53:16 +05:30
Himanshu Warekar
7f253b679a pull from hotfix 2019-04-04 15:19:44 +05:30
Himanshu Warekar
28db545947 fix: check transactions for batch, serial check 2019-04-04 15:02:25 +05:30
Nabin Hait
82bd388993 Merge pull request #17122 from frappe/asbasawaraj-remove-location-from-abbreviation-doctypes
fix: Removed Location from Abbreviation Update DocTypes
2019-04-04 11:50:33 +05:30
Nabin Hait
e0a9835f30 Merge pull request #16987 from SaiFi0102/Party-Ledger-Summary-Fix
fix(Party Ledger Summary): Show all adjustment entries as columns
2019-04-04 11:45:36 +05:30
Nabin Hait
0747273ea4 Merge pull request #17028 from sagarvora/field_order
fix(accounts): dependent field should be displayed after source link field
2019-04-04 11:45:01 +05:30
Nabin Hait
9eeb3715f0 Merge pull request #16992 from hrwX/cost_center
fix(Purchase Invoice): Cost Centre as per company
2019-04-04 11:43:35 +05:30
Nabin Hait
2df623c693 Merge pull request #17072 from kennethsequeira/auto-re-val
fix: spelling in validation message for Auto-reorder
2019-04-04 11:40:08 +05:30
Nabin Hait
1e5664ba5f Update item.py 2019-04-04 11:39:55 +05:30
Nabin Hait
f4ae29320f Merge pull request #17087 from deepeshgarg007/payment_entry
Party type validation in payment entry
2019-04-04 11:39:00 +05:30
Nabin Hait
f86a01446f Merge pull request #17086 from adityahase/check-version-hf
fix: Raise exception if apps are on incompatible branches
2019-04-04 11:17:04 +05:30
Nabin Hait
9ee417888e Merge pull request #17092 from nabinhait/ar-ap-print
fix: Show Sales Person in AR/AP print is optional
2019-04-04 11:02:26 +05:30
Nabin Hait
2c869bd486 Merge pull request #17101 from hrwX/india_setup
fix(India): Add HSN/SAC in setup
2019-04-04 11:02:11 +05:30
Himanshu
c930cb10fa fix: remove duplicate doctype 2019-04-04 11:01:10 +05:30
Nabin Hait
91b1875ccf Merge pull request #17099 from nabinhait/return-precision-issue
fix: Validate returned qty with ref qty considering field precision
2019-04-04 10:59:26 +05:30
Nabin Hait
2092a8b1cf Merge pull request #17100 from nabinhait/gl-entry-precision
fix: Validate gl entry debit/credit as per field's precision
2019-04-04 10:59:06 +05:30
Nabin Hait
6ffdddc100 Merge pull request #17126 from rmehta/warehouse-account-description
fix(kaizen): warehouse account description
2019-04-04 10:50:52 +05:30
Nabin Hait
d2c370a215 Merge pull request #17113 from deepeshgarg007/item-register
fix: Divide by zero exception handling
2019-04-04 10:49:13 +05:30
Rushabh Mehta
1f0edabda8 fix(kaizen): warehouse account description 2019-04-04 08:58:34 +05:30
Rushabh Mehta
e7b6b46309 Merge pull request #17109 from PawanMeh/fixes_16894_v11
fix: Amazon v11 integration issues
2019-04-03 22:54:43 +05:30
asbasawaraj
d2b69445b1 Removed Location from Abbreviation Update DocTypes 2019-04-03 17:05:53 +05:30
rohitwaghchaure
fb48686d82 Merge pull request #17118 from rohitwaghchaure/_incorrect_prezzototale
fix: incorrect PrezzoTotale
2019-04-03 16:33:56 +05:30
Rohit Waghchaure
a2f71cdeec fix: incorrect PrezzoTotale 2019-04-03 16:10:14 +05:30
Nabin Hait
b1f3f04d71 fix: Validate gl entry debit/credit as per field's precision 2019-04-03 12:30:25 +05:30
deepeshgarg007
5ad7b655cf fix: Divide by zero exception handling 2019-04-03 09:11:03 +05:30
hello@openetech.com
ea00f8cbc3 [fix] #16894 2019-04-02 14:22:23 +05:30
rohitwaghchaure
b035bf7f39 Merge pull request #17095 from rohitwaghchaure/incorrect_calculation_of_imponibile_importo
fix: incorrect calcualtion of ImponibileImporto if tax rate is zero
2019-04-01 23:14:56 +05:30
Himanshu Warekar
624477cb21 fix(India): Add HSN/SAC in setup 2019-04-01 19:25:28 +05:30
Nabin Hait
b4263a41c6 fix: Validate gl entry debit/credit as per field's precision 2019-04-01 19:11:34 +05:30
Nabin Hait
88f036a171 fix: Validate returned qty with ref qty considering field precision 2019-04-01 18:41:31 +05:30
Nabin Hait
0049986efd Merge pull request #17088 from nabinhait/hsn-fixes
fix: Fetch HSN code only if empty
2019-04-01 18:17:26 +05:30
Rohit Waghchaure
ebc2437516 fix: calcualtion of ImponibileImporto if tax rate is zero 2019-04-01 17:50:31 +05:30
Nabin Hait
51d08786dc fix: Show Sales Person in AR/AP print is optional 2019-04-01 16:24:23 +05:30
Nabin Hait
f4af608408 fix: Fetch HSN code only if empty 2019-04-01 11:51:54 +05:30
deepeshgarg007
4614eb219b Merge branch 'hotfix' of https://github.com/frappe/erpnext into payment_entry 2019-04-01 11:48:07 +05:30
Aditya Hase
b841cb2a66 fix: Raise exception if apps are on incompatible branches 2019-04-01 11:36:57 +05:30
Nabin Hait
4873875c1c Merge pull request #17038 from netchampfaris/fix-leave-application-condition
fix: Missing "and" in filter conditions
2019-04-01 11:15:36 +05:30
Nabin Hait
093f4c529b Merge pull request #17055 from deepeshgarg007/tds
fix: TDS payable monthly report fix
2019-04-01 11:12:45 +05:30
deepeshgarg007
d0b98d74de fix: Allow doctype only in party account types 2019-03-30 19:44:31 +05:30
Nabin Hait
08319cecf5 Merge pull request #17074 from nabinhait/woocommerce-fix
fix: Woo-commerce fix
2019-03-30 19:12:38 +05:30
Nabin Hait
f9f04ed89e fix: woocommerce settings 2019-03-30 17:39:40 +05:30
Kenneth Sequeira
4f5839eb65 fixed spelling in validation message
fixed typo in auto-reorder validation message
2019-03-30 15:37:51 +05:30
Saurabh
05c8474db3 Merge branch 'hotfix' 2019-03-30 15:00:36 +05:30
Saurabh
75b4de3e20 bumped to version 11.1.18 2019-03-30 15:30:36 +06:00
rohitwaghchaure
892f675cf7 Merge pull request #17069 from frappe/revert-16950-fix-issue-credit
feat: Revert "Fix(Delivery Note): Fix issue credit note"
2019-03-30 14:25:08 +05:30
rohitwaghchaure
223bd45e06 Merge pull request #17039 from surajshetty3416/fix-bom-item-subquery-issue
fix: Subquery in get_bom_items method
2019-03-30 14:23:25 +05:30
rohitwaghchaure
f3a1fa0bae Revert "Fix(Delivery Note): Fix issue credit note" 2019-03-30 12:33:54 +05:30
rohitwaghchaure
5fdbdd50f9 Merge pull request #16950 from hrwX/fix-issue-credit
Fix(Delivery Note): Fix issue credit note
2019-03-30 12:31:18 +05:30
Himanshu
52ae923566 fix(Update GSTIN): remove '.__' from template (#17061)
'.__'  Avoid Server Side Template Injection
2019-03-30 12:11:27 +05:30
rohitwaghchaure
9d159be826 Merge pull request #17064 from rohitwaghchaure/not_able_to_create_chart_of_account
fix: user not able to create chart of account in parent if child has no chart of account
2019-03-30 10:14:19 +05:30
rohitwaghchaure
d4365e25c4 Merge pull request #17063 from scmmishra/hotfix
fix: healthcare unit type enable toggle
2019-03-30 10:13:30 +05:30
scmmishra
6f82f96816 Merge branch 'hotfix' of https://github.com/frappe/erpnext into hotfix 2019-03-29 20:05:40 +05:30
rohitwaghchaure
8dadd4b0b2 Merge pull request #17059 from rohitwaghchaure/cherry_pick_test_case_fix
fix: cherry-pick item variant test cases fix
2019-03-29 19:32:30 +05:30
Rohit Waghchaure
fd2b1385a3 fix: user not able to create chart of account in parent if child has no chart of account 2019-03-29 19:20:47 +05:30
scmmishra
29dc744354 fix: healtcare unit type enable toggle 2019-03-29 19:00:45 +05:30
Himanshu
6343a697a2 fix(Salary Slip): Consider Leave without Pay for calculation (#16926)
while net salary calculation, it was not considering actual days worked but now it will consider it
2019-03-29 18:48:56 +05:30
rohitwaghchaure
13752774ab Merge pull request #17000 from scmmishra/hotfix-task-status
fix: Task overdue status propagates to project
2019-03-29 18:44:36 +05:30
Rushabh Mehta
c4599c21c3 fix(test): item variant 2019-03-29 18:30:00 +05:30
rohitwaghchaure
fb8f1b93d6 Merge pull request #17058 from hrwX/bank_reco_fix
fix(Bank Reconciliation): get credit and debit in float and not string
2019-03-29 18:18:15 +05:30
Himanshu Warekar
f7f85f7379 fix: get credit and debit in float and not string 2019-03-29 16:19:15 +05:30
deepeshgarg007
4092ead41e fix: fetch account only if available 2019-03-29 16:19:04 +05:30
Faris Ansari
eec89ba4cb Merge branch 'hotfix' of https://github.com/frappe/erpnext into fix-leave-application-condition 2019-03-29 16:06:38 +05:30
Nabin Hait
862f77cc13 Merge branch 'deferred_revenue' into hotfix 2019-03-29 13:26:16 +05:30
Nabin Hait
66d07c2700 fix(accounts): Indentation 2019-03-29 13:25:11 +05:30
Nabin Hait
cf7538c17f Merge pull request #17046 from nabinhait/deferred_revenue
Refactor: deferred revenue booking logic
2019-03-29 12:39:36 +05:30
rohitwaghchaure
043cfe99ad Merge pull request #17051 from rohitwaghchaure/accounts_receivable_summary_issue
fix: accounts receivable summary
2019-03-29 09:28:21 +05:30
rohitwaghchaure
c268682772 Merge pull request #17048 from rohitwaghchaure/fixed_bank_reconciliation_not_working
fix: bank reconciliation not working
2019-03-29 09:27:50 +05:30
Rohit Waghchaure
9da14747aa fix: accounts receivable summary 2019-03-29 09:26:40 +05:30
Rohit Waghchaure
573d1dd31f fix: bank reconciliation not working 2019-03-28 20:39:49 +05:30
Nabin Hait
86fb523ea7 fix(accounts): codacy fixes 2019-03-28 20:06:57 +05:30
Nabin Hait
0a90ce5cf6 Refactored deferred revenue booking logic 2019-03-28 19:43:02 +05:30
Faris Ansari
f04988a02f fix: Missing "and" in filter conditions 2019-03-28 15:42:07 +05:30
Suraj Shetty
6262c9ed6a fix: Subquery in get_bom_items method 2019-03-28 14:59:27 +05:30
Saurabh
6cc9831ce9 Merge branch 'hotfix' 2019-03-28 13:51:58 +05:30
Saurabh
f2036dd1d1 bumped to version 11.1.17 2019-03-28 14:21:58 +06:00
Saurabh
1271dea39b Merge pull request #17035 from gaurav-naik/issue-17033
fix(regional,italy): autoset tax id, cf from customer before validating
2019-03-28 12:46:24 +05:30
rohitwaghchaure
89a2577ae5 Merge pull request #17032 from surajshetty3416/fix-group-same-items-in-printview
fix(print): Fix group same items for print view
2019-03-28 12:42:22 +05:30
Gaurav
bd80fd13cb fix(regional,italy): autoset company cf, tax_id before validating 2019-03-28 12:18:03 +05:30
Saurabh
ea19250884 Merge pull request #16859 from rohitwaghchaure/added_new_tags_e_invoice_xml
fix: added tags for discount amount, multiple customer po no, delivery notes
2019-03-28 11:19:44 +05:30
Gaurav
010acf75fa fix(regional,italy): autoset tax id, cf from customer before validating missing values
Fixes issue #17033
2019-03-28 10:42:29 +05:30
Suraj Shetty
a7992ecb62 style: Fix formatting 2019-03-27 20:32:42 +05:30
Suraj Shetty
abc2a64d5e fix: Commonify get gl_entry code by moving it to accounts_controller 2019-03-27 20:25:18 +05:30
Sagar Vora
d20ecb0a71 fix(accounts): dependent field should be displayed after source link field 2019-03-27 17:42:42 +05:30
Rohit Waghchaure
1b7059b867 fix: ImponibileImporto calculation 2019-03-27 15:33:47 +05:30
scmmishra
2405e14dde Merge branch 'hotfix-task-status' of github.com:scmmishra/erpnext into hotfix-task-status 2019-03-27 15:02:35 +05:30
scmmishra
36824cf7fb feat: refactored update status 2019-03-27 15:01:40 +05:30
rohitwaghchaure
4510e3a836 Merge pull request #17020 from rohitwaghchaure/offline_pos_duplicate_records_making
fix: offline pos, duplicate records creating
2019-03-26 22:49:42 +05:30
Himanshu
e43b6beff0 fix(Leave Balance Report): total allocated leaves not calculated properly (#16969)
* fix: total alloted leaves not calculated properly

* fix: Possible SQL injection

* typo fix in sql query

* prevent sql injection again ?

* Use ORM for query
2019-03-26 21:42:12 +05:30
Rohit Waghchaure
22ebaf1b11 fix: added tags for discount amount, multiple customer po no, delivery notes 2019-03-26 20:19:46 +05:30
Rohit Waghchaure
1df62097f6 fix: offline pos, duplicate records creating 2019-03-26 19:15:53 +05:30
Prateeksha Singh
6d2bb9126a Merge pull request #17019 from pratu16x7/hotfix-stock_entry_from_bom
fix(uom): Get items as per UOM defined in BOM
2019-03-26 18:00:50 +05:30
Nabin Hait
411f66a177 Merge pull request #17006 from deepeshgarg007/account-fix
fix: Ignore root company validation setting in company master
2019-03-26 17:49:21 +05:30
deepeshgarg007
3eeb1cacb0 fix: Change name to Allow Account Creation against Child Company in company master 2019-03-26 17:18:06 +05:30
Prateeksha Singh
a0927c1ba6 fix: correct use of include_item_in_manufacturing 2019-03-26 16:55:13 +05:30
Nabin Hait
8aaee57921 fix(uom): Get items as per UOM defined in BOM, fixes #15081 2019-03-26 16:53:13 +05:30
deepeshgarg007
c45c2bdabb fix: Missing semicolon 2019-03-26 15:38:38 +05:30
deepeshgarg007
7aefc15352 fix: Allow to add child account if ignore validation checked 2019-03-26 15:09:29 +05:30
Raffael Meyer
fdbb516a1b fix(projects): Auto-set employee and company in Timesheet (#16743)
* fix(projects): auto-set employee and company

* only set employee and company if document is unsaved

* use frm.set_value()
2019-03-26 12:47:36 +05:30
deepeshgarg007
1c785a99b1 fix: Added setting in company to ignore root company validation 2019-03-25 22:32:29 +05:30
Faris Ansari
843b7f6dd5 fix: Reorder Currency column to fix print (#17008)
Every Financial Report's 2nd column is Currency, which is an implicit requirement to Print them properly. In this case, Income column was not printed. This fixes that.
2019-03-25 15:50:36 +05:30
rohitwaghchaure
0a03e3d30c Merge pull request #17011 from rohitwaghchaure/fix_incorrect_paid_amt_in_accounts_receivable_summary_report
fix: incorrect paid amount in accounts receivable summary report
2019-03-25 15:41:29 +05:30
Rohit Waghchaure
4ed7d035cb fix: incorrect paid amount in accounts receivable summary report 2019-03-25 15:37:25 +05:30
rohitwaghchaure
794b6b6c0d Merge pull request #17004 from surajshetty3416/fix-bank-reconciliation-entries-hotfix
fix: Show consolidated amount of payment entries in Bank reconciliation
2019-03-25 14:11:47 +05:30
Rushabh Mehta
689490e4de Merge pull request #16986 from hrwX/italy_xml_fix
fix(Italy Customisation): Include fiscal code in invoice xml if present
2019-03-25 11:57:30 +05:30
deepeshgarg007
4f9ac0ad55 fix: Child company account currency fix 2019-03-25 11:39:25 +05:30
Shivam Mishra
ec56122876 fix: minor fix in test 2019-03-25 11:36:43 +05:30
scmmishra
1af3c41da3 fix: Typo in update_status 2019-03-25 11:34:33 +05:30
Suraj Shetty
67876d1026 fix: Show amount of entry based on diff of credit and debit 2019-03-25 11:19:07 +05:30
scmmishra
f7f32634c8 feat: Added check for no end date and refactored query 2019-03-24 20:43:15 +05:30
scmmishra
6ab6d35f92 fix: Task Overdue status propagates to project
- Used ORM instead of a SQL for set_task_as_overdue
- update_status function compares the time and marks the appropriate task as overdue
- The on_update hook makes the changes in project as well
2019-03-24 18:17:13 +05:30
rohitwaghchaure
9673d0ddae fix: description missing in the XML (#16985) 2019-03-24 12:19:58 +05:30
Himanshu Warekar
92593bb717 fix: Cost center as per company 2019-03-23 19:46:31 +05:30
Frappe Bot
0f1271612a Merge branch 'hotfix' 2019-03-23 07:25:02 +00:00
Frappe Bot
021ccf572a bumped to version 11.1.16 2019-03-23 07:25:02 +00:00
Himanshu
138e030055 CodiceFiscale should be after IdFiscaleIVA 2019-03-22 23:22:52 +05:30
Saif Ur Rehman
7d1c1aa28f fix(Party Ledger Summary): Show all adjustment entries as columns
Consider only Income Account or Expense Account account type for adjustment amounts
Check if GL Entry's is_opening == "Yes"
2019-03-22 17:18:32 +05:00
Himanshu Warekar
1d04ea1212 fix: include fiscal code in invoice xml if present 2019-03-22 17:47:57 +05:30
rohitwaghchaure
56e491bccd Merge pull request #16983 from rohitwaghchaure/allow_on_submit_for_budget_fields
feat: enabled allow on submit for action fields in the Budget
2019-03-22 15:34:41 +05:30
Rushabh Mehta
d562e9530e fix(link): help link in selling 2019-03-22 14:46:12 +05:30
Rushabh Mehta
c0de5b741e fix: remove gitter chat 2019-03-22 14:32:00 +05:30
Rushabh Mehta
da87a491ab Merge pull request #16816 from finbyz/hotfix
fix: Rounding adjustment in Rounded Total
2019-03-22 12:51:09 +05:30
Rushabh Mehta
7678c7b179 Merge pull request #16869 from rohitwaghchaure/not_able_to_submit_purchase_receipt
fix: purchase receipt not able to submit because default inventory account has not selected in another company
2019-03-22 12:47:06 +05:30
Rushabh Mehta
ff04142d9b Merge pull request #16848 from alyf-de/hotfix-1
fix(projects): change fieldtype of billing amounts to Currency
2019-03-22 12:44:18 +05:30
Rushabh Mehta
7defd6f3b5 Merge pull request #16749 from Alchez/hotfix-cancelled-payments
fix(payments): Only check for Draft or Submitted payments while cancelling payment requests
2019-03-22 12:43:52 +05:30
Rushabh Mehta
199aae0fe8 Merge pull request #16861 from Anurag810/asset_fixes
fix: passing the correct argument in get_depreciation_amount
2019-03-22 12:42:46 +05:30
Rohit Waghchaure
9c214b6129 feat: enabled allow on submit for action fields in the Budget 2019-03-22 12:08:09 +05:30
Rushabh Mehta
2f9c7171fa Merge pull request #16980 from chdecultot/fec_correctioon
fix: [Regional] [FEC report] Mapping issue in sql query
2019-03-22 12:05:51 +05:30
Charles-Henri Decultot
a7cf7fbccc Fix: Mapping issue in sql query 2019-03-21 13:28:14 +00:00
Saurabh
ce8d20c489 Merge branch 'hotfix' 2019-03-20 14:33:01 +05:30
Saurabh
83cc587f8f bumped to version 11.1.15 2019-03-20 15:03:00 +06:00
rohitwaghchaure
f45db71ba2 Merge pull request #16964 from rohitwaghchaure/fix_cost_center_mapping_not_working
fix: Cost center from PO to PI is not mapping
2019-03-20 13:40:05 +05:30
Rohit Waghchaure
f288866130 fix: Cost center from PO to PI is not mapping 2019-03-20 13:34:28 +05:30
rohitwaghchaure
e521f51e5f Merge pull request #16955 from rohitwaghchaure/sales_person_showing_wrong_on_ars
fix: Accounts receivable report, remarks showing in the sales person column
2019-03-19 18:17:15 +05:30
Mangesh-Khairnar
7fc1bc0b27 fix: handle an empty match query condition in leave application (#16931) 2019-03-19 18:14:02 +05:30
Rohit Waghchaure
a322687897 fix: Accounts receivable report, remarks showing in the sales person column 2019-03-19 18:10:08 +05:30
rohitwaghchaure
40046721b2 Merge pull request #16954 from rohitwaghchaure/pos_cost_center_not_added_against_debtors
fix: POS, cost center not added against debtors
2019-03-19 16:38:07 +05:30
Rohit Waghchaure
8808a3fc8e fix: POS, cost center not added against debtors 2019-03-19 15:32:05 +05:30
rohitwaghchaure
4904ce649e Merge pull request #16952 from rohitwaghchaure/fixed_accounts_receivable_summary_advance_amt
fix: advance amount is not calculating properly
2019-03-19 15:26:41 +05:30
Rohit Waghchaure
1a6e01542a fix: advance amount is not calculating properly 2019-03-19 15:06:01 +05:30
Rushabh Mehta
1e7d768a45 Merge pull request #16951 from hrwX/change-to-supplier
fix(Supplier Ledger Summary): Change Customer to Supplier in Supplier Ledger Summary
2019-03-19 09:47:14 +05:30
Himanshu Warekar
642a5b69f5 fix: change customer to supplier 2019-03-18 21:53:33 +05:30
Himanshu Warekar
2f5f17fcbb refactor: fix issue credit note 2019-03-18 21:46:26 +05:30
rohitwaghchaure
2046024de9 Merge pull request #16942 from hrwX/invoice-creation-tool
fix(Invoice Creation Tool): Disable P/L validation for opening invoice creation
2019-03-18 15:48:55 +05:30
Himanshu
ac199580af fix(Customer Ledger): ambiguous error in where clause (#16914)
fix for error "InternalError: (1052, u"Column 'company' in where clause is ambiguous")" in Customer Ledger Summary
2019-03-18 15:44:54 +05:30
rohitwaghchaure
4c8627e88d Merge pull request #16523 from Zlash65/comp-sync
feat: Sync Chart of Accounts in Company hierarchy
2019-03-18 15:43:50 +05:30
Rohit Waghchaure
d4e4316d0b fix: test cases and codacy 2019-03-18 14:18:49 +05:30
Zlash65
01086ff60c codacy fixes 2019-03-18 12:50:29 +05:30
Zlash65
11bba571af test case added to check account syncing 2019-03-18 12:50:29 +05:30
Zlash65
cc65447e62 fix: chart of accounts field toggling improv 2019-03-18 12:50:29 +05:30
Zlash65
f71cb8dc6d fix: return if no descendants found 2019-03-18 12:50:28 +05:30
Zlash65
73acb8c837 fix: set chart of accounts based on parent company on server side 2019-03-18 12:50:28 +05:30
Zlash65
d787ef8b8e feat: sync account created for a group company to all its descendants 2019-03-18 12:50:28 +05:30
Zlash65
88c990901d fix: added validation to if account is being added to child company 2019-03-18 12:50:28 +05:30
Zlash65
0407bf1e00 fix: override primary action button, change filter to root company 2019-03-18 12:50:27 +05:30
Zlash65
2def228da8 feat: allow adding account only if topmost parent company
- hidden filter for Parent Company added
- Add button overriden with new condition
2019-03-18 12:50:27 +05:30
Zlash65
a57d58f756 feat: once company is saved, parent_company cannot be selected 2019-03-18 12:50:27 +05:30
Zlash65
1a4bfdd090 feat: selecting parent_company should disable chart_of_accounts based fields 2019-03-18 12:50:27 +05:30
Himanshu Warekar
aa03ea2a56 disbale pl check for Sales and Purchase Invoice 2019-03-18 12:36:42 +05:30
Deepesh Garg
3ead70ba3c fix: Change IBAN Account length from 25 to 30 (#16847) 2019-03-18 08:22:57 +05:30
Deepesh Garg
2ae7ed4cf0 fix: Gross profit report fix (#16935) 2019-03-17 09:49:24 +05:30
rohitwaghchaure
fd33c55760 Merge pull request #16865 from rohitwaghchaure/purchase_invoice_asset_issue_not_able_to_submit
feat: added provision to disable CWIP accounting in asset settings
2019-03-16 12:18:36 +05:30
rushin29
08a209bc52 fix: gst_state_number for address with Unregistered GST (#16798) 2019-03-15 15:28:50 +05:30
rohitwaghchaure
ef74e94374 Merge pull request #16882 from rohitwaghchaure/multiple_time_logs_in_job_card
feat: child table to add multiple time logs in job card
2019-03-15 11:46:33 +05:30
Rushabh Mehta
59a3012a5c Update payment_request.py 2019-03-15 08:57:49 +05:30
Bassam Ramadan
e14758c897 fix: add returns field to cashier closing (#16911) 2019-03-14 15:01:50 +05:30
Rushabh Mehta
947d573276 Merge pull request #16892 from hrwX/uae_fix
fix(UAE): Fetch from fix for UAE customizations
2019-03-14 14:20:32 +05:30
Rushabh Mehta
e8258fc352 Merge pull request #16854 from jay-parikh/hotfix
fix: Default Company to Total Stock Summary Report
2019-03-14 14:18:36 +05:30
Rushabh Mehta
d63e0f490c Merge pull request #16856 from hrwX/sales-work-fix
fix(Work Order): fetch item info when making work order from sales order
2019-03-14 14:17:40 +05:30
Rushabh Mehta
20af5a2b40 Merge pull request #16866 from deepeshgarg007/additional
fix: Removed relieving date validation form additional salary
2019-03-14 14:16:18 +05:30
Rohit Waghchaure
52729bf369 feat: child table to add multiple time logs in job card 2019-03-11 00:02:32 +05:30
Himanshu Warekar
1692fbaf1c fetch from fix 2019-03-08 18:37:34 +05:30
Frappe Bot
2ae018a653 Merge branch 'hotfix' 2019-03-08 09:39:33 +00:00
Frappe Bot
3406229152 bumped to version 11.1.14 2019-03-08 09:39:32 +00:00
Rohit Waghchaure
6b33c9b934 fix: purchase receipt not able to submit because default inventory account has not selected in another company 2019-03-08 11:13:35 +05:30
Rohit Waghchaure
821a002125 feat: added provision to disable CWIP accounting in asset settings 2019-03-08 10:51:37 +05:30
Nabin Hait
9ec4816b32 Update item_barcode_childtable_migrate.py 2019-03-08 10:44:13 +05:30
deepeshgarg007
78a32ae172 fix: Remove validation for relieving date from additional salary 2019-03-07 20:00:07 +05:30
Anurag Mishra
1b0f5fd430 fix: pass correct argument to method get_deprication_amount 2019-03-07 16:17:00 +05:30
rohitwaghchaure
d4754619d0 Merge pull request #16806 from rohitwaghchaure/set_scanned_barcode_in_the_table
fix: scan barcode not adding the barcode value in the items table
2019-03-07 11:29:56 +05:30
rohitwaghchaure
d06212e408 Merge pull request #16853 from rohitwaghchaure/pos_profile_changes
fix: POS profile, account for change amount must be cash or bank account
2019-03-07 11:28:25 +05:30
Himanshu Warekar
7ab961f798 remove debug code 2019-03-06 23:53:38 +05:30
Himanshu Warekar
59699bf46e [debug] locally tests passed but travis failed 2019-03-06 23:33:03 +05:30
Himanshu Warekar
4f1737c2dd fix sales order test for creating work order from sales order 2019-03-06 22:19:15 +05:30
Himanshu Warekar
783331c645 sales_order to work_order item desc fix 2019-03-06 18:44:04 +05:30
Rohit Waghchaure
db8500c03a POS profile, account for change amount must be cash or bank account 2019-03-06 18:28:45 +05:30
Jay Parikh
9757a603fa Fix Company Default to Total Stock Summary Report 2019-03-06 12:44:41 +00:00
Rushabh Mehta
29c46bb311 fix(sales_order.py): handle zero bundle qty 2019-03-06 14:49:13 +05:30
Raffael Meyer
33d0a9f684 fix(projects): change fieldtype of billing amounts to Currency 2019-03-05 21:57:11 +01:00
Prateeksha Singh
fb491a568f Merge pull request #16842 from hrwX/additional_salary
fix(Additional Salary): Allow additional salary to be zero
2019-03-05 17:34:37 +05:30
Himanshu Warekar
acb7238ad6 Allow zero amount in additional salary 2019-03-05 12:20:19 +05:30
Rushabh Mehta
1f0792d5ea Merge pull request #16823 from jay-parikh/sales-return
fix: Python 3 Sales Invoice Return Validation "validate_pos"
2019-03-05 08:05:00 +05:30
rohitwaghchaure
55c382a780 Merge pull request #16820 from rohitwaghchaure/state_code_blank_if_not_matched_with_state_codes
fix: on save of the address, state code field become blank
2019-03-04 16:59:45 +05:30
rohitwaghchaure
f6a8b17717 Merge pull request #16824 from rohitwaghchaure/user_not_able_to_search_item_by_description
fix(sales order item): not able to search item by description
2019-03-04 16:59:19 +05:30
rohitwaghchaure
369d20ac2b Merge pull request #16829 from rohitwaghchaure/gst_purchase_invoice_hsn_number
fix: HSN code not disaplying for the GST Purchase Invoice print format
2019-03-04 16:58:58 +05:30
rohitwaghchaure
e552170ce6 Merge pull request #16704 from Anurag810/vedmata-print-formats
feat: Auditors print formats
2019-03-04 16:58:31 +05:30
rohitwaghchaure
8c96e06e19 Merge pull request #16629 from Anurag810/gross-and-net-profit-report
feat: Gross and Net Profit Report
2019-03-04 16:57:21 +05:30
Anurag Mishra
0c9945e0bf Minor fixes 2019-03-04 16:14:53 +05:30
Anurag Mishra
02138b6bfc fix: gross depends upon now report type 2019-03-04 14:46:28 +05:30
Rohit Waghchaure
9842ce5a79 fix: HSN code not disaplying for the GST Purchase Invoice print format 2019-03-04 13:39:52 +05:30
Deepesh Garg
44ff41188d fix: Selling and buying amount precision fix (#16764) 2019-03-04 12:56:27 +05:30
Deepesh Garg
40743840b7 fix: Print letter head only if checked in Print Settings (#16789)
Letter head is printed in financial statements even if option is not checked

![letter head option](https://user-images.githubusercontent.com/42651287/53430759-26baa080-3a15-11e9-948a-bc95700a18d2.png)
2019-03-04 12:53:11 +05:30
Deepesh Garg
e1f72cc010 revert: Address and contact report fix (#16786)
Reverts #16674 

Address and other info are not visible in address and contact report
![screenshot 2019-02-27 at 11 31 38 am](https://user-images.githubusercontent.com/42651287/53469309-6029f500-3a83-11e9-9672-e5e7d14dc470.png)
2019-03-04 12:49:39 +05:30
Anurag Mishra
1e4e61bd94 Minor fixes 2019-03-04 12:36:51 +05:30
Anurag Mishra
f3bdeedc68 minor fixes 2019-03-04 12:27:41 +05:30
Rohit Waghchaure
2bfb063fdb fix(sales order item): not able to search item by description 2019-03-02 21:47:55 +05:30
Jay Parikh
c2090939d7 Fix Sales Invoice Return Validation "validate_pos" 2019-03-02 12:19:32 +00:00
Rohit Waghchaure
4ef924d0ba fix: on save state code field become blank 2019-03-01 18:11:43 +05:30
Frappe Bot
9ce994a320 Merge branch 'hotfix' 2019-03-01 09:12:25 +00:00
Frappe Bot
3ec0bb7e53 bumped to version 11.1.13 2019-03-01 09:12:25 +00:00
rohitwaghchaure
066da6b1b6 Merge pull request #16817 from gaurav-naik/italy-einvoice-bank-details-fix
fix(regional,italy): bank details, custom button on sales invoice
2019-03-01 14:26:07 +05:30
rohitwaghchaure
5e71a56c7a Merge pull request #16807 from rohitwaghchaure/remove_validation_for_group_by_voucher_consolidate
fix: when General Ledger is opened from Purchase Receipt or Delivery note, user get Opening and Closing printed twice
2019-03-01 14:25:00 +05:30
Gaurav
6a4625b94c fix(regional,italy): codacy fixes in regional sales_invoice js 2019-03-01 13:58:39 +05:30
Gaurav
b30a9b1869 fix(regional,italy): bank details, custom button on sales invoice
Updates to Bank details in e-invoice XML
Additional fields on Payment Schedule
Button to Generate E-Invoice on Sales Invoice (generates and replaces attached e-invoice)
Replaced `x.decode('utf-8')` with `frappe.safe_decode(x, encoding='utf-8')` in setup.py
Updated italian localisation patch line in patches.txt
2019-03-01 12:38:35 +05:30
FinByz Tech Pvt. Ltd
6635583103 fix: Rounding adjustment in Rounded Total
In Purchase Receipt and GST Purchase Receipt report, the Rounded Total column doesn't display rounding adjustment of Base Grand Total. So, we have created a fix for that rounding adjustment.
2019-03-01 11:57:06 +05:30
Rohit Waghchaure
c21cda2790 Removed validation for group by voucher in general ledger 2019-02-28 16:20:45 +05:30
Frappe Bot
5d414af86b Merge branch 'hotfix' 2019-02-28 10:08:08 +00:00
Frappe Bot
58135976dd bumped to version 11.1.12 2019-02-28 10:08:08 +00:00
Rohit Waghchaure
ab4ff984c4 fix: scan barcode not adding the barcode value in the items table 2019-02-28 13:31:02 +05:30
rohitwaghchaure
1d41c1c2de Merge pull request #16787 from rohitwaghchaure/italian_more_fixes
fix: e-invoicing patch, patch to set country code in the address
2019-02-28 11:28:04 +05:30
rohitwaghchaure
75e17c664a Merge pull request #16797 from rohitwaghchaure/cost_update_not_working_for_price_list
fix: bom cost update is not working
2019-02-27 20:52:28 +05:30
Rohit Waghchaure
b48effebce fix: test case 2019-02-27 19:33:22 +05:30
Rohit Waghchaure
cd34c70670 fix: bom cost update is not working 2019-02-27 18:01:30 +05:30
Rohit Waghchaure
74cfe57716 fix: e-invoicing patch, patch to set country code in the address 2019-02-27 14:38:36 +05:30
Anurag Mishra
a9a1552e32 refactor 2019-02-27 14:10:24 +05:30
Rushabh Mehta
76f36f68d3 Merge pull request #16790 from crossxcell99/master
fix: call base class onload method
2019-02-27 08:31:14 +05:30
crossxcell99
f95171e808 fix: call base clase onload method 2019-02-26 18:01:37 +01:00
Sagar Vora
2ca1f135ef Merge branch 'hotfix' 2019-02-26 17:08:58 +05:30
Sagar Vora
5a14e46a1b bumped to version 11.1.11 2019-02-26 17:28:58 +05:50
Sagar Vora
311a9c79e3 fix: use node v10 for CI 2019-02-26 16:56:37 +05:30
Nabin Hait
39c489bfdc Merge pull request #16781 from deepeshgarg007/summary
fix: Make company filter mandatory in sales person wise transaction summary
2019-02-26 16:00:51 +05:30
Nabin Hait
be5124fe10 Merge pull request #16784 from rohitwaghchaure/multiple_fixes_e_invoicing
fix: multiple e-invoicing issues for italy region
2019-02-26 15:52:56 +05:30
Rohit Waghchaure
0f98cb8b83 fix: multiple e-invoicing issues for italy region 2019-02-26 15:09:27 +05:30
deepeshgarg007
d2d84e3c9d fix: Company filter fix 2019-02-26 11:52:22 +05:30
Sagar Vora
1ca2d47d35 fix: update node to version supported by Yarn (#16772) 2019-02-25 21:10:11 +05:30
Suraj Shetty
5636f924a9 fix: get mode of payment while selecting payment term in payment term template (#16765) 2019-02-25 12:43:34 +05:30
Nabin Hait
9990306399 fix: Consider only active BOMs while updating cost via BOM Update Tool (#16753) 2019-02-25 11:59:05 +05:30
Rushabh Mehta
e2de8e0fa5 fix: expense claim type (#16760) 2019-02-25 11:56:30 +05:30
Suraj Shetty
3ed3332c46 Merge pull request #16726 from deepeshgarg007/bom-item
fix: Removed duplicate fields from BOM Item
2019-02-22 10:26:29 +05:30
Suraj Shetty
2dadc1ef98 chore: Remove trailing whitespaces 2019-02-21 20:51:35 +05:30
deepeshgarg007
bf6b36a39b fix: Removed white spaces 2019-02-21 19:30:27 +05:30
deepeshgarg007
56b52d43e6 Merge branch 'hotfix' of https://github.com/frappe/erpnext into bom-item 2019-02-21 18:30:02 +05:30
Saurabh
539c77c591 Merge branch 'hotfix' 2019-02-21 18:25:28 +05:30
Saurabh
76cd402ca5 bumped to version 11.1.10 2019-02-21 18:55:28 +06:00
Saurabh
e5ff28a92c Merge pull request #16754 from deepeshgarg007/state_code
fix: State code issue fix
2019-02-21 18:21:24 +05:30
Nabin Hait
367d7c104e Merge pull request #16724 from rohitwaghchaure/user_progress_issue
fix: user progress issue
2019-02-21 18:13:52 +05:30
Saurabh
47738f9792 Merge pull request #16750 from nabinhait/cc-against-bs
fix: Ignore cost center while fetching outstanding invoices if not allowed from accounts settings
2019-02-21 18:12:06 +05:30
Nabin Hait
e08cb3a49b Merge pull request #16745 from nabinhait/manage-returned-qty
fix: Consider returned qty while making invoice from DN / PR
2019-02-21 18:11:37 +05:30
Nabin Hait
31f46b313c Merge pull request #16728 from rohitwaghchaure/maintainance_visit_issue
fix: not able to cancel maintenance visit
2019-02-21 18:10:46 +05:30
Nabin Hait
e328869b10 Merge pull request #16738 from deepeshgarg007/unique_tree_options
fix: Filter out unique values for tree options
2019-02-21 18:09:42 +05:30
Nabin Hait
e3b1b11bc5 Merge pull request #16740 from nabinhait/leave-calendar
fix: Calendar events for leaves considering user permissions
2019-02-21 18:08:19 +05:30
Saurabh
a05ccb76f4 Merge pull request #16748 from nabinhait/multi-company-serial-invoicing
fix: Validate serial no usage in invoice considering multi company transaction
2019-02-21 18:07:40 +05:30
Nabin Hait
e797ec7463 Merge pull request #16746 from deepeshgarg007/gross_profit
fix: Decimal point issue in gross profit print
2019-02-21 18:07:14 +05:30
deepeshgarg007
1915e15a9e fix: State code issue fix in regional module(Italy) 2019-02-21 17:55:57 +05:30
rohitwaghchaure
a49f59fcec Merge pull request #16751 from rohitwaghchaure/parent_value_showing_as_zero
(Profit and Loss Statement, fix): for parent account value was showing as zero
2019-02-21 17:50:51 +05:30
Rohit Waghchaure
90691dc0d8 (Profit and Loss Statement, fix): for parent account value was showing as zero 2019-02-21 17:18:28 +05:30
Nabin Hait
b24caad789 fix: Ignore cost center while fetching outstanding invocies if not allowed from accounts settings 2019-02-21 17:11:35 +05:30
Rohan Bansal
143973166f fix(payments): Only check for Draft or Submitted paymentswhile cancelling payment requests 2019-02-21 15:57:06 +05:30
Suraj Shetty
463a3cf8cf Merge pull request #16725 from deepeshgarg007/item_dashboard
fix: Item name display issue fix in item dashboard
2019-02-21 14:42:38 +05:30
Nabin Hait
26972c954d fix: Validate serial no usage in invoice considering multi company transaction 2019-02-21 14:32:41 +05:30
deepeshgarg007
14ff6bfc32 fix: Decimal point issue in gross profit print 2019-02-21 12:08:32 +05:30
Nabin Hait
816a4655a0 fix: Consider returned qty while making invoice from DN / PR 2019-02-21 12:02:36 +05:30
Nabin Hait
40c15d2e74 fix: Calendar events for leaves considering user permissions 2019-02-20 18:55:38 +05:30
Saurabh
bc3bdd77f6 Merge branch 'hotfix' 2019-02-20 18:14:17 +05:30
Saurabh
ada93e5d77 bumped to version 11.1.9 2019-02-20 18:44:17 +06:00
deepeshgarg007
0d64d622e5 fix: filter only unique values for tree options 2019-02-20 17:55:14 +05:30
rohitwaghchaure
485bd93dae Merge pull request #16737 from saurabh6790/indentation_fixes
fix: reload report doc and indentation fixes
2019-02-20 17:40:50 +05:30
rohitwaghchaure
c18e925d61 fix: Moved regional methods from controller to hooks (#16736) 2019-02-20 17:13:15 +05:30
Saurabh
9fcfc63f77 fix: reload report doc and indentation fixes 2019-02-20 17:04:18 +05:30
rohitwaghchaure
ef3f864123 fix: not able to submit purchase order (#16735) 2019-02-20 15:47:06 +05:30
rohitwaghchaure
e141865c43 Merge pull request #16722 from rohitwaghchaure/stop_button_not_working
fix: stop button not working in material request
2019-02-20 12:30:26 +05:30
Rohit Waghchaure
7e02e1c3cd fix: not able to cancel maintenance visit 2019-02-19 22:53:31 +05:30
deepeshgarg007
1b04534095 fix: Removed duplicate fields from BOM Item 2019-02-19 21:36:12 +05:30
deepeshgarg007
942c894f93 fix: fetch item name in item dashboard 2019-02-19 19:51:23 +05:30
Rohit Waghchaure
f4049f9dfd fix: user progress issue 2019-02-19 19:46:14 +05:30
Rohit Waghchaure
389cd6ad63 fix: stop button not working in material request 2019-02-19 19:18:07 +05:30
Anurag Mishra
879e5fd8bb remove print and codacy 2019-02-18 14:43:55 +05:30
Anurag Mishra
42a106c7ba Auditors print formats 2019-02-18 14:35:33 +05:30
Anurag Mishra
61f981ae05 Changes Requested 2019-02-18 11:43:32 +05:30
Anurag Mishra
4f0fd38209 refractor 2019-02-13 16:46:05 +05:30
Anurag Mishra
aaa57026ac Merge branch 'gross-and-net-profit-report' of https://github.com/Anurag810/erpnext into gross-and-net-profit-report 2019-02-11 17:02:59 +05:30
Anurag Mishra
f70d4089bc fix: codacy 2019-02-11 17:02:20 +05:30
Sagar Vora
4e92414850 Merge branch 'hotfix' into gross-and-net-profit-report 2019-02-11 16:00:28 +05:30
Anurag Mishra
a032f0528e new report gross-and-net-profit-report 2019-02-11 13:12:44 +05:30
146 changed files with 6117 additions and 3751 deletions

View File

@@ -15,7 +15,7 @@ install:
- sudo rm /etc/apt/sources.list.d/docker.list
- sudo apt-get install hhvm && rm -rf /home/travis/.kiex/
- sudo apt-get purge -y mysql-common mysql-server mysql-client
- nvm install v7.10.0
- nvm install 10
- pip install python-coveralls
- wget https://raw.githubusercontent.com/frappe/bench/master/playbooks/install.py
- sudo python install.py --develop --user travis --without-bench-setup

View File

@@ -6,7 +6,6 @@
</p>
[![Build Status](https://travis-ci.com/frappe/erpnext.png)](https://travis-ci.com/frappe/erpnext)
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/frappe/erpnext?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Open Source Helpers](https://www.codetriage.com/frappe/erpnext/badges/users.svg)](https://www.codetriage.com/frappe/erpnext)
[![Coverage Status](https://coveralls.io/repos/github/frappe/erpnext/badge.svg?branch=develop)](https://coveralls.io/github/frappe/erpnext?branch=develop)

View File

@@ -5,7 +5,7 @@ import frappe
from erpnext.hooks import regional_overrides
from frappe.utils import getdate
__version__ = '11.1.8'
__version__ = '11.1.19'
def get_default_company(user=None):
'''Get default company for user'''
@@ -144,4 +144,15 @@ def is_member():
last_membership = get_last_membership()
if last_membership and getdate(last_membership.to_date) > getdate():
return True
return False
return False
def check_branch_compatibility_with_frappe():
from frappe.utils.change_log import get_versions
versions = get_versions()
frappe_branch = versions["frappe"]["branch"]
erpnext_branch = versions["erpnext"]["branch"]
if frappe_branch in ("hotfix", "master") and erpnext_branch == "develop":
raise frappe.IncompatibleApp("Frappe is on branch: {} and ERPNext is on branch: {}".format(frappe_branch, erpnext_branch))
if erpnext_branch in ("hotfix", "master") and frappe_branch == "develop":
raise frappe.IncompatibleApp("Frappe is on branch: {} and ERPNext is on branch: {}".format(frappe_branch, erpnext_branch))

View File

@@ -2,9 +2,9 @@ from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import date_diff, add_months, today, getdate, add_days, flt
from frappe.utils import date_diff, add_months, today, getdate, add_days, flt, get_last_day
from erpnext.accounts.utils import get_account_currency
from erpnext.accounts.general_ledger import make_gl_entries
from frappe.email import sendmail_to_system_managers
def validate_service_stop_date(doc):
''' Validates service_stop_date for Purchase Invoice and Sales Invoice '''
@@ -33,47 +33,49 @@ def validate_service_stop_date(doc):
frappe.throw(_("Cannot change Service Stop Date for item in row {0}".format(item.idx)))
def convert_deferred_expense_to_expense(start_date=None, end_date=None):
# book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
if not start_date:
start_date = add_months(today(), -1)
if not end_date:
end_date = add_days(today(), -1)
# check for the purchase invoice for which GL entries has to be done
invoices = frappe.db.sql_list('''
select distinct parent from `tabPurchase Invoice Item` where service_start_date<=%s and service_end_date>=%s
select distinct parent from `tabPurchase Invoice Item`
where service_start_date<=%s and service_end_date>=%s
and enable_deferred_expense = 1 and docstatus = 1 and ifnull(amount, 0) > 0
''', (end_date or today(), start_date or add_months(today(), -1)))
''', (end_date, start_date))
# For each invoice, book deferred expense
for invoice in invoices:
doc = frappe.get_doc("Purchase Invoice", invoice)
book_deferred_income_or_expense(doc, start_date, end_date)
book_deferred_income_or_expense(doc, end_date)
def convert_deferred_revenue_to_income(start_date=None, end_date=None):
# book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
if not start_date:
start_date = add_months(today(), -1)
if not end_date:
end_date = add_days(today(), -1)
# check for the sales invoice for which GL entries has to be done
invoices = frappe.db.sql_list('''
select distinct parent from `tabSales Invoice Item` where service_start_date<=%s and service_end_date>=%s
select distinct parent from `tabSales Invoice Item`
where service_start_date<=%s and service_end_date>=%s
and enable_deferred_revenue = 1 and docstatus = 1 and ifnull(amount, 0) > 0
''', (end_date or today(), start_date or add_months(today(), -1)))
''', (end_date, start_date))
# For each invoice, book deferred revenue
for invoice in invoices:
doc = frappe.get_doc("Sales Invoice", invoice)
book_deferred_income_or_expense(doc, start_date, end_date)
book_deferred_income_or_expense(doc, end_date)
def get_booking_dates(doc, item, posting_date=None):
if not posting_date:
posting_date = add_days(today(), -1)
last_gl_entry = False
def get_booking_dates(doc, item, start_date=None, end_date=None):
deferred_account = "deferred_revenue_account" if doc.doctype=="Sales Invoice" else "deferred_expense_account"
last_gl_entry, skip = False, False
booking_end_date = getdate(add_days(today(), -1) if not end_date else end_date)
if booking_end_date < item.service_start_date or \
(item.service_stop_date and booking_end_date.month > item.service_stop_date.month):
return None, None, None, True
elif booking_end_date >= item.service_end_date:
last_gl_entry = True
booking_end_date = item.service_end_date
elif item.service_stop_date and item.service_stop_date <= booking_end_date:
last_gl_entry = True
booking_end_date = item.service_stop_date
booking_start_date = getdate(add_months(today(), -1) if not start_date else start_date)
booking_start_date = booking_start_date \
if booking_start_date > item.service_start_date else item.service_start_date
prev_gl_entry = frappe.db.sql('''
select name, posting_date from `tabGL Entry` where company=%s and account=%s and
@@ -81,17 +83,28 @@ def get_booking_dates(doc, item, start_date=None, end_date=None):
order by posting_date desc limit 1
''', (doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name), as_dict=True)
if not prev_gl_entry and item.service_start_date < booking_start_date:
booking_start_date = item.service_start_date
elif prev_gl_entry:
booking_start_date = getdate(add_days(prev_gl_entry[0].posting_date, 1))
skip = True if booking_start_date > booking_end_date else False
if prev_gl_entry:
start_date = getdate(add_days(prev_gl_entry[0].posting_date, 1))
else:
start_date = item.service_start_date
return last_gl_entry, booking_start_date, booking_end_date, skip
end_date = get_last_day(start_date)
if end_date >= item.service_end_date:
end_date = item.service_end_date
last_gl_entry = True
elif item.service_stop_date and end_date >= item.service_stop_date:
end_date = item.service_stop_date
last_gl_entry = True
def calculate_amount_and_base_amount(doc, item, last_gl_entry, total_days, total_booking_days):
account_currency = get_account_currency(item.expense_account)
if end_date > getdate(posting_date):
end_date = posting_date
if getdate(start_date) <= getdate(end_date):
return start_date, end_date, last_gl_entry
else:
return None, None, None
def calculate_amount(doc, item, last_gl_entry, total_days, total_booking_days, account_currency):
if doc.doctype == "Sales Invoice":
total_credit_debit, total_credit_debit_currency = "debit", "debit_in_account_currency"
deferred_account = "deferred_revenue_account"
@@ -123,28 +136,15 @@ def calculate_amount_and_base_amount(doc, item, last_gl_entry, total_days, total
return amount, base_amount
def book_deferred_income_or_expense(doc, start_date=None, end_date=None):
# book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM
# start_date: 1st of the last month or the start date
# end_date: end_date or today-1
def book_deferred_income_or_expense(doc, posting_date=None):
enable_check = "enable_deferred_revenue" \
if doc.doctype=="Sales Invoice" else "enable_deferred_expense"
gl_entries = []
for item in doc.get('items'):
if not item.get(enable_check): continue
skip = False
last_gl_entry, booking_start_date, booking_end_date, skip = \
get_booking_dates(doc, item, start_date, end_date)
if skip: continue
total_days = date_diff(item.service_end_date, item.service_start_date) + 1
total_booking_days = date_diff(booking_end_date, booking_start_date) + 1
def _book_deferred_revenue_or_expense(item):
start_date, end_date, last_gl_entry = get_booking_dates(doc, item, posting_date=posting_date)
if not (start_date and end_date): return
account_currency = get_account_currency(item.expense_account)
amount, base_amount = calculate_amount_and_base_amount(doc, item, last_gl_entry, total_days, total_booking_days)
if doc.doctype == "Sales Invoice":
against, project = doc.customer, doc.project
credit_account, debit_account = item.income_account, item.deferred_revenue_account
@@ -152,36 +152,62 @@ def book_deferred_income_or_expense(doc, start_date=None, end_date=None):
against, project = doc.supplier, item.project
credit_account, debit_account = item.deferred_expense_account, item.expense_account
# GL Entry for crediting the amount in the deferred expense
gl_entries.append(
doc.get_gl_dict({
"account": credit_account,
"against": against,
"credit": base_amount,
"credit_in_account_currency": amount,
"cost_center": item.cost_center,
"voucher_detail_no": item.name,
'posting_date': booking_end_date,
'project': project
}, account_currency)
)
# GL Entry to debit the amount from the expense
gl_entries.append(
doc.get_gl_dict({
"account": debit_account,
"against": against,
"debit": base_amount,
"debit_in_account_currency": amount,
"cost_center": item.cost_center,
"voucher_detail_no": item.name,
'posting_date': booking_end_date,
'project': project
}, account_currency)
)
total_days = date_diff(item.service_end_date, item.service_start_date) + 1
total_booking_days = date_diff(end_date, start_date) + 1
amount, base_amount = calculate_amount(doc, item, last_gl_entry,
total_days, total_booking_days, account_currency)
make_gl_entries(doc, credit_account, debit_account, against,
amount, base_amount, end_date, project, account_currency, item.cost_center, item.name)
if getdate(end_date) < getdate(posting_date) and not last_gl_entry:
_book_deferred_revenue_or_expense(item)
for item in doc.get('items'):
if item.get(enable_check):
_book_deferred_revenue_or_expense(item)
def make_gl_entries(doc, credit_account, debit_account, against,
amount, base_amount, posting_date, project, account_currency, cost_center, voucher_detail_no):
# GL Entry for crediting the amount in the deferred expense
from erpnext.accounts.general_ledger import make_gl_entries
gl_entries = []
gl_entries.append(
doc.get_gl_dict({
"account": credit_account,
"against": against,
"credit": base_amount,
"credit_in_account_currency": amount,
"cost_center": cost_center,
"voucher_detail_no": voucher_detail_no,
'posting_date': posting_date,
'project': project
}, account_currency)
)
# GL Entry to debit the amount from the expense
gl_entries.append(
doc.get_gl_dict({
"account": debit_account,
"against": against,
"debit": base_amount,
"debit_in_account_currency": amount,
"cost_center": cost_center,
"voucher_detail_no": voucher_detail_no,
'posting_date': posting_date,
'project': project
}, account_currency)
)
if gl_entries:
try:
make_gl_entries(gl_entries, cancel=(doc.docstatus == 2), merge_entries=True)
frappe.db.commit()
except:
frappe.db.rollback()
frappe.log_error(message = frappe.get_traceback(), title = _("Error while processing deferred accounting for {0}").format(doc.name))
title = _("Error while processing deferred accounting for {0}").format(doc.name)
traceback = frappe.get_traceback()
frappe.log_error(message=traceback , title=title)
sendmail_to_system_managers(title, traceback)

View File

@@ -632,6 +632,39 @@
"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": "eval:(doc.report_type == 'Profit and Loss' && !doc.is_group)",
"fieldname": "include_in_gross",
"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": "Include in gross",
"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
}
],
"has_web_view": 0,
@@ -645,7 +678,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2019-01-07 16:52:02.557837",
"modified": "2019-03-04 14:42:07.208893",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Account",

View File

@@ -5,7 +5,7 @@ from __future__ import unicode_literals
import frappe
from frappe.utils import cint, cstr
from frappe import throw, _
from frappe.utils.nestedset import NestedSet
from frappe.utils.nestedset import NestedSet, get_ancestors_of, get_descendants_of
class RootNotEditable(frappe.ValidationError): pass
class BalanceMismatchError(frappe.ValidationError): pass
@@ -41,6 +41,7 @@ class Account(NestedSet):
self.validate_frozen_accounts_modifier()
self.validate_balance_must_be_debit_or_credit()
self.validate_account_currency()
self.validate_root_company_and_sync_account_to_children()
def validate_parent(self):
"""Fetch Parent Details and validate parent account"""
@@ -90,6 +91,38 @@ class Account(NestedSet):
if not self.parent_account and not self.is_group:
frappe.throw(_("Root Account must be a group"))
def validate_root_company_and_sync_account_to_children(self):
# ignore validation while creating new compnay or while syncing to child companies
if frappe.local.flags.ignore_root_company_validation or self.flags.ignore_root_company_validation:
return
ancestors = get_root_company(self.company)
if ancestors:
if frappe.get_value("Company", self.company, "allow_account_creation_against_child_company"):
return
frappe.throw(_("Please add the account to root level Company - %s" % ancestors[0]))
else:
descendants = get_descendants_of('Company', self.company)
if not descendants: return
acc_name_map = {}
acc_name = frappe.db.get_value('Account', self.parent_account, "account_name")
for d in frappe.db.get_values('Account',
{"company": ["in", descendants], "account_name": acc_name},
["company", "name"], as_dict=True):
acc_name_map[d["company"]] = d["name"]
if not acc_name_map: return
for company in descendants:
doc = frappe.copy_doc(self)
doc.flags.ignore_root_company_validation = True
doc.update({"company": company, "account_currency": None,
"parent": acc_name_map[company], "parent_account": acc_name_map[company]})
doc.save()
frappe.msgprint(_("Account {0} is added in the child company {1}")
.format(doc.name, company))
def validate_group_or_ledger(self):
if self.get("__islocal"):
return
@@ -250,3 +283,9 @@ def merge_account(old, new, is_group, root_type, company):
frappe.rename_doc("Account", old, new, merge=1, ignore_permissions=1)
return new
@frappe.whitelist()
def get_root_company(company):
# return the topmost company in the hierarchy
ancestors = get_ancestors_of('Company', company, "lft asc")
return [ancestors[0]] if ancestors else []

View File

@@ -4,13 +4,42 @@ frappe.treeview_settings["Account"] = {
breadcrumbs: "Accounts",
title: __("Chart Of Accounts"),
get_tree_root: false,
filters: [{
fieldname: "company",
fieldtype:"Select",
options: erpnext.utils.get_tree_options("company"),
label: __("Company"),
default: erpnext.utils.get_tree_default("company")
}],
filters: [
{
fieldname: "company",
fieldtype:"Select",
options: erpnext.utils.get_tree_options("company"),
label: __("Company"),
default: erpnext.utils.get_tree_default("company"),
on_change: function() {
var me = frappe.treeview_settings['Account'].treeview;
var company = me.page.fields_dict.company.get_value();
frappe.call({
method: "erpnext.accounts.doctype.account.account.get_root_company",
args: {
company: company,
},
callback: function(r) {
if(r.message) {
let root_company = r.message.length ? r.message[0] : "";
me.page.fields_dict.root_company.set_value(root_company);
frappe.db.get_value("Company", {"name": company}, "allow_account_creation_against_child_company", (r) => {
frappe.flags.ignore_root_company_validation = r.allow_account_creation_against_child_company;
});
}
}
});
}
},
{
fieldname: "root_company",
fieldtype:"Data",
label: __("Root Company"),
hidden: true,
disable_onchange: true
}
],
root_label: "Accounts",
get_tree_nodes: 'erpnext.accounts.utils.get_children',
add_tree_node: 'erpnext.accounts.utils.add_ac',
@@ -42,8 +71,8 @@ frappe.treeview_settings["Account"] = {
],
ignore_fields:["parent_account"],
onload: function(treeview) {
frappe.treeview_settings['Account'].page = {};
$.extend(frappe.treeview_settings['Account'].page, treeview.page);
frappe.treeview_settings['Account'].treeview = {};
$.extend(frappe.treeview_settings['Account'].treeview, treeview);
function get_company() {
return treeview.page.fields_dict.company.get_value();
}
@@ -78,6 +107,18 @@ frappe.treeview_settings["Account"] = {
}
},
post_render: function(treeview) {
frappe.treeview_settings['Account'].treeview["tree"] = treeview.tree;
treeview.page.set_primary_action(__("New"), function() {
let root_company = treeview.page.fields_dict.root_company.get_value();
if(root_company) {
frappe.throw(__("Please add the account to root level Company - ") + root_company);
} else {
treeview.new_node();
}
}, "octicon octicon-plus");
},
onrender: function(node) {
if(frappe.boot.user.can_read.indexOf("GL Entry") !== -1){
var dr_or_cr = node.data.balance < 0 ? "Cr" : "Dr";
@@ -93,6 +134,20 @@ frappe.treeview_settings["Account"] = {
}
},
toolbar: [
{
label:__("Add Child"),
condition: function(node) {
return frappe.boot.user.can_create.indexOf("Account") !== -1
&& (!frappe.treeview_settings['Account'].treeview.page.fields_dict.root_company.get_value()
|| frappe.flags.ignore_root_company_validation)
&& node.expandable && !node.hide_add;
},
click: function() {
var me = frappe.treeview_settings['Account'].treeview;
me.new_node();
},
btnClass: "hidden-xs"
},
{
condition: function(node) {
return !node.root && frappe.boot.user.can_read.indexOf("GL Entry") !== -1
@@ -103,7 +158,7 @@ frappe.treeview_settings["Account"] = {
"account": node.label,
"from_date": frappe.sys_defaults.year_start_date,
"to_date": frappe.sys_defaults.year_end_date,
"company": frappe.treeview_settings['Account'].page.fields_dict.company.get_value()
"company": frappe.treeview_settings['Account'].treeview.page.fields_dict.company.get_value()
};
frappe.set_route("query-report", "General Ledger");
},

View File

@@ -97,6 +97,19 @@ class TestAccount(unittest.TestCase):
self.assertRaises(frappe.ValidationError, merge_account, "Capital Stock - _TC",\
"Softwares - _TC", doc.is_group, doc.root_type, doc.company)
def test_account_sync(self):
del frappe.local.flags["ignore_root_company_validation"]
acc = frappe.new_doc("Account")
acc.account_name = "Test Sync Account"
acc.parent_account = "Temporary Accounts - _TC3"
acc.company = "_Test Company 3"
acc.insert()
acc_tc_4 = frappe.db.get_value('Account', {'account_name': "Test Sync Account", "company": "_Test Company 4"})
acc_tc_5 = frappe.db.get_value('Account', {'account_name': "Test Sync Account", "company": "_Test Company 5"})
self.assertEqual(acc_tc_4, "Test Sync Account - _TC4")
self.assertEqual(acc_tc_5, "Test Sync Account - _TC5")
def _make_test_records(verbose):
from frappe.test_runner import make_test_objects
@@ -131,7 +144,7 @@ def _make_test_records(verbose):
# related to Account Inventory Integration
["_Test Account Stock In Hand", "Current Assets", 0, None, None],
# fixed asset depreciation
["_Test Fixed Asset", "Current Assets", 0, "Fixed Asset", None],
["_Test Accumulated Depreciations", "Current Assets", 0, None, None],
@@ -168,13 +181,17 @@ def get_inventory_account(company, warehouse=None):
return account
def create_account(**kwargs):
account = frappe.get_doc(dict(
doctype = "Account",
account_name = kwargs.get('account_name'),
account_type = kwargs.get('account_type'),
parent_account = kwargs.get('parent_account'),
company = kwargs.get('company')
))
account.save()
return account.name
account = frappe.db.get_value("Account", filters={"account_name": kwargs.get("account_name"), "company": kwargs.get("company")})
if account:
return account
else:
account = frappe.get_doc(dict(
doctype = "Account",
account_name = kwargs.get('account_name'),
account_type = kwargs.get('account_type'),
parent_account = kwargs.get('parent_account'),
company = kwargs.get('company')
))
account.save()
return account.name

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 1,
@@ -290,7 +291,7 @@
"in_list_view": 1,
"in_standard_filter": 0,
"label": "IBAN",
"length": 25,
"length": 30,
"no_copy": 0,
"permlevel": 0,
"precision": "",
@@ -669,7 +670,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-07-20 13:55:36.996465",
"modified": "2019-03-05 17:56:05.103238",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Account",

View File

@@ -23,36 +23,36 @@ class BankReconciliation(Document):
journal_entries = frappe.db.sql("""
select
"Journal Entry" as payment_document, t1.name as payment_entry,
t1.cheque_no as cheque_number, t1.cheque_date,
select
"Journal Entry" as payment_document, t1.name as payment_entry,
t1.cheque_no as cheque_number, t1.cheque_date,
sum(t2.debit_in_account_currency) as debit, sum(t2.credit_in_account_currency) as credit,
t1.posting_date, t2.against_account, t1.clearance_date, t2.account_currency
t1.posting_date, t2.against_account, t1.clearance_date, t2.account_currency
from
`tabJournal Entry` t1, `tabJournal Entry Account` t2
where
t2.parent = t1.name and t2.account = %s and t1.docstatus=1
and t1.posting_date >= %s and t1.posting_date <= %s
and t1.posting_date >= %s and t1.posting_date <= %s
and ifnull(t1.is_opening, 'No') = 'No' {0}
group by t2.account, t1.name
order by t1.posting_date ASC, t1.name DESC
""".format(condition), (self.bank_account, self.from_date, self.to_date), as_dict=1)
payment_entries = frappe.db.sql("""
select
"Payment Entry" as payment_document, name as payment_entry,
reference_no as cheque_number, reference_date as cheque_date,
if(paid_from=%(account)s, paid_amount, "") as credit,
if(paid_from=%(account)s, "", received_amount) as debit,
select
"Payment Entry" as payment_document, name as payment_entry,
reference_no as cheque_number, reference_date as cheque_date,
if(paid_from=%(account)s, paid_amount, 0) as credit,
if(paid_from=%(account)s, 0, received_amount) as debit,
posting_date, ifnull(party,if(paid_from=%(account)s,paid_to,paid_from)) as against_account, clearance_date,
if(paid_to=%(account)s, paid_to_account_currency, paid_from_account_currency) as account_currency
from `tabPayment Entry`
where
(paid_from=%(account)s or paid_to=%(account)s) and docstatus=1
and posting_date >= %(from)s and posting_date <= %(to)s {0}
order by
order by
posting_date ASC, name DESC
""".format(condition),
""".format(condition),
{"account":self.bank_account, "from":self.from_date, "to":self.to_date}, as_dict=1)
pos_entries = []
@@ -79,8 +79,12 @@ class BankReconciliation(Document):
for d in entries:
row = self.append('payment_entries', {})
amount = d.debit if d.debit else d.credit
d.amount = fmt_money(amount, 2, d.account_currency) + " " + (_("Dr") if d.debit else _("Cr"))
amount = flt(d.get('debit', 0)) - flt(d.get('credit', 0))
formatted_amount = fmt_money(abs(amount), 2, d.account_currency)
d.amount = formatted_amount + " " + (_("Dr") if amount > 0 else _("Cr"))
d.pop("credit")
d.pop("debit")
d.pop("account_currency")
@@ -103,10 +107,10 @@ class BankReconciliation(Document):
d.clearance_date = None
frappe.db.set_value(d.payment_document, d.payment_entry, "clearance_date", d.clearance_date)
frappe.db.sql("""update `tab{0}` set clearance_date = %s, modified = %s
where name=%s""".format(d.payment_document),
frappe.db.sql("""update `tab{0}` set clearance_date = %s, modified = %s
where name=%s""".format(d.payment_document),
(d.clearance_date, nowdate(), d.payment_entry))
clearance_date_updated = True
if clearance_date_updated:

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 1,
"allow_rename": 0,
@@ -19,6 +20,7 @@
"collapsible": 0,
"columns": 0,
"default": "Cost Center",
"fetch_if_empty": 0,
"fieldname": "budget_against",
"fieldtype": "Select",
"hidden": 0,
@@ -52,6 +54,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
@@ -86,6 +89,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.budget_against == 'Cost Center'",
"fetch_if_empty": 0,
"fieldname": "cost_center",
"fieldtype": "Link",
"hidden": 0,
@@ -120,6 +124,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:doc.budget_against == 'Project'",
"fetch_if_empty": 0,
"fieldname": "project",
"fieldtype": "Link",
"hidden": 0,
@@ -153,6 +158,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "fiscal_year",
"fieldtype": "Link",
"hidden": 0,
@@ -186,6 +192,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_3",
"fieldtype": "Column Break",
"hidden": 0,
@@ -218,6 +225,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:in_list([\"Stop\", \"Warn\"], doc.action_if_accumulated_monthly_budget_exceeded_on_po || doc.action_if_accumulated_monthly_budget_exceeded_on_mr || doc.action_if_accumulated_monthly_budget_exceeded_on_actual)",
"fetch_if_empty": 0,
"fieldname": "monthly_distribution",
"fieldtype": "Link",
"hidden": 0,
@@ -251,6 +259,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "amended_from",
"fieldtype": "Link",
"hidden": 0,
@@ -283,6 +292,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_6",
"fieldtype": "Section Break",
"hidden": 0,
@@ -315,6 +325,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "applicable_on_material_request",
"fieldtype": "Check",
"hidden": 0,
@@ -343,12 +354,13 @@
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Stop",
"depends_on": "eval:doc.applicable_on_material_request == 1",
"fetch_if_empty": 0,
"fieldname": "action_if_annual_budget_exceeded_on_mr",
"fieldtype": "Select",
"hidden": 0,
@@ -378,12 +390,13 @@
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Warn",
"depends_on": "eval:doc.applicable_on_material_request == 1",
"fetch_if_empty": 0,
"fieldname": "action_if_accumulated_monthly_budget_exceeded_on_mr",
"fieldtype": "Select",
"hidden": 0,
@@ -417,6 +430,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_13",
"fieldtype": "Column Break",
"hidden": 0,
@@ -448,6 +462,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "applicable_on_purchase_order",
"fieldtype": "Check",
"hidden": 0,
@@ -476,12 +491,13 @@
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Stop",
"depends_on": "eval:doc.applicable_on_purchase_order == 1",
"fetch_if_empty": 0,
"fieldname": "action_if_annual_budget_exceeded_on_po",
"fieldtype": "Select",
"hidden": 0,
@@ -511,12 +527,13 @@
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Warn",
"depends_on": "eval:doc.applicable_on_purchase_order == 1",
"fetch_if_empty": 0,
"fieldname": "action_if_accumulated_monthly_budget_exceeded_on_po",
"fieldtype": "Select",
"hidden": 0,
@@ -550,6 +567,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_16",
"fieldtype": "Section Break",
"hidden": 0,
@@ -581,6 +599,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "applicable_on_booking_actual_expenses",
"fieldtype": "Check",
"hidden": 0,
@@ -609,12 +628,13 @@
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Stop",
"depends_on": "eval:doc.applicable_on_booking_actual_expenses == 1",
"fetch_if_empty": 0,
"fieldname": "action_if_annual_budget_exceeded",
"fieldtype": "Select",
"hidden": 0,
@@ -644,12 +664,13 @@
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Warn",
"depends_on": "eval:doc.applicable_on_booking_actual_expenses == 1",
"fetch_if_empty": 0,
"fieldname": "action_if_accumulated_monthly_budget_exceeded",
"fieldtype": "Select",
"hidden": 0,
@@ -683,6 +704,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_21",
"fieldtype": "Section Break",
"hidden": 0,
@@ -715,6 +737,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "",
"fetch_if_empty": 0,
"fieldname": "accounts",
"fieldtype": "Table",
"hidden": 0,
@@ -735,7 +758,7 @@
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
@@ -752,7 +775,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-09-12 11:02:41.825923",
"modified": "2019-03-22 12:06:02.323099",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Budget",
@@ -785,7 +808,7 @@
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0,
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}

View File

@@ -1,426 +1,434 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "naming_series:",
"beta": 0,
"creation": "2018-06-18 16:51:49.994750",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Cashier-closing-",
"fieldname": "naming_series",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 1,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "Series",
"length": 0,
"no_copy": 0,
"options": "Cashier-closing-",
"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
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "user",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "User",
"length": 0,
"no_copy": 0,
"options": "User",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"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,
"default": "Today",
"fieldname": "date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "Date",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "from_time",
"fieldtype": "Time",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "From Time",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "",
"fieldname": "time",
"fieldtype": "Time",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "To Time",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0.00",
"fieldname": "expense",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Expense",
"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,
"default": "0.00",
"fieldname": "custody",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Custody",
"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,
"default": "0.00",
"fieldname": "outstanding_amount",
"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": "Outstanding Amount",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0.0",
"fieldname": "payments",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Payments",
"length": 0,
"no_copy": 0,
"options": "Cashier Closing Payments",
"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": "net_amount",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Net Amount",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"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": "Cashier Closing",
"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
}
],
"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-02-19 08:35:23.157327",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Cashier Closing",
"name_case": "",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 1,
"write": 1
}
],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "naming_series:",
"beta": 0,
"creation": "2018-06-18 16:51:49.994750",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "POS-CLO-",
"fieldname": "naming_series",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 1,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "Series",
"length": 0,
"no_copy": 0,
"options": "POS-CLO-",
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "user",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "User",
"length": 0,
"no_copy": 0,
"options": "User",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Today",
"fieldname": "date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "Date",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "from_time",
"fieldtype": "Time",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "From Time",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "",
"fieldname": "time",
"fieldtype": "Time",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 1,
"label": "To Time",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0.00",
"fieldname": "expense",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Expense",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "2",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0.00",
"fieldname": "custody",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Custody",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "2",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0.00",
"fieldname": "returns",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Returns",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "2",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0.00",
"fieldname": "outstanding_amount",
"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": "Outstanding Amount",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "2",
"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,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0.0",
"fieldname": "payments",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Payments",
"length": 0,
"no_copy": 0,
"options": "Cashier Closing Payments",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "net_amount",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 1,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Net Amount",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 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": "Cashier Closing",
"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,
"unique": 0
}
],
"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-03-14 09:14:26.727129",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Cashier Closing",
"name_case": "",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 1,
"write": 1
}
],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0
}

View File

@@ -29,8 +29,8 @@ class CashierClosing(Document):
for i in self.payments:
total += flt(i.amount)
self.net_amount = total + self.outstanding_amount + self.expense - self.custody
self.net_amount = total + self.outstanding_amount + self.expense - self.custody + self.returns
def validate_time(self):
if self.from_time >= self.time:
frappe.throw(_("From Time Should Be Less Than To Time"))
frappe.throw(_("From Time Should Be Less Than To Time"))

View File

@@ -6,6 +6,7 @@ import frappe, erpnext
from frappe import _
from frappe.utils import flt, fmt_money, getdate, formatdate
from frappe.model.document import Document
from frappe.model.meta import get_field_precision
from erpnext.accounts.party import validate_party_gle_currency, validate_party_frozen_disabled
from erpnext.accounts.utils import get_account_currency
from erpnext.accounts.utils import get_fiscal_year
@@ -56,7 +57,7 @@ class GLEntry(Document):
.format(self.voucher_type, self.voucher_no, self.account))
# Zero value transaction is not allowed
if not (flt(self.debit) or flt(self.credit)):
if not (flt(self.debit, self.precision("debit")) or flt(self.credit, self.precision("credit"))):
frappe.throw(_("{0} {1}: Either debit or credit amount is required for {2}")
.format(self.voucher_type, self.voucher_no, self.account))
@@ -74,7 +75,8 @@ 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":
frappe.db.get_value("Account", self.account, "report_type")=="Profit and Loss" and \
self.voucher_type not in ['Purchase Invoice', 'Sales Invoice']:
frappe.throw(_("{0} {1}: 'Profit and Loss' type account {2} not allowed in Opening Entry")
.format(self.voucher_type, self.voucher_no, self.account))
@@ -215,17 +217,23 @@ def validate_frozen_account(account, adv_adj=None):
def update_against_account(voucher_type, voucher_no):
entries = frappe.db.get_all("GL Entry",
filters={"voucher_type": voucher_type, "voucher_no": voucher_no},
fields=["name", "party", "against", "debit", "credit", "account"])
fields=["name", "party", "against", "debit", "credit", "account", "company"])
if not entries:
return
company_currency = erpnext.get_company_currency(entries[0].company)
precision = get_field_precision(frappe.get_meta("GL Entry")
.get_field("debit"), company_currency)
accounts_debited, accounts_credited = [], []
for d in entries:
if flt(d.debit > 0): accounts_debited.append(d.party or d.account)
if flt(d.credit) > 0: accounts_credited.append(d.party or d.account)
if flt(d.debit, precision) > 0: accounts_debited.append(d.party or d.account)
if flt(d.credit, precision) > 0: accounts_credited.append(d.party or d.account)
for d in entries:
if flt(d.debit > 0):
if flt(d.debit, precision) > 0:
new_against = ", ".join(list(set(accounts_credited)))
if flt(d.credit > 0):
if flt(d.credit, precision) > 0:
new_against = ", ".join(list(set(accounts_debited)))
if d.against != new_against:

View File

@@ -52,6 +52,7 @@ class JournalEntry(AccountsController):
self.update_loan()
self.update_inter_company_jv()
def get_title(self):
return self.pay_to_recd_from or self.accounts[0].account

View File

@@ -232,6 +232,13 @@ frappe.ui.form.on('Payment Entry', {
},
party_type: function(frm) {
let party_types = Object.keys(frappe.boot.party_account_types);
if(frm.doc.party_type && !party_types.includes(frm.doc.party_type)){
frm.set_value("party_type", "");
frappe.throw(__("Party can only be one of "+ party_types.join(", ")));
}
if(frm.doc.party) {
$.each(["party", "party_balance", "paid_from", "paid_to",
"paid_from_account_currency", "paid_from_account_balance",

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@ from __future__ import unicode_literals
import frappe, erpnext, json
from frappe import _, scrub, ValidationError
from frappe.utils import flt, comma_or, nowdate, getdate
from erpnext.accounts.utils import get_outstanding_invoices, get_account_currency, get_balance_on
from erpnext.accounts.utils import get_outstanding_invoices, get_account_currency, get_balance_on, get_allow_cost_center_in_entry_of_bs_account
from erpnext.accounts.party import get_party_account
from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account
from erpnext.setup.utils import get_exchange_rate
@@ -70,6 +70,7 @@ class PaymentEntry(AccountsController):
self.update_advance_paid()
self.update_expense_claim()
def on_cancel(self):
self.setup_party_account_field()
self.make_gl_entries(cancel=1)
@@ -564,8 +565,8 @@ def get_outstanding_reference_documents(args):
.format(frappe.db.escape(args["voucher_type"]), frappe.db.escape(args["voucher_no"]))
# Add cost center condition
if args.get("cost_center"):
condition += " and cost_center='%s'" % args.get("cost_center")
if args.get("cost_center") and get_allow_cost_center_in_entry_of_bs_account():
condition += " and cost_center='%s'" % args.get("cost_center")
outstanding_invoices = get_outstanding_invoices(args.get("party_type"), args.get("party"),
args.get("party_account"), condition=condition)
@@ -748,7 +749,7 @@ def get_outstanding_on_journal_entry(name):
@frappe.whitelist()
def get_reference_details(reference_doctype, reference_name, party_account_currency):
total_amount = outstanding_amount = exchange_rate = None
total_amount = outstanding_amount = exchange_rate = bill_no = None
ref_doc = frappe.get_doc(reference_doctype, reference_name)
company_currency = ref_doc.get("company_currency") or erpnext.get_company_currency(ref_doc.company)
@@ -782,6 +783,7 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre
if reference_doctype in ("Sales Invoice", "Purchase Invoice"):
outstanding_amount = ref_doc.get("outstanding_amount")
bill_no = ref_doc.get("bill_no")
elif reference_doctype == "Expense Claim":
outstanding_amount = flt(ref_doc.get("total_sanctioned_amount")) \
- flt(ref_doc.get("total_amount+reimbursed")) - flt(ref_doc.get("total_advance_amount"))
@@ -798,7 +800,8 @@ def get_reference_details(reference_doctype, reference_name, party_account_curre
"due_date": ref_doc.get("due_date"),
"total_amount": total_amount,
"outstanding_amount": outstanding_amount,
"exchange_rate": exchange_rate
"exchange_rate": exchange_rate,
"bill_no": bill_no
})

View File

@@ -214,9 +214,10 @@ class PaymentRequest(Document):
def check_if_payment_entry_exists(self):
if self.status == "Paid":
payment_entry = frappe.db.sql_list("""select parent from `tabPayment Entry Reference`
where reference_name=%s""", self.reference_name)
if payment_entry:
if frappe.get_all("Payment Entry Reference",
filters={"reference_name": self.reference_name, "docstatus": ["<", 2]},
fields=["parent"],
limit=1):
frappe.throw(_("Payment Entry already exists"), title=_('Error'))
def make_communication_entry(self):

View File

@@ -8,5 +8,6 @@ frappe.ui.form.on('Payment Terms Template', {
frm.add_fetch("payment_term", "due_date_based_on", "due_date_based_on");
frm.add_fetch("payment_term", "credit_days", "credit_days");
frm.add_fetch("payment_term", "credit_months", "credit_months");
frm.add_fetch("payment_term", "mode_of_payment", "mode_of_payment");
}
});

View File

@@ -33,6 +33,14 @@ frappe.ui.form.on('POS Profile', {
};
});
frm.set_query("account_for_change_amount", function() {
return {
filters: {
account_type: ['in', ["Cash", "Bank"]]
}
};
});
frm.set_query("print_format", function() {
return { filters: { doc_type: "Sales Invoice", print_format_type: "Js"} };
});

View File

@@ -468,7 +468,7 @@ cur_frm.fields_dict["items"].grid.get_field("cost_center").get_query = function(
cur_frm.cscript.cost_center = function(doc, cdt, cdn){
var d = locals[cdt][cdn];
if(d.idx == 1 && d.cost_center){
if(d.cost_center){
var cl = doc.items || [];
for(var i = 0; i < cl.length; i++){
if(!cl[i].cost_center) cl[i].cost_center = d.cost_center;
@@ -510,6 +510,15 @@ frappe.ui.form.on("Purchase Invoice", {
}
}
}
frm.set_query("cost_center", function() {
return {
filters: {
company: frm.doc.company,
is_group: 0
}
};
});
},
onload: function(frm) {

View File

@@ -8,6 +8,7 @@ from frappe.utils import cint, cstr, formatdate, flt, getdate, nowdate
from frappe import _, throw
import frappe.defaults
from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
from erpnext.controllers.buying_controller import BuyingController
from erpnext.accounts.party import get_party_account, get_due_date
from erpnext.accounts.utils import get_account_currency, get_fiscal_year
@@ -17,7 +18,7 @@ from erpnext.accounts.general_ledger import make_gl_entries, merge_similar_entri
from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
from erpnext.buying.utils import check_for_closed_status
from erpnext.accounts.general_ledger import get_round_off_account_and_cost_center
from erpnext.assets.doctype.asset.asset import get_asset_account
from erpnext.assets.doctype.asset.asset import get_asset_account, is_cwip_accounting_disabled
from frappe.model.mapper import get_mapped_doc
from six import iteritems
from erpnext.accounts.doctype.sales_invoice.sales_invoice import validate_inter_company_party, update_linked_invoice,\
@@ -46,6 +47,7 @@ class PurchaseInvoice(BuyingController):
}]
def onload(self):
super(PurchaseInvoice, self).onload()
supplier_tds = frappe.db.get_value("Supplier", self.supplier, "tax_withholding_category")
self.set_onload("supplier_tds", supplier_tds)
@@ -53,6 +55,7 @@ class PurchaseInvoice(BuyingController):
if not self.on_hold:
self.release_date = ''
def invoice_is_blocked(self):
return self.on_hold and (not self.release_date or self.release_date > getdate(nowdate()))
@@ -215,7 +218,7 @@ class PurchaseInvoice(BuyingController):
self.validate_item_code()
self.validate_warehouse()
if auto_accounting_for_stock:
warehouse_account = get_warehouse_account_map()
warehouse_account = get_warehouse_account_map(self.company)
for item in self.get("items"):
# in case of auto inventory accounting,
@@ -231,6 +234,13 @@ class PurchaseInvoice(BuyingController):
item.expense_account = warehouse_account[item.warehouse]["account"]
else:
item.expense_account = stock_not_billed_account
elif item.is_fixed_asset and is_cwip_accounting_disabled():
if not item.asset:
frappe.throw(_("Row {0}: asset is required for item {1}")
.format(item.idx, item.item_code))
item.expense_account = get_asset_category_account(item.asset, 'fixed_asset_account',
company = self.company)
elif item.is_fixed_asset and item.pr_detail:
item.expense_account = asset_received_but_not_billed
elif not item.expense_account and for_validate:
@@ -359,7 +369,8 @@ class PurchaseInvoice(BuyingController):
if repost_future_gle and cint(self.update_stock) and self.auto_accounting_for_stock:
from erpnext.controllers.stock_controller import update_gl_entries_after
items, warehouses = self.get_items_and_warehouses()
update_gl_entries_after(self.posting_date, self.posting_time, warehouses, items)
update_gl_entries_after(self.posting_date, self.posting_time,
warehouses, items, company = self.company)
elif self.docstatus == 2 and cint(self.update_stock) and self.auto_accounting_for_stock:
delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
@@ -376,7 +387,9 @@ class PurchaseInvoice(BuyingController):
self.make_supplier_gl_entry(gl_entries)
self.make_item_gl_entries(gl_entries)
self.get_asset_gl_entry(gl_entries)
if not is_cwip_accounting_disabled():
self.get_asset_gl_entry(gl_entries)
self.make_tax_gl_entries(gl_entries)
gl_entries = merge_similar_entries(gl_entries)
@@ -416,7 +429,7 @@ class PurchaseInvoice(BuyingController):
stock_items = self.get_stock_items()
expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
if self.update_stock and self.auto_accounting_for_stock:
warehouse_account = get_warehouse_account_map()
warehouse_account = get_warehouse_account_map(self.company)
voucher_wise_stock_value = {}
if self.update_stock:
@@ -468,7 +481,7 @@ class PurchaseInvoice(BuyingController):
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
"credit": flt(item.rm_supp_cost)
}, warehouse_account[self.supplier_warehouse]["account_currency"]))
elif not item.is_fixed_asset:
elif not item.is_fixed_asset or (item.is_fixed_asset and is_cwip_accounting_disabled()):
gl_entries.append(
self.get_gl_dict({
"account": item.expense_account if not item.enable_deferred_expense else item.deferred_expense_account,
@@ -513,7 +526,7 @@ class PurchaseInvoice(BuyingController):
base_asset_amount = flt(item.base_net_amount + item.item_tax_amount)
if (not item.expense_account or frappe.db.get_value('Account',
item.expense_account, 'account_type') != 'Asset Received But Not Billed'):
item.expense_account, 'account_type') not in ['Asset Received But Not Billed', 'Fixed Asset']):
arbnb_account = self.get_company_default("asset_received_but_not_billed")
item.expense_account = arbnb_account

View File

@@ -0,0 +1,3 @@
{% include "erpnext/regional/italy/sales_invoice.js" %}
erpnext.setup_e_invoice_button('Sales Invoice')

View File

@@ -201,7 +201,8 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
get_query: function() {
var filters = {
docstatus: 1,
company: me.frm.doc.company
company: me.frm.doc.company,
is_return: 0
};
if(me.frm.doc.customer) filters["customer"] = me.frm.doc.customer;
return {
@@ -555,6 +556,23 @@ frappe.ui.form.on('Sales Invoice', {
frm.add_fetch('payment_term', 'invoice_portion', 'invoice_portion');
frm.add_fetch('payment_term', 'description', 'description');
frm.set_query("account_for_change_amount", function() {
return {
filters: {
account_type: ['in', ["Cash", "Bank"]]
}
};
});
frm.set_query("cost_center", function() {
return {
filters: {
company: frm.doc.company,
is_group: 0
}
};
});
frm.custom_make_buttons = {
'Delivery Note': 'Delivery',
'Sales Invoice': 'Sales Return',

View File

@@ -24,7 +24,6 @@ from erpnext.accounts.general_ledger import get_round_off_account_and_cost_cente
from erpnext.accounts.doctype.loyalty_program.loyalty_program import \
get_loyalty_program_details_with_points, get_loyalty_details, validate_loyalty_points
from erpnext.accounts.deferred_revenue import validate_service_stop_date
from erpnext.controllers.accounts_controller import on_submit_regional, on_cancel_regional
from erpnext.healthcare.utils import manage_invoice_submit_cancel
@@ -199,8 +198,6 @@ class SalesInvoice(SellingController):
if "Healthcare" in active_domains:
manage_invoice_submit_cancel(self, "on_submit")
on_submit_regional(self)
def validate_pos_paid_amount(self):
if len(self.payments) == 0 and self.is_pos:
frappe.throw(_("At least one mode of payment is required for POS invoice."))
@@ -208,6 +205,7 @@ class SalesInvoice(SellingController):
def before_cancel(self):
self.update_time_sheet(None)
def on_cancel(self):
self.check_close_sales_order("sales_order")
@@ -256,8 +254,6 @@ class SalesInvoice(SellingController):
if "Healthcare" in active_domains:
manage_invoice_submit_cancel(self, "on_cancel")
on_cancel_regional(self)
def update_status_updater_args(self):
if cint(self.update_stock):
self.status_updater.extend([{
@@ -404,7 +400,7 @@ class SalesInvoice(SellingController):
for fieldname in ('territory', 'naming_series', 'currency', 'taxes_and_charges', 'letter_head', 'tc_name',
'company', 'select_print_heading', 'cash_bank_account', 'company_address',
'write_off_account', 'write_off_cost_center', 'apply_discount_on'):
'write_off_account', 'write_off_cost_center', 'apply_discount_on', 'cost_center'):
if (not for_validate) or (for_validate and not self.get(fieldname)):
self.set(fieldname, pos.get(fieldname))
@@ -528,8 +524,8 @@ class SalesInvoice(SellingController):
def validate_pos(self):
if self.is_return:
if flt(self.paid_amount) + flt(self.write_off_amount) - flt(self.grand_total) < \
1/(10**(self.precision("grand_total") + 1)):
if flt(self.paid_amount) + flt(self.write_off_amount) - flt(self.grand_total) > \
1.0/(10.0**(self.precision("grand_total") + 1.0)):
frappe.throw(_("Paid amount + Write Off Amount can not be greater than Grand Total"))
def validate_item_code(self):
@@ -694,7 +690,8 @@ class SalesInvoice(SellingController):
if repost_future_gle and cint(self.update_stock) \
and cint(auto_accounting_for_stock):
items, warehouses = self.get_items_and_warehouses()
update_gl_entries_after(self.posting_date, self.posting_time, warehouses, items)
update_gl_entries_after(self.posting_date, self.posting_time,
warehouses, items, company = self.company)
elif self.docstatus == 2 and cint(self.update_stock) \
and cint(auto_accounting_for_stock):
from erpnext.accounts.general_ledger import delete_gl_entries
@@ -1017,9 +1014,10 @@ class SalesInvoice(SellingController):
for serial_no in item.serial_no.split("\n"):
sales_invoice = frappe.db.get_value("Serial No", serial_no, "sales_invoice")
if sales_invoice and self.name != sales_invoice:
frappe.throw(_("Serial Number: {0} is already referenced in Sales Invoice: {1}".format(
serial_no, sales_invoice
)))
sales_invoice_company = frappe.db.get_value("Sales Invoice", 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)))
def update_project(self):
if self.project:

View File

@@ -14,8 +14,9 @@ from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_per
from erpnext.exceptions import InvalidAccountCurrency, InvalidCurrency
from erpnext.stock.doctype.serial_no.serial_no import SerialNoWarehouseError
from frappe.model.naming import make_autoname
from erpnext.accounts.doctype.account.test_account import get_inventory_account
from erpnext.accounts.doctype.account.test_account import get_inventory_account, create_account
from erpnext.controllers.taxes_and_totals import get_itemised_tax_breakup_data
from erpnext.stock.doctype.item.test_item import create_item
from six import iteritems
class TestSalesInvoice(unittest.TestCase):
def make(self):
@@ -762,7 +763,7 @@ class TestSalesInvoice(unittest.TestCase):
set_perpetual_inventory(0)
frappe.db.sql("delete from `tabPOS Profile`")
def test_pos_si_without_payment(self):
set_perpetual_inventory()
make_pos_profile()
@@ -1514,6 +1515,56 @@ class TestSalesInvoice(unittest.TestCase):
accounts_settings.allow_cost_center_in_entry_of_bs_account = 0
accounts_settings.save()
def test_deferred_revenue(self):
deferred_account = create_account(account_name="Deferred Revenue",
parent_account="Current Liabilities - _TC", company="_Test Company")
item = create_item("_Test Item for Deferred Accounting")
item.enable_deferred_revenue = 1
item.deferred_revenue_account = deferred_account
item.no_of_months = 12
item.save()
si = create_sales_invoice(item=item.name, posting_date="2019-01-10", do_not_submit=True)
si.items[0].enable_deferred_revenue = 1
si.items[0].service_start_date = "2019-01-10"
si.items[0].service_end_date = "2019-03-15"
si.items[0].deferred_revenue_account = deferred_account
si.save()
si.submit()
from erpnext.accounts.deferred_revenue import convert_deferred_revenue_to_income
convert_deferred_revenue_to_income(start_date="2019-01-01", end_date="2019-01-31")
expected_gle = [
[deferred_account, 33.85, 0.0, "2019-01-31"],
["Sales - _TC", 0.0, 33.85, "2019-01-31"]
]
self.check_gl_entries(si.name, expected_gle, "2019-01-10")
convert_deferred_revenue_to_income(start_date="2019-01-01", end_date="2019-03-31")
expected_gle = [
[deferred_account, 43.08, 0.0, "2019-02-28"],
["Sales - _TC", 0.0, 43.08, "2019-02-28"],
[deferred_account, 23.07, 0.0, "2019-03-15"],
["Sales - _TC", 0.0, 23.07, "2019-03-15"]
]
self.check_gl_entries(si.name, expected_gle, "2019-01-31")
def check_gl_entries(self, voucher_no, expected_gle, posting_date):
gl_entries = frappe.db.sql("""select account, debit, credit, posting_date
from `tabGL Entry`
where voucher_type='Sales Invoice' and voucher_no=%s and posting_date > %s
order by posting_date asc, account asc""", (voucher_no, posting_date), as_dict=1)
for i, gle in enumerate(gl_entries):
self.assertEqual(expected_gle[i][0], gle.account)
self.assertEqual(expected_gle[i][1], gle.debit)
self.assertEqual(expected_gle[i][2], gle.credit)
self.assertEqual(getdate(expected_gle[i][3]), gle.posting_date)
def create_sales_invoice(**args):
si = frappe.new_doc("Sales Invoice")
@@ -1611,4 +1662,4 @@ def get_outstanding_amount(against_voucher_type, against_voucher, account, party
if against_voucher_type == 'Purchase Invoice':
bal = bal * -1
return bal
return bal

View File

@@ -20,6 +20,7 @@
"collapsible": 0,
"columns": 0,
"depends_on": "eval:parent.doctype == 'POS Profile'",
"fetch_if_empty": 0,
"fieldname": "default",
"fieldtype": "Check",
"hidden": 0,
@@ -52,6 +53,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "mode_of_payment",
"fieldtype": "Link",
"hidden": 0,
@@ -85,8 +87,9 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "",
"default": "0",
"depends_on": "eval:parent.doctype == 'Sales Invoice'",
"fetch_if_empty": 0,
"fieldname": "amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -120,6 +123,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_3",
"fieldtype": "Column Break",
"hidden": 0,
@@ -151,6 +155,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "account",
"fieldtype": "Link",
"hidden": 0,
@@ -185,6 +190,7 @@
"collapsible": 0,
"columns": 0,
"fetch_from": "mode_of_payment.type",
"fetch_if_empty": 0,
"fieldname": "type",
"fieldtype": "Read Only",
"hidden": 0,
@@ -218,6 +224,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "base_amount",
"fieldtype": "Currency",
"hidden": 0,
@@ -251,6 +258,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "clearance_date",
"fieldtype": "Date",
"hidden": 0,
@@ -287,7 +295,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2019-02-18 15:03:59.720469",
"modified": "2019-03-06 15:58:37.839241",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Payment",

View File

@@ -333,6 +333,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
var me = this;
this.frm = {}
this.load_data(true);
this.frm.doc.offline_pos_name = '';
this.setup();
this.set_default_customer()
},
@@ -345,7 +346,6 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
if (load_doc) {
this.frm.doc = JSON.parse(localStorage.getItem('doc'));
this.frm.doc.offline_pos_name = null;
}
$.each(this.meta, function (i, data) {
@@ -641,7 +641,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
me.list_customers_btn.toggleClass("view_customer");
me.pos_bill.show();
me.list_customers_btn.show();
me.frm.doc.offline_pos_name = $(this).parents().attr('invoice-name')
me.frm.doc.offline_pos_name = $(this).parents().attr('invoice-name');
me.edit_record();
})
@@ -984,7 +984,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
}
if(!this.customer_doc.fields_dict.customer_pos_id.value) {
this.customer_doc.set_value("customer_pos_id", $.now())
this.customer_doc.set_value("customer_pos_id", frappe.datetime.now_datetime())
}
},
@@ -1686,10 +1686,18 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
create_invoice: function () {
var me = this;
var existing_pos_list = [];
var invoice_data = {};
this.si_docs = this.get_doc_from_localstorage();
if (this.frm.doc.offline_pos_name) {
if(this.si_docs) {
this.si_docs.forEach((row) => {
existing_pos_list.push(Object.keys(row));
});
}
if (this.frm.doc.offline_pos_name
&& in_list(existing_pos_list, this.frm.doc.offline_pos_name)) {
this.update_invoice()
//to retrieve and set the default payment
invoice_data[this.frm.doc.offline_pos_name] = this.frm.doc;
@@ -1698,8 +1706,8 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
this.frm.doc.paid_amount = this.frm.doc.net_total
this.frm.doc.outstanding_amount = 0
} else {
this.frm.doc.offline_pos_name = $.now();
} else if(!this.frm.doc.offline_pos_name) {
this.frm.doc.offline_pos_name = frappe.datetime.now_datetime();
this.frm.doc.posting_date = frappe.datetime.get_today();
this.frm.doc.posting_time = frappe.datetime.now_time();
this.frm.doc.pos_total_qty = this.frm.doc.qty_total;

View File

@@ -573,11 +573,17 @@ def get_party_shipping_address(doctype, name):
else:
return ''
def get_partywise_advanced_payment_amount(party_type="Customer"):
def get_partywise_advanced_payment_amount(party_type, posting_date = None):
cond = "1=1"
if posting_date:
cond = "posting_date <= '{0}'".format(posting_date)
data = frappe.db.sql(""" SELECT party, sum({0}) as amount
FROM `tabGL Entry`
WHERE party_type = %s and against_voucher is null GROUP BY party"""
.format(("credit - debit") if party_type == "Customer" else "debit") , party_type)
WHERE
party_type = %s and against_voucher is null
and {1} GROUP BY party"""
.format(("credit") if party_type == "Customer" else "debit", cond) , party_type)
if data:
return frappe._dict(data)

View File

@@ -0,0 +1,82 @@
{%- from "templates/print_formats/standard_macros.html" import add_header -%}
<style>
.table-bordered td.top-bottom {border-top: none !important;border-bottom: none !important;}
.table-bordered td.right{border-right: none !important;}
.table-bordered td.left{border-left: none !important;}
</style>
<div class="page-break">
{%- if not doc.get("print_heading") and not doc.get("select_print_heading")
and doc.set("select_print_heading", _("Payment Entry")) -%}{%- endif -%}
{{ add_header(0, 1, doc, letter_head, no_letterhead, print_settings) }}
<div class="row margin-bottom">
<div class="col-sm-6">
<table>
<tr><td><strong>Voucher No: </strong></td><td>{{ doc.name }}</td></tr>
</table>
</div>
<div>
<table>
<tr><td><strong>Date: </strong></td><td>{{ frappe.utils.formatdate(doc.creation) }}</td></tr>
</table>
</div>
</div>
<div class="margin-top">
<table class="table table-bordered table-condensed">
<tr>
<th>Account</th>
<th>Party Type</th>
<th>Party</th>
<th>Amount</th>
</tr>
<tr>
<td class="top-bottom" colspan="5"><strong>Credit</strong></td>
</tr>
{% set total_credit = 0 -%}
{% for entries in doc.gl_entries %}
{% if entries.debit == 0.0 %}
<tr>
<td class="right top-bottom">{{ entries.account }}</td>
<td class="right left top-bottom">{{ entries.party_type }}</td>
<td class="right left top-bottom">{{ entries.party }}</td>
<td class="left top-bottom">{{ entries.credit }}</td>
{% set total_credit = total_credit + entries.credit -%}
</tr>
<tr>
<td class="top-bottom" colspan="4"><strong> Narration </strong><br>{{ entries.remarks }}</td>
</tr>
<tr>
<td class="right" colspan="3"><strong>Total (credit) </strong></td>
<td class="left" >{{total_credit}}</td>
</tr>
{% endif %}
{% endfor %}
<tr>
<td class="top-bottom" colspan="4"> </td>
</tr>
<tr>
<td class="top-bottom" colspan="5"><strong>Debit</strong></td>
</tr>
{% set total_debit = 0 -%}
{% for entries in doc.gl_entries %}
{% if entries.credit == 0.0 %}
<tr>
<td class="right top-bottom">{{ entries.account }}</td>
<td class="right left top-bottom">{{ entries.party_type }}</td>
<td class="right left top-bottom">{{ entries.party }}</td>
{% set total_debit = total_debit + entries.debit -%}
<td class="left top-bottom">{{ entries.debit }}</td>
</tr>
<tr>
<td class="top-bottom"colspan="4"><strong> Narration </strong><br>{{ entries.remarks }}</td>
</tr>
<tr>
<td class="right" colspan="3" ><strong>Total (debit) </strong></td>
<td class="left" >{{total_debit}}</td>
</tr>
{% endif %}
{% endfor %}
</table>
<div>
</div>

View File

@@ -0,0 +1,22 @@
{
"align_labels_right": 0,
"creation": "2019-02-15 11:49:08.608619",
"custom_format": 0,
"default_print_language": "en",
"disabled": 0,
"doc_type": "Payment Entry",
"docstatus": 0,
"doctype": "Print Format",
"font": "Default",
"idx": 0,
"line_breaks": 0,
"modified": "2019-02-15 11:49:08.608619",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank and Cash Payment Voucher",
"owner": "Administrator",
"print_format_builder": 0,
"print_format_type": "Server",
"show_section_headings": 0,
"standard": "Yes"
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,76 @@
{%- from "templates/print_formats/standard_macros.html" import add_header -%}
<style>
.table-bordered td.top-bottom {border-top: none !important;border-bottom: none !important;}
.table-bordered td.right{border-right: none !important;}
.table-bordered td.left{border-left: none !important;}
</style>
<div class="page-break">
{%- if not doc.get("print_heading") and not doc.get("select_print_heading")
and doc.set("select_print_heading", _("Journal Entry")) -%}{%- endif -%}
{{ add_header(0, 1, doc, letter_head, no_letterhead, print_settings) }}
<div class="row margin-bottom">
<div class="col-sm-6">
<table>
<tr><td><strong>Voucher No: </strong></td><td>{{ doc.name }}</td></tr>
</table>
</div>
<div>
<table>
<tr><td><strong>Date: </strong></td><td>{{ frappe.utils.formatdate(doc.creation) }}</td></tr>
</table>
</div>
</div>
<div class="margin-top">
<table class="table table-bordered table-condensed">
<tr>
<th>Account</th>
<th>Party Type</th>
<th>Party</th>
<th>Amount</th>
</tr>
<tr>
<td class="top-bottom" colspan="5"><strong>Credit</strong></td>
</tr>
{% set total_credit = 0 -%}
{% for entries in doc.gl_entries %}
{% if entries.debit == 0.0 %}
<tr>
<td class="right top-bottom">{{ entries.account }}</td>
<td class="right left top-bottom">{{ entries.party_type }}</td>
<td class="right left top-bottom">{{ entries.party }}</td>
<td class="left top-bottom">{{ entries.credit }}</td>
{% set total_credit = total_credit + entries.credit -%}
</tr>
<tr>
<td class="right" colspan="3"><strong>Total (credit) </strong></td>
<td class="left" >{{total_credit}}</td>
</tr>
{% endif %}
{% endfor %}
<tr>
<td class="top-bottom" colspan="4"> </td>
</tr>
<tr>
<td class="top-bottom" colspan="5"><strong>Debit</strong></td>
</tr>
{% set total_debit = 0 -%}
{% for entries in doc.gl_entries %}
{% if entries.credit == 0.0 %}
<tr>
<td class="right top-bottom">{{ entries.account }}</td>
<td class="right left top-bottom">{{ entries.party_type }}</td>
<td class="right left top-bottom">{{ entries.party }}</td>
{% set total_debit = total_debit + entries.debit -%}
<td class="left top-bottom">{{ entries.debit }}</td>
</tr>
<tr>
<td class="right" colspan="3" ><strong>Total (debit) </strong></td>
<td class="left" >{{total_debit}}</td>
</tr>
{% endif %}
{% endfor %}
</table>
<div>
</div>

View File

@@ -0,0 +1,22 @@
{
"align_labels_right": 0,
"creation": "2019-02-15 14:13:05.721784",
"custom_format": 0,
"default_print_language": "en",
"disabled": 0,
"doc_type": "Journal Entry",
"docstatus": 0,
"doctype": "Print Format",
"font": "Default",
"idx": 0,
"line_breaks": 0,
"modified": "2019-02-15 14:13:05.721784",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Journal Auditing Voucher",
"owner": "Administrator",
"print_format_builder": 0,
"print_format_type": "Server",
"show_section_headings": 0,
"standard": "Yes"
}

View File

@@ -0,0 +1,99 @@
{%- from "templates/print_formats/standard_macros.html" import add_header -%}
<div class="page-break">
{%- if not doc.get("print_heading") and not doc.get("select_print_heading")
and doc.set("select_print_heading", _("Purchase Invoice")) -%}{%- endif -%}
{{ add_header(0, 1, doc, letter_head, no_letterhead, print_settings) }}
<div class="row margin-bottom">
<div class="col-sm-6">
<table>
<tr><td><strong>Supplier Name: </strong></td><td>{{ doc.supplier }}</td></tr>
<tr><td><strong>Due Date: </strong></td><td>{{ frappe.utils.formatdate(doc.due_date) }}</td></tr>
<tr><td><strong>Address: </strong></td><td>{{doc.address_display}}</td></tr>
<tr><td><strong>Contact: </strong></td><td>{{doc.contact_display}}</td></tr>
<tr><td><strong>Mobile no: </strong> </td><td>{{doc.contact_mobile}}</td></tr>
</table>
</div>
<div>
<table>
<tr><td><strong>Voucher No: </strong></td><td>{{ doc.name }}</td></tr>
<tr><td><strong>Date: </strong></td><td>{{ frappe.utils.formatdate(doc.creation) }}</td></tr>
</table>
</div>
</div>
<div class="margin-top margin-bottom">
<table class="table table-bordered table-condensed">
<tr>
<th>SL</th>
<th>Item Code</th>
<th>Item Name</th>
<th>UOM</th>
<th>Received Qty.</th>
<th>Rejected Qty</th>
<th>Qty</th>
<th>Basic Rate</th>
<th>Amount</th>
</tr>
{% for item in doc.items %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ item.item_code }}</td>
<td>{{ item.item_name }}</td>
<td>{{ item.uom }}</td>
<td>{{ item.received_qty }}</td>
<td>{{ item.rejected_qty }}</td>
<td>{{ item.qty}}</td>
<td>{{ item.rate }}</td>
<td>{{ item.amount }}</td>
</tr>
{% endfor %}
</table>
</div>
<div class="row margin-bottom">
<div class="col-sm-6">
<table>
<tr><td><strong>Total Quantity: </strong></td><td>{{ doc.total_qty }}</td></tr>
<tr><td><strong>Total: </strong></td><td>{{doc.total}}</td></tr>
<tr><td><strong>Net Weight: </strong></td><td>{{ doc.total_net_weight }}</td></tr>
</table>
</div>
<div>
<table>
<tr><td><strong>Tax and Charges: </strong></td><td>{{doc.taxes_and_charges}}</td></tr>
{% for tax in doc.taxes %}
<tr><td><strong>{{ tax.account_head }}: </strong></td><td>{{ tax.tax_amount_after_discount_amount }}</td></tr>
{% endfor %}
<tr><td><strong> Taxes and Charges Added: </strong></td><td>{{ doc.taxes_and_charges_added }}</td></tr>
<tr><td><strong> Taxes and Charges Deducted: </strong></td><td>{{ doc.taxes_and_charges_deducted }}</td></tr>
<tr><td><strong> Total Taxes and Charges: </strong></td><td>{{ doc.total_taxes_and_charges }}</td></tr>
<tr><td><strong> Net Payable: </strong></td><td>{{ doc.grand_total }}</td></tr>
</table>
</div>
</div>
<div class="margin-top">
<table class='table table-bordered table-condensed'>
<tr>
<th>SL</th>
<th>Account</th>
<th>Party Type</th>
<th>Party</th>
<th>Credit Amount</th>
<th>Debit Amount</th>
</tr>
{% for entries in doc.gl_entries %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ entries.account }}</td>
<td>{{ entries.party_type }}</td>
<td>{{ entries.party }}</td>
<td>{{ entries.credit }}</td>
<td>{{ entries.debit }}</td>
</tr>
{% endfor %}
<tr>
<td colspan="4"><strong>Total</strong></td>
<td>{{ doc.grand_total|flt }}</td>
<td>{{ doc.grand_total|flt }}</td>
</tr>
</table>
</div>
</div>

View File

@@ -0,0 +1,22 @@
{
"align_labels_right": 0,
"creation": "2019-02-14 14:42:35.151611",
"custom_format": 0,
"default_print_language": "en",
"disabled": 0,
"doc_type": "Purchase Invoice",
"docstatus": 0,
"doctype": "Print Format",
"font": "Default",
"idx": 0,
"line_breaks": 0,
"modified": "2019-02-14 14:42:35.151611",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Auditing Voucher",
"owner": "Administrator",
"print_format_builder": 0,
"print_format_type": "Server",
"show_section_headings": 0,
"standard": "Yes"
}

View File

@@ -0,0 +1,93 @@
{%- from "templates/print_formats/standard_macros.html" import add_header -%}
<div class="page-break">
{%- if not doc.get("print_heading") and not doc.get("select_print_heading")
and doc.set("select_print_heading", _("Sales Invoice")) -%}{%- endif -%}
{{ add_header(0, 1, doc, letter_head, no_letterhead, print_settings) }}
<div class="row margin-bottom">
<div class="col-sm-6">
<table>
<tr><td><strong>Customer Name: </strong></td><td>{{ doc.customer }}</td></tr>
<tr><td><strong>Due Date: </strong></td><td>{{ frappe.utils.formatdate(doc.due_date) }}</td></tr>
<tr><td><strong>Address: </strong></td><td>{{doc.address_display}}</td></tr>
<tr><td><strong>Contact: </strong></td><td>{{doc.contact_display}}</td></tr>
<tr><td><strong>Mobile no: </strong> </td><td>{{doc.contact_mobile}}</td></tr>
</table>
</div>
<div>
<table>
<tr><td><strong>Voucher No: </strong></td><td>{{ doc.name }}</td></tr>
<tr><td><strong>Date: </strong></td><td>{{ frappe.utils.formatdate(doc.creation) }}</td></tr>
</table>
</div>
</div>
<div class="margin-top margin-bottom">
<table class="table table-bordered table-condensed">
<tr>
<th>SL</th>
<th>Item Code</th>
<th>Item Name</th>
<th>UOM</th>
<th>Quantity</th>
<th>Basic Rate</th>
<th>Amount</th>
</tr>
{% for item in doc.items %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ item.item_code }}</td>
<td>{{ item.item_name }}</td>
<td>{{ item.uom }}</td>
<td>{{ item.qty}}</td>
<td>{{ item.rate }}</td>
<td>{{ item.amount }}</td>
</tr>
{% endfor %}
</table>
</div>
<div class="row margin-bottom">
<div class="col-sm-6">
<table>
<tr><td><strong>Total Quantity: </strong></td><td>{{ doc.total_qty }}</td></tr>
<tr><td><strong>Total: </strong></td><td>{{doc.total}}</td></tr>
<tr><td><strong>Net Weight: </strong></td><td>{{ doc.total_net_weight }}</td></tr>
</table>
</div>
<div>
<table>
<tr><td><strong>Tax and Charges: </strong></td><td>{{doc.taxes_and_charges}}</td></tr>
{% for tax in doc.taxes %}
<tr><td><strong>{{ tax.account_head }}: </strong></td><td>{{ tax.tax_amount_after_discount_amount }}</td></tr>
{% endfor %}
<tr><td><strong> Total Taxes and Charges: </strong></td><td>{{ doc.total_taxes_and_charges }}</td></tr>
<tr><td><strong> Net Payable: </strong></td><td>{{ doc.grand_total }}</td></tr>
</table>
</div>
</div>
<div class="margin-top">
<table class='table table-bordered table-condensed'>
<tr>
<th>SL</th>
<th>Account</th>
<th>Party Type</th>
<th>Party</th>
<th>Credit Amount</th>
<th>Debit Amount</th>
</tr>
{% for entries in doc.gl_entries %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ entries.account }}</td>
<td>{{ entries.party_type }}</td>
<td>{{ entries.party }}</td>
<td>{{ entries.credit }}</td>
<td>{{ entries.debit }}</td>
</tr>
{% endfor %}
<tr>
<td colspan="4"><strong>Total</strong></td>
<td>{{ doc.grand_total|flt }}</td>
<td>{{ doc.grand_total|flt }}</td>
</tr>
</table>
</div>
</div>

View File

@@ -0,0 +1,22 @@
{
"align_labels_right": 0,
"creation": "2019-02-15 15:02:51.454754",
"custom_format": 0,
"default_print_language": "en",
"disabled": 0,
"doc_type": "Sales Invoice",
"docstatus": 0,
"doctype": "Print Format",
"font": "Default",
"idx": 0,
"line_breaks": 0,
"modified": "2019-02-15 15:02:51.454754",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Auditing Voucher",
"owner": "Administrator",
"print_format_builder": 0,
"print_format_type": "Server",
"show_section_headings": 0,
"standard": "Yes"
}

View File

@@ -107,26 +107,28 @@
<thead>
<tr>
{% if(report.report_name === "Accounts Receivable" || report.report_name === "Accounts Payable") { %}
<th style="width: 7%">{%= __("Date") %}</th>
<th style="width: 7%">{%= __("Age (Days)") %}</th>
<th style="width: 13%">{%= __("Reference") %}</th>
{% if(report.report_name === "Accounts Receivable") { %}
<th style="width: 10%">{%= __("Sales Person") %}</th>
<th style="width: 9%">{%= __("Date") %}</th>
<th style="width: 5%">{%= __("Age (Days)") %}</th>
{% if(report.report_name === "Accounts Receivable" && filters.show_sales_person_in_print) { %}
<th style="width: 16%">{%= __("Reference") %}</th>
<th style="width: 10%">{%= __("Sales Person") %}</th>
{% } else { %}
<th style="width: 26%">{%= __("Reference") %}</th>
{% } %}
{% if(!filters.show_pdc_in_print) { %}
<th style="width: 20%">{%= (filters.customer || filters.supplier) ? __("Remarks"): __("Party") %}</th>
<th style="width: 20%">{%= (filters.customer || filters.supplier) ? __("Remarks"): __("Party") %}</th>
{% } %}
<th style="width: 10%; text-align: right">{%= __("Invoiced Amount") %}</th>
{% if(!filters.show_pdc_in_print) { %}
<th style="width: 10%; text-align: right">{%= __("Paid Amount") %}</th>
<th style="width: 10%; text-align: right">{%= report.report_name === "Accounts Receivable" ? __('Credit Note') : __('Debit Note') %}</th>
{% } %}
<th style="width: 15%; text-align: right">{%= __("Outstanding Amount") %}</th>
<th style="width: 10%; text-align: right">{%= __("Outstanding Amount") %}</th>
{% if(filters.show_pdc_in_print) { %}
{% if(report.report_name === "Accounts Receivable") { %}
<th style="width: 10%">{%= __("Customer LPO No.") %}</th>
{% } %}
<th style="width: 10%">{%= __("PDC/LC Date") %}</th>
<th style="width: 10%">{%= __("PDC/LC Ref") %}</th>
<th style="width: 10%">{%= __("PDC/LC Amount") %}</th>
<th style="width: 10%">{%= __("Remaining Balance") %}</th>
@@ -155,7 +157,7 @@
{%= data[i]["voucher_no"] %}
</td>
{% if(report.report_name === "Accounts Receivable") { %}
{% if(report.report_name === "Accounts Receivable" && filters.show_sales_person_in_print) { %}
<td>{%= data[i]["sales_person"] %}</td>
{% } %}
@@ -195,7 +197,6 @@
<td style="text-align: right">
{%= data[i]["po_no"] %}</td>
{% } %}
<td style="text-align: right">{%= frappe.datetime.str_to_user(data[i][("pdc/lc_date")]) %}</td>
<td style="text-align: right">{%= data[i][("pdc/lc_ref")] %}</td>
<td style="text-align: right">{%= format_currency(data[i][("pdc/lc_amount")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i][("remaining_balance")], data[i]["currency"]) %}</td>
@@ -226,7 +227,6 @@
<td style="text-align: right">
{%= data[i][__("Customer LPO")] %}</td>
{% } %}
<td style="text-align: right">{%= frappe.datetime.str_to_user(data[i][__("PDC/LC Date")]) %}</td>
<td style="text-align: right">{%= data[i][("pdc/lc_ref")] %}</td>
<td style="text-align: right">{%= format_currency(data[i][("pdc/lc_amount")], data[i]["currency"]) %}</td>
<td style="text-align: right">{%= format_currency(data[i][("remaining_balance")], data[i]["currency"]) %}</td>

View File

@@ -102,14 +102,19 @@ frappe.query_reports["Accounts Receivable"] = {
"fieldtype": "Link",
"options": "Sales Person"
},
{
"fieldname":"based_on_payment_terms",
"label": __("Based On Payment Terms"),
"fieldtype": "Check",
},
{
"fieldname":"show_pdc_in_print",
"label": __("Show PDC in Print"),
"fieldtype": "Check",
},
{
"fieldname":"based_on_payment_terms",
"label": __("Based On Payment Terms"),
"fieldname":"show_sales_person_in_print",
"label": __("Show Sales Person in Print"),
"fieldtype": "Check",
},
{

View File

@@ -136,7 +136,8 @@ class AccountsReceivableSummary(ReceivablePayableReport):
partywise_total = self.get_partywise_total(party_naming_by, args)
partywise_advance_amount = get_partywise_advanced_payment_amount(args.get("party_type")) or {}
partywise_advance_amount = get_partywise_advanced_payment_amount(args.get("party_type"),
self.filters.get("report_date")) or {}
for party, party_dict in iteritems(partywise_total):
row = [party]
@@ -145,8 +146,12 @@ class AccountsReceivableSummary(ReceivablePayableReport):
row += [partywise_advance_amount.get(party, 0)]
paid_amt = 0
if party_dict.paid_amt > 0:
paid_amt = flt(party_dict.paid_amt - partywise_advance_amount.get(party, 0))
row += [
party_dict.invoiced_amt, party_dict.paid_amt, party_dict.credit_amt, party_dict.outstanding_amt,
party_dict.invoiced_amt, paid_amt, party_dict.credit_amt, party_dict.outstanding_amt,
party_dict.range1, party_dict.range2, party_dict.range3, party_dict.range4,
]
@@ -205,7 +210,7 @@ class AccountsReceivableSummary(ReceivablePayableReport):
cols += ["invoiced_amt", "paid_amt", "credit_amt",
"outstanding_amt", "age", "range1", "range2", "range3", "range4", "currency", "pdc/lc_date", "pdc/lc_ref",
"pdc/lc_amount", "remaining_balance"]
"pdc/lc_amount"]
if args.get("party_type") == "Supplier":
cols += ["supplier_group", "remarks"]

View File

@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe
import erpnext
from frappe import _
from frappe import _, scrub
from frappe.utils import getdate, nowdate
from six import iteritems, itervalues
@@ -14,6 +14,9 @@ class PartyLedgerSummaryReport(object):
self.filters.from_date = getdate(self.filters.from_date or nowdate())
self.filters.to_date = getdate(self.filters.to_date or nowdate())
if not self.filters.get("company"):
self.filters["company"] = frappe.db.get_single_value('Global Defaults', 'default_company')
def run(self, args):
if self.filters.from_date > self.filters.to_date:
frappe.throw(_("From Date must be before To Date"))
@@ -21,10 +24,9 @@ class PartyLedgerSummaryReport(object):
self.filters.party_type = args.get("party_type")
self.party_naming_by = frappe.db.get_value(args.get("naming_by")[0], None, args.get("naming_by")[1])
discount_account_field = "discount_allowed_account" if self.filters.party_type == "Customer" \
else "discount_received_account"
self.round_off_account, self.write_off_account, self.discount_account = frappe.get_cached_value('Company',
self.filters.company, ["round_off_account", "write_off_account", discount_account_field])
self.get_gl_entries()
self.get_return_invoices()
self.get_party_adjustment_amounts()
columns = self.get_columns()
data = self.get_data()
@@ -48,7 +50,6 @@ class PartyLedgerSummaryReport(object):
})
credit_or_debit_note = "Credit Note" if self.filters.party_type == "Customer" else "Debit Note"
discount_allowed_or_received = "Discount Allowed" if self.filters.party_type == "Customer" else "Discount Received"
columns += [
{
@@ -79,27 +80,19 @@ class PartyLedgerSummaryReport(object):
"options": "currency",
"width": 120
},
{
"label": _(discount_allowed_or_received),
"fieldname": "discount_amount",
]
for account in self.party_adjustment_accounts:
columns.append({
"label": account,
"fieldname": "adj_" + scrub(account),
"fieldtype": "Currency",
"options": "currency",
"width": 120
},
{
"label": _("Write Off Amount"),
"fieldname": "write_off_amount",
"fieldtype": "Currency",
"options": "currency",
"width": 120
},
{
"label": _("Other Adjustments"),
"fieldname": "adjustment_amount",
"fieldtype": "Currency",
"options": "currency",
"width": 120
},
"width": 120,
"is_adjustment": 1
})
columns += [
{
"label": _("Closing Balance"),
"fieldname": "closing_balance",
@@ -119,17 +112,10 @@ class PartyLedgerSummaryReport(object):
return columns
def get_data(self):
if not self.filters.get("company"):
self.filters["company"] = frappe.db.get_single_value('Global Defaults', 'default_company')
company_currency = frappe.get_cached_value('Company', self.filters.get("company"), "default_currency")
invoice_dr_or_cr = "debit" if self.filters.party_type == "Customer" else "credit"
reverse_dr_or_cr = "credit" if self.filters.party_type == "Customer" else "debit"
self.get_gl_entries()
self.get_return_invoices()
self.get_party_adjustment_amounts()
self.party_data = frappe._dict({})
for gle in self.gl_entries:
self.party_data.setdefault(gle.party, frappe._dict({
@@ -146,7 +132,7 @@ class PartyLedgerSummaryReport(object):
amount = gle.get(invoice_dr_or_cr) - gle.get(reverse_dr_or_cr)
self.party_data[gle.party].closing_balance += amount
if gle.posting_date < self.filters.from_date:
if gle.posting_date < self.filters.from_date or gle.is_opening == "Yes":
self.party_data[gle.party].opening_balance += amount
else:
if amount > 0:
@@ -161,9 +147,10 @@ class PartyLedgerSummaryReport(object):
if row.opening_balance or row.invoiced_amount or row.paid_amount or row.return_amount or row.closing_amount:
total_party_adjustment = sum([amount for amount in itervalues(self.party_adjustment_details.get(party, {}))])
row.paid_amount -= total_party_adjustment
row.discount_amount = self.party_adjustment_details.get(party, {}).get(self.discount_account, 0)
row.write_off_amount = self.party_adjustment_details.get(party, {}).get(self.write_off_account, 0)
row.adjustment_amount = total_party_adjustment - row.discount_amount - row.write_off_amount
adjustments = self.party_adjustment_details.get(party, {})
for account in self.party_adjustment_accounts:
row["adj_" + scrub(account)] = adjustments.get(account, 0)
out.append(row)
@@ -182,7 +169,7 @@ class PartyLedgerSummaryReport(object):
self.gl_entries = frappe.db.sql("""
select
gle.posting_date, gle.party, gle.voucher_type, gle.voucher_no, gle.against_voucher_type,
gle.against_voucher, gle.debit, gle.credit {join_field}
gle.against_voucher, gle.debit, gle.credit, gle.is_opening {join_field}
from `tabGL Entry` gle
{join}
where
@@ -195,7 +182,7 @@ class PartyLedgerSummaryReport(object):
conditions = [""]
if self.filters.company:
conditions.append("company=%(company)s")
conditions.append("gle.company=%(company)s")
self.filters.company_finance_book = erpnext.get_default_finance_book(self.filters.company)
@@ -254,9 +241,10 @@ class PartyLedgerSummaryReport(object):
def get_party_adjustment_amounts(self):
conditions = self.prepare_conditions()
income_or_expense = "Expense" if self.filters.party_type == "Customer" else "Income"
income_or_expense = "Expense Account" if self.filters.party_type == "Customer" else "Income Account"
invoice_dr_or_cr = "debit" if self.filters.party_type == "Customer" else "credit"
reverse_dr_or_cr = "credit" if self.filters.party_type == "Customer" else "debit"
round_off_account = frappe.get_cached_value('Company', self.filters.company, "round_off_account")
gl_entries = frappe.db.sql("""
select
@@ -267,7 +255,7 @@ class PartyLedgerSummaryReport(object):
docstatus < 2
and (voucher_type, voucher_no) in (
select voucher_type, voucher_no from `tabGL Entry` gle, `tabAccount` acc
where acc.name = gle.account and acc.root_type = '{income_or_expense}'
where acc.name = gle.account and acc.account_type = '{income_or_expense}'
and gle.posting_date between %(from_date)s and %(to_date)s and gle.docstatus < 2
) and (voucher_type, voucher_no) in (
select voucher_type, voucher_no from `tabGL Entry` gle
@@ -277,6 +265,7 @@ class PartyLedgerSummaryReport(object):
""".format(conditions=conditions, income_or_expense=income_or_expense), self.filters, as_dict=True)
self.party_adjustment_details = {}
self.party_adjustment_accounts = set()
adjustment_voucher_entries = {}
for gle in gl_entries:
adjustment_voucher_entries.setdefault((gle.voucher_type, gle.voucher_no), [])
@@ -288,12 +277,12 @@ class PartyLedgerSummaryReport(object):
has_irrelevant_entry = False
for gle in voucher_gl_entries:
if gle.account == self.round_off_account:
if gle.account == round_off_account:
continue
elif gle.party:
parties.setdefault(gle.party, 0)
parties[gle.party] += gle.get(reverse_dr_or_cr) - gle.get(invoice_dr_or_cr)
elif frappe.get_cached_value("Account", gle.account, "root_type") == income_or_expense:
elif frappe.get_cached_value("Account", gle.account, "account_type") == income_or_expense:
accounts.setdefault(gle.account, 0)
accounts[gle.account] += gle.get(invoice_dr_or_cr) - gle.get(reverse_dr_or_cr)
else:
@@ -303,11 +292,13 @@ class PartyLedgerSummaryReport(object):
if len(parties) == 1:
party = 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]
self.party_adjustment_accounts.add(account)
for party, amount in iteritems(parties):
self.party_adjustment_details.setdefault(party, {})
self.party_adjustment_details[party].setdefault(account, 0)

View File

@@ -15,7 +15,7 @@
height: 37px;
}
</style>
{% var letterhead= filters.letter_head || (frappe.get_doc(":Company", filters.company) && frappe.get_doc(":Company", filters.company).default_letter_head) || frappe.defaults.get_default("letter_head"); %}
{% var letterhead= filters.letter_head || (frappe.get_doc(":Company", filters.company) && frappe.get_doc(":Company", filters.company).default_letter_head) %}
{% if(letterhead) { %}
<div style="margin-bottom: 7px;" class="text-center">
{%= frappe.boot.letter_heads[letterhead].header %}

View File

@@ -126,7 +126,7 @@ def get_label(periodicity, from_date, to_date):
def get_data(
company, root_type, balance_must_be, period_list, filters=None,
accumulated_values=1, only_current_fiscal_year=True, ignore_closing_entries=False,
ignore_accumulated_values_for_fy=False):
ignore_accumulated_values_for_fy=False , total = True):
accounts = get_accounts(company, root_type)
if not accounts:
@@ -154,7 +154,7 @@ def get_data(
out = prepare_data(accounts, balance_must_be, period_list, company_currency)
out = filter_out_zero_value_rows(out, parent_children_map)
if out:
if out and total:
add_total_row(out, root_type, balance_must_be, period_list, company_currency)
return out
@@ -218,6 +218,9 @@ def prepare_data(accounts, balance_must_be, period_list, company_currency):
"year_start_date": year_start_date,
"year_end_date": year_end_date,
"currency": company_currency,
"include_in_gross": d.include_in_gross,
"account_type": d.account_type,
"is_group": d.is_group,
"opening_balance": d.get("opening_balance", 0.0) * (1 if balance_must_be=="Debit" else -1),
"account_name": ('%s - %s' %(_(d.account_number), _(d.account_name))
if d.account_number else _(d.account_name))
@@ -270,7 +273,7 @@ def add_total_row(out, root_type, balance_must_be, period_list, company_currency
for period in period_list:
total_row.setdefault(period.key, 0.0)
total_row[period.key] += row.get(period.key, 0.0)
row[period.key] = 0.0
row[period.key] = row.get(period.key, 0.0)
total_row.setdefault("total", 0.0)
total_row["total"] += flt(row["total"])
@@ -285,7 +288,7 @@ def add_total_row(out, root_type, balance_must_be, period_list, company_currency
def get_accounts(company, root_type):
return frappe.db.sql("""
select name, account_number, parent_account, lft, rgt, root_type, report_type, account_name
select name, account_number, parent_account, lft, rgt, root_type, report_type, account_name, include_in_gross, account_type, is_group, lft, rgt
from `tabAccount`
where company=%s and root_type=%s order by lft""", (company, root_type), as_dict=True)

View File

@@ -53,7 +53,7 @@ def validate_filters(filters, account_details):
frappe.throw(_("Can not filter based on Account, if grouped by Account"))
if (filters.get("voucher_no")
and filters.get("group_by") in [_('Group by Voucher'), _('Group by Voucher (Consolidated)')]):
and filters.get("group_by") in [_('Group by Voucher')]):
frappe.throw(_("Can not filter based on Voucher No, if grouped by Voucher"))
if filters.from_date > filters.to_date:

View File

@@ -0,0 +1 @@
{% include "accounts/report/financial_statements.html" %}

View File

@@ -0,0 +1,51 @@
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
/* eslint-disable */
frappe.query_reports["Gross and Net Profit Report"] = {
"filters": [
]
}
frappe.require("assets/erpnext/js/financial_statements.js", function() {
frappe.query_reports["Gross and Net Profit Report"] = $.extend({},
erpnext.financial_statements);
frappe.query_reports["Gross and Net Profit Report"]["filters"].push(
{
"fieldname":"project",
"label": __("Project"),
"fieldtype": "MultiSelect",
get_data: function() {
var projects = frappe.query_report.get_filter_value("project") || "";
const values = projects.split(/\s*,\s*/).filter(d => d);
const txt = projects.match(/[^,\s*]*$/)[0] || '';
let data = [];
frappe.call({
type: "GET",
method:'frappe.desk.search.search_link',
async: false,
no_spinner: true,
args: {
doctype: "Project",
txt: txt,
filters: {
"name": ["not in", values]
}
},
callback: function(r) {
data = r.results;
}
});
return data;
}
},
{
"fieldname": "accumulated_values",
"label": __("Accumulated Values"),
"fieldtype": "Check"
}
);
});

View File

@@ -0,0 +1,30 @@
{
"add_total_row": 0,
"creation": "2019-02-08 10:58:55.763090",
"disable_prepared_report": 0,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"modified": "2019-02-08 10:58:55.763090",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Gross and Net Profit Report",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "GL Entry",
"report_name": "Gross and Net Profit Report",
"report_type": "Script Report",
"roles": [
{
"role": "Accounts User"
},
{
"role": "Accounts Manager"
},
{
"role": "Auditor"
}
]
}

View File

@@ -0,0 +1,154 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import flt
from erpnext.accounts.report.financial_statements import (get_period_list, get_columns, get_data)
import copy
def execute(filters=None):
period_list = get_period_list(filters.from_fiscal_year, filters.to_fiscal_year,
filters.periodicity, filters.accumulated_values, filters.company)
columns, data = [], []
income = get_data(filters.company, "Income", "Credit", period_list, filters = filters,
accumulated_values=filters.accumulated_values,
ignore_closing_entries=True, ignore_accumulated_values_for_fy= True, total= False)
expense = get_data(filters.company, "Expense", "Debit", period_list, filters=filters,
accumulated_values=filters.accumulated_values,
ignore_closing_entries=True, ignore_accumulated_values_for_fy= True, total= False)
columns = get_columns(filters.periodicity, period_list, filters.accumulated_values, filters.company)
gross_income = get_revenue(income, period_list)
gross_expense = get_revenue(expense, period_list)
if(len(gross_income)==0 and len(gross_expense)== 0):
data.append({"account_name": "'" + _("Nothing is included in gross") + "'",
"account": "'" + _("Nothing is included in gross") + "'"})
return columns, data
data.append({"account_name": "'" + _("Included in Gross Profit") + "'",
"account": "'" + _("Included in Gross Profit") + "'"})
data.append({})
data.extend(gross_income or [])
data.append({})
data.extend(gross_expense or [])
data.append({})
gross_profit = get_profit(gross_income, gross_expense, period_list, filters.company, 'Gross Profit',filters.presentation_currency)
data.append(gross_profit)
non_gross_income = get_revenue(income, period_list, 0)
data.append({})
data.extend(non_gross_income or [])
non_gross_expense = get_revenue(expense, period_list, 0)
data.append({})
data.extend(non_gross_expense or [])
net_profit = get_net_profit(non_gross_income, gross_income, gross_expense, non_gross_expense, period_list, filters.company,filters.presentation_currency)
data.append({})
data.append(net_profit)
return columns, data
def get_revenue(data, period_list, include_in_gross=1):
revenue = [item for item in data if item['include_in_gross']==include_in_gross or item['is_group']==1]
data_to_be_removed =True
while data_to_be_removed:
revenue, data_to_be_removed = remove_parent_with_no_child(revenue, period_list)
revenue = adjust_account(revenue, period_list)
return copy.deepcopy(revenue)
def remove_parent_with_no_child(data, period_list):
data_to_be_removed = False
for parent in data:
if 'is_group' in parent and parent.get("is_group") == 1:
have_child = False
for child in data:
if 'parent_account' in child and child.get("parent_account") == parent.get("account"):
have_child = True
break
if not have_child:
data_to_be_removed = True
data.remove(parent)
return data, data_to_be_removed
def adjust_account(data, period_list, consolidated= False):
leaf_nodes = [item for item in data if item['is_group'] == 0]
totals = {}
for node in leaf_nodes:
set_total(node, node["total"], data, totals)
for d in data:
for period in period_list:
key = period if consolidated else period.key
d[key] = totals[d["account"]]
d['total'] = totals[d["account"]]
return data
def set_total(node, value, complete_list, totals):
if not totals.get(node['account']):
totals[node["account"]] = 0
totals[node["account"]] += value
parent = node['parent_account']
if not parent == '':
return set_total(next(item for item in complete_list if item['account'] == parent), value, complete_list, totals)
def get_profit(gross_income, gross_expense, period_list, company, profit_type, currency=None, consolidated=False):
profit_loss = {
"account_name": "'" + _(profit_type) + "'",
"account": "'" + _(profit_type) + "'",
"warn_if_negative": True,
"currency": currency or frappe.get_cached_value('Company', company, "default_currency")
}
has_value = False
for period in period_list:
key = period if consolidated else period.key
profit_loss[key] = flt(gross_income[0].get(key, 0)) - flt(gross_expense[0].get(key, 0))
if profit_loss[key]:
has_value=True
if has_value:
return profit_loss
def get_net_profit(non_gross_income, gross_income, gross_expense, non_gross_expense, period_list, company, currency=None, consolidated=False):
profit_loss = {
"account_name": "'" + _("Net Profit") + "'",
"account": "'" + _("Net Profit") + "'",
"warn_if_negative": True,
"currency": currency or frappe.get_cached_value('Company', company, "default_currency")
}
has_value = False
for period in period_list:
key = period if consolidated else period.key
total_income = flt(gross_income[0].get(key, 0)) + flt(non_gross_income[0].get(key, 0))
total_expense = flt(gross_expense[0].get(key, 0)) + flt(non_gross_expense[0].get(key, 0))
profit_loss[key] = flt(total_income) - flt(total_expense)
if profit_loss[key]:
has_value=True
if has_value:
return profit_loss

View File

@@ -6,7 +6,7 @@ import frappe
from frappe import _, scrub
from erpnext.stock.utils import get_incoming_rate
from erpnext.controllers.queries import get_match_cond
from frappe.utils import flt
from frappe.utils import flt, cint
def execute(filters=None):
@@ -106,11 +106,14 @@ class GrossProfitGenerator(object):
self.grouped = {}
self.grouped_data = []
self.currency_precision = cint(frappe.db.get_default("currency_precision")) or 3
self.float_precision = cint(frappe.db.get_default("float_precision")) or 2
for row in self.si_list:
if self.skip_row(row, self.product_bundles):
continue
row.base_amount = flt(row.base_net_amount)
row.base_amount = flt(row.base_net_amount, self.currency_precision)
product_bundles = []
if row.update_stock:
@@ -122,22 +125,23 @@ class GrossProfitGenerator(object):
# get buying amount
if row.item_code in product_bundles:
row.buying_amount = self.get_buying_amount_from_product_bundle(row,
product_bundles[row.item_code])
row.buying_amount = flt(self.get_buying_amount_from_product_bundle(row,
product_bundles[row.item_code]), self.currency_precision)
else:
row.buying_amount = self.get_buying_amount(row, row.item_code)
row.buying_amount = flt(self.get_buying_amount(row, row.item_code),
self.currency_precision)
# get buying rate
if row.qty:
row.buying_rate = row.buying_amount / row.qty
row.base_rate = row.base_amount / row.qty
row.buying_rate = flt(row.buying_amount / row.qty, self.float_precision)
row.base_rate = flt(row.base_amount / row.qty, self.float_precision)
else:
row.buying_rate, row.base_rate = 0.0, 0.0
# calculate gross profit
row.gross_profit = row.base_amount - row.buying_amount
row.gross_profit = flt(row.base_amount - row.buying_amount, self.currency_precision)
if row.base_amount:
row.gross_profit_percent = (row.gross_profit / row.base_amount) * 100.0
row.gross_profit_percent = flt((row.gross_profit / row.base_amount) * 100.0, self.currency_precision)
else:
row.gross_profit_percent = 0.0
@@ -156,8 +160,8 @@ class GrossProfitGenerator(object):
new_row = row
else:
new_row.qty += row.qty
new_row.buying_amount += row.buying_amount
new_row.base_amount += row.base_amount
new_row.buying_amount += flt(row.buying_amount, self.currency_precision)
new_row.base_amount += flt(row.base_amount, self.currency_precision)
new_row = self.set_average_rate(new_row)
self.grouped_data.append(new_row)
else:
@@ -167,18 +171,19 @@ class GrossProfitGenerator(object):
returned_item_rows = self.returned_invoices[row.parent][row.item_code]
for returned_item_row in returned_item_rows:
row.qty += returned_item_row.qty
row.base_amount += returned_item_row.base_amount
row.buying_amount = row.qty * row.buying_rate
row.base_amount += flt(returned_item_row.base_amount, self.currency_precision)
row.buying_amount = flt(row.qty * row.buying_rate, self.currency_precision)
if row.qty or row.base_amount:
row = self.set_average_rate(row)
self.grouped_data.append(row)
def set_average_rate(self, new_row):
new_row.gross_profit = new_row.base_amount - new_row.buying_amount
new_row.gross_profit_percent = ((new_row.gross_profit / new_row.base_amount) * 100.0) \
new_row.gross_profit = flt(new_row.base_amount - new_row.buying_amount, self.currency_precision)
new_row.gross_profit_percent = flt(((new_row.gross_profit / new_row.base_amount) * 100.0), self.currency_precision) \
if new_row.base_amount else 0
new_row.buying_rate = (new_row.buying_amount / new_row.qty) if new_row.qty else 0
new_row.base_rate = (new_row.base_amount / new_row.qty) if new_row.qty else 0
new_row.buying_rate = flt(new_row.buying_amount / new_row.qty, self.float_precision) if new_row.qty else 0
new_row.base_rate = flt(new_row.base_amount / new_row.qty, self.float_precision) if new_row.qty else 0
return new_row
def get_returned_invoice_items(self):
@@ -211,7 +216,7 @@ class GrossProfitGenerator(object):
if packed_item.get("parent_detail_docname")==row.item_row:
buying_amount += self.get_buying_amount(row, packed_item.item_code)
return buying_amount
return flt(buying_amount, self.currency_precision)
def get_buying_amount(self, row, item_code):
# IMP NOTE

View File

@@ -54,8 +54,10 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
delivery_note, d.income_account, d.cost_center, d.stock_qty, d.stock_uom
]
row += [(d.base_net_rate * d.qty)/d.stock_qty, d.base_net_amount] \
if d.stock_uom != d.uom and d.stock_qty != 0 else [d.base_net_rate, d.base_net_amount]
if d.stock_uom != d.uom and d.stock_qty:
row += [(d.base_net_rate * d.qty)/d.stock_qty, d.base_net_amount]
else:
row += [d.base_net_rate, d.base_net_amount]
total_tax = 0
for tax in tax_columns:
@@ -108,13 +110,13 @@ def get_conditions(filters):
conditions += """ and exists(select name from `tabSales Invoice Payment`
where parent=`tabSales Invoice`.name
and ifnull(`tabSales Invoice Payment`.mode_of_payment, '') = %(mode_of_payment)s)"""
if filters.get("warehouse"):
conditions += """ and exists(select name from `tabSales Invoice Item`
where parent=`tabSales Invoice`.name
and ifnull(`tabSales Invoice Item`.warehouse, '') = %(warehouse)s)"""
if filters.get("brand"):
conditions += """ and exists(select name from `tabSales Invoice Item`
where parent=`tabSales Invoice`.name
@@ -131,10 +133,10 @@ def get_conditions(filters):
def get_items(filters, additional_query_columns):
conditions = get_conditions(filters)
match_conditions = frappe.build_match_conditions("Sales Invoice")
if match_conditions:
match_conditions = " and {0} ".format(match_conditions)
if additional_query_columns:
additional_query_columns = ', ' + ', '.join(additional_query_columns)

View File

@@ -133,6 +133,13 @@ def get_columns(filters):
"options": filters.get("based_on"),
"width": 300
},
{
"fieldname": "currency",
"label": _("Currency"),
"fieldtype": "Link",
"options": "Currency",
"hidden": 1
},
{
"fieldname": "income",
"label": _("Income"),
@@ -153,13 +160,6 @@ def get_columns(filters):
"fieldtype": "Currency",
"options": "currency",
"width": 120
},
{
"fieldname": "currency",
"label": _("Currency"),
"fieldtype": "Link",
"options": "Currency",
"hidden": 1
}
]
@@ -191,4 +191,4 @@ def set_gl_entries_by_account(company, from_date, to_date, based_on, gl_entries_
for entry in gl_entries:
gl_entries_by_account.setdefault(entry.based_on, []).append(entry)
return gl_entries_by_account
return gl_entries_by_account

View File

@@ -66,8 +66,8 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
total_tax += tax_amount
row.append(tax_amount)
# total tax, grand total, outstanding amount & rounded total
row += [total_tax, inv.base_grand_total, flt(inv.base_grand_total, 2), inv.outstanding_amount]
# total tax, grand total, rounded total & outstanding amount
row += [total_tax, inv.base_grand_total, flt(inv.base_grand_total, 0), inv.outstanding_amount]
data.append(row)
return columns, data

View File

@@ -35,9 +35,9 @@ frappe.query_reports["Supplier Ledger Summary"] = {
},
{
"fieldname":"party",
"label": __("Customer"),
"label": __("Supplier"),
"fieldtype": "Link",
"options": "Customer",
"options": "Supplier",
on_change: () => {
var party = frappe.query_report.get_filter_value('party');
if (party) {

View File

@@ -55,12 +55,15 @@ def get_result(filters):
supplier = supplier_map[d]
tds_doc = tds_docs[supplier.tax_withholding_category]
account = [i.account for i in tds_doc.accounts if i.company == filters.company][0]
account_list = [i.account for i in tds_doc.accounts if i.company == filters.company]
if account_list:
account = account_list[0]
for k in gle_map[d]:
if k.party == supplier_map[d] and k.credit > 0:
total_amount_credited += k.credit
elif k.account == account and k.credit > 0:
elif account_list and k.account == account and k.credit > 0:
tds_deducted = k.credit
total_amount_credited += k.credit

View File

@@ -544,14 +544,14 @@ def fix_total_debit_credit():
(dr_or_cr, dr_or_cr, '%s', '%s', '%s', dr_or_cr),
(d.diff, d.voucher_type, d.voucher_no))
def get_stock_and_account_difference(account_list=None, posting_date=None):
def get_stock_and_account_difference(account_list=None, posting_date=None, company=None):
from erpnext.stock.utils import get_stock_value_on
from erpnext.stock import get_warehouse_account_map
if not posting_date: posting_date = nowdate()
difference = {}
warehouse_account = get_warehouse_account_map()
warehouse_account = get_warehouse_account_map(company)
for warehouse, account_data in iteritems(warehouse_account):
if account_data.get('account') in account_list:

View File

@@ -33,7 +33,7 @@ class Asset(AccountsController):
self.validate_in_use_date()
self.set_status()
self.update_stock_movement()
if not self.booked_fixed_asset:
if not self.booked_fixed_asset and not is_cwip_accounting_disabled():
self.make_gl_entries()
def on_cancel(self):
@@ -71,14 +71,15 @@ class Asset(AccountsController):
if not flt(self.gross_purchase_amount):
frappe.throw(_("Gross Purchase Amount is mandatory"), frappe.MandatoryError)
if not self.is_existing_asset and not (self.purchase_receipt or self.purchase_invoice):
frappe.throw(_("Please create purchase receipt or purchase invoice for the item {0}").
format(self.item_code))
if not is_cwip_accounting_disabled():
if not self.is_existing_asset and not (self.purchase_receipt or self.purchase_invoice):
frappe.throw(_("Please create purchase receipt or purchase invoice for the item {0}").
format(self.item_code))
if (not self.purchase_receipt and self.purchase_invoice
and not frappe.db.get_value('Purchase Invoice', self.purchase_invoice, 'update_stock')):
frappe.throw(_("Update stock must be enable for the purchase invoice {0}").
format(self.purchase_invoice))
if (not self.purchase_receipt and self.purchase_invoice
and not frappe.db.get_value('Purchase Invoice', self.purchase_invoice, 'update_stock')):
frappe.throw(_("Update stock must be enable for the purchase invoice {0}").
format(self.purchase_invoice))
if not self.calculate_depreciation:
return
@@ -255,7 +256,7 @@ class Asset(AccountsController):
def get_depreciation_amount(self, depreciable_value, total_number_of_depreciations, row):
percentage_value = 100.0 if row.depreciation_method == 'Written Down Value' else 200.0
factor = percentage_value / total_number_of_depreciations
factor = percentage_value / cint(total_number_of_depreciations)
depreciation_amount = flt(depreciable_value * factor / 100, 0)
value_after_depreciation = flt(depreciable_value) - depreciation_amount
@@ -275,7 +276,7 @@ class Asset(AccountsController):
flt(row.expected_value_after_useful_life)) / (cint(row.total_number_of_depreciations) -
cint(self.number_of_depreciations_booked)) * prorata_temporis
else:
depreciation_amount = self.get_depreciation_amount(depreciable_value, row)
depreciation_amount = self.get_depreciation_amount(depreciable_value, row.total_number_of_depreciations, row)
return depreciation_amount
@@ -404,6 +405,9 @@ def update_maintenance_status():
asset.set_status('Out of Order')
def make_post_gl_entry():
if is_cwip_accounting_disabled():
return
assets = frappe.db.sql_list(""" select name from `tabAsset`
where ifnull(booked_fixed_asset, 0) = 0 and available_for_use_date = %s""", nowdate())
@@ -551,3 +555,6 @@ def make_journal_entry(asset_name):
})
return je
def is_cwip_accounting_disabled():
return cint(frappe.db.get_single_value("Asset Settings", "disable_cwip_accounting"))

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
@@ -14,10 +15,12 @@
"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": "depreciation_options",
"fieldtype": "Section Break",
"hidden": 0,
@@ -40,14 +43,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": "schedule_based_on_fiscal_year",
"fieldtype": "Check",
"hidden": 0,
@@ -70,10 +76,12 @@
"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,
@@ -81,6 +89,7 @@
"default": "360",
"depends_on": "eval:doc.schedule_based_on_fiscal_year",
"description": "This value is used for pro-rata temporis calculation",
"fetch_if_empty": 0,
"fieldname": "number_of_days_in_fiscal_year",
"fieldtype": "Data",
"hidden": 0,
@@ -103,6 +112,40 @@
"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": "disable_cwip_accounting",
"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": "Disable CWIP Accounting",
"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
}
],
@@ -116,7 +159,7 @@
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"modified": "2018-01-05 10:10:39.803255",
"modified": "2019-03-08 10:44:41.924547",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset Settings",
@@ -125,7 +168,6 @@
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
@@ -145,7 +187,6 @@
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
@@ -171,5 +212,6 @@
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0
"track_seen": 0,
"track_views": 0
}

View File

@@ -388,9 +388,10 @@ def make_purchase_invoice(source_name, target_doc=None):
item = get_item_defaults(target.item_code, source_parent.company)
item_group = get_item_group_defaults(target.item_code, source_parent.company)
target.cost_center = frappe.db.get_value("Project", obj.project, "cost_center") \
or item.get("buying_cost_center") \
or item_group.get("buying_cost_center")
target.cost_center = (obj.cost_center
or frappe.db.get_value("Project", obj.project, "cost_center")
or item.get("buying_cost_center")
or item_group.get("buying_cost_center"))
doc = get_mapped_doc("Purchase Order", source_name, {
"Purchase Order": {

View File

@@ -325,7 +325,7 @@ def get_data():
{
"type": "help",
"label": _("Sales Order to Payment"),
"youtube_id": "7AMq4lqkN4A"
"youtube_id": "1eP90MWoDQM"
},
{
"type": "help",

View File

@@ -116,6 +116,12 @@ class AccountsController(TransactionBase):
self.validate_non_invoice_documents_schedule()
def before_print(self):
if self.doctype in ['Journal Entry', 'Payment Entry', 'Sales Invoice', 'Purchase Invoice']:
self.gl_entries = frappe.get_list("GL Entry", filters={
"voucher_type": self.doctype,
"voucher_no": self.name
}, fields=["account", "party_type", "party", "debit", "credit", "remarks"])
if self.doctype in ['Purchase Order', 'Sales Order', 'Sales Invoice', 'Purchase Invoice',
'Supplier Quotation', 'Purchase Receipt', 'Delivery Note', 'Quotation']:
if self.get("group_same_items"):
@@ -1138,11 +1144,3 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name):
@erpnext.allow_regional
def validate_regional(doc):
pass
@erpnext.allow_regional
def on_submit_regional(doc):
pass
@erpnext.allow_regional
def on_cancel_regional(doc):
pass

View File

@@ -172,8 +172,8 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals
or tabItem.item_code LIKE %(txt)s
or tabItem.item_group LIKE %(txt)s
or tabItem.item_name LIKE %(txt)s
or tabItem.item_code IN (select parent from `tabItem Barcode` where barcode LIKE %(txt)s
{description_cond}))
or tabItem.item_code IN (select parent from `tabItem Barcode` where barcode LIKE %(txt)s)
{description_cond})
{fcond} {mcond}
order by
if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999),

View File

@@ -2,8 +2,9 @@
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
import frappe, erpnext
from frappe import _
from frappe.model.meta import get_field_precision
from frappe.utils import flt, get_datetime, format_datetime
class StockOverReturnError(frappe.ValidationError): pass
@@ -116,6 +117,10 @@ def validate_quantity(doc, args, ref, valid_items, already_returned_items):
already_returned_data = already_returned_items.get(args.item_code) or {}
company_currency = erpnext.get_company_currency(doc.company)
stock_qty_precision = get_field_precision(frappe.get_meta(doc.doctype + " Item")
.get_field("stock_qty"), company_currency)
for column in fields:
returned_qty = flt(already_returned_data.get(column, 0)) if len(already_returned_data) > 0 else 0
@@ -126,7 +131,7 @@ def validate_quantity(doc, args, ref, valid_items, already_returned_items):
reference_qty = ref.get(column) * ref.get("conversion_factor", 1.0)
current_stock_qty = args.get(column) * args.get("conversion_factor", 1.0)
max_returnable_qty = flt(reference_qty) - returned_qty
max_returnable_qty = flt(reference_qty, stock_qty_precision) - returned_qty
label = column.replace('_', ' ').title()
if reference_qty:
@@ -135,7 +140,7 @@ def validate_quantity(doc, args, ref, valid_items, already_returned_items):
elif returned_qty >= reference_qty and args.get(column):
frappe.throw(_("Item {0} has already been returned")
.format(args.item_code), StockOverReturnError)
elif abs(current_stock_qty) > max_returnable_qty:
elif abs(flt(current_stock_qty, stock_qty_precision)) > max_returnable_qty:
frappe.throw(_("Row # {0}: Cannot return more than {1} for Item {2}")
.format(args.idx, max_returnable_qty, args.item_code), StockOverReturnError)

View File

@@ -26,7 +26,7 @@ class StockController(AccountsController):
delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
if cint(erpnext.is_perpetual_inventory_enabled(self.company)):
warehouse_account = get_warehouse_account_map()
warehouse_account = get_warehouse_account_map(self.company)
if self.docstatus==1:
if not gl_entries:
@@ -36,7 +36,7 @@ class StockController(AccountsController):
if repost_future_gle:
items, warehouses = self.get_items_and_warehouses()
update_gl_entries_after(self.posting_date, self.posting_time, warehouses, items,
warehouse_account)
warehouse_account, company=self.company)
elif self.doctype in ['Purchase Receipt', 'Purchase Invoice'] and self.docstatus == 1:
gl_entries = []
gl_entries = self.get_asset_gl_entry(gl_entries)
@@ -46,7 +46,7 @@ class StockController(AccountsController):
default_cost_center=None):
if not warehouse_account:
warehouse_account = get_warehouse_account_map()
warehouse_account = get_warehouse_account_map(self.company)
sle_map = self.get_stock_ledger_details()
voucher_details = self.get_voucher_details(default_expense_account, default_cost_center, sle_map)
@@ -199,7 +199,8 @@ class StockController(AccountsController):
def make_adjustment_entry(self, expected_gle, voucher_obj):
from erpnext.accounts.utils import get_stock_and_account_difference
account_list = [d.account for d in expected_gle]
acc_diff = get_stock_and_account_difference(account_list, expected_gle[0].posting_date)
acc_diff = get_stock_and_account_difference(account_list,
expected_gle[0].posting_date, self.company)
cost_center = self.get_company_default("cost_center")
stock_adjustment_account = self.get_company_default("stock_adjustment_account")
@@ -361,13 +362,13 @@ class StockController(AccountsController):
frappe.get_doc("Blanket Order", blanket_order).update_ordered_qty()
def update_gl_entries_after(posting_date, posting_time, for_warehouses=None, for_items=None,
warehouse_account=None):
warehouse_account=None, company=None):
def _delete_gl_entries(voucher_type, voucher_no):
frappe.db.sql("""delete from `tabGL Entry`
where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
if not warehouse_account:
warehouse_account = get_warehouse_account_map()
warehouse_account = get_warehouse_account_map(company)
future_stock_vouchers = get_future_stock_vouchers(posting_date, posting_time, for_warehouses, for_items)
gle = get_voucherwise_gl_entries(future_stock_vouchers, posting_date)

View File

@@ -162,6 +162,8 @@ def create_item_code(amazon_item_json, sku):
igroup.parent_item_group = mws_settings.item_group
igroup.insert()
item.append("item_defaults", {'company':mws_settings.company})
item.insert(ignore_permissions=True)
create_item_price(amazon_item_json, item.item_code)
@@ -213,7 +215,7 @@ def get_orders(after_date):
fulfillment_channels=["MFN", "AFN"],
lastupdatedafter=after_date,
orderstatus=statuses,
max_results='20')
max_results='50')
while True:
orders_list = []
@@ -432,8 +434,8 @@ def get_order_items(market_place_order_id):
return final_order_items
def get_item_code(order_item):
asin = order_item.ASIN
item_code = frappe.db.get_value("Item", {"amazon_item_code": asin}, "item_code")
sku = order_item.SellerSKU
item_code = frappe.db.get_value("Item", {"item_code": sku}, "item_code")
if item_code:
return item_code
@@ -451,11 +453,16 @@ def get_charges_and_fees(market_place_order_id):
shipment_item_list = return_as_list(shipment_event.ShipmentEvent.ShipmentItemList.ShipmentItem)
for shipment_item in shipment_item_list:
charges = return_as_list(shipment_item.ItemChargeList.ChargeComponent)
fees = return_as_list(shipment_item.ItemFeeList.FeeComponent)
charges, fees = []
if 'ItemChargeList' in shipment_item.keys():
charges = return_as_list(shipment_item.ItemChargeList.ChargeComponent)
if 'ItemFeeList' in shipment_item.keys():
fees = return_as_list(shipment_item.ItemFeeList.FeeComponent)
for charge in charges:
if(charge.ChargeType != "Principal"):
if(charge.ChargeType != "Principal") and float(charge.ChargeAmount.CurrencyAmount) != 0:
charge_account = get_account(charge.ChargeType)
charges_fees.get("charges").append({
"charge_type":"Actual",
@@ -465,13 +472,14 @@ def get_charges_and_fees(market_place_order_id):
})
for fee in fees:
fee_account = get_account(fee.FeeType)
charges_fees.get("fees").append({
"charge_type":"Actual",
"account_head": fee_account,
"tax_amount": fee.FeeAmount.CurrencyAmount,
"description": fee.FeeType + " for " + shipment_item.SellerSKU
})
if float(fee.FeeAmount.CurrencyAmount) != 0:
fee_account = get_account(fee.FeeType)
charges_fees.get("fees").append({
"charge_type":"Actual",
"account_head": fee_account,
"tax_amount": fee.FeeAmount.CurrencyAmount,
"description": fee.FeeType + " for " + shipment_item.SellerSKU
})
return charges_fees

View File

@@ -65,7 +65,7 @@ class WoocommerceSettings(Document):
if not frappe.get_value("Item Group",{"name": "WooCommerce Products"}):
item_group = frappe.new_doc("Item Group")
item_group.item_group_name = "WooCommerce Products"
item_group.parent_item_group = "All Item Groups"
item_group.parent_item_group = _("All Item Groups")
item_group.save()

View File

@@ -49,7 +49,7 @@ frappe.ui.form.on('Healthcare Service Unit Type', {
var disable = function(frm){
var doc = frm.doc;
frappe.call({
method: "erpnext.healthcare.doctype.healthcare_service_unit_type.healthcare_service_unit_type.disable_enable",
method: "erpnext.healthcare.doctype.healthcare_service_unit_type.healthcare_service_unit_type.disable_enable",
args: {status: 1, doc_name: doc.name, item: doc.item, is_billable: doc.is_billable},
callback: function(){
cur_frm.reload_doc();
@@ -60,7 +60,7 @@ var disable = function(frm){
var enable = function(frm){
var doc = frm.doc;
frappe.call({
method: "erpnext.healthcare.doctype.healthcare_service_unit_type.healthcare_service_unit_type.disable_enable",
method: "erpnext.healthcare.doctype.healthcare_service_unit_type.healthcare_service_unit_type.disable_enable",
args: {status: 0, doc_name: doc.name, item: doc.item, is_billable: doc.is_billable},
callback: function(){
cur_frm.reload_doc();

View File

@@ -111,7 +111,7 @@ def change_item_code(item, item_code, doc_name):
frappe.db.set_value("Healthcare Service Unit Type", doc_name, "item_code", item_code)
@frappe.whitelist()
def disable_enable(status, doc_name, item, is_billable):
def disable_enable(status, doc_name, item=None, is_billable=None):
frappe.db.set_value("Healthcare Service Unit Type", doc_name, "disabled", status)
if(is_billable == 1):
frappe.db.set_value("Item", item, "disabled", status)

View File

@@ -27,6 +27,8 @@ doctype_js = {
welcome_email = "erpnext.setup.utils.welcome_email"
connect = "erpnext.check_branch_compatibility_with_frappe"
# setup wizard
setup_wizard_requires = "assets/erpnext/js/setup_wizard.js"
setup_wizard_stages = "erpnext.setup.setup_wizard.setup_wizard.get_setup_stages"
@@ -202,7 +204,8 @@ doc_events = {
"validate": "erpnext.portal.doctype.products_settings.products_settings.home_page_is_products"
},
"Sales Invoice": {
"on_submit": "erpnext.regional.france.utils.create_transaction_log",
"on_submit": ["erpnext.regional.france.utils.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"
},
"Payment Entry": {
@@ -305,7 +308,5 @@ regional_overrides = {
'Italy': {
'erpnext.controllers.taxes_and_totals.update_itemised_tax_data': 'erpnext.regional.italy.utils.update_itemised_tax_data',
'erpnext.controllers.accounts_controller.validate_regional': 'erpnext.regional.italy.utils.sales_invoice_validate',
'erpnext.controllers.accounts_controller.on_submit_regional': 'erpnext.regional.italy.utils.sales_invoice_on_submit',
'erpnext.controllers.accounts_controller.on_cancel_regional': 'erpnext.regional.italy.utils.sales_invoice_on_cancel'
}
}

View File

@@ -11,16 +11,14 @@ from frappe.utils import getdate, date_diff
class AdditionalSalary(Document):
def validate(self):
self.validate_dates()
if self.amount <= 0:
frappe.throw(_("Amount should be greater than zero."))
if self.amount < 0:
frappe.throw(_("Amount should not be less than zero."))
def validate_dates(self):
date_of_joining, relieving_date = frappe.db.get_value("Employee", self.employee,
["date_of_joining", "relieving_date"])
if date_of_joining and getdate(self.payroll_date) < getdate(date_of_joining):
frappe.throw(_("Payroll date can not be less than employee's joining date"))
elif relieving_date and getdate(self.payroll_date) > getdate(relieving_date):
frappe.throw(_("To date can not greater than employee's relieving date"))
def get_amount(self, sal_start_date, sal_end_date):
start_date = getdate(sal_start_date)

View File

@@ -35,6 +35,7 @@ $.extend(cur_frm.cscript, new erpnext.hr.ExpenseClaimController({frm: cur_frm}))
cur_frm.add_fetch('employee', 'company', 'company');
cur_frm.add_fetch('employee','employee_name','employee_name');
cur_frm.add_fetch('expense_type','description','description');
cur_frm.cscript.onload = function(doc) {
if (doc.__islocal) {

View File

@@ -1,366 +1,378 @@
{
"allow_copy": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2013-02-22 01:27:46",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"editable_grid": 1,
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2013-02-22 01:27:46",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"editable_grid": 1,
"fields": [
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "expense_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": "Expense Date",
"length": 0,
"no_copy": 0,
"oldfieldname": "expense_date",
"oldfieldtype": "Date",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "150px",
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "expense_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": "Expense Date",
"length": 0,
"no_copy": 0,
"oldfieldname": "expense_date",
"oldfieldtype": "Date",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "150px",
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"unique": 0,
"width": "150px"
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_2",
"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,
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_2",
"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_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "expense_type",
"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": "Expense Claim Type",
"length": 0,
"no_copy": 0,
"oldfieldname": "expense_type",
"oldfieldtype": "Link",
"options": "Expense Claim Type",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "150px",
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "expense_type",
"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": "Expense Claim Type",
"length": 0,
"no_copy": 0,
"oldfieldname": "expense_type",
"oldfieldtype": "Link",
"options": "Expense Claim Type",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "150px",
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"unique": 0,
"width": "150px"
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "expense_type",
"fieldname": "default_account",
"fieldtype": "Link",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Default Account",
"length": 0,
"no_copy": 0,
"options": "Account",
"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,
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "expense_type",
"fieldname": "default_account",
"fieldtype": "Link",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Default Account",
"length": 0,
"no_copy": 0,
"options": "Account",
"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
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_4",
"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,
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_4",
"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
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_from": "expense_type.description",
"fieldname": "description",
"fieldtype": "Text Editor",
"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": "Description",
"length": 0,
"no_copy": 0,
"oldfieldname": "description",
"oldfieldtype": "Small Text",
"options": "",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "300px",
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_from": "",
"fieldname": "description",
"fieldtype": "Text Editor",
"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": "Description",
"length": 0,
"no_copy": 0,
"oldfieldname": "description",
"oldfieldtype": "Small Text",
"options": "",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "300px",
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"unique": 0,
"width": "300px"
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_6",
"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,
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_6",
"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
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "claim_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Claim Amount",
"length": 0,
"no_copy": 0,
"oldfieldname": "claim_amount",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "150px",
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "claim_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Claim Amount",
"length": 0,
"no_copy": 0,
"oldfieldname": "claim_amount",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "150px",
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"unique": 0,
"width": "150px"
},
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_8",
"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,
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_8",
"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_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "sanctioned_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Sanctioned Amount",
"length": 0,
"no_copy": 1,
"oldfieldname": "sanctioned_amount",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "150px",
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "sanctioned_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1,
"in_standard_filter": 0,
"label": "Sanctioned Amount",
"length": 0,
"no_copy": 1,
"oldfieldname": "sanctioned_amount",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"print_width": "150px",
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0,
"unique": 0,
"width": "150px"
}
],
"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": "2018-05-16 22:42:56.727863",
"modified_by": "Administrator",
"module": "HR",
"name": "Expense Claim Detail",
"owner": "harshada@webnotestech.com",
"permissions": [],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 0,
"track_seen": 0
],
"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": "2019-02-24 08:41:36.122565",
"modified_by": "Administrator",
"module": "HR",
"name": "Expense Claim Detail",
"owner": "harshada@webnotestech.com",
"permissions": [],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 0,
"track_seen": 0,
"track_views": 0
}

View File

@@ -399,6 +399,19 @@ def get_leave_balance_on(employee, leave_type, date, allocation_records=None, do
return flt(allocation.total_leaves_allocated) - (flt(leaves_taken) + flt(leaves_encashed))
def get_total_allocated_leaves(employee, leave_type, date):
filters= {
'from_date': ['<=', date],
'to_date': ['>=', date],
'docstatus': 1,
'leave_type': leave_type,
'employee': employee
}
leave_allocation_records = frappe.db.get_all('Leave Allocation', filters=filters, fields=['total_leaves_allocated'])
return flt(leave_allocation_records[0]['total_leaves_allocated']) if leave_allocation_records else flt(0)
def get_leaves_for_period(employee, leave_type, from_date, to_date, status, docname=None):
leave_applications = frappe.db.sql("""
select name, employee, leave_type, from_date, to_date, total_leave_days
@@ -487,7 +500,6 @@ def get_events(start, end, filters=None):
add_block_dates(events, start, end, employee, company)
add_holidays(events, start, end, employee, company)
return events
def add_department_leaves(events, start, end, employee, company):
@@ -500,19 +512,32 @@ def add_department_leaves(events, start, end, employee, company):
department_employees = frappe.db.sql_list("""select name from tabEmployee where department=%s
and company=%s""", (department, company))
match_conditions = "and employee in (\"%s\")" % '", "'.join(department_employees)
add_leaves(events, start, end, match_conditions=match_conditions)
filter_conditions = " and employee in (\"%s\")" % '", "'.join(department_employees)
add_leaves(events, start, end, filter_conditions=filter_conditions)
def add_leaves(events, start, end, filter_conditions=None):
conditions = []
if not cint(frappe.db.get_value("HR Settings", None, "show_leaves_of_all_department_members_in_calendar")):
from frappe.desk.reportview import build_match_conditions
match_conditions = build_match_conditions("Leave Application")
if match_conditions:
conditions.append(match_conditions)
def add_leaves(events, start, end, match_conditions=None):
query = """select name, from_date, to_date, employee_name, half_day,
status, employee, docstatus
from `tabLeave Application` where
from_date <= %(end)s and to_date >= %(start)s <= to_date
and docstatus < 2
and status!="Rejected" """
and status!='Rejected' """
if match_conditions:
query += match_conditions
if conditions:
query += ' and ' + ' and '.join(conditions)
if filter_conditions:
query += filter_conditions
for d in frappe.db.sql(query, {"start":start, "end": end}, as_dict=True):
e = {

View File

@@ -441,7 +441,7 @@ class SalarySlip(TransactionBase):
def calculate_net_pay(self):
if self.salary_structure:
self.calculate_component_amounts()
disable_rounded_total = cint(frappe.db.get_value("Global Defaults", None, "disable_rounded_total"))
precision = frappe.defaults.get_global_default("currency_precision")
self.total_deduction = 0
@@ -452,10 +452,10 @@ class SalarySlip(TransactionBase):
self.set_loan_repayment()
self.net_pay = flt(self.gross_pay) - (flt(self.total_deduction) + flt(self.total_loan_repayment))
self.net_pay = (flt(self.gross_pay) - (flt(self.total_deduction) + flt(self.total_loan_repayment))) * flt(self.payment_days / self.total_working_days)
self.rounded_total = rounded(self.net_pay,
self.precision("net_pay") if disable_rounded_total else 0)
if self.net_pay < 0:
frappe.throw(_("Net Pay cannnot be negative"))

View File

@@ -20,6 +20,7 @@ class StaffingPlan(Document):
self.total_estimated_budget = 0
for detail in self.get("staffing_details"):
self.set_vacancies(detail)
self.validate_overlap(detail)
self.validate_with_subsidiary_plans(detail)
self.validate_with_parent_plan(detail)
@@ -39,6 +40,15 @@ class StaffingPlan(Document):
else: detail.vacancies = detail.number_of_positions = detail.total_estimated_cost = 0
self.total_estimated_budget += detail.total_estimated_cost
def set_vacancies(self, row):
if not row.vacancies:
current_openings = 0
for field in ['current_count', 'current_openings']:
if row.get(field):
current_openings += row.get(field)
row.vacancies = row.number_of_positions - current_openings
def validate_overlap(self, staffing_plan_detail):
# Validate if any submitted Staffing Plan exist for any Designations in this plan
# and spd.vacancies>0 ?

View File

@@ -18,7 +18,7 @@ class TestStaffingPlan(unittest.TestCase):
if frappe.db.exists("Staffing Plan", "Test"):
return
staffing_plan = frappe.new_doc("Staffing Plan")
staffing_plan.company = "_Test Company 3"
staffing_plan.company = "_Test Company 10"
staffing_plan.name = "Test"
staffing_plan.from_date = nowdate()
staffing_plan.to_date = add_days(nowdate(), 10)
@@ -67,7 +67,7 @@ class TestStaffingPlan(unittest.TestCase):
if frappe.db.exists("Staffing Plan", "Test 1"):
return
staffing_plan = frappe.new_doc("Staffing Plan")
staffing_plan.company = "_Test Company 3"
staffing_plan.company = "_Test Company 10"
staffing_plan.name = "Test 1"
staffing_plan.from_date = nowdate()
staffing_plan.to_date = add_days(nowdate(), 10)
@@ -85,11 +85,11 @@ def _set_up():
make_company()
def make_company():
if frappe.db.exists("Company", "_Test Company 3"):
if frappe.db.exists("Company", "_Test Company 10"):
return
company = frappe.new_doc("Company")
company.company_name = "_Test Company 3"
company.abbr = "_TC3"
company.company_name = "_Test Company 10"
company.abbr = "_TC10"
company.parent_company = "_Test Company"
company.default_currency = "INR"
company.country = "India"

View File

@@ -5,21 +5,21 @@ from __future__ import unicode_literals
import frappe
from frappe import _
from erpnext.hr.doctype.leave_application.leave_application \
import get_leave_allocation_records, get_leave_balance_on, get_approved_leaves_for_period
import get_leave_allocation_records, get_leave_balance_on, get_approved_leaves_for_period, get_total_allocated_leaves
def execute(filters=None):
leave_types = frappe.db.sql_list("select name from `tabLeave Type` order by name asc")
columns = get_columns(leave_types)
data = get_data(filters, leave_types)
return columns, data
def get_columns(leave_types):
columns = [
_("Employee") + ":Link/Employee:150",
_("Employee Name") + "::200",
_("Employee") + ":Link/Employee:150",
_("Employee Name") + "::200",
_("Department") +"::150"
]
@@ -27,18 +27,18 @@ def get_columns(leave_types):
columns.append(_(leave_type) + " " + _("Opening") + ":Float:160")
columns.append(_(leave_type) + " " + _("Taken") + ":Float:160")
columns.append(_(leave_type) + " " + _("Balance") + ":Float:160")
return columns
def get_data(filters, leave_types):
user = frappe.session.user
allocation_records_based_on_to_date = get_leave_allocation_records(filters.to_date)
allocation_records_based_on_from_date = get_leave_allocation_records(filters.from_date)
active_employees = frappe.get_all("Employee",
filters = { "status": "Active", "company": filters.company},
active_employees = frappe.get_all("Employee",
filters = { "status": "Active", "company": filters.company},
fields = ["name", "employee_name", "department", "user_id"])
data = []
for employee in active_employees:
leave_approvers = get_approvers(employee.department)
@@ -51,8 +51,7 @@ def get_data(filters, leave_types):
filters.from_date, filters.to_date)
# opening balance
opening = get_leave_balance_on(employee.name, leave_type, filters.from_date,
allocation_records_based_on_from_date.get(employee.name, frappe._dict()))
opening = get_total_allocated_leaves(employee.name, leave_type, filters.to_date)
# closing balance
closing = get_leave_balance_on(employee.name, leave_type, filters.to_date,
@@ -61,7 +60,7 @@ def get_data(filters, leave_types):
row += [opening, leaves_taken, closing]
data.append(row)
return data
def get_approvers(department):

View File

@@ -41,12 +41,19 @@ class MaintenanceVisit(TransactionBase):
work_done = nm and nm[0][3] or ''
else:
status = 'Open'
mntc_date = ''
service_person = ''
work_done = ''
mntc_date = None
service_person = None
work_done = None
frappe.db.sql("update `tabWarranty Claim` set resolution_date=%s, resolved_by=%s, resolution_details=%s, status=%s where name =%s",(mntc_date,service_person,work_done,status,d.prevdoc_docname))
wc_doc = frappe.get_doc('Warranty Claim', d.prevdoc_docname)
wc_doc.update({
'resolution_date': mntc_date,
'resolved_by': service_person,
'resolution_details': work_done,
'status': status
})
wc_doc.db_update()
def check_if_last_visit(self):
"""check if last maintenance visit against same sales order/ Warranty Claim"""

View File

@@ -580,7 +580,7 @@ def get_list_context(context):
context.title = _("Bill of Materials")
# context.introduction = _('Boms')
def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_items=0, include_non_stock_items=False):
def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_items=0, include_non_stock_items=False, fetch_qty_in_stock_uom=True):
item_dict = {}
# Did not use qty_consumed_per_unit in the query, as it leads to rounding loss
@@ -588,7 +588,7 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite
bom_item.item_code,
bom_item.idx,
item.item_name,
sum(bom_item.stock_qty/ifnull(bom.quantity, 1)) * %(qty)s as qty,
sum(bom_item.{qty_field}/ifnull(bom.quantity, 1)) * %(qty)s as qty,
item.description,
item.image,
item.stock_uom,
@@ -616,16 +616,18 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1, fetch_scrap_ite
query = query.format(table="BOM Explosion Item",
where_conditions="",
is_stock_item=is_stock_item,
qty_field="stock_qty",
select_columns = """, bom_item.source_warehouse, bom_item.operation, bom_item.include_item_in_manufacturing,
(Select idx from `tabBOM Item` where item_code = bom_item.item_code and parent = %(parent)s ) as idx""")
(Select idx from `tabBOM Item` where item_code = bom_item.item_code and parent = %(parent)s limit 1) as idx""")
items = frappe.db.sql(query, { "parent": bom, "qty": qty, "bom": bom, "company": company }, as_dict=True)
elif fetch_scrap_items:
query = query.format(table="BOM Scrap Item", where_conditions="", select_columns=", bom_item.idx", is_stock_item=is_stock_item)
query = query.format(table="BOM Scrap Item", where_conditions="", select_columns=", bom_item.idx", is_stock_item=is_stock_item, qty_field="stock_qty")
items = frappe.db.sql(query, { "qty": qty, "bom": bom, "company": company }, as_dict=True)
else:
query = query.format(table="BOM Item", where_conditions="", is_stock_item=is_stock_item,
select_columns = ", bom_item.source_warehouse, bom_item.idx, bom_item.operation, bom_item.include_item_in_manufacturing")
qty_field="stock_qty" if fetch_qty_in_stock_uom else "qty",
select_columns = ", bom_item.uom, bom_item.conversion_factor, bom_item.source_warehouse, bom_item.idx, bom_item.operation, bom_item.include_item_in_manufacturing")
items = frappe.db.sql(query, { "qty": qty, "bom": bom, "company": company }, as_dict=True)
for item in items:
@@ -706,8 +708,11 @@ def get_children(doctype, parent=None, is_root=False, **filters):
def get_boms_in_bottom_up_order(bom_no=None):
def _get_parent(bom_no):
return frappe.db.sql_list("""select distinct parent from `tabBOM Item`
where bom_no = %s and docstatus=1 and parenttype='BOM'""", bom_no)
return frappe.db.sql_list("""
select distinct bom_item.parent from `tabBOM Item` bom_item
where bom_item.bom_no = %s and bom_item.docstatus=1 and bom_item.parenttype='BOM'
and exists(select bom.name from `tabBOM` bom where bom.name=bom_item.parent and bom.is_active=1)
""", bom_no)
count = 0
bom_list = []
@@ -715,9 +720,10 @@ def get_boms_in_bottom_up_order(bom_no=None):
bom_list.append(bom_no)
else:
# get all leaf BOMs
bom_list = frappe.db.sql_list("""select name from `tabBOM` bom where docstatus=1
and not exists(select bom_no from `tabBOM Item`
where parent=bom.name and ifnull(bom_no, '')!='')""")
bom_list = frappe.db.sql_list("""select name from `tabBOM` bom
where docstatus=1 and is_active=1
and not exists(select bom_no from `tabBOM Item`
where parent=bom.name and ifnull(bom_no, '')!='')""")
while(count < len(bom_list)):
for child_bom in _get_parent(bom_list[count]):

View File

@@ -78,6 +78,39 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "operation",
"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": "Item operation",
"length": 0,
"no_copy": 0,
"options": "Operation",
"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,
@@ -893,6 +926,38 @@
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "allow_alternative_item",
"fieldtype": "Check",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Allow Alternative Item",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
@@ -958,71 +1023,6 @@
"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": "operation",
"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": "Item operation",
"length": 0,
"no_copy": 0,
"options": "Operation",
"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": "allow_alternative_item",
"fieldtype": "Check",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Allow Alternative Item",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}
],
"has_web_view": 0,
@@ -1035,7 +1035,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2018-11-23 15:05:55.187136",
"modified": "2019-02-21 19:19:54.872459",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "BOM Item",
@@ -1050,4 +1050,4 @@
"track_changes": 0,
"track_seen": 0,
"track_views": 0
}
}

View File

@@ -18,20 +18,27 @@ frappe.ui.form.on('Job Card', {
}
if (frm.doc.docstatus == 0) {
if (!frm.doc.actual_start_date || !frm.doc.actual_end_date) {
frm.trigger("make_dashboard");
}
frm.trigger("make_dashboard");
if (!frm.doc.actual_start_date) {
if (!frm.doc.job_started) {
frm.add_custom_button(__("Start Job"), () => {
frm.set_value('actual_start_date', frappe.datetime.now_datetime());
let row = frappe.model.add_child(frm.doc, 'Job Card Time Log', 'time_logs');
row.from_time = frappe.datetime.now_datetime();
frm.set_value('job_started', 1);
frm.set_value('started_time' , row.from_time);
frm.save();
});
} else if (!frm.doc.actual_end_date) {
} else {
frm.add_custom_button(__("Complete Job"), () => {
frm.set_value('actual_end_date', frappe.datetime.now_datetime());
frm.save();
frm.savesubmit();
let completed_time = frappe.datetime.now_datetime();
frm.doc.time_logs.forEach(d => {
if (d.from_time && !d.to_time) {
d.to_time = completed_time;
frm.set_value('started_time' , '');
frm.set_value('job_started', 0);
frm.save();
}
})
});
}
}
@@ -53,8 +60,8 @@ frappe.ui.form.on('Job Card', {
var section = frm.dashboard.add_section(timer);
if (frm.doc.actual_start_date) {
let currentIncrement = moment(frappe.datetime.now_datetime()).diff(moment(frm.doc.actual_start_date),"seconds");
if (frm.doc.started_time) {
let currentIncrement = moment(frappe.datetime.now_datetime()).diff(moment(frm.doc.started_time),"seconds");
initialiseTimer();
function initialiseTimer() {

View File

@@ -21,6 +21,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "work_order",
"fieldtype": "Link",
"hidden": 0,
@@ -54,6 +55,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "bom_no",
"fieldtype": "Link",
"hidden": 0,
@@ -87,6 +89,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "workstation",
"fieldtype": "Link",
"hidden": 0,
@@ -120,6 +123,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "operation",
"fieldtype": "Link",
"hidden": 0,
@@ -153,6 +157,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_4",
"fieldtype": "Column Break",
"hidden": 0,
@@ -185,6 +190,7 @@
"collapsible": 0,
"columns": 0,
"default": "Today",
"fetch_if_empty": 0,
"fieldname": "posting_date",
"fieldtype": "Date",
"hidden": 0,
@@ -217,6 +223,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
@@ -250,6 +257,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "for_quantity",
"fieldtype": "Float",
"hidden": 0,
@@ -282,6 +290,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "wip_warehouse",
"fieldtype": "Link",
"hidden": 0,
@@ -315,6 +324,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "timing_detail",
"fieldtype": "Section Break",
"hidden": 0,
@@ -347,6 +357,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "employee",
"fieldtype": "Link",
"hidden": 0,
@@ -380,7 +391,74 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "time_in_mins",
"fetch_if_empty": 0,
"fieldname": "time_logs",
"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": "Time Logs",
"length": 0,
"no_copy": 0,
"options": "Job Card Time Log",
"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_if_empty": 0,
"fieldname": "section_break_13",
"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
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "total_completed_qty",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -389,7 +467,7 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Time In Mins",
"label": "Total Completed Qty",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -412,7 +490,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_13",
"fetch_if_empty": 0,
"fieldname": "column_break_15",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
@@ -443,8 +522,9 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "actual_start_date",
"fieldtype": "Datetime",
"fetch_if_empty": 0,
"fieldname": "total_time_in_mins",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -452,46 +532,14 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Actual Start Date",
"label": "Total Time in Mins",
"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": "actual_end_date",
"fieldtype": "Datetime",
"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 End Date",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
@@ -507,6 +555,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "section_break_8",
"fieldtype": "Section Break",
"hidden": 0,
@@ -539,6 +588,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "items",
"fieldtype": "Table",
"hidden": 0,
@@ -572,6 +622,7 @@
"bold": 0,
"collapsible": 1,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "more_information",
"fieldtype": "Section Break",
"hidden": 0,
@@ -604,6 +655,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "operation_id",
"fieldtype": "Data",
"hidden": 1,
@@ -637,6 +689,7 @@
"collapsible": 0,
"columns": 0,
"default": "0",
"fetch_if_empty": 0,
"fieldname": "transferred_qty",
"fieldtype": "Float",
"hidden": 0,
@@ -670,6 +723,7 @@
"collapsible": 0,
"columns": 0,
"default": "0",
"fetch_if_empty": 0,
"fieldname": "requested_qty",
"fieldtype": "Float",
"hidden": 0,
@@ -702,6 +756,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "project",
"fieldtype": "Link",
"hidden": 0,
@@ -735,6 +790,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "remarks",
"fieldtype": "Small Text",
"hidden": 0,
@@ -767,6 +823,7 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_20",
"fieldtype": "Column Break",
"hidden": 0,
@@ -799,6 +856,7 @@
"collapsible": 0,
"columns": 0,
"default": "Open",
"fetch_if_empty": 0,
"fieldname": "status",
"fieldtype": "Select",
"hidden": 0,
@@ -832,6 +890,73 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "job_started",
"fieldtype": "Check",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Job Started",
"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": "started_time",
"fieldtype": "Datetime",
"hidden": 1,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Started Time",
"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": "amended_from",
"fieldtype": "Link",
"hidden": 0,
@@ -868,7 +993,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2018-12-13 17:23:57.986381",
"modified": "2019-03-10 17:38:37.499871",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Job Card",

View File

@@ -11,44 +11,56 @@ from frappe.model.document import Document
class JobCard(Document):
def validate(self):
self.validate_actual_dates()
self.set_time_in_mins()
self.validate_time_logs()
self.set_status()
def validate_actual_dates(self):
if get_datetime(self.actual_start_date) > get_datetime(self.actual_end_date):
frappe.throw(_("Actual start date must be less than actual end date"))
def validate_time_logs(self):
self.total_completed_qty = 0.0
self.total_time_in_mins = 0.0
if not (self.employee and self.actual_start_date and self.actual_end_date):
return
for d in self.get('time_logs'):
if get_datetime(d.from_time) > get_datetime(d.to_time):
frappe.throw(_("Row {0}: From time must be less than to time").format(d.idx))
data = frappe.db.sql(""" select name from `tabJob Card`
where
((%(actual_start_date)s > actual_start_date and %(actual_start_date)s < actual_end_date) or
(%(actual_end_date)s > actual_start_date and %(actual_end_date)s < actual_end_date) or
(%(actual_start_date)s <= actual_start_date and %(actual_end_date)s >= actual_end_date)) and
name != %(name)s and employee = %(employee)s and docstatus =1
""", {
'actual_start_date': self.actual_start_date,
'actual_end_date': self.actual_end_date,
'employee': self.employee,
'name': self.name
}, as_dict=1)
data = self.get_overlap_for(d)
if data:
frappe.throw(_("Row {0}: From Time and To Time of {1} is overlapping with {2}")
.format(d.idx, self.name, data.name))
if data:
frappe.throw(_("Start date and end date is overlapping with the job card <a href='#Form/Job Card/{0}'>{1}</a>")
.format(data[0].name, data[0].name))
if d.from_time and d.to_time:
d.time_in_mins = time_diff_in_hours(d.to_time, d.from_time) * 60
self.total_time_in_mins += d.time_in_mins
def set_time_in_mins(self):
if self.actual_start_date and self.actual_end_date:
self.time_in_mins = time_diff_in_hours(self.actual_end_date, self.actual_start_date) * 60
if d.completed_qty:
self.total_completed_qty += d.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
(
(%(from_time)s > jctl.from_time and %(from_time)s < jctl.to_time) or
(%(to_time)s > jctl.from_time and %(to_time)s < jctl.to_time) or
(%(from_time)s <= jctl.from_time and %(to_time)s >= jctl.to_time))
and jctl.name!=%(name)s
and jc.name!=%(parent)s
and jc.docstatus < 2
and jc.employee = %(employee)s """,
{
"from_time": args.from_time,
"to_time": args.to_time,
"name": args.name or "No Name",
"parent": args.parent or "No Name",
"employee": self.employee
}, as_dict=True)
return existing[0] if existing else None
def get_required_items(self):
if not self.get('work_order'):
return
doc = frappe.get_doc('Work Order', self.get('work_order'))
if doc.transfer_material_against == 'Work Order' and doc.skip_transfer:
if doc.transfer_material_against == 'Work Order' or doc.skip_transfer:
return
for d in doc.required_items:
@@ -67,36 +79,51 @@ class JobCard(Document):
})
def on_submit(self):
self.validate_dates()
self.validate_job_card()
self.update_work_order()
self.set_transferred_qty()
def validate_dates(self):
if not self.actual_start_date and not self.actual_end_date:
frappe.throw(_("Actual start date and actual end date is mandatory"))
def on_cancel(self):
self.update_work_order()
self.set_transferred_qty()
def validate_job_card(self):
if not self.time_logs:
frappe.throw(_("Time logs are required for job card {0}").format(self.name))
if self.total_completed_qty <= 0.0:
frappe.throw(_("Total completed qty must be greater than zero"))
if self.total_completed_qty > self.for_quantity:
frappe.throw(_("Total completed qty can not be greater than for quantity"))
def update_work_order(self):
if not self.work_order:
return
data = frappe.db.get_value("Job Card", {'docstatus': 1, 'operation_id': self.operation_id},
['sum(time_in_mins)', 'min(actual_start_date)', 'max(actual_end_date)', 'sum(for_quantity)'])
for_quantity, time_in_mins = 0, 0
from_time_list, to_time_list = [], []
if data:
time_in_mins, actual_start_date, actual_end_date, for_quantity = data
for d in frappe.get_all('Job Card',
filters = {'docstatus': 1, 'operation_id': self.operation_id}):
doc = frappe.get_doc('Job Card', d.name)
for_quantity += doc.total_completed_qty
time_in_mins += doc.total_time_in_mins
for time_log in doc.time_logs:
from_time_list.append(time_log.from_time)
to_time_list.append(time_log.to_time)
if for_quantity:
wo = frappe.get_doc('Work Order', self.work_order)
for data in wo.operations:
if data.name == self.operation_id:
data.completed_qty = for_quantity
data.actual_operation_time = time_in_mins
data.actual_start_time = actual_start_date
data.actual_end_time = actual_end_date
data.actual_start_time = min(from_time_list)
data.actual_end_time = max(to_time_list)
wo.flags.ignore_validate_update_after_submit = True
wo.update_operation_status()
@@ -132,9 +159,11 @@ class JobCard(Document):
break
if completed:
job_cards = frappe.get_all('Job Card', filters = {'work_order': self.work_order,
job_cards = frappe.get_all('Job Card', filters = {'work_order': self.work_order,
'docstatus': ('!=', 2)}, fields = 'sum(transferred_qty) as qty', group_by='operation_id')
qty = min([d.qty for d in job_cards])
if job_cards:
qty = min([d.qty for d in job_cards])
doc.db_set('material_transferred_for_manufacturing', qty)
@@ -147,7 +176,7 @@ class JobCard(Document):
2: "Cancelled"
}[self.docstatus or 0]
if self.actual_start_date:
if self.time_logs:
self.status = 'Work In Progress'
if (self.docstatus == 1 and

View File

@@ -0,0 +1,208 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2019-03-08 23:56:43.187569",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"editable_grid": 1,
"engine": "InnoDB",
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "from_time",
"fieldtype": "Datetime",
"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": "From Time",
"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,
"fetch_if_empty": 0,
"fieldname": "to_time",
"fieldtype": "Datetime",
"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": "To Time",
"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,
"fetch_if_empty": 0,
"fieldname": "column_break_2",
"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,
"fetch_if_empty": 0,
"fieldname": "time_in_mins",
"fieldtype": "Float",
"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": "Time In Mins",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "0",
"fetch_if_empty": 0,
"fieldname": "completed_qty",
"fieldtype": "Float",
"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": "Completed Qty",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}
],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2019-03-10 17:08:46.504910",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Job Card Time Log",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified",
"sort_order": "ASC",
"track_changes": 1,
"track_seen": 0,
"track_views": 0
}

View File

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

View File

@@ -302,6 +302,19 @@ class TestWorkOrder(unittest.TestCase):
self.assertEqual(len(ste.additional_costs), 1)
self.assertEqual(ste.total_additional_costs, 1000)
def test_job_card(self):
data = frappe.get_cached_value('BOM',
{'docstatus': 1, 'with_operations': 1, 'company': '_Test Company'}, ['name', 'item'])
if data:
bom, bom_item = data
bom_doc = frappe.get_doc('BOM', bom)
work_order = make_wo_order_test_record(item=bom_item, qty=1, bom_no=bom)
job_cards = frappe.get_all('Job Card', filters = {'work_order': work_order})
self.assertEqual(len(job_cards), len(bom_doc.operations))
def test_work_order_with_non_transfer_item(self):
items = {'Finished Good Transfer Item': 1, '_Test FG Item': 1, '_Test FG Item 1': 0}
for item, allow_transfer in items.items():
@@ -346,7 +359,7 @@ def make_wo_order_test_record(**args):
wo_order = frappe.new_doc("Work Order")
wo_order.production_item = args.production_item or args.item or args.item_code or "_Test FG Item"
wo_order.bom_no = frappe.db.get_value("BOM", {"item": wo_order.production_item,
wo_order.bom_no = args.bom_no or frappe.db.get_value("BOM", {"item": wo_order.production_item,
"is_active": 1, "is_default": 1})
wo_order.qty = args.qty or 10
wo_order.wip_warehouse = args.wip_warehouse or "_Test Warehouse - _TC"

View File

@@ -282,6 +282,10 @@ class WorkOrder(Document):
total_bundle_qty = frappe.db.sql(""" select sum(qty) from
`tabProduct Bundle Item` where parent = %s""", (frappe.db.escape(self.product_bundle_item)))[0][0]
if not total_bundle_qty:
# product bundle is 0 (product bundle allows 0 qty for items)
total_bundle_qty = 1
cond = "product_bundle_item = %s" if self.product_bundle_item else "production_item = %s"
qty = frappe.db.sql(""" select sum(qty) from

View File

@@ -571,7 +571,7 @@ execute:frappe.delete_doc_if_exists("Page", "sales-analytics")
execute:frappe.delete_doc_if_exists("Page", "purchase-analytics")
execute:frappe.delete_doc_if_exists("Page", "stock-analytics")
execute:frappe.delete_doc_if_exists("Page", "production-analytics")
erpnext.patches.v11_0.ewaybill_fields_gst_india #2018-11-13 #2019-01-09
erpnext.patches.v11_0.ewaybill_fields_gst_india #2018-11-13 #2019-01-09 #2019-04-01
erpnext.patches.v11_0.drop_column_max_days_allowed
erpnext.patches.v11_0.change_healthcare_desktop_icons
erpnext.patches.v10_0.update_user_image_in_employee
@@ -587,4 +587,6 @@ erpnext.patches.v11_1.setup_guardian_role
execute:frappe.delete_doc('DocType', 'Notification Control')
erpnext.patches.v11_0.remove_barcodes_field_from_copy_fields_to_variants
erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019
erpnext.patches.v11_0.make_italian_localization_fields
erpnext.patches.v11_0.make_italian_localization_fields # 26-03-2019
erpnext.patches.v11_1.make_job_card_time_logs
erpnext.patches.v11_1.set_variant_based_on

View File

@@ -27,5 +27,5 @@ def execute():
'parent': item.name,
'parentfield': 'barcodes'
}).insert()
except frappe.DuplicateEntryError:
except (frappe.DuplicateEntryError, frappe.UniqueValidationError):
continue

View File

@@ -6,23 +6,32 @@ from erpnext.regional.italy.setup import make_custom_fields, setup_report
from erpnext.regional.italy import state_codes
import frappe
def execute():
company = frappe.get_all('Company', filters = {'country': 'Italy'})
if not company:
return
company = frappe.get_all('Company', filters = {'country': 'Italy'})
if not company:
return
frappe.reload_doc('regional', 'report', 'electronic_invoice_register')
make_custom_fields()
setup_report()
make_custom_fields()
setup_report()
# Set state codes
condition = ""
for state, code in state_codes.items():
condition += " when '{0}' then '{1}'".format(frappe.db.escape(state), frappe.db.escape(code))
# Set state codes
condition = ""
for state, code in state_codes.items():
condition += " when '{0}' then '{1}'".format(frappe.db.escape(state), frappe.db.escape(code))
if condition:
condition = "state_code = (case state {0} end),".format(condition)
if condition:
frappe.db.sql("""
UPDATE tabAddress set state_code = (case state {condition} end)
WHERE country in ('Italy', 'Italia', 'Italian Republic', 'Repubblica Italiana')
""".format(condition=condition))
frappe.db.sql("""
UPDATE tabAddress set {condition} country_code = UPPER(ifnull((select code
from `tabCountry` where name = `tabAddress`.country), ''))
where country_code is null and state_code is null
""".format(condition=condition))
frappe.db.sql("""
UPDATE `tabSales Invoice Item` si, `tabSales Order` so
set si.customer_po_no = so.po_no, si.customer_po_date = so.po_date
WHERE
si.sales_order = so.name and so.po_no is not null
""")

View File

@@ -0,0 +1,29 @@
# 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
def execute():
frappe.reload_doc('manufacturing', 'doctype', 'job_card_time_log')
if (frappe.db.table_exists("Job Card")
and frappe.get_meta("Job Card").has_field("actual_start_date")):
time_logs = []
for d in frappe.get_all('Job Card',
fields = ["actual_start_date", "actual_end_date", "time_in_mins", "name", "for_quantity"],
filters = {'docstatus': ("<", 2)}):
if d.actual_start_date:
time_logs.append([d.actual_start_date, d.actual_end_date, d.time_in_mins,
d.for_quantity, d.name, 'Job Card', 'time_logs', frappe.generate_hash("", 10)])
if time_logs:
frappe.db.sql(""" INSERT INTO
`tabJob Card Time Log`
(from_time, to_time, time_in_mins, completed_qty, parent, parenttype, parentfield, name)
values {values}
""".format(values = ','.join(['%s'] * len(time_logs))), tuple(time_logs))
frappe.reload_doc('manufacturing', 'doctype', 'job_card')
frappe.db.sql(""" update `tabJob Card` set total_completed_qty = for_quantity,
total_time_in_mins = time_in_mins where docstatus < 2 """)

View File

@@ -0,0 +1,11 @@
# 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
def execute():
frappe.db.sql("""update tabItem set variant_based_on = 'Item Attribute'
where ifnull(variant_based_on, '') = ''
and (has_variants=1 or ifnull(variant_of, '') != '')
""")

View File

@@ -10,14 +10,15 @@ from erpnext.controllers.stock_controller import update_gl_entries_after
def execute():
company_list = frappe.db.sql_list("""Select name from tabCompany where enable_perpetual_inventory = 1""")
frappe.reload_doc('accounts', 'doctype', 'sales_invoice')
frappe.reload_doctype("Purchase Invoice")
frappe.reload_doctype("Purchase Invoice")
wh_account = get_warehouse_account_map()
for pi in frappe.get_all("Purchase Invoice", fields=["name", "company"], filters={"docstatus": 1, "update_stock": 1}):
if pi.company in company_list:
pi_doc = frappe.get_doc("Purchase Invoice", pi.name)
items, warehouses = pi_doc.get_items_and_warehouses()
update_gl_entries_after(pi_doc.posting_date, pi_doc.posting_time, warehouses, items, wh_account)
update_gl_entries_after(pi_doc.posting_date, pi_doc.posting_time,
warehouses, items, wh_account, company = pi.company)
frappe.db.commit()

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