Compare commits

...

213 Commits

Author SHA1 Message Date
Pratik Vyas
8c78a1abb7 Merge branch 'develop' 2014-01-27 17:19:45 +05:30
Pratik Vyas
8821541f33 bumped to version 3.7.0 2014-01-27 17:49:45 +06:00
Nabin Hait
5cec7ec84a Merge pull request #1355 from akhileshdarjee/hotfix
Allow rename for price list
2014-01-27 02:40:08 -08:00
Nabin Hait
9536f112b5 Merge pull request #1358 from nabinhait/hotfix
Serial no and planned qty
2014-01-27 01:33:56 -08:00
Nabin Hait
44a40b860e Fixed planned qty bug and patch to recalculate planned qty 2014-01-27 15:02:30 +05:30
Nabin Hait
b3d26c08f6 Fixed planned qty bug and patch to recalculate planned qty 2014-01-27 14:58:55 +05:30
Nabin Hait
fa9fabaa49 Serial no status fix: patch to set status not available where no sle exists 2014-01-27 12:46:18 +05:30
Akhilesh Darjee
49e8e783e3 webnotes/erpnext#1353 allow rename for price list 2014-01-27 11:12:24 +05:30
Anand Doshi
c4ee74857d BugFix: Production Planning Tool - get_raw_materials 2014-01-24 21:53:11 +05:30
Anand Doshi
fc13b87fd5 Fixes in Make Demo 2014-01-24 18:54:50 +05:30
Anand Doshi
d9ba544e09 Fix in Item Test Case 2014-01-24 15:59:05 +05:30
Nabin Hait
af21479665 Merge pull request #1342 from akhileshdarjee/hotfix
Item List refresh when price list changed in POS
2014-01-23 05:14:16 -08:00
Nabin Hait
eec59ae7c4 Merge pull request #1345 from nabinhait/hotfix
Order preview through customer login
2014-01-23 01:48:28 -08:00
Nabin Hait
efa9a7ed5b Merge branch 'develop' of github.com:webnotes/erpnext into hotfix 2014-01-23 13:25:39 +05:30
Nabin Hait
557abdebe0 order preview through customer login 2014-01-23 13:25:26 +05:30
Akhilesh Darjee
8589b1db22 Use model set_value for updating values from POS 2014-01-22 19:25:51 +05:30
Akhilesh Darjee
82a21beba0 Item List refresh when price list changed in POS 2014-01-22 16:55:32 +05:30
Pratik Vyas
256c4da0a5 Merge branch 'develop' 2014-01-22 16:03:07 +05:30
Pratik Vyas
7395dc9969 bumped to version 3.6.6 2014-01-22 16:33:07 +06:00
Nabin Hait
d39bc09e62 Merge pull request #1341 from nabinhait/hotfix
Small fix
2014-01-22 02:21:17 -08:00
Nabin Hait
c7676797e1 Dont display old fraction outstanding in AR report 2014-01-22 15:36:44 +05:30
Nabin Hait
423932fab2 Fixes in general ledger opening 2014-01-22 11:53:44 +05:30
Nabin Hait
efda5b0d36 Merge branch 'develop' of github.com:webnotes/erpnext into hotfix 2014-01-21 20:58:10 +05:30
Nabin Hait
13a9e27320 Fixes in warehouse merge function 2014-01-21 20:57:39 +05:30
Pratik Vyas
b0433d96a3 Merge branch 'develop' 2014-01-21 12:09:31 +05:30
Pratik Vyas
f3aba2e536 bumped to version 3.6.5 2014-01-21 12:39:31 +06:00
Nabin Hait
1594f102fd Merge pull request #1340 from nabinhait/hotfix
General ledger
2014-01-20 22:29:33 -08:00
Nabin Hait
b2f2df4c64 General ledger: opening balance issue fixed 2014-01-21 11:58:17 +05:30
Nabin Hait
9f6c48d82e Merge branch 'develop' of github.com:webnotes/erpnext into hotfix 2014-01-21 10:44:16 +05:30
Pratik Vyas
f0307dc75e Merge branch 'develop' 2014-01-20 19:21:25 +05:30
Pratik Vyas
872e4d1f3d bumped to version 3.6.4 2014-01-20 19:51:25 +06:00
Nabin Hait
b164e606f9 Merge pull request #1337 from nabinhait/hotfix
Hotfix
2014-01-20 05:00:43 -08:00
Nabin Hait
806343395a Merge branch 'develop' of github.com:webnotes/erpnext into hotfix 2014-01-20 18:29:48 +05:30
Nabin Hait
afe93d633c Increased remarks width in general ledger 2014-01-20 18:28:48 +05:30
Nabin Hait
cd20717c3d Merge pull request #1336 from akhileshdarjee/disable-price-list
Enabled feature for Price List
2014-01-20 04:47:10 -08:00
Akhilesh Darjee
529709e08b patch for enabling all price list 2014-01-20 16:39:03 +05:30
Akhilesh Darjee
e82eee512b Enabled feature in Price List 2014-01-20 16:09:45 +05:30
Nabin Hait
ee0c623760 Merge branch 'develop' of github.com:webnotes/erpnext into hotfix 2014-01-20 10:57:12 +05:30
Nabin Hait
dbb4955483 Merge pull request #1332 from akhileshdarjee/hotfix
decimal places fix in item prices report
2014-01-17 20:18:30 -08:00
Akhilesh Darjee
ed87335513 decimal places fix in item prices report 2014-01-17 18:57:21 +05:30
Akhilesh Darjee
8a4111fe0e decimal places fixed in item prices report 2014-01-17 18:50:44 +05:30
Pratik Vyas
4bfa8d560b Merge branch 'develop' 2014-01-17 16:56:31 +05:30
Pratik Vyas
96db41d996 bumped to version 3.6.3 2014-01-17 17:26:31 +06:00
Nabin Hait
9a74330d6f Merge pull request #1330 from pdvyas/fix-mysql-installer
remove mysql-python pinning to 1.2.4
2014-01-17 02:37:25 -08:00
Nabin Hait
1951baca57 Merge pull request #1319 from pdvyas/about-version
update about erpnext with version number
2014-01-17 02:36:11 -08:00
Pratik Vyas
da08124df2 remove mysql-python pinning to 1.2.4 2014-01-17 15:27:19 +05:30
Nabin Hait
2aecc5a717 Merge pull request #1329 from nabinhait/hotfix
Patch for updating billing status for old zero value order
2014-01-17 01:41:40 -08:00
Nabin Hait
a37ffe162b Merge branch 'develop' of github.com:webnotes/erpnext into hotfix 2014-01-17 12:05:06 +05:30
Nabin Hait
bc99c9d6e0 Priority to user's deafult price list over customer's default price list 2014-01-17 12:04:24 +05:30
Nabin Hait
f32314dd0b Do not set income/expense account automatically in company master 2014-01-17 11:53:25 +05:30
Nabin Hait
7e73f35916 Merge pull request #1327 from akhileshdarjee/hotfix
Allow renaming of campaign
2014-01-16 21:48:10 -08:00
Akhilesh Darjee
e1e63a91d6 Allow renaming of campaign 2014-01-17 11:12:20 +05:30
Nabin Hait
9a05aad8ea Merge branch 'develop' of github.com:webnotes/erpnext into hotfix 2014-01-17 10:31:43 +05:30
Nabin Hait
f6b77479d7 Patch: Update billing status for zero value order 2014-01-16 18:18:49 +05:30
Pratik Vyas
3c279163fc Merge branch 'develop' 2014-01-16 16:29:22 +05:30
Pratik Vyas
6933617538 bumped to version 3.6.2 2014-01-16 16:59:22 +06:00
Nabin Hait
2648661757 Merge pull request #1326 from nabinhait/hotfix
Calculate taxes and charges total in server side
2014-01-16 01:28:33 -08:00
Nabin Hait
e31a97f355 Calculate taxes and charges total in server side 2014-01-16 14:24:32 +05:30
Nabin Hait
6bdb73c392 Merge pull request #1324 from nabinhait/hotfix
Minor Fix
2014-01-15 22:44:25 -08:00
Nabin Hait
deda7e2c75 Merge branch 'develop' of github.com:webnotes/erpnext into hotfix 2014-01-16 12:08:36 +05:30
Nabin Hait
5cdb8cea13 Reset filters in Item Price report on each route 2014-01-16 12:08:12 +05:30
Nabin Hait
90a8c9e636 Merge pull request #1323 from nabinhait/hotfix
Billing status for zero value SO/PO
2014-01-15 05:20:51 -08:00
Nabin Hait
c0c951b6a9 Merge branch 'develop' of github.com:webnotes/erpnext into hotfix 2014-01-15 17:36:34 +05:30
Nabin Hait
39eb7faeb9 Update billing percentage and status from SI/PI in SO/PO, when net total is zero 2014-01-15 17:36:18 +05:30
Nabin Hait
4829ad3eb8 Merge pull request #1321 from akhileshdarjee/hotfix
Hide fields fix
2014-01-15 03:17:23 -08:00
Akhilesh Darjee
a682d45846 webnotes/erpnext # 1320 - hide fields fix 2014-01-15 16:39:01 +05:30
Pratik Vyas
76dd468f0e update about erpnext with version number 2014-01-15 14:23:38 +05:30
Nabin Hait
a6df26839d Higher priority to user's default price list over customer's default price list 2014-01-15 12:21:14 +05:30
Nabin Hait
c5d4fc38aa Fixes in monthly salary register 2014-01-15 10:54:07 +05:30
Pratik Vyas
02f7e83bd1 Merge branch 'develop' 2014-01-14 18:49:14 +05:30
Pratik Vyas
f55d9414cd bumped to version 3.6.1 2014-01-14 19:19:14 +06:00
Nabin Hait
5644ed37a4 Merge pull request #1316 from nabinhait/hotfix
rounding and divisional loss
2014-01-14 05:05:33 -08:00
Nabin Hait
ee6200576a Highest priority to user properties while fetching warehouse from item 2014-01-14 18:34:10 +05:30
Nabin Hait
eeb8ba18cd Merge branch 'develop' of github.com:webnotes/erpnext into hotfix 2014-01-14 17:44:47 +05:30
Nabin Hait
3a19370892 Rounding issue and divisional loss adjustment 2014-01-14 17:44:34 +05:30
Nabin Hait
6dc1ba6f7f Merge pull request #1314 from nabinhait/hotfix
comment fix
2014-01-14 02:29:39 -08:00
Nabin Hait
d91af2853e Allowed import for customer issue 2014-01-14 15:56:52 +05:30
Nabin Hait
d23ae108ae Fixes in Comment, if comment by not mentioned, consider owner 2014-01-14 15:52:09 +05:30
Pratik Vyas
72f8ae2d5a Merge branch 'develop' 2014-01-13 18:37:07 +05:30
Pratik Vyas
1e347910d5 bumped to version 3.6.0 2014-01-13 19:07:07 +06:00
Nabin Hait
25cfb700bb Merge pull request #1311 from akhileshdarjee/hotfix
Increase and decrease quantity buttons in POS
2014-01-13 04:33:50 -08:00
Nabin Hait
8d2d4e82fd Merge pull request #1302 from nabinhait/hotfix
Hotfix
2014-01-13 04:33:18 -08:00
Nabin Hait
c43d58ac79 Delete Property Setters for Custom Fields, and set them inside Custom Field 2014-01-13 17:55:24 +05:30
Akhilesh Darjee
0b3c10601c Increase and decrease quantity buttons in POS 2014-01-13 13:34:34 +05:30
Nabin Hait
14bf711d04 Fixes in frozen accounts validation 2014-01-13 13:28:07 +05:30
Nabin Hait
35a9d585b4 Bank Reconciliation Statement: Show balance in debit or credit column based on account type 2014-01-13 12:24:27 +05:30
Nabin Hait
38e56eeb45 Merge branch 'develop' of github.com:webnotes/erpnext into hotfix 2014-01-13 12:23:29 +05:30
Nabin Hait
3dd1043d5e Merge pull request #1301 from akhileshdarjee/hotfix
pos view showing inclusive taxes
2014-01-10 03:09:12 -08:00
Nabin Hait
55387aa931 Fixed conflict 2014-01-10 16:31:48 +05:30
Nabin Hait
03463ef73b Move related property setters to custom field property 2014-01-10 16:28:41 +05:30
Akhilesh Darjee
371663169c pos view showing inclusive taxes 2014-01-10 15:05:44 +05:30
Nabin Hait
f3ded044e0 Monthly Salary Register: Month is now optional 2014-01-09 17:38:50 +05:30
Nabin Hait
68b0d54b4b Set default accounts in company related to perpetual inventory, only it is enabled 2014-01-09 17:25:55 +05:30
Pratik Vyas
e4a71935eb Merge branch 'develop' 2014-01-09 15:56:53 +05:30
Pratik Vyas
3e846d19d4 bumped to version 3.5.1 2014-01-09 16:26:53 +06:00
Nabin Hait
5411ece766 Merge pull request #1299 from nabinhait/hotfix
Accounts Receivable fix for partial payment in pos
2014-01-09 02:25:12 -08:00
Nabin Hait
aeb68b2899 Accounts Receivable fix for partial payment in pos 2014-01-09 15:54:18 +05:30
Pratik Vyas
0064dc6f4a Merge branch 'develop' 2014-01-09 15:52:09 +05:30
Pratik Vyas
11bf06ad76 bumped to version 3.5.0 2014-01-09 16:22:09 +06:00
Nabin Hait
5c6a2acff7 Merge pull request #1298 from nabinhait/hotfix
Accounts Receivable fix for partial payment in pos
2014-01-09 02:20:06 -08:00
Nabin Hait
cdbd4218a8 Accounts Receivable fix for partial payment in pos 2014-01-09 15:49:26 +05:30
Nabin Hait
701cddfb15 Merge pull request #1297 from nabinhait/hotfix
Hotfix
2014-01-08 23:18:54 -08:00
Nabin Hait
4bbf91bea1 Added match condition in general ledger report 2014-01-09 12:44:44 +05:30
Nabin Hait
e481e81e67 Merge pull request #1296 from akhileshdarjee/hotfix
POS print format fixed
2014-01-08 22:23:56 -08:00
Anand Doshi
102b417b52 Fix: Typo on patch 2014-01-09 11:39:10 +05:30
Akhilesh Darjee
efc2a45835 merge conflict fixed 2014-01-08 19:42:17 +05:30
Akhilesh Darjee
5c119a7e95 Merge branch 'master' of github.com:webnotes/erpnext into hotfix 2014-01-08 19:36:26 +05:30
Akhilesh Darjee
f7a102ffe3 POS print format fixed 2014-01-08 19:35:01 +05:30
Nabin Hait
d659343541 Payment Reconciliation: Fix for outstanding voucher query 2014-01-08 17:29:23 +05:30
Nabin Hait
dbf5e54eab Merge pull request #1290 from akhileshdarjee/price-list
Price List and Item Price : Valid for Buying and Selling as separate check box
2014-01-07 21:49:52 -08:00
Pratik Vyas
5eb139a531 Merge branch 'develop' 2014-01-07 21:45:04 +05:30
Pratik Vyas
9e2358c544 bumped to version 3.4.9 2014-01-07 22:15:04 +06:00
Akhilesh Darjee
8d0ef21911 pos invoice print format changes 2014-01-07 19:45:33 +05:30
Pratik Vyas
9a8f37c579 Merge pull request #1289 from pdvyas/hotfix-installer
fix installer python packages issue
2014-01-07 06:14:08 -08:00
Akhilesh Darjee
029f698c65 patch for item price and price list 2014-01-07 19:43:35 +05:30
Akhilesh Darjee
806017c92a Price List and Item Price : Validfor Buying and Selling as separate check box 2014-01-07 18:37:38 +05:30
Pratik Vyas
69951e5d1c fix installer python packages issue 2014-01-07 18:24:40 +05:30
Nabin Hait
10fd91c78e Close tickets automatically through scheduler 2014-01-07 16:18:41 +05:30
Pratik Vyas
63d71d7f2f Merge branch 'develop' 2014-01-07 13:47:44 +05:30
Pratik Vyas
777bff6e8d bumped to version 3.4.8 2014-01-07 14:17:44 +06:00
Nabin Hait
1e42a3d028 Merge pull request #1287 from nabinhait/hotfix
Fixes in overbilling validation against DN/PR
2014-01-06 23:12:45 -08:00
Nabin Hait
da282d405f Fixes in overbilling validation against DN/PR 2014-01-07 12:41:09 +05:30
Nabin Hait
8f1bb82ab9 Merge pull request #1286 from nabinhait/hotfix
Removed unwanted debug
2014-01-06 22:40:54 -08:00
Anand Doshi
f2b46635b5 Merge pull request #1285 from pdvyas/hotfix-installer
fix branching, pip version and mysql-python version pinning in install_erpnext
2014-01-06 22:35:49 -08:00
Pratik Vyas
a11e14424c fix branching, pip version and mysql-python version pinning in install_erpnext 2014-01-07 12:03:09 +05:30
Nabin Hait
01441ef37f Removed unwanted debug 2014-01-07 11:59:36 +05:30
Nabin Hait
cb665285db Merge pull request #1280 from nabinhait/hotfix
Fixes in item-wise sales/purchase register
2014-01-06 03:03:02 -08:00
Nabin Hait
6b66c387ad Fixes in item-wise sales/purchase register 2014-01-06 16:28:17 +05:30
Nabin Hait
5e702de710 Merge pull request #1279 from akhileshdarjee/hotfix
accounts payable fixed
2014-01-05 23:01:51 -08:00
Akhilesh Darjee
7e79f300a1 accounts payable fixed 2014-01-06 12:23:29 +05:30
Pratik Vyas
955902ccad Merge branch 'develop' 2014-01-06 12:18:58 +05:30
Pratik Vyas
b882fa14f4 bumped to version 3.4.7 2014-01-06 12:48:58 +06:00
Nabin Hait
d12d7142c6 Merge pull request #1278 from nabinhait/hotfix
Fixes in overbilling validation
2014-01-05 22:35:10 -08:00
Nabin Hait
42db5d76a9 Fixes in overbilling validation 2014-01-06 11:20:37 +05:30
Pratik Vyas
bd4030bf85 Merge branch 'develop' 2014-01-03 18:40:11 +05:30
Pratik Vyas
a83337a2dd bumped to version 3.4.6 2014-01-03 19:10:11 +06:00
Nabin Hait
e51e5238ec Merge pull request #1267 from nabinhait/hotfix
Hotfix
2014-01-03 04:59:34 -08:00
Nabin Hait
5d5fe5d9d5 Cost center field added in Purchase Receipt Item table 2014-01-03 18:28:53 +05:30
Nabin Hait
b476c989a4 Fixes test cases for date and year mismatch 2014-01-03 17:43:52 +05:30
Nabin Hait
7f0406f281 Chekc over billing validation considering tolerance 2014-01-03 17:43:19 +05:30
Nabin Hait
33f6b9d6e8 Unlinked message listing all linked entries while cancelling an accounting trandsaction 2014-01-03 15:12:16 +05:30
Pratik Vyas
c196037cb0 Merge branch 'develop' 2014-01-03 13:27:06 +05:30
Pratik Vyas
866103bf66 bumped to version 3.4.5 2014-01-03 13:57:06 +06:00
Nabin Hait
528eb4e4ff Merge pull request #1264 from akhileshdarjee/hotfix
fixed accounts receivable for customer name
2014-01-02 23:53:30 -08:00
Nabin Hait
481454298d Merge pull request #1265 from nabinhait/hotfix
Fixes in general ledger report
2014-01-02 23:53:15 -08:00
Akhilesh Darjee
8a0b7cece1 accounts receivable fixed 2014-01-03 13:21:38 +05:30
Akhilesh Darjee
b4eba77f7b fixed accounts receivable 2014-01-03 12:58:04 +05:30
Akhilesh Darjee
b0a9581e59 fixed accounts receivable for customer name 2014-01-03 12:44:00 +05:30
Nabin Hait
6472bdace2 Fixes in general ledger report 2014-01-03 12:30:24 +05:30
Nabin Hait
c95b9f9221 Merge pull request #1263 from nabinhait/hotfix
Hotfix
2014-01-02 22:44:24 -08:00
Nabin Hait
a4db83a934 Fixes in valuation rate calculation in purchase receipt 2014-01-03 12:13:18 +05:30
Nabin Hait
28acaeb345 Fixes in valuation rate calculation in purchase receipt 2014-01-03 11:16:16 +05:30
Pratik Vyas
5fbb757c2c Merge branch 'develop' 2014-01-02 17:12:01 +05:30
Pratik Vyas
df07c964f7 bumped to version 3.4.4 2014-01-02 17:42:01 +06:00
Nabin Hait
0e2a088ac4 Merge pull request #1260 from nabinhait/hotfix
Hotfix
2014-01-02 03:02:56 -08:00
Nabin Hait
ffc2f8885b Merge branch 'develop' of github.com:webnotes/erpnext into hotfix 2014-01-02 16:30:38 +05:30
Nabin Hait
a1ffacaf0b Valuation related charges should only go to stock items 2014-01-02 16:30:16 +05:30
Pratik Vyas
8c52258e6d Merge branch 'develop' 2013-12-31 14:12:36 +05:30
Pratik Vyas
ffe8af3f2f bumped to version 3.4.3 2013-12-31 14:42:36 +06:00
Nabin Hait
fe5728718f Merge pull request #1251 from nabinhait/hotfix
Hotfix
2013-12-30 21:02:20 -08:00
Nabin Hait
424b4a4b36 Supplier bill info in accounts payable report 2013-12-31 10:24:28 +05:30
Nabin Hait
2a3d7e660f Fixes in general ledger report 2013-12-30 20:28:23 +05:30
Pratik Vyas
a0a43ca4e4 Merge branch 'develop' 2013-12-30 19:34:38 +05:30
Pratik Vyas
9cd9836e18 bumped to version 3.4.2 2013-12-30 20:04:38 +06:00
Pratik Vyas
39a3f50732 Merge branch 'develop' 2013-12-30 18:58:03 +05:30
Pratik Vyas
ba7221c332 bumped to version 3.4.1 2013-12-30 19:28:03 +06:00
Pratik Vyas
6a45588a2c Merge branch 'develop' 2013-12-30 17:48:01 +05:30
Pratik Vyas
ab9d755e4d bumped to version 3.4.0 2013-12-30 18:18:01 +06:00
Nabin Hait
1cf8bd8767 Merge pull request #1246 from nabinhait/hotfix
General Ledger and more
2013-12-30 03:44:41 -08:00
Nabin Hait
a4f99428d7 Fixes in time log batch 2013-12-27 17:36:17 +05:30
Nabin Hait
e761fe89e2 Stock Entry catch exceptions for testcase 2013-12-27 17:35:39 +05:30
Nabin Hait
d51f805b78 Rewritten General Ledger report with grouping functions 2013-12-27 17:33:55 +05:30
Nabin Hait
9a064e9ced Merge pull request #1233 from nabinhait/hotfix
Removed country field from Search Fields
2013-12-25 01:01:17 -08:00
Nabin Hait
9dc1b00d87 Removed country field from Search Fields 2013-12-25 12:28:54 +05:30
Pratik Vyas
9373ba96d5 Merge branch 'develop' 2013-12-24 13:12:21 +05:30
Pratik Vyas
a402079cd4 bumped to version 3.3.8 2013-12-24 13:42:21 +06:00
Nabin Hait
2ca388b0a5 Merge pull request #1232 from nabinhait/hotfix
Hotfix
2013-12-23 23:29:00 -08:00
Nabin Hait
6ebcc5c006 Change parent account of warehouse from inside the warehouse 2013-12-24 12:14:12 +05:30
Nabin Hait
6a2edee914 Fixes in general ledger report 2013-12-24 11:58:05 +05:30
Nabin Hait
de69ad0a48 Merge pull request #1230 from akhileshdarjee/hotfix
[fix] [minor] update item_name and description in item price
2013-12-23 22:09:13 -08:00
Akhilesh Darjee
25a4bd02f4 [fix] [minor] update item_name and description in item price 2013-12-24 11:32:57 +05:30
Nabin Hait
a3d058938e Company mandatory validation while enabling perpetual inventory 2013-12-24 11:03:04 +05:30
Nabin Hait
4cae8a0d54 Fixes in stock ledger report 2013-12-24 10:47:34 +05:30
Nabin Hait
454b6f9f8a Merge pull request #1229 from nabinhait/hotfix
Fixes in sales return validation
2013-12-23 07:05:08 -08:00
Nabin Hait
9f1b59dfc6 Fixes in sales return validation 2013-12-23 20:34:09 +05:30
Pratik Vyas
74f64b67db Merge branch 'develop' 2013-12-23 17:31:22 +05:30
Pratik Vyas
2117afba07 bumped to version 3.3.7 2013-12-23 18:01:22 +06:00
Nabin Hait
e409d0d70b Merge pull request #1227 from akhileshdarjee/hotfix
[fix] [minor] update item price on change of item details
2013-12-23 03:42:08 -08:00
Nabin Hait
50125b35d2 Merge pull request #1228 from nabinhait/hotfix
Hotfix
2013-12-23 03:41:13 -08:00
Nabin Hait
c38527ef5f Show general/stock ledger button links to new query reports 2013-12-23 17:07:57 +05:30
Nabin Hait
facde47c6c Stock ledger report filter by item and brand 2013-12-23 17:06:46 +05:30
Nabin Hait
20dc79ac99 General ledger filter by account group 2013-12-23 17:06:10 +05:30
Akhilesh Darjee
61da43f793 [fix] [minor] update modified date and time to item price when updating item and price list 2013-12-23 16:24:33 +05:30
Akhilesh Darjee
af30c3fdfd [fix] [minor] update item price on change of item details 2013-12-23 16:13:42 +05:30
Pratik Vyas
68888a21ec Merge branch 'develop' 2013-12-23 14:41:05 +05:30
Pratik Vyas
7d7661c9ed bumped to version 3.3.6 2013-12-23 15:11:05 +06:00
Nabin Hait
fbda00eef0 Merge pull request #1225 from nabinhait/hotfix
Fixes in Stock ageing report
2013-12-22 22:53:13 -08:00
Nabin Hait
a0212d8014 Fixes in Stock ageing report 2013-12-23 12:21:14 +05:30
Nabin Hait
c8d2604afc Merge pull request #1224 from nabinhait/hotfix
Incoming rate for stock ledger entry should not be rounded
2013-12-22 22:50:41 -08:00
Nabin Hait
861453279d Incoming rate for stock ledger entry should not be rounded 2013-12-23 12:14:45 +05:30
Pratik Vyas
be96600c1c Merge branch 'develop' 2013-12-20 15:15:45 +05:30
Pratik Vyas
8709c51e84 bumped to version 3.3.5 2013-12-20 15:45:45 +06:00
Pratik Vyas
6fc0262cb6 Merge pull request #1220 from nabinhait/hotfix
Fixes in stock projected qty report
2013-12-20 01:36:27 -08:00
Nabin Hait
4b5ced03ec Fixes in merge functions 2013-12-20 12:26:48 +05:30
Nabin Hait
a888e29b0a Fixes in stock projected qty report 2013-12-20 12:18:37 +05:30
Pratik Vyas
ae2e8996b0 Merge branch 'develop' 2013-12-19 19:18:57 +05:30
Pratik Vyas
1c2bbd77a0 bumped to version 3.3.4 2013-12-19 19:48:56 +06:00
Nabin Hait
2ffba327ac Merge pull request #1218 from nabinhait/hotfix
Opening and closing balance in general ledger report
2013-12-19 05:48:07 -08:00
Pratik Vyas
4764f3ea1d Merge pull request #1217 from pdvyas/patch-reload-packed_item
reload packed item in patch, for migration from slow branch
2013-12-19 05:46:52 -08:00
Pratik Vyas
104deeebb5 reload packed item in patch, for migration from slow branch 2013-12-19 19:16:00 +05:30
Nabin Hait
2a9e4e9a32 Opening and closing balance in general ledger report 2013-12-19 19:11:53 +05:30
Pratik Vyas
a38a7b8e76 Merge pull request #1214 from anandpdoshi/hotfix-scheduler-errors
Send Email Digest, only if there is atleast one update for selected cate...
2013-12-19 01:12:17 -08:00
Anand Doshi
88eedb7397 Send Email Digest, only if there is atleast one update for selected categories 2013-12-19 14:07:39 +05:30
115 changed files with 1383 additions and 753 deletions

