Compare commits

..

225 Commits

Author SHA1 Message Date
Anand Doshi
701b994671 Merge branch 'develop' 2015-08-19 14:34:30 +05:30
Anand Doshi
139283fbf7 bumped to version 5.7.0 2015-08-19 15:04:30 +06:00
Anand Doshi
89cac6c8a6 Merge pull request #3909 from nabinhait/testcase1
Testcase and Patch Fix
2015-08-19 14:33:50 +05:30
Nabin Hait
3922823bd6 [fix] Test case fixed for purchase cost against project 2015-08-19 14:23:13 +05:30
Nabin Hait
6ce72c5b07 [fix] Update project cost for draft project only 2015-08-19 14:15:28 +05:30
Anand Doshi
548f7e8c74 [change-log] for v5.7.0 2015-08-19 13:31:35 +05:30
Anand Doshi
e270c7261d [minor] project cost 2015-08-19 13:02:30 +05:30
Anand Doshi
4765d75b83 [minor] fix typo 2015-08-19 12:50:44 +05:30
Anand Doshi
8af567a229 [minor] import error 2015-08-19 12:10:03 +05:30
Anand Doshi
6e82d7b50d Merge pull request #3899 from nabinhait/project
[fix] Purchase cost against project
2015-08-19 11:58:12 +05:30
Nabin Hait
fa5fcf5405 [fix] Purchase cost against project 2015-08-19 11:56:23 +05:30
Anand Doshi
ffca81dbc1 [fix] added test cases and fixes to Item Variants 2015-08-19 11:52:05 +05:30
Rushabh Mehta
b52724f5b9 [minor] should fix #3884 2015-08-19 11:41:41 +05:30
Anand Doshi
b82961e8dd Merge pull request #3898 from nabinhait/reserved_qty
[fix][patch] Reserved Qty logic fixed and reposted for existing items
2015-08-19 11:22:03 +05:30
Nabin Hait
1826791891 [fix][patch] Reserved Qty logic fixed and reposted for existing items 2015-08-19 11:00:00 +05:30
Anand Doshi
df469c3e02 Merge pull request #3901 from rmehta/notify
[minor] notify stop/unstop (merge after merging realtime in frappe)
2015-08-19 10:31:41 +05:30
Anand Doshi
79cb7bffab Merge pull request #3906 from anandpdoshi/item-variant-fixes
Fixes to Item Variant Attribute
2015-08-19 10:31:11 +05:30
Anand Doshi
90fd6fee23 [fix] generate item code for variant 2015-08-19 10:21:24 +05:30
Anand Doshi
2538e51887 Fixes to Item Variant Attribute. Fixes #3905 2015-08-19 09:33:07 +05:30
Anand Doshi
1d2bde3b56 Merge pull request #3900 from nabinhait/fix6
Note files deleted, shifted to frappe repo
2015-08-18 18:35:17 +05:30
Anand Doshi
cf2c624c03 Merge pull request #3902 from rmehta/pos-print
[enhancement] POS print after save #3853
2015-08-18 18:32:04 +05:30
Rushabh Mehta
ad9156a6ae [enhancement] POS print after save #385:wq:wq 2015-08-18 18:05:43 +05:30
Anand Doshi
2f01f96ae3 [fix] [patch] item template attributes 2015-08-18 17:52:50 +05:30
Anand Doshi
2235caebee Merge pull request #3903 from anandpdoshi/fix-item-variant-attribute
patch and rename Variant Attribute to Item Variant Attribute
2015-08-18 17:44:21 +05:30
Anand Doshi
afbe39a559 [fix] patch and rename Variant Attribute to Item Variant Attribute 2015-08-18 17:30:44 +05:30
Rushabh Mehta
1d1f1b06d9 [minor] notify stop/unstop 2015-08-18 17:26:50 +05:30
Anand Doshi
b6c5b21dd0 [fix] [patch] typo and remove Bulk SMS 2015-08-18 16:27:20 +05:30
Anand Doshi
71c33823f6 Merge pull request #3806 from neilLasrado/item-variants
Improvements in Item Variants
2015-08-18 16:13:10 +05:30
Anand Doshi
82988be79f Merge pull request #3846 from rmehta/add-to-learn
Learn module
2015-08-18 12:10:03 +05:30
Nabin Hait
5b19dc3a5f Note files deleted, shifted to frappe repo 2015-08-18 11:46:53 +05:30
Anand Doshi
09ba897297 [fix] [patch] Item Template Attributes - migration from v4 and v5 2015-08-17 19:21:29 +05:30
Anand Doshi
2e0d90a7b9 [fix] travis 2015-08-17 17:58:53 +05:30
Anand Doshi
ddcc766a55 bumped to version 5.6.4 2015-08-17 17:58:53 +05:30
Nabin Hait
9495adc9d7 Update patches.txt 2015-08-17 17:58:53 +05:30
Nabin Hait
26bc1a58af [fix] Get Balance only if account or party mentioned 2015-08-17 17:58:53 +05:30
Nabin Hait
91e1077e4c [fix] precision issue in stock entry 2015-08-17 17:58:52 +05:30
Nabin Hait
3278ea177d [fix] Additional Costs patch fixed for version 4 to 5 migration 2015-08-17 17:58:52 +05:30
Nabin Hait
f1b2032466 Included Party and reference name in Journal Entry Account grid view 2015-08-17 17:58:52 +05:30
Nabin Hait
1c98886c85 [fix] Get stock and rate function restored 2015-08-17 17:58:52 +05:30
Anand Doshi
92d8a9b2d5 bumped to version 5.6.3 2015-08-17 17:58:52 +05:30
Anand Doshi
fd67ebf66d Show Communication in CRM 2015-08-17 17:58:51 +05:30
Anand Doshi
720ccabfe9 [fix] Journal Entry Reference Name query 2015-08-17 17:58:51 +05:30
Anand Doshi
d4cb1045ed [fix] Show 'Backflush Raw Materials Based On' in Manufacturing Settings 2015-08-17 17:58:51 +05:30
Anand Doshi
4f3eadc488 bumped to version 5.6.2 2015-08-17 17:58:51 +05:30
Anand Doshi
5dc7ff1355 [hotfix] [patch] cleanup journal entry 2015-08-17 17:58:51 +05:30
Anand Doshi
bfbf768daa [hotfix] [patch] cleanup journal entry 2015-08-17 17:58:51 +05:30
Anand Doshi
b334065977 [hotfix] translation in es.csv 2015-08-17 17:58:50 +05:30
Anand Doshi
d74d121199 [hotfix] [report] payment period based on invoice date 2015-08-17 17:58:50 +05:30
Anand Doshi
d726ce5e9e [fix] travis 2015-08-17 15:14:25 +05:30
Anand Doshi
5e35590bc9 Merge pull request #3871 from anandpdoshi/append-to-communication
Show Communication in CRM
2015-08-17 14:48:08 +05:30
Anand Doshi
41793bddd2 Merge branch 'develop' 2015-08-17 14:36:48 +05:30
Anand Doshi
b23049a55e bumped to version 5.6.4 2015-08-17 15:06:48 +06:00
Nabin Hait
99bf6c0927 Update patches.txt 2015-08-17 14:31:29 +05:30
Anand Doshi
b528c5cad2 Merge pull request #3893 from nabinhait/fix2
[fix] Get Balance only if account or party mentioned
2015-08-17 14:29:03 +05:30
Nabin Hait
dc76823a81 [fix] Get Balance only if account or party mentioned 2015-08-17 14:28:19 +05:30
Anand Doshi
862c36832a Merge pull request #3892 from nabinhait/fix1
[fix] Get stock and rate function restored
2015-08-17 14:26:01 +05:30
Anand Doshi
bd9dad96ae Merge pull request #3894 from nabinhait/fix3
Included Party and reference name in Journal Entry Account grid view
2015-08-17 14:24:52 +05:30
Anand Doshi
8ca933a83f Merge pull request #3895 from nabinhait/fix4
[fix] Additional Costs patch fixed for version 4 to 5 migration
2015-08-17 14:24:30 +05:30
Anand Doshi
f0107db3ca Merge pull request #3896 from nabinhait/fix5
[fix] precision issue in stock entry
2015-08-17 14:20:51 +05:30
Nabin Hait
c01342190c [fix] precision issue in stock entry 2015-08-17 14:18:44 +05:30
Nabin Hait
f763c1af25 [fix] Additional Costs patch fixed for version 4 to 5 migration 2015-08-17 12:06:53 +05:30
Nabin Hait
cbfd387c0b Included Party and reference name in Journal Entry Account grid view 2015-08-17 11:42:48 +05:30
Nabin Hait
ac07b1cc07 [fix] Get stock and rate function restored 2015-08-17 10:50:30 +05:30
Anand Doshi
4a1319289e Merge branch 'develop' 2015-08-14 17:53:41 +05:30
Anand Doshi
c5a43e46d8 bumped to version 5.6.3 2015-08-14 18:23:40 +06:00
Anand Doshi
1a2e6bf718 Show Communication in CRM 2015-08-14 17:51:14 +05:30
Anand Doshi
04dfd7b98f [fix] Journal Entry Reference Name query 2015-08-14 17:34:43 +05:30
Anand Doshi
85e0e87f01 [fix] Show 'Backflush Raw Materials Based On' in Manufacturing Settings 2015-08-14 12:55:27 +05:30
Anand Doshi
e7a3c7c5ab Merge branch 'develop' 2015-08-14 12:21:37 +05:30
Anand Doshi
acc32fe7f7 bumped to version 5.6.2 2015-08-14 12:51:37 +06:00
Anand Doshi
487454e817 [hotfix] [patch] cleanup journal entry 2015-08-14 12:17:34 +05:30
Anand Doshi
dc278a7427 [hotfix] [patch] cleanup journal entry 2015-08-14 12:05:50 +05:30
Anand Doshi
698ee434c0 [hotfix] translation in es.csv 2015-08-14 11:45:43 +05:30
Neil Trini Lasrado
68f66a7e8b fixed Test Cases 2015-08-13 17:34:25 +05:30
Anand Doshi
e116cb596c [hotfix] [report] payment period based on invoice date 2015-08-13 17:25:20 +05:30
Neil Trini Lasrado
6cce304b27 Changelog added 2015-08-13 16:19:55 +05:30
Neil Trini Lasrado
9710eede00 Fixed Test Cases 2015-08-13 16:19:55 +05:30
Neil Trini Lasrado
62dba50e9b Multiple Fixes 2015-08-13 16:18:55 +05:30
Neil Trini Lasrado
cdc060cb7c Allow Editing variant attribute in Variant. Add validation to check duplication. 2015-08-13 16:17:36 +05:30
Neil Trini Lasrado
b9b49632f2 Added patch to fetch Item Template Attributes 2015-08-13 16:17:36 +05:30
Neil Trini Lasrado
ebf4cbeae3 Fixed Manage Variant 2015-08-13 16:17:01 +05:30
Neil Trini Lasrado
8b608c9043 Search Variants added to Item Master
Added feature for Variants to hande numeric values
2015-08-13 16:17:01 +05:30
Anand Doshi
169c3ed09d Merge branch 'develop' 2015-08-13 15:54:41 +05:30
Anand Doshi
d7ba618b92 bumped to version 5.6.1 2015-08-13 16:24:41 +06:00
Anand Doshi
0a37f5575f [hotfix] [patch] stock entry additional cost for docstatus < 2 2015-08-13 15:53:40 +05:30
Anand Doshi
b1bae1bde8 Merge branch 'develop' 2015-08-13 15:44:03 +05:30
Anand Doshi
bcfd4277f4 bumped to version 5.6.0 2015-08-13 16:14:03 +06:00
Anand Doshi
2b6915519f [change-log] 2015-08-13 15:36:18 +05:30
Anand Doshi
5eb84352ec Merge pull request #3868 from nabinhait/price_list_rate
[fix] Reset price list rate based on Pricing Rule type
2015-08-13 15:10:08 +05:30
Anand Doshi
1580bf9ca4 Merge pull request #3869 from rmehta/pricing-rule-layout
[minor] pricing rule layout
2015-08-13 15:08:54 +05:30
Rushabh Mehta
4c4c534dcd [minor] pricing rule layout 2015-08-13 15:00:54 +05:30
Nabin Hait
0da11f1b10 [fix] Reset price list rate based on Pricing Rule type 2015-08-13 14:58:19 +05:30
Anand Doshi
cb4784c940 Merge pull request #3822 from neilLasrado/item-uom
Changed UOM validation for Item Master
2015-08-13 14:36:37 +05:30
Nabin Hait
4c8ee279f3 Merge branch 'bobzz-zone-patch-7' into develop 2015-08-13 14:15:45 +05:30
Nabin Hait
58aea1f819 minor fix 2015-08-13 14:15:27 +05:30
Nabin Hait
760bfb27d0 Merge branch 'patch-7' of https://github.com/bobzz-zone/erpnext into bobzz-zone-patch-7 2015-08-13 14:14:26 +05:30
Anand Doshi
c0c4e866be Merge branch 'nabinhait-item_description' into develop
Conflicts:
	erpnext/patches.txt
2015-08-13 13:40:33 +05:30
Anand Doshi
b16474e606 [minor] Reload Journal Entry Account 2015-08-13 13:38:22 +05:30
Rushabh Mehta
bbed8972c3 [minor] pincode label changed to postal code, #3770 2015-08-13 13:38:21 +05:30
Rushabh Mehta
35f94dfbc6 [patch] cleanup_journal_entry 2015-08-13 13:38:21 +05:30
Rushabh Mehta
832fa2e76b [patch] cleanup_journal_entry 2015-08-13 13:38:21 +05:30
Rushabh Mehta
682ce24f8c [patch] cleanup_journal_entry 2015-08-13 13:38:21 +05:30
Nabin Hait
9f02b08427 minor fix 2015-08-13 13:38:20 +05:30
Rushabh Mehta
2645980f62 [patch] cleanup_journal_entry 2015-08-13 13:38:20 +05:30
Anand Doshi
ae1a91835e Merge pull request #3866 from nabinhait/fix3
[fix] fraction issue in gl entry
2015-08-13 13:35:57 +05:30
Anand Doshi
094755415a Merge pull request #3867 from rmehta/salary-slip-fix
[fix] salary slip to consider disable rounded total, #3792
2015-08-13 13:35:02 +05:30
Anand Doshi
746eae4d1a [minor] Reload Journal Entry Account 2015-08-13 12:52:13 +05:30
Rushabh Mehta
cdbb448f6c [fix] salary slip to consider disable rounded total, #3792 2015-08-13 12:48:04 +05:30
Rushabh Mehta
907ea7dd8a [minor] pincode label changed to postal code, #3770 2015-08-13 12:35:43 +05:30
Neil Trini Lasrado
9a73b7a319 Changed UOM validation for Item Master 2015-08-13 12:21:32 +05:30
Nabin Hait
2e54da2ea5 [fix] fraction issue in gl entry 2015-08-13 12:19:27 +05:30
Rushabh Mehta
7e4b93f48e [patch] cleanup_journal_entry 2015-08-13 12:10:21 +05:30
Rushabh Mehta
b01cc1b449 [patch] cleanup_journal_entry 2015-08-13 11:54:04 +05:30
Rushabh Mehta
f738b951c5 [patch] cleanup_journal_entry 2015-08-13 11:50:51 +05:30
Anand Doshi
bb1679b74b Merge pull request #3865 from nabinhait/fix3
minor fix
2015-08-13 11:48:47 +05:30
Nabin Hait
6ddcac7cee minor fix 2015-08-13 11:47:35 +05:30
Rushabh Mehta
bcf7da6b1e [patch] cleanup_journal_entry 2015-08-13 11:46:01 +05:30
Nabin Hait
c51d5ba5df [patch] Update item description in Production Order based on item master 2015-08-13 11:39:45 +05:30
Anand Doshi
57ca765d9e Merge pull request #3848 from rmehta/journal-entry-refactor
[refactor] added dynamic link in journal entry, #3847, #3814
2015-08-13 11:39:13 +05:30
Anand Doshi
92e7d1f41d Merge pull request #3855 from nabinhait/discount
discount percentage should not be reset to zero on applying price list
2015-08-13 11:39:03 +05:30
Rushabh Mehta
ed40542658 [fix] minor auto-select party type and add has_permission in whitelisted methods 2015-08-13 10:34:49 +05:30
Rushabh Mehta
207b3efed7 [fix] journal entry get_query 2015-08-12 15:18:35 +05:30
Rushabh Mehta
3131c732ff [fix] capacity planning error 2015-08-12 12:29:16 +05:30
Rushabh Mehta
1828c12481 [refactor] added dynamic link in journal entry, #3847 2015-08-12 12:28:33 +05:30
Nabin Hait
4a91c49e0d discount percentage should not be reset to zero on applying price list 2015-08-11 18:16:10 +05:30
Anand Doshi
ba1f4263dd Added Rohit Industries as sponsors for #3546 2015-08-11 17:05:17 +05:30
Anand Doshi
7d45929872 Merge pull request #3829 from dottenbr/customer-taxid
Tax ID added and Customer Details description updated
2015-08-11 12:33:32 +05:30
Rushabh Mehta
b70f871592 Merge pull request #3850 from dottenbr/patch-1
Update README.md
2015-08-11 10:15:42 +05:30
Rushabh Mehta
d58df13150 Merge pull request #3849 from dottenbr/phone-mandatory-removed
Phone removed from mandatory in Address
2015-08-11 10:03:28 +05:30
Dominik
4101a48869 Update README.md 2015-08-10 23:59:16 +05:30
Dominik
28eff7fb91 Phone removed from mandatory in Address 2015-08-10 20:22:21 +05:30
Nabin Hait
6dc40e9baf Update accounts_controller.py 2015-08-10 19:18:39 +05:30
Nabin Hait
ac6d11eb3c minor improvements 2015-08-10 19:14:43 +05:30
Neil Trini Lasrado
1c6eeb228f Fixes in Stock Entry 2015-08-10 19:14:43 +05:30
Neil Trini Lasrado
b44f26d1ba Fixed Max value for update FG Item in Production Order 2015-08-10 19:14:43 +05:30
Neil Trini Lasrado
8ea2f45713 Renamed update_fg_goods_based_on in Manufacturing Settings to backflush_raw_materials_based_on 2015-08-10 19:14:43 +05:30
Neil Trini Lasrado
dde65752b6 Fixed code to consider partial FG entry 2015-08-10 19:14:43 +05:30
Neil Trini Lasrado
845980c010 Added Feature - Update FG based on Material Transfer For Manufacturing 2015-08-10 19:14:43 +05:30
Rushabh Mehta
6f593130d0 Merge pull request #3823 from nabinhait/stock-entry-tax
Stock entry tax
2015-08-10 14:31:20 +05:30
Nabin Hait
52f3bfca73 change log and sponsors page 2015-08-10 14:07:45 +05:30
Nabin Hait
3c3a3ecea8 Additional Costs in Stock Entry 2015-08-10 14:07:45 +05:30
Nabin Hait
246e47e76e [fix] Dashboard in customer / supplier 2015-08-10 14:07:02 +05:30
Nabin Hait
f6aad5ed2d Distribute tax amount between items in stock entry 2015-08-10 14:07:01 +05:30
Nabin Hait
aa87931172 Show only active BOM in stock entry 2015-08-10 14:07:01 +05:30
Nabin Hait
fc155c7712 Added tax table in stock entry 2015-08-10 14:07:01 +05:30
Rushabh Mehta
bf4f99adf1 [learn] added modules #3841 2015-08-10 13:21:57 +05:30
Rushabh Mehta
47b5e6272d Merge pull request #3844 from nabinhait/fix12
[fix] Made expense account non-mandatory in POS Profile
2015-08-10 13:16:39 +05:30
Rushabh Mehta
eae56cae54 Merge pull request #3843 from thecarly/patch-1
[minor] fixed typo
2015-08-10 13:13:00 +05:30
Nabin Hait
ea925d26a8 [fix] Made expense account non-mandatory in POS Profile 2015-08-10 12:57:05 +05:30
thecarly
56f5156f3c [minor] fixed typo 2015-08-10 12:50:44 +05:30
Rushabh Mehta
ee069d47b5 Merge pull request #3797 from anandpdoshi/fix-missing-item-images
Rename old filenames for Item
2015-08-10 11:58:54 +05:30
Rushabh Mehta
6c83b6bddc Merge pull request #3811 from rmehta/opportunity-customer
[minor] add close button in opportunity and project links in customer
2015-08-10 11:57:23 +05:30
Rushabh Mehta
815b460ddd Merge pull request #3809 from nabinhait/journal_entry_fix
[fix] Party / Account Validation message against Invoice
2015-08-10 11:57:01 +05:30
Rushabh Mehta
5f7166de83 [minor] remove section break in opportunity 2015-08-10 11:30:47 +05:30
Dominik
d1416542a0 Tax ID added and Customer Details description updated
Tax ID is a relatively generic descriptor for VAT (Value Added Tax) or any other countrie's tax identification system and should be required by most users of an ERP system. Since this removes the necessity to put the VAT into the Customer Description (not the ideal place to begin with) the description was updated and slimmed down.
2015-08-08 00:05:38 +05:30
Rushabh Mehta
69095e7285 [fix] website search 2015-08-07 15:48:53 +05:30
Rushabh Mehta
d6bdad7adf [fix] [hot] total in time log batch 2015-08-06 15:46:42 +05:30
Rushabh Mehta
48cccca9af [minor] add close button in opportunity and project links in customer 2015-08-06 15:37:01 +05:30
Nabin Hait
7c5124140e [fix] Party / Account Validation message against Invoice 2015-08-06 12:58:53 +05:30
Nabin Hait
143f384986 Merge branch 'develop' 2015-08-05 19:14:37 +05:30
Nabin Hait
37fdc43c88 bumped to version 5.5.1 2015-08-05 19:44:37 +06:00
Nabin Hait
ceb761852e Merge pull request #3807 from nabinhait/hotfix
[fix] fifo in stock ledger
2015-08-05 19:13:12 +05:30
Nabin Hait
65d8de36d0 Merge pull request #3804 from nabinhait/fix1
Fixes
2015-08-05 19:04:41 +05:30
Nabin Hait
8142cd2865 [fix] fifo in stock ledger 2015-08-05 18:57:37 +05:30
Anand Doshi
ed3a6cf748 [minor] removed print 2015-08-05 18:38:33 +05:30
Nabin Hait
2285eb7649 Merge pull request #3801 from bobzz-zone/patch-8
Update buying_controller.py
2015-08-05 16:15:02 +05:30
Nabin Hait
1648605950 [fix] Disabled OHADA system while fetching COA based on country 2015-08-05 15:56:05 +05:30
Nabin Hait
039154faa9 [fix] Asynchronus issue while fetching item description in Production Order 2015-08-05 15:56:05 +05:30
Rushabh Mehta
147acfd502 [fix] [mobile] abs url erpnext icon 2015-08-05 14:49:32 +05:30
bobzz-zone
b4c7bad33d Update buying_controller.py
dont force change conversion factor
2015-08-05 11:30:12 +07:00
bobzz-zone
ff04bf6346 Update stock_entry.py
fixed for null expense account
2015-08-05 11:28:11 +07:00
Anand Doshi
aa5182bb9e [fix] rename old filenames that start with FileData and fix missing Item images 2015-08-04 23:06:01 +05:30
Anand Doshi
329afe88f9 Merge branch 'develop' 2015-08-04 16:12:22 +05:30
Anand Doshi
ffa1e1c3bc bumped to version 5.5.0 2015-08-04 16:42:22 +06:00
Anand Doshi
f6616b6cbd [change-log] 2015-08-04 16:02:37 +05:30
Anand Doshi
d95b8e530a Merge pull request #3794 from nabinhait/serial_no
[fix] serial no validation in return entry
2015-08-04 15:43:23 +05:30
Nabin Hait
0e1314c5b5 [fix] serial no validation in return entry 2015-08-04 15:22:48 +05:30
Anand Doshi
cc920a7e4c Merge pull request #3780 from rmehta/service-product-bundle
[enhancement] make service type product bundle #3452
2015-08-04 15:05:05 +05:30
Rushabh Mehta
5bd394278d [fix] test-case, warehouse mandatory for mix type product bundle 2015-08-04 14:49:25 +05:30
Rushabh Mehta
a208c56813 [enhancement] auto insert item price if missing, #3533 2015-08-04 14:48:52 +05:30
Rushabh Mehta
862a2eb975 [enhancement] make service type product bundle: 2015-08-04 14:47:45 +05:30
Anand Doshi
1385f20042 Merge pull request #3791 from rmehta/update-translations
[translations] updated
2015-08-04 14:45:58 +05:30
Anand Doshi
950250d444 Merge pull request #3793 from nabinhait/serial_no
Validate serial no in return entry with against document
2015-08-04 14:45:30 +05:30
Rushabh Mehta
63b98ec113 [translations] updated 2015-08-04 12:43:37 +05:30
Anand Doshi
4a0edd04c4 Merge pull request #3779 from nabinhait/fifo_stack
[fix] Get fifo rate only qty exists in batch
2015-08-04 12:26:42 +05:30
Nabin Hait
b7c0c55d61 Validate serial no in return entry with against document 2015-08-04 12:18:12 +05:30
Nabin Hait
232ad777c9 [fix][patch] Remove fifo stack entry if qty after transaction is zero via stock reconciliation 2015-08-04 11:40:38 +05:30
Nabin Hait
7edb951fdb [fix] Get fifo rate only qty exists in batch 2015-08-04 11:09:14 +05:30
Nabin Hait
845bbe3e27 Update fix_invoice_outstanding.py 2015-08-04 10:48:05 +05:30
Nabin Hait
f7bf50d6fe Merge pull request #3786 from nabinhait/fix4
[fix] Ignore if error coming while sending emails to system managers
2015-08-03 19:27:04 +05:30
Nabin Hait
374559bfad [fix] Ignore if error coming while sending emails to system managers 2015-08-03 19:26:32 +05:30
Anand Doshi
e7c6605455 Merge pull request #3761 from nabinhait/fix1
Fixes
2015-08-03 19:20:31 +05:30
Nabin Hait
5bbe823106 [patch] Fix outstanding amount for original invoice for return entry 2015-08-03 19:19:11 +05:30
Nabin Hait
ad44b00f33 [patch] Fix outstanding amount for original invoice for return entry 2015-08-03 19:19:11 +05:30
Nabin Hait
893db7a5c3 Allow payment against invoice with negative outstanding 2015-08-03 19:18:22 +05:30
Nabin Hait
433cdc960d Update outstanding in original invoice from return invoice 2015-08-03 19:18:22 +05:30
Nabin Hait
4f2832ecd2 [fix] Allow against purchase invoice against credit amount row 2015-08-03 19:18:22 +05:30
Nabin Hait
1755a5f298 [fix] get items from bom in material request 2015-08-03 19:18:21 +05:30
Nabin Hait
b3b059b0ea [fix] payment reconciliation 2015-08-03 19:18:21 +05:30
Anand Doshi
d615d4fdcd Merge pull request #3785 from nabinhait/fix3
[fix] newsletter list unique check
2015-08-03 19:18:07 +05:30
Anand Doshi
da77abc25b Merge pull request #3767 from nabinhait/tax_calc
[fix] Tax calculation while discount applied on net total
2015-08-03 19:17:04 +05:30
Anand Doshi
7cb19f6e9f Merge pull request #3783 from nabinhait/fix2
[fix] Get open SO in production planning tool
2015-08-03 19:14:24 +05:30
Anand Doshi
441a75b1d4 Merge pull request #3782 from rmehta/uom-fix
[fix] force stock_uom in item and stock ledger entry
2015-08-03 19:13:38 +05:30
Nabin Hait
03bccb81d8 [test case] Test case for discount amount on net total 2015-08-03 19:11:44 +05:30
Nabin Hait
1db0b6de0c Patch to notify system managers if there are any wrong entries due to bug related to discount amount on net total 2015-08-03 19:11:44 +05:30
Nabin Hait
db53a789be [fix] Tax calculation while discount applied on net total 2015-08-03 19:10:59 +05:30
Nabin Hait
c3e1f6bb96 [fix] newsletter list unique check 2015-08-03 19:09:05 +05:30
Anand Doshi
f2e5e7fc22 Merge pull request #3776 from nabinhait/account_type
Propogate root type and report type into children based on parent
2015-08-03 19:04:42 +05:30
Nabin Hait
541927d58a [fix] Get open SO in production planning tool 2015-08-03 16:39:20 +05:30
Rushabh Mehta
b16b9cd7a0 [fix] force stock_uom in item and stock ledger entry 2015-08-03 16:13:33 +05:30
Nabin Hait
94f15fcec6 Propogate root type and report type into children based on parent 2015-08-03 11:17:07 +05:30
Anand Doshi
ba9dbb1b09 [minor] removed Link/DocType in Payment Period Based on Invoice Date 2015-08-03 11:05:45 +05:30
Nabin Hait
b7f2066250 Merge pull request #3768 from nabinhait/uom
[fix] UOM conversion factor in stock entry
2015-07-31 20:11:23 +05:30
Nabin Hait
b30c40ec8a [fix] UOM conversion factor in stock entry 2015-07-31 19:48:57 +05:30
Rushabh Mehta
2f5587ab25 [fix] uom conversion factor in stock entry, #3734 2015-07-31 15:20:29 +05:30
Nabin Hait
75e9733283 Merge branch 'develop' 2015-07-30 16:47:49 +05:30
Nabin Hait
69588f57e7 bumped to version 5.4.2 2015-07-30 17:17:48 +06:00
Nabin Hait
88d8c164f7 Merge pull request #3757 from nabinhait/fix1
[hotfix] item search in production order
2015-07-30 16:46:27 +05:30
Nabin Hait
c330a49e9d [hotfix] item search in production order 2015-07-30 16:45:58 +05:30
Nabin Hait
b75f5fd5ab Merge branch 'develop' 2015-07-30 14:59:01 +05:30
Nabin Hait
6f5815838e bumped to version 5.4.1 2015-07-30 15:29:01 +06:00
Nabin Hait
fe53651287 Merge pull request #3755 from nabinhait/fix1
repost stock for product bundle materials
2015-07-30 14:54:21 +05:30
Nabin Hait
d8546c4316 Fixed include holiday logic in leave calculation 2015-07-30 14:53:27 +05:30
Nabin Hait
17405d4130 repost stock for product bundle materials 2015-07-30 14:53:27 +05:30
Anand Doshi
2f443a5789 [hotfix] Item checkbox mandatory and removed Module Def Contacts 2015-07-30 14:44:43 +05:30
201 changed files with 74006 additions and 37531 deletions

