Compare commits

...

318 Commits

Author SHA1 Message Date
Pratik Vyas
eda4265dbc Merge branch 'develop' 2015-02-11 13:07:59 +05:30
Pratik Vyas
a9eae0b424 bumped to version 4.21.4 2015-02-11 13:37:59 +06:00
Nabin Hait
c3fc490d53 Merge pull request #2722 from nabinhait/fix1
minor fix in authorization rule
2015-02-11 12:25:16 +05:30
Nabin Hait
108e935744 minor fix in authorization rule 2015-02-11 12:24:45 +05:30
Pratik Vyas
eac82039e3 Merge branch 'develop' 2015-02-09 18:34:23 +05:30
Pratik Vyas
e0a8f2d859 bumped to version 4.21.3 2015-02-09 19:04:23 +06:00
Nabin Hait
fcca772383 Merge pull request #2712 from nabinhait/fix1
UOM validation for BOM Items
2015-02-09 17:02:41 +05:30
Nabin Hait
c5fb88c1cd UOM validation for BOM Items 2015-02-09 16:48:02 +05:30
Pratik Vyas
aacb0a702e Add auto email id in test site_config.json 2015-02-06 16:55:41 +05:30
Pratik Vyas
f3a9d788bf Merge branch 'develop' 2015-02-06 16:32:00 +05:30
Pratik Vyas
6203cf7f04 bumped to version 4.21.2 2015-02-06 17:02:00 +06:00
Nabin Hait
4ec5d5594b Merge pull request #2696 from nabinhait/fix1
net_total and grand_total mismatch issue
2015-02-06 15:43:10 +05:30
Nabin Hait
a3cb828ed3 progress bar in item grid 2015-02-06 13:00:33 +05:30
Nabin Hait
5e13e0c316 net_total and grand_total mismatch issue 2015-02-05 17:18:03 +05:30
Pratik Vyas
bfeb7c4a57 Merge branch 'develop' 2015-02-05 15:44:06 +05:30
Pratik Vyas
43f627a83a bumped to version 4.21.1 2015-02-05 16:14:06 +06:00
Anand Doshi
d0b3a3734e Merge pull request #2693 from anandpdoshi/anand-feb-5
Fixed call to calculate
2015-02-05 15:25:25 +05:30
Nabin Hait
94365fa035 Merge pull request #2694 from nabinhait/fix1
divisional loss adjustment while doing gl entry for purchase receipt
2015-02-05 15:22:28 +05:30
Nabin Hait
e0ce9407cb divisional loss adjustment while doing gl entry for purchase receipt 2015-02-05 15:12:37 +05:30
Anand Doshi
dea3fb0d64 [fix] call calculate code only once after applying pricing rule 2015-02-05 15:06:16 +05:30
Pratik Vyas
1dae1c40b9 Merge branch 'develop' 2015-02-05 14:25:13 +05:30
Pratik Vyas
fd654a06e8 bumped to version 4.21.0 2015-02-05 14:55:13 +06:00
Nabin Hait
5bf1f89da7 Merge pull request #2669 from nathando/patch-2
Look like a minor bug
2015-02-05 13:48:47 +05:30
Nabin Hait
b6c8c7436f Merge pull request #2691 from nabinhait/fix1
item-wise tax distribution if amount entered in actual
2015-02-05 10:31:30 +05:30
Nabin Hait
1dc8ff5220 item-wise tax distribution if amount entered in actual 2015-02-04 18:06:59 +05:30
Nabin Hait
06d81822fd Merge pull request #2673 from nabinhait/fix1
Multiple fixes
2015-02-03 18:32:19 +05:30
Nabin Hait
0c883500bb Expense account query in purchase invoice 2015-02-03 17:59:00 +05:30
Nabin Hait
4ce020f521 Item grid header in print format 2015-02-03 17:59:00 +05:30
Nabin Hait
11cb9de10a Merge pull request #2670 from nabinhait/fix1
default target warehouse for subcontract
2015-02-03 14:34:34 +05:30
Do Le Bao Nguyen
f9b63dd36a Look like a minor bug
- There is no frappe.get_default but only frappe.db.get_default ?
- Error return if selecting Employee in Salary Slip without specifying the Fiscal Year first
2015-02-03 11:10:09 +08:00
Nabin Hait
282695f536 Merge pull request #2664 from neilLasrado/lead-search
lead report - state, country and pincode seprated from address
2015-02-02 17:07:00 +05:30
Neil Trini Lasrado
809abdf295 lead report - state, country and pincode seprated from address 2015-02-02 11:43:56 +05:30
Nabin Hait
79dc136d50 default target warehouse for subcontract 2015-01-29 12:51:17 +05:30
Pratik Vyas
2407d87b0d Merge branch 'develop' 2015-01-28 17:01:56 +05:30
Pratik Vyas
276053b35f bumped to version 4.20.2 2015-01-28 17:31:56 +06:00
Nabin Hait
dc4c2733f4 Merge pull request #2648 from nabinhait/fix1
Print format: show item table header as per meta label
2015-01-28 16:48:38 +05:30
Nabin Hait
f6f2fc4079 Print format: show item table header as per meta label 2015-01-28 16:45:13 +05:30
Nabin Hait
68b5eaa82f Merge pull request #2646 from nabinhait/fix1
Minor fixes
2015-01-28 14:30:55 +05:30
Nabin Hait
238fd68803 Minor fix 2015-01-28 14:30:03 +05:30
Nabin Hait
22a4b82bd2 Minor fixes 2015-01-28 13:11:49 +05:30
Pratik Vyas
f456eb6254 Merge branch 'develop' 2015-01-27 14:43:53 +05:30
Pratik Vyas
408a8e804c bumped to version 4.20.1 2015-01-27 15:13:53 +06:00
Anand Doshi
e0b39b860f Merge pull request #2640 from anandpdoshi/anand-jan-27
Fixes to Error Reports
2015-01-27 14:33:12 +05:30
Anand Doshi
fde7febf0d Merge pull request #2637 from neilLasrado/batch-patch
patch fix for Batch problem
2015-01-27 13:54:52 +05:30
Anand Doshi
eebf194468 Merge pull request #2638 from gitter-badger/gitter-badge-1
Add a Gitter chat badge to README.md
2015-01-27 13:31:05 +05:30
Anand Doshi
6f701b3b6a [minor] Packing Slip get_query 2015-01-27 13:18:01 +05:30
Anand Doshi
8147f74e4e [minor] Mandatory filters in Customer Acquisition and Loyalty 2015-01-27 13:16:18 +05:30
Neil Trini Lasrado
dc65dc3778 rename patch 2015-01-27 12:27:10 +05:30
The Gitter Badger
a7fb9216c9 Added Gitter badge 2015-01-27 06:12:58 +00:00
Neil Trini Lasrado
81b98261ae patch fix 2015-01-27 11:28:56 +05:30
Pratik Vyas
c20072e940 Merge branch 'develop' 2015-01-23 16:16:53 +05:30
Pratik Vyas
e4c2ebfc57 bumped to version 4.20.0 2015-01-23 16:46:53 +06:00
Nabin Hait
587c061550 Merge pull request #2622 from neilLasrado/batch-patch
patch for is_batch_item
2015-01-23 15:45:53 +05:30
Neil Trini Lasrado
40a9f6f8e9 patch fix 2015-01-23 15:32:35 +05:30
Neil Trini Lasrado
f0b0464cce patch for is_batch_item 2015-01-23 15:32:35 +05:30
Nabin Hait
4e803af0e6 Merge pull request #2625 from nabinhait/fix1
Allow nagative batch balance from landed cost voucher
2015-01-23 14:30:31 +05:30
Nabin Hait
4ccd8d3326 Allow nagative batch balance from landed cost voucher 2015-01-23 12:18:14 +05:30
Nabin Hait
9768467d53 Merge pull request #2619 from nabinhait/fix1
POS fix: setting discount amount
2015-01-21 17:53:09 +05:30
Nabin Hait
59de1e23bc POS fix: setting discount amount 2015-01-21 17:50:28 +05:30
Pratik Vyas
f19b1e0c6b Merge branch 'develop' 2015-01-21 17:05:29 +05:30
Pratik Vyas
d33a3a295f bumped to version 4.19.0 2015-01-21 17:35:29 +06:00
Nabin Hait
f749302d25 Merge pull request #2616 from nabinhait/fix1
Fix1
2015-01-21 16:32:28 +05:30
Nabin Hait
9c47efb592 Landed cost voucher: allow negative stock while doing cancellation entry for purchase receipts 2015-01-21 16:22:45 +05:30
Nabin Hait
ea61046e8d Updated Quotation Status 2015-01-21 14:08:06 +05:30
Nabin Hait
3f671ea60f Landed Cost Voucher: Add field and fixed reposting issue 2015-01-21 14:08:06 +05:30
Pratik Vyas
c1a7c3b08b Update .travis.yml 2015-01-21 12:39:26 +05:30
Pratik Vyas
d1225661d2 Translation updates 2015-01-21 12:05:45 +05:30
Rushabh Mehta
302eee9406 Merge pull request #2463 from Steggur/develop
first is translation commit
2015-01-19 17:08:53 +05:30
Nabin Hait
b434464b1c Merge pull request #2604 from nabinhait/fix1
Fixes
2015-01-19 11:10:39 +05:30
Nabin Hait
aabeb38c15 minor fix 2015-01-19 11:07:32 +05:30
Nabin Hait
fe93ea56b6 Minor fixes: escaped characters 2015-01-19 11:07:32 +05:30
Pratik Vyas
b301603740 Merge branch 'develop' 2015-01-17 01:42:05 +05:30
Pratik Vyas
d7ba759844 bumped to version 4.18.1 2015-01-17 02:12:05 +06:00
Nabin Hait
8efe58bd3c Merge pull request #2591 from nabinhait/fix1
Fixes
2015-01-16 12:03:49 +05:30
Nabin Hait
6609938483 Removed validation: target_valuation > source_valuation 2015-01-16 11:59:47 +05:30
Nabin Hait
84662f2db5 minor fix in payment receipt voucher print format 2015-01-16 11:59:47 +05:30
Nabin Hait
da975f5a76 Merge pull request #2581 from nabinhait/fix1
minor fix
2015-01-14 11:49:46 +05:30
Nabin Hait
f34c96bf7a minor fix 2015-01-14 11:49:04 +05:30
Pratik Vyas
0f96f8e68f Merge branch 'develop' 2015-01-14 11:42:45 +05:30
Pratik Vyas
991962b6fd bumped to version 4.18.0 2015-01-14 12:12:45 +06:00
Nabin Hait
c481e27d88 Merge pull request #2565 from alexandre-00/patch-11
Update bom.py
2015-01-14 11:39:08 +05:30
Nabin Hait
56e04e0727 Merge pull request #2576 from nabinhait/fix1
Discount amount in party currency
2015-01-14 11:27:30 +05:30
Nabin Hait
2244ac4d52 Discount amount in party currency 2015-01-12 17:35:37 +05:30
Nabin Hait
024b537b7f Merge pull request #2557 from neilLasrado/spelling-of-approver
Spelling Correction - Leave application #2552
2015-01-12 17:02:10 +05:30
Pratik Vyas
e4ee5c3f1c Update .travis.yml 2015-01-12 12:48:27 +05:30
Pratik Vyas
4b3d99d39a Merge branch 'develop' 2015-01-12 12:14:36 +05:30
Pratik Vyas
47a10f5a39 bumped to version 4.17.0 2015-01-12 12:44:35 +06:00
Nabin Hait
ecb39a5b63 Merge pull request #2571 from nabinhait/fix1
Fixes
2015-01-12 11:04:50 +05:30
Nabin Hait
39c8c9e7b0 Fixes in print format css 2015-01-12 11:04:07 +05:30
Nabin Hait
4e7cc93af9 minor fix in reposting utility 2015-01-12 10:55:48 +05:30
Rushabh Mehta
f8cb1a916e Merge pull request #2570 from dalers/develop
fix web links and clarify install options
2015-01-12 10:47:06 +05:30
Dale Scott
ab2e75e98e Update README.md 2015-01-11 11:04:43 -07:00
Dale Scott
354892b1c6 Update README.md 2015-01-11 11:01:01 -07:00
Dale Scott
abe69afd69 corrections and clarifications
mostly current websites for user guide, forum, ...
2015-01-11 10:38:03 -07:00
Nabin Hait
c72a89aaf8 Merge pull request #2569 from nabinhait/fix1
create material request from production planning tool
2015-01-11 22:04:07 +05:30
Nabin Hait
873d98be2d create material request from production planning tool 2015-01-11 22:01:59 +05:30
Nabin Hait
f1d06b02e7 Merge pull request #2567 from nabinhait/fix1
valuation rate mandatory if item is transacting for the first time
2015-01-10 10:31:34 +05:30
Nabin Hait
675276b802 valuation rate mandatory if item is transacting for the first time 2015-01-10 10:27:28 +05:30
alexandre-00
3ed3a2d176 Update bom.py
removed the attrgetter
2015-01-09 14:42:27 +08:00
Rushabh Mehta
9e95e780da Merge pull request #2560 from neilLasrado/test-fix
opportunity - test records fixed
2015-01-09 12:03:28 +05:30
alexandre-00
de58657537 Update bom.py
Hi guys,

Just a proposal to sort the Materials Required (Exploded) from the BOM.
So the items and sub-assemblies items looks a little bit more organized in the list.

