Compare commits

..

262 Commits

Author SHA1 Message Date
Anand Doshi
e3910d02a5 Merge branch 'develop' 2015-10-22 18:53:19 +05:30
Anand Doshi
0af146cea6 bumped to version 6.6.1 2015-10-22 19:23:19 +06:00
Anand Doshi
683f756d0f [fix] Fetch company of employee in leave application 2015-10-22 18:52:15 +05:30
Anand Doshi
d905204e49 [fix] Update expense account in old purchase invoices if missing 2015-10-22 18:49:08 +05:30
Anand Doshi
d8bc40d7f0 [fix] party gle currency validation 2015-10-22 17:55:22 +05:30
Anand Doshi
54059b77a0 Merge branch 'develop' 2015-10-22 17:12:01 +05:30
Anand Doshi
f9f0e2591f bumped to version 6.6.0 2015-10-22 17:42:00 +06:00
Anand Doshi
5810bf70c7 [change-log] 2015-10-22 17:02:44 +05:30
Anand Doshi
97d8db775e Merge pull request #4208 from nabinhait/pcv
Period Closing Voucher as per multi currency
2015-10-22 16:46:26 +05:30
Nabin Hait
fbe08ec7d0 Period Closing Voucher Test Cases 2015-10-22 16:21:37 +05:30
Nabin Hait
0045c305ac Period Closing Voucher as per multi currency 2015-10-22 16:21:37 +05:30
Anand Doshi
5dd0fb6e2a Merge pull request #4213 from nabinhait/serial_no_fix
[fix] For Serial No Status
2015-10-22 15:25:11 +05:30
Anand Doshi
e99fff8d08 Merge pull request #4212 from anandpdoshi/leave-application-js-clenup
[minor] leave application cleanup
2015-10-22 15:19:57 +05:30
Anand Doshi
b61fed9106 Merge pull request #4205 from nabinhait/expenses_included_in_valuation
Expenses Included in Valuation
2015-10-22 15:19:38 +05:30
Nabin Hait
398c83afa5 [fix] For Serial No Status 2015-10-22 15:11:44 +05:30
Anand Doshi
c346484ca4 [minor] leave application cleanup 2015-10-21 19:56:14 +05:30
Nabin Hait
70b7f7f036 minor improvement in patch 2015-10-21 17:40:06 +05:30
Nabin Hait
31c51ef914 [fix] test case for purchase invoice gle 2015-10-21 17:40:06 +05:30
Nabin Hait
be464696cc [fix][patch] Fix wrong gle for Purchase Invoice against Expenses Included in Valuation account 2015-10-21 17:40:06 +05:30
Anand Doshi
191b2970e9 [translations] updated 2015-10-21 16:59:33 +05:30
Anand Doshi
c50f033722 [language] Added Ukranian language - українська. Closes frappe/translator#57 2015-10-21 16:59:32 +05:30
Anand Doshi
e1e1414894 Merge pull request #4195 from anandpdoshi/journal-entry-posting-date
[enhancement] Quick Entry in Journal Entry, remember Posting Date
2015-10-21 16:50:40 +05:30
Anand Doshi
d1441245fb [fix] variant website page render 2015-10-21 16:36:43 +05:30
Anand Doshi
87da662703 [enhancement] Quick Entry in Journal Entry, remember Posting Date 2015-10-21 16:27:13 +05:30
Anand Doshi
99ba924303 Merge pull request #4207 from rmehta/rename-tool
[feature] rename via console merge with frappe/frappe#1349
2015-10-21 14:27:49 +05:30
Anand Doshi
066ff9599a Merge pull request #4206 from neilLasrado/variant
Prevent Template Item from going into infinite loop while saving
2015-10-21 14:20:49 +05:30
Rushabh Mehta
33ebaf479d [feature] rename via console merge with frappe/frappe#1349 2015-10-21 12:26:37 +05:30
Neil Trini Lasrado
3a573d1a6d Prevent Template Item from going into infinite loop while saving 2015-10-21 12:20:06 +05:30
Rushabh Mehta
7f66983309 [minor] added column type definition in batch-wise balance history 2015-10-21 12:04:27 +05:30
Rushabh Mehta
2c867fdd73 [fix] email digest cache 2015-10-21 11:13:40 +05:30
Anand Doshi
95dfc2730b [fix] re-run thumbnail patch 2015-10-20 19:03:30 +05:30
Anand Doshi
558646c6b8 [fix] ignore mandatory when creating customer and contact in cart 2015-10-20 18:57:38 +05:30
Anand Doshi
ea0d98891f [minor] don't display missing file doc message in item's make thumbnail 2015-10-20 18:57:38 +05:30
Anand Doshi
1b4c5ad1e1 Merge branch 'develop' 2015-10-20 18:35:49 +05:30
Anand Doshi
2678135f5e bumped to version 6.5.3 2015-10-20 19:05:49 +06:00
Anand Doshi
25ef4ff373 [fix] variant selector display 2015-10-20 18:34:21 +05:30
Anand Doshi
c85a37fe00 Merge branch 'develop' 2015-10-20 17:53:37 +05:30
Anand Doshi
3c3d69f905 bumped to version 6.5.2 2015-10-20 18:23:37 +06:00
Anand Doshi
aed8da40ae Merge pull request #4198 from nabinhait/mc_fix
[fix] Set higher precision for debit, credit and exchange rate field
2015-10-20 17:46:22 +05:30
Anand Doshi
3bc43682f1 Merge pull request #4199 from neilLasrado/item
Default value of allow production order in Item master changed to 1
2015-10-20 17:44:26 +05:30
Rushabh Mehta
725816e616 Merge pull request #4203 from anandpdoshi/item-variant-in-website
[fix] Patch template item to be shown in website, show variant's description and price on change of attribute
2015-10-20 17:41:26 +05:30
Anand Doshi
7c0eadb451 [fix] Patch template item to be shown in website, show variant's description and price on change of attribute 2015-10-20 17:30:02 +05:30
Neil Trini Lasrado
d4357e80d7 Fixed Test Cases 2015-10-20 16:21:02 +05:30
Neil Trini Lasrado
c0f88e4caf Default value fot allow production order in Item master changed to 1 2015-10-20 15:51:04 +05:30
Anand Doshi
73286dd9f5 [minor] define email field for Issue 2015-10-20 14:53:22 +05:30
Anand Doshi
1f259ba73d Merge pull request #4178 from anandpdoshi/item-reorder-if-no-bin
[fix] Item Re-order if Bin does not exists and fixed Stock Projected Qty report to show per Warehouse Re-order level
2015-10-20 14:43:20 +05:30
Anand Doshi
7b2b0cd73c [fix] Item Re-order if Bin does not exists and fixed Stock Projected Qty report to show per Warehouse Re-order level 2015-10-20 14:29:47 +05:30
Anand Doshi
2c749db2a9 Merge pull request #4196 from neilLasrado/develop
Fixed issue in Item Variant for Numeric Attributes
2015-10-20 14:28:16 +05:30
Anand Doshi
17c633d00f [fix] Set fieldtype of description field as Text Editor in Landed Cost Item 2015-10-20 14:26:44 +05:30
Anand Doshi
4ee5b75687 Merge pull request #4200 from nabinhait/fix16
[fix] Set fieldtype of description field as Text in Landed Cost Item
2015-10-20 14:24:36 +05:30
Neil Trini Lasrado
a4fad72a65 Considered greater precision of value and increment (better code) 2015-10-20 12:20:49 +05:30
Neil Trini Lasrado
e65ac00f36 Considered greater precision of value and increment 2015-10-20 12:20:49 +05:30
Neil Trini Lasrado
75bd0f7cfe Fixed issue in Item Variant for Numeric Attributes 2015-10-20 12:20:49 +05:30
Nabin Hait
4d20f3029b [fix] Set fieldtype of description field as Text in Landed Cost Item 2015-10-20 12:18:19 +05:30
Nabin Hait
c35b35abca [fix] Set higher precision for exchange rate field 2015-10-20 12:11:51 +05:30
Anand Doshi
17dc249841 [fix] rollback if exception in bulk rename 2015-10-20 12:11:26 +05:30
Anand Doshi
12af47918d [fix] rename tool 2015-10-20 12:02:39 +05:30
Anand Doshi
84ca0197e4 Merge pull request #4197 from saurabh6790/fixes
[minor][fix] set default fiscal year for holiday list calendar view
2015-10-20 11:40:00 +05:30
Anand Doshi
3395e7a2e4 [fix] Daily digest date format 2015-10-20 08:48:43 +05:30
Anand Doshi
25956d6282 [fix] Item thumbnail 2015-10-20 08:48:43 +05:30
Saurabh
ba2133cba2 [minor][fix] set default fiscal year for holiday list calendar view 2015-10-19 19:20:11 +05:30
Anand Doshi
28e3d63280 Merge branch 'develop' 2015-10-19 19:10:58 +05:30
Anand Doshi
414660313a bumped to version 6.5.1 2015-10-19 19:40:58 +06:00
Anand Doshi
c52a601e87 Merge pull request #4189 from nabinhait/dn_target_wh_testcase
Test case fixed for swtiching valuation method
2015-10-19 19:09:27 +05:30
Anand Doshi
7a869b0dca [hotfix] print in patch 2015-10-19 17:33:40 +05:30
Nabin Hait
6f64a78ecf Test case fixed for swtiching valuation method 2015-10-19 16:53:35 +05:30
Nabin Hait
608bbc7850 Test case fixed for swtiching valuation method 2015-10-19 16:53:35 +05:30
Anand Doshi
639826e888 Merge branch 'develop' 2015-10-19 16:30:33 +05:30
Anand Doshi
16b2c51988 bumped to version 6.5.0 2015-10-19 17:00:33 +06:00
Anand Doshi
76e9ba1e76 [change-log] 2015-10-19 16:03:34 +05:30
Anand Doshi
9dad86c189 Merge pull request #4190 from nabinhait/income_expense_account_query
[fix] Allowed accounts with account type='Income Account' for default income account in item
2015-10-19 15:43:32 +05:30
Anand Doshi
5302b46955 Merge pull request #4183 from nabinhait/multi_currency_fix
Multi currency fix
2015-10-19 15:32:24 +05:30
Nabin Hait
afd14f6f0e [fix] Allowed accounts with account type='Income Account' for default income account in item 2015-10-19 15:27:58 +05:30
Anand Doshi
05584d6d8b Merge pull request #4191 from rmehta/email-digest-quotes
[enhancement] add a quote with email digest
2015-10-19 15:18:20 +05:30
Nabin Hait
aa015902d5 Validate currency of default receivable/payable accounts 2015-10-19 15:10:11 +05:30
Nabin Hait
2873f2e7de Validate currency of default receivable/payable accounts 2015-10-19 15:10:11 +05:30
Rushabh Mehta
64fd970a8a Merge pull request #4193 from anandpdoshi/attach-as-small-text
[fix] change attach fields to small text
2015-10-19 14:58:57 +05:30
Anand Doshi
b4e9c1da64 [fix] thumbnail generation for item 2015-10-19 12:57:19 +05:30
Anand Doshi
1d093a4039 [fix] change attach fields to small text 2015-10-19 12:56:29 +05:30
Rushabh Mehta
fe9717cb9c [enhancement] add a quote with email digest 2015-10-19 12:35:07 +05:30
Anand Doshi
d665a07621 [fix] remove label 'Column Break' 2015-10-16 15:44:28 +05:30
Rushabh Mehta
2a1ba886f1 [patch-fix] 2015-10-15 16:56:53 +05:30
Rushabh Mehta
55f1ea05da [release] Added change log 2015-10-15 16:32:36 +05:30
Rushabh Mehta
2e7f9d2b8f [fixes] email digest 2015-10-15 16:31:16 +05:30
Rushabh Mehta
3a519f269d Merge pull request #4175 from anandpdoshi/dynamic-linked-with
[fix] exclude gl entry and stock ledger entry in linked with. Depends on frappe/frappe#1339
2015-10-15 14:25:18 +05:30
Rushabh Mehta
4c0d0793a3 Merge pull request #4174 from saurabh6790/shopping_cart
[fix] order.html rate display
2015-10-15 14:01:46 +05:30
Rushabh Mehta
d3b8a74508 [test] fix, force values in target warehouse too 2015-10-15 13:23:10 +05:30
Anand Doshi
77760db89c [fix] strip whitespace in setup wizard args 2015-10-15 12:54:40 +05:30
Anand Doshi
1d23ebb51d [fix] exclude gl entry and stock ledger entry in linked with. Depends on frappe/frappe#1339 2015-10-15 12:54:40 +05:30
Rushabh Mehta
ba5b0e8458 [test] [fix] print values for failing test 2015-10-15 12:45:42 +05:30
Rushabh Mehta
14a908bdec [test] [fix] abs(valuation_rate) for moving average 2015-10-15 12:28:20 +05:30
Rushabh Mehta
9f436a7c71 [fix] [exchange-rate] let user defined exchange rate take preceedence 2015-10-15 11:57:46 +05:30
Rushabh Mehta
746fd90625 [fix] [exchange-rate] let user defined exchange rate take preceedence 2015-10-15 11:50:38 +05:30
Rushabh Mehta
f861856ed9 [fix] do not check purchase invoice uniqueness for cancelled documents 2015-10-15 11:37:34 +05:30
Rushabh Mehta
f94f153078 [test] fixes 2015-10-15 11:31:59 +05:30
Rushabh Mehta
c9bacedbfe [test] fixes 2015-10-15 11:00:34 +05:30
Saurabh
c0cee82727 [small fixes] frozen customer testcase 2015-10-14 18:03:07 +05:30
Saurabh
4c53931363 [fixes and test case] test case to avoid duplicate customer name exection 2015-10-14 18:03:07 +05:30
Saurabh
53f7e6281c [fix] Duplicate Customer Name Error 2015-10-14 18:03:07 +05:30
Saurabh
9f235b891f [fix] order.html rate display 2015-10-14 18:03:07 +05:30
Rushabh Mehta
c4d4c7feb0 [fix] repost_actual_qty fix 2015-10-14 17:37:28 +05:30
Rushabh Mehta
ee6862b277 [fix] VARCHAR lengths as 140 2015-10-14 17:28:35 +05:30
Rushabh Mehta
53f77ad5e8 Merge pull request #4125 from rmehta/variant-in-website
[enhancement] add variants in website
2015-10-14 16:22:36 +05:30
Rushabh Mehta
fb73151da6 [fixes] 2015-10-14 16:22:01 +05:30
Rushabh Mehta
6e322d0a02 [enhancement] use thumbnails in grid views, patch to make thumbnails 2015-10-14 16:21:24 +05:30
Rushabh Mehta
73e73795f1 [minor] Added 'Invite User' in Contact 2015-10-14 16:20:39 +05:30
Rushabh Mehta
80d2a55342 [enhancement] add variants in website 2015-10-14 16:16:00 +05:30
Rushabh Mehta
9cbf6b1b22 Merge pull request #4114 from anandpdoshi/varchar-140
Limit varchar length to 140 instead of 255 to mitigate Row Size Too Large error
2015-10-14 16:14:53 +05:30
Anand Doshi
41dd2c458b [minor] pass does not exist error 2015-10-14 16:13:49 +05:30
Anand Doshi
71ebad5668 Limit varchar length to 140 instead of 255 to mitigate Row Size Too Large error 2015-10-14 16:13:49 +05:30
Rushabh Mehta
b4c0e94e99 Merge pull request #4113 from rmehta/email-digest-cleanup
[cleanup] Email Digest
2015-10-14 15:53:53 +05:30
Rushabh Mehta
73f1dc4edf [cleanup] added unsubscribe to email digest 2015-10-14 15:53:37 +05:30
Rushabh Mehta
174299124f [cleanup] [wip] email digest 2015-10-14 15:53:37 +05:30
Rushabh Mehta
c27748b2b3 Merge pull request #4040 from nabinhait/dn_target_warehouse
Delivery to target warehouse
2015-10-14 15:29:54 +05:30
Rushabh Mehta
626ba1bb81 [translations] added bn, da-DK, es-PE, si 2015-10-14 15:24:42 +05:30
Rushabh Mehta
591f047974 Merge pull request #4163 from neilLasrado/develop
Cost Center - Income Account
2015-10-14 15:20:11 +05:30
Nabin Hait
38e4c6f2af Allow same serial nos for raw materials and fg item in repack / manufacture entry 2015-10-13 18:37:39 +05:30
Neil Trini Lasrado
58e9590850 Fixed issues with Permissions in Company Doctype 2015-10-13 17:45:43 +05:30
Nabin Hait
03afb45e34 [fix] Validate deletion of serial no 2015-10-13 15:46:42 +05:30
Nabin Hait
d91382dbf3 [fix] serial no status 2015-10-13 15:46:42 +05:30
Nabin Hait
e07958bbda Change log and sopnsors for delivery to target warehouse 2015-10-13 15:46:42 +05:30
Nabin Hait
b445be3552 Test case for delivery to target warehouse 2015-10-13 15:46:42 +05:30
Nabin Hait
c865f229fb Target Warehouse in Delivery Note and Sales Invoice and removed Serial No status 2015-10-13 15:46:42 +05:30
Neil Trini Lasrado
ec5deb6e48 Changed label in Company 2015-10-13 15:28:12 +05:30
Neil Trini Lasrado
486bf2e113 Added Change Log 2015-10-13 15:17:53 +05:30
Neil Trini Lasrado
f49b085625 Allowed Income account to be added to Cost Center 2015-10-13 14:54:39 +05:30
Rushabh Mehta
adcaf75bb0 Merge branch 'develop' 2015-10-13 14:46:15 +05:30
Rushabh Mehta
4f4fc45ae6 bumped to version 6.4.7 2015-10-13 15:16:15 +06:00
Rushabh Mehta
079d0b7108 Merge pull request #4161 from rmehta/sales-order-status
[fix] Sales Order status for Maintenance
2015-10-13 12:38:00 +05:30
Rushabh Mehta
86125b2b9f [fix] sales order status for maintenance 2015-10-13 12:31:05 +05:30
Rushabh Mehta
22d0d586ab [minor] [typo] 2015-10-13 12:30:21 +05:30
Rushabh Mehta
eb62aed8c7 Merge pull request #4157 from nabinhait/bin
[fix][patch] Delete duplicate bins
2015-10-12 18:39:16 +05:30
Rushabh Mehta
60f1739ca5 Merge pull request #4158 from rmehta/journal-entry-title-fix
[fix] set title in Journal Entry only if not set
2015-10-12 18:35:49 +05:30
Rushabh Mehta
5f349a67c9 Merge pull request #4156 from rmehta/item-section-fix
[fix] [minor] collapsible section for Item - removed custom script
2015-10-12 18:35:38 +05:30
Rushabh Mehta
fd294eb981 Merge pull request #4154 from rmehta/sales-analytics-fix
[minor] [fix] Use customer_name in Sales Analytics
2015-10-12 18:32:39 +05:30
Rushabh Mehta
d256055a8c Merge pull request #4153 from rmehta/stock-entry-fix
[fix] [minor] stock_entry.py error for None qty
2015-10-12 18:32:28 +05:30
Rushabh Mehta
cefa106a06 Merge pull request #4151 from anandpdoshi/purchase-invoice-letterhead
[fix] Added Letter Head field to Purchase Invoice
2015-10-12 18:30:25 +05:30
Rushabh Mehta
67ecfcf52c Merge pull request #4148 from saurabh6790/erp_support
[minor fix], escape % char
2015-10-12 18:30:13 +05:30
Nabin Hait
b7e46c4ed9 [fix][patch] Delete duplicate bins 2015-10-12 18:28:50 +05:30
Rushabh Mehta
bc5ecfff06 Merge pull request #4146 from nabinhait/fix10
[fix] Multiple minor fixes
2015-10-12 18:27:02 +05:30
Rushabh Mehta
8fa4845d00 [fix] set title in Journal Entry only if not set 2015-10-12 16:59:52 +05:30
Rushabh Mehta
d4882653c3 [fix] [minor] collapsible section for Item - removed custom script 2015-10-12 16:45:53 +05:30
Anand Doshi
9a4d165ba2 [fix] get_party_details.js - set posting_date if args are initialised 2015-10-12 16:23:51 +05:30
Rushabh Mehta
a7099eaa8d [minor] [fix] Use customer_name in Sales Analytics 2015-10-12 16:22:10 +05:30
Anand Doshi
4b72d05793 [fix] get allocated_percentage from party's sales team 2015-10-12 16:15:52 +05:30
Rushabh Mehta
a30f3ea1f9 [fix] [minor] stock_entry.py error for None qty 2015-10-12 16:12:52 +05:30
Rushabh Mehta
3b6a8af0da Merge pull request #4150 from rmehta/project-title-fix
[fix] copy task titles with project
2015-10-12 15:57:04 +05:30
Anand Doshi
4fa69780a8 [fix] Added Letter Head field to Purchase Invoice 2015-10-12 15:55:24 +05:30
Rushabh Mehta
2dc619ae1f [fix] copy task titles with project 2015-10-12 15:55:12 +05:30
Nabin Hait
fc9031924e [fix] Field type of Age field converted to Int 2015-10-12 15:47:07 +05:30
Saurabh
e14124198d minor fix, escape % char 2015-10-12 15:08:09 +05:30
Nabin Hait
51e980dd2c [fix] Multiple minor fixes 2015-10-10 18:10:05 +05:30
Rushabh Mehta
95781919fb [fix] sales order notification 2015-10-08 11:50:04 +05:30
Rushabh Mehta
c03cba9d17 [fix] sales order notification 2015-10-08 11:46:32 +05:30
Nabin Hait
72cd206286 Merge branch 'develop' 2015-10-07 17:27:23 +05:30
Nabin Hait
9801745090 bumped to version 6.4.6 2015-10-07 17:57:23 +06:00
Anand Doshi
7866c6e6db [fix] modified in sales order and purchase order 2015-10-07 17:26:19 +05:30
Nabin Hait
5812fdb574 Merge branch 'develop' 2015-10-07 14:40:32 +05:30
Nabin Hait
4c502bcd26 bumped to version 6.4.5 2015-10-07 15:10:32 +06:00
Nabin Hait
714948c867 Merge pull request #4136 from nabinhait/uom
[fix] Fetch UOM Conversion Factor from template if not specified in variants
2015-10-07 14:30:18 +05:30
Nabin Hait
8f3b360f83 Merge pull request #4133 from saurabh6790/erp_support
Calendar view for holiday listing
2015-10-07 14:29:38 +05:30
Nabin Hait
314086d6c0 [fix] Fetch UOM Conversion Factor from template if not specified in variants 2015-10-07 11:55:08 +05:30
Nabin Hait
bcd655a985 Merge pull request #4109 from rmehta/fix-sales-purchase-order-status
[fix] sales & purchase order status
2015-10-07 11:34:30 +05:30
Saurabh
b0dbdc1439 minor fixes 2015-10-07 11:27:25 +05:30
Nabin Hait
37b0bf257d Merge pull request #4117 from nabinhait/sample_data
[fix] Create sample opportunity and quotation only if Customer exists
2015-10-07 11:25:50 +05:30
Nabin Hait
c5a25f44e1 Merge pull request #4119 from nabinhait/fix3
[fix] Return account currency only if account provided
2015-10-07 11:25:19 +05:30
Nabin Hait
8dafa376ab Merge pull request #4123 from nabinhait/fix4
[fix] allowed more than 2 currencies in Journal Entry
2015-10-07 11:24:45 +05:30
Saurabh
74eb8e34da [Fixes] minor fix for fiscal year in holiday list 2015-10-07 11:17:14 +05:30
Nabin Hait
5c66fb7631 Merge pull request #4130 from nabinhait/reports
[fix][report] Left join used in pending reports
2015-10-07 11:15:36 +05:30
Nabin Hait
be3b3b2107 Merge pull request #4132 from nabinhait/credit_limit
minor fix in credit limit
2015-10-07 11:15:02 +05:30
Nabin Hait
9ab09fd1d6 Merge pull request #4134 from nabinhait/valuation_rate
[fix] Valuation Rate in Stock Balance report
2015-10-07 11:09:56 +05:30
Nabin Hait
8a7bdd5a92 [fix] Valuation Rate in Stock Balance report 2015-10-06 18:46:56 +05:30
Saurabh
1d753c92b1 Calendar view for holiday listing 2015-10-06 15:21:23 +05:30
Nabin Hait
54ecc8ebba minor fix in credit limit 2015-10-06 14:28:41 +05:30
Nabin Hait
f4edaef481 [fix][report] Left join used in pending reports 2015-10-06 12:48:04 +05:30
Nabin Hait
ebbd163903 [fix] allowed more than 2 currencies in Journal Entry 2015-10-05 13:21:38 +05:30
Nabin Hait
8954b24b22 [fix] Return account currency only if account provided 2015-10-04 12:27:46 +05:30
Nabin Hait
ae92fc7f35 [fix] Create sample opportunity and quotation only if Customer exists 2015-10-03 13:42:44 +05:30
Rushabh Mehta
0bc3ca02f3 [fix] default contact for website 2015-10-03 12:08:43 +05:30
Rushabh Mehta
d10ba853e6 [fix] sales & purchase order status 2015-10-02 17:16:51 +05:30
Anand Doshi
5bcf8315de Merge branch 'develop' 2015-10-02 16:35:36 +05:30
Anand Doshi
789a798e36 bumped to version 6.4.4 2015-10-02 17:05:36 +06:00
Nabin Hait
ee1169dac7 Merge pull request #4112 from nabinhait/fix1
Minor fix
2015-10-02 16:27:49 +05:30
Nabin Hait
fbef1fdf3a Minor fix 2015-10-02 16:26:18 +05:30
Anand Doshi
4358e1cd46 Merge pull request #4111 from nabinhait/payment_reco_patch
[patch] Fix affected Journal Entries due to reconciliation
2015-10-02 16:05:03 +05:30
Nabin Hait
7a287a9153 [patch] Fix affected Journal Entries due to reconciliation 2015-10-02 16:00:42 +05:30
Anand Doshi
5a49ded5d9 Merge branch 'develop' 2015-10-02 12:43:27 +05:30
Anand Doshi
71f23acc2b bumped to version 6.4.3 2015-10-02 13:13:27 +06:00
Anand Doshi
1a1f790150 [fix] test case 2015-10-02 12:34:18 +05:30
Rushabh Mehta
3c54e9779b Merge pull request #4108 from nabinhait/payment_reco
[fix] Payment Reconciliation in multi-currency
2015-10-02 12:32:54 +05:30
Nabin Hait
db48b7d764 [fix] Payment Reconciliation in multi-currency 2015-10-02 12:05:55 +05:30
Rushabh Mehta
83c0899c83 [fix] [minor] default ranges for demo 2015-10-02 11:31:37 +05:30
Nabin Hait
e5047ec90a Merge pull request #4106 from anandpdoshi/payment-tool-amount
In Payment Tool, Set Payment Amount = Outstanding Amount if checked
2015-10-02 10:39:57 +05:30
Anand Doshi
d9ab725be4 [fix] In Payment Tool, Set Payment Amount = Outstanding Amount if checked 2015-10-01 19:17:02 +05:30
Anand Doshi
7afaeb0820 [fix] the case when party account currency is missing 2015-10-01 18:55:43 +05:30
Anand Doshi
da2d8b958d Merge branch 'develop' 2015-10-01 14:01:22 +05:30
Anand Doshi
ba48f82e03 bumped to version 6.4.2 2015-10-01 14:31:22 +06:00
Anand Doshi
8e7e128e81 Merge pull request #4104 from nabinhait/addresses_and_contacts
[fix] get permission query condition if no permitted links
2015-10-01 14:00:38 +05:30
Anand Doshi
0353569e8b Merge pull request #4103 from nabinhait/monthly_attendance_sheet
[fix] Month issue fixed in Monthly Attendance Sheet
2015-10-01 13:58:33 +05:30
Anand Doshi
665e2f5418 Merge pull request #4100 from nabinhait/general_ledger_report
[fix] General Ledger report fixed
2015-10-01 13:56:13 +05:30
Nabin Hait
dace2b6796 [fix] get permission query condition if no permitted links 2015-10-01 13:54:46 +05:30
Nabin Hait
712b02593a [fix] Month issue fixed in Monthly Attendance Sheet 2015-10-01 12:35:54 +05:30
Anand Doshi
d2a60fd727 Merge pull request #4102 from nabinhait/lead_email
[fix] Validate duplicate email ids in Lead
2015-10-01 12:07:37 +05:30
Nabin Hait
f924e08b93 [fix] Validate duplicate email ids in Lead 2015-10-01 11:51:48 +05:30
Nabin Hait
5c623dae4d [fix] General Ledger report fixed 2015-10-01 11:22:15 +05:30
Anand Doshi
e2c3d40b57 [hotfix] Payment Reconciliation Invoice Type 2015-10-01 11:21:26 +05:30
Anand Doshi
673887455f [fix] Show Contribution (%) in Sales Team table in Customer Form 2015-10-01 11:21:25 +05:30
Anand Doshi
63199e486b Merge branch 'develop' 2015-09-30 20:51:00 +05:30
Anand Doshi
bf7294cf5c bumped to version 6.4.1 2015-09-30 21:20:59 +06:00
Anand Doshi
8aa06a809a Merge pull request #4096 from nabinhait/jv_reference
Repost GL Entries for Journal Entries where reference name is missing
2015-09-30 19:44:21 +05:30
Nabin Hait
72d2d682ae Repost GL Entries for Journal Entries where reference name is missing 2015-09-30 18:50:54 +05:30
Anand Doshi
21f6ea6f7e [hotfix] remove allow on submit from item tables 2015-09-30 18:45:29 +05:30
Anand Doshi
185f488c51 Merge branch 'develop' 2015-09-30 17:23:52 +05:30
Anand Doshi
f3006972d5 bumped to version 6.4.0 2015-09-30 17:53:52 +06:00
Anand Doshi
dccc6bc11d [change-log] 2015-09-30 17:19:51 +05:30
Anand Doshi
15d2c89939 Merge remote-tracking branch 'upstream/master' into develop
Conflicts:
	erpnext/accounts/report/general_ledger/general_ledger.py