View File

@@ -15,7 +15,6 @@ install:
- wget https://raw.githubusercontent.com/frappe/bench/master/install_scripts/setup_frappe.sh
- sudo bash setup_frappe.sh --skip-setup-bench --mysql-root-password travis
- sudo pip install --upgrade pip
- sudo service redis-server start
- rm $TRAVIS_BUILD_DIR/.git/shallow
- cd ~/ && bench init frappe-bench --frappe-path https://github.com/frappe/frappe.git --frappe-branch develop
- cp -r $TRAVIS_BUILD_DIR/test_sites/test_site ~/frappe-bench/sites/
@@ -24,9 +23,13 @@ script:
- cd ~/frappe-bench
- bench get-app erpnext $TRAVIS_BUILD_DIR
- bench use test_site
- bench setup redis-cache
- bench setup redis-async-broker
- bench setup procfile --with-celery-broker
- bench reinstall
- bench build
- bench build-website
- bench serve &
- bench start &
- sleep 10
- bench --verbose run-tests --driver Firefox

View File

@@ -2,7 +2,7 @@
## Questions
If you have questions on how to use ERPNext or want help in customization or debugging of your scripts, please post on https://discuss.frappe.io. This is only for bug reports and feature requests.
If you have questions on how to use ERPNext or want help in customization or debugging of your scripts, please post on https://discuss.erpnext.com. This is only for bug reports and feature requests.
## Reporting issues

View File

