Compare commits

...

283 Commits

Author SHA1 Message Date
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
Anand Doshi
0ea68b33ed Merge branch 'develop' 2015-09-24 15:23:05 +05:30
Anand Doshi
7f96c20f5b bumped to version 6.3.1 2015-09-24 15:53:05 +06:00
Anand Doshi
e75d947867 [fix] [patch] convert applicable territory 2015-09-24 15:22:12 +05:30
Anand Doshi
bba0a5d38f [fix] [patch] tax rule 2015-09-24 15:11:24 +05:30
Anand Doshi
953e97536a [fix] [patch] tax rule 2015-09-24 15:05:06 +05:30
Anand Doshi
e74d7ca33e [fix] [patch] tax rule 2015-09-24 15:04:15 +05:30
Rushabh Mehta
8f2b8afcb7 [fix] gl entry report if not filtered 2015-09-24 15:03:53 +05:30
Anand Doshi
b3f12c3109 [fix] [patch] convert_applicable_territory 2015-09-24 15:01:27 +05:30
Anand Doshi
f66e6aacd4 [fix] [patch] convert_applicable_territory 2015-09-24 14:59:26 +05:30
Anand Doshi
1d621be1f7 Merge branch 'develop' 2015-09-24 14:35:36 +05:30
Anand Doshi
ab57e52cbd bumped to version 6.3.0 2015-09-24 15:05:35 +06:00
Anand Doshi
e63da9813c Merge remote-tracking branch 'frappe/master' into develop
Conflicts:
	erpnext/patches.txt
2015-09-24 14:34:50 +05:30
Anand Doshi
c020e42d20 [fix] [patch] convert applicable territory 2015-09-24 13:08:35 +05:30
Anand Doshi
b126ba0132 [change-log] 2015-09-24 13:06:00 +05:30
Anand Doshi
20ae349ebd Merge pull request #4055 from anandpdoshi/project-sales-order-query
Project's Sales Order - get_query fix
2015-09-24 12:49:54 +05:30
Anand Doshi
c6e4b5978d [fix] Sales Order - get_query fix 2015-09-24 11:32:54 +05:30
Anand Doshi
361eca4cae Merge pull request #4054 from anandpdoshi/sales-team-update-after-submit
Sales Team editable after submit
2015-09-24 11:30:31 +05:30
Anand Doshi
9fc03b6c10 Merge pull request #4052 from rmehta/fix-operation-name
[fix] minor, remove operation naming field from operation
2015-09-24 11:30:07 +05:30
Anand Doshi
e2d46d0474 [fix] Allow Sales Team to be added/updated after submit 2015-09-23 19:26:29 +05:30
Rushabh Mehta
dd2f2f5321 [fix] minor, remove operation naming field from operation 2015-09-23 17:06:01 +05:30
Anand Doshi
6e4f5a214a Merge pull request #4033 from rmehta/portal-fixes
Portal Fixes
2015-09-23 16:05:12 +05:30
Anand Doshi
b07b0a9e54 [fix] Sales Order indicators for Maintenance 2015-09-23 15:52:11 +05:30
Rushabh Mehta
307978fea9 [test-fixes] 2015-09-23 15:43:09 +05:30
Anand Doshi
06ad308ca1 [fixes] setup wizard and other fixes related to cart 2015-09-23 12:50:35 +05:30
Anand Doshi
52dfc32eca [fix] validate_valuation_rate for Repack 2015-09-23 12:50:35 +05:30
Rushabh Mehta
72fbf902d7 [cleanup] added single price list for shopping cart, removed Applicable Territory 2015-09-23 12:50:34 +05:30
Rushabh Mehta
8ffd483e24 [wip] shopping cart shipping rule, price list cleanup 2015-09-23 12:49:16 +05:30
Rushabh Mehta
3d76686b82 [shopping-cart] cart via Jinja WIP 2015-09-23 12:49:16 +05:30
Rushabh Mehta
156ce607e2 [cleanup] [wip] portal, shopping cart cleanup 2015-09-23 12:49:16 +05:30
Anand Doshi
65b6762247 Merge pull request #4049 from bobzz-zone/patch-11
Update item_grid.html
2015-09-23 12:09:26 +05:30
Rushabh Mehta
abdfb4d3db [fixed] New button in POS Sales Invoice, reported via forum 2015-09-23 12:05:51 +05:30
bobzz-zone
3bcb13b1b8 Update item_grid.html
Change the colour of the indicator to be green when delivered qty is bigger than ordered qty
2015-09-23 11:42:06 +07:00
Anand Doshi
b6ec680c46 [fix] round percentages in get_indicator 2015-09-22 16:36:20 +05:30
Anand Doshi
53a0de7607 [fix] Recalculate rate after applying Pricing Rule 2015-09-22 15:26:53 +05:30
Anand Doshi
0a1d037f01 Merge pull request #3974 from rmehta/dms
[enhancement] document management system
2015-09-22 14:51:01 +05:30
Anand Doshi
ce3e15d30c Merge pull request #4042 from anandpdoshi/fix-payment-reconciliation-invoice
[fix] Show payment's invoice number as 'Invoice Type | Invoice Number' for better unsability
2015-09-22 14:21:23 +05:30
Nabin Hait
5b649521d1 [fix] Get outstanding invoices in Payment Reconciliation and Payment Tool 2015-09-22 13:06:34 +05:30
Anand Doshi
798e75832c [fix] Show payment's invoice number as 'Invoice Type | Invoice Number' for better unsability 2015-09-22 12:59:43 +05:30
Anand Doshi
aa95a1b1ef Merge pull request #4047 from nabinhait/payment_reco
[fix] Get outstanding invoices in Payment Reconciliation and Payment Tool
2015-09-22 12:55:27 +05:30
Nabin Hait
c0c94aef44 [fix] Get outstanding invoices in Payment Reconciliation and Payment Tool 2015-09-22 08:37:37 +05:30
Anand Doshi
e4dfeb651f [optimization] get balance on 2015-09-21 19:31:43 +05:30
Anand Doshi
f7e6eb4fd7 [optimization] get balance on 2015-09-21 19:30:21 +05:30
Rushabh Mehta
97c858a5e3 [fix] pull sales team from customer 2015-09-21 10:03:38 +05:30
Rushabh Mehta
974892bf87 Merge pull request #4036 from rmehta/no-party-currency
[fix] no default party currency
2015-09-18 13:40:42 +05:30
Rushabh Mehta
361df8993f [fix] no default party currency 2015-09-18 12:59:51 +05:30
Anand Doshi
b8b8de7a49 [hotfix] multicurrency gl entry 2015-09-17 21:07:45 +05:30
Anand Doshi
be6cfddc4d [hotfix] multicurrency gl entry 2015-09-17 21:07:04 +05:30
Anand Doshi
bf8c8df9ce Revert "[hotfix] set_balance_in_account_currency"
This reverts commit 9acd6a2629.
2015-09-17 20:55:50 +05:30
Anand Doshi
40759c284c Revert "[hotfix] set_balance_in_account_currency"
This reverts commit 9acd6a2629.
2015-09-17 20:51:41 +05:30
Nabin Hait
a48d754158 [fix] minor issue 2015-09-17 20:37:07 +05:30
Anand Doshi
26bcd89d10 [hotfix] journal entry - get balance 2015-09-17 20:36:44 +05:30
Anand Doshi
20fd360a63 [hotfix] journal entry - get balance 2015-09-17 20:36:19 +05:30
Anand Doshi
df8efce36f [hotfix] set_balance_in_account_currency 2015-09-17 20:29:57 +05:30
Anand Doshi
9acd6a2629 [hotfix] set_balance_in_account_currency 2015-09-17 20:29:31 +05:30
Anand Doshi
779ae439cd Merge pull request #4034 from nabinhait/mc5
[fix] minor issue
2015-09-17 20:10:19 +05:30
Nabin Hait
a8ef4c9220 [fix] minor issue 2015-09-17 19:38:11 +05:30
Anand Doshi
ce6b61b41e [fix] customer naming series validation and patch to fix missing default taxes and lead 2015-09-17 19:02:59 +05:30
Anand Doshi
0332f83bc2 [fix] customer naming series validation and patch to fix missing default taxes and lead 2015-09-17 19:01:48 +05:30
Nabin Hait
926ae17e5a Update journal_entry.py 2015-09-17 18:42:55 +05:30
Nabin Hait
8adb5f3e32 Update journal_entry.py 2015-09-17 18:40:35 +05:30
Anand Doshi
5532a14938 [hotfix] create customer contact and address from lead only on create 2015-09-17 18:27:56 +05:30
Anand Doshi
a69682c4e0 [hotfix] create customer contact and address from lead only on create 2015-09-17 18:27:36 +05:30
Anand Doshi
d20120e649 [fix] remove duplicate newsletter subscribers 2015-09-17 17:47:26 +05:30
Anand Doshi
e9b14e497b [fix] remove duplicate newsletter subscribers 2015-09-17 17:46:40 +05:30
Anand Doshi
ba0bf9e13d [hotfix] multicurrency patch 2015-09-17 17:36:20 +05:30
Anand Doshi
cba5a684cb [hotfix] multicurrency patch 2015-09-17 17:36:05 +05:30
Anand Doshi
c439b87ccc [hotfix] multicurrency patch 2015-09-17 17:28:58 +05:30
Anand Doshi
340709b2da [hotfix] multicurrency patch 2015-09-17 17:28:39 +05:30
Nabin Hait
a8de61e24b [fix] Multi currency patch 2015-09-17 17:16:58 +05:30
Anand Doshi
28386f551b Merge pull request #4032 from nabinhait/mc4
[fix] Multi currency patch
2015-09-17 17:16:08 +05:30
Nabin Hait
9ff52cd57e [fix] Multi currency patch 2015-09-17 17:07:26 +05:30
Rushabh Mehta
e3401182c8 Merge pull request #4012 from saurabh6790/cart
Taxation for Shopping Cart based on Tax Rule template
2015-09-17 16:26:35 +05:30
Saurabh
0bd145a608 [fixes] test cases and tax rule validation 2015-09-15 17:06:52 +05:30
Saurabh
c663f5c2bd [Test] test state based taxasion 2015-09-15 15:41:01 +05:30
Saurabh
adde1cff48 [Enhancement] add state ccriteria in tax rule 2015-09-15 15:41:01 +05:30
Saurabh
bb9427d1ef [Fixes] deprecated 2015-09-15 15:41:01 +05:30
Saurabh
052babc6b6 [Fixes] [Minor] removed console statement 2015-09-15 15:41:01 +05:30
Saurabh
24fa06bc53 [Fixes] rebase conflict fixes 2015-09-15 15:41:01 +05:30
Saurabh
7c867ae9ad [Fixes] Tax Rule preparation and test taxes creation, remove dummy quotation 2015-09-15 15:41:01 +05:30
Saurabh
8f7317175d [enhancement] bring taxes from tax rules and test cases 2015-09-15 15:41:01 +05:30
Saurabh
957e7a37be [Shopping Cart][Fixes] tax calculation based on tax rule 2015-09-15 15:41:01 +05:30
Saurabh
def71d4d5d [Shopping Cart][Fixes] tax calculation based on tax rule 2015-09-15 15:41:00 +05:30
Neil Trini Lasrado
ef511b160e Added Tax Rule under ERPNext > Accounts > Setup 2015-09-15 15:41:00 +05:30
Neil Trini Lasrado
09f9c96c53 Fixes in Tax Rule 2015-09-15 15:41:00 +05:30
Neil Trini Lasrado
1a2d121073 Removed default taxes and charges from customer and supplier master. Added patch to create tax rules against customer/supplier 2015-09-15 15:41:00 +05:30
Neil Trini Lasrado
810bd35609 Apply Tax Rule based on Customer Selection in Sales / Purchase Transactions 2015-09-15 15:41:00 +05:30
Neil Trini Lasrado
949d7dbaba Added validations, test-cases to Tax Rule 2015-09-15 15:41:00 +05:30
Neil Trini Lasrado
72e6aa160c Added New Doctype Tax Rule 2015-09-15 15:41:00 +05:30
Rushabh Mehta
deb38f7a68 [enhancement] document management system 2015-09-02 18:34:24 +05:30
448 changed files with 75392 additions and 62700 deletions