2015-09-30 17:13:58 +05:30
Anand Doshi
ca4c8a2a46 [translations] 2015-09-30 17:10:58 +05:30
Anand Doshi
c320fe541d Merge pull request #4067 from anandpdoshi/remove-party-account-currency
Remove party_account_currency from Customer and Supplier, and use currency derived from get_party_account
2015-09-30 16:55:24 +05:30
Anand Doshi
f40a87511e Merge pull request #4091 from rmehta/repack-allow-low-rate
[fix] remove validation to disallow lower rate
2015-09-30 16:46:31 +05:30
Anand Doshi
4945b94950 [fix] added validation to match account currency with existing gle and test case 2015-09-30 16:41:15 +05:30
Rushabh Mehta
cb96b61449 [fix] remove validation to disallow lower rate 2015-09-30 16:22:05 +05:30
Anand Doshi
248c867a2c [minor] removed test case for party multi-currency validation, since party multi-currency is now based on account 2015-09-30 15:11:13 +05:30
Anand Doshi
da98ab6f3c [fix] Only 1 account per company for a party 2015-09-30 15:11:12 +05:30
Anand Doshi
cd0989e051 Added method get_account_currency 2015-09-30 15:11:12 +05:30
Anand Doshi
b20baf894f [fix] Remove party_account_currency from Customer and Supplier, and use currency derived from get_party_account 2015-09-30 15:11:12 +05:30
Nabin Hait
d3cf4f1264 Merge pull request #4075 from anandpdoshi/journal-entry-get-exchange-rate
return exchange rate as 1 if no account is specified
2015-09-30 15:05:41 +05:30
Anand Doshi
2dbe2b63b2 Merge pull request #4088 from anandpdoshi/address-contact-permissions
Apply permissions on address and contact based on permissions of Customer, Supplier
2015-09-30 12:19:50 +05:30
Anand Doshi
edba8f5582 [fix] Print 'Attach' field in Stock Entry Detail 2015-09-30 11:50:08 +05:30
Anand Doshi
89b8d11f9c [fix] Apply permissions on address and contact based on permissions of Customer, Supplier 2015-09-29 20:11:57 +05:30
Anand Doshi
19a33994da [cleanup] removed desk_home and desk_home_flows from conf.js 2015-09-29 20:06:22 +05:30
Rushabh Mehta
89349d3ae3 [fix] [payment-reconciliation] ignore rows with blank invoice numbers 2015-09-29 16:39:53 +05:30
Anand Doshi
f6a31a568a Merge pull request #4085 from rmehta/bulk-priority
[enhancement] lower priority for newsletter emails
2015-09-29 15:25:13 +05:30
Rushabh Mehta
4bcbcd29f7 [enhancement] lower priority for newsletter emails 2015-09-29 14:58:45 +05:30
Anand Doshi
740a11263f [minor] validate invoice number is selected in Payment Reconciliation 2015-09-29 12:55:11 +05:30
Anand Doshi
142859f36e Merge pull request #4076 from anandpdoshi/shopping-cart-order
check doc.has_website_permission in order.html. Merge after frappe/frappe#1316
2015-09-28 19:40:17 +05:30
Anand Doshi
6534ad082d Merge pull request #4069 from anandpdoshi/round-status-updater-percentages
Round status update percentages to 2 decimals
2015-09-28 19:40:01 +05:30
Anand Doshi
6361ae3495 Merge branch 'rmehta-backup-cleanup' into develop 2015-09-28 19:38:06 +05:30
Rushabh Mehta
7f75dbf061 [cleanup] remove backup manager 2015-09-28 19:12:54 +05:30
Anand Doshi
199d8a44fc [fix] check doc.has_website_permission in order.html 2015-09-28 19:04:42 +05:30
Rushabh Mehta
72b1128467 [fixes] accounts controller add flt 2015-09-28 17:29:46 +05:30
Anand Doshi
d6cb55ad1a [fix] return exchange rate as 1 if no account is specified 2015-09-28 17:20:02 +05:30
Anand Doshi
c76e34d7de [fix] In get_bom_items_as_dict don't filter by is_pro_applicable for multi-level bom 2015-09-28 17:01:44 +05:30
Anand Doshi
33b10faf94 Merge pull request #4074 from anandpdoshi/multi-level-bom-fetch
[fix] In get_bom_items_as_dict don't filter by is_pro_applicable for multi-level bom
2015-09-28 17:00:52 +05:30
Anand Doshi
d970b001a4 [fix] Round status update percentages to 2 decimals 2015-09-28 16:52:22 +05:30
Anand Doshi
d767fb6134 [fix] In get_bom_items_as_dict don't filter by is_pro_applicable for multi-level bom 2015-09-28 16:44:48 +05:30
Rushabh Mehta
6239923340 Merge pull request #4071 from gmarke/patch-2
Update get_item_details.py
2015-09-28 10:18:56 +05:30
gmarke
e5a31462fe Update get_item_details.py
like this it will be possible to correctly handle cost center for stock entries when no default cost center per company is set
2015-09-27 09:38:01 +02:00
Anand Doshi
6f39300d43 Merge pull request #4068 from anandpdoshi/due-date-validation
if no party, don't validate due date based on credit days
2015-09-25 17:31:33 +05:30
Anand Doshi
0ca587e018 [fix] if no party, don't validate due date based on credit days 2015-09-25 16:32:14 +05:30
Rushabh Mehta
8ffe12ebe4 [chart-of-accounts] added default for Guatemala 2015-09-25 15:40:33 +05:30
Anand Doshi
8579af371c Merge pull request #4057 from rmehta/gl-report-fix
GL Report Fix
2015-09-25 12:30:26 +05:30
Rushabh Mehta
b5ff9421e1 [optimize] customer outstanding query 2015-09-25 12:25:12 +05:30
Rushabh Mehta
ba8ec17f0b Merge pull request #4065 from nabinhait/receivable_payable
[fix] Fetch gl entries in receivable/payable report only if party mentioned
2015-09-25 11:34:14 +05:30
Nabin Hait
44bd3b2601 [fix] Fetch gl entries in receivable/payable report only if party mentioned 2015-09-25 10:33:51 +05:30
Rushabh Mehta
9d40eca428 Merge pull request #4064 from nabinhait/trial_balance_for_party
[report] Trial Balance for Party
2015-09-25 10:01:44 +05:30
Nabin Hait
1b6c00e2c7 [report] Trial Balance for Party 2015-09-25 09:18:03 +05:30
Anand Doshi
52efde31e7 Merge branch 'develop' 2015-09-24 17:31:12 +05:30
Anand Doshi
f723032fd7 bumped to version 6.3.2 2015-09-24 18:01:11 +06:00
Anand Doshi
3297c43bdf [fix] Tax Rule permission to Account Manager 2015-09-24 17:29:28 +05:30
Anand Doshi
aea250bc5a [fix] [patch] fix missing default lead 2015-09-24 16:31:36 +05:30
Anand Doshi
d37d4dfdec [fix] applicable territory patch and tax rule tests 2015-09-24 15:44:39 +05:30
Rushabh Mehta
8f2b8afcb7 [fix] gl entry report if not filtered 2015-09-24 15:03:53 +05:30
408 changed files with 81218 additions and 66750 deletions

View File

@@ -1,2 +1,2 @@
from __future__ import unicode_literals
__version__ = '6.3.1'
__version__ = '6.6.1'

File diff suppressed because it is too large Load Diff

View File

@@ -50,20 +50,20 @@ class Account(Document):
def set_root_and_report_type(self):
if self.parent_account:
par = frappe.db.get_value("Account", self.parent_account, ["report_type", "root_type"], as_dict=1)
if par.report_type:
self.report_type = par.report_type
if par.root_type:
self.root_type = par.root_type
if self.is_group:
db_value = frappe.db.get_value("Account", self.name, ["report_type", "root_type"], as_dict=1)
if db_value:
if self.report_type != db_value.report_type:
frappe.db.sql("update `tabAccount` set report_type=%s where lft > %s and rgt < %s",
frappe.db.sql("update `tabAccount` set report_type=%s where lft > %s and rgt < %s",
(self.report_type, self.lft, self.rgt))
if self.root_type != db_value.root_type:
frappe.db.sql("update `tabAccount` set root_type=%s where lft > %s and rgt < %s",
frappe.db.sql("update `tabAccount` set root_type=%s where lft > %s and rgt < %s",
(self.root_type, self.lft, self.rgt))
def validate_root_details(self):
@@ -89,11 +89,11 @@ class Account(Document):
frappe.throw(_("Account balance already in Debit, you are not allowed to set 'Balance Must Be' as 'Credit'"))
elif account_balance < 0 and self.balance_must_be == "Debit":
frappe.throw(_("Account balance already in Credit, you are not allowed to set 'Balance Must Be' as 'Debit'"))
def validate_account_currency(self):
if not self.account_currency:
self.account_currency = frappe.db.get_value("Company", self.company, "default_currency")
elif self.account_currency != frappe.db.get_value("Account", self.name, "account_currency"):
if frappe.db.get_value("GL Entry", {"account": self.name}):
frappe.throw(_("Currency can not be changed after making entries using some other currency"))
@@ -207,3 +207,16 @@ def get_parent_account(doctype, txt, searchfield, start, page_len, filters):
and %s like %s order by name limit %s, %s""" %
("%s", searchfield, "%s", "%s", "%s"),
(filters["company"], "%%%s%%" % txt, start, page_len), as_list=1)
def get_account_currency(account):
"""Helper function to get account currency"""
if not account:
return
def generator():
account_currency, company = frappe.db.get_value("Account", account, ["account_currency", "company"])
if not account_currency:
account_currency = frappe.db.get_value("Company", company, "default_currency")
return account_currency
return frappe.local_cache("account_currency", account, generator)

View File

@@ -0,0 +1,90 @@
{
"country_code": "gt",
"name": "Cuentas de Guatemala",
"is_active": "Yes",
"tree": {
"Activos": {
"Activo Corriente": {
"Caja y Bancos": {},
"Cuentas por Cobrar": {},
"Impuestos por Cobrar": {
"IVA por Cobrar": {},
"Retenciones de IVA recibidas": {}
},
"Inventario": {}
},
"No Corriente": {
"Activos Fijos": {},
"Cargos Diferidos": {}
},
"root_type": "Asset"
},
"Pasivos": {
"Pasivo Corriente": {
"Proveedores": {
"Inventario Recibido pero No Cobrado": {
"account_type": "Stock Received But Not Billed"
}
},
"Impuestos por Pagar": {},
"Sueldos por Liquidar": {},
"Prestaciones": {},
"Cuentas por Pagar": {},
"Otras Cuentas por Pagar": {},
"Acreedores": {}
},
"Pasivo No Corriente": {
"Provisión para Indemnizaciones": {},
"Acreedores": {}
},
"root_type": "Liability"
},
"Patrimonio": {
"Capital": {},
"Utilidades Retenidas": {},
"Resultados del Ejercicio": {},
"root_type": "Asset"
},
"Costos": {
"Costo de Ventas": {},
"Costos Incluidos en la Valuación": {
"account_type": "Expenses Included In Valuation"
},
"Stock Adjustment": {
"account_type": "Stock Adjustment"
},
"root_type": "Expense"
},
"Gastos": {
"Gastos de Personal": {},
"Honorarios Profesionales": {},
"Servicios Básicos": {},
"Alquileres": {},
"Seguros": {},
"Mantenimiento": {},
"Depreciaciones": {},
"Gastos Diversos": {},
"root_type": "Expense"
},
"Ingresos": {
"Productos": {},
"Servicios": {},
"root_type": "Income"
},
"Otros Gastos y Productos Financieros": {
"Otros Ingresos": {
"Otros Gastos y Productos Financieros": {
"Intereses": {},
"Otros Gastos Financieros": {}
}
},
"Otros Gastos": {
"Otros Gastos y Productos Financieros": {
"Intereses": {},
"Otros Gastos Financieros": {}
}
},
"root_type": "Expense"
}
}
}

View File

@@ -249,7 +249,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-08-10 16:59:43.974705",
"modified": "2015-10-02 07:38:39.149782",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Reconciliation Detail",

View File

@@ -89,7 +89,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-02-19 01:06:59.471417",
"modified": "2015-10-02 07:38:40.727468",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Budget Detail",

View File

@@ -40,7 +40,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Series",
"label": "Series",
"no_copy": 0,
"options": "C-FORM-",
"permlevel": 0,
@@ -192,7 +192,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Quarter",
"label": "Quarter",
"no_copy": 0,
"options": "\nI\nII\nIII\nIV",
"permlevel": 0,
@@ -344,7 +344,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 3,
"modified": "2015-09-07 15:51:26",
"modified": "2015-10-02 07:38:40.926061",
"modified_by": "Administrator",
"module": "Accounts",
"name": "C-Form",

View File

@@ -136,7 +136,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-01-01 14:29:58.597428",
"modified": "2015-10-02 07:38:41.105885",
"modified_by": "Administrator",
"module": "Accounts",
"name": "C-Form Invoice Detail",

View File

@@ -17,8 +17,7 @@ erpnext.accounts.CostCenterController = frappe.ui.form.Controller.extend({
return {
filters:[
['Account', 'company', '=', me.frm.doc.company],
['Account', 'root_type', '=', 'Expense'],
['Account', 'is_group', '=', '0'],
['Account', 'is_group', '=', '0']
]
}
});

View File

@@ -298,7 +298,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-09-14 02:55:55.020690",
"modified": "2015-10-02 07:38:42.617993",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Cost Center",

View File

@@ -32,13 +32,13 @@ class CostCenter(NestedSet):
for d in self.get('budgets'):
if d.account:
account_details = frappe.db.get_value("Account", d.account,
["is_group", "company", "root_type"], as_dict=1)
["is_group", "company", "report_type"], as_dict=1)
if account_details.is_group:
frappe.throw(_("Budget cannot be assigned against Group Account {0}").format(d.account))
elif account_details.company != self.company:
frappe.throw(_("Account {0} does not belongs to company {1}").format(d.account, self.company))
elif account_details.root_type != "Expense":
frappe.throw(_("Budget cannot be assigned against {0}, as it's not an Expense account")
elif account_details.report_type != "Profit and Loss":
frappe.throw(_("Budget cannot be assigned against {0}, as it's not an Income or Expense account")
.format(d.account))
if [d.account, d.fiscal_year] in check_acc_list:

View File

@@ -133,7 +133,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-09-14 02:55:56.280252",
"modified": "2015-10-02 07:38:50.942038",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Fiscal Year",

View File

@@ -1,32 +1,38 @@
[
{
"doctype": "Fiscal Year",
"year": "_Test Fiscal Year 2012",
"year_end_date": "2012-12-31",
"doctype": "Fiscal Year",
"year": "_Test Fiscal Year 2012",
"year_end_date": "2012-12-31",
"year_start_date": "2012-01-01"
},
},
{
"doctype": "Fiscal Year",
"year": "_Test Fiscal Year 2013",
"year_end_date": "2013-12-31",
"doctype": "Fiscal Year",
"year": "_Test Fiscal Year 2013",
"year_end_date": "2013-12-31",
"year_start_date": "2013-01-01"
},
},
{
"doctype": "Fiscal Year",
"year": "_Test Fiscal Year 2014",
"year_end_date": "2014-12-31",
"doctype": "Fiscal Year",
"year": "_Test Fiscal Year 2014",
"year_end_date": "2014-12-31",
"year_start_date": "2014-01-01"
},
},
{
"doctype": "Fiscal Year",
"year": "_Test Fiscal Year 2015",
"year_end_date": "2015-12-31",
"doctype": "Fiscal Year",
"year": "_Test Fiscal Year 2015",
"year_end_date": "2015-12-31",
"year_start_date": "2015-01-01"
},
},
{
"doctype": "Fiscal Year",
"year": "_Test Fiscal Year 2016",
"year_end_date": "2016-12-31",
"doctype": "Fiscal Year",
"year": "_Test Fiscal Year 2016",
"year_end_date": "2016-12-31",
"year_start_date": "2016-01-01"
},
{
"doctype": "Fiscal Year",
"year": "_Test Fiscal Year 2017",
"year_end_date": "2017-12-31",
"year_start_date": "2017-01-01"
}
]
]

View File

@@ -39,7 +39,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-09-14 02:55:56.368682",
"modified": "2015-10-02 07:38:51.045350",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Fiscal Year Company",

File diff suppressed because it is too large Load Diff

View File

@@ -3,15 +3,15 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import flt, fmt_money, getdate, formatdate
from frappe import _
from frappe.utils import flt, fmt_money, getdate, formatdate
from frappe.model.document import Document
from erpnext.accounts.party import validate_party_gle_currency
from erpnext.accounts.utils import get_account_currency
from erpnext.setup.doctype.company.company import get_company_currency
from erpnext.exceptions import InvalidAccountCurrency, CustomerFrozen
class CustomerFrozen(frappe.ValidationError): pass
class InvalidCurrency(frappe.ValidationError): pass
class InvalidAccountCurrency(frappe.ValidationError): pass
exclude_from_linked_with = True
class GLEntry(Document):
def validate(self):
@@ -101,25 +101,20 @@ class GLEntry(Document):
if not frozen_accounts_modifier in frappe.get_roles():
if frappe.db.get_value(self.party_type, self.party, "is_frozen"):
frappe.throw("{0} {1} is frozen".format(self.party_type, self.party), CustomerFrozen)
def validate_currency(self):
company_currency = frappe.db.get_value("Company", self.company, "default_currency")
account_currency = frappe.db.get_value("Account", self.account, "account_currency") or company_currency
company_currency = get_company_currency(self.company)
account_currency = get_account_currency(self.account)
if not self.account_currency:
self.account_currency = company_currency
if account_currency != self.account_currency:
frappe.throw(_("Accounting Entry for {0} can only be made in currency: {1}")
.format(self.account, (account_currency or company_currency)), InvalidAccountCurrency)
if self.party_type and self.party:
party_account_currency = frappe.db.get_value(self.party_type, self.party, "party_account_currency") \
or company_currency
if party_account_currency != self.account_currency:
frappe.throw(_("Accounting Entry for {0}: {1} can only be made in currency: {2}")
.format(self.party_type, self.party, party_account_currency), InvalidAccountCurrency)
if self.party_type and self.party:
validate_party_gle_currency(self.party_type, self.party, self.company, self.account_currency)
def validate_balance_type(account, adv_adj=False):
if not adv_adj and account:
@@ -159,7 +154,7 @@ def update_outstanding_amt(account, party_type, party, against_voucher_type, aga
where against_voucher_type=%s and against_voucher=%s
and account = %s {0}""".format(party_condition),
(against_voucher_type, against_voucher, account))[0][0] or 0.0)
if against_voucher_type == 'Purchase Invoice':
bal = -bal
elif against_voucher_type == "Journal Entry":