@@ -10,13 +10,13 @@ ERPNext is built on the [Frappe](https://github.com/frappe/frappe) Framework, a
- [User Guide](https://manual.erpnext.com)
- [Getting Help](http://erpnext.org/getting-help.html)
- [Discussion Forum](https://discuss.frappe.io/)
- [Discussion Forum](https://discuss.erpnext.com/)
---
### Full Install
The Easy Way install script for bench will install all dependencies (e.g. MariaDB). See https://github.com/frappe/bench
The Easy Way: our install script for bench will install all dependencies (e.g. MariaDB). See https://github.com/frappe/bench for more details.
New passwords will be created for the ERPNext "Administrator" user, the MariaDB root user, and the frappe user (the script displays the passwords and saves them to ~/frappe_passwords.txt).
@@ -71,6 +71,6 @@ We do not allow the use of the trademark in advertising, including AdSense/AdWor
Please note that it is not the goal of this policy to limit commercial activity around ERPNext. We encourage ERPNext-based businesses, and we would love to see hundreds of them.
When in doubt about your use of the ERPNext name or logo, please contact the Frappe Technologies for clarification.
When in doubt about your use of the ERPNext name or logo, please contact Frappe Technologies for clarification.
(inspired from WordPress)
(inspired by WordPress)

View File

@@ -1,2 +1,2 @@
from __future__ import unicode_literals
__version__ = '5.4.0'
__version__ = '5.7.0'

View File

@@ -23,6 +23,7 @@ class Account(Document):
def validate(self):
self.validate_parent()
self.validate_root_details()
self.set_root_and_report_type()
self.validate_mandatory()
self.validate_warehouse_account()
self.validate_frozen_accounts_modifier()
@@ -32,7 +33,7 @@ class Account(Document):
"""Fetch Parent Details and validate parent account"""
if self.parent_account:
par = frappe.db.get_value("Account", self.parent_account,
["name", "is_group", "report_type", "root_type", "company"], as_dict=1)
["name", "is_group", "company"], as_dict=1)
if not par:
throw(_("Account {0}: Parent account {1} does not exist").format(self.name, self.parent_account))
elif par.name == self.name:
@@ -43,10 +44,24 @@ class Account(Document):
throw(_("Account {0}: Parent account {1} does not belong to company: {2}")
.format(self.name, self.parent_account, self.company))
def set_root_and_report_type(self):
if self.parent_account:
par = frappe.db.get_value("Account", self.parent_account, ["report_type", "root_type"], as_dict=1)
if par.report_type:
self.report_type = par.report_type
if par.root_type:
self.root_type = par.root_type
if self.is_group:
db_value = frappe.db.get_value("Account", self.name, ["report_type", "root_type"], as_dict=1)
if db_value:
if self.report_type != db_value.report_type:
frappe.db.sql("update `tabAccount` set report_type=%s where lft > %s and rgt < %s",
(self.report_type, self.lft, self.rgt))
if self.root_type != db_value.root_type:
frappe.db.sql("update `tabAccount` set root_type=%s where lft > %s and rgt < %s",
(self.root_type, self.lft, self.rgt))
def validate_root_details(self):
# does not exists parent

View File

@@ -92,13 +92,13 @@ def get_charts_for_country(country):
with open(os.path.join(path, fname), "r") as f:
_get_chart_name(f.read())
countries_use_OHADA_system = ["Benin", "Burkina Faso", "Cameroon", "Central African Republic", "Comoros",
"Congo", "Ivory Coast", "Gabon", "Guinea", "Guinea Bissau", "Equatorial Guinea", "Mali", "Niger",
"Replica of Democratic Congo", "Senegal", "Chad", "Togo"]
if country in countries_use_OHADA_system:
with open(os.path.join(os.path.dirname(__file__), "syscohada_syscohada_chart_template.json"), "r") as f:
_get_chart_name(f.read())
# countries_use_OHADA_system = ["Benin", "Burkina Faso", "Cameroon", "Central African Republic", "Comoros",
# "Congo", "Ivory Coast", "Gabon", "Guinea", "Guinea Bissau", "Equatorial Guinea", "Mali", "Niger",
# "Replica of Democratic Congo", "Senegal", "Chad", "Togo"]
#
# if country in countries_use_OHADA_system:
# with open(os.path.join(os.path.dirname(__file__), "syscohada_syscohada_chart_template.json"), "r") as f:
# _get_chart_name(f.read())
if len(charts) != 1:
charts.append("Standard")

View File

@@ -19,7 +19,8 @@ class BankReconciliation(Document):
dl = frappe.db.sql("""select t1.name, t1.cheque_no, t1.cheque_date, t2.debit,
t2.credit, t1.posting_date, t2.against_account, t1.clearance_date
t2.credit, t1.posting_date, t2.against_account, t1.clearance_date,
t2.reference_type, t2.reference_name
from
`tabJournal Entry` t1, `tabJournal Entry Account` t2
where

View File

@@ -1,11 +1,19 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"creation": "2013-02-22 01:27:37",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"fields": [
{
"allow_on_submit": 0,
"fieldname": "voucher_id",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Voucher ID",
"no_copy": 0,
@@ -13,46 +21,84 @@
"oldfieldtype": "Link",
"options": "Journal Entry",
"permlevel": 0,
"search_index": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "clearance_date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Clearance Date",
"no_copy": 0,
"oldfieldname": "clearance_date",
"oldfieldtype": "Date",
"permlevel": 0,
"search_index": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "against_account",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Against Account",
"no_copy": 0,
"oldfieldname": "against_account",
"oldfieldtype": "Data",
"permlevel": 0,
"print_hide": 0,
"read_only": 1,
"search_index": 0
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "cheque_number",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Cheque Number",
"no_copy": 0,
"oldfieldname": "cheque_number",
"oldfieldtype": "Data",
"permlevel": 0,
"print_hide": 0,
"read_only": 1,
"search_index": 0
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "debit",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Debit",
"no_copy": 0,
@@ -60,12 +106,21 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"print_hide": 0,
"read_only": 1,
"search_index": 0
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "credit",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Credit",
"no_copy": 0,
@@ -73,40 +128,113 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"print_hide": 0,
"read_only": 1,
"search_index": 0
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "reference_type",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Reference Type",
"no_copy": 0,
"options": "DocType",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "reference_name",
"fieldtype": "Dynamic Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Reference Name",
"no_copy": 0,
"options": "reference_type",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "posting_date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Posting Date",
"no_copy": 0,
"oldfieldname": "posting_date",
"oldfieldtype": "Date",
"permlevel": 0,
"print_hide": 0,
"read_only": 1,
"search_index": 0
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "cheque_date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Cheque Date",
"no_copy": 0,
"oldfieldname": "cheque_date",
"oldfieldtype": "Date",
"permlevel": 0,
"print_hide": 0,
"read_only": 1,
"search_index": 0
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 1,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-04-21 01:29:29.570890",
"modified": "2015-08-10 16:59:43.974705",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Reconciliation Detail",
"owner": "Administrator",
"permissions": []
"permissions": [],
"read_only": 0,
"read_only_onload": 0
}

View File

@@ -48,34 +48,49 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
}
});
$.each([["against_voucher", "Purchase Invoice", "supplier"],
["against_invoice", "Sales Invoice", "customer"]], function(i, opts) {
me.frm.set_query(opts[0], "accounts", function(doc, cdt, cdn) {
var jvd = frappe.get_doc(cdt, cdn);
frappe.model.validate_missing(jvd, "party_type");
frappe.model.validate_missing(jvd, "party");
return {
filters: [
[opts[1], opts[2], "=", jvd.party],
[opts[1], "docstatus", "=", 1],
[opts[1], "outstanding_amount", ">", 0]
]
};
});
});
this.frm.set_query("against_jv", "accounts", function(doc, cdt, cdn) {
me.frm.set_query("reference_name", "accounts", function(doc, cdt, cdn) {
var jvd = frappe.get_doc(cdt, cdn);
frappe.model.validate_missing(jvd, "account");
return {
query: "erpnext.accounts.doctype.journal_entry.journal_entry.get_against_jv",
filters: {
account: jvd.account,
party: jvd.party
}
// expense claim
if(jvd.reference_type==="Expense Claim") {
return {};
}
// journal entry
if(jvd.reference_type==="Journal Entry") {
frappe.model.validate_missing(jvd, "account");
return {
query: "erpnext.accounts.doctype.journal_entry.journal_entry.get_against_jv",
filters: {
account: jvd.account,
party: jvd.party
}
};
}
// against party
frappe.model.validate_missing(jvd, "party_type");
frappe.model.validate_missing(jvd, "party");
var out = {
filters: [
[jvd.reference_type, jvd.reference_type.indexOf("Sales")===0 ? "customer" : "supplier", "=", jvd.party],
[jvd.reference_type, "docstatus", "=", 1],
]
};
if(in_list(["Sales Invoice", "Purchase Invoice"], jvd.reference_type)) {
out.filters.push([jvd.reference_type, "outstanding_amount", "!=", 0]);
} else {
out.filters.push([jvd.reference_type, "per_billed", "<", 100]);
}
return out;
});
},
setup_balance_formatter: function() {
@@ -93,24 +108,16 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
})
},
against_voucher: function(doc, cdt, cdn) {
reference_name: function(doc, cdt, cdn) {
var d = frappe.get_doc(cdt, cdn);
if (d.against_voucher && !flt(d.debit)) {
this.get_outstanding('Purchase Invoice', d.against_voucher, d);
if (d.reference_type==="Purchase Invoice" && !flt(d.debit)) {
this.get_outstanding('Purchase Invoice', d.reference_name, d);
}
},
against_invoice: function(doc, cdt, cdn) {
var d = frappe.get_doc(cdt, cdn);
if (d.against_invoice && !flt(d.credit)) {
this.get_outstanding('Sales Invoice', d.against_invoice, d);
if (d.reference_type==="Sales Invoice" && !flt(d.credit)) {
this.get_outstanding('Sales Invoice', d.reference_name, d);
}
},
against_jv: function(doc, cdt, cdn) {
var d = frappe.get_doc(cdt, cdn);
if (d.against_jv && !flt(d.credit) && !flt(d.debit)) {
this.get_outstanding('Journal Entry', d.against_jv, d);
if (d.reference_type==="Journal Entry" && !flt(d.credit) && !flt(d.debit)) {
this.get_outstanding('Journal Entry', d.reference_name, d);
}
},
@@ -214,11 +221,12 @@ cur_frm.cscript.account = function(doc,dt,dn) {
var d = locals[dt][dn];
if(d.account) {
return frappe.call({
method: "erpnext.accounts.utils.get_balance_on",
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_account_balance_and_party_type",
args: {account: d.account, date: doc.posting_date},
callback: function(r) {
d.balance = r.message;
$.extend(d, r.message);
refresh_field('balance', d.name, 'accounts');
refresh_field('party_type', d.name, 'accounts');
}
});
}

View File

@@ -28,13 +28,10 @@ class JournalEntry(AccountsController):
self.validate_entries_for_advance()
self.validate_debit_and_credit()
self.validate_against_jv()
self.validate_against_sales_invoice()
self.validate_against_purchase_invoice()
self.validate_reference_doc()
self.set_against_account()
self.create_remarks()
self.set_print_format_fields()
self.validate_against_sales_order()
self.validate_against_purchase_order()
self.check_due_date()
self.validate_expense_claim()
self.validate_credit_debit_note()
@@ -54,10 +51,8 @@ class JournalEntry(AccountsController):
advance_paid = frappe._dict()
for d in self.get("accounts"):
if d.is_advance:
if d.against_sales_order:
advance_paid.setdefault("Sales Order", []).append(d.against_sales_order)
elif d.against_purchase_order:
advance_paid.setdefault("Purchase Order", []).append(d.against_purchase_order)
if d.reference_type in ("Sales Order", "Purchase Order"):
advance_paid.setdefault(d.reference_type, []).append(d.reference_name)
for voucher_type, order_list in advance_paid.items():
for voucher_no in list(set(order_list)):
@@ -65,7 +60,7 @@ class JournalEntry(AccountsController):
def on_cancel(self):
from erpnext.accounts.utils import remove_against_link_from_jv
remove_against_link_from_jv(self.doctype, self.name, "against_jv")
remove_against_link_from_jv(self.doctype, self.name)
self.make_gl_entries(1)
self.update_advance_paid()
@@ -93,10 +88,8 @@ class JournalEntry(AccountsController):
for d in self.get("accounts"):
if d.party_type and d.party and d.get("credit" if d.party_type=="Customer" else "debit") > 0:
due_date = None
if d.against_invoice:
due_date = frappe.db.get_value("Sales Invoice", d.against_invoice, "due_date")
elif d.against_voucher:
due_date = frappe.db.get_value("Purchase Invoice", d.against_voucher, "due_date")
if d.reference_type in ("Sales Invoice", "Purchase Invoice"):
due_date = frappe.db.get_value(d.reference_type, d.reference_name, "due_date")
if due_date and getdate(self.cheque_date) > getdate(due_date):
diff = date_diff(self.cheque_date, due_date)
@@ -115,17 +108,17 @@ class JournalEntry(AccountsController):
def validate_entries_for_advance(self):
for d in self.get('accounts'):
if not (d.against_voucher and d.against_invoice and d.against_jv):
if d.reference_type not in ("Sales Invoice", "Purchase Invoice", "Journal Entry"):
if (d.party_type == 'Customer' and flt(d.credit) > 0) or \
(d.party_type == 'Supplier' and flt(d.debit) > 0):
if not d.is_advance:
if d.is_advance=="No":
msgprint(_("Row {0}: Please check 'Is Advance' against Account {1} if this is an advance entry.").format(d.idx, d.account))
elif (d.against_sales_order or d.against_purchase_order) and d.is_advance != "Yes":
elif d.reference_type in ("Sales Order", "Purchase Order") and d.is_advance != "Yes":
frappe.throw(_("Row {0}: Payment against Sales/Purchase Order should always be marked as advance").format(d.idx))
def validate_against_jv(self):
for d in self.get('accounts'):
if d.against_jv:
if d.reference_type=="Journal Entry":
account_root_type = frappe.db.get_value("Account", d.account, "root_type")
if account_root_type == "Asset" and flt(d.debit) > 0:
frappe.throw(_("For {0}, only credit accounts can be linked against another debit entry")
@@ -134,17 +127,17 @@ class JournalEntry(AccountsController):
frappe.throw(_("For {0}, only debit accounts can be linked against another credit entry")
.format(d.account))
if d.against_jv == self.name:
if d.reference_name == self.name:
frappe.throw(_("You can not enter current voucher in 'Against Journal Entry' column"))
against_entries = frappe.db.sql("""select * from `tabJournal Entry Account`
where account = %s and docstatus = 1 and parent = %s
and ifnull(against_jv, '') = '' and ifnull(against_invoice, '') = ''
and ifnull(against_voucher, '') = ''""", (d.account, d.against_jv), as_dict=True)
and ifnull(reference_type, '') in ("", "Sales Order", "Purchase Order")
""", (d.account, d.reference_name), as_dict=True)
if not against_entries:
frappe.throw(_("Journal Entry {0} does not have account {1} or already matched against other voucher")
.format(d.against_jv, d.account))
.format(d.reference_name, d.account))
else:
dr_or_cr = "debit" if d.credit > 0 else "credit"
valid = False
@@ -153,90 +146,99 @@ class JournalEntry(AccountsController):
valid = True
if not valid:
frappe.throw(_("Against Journal Entry {0} does not have any unmatched {1} entry")
.format(d.against_jv, dr_or_cr))
.format(d.reference_name, dr_or_cr))
def validate_against_sales_invoice(self):
payment_against_voucher = self.validate_account_in_against_voucher("against_invoice", "Sales Invoice")
self.validate_against_invoice_fields("Sales Invoice", payment_against_voucher)
def validate_against_purchase_invoice(self):
payment_against_voucher = self.validate_account_in_against_voucher("against_voucher", "Purchase Invoice")
self.validate_against_invoice_fields("Purchase Invoice", payment_against_voucher)
def validate_against_sales_order(self):
payment_against_voucher = self.validate_account_in_against_voucher("against_sales_order", "Sales Order")
self.validate_against_order_fields("Sales Order", payment_against_voucher)
def validate_against_purchase_order(self):
payment_against_voucher = self.validate_account_in_against_voucher("against_purchase_order", "Purchase Order")
self.validate_against_order_fields("Purchase Order", payment_against_voucher)
def validate_account_in_against_voucher(self, against_field, doctype):
payment_against_voucher = frappe._dict()
field_dict = {'Sales Invoice': ["Customer", "Debit To"],
def validate_reference_doc(self):
"""Validates reference document"""
field_dict = {
'Sales Invoice': ["Customer", "Debit To"],
'Purchase Invoice': ["Supplier", "Credit To"],
'Sales Order': ["Customer"],
'Purchase Order': ["Supplier"]
}
}
self.reference_totals = {}
self.reference_types = {}
for d in self.get("accounts"):
if d.get(against_field):
dr_or_cr = "credit" if against_field in ["against_invoice", "against_sales_order"] \
if not d.reference_type:
d.reference_name = None
if not d.reference_name:
d.reference_type = None
if d.reference_type and d.reference_name and (d.reference_type in field_dict.keys()):
dr_or_cr = "credit" if d.reference_type in ("Sales Order", "Sales Invoice") \
else "debit"
if against_field in ["against_invoice", "against_sales_order"] and flt(d.debit) > 0:
frappe.throw(_("Row {0}: Debit entry can not be linked with a {1}").format(d.idx, doctype))
if against_field in ["against_voucher", "against_purchase_order"] and flt(d.credit) > 0:
frappe.throw(_("Row {0}: Credit entry can not be linked with a {1}").format(d.idx, doctype))
# check debit or credit type Sales / Purchase Order
if d.reference_type=="Sales Order" and flt(d.debit) > 0:
frappe.throw(_("Row {0}: Debit entry can not be linked with a {1}").format(d.idx, d.reference_type))
against_voucher = frappe.db.get_value(doctype, d.get(against_field),
[scrub(dt) for dt in field_dict.get(doctype)])
if d.reference_type == "Purchase Order" and flt(d.credit) > 0:
frappe.throw(_("Row {0}: Credit entry can not be linked with a {1}").format(d.idx, d.reference_type))
if against_field in ["against_invoice", "against_voucher"]:
if (against_voucher[0] !=d.party or against_voucher[1] != d.account):
frappe.throw(_("Row {0}: Party / Account does not match with \
Customer / Debit To in {1}").format(d.idx, doctype))
else:
payment_against_voucher.setdefault(d.get(against_field), []).append(flt(d.get(dr_or_cr)))
# set totals
if not d.reference_name in self.reference_totals:
self.reference_totals[d.reference_name] = 0.0
self.reference_totals[d.reference_name] += flt(d.get(dr_or_cr))
self.reference_types[d.reference_name] = d.reference_type
if against_field in ["against_sales_order", "against_purchase_order"]:
against_voucher = frappe.db.get_value(d.reference_type, d.reference_name,
[scrub(dt) for dt in field_dict.get(d.reference_type)])
# check if party and account match
if d.reference_type in ("Sales Invoice", "Purchase Invoice"):
if (against_voucher[0] != d.party or against_voucher[1] != d.account):
frappe.throw(_("Row {0}: Party / Account does not match with {1} / {2} in {3} {4}")
.format(d.idx, field_dict.get(d.reference_type)[0], field_dict.get(d.reference_type)[1],
d.reference_type, d.reference_name))
# check if party matches for Sales / Purchase Order
if d.reference_type in ("Sales Order", "Purchase Order"):
# set totals
if against_voucher != d.party:
frappe.throw(_("Row {0}: {1} {2} does not match with {3}") \
.format(d.idx, d.party_type, d.party, doctype))
elif d.is_advance == "Yes":
payment_against_voucher.setdefault(d.get(against_field), []).append(flt(d.get(dr_or_cr)))
.format(d.idx, d.party_type, d.party, d.reference_type))
return payment_against_voucher
self.validate_orders()
self.validate_invoices()
def validate_against_invoice_fields(self, doctype, payment_against_voucher):
for voucher_no, payment_list in payment_against_voucher.items():
voucher_properties = frappe.db.get_value(doctype, voucher_no,
["docstatus", "outstanding_amount"])
def validate_orders(self):
"""Validate totals, stopped and docstatus for orders"""
for reference_name, total in self.reference_totals.iteritems():
reference_type = self.reference_types[reference_name]
if voucher_properties[0] != 1:
frappe.throw(_("{0} {1} is not submitted").format(doctype, voucher_no))
if reference_type in ("Sales Order", "Purchase Order"):
voucher_properties = frappe.db.get_value(reference_type, reference_name,
["docstatus", "per_billed", "status", "advance_paid", "base_grand_total"])
if flt(voucher_properties[1]) < flt(sum(payment_list)):
frappe.throw(_("Payment against {0} {1} cannot be greater \
than Outstanding Amount {2}").format(doctype, voucher_no, voucher_properties[1]))
if voucher_properties[0] != 1:
frappe.throw(_("{0} {1} is not submitted").format(reference_type, reference_name))
def validate_against_order_fields(self, doctype, payment_against_voucher):
for voucher_no, payment_list in payment_against_voucher.items():
voucher_properties = frappe.db.get_value(doctype, voucher_no,
["docstatus", "per_billed", "status", "advance_paid", "base_grand_total"])
if flt(voucher_properties[1]) >= 100:
frappe.throw(_("{0} {1} is fully billed").format(reference_type, reference_name))
if voucher_properties[0] != 1:
frappe.throw(_("{0} {1} is not submitted").format(doctype, voucher_no))
if cstr(voucher_properties[2]) == "Stopped":
frappe.throw(_("{0} {1} is stopped").format(reference_type, reference_name))
if flt(voucher_properties[1]) >= 100:
frappe.throw(_("{0} {1} is fully billed").format(doctype, voucher_no))
if flt(voucher_properties[4]) < (flt(voucher_properties[3]) + total):
frappe.throw(_("Advance paid against {0} {1} cannot be greater \
than Grand Total {2}").format(reference_type, reference_name, voucher_properties[4]))
if cstr(voucher_properties[2]) == "Stopped":
frappe.throw(_("{0} {1} is stopped").format(doctype, voucher_no))
def validate_invoices(self):
"""Validate totals and docstatus for invoices"""
for reference_name, total in self.reference_totals.iteritems():
reference_type = self.reference_types[reference_name]
if flt(voucher_properties[4]) < flt(voucher_properties[3]) + flt(sum(payment_list)):
frappe.throw(_("Advance paid against {0} {1} cannot be greater \
than Grand Total {2}").format(doctype, voucher_no, voucher_properties[3]))
if reference_type in ("Sales Invoice", "Purchase Invoice"):
voucher_properties = frappe.db.get_value(reference_type, reference_name,
["docstatus", "outstanding_amount"])
if voucher_properties[0] != 1:
frappe.throw(_("{0} {1} is not submitted").format(reference_type, reference_name))
if flt(voucher_properties[1]) < total:
frappe.throw(_("Payment against {0} {1} cannot be greater \
than Outstanding Amount {2}").format(reference_type, reference_name, voucher_properties[1]))
def set_against_account(self):
accounts_debited, accounts_credited = [], []
@@ -276,25 +278,25 @@ class JournalEntry(AccountsController):
company_currency = get_company_currency(self.company)
for d in self.get('accounts'):
if d.against_invoice and d.credit:
if d.reference_type=="Sales Invoice" and d.credit:
r.append(_("{0} against Sales Invoice {1}").format(fmt_money(flt(d.credit), currency = company_currency), \
d.against_invoice))
d.reference_name))
if d.against_sales_order and d.credit:
if d.reference_type=="Sales Order" and d.credit:
r.append(_("{0} against Sales Order {1}").format(fmt_money(flt(d.credit), currency = company_currency), \
d.against_sales_order))
d.reference_name))
if d.against_voucher and d.debit:
if d.reference_type == "Purchase Invoice" and d.debit:
bill_no = frappe.db.sql("""select bill_no, bill_date
from `tabPurchase Invoice` where name=%s""", d.against_voucher)
from `tabPurchase Invoice` where name=%s""", d.reference_name)
if bill_no and bill_no[0][0] and bill_no[0][0].lower().strip() \
not in ['na', 'not applicable', 'none']:
r.append(_('{0} against Bill {1} dated {2}').format(fmt_money(flt(d.debit), currency=company_currency), bill_no[0][0],
bill_no[0][1] and formatdate(bill_no[0][1].strftime('%Y-%m-%d'))))
if d.against_purchase_order and d.debit:
if d.reference_type == "Purchase Order" and d.debit:
r.append(_("{0} against Purchase Order {1}").format(fmt_money(flt(d.credit), currency = company_currency), \
d.against_purchase_order))
d.reference_name))
if self.user_remark:
r.append(_("Note: {0}").format(self.user_remark))
@@ -333,13 +335,8 @@ class JournalEntry(AccountsController):
"against": d.against_account,
"debit": flt(d.debit, self.precision("debit", "accounts")),
"credit": flt(d.credit, self.precision("credit", "accounts")),
"against_voucher_type": (("Purchase Invoice" if d.against_voucher else None)
or ("Sales Invoice" if d.against_invoice else None)
or ("Journal Entry" if d.against_jv else None)
or ("Sales Order" if d.against_sales_order else None)
or ("Purchase Order" if d.against_purchase_order else None)),
"against_voucher": d.against_voucher or d.against_invoice or d.against_jv
or d.against_sales_order or d.against_purchase_order,
"against_voucher_type": d.reference_type,
"against_voucher": d.reference_name,
"remarks": self.remark,
"cost_center": d.cost_center
})
@@ -386,11 +383,13 @@ class JournalEntry(AccountsController):
if self.write_off_based_on == 'Accounts Receivable':
jd1.party_type = "Customer"
jd1.credit = flt(d.outstanding_amount, self.precision("credit", "accounts"))
jd1.against_invoice = cstr(d.name)
jd1.reference_type = "Sales Invoice"
jd1.reference_name = cstr(d.name)
elif self.write_off_based_on == 'Accounts Payable':
jd1.party_type = "Supplier"
jd1.debit = flt(d.outstanding_amount, self.precision("debit", "accounts"))
jd1.against_voucher = cstr(d.name)
jd1.reference_type = "Purchase Invoice"
jd1.reference_name = cstr(d.name)
jd2 = self.append('accounts', {})
if self.write_off_based_on == 'Accounts Receivable':
@@ -416,19 +415,20 @@ class JournalEntry(AccountsController):
def update_expense_claim(self):
for d in self.accounts:
if d.against_expense_claim:
if d.reference_type=="Expense Claim":
amt = frappe.db.sql("""select sum(debit) as amt from `tabJournal Entry Account`
where against_expense_claim = %s and docstatus = 1""", d.against_expense_claim ,as_dict=1)[0].amt
frappe.db.set_value("Expense Claim", d.against_expense_claim , "total_amount_reimbursed", amt)
where reference_type = "Expense Claim" and
reference_name = %s and docstatus = 1""", d.reference_name ,as_dict=1)[0].amt
frappe.db.set_value("Expense Claim", d.reference_name , "total_amount_reimbursed", amt)
def validate_expense_claim(self):
for d in self.accounts:
if d.against_expense_claim:
if d.reference_type=="Expense Claim":
sanctioned_amount, reimbursed_amount = frappe.db.get_value("Expense Claim",
d.against_expense_claim, ("total_sanctioned_amount", "total_amount_reimbursed"))
d.reference_name, ("total_sanctioned_amount", "total_amount_reimbursed"))
pending_amount = flt(sanctioned_amount) - flt(reimbursed_amount)
if d.debit > pending_amount:
frappe.throw(_("Row No {0}: Amount cannot be greater than Pending Amount against Expense Claim {1}. Pending Amount is {2}".format(d.idx, d.against_expense_claim, pending_amount)))
frappe.throw(_("Row No {0}: Amount cannot be greater than Pending Amount against Expense Claim {1}. Pending Amount is {2}".format(d.idx, d.reference_name, pending_amount)))
def validate_credit_debit_note(self):
if self.stock_entry:
@@ -468,6 +468,7 @@ def get_default_bank_cash_account(company, voucher_type, mode_of_payment=None):
@frappe.whitelist()
def get_payment_entry_from_sales_invoice(sales_invoice):
"""Returns new Journal Entry document as dict for given Sales Invoice"""
from erpnext.accounts.utils import get_balance_on
si = frappe.get_doc("Sales Invoice", sales_invoice)
jv = get_payment_entry(si)
@@ -480,7 +481,8 @@ def get_payment_entry_from_sales_invoice(sales_invoice):
jv.get("accounts")[0].balance = get_balance_on(si.debit_to)
jv.get("accounts")[0].party_balance = get_balance_on(party=si.customer, party_type="Customer")
jv.get("accounts")[0].credit = si.outstanding_amount
jv.get("accounts")[0].against_invoice = si.name
jv.get("accounts")[0].reference_type = si.doctype
jv.get("accounts")[0].reference_name = si.name
# debit bank
jv.get("accounts")[1].debit = si.outstanding_amount
@@ -489,6 +491,7 @@ def get_payment_entry_from_sales_invoice(sales_invoice):
@frappe.whitelist()
def get_payment_entry_from_purchase_invoice(purchase_invoice):
"""Returns new Journal Entry document as dict for given Purchase Invoice"""
pi = frappe.get_doc("Purchase Invoice", purchase_invoice)
jv = get_payment_entry(pi)
jv.remark = 'Payment against Purchase Invoice {0}. {1}'.format(pi.name, pi.remarks)
@@ -500,13 +503,78 @@ def get_payment_entry_from_purchase_invoice(purchase_invoice):
jv.get("accounts")[0].balance = get_balance_on(pi.credit_to)
jv.get("accounts")[0].party_balance = get_balance_on(party=pi.supplier, party_type="Supplier")
jv.get("accounts")[0].debit = pi.outstanding_amount
jv.get("accounts")[0].against_voucher = pi.name
jv.get("accounts")[0].reference_type = pi.doctype
jv.get("accounts")[0].reference_name = pi.name
# credit bank
jv.get("accounts")[1].credit = pi.outstanding_amount
return jv.as_dict()
@frappe.whitelist()
def get_payment_entry_from_sales_order(sales_order):
"""Returns new Journal Entry document as dict for given Sales Order"""
from erpnext.accounts.utils import get_balance_on
from erpnext.accounts.party import get_party_account
so = frappe.get_doc("Sales Order", sales_order)
if flt(so.per_billed, 2) != 0.0:
frappe.throw(_("Can only make payment against unbilled Sales Order"))
jv = get_payment_entry(so)
jv.remark = 'Advance payment received against Sales Order {0}.'.format(so.name)
party_account = get_party_account(so.company, so.customer, "Customer")
amount = flt(so.base_grand_total) - flt(so.advance_paid)
# credit customer
jv.get("accounts")[0].account = party_account
jv.get("accounts")[0].party_type = "Customer"
jv.get("accounts")[0].party = so.customer
jv.get("accounts")[0].balance = get_balance_on(party_account)
jv.get("accounts")[0].party_balance = get_balance_on(party=so.customer, party_type="Customer")
jv.get("accounts")[0].credit = amount
jv.get("accounts")[0].reference_type = so.doctype
jv.get("accounts")[0].reference_name = so.name
jv.get("accounts")[0].is_advance = "Yes"
# debit bank
jv.get("accounts")[1].debit = amount
return jv.as_dict()
@frappe.whitelist()
def get_payment_entry_from_purchase_order(purchase_order):
"""Returns new Journal Entry document as dict for given Sales Order"""
from erpnext.accounts.utils import get_balance_on
from erpnext.accounts.party import get_party_account
po = frappe.get_doc("Purchase Order", purchase_order)
if flt(po.per_billed, 2) != 0.0:
frappe.throw(_("Can only make payment against unbilled Sales Order"))
jv = get_payment_entry(po)
jv.remark = 'Advance payment made against Purchase Order {0}.'.format(po.name)
party_account = get_party_account(po.company, po.supplier, "Supplier")
amount = flt(po.base_grand_total) - flt(po.advance_paid)
# credit customer
jv.get("accounts")[0].account = party_account
jv.get("accounts")[0].party_type = "Supplier"
jv.get("accounts")[0].party = po.supplier
jv.get("accounts")[0].balance = get_balance_on(party_account)
jv.get("accounts")[0].party_balance = get_balance_on(party=po.supplier, party_type="Supplier")
jv.get("accounts")[0].debit = amount
jv.get("accounts")[0].reference_type = po.doctype
jv.get("accounts")[0].reference_name = po.name
jv.get("accounts")[0].is_advance = "Yes"
# debit bank
jv.get("accounts")[1].credit = amount
return jv.as_dict()
def get_payment_entry(doc):
bank_account = get_default_bank_cash_account(doc.company, "Bank Entry")
@@ -537,40 +605,43 @@ def get_against_jv(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql("""select jv.name, jv.posting_date, jv.user_remark
from `tabJournal Entry` jv, `tabJournal Entry Account` jv_detail
where jv_detail.parent = jv.name and jv_detail.account = %s and ifnull(jv_detail.party, '') = %s
and (ifnull(jv_detail.against_invoice, '') = '' and ifnull(jv_detail.against_voucher, '') = ''
and ifnull(jv_detail.against_jv, '') = '' )
and ifnull(jv_detail.reference_type, '') = ''
and jv.docstatus = 1 and jv.{0} like %s order by jv.name desc limit %s, %s""".format(searchfield),
(filters.get("account"), cstr(filters.get("party")), "%{0}%".format(txt), start, page_len))
@frappe.whitelist()
def get_outstanding(args):
if not frappe.has_permission("Account"):
frappe.msgprint(_("No Permission"), raise_exception=1)
args = eval(args)
if args.get("doctype") == "Journal Entry":
condition = " and party=%(party)s" if args.get("party") else ""
against_jv_amount = frappe.db.sql("""
select sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))
from `tabJournal Entry Account` where parent=%(docname)s and account=%(account)s {0}
and ifnull(against_invoice, '')='' and ifnull(against_voucher, '')=''
and ifnull(against_jv, '')=''""".format(condition), args)
and ifnull(reference_type, '')=''""".format(condition), args)
against_jv_amount = flt(against_jv_amount[0][0]) if against_jv_amount else 0
if against_jv_amount > 0:
return {"credit": against_jv_amount}
else:
return {"debit": -1* against_jv_amount}
elif args.get("doctype") == "Sales Invoice":
return {
"credit": flt(frappe.db.get_value("Sales Invoice", args["docname"], "outstanding_amount"))
("credit" if against_jv_amount > 0 else "debit"): abs(against_jv_amount)
}
elif args.get("doctype") == "Sales Invoice":
outstanding_amount = flt(frappe.db.get_value("Sales Invoice", args["docname"], "outstanding_amount"))
return {
("credit" if outstanding_amount > 0 else "debit"): abs(outstanding_amount)
}
elif args.get("doctype") == "Purchase Invoice":
outstanding_amount = flt(frappe.db.get_value("Purchase Invoice", args["docname"], "outstanding_amount"))
return {
"debit": flt(frappe.db.get_value("Purchase Invoice", args["docname"], "outstanding_amount"))
("debit" if outstanding_amount > 0 else "credit"): abs(outstanding_amount)
}
@frappe.whitelist()
def get_party_account_and_balance(company, party_type, party):
if not frappe.has_permission("Account"):
frappe.msgprint(_("No Permission"), raise_exception=1)
from erpnext.accounts.party import get_party_account
account = get_party_account(company, party, party_type)
@@ -582,3 +653,16 @@ def get_party_account_and_balance(company, party_type, party):
"balance": account_balance,
"party_balance": party_balance
}
@frappe.whitelist()
def get_account_balance_and_party_type(account, date):
"""Returns dict of account balance and party type to be set in Journal Entry on selection of account."""
if not frappe.has_permission("Account"):
frappe.msgprint(_("No Permission"), raise_exception=1)
account_type = frappe.db.get_value("Account", account, "account_type")
return {
"balance": get_balance_on(account, date),
"party_type": {"Receivable":"Customer", "Payable":"Supplier"}.get(account_type, "")
}

View File

@@ -29,10 +29,6 @@ class TestJournalEntry(unittest.TestCase):
def jv_against_voucher_testcase(self, base_jv, test_voucher):
dr_or_cr = "credit" if test_voucher.doctype in ["Sales Order", "Journal Entry"] else "debit"
field_dict = {'Journal Entry': "against_jv",
'Sales Order': "against_sales_order",
'Purchase Order': "against_purchase_order"
}
test_voucher.insert()
test_voucher.submit()
@@ -42,21 +38,20 @@ class TestJournalEntry(unittest.TestCase):
where account = %s and docstatus = 1 and parent = %s""",
("_Test Receivable - _TC", test_voucher.name)))
self.assertTrue(not frappe.db.sql("""select name from `tabJournal Entry Account`
where %s=%s""" % (field_dict.get(test_voucher.doctype), '%s'), (test_voucher.name)))
self.assertFalse(frappe.db.sql("""select name from `tabJournal Entry Account`
where reference_type = %s and reference_name = %s""", (test_voucher.doctype, test_voucher.name)))
base_jv.get("accounts")[0].is_advance = "Yes" if (test_voucher.doctype in ["Sales Order", "Purchase Order"]) else "No"
base_jv.get("accounts")[0].set(field_dict.get(test_voucher.doctype), test_voucher.name)
base_jv.get("accounts")[0].set("reference_type", test_voucher.doctype)
base_jv.get("accounts")[0].set("reference_name", test_voucher.name)
base_jv.insert()
base_jv.submit()
submitted_voucher = frappe.get_doc(test_voucher.doctype, test_voucher.name)
self.assertTrue(frappe.db.sql("""select name from `tabJournal Entry Account`
where %s=%s""" % (field_dict.get(test_voucher.doctype), '%s'), (submitted_voucher.name)))
self.assertTrue(frappe.db.sql("""select name from `tabJournal Entry Account`
where %s=%s and %s=400""" % (field_dict.get(submitted_voucher.doctype), '%s', dr_or_cr), (submitted_voucher.name)))
where reference_type = %s and reference_name = %s and {0}=400""".format(dr_or_cr),
(submitted_voucher.doctype, submitted_voucher.name)))
if base_jv.get("accounts")[0].is_advance == "Yes":
self.advance_paid_testcase(base_jv, submitted_voucher, dr_or_cr)
@@ -74,8 +69,8 @@ class TestJournalEntry(unittest.TestCase):
if test_voucher.doctype == "Journal Entry":
# if test_voucher is a Journal Entry, test cancellation of test_voucher
test_voucher.cancel()
self.assertTrue(not frappe.db.sql("""select name from `tabJournal Entry Account`
where against_jv=%s""", test_voucher.name))
self.assertFalse(frappe.db.sql("""select name from `tabJournal Entry Account`
where reference_type='Journal Entry' and reference_name=%s""", test_voucher.name))
elif test_voucher.doctype in ["Sales Order", "Purchase Order"]:
# if test_voucher is a Sales Order/Purchase Order, test error on cancellation of test_voucher
@@ -102,23 +97,23 @@ class TestJournalEntry(unittest.TestCase):
def test_monthly_budget_crossed_ignore(self):
frappe.db.set_value("Company", "_Test Company", "monthly_bgt_flag", "Ignore")
self.set_total_expense_zero("2013-02-28")
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
"_Test Account Bank Account - _TC", 40000, "_Test Cost Center - _TC", submit=True)
self.assertTrue(frappe.db.get_value("GL Entry",
{"voucher_type": "Journal Entry", "voucher_no": jv.name}))
def test_monthly_budget_crossed_stop(self):
frappe.db.set_value("Company", "_Test Company", "monthly_bgt_flag", "Stop")
self.set_total_expense_zero("2013-02-28")
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
"_Test Account Bank Account - _TC", 40000, "_Test Cost Center - _TC")
self.assertRaises(BudgetError, jv.submit)
frappe.db.set_value("Company", "_Test Company", "monthly_bgt_flag", "Ignore")
@@ -127,37 +122,37 @@ class TestJournalEntry(unittest.TestCase):
self.test_monthly_budget_crossed_ignore()
frappe.db.set_value("Company", "_Test Company", "yearly_bgt_flag", "Stop")
self.set_total_expense_zero("2013-02-28")
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
"_Test Account Bank Account - _TC", 150000, "_Test Cost Center - _TC")
self.assertRaises(BudgetError, jv.submit)
frappe.db.set_value("Company", "_Test Company", "yearly_bgt_flag", "Ignore")
def test_monthly_budget_on_cancellation(self):
self.set_total_expense_zero("2013-02-28")
jv1 = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
jv1 = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
"_Test Account Bank Account - _TC", 20000, "_Test Cost Center - _TC", submit=True)
self.assertTrue(frappe.db.get_value("GL Entry",
{"voucher_type": "Journal Entry", "voucher_no": jv1.name}))
jv2 = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
jv2 = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
"_Test Account Bank Account - _TC", 20000, "_Test Cost Center - _TC", submit=True)
self.assertTrue(frappe.db.get_value("GL Entry",
{"voucher_type": "Journal Entry", "voucher_no": jv2.name}))
frappe.db.set_value("Company", "_Test Company", "monthly_bgt_flag", "Stop")
self.assertRaises(BudgetError, jv1.cancel)
frappe.db.set_value("Company", "_Test Company", "monthly_bgt_flag", "Ignore")
def get_actual_expense(self, monthly_end_date):
return get_actual_expense({
"account": "_Test Account Cost for Goods Sold - _TC",
@@ -166,19 +161,19 @@ class TestJournalEntry(unittest.TestCase):
"company": "_Test Company",
"fiscal_year": get_fiscal_year(monthly_end_date)[0]
})
def set_total_expense_zero(self, posting_date):
existing_expense = self.get_actual_expense(posting_date)
make_journal_entry("_Test Account Cost for Goods Sold - _TC",
make_journal_entry("_Test Account Cost for Goods Sold - _TC",
"_Test Account Bank Account - _TC", -existing_expense, "_Test Cost Center - _TC", submit=True)
def make_journal_entry(account1, account2, amount, cost_center=None, submit=False):
jv = frappe.new_doc("Journal Entry")
jv.posting_date = "2013-02-14"
jv.company = "_Test Company"
jv.fiscal_year = "_Test Fiscal Year 2013"
jv.user_remark = "test"
jv.set("accounts", [
{
"account": account1,
@@ -193,11 +188,11 @@ def make_journal_entry(account1, account2, amount, cost_center=None, submit=Fals
}
])
jv.insert()
if submit:
jv.submit()
return jv
test_records = frappe.get_test_records('Journal Entry')

View File

@@ -1,28 +1,45 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "hash",
"creation": "2013-02-22 01:27:39",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"fields": [
{
"allow_on_submit": 0,
"fieldname": "account",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 1,
"label": "Account",
"no_copy": 0,
"oldfieldname": "account",
"oldfieldtype": "Link",
"options": "Account",
"permlevel": 0,
"print_hide": 0,
"print_width": "250px",
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 1,
"set_only_once": 0,
"unique": 0,
"width": "250px"
},
{
"allow_on_submit": 0,
"fieldname": "balance",
"fieldtype": "Currency",
"in_list_view": 1,
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Account Balance",
"no_copy": 1,
"oldfieldname": "balance",
@@ -30,186 +47,336 @@
"options": "Company:company:default_currency",
"permlevel": 0,
"print_hide": 1,
"read_only": 1
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"default": ":Company",
"description": "If Income or Expense",
"fieldname": "cost_center",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 1,
"in_list_view": 0,
"label": "Cost Center",
"no_copy": 0,
"oldfieldname": "cost_center",
"oldfieldtype": "Link",
"options": "Cost Center",
"permlevel": 0,
"print_hide": 1,
"print_width": "180px",
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0,
"width": "180px"
},
{
"allow_on_submit": 0,
"fieldname": "col_break1",
"fieldtype": "Column Break",
"permlevel": 0
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "party_type",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Party Type",
"no_copy": 0,
"options": "DocType",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "party",
"fieldtype": "Dynamic Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Party",
"no_copy": 0,
"options": "party_type",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "party_balance",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Party Balance",
"no_copy": 0,
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "sec_break1",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Amount",
"permlevel": 0
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "debit",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Debit",
"no_copy": 0,
"oldfieldname": "debit",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "col_break2",
"fieldtype": "Column Break",
"permlevel": 0
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "credit",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Credit",
"no_copy": 0,
"oldfieldname": "credit",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "reference",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Reference",
"permlevel": 0
},
{
"fieldname": "against_invoice",
"fieldtype": "Link",
"in_filter": 1,
"label": "Against Sales Invoice",
"no_copy": 1,
"oldfieldname": "against_invoice",
"oldfieldtype": "Link",
"options": "Sales Invoice",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"search_index": 1
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"fieldname": "against_voucher",
"fieldtype": "Link",
"in_filter": 1,
"allow_on_submit": 0,
"fieldname": "reference_type",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Reference Type",
"no_copy": 0,
"options": "\nSales Invoice\nPurchase Invoice\nJournal Entry\nSales Order\nPurchase Order\nExpense Claim",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "reference_name",
"fieldtype": "Dynamic Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Against Purchase Invoice",
"no_copy": 1,
"oldfieldname": "against_voucher",
"oldfieldtype": "Link",
"options": "Purchase Invoice",
"label": "Reference Name",
"no_copy": 0,
"options": "reference_type",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"search_index": 1
},
{
"fieldname": "against_jv",
"fieldtype": "Link",
"in_filter": 1,
"label": "Against Journal Entry",
"no_copy": 1,
"oldfieldname": "against_jv",
"oldfieldtype": "Link",
"options": "Journal Entry",
"permlevel": 0,
"print_hide": 0,
"search_index": 1
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "col_break3",
"fieldtype": "Column Break",
"permlevel": 0
},
{
"fieldname": "against_sales_order",
"fieldtype": "Link",
"label": "Against Sales Order",
"options": "Sales Order",
"permlevel": 0
},
{
"fieldname": "against_purchase_order",
"fieldtype": "Link",
"label": "Against Purchase Order",
"options": "Purchase Order",
"permlevel": 0
},
{
"fieldname": "against_expense_claim",
"fieldtype": "Link",
"label": "Against Expense Claim",
"options": "Expense Claim",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": ""
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "is_advance",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Is Advance",
"no_copy": 1,
"oldfieldname": "is_advance",
"oldfieldtype": "Select",
"options": "No\nYes",
"permlevel": 0,
"print_hide": 1
"print_hide": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "against_account",
"fieldtype": "Text",
"hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Against Account",
"no_copy": 1,
"oldfieldname": "against_account",
"oldfieldtype": "Text",
"permlevel": 0,
"print_hide": 1
"print_hide": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 1,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-02-19 01:07:00.388689",
"modified": "2015-08-17 02:11:33.991361",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Journal Entry Account",
"owner": "Administrator",
"permissions": []
"permissions": [],
"read_only": 0,
"read_only_onload": 0
}

View File

@@ -34,8 +34,8 @@ class PaymentReconciliation(Document):
t1.name = t2.parent and t1.docstatus = 1 and t2.docstatus = 1
and t2.party_type = %(party_type)s and t2.party = %(party)s
and t2.account = %(account)s and {dr_or_cr} > 0
and ifnull(t2.against_voucher, '')='' and ifnull(t2.against_invoice, '')=''
and ifnull(t2.against_jv, '')='' {cond}
and ifnull(t2.reference_type, '') in ('', 'Sales Order', 'Purchase Order')
{cond}
and (CASE
WHEN t1.voucher_type in ('Debit Note', 'Credit Note')
THEN 1=1
@@ -190,11 +190,11 @@ class PaymentReconciliation(Document):
if flt(p.allocated_amount) > flt(p.amount):
frappe.throw(_("Row {0}: Allocated amount {1} must be less than or equals to JV amount {2}")
.format(p.idx, p.allocated_amount, p.amount))
invoice_outstanding = unreconciled_invoices.get(p.invoice_type, {}).get(p.invoice_number)
if abs(flt(p.allocated_amount) - invoice_outstanding) > 0.009:
if flt(p.allocated_amount) - invoice_outstanding > 0.009:
frappe.throw(_("Row {0}: Allocated amount {1} must be less than or equals to invoice outstanding amount {2}")
.format(p.idx, p.allocated_amount, unreconciled_invoices.get(p.invoice_type, {}).get(p.invoice_number)))
.format(p.idx, p.allocated_amount, invoice_outstanding))
if not invoices_to_reconcile:
frappe.throw(_("Please select Allocated Amount, Invoice Type and Invoice Number in atleast one row"))

View File

@@ -12,13 +12,6 @@ class PaymentTool(Document):
def make_journal_entry(self):
from erpnext.accounts.utils import get_balance_on
total_payment_amount = 0.00
invoice_voucher_type = {
'Sales Invoice': 'against_invoice',
'Purchase Invoice': 'against_voucher',
'Journal Entry': 'against_jv',
'Sales Order': 'against_sales_order',
'Purchase Order': 'against_purchase_order',
}
jv = frappe.new_doc('Journal Entry')
jv.voucher_type = 'Journal Entry'
@@ -41,7 +34,8 @@ class PaymentTool(Document):
d1.party = self.party
d1.balance = get_balance_on(self.party_account)
d1.set("debit" if self.received_or_paid=="Paid" else "credit", flt(v.payment_amount))
d1.set(invoice_voucher_type.get(v.against_voucher_type), v.against_voucher_no)
d1.set("reference_type", v.against_voucher_type)
d1.set("reference_name", v.against_voucher_no)
d1.set('is_advance', 'Yes' if v.against_voucher_type in ['Sales Order', 'Purchase Order'] else 'No')
total_payment_amount = flt(total_payment_amount) + flt(d1.debit) - flt(d1.credit)

View File

@@ -23,10 +23,11 @@ class TestPaymentTool(unittest.TestCase):
# Create SO with partial outstanding
so1 = make_sales_order(customer="_Test Customer 3", qty=10, rate=100)
self.create_against_jv(jv_test_records[0], {
"party": "_Test Customer 3",
"against_sales_order": so1.name,
"reference_type": "Sales Order",
"reference_name": so1.name,
"is_advance": "Yes"
})
@@ -36,7 +37,8 @@ class TestPaymentTool(unittest.TestCase):
self.create_against_jv(jv_test_records[0], {
"party": "_Test Customer 3",
"against_sales_order": so2.name,
"reference_type": "Sales Order",
"reference_name": so2.name,
"credit": 1000,
"is_advance": "Yes"
})
@@ -52,7 +54,8 @@ class TestPaymentTool(unittest.TestCase):
self.create_against_jv(jv_test_records[0], {
"party": "_Test Customer 3",
"against_invoice": si1.name
"reference_type": si1.doctype,
"reference_name": si1.name
})
#Create SI with no outstanding
si2 = self.create_voucher(si_test_records[0], {
@@ -62,7 +65,8 @@ class TestPaymentTool(unittest.TestCase):
self.create_against_jv(jv_test_records[0], {
"party": "_Test Customer 3",
"against_invoice": si2.name,
"reference_type": si2.doctype,
"reference_name": si2.name,
"credit": 561.80
})
@@ -125,7 +129,7 @@ class TestPaymentTool(unittest.TestCase):
def make_voucher_for_party(self, args, expected_outstanding):
#Make Journal Entry for Party
payment_tool_doc = frappe.new_doc("Payment Tool")
for k, v in args.items():
payment_tool_doc.set(k, v)
@@ -153,29 +157,12 @@ class TestPaymentTool(unittest.TestCase):
new_jv = paytool.make_journal_entry()
#Create a list of expected values as [party account, payment against, against_jv, against_invoice,
#against_voucher, against_sales_order, against_purchase_order]
expected_values = [
[paytool.party_account, paytool.party, 100.00, expected_outstanding.get("Journal Entry")[0], None, None, None, None],
[paytool.party_account, paytool.party, 100.00, None, expected_outstanding.get("Sales Invoice")[0], None, None, None],
[paytool.party_account, paytool.party, 100.00, None, None, expected_outstanding.get("Purchase Invoice")[0], None, None],
[paytool.party_account, paytool.party, 100.00, None, None, None, expected_outstanding.get("Sales Order")[0], None],
[paytool.party_account, paytool.party, 100.00, None, None, None, None, expected_outstanding.get("Purchase Order")[0]]
]
for jv_entry in new_jv.get("accounts"):
if paytool.party_account == jv_entry.get("account") and paytool.party == jv_entry.get("party"):
row = [
jv_entry.get("account"),
jv_entry.get("party"),
jv_entry.get("debit" if paytool.party_type=="Supplier" else "credit"),
jv_entry.get("against_jv"),
jv_entry.get("against_invoice"),
jv_entry.get("against_voucher"),
jv_entry.get("against_sales_order"),
jv_entry.get("against_purchase_order"),
]
self.assertTrue(row in expected_values)
self.assertEquals(100.00,
jv_entry.get("debit" if paytool.party_type=="Supplier" else "credit"))
self.assertEquals(jv_entry.reference_name,
expected_outstanding[jv_entry.reference_type][0])
self.assertEquals(new_jv.get("cheque_no"), paytool.reference_no)
self.assertEquals(new_jv.get("cheque_date"), paytool.reference_date)

View File

@@ -6,6 +6,14 @@ frappe.ui.form.on("POS Profile", "onload", function(frm) {
return { filter: { selling: 1 } };
});
frm.set_query("print_format", function() {
return { filter: { doc_type: "Sales Invoice" } };
});
erpnext.queries.setup_queries(frm, "Warehouse", function() {
return erpnext.queries.warehouse(frm.doc);
});
frm.call({
method: "erpnext.accounts.doctype.pos_profile.pos_profile.get_series",
callback: function(r) {

View File

@@ -1,37 +1,42 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "hash",
"creation": "2013-05-24 12:15:51",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"fields": [
{
"allow_on_submit": 0,
"fieldname": "user",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "User",
"label": "Applicable for User",
"no_copy": 0,
"oldfieldname": "user",
"oldfieldtype": "Link",
"options": "User",
"permlevel": 0,
"read_only": 0
},
{
"description": "",
"fieldname": "territory",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Territory",
"oldfieldname": "territory",
"oldfieldtype": "Link",
"options": "Territory",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"reqd": 0
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "naming_series",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Series",
"no_copy": 1,
@@ -39,232 +44,581 @@
"oldfieldtype": "Select",
"options": "[Select]",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"reqd": 1
},
{
"fieldname": "currency",
"fieldtype": "Link",
"in_list_view": 0,
"label": "Currency",
"oldfieldname": "currency",
"oldfieldtype": "Select",
"options": "Currency",
"permlevel": 0,
"read_only": 0,
"reqd": 1
},
{
"fieldname": "selling_price_list",
"fieldtype": "Link",
"label": "Price List",
"oldfieldname": "price_list_name",
"oldfieldtype": "Select",
"options": "Price List",
"permlevel": 0,
"read_only": 0,
"reqd": 0
},
{
"fieldname": "company",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Company",
"oldfieldname": "company",
"oldfieldtype": "Link",
"options": "Company",
"permlevel": 0,
"read_only": 0,
"reqd": 1
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "warehouse",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Warehouse",
"no_copy": 0,
"oldfieldname": "warehouse",
"oldfieldtype": "Link",
"options": "Warehouse",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"reqd": 0
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"default": "1",
"description": "",
"fieldname": "update_stock",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Update Stock",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break_4",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "customer",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Customer",
"no_copy": 0,
"oldfieldname": "customer_account",
"oldfieldtype": "Link",
"options": "Customer",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Company",
"no_copy": 0,
"oldfieldname": "company",
"oldfieldtype": "Link",
"options": "Company",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "currency",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Currency",
"no_copy": 0,
"oldfieldname": "currency",
"oldfieldtype": "Select",
"options": "Currency",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "mode_of_payment",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Mode of Payment",
"no_copy": 0,
"options": "Mode of Payment",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "section_break_16",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "print_format",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Print Format",
"no_copy": 0,
"options": "Print Format",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 1,
"fieldname": "letter_head",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Letter Head",
"no_copy": 0,
"oldfieldname": "letter_head",
"oldfieldtype": "Select",
"options": "Letter Head",
"permlevel": 0,
"print_hide": 1,
"read_only": 0
},
{
"fieldname": "tc_name",
"fieldtype": "Link",
"label": "Terms and Conditions",
"oldfieldname": "tc_name",
"oldfieldtype": "Link",
"options": "Terms and Conditions",
"permlevel": 0,
"read_only": 0
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 1,
"fieldname": "select_print_heading",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Print Heading",
"no_copy": 0,
"oldfieldname": "select_print_heading",
"oldfieldtype": "Select",
"options": "Print Heading",
"permlevel": 0,
"read_only": 0
},
{
"fieldname": "column_break0",
"fieldtype": "Column Break",
"oldfieldtype": "Column Break",
"permlevel": 0,
"read_only": 0
},
{
"default": "1",
"description": "Create Stock Ledger Entries when you submit a Sales Invoice",
"fieldname": "update_stock",
"fieldtype": "Check",
"label": "Update Stock",
"permlevel": 0,
"reqd": 0
},
{
"fieldname": "customer",
"fieldtype": "Link",
"in_list_view": 0,
"label": "Customer",
"oldfieldname": "customer_account",
"oldfieldtype": "Link",
"options": "Customer",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"reqd": 0
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"fieldname": "mode_of_payment",
"fieldtype": "Link",
"label": "Mode of Payment",
"options": "Mode of Payment",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "cash_bank_account",
"fieldtype": "Link",
"label": "Cash/Bank Account",
"oldfieldname": "cash_bank_account",
"oldfieldtype": "Link",
"options": "Account",
"permlevel": 0,
"read_only": 0,
"reqd": 0
},
{
"fieldname": "income_account",
"fieldtype": "Link",
"label": "Income Account",
"oldfieldname": "income_account",
"oldfieldtype": "Link",
"options": "Account",
"permlevel": 0,
"read_only": 0,
"reqd": 0
},
{
"depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)",
"fieldname": "expense_account",
"allow_on_submit": 0,
"fieldname": "tc_name",
"fieldtype": "Link",
"hidden": 0,
"label": "Expense Account",
"options": "Account",
"permlevel": 0,
"print_hide": 1,
"read_only": 0,
"reqd": 0
},
{
"fieldname": "cost_center",
"fieldtype": "Link",
"label": "Cost Center",
"oldfieldname": "cost_center",
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Terms and Conditions",
"no_copy": 0,
"oldfieldname": "tc_name",
"oldfieldtype": "Link",
"options": "Cost Center",
"options": "Terms and Conditions",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"reqd": 0
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break0",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"oldfieldtype": "Column Break",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"description": "",
"fieldname": "territory",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Territory",
"no_copy": 0,
"oldfieldname": "territory",
"oldfieldtype": "Link",
"options": "Territory",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "selling_price_list",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Price List",
"no_copy": 0,
"oldfieldname": "price_list_name",
"oldfieldtype": "Select",
"options": "Price List",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "section_break_19",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "write_off_account",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Write Off Account",
"no_copy": 0,
"options": "Account",
"permlevel": 0,
"precision": "",
"reqd": 1
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "write_off_cost_center",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Write Off Cost Center",
"no_copy": 0,
"options": "Cost Center",
"permlevel": 0,
"precision": "",
"reqd": 1
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "taxes_and_charges",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Taxes and Charges",
"no_copy": 0,
"oldfieldname": "charge",
"oldfieldtype": "Link",
"options": "Sales Taxes and Charges Template",
"permlevel": 0,
"read_only": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break_23",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "cash_bank_account",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Cash/Bank Account",
"no_copy": 0,
"oldfieldname": "cash_bank_account",
"oldfieldtype": "Link",
"options": "Account",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "income_account",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Income Account",
"no_copy": 0,
"oldfieldname": "income_account",
"oldfieldtype": "Link",
"options": "Account",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)",
"fieldname": "expense_account",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Expense Account",
"no_copy": 0,
"options": "Account",
"permlevel": 0,
"print_hide": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "cost_center",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Cost Center",
"no_copy": 0,
"oldfieldname": "cost_center",
"oldfieldtype": "Link",
"options": "Cost Center",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "icon-cog",
"idx": 1,
"modified": "2015-07-28 15:07:14.417200",
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-08-18 17:49:09.098876",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Profile",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"apply_user_permissions": 1,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts User",
"submit": 0
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
}
],
"read_only": 0,
"read_only_onload": 0,
"sort_field": "modified",
"sort_order": "DESC",
"title_field": "user"

View File

@@ -11,7 +11,6 @@ from frappe.model.document import Document
class POSProfile(Document):
def validate(self):
self.check_for_duplicate()
self.validate_expense_account()
self.validate_all_link_fields()
def check_for_duplicate(self):
@@ -26,11 +25,6 @@ class POSProfile(Document):
msgprint(_("Global POS Profile {0} already created for company {1}").format(res[0][0],
self.company), raise_exception=1)
def validate_expense_account(self):
if cint(frappe.defaults.get_global_default("auto_accounting_for_stock")) \
and not self.expense_account:
msgprint(_("Expense Account is mandatory"), raise_exception=1)
def validate_all_link_fields(self):
accounts = {"Account": [self.cash_bank_account, self.income_account,
self.expense_account], "Cost Center": [self.cost_center],

File diff suppressed because it is too large Load Diff

View File

@@ -147,6 +147,7 @@ def get_pricing_rule_for_item(args):
if pricing_rule:
item_details.pricing_rule = pricing_rule.name
item_details.pricing_rule_for = pricing_rule.price_or_discount
if pricing_rule.price_or_discount == "Price":
item_details.update({
"price_list_rate": pricing_rule.price/flt(args.conversion_rate) \

View File

@@ -21,16 +21,15 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
// Show / Hide button
this.show_general_ledger();
if(!doc.is_return) {
if(doc.docstatus==1) {
if(doc.outstanding_amount > 0) {
this.frm.add_custom_button(__('Make Payment Entry'), this.make_bank_entry);
this.frm.add_custom_button(__('Payment'), this.make_bank_entry).addClass("btn-primary");
}
cur_frm.add_custom_button(__('Make Debit Note'), this.make_debit_note);
cur_frm.add_custom_button(__('Debit Note'), this.make_debit_note);
}
if(doc.docstatus===0) {
cur_frm.add_custom_button(__('From Purchase Order'), function() {
frappe.model.map_current_doc({
@@ -102,7 +101,7 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
if(row.purchase_receipt) frappe.model.clear_doc("Purchase Receipt", row.purchase_receipt)
})
},
make_debit_note: function() {
frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.purchase_invoice.purchase_invoice.make_debit_note",

View File

@@ -41,8 +41,8 @@ class PurchaseInvoice(BuyingController):
self.po_required()
self.pr_required()
self.validate_supplier_invoice()
self.validate_advance_jv("advances", "purchase_order")
self.validate_advance_jv("Purchase Order")
self.check_active_purchase_items()
self.check_conversion_rate()
self.validate_credit_to_acc()
@@ -233,7 +233,7 @@ class PurchaseInvoice(BuyingController):
self.update_against_document_in_jv()
self.update_prevdoc_status()
self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
self.update_project()
def make_gl_entries(self):
@@ -365,7 +365,7 @@ class PurchaseInvoice(BuyingController):
def on_cancel(self):
if not self.is_return:
from erpnext.accounts.utils import remove_against_link_from_jv
remove_against_link_from_jv(self.doctype, self.name, "against_voucher")
remove_against_link_from_jv(self.doctype, self.name)
self.update_prevdoc_status()
self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
@@ -413,4 +413,4 @@ def get_expense_account(doctype, txt, searchfield, start, page_len, filters):
@frappe.whitelist()
def make_debit_note(source_name, target_doc=None):
from erpnext.controllers.sales_and_purchase_return import make_return_doc
return make_return_doc("Purchase Invoice", source_name, target_doc)
return make_return_doc("Purchase Invoice", source_name, target_doc)

View File

@@ -218,71 +218,47 @@ class TestPurchaseInvoice(unittest.TestCase):
pi.load_from_db()
self.assertTrue(frappe.db.sql("""select name from `tabJournal Entry Account`
where against_voucher=%s""", pi.name))
self.assertTrue(frappe.db.sql("""select name from `tabJournal Entry Account`
where against_voucher=%s and debit=300""", pi.name))
where reference_type='Purchase Invoice' and reference_name=%s and debit=300""", pi.name))
self.assertEqual(pi.outstanding_amount, 1212.30)
pi.cancel()
self.assertTrue(not frappe.db.sql("""select name from `tabJournal Entry Account`
where against_voucher=%s""", pi.name))
self.assertFalse(frappe.db.sql("""select name from `tabJournal Entry Account`
where reference_type='Purchase Invoice' and reference_name=%s""", pi.name))
def test_recurring_invoice(self):
from erpnext.controllers.tests.test_recurring_document import test_recurring_document
test_recurring_document(self, test_records)
def test_total_purchase_cost_for_project(self):
existing_purchase_cost = frappe.db.sql("""select sum(ifnull(base_net_amount, 0))
from `tabPurchase Invoice Item` where project_name = '_Test Project' and docstatus=1""")
existing_purchase_cost = existing_purchase_cost and existing_purchase_cost[0][0] or 0
def test_total_purchase_cost_for_project(self):
purchase_invoice = frappe.new_doc('Purchase Invoice')
purchase_invoice.update({
"credit_to": "_Test Payable - _TC",
"supplier": "_Test Supplier",
"company": "_Test Company",
"items": [
{
"rate": 500,
"qty": 1,
"project_name": "_Test Project",
"item_code": "_Test Item Home Desktop 100",
"expense_account": "_Test Account Cost for Goods Sold - _TC",
"cost_center": "_Test Cost Center - _TC"
},
{
"rate": 1500,
"qty": 1,
"project_name": "_Test Project",
"item_code": "_Test Item Home Desktop 200",
"expense_account": "_Test Account Cost for Goods Sold - _TC",
"cost_center": "_Test Cost Center - _TC"
}
]
})
purchase_invoice.save()
purchase_invoice.submit()
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"), 2000)
purchase_invoice1 = frappe.copy_doc(purchase_invoice)
purchase_invoice1.save()
purchase_invoice1.submit()
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"), 4000)
purchase_invoice1.cancel()
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"), 2000)
purchase_invoice.cancel()
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"), 0)
pi = make_purchase_invoice(currency="USD", conversion_rate=60, project_name="_Test Project")
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"),
existing_purchase_cost + 15000)
pi1 = make_purchase_invoice(qty=10, project_name="_Test Project")
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"),
existing_purchase_cost + 15500)
pi1.cancel()
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"),
existing_purchase_cost + 15000)
pi.cancel()
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"), existing_purchase_cost)
def test_return_purchase_invoice(self):
set_perpetual_inventory()
pi = make_purchase_invoice()
return_pi = make_purchase_invoice(is_return=1, return_against=pi.name, qty=-2)
# check gl entries for return
gl_entries = frappe.db.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type=%s and voucher_no=%s
@@ -298,9 +274,9 @@ class TestPurchaseInvoice(unittest.TestCase):
for gle in gl_entries:
self.assertEquals(expected_values[gle.account][0], gle.debit)
self.assertEquals(expected_values[gle.account][1], gle.credit)
set_perpetual_inventory(0)
def make_purchase_invoice(**args):
pi = frappe.new_doc("Purchase Invoice")
args = frappe._dict(args)
@@ -311,9 +287,10 @@ def make_purchase_invoice(**args):
pi.company = args.company or "_Test Company"
pi.supplier = args.supplier or "_Test Supplier"
pi.currency = args.currency or "INR"
pi.conversion_rate = args.conversion_rate or 1
pi.is_return = args.is_return
pi.return_against = args.return_against
pi.append("items", {
"item_code": args.item or args.item_code or "_Test Item",
"warehouse": args.warehouse or "_Test Warehouse - _TC",
@@ -321,7 +298,9 @@ def make_purchase_invoice(**args):
"rate": args.rate or 50,
"conversion_factor": 1.0,
"serial_no": args.serial_no,
"stock_uom": "_Test UOM"
"stock_uom": "_Test UOM",
"cost_center": "_Test Cost Center - _TC",
"project_name": args.project_name
})
if not args.do_not_save:
pi.insert()