File diff suppressed because one or more lines are too long

View File

@@ -95,9 +95,10 @@ cur_frm.cscript.add_toolbar_buttons = function(doc) {
wn.route_options = {
"account": doc.name,
"from_date": sys_defaults.year_start_date,
"to_date": sys_defaults.year_end_date
"to_date": sys_defaults.year_end_date,
"company": doc.company
};
wn.set_route("general-ledger");
wn.set_route("query-report", "General Ledger");
}, "icon-table");
}
}

View File

@@ -211,6 +211,9 @@ class DocType:
# Validate properties before merging
if merge:
if not webnotes.conn.exists("Account", new):
webnotes.throw(_("Account ") + new +_(" does not exists"))
val = list(webnotes.conn.get_value("Account", new_account,
["group_or_ledger", "debit_or_credit", "is_pl_account"]))

View File

@@ -5,8 +5,8 @@
from __future__ import unicode_literals
import webnotes
from webnotes.utils import cint, cstr
from webnotes import msgprint, _
from webnotes import _
from webnotes.utils import cint
class DocType:
def __init__(self, d, dl):
@@ -15,7 +15,17 @@ class DocType:
def on_update(self):
webnotes.conn.set_default("auto_accounting_for_stock", self.doc.auto_accounting_for_stock)
if self.doc.auto_accounting_for_stock:
for wh in webnotes.conn.sql("select name from `tabWarehouse`"):
wh_bean = webnotes.bean("Warehouse", wh[0])
if cint(self.doc.auto_accounting_for_stock):
# set default perpetual account in company
for company in webnotes.conn.sql("select name from tabCompany"):
webnotes.bean("Company", company[0]).save()
# Create account head for warehouses
warehouse_list = webnotes.conn.sql("select name, company from tabWarehouse", as_dict=1)
warehouse_with_no_company = [d.name for d in warehouse_list if not d.company]
if warehouse_with_no_company:
webnotes.throw(_("Company is missing in following warehouses") + ": \n" +
"\n".join(warehouse_with_no_company))
for wh in warehouse_list:
wh_bean = webnotes.bean("Warehouse", wh.name)
wh_bean.save()

View File

@@ -146,11 +146,12 @@ def update_outstanding_amt(account, against_voucher_type, against_voucher, on_ca
webnotes.conn.sql("update `tab%s` set outstanding_amount=%s where name='%s'" %
(against_voucher_type, bal, against_voucher))
def validate_frozen_account(account, adv_adj):
def validate_frozen_account(account, adv_adj=None):
frozen_account = webnotes.conn.get_value("Account", account, "freeze_account")
if frozen_account == 'Yes' and not adv_adj:
frozen_accounts_modifier = webnotes.conn.get_value( 'Accounts Settings', None,
'frozen_accounts_modifier')
if not frozen_accounts_modifier:
webnotes.throw(account + _(" is a frozen account. \
Either make the account active or assign role in Accounts Settings \

View File

@@ -120,8 +120,10 @@ cur_frm.cscript.refresh = function(doc) {
"voucher_no": doc.name,
"from_date": doc.posting_date,
"to_date": doc.posting_date,
"company": doc.company,
group_by_voucher: 0
};
wn.set_route("general-ledger");
wn.set_route("query-report", "General Ledger");
}, "icon-table");
}
}

View File