Cheers
Alexandre
2015-01-09 14:20:43 +08:00
Anand Doshi
015fa7a1d1 [fix] escape quote in Accounts Receivable 2015-01-08 18:26:53 +05:30
Neil Trini Lasrado
1ff3a6cdb8 fix 2015-01-07 16:24:52 +05:30
Nabin Hait
7620efc9ad Merge pull request #2561 from nabinhait/fix1
fix reposting gl entries for future vouchers
2015-01-07 15:49:35 +05:30
Nabin Hait
7778b480fd fix reposting gl entries for future vouchers 2015-01-07 15:45:10 +05:30
Neil Trini Lasrado
a17d7cea34 test records fixed 2015-01-07 15:42:59 +05:30
Pratik Vyas
a9cafcb8ae Merge branch 'develop' 2015-01-07 11:37:22 +05:30
Pratik Vyas
bdfd0d1ff9 bumped to version 4.16.0 2015-01-07 12:07:22 +06:00
Nabin Hait
afc8b1a087 Merge pull request #2558 from nabinhait/fix1
message changed
2015-01-07 11:34:42 +05:30
Nabin Hait
6c1773025b fiscal year error message 2015-01-07 11:33:14 +05:30
Neil Trini Lasrado
1b7d66fab6 Update leave_application.js 2015-01-07 11:16:41 +05:30
Nabin Hait
e24365f1f4 message fix 2015-01-06 12:57:23 +05:30
Nabin Hait
fd334bf451 Merge pull request #2551 from nabinhait/fix1
minor fix
2015-01-05 08:20:08 +05:30
Nabin Hait
5515b1ea7f minor fix 2015-01-05 08:18:15 +05:30
Nabin Hait
96d67f5153 Merge pull request #2547 from nabinhait/fix1
minor fix
2015-01-04 17:29:14 +05:30
Nabin Hait
8a00319962 minor fix 2015-01-04 17:27:40 +05:30
Nabin Hait
c6136e4801 Merge pull request #2543 from nabinhait/fix1
FG item and raw material can not be merged
2015-01-02 15:13:17 +05:30
Nabin Hait
0938b5dec6 FG item and raw material can not be merged 2015-01-02 15:12:30 +05:30
Nabin Hait
88f8fcb32e Merge pull request #2542 from nabinhait/fix1
In stock entry, difference account can be non-profit-and-loss account
2015-01-02 14:37:43 +05:30
Nabin Hait
f40ce616a7 In stock entry, difference account can be non-profit-and-loss account 2015-01-02 14:37:01 +05:30
Pratik Vyas
b02788b915 Merge branch 'develop' 2014-12-31 12:41:14 +05:30
Pratik Vyas
b094ee45d7 bumped to version 4.15.4 2014-12-31 13:11:14 +06:00
Nabin Hait
de0c87757a Merge pull request #2539 from nabinhait/fix1
item validation in bom
2014-12-31 12:37:38 +05:30
Nabin Hait
5604f987f2 item validation in bom 2014-12-31 12:37:11 +05:30
Nabin Hait
9d14f0f36a Merge pull request #2538 from nabinhait/fix1
set missing cost center using default
2014-12-30 18:35:14 +05:30
Nabin Hait
a74468b353 set missing cost center using default 2014-12-30 18:33:52 +05:30
Nabin Hait
35f81b24f1 Merge pull request #2537 from nabinhait/fix1
focus on barcode field after adding a row
2014-12-30 17:53:58 +05:30
Nabin Hait
40431cbf89 focus on barcode field after adding a row 2014-12-30 17:53:16 +05:30
Nabin Hait
5529f14aaf Merge pull request #2536 from nabinhait/fix1
Fixes in Stock Analytics
2014-12-30 16:35:57 +05:30
Nabin Hait
54c31b498b Fixes in Stock Analytics 2014-12-30 16:33:07 +05:30
Nabin Hait
899dba9022 Merge pull request #2535 from nabinhait/fix1
always calculate taxes and totals onchange of exchange rate
2014-12-30 15:41:22 +05:30
Nabin Hait
7d8fa8089a always calculate taxes and totals onchange of exchange rate 2014-12-30 15:35:59 +05:30
Pratik Vyas
ac86c5b6d1 Merge branch 'develop' 2014-12-28 16:59:08 +05:30
Pratik Vyas
ecc3f312b9 bumped to version 4.15.3 2014-12-28 17:29:08 +06:00
Nabin Hait
b65b5f43a7 Merge pull request #2530 from nabinhait/fix1
exchange_rate no_copy fix
2014-12-26 11:00:03 +05:30
Nabin Hait
c3270d7504 exchange_rate no_copy fix 2014-12-26 10:58:58 +05:30
Pratik Vyas
ea909ace01 Merge branch 'develop' 2014-12-23 19:11:08 +05:30
Pratik Vyas
f64d11da3c bumped to version 4.15.2 2014-12-23 19:41:08 +06:00
Nabin Hait
95225be93d Merge pull request #2509 from pdvyas/fix-patches
add reload_doc in a few patches
2014-12-23 17:43:52 +05:30
Nabin Hait
e5d169b8d2 Merge pull request #2521 from nabinhait/fix1
fixed negative batch wty message
2014-12-23 11:26:04 +05:30
Nabin Hait
da4e3fb366 fixed negative batch wty message 2014-12-23 10:58:01 +05:30
Nabin Hait
13ce150149 Merge pull request #2520 from nabinhait/fix1
minor fix no-copy
2014-12-22 15:07:28 +05:30
Nabin Hait
a04489a72b minor fix no-copy 2014-12-22 14:58:36 +05:30
Pratik Vyas
35cd88b09b Merge branch 'develop' 2014-12-22 11:17:45 +05:30
Pratik Vyas
ff56566506 bumped to version 4.15.1 2014-12-22 11:47:45 +06:00
Nabin Hait
01ad94bfad Merge pull request #2519 from nabinhait/fix1
Dont reset pricing if ignore pricing rule
2014-12-22 11:16:02 +05:30
Nabin Hait
cfe3c54ca0 Dont reset pricing if ignore pricing rule 2014-12-22 10:43:10 +05:30
Pratik Vyas
2f6a20a93a Merge branch 'develop' 2014-12-19 18:13:55 +05:30
Pratik Vyas
5d1543f241 bumped to version 4.15.0 2014-12-19 18:43:55 +06:00
Nabin Hait
c56650c773 Merge pull request #2516 from nabinhait/fix1
Customer should not copied from lead to opoortunity
2014-12-19 10:52:52 +05:30
Nabin Hait
cb11f27558 Customer should not copied from lead to opoortunity 2014-12-19 10:51:59 +05:30
Anand Doshi
98be98816c Merge pull request #2515 from anandpdoshi/anand-dec-18
[fix] In Setup Wizard, load languages from languages.txt
2014-12-18 17:40:58 +05:30
Anand Doshi
ca2c297f72 [fix] In Setup Wizard, load languages from languages.txt 2014-12-18 17:31:21 +05:30
Pratik Vyas
387e1e21cb add reload_doc in a few patches 2014-12-18 11:36:23 +05:30
Nabin Hait
d6e49150a8 Merge pull request #2505 from nabinhait/fix1
Reapply price list if pricing rule reset as blank
2014-12-17 15:39:28 +05:30
Nabin Hait
49a2729663 Reapply price list if pricing rule reset as blank 2014-12-17 11:24:00 +05:30
Pratik Vyas
06baf20edd Merge branch 'develop' 2014-12-16 15:47:07 +05:30
Pratik Vyas
13553c2bf0 bumped to version 4.14.0 2014-12-16 16:17:06 +06:00
Nabin Hait
f638c1acd5 Merge pull request #2503 from nabinhait/fix1
packing list index
2014-12-16 15:17:27 +05:30
Nabin Hait
e4c659386a packing list index 2014-12-16 15:16:55 +05:30
Anand Doshi
cd7a1661c6 Merge pull request #2498 from anandpdoshi/anand-dec-15
[minor] use frappe.attach_print() in salary slip and recurring document
2014-12-16 12:42:40 +05:30
Nabin Hait
96962e2101 Merge pull request #2501 from nabinhait/fix1
Fecth contact details on change of contact in purchase transactions
2014-12-16 11:57:11 +05:30
Nabin Hait
7eedebc970 Fecth contact details on change of contact in purchase transactions 2014-12-16 11:56:21 +05:30
Nabin Hait
437e34accb Merge pull request #2500 from nabinhait/fix1
no copy property for customer's po no
2014-12-16 11:26:08 +05:30
Nabin Hait
0f2137be18 no copy property for customer's po no 2014-12-16 10:37:55 +05:30
Anand Doshi
f87a622ef0 [minor] use frappe.attach_print() in salary slip and recurring document 2014-12-15 23:14:35 +05:30
Nabin Hait
07722b835c Merge pull request #2495 from nabinhait/fix1
Translation fixes
2014-12-15 15:00:12 +05:30
Nabin Hait
3cd7a45c1b Translation fixes 2014-12-15 14:56:58 +05:30
Nabin Hait
90b5174256 minor fix 2014-12-15 11:48:43 +05:30
Pratik Vyas
bffad26226 Merge branch 'develop' 2014-12-12 16:52:09 +05:30
Pratik Vyas
a578f3e23a bumped to version 4.13.1 2014-12-12 17:22:09 +06:00
Nabin Hait
870dd43268 Merge pull request #2489 from nabinhait/fix1
Pull all customer's po no in delivery note when made from multiple SO
2014-12-12 12:50:41 +05:30
Nabin Hait
ad0bd4ca92 Pull all customer's po no in delivery note when made from multiple sales order 2014-12-12 12:49:45 +05:30
Nabin Hait
eba480e15a Merge pull request #2487 from nabinhait/fix1
Fixed bom patch
2014-12-12 11:29:49 +05:30
Nabin Hait
4b83403a63 Fixed bom patch 2014-12-12 11:28:58 +05:30
Nabin Hait
22c9e42f4d Merge pull request #2482 from neilLasrado/fix-cost
Fixed cost calculation Error
2014-12-11 17:36:49 +05:30
Neil Trini Lasrado
6ddc487fb6 patch fix 2014-12-11 17:33:41 +05:30
Neil Trini Lasrado
3a34cadcb2 Fix - Total Fixed Cost with patch 2014-12-11 17:15:12 +05:30
Nabin Hait
b71d1a4c7f Merge pull request #2486 from nabinhait/fix1
Removed gross profit field from sales invoice
2014-12-11 17:14:26 +05:30
Nabin Hait
bef80bab0d Removed gross profit field from sales invoice 2014-12-11 16:27:18 +05:30
Nabin Hait
190210394c Merge pull request #2484 from nabinhait/fix1
Leave application fix
2014-12-11 00:02:38 +05:30
Nabin Hait
5cafcf66b0 Leave application fix 2014-12-10 23:59:04 +05:30
Nabin Hait
d71e50c9fc Merge pull request #2480 from nabinhait/fix1
Fixes for discount amount
2014-12-10 12:44:56 +05:30
Nabin Hait
35ebe1bf78 Tax amount in POS invoice print format 2014-12-10 12:42:32 +05:30
Nabin Hait
b14cc0417d Display tax amount after discount, if there is any discount amount 2014-12-10 12:28:25 +05:30
Pratik Vyas
399a3097e8 Merge branch 'develop' 2014-12-09 16:40:28 +05:30
Pratik Vyas
c8f5c3cdbe bumped to version 4.13.0 2014-12-09 17:10:28 +06:00
Nabin Hait
e83d506319 Merge pull request #2474 from nabinhait/fix1
Added leave approver name field in leave application
2014-12-09 16:37:40 +05:30
Nabin Hait
690bcd7b66 Added leave approver name field in leave application 2014-12-09 16:36:33 +05:30
Nabin Hait
f18d285eab Merge pull request #2473 from nabinhait/fix1
minor fix
2014-12-09 16:31:03 +05:30
Nabin Hait
7887ccb441 Credit days fix 2014-12-09 14:34:14 +05:30
Nabin Hait
d57b57a21d Minor fix in accounts receivable report 2014-12-09 11:56:13 +05:30
erp
9fc0a8cbf8 first is translation commit 2014-12-05 11:17:44 +00:00
Nabin Hait
5cc0531d27 Merge pull request #2451 from revant/develop
"From time" cannot be later than "To time" and hours cannot be negative
2014-12-02 14:27:00 +05:30
Revant Nandgaonkar
0e5cdc8495 Merge branch 'develop' of https://github.com/revant/erpnext into develop 2014-12-02 14:21:15 +05:30
Revant Nandgaonkar
b80d892eab removed unecessary backslash 2014-12-02 14:19:29 +05:30
Revant Nandgaonkar
185af03fb2 Update time_log.py 2014-12-02 14:18:10 +05:30
Nabin Hait
abcbbc63d8 Merge pull request #2435 from nabinhait/fix1
Fixes in authorization rule based on average discount
2014-12-02 10:36:25 +05:30
Nabin Hait
6871c74ce1 Merge pull request #2444 from ankitjavalkarwork/contactmob
Display mobile no. of contact
2014-12-02 10:35:46 +05:30
Revant Nandgaonkar
d0a44ca85c Changed contact_date to Datetime so appointment or call with time can be scheduled 2014-12-01 23:31:53 +05:30
Revant Nandgaonkar
83db3e3ddb "From time" cannot be later than "To time" and hours cannot be negative 2014-12-01 16:53:29 +05:30
Nabin Hait
cc11045fd3 minor fix 2014-11-28 16:59:32 +05:30
Nabin Hait
1b5afe737f Fixes in authorization rule based on average discount 2014-11-28 16:59:32 +05:30
Rushabh Mehta
3d65d9602e [error-reports] 2014-11-28 14:58:43 +05:30
ankitjavalkarwork
9440d080d4 Print Hide Recurring Order/Invoice based fields 2014-11-27 17:28:53 +05:30
ankitjavalkarwork
9269c86339 Display mobile no of contact 2014-11-27 17:13:36 +05:30
Pratik Vyas
7c82d616c9 Merge branch 'develop' 2014-11-25 11:16:33 +05:30
Pratik Vyas
f227379d2f bumped to version 4.12.0 2014-11-25 11:46:33 +06:00
Nabin Hait
eba88919c1 Merge pull request #2431 from mayur-patel/patch-2
Update leave_application.py : Modified get_holidays function
2014-11-25 10:55:11 +05:30
Rushabh Mehta
3408432b50 Merge pull request #2428 from rmehta/translations-update
[translations] updated via frappe.io/translator
2014-11-25 10:54:36 +05:30
Rushabh Mehta
a0949158b7 [translations] updated via frappe.io/translator 2014-11-25 10:53:12 +05:30
Nabin Hait
ea91d2aaf1 Merge pull request #2429 from ankitjavalkarwork/expclaimname
Add configurable naming series to Expense claim
2014-11-25 10:51:03 +05:30
Rushabh Mehta
de992abf83 Merge pull request #2413 from Delte/patch-1
Update tr.csv
2014-11-25 10:49:51 +05:30
Mayur Patel
5d8635a8dc Update leave_application.py
See issue #2422 for more detail.
2014-11-24 16:57:53 +00:00
ankitjavalkarwork
7e911bae95 Add configurable naming series to Expense claim 2014-11-24 18:26:17 +05:30
Nabin Hait
0676cf6d3f Merge pull request #2430 from nabinhait/fix1
Multiple minor fixes
2014-11-24 18:21:37 +05:30
Nabin Hait
b74ae7aa31 Minor fix for order to invoice mapping 2014-11-24 18:17:01 +05:30
Nabin Hait
0ad7db3bbd Minor fix in salary slip net total calculation 2014-11-24 15:25:13 +05:30
Nabin Hait
db74e316d2 Validate serial no after auto-creation based on naming series 2014-11-24 15:25:13 +05:30
Nabin Hait
1897360e4b Set default language as English in setup wizard 2014-11-24 15:25:13 +05:30
Nabin Hait
e7fb957415 Merge pull request #2427 from rmehta/develop
[fix] client side queries
2014-11-24 15:23:27 +05:30
Rushabh Mehta
2f4567fa3c [minor] [ux] address refresh for lead 2014-11-24 15:18:40 +05:30
Rushabh Mehta
0a7abc188e [minor] [ux] contact template 2014-11-24 15:06:40 +05:30
Rushabh Mehta
5eeef7f065 [refactor] address and contact list in customer, supplier, lead, sales person 2014-11-24 14:16:51 +05:30
Rushabh Mehta
7d36875d6f [refactor] address and contact list in customer, supplier, lead, sales person 2014-11-24 14:16:47 +05:30
Delte
2fa718705a Update tr.csv
Typo & translation fix
2014-11-15 22:39:25 +02:00
Pratik Vyas
b1fdbf2335 Merge branch 'develop' 2014-11-14 15:27:34 +05:30
Pratik Vyas
2277922313 bumped to version 4.11.2 2014-11-14 15:57:34 +06:00
Nabin Hait
3e1029309c Merge pull request #2411 from nabinhait/fix1
minor fix
2014-11-14 15:19:51 +05:30
Nabin Hait
aa5deaa070 minor fix 2014-11-14 15:19:07 +05:30
Nabin Hait
6b5d51ca22 Merge pull request #2402 from jorxzpagta/patch-1
Update supplier.js [Displaying Messages on the Communation History]
2014-11-14 15:05:11 +05:30
Nabin Hait
2c114b5bb5 Merge pull request #2407 from ankitjavalkarwork/packingsliphead
Add letterhead field and mapper in Packing Slip
2014-11-14 14:50:28 +05:30
Nabin Hait
bd38a79e5e Merge pull request #2410 from nabinhait/fix1
Minor fixes
2014-11-14 14:48:02 +05:30
Nabin Hait
ccd9fd3e94 Rounding in totals calculation 2014-11-14 14:27:24 +05:30
Nabin Hait
4215b3afc3 temporary fix in payment tool 2014-11-14 10:51:31 +05:30
ankitjavalkarwork
f60f111afe Add letterhead field and mapper in Packing Slip 2014-11-13 17:28:42 +05:30
jorxzpagta
6fe0a3cee3 Update supplier.js
Display Messages on the Communication History
2014-11-12 17:02:06 +08:00
Nabin Hait
f004077734 Map only pending qty from Material Request to Purchase Order/Stock Entry 2014-11-11 10:51:41 +05:30
Nabin Hait
6c5cfd2148 Merge pull request #2396 from nabinhait/fix1
Reference / Cheque date is after due date
2014-11-10 18:07:52 +05:30
Nabin Hait
6c1011df92 Reference / Cheque date is after due date 2014-11-10 14:57:53 +05:30
Pratik Vyas
1582a0ce78 Merge branch 'develop' 2014-11-10 12:38:45 +05:30
Pratik Vyas
b5b821363d bumped to version 4.11.1 2014-11-10 13:08:45 +06:00
Nabin Hait
399afc87ef Merge pull request #2379 from nathando/develop
Remove get_server_field from leave_application
2014-11-10 12:05:40 +05:30
Nabin Hait
8c842af172 Merge pull request #2393 from nabinhait/fix1
Credit days and payment tool fixes
2014-11-10 11:44:37 +05:30
Nabin Hait
bf836277f9 Payment tool fix: get outstanding sales orders 2014-11-10 11:28:25 +05:30
Nabin Hait
10d1806d81 Credit days validation fixes 2014-11-10 11:11:58 +05:30
Pratik Vyas
bc41ce95fc Merge branch 'develop' 2014-11-06 14:36:51 +05:30
Pratik Vyas
4948d336c4 bumped to version 4.11.0 2014-11-06 15:06:51 +06:00
Nabin Hait
be2527d93d Merge pull request #2386 from nabinhait/fix1
Translation fixed for Croatia
2014-11-06 12:52:59 +05:30
Nabin Hait
7f5bb1c8aa Translation fixed for Croatia 2014-11-06 12:51:27 +05:30
Pratik Vyas
a8d40e4409 Merge branch 'develop' 2014-11-05 14:15:47 +05:30
Pratik Vyas
e9b4686fec bumped to version 4.10.0 2014-11-05 14:45:47 +06:00
Nabin Hait
5086ef2499 Update update_requested_and_ordered_qty.py 2014-11-05 12:33:29 +05:30
Nathan Do
8a55d9a795 Remove get_server_field from leave_application
- Make get_holidays and get_total_leave_days global to module
- Replace get_server_field with using whitelisted function
get_total_leave_days
2014-11-05 12:32:57 +08:00
Nabin Hait
1caca80203 Merge pull request #2378 from nabinhait/fix1
Requested and ordered qty calculation
2014-11-04 18:06:00 +05:30
Nabin Hait
9114c26857 Patch to recalculate requested qty and ordered qty for all items 2014-11-04 15:34:03 +05:30
Nabin Hait
941a965af4 Ordered qty calculation logic 2014-11-04 15:34:03 +05:30
Nabin Hait
4acd431b92 Requested qty calculation logic 2014-11-04 15:34:03 +05:30
Nabin Hait
fad0d566f9 Payment receipt voucher print format fixed 2014-11-04 15:34:03 +05:30
Pratik Vyas
e2d4079363 Merge branch 'develop' 2014-11-03 16:04:30 +05:30
Pratik Vyas
b9ce1f590b bumped to version 4.9.3 2014-11-03 16:34:29 +06:00
Nabin Hait
36463ed790 Merge pull request #2375 from nabinhait/fix1
Check credit limit only if customer debited
2014-11-03 15:55:03 +05:30
Nabin Hait
3c8838816d Check credit limit only if customer debited 2014-11-03 15:49:29 +05:30
Nabin Hait
11e50a8eee Merge pull request #2366 from ankitjavalkarwork/fixprinthideamt
Hide totals in DN, Auto set Bank/Cash acc. in JV
2014-11-03 15:38:45 +05:30
Nabin Hait
9de4c60bd6 Merge pull request #2374 from nabinhait/fix1
minor fix
2014-11-03 15:37:51 +05:30
Nabin Hait
5288bdeabb Minor fix 2014-11-03 15:08:21 +05:30
ankitjavalkarwork
f5804438bb Auto set default bank/cash account on select of Bank/Cash Voucher in JV 2014-11-03 12:23:55 +05:30
ankitjavalkarwork
6e06357dc5 Hide totals on checking print_without_amount field in DN 2014-11-03 11:57:44 +05:30
Nabin Hait
28913b97b0 [fix] Null issue fixed in stock analytics report 2014-10-31 14:46:25 +05:30
Pratik Vyas
c59cd46391 Merge branch 'develop' 2014-10-30 14:22:17 +05:30
Pratik Vyas
dda239fd49 bumped to version 4.9.2 2014-10-30 14:52:17 +06:00
Nabin Hait
b86a6ce26a Merge pull request #2358 from nabinhait/fix1
[fix] Floating point issue fixed in payment reconciliation
2014-10-29 14:26:41 +05:30
Nabin Hait
ee212e7bb5 [fix] Floating point issue fixed in payment reconciliation 2014-10-29 14:26:05 +05:30
Nabin Hait
4952c7b3b5 Merge pull request #2343 from ankitjavalkarwork/fixcustissue
Fix Customer Issue error on click event of Serial No. field
2014-10-27 11:40:18 +05:30
ankitjavalkarwork
4e61536f50 Fix Customer Issue error on click event of Serial No. field 2014-10-27 11:08:05 +05:30
Pratik Vyas
f2886f152b Merge pull request #2348 from pdvyas/fix-pdf-test
Fix PDF test
2014-10-27 10:47:00 +05:30
Pratik Vyas
b5c56f6cea [minor] add port to test site 2014-10-27 09:51:08 +05:30
Pratik Vyas
80e95388f5 Merge branch 'develop' 2014-10-27 09:26:36 +05:30
Pratik Vyas
daed0b655a bumped to version 4.9.1 2014-10-27 09:56:36 +06:00
Nabin Hait
fbb994c731 Merge pull request #2344 from nabinhait/fix1
cost center based on project
2014-10-23 13:30:51 +05:30
Nabin Hait
10b155a486 cost center based on project 2014-10-23 13:18:59 +05:30
Nabin Hait
ce6eda709b Merge pull request #2342 from ankitjavalkarwork/fixtimelogui
Change position of 'To Time' field for better UX
2014-10-22 16:57:52 +05:30
ankitjavalkarwork
14e1d20df3 Change position of 'To Time' field for better UX 2014-10-22 16:55:29 +05:30
Pratik Vyas
da8a02d56e Merge branch 'develop' 2014-10-22 14:19:17 +05:30
Pratik Vyas
16343683d9 bumped to version 4.9.0 2014-10-22 14:49:17 +06:00
Nabin Hait
2bdc017aff Merge pull request #2339 from nabinhait/fix1
Minor fixes
2014-10-22 13:11:21 +05:30
Nabin Hait
16e05c321c Removed stock ageing grid report 2014-10-22 13:10:43 +05:30
Nabin Hait
23d7919865 Stock ageing report fix 2014-10-22 13:06:26 +05:30
Nabin Hait
38265efc39 Minor fix 2014-10-21 20:23:39 +05:30
Rushabh Mehta
2d414706dc [hotfix] translation boo boo 2014-10-21 11:49:40 +05:30
Rushabh Mehta
d85e4b0d46 Merge pull request #2331 from rmehta/translation
[translations] update
2014-10-20 17:12:22 +05:30
Rushabh Mehta
45d03af8f6 [translations] update 2014-10-20 17:11:06 +05:30
Nabin Hait
73a3a2a131 Merge pull request #2327 from nabinhait/stock_reco
Fixes in credit note and quotation
2014-10-20 11:51:01 +05:30
Nabin Hait
73804580d4 validate quotation to lead or customer 2014-10-20 11:18:11 +05:30
Nabin Hait
259f9779db Credit Note: Set total amount and print format fix 2014-10-20 11:18:11 +05:30
Pratik Vyas
14e0e58a7d Merge branch 'develop' 2014-10-17 15:04:05 +05:30
Pratik Vyas
5eb373f7b5 bumped to version 4.8.0 2014-10-17 15:34:05 +06:00
Nabin Hait
4595c30a7b Merge pull request #2322 from nabinhait/stock_reco
Partial payment reconciliation
2014-10-17 15:01:13 +05:30
Nabin Hait
fc2dd44694 Partial payment reconciliation. Fixes #1982 2014-10-17 14:57:20 +05:30
Pratik Vyas
053c54017e [minor] add admin password to travis test site 2014-10-17 14:16:10 +05:30
Pratik Vyas
af473d78f2 Merge branch 'develop' 2014-10-15 15:34:39 +05:30
Pratik Vyas
26d096aa87 bumped to version 4.7.2 2014-10-15 16:04:39 +06:00
Nabin Hait
476c613ba6 Merge pull request #2317 from nabinhait/stock_reco
repost stock utility
2014-10-15 15:33:50 +05:30
Nabin Hait
2348a5f592 repost stock utility 2014-10-15 15:31:33 +05:30
Pratik Vyas
9d8d045c66 Merge branch 'develop' 2014-10-15 14:44:35 +05:30
Pratik Vyas
63914dd55b bumped to version 4.7.1 2014-10-15 15:14:35 +06:00
Nabin Hait
93a8042f08 Merge pull request #2316 from nabinhait/stock_reco
Minor fix
2014-10-15 14:44:06 +05:30
Nabin Hait
b2f32dac1b Minor fix 2014-10-15 14:42:18 +05:30
Pratik Vyas
577a3acaac Merge branch 'develop' 2014-10-15 14:35:47 +05:30
Pratik Vyas
5e46ce8a50 bumped to version 4.7.0 2014-10-15 15:05:47 +06:00
Nabin Hait
3b7342b7b5 Merge pull request #2315 from nabinhait/stock_reco
Strip company in setup wizard
2014-10-15 13:59:07 +05:30
Nabin Hait
531077e504 Strip company in setup wizard 2014-10-15 13:55:37 +05:30
Nabin Hait
147918ed66 Merge pull request #2313 from nabinhait/stock_reco
Fix gl entries for stock transactions
2014-10-15 12:44:59 +05:30
Nabin Hait
9bbfca9226 Fix gl entries for stock transactions 2014-10-15 12:24:38 +05:30
Nabin Hait
f1a07ff105 Allow zero rate while reposting 2014-10-15 12:23:35 +05:30
Nabin Hait
fb6e434315 Guess valuation rate in case of negative stock 2014-10-15 11:34:40 +05:30
Rushabh Mehta
3811d96feb Merge pull request #2308 from devdesco-ceo/patch-1
Update README.md
2014-10-15 10:02:06 +05:30
Viktor Zhuromskyy
1017615d02 Update README.md 2014-10-14 10:12:10 -05:00
163 changed files with 13295 additions and 9661 deletions

View File

@@ -16,8 +16,9 @@ install:
- sudo apt-get install mariadb-server mariadb-common libmariadbclient-dev
- ./ci/fix-mariadb.sh
- wget http://downloads.sourceforge.net/project/wkhtmltopdf/0.12.1/wkhtmltox-0.12.1_linux-precise-amd64.deb
- sudo dpkg -i wkhtmltox-0.12.1_linux-precise-amd64.deb
- sudo apt-get install xfonts-75dpi xfonts-base -y
- wget http://downloads.sourceforge.net/project/wkhtmltopdf/0.12.2.1/wkhtmltox-0.12.2.1_linux-precise-amd64.deb
- sudo dpkg -i wkhtmltox-0.12.2.1_linux-precise-amd64.deb
- CFLAGS=-O0 pip install git+https://github.com/frappe/frappe.git@develop
- CFLAGS=-O0 pip install --editable .

View File

