Compare commits

...

214 Commits

Author SHA1 Message Date
Nabin Hait
3631e9cbe0 Merge branch 'develop' 2015-07-16 17:15:41 +05:30
Nabin Hait
1c9a7d2a1b bumped to version 5.2.0 2015-07-16 17:45:40 +06:00
Anand Doshi
972f2f9194 [change-log] 2015-07-16 16:19:30 +05:30
Anand Doshi
239296d16a Merge pull request #3657 from nabinhait/fix4
Reserved warehouse should not be validated on cancellation of sales order
2015-07-16 15:57:59 +05:30
Anand Doshi
3210db9056 Merge pull request #3656 from rmehta/sms-log
[fix] create SMS Log
2015-07-16 15:56:08 +05:30
Anand Doshi
f6954fb798 Merge pull request #3663 from neilLasrado/bom
Bom
2015-07-16 15:02:40 +05:30
Anand Doshi
c6656e68b8 Merge pull request #3666 from nabinhait/patch-fix
[patch][fix] Sales BOM should be renamed before rename_table_fields patch
2015-07-16 14:55:35 +05:30
Anand Doshi
a39387d352 Merge pull request #3664 from rmehta/develop
[cleanup] removed welcome emails
2015-07-16 14:25:24 +05:30
Rushabh Mehta
f3791797d6 [fix] [patch] 2015-07-16 14:17:59 +05:30
Rushabh Mehta
ea4d63cef3 [cleanup] removed welcome emails 2015-07-16 14:17:59 +05:30
Nabin Hait
5464ca8a73 [patch][fix] Sales BOM should be renamed before rename_table_fields patch 2015-07-16 12:19:57 +05:30
Rushabh Mehta
6c6875f503 [cleanup] removed welcome emails 2015-07-16 11:53:18 +05:30
Neil Trini Lasrado
20523c45c7 Patch for default BOM 2015-07-16 11:27:06 +05:30
Neil Trini Lasrado
0248811e53 Fixed deafault BOM problem 2015-07-16 11:26:40 +05:30
Rushabh Mehta
93416ee72c Update sponsors.md 2015-07-15 16:42:46 +05:30
Rushabh Mehta
51e7086a08 [patch] rename roles 2015-07-15 16:30:49 +05:30
Anand Doshi
5e849ae53e [help] added new links to Learn 2015-07-15 15:23:02 +05:30
Rushabh Mehta
de0db0d000 Merge pull request #3658 from anandpdoshi/anand-july-15
[fix] Mozilla hack for images in table for print
2015-07-15 12:58:19 +05:30
Anand Doshi
f3a67c4533 [fix] Mozilla hack for images in table for print 2015-07-15 12:37:45 +05:30
Nabin Hait
0847f9a074 Reserved warehouse should not be validated on cancellation of sales order 2015-07-14 18:23:05 +05:30
Anand Doshi
9490c21b8a Merge pull request #3641 from rmehta/role-rename
[rename] Material User > Stock User
2015-07-14 12:10:48 +05:30
Rushabh Mehta
bdb71bca4e [perm] added stock, project user for company 2015-07-14 11:54:42 +05:30
Anand Doshi
e8861e2871 Merge pull request #3649 from rmehta/purchase-invoice-fix
[fix] supplier invoice number fix
2015-07-14 11:50:07 +05:30
Anand Doshi
b084b5e449 Merge pull request #3651 from rmehta/pos-default-pay-fix
[fix] pos default payment #3631
2015-07-14 11:49:46 +05:30
Anand Doshi
41d3e57702 Merge pull request #3650 from rmehta/time-log-fix-2
[fix] overlap fix in time log #3647
2015-07-14 11:45:49 +05:30
Anand Doshi
9df2899f72 Merge pull request #3648 from rmehta/time-log-fix
[fixes] hours in time-log #3644, project buttons on condition, removed Guest permission in notification_control
2015-07-14 11:25:46 +05:30
Rushabh Mehta
dacf127f1b [fix] time log overlap condition, #SavedByATestCase 2015-07-14 11:06:28 +05:30
Rushabh Mehta
2b49f9b30a [fix] pos default payment #3631 2015-07-14 11:01:42 +05:30
Rushabh Mehta
533434e878 [fix] overlap fix in time log #3647 2015-07-14 10:39:33 +05:30
Rushabh Mehta
1956028ddc [fix] supplier invoice number fix 2015-07-14 10:26:50 +05:30
Rushabh Mehta
a87dc3b4e6 [minor] move position in accounts settings 2015-07-14 10:22:07 +05:30
Rushabh Mehta
97b3f750c9 [fixes] hours in time-log #3644, project buttons on condition, removed Guest permission in notification_control 2015-07-14 10:14:48 +05:30
Anand Doshi
c41b63eff1 Merge pull request #3642 from anandpdoshi/anand-july-13
Fixes to Cart
2015-07-13 16:56:37 +05:30
Anand Doshi
e6f7ac961f [fix] Add to Cart visibility, Customer's Price List in Shopping Cart and Address creation from Shopping Cart 2015-07-13 16:24:37 +05:30
Rushabh Mehta
cf26964deb Merge pull request #3640 from anandpdoshi/anand-july-13
Fixes to Issues
2015-07-13 15:37:11 +05:30
Rushabh Mehta
94157334a7 [rename] Material User > Stock User 2015-07-13 15:06:12 +05:30
Anand Doshi
c530161de0 [fix] Item image urls can now have paranthesis 2015-07-13 15:05:39 +05:30
Nabin Hait
2212ae12d8 Merge branch 'develop' 2015-07-13 14:26:23 +05:30
Nabin Hait
54ade0d26c bumped to version 5.1.6 2015-07-13 14:56:23 +06:00
Nabin Hait
f043760526 Merge pull request #3639 from neilLasrado/develop
Sales BOM to Product Bundle rename changes
2015-07-13 14:22:10 +05:30
Neil Trini Lasrado
1cd049d824 Sales BOM to Product Bundle rename changes 2015-07-13 14:17:42 +05:30
Nabin Hait
0a45260ed9 Merge branch 'develop' 2015-07-13 13:09:05 +05:30
Nabin Hait
1540ad12f9 bumped to version 5.1.5 2015-07-13 13:39:05 +06:00
Nabin Hait
76bd015b2c Merge pull request #3637 from rmehta/time-log-filter
[minor] [enhancement] added employee filter in timelog #3607
2015-07-13 13:04:03 +05:30
Rushabh Mehta
5054a3955b Update CONTRIBUTING.md 2015-07-13 12:54:08 +05:30
Nabin Hait
1a0713e4b9 Merge pull request #3584 from neilLasrado/develop
Minor fixes
2015-07-13 12:49:46 +05:30
Rushabh Mehta
e9604d8484 [minor] [enhancement] added employee filter in timelog #3607 2015-07-13 12:47:45 +05:30
Neil Trini Lasrado
008d1a0334 Fixes in Stock Entry 2015-07-13 12:41:28 +05:30
Neil Trini Lasrado
fe2ffaeafa Fixes in Production Planning Tool 2015-07-13 12:41:28 +05:30
Neil Trini Lasrado
dcef448f1e Planned Start Date added to Production Planning Tool 2015-07-13 12:41:28 +05:30
Neil Trini Lasrado
6224cfc414 Manage Variants added in Tools under Stock Module 2015-07-13 12:41:28 +05:30
Neil Trini Lasrado
700434ff37 has_variants made 'no copy' in Item Master 2015-07-13 12:41:28 +05:30
Neil Trini Lasrado
4089b3d376 Salary Slip renamed to Process Payroll 2015-07-13 12:41:28 +05:30
Neil Trini Lasrado
6cfab43d5f Renamed Depends on LWP field in the Earning and Deduction table of Salary Slip. 2015-07-13 12:41:27 +05:30
Neil Trini Lasrado
09a66c4201 Fixed issue with Customer Contacts in Transaction Documents 2015-07-13 12:41:27 +05:30
Neil Trini Lasrado
ed8cecbdd8 Sales BOM renamed to Product Bundle 2015-07-13 12:41:27 +05:30
Neil Trini Lasrado
c70109d0c5 Item table made mandatory in Stock Reconciliation 2015-07-13 12:40:57 +05:30
Neil Trini Lasrado
ccf8c337f7 Expected Delivery date validation changed to message 2015-07-13 12:40:57 +05:30
Nabin Hait
6809b4d86c Merge pull request #3636 from neilLasrado/po
Patch for Production Order Track Operation
2015-07-13 12:38:45 +05:30
Neil Trini Lasrado
cc08c68153 Patch for Production Order Track Operation 2015-07-13 12:35:20 +05:30
Nabin Hait
7daa7900ea Merge pull request #3614 from neilLasrado/po
Track Operations added to Production Order
2015-07-13 12:29:45 +05:30
Nabin Hait
7641f3fe53 Merge pull request #3635 from nabinhait/fix3
Reserved warehouse should not be validated on cancellation of sales order
2015-07-13 12:28:49 +05:30
Nabin Hait
fe2f51bbbc Merge pull request #3628 from nabinhait/sponsors
Change log and Sponsors page
2015-07-13 12:27:30 +05:30
Neil Trini Lasrado
4f33249e1c Fixes in Production Order 2015-07-13 12:26:33 +05:30
Nabin Hait
b95b606f25 sponsors page and change log 2015-07-13 12:26:24 +05:30
Nabin Hait
e690f245f2 Change log and Sponsors page 2015-07-13 12:26:24 +05:30
Neil Trini Lasrado
5da4d857c9 Track Operations added to Production Order 2015-07-13 12:01:57 +05:30
Nabin Hait
6e38e917eb Reserved warehouse should not be validated on cancellation of sales order 2015-07-13 11:36:36 +05:30
Rushabh Mehta
f3b0b95b15 [fix] [filter] for general ledger 2015-07-13 10:24:25 +05:30
Nabin Hait
7b0f1ffb2d Merge pull request #3627 from nabinhait/fix2
PP Tool: Create production order if applicable for item
2015-07-10 17:32:16 +05:30
Nabin Hait
97bb6bbaf4 Merge pull request #3621 from neilLasrado/batch
Validation added to prevent adding items with expired batch numbers t…
2015-07-10 17:31:52 +05:30
Neil Trini Lasrado
cb4b2ec52a Fixes in validate baatch function 2015-07-10 17:31:06 +05:30
Nabin Hait
f18bbcef86 PP Tool: Create production order if applicable for item 2015-07-10 17:31:03 +05:30
Nabin Hait
27976382d8 Merge pull request #3626 from nabinhait/credit_days
minor fix in due date validation
2015-07-10 17:13:15 +05:30
Nabin Hait
93d3c82737 minor fix in due date validation 2015-07-10 17:12:08 +05:30
Neil Trini Lasrado
03bf529622 Validation added to prevent adding items with expired batch numbers to stock ledger entry 2015-07-10 16:20:21 +05:30
Nabin Hait
6c4085fc0c Merge pull request #3616 from nabinhait/credit_days
Customer's credit days based on fixed days / last day of the next month
2015-07-10 16:16:14 +05:30
Nabin Hait
c37484c8da Merge pull request #3622 from rmehta/minor-fixes
[fix] cart and general leger report
2015-07-10 16:12:01 +05:30
Rushabh Mehta
b4ec294463 Merge pull request #3625 from neilLasrado/task
Validation added to prevent task being closed with open dependent tasks
2015-07-10 14:30:46 +05:30
Neil Trini Lasrado
58406a920c Validation added to prevent task being closed with open dependent tasks 2015-07-10 12:57:49 +05:30
Rushabh Mehta
98311f4394 Merge pull request #3624 from pdvyas/lang
Fix lang code for česky and update translations
2015-07-10 12:37:31 +05:30
Pratik Vyas
53829707ad Fix lang code for česky 2015-07-10 12:05:53 +05:30
Pratik Vyas
fcc31028c6 Update translations 2015-07-10 12:05:24 +05:30
Rushabh Mehta
fc3d87181a [fix] cart and general leger report 2015-07-10 10:11:07 +05:30
Nabin Hait
6336ff7323 minor fixes 2015-07-09 19:48:21 +05:30
Nabin Hait
fde13e666a Merge pull request #3609 from rmehta/address-link
[fix] link address via owner, if created in portal #3540
2015-07-09 19:09:39 +05:30
Nabin Hait
f80c09290e Merge pull request #3610 from nabinhait/variants
Adding rows not allowed in Variant table in Manage Variants and Item
2015-07-09 19:07:56 +05:30
Nabin Hait
b797963bd8 Merge pull request #3618 from neilLasrado/naming
Validation added in Production Order
2015-07-09 18:53:39 +05:30
Nabin Hait
03b42a7934 Merge pull request #3619 from neilLasrado/contact
Allowed same contact to be Linked to Customer AND Supplier AND Sales …
2015-07-09 18:52:22 +05:30
Nabin Hait
7e9ff99a6c Merge pull request #3620 from nabinhait/currency_symbol
Currency symbol fixed in sales invoice outstanding and advance amount
2015-07-09 18:51:38 +05:30
Nabin Hait
5cbe3441e8 Reload doctype in patch 2015-07-09 18:42:15 +05:30
Nabin Hait
0724449d0e [patch] Set 'Credit days based on' in existing customer, customer group and company 2015-07-09 17:49:50 +05:30
Neil Trini Lasrado
5a6ff218e8 Allowed same contact to be Linked to Customer AND Supplier AND Sales Partner 2015-07-09 17:49:40 +05:30
Nabin Hait
122e4e0a96 Currency symbol fixed in sales invoice outstanding and advance amount 2015-07-09 17:36:58 +05:30
Neil Trini Lasrado
e233f0e2ff Validation added in Production Order to prevent PO against Item Template or if Allow PO is No in Item Master 2015-07-09 17:35:51 +05:30
Nabin Hait
40e92b679b Posting date trigger function commonified 2015-07-09 17:12:23 +05:30
Nabin Hait
4770a1abb5 Customer's credit days based on fixed days / last day of the next month 2015-07-09 16:35:53 +05:30
Rushabh Mehta
ccb9117ba5 [minor] Added employees in Newsletter List 2015-07-09 13:56:02 +05:30
Nabin Hait
db938762c7 [fix] Adding rows not allowed in Variant table in Manage Variants and Item form 2015-07-09 11:55:38 +05:30
Nabin Hait
0910fc3b25 Merge pull request #3605 from nabinhait/testcases
Test case fixed
2015-07-09 11:28:36 +05:30
Rushabh Mehta
f0737667c6 [fix] link address via owner, if created in portal #3540 2015-07-09 11:09:01 +05:30
Nabin Hait
2d83122c6b removed client side test cases 2015-07-08 18:02:42 +05:30
Nabin Hait
e2b7f832cc Test case fixed 2015-07-08 17:56:06 +05:30
Nabin Hait
6a6958db5c Merge branch 'develop' 2015-07-08 16:53:55 +05:30
Nabin Hait
ab1acb460b bumped to version 5.1.4 2015-07-08 17:23:55 +06:00
Nabin Hait
48d71fa7f7 Merge pull request #3602 from nabinhait/develop
Change log
2015-07-08 16:47:14 +05:30
Nabin Hait
30960e6a06 Change log added 2015-07-08 16:46:28 +05:30
Nabin Hait
736000c223 Merge pull request #3600 from neilLasrado/batch
Fixed issues in Expired Batches while making Stock Entry
2015-07-08 16:10:21 +05:30
Nabin Hait
4017bfcd2e Merge pull request #3591 from rmehta/salary-manager-fix
[fixes] salary manager #3554
2015-07-08 15:39:33 +05:30
Nabin Hait
e594e5de49 Merge pull request #3596 from neilLasrado/pos
Mode of Payment added to POS Profile
2015-07-08 15:36:30 +05:30
Nabin Hait
1f1f14be39 Merge pull request #3599 from nabinhait/develop
Multiple fixes
2015-07-08 15:33:57 +05:30
Neil Trini Lasrado
ebb60f5dbc Fixed issues in Expired Batches while making Stock Entry 2015-07-08 15:24:02 +05:30
Neil Trini Lasrado
75b00e3958 Mode of Payment added to POS Profile 2015-07-08 14:43:47 +05:30
Nabin Hait
5e3646ad6e validation message fix 2015-07-08 14:39:03 +05:30
Nabin Hait
4439d8264f minor fix 2015-07-08 14:32:56 +05:30
Nabin Hait
00d79eb68d minor fix 2015-07-08 14:32:27 +05:30
Nabin Hait
28a9e35de9 Validate item rate with reference document with tolerance 0.009 2015-07-08 13:10:59 +05:30
Nabin Hait
c450536a2c [fix] Map values in Debit / Credit Note from Stock Entry 2015-07-08 13:10:59 +05:30
Nabin Hait
3b3c48c877 [fix] Set Customer name in opportunity as per company name in lead 2015-07-08 13:10:59 +05:30
Rushabh Mehta
621d6eac3c [minor] added calendar hooks 2015-07-08 12:39:27 +05:30
Rushabh Mehta
f9b356992a [fixes] salary manager #3554 2015-07-07 16:30:29 +05:30
Nabin Hait
c516e1871d Merge branch 'develop' 2015-07-06 15:32:32 +05:30
Nabin Hait
9a38e669ef bumped to version 5.1.3 2015-07-06 16:02:32 +06:00
Nabin Hait
143f2c6faf Merge pull request #3585 from nabinhait/change_log
Added change log
2015-07-06 15:15:29 +05:30
Nabin Hait
9269813207 Added change log 2015-07-06 15:13:35 +05:30
Nabin Hait
0e6f92efa8 Merge pull request #3571 from neilLasrado/item-varients
Fixes for Item Attributes
2015-07-06 14:56:33 +05:30
Neil Trini Lasrado
1a0e86f11d Update item_attribute.py
Error Description Changed
2015-07-06 14:46:06 +05:30
Nabin Hait
73b7efd61d Merge pull request #3583 from rmehta/quotation-list-fix
[fix] quotation list #3492
2015-07-06 14:31:23 +05:30
Nabin Hait
4c4a5b968c Merge pull request #3576 from nabinhait/variant
[fix][patch] delete item variant attributes if no variants exists against that item
2015-07-06 14:30:48 +05:30
Nabin Hait
7b5ac6396a Merge pull request #3575 from nabinhait/batch_report
[fix] Hide zero balance rows in batch-wise balance history report
2015-07-06 14:30:23 +05:30
Nabin Hait
01771e8afc Merge pull request #3573 from rmehta/fix-labels
[fix] [minor] fix customer_name, supplier_name labels
2015-07-06 14:30:13 +05:30
Nabin Hait
347c4affe9 Merge pull request #3567 from rmehta/item-description-mozilla-fix
[fix] item image in mozilla #3412 #3413
2015-07-06 14:27:34 +05:30
Nabin Hait
526957505f Merge pull request #3569 from rmehta/employee-unset-user-id
[fix] remove user permission if user id is unset #3447
2015-07-06 14:27:22 +05:30
Nabin Hait
faa3416852 Merge pull request #3570 from rmehta/remove-masters-from-setup
[minor] remove the term 'Masters' from setup, it is confusing and not used anywhere, add Company to Accounts tab
2015-07-06 14:26:51 +05:30
Rushabh Mehta
56912791e2 [fix] quotation list #3492 2015-07-06 11:14:31 +05:30
Rushabh Mehta
38647c68b9 Merge pull request #3579 from neilLasrado/autocomplete
Autocomplete issues fixed in Manage Variants
2015-07-05 13:52:56 +05:30
Neil Trini Lasrado
4d64acfafc Autocomplete issues fixed in Manage Variants 2015-07-04 14:50:00 +05:30
Nabin Hait
d7441ec051 [fix][patch] delete item variant attributes if no variants exists against that item 2015-07-03 19:20:27 +05:30
Rushabh Mehta
0f15273bd7 Merge pull request #3572 from tmimori/develop
Fix for Monthly Attendance Report #3402
2015-07-03 15:49:26 +05:30
Nabin Hait
24efb3122a [fix] Hide zero balance rows in batch-wise balance history report 2015-07-03 15:20:14 +05:30
Rushabh Mehta
85e6f5d04e [fix] [minor] fix customer_name, supplier_name labels 2015-07-03 12:59:08 +05:30
Neil Trini Lasrado
1faaf71dfc Auto-Capitalize Item Attribute Abbreation, Prevent attribute to be deleated if Variant exists 2015-07-03 12:44:01 +05:30
Tsutomu Mimori
5a0fbff1a3 #3402 2015-07-03 16:08:02 +09:00
Rushabh Mehta
7278c0ae85 [minor] remove the term 'Masters' from setup, it is confusing and not used anywhere, add Company to Accounts tab 2015-07-03 12:21:50 +05:30
Rushabh Mehta
5688a6c31a [fix] remove user permission if user id is unset #3447 2015-07-03 11:34:53 +05:30
Rushabh Mehta
71349d221b [fix] item image in mozilla #3412 #3413 2015-07-03 10:43:35 +05:30
Nabin Hait
b7219dc698 Merge branch 'develop' 2015-07-02 17:58:40 +05:30
Nabin Hait
37c6ce7b1e bumped to version 5.1.2 2015-07-02 18:28:40 +06:00
Nabin Hait
7028ba507e Merge pull request #3561 from nabinhait/develop
Fixes
2015-07-02 17:55:18 +05:30
Nabin Hait
fcee17fd16 Removed purchase item validation 2015-07-02 17:51:35 +05:30
Nabin Hait
5906f02e3a update item image in invoice if item exists 2015-07-02 17:51:35 +05:30
Nabin Hait
721dcb1870 Merge branch 'develop' 2015-07-02 16:33:52 +05:30
Nabin Hait
6385967ccd bumped to version 5.1.1 2015-07-02 17:03:52 +06:00
Nabin Hait
81a977cacf Merge pull request #3559 from nabinhait/develop
Fixes
2015-07-02 16:32:34 +05:30
Nabin Hait
34058ded0e [fix] Update item image in sales invoice 2015-07-02 16:31:55 +05:30
Nabin Hait
e98120b716 [fix] Change log path 2015-07-02 16:29:28 +05:30
Nabin Hait
50e363b24e Merge branch 'develop' 2015-07-02 15:28:49 +05:30
Nabin Hait
bc176b6bf8 bumped to version 5.1.0 2015-07-02 15:58:49 +06:00
Nabin Hait
784b49e54e change log 2015-07-02 15:28:15 +05:30
Nabin Hait
04fb6e1a45 Merge pull request #3558 from nabinhait/develop
Change log
2015-07-02 15:22:20 +05:30
Nabin Hait
dffd7c3889 Change log 2015-07-02 15:21:25 +05:30
Nabin Hait
0c7594e5ed Merge pull request #3557 from rmehta/item-description-in-form
[fix] show item description in form grid based on in_list_view
2015-07-02 15:19:24 +05:30
Rushabh Mehta
5105f909d6 [fix] show item description in form grid based on in_list_view 2015-07-02 15:09:18 +05:30
Nabin Hait
2ab9d6e92c Merge pull request #3552 from nabinhait/develop
Recurring docs should not consider Stopped documents and should be scheduled for hourly
2015-07-02 14:42:57 +05:30
Nabin Hait
7580723ab3 Recurring docs should not consider Stopped documents and should be scheduled for hourly 2015-07-02 14:41:27 +05:30
Nabin Hait
52fef71c14 Merge pull request #3543 from rmehta/against-account-fix
Fix against account to show party instead of account
2015-07-02 14:28:11 +05:30
Rushabh Mehta
2cd02af80a [fix] patch date 2015-07-02 14:25:51 +05:30
Rushabh Mehta
0b0ec3536c [change-log] added 2015-07-02 14:25:51 +05:30
Rushabh Mehta
6b35ea873b [fix] against account in general ledger will show party 2015-07-02 14:25:51 +05:30
Nabin Hait
ecf220a721 Merge pull request #3549 from neilLasrado/item-varients
Validation changed for Item Template cannot have Stock
2015-07-02 14:18:31 +05:30
Nabin Hait
04fb1c7fe4 Merge pull request #3550 from neilLasrado/item-desc
Image feild added to Sales Invoice & Purchase Invoice
2015-07-02 14:17:52 +05:30
Neil Trini Lasrado
53bd62eafc Validation changed for Item Template cannot have Stock 2015-07-02 14:15:23 +05:30
Nabin Hait
ff68bf2609 Merge pull request #3551 from nabinhait/develop
Fixes
2015-07-02 14:10:58 +05:30
Nabin Hait
fdd0db3459 Update project completion percentage and costing after syncing task 2015-07-02 14:09:49 +05:30
Nabin Hait
f92465981c datetime issue fixed in maintenance schedule 2015-07-02 14:09:49 +05:30
Nabin Hait
885c70984d [fix] Always show Sales invoice in Gross profit report 2015-07-02 14:09:49 +05:30
Neil Trini Lasrado
9c15ef903d Image feild added to Sales Invoice & Purchase Invoice 2015-07-02 13:09:57 +05:30
Rushabh Mehta
bc799885d0 [fix] bom client script 2015-07-02 12:44:16 +05:30
Nabin Hait
cb129264cb Merge pull request #3386 from neilLasrado/item-varients
[redesign] Manage Item varients
2015-07-01 18:29:04 +05:30
Neil Trini Lasrado
fe9cd1d875 More Fixes in Manage Varients 2015-07-01 14:41:30 +05:30
Neil Trini Lasrado
64fbe955c7 Modified Date changed for Item Doctype 2015-07-01 14:04:00 +05:30
Neil Trini Lasrado
0988440fd9 Fixes for Manage Variants 2015-07-01 13:17:15 +05:30
Neil Trini Lasrado
274dd4ada0 Fixed Manage Variants Attribute autocomplete appearance. 2015-07-01 12:51:40 +05:30
Neil Trini Lasrado
724fd82419 Fixes in Manage Variants 2015-07-01 12:51:40 +05:30
Neil Trini Lasrado
3f2604eff6 Patch for Item Variants 2015-07-01 12:51:40 +05:30
Neil Trini Lasrado
c761fefb78 more fixes in test records 2015-07-01 12:51:11 +05:30
Neil Trini Lasrado
203cb10ef7 fixes in test cases 2015-07-01 12:51:11 +05:30
Neil Trini Lasrado
90c66b1998 test cases added 2015-07-01 12:51:11 +05:30
Neil Trini Lasrado
fed431f908 Code Fixes in Manage Variants 2015-07-01 12:51:11 +05:30
Neil Trini Lasrado
bd9745ba72 Rename Item Variant from Manage Variants feature Added. 2015-07-01 12:51:11 +05:30
Neil Trini Lasrado
8fb123b20e item variants, creation, deleation and update logic added.
logic added to copy changes in template to variants
2015-07-01 12:51:11 +05:30
Neil Trini Lasrado
333ccd212b variants combination generation logic added 2015-07-01 12:51:10 +05:30
Neil Trini Lasrado
c8cc8b7115 manage variants new doctype created 2015-07-01 12:51:10 +05:30
Nabin Hait
ec44fa95ce Merge pull request #3537 from neilLasrado/project
Fixed Issues in Project Task
2015-06-30 17:29:19 +05:30
Neil Trini Lasrado
a25e8ea0bc Fixed Issues in Project Task 2015-06-30 17:15:13 +05:30
Rushabh Mehta
ea02b9a5c3 Merge pull request #3530 from anandpdoshi/anand-june-29
[fix] Item Variant Attribute autocomplete appearance. Fixes #3488, #3515, #3525
2015-06-30 13:05:19 +05:30
Rushabh Mehta
74a63bf003 Merge pull request #3531 from pdvyas/exchange-rate-api
Change currency exchange rate api to fixer.io
2015-06-30 12:46:52 +05:30
Pratik Vyas
a0f2510b01 Change currency exchange rate api to fixer.io 2015-06-30 12:36:17 +05:30
Anand Doshi
0820161157 [fix] Item Variant Attribute autocomplete appearance. Fixes #3488, #3515, #3525 2015-06-29 20:57:06 -07:00
Nabin Hait
56bc215855 Merge pull request #3505 from neilLasrado/print-format
Recurring Invoice Print Format
2015-06-29 18:54:24 +05:30
Nabin Hait
8687d25f7e Merge pull request #3526 from neilLasrado/minor-fixes
Minor fixes
2015-06-29 18:53:10 +05:30
Nabin Hait
9cea01fa8b Merge pull request #3527 from nabinhait/develop
Journal Entry list view and delete events via query
2015-06-29 18:39:43 +05:30
Nabin Hait
e06d01e3ed Delete events via query instead of delete_doc function, to save time 2015-06-29 18:38:38 +05:30
Nabin Hait
11243a4fb4 Show amount in Journal Entry list view 2015-06-29 18:38:38 +05:30
Neil Trini Lasrado
b9e5cd0df4 Fixed lead status not updating on Creation of oppurtunity issue 2015-06-29 17:01:32 +05:30
Neil Trini Lasrado
a1f1edc786 Typo fixes in Sales Person 2015-06-29 16:04:12 +05:30
Neil Trini Lasrado
e2d8dd0663 added recurring print format to sales/purchase invoice and order 2015-06-29 12:50:41 +05:30
Nabin Hait
d1605c5cb2 Merge branch 'develop' 2015-06-27 13:09:05 +05:30
Nabin Hait
64ca52fb77 bumped to version 5.0.29 2015-06-27 13:39:05 +06:00
Nabin Hait
2f11a3bdaf Merge pull request #3523 from nabinhait/develop
Multiple fixes
2015-06-27 13:07:44 +05:30
Nabin Hait
93cdee4503 [fix] Escape values in queries 2015-06-27 12:51:00 +05:30
Nabin Hait
dfac6848cc In list view property added in BOM 2015-06-26 14:42:51 +05:30
Nabin Hait
8ad0b4e0b9 Show Issue id in list view from customer login 2015-06-26 14:42:51 +05:30
Rushabh Mehta
9624bac3cf [fix] create SMS Log 2015-05-20 15:48:58 +05:30
217 changed files with 3457 additions and 2409 deletions