@@ -140,13 +140,13 @@ def gl_entry_details(doctype, txt, searchfield, start, page_len, filters):
and ifnull(gle.%(account_type)s, 0) > 0
and (select ifnull(abs(sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))), 0)
from `tabGL Entry`
where against_voucher_type = '%(dt)s'
where account = '%(acc)s'
and against_voucher_type = '%(dt)s'
and against_voucher = gle.voucher_no
and voucher_no != gle.voucher_no)
!= abs(ifnull(gle.debit, 0) - ifnull(gle.credit, 0)
)
and if(gle.voucher_type='Sales Invoice', (select is_pos from `tabSales Invoice`
where name=gle.voucher_no), 0)=0
!= abs(ifnull(gle.debit, 0) - ifnull(gle.credit, 0))
and if(gle.voucher_type='Sales Invoice', ifnull((select is_pos from `tabSales Invoice`
where name=gle.voucher_no), 0), 0)=0
%(mcond)s
ORDER BY gle.posting_date desc, gle.voucher_no desc
limit %(start)s, %(page_len)s""" % {

View File

@@ -7,7 +7,7 @@ cur_frm.cscript.onload = function(doc,cdt,cdn){
});
cur_frm.set_query("selling_price_list", function() {
return { filters: { buying_or_selling: "Selling" } };
return { filters: { selling: 1 } };
});
}

View File

@@ -2,7 +2,7 @@
{
"creation": "2013-05-24 12:15:51",
"docstatus": 0,
"modified": "2013-11-02 16:58:38",
"modified": "2014-01-15 16:23:58",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -154,7 +154,7 @@
"reqd": 1
},
{
"depends_on": "eval:sys_defaults.auto_accounting_for_stock",
"depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)",
"doctype": "DocField",
"fieldname": "expense_account",
"fieldtype": "Link",

View File

@@ -35,8 +35,10 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({
"voucher_no": doc.name,
"from_date": doc.posting_date,
"to_date": doc.posting_date,
"company": doc.company,
group_by_voucher: 0
};
wn.set_route("general-ledger");
wn.set_route("query-report", "General Ledger");
}, "icon-table");
}

View File

@@ -302,6 +302,7 @@ class DocType(BuyingController):
self.make_gl_entries()
self.update_against_document_in_jv()
self.update_prevdoc_status()
self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
def make_gl_entries(self):
auto_accounting_for_stock = \
@@ -350,7 +351,6 @@ class DocType(BuyingController):
# item gl entries
stock_item_and_auto_accounting_for_stock = False
stock_items = self.get_stock_items()
rounding_diff = 0.0
for item in self.doclist.get({"parentfield": "entries"}):
if auto_accounting_for_stock and item.item_code in stock_items:
if flt(item.valuation_rate):
@@ -359,13 +359,8 @@ class DocType(BuyingController):
# expense will be booked in sales invoice
stock_item_and_auto_accounting_for_stock = True
valuation_amt = flt(flt(item.valuation_rate) * flt(item.qty) * \
flt(item.conversion_factor), self.precision("valuation_rate", item))
rounding_diff += (flt(item.amount, self.precision("amount", item)) +
flt(item.item_tax_amount, self.precision("item_tax_amount", item)) +
flt(item.rm_supp_cost, self.precision("rm_supp_cost", item)) -
valuation_amt)
valuation_amt = flt(item.amount + item.item_tax_amount + item.rm_supp_cost,
self.precision("amount", item))
gl_entries.append(
self.get_gl_dict({
@@ -393,12 +388,6 @@ class DocType(BuyingController):
# this will balance out valuation amount included in cost of goods sold
expenses_included_in_valuation = \
self.get_company_default("expenses_included_in_valuation")
if rounding_diff:
import operator
cost_center_with_max_value = max(valuation_tax.iteritems(),
key=operator.itemgetter(1))[0]
valuation_tax[cost_center_with_max_value] -= flt(rounding_diff)
for cost_center, amount in valuation_tax.items():
gl_entries.append(
@@ -433,7 +422,7 @@ class DocType(BuyingController):
remove_against_link_from_jv(self.doc.doctype, self.doc.name, "against_voucher")
self.update_prevdoc_status()
self.update_billing_status_for_zero_amount_refdoc("Purchase Order")
self.make_cancel_gl_entries()
def on_update(self):

View File

@@ -19,8 +19,10 @@ erpnext.POS = Class.extend({
<table class="table table-condensed table-hover" id="cart" style="table-layout: fixed;">\
<thead>\
<tr>\
<th style="width: 50%">Item</th>\
<th style="width: 25%; text-align: right;">Qty</th>\
<th style="width: 40%">Item</th>\
<th style="width: 9%"></th>\
<th style="width: 17%; text-align: right;">Qty</th>\
<th style="width: 9%"></th>\
<th style="width: 25%; text-align: right;">Rate</th>\
</tr>\
</thead>\
@@ -60,10 +62,16 @@ erpnext.POS = Class.extend({
</div>\
</div>\
<br><br>\
<button class="btn btn-success btn-lg make-payment">\
<i class="icon-money"></i> Make Payment</button>\
<button class="btn btn-default btn-lg delete-items pull-right" style="display: none;">\
<i class="icon-trash"></i> Del</button>\
<div class="row">\
<div class="col-sm-9">\
<button class="btn btn-success btn-lg make-payment">\
<i class="icon-money"></i> Make Payment</button>\
</div>\
<div class="col-sm-3">\
<button class="btn btn-default btn-lg remove-items" style="display: none;">\
<i class="icon-trash"></i> Del</button>\
</div>\
</div>\
<br><br>\
</div>\
<div class="col-sm-6">\
@@ -82,7 +90,7 @@ erpnext.POS = Class.extend({
me.refresh();
});
this.call_function("delete-items", function() {me.remove_selected_item();});
this.call_function("remove-items", function() {me.remove_selected_items();});
this.call_function("make-payment", function() {me.make_payment();});
},
check_transaction_type: function() {
@@ -101,6 +109,7 @@ erpnext.POS = Class.extend({
this.party = party;
this.price_list = (party == "Customer" ?
this.frm.doc.selling_price_list : this.frm.doc.buying_price_list);
this.price_list_field = (party == "Customer" ? "selling_price_list" : "buying_price_list");
this.sales_or_purchase = (party == "Customer" ? "Sales" : "Purchase");
this.net_total = "net_total_" + export_or_import;
this.grand_total = "grand_total_" + export_or_import;
@@ -261,22 +270,17 @@ erpnext.POS = Class.extend({
this.frm.cscript.fname, this.frm.doctype), function(i, d) {
if (d.item_code == item_code) {
caught = true;
if (serial_no) {
d.serial_no += '\n' + serial_no;
me.frm.script_manager.trigger("serial_no", d.doctype, d.name);
}
else {
d.qty += 1;
me.frm.script_manager.trigger("qty", d.doctype, d.name);
}
if (serial_no)
wn.model.set_value(d.doctype, d.name, "serial_no", d.serial_no + '\n' + serial_no);
else
wn.model.set_value(d.doctype, d.name, "qty", d.qty + 1);
}
});
}
// if item not found then add new item
if (!caught) {
if (!caught)
this.add_new_item_to_grid(item_code, serial_no);
}
this.refresh();
this.refresh_search_box();
@@ -311,15 +315,16 @@ erpnext.POS = Class.extend({
wn.model.clear_doc(d.doctype, d.name);
me.refresh_grid();
} else {
d.qty = qty;
me.frm.script_manager.trigger("qty", d.doctype, d.name);
wn.model.set_value(d.doctype, d.name, "qty", qty);
}
}
});
me.refresh();
this.refresh();
},
refresh: function() {
var me = this;
this.refresh_item_list();
this.party_field.set_input(this.frm.doc[this.party.toLowerCase()]);
this.barcode.set_input("");
@@ -333,7 +338,7 @@ erpnext.POS = Class.extend({
}
this.disable_text_box_and_button();
this.make_payment_button();
this.hide_payment_button();
// If quotation to is not Customer then remove party
if (this.frm.doctype == "Quotation") {
@@ -342,6 +347,14 @@ erpnext.POS = Class.extend({
this.make_party();
}
},
refresh_item_list: function() {
var me = this;
// refresh item list on change of price list
if (this.frm.doc[this.price_list_field] != this.price_list) {
this.price_list = this.frm.doc[this.price_list_field];
this.make_item_list();
}
},
show_items_in_item_cart: function() {
var me = this;
var $items = this.wrapper.find("#cart tbody").empty();
@@ -351,8 +364,18 @@ erpnext.POS = Class.extend({
$(repl('<tr id="%(item_code)s" data-selected="false">\
<td>%(item_code)s%(item_name)s</td>\
<td><input type="text" value="%(qty)s" \
<td style="vertical-align:middle;" align="right">\
<div class="decrease-qty" style="cursor:pointer;">\
<i class="icon-minus-sign icon-large text-danger"></i>\
</div>\
</td>\
<td style="vertical-align:middle;"><input type="text" value="%(qty)s" \
class="form-control qty" style="text-align: right;"></td>\
<td style="vertical-align:middle;cursor:pointer;">\
<div class="increase-qty" style="cursor:pointer;">\
<i class="icon-plus-sign icon-large text-success"></i>\
</div>\
</td>\
<td style="text-align: right;"><b>%(amount)s</b><br>%(rate)s</td>\
</tr>',
{
@@ -364,27 +387,31 @@ erpnext.POS = Class.extend({
}
)).appendTo($items);
});
this.wrapper.find("input.qty").on("focus", function() {
$(this).select();
});
},
show_taxes: function() {
var me = this;
var taxes = wn.model.get_children(this.sales_or_purchase + " Taxes and Charges",
this.frm.doc.name, this.frm.cscript.other_fname, this.frm.doctype);
$(this.wrapper).find(".tax-table")
.toggle((taxes && taxes.length &&
flt(me.frm.doc.other_charges_total_export ||
me.frm.doc.other_charges_added_import) != 0.0) ? true : false)
.toggle((taxes && taxes.length) ? true : false)
.find("tbody").empty();
$.each(taxes, function(i, d) {
$(repl('<tr>\
<td>%(description)s %(rate)s</td>\
<td style="text-align: right;">%(tax_amount)s</td>\
<tr>', {
description: d.description,
rate: ((d.charge_type == "Actual") ? '' : ("(" + d.rate + "%)")),
tax_amount: format_currency(flt(d.tax_amount)/flt(me.frm.doc.conversion_rate),
me.frm.doc.currency)
})).appendTo(".tax-table tbody");
if (d.tax_amount) {
$(repl('<tr>\
<td>%(description)s %(rate)s</td>\
<td style="text-align: right;">%(tax_amount)s</td>\
<tr>', {
description: d.description,
rate: ((d.charge_type == "Actual") ? '' : ("(" + d.rate + "%)")),
tax_amount: format_currency(flt(d.tax_amount)/flt(me.frm.doc.conversion_rate),
me.frm.doc.currency)
})).appendTo(".tax-table tbody");
}
});
},
set_totals: function() {
@@ -399,10 +426,16 @@ erpnext.POS = Class.extend({
// append quantity to the respective item after change from input box
$(this.wrapper).find("input.qty").on("change", function() {
var item_code = $(this).closest("tr")[0].id;
var item_code = $(this).closest("tr").attr("id");
me.update_qty(item_code, $(this).val());
});
// increase/decrease qty on plus/minus button
$(this.wrapper).find(".increase-qty, .decrease-qty").on("click", function() {
var tr = $(this).closest("tr");
me.increase_decrease_qty(tr, $(this).attr("class"));
});
// on td click toggle the highlighting of row
$(this.wrapper).find("#cart tbody tr td").on("click", function() {
var row = $(this).closest("tr");
@@ -420,6 +453,15 @@ erpnext.POS = Class.extend({
me.refresh_delete_btn();
this.barcode.$input.focus();
},
increase_decrease_qty: function(tr, operation) {
var item_code = tr.attr("id");
var item_qty = cint(tr.find("input.qty").val());
if (operation == "increase-qty")
this.update_qty(item_code, item_qty + 1);
else if (operation == "decrease-qty" && item_qty != 1)
this.update_qty(item_code, item_qty - 1);
},
disable_text_box_and_button: function() {
var me = this;
// if form is submitted & cancelled then disable all input box & buttons
@@ -427,7 +469,7 @@ erpnext.POS = Class.extend({
$(this.wrapper).find('input, button').each(function () {
$(this).prop('disabled', true);
});
$(this.wrapper).find(".delete-items").hide();
$(this.wrapper).find(".remove-items").hide();
$(this.wrapper).find(".make-payment").hide();
}
else {
@@ -437,14 +479,14 @@ erpnext.POS = Class.extend({
$(this.wrapper).find(".make-payment").show();
}
},
make_payment_button: function() {
hide_payment_button: function() {
var me = this;
// Show Make Payment button only in Sales Invoice
if (this.frm.doctype != "Sales Invoice")
$(this.wrapper).find(".make-payment").hide();
},
refresh_delete_btn: function() {
$(this.wrapper).find(".delete-items").toggle($(".item-cart .warning").length ? true : false);
$(this.wrapper).find(".remove-items").toggle($(".item-cart .warning").length ? true : false);
},
add_item_thru_barcode: function() {
var me = this;
@@ -466,7 +508,7 @@ erpnext.POS = Class.extend({
}
});
},
remove_selected_item: function() {
remove_selected_items: function() {
var me = this;
var selected_items = [];
var no_of_items = $(this.wrapper).find("#cart tbody tr").length;
@@ -487,9 +529,11 @@ erpnext.POS = Class.extend({
}
}
});
this.refresh_grid();
},
refresh_grid: function() {
this.frm.dirty();
this.frm.fields_dict[this.frm.cscript.fname].grid.refresh();
this.frm.script_manager.trigger("calculate_taxes_and_totals");
this.refresh();

View File

@@ -54,8 +54,10 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
"voucher_no": doc.name,
"from_date": doc.posting_date,
"to_date": doc.posting_date,
"company": doc.company,
group_by_voucher: 0
};
wn.set_route("general-ledger");
wn.set_route("query-report", "General Ledger");
}, "icon-table");
var percent_paid = cint(flt(doc.grand_total - doc.outstanding_amount) / flt(doc.grand_total) * 100);

View File

@@ -88,6 +88,7 @@ class DocType(SellingController):
self.update_status_updater_args()
self.update_prevdoc_status()
self.update_billing_status_for_zero_amount_refdoc("Sales Order")
# this sequence because outstanding may get -ve
self.make_gl_entries()
@@ -114,6 +115,7 @@ class DocType(SellingController):
self.update_status_updater_args()
self.update_prevdoc_status()
self.update_billing_status_for_zero_amount_refdoc("Sales Order")
self.make_cancel_gl_entries()
@@ -318,12 +320,9 @@ class DocType(SellingController):
item = webnotes.conn.sql("select name,is_asset_item,is_sales_item from `tabItem` where name = '%s' and (ifnull(end_of_life,'')='' or end_of_life = '0000-00-00' or end_of_life > now())"% d.item_code)
acc = webnotes.conn.sql("select account_type from `tabAccount` where name = '%s' and docstatus != 2" % d.income_account)
if not acc:
msgprint("Account: "+d.income_account+" does not exist in the system")
raise Exception
msgprint("Account: "+d.income_account+" does not exist in the system", raise_exception=True)
elif item and item[0][1] == 'Yes' and not acc[0][0] == 'Fixed Asset Account':
msgprint("Please select income head with account type 'Fixed Asset Account' as Item %s is an asset item" % d.item_code)
raise Exception
msgprint("Please select income head with account type 'Fixed Asset Account' as Item %s is an asset item" % d.item_code, raise_exception=True)
def validate_with_previous_doc(self):
super(DocType, self).validate_with_previous_doc(self.tname, {

View File

@@ -2,7 +2,7 @@
{
"creation": "2013-05-24 19:29:05",
"docstatus": 0,
"modified": "2013-11-18 15:16:50",
"modified": "2014-01-16 15:36:16",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -1091,7 +1091,7 @@
"fieldtype": "Select",
"label": "Recurring Type",
"no_copy": 1,
"options": "Monthly\nQuarterly\nHalf-yearly\nYearly",
"options": "\nMonthly\nQuarterly\nHalf-yearly\nYearly",
"print_hide": 1,
"read_only": 0
},

View File

@@ -364,7 +364,6 @@ class TestSalesInvoice(unittest.TestCase):
from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
order by account asc, debit asc""", si.doc.name, as_dict=1)
self.assertTrue(gl_entries)
# print gl_entries
stock_in_hand = webnotes.conn.get_value("Account", {"master_name": "_Test Warehouse - _TC"})
@@ -566,16 +565,17 @@ class TestSalesInvoice(unittest.TestCase):
where against_invoice=%s""", si.doc.name))
def test_recurring_invoice(self):
from webnotes.utils import now_datetime, get_first_day, get_last_day, add_to_date
today = now_datetime().date()
from webnotes.utils import get_first_day, get_last_day, add_to_date, nowdate, getdate
from accounts.utils import get_fiscal_year
today = nowdate()
base_si = webnotes.bean(copy=test_records[0])
base_si.doc.fields.update({
"convert_into_recurring_invoice": 1,
"recurring_type": "Monthly",
"notification_email_address": "test@example.com, test1@example.com, test2@example.com",
"repeat_on_day_of_month": today.day,
"repeat_on_day_of_month": getdate(today).day,
"posting_date": today,
"fiscal_year": get_fiscal_year(today)[0],
"invoice_period_from_date": get_first_day(today),
"invoice_period_to_date": get_last_day(today)
})

View File

@@ -45,7 +45,7 @@ def merge_similar_entries(gl_map):
same_head.credit = flt(same_head.credit) + flt(entry.credit)
else:
merged_gl_map.append(entry)
# filter zero debit and credit entries
merged_gl_map = filter(lambda x: flt(x.debit)!=0 or flt(x.credit)!=0, merged_gl_map)
return merged_gl_map

View File

@@ -175,9 +175,10 @@ erpnext.AccountsChart = Class.extend({
wn.route_options = {
"account": node.data('label'),
"from_date": sys_defaults.year_start_date,
"to_date": sys_defaults.year_end_date
"to_date": sys_defaults.year_end_date,
"company": me.company
};
wn.set_route("general-ledger");
wn.set_route("query-report", "General Ledger");
},
rename: function() {
var node = this.selected_node();

View File

@@ -9,17 +9,19 @@ from accounts.report.accounts_receivable.accounts_receivable import get_ageing_d
def execute(filters=None):
if not filters: filters = {}
columns = get_columns()
supplier_naming_by = webnotes.conn.get_value("Buying Settings", None, "supp_master_name")
columns = get_columns(supplier_naming_by)
entries = get_gl_entries(filters)
account_supplier = dict(webnotes.conn.sql("""select account.name, supplier.supplier_name
from `tabAccount` account, `tabSupplier` supplier
where account.master_type="Supplier" and supplier.name=account.master_name"""))
account_map = dict(((r.name, r) for r in webnotes.conn.sql("""select acc.name,
supp.supplier_name, supp.name as supplier
from `tabAccount` acc, `tabSupplier` supp
where acc.master_type="Supplier" and supp.name=acc.master_name""", as_dict=1)))
entries_after_report_date = [[gle.voucher_type, gle.voucher_no]
for gle in get_gl_entries(filters, before_report_date=False)]
account_supplier_type_map = get_account_supplier_type_map()
pi_map = get_pi_map()
voucher_detail_map = get_voucher_details()
# Age of the invoice on this date
age_on = getdate(filters.get("report_date")) > getdate(nowdate()) \
@@ -29,46 +31,57 @@ def execute(filters=None):
for gle in entries:
if cstr(gle.against_voucher) == gle.voucher_no or not gle.against_voucher \
or [gle.against_voucher_type, gle.against_voucher] in entries_after_report_date:
if gle.voucher_type == "Purchase Invoice":
pi_info = pi_map.get(gle.voucher_no)
due_date = pi_info.get("due_date")
bill_no = pi_info.get("bill_no")
bill_date = pi_info.get("bill_date")
else:
due_date = bill_no = bill_date = ""
voucher_details = voucher_detail_map.get(gle.voucher_type, {}).get(gle.voucher_no, {})
invoiced_amount = gle.credit > 0 and gle.credit or 0
outstanding_amount = get_outstanding_amount(gle,
filters.get("report_date") or nowdate())
if abs(flt(outstanding_amount)) > 0.01:
paid_amount = invoiced_amount - outstanding_amount
row = [gle.posting_date, gle.account, account_supplier.get(gle.account, ""),
gle.voucher_type, gle.voucher_no,
gle.remarks, account_supplier_type_map.get(gle.account), due_date, bill_no,
bill_date, invoiced_amount, paid_amount, outstanding_amount]
row = [gle.posting_date, gle.account, gle.voucher_type, gle.voucher_no,
voucher_details.get("due_date", ""), voucher_details.get("bill_no", ""),
voucher_details.get("bill_date", ""), invoiced_amount,
paid_amount, outstanding_amount]
# Ageing
if filters.get("ageing_based_on") == "Due Date":
ageing_based_on_date = due_date
ageing_based_on_date = voucher_details.get("due_date", "")
else:
ageing_based_on_date = gle.posting_date
row += get_ageing_data(age_on, ageing_based_on_date, outstanding_amount)
row += get_ageing_data(age_on, ageing_based_on_date, outstanding_amount) + \
[account_map.get(gle.account).get("supplier") or ""]
if supplier_naming_by == "Naming Series":
row += [account_map.get(gle.account).get("supplier_name") or ""]
row += [account_supplier_type_map.get(gle.account), gle.remarks]
data.append(row)
for i in range(0, len(data)):
data[i].insert(4, """<a href="%s"><i class="icon icon-share" style="cursor: pointer;"></i></a>""" \
% ("/".join(["#Form", data[i][2], data[i][3]]),))
return columns, data
def get_columns():
return [
"Posting Date:Date:80", "Account:Link/Account:150", "Supplier::150", "Voucher Type::110",
"Voucher No::120", "Remarks::150", "Supplier Type:Link/Supplier Type:120",
"Due Date:Date:80", "Bill No::80", "Bill Date:Date:80",
def get_columns(supplier_naming_by):
columns = [
"Posting Date:Date:80", "Account:Link/Account:150", "Voucher Type::110",
"Voucher No::120", "::30", "Due Date:Date:80", "Bill No::80", "Bill Date:Date:80",
"Invoiced Amount:Currency:100", "Paid Amount: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"
"30-60:Currency:100", "60-90:Currency:100", "90-Above:Currency:100",
"Supplier:Link/Supplier:150"
]
if supplier_naming_by == "Naming Series":
columns += ["Supplier Name::110"]
columns += ["Supplier Type:Link/Supplier Type:120", "Remarks::150"]
return columns
def get_gl_entries(filters, before_report_date=True):
conditions, supplier_accounts = get_conditions(filters, before_report_date)
gl_entries = []
@@ -106,20 +119,21 @@ def get_conditions(filters, before_report_date=True):
def get_account_supplier_type_map():
account_supplier_type_map = {}
for each in webnotes.conn.sql("""select t2.name, t1.supplier_type from `tabSupplier` t1,
`tabAccount` t2 where t1.name = t2.master_name group by t2.name"""):
for each in webnotes.conn.sql("""select acc.name, supp.supplier_type from `tabSupplier` supp,
`tabAccount` acc where supp.name = acc.master_name group by acc.name"""):
account_supplier_type_map[each[0]] = each[1]
return account_supplier_type_map
def get_pi_map():
""" get due_date from sales invoice """
pi_map = {}
for t in webnotes.conn.sql("""select name, due_date, bill_no, bill_date
from `tabPurchase Invoice`""", as_dict=1):
pi_map[t.name] = t
def get_voucher_details():
voucher_details = {}
for dt in ["Purchase Invoice", "Journal Voucher"]:
voucher_details.setdefault(dt, webnotes._dict())
for t in webnotes.conn.sql("""select name, due_date, bill_no, bill_date
from `tab%s`""" % dt, as_dict=1):
voucher_details[dt].setdefault(t.name, t)
return pi_map
return voucher_details
def get_outstanding_amount(gle, report_date):
payment_amount = webnotes.conn.sql("""

View File