@@ -1,34 +1,33 @@
# ERPNext - Open Source ERP for small, medium sized businesses [![Build Status](https://travis-ci.org/frappe/erpnext.png)](https://travis-ci.org/frappe/erpnext)
# ERPNext - Open source ERP for small and medium-size business [![Build Status](https://travis-ci.org/frappe/erpnext.png)](https://travis-ci.org/frappe/erpnext)
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/frappe/erpnext?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[https://erpnext.com](https://erpnext.com)
Includes Accounting, Inventory, CRM, Sales, Purchase, Projects, HRMS. Built on Python / MariaDB.
Includes: Accounting, Inventory, CRM, Sales, Purchase, Projects, HRMS. Requires MariaDB.
ERPNext is built on [frappe](https://github.com/frappe/frappe)
ERPNext is built on the [Frappe](https://github.com/frappe/frappe) Framework, a full-stack web app framework in Python & Javascript.
- [User Guide](http://erpnext.org/user-guide.html)
- [User Guide](https://erpnext.com/user-guide)
- [Getting Help](http://erpnext.org/getting-help.html)
- [Developer Forum](http://groups.google.com/group/erpnext-developer-forum)
- [User Forum](http://groups.google.com/group/erpnext-user-forum)
- [Discussion Forum](https://discuss.frappe.io/)
---
### Install
### Full Install
Use the bench, https://github.com/frappe/bench
The Easy Way install script for bench will install all dependencies (e.g. MariaDB). See https://github.com/frappe/bench
### Admin Login
New passwords will be created for the ERPNext "Administrator" user, the MariaDB root user, and the frappe user (the script displays the passwords and saves them to ~/frappe_passwords.txt).
1. go to "/login"
1. Administrator user name: "Administrator"
1. Administrator passowrd "admin"
### Virtual Image
### Download and Install
##### Virtual Image:
You can download a virtual image to run ERPNext in a virtual machine on your local system.
- [ERPNext Download](http://erpnext.com/download)
System and user credentials are listed on the download page.
---
## License

View File

@@ -1 +1 @@
__version__ = '4.6.2'
__version__ = '4.21.4'

View File

@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import flt, cstr, cint, getdate, add_days, formatdate
from frappe.utils import flt, cstr, cint, getdate
from frappe import msgprint, throw, _
from frappe.model.document import Document
@@ -176,15 +176,7 @@ class Account(Document):
frappe.throw(_("Due Date cannot be before Posting Date"))
elif credit_days is not None and diff > credit_days:
is_credit_controller = frappe.db.get_value("Accounts Settings", None,
"credit_controller") in frappe.user.get_roles()
if is_credit_controller:
msgprint(_("Note: Due Date exceeds the allowed credit days by {0} day(s)").format(
diff - credit_days))
else:
max_due_date = formatdate(add_days(posting_date, credit_days))
frappe.throw(_("Due Date cannot be after {0}").format(max_due_date))
msgprint(_("Note: Due Date exceeds the allowed credit days by {0} day(s)").format(diff - credit_days))
def validate_trash(self):
"""checks gl entries and if child exists"""

View File

@@ -124,6 +124,10 @@ def update_outstanding_amt(account, against_voucher_type, against_voucher, on_ca
from `tabGL Entry` where voucher_type = 'Journal Voucher' and voucher_no = %s
and account = %s and ifnull(against_voucher, '') = ''""",
(against_voucher, account))[0][0])
if not against_voucher_amount:
frappe.throw(_("Against Journal Voucher {0} is already adjusted against some other voucher")
.format(against_voucher))
bal = against_voucher_amount + bal
if against_voucher_amount < 0:
bal = -bal

View File

@@ -213,10 +213,11 @@ cur_frm.cscript.voucher_type = function(doc, cdt, cdn) {
return;
var update_jv_details = function(doc, r) {
$.each(r.message, function(i, d) {
var jvdetail = frappe.model.add_child(doc, "Journal Voucher Detail", "entries");
jvdetail.account = d.account;
jvdetail.balance = d.balance;
var jvdetail = frappe.model.add_child(doc, "Journal Voucher Detail", "entries");
$.each(r, function(i, d) {
var row = frappe.model.add_child(doc, "Journal Voucher Detail", "entries");
row.account = d.account;
row.balance = d.balance;
});
refresh_field("entries");
}
@@ -231,7 +232,7 @@ cur_frm.cscript.voucher_type = function(doc, cdt, cdn) {
},
callback: function(r) {
if(r.message) {
update_jv_details(doc, r);
update_jv_details(doc, [r.message]);
}
}
})
@@ -245,7 +246,7 @@ cur_frm.cscript.voucher_type = function(doc, cdt, cdn) {
callback: function(r) {
frappe.model.clear_table(doc, "entries");
if(r.message) {
update_jv_details(doc, r);
update_jv_details(doc, r.message);
}
cur_frm.set_value("is_opening", "Yes")
}

View File

@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import cint, cstr, flt, fmt_money, formatdate, getdate
from frappe.utils import cstr, flt, fmt_money, formatdate, getdate
from frappe import msgprint, _, scrub
from erpnext.setup.utils import get_company_currency
@@ -13,10 +13,6 @@ from erpnext.controllers.accounts_controller import AccountsController
class JournalVoucher(AccountsController):
def __init__(self, arg1, arg2=None):
super(JournalVoucher, self).__init__(arg1, arg2)
self.master_type = {}
self.credit_days_for = {}
self.credit_days_global = -1
self.is_approving_authority = -1
def validate(self):
if not self.is_opening:
@@ -40,7 +36,7 @@ class JournalVoucher(AccountsController):
def on_submit(self):
if self.voucher_type in ['Bank Voucher', 'Contra Voucher', 'Journal Entry']:
self.check_credit_days()
self.check_reference_date()
self.make_gl_entries()
self.check_credit_limit()
self.update_advance_paid()
@@ -88,15 +84,24 @@ class JournalVoucher(AccountsController):
def validate_against_jv(self):
for d in self.get('entries'):
if d.against_jv:
account_root_type = frappe.db.get_value("Account", d.account, "root_type")
if account_root_type == "Asset" and flt(d.debit) > 0:
frappe.throw(_("For {0}, only credit entries can be linked against another debit entry")
.format(d.account))
elif account_root_type == "Liability" and flt(d.credit) > 0:
frappe.throw(_("For {0}, only debit entries can be linked against another credit entry")
.format(d.account))
if d.against_jv == self.name:
frappe.throw(_("You can not enter current voucher in 'Against Journal Voucher' column"))
against_entries = frappe.db.sql("""select * from `tabJournal Voucher Detail`
where account = %s and docstatus = 1 and parent = %s
and ifnull(against_jv, '') = ''""", (d.account, d.against_jv), as_dict=True)
and ifnull(against_jv, '') = '' and ifnull(against_invoice, '') = ''
and ifnull(against_voucher, '') = ''""", (d.account, d.against_jv), as_dict=True)
if not against_entries:
frappe.throw(_("Journal Voucher {0} does not have account {1} or already matched")
frappe.throw(_("Journal Voucher {0} does not have account {1} or already matched against other voucher")
.format(d.against_jv, d.account))
else:
dr_or_cr = "debit" if d.credit > 0 else "credit"
@@ -153,7 +158,7 @@ class JournalVoucher(AccountsController):
and voucher_account != d.account:
frappe.throw(_("Row {0}: Account {1} does not match with {2} {3} account") \
.format(d.idx, d.account, doctype, field_dict.get(doctype)))
if against_field in ["against_sales_order", "against_purchase_order"]:
if voucher_account != account_master_name:
frappe.throw(_("Row {0}: Account {1} does not match with {2} {3} Name") \
@@ -165,7 +170,7 @@ class JournalVoucher(AccountsController):
def validate_against_invoice_fields(self, doctype, payment_against_voucher):
for voucher_no, payment_list in payment_against_voucher.items():
voucher_properties = frappe.db.get_value(doctype, voucher_no,
voucher_properties = frappe.db.get_value(doctype, voucher_no,
["docstatus", "outstanding_amount"])
if voucher_properties[0] != 1:
@@ -177,7 +182,7 @@ class JournalVoucher(AccountsController):
def validate_against_order_fields(self, doctype, payment_against_voucher):
for voucher_no, payment_list in payment_against_voucher.items():
voucher_properties = frappe.db.get_value(doctype, voucher_no,
voucher_properties = frappe.db.get_value(doctype, voucher_no,
["docstatus", "per_billed", "status", "advance_paid", "grand_total"])
if voucher_properties[0] != 1:
@@ -280,71 +285,38 @@ class JournalVoucher(AccountsController):
def set_print_format_fields(self):
for d in self.get('entries'):
result = frappe.db.get_value("Account", d.account,
["account_type", "master_type"])
acc = frappe.db.get_value("Account", d.account, ["account_type", "master_type"], as_dict=1)
if not result:
continue
if not acc: continue
account_type, master_type = result
if master_type in ['Supplier', 'Customer']:
if acc.master_type in ['Supplier', 'Customer']:
if not self.pay_to_recd_from:
self.pay_to_recd_from = frappe.db.get_value(master_type,
' - '.join(d.account.split(' - ')[:-1]),
master_type == 'Customer' and 'customer_name' or 'supplier_name')
self.pay_to_recd_from = frappe.db.get_value(acc.master_type, ' - '.join(d.account.split(' - ')[:-1]),
acc.master_type == 'Customer' and 'customer_name' or 'supplier_name')
if self.voucher_type in ["Credit Note", "Debit Note"]:
self.set_total_amount(d.debit or d.credit)
if account_type in ['Bank', 'Cash']:
company_currency = get_company_currency(self.company)
amt = flt(d.debit) and d.debit or d.credit
self.total_amount = fmt_money(amt, currency=company_currency)
from frappe.utils import money_in_words
self.total_amount_in_words = money_in_words(amt, company_currency)
if acc.account_type in ['Bank', 'Cash']:
self.set_total_amount(d.debit or d.credit)
def check_credit_days(self):
date_diff = 0
def set_total_amount(self, amt):
company_currency = get_company_currency(self.company)
self.total_amount = fmt_money(amt, currency=company_currency)
from frappe.utils import money_in_words
self.total_amount_in_words = money_in_words(amt, company_currency)
def check_reference_date(self):
if self.cheque_date:
date_diff = (getdate(self.cheque_date)-getdate(self.posting_date)).days
for d in self.get("entries"):
due_date = None
if d.against_invoice and flt(d.credit) > 0:
due_date = frappe.db.get_value("Sales Invoice", d.against_invoice, "due_date")
elif d.against_voucher and flt(d.debit) > 0:
due_date = frappe.db.get_value("Purchase Invoice", d.against_voucher, "due_date")
if date_diff <= 0: return
# Get List of Customer Account
acc_list = filter(lambda d: frappe.db.get_value("Account", d.account,
"master_type")=='Customer', self.get('entries'))
for d in acc_list:
credit_days = self.get_credit_days_for(d.account)
# Check credit days
if credit_days > 0 and not self.get_authorized_user() and cint(date_diff) > credit_days:
msgprint(_("Maximum allowed credit is {0} days after posting date").format(credit_days),
raise_exception=1)
def get_credit_days_for(self, ac):
if not self.credit_days_for.has_key(ac):
self.credit_days_for[ac] = cint(frappe.db.get_value("Account", ac, "credit_days"))
if not self.credit_days_for[ac]:
if self.credit_days_global==-1:
self.credit_days_global = cint(frappe.db.get_value("Company",
self.company, "credit_days"))
return self.credit_days_global
else:
return self.credit_days_for[ac]
def get_authorized_user(self):
if self.is_approving_authority==-1:
self.is_approving_authority = 0
# Fetch credit controller role
approving_authority = frappe.db.get_value("Accounts Settings", None,
"credit_controller")
# Check logged-in user is authorized
if approving_authority in frappe.user.get_roles():
self.is_approving_authority = 1
return self.is_approving_authority
if due_date and getdate(self.cheque_date) > getdate(due_date):
msgprint(_("Note: Reference Date {0} is after invoice due date {1}")
.format(formatdate(self.cheque_date), formatdate(due_date)))
def make_gl_entries(self, cancel=0, adv_adj=0):
from erpnext.accounts.general_ledger import make_gl_entries
@@ -377,7 +349,7 @@ class JournalVoucher(AccountsController):
for d in self.get("entries"):
master_type, master_name = frappe.db.get_value("Account", d.account,
["master_type", "master_name"])
if master_type == "Customer" and master_name:
if master_type == "Customer" and master_name and flt(d.debit) > 0:
super(JournalVoucher, self).check_credit_limit(d.account)
def get_balance(self):
@@ -532,9 +504,10 @@ def get_against_sales_invoice(doctype, txt, searchfield, start, page_len, filter
(filters["account"], "%%%s%%" % txt, start, page_len))
def get_against_jv(doctype, txt, searchfield, start, page_len, filters):
return frappe.db.sql("""select jv.name, jv.posting_date, jv.user_remark
from `tabJournal Voucher` jv, `tabJournal Voucher Detail` jv_detail
where jv_detail.parent = jv.name and jv_detail.account = %s and jv.docstatus = 1
return frappe.db.sql("""select distinct jv.name, jv.posting_date, jv.user_remark
from `tabJournal Voucher` jv, `tabJournal Voucher Detail` jvd
where jvd.parent = jv.name and jvd.account = %s and jv.docstatus = 1
and (ifnull(jvd.against_invoice, '') = '' and ifnull(jvd.against_voucher, '') = '' and ifnull(jvd.against_jv, '') = '' )
and jv.%s like %s order by jv.name desc limit %s, %s""" %
("%s", searchfield, "%s", "%s", "%s"),
(filters["account"], "%%%s%%" % txt, start, page_len))

View File

@@ -19,9 +19,9 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
]
};
}
});
this.frm.set_query('bank_cash_account', function() {
if(!me.frm.doc.company) {
msgprint(__("Please select company first"));
@@ -35,12 +35,8 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
};
}
});
var help_content = '<i class="icon-hand-right"></i> ' + __("Note") + ':<br>'+
'<ul>' + __("If you are unable to match the exact amount, then amend your Journal Voucher and split rows such that payment amount match the invoice amount.") + '</ul>';
this.frm.set_value("reconcile_help", help_content);
},
get_unreconciled_entries: function() {
var me = this;
return this.frm.call({
@@ -48,12 +44,12 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
method: 'get_unreconciled_entries',
callback: function(r, rt) {
var invoices = [];
$.each(me.frm.doc.payment_reconciliation_invoices || [], function(i, row) {
if (row.invoice_number && !inList(invoices, row.invoice_number))
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");
@@ -79,4 +75,4 @@ erpnext.accounts.PaymentReconciliationController = frappe.ui.form.Controller.ext
$.extend(cur_frm.cscript, new erpnext.accounts.PaymentReconciliationController({frm: cur_frm}));
cur_frm.add_fetch('party_account', 'master_type', 'party_type')
cur_frm.add_fetch('party_account', 'master_type', 'party_type')

View File

@@ -118,19 +118,12 @@
"options": "Payment Reconciliation Invoice",
"permlevel": 0,
"read_only": 1
},
{
"fieldname": "reconcile_help",
"fieldtype": "Small Text",
"label": "",
"permlevel": 0,
"read_only": 1
}
],
"hide_toolbar": 1,
"icon": "icon-resize-horizontal",
"issingle": 1,
"modified": "2014-07-31 05:43:03.410832",
"modified": "2014-10-16 17:51:44.367107",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Reconciliation",

View File

@@ -96,13 +96,14 @@ class PaymentReconciliation(Document):
payment_amount = payment_amount[0][0] if payment_amount else 0
if d.invoice_amount > payment_amount:
if d.invoice_amount - payment_amount > 0.005:
non_reconciled_invoices.append({
'voucher_no': d.voucher_no,
'voucher_type': d.voucher_type,
'posting_date': d.posting_date,
'invoice_amount': flt(d.invoice_amount),
'outstanding_amount': d.invoice_amount - payment_amount})
'outstanding_amount': flt(d.invoice_amount - payment_amount, 2)
})
self.add_invoice_entries(non_reconciled_invoices)
@@ -124,7 +125,7 @@ class PaymentReconciliation(Document):
dr_or_cr = "credit" if self.party_type == "Customer" else "debit"
lst = []
for e in self.get('payment_reconciliation_payments'):
if e.invoice_type and e.invoice_number:
if e.invoice_type and e.invoice_number and e.allocated_amount:
lst.append({
'voucher_no' : e.journal_voucher,
'voucher_detail_no' : e.voucher_detail_number,
@@ -134,7 +135,7 @@ class PaymentReconciliation(Document):
'is_advance' : e.is_advance,
'dr_or_cr' : dr_or_cr,
'unadjusted_amt' : flt(e.amount),
'allocated_amt' : flt(e.amount)
'allocated_amt' : flt(e.allocated_amount)
})
if lst:
@@ -162,18 +163,23 @@ class PaymentReconciliation(Document):
invoices_to_reconcile = []
for p in self.get("payment_reconciliation_payments"):
if p.invoice_type and p.invoice_number:
if p.invoice_type and p.invoice_number and p.allocated_amount:
invoices_to_reconcile.append(p.invoice_number)
if p.invoice_number not in unreconciled_invoices.get(p.invoice_type, {}):
frappe.throw(_("{0}: {1} not found in Invoice Details table")
.format(p.invoice_type, p.invoice_number))
if p.amount > unreconciled_invoices.get(p.invoice_type, {}).get(p.invoice_number):
frappe.throw(_("Row {0}: Payment amount must be less than or equals to invoice outstanding amount. Please refer Note below.").format(p.idx))
if flt(p.allocated_amount) > flt(p.amount):
frappe.throw(_("Row {0}: Allocated amount {1} must be less than or equals to JV amount {2}")
.format(p.idx, p.allocated_amount, p.amount))
if flt(p.allocated_amount) > unreconciled_invoices.get(p.invoice_type, {}).get(p.invoice_number):
frappe.throw(_("Row {0}: Allocated amount {1} must be less than or equals to invoice outstanding amount {2}")
.format(p.idx, p.allocated_amount, unreconciled_invoices.get(p.invoice_type, {}).get(p.invoice_number)))
if not invoices_to_reconcile:
frappe.throw(_("Please select Invoice Type and Invoice Number in atleast one row"))
frappe.throw(_("Please select Allocated Amount, Invoice Type and Invoice Number in atleast one row"))
def check_condition(self, dr_or_cr):
cond = self.from_date and " and posting_date >= '" + self.from_date + "'" or ""

View File

@@ -53,11 +53,20 @@
"label": "Column Break",
"permlevel": 0
},
{
"fieldname": "allocated_amount",
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Allocated amount",
"permlevel": 0,
"precision": "",
"reqd": 1
},
{
"default": "Sales Invoice",
"fieldname": "invoice_type",
"fieldtype": "Select",
"in_list_view": 1,
"in_list_view": 0,
"label": "Invoice Type",
"options": "\nSales Invoice\nPurchase Invoice\nJournal Voucher",
"permlevel": 0,
@@ -95,7 +104,7 @@
}
],
"istable": 1,
"modified": "2014-07-21 16:53:56.206169",
"modified": "2014-10-16 17:40:54.040194",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Reconciliation Payment",

View File

@@ -42,9 +42,6 @@ frappe.ui.form.on("Payment Tool", "received_or_paid", function(frm) {
erpnext.payment_tool.check_mandatory_to_set_button(frm);
});
// Fetch bank/cash account based on payment mode
cur_frm.add_fetch("payment_mode", "default_account", "payment_account");
// Set party account name
frappe.ui.form.on("Payment Tool", "customer", function(frm) {
erpnext.payment_tool.set_party_account(frm);

View File

@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import frappe
from frappe import _, scrub
from frappe import _
from frappe.utils import flt
from frappe.model.document import Document
import json
@@ -93,7 +93,7 @@ def get_orders_to_be_billed(party_type, party_name):
and docstatus = 1
and ifnull(status, "") != "Stopped"
and ifnull(grand_total, 0) > ifnull(advance_paid, 0)
and ifnull(per_billed, 0) < 100.0
and abs(100 - ifnull(per_billed, 0)) > 0.01
""" % (voucher_type, 'customer' if party_type == "Customer" else 'supplier', '%s'),
party_name, as_dict = True)

View File

@@ -800,7 +800,8 @@
"fieldtype": "Date",
"label": "From Date",
"no_copy": 1,
"permlevel": 0
"permlevel": 0,
"print_hide": 1
},
{
"allow_on_submit": 1,
@@ -810,7 +811,8 @@
"fieldtype": "Date",
"label": "To Date",
"no_copy": 1,
"permlevel": 0
"permlevel": 0,
"print_hide": 1
},
{
"allow_on_submit": 1,
@@ -878,7 +880,7 @@
"icon": "icon-file-text",
"idx": 1,
"is_submittable": 1,
"modified": "2014-10-08 14:23:20.234176",
"modified": "2014-11-27 17:28:20.133701",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice",

View File

@@ -405,7 +405,7 @@ def get_expense_account(doctype, txt, searchfield, start, page_len, filters):
# 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 = "Expense Account")
or tabAccount.account_type in ("Expense Account", "Fixed Asset"))
and tabAccount.group_or_ledger="Ledger"
and tabAccount.docstatus!=2
and ifnull(tabAccount.master_type, "")=""

View File

@@ -114,7 +114,7 @@ erpnext.POS = Class.extend({
});
this.wrapper.find('input.discount-amount').on("change", function() {
frappe.model.set_value(me.frm.doctype, me.frm.docname, "discount_amount", this.value);
frappe.model.set_value(me.frm.doctype, me.frm.docname, "discount_amount", flt(this.value));
});
this.call_function("remove-items", function() {me.remove_selected_items();});
@@ -233,6 +233,11 @@ erpnext.POS = Class.extend({
},
make_item_list: function() {
var me = this;
if(!this.price_list) {
msgprint(__("Price List not found or disabled"));
return;
}
me.item_timeout = null;
frappe.call({
method: 'erpnext.accounts.doctype.sales_invoice.pos.get_items',
@@ -487,7 +492,7 @@ erpnext.POS = Class.extend({
});
me.refresh_delete_btn();
if(me.frm.doc[this.party]) {
if(me.frm.doc[this.party.toLowerCase()]) {
this.barcode.$input.focus();
} else {
this.party_field.$input.focus();

View File

@@ -225,8 +225,7 @@ $.extend(cur_frm.cscript, new erpnext.accounts.SalesInvoiceController({frm: cur_
// Hide Fields
// ------------
cur_frm.cscript.hide_fields = function(doc) {
par_flds = ['project_name', 'due_date', 'is_opening', 'source', 'total_advance', 'gross_profit',
'gross_profit_percent', 'get_advances_received',
par_flds = ['project_name', 'due_date', 'is_opening', 'source', 'total_advance', 'get_advances_received',
'advance_adjustment_details', 'sales_partner', 'commission_rate',
'total_commission', 'advances', 'from_date', 'to_date'];

View File

@@ -422,6 +422,15 @@
"fieldtype": "Section Break",
"permlevel": 0
},
{
"fieldname": "other_charges_total_export",
"fieldtype": "Currency",
"label": "Total Taxes and Charges",
"options": "currency",
"permlevel": 0,
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "other_charges_total",
"fieldtype": "Currency",
@@ -438,23 +447,24 @@
"fieldtype": "Column Break",
"permlevel": 0
},
{
"fieldname": "other_charges_total_export",
"fieldtype": "Currency",
"label": "Total Taxes and Charges",
"options": "currency",
"permlevel": 0,
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "discount_amount",
"fieldtype": "Currency",
"label": "Discount Amount",
"options": "Company:company:default_currency",
"options": "currency",
"permlevel": 0,
"print_hide": 0
},
{
"fieldname": "base_discount_amount",
"fieldtype": "Currency",
"label": "Discount Amount (Company Currency)",
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "totals",
"fieldtype": "Section Break",
@@ -568,27 +578,6 @@
"print_hide": 0,
"read_only": 1
},
{
"fieldname": "gross_profit",
"fieldtype": "Currency",
"label": "Gross Profit",
"oldfieldname": "gross_profit",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "gross_profit_percent",
"fieldtype": "Float",
"label": "Gross Profit (%)",
"oldfieldname": "gross_profit_percent",
"oldfieldtype": "Currency",
"permlevel": 0,
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "advances",
"fieldtype": "Section Break",
@@ -1213,7 +1202,7 @@
"icon": "icon-file-text",
"idx": 1,
"is_submittable": 1,
"modified": "2014-10-10 16:54:22.284284",
"modified": "2015-01-12 17:34:36.353241",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Invoice",

View File

@@ -7,7 +7,7 @@ import frappe.defaults
from frappe.utils import cint, cstr, flt
from frappe import _, msgprint, throw
from erpnext.accounts.party import get_party_account, get_due_date
from erpnext.controllers.stock_controller import update_gl_entries_after, block_negative_stock
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
@@ -456,8 +456,8 @@ class SalesInvoice(SellingController):
self.make_sl_entries(sl_entries)
def make_gl_entries(self, repost_future_gle=True, allow_negative_stock=False):
gl_entries = self.get_gl_entries(allow_negative_stock=allow_negative_stock)
def make_gl_entries(self, repost_future_gle=True):
gl_entries = self.get_gl_entries()
if gl_entries:
from erpnext.accounts.general_ledger import make_gl_entries
@@ -476,7 +476,7 @@ class SalesInvoice(SellingController):
items, warehouses = self.get_items_and_warehouses()
update_gl_entries_after(self.posting_date, self.posting_time, warehouses, items)
def get_gl_entries(self, warehouse_account=None, allow_negative_stock=False):
def get_gl_entries(self, warehouse_account=None):
from erpnext.accounts.general_ledger import merge_similar_entries
gl_entries = []
@@ -485,7 +485,7 @@ class SalesInvoice(SellingController):
self.make_tax_gl_entries(gl_entries)
self.make_item_gl_entries(gl_entries, allow_negative_stock)
self.make_item_gl_entries(gl_entries)
# merge gl entries before adding pos entries
gl_entries = merge_similar_entries(gl_entries)
@@ -520,7 +520,7 @@ class SalesInvoice(SellingController):
})
)
def make_item_gl_entries(self, gl_entries, allow_negative_stock=False):
def make_item_gl_entries(self, gl_entries):
# income account gl entries
for item in self.get("entries"):
if flt(item.base_amount):
@@ -537,7 +537,7 @@ class SalesInvoice(SellingController):
# expense account gl entries
if cint(frappe.defaults.get_global_default("auto_accounting_for_stock")) \
and cint(self.update_stock):
gl_entries += super(SalesInvoice, self).get_gl_entries(allow_negative_stock=allow_negative_stock)
gl_entries += super(SalesInvoice, self).get_gl_entries()
def make_pos_gl_entries(self, gl_entries):
if cint(self.is_pos) and self.cash_bank_account and self.paid_amount:

View File

@@ -1,155 +1,156 @@
{
"autoname": "INVTD.######",
"creation": "2013-04-24 11:39:32",
"docstatus": 0,
"doctype": "DocType",
"autoname": "INVTD.######",
"creation": "2013-04-24 11:39:32",
"docstatus": 0,
"doctype": "DocType",
"fields": [
{
"fieldname": "charge_type",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Type",
"oldfieldname": "charge_type",
"oldfieldtype": "Select",
"options": "\nActual\nOn Net Total\nOn Previous Row Amount\nOn Previous Row Total",
"permlevel": 0,
"fieldname": "charge_type",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Type",
"oldfieldname": "charge_type",
"oldfieldtype": "Select",
"options": "\nActual\nOn Net Total\nOn Previous Row Amount\nOn Previous Row Total",
"permlevel": 0,
"reqd": 1
},
},
{
"depends_on": "eval:[\"On Previous Row Amount\", \"On Previous Row Total\"].indexOf(doc.charge_type)!==-1",
"fieldname": "row_id",
"fieldtype": "Data",
"hidden": 0,
"label": "Reference Row #",
"oldfieldname": "row_id",
"oldfieldtype": "Data",
"depends_on": "eval:[\"On Previous Row Amount\", \"On Previous Row Total\"].indexOf(doc.charge_type)!==-1",
"fieldname": "row_id",
"fieldtype": "Data",
"hidden": 0,
"label": "Reference Row #",
"oldfieldname": "row_id",
"oldfieldtype": "Data",
"permlevel": 0
},
},
{
"fieldname": "description",
"fieldtype": "Small Text",
"in_list_view": 1,
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Small Text",
"permlevel": 0,
"print_width": "300px",
"reqd": 1,
"fieldname": "description",
"fieldtype": "Small Text",
"in_list_view": 1,
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Small Text",
"permlevel": 0,
"print_width": "300px",
"reqd": 1,
"width": "300px"
},
},
{
"fieldname": "col_break_1",
"fieldtype": "Column Break",
"permlevel": 0,
"fieldname": "col_break_1",
"fieldtype": "Column Break",
"permlevel": 0,
"width": "50%"
},
},
{
"fieldname": "account_head",
"fieldtype": "Link",
"in_list_view": 0,
"label": "Account Head",
"oldfieldname": "account_head",
"oldfieldtype": "Link",
"options": "Account",
"permlevel": 0,
"reqd": 1,
"fieldname": "account_head",
"fieldtype": "Link",
"in_list_view": 0,
"label": "Account Head",
"oldfieldname": "account_head",
"oldfieldtype": "Link",
"options": "Account",
"permlevel": 0,
"reqd": 1,
"search_index": 1
},
},
{
"default": ":Company",
"fieldname": "cost_center",
"fieldtype": "Link",
"in_list_view": 0,
"label": "Cost Center",
"oldfieldname": "cost_center_other_charges",
"oldfieldtype": "Link",
"options": "Cost Center",
"default": ":Company",
"fieldname": "cost_center",
"fieldtype": "Link",
"in_list_view": 0,
"label": "Cost Center",
"oldfieldname": "cost_center_other_charges",
"oldfieldtype": "Link",
"options": "Cost Center",
"permlevel": 0
},
},
{
"fieldname": "rate",
"fieldtype": "Float",
"in_list_view": 1,
"label": "Rate",
"oldfieldname": "rate",
"oldfieldtype": "Currency",
"permlevel": 0,
"fieldname": "rate",
"fieldtype": "Float",
"in_list_view": 1,
"label": "Rate",
"oldfieldname": "rate",
"oldfieldtype": "Currency",
"permlevel": 0,
"reqd": 1
},
},
{
"fieldname": "tax_amount",
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Amount",
"oldfieldname": "tax_amount",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"read_only": 1,
"fieldname": "tax_amount",
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Amount",
"oldfieldname": "tax_amount",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"read_only": 1,
"reqd": 0
},
},
{
"fieldname": "total",
"fieldtype": "Currency",
"label": "Total",
"oldfieldname": "total",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"fieldname": "total",
"fieldtype": "Currency",
"label": "Total",
"oldfieldname": "total",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"permlevel": 0,
"read_only": 1
},
},
{
"allow_on_submit": 0,
"description": "If checked, the tax amount will be considered as already included in the Print Rate / Print Amount",
"fieldname": "included_in_print_rate",
"fieldtype": "Check",
"label": "Is this Tax included in Basic Rate?",
"no_copy": 0,
"permlevel": 0,
"print_hide": 1,
"print_width": "150px",
"report_hide": 1,
"allow_on_submit": 0,
"description": "If checked, the tax amount will be considered as already included in the Print Rate / Print Amount",
"fieldname": "included_in_print_rate",
"fieldtype": "Check",
"label": "Is this Tax included in Basic Rate?",
"no_copy": 0,
"permlevel": 0,
"print_hide": 1,
"print_width": "150px",
"report_hide": 1,
"width": "150px"
},
},
{
"fieldname": "tax_amount_after_discount_amount",
"fieldtype": "Currency",
"hidden": 1,
"label": "Tax Amount After Discount Amount",
"options": "Company:company:default_currency",
"permlevel": 0,
"depends_on": "eval:parent.discount_amount",
"fieldname": "tax_amount_after_discount_amount",
"fieldtype": "Currency",
"hidden": 0,
"label": "Tax Amount After Discount Amount",
"options": "Company:company:default_currency",
"permlevel": 0,
"read_only": 1
},
},
{
"fieldname": "item_wise_tax_detail",
"fieldtype": "Small Text",
"hidden": 1,
"label": "Item Wise Tax Detail",
"oldfieldname": "item_wise_tax_detail",
"oldfieldtype": "Small Text",
"permlevel": 0,
"fieldname": "item_wise_tax_detail",
"fieldtype": "Small Text",
"hidden": 1,
"label": "Item Wise Tax Detail",
"oldfieldname": "item_wise_tax_detail",
"oldfieldtype": "Small Text",
"permlevel": 0,
"read_only": 1
},
},
{
"fieldname": "parenttype",
"fieldtype": "Data",
"hidden": 1,
"in_filter": 1,
"label": "Parenttype",
"oldfieldname": "parenttype",
"oldfieldtype": "Data",
"permlevel": 0,
"print_hide": 1,
"fieldname": "parenttype",
"fieldtype": "Data",
"hidden": 1,
"in_filter": 1,
"label": "Parenttype",
"oldfieldname": "parenttype",
"oldfieldtype": "Data",
"permlevel": 0,
"print_hide": 1,
"search_index": 1
}
],
"hide_heading": 1,
"idx": 1,
"istable": 1,
"modified": "2014-05-30 03:43:39.740638",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Taxes and Charges",
"owner": "Administrator",
],
"hide_heading": 1,
"idx": 1,
"istable": 1,
"modified": "2014-12-10 12:26:41.222471",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Sales Taxes and Charges",
"owner": "Administrator",
"permissions": []
}
}

View File

@@ -46,17 +46,17 @@ cur_frm.pformat.other_charges= function(doc){
var new_val = flt(val)/flt(doc.conversion_rate);
return new_val;
}
function print_hide(fieldname) {
var doc_field = frappe.meta.get_docfield(doc.doctype, fieldname, doc.name);
return doc_field.print_hide;
}
out ='';
if (!doc.print_without_amount) {
var cl = doc.other_charges || [];
// outer table
// outer table
var out='<div><table class="noborder" style="width:100%"><tr><td style="width: 60%"></td><td>';
// main table
@@ -77,12 +77,12 @@ cur_frm.pformat.other_charges= function(doc){
// Discount Amount
if(!print_hide('discount_amount') && doc.discount_amount)
out += make_row('Discount Amount', convert_rate(doc.discount_amount), 0);
out += make_row('Discount Amount', doc.discount_amount, 0);
// grand total
if(!print_hide('grand_total_export'))
out += make_row('Grand Total', doc.grand_total_export, 1);
if(!print_hide('rounded_total_export'))
out += make_row('Rounded Total', doc.rounded_total_export, 1);
@@ -92,7 +92,7 @@ cur_frm.pformat.other_charges= function(doc){
out += '<table><tr><td style="width:25%;"><b>In Words</b></td>';
out += '<td style="width:50%;">' + doc.in_words_export + '</td></tr>';
}
out += '</table></td></tr></table></div>';
out += '</table></td></tr></table></div>';
}
return out;
}
@@ -139,14 +139,14 @@ cur_frm.fields_dict['other_charges'].grid.get_field("account_head").get_query =
"account_type": ["Tax", "Chargeable", "Income Account"],
"company": doc.company
}
}
}
}
cur_frm.fields_dict['other_charges'].grid.get_field("cost_center").get_query = function(doc) {
return{
'company': doc.company,
'group_or_ledger': "Ledger"
}
}
}
cur_frm.cscript.rate = function(doc, cdt, cdn) {

View File

@@ -3,9 +3,9 @@
"doc_type": "Journal Voucher",
"docstatus": 0,
"doctype": "Print Format",
"html": "<div style=\"position: relative\">\n\n\t{%- from \"templates/print_formats/standard_macros.html\" import add_header -%}\n<div class=\"page-break\">\n {%- if not doc.get(\"print_heading\") and not doc.get(\"select_print_heading\") \n and doc.set(\"select_print_heading\", _(\"Payment Advice\")) -%}{%- endif -%}\n {{ add_header(0, 1, doc, letter_head, no_letterhead) }}\n\n{%- for label, value in (\n (_(\"Voucher Date\"), frappe.utils.formatdate(doc.voucher_date)),\n (_(\"Reference / Cheque No.\"), doc.cheque_no),\n (_(\"Reference / Cheque Date\"), frappe.utils.formatdate(doc.cheque_date))\n ) -%}\n <div class=\"row\">\n <div class=\"col-sm-4\"><label class=\"text-right\">{{ label }}</label></div>\n <div class=\"col-sm-8\">{{ value }}</div>\n </div>\n{%- endfor -%}\n\t<hr>\n\t<p>{{ _(\"This amount is in full / part settlement of the listed bills\") }}:</p>\n{%- for label, value in (\n (_(\"Amount\"), \"<strong>\" + (doc.total_amount or \"\") + \"</strong><br>\" + (doc.total_amount_in_words or \"\") + \"<br>\"),\n (_(\"References\"), doc.remark)\n ) -%}\n <div class=\"row\">\n <div class=\"col-sm-4\"><label class=\"text-right\">{{ label }}</label></div>\n <div class=\"col-sm-8\">{{ value }}</div>\n </div>\n {%- endfor -%}\n <hr>\n\t<div style=\"position: absolute; top: 14cm; left: 0cm;\">\n\t\tPrepared By</div>\n\t<div style=\"position: absolute; top: 14cm; left: 5.5cm;\">\n\t\tAuthorised Signatory</div>\n\t<div style=\"position: absolute; top: 14cm; left: 11cm;\">\n\t\tReceived Payment as Above</div>\n\t<div style=\"position: absolute; top: 16.4cm; left: 5.9cm;\">\n\t\t<strong>_____________</strong></div>\n\t<div style=\"position: absolute; top: 16.7cm; left: 6cm;\">\n\t\t<strong>A/C Payee</strong></div>\n\t<div style=\"position: absolute; top: 16.7cm; left: 5.9cm;\">\n\t\t<strong>_____________</strong></div>\n\t<div style=\"position: absolute; top: 16.9cm; left: 12cm;\">\n\t\t{{ frappe.utils.formatdate(doc.cheque_date) }}</div>\n\t<div style=\"position: absolute; top: 17.9cm; left: 1cm;\">\n\t\t{{ doc.pay_to_recd_from }}</div>\n\t<div style=\"position: absolute; top: 18.6cm; left: 1cm; width: 7cm;\">\n\t\t{{ doc.total_amount_in_words }}</div>\n\t<div style=\"position: absolute; top: 19.7cm; left: 12cm;\">\n\t\t{{ doc.total_amount }}</div>\n</div>",
"html": "<div style=\"position: relative\">\n\n\t{%- from \"templates/print_formats/standard_macros.html\" import add_header -%}\n<div class=\"page-break\">\n {%- if not doc.get(\"print_heading\") and not doc.get(\"select_print_heading\") \n and doc.set(\"select_print_heading\", _(\"Payment Advice\")) -%}{%- endif -%}\n {{ add_header(0, 1, doc, letter_head, no_letterhead) }}\n\n{%- for label, value in (\n (_(\"Voucher Date\"), frappe.utils.formatdate(doc.voucher_date)),\n (_(\"Reference / Cheque No.\"), doc.cheque_no),\n (_(\"Reference / Cheque Date\"), frappe.utils.formatdate(doc.cheque_date))\n ) -%}\n <div class=\"row\">\n <div class=\"col-xs-4\"><label class=\"text-right\">{{ label }}</label></div>\n <div class=\"col-xs-8\">{{ value }}</div>\n </div>\n{%- endfor -%}\n\t<hr>\n\t<p>{{ _(\"This amount is in full / part settlement of the listed bills\") }}:</p>\n{%- for label, value in (\n (_(\"Amount\"), \"<strong>\" + (doc.total_amount or \"\") + \"</strong><br>\" + (doc.total_amount_in_words or \"\") + \"<br>\"),\n (_(\"References\"), doc.remark)\n ) -%}\n <div class=\"row\">\n <div class=\"col-xs-4\"><label class=\"text-right\">{{ label }}</label></div>\n <div class=\"col-xs-8\">{{ value }}</div>\n </div>\n {%- endfor -%}\n <hr>\n\t<div style=\"position: absolute; top: 14cm; left: 0cm;\">\n\t\tPrepared By</div>\n\t<div style=\"position: absolute; top: 14cm; left: 5.5cm;\">\n\t\tAuthorised Signatory</div>\n\t<div style=\"position: absolute; top: 14cm; left: 11cm;\">\n\t\tReceived Payment as Above</div>\n\t<div style=\"position: absolute; top: 16.4cm; left: 5.9cm;\">\n\t\t<strong>_____________</strong></div>\n\t<div style=\"position: absolute; top: 16.7cm; left: 6cm;\">\n\t\t<strong>A/C Payee</strong></div>\n\t<div style=\"position: absolute; top: 16.7cm; left: 5.9cm;\">\n\t\t<strong>_____________</strong></div>\n\t<div style=\"position: absolute; top: 16.9cm; left: 12cm;\">\n\t\t{{ frappe.utils.formatdate(doc.cheque_date) }}</div>\n\t<div style=\"position: absolute; top: 17.9cm; left: 1cm;\">\n\t\t{{ doc.pay_to_recd_from }}</div>\n\t<div style=\"position: absolute; top: 18.6cm; left: 1cm; width: 7cm;\">\n\t\t{{ doc.total_amount_in_words }}</div>\n\t<div style=\"position: absolute; top: 19.7cm; left: 12cm;\">\n\t\t{{ doc.total_amount }}</div>\n</div>",
"idx": 1,
"modified": "2014-09-09 03:27:13.708596",
"modified": "2015-01-12 11:03:17.032512",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Cheque Printing Format",

View File

@@ -4,9 +4,9 @@
"doc_type": "Journal Voucher",
"docstatus": 0,
"doctype": "Print Format",
"html": "{%- from \"templates/print_formats/standard_macros.html\" import add_header -%}\n\n<div class=\"page-break\">\n {%- if not doc.get(\"print_heading\") and not doc.get(\"select_print_heading\") \n and doc.set(\"select_print_heading\", _(\"Credit Note\")) -%}{%- endif -%}\n {{ add_header(0, 1, doc, letter_head, no_letterhead) }}\n\n {%- for label, value in (\n (_(\"Credit To\"), doc.pay_to_recd_from),\n (_(\"Date\"), frappe.utils.formatdate(doc.voucher_date)),\n (_(\"Amount\"), \"<strong>\" + doc.total_amount + \"</strong><br>\" + (doc.total_amount_in_words or \"\") + \"<br>\"),\n (_(\"Remarks\"), doc.remark)\n ) -%}\n\n <div class=\"row\">\n <div class=\"col-sm-3\"><label class=\"text-right\">{{ label }}</label></div>\n <div class=\"col-sm-9\">{{ value }}</div>\n </div>\n\n {%- endfor -%}\n\n <hr>\n <br>\n <p class=\"strong\">\n {{ _(\"For\") }} {{ doc.company }},<br>\n <br>\n <br>\n <br>\n {{ _(\"Authorized Signatory\") }}\n </p>\n</div>\n\n\n",
"html": "{%- from \"templates/print_formats/standard_macros.html\" import add_header -%}\n\n<div class=\"page-break\">\n {%- if not doc.get(\"print_heading\") and not doc.get(\"select_print_heading\") \n and doc.set(\"select_print_heading\", _(\"Credit Note\")) -%}{%- endif -%}\n {{ add_header(0, 1, doc, letter_head, no_letterhead) }}\n\n {%- for label, value in (\n (_(\"Credit To\"), doc.pay_to_recd_from),\n (_(\"Date\"), frappe.utils.formatdate(doc.voucher_date)),\n (_(\"Amount\"), \"<strong>\" + frappe.utils.cstr(doc.total_amount) + \"</strong><br>\" + (doc.total_amount_in_words or \"\") + \"<br>\"),\n (_(\"Remarks\"), doc.remark)\n ) -%}\n\n <div class=\"row\">\n <div class=\"col-xs-3\"><label class=\"text-right\">{{ label }}</label></div>\n <div class=\"col-xs-9\">{{ value }}</div>\n </div>\n\n {%- endfor -%}\n\n <hr>\n <br>\n <p class=\"strong\">\n {{ _(\"For\") }} {{ doc.company }},<br>\n <br>\n <br>\n <br>\n {{ _(\"Authorized Signatory\") }}\n </p>\n</div>\n\n\n",
"idx": 2,
"modified": "2014-08-29 13:20:15.789533",
"modified": "2015-01-12 11:02:25.716825",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Credit Note",

View File

@@ -1,15 +1,15 @@
{
"creation": "2012-05-01 12:46:31",
"doc_type": "Journal Voucher",
"docstatus": 0,
"doctype": "Print Format",
"html": "{%- from \"templates/print_formats/standard_macros.html\" import add_header -%}\n<div class=\"page-break\">\n {%- if not doc.get(\"print_heading\") and not doc.get(\"select_print_heading\") \n and doc.set(\"select_print_heading\", _(\"Payment Receipt Note\")) -%}{%- endif -%}\n {{ add_header(0, 1, doc, letter_head, no_letterhead) }}\n\n {%- for label, value in (\n (_(\"Received On\"), frappe.utils.formatdate(doc.voucher_date)),\n (_(\"Received From\"), doc.pay_to_recd_from),\n (_(\"Amount\"), \"<strong>\" + doc.total_amount + \"</strong><br>\" + (doc.total_amount_in_words or \"\") + \"<br>\"),\n (_(\"Remarks\"), doc.remark)\n ) -%}\n <div class=\"row\">\n <div class=\"col-sm-3\"><label class=\"text-right\">{{ label }}</label></div>\n <div class=\"col-sm-9\">{{ value }}</div>\n </div>\n\n {%- endfor -%}\n\n <hr>\n <br>\n <p class=\"strong\">\n {{ _(\"For\") }} {{ doc.company }},<br>\n <br>\n <br>\n <br>\n {{ _(\"Authorized Signatory\") }}\n </p>\n</div>\n\n",
"idx": 1,
"modified": "2014-08-29 15:55:34.248384",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Receipt Voucher",
"owner": "Administrator",
"print_format_type": "Server",
"creation": "2012-05-01 12:46:31",
"doc_type": "Journal Voucher",
"docstatus": 0,
"doctype": "Print Format",
"html": "{%- from \"templates/print_formats/standard_macros.html\" import add_header -%}\n<div class=\"page-break\">\n {%- if not doc.get(\"print_heading\") and not doc.get(\"select_print_heading\") \n and doc.set(\"select_print_heading\", _(\"Payment Receipt Note\")) -%}{%- endif -%}\n {{ add_header(0, 1, doc, letter_head, no_letterhead) }}\n\n {%- for label, value in (\n (_(\"Received On\"), frappe.utils.formatdate(doc.voucher_date)),\n (_(\"Received From\"), doc.pay_to_recd_from),\n (_(\"Amount\"), \"<strong>\" + frappe.utils.cstr(doc.total_amount or 0) + \"</strong><br>\" + (doc.total_amount_in_words or \"\") + \"<br>\"),\n (_(\"Remarks\"), doc.remark)\n ) -%}\n <div class=\"row\">\n <div class=\"col-xs-3\"><label class=\"text-right\">{{ label }}</label></div>\n <div class=\"col-xs-9\">{{ value }}</div>\n </div>\n\n {%- endfor -%}\n\n <hr>\n <br>\n <p class=\"strong\">\n {{ _(\"For\") }} {{ doc.company }},<br>\n <br>\n <br>\n <br>\n {{ _(\"Authorized Signatory\") }}\n </p>\n</div>\n\n",
"idx": 1,
"modified": "2015-01-16 11:03:22.893209",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Payment Receipt Voucher",
"owner": "Administrator",
"print_format_type": "Server",
"standard": "Yes"
}
}

View File

@@ -3,9 +3,9 @@
"doc_type": "Sales Invoice",
"docstatus": 0,
"doctype": "Print Format",
"html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n<p class=\"text-center\">\n\t{{ doc.company }}<br>\n\t{{ doc.select_print_heading or _(\"Invoice\") }}<br>\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t<b>{{ _(\"Customer\") }}:</b> {{ doc.customer_name }}\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"60%\">{{ _(\"Item\") }}</b></th>\n\t\t\t<th width=\"10%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"30%\" class=\"text-right\">{{ _(\"Rate\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.entries -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}</td>\n\t\t\t<td class=\"text-right\">{{ item.amount }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ _(\"Net Total\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"net_total_export\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- for row in doc.other_charges -%}\n\t\t{%- if not row.included_in_print_rate -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ row.description }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t{%- endfor -%}\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total_export\") }}\n\t\t\t</td>\n\t\t</tr>\n\t</tbody>\n</table>\n{% if doc.get(\"other_charges\", filters={\"included_in_print_rate\": 1}) %}\n<hr>\n<p><b>Taxes Included:</b></p>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t{%- for row in doc.other_charges -%}\n\t\t{%- if row.included_in_print_rate -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ row.description }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t</td>\n\t\t<tr>\n\t\t{%- endif -%}\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n{%- endif -%}\n<hr>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
"html": "<style>\n\t.print-format table, .print-format tr, \n\t.print-format td, .print-format div, .print-format p {\n\t\tfont-family: Monospace;\n\t\tline-height: 200%;\n\t\tvertical-align: middle;\n\t}\n\t@media screen {\n\t\t.print-format {\n\t\t\twidth: 4in;\n\t\t\tpadding: 0.25in;\n\t\t\tmin-height: 8in;\n\t\t}\n\t}\n</style>\n\n<p class=\"text-center\">\n\t{{ doc.company }}<br>\n\t{{ doc.select_print_heading or _(\"Invoice\") }}<br>\n</p>\n<p>\n\t<b>{{ _(\"Receipt No\") }}:</b> {{ doc.name }}<br>\n\t<b>{{ _(\"Date\") }}:</b> {{ doc.get_formatted(\"posting_date\") }}<br>\n\t<b>{{ _(\"Customer\") }}:</b> {{ doc.customer_name }}\n</p>\n\n<hr>\n<table class=\"table table-condensed cart no-border\">\n\t<thead>\n\t\t<tr>\n\t\t\t<th width=\"60%\">{{ _(\"Item\") }}</b></th>\n\t\t\t<th width=\"10%\" class=\"text-right\">{{ _(\"Qty\") }}</th>\n\t\t\t<th width=\"30%\" class=\"text-right\">{{ _(\"Rate\") }}</th>\n\t\t</tr>\n\t</thead>\n\t<tbody>\n\t\t{%- for item in doc.entries -%}\n\t\t<tr>\n\t\t\t<td>\n\t\t\t\t{{ item.item_code }}\n\t\t\t\t{%- if item.item_name != item.item_code -%}\n\t\t\t\t\t<br>{{ item.item_name }}{%- endif -%}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">{{ item.qty }}</td>\n\t\t\t<td class=\"text-right\">{{ item.amount }}</td>\n\t\t</tr>\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ _(\"Net Total\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"net_total_export\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- for row in doc.other_charges -%}\n\t\t{%- if not row.included_in_print_rate -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ row.description }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ row.get_formatted(\"tax_amount\", doc) }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t{%- endfor -%}\n\t\t{%- if doc.discount_amount -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ _(\"Discount\") }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"discount_amount\") }}\n\t\t\t</td>\n\t\t</tr>\n\t\t{%- endif -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t<b>{{ _(\"Grand Total\") }}</b>\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ doc.get_formatted(\"grand_total_export\") }}\n\t\t\t</td>\n\t\t</tr>\n\t</tbody>\n</table>\n{% if doc.get(\"other_charges\", filters={\"included_in_print_rate\": 1}) %}\n<hr>\n<p><b>Taxes Included:</b></p>\n<table class=\"table table-condensed no-border\">\n\t<tbody>\n\t\t{%- for row in doc.other_charges -%}\n\t\t{%- if row.included_in_print_rate -%}\n\t\t<tr>\n\t\t\t<td class=\"text-right\" style=\"width: 70%\">\n\t\t\t\t{{ row.description }}\n\t\t\t</td>\n\t\t\t<td class=\"text-right\">\n\t\t\t\t{{ row.get_formatted(\"tax_amount_after_discount_amount\", doc) }}\n\t\t\t</td>\n\t\t<tr>\n\t\t{%- endif -%}\n\t\t{%- endfor -%}\n\t</tbody>\n</table>\n{%- endif -%}\n<hr>\n<p>{{ doc.terms or \"\" }}</p>\n<p class=\"text-center\">{{ _(\"Thank you, please visit again.\") }}</p>",
"idx": 1,
"modified": "2014-07-22 02:08:26.603223",
"modified": "2014-12-10 12:37:10.854370",
"modified_by": "Administrator",
"module": "Accounts",
"name": "POS Invoice",

View File

@@ -13,17 +13,17 @@ class AccountsReceivableReport(object):
self.age_as_on = getdate(nowdate()) \
if self.filters.report_date > getdate(nowdate()) \
else self.filters.report_date
def run(self):
customer_naming_by = frappe.db.get_value("Selling Settings", None, "cust_master_name")
return self.get_columns(customer_naming_by), self.get_data(customer_naming_by)
def get_columns(self, customer_naming_by):
columns = [
_("Posting Date") + ":Date:80", _("Account") + ":Link/Account:150",
_("Voucher Type") + "::110", _("Voucher No") + ":Dynamic Link/Voucher Type:120",
_("Due Date") + ":Date:80",
_("Invoiced Amount") + ":Currency:100", _("Payment Received") + ":Currency:100",
_("Due Date") + ":Date:80",
_("Invoiced Amount") + ":Currency:100", _("Payment Received") + ":Currency:100",
_("Outstanding Amount") + ":Currency:100", _("Age") + ":Int:50", "0-30:Currency:100",
"30-60:Currency:100", "60-90:Currency:100", _("90-Above") + ":Currency:100",
_("Customer") + ":Link/Customer:200"
@@ -69,27 +69,27 @@ class AccountsReceivableReport(object):
# returns a distinct list
return list(set([(e.voucher_type, e.voucher_no) for e in self.get_gl_entries()
if getdate(e.posting_date) > report_date]))
def get_entries_till(self, report_date):
# returns a generator
return (e for e in self.get_gl_entries()
return (e for e in self.get_gl_entries()
if getdate(e.posting_date) <= report_date)
def is_receivable(self, gle, future_vouchers):
return (
# advance
(not gle.against_voucher) or
(not gle.against_voucher) or
# against sales order
(gle.against_voucher_type == "Sales Order") or
# sales invoice
(gle.against_voucher==gle.voucher_no and gle.debit > 0) or
(gle.against_voucher==gle.voucher_no and gle.debit > 0) or
# entries adjusted with future vouchers
((gle.against_voucher_type, gle.against_voucher) in future_vouchers)
)
def get_outstanding_amount(self, gle, report_date):
payment_received = 0.0
for e in self.get_gl_entries_for(gle.account, gle.voucher_type, gle.voucher_no):
@@ -97,7 +97,7 @@ class AccountsReceivableReport(object):
payment_received += (flt(e.credit) - flt(e.debit))
return flt(gle.debit) - flt(gle.credit) - payment_received
def get_customer(self, account):
return self.get_account_map().get(account, {}).get("customer") or ""
@@ -106,25 +106,25 @@ class AccountsReceivableReport(object):
def get_territory(self, account):
return self.get_account_map().get(account, {}).get("territory") or ""
def get_account_map(self):
if not hasattr(self, "account_map"):
self.account_map = dict(((r.name, r) for r in frappe.db.sql("""select
self.account_map = dict(((r.name, r) for r in frappe.db.sql("""select
acc.name, cust.name as customer, cust.customer_name, cust.territory
from `tabAccount` acc left join `tabCustomer` cust
from `tabAccount` acc left join `tabCustomer` cust
on cust.name=acc.master_name where acc.master_type="Customer" """, as_dict=True)))
return self.account_map
def get_due_date(self, gle):
if not hasattr(self, "invoice_due_date_map"):
# TODO can be restricted to posting date
self.invoice_due_date_map = dict(frappe.db.sql("""select name, due_date
from `tabSales Invoice` where docstatus=1"""))
return gle.voucher_type == "Sales Invoice" \
and self.invoice_due_date_map.get(gle.voucher_no) or ""
def get_gl_entries(self):
if not hasattr(self, "gl_entries"):
conditions, values = self.prepare_conditions()
@@ -132,15 +132,15 @@ class AccountsReceivableReport(object):
where docstatus < 2 {0} order by posting_date, account""".format(conditions),
values, as_dict=True)
return self.gl_entries
def prepare_conditions(self):
conditions = [""]
values = {}
if self.filters.company:
conditions.append("company=%(company)s")
values["company"] = self.filters.company
if self.filters.account:
conditions.append("account=%(account)s")
values["account"] = self.filters.account
@@ -149,11 +149,11 @@ class AccountsReceivableReport(object):
if not account_map:
frappe.throw(_("No Customer Accounts found."))
else:
accounts_list = ['"{0}"'.format(ac) for ac in account_map]
accounts_list = ["'{0}'".format(frappe.db.escape(ac)) for ac in account_map]
conditions.append("account in ({0})".format(", ".join(accounts_list)))
return " and ".join(conditions), values
def get_gl_entries_for(self, account, against_voucher_type, against_voucher):
if not hasattr(self, "gl_entries_map"):
self.gl_entries_map = {}
@@ -163,7 +163,7 @@ class AccountsReceivableReport(object):
.setdefault(gle.against_voucher_type, {})\
.setdefault(gle.against_voucher, [])\
.append(gle)
return self.gl_entries_map.get(account, {})\
.get(against_voucher_type, {})\
.get(against_voucher, [])
@@ -176,15 +176,15 @@ def get_ageing_data(age_as_on, entry_date, outstanding_amount):
outstanding_range = [0.0, 0.0, 0.0, 0.0]
if not (age_as_on and entry_date):
return [0] + outstanding_range
age = (getdate(age_as_on) - getdate(entry_date)).days or 0
index = None
for i, days in enumerate([30, 60, 90]):
if age <= days:
index = i
break
if index is None: index = 3
outstanding_range[index] = outstanding_amount
return [age] + outstanding_range

View File

@@ -10,40 +10,40 @@ def execute(filters=None):
if not filters: filters = {}
columns = get_columns()
last_col = len(columns)
item_list = get_items(filters)
aii_account_map = get_aii_accounts()
if item_list:
item_tax, tax_accounts = get_tax_accounts(item_list, columns)
data = []
for d in item_list:
expense_account = d.expense_account or aii_account_map.get(d.company)
row = [d.item_code, d.item_name, d.item_group, d.parent, d.posting_date,
d.supplier_name, d.credit_to, d.project_name, d.company, d.purchase_order,
row = [d.item_code, d.item_name, d.item_group, d.parent, d.posting_date,
d.supplier_name, d.credit_to, d.project_name, d.company, d.purchase_order,
d.purchase_receipt, expense_account, d.qty, d.base_rate, d.base_amount]
for tax in tax_accounts:
row.append(item_tax.get(d.parent, {}).get(d.item_code, {}).get(tax, 0))
total_tax = sum(row[last_col:])
row += [total_tax, d.base_amount + total_tax]
data.append(row)
return columns, data
def get_columns():
return [_("Item Code") + ":Link/Item:120", _("Item Name") + "::120", _("Item Group") + ":Link/Item Group:100",
_("Invoice") + ":Link/Purchase Invoice:120", _("Posting Date") + ":Date:80", _("Supplier") + ":Link/Customer:120",
_("Supplier Account") + ":Link/Account:120", _("Project") + ":Link/Project:80", _("Company") + ":Link/Company:100",
_("Purchase Order") + ":Link/Purchase Order:100", _("Purchase Receipt") + ":Link/Purchase Receipt:100",
_("Expense Account") + ":Link/Account:140", _("Qty") + ":Float:120", _("Rate") + ":Currency:120",
return [_("Item Code") + ":Link/Item:120", _("Item Name") + "::120", _("Item Group") + ":Link/Item Group:100",
_("Invoice") + ":Link/Purchase Invoice:120", _("Posting Date") + ":Date:80", _("Supplier") + ":Link/Customer:120",
_("Supplier Account") + ":Link/Account:120", _("Project") + ":Link/Project:80", _("Company") + ":Link/Company:100",
_("Purchase Order") + ":Link/Purchase Order:100", _("Purchase Receipt") + ":Link/Purchase Receipt:100",
_("Expense Account") + ":Link/Account:140", _("Qty") + ":Float:120", _("Rate") + ":Currency:120",
_("Amount") + ":Currency:120"]
def get_conditions(filters):
conditions = ""
for opts in (("company", " and company=%(company)s"),
("account", " and pi.credit_to = %(account)s"),
("item_code", " and pi_item.item_code = %(item_code)s"),
@@ -53,48 +53,56 @@ def get_conditions(filters):
conditions += opts[1]
return conditions
def get_items(filters):
conditions = get_conditions(filters)
match_conditions = frappe.build_match_conditions("Purchase Invoice")
return frappe.db.sql("""select pi_item.parent, pi.posting_date, pi.credit_to, pi.company,
pi.supplier, pi.remarks, pi_item.item_code, pi_item.item_name, pi_item.item_group,
pi_item.project_name, pi_item.purchase_order, pi_item.purchase_receipt,
return frappe.db.sql("""select pi_item.parent, pi.posting_date, pi.credit_to, pi.company,
pi.supplier, pi.remarks, pi.net_total, pi_item.item_code, pi_item.item_name, pi_item.item_group,
pi_item.project_name, pi_item.purchase_order, pi_item.purchase_receipt,
pi_item.expense_account, pi_item.qty, pi_item.base_rate, pi_item.base_amount, pi.supplier_name
from `tabPurchase Invoice` pi, `tabPurchase Invoice Item` pi_item
from `tabPurchase Invoice` pi, `tabPurchase Invoice Item` pi_item
where pi.name = pi_item.parent and pi.docstatus = 1 %s %s
order by pi.posting_date desc, pi_item.item_code desc""" % (conditions, match_conditions), filters, as_dict=1)
def get_aii_accounts():
return dict(frappe.db.sql("select name, stock_received_but_not_billed from tabCompany"))
def get_tax_accounts(item_list, columns):
import json
item_tax = {}
tax_accounts = []
tax_details = frappe.db.sql("""select parent, account_head, item_wise_tax_detail
from `tabPurchase Taxes and Charges` where parenttype = 'Purchase Invoice'
and docstatus = 1 and ifnull(account_head, '') != '' and category in ('Total', 'Valuation and Total')
and parent in (%s)""" % ', '.join(['%s']*len(item_list)), tuple([item.parent for item in item_list]))
for parent, account_head, item_wise_tax_detail in tax_details:
invoice_wise_items = {}
for d in item_list:
invoice_wise_items.setdefault(d.parent, []).append(d)
tax_details = frappe.db.sql("""select parent, account_head, item_wise_tax_detail, charge_type, tax_amount
from `tabPurchase Taxes and Charges` where parenttype = 'Purchase Invoice'
and docstatus = 1 and ifnull(account_head, '') != '' and category in ('Total', 'Valuation and Total')
and parent in (%s)""" % ', '.join(['%s']*len(invoice_wise_items)), tuple(invoice_wise_items.keys()))
for parent, account_head, item_wise_tax_detail, charge_type, tax_amount in tax_details:
if account_head not in tax_accounts:
tax_accounts.append(account_head)
if item_wise_tax_detail:
try:
item_wise_tax_detail = json.loads(item_wise_tax_detail)
for item, tax_amount in item_wise_tax_detail.items():
item_tax.setdefault(parent, {}).setdefault(item, {})[account_head] = \
flt(tax_amount[1]) if isinstance(tax_amount, list) else flt(tax_amount)
except ValueError:
continue
elif charge_type == "Actual" and tax_amount:
for d in invoice_wise_items.get(parent, []):
item_tax.setdefault(parent, {}).setdefault(d.item_code, {})[account_head] = \
(tax_amount * d.base_amount) / d.net_total
tax_accounts.sort()
columns += [account_head + ":Currency:80" for account_head in tax_accounts]
columns += ["Total Tax:Currency:80", "Total:Currency:80"]
return item_tax, tax_accounts
return item_tax, tax_accounts

View File

@@ -14,36 +14,36 @@ def execute(filters=None):
item_list = get_items(filters)
if item_list:
item_tax, tax_accounts = get_tax_accounts(item_list, columns)
data = []
for d in item_list:
row = [d.item_code, d.item_name, d.item_group, d.parent, d.posting_date,
d.customer_name, d.debit_to, d.territory, d.project_name, d.company, d.sales_order,
row = [d.item_code, d.item_name, d.item_group, d.parent, d.posting_date,
d.customer_name, d.debit_to, d.territory, d.project_name, d.company, d.sales_order,
d.delivery_note, d.income_account, d.qty, d.base_rate, d.base_amount]
for tax in tax_accounts:
row.append(item_tax.get(d.parent, {}).get(d.item_code, {}).get(tax, 0))
total_tax = sum(row[last_col:])
row += [total_tax, d.base_amount + total_tax]
data.append(row)
return columns, data
def get_columns():
return [
_("Item Code") + ":Link/Item:120", _("Item Name") + "::120", _("Item Group") + ":Link/Item Group:100",
_("Invoice") + ":Link/Sales Invoice:120", _("Posting Date") + ":Date:80", _("Customer") + ":Link/Customer:120",
_("Item Code") + ":Link/Item:120", _("Item Name") + "::120", _("Item Group") + ":Link/Item Group:100",
_("Invoice") + ":Link/Sales Invoice:120", _("Posting Date") + ":Date:80", _("Customer") + ":Link/Customer:120",
_("Customer Account") + ":Link/Account:120", _("Territory") + ":Link/Territory:80",
_("Project") + ":Link/Project:80", _("Company") + ":Link/Company:100", _("Sales Order") + ":Link/Sales Order:100",
_("Delivery Note") + ":Link/Delivery Note:100", _("Income Account") + ":Link/Account:140",
_("Project") + ":Link/Project:80", _("Company") + ":Link/Company:100", _("Sales Order") + ":Link/Sales Order:100",
_("Delivery Note") + ":Link/Delivery Note:100", _("Income Account") + ":Link/Account:140",
_("Qty") + ":Float:120", _("Rate") + ":Currency:120", _("Amount") + ":Currency:120"
]
def get_conditions(filters):
conditions = ""
for opts in (("company", " and company=%(company)s"),
("account", " and si.debit_to = %(account)s"),
("item_code", " and si_item.item_code = %(item_code)s"),
@@ -53,32 +53,36 @@ def get_conditions(filters):
conditions += opts[1]
return conditions
def get_items(filters):
conditions = get_conditions(filters)
return frappe.db.sql("""select si_item.parent, si.posting_date, si.debit_to, si.project_name,
si.customer, si.remarks, si.territory, si.company, si_item.item_code, si_item.item_name,
si_item.item_group, si_item.sales_order, si_item.delivery_note, si_item.income_account,
return frappe.db.sql("""select si_item.parent, si.posting_date, si.debit_to, si.project_name,
si.customer, si.remarks, si.territory, si.company, si.net_total, si_item.item_code, si_item.item_name,
si_item.item_group, si_item.sales_order, si_item.delivery_note, si_item.income_account,
si_item.qty, si_item.base_rate, si_item.base_amount, si.customer_name
from `tabSales Invoice` si, `tabSales Invoice Item` si_item
where si.name = si_item.parent and si.docstatus = 1 %s
from `tabSales Invoice` si, `tabSales Invoice Item` si_item
where si.name = si_item.parent and si.docstatus = 1 %s
order by si.posting_date desc, si_item.item_code desc""" % conditions, filters, as_dict=1)
def get_tax_accounts(item_list, columns):
import json
item_tax = {}
tax_accounts = []
tax_details = frappe.db.sql("""select parent, account_head, item_wise_tax_detail
from `tabSales Taxes and Charges` where parenttype = 'Sales Invoice'
invoice_wise_items = {}
for d in item_list:
invoice_wise_items.setdefault(d.parent, []).append(d)
tax_details = frappe.db.sql("""select parent, account_head, item_wise_tax_detail, charge_type, tax_amount
from `tabSales Taxes and Charges` where parenttype = 'Sales Invoice'
and docstatus = 1 and ifnull(account_head, '') != ''
and parent in (%s)""" % ', '.join(['%s']*len(item_list)),
tuple([item.parent for item in item_list]))
for parent, account_head, item_wise_tax_detail in tax_details:
and parent in (%s)""" % ', '.join(['%s']*len(invoice_wise_items)),
tuple(invoice_wise_items.keys()))
for parent, account_head, item_wise_tax_detail, charge_type, tax_amount in tax_details:
if account_head not in tax_accounts:
tax_accounts.append(account_head)
if item_wise_tax_detail:
try:
item_wise_tax_detail = json.loads(item_wise_tax_detail)
@@ -87,9 +91,13 @@ def get_tax_accounts(item_list, columns):
flt(tax_amount[1]) if isinstance(tax_amount, list) else flt(tax_amount)
except ValueError:
continue
elif charge_type == "Actual" and tax_amount:
for d in invoice_wise_items.get(parent, []):
item_tax.setdefault(parent, {}).setdefault(d.item_code, {})[account_head] = \
flt((tax_amount * d.base_amount) / d.net_total)
tax_accounts.sort()
columns += [account_head + ":Currency:80" for account_head in tax_accounts]
columns += ["Total Tax:Currency:80", "Total:Currency:80"]
return item_tax, tax_accounts
return item_tax, tax_accounts

View File

@@ -28,7 +28,7 @@ def get_fiscal_years(date=None, fiscal_year=None, label="Date", verbose=1):
from `tabFiscal Year` where %s order by year_start_date desc""" % cond)
if not fy:
error_msg = _("""{0} {1} not in any Fiscal Year""").format(label, formatdate(date))
error_msg = _("""{0} {1} not in any Fiscal Year. For more details check {2}.""").format(label, formatdate(date), "https://erpnext.com/kb/accounts/fiscal-year-error")
if verbose: frappe.msgprint(error_msg)
raise FiscalYearError, error_msg

View File

@@ -71,7 +71,7 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
},
contact_person: function() {
this.supplier_address();
erpnext.utils.get_contact_details(this.frm);
},
buying_price_list: function() {
@@ -209,24 +209,17 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
calculate_totals: function() {
var tax_count = this.frm.tax_doclist.length;
this.frm.doc.grand_total = flt(tax_count ?
this.frm.tax_doclist[tax_count - 1].total : this.frm.doc.net_total,
precision("grand_total"));
this.frm.doc.grand_total_import = flt(this.frm.doc.grand_total /
this.frm.doc.conversion_rate, precision("grand_total_import"));
this.frm.doc.grand_total = flt(tax_count ? this.frm.tax_doclist[tax_count - 1].total : this.frm.doc.net_total);
this.frm.doc.total_tax = flt(this.frm.doc.grand_total - this.frm.doc.net_total,
precision("total_tax"));
this.frm.doc.total_tax = flt(this.frm.doc.grand_total - this.frm.doc.net_total, precision("total_tax"));
this.frm.doc.grand_total = flt(this.frm.doc.grand_total, precision("grand_total"));
// rounded totals
if(frappe.meta.get_docfield(this.frm.doc.doctype, "rounded_total", this.frm.doc.name)) {
this.frm.doc.rounded_total = Math.round(this.frm.doc.grand_total);
}
if(frappe.meta.get_docfield(this.frm.doc.doctype, "rounded_total_import", this.frm.doc.name)) {
this.frm.doc.rounded_total_import = Math.round(this.frm.doc.grand_total_import);
}
// other charges added/deducted
this.frm.doc.other_charges_added = 0.0
this.frm.doc.other_charges_deducted = 0.0
@@ -244,6 +237,16 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
frappe.model.round_floats_in(this.frm.doc,
["other_charges_added", "other_charges_deducted"]);
}
this.frm.doc.grand_total_import = flt((this.frm.doc.other_charges_added || this.frm.doc.other_charges_deducted) ?
flt(this.frm.doc.grand_total / this.frm.doc.conversion_rate) : this.frm.doc.net_total_import);
this.frm.doc.grand_total_import = flt(this.frm.doc.grand_total_import, precision("grand_total_import"));
if(frappe.meta.get_docfield(this.frm.doc.doctype, "rounded_total_import", this.frm.doc.name)) {
this.frm.doc.rounded_total_import = Math.round(this.frm.doc.grand_total_import);
}
this.frm.doc.other_charges_added_import = flt(this.frm.doc.other_charges_added /
this.frm.doc.conversion_rate, precision("other_charges_added_import"));
this.frm.doc.other_charges_deducted_import = flt(this.frm.doc.other_charges_deducted /

View File

@@ -3,15 +3,13 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import cstr, flt
from frappe.utils import flt
from frappe import _
from erpnext.stock.doctype.item.item import get_last_purchase_details
from erpnext.controllers.buying_controller import BuyingController
class PurchaseCommon(BuyingController):
def update_last_purchase_rate(self, obj, is_submit):
"""updates last_purchase_rate in item table for each item"""
@@ -123,27 +121,6 @@ class PurchaseCommon(BuyingController):
else:
chk_dupl_itm.append(f)
def get_qty(self, curr_doctype, ref_tab_fname, ref_tab_dn, ref_doc_tname, transaction, curr_parent_name):
# Get total Quantities of current doctype (eg. PR) except for qty of this transaction
#------------------------------
# please check as UOM changes from Material Request - Purchase Order ,so doing following else uom should be same .
# i.e. in PO uom is NOS then in PR uom should be NOS
# but if in Material Request uom KG it can change in PO
get_qty = (transaction == 'Material Request - Purchase Order') and 'qty * conversion_factor' or 'qty'
qty = frappe.db.sql("""select sum(%s) from `tab%s` where %s = %s and
docstatus = 1 and parent != %s""" % (get_qty, curr_doctype, ref_tab_fname, '%s', '%s'),
(ref_tab_dn, curr_parent_name))
qty = qty and flt(qty[0][0]) or 0
# get total qty of ref doctype
#--------------------
max_qty = frappe.db.sql("""select qty from `tab%s` where name = %s
and docstatus = 1""" % (ref_doc_tname, '%s'), ref_tab_dn)
max_qty = max_qty and flt(max_qty[0][0]) or 0
return cstr(qty)+'~~~'+cstr(max_qty)
def check_for_stopped_status(self, doctype, docname):
stopped = frappe.db.sql("""select name from `tab%s` where name = %s and
status = 'Stopped'""" % (doctype, '%s'), docname)

View File

@@ -685,7 +685,8 @@
"label": "Recurring Type",
"no_copy": 1,
"options": "Monthly\nQuarterly\nHalf-yearly\nYearly",
"permlevel": 0
"permlevel": 0,
"print_hide": 1
},
{
"allow_on_submit": 1,
@@ -695,7 +696,8 @@
"fieldtype": "Date",
"label": "From Date",
"no_copy": 1,
"permlevel": 0
"permlevel": 0,
"print_hide": 1
},
{
"allow_on_submit": 1,
@@ -705,7 +707,8 @@
"fieldtype": "Date",
"label": "To Date",
"no_copy": 1,
"permlevel": 0
"permlevel": 0,
"print_hide": 1
},
{
"allow_on_submit": 1,
@@ -772,7 +775,7 @@
"icon": "icon-file-text",
"idx": 1,
"is_submittable": 1,
"modified": "2014-10-08 14:23:29.718779",
"modified": "2014-11-27 17:27:38.839440",
"modified_by": "Administrator",
"module": "Buying",
"name": "Purchase Order",

View File

@@ -96,50 +96,45 @@ class PurchaseOrder(BuyingController):
check_list.append(d.prevdoc_docname)
pc_obj.check_for_stopped_status( d.prevdoc_doctype, d.prevdoc_docname)
def update_requested_qty(self):
material_request_map = {}
for d in self.get("po_details"):
if d.prevdoc_doctype and d.prevdoc_doctype == "Material Request" and d.prevdoc_detail_docname:
material_request_map.setdefault(d.prevdoc_docname, []).append(d.prevdoc_detail_docname)
def update_bin(self, is_submit, is_stopped = 0):
from erpnext.stock.utils import update_bin
pc_obj = frappe.get_doc('Purchase Common')
for d in self.get('po_details'):
#1. Check if is_stock_item == 'Yes'
if frappe.db.get_value("Item", d.item_code, "is_stock_item") == "Yes":
# this happens when item is changed from non-stock to stock item
if not d.warehouse:
continue
for mr, mr_item_rows in material_request_map.items():
if mr and mr_item_rows:
mr_obj = frappe.get_doc("Material Request", mr)
ind_qty, po_qty = 0, flt(d.qty) * flt(d.conversion_factor)
if is_stopped:
po_qty = flt(d.qty) > flt(d.received_qty) and \
flt( flt(flt(d.qty) - flt(d.received_qty))*flt(d.conversion_factor)) or 0
if mr_obj.status in ["Stopped", "Cancelled"]:
frappe.throw(_("Material Request {0} is cancelled or stopped").format(mr), frappe.InvalidStatusError)
# No updates in Material Request on Stop / Unstop
if cstr(d.prevdoc_doctype) == 'Material Request' and not is_stopped:
# get qty and pending_qty of prevdoc
curr_ref_qty = pc_obj.get_qty(d.doctype, 'prevdoc_detail_docname',
d.prevdoc_detail_docname, 'Material Request Item',
'Material Request - Purchase Order', self.name)
max_qty, qty, curr_qty = flt(curr_ref_qty.split('~~~')[1]), \
flt(curr_ref_qty.split('~~~')[0]), 0
mr_obj.update_requested_qty(mr_item_rows)
if flt(qty) + flt(po_qty) > flt(max_qty):
curr_qty = flt(max_qty) - flt(qty)
# special case as there is no restriction
# for Material Request - Purchase Order
curr_qty = curr_qty > 0 and curr_qty or 0
else:
curr_qty = flt(po_qty)
def update_ordered_qty(self, po_item_rows=None):
"""update requested qty (before ordered_qty is updated)"""
from erpnext.stock.utils import get_bin
ind_qty = -flt(curr_qty)
def _update_ordered_qty(item_code, warehouse):
ordered_qty = frappe.db.sql("""
select sum((po_item.qty - ifnull(po_item.received_qty, 0))*po_item.conversion_factor)
from `tabPurchase Order Item` po_item, `tabPurchase Order` po
where po_item.item_code=%s and po_item.warehouse=%s
and po_item.qty > ifnull(po_item.received_qty, 0) and po_item.parent=po.name
and po.status!='Stopped' and po.docstatus=1""", (item_code, warehouse))
# Update ordered_qty and indented_qty in bin
args = {
"item_code": d.item_code,
"warehouse": d.warehouse,
"ordered_qty": (is_submit and 1 or -1) * flt(po_qty),
"indented_qty": (is_submit and 1 or -1) * flt(ind_qty),
"posting_date": self.transaction_date
}
update_bin(args)
bin_doc = get_bin(item_code, warehouse)
bin_doc.ordered_qty = flt(ordered_qty[0][0]) if ordered_qty else 0
bin_doc.save()
item_wh_list = []
for d in self.get("po_details"):
if (not po_item_rows or d.name in po_item_rows) and [d.item_code, d.warehouse] not in item_wh_list \
and frappe.db.get_value("Item", d.item_code, "is_stock_item") == "Yes" and d.warehouse:
item_wh_list.append([d.item_code, d.warehouse])
for item_code, warehouse in item_wh_list:
_update_ordered_qty(item_code, warehouse)
def check_modified_date(self):
mod_db = frappe.db.sql("select modified from `tabPurchase Order` where name = %s",
@@ -152,13 +147,11 @@ class PurchaseOrder(BuyingController):
def update_status(self, status):
self.check_modified_date()
# step 1:=> Set Status
frappe.db.set(self,'status',cstr(status))
# step 2:=> Update Bin
self.update_bin(is_submit = (status == 'Submitted') and 1 or 0, is_stopped = 1)
self.update_requested_qty()
self.update_ordered_qty()
# step 3:=> Acknowledge user
msgprint(_("Status of {0} {1} is now {2}").format(self.doctype, self.name, status))
def on_submit(self):
@@ -167,7 +160,8 @@ class PurchaseOrder(BuyingController):
purchase_controller = frappe.get_doc("Purchase Common")
self.update_prevdoc_status()
self.update_bin(is_submit = 1, is_stopped = 0)
self.update_requested_qty()
self.update_ordered_qty()
frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype,
self.company, self.grand_total)
@@ -192,8 +186,13 @@ class PurchaseOrder(BuyingController):
throw(_("Purchase Invoice {0} is already submitted").format(", ".join(submitted)))
frappe.db.set(self,'status','Cancelled')
self.update_prevdoc_status()
self.update_bin( is_submit = 0, is_stopped = 0)
# Must be called after updating ordered qty in Material Request
self.update_requested_qty()
self.update_ordered_qty()
pc_obj.update_last_purchase_rate(self, is_submit = 0)
def on_update(self):
@@ -248,7 +247,7 @@ def make_purchase_invoice(source_name, target_doc=None):
def update_item(obj, target, source_parent):
target.amount = flt(obj.amount) - flt(obj.billed_amt)
target.base_amount = target.amount * flt(source_parent.conversion_rate)
target.qty = target.amount / flt(obj.rate) if flt(obj.rate) else flt(obj.qty)
target.qty = target.amount / flt(obj.rate) if (flt(obj.rate) and flt(obj.billed_amt)) else flt(obj.qty)
doc = get_mapped_doc("Purchase Order", source_name, {
"Purchase Order": {

View File

@@ -29,8 +29,7 @@ class TestPurchaseOrder(unittest.TestCase):
frappe.get_doc(pr).insert()
def test_ordered_qty(self):
frappe.db.sql("delete from tabBin")
existing_ordered_qty = self._get_ordered_qty("_Test Item", "_Test Warehouse - _TC")
from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt
po = frappe.copy_doc(test_records[0]).insert()
@@ -43,8 +42,7 @@ class TestPurchaseOrder(unittest.TestCase):
po.get("po_details")[0].item_code = "_Test Item"
po.submit()
self.assertEquals(frappe.db.get_value("Bin", {"item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC"}, "ordered_qty"), 10)
self.assertEquals(self._get_ordered_qty("_Test Item", "_Test Warehouse - _TC"), existing_ordered_qty + 10)
pr = make_purchase_receipt(po.name)
@@ -56,8 +54,9 @@ class TestPurchaseOrder(unittest.TestCase):
pr.insert()
pr.submit()
self.assertEquals(flt(frappe.db.get_value("Bin", {"item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC"}, "ordered_qty")), 6.0)
po.load_from_db()
self.assertEquals(po.get("po_details")[0].received_qty, 4)
self.assertEquals(self._get_ordered_qty("_Test Item", "_Test Warehouse - _TC"), existing_ordered_qty + 6)
frappe.db.set_value('Item', '_Test Item', 'tolerance', 50)
@@ -68,8 +67,16 @@ class TestPurchaseOrder(unittest.TestCase):
pr1.insert()
pr1.submit()
self.assertEquals(flt(frappe.db.get_value("Bin", {"item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC"}, "ordered_qty")), 0.0)
po.load_from_db()
self.assertEquals(po.get("po_details")[0].received_qty, 12)
self.assertEquals(self._get_ordered_qty("_Test Item", "_Test Warehouse - _TC"), existing_ordered_qty)
pr1.load_from_db()
pr1.cancel()
po.load_from_db()
self.assertEquals(po.get("po_details")[0].received_qty, 4)
self.assertEquals(self._get_ordered_qty("_Test Item", "_Test Warehouse - _TC"), existing_ordered_qty + 6)
def test_make_purchase_invoice(self):
from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_invoice
@@ -111,6 +118,9 @@ class TestPurchaseOrder(unittest.TestCase):
from erpnext.controllers.tests.test_recurring_document import test_recurring_document
test_recurring_document(self, test_records)
def _get_ordered_qty(self, item_code, warehouse):
return flt(frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, "ordered_qty"))
test_dependencies = ["BOM", "Item Price"]

View File

@@ -1,8 +1,6 @@
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
{% include 'setup/doctype/contact_control/contact_control.js' %};
cur_frm.cscript.refresh = function(doc, dt, dn) {
cur_frm.cscript.make_dashboard(doc);
@@ -17,15 +15,13 @@ cur_frm.cscript.refresh = function(doc, dt, dn) {
}
else{
unhide_field(['address_html','contact_html']);
// make lists
cur_frm.cscript.make_address(doc,dt,dn);
cur_frm.cscript.make_contact(doc,dt,dn);
erpnext.utils.render_address_and_contact(cur_frm)
cur_frm.communication_view = new frappe.views.CommunicationList({
list: frappe.get_list("Communication", {"supplier": doc.name}),
parent: cur_frm.fields_dict.communication_html.wrapper,
doc: doc
})
});
}
}
@@ -61,45 +57,6 @@ cur_frm.cscript.make_dashboard = function(doc) {
})
}
cur_frm.cscript.make_address = function() {
if(!cur_frm.address_list) {
cur_frm.address_list = new frappe.ui.Listing({
parent: cur_frm.fields_dict['address_html'].wrapper,
page_length: 5,
new_doctype: "Address",
get_query: function() {
return "select name, address_type, address_line1, address_line2, city, state, country, pincode, fax, email_id, phone, is_primary_address, is_shipping_address from tabAddress where supplier='" +
cur_frm.doc.name.replace(/'/g, "\\'") + "' and docstatus != 2 order by is_primary_address desc"
},
as_dict: 1,
no_results_message: __('No addresses created'),
render_row: cur_frm.cscript.render_address_row,
});
// note: render_address_row is defined in contact_control.js
}
cur_frm.address_list.run();
}
cur_frm.cscript.make_contact = function() {
if(!cur_frm.contact_list) {
cur_frm.contact_list = new frappe.ui.Listing({
parent: cur_frm.fields_dict['contact_html'].wrapper,
page_length: 5,
new_doctype: "Contact",
get_query: function() {
return "select name, first_name, last_name, email_id, phone, mobile_no, department, designation, is_primary_contact from tabContact where supplier='" +
cur_frm.doc.name.replace(/'/g, "\\'") + "' and docstatus != 2 order by is_primary_contact desc"
},
as_dict: 1,
no_results_message: __('No contacts created'),
render_row: cur_frm.cscript.render_contact_row,
});
// note: render_contact_row is defined in contact_control.js
}
cur_frm.contact_list.run();
}
cur_frm.fields_dict['default_price_list'].get_query = function(doc, cdt, cdn) {
return{
filters:{'buying': 1}

View File

@@ -9,10 +9,14 @@ from frappe.utils import cint
from frappe import msgprint, _
from frappe.model.naming import make_autoname
from erpnext.accounts.party import create_party_account
from erpnext.utilities.address_and_contact import load_address_and_contact
from erpnext.utilities.transaction_base import TransactionBase
class Supplier(TransactionBase):
def onload(self):
"""Load address and contacts in `__onload`"""
load_address_and_contact(self, "supplier")
def autoname(self):
supp_master_name = frappe.defaults.get_global_default('supp_master_name')

View File

@@ -119,6 +119,10 @@ class AccountsController(TransactionBase):
item.get(fieldname) is None and value is not None:
item.set(fieldname, value)
if fieldname == "cost_center" and item.meta.get_field("cost_center") \
and not item.get("cost_center") and value is not None:
item.set(fieldname, value)
if ret.get("pricing_rule"):
for field in ["base_price_list_rate", "price_list_rate",
"discount_percentage", "base_rate", "rate"]:
@@ -291,7 +295,7 @@ class AccountsController(TransactionBase):
self.precision("tax_amount", tax))
def adjust_discount_amount_loss(self, tax):
discount_amount_loss = self.grand_total - flt(self.discount_amount) - tax.total
discount_amount_loss = self.grand_total - flt(self.base_discount_amount) - tax.total
tax.tax_amount_after_discount_amount = flt(tax.tax_amount_after_discount_amount +
discount_amount_loss, self.precision("tax_amount", tax))
tax.total = flt(tax.total + discount_amount_loss, self.precision("total", tax))
@@ -437,7 +441,7 @@ class AccountsController(TransactionBase):
for order, jv_list in order_jv_map.items():
for jv in jv_list:
if not advance_jv_against_si or jv not in advance_jv_against_si:
frappe.throw(_("Journal Voucher {0} is linked against Order {1}, hence it must be fetched as advance in Invoice as well.")
frappe.msgprint(_("Journal Voucher {0} is linked against Order {1}, check if it should be pulled as advance in this invoice.")
.format(jv, order))
@@ -467,7 +471,7 @@ class AccountsController(TransactionBase):
max_allowed_amt = flt(ref_amt * (100 + tolerance) / 100)
if total_billed_amt - max_allowed_amt > 0.01:
frappe.throw(_("Cannot overbill for Item {0} in row {0} more than {1}. To allow overbilling, please set in Stock Settings").format(item.item_code, item.idx, max_allowed_amt))
frappe.throw(_("Cannot overbill for Item {0} in row {1} more than {2}. To allow overbilling, please set in Stock Settings").format(item.item_code, item.idx, max_allowed_amt))
def get_company_default(self, fieldname):
from erpnext.accounts.utils import get_company_default

View File

@@ -91,8 +91,7 @@ class BuyingController(StockController):
item.rate = flt(item.price_list_rate * (1.0 - (item.discount_percentage / 100.0)),
self.precision("rate", item))
item.amount = flt(item.rate * item.qty,
self.precision("amount", item))
item.amount = flt(item.rate * item.qty, self.precision("amount", item))
item.item_tax_amount = 0.0;
self._set_in_company_currency(item, "amount", "base_amount")
@@ -110,20 +109,15 @@ class BuyingController(StockController):
self.round_floats_in(self, ["net_total", "net_total_import"])
def calculate_totals(self):
self.grand_total = flt(self.tax_doclist[-1].total if self.tax_doclist
else self.net_total, self.precision("grand_total"))
self.grand_total_import = flt(self.grand_total / self.conversion_rate,
self.precision("grand_total_import"))
self.grand_total = flt(self.tax_doclist[-1].total if self.tax_doclist else self.net_total)
self.total_tax = flt(self.grand_total - self.net_total,
self.precision("total_tax"))
self.total_tax = flt(self.grand_total - self.net_total, self.precision("total_tax"))
self.grand_total = flt(self.grand_total, self.precision("grand_total"))
if self.meta.get_field("rounded_total"):
self.rounded_total = rounded(self.grand_total)
if self.meta.get_field("rounded_total_import"):
self.rounded_total_import = rounded(self.grand_total_import)
if self.meta.get_field("other_charges_added"):
self.other_charges_added = flt(sum([flt(d.tax_amount) for d in self.tax_doclist
if d.add_deduct_tax=="Add" and d.category in ["Valuation and Total", "Total"]]),
@@ -134,6 +128,14 @@ class BuyingController(StockController):
if d.add_deduct_tax=="Deduct" and d.category in ["Valuation and Total", "Total"]]),
self.precision("other_charges_deducted"))
self.grand_total_import = flt(self.grand_total / self.conversion_rate) \
if (self.other_charges_added or self.other_charges_deducted) else self.net_total_import
self.grand_total_import = flt(self.grand_total_import, self.precision("grand_total_import"))
if self.meta.get_field("rounded_total_import"):
self.rounded_total_import = rounded(self.grand_total_import)
if self.meta.get_field("other_charges_added_import"):
self.other_charges_added_import = flt(self.other_charges_added /
self.conversion_rate, self.precision("other_charges_added_import"))
@@ -269,7 +271,7 @@ class BuyingController(StockController):
# get raw materials rate
if self.doctype == "Purchase Receipt":
from erpnext.stock.utils import get_incoming_rate
item_rate = get_incoming_rate({
rm.rate = get_incoming_rate({
"item_code": bom_item.item_code,
"warehouse": self.supplier_warehouse,
"posting_date": self.posting_date,
@@ -277,10 +279,9 @@ class BuyingController(StockController):
"qty": -1 * required_qty,
"serial_no": rm.serial_no
})
if not item_rate:
from erpnext.controllers.stock_controller import get_valuation_rate
item_rate = get_valuation_rate(bom_item.item_code, self.supplier_warehouse)
rm.rate = item_rate or bom_item.rate
if not rm.rate:
from erpnext.stock.stock_ledger import get_valuation_rate
rm.rate = get_valuation_rate(bom_item.item_code, self.supplier_warehouse)
else:
rm.rate = bom_item.rate

View File

@@ -124,10 +124,7 @@ def send_notification(new_rv):
frappe.sendmail(new_rv.notification_email_address,
subject= _("New {0}: #{1}").format(new_rv.doctype, new_rv.name),
message = _("Please find attached {0} #{1}").format(new_rv.doctype, new_rv.name),
attachments = [{
"fname": new_rv.name + ".pdf",
"fcontent": frappe.get_print_format(new_rv.doctype, new_rv.name, as_pdf=True)
}])
attachments = [frappe.attach_print(new_rv.doctype, new_rv.name, file_name=new_rv.name)])
def notify_errors(doc, doctype, party, owner):
from frappe.utils.user import get_system_managers

View File

@@ -216,33 +216,38 @@ class SellingController(StockController):
self.round_floats_in(self, ["net_total", "net_total_export"])
def calculate_totals(self):
self.grand_total = flt(self.tax_doclist and \
self.tax_doclist[-1].total or self.net_total, self.precision("grand_total"))
self.grand_total_export = flt(self.grand_total / self.conversion_rate,
self.precision("grand_total_export"))
self.grand_total = flt(self.tax_doclist[-1].total if self.tax_doclist else self.net_total)
self.other_charges_total = flt(self.grand_total - self.net_total,
self.precision("other_charges_total"))
self.other_charges_total = flt(self.grand_total - self.net_total, self.precision("other_charges_total"))
self.other_charges_total_export = flt(self.grand_total_export -
self.net_total_export + flt(self.discount_amount),
self.precision("other_charges_total_export"))
self.grand_total_export = flt(self.grand_total / self.conversion_rate) \
if (self.other_charges_total or self.discount_amount) else self.net_total_export
self.other_charges_total_export = flt(self.grand_total_export - self.net_total_export +
flt(self.discount_amount), self.precision("other_charges_total_export"))
self.grand_total = flt(self.grand_total, self.precision("grand_total"))
self.grand_total_export = flt(self.grand_total_export, self.precision("grand_total_export"))
self.rounded_total = rounded(self.grand_total)
self.rounded_total_export = rounded(self.grand_total_export)
def apply_discount_amount(self):
if self.discount_amount:
self.base_discount_amount = flt(self.discount_amount * self.conversion_rate, self.precision("base_discount_amount"))
grand_total_for_discount_amount = self.get_grand_total_for_discount_amount()
if grand_total_for_discount_amount:
# calculate item amount after Discount Amount
for item in self.item_doclist:
distributed_amount = flt(self.discount_amount) * item.base_amount / grand_total_for_discount_amount
distributed_amount = flt(self.base_discount_amount) * item.base_amount / grand_total_for_discount_amount
item.base_amount = flt(item.base_amount - distributed_amount, self.precision("base_amount", item))
self.discount_amount_applied = True
self._calculate_taxes_and_totals()
else:
self.base_discount_amount = 0
def get_grand_total_for_discount_amount(self):
actual_taxes_dict = {}

View File

@@ -11,7 +11,7 @@ from erpnext.controllers.accounts_controller import AccountsController
from erpnext.accounts.general_ledger import make_gl_entries, delete_gl_entries, process_gl_map
class StockController(AccountsController):
def make_gl_entries(self, repost_future_gle=True, allow_negative_stock=False):
def make_gl_entries(self, repost_future_gle=True):
if self.docstatus == 2:
delete_gl_entries(voucher_type=self.doctype, voucher_no=self.name)
@@ -19,18 +19,16 @@ class StockController(AccountsController):
warehouse_account = get_warehouse_account()
if self.docstatus==1:
gl_entries = self.get_gl_entries(warehouse_account, allow_negative_stock=allow_negative_stock)
gl_entries = self.get_gl_entries(warehouse_account)
make_gl_entries(gl_entries)
if repost_future_gle:
items, warehouses = self.get_items_and_warehouses()
update_gl_entries_after(self.posting_date, self.posting_time, warehouses, items,
warehouse_account, allow_negative_stock)
warehouse_account)
def get_gl_entries(self, warehouse_account=None, default_expense_account=None,
default_cost_center=None, allow_negative_stock=False):
# block_negative_stock(allow_negative_stock)
default_cost_center=None):
if not warehouse_account:
warehouse_account = get_warehouse_account()
@@ -49,17 +47,12 @@ class StockController(AccountsController):
self.check_expense_account(detail)
stock_value_difference = flt(sle.stock_value_difference, 2)
if not stock_value_difference:
valuation_rate = get_valuation_rate(sle.item_code, sle.warehouse)
stock_value_difference = flt(sle.actual_qty)*flt(valuation_rate)
gl_list.append(self.get_gl_dict({
"account": warehouse_account[sle.warehouse],
"against": detail.expense_account,
"cost_center": detail.cost_center,
"remarks": self.get("remarks") or "Accounting Entry for Stock",
"debit": stock_value_difference
"debit": flt(sle.stock_value_difference, 2)
}))
# to target warehouse / expense account
@@ -68,7 +61,7 @@ class StockController(AccountsController):
"against": warehouse_account[sle.warehouse],
"cost_center": detail.cost_center,
"remarks": self.get("remarks") or "Accounting Entry for Stock",
"credit": stock_value_difference
"credit": flt(sle.stock_value_difference, 2)
}))
elif sle.warehouse not in warehouse_with_no_account:
warehouse_with_no_account.append(sle.warehouse)
@@ -174,7 +167,7 @@ class StockController(AccountsController):
else:
is_expense_account = frappe.db.get_value("Account",
item.get("expense_account"), "report_type")=="Profit and Loss"
if self.doctype not in ("Purchase Receipt", "Stock Reconciliation") and not is_expense_account:
if self.doctype not in ("Purchase Receipt", "Stock Reconciliation", "Stock Entry") and not is_expense_account:
frappe.throw(_("Expense / Difference account ({0}) must be a 'Profit or Loss' account")
.format(item.get("expense_account")))
if is_expense_account and not item.get("cost_center"):
@@ -182,7 +175,7 @@ class StockController(AccountsController):
_(self.doctype), self.name, item.get("item_code")))
def get_sl_entries(self, d, args):
sl_dict = {
sl_dict = frappe._dict({
"item_code": d.get("item_code", None),
"warehouse": d.get("warehouse", None),
"posting_date": self.posting_date,
@@ -199,14 +192,14 @@ class StockController(AccountsController):
"serial_no": d.get("serial_no"),
"project": d.get("project_name"),
"is_cancelled": self.docstatus==2 and "Yes" or "No"
}
})
sl_dict.update(args)
return sl_dict
def make_sl_entries(self, sl_entries, is_amended=None):
def make_sl_entries(self, sl_entries, is_amended=None, allow_negative_stock=False):
from erpnext.stock.stock_ledger import make_sl_entries
make_sl_entries(sl_entries, is_amended)
make_sl_entries(sl_entries, is_amended, allow_negative_stock)
def make_gl_entries_on_cancel(self):
if frappe.db.sql("""select name from `tabGL Entry` where voucher_type=%s
@@ -224,7 +217,7 @@ class StockController(AccountsController):
return serialized_items
def update_gl_entries_after(posting_date, posting_time, for_warehouses=None, for_items=None,
warehouse_account=None, allow_negative_stock=False):
warehouse_account=None):
def _delete_gl_entries(voucher_type, voucher_no):
frappe.db.sql("""delete from `tabGL Entry`
where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
@@ -238,12 +231,12 @@ def update_gl_entries_after(posting_date, posting_time, for_warehouses=None, for
for voucher_type, voucher_no in future_stock_vouchers:
existing_gle = gle.get((voucher_type, voucher_no), [])
voucher_obj = frappe.get_doc(voucher_type, voucher_no)
expected_gle = voucher_obj.get_gl_entries(warehouse_account, allow_negative_stock=allow_negative_stock)
expected_gle = voucher_obj.get_gl_entries(warehouse_account)
if expected_gle:
if not existing_gle or not compare_existing_and_expected_gle(existing_gle,
expected_gle):
_delete_gl_entries(voucher_type, voucher_no)
voucher_obj.make_gl_entries(repost_future_gle=False, allow_negative_stock=allow_negative_stock)
voucher_obj.make_gl_entries(repost_future_gle=False)
else:
_delete_gl_entries(voucher_type, voucher_no)
@@ -252,7 +245,7 @@ def compare_existing_and_expected_gle(existing_gle, expected_gle):
for entry in expected_gle:
for e in existing_gle:
if entry.account==e.account and entry.against_account==e.against_account \
and entry.cost_center==e.cost_center \
and (not entry.cost_center or not e.cost_center or entry.cost_center==e.cost_center) \
and (entry.debit != e.debit or entry.credit != e.credit):
matched = False
break
@@ -295,31 +288,3 @@ def get_warehouse_account():
warehouse_account = dict(frappe.db.sql("""select master_name, name from tabAccount
where account_type = 'Warehouse' and ifnull(master_name, '') != ''"""))
return warehouse_account
def block_negative_stock(allow_negative_stock=False):
if cint(frappe.defaults.get_global_default("auto_accounting_for_stock")) and not allow_negative_stock:
if cint(frappe.db.get_value("Stock Settings", None, "allow_negative_stock")):
frappe.throw(_("Negative stock is not allowed in case of Perpetual Inventory, please disable it from Stock Settings"))
def get_valuation_rate(item_code, warehouse):
last_valuation_rate = frappe.db.sql("""select valuation_rate
from `tabStock Ledger Entry`
where item_code = %s and warehouse = %s
and ifnull(valuation_rate, 0) > 0
order by posting_date desc, posting_time desc, name desc limit 1""", (item_code, warehouse))
if not last_valuation_rate:
last_valuation_rate = frappe.db.sql("""select valuation_rate
from `tabStock Ledger Entry`
where item_code = %s and ifnull(valuation_rate, 0) > 0
order by posting_date desc, posting_time desc, name desc limit 1""", item_code)
valuation_rate = flt(last_valuation_rate[0][0]) if last_valuation_rate else 0
if not valuation_rate:
valuation_rate = frappe.db.get_value("Item Price", {"item_code": item_code, "buying": 1}, "price_list_rate")
if not valuation_rate:
frappe.throw(_("Purchase rate for item: {0} not found, which is required to book accounting entry. Please mention item price against a buying price list.").format(item_code))
return valuation_rate

View File

@@ -4,7 +4,7 @@ app_publisher = "Web Notes Technologies Pvt. Ltd. and Contributors"
app_description = "Open Source Enterprise Resource Planning for Small and Midsized Organizations"
app_icon = "icon-th"
app_color = "#e74c3c"
app_version = "4.6.2"
app_version = "4.21.4"
error_report_email = "support@erpnext.com"
@@ -47,8 +47,8 @@ doc_events = {
"on_update": "erpnext.home.make_comment_feed"
},
"Stock Entry": {
"on_submit": "erpnext.stock.doctype.material_request.material_request.update_completed_qty",
"on_cancel": "erpnext.stock.doctype.material_request.material_request.update_completed_qty"
"on_submit": "erpnext.stock.doctype.material_request.material_request.update_completed_and_requested_qty",
"on_cancel": "erpnext.stock.doctype.material_request.material_request.update_completed_and_requested_qty"
},
"User": {
"validate": "erpnext.hr.doctype.employee.employee.validate_employee_role",

View File

@@ -1,9 +1,21 @@
{
"autoname": "EXP.######",
"autoname": "naming_series:",
"creation": "2013-01-10 16:34:14",
"docstatus": 0,
"doctype": "DocType",
"fields": [
{
"default": "EXP",
"fieldname": "naming_series",
"fieldtype": "Select",
"label": "Series",
"no_copy": 1,
"options": "EXP",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"reqd": 1
},
{
"default": "Draft",
"depends_on": "eval:!doc.__islocal",
@@ -190,7 +202,7 @@
"icon": "icon-money",
"idx": 1,
"is_submittable": 1,
"modified": "2014-08-27 07:08:48.454580",
"modified": "2014-11-24 18:25:53.038826",
"modified_by": "Administrator",
"module": "HR",
"name": "Expense Claim",

View File

@@ -33,7 +33,7 @@ cur_frm.cscript.refresh = function(doc, dt, dn) {
cur_frm.set_intro(__("You are the Leave Approver for this record. Please Update the 'Status' and Save"));
cur_frm.toggle_enable("status", true);
} else {
cur_frm.set_intro(__("This Leave Application is pending approval. Only the Leave Apporver can update status."))
cur_frm.set_intro(__("This Leave Application is pending approval. Only the Leave Approver can update status."))
cur_frm.toggle_enable("status", false);
if(!doc.__islocal) {
cur_frm.frm_head.appframe.set_title_right("");
@@ -104,9 +104,32 @@ cur_frm.cscript.calculate_total_days = function(doc, dt, dn) {
if(cint(doc.half_day) == 1) set_multiple(dt,dn,{total_leave_days:0.5});
else{
// server call is done to include holidays in leave days calculations
return get_server_fields('get_total_leave_days', '', '', doc, dt, dn, 1);
return frappe.call({
method: 'erpnext.hr.doctype.leave_application.leave_application.get_total_leave_days',
args: {leave_app: doc},
callback: function(response) {
if (response && response.message) {
cur_frm.set_value('total_leave_days', response.message.total_leave_days);
}
}
});
}
}
}
cur_frm.fields_dict.employee.get_query = erpnext.queries.employee;
frappe.ui.form.on("Leave Application", "leave_approver", function(frm) {
frappe.call({
"method": "frappe.client.get",
args: {
doctype: "User",
name: frm.doc.leave_approver
},
callback: function (data) {
frappe.model.set_value(frm.doctype, frm.docname, "leave_approver_name",
data.message.first_name
+ (data.message.last_name ? (" " + data.message.last_name) : ""))
}
})
})

View File

@@ -24,6 +24,13 @@
"options": "User",
"permlevel": 0
},
{
"fieldname": "leave_approver_name",
"fieldtype": "Read Only",
"label": "Leave Approver Name",
"permlevel": 0,
"precision": ""
},
{
"fieldname": "leave_type",
"fieldtype": "Link",
@@ -184,7 +191,7 @@
"idx": 1,
"is_submittable": 1,
"max_attachments": 3,
"modified": "2014-09-09 05:35:31.531651",
"modified": "2014-12-09 16:33:29.626849",
"modified_by": "Administrator",
"module": "HR",
"name": "Leave Application",

View File

@@ -2,7 +2,7 @@
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
import frappe, json
from frappe import _
from frappe.utils import cint, cstr, date_diff, flt, formatdate, getdate, get_url_to_form, \
@@ -77,26 +77,10 @@ class LeaveApplication(Document):
LeaveDayBlockedError)
def get_holidays(self):
tot_hol = frappe.db.sql("""select count(*) from `tabHoliday` h1, `tabHoliday List` h2, `tabEmployee` e1
where e1.name = %s and h1.parent = h2.name and e1.holiday_list = h2.name
and h1.holiday_date between %s and %s""", (self.employee, self.from_date, self.to_date))
if not tot_hol:
tot_hol = frappe.db.sql("""select count(*) from `tabHoliday` h1, `tabHoliday List` h2
where h1.parent = h2.name and h1.holiday_date between %s and %s
and ifnull(h2.is_default,0) = 1 and h2.fiscal_year = %s""",
(self.from_date, self.to_date, self.fiscal_year))
return tot_hol and flt(tot_hol[0][0]) or 0
return get_holidays(self)
def get_total_leave_days(self):
"""Calculates total leave days based on input and holidays"""
ret = {'total_leave_days' : 0.5}
if not self.half_day:
tot_days = date_diff(self.to_date, self.from_date) + 1
holidays = self.get_holidays()
ret = {
'total_leave_days' : flt(tot_days)-flt(holidays)
}
return ret
return get_total_leave_days(self)
def validate_to_date(self):
if self.from_date and self.to_date and \
@@ -216,6 +200,35 @@ class LeaveApplication(Document):
post(**{"txt": args.message, "contact": args.message_to, "subject": args.subject,
"notify": cint(self.follow_via_email)})
def get_holidays(leave_app):
tot_hol = frappe.db.sql("""select count(*) from `tabHoliday` h1, `tabHoliday List` h2, `tabEmployee` e1
where e1.name = %s and h1.parent = h2.name and e1.holiday_list = h2.name
and h1.holiday_date between %s and %s""", (leave_app.employee, leave_app.from_date,
leave_app.to_date))[0][0]
# below line is needed. If an employee hasn't been assigned with any holiday list then above will return 0 rows.
if not tot_hol:
tot_hol = frappe.db.sql("""select count(*) from `tabHoliday` h1, `tabHoliday List` h2
where h1.parent = h2.name and h1.holiday_date between %s and %s
and ifnull(h2.is_default,0) = 1 and h2.fiscal_year = %s""",
(leave_app.from_date, leave_app.to_date, leave_app.fiscal_year))[0][0]
return tot_hol
@frappe.whitelist()
def get_total_leave_days(leave_app):
# Parse Leave Application if neccessary
if isinstance(leave_app, str) or isinstance(leave_app, unicode):
leave_app = frappe.get_doc(json.loads(leave_app))
"""Calculates total leave days based on input and holidays"""
ret = {'total_leave_days' : 0.5}
if not leave_app.half_day:
tot_days = date_diff(leave_app.to_date, leave_app.from_date) + 1
holidays = leave_app.get_holidays()
ret = {
'total_leave_days' : flt(tot_days)-flt(holidays)
}
return ret
@frappe.whitelist()
def get_leave_balance(employee, leave_type, fiscal_year):
leave_all = frappe.db.sql("""select total_leaves_allocated

View File

@@ -45,7 +45,7 @@ class SalarySlip(TransactionBase):
def get_leave_details(self, lwp=None):
if not self.fiscal_year:
self.fiscal_year = frappe.get_default("fiscal_year")
self.fiscal_year = frappe.db.get_default("fiscal_year")
if not self.month:
self.month = "%02d" % getdate(nowdate()).month
@@ -156,7 +156,7 @@ class SalarySlip(TransactionBase):
/ cint(self.total_days_in_month), 2)
elif not self.payment_days:
d.e_modified_amount = 0
else:
elif not d.e_modified_amount:
d.e_modified_amount = d.e_amount
self.gross_pay += flt(d.e_modified_amount)
@@ -168,7 +168,7 @@ class SalarySlip(TransactionBase):
/ cint(self.total_days_in_month), 2)
elif not self.payment_days:
d.d_modified_amount = 0
else:
elif not d.d_modified_amount:
d.d_modified_amount = d.d_amount
self.total_deduction += flt(d.d_modified_amount)
@@ -191,9 +191,6 @@ class SalarySlip(TransactionBase):
if receiver:
subj = 'Salary Slip - ' + cstr(self.month) +'/'+cstr(self.fiscal_year)
sendmail([receiver], subject=subj, msg = _("Please see attachment"),
attachments=[{
"fname": self.name + ".pdf",
"fcontent": frappe.get_print_format(self.doctype, self.name, as_pdf = True)
}])
attachments=[frappe.attach_print(self.doctype, self.name, file_name=self.name)])
else:
msgprint(_("Company Email ID not found, hence mail not sent"))

View File

@@ -83,6 +83,7 @@ cur_frm.cscript.hour_rate = function(doc, dt, dn) {
cur_frm.cscript.time_in_mins = cur_frm.cscript.hour_rate;
cur_frm.cscript.fixed_cycle_cost = cur_frm.cscript.hour_rate;
cur_frm.cscript.item_code = function(doc, cdt, cdn) {
get_bom_material_detail(doc, cdt, cdn);

View File

@@ -8,6 +8,8 @@ from frappe.utils import cint, cstr, flt
from frappe import _
from frappe.model.document import Document
from operator import itemgetter
class BOM(Document):
def autoname(self):
@@ -25,7 +27,7 @@ class BOM(Document):
self.validate_main_item()
from erpnext.utilities.transaction_base import validate_uom_is_integer
validate_uom_is_integer(self, "stock_uom", "qty")
validate_uom_is_integer(self, "stock_uom", "qty", "BOM Item")
self.validate_operations()
self.validate_materials()
@@ -57,6 +59,9 @@ class BOM(Document):
last_purchase_rate, is_manufactured_item
from `tabItem` where name=%s""", item_code, as_dict = 1)
if not item:
frappe.throw(_("Item: {0} does not exist in the system").format(item_code))
return item
def validate_rm_item(self, item):
@@ -285,7 +290,10 @@ class BOM(Document):
if not d.hour_rate:
d.hour_rate = flt(w[0])
fixed_cost += flt(w[1])
if d.fixed_cycle_cost == None:
d.fixed_cycle_cost= flt(w[1])
fixed_cost += d.fixed_cycle_cost
if d.hour_rate and d.time_in_mins:
d.operating_cost = flt(d.hour_rate) * flt(d.time_in_mins) / 60.0
@@ -354,7 +362,7 @@ class BOM(Document):
"Add items to Flat BOM table"
frappe.db.sql("""delete from `tabBOM Explosion Item` where parent=%s""", self.name)
self.set('flat_bom_details', [])
for d in self.cur_exploded_items:
for d in sorted(self.cur_exploded_items, key=itemgetter(0)):
ch = self.append('flat_bom_details', {})
for i in self.cur_exploded_items[d].keys():
ch.set(i, self.cur_exploded_items[d][i])

View File

@@ -10,7 +10,7 @@ from erpnext.manufacturing.doctype.production_order.production_order import make
from erpnext.stock.doctype.stock_entry import test_stock_entry
class TestProductionOrder(unittest.TestCase):
def test_planned_qty(self):
def check_planned_qty(self):
set_perpetual_inventory(0)
planned0 = frappe.db.get_value("Bin", {"item_code": "_Test FG Item", "warehouse": "_Test Warehouse 1 - _TC"}, "planned_qty") or 0
@@ -27,11 +27,15 @@ class TestProductionOrder(unittest.TestCase):
s = frappe.get_doc(make_stock_entry(pro_doc.name, "Material Transfer", 4))
for d in s.get("mtn_details"):
d.s_warehouse = "Stores - _TC"
s.fiscal_year = "_Test Fiscal Year 2013"
s.posting_date = "2013-01-02"
s.insert()
s.submit()
# from wip to fg
s = frappe.get_doc(make_stock_entry(pro_doc.name, "Manufacture", 4))
s.fiscal_year = "_Test Fiscal Year 2013"
s.posting_date = "2013-01-03"
s.insert()
s.submit()
@@ -44,12 +48,14 @@ class TestProductionOrder(unittest.TestCase):
def test_over_production(self):
from erpnext.manufacturing.doctype.production_order.production_order import StockOverProductionError
pro_doc = self.test_planned_qty()
pro_doc = self.check_planned_qty()
test_stock_entry.make_stock_entry("_Test Item", None, "_Test Warehouse - _TC", 100, 100)
test_stock_entry.make_stock_entry("_Test Item Home Desktop 100", None, "_Test Warehouse - _TC", 100, 100)
s = frappe.get_doc(make_stock_entry(pro_doc.name, "Manufacture", 7))
s.fiscal_year = "_Test Fiscal Year 2013"
s.posting_date = "2013-01-04"
s.insert()
self.assertRaises(StockOverProductionError, s.submit)

View File

@@ -24,6 +24,13 @@ cur_frm.cscript.item_code = function(doc,cdt,cdn) {
}
}
cur_frm.cscript.raise_purchase_request = function(doc, cdt, cdn) {
return frappe.call({
method: "raise_purchase_request",
doc:doc
})
}
cur_frm.cscript.download_materials_required = function(doc, cdt, cdn) {
return $c_obj(doc, 'validate_data', '', function(r, rt) {
if (!r['exc'])

View File

@@ -1,5 +1,5 @@
{
"creation": "2013-01-21 12:03:47.000000",
"creation": "2013-01-21 12:03:47",
"default_print_format": "Standard",
"docstatus": 0,
"doctype": "DocType",
@@ -20,6 +20,7 @@
{
"fieldname": "fg_item",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Filter based on item",
"options": "Item",
"permlevel": 0
@@ -27,6 +28,7 @@
{
"fieldname": "customer",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Filter based on customer",
"options": "Customer",
"permlevel": 0
@@ -34,6 +36,7 @@
{
"fieldname": "company",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Company",
"options": "Company",
"permlevel": 0,
@@ -140,7 +143,7 @@
"fieldname": "raise_purchase_request",
"fieldtype": "Button",
"label": "Create Material Requests",
"options": "raise_purchase_request",
"options": "",
"permlevel": 0
},
{
@@ -155,7 +158,7 @@
"idx": 1,
"in_create": 1,
"issingle": 1,
"modified": "2013-12-20 19:23:25.000000",
"modified": "2015-01-11 21:53:21.253556",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Production Planning Tool",

View File

@@ -85,4 +85,11 @@ erpnext.patches.v4_2.seprate_manufacture_and_repack
execute:frappe.delete_doc("Report", "Warehouse-Wise Stock Balance")
execute:frappe.delete_doc("DocType", "Purchase Request")
execute:frappe.delete_doc("DocType", "Purchase Request Item")
erpnext.patches.v4_2.recalculate_bom_cost
erpnext.patches.v4_2.recalculate_bom_cost
erpnext.patches.v4_2.fix_gl_entries_for_stock_transactions
erpnext.patches.v4_2.update_requested_and_ordered_qty
execute:frappe.delete_doc("DocType", "Contact Control")
erpnext.patches.v4_2.recalculate_bom_costs
erpnext.patches.v4_2.discount_amount
erpnext.patches.v4_2.update_landed_cost_voucher
erpnext.patches.v4_2.set_item_has_batch

View File

@@ -6,6 +6,7 @@ import frappe
def execute():
reference_date = guess_reference_date()
frappe.reload_doc('accounts', 'doctype', 'journal_voucher_detail')
for name in frappe.db.sql_list("""select name from `tabJournal Voucher`
where date(creation)>=%s""", reference_date):
jv = frappe.get_doc("Journal Voucher", name)

View File

@@ -0,0 +1,12 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
from frappe.modules import scrub, get_doctype_module
def execute():
for dt in ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"]:
frappe.reload_doc(get_doctype_module(dt), "doctype", scrub(dt))
frappe.db.sql("""update `tab{0}` set base_discount_amount=discount_amount,
discount_amount=discount_amount/conversion_rate""".format(dt))

View File

@@ -7,45 +7,46 @@ from frappe.utils import flt
def execute():
from erpnext.utilities.repost_stock import repost
repost()
repost(allow_zero_rate=True, only_actual=True)
warehouse_account = frappe.db.sql("""select name, master_name from tabAccount
where ifnull(account_type, '') = 'Warehouse'""")
warehouses = [d[1] for d in warehouse_account]
accounts = [d[0] for d in warehouse_account]
if warehouse_account:
warehouses = [d[1] for d in warehouse_account]
accounts = [d[0] for d in warehouse_account]
stock_vouchers = frappe.db.sql("""select distinct sle.voucher_type, sle.voucher_no
from `tabStock Ledger Entry` sle
where sle.warehouse in (%s)
order by sle.posting_date""" %
', '.join(['%s']*len(warehouses)), tuple(warehouses))
stock_vouchers = frappe.db.sql("""select distinct sle.voucher_type, sle.voucher_no
from `tabStock Ledger Entry` sle
where sle.warehouse in (%s)
order by sle.posting_date""" %
', '.join(['%s']*len(warehouses)), tuple(warehouses))
rejected = []
for voucher_type, voucher_no in stock_vouchers:
stock_bal = frappe.db.sql("""select sum(stock_value_difference) from `tabStock Ledger Entry`
where voucher_type=%s and voucher_no =%s and warehouse in (%s)""" %
('%s', '%s', ', '.join(['%s']*len(warehouses))), tuple([voucher_type, voucher_no] + warehouses))
rejected = []
for voucher_type, voucher_no in stock_vouchers:
stock_bal = frappe.db.sql("""select sum(stock_value_difference) from `tabStock Ledger Entry`
where voucher_type=%s and voucher_no =%s and warehouse in (%s)""" %
('%s', '%s', ', '.join(['%s']*len(warehouses))), tuple([voucher_type, voucher_no] + warehouses))
account_bal = frappe.db.sql("""select ifnull(sum(ifnull(debit, 0) - ifnull(credit, 0)), 0)
from `tabGL Entry`
where voucher_type=%s and voucher_no =%s and account in (%s)
group by voucher_type, voucher_no""" %
('%s', '%s', ', '.join(['%s']*len(accounts))), tuple([voucher_type, voucher_no] + accounts))
account_bal = frappe.db.sql("""select ifnull(sum(ifnull(debit, 0) - ifnull(credit, 0)), 0)
from `tabGL Entry`
where voucher_type=%s and voucher_no =%s and account in (%s)
group by voucher_type, voucher_no""" %
('%s', '%s', ', '.join(['%s']*len(accounts))), tuple([voucher_type, voucher_no] + accounts))
if stock_bal and account_bal and abs(flt(stock_bal[0][0]) - flt(account_bal[0][0])) > 0.1:
try:
print voucher_type, voucher_no, stock_bal[0][0], account_bal[0][0]
if stock_bal and account_bal and abs(flt(stock_bal[0][0]) - flt(account_bal[0][0])) > 0.1:
try:
print voucher_type, voucher_no, stock_bal[0][0], account_bal[0][0]
frappe.db.sql("""delete from `tabGL Entry`
where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
frappe.db.sql("""delete from `tabGL Entry`
where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
voucher = frappe.get_doc(voucher_type, voucher_no)
voucher.make_gl_entries(repost_future_gle=False, allow_negative_stock=True)
frappe.db.commit()
except Exception, e:
print frappe.get_traceback()
rejected.append([voucher_type, voucher_no])
frappe.db.rollback()
voucher = frappe.get_doc(voucher_type, voucher_no)
voucher.make_gl_entries(repost_future_gle=False)
frappe.db.commit()
except Exception, e:
print frappe.get_traceback()
rejected.append([voucher_type, voucher_no])
frappe.db.rollback()
print "Failed to repost: "
print rejected
print "Failed to repost: "
print rejected

View File

@@ -0,0 +1,19 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
frappe.reload_doc('manufacturing', 'doctype', 'bom_operation')
for d in frappe.db.sql("""select bom.name from `tabBOM` bom where bom.docstatus < 2 and
exists(select bom_op.name from `tabBOM Operation` bom_op where
bom.name = bom_op.parent and bom_op.fixed_cycle_cost IS NOT NULL)""", as_dict=1):
try:
bom = frappe.get_doc('BOM', d.name)
bom.ignore_validate_update_after_submit = True
bom.calculate_cost()
bom.save()
frappe.db.commit()
except:
frappe.db.rollback()

View File

@@ -0,0 +1,65 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
frappe.db.sql("update tabItem set has_batch_no = 'No' where ifnull(has_batch_no, '') = ''")
frappe.db.sql("update tabItem set has_serial_no = 'No' where ifnull(has_serial_no, '') = ''")
item_list = frappe.db.sql("""select name, has_batch_no, has_serial_no from tabItem
where ifnull(is_stock_item, 'No') = 'Yes'""", as_dict=1)
sle_count = get_sle_count()
sle_with_batch = get_sle_with_batch()
sle_with_serial = get_sle_with_serial()
batch_items = get_items_with_batch()
serialized_items = get_items_with_serial()
for d in item_list:
if d.has_batch_no == 'Yes':
if d.name not in batch_items and sle_count.get(d.name) and sle_count.get(d.name) != sle_with_batch.get(d.name):
frappe.db.set_value("Item", d.name, "has_batch_no", "No")
else:
if d.name in batch_items or (sle_count.get(d.name) and sle_count.get(d.name) == sle_with_batch.get(d.name)):
frappe.db.set_value("Item", d.name, "has_batch_no", "Yes")
if d.has_serial_no == 'Yes':
if d.name not in serialized_items and sle_count.get(d.name) and sle_count.get(d.name) != sle_with_serial.get(d.name):
frappe.db.set_value("Item", d.name, "has_serial_no", "No")
else:
if d.name in serialized_items or (sle_count.get(d.name) and sle_count.get(d.name) == sle_with_serial.get(d.name)):
frappe.db.set_value("Item", d.name, "has_serial_no", "Yes")
def get_sle_count():
sle_count = {}
for d in frappe.db.sql("""select item_code, count(name) as cnt from `tabStock Ledger Entry` group by item_code""", as_dict=1):
sle_count.setdefault(d.item_code, d.cnt)
return sle_count
def get_sle_with_batch():
sle_with_batch = {}
for d in frappe.db.sql("""select item_code, count(name) as cnt from `tabStock Ledger Entry`
where ifnull(batch_no, '') != '' group by item_code""", as_dict=1):
sle_with_batch.setdefault(d.item_code, d.cnt)
return sle_with_batch
def get_sle_with_serial():
sle_with_serial = {}
for d in frappe.db.sql("""select item_code, count(name) as cnt from `tabStock Ledger Entry`
where ifnull(serial_no, '') != '' group by item_code""", as_dict=1):
sle_with_serial.setdefault(d.item_code, d.cnt)
return sle_with_serial
def get_items_with_batch():
return frappe.db.sql_list("select item from tabBatch")
def get_items_with_serial():
return frappe.db.sql_list("select item_code from `tabSerial No`")

View File

@@ -0,0 +1,10 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
frappe.reload_doc("stock", "doctype", "landed_cost_voucher")
frappe.db.sql("""update `tabLanded Cost Voucher` set distribute_charges_based_on = 'Amount'
where docstatus=1""")

View File

@@ -0,0 +1,24 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
from erpnext.utilities.repost_stock import update_bin_qty, get_indented_qty, get_ordered_qty
count=0
for item_code, warehouse in frappe.db.sql("""select distinct item_code, warehouse from
(select item_code, warehouse from tabBin
union
select item_code, warehouse from `tabStock Ledger Entry`) a"""):
try:
count += 1
update_bin_qty(item_code, warehouse, {
"indented_qty": get_indented_qty(item_code, warehouse),
"ordered_qty": get_ordered_qty(item_code, warehouse)
})
if count % 200 == 0:
frappe.db.commit()
except:
frappe.db.rollback()

View File

@@ -16,6 +16,15 @@ class TestTimeLog(unittest.TestCase):
self.assertRaises(OverlapError, ts.insert)
frappe.db.sql("delete from `tabTime Log`")
def test_negative_hours(self):
frappe.db.sql("delete from `tabTime Log`")
test_time_log = frappe.new_doc("Time Log")
test_time_log.activity_type = "Communication"
test_time_log.from_time = "2013-01-01 11:00:00.000000"
test_time_log.to_time = "2013-01-01 10:00:00.000000"
self.assertRaises(frappe.ValidationError, test_time_log.save)
frappe.db.sql("delete from `tabTime Log`")
test_records = frappe.get_test_records('Time Log')
test_ignore = ["Time Log Batch", "Sales Invoice"]

View File

@@ -1,5 +1,5 @@
{
"allow_import": 1,
"allow_import": 1,
"autoname": "naming_series:",
"creation": "2013-04-03 16:38:41",
"description": "Log of Activities performed by users against Tasks that can be used for tracking time, billing.",
@@ -25,14 +25,6 @@
"read_only": 0,
"reqd": 1
},
{
"fieldname": "hours",
"fieldtype": "Float",
"in_list_view": 1,
"label": "Hours",
"permlevel": 0,
"read_only": 0
},
{
"fieldname": "to_time",
"fieldtype": "Datetime",
@@ -42,6 +34,14 @@
"read_only": 0,
"reqd": 1
},
{
"fieldname": "hours",
"fieldtype": "Float",
"in_list_view": 1,
"label": "Hours",
"permlevel": 0,
"read_only": 0
},
{
"fieldname": "column_break_3",
"fieldtype": "Column Break",
@@ -151,7 +151,7 @@
"icon": "icon-time",
"idx": 1,
"is_submittable": 1,
"modified": "2014-08-04 05:23:15.740050",
"modified": "2014-10-22 16:53:26.993828",
"modified_by": "Administrator",
"module": "Projects",
"name": "Time Log",

View File

@@ -19,10 +19,12 @@ class TimeLog(Document):
self.set_status()
self.validate_overlap()
self.calculate_total_hours()
def calculate_total_hours(self):
from frappe.utils import time_diff_in_hours
self.hours = time_diff_in_hours(self.to_time, self.from_time)
if self.hours < 0:
frappe.throw(_("'From Time' cannot be later than 'To Time'"))
def set_status(self):
self.status = {

View File

@@ -10,6 +10,8 @@
"public/js/feature_setup.js",
"public/js/utils.js",
"public/js/queries.js",
"public/js/utils/party.js"
"public/js/utils/party.js",
"public/js/templates/address_list.html",
"public/js/templates/contact_list.html"
]
}

View File

@@ -108,6 +108,7 @@ erpnext.StockAnalytics = erpnext.StockGridReport.extend({
// otherwise, only reset values
$.each(this.data, function(i, d) {
me.reset_item_values(d);
d["closing_qty_value"] = 0;
});
}
@@ -131,6 +132,7 @@ erpnext.StockAnalytics = erpnext.StockGridReport.extend({
if(me.is_default("warehouse") ? true : me.warehouse == sl.warehouse) {
var item = me.item_by_name[sl.item_code];
if(item.closing_qty_value==undefined) item.closing_qty_value = 0;
if(me.value_or_qty!="Quantity") {
var wh = me.get_item_warehouse(sl.warehouse, sl.item_code);

View File

@@ -0,0 +1,20 @@
<p><button class="btn btn-sm btn-default btn-address">
<i class="icon-plus"></i> New Address</button></p>
{% for(var i=0, l=addr_list.length; i<l; i++) { %}
<hr>
<a href="#Form/Address/{%= addr_list[i].name %}" class="btn btn-sm btn-default pull-right">
{%= __("Edit") %}</a>
<p><b>{%= i+1 %}. {%= addr_list[i].address_type %}</b></p>
<div style="padding-left: 15px;">
<div>
{% if(addr_list[i].is_primary_address) { %}<span class="label label-info">
{%= __("Primary") %}</span>{% } %}
{% if(addr_list[i].is_shipping_address) { %}<span class="label label-default">
{%= __("Shipping") %}</span>{% } %}
</div>
<p style="margin-top: 5px;">{%= addr_list[i].display %}</p>
</div>
{% } %}
{% if(!addr_list.length) { %}
<p class="text-muted">{%= __("No address added yet.") %}</p>
{% } %}

View File

@@ -0,0 +1,28 @@
<p><button class="btn btn-sm btn-default btn-contact">
<i class="icon-plus"></i> New Contact</button></p>
{% for(var i=0, l=contact_list.length; i<l; i++) { %}
<hr>
<a href="#Form/Contact/{%= contact_list[i].name %}" class="btn btn-sm btn-default pull-right">
{%= __("Edit") %}</a>
<p><b>{%= i+1 %}. {%= contact_list[i].first_name %} {%= contact_list[i].last_name %}</b></p>
<div style="padding-left: 15px;">
<div>
{% if(contact_list[i].is_primary_contact) { %}<span class="label label-info">
{%= __("Primary") %}</span>{% } %}
</div>
<p style="padding-top: 5px;">
{% if(contact_list[i].phone) { %}
{%= __("Phone") %}: {%= contact_list[i].phone %}<br>
{% } %}
{% if(contact_list[i].mobile_no) { %}
{%= __("Mobile No.") %}: {%= contact_list[i].mobile_no %}<br>
{% } %}
{% if(contact_list[i].email_id) { %}
{%= __("Email ID") %}: {%= contact_list[i].email_id %}
{% } %}
</p>
</div>
{% } %}
{% if(!contact_list.length) { %}
<p class="text-muted">{%= __("No contacts added yet.") %}</p>
{% } %}

View File

@@ -402,20 +402,36 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
},
_set_values_for_item_list: function(children) {
$.each(children, function(i, d) {
$.each(d, function(k, v) {
var me = this;
var price_list_rate_changed = false;
for(var i=0, l=children.length; i<l; i++) {
var d = children[i];
var existing_pricing_rule = frappe.model.get_value(d.doctype, d.name, "pricing_rule");
for(var k in d) {
var v = d[k];
if (["doctype", "name"].indexOf(k)===-1) {
if(k=="price_list_rate") {
if(flt(v) != flt(d.price_list_rate)) price_list_rate_changed = true;
}
frappe.model.set_value(d.doctype, d.name, k, v);
}
});
});
}
// if pricing rule set as blank from an existing value, apply price_list
if(!me.frm.doc.ignore_pricing_rule && existing_pricing_rule && !d.pricing_rule) {
me.apply_price_list(frappe.get_doc(d.doctype, d.name));
}
}
if(!price_list_rate_changed) me.calculate_taxes_and_totals();
},
apply_price_list: function() {
apply_price_list: function(item) {
var me = this;
return this.frm.call({
method: "erpnext.stock.get_item_details.apply_price_list",
args: { args: this._get_args() },
args: { args: this._get_args(item) },
callback: function(r) {
if (!r.exc) {
me.in_apply_price_list = true;
@@ -722,7 +738,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
},
adjust_discount_amount_loss: function(tax) {
var discount_amount_loss = this.frm.doc.grand_total - flt(this.frm.doc.discount_amount) - tax.total;
var discount_amount_loss = this.frm.doc.grand_total - flt(this.frm.doc.base_discount_amount) - tax.total;
tax.tax_amount_after_discount_amount = flt(tax.tax_amount_after_discount_amount +
discount_amount_loss, precision("tax_amount", tax));
tax.total = flt(tax.total + discount_amount_loss, precision("total", tax));
@@ -736,8 +752,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
// distribute the tax amount proportionally to each item row
var actual = flt(tax.rate, precision("tax_amount", tax));
current_tax_amount = this.frm.doc.net_total ?
((item.base_amount / this.frm.doc.net_total) * actual) :
0.0;
((item.base_amount / this.frm.doc.net_total) * actual) : 0.0;
} else if(tax.charge_type == "On Net Total") {
current_tax_amount = (tax_rate / 100.0) * item.base_amount;

View File

@@ -81,5 +81,28 @@ $.extend(erpnext, {
d.show();
});
}
},
});
erpnext.utils = {
render_address_and_contact: function(frm) {
// render address
$(frm.fields_dict['address_html'].wrapper)
.html(frappe.render(frappe.templates.address_list,
cur_frm.doc.__onload))
.find(".btn-address").on("click", function() {
new_doc("Address");
});
// render contact
if(frm.fields_dict['contact_html']) {
$(frm.fields_dict['contact_html'].wrapper)
.html(frappe.render(frappe.templates.contact_list,
cur_frm.doc.__onload))
.find(".btn-contact").on("click", function() {
new_doc("Contact");
}
);
}
}
}

View File

@@ -1,8 +1,6 @@
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
{% include 'setup/doctype/contact_control/contact_control.js' %};
cur_frm.cscript.onload = function(doc, dt, dn) {
cur_frm.cscript.load_defaults(doc, dt, dn);
}
@@ -32,8 +30,8 @@ cur_frm.cscript.refresh = function(doc, dt, dn) {
}else{
unhide_field(['address_html','contact_html']);
// make lists
cur_frm.cscript.make_address(doc, dt, dn);
cur_frm.cscript.make_contact(doc, dt, dn);
erpnext.utils.render_address_and_contact(cur_frm)
cur_frm.communication_view = new frappe.views.CommunicationList({
parent: cur_frm.fields_dict.communication_html.wrapper,
@@ -79,44 +77,6 @@ cur_frm.cscript.setup_dashboard = function(doc) {
});
}
cur_frm.cscript.make_address = function() {
if(!cur_frm.address_list) {
cur_frm.address_list = new frappe.ui.Listing({
parent: cur_frm.fields_dict['address_html'].wrapper,
page_length: 5,
new_doctype: "Address",
get_query: function() {
return "select name, address_type, address_line1, address_line2, city, state, country, pincode, fax, email_id, phone, is_primary_address, is_shipping_address from tabAddress where customer='" +
cur_frm.doc.name.replace(/'/g, "\\'") + "' and docstatus != 2 order by is_primary_address desc"
},
as_dict: 1,
no_results_message: __('No addresses created'),
render_row: cur_frm.cscript.render_address_row,
});
// note: render_address_row is defined in contact_control.js
}
cur_frm.address_list.run();
}
cur_frm.cscript.make_contact = function() {
if(!cur_frm.contact_list) {
cur_frm.contact_list = new frappe.ui.Listing({
parent: cur_frm.fields_dict['contact_html'].wrapper,
page_length: 5,
new_doctype: "Contact",
get_query: function() {
return "select name, first_name, last_name, email_id, phone, mobile_no, department, designation, is_primary_contact from tabContact where customer='" +
cur_frm.doc.name.replace(/'/g, "\\'") + "' and docstatus != 2 order by is_primary_contact desc"
},
as_dict: 1,
no_results_message: __('No contacts created'),
render_row: cur_frm.cscript.render_contact_row,
});
// note: render_contact_row is defined in contact_control.js
}
cur_frm.contact_list.run();
}
cur_frm.fields_dict['customer_group'].get_query = function(doc, dt, dn) {
return{
filters:{'is_group': 'No'}

View File

@@ -7,11 +7,14 @@ from frappe.model.naming import make_autoname
from frappe import msgprint, _
import frappe.defaults
from erpnext.utilities.transaction_base import TransactionBase
from erpnext.utilities.address_and_contact import load_address_and_contact
from erpnext.accounts.party import create_party_account
class Customer(TransactionBase):
def onload(self):
"""Load address and contacts in `__onload`"""
load_address_and_contact(self, "customer")
def autoname(self):
cust_master_name = frappe.defaults.get_global_default('cust_master_name')

View File

@@ -1,8 +1,6 @@
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
{% include 'setup/doctype/contact_control/contact_control.js' %};
frappe.provide("erpnext");
erpnext.LeadController = frappe.ui.form.Controller.extend({
setup: function() {
@@ -42,33 +40,10 @@ erpnext.LeadController = frappe.ui.form.Controller.extend({
});
if(!this.frm.doc.__islocal) {
this.make_address_list();
erpnext.utils.render_address_and_contact(cur_frm);
}
},
make_address_list: function() {
var me = this;
if(!this.frm.address_list) {
this.frm.address_list = new frappe.ui.Listing({
parent: this.frm.fields_dict['address_html'].wrapper,
page_length: 5,
new_doctype: "Address",
get_query: function() {
return 'select name, address_type, address_line1, address_line2, \
city, state, country, pincode, fax, email_id, phone, \
is_primary_address, is_shipping_address from tabAddress \
where lead="'+me.frm.doc.name+'" and docstatus != 2 \
order by is_primary_address, is_shipping_address desc'
},
as_dict: 1,
no_results_message: __('No addresses created'),
render_row: this.render_address_row,
});
// note: render_address_row is defined in contact_control.js
}
this.frm.address_list.run();
},
create_customer: function() {
frappe.model.open_mapped_doc({
method: "erpnext.selling.doctype.lead.lead.make_customer",

View File

@@ -160,7 +160,7 @@
"allow_on_submit": 0,
"description": "Add to calendar on this date",
"fieldname": "contact_date",
"fieldtype": "Date",
"fieldtype": "Datetime",
"in_filter": 1,
"label": "Next Contact Date",
"no_copy": 1,
@@ -368,7 +368,7 @@
],
"icon": "icon-user",
"idx": 1,
"modified": "2014-08-12 05:22:18.801092",
"modified": "2014-12-01 08:22:23.286314",
"modified_by": "Administrator",
"module": "Selling",
"name": "Lead",

View File

@@ -9,11 +9,13 @@ from frappe import session
from frappe.model.mapper import get_mapped_doc
from erpnext.controllers.selling_controller import SellingController
from erpnext.utilities.address_and_contact import load_address_and_contact
class Lead(SellingController):
def onload(self):
customer = frappe.db.get_value("Customer", {"lead_name": self.name})
self.get("__onload").is_customer = customer
load_address_and_contact(self, "lead")
def validate(self):
self._prev = frappe._dict({
@@ -43,6 +45,7 @@ class Lead(SellingController):
def add_calendar_event(self, opts=None, force=False):
super(Lead, self).add_calendar_event({
"owner": self.lead_owner,
"starts_on": self.contact_date,
"subject": ('Contact ' + cstr(self.lead_name)),
"description": ('Contact ' + cstr(self.lead_name)) + \
(self.contact_by and ('. By : ' + cstr(self.contact_by)) or '')

View File

@@ -35,8 +35,6 @@ erpnext.selling.Opportunity = frappe.ui.form.Controller.extend({
});
}
if(this.frm.doc.customer && !this.frm.doc.customer_name) cur_frm.cscript.customer(this.frm.doc);
this.setup_queries();
},

View File

@@ -47,6 +47,7 @@
"in_filter": 1,
"in_list_view": 1,
"label": "Customer",
"no_copy": 1,
"oldfieldname": "customer",
"oldfieldtype": "Link",
"options": "Customer",
@@ -372,7 +373,7 @@
{
"description": "Your sales person will get a reminder on this date to contact the customer",
"fieldname": "contact_date",
"fieldtype": "Date",
"fieldtype": "Datetime",
"label": "Next Contact Date",
"oldfieldname": "contact_date",
"oldfieldtype": "Date",
@@ -416,7 +417,7 @@
"icon": "icon-info-sign",
"idx": 1,
"is_submittable": 1,
"modified": "2014-08-12 05:21:51.282397",
"modified": "2014-12-19 10:49:20.695720",
"modified_by": "Administrator",
"module": "Selling",
"name": "Opportunity",

View File

@@ -57,6 +57,7 @@ class Opportunity(TransactionBase):
opts = frappe._dict()
opts.description = ""
opts.contact_date = self.contact_date
if self.customer:
if self.contact_person:

View File

@@ -5,6 +5,8 @@
"enquiry_from": "Lead",
"enquiry_type": "Sales",
"lead": "_T-Lead-00001",
"transaction_date": "2013-12-12",
"fiscal_year": "_Test Fiscal Year 2013",
"enquiry_details": [{
"item_name": "Test Item",
"description": "Some description"

View File

@@ -405,6 +405,15 @@
"fieldtype": "Section Break",
"permlevel": 0
},
{
"fieldname": "other_charges_total_export",
"fieldtype": "Currency",
"label": "Taxes and Charges Total",
"options": "currency",
"permlevel": 0,
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "other_charges_total",
"fieldtype": "Currency",
@@ -421,22 +430,23 @@
"fieldtype": "Column Break",
"permlevel": 0
},
{
"fieldname": "other_charges_total_export",
"fieldtype": "Currency",
"label": "Taxes and Charges Total",
"options": "currency",
"permlevel": 0,
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "discount_amount",
"fieldtype": "Currency",
"label": "Discount Amount",
"options": "Company:company:default_currency",
"options": "currency",
"permlevel": 0
},
{
"fieldname": "base_discount_amount",
"fieldtype": "Currency",
"label": "Discount Amount (Company Currency)",
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "totals",
"fieldtype": "Section Break",
@@ -713,7 +723,7 @@
"no_copy": 1,
"oldfieldname": "status",
"oldfieldtype": "Select",
"options": "Draft\nSubmitted\nOrdered\nLost\nCancelled",
"options": "Draft\nSubmitted\nOrdered\nLost\nCancelled\nOpen\nReplied",
"permlevel": 0,
"print_hide": 1,
"read_only": 1,
@@ -832,7 +842,7 @@
"idx": 1,
"is_submittable": 1,
"max_attachments": 1,
"modified": "2014-09-09 05:35:33.413559",
"modified": "2015-01-21 11:24:08.210880",
"modified_by": "Administrator",
"module": "Selling",
"name": "Quotation",

View File

@@ -23,7 +23,7 @@ class Quotation(SellingController):
self.validate_order_type()
self.validate_for_items()
self.validate_uom_is_integer("stock_uom", "qty")
self.quotation_to = "Customer" if self.customer else "Lead"
self.validate_quotation_to()
def has_sales_order(self):
return frappe.db.get_value("Sales Order Item", {"prevdoc_docname": self.name, "docstatus": 1})
@@ -54,6 +54,13 @@ class Quotation(SellingController):
if is_sales_item == 'No':
frappe.throw(_("Item {0} must be Sales Item").format(d.item_code))
def validate_quotation_to(self):
if self.customer:
self.quotation_to = "Customer"
self.lead = None
elif self.lead:
self.quotation_to = "Lead"
def update_opportunity(self):
for opportunity in list(set([d.prevdoc_docname for d in self.get("quotation_details")])):
if opportunity:
@@ -139,8 +146,8 @@ def _make_sales_order(source_name, target_doc=None, ignore_permissions=False):
return doclist
def _make_customer(source_name, ignore_permissions=False):
quotation = frappe.db.get_value("Quotation", source_name, ["lead", "order_type"])
if quotation and quotation[0]:
quotation = frappe.db.get_value("Quotation", source_name, ["lead", "order_type", "customer"])
if quotation and quotation[0] and not quotation[2]:
lead_name = quotation[0]
customer_name = frappe.db.get_value("Customer", {"lead_name": lead_name},
["name", "customer_name"], as_dict=True)

View File

@@ -175,6 +175,7 @@
"fieldtype": "Data",
"hidden": 0,
"label": "PO No",
"no_copy": 0,
"oldfieldname": "po_no",
"oldfieldtype": "Data",
"permlevel": 0,
@@ -419,11 +420,6 @@
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "column_break_46",
"fieldtype": "Column Break",
"permlevel": 0
},
{
"fieldname": "other_charges_total",
"fieldtype": "Currency",
@@ -436,12 +432,28 @@
"read_only": 1,
"width": "150px"
},
{
"fieldname": "column_break_46",
"fieldtype": "Column Break",
"permlevel": 0
},
{
"fieldname": "discount_amount",
"fieldtype": "Currency",
"label": "Discount Amount",
"options": "currency",
"permlevel": 0,
"print_hide": 0
},
{
"fieldname": "base_discount_amount",
"fieldtype": "Currency",
"label": "Discount Amount (Company Currency)",
"options": "Company:company:default_currency",
"permlevel": 0
"permlevel": 0,
"precision": "",
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "totals",
@@ -489,14 +501,6 @@
"read_only": 1,
"width": "200px"
},
{
"fieldname": "advance_paid",
"fieldtype": "Currency",
"label": "Advance Paid",
"permlevel": 0,
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "column_break3",
"fieldtype": "Column Break",
@@ -541,6 +545,15 @@
"read_only": 1,
"width": "200px"
},
{
"fieldname": "advance_paid",
"fieldtype": "Currency",
"label": "Advance Paid",
"options": "Company:company:default_currency",
"permlevel": 0,
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "view_details",
"fieldtype": "Fold",
@@ -1020,7 +1033,7 @@
"idx": 1,
"is_submittable": 1,
"issingle": 0,
"modified": "2014-10-08 14:22:44.717108",
"modified": "2015-01-12 15:16:51.611467",
"modified_by": "Administrator",
"module": "Selling",
"name": "Sales Order",

View File

@@ -51,12 +51,12 @@ class SalesOrder(SellingController):
frappe.throw(_("Reserved warehouse required for stock item {0}").format(d.item_code))
if e in check_list:
frappe.throw(_("Item {0} has been entered twice").format(d.item_code))
frappe.msgprint(_("Item {0} has been entered twice").format(d.item_code))
else:
check_list.append(e)
else:
if f in chk_dupl_itm:
frappe.throw(_("Item {0} has been entered twice").format(d.item_code))
frappe.msgprint(_("Item {0} has been entered twice").format(d.item_code))
else:
chk_dupl_itm.append(f)
@@ -157,7 +157,7 @@ class SalesOrder(SellingController):
self.check_credit(self.grand_total)
frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype, self.grand_total, self)
frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype, self.company, self.grand_total, self)
self.update_prevdoc_status('submit')
frappe.db.set(self, 'status', 'Submitted')
@@ -275,6 +275,14 @@ def make_material_request(source_name, target_doc=None):
@frappe.whitelist()
def make_delivery_note(source_name, target_doc=None):
def set_missing_values(source, target):
if source.po_no:
if target.po_no:
target_po_no = target.po_no.split(", ")
target_po_no.append(source.po_no)
target.po_no = ", ".join(list(set(target_po_no))) if len(target_po_no) > 1 else target_po_no[0]
else:
target.po_no = source.po_no
target.ignore_pricing_rule = 1
target.run_method("set_missing_values")
target.run_method("calculate_taxes_and_totals")
@@ -329,7 +337,7 @@ def make_sales_invoice(source_name, target_doc=None):
def update_item(source, target, source_parent):
target.amount = flt(source.amount) - flt(source.billed_amt)
target.base_amount = target.amount * flt(source_parent.conversion_rate)
target.qty = source.rate and target.amount / flt(source.rate) or source.qty
target.qty = target.amount / flt(source.rate) if (source.rate and source.billed_amt) else source.qty
doclist = get_mapped_doc("Sales Order", source_name, {
"Sales Order": {
@@ -357,17 +365,6 @@ def make_sales_invoice(source_name, target_doc=None):
}
}, target_doc, postprocess)
def set_advance_vouchers(source, target):
advance_voucher_list = []
advance_voucher = frappe.db.sql("""
select
t1.name as voucher_no, t1.posting_date, t1.remark, t2.account,
t2.name as voucher_detail_no, {amount_query} as payment_amount, t2.is_advance
from
`tabJournal Voucher` t1, `tabJournal Voucher Detail` t2
""")
return doclist
@frappe.whitelist()

View File

@@ -8,19 +8,22 @@ frappe.query_reports["Customer Acquisition and Loyalty"] = {
"label": __("Company"),
"fieldtype": "Link",
"options": "Company",
"default": frappe.defaults.get_user_default("company")
"default": frappe.defaults.get_user_default("company"),
"reqd": 1
},
{
"fieldname":"from_date",
"label": __("From Date"),
"fieldtype": "Date",
"default": frappe.defaults.get_user_default("year_start_date")
"default": frappe.defaults.get_user_default("year_start_date"),
"reqd": 1
},
{
"fieldname":"to_date",
"label": __("To Date"),
"fieldtype": "Date",
"default": frappe.defaults.get_user_default("year_end_date")
"default": frappe.defaults.get_user_default("year_end_date"),
"reqd": 1
},
]
}
}

View File

@@ -5,12 +5,12 @@
"doctype": "Report",
"idx": 1,
"is_standard": "Yes",
"modified": "2014-06-03 07:18:17.139224",
"modified": "2015-02-02 11:39:57.231750",
"modified_by": "Administrator",
"module": "Selling",
"name": "Lead Details",
"owner": "Administrator",
"query": "SELECT\n `tabLead`.name as \"Lead Id:Link/Lead:120\",\n `tabLead`.lead_name as \"Lead Name::120\",\n\t`tabLead`.company_name as \"Company Name::120\",\n\t`tabLead`.status as \"Status::120\",\n\tconcat_ws(', ', \n\t\ttrim(',' from `tabAddress`.address_line1), \n\t\ttrim(',' from tabAddress.address_line2), \n\t\ttabAddress.state, tabAddress.pincode, tabAddress.country\n\t) as 'Address::180',\n\t`tabLead`.phone as \"Phone::100\",\n\t`tabLead`.mobile_no as \"Mobile No::100\",\n\t`tabLead`.email_id as \"Email Id::120\",\n\t`tabLead`.lead_owner as \"Lead Owner::120\",\n\t`tabLead`.source as \"Source::120\",\n\t`tabLead`.territory as \"Territory::120\",\n `tabLead`.owner as \"Owner:Link/User:120\"\nFROM\n\t`tabLead`\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.lead=`tabLead`.name\n\t)\nWHERE\n\t`tabLead`.docstatus<2\nORDER BY\n\t`tabLead`.name asc",
"query": "SELECT\n `tabLead`.name as \"Lead Id:Link/Lead:120\",\n `tabLead`.lead_name as \"Lead Name::120\",\n\t`tabLead`.company_name as \"Company Name::120\",\n\t`tabLead`.status as \"Status::120\",\n\tconcat_ws(', ', \n\t\ttrim(',' from `tabAddress`.address_line1), \n\t\ttrim(',' from tabAddress.address_line2)\n\t) as 'Address::180',\n\t`tabAddress`.state as \"State::100\",\n\t`tabAddress`.pincode as \"Pincode::70\",\n\t`tabAddress`.country as \"Country::100\",\n\t`tabLead`.phone as \"Phone::100\",\n\t`tabLead`.mobile_no as \"Mobile No::100\",\n\t`tabLead`.email_id as \"Email Id::120\",\n\t`tabLead`.lead_owner as \"Lead Owner::120\",\n\t`tabLead`.source as \"Source::120\",\n\t`tabLead`.territory as \"Territory::120\",\n `tabLead`.owner as \"Owner:Link/User:120\"\nFROM\n\t`tabLead`\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.lead=`tabLead`.name\n\t)\nWHERE\n\t`tabLead`.docstatus<2\nORDER BY\n\t`tabLead`.name asc",
"ref_doctype": "Lead",
"report_name": "Lead Details",
"report_type": "Query Report"

View File

@@ -341,18 +341,21 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
var me = this;
var tax_count = this.frm.tax_doclist.length;
this.frm.doc.grand_total = flt(
tax_count ? this.frm.tax_doclist[tax_count - 1].total : this.frm.doc.net_total,
precision("grand_total"));
this.frm.doc.grand_total_export = flt(this.frm.doc.grand_total / this.frm.doc.conversion_rate,
precision("grand_total_export"));
this.frm.doc.grand_total = flt(tax_count ? this.frm.tax_doclist[tax_count - 1].total : this.frm.doc.net_total);
this.frm.doc.other_charges_total = flt(this.frm.doc.grand_total - this.frm.doc.net_total,
precision("other_charges_total"));
this.frm.doc.grand_total_export = (this.frm.doc.other_charges_total || this.frm.doc.discount_amount) ?
flt(this.frm.doc.grand_total / this.frm.doc.conversion_rate) : this.frm.doc.net_total_export;
this.frm.doc.other_charges_total_export = flt(this.frm.doc.grand_total_export -
this.frm.doc.net_total_export + flt(this.frm.doc.discount_amount),
precision("other_charges_total_export"));
this.frm.doc.grand_total = flt(this.frm.doc.grand_total, precision("grand_total"));
this.frm.doc.grand_total_export = flt(this.frm.doc.grand_total_export, precision("grand_total_export"));
this.frm.doc.rounded_total = Math.round(this.frm.doc.grand_total);
this.frm.doc.rounded_total_export = Math.round(this.frm.doc.grand_total_export);
},
@@ -362,17 +365,22 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
var distributed_amount = 0.0;
if (this.frm.doc.discount_amount) {
this.frm.set_value("base_discount_amount",
flt(this.frm.doc.discount_amount * this.frm.doc.conversion_rate, precision("base_discount_amount")))
var grand_total_for_discount_amount = this.get_grand_total_for_discount_amount();
// calculate item amount after Discount Amount
if (grand_total_for_discount_amount) {
$.each(this.frm.item_doclist, function(i, item) {
distributed_amount = flt(me.frm.doc.discount_amount) * item.base_amount / grand_total_for_discount_amount;
distributed_amount = flt(me.frm.doc.base_discount_amount) * item.base_amount / grand_total_for_discount_amount;
item.base_amount = flt(item.base_amount - distributed_amount, precision("base_amount", item));
});
this.discount_amount_applied = true;
this._calculate_taxes_and_totals();
}
} else {
this.frm.set_value("base_discount_amount", 0);
}
},
@@ -506,12 +514,12 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
}
});
};
setup_field_label_map(["net_total", "other_charges_total", "grand_total",
setup_field_label_map(["net_total", "other_charges_total", "base_discount_amount", "grand_total",
"rounded_total", "in_words",
"outstanding_amount", "total_advance", "paid_amount", "write_off_amount"],
company_currency);
setup_field_label_map(["net_total_export", "other_charges_total_export", "grand_total_export",
setup_field_label_map(["net_total_export", "other_charges_total_export", "discount_amount", "grand_total_export",
"rounded_total_export", "in_words_export"], this.frm.doc.currency);
cur_frm.set_df_property("conversion_rate", "description", "1 " + this.frm.doc.currency
@@ -524,7 +532,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
// toggle fields
this.frm.toggle_display(["conversion_rate", "net_total", "other_charges_total",
"grand_total", "rounded_total", "in_words"],
"grand_total", "rounded_total", "in_words", "base_discount_amount"],
this.frm.doc.currency != company_currency);
this.frm.toggle_display(["plc_conversion_rate", "price_list_currency"],
@@ -587,16 +595,18 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
});
frappe.ui.form.on(cur_frm.doctype,"project_name", function(frm) {
frappe.call({
method:'erpnext.projects.doctype.project.project.get_cost_center_name' ,
args: { project_name: frm.doc.project_name },
callback: function(r, rt) {
if(!r.exc) {
$.each(frm.doc[cur_frm.cscript.fname] || [], function(i, row) {
frappe.model.set_value(row.doctype, row.name, "cost_center", r.message);
msgprint(__("Cost Center For Item with Item Code '"+row.item_name+"' has been Changed to "+ r.message));
})
if(in_list(["Delivery Note", "Sales Invoice"], frm.doc.doctype)) {
frappe.call({
method:'erpnext.projects.doctype.project.project.get_cost_center_name' ,
args: { project_name: frm.doc.project_name },
callback: function(r, rt) {
if(!r.exc) {
$.each(frm.doc[cur_frm.cscript.fname] || [], function(i, row) {
frappe.model.set_value(row.doctype, row.name, "cost_center", r.message);
msgprint(__("Cost Center For Item with Item Code '"+row.item_name+"' has been Changed to "+ r.message));
})
}
}
}
})
})
}
})

View File

@@ -94,13 +94,19 @@ class AuthorizationControl(TransactionBase):
self.validate_auth_rule(doctype_name, auth_value, based_on, add_cond, company)
def validate_approving_authority(self, doctype_name,company, total, doc_obj = ''):
if not frappe.db.count("Authorization Rule"):
return
av_dis = 0
if doc_obj:
price_list_rate, base_rate = 0, 0
for d in doc_obj.get(doc_obj.fname):
if d.base_price_list_rate and d.base_rate:
price_list_rate += flt(d.base_price_list_rate)
if d.base_rate:
price_list_rate += flt(d.base_price_list_rate) or flt(d.base_rate)
base_rate += flt(d.base_rate)
if doc_obj.get("discount_amount"):
base_rate -= flt(doc_obj.discount_amount)
if price_list_rate: av_dis = 100 - flt(base_rate * 100 / price_list_rate)
final_based_on = ['Grand Total','Average Discount','Customerwise Discount','Itemwise Discount']

View File

@@ -1 +0,0 @@
[To deprecate] Common scripts for Contacts.

View File

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

View File

@@ -1,161 +0,0 @@
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
if(cur_frm.fields_dict['territory']) {
cur_frm.fields_dict['territory'].get_query = function(doc, dt, dn) {
return {
filters: {
'is_group': "No"
}
}
}
}
cur_frm.cscript.render_contact_row = function(wrapper, data) {
// prepare data
data.fullname = (data.first_name || '')
+ (data.last_name ? ' ' + data.last_name : '');
data.primary = data.is_primary_contact ? ' [Primary]' : '';
// prepare description
var description = [];
$.each([
['phone', 'Tel'],
['mobile_no', 'Mobile'],
['email_id', 'Email'],
['department', 'Department'],
['designation', 'Designation']],
function(i, v) {
if(v[0] && data[v[0]]) {
description.push(repl('<h6>%(label)s:</h6> %(value)s', {
label: v[1],
value: data[v[0]],
}));
}
});
data.description = description.join('<br />');
cur_frm.cscript.render_row_in_wrapper(wrapper, data, 'Contact');
}
cur_frm.cscript.render_address_row = function(wrapper, data) {
// prepare data
data.fullname = data.address_type;
data.primary = '';
if (data.is_primary_address) data.primary += ' [Preferred for Billing]';
if (data.is_shipping_address) data.primary += ' [Preferred for Shipping]';
// prepare address
var address = [];
$.each(['address_line1', 'address_line2', 'city', 'state', 'country', 'pincode'],
function(i, v) {
if(data[v]) address.push(data[v]);
});
data.address = address.join('<br />');
data.address = "<p class='address-list'>" + data.address + "</p>";
// prepare description
var description = [];
$.each([
['address', 'Address'],
['phone', 'Tel'],
['fax', 'Fax'],
['email_id', 'Email']],
function(i, v) {
if(data[v[0]]) {
description.push(repl('<h6>%(label)s:</h6> %(value)s', {
label: v[1],
value: data[v[0]],
}));
}
});
data.description = description.join('<br />');
cur_frm.cscript.render_row_in_wrapper(wrapper, data, 'Address');
$(wrapper).find('p.address-list').css({
'padding-left': '10px',
'margin-bottom': '-10px'
});
}
cur_frm.cscript.render_row_in_wrapper = function(wrapper, data, doctype) {
// render
var $wrapper = $(wrapper);
data.doctype = doctype.toLowerCase();
$wrapper.append(repl("\
<h4><a class='link_type'>%(fullname)s</a>%(primary)s</h4>\
<div class='description'>\
<p>%(description)s</p>\
<p><a class='delete link_type'>delete this %(doctype)s</a></p>\
</div>", data));
// make link
$wrapper.find('h4 a.link_type').click(function() {
loaddoc(doctype, data.name);
});
// css
$wrapper.css({ 'margin': '0px' });
$wrapper.find('div.description').css({
'padding': '5px 2px',
'line-height': '150%',
});
$wrapper.find('h6').css({ 'display': 'inline-block' });
// show delete
var $delete_doc = $wrapper.find('a.delete');
if (frappe.model.can_delete(doctype))
$delete_doc.toggle(true);
else
$delete_doc.toggle(false);
$delete_doc.css({ 'padding-left': '0px' });
$delete_doc.click(function() {
cur_frm.cscript.delete_doc(doctype, data.name);
return false;
});
}
cur_frm.cscript.delete_doc = function(doctype, name) {
// confirm deletion
var go_ahead = confirm(__("Delete {0} {1}?", [doctype, name]));
if (!go_ahead) return;
frappe.model.delete_doc(doctype, name, function(r) {
if (!r.exc) {
var list_name = doctype.toLowerCase() + '_list';
cur_frm[list_name].run();
}
});
}
// Render List
cur_frm.cscript.render_list = function(doc, doctype, wrapper, ListView, make_new_doc) {
frappe.model.with_doctype(doctype, function(r) {
if((r && r['403']) || frappe.boot.user.all_read.indexOf(doctype)===-1) {
return;
}
var RecordListView = frappe.views.RecordListView.extend({
default_docstatus: ['0', '1', '2'],
default_filters: [
[doctype, doc.doctype.toLowerCase().replace(" ", "_"), '=', doc.name],
],
});
if (make_new_doc) {
RecordListView = RecordListView.extend({
make_new_doc: make_new_doc,
});
}
var record_list_view = new RecordListView(doctype, wrapper, ListView);
if (!cur_frm[doctype.toLowerCase().replace(" ", "_") + "_list"]) {
cur_frm[doctype.toLowerCase().replace(" ", "_") + "_list"] = record_list_view;
}
});
}

View File

@@ -1,48 +0,0 @@
{
"creation": "2012-03-27 14:36:19.000000",
"docstatus": 0,
"doctype": "DocType",
"fields": [
{
"fieldname": "header",
"fieldtype": "Text",
"in_list_view": 1,
"label": "Header",
"permlevel": 0
},
{
"fieldname": "customer_intro",
"fieldtype": "Text",
"in_list_view": 1,
"label": "Customer Intro",
"permlevel": 0
},
{
"fieldname": "supplier_intro",
"fieldtype": "Text",
"in_list_view": 1,
"label": "Supplier Intro",
"permlevel": 0
}
],
"idx": 1,
"in_create": 1,
"issingle": 1,
"modified": "2013-12-20 19:23:02.000000",
"modified_by": "Administrator",
"module": "Setup",
"name": "Contact Control",
"owner": "Administrator",
"permissions": [
{
"create": 0,
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"role": "System Manager",
"write": 1
}
],
"read_only": 1
}

View File

@@ -1,10 +0,0 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
from frappe.model.document import Document
class ContactControl(Document):
pass

View File

@@ -1,12 +1,6 @@
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
{% include 'setup/doctype/contact_control/contact_control.js' %};
cur_frm.cscript.onload = function(doc,dt,dn){
}
cur_frm.cscript.refresh = function(doc,dt,dn){
if(doc.__islocal){
@@ -15,8 +9,8 @@ cur_frm.cscript.refresh = function(doc,dt,dn){
else{
unhide_field(['address_html', 'contact_html']);
// make lists
cur_frm.cscript.make_address(doc,dt,dn);
cur_frm.cscript.make_contact(doc,dt,dn);
erpnext.utils.render_address_and_contact(cur_frm)
if (doc.show_in_website) {
cur_frm.set_intro(__("Published on website at: {0}",
@@ -25,57 +19,6 @@ cur_frm.cscript.refresh = function(doc,dt,dn){
}
}
cur_frm.cscript.make_address = function() {
if(!cur_frm.address_list) {
cur_frm.address_list = new frappe.ui.Listing({
parent: cur_frm.fields_dict['address_html'].wrapper,
page_length: 2,
new_doctype: "Address",
custom_new_doc: function(doctype) {
var address = frappe.model.make_new_doc_and_get_name('Address');
address = locals['Address'][address];
address.sales_partner = cur_frm.doc.name;
address.address_title = cur_frm.doc.name;
address.address_type = "Office";
frappe.set_route("Form", "Address", address.name);
},
get_query: function() {
return "select name, address_type, address_line1, address_line2, city, state, country, pincode, fax, email_id, phone, is_primary_address, is_shipping_address from tabAddress where sales_partner='" +
cur_frm.doc.name.replace(/'/g, "\\'") + "' and docstatus != 2 order by is_primary_address desc"
},
as_dict: 1,
no_results_message: __('No addresses created'),
render_row: cur_frm.cscript.render_address_row,
});
}
cur_frm.address_list.run();
}
cur_frm.cscript.make_contact = function() {
if(!cur_frm.contact_list) {
cur_frm.contact_list = new frappe.ui.Listing({
parent: cur_frm.fields_dict['contact_html'].wrapper,
page_length: 2,
new_doctype: "Contact",
custom_new_doc: function(doctype) {
var contact = frappe.model.make_new_doc_and_get_name('Contact');
contact = locals['Contact'][contact];
contact.sales_partner = cur_frm.doc.name;
frappe.set_route("Form", "Contact", contact.name);
},
get_query: function() {
return "select name, first_name, last_name, email_id, phone, mobile_no, department, designation, is_primary_contact from tabContact where sales_partner='" +
cur_frm.doc.name.replace(/'/g, "\\'") + "' and docstatus != 2 order by is_primary_contact desc"
},
as_dict: 1,
no_results_message: __('No contacts created'),
render_row: cur_frm.cscript.render_contact_row,
});
}
cur_frm.contact_list.run();
}
cur_frm.fields_dict['partner_target_details'].grid.get_field("item_group").get_query = function(doc, dt, dn) {
return{
filters:{ 'is_group': "No" }

View File

@@ -5,11 +5,16 @@ from __future__ import unicode_literals
import frappe
from frappe.utils import cstr, filter_strip_join
from frappe.website.website_generator import WebsiteGenerator
from erpnext.utilities.address_and_contact import load_address_and_contact
class SalesPartner(WebsiteGenerator):
page_title_field = "partner_name"
condition_field = "show_in_website"
template = "templates/generators/sales_partner.html"
def onload(self):
"""Load address and contacts in `__onload`"""
load_address_and_contact(self, "sales_partner")
def autoname(self):
self.name = self.partner_name

View File

@@ -59,15 +59,31 @@ frappe.pages['setup-wizard'].onload = function(wrapper) {
title: __("Select Your Language"),
icon: "icon-globe",
fields: [
{"fieldname": "language", "label": __("Language"), "fieldtype": "Select",
options: ["english", "العربية", "deutsch", "ελληνικά", "español", "français", "हिंदी", "hrvatski",
"italiano", "nederlands", "polski", "português brasileiro", "português", "српски", "தமிழ்",
"ไทย", "中国(简体)", "中國(繁體)"], reqd:1},
{
"fieldname": "language", "label": __("Language"), "fieldtype": "Select",
reqd:1
},
],
help: __("Welcome to ERPNext. Please select your language to begin the Setup Wizard."),
onload: function(slide) {
var me = this;
if (!this.language_list) {
frappe.call({
method: "erpnext.setup.page.setup_wizard.setup_wizard.load_languages",
callback: function(r) {
me.language_list = r.message;
slide.get_input("language")
.add_options(r.message)
.val("english");
}
})
} else {
slide.get_input("language").add_options(this.language_list);
}
slide.get_input("language").on("change", function() {
var lang = $(this).val();
var lang = $(this).val() || "english";
frappe._messages = {};
frappe.call({
method: "erpnext.setup.page.setup_wizard.setup_wizard.load_messages",

View File

@@ -71,7 +71,7 @@ def setup_account(args=None):
frappe.db.set_default('desktop:home_page', 'desktop')
website_maker(args.company_name, args.company_tagline, args.name)
website_maker(args.company_name.strip(), args.company_tagline, args.name)
create_logo(args)
frappe.clear_cache()
@@ -135,7 +135,7 @@ def create_fiscal_year_and_company(args):
frappe.get_doc({
"doctype":"Company",
'domain': args.get("industry"),
'company_name':args.get('company_name'),
'company_name':args.get('company_name').strip(),
'abbr':args.get('company_abbr'),
'default_currency':args.get('currency'),
'country': args.get('country'),
@@ -166,7 +166,7 @@ def set_defaults(args):
global_defaults.update({
'current_fiscal_year': args.curr_fiscal_year,
'default_currency': args.get('currency'),
'default_company':args.get('company_name'),
'default_company':args.get('company_name').strip(),
"country": args.get("country"),
})
@@ -285,7 +285,7 @@ def create_taxes(args):
try:
frappe.get_doc({
"doctype":"Account",
"company": args.get("company_name"),
"company": args.get("company_name").strip(),
"parent_account": _("Duties and Taxes") + " - " + args.get("company_abbr"),
"account_name": args.get("tax_" + str(i)),
"group_or_ledger": "Ledger",
@@ -345,7 +345,7 @@ def create_customers(args):
"customer_type": "Company",
"customer_group": _("Commercial"),
"territory": args.get("country"),
"company": args.get("company_name")
"company": args.get("company_name").strip()
}).insert()
if args.get("customer_contact_" + str(i)):
@@ -365,7 +365,7 @@ def create_suppliers(args):
"doctype":"Supplier",
"supplier_name": supplier,
"supplier_type": _("Local"),
"company": args.get("company_name")
"company": args.get("company_name").strip()
}).insert()
if args.get("supplier_contact_" + str(i)):
@@ -434,4 +434,6 @@ def load_messages(language):
send_translations(m)
return lang
@frappe.whitelist()
def load_languages():
return sorted(get_lang_dict().keys())

View File

@@ -23,7 +23,7 @@ class Bin(Document):
if (not getattr(self, f, None)) or (not self.get(f)):
self.set(f, 0.0)
def update_stock(self, args):
def update_stock(self, args, allow_negative_stock=False):
self.update_qty(args)
if args.get("actual_qty") or args.get("voucher_type") == "Stock Reconciliation":
@@ -38,7 +38,7 @@ class Bin(Document):
"warehouse": self.warehouse,
"posting_date": args.get("posting_date"),
"posting_time": args.get("posting_time")
})
}, allow_negative_stock=allow_negative_stock)
def update_qty(self, args):
# update the stock values (for current quantities)

View File

@@ -178,7 +178,7 @@
{
"fieldname": "po_no",
"fieldtype": "Data",
"hidden": 1,
"hidden": 0,
"label": "Customer's Purchase Order No",
"no_copy": 0,
"oldfieldname": "po_no",
@@ -434,6 +434,15 @@
"fieldtype": "Section Break",
"permlevel": 0
},
{
"fieldname": "other_charges_total_export",
"fieldtype": "Currency",
"label": "Taxes and Charges Total",
"options": "Company:company:default_currency",
"permlevel": 0,
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "other_charges_total",
"fieldtype": "Currency",
@@ -452,22 +461,23 @@
"fieldtype": "Column Break",
"permlevel": 0
},
{
"fieldname": "other_charges_total_export",
"fieldtype": "Currency",
"label": "Taxes and Charges Total",
"options": "Company:company:default_currency",
"permlevel": 0,
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "discount_amount",
"fieldtype": "Currency",
"label": "Discount Amount",
"options": "Company:company:default_currency",
"options": "currency",
"permlevel": 0
},
{
"fieldname": "base_discount_amount",
"fieldtype": "Currency",
"label": "Discount Amount (Company Currency)",
"options": "Company:company:default_currency",
"permlevel": 0,
"precision": "",
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "totals",
"fieldtype": "Section Break",
@@ -1013,7 +1023,7 @@
"idx": 1,
"in_create": 0,
"is_submittable": 1,
"modified": "2014-09-09 05:35:30.700911",
"modified": "2015-01-12 16:56:39.975961",
"modified_by": "Administrator",
"module": "Stock",
"name": "Delivery Note",

View File

@@ -52,11 +52,15 @@ class DeliveryNote(SellingController):
else:
df.delete_key("__print_hide")
toggle_print_hide(self.meta, "currency")
item_meta = frappe.get_meta("Delivery Note Item")
for fieldname in ("rate", "amount", "price_list_rate", "discount_percentage"):
toggle_print_hide(item_meta, fieldname)
print_hide_fields = {
"parent": ["grand_total_export", "rounded_total_export", "in_words_export", "currency", "net_total_export"],
"items": ["rate", "amount", "price_list_rate", "discount_percentage"]
}
for key, fieldname in print_hide_fields.items():
for f in fieldname:
toggle_print_hide(self.meta if key == "parent" else item_meta, f)
def get_portal_page(self):
return "shipment" if self.docstatus==1 else None
@@ -245,7 +249,7 @@ class DeliveryNote(SellingController):
sl_entries = []
for d in self.get_item_list():
if frappe.db.get_value("Item", d.item_code, "is_stock_item") == "Yes" \
and d.warehouse:
and d.warehouse and flt(d['qty']):
self.update_reserved_qty(d)
sl_entries.append(self.get_sl_entries(d, {
@@ -377,7 +381,8 @@ def make_packing_slip(source_name, target_doc=None):
"Delivery Note": {
"doctype": "Packing Slip",
"field_map": {
"name": "delivery_note"
"name": "delivery_note",
"letter_head": "letter_head"
},
"validation": {
"docstatus": ["=", 0]

View File

@@ -229,7 +229,7 @@ class Item(WebsiteGenerator):
if not frappe.db.exists("Item", newdn):
frappe.throw(_("Item {0} does not exist").format(newdn))
field_list = ["stock_uom", "is_stock_item", "has_serial_no", "has_batch_no"]
field_list = ["stock_uom", "is_stock_item", "has_serial_no", "has_batch_no", "is_manufactured_item"]
new_properties = [cstr(d) for d in frappe.db.get_value("Item", newdn, field_list)]
if new_properties != [cstr(self.get(fld)) for fld in field_list]:
frappe.throw(_("To merge, following properties must be same for both items")

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