Compare commits

..

142 Commits

Author SHA1 Message Date
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
Pratik Vyas
605cc93c90 Merge branch 'develop' 2013-12-19 11:42:38 +05:30
Pratik Vyas
1644fce273 bumped to version 3.3.3 2013-12-19 12:12:38 +06:00
Pratik Vyas
8cc2bf7fcf Merge pull request #1213 from pdvyas/email-digest-error
fix company email digest patch
2013-12-18 22:12:03 -08:00
Pratik Vyas
fe6409debf fix company email digest patch 2013-12-19 11:41:10 +05:30
Nabin Hait
edc58619d1 Merge pull request #1211 from nabinhait/hotfix
fixes in item validation
2013-12-18 21:28:25 -08:00
Nabin Hait
85800fa929 fixes in item validation 2013-12-19 10:57:43 +05:30
Nabin Hait
60ec0128a2 Merge pull request #1205 from akhileshdarjee/master
[fix] [issue] webnotes/erpnext#1191 - set expected delivery date in production order
2013-12-18 20:03:36 -08:00
Nabin Hait
90e0700e24 Merge pull request #1208 from nabinhait/hotfix
fixes in stock projected qty report
2013-12-18 05:46:03 -08:00
Nabin Hait
48156e3d8b fixes in stock projected qty report 2013-12-18 18:51:20 +05:30
Nabin Hait
8b353e5e15 Merge pull request #1207 from nabinhait/hotfix
Removed sales_order_no from no_copy in material request item
2013-12-18 01:24:02 -08:00
Nabin Hait
fcbd4d7638 Removed sales_order_no from no_copy in material request item 2013-12-18 14:53:36 +05:30
Pratik Vyas
9409efe02a Merge branch 'develop' 2013-12-18 14:40:36 +05:30
Pratik Vyas
b645a217fd bumped to version 3.3.2 2013-12-18 15:10:36 +06:00
Pratik Vyas
ef295d2977 Merge pull request #1203 from anandpdoshi/hotfix-scheduler-errors
[fix] scheduler error email digest
2013-12-18 01:10:12 -08:00
Akhilesh Darjee
2d0e31b479 [fix] [minor] merge conflict fixed 2013-12-18 13:32:37 +05:30
Akhilesh Darjee
2678ed181a [fix] [issue] webnotes/erpnext#1191 - set expected delivery date in production order 2013-12-18 13:28:40 +05:30
Anand Doshi
1fce0b1f79 [fix] scheduler error email digest 2013-12-18 13:22:18 +05:30
Pratik Vyas
649660d9f0 Merge branch 'develop' 2013-12-18 12:19:28 +05:30
Pratik Vyas
797e0713ea bumped to version 3.3.1 2013-12-18 12:49:28 +06:00
Nabin Hait
6a0ffabbd0 Merge pull request #1201 from nabinhait/hotfix
Hotfix
2013-12-17 21:48:18 -08:00
Nabin Hait
56f58cfa68 Merge pull request #1202 from anandpdoshi/hotfix-backup-manager
[fix] backup manager
2013-12-17 21:48:03 -08:00
Anand Doshi
677ef0c3cf [fix] backup manager 2013-12-18 10:56:43 +05:30
Nabin Hait
64367a905a Merge branch 'develop' of github.com:webnotes/erpnext into hotfix 2013-12-18 10:42:04 +05:30
Nabin Hait
c565de2c12 Removed schedule_date from no_copy in purchase receipt item 2013-12-18 10:41:29 +05:30
Nabin Hait
908f2dc0fd Merge pull request #1200 from anandpdoshi/hotfix-scheduler-errors
[patch] Email Digest
2013-12-17 20:13:56 -08:00
Anand Doshi
0b1a8e13fd [patch] Email Digest 2013-12-18 07:53:49 +05:30
85 changed files with 945 additions and 599 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,7 @@
from __future__ import unicode_literals
import webnotes
from webnotes.utils import cint, cstr
from webnotes import msgprint, _
from webnotes import _
class DocType:
def __init__(self, d, dl):
@@ -16,6 +15,11 @@ class DocType:
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])
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

@@ -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

@@ -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

@@ -350,7 +350,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 +358,7 @@ 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 = item.amount + item.item_tax_amount + item.rm_supp_cost
gl_entries.append(
self.get_gl_dict({
@@ -393,12 +386,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(

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

@@ -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,20 +15,28 @@ 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):
data = []
future_vouchers = self.get_entries_after(self.filters.report_date)
for gle in self.get_entries_till(self.filters.report_date):
@@ -42,18 +50,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 +78,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 +171,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

@@ -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::200"]
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_advance, 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_advance) == "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):
@@ -368,4 +378,4 @@ def get_account_for(account_for_doctype, account_for):
account_for_field = "account_type"
return webnotes.conn.get_value("Account", {account_for_field: account_for_doctype,
"master_name": account_for})
"master_name": account_for})

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 }
}
});
}

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