@@ -15,26 +15,37 @@ class AccountsReceivableReport(object):
else self.filters.report_date
def run(self):
return self.get_columns(), self.get_data()
customer_naming_by = webnotes.conn.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):
return [
def get_columns(self, customer_naming_by):
columns = [
"Posting Date:Date:80", "Account:Link/Account:150",
"Voucher Type::110", "Voucher No::120", "::30",
"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", "Territory:Link/Territory:80", "Remarks::200"
"Customer:Link/Customer:200"
]
def get_data(self):
if customer_naming_by == "Naming Series":
columns += ["Customer Name::110"]
columns += ["Territory:Link/Territory:80", "Remarks::200"]
return columns
def get_data(self, customer_naming_by):
from accounts.utils import get_currency_precision
currency_precision = get_currency_precision() or 2
data = []
future_vouchers = self.get_entries_after(self.filters.report_date)
for gle in self.get_entries_till(self.filters.report_date):
if self.is_receivable(gle, future_vouchers):
outstanding_amount = self.get_outstanding_amount(gle, self.filters.report_date)
if abs(outstanding_amount) > 0.01:
if abs(outstanding_amount) > 0.1/10**currency_precision:
due_date = self.get_due_date(gle)
invoiced_amount = gle.debit if (gle.debit > 0) else 0
payment_received = invoiced_amount - outstanding_amount
@@ -42,18 +53,23 @@ class AccountsReceivableReport(object):
gle.voucher_type, gle.voucher_no, due_date,
invoiced_amount, payment_received,
outstanding_amount]
entry_date = due_date if self.filters.ageing_based_on=="Due Date" \
entry_date = due_date if self.filters.ageing_based_on == "Due Date" \
else gle.posting_date
row += get_ageing_data(self.age_as_on, entry_date, outstanding_amount)
row += [self.get_customer(gle.account), self.get_territory(gle.account), gle.remarks]
row += get_ageing_data(self.age_as_on, entry_date, outstanding_amount) + \
[self.get_customer(gle.account)]
if customer_naming_by == "Naming Series":
row += [self.get_customer_name(gle.account)]
row += [self.get_territory(gle.account), gle.remarks]
data.append(row)
for i in range(0,len(data)):
for i in range(0, len(data)):
data[i].insert(4, """<a href="%s"><i class="icon icon-share" style="cursor: pointer;"></i></a>""" \
% ("/".join(["#Form", data[i][2], data[i][3]]),))
return data
def get_entries_after(self, report_date):
# returns a distinct list
return list(set([(e.voucher_type, e.voucher_no) for e in self.get_gl_entries()
@@ -65,30 +81,41 @@ class AccountsReceivableReport(object):
if getdate(e.posting_date) <= report_date)
def is_receivable(self, gle, future_vouchers):
return ((not gle.against_voucher) or (gle.against_voucher==gle.voucher_no) or
((gle.against_voucher_type, gle.against_voucher) in future_vouchers))
return (
# advance
(not gle.against_voucher) or
# sales invoice
(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):
if getdate(e.posting_date) <= report_date and e.name!=gle.name:
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 ""
def get_customer_name(self, account):
return self.get_account_map().get(account).get("customer_name") or ""
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 webnotes.conn.sql("""select
account.name, customer.name as customer_name, customer.territory
from `tabAccount` account, `tabCustomer` customer
where account.master_type="Customer"
and customer.name=account.master_name""", as_dict=True)))
acc.name, cust.name as customer, cust.customer_name, cust.territory
from `tabAccount` acc, `tabCustomer` cust
where acc.master_type="Customer"
and cust.name=acc.master_name""", as_dict=True)))
return self.account_map
@@ -147,7 +174,7 @@ class AccountsReceivableReport(object):
def execute(filters=None):
return AccountsReceivableReport(filters).run()
def get_ageing_data(age_as_on, entry_date, outstanding_amount):
# [0-30, 30-60, 60-90, 90-above]
outstanding_range = [0.0, 0.0, 0.0, 0.0]

View File

@@ -8,6 +8,7 @@ wn.query_reports["Bank Reconciliation Statement"] = {
"label": wn._("Bank Account"),
"fieldtype": "Link",
"options": "Account",
"reqd": 1,
"get_query": function() {
return {
"query": "accounts.utils.get_account_list",
@@ -22,7 +23,8 @@ wn.query_reports["Bank Reconciliation Statement"] = {
"fieldname":"report_date",
"label": wn._("Date"),
"fieldtype": "Date",
"default": get_today()
"default": get_today(),
"reqd": 1
},
]
}

View File

@@ -3,13 +3,14 @@
from __future__ import unicode_literals
import webnotes
from webnotes import _, msgprint
from webnotes.utils import flt
def execute(filters=None):
if not filters: filters = {}
columns = get_columns()
debit_or_credit = webnotes.conn.get_value("Account", filters["account"], "debit_or_credit")
columns = get_columns()
data = get_entries(filters)
from accounts.utils import get_balance_on
@@ -20,47 +21,39 @@ def execute(filters=None):
total_debit += flt(d[4])
total_credit += flt(d[5])
if webnotes.conn.get_value("Account", filters["account"], "debit_or_credit") == 'Debit':
if debit_or_credit == 'Debit':
bank_bal = flt(balance_as_per_company) - flt(total_debit) + flt(total_credit)
else:
bank_bal = flt(balance_as_per_company) + flt(total_debit) - flt(total_credit)
data += [
["", "", "", "Balance as per company books", balance_as_per_company, ""],
get_balance_row("Balance as per company books", balance_as_per_company, debit_or_credit),
["", "", "", "Amounts not reflected in bank", total_debit, total_credit],
["", "", "", "Balance as per bank", bank_bal, ""]
get_balance_row("Balance as per bank", bank_bal, debit_or_credit)
]
return columns, data
return columns, data
def get_columns():
return ["Journal Voucher:Link/Journal Voucher:140", "Posting Date:Date:100",
"Clearance Date:Date:110", "Against Account:Link/Account:200",
"Debit:Currency:120", "Credit:Currency:120"
]
def get_conditions(filters):
conditions = ""
if not filters.get("account"):
msgprint(_("Please select Bank Account"), raise_exception=1)
else:
conditions += " and jvd.account = %(account)s"
if not filters.get("report_date"):
msgprint(_("Please select Date on which you want to run the report"), raise_exception=1)
else:
conditions += """ and jv.posting_date <= %(report_date)s
and ifnull(jv.clearance_date, '4000-01-01') > %(report_date)s"""
return conditions
def get_entries(filters):
conditions = get_conditions(filters)
entries = webnotes.conn.sql("""select jv.name, jv.posting_date, jv.clearance_date,
jvd.against_account, jvd.debit, jvd.credit
from `tabJournal Voucher Detail` jvd, `tabJournal Voucher` jv
where jvd.parent = jv.name and jv.docstatus=1 and ifnull(jv.cheque_no, '')!= '' %s
order by jv.name DESC""" % conditions, filters, as_list=1)
entries = webnotes.conn.sql("""select
jv.name, jv.posting_date, jv.clearance_date, jvd.against_account, jvd.debit, jvd.credit
from
`tabJournal Voucher Detail` jvd, `tabJournal Voucher` jv
where jvd.parent = jv.name and jv.docstatus=1 and ifnull(jv.cheque_no, '')!= ''
and jvd.account = %(account)s and jv.posting_date <= %(report_date)s
and ifnull(jv.clearance_date, '4000-01-01') > %(report_date)s
order by jv.name DESC""", filters, as_list=1)
return entries
return entries
def get_balance_row(label, amount, debit_or_credit):
if debit_or_credit == "Debit":
return ["", "", "", label, amount, 0]
else:
return ["", "", "", label, 0, amount]

View File

@@ -11,26 +11,6 @@ wn.query_reports["General Ledger"] = {
"default": wn.defaults.get_user_default("company"),
"reqd": 1
},
{
"fieldname":"account",
"label": wn._("Account"),
"fieldtype": "Link",
"options": "Account"
},
{
"fieldname":"voucher_no",
"label": wn._("Voucher No"),
"fieldtype": "Data",
},
{
"fieldname":"group_by",
"label": wn._("Group by"),
"fieldtype": "Select",
"options": "\nGroup by Account\nGroup by Voucher"
},
{
"fieldtype": "Break",
},
{
"fieldname":"from_date",
"label": wn._("From Date"),
@@ -46,6 +26,40 @@ wn.query_reports["General Ledger"] = {
"default": wn.datetime.get_today(),
"reqd": 1,
"width": "60px"
},
{
"fieldtype": "Break",
},
{
"fieldname":"account",
"label": wn._("Account"),
"fieldtype": "Link",
"options": "Account",
"get_query": function() {
var company = wn.query_report.filters_by_name.company.get_value();
return {
"doctype": "Account",
"filters": {
"company": company,
}
}
}
},
{
"fieldname":"voucher_no",
"label": wn._("Voucher No"),
"fieldtype": "Data",
},
{
"fieldname":"group_by_voucher",
"label": wn._("Group by Voucher"),
"fieldtype": "Check",
"default": 1
},
{
"fieldname":"group_by_account",
"label": wn._("Group by Account"),
"fieldtype": "Check",
}
]
}

View File

@@ -3,77 +3,175 @@
from __future__ import unicode_literals
import webnotes
from webnotes.utils import flt
from webnotes.utils import cstr, flt
from webnotes import _
def execute(filters=None):
validate_filters(filters)
account_details = {}
for acc in webnotes.conn.sql("""select name, debit_or_credit, group_or_ledger
from tabAccount""", as_dict=1):
account_details.setdefault(acc.name, acc)
validate_filters(filters, account_details)
columns = get_columns()
if filters.get("group_by"):
data = get_grouped_gle(filters)
else:
data = get_gl_entries(filters)
if data:
data.append(get_total_row(data))
res = get_result(filters, account_details)
return columns, data
return columns, res
def validate_filters(filters):
if filters.get("account") and filters.get("group_by") == "Group by Account":
def validate_filters(filters, account_details):
if filters.get("account") and filters.get("group_by_account") \
and account_details[filters.account].group_or_ledger == "Ledger":
webnotes.throw(_("Can not filter based on Account, if grouped by Account"))
if filters.get("voucher_no") and filters.get("group_by") == "Group by Voucher":
if filters.get("voucher_no") and filters.get("group_by_voucher"):
webnotes.throw(_("Can not filter based on Voucher No, if grouped by Voucher"))
if filters.from_date > filters.to_date:
webnotes.throw(_("From Date must be before To Date"))
def get_columns():
return ["Posting Date:Date:100", "Account:Link/Account:200", "Debit:Currency:100",
"Credit:Currency:100", "Voucher Type::120", "Voucher No::160",
"Cost Center:Link/Cost Center:100", "Remarks::200"]
return ["Posting Date:Date:100", "Account:Link/Account:200", "Debit:Float:100",
"Credit:Float:100", "Voucher Type::120", "Voucher No::160", "Link::20",
"Against Account::120", "Cost Center:Link/Cost Center:100", "Remarks::400"]
def get_result(filters, account_details):
gl_entries = get_gl_entries(filters)
data = get_data_with_opening_closing(filters, account_details, gl_entries)
result = get_result_as_list(data)
return result
def get_gl_entries(filters):
return webnotes.conn.sql("""select
posting_date, account, debit, credit, voucher_type, voucher_no, cost_center, remarks
group_by_condition = "group by voucher_type, voucher_no, account" \
if filters.get("group_by_voucher") else "group by name"
gl_entries = webnotes.conn.sql("""select posting_date, account,
sum(ifnull(debit, 0)) as debit, sum(ifnull(credit, 0)) as credit,
voucher_type, voucher_no, cost_center, remarks, is_opening, against
from `tabGL Entry`
where company=%(company)s
and posting_date between %(from_date)s and %(to_date)s
{conditions}
where company=%(company)s {conditions}
{group_by_condition}
order by posting_date, account"""\
.format(conditions=get_conditions(filters)), filters, as_list=1)
.format(conditions=get_conditions(filters), group_by_condition=group_by_condition),
filters, as_dict=1)
return gl_entries
def get_conditions(filters):
conditions = []
if filters.get("account"):
conditions.append("account=%(account)s")
lft, rgt = webnotes.conn.get_value("Account", filters["account"], ["lft", "rgt"])
conditions.append("""account in (select name from tabAccount
where lft>=%s and rgt<=%s and docstatus<2)""" % (lft, rgt))
else:
conditions.append("posting_date between %(from_date)s and %(to_date)s")
if filters.get("voucher_no"):
conditions.append("voucher_no=%(voucher_no)s")
from webnotes.widgets.reportview import build_match_conditions
match_conditions = build_match_conditions("GL Entry")
if match_conditions: conditions.append(match_conditions)
return "and {}".format(" and ".join(conditions)) if conditions else ""
def get_grouped_gle(filters):
gle_map = {}
gle = get_gl_entries(filters)
for d in gle:
gle_map.setdefault(d[1 if filters["group_by"]=="Group by Account" else 5], []).append(d)
def get_data_with_opening_closing(filters, account_details, gl_entries):
data = []
for entries in gle_map.values():
subtotal_debit = subtotal_credit = 0.0
for entry in entries:
data.append(entry)
subtotal_debit += flt(entry[2])
subtotal_credit += flt(entry[3])
data.append(["", "Total", subtotal_debit, subtotal_credit, "", "", ""])
gle_map = initialize_gle_map(gl_entries)
opening, total_debit, total_credit, gle_map = get_accountwise_gle(filters, gl_entries, gle_map)
# Opening for filtered account
if filters.get("account"):
data += [get_balance_row("Opening", account_details[filters.account].debit_or_credit,
opening), {}]
for acc, acc_dict in gle_map.items():
if acc_dict.entries:
# Opening for individual ledger, if grouped by account
if filters.get("group_by_account"):
data.append(get_balance_row("Opening", account_details[acc].debit_or_credit,
acc_dict.opening))
data += acc_dict.entries
# Totals and closing for individual ledger, if grouped by account
if filters.get("group_by_account"):
data += [{"account": "Totals", "debit": acc_dict.total_debit,
"credit": acc_dict.total_credit},
get_balance_row("Closing (Opening + Totals)",
account_details[acc].debit_or_credit, (acc_dict.opening
+ acc_dict.total_debit - acc_dict.total_credit)), {}]
# Total debit and credit between from and to date
if total_debit or total_credit:
data.append({"account": "Totals", "debit": total_debit, "credit": total_credit})
# Closing for filtered account
if filters.get("account"):
data.append(get_balance_row("Closing (Opening + Totals)",
account_details[filters.account].debit_or_credit,
(opening + total_debit - total_credit)))
if data:
data.append(get_total_row(gle))
return data
def initialize_gle_map(gl_entries):
gle_map = webnotes._dict()
for gle in gl_entries:
gle_map.setdefault(gle.account, webnotes._dict({
"opening": 0,
"entries": [],
"total_debit": 0,
"total_credit": 0,
"closing": 0
}))
return gle_map
def get_accountwise_gle(filters, gl_entries, gle_map):
opening, total_debit, total_credit = 0, 0, 0
def get_total_row(gle):
total_debit = total_credit = 0.0
for d in gle:
total_debit += flt(d[2])
total_credit += flt(d[3])
for gle in gl_entries:
amount = flt(gle.debit) - flt(gle.credit)
if filters.get("account") and (gle.posting_date < filters.from_date
or cstr(gle.is_opening) == "Yes"):
gle_map[gle.account].opening += amount
opening += amount
elif gle.posting_date <= filters.to_date:
gle_map[gle.account].entries.append(gle)
gle_map[gle.account].total_debit += flt(gle.debit)
gle_map[gle.account].total_credit += flt(gle.credit)
total_debit += flt(gle.debit)
total_credit += flt(gle.credit)
return opening, total_debit, total_credit, gle_map
def get_balance_row(label, debit_or_credit, balance):
return {
"account": label,
"debit": balance if debit_or_credit=="Debit" else 0,
"credit": -1*balance if debit_or_credit=="Credit" else 0,
}
def get_result_as_list(data):
result = []
for d in data:
result.append([d.get("posting_date"), d.get("account"), d.get("debit"),
d.get("credit"), d.get("voucher_type"), d.get("voucher_no"),
get_voucher_link(d.get("voucher_type"), d.get("voucher_no")),
d.get("against"), d.get("cost_center"), d.get("remarks")])
return result
def get_voucher_link(voucher_type, voucher_no):
icon = ""
if voucher_type and voucher_no:
icon = """<a href="%s"><i class="icon icon-share" style="cursor: pointer;">
</i></a>""" % ("/".join(["#Form", voucher_type, voucher_no]))
return ["", "Total Debit/Credit", total_debit, total_credit, "", "", ""]
return icon

View File

@@ -12,7 +12,8 @@ def execute(filters=None):
item_list = get_items(filters)
aii_account_map = get_aii_accounts()
item_tax, tax_accounts = get_tax_accounts(item_list, columns)
if item_list:
item_tax, tax_accounts = get_tax_accounts(item_list, columns)
data = []
for d in item_list:

View File

@@ -11,7 +11,8 @@ def execute(filters=None):
last_col = len(columns)
item_list = get_items(filters)
item_tax, tax_accounts = get_tax_accounts(item_list, columns)
if item_list:
item_tax, tax_accounts = get_tax_accounts(item_list, columns)
data = []
for d in item_list:
@@ -39,7 +40,6 @@ def get_columns():
"Qty:Float:120", "Rate:Currency:120", "Amount:Currency:120"
]
def get_conditions(filters):
conditions = ""

View File

@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import webnotes
from webnotes.utils import nowdate, nowtime, cstr, flt, now, getdate, add_months
from webnotes.utils import nowdate, cstr, flt, now, getdate, add_months
from webnotes.model.doc import addchild
from webnotes import msgprint, _
from webnotes.utils import formatdate
@@ -16,7 +16,7 @@ class BudgetError(webnotes.ValidationError): pass
def get_fiscal_year(date=None, fiscal_year=None, label="Date", verbose=1):
return get_fiscal_years(date, fiscal_year, label, verbose=1)[0]
return get_fiscal_years(date, fiscal_year, label, verbose)[0]
def get_fiscal_years(date=None, fiscal_year=None, label="Date", verbose=1):
# if year start date is 2012-04-01, year end date should be 2013-03-31 (hence subdate)
@@ -31,6 +31,8 @@ def get_fiscal_years(date=None, fiscal_year=None, label="Date", verbose=1):
if not fy:
error_msg = """%s %s not in any Fiscal Year""" % (label, formatdate(date))
error_msg = """{msg}: {date}""".format(msg=_("Fiscal Year does not exist for date"),
date=formatdate(date))
if verbose: webnotes.msgprint(error_msg)
raise FiscalYearError, error_msg
@@ -62,7 +64,6 @@ def get_balance_on(account=None, date=None):
try:
year_start_date = get_fiscal_year(date, verbose=0)[1]
except FiscalYearError, e:
from webnotes.utils import getdate
if getdate(date) > getdate(nowdate()):
# if fiscal year not found and the date is greater than today
# get fiscal year for today's date and its corresponding year start date
@@ -220,17 +221,26 @@ def get_cost_center_list(doctype, txt, searchfield, start, page_len, filters):
tuple(filter_values + ["%%%s%%" % txt, start, page_len]))
def remove_against_link_from_jv(ref_type, ref_no, against_field):
webnotes.conn.sql("""update `tabJournal Voucher Detail` set `%s`=null,
modified=%s, modified_by=%s
where `%s`=%s and docstatus < 2""" % (against_field, "%s", "%s", against_field, "%s"),
(now(), webnotes.session.user, ref_no))
linked_jv = webnotes.conn.sql_list("""select parent from `tabJournal Voucher Detail`
where `%s`=%s and docstatus < 2""" % (against_field, "%s"), (ref_no))
if linked_jv:
webnotes.conn.sql("""update `tabJournal Voucher Detail` set `%s`=null,
modified=%s, modified_by=%s
where `%s`=%s and docstatus < 2""" % (against_field, "%s", "%s", against_field, "%s"),
(now(), webnotes.session.user, ref_no))
webnotes.conn.sql("""update `tabGL Entry`
set against_voucher_type=null, against_voucher=null,
modified=%s, modified_by=%s
where against_voucher_type=%s and against_voucher=%s
and voucher_no != ifnull(against_voucher, '')""",
(now(), webnotes.session.user, ref_type, ref_no))
webnotes.conn.sql("""update `tabGL Entry`
set against_voucher_type=null, against_voucher=null,
modified=%s, modified_by=%s
where against_voucher_type=%s and against_voucher=%s
and voucher_no != ifnull(against_voucher, '')""",
(now(), webnotes.session.user, ref_type, ref_no))
webnotes.msgprint("{msg} {linked_jv}".format(msg = _("""Following linked Journal Vouchers \
made against this transaction has been unlinked. You can link them again with other \
transactions via Payment Reconciliation Tool."""), linked_jv="\n".join(linked_jv)))
@webnotes.whitelist()
def get_company_default(company, fieldname):
@@ -369,3 +379,12 @@ def get_account_for(account_for_doctype, account_for):
return webnotes.conn.get_value("Account", {account_for_field: account_for_doctype,
"master_name": account_for})
def get_currency_precision(currency=None):
if not currency:
currency = webnotes.conn.get_value("Company",
webnotes.conn.get_default("company"), "default_currency")
currency_format = webnotes.conn.get_value("Currency", currency, "number_format")
from webnotes.utils import get_number_format_info
return get_number_format_info(currency_format)[2]

View File