View File

@@ -8,10 +8,10 @@ frappe.require("assets/erpnext/js/utils.js");
frappe.ui.form.on("Journal Entry", {
refresh: function(frm) {
erpnext.toggle_naming_series();
cur_frm.cscript.voucher_type(frm.doc);
frm.cscript.voucher_type(frm.doc);
if(frm.doc.docstatus==1) {
cur_frm.add_custom_button(__('View Ledger'), function() {
frm.add_custom_button(__('View Ledger'), function() {
frappe.route_options = {
"voucher_no": frm.doc.name,
"from_date": frm.doc.posting_date,
@@ -22,34 +22,22 @@ frappe.ui.form.on("Journal Entry", {
frappe.set_route("query-report", "General Ledger");
}, "icon-table");
}
if (frm.doc.__islocal) {
frm.add_custom_button(__('Quick Entry'), function() {
return erpnext.journal_entry.quick_entry(frm);
});
}
// hide /unhide fields based on currency
erpnext.journal_entry.toggle_fields_based_on_currency(frm);
},
multi_currency: function(frm) {
erpnext.journal_entry.toggle_fields_based_on_currency(frm);
}
})
erpnext.journal_entry.toggle_fields_based_on_currency = function(frm) {
var fields = ["currency_section", "account_currency", "exchange_rate", "debit", "credit"];
var grid = frm.get_field("accounts").grid;
if(grid) grid.set_column_disp(fields, frm.doc.multi_currency);
// dynamic label
var field_label_map = {
"debit_in_account_currency": "Debit",
"credit_in_account_currency": "Credit"
};
$.each(field_label_map, function (fieldname, label) {
var df = frappe.meta.get_docfield("Journal Entry Account", fieldname, frm.doc.name);
df.label = frm.doc.multi_currency ? (label + " in Account Currency") : label;
})
}
erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
onload: function() {
this.load_defaults();
@@ -69,28 +57,19 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
}
);
if(!this.frm.doc.amended_from) this.frm.doc.posting_date = get_today();
if(!this.frm.doc.amended_from) this.frm.doc.posting_date = this.frm.posting_date || get_today();
}
},
setup_queries: function() {
var me = this;
me.frm.set_query("account", "accounts", function(doc, cdt, cdn) {
var filters = {
company: me.frm.doc.company,
is_group: 0
};
if(!doc.multi_currency) {
$.extend(filters, {
account_currency: frappe.get_doc(":Company", me.frm.doc.company).default_currency
});
}
return { filters: filters };
return erpnext.journal_entry.account_query(me.frm);
});
me.frm.set_query("cost_center", "accounts", function(doc, cdt, cdn) {
return {
return {
filters: {
company: me.frm.doc.company,
is_group: 0
@@ -132,22 +111,22 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
if(in_list(["Sales Invoice", "Purchase Invoice"], jvd.reference_type)) {
out.filters.push([jvd.reference_type, "outstanding_amount", "!=", 0]);
// account filter
frappe.model.validate_missing(jvd, "account");
party_account_field = jvd.reference_type==="Sales Invoice" ? "debit_to": "credit_to";
out.filters.push([jvd.reference_type, party_account_field, "=", jvd.account]);
} else {
// party_type and party mandatory
frappe.model.validate_missing(jvd, "party_type");
frappe.model.validate_missing(jvd, "party");
out.filters.push([jvd.reference_type, "per_billed", "<", 100]);
}
if(jvd.party_type && jvd.party) {
out.filters.push([jvd.reference_type,
out.filters.push([jvd.reference_type,
(jvd.reference_type.indexOf("Sales")===0 ? "customer" : "supplier"), "=", jvd.party]);
}
@@ -244,6 +223,7 @@ cur_frm.cscript.company = function(doc, cdt, cdn) {
}
cur_frm.cscript.posting_date = function(doc, cdt, cdn){
cur_frm.posting_date = cur_frm.doc.posting_date;
erpnext.get_fiscal_year(doc.company, doc.posting_date);
}
@@ -335,6 +315,7 @@ frappe.ui.form.on("Journal Entry Account", {
party: function(frm, cdt, cdn) {
var d = frappe.get_doc(cdt, cdn);
if(!d.account && d.party_type && d.party) {
if(!frm.doc.company) frappe.throw(__("Please select Company"));
return frm.call({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_party_account_and_balance",
child: d,
@@ -346,17 +327,17 @@ frappe.ui.form.on("Journal Entry Account", {
});
}
},
account: function(frm, dt, dn) {
var d = locals[dt][dn];
if(d.account) {
if(!frm.doc.company) frappe.throw(__("Please select Company first"));
if(!frm.doc.posting_date) frappe.throw(__("Please select Posting Date first"));
return frappe.call({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_account_balance_and_party_type",
args: {
account: d.account,
account: d.account,
date: frm.doc.posting_date,
company: frm.doc.company,
debit: flt(d.debit_in_account_currency),
@@ -372,23 +353,23 @@ frappe.ui.form.on("Journal Entry Account", {
});
}
},
debit_in_account_currency: function(frm, cdt, cdn) {
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
},
credit_in_account_currency: function(frm, cdt, cdn) {
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
},
debit: function(frm, dt, dn) {
cur_frm.cscript.update_totals(frm.doc);
},
credit: function(frm, dt, dn) {
cur_frm.cscript.update_totals(frm.doc);
},
exchange_rate: function(frm, cdt, cdn) {
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, cdt, cdn);
}
@@ -398,41 +379,132 @@ frappe.ui.form.on("Journal Entry Account", "accounts_remove", function(frm) {
cur_frm.cscript.update_totals(frm.doc);
});
erpnext.journal_entry.set_debit_credit_in_company_currency = function(frm, cdt, cdn) {
erpnext.journal_entry.set_exchange_rate(frm, cdt, cdn);
var row = locals[cdt][cdn];
frappe.model.set_value(cdt, cdn, "debit",
flt(flt(row.debit_in_account_currency)*row.exchange_rate), precision("debit", row));
frappe.model.set_value(cdt, cdn, "credit",
flt(flt(row.credit_in_account_currency)*row.exchange_rate), precision("credit", row));
}
$.extend(erpnext.journal_entry, {
toggle_fields_based_on_currency: function(frm) {
var fields = ["currency_section", "account_currency", "exchange_rate", "debit", "credit"];
erpnext.journal_entry.set_exchange_rate = function(frm, cdt, cdn) {
var company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency;
var row = locals[cdt][cdn];
if(row.account_currency == company_currency || !frm.doc.multi_currency) {
frappe.model.set_value(cdt, cdn, "exchange_rate", 1);
} else if (!row.exchange_rate || row.account_type == "Bank") {
frappe.call({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_exchange_rate",
args: {
account: row.account,
account_currency: row.account_currency,
company: frm.doc.company,
reference_type: cstr(row.reference_type),
reference_name: cstr(row.reference_name),
debit: flt(row.debit_in_account_currency),
credit: flt(row.credit_in_account_currency),
exchange_rate: row.exchange_rate
},
callback: function(r) {
if(r.message) {
frappe.model.set_value(cdt, cdn, "exchange_rate", r.message);
}
}
var grid = frm.get_field("accounts").grid;
if(grid) grid.set_column_disp(fields, frm.doc.multi_currency);
// dynamic label
var field_label_map = {
"debit_in_account_currency": "Debit",
"credit_in_account_currency": "Credit"
};
$.each(field_label_map, function (fieldname, label) {
var df = frappe.meta.get_docfield("Journal Entry Account", fieldname, frm.doc.name);
df.label = frm.doc.multi_currency ? (label + " in Account Currency") : label;
})
},
set_debit_credit_in_company_currency: function(frm, cdt, cdn) {
erpnext.journal_entry.set_exchange_rate(frm, cdt, cdn);
var row = locals[cdt][cdn];
frappe.model.set_value(cdt, cdn, "debit",
flt(flt(row.debit_in_account_currency)*row.exchange_rate), precision("debit", row));
frappe.model.set_value(cdt, cdn, "credit",
flt(flt(row.credit_in_account_currency)*row.exchange_rate), precision("credit", row));
},
set_exchange_rate: function(frm, cdt, cdn) {
var company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency;
var row = locals[cdt][cdn];
if(row.account_currency == company_currency || !frm.doc.multi_currency) {
frappe.model.set_value(cdt, cdn, "exchange_rate", 1);
} else if (!row.exchange_rate || row.account_type == "Bank") {
frappe.call({
method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_exchange_rate",
args: {
account: row.account,
account_currency: row.account_currency,
company: frm.doc.company,
reference_type: cstr(row.reference_type),
reference_name: cstr(row.reference_name),
debit: flt(row.debit_in_account_currency),
credit: flt(row.credit_in_account_currency),
exchange_rate: row.exchange_rate
},
callback: function(r) {
if(r.message) {
frappe.model.set_value(cdt, cdn, "exchange_rate", r.message);
}
}
})
}
},
quick_entry: function(frm) {
var naming_series_options = frm.fields_dict.naming_series.df.options;
var naming_series_default = frm.fields_dict.naming_series.df.default || naming_series_options.split("\n")[0];
var dialog = new frappe.ui.Dialog({
title: __("Quick Journal Entry"),
fields: [
{fieldtype: "Currency", fieldname: "debit", label: __("Amount"), reqd: 1},
{fieldtype: "Link", fieldname: "debit_account", label: __("Debit Account"), reqd: 1,
options: "Account",
get_query: function() {
return erpnext.journal_entry.account_query(frm);
}
},
{fieldtype: "Link", fieldname: "credit_account", label: __("Credit Account"), reqd: 1,
options: "Account",
get_query: function() {
return erpnext.journal_entry.account_query(frm);
}
},
{fieldtype: "Date", fieldname: "posting_date", label: __("Date"), reqd: 1,
default: frm.doc.posting_date},
{fieldtype: "Select", fieldname: "naming_series", label: __("Series"), reqd: 1,
options: naming_series_options, default: naming_series_default},
]
});
dialog.set_primary_action(__("Save"), function() {
var btn = this;
var values = dialog.get_values();
frm.set_value("posting_date", values.posting_date);
frm.set_value("naming_series", values.naming_series);
// clear table is used because there might've been an error while adding child
// and cleanup didn't happen
frm.clear_table("accounts");
// using grid.add_new_row() to add a row in UI as well as locals
// this is required because triggers try to refresh the grid
var debit_row = frm.fields_dict.accounts.grid.add_new_row();
frappe.model.set_value(debit_row.doctype, debit_row.name, "account", values.debit_account);
frappe.model.set_value(debit_row.doctype, debit_row.name, "debit_in_account_currency", values.debit);
var credit_row = frm.fields_dict.accounts.grid.add_new_row();
frappe.model.set_value(credit_row.doctype, credit_row.name, "account", values.credit_account);
frappe.model.set_value(credit_row.doctype, credit_row.name, "credit_in_account_currency", values.debit);
frm.save();
dialog.hide();
});
dialog.show();
},
account_query: function(frm) {
var filters = {
company: frm.doc.company,
is_group: 0
};
if(!frm.doc.multi_currency) {
$.extend(filters, {
account_currency: frappe.get_doc(":Company", frm.doc.company).default_currency
});
}
return { filters: filters };
}
}
});

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@ import frappe
from frappe.utils import cstr, flt, fmt_money, formatdate
from frappe import msgprint, _, scrub
from erpnext.controllers.accounts_controller import AccountsController
from erpnext.accounts.utils import get_balance_on
from erpnext.accounts.utils import get_balance_on, get_account_currency
from erpnext.setup.utils import get_company_currency
@@ -37,7 +37,8 @@ class JournalEntry(AccountsController):
self.validate_credit_debit_note()
self.validate_empty_accounts_table()
self.set_account_and_party_balance()
self.set_title()
if not self.title:
self.title = self.get_title()
def on_submit(self):
self.check_credit_limit()
@@ -45,8 +46,8 @@ class JournalEntry(AccountsController):
self.update_advance_paid()
self.update_expense_claim()
def set_title(self):
self.title = self.pay_to_recd_from or self.accounts[0].account
def get_title(self):
return self.pay_to_recd_from or self.accounts[0].account
def update_advance_paid(self):
advance_paid = frappe._dict()
@@ -146,7 +147,7 @@ class JournalEntry(AccountsController):
self.reference_totals = {}
self.reference_types = {}
self.reference_parties = {}
self.reference_accounts = {}
for d in self.get("accounts"):
if not d.reference_type:
@@ -169,8 +170,7 @@ class JournalEntry(AccountsController):
self.reference_totals[d.reference_name] = 0.0
self.reference_totals[d.reference_name] += flt(d.get(dr_or_cr))
self.reference_types[d.reference_name] = d.reference_type
if d.party_type and d.party:
self.reference_parties[d.reference_name] = [d.party_type, d.party]
self.reference_accounts[d.reference_name] = d.account
against_voucher = frappe.db.get_value(d.reference_type, d.reference_name,
[scrub(dt) for dt in field_dict.get(d.reference_type)])
@@ -196,7 +196,7 @@ class JournalEntry(AccountsController):
"""Validate totals, stopped and docstatus for orders"""
for reference_name, total in self.reference_totals.iteritems():
reference_type = self.reference_types[reference_name]
party_type, party = self.reference_parties.get(reference_name)
account = self.reference_accounts[reference_name]
if reference_type in ("Sales Order", "Purchase Order"):
order = frappe.db.get_value(reference_type, reference_name,
@@ -212,8 +212,8 @@ class JournalEntry(AccountsController):
if cstr(order.status) == "Stopped":
frappe.throw(_("{0} {1} is stopped").format(reference_type, reference_name))
party_account_currency = frappe.db.get_value(party_type, party, "party_account_currency")
if party_account_currency == self.company_currency:
account_currency = get_account_currency(account)
if account_currency == self.company_currency:
voucher_total = order.base_grand_total
else:
voucher_total = order.grand_total
@@ -278,9 +278,6 @@ class JournalEntry(AccountsController):
if not self.multi_currency:
frappe.throw(_("Please check Multi Currency option to allow accounts with other currency"))
if len(alternate_currency) > 1:
frappe.throw(_("Only one alternate currency can be used in a single Journal Entry"))
self.set_exchange_rate()
for d in self.get("accounts"):
@@ -609,8 +606,8 @@ def get_payment_entry_from_sales_order(sales_order):
jv = get_payment_entry(so)
jv.remark = 'Advance payment received against Sales Order {0}.'.format(so.name)
party_account = get_party_account(so.company, so.customer, "Customer")
party_account_currency = frappe.db.get_value("Account", party_account, "account_currency")
party_account = get_party_account("Customer", so.customer, so.company)
party_account_currency = get_account_currency(party_account)
exchange_rate = get_exchange_rate(party_account, party_account_currency, so.company)
@@ -660,8 +657,8 @@ def get_payment_entry_from_purchase_order(purchase_order):
jv = get_payment_entry(po)
jv.remark = 'Advance payment made against Purchase Order {0}.'.format(po.name)
party_account = get_party_account(po.company, po.supplier, "Supplier")
party_account_currency = frappe.db.get_value("Account", party_account, "account_currency")
party_account = get_party_account("Supplier", po.supplier, po.company)
party_account_currency = get_account_currency(party_account)
exchange_rate = get_exchange_rate(party_account, party_account_currency, po.company)
@@ -779,7 +776,7 @@ def get_party_account_and_balance(company, party_type, party):
frappe.msgprint(_("No Permission"), raise_exception=1)
from erpnext.accounts.party import get_party_account
account = get_party_account(company, party, party_type)
account = get_party_account(party_type, party, company)
account_balance = get_balance_on(account=account)
party_balance = get_balance_on(party_type=party_type, party=party)
@@ -826,17 +823,20 @@ def get_exchange_rate(account, account_currency, company,
if account_currency != company_currency:
if reference_type in ("Sales Invoice", "Purchase Invoice") and reference_name:
exchange_rate = frappe.db.get_value(reference_type, reference_name, "conversion_rate")
elif account_details.account_type == "Bank" and \
elif account_details and account_details.account_type == "Bank" and \
((account_details.root_type == "Asset" and flt(credit) > 0) or
(account_details.root_type == "Liability" and debit)):
exchange_rate = get_average_exchange_rate(account)
if not exchange_rate:
if not exchange_rate and account_currency:
exchange_rate = get_exchange_rate(account_currency, company_currency)
else:
exchange_rate = 1
return exchange_rate
# don't return None or 0 as it is multipled with a value and that value could be lost
return exchange_rate or 1
def get_average_exchange_rate(account):
exchange_rate = 0

View File

@@ -5,6 +5,7 @@ from __future__ import unicode_literals
import unittest, frappe
from frappe.utils import flt
from erpnext.accounts.utils import get_actual_expense, BudgetError, get_fiscal_year
from erpnext.exceptions import InvalidAccountCurrency
class TestJournalEntry(unittest.TestCase):
@@ -166,15 +167,15 @@ class TestJournalEntry(unittest.TestCase):
existing_expense = self.get_actual_expense(posting_date)
make_journal_entry("_Test Account Cost for Goods Sold - _TC",
"_Test Bank - _TC", -existing_expense, "_Test Cost Center - _TC", submit=True)
def test_multi_currency(self):
jv = make_journal_entry("_Test Bank USD - _TC",
"_Test Bank - _TC", 100, exchange_rate=50, save=False)
jv.get("accounts")[1].credit_in_account_currency = 5000
jv.submit()
gl_entries = frappe.db.sql("""select account, account_currency, debit, credit,
gl_entries = frappe.db.sql("""select account, account_currency, debit, credit,
debit_in_account_currency, credit_in_account_currency
from `tabGL Entry` where voucher_type='Journal Entry' and voucher_no=%s
order by account asc""", jv.name, as_dict=1)
@@ -197,12 +198,10 @@ class TestJournalEntry(unittest.TestCase):
"credit_in_account_currency": 5000
}
}
for field in ("account_currency", "debit", "debit_in_account_currency", "credit", "credit_in_account_currency"):
for i, gle in enumerate(gl_entries):
self.assertEquals(expected_values[gle.account][field], gle[field])
# cancel
jv.cancel()
@@ -212,6 +211,40 @@ class TestJournalEntry(unittest.TestCase):
self.assertFalse(gle)
def test_disallow_change_in_account_currency_for_a_party(self):
# create jv in USD
jv = make_journal_entry("_Test Bank USD - _TC",
"_Test Receivable USD - _TC", 100, save=False)
jv.accounts[1].update({
"party_type": "Customer",
"party": "_Test Customer USD"
})
jv.submit()
# create jv in USD, but account currency in INR
jv = make_journal_entry("_Test Bank - _TC",
"_Test Receivable - _TC", 100, save=False)
jv.accounts[1].update({
"party_type": "Customer",
"party": "_Test Customer USD"
})
self.assertRaises(InvalidAccountCurrency, jv.submit)
# back in USD
jv = make_journal_entry("_Test Bank USD - _TC",
"_Test Receivable USD - _TC", 100, save=False)
jv.accounts[1].update({
"party_type": "Customer",
"party": "_Test Customer USD"
})
jv.submit()
def make_journal_entry(account1, account2, amount, cost_center=None, exchange_rate=1, save=True, submit=False):
jv = frappe.new_doc("Journal Entry")
jv.posting_date = "2013-02-14"
@@ -231,7 +264,7 @@ def make_journal_entry(account1, account2, amount, cost_center=None, exchange_ra
"cost_center": cost_center,
"credit_in_account_currency": amount if amount > 0 else 0,
"debit_in_account_currency": abs(amount) if amount < 0 else 0,
exchange_rate: exchange_rate
"exchange_rate": exchange_rate
}
])
if save or submit:

View File

@@ -65,7 +65,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-09-14 02:55:58.003800",
"modified": "2015-10-02 07:38:57.318104",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Mode of Payment",

View File

@@ -63,7 +63,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-01-06 17:26:57.053474",
"modified": "2015-10-02 07:38:57.388194",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Mode of Payment Account",

View File

@@ -91,7 +91,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-02-05 05:11:41.429491",
"modified": "2015-10-02 07:38:57.594541",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Monthly Distribution",

View File

@@ -63,7 +63,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-02-19 01:07:00.800015",
"modified": "2015-10-02 07:38:57.670950",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Monthly Distribution Percentage",

View File

@@ -82,7 +82,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-08-26 11:23:22.917738",
"modified": "2015-10-02 07:38:59.582533",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Party Account",

View File

@@ -74,21 +74,7 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
doc: me.frm.doc,
method: 'get_unreconciled_entries',
callback: function(r, rt) {
var invoices = [];
$.each(me.frm.doc.invoices || [], function(i, row) {
if (row.invoice_number && !inList(invoices, row.invoice_number))
invoices.push(row.invoice_type + " | " + row.invoice_number);
});
frappe.meta.get_docfield("Payment Reconciliation Payment", "invoice_number",
me.frm.doc.name).options = invoices.join("\n");
$.each(me.frm.doc.payments || [], function(i, p) {
if(!inList(invoices, cstr(p.invoice_number))) p.invoice_number = null;
});
refresh_field("payments");
me.set_invoice_options();
}
});
@@ -98,8 +84,29 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
var me = this;
return this.frm.call({
doc: me.frm.doc,
method: 'reconcile'
method: 'reconcile',
callback: function(r, rt) {
me.set_invoice_options();
}
});
},
set_invoice_options: function() {
var invoices = [];
$.each(me.frm.doc.invoices || [], function(i, row) {
if (row.invoice_number && !inList(invoices, row.invoice_number))
invoices.push(row.invoice_type + " | " + row.invoice_number);
});
frappe.meta.get_docfield("Payment Reconciliation Payment", "invoice_number",
me.frm.doc.name).options = invoices.join("\n");
$.each(me.frm.doc.payments || [], function(i, p) {
if(!inList(invoices, cstr(p.invoice_number))) p.invoice_number = null;
});
refresh_field("payments");
}
});

View File

@@ -3,11 +3,8 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import flt
from frappe import msgprint, _
from frappe.model.document import Document
class PaymentReconciliation(Document):
@@ -17,7 +14,8 @@ class PaymentReconciliation(Document):
def get_jv_entries(self):
self.check_mandatory_to_fetch()
dr_or_cr = "credit" if self.party_type == "Customer" else "debit"
dr_or_cr = "credit_in_account_currency" if self.party_type == "Customer" \
else "debit_in_account_currency"
cond = self.check_condition(dr_or_cr)
@@ -68,9 +66,9 @@ class PaymentReconciliation(Document):
def get_invoice_entries(self):
#Fetch JVs, Sales and Purchase Invoices for 'invoices' to reconcile against
non_reconciled_invoices = []
dr_or_cr = "debit" if self.party_type == "Customer" else "credit"
dr_or_cr = "debit_in_account_currency" if self.party_type == "Customer" else "credit_in_account_currency"
cond = self.check_condition(dr_or_cr)
invoice_list = frappe.db.sql("""
select
voucher_no, voucher_type, posting_date,
@@ -106,13 +104,15 @@ class PaymentReconciliation(Document):
and account = %(account)s and {0} > 0
and against_voucher_type = %(against_voucher_type)s
and ifnull(against_voucher, '') = %(against_voucher)s
""".format("credit" if self.party_type == "Customer" else "debit"), {
"party_type": self.party_type,
"party": self.party,
"account": self.receivable_payable_account,
"against_voucher_type": d.voucher_type,
"against_voucher": d.voucher_no
})
""".format("credit_in_account_currency" if self.party_type == "Customer"
else "debit_in_account_currency"), {
"party_type": self.party_type,
"party": self.party,
"account": self.receivable_payable_account,
"against_voucher_type": d.voucher_type,
"against_voucher": d.voucher_no
}
)
payment_amount = payment_amount[0][0] if payment_amount else 0
@@ -141,12 +141,14 @@ class PaymentReconciliation(Document):
def reconcile(self, args):
for e in self.get('payments'):
if " | " in e.invoice_number:
e.invoice_type = None
if e.invoice_number and " | " in e.invoice_number:
e.invoice_type, e.invoice_number = e.invoice_number.split(" | ")
self.get_invoice_entries()
self.validate_invoice()
dr_or_cr = "credit" if self.party_type == "Customer" else "debit"
dr_or_cr = "credit_in_account_currency" if self.party_type == "Customer" \
else "debit_in_account_currency"
lst = []
for e in self.get('payments'):
if e.invoice_number and e.allocated_amount:

View File

@@ -83,7 +83,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Column Break",
"label": "",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
@@ -144,7 +144,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2014-07-18 12:20:51.269974",
"modified": "2015-10-16 06:14:07.460813",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Reconciliation Invoice",

View File

@@ -229,7 +229,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-09-21 03:39:40.320070",
"modified": "2015-10-02 07:38:59.835936",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Reconciliation Payment",

View File

@@ -141,7 +141,10 @@ frappe.ui.form.on("Payment Tool", "get_outstanding_vouchers", function(frm) {
c.against_voucher_no = d.voucher_no;
c.total_amount = d.invoice_amount;
c.outstanding_amount = d.outstanding_amount;
c.payment_amount = d.outstanding_amount;
if (frm.doc.set_payment_amount) {
c.payment_amount = d.outstanding_amount;
}
});
}
refresh_field("vouchers");

View File

@@ -185,6 +185,28 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "set_payment_amount",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Set Payment Amount = Outstanding Amount",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
@@ -474,7 +496,7 @@
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"modified": "2015-08-31 18:58:21.813054",
"modified": "2015-10-01 09:43:24.199025",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Tool",

View File

@@ -7,6 +7,7 @@ from frappe import _, scrub
from frappe.utils import flt
from frappe.model.document import Document
import json
from erpnext.accounts.utils import get_account_currency
class PaymentTool(Document):
def make_journal_entry(self):
@@ -59,7 +60,7 @@ def get_outstanding_vouchers(args):
args = json.loads(args)
party_account_currency = frappe.db.get_value("Account", args.get("party_account"), "account_currency")
party_account_currency = get_account_currency(args.get("party_account"))
company_currency = frappe.db.get_value("Company", args.get("company"), "default_currency")
if args.get("party_type") == "Customer" and args.get("received_or_paid") == "Received":
@@ -112,7 +113,7 @@ def get_orders_to_be_billed(party_type, party, party_account_currency, company_c
@frappe.whitelist()
def get_against_voucher_amount(against_voucher_type, against_voucher_no, party_account, company):
party_account_currency = frappe.db.get_value("Account", party_account, "account_currency")
party_account_currency = get_account_currency(party_account)
company_currency = frappe.db.get_value("Company", company, "default_currency")
ref_field = "base_grand_total" if party_account_currency == company_currency else "grand_total"

View File

@@ -149,7 +149,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-08-31 18:58:35.537060",
"modified": "2015-10-02 07:38:59.950506",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Tool Detail",

View File

@@ -13,7 +13,7 @@ cur_frm.fields_dict['closing_account_head'].get_query = function(doc, cdt, cdn)
return{
filters:{
"company": doc.company,
"report_type": "Balance Sheet",
"root_type": "Liability",
"freeze_account": "No",
"is_group": 0
}

View File

@@ -194,29 +194,6 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "coa_help",
"fieldtype": "HTML",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "CoA Help",
"no_copy": 0,
"oldfieldtype": "HTML",
"options": "<a href=\"#!Accounts Browser/Account\">To manage Account Head, click here</a>",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
@@ -250,7 +227,7 @@
"is_submittable": 1,
"issingle": 0,
"istable": 0,
"modified": "2015-02-05 05:11:42.268561",
"modified": "2015-10-21 12:40:58.278256",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Period Closing Voucher",

View File

@@ -5,6 +5,7 @@ from __future__ import unicode_literals
import frappe
from frappe.utils import flt
from frappe import _
from erpnext.accounts.utils import get_account_currency
from erpnext.controllers.accounts_controller import AccountsController
class PeriodClosingVoucher(AccountsController):
@@ -20,51 +21,75 @@ class PeriodClosingVoucher(AccountsController):
where voucher_type = 'Period Closing Voucher' and voucher_no=%s""", self.name)
def validate_account_head(self):
if frappe.db.get_value("Account", self.closing_account_head, "report_type") \
!= "Balance Sheet":
frappe.throw(_("Closing Account {0} must be of type 'Liability'").format(self.closing_account_head))
closing_account_type = frappe.db.get_value("Account", self.closing_account_head, "root_type")
if closing_account_type != "Liability":
frappe.throw(_("Closing Account {0} must be of type 'Liability'")
.format(self.closing_account_head))
account_currency = get_account_currency(self.closing_account_head)
company_currency = frappe.db.get_value("Company", self.company, "default_currency")
if account_currency != company_currency:
frappe.throw(_("Currency of the Closing Account must be {0}").format(company_currency))
def validate_posting_date(self):
from erpnext.accounts.utils import get_fiscal_year
from erpnext.accounts.utils import get_fiscal_year, validate_fiscal_year
validate_fiscal_year(self.posting_date, self.fiscal_year, label=_("Posting Date"), doc=self)
self.year_start_date = get_fiscal_year(self.posting_date, self.fiscal_year)[1]
pce = frappe.db.sql("""select name from `tabPeriod Closing Voucher`
where posting_date > %s and fiscal_year = %s and docstatus = 1""",
(self.posting_date, self.fiscal_year))
if pce and pce[0][0]:
frappe.throw(_("Another Period Closing Entry {0} has been made after {1}").format(pce[0][0], self.posting_date))
def get_pl_balances(self):
"""Get balance for pl accounts"""
return frappe.db.sql("""
select t1.account, sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) as balance
from `tabGL Entry` t1, `tabAccount` t2
where t1.account = t2.name and ifnull(t2.report_type, '') = 'Profit and Loss'
and t2.docstatus < 2 and t2.company = %s
and t1.posting_date between %s and %s
group by t1.account
""", (self.company, self.get("year_start_date"), self.posting_date), as_dict=1)
frappe.throw(_("Another Period Closing Entry {0} has been made after {1}")
.format(pce[0][0], self.posting_date))
def make_gl_entries(self):
gl_entries = []
net_pl_balance = 0
pl_accounts = self.get_pl_balances()
for acc in pl_accounts:
if flt(acc.balance):
if flt(acc.balance_in_company_currency):
gl_entries.append(self.get_gl_dict({
"account": acc.account,
"debit": abs(flt(acc.balance)) if flt(acc.balance) < 0 else 0,
"credit": abs(flt(acc.balance)) if flt(acc.balance) > 0 else 0,
"account_currency": acc.account_currency,
"debit_in_account_currency": abs(flt(acc.balance_in_account_currency)) \
if flt(acc.balance_in_account_currency) < 0 else 0,
"debit": abs(flt(acc.balance_in_company_currency)) \
if flt(acc.balance_in_company_currency) < 0 else 0,
"credit_in_account_currency": abs(flt(acc.balance_in_account_currency)) \
if flt(acc.balance_in_account_currency) > 0 else 0,
"credit": abs(flt(acc.balance_in_company_currency)) \
if flt(acc.balance_in_company_currency) > 0 else 0
}))
net_pl_balance += flt(acc.balance)
net_pl_balance += flt(acc.balance_in_company_currency)
if net_pl_balance:
gl_entries.append(self.get_gl_dict({
"account": self.closing_account_head,
"debit_in_account_currency": abs(net_pl_balance) if net_pl_balance > 0 else 0,
"debit": abs(net_pl_balance) if net_pl_balance > 0 else 0,
"credit_in_account_currency": abs(net_pl_balance) if net_pl_balance < 0 else 0,
"credit": abs(net_pl_balance) if net_pl_balance < 0 else 0
}))
from erpnext.accounts.general_ledger import make_gl_entries
make_gl_entries(gl_entries)
def get_pl_balances(self):
"""Get balance for pl accounts"""
return frappe.db.sql("""
select
t1.account, t2.account_currency, sum(ifnull(t1.debit_in_account_currency,0))-sum(ifnull(t1.credit_in_account_currency,0))
as balance_in_account_currency,
sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) as balance_in_company_currency
from `tabGL Entry` t1, `tabAccount` t2
where t1.account = t2.name and ifnull(t2.report_type, '') = 'Profit and Loss'
and t2.docstatus < 2 and t2.company = %s
and t1.posting_date between %s and %s
group by t1.account
""", (self.company, self.get("year_start_date"), self.posting_date), as_dict=1)

View File

@@ -5,42 +5,74 @@
from __future__ import unicode_literals
import unittest
import frappe
from frappe.utils import flt
from frappe.utils import flt, today
from erpnext.accounts.utils import get_fiscal_year
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
class TestPeriodClosingVoucher(unittest.TestCase):
def test_closing_entry(self):
year_start_date = get_fiscal_year(today())[1]
make_journal_entry("_Test Bank - _TC", "Sales - _TC", 400,
"_Test Cost Center - _TC", submit=True)
make_journal_entry("_Test Account Cost for Goods Sold - _TC",
"_Test Bank - _TC", 600, "_Test Cost Center - _TC", submit=True)
random_expense_account = frappe.db.sql("""
select t1.account,
sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) as balance,
sum(ifnull(t1.debit_in_account_currency,0))-sum(ifnull(t1.credit_in_account_currency,0)) \
as balance_in_account_currency
from `tabGL Entry` t1, `tabAccount` t2
where t1.account = t2.name and ifnull(t2.root_type, '') = 'Expense'
and t2.docstatus < 2 and t2.company = '_Test Company'
and t1.posting_date between %s and %s
group by t1.account
having sum(ifnull(t1.debit,0)) > sum(ifnull(t1.credit,0))
limit 1""", (year_start_date, today()), as_dict=True)
profit_or_loss = frappe.db.sql("""select sum(ifnull(t1.debit,0))-sum(ifnull(t1.credit,0)) as balance
from `tabGL Entry` t1, `tabAccount` t2
where t1.account = t2.name and ifnull(t2.report_type, '') = 'Profit and Loss'
and t2.docstatus < 2 and t2.company = '_Test Company'
and t1.posting_date between '2013-01-01' and '2013-12-31'""")
and t1.posting_date between %s and %s""", (year_start_date, today()))
profit_or_loss = flt(profit_or_loss[0][0]) if profit_or_loss else 0
pcv = self.make_period_closing_voucher()
gle_value = frappe.db.sql("""select ifnull(debit, 0) - ifnull(credit, 0)
# Check value for closing account
gle_amount_for_closing_account = frappe.db.sql("""select ifnull(debit, 0) - ifnull(credit, 0)
from `tabGL Entry` where voucher_type='Period Closing Voucher' and voucher_no=%s
and account = '_Test Account Reserves and Surplus - _TC'""", pcv.name)
gle_value = flt(gle_value[0][0]) if gle_value else 0
gle_amount_for_closing_account = flt(gle_amount_for_closing_account[0][0]) \
if gle_amount_for_closing_account else 0
self.assertEqual(gle_value, profit_or_loss)
self.assertEqual(gle_amount_for_closing_account, profit_or_loss)
if random_expense_account:
# Check posted value for teh above random_expense_account
gle_for_random_expense_account = frappe.db.sql("""
select ifnull(debit, 0) - ifnull(credit, 0) as amount,
ifnull(debit_in_account_currency, 0) - ifnull(credit_in_account_currency, 0)
as amount_in_account_currency
from `tabGL Entry`
where voucher_type='Period Closing Voucher' and voucher_no=%s and account =%s""",
(pcv.name, random_expense_account[0].account), as_dict=True)
self.assertEqual(gle_for_random_expense_account[0].amount, -1*random_expense_account[0].balance)
self.assertEqual(gle_for_random_expense_account[0].amount_in_account_currency,
-1*random_expense_account[0].balance_in_account_currency)
def make_period_closing_voucher(self):
pcv = frappe.get_doc({
"doctype": "Period Closing Voucher",
"closing_account_head": "_Test Account Reserves and Surplus - _TC",
"company": "_Test Company",
"fiscal_year": "_Test Fiscal Year 2013",
"posting_date": "2013-12-31",
"fiscal_year": get_fiscal_year(today())[0],
"posting_date": today(),
"remarks": "test"
})
pcv.insert()

View File

@@ -622,7 +622,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-09-07 15:51:26",
"modified": "2015-10-02 07:39:00.196535",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Profile",

View File

@@ -63,7 +63,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Apply On",
"label": "Apply On",
"no_copy": 0,
"options": "\nItem Code\nItem Group\nBrand",
"permlevel": 0,
@@ -176,7 +176,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Priority",
"label": "Priority",
"no_copy": 0,
"options": "\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20",
"permlevel": 0,
@@ -304,7 +304,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Applicable For",
"label": "Applicable For",
"no_copy": 0,
"options": "\nCustomer\nCustomer Group\nTerritory\nSales Partner\nCampaign\nSupplier\nSupplier Type",
"permlevel": 0,
@@ -699,7 +699,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Price or Discount",
"label": "Price or Discount",
"no_copy": 0,
"options": "\nPrice\nDiscount Percentage",
"permlevel": 0,
@@ -851,7 +851,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-09-11 12:19:52.242771",
"modified": "2015-10-02 07:39:00.632196",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Pricing Rule",

View File

@@ -175,7 +175,7 @@ def get_pricing_rules(args):
if parent_groups:
if allow_blank: parent_groups.append('')
condition = " ifnull("+field+", '') in ('" + \
"', '".join([d.replace("'", "\\'").replace('"', '\\"') for d in parent_groups])+"')"
"', '".join([d.replace("'", "\\'").replace('"', '\\"').replace("%", "%%") for d in parent_groups])+"')"
return condition

File diff suppressed because it is too large Load Diff

View File

@@ -10,6 +10,7 @@ import frappe.defaults
from erpnext.controllers.buying_controller import BuyingController
from erpnext.accounts.party import get_party_account, get_due_date
from erpnext.accounts.utils import get_account_currency
form_grid_templates = {
"items": "templates/form_grid/item_grid.html"
@@ -66,7 +67,7 @@ class PurchaseInvoice(BuyingController):
def set_missing_values(self, for_validate=False):
if not self.credit_to:
self.credit_to = get_party_account(self.company, self.supplier, "Supplier")
self.credit_to = get_party_account("Supplier", self.supplier, self.company)
if not self.due_date:
self.due_date = get_due_date(self.posting_date, "Supplier", self.supplier, self.company)
@@ -75,7 +76,7 @@ class PurchaseInvoice(BuyingController):
def get_advances(self):
if not self.is_return:
super(PurchaseInvoice, self).get_advances(self.credit_to, "Supplier", self.supplier,
"Purchase Invoice Advance", "advances", "debit", "purchase_order")
"Purchase Invoice Advance", "advances", "debit_in_account_currency", "purchase_order")
def check_active_purchase_items(self):
for d in self.get('items'):
@@ -91,7 +92,7 @@ class PurchaseInvoice(BuyingController):
throw(_("Conversion rate cannot be 0 or 1"))
def validate_credit_to_acc(self):
account = frappe.db.get_value("Account", self.credit_to,
account = frappe.db.get_value("Account", self.credit_to,
["account_type", "report_type", "account_currency"], as_dict=True)
if account.report_type != "Balance Sheet":
@@ -99,7 +100,7 @@ class PurchaseInvoice(BuyingController):
if self.supplier and account.account_type != "Payable":
frappe.throw(_("Credit To account must be a Payable account"))
self.party_account_currency = account.account_currency
def check_for_stopped_status(self):
@@ -251,7 +252,7 @@ class PurchaseInvoice(BuyingController):
expenses_included_in_valuation = self.get_company_default("expenses_included_in_valuation")
gl_entries = []
# parent's gl entry
if self.base_grand_total:
gl_entries.append(
@@ -272,10 +273,10 @@ class PurchaseInvoice(BuyingController):
valuation_tax = {}
for tax in self.get("taxes"):
if tax.category in ("Total", "Valuation and Total") and flt(tax.base_tax_amount_after_discount_amount):
account_currency = frappe.db.get_value("Account", tax.account_head, "account_currency")
account_currency = get_account_currency(tax.account_head)
dr_or_cr = "debit" if tax.add_deduct_tax == "Add" else "credit"
gl_entries.append(
self.get_gl_dict({
"account": tax.account_head,
@@ -301,7 +302,7 @@ class PurchaseInvoice(BuyingController):
stock_items = self.get_stock_items()
for item in self.get("items"):
if flt(item.base_net_amount):
account_currency = frappe.db.get_value("Account", item.expense_account, "account_currency")
account_currency = get_account_currency(item.expense_account)
gl_entries.append(
self.get_gl_dict({
"account": item.expense_account,
@@ -316,23 +317,22 @@ class PurchaseInvoice(BuyingController):
if auto_accounting_for_stock and self.is_opening == "No" and \
item.item_code in stock_items and item.item_tax_amount:
# Post reverse entry for Stock-Received-But-Not-Billed if it is booked in Purchase Receipt
negative_expense_booked_in_pi = None
if item.purchase_receipt:
negative_expense_booked_in_pi = frappe.db.sql("""select name from `tabGL Entry`
negative_expense_booked_in_pr = frappe.db.sql("""select name from `tabGL Entry`
where voucher_type='Purchase Receipt' and voucher_no=%s and account=%s""",
(item.purchase_receipt, expenses_included_in_valuation))
if not negative_expense_booked_in_pi:
gl_entries.append(
self.get_gl_dict({
"account": stock_received_but_not_billed,
"against": self.supplier,
"debit": flt(item.item_tax_amount, self.precision("item_tax_amount", item)),
"remarks": self.remarks or "Accounting Entry for Stock"
})
)
if not negative_expense_booked_in_pr:
gl_entries.append(
self.get_gl_dict({
"account": stock_received_but_not_billed,
"against": self.supplier,
"debit": flt(item.item_tax_amount, self.precision("item_tax_amount", item)),
"remarks": self.remarks or "Accounting Entry for Stock"
})
)
negative_expense_to_be_booked += flt(item.item_tax_amount, self.precision("item_tax_amount", item))
negative_expense_to_be_booked += flt(item.item_tax_amount, self.precision("item_tax_amount", item))
if self.is_opening == "No" and negative_expense_to_be_booked and valuation_tax:
# credit valuation tax amount in "Expenses Included In Valuation"
@@ -363,8 +363,8 @@ class PurchaseInvoice(BuyingController):
# writeoff account includes petty difference in the invoice amount
# and the amount that is paid
if self.write_off_account and flt(self.write_off_amount):
write_off_account_currency = frappe.db.get_value("Account", self.write_off_account, "account_currency")
write_off_account_currency = get_account_currency(self.write_off_account)
gl_entries.append(
self.get_gl_dict({
"account": self.credit_to,
@@ -420,7 +420,7 @@ class PurchaseInvoice(BuyingController):
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, "name": ("!=", self.name)})
"fiscal_year": self.fiscal_year, "name": ("!=", self.name), "docstatus": ("<", 2)})
if pi:
frappe.throw("Supplier Invoice No exists in Purchase Invoice {0}".format(pi))

View File

@@ -10,7 +10,7 @@ from frappe.utils import cint
import frappe.defaults
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory, \
test_records as pr_test_records
from erpnext.controllers.accounts_controller import InvalidCurrency
from erpnext.exceptions import InvalidCurrency
test_dependencies = ["Item", "Cost Center"]
test_ignore = ["Serial No"]
@@ -49,25 +49,9 @@ class TestPurchaseInvoice(unittest.TestCase):
pi = frappe.copy_doc(test_records[1])
pi.insert()
pi.submit()
gl_entries = frappe.db.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s
order by account asc""", pi.name, as_dict=1)
self.assertTrue(gl_entries)
expected_values = dict((d[0], d) for d in [
["_Test Payable - _TC", 0, 720],
["Stock Received But Not Billed - _TC", 750.0, 0],
["Expenses Included In Valuation - _TC", 0.0, 250.0],
["_Test Account Shipping Charges - _TC", 100.0, 0],
["_Test Account VAT - _TC", 120.0, 0],
])
for i, gle in enumerate(gl_entries):
self.assertEquals(expected_values[gle.account][0], gle.account)
self.assertEquals(expected_values[gle.account][1], gle.debit)
self.assertEquals(expected_values[gle.account][2], gle.credit)
self.check_gle_for_pi(pi.name)
set_perpetual_inventory(0)
def test_gl_entries_with_auto_accounting_for_stock_against_pr(self):
@@ -83,9 +67,14 @@ class TestPurchaseInvoice(unittest.TestCase):
pi.insert()
pi.submit()
self.check_gle_for_pi(pi.name)
set_perpetual_inventory(0)
def check_gle_for_pi(self, pi):
gl_entries = frappe.db.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s
order by account asc""", pi.name, as_dict=1)
order by account asc""", pi, as_dict=1)
self.assertTrue(gl_entries)
expected_values = dict((d[0], d) for d in [
@@ -100,8 +89,6 @@ class TestPurchaseInvoice(unittest.TestCase):
self.assertEquals(expected_values[gle.account][1], gle.debit)
self.assertEquals(expected_values[gle.account][2], gle.credit)
set_perpetual_inventory(0)
def test_gl_entries_with_aia_for_non_stock_items(self):
set_perpetual_inventory()
self.assertEqual(cint(frappe.defaults.get_global_default("auto_accounting_for_stock")), 1)
@@ -219,7 +206,7 @@ class TestPurchaseInvoice(unittest.TestCase):
pi.load_from_db()
self.assertTrue(frappe.db.sql("""select name from `tabJournal Entry Account`
where reference_type='Purchase Invoice'
where reference_type='Purchase Invoice'
and reference_name=%s and debit_in_account_currency=300""", pi.name))
self.assertEqual(pi.outstanding_amount, 1212.30)
@@ -237,17 +224,17 @@ class TestPurchaseInvoice(unittest.TestCase):
existing_purchase_cost = frappe.db.sql("""select sum(ifnull(base_net_amount, 0))
from `tabPurchase Invoice Item` where project_name = '_Test Project' and docstatus=1""")
existing_purchase_cost = existing_purchase_cost and existing_purchase_cost[0][0] or 0
pi = make_purchase_invoice(currency="USD", conversion_rate=60, project_name="_Test Project")
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"),
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"),
existing_purchase_cost + 15000)
pi1 = make_purchase_invoice(qty=10, project_name="_Test Project")
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"),
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"),
existing_purchase_cost + 15500)
pi1.cancel()
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"),
self.assertEqual(frappe.db.get_value("Project", "_Test Project", "total_purchase_cost"),
existing_purchase_cost + 15000)
pi.cancel()
@@ -278,14 +265,14 @@ class TestPurchaseInvoice(unittest.TestCase):
self.assertEquals(expected_values[gle.account][1], gle.credit)
set_perpetual_inventory(0)
def test_multi_currency_gle(self):
set_perpetual_inventory(0)
pi = make_purchase_invoice(supplier="_Test Supplier USD", credit_to="_Test Payable USD - _TC",
pi = make_purchase_invoice(supplier="_Test Supplier USD", credit_to="_Test Payable USD - _TC",
currency="USD", conversion_rate=50)
gl_entries = frappe.db.sql("""select account, account_currency, debit, credit,
gl_entries = frappe.db.sql("""select account, account_currency, debit, credit,
debit_in_account_currency, credit_in_account_currency
from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no=%s
order by account asc""", pi.name, as_dict=1)
@@ -308,16 +295,16 @@ class TestPurchaseInvoice(unittest.TestCase):
"credit_in_account_currency": 0
}
}
for field in ("account_currency", "debit", "debit_in_account_currency", "credit", "credit_in_account_currency"):
for i, gle in enumerate(gl_entries):
self.assertEquals(expected_values[gle.account][field], gle[field])
# Check for valid currency
pi1 = make_purchase_invoice(supplier="_Test Supplier USD", credit_to="_Test Payable USD - _TC",
do_not_save=True)
self.assertRaises(InvalidCurrency, pi1.save)
# cancel

View File

@@ -164,7 +164,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-08-25 17:51:30.274069",
"modified": "2015-10-02 07:39:03.538046",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Advance",

View File

@@ -1093,7 +1093,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-08-26 12:28:16.728059",
"modified": "2015-10-19 03:04:52.304768",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",

View File

@@ -19,7 +19,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Consider Tax or Charge for",
"label": "Consider Tax or Charge for",
"no_copy": 0,
"oldfieldname": "category",
"oldfieldtype": "Select",
@@ -44,7 +44,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Add or Deduct",
"label": "Add or Deduct",
"no_copy": 0,
"oldfieldname": "add_deduct_tax",
"oldfieldtype": "Select",
@@ -68,7 +68,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Type",
"label": "Type",
"no_copy": 0,
"oldfieldname": "charge_type",
"oldfieldtype": "Select",
@@ -504,7 +504,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-08-28 02:57:08.769473",
"modified": "2015-10-02 07:39:06.372275",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Taxes and Charges",

View File

@@ -176,7 +176,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-09-11 12:19:53.741725",
"modified": "2015-10-02 07:39:06.563868",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Taxes and Charges Template",

View File

@@ -376,7 +376,7 @@ cur_frm.fields_dict['project_name'].get_query = function(doc, cdt, cdn) {
// --------------------------------
cur_frm.set_query("income_account", "items", function(doc) {
return{
query: "erpnext.accounts.doctype.sales_invoice.sales_invoice.get_income_account",
query: "erpnext.controllers.queries.get_income_account",
filters: {'company': doc.company}
}
});

View File

@@ -65,7 +65,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Series",
"label": "Series",
"no_copy": 1,
"oldfieldname": "naming_series",
"oldfieldtype": "Select",
@@ -671,7 +671,7 @@
"unique": 0
},
{
"allow_on_submit": 1,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "items",
@@ -1002,7 +1002,7 @@
"unique": 0
},
{
"allow_on_submit": 1,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "taxes",
@@ -1168,7 +1168,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Apply Additional Discount On",
"label": "Apply Additional Discount On",
"no_copy": 0,
"options": "\nGrand Total\nNet Total",
"permlevel": 0,
@@ -2211,7 +2211,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Source",
"label": "Source",
"no_copy": 0,
"oldfieldname": "source",
"oldfieldtype": "Select",
@@ -2308,7 +2308,7 @@
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "Is Opening Entry",
"label": "Is Opening Entry",
"no_copy": 0,
"oldfieldname": "is_opening",
"oldfieldtype": "Select",
@@ -2332,7 +2332,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "C-Form Applicable",
"label": "C-Form Applicable",
"no_copy": 1,
"options": "No\nYes",
"permlevel": 0,
@@ -2700,7 +2700,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Recurring Type",
"label": "Recurring Type",
"no_copy": 1,
"options": "\nMonthly\nQuarterly\nHalf-yearly\nYearly",
"permlevel": 0,
@@ -2951,7 +2951,7 @@
"is_submittable": 1,
"issingle": 0,
"istable": 0,
"modified": "2015-09-23 09:52:09.675668",
"modified": "2015-10-02 07:39:09.123982",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",

View File

@@ -11,6 +11,7 @@ from erpnext.controllers.stock_controller import update_gl_entries_after
from frappe.model.mapper import get_mapped_doc
from erpnext.controllers.selling_controller import SellingController
from erpnext.accounts.utils import get_account_currency
form_grid_templates = {
"items": "templates/form_grid/item_grid.html"
@@ -186,7 +187,7 @@ class SalesInvoice(SellingController):
pos = self.set_pos_fields(for_validate)
if not self.debit_to:
self.debit_to = get_party_account(self.company, self.customer, "Customer")
self.debit_to = get_party_account("Customer", self.customer, self.company)
if not self.due_date and self.customer:
self.due_date = get_due_date(self.posting_date, "Customer", self.customer, self.company)
@@ -206,8 +207,8 @@ class SalesInvoice(SellingController):
def validate_time_logs_are_submitted(self):
for d in self.get("items"):
if d.time_log_batch:
status = frappe.db.get_value("Time Log Batch", d.time_log_batch, "status")
if status!="Submitted":
docstatus = frappe.db.get_value("Time Log Batch", d.time_log_batch, "docstatus")
if docstatus!=1:
frappe.throw(_("Time Log Batch {0} must be 'Submitted'").format(d.time_log_batch))
def set_pos_fields(self, for_validate=False):
@@ -255,7 +256,7 @@ class SalesInvoice(SellingController):
def get_advances(self):
if not self.is_return:
super(SalesInvoice, self).get_advances(self.debit_to, "Customer", self.customer,
"Sales Invoice Advance", "advances", "credit", "sales_order")
"Sales Invoice Advance", "advances", "credit_in_account_currency", "sales_order")
def get_company_abbr(self):
return frappe.db.sql("select abbr from tabCompany where name=%s", self.company)[0][0]
@@ -421,7 +422,7 @@ class SalesInvoice(SellingController):
def update_packing_list(self):
if cint(self.update_stock) == 1:
from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
make_packing_list(self, 'items')
make_packing_list(self)
else:
self.set('packed_items', [])
@@ -531,7 +532,7 @@ class SalesInvoice(SellingController):
def make_tax_gl_entries(self, gl_entries):
for tax in self.get("taxes"):
if flt(tax.base_tax_amount_after_discount_amount):
account_currency = frappe.db.get_value("Account", tax.account_head, "account_currency")
account_currency = get_account_currency(tax.account_head)
gl_entries.append(
self.get_gl_dict({
"account": tax.account_head,
@@ -547,7 +548,7 @@ class SalesInvoice(SellingController):
# income account gl entries
for item in self.get("items"):
if flt(item.base_net_amount):
account_currency = frappe.db.get_value("Account", item.income_account, "account_currency")
account_currency = get_account_currency(item.income_account)
gl_entries.append(
self.get_gl_dict({
"account": item.income_account,
@@ -566,7 +567,7 @@ class SalesInvoice(SellingController):
def make_pos_gl_entries(self, gl_entries):
if cint(self.is_pos) and self.cash_bank_account and self.paid_amount:
bank_account_currency = frappe.db.get_value("Account", self.cash_bank_account, "account_currency")
bank_account_currency = get_account_currency(self.cash_bank_account)
# POS, make payment entries
gl_entries.append(
self.get_gl_dict({
@@ -594,7 +595,7 @@ class SalesInvoice(SellingController):
def make_write_off_gl_entry(self, gl_entries):
# write off entries, applicable if only pos
if self.write_off_account and self.write_off_amount:
write_off_account_currency = frappe.db.get_value("Account", self.write_off_account, "account_currency")
write_off_account_currency = get_account_currency(self.write_off_account)
gl_entries.append(
self.get_gl_dict({
@@ -636,24 +637,6 @@ def get_bank_cash_account(mode_of_payment, company):
"account": account
}
@frappe.whitelist()
def get_income_account(doctype, txt, searchfield, start, page_len, filters):
from erpnext.controllers.queries import get_match_cond
# income account can be any Credit account,
# but can also be a Asset account with account_type='Income Account' in special circumstances.
# Hence the first condition is an "OR"
return frappe.db.sql("""select tabAccount.name from `tabAccount`
where (tabAccount.report_type = "Profit and Loss"
or tabAccount.account_type in ("Income Account", "Temporary"))
and tabAccount.is_group=0
and tabAccount.docstatus!=2
and tabAccount.company = '%(company)s'
and tabAccount.%(key)s LIKE '%(txt)s'
%(mcond)s""" % {'company': filters['company'], 'key': searchfield,
'txt': "%%%s%%" % frappe.db.escape(txt), 'mcond':get_match_cond(doctype)})
@frappe.whitelist()
def make_delivery_note(source_name, target_doc=None):
def set_missing_values(source, target):

View File

@@ -7,8 +7,9 @@ import unittest, copy
from frappe.utils import nowdate, add_days, flt
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
from erpnext.controllers.accounts_controller import InvalidCurrency
from erpnext.accounts.doctype.gl_entry.gl_entry import InvalidAccountCurrency
from erpnext.exceptions import InvalidAccountCurrency, InvalidCurrency
from erpnext.stock.doctype.serial_no.serial_no import SerialNoWarehouseError
from frappe.model.naming import make_autoname
class TestSalesInvoice(unittest.TestCase):
def make(self):
@@ -689,7 +690,6 @@ class TestSalesInvoice(unittest.TestCase):
si.insert()
si.submit()
self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0], "status"), "Delivered")
self.assertFalse(frappe.db.get_value("Serial No", serial_nos[0], "warehouse"))
self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0],
"delivery_document_no"), si.name)
@@ -703,33 +703,26 @@ class TestSalesInvoice(unittest.TestCase):
serial_nos = get_serial_nos(si.get("items")[0].serial_no)
self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0], "status"), "Available")
self.assertEquals(frappe.db.get_value("Serial No", serial_nos[0], "warehouse"), "_Test Warehouse - _TC")
self.assertFalse(frappe.db.get_value("Serial No", serial_nos[0],
"delivery_document_no"))
def test_serialize_status(self):
from erpnext.stock.doctype.serial_no.serial_no import SerialNoStatusError, get_serial_nos, SerialNoDuplicateError
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
se = make_serialized_item()
serial_nos = get_serial_nos(se.get("items")[0].serial_no)
sr = frappe.get_doc("Serial No", serial_nos[0])
sr.status = "Not Available"
sr.save()
serial_no = frappe.get_doc({
"doctype": "Serial No",
"item_code": "_Test Serialized Item With Series",
"serial_no": make_autoname("SR", "Serial No")
})
serial_no.save()
si = frappe.copy_doc(test_records[0])
si.update_stock = 1
si.get("items")[0].item_code = "_Test Serialized Item With Series"
si.get("items")[0].qty = 1
si.get("items")[0].serial_no = serial_nos[0]
si.get("items")[0].serial_no = serial_no.name
si.insert()
self.assertRaises(SerialNoStatusError, si.submit)
# hack! because stock ledger entires are already inserted and are not rolled back!
self.assertRaises(SerialNoDuplicateError, si.cancel)
self.assertRaises(SerialNoWarehouseError, si.submit)
def test_invoice_due_date_against_customers_credit_days(self):
# set customer's credit days
@@ -842,13 +835,13 @@ class TestSalesInvoice(unittest.TestCase):
self.assertEquals(si.total_taxes_and_charges, 234.44)
self.assertEquals(si.base_grand_total, 859.44)
self.assertEquals(si.grand_total, 859.44)
def test_multi_currency_gle(self):
set_perpetual_inventory(0)
si = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
si = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
currency="USD", conversion_rate=50)
gl_entries = frappe.db.sql("""select account, account_currency, debit, credit,
gl_entries = frappe.db.sql("""select account, account_currency, debit, credit,
debit_in_account_currency, credit_in_account_currency
from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
order by account asc""", si.name, as_dict=1)
@@ -871,7 +864,7 @@ class TestSalesInvoice(unittest.TestCase):
"credit_in_account_currency": 5000
}
}
for field in ("account_currency", "debit", "debit_in_account_currency", "credit", "credit_in_account_currency"):
for i, gle in enumerate(gl_entries):
self.assertEquals(expected_values[gle.account][field], gle[field])
@@ -883,38 +876,38 @@ class TestSalesInvoice(unittest.TestCase):
where voucher_type='Sales Invoice' and voucher_no=%s""", si.name)
self.assertFalse(gle)
def test_invalid_currency(self):
# Customer currency = USD
# Transaction currency cannot be INR
si1 = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
si1 = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
do_not_save=True)
self.assertRaises(InvalidCurrency, si1.save)
# Transaction currency cannot be EUR
si2 = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
si2 = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
currency="EUR", conversion_rate=80, do_not_save=True)
self.assertRaises(InvalidCurrency, si2.save)
# Transaction currency only allowed in USD
si3 = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
si3 = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC",
currency="USD", conversion_rate=50)
# Party Account currency must be in USD, as there is existing GLE with USD
si4 = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable - _TC",
si4 = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable - _TC",
currency="USD", conversion_rate=50, do_not_submit=True)
self.assertRaises(InvalidAccountCurrency, si4.submit)
# Party Account currency must be in USD, force customer currency as there is no GLE
si3.cancel()
si5 = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable - _TC",
si5 = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable - _TC",
currency="USD", conversion_rate=50, do_not_submit=True)
self.assertRaises(InvalidAccountCurrency, si5.submit)
def create_sales_invoice(**args):

View File

@@ -164,7 +164,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-08-21 16:22:28.866049",
"modified": "2015-10-02 07:39:09.979547",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Advance",

View File

@@ -843,6 +843,29 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "target_warehouse",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Target Warehouse",
"no_copy": 0,
"options": "Warehouse",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
@@ -1259,7 +1282,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-08-20 17:18:52.752064",
"modified": "2015-10-19 03:04:52.093181",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice Item",

View File

@@ -18,7 +18,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Type",
"label": "Type",
"no_copy": 0,
"oldfieldname": "charge_type",
"oldfieldtype": "Select",
@@ -456,7 +456,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-08-28 02:57:00.766305",
"modified": "2015-10-02 07:39:11.977789",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Taxes and Charges",

View File

@@ -175,7 +175,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-09-17 07:09:28.797959",
"modified": "2015-10-02 07:39:12.157257",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Taxes and Charges Template",

View File

@@ -1,397 +1,397 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "field:label",
"creation": "2013-06-25 11:48:03",
"custom": 0,
"description": "Specify conditions to calculate shipping amount",
"docstatus": 0,
"doctype": "DocType",
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"autoname": "field:label",
"creation": "2013-06-25 11:48:03",
"custom": 0,
"description": "Specify conditions to calculate shipping amount",
"docstatus": 0,
"doctype": "DocType",
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"description": "example: Next Day Shipping",
"fieldname": "label",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Shipping Rule Label",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"description": "example: Next Day Shipping",
"fieldname": "label",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Shipping Rule Label",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "disabled",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Disabled",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "disabled",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Disabled",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"default": "Net Total",
"fieldname": "calculate_based_on",
"fieldtype": "Select",
"hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Calculate Based On",
"no_copy": 0,
"options": "Net Total\nNet Weight",
"permlevel": 0,
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"default": "Net Total",
"fieldname": "calculate_based_on",
"fieldtype": "Select",
"hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Calculate Based On",
"no_copy": 0,
"options": "Net Total\nNet Weight",
"permlevel": 0,
"print_hide": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"depends_on": "eval:!doc.disabled",
"fieldname": "rule_conditions_section",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Shipping Rule Conditions",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"depends_on": "eval:!doc.disabled",
"fieldname": "rule_conditions_section",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Shipping Rule Conditions",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "conditions",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Shipping Rule Conditions",
"no_copy": 0,
"options": "Shipping Rule Condition",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "conditions",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Shipping Rule Conditions",
"no_copy": 0,
"options": "Shipping Rule Condition",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"depends_on": "eval:!doc.disabled",
"fieldname": "section_break_6",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Valid for Countries",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"depends_on": "eval:!doc.disabled",
"fieldname": "section_break_6",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Valid for Countries",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "worldwide_shipping",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Worldwide Shipping",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "worldwide_shipping",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Worldwide Shipping",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"depends_on": "eval:!doc.worldwide_shipping",
"fieldname": "countries",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Valid for Countries",
"no_copy": 0,
"options": "Shipping Rule Country",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"depends_on": "eval:!doc.worldwide_shipping",
"fieldname": "countries",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Valid for Countries",
"no_copy": 0,
"options": "Shipping Rule Country",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"depends_on": "eval:!doc.disabled",
"fieldname": "section_break_10",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"depends_on": "eval:!doc.disabled",
"fieldname": "section_break_10",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Company",
"no_copy": 0,
"options": "Company",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Company",
"no_copy": 0,
"options": "Company",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "column_break_12",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "column_break_12",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "account",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Shipping Account",
"no_copy": 0,
"options": "Account",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "account",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Shipping Account",
"no_copy": 0,
"options": "Account",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "cost_center",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Cost Center",
"no_copy": 0,
"options": "Cost Center",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "cost_center",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Cost Center",
"no_copy": 0,
"options": "Cost Center",
"permlevel": 0,
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "icon-truck",
"idx": 1,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-09-22 08:30:57.226342",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Shipping Rule",
"owner": "Administrator",
],
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "icon-truck",
"idx": 1,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-10-02 07:39:12.778062",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Shipping Rule",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 1,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts User",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"amend": 0,
"apply_user_permissions": 1,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts User",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
},
},
{
"amend": 0,
"apply_user_permissions": 1,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales User",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"amend": 0,
"apply_user_permissions": 1,
"cancel": 0,
"create": 0,
"delete": 0,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales User",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 0
},
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
},
},
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales Master Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 1,
"email": 1,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Sales Master Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
"write": 1
}
],
"read_only": 0,
],
"read_only": 0,
"read_only_onload": 0
}
}

View File

@@ -81,7 +81,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2013-12-20 19:21:46",
"modified": "2015-10-02 07:39:12.974539",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Shipping Rule Condition",

View File

@@ -39,7 +39,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-09-17 06:43:22.767534",
"modified": "2015-10-02 07:39:13.035775",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Shipping Rule Country",

View File

@@ -20,7 +20,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Tax Type",
"label": "Tax Type",
"no_copy": 0,
"options": "Sales\nPurchase",
"permlevel": 0,
@@ -580,7 +580,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-09-15 12:29:34.435839",
"modified": "2015-10-02 07:39:16.298546",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Tax Rule",
@@ -601,7 +601,7 @@
"print": 1,
"read": 1,
"report": 1,
"role": "Administrator",
"role": "Accounts Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,

View File

@@ -12,25 +12,15 @@ test_records = frappe.get_test_records('Tax Rule')
class TestTaxRule(unittest.TestCase):
def setUp(self):
frappe.db.sql("delete from `tabTax Rule` where use_for_shopping_cart <> 1")
def test_customer_group(self):
tax_rule = make_tax_rule(customer= "_Test Customer", customer_group= "_Test Customer Group 1",
sales_tax_template = "_Test Sales Taxes and Charges Template")
self.assertRaises(IncorrectCustomerGroup, tax_rule.save)
def test_supplier_type(self):
tax_rule = make_tax_rule(tax_type= "Purchase", supplier= "_Test Supplier", supplier_type= "_Test Supplier Type 1",
purchase_tax_template = "_Test Purchase Taxes and Charges Template")
self.assertRaises(IncorrectSupplierType, tax_rule.save)
def test_conflict(self):
def test_conflict(self):
tax_rule1 = make_tax_rule(customer= "_Test Customer",
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1)
tax_rule1.save()
tax_rule2 = make_tax_rule(customer= "_Test Customer",
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1)
self.assertRaises(ConflictingTaxRule, tax_rule2.save)
def test_conflict_with_non_overlapping_dates(self):
@@ -40,25 +30,25 @@ class TestTaxRule(unittest.TestCase):
tax_rule2 = make_tax_rule(customer= "_Test Customer",
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, to_date = "2013-01-01")
tax_rule2.save()
self.assertTrue(tax_rule2.name)
def test_conflict_with_overlapping_dates(self):
def test_conflict_with_overlapping_dates(self):
tax_rule1 = make_tax_rule(customer= "_Test Customer",
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, from_date = "2015-01-01", to_date = "2015-01-05")
tax_rule1.save()
tax_rule2 = make_tax_rule(customer= "_Test Customer",
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, from_date = "2015-01-03", to_date = "2015-01-09")
self.assertRaises(ConflictingTaxRule, tax_rule2.save)
def test_tax_template(self):
tax_rule = make_tax_rule()
self.assertEquals(tax_rule.purchase_tax_template, None)
def test_select_tax_rule_based_on_customer(self):
make_tax_rule(customer= "_Test Customer",
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
@@ -68,8 +58,8 @@ class TestTaxRule(unittest.TestCase):
make_tax_rule(customer= "_Test Customer 2",
sales_tax_template = "_Test Sales Taxes and Charges Template 2", save=1)
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer 2"}),
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer 2"}),
"_Test Sales Taxes and Charges Template 2")
def test_select_tax_rule_based_on_better_match(self):
@@ -78,18 +68,18 @@ class TestTaxRule(unittest.TestCase):
make_tax_rule(customer= "_Test Customer", billing_city = "Test City1", billing_state = "Test State",
sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1)
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City", "billing_state": "Test State"}),
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City", "billing_state": "Test State"}),
"_Test Sales Taxes and Charges Template")
def test_select_tax_rule_based_on_state_match(self):
make_tax_rule(customer= "_Test Customer", shipping_state = "Test State",
make_tax_rule(customer= "_Test Customer", shipping_state = "Test State",
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
make_tax_rule(customer= "_Test Customer", shipping_state = "Test State12",
make_tax_rule(customer= "_Test Customer", shipping_state = "Test State12",
sales_tax_template = "_Test Sales Taxes and Charges Template 1", priority=2, save=1)
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "shipping_state": "Test State"}),
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "shipping_state": "Test State"}),
"_Test Sales Taxes and Charges Template")
def test_select_tax_rule_based_on_better_priority(self):
@@ -98,18 +88,18 @@ class TestTaxRule(unittest.TestCase):
make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
sales_tax_template = "_Test Sales Taxes and Charges Template 1", priority=2, save=1)
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City"}),
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City"}),
"_Test Sales Taxes and Charges Template 1")
def test_select_tax_rule_based_cross_matching_keys(self):
make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
make_tax_rule(customer= "_Test Customer 1", billing_city = "Test City 1",
sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1)
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City 1"}),
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City 1"}),
None)
def test_select_tax_rule_based_cross_partially_keys(self):
@@ -118,24 +108,23 @@ class TestTaxRule(unittest.TestCase):
make_tax_rule(billing_city = "Test City 1",
sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1)
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City 1"}),
self.assertEquals(get_tax_template("2015-01-01", {"customer":"_Test Customer", "billing_city": "Test City 1"}),
"_Test Sales Taxes and Charges Template 1")
def make_tax_rule(**args):
args = frappe._dict(args)
tax_rule = frappe.new_doc("Tax Rule")
for key, val in args.iteritems():
if key != "save":
tax_rule.set(key, val)
tax_rule.company = args.company or "_Test Company"
if args.save:
tax_rule.insert()
return tax_rule