View File

@@ -28,26 +28,26 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
}
}
// if document is POS then change default print format to "POS Invoice" if no default is specified
if(cur_frm.doc.is_pos && cur_frm.doc.docstatus===1 && cint(frappe.defaults.get_user_defaults("fs_pos_view"))===1
&& !locals.DocType[cur_frm.doctype].default_print_format) {
locals.DocType[cur_frm.doctype].default_print_format = "POS Invoice";
cur_frm.setup_print_layout();
}
erpnext.queries.setup_queries(this.frm, "Warehouse", function() {
return erpnext.queries.warehouse(me.frm.doc);
});
},
refresh: function(doc, dt, dn) {
this._super();
cur_frm.dashboard.reset();
this.frm.toggle_reqd("due_date", !this.frm.doc.is_return);
this.show_general_ledger();
if(doc.update_stock) this.show_stock_ledger();
if(doc.docstatus==1 && !doc.is_return) {
cur_frm.add_custom_button(doc.update_stock ? __('Sales Return') : __('Credit Note'),
this.make_sales_return);
if(cint(doc.update_stock)!=1) {
// show Make Delivery Note button only if Sales Invoice is not created from Delivery Note
var from_delivery_note = false;
@@ -57,16 +57,13 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
});
if(!from_delivery_note) {
cur_frm.add_custom_button(__('Make Delivery'), cur_frm.cscript['Make Delivery Note'])
cur_frm.add_custom_button(__('Delivery'), cur_frm.cscript['Make Delivery Note']).addClass("btn-primary");
}
}
if(doc.outstanding_amount!=0 && !cint(doc.is_return)) {
cur_frm.add_custom_button(__('Make Payment Entry'), cur_frm.cscript.make_bank_entry);
cur_frm.add_custom_button(__('Payment'), cur_frm.cscript.make_bank_entry).addClass("btn-primary");
}
cur_frm.add_custom_button(doc.update_stock ? __('Make Sales Return') : __('Make Credit Note'),
this.make_sales_return);
}
// Show buttons only when pos view is active
@@ -74,6 +71,23 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
cur_frm.cscript.sales_order_btn();
cur_frm.cscript.delivery_note_btn();
}
this.set_default_print_format();
},
set_default_print_format: function() {
// set default print format to POS type
if(cur_frm.doc.is_pos) {
if(cur_frm.pos_print_format) {
cur_frm.meta._default_print_format = cur_frm.meta.default_print_format;
cur_frm.meta.default_print_format = cur_frm.pos_print_format;
}
} else {
if(cur_frm.meta._default_print_format) {
cur_frm.meta.default_print_format = cur_frm.meta._default_print_format;
cur_frm.meta._default_print_format = null;
}
}
},
sales_order_btn: function() {
@@ -118,6 +132,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
},
is_pos: function(doc, dt, dn, callback_fn) {
if(cur_frm.doc.__missing_values_set) return;
cur_frm.cscript.hide_fields(this.frm.doc);
if(cint(this.frm.doc.is_pos)) {
if(!this.frm.doc.company) {
@@ -130,6 +145,8 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
method: "set_missing_values",
callback: function(r) {
if(!r.exc) {
cur_frm.pos_print_format = r.message.print_format;
cur_frm.doc.__missing_values_set = true;
me.frm.script_manager.trigger("update_stock");
frappe.model.set_default_values(me.frm.doc);
me.set_dynamic_labels();
@@ -201,7 +218,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
items_on_form_rendered: function() {
erpnext.setup_serial_no();
},
make_sales_return: function() {
frappe.model.open_mapped_doc({
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.make_sales_return",
@@ -376,10 +393,13 @@ cur_frm.cscript.on_submit = function(doc, cdt, cdn) {
if(row.delivery_note) frappe.model.clear_doc("Delivery Note", row.delivery_note)
})
if(cint(frappe.boot.notification_settings.sales_invoice)) {
if(cur_frm.doc.is_pos) {
frappe.msgprint('<a class="btn btn-primary" \
onclick="cur_frm.print_preview.printit(true)" style="margin-right: 5px;">Print</a>\
<a class="btn btn-default" href="#Form/Sales Invoice/New">New</a>');
} else if(cint(frappe.boot.notification_settings.sales_invoice)) {
cur_frm.email_doc(frappe.boot.notification_settings.sales_invoice_message);
} else if(cur_frm.doc.is_pos) {
new_doc("Sales Invoice");
}
}
@@ -390,4 +410,4 @@ cur_frm.set_query("debit_to", function(doc) {
['Account', 'account_type', '=', 'Receivable']
]
}
});
});

View File

@@ -46,7 +46,7 @@ class SalesInvoice(SellingController):
self.validate_debit_to_acc()
self.validate_fixed_asset_account()
self.clear_unallocated_advances("Sales Invoice Advance", "advances")
self.validate_advance_jv("advances", "sales_order")
self.validate_advance_jv("Sales Order")
self.add_remarks()
self.validate_write_off_account()
@@ -105,7 +105,7 @@ class SalesInvoice(SellingController):
self.check_stop_sales_order("sales_order")
from erpnext.accounts.utils import remove_against_link_from_jv
remove_against_link_from_jv(self.doctype, self.name, "against_invoice")
remove_against_link_from_jv(self.doctype, self.name)
if not self.is_return:
self.update_status_updater_args()
@@ -139,7 +139,7 @@ class SalesInvoice(SellingController):
})
def set_missing_values(self, for_validate=False):
self.set_pos_fields(for_validate)
pos = self.set_pos_fields(for_validate)
if not self.debit_to:
self.debit_to = get_party_account(self.company, self.customer, "Customer")
@@ -148,6 +148,9 @@ class SalesInvoice(SellingController):
super(SalesInvoice, self).set_missing_values(for_validate)
if pos:
return {"print_format": pos.get("print_format") }
def update_time_log_batch(self, sales_invoice):
for d in self.get("items"):
if d.time_log_batch:
@@ -168,8 +171,8 @@ class SalesInvoice(SellingController):
if cint(self.is_pos) != 1:
return
from erpnext.stock.get_item_details import get_pos_profiles_item_details, get_pos_profiles
pos = get_pos_profiles(self.company)
from erpnext.stock.get_item_details import get_pos_profile_item_details, get_pos_profile
pos = get_pos_profile(self.company)
if pos:
if not for_validate and not self.customer:
@@ -189,7 +192,7 @@ class SalesInvoice(SellingController):
# set pos values in items
for item in self.get("items"):
if item.get('item_code'):
for fname, val in get_pos_profiles_item_details(pos,
for fname, val in get_pos_profile_item_details(pos,
frappe._dict(item.as_dict()), pos).items():
if (not for_validate) or (for_validate and not item.get(fname)):
@@ -203,6 +206,8 @@ class SalesInvoice(SellingController):
if self.taxes_and_charges and not len(self.get("taxes")):
self.set_taxes()
return pos
def get_advances(self):
if not self.is_return:
super(SalesInvoice, self).get_advances(self.debit_to, "Customer", self.customer,
@@ -420,7 +425,7 @@ class SalesInvoice(SellingController):
for d in self.get_item_list():
if frappe.db.get_value("Item", d.item_code, "is_stock_item") == 1 and d.warehouse and flt(d['qty']):
self.update_reserved_qty(d)
incoming_rate = 0
if cint(self.is_return) and self.return_against and self.docstatus==1:
incoming_rate = self.get_incoming_rate_for_sales_return(d.item_code,
@@ -439,7 +444,7 @@ class SalesInvoice(SellingController):
if gl_entries:
from erpnext.accounts.general_ledger import make_gl_entries
# if POS and amount is written off, there's no outstanding and hence no need to update it
# if POS and amount is written off, updating outstanding amt after posting all gl entries
update_outstanding = "No" if (cint(self.is_pos) or self.write_off_account) else "Yes"
make_gl_entries(gl_entries, cancel=(self.docstatus == 2),
@@ -447,7 +452,8 @@ class SalesInvoice(SellingController):
if update_outstanding == "No":
from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
update_outstanding_amt(self.debit_to, "Customer", self.customer, self.doctype, self.name)
update_outstanding_amt(self.debit_to, "Customer", self.customer,
self.doctype, self.return_against if cint(self.is_return) else self.name)
if repost_future_gle and cint(self.update_stock) \
and cint(frappe.defaults.get_global_default("auto_accounting_for_stock")):

View File

@@ -391,7 +391,8 @@ class TestSalesInvoice(unittest.TestCase):
import test_records as jv_test_records
jv = frappe.get_doc(frappe.copy_doc(jv_test_records[0]))
jv.get("accounts")[0].against_invoice = w.name
jv.get("accounts")[0].reference_type = w.doctype
jv.get("accounts")[0].reference_name = w.name
jv.insert()
jv.submit()
@@ -656,17 +657,17 @@ class TestSalesInvoice(unittest.TestCase):
si.load_from_db()
self.assertTrue(frappe.db.sql("""select name from `tabJournal Entry Account`
where against_invoice=%s""", si.name))
where reference_name=%s""", si.name))
self.assertTrue(frappe.db.sql("""select name from `tabJournal Entry Account`
where against_invoice=%s and credit=300""", si.name))
where reference_name=%s and credit=300""", si.name))
self.assertEqual(si.outstanding_amount, 261.8)
si.cancel()
self.assertTrue(not frappe.db.sql("""select name from `tabJournal Entry Account`
where against_invoice=%s""", si.name))
where reference_name=%s""", si.name))
def test_recurring_invoice(self):
from erpnext.controllers.tests.test_recurring_document import test_recurring_document
@@ -728,68 +729,119 @@ class TestSalesInvoice(unittest.TestCase):
# hack! because stock ledger entires are already inserted and are not rolled back!
self.assertRaises(SerialNoDuplicateError, si.cancel)
def test_invoice_due_date_against_customers_credit_days(self):
# set customer's credit days
frappe.db.set_value("Customer", "_Test Customer", "credit_days_based_on", "Fixed Days")
frappe.db.set_value("Customer", "_Test Customer", "credit_days", 10)
si = create_sales_invoice()
self.assertEqual(si.due_date, add_days(nowdate(), 10))
# set customer's credit days is last day of the next month
frappe.db.set_value("Customer", "_Test Customer", "credit_days_based_on", "Last Day of the Next Month")
si1 = create_sales_invoice(posting_date="2015-07-05")
si1 = create_sales_invoice(posting_date="2015-07-05")
self.assertEqual(si1.due_date, "2015-08-31")
def test_return_sales_invoice(self):
set_perpetual_inventory()
make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, incoming_rate=100)
make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100)
actual_qty_0 = get_qty_after_transaction()
si = create_sales_invoice(qty=5, rate=500, update_stock=1)
actual_qty_1 = get_qty_after_transaction()
self.assertEquals(actual_qty_0 - 5, actual_qty_1)
# outgoing_rate
outgoing_rate = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Sales Invoice",
outgoing_rate = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Sales Invoice",
"voucher_no": si.name}, "stock_value_difference") / 5
# return entry
si1 = create_sales_invoice(is_return=1, return_against=si.name, qty=-2, rate=500, update_stock=1)
actual_qty_2 = get_qty_after_transaction()
self.assertEquals(actual_qty_1 + 2, actual_qty_2)
incoming_rate, stock_value_difference = frappe.db.get_value("Stock Ledger Entry",
{"voucher_type": "Sales Invoice", "voucher_no": si1.name},
incoming_rate, stock_value_difference = frappe.db.get_value("Stock Ledger Entry",
{"voucher_type": "Sales Invoice", "voucher_no": si1.name},
["incoming_rate", "stock_value_difference"])
self.assertEquals(flt(incoming_rate, 3), abs(flt(outgoing_rate, 3)))
# Check gl entry
gle_warehouse_amount = frappe.db.get_value("GL Entry", {"voucher_type": "Sales Invoice",
gle_warehouse_amount = frappe.db.get_value("GL Entry", {"voucher_type": "Sales Invoice",
"voucher_no": si1.name, "account": "_Test Warehouse - _TC"}, "debit")
self.assertEquals(gle_warehouse_amount, stock_value_difference)
party_credited = frappe.db.get_value("GL Entry", {"voucher_type": "Sales Invoice",
party_credited = frappe.db.get_value("GL Entry", {"voucher_type": "Sales Invoice",
"voucher_no": si1.name, "account": "Debtors - _TC", "party": "_Test Customer"}, "credit")
self.assertEqual(party_credited, 1000)
# Check outstanding amount
self.assertFalse(si1.outstanding_amount)
self.assertEqual(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount"), 1500)
set_perpetual_inventory(0)
def test_discount_on_net_total(self):
si = frappe.copy_doc(test_records[2])
si.apply_discount_on = "Net Total"
si.discount_amount = 625
si.insert()
expected_values = {
"keys": ["price_list_rate", "discount_percentage", "rate", "amount",
"base_price_list_rate", "base_rate", "base_amount",
"net_rate", "base_net_rate", "net_amount", "base_net_amount"],
"_Test Item Home Desktop 100": [50, 0, 50, 500, 50, 50, 500, 25, 25, 250, 250],
"_Test Item Home Desktop 200": [150, 0, 150, 750, 150, 150, 750, 75, 75, 375, 375],
}
# check if children are saved
self.assertEquals(len(si.get("items")),
len(expected_values)-1)
# check if item values are calculated
for d in si.get("items"):
for i, k in enumerate(expected_values["keys"]):
self.assertEquals(d.get(k), expected_values[d.item_code][i])
# check net total
self.assertEquals(si.base_total, 1250)
self.assertEquals(si.total, 1250)
self.assertEquals(si.base_net_total, 625)
self.assertEquals(si.net_total, 625)
# check tax calculation
expected_values = {
"keys": ["tax_amount", "tax_amount_after_discount_amount",
"base_tax_amount_after_discount_amount"],
"_Test Account Shipping Charges - _TC": [100, 100, 100],
"_Test Account Customs Duty - _TC": [62.5, 62.5, 62.5],
"_Test Account Excise Duty - _TC": [70, 70, 70],
"_Test Account Education Cess - _TC": [1.4, 1.4, 1.4],
"_Test Account S&H Education Cess - _TC": [.7, 0.7, 0.7],
"_Test Account CST - _TC": [17.2, 17.2, 17.2],
"_Test Account VAT - _TC": [78.13, 78.13, 78.13],
"_Test Account Discount - _TC": [-95.49, -95.49, -95.49]
}
for d in si.get("taxes"):
for i, k in enumerate(expected_values["keys"]):
self.assertEquals(d.get(k), expected_values[d.account_head][i])
self.assertEquals(si.total_taxes_and_charges, 234.44)
self.assertEquals(si.base_grand_total, 859.44)
self.assertEquals(si.grand_total, 859.44)
def create_sales_invoice(**args):
si = frappe.new_doc("Sales Invoice")

View File

@@ -11,8 +11,7 @@ from erpnext.accounts.utils import validate_expense_against_budget
class StockAccountInvalidTransaction(frappe.ValidationError): pass
def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True,
update_outstanding='Yes'):
def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True, update_outstanding='Yes'):
if gl_map:
if not cancel:
gl_map = process_gl_map(gl_map, merge_entries)
@@ -51,7 +50,7 @@ def merge_similar_entries(gl_map):
merged_gl_map.append(entry)
# filter zero debit and credit entries
merged_gl_map = filter(lambda x: flt(x.debit)!=0 or flt(x.credit)!=0, merged_gl_map)
merged_gl_map = filter(lambda x: flt(x.debit, 9)!=0 or flt(x.credit, 9)!=0, merged_gl_map)
return merged_gl_map
def check_if_in_list(gle, gl_map):

View File

@@ -202,7 +202,7 @@ erpnext.AccountsChart = Class.extend({
title:__('New Account'),
fields: [
{fieldtype:'Data', fieldname:'account_name', label:__('New Account Name'), reqd:true,
description: __("Name of new Account. Note: Please don't create accounts for Customers and Suppliers, they are created automatically from the Customer and Supplier master")},
description: __("Name of new Account. Note: Please don't create accounts for Customers and Suppliers")},
{fieldtype:'Check', fieldname:'is_group', label:__('Is Group'),
description: __('Further accounts can be made under Groups, but entries can be made against non-Groups')},
{fieldtype:'Select', fieldname:'account_type', label:__('Account Type'),

View File

@@ -10,26 +10,24 @@ from frappe.utils import flt
def execute(filters=None):
if not filters: filters = {}
validate_filters(filters)
columns = get_columns(filters)
entries = get_entries(filters)
invoice_posting_date_map = get_invoice_posting_date_map(filters)
against_date = ""
outstanding_amount = 0.0
data = []
for d in entries:
if d.against_voucher:
against_date = d.against_voucher and invoice_posting_date_map[d.against_voucher] or ""
against_date = invoice_posting_date_map.get(d.reference_name) or ""
if d.reference_type=="Purchase Invoice":
payment_amount = flt(d.debit) or -1 * flt(d.credit)
else:
against_date = d.against_invoice and invoice_posting_date_map[d.against_invoice] or ""
payment_amount = flt(d.credit) or -1 * flt(d.debit)
row = [d.name, d.party_type, d.party, d.posting_date, d.against_voucher or d.against_invoice,
row = [d.name, d.party_type, d.party, d.posting_date, d.reference_name,
against_date, d.debit, d.credit, d.cheque_no, d.cheque_date, d.remark]
if d.against_voucher or d.against_invoice:
if d.reference_name:
row += get_ageing_data(30, 60, 90, d.posting_date, against_date, payment_amount)
else:
row += ["", "", "", "", ""]
@@ -37,7 +35,7 @@ def execute(filters=None):
data.append(row)
return columns, data
def validate_filters(filters):
if (filters.get("payment_type") == "Incoming" and filters.get("party_type") == "Supplier") or \
(filters.get("payment_type") == "Outgoing" and filters.get("party_type") == "Customer"):
@@ -45,9 +43,9 @@ def validate_filters(filters):
.format(filters.payment_type, filters.party_type))
def get_columns(filters):
return [_("Journal Entry") + ":Link/Journal Entry:140",
_("Party Type") + ":Link/DocType:100", _("Party") + ":Dynamic Link/Party Type:140",
_("Posting Date") + ":Date:100",
return [_("Journal Entry") + ":Link/Journal Entry:140",
_("Party Type") + "::100", _("Party") + ":Dynamic Link/Party Type:140",
_("Posting Date") + ":Date:100",
_("Against Invoice") + (":Link/Purchase Invoice:130" if filters.get("payment_type") == "Outgoing" else ":Link/Sales Invoice:130"),
_("Against Invoice Posting Date") + ":Date:130", _("Debit") + ":Currency:120", _("Credit") + ":Currency:120",
_("Reference No") + "::100", _("Reference Date") + ":Date:100", _("Remarks") + "::150", _("Age") +":Int:40",
@@ -62,7 +60,7 @@ def get_conditions(filters):
filters["party_type"] = "Supplier"
else:
filters["party_type"] = "Customer"
if filters.get("party_type"):
conditions.append("jvd.party_type=%(party_type)s")
@@ -82,7 +80,7 @@ def get_conditions(filters):
def get_entries(filters):
conditions = get_conditions(filters)
entries = frappe.db.sql("""select jv.name, jvd.party_type, jvd.party, jv.posting_date,
jvd.against_voucher, jvd.against_invoice, jvd.debit, jvd.credit,
jvd.reference_type, jvd.reference_name, jvd.debit, jvd.credit,
jv.cheque_no, jv.cheque_date, jv.remark
from `tabJournal Entry Account` jvd, `tabJournal Entry` jv
where jvd.parent = jv.name and jv.docstatus=1 %s order by jv.name DESC""" %

View File

@@ -100,14 +100,15 @@ def get_balance_on(account=None, date=None, party_type=None, party=None):
if party_type and party:
cond.append("""gle.party_type = "%s" and gle.party = "%s" """ %
(party_type.replace('"', '\\"'), party.replace('"', '\\"')))
if account or (party_type and party):
bal = frappe.db.sql("""
SELECT sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))
FROM `tabGL Entry` gle
WHERE %s""" % " and ".join(cond))[0][0]
bal = frappe.db.sql("""
SELECT sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))
FROM `tabGL Entry` gle
WHERE %s""" % " and ".join(cond))[0][0]
# if bal is None, return 0
return flt(bal)
# if bal is None, return 0
return flt(bal)
@frappe.whitelist()
def add_ac(args=None):
@@ -142,13 +143,6 @@ def reconcile_against_document(args):
for d in args:
check_if_jv_modified(d)
validate_allocated_amount(d)
against_fld = {
'Journal Entry' : 'against_jv',
'Sales Invoice' : 'against_invoice',
'Purchase Invoice' : 'against_voucher'
}
d['against_fld'] = against_fld[d['against_voucher_type']]
# cancel JV
jv_obj = frappe.get_doc('Journal Entry', d['voucher_no'])
@@ -173,8 +167,7 @@ def check_if_jv_modified(args):
select t2.{dr_or_cr} from `tabJournal Entry` t1, `tabJournal Entry Account` t2
where t1.name = t2.parent and t2.account = %(account)s
and t2.party_type = %(party_type)s and t2.party = %(party)s
and ifnull(t2.against_voucher, '')=''
and ifnull(t2.against_invoice, '')='' and ifnull(t2.against_jv, '')=''
and ifnull(t2.reference_type, '') in ("", "Sales Order", "Purchase Order")
and t1.name = %(voucher_no)s and t2.name = %(voucher_detail_no)s
and t1.docstatus=1 """.format(dr_or_cr = args.get("dr_or_cr")), args)
@@ -193,7 +186,12 @@ def update_against_doc(d, jv_obj):
"""
jv_detail = jv_obj.get("accounts", {"name": d["voucher_detail_no"]})[0]
jv_detail.set(d["dr_or_cr"], d["allocated_amt"])
jv_detail.set(d["against_fld"], d["against_voucher"])
original_reference_type = jv_detail.reference_type
original_reference_name = jv_detail.reference_name
jv_detail.set("reference_type", d["against_voucher_type"])
jv_detail.set("reference_name", d["against_voucher"])
if d['allocated_amt'] < d['unadjusted_amt']:
jvd = frappe.db.sql("""select cost_center, balance, against_account, is_advance
@@ -208,6 +206,8 @@ def update_against_doc(d, jv_obj):
ch.set(d['dr_or_cr'], flt(d['unadjusted_amt']) - flt(d['allocated_amt']))
ch.set(d['dr_or_cr']== 'debit' and 'credit' or 'debit', 0)
ch.against_account = cstr(jvd[0][2])
ch.reference_type = original_reference_type
ch.reference_name = original_reference_name
ch.is_advance = cstr(jvd[0][3])
ch.docstatus = 1
@@ -215,15 +215,16 @@ def update_against_doc(d, jv_obj):
jv_obj.flags.ignore_validate_update_after_submit = True
jv_obj.save()
def remove_against_link_from_jv(ref_type, ref_no, against_field):
def remove_against_link_from_jv(ref_type, ref_no):
linked_jv = frappe.db.sql_list("""select parent from `tabJournal Entry Account`
where `%s`=%s and docstatus < 2""" % (against_field, "%s"), (ref_no))
where reference_type=%s and reference_name=%s and docstatus < 2""", (ref_type, ref_no))
if linked_jv:
frappe.db.sql("""update `tabJournal Entry Account` set `%s`=null,
frappe.db.sql("""update `tabJournal Entry Account`
set reference_type=null, reference_name = null,
modified=%s, modified_by=%s
where `%s`=%s and docstatus < 2""" % (against_field, "%s", "%s", against_field, "%s"),
(now(), frappe.session.user, ref_no))
where reference_type=%s and reference_name=%s
and docstatus < 2""", (now(), frappe.session.user, ref_type, ref_no))
frappe.db.sql("""update `tabGL Entry`
set against_voucher_type=null, against_voucher=null,