View File

@@ -1,5 +1,9 @@
# Contributing to Frappe / ERPNext
## 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.
## Reporting issues
We only accept issues that are bug reports or feature requests. Bugs must be isolated and reproducible problems. Please read the following guidelines before opening any issue.

View File

@@ -1,2 +1,2 @@
from __future__ import unicode_literals
__version__ = '5.0.28'
__version__ = '5.2.0'

View File

@@ -4,13 +4,6 @@
"docstatus": 0,
"doctype": "DocType",
"fields": [
{
"fieldname": "check_supplier_invoice_uniqueness",
"fieldtype": "Check",
"label": "Check Supplier Invoice Number Uniqueness",
"permlevel": 0,
"precision": ""
},
{
"default": "1",
"description": "If enabled, the system will post accounting entries for inventory automatically.",
@@ -45,12 +38,19 @@
"label": "Credit Controller",
"options": "Role",
"permlevel": 0
},
{
"fieldname": "check_supplier_invoice_uniqueness",
"fieldtype": "Check",
"label": "Check Supplier Invoice Number Uniqueness",
"permlevel": 0,
"precision": ""
}
],
"icon": "icon-cog",
"idx": 1,
"issingle": 1,
"modified": "2015-06-11 06:06:34.047890",
"modified": "2015-07-14 00:51:48.095525",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Accounts Settings",

View File

@@ -139,7 +139,7 @@
"icon": "icon-money",
"idx": 1,
"in_create": 0,
"modified": "2015-04-23 02:54:26.934607",
"modified": "2015-07-13 05:28:25.504801",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Cost Center",
@@ -189,7 +189,7 @@
"apply_user_permissions": 1,
"permlevel": 0,
"read": 1,
"role": "Material User"
"role": "Stock User"
}
],
"search_fields": "parent_cost_center, is_group"

View File

@@ -56,7 +56,7 @@
],
"icon": "icon-calendar",
"idx": 1,
"modified": "2015-04-18 07:33:23.922518",
"modified": "2015-07-13 05:28:27.745408",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Fiscal Year",
@@ -78,11 +78,63 @@
{
"apply_user_permissions": 1,
"delete": 0,
"email": 1,
"email": 0,
"permlevel": 0,
"print": 1,
"print": 0,
"read": 1,
"role": "All"
"role": "Sales User"
},
{
"create": 0,
"delete": 0,
"email": 0,
"export": 0,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 0,
"role": "Purchase User",
"share": 0,
"write": 0
},
{
"create": 0,
"delete": 0,
"email": 0,
"export": 0,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 0,
"role": "Accounts User",
"share": 0,
"write": 0
},
{
"create": 0,
"delete": 0,
"email": 0,
"export": 0,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 0,
"role": "Stock User",
"share": 0,
"write": 0
},
{
"create": 0,
"delete": 0,
"email": 0,
"export": 0,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 0,
"role": "Employee",
"share": 0,
"write": 0
}
],
"sort_field": "name",

View File

@@ -193,7 +193,7 @@
"icon": "icon-list",
"idx": 1,
"in_create": 1,
"modified": "2015-06-14 20:57:19.800276",
"modified": "2015-07-09 15:51:04.986518",
"modified_by": "Administrator",
"module": "Accounts",
"name": "GL Entry",
@@ -225,6 +225,19 @@
"role": "Accounts Manager",
"submit": 0,
"write": 0
},
{
"create": 0,
"delete": 0,
"email": 0,
"export": 1,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 1,
"role": "Auditor",
"share": 0,
"write": 0
}
],
"search_fields": "voucher_no,account,posting_date,against_voucher",

View File