@@ -22,7 +22,7 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
if(this.frm.fields_dict.buying_price_list) {
this.frm.set_query("buying_price_list", function() {
return{
filters: { 'buying_or_selling': "Buying" }
filters: { 'buying': 1 }
}
});
}
@@ -302,11 +302,11 @@ 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,
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_import = flt(this.frm.doc.grand_total /
this.frm.doc.conversion_rate, precision("grand_total_import"));
this.frm.doc.total_tax = flt(this.frm.doc.grand_total - this.frm.doc.net_total,
precision("total_tax"));
@@ -321,20 +321,26 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
}
// other charges added/deducted
this.frm.doc.other_charges_added = 0.0
this.frm.doc.other_charges_deducted = 0.0
if(tax_count) {
this.frm.doc.other_charges_added = wn.utils.sum($.map(this.frm.tax_doclist,
function(tax) { return (tax.add_deduct_tax == "Add" && in_list(["Valuation and Total", "Total"], tax.category)) ? tax.tax_amount : 0.0; }));
function(tax) { return (tax.add_deduct_tax == "Add"
&& in_list(["Valuation and Total", "Total"], tax.category)) ?
tax.tax_amount : 0.0; }));
this.frm.doc.other_charges_deducted = wn.utils.sum($.map(this.frm.tax_doclist,
function(tax) { return (tax.add_deduct_tax == "Deduct" && in_list(["Valuation and Total", "Total"], tax.category)) ? tax.tax_amount : 0.0; }));
function(tax) { return (tax.add_deduct_tax == "Deduct"
&& in_list(["Valuation and Total", "Total"], tax.category)) ?
tax.tax_amount : 0.0; }));
wn.model.round_floats_in(this.frm.doc, ["other_charges_added", "other_charges_deducted"]);
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 / this.frm.doc.conversion_rate,
precision("other_charges_deducted_import"));
wn.model.round_floats_in(this.frm.doc,
["other_charges_added", "other_charges_deducted"]);
}
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 /
this.frm.doc.conversion_rate, precision("other_charges_deducted_import"));
},
_cleanup: function() {

View File

@@ -22,7 +22,7 @@ class TestPurchaseOrder(unittest.TestCase):
pr = make_purchase_receipt(po.doc.name)
pr[0]["supplier_warehouse"] = "_Test Warehouse 1 - _TC"
pr[0]["posting_date"] = "2013-05-12"
self.assertEquals(pr[0]["doctype"], "Purchase Receipt")
self.assertEquals(len(pr), len(test_records[0]))
@@ -52,7 +52,7 @@ class TestPurchaseOrder(unittest.TestCase):
self.assertEquals(pr[0]["doctype"], "Purchase Receipt")
self.assertEquals(len(pr), len(test_records[0]))
pr[0]["posting_date"] = "2013-05-12"
pr[0].naming_series = "_T-Purchase Receipt-"
pr[1].qty = 4.0
pr_bean = webnotes.bean(pr)
@@ -66,6 +66,7 @@ class TestPurchaseOrder(unittest.TestCase):
pr1 = make_purchase_receipt(po.doc.name)
pr1[0].naming_series = "_T-Purchase Receipt-"
pr1[0]["posting_date"] = "2013-05-12"
pr1[1].qty = 8
pr1_bean = webnotes.bean(pr1)
pr1_bean.insert()
@@ -88,7 +89,7 @@ class TestPurchaseOrder(unittest.TestCase):
self.assertEquals(pi[0]["doctype"], "Purchase Invoice")
self.assertEquals(len(pi), len(test_records[0]))
pi[0]["posting_date"] = "2013-05-12"
pi[0].bill_no = "NA"
webnotes.bean(pi).insert()

View File

@@ -3,7 +3,7 @@
wn.require('app/setup/doctype/contact_control/contact_control.js');
cur_frm.cscript.refresh = function(doc,dt,dn) {
cur_frm.cscript.refresh = function(doc, dt, dn) {
cur_frm.cscript.make_dashboard(doc);
erpnext.hide_naming_series();
@@ -93,8 +93,8 @@ cur_frm.cscript.make_contact = function() {
cur_frm.contact_list.run();
}
cur_frm.fields_dict['default_price_list'].get_query = function(doc,cdt,cdn) {
cur_frm.fields_dict['default_price_list'].get_query = function(doc, cdt, cdn) {
return{
filters:{'buying_or_selling': "Buying"}
filters:{'buying': 1}
}
}

View File

@@ -2,7 +2,7 @@
{
"creation": "2013-05-13 16:10:02",
"docstatus": 0,
"modified": "2013-05-13 16:21:07",
"modified": "2014-01-24 18:19:11",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -11,7 +11,7 @@
"doctype": "Report",
"is_standard": "Yes",
"name": "__common__",
"query": "select \n mr.name as \"Material Request:Link/Material Request:120\",\n\tmr.transaction_date as \"Date:Date:100\",\n\tmr_item.item_code as \"Item Code:Link/Item:120\",\n\tmr_item.qty as \"Qty:Float:100\",\n\tmr_item.ordered_qty as \"Ordered Qty:Float:100\", \n\t(mr_item.qty - ifnull(mr_item.ordered_qty, 0)) as \"Qty to Order:Float:100\",\n\tmr_item.item_name as \"Item Name::150\",\n\tmr_item.description as \"Description::200\"\nfrom\n\t`tabMaterial Request` mr, `tabMaterial Request Item` mr_item\nwhere\n\tmr_item.parent = mr.name\n\tand mr.material_request_type = \"Purchase\"\n\tand mr.docstatus = 1\n\tand mr.status != \"Stopped\"\n\tand ifnull(mr_item.ordered_qty, 0) < ifnull(mr_item.qty, 0)\norder by mr.transaction_date asc",
"query": "select \n mr.name as \"Material Request:Link/Material Request:120\",\n\tmr.transaction_date as \"Date:Date:100\",\n\tmr_item.item_code as \"Item Code:Link/Item:120\",\n\tsum(ifnull(mr_item.qty, 0)) as \"Qty:Float:100\",\n\tsum(ifnull(mr_item.ordered_qty, 0)) as \"Ordered Qty:Float:100\", \n\t(sum(mr_item.qty) - sum(ifnull(mr_item.ordered_qty, 0))) as \"Qty to Order:Float:100\",\n\tmr_item.item_name as \"Item Name::150\",\n\tmr_item.description as \"Description::200\"\nfrom\n\t`tabMaterial Request` mr, `tabMaterial Request Item` mr_item\nwhere\n\tmr_item.parent = mr.name\n\tand mr.material_request_type = \"Purchase\"\n\tand mr.docstatus = 1\n\tand mr.status != \"Stopped\"\ngroup by mr.name, mr_item.item_code\nhaving\n\tsum(ifnull(mr_item.ordered_qty, 0)) < sum(ifnull(mr_item.qty, 0))\norder by mr.transaction_date asc",
"ref_doctype": "Purchase Order",
"report_name": "Requested Items To Be Ordered",
"report_type": "Query Report"

View File

@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import webnotes
from webnotes import msgprint, _
from webnotes import msgprint, _, throw
from webnotes.utils import getdate, flt, add_days, cstr
import json
@@ -89,8 +89,10 @@ def _get_price_list_rate(args, item_bean, meta):
# try fetching from price list
if args.buying_price_list and args.price_list_currency:
price_list_rate = webnotes.conn.sql("""select ref_rate from `tabItem Price`
where price_list=%s and item_code=%s and buying_or_selling='Buying'""",
price_list_rate = webnotes.conn.sql("""select ip.ref_rate from
`tabItem Price` ip, `tabPrice List` pl
where ip.price_list=pl.name and ip.price_list=%s and
ip.item_code=%s and ip.buying=1 and pl.enabled=1""",
(args.buying_price_list, args.item_code), as_dict=1)
if price_list_rate:
@@ -122,14 +124,12 @@ def _validate_item_details(args, item):
# validate if purchase item or subcontracted item
if item.is_purchase_item != "Yes":
msgprint(_("Item") + (" %s: " % item.name) + _("not a purchase item"),
raise_exception=True)
throw(_("Item") + (" %s: " % item.name) + _("not a purchase item"))
if args.is_subcontracted == "Yes" and item.is_sub_contracted_item != "Yes":
msgprint(_("Item") + (" %s: " % item.name) +
throw(_("Item") + (" %s: " % item.name) +
_("not a sub-contracted item.") +
_("Please select a sub-contracted item or do not sub-contract the transaction."),
raise_exception=True)
_("Please select a sub-contracted item or do not sub-contract the transaction."))
def get_last_purchase_details(item_code, doc_name=None, conversion_rate=1.0):
"""returns last purchase details in stock uom"""

View File

@@ -1,6 +1,6 @@
{
"app_name": "ERPNext",
"app_version": "3.3.3",
"app_version": "3.7.0",
"base_template": "app/portal/templates/base.html",
"modules": {
"Accounts": {
@@ -74,5 +74,5 @@
"type": "module"
}
},
"requires_framework_version": "==3.3.1"
"requires_framework_version": "==3.8.0"
}

View File

@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import webnotes
from webnotes import _, msgprint
from webnotes import _, throw
from webnotes.utils import flt, cint, today, cstr
from webnotes.model.code import get_obj
from setup.utils import get_company_currency
@@ -44,14 +44,13 @@ class AccountsController(TransactionBase):
def validate_for_freezed_account(self):
for fieldname in ["customer", "supplier"]:
if self.meta.get_field(fieldname) and self.doc.fields.get(fieldname):
accounts = webnotes.conn.get_values("Account", {"master_type": fieldname.title(),
"master_name": self.doc.fields[fieldname], "company": self.doc.company},
"freeze_account", as_dict=1)
accounts = webnotes.conn.get_values("Account",
{"master_type": fieldname.title(), "master_name": self.doc.fields[fieldname],
"company": self.doc.company}, "name")
if accounts:
if not filter(lambda x: cstr(x.freeze_account) in ["", "No"], accounts):
msgprint(_("Account for this ") + fieldname + _(" has been freezed. ") +
self.doc.doctype + _(" can not be made."), raise_exception=1)
from accounts.doctype.gl_entry.gl_entry import validate_frozen_account
for account in accounts:
validate_frozen_account(account[0])
def set_price_list_currency(self, buying_or_selling):
if self.meta.get_field("currency"):
@@ -179,17 +178,17 @@ class AccountsController(TransactionBase):
"""
if tax.charge_type in ["On Previous Row Amount", "On Previous Row Total"] and \
(not tax.row_id or cint(tax.row_id) >= tax.idx):
msgprint((_("Row") + " # %(idx)s [%(taxes_doctype)s]: " + \
throw((_("Row") + " # %(idx)s [%(taxes_doctype)s]: " + \
_("Please specify a valid") + " %(row_id_label)s") % {
"idx": tax.idx,
"taxes_doctype": tax.doctype,
"row_id_label": self.meta.get_label("row_id",
parentfield=self.other_fname)
}, raise_exception=True)
})
def validate_inclusive_tax(self, tax):
def _on_previous_row_error(row_range):
msgprint((_("Row") + " # %(idx)s [%(doctype)s]: " +
throw((_("Row") + " # %(idx)s [%(doctype)s]: " +
_("to be included in Item's rate, it is required that: ") +
" [" + _("Row") + " # %(row_range)s] " + _("also be included in Item's rate")) % {
"idx": tax.idx,
@@ -200,12 +199,12 @@ class AccountsController(TransactionBase):
parentfield=self.other_fname),
"charge_type": tax.charge_type,
"row_range": row_range
}, raise_exception=True)
})
if cint(tax.included_in_print_rate):
if tax.charge_type == "Actual":
# inclusive tax cannot be of type Actual
msgprint((_("Row")
throw((_("Row")
+ " # %(idx)s [%(doctype)s]: %(charge_type_label)s = \"%(charge_type)s\" "
+ "cannot be included in Item's rate") % {
"idx": tax.idx,
@@ -213,7 +212,7 @@ class AccountsController(TransactionBase):
"charge_type_label": self.meta.get_label("charge_type",
parentfield=self.other_fname),
"charge_type": tax.charge_type,
}, raise_exception=True)
})
elif tax.charge_type == "On Previous Row Amount" and \
not cint(self.tax_doclist[tax.row_id - 1].included_in_print_rate):
# referred row should also be inclusive
@@ -224,23 +223,22 @@ class AccountsController(TransactionBase):
_on_previous_row_error("1 - %d" % (tax.row_id,))
def calculate_taxes(self):
for item in self.item_doclist:
# maintain actual tax rate based on idx
actual_tax_dict = dict([[tax.idx, tax.rate] for tax in self.tax_doclist
if tax.charge_type == "Actual"])
for n, item in enumerate(self.item_doclist):
item_tax_map = self._load_item_tax_rate(item.item_tax_rate)
for i, tax in enumerate(self.tax_doclist):
# tax_amount represents the amount of tax for the current step
current_tax_amount = self.get_current_tax_amount(item, tax, item_tax_map)
if hasattr(self, "set_item_tax_amount"):
self.set_item_tax_amount(item, tax, current_tax_amount)
# case when net total is 0 but there is an actual type charge
# in this case add the actual amount to tax.tax_amount
# and tax.grand_total_for_current_item for the first such iteration
if tax.charge_type=="Actual" and \
not (current_tax_amount or self.doc.net_total or tax.tax_amount):
zero_net_total_adjustment = flt(tax.rate, self.precision("tax_amount", tax))
current_tax_amount += zero_net_total_adjustment
# Adjust divisional loss to the last item
if tax.charge_type == "Actual":
actual_tax_dict[tax.idx] -= current_tax_amount
if n == len(self.item_doclist) - 1:
current_tax_amount += actual_tax_dict[tax.idx]
# store tax_amount for current item as it will be used for
# charge type = 'On Previous Row Amount'
@@ -252,7 +250,8 @@ class AccountsController(TransactionBase):
if tax.category:
# if just for valuation, do not add the tax amount in total
# hence, setting it as 0 for further steps
current_tax_amount = 0.0 if (tax.category == "Valuation") else current_tax_amount
current_tax_amount = 0.0 if (tax.category == "Valuation") \
else current_tax_amount
current_tax_amount *= -1.0 if (tax.add_deduct_tax == "Deduct") else 1.0
@@ -271,6 +270,11 @@ class AccountsController(TransactionBase):
# in tax.total, accumulate grand total of each item
tax.total += tax.grand_total_for_current_item
# set precision in the last item iteration
if n == len(self.item_doclist) - 1:
tax.total = flt(tax.total, self.precision("total", tax))
tax.tax_amount = flt(tax.tax_amount, self.precision("tax_amount", tax))
def get_current_tax_amount(self, item, tax, item_tax_map):
tax_rate = self._get_tax_rate(tax, item_tax_map)
current_tax_amount = 0.0
@@ -384,24 +388,45 @@ class AccountsController(TransactionBase):
})
def validate_multiple_billing(self, ref_dt, item_ref_dn, based_on, parentfield):
from controllers.status_updater import get_tolerance_for
item_tolerance = {}
global_tolerance = None
for item in self.doclist.get({"parentfield": "entries"}):
if item.fields.get(item_ref_dn):
already_billed = webnotes.conn.sql("""select sum(%s) from `tab%s`
where %s=%s and docstatus=1""" % (based_on, self.tname, item_ref_dn, '%s'),
item.fields[item_ref_dn])[0][0]
max_allowed_amt = flt(webnotes.conn.get_value(ref_dt + " Item",
ref_amt = flt(webnotes.conn.get_value(ref_dt + " Item",
item.fields[item_ref_dn], based_on), self.precision(based_on, item))
if not ref_amt:
webnotes.msgprint(_("As amount for item") + ": " + item.item_code + _(" in ") +
ref_dt + _(" is zero, system will not check for over-billed"))
else:
already_billed = webnotes.conn.sql("""select sum(%s) from `tab%s`
where %s=%s and docstatus=1 and parent != %s""" %
(based_on, self.tname, item_ref_dn, '%s', '%s'),
(item.fields[item_ref_dn], self.doc.name))[0][0]
total_billed_amt = flt(flt(already_billed) + flt(item.fields[based_on]),
self.precision(based_on, item))
total_billed_amt = flt(flt(already_billed) + flt(item.fields[based_on]),
self.precision(based_on, item))
tolerance, item_tolerance, global_tolerance = get_tolerance_for(item.item_code,
item_tolerance, global_tolerance)
if max_allowed_amt and total_billed_amt - max_allowed_amt > 0.02:
webnotes.msgprint(_("Row ")+ cstr(item.idx) + ": " + cstr(item.item_code) +
_(" will be over-billed against mentioned ") + cstr(ref_dt) +
_(". Max allowed " + cstr(based_on) + ": " + cstr(max_allowed_amt)),
raise_exception=1)
max_allowed_amt = flt(ref_amt * (100 + tolerance) / 100)
if total_billed_amt - max_allowed_amt > 0.01:
reduce_by = total_billed_amt - max_allowed_amt
webnotes.throw(_("Row #") + cstr(item.idx) + ": " +
_(" Max amount allowed for Item ") + cstr(item.item_code) +
_(" against ") + ref_dt + " " +
cstr(item.fields[ref_dt.lower().replace(" ", "_")]) + _(" is ") +
cstr(max_allowed_amt) + ". \n" +
_("""If you want to increase your overflow tolerance, please increase \
tolerance % in Global Defaults or Item master.
Or, you must reduce the amount by """) + cstr(reduce_by) + "\n" +
_("""Also, please check if the order item has already been billed \
in the Sales Order"""))
def get_company_default(self, fieldname):
from accounts.utils import get_company_default
return get_company_default(self.doc.company, fieldname)

View File

@@ -108,10 +108,11 @@ class BuyingController(StockController):
item.import_amount = flt(item.import_rate * item.qty,
self.precision("import_amount", item))
item.item_tax_amount = 0.0;
self._set_in_company_currency(item, "import_amount", "amount")
self._set_in_company_currency(item, "import_ref_rate", "purchase_ref_rate")
self._set_in_company_currency(item, "import_rate", "rate")
self._set_in_company_currency(item, "import_amount", "amount")
def calculate_net_total(self):
self.doc.net_total = self.doc.net_total_import = 0.0
@@ -123,8 +124,8 @@ class BuyingController(StockController):
self.round_floats_in(self.doc, ["net_total", "net_total_import"])
def calculate_totals(self):
self.doc.grand_total = flt(self.tax_doclist and \
self.tax_doclist[-1].total or self.doc.net_total, self.precision("grand_total"))
self.doc.grand_total = flt(self.tax_doclist[-1].total if self.tax_doclist
else self.doc.net_total, self.precision("grand_total"))
self.doc.grand_total_import = flt(self.doc.grand_total / self.doc.conversion_rate,
self.precision("grand_total_import"))
@@ -136,6 +137,24 @@ class BuyingController(StockController):
if self.meta.get_field("rounded_total_import"):
self.doc.rounded_total_import = _round(self.doc.grand_total_import)
if self.meta.get_field("other_charges_added"):
self.doc.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"]]),
self.precision("other_charges_added"))
if self.meta.get_field("other_charges_deducted"):
self.doc.other_charges_deducted = flt(sum([flt(d.tax_amount) for d in self.tax_doclist
if d.add_deduct_tax=="Deduct" and d.category in ["Valuation and Total", "Total"]]),
self.precision("other_charges_deducted"))
if self.meta.get_field("other_charges_added_import"):
self.doc.other_charges_added_import = flt(self.doc.other_charges_added /
self.doc.conversion_rate, self.precision("other_charges_added_import"))
if self.meta.get_field("other_charges_deducted_import"):
self.doc.other_charges_deducted_import = flt(self.doc.other_charges_deducted /
self.doc.conversion_rate, self.precision("other_charges_deducted_import"))
def calculate_outstanding_amount(self):
if self.doc.doctype == "Purchase Invoice" and self.doc.docstatus < 2:
@@ -162,35 +181,52 @@ class BuyingController(StockController):
if not self.meta.get_field("item_tax_amount", parentfield=self.fname):
for item in self.item_doclist:
del item.fields["item_tax_amount"]
def set_item_tax_amount(self, item, tax, current_tax_amount):
# update valuation rate
def update_valuation_rate(self, parentfield):
"""
item_tax_amount is the total tax amount applied on that item
stored for valuation
TODO: rename item_tax_amount to valuation_tax_amount
"""
if tax.category in ["Valuation", "Valuation and Total"] and \
self.meta.get_field("item_tax_amount", parentfield=self.fname):
item.item_tax_amount += flt(current_tax_amount, self.precision("item_tax_amount", item))
# update valuation rate
def update_valuation_rate(self, parentfield):
for item in self.doclist.get({"parentfield": parentfield}):
item.conversion_factor = item.conversion_factor or flt(webnotes.conn.get_value(
"UOM Conversion Detail", {"parent": item.item_code, "uom": item.uom},
"conversion_factor")) or 1
stock_items = self.get_stock_items()
stock_items_qty, stock_items_amount = 0, 0
last_stock_item_idx = 1
for d in self.doclist.get({"parentfield": parentfield}):
if d.item_code and d.item_code in stock_items:
stock_items_qty += flt(d.qty)
stock_items_amount += flt(d.amount)
last_stock_item_idx = d.idx
if item.item_code and item.qty:
total_valuation_amount = sum([flt(d.tax_amount) for d in
self.doclist.get({"parentfield": "purchase_tax_details"})
if d.category in ["Valuation", "Valuation and Total"]])
valuation_amount_adjustment = total_valuation_amount
for i, item in enumerate(self.doclist.get({"parentfield": parentfield})):
if item.item_code and item.qty and item.item_code in stock_items:
item_proportion = flt(item.amount) / stock_items_amount if stock_items_amount \
else flt(item.qty) / stock_items_qty
if i == (last_stock_item_idx - 1):
item.item_tax_amount = flt(valuation_amount_adjustment,
self.precision("item_tax_amount", item))
else:
item.item_tax_amount = flt(item_proportion * total_valuation_amount,
self.precision("item_tax_amount", item))
valuation_amount_adjustment -= item.item_tax_amount
self.round_floats_in(item)
purchase_rate = item.rate if self.doc.doctype == "Purchase Invoice" else item.purchase_rate
# if no item code, which is sometimes the case in purchase invoice,
# then it is not possible to track valuation against it
item.valuation_rate = flt((purchase_rate +
(item.item_tax_amount + item.rm_supp_cost) / item.qty) / item.conversion_factor,
self.precision("valuation_rate", item))
item.conversion_factor = item.conversion_factor or flt(webnotes.conn.get_value(
"UOM Conversion Detail", {"parent": item.item_code, "uom": item.uom},
"conversion_factor")) or 1
qty_in_stock_uom = flt(item.qty * item.conversion_factor)
item.valuation_rate = ((item.amount + item.item_tax_amount + item.rm_supp_cost)
/ qty_in_stock_uom)
else:
item.valuation_rate = 0.0

View File

@@ -191,7 +191,8 @@ class SellingController(StockController):
self.doc.other_charges_total = flt(self.doc.grand_total - self.doc.net_total,
self.precision("other_charges_total"))
self.doc.other_charges_total_export = flt(self.doc.grand_total_export - self.doc.net_total_export,
self.doc.other_charges_total_export = flt(
self.doc.grand_total_export - self.doc.net_total_export,
self.precision("other_charges_total_export"))
self.doc.rounded_total = _round(self.doc.grand_total)

View File

@@ -151,7 +151,9 @@ class StatusUpdater(DocListController):
"""
# check if overflow is within tolerance
tolerance = self.get_tolerance_for(item['item_code'])
tolerance, self.tolerance, self.global_tolerance = get_tolerance_for(item['item_code'],
self.tolerance, self.global_tolerance)
overflow_percent = ((item[args['target_field']] - item[args['target_ref_field']]) /
item[args['target_ref_field']]) * 100
@@ -170,23 +172,6 @@ class StatusUpdater(DocListController):
Also, please check if the order item has already been billed in the Sales Order""" %
item, raise_exception=1)
def get_tolerance_for(self, item_code):
"""
Returns the tolerance for the item, if not set, returns global tolerance
"""
if self.tolerance.get(item_code): return self.tolerance[item_code]
tolerance = flt(webnotes.conn.get_value('Item',item_code,'tolerance') or 0)
if not tolerance:
if self.global_tolerance == None:
self.global_tolerance = flt(webnotes.conn.get_value('Global Defaults', None,
'tolerance'))
tolerance = self.global_tolerance
self.tolerance[item_code] = tolerance
return tolerance
def update_qty(self, change_modified=True):
@@ -245,4 +230,59 @@ class StatusUpdater(DocListController):
set %(status_field)s = if(ifnull(%(target_parent_field)s,0)<0.001,
'Not %(keyword)s', if(%(target_parent_field)s>=99.99,
'Fully %(keyword)s', 'Partly %(keyword)s'))
where name='%(name)s'""" % args)
where name='%(name)s'""" % args)
def update_billing_status_for_zero_amount_refdoc(self, ref_dt):
ref_fieldname = ref_dt.lower().replace(" ", "_")
zero_amount_refdoc = []
all_zero_amount_refdoc = webnotes.conn.sql_list("""select name from `tab%s`
where docstatus=1 and net_total = 0""" % ref_dt)
for item in self.doclist.get({"parentfield": "entries"}):
if item.fields.get(ref_fieldname) \
and item.fields.get(ref_fieldname) in all_zero_amount_refdoc \
and item.fields.get(ref_fieldname) not in zero_amount_refdoc:
zero_amount_refdoc.append(item.fields[ref_fieldname])
if zero_amount_refdoc:
self.update_biling_status(zero_amount_refdoc, ref_dt, ref_fieldname)
def update_biling_status(self, zero_amount_refdoc, ref_dt, ref_fieldname):
for ref_dn in zero_amount_refdoc:
ref_doc_qty = flt(webnotes.conn.sql("""select sum(ifnull(qty, 0)) from `tab%s Item`
where parent=%s""" % (ref_dt, '%s'), (ref_dn))[0][0])
billed_qty = flt(webnotes.conn.sql("""select sum(ifnull(qty, 0))
from `tab%s Item` where %s=%s and docstatus=1""" %
(self.doc.doctype, ref_fieldname, '%s'), (ref_dn))[0][0])
per_billed = ((ref_doc_qty if billed_qty > ref_doc_qty else billed_qty)\
/ ref_doc_qty)*100
webnotes.conn.set_value(ref_dt, ref_dn, "per_billed", per_billed)
from webnotes.model.meta import has_field
if has_field(ref_dt, "billing_status"):
if per_billed < 0.001: billing_status = "Not Billed"
elif per_billed >= 99.99: billing_status = "Fully Billed"
else: billing_status = "Partly Billed"
webnotes.conn.set_value(ref_dt, ref_dn, "billing_status", billing_status)
def get_tolerance_for(item_code, item_tolerance={}, global_tolerance=None):
"""
Returns the tolerance for the item, if not set, returns global tolerance
"""
if item_tolerance.get(item_code):
return item_tolerance[item_code], item_tolerance, global_tolerance
tolerance = flt(webnotes.conn.get_value('Item',item_code,'tolerance') or 0)
if not tolerance:
if global_tolerance == None:
global_tolerance = flt(webnotes.conn.get_value('Global Defaults', None,
'tolerance'))
tolerance = global_tolerance
item_tolerance[item_code] = tolerance
return tolerance, item_tolerance, global_tolerance

View File

@@ -43,7 +43,7 @@ cur_frm.cscript.make_jv = function(doc, dt, dn) {
jv = locals['Journal Voucher'][jv];
jv.voucher_type = 'Bank Voucher';
jv.user_remark = wn._('Payment of salary for the month: ') + doc.month +
wn._('and fiscal year: ') + doc.fiscal_year;
wn._(' and fiscal year: ') + doc.fiscal_year;
jv.fiscal_year = doc.fiscal_year;
jv.company = doc.company;
jv.posting_date = dateutil.obj_to_str(new Date());

View File

@@ -7,7 +7,7 @@ wn.query_reports["Monthly Salary Register"] = {
"fieldname":"month",
"label": wn._("Month"),
"fieldtype": "Select",
"options": "Jan\nFeb\nMar\nApr\nMay\nJun\nJul\nAug\nSep\nOct\nNov\nDec",
"options": "\nJan\nFeb\nMar\nApr\nMay\nJun\nJul\nAug\nSep\nOct\nNov\nDec",
"default": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov",
"Dec"][wn.datetime.str_to_obj(wn.datetime.get_today()).getMonth()],
},

View File

@@ -50,17 +50,17 @@ def get_columns(salary_slips):
where ifnull(d_modified_amount, 0) != 0 and parent in (%s)""" %
(', '.join(['%s']*len(salary_slips))), tuple([d.name for d in salary_slips]))
columns = columns + [(e + ":Link/Earning Type:120") for e in earning_types] + \
columns = columns + [(e + ":Currency:120") for e in earning_types] + \
["Arrear Amount:Currency:120", "Leave Encashment Amount:Currency:150",
"Gross Pay:Currency:120"] + [(d + ":Link/Deduction Type:120") for d in ded_types] + \
"Gross Pay:Currency:120"] + [(d + ":Currency:120") for d in ded_types] + \
["Total Deduction:Currency:120", "Net Pay:Currency:120"]
return columns, earning_types, ded_types
def get_salary_slips(filters):
conditions, filters = get_conditions(filters)
salary_slips = webnotes.conn.sql("""select * from `tabSalary Slip` where docstatus = 1 %s""" %
conditions, filters, as_dict=1)
salary_slips = webnotes.conn.sql("""select * from `tabSalary Slip` where docstatus = 1 %s
order by employee, month""" % conditions, filters, as_dict=1)
if not salary_slips:
msgprint(_("No salary slip found for month: ") + cstr(filters.get("month")) +
@@ -102,6 +102,6 @@ def get_ss_ded_map(salary_slips):
ss_ded_map = {}
for d in ss_deductions:
ss_ded_map.setdefault(d.parent, webnotes._dict()).setdefault(d.d_type, [])
ss_ded_map[d.parent][d.e_type] = flt(d.d_modified_amount)
ss_ded_map[d.parent][d.d_type] = flt(d.d_modified_amount)
return ss_ded_map

View File

@@ -5,6 +5,7 @@
from __future__ import unicode_literals
import os, sys
import argparse
import subprocess
is_redhat = is_debian = None
root_password = None
@@ -19,7 +20,7 @@ requirements = [
"jinja2",
"markdown2",
"markupsafe",
"mysql-python",
"mysql-python",
"pygeoip",
"python-dateutil",
"python-memcached",
@@ -80,7 +81,7 @@ def validate_install():
return is_redhat, is_debian
def install_using_yum():
packages = "python python-setuptools gcc python-devel MySQL-python git memcached ntp vim-enhanced screen"
packages = "gcc MySQL-python git memcached ntp vim-enhanced screen"
print "-"*80
print "Installing Packages: (This may take some time)"
@@ -88,7 +89,10 @@ def install_using_yum():
print "-"*80
exec_in_shell("yum install -y %s" % packages)
if not exec_in_shell("which mysql"):
try:
exec_in_shell("which mysql")
except subprocess.CalledProcessError:
packages = "mysql mysql-server mysql-devel"
print "Installing Packages:", packages
exec_in_shell("yum install -y %s" % packages)
@@ -101,26 +105,19 @@ def install_using_yum():
exec_in_shell('mysqladmin -u root password "%s"' % (root_password,))
print "Root password set as", root_password
# install htop
if not exec_in_shell("which htop"):
try:
exec_in_shell("cd /tmp && rpm -i --force http://packages.sw.be/rpmforge-release/rpmforge-release-0.5.2-2.el6.rf.x86_64.rpm && yum install -y htop")
except:
pass
update_config_for_redhat()
def update_config_for_redhat():
import re
# set to autostart on startup
for service in ("mysqld", "memcached", "ntpd"):
for service in ("mysqld", "memcached"):
exec_in_shell("chkconfig --level 2345 %s on" % service)
exec_in_shell("service %s restart" % service)
def install_using_apt():
exec_in_shell("apt-get update")
packages = "python python-setuptools python-dev build-essential python-pip python-mysqldb git memcached ntp vim screen htop"
packages = "python python-setuptools python-dev build-essential python-mysqldb git memcached ntp vim screen htop"
print "-"*80
print "Installing Packages: (This may take some time)"
print packages
@@ -132,7 +129,9 @@ def install_using_apt():
exec_in_shell("echo mysql-server mysql-server/root_password password %s | sudo debconf-set-selections" % root_password)
exec_in_shell("echo mysql-server mysql-server/root_password_again password %s | sudo debconf-set-selections" % root_password)
if not exec_in_shell("which mysql"):
try:
exec_in_shell("which mysql")
except subprocess.CalledProcessError:
packages = "mysql-server libmysqlclient-dev"
print "Installing Packages:", packages
exec_in_shell("apt-get install -y %s" % packages)
@@ -140,7 +139,7 @@ def install_using_apt():
update_config_for_debian()
def update_config_for_debian():
for service in ("mysql", "ntpd"):
for service in ("mysql",):
exec_in_shell("service %s restart" % service)
def install_python_modules():
@@ -148,13 +147,14 @@ def install_python_modules():
print "Installing Python Modules: (This may take some time)"
print "-"*80
if not exec_in_shell("which pip"):
exec_in_shell("easy_install pip")
try:
exec_in_shell("which pip2.7")
except subprocess.CalledProcessError:
exec_in_shell("easy_install-2.7 pip")
exec_in_shell("pip install --upgrade pip")
exec_in_shell("pip install --upgrade setuptools")
exec_in_shell("pip install --upgrade virtualenv")
exec_in_shell("pip install {}".format(' '.join(requirements)))
exec_in_shell("pip2.7 install --upgrade setuptools --no-use-wheel")
exec_in_shell("pip2.7 install --upgrade setuptools")
exec_in_shell("pip2.7 install {}".format(' '.join(requirements)))
def install_erpnext(install_path):
print
@@ -200,7 +200,7 @@ def setup_folders(install_path):
app = os.path.join(install_path, "app")
if not os.path.exists(app):
print "Cloning erpnext"
exec_in_shell("cd %s && git clone https://github.com/webnotes/erpnext.git app" % install_path)
exec_in_shell("cd %s && git clone --branch master https://github.com/webnotes/erpnext.git app" % install_path)
exec_in_shell("cd app && git config core.filemode false")
if not os.path.exists(app):
raise Exception, "Couldn't clone erpnext repository"
@@ -208,7 +208,7 @@ def setup_folders(install_path):
lib = os.path.join(install_path, "lib")
if not os.path.exists(lib):
print "Cloning wnframework"
exec_in_shell("cd %s && git clone https://github.com/webnotes/wnframework.git lib" % install_path)
exec_in_shell("cd %s && git clone --branch master https://github.com/webnotes/wnframework.git lib" % install_path)
exec_in_shell("cd lib && git config core.filemode false")
if not os.path.exists(lib):
raise Exception, "Couldn't clone wnframework repository"
@@ -243,28 +243,8 @@ def post_install(install_path):
def exec_in_shell(cmd):
# using Popen instead of os.system - as recommended by python docs
from subprocess import Popen
import tempfile
with tempfile.TemporaryFile() as stdout:
with tempfile.TemporaryFile() as stderr:
p = Popen(cmd, shell=True, stdout=stdout, stderr=stderr)
p.wait()
stdout.seek(0)
out = stdout.read()
if out: out = out.decode('utf-8')
stderr.seek(0)
err = stderr.read()
if err: err = err.decode('utf-8')
if err and any((kw in err.lower() for kw in ["traceback", "error", "exception"])):
print out
raise Exception, err
else:
print "."
import subprocess
out = subprocess.check_output(cmd, shell=True)
return out
def parse_args():

View File

@@ -34,6 +34,8 @@ class TestProductionOrder(unittest.TestCase):
stock_entry = webnotes.bean(stock_entry)
stock_entry.doc.fg_completed_qty = 4
stock_entry.doc.posting_date = "2013-05-12"
stock_entry.doc.fiscal_year = "_Test Fiscal Year 2013"
stock_entry.run_method("get_items")
stock_entry.submit()
@@ -50,7 +52,8 @@ class TestProductionOrder(unittest.TestCase):
stock_entry = make_stock_entry(pro_order, "Manufacture/Repack")
stock_entry = webnotes.bean(stock_entry)
stock_entry.doc.posting_date = "2013-05-12"
stock_entry.doc.fiscal_year = "_Test Fiscal Year 2013"
stock_entry.doc.fg_completed_qty = 15
stock_entry.run_method("get_items")
stock_entry.insert()

View File

@@ -243,10 +243,10 @@ class DocType:
"item_code": [qty_required, description, stock_uom, min_order_qty]
}
"""
bom_wise_item_details = {}
item_list = []
for bom, so_wise_qty in bom_dict.items():
bom_wise_item_details = {}
if self.doc.use_multi_level_bom:
# get all raw materials with sub assembly childs
for d in webnotes.conn.sql("""select fb.item_code,

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 webnotes
def execute():
webnotes.conn.sql("""update `tabItem Price` ip INNER JOIN `tabItem` i
ON (ip.item_code = i.name)
set ip.item_name = i.item_name, ip.item_description = i.description""")

0
patches/1401/__init__.py Normal file
View File

View File

@@ -0,0 +1,9 @@
# Copyright (c) 2014, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import webnotes
def execute():
webnotes.reload_doc("stock", "doctype", "price_list")
webnotes.conn.sql("""update `tabPrice List` set enabled=1""")

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
import webnotes
def execute():
from utilities.repost_stock import repost_stock
for d in webnotes.conn.sql("""select distinct production_item, fg_warehouse
from `tabProduction Order` where docstatus>0""", as_dict=1):
repost_stock(d.production_item, d.fg_warehouse)

View File

@@ -0,0 +1,17 @@
# 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 webnotes
def execute():
serial_nos = webnotes.conn.sql("""select name from `tabSerial No` where docstatus=0
and status in ('Available', 'Sales Returned') and ifnull(warehouse, '') = ''""")
for sr in serial_nos:
try:
sr_bean = webnotes.bean("Serial No", sr[0])
sr_bean.make_controller().via_stock_ledger = True
sr_bean.save()
webnotes.conn.commit()
except:
pass

View File

@@ -0,0 +1,29 @@
# Copyright (c) 2014, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import webnotes
def execute():
webnotes.reload_doc("stock", "doctype", "price_list")
webnotes.reload_doc("stock", "doctype", "item_price")
if "buying_or_selling" in webnotes.conn.get_table_columns("Price List"):
webnotes.conn.sql("""update `tabPrice List` set
selling =
case
when buying_or_selling='Selling'
then 1
end,
buying =
case
when buying_or_selling='Buying'
then 1
end
""")
webnotes.conn.sql("""update `tabItem Price` ip, `tabPrice List` pl
set ip.buying=pl.buying, ip.selling=pl.selling
where ip.price_list=pl.name""")
webnotes.conn.sql("""update `tabItem Price` set selling=1 where ifnull(selling, 0)=0 and
ifnull(buying, 0)=0""")

View File

@@ -0,0 +1,25 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import webnotes
def execute():
webnotes.reload_doc("core", "doctype", "custom_field")
cf_doclist = webnotes.get_doctype("Custom Field")
delete_list = []
for d in webnotes.conn.sql("""select cf.name as cf_name, ps.property,
ps.value, ps.name as ps_name
from `tabProperty Setter` ps, `tabCustom Field` cf
where ps.doctype_or_field = 'DocField' and ps.property != 'previous_field'
and ps.doc_type=cf.dt and ps.field_name=cf.fieldname""", as_dict=1):
if cf_doclist.get_field(d.property):
webnotes.conn.sql("""update `tabCustom Field`
set `%s`=%s where name=%s""" % (d.property, '%s', '%s'), (d.value, d.cf_name))
delete_list.append(d.ps_name)
if delete_list:
webnotes.conn.sql("""delete from `tabProperty Setter` where name in (%s)""" %
', '.join(['%s']*len(delete_list)), tuple(delete_list))

View File

@@ -0,0 +1,29 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import webnotes
from webnotes.utils import flt
def execute():
for order_type in ["Sales", "Purchase"]:
for d in webnotes.conn.sql("""select par.name, sum(ifnull(child.qty, 0)) as total_qty
from `tab%s Order` par, `tab%s Order Item` child
where par.name = child.parent and par.docstatus = 1
and ifnull(par.net_total, 0) = 0 group by par.name""" %
(order_type, order_type), as_dict=1):
billed_qty = flt(webnotes.conn.sql("""select sum(ifnull(qty, 0))
from `tab%s Invoice Item` where %s=%s and docstatus=1""" %
(order_type, "sales_order" if order_type=="Sales" else "purchase_order", '%s'),
(d.name))[0][0])
per_billed = ((d.total_qty if billed_qty > d.total_qty else billed_qty)\
/ d.total_qty)*100
webnotes.conn.set_value(order_type+ " Order", d.name, "per_billed", per_billed)
if order_type == "Sales":
if per_billed < 0.001: billing_status = "Not Billed"
elif per_billed >= 99.99: billing_status = "Fully Billed"
else: billing_status = "Partly Billed"
webnotes.conn.set_value("Sales Order", d.name, "billing_status", billing_status)

View File

@@ -5,7 +5,8 @@ from __future__ import unicode_literals
def execute():
import webnotes
webnotes.reload_doc('stock', 'doctype', 'packed_item')
for si in webnotes.conn.sql("""select name from `tabSales Invoice` where docstatus = 1"""):
webnotes.get_obj("Sales Invoice", si[0],
with_children=1).update_qty(change_modified=False)
webnotes.conn.commit()
webnotes.conn.commit()

View File

@@ -8,20 +8,7 @@ from webnotes.utils import cint
def execute():
webnotes.reload_doc("stock", "doctype", "price_list")
webnotes.reload_doc("stock", "doctype", "item_price")
try:
for price_list in webnotes.conn.sql_list("""select name from `tabPrice List`"""):
buying, selling = False, False
for b, s in webnotes.conn.sql("""select distinct buying, selling
from `tabItem Price` where price_list_name=%s""", price_list):
buying = buying or cint(b)
selling = selling or cint(s)
buying_or_selling = "Selling" if selling else "Buying"
webnotes.conn.set_value("Price List", price_list, "buying_or_selling", buying_or_selling)
except webnotes.SQLError, e:
if e.args[0] == 1054:
webnotes.conn.sql("""update `tabPrice List` set buying_or_selling='Selling'
where ifnull(buying_or_selling, '')='' """)
else:
raise
webnotes.conn.sql("""update `tabPrice List` pl, `tabItem Price` ip
set pl.selling=ip.selling, pl.buying=ip.buying
where pl.name=ip.price_list_name""")

View File

@@ -12,9 +12,7 @@ def execute():
where ip.item_code=i.name""")
webnotes.conn.sql("""update `tabItem Price` ip, `tabPrice List` pl
set ip.price_list=pl.name, ip.currency=pl.currency,
ip.buying_or_selling=pl.buying_or_selling
where ip.parent=pl.name""")
set ip.price_list=pl.name, ip.currency=pl.currency where ip.parent=pl.name""")
webnotes.conn.sql("""update `tabItem Price`
set parent=null, parenttype=null, parentfield=null, idx=null""")

View File

@@ -262,4 +262,11 @@ patch_list = [
"patches.1311.p07_scheduler_errors_digest",
"patches.1311.p08_email_digest_recipients",
"execute:webnotes.delete_doc('DocType', 'Warehouse Type')",
"patches.1312.p02_update_item_details_in_item_price",
"patches.1401.p01_move_related_property_setters_to_custom_field",
"patches.1401.p01_make_buying_selling_as_check_box_in_price_list",
"patches.1401.update_billing_status_for_zero_value_order",
"patches.1401.enable_all_price_list",
"patches.1401.fix_serial_no_status_and_warehouse",
"patches.1401.fix_planned_qty",
]

View File

@@ -10,9 +10,9 @@
<li class="active"><i class="icon-file icon-fixed-width"></i> {{ doc.name }}</li>
</ul>
<h3><i class="icon-file icon-fixed-width"></i> {{ doc.name }}</h3>
{% if doc.name == "Not Allowed" -%}
{% if session_user == "Guest" -%}
<script>ask_to_login();</script>
{% else %}
{% elif doc.name != "Not Allowed"%}
<hr>
<div>
<div class="row">

View File

@@ -41,21 +41,23 @@ def get_currency_context():
}
def get_transaction_context(doctype, name):
context = {"session_user": webnotes.session.user}
customer = webnotes.conn.get_value("Contact", {"email_id": webnotes.session.user},
"customer")
bean = webnotes.bean(doctype, name)
if bean.doc.customer != customer:
return {
"doc": {"name": "Not Allowed"}
}
context.update({"doc": {"name": "Not Allowed"}})
else:
return {
context.update({
"doc": bean.doc,
"doclist": bean.doclist,
"webnotes": webnotes,
"utils": webnotes.utils
}
})
return context
@webnotes.whitelist(allow_guest=True)
def send_message(subject="Website Query", message="", sender="", status="Open"):

View File

@@ -28,7 +28,7 @@ class DocType:
})
def validate_time_log_is_submitted(self, tl):
if tl.status != "Submitted":
if tl.status != "Submitted" and self.doc.docstatus == 0:
webnotes.msgprint(_("Time Log must have status 'Submitted'") + \
" :" + tl.name + " (" + _(tl.status) + ")", raise_exception=True)
@@ -57,7 +57,4 @@ class DocType:
tl = webnotes.bean("Time Log", d.time_log)
tl.doc.time_log_batch = time_log_batch
tl.doc.sales_invoice = self.doc.sales_invoice
tl.update_after_submit()
tl.update_after_submit()