View File

@@ -5,6 +5,14 @@ frappe.provide("erpnext.buying");
{% include 'buying/doctype/purchase_common/purchase_common.js' %};
frappe.ui.form.on("Purchase Order", {
onload: function(frm) {
erpnext.queries.setup_queries(frm, "Warehouse", function() {
return erpnext.queries.warehouse(frm.doc);
});
}
});
erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend({
refresh: function(doc, cdt, cdn) {
var me = this;
@@ -12,31 +20,38 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
// this.frm.dashboard.reset();
if(doc.docstatus == 1 && doc.status != 'Stopped') {
if(flt(doc.per_billed, 2) < 100 || doc.per_received < 100)
cur_frm.add_custom_button(__('Stop'), cur_frm.cscript['Stop Purchase Order']);
if(flt(doc.per_billed)==0) {
cur_frm.add_custom_button(__('Payment'), cur_frm.cscript.make_bank_entry);
}
if(flt(doc.per_received, 2) < 100) {
cur_frm.add_custom_button(__('Make Purchase Receipt'), this.make_purchase_receipt);
cur_frm.add_custom_button(__('Receive'), this.make_purchase_receipt).addClass("btn-primary");
if(doc.is_subcontracted==="Yes") {
cur_frm.add_custom_button(__('Transfer Material to Supplier'), this.make_stock_entry);
}
}
if(flt(doc.per_billed, 2) < 100)
cur_frm.add_custom_button(__('Make Invoice'), this.make_purchase_invoice);
if(flt(doc.per_billed, 2) < 100 || doc.per_received < 100)
cur_frm.add_custom_button(__('Stop'), cur_frm.cscript['Stop Purchase Order']);
cur_frm.add_custom_button(__('Invoice'), this.make_purchase_invoice);
} else if(doc.docstatus===0) {
cur_frm.cscript.add_from_mappers();
}
if(doc.docstatus == 1 && doc.status == 'Stopped')
cur_frm.add_custom_button(__('Unstop Purchase Order'), cur_frm.cscript['Unstop Purchase Order']);
cur_frm.add_custom_button(__('Unstop'), cur_frm.cscript['Unstop Purchase Order']);
},
make_stock_entry: function() {
var items = $.map(cur_frm.doc.items, function(d) { return d.bom ? d.item_code : false; });
var me = this;
if(items.length===1) {
me._make_stock_entry(items[0]);
return;
@@ -126,7 +141,21 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
items_add: function(doc, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn);
this.frm.script_manager.copy_from_first_row("items", row, ["schedule_date"]);
},
make_bank_entry: function() {
return frappe.call({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_payment_entry_from_purchase_order",
args: {
"purchase_order": cur_frm.doc.name
},
callback: function(r) {
var doclist = frappe.model.sync(r.message);
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
}
});
}
});
// for backward compatibility: combine new and previous states

View File

@@ -248,6 +248,8 @@ def stop_or_unstop_purchase_orders(names, status):
if po.status == "Stopped":
po.update_status("Submitted")
po.notify_modified()
frappe.local.message_log = []

View File

@@ -46,6 +46,8 @@ cur_frm.cscript.make_dashboard = function(doc) {
+ '</b> / <span class="text-muted">' + __("Total Unpaid") + ": <b>"
+ format_currency(r.message.total_unpaid, r.message.company_currency[0])
+ '</b></span>');
} else {
cur_frm.dashboard.set_headline("");
}
}
cur_frm.dashboard.set_badge_count(r.message);

View File

@@ -1,4 +1,3 @@
- Item variants is now manageable via dedicated tool **Manage Variants**. To learn about it, check [Manual Page for Item variants](https://manual.erpnext.com/contents/stock/item/item-variants)
- Against account in General Ledger will show Party instead of Account (which is not useful)
- Print format for recurring documents can be set by the users
- Recurring documents won't be created for Stopped Sales / Purchase Orders.

View File

@@ -1,3 +1,2 @@
- Hide zero balance rows in batch-wise balance history report
- Autocomplete issue fixed in Manage Variants
- Remove user permission (Employee role) if user id is unset from Employee record

View File

@@ -0,0 +1,2 @@
- Automatically insert Price List Rate in Price List if added in transaction if permission exists and allowed from Stock Settings
- Product Bundle now allowed for all Items (stock or non-stock)

View File

@@ -0,0 +1,6 @@
- For referencing a line in **Journal Entry**, now you can reference by the **Reference Type** and **Reference Name** columns, instead of "Against Sales Invoice", "Against Purchase Invoice", etc.
- Additional Costs in Stock Entry **[Sponsored by PT. Ridho Sribumi Sejahtera]**
Now additional costs like shipping charges, operating costs etc can be added in Stock Entry in item valuation
- **Update Finished Goods** in Production Order can now use the items from **Transfer Materials for Manufacture** step instead of items from the Bill of Materials. This can be configured in Manufacturing Settings
- Added field **Tax ID** in Customer
- Bug fixes in Item, Time Log Batch, Pricing Rule, Salary Slip, Address and Stock Entry

View File

@@ -0,0 +1,7 @@
- **Item Variants**
- Removed **Manage Variants** tool
- Use **Make Variant** button in the Item form to create new variants based on a template Item
- Added ability to specify Range of Numeric Values in Item Attribute
- Set default Print Format for Point-of-Sale (POS) via **POS Profile**
- Option to automatically print after submitting POS **Sales Invoice**
- **Communication** added to CRM module

View File

@@ -31,6 +31,11 @@ def get_data():
"name": "Newsletter",
"description": _("Newsletters to contacts, leads."),
},
{
"type": "doctype",
"name": "Communication",
"description": _("Record of all communications of type email, phone, chat, visit, etc."),
},
]
},
{

View File

@@ -87,6 +87,11 @@ def get_data():
"label": _("Lead to Quotation"),
"youtube_id": "TxYX4r4JAKA"
},
{
"type": "help",
"label": _("Newsletters"),
"youtube_id": "muLKsCrrDRo"
},
]
},
{
@@ -122,6 +127,26 @@ def get_data():
"label": _("Opening Stock Balance"),
"youtube_id": "0yPgrtfeCTs"
},
{
"type": "help",
"label": _("Making Stock Entries"),
"youtube_id": "Njt107hlY3I"
},
{
"type": "help",
"label": _("Serialized Inventory"),
"youtube_id": "gvOVlEwFDAk"
},
{
"type": "help",
"label": _("Batch Inventory"),
"youtube_id": "J0QKl7ABPKM"
},
{
"type": "help",
"label": _("Managing Subcontracting"),
"youtube_id": "ThiMCC2DtKo"
},
]
},
{
@@ -137,7 +162,16 @@ def get_data():
"label": _("Material Request to Purchase Order"),
"youtube_id": "4TN9kPyfIqM"
},
{
"type": "help",
"label": _("Purchase Order to Payment"),
"youtube_id": "EK65tLdVUDk"
},
{
"type": "help",
"label": _("Managing Subcontracting"),
"youtube_id": "ThiMCC2DtKo"
},
]
},
{
@@ -179,6 +213,11 @@ def get_data():
"label": _("Expense Claims"),
"youtube_id": "5SZHJF--ZFY"
},
{
"type": "help",
"label": _("Processing Payroll"),
"youtube_id": "apgE-f25Rm0"
},
]
},
{

View File

@@ -82,12 +82,7 @@ def get_data():
"type": "doctype",
"name": "Stock UOM Replace Utility",
"description": _("Change UOM for an Item."),
},
{
"type": "doctype",
"name": "Manage Variants",
"description": _("Manage Item Variants."),
},
}
]
},
{

View File

@@ -11,6 +11,8 @@ from erpnext.utilities.transaction_base import TransactionBase
from erpnext.controllers.recurring_document import convert_to_recurring, validate_recurring_document
from erpnext.controllers.sales_and_purchase_return import validate_return
force_item_fields = ("item_group", "barcode", "brand", "stock_uom")
class CustomerFrozen(frappe.ValidationError): pass
class AccountsController(TransactionBase):
@@ -18,12 +20,12 @@ class AccountsController(TransactionBase):
if self.get("_action") and self._action != "update_after_submit":
self.set_missing_values(for_validate=True)
self.validate_date_with_fiscal_year()
if self.meta.get_field("currency"):
self.calculate_taxes_and_totals()
if not self.meta.get_field("is_return") or not self.is_return:
self.validate_value("base_grand_total", ">=", 0)
validate_return(self)
self.set_total_in_words()
@@ -35,7 +37,7 @@ class AccountsController(TransactionBase):
if self.meta.get_field("taxes_and_charges"):
self.validate_enabled_taxes_and_charges()
self.validate_party()
def on_submit(self):
@@ -86,7 +88,7 @@ class AccountsController(TransactionBase):
if self.doctype == "Sales Invoice":
if not self.due_date:
frappe.throw(_("Due Date is mandatory"))
validate_due_date(self.posting_date, self.due_date, "Customer", self.customer, self.company)
elif self.doctype == "Purchase Invoice":
validate_due_date(self.posting_date, self.due_date, "Supplier", self.supplier, self.company)
@@ -142,7 +144,8 @@ class AccountsController(TransactionBase):
for fieldname, value in ret.items():
if item.meta.get_field(fieldname) and \
item.get(fieldname) is None and value is not None:
(item.get(fieldname) is None or fieldname in force_item_fields) \
and value is not None:
item.set(fieldname, value)
if fieldname == "cost_center" and item.meta.get_field("cost_center") \
@@ -150,9 +153,10 @@ class AccountsController(TransactionBase):
item.set(fieldname, value)
if ret.get("pricing_rule"):
for field in ["base_price_list_rate", "price_list_rate",
"discount_percentage", "base_rate", "rate"]:
item.set(field, ret.get(field))
item.set("discount_percentage", ret.get("discount_percentage"))
if ret.get("pricing_rule_for") == "Price":
item.set("pricing_list_rate", ret.get("pricing_list_rate"))
def set_taxes(self):
if not self.meta.get_field("taxes"):
@@ -208,29 +212,32 @@ class AccountsController(TransactionBase):
and ifnull(allocated_amount, 0) = 0""" % (childtype, '%s', '%s'), (parentfield, self.name))
def get_advances(self, account_head, party_type, party, child_doctype, parentfield, dr_or_cr, against_order_field):
so_list = list(set([d.get(against_order_field) for d in self.get("items") if d.get(against_order_field)]))
cond = ""
if so_list:
cond = "or (ifnull(t2.%s, '') in (%s))" % ("against_" + against_order_field, ', '.join(['%s']*len(so_list)))
"""Returns list of advances against Account, Party, Reference"""
order_list = list(set([d.get(against_order_field) for d in self.get("items") if d.get(against_order_field)]))
if not order_list:
return
in_placeholder = ', '.join(['%s'] * len(order_list))
# conver sales_order to "Sales Order"
reference_type = against_order_field.replace("_", " ").title()
res = frappe.db.sql("""
select
t1.name as jv_no, t1.remark, t2.{0} as amount, t2.name as jv_detail_no, `against_{1}` as against_order
t1.name as jv_no, t1.remark, t2.{0} as amount, t2.name as jv_detail_no,
reference_name as against_order
from
`tabJournal Entry` t1, `tabJournal Entry Account` t2
where
t1.name = t2.parent and t2.account = %s
and t2.party_type=%s and t2.party=%s
and t2.party_type = %s and t2.party = %s
and t2.is_advance = 'Yes' and t1.docstatus = 1
and ((
ifnull(t2.against_voucher, '') = ''
and ifnull(t2.against_invoice, '') = ''
and ifnull(t2.against_jv, '') = ''
and ifnull(t2.against_sales_order, '') = ''
and ifnull(t2.against_purchase_order, '') = ''
) {2})
order by t1.posting_date""".format(dr_or_cr, against_order_field, cond),
[account_head, party_type, party] + so_list, as_dict=1)
and (
ifnull(t2.reference_type, '')=''
or (t2.reference_type = %s and ifnull(t2.reference_name, '') in ({1})))
order by t1.posting_date""".format(dr_or_cr, in_placeholder),
[account_head, party_type, party, reference_type] + order_list, as_dict=1)
self.set(parentfield, [])
for d in res:
@@ -243,25 +250,26 @@ class AccountsController(TransactionBase):
"allocated_amount": flt(d.amount) if d.against_order else 0
})
def validate_advance_jv(self, advance_table_fieldname, against_order_field):
def validate_advance_jv(self, reference_type):
against_order_field = frappe.scrub(reference_type)
order_list = list(set([d.get(against_order_field) for d in self.get("items") if d.get(against_order_field)]))
if order_list:
account = self.get("debit_to" if self.doctype=="Sales Invoice" else "credit_to")
jv_against_order = frappe.db.sql("""select parent, %s as against_order
jv_against_order = frappe.db.sql("""select parent, reference_name as against_order
from `tabJournal Entry Account`
where docstatus=1 and account=%s and ifnull(is_advance, 'No') = 'Yes'
and ifnull(against_sales_order, '') in (%s)
group by parent, against_sales_order""" %
("against_" + against_order_field, '%s', ', '.join(['%s']*len(order_list))),
tuple([account] + order_list), as_dict=1)
and reference_type=%s
and ifnull(reference_name, '') in ({0})
group by parent, reference_name""".format(', '.join(['%s']*len(order_list))),
tuple([account, reference_type] + order_list), as_dict=1)
if jv_against_order:
order_jv_map = {}
for d in jv_against_order:
order_jv_map.setdefault(d.against_order, []).append(d.parent)
advance_jv_against_si = [d.journal_entry for d in self.get(advance_table_fieldname)]
advance_jv_against_si = [d.journal_entry for d in self.get("advances")]
for order, jv_list in order_jv_map.items():
for jv in jv_list:
@@ -315,10 +323,8 @@ class AccountsController(TransactionBase):
def set_total_advance_paid(self):
if self.doctype == "Sales Order":
dr_or_cr = "credit"
against_field = "against_sales_order"
else:
dr_or_cr = "debit"
against_field = "against_purchase_order"
advance_paid = frappe.db.sql("""
select
@@ -326,8 +332,10 @@ class AccountsController(TransactionBase):
from
`tabJournal Entry Account`
where
{against_field} = %s and docstatus = 1 and is_advance = "Yes" """.format(dr_or_cr=dr_or_cr, \
against_field=against_field), self.name)
reference_type = %s and
reference_name = %s and
docstatus = 1 and is_advance = "Yes" """.format(dr_or_cr=dr_or_cr),
(self.doctype, self.name))
if advance_paid:
advance_paid = flt(advance_paid[0][0], self.precision("advance_paid"))
@@ -349,14 +357,14 @@ class AccountsController(TransactionBase):
frozen_accounts_modifier = frappe.db.get_value( 'Accounts Settings', None,'frozen_accounts_modifier')
if frozen_accounts_modifier in frappe.get_roles():
return
party_type = None
if self.meta.get_field("customer"):
party_type = 'Customer'
elif self.meta.get_field("supplier"):
party_type = 'Supplier'
if party_type:
party = self.get(party_type.lower())
if frappe.db.get_value(party_type, party, "is_frozen"):

View File

@@ -112,8 +112,8 @@ class BuyingController(StockController):
valuation_amount_adjustment -= item.item_tax_amount
self.round_floats_in(item)
item.conversion_factor = get_conversion_factor(item.item_code, item.uom).get("conversion_factor") or 1.0
if flt(item.conversion_factor)==0:
item.conversion_factor = get_conversion_factor(item.item_code, item.uom).get("conversion_factor") or 1.0
qty_in_stock_uom = flt(item.qty * item.conversion_factor)
rm_supp_cost = flt(item.rm_supp_cost) if self.doctype=="Purchase Receipt" else 0.0

View File

@@ -8,7 +8,6 @@ from frappe.utils import flt, get_datetime, format_datetime
class StockOverReturnError(frappe.ValidationError): pass
def validate_return(doc):
if not doc.meta.get_field("is_return") or not doc.is_return:
return
@@ -50,13 +49,19 @@ def validate_return_against(doc):
.format(doc.return_against))
def validate_returned_items(doc):
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
valid_items = frappe._dict()
for d in frappe.db.sql("""select item_code, sum(qty) as qty, rate from `tab{0} Item`
where parent = %s group by item_code""".format(doc.doctype), doc.return_against, as_dict=1):
valid_items.setdefault(d.item_code, d)
select_fields = "item_code, sum(qty) as qty, rate" if doc.doctype=="Purchase Invoice" \
else "item_code, sum(qty) as qty, rate, serial_no, batch_no"
for d in frappe.db.sql("""select {0} from `tab{1} Item` where parent = %s
group by item_code""".format(select_fields, doc.doctype), doc.return_against, as_dict=1):
valid_items.setdefault(d.item_code, d)
if doc.doctype in ("Delivery Note", "Sales Invoice"):
for d in frappe.db.sql("""select item_code, sum(qty) as qty from `tabPacked Item`
for d in frappe.db.sql("""select item_code, sum(qty) as qty, serial_no, batch_no from `tabPacked Item`
where parent = %s group by item_code""".format(doc.doctype), doc.return_against, as_dict=1):
valid_items.setdefault(d.item_code, d)
@@ -81,8 +86,20 @@ def validate_returned_items(doc):
elif ref.rate and flt(d.rate) != ref.rate:
frappe.throw(_("Row # {0}: Rate must be same as {1} {2}")
.format(d.idx, doc.doctype, doc.return_against))
elif ref.batch_no and d.batch_no != ref.batch_no:
frappe.throw(_("Row # {0}: Batch No must be same as {1} {2}")
.format(d.idx, doc.doctype, doc.return_against))
elif ref.serial_no:
if not d.serial_no:
frappe.throw(_("Row # {0}: Serial No is mandatory").format(d.idx))
else:
serial_nos = get_serial_nos(d.serial_no)
ref_serial_nos = get_serial_nos(ref.serial_no)
for s in serial_nos:
if s not in ref_serial_nos:
frappe.throw(_("Row # {0}: Serial No {1} does not match with {2} {3}")
.format(d.idx, s, doc.doctype, doc.return_against))
items_returned = True
if not items_returned:
@@ -134,9 +151,11 @@ def make_return_doc(doctype, source_name, target_doc=None):
},
doctype +" Item": {
"doctype": doctype + " Item",
"fields": {
"field_map": {
"purchase_order": "purchase_order",
"purchase_receipt": "purchase_receipt"
"purchase_receipt": "purchase_receipt",
"serial_no": "serial_no",
"batch_no": "batch_no"
},
"postprocess": update_item
},

View File

@@ -188,7 +188,7 @@ class SellingController(StockController):
reserved_qty_for_main_item = -(so_qty - already_delivered_qty)
else:
reserved_qty_for_main_item = -flt(d.qty)
if self.has_product_bundle(d.item_code):
for p in self.get("packed_items"):
if p.parent_detail_docname == d.name and p.parent_item == d.item_code:
@@ -229,10 +229,12 @@ class SellingController(StockController):
and against_sales_order = %s
and parent != %s""", (so_detail, so, current_docname))
delivered_via_si = frappe.db.sql("""select sum(qty) from `tabSales Invoice Item`
where so_detail = %s and docstatus = 1
and sales_order = %s
and parent != %s""", (so_detail, so, current_docname))
delivered_via_si = frappe.db.sql("""select sum(si_item.qty)
from `tabSales Invoice Item` si_item, `tabSales Invoice` si
where si_item.parent = si.name and ifnull(si.update_stock, 0) = 1
and si_item.so_detail = %s and si.docstatus = 1
and si_item.sales_order = %s
and si.name != %s""", (so_detail, so, current_docname))
total_delivered_qty = (flt(delivered_via_dn[0][0]) if delivered_via_dn else 0) \
+ (flt(delivered_via_si[0][0]) if delivered_via_si else 0)

View File

@@ -218,7 +218,7 @@ class StockController(AccountsController):
tuple(item_codes))
return serialized_items
def get_incoming_rate_for_sales_return(self, item_code, against_document):
incoming_rate = 0.0
if against_document and item_code:
@@ -229,12 +229,12 @@ class StockController(AccountsController):
incoming_rate = incoming_rate[0][0] if incoming_rate else 0.0
return incoming_rate
def update_reserved_qty(self, d):
if d['reserved_qty'] < 0 :
# Reduce reserved qty from reserved warehouse mentioned in so
if not d["reserved_warehouse"]:
frappe.throw(_("Reserved Warehouse is missing in Sales Order"))
frappe.throw(_("Delivery Warehouse is missing in Sales Order"))
args = {
"item_code": d['item_code'],

View File

@@ -219,7 +219,7 @@ class calculate_taxes_and_totals(object):
# adjust Discount Amount loss in last tax iteration
if i == (len(self.doc.get("taxes")) - 1) and self.discount_amount_applied \
and self.doc.discount_amount:
and self.doc.discount_amount and self.doc.apply_discount_on == "Grand Total":
self.adjust_discount_amount_loss(tax)
@@ -303,9 +303,9 @@ class calculate_taxes_and_totals(object):
for tax in self.doc.get("taxes"):
if tax.category in ["Valuation and Total", "Total"]:
if tax.add_deduct_tax == "Add":
self.doc.taxes_and_charges_added += flt(tax.tax_amount)
self.doc.taxes_and_charges_added += flt(tax.tax_amount_after_discount_amount)
else:
self.doc.taxes_and_charges_deducted += flt(tax.tax_amount)
self.doc.taxes_and_charges_deducted += flt(tax.tax_amount_after_discount_amount)
self.doc.round_floats_in(self.doc, ["taxes_and_charges_added", "taxes_and_charges_deducted"])

View File

@@ -138,8 +138,6 @@ def subscribe(email):
_("Click here to verify")
)
print url
content = """
<p>{0}. {1}.</p>
<p><a href="{2}">{3}</a></p>

View File

@@ -34,10 +34,8 @@ class NewsletterList(Document):
}).insert(ignore_permissions=True)
added += 1
except Exception, e:
# already added, ignore
if e.args[0]!=1062:
raise
except frappe.UniqueValidationError:
pass
frappe.msgprint(_("{0} subscribers added").format(added))

View File