View File

@@ -10,9 +10,9 @@ from frappe.defaults import get_user_permissions
from frappe.utils import add_days, getdate, formatdate, get_first_day, date_diff
from erpnext.utilities.doctype.address.address import get_address_display
from erpnext.utilities.doctype.contact.contact import get_contact_details
from erpnext.exceptions import InvalidAccountCurrency
class InvalidCurrency(frappe.ValidationError): pass
class InvalidAccountCurrency(frappe.ValidationError): pass
class DuplicatePartyAccountError(frappe.ValidationError): pass
@frappe.whitelist()
def get_party_details(party=None, account=None, party_type="Customer", company=None,
@@ -51,7 +51,8 @@ def _get_party_details(party=None, account=None, party_type="Customer", company=
# sales team
if party_type=="Customer":
out["sales_team"] = [{
"sales_person": d.sales_person
"sales_person": d.sales_person,
"allocated_percentage": d.allocated_percentage or None
} for d in party.get("sales_team")]
return out
@@ -142,7 +143,7 @@ def set_account_and_due_date(party, account, party_type, company, posting_date,
}
if party:
account = get_party_account(company, party, party_type)
account = get_party_account(party_type, party, company)
account_fieldname = "debit_to" if party_type=="Customer" else "credit_to"
@@ -153,44 +154,6 @@ def set_account_and_due_date(party, account, party_type, company, posting_date,
}
return out
def validate_accounting_currency(party):
party_account_currency_in_db = frappe.db.get_value(party.doctype, party.name, "party_account_currency")
if party_account_currency_in_db != party.party_account_currency:
existing_gle = frappe.db.get_value("GL Entry", {"party_type": party.doctype,
"party": party.name}, ["name", "account_currency"], as_dict=1)
if existing_gle:
if party_account_currency_in_db:
frappe.throw(_("Accounting Currency cannot be changed, as GL Entry exists for this {0}")
.format(party.doctype), InvalidCurrency)
else:
party.party_account_currency = existing_gle.account_currency
def validate_party_account(party):
company_currency = get_company_currency()
if party.party_account_currency:
companies_with_different_currency = []
for company, currency in company_currency.items():
if currency != party.party_account_currency:
companies_with_different_currency.append(company)
for d in party.get("accounts"):
if d.company in companies_with_different_currency:
companies_with_different_currency.remove(d.company)
selected_account_currency = frappe.db.get_value("Account", d.account, "account_currency")
if selected_account_currency != party.party_account_currency:
frappe.throw(_("Account {0} is invalid, account currency must be {1}")
.format(d.account, selected_account_currency), InvalidAccountCurrency)
if companies_with_different_currency:
frappe.msgprint(_("Please mention Default {0} Account for the following companies, as accounting currency is different from company's default currency: {1}")
.format(
"Receivable" if party.doctype=="Customer" else "Payable",
"\n" + "\n".join(companies_with_different_currency)
)
)
def get_company_currency():
company_currency = frappe._dict()
for d in frappe.get_all("Company", fields=["name", "default_currency"]):
@@ -199,13 +162,13 @@ def get_company_currency():
return company_currency
@frappe.whitelist()
def get_party_account(company, party, party_type):
def get_party_account(party_type, party, company):
"""Returns the account for the given `party`.
Will first search in party (Customer / Supplier) record, if not found,
will search in group (Customer Group / Supplier Type),
finally will return default."""
if not company:
frappe.throw(_("Please select company first."))
frappe.throw(_("Please select a Company"))
if party:
account = frappe.db.get_value("Party Account",
@@ -223,6 +186,50 @@ def get_party_account(company, party, party_type):
return account
def get_party_account_currency(party_type, party, company):
def generator():
party_account = get_party_account(party_type, party, company)
return frappe.db.get_value("Account", party_account, "account_currency")
return frappe.local_cache("party_account_currency", (party_type, party, company), generator)
def get_party_gle_currency(party_type, party, company):
def generator():
existing_gle_currency = frappe.db.sql("""select account_currency from `tabGL Entry`
where docstatus=1 and company=%(company)s and party_type=%(party_type)s and party=%(party)s
limit 1""", { "company": company, "party_type": party_type, "party": party })
return existing_gle_currency[0][0] if existing_gle_currency else None
return frappe.local_cache("party_gle_currency", (party_type, party, company), generator)
def validate_party_gle_currency(party_type, party, company, party_account_currency=None):
"""Validate party account currency with existing GL Entry's currency"""
if not party_account_currency:
party_account_currency = get_party_account_currency(party_type, party, company)
existing_gle_currency = get_party_gle_currency(party_type, party, company)
if existing_gle_currency and party_account_currency != existing_gle_currency:
frappe.throw(_("Accounting Entry for {0}: {1} can only be made in currency: {2}")
.format(party_type, party, existing_gle_currency), InvalidAccountCurrency)
def validate_party_accounts(doc):
companies = []
for account in doc.get("accounts"):
if account.company in companies:
frappe.throw(_("There can only be 1 Account per Company in {0} {1}")
.format(doc.doctype, doc.name), DuplicatePartyAccountError)
else:
companies.append(account.company)
party_account_currency = frappe.db.get_value("Account", account.account, "account_currency")
existing_gle_currency = get_party_gle_currency(doc.doctype, doc.name, account.company)
if existing_gle_currency and party_account_currency != existing_gle_currency:
frappe.throw(_("Accounting entries have already been made in currency {0} for company {1}. Please select a receivable or payable account with currency {0}.").format(existing_gle_currency, account.company))
@frappe.whitelist()
def get_due_date(posting_date, party_type, party, company):
"""Set Due Date = Posting Date + Credit Days"""
@@ -267,6 +274,9 @@ def validate_due_date(posting_date, due_date, party_type, party, company):
frappe.throw(_("Due Date cannot be before Posting Date"))
else:
default_due_date = get_due_date(posting_date, party_type, party, company)
if not default_due_date:
return
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:

View File

@@ -38,7 +38,14 @@ class ReceivablePayableReport(object):
"width": 120
})
columns += [_("Age (Days)") + "::80"]
columns += [_("Age (Days)") + ":Int:80"]
if not "range1" in self.filters:
self.filters["range1"] = "30"
if not "range2" in self.filters:
self.filters["range2"] = "60"
if not "range3" in self.filters:
self.filters["range3"] = "90"
for label in ("0-{range1}".format(**self.filters),
"{range1}-{range2}".format(**self.filters),
@@ -75,9 +82,9 @@ class ReceivablePayableReport(object):
voucher_details = self.get_voucher_details(args.get("party_type"))
future_vouchers = self.get_entries_after(self.filters.report_date, args.get("party_type"))
company_currency = frappe.db.get_value("Company", self.filters.get("company"), "default_currency")
data = []
for gle in self.get_entries_till(self.filters.report_date, args.get("party_type")):
if self.is_receivable_or_payable(gle, dr_or_cr, future_vouchers):
@@ -117,7 +124,7 @@ class ReceivablePayableReport(object):
row += [self.get_territory(gle.party)]
if args.get("party_type") == "Supplier":
row += [self.get_supplier_type(gle.party)]
if self.filters.get(scrub(args.get("party_type"))):
row.append(gle.account_currency)
else:
@@ -209,7 +216,8 @@ class ReceivablePayableReport(object):
self.gl_entries = frappe.db.sql("""select name, posting_date, account, party_type, party,
voucher_type, voucher_no, against_voucher_type, against_voucher, account_currency, remarks, {0}
from `tabGL Entry`
where docstatus < 2 and party_type=%s {1} order by posting_date, party"""
where docstatus < 2 and party_type=%s and ifnull(party, '') != '' {1}
order by posting_date, party"""
.format(select_fields, conditions), values, as_dict=True)
return self.gl_entries

View File

@@ -5,6 +5,7 @@ from __future__ import unicode_literals
import frappe
from frappe.utils import flt, getdate, cstr
from frappe import _
from erpnext.accounts.utils import get_account_currency
def execute(filters=None):
account_details = {}
@@ -12,10 +13,10 @@ def execute(filters=None):
account_details.setdefault(acc.name, acc)
validate_filters(filters, account_details)
validate_party(filters)
filters = set_account_currency(filters)
filters = set_account_currency(filters)
columns = get_columns(filters)
@@ -46,49 +47,49 @@ def validate_party(filters):
frappe.throw(_("To filter based on Party, select Party Type first"))
elif not frappe.db.exists(party_type, party):
frappe.throw(_("Invalid {0}: {1}").format(party_type, party))
def set_account_currency(filters):
if not (filters.get("account") or filters.get("party")):
return filters
else:
filters["company_currency"] = frappe.db.get_value("Company", filters.company, "default_currency")
account_currency = None
if filters.get("account"):
account_currency = frappe.db.get_value("Account", filters.account, "account_currency")
account_currency = get_account_currency(filters.account)
elif filters.get("party"):
gle_currency = frappe.db.get_value("GL Entry", {"party_type": filters.party_type,
gle_currency = frappe.db.get_value("GL Entry", {"party_type": filters.party_type,
"party": filters.party, "company": filters.company}, "account_currency")
if gle_currency:
account_currency = gle_currency
else:
account_currency = frappe.db.get_value(filters.party_type, filters.party, "default_currency")
filters["account_currency"] = account_currency or filters.company_currency
if filters.account_currency != filters.company_currency:
filters["show_in_account_currency"] = 1
return filters
def get_columns(filters):
columns = [
_("Posting Date") + ":Date:90", _("Account") + ":Link/Account:200",
_("Debit") + ":Float:100", _("Credit") + ":Float:100"
]
if filters.get("show_in_account_currency"):
columns += [
_("Debit") + " (" + filters.account_currency + ")" + ":Float:100",
_("Debit") + " (" + filters.account_currency + ")" + ":Float:100",
_("Credit") + " (" + filters.account_currency + ")" + ":Float:100"
]
columns += [
_("Voucher Type") + "::120", _("Voucher No") + ":Dynamic Link/Voucher Type:160",
_("Against Account") + "::120", _("Party Type") + "::80", _("Party") + "::150",
_("Cost Center") + ":Link/Cost Center:100", _("Remarks") + "::400"
]
return columns
def get_result(filters, account_details):
@@ -101,21 +102,21 @@ def get_result(filters, account_details):
return result
def get_gl_entries(filters):
select_fields = """, sum(ifnull(debit_in_account_currency, 0)) as debit_in_account_currency,
select_fields = """, sum(ifnull(debit_in_account_currency, 0)) as debit_in_account_currency,
sum(ifnull(credit_in_account_currency, 0)) as credit_in_account_currency""" \
if filters.get("show_in_account_currency") else ""
group_by_condition = "group by voucher_type, voucher_no, account, cost_center" \
if filters.get("group_by_voucher") else "group by name"
gl_entries = frappe.db.sql("""select posting_date, account, party_type, party,
sum(ifnull(debit, 0)) as debit, sum(ifnull(credit, 0)) as credit,
sum(ifnull(debit, 0)) as debit, sum(ifnull(credit, 0)) as credit,
voucher_type, voucher_no, cost_center, remarks, against, is_opening {select_fields}
from `tabGL Entry`
where company=%(company)s {conditions}
{group_by_condition}
order by posting_date, account"""\
.format(select_fields=select_fields, conditions=get_conditions(filters),
.format(select_fields=select_fields, conditions=get_conditions(filters),
group_by_condition=group_by_condition), filters, as_dict=1)
return gl_entries
@@ -135,7 +136,7 @@ def get_conditions(filters):
if filters.get("party"):
conditions.append("party=%(party)s")
if not (filters.get("account") or filters.get("party") or filters.get("group_by_account")):
conditions.append("posting_date >=%(from_date)s")
@@ -156,33 +157,38 @@ def get_data_with_opening_closing(filters, account_details, gl_entries):
if filters.get("account") or filters.get("party"):
data += [get_balance_row(_("Opening"), opening, opening_in_account_currency), {}]
for acc, acc_dict in gle_map.items():
if acc_dict.entries:
# Opening for individual ledger, if grouped by account
if filters.get("group_by_account"):
data.append(get_balance_row(_("Opening"), acc_dict.opening,
if filters.get("group_by_account"):
for acc, acc_dict in gle_map.items():
if acc_dict.entries:
# Opening for individual ledger, if grouped by account
data.append(get_balance_row(_("Opening"), acc_dict.opening,
acc_dict.opening_in_account_currency))
data += acc_dict.entries
data += acc_dict.entries
# Totals and closing for individual ledger, if grouped by account
if filters.get("group_by_account"):
# Totals and closing for individual ledger, if grouped by account
account_closing = acc_dict.opening + acc_dict.total_debit - acc_dict.total_credit
account_closing_in_account_currency = acc_dict.opening_in_account_currency \
+ acc_dict.total_debit_in_account_currency - acc_dict.total_credit_in_account_currency
data += [{"account": "'" + _("Totals") + "'", "debit": acc_dict.total_debit,
"credit": acc_dict.total_credit},
get_balance_row(_("Closing (Opening + Totals)"),
account_closing, account_closing_in_account_currency), {}]
else:
for gl in gl_entries:
if gl.posting_date >= getdate(filters.from_date) and gl.posting_date <= getdate(filters.to_date):
data.append(gl)
# Total debit and credit between from and to date
if total_debit or total_credit:
data.append({
"account": "'" + _("Totals") + "'",
"debit": total_debit,
"account": "'" + _("Totals") + "'",
"debit": total_debit,
"credit": total_credit,
"debit_in_account_currency": total_debit_in_account_currency,
"debit_in_account_currency": total_debit_in_account_currency,
"credit_in_account_currency": total_credit_in_account_currency
})
@@ -191,7 +197,7 @@ def get_data_with_opening_closing(filters, account_details, gl_entries):
closing = opening + total_debit - total_credit
closing_in_account_currency = opening_in_account_currency + \
total_debit_in_account_currency - total_credit_in_account_currency
data.append(get_balance_row(_("Closing (Opening + Totals)"),
closing, closing_in_account_currency))
@@ -216,38 +222,38 @@ def initialize_gle_map(gl_entries):
def get_accountwise_gle(filters, gl_entries, gle_map):
opening, total_debit, total_credit = 0, 0, 0
opening_in_account_currency, total_debit_in_account_currency, total_credit_in_account_currency = 0, 0, 0
from_date, to_date = getdate(filters.from_date), getdate(filters.to_date)
for gle in gl_entries:
amount = flt(gle.debit, 3) - flt(gle.credit, 3)
amount_in_account_currency = flt(gle.debit_in_account_currency, 3) - flt(gle.credit_in_account_currency, 3)
if (filters.get("account") or filters.get("party") or filters.get("group_by_account")) \
and (gle.posting_date < from_date or cstr(gle.is_opening) == "Yes"):
gle_map[gle.account].opening += amount
if filters.get("show_in_account_currency"):
gle_map[gle.account].opening_in_account_currency += amount_in_account_currency
if filters.get("account") or filters.get("party"):
opening += amount
if filters.get("show_in_account_currency"):
opening_in_account_currency += amount_in_account_currency
elif gle.posting_date <= to_date:
gle_map[gle.account].entries.append(gle)
gle_map[gle.account].total_debit += flt(gle.debit, 3)
gle_map[gle.account].total_credit += flt(gle.credit, 3)
total_debit += flt(gle.debit, 3)
total_credit += flt(gle.credit, 3)
if filters.get("show_in_account_currency"):
gle_map[gle.account].total_debit_in_account_currency += flt(gle.debit_in_account_currency, 3)
gle_map[gle.account].total_credit_in_account_currency += flt(gle.credit_in_account_currency, 3)
total_debit_in_account_currency += flt(gle.debit_in_account_currency, 3)
total_credit_in_account_currency += flt(gle.credit_in_account_currency, 3)
total_credit_in_account_currency += flt(gle.credit_in_account_currency, 3)
return opening, total_debit, total_credit, opening_in_account_currency, \
total_debit_in_account_currency, total_credit_in_account_currency, gle_map
@@ -258,27 +264,27 @@ def get_balance_row(label, balance, balance_in_account_currency=None):
"debit": balance if balance > 0 else 0,
"credit": -1*balance if balance < 0 else 0
}
if balance_in_account_currency != None:
balance_row.update({
"debit_in_account_currency": balance_in_account_currency if balance_in_account_currency > 0 else 0,
"credit_in_account_currency": -1*balance_in_account_currency if balance_in_account_currency < 0 else 0
})
return balance_row
def get_result_as_list(data, filters):
result = []
for d in data:
row = [d.get("posting_date"), d.get("account"), d.get("debit"), d.get("credit")]
if filters.get("show_in_account_currency"):
row += [d.get("debit_in_account_currency"), d.get("credit_in_account_currency")]
row += [d.get("voucher_type"), d.get("voucher_no"), d.get("against"),
row += [d.get("voucher_type"), d.get("voucher_no"), d.get("against"),
d.get("party_type"), d.get("party"), d.get("cost_center"), d.get("remarks")
]
result.append(row)
return result

View File

@@ -0,0 +1,59 @@
// Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.query_reports["Trial Balance for Party"] = {
"filters": [
{
"fieldname": "company",
"label": __("Company"),
"fieldtype": "Link",
"options": "Company",
"default": frappe.defaults.get_user_default("company"),
"reqd": 1
},
{
"fieldname": "fiscal_year",
"label": __("Fiscal Year"),
"fieldtype": "Link",
"options": "Fiscal Year",
"default": frappe.defaults.get_user_default("fiscal_year"),
"reqd": 1,
"on_change": function(query_report) {
var fiscal_year = query_report.get_values().fiscal_year;
if (!fiscal_year) {
return;
}
frappe.model.with_doc("Fiscal Year", fiscal_year, function(r) {
var fy = frappe.model.get_doc("Fiscal Year", fiscal_year);
query_report.filters_by_name.from_date.set_input(fy.year_start_date);
query_report.filters_by_name.to_date.set_input(fy.year_end_date);
query_report.trigger_refresh();
});
}
},
{
"fieldname": "from_date",
"label": __("From Date"),
"fieldtype": "Date",
"default": frappe.defaults.get_user_default("year_start_date"),
},
{
"fieldname": "to_date",
"label": __("To Date"),
"fieldtype": "Date",
"default": frappe.defaults.get_user_default("year_end_date"),
},
{
"fieldname":"party_type",
"label": __("Party Type"),
"fieldtype": "Select",
"options": ["Customer", "Supplier"],
"default": "Customer"
},
{
"fieldname": "show_zero_values",
"label": __("Show zero values"),
"fieldtype": "Check"
}
]
}

View File

@@ -0,0 +1,17 @@
{
"add_total_row": 0,
"apply_user_permissions": 1,
"creation": "2015-09-22 10:28:45.762272",
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"is_standard": "Yes",
"modified": "2015-09-22 10:28:45.762272",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Trial Balance for Party",
"owner": "Administrator",
"ref_doctype": "GL Entry",
"report_name": "Trial Balance for Party",
"report_type": "Script Report"
}

View File

@@ -0,0 +1,195 @@
# Copyright (c) 2013, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import flt, cint
from erpnext.accounts.report.trial_balance.trial_balance import validate_filters
def execute(filters=None):
validate_filters(filters)
show_party_name = is_party_name_visible(filters)
columns = get_columns(filters, show_party_name)
data = get_data(filters, show_party_name)
return columns, data
def get_data(filters, show_party_name):
party_name_field = "customer_name" if filters.get("party_type")=="Customer" else "supplier_name"
parties = frappe.get_all(filters.get("party_type"), fields = ["name", party_name_field], order_by="name")
opening_balances = get_opening_balances(filters)
balances_within_period = get_balances_within_period(filters)
data = []
total_debit, total_credit = 0, 0
for party in parties:
row = { "party": party.name }
if show_party_name:
row["party_name"] = party.get(party_name_field)
# opening
opening_debit, opening_credit = opening_balances.get(party.name, [0, 0])
row.update({
"opening_debit": opening_debit,
"opening_credit": opening_credit
})
# within period
debit, credit = balances_within_period.get(party.name, [0, 0])
row.update({
"debit": debit,
"credit": credit
})
# totals
total_debit += debit
total_credit += credit
# closing
closing_debit, closing_credit = toggle_debit_credit(opening_debit + debit, opening_credit + credit)
row.update({
"closing_debit": closing_debit,
"closing_credit": closing_credit
})
has_value = False
if (opening_debit or opening_credit or debit or credit or closing_debit or closing_credit):
has_value =True
if cint(filters.show_zero_values) or has_value:
data.append(row)
# Add total row
if total_debit or total_credit:
data.append({
"party": "'" + _("Totals") + "'",
"debit": total_debit,
"credit": total_credit
})
return data
def get_opening_balances(filters):
gle = frappe.db.sql("""
select party, sum(ifnull(debit, 0)) as opening_debit, sum(ifnull(credit, 0)) as opening_credit
from `tabGL Entry`
where company=%(company)s
and ifnull(party_type, '') = %(party_type)s and ifnull(party, '') != ''
and (posting_date < %(from_date)s or ifnull(is_opening, 'No') = 'Yes')
group by party""", {
"company": filters.company,
"from_date": filters.from_date,
"party_type": filters.party_type
}, as_dict=True)
opening = frappe._dict()
for d in gle:
opening_debit, opening_credit = toggle_debit_credit(d.opening_debit, d.opening_credit)
opening.setdefault(d.party, [opening_debit, opening_credit])
return opening
def get_balances_within_period(filters):
gle = frappe.db.sql("""
select party, sum(ifnull(debit, 0)) as debit, sum(ifnull(credit, 0)) as credit
from `tabGL Entry`
where company=%(company)s
and ifnull(party_type, '') = %(party_type)s and ifnull(party, '') != ''
and posting_date >= %(from_date)s and posting_date <= %(to_date)s
and ifnull(is_opening, 'No') = 'No'
group by party""", {
"company": filters.company,
"from_date": filters.from_date,
"to_date": filters.to_date,
"party_type": filters.party_type
}, as_dict=True)
balances_within_period = frappe._dict()
for d in gle:
balances_within_period.setdefault(d.party, [d.debit, d.credit])
return balances_within_period
def toggle_debit_credit(debit, credit):
if flt(debit) > flt(credit):
debit = flt(debit) - flt(credit)
credit = 0.0
else:
credit = flt(credit) - flt(debit)
debit = 0.0
return debit, credit
def get_columns(filters, show_party_name):
columns = [
{
"fieldname": "party",
"label": _(filters.party_type),
"fieldtype": "Link",
"options": filters.party_type,
"width": 200
},
{
"fieldname": "opening_debit",
"label": _("Opening (Dr)"),
"fieldtype": "Currency",
"width": 120
},
{
"fieldname": "opening_credit",
"label": _("Opening (Cr)"),
"fieldtype": "Currency",
"width": 120
},
{
"fieldname": "debit",
"label": _("Debit"),
"fieldtype": "Currency",
"width": 120
},
{
"fieldname": "credit",
"label": _("Credit"),
"fieldtype": "Currency",
"width": 120
},
{
"fieldname": "closing_debit",
"label": _("Closing (Dr)"),
"fieldtype": "Currency",
"width": 120
},
{
"fieldname": "closing_credit",
"label": _("Closing (Cr)"),
"fieldtype": "Currency",
"width": 120
}
]
if show_party_name:
columns.insert(1, {
"fieldname": "party_name",
"label": _(filters.party_type) + " Name",
"fieldtype": "Data",
"width": 200
})
return columns
def is_party_name_visible(filters):
show_party_name = False
if filters.get("party_type") == "Customer":
party_naming_by = frappe.db.get_single_value("Selling Settings", "cust_master_name")
else:
party_naming_by = frappe.db.get_single_value("Buying Settings", "supp_master_name")
if party_naming_by == "Naming Series":
show_party_name = True
return show_party_name

View File

@@ -9,6 +9,9 @@ from frappe import throw, _
from frappe.utils import formatdate
import frappe.desk.reportview
# imported to enable erpnext.accounts.utils.get_account_currency
from erpnext.accounts.doctype.account.account import get_account_currency
class FiscalYearError(frappe.ValidationError): pass
class BudgetError(frappe.ValidationError): pass
@@ -81,7 +84,9 @@ def get_balance_on(account=None, date=None, party_type=None, party=None, in_acco
if account:
acc = frappe.get_doc("Account", account)
acc.check_permission("read")
if not frappe.flags.ignore_account_permission:
acc.check_permission("read")
# for pl accounts, get balance within a fiscal year
if acc.report_type == 'Profit and Loss':
@@ -94,8 +99,8 @@ def get_balance_on(account=None, date=None, party_type=None, party=None, in_acco
select name from `tabAccount` ac where ac.name = gle.account
and ac.lft >= %s and ac.rgt <= %s
)""" % (acc.lft, acc.rgt))
# If group and currency same as company,
# If group and currency same as company,
# always return balance based on debit and credit in company currency
if acc.account_currency == frappe.db.get_value("Company", acc.company, "default_currency"):
in_account_currency = False
@@ -195,6 +200,8 @@ def update_against_doc(d, jv_obj):
"""
jv_detail = jv_obj.get("accounts", {"name": d["voucher_detail_no"]})[0]
jv_detail.set(d["dr_or_cr"], d["allocated_amt"])
jv_detail.set('debit' if d['dr_or_cr']=='debit_in_account_currency' else 'credit',
d["allocated_amt"]*flt(jv_detail.exchange_rate))
original_reference_type = jv_detail.reference_type
original_reference_name = jv_detail.reference_name
@@ -204,21 +211,32 @@ def update_against_doc(d, jv_obj):
if d['allocated_amt'] < d['unadjusted_amt']:
jvd = frappe.db.sql("""
select cost_center, balance, against_account, is_advance, account_type, exchange_rate
select cost_center, balance, against_account, is_advance,
account_type, exchange_rate, account_currency
from `tabJournal Entry Account` where name = %s
""", d['voucher_detail_no'], as_dict=True)
amount_in_account_currency = flt(d['unadjusted_amt']) - flt(d['allocated_amt'])
amount_in_company_currency = amount_in_account_currency * flt(jvd[0]['exchange_rate'])
# new entry with balance amount
ch = jv_obj.append("accounts")
ch.account = d['account']
ch.account_type = jvd[0]['account_type']
ch.account_currency = jvd[0]['account_currency']
ch.exchange_rate = jvd[0]['exchange_rate']
ch.party_type = d["party_type"]
ch.party = d["party"]
ch.cost_center = cstr(jvd[0]["cost_center"])
ch.balance = flt(jvd[0]["balance"])
ch.set(d['dr_or_cr'], flt(d['unadjusted_amt']) - flt(d['allocated_amt']))
ch.set(d['dr_or_cr']== 'debit' and 'credit' or 'debit', 0)
ch.set(d['dr_or_cr'], amount_in_account_currency)
ch.set('debit' if d['dr_or_cr']=='debit_in_account_currency' else 'credit', amount_in_company_currency)
ch.set('credit_in_account_currency' if d['dr_or_cr']== 'debit_in_account_currency'
else 'debit_in_account_currency', 0)
ch.set('credit' if d['dr_or_cr']== 'debit_in_account_currency' else 'debit', 0)
ch.against_account = cstr(jvd[0]["against_account"])
ch.reference_type = original_reference_type
ch.reference_name = original_reference_name
@@ -296,7 +314,7 @@ def get_stock_and_account_difference(account_list=None, posting_date=None):
def validate_expense_against_budget(args):
args = frappe._dict(args)
if frappe.db.get_value("Account", {"name": args.account, "report_type": "Profit and Loss"}):
if frappe.db.get_value("Account", {"name": args.account, "root_type": "Expense"}):
budget = frappe.db.sql("""
select bd.budget_allocated, cc.distribution_id
from `tabCost Center` cc, `tabBudget Detail` bd

View File

@@ -528,7 +528,7 @@
"unique": 0
},
{
"allow_on_submit": 1,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "items",
@@ -1468,6 +1468,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"default": "Draft",
"fieldname": "status",
"fieldtype": "Select",
"hidden": 0,
@@ -1478,7 +1479,7 @@
"no_copy": 1,
"oldfieldname": "status",
"oldfieldtype": "Select",
"options": "\nDraft\nSubmitted\nStopped\nCancelled",
"options": "\nDraft\nTo Receive and Bill\nTo Bill\nTo Receive\nCompleted\nStopped\nCancelled",
"permlevel": 0,
"print_hide": 1,
"read_only": 1,
@@ -1704,7 +1705,7 @@
"unique": 0
},
{
"allow_on_submit": 1,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "supplied_items",
@@ -1760,7 +1761,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Column Break",
"label": "",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
@@ -1919,7 +1920,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Column Break",
"label": "",
"no_copy": 0,
"permlevel": 0,
"print_hide": 1,
@@ -2032,7 +2033,7 @@
"is_submittable": 1,
"issingle": 0,
"istable": 0,
"modified": "2015-09-11 12:19:55.502661",
"modified": "2015-10-16 06:13:50.058318",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",

View File

@@ -36,13 +36,7 @@ class PurchaseOrder(BuyingController):
def validate(self):
super(PurchaseOrder, self).validate()
if not self.status:
self.status = "Draft"
from erpnext.controllers.status_updater import validate_status
validate_status(self.status, ["Draft", "Submitted", "Stopped",
"Cancelled"])
self.set_status()
pc_obj = frappe.get_doc('Purchase Common')
pc_obj.validate_for_items(self)
self.check_for_stopped_status(pc_obj)
@@ -160,12 +154,10 @@ class PurchaseOrder(BuyingController):
def update_status(self, status):
self.check_modified_date()
frappe.db.set(self,'status',cstr(status))
self.db_set('status', status)
self.set_status(update=True)
self.update_requested_qty()
self.update_ordered_qty()
msgprint(_("Status of {0} {1} is now {2}").format(self.doctype, self.name, status))
self.notify_update()
clear_doctype_notifications(self)
@@ -183,8 +175,6 @@ class PurchaseOrder(BuyingController):
purchase_controller.update_last_purchase_rate(self, is_submit = 1)
frappe.db.set(self,'status','Submitted')
def on_cancel(self):
pc_obj = frappe.get_doc('Purchase Common')
self.check_for_stopped_status(pc_obj)
@@ -238,7 +228,7 @@ def stop_or_unstop_purchase_orders(names, status):
po.update_status("Stopped")
else:
if po.status == "Stopped":
po.update_status("Submitted")
po.update_status("Draft")
frappe.local.message_log = []

View File

@@ -1200,7 +1200,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-08-27 02:29:53.767477",
"modified": "2015-10-19 03:04:51.773011",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order Item",

View File

@@ -226,7 +226,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-03-03 03:40:45.982762",
"modified": "2015-10-02 07:39:05.021801",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order Item Supplied",

View File

@@ -360,7 +360,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-08-19 12:45:54.810580",
"modified": "2015-10-02 07:39:06.224300",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Receipt Item Supplied",

View File

@@ -18,7 +18,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Series",
"label": "Series",
"no_copy": 1,
"options": "QI-",
"permlevel": 0,
@@ -85,7 +85,7 @@
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 1,
"label": "Inspection Type",
"label": "Inspection Type",
"no_copy": 0,
"oldfieldname": "inspection_type",
"oldfieldtype": "Select",
@@ -547,7 +547,7 @@
"is_submittable": 1,
"issingle": 0,
"istable": 0,
"modified": "2015-06-08 02:40:25.121948",
"modified": "2015-10-02 07:39:06.674821",
"modified_by": "Administrator",
"module": "Buying",
"name": "Quality Inspection",

View File

@@ -295,7 +295,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Status",
"label": "Status",
"no_copy": 0,
"oldfieldname": "status",
"oldfieldtype": "Select",
@@ -318,7 +318,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-02-19 01:07:01.658125",
"modified": "2015-10-02 07:39:06.876419",
"modified_by": "Administrator",
"module": "Buying",
"name": "Quality Inspection Reading",

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@ from frappe import msgprint, _
from frappe.model.naming import make_autoname
from erpnext.utilities.address_and_contact import load_address_and_contact
from erpnext.utilities.transaction_base import TransactionBase
from erpnext.accounts.party import validate_accounting_currency, validate_party_account
from erpnext.accounts.party import validate_party_accounts
class Supplier(TransactionBase):
def get_feed(self):
@@ -45,9 +45,8 @@ class Supplier(TransactionBase):
if frappe.defaults.get_global_default('supp_master_name') == 'Naming Series':
if not self.naming_series:
msgprint(_("Series is mandatory"), raise_exception=1)
validate_accounting_currency(self)
validate_party_account(self)
validate_party_accounts(self)
def get_contacts(self,nm):
if nm:
@@ -96,14 +95,14 @@ def get_dashboard_info(supplier):
billing_this_year = frappe.db.sql("""
select sum(ifnull(credit_in_account_currency, 0)) - sum(ifnull(debit_in_account_currency, 0))
from `tabGL Entry`
where voucher_type='Purchase Invoice' and party_type = 'Supplier'
and party=%s and fiscal_year = %s""",
where voucher_type='Purchase Invoice' and party_type = 'Supplier'
and party=%s and fiscal_year = %s""",
(supplier, frappe.db.get_default("fiscal_year")))
total_unpaid = frappe.db.sql("""select sum(outstanding_amount)
from `tabPurchase Invoice`
where supplier=%s and docstatus = 1""", supplier)
out["billing_this_year"] = billing_this_year[0][0] if billing_this_year else 0
out["total_unpaid"] = total_unpaid[0][0] if total_unpaid else 0

View File

@@ -1,22 +1,21 @@
[
{
"doctype": "Supplier",
"supplier_name": "_Test Supplier",
"doctype": "Supplier",
"supplier_name": "_Test Supplier",
"supplier_type": "_Test Supplier Type"
},
{
"doctype": "Supplier",
"supplier_name": "_Test Supplier 1",
"doctype": "Supplier",
"supplier_name": "_Test Supplier 1",
"supplier_type": "_Test Supplier Type"
},
{
"doctype": "Supplier",
"supplier_name": "_Test Supplier USD",
"doctype": "Supplier",
"supplier_name": "_Test Supplier USD",
"supplier_type": "_Test Supplier Type",
"party_account_currency": "USD",
"accounts": [{
"company": "_Test Company",
"account": "_Test Payable USD - _TC"
}]
}
]
]

View File

@@ -64,7 +64,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Series",
"label": "Series",
"no_copy": 1,
"oldfieldname": "naming_series",
"oldfieldtype": "Select",
@@ -509,7 +509,7 @@
"unique": 0
},
{
"allow_on_submit": 1,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "items",
@@ -981,7 +981,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Apply Additional Discount On",
"label": "Apply Additional Discount On",
"no_copy": 0,
"options": "\nGrand Total\nNet Total",
"permlevel": 0,
@@ -1463,7 +1463,7 @@
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "Status",
"label": "Status",
"no_copy": 1,
"oldfieldname": "status",
"oldfieldtype": "Select",
@@ -1488,7 +1488,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Is Subcontracted",
"label": "Is Subcontracted",
"no_copy": 0,
"options": "\nYes\nNo",
"permlevel": 0,
@@ -1554,7 +1554,7 @@
"is_submittable": 1,
"issingle": 0,
"istable": 0,
"modified": "2015-09-11 12:20:10.684388",
"modified": "2015-10-02 07:39:15.027459",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Quotation",

View File

@@ -925,7 +925,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-08-26 11:51:55.140967",
"modified": "2015-10-19 03:04:51.597343",
"modified_by": "Administrator",
"module": "Buying",
"name": "Supplier Quotation Item",

View File

@@ -0,0 +1,4 @@
- Trial Balance for Customer and Supplier
- Chart of Accounts for Guatemala
- Address and Contact permissions based on Customer and Supplier
- Multi-currency Accounting: Allow Accounts in different currencies for a Customer or Supplier, if they belong to a different Company

View File

@@ -0,0 +1,7 @@
- Income type Account can now be added to Cost Center Budget
- Target Warehouse added to Delivery Note. Sponsored by [Startrack GPS (Guatemala)](http://gps.gt/)
- Serial No validations will now be based on Warehouse and not Status
- New Design for Email Digests. Now Email Digest will show Accounting Status and notifications. And, something special at the end!
- Thumbnail generation for Website views of product listing
- Ability to select Variant in shopping cart
- Now you can invite a Contact to become a portal user

View File

@@ -0,0 +1,2 @@
- **Quick Entry dialog for Journal Entry**: Just enter Amount, Accounts, Date and save!
- Period Closing Voucher as per multi-currency accounting

View File

@@ -187,6 +187,12 @@ def get_data():
"doctype": "GL Entry",
"is_query_report": True,
},
{
"type": "report",
"name": "Trial Balance for Party",
"doctype": "GL Entry",
"is_query_report": True,
},
{
"type": "report",
"name": "Gross Profit",

View File

@@ -6,16 +6,15 @@ import frappe
from frappe import _, throw
from frappe.utils import today, flt, cint
from erpnext.setup.utils import get_company_currency, get_exchange_rate
from erpnext.accounts.utils import get_fiscal_year, validate_fiscal_year
from erpnext.accounts.utils import get_fiscal_year, validate_fiscal_year, get_account_currency
from erpnext.utilities.transaction_base import TransactionBase
from erpnext.controllers.recurring_document import convert_to_recurring, validate_recurring_document
from erpnext.controllers.sales_and_purchase_return import validate_return
from erpnext.accounts.party import get_party_account_currency
from erpnext.exceptions import CustomerFrozen, InvalidCurrency
force_item_fields = ("item_group", "barcode", "brand", "stock_uom")
class CustomerFrozen(frappe.ValidationError): pass
class InvalidCurrency(frappe.ValidationError): pass
class AccountsController(TransactionBase):
def __init__(self, arg1, arg2=None):
super(AccountsController, self).__init__(arg1, arg2)
@@ -169,7 +168,7 @@ class AccountsController(TransactionBase):
if item.price_list_rate:
item.rate = flt(item.price_list_rate *
(1.0 - (item.discount_percentage / 100.0)), item.precision("rate"))
(1.0 - (flt(item.discount_percentage) / 100.0)), item.precision("rate"))
def set_taxes(self):
if not self.meta.get_field("taxes"):
@@ -220,9 +219,9 @@ class AccountsController(TransactionBase):
gl_dict.update(args)
if not account_currency:
account_currency = frappe.db.get_value("Account", gl_dict.account, "account_currency")
account_currency = get_account_currency(gl_dict.account)
if self.doctype != "Journal Entry":
if self.doctype not in ["Journal Entry", "Period Closing Voucher"]:
self.validate_account_currency(gl_dict.account, account_currency)
self.set_balance_in_account_currency(gl_dict, account_currency)
@@ -427,13 +426,17 @@ class AccountsController(TransactionBase):
if self.get("currency"):
party_type, party = self.get_party()
if party_type and party:
party_account_currency = frappe.db.get_value(party_type, party, "party_account_currency") \
or self.company_currency
party_account_currency = get_party_account_currency(party_type, party, self.company)
if (party_account_currency
and party_account_currency != self.company_currency
and self.currency != party_account_currency):
if party_account_currency != self.company_currency and self.currency != party_account_currency:
frappe.throw(_("Accounting Entry for {0}: {1} can only be made in currency: {2}")
.format(party_type, party, party_account_currency), InvalidCurrency)
# Note: not validating with gle account because we don't have the account at quotation / sales order level and we shouldn't stop someone from creating a sales invoice if sales order is already created
@frappe.whitelist()
def get_tax_rate(account_head):
return frappe.db.get_value("Account", account_head, "tax_rate")

View File

@@ -51,7 +51,7 @@ def validate_item_variant_attributes(item, args):
frappe.throw(_("Increment for Attribute {0} cannot be 0").format(attribute))
is_in_range = from_range <= flt(value) <= to_range
precision = len(cstr(increment).split(".")[-1].rstrip("0"))
precision = max(len(cstr(v).split(".")[-1].rstrip("0")) for v in (value, increment))
#avoid precision error by rounding the remainder
remainder = flt((flt(value) - from_range) % increment, precision)
@@ -60,7 +60,7 @@ def validate_item_variant_attributes(item, args):
if not (is_in_range and is_incremental):
frappe.throw(_("Value for Attribute {0} must be within the range of {1} to {2} in the increments of {3}")\
.format(attribute, from_range, to_range, increment), InvalidItemAttributeValueError)
elif value not in attribute_values.get(attribute, []):
frappe.throw(_("Value {0} for Attribute {1} does not exist in the list of valid Item Attribute Values").format(
value, attribute))
@@ -125,12 +125,11 @@ def copy_attributes_to_variant(item, variant):
from frappe.model import no_value_fields
for field in item.meta.fields:
if field.fieldtype not in no_value_fields and (not field.no_copy)\
and field.fieldname not in ("item_code", "item_name"):
and field.fieldname not in ("item_code", "item_name", "show_in_website"):
if variant.get(field.fieldname) != item.get(field.fieldname):
variant.set(field.fieldname, item.get(field.fieldname))
variant.variant_of = item.name
variant.has_variants = 0
variant.show_in_website = 0
if variant.attributes:
variant.description += "\n"
for d in variant.attributes:

View File

@@ -293,3 +293,27 @@ def get_account_list(doctype, txt, searchfield, start, page_len, filters):
fields = ["name", "parent_account"],
limit_start=start, limit_page_length=page_len, as_list=True)
@frappe.whitelist()
def get_income_account(doctype, txt, searchfield, start, page_len, filters):
from erpnext.controllers.queries import get_match_cond
# income account can be any Credit account,
# but can also be a Asset account with account_type='Income Account' in special circumstances.
# Hence the first condition is an "OR"
if not filters: filters = {}
condition = ""
if filters.get("company"):
condition += "and tabAccount.company = %(company)s"
return frappe.db.sql("""select tabAccount.name from `tabAccount`
where (tabAccount.report_type = "Profit and Loss"
or tabAccount.account_type in ("Income Account", "Temporary"))
and tabAccount.is_group=0
and tabAccount.`{key}` LIKE %(txt)s
{condition} {match_condition}"""
.format(condition=condition, match_condition=get_match_cond(doctype), key=searchfield), {
'txt': "%%%s%%" % frappe.db.escape(txt),
'company': filters.get("company", "")
})

View File

@@ -173,7 +173,8 @@ class SellingController(StockController):
'uom': p.uom,
'batch_no': cstr(p.batch_no).strip(),
'serial_no': cstr(p.serial_no).strip(),
'name': d.name
'name': d.name,
'target_warehouse': p.target_warehouse
}))
else:
il.append(frappe._dict({
@@ -184,7 +185,8 @@ class SellingController(StockController):
'stock_uom': d.stock_uom,
'batch_no': cstr(d.get("batch_no")).strip(),
'serial_no': cstr(d.get("serial_no")).strip(),
'name': d.name
'name': d.name,
'target_warehouse': d.target_warehouse
}))
return il

View File

@@ -30,7 +30,20 @@ status_map = {
],
"Sales Order": [
["Draft", None],
["Submitted", "eval:self.docstatus==1"],
["To Deliver and Bill", "eval:self.per_delivered < 100 and self.per_billed < 100 and self.docstatus == 1"],
["To Bill", "eval:self.per_delivered == 100 and self.per_billed < 100 and self.docstatus == 1"],
["To Deliver", "eval:self.per_delivered < 100 and self.per_billed == 100 and self.docstatus == 1"],
["Completed", "eval:self.per_delivered == 100 and self.per_billed == 100 and self.docstatus == 1"],
["Completed", "eval:self.order_type == 'Maintenance' and self.per_billed == 100 and self.docstatus == 1"],
["Stopped", "eval:self.status=='Stopped'"],
["Cancelled", "eval:self.docstatus==2"],
],
"Purchase Order": [
["Draft", None],
["To Receive and Bill", "eval:self.per_received < 100 and self.per_billed < 100 and self.docstatus == 1"],
["To Bill", "eval:self.per_received == 100 and self.per_billed < 100 and self.docstatus == 1"],
["To Receive", "eval:self.per_received < 100 and self.per_billed == 100 and self.docstatus == 1"],
["Completed", "eval:self.per_received == 100 and self.per_billed == 100 and self.docstatus == 1"],
["Stopped", "eval:self.status=='Stopped'"],
["Cancelled", "eval:self.docstatus==2"],
],
@@ -207,10 +220,10 @@ class StatusUpdater(Document):
# update percent complete in the parent table
if args.get('target_parent_field'):
frappe.db.sql("""update `tab%(target_parent_dt)s`
set %(target_parent_field)s = (select sum(if(%(target_ref_field)s >
set %(target_parent_field)s = round((select sum(if(%(target_ref_field)s >
ifnull(%(target_field)s, 0), %(target_field)s,
%(target_ref_field)s))/sum(%(target_ref_field)s)*100
from `tab%(target_dt)s` where parent="%(name)s") %(set_modified)s
from `tab%(target_dt)s` where parent="%(name)s"), 2) %(set_modified)s
where name='%(name)s'""" % args)
# update field
@@ -222,7 +235,9 @@ class StatusUpdater(Document):
where name='%(name)s'""" % args)
if args.get("set_modified"):
frappe.get_doc(args["target_parent_dt"], name).notify_update()
target = frappe.get_doc(args["target_parent_dt"], name)
target.set_status(update=True)
target.notify_update()
def update_billing_status_for_zero_amount_refdoc(self, ref_dt):
ref_fieldname = ref_dt.lower().replace(" ", "_")

View File

@@ -7,6 +7,7 @@ from frappe.utils import cint, flt, cstr
from frappe import msgprint, _
import frappe.defaults
from erpnext.accounts.general_ledger import make_gl_entries, delete_gl_entries, process_gl_map
from erpnext.stock.utils import get_incoming_rate
from erpnext.controllers.accounts_controller import AccountsController
@@ -46,7 +47,7 @@ class StockController(AccountsController):
# from warehouse account
self.check_expense_account(detail)
gl_list.append(self.get_gl_dict({
"account": warehouse_account[sle.warehouse]["name"],
"against": detail.expense_account,
@@ -55,7 +56,7 @@ class StockController(AccountsController):
"debit": flt(sle.stock_value_difference, 2),
}, warehouse_account[sle.warehouse]["account_currency"]))
# to target warehouse / expense account
# to target warehouse / expense account
gl_list.append(self.get_gl_dict({
"account": detail.expense_account,
"against": warehouse_account[sle.warehouse]["name"],
@@ -69,7 +70,7 @@ class StockController(AccountsController):
if warehouse_with_no_account:
msgprint(_("No accounting entries for the following warehouses") + ": \n" +
"\n".join(warehouse_with_no_account))
return process_gl_map(gl_list)
def get_voucher_details(self, default_expense_account, default_cost_center, sle_map):
@@ -184,7 +185,7 @@ class StockController(AccountsController):
"voucher_no": self.name,
"voucher_detail_no": d.name,
"actual_qty": (self.docstatus==1 and 1 or -1)*flt(d.get("stock_qty")),
"stock_uom": d.get("stock_uom"),
"stock_uom": frappe.db.get_value("Item", args.get("item_code") or d.get("item_code"), "stock_uom"),
"incoming_rate": 0,
"company": self.company,
"fiscal_year": self.fiscal_year,
@@ -217,13 +218,14 @@ class StockController(AccountsController):
return serialized_items
def get_incoming_rate_for_sales_return(self, item_code, against_document):
def get_incoming_rate_for_sales_return(self, item_code, warehouse, against_document):
incoming_rate = 0.0
if against_document and item_code:
incoming_rate = frappe.db.sql("""select abs(ifnull(stock_value_difference, 0) / actual_qty)
from `tabStock Ledger Entry`
where voucher_type = %s and voucher_no = %s and item_code = %s limit 1""",
(self.doctype, against_document, item_code))
where voucher_type = %s and voucher_no = %s
and item_code = %s and warehouse=%s limit 1""",
(self.doctype, against_document, item_code, warehouse))
incoming_rate = incoming_rate[0][0] if incoming_rate else 0.0
return incoming_rate
@@ -252,18 +254,53 @@ class StockController(AccountsController):
sl_entries = []
for d in self.get_item_list():
if frappe.db.get_value("Item", d.item_code, "is_stock_item") == 1 \
and d.warehouse and flt(d['qty']):
incoming_rate = 0
if frappe.db.get_value("Item", d.item_code, "is_stock_item") == 1 and flt(d.qty):
return_rate = 0
if cint(self.is_return) and self.return_against and self.docstatus==1:
incoming_rate = self.get_incoming_rate_for_sales_return(d.item_code, self.return_against)
return_rate = self.get_incoming_rate_for_sales_return(d.item_code,
d.warehouse, self.return_against)
sl_entries.append(self.get_sl_entries(d, {
"actual_qty": -1*flt(d['qty']),
"stock_uom": frappe.db.get_value("Item", d.item_code, "stock_uom"),
"incoming_rate": incoming_rate
}))
# On cancellation or if return entry submission, make stock ledger entry for
# target warehouse first, to update serial no values properly
if d.warehouse and ((not cint(self.is_return) and self.docstatus==1)
or (cint(self.is_return) and self.docstatus==2)):
sl_entries.append(self.get_sl_entries(d, {
"actual_qty": -1*flt(d.qty),
"incoming_rate": return_rate
}))
if d.target_warehouse:
target_warehouse_sle = self.get_sl_entries(d, {
"actual_qty": flt(d.qty),
"warehouse": d.target_warehouse
})
if self.docstatus == 1:
if not cint(self.is_return):
args = frappe._dict({
"item_code": d.item_code,
"warehouse": d.warehouse,
"posting_date": self.posting_date,
"posting_time": self.posting_time,
"qty": -1*flt(d.qty),
"serial_no": d.serial_no
})
target_warehouse_sle.update({
"incoming_rate": get_incoming_rate(args)
})
else:
target_warehouse_sle.update({
"outgoing_rate": return_rate
})
sl_entries.append(target_warehouse_sle)
if d.warehouse and ((not cint(self.is_return) and self.docstatus==2)
or (cint(self.is_return) and self.docstatus==1)):
sl_entries.append(self.get_sl_entries(d, {
"actual_qty": -1*flt(d.qty),
"incoming_rate": return_rate
}))
self.make_sl_entries(sl_entries)
@@ -337,7 +374,7 @@ def get_voucherwise_gl_entries(future_stock_vouchers, posting_date):
def get_warehouse_account():
warehouse_account = frappe._dict()
for d in frappe.db.sql("""select warehouse, name, account_currency from tabAccount
where account_type = 'Warehouse' and ifnull(warehouse, '') != ''""", as_dict=1):
warehouse_account.setdefault(d.warehouse, d)