View File

@@ -26,9 +26,10 @@ erpnext.AccountTreeGrid = wn.views.TreeGridReport.extend({
show: true,
parent_field: "parent_account",
formatter: function(item) {
return repl('<a href="#general-ledger/account=%(enc_value)s">%(value)s</a>', {
return repl("<a \
onclick='wn.cur_grid_report.show_general_ledger(\"%(value)s\")'>\
%(value)s</a>", {
value: item.name,
enc_value: encodeURIComponent(item.name)
});
}
},
@@ -211,4 +212,14 @@ erpnext.AccountTreeGrid = wn.views.TreeGridReport.extend({
return;
}
},
show_general_ledger: function(account) {
wn.route_options = {
account: account,
company: this.company,
from_date: this.from_date,
to_date: this.to_date
};
wn.set_route("query-report", "General Ledger");
}
});

View File

@@ -24,16 +24,17 @@ $(document).bind('toolbar_setup', function() {
wn.provide('wn.ui.misc');
wn.ui.misc.about = function() {
if(!wn.ui.misc.about_dialog) {
var d = new wn.ui.Dialog({title: wn._('About ERPNext')})
var d = new wn.ui.Dialog({title: wn._('About')})
$(d.body).html(repl("<div>\
<p>"+wn._("ERPNext is an open-source web based ERP made by Web Notes Technologies Pvt Ltd.\
to provide an integrated tool to manage most processes in a small organization.\
For more information about Web Notes, or to buy hosting servies, go to ")+
"<a href='https://erpnext.com'>https://erpnext.com</a>.</p>\
<p>"+wn._("To report an issue, go to ")+"<a href='https://github.com/webnotes/erpnext/issues'>GitHub Issues</a></p>\
<hr>\
<h2>ERPNext</h2> \
<p><strong>v" + wn.boot.app_version + "</strong></p>\
<p>"+wn._("An open source ERP made for the web.</p>") +
"<p>"+wn._("To report an issue, go to ")+"<a href='https://github.com/webnotes/erpnext/issues'>GitHub Issues</a></p> \
<p><a href='http://erpnext.org' target='_blank'>http://erpnext.org</a>.</p>\
<p><a href='http://www.gnu.org/copyleft/gpl.html'>License: GNU General Public License Version 3</a></p>\
<hr>\
<p>&copy; 2014 Web Notes Technologies Pvt. Ltd and contributers </p> \
</div>", wn.app));
wn.ui.misc.about_dialog = d;

View File

@@ -11,9 +11,10 @@ erpnext.stock.StockController = wn.ui.form.Controller.extend({
wn.route_options = {
voucher_no: me.frm.doc.name,
from_date: me.frm.doc.posting_date,
to_date: me.frm.doc.posting_date
to_date: me.frm.doc.posting_date,
company: me.frm.doc.company
};
wn.set_route('stock-ledger');
wn.set_route("query-report", "Stock Ledger");
}, "icon-bar-chart");
}
@@ -24,11 +25,13 @@ erpnext.stock.StockController = wn.ui.form.Controller.extend({
if(this.frm.doc.docstatus===1 && cint(wn.defaults.get_default("auto_accounting_for_stock"))) {
cur_frm.appframe.add_button(wn._('Accounting Ledger'), function() {
wn.route_options = {
"voucher_no": me.frm.doc.name,
"from_date": me.frm.doc.posting_date,
"to_date": me.frm.doc.posting_date,
voucher_no: me.frm.doc.name,
from_date: me.frm.doc.posting_date,
to_date: me.frm.doc.posting_date,
company: me.frm.doc.company,
group_by_voucher: false
};
wn.set_route("general-ledger");
wn.set_route("query-report", "General Ledger");
}, "icon-table");
}
},

View File

@@ -17,10 +17,10 @@ erpnext.StockAnalytics = erpnext.StockGridReport.extend({
parent_field: "parent_item_group",
formatter: function(item) {
if(!item.is_group) {
return repl('<a href="#stock-ledger/item_code=%(enc_value)s">%(value)s</a>',
{
return repl("<a \
onclick='wn.cur_grid_report.show_stock_ledger(\"%(value)s\")'>\
%(value)s</a>", {
value: item.name,
enc_value: encodeURIComponent(item.name)
});
} else {
return item.name;
@@ -183,5 +183,13 @@ erpnext.StockAnalytics = erpnext.StockGridReport.extend({
},
get_plot_points: function(item, col, idx) {
return [[dateutil.user_to_obj(col.name).getTime(), item[col.field]]]
},
show_stock_ledger: function(item_code) {
wn.route_options = {
item_code: item_code,
from_date: this.from_date,
to_date: this.to_date
};
wn.set_route("query-report", "Stock Ledger");
}
});

View File

@@ -21,6 +21,6 @@ erpnext.toolbar.setup = function() {
<i class="icon-fixed-width icon-comments"></i> '+wn._('Live Chat')+'</a></li>');
}
$("#toolbar-tools").append('<li><a href="#latest-updates">\
$("#toolbar-tools").append('<li><a href="https://github.com/webnotes/erpnext/releases" target="_blank">\
<i class="icon-fixed-width icon-rss"></i> Latest Updates</li>');
}
}

View File

@@ -330,8 +330,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
doctype: tax.doctype,
row_id_label: wn.meta.get_label(tax.doctype, "row_id", tax.name)
});
msgprint(msg);
throw msg;
wn.throw(msg);
}
},
@@ -347,8 +346,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
charge_type_label: wn.meta.get_label(tax.doctype, "charge_type", tax.name),
charge_type: tax.charge_type
});
msgprint(msg);
throw msg;
wn.throw(msg);
};
var on_previous_row_error = function(row_range) {
@@ -363,8 +361,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
row_range: row_range,
});
msgprint(msg);
throw msg;
wn.throw(msg);
};
if(cint(tax.included_in_print_rate)) {
@@ -543,6 +540,14 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
calculate_taxes: function() {
var me = this;
var actual_tax_dict = {};
// maintain actual tax rate based on idx
$.each(this.frm.tax_doclist, function(i, tax) {
if (tax.charge_type == "Actual") {
actual_tax_dict[tax.idx] = flt(tax.rate);
}
});
$.each(this.frm.item_doclist, function(n, item) {
var item_tax_map = me._load_item_tax_rate(item.item_tax_rate);
@@ -552,15 +557,15 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
var current_tax_amount = me.get_current_tax_amount(item, tax, item_tax_map);
me.set_item_tax_amount && me.set_item_tax_amount(item, tax, current_tax_amount);
// case when net total is 0 but there is an actual type charge
// in this case add the actual amount to tax.tax_amount
// and tax.grand_total_for_current_item for the first such iteration
if(tax.charge_type == "Actual" &&
!(current_tax_amount || me.frm.doc.net_total || tax.tax_amount)) {
var zero_net_total_adjustment = flt(tax.rate, precision("tax_amount", tax));
current_tax_amount += zero_net_total_adjustment;
// Adjust divisional loss to the last item
if (tax.charge_type == "Actual") {
actual_tax_dict[tax.idx] -= current_tax_amount;
if (n == me.frm.item_doclist.length - 1) {
current_tax_amount += actual_tax_dict[tax.idx]
}
}
// store tax_amount for current item as it will be used for
// charge type = 'On Previous Row Amount'
@@ -592,6 +597,11 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
// in tax.total, accumulate grand total for each item
tax.total += tax.grand_total_for_current_item;
if (n == me.frm.item_doclist.length - 1) {
tax.total = flt(tax.total, precision("total", tax));
tax.tax_amount = flt(tax.tax_amount, precision("tax_amount", tax));
}
});
});
},