@@ -80,9 +80,23 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) {
if(doc.status!=="Quotation")
cur_frm.add_custom_button(__('Opportunity Lost'),
cur_frm.cscript['Declare Opportunity Lost'], "icon-remove", "btn-default");
}
var frm = cur_frm;
if(frm.perm[0].write && doc.docstatus==0) {
if(frm.doc.status==="Open") {
frm.add_custom_button("Close", function() {
frm.set_value("status", "Closed");
frm.save();
});
} else {
frm.add_custom_button("Reopen", function() {
frm.set_value("status", "Open");
frm.save();
});
}
}
}
cur_frm.cscript.onload_post_render = function(doc, cdt, cdn) {

View File

@@ -1,36 +1,67 @@
{
"allow_copy": 0,
"allow_import": 1,
"allow_rename": 0,
"autoname": "naming_series:",
"creation": "2013-03-07 18:50:30",
"custom": 0,
"description": "Potential Sales Deal",
"docstatus": 0,
"doctype": "DocType",
"document_type": "Transaction",
"document_type": "Document",
"fields": [
{
"allow_on_submit": 0,
"fieldname": "from_section",
"fieldtype": "Section Break",
"label": "From",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "",
"no_copy": 0,
"options": "icon-user",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "naming_series",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Series",
"no_copy": 1,
"oldfieldname": "naming_series",
"oldfieldtype": "Select",
"options": "OPTY-",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"reqd": 1
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "enquiry_from",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Opportunity From",
"no_copy": 0,
"oldfieldname": "enquiry_from",
"oldfieldtype": "Select",
"options": "\nLead\nCustomer",
@@ -38,13 +69,18 @@
"print_hide": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 1
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "eval:doc.enquiry_from===\"Customer\"",
"fieldname": "customer",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "Customer",
@@ -55,65 +91,126 @@
"permlevel": 0,
"print_hide": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "eval:doc.enquiry_from===\"Lead\"",
"fieldname": "lead",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "Lead",
"no_copy": 0,
"oldfieldname": "lead",
"oldfieldtype": "Link",
"options": "Lead",
"permlevel": 0,
"print_hide": 1,
"read_only": 0
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "",
"fieldname": "customer_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Customer / Lead Name",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 1
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break0",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"oldfieldtype": "Column Break",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0,
"width": "50%"
},
{
"allow_on_submit": 0,
"fieldname": "title",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Title",
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"default": "Sales",
"fieldname": "enquiry_type",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Opportunity Type",
"no_copy": 0,
"oldfieldname": "enquiry_type",
"oldfieldtype": "Select",
"options": "Sales\nMaintenance",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"reqd": 1
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"default": "Open",
"fieldname": "status",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Status",
"no_copy": 1,
@@ -123,276 +220,571 @@
"permlevel": 0,
"print_hide": 1,
"read_only": 0,
"reqd": 1
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "with_items",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "With Items",
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "with_items",
"fieldname": "items_section",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "",
"no_copy": 0,
"oldfieldtype": "Section Break",
"options": "icon-shopping-cart",
"permlevel": 0,
"read_only": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"description": "",
"fieldname": "items",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Items",
"no_copy": 0,
"oldfieldname": "enquiry_details",
"oldfieldtype": "Table",
"options": "Opportunity Item",
"permlevel": 0,
"read_only": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "fold",
"fieldtype": "Fold",
"permlevel": 0
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "eval:doc.lead || doc.customer",
"fieldname": "contact_info",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Contact Info",
"no_copy": 0,
"options": "icon-bullhorn",
"permlevel": 0,
"read_only": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "eval:doc.customer || doc.lead",
"fieldname": "customer_address",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "Customer / Lead Address",
"no_copy": 0,
"options": "Address",
"permlevel": 0,
"print_hide": 1,
"read_only": 0
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "address_display",
"fieldtype": "Small Text",
"hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Address",
"no_copy": 0,
"oldfieldname": "address",
"oldfieldtype": "Small Text",
"permlevel": 0,
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "customer",
"description": "",
"fieldname": "territory",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 1,
"label": "Territory",
"no_copy": 0,
"options": "Territory",
"permlevel": 0,
"print_hide": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 1
"search_index": 1,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "customer",
"description": "",
"fieldname": "customer_group",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "Customer Group",
"no_copy": 0,
"oldfieldname": "customer_group",
"oldfieldtype": "Link",
"options": "Customer Group",
"permlevel": 0,
"print_hide": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 1
"search_index": 1,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break3",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"read_only": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "eval:doc.lead || doc.customer",
"fieldname": "contact_person",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "Contact Person",
"no_copy": 0,
"options": "Contact",
"permlevel": 0,
"print_hide": 1,
"read_only": 0
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "customer",
"fieldname": "contact_display",
"fieldtype": "Small Text",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Contact",
"no_copy": 0,
"permlevel": 0,
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "eval:doc.lead || doc.customer",
"fieldname": "contact_email",
"fieldtype": "Small Text",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Contact Email",
"no_copy": 0,
"permlevel": 0,
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "eval:doc.lead || doc.customer",
"fieldname": "contact_mobile",
"fieldtype": "Small Text",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Contact Mobile No",
"no_copy": 0,
"permlevel": 0,
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "more_info",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "More Info",
"no_copy": 0,
"oldfieldtype": "Section Break",
"options": "icon-file-text",
"permlevel": 0,
"read_only": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break1",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"oldfieldtype": "Column Break",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0,
"width": "50%"
},
{
"allow_on_submit": 0,
"default": "Today",
"fieldname": "transaction_date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Opportunity Date",
"no_copy": 0,
"oldfieldname": "transaction_date",
"oldfieldtype": "Date",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0,
"width": "50px"
},
{
"allow_on_submit": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "Company",
"no_copy": 0,
"oldfieldname": "company",
"oldfieldtype": "Link",
"options": "Company",
"permlevel": 0,
"print_hide": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 1
"search_index": 1,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "source",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Source",
"no_copy": 0,
"oldfieldname": "source",
"oldfieldtype": "Select",
"options": "\nExisting Customer\nReference\nAdvertisement\nCold Calling\nExhibition\nSupplier Reference\nMass Mailing\nCustomer's Vendor\nCampaign\nWalk In",
"permlevel": 0,
"read_only": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"description": "Enter name of campaign if source of enquiry is campaign",
"fieldname": "campaign",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Campaign",
"no_copy": 0,
"oldfieldname": "campaign",
"oldfieldtype": "Link",
"options": "Campaign",
"permlevel": 0,
"read_only": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "fiscal_year",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "Fiscal Year",
"no_copy": 0,
"oldfieldname": "fiscal_year",
"oldfieldtype": "Select",
"options": "Fiscal Year",
"permlevel": 0,
"print_hide": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 1
"search_index": 1,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "eval:!doc.__islocal",
"fieldname": "order_lost_reason",
"fieldtype": "Text",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Lost Reason",
"no_copy": 1,
"permlevel": 0,
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break2",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"oldfieldtype": "Column Break",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0,
"width": "50%"
},
{
"allow_on_submit": 0,
"description": "Your sales person who will contact the customer in future",
"fieldname": "contact_by",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "Next Contact By",
"no_copy": 0,
"oldfieldname": "contact_by",
"oldfieldtype": "Link",
"options": "User",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0,
"width": "75px"
},
{
"allow_on_submit": 0,
"description": "Your sales person will get a reminder on this date to contact the customer",
"fieldname": "contact_date",
"fieldtype": "Datetime",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Next Contact Date",
"no_copy": 0,
"oldfieldname": "contact_date",
"oldfieldtype": "Date",
"permlevel": 0,
"read_only": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "to_discuss",
"fieldtype": "Small Text",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "To Discuss",
"no_copy": 1,
"oldfieldname": "to_discuss",
"oldfieldtype": "Small Text",
"permlevel": 0,
"read_only": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "amended_from",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 1,
"in_filter": 0,
"in_list_view": 0,
"label": "Amended From",
"no_copy": 1,
"oldfieldname": "amended_from",
@@ -401,13 +793,24 @@
"permlevel": 0,
"print_hide": 1,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0,
"width": "150px"
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "icon-info-sign",
"idx": 1,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"modified": "2015-04-13 12:53:43.490817",
"issingle": 0,
"istable": 0,
"modified": "2015-08-07 17:11:33.955441",
"modified_by": "Administrator",
"module": "CRM",
"name": "Opportunity",
@@ -420,31 +823,42 @@
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales User",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
}
],
"read_only": 0,
"read_only_onload": 0,
"search_fields": "status,transaction_date,customer,lead,enquiry_type,territory,company",
"sort_field": "modified",
"sort_order": "DESC",

View File

@@ -27,7 +27,7 @@ blogs.
"""
app_icon = "icon-th"
app_color = "#e74c3c"
app_version = "5.4.0"
app_version = "5.7.0"
github_link = "https://github.com/frappe/erpnext"
error_report_email = "support@erpnext.com"

View File

@@ -24,13 +24,15 @@ erpnext.hr.ExpenseClaimController = frappe.ui.form.Controller.extend({
var d1 = frappe.model.add_child(jv, 'Journal Entry Account', 'accounts');
d1.debit = expense[i].sanctioned_amount;
d1.account = expense[i].default_account;
d1.against_expense_claim = cur_frm.doc.name;
d1.reference_type = cur_frm.doc.doctype;
d1.reference_name = cur_frm.doc.name;
}
// credit to bank
var d1 = frappe.model.add_child(jv, 'Journal Entry Account', 'accounts');
d1.credit = cur_frm.doc.total_sanctioned_amount;
d1.against_expense_claim = cur_frm.doc.name;
d1.reference_type = cur_frm.doc.doctype;
d1.reference_name = cur_frm.doc.name;
if(r.message) {
d1.account = r.message.account;
d1.balance = r.message.balance;
@@ -179,5 +181,5 @@ cur_frm.fields_dict['task'].get_query = function(doc) {
filters:{
'project': doc.project
}
}
}
}
}

View File

@@ -239,14 +239,15 @@ def get_total_leave_days(leave_app):
if not leave_app.half_day:
tot_days = date_diff(leave_app.to_date, leave_app.from_date) + 1
if frappe.db.get_value("Leave Type", leave_app.leave_type, "include_holiday"):
ret = {
'total_leave_days' : flt(tot_days)
}
else:
holidays = leave_app.get_holidays()
ret = {
'total_leave_days' : flt(tot_days)-flt(holidays)
}
else:
ret = {
'total_leave_days' : flt(tot_days)
}
return ret
@frappe.whitelist()

View File

@@ -152,8 +152,8 @@ class SalarySlip(TransactionBase):
self.gross_pay = flt(self.arrear_amount) + flt(self.leave_encashment_amount)
for d in self.get("earnings"):
if cint(d.e_depends_on_lwp) == 1:
d.e_modified_amount = rounded(flt(d.e_amount) * flt(self.payment_days)
/ cint(self.total_days_in_month), 2)
d.e_modified_amount = rounded((flt(d.e_amount) * flt(self.payment_days)
/ cint(self.total_days_in_month)), self.precision("e_modified_amount", "earnings"))
elif not self.payment_days:
d.e_modified_amount = 0
elif not d.e_modified_amount:
@@ -164,8 +164,8 @@ class SalarySlip(TransactionBase):
self.total_deduction = 0
for d in self.get('deductions'):
if cint(d.d_depends_on_lwp) == 1:
d.d_modified_amount = rounded(flt(d.d_amount) * flt(self.payment_days)
/ cint(self.total_days_in_month), 2)
d.d_modified_amount = rounded((flt(d.d_amount) * flt(self.payment_days)
/ cint(self.total_days_in_month)), self.precision("d_modified_amount", "deductions"))
elif not self.payment_days:
d.d_modified_amount = 0
elif not d.d_modified_amount:
@@ -174,10 +174,13 @@ class SalarySlip(TransactionBase):
self.total_deduction += flt(d.d_modified_amount)
def calculate_net_pay(self):
disable_rounded_total = cint(frappe.db.get_value("Global Defaults", None, "disable_rounded_total"))
self.calculate_earning_total()
self.calculate_ded_total()
self.net_pay = flt(self.gross_pay) - flt(self.total_deduction)
self.rounded_total = rounded(self.net_pay)
self.rounded_total = rounded(self.net_pay,
self.precision("net_pay") if disable_rounded_total else 0)
def on_submit(self):
if(self.email_check == 1):

View File

@@ -3,50 +3,112 @@
"allow_import": 1,
"allow_rename": 0,
"creation": "2013-01-22 15:11:38",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Master",
"fields": [
{
"allow_on_submit": 0,
"description": "Item to be manufactured or repacked",
"fieldname": "item",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 1,
"label": "Item",
"no_copy": 0,
"oldfieldname": "item",
"oldfieldtype": "Link",
"options": "Item",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 1
"search_index": 1,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "item_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Item Name",
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "rm_cost_as_per",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Rate Of Materials Based On",
"no_copy": 0,
"options": "Valuation Rate\nLast Purchase Rate\nPrice List",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "eval:doc.rm_cost_as_per===\"Price List\"",
"fieldname": "buying_price_list",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Price List",
"no_copy": 0,
"options": "Price List",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "cb0",
"fieldtype": "Column Break",
"permlevel": 0
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 1,
@@ -54,213 +116,517 @@
"fieldname": "is_active",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Is Active",
"no_copy": 1,
"oldfieldname": "is_active",
"oldfieldtype": "Select",
"permlevel": 0,
"reqd": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 1,
"default": "1",
"fieldname": "is_default",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Is Default",
"no_copy": 1,
"oldfieldname": "is_default",
"oldfieldtype": "Check",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"description": "Manage cost of operations",
"fieldname": "with_operations",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "With Operations",
"permlevel": 0
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "",
"description": "Specify the operations, operating cost and give a unique Operation no to your operations.",
"fieldname": "operations_section",
"fieldtype": "Section Break",
"label": "Operations",
"oldfieldtype": "Section Break",
"permlevel": 0
},
{
"fieldname": "operations",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Operations",
"no_copy": 0,
"oldfieldtype": "Section Break",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "operations",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Operations",
"no_copy": 0,
"oldfieldname": "bom_operations",
"oldfieldtype": "Table",
"options": "BOM Operation",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "materials_section",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Materials",
"no_copy": 0,
"oldfieldtype": "Section Break",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "items",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Items",
"no_copy": 0,
"oldfieldname": "bom_materials",
"oldfieldtype": "Table",
"options": "BOM Item",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"default": "1",
"description": "Quantity of item obtained after manufacturing / repacking from given quantities of raw materials",
"fieldname": "quantity",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Quantity",
"no_copy": 0,
"oldfieldname": "quantity",
"oldfieldtype": "Currency",
"permlevel": 0,
"reqd": 1
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "costing",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Costing",
"no_copy": 0,
"oldfieldtype": "Section Break",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "operating_cost",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Operating Cost",
"no_copy": 0,
"options": "Company:company:default_currency",
"permlevel": 0,
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "raw_material_cost",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Raw Material Cost",
"no_copy": 0,
"options": "Company:company:default_currency",
"permlevel": 0,
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "cb1",
"fieldtype": "Column Break",
"permlevel": 0
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "total_cost",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Total Cost",
"no_copy": 0,
"options": "Company:company:default_currency",
"permlevel": 0,
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "more_info_section",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "",
"permlevel": 0
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "project_name",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "Project Name",
"no_copy": 0,
"oldfieldname": "project_name",
"oldfieldtype": "Link",
"options": "Project",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Company",
"no_copy": 0,
"options": "Company",
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "amended_from",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 1,
"in_filter": 0,
"in_list_view": 0,
"label": "Amended From",
"no_copy": 1,
"options": "BOM",
"permlevel": 0,
"print_hide": 1,
"read_only": 1
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "col_break23",
"fieldtype": "Column Break",
"permlevel": 0
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "uom",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Item UOM",
"no_copy": 0,
"options": "UOM",
"permlevel": 0,
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "section_break_25",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "description",
"fieldtype": "Small Text",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Item Desription",
"no_copy": 0,
"permlevel": 0,
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break_27",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "image",
"fieldtype": "Attach",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Image",
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"fieldname": "Image_view",
"allow_on_submit": 0,
"fieldname": "image_view",
"fieldtype": "Image",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Image View",
"no_copy": 0,
"options": "image",
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "eval:!doc.__islocal",
"fieldname": "section_break0",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Materials Required (Exploded)",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "exploded_items",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Exploded_items",
"no_copy": 1,
"oldfieldname": "flat_bom_details",
@@ -268,7 +634,12 @@
"options": "BOM Explosion Item",
"permlevel": 0,
"print_hide": 1,
"read_only": 1
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"hide_heading": 0,
@@ -276,46 +647,59 @@
"icon": "icon-sitemap",
"idx": 1,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 1,
"issingle": 0,
"istable": 0,
"modified": "2015-06-26 02:02:30.705279",
"modified": "2015-08-12 08:52:36.656865",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "BOM",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Manufacturing Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 1,
"write": 1
},
{
"amend": 0,
"apply_user_permissions": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Manufacturing User",
"set_user_permissions": 0,
"share": 1,
"submit": 1,
"write": 1
}
],
"read_only": 0,
"read_only_onload": 0,
"search_fields": "item",
"sort_field": "modified",
"sort_order": "DESC"

View File

@@ -1,150 +1,336 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "hash",
"creation": "2013-03-07 11:42:57",
"custom": 0,
"default_print_format": "Standard",
"docstatus": 0,
"doctype": "DocType",
"fields": [
{
"allow_on_submit": 0,
"fieldname": "item_code",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Item Code",
"no_copy": 0,
"oldfieldname": "item_code",
"oldfieldtype": "Link",
"options": "Item",
"permlevel": 0,
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "cb",
"fieldtype": "Column Break",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "item_name",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Item Name",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"read_only": 1
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "item_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Item Name",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "section_break_3",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "description",
"fieldtype": "Text",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Description",
"no_copy": 0,
"oldfieldname": "description",
"oldfieldtype": "Text",
"permlevel": 0,
"print_hide": 0,
"print_width": "300px",
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0,
"width": "300px"
},
{
"allow_on_submit": 0,
"fieldname": "column_break_2",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "image",
"fieldtype": "Attach",
"hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Image",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 1
"print_hide": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "image_view",
"fieldtype": "Image",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Image View",
"no_copy": 0,
"options": "image",
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "section_break_4",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "qty",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Qty",
"no_copy": 0,
"oldfieldname": "qty",
"oldfieldtype": "Currency",
"permlevel": 0,
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "rate",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Rate",
"no_copy": 0,
"oldfieldname": "standard_rate",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "qty_consumed_per_unit",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Qty Consumed Per Unit",
"no_copy": 0,
"permlevel": 0,
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break_8",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "stock_uom",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Stock UOM",
"no_copy": 0,
"oldfieldname": "stock_uom",
"oldfieldtype": "Link",
"options": "UOM",
"permlevel": 0,
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Amount",
"no_copy": 0,
"oldfieldname": "amount_as_per_sr",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 1,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-02-19 01:06:59.399382",
"modified": "2015-08-12 08:52:39.190103",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "BOM Explosion Item",
"owner": "Administrator",
"permissions": [],
"read_only": 0
"read_only": 0,
"read_only_onload": 0
}

View File

@@ -1,174 +1,382 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"creation": "2013-02-22 01:27:49",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"fields": [
{
"allow_on_submit": 0,
"fieldname": "item_code",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 1,
"label": "Item Code",
"no_copy": 0,
"oldfieldname": "item_code",
"oldfieldtype": "Link",
"options": "Item",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 1
"search_index": 1,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "item_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Item Name",
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break_3",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "bom_no",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "BOM No",
"no_copy": 0,
"oldfieldname": "bom_no",
"oldfieldtype": "Link",
"options": "BOM",
"permlevel": 0,
"print_hide": 0,
"print_width": "150px",
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 1,
"set_only_once": 0,
"unique": 0,
"width": "150px"
},
{
"allow_on_submit": 0,
"fieldname": "section_break_5",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "description",
"fieldtype": "Text",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Item Description",
"no_copy": 0,
"oldfieldname": "description",
"oldfieldtype": "Text",
"permlevel": 0,
"print_hide": 0,
"print_width": "250px",
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0,
"width": "250px"
},
{
"allow_on_submit": 0,
"fieldname": "col_break1",
"fieldtype": "Column Break",
"permlevel": 0
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "image",
"fieldtype": "Attach",
"hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Image",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 1
"print_hide": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "image_view",
"fieldtype": "Image",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Image View",
"no_copy": 0,
"options": "image",
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "quantity_and_rate",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Quantity and Rate",
"permlevel": 0
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "qty",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Qty",
"no_copy": 0,
"oldfieldname": "qty",
"oldfieldtype": "Currency",
"permlevel": 0,
"reqd": 1
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"description": "See \"Rate Of Materials Based On\" in Costing Section",
"fieldname": "rate",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Rate",
"no_copy": 0,
"options": "Company:company:default_currency",
"permlevel": 0,
"reqd": 1
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "col_break2",
"fieldtype": "Column Break",
"permlevel": 0
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "stock_uom",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Stock UOM",
"no_copy": 0,
"oldfieldname": "stock_uom",
"oldfieldtype": "Data",
"options": "UOM",
"permlevel": 0,
"print_hide": 0,
"read_only": 1,
"reqd": 1
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Amount",
"no_copy": 0,
"oldfieldname": "amount_as_per_mar",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"print_hide": 0,
"print_width": "150px",
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0,
"width": "150px"
},
{
"allow_on_submit": 0,
"fieldname": "scrap",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Scrap %",
"no_copy": 0,
"oldfieldname": "scrap",
"oldfieldtype": "Currency",
"permlevel": 0,
"print_hide": 1
"print_hide": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "qty_consumed_per_unit",
"fieldtype": "Float",
"hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Qty Consumed Per Unit",
"no_copy": 0,
"oldfieldname": "qty_consumed_per_unit",
"oldfieldtype": "Float",
"permlevel": 0,
"print_hide": 1,
"read_only": 1
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 1,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-02-12 15:17:18.324810",
"modified": "2015-08-12 08:52:41.512788",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "BOM Item",
"owner": "Administrator",
"permissions": [],
"read_only": 0,
"read_only_onload": 0,
"sort_field": "modified",
"sort_order": "DESC"
}

View File

@@ -1,86 +1,175 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"creation": "2013-02-22 01:27:49",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"fields": [
{
"allow_on_submit": 0,
"fieldname": "operation",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Operation",
"no_copy": 0,
"oldfieldname": "operation_no",
"oldfieldtype": "Data",
"options": "Operation",
"permlevel": 0,
"reqd": 1
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "workstation",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Workstation",
"no_copy": 0,
"oldfieldname": "workstation",
"oldfieldtype": "Link",
"options": "Workstation",
"permlevel": 0,
"reqd": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "description",
"fieldtype": "Text",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Operation Description",
"no_copy": 0,
"oldfieldname": "opn_description",
"oldfieldtype": "Text",
"permlevel": 0,
"reqd": 1
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "col_break1",
"fieldtype": "Column Break",
"permlevel": 0
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "hour_rate",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Hour Rate",
"no_copy": 0,
"oldfieldname": "hour_rate",
"oldfieldtype": "Currency",
"permlevel": 0,
"reqd": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"description": "In minutes",
"fieldname": "time_in_mins",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Operation Time ",
"no_copy": 0,
"oldfieldname": "time_in_mins",
"oldfieldtype": "Currency",
"options": "",
"permlevel": 0,
"reqd": 1
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "operating_cost",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Operating Cost",
"no_copy": 0,
"oldfieldname": "operating_cost",
"oldfieldtype": "Currency",
"permlevel": 0,
"print_hide": 0,
"read_only": 1,
"reqd": 0
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 1,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-04-22 03:24:47.809532",
"modified": "2015-08-12 08:52:43.922881",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "BOM Operation",
"owner": "Administrator",
"permissions": []
"permissions": [],
"read_only": 0,
"read_only_onload": 0
}

View File

@@ -1,40 +1,77 @@
{
"allow_copy": 1,
"allow_email": 1,
"allow_import": 0,
"allow_print": 1,
"allow_rename": 0,
"creation": "2012-12-06 12:10:10",
"custom": 0,
"description": "Replace a particular BOM in all other BOMs where it is used. It will replace the old BOM link, update cost and regenerate \"BOM Explosion Item\" table as per new BOM",
"docstatus": 0,
"doctype": "DocType",
"document_type": "Other",
"fields": [
{
"allow_on_submit": 0,
"description": "The BOM which will be replaced",
"fieldname": "current_bom",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Current BOM",
"no_copy": 0,
"options": "BOM",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"reqd": 1
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"description": "The new BOM after replacement",
"fieldname": "new_bom",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "New BOM",
"no_copy": 0,
"options": "BOM",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"reqd": 1
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "replace",
"fieldtype": "Button",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Replace",
"no_copy": 0,
"options": "replace_bom",
"permlevel": 0,
"read_only": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"hide_heading": 1,
@@ -42,23 +79,37 @@
"icon": "icon-magic",
"idx": 1,
"in_create": 1,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 1,
"modified": "2015-02-05 05:11:35.233845",
"istable": 0,
"modified": "2015-08-12 08:52:46.035343",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "BOM Replace Tool",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 0,
"email": 0,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 0,
"role": "Manufacturing Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
}
],
"read_only": 1
"read_only": 1,
"read_only_onload": 0
}

View File

@@ -1,114 +1,123 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"creation": "2014-11-27 14:12:07.542534",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Master",
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"creation": "2014-11-27 14:12:07.542534",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Master",
"fields": [
{
"fieldname": "capacity_planning",
"fieldtype": "Section Break",
"label": "Capacity Planning",
"permlevel": 0,
"fieldname": "capacity_planning",
"fieldtype": "Section Break",
"label": "Capacity Planning",
"permlevel": 0,
"precision": ""
},
},
{
"description": "Disables creation of time logs against Production Orders.\nOperations shall not be tracked against Production Order",
"fieldname": "disable_capacity_planning",
"fieldtype": "Check",
"label": "Disable Capacity Planning and Time Tracking",
"permlevel": 0,
"description": "Disables creation of time logs against Production Orders.\nOperations shall not be tracked against Production Order",
"fieldname": "disable_capacity_planning",
"fieldtype": "Check",
"label": "Disable Capacity Planning and Time Tracking",
"permlevel": 0,
"precision": ""
},
},
{
"description": "Plan time logs outside Workstation Working Hours.",
"fieldname": "allow_overtime",
"fieldtype": "Check",
"label": "Allow Overtime",
"permlevel": 0,
"description": "Plan time logs outside Workstation Working Hours.",
"fieldname": "allow_overtime",
"fieldtype": "Check",
"label": "Allow Overtime",
"permlevel": 0,
"precision": ""
},
},
{
"default": "",
"fieldname": "allow_production_on_holidays",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Allow Production on Holidays",
"options": "",
"permlevel": 0,
"default": "",
"fieldname": "allow_production_on_holidays",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Allow Production on Holidays",
"options": "",
"permlevel": 0,
"precision": ""
},
},
{
"fieldname": "column_break_3",
"fieldtype": "Column Break",
"permlevel": 0,
"default": "BOM",
"fieldname": "backflush_raw_materials_based_on",
"fieldtype": "Select",
"label": "Backflush Raw Materials Based On",
"options": "BOM\nMaterial Transferred for Manufacture",
"permlevel": 0,
"precision": ""
},
},
{
"default": "30",
"description": "Try planning operations for X days in advance.",
"fieldname": "capacity_planning_for_days",
"fieldtype": "Int",
"label": "Capacity Planning For (Days)",
"permlevel": 0,
"fieldname": "column_break_3",
"fieldtype": "Column Break",
"permlevel": 0,
"precision": ""
},
},
{
"description": "Default 10 mins",
"fieldname": "mins_between_operations",
"fieldtype": "Int",
"label": "Time Between Operations (in mins)",
"permlevel": 0,
"default": "30",
"description": "Try planning operations for X days in advance.",
"fieldname": "capacity_planning_for_days",
"fieldtype": "Int",
"label": "Capacity Planning For (Days)",
"permlevel": 0,
"precision": ""
},
},
{
"fieldname": "over_production_allowance_percentage",
"fieldtype": "Percent",
"label": "Over Production Allowance Percentage",
"permlevel": 0,
"description": "Default 10 mins",
"fieldname": "mins_between_operations",
"fieldtype": "Int",
"label": "Time Between Operations (in mins)",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "over_production_allowance_percentage",
"fieldtype": "Percent",
"label": "Over Production Allowance Percentage",
"permlevel": 0,
"precision": ""
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "icon-wrench",
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"modified": "2015-07-23 08:12:33.889753",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Manufacturing Settings",
"name_case": "",
"owner": "Administrator",
],
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "icon-wrench",
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"modified": "2015-08-12 08:12:33.889753",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Manufacturing Settings",
"name_case": "",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 0,
"email": 0,
"export": 0,
"import": 0,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 0,
"role": "Manufacturing Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 0,
"email": 0,
"export": 0,
"import": 0,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 0,
"role": "Manufacturing Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
}
],
"read_only": 0,
"read_only_onload": 0,
"sort_field": "modified",
],
"read_only": 0,
"read_only_onload": 0,
"sort_field": "modified",
"sort_order": "DESC"
}
}

View File

@@ -4,6 +4,14 @@
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
from frappe.utils import cint
from dateutil.relativedelta import relativedelta
class ManufacturingSettings(Document):
pass
def get_mins_between_operations():
if not hasattr(frappe.local, "_mins_between_operations"):
frappe.local._mins_between_operations = cint(frappe.db.get_single_value("Manufacturing Settings",
"mins_between_operations")) or 10
return relativedelta(minutes=frappe.local._mins_between_operations)

View File

@@ -152,7 +152,9 @@ $.extend(cur_frm.cscript, {
method: "erpnext.manufacturing.doctype.production_order.production_order.get_item_details",
args: { item: doc.production_item },
callback: function(r) {
cur_frm.set_value(r.message);
$.each(["description", "stock_uom", "bom_no"], function(i, field) {
cur_frm.set_value(field, r.message[field]);
});
}
});
},
@@ -160,7 +162,7 @@ $.extend(cur_frm.cscript, {
make_se: function(purpose) {
var me = this;
var max = (purpose === "Manufacture") ?
flt(this.frm.doc.qty) - flt(this.frm.doc.produced_qty) :
flt(this.frm.doc.material_transferred_for_manufacturing) - flt(this.frm.doc.produced_qty) :
flt(this.frm.doc.qty) - flt(this.frm.doc.material_transferred_for_manufacturing);
frappe.prompt({fieldtype:"Int", label: __("Qty for {0}", [purpose]), fieldname:"qty",
@@ -187,8 +189,8 @@ $.extend(cur_frm.cscript, {
bom_no: function() {
return this.frm.call({
doc: this.frm.doc,
method: "set_production_order_operations"
doc: this.frm.doc,
method: "set_production_order_operations"
});
},
@@ -250,7 +252,7 @@ cur_frm.fields_dict['production_item'].get_query = function(doc) {
return {
filters:[
['Item', 'is_pro_applicable', '=', 1],
['Item', 'has_variants', '=', 0]
['Item', 'has_variants', '=', 0],
['Item', 'end_of_life', '>=', frappe.datetime.nowdate()]
]
}

View File

@@ -1,31 +1,62 @@
{
"allow_copy": 0,
"allow_import": 1,
"allow_rename": 0,
"autoname": "naming_series:",
"creation": "2013-01-10 16:34:16",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"fields": [
{
"allow_on_submit": 0,
"fieldname": "item",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "",
"no_copy": 0,
"options": "icon-gift",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"default": "PRO-",
"fieldname": "naming_series",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Series",
"no_copy": 0,
"options": "PRO-",
"permlevel": 0,
"reqd": 1
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"default": "Draft",
"depends_on": "eval:!doc.__islocal",
"fieldname": "status",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "Status",
@@ -34,333 +65,739 @@
"oldfieldtype": "Select",
"options": "\nDraft\nSubmitted\nStopped\nIn Process\nCompleted\nCancelled",
"permlevel": 0,
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 1,
"search_index": 1
"search_index": 1,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "production_item",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 1,
"label": "Item To Manufacture",
"no_copy": 0,
"oldfieldname": "production_item",
"oldfieldtype": "Link",
"options": "Item",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"reqd": 1
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "",
"description": "",
"fieldname": "bom_no",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "BOM No",
"no_copy": 0,
"oldfieldname": "bom_no",
"oldfieldtype": "Link",
"options": "BOM",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"reqd": 1
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"default": "1",
"description": "Plan material for sub-assemblies",
"fieldname": "use_multi_level_bom",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Use Multi-Level BOM",
"permlevel": 0
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break1",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"oldfieldtype": "Column Break",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0,
"width": "50%"
},
{
"allow_on_submit": 0,
"depends_on": "",
"fieldname": "qty",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Qty To Manufacture",
"no_copy": 0,
"oldfieldname": "qty",
"oldfieldtype": "Currency",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"reqd": 1
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"default": "0",
"depends_on": "eval:doc.docstatus==1",
"description": "",
"fieldname": "material_transferred_for_manufacturing",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Material Transferred for Manufacturing",
"no_copy": 1,
"permlevel": 0,
"precision": "",
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"default": "0",
"depends_on": "eval:doc.docstatus==1",
"description": "",
"fieldname": "produced_qty",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Manufactured Qty",
"no_copy": 1,
"oldfieldname": "produced_qty",
"oldfieldtype": "Currency",
"permlevel": 0,
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "warehouses",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Warehouses",
"no_copy": 0,
"options": "icon-building",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "wip_warehouse",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Work-in-Progress Warehouse",
"no_copy": 0,
"options": "Warehouse",
"permlevel": 0,
"reqd": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break_12",
"fieldtype": "Column Break",
"permlevel": 0
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "",
"description": "",
"fieldname": "fg_warehouse",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Target Warehouse",
"no_copy": 0,
"options": "Warehouse",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"reqd": 0
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "time",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Time",
"no_copy": 0,
"options": "icon-time",
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "",
"fieldname": "expected_delivery_date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Expected Delivery Date",
"no_copy": 0,
"permlevel": 0,
"read_only": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"default": "now",
"fieldname": "planned_start_date",
"fieldtype": "Datetime",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Planned Start Date",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"reqd": 1
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "planned_end_date",
"fieldtype": "Datetime",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Planned End Date",
"no_copy": 1,
"permlevel": 0,
"precision": "",
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break_13",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "actual_start_date",
"fieldtype": "Datetime",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Actual Start Date",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "actual_end_date",
"fieldtype": "Datetime",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Actual End Date",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "",
"fieldname": "operations_section",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Operations",
"no_copy": 0,
"options": "icon-wrench",
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "",
"fieldname": "operations",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Operations",
"no_copy": 0,
"options": "Production Order Operation",
"permlevel": 0,
"precision": "",
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "operations",
"fieldname": "section_break_22",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Operation Cost",
"no_copy": 0,
"options": "",
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "planned_operating_cost",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Planned Operating Cost",
"no_copy": 0,
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "actual_operating_cost",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Actual Operating Cost",
"no_copy": 1,
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "additional_operating_cost",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Additional Operating Cost",
"no_copy": 1,
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break_24",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "total_operating_cost",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Total Operating Cost",
"no_copy": 1,
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "more_info",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "More Info",
"no_copy": 0,
"options": "icon-file-text",
"permlevel": 0,
"read_only": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "description",
"fieldtype": "Small Text",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Item Description",
"no_copy": 0,
"permlevel": 0,
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "",
"fieldname": "stock_uom",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Stock UOM",
"no_copy": 0,
"oldfieldname": "stock_uom",
"oldfieldtype": "Data",
"options": "UOM",
"permlevel": 0,
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break2",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0,
"width": "50%"
},
{
"allow_on_submit": 0,
"fieldname": "project_name",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "Project Name",
"no_copy": 0,
"oldfieldname": "project_name",
"oldfieldtype": "Link",
"options": "Project",
"permlevel": 0,
"read_only": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"description": "Manufacture against Sales Order",
"fieldname": "sales_order",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Sales Order",
"no_copy": 0,
"options": "Sales Order",
"permlevel": 0,
"read_only": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Company",
"no_copy": 0,
"oldfieldname": "company",
"oldfieldtype": "Link",
"options": "Company",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"reqd": 1
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "amended_from",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 1,
"in_filter": 0,
"in_list_view": 0,
"label": "Amended From",
"no_copy": 1,
"oldfieldname": "amended_from",
"oldfieldtype": "Data",
"options": "Production Order",
"permlevel": 0,
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "icon-cogs",
"idx": 1,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 1,
"modified": "2015-07-21 07:45:53.206902",
"issingle": 0,
"istable": 0,
"modified": "2015-08-12 08:50:32.803526",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Production Order",
@@ -373,22 +810,41 @@
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Manufacturing User",
"set_user_permissions": 0,
"share": 1,
"submit": 1,
"write": 1
},
{
"amend": 0,
"apply_user_permissions": 1,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 0,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 1,
"role": "Stock User"
"role": "Stock User",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
}
],
"read_only": 0,
"read_only_onload": 0,
"title_field": "production_item"
}

View File

@@ -10,6 +10,10 @@ from frappe.model.document import Document
from erpnext.manufacturing.doctype.bom.bom import validate_bom_no
from dateutil.relativedelta import relativedelta
from erpnext.stock.doctype.item.item import validate_end_of_life
from erpnext.manufacturing.doctype.workstation.workstation import WorkstationHolidayError, NotInWorkingHoursError
from erpnext.projects.doctype.time_log.time_log import OverlapError
from erpnext.stock.doctype.stock_entry.stock_entry import get_additional_costs
from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import get_mins_between_operations
class OverProductionError(frappe.ValidationError): pass
class StockOverProductionError(frappe.ValidationError): pass
@@ -17,9 +21,6 @@ class OperationTooLongError(frappe.ValidationError): pass
class ProductionNotApplicableError(frappe.ValidationError): pass
class ItemHasVariantError(frappe.ValidationError): pass
from erpnext.manufacturing.doctype.workstation.workstation import WorkstationHolidayError, NotInWorkingHoursError
from erpnext.projects.doctype.time_log.time_log import OverlapError
form_grid_templates = {
"operations": "templates/form_grid/production_order_grid.html"
}
@@ -106,6 +107,7 @@ class ProductionOrder(Document):
qty = (flt(self.qty)-flt(self.produced_qty)) * ((status == 'Stopped') and -1 or 1)
self.update_planned_qty(qty)
frappe.msgprint(_("Production Order status is {0}").format(status))
self.notify_modified()
def update_status(self, status=None):
@@ -231,6 +233,7 @@ class ProductionOrder(Document):
original_start_time = time_log.from_time
while True:
_from_time = time_log.from_time
try:
time_log.save()
break
@@ -248,6 +251,7 @@ class ProductionOrder(Document):
frappe.msgprint(_("Unable to find Time Slot in the next {0} days for Operation {1}").format(plan_days, d.operation))
break
# if time log needs to be moved, make sure that the from time is not the same
if _from_time == time_log.from_time:
frappe.throw("Capacity Planning Error")
@@ -273,19 +277,13 @@ class ProductionOrder(Document):
d.planned_start_time = self.planned_start_date
else:
d.planned_start_time = get_datetime(self.operations[i-1].planned_end_time)\
+ self.get_mins_between_operations()
+ get_mins_between_operations()
d.planned_end_time = get_datetime(d.planned_start_time) + relativedelta(minutes = d.time_in_mins)
if d.planned_start_time == d.planned_end_time:
frappe.throw(_("Capacity Planning Error"))
def get_mins_between_operations(self):
if not hasattr(self, "_mins_between_operations"):
self._mins_between_operations = cint(frappe.db.get_single_value("Manufacturing Settings",
"mins_between_operations")) or 10
return relativedelta(minutes=self._mins_between_operations)
def check_operation_fits_in_working_hours(self, d):
"""Raises expection if operation is longer than working hours in the given workstation."""
from erpnext.manufacturing.doctype.workstation.workstation import check_if_within_operating_hours
@@ -356,7 +354,6 @@ def make_stock_entry(production_order_id, purpose, qty=None):
stock_entry.company = production_order.company
stock_entry.from_bom = 1
stock_entry.bom_no = production_order.bom_no
stock_entry.additional_operating_cost = production_order.additional_operating_cost
stock_entry.use_multi_level_bom = production_order.use_multi_level_bom
stock_entry.fg_completed_qty = qty or (flt(production_order.qty) - flt(production_order.produced_qty))
@@ -365,6 +362,8 @@ def make_stock_entry(production_order_id, purpose, qty=None):
else:
stock_entry.from_warehouse = production_order.wip_warehouse
stock_entry.to_warehouse = production_order.fg_warehouse
additional_costs = get_additional_costs(production_order, fg_qty=stock_entry.fg_completed_qty)
stock_entry.set("additional_costs", additional_costs)
stock_entry.get_items()
return stock_entry.as_dict()

View File

@@ -28,9 +28,9 @@ class TestProductionOrder(unittest.TestCase):
# add raw materials to stores
test_stock_entry.make_stock_entry(item_code="_Test Item",
target="Stores - _TC", qty=100, incoming_rate=100)
target="Stores - _TC", qty=100, basic_rate=100)
test_stock_entry.make_stock_entry(item_code="_Test Item Home Desktop 100",
target="Stores - _TC", qty=100, incoming_rate=100)
target="Stores - _TC", qty=100, basic_rate=100)
# from stores to wip
s = frappe.get_doc(make_stock_entry(pro_order.name, "Material Transfer for Manufacture", 4))
@@ -58,9 +58,9 @@ class TestProductionOrder(unittest.TestCase):
pro_doc = self.check_planned_qty()
test_stock_entry.make_stock_entry(item_code="_Test Item",
target="_Test Warehouse - _TC", qty=100, incoming_rate=100)
target="_Test Warehouse - _TC", qty=100, basic_rate=100)
test_stock_entry.make_stock_entry(item_code="_Test Item Home Desktop 100",
target="_Test Warehouse - _TC", qty=100, incoming_rate=100)
target="_Test Warehouse - _TC", qty=100, basic_rate=100)
s = frappe.get_doc(make_stock_entry(pro_doc.name, "Manufacture", 7))
s.insert()

View File

@@ -44,31 +44,35 @@ class ProductionPlanningTool(Document):
""" Pull sales orders which are pending to deliver based on criteria selected"""
so_filter = item_filter = ""
if self.from_date:
so_filter += ' and so.transaction_date >= "' + self.from_date + '"'
so_filter += " and so.transaction_date >= %(from_date)s"
if self.to_date:
so_filter += ' and so.transaction_date <= "' + self.to_date + '"'
so_filter += " and so.transaction_date <= %(to_date)s"
if self.customer:
so_filter += ' and so.customer = "' + self.customer + '"'
so_filter += " and so.customer = %(customer)s"
if self.fg_item:
item_filter += ' and item.name = "' + self.fg_item + '"'
item_filter += " and item.name = %(item)s"
open_so = frappe.db.sql("""
select distinct so.name, so.transaction_date, so.customer, so.base_grand_total
from `tabSales Order` so, `tabSales Order Item` so_item
where so_item.parent = so.name
and so.docstatus = 1 and so.status != "Stopped"
and so.company = %s
and ifnull(so_item.qty, 0) > ifnull(so_item.delivered_qty, 0) %s
and so.company = %(company)s
and ifnull(so_item.qty, 0) > ifnull(so_item.delivered_qty, 0) {0}
and (exists (select name from `tabItem` item where item.name=so_item.item_code
and (item.is_pro_applicable = 1
or item.is_sub_contracted_item = 1 %s)
and (item.is_pro_applicable = 1 or item.is_sub_contracted_item = 1 {1}))
or exists (select name from `tabPacked Item` pi
where pi.parent = so.name and pi.parent_item = so_item.item_code
and exists (select name from `tabItem` item where item.name=pi.item_code
and (item.is_pro_applicable = 1
or item.is_sub_contracted_item = 1) %s)))
""" % ('%s', so_filter, item_filter, item_filter), self.company, as_dict=1)
and (item.is_pro_applicable = 1 or item.is_sub_contracted_item = 1) {2})))
""".format(so_filter, item_filter, item_filter), {
"from_date": self.from_date,
"to_date": self.to_date,
"customer": self.customer,
"item": self.fg_item,
"company": self.company
}, as_dict=1)
self.add_so_in_table(open_so)

View File

@@ -47,6 +47,7 @@ erpnext.patches.v4_0.update_account_root_type
execute:frappe.delete_doc("Report", "Purchase In Transit")
erpnext.patches.v4_0.new_address_template
execute:frappe.delete_doc("DocType", "SMS Control")
execute:frappe.delete_doc_if_exists("DocType", "Bulk SMS") #2015-08-18
erpnext.patches.v4_0.fix_case_of_hr_module_def
erpnext.patches.v4_0.fix_address_template
@@ -99,7 +100,6 @@ execute:frappe.db.sql("update `tabMaterial Request` set material_request_type =
execute:frappe.reload_doc('stock', 'doctype', 'item')
execute:frappe.db.sql("update `tabItem` i set apply_warehouse_wise_reorder_level=1, re_order_level=0, re_order_qty=0 where exists(select name from `tabItem Reorder` where parent=i.name)")
erpnext.patches.v5_0.set_default_company_in_bom
erpnext.patches.v5_0.capacity_planning
execute:frappe.reload_doc('crm', 'doctype', 'lead')
execute:frappe.reload_doc('crm', 'doctype', 'opportunity')
erpnext.patches.v5_0.rename_taxes_and_charges_master
@@ -137,7 +137,6 @@ erpnext.patches.v5_0.update_account_types
erpnext.patches.v5_0.update_sms_sender
erpnext.patches.v5_0.set_appraisal_remarks
erpnext.patches.v5_0.update_time_log_title
erpnext.patches.v4_2.repost_reserved_qty
erpnext.patches.v4_2.repost_sle_for_si_with_no_warehouse
erpnext.patches.v5_0.newsletter
execute:frappe.delete_doc("DocType", "Chart of Accounts")
@@ -172,7 +171,6 @@ execute:frappe.delete_doc("Page", "users")
erpnext.patches.v5_0.update_material_transferred_for_manufacturing_again
erpnext.patches.v5_0.index_on_account_and_gl_entry
execute:frappe.db.sql("""delete from `tabProject Task`""")
erpnext.patches.v5_0.item_variants
erpnext.patches.v5_0.update_item_desc_in_invoice
erpnext.patches.v5_1.fix_against_account
erpnext.patches.v5_1.fix_credit_days_based_on
@@ -180,6 +178,18 @@ execute:frappe.rename_doc("DocType", "Salary Manager", "Process Payroll", force=
erpnext.patches.v5_1.rename_roles
erpnext.patches.v5_1.default_bom
execute:frappe.delete_doc("DocType", "Party Type")
erpnext.patches.v5_4.fix_reserved_qty_and_sle_for_packed_items
execute:frappe.delete_doc("Module Def", "Contacts")
erpnext.patches.v5_4.fix_reserved_qty_and_sle_for_packed_items # 30-07-2015
execute:frappe.reload_doctype("Leave Type")
execute:frappe.db.sql("update `tabLeave Type` set include_holiday=1")
execute:frappe.db.sql("update `tabLeave Type` set include_holiday=0")
erpnext.patches.v5_4.set_root_and_report_type
erpnext.patches.v5_4.notify_system_managers_regarding_wrong_tax_calculation
erpnext.patches.v5_4.fix_invoice_outstanding
execute:frappe.db.sql("update `tabStock Ledger Entry` set stock_queue = '[]' where voucher_type = 'Stock Reconciliation' and ifnull(qty_after_transaction, 0) = 0")
erpnext.patches.v5_4.fix_missing_item_images
erpnext.patches.v5_4.stock_entry_additional_costs
erpnext.patches.v5_4.cleanup_journal_entry #2015-08-14
execute:frappe.db.sql("update `tabProduction Order` pro set description = (select description from tabItem where name=pro.production_item) where ifnull(description, '') = ''")
erpnext.patches.v5_7.item_template_attributes
erpnext.patches.v4_2.repost_reserved_qty #2015-08-17
erpnext.patches.v5_4.update_purchase_cost_against_project

View File

@@ -6,7 +6,22 @@ import frappe
from erpnext.utilities.repost_stock import update_bin_qty, get_reserved_qty
def execute():
for item_code, warehouse in frappe.db.sql("select item_code, warehouse from tabBin where ifnull(reserved_qty, 0) < 0"):
update_bin_qty(item_code, warehouse, {
"reserved_qty": get_reserved_qty(item_code, warehouse)
})
repost_for = frappe.db.sql("""
select
distinct item_code, warehouse
from
(
(
select distinct item_code, warehouse
from `tabSales Order Item` where docstatus=1
) UNION (
select distinct item_code, warehouse
from `tabPacked Item` where docstatus=1 and parenttype='Sales Order'
)
) items
""")
for item_code, warehouse in repost_for:
update_bin_qty(item_code, warehouse, {
"reserved_qty": get_reserved_qty(item_code, warehouse)
})

View File

@@ -1,9 +0,0 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import frappe
def execute():
frappe.reload_doc("stock", "doctype", "stock_entry")
if "total_fixed_cost" in frappe.db.get_table_columns("Stock Entry"):
frappe.db.sql("update `tabStock Entry` set additional_operating_cost = total_fixed_cost")

View File

@@ -1,19 +0,0 @@
import frappe
def execute():
frappe.reload_doctype("Item")
for dt in ["manage_variants", "manage_variants_item", "variant_attribute"]:
frappe.reload_doc("stock", "doctype", dt)
for d in frappe.get_list("Item", filters={"has_variants":1}):
manage_variant = frappe.new_doc("Manage Variants")
manage_variant.item_code = d.name
manage_variant.attributes = frappe.db.sql("select item_attribute as attribute, item_attribute_value as attribute_value \
from `tabItem Variant` where parent = %s", d.name, as_dict=1)
if manage_variant.attributes:
if not frappe.get_list("Item", filters={"variant_of": d.name}, limit_page_length=1):
frappe.db.sql("delete from `tabItem Variant` where parent=%s", d.name)
else:
manage_variant.generate_combinations()
manage_variant.create_variants()
frappe.delete_doc("DocType", "Item Variant")

View File

@@ -0,0 +1,20 @@
import frappe
from MySQLdb import OperationalError
def execute():
frappe.reload_doctype("Journal Entry Account")
for doctype, fieldname in (
("Sales Order", "against_sales_order"),
("Purchase Order", "against_purchase_order"),
("Sales Invoice", "against_invoice"),
("Purchase Invoice", "against_voucher"),
("Journal Entry", "against_jv"),
("Expense Claim", "against_expense_claim"),
):
try:
frappe.db.sql("""update `tabJournal Entry Account`
set reference_type=%s, reference_name={0} where ifnull({0}, '') != ''
""".format(fieldname), doctype)
except OperationalError:
# column not found
pass

View File

@@ -0,0 +1,13 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
def execute():
frappe.reload_doctype("Sales Invoice")
return_entries = frappe.get_list("Sales Invoice", filters={"is_return": 1, "docstatus": 1},
fields=["debit_to", "customer", "return_against"])
for d in return_entries:
update_outstanding_amt(d.debit_to, "Customer", d.customer, "Sales Invoice", d.return_against)

View File

@@ -0,0 +1,116 @@
from __future__ import unicode_literals
import frappe
import os
from frappe.utils import get_files_path
from frappe.utils.file_manager import get_content_hash
def execute():
files_path = get_files_path()
# get files that don't have attached_to_name but exist
unlinked_files = get_unlinked_files(files_path)
if not unlinked_files:
return
fixed_files = fix_files_for_item(files_path, unlinked_files)
# fix remaining files
for key, file_data in unlinked_files.items():
if key not in fixed_files:
rename_and_set_content_hash(files_path, unlinked_files, key)
frappe.db.commit()
def fix_files_for_item(files_path, unlinked_files):
fixed_files = []
# make a list of files/something and /files/something to check in child table's image column
file_urls = [key for key in unlinked_files.keys()] + ["/" + key for key in unlinked_files.keys()]
file_item_code = get_file_item_code(file_urls)
for (file_url, item_code), children in file_item_code.items():
new_file_url = "/files/{0}".format(unlinked_files[file_url]["file_name"])
for row in children:
# print file_url, new_file_url, item_code, row.doctype, row.name
# replace image in these rows with the new file url
frappe.db.set_value(row.doctype, row.name, "image", new_file_url, update_modified=False)
# set it as attachment of this item code
file_data = frappe.get_doc("File Data", unlinked_files[file_url]["file"])
file_data.attached_to_doctype = "Item"
file_data.attached_to_name = item_code
file_data.save()
# set it as image in Item
if not frappe.db.get_value("Item", item_code, "image"):
frappe.db.set_value("Item", item_code, "image", new_file_url, update_modified=False)
rename_and_set_content_hash(files_path, unlinked_files, file_url)
fixed_files.append(file_url)
# commit
frappe.db.commit()
return fixed_files
def rename_and_set_content_hash(files_path, unlinked_files, file_url):
# rename this file
old_filename = os.path.join(files_path, unlinked_files[file_url]["file"])
new_filename = os.path.join(files_path, unlinked_files[file_url]["file_name"])
if not os.path.exists(new_filename):
os.rename(old_filename, new_filename)
# set content hash if missing
file_data_name = unlinked_files[file_url]["file"]
if not frappe.db.get_value("File Data", file_data_name, "content_hash"):
with open(new_filename, "r") as f:
content_hash = get_content_hash(f.read())
frappe.db.set_value("File Data", file_data_name, "content_hash", content_hash)
def get_unlinked_files(files_path):
# find files that have the same name as a File Data doc
# and the file_name mentioned in that File Data doc doesn't exist
# and it isn't already attached to a doc
unlinked_files = {}
files = os.listdir(files_path)
for file in files:
if not frappe.db.exists("File Data", {"file_name": file}):
file_data = frappe.db.get_value("File Data", {"name": file},
["file_name", "attached_to_doctype", "attached_to_name"], as_dict=True)
if (file_data
and file_data.file_name
and file_data.file_name not in files
and not file_data.attached_to_doctype
and not file_data.attached_to_name):
file_data["file"] = file
unlinked_files["files/{0}".format(file)] = file_data
return unlinked_files
def get_file_item_code(file_urls):
# get a map of file_url, item_code and list of documents where file_url will need to be changed in image field
file_item_code = {}
doctypes = frappe.db.sql_list("""select name from `tabDocType` dt
where istable=1
and exists (select name from `tabDocField` df where df.parent=dt.name and df.fieldname='item_code')
and exists (select name from `tabDocField` df where df.parent=dt.name and df.fieldname='image')""")
for doctype in doctypes:
result = frappe.db.sql("""select name, image, item_code, '{0}' as doctype from `tab{0}`
where image in ({1})""".format(doctype, ", ".join(["%s"]*len(file_urls))),
file_urls, as_dict=True)
for r in result:
key = (r.image, r.item_code)
if key not in file_item_code:
file_item_code[key] = []
file_item_code[key].append(r)
return file_item_code

View File

@@ -3,22 +3,20 @@
from __future__ import unicode_literals
import frappe
from erpnext.utilities.repost_stock import update_bin_qty, get_reserved_qty, repost_actual_qty
from erpnext.utilities.repost_stock import repost_actual_qty
def execute():
cancelled_invoices = frappe.db.sql_list("""select name from `tabSales Invoice`
where docstatus = 2 and ifnull(update_stock, 0) = 1""")
if cancelled_invoices:
repost_for = frappe.db.sql("""select distinct item_code, warehouse from `tabStock Ledger Entry`
where voucher_type = 'Sales Invoice' and voucher_no in (%s)"""
% (', '.join(['%s']*len(cancelled_invoices))), tuple(cancelled_invoices))
frappe.db.sql("""delete from `tabStock Ledger Entry`
where voucher_type = 'Sales Invoice' and voucher_no in (%s)"""
% (', '.join(['%s']*len(cancelled_invoices))), tuple(cancelled_invoices))
for item_code, warehouse in frappe.db.sql("select item_code, warehouse from tabBin where ifnull(reserved_qty, 0) < 0"):
repost_actual_qty(item_code, warehouse)
update_bin_qty(item_code, warehouse, {
"reserved_qty": get_reserved_qty(item_code, warehouse)
})
for item_code, warehouse in repost_for:
repost_actual_qty(item_code, warehouse)

View File

@@ -0,0 +1,41 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
from frappe.email import sendmail_to_system_managers
from frappe.utils import get_url_to_form
def execute():
wrong_records = []
for dt in ("Quotation", "Sales Order", "Delivery Note", "Sales Invoice",
"Purchase Order", "Purchase Receipt", "Purchase Invoice"):
records = frappe.db.sql_list("""select name from `tab{0}`
where apply_discount_on = 'Net Total' and ifnull(discount_amount, 0) != 0
and modified >= '2015-02-17' and docstatus=1""".format(dt))
if records:
records = [get_url_to_form(dt, d) for d in records]
wrong_records.append([dt, records])
if wrong_records:
content = """Dear System Manager,
Due to an error related to Discount Amount on Net Total, tax calculation might be wrong in the following records. We did not fix the tax amount automatically because it can corrupt the entries, so we request you to check these records and amend if you found the calculation wrong.
Please check following Entries:
%s
Regards,
Administrator""" % "\n".join([(d[0] + ": " + ", ".join(d[1])) for d in wrong_records])
try:
sendmail_to_system_managers("[Important] [ERPNext] Tax calculation might be wrong, please check.", content)
except:
pass
print "="*50
print content
print "="*50

View File

@@ -0,0 +1,12 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
roots = frappe.db.sql("""select lft, rgt, report_type, root_type
from `tabAccount` where ifnull(parent_account, '')=''""", as_dict=1)
for d in roots:
frappe.db.sql("update `tabAccount` set report_type=%s, root_type=%s where lft > %s and rgt < %s",
(d.report_type, d.root_type, d.lft, d.rgt))

View File

@@ -0,0 +1,52 @@
# Copyright (c) 2015, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
from frappe.utils import flt
def execute():
frappe.reload_doctype("Stock Entry")
frappe.reload_doctype("Stock Entry Detail")
frappe.reload_doctype("Landed Cost Taxes and Charges")
frappe.db.sql("""update `tabStock Entry Detail` sed, `tabStock Entry` se
set sed.valuation_rate=sed.incoming_rate, sed.basic_rate=sed.incoming_rate, sed.basic_amount=sed.amount
where sed.parent = se.name
and (se.purpose not in ('Manufacture', 'Repack') or ifnull(additional_operating_cost, 0)=0)
""")
stock_entry_db_columns = frappe.db.get_table_columns("Stock Entry")
if "additional_operating_cost" in stock_entry_db_columns:
operating_cost_fieldname = "additional_operating_cost"
elif "total_fixed_cost" in stock_entry_db_columns:
operating_cost_fieldname = "total_fixed_cost"
else:
return
stock_entries = frappe.db.sql_list("""select name from `tabStock Entry`
where purpose in ('Manufacture', 'Repack') and ifnull({0}, 0)!=0
and docstatus < 2""".format(operating_cost_fieldname))
for d in stock_entries:
stock_entry = frappe.get_doc("Stock Entry", d)
stock_entry.append("additional_costs", {
"description": "Additional Operating Cost",
"amount": stock_entry.get(operating_cost_fieldname)
})
number_of_fg_items = len([t.t_warehouse for t in stock_entry.get("items") if t.t_warehouse])
for d in stock_entry.get("items"):
d.valuation_rate = d.incoming_rate
if d.bom_no or (d.t_warehouse and number_of_fg_items == 1):
d.additional_cost = stock_entry.get(operating_cost_fieldname)
d.basic_rate = flt(d.valuation_rate) - flt(d.additional_cost)
d.basic_amount = flt(flt(d.basic_rate) *flt(d.transfer_qty), d.precision("basic_amount"))
stock_entry.flags.ignore_validate = True
stock_entry.flags.ignore_validate_update_after_submit = True
stock_entry.save()

View File

@@ -0,0 +1,13 @@
# Copyright (c) 2015, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
for p in frappe.get_all("Project"):
purchase_cost = frappe.db.sql("""select sum(ifnull(base_net_amount, 0))
from `tabPurchase Invoice Item` where project_name = %s and docstatus=1""", p.name)
purchase_cost = purchase_cost and purchase_cost[0][0] or 0
frappe.db.set_value("Project", p.name, "total_purchase_cost", purchase_cost)

View File

@@ -0,0 +1 @@
from __future__ import unicode_literals

View File

@@ -0,0 +1,121 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
import MySQLdb
def execute():
"""
Structure History:
1. Item and Item Variant
2. Item, Variant Attribute, Manage Variants and Manage Variant Items
3. Item, Item Variant Attribute, Item Attribute and Item Attribute Type (latest)
"""
rename_and_reload_doctypes()
variant_templates = frappe.get_all("Item", filters={"has_variants": 1}, limit_page_length=1)
if not variant_templates:
# database does not have items that have variants
# so no point in running the patch
return
variant_attributes = frappe.get_all("Item Variant Attribute", fields=["*"], limit_page_length=1)
if variant_attributes:
# manage variant patch is already applied
migrate_manage_variants()
else:
# old structure based on "Item Variant" table
try:
migrate_item_variants()
except MySQLdb.ProgrammingError:
print "`tabItem Variant` not found"
def rename_and_reload_doctypes():
if "tabVariant Attribute" in frappe.db.get_tables():
frappe.rename_doc("DocType", "Variant Attribute", "Item Variant Attribute")
frappe.reload_doctype("Item")
frappe.reload_doctype("Item Variant Attribute")
frappe.reload_doctype("Item Attribute Value")
frappe.reload_doctype("Item Attribute")
def migrate_manage_variants():
item_attribute = {}
for d in frappe.db.sql("""select DISTINCT va.attribute, i.variant_of
from `tabItem Variant Attribute` va, `tabItem` i
where va.parent = i.name and ifnull(i.variant_of, '')!=''""", as_dict=1):
item_attribute.setdefault(d.variant_of, []).append({"attribute": d.attribute})
for item, attributes in item_attribute.items():
template = frappe.get_doc("Item", item)
template.set('attributes', attributes)
template.save()
frappe.delete_doc("DocType", "Manage Variants")
frappe.delete_doc("DocType", "Manage Variants Item")
# patch old style
def migrate_item_variants():
for item in frappe.get_all("Item", filters={"has_variants": 1}):
all_variants = frappe.get_all("Item", filters={"variant_of": item.name}, fields=["name", "description"])
item_attributes = frappe.db.sql("""select distinct item_attribute, item_attribute_value
from `tabItem Variant` where parent=%s""", item.name)
attribute_value_options = {}
for attribute, value in item_attributes:
attribute_value_options.setdefault(attribute, []).append(value)
save_attributes_in_template(item, attribute_value_options)
possible_combinations = get_possible_combinations(attribute_value_options)
for variant in all_variants:
for combination in possible_combinations:
match = True
for attribute, value in combination.items():
if "{0}: {1}".format(attribute, value) not in variant.description:
match = False
break
if match:
# found the right variant
save_attributes_in_variant(variant, combination)
break
frappe.delete_doc("DocType", "Item Variant")
def save_attributes_in_template(item, attribute_value_options):
# store attribute in Item Variant Attribute table for template
template = frappe.get_doc("Item", item)
template.set("attributes", [{"attribute": attribute} for attribute in attribute_value_options.keys()])
template.save()
def get_possible_combinations(attribute_value_options):
possible_combinations = []
for attribute, values in attribute_value_options.items():
if not possible_combinations:
for v in values:
possible_combinations.append({attribute: v})
else:
for v in values:
for combination in possible_combinations:
combination[attribute] = v
return possible_combinations
def save_attributes_in_variant(variant, combination):
# add data into attributes table
variant_item = frappe.get_doc("Item", variant.name)
variant_item.set("attributes", [])
for attribute, value in combination.items():
variant_item.append("attributes", {
"attribute": attribute,
"attribute_value": value
})
variant_item.save()

View File

@@ -1,68 +1,129 @@
{
"allow_copy": 0,
"allow_import": 1,
"allow_rename": 1,
"autoname": "field:project_name",
"creation": "2013-03-07 11:55:07",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Master",
"fields": [
{
"allow_on_submit": 0,
"description": "",
"fieldname": "project_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Project Name",
"no_copy": 0,
"oldfieldname": "project_name",
"oldfieldtype": "Data",
"permlevel": 0,
"reqd": 1
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"default": "Open",
"fieldname": "status",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "Status",
"no_copy": 1,
"oldfieldname": "status",
"oldfieldtype": "Select",
"options": "Open\nCompleted\nCancelled",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 1
"search_index": 1,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "project_type",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Project Type",
"no_copy": 0,
"oldfieldname": "project_type",
"oldfieldtype": "Data",
"options": "Internal\nExternal\nOther",
"permlevel": 0,
"search_index": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break_5",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "is_active",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Is Active",
"no_copy": 0,
"oldfieldname": "is_active",
"oldfieldtype": "Select",
"options": "Yes\nNo",
"permlevel": 0,
"search_index": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "priority",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Priority",
"no_copy": 0,
@@ -70,53 +131,123 @@
"oldfieldtype": "Select",
"options": "Medium\nLow\nHigh",
"permlevel": 0,
"search_index": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "section_break_12",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "expected_start_date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "Expected Start Date",
"no_copy": 0,
"oldfieldname": "project_start_date",
"oldfieldtype": "Date",
"permlevel": 0,
"search_index": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break_11",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "expected_end_date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Expected End Date",
"no_copy": 0,
"oldfieldname": "completion_date",
"oldfieldtype": "Date",
"permlevel": 0,
"search_index": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "customer_details",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "",
"no_copy": 0,
"oldfieldtype": "Section Break",
"options": "icon-user",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "customer",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "Customer",
"no_copy": 0,
"oldfieldname": "customer",
@@ -124,115 +255,281 @@
"options": "Customer",
"permlevel": 0,
"print_hide": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 1
"search_index": 1,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break_14",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "sales_order",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Sales Order",
"no_copy": 0,
"options": "Sales Order",
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "sb_milestones",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Tasks",
"no_copy": 0,
"oldfieldtype": "Section Break",
"options": "icon-flag",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "tasks",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Tasks",
"no_copy": 0,
"options": "Project Task",
"permlevel": 0,
"precision": "",
"reqd": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "percent_complete",
"fieldtype": "Percent",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "% Tasks Completed",
"no_copy": 1,
"permlevel": 0,
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "section_break0",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "",
"no_copy": 0,
"oldfieldtype": "Section Break",
"options": "icon-list",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "notes",
"fieldtype": "Text Editor",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Notes",
"no_copy": 0,
"oldfieldname": "notes",
"oldfieldtype": "Text Editor",
"permlevel": 0,
"search_index": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "section_break_18",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "actual_start_date",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Actual Start Date",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "actual_time",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Actual Time (in Hours)",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break_20",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "actual_end_date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Actual End Date",
"no_copy": 0,
"oldfieldname": "act_completion_date",
"oldfieldtype": "Date",
"permlevel": 0,
"print_hide": 0,
"read_only": 1,
"search_index": 0
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "section_break_26",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "estimated_costing",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Estimated Costing",
"no_copy": 0,
@@ -240,124 +537,292 @@
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break_22",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Company",
"no_copy": 0,
"options": "Company",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "cost_center",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Default Cost Center",
"no_copy": 0,
"options": "Cost Center",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "project_details",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "",
"no_copy": 0,
"oldfieldtype": "Section Break",
"options": "icon-money",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"description": "",
"fieldname": "total_costing_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Total Costing Amount (via Time Logs)",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"description": "",
"fieldname": "total_expense_claim",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Total Expense Claim (via Expense Claims)",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break_28",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"description": "",
"fieldname": "total_billing_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Total Billing Amount (via Time Logs)",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "total_purchase_cost",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Total Purchase Cost (via Purchase Invoice)",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "margin",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "",
"no_copy": 0,
"oldfieldtype": "Column Break",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0,
"width": "50%"
},
{
"allow_on_submit": 0,
"fieldname": "gross_margin",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Gross Margin",
"no_copy": 0,
"oldfieldname": "gross_margin_value",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break_37",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "per_gross_margin",
"fieldtype": "Percent",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Gross Margin %",
"no_copy": 0,
"oldfieldname": "per_gross_margin",
"oldfieldtype": "Currency",
"options": "",
"permlevel": 0,
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "icon-puzzle-piece",
"idx": 1,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"max_attachments": 4,
"modified": "2015-06-12 09:00:54.080220",
"modified": "2015-08-12 08:51:43.620261",
"modified_by": "Administrator",
"module": "Projects",
"name": "Project",
@@ -366,29 +831,45 @@
{
"amend": 0,
"apply_user_permissions": 1,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Projects User",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 0,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 1,
"print": 0,
"read": 1,
"report": 1,
"role": "All",
"submit": 0
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
}
],
"read_only": 0,
"read_only_onload": 0,
"search_fields": "customer, status, priority, is_active"
}

View File

@@ -25,13 +25,13 @@ class Project(Document):
"description": task.description,
"task_id": task.name
})
def __setup__(self):
self.onload()
def get_tasks(self):
return frappe.get_all("Task", "*", {"project": self.name}, order_by="exp_start_date asc")
def validate(self):
self.validate_dates()
self.sync_tasks()
@@ -74,7 +74,7 @@ class Project(Document):
for t in frappe.get_all("Task", ["name"], {"project": self.name, "name": ("not in", task_names)}):
frappe.delete_doc("Task", t.name)
task_added_or_deleted = True
if task_added_or_deleted:
self.update_project()
@@ -87,12 +87,12 @@ class Project(Document):
if total:
completed = frappe.db.sql("""select count(*) from tabTask where
project=%s and status in ('Closed', 'Cancelled')""", self.name)[0][0]
self.percent_complete = flt(completed) / total * 100
def update_costing(self):
total_cost = frappe.db.sql("""select sum(total_costing_amount) as costing_amount,
sum(total_billing_amount) as billing_amount, sum(total_expense_claim) as expense_claim,
total_cost = frappe.db.sql("""select sum(ifnull(total_costing_amount, 0)) as costing_amount,
sum(ifnull(total_billing_amount, 0)) as billing_amount, sum(ifnull(total_expense_claim, 0)) as expense_claim,
min(act_start_date) as start_date, max(act_end_date) as end_date, sum(actual_time) as time
from `tabTask` where project = %s""", self.name, as_dict=1)[0]
@@ -105,10 +105,12 @@ class Project(Document):
self.gross_margin = flt(total_cost.billing_amount) - flt(total_cost.costing_amount)
if self.total_billing_amount:
self.per_gross_margin = (self.gross_margin / flt(self.total_billing_amount)) *100
def update_purchase_costing(self):
self.total_purchase_cost = frappe.db.sql("""select sum(amount) as cost
from `tabPurchase Invoice Item` where project_name = %s and docstatus=1 """, self.name, as_dict=1)[0].cost or 0
total_purchase_cost = frappe.db.sql("""select sum(ifnull(base_net_amount, 0))
from `tabPurchase Invoice Item` where project_name = %s and docstatus=1""", self.name)
self.total_purchase_cost = total_purchase_cost and total_purchase_cost[0][0] or 0
@frappe.whitelist()
def get_cost_center_name(project_name):

View File

@@ -25,7 +25,8 @@
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
@@ -46,21 +47,48 @@
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "task_id",
"fieldname": "edit_task",
"fieldtype": "Button",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "View Task",
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break_3",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
@@ -79,7 +107,8 @@
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
@@ -99,13 +128,27 @@
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "section_break_6",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
@@ -124,17 +167,29 @@
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "task_id",
"fieldtype": "Link",
"hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Task ID",
"no_copy": 1,
"options": "Task",
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"hide_heading": 0,
@@ -144,7 +199,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-04-23 05:48:00.504508",
"modified": "2015-08-12 08:51:46.609018",
"modified_by": "Administrator",
"module": "Projects",
"name": "Project Task",

View File

@@ -6,6 +6,7 @@ import frappe, json
from frappe import _
from frappe.utils import cstr, flt, get_datetime, get_time, getdate
from dateutil.relativedelta import relativedelta
from erpnext.manufacturing.doctype.manufacturing_settings.manufacturing_settings import get_mins_between_operations
class OverlapError(frappe.ValidationError): pass
class OverProductionLoggedError(frappe.ValidationError): pass
@@ -182,9 +183,14 @@ class TimeLog(Document):
def move_to_next_non_overlapping_slot(self):
"""If in overlap, set start as the end point of the overlapping time log"""
overlapping = self.get_overlap_for("workstation")
if overlapping:
self.from_time = get_datetime(overlapping.to_time) + relativedelta(minutes=10)
overlapping = self.get_overlap_for("workstation") \
or self.get_overlap_for("employee") \
or self.get_overlap_for("user")
if not overlapping:
frappe.throw("Logical error: Must find overlapping")
self.from_time = get_datetime(overlapping.to_time) + get_mins_between_operations()
def get_time_log_summary(self):
"""Returns 'Actual Operating Time'. """

View File

@@ -15,6 +15,8 @@ class TimeLogBatch(Document):
def validate(self):
self.set_status()
self.total_hours = 0.0
self.total_billing_amount = 0.0
for d in self.get("time_logs"):
tl = frappe.get_doc("Time Log", d.time_log)
self.update_time_log_values(d, tl)

View File

@@ -11,7 +11,8 @@ $(document).bind('toolbar_setup', function() {
href="https://discuss.erpnext.com">Feedback</a></p>'
$('.navbar-home').html('<img class="erpnext-icon" src="/assets/erpnext/images/erp-icon.svg" />');
$('.navbar-home').html('<img class="erpnext-icon" src="'+
frappe.urllib.get_base_url()+'/assets/erpnext/images/erp-icon.svg" />');
$('[data-link="docs"]').attr("href", "https://manual.erpnext.com")
});

View File

@@ -13,30 +13,8 @@ erpnext.stock.StockController = frappe.ui.form.Controller.extend({
setup_warehouse_query: function() {
var me = this;
var warehouse_query_method = function() {
erpnext.queries.setup_queries(this.frm, "Warehouse", function() {
return erpnext.queries.warehouse(me.frm.doc);
};
var _set_warehouse_query = function(doctype, parentfield) {
var warehouse_link_fields = frappe.meta.get_docfields(doctype, me.frm.doc.name,
{"fieldtype": "Link", "options": "Warehouse"});
$.each(warehouse_link_fields, function(i, df) {
if(parentfield) {
me.frm.set_query(df.fieldname, parentfield, warehouse_query_method);
} else {
me.frm.set_query(df.fieldname, warehouse_query_method);
}
});
};
_set_warehouse_query(me.frm.doc.doctype);
// warehouse field in tables
var table_fields = frappe.meta.get_docfields(me.frm.doc.doctype, me.frm.doc.name,
{"fieldtype": "Table"});
$.each(table_fields, function(i, df) {
_set_warehouse_query(df.options, df.fieldname);
});
},

View File

@@ -256,7 +256,8 @@ erpnext.taxes_and_totals = erpnext.stock.StockController.extend({
me.round_off_totals(tax);
// adjust Discount Amount loss in last tax iteration
if ((i == me.frm.doc["taxes"].length - 1) && me.discount_amount_applied && me.frm.doc.apply_discount_on == "Grand Total")
if ((i == me.frm.doc["taxes"].length - 1) && me.discount_amount_applied
&& me.frm.doc.apply_discount_on == "Grand Total" && me.frm.doc.discount_amount)
me.adjust_discount_amount_loss(tax);
}
});
@@ -365,9 +366,9 @@ erpnext.taxes_and_totals = erpnext.stock.StockController.extend({
$.each(this.frm.doc["taxes"] || [], function(i, tax) {
if (in_list(["Valuation and Total", "Total"], tax.category)) {
if(tax.add_deduct_tax == "Add") {
me.frm.doc.taxes_and_charges_added += flt(tax.tax_amount);
me.frm.doc.taxes_and_charges_added += flt(tax.tax_amount_after_discount_amount);
} else {
me.frm.doc.taxes_and_charges_deducted += flt(tax.tax_amount);
me.frm.doc.taxes_and_charges_deducted += flt(tax.tax_amount_after_discount_amount);
}
}
})

View File

@@ -36,7 +36,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
if(this.frm.fields_dict["items"]) {
this["items_remove"] = this.calculate_taxes_and_totals;
}
if(this.frm.fields_dict["recurring_print_format"]) {
this.frm.set_query("recurring_print_format", function(doc) {
return{
@@ -46,7 +46,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
}
});
}
if(this.frm.fields_dict["return_against"]) {
this.frm.set_query("return_against", function(doc) {
var filters = {
@@ -56,13 +56,13 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
};
if (me.frm.fields_dict["customer"] && doc.customer) filters["customer"] = doc.customer;
if (me.frm.fields_dict["supplier"] && doc.supplier) filters["supplier"] = doc.supplier;
return {
filters: filters
}
});
}
},
onload_post_render: function() {
@@ -218,7 +218,9 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
item.serial_no += sr_no[x] + '\n';
refresh_field("serial_no", item.name, item.parentfield);
frappe.model.set_value(item.doctype, item.name, "qty", sr_no.length);
if(!doc.is_return) {
frappe.model.set_value(item.doctype, item.name, "qty", sr_no.length);
}
}
}
},
@@ -273,7 +275,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
posting_date: function() {
var me = this;
if (this.frm.doc.posting_date) {
if ((this.frm.doc.doctype == "Sales Invoice" && this.frm.doc.customer) ||
if ((this.frm.doc.doctype == "Sales Invoice" && this.frm.doc.customer) ||
(this.frm.doc.doctype == "Purchase Invoice" && this.frm.doc.supplier)) {
return frappe.call({
method: "erpnext.accounts.party.get_due_date",
@@ -282,7 +284,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
"party_type": me.frm.doc.doctype == "Sales Invoice" ? "Customer" : "Supplier",
"party": me.frm.doc.doctype == "Sales Invoice" ? me.frm.doc.customer : me.frm.doc.supplier,
"company": me.frm.doc.company
},
},
callback: function(r, rt) {
if(r.message) {
me.frm.set_value("due_date", r.message);
@@ -299,7 +301,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
get_company_currency: function() {
return erpnext.get_currency(this.frm.doc.company);
},
contact_person: function() {
erpnext.utils.get_contact_details(this.frm);
},
@@ -371,7 +373,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
plc_conversion_rate: function() {
if(this.frm.doc.price_list_currency === this.get_company_currency()) {
this.frm.set_value("plc_conversion_rate", 1.0);
} else if(this.frm.doc.price_list_currency === this.frm.doc.currency
} else if(this.frm.doc.price_list_currency === this.frm.doc.currency
&& this.frm.doc.plc_conversion_rate && cint(this.frm.doc.plc_conversion_rate) != 1 &&
cint(this.frm.doc.plc_conversion_rate) != cint(this.frm.doc.conversion_rate)) {
this.frm.set_value("conversion_rate", this.frm.doc.plc_conversion_rate);

View File

@@ -182,6 +182,9 @@ erpnext.pos.PointOfSale = Class.extend({
child.serial_no = serial_no;
this.frm.script_manager.trigger("item_code", child.doctype, child.name);
frappe.after_ajax(function() {
me.frm.script_manager.trigger("qty", child.doctype, child.name);
})
},
refresh_search_box: function() {
var me = this;
@@ -432,7 +435,7 @@ erpnext.pos.PointOfSale = Class.extend({
}
},
{fieldtype:'Currency', fieldname:'write_off_amount',
label: __('Write Off'), default: 0.0, hidden: 1},
label: __('Write Off'), "default": 0.0, hidden: 1},
]
});
me.dialog = dialog;
@@ -470,6 +473,8 @@ erpnext.pos.PointOfSale = Class.extend({
}
me.frm.set_value("mode_of_payment", values.mode_of_payment);
//me.frm.cscript.calculate_taxes_and_totals();
var paid_amount = flt((flt(values.paid_amount) - flt(values.change)) / me.frm.doc.conversion_rate, precision("paid_amount"));
me.frm.set_value("paid_amount", paid_amount);
@@ -479,7 +484,6 @@ erpnext.pos.PointOfSale = Class.extend({
me.frm.savesubmit(this);
dialog.hide();
me.refresh();
})
}

View File

@@ -75,3 +75,26 @@ $.extend(erpnext.queries, {
}
}
});
erpnext.queries.setup_queries = function(frm, options, query_fn) {
var me = this;
var set_query = function(doctype, parentfield) {
var link_fields = frappe.meta.get_docfields(doctype, frm.doc.name,
{"fieldtype": "Link", "options": options});
$.each(link_fields, function(i, df) {
if(parentfield) {
frm.set_query(df.fieldname, parentfield, query_fn);
} else {
frm.set_query(df.fieldname, query_fn);
}
});
};
set_query(frm.doc.doctype);
// warehouse field in tables
$.each(frappe.meta.get_docfields(frm.doc.doctype, frm.doc.name, {"fieldtype": "Table"}),
function(i, df) {
set_query(df.options, df.fieldname);
});
}

View File

@@ -83,7 +83,7 @@ $.extend(erpnext, {
return {
filters: {
item_code:grid_row.doc.item_code ,
warehouse:grid_row.doc.warehouse
warehouse:cur_frm.doc.is_return ? null : grid_row.doc.warehouse
}
}
}

View File

@@ -46,6 +46,7 @@ cur_frm.cscript.setup_dashboard = function(doc) {
cur_frm.dashboard.add_doctype_badge("Sales Order", "customer");
cur_frm.dashboard.add_doctype_badge("Delivery Note", "customer");
cur_frm.dashboard.add_doctype_badge("Sales Invoice", "customer");
cur_frm.dashboard.add_doctype_badge("Project", "customer");
return frappe.call({
type: "GET",
@@ -62,6 +63,8 @@ cur_frm.cscript.setup_dashboard = function(doc) {
+ '</b> / <span class="text-muted">' + __("Unpaid") + ": <b>"
+ format_currency(r.message.total_unpaid, r.message["company_currency"][0])
+ '</b></span>');
} else {
cur_frm.dashboard.set_headline("");
}
}
cur_frm.dashboard.set_badge_count(r.message);

View File

@@ -1,35 +1,62 @@
{
"allow_copy": 0,
"allow_import": 1,
"allow_rename": 1,
"autoname": "naming_series:",
"creation": "2013-06-11 14:26:44",
"custom": 0,
"description": "Buyer of Goods and Services.",
"docstatus": 0,
"doctype": "DocType",
"document_type": "Master",
"fields": [
{
"allow_on_submit": 0,
"fieldname": "basic_info",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "",
"no_copy": 0,
"oldfieldtype": "Section Break",
"options": "icon-user",
"permlevel": 0,
"reqd": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "naming_series",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Series",
"no_copy": 1,
"options": "CUST-",
"permlevel": 0,
"print_hide": 0
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "customer_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "Full Name",
@@ -38,25 +65,43 @@
"oldfieldtype": "Data",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 1
"search_index": 1,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "customer_type",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Type",
"no_copy": 0,
"oldfieldname": "customer_type",
"oldfieldtype": "Select",
"options": "\nCompany\nIndividual",
"permlevel": 0,
"reqd": 1
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "lead_name",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "From Lead",
"no_copy": 1,
"oldfieldname": "lead_name",
@@ -64,228 +109,580 @@
"options": "Lead",
"permlevel": 0,
"print_hide": 1,
"report_hide": 1
"read_only": 0,
"report_hide": 1,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break0",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0,
"width": "50%"
},
{
"allow_on_submit": 0,
"description": "",
"fieldname": "customer_group",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 1,
"label": "Customer Group",
"no_copy": 0,
"oldfieldname": "customer_group",
"oldfieldtype": "Link",
"options": "Customer Group",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 1
"search_index": 1,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"description": "",
"fieldname": "territory",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Territory",
"no_copy": 0,
"oldfieldname": "territory",
"oldfieldtype": "Link",
"options": "Territory",
"permlevel": 0,
"print_hide": 1,
"reqd": 1
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "tax_id",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Tax ID",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "is_frozen",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Is Frozen",
"no_copy": 0,
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "eval:!doc.__islocal",
"fieldname": "address_contacts",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "",
"no_copy": 0,
"options": "icon-map-marker",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "address_html",
"fieldtype": "HTML",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Address HTML",
"no_copy": 0,
"permlevel": 0,
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break1",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0,
"width": "50%"
},
{
"allow_on_submit": 0,
"fieldname": "contact_html",
"fieldtype": "HTML",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Contact HTML",
"no_copy": 0,
"oldfieldtype": "HTML",
"permlevel": 0,
"read_only": 1
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "default_receivable_accounts",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Default Receivable Accounts",
"permlevel": 0
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "eval:!doc.__islocal",
"description": "Mention if non-standard receivable account applicable",
"fieldname": "accounts",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Accounts",
"no_copy": 0,
"options": "Party Account",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "more_info",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "",
"no_copy": 0,
"oldfieldtype": "Section Break",
"options": "icon-file-text",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break2",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0,
"width": "50%"
},
{
"description": "Your Customer's TAX registration numbers (if applicable) or any general information",
"allow_on_submit": 0,
"description": "Additional information regarding the customer.",
"fieldname": "customer_details",
"fieldtype": "Text",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Customer Details",
"no_copy": 0,
"oldfieldname": "customer_details",
"oldfieldtype": "Code",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "column_break3",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0,
"width": "50%"
},
{
"allow_on_submit": 0,
"fieldname": "default_currency",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 1,
"in_filter": 0,
"in_list_view": 0,
"label": "Currency",
"no_copy": 1,
"options": "Currency",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "default_price_list",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 1,
"in_filter": 0,
"in_list_view": 0,
"label": "Price List",
"no_copy": 0,
"options": "Price List",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "default_taxes_and_charges",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 1,
"in_filter": 0,
"in_list_view": 0,
"label": "Taxes and Charges",
"no_copy": 0,
"options": "Sales Taxes and Charges Template",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "credit_days_based_on",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Credit Days Based On",
"no_copy": 0,
"options": "\nFixed Days\nLast Day of the Next Month",
"permlevel": 0,
"precision": ""
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"depends_on": "eval:doc.credit_days_based_on=='Fixed Days'",
"fieldname": "credit_days",
"fieldtype": "Int",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Credit Days",
"no_copy": 0,
"oldfieldname": "credit_days",
"oldfieldtype": "Int",
"permlevel": 1
"permlevel": 1,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "credit_limit",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Credit Limit",
"no_copy": 0,
"oldfieldname": "credit_limit",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 1
"permlevel": 1,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "website",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Website",
"permlevel": 0
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "sales_team_section_break",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "",
"no_copy": 0,
"oldfieldtype": "Section Break",
"options": "icon-group",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "default_sales_partner",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 1,
"in_filter": 0,
"in_list_view": 0,
"label": "Sales Partner",
"no_copy": 0,
"oldfieldname": "default_sales_partner",
"oldfieldtype": "Link",
"options": "Sales Partner",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "default_commission_rate",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Commission Rate",
"no_copy": 0,
"oldfieldname": "default_commission_rate",
"oldfieldtype": "Currency",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "sales_team",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Sales Team Details",
"no_copy": 0,
"oldfieldname": "sales_team",
"oldfieldtype": "Table",
"options": "Sales Team",
"permlevel": 0
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "communications",
"fieldtype": "Table",
"hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Communications",
"no_copy": 0,
"options": "Communication",
"permlevel": 0,
"print_hide": 1
"print_hide": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "icon-user",
"idx": 1,
"modified": "2015-07-17 09:38:50.086978",
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-08-07 20:34:25.761769",
"modified_by": "Administrator",
"module": "Selling",
"name": "Customer",
@@ -294,38 +691,73 @@
{
"amend": 0,
"apply_user_permissions": 1,
"cancel": 0,
"create": 1,
"delete": 0,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales User",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 0,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 1,
"print": 0,
"read": 1,
"role": "Sales User"
"report": 0,
"role": "Sales User",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales Manager"
"role": "Sales Manager",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
@@ -337,46 +769,108 @@
"write": 1
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 0,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 1,
"print": 0,
"read": 1,
"report": 0,
"role": "Sales Master Manager",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 1
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Stock User"
"role": "Stock User",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Stock Manager"
"role": "Stock Manager",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts User"
"role": "Accounts User",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager"
"role": "Accounts Manager",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
}
],
"read_only": 0,
"read_only_onload": 0,
"search_fields": "customer_name,customer_group,territory",
"title_field": "customer_name"
}

View File

@@ -119,7 +119,8 @@ def get_dashboard_info(customer):
frappe.msgprint(_("Not permitted"), raise_exception=True)
out = {}
for doctype in ["Opportunity", "Quotation", "Sales Order", "Delivery Note", "Sales Invoice"]:
for doctype in ["Opportunity", "Quotation", "Sales Order", "Delivery Note",
"Sales Invoice", "Project"]:
out[doctype] = frappe.db.get_value(doctype,
{"customer": customer, "docstatus": ["!=", 2] }, "count(*)")

View File

@@ -1,21 +1,41 @@
{
"allow_copy": 0,
"allow_import": 1,
"allow_rename": 0,
"creation": "2013-06-20 11:53:21",
"custom": 0,
"description": "Aggregate group of **Items** into another **Item**. This is useful if you are bundling a certain **Items** into a package and you maintain stock of the packed **Items** and not the aggregate **Item**. \n\nThe package **Item** will have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\".\n\nFor Example: If you are selling Laptops and Backpacks separately and have a special price if the customer buys both, then the Laptop + Backpack will be a new Product Bundle Item.\n\nNote: BOM = Bill of Materials",
"docstatus": 0,
"doctype": "DocType",
"document_type": "Master",
"document_type": "",
"fields": [
{
"allow_on_submit": 0,
"fieldname": "basic_section",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "",
"permlevel": 0
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"description": "The Item that represents the Package. This Item must have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\"",
"allow_on_submit": 0,
"description": "",
"fieldname": "new_item_code",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Parent Item",
"no_copy": 1,
@@ -23,30 +43,67 @@
"oldfieldtype": "Data",
"options": "Item",
"permlevel": 0,
"reqd": 1
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"description": "List items that form the package.",
"fieldname": "item_section",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "",
"permlevel": 0
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"fieldname": "items",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Items",
"no_copy": 0,
"oldfieldname": "sales_bom_items",
"oldfieldtype": "Table",
"options": "Product Bundle Item",
"permlevel": 0,
"reqd": 1
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "icon-sitemap",
"idx": 1,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"modified": "2015-07-13 05:28:28.140327",
"issingle": 0,
"istable": 0,
"modified": "2015-08-03 11:23:26.263254",
"modified_by": "Administrator",
"module": "Selling",
"name": "Product Bundle",
@@ -54,14 +111,20 @@
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Stock Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
@@ -69,31 +132,44 @@
{
"amend": 0,
"apply_user_permissions": 1,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Stock User",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
},
{
"amend": 0,
"apply_user_permissions": 1,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales User",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
}
]
],
"read_only": 0,
"read_only_onload": 0
}

View File

@@ -14,15 +14,13 @@ class ProductBundle(Document):
def validate(self):
self.validate_main_item()
from erpnext.utilities.transaction_base import validate_uom_is_integer
validate_uom_is_integer(self, "uom", "qty")
def validate_main_item(self):
"""main item must have Is Stock Item as No and Is Sales Item as Yes"""
if not frappe.db.sql("""select name from tabItem where name=%s and
is_stock_item = 0 and is_sales_item = 1""", self.new_item_code):
frappe.throw(_("Parent Item {0} must be not Stock Item and must be a Sales Item").format(self.new_item_code))
"""Validates, main Item is not a stock item"""
if frappe.db.get_value("Item", self.new_item_code, "is_stock_item"):
frappe.throw(_("Parent Item {0} must not be a Stock Item").format(self.new_item_code))
def get_item_details(self, name):
det = frappe.db.sql("""select description, stock_uom from `tabItem`
@@ -36,8 +34,7 @@ def get_new_item_code(doctype, txt, searchfield, start, page_len, filters):
from erpnext.controllers.queries import get_match_cond
return frappe.db.sql("""select name, item_name, description from tabItem
where is_stock_item=0 and is_sales_item=1
and name not in (select name from `tabProduct Bundle`) and %s like %s
%s limit %s, %s""" % (searchfield, "%s",
where is_stock_item=0 and name not in (select name from `tabProduct Bundle`)
and %s like %s %s limit %s, %s""" % (searchfield, "%s",
get_match_cond(doctype),"%s", "%s"),
("%%%s%%" % txt, start, page_len))

View File

@@ -5,4 +5,20 @@ from __future__ import unicode_literals
import frappe
test_records = frappe.get_test_records('Product Bundle')
test_records = frappe.get_test_records('Product Bundle')
def make_product_bundle(parent, items):
if frappe.db.exists("Product Bundle", parent):
return frappe.get_doc("Product Bundle", parent)
product_bundle = frappe.get_doc({
"doctype": "Product Bundle",
"new_item_code": parent
})
for item in items:
product_bundle.append("items", {"item_code": item, "qty": 1})
product_bundle.insert()
return product_bundle

View File

@@ -3,6 +3,14 @@
{% include 'selling/sales_common.js' %}
frappe.ui.form.on("Sales Order", {
onload: function(frm) {
erpnext.queries.setup_queries(frm, "Warehouse", function() {
return erpnext.queries.warehouse(frm.doc);
});
}
});
erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend({
refresh: function(doc, dt, dn) {
this._super();
@@ -16,29 +24,32 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
// cur_frm.dashboard.add_progress(cint(doc.per_billed) + __("% Billed"),
// doc.per_billed);
// delivery note
if(flt(doc.per_delivered, 2) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1)
cur_frm.add_custom_button(__('Make Delivery'), this.make_delivery_note);
// indent
if(!doc.order_type || ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1)
cur_frm.add_custom_button(__('Make ') + __('Material Request'),
this.make_material_request);
cur_frm.add_custom_button(__('Material Request'), this.make_material_request);
// sales invoice
if(flt(doc.per_billed, 2) < 100) {
cur_frm.add_custom_button(__('Make Invoice'), this.make_sales_invoice);
if(flt(doc.per_billed)==0) {
cur_frm.add_custom_button(__('Payment'), cur_frm.cscript.make_bank_entry);
}
// stop
if(flt(doc.per_delivered, 2) < 100 || doc.per_billed < 100)
cur_frm.add_custom_button(__('Stop'), cur_frm.cscript['Stop Sales Order'])
// maintenance
if(flt(doc.per_delivered, 2) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)===-1) {
cur_frm.add_custom_button(__('Make Maint. Visit'), this.make_maintenance_visit);
cur_frm.add_custom_button(__('Make Maint. Schedule'), this.make_maintenance_schedule);
}
// maintenance
if(flt(doc.per_delivered, 2) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)===-1) {
cur_frm.add_custom_button(__('Maint. Visit'), this.make_maintenance_visit);
cur_frm.add_custom_button(__('Maint. Schedule'), this.make_maintenance_schedule);
}
// delivery note
if(flt(doc.per_delivered, 2) < 100 && ["Sales", "Shopping Cart"].indexOf(doc.order_type)!==-1)
cur_frm.add_custom_button(__('Delivery'), this.make_delivery_note).addClass("btn-primary");
// sales invoice
if(flt(doc.per_billed, 2) < 100) {
cur_frm.add_custom_button(__('Invoice'), this.make_sales_invoice).addClass("btn-primary");
}
} else {
// un-stop
@@ -122,6 +133,20 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
frm: cur_frm
})
},
make_bank_entry: function() {
return frappe.call({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_payment_entry_from_sales_order",
args: {
"sales_order": cur_frm.doc.name
},
callback: function(r) {
var doclist = frappe.model.sync(r.message);
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
}
});
}
});
// for backward compatibility: combine new and previous states

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