@@ -95,6 +95,6 @@ cur_frm.cscript.make_contact = function() {
cur_frm.fields_dict['default_price_list'].get_query = function(doc,cdt,cdn) {
return{
filters:{'buying_or_selling': "Buying"}
filters:{'buying': 1}
}
}

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
@@ -90,7 +90,7 @@ 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'""",
where price_list=%s and item_code=%s and buying=1""",
(args.buying_price_list, args.item_code), as_dict=1)
if price_list_rate:
@@ -122,14 +122,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.0",
"app_version": "3.5.0",
"base_template": "app/portal/templates/base.html",
"modules": {
"Accounts": {
@@ -74,5 +74,5 @@
"type": "module"
}
},
"requires_framework_version": "==3.3.0"
"requires_framework_version": "==3.5.0"
}

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 flt, cint, today, cstr
from webnotes.model.code import get_obj
from setup.utils import get_company_currency
@@ -50,8 +50,8 @@ class AccountsController(TransactionBase):
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)
throw(_("Account for this ") + fieldname + _(" has been freezed. ") +
self.doc.doctype + _(" can not be made."))
def set_price_list_currency(self, buying_or_selling):
if self.meta.get_field("currency"):
@@ -179,17 +179,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 +200,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 +213,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
@@ -231,9 +231,6 @@ class AccountsController(TransactionBase):
# 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
@@ -384,24 +381,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
@@ -162,35 +163,44 @@ 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
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)
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"]])
for item in 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
item.item_tax_amount = flt(item_proportion * total_valuation_amount,
self.precision("item_tax_amount", item))
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

@@ -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,22 @@ 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 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

@@ -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==1.2.4",
"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

@@ -1,28 +1,56 @@
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
cur_frm.cscript.onload = function(doc, dt, dn) {
if (!doc.status) doc.status = 'Draft';
cfn_set_fields(doc, dt, dn);
}
$.extend(cur_frm.cscript, {
onload: function (doc, dt, dn) {
cur_frm.cscript.refresh = function(doc, dt, dn) {
cur_frm.dashboard.reset();
erpnext.hide_naming_series();
cur_frm.set_intro("");
cfn_set_fields(doc, dt, dn);
if (!doc.status) doc.status = 'Draft';
cfn_set_fields(doc, dt, dn);
if(doc.docstatus===0 && !doc.__islocal) {
cur_frm.set_intro(wn._("Submit this Production Order for further processing."));
} else if(doc.docstatus===1) {
var percent = flt(doc.produced_qty) / flt(doc.qty) * 100;
cur_frm.dashboard.add_progress(cint(percent) + "% " + wn._("Complete"), percent);
this.frm.add_fetch("sales_order", "delivery_date", "expected_delivery_date");
},
if(doc.status === "Stopped") {
cur_frm.dashboard.set_headline_alert(wn._("Stopped"), "alert-danger", "icon-stop");
refresh: function(doc, dt, dn) {
this.frm.dashboard.reset();
erpnext.hide_naming_series();
this.frm.set_intro("");
cfn_set_fields(doc, dt, dn);
if (doc.docstatus === 0 && !doc.__islocal) {
this.frm.set_intro(wn._("Submit this Production Order for further processing."));
} else if (doc.docstatus === 1) {
var percent = flt(doc.produced_qty) / flt(doc.qty) * 100;
this.frm.dashboard.add_progress(cint(percent) + "% " + wn._("Complete"), percent);
if(doc.status === "Stopped") {
this.frm.dashboard.set_headline_alert(wn._("Stopped"), "alert-danger", "icon-stop");
}
}
},
production_item: function(doc) {
return this.frm.call({
method: "get_item_details",
args: { item: doc.production_item }
});
},
make_se: function(purpose) {
var me = this;
wn.call({
method:"manufacturing.doctype.production_order.production_order.make_stock_entry",
args: {
"production_order_id": me.frm.doc.name,
"purpose": purpose
},
callback: function(r) {
var doclist = wn.model.sync(r.message);
wn.set_route("Form", doclist[0].doctype, doclist[0].name);
}
});
}
}
});
var cfn_set_fields = function(doc, dt, dn) {
if (doc.docstatus == 1) {
@@ -38,13 +66,6 @@ var cfn_set_fields = function(doc, dt, dn) {
}
}
cur_frm.cscript.production_item = function(doc) {
return cur_frm.call({
method: "get_item_details",
args: { item: doc.production_item }
});
}
cur_frm.cscript['Stop Production Order'] = function() {
var doc = cur_frm.doc;
var check = confirm(wn._("Do you really want to stop production order: " + doc.name));
@@ -57,7 +78,7 @@ cur_frm.cscript['Unstop Production Order'] = function() {
var doc = cur_frm.doc;
var check = confirm(wn._("Do really want to unstop production order: " + doc.name));
if (check)
return $c_obj(make_doclist(doc.doctype, doc.name), 'stop_unstop', 'Unstopped', function(r, rt) {cur_frm.refresh();});
return $c_obj(make_doclist(doc.doctype, doc.name), 'stop_unstop', 'Unstopped', function(r, rt) {cur_frm.refresh();});
}
cur_frm.cscript['Transfer Raw Materials'] = function() {
@@ -68,20 +89,6 @@ cur_frm.cscript['Update Finished Goods'] = function() {
cur_frm.cscript.make_se('Manufacture/Repack');
}
cur_frm.cscript.make_se = function(purpose) {
wn.call({
method:"manufacturing.doctype.production_order.production_order.make_stock_entry",
args: {
"production_order_id": cur_frm.doc.name,
"purpose": purpose
},
callback: function(r) {
var doclist = wn.model.sync(r.message);
wn.set_route("Form", doclist[0].doctype, doclist[0].name);
}
})
}
cur_frm.fields_dict['production_item'].get_query = function(doc) {
return {
filters:[
@@ -98,7 +105,6 @@ cur_frm.fields_dict['project_name'].get_query = function(doc, dt, dn) {
}
}
cur_frm.set_query("bom_no", function(doc) {
if (doc.production_item) {
return{

View File

@@ -8,7 +8,6 @@ from webnotes.utils import cstr, flt, nowdate
from webnotes.model.code import get_obj
from webnotes import msgprint, _
class OverProductionError(webnotes.ValidationError): pass
class DocType:
@@ -37,15 +36,20 @@ class DocType:
and is_active=1 and item=%s"""
, (self.doc.bom_no, self.doc.production_item), as_dict =1)
if not bom:
msgprint("""Incorrect BOM: %s entered.
webnotes.throw("""Incorrect BOM: %s entered.
May be BOM not exists or inactive or not submitted
or for some other item.""" % cstr(self.doc.bom_no), raise_exception=1)
or for some other item.""" % cstr(self.doc.bom_no))
def validate_sales_order(self):
if self.doc.sales_order:
if not webnotes.conn.sql("""select name from `tabSales Order`
where name=%s and docstatus = 1""", self.doc.sales_order):
msgprint("Sales Order: %s is not valid" % self.doc.sales_order, raise_exception=1)
so = webnotes.conn.sql("""select name, delivery_date from `tabSales Order`
where name=%s and docstatus = 1""", self.doc.sales_order, as_dict=1)[0]
if not so.name:
webnotes.throw("Sales Order: %s is not valid" % self.doc.sales_order)
if not self.doc.expected_delivery_date:
self.doc.expected_delivery_date = so.delivery_date
self.validate_production_order_against_so()
@@ -76,11 +80,11 @@ class DocType:
so_qty = flt(so_item_qty) + flt(dnpi_qty)
if total_qty > so_qty:
webnotes.msgprint(_("Total production order qty for item") + ": " +
webnotes.throw(_("Total production order qty for item") + ": " +
cstr(self.doc.production_item) + _(" against sales order") + ": " +
cstr(self.doc.sales_order) + _(" will be ") + cstr(total_qty) + ", " +
_("which is greater than sales order qty ") + "(" + cstr(so_qty) + ")" +
_("Please reduce qty."), raise_exception=OverProductionError)
_("Please reduce qty."), exc=OverProductionError)
def stop_unstop(self, status):
""" Called from client side on Stop/Unstop event"""
@@ -114,8 +118,8 @@ class DocType:
stock_entry = webnotes.conn.sql("""select name from `tabStock Entry`
where production_order = %s and docstatus = 1""", self.doc.name)
if stock_entry:
msgprint("""Submitted Stock Entry %s exists against this production order.
Hence can not be cancelled.""" % stock_entry[0][0], raise_exception=1)
webnotes.throw("""Submitted Stock Entry %s exists against this production order.
Hence can not be cancelled.""" % stock_entry[0][0])
webnotes.conn.set(self.doc,'status', 'Cancelled')
self.update_planned_qty(-self.doc.qty)