@@ -127,7 +127,7 @@ def update_outstanding_amt(account, party_type, party, against_voucher_type, aga
against_voucher_amount = flt(frappe.db.sql("""
select sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))
from `tabGL Entry` where voucher_type = 'Journal Entry' and voucher_no = %s
and account = %s and ifnull(party_type, '')=%s and ifnull(party, '')=%s
and account = %s and ifnull(party_type, '')=%s and ifnull(party, '')=%s
and ifnull(against_voucher, '') = ''""",
(against_voucher, account, cstr(party_type), cstr(party)))[0][0])
@@ -158,3 +158,22 @@ def validate_frozen_account(account, adv_adj=None):
frappe.throw(_("Account {0} is frozen").format(account))
elif frozen_accounts_modifier not in frappe.get_roles():
frappe.throw(_("Not authorized to edit frozen Account {0}").format(account))
def update_against_account(voucher_type, voucher_no):
entries = frappe.db.get_all("GL Entry",
filters={"voucher_type": voucher_type, "voucher_no": voucher_no},
fields=["name", "party", "against", "debit", "credit", "account"])
accounts_debited, accounts_credited = [], []
for d in entries:
if flt(d.debit > 0): accounts_debited.append(d.party or d.account)
if flt(d.credit) > 0: accounts_credited.append(d.party or d.account)
for d in entries:
if flt(d.debit > 0):
new_against = ", ".join(list(set(accounts_credited)))
if flt(d.credit > 0):
new_against = ", ".join(list(set(accounts_debited)))
if d.against != new_against:
frappe.db.set_value("GL Entry", d.name, "against", new_against)

View File

@@ -53,7 +53,7 @@
"fieldname": "posting_date",
"fieldtype": "Date",
"in_filter": 1,
"in_list_view": 1,
"in_list_view": 0,
"label": "Posting Date",
"no_copy": 1,
"oldfieldname": "posting_date",
@@ -445,7 +445,7 @@
"icon": "icon-file-text",
"idx": 1,
"is_submittable": 1,
"modified": "2015-04-27 20:32:31.655580",
"modified": "2015-06-29 15:28:12.529019",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Journal Entry",

View File

@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import cstr, flt, fmt_money, formatdate, getdate
from frappe.utils import cstr, flt, fmt_money, formatdate, getdate, date_diff
from frappe import msgprint, _, scrub
from erpnext.setup.utils import get_company_currency
from erpnext.controllers.accounts_controller import AccountsController
@@ -35,7 +35,7 @@ class JournalEntry(AccountsController):
self.set_print_format_fields()
self.validate_against_sales_order()
self.validate_against_purchase_order()
self.check_credit_days()
self.check_due_date()
self.validate_expense_claim()
self.validate_credit_debit_note()
self.validate_empty_accounts_table()
@@ -81,30 +81,28 @@ class JournalEntry(AccountsController):
frappe.throw(_("Row {0}: Party Type and Party is only applicable against Receivable / Payable account").format(d.idx))
def check_credit_limit(self):
customers = list(set([d.party for d in self.get("accounts")
customers = list(set([d.party for d in self.get("accounts")
if d.party_type=="Customer" and d.party and flt(d.debit) > 0]))
if customers:
from erpnext.selling.doctype.customer.customer import check_credit_limit
for customer in customers:
check_credit_limit(customer, self.company)
def check_credit_days(self):
from erpnext.accounts.party import get_credit_days
posting_date = None
def check_due_date(self):
if self.cheque_date:
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:
posting_date = frappe.db.get_value("Sales Invoice", d.against_invoice, "posting_date")
due_date = frappe.db.get_value("Sales Invoice", d.against_invoice, "due_date")
elif d.against_voucher:
posting_date = frappe.db.get_value("Purchase Invoice", d.against_voucher, "posting_date")
due_date = frappe.db.get_value("Purchase Invoice", d.against_voucher, "due_date")
credit_days = get_credit_days(d.party_type, d.party, self.company)
if posting_date and credit_days:
date_diff = (getdate(self.cheque_date) - getdate(posting_date)).days
if date_diff > flt(credit_days):
msgprint(_("Note: Reference Date exceeds allowed credit days by {0} days for {1} {2}")
.format(date_diff - flt(credit_days), d.party_type, d.party))
if due_date and getdate(self.cheque_date) > getdate(due_date):
diff = date_diff(self.cheque_date, due_date)
if diff > 0:
msgprint(_("Note: Reference Date exceeds invoice due date by {0} days for {1} {2}")
.format(diff, d.party_type, d.party))
def validate_cheque_info(self):
if self.voucher_type in ['Bank Entry']:
@@ -243,8 +241,8 @@ class JournalEntry(AccountsController):
def set_against_account(self):
accounts_debited, accounts_credited = [], []
for d in self.get("accounts"):
if flt(d.debit > 0): accounts_debited.append(d.account)
if flt(d.credit) > 0: accounts_credited.append(d.account)
if flt(d.debit > 0): accounts_debited.append(d.party or d.account)
if flt(d.credit) > 0: accounts_credited.append(d.party or d.account)
for d in self.get("accounts"):
if flt(d.debit > 0): d.against_account = ", ".join(list(set(accounts_credited)))
@@ -274,9 +272,9 @@ class JournalEntry(AccountsController):
r.append(_('Reference #{0} dated {1}').format(self.cheque_no, formatdate(self.cheque_date)))
else:
msgprint(_("Please enter Reference date"), raise_exception=frappe.MandatoryError)
company_currency = get_company_currency(self.company)
for d in self.get('accounts'):
if d.against_invoice and d.credit:
r.append(_("{0} against Sales Invoice {1}").format(fmt_money(flt(d.credit), currency = company_currency), \
@@ -426,7 +424,7 @@ class JournalEntry(AccountsController):
def validate_expense_claim(self):
for d in self.accounts:
if d.against_expense_claim:
sanctioned_amount, reimbursed_amount = frappe.db.get_value("Expense Claim",
sanctioned_amount, reimbursed_amount = frappe.db.get_value("Expense Claim",
d.against_expense_claim, ("total_sanctioned_amount", "total_amount_reimbursed"))
pending_amount = flt(sanctioned_amount) - flt(reimbursed_amount)
if d.debit > pending_amount:

View File

@@ -77,6 +77,51 @@
"read_only": 0,
"reqd": 1
},
{
"fieldname": "warehouse",
"fieldtype": "Link",
"label": "Warehouse",
"oldfieldname": "warehouse",
"oldfieldtype": "Link",
"options": "Warehouse",
"permlevel": 0,
"read_only": 0,
"reqd": 0
},
{
"allow_on_submit": 1,
"fieldname": "letter_head",
"fieldtype": "Link",
"label": "Letter Head",
"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
},
{
"allow_on_submit": 1,
"fieldname": "select_print_heading",
"fieldtype": "Link",
"in_filter": 0,
"label": "Print Heading",
"oldfieldname": "select_print_heading",
"oldfieldtype": "Select",
"options": "Print Heading",
"permlevel": 0,
"read_only": 0
},
{
"fieldname": "column_break0",
"fieldtype": "Column Break",
@@ -105,6 +150,14 @@
"read_only": 0,
"reqd": 0
},
{
"fieldname": "mode_of_payment",
"fieldtype": "Link",
"label": "Mode of Payment",
"options": "Mode of Payment",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "cash_bank_account",
"fieldtype": "Link",
@@ -139,17 +192,6 @@
"read_only": 0,
"reqd": 0
},
{
"fieldname": "warehouse",
"fieldtype": "Link",
"label": "Warehouse",
"oldfieldname": "warehouse",
"oldfieldtype": "Link",
"options": "Warehouse",
"permlevel": 0,
"read_only": 0,
"reqd": 0
},
{
"fieldname": "cost_center",
"fieldtype": "Link",
@@ -161,16 +203,6 @@
"read_only": 0,
"reqd": 1
},
{
"fieldname": "taxes_and_charges",
"fieldtype": "Link",
"label": "Taxes and Charges",
"oldfieldname": "charge",
"oldfieldtype": "Link",
"options": "Sales Taxes and Charges Template",
"permlevel": 0,
"read_only": 0
},
{
"fieldname": "write_off_account",
"fieldtype": "Link",
@@ -190,43 +222,19 @@
"reqd": 1
},
{
"allow_on_submit": 1,
"fieldname": "letter_head",
"fieldname": "taxes_and_charges",
"fieldtype": "Link",
"label": "Letter Head",
"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",
"label": "Taxes and Charges",
"oldfieldname": "charge",
"oldfieldtype": "Link",
"options": "Terms and Conditions",
"permlevel": 0,
"read_only": 0
},
{
"allow_on_submit": 1,
"fieldname": "select_print_heading",
"fieldtype": "Link",
"in_filter": 0,
"label": "Print Heading",
"oldfieldname": "select_print_heading",
"oldfieldtype": "Select",
"options": "Print Heading",
"options": "Sales Taxes and Charges Template",
"permlevel": 0,
"read_only": 0
}
],
"icon": "icon-cog",
"idx": 1,
"modified": "2015-05-20 05:38:44.482696",
"modified": "2015-07-07 08:56:04.381471",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Profile",

View File

@@ -68,7 +68,7 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
}
},
supplier: function() {
var me = this;
if(this.frm.updating_party_details)
@@ -224,3 +224,4 @@ cur_frm.cscript.select_print_heading = function(doc,cdt,cdn){
else
cur_frm.pformat.print_heading = __("Purchase Invoice");
}

View File

@@ -38,7 +38,7 @@
"fieldtype": "Data",
"hidden": 0,
"in_list_view": 0,
"label": "Name",
"label": "Supplier Name",
"oldfieldname": "supplier_name",
"oldfieldtype": "Data",
"permlevel": 0,
@@ -926,12 +926,21 @@
"no_copy": 1,
"permlevel": 0,
"print_hide": 1
},
{
"depends_on": "eval:doc.is_recurring==1",
"fieldname": "recurring_print_format",
"fieldtype": "Link",
"label": "Recurring Print Format",
"options": "Print Format",
"permlevel": 0,
"precision": ""
}
],
"icon": "icon-file-text",
"idx": 1,
"is_submittable": 1,
"modified": "2015-06-16 16:46:47.308287",
"modified": "2015-07-03 03:26:32.934540",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",

View File

@@ -124,20 +124,11 @@ class PurchaseInvoice(BuyingController):
}
})
if cint(frappe.defaults.get_global_default('maintain_same_rate')):
super(PurchaseInvoice, self).validate_with_previous_doc({
"Purchase Order Item": {
"ref_dn_field": "po_detail",
"compare_fields": [["rate", "="]],
"is_child_table": True,
"allow_duplicate_prev_row_id": True
},
"Purchase Receipt Item": {
"ref_dn_field": "pr_detail",
"compare_fields": [["rate", "="]],
"is_child_table": True
}
})
if cint(frappe.db.get_single_value('Buying Settings', 'maintain_same_rate')):
self.validate_rate_with_reference_doc([
["Purchase Order", "purchase_order", "po_detail"],
["Purchase Receipt", "purchase_receipt", "pr_detail"]
])
def set_against_expense_account(self):
auto_accounting_for_stock = cint(frappe.defaults.get_global_default("auto_accounting_for_stock"))
@@ -164,7 +155,7 @@ class PurchaseInvoice(BuyingController):
elif item.expense_account not in against_accounts:
# if no auto_accounting_for_stock or not a stock item
against_accounts.append(item.expense_account)
self.against_expense_account = ",".join(against_accounts)
def po_required(self):
@@ -271,7 +262,7 @@ class PurchaseInvoice(BuyingController):
gl_entries.append(
self.get_gl_dict({
"account": tax.account_head,
"against": self.credit_to,
"against": self.supplier,
"debit": tax.add_deduct_tax == "Add" and tax.base_tax_amount_after_discount_amount or 0,
"credit": tax.add_deduct_tax == "Deduct" and tax.base_tax_amount_after_discount_amount or 0,
"remarks": self.remarks,
@@ -295,7 +286,7 @@ class PurchaseInvoice(BuyingController):
gl_entries.append(
self.get_gl_dict({
"account": item.expense_account,
"against": self.credit_to,
"against": self.supplier,
"debit": item.base_net_amount,
"remarks": self.remarks,
"cost_center": item.cost_center
@@ -315,7 +306,7 @@ class PurchaseInvoice(BuyingController):
gl_entries.append(
self.get_gl_dict({
"account": stock_received_but_not_billed,
"against": self.credit_to,
"against": self.supplier,
"debit": flt(item.item_tax_amount, self.precision("item_tax_amount", item)),
"remarks": self.remarks or "Accounting Entry for Stock"
})
@@ -341,7 +332,7 @@ class PurchaseInvoice(BuyingController):
self.get_gl_dict({
"account": expenses_included_in_valuation,
"cost_center": cost_center,
"against": self.credit_to,
"against": self.supplier,
"credit": applicable_amount,
"remarks": self.remarks or "Accounting Entry for Stock"
})
@@ -355,7 +346,7 @@ class PurchaseInvoice(BuyingController):
gl_entries.append(
self.get_gl_dict({
"account": self.write_off_account,
"against": self.credit_to,
"against": self.supplier,
"credit": flt(self.write_off_amount),
"remarks": self.remarks,
"cost_center": self.write_off_cost_center
@@ -374,7 +365,7 @@ class PurchaseInvoice(BuyingController):
self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
self.make_gl_entries_on_cancel()
self.update_project()
def update_project(self):
project_list = []
for d in self.items:
@@ -384,14 +375,15 @@ class PurchaseInvoice(BuyingController):
project.update_purchase_costing()
project.save()
project_list.append(d.project_name)
def validate_supplier_invoice(self):
if self.bill_date:
if getdate(self.bill_date) > getdate(self.posting_date):
frappe.throw("Supplier Invoice Date cannot be greater than Posting Date")
if self.bill_no:
if cint(frappe.db.get_single_value("Accounts Settings", "check_supplier_invoice_uniqueness")):
pi = frappe.db.exists("Purchase Invoice", {"bill_no": self.bill_no, "fiscal_year": self.fiscal_year})
pi = frappe.db.exists("Purchase Invoice", {"bill_no": self.bill_no,
"fiscal_year": self.fiscal_year, "name": ("!=", self.name)})
if pi:
frappe.throw("Supplier Invoice No exists in Purchase Invoice {0}".format(pi))
@@ -410,4 +402,4 @@ def get_expense_account(doctype, txt, searchfield, start, page_len, filters):
and tabAccount.company = '%(company)s'
and tabAccount.%(key)s LIKE '%(txt)s'
%(mcond)s""" % {'company': filters['company'], 'key': searchfield,
'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype)})
'txt': "%%%s%%" % frappe.db.escape(txt), 'mcond':get_match_cond(doctype)})

View File

@@ -49,6 +49,23 @@
"read_only": 0,
"width": "300px"
},
{
"fieldname": "image",
"fieldtype": "Attach",
"hidden": 1,
"label": "Image",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "image_view",
"fieldtype": "Image",
"label": "Image View",
"options": "image",
"permlevel": 0,
"precision": "",
"print_hide": 1
},
{
"fieldname": "quantity_and_rate",
"fieldtype": "Section Break",
@@ -452,7 +469,7 @@
],
"idx": 1,
"istable": 1,
"modified": "2015-06-02 14:18:56.294949",
"modified": "2015-07-02 03:00:44.496683",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",

View File

@@ -36,7 +36,7 @@ def get_items(price_list, sales_or_purchase, item=None):
if(locate(%(_name)s, i.item_name), locate(%(_name)s, i.item_name), 99999),
if(locate(%(_name)s, i.variant_of), locate(%(_name)s, i.variant_of), 99999),
if(locate(%(_name)s, i.item_group), locate(%(_name)s, i.item_group), 99999),"""
args["name"] = "%%%s%%" % item
args["name"] = "%%%s%%" % frappe.db.escape(item)
args["_name"] = item.replace("%", "")
# locate function is used to sort by closest match from the beginning of the value

View File

@@ -369,15 +369,15 @@ cur_frm.fields_dict["items"].grid.get_field("cost_center").get_query = function(
}
cur_frm.cscript.income_account = function(doc, cdt, cdn) {
cur_frm.cscript.copy_account_in_all_row(doc, cdt, cdn, "income_account");
erpnext.utils.copy_value_in_all_row(doc, cdt, cdn, "items", "income_account");
}
cur_frm.cscript.expense_account = function(doc, cdt, cdn) {
cur_frm.cscript.copy_account_in_all_row(doc, cdt, cdn, "expense_account");
erpnext.utils.copy_value_in_all_row(doc, cdt, cdn, "items", "expense_account");
}
cur_frm.cscript.cost_center = function(doc, cdt, cdn) {
cur_frm.cscript.copy_account_in_all_row(doc, cdt, cdn, "cost_center");
erpnext.utils.copy_value_in_all_row(doc, cdt, cdn, "items", "cost_center");
}
cur_frm.cscript.on_submit = function(doc, cdt, cdn) {
@@ -392,8 +392,6 @@ cur_frm.cscript.on_submit = function(doc, cdt, cdn) {
}
}
cur_frm.set_query("debit_to", function(doc) {
return{
filters: [

View File

@@ -47,7 +47,7 @@
"fieldtype": "Data",
"hidden": 0,
"in_list_view": 0,
"label": "Name",
"label": "Customer Name",
"oldfieldname": "customer_name",
"oldfieldtype": "Data",
"permlevel": 0,
@@ -322,9 +322,9 @@
"read_only": 0
},
{
"fieldname": "sales_bom_help",
"fieldname": "product_bundle_help",
"fieldtype": "HTML",
"label": "Sales BOM Help",
"label": "Product Bundle Help",
"permlevel": 0,
"print_hide": 1,
"read_only": 0
@@ -605,7 +605,7 @@
"label": "Total Advance",
"oldfieldname": "total_advance",
"oldfieldtype": "Currency",
"options": "",
"options": "Company:company:default_currency",
"permlevel": 0,
"print_hide": 1,
"read_only": 1
@@ -618,7 +618,7 @@
"no_copy": 1,
"oldfieldname": "outstanding_amount",
"oldfieldtype": "Currency",
"options": "currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"print_hide": 1,
"read_only": 1
@@ -671,7 +671,7 @@
"no_copy": 1,
"oldfieldname": "paid_amount",
"oldfieldtype": "Currency",
"options": "currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"print_hide": 1,
"read_only": 0
@@ -711,7 +711,7 @@
"fieldtype": "Currency",
"label": "Write Off Amount",
"no_copy": 1,
"options": "currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"print_hide": 1,
"read_only": 0
@@ -1227,6 +1227,15 @@
"print_hide": 1,
"read_only": 0
},
{
"depends_on": "eval:doc.is_recurring==1",
"fieldname": "recurring_print_format",
"fieldtype": "Link",
"label": "Recurring Print Format",
"options": "Print Format",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "against_income_account",
"fieldtype": "Small Text",
@@ -1243,8 +1252,8 @@
],
"icon": "icon-file-text",
"idx": 1,
"is_submittable": 1,
"modified": "2015-06-16 16:45:06.618286",
"is_submittable": 1,
"modified": "2015-07-09 17:33:28.583808",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",

View File

@@ -138,7 +138,7 @@ class SalesInvoice(SellingController):
if not self.debit_to:
self.debit_to = get_party_account(self.company, self.customer, "Customer")
if not self.due_date:
if not self.due_date and self.customer:
self.due_date = get_due_date(self.posting_date, "Customer", self.customer, self.company)
super(SalesInvoice, self).set_missing_values(for_validate)
@@ -169,6 +169,7 @@ class SalesInvoice(SellingController):
if pos:
if not for_validate and not self.customer:
self.customer = pos.customer
self.mode_of_payment = pos.mode_of_payment
# self.set_customer_defaults()
for fieldname in ('territory', 'naming_series', 'currency', 'taxes_and_charges', 'letter_head', 'tc_name',
@@ -263,20 +264,11 @@ class SalesInvoice(SellingController):
},
})
if cint(frappe.defaults.get_global_default('maintain_same_sales_rate')):
super(SalesInvoice, self).validate_with_previous_doc({
"Sales Order Item": {
"ref_dn_field": "so_detail",
"compare_fields": [["rate", "="]],
"is_child_table": True,
"allow_duplicate_prev_row_id": True
},
"Delivery Note Item": {
"ref_dn_field": "dn_detail",
"compare_fields": [["rate", "="]],
"is_child_table": True
}
})
if cint(frappe.db.get_single_value('Selling Settings', 'maintain_same_sales_rate')):
self.validate_rate_with_reference_doc([
["Sales Order", "sales_order", "so_detail"],
["Delivery Note", "delivery_note", "dn_detail"]
])
def set_against_income_account(self):
"""Set against account for debit to account"""
@@ -503,7 +495,7 @@ class SalesInvoice(SellingController):
gl_entries.append(
self.get_gl_dict({
"account": tax.account_head,
"against": self.debit_to,
"against": self.customer,
"credit": flt(tax.base_tax_amount_after_discount_amount),
"remarks": self.remarks,
"cost_center": tax.cost_center
@@ -517,7 +509,7 @@ class SalesInvoice(SellingController):
gl_entries.append(
self.get_gl_dict({
"account": item.income_account,
"against": self.debit_to,
"against": self.customer,
"credit": item.base_net_amount,
"remarks": self.remarks,
"cost_center": item.cost_center
@@ -548,7 +540,7 @@ class SalesInvoice(SellingController):
gl_entries.append(
self.get_gl_dict({
"account": self.cash_bank_account,
"against": self.debit_to,
"against": self.customer,
"debit": self.paid_amount,
"remarks": self.remarks,
})
@@ -572,7 +564,7 @@ class SalesInvoice(SellingController):
gl_entries.append(
self.get_gl_dict({
"account": self.write_off_account,
"against": self.debit_to,
"against": self.customer,
"debit": self.write_off_amount,
"remarks": self.remarks,
"cost_center": self.write_off_cost_center
@@ -587,7 +579,7 @@ def get_list_context(context=None):
@frappe.whitelist()
def get_bank_cash_account(mode_of_payment, company):
account = frappe.db.get_value("Mode of Payment Account",
account = frappe.db.get_value("Mode of Payment Account",
{"parent": mode_of_payment, "company": company}, "default_account")
if not account:
frappe.msgprint(_("Please set default Cash or Bank account in Mode of Payment {0}").format(mode_of_payment))
@@ -611,7 +603,7 @@ def get_income_account(doctype, txt, searchfield, start, page_len, filters):
and tabAccount.company = '%(company)s'
and tabAccount.%(key)s LIKE '%(txt)s'
%(mcond)s""" % {'company': filters['company'], 'key': searchfield,
'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype)})
'txt': "%%%s%%" % frappe.db.escape(txt), 'mcond':get_match_cond(doctype)})
@frappe.whitelist()
def make_delivery_note(source_name, target_doc=None):

View File

@@ -5,6 +5,7 @@ from __future__ import unicode_literals
import frappe
import unittest, copy
import time
from frappe.utils import nowdate, add_days
from erpnext.accounts.utils import get_stock_and_account_difference
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
from erpnext.projects.doctype.time_log_batch.test_time_log_batch import *
@@ -756,14 +757,27 @@ 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")
self.assertEqual(si1.due_date, "2015-08-31")
def create_sales_invoice(**args):
si = frappe.new_doc("Sales Invoice")
args = frappe._dict(args)
if args.posting_date:
si.posting_date = args.posting_date
if args.posting_time:
si.posting_time = args.posting_time
si.posting_date = args.posting_date or nowdate()
si.company = args.company or "_Test Company"
si.customer = args.customer or "_Test Customer"

View File

@@ -68,6 +68,23 @@
"reqd": 1,
"width": "200px"
},
{
"fieldname": "image",
"fieldtype": "Attach",
"hidden": 1,
"label": "Image",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "image_view",
"fieldtype": "Image",
"label": "Image View",
"options": "image",
"permlevel": 0,
"precision": "",
"print_hide": 1
},
{
"fieldname": "quantity_and_rate",
"fieldtype": "Section Break",
@@ -505,7 +522,7 @@
],
"idx": 1,
"istable": 1,
"modified": "2015-06-02 14:18:45.176726",
"modified": "2015-07-02 02:59:08.413213",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Item",

View File

@@ -4,9 +4,10 @@
from __future__ import unicode_literals
import frappe
import datetime
from frappe import _, msgprint, scrub
from frappe.defaults import get_user_permissions
from frappe.utils import add_days, getdate, formatdate, flt
from frappe.utils import add_days, getdate, formatdate, flt, get_first_day, date_diff, nowdate
from erpnext.utilities.doctype.address.address import get_address_display
from erpnext.utilities.doctype.contact.contact import get_contact_details
@@ -73,9 +74,17 @@ def set_contact_details(out, party, party_type):
{party_type.lower(): party.name, "is_primary_contact":1}, "name")
if not out.contact_person:
return
out.update(get_contact_details(out.contact_person))
out.update({
"contact_person": None,
"contact_display": None,
"contact_email": None,
"contact_mobile": None,
"contact_phone": None,
"contact_designation": None,
"contact_department": None
})
else:
out.update(get_contact_details(out.contact_person))
def set_other_values(out, party, party_type):
# copy
@@ -158,43 +167,54 @@ def get_party_account(company, party, party_type):
return account
@frappe.whitelist()
def get_due_date(posting_date, party_type, party, company):
"""Set Due Date = Posting Date + Credit Days"""
due_date = None
if posting_date:
credit_days = get_credit_days(party_type, party, company)
due_date = add_days(posting_date, credit_days) if credit_days else posting_date
if posting_date and party:
due_date = posting_date
if party_type=="Customer":
credit_days_based_on, credit_days = get_credit_days(party_type, party, company)
if credit_days_based_on == "Fixed Days" and credit_days:
due_date = add_days(posting_date, credit_days)
elif credit_days_based_on == "Last Day of the Next Month":
due_date = (get_first_day(posting_date, 0, 2) + datetime.timedelta(-1)).strftime("%Y-%m-%d")
else:
credit_days = get_credit_days(party_type, party, company)
if credit_days:
due_date = add_days(posting_date, credit_days)
return due_date
def get_credit_days(party_type, party, company):
if not party:
return None
party_group_doctype = "Customer Group" if party_type=="Customer" else "Supplier Type"
credit_days, party_group = frappe.db.get_value(party_type, party, ["credit_days", frappe.scrub(party_group_doctype)])
if not credit_days:
credit_days = frappe.db.get_value(party_group_doctype, party_group, "credit_days") or \
frappe.db.get_value("Company", company, "credit_days")
return credit_days
def validate_due_date(posting_date, due_date, party_type, party, company):
credit_days = get_credit_days(party_type, party, company)
posting_date, due_date = getdate(posting_date), getdate(due_date)
diff = (due_date - posting_date).days
if diff < 0:
frappe.throw(_("Due Date cannot be before Posting Date"))
elif credit_days is not None and diff > flt(credit_days):
is_credit_controller = frappe.db.get_value("Accounts Settings", None,
"credit_controller") in frappe.get_roles()
if is_credit_controller:
msgprint(_("Note: Due / Reference Date exceeds allowed customer credit days by {0} day(s)")
.format(diff - flt(credit_days)))
if party_type and party:
if party_type == "Customer":
credit_days_based_on, credit_days, customer_group = \
frappe.db.get_value(party_type, party, ["credit_days_based_on", "credit_days", "customer_group"])
if not credit_days_based_on:
credit_days_based_on, credit_days = \
frappe.db.get_value("Customer Group", customer_group, ["credit_days_based_on", "credit_days"]) \
or frappe.db.get_value("Company", company, ["credit_days_based_on", "credit_days"])
return credit_days_based_on, credit_days
else:
max_due_date = formatdate(add_days(posting_date, credit_days))
frappe.throw(_("Due / Reference Date cannot be after {0}").format(max_due_date))
credit_days, supplier_type = frappe.db.get_value(party_type, party, ["credit_days", "supplier_type"])
if not credit_days:
credit_days = frappe.db.get_value("Supplier Type", supplier_type, "credit_days") \
or frappe.db.get_value("Company", company, "credit_days")
return credit_days
def validate_due_date(posting_date, due_date, party_type, party, company):
if getdate(due_date) < getdate(posting_date):
frappe.throw(_("Due Date cannot be before Posting Date"))
else:
default_due_date = get_due_date(posting_date, party_type, party, company)
if default_due_date != posting_date and getdate(due_date) > getdate(default_due_date):
is_credit_controller = frappe.db.get_single_value("Accounts Settings", "credit_controller") in frappe.get_roles()
if is_credit_controller:
msgprint(_("Note: Due / Reference Date exceeds allowed customer credit days by {0} day(s)")
.format(date_diff(due_date, default_due_date)))
else:
frappe.throw(_("Due / Reference Date cannot be after {0}").format(formatdate(default_due_date)))

View File

@@ -53,13 +53,9 @@ frappe.query_reports["General Ledger"] = {
{
"fieldname":"party_type",
"label": __("Party Type"),
"fieldtype": "Link",
"options": "DocType",
"get_query": function() {
return {
filters: {"name": ["in", ["Customer", "Supplier"]]}
}
}
"fieldtype": "Select",
"options": ["", "Customer", "Supplier"],
"default": ""
},
{
"fieldname":"party",

View File

@@ -86,23 +86,23 @@ class GrossProfitGenerator(object):
self.filters = frappe._dict(filters)
self.load_invoice_items()
self.load_stock_ledger_entries()
self.load_sales_bom()
self.load_product_bundle()
self.load_non_stock_items()
self.process()
def process(self):
self.grouped = {}
for row in self.si_list:
if self.skip_row(row, self.sales_boms):
if self.skip_row(row, self.product_bundles):
continue
row.base_amount = flt(row.base_net_amount)
sales_boms = self.sales_boms.get(row.parenttype, {}).get(row.parent, frappe._dict())
product_bundles = self.product_bundles.get(row.parenttype, {}).get(row.parent, frappe._dict())
# get buying amount
if row.item_code in sales_boms:
row.buying_amount = self.get_buying_amount_from_sales_bom(row, sales_boms[row.item_code])
if row.item_code in product_bundles:
row.buying_amount = self.get_buying_amount_from_product_bundle(row, product_bundles[row.item_code])
else:
row.buying_amount = self.get_buying_amount(row, row.item_code)
@@ -152,13 +152,13 @@ class GrossProfitGenerator(object):
self.grouped_data.append(new_row)
def skip_row(self, row, sales_boms):
def skip_row(self, row, product_bundles):
if self.filters.get("group_by") != "Invoice" and not row.get(scrub(self.filters.get("group_by"))):
return True
def get_buying_amount_from_sales_bom(self, row, sales_bom):
def get_buying_amount_from_product_bundle(self, row, product_bundle):
buying_amount = 0.0
for bom_item in sales_bom:
for bom_item in product_bundle:
if bom_item.get("parent_detail_docname")==row.item_row:
buying_amount += self.get_buying_amount(row, bom_item.item_code)
@@ -175,16 +175,15 @@ class GrossProfitGenerator(object):
else:
if row.update_stock or row.dn_detail:
parenttype, parent, item_row = row.parenttype, row.parent, row.item_row
if row.dn_detail:
row.parenttype = "Delivery Note"
row.parent = row.delivery_note
row.item_row = row.dn_detail
parenttype, parent, item_row = "Delivery Note", row.delivery_note, row.dn_detail
my_sle = self.sle.get((item_code, row.warehouse))
for i, sle in enumerate(my_sle):
# find the stock valution rate from stock ledger entry
if sle.voucher_type == row.parenttype and row.parent == sle.voucher_no and \
sle.voucher_detail_no == row.item_row:
if sle.voucher_type == parenttype and parent == sle.voucher_no and \
sle.voucher_detail_no == item_row:
previous_stock_value = len(my_sle) > i+1 and \
flt(my_sle[i+1].stock_value) or 0.0
return previous_stock_value - flt(sle.stock_value)
@@ -247,13 +246,13 @@ class GrossProfitGenerator(object):
self.sle[(r.item_code, r.warehouse)].append(r)
def load_sales_bom(self):
self.sales_boms = {}
def load_product_bundle(self):
self.product_bundles = {}
for d in frappe.db.sql("""select parenttype, parent, parent_item,
item_code, warehouse, -1*qty as total_qty, parent_detail_docname
from `tabPacked Item` where docstatus=1""", as_dict=True):
self.sales_boms.setdefault(d.parenttype, frappe._dict()).setdefault(d.parent,
self.product_bundles.setdefault(d.parenttype, frappe._dict()).setdefault(d.parent,
frappe._dict()).setdefault(d.parent_item, []).append(d)
def load_non_stock_items(self):

View File

@@ -70,10 +70,6 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
erpnext.utils.get_address_display(this.frm);
},
contact_person: function() {
erpnext.utils.get_contact_details(this.frm);
},
buying_price_list: function() {
this.apply_price_list();
},

View File

@@ -249,7 +249,7 @@ cur_frm.cscript.on_submit = function(doc, cdt, cdn) {
cur_frm.cscript.schedule_date = function(doc, cdt, cdn) {
cur_frm.cscript.copy_account_in_all_row(doc, cdt, cdn, "schedule_date");
erpnext.utils.copy_value_in_all_row(doc, cdt, cdn, "items", "schedule_date");
}
frappe.provide("erpnext.buying");

View File

@@ -53,7 +53,7 @@
"fieldtype": "Data",
"hidden": 0,
"in_list_view": 0,
"label": "Name",
"label": "Supplier Name",
"permlevel": 0,
"read_only": 1
},
@@ -868,12 +868,21 @@
"no_copy": 1,
"permlevel": 0,
"print_hide": 1
},
{
"depends_on": "eval:doc.is_recurring==1",
"fieldname": "recurring_print_format",
"fieldtype": "Link",
"label": "Recurring Print Format",
"options": "Print Format",
"permlevel": 0,
"precision": ""
}
],
"icon": "icon-file-text",
"idx": 1,
"is_submittable": 1,
"modified": "2015-06-15 15:38:56.794601",
"modified": "2015-07-13 05:28:29.397705",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",
@@ -890,7 +899,7 @@
"print": 0,
"read": 1,
"report": 1,
"role": "Material User",
"role": "Stock User",
"submit": 0,
"write": 0
},

View File

@@ -1,247 +1,247 @@
{
"allow_import": 1,
"allow_rename": 1,
"autoname": "naming_series:",
"creation": "2013-01-10 16:34:11",
"description": "Supplier of Goods or Services.",
"docstatus": 0,
"doctype": "DocType",
"document_type": "Master",
"allow_import": 1,
"allow_rename": 1,
"autoname": "naming_series:",
"creation": "2013-01-10 16:34:11",
"description": "Supplier of Goods or Services.",
"docstatus": 0,
"doctype": "DocType",
"document_type": "Master",
"fields": [
{
"fieldname": "basic_info",
"fieldtype": "Section Break",
"label": "",
"oldfieldtype": "Section Break",
"options": "icon-user",
"fieldname": "basic_info",
"fieldtype": "Section Break",
"label": "",
"oldfieldtype": "Section Break",
"options": "icon-user",
"permlevel": 0
},
},
{
"fieldname": "naming_series",
"fieldtype": "Select",
"label": "Series",
"no_copy": 1,
"oldfieldname": "naming_series",
"oldfieldtype": "Select",
"options": "SUPP-",
"fieldname": "naming_series",
"fieldtype": "Select",
"label": "Series",
"no_copy": 1,
"oldfieldname": "naming_series",
"oldfieldtype": "Select",
"options": "SUPP-",
"permlevel": 0
},
},
{
"fieldname": "supplier_name",
"fieldtype": "Data",
"in_list_view": 0,
"label": "Supplier Name",
"no_copy": 1,
"oldfieldname": "supplier_name",
"oldfieldtype": "Data",
"permlevel": 0,
"fieldname": "supplier_name",
"fieldtype": "Data",
"in_list_view": 0,
"label": "Supplier Name",
"no_copy": 1,
"oldfieldname": "supplier_name",
"oldfieldtype": "Data",
"permlevel": 0,
"reqd": 1
},
},
{
"fieldname": "column_break0",
"fieldtype": "Column Break",
"permlevel": 0,
"fieldname": "column_break0",
"fieldtype": "Column Break",
"permlevel": 0,
"width": "50%"
},
},
{
"fieldname": "supplier_type",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Supplier Type",
"oldfieldname": "supplier_type",
"oldfieldtype": "Link",
"options": "Supplier Type",
"permlevel": 0,
"fieldname": "supplier_type",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Supplier Type",
"oldfieldname": "supplier_type",
"oldfieldtype": "Link",
"options": "Supplier Type",
"permlevel": 0,
"reqd": 1
},
},
{
"depends_on": "eval:!doc.__islocal",
"fieldname": "address_contacts",
"fieldtype": "Section Break",
"label": "Address & Contacts",
"oldfieldtype": "Column Break",
"options": "icon-map-marker",
"depends_on": "eval:!doc.__islocal",
"fieldname": "address_contacts",
"fieldtype": "Section Break",
"label": "Address & Contacts",
"oldfieldtype": "Column Break",
"options": "icon-map-marker",
"permlevel": 0
},
},
{
"fieldname": "address_html",
"fieldtype": "HTML",
"label": "Address HTML",
"permlevel": 0,
"fieldname": "address_html",
"fieldtype": "HTML",
"label": "Address HTML",
"permlevel": 0,
"read_only": 1
},
},
{
"fieldname": "column_break1",
"fieldtype": "Column Break",
"permlevel": 0,
"fieldname": "column_break1",
"fieldtype": "Column Break",
"permlevel": 0,
"width": "50%"
},
},
{
"fieldname": "contact_html",
"fieldtype": "HTML",
"label": "Contact HTML",
"permlevel": 0,
"fieldname": "contact_html",
"fieldtype": "HTML",
"label": "Contact HTML",
"permlevel": 0,
"read_only": 1
},
},
{
"fieldname": "default_payable_accounts",
"fieldtype": "Section Break",
"label": "Default Payable Accounts",
"fieldname": "default_payable_accounts",
"fieldtype": "Section Break",
"label": "Default Payable Accounts",
"permlevel": 0
},
},
{
"depends_on": "eval:!doc.__islocal",
"description": "Mention if non-standard receivable account applicable",
"fieldname": "accounts",
"fieldtype": "Table",
"label": "Accounts",
"options": "Party Account",
"depends_on": "eval:!doc.__islocal",
"description": "Mention if non-standard receivable account applicable",
"fieldname": "accounts",
"fieldtype": "Table",
"label": "Accounts",
"options": "Party Account",
"permlevel": 0
},
},
{
"fieldname": "more_info",
"fieldtype": "Section Break",
"label": "More Info",
"oldfieldtype": "Section Break",
"options": "icon-file-text",
"fieldname": "more_info",
"fieldtype": "Section Break",
"label": "More Info",
"oldfieldtype": "Section Break",
"options": "icon-file-text",
"permlevel": 0
},
},
{
"fieldname": "default_currency",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "Default Currency",
"no_copy": 1,
"options": "Currency",
"fieldname": "default_currency",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "Default Currency",
"no_copy": 1,
"options": "Currency",
"permlevel": 0
},
},
{
"fieldname": "default_price_list",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "Price List",
"options": "Price List",
"fieldname": "default_price_list",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "Price List",
"options": "Price List",
"permlevel": 0
},
},
{
"fieldname": "default_taxes_and_charges",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "Taxes and Charges",
"options": "Purchase Taxes and Charges Template",
"fieldname": "default_taxes_and_charges",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "Taxes and Charges",
"options": "Purchase Taxes and Charges Template",
"permlevel": 0
},
},
{
"fieldname": "credit_days",
"fieldtype": "Int",
"label": "Credit Days",
"fieldname": "credit_days",
"fieldtype": "Int",
"label": "Credit Days",
"permlevel": 0
},
},
{
"fieldname": "column_break2",
"fieldtype": "Column Break",
"permlevel": 0,
"fieldname": "column_break2",
"fieldtype": "Column Break",
"permlevel": 0,
"width": "50%"
},
},
{
"fieldname": "website",
"fieldtype": "Data",
"label": "Website",
"oldfieldname": "website",
"oldfieldtype": "Data",
"fieldname": "website",
"fieldtype": "Data",
"label": "Website",
"oldfieldname": "website",
"oldfieldtype": "Data",
"permlevel": 0
},
},
{
"description": "Statutory info and other general information about your Supplier",
"fieldname": "supplier_details",
"fieldtype": "Text",
"label": "Supplier Details",
"oldfieldname": "supplier_details",
"oldfieldtype": "Code",
"description": "Statutory info and other general information about your Supplier",
"fieldname": "supplier_details",
"fieldtype": "Text",
"label": "Supplier Details",
"oldfieldname": "supplier_details",
"oldfieldtype": "Code",
"permlevel": 0
},
},
{
"fieldname": "communications",
"fieldtype": "Table",
"hidden": 1,
"label": "Communications",
"options": "Communication",
"permlevel": 0,
"fieldname": "communications",
"fieldtype": "Table",
"hidden": 1,
"label": "Communications",
"options": "Communication",
"permlevel": 0,
"print_hide": 1
}
],
"icon": "icon-user",
"idx": 1,
"modified": "2015-02-24 17:35:03.821319",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier",
"owner": "Administrator",
],
"icon": "icon-user",
"idx": 1,
"modified": "2015-07-13 05:28:29.121285",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier",
"owner": "Administrator",
"permissions": [
{
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Purchase User"
},
},
{
"amend": 0,
"create": 0,
"delete": 0,
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Purchase Manager",
"submit": 0,
"amend": 0,
"create": 0,
"delete": 0,
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Purchase Manager",
"submit": 0,
"write": 0
},
},
{
"amend": 0,
"create": 1,
"delete": 1,
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Purchase Master Manager",
"share": 1,
"submit": 0,
"amend": 0,
"create": 1,
"delete": 1,
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Purchase Master Manager",
"share": 1,
"submit": 0,
"write": 1
},
},
{
"apply_user_permissions": 1,
"permlevel": 0,
"read": 1,
"role": "Material User"
},
"apply_user_permissions": 1,
"permlevel": 0,
"read": 1,
"role": "Stock User"
},
{
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Material Manager"
},
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Stock Manager"
},
{
"apply_user_permissions": 1,
"permlevel": 0,
"read": 1,
"apply_user_permissions": 1,
"permlevel": 0,
"read": 1,
"role": "Accounts User"
},
},
{
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager"
}
],
"search_fields": "supplier_name, supplier_type",
],
"search_fields": "supplier_name, supplier_type",
"title_field": "supplier_name"
}
}

View File

@@ -660,7 +660,7 @@
"icon": "icon-shopping-cart",
"idx": 1,
"is_submittable": 1,
"modified": "2015-06-15 15:39:08.954248",
"modified": "2015-07-13 05:28:30.252636",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Quotation",
@@ -723,7 +723,7 @@
"print": 1,
"read": 1,
"report": 1,
"role": "Material User",
"role": "Stock User",
"submit": 0,
"write": 0
},

View File

@@ -0,0 +1,3 @@
Leave change log files in this folder for user release notes.
(this file is just a place holder, don't delete it)

View File

@@ -0,0 +1,8 @@
- 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.
- Lead status will be changed to 'Opportunity' when Lead converted to Opportunity
- Amount in Journal Entry list view
- Currency exchange rate is now automatically fetched from fixer.io, instead of jsonrates.com
- Item image is now available in Sales / Purchase Invoice

View File

@@ -0,0 +1,3 @@
- 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,4 @@
- Mode of Payment added to POS Profile
- Expired Batch is not allowed in stock entry of type manufacturing / repack
- Validate item rate against reference document with tolerance 0.009
- Set Customer name in opportunity as per company name in lead

View File

@@ -0,0 +1,8 @@
- Customer's credit days based on fixed days / last day of the next month **[Sponsored by McLean Images](http://www.mcleans.net.au)**
- Production Order is not allowed against Item Template (for Variants)
- Currency symbol fixed for outstanding amount and advance amount field in Sales Invoice
- A Contact can be linked to Customer, Supplier and Sales partner at the same time
- Validation added to prevent task being closed with open dependent tasks
- Blocked stock transactions against an expired batch
- Added Employees in Newsletter List
- Link Address to Customer / Supplier / Lead, based on logged-in user, if created in portal

View File

@@ -0,0 +1,9 @@
- New help videos for Selling, Buying, Human Resource, Manufacturing and Buying
- Role rename: **Material User** is now **Stock User**
- Role rename: **Material Manager** is now **Stock Manager**
- Role rename: **Material Master Manager** is now **Item Manager**
- Fixed inconsistent visibility of 'Add to Cart' button
- Use Customer's Price List in Shopping Cart
- Fixed Address creation from Shopping Cart
- Display images in website's Item and Item List pages when the filename has paranthesis in its name

View File

@@ -73,6 +73,11 @@ def get_data():
"label": _("Setup"),
"icon": "icon-cog",
"items": [
{
"type": "doctype",
"name": "Company",
"description": _("Company (not Customer or Supplier) master.")
},
{
"type": "doctype",
"name": "Fiscal Year",

View File

@@ -60,7 +60,7 @@ def get_data():
"items": [
{
"type": "doctype",
"name": "Salary Manager",
"name": "Process Payroll",
"label": _("Process Payroll"),
"description":_("Generate Salary Slips"),
"hide_count": True

View File

@@ -15,8 +15,12 @@ def get_data():
"type": "help",
"label": _("Setup Wizard"),
"youtube_id": "oIOf_zCFWKQ"
}
},
{
"type": "help",
"label": _("Customizing Forms"),
"youtube_id": "pJhL9mmxV_U"
},
]
},
@@ -93,6 +97,16 @@ def get_data():
"label": _("Customer and Supplier"),
"youtube_id": "anoGi_RpQ20"
},
{
"type": "help",
"label": _("Sales Order to Payment"),
"youtube_id": "7AMq4lqkN4A"
},
{
"type": "help",
"label": _("Point-of-Sale"),
"youtube_id": "4WkelWkbP_c"
}
]
},
{
@@ -108,11 +122,6 @@ def get_data():
"label": _("Opening Stock Balance"),
"youtube_id": "0yPgrtfeCTs"
},
{
"type": "help",
"label": _("Item Variants"),
"youtube_id": "OGBETlCzU5o"
},
]
},
{
@@ -123,6 +132,12 @@ def get_data():
"label": _("Customer and Supplier"),
"youtube_id": "anoGi_RpQ20"
},
{
"type": "help",
"label": _("Material Request to Purchase Order"),
"youtube_id": "4TN9kPyfIqM"
},
]
},
{
@@ -133,6 +148,47 @@ def get_data():
"label": _("Bill of Materials"),
"youtube_id": "hDV0c1OeWLo"
},
{
"type": "help",
"label": _("Production Planning Tool"),
"youtube_id": "CzatSl4zJ2Y"
},
{
"type": "help",
"label": _("Production Order"),
"youtube_id": "ZotgLyp2YFY"
},
]
}
},
{
"label": _("Human Resource"),
"items": [
{
"type": "help",
"label": _("Setting up Employees"),
"youtube_id": "USfIUdZlUhw"
},
{
"type": "help",
"label": _("Leave Management"),
"youtube_id": "fc0p_AXebc8"
},
{
"type": "help",
"label": _("Expense Claims"),
"youtube_id": "5SZHJF--ZFY"
},
]
},
{
"label": _("Projects"),
"items": [
{
"type": "help",
"label": _("Managing Projects"),
"youtube_id": "egxIGwtoKI4"
},
]
},
]

View File

@@ -144,7 +144,7 @@ def get_data():
},
{
"type": "doctype",
"name": "Sales BOM",
"name": "Product Bundle",
"description": _("Bundle items at time of sale."),
},
{

View File

@@ -110,43 +110,7 @@ def get_data():
"description": _("Setup SMS gateway settings")
},
]
},
{
"label": _("Masters"),
"icon": "icon-star",
"items": [
{
"type": "doctype",
"name": "Company",
"description": _("Company (not Customer or Supplier) master.")
},
{
"type": "doctype",
"name": "Item",
"description": _("Item master.")
},
{
"type": "doctype",
"name": "Customer",
"description": _("Customer master.")
},
{
"type": "doctype",
"name": "Supplier",
"description": _("Supplier master.")
},
{
"type": "doctype",
"name": "Contact",
"description": _("Contact master.")
},
{
"type": "doctype",
"name": "Address",
"description": _("Address master.")
},
]
},
}
]
for module, label, icon in (

View File

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

View File

@@ -194,7 +194,7 @@ def bom(doctype, txt, searchfield, start, page_len, filters):
and tabBOM.is_active=1
and tabBOM.%(key)s like "%(txt)s"
%(fcond)s %(mcond)s
limit %(start)s, %(page_len)s """ % {'key': searchfield, 'txt': "%%%s%%" % txt,
limit %(start)s, %(page_len)s """ % {'key': searchfield, 'txt': "%%%s%%" % frappe.db.escape(txt),
'fcond': get_filters_cond(doctype, filters, conditions),
'mcond':get_match_cond(doctype), 'start': start, 'page_len': page_len})
@@ -207,7 +207,7 @@ def get_project_name(doctype, txt, searchfield, start, page_len, filters):
where `tabProject`.status not in ("Completed", "Cancelled")
and %(cond)s `tabProject`.name like "%(txt)s" %(mcond)s
order by `tabProject`.name asc
limit %(start)s, %(page_len)s """ % {'cond': cond,'txt': "%%%s%%" % txt,
limit %(start)s, %(page_len)s """ % {'cond': cond,'txt': "%%%s%%" % frappe.db.escape(txt),
'mcond':get_match_cond(doctype),'start': start, 'page_len': page_len})
def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len, filters):
@@ -229,9 +229,10 @@ def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len,
}, { "start": start, "page_len": page_len, "txt": ("%%%s%%" % txt) })
def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
if not filters.get("posting_date"):
filters["posting_date"] = nowdate()
cond = ""
if filters.get("posting_date"):
cond = "and (ifnull(batch.expiry_date, '')='' or batch.expiry_date >= %(posting_date)s)"
batch_nos = None
args = {
'item_code': filters.get("item_code"),
@@ -251,23 +252,23 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
and sle.warehouse = %(warehouse)s
and sle.batch_no like %(txt)s
and batch.docstatus < 2
and (ifnull(batch.expiry_date, '')='' or batch.expiry_date >= %(posting_date)s)
{0}
{match_conditions}
group by batch_no having sum(sle.actual_qty) > 0
order by batch.expiry_date, sle.batch_no desc
limit %(start)s, %(page_len)s""".format(match_conditions=get_match_cond(doctype)), args)
limit %(start)s, %(page_len)s""".format(cond, match_conditions=get_match_cond(doctype)), args)
if batch_nos:
return batch_nos
else:
return frappe.db.sql("""select name, expiry_date from `tabBatch`
return frappe.db.sql("""select name, expiry_date from `tabBatch` batch
where item = %(item_code)s
and name like %(txt)s
and docstatus < 2
and (ifnull(expiry_date, '')='' or expiry_date >= %(posting_date)s)
{0}
{match_conditions}
order by expiry_date, name desc
limit %(start)s, %(page_len)s""".format(match_conditions=get_match_cond(doctype)), args)
limit %(start)s, %(page_len)s""".format(cond, match_conditions=get_match_cond(doctype)), args, debug=1)
def get_account_list(doctype, txt, searchfield, start, page_len, filters):
filter_list = []

View File

@@ -33,11 +33,13 @@ def manage_recurring_documents(doctype, next_date=None, commit=True):
next_date = next_date or nowdate()
date_field = date_field_map[doctype]
condition = " and ifnull(status, '') != 'Stopped'" if doctype in ("Sales Order", "Purchase Order") else ""
recurring_documents = frappe.db.sql("""select name, recurring_id
from `tab{}` where ifnull(is_recurring, 0)=1
and docstatus=1 and next_date='{}'
and next_date <= ifnull(end_date, '2199-12-31')""".format(doctype, next_date))
from `tab{0}` where ifnull(is_recurring, 0)=1
and docstatus=1 and next_date=%s
and next_date <= ifnull(end_date, '2199-12-31') {1}""".format(doctype, condition), next_date)
exception_list = []
for ref_document, recurring_id in recurring_documents:
@@ -124,7 +126,7 @@ def send_notification(new_rv):
frappe.sendmail(new_rv.notification_email_address,
subject= _("New {0}: #{1}").format(new_rv.doctype, new_rv.name),
message = _("Please find attached {0} #{1}").format(new_rv.doctype, new_rv.name),
attachments = [frappe.attach_print(new_rv.doctype, new_rv.name, file_name=new_rv.name)])
attachments = [frappe.attach_print(new_rv.doctype, new_rv.name, file_name=new_rv.name, print_format=new_rv.recurring_print_format)])
def notify_errors(doc, doctype, party, owner):
from frappe.utils.user import get_system_managers

View File

@@ -171,9 +171,6 @@ class SellingController(StockController):
frappe.throw(_("Row {0}: Qty is mandatory").format(d.idx))
if self.doctype == "Sales Order":
if (frappe.db.get_value("Item", d.item_code, "is_stock_item") == 'Yes' or
self.has_sales_bom(d.item_code)) and not d.warehouse:
frappe.throw(_("Reserved Warehouse required for stock Item {0} in row {1}").format(d.item_code, d.idx))
reserved_warehouse = d.warehouse
if flt(d.qty) > flt(d.delivered_qty):
reserved_qty_for_main_item = flt(d.qty) - flt(d.delivered_qty)
@@ -191,7 +188,7 @@ class SellingController(StockController):
else:
reserved_qty_for_main_item = -flt(d.qty)
if self.has_sales_bom(d.item_code):
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:
# the packing details table's qty is already multiplied with parent's qty
@@ -221,8 +218,8 @@ class SellingController(StockController):
}))
return il
def has_sales_bom(self, item_code):
return frappe.db.sql("""select name from `tabSales BOM`
def has_product_bundle(self, item_code):
return frappe.db.sql("""select name from `tabProduct Bundle`
where new_item_code=%s and docstatus != 2""", item_code)
def get_already_delivered_qty(self, dn, so, so_detail):

View File

@@ -29,7 +29,7 @@
"fieldtype": "Data",
"in_filter": 1,
"in_list_view": 0,
"label": "Contact Name",
"label": "Person Name",
"oldfieldname": "lead_name",
"oldfieldtype": "Data",
"permlevel": 0,
@@ -344,7 +344,7 @@
],
"icon": "icon-user",
"idx": 1,
"modified": "2015-04-02 15:13:02.621854",
"modified": "2015-07-03 03:26:18.579905",
"modified_by": "Administrator",
"module": "CRM",
"name": "Lead",

View File

@@ -75,8 +75,7 @@ class Lead(SellingController):
return frappe.db.get_value("Customer", {"lead_name": self.name})
def has_opportunity(self):
return frappe.db.get_value("Opportunity", {"lead": self.name, "docstatus": 1,
"status": ["!=", "Lost"]})
return frappe.db.get_value("Opportunity", {"lead": self.name, "status": ["!=", "Lost"]})
@frappe.whitelist()
def make_customer(source_name, target_doc=None):

View File

@@ -32,6 +32,7 @@
"default": "0",
"fieldname": "total_subscribers",
"fieldtype": "Int",
"in_list_view": 1,
"label": "Total Subscribers",
"permlevel": 0,
"precision": "",
@@ -45,7 +46,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-03-18 08:08:37.692367",
"modified": "2015-07-15 07:18:30.094155",
"modified_by": "Administrator",
"module": "CRM",
"name": "Newsletter List",

View File

@@ -12,8 +12,8 @@ from email.utils import parseaddr
class NewsletterList(Document):
def onload(self):
singles = [d.name for d in frappe.db.get_all("DocType", "name", {"issingle": 1})]
self.get("__onload").import_types = [d.parent \
for d in frappe.db.get_all("DocField", "parent", {"options": "Email"}) if d.parent not in singles]
self.get("__onload").import_types = [{"value": d.parent, "label": "{0} ({1})".format(d.parent, d.label)} \
for d in frappe.db.get_all("DocField", ("parent", "label"), {"options": "Email"}) if d.parent not in singles]
def import_from(self, doctype):
"""Extract email ids from given doctype and add them to the current list"""

View File

@@ -79,7 +79,8 @@ class Opportunity(TransactionBase):
if self.customer:
self.customer_name = frappe.db.get_value("Customer", self.customer, "customer_name")
elif self.lead:
self.customer_name = frappe.db.get_value("Lead", self.lead, "lead_name")
lead_name, company_name = frappe.db.get_value("Lead", self.lead, ["lead_name", "company_name"])
self.customer_name = company_name or lead_name
def get_cust_address(self,name):
details = frappe.db.sql("""select customer_name, address, territory, customer_group

View File

@@ -5,7 +5,7 @@ app_publisher = "Frappe Technologies Pvt. Ltd. and Contributors"
app_description = "Open Source Enterprise Resource Planning for Small and Midsized Organizations"
app_icon = "icon-th"
app_color = "#e74c3c"
app_version = "5.0.28"
app_version = "5.2.0"
error_report_email = "support@erpnext.com"
@@ -25,8 +25,13 @@ on_logout = "erpnext.shopping_cart.utils.clear_cart_count"
# website
update_website_context = "erpnext.shopping_cart.utils.update_website_context"
my_account_context = "erpnext.shopping_cart.utils.update_my_account_context"
email_append_to = ["Job Applicant", "Opportunity", "Issue"]
calendars = ["Task", "Production Order", "Time Log", "Leave Application"]
website_generators = ["Item Group", "Item", "Sales Partner"]
website_context = {
"favicon": "/assets/erpnext/images/favicon.png",
"splash_image": "/assets/erpnext/images/splash.png"
@@ -52,14 +57,10 @@ dump_report_map = "erpnext.startup.report_data_map.data_map"
before_tests = "erpnext.setup.utils.before_tests"
website_generators = ["Item Group", "Item", "Sales Partner"]
standard_queries = {
"Customer": "erpnext.selling.doctype.customer.customer.get_customer_list"
}
communication_covert_to = ["Lead", "Issue", "Job Application"]
doc_events = {
"Stock Entry": {
"on_submit": "erpnext.stock.doctype.material_request.material_request.update_completed_and_requested_qty",
@@ -78,8 +79,10 @@ doc_events = {
}
scheduler_events = {
"hourly": [
"erpnext.controllers.recurring_document.create_recurring_documents"
],
"daily": [
"erpnext.controllers.recurring_document.create_recurring_documents",
"erpnext.stock.reorder_item.reorder_item",
"erpnext.setup.doctype.email_digest.email_digest.send",
"erpnext.support.doctype.issue.issue.auto_close_tickets",
@@ -104,4 +107,3 @@ get_translated_dict = {
("page", "setup-wizard"): "frappe.geo.country_info.get_translated_dict",
("doctype", "Global Defaults"): "frappe.geo.country_info.get_translated_dict"
}

View File

@@ -290,6 +290,7 @@
"label": "Company Email",
"oldfieldname": "company_email",
"oldfieldtype": "Data",
"options": "Email",
"permlevel": 0,
"reqd": 0
},
@@ -385,6 +386,7 @@
"fieldname": "personal_email",
"fieldtype": "Data",
"label": "Personal Email",
"options": "Email",
"permlevel": 0
},
{
@@ -674,7 +676,7 @@
],
"icon": "icon-user",
"idx": 1,
"modified": "2015-02-20 05:02:14.205144",
"modified": "2015-07-09 02:25:20.987412",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee",

View File

@@ -45,6 +45,10 @@ class Employee(Document):
if self.user_id:
self.validate_for_enabled_user_id()
self.validate_duplicate_user_id()
else:
existing_user_id = frappe.db.get_value("Employee", self.name, "user_id")
if existing_user_id:
frappe.permissions.remove_user_permission("Employee", self.name, existing_user_id)
def on_update(self):
if self.user_id:

View File

@@ -29,7 +29,7 @@
],
"icon": "icon-flag",
"idx": 1,
"modified": "2015-04-19 06:47:51.860833",
"modified": "2015-07-13 04:46:38.897484",
"modified_by": "Administrator",
"module": "HR",
"name": "Expense Claim Type",
@@ -55,7 +55,7 @@
"print": 0,
"read": 1,
"report": 0,
"role": "All",
"role": "Employee",
"share": 0,
"write": 0
}

View File

@@ -1,30 +1,44 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
var display_activity_log = function(msg) {
cur_frm.cscript.display_activity_log = function(msg) {
if(!cur_frm.ss_html)
cur_frm.ss_html = $a(cur_frm.fields_dict['activity_log'].wrapper,'div');
cur_frm.ss_html.innerHTML =
'<div class="padding"><h4>'+__("Activity Log:")+'</h4>'+msg+'</div>';
if(msg) {
cur_frm.ss_html.innerHTML =
'<div class="padding"><h4>'+__("Activity Log:")+'</h4>'+msg+'</div>';
} else {
cur_frm.ss_html.innerHTML = "";
}
}
//Create salary slip
//-----------------------
cur_frm.cscript.create_salary_slip = function(doc, cdt, cdn) {
cur_frm.cscript.display_activity_log("");
var callback = function(r, rt){
if (r.message)
display_activity_log(r.message);
cur_frm.cscript.display_activity_log(r.message);
}
return $c('runserverobj', args={'method':'create_sal_slip','docs':doc},callback);
}
cur_frm.cscript.submit_salary_slip = function(doc, cdt, cdn) {
cur_frm.cscript.display_activity_log("");
var check = confirm(__("Do you really want to Submit all Salary Slip for month {0} and year {1}", [doc.month, doc.fiscal_year]));
if(check){
// clear all in locals
if(locals["Salary Slip"]) {
$.each(locals["Salary Slip"], function(name, d) {
frappe.model.remove_from_locals("Salary Slip", name);
});
}
var callback = function(r, rt){
if (r.message)
display_activity_log(r.message);
cur_frm.cscript.display_activity_log(r.message);
}
return $c('runserverobj', args={'method':'submit_salary_slip','docs':doc},callback);
}
}
@@ -45,6 +59,6 @@ cur_frm.cscript.make_jv = function(doc, dt, dn) {
}
frappe.ui.form.on("Salary Manager", "refresh", function(frm) {
frappe.ui.form.on("Process Payroll", "refresh", function(frm) {
frm.disable_save();
});
});

View File

@@ -154,10 +154,10 @@
"icon": "icon-cog",
"idx": 1,
"issingle": 1,
"modified": "2015-06-05 11:33:00.152362",
"modified": "2015-07-07 07:16:02.380839",
"modified_by": "Administrator",
"module": "HR",
"name": "Salary Manager",
"name": "Process Payroll",
"owner": "Administrator",
"permissions": [
{

View File

@@ -8,7 +8,7 @@ from frappe import _
from frappe.model.document import Document
class SalaryManager(Document):
class ProcessPayroll(Document):
def get_emp_list(self):
"""
@@ -101,7 +101,7 @@ class SalaryManager(Document):
log = "<p>No employee for the above selected criteria OR salary slip already created</p>"
if ss_list:
log = "<b>Salary Slip Created For</b>\
<br><br>%s" % '<br>'.join(ss_list)
<br><br>%s" % '<br>'.join(self.format_as_links(ss_list))
return log
@@ -144,7 +144,7 @@ class SalaryManager(Document):
else:
all_ss = [d[0] for d in all_ss]
submitted_ss = list(set(all_ss) - set(not_submitted_ss))
submitted_ss = self.format_as_links(list(set(all_ss) - set(not_submitted_ss)))
if submitted_ss:
mail_sent_msg = self.send_email and " (Mail has been sent to the employee)" or ""
log = """
@@ -164,6 +164,9 @@ class SalaryManager(Document):
"""% ('<br>'.join(not_submitted_ss))
return log
def format_as_links(self, ss_list):
return ['<a href="#Form/Salary Slip/{0}">{0}</a>'.format(s) for s in ss_list]
def get_total_salary(self):
"""

View File

@@ -1 +0,0 @@
Tool to issue monthly Salary Slips to all Employees.

View File

@@ -1,21 +0,0 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Frappe Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
from frappe import ValidationError
class SalarySlipExistsError(ValidationError): pass

View File

@@ -49,7 +49,7 @@ class SalarySlip(TransactionBase):
if not self.month:
self.month = "%02d" % getdate(nowdate()).month
m = frappe.get_doc('Salary Manager').get_month_details(self.fiscal_year, self.month)
m = frappe.get_doc('Process Payroll').get_month_details(self.fiscal_year, self.month)
holidays = self.get_holidays_for_employee(m)
if not cint(frappe.db.get_value("HR Settings", "HR Settings",

View File

@@ -31,7 +31,7 @@
"fieldname": "d_depends_on_lwp",
"fieldtype": "Check",
"in_list_view": 0,
"label": "Depends on LWP",
"label": "Depends on Leave Without Pay",
"permlevel": 0,
"print_hide": 1
},
@@ -46,7 +46,7 @@
],
"idx": 1,
"istable": 1,
"modified": "2015-03-03 12:41:04.505378",
"modified": "2015-07-07 07:13:11.919941",
"modified_by": "Administrator",
"module": "HR",
"name": "Salary Slip Deduction",

View File

@@ -31,7 +31,7 @@
"fieldname": "e_depends_on_lwp",
"fieldtype": "Check",
"in_list_view": 0,
"label": "Depends on LWP",
"label": "Depends on Leave Without Pay",
"permlevel": 0,
"print_hide": 1
},
@@ -46,7 +46,7 @@
],
"idx": 1,
"istable": 1,
"modified": "2015-03-03 12:42:49.087748",
"modified": "2015-07-07 07:13:24.833881",
"modified_by": "Administrator",
"module": "HR",
"name": "Salary Slip Earning",

View File

@@ -75,8 +75,20 @@ def get_conditions(filters):
filters["month"] = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov",
"Dec"].index(filters["month"]) + 1
from frappe.model.document import Document
fiscal_years = frappe.get_doc("Fiscal Year",filters["fiscal_year"])
import datetime
year_start = fiscal_years.year_start_date.strftime("%Y")
year_end = fiscal_years.year_end_date.strftime("%Y")
dt_test = datetime.datetime.strptime(year_end + "-" + str(100+int(filters["month"]))[2:3] + "-01", "%Y-%m-%d")
date_test = datetime.date(dt_test.year, dt_test.month, dt_test.day)
if date_test > fiscal_years.year_end_date:
year_target = year_start
else:
year_target = year_end
from calendar import monthrange
filters["total_days_in_month"] = monthrange(cint(filters["fiscal_year"].split("-")[-1]),
filters["total_days_in_month"] = monthrange(cint(year_target),
filters["month"])[1]
conditions = " and month(att_date) = %(month)s and fiscal_year = %(fiscal_year)s"

View File

@@ -61,7 +61,7 @@ var get_bom_material_detail= function(doc, cdt, cdn) {
var d = locals[cdt][cdn];
if (d.item_code) {
return frappe.call({
doc: cur_frm.doc,
doc: doc,
method: "get_bom_material_detail",
args: {
'item_code': d.item_code,
@@ -234,5 +234,3 @@ frappe.ui.form.on("BOM", "with_operations", function(frm) {
cur_frm.cscript.image = function() {
refresh_field("image_view");
}

View File

@@ -12,7 +12,7 @@
"fieldname": "item",
"fieldtype": "Link",
"in_filter": 1,
"in_list_view": 0,
"in_list_view": 1,
"label": "Item",
"oldfieldname": "item",
"oldfieldtype": "Link",
@@ -54,7 +54,7 @@
"fieldname": "is_active",
"fieldtype": "Check",
"hidden": 0,
"in_list_view": 0,
"in_list_view": 1,
"label": "Is Active",
"no_copy": 1,
"oldfieldname": "is_active",
@@ -67,7 +67,7 @@
"default": "1",
"fieldname": "is_default",
"fieldtype": "Check",
"in_list_view": 0,
"in_list_view": 1,
"label": "Is Default",
"no_copy": 1,
"oldfieldname": "is_default",
@@ -279,7 +279,7 @@
"is_submittable": 1,
"issingle": 0,
"istable": 0,
"modified": "2015-03-03 14:22:44.725097",
"modified": "2015-06-26 02:02:30.705279",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "BOM",

View File

@@ -181,15 +181,12 @@ class BOM(Document):
if item.default_bom != self.name:
item.default_bom = self.name
item.save()
else:
if not self.is_active:
frappe.db.set(self, "is_default", 0)
item = frappe.get_doc("Item", self.item)
if item.default_bom == self.name:
item.default_bom = None
item.save()
frappe.db.set(self, "is_default", 0)
item = frappe.get_doc("Item", self.item)
if item.default_bom == self.name:
item.default_bom = None
item.save()
def clear_operations(self):
if not self.with_operations:

View File

@@ -186,15 +186,26 @@ $.extend(cur_frm.cscript, {
},
bom_no: function() {
return this.frm.call({
doc: this.frm.doc,
method: "set_production_order_operations"
});
if (this.frm.doc.track_operations) {
return this.frm.call({
doc: this.frm.doc,
method: "set_production_order_operations"
});
}
},
qty: function() {
frappe.ui.form.trigger("Production Order", 'bom_no')
},
track_operations: function(doc) {
if (doc.track_operations) {
frappe.ui.form.trigger("Production Order", 'bom_no')
}
else {
doc.operations =[];
}
},
show_time_logs: function(doc, cdt, cdn) {
var child = locals[cdt][cdn]
@@ -250,7 +261,8 @@ cur_frm.cscript['Update Finished Goods'] = function() {
cur_frm.fields_dict['production_item'].get_query = function(doc) {
return {
filters:[
['Item', 'is_pro_applicable', '=', 'Yes']
['Item', 'is_pro_applicable', '=', 'Yes'],
['Item', 'has_variants', '=', 'No']
]
}
}

View File

@@ -73,6 +73,14 @@
"label": "Use Multi-Level BOM",
"permlevel": 0
},
{
"default": "1",
"fieldname": "track_operations",
"fieldtype": "Check",
"label": "Track Operations",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "column_break1",
"fieldtype": "Column Break",
@@ -207,7 +215,7 @@
"read_only": 1
},
{
"depends_on": "",
"depends_on": "track_operations",
"fieldname": "operations_section",
"fieldtype": "Section Break",
"label": "Operations",
@@ -216,6 +224,7 @@
"precision": ""
},
{
"depends_on": "",
"fieldname": "operations",
"fieldtype": "Table",
"label": "Operations",
@@ -225,6 +234,7 @@
"read_only": 1
},
{
"depends_on": "track_operations",
"fieldname": "section_break_22",
"fieldtype": "Section Break",
"label": "Operation Cost",
@@ -358,7 +368,7 @@
"idx": 1,
"in_create": 0,
"is_submittable": 1,
"modified": "2015-04-13 02:44:17.319988",
"modified": "2015-07-13 05:28:23.259016",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Production Order",
@@ -385,7 +395,7 @@
"permlevel": 0,
"read": 1,
"report": 1,
"role": "Material User"
"role": "Stock User"
}
],
"title_field": "production_item"

View File

@@ -30,6 +30,7 @@ class ProductionOrder(Document):
validate_status(self.status, ["Draft", "Submitted", "Stopped",
"In Process", "Completed", "Cancelled"])
self.validate_production_item()
if self.bom_no:
validate_bom_no(self.production_item, self.bom_no)
@@ -173,13 +174,17 @@ class ProductionOrder(Document):
def set_production_order_operations(self):
"""Fetch operations from BOM and set in 'Production Order'"""
if not self.bom_no:
return
self.set('operations', [])
operations = frappe.db.sql("""select operation, description, workstation, idx,
hour_rate, time_in_mins, "Pending" as status from `tabBOM Operation`
where parent = %s order by idx""", self.bom_no, as_dict=1)
if operations:
self.track_operations=1
else:
self.track_operations=0
frappe.msgprint(_("Cannot 'track operations' as selected BOM does not have Operations."))
self.set('operations', operations)
self.calculate_time()
@@ -218,14 +223,12 @@ class ProductionOrder(Document):
for i, d in enumerate(self.operations):
self.set_operation_start_end_time(i, d)
if not d.workstation:
continue
time_log = make_time_log(self.name, d.operation, d.planned_start_time, d.planned_end_time,
flt(self.qty) - flt(d.completed_qty), self.project_name, d.workstation, operation_id=d.name)
# validate operating hours if workstation [not mandatory] is specified
self.check_operation_fits_in_working_hours(d)
if d.workstation:
# validate operating hours if workstation [not mandatory] is specified
self.check_operation_fits_in_working_hours(d)
original_start_time = time_log.from_time
while True:
@@ -314,11 +317,18 @@ class ProductionOrder(Document):
def validate_delivery_date(self):
if self.planned_start_date and self.expected_delivery_date \
and getdate(self.expected_delivery_date) < getdate(self.planned_start_date):
frappe.throw(_("Expected Delivery Date must be greater than Planned Start Date."))
frappe.msgprint(_("Expected Delivery Date is lesser than Planned Start Date."))
def delete_time_logs(self):
for time_log in frappe.get_all("Time Log", ["name"], {"production_order": self.name}):
frappe.delete_doc("Time Log", time_log.name)
def validate_production_item(self):
if frappe.db.get_value("Item", self.production_item, "is_pro_applicable")=='No':
frappe.throw(_("Item is not allowed to have Production Order."))
if frappe.db.get_value("Item", self.production_item, "has_variants"):
frappe.throw(_("Production Order cannot be raised against a Item Template"))
@frappe.whitelist()
def get_item_details(item):
@@ -383,7 +393,7 @@ def get_events(start, end, filters=None):
return data
@frappe.whitelist()
def make_time_log(name, operation, from_time, to_time, qty=None, project=None, workstation=None, operation_id=None):
def make_time_log(name, operation, from_time=None, to_time=None, qty=None, project=None, workstation=None, operation_id=None):
time_log = frappe.new_doc("Time Log")
time_log.for_manufacturing = 1
time_log.from_time = from_time

View File

@@ -42,6 +42,15 @@
"reqd": 1,
"width": "100px"
},
{
"default": "",
"fieldname": "planned_start_date",
"fieldtype": "Datetime",
"label": "Planned Start Date",
"permlevel": 0,
"precision": "",
"reqd": 1
},
{
"fieldname": "sales_order",
"fieldtype": "Link",
@@ -104,7 +113,7 @@
],
"idx": 1,
"istable": 1,
"modified": "2015-02-19 01:07:00.936590",
"modified": "2015-07-08 07:12:11.211808",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Production Plan Item",

View File

@@ -1,6 +1,8 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
frappe.require("assets/erpnext/js/utils.js");
cur_frm.cscript.onload = function(doc, cdt, cdn) {
cur_frm.set_value("company", frappe.defaults.get_user_default("company"))
cur_frm.set_value("use_multi_level_bom", 1)
@@ -72,3 +74,7 @@ cur_frm.fields_dict.customer.get_query = function(doc,cdt,cdn) {
cur_frm.fields_dict.sales_orders.grid.get_field("customer").get_query =
cur_frm.fields_dict.customer.get_query;
cur_frm.cscript.planned_start_date = function(doc, cdt, cdn) {
erpnext.utils.copy_value_in_all_row(doc, cdt, cdn, "items", "planned_start_date");
}

View File

@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import cstr, flt, cint, nowdate, now, add_days, comma_and
from frappe.utils import cstr, flt, cint, nowdate, add_days, comma_and
from frappe import msgprint, _
@@ -185,20 +185,22 @@ class ProductionPlanningTool(Document):
"""
item_dict, bom_dict = {}, {}
for d in self.get("items"):
bom_dict.setdefault(d.bom_no, []).append([d.sales_order, flt(d.planned_qty)])
item_dict[(d.item_code, d.sales_order, d.warehouse)] = {
"production_item" : d.item_code,
"sales_order" : d.sales_order,
"qty" : flt(item_dict.get((d.item_code, d.sales_order, d.warehouse),
{}).get("qty")) + flt(d.planned_qty),
"bom_no" : d.bom_no,
"description" : d.description,
"stock_uom" : d.stock_uom,
"company" : self.company,
"wip_warehouse" : "",
"fg_warehouse" : d.warehouse,
"status" : "Draft",
}
if d.bom_no:
bom_dict.setdefault(d.bom_no, []).append([d.sales_order, flt(d.planned_qty)])
if frappe.db.get_value("Item", d.item_code, "is_pro_applicable") == "Yes":
item_dict[(d.item_code, d.sales_order, d.warehouse)] = {
"production_item" : d.item_code,
"sales_order" : d.sales_order,
"qty" : flt(item_dict.get((d.item_code, d.sales_order, d.warehouse),
{}).get("qty")) + flt(d.planned_qty),
"bom_no" : d.bom_no,
"description" : d.description,
"stock_uom" : d.stock_uom,
"company" : self.company,
"wip_warehouse" : "",
"fg_warehouse" : d.warehouse,
"status" : "Draft",
}
return bom_dict, item_dict
def create_production_order(self, items):
@@ -209,8 +211,6 @@ class ProductionPlanningTool(Document):
for key in items:
pro = frappe.new_doc("Production Order")
pro.update(items[key])
pro.planned_start_date = now()
pro.set_production_order_operations()
frappe.flags.mute_messages = True

View File

@@ -100,6 +100,7 @@ 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
erpnext.patches.v5_1.sales_bom_rename
erpnext.patches.v5_0.rename_table_fieldnames
execute:frappe.db.sql("update `tabJournal Entry` set voucher_type='Journal Entry' where ifnull(voucher_type, '')=''")
erpnext.patches.v5_0.is_group
@@ -166,4 +167,13 @@ erpnext.patches.v5_0.portal_fixes
erpnext.patches.v5_0.reset_values_in_tools
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
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
erpnext.patches.v5_1.track_operations
execute:frappe.rename_doc("DocType", "Salary Manager", "Process Payroll", force=True)
erpnext.patches.v5_1.rename_roles
erpnext.patches.v5_1.default_bom

View File

@@ -0,0 +1,19 @@
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

@@ -111,7 +111,6 @@ rename_map = {
["installed_item_details", "items"]
],
"Item": [
["item_variants", "variants"],
["item_reorder", "reorder_levels"],
["uom_conversion_details", "uoms"],
["item_supplier_details", "supplier_items"],
@@ -168,7 +167,7 @@ rename_map = {
["earning_details", "earnings"],
["deduction_details", "deductions"]
],
"Sales BOM": [
"Product Bundle": [
["sales_bom_items", "items"]
],
"SMS Settings": [

View File

@@ -0,0 +1,51 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import frappe
from frappe.website.utils import find_first_image
from frappe.utils import cstr
import re
def execute():
item_details = frappe._dict()
for d in frappe.db.sql("select name, description, image from `tabItem`", as_dict=1):
description = cstr(d.description).strip()
item_details.setdefault(d.name, frappe._dict({
"description": description,
"image": d.image
}))
dt_list= ["Sales Invoice Item","Purchase Invoice Item"]
for dt in dt_list:
frappe.reload_doctype(dt)
records = frappe.db.sql("""select name, item_code, description from `tab{0}`
where ifnull(item_code, '') != '' and description is not null """.format(dt), as_dict=1)
count = 1
for d in records:
if item_details.get(d.item_code) and cstr(d.description) == item_details.get(d.item_code).description:
desc = item_details.get(d.item_code).description
image = item_details.get(d.item_code).image
else:
desc, image = extract_image_and_description(cstr(d.description))
if not image:
item_detail = item_details.get(d.item_code)
if item_detail:
image = item_detail.image
frappe.db.sql("""update `tab{0}` set description = %s, image = %s
where name = %s """.format(dt), (desc, image, d.name))
count += 1
if count % 500 == 0:
frappe.db.commit()
def extract_image_and_description(data):
image_url = find_first_image(data)
desc = data
for tag in ("img", "table", "tr", "td"):
desc = re.sub("\</*{0}[^>]*\>".format(tag), "", desc)
return desc, image_url

View File

View File

@@ -0,0 +1,7 @@
from __future__ import unicode_literals
import frappe
def execute():
frappe.db.sql("""Update `tabItem` as item set default_bom = NULL where
not exists(select name from `tabBOM` as bom where item.default_bom = bom.name and bom.docstatus =1 )""")

View File

@@ -0,0 +1,37 @@
from __future__ import unicode_literals
import frappe
from erpnext.accounts.doctype.gl_entry.gl_entry import update_against_account
def execute():
from_date = "2015-05-01"
for doc in frappe.get_all("Journal Entry",
filters={"creation": (">", from_date), "docstatus": "1"}):
# update in gl_entry
update_against_account("Journal Entry", doc.name)
# update in jv
doc = frappe.get_doc("Journal Entry", doc.name)
doc.set_against_account()
doc.db_update()
for doc in frappe.get_all("Sales Invoice",
filters={"creation": (">", from_date), "docstatus": "1"},
fields=["name", "customer"]):
frappe.db.sql("""update `tabGL Entry` set against=%s
where voucher_type='Sales Invoice' and voucher_no=%s
and credit > 0 and ifnull(party, '')=''""",
(doc.customer, doc.name))
for doc in frappe.get_all("Purchase Invoice",
filters={"creation": (">", from_date), "docstatus": "1"},
fields=["name", "supplier"]):
frappe.db.sql("""update `tabGL Entry` set against=%s
where voucher_type='Purchase Invoice' and voucher_no=%s
and debit > 0 and ifnull(party, '')=''""",
(doc.supplier, doc.name))

View File

@@ -0,0 +1,9 @@
from __future__ import unicode_literals
import frappe
def execute():
for dt in ("Customer", "Customer Group", "Company"):
frappe.reload_doctype(dt, force=True)
frappe.db.sql("""update `tab{0}` set credit_days_based_on='Fixed Days'
where ifnull(credit_days, 0) > 0""".format(dt))

View File

@@ -0,0 +1,9 @@
import frappe
def execute():
if not frappe.db.exists("Role", "Stock User"):
frappe.rename_doc("Role", "Material User", "Stock User")
if not frappe.db.exists("Role", "Stock Manager"):
frappe.rename_doc("Role", "Material Manager", "Stock Manager")
if not frappe.db.exists("Role", "Stock Manager"):
frappe.rename_doc("Role", "Material Master Manager", "Item Manager")

View File

@@ -0,0 +1,12 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
tables = frappe.db.sql_list("show tables")
for old_dt, new_dt in [["Sales BOM Item", "Product Bundle Item"],
["Sales BOM", "Product Bundle"]]:
if "tab"+new_dt not in tables:
frappe.rename_doc("DocType", old_dt, new_dt, force=True)

View File

@@ -0,0 +1,8 @@
from __future__ import unicode_literals
import frappe
def execute():
frappe.reload_doctype("Production Order")
frappe.db.sql("""Update `tabProduction Order` as po set track_operations=1 where
exists(select name from `tabProduction Order Operation` as po_operation where po_operation.parent = po.name )""")

View File

@@ -26,22 +26,29 @@ frappe.ui.form.on("Project Task", "edit_task", function(frm, doctype, name) {
// show tasks
cur_frm.cscript.refresh = function(doc) {
if(!doc.__islocal) {
cur_frm.add_custom_button(__("Gantt Chart"), function() {
frappe.route_options = {"project": doc.name, "start": doc.expected_start_date, "end": doc.expected_end_date};
frappe.set_route("Gantt", "Task");
}, "icon-tasks", true);
cur_frm.add_custom_button(__("Tasks"), function() {
frappe.route_options = {"project": doc.name}
frappe.set_route("List", "Task");
}, "icon-list", true);
cur_frm.add_custom_button(__("Time Logs"), function() {
frappe.route_options = {"project": doc.name}
frappe.set_route("List", "Time Log");
}, "icon-list", true);
cur_frm.add_custom_button(__("Expense Claims"), function() {
frappe.route_options = {"project": doc.name}
frappe.set_route("List", "Expense Claim");
}, "icon-list", true);
if(frappe.model.can_read("Task")) {
cur_frm.add_custom_button(__("Gantt Chart"), function() {
frappe.route_options = {"project": doc.name, "start": doc.expected_start_date, "end": doc.expected_end_date};
frappe.set_route("Gantt", "Task");
}, "icon-tasks", true);
cur_frm.add_custom_button(__("Tasks"), function() {
frappe.route_options = {"project": doc.name}
frappe.set_route("List", "Task");
}, "icon-list", true);
}
if(frappe.model.can_read("Time Log")) {
cur_frm.add_custom_button(__("Time Logs"), function() {
frappe.route_options = {"project": doc.name}
frappe.set_route("List", "Time Log");
}, "icon-list", true);
}
if(frappe.model.can_read("Expense Claim")) {
cur_frm.add_custom_button(__("Expense Claims"), function() {
frappe.route_options = {"project": doc.name}
frappe.set_route("List", "Expense Claim");
}, "icon-list", true);
}
}
}
@@ -56,5 +63,5 @@ cur_frm.fields_dict['sales_order'].get_query = function(doc) {
filters:{
'project_name': doc.name
}
}
}
}

View File

@@ -35,6 +35,7 @@ class Project(Document):
def validate(self):
self.validate_dates()
self.sync_tasks()
self.tasks = []
def validate_dates(self):
if self.expected_start_date and self.expected_end_date:
@@ -45,6 +46,8 @@ class Project(Document):
"""sync tasks and remove table"""
if self.flags.dont_sync_tasks: return
task_added_or_deleted = False
task_names = []
for t in self.tasks:
if t.task_id:
@@ -52,6 +55,7 @@ class Project(Document):
else:
task = frappe.new_doc("Task")
task.project = self.name
task_added_or_deleted = True
task.update({
"subject": t.title,
@@ -69,17 +73,22 @@ class Project(Document):
# delete
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()
self.tasks = []
def update_project(self):
self.update_percent_complete()
self.update_costing()
def update_percent_complete(self):
total = frappe.db.sql("""select count(*) from tabTask where project=%s""",
self.name)[0][0]
total = frappe.db.sql("""select count(*) from tabTask where project=%s""", self.name)[0][0]
if total:
completed = frappe.db.sql("""select count(*) from tabTask where
project=%s and status in ('Closed', 'Cancelled')""", self.name)[0][0]
frappe.db.set_value("Project", self.name, "percent_complete",
int(float(completed) / total * 100))
self.percent_complete = flt(completed) / total * 100
def update_costing(self):
total_cost = frappe.db.sql("""select sum(total_costing_amount) as costing_amount,

View File

@@ -5,3 +5,4 @@ from __future__ import unicode_literals
import frappe
test_records = frappe.get_test_records('Project')
test_ignore = ["Sales Order"]

View File

@@ -28,10 +28,7 @@ class Task(Document):
def validate(self):
self.validate_dates()
if self.status!=self.get_db_value("status") and self.status == "Closed":
from frappe.desk.form.assign_to import clear
clear(self.doctype, self.name)
self.validate_status()
def validate_dates(self):
if self.exp_start_date and self.exp_end_date and getdate(self.exp_start_date) > getdate(self.exp_end_date):
@@ -40,18 +37,20 @@ class Task(Document):
if self.act_start_date and self.act_end_date and getdate(self.act_start_date) > getdate(self.act_end_date):
frappe.throw(_("'Actual Start Date' can not be greater than 'Actual End Date'"))
def validate_status(self):
if self.status!=self.get_db_value("status") and self.status == "Closed":
for d in self.depends_on:
if frappe.db.get_value("Task", d.task, "status") != "Closed":
frappe.throw(_("Cannot close task as its dependant task {0} is not closed.").format(d.task))
from frappe.desk.form.assign_to import clear
clear(self.doctype, self.name)
def on_update(self):
self.check_recursion()
self.reschedule_dependent_tasks()
self.update_percentage()
self.update_project()
def update_percentage(self):
"""update percent complete in project"""
if self.project and not self.flags.from_project:
project = frappe.get_doc("Project", self.project)
project.run_method("update_percent_complete")
def update_total_expense_claim(self):
self.total_expense_claim = frappe.db.sql("""select sum(total_sanctioned_amount) from `tabExpense Claim`
where project = %s and task = %s and approval_status = "Approved" and docstatus=1""",(self.project, self.name))
@@ -70,10 +69,10 @@ class Task(Document):
self.act_end_date= tl.end_date
def update_project(self):
if self.project and frappe.db.exists("Project", self.project):
if self.project and not self.flags.from_project:
project = frappe.get_doc("Project", self.project)
project.flags.dont_sync_tasks = True
project.update_costing()
project.update_project()
project.save()
def check_recursion(self):
@@ -141,7 +140,7 @@ def get_project(doctype, txt, searchfield, start, page_len, filters):
%(mcond)s
order by name
limit %(start)s, %(page_len)s """ % {'key': searchfield,
'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype),
'txt': "%%%s%%" % frappe.db.escape(txt), 'mcond':get_match_cond(doctype),
'start': start, 'page_len': page_len})

View File

@@ -42,7 +42,7 @@ frappe.ui.form.on("Time Log", "before_save", function(frm) {
frappe.ui.form.on("Time Log", "to_time", function(frm) {
if(frm._setting_hours) return;
frm.set_value("hours", moment(cur_frm.doc.to_time).diff(moment(cur_frm.doc.from_time),
"hours"));
"minutes") / 60);
});
@@ -98,5 +98,5 @@ cur_frm.fields_dict['task'].get_query = function(doc) {
filters:{
'project': doc.project
}
}
}
}

View File

@@ -73,18 +73,20 @@ class TimeLog(Document):
def validate_overlap_for(self, fieldname):
existing = self.get_overlap_for(fieldname)
if existing:
frappe.throw(_("This Time Log conflicts with {0} for {1}").format(existing.name,
self.meta.get_label(fieldname)), OverlapError)
frappe.throw(_("This Time Log conflicts with {0} for {1} {2}").format(existing.name,
self.meta.get_label(fieldname), self.get(fieldname)), OverlapError)
def get_overlap_for(self, fieldname):
if not self.get(fieldname):
return
existing = frappe.db.sql("""select name, from_time, to_time from `tabTime Log` where `{0}`=%(val)s and
existing = frappe.db.sql("""select name, from_time, to_time from `tabTime Log`
where `{0}`=%(val)s and
(
(from_time between %(from_time)s and %(to_time)s) or
(to_time between %(from_time)s and %(to_time)s) or
(%(from_time)s between from_time and to_time))
(from_time > %(from_time)s and from_time < %(to_time)s) or
(to_time > %(from_time)s and to_time < %(to_time)s) or
(%(from_time)s > from_time and %(from_time)s < to_time) or
(%(from_time)s = from_time and %(to_time)s = to_time))
and name!=%(name)s
and ifnull(task, "")=%(task)s
and docstatus < 2""".format(fieldname),

View File

@@ -17,6 +17,12 @@ frappe.views.calendar["Time Log"] = {
"options": "Workstation",
"label": __("Workstation")
},
{
"fieldtype": "Link",
"fieldname": "employee",
"options": "Employee",
"label": __("Employee")
},
],
get_events_method: "erpnext.projects.doctype.time_log.time_log.get_events"
}
}

View File

@@ -7,6 +7,10 @@ frappe.provide('erpnext');
$(document).bind('toolbar_setup', function() {
frappe.app.name = "ERPNext";
frappe.help_feedback_link = '<p><a class="text-muted" \
href="https://discuss.erpnext.com">Feedback</a></p>'
$('.navbar-home').html('ERPNext');
$('[data-link="docs"]').attr("href", "https://manual.erpnext.com")

View File

@@ -70,16 +70,5 @@ erpnext.stock.StockController = frappe.ui.form.Controller.extend({
frappe.set_route("query-report", "General Ledger");
}, "icon-table");
}
},
copy_account_in_all_row: function(doc, dt, dn, fieldname) {
var d = locals[dt][dn];
if(d[fieldname]){
var cl = doc["items"] || [];
for(var i = 0; i < cl.length; i++) {
if(!cl[i][fieldname]) cl[i][fieldname] = d[fieldname];
}
}
refresh_field("items");
}
});

View File

@@ -14,7 +14,6 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
$.each({
posting_date: today,
due_date: today,
transaction_date: today,
currency: currency,
price_list_currency: currency,
@@ -37,6 +36,16 @@ 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{
filters: [
['Print Format', 'doc_type', '=', cur_frm.doctype],
]
}
});
}
},
onload_post_render: function() {
@@ -245,12 +254,38 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
},
posting_date: function() {
erpnext.get_fiscal_year(this.frm.doc.company, this.frm.doc.posting_date);
var me = this;
if (this.frm.doc.posting_date) {
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",
args: {
"posting_date": me.frm.doc.posting_date,
"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);
}
erpnext.get_fiscal_year(me.frm.doc.company, me.frm.doc.posting_date);
}
})
} else {
erpnext.get_fiscal_year(me.frm.doc.company, me.frm.doc.posting_date);
}
}
},
get_company_currency: function() {
return erpnext.get_currency(this.frm.doc.company);
},
contact_person: function() {
erpnext.utils.get_contact_details(this.frm);
},
currency: function() {
var me = this;
@@ -782,3 +817,5 @@ frappe.ui.form.on(cur_frm.doctype, "discount_amount", function(frm) {
cur_frm.cscript.set_dynamic_labels();
cur_frm.cscript.calculate_taxes_and_totals();
})

View File

@@ -46,7 +46,7 @@ erpnext.feature_setup.feature_dict = {
'Purchase Invoice': {'items':['brand']},
'Quotation': {'items':['brand']},
'Sales Invoice': {'items':['brand']},
'Sales BOM': {'fields':['new_item_brand']},
'Product Bundle': {'fields':['new_item_brand']},
'Sales Order': {'items':['brand']},
'Serial No': {'fields':['brand']}
},
@@ -95,7 +95,7 @@ erpnext.feature_setup.feature_dict = {
'Purchase Voucher': {'items':['item_group']},
'Quotation': {'items':['item_group']},
'Sales Invoice': {'items':['item_group']},
'Sales BOM': {'fields':['serial_no']},
'Product Bundle': {'fields':['serial_no']},
'Sales Order': {'items':['item_group']},
'Serial No': {'fields':['item_group']},
'Sales Partner': {'targets':['item_group']},
@@ -129,7 +129,7 @@ erpnext.feature_setup.feature_dict = {
'base_total', 'base_net_total', 'base_discount_amount', 'base_total_taxes_and_charges'],
'items': ['base_price_list_rate','base_amount','base_rate', 'base_net_rate', 'base_net_amount']
},
'Sales BOM': {'fields':['currency']},
'Product Bundle': {'fields':['currency']},
'Sales Order': {
'fields': ['conversion_rate','currency','base_grand_total','base_in_words','base_rounded_total',
'base_total', 'base_net_total', 'base_discount_amount', 'base_total_taxes_and_charges'],

View File

@@ -401,7 +401,8 @@ erpnext.pos.PointOfSale = Class.extend({
this.with_modes_of_payment(function() {
// prefer cash payment!
var default_mode = me.modes_of_payment.indexOf(__("Cash"))!==-1 ? __("Cash") : undefined;
var default_mode = me.frm.doc.mode_of_payment ? me.frm.doc.mode_of_payment :
me.modes_of_payment.indexOf(__("Cash"))!==-1 ? __("Cash") : undefined;
// show payment wizard
var dialog = new frappe.ui.Dialog({
@@ -449,8 +450,7 @@ erpnext.pos.PointOfSale = Class.extend({
if (is_cash && !dialog.get_value("change")) {
// set to nearest 5
var paid_amount = 5 * Math.ceil(dialog.get_value("total_amount") / 5);
dialog.set_value("paid_amount", paid_amount);
dialog.set_value("paid_amount", dialog.get_value("total_amount"));
dialog.get_input("paid_amount").trigger("change");
}
}).trigger("change");
@@ -486,6 +486,12 @@ erpnext.pos.PointOfSale = Class.extend({
});
erpnext.pos.make_pos_btn = function(frm) {
frm.page.add_menu_item(__("{0} View", [frm.page.current_view_name === "pos" ? "Form" : "Point-of-Sale"]), function() {
erpnext.pos.toggle(frm);
});
if(frm.pos_btn) return;
// Show POS button only if it is enabled from features setup
if (cint(sys_defaults.fs_pos_view)!==1 || frm.doctype==="Material Request") {
return;
@@ -493,7 +499,8 @@ erpnext.pos.make_pos_btn = function(frm) {
if(!frm.pos_btn) {
frm.pos_btn = frm.page.add_action_icon("icon-th", function() {
erpnext.pos.toggle(frm) });
erpnext.pos.toggle(frm);
});
}
if(erpnext.open_as_pos && frm.page.current_view_name !== "pos") {

View File

@@ -131,6 +131,17 @@ $.extend(erpnext.utils, {
}
);
}
},
copy_value_in_all_row: function(doc, dt, dn, table_fieldname, fieldname) {
var d = locals[dt][dn];
if(d[fieldname]){
var cl = doc[table_fieldname] || [];
for(var i = 0; i < cl.length; i++) {
if(!cl[i][fieldname]) cl[i][fieldname] = d[fieldname];
}
}
refresh_field(table_fieldname);
}
});

View File

@@ -1,366 +1,375 @@
{
"allow_import": 1,
"allow_rename": 1,
"autoname": "naming_series:",
"creation": "2013-06-11 14:26:44",
"description": "Buyer of Goods and Services.",
"docstatus": 0,
"doctype": "DocType",
"document_type": "Master",
"allow_import": 1,
"allow_rename": 1,
"autoname": "naming_series:",
"creation": "2013-06-11 14:26:44",
"description": "Buyer of Goods and Services.",
"docstatus": 0,
"doctype": "DocType",
"document_type": "Master",
"fields": [
{
"fieldname": "basic_info",
"fieldtype": "Section Break",
"label": "",
"oldfieldtype": "Section Break",
"options": "icon-user",
"permlevel": 0,
"fieldname": "basic_info",
"fieldtype": "Section Break",
"label": "",
"oldfieldtype": "Section Break",
"options": "icon-user",
"permlevel": 0,
"reqd": 0
},
},
{
"fieldname": "naming_series",
"fieldtype": "Select",
"label": "Series",
"no_copy": 1,
"options": "CUST-",
"permlevel": 0,
"fieldname": "naming_series",
"fieldtype": "Select",
"label": "Series",
"no_copy": 1,
"options": "CUST-",
"permlevel": 0,
"print_hide": 0
},
},
{
"fieldname": "customer_name",
"fieldtype": "Data",
"hidden": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "Full Name",
"no_copy": 1,
"oldfieldname": "customer_name",
"oldfieldtype": "Data",
"permlevel": 0,
"print_hide": 0,
"report_hide": 0,
"reqd": 1,
"fieldname": "customer_name",
"fieldtype": "Data",
"hidden": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "Full Name",
"no_copy": 1,
"oldfieldname": "customer_name",
"oldfieldtype": "Data",
"permlevel": 0,
"print_hide": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 1
},
},
{
"fieldname": "customer_type",
"fieldtype": "Select",
"label": "Type",
"oldfieldname": "customer_type",
"oldfieldtype": "Select",
"options": "\nCompany\nIndividual",
"permlevel": 0,
"fieldname": "customer_type",
"fieldtype": "Select",
"label": "Type",
"oldfieldname": "customer_type",
"oldfieldtype": "Select",
"options": "\nCompany\nIndividual",
"permlevel": 0,
"reqd": 1
},
},
{
"fieldname": "lead_name",
"fieldtype": "Link",
"hidden": 0,
"in_filter": 1,
"label": "From Lead",
"no_copy": 1,
"oldfieldname": "lead_name",
"oldfieldtype": "Link",
"options": "Lead",
"permlevel": 0,
"print_hide": 1,
"fieldname": "lead_name",
"fieldtype": "Link",
"hidden": 0,
"in_filter": 1,
"label": "From Lead",
"no_copy": 1,
"oldfieldname": "lead_name",
"oldfieldtype": "Link",
"options": "Lead",
"permlevel": 0,
"print_hide": 1,
"report_hide": 1
},
},
{
"fieldname": "column_break0",
"fieldtype": "Column Break",
"permlevel": 0,
"fieldname": "column_break0",
"fieldtype": "Column Break",
"permlevel": 0,
"width": "50%"
},
},
{
"description": "",
"fieldname": "customer_group",
"fieldtype": "Link",
"hidden": 0,
"in_filter": 1,
"in_list_view": 1,
"label": "Customer Group",
"oldfieldname": "customer_group",
"oldfieldtype": "Link",
"options": "Customer Group",
"permlevel": 0,
"print_hide": 0,
"reqd": 1,
"description": "",
"fieldname": "customer_group",
"fieldtype": "Link",
"hidden": 0,
"in_filter": 1,
"in_list_view": 1,
"label": "Customer Group",
"oldfieldname": "customer_group",
"oldfieldtype": "Link",
"options": "Customer Group",
"permlevel": 0,
"print_hide": 0,
"reqd": 1,
"search_index": 1
},
},
{
"description": "",
"fieldname": "territory",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Territory",
"oldfieldname": "territory",
"oldfieldtype": "Link",
"options": "Territory",
"permlevel": 0,
"print_hide": 1,
"description": "",
"fieldname": "territory",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Territory",
"oldfieldname": "territory",
"oldfieldtype": "Link",
"options": "Territory",
"permlevel": 0,
"print_hide": 1,
"reqd": 1
},
},
{
"depends_on": "eval:!doc.__islocal",
"fieldname": "address_contacts",
"fieldtype": "Section Break",
"label": "",
"options": "icon-map-marker",
"depends_on": "eval:!doc.__islocal",
"fieldname": "address_contacts",
"fieldtype": "Section Break",
"label": "",
"options": "icon-map-marker",
"permlevel": 0
},
},
{
"fieldname": "address_html",
"fieldtype": "HTML",
"label": "Address HTML",
"permlevel": 0,
"fieldname": "address_html",
"fieldtype": "HTML",
"label": "Address HTML",
"permlevel": 0,
"read_only": 1
},
},
{
"fieldname": "column_break1",
"fieldtype": "Column Break",
"permlevel": 0,
"fieldname": "column_break1",
"fieldtype": "Column Break",
"permlevel": 0,
"width": "50%"
},
},
{
"fieldname": "contact_html",
"fieldtype": "HTML",
"label": "Contact HTML",
"oldfieldtype": "HTML",
"permlevel": 0,
"fieldname": "contact_html",
"fieldtype": "HTML",
"label": "Contact HTML",
"oldfieldtype": "HTML",
"permlevel": 0,
"read_only": 1
},
},
{
"fieldname": "default_receivable_accounts",
"fieldtype": "Section Break",
"label": "Default Receivable Accounts",
"fieldname": "default_receivable_accounts",
"fieldtype": "Section Break",
"label": "Default Receivable Accounts",
"permlevel": 0
},
},
{
"depends_on": "eval:!doc.__islocal",
"description": "Mention if non-standard receivable account applicable",
"fieldname": "accounts",
"fieldtype": "Table",
"label": "Accounts",
"options": "Party Account",
"depends_on": "eval:!doc.__islocal",
"description": "Mention if non-standard receivable account applicable",
"fieldname": "accounts",
"fieldtype": "Table",
"label": "Accounts",
"options": "Party Account",
"permlevel": 0
},
},
{
"fieldname": "more_info",
"fieldtype": "Section Break",
"label": "",
"oldfieldtype": "Section Break",
"options": "icon-file-text",
"fieldname": "more_info",
"fieldtype": "Section Break",
"label": "",
"oldfieldtype": "Section Break",
"options": "icon-file-text",
"permlevel": 0
},
},
{
"fieldname": "column_break2",
"fieldtype": "Column Break",
"permlevel": 0,
"fieldname": "column_break2",
"fieldtype": "Column Break",
"permlevel": 0,
"width": "50%"
},
},
{
"description": "Your Customer's TAX registration numbers (if applicable) or any general information",
"fieldname": "customer_details",
"fieldtype": "Text",
"label": "Customer Details",
"oldfieldname": "customer_details",
"oldfieldtype": "Code",
"description": "Your Customer's TAX registration numbers (if applicable) or any general information",
"fieldname": "customer_details",
"fieldtype": "Text",
"label": "Customer Details",
"oldfieldname": "customer_details",
"oldfieldtype": "Code",
"permlevel": 0
},
},
{
"fieldname": "column_break3",
"fieldtype": "Column Break",
"permlevel": 0,
"fieldname": "column_break3",
"fieldtype": "Column Break",
"permlevel": 0,
"width": "50%"
},
},
{
"fieldname": "default_currency",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "Currency",
"no_copy": 1,
"options": "Currency",
"fieldname": "default_currency",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "Currency",
"no_copy": 1,
"options": "Currency",
"permlevel": 0
},
},
{
"fieldname": "default_price_list",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "Price List",
"options": "Price List",
"fieldname": "default_price_list",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "Price List",
"options": "Price List",
"permlevel": 0
},
},
{
"fieldname": "default_taxes_and_charges",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "Taxes and Charges",
"options": "Sales Taxes and Charges Template",
"fieldname": "default_taxes_and_charges",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "Taxes and Charges",
"options": "Sales Taxes and Charges Template",
"permlevel": 0
},
},
{
"fieldname": "credit_days",
"fieldtype": "Int",
"label": "Credit Days",
"oldfieldname": "credit_days",
"oldfieldtype": "Int",
"fieldname": "credit_days_based_on",
"fieldtype": "Select",
"label": "Credit Days Based On",
"options": "\nFixed Days\nLast Day of the Next Month",
"permlevel": 0,
"precision": ""
},
{
"depends_on": "eval:doc.credit_days_based_on=='Fixed Days'",
"fieldname": "credit_days",
"fieldtype": "Int",
"label": "Credit Days",
"oldfieldname": "credit_days",
"oldfieldtype": "Int",
"permlevel": 1
},
},
{
"fieldname": "credit_limit",
"fieldtype": "Currency",
"label": "Credit Limit",
"oldfieldname": "credit_limit",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"fieldname": "credit_limit",
"fieldtype": "Currency",
"label": "Credit Limit",
"oldfieldname": "credit_limit",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 1
},
},
{
"fieldname": "website",
"fieldtype": "Data",
"label": "Website",
"fieldname": "website",
"fieldtype": "Data",
"label": "Website",
"permlevel": 0
},
},
{
"fieldname": "sales_team_section_break",
"fieldtype": "Section Break",
"label": "",
"oldfieldtype": "Section Break",
"options": "icon-group",
"fieldname": "sales_team_section_break",
"fieldtype": "Section Break",
"label": "",
"oldfieldtype": "Section Break",
"options": "icon-group",
"permlevel": 0
},
},
{
"fieldname": "default_sales_partner",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "Sales Partner",
"oldfieldname": "default_sales_partner",
"oldfieldtype": "Link",
"options": "Sales Partner",
"fieldname": "default_sales_partner",
"fieldtype": "Link",
"ignore_user_permissions": 1,
"label": "Sales Partner",
"oldfieldname": "default_sales_partner",
"oldfieldtype": "Link",
"options": "Sales Partner",
"permlevel": 0
},
},
{
"fieldname": "default_commission_rate",
"fieldtype": "Float",
"label": "Commission Rate",
"oldfieldname": "default_commission_rate",
"oldfieldtype": "Currency",
"fieldname": "default_commission_rate",
"fieldtype": "Float",
"label": "Commission Rate",
"oldfieldname": "default_commission_rate",
"oldfieldtype": "Currency",
"permlevel": 0
},
},
{
"fieldname": "sales_team",
"fieldtype": "Table",
"label": "Sales Team Details",
"oldfieldname": "sales_team",
"oldfieldtype": "Table",
"options": "Sales Team",
"fieldname": "sales_team",
"fieldtype": "Table",
"label": "Sales Team Details",
"oldfieldname": "sales_team",
"oldfieldtype": "Table",
"options": "Sales Team",
"permlevel": 0
},
},
{
"fieldname": "communications",
"fieldtype": "Table",
"hidden": 1,
"label": "Communications",
"options": "Communication",
"permlevel": 0,
"fieldname": "communications",
"fieldtype": "Table",
"hidden": 1,
"label": "Communications",
"options": "Communication",
"permlevel": 0,
"print_hide": 1
}
],
"icon": "icon-user",
"idx": 1,
"modified": "2015-02-24 17:32:36.065248",
"modified_by": "Administrator",
"module": "Selling",
"name": "Customer",
"owner": "Administrator",
],
"icon": "icon-user",
"idx": 1,
"modified": "2015-07-13 05:28:25.753684",
"modified_by": "Administrator",
"module": "Selling",
"name": "Customer",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 1,
"create": 1,
"delete": 0,
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales User",
"share": 1,
"submit": 0,
"amend": 0,
"apply_user_permissions": 1,
"create": 1,
"delete": 0,
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales User",
"share": 1,
"submit": 0,
"write": 1
},
},
{
"cancel": 0,
"delete": 0,
"permlevel": 1,
"read": 1,
"cancel": 0,
"delete": 0,
"permlevel": 1,
"read": 1,
"role": "Sales User"
},
},
{
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales Manager"
},
},
{
"amend": 0,
"create": 1,
"delete": 1,
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales Master Manager",
"set_user_permissions": 1,
"share": 1,
"submit": 0,
"amend": 0,
"create": 1,
"delete": 1,
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales Master Manager",
"set_user_permissions": 1,
"share": 1,
"submit": 0,
"write": 1
},
},
{
"cancel": 0,
"delete": 0,
"permlevel": 1,
"read": 1,
"role": "Sales Master Manager",
"cancel": 0,
"delete": 0,
"permlevel": 1,
"read": 1,
"role": "Sales Master Manager",
"write": 1
},
},
{
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Material User"
},
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Stock User"
},
{
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Material Manager"
},
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Stock Manager"
},
{
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts User"
},
},
{
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager"
}
],
"search_fields": "customer_name,customer_group,territory",
],
"search_fields": "customer_name,customer_group,territory",
"title_field": "customer_name"
}
}