View File

@@ -1,2 +1,2 @@
from __future__ import unicode_literals
__version__ = '6.2.0'
__version__ = '6.5.0'

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, get_party_account_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,26 @@ 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
party_account_currency = get_party_account_currency(self.party_type, self.party, self.company)
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)
.format(self.party_type, self.party, party_account_currency), InvalidAccountCurrency)
validate_party_gle_currency(self.party_type, self.party, self.company)
def validate_balance_type(account, adv_adj=False):
if not adv_adj and account:
@@ -159,7 +160,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

@@ -335,6 +335,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,
@@ -350,6 +351,9 @@ 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: {

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"):
@@ -386,6 +383,7 @@ class JournalEntry(AccountsController):
# If any row without amount, set the diff on that row
if diff:
blank_row = None
for d in self.get('accounts'):
if not d.credit_in_account_currency and not d.debit_in_account_currency and diff != 0:
blank_row = d
@@ -475,9 +473,18 @@ class JournalEntry(AccountsController):
frappe.throw("Accounts table cannot be blank.")
def set_account_and_party_balance(self):
account_balance = {}
party_balance = {}
for d in self.get("accounts"):
d.account_balance = get_balance_on(account=d.account, date=self.posting_date)
d.party_balance = get_balance_on(party_type=d.party_type, party=d.party, date=self.posting_date)
if d.account not in account_balance:
account_balance[d.account] = get_balance_on(account=d.account, date=self.posting_date)
if (d.party_type, d.party) not in party_balance:
party_balance[(d.party_type, d.party)] = get_balance_on(party_type=d.party_type,
party=d.party, date=self.posting_date)
d.account_balance = account_balance[d.account]
d.party_balance = party_balance[(d.party_type, d.party)]
@frappe.whitelist()
def get_default_bank_cash_account(company, voucher_type, mode_of_payment=None):
@@ -551,7 +558,7 @@ def get_payment_entry_from_purchase_invoice(purchase_invoice):
"""Returns new Journal Entry document as dict for given Purchase Invoice"""
pi = frappe.get_doc("Purchase Invoice", purchase_invoice)
exchange_rate = get_exchange_rate(pi.debit_to, pi.party_account_currency, pi.company,
exchange_rate = get_exchange_rate(pi.credit_to, pi.party_account_currency, pi.company,
pi.doctype, pi.name)
jv = get_payment_entry(pi)
@@ -599,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)
@@ -650,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)
@@ -769,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)
@@ -816,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

@@ -44,7 +44,7 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
}
});
},
refresh: function() {
this.frm.disable_save();
},
@@ -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_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