View File

@@ -2,7 +2,7 @@
{
"creation": "2013-01-10 16:34:16",
"docstatus": 0,
"modified": "2013-11-02 14:05:44",
"modified": "2013-12-18 13:22:14",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -136,6 +136,14 @@
"oldfieldtype": "Currency",
"read_only": 1
},
{
"depends_on": "sales_order",
"doctype": "DocField",
"fieldname": "expected_delivery_date",
"fieldtype": "Date",
"label": "Expected Delivery Date",
"read_only": 1
},
{
"doctype": "DocField",
"fieldname": "warehouses",

View File

@@ -34,6 +34,7 @@ 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.run_method("get_items")
stock_entry.submit()
@@ -50,7 +51,7 @@ 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.fg_completed_qty = 15
stock_entry.run_method("get_items")
stock_entry.insert()

View File

@@ -186,7 +186,6 @@ class DocType:
else :
msgprint(_("No Production Order created."))
def get_distinct_items_and_boms(self):
""" Club similar BOM and item for processing
bom_dict {

View File

@@ -5,19 +5,28 @@ from __future__ import unicode_literals
import webnotes
def execute():
webnotes.reload_doc("setup", "doctype", "email_digest")
from webnotes.profile import get_system_managers
system_managers = get_system_managers(only_name=True)
if not system_managers:
return
# no default company
company = webnotes.conn.sql_list("select name from `tabCompany`")
if company:
company = company[0]
if not company:
return
# scheduler errors digest
edigest = webnotes.new_bean("Email Digest")
edigest.doc.fields.update({
"name": "Scheduler Errors",
"company": webnotes.conn.get_default("company"),
"company": company,
"frequency": "Daily",
"enabled": 1,
"recipient_list": "\n".join(system_managers),
"scheduler_errors": 1
})
edigest.insert()
edigest.insert()

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,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

@@ -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

@@ -261,4 +261,7 @@ patch_list = [
"execute:webnotes.delete_doc('Report', 'Payment Made With Ageing')",
"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_make_buying_selling_as_check_box_in_price_list",
]

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

@@ -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

@@ -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)) {

View File

@@ -122,6 +122,6 @@ cur_frm.fields_dict.lead_name.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

@@ -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,7 +3,7 @@
from __future__ import unicode_literals
import webnotes
from webnotes import msgprint, _
from webnotes import msgprint, _, throw
from webnotes.utils import flt, cint, comma_and
import json
@@ -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,14 +111,12 @@ 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
@@ -147,7 +145,7 @@ def _get_basic_details(args, item_bean, warehouse_fieldname):
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'""",
where price_list=%s and item_code=%s and selling=1""",
(args.selling_price_list, args.item_code), as_dict=1)
if not ref_rate:

View File

@@ -16,8 +16,6 @@ import webnotes
from webnotes.utils import get_request_site_address, cstr
from webnotes import _
from backup_manager import ignore_list
@webnotes.whitelist()
def get_dropbox_authorize_url():
sess = get_dropbox_session()
@@ -100,9 +98,7 @@ def backup_to_dropbox():
path = get_files_path()
for filename in os.listdir(path):
filename = cstr(filename)
if filename in ignore_list:
continue
found = False
filepath = os.path.join(path, filename)
for file_metadata in response["contents"]:

View File

@@ -87,7 +87,7 @@ $.extend(cur_frm.cscript, {
cur_frm.save();
},
upload_backups_to_gdrive: function() {
cur_frm.save();
},
// upload_backups_to_gdrive: function() {
// cur_frm.save();
// },
});

View File

@@ -7,8 +7,6 @@ from __future__ import unicode_literals
import webnotes
from webnotes import _
ignore_list = []
class DocType:
def __init__(self, d, dl):
self.doc, self.doclist = d, dl
@@ -39,10 +37,6 @@ def take_backups_dropbox():
file_and_error = [" - ".join(f) for f in zip(did_not_upload, error_log)]
error_message = ("\n".join(file_and_error) + "\n" + webnotes.getTraceback())
webnotes.errprint(error_message)
if not webnotes.conn:
webnotes.connect()
send_email(False, "Dropbox", error_message)
#backup to gdrive
@@ -62,6 +56,7 @@ def take_backups_gdrive():
send_email(False, "Google Drive", error_message)
def send_email(success, service_name, error_status=None):
from webnotes.utils.email_lib import sendmail
if success:
subject = "Backup Upload Successful"
message ="""<h3>Backup Uploaded Successfully</h3><p>Hi there, this is just to inform you
@@ -76,7 +71,8 @@ def send_email(success, service_name, error_status=None):
<p>Please contact your system manager for more information.</p>
""" % (service_name, error_status)
# email system managers
from webnotes.utils.email_lib import sendmail
sendmail(webnotes.conn.get_value("Backup Manager", None, "send_notifications_to").split(","),
subject=subject, msg=message)
if not webnotes.conn:
webnotes.connect()
recipients = webnotes.conn.get_value("Backup Manager", None, "send_notifications_to").split(",")
sendmail(recipients, subject=subject, msg=message)

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,8 @@ def create_price_lists(args):
{
"doctype": "Price List",
"price_list_name": "Standard " + pl_type,
"buying_or_selling": pl_type,
"buying": 1 if pl_type == "Buying" else 0,
"selling": 1 if pl_type == "Selling" else 0,
"currency": args["currency"]
},
{
@@ -158,6 +159,10 @@ def set_defaults(args):
hr_settings.doc.emp_created_by = "Naming Series"
hr_settings.save()
email_settings = webnotes.bean("Email Settings")
email_settings.doc.send_print_in_body_and_attachment = 1
email_settings.save()
# control panel
cp = webnotes.doc("Control Panel", "Control Panel")
cp.company_name = args["company_name"]
@@ -175,7 +180,8 @@ def create_email_digest():
if not system_managers:
return
for company in webnotes.conn.sql_list("select name FROM `tabCompany`"):
companies = webnotes.conn.sql_list("select name FROM `tabCompany`")
for company in companies:
if not webnotes.conn.exists("Email Digest", "Default Weekly Digest - " + company):
edigest = webnotes.bean({
"doctype": "Email Digest",
@@ -192,16 +198,17 @@ def create_email_digest():
edigest.insert()
# scheduler errors digest
edigest = webnotes.new_bean("Email Digest")
edigest.doc.fields.update({
"name": "Scheduler Errors",
"company": webnotes.conn.get_default("company"),
"frequency": "Daily",
"recipient_list": "\n".join(system_managers),
"scheduler_errors": 1,
"enabled": 1
})
edigest.insert()
if companies:
edigest = webnotes.new_bean("Email Digest")
edigest.doc.fields.update({
"name": "Scheduler Errors",
"company": companies[0],
"frequency": "Daily",
"recipient_list": "\n".join(system_managers),
"scheduler_errors": 1,
"enabled": 1
})
edigest.insert()
def get_fy_details(fy_start_date, fy_end_date):
start_year = getdate(fy_start_date).year

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

@@ -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:
@@ -123,14 +124,14 @@ class DocType(DocListController, WebsiteGenerator):
msgprint("'Has Serial No' can not be 'Yes' for non-stock item", raise_exception=1)
def check_for_active_boms(self):
if self.doc.is_active != "Yes" or self.doc.is_purchase_item != "Yes":
if self.doc.is_purchase_item != "Yes":
bom_mat = webnotes.conn.sql("""select distinct t1.parent
from `tabBOM Item` t1, `tabBOM` t2 where t2.name = t1.parent
and t1.item_code =%s and ifnull(t1.bom_no, '') = '' and t2.is_active = 1
and t2.docstatus = 1 and t1.docstatus =1 """, self.doc.name)
if bom_mat and bom_mat[0][0]:
webnotes.throw(_("Item must be active and purchase item, \
webnotes.throw(_("Item must be a purchase item, \
as it is present in one or many Active BOMs"))
if self.doc.is_manufactured_item != "Yes":
@@ -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

@@ -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,7 +1,5 @@
# 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
@@ -19,8 +17,8 @@ class DocType:
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"])
self.doc.buying, self.doc.selling, self.doc.currency = webnotes.conn.get_value("Price List",
self.doc.price_list, ["buying", "selling", "currency"])
def update_item_details(self):
self.doc.item_name, self.doc.item_description = webnotes.conn.get_value("Item",

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

@@ -2,7 +2,7 @@
{
"creation": "2013-02-22 01:28:02",
"docstatus": 0,
"modified": "2013-11-03 20:36:45",
"modified": "2013-12-18 14:52:02",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -219,7 +219,7 @@
"fieldname": "sales_order_no",
"fieldtype": "Link",
"label": "Sales Order No",
"no_copy": 1,
"no_copy": 0,
"options": "Sales Order",
"print_hide": 1,
"read_only": 1

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-06 18:28:23",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -61,14 +61,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

@@ -12,7 +12,7 @@ test_records = [
"doctype": "Price List",
"price_list_name": "_Test Price List",
"currency": "INR",
"buying_or_selling": "Selling"
"selling": 1
},
{
"doctype": "Applicable Territory",
@@ -25,7 +25,7 @@ test_records = [
"doctype": "Price List",
"price_list_name": "_Test Price List 2",
"currency": "INR",
"buying_or_selling": "Selling"
"selling": 1
},
{
"doctype": "Applicable Territory",
@@ -38,7 +38,7 @@ test_records = [
"doctype": "Price List",
"price_list_name": "_Test Price List India",
"currency": "INR",
"buying_or_selling": "Selling"
"selling": 1
},
{
"doctype": "Applicable Territory",
@@ -51,7 +51,7 @@ test_records = [
"doctype": "Price List",
"price_list_name": "_Test Price List Rest of the World",
"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-11-02 19:41:45",
"modified": "2014-01-03 18:28:20",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -326,7 +326,7 @@
"fieldname": "schedule_date",
"fieldtype": "Date",
"label": "Required By",
"no_copy": 1,
"no_copy": 0,
"oldfieldname": "schedule_date",
"oldfieldtype": "Date",
"print_hide": 1,
@@ -334,6 +334,16 @@
"report_hide": 0,
"reqd": 0
},
{
"default": ":Company",
"depends_on": "eval: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

@@ -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 (

View File

@@ -20,6 +20,19 @@ class DocType:
if self.doc.email_id and not validate_email_add(self.doc.email_id):
msgprint("Please enter valid Email Id", raise_exception=1)
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()
@@ -84,6 +97,9 @@ class DocType:
new_warehouse = get_name_with_abbr(newdn, self.doc.company)
if merge:
if not webnotes.conn.exists("Warehouse", newdn):
webnotes.throw(_("Warehouse ") + newdn +_(" does not exists"))
if self.doc.company != webnotes.conn.get_value("Warehouse", new_warehouse, "company"):
webnotes.throw(_("Both Warehouse must belong to same Company"))

View File

@@ -15,8 +15,8 @@ def execute(filters=None):
bom_rate = get_item_bom_rate()
val_rate_map = get_valuation_rate()
precision = webnotes.conn.get_value("Global Defaults", None, "float_precision") or 2
precision = get_currency_precision or 2
data = []
for item in sorted(item_map):
data.append([item, item_map[item]["item_name"],
@@ -30,6 +30,14 @@ def execute(filters=None):
])
return columns, data
def get_currency_precision():
company_currency = webnotes.conn.get_value("Company",
webnotes.conn.get_default("company"), "default_currency")
currency_format = webnotes.conn.get_value("Currency", company_currency, "number_format")
from webnotes.utils import get_number_format_info
return get_number_format_info(currency_format)[2]
def get_columns(filters):
"""return columns based on filters"""
@@ -57,13 +65,13 @@ def get_price_list():
rate = {}
price_list = webnotes.conn.sql("""select item_code, buying_or_selling,
price_list = webnotes.conn.sql("""select item_code, buying, selling,
concat(price_list, " - ", currency, " ", ref_rate) as price
from `tabItem Price`""", as_dict=1)
for j in price_list:
if j.price:
rate.setdefault(j.item_code, {}).setdefault(j.buying_or_selling, []).append(j.price)
rate.setdefault(j.item_code, {}).setdefault("Buying" if j.buying else "Selling", []).append(j.price)
item_rate_map = {}
for item in rate:

View File

@@ -0,0 +1,22 @@
[
{
"creation": "2013-09-25 10:21:15",
"docstatus": 0,
"modified": "2014-01-07 18:35:22",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"doctype": "Report",
"is_standard": "Yes",
"json": "{\"filters\":[[\"Item Price\",\"price_list\",\"like\",\"%\"],[\"Item Price\",\"item_code\",\"like\",\"%\"]],\"columns\":[[\"name\",\"Item Price\"],[\"price_list\",\"Item Price\"],[\"item_code\",\"Item Price\"],[\"item_name\",\"Item Price\"],[\"item_description\",\"Item Price\"],[\"ref_rate\",\"Item Price\"],[\"buying\",\"Item Price\"],[\"selling\",\"Item Price\"],[\"currency\",\"Item Price\"]],\"sort_by\":\"Item Price.modified\",\"sort_order\":\"desc\",\"sort_by_next\":\"\",\"sort_order_next\":\"desc\"}",
"name": "__common__",
"ref_doctype": "Price List",
"report_name": "Item-wise Price List Rate",
"report_type": "Report Builder"
},
{
"doctype": "Report",
"name": "Item-wise Price List Rate"
}
]

View File

@@ -67,7 +67,7 @@ def get_stock_ledger_entries(filters):
item.name, item.item_name, item_group, brand, description, item.stock_uom,
actual_qty, posting_date
from `tabStock Ledger Entry` sle,
(select name, item_name, description, stock_uom, brand
(select name, item_name, description, stock_uom, brand, item_group
from `tabItem` {item_conditions}) item
where item_code = item.name and
company = %(company)s and

View File

@@ -3,7 +3,6 @@
from __future__ import unicode_literals
import webnotes
from webnotes import _
def execute(filters=None):
columns = get_columns()
@@ -13,10 +12,14 @@ def execute(filters=None):
data = []
for sle in sl_entries:
item_detail = item_details[sle.item_code]
voucher_link_icon = """<a href="%s"><i class="icon icon-share"
style="cursor: pointer;"></i></a>""" \
% ("/".join(["#Form", sle.voucher_type, sle.voucher_no]),)
data.append([sle.date, sle.item_code, item_detail.item_name, item_detail.item_group,
item_detail.brand, item_detail.description, sle.warehouse, item_detail.stock_uom,
sle.actual_qty, sle.qty_after_transaction, sle.stock_value, sle.voucher_type,
sle.voucher_no, sle.batch_no, sle.serial_no, sle.company])
sle.voucher_no, voucher_link_icon, sle.batch_no, sle.serial_no, sle.company])
return columns, data
@@ -25,17 +28,10 @@ def get_columns():
"Item Group:Link/Item Group:100", "Brand:Link/Brand:100",
"Description::200", "Warehouse:Link/Warehouse:100",
"Stock UOM:Link/UOM:100", "Qty:Float:50", "Balance Qty:Float:80",
"Balance Value:Currency:100", "Voucher Type::100", "Voucher #::100",
"Balance Value:Currency:100", "Voucher Type::100", "Voucher #::100", "Link::30",
"Batch:Link/Batch:100", "Serial #:Link/Serial No:100", "Company:Link/Company:100"]
def get_stock_ledger_entries(filters):
if not filters.get("company"):
webnotes.throw(_("Company is mandatory"))
if not filters.get("from_date"):
webnotes.throw(_("From Date is mandatory"))
if not filters.get("to_date"):
webnotes.throw(_("To Date is mandatory"))
return webnotes.conn.sql("""select concat_ws(" ", posting_date, posting_time) as date,
item_code, warehouse, actual_qty, qty_after_transaction,
stock_value, voucher_type, voucher_no, batch_no, serial_no, company
@@ -66,6 +62,10 @@ def get_item_conditions(filters):
def get_sle_conditions(filters):
conditions = []
item_conditions=get_item_conditions(filters)
if item_conditions:
conditions.append("""item_code in (select name from tabItem
{item_conditions})""".format(item_conditions=item_conditions))
if filters.get("warehouse"):
conditions.append("warehouse=%(warehouse)s")
if filters.get("voucher_no"):

View File

@@ -7,9 +7,7 @@ wn.query_reports["Stock Projected Qty"] = {
"fieldname":"company",
"label": wn._("Company"),
"fieldtype": "Link",
"options": "Company",
"default": wn.defaults.get_user_default("company"),
"reqd": 1
"options": "Company"
},
{
"fieldname":"warehouse",

View File

@@ -13,23 +13,23 @@ def execute(filters=None):
projected_qty, item.re_order_level, item.re_order_qty
from `tabBin` bin,
(select name, company from tabWarehouse
where company=%(company)s {warehouse_conditions}) wh,
{warehouse_conditions}) wh,
(select name, item_name, description, stock_uom, item_group,
brand, re_order_level, re_order_qty
from `tabItem` {item_conditions}) item
where item_code = item.name and warehouse = wh.name
order by item.name, wh.name"""\
.format(item_conditions=get_item_conditions(filters),
warehouse_conditions=get_warehouse_conditions(filters)), filters, debug=1)
warehouse_conditions=get_warehouse_conditions(filters)), filters)
return columns, data
def get_columns():
return ["Item Code:Link/Item:140", "Item Name::100", "Description::200",
"Brand:Link/Brand:100", "Warehouse:Link/Warehouse:120", "UOM:Link/UOM:100",
"Actual Qty:Float:100", "Planned Qty:Float:100", "Requested Qty:Float:110",
"Ordered Qty:Float:100", "Reserved Qty:Float:100", "Projected Qty:Float:100",
"Reorder Level:Float:100", "Reorder Qty:Float:100"]
"Item Group:Link/Item Group:100", "Brand:Link/Brand:100", "Warehouse:Link/Warehouse:120",
"UOM:Link/UOM:100", "Actual Qty:Float:100", "Planned Qty:Float:100",
"Requested Qty:Float:110", "Ordered Qty:Float:100", "Reserved Qty:Float:100",
"Projected Qty:Float:100", "Reorder Level:Float:100", "Reorder Qty:Float:100"]
def get_item_conditions(filters):
conditions = []
@@ -41,4 +41,10 @@ def get_item_conditions(filters):
return "where {}".format(" and ".join(conditions)) if conditions else ""
def get_warehouse_conditions(filters):
return " and name=%(warehouse)s" if filters.get("warehouse") else ""
conditions = []
if filters.get("company"):
conditions.append("company=%(company)s")
if filters.get("warehouse"):
conditions.append("name=%(warehouse)s")
return "where {}".format(" and ".join(conditions)) if conditions else ""