View File

@@ -7,10 +7,10 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) {
cur_frm.fields_dict.new_item_code.get_query = function() {
return{
query: "erpnext.selling.doctype.sales_bom.sales_bom.get_new_item_code"
query: "erpnext.selling.doctype.product_bundle.product_bundle.get_new_item_code"
}
}
cur_frm.fields_dict.new_item_code.query_description = __('Please select Item where "Is Stock Item" is "No" and "Is Sales Item" is "Yes" and there is no other Sales BOM');
cur_frm.fields_dict.new_item_code.query_description = __('Please select Item where "Is Stock Item" is "No" and "Is Sales Item" is "Yes" and there is no other Product Bundle');
cur_frm.cscript.item_code = function(doc, dt, dn) {
var d = locals[dt][dn];

View File

@@ -1,7 +1,7 @@
{
"allow_import": 1,
"creation": "2013-06-20 11:53:21",
"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 Sales BOM Item.\n\nNote: BOM = Bill of Materials",
"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",
@@ -38,7 +38,7 @@
"label": "Items",
"oldfieldname": "sales_bom_items",
"oldfieldtype": "Table",
"options": "Sales BOM Item",
"options": "Product Bundle Item",
"permlevel": 0,
"reqd": 1
}
@@ -46,10 +46,10 @@
"icon": "icon-sitemap",
"idx": 1,
"is_submittable": 0,
"modified": "2015-02-20 05:05:03.719573",
"modified": "2015-07-13 05:28:28.140327",
"modified_by": "Administrator",
"module": "Selling",
"name": "Sales BOM",
"name": "Product Bundle",
"owner": "Administrator",
"permissions": [
{
@@ -61,7 +61,7 @@
"print": 1,
"read": 1,
"report": 1,
"role": "Material Manager",
"role": "Stock Manager",
"share": 1,
"submit": 0,
"write": 1
@@ -76,7 +76,7 @@
"print": 1,
"read": 1,
"report": 1,
"role": "Material User",
"role": "Stock User",
"submit": 0,
"write": 0
},

View File

@@ -8,9 +8,7 @@ from frappe import _
from frappe.model.document import Document
class SalesBOM(Document):
class ProductBundle(Document):
def autoname(self):
self.name = self.new_item_code
@@ -39,7 +37,7 @@ def get_new_item_code(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql("""select name, item_name, description from tabItem
where is_stock_item="No" and is_sales_item="Yes"
and name not in (select name from `tabSales BOM`) and %s like %s
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))

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