View File

@@ -1,13 +1,2 @@
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
//--------- ONLOAD -------------
cur_frm.cscript.onload = function(doc, cdt, cdn) {
}
cur_frm.cscript.refresh = function(doc, cdt, cdn) {
}
// License: GNU General Public License v3. See license.txt

View File

@@ -2,11 +2,12 @@
{
"creation": "2013-01-10 16:34:18",
"docstatus": 0,
"modified": "2013-07-05 14:29:57",
"modified": "2014-01-16 12:52:19",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"allow_rename": 1,
"autoname": "field:campaign_name",
"description": "Keep Track of Sales Campaigns. Keep track of Leads, Quotations, Sales Order etc from Campaigns to gauge Return on Investment. ",
"doctype": "DocType",

View File

@@ -18,7 +18,7 @@ cur_frm.cscript.load_defaults = function(doc, dt, dn) {
cur_frm.add_fetch('lead_name', 'company_name', 'customer_name');
cur_frm.add_fetch('default_sales_partner','commission_rate','default_commission_rate');
cur_frm.cscript.refresh = function(doc,dt,dn) {
cur_frm.cscript.refresh = function(doc, dt, dn) {
cur_frm.cscript.setup_dashboard(doc);
erpnext.hide_naming_series();
@@ -107,21 +107,21 @@ cur_frm.cscript.make_contact = function() {
}
cur_frm.fields_dict['customer_group'].get_query = function(doc,dt,dn) {
cur_frm.fields_dict['customer_group'].get_query = function(doc, dt, dn) {
return{
filters:{'is_group': 'No'}
}
}
cur_frm.fields_dict.lead_name.get_query = function(doc,cdt,cdn) {
cur_frm.fields_dict.lead_name.get_query = function(doc, cdt, cdn) {
return{
query:"controllers.queries.lead_query"
}
}
cur_frm.fields_dict['default_price_list'].get_query = function(doc,cdt,cdn) {
cur_frm.fields_dict['default_price_list'].get_query = function(doc, cdt, cdn) {
return{
filters:{'buying_or_selling': "Selling"}
filters:{'selling': 1}
}
}

View File

@@ -2,7 +2,7 @@
{
"creation": "2013-06-11 14:26:44",
"docstatus": 0,
"modified": "2013-11-03 14:01:33",
"modified": "2013-12-25 11:15:05",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -16,7 +16,7 @@
"icon": "icon-user",
"module": "Selling",
"name": "__common__",
"search_fields": "customer_name,customer_group,country,territory"
"search_fields": "customer_name,customer_group,territory"
},
{
"doctype": "DocField",

View File

@@ -28,6 +28,7 @@ class TestQuotation(unittest.TestCase):
sales_order[0]["delivery_date"] = "2014-01-01"
sales_order[0]["naming_series"] = "_T-Quotation-"
sales_order[0]["transaction_date"] = "2013-05-12"
webnotes.bean(sales_order).insert()

View File

@@ -10,11 +10,12 @@ no_cache = True
def get_context():
from portal.utils import get_transaction_context
context = get_transaction_context("Sales Order", webnotes.form_dict.name)
modify_status(context.get("doc"))
context.update({
"parent_link": "orders",
"parent_title": "My Orders"
})
if context.get("doc").get("name") != "Not Allowed":
modify_status(context.get("doc"))
context.update({
"parent_link": "orders",
"parent_title": "My Orders"
})
return context
def modify_status(doc):

View File

@@ -53,6 +53,7 @@ class TestSalesOrder(unittest.TestCase):
self.assertEquals(len([d for d in si if d["doctype"]=="Sales Invoice Item"]), 1)
si = webnotes.bean(si)
si.doc.posting_date = "2013-10-10"
si.insert()
si.submit()

View File

@@ -48,7 +48,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
if(this.frm.fields_dict.selling_price_list) {
this.frm.set_query("selling_price_list", function() {
return { filters: { buying_or_selling: "Selling" } };
return { filters: { selling: 1 } };
});
}

View File

@@ -3,8 +3,8 @@
from __future__ import unicode_literals
import webnotes
from webnotes import msgprint, _
from webnotes.utils import flt, cint, comma_and
from webnotes import _, throw
from webnotes.utils import flt, cint
import json
def get_customer_list(doctype, txt, searchfield, start, page_len, filters):
@@ -100,7 +100,7 @@ def _get_item_code(barcode=None, serial_no=None):
where name=%s""", serial_no)
if not item_code:
msgprint(_("No Item found with ") + input_type + ": %s" % (barcode or serial_no), raise_exception=True)
throw(_("No Item found with ") + input_type + ": %s" % (barcode or serial_no))
return item_code[0]
@@ -111,22 +111,26 @@ def _validate_item_details(args, item):
# validate if sales item or service item
if args.order_type == "Maintenance":
if item.is_service_item != "Yes":
msgprint(_("Item") + (" %s: " % item.name) +
throw(_("Item") + (" %s: " % item.name) +
_("not a service item.") +
_("Please select a service item or change the order type to Sales."),
raise_exception=True)
_("Please select a service item or change the order type to Sales."))
elif item.is_sales_item != "Yes":
msgprint(_("Item") + (" %s: " % item.name) + _("not a sales item"),
raise_exception=True)
throw(_("Item") + (" %s: " % item.name) + _("not a sales item"))
def _get_basic_details(args, item_bean, warehouse_fieldname):
item = item_bean.doc
from webnotes.defaults import get_user_default_as_list
user_default_warehouse_list = get_user_default_as_list('warehouse')
user_default_warehouse = user_default_warehouse_list[0] \
if len(user_default_warehouse_list)==1 else ""
out = webnotes._dict({
"item_code": item.name,
"description": item.description_html or item.description,
warehouse_fieldname: item.default_warehouse or args.get(warehouse_fieldname),
warehouse_fieldname: user_default_warehouse or item.default_warehouse \
or args.get(warehouse_fieldname),
"income_account": item.default_income_account or args.income_account \
or webnotes.conn.get_value("Company", args.company, "default_income_account"),
"expense_account": item.purchase_account or args.expense_account \
@@ -146,8 +150,10 @@ def _get_basic_details(args, item_bean, warehouse_fieldname):
return out
def _get_price_list_rate(args, item_bean, meta):
ref_rate = webnotes.conn.sql("""select ref_rate from `tabItem Price`
where price_list=%s and item_code=%s and buying_or_selling='Selling'""",
ref_rate = webnotes.conn.sql("""select ip.ref_rate from
`tabItem Price` ip, `tabPrice List` pl
where ip.price_list=pl.name and ip.price_list=%s and
ip.item_code=%s and ip.selling=1 and pl.enabled=1""",
(args.selling_price_list, args.item_code), as_dict=1)
if not ref_rate:

View File

@@ -282,7 +282,7 @@ def apply_cart_settings(party=None, quotation=None):
party = get_lead_or_customer()
if not quotation:
quotation = _get_cart_quotation(party)
cart_settings = webnotes.get_obj("Shopping Cart Settings")
billing_territory = get_address_territory(quotation.doc.customer_address) or \
@@ -310,7 +310,8 @@ def set_price_list_and_rate(quotation, cart_settings, billing_territory):
quotation.run_method("set_price_list_and_item_details")
# set it in cookies for using in product page
webnotes.local._response.set_cookie("selling_price_list", quotation.doc.selling_price_list)
if quotation.doc.selling_price_list:
webnotes.local._response.set_cookie("selling_price_list", quotation.doc.selling_price_list)
def set_taxes(quotation, cart_settings, billing_territory):
"""set taxes based on billing territory"""

View File

@@ -27,8 +27,9 @@ def get_product_info(item_code):
else:
in_stock = -1
price = price_list and webnotes.conn.sql("""select ref_rate, currency from
`tabItem Price` where item_code=%s and price_list=%s""",
price = price_list and webnotes.conn.sql("""select ip.ref_rate, ip.currency from
`tabItem Price` ip, `tabPrice List` pl where ip.price_list=pl.name and
ip.item_code=%s and ip.price_list=%s and pl.enabled=1""",
(item_code, price_list), as_dict=1) or []
price = price and price[0] or None

View File

@@ -5,7 +5,7 @@ from __future__ import unicode_literals
import webnotes
from webnotes import _, msgprint
from webnotes.utils import cstr
from webnotes.utils import cstr, cint
import webnotes.defaults
@@ -237,21 +237,24 @@ class DocType:
account.insert()
def set_default_accounts(self):
accounts = {
"default_income_account": "Sales",
"default_expense_account": "Cost of Goods Sold",
def _set_default_accounts(accounts):
for a in accounts:
account_name = accounts[a] + " - " + self.doc.abbr
if not self.doc.fields.get(a) and webnotes.conn.exists("Account", account_name):
webnotes.conn.set(self.doc, a, account_name)
_set_default_accounts({
"receivables_group": "Accounts Receivable",
"payables_group": "Accounts Payable",
"default_cash_account": "Cash",
"stock_received_but_not_billed": "Stock Received But Not Billed",
"stock_adjustment_account": "Stock Adjustment",
"expenses_included_in_valuation": "Expenses Included In Valuation"
}
"default_cash_account": "Cash"
})
for a in accounts:
account_name = accounts[a] + " - " + self.doc.abbr
if not self.doc.fields.get(a) and webnotes.conn.exists("Account", account_name):
webnotes.conn.set(self.doc, a, account_name)
if cint(webnotes.conn.get_value("Accounts Settings", None, "auto_accounting_for_stock")):
_set_default_accounts({
"stock_received_but_not_billed": "Stock Received But Not Billed",
"stock_adjustment_account": "Stock Adjustment",
"expenses_included_in_valuation": "Expenses Included In Valuation"
})
def create_default_cost_center(self):
cc_list = [

View File

@@ -9,6 +9,7 @@ from webnotes.utils import fmt_money, formatdate, now_datetime, cstr, esc, \
from webnotes.utils.dateutils import datetime_in_user_format
from datetime import timedelta
from dateutil.relativedelta import relativedelta
from webnotes.utils.email_lib import sendmail
content_sequence = [
["Income / Expenses", ["income_year_to_date", "bank_balance",
@@ -80,15 +81,15 @@ class DocType(DocListController):
for user_id in recipients:
msg_for_this_receipient = self.get_msg_html(self.get_user_specific_content(user_id) + \
common_msg)
from webnotes.utils.email_lib import sendmail
sendmail(recipients=user_id,
subject="[ERPNext] [{frequency} Digest] {name}".format(
frequency=self.doc.frequency, name=self.doc.name),
msg=msg_for_this_receipient)
if msg_for_this_receipient:
sendmail(recipients=user_id,
subject="[ERPNext] [{frequency} Digest] {name}".format(
frequency=self.doc.frequency, name=self.doc.name),
msg=msg_for_this_receipient)
def get_digest_msg(self):
return self.get_msg_html(self.get_user_specific_content(webnotes.session.user) + \
self.get_common_content())
self.get_common_content(), send_only_if_updates=False)
def get_common_content(self):
out = []
@@ -119,14 +120,19 @@ class DocType(DocListController):
return out
def get_msg_html(self, out):
def get_msg_html(self, out, send_only_if_updates=True):
with_value = [o[1] for o in out if o[0]]
if with_value:
has_updates = True
with_value = "\n".join(with_value)
else:
has_updates = False
with_value = "<p>There were no updates in the items selected for this digest.</p><hr>"
if not has_updates and send_only_if_updates:
return
# seperate out no value items
no_value = [o[1] for o in out if not o[0]]
if no_value:

View File

@@ -2,7 +2,7 @@
{
"creation": "2012-12-20 12:50:49",
"docstatus": 0,
"modified": "2013-11-03 14:20:18",
"modified": "2013-12-24 11:40:19",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -90,7 +90,7 @@
"doctype": "DocField",
"fieldname": "fs_packing_details",
"fieldtype": "Check",
"label": "Packing Detials"
"label": "Packing Details"
},
{
"description": "To get Item Group in details table",

View File

@@ -98,7 +98,9 @@ def create_price_lists(args):
{
"doctype": "Price List",
"price_list_name": "Standard " + pl_type,
"buying_or_selling": pl_type,
"enabled": 1,
"buying": 1 if pl_type == "Buying" else 0,
"selling": 1 if pl_type == "Selling" else 0,
"currency": args["currency"]
},
{

View File

@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import webnotes
from webnotes import _, msgprint
from webnotes import _, msgprint, throw
import json
def get_company_currency(company):
@@ -11,8 +11,8 @@ def get_company_currency(company):
if not currency:
currency = webnotes.conn.get_default("currency")
if not currency:
msgprint(_('Please specify Default Currency in Company Master \
and Global Defaults'), raise_exception=True)
throw(_('Please specify Default Currency in Company Master \
and Global Defaults'))
return currency
@@ -32,5 +32,14 @@ def get_ancestors_of(doctype, name):
@webnotes.whitelist()
def get_price_list_currency(price_list):
return {"price_list_currency": webnotes.conn.get_value("Price List", price_list,
"currency")}
price_list_currency = webnotes.conn.get_value("Price List", {"name": price_list,
"enabled": 1}, "currency")
if not price_list_currency:
throw("{message}: {price_list} {disabled}".format(**{
"message": _("Price List"),
"price_list": price_list,
"disabled": _("is disabled.")
}))
else:
return {"price_list_currency": price_list_currency}

View File

@@ -70,6 +70,6 @@ def on_build():
def comment_added(doc):
"""add comment to feed"""
home.make_feed('Comment', doc.comment_doctype, doc.comment_docname, doc.comment_by,
'<i>"' + doc.comment + '"</i>', '#6B24B3')
home.make_feed('Comment', doc.comment_doctype, doc.comment_docname,
doc.comment_by or doc.owner, '<i>"' + doc.comment + '"</i>', '#6B24B3')

View File

@@ -53,6 +53,10 @@ def execute_daily():
# email digest
from setup.doctype.email_digest.email_digest import send
run_fn(send)
# auto close support tickets
from support.doctype.support_ticket.support_ticket import auto_close_tickets
run_fn(auto_close_tickets)
def execute_weekly():
from setup.doctype.backup_manager.backup_manager import take_backups_weekly

View File

@@ -58,11 +58,6 @@ class TestDeliveryNote(unittest.TestCase):
self.assertEqual(stock_value, 0)
self.assertEqual(stock_value_difference, -375)
gl_entries = webnotes.conn.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type='Delivery Note' and voucher_no=%s
order by account desc""", dn.doc.name, as_dict=1)
self.assertFalse(get_gl_entries("Delivery Note", dn.doc.name))
def test_delivery_note_gl_entry(self):
@@ -111,8 +106,8 @@ class TestDeliveryNote(unittest.TestCase):
gl_entries = get_gl_entries("Delivery Note", dn.doc.name)
self.assertTrue(gl_entries)
expected_values = {
stock_in_hand_account: [0.0, 666.65],
"Cost of Goods Sold - _TC": [666.65, 0.0]
stock_in_hand_account: [0.0, 666.67],
"Cost of Goods Sold - _TC": [666.67, 0.0]
}
for i, gle in enumerate(gl_entries):
self.assertEquals([gle.debit, gle.credit], expected_values.get(gle.account))

View File

@@ -29,10 +29,7 @@ cur_frm.cscript.make_dashboard = function() {
cur_frm.cscript.edit_prices_button = function() {
cur_frm.add_custom_button("Add / Edit Prices", function() {
wn.route_options = {
"item_code": cur_frm.doc.name
};
wn.set_route("Report", "Item Price");
wn.set_route("Report", "Item Price", {"item_code": cur_frm.doc.name});
}, "icon-money");
}

View File

@@ -49,6 +49,7 @@ class DocType(DocListController, WebsiteGenerator):
def on_update(self):
self.validate_name_with_item_group()
self.update_website()
self.update_item_price()
def check_warehouse_is_set_for_stock_item(self):
if self.doc.is_stock_item=="Yes" and not self.doc.default_warehouse:
@@ -210,6 +211,11 @@ class DocType(DocListController, WebsiteGenerator):
WebsiteGenerator.on_update(self)
def update_item_price(self):
webnotes.conn.sql("""update `tabItem Price` set item_name=%s,
item_description=%s, modified=NOW() where item_code=%s""",
(self.doc.item_name, self.doc.description, self.doc.name))
def get_page_title(self):
if self.doc.name==self.doc.item_name:
page_name_from = self.doc.name
@@ -246,6 +252,9 @@ class DocType(DocListController, WebsiteGenerator):
def before_rename(self, olddn, newdn, merge=False):
if merge:
# Validate properties before merging
if not webnotes.conn.exists("Item", newdn):
webnotes.throw(_("Item ") + newdn +_(" does not exists"))
field_list = ["stock_uom", "is_stock_item", "has_serial_no", "has_batch_no"]
new_properties = [cstr(d) for d in webnotes.conn.get_value("Item", newdn, field_list)]
if new_properties != [cstr(self.doc.fields[fld]) for fld in field_list]:

View File

@@ -36,6 +36,7 @@ test_records = [
"stock_uom": "_Test UOM",
"default_income_account": "Sales - _TC",
"default_warehouse": "_Test Warehouse - _TC",
"purchase_account": "_Test Account Cost for Goods Sold - _TC"
}, {
"doctype": "Item Reorder",
"parentfield": "item_reorder",
@@ -64,6 +65,7 @@ test_records = [
"stock_uom": "_Test UOM",
"default_income_account": "Sales - _TC",
"default_warehouse": "_Test Warehouse - _TC",
"purchase_account": "_Test Account Cost for Goods Sold - _TC"
}],
[{
"doctype": "Item",
@@ -73,6 +75,7 @@ test_records = [
"item_group": "_Test Item Group Desktops",
"default_warehouse": "_Test Warehouse - _TC",
"default_income_account": "Sales - _TC",
"purchase_account": "_Test Account Cost for Goods Sold - _TC",
"is_stock_item": "Yes",
"is_asset_item": "No",
"has_batch_no": "No",
@@ -99,6 +102,7 @@ test_records = [
"item_group": "_Test Item Group Desktops",
"default_warehouse": "_Test Warehouse - _TC",
"default_income_account": "Sales - _TC",
"purchase_account": "_Test Account Cost for Goods Sold - _TC",
"is_stock_item": "Yes",
"is_asset_item": "No",
"has_batch_no": "No",
@@ -119,6 +123,7 @@ test_records = [
"description": "_Test Sales BOM Item",
"item_group": "_Test Item Group Desktops",
"default_income_account": "Sales - _TC",
"purchase_account": "_Test Account Cost for Goods Sold - _TC",
"is_stock_item": "No",
"is_asset_item": "No",
"has_batch_no": "No",
@@ -140,6 +145,7 @@ test_records = [
"is_stock_item": "Yes",
"default_warehouse": "_Test Warehouse - _TC",
"default_income_account": "Sales - _TC",
"purchase_account": "_Test Account Cost for Goods Sold - _TC",
"is_asset_item": "No",
"has_batch_no": "No",
"has_serial_no": "No",
@@ -216,6 +222,7 @@ test_records = [
"item_group": "_Test Item Group Desktops",
"default_warehouse": "_Test Warehouse - _TC",
"default_income_account": "Sales - _TC",
"purchase_account": "_Test Account Cost for Goods Sold - _TC",
"is_stock_item": "Yes",
"is_asset_item": "No",
"has_batch_no": "No",
@@ -238,6 +245,7 @@ test_records = [
"is_stock_item": "Yes",
"default_warehouse": "_Test Warehouse - _TC",
"default_income_account": "Sales - _TC",
"purchase_account": "_Test Account Cost for Goods Sold - _TC",
"is_asset_item": "No",
"has_batch_no": "No",
"has_serial_no": "No",

View File

@@ -2,11 +2,10 @@
// License: GNU General Public License v3. See license.txt
$.extend(cur_frm.cscript, {
onload: function () {
// Fetch price list details
cur_frm.add_fetch("price_list", "buying_or_selling", "buying_or_selling");
cur_frm.add_fetch("price_list", "buying", "buying");
cur_frm.add_fetch("price_list", "selling", "selling");
cur_frm.add_fetch("price_list", "currency", "currency");
// Fetch item details

View File

@@ -1,11 +1,9 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt
# For license information, please see license.txt
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import webnotes
from webnotes import _
from webnotes import throw, _
class ItemPriceDuplicateItem(webnotes.ValidationError): pass
@@ -14,26 +12,36 @@ class DocType:
self.doc, self.doclist = d, dl
def validate(self):
self.validate_price_list()
self.check_duplicate_item()
self.update_price_list_details()
self.update_item_details()
def update_price_list_details(self):
self.doc.buying_or_selling, self.doc.currency = webnotes.conn.get_value("Price List",
self.doc.price_list, ["buying_or_selling", "currency"])
def update_item_details(self):
self.doc.item_name, self.doc.item_description = webnotes.conn.get_value("Item",
self.doc.item_code, ["item_name", "description"])
def validate_price_list(self):
enabled = webnotes.conn.get_value("Price List", self.doc.price_list, "enabled")
if not enabled:
throw("{message}: {price_list} {disabled}".format(**{
"message": _("Price List"),
"price_list": self.doc.price_list,
"disabled": _("is disabled.")
}))
def check_duplicate_item(self):
if webnotes.conn.sql("""select name from `tabItem Price`
where item_code=%s and price_list=%s and name!=%s""",
(self.doc.item_code, self.doc.price_list, self.doc.name)):
webnotes.throw("{duplicate_item}: {item_code}, {already}: {price_list}".format(**{
throw("{duplicate_item}: {item_code}, {already}: {price_list}".format(**{
"duplicate_item": _("Duplicate Item"),
"item_code": self.doc.item_code,
"already": _("already available in Price List"),
"price_list": self.doc.price_list
}), ItemPriceDuplicateItem)
def update_price_list_details(self):
self.doc.buying, self.doc.selling, self.doc.currency = webnotes.conn.get_value("Price List",
{"name": self.doc.price_list, "enabled": 1}, ["buying", "selling", "currency"])
def update_item_details(self):
self.doc.item_name, self.doc.item_description = webnotes.conn.get_value("Item",
self.doc.item_code, ["item_name", "description"])

View File

@@ -2,7 +2,7 @@
{
"creation": "2013-05-02 16:29:48",
"docstatus": 0,
"modified": "2013-10-31 12:59:02",
"modified": "2014-01-07 19:16:49",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -43,6 +43,13 @@
"doctype": "DocType",
"name": "Item Price"
},
{
"doctype": "DocField",
"fieldname": "price_list_details",
"fieldtype": "Section Break",
"label": "Price List",
"options": "icon-tags"
},
{
"doctype": "DocField",
"fieldname": "price_list",
@@ -52,6 +59,29 @@
"options": "Price List",
"reqd": 1
},
{
"doctype": "DocField",
"fieldname": "buying",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Buying",
"read_only": 1
},
{
"doctype": "DocField",
"fieldname": "selling",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Selling",
"read_only": 1
},
{
"doctype": "DocField",
"fieldname": "item_details",
"fieldtype": "Section Break",
"label": "Item",
"options": "icon-tag"
},
{
"doctype": "DocField",
"fieldname": "item_code",
@@ -83,16 +113,6 @@
"fieldname": "col_br_1",
"fieldtype": "Column Break"
},
{
"doctype": "DocField",
"fieldname": "buying_or_selling",
"fieldtype": "Select",
"in_filter": 1,
"in_list_view": 1,
"label": "Valid for Buying or Selling?",
"options": "Selling\nBuying",
"reqd": 0
},
{
"doctype": "DocField",
"fieldname": "item_name",

View File

@@ -125,6 +125,7 @@ class TestMaterialRequest(unittest.TestCase):
from stock.doctype.material_request.material_request import make_purchase_order
po_doclist = make_purchase_order(mr.doc.name)
po_doclist[0].supplier = "_Test Supplier"
po_doclist[0].transaction_date = "2013-07-07"
po_doclist[1].qty = 27.0
po_doclist[2].qty = 1.5
po_doclist[1].schedule_date = "2013-07-09"

View File

@@ -1,7 +0,0 @@
.table-grid tbody tr {
cursor: pointer;
}
.table-grid thead tr {
height: 50px;
}

View File

@@ -3,16 +3,15 @@
from __future__ import unicode_literals
import webnotes
from webnotes import msgprint, _
from webnotes.utils import comma_or, cint
from webnotes import msgprint, _, throw
from webnotes.utils import cint
from webnotes.model.controller import DocListController
import webnotes.defaults
class DocType(DocListController):
def validate(self):
if self.doc.buying_or_selling not in ["Buying", "Selling"]:
msgprint(_(self.meta.get_label("buying_or_selling")) + " " + _("must be one of") + " " +
comma_or(["Buying", "Selling"]), raise_exception=True)
if not cint(self.doc.buying) and not cint(self.doc.selling):
throw(_("Price List must be applicable for Buying or Selling"))
if not self.doclist.get({"parentfield": "valid_for_territories"}):
# if no territory, set default territory
@@ -25,24 +24,24 @@ class DocType(DocListController):
else:
# at least one territory
self.validate_table_has_rows("valid_for_territories")
def on_update(self):
self.set_default_if_missing()
self.update_item_price()
cart_settings = webnotes.get_obj("Shopping Cart Settings")
if cint(cart_settings.doc.enabled):
cart_settings.validate_price_lists()
def set_default_if_missing(self):
if self.doc.buying_or_selling=="Selling":
if cint(self.doc.selling):
if not webnotes.conn.get_value("Selling Settings", None, "selling_price_list"):
webnotes.set_value("Selling Settings", "Selling Settings", "selling_price_list", self.doc.name)
elif self.doc.buying_or_selling=="Buying":
elif cint(self.doc.buying):
if not webnotes.conn.get_value("Buying Settings", None, "buying_price_list"):
webnotes.set_value("Buying Settings", "Buying Settings", "buying_price_list", self.doc.name)
def update_item_price(self):
webnotes.conn.sql("""update `tabItem Price` set currency=%s,
buying_or_selling=%s where price_list=%s""",
(self.doc.currency, self.doc.buying_or_selling, self.doc.name))
buying=%s, selling=%s, modified=NOW() where price_list=%s""",
(self.doc.currency, cint(self.doc.buying), cint(self.doc.selling), self.doc.name))

View File

@@ -2,7 +2,7 @@
{
"creation": "2013-01-25 11:35:09",
"docstatus": 0,
"modified": "2013-10-31 19:24:33",
"modified": "2014-01-27 11:11:08",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -11,6 +11,7 @@
"allow_copy": 0,
"allow_email": 1,
"allow_print": 1,
"allow_rename": 1,
"autoname": "field:price_list_name",
"description": "Price List Master",
"doctype": "DocType",
@@ -42,6 +43,18 @@
"doctype": "DocType",
"name": "Price List"
},
{
"default": "1",
"doctype": "DocField",
"fieldname": "enabled",
"fieldtype": "Check",
"label": "Enabled"
},
{
"doctype": "DocField",
"fieldname": "sb_1",
"fieldtype": "Section Break"
},
{
"doctype": "DocField",
"fieldname": "price_list_name",
@@ -61,14 +74,19 @@
"reqd": 1
},
{
"default": "Selling",
"doctype": "DocField",
"fieldname": "buying_or_selling",
"fieldtype": "Select",
"fieldname": "buying",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Valid for Buying or Selling?",
"options": "Buying\nSelling",
"reqd": 1
"label": "Buying"
},
{
"doctype": "DocField",
"fieldname": "selling",
"fieldtype": "Check",
"in_list_view": 1,
"label": "Selling",
"reqd": 0
},
{
"doctype": "DocField",

View File

@@ -11,8 +11,9 @@ test_records = [
{
"doctype": "Price List",
"price_list_name": "_Test Price List",
"enabled": 1,
"currency": "INR",
"buying_or_selling": "Selling"
"selling": 1
},
{
"doctype": "Applicable Territory",
@@ -24,8 +25,9 @@ test_records = [
{
"doctype": "Price List",
"price_list_name": "_Test Price List 2",
"enabled": 1,
"currency": "INR",
"buying_or_selling": "Selling"
"selling": 1
},
{
"doctype": "Applicable Territory",
@@ -37,8 +39,9 @@ test_records = [
{
"doctype": "Price List",
"price_list_name": "_Test Price List India",
"enabled": 1,
"currency": "INR",
"buying_or_selling": "Selling"
"selling": 1
},
{
"doctype": "Applicable Territory",
@@ -50,8 +53,9 @@ test_records = [
{
"doctype": "Price List",
"price_list_name": "_Test Price List Rest of the World",
"enabled": 1,
"currency": "USD",
"buying_or_selling": "Selling"
"selling": 1
},
{
"doctype": "Applicable Territory",

View File

@@ -2,7 +2,7 @@
{
"creation": "2013-05-24 19:29:10",
"docstatus": 0,
"modified": "2013-12-18 10:38:39",
"modified": "2014-01-15 16:00:44",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -334,6 +334,16 @@
"report_hide": 0,
"reqd": 0
},
{
"default": ":Company",
"depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)",
"doctype": "DocField",
"fieldname": "cost_center",
"fieldtype": "Link",
"label": "Cost Center",
"options": "Cost Center",
"print_hide": 1
},
{
"doctype": "DocField",
"fieldname": "project_name",

View File

@@ -87,6 +87,8 @@ class DocType(StockController):
self.doc.status = "Sales Returned"
else:
self.doc.status = "Available"
if not self.doc.warehouse:
self.doc.warehouse = last_sle.warehouse
else:
if document_type == "Purchase Return":
self.doc.status = "Purchase Returned"
@@ -94,6 +96,8 @@ class DocType(StockController):
self.doc.status = "Delivered"
else:
self.doc.status = "Not Available"
else:
self.doc.status = "Not Available"
def set_purchase_details(self, purchase_sle):
if purchase_sle:
@@ -185,10 +189,9 @@ class DocType(StockController):
def on_stock_ledger_entry(self):
if self.via_stock_ledger and not self.doc.fields.get("__islocal"):
last_sle = self.get_last_sle()
if last_sle:
self.set_status(last_sle.get("last_sle"))
self.set_purchase_details(last_sle.get("purchase_sle"))
self.set_sales_details(last_sle.get("delivery_sle"))
self.set_status(last_sle.get("last_sle"))
self.set_purchase_details(last_sle.get("purchase_sle"))
self.set_sales_details(last_sle.get("delivery_sle"))
def on_communication(self):
return

View File

@@ -287,9 +287,16 @@ class DocType(StockController):
# validate quantity <= ref item's qty - qty already returned
ref_item = ref.doclist.getone({"item_code": item.item_code})
returnable_qty = ref_item.qty - flt(already_returned_item_qty.get(item.item_code))
self.validate_value("transfer_qty", "<=", returnable_qty, item,
raise_exception=StockOverReturnError)
if not returnable_qty:
webnotes.throw("{item}: {item_code} {returned}".format(
item=_("Item"), item_code=item.item_code,
returned=_("already returned though some other documents")),
StockOverReturnError)
elif item.transfer_qty > returnable_qty:
webnotes.throw("{item}: {item_code}, {returned}: {qty}".format(
item=_("Item"), item_code=item.item_code,
returned=_("Max Returnable Qty"), qty=returnable_qty), StockOverReturnError)
def get_already_returned_item_qty(self, ref_fieldname):
return dict(webnotes.conn.sql("""select item_code, sum(transfer_qty) as qty
from `tabStock Entry Detail` where parent in (
@@ -339,7 +346,8 @@ class DocType(StockController):
pro_bean = webnotes.bean("Production Order", self.doc.production_order)
_validate_production_order(pro_bean)
self.update_produced_qty(pro_bean)
self.update_planned_qty(pro_bean)
if self.doc.purpose == "Manufacture/Repack":
self.update_planned_qty(pro_bean)
def update_produced_qty(self, pro_bean):
if self.doc.purpose == "Manufacture/Repack":

View File

@@ -2,7 +2,7 @@
{
"creation": "2013-03-29 18:22:12",
"docstatus": 0,
"modified": "2013-11-08 16:15:44",
"modified": "2014-01-15 16:08:45",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -165,7 +165,7 @@
"read_only": 1
},
{
"depends_on": "eval:sys_defaults.auto_accounting_for_stock",
"depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)",
"doctype": "DocField",
"fieldname": "expense_account",
"fieldtype": "Link",
@@ -175,7 +175,7 @@
},
{
"default": ":Company",
"depends_on": "eval:sys_defaults.auto_accounting_for_stock",
"depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)",
"doctype": "DocField",
"fieldname": "cost_center",
"fieldtype": "Link",

View File

@@ -2,7 +2,7 @@
{
"creation": "2013-03-28 10:35:31",
"docstatus": 0,
"modified": "2013-09-24 15:35:12",
"modified": "2014-01-15 15:45:07",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -102,7 +102,7 @@
"reqd": 1
},
{
"depends_on": "eval:sys_defaults.auto_accounting_for_stock",
"depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)",
"doctype": "DocField",
"fieldname": "expense_account",
"fieldtype": "Link",
@@ -110,6 +110,7 @@
"options": "Account"
},
{
"depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)",
"doctype": "DocField",
"fieldname": "cost_center",
"fieldtype": "Link",

View File

@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import webnotes
from webnotes.utils import cint, validate_email_add
from webnotes import msgprint, _
from webnotes import throw, msgprint, _
class DocType:
def __init__(self, doc, doclist=[]):
@@ -18,7 +18,20 @@ class DocType:
def validate(self):
if self.doc.email_id and not validate_email_add(self.doc.email_id):
msgprint("Please enter valid Email Id", raise_exception=1)
throw(_("Please enter valid Email Id"))
self.update_parent_account()
def update_parent_account(self):
if not self.doc.__islocal and (self.doc.create_account_under !=
webnotes.conn.get_value("Warehouse", self.doc.name, "create_account_under")):
warehouse_account = webnotes.conn.get_value("Account",
{"account_type": "Warehouse", "company": self.doc.company,
"master_name": self.doc.name}, ["name", "parent_account"])
if warehouse_account and warehouse_account[1] != self.doc.create_account_under:
acc_bean = webnotes.bean("Account", warehouse_account[0])
acc_bean.doc.parent_account = self.doc.create_account_under
acc_bean.save()
def on_update(self):
self.create_account_head()
@@ -63,8 +76,8 @@ class DocType:
for d in bins:
if d['actual_qty'] or d['reserved_qty'] or d['ordered_qty'] or \
d['indented_qty'] or d['projected_qty'] or d['planned_qty']:
msgprint("""Warehouse: %s can not be deleted as qty exists for item: %s"""
% (self.doc.name, d['item_code']), raise_exception=1)
throw("""Warehouse: %s can not be deleted as qty exists for item: %s"""
% (self.doc.name, d['item_code']))
else:
webnotes.conn.sql("delete from `tabBin` where name = %s", d['name'])
@@ -75,24 +88,23 @@ class DocType:
if webnotes.conn.sql("""select name from `tabStock Ledger Entry`
where warehouse = %s""", self.doc.name):
msgprint("""Warehouse can not be deleted as stock ledger entry
exists for this warehouse.""", raise_exception=1)
throw(_("""Warehouse can not be deleted as stock ledger entry
exists for this warehouse."""))
def before_rename(self, olddn, newdn, merge=False):
# Add company abbr if not provided
from setup.doctype.company.company import get_name_with_abbr
new_warehouse = get_name_with_abbr(newdn, self.doc.company)
if merge:
if self.doc.company != webnotes.conn.get_value("Warehouse", new_warehouse, "company"):
if not webnotes.conn.exists("Warehouse", newdn):
webnotes.throw(_("Warehouse ") + newdn +_(" does not exists"))
if self.doc.company != webnotes.conn.get_value("Warehouse", newdn, "company"):
webnotes.throw(_("Both Warehouse must belong to same Company"))
webnotes.conn.sql("delete from `tabBin` where warehouse=%s", olddn)
from accounts.utils import rename_account_for
rename_account_for("Warehouse", olddn, new_warehouse, merge)
rename_account_for("Warehouse", olddn, newdn, merge)
return new_warehouse
return newdn
def after_rename(self, olddn, newdn, merge=False):
if merge:

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