View File

@@ -113,7 +113,14 @@ def update_entries_after(args, verbose=1):
(qty_after_transaction * valuation_rate) or 0
else:
stock_value = sum((flt(batch[0]) * flt(batch[1]) for batch in stock_queue))
# rounding as per precision
from webnotes.model.meta import get_field_precision
meta = webnotes.get_doctype("Stock Ledger Entry")
stock_value = flt(stock_value, get_field_precision(meta.get_field("stock_value"),
webnotes._dict({"fields": sle})))
stock_value_difference = stock_value - prev_stock_value
prev_stock_value = stock_value

View File

@@ -52,11 +52,6 @@ Original Query:
subject = '['+cstr(d.name)+'] ' + cstr(d.subject), \
msg = cstr(response))
def auto_close_tickets(self):
webnotes.conn.sql("""update `tabSupport Ticket` set status = 'Closed'
where status = 'Replied'
and date_sub(curdate(),interval 15 Day) > modified""")
def get_support_mails():
if cint(webnotes.conn.get_value('Email Settings', None, 'sync_support_mails')):
SupportMailbox()

View File

@@ -66,4 +66,9 @@ class DocType(TransactionBase):
def set_status(name, status):
st = webnotes.bean("Support Ticket", name)
st.doc.status = status
st.save()
st.save()
def auto_close_tickets():
webnotes.conn.sql("""update `tabSupport Ticket` set status = 'Closed'
where status = 'Replied'
and date_sub(curdate(),interval 15 Day) > modified""")