View File

@@ -355,7 +355,7 @@ class calculate_taxes_and_totals(object):
item.net_amount = flt(item.net_amount + discount_amount_loss,
item.precision("net_amount"))
item.net_rate = flt(item.net_amount / item.qty, item.precision("net_rate"))
item.net_rate = flt(item.net_amount / item.qty, item.precision("net_rate")) if item.qty else 0
self._set_in_company_currency(item, ["net_rate", "net_amount"])

View File

@@ -35,6 +35,8 @@ def get_transaction_list(doctype, txt=None, filters=None, limit_start=0, limit_p
key, parties = "customer", customers
elif suppliers:
key, parties = "supplier", suppliers
else:
key, parties = "customer", []
filters.append((doctype, key, "in", parties))

View File

@@ -41,7 +41,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Series",
"label": "Series",
"no_copy": 1,
"oldfieldname": "naming_series",
"oldfieldtype": "Select",
@@ -157,7 +157,7 @@
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 1,
"label": "Status",
"label": "Status",
"no_copy": 1,
"oldfieldname": "status",
"oldfieldtype": "Select",
@@ -181,7 +181,7 @@
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "Source",
"label": "Source",
"no_copy": 1,
"oldfieldname": "source",
"oldfieldtype": "Select",
@@ -600,7 +600,7 @@
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "Lead Type",
"label": "Lead Type",
"no_copy": 0,
"oldfieldname": "type",
"oldfieldtype": "Select",
@@ -624,7 +624,7 @@
"ignore_user_permissions": 0,
"in_filter": 1,
"in_list_view": 0,
"label": "Market Segment",
"label": "Market Segment",
"no_copy": 0,
"oldfieldname": "market_segment",
"oldfieldtype": "Select",
@@ -672,7 +672,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Request Type",
"label": "Request Type",
"no_copy": 0,
"oldfieldname": "request_type",
"oldfieldtype": "Select",
@@ -808,7 +808,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-09-14 02:57:27.841011",
"modified": "2015-10-02 07:38:55.014441",
"modified_by": "Administrator",
"module": "CRM",
"name": "Lead",

View File

@@ -58,12 +58,12 @@ class Lead(SellingController):
def check_email_id_is_unique(self):
if self.email_id:
# validate email is unique
email_list = frappe.db.sql("""select name from tabLead where email_id=%s""",
self.email_id)
email_list = [e[0] for e in email_list if e[0]!=self.name]
if len(email_list) > 1:
frappe.throw(_("Email id must be unique, already exists for {0}").format(comma_and(email_list)),
frappe.DuplicateEntryError)
duplicate_leads = frappe.db.sql_list("""select name from tabLead
where email_id=%s and name!=%s""", (self.email_id, self.name))
if duplicate_leads:
frappe.throw(_("Email id must be unique, already exists for {0}")
.format(comma_and(duplicate_leads)), frappe.DuplicateEntryError)
def on_trash(self):
frappe.db.sql("""update `tabIssue` set lead='' where lead=%s""",

View File

@@ -215,7 +215,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-07-20 05:43:33.818567",
"modified": "2015-10-02 07:38:57.733269",
"modified_by": "Administrator",
"module": "CRM",
"name": "Newsletter",

View File

@@ -62,7 +62,8 @@ class Newsletter(Document):
subject = self.subject, message = self.message,
reference_doctype = self.doctype, reference_name = self.name,
unsubscribe_method = "/api/method/erpnext.crm.doctype.newsletter.newsletter.unsubscribe",
unsubscribe_params = {"name": self.newsletter_list})
unsubscribe_params = {"name": self.newsletter_list},
bulk_priority = 1)
if not frappe.flags.in_test:
frappe.db.auto_commit_on_many_writes = False