@@ -130,7 +130,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Column Break",
"label": "",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
@@ -362,7 +362,7 @@
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"modified": "2015-02-05 05:11:42.105088",
"modified": "2015-09-21 03:41:24.672227",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Reconciliation",

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,7 +66,7 @@ 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("""
@@ -79,8 +77,12 @@ class PaymentReconciliation(Document):
`tabGL Entry`
where
party_type = %(party_type)s and party = %(party)s
and voucher_type != "Journal Entry"
and account = %(account)s and {dr_or_cr} > 0 {cond}
and (CASE
WHEN voucher_type = 'Journal Entry'
THEN ifnull(against_voucher, '') = ''
ELSE 1=1
END)
group by voucher_type, voucher_no
""".format(**{
"cond": cond,
@@ -102,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
@@ -136,12 +140,18 @@ class PaymentReconciliation(Document):
ent.outstanding_amount = e.get('outstanding_amount')
def reconcile(self, args):
for e in self.get('payments'):
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_type and e.invoice_number and e.allocated_amount:
if e.invoice_number and e.allocated_amount:
lst.append({
'voucher_no' : e.journal_entry,
'voucher_detail_no' : e.voucher_detail_number,

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

@@ -124,7 +124,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Column Break",
"label": "",
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
@@ -135,51 +135,6 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "allocated_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Allocated amount",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"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,
"default": "Sales Invoice",
"fieldname": "invoice_type",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Invoice Type",
"no_copy": 0,
"options": "\nSales Invoice\nPurchase Invoice\nJournal Entry",
"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,
@@ -202,6 +157,28 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "allocated_amount",
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Allocated amount",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"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,
@@ -243,27 +220,6 @@
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "col_break2",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Column Break",
"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
}
],
"hide_heading": 0,
@@ -273,7 +229,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2014-12-25 16:26:48.345281",
"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":
@@ -71,7 +72,7 @@ def get_outstanding_vouchers(args):
# Get all outstanding sales /purchase invoices
outstanding_invoices = get_outstanding_invoices(amount_query, args.get("party_account"),
args.get("party_type"), args.get("party"), with_journal_entry=False)
args.get("party_type"), args.get("party"))
# Get all SO / PO which are not fully billed or aginst which full advance not paid
orders_to_be_billed = get_orders_to_be_billed(args.get("party_type"), args.get("party"),
@@ -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

@@ -250,7 +250,7 @@
"is_submittable": 1,
"issingle": 0,
"istable": 0,
"modified": "2015-02-05 05:11:42.268561",
"modified": "2015-10-02 07:39:00.056337",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Period Closing Voucher",

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,
@@ -363,8 +364,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 +421,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"]
@@ -219,7 +219,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 +237,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 +278,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 +308,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-19 12:46:32.687299",
"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

@@ -36,6 +36,11 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
refresh: function(doc, dt, dn) {
this._super();
if(cur_frm.msgbox && cur_frm.msgbox.$wrapper.is(":visible")) {
// hide new msgbox
cur_frm.msgbox.hide();
}
cur_frm.dashboard.reset();
this.frm.toggle_reqd("due_date", !this.frm.doc.is_return);
@@ -146,7 +151,9 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
method: "set_missing_values",
callback: function(r) {
if(!r.exc) {
cur_frm.pos_print_format = r.message.print_format;
if(r.message && r.message.print_format) {
cur_frm.pos_print_format = r.message.print_format;
}
cur_frm.doc.__missing_values_set = true;
me.frm.script_manager.trigger("update_stock");
frappe.model.set_default_values(me.frm.doc);
@@ -175,7 +182,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
me.apply_pricing_rule();
})
},
debit_to: function() {
var me = this;
if(this.frm.doc.debit_to) {
@@ -193,7 +200,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
}
}
});
}
}
},
allocated_amount: function() {
@@ -369,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}
}
});
@@ -417,9 +424,9 @@ cur_frm.cscript.on_submit = function(doc, cdt, cdn) {
})
if(cur_frm.doc.is_pos) {
frappe.msgprint('<a class="btn btn-primary" \
cur_frm.msgbox = frappe.msgprint('<a class="btn btn-primary" \
onclick="cur_frm.print_preview.printit(true)" style="margin-right: 5px;">Print</a>\
<a class="btn btn-default" href="#Form/Sales Invoice/New">New</a>');
<a class="btn btn-default" href="#Form/Sales Invoice/New Sales Invoice">New</a>');
} else if(cint(frappe.boot.notification_settings.sales_invoice)) {
cur_frm.email_doc(frappe.boot.notification_settings.sales_invoice_message);

File diff suppressed because it is too large Load Diff

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"
@@ -35,6 +36,15 @@ class SalesInvoice(SellingController):
'overflow_type': 'billing'
}]
def set_indicator(self):
"""Set indicator for portal"""
if self.outstanding_amount > 0:
self.indicator_color = "orange"
self.indicator_title = _("Unpaid")
else:
self.indicator_color = "green"
self.indicator_title = _("Paid")
def validate(self):
super(SalesInvoice, self).validate()
self.validate_posting_time()
@@ -90,7 +100,7 @@ class SalesInvoice(SellingController):
# this sequence because outstanding may get -ve
self.make_gl_entries()
if not self.is_return:
self.update_billing_status_for_zero_amount_refdoc("Sales Order")
self.check_credit_limit()
@@ -161,10 +171,10 @@ class SalesInvoice(SellingController):
'extra_cond': """ and exists (select name from `tabSales Invoice` where name=`tabSales Invoice Item`.parent and update_stock=1 and is_return=1)"""
}
])
def check_credit_limit(self):
from erpnext.selling.doctype.customer.customer import check_credit_limit
validate_against_credit_limit = False
for d in self.get("items"):
if not (d.sales_order or d.delivery_note):
@@ -177,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)
@@ -197,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):
@@ -246,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]
@@ -282,7 +292,7 @@ class SalesInvoice(SellingController):
reconcile_against_document(lst)
def validate_debit_to_acc(self):
account = frappe.db.get_value("Account", self.debit_to,
account = frappe.db.get_value("Account", self.debit_to,
["account_type", "report_type", "account_currency"], as_dict=True)
if account.report_type != "Balance Sheet":
@@ -290,7 +300,7 @@ class SalesInvoice(SellingController):
if self.customer and account.account_type != "Receivable":
frappe.throw(_("Debit To account must be a Receivable account"))
self.party_account_currency = account.account_currency
def validate_fixed_asset_account(self):
@@ -412,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', [])
@@ -437,18 +447,18 @@ class SalesInvoice(SellingController):
if cint(self.is_pos) == 1:
if flt(self.paid_amount) == 0:
if self.cash_bank_account:
frappe.db.set(self, 'paid_amount',
flt(flt(self.grand_total) - flt(self.write_off_amount), self.precision("paid_amount")))
frappe.db.set(self, 'paid_amount',
flt(flt(self.grand_total) - flt(self.write_off_amount), self.precision("paid_amount")))
else:
# show message that the amount is not paid
frappe.db.set(self,'paid_amount',0)
frappe.msgprint(_("Note: Payment Entry will not be created since 'Cash or Bank Account' was not specified"))
else:
frappe.db.set(self,'paid_amount',0)
frappe.db.set(self, 'base_paid_amount',
frappe.db.set(self, 'base_paid_amount',
flt(self.paid_amount*self.conversion_rate, self.precision("base_paid_amount")))
def check_prev_docstatus(self):
for d in self.get('items'):
if d.sales_order and frappe.db.get_value("Sales Order", d.sales_order, "docstatus") != 1:
@@ -487,7 +497,7 @@ class SalesInvoice(SellingController):
from erpnext.accounts.general_ledger import merge_similar_entries
gl_entries = []
self.make_customer_gl_entry(gl_entries)
self.make_tax_gl_entries(gl_entries)
@@ -522,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,
@@ -538,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,
@@ -557,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({
@@ -585,8 +595,8 @@ 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({
"account": self.debit_to,
@@ -627,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-19 12:46:33.165519",
"modified": "2015-10-02 07:39:11.977789",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Taxes and Charges",

View File

@@ -5,6 +5,3 @@ cur_frm.cscript.tax_table = "Sales Taxes and Charges";
{% include "public/js/controllers/accounts.js" %}
frappe.ui.form.on("Sales Taxes and Charges Template", "onload", function(frm) {
erpnext.add_applicable_territory();
});

View File

@@ -164,29 +164,6 @@
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"description": "Specify a list of Territories, for which, this Taxes Master is valid",
"fieldname": "territories",
"fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Valid for Territories",
"no_copy": 0,
"options": "Applicable Territory",
"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,
@@ -198,7 +175,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-09-11 12:19:46.488710",
"modified": "2015-10-02 07:39:12.157257",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Taxes and Charges Template",
@@ -206,7 +183,7 @@
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"apply_user_permissions": 1,
"cancel": 0,
"create": 0,
"delete": 0,

View File

@@ -5,7 +5,6 @@ from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
from erpnext.controllers.accounts_controller import validate_taxes_and_charges, validate_inclusive_tax
from frappe.utils.nestedset import get_root_of
class SalesTaxesandChargesTemplate(Document):
def validate(self):
@@ -20,10 +19,6 @@ def valdiate_taxes_and_charges_template(doc):
where ifnull(is_default,0) = 1 and name != %s and company = %s""".format(doc.doctype),
(doc.name, doc.company))
if doc.meta.get_field("territories"):
if not doc.territories:
doc.append("territories", {"territory": get_root_of("Territory") })
for tax in doc.get("taxes"):
validate_taxes_and_charges(tax)
validate_inclusive_tax(tax, doc)

View File

@@ -20,19 +20,7 @@
"rate": 6.36
}
],
"title": "_Test Sales Taxes and Charges Template",
"territories": [
{
"doctype": "Applicable Territory",
"parentfield": "territories",
"territory": "All Territories"
},
{
"doctype": "Applicable Territory",
"parentfield": "territories",
"territory": "_Test Territory Rest Of The World"
}
]
"title": "_Test Sales Taxes and Charges Template"
},
{
"company": "_Test Company",
@@ -115,14 +103,7 @@
"row_id": 7
}
],
"title": "_Test India Tax Master",
"territories": [
{
"doctype": "Applicable Territory",
"parentfield": "territories",
"territory": "_Test Territory India"
}
]
"title": "_Test India Tax Master"
},
{
"company": "_Test Company",
@@ -145,13 +126,76 @@
"rate": 4
}
],
"title": "_Test Sales Taxes and Charges Template - Rest of the World",
"territories": [
"title": "_Test Sales Taxes and Charges Template - Rest of the World"
},
{
"company": "_Test Company",
"doctype": "Sales Taxes and Charges Template",
"taxes": [
{
"doctype": "Applicable Territory",
"parentfield": "territories",
"territory": "_Test Territory Rest Of The World"
"account_head": "_Test Account VAT - _TC",
"charge_type": "On Net Total",
"description": "VAT",
"doctype": "Sales Taxes and Charges",
"parentfield": "taxes",
"rate": 12
},
{
"account_head": "_Test Account Service Tax - _TC",
"charge_type": "On Net Total",
"description": "Service Tax",
"doctype": "Sales Taxes and Charges",
"parentfield": "taxes",
"rate": 4
}
]
],
"title": "_Test Sales Taxes and Charges Template 1"
},
{
"company": "_Test Company",
"doctype": "Sales Taxes and Charges Template",
"taxes": [
{
"account_head": "_Test Account VAT - _TC",
"charge_type": "On Net Total",
"description": "VAT",
"doctype": "Sales Taxes and Charges",
"parentfield": "taxes",
"rate": 12
},
{
"account_head": "_Test Account Service Tax - _TC",
"charge_type": "On Net Total",
"description": "Service Tax",
"doctype": "Sales Taxes and Charges",
"parentfield": "taxes",
"rate": 4
}
],
"title": "_Test Sales Taxes and Charges Template 2"
},
{
"doctype" : "Sales Taxes and Charges Template",
"title": "_Test Tax 1",
"company": "_Test Company",
"taxes":[{
"charge_type": "Actual",
"account_head": "Sales Expenses - _TC",
"cost_center": "Main - _TC",
"description": "Test Shopping cart taxes with Tax Rule",
"tax_amount": 1000
}]
},
{
"doctype" : "Sales Taxes and Charges Template",
"title": "_Test Tax 2",
"company": "_Test Company",
"taxes":[{
"charge_type": "Actual",
"account_head": "Sales Expenses - _TC",
"cost_center": "Main - _TC",
"description": "Test Shopping cart taxes with Tax Rule",
"tax_amount": 200
}]
}
]

View File

@@ -1,8 +1,3 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
$.extend(cur_frm.cscript, {
onload: function() {
erpnext.add_applicable_territory();
}
});

View File

@@ -35,14 +35,16 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "column_break_2",
"fieldtype": "Column Break",
"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,
@@ -62,7 +64,7 @@
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Calculate Based On",
"label": "Calculate Based On",
"no_copy": 0,
"options": "Net Total\nNet Weight",
"permlevel": 0,
@@ -78,6 +80,7 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"depends_on": "eval:!doc.disabled",
"fieldname": "rule_conditions_section",
"fieldtype": "Section Break",
"hidden": 0,
@@ -121,12 +124,14 @@
"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,
@@ -141,21 +146,20 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"description": "Specify a list of Territories, for which, this Shipping Rule is valid",
"fieldname": "territories",
"fieldtype": "Table",
"fieldname": "worldwide_shipping",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Valid For Territories",
"label": "Worldwide Shipping",
"no_copy": 0,
"options": "Applicable Territory",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 1,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
@@ -164,8 +168,33 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "column_break_8",
"fieldtype": "Column Break",
"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,
@@ -206,8 +235,8 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "section_break_10",
"fieldtype": "Section Break",
"fieldname": "column_break_12",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
@@ -244,26 +273,6 @@
"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,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
@@ -296,7 +305,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-09-07 15:51:26",
"modified": "2015-10-02 07:39:12.778062",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Shipping Rule",
@@ -304,7 +313,7 @@
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"apply_user_permissions": 1,
"cancel": 0,
"create": 0,
"delete": 0,
@@ -324,7 +333,7 @@
},
{
"amend": 0,
"apply_user_permissions": 0,
"apply_user_permissions": 1,
"cancel": 0,
"create": 0,
"delete": 0,

View File

@@ -22,6 +22,12 @@ class ShippingRule(Document):
self.sort_shipping_rule_conditions()
self.validate_overlapping_shipping_rule_conditions()
if self.worldwide_shipping:
self.countries = []
elif not len([d.country for d in self.countries if d.country]):
frappe.throw(_("Please specify a country for this Shipping Rule or check Worldwide Shipping"))
def validate_from_to_values(self):
zero_to_values = []

View File

@@ -1,116 +1,100 @@
[
{
"account": "_Test Account Shipping Charges - _TC",
"calculate_based_on": "Net Total",
"company": "_Test Company",
"cost_center": "_Test Cost Center - _TC",
"doctype": "Shipping Rule",
"label": "_Test Shipping Rule",
"name": "_Test Shipping Rule",
"account": "_Test Account Shipping Charges - _TC",
"calculate_based_on": "Net Total",
"company": "_Test Company",
"cost_center": "_Test Cost Center - _TC",
"doctype": "Shipping Rule",
"label": "_Test Shipping Rule",
"name": "_Test Shipping Rule",
"conditions": [
{
"doctype": "Shipping Rule Condition",
"from_value": 0,
"parentfield": "conditions",
"shipping_amount": 50.0,
"doctype": "Shipping Rule Condition",
"from_value": 0,
"parentfield": "conditions",
"shipping_amount": 50.0,
"to_value": 100
},
},
{
"doctype": "Shipping Rule Condition",
"from_value": 101,
"parentfield": "conditions",
"shipping_amount": 100.0,
"doctype": "Shipping Rule Condition",
"from_value": 101,
"parentfield": "conditions",
"shipping_amount": 100.0,
"to_value": 200
},
},
{
"doctype": "Shipping Rule Condition",
"from_value": 201,
"parentfield": "conditions",
"doctype": "Shipping Rule Condition",
"from_value": 201,
"parentfield": "conditions",
"shipping_amount": 0.0
}
],
"territories": [
{
"doctype": "Applicable Territory",
"parentfield": "territories",
"territory": "_Test Territory"
}
]
},
],
"worldwide_shipping": 1
},
{
"account": "_Test Account Shipping Charges - _TC",
"calculate_based_on": "Net Total",
"company": "_Test Company",
"cost_center": "_Test Cost Center - _TC",
"doctype": "Shipping Rule",
"label": "_Test Shipping Rule - India",
"name": "_Test Shipping Rule - India",
"account": "_Test Account Shipping Charges - _TC",
"calculate_based_on": "Net Total",
"company": "_Test Company",
"cost_center": "_Test Cost Center - _TC",
"doctype": "Shipping Rule",
"label": "_Test Shipping Rule - India",
"name": "_Test Shipping Rule - India",
"conditions": [
{
"doctype": "Shipping Rule Condition",
"from_value": 0,
"parentfield": "conditions",
"shipping_amount": 50.0,
"doctype": "Shipping Rule Condition",
"from_value": 0,
"parentfield": "conditions",
"shipping_amount": 50.0,
"to_value": 100
},
},
{
"doctype": "Shipping Rule Condition",
"from_value": 101,
"parentfield": "conditions",
"shipping_amount": 100.0,
"doctype": "Shipping Rule Condition",
"from_value": 101,
"parentfield": "conditions",
"shipping_amount": 100.0,
"to_value": 200
},
},
{
"doctype": "Shipping Rule Condition",
"from_value": 201,
"parentfield": "conditions",
"doctype": "Shipping Rule Condition",
"from_value": 201,
"parentfield": "conditions",
"shipping_amount": 0.0
}
],
"territories": [
{
"doctype": "Applicable Territory",
"parentfield": "territories",
"territory": "_Test Territory India"
}
],
"countries": [
{"country": "India"}
]
},
},
{
"account": "_Test Account Shipping Charges - _TC",
"calculate_based_on": "Net Total",
"company": "_Test Company",
"cost_center": "_Test Cost Center - _TC",
"doctype": "Shipping Rule",
"label": "_Test Shipping Rule - Rest of the World",
"name": "_Test Shipping Rule - Rest of the World",
"account": "_Test Account Shipping Charges - _TC",
"calculate_based_on": "Net Total",
"company": "_Test Company",
"cost_center": "_Test Cost Center - _TC",
"doctype": "Shipping Rule",
"label": "_Test Shipping Rule - Rest of the World",
"name": "_Test Shipping Rule - Rest of the World",
"conditions": [
{
"doctype": "Shipping Rule Condition",
"from_value": 0,
"parentfield": "conditions",
"shipping_amount": 500.0,
"doctype": "Shipping Rule Condition",
"from_value": 0,
"parentfield": "conditions",
"shipping_amount": 500.0,
"to_value": 1000
},
},
{
"doctype": "Shipping Rule Condition",
"from_value": 1001,
"parentfield": "conditions",
"shipping_amount": 1000.0,
"doctype": "Shipping Rule Condition",
"from_value": 1001,
"parentfield": "conditions",
"shipping_amount": 1000.0,
"to_value": 2000
},
},
{
"doctype": "Shipping Rule Condition",
"from_value": 2001,
"parentfield": "conditions",
"doctype": "Shipping Rule Condition",
"from_value": 2001,
"parentfield": "conditions",
"shipping_amount": 1500.0
}
],
"territories": [
{
"doctype": "Applicable Territory",
"parentfield": "territories",
"territory": "_Test Territory Rest Of The World"
}
]
],
"worldwide_shipping": 1
}
]
]

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

@@ -2,26 +2,27 @@
"allow_copy": 0,
"allow_import": 0,
"allow_rename": 0,
"creation": "2013-06-20 12:48:38",
"creation": "2015-09-17 06:43:22.767534",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "Other",
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"description": "",
"fieldname": "territory",
"fieldname": "country",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Territory",
"label": "Country",
"no_copy": 0,
"options": "Territory",
"options": "Country",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
@@ -33,18 +34,20 @@
],
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 1,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1,
"modified": "2015-01-01 14:29:58.724652",
"modified": "2015-10-02 07:39:13.035775",
"modified_by": "Administrator",
"module": "Setup",
"name": "Applicable Territory",
"module": "Accounts",
"name": "Shipping Rule Country",
"name_case": "",
"owner": "Administrator",
"permissions": [],
"read_only": 0,
"read_only_onload": 0
"read_only_onload": 0,
"sort_field": "modified",
"sort_order": "DESC"
}

View File

@@ -1,12 +1,10 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt
# -*- coding: utf-8 -*-
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
class ApplicableTerritory(Document):
pass
class ShippingRuleCountry(Document):
pass

View File

@@ -0,0 +1,60 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
cur_frm.add_fetch("customer", "customer_group", "customer_group" );
cur_frm.add_fetch("supplier", "supplier_type", "supplier_type" );
cur_frm.toggle_reqd("sales_tax_template", cur_frm.doc.tax_type=="Sales");
cur_frm.toggle_reqd("purchase_tax_template", cur_frm.doc.tax_type=="Purchase");
frappe.ui.form.on("Tax Rule", "onload", function(frm) {
if(frm.doc.__islocal){
frm.set_value("use_for_shopping_cart", 1);
}
})
frappe.ui.form.on("Tax Rule", "use_for_shopping_cart", function(frm) {
if(!frm.doc.use_for_shopping_cart && (frappe.get_list("Tax Rule", {"use_for_shopping_cart":1}).length == 0)){
frappe.model.get_value("Shopping Cart Settings", "Shopping Cart Settings", "enabled", function(docfield) {
if(docfield.enabled){
frm.set_value("use_for_shopping_cart", 1);
frappe.throw(__("Shopping Cart is enabled"));
}
});
}
})
frappe.ui.form.on("Tax Rule", "customer", function(frm) {
frappe.call({
method:"erpnext.accounts.doctype.tax_rule.tax_rule.get_party_details",
args: {
"party": frm.doc.customer,
"party_type": "customer"
},
callback: function(r) {
if(!r.exc) {
$.each(r.message, function(k, v) {
frm.set_value(k, v);
});
}
}
});
});
frappe.ui.form.on("Tax Rule", "supplier", function(frm) {
frappe.call({
method:"erpnext.accounts.doctype.tax_rule.tax_rule.get_party_details",
args: {
"party": frm.doc.supplier,
"party_type": "supplier"
},
callback: function(r) {
if(!r.exc) {
$.each(r.message, function(k, v) {
frm.set_value(k, v);
});
}
}
});
});

View File

@@ -1,27 +1,30 @@
{
"allow_copy": 0,
"allow_import": 0,
"allow_import": 1,
"allow_rename": 0,
"creation": "2013-04-30 12:58:38",
"autoname": "TR.####",
"creation": "2015-08-07 02:33:52.670866",
"custom": 0,
"description": "System for managing Backups",
"docstatus": 0,
"doctype": "DocType",
"document_type": "System",
"document_type": "Setup",
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "setup",
"fieldtype": "Section Break",
"default": "Sales",
"fieldname": "tax_type",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Download Backups",
"in_list_view": 1,
"label": "Tax Type",
"no_copy": 0,
"options": "Sales\nPurchase",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
@@ -34,13 +37,13 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "current_backups",
"fieldtype": "HTML",
"fieldname": "use_for_shopping_cart",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Current Backups",
"label": "Use for Shopping Cart",
"no_copy": 0,
"permlevel": 0,
"precision": "",
@@ -56,56 +59,12 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"description": "",
"fieldname": "sync_with_dropbox",
"fieldtype": "Section Break",
"fieldname": "column_break_1",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Sync with Dropbox",
"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": "backup_right_now",
"fieldtype": "Button",
"hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Backup Right Now",
"no_copy": 0,
"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,
"fieldname": "send_backups_to_dropbox",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Send Backups to Dropbox",
"no_copy": 0,
"permlevel": 0,
"precision": "",
@@ -121,18 +80,18 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"depends_on": "send_backups_to_dropbox",
"description": "Note: Backups and files are not deleted from Dropbox, you will have to delete them manually.",
"fieldname": "upload_backups_to_dropbox",
"fieldtype": "Select",
"depends_on": "eval:doc.tax_type==\"Sales\"",
"fieldname": "sales_tax_template",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Upload Backups to Dropbox",
"label": "Sales Tax Template",
"no_copy": 0,
"options": "Never\nWeekly\nDaily",
"options": "Sales Taxes and Charges Template",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
@@ -145,17 +104,18 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"depends_on": "send_backups_to_dropbox",
"description": "Email ids separated by commas.",
"fieldname": "send_notifications_to",
"fieldtype": "Data",
"depends_on": "eval:doc.tax_type==\"Purchase\"",
"fieldname": "purchase_tax_template",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Send Notifications To",
"label": "Purchase Tax Template",
"no_copy": 0,
"options": "Purchase Taxes and Charges Template",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
@@ -168,123 +128,16 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "dropbox_access_key",
"fieldtype": "Data",
"hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Dropbox Access Key",
"no_copy": 0,
"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,
"fieldname": "dropbox_access_secret",
"fieldtype": "Data",
"hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Dropbox Access Secret",
"no_copy": 0,
"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,
"fieldname": "dropbox_access_allowed",
"fieldtype": "Check",
"hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Dropbox Access Allowed",
"no_copy": 0,
"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": "send_backups_to_dropbox",
"fieldname": "allow_dropbox_access",
"fieldtype": "Button",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Allow Dropbox Access",
"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,
"description": "Note: Backups and files are not deleted from Google Drive, you will have to delete them manually.",
"fieldname": "sync_with_gdrive",
"fieldname": "filters",
"fieldtype": "Section Break",
"hidden": 1,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Sync with Google Drive",
"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": "upload_backups_to_gdrive",
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Upload Backups to Google Drive",
"label": "Filters",
"no_copy": 0,
"options": "Never\nDaily\nWeekly",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
@@ -297,15 +150,18 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "allow_gdrive_access",
"fieldtype": "Button",
"depends_on": "eval:doc.tax_type==\"Sales\"",
"fieldname": "customer",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Allow Google Drive Access",
"label": "Customer",
"no_copy": 0,
"options": "Customer",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
@@ -318,15 +174,40 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "verification_code",
"depends_on": "eval:doc.tax_type==\"Purchase\"",
"fieldname": "supplier",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Supplier",
"no_copy": 0,
"options": "Supplier",
"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,
"fieldname": "billing_city",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Enter Verification Code",
"label": "Billing City",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
@@ -339,15 +220,16 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "validate_gdrive",
"fieldtype": "Button",
"fieldname": "billing_state",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Validate",
"label": "Billing State",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
@@ -360,17 +242,19 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "gdrive_access_allowed",
"fieldtype": "Check",
"hidden": 1,
"fieldname": "billing_country",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Google Drive Access Allowed",
"label": "Billing Country",
"no_copy": 0,
"options": "Country",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -381,17 +265,17 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "gdrive_credentials",
"fieldtype": "Text",
"hidden": 1,
"fieldname": "column_break_2",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Credentials",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -402,17 +286,66 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "database_folder_id",
"depends_on": "eval:doc.tax_type==\"Sales\"",
"fieldname": "customer_group",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Customer Group",
"no_copy": 0,
"options": "Customer Group",
"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.tax_type==\"Purchase\"",
"fieldname": "supplier_type",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Supplier Type",
"no_copy": 0,
"options": "Supplier Type",
"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,
"fieldname": "shipping_city",
"fieldtype": "Data",
"hidden": 1,
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Database Folder ID",
"label": "Shipping City",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -423,17 +356,216 @@
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "files_folder_id",
"fieldname": "shipping_state",
"fieldtype": "Data",
"hidden": 1,
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Files Folder ID",
"label": "Shipping State",
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 1,
"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": "shipping_country",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Shipping Country",
"no_copy": 0,
"options": "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,
"fieldname": "section_break_4",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Validity",
"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,
"fieldname": "from_date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "From Date",
"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,
"fieldname": "column_break_7",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "to_date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "To Date",
"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,
"fieldname": "section_break_6",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"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": "1",
"fieldname": "priority",
"fieldtype": "Int",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Priority",
"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,
"fieldname": "column_break_20",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"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,
"precision": "",
"print_hide": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
@@ -443,17 +575,16 @@
],
"hide_heading": 0,
"hide_toolbar": 0,
"icon": "icon-cloud-upload",
"idx": 1,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 1,
"issingle": 0,
"istable": 0,
"modified": "2015-05-26 04:54:10.193573",
"modified": "2015-10-02 07:39:16.298546",
"modified_by": "Administrator",
"module": "Setup",
"name": "Backup Manager",
"module": "Accounts",
"name": "Tax Rule",
"name_case": "",
"owner": "Administrator",
"permissions": [
{
@@ -461,16 +592,16 @@
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 0,
"delete": 1,
"email": 1,
"export": 0,
"export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 0,
"role": "System Manager",
"report": 1,
"role": "Accounts Manager",
"set_user_permissions": 0,
"share": 1,
"submit": 0,
@@ -478,5 +609,7 @@
}
],
"read_only": 0,
"read_only_onload": 0
"read_only_onload": 0,
"sort_field": "modified",
"sort_order": "DESC"
}

View File

@@ -0,0 +1,132 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2015, 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.model.document import Document
from frappe.utils import cstr
class IncorrectCustomerGroup(frappe.ValidationError): pass
class IncorrectSupplierType(frappe.ValidationError): pass
class ConflictingTaxRule(frappe.ValidationError): pass
class TaxRule(Document):
def __setup__(self):
self.flags.ignore_these_exceptions_in_test = [ConflictingTaxRule]
def validate(self):
self.validate_tax_template()
self.validate_date()
self.validate_filters()
def validate_tax_template(self):
if self.tax_type== "Sales":
self.purchase_tax_template = self.supplier = self.supplier_type= None
if self.customer:
self.customer_group = None
else:
self.sales_tax_template= self.customer = self.customer_group= None
if self.supplier:
self.supplier_type = None
if not (self.sales_tax_template or self.purchase_tax_template):
frappe.throw(_("Tax Template is mandatory."))
def validate_date(self):
if self.from_date and self.to_date and self.from_date > self.to_date:
frappe.throw(_("From Date cannot be greater than To Date"))
def validate_filters(self):
filters = {
"tax_type": self.tax_type,
"customer": self.customer,
"customer_group": self.customer_group,
"supplier": self.supplier,
"supplier_type": self.supplier_type,
"billing_city": self.billing_city,
"billing_state": self.billing_state,
"billing_country": self.billing_country,
"shipping_city": self.shipping_city,
"shipping_state": self.shipping_state,
"shipping_country": self.shipping_country,
"company": self.company
}
conds=""
for d in filters:
if conds:
conds += " and "
conds += """ifnull({0}, '') = '{1}'""".format(d, frappe.db.escape(cstr(filters[d])))
if self.from_date and self.to_date:
conds += """ and ((from_date > '{from_date}' and from_date < '{to_date}') or
(to_date > '{from_date}' and to_date < '{to_date}') or
('{from_date}' > from_date and '{from_date}' < to_date) or
('{from_date}' = from_date and '{to_date}' = to_date))""".format(from_date=self.from_date, to_date=self.to_date)
elif self.from_date and not self.to_date:
conds += """ and to_date > '{from_date}'""".format(from_date = self.from_date)
elif self.to_date and not self.from_date:
conds += """ and from_date < '{to_date}'""".format(to_date = self.to_date)
tax_rule = frappe.db.sql("select name, priority \
from `tabTax Rule` where {0} and name != '{1}'".format(conds, self.name), as_dict=1)
if tax_rule:
if tax_rule[0].priority == self.priority:
frappe.throw(_("Tax Rule Conflicts with {0}".format(tax_rule[0].name)), ConflictingTaxRule)
@frappe.whitelist()
def get_party_details(party, party_type, args=None):
out = {}
if args:
billing_filters= {"name": args.get("billing_address")}
shipping_filters= {"name": args.get("shipping_address")}
else:
billing_filters= {party_type: party, "is_primary_address": 1}
shipping_filters= {party_type:party, "is_shipping_address": 1}
billing_address= frappe.get_all("Address", fields=["city", "state", "country"], filters= billing_filters)
shipping_address= frappe.get_all("Address", fields=["city", "state", "country"], filters= shipping_filters)
if billing_address:
out["billing_city"]= billing_address[0].city
out["billing_state"]= billing_address[0].state
out["billing_country"]= billing_address[0].country
if shipping_address:
out["shipping_city"]= shipping_address[0].city
out["shipping_state"]= shipping_address[0].state
out["shipping_country"]= shipping_address[0].country
return out
def get_tax_template(posting_date, args):
"""Get matching tax rule"""
args = frappe._dict(args)
conditions = []
for key, value in args.iteritems():
if key in "use_for_shopping_cart":
conditions.append("use_for_shopping_cart = {0}".format(1 if value else 0))
else:
conditions.append("ifnull({0}, '') in ('', '{1}')".format(key, frappe.db.escape(cstr(value))))
matching = frappe.db.sql("""select * from `tabTax Rule`
where {0}""".format(" and ".join(conditions)), as_dict = True)
if not matching:
return None
for rule in matching:
rule.no_of_keys_matched = 0
for key in args:
if rule.get(key): rule.no_of_keys_matched += 1
rule = sorted(matching, lambda b, a: cmp(a.no_of_keys_matched, b.no_of_keys_matched) or cmp(a.priority, b.priority))[0]
return rule.sales_tax_template or rule.purchase_tax_template

View File

@@ -0,0 +1,28 @@
[
{
"doctype": "Tax Rule",
"tax_type" : "Sales",
"sales_tax_template": "_Test Tax 1",
"use_for_shopping_cart": 1,
"billing_city": "_Test City",
"billing_state": "Test State",
"billing_country": "India",
"shipping_city": "_Test City",
"shipping_country": "India",
"priority": 1,
"company": "_Test Company"
},
{
"doctype": "Tax Rule",
"tax_type" : "Sales",
"sales_tax_template": "_Test Tax 2",
"use_for_shopping_cart": 0,
"billing_city": "_Test City",
"billing_country": "India",
"shipping_city": "_Test City",
"shipping_state": "Test State",
"shipping_country": "India",
"priority": 2,
"company": "_Test Company"
}
]

View File

@@ -0,0 +1,130 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals
import frappe
import unittest
from erpnext.accounts.doctype.tax_rule.tax_rule import IncorrectCustomerGroup, IncorrectSupplierType, ConflictingTaxRule, get_tax_template
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_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):
tax_rule1 = make_tax_rule(customer= "_Test Customer",
sales_tax_template = "_Test Sales Taxes and Charges Template", priority = 1, from_date = "2015-01-01")
tax_rule1.save()
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):
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)
make_tax_rule(customer= "_Test Customer 1",
sales_tax_template = "_Test Sales Taxes and Charges Template 1", save=1)
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"}),
"_Test Sales Taxes and Charges Template 2")
def test_select_tax_rule_based_on_better_match(self):
make_tax_rule(customer= "_Test Customer", billing_city = "Test City", billing_state = "Test State",
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
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"}),
"_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",
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
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"}),
"_Test Sales Taxes and Charges Template")
def test_select_tax_rule_based_on_better_priority(self):
make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
sales_tax_template = "_Test Sales Taxes and Charges Template", priority=1, save=1)
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"}),
"_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",
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"}),
None)
def test_select_tax_rule_based_cross_partially_keys(self):
make_tax_rule(customer= "_Test Customer", billing_city = "Test City",
sales_tax_template = "_Test Sales Taxes and Charges Template", save=1)
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"}),
"_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,
@@ -20,7 +20,7 @@ def get_party_details(party=None, account=None, party_type="Customer", company=N
if not party:
return {}
if not frappe.db.exists(party_type, party):
frappe.throw(_("{0}: {1} does not exists").format(party_type, party))
@@ -29,7 +29,7 @@ def get_party_details(party=None, account=None, party_type="Customer", company=N
def _get_party_details(party=None, account=None, party_type="Customer", company=None,
posting_date=None, price_list=None, currency=None, doctype=None, ignore_permissions=False):
out = frappe._dict(set_account_and_due_date(party, account, party_type, company, posting_date, doctype))
party = out[party_type.lower()]
@@ -43,6 +43,7 @@ def _get_party_details(party=None, account=None, party_type="Customer", company=
set_contact_details(out, party, party_type)
set_other_values(out, party, party_type)
set_price_list(out, party, party_type, price_list)
out["taxes_and_charges"] = set_taxes(party.name, party_type, posting_date, company, out.customer_group, out.supplier_type)
if not out.get("currency"):
out["currency"] = currency
@@ -51,8 +52,7 @@ def _get_party_details(party=None, account=None, party_type="Customer", company=
if party_type=="Customer":
out["sales_team"] = [{
"sales_person": d.sales_person,
"sales_designation": d.sales_designation,
"allocated_percentage": d.allocated_percentage
"allocated_percentage": d.allocated_percentage or None
} for d in party.get("sales_team")]
return out
@@ -99,11 +99,24 @@ def set_other_values(out, party, party_type):
out[f] = party.get(f)
# fields prepended with default in Customer doctype
for f in ['currency', 'taxes_and_charges'] \
for f in ['currency'] \
+ (['sales_partner', 'commission_rate'] if party_type=="Customer" else []):
if party.get("default_" + f):
out[f] = party.get("default_" + f)
def get_default_price_list(party):
"""Return default price list for party (Document object)"""
if party.default_price_list:
return party.default_price_list
if party.doctype == "Customer":
price_list = frappe.db.get_value("Customer Group",
party.customer_group, "default_price_list")
if price_list:
return price_list
return None
def set_price_list(out, party, party_type, given_price_list):
# price list
price_list = filter(None, get_user_permissions().get("Price List", []))
@@ -111,11 +124,7 @@ def set_price_list(out, party, party_type, given_price_list):
price_list = price_list[0] if len(price_list)==1 else None
if not price_list:
price_list = party.default_price_list
if not price_list and party_type=="Customer":
price_list = frappe.db.get_value("Customer Group",
party.customer_group, "default_price_list")
price_list = get_default_price_list(party)
if not price_list:
price_list = given_price_list
@@ -134,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"
@@ -144,69 +153,22 @@ def set_account_and_due_date(party, account, party_type, company, posting_date,
"due_date": get_due_date(posting_date, party_type, party, company)
}
return out
def validate_accounting_currency(party):
company_currency = get_company_currency()
# set party account currency
if not party.party_account_currency:
if party.default_currency:
party.party_account_currency = party.default_currency
elif len(set(company_currency.values())) == 1:
party.party_account_currency = company_currency.values()[0]
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"]):
company_currency.setdefault(d.name, d.default_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",
@@ -224,6 +186,48 @@ 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):
"""Validate party account currency with existing GL Entry's 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"""
@@ -240,7 +244,7 @@ def get_due_date(posting_date, party_type, party, company):
credit_days = get_credit_days(party_type, party, company)
if credit_days:
due_date = add_days(posting_date, credit_days)
return due_date
def get_credit_days(party_type, party, company):
@@ -248,30 +252,60 @@ def get_credit_days(party_type, party, company):
if party_type == "Customer":
credit_days_based_on, credit_days, customer_group = \
frappe.db.get_value(party_type, party, ["credit_days_based_on", "credit_days", "customer_group"])
if not credit_days_based_on:
credit_days_based_on, credit_days = \
frappe.db.get_value("Customer Group", customer_group, ["credit_days_based_on", "credit_days"]) \
or frappe.db.get_value("Company", company, ["credit_days_based_on", "credit_days"])
return credit_days_based_on, credit_days
else:
credit_days, supplier_type = frappe.db.get_value(party_type, party, ["credit_days", "supplier_type"])
if not credit_days:
credit_days = frappe.db.get_value("Supplier Type", supplier_type, "credit_days") \
or frappe.db.get_value("Company", company, "credit_days")
return credit_days
def validate_due_date(posting_date, due_date, party_type, party, company):
if getdate(due_date) < getdate(posting_date):
frappe.throw(_("Due Date cannot be before Posting Date"))
else:
default_due_date = get_due_date(posting_date, party_type, party, company)
if 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:
msgprint(_("Note: Due / Reference Date exceeds allowed customer credit days by {0} day(s)")
.format(date_diff(due_date, default_due_date)))
else:
frappe.throw(_("Due / Reference Date cannot be after {0}").format(formatdate(default_due_date)))
frappe.throw(_("Due / Reference Date cannot be after {0}").format(formatdate(default_due_date)))
@frappe.whitelist()
def set_taxes(party, party_type, posting_date, company, customer_group=None, supplier_type=None,
billing_address=None, shipping_address=None, use_for_shopping_cart=None):
from erpnext.accounts.doctype.tax_rule.tax_rule import get_tax_template, get_party_details
args = {
party_type.lower(): party,
"customer_group": customer_group,
"supplier_type": supplier_type,
"company": company
}
if billing_address or shipping_address:
args.update(get_party_details(party, party_type, {"billing_address": billing_address, \
"shipping_address": shipping_address }))
else:
args.update(get_party_details(party, party_type))
if party_type=="Customer":
args.update({"tax_type": "Sales"})
else:
args.update({"tax_type": "Purchase"})
if use_for_shopping_cart:
args.update({"use_for_shopping_cart": use_for_shopping_cart})
return get_tax_template(posting_date, args)

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
@@ -397,7 +415,7 @@ def get_stock_rbnb_difference(posting_date, company):
# Amount should be credited
return flt(stock_rbnb) + flt(sys_bal)
def get_outstanding_invoices(amount_query, account, party_type, party, with_journal_entry=True):
def get_outstanding_invoices(amount_query, account, party_type, party):
all_outstanding_vouchers = []
outstanding_voucher_list = frappe.db.sql("""
select
@@ -407,6 +425,11 @@ def get_outstanding_invoices(amount_query, account, party_type, party, with_jour
`tabGL Entry`
where
account = %s and party_type=%s and party=%s and {amount_query} > 0
and (CASE
WHEN voucher_type = 'Journal Entry'
THEN ifnull(against_voucher, '') = ''
ELSE 1=1
END)
group by voucher_type, voucher_no
""".format(amount_query = amount_query), (account, party_type, party), as_dict = True)
@@ -425,9 +448,6 @@ def get_outstanding_invoices(amount_query, account, party_type, party, with_jour
payment_amount = -1*payment_amount[0][0] if payment_amount else 0
precision = frappe.get_precision("Sales Invoice", "outstanding_amount")
if not with_journal_entry and d.voucher_type=="Journal Entry":
continue
if d.invoice_amount > payment_amount:
all_outstanding_vouchers.append({

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

@@ -4,17 +4,17 @@ frappe.listview_settings['Purchase Order'] = {
get_indicator: function(doc) {
if(doc.status==="Stopped") {
return [__("Stopped"), "darkgrey", "status,=,Stopped"];
} else if(flt(doc.per_received) < 100 && doc.status!=="Stopped") {
if(flt(doc.per_billed) < 100) {
} else if(flt(doc.per_received, 2) < 100 && doc.status!=="Stopped") {
if(flt(doc.per_billed, 2) < 100) {
return [__("To Receive and Bill"), "orange",
"per_received,<,100|per_billed,<,100|status,!=,Stopped"];
} else {
return [__("To Receive"), "orange",
"per_received,<,100|per_billed,=,100|status,!=,Stopped"];
}
} else if(flt(doc.per_received) == 100 && flt(doc.per_billed) < 100 && doc.status!=="Stopped") {
} else if(flt(doc.per_received, 2) == 100 && flt(doc.per_billed, 2) < 100 && doc.status!=="Stopped") {
return [__("To Bill"), "orange", "per_received,=,100|per_billed,<,100|status,!=,Stopped"];
} else if(flt(doc.per_received) == 100 && flt(doc.per_billed) == 100 && doc.status!=="Stopped") {
} else if(flt(doc.per_received, 2) == 100 && flt(doc.per_billed, 2) == 100 && doc.status!=="Stopped") {
return [__("Completed"), "green", "per_received,=,100|per_billed,=,100|status,!=,Stopped"];
}
},

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,8 @@
- **Tax Rule:** Define rules to automatically select a Tax Template based on Customer, Supplier, Billing Address or Shipping Address
- Changes to **Shopping Cart:**
- The prices will be based on only a single Price List defined in Shopping Cart Settings. Essentially, it means that your Shopping Cart will be available only in a single currency.
- Shipping Rule will be defined per Country, instead of Territory.
- Taxes will be applied based on the new Tax Rule system, instead of Territory.
- **Important Note:** Your Shopping Cart Settings have been disabled. The new changes require you to review your Price List, Tax Rules and Shipping Rule, update the settings, and then enable Shopping Cart again.
- Enhancements in Customer Portal user interface
- Sales Team is now editable after submission of Sales Order, Sales Invoice and Delivery Note

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

@@ -106,6 +106,11 @@ def get_data():
"name": "Accounts Settings",
"description": _("Default settings for accounting transactions.")
},
{
"type": "doctype",
"name": "Tax Rule",
"description": _("Tax Rule for transactions.")
},
{
"type": "doctype",
"name": "Sales Taxes and Charges Template",
@@ -182,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, validate_party_gle_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)
@@ -167,6 +166,9 @@ class AccountsController(TransactionBase):
if ret.get("pricing_rule_for") == "Price":
item.set("pricing_list_rate", ret.get("pricing_list_rate"))
if item.price_list_rate:
item.rate = flt(item.price_list_rate *
(1.0 - (flt(item.discount_percentage) / 100.0)), item.precision("rate"))
def set_taxes(self):
if not self.meta.get_field("taxes"):
@@ -217,16 +219,15 @@ 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)
self.validate_account_currency(gl_dict.account, account_currency)
gl_dict = self.set_balance_in_account_currency(gl_dict, account_currency)
if self.doctype != "Journal Entry":
self.validate_account_currency(gl_dict.account, account_currency)
self.set_balance_in_account_currency(gl_dict, account_currency)
return gl_dict
def validate_account_currency(self, account, account_currency=None):
if self.doctype == "Journal Entry":
return
valid_currency = [self.company_currency]
if self.get("currency") and self.currency != self.company_currency:
valid_currency.append(self.currency)
@@ -236,8 +237,7 @@ class AccountsController(TransactionBase):
.format(account, _(" or ").join(valid_currency)))
def set_balance_in_account_currency(self, gl_dict, account_currency=None):
if (not self.get("conversion_rate") and self.doctype!="Journal Entry"
and account_currency!=self.company_currency):
if (not self.get("conversion_rate") and account_currency!=self.company_currency):
frappe.throw(_("Account: {0} with currency: {1} can not be selected")
.format(gl_dict.account, account_currency))
@@ -253,8 +253,6 @@ class AccountsController(TransactionBase):
gl_dict.credit_in_account_currency = gl_dict.credit if account_currency==self.company_currency \
else flt(gl_dict.credit / (self.get("conversion_rate")), 2)
return gl_dict
def clear_unallocated_advances(self, childtype, parentfield):
self.set(parentfield, self.get(parentfield, {"allocated_amount": ["not in", [0, None, ""]]}))
@@ -428,10 +426,12 @@ 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)

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(" ", "_")

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