View File

@@ -1,49 +1,49 @@
Data Import Template,,,,,,,
Table:,Item Price,,,,,,
,,,,,,,
,,,,,,,
Notes:,,,,,,,
Please do not change the template headings.,,,,,,,
First data column must be blank.,,,,,,,
"If you are uploading new records, leave the ""name"""" (ID) column blank.""",,,,,,,
"If you are uploading new records, ""Naming Series"""" becomes mandatory"," if present.""",,,,,,
Only mandatory fields are necessary for new records. You can delete non-mandatory columns if you wish.,,,,,,,
"For updating, you can update only selective columns.",,,,,,,
You can only upload upto 5000 records in one go. (may be less in some cases),,,,,,,
,,,,,,,
DocType:,Item Price,,,,,,
Column Labels:,ID,Price List,Item Code,Rate,Valid for Buying or Selling?,Item Name,Item Description
Column Name:,name,price_list,item_code,ref_rate,buying_or_selling,item_name,item_description
Mandatory:,Yes,Yes,Yes,Yes,No,No,No
Type:,Data (text),Link,Link,Currency,Select,Data,Text
Info:,,Valid Price List,Valid Item,,"One of: Selling, Buying",,
Start entering data below this line,,,,,,,
,,Standard Buying,Base Bearing Plate,15,Buying,,
,,Standard Buying,Base Plate,20,Buying,,
,,Standard Buying,Bearing Block,10,Buying,,
,,Standard Buying,Bearing Collar,20,Buying,,
,,Standard Buying,Bearing Pipe,15,Buying,,
,,Standard Buying,Blade Rib,10,Buying,,
,,Standard Buying,Disc Collars,74,Buying,,
,,Standard Buying,External Disc,45,Buying,,
,,Standard Buying,Internal Disc,33,Buying,,
,,Standard Buying,Shaft,30,Buying,,
,,Standard Buying,Stand,40,Buying,,
,,Standard Buying,Upper Bearing Plate,50,Buying,,
,,Standard Buying,Wing Sheet,22,Buying,,
,,Standard Selling,Wind Turbine,21,Selling,,
,,Standard Selling,Wind Mill A Series,28,Selling,,
,,Standard Selling,Wind MIll C Series,14,Selling,,
,,Standard Selling,Base Bearing Plate,28,Selling,,
,,Standard Selling,Base Plate,21,Selling,,
,,Standard Selling,Bearing Block,14,Selling,,
,,Standard Selling,Bearing Collar,103.6,Selling,,
,,Standard Selling,Bearing Pipe,63,Selling,,
,,Standard Selling,Blade Rib,46.2,Selling,,
,,Standard Selling,Disc Collars,42,Selling,,
,,Standard Selling,External Disc,56,Selling,,
,,Standard Selling,Internal Disc,70,Selling,,
,,Standard Selling,Shaft,340,Selling,,
,,Standard Selling,Stand,400,Selling,,
,,Standard Selling,Upper Bearing Plate,300,Selling,,
,,Standard Selling,Wing Sheet,30.8,Selling,,
Data Import Template,,,,,,,,
Table:,Item Price,,,,,,,
,,,,,,,,
,,,,,,,,
Notes:,,,,,,,,
Please do not change the template headings.,,,,,,,,
First data column must be blank.,,,,,,,,
"If you are uploading new records, leave the ""name"" (ID) column blank.",,,,,,,,
"If you are uploading new records, ""Naming Series"" becomes mandatory, if present.",,,,,,,,
Only mandatory fields are necessary for new records. You can delete non-mandatory columns if you wish.,,,,,,,,
"For updating, you can update only selective columns.",,,,,,,,
You can only upload upto 5000 records in one go. (may be less in some cases),,,,,,,,
,,,,,,,,
DocType:,Item Price,,,,,,,
Column Labels:,ID,Price List,Item Code,Rate,Buying,Selling,Item Name,Item Description
Column Name:,name,price_list,item_code,ref_rate,buying,selling,item_name,item_description
Mandatory:,Yes,Yes,Yes,Yes,No,No,No,No
Type:,Data (text),Link,Link,Currency,Check,Check,Data,Text
Info:,,Valid Price List,Valid Item,,0 or 1,0 or 1,,
Start entering data below this line,,,,,,,,
,,Standard Buying,Base Bearing Plate,15,1,,,
,,Standard Buying,Base Plate,20,1,,,
,,Standard Buying,Bearing Block,10,1,,,
,,Standard Buying,Bearing Collar,20,1,,,
,,Standard Buying,Bearing Pipe,15,1,,,
,,Standard Buying,Blade Rib,10,1,,,
,,Standard Buying,Disc Collars,74,1,,,
,,Standard Buying,External Disc,45,1,,,
,,Standard Buying,Internal Disc,33,1,,,
,,Standard Buying,Shaft,30,1,,,
,,Standard Buying,Stand,40,1,,,
,,Standard Buying,Upper Bearing Plate,50,1,,,
,,Standard Buying,Wing Sheet,22,1,,,
,,Standard Selling,Wind Turbine,21,,1,,
,,Standard Selling,Wind Mill A Series,28,,1,,
,,Standard Selling,Wind MIll C Series,14,,1,,
,,Standard Selling,Base Bearing Plate,28,,1,,
,,Standard Selling,Base Plate,21,,1,,
,,Standard Selling,Bearing Block,14,,1,,
,,Standard Selling,Bearing Collar,103.6,,1,,
,,Standard Selling,Bearing Pipe,63,,1,,
,,Standard Selling,Blade Rib,46.2,,1,,
,,Standard Selling,Disc Collars,42,,1,,
,,Standard Selling,External Disc,56,,1,,
,,Standard Selling,Internal Disc,70,,1,,
,,Standard Selling,Shaft,340,,1,,
,,Standard Selling,Stand,400,,1,,
,,Standard Selling,Upper Bearing Plate,300,,1,,
,,Standard Selling,Wing Sheet,30.8,,1,,
1 Data Import Template
2 Table: Item Price
3
4
5 Notes:
6 Please do not change the template headings.
7 First data column must be blank.
8 If you are uploading new records, leave the "name"" (ID) column blank." If you are uploading new records, leave the "name" (ID) column blank.
9 If you are uploading new records, "Naming Series"" becomes mandatory If you are uploading new records, "Naming Series" becomes mandatory, if present. if present."
10 Only mandatory fields are necessary for new records. You can delete non-mandatory columns if you wish.
11 For updating, you can update only selective columns.
12 You can only upload upto 5000 records in one go. (may be less in some cases)
13
14 DocType: Item Price
15 Column Labels: ID Price List Item Code Rate Valid for Buying or Selling? Buying Item Name Selling Item Description Item Name Item Description
16 Column Name: name price_list item_code ref_rate buying_or_selling buying item_name selling item_description item_name item_description
17 Mandatory: Yes Yes Yes Yes No No No No
18 Type: Data (text) Link Link Currency Select Check Data Check Text Data Text
19 Info: Valid Price List Valid Item One of: Selling, Buying 0 or 1 0 or 1
20 Start entering data below this line
21 Standard Buying Base Bearing Plate 15 Buying 1
22 Standard Buying Base Plate 20 Buying 1
23 Standard Buying Bearing Block 10 Buying 1
24 Standard Buying Bearing Collar 20 Buying 1
25 Standard Buying Bearing Pipe 15 Buying 1
26 Standard Buying Blade Rib 10 Buying 1
27 Standard Buying Disc Collars 74 Buying 1
28 Standard Buying External Disc 45 Buying 1
29 Standard Buying Internal Disc 33 Buying 1
30 Standard Buying Shaft 30 Buying 1
31 Standard Buying Stand 40 Buying 1
32 Standard Buying Upper Bearing Plate 50 Buying 1
33 Standard Buying Wing Sheet 22 Buying 1
34 Standard Selling Wind Turbine 21 Selling 1
35 Standard Selling Wind Mill A Series 28 Selling 1
36 Standard Selling Wind MIll C Series 14 Selling 1
37 Standard Selling Base Bearing Plate 28 Selling 1
38 Standard Selling Base Plate 21 Selling 1
39 Standard Selling Bearing Block 14 Selling 1
40 Standard Selling Bearing Collar 103.6 Selling 1
41 Standard Selling Bearing Pipe 63 Selling 1
42 Standard Selling Blade Rib 46.2 Selling 1
43 Standard Selling Disc Collars 42 Selling 1
44 Standard Selling External Disc 56 Selling 1
45 Standard Selling Internal Disc 70 Selling 1
46 Standard Selling Shaft 340 Selling 1
47 Standard Selling Stand 400 Selling 1
48 Standard Selling Upper Bearing Plate 300 Selling 1
49 Standard Selling Wing Sheet 30.8 Selling 1