View File

@@ -62,7 +62,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-09-11 12:20:05.237636",
"modified": "2015-10-02 07:38:57.839265",
"modified_by": "Administrator",
"module": "CRM",
"name": "Newsletter List",

View File

@@ -84,7 +84,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-09-14 02:55:58.113810",
"modified": "2015-10-02 07:38:57.901238",
"modified_by": "Administrator",
"module": "CRM",
"name": "Newsletter List Subscriber",

View File

@@ -42,7 +42,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Series",
"label": "Series",
"no_copy": 1,
"oldfieldname": "naming_series",
"oldfieldtype": "Select",
@@ -66,7 +66,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Opportunity From",
"label": "Opportunity From",
"no_copy": 0,
"oldfieldname": "enquiry_from",
"oldfieldtype": "Select",
@@ -207,7 +207,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Opportunity Type",
"label": "Opportunity Type",
"no_copy": 0,
"oldfieldname": "enquiry_type",
"oldfieldtype": "Select",
@@ -232,7 +232,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Status",
"label": "Status",
"no_copy": 1,
"oldfieldname": "status",
"oldfieldtype": "Select",
@@ -602,7 +602,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Source",
"label": "Source",
"no_copy": 0,
"oldfieldname": "source",
"oldfieldtype": "Select",
@@ -889,7 +889,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-09-11 12:19:38.052900",
"modified": "2015-10-02 07:38:58.453338",
"modified_by": "Administrator",
"module": "CRM",
"name": "Opportunity",

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