Compare commits

...

49 Commits

Author SHA1 Message Date
Pratik Vyas
02f7e83bd1 Merge branch 'develop' 2014-01-14 18:49:14 +05:30
Pratik Vyas
f55d9414cd bumped to version 3.6.1 2014-01-14 19:19:14 +06:00
Nabin Hait
5644ed37a4 Merge pull request #1316 from nabinhait/hotfix
rounding and divisional loss
2014-01-14 05:05:33 -08:00
Nabin Hait
ee6200576a Highest priority to user properties while fetching warehouse from item 2014-01-14 18:34:10 +05:30
Nabin Hait
eeb8ba18cd Merge branch 'develop' of github.com:webnotes/erpnext into hotfix 2014-01-14 17:44:47 +05:30
Nabin Hait
3a19370892 Rounding issue and divisional loss adjustment 2014-01-14 17:44:34 +05:30
Nabin Hait
6dc1ba6f7f Merge pull request #1314 from nabinhait/hotfix
comment fix
2014-01-14 02:29:39 -08:00
Nabin Hait
d91af2853e Allowed import for customer issue 2014-01-14 15:56:52 +05:30
Nabin Hait
d23ae108ae Fixes in Comment, if comment by not mentioned, consider owner 2014-01-14 15:52:09 +05:30
Pratik Vyas
72f8ae2d5a Merge branch 'develop' 2014-01-13 18:37:07 +05:30
Pratik Vyas
1e347910d5 bumped to version 3.6.0 2014-01-13 19:07:07 +06:00
Nabin Hait
25cfb700bb Merge pull request #1311 from akhileshdarjee/hotfix
Increase and decrease quantity buttons in POS
2014-01-13 04:33:50 -08:00
Nabin Hait
8d2d4e82fd Merge pull request #1302 from nabinhait/hotfix
Hotfix
2014-01-13 04:33:18 -08:00
Nabin Hait
c43d58ac79 Delete Property Setters for Custom Fields, and set them inside Custom Field 2014-01-13 17:55:24 +05:30
Akhilesh Darjee
0b3c10601c Increase and decrease quantity buttons in POS 2014-01-13 13:34:34 +05:30
Nabin Hait
14bf711d04 Fixes in frozen accounts validation 2014-01-13 13:28:07 +05:30
Nabin Hait
35a9d585b4 Bank Reconciliation Statement: Show balance in debit or credit column based on account type 2014-01-13 12:24:27 +05:30
Nabin Hait
38e56eeb45 Merge branch 'develop' of github.com:webnotes/erpnext into hotfix 2014-01-13 12:23:29 +05:30
Nabin Hait
3dd1043d5e Merge pull request #1301 from akhileshdarjee/hotfix
pos view showing inclusive taxes
2014-01-10 03:09:12 -08:00
Nabin Hait
55387aa931 Fixed conflict 2014-01-10 16:31:48 +05:30
Nabin Hait
03463ef73b Move related property setters to custom field property 2014-01-10 16:28:41 +05:30
Akhilesh Darjee
371663169c pos view showing inclusive taxes 2014-01-10 15:05:44 +05:30
Nabin Hait
f3ded044e0 Monthly Salary Register: Month is now optional 2014-01-09 17:38:50 +05:30
Nabin Hait
68b0d54b4b Set default accounts in company related to perpetual inventory, only it is enabled 2014-01-09 17:25:55 +05:30
Pratik Vyas
e4a71935eb Merge branch 'develop' 2014-01-09 15:56:53 +05:30
Pratik Vyas
3e846d19d4 bumped to version 3.5.1 2014-01-09 16:26:53 +06:00
Nabin Hait
5411ece766 Merge pull request #1299 from nabinhait/hotfix
Accounts Receivable fix for partial payment in pos
2014-01-09 02:25:12 -08:00
Nabin Hait
aeb68b2899 Accounts Receivable fix for partial payment in pos 2014-01-09 15:54:18 +05:30
Pratik Vyas
0064dc6f4a Merge branch 'develop' 2014-01-09 15:52:09 +05:30
Pratik Vyas
11bf06ad76 bumped to version 3.5.0 2014-01-09 16:22:09 +06:00
Nabin Hait
5c6a2acff7 Merge pull request #1298 from nabinhait/hotfix
Accounts Receivable fix for partial payment in pos
2014-01-09 02:20:06 -08:00
Nabin Hait
cdbd4218a8 Accounts Receivable fix for partial payment in pos 2014-01-09 15:49:26 +05:30
Nabin Hait
701cddfb15 Merge pull request #1297 from nabinhait/hotfix
Hotfix
2014-01-08 23:18:54 -08:00
Nabin Hait
4bbf91bea1 Added match condition in general ledger report 2014-01-09 12:44:44 +05:30
Nabin Hait
e481e81e67 Merge pull request #1296 from akhileshdarjee/hotfix
POS print format fixed
2014-01-08 22:23:56 -08:00
Anand Doshi
102b417b52 Fix: Typo on patch 2014-01-09 11:39:10 +05:30
Akhilesh Darjee
efc2a45835 merge conflict fixed 2014-01-08 19:42:17 +05:30
Akhilesh Darjee
5c119a7e95 Merge branch 'master' of github.com:webnotes/erpnext into hotfix 2014-01-08 19:36:26 +05:30
Akhilesh Darjee
f7a102ffe3 POS print format fixed 2014-01-08 19:35:01 +05:30
Nabin Hait
d659343541 Payment Reconciliation: Fix for outstanding voucher query 2014-01-08 17:29:23 +05:30
Nabin Hait
dbf5e54eab Merge pull request #1290 from akhileshdarjee/price-list
Price List and Item Price : Valid for Buying and Selling as separate check box
2014-01-07 21:49:52 -08:00
Pratik Vyas
5eb139a531 Merge branch 'develop' 2014-01-07 21:45:04 +05:30
Pratik Vyas
9e2358c544 bumped to version 3.4.9 2014-01-07 22:15:04 +06:00
Akhilesh Darjee
8d0ef21911 pos invoice print format changes 2014-01-07 19:45:33 +05:30
Pratik Vyas
9a8f37c579 Merge pull request #1289 from pdvyas/hotfix-installer
fix installer python packages issue
2014-01-07 06:14:08 -08:00
Akhilesh Darjee
029f698c65 patch for item price and price list 2014-01-07 19:43:35 +05:30
Akhilesh Darjee
806017c92a Price List and Item Price : Validfor Buying and Selling as separate check box 2014-01-07 18:37:38 +05:30
Pratik Vyas
69951e5d1c fix installer python packages issue 2014-01-07 18:24:40 +05:30
Nabin Hait
10fd91c78e Close tickets automatically through scheduler 2014-01-07 16:18:41 +05:30
48 changed files with 468 additions and 319 deletions

File diff suppressed because one or more lines are too long

View File

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

View File

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

@@ -358,7 +358,8 @@ class DocType(BuyingController):
# expense will be booked in sales invoice
stock_item_and_auto_accounting_for_stock = True
valuation_amt = item.amount + item.item_tax_amount + item.rm_supp_cost
valuation_amt = flt(item.amount + item.item_tax_amount + item.rm_supp_cost,
self.precision("amount", item))
gl_entries.append(
self.get_gl_dict({

View File

@@ -19,8 +19,10 @@ erpnext.POS = Class.extend({
<table class="table table-condensed table-hover" id="cart" style="table-layout: fixed;">\
<thead>\
<tr>\
<th style="width: 50%">Item</th>\
<th style="width: 25%; text-align: right;">Qty</th>\
<th style="width: 40%">Item</th>\
<th style="width: 9%"></th>\
<th style="width: 17%; text-align: right;">Qty</th>\
<th style="width: 9%"></th>\
<th style="width: 25%; text-align: right;">Rate</th>\
</tr>\
</thead>\
@@ -60,10 +62,16 @@ erpnext.POS = Class.extend({
</div>\
</div>\
<br><br>\
<button class="btn btn-success btn-lg make-payment">\
<i class="icon-money"></i> Make Payment</button>\
<button class="btn btn-default btn-lg delete-items pull-right" style="display: none;">\
<i class="icon-trash"></i> Del</button>\
<div class="row">\
<div class="col-sm-9">\
<button class="btn btn-success btn-lg make-payment">\
<i class="icon-money"></i> Make Payment</button>\
</div>\
<div class="col-sm-3">\
<button class="btn btn-default btn-lg remove-items" style="display: none;">\
<i class="icon-trash"></i> Del</button>\
</div>\
</div>\
<br><br>\
</div>\
<div class="col-sm-6">\
@@ -82,7 +90,7 @@ erpnext.POS = Class.extend({
me.refresh();
});
this.call_function("delete-items", function() {me.remove_selected_item();});
this.call_function("remove-items", function() {me.remove_selected_items();});
this.call_function("make-payment", function() {me.make_payment();});
},
check_transaction_type: function() {
@@ -333,7 +341,7 @@ erpnext.POS = Class.extend({
}
this.disable_text_box_and_button();
this.make_payment_button();
this.hide_payment_button();
// If quotation to is not Customer then remove party
if (this.frm.doctype == "Quotation") {
@@ -351,8 +359,18 @@ erpnext.POS = Class.extend({
$(repl('<tr id="%(item_code)s" data-selected="false">\
<td>%(item_code)s%(item_name)s</td>\
<td><input type="text" value="%(qty)s" \
<td style="vertical-align:middle;" align="right">\
<div class="decrease-qty" style="cursor:pointer;">\
<i class="icon-minus-sign icon-large text-danger"></i>\
</div>\
</td>\
<td style="vertical-align:middle;"><input type="text" value="%(qty)s" \
class="form-control qty" style="text-align: right;"></td>\
<td style="vertical-align:middle;cursor:pointer;">\
<div class="increase-qty" style="cursor:pointer;">\
<i class="icon-plus-sign icon-large text-success"></i>\
</div>\
</td>\
<td style="text-align: right;"><b>%(amount)s</b><br>%(rate)s</td>\
</tr>',
{
@@ -364,27 +382,32 @@ erpnext.POS = Class.extend({
}
)).appendTo($items);
});
this.wrapper.find(".increase-qty, .decrease-qty").on("click", function() {
var item_code = $(this).closest("tr").attr("id");
me.selected_item_qty_operation(item_code, $(this).attr("class"));
});
},
show_taxes: function() {
var me = this;
var taxes = wn.model.get_children(this.sales_or_purchase + " Taxes and Charges",
this.frm.doc.name, this.frm.cscript.other_fname, this.frm.doctype);
$(this.wrapper).find(".tax-table")
.toggle((taxes && taxes.length &&
flt(me.frm.doc.other_charges_total_export ||
me.frm.doc.other_charges_added_import) != 0.0) ? true : false)
.toggle((taxes && taxes.length) ? true : false)
.find("tbody").empty();
$.each(taxes, function(i, d) {
$(repl('<tr>\
<td>%(description)s %(rate)s</td>\
<td style="text-align: right;">%(tax_amount)s</td>\
<tr>', {
description: d.description,
rate: ((d.charge_type == "Actual") ? '' : ("(" + d.rate + "%)")),
tax_amount: format_currency(flt(d.tax_amount)/flt(me.frm.doc.conversion_rate),
me.frm.doc.currency)
})).appendTo(".tax-table tbody");
if (d.tax_amount) {
$(repl('<tr>\
<td>%(description)s %(rate)s</td>\
<td style="text-align: right;">%(tax_amount)s</td>\
<tr>', {
description: d.description,
rate: ((d.charge_type == "Actual") ? '' : ("(" + d.rate + "%)")),
tax_amount: format_currency(flt(d.tax_amount)/flt(me.frm.doc.conversion_rate),
me.frm.doc.currency)
})).appendTo(".tax-table tbody");
}
});
},
set_totals: function() {
@@ -427,7 +450,7 @@ erpnext.POS = Class.extend({
$(this.wrapper).find('input, button').each(function () {
$(this).prop('disabled', true);
});
$(this.wrapper).find(".delete-items").hide();
$(this.wrapper).find(".remove-items").hide();
$(this.wrapper).find(".make-payment").hide();
}
else {
@@ -437,14 +460,14 @@ erpnext.POS = Class.extend({
$(this.wrapper).find(".make-payment").show();
}
},
make_payment_button: function() {
hide_payment_button: function() {
var me = this;
// Show Make Payment button only in Sales Invoice
if (this.frm.doctype != "Sales Invoice")
$(this.wrapper).find(".make-payment").hide();
},
refresh_delete_btn: function() {
$(this.wrapper).find(".delete-items").toggle($(".item-cart .warning").length ? true : false);
$(this.wrapper).find(".remove-items").toggle($(".item-cart .warning").length ? true : false);
},
add_item_thru_barcode: function() {
var me = this;
@@ -466,7 +489,7 @@ erpnext.POS = Class.extend({
}
});
},
remove_selected_item: function() {
remove_selected_items: function() {
var me = this;
var selected_items = [];
var no_of_items = $(this.wrapper).find("#cart tbody tr").length;
@@ -487,6 +510,7 @@ erpnext.POS = Class.extend({
}
}
});
this.refresh_grid();
},
refresh_grid: function() {
@@ -494,6 +518,22 @@ erpnext.POS = Class.extend({
this.frm.script_manager.trigger("calculate_taxes_and_totals");
this.refresh();
},
selected_item_qty_operation: function(item_code, operation) {
var me = this;
var child = wn.model.get_children(this.frm.doctype + " Item", this.frm.doc.name,
this.frm.cscript.fname, this.frm.doctype);
$.each(child, function(i, d) {
if (d.item_code == item_code) {
if (operation == "increase-qty")
d.qty += 1;
else if (operation == "decrease-qty")
d.qty != 1 ? d.qty -= 1 : d.qty = 1;
me.refresh();
}
});
},
make_payment: function() {
var me = this;
var no_of_items = $(this.wrapper).find("#cart tbody tr").length;

View File

@@ -42,7 +42,7 @@ class AccountsReceivableReport(object):
for gle in self.get_entries_till(self.filters.report_date):
if self.is_receivable(gle, future_vouchers):
outstanding_amount = self.get_outstanding_amount(gle, self.filters.report_date)
if abs(outstanding_amount) > 0.01:
if abs(outstanding_amount) > 0.0:
due_date = self.get_due_date(gle)
invoiced_amount = gle.debit if (gle.debit > 0) else 0
payment_received = invoiced_amount - outstanding_amount
@@ -78,15 +78,23 @@ 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):
@@ -180,4 +188,4 @@ def get_ageing_data(age_as_on, entry_date, outstanding_amount):
if index is None: index = 3
outstanding_range[index] = outstanding_amount
return [age] + outstanding_range
return [age] + outstanding_range

View File

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

View File

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

View File

@@ -72,6 +72,11 @@ def get_conditions(filters):
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 ""

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

@@ -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.4.8",
"app_version": "3.6.1",
"base_template": "app/portal/templates/base.html",
"modules": {
"Accounts": {
@@ -74,5 +74,5 @@
"type": "module"
}
},
"requires_framework_version": "==3.4.4"
"requires_framework_version": "==3.7.1"
}

View File

@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import webnotes
from webnotes import _, msgprint
from webnotes import _, throw
from webnotes.utils import flt, cint, today, cstr
from webnotes.model.code import get_obj
from setup.utils import get_company_currency
@@ -44,14 +44,13 @@ class AccountsController(TransactionBase):
def validate_for_freezed_account(self):
for fieldname in ["customer", "supplier"]:
if self.meta.get_field(fieldname) and self.doc.fields.get(fieldname):
accounts = webnotes.conn.get_values("Account", {"master_type": fieldname.title(),
"master_name": self.doc.fields[fieldname], "company": self.doc.company},
"freeze_account", as_dict=1)
accounts = webnotes.conn.get_values("Account",
{"master_type": fieldname.title(), "master_name": self.doc.fields[fieldname],
"company": self.doc.company}, "name")
if accounts:
if not filter(lambda x: cstr(x.freeze_account) in ["", "No"], accounts):
msgprint(_("Account for this ") + fieldname + _(" has been freezed. ") +
self.doc.doctype + _(" can not be made."), raise_exception=1)
from accounts.doctype.gl_entry.gl_entry import validate_frozen_account
for account in accounts:
validate_frozen_account(account[0])
def set_price_list_currency(self, buying_or_selling):
if self.meta.get_field("currency"):
@@ -179,17 +178,17 @@ class AccountsController(TransactionBase):
"""
if tax.charge_type in ["On Previous Row Amount", "On Previous Row Total"] and \
(not tax.row_id or cint(tax.row_id) >= tax.idx):
msgprint((_("Row") + " # %(idx)s [%(taxes_doctype)s]: " + \
throw((_("Row") + " # %(idx)s [%(taxes_doctype)s]: " + \
_("Please specify a valid") + " %(row_id_label)s") % {
"idx": tax.idx,
"taxes_doctype": tax.doctype,
"row_id_label": self.meta.get_label("row_id",
parentfield=self.other_fname)
}, raise_exception=True)
})
def validate_inclusive_tax(self, tax):
def _on_previous_row_error(row_range):
msgprint((_("Row") + " # %(idx)s [%(doctype)s]: " +
throw((_("Row") + " # %(idx)s [%(doctype)s]: " +
_("to be included in Item's rate, it is required that: ") +
" [" + _("Row") + " # %(row_range)s] " + _("also be included in Item's rate")) % {
"idx": tax.idx,
@@ -200,12 +199,12 @@ class AccountsController(TransactionBase):
parentfield=self.other_fname),
"charge_type": tax.charge_type,
"row_range": row_range
}, raise_exception=True)
})
if cint(tax.included_in_print_rate):
if tax.charge_type == "Actual":
# inclusive tax cannot be of type Actual
msgprint((_("Row")
throw((_("Row")
+ " # %(idx)s [%(doctype)s]: %(charge_type_label)s = \"%(charge_type)s\" "
+ "cannot be included in Item's rate") % {
"idx": tax.idx,
@@ -213,7 +212,7 @@ class AccountsController(TransactionBase):
"charge_type_label": self.meta.get_label("charge_type",
parentfield=self.other_fname),
"charge_type": tax.charge_type,
}, raise_exception=True)
})
elif tax.charge_type == "On Previous Row Amount" and \
not cint(self.tax_doclist[tax.row_id - 1].included_in_print_rate):
# referred row should also be inclusive
@@ -224,20 +223,22 @@ class AccountsController(TransactionBase):
_on_previous_row_error("1 - %d" % (tax.row_id,))
def calculate_taxes(self):
for item in self.item_doclist:
# maintain actual tax rate based on idx
actual_tax_dict = dict([[tax.idx, tax.rate] for tax in self.tax_doclist
if tax.charge_type == "Actual"])
for n, item in enumerate(self.item_doclist):
item_tax_map = self._load_item_tax_rate(item.item_tax_rate)
for i, tax in enumerate(self.tax_doclist):
# tax_amount represents the amount of tax for the current step
current_tax_amount = self.get_current_tax_amount(item, tax, item_tax_map)
# case when net total is 0 but there is an actual type charge
# in this case add the actual amount to tax.tax_amount
# and tax.grand_total_for_current_item for the first such iteration
if tax.charge_type=="Actual" and \
not (current_tax_amount or self.doc.net_total or tax.tax_amount):
zero_net_total_adjustment = flt(tax.rate, self.precision("tax_amount", tax))
current_tax_amount += zero_net_total_adjustment
# Adjust divisional loss to the last item
if tax.charge_type == "Actual":
actual_tax_dict[tax.idx] -= current_tax_amount
if n == len(self.item_doclist) - 1:
current_tax_amount += actual_tax_dict[tax.idx]
# store tax_amount for current item as it will be used for
# charge type = 'On Previous Row Amount'
@@ -249,7 +250,8 @@ class AccountsController(TransactionBase):
if tax.category:
# if just for valuation, do not add the tax amount in total
# hence, setting it as 0 for further steps
current_tax_amount = 0.0 if (tax.category == "Valuation") else current_tax_amount
current_tax_amount = 0.0 if (tax.category == "Valuation") \
else current_tax_amount
current_tax_amount *= -1.0 if (tax.add_deduct_tax == "Deduct") else 1.0
@@ -268,6 +270,11 @@ class AccountsController(TransactionBase):
# in tax.total, accumulate grand total of each item
tax.total += tax.grand_total_for_current_item
# set precision in the last item iteration
if n == len(self.item_doclist) - 1:
tax.total = flt(tax.total, self.precision("total", tax))
tax.tax_amount = flt(tax.tax_amount, self.precision("tax_amount", tax))
def get_current_tax_amount(self, item, tax, item_tax_map):
tax_rate = self._get_tax_rate(tax, item_tax_map)
current_tax_amount = 0.0

View File

@@ -175,23 +175,31 @@ class BuyingController(StockController):
stock_items = self.get_stock_items()
stock_items_qty, stock_items_amount = 0, 0
last_stock_item_idx = 1
for d in self.doclist.get({"parentfield": parentfield}):
if d.item_code and d.item_code in stock_items:
stock_items_qty += flt(d.qty)
stock_items_amount += flt(d.amount)
last_stock_item_idx = d.idx
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}):
valuation_amount_adjustment = total_valuation_amount
for i, item in enumerate(self.doclist.get({"parentfield": parentfield})):
if item.item_code and item.qty and item.item_code in stock_items:
item_proportion = flt(item.amount) / stock_items_amount if stock_items_amount \
else flt(item.qty) / stock_items_qty
item.item_tax_amount = flt(item_proportion * total_valuation_amount,
self.precision("item_tax_amount", item))
if i == (last_stock_item_idx - 1):
item.item_tax_amount = flt(valuation_amount_adjustment,
self.precision("item_tax_amount", item))
else:
item.item_tax_amount = flt(item_proportion * total_valuation_amount,
self.precision("item_tax_amount", item))
valuation_amount_adjustment -= item.item_tax_amount
self.round_floats_in(item)

View File

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

View File

@@ -59,8 +59,8 @@ def get_columns(salary_slips):
def get_salary_slips(filters):
conditions, filters = get_conditions(filters)
salary_slips = webnotes.conn.sql("""select * from `tabSalary Slip` where docstatus = 1 %s""" %
conditions, filters, as_dict=1)
salary_slips = webnotes.conn.sql("""select * from `tabSalary Slip` where docstatus = 1 %s
order by employee, month""" % conditions, filters, as_dict=1)
if not salary_slips:
msgprint(_("No salary slip found for month: ") + cstr(filters.get("month")) +

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
@@ -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-2.7"):
try:
exec_in_shell("which pip2.7")
except subprocess.CalledProcessError:
exec_in_shell("easy_install-2.7 pip")
exec_in_shell("pip-2.7 install --upgrade pip")
exec_in_shell("pip-2.7 install --upgrade setuptools")
exec_in_shell("pip-2.7 install --upgrade virtualenv")
exec_in_shell("pip-2.7 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
@@ -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

@@ -35,6 +35,7 @@ class TestProductionOrder(unittest.TestCase):
stock_entry.doc.fg_completed_qty = 4
stock_entry.doc.posting_date = "2013-05-12"
stock_entry.doc.fiscal_year = "_Test Fiscal Year 2013"
stock_entry.run_method("get_items")
stock_entry.submit()
@@ -52,6 +53,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.fiscal_year = "_Test Fiscal Year 2013"
stock_entry.doc.fg_completed_qty = 15
stock_entry.run_method("get_items")
stock_entry.insert()

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

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

View File

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

@@ -263,4 +263,6 @@ patch_list = [
"patches.1311.p08_email_digest_recipients",
"execute:webnotes.delete_doc('DocType', 'Warehouse Type')",
"patches.1312.p02_update_item_details_in_item_price",
"patches.1401.p01_move_related_property_setters_to_custom_field",
"patches.1401.p01_make_buying_selling_as_check_box_in_price_list",
]

View File

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

View File

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

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

View File

@@ -3,8 +3,8 @@
from __future__ import unicode_literals
import webnotes
from webnotes import msgprint, _
from webnotes.utils import flt, cint, comma_and
from webnotes import _, throw
from webnotes.utils import flt, cint
import json
def get_customer_list(doctype, txt, searchfield, start, page_len, filters):
@@ -100,7 +100,7 @@ def _get_item_code(barcode=None, serial_no=None):
where name=%s""", serial_no)
if not item_code:
msgprint(_("No Item found with ") + input_type + ": %s" % (barcode or serial_no), raise_exception=True)
throw(_("No Item found with ") + input_type + ": %s" % (barcode or serial_no))
return item_code[0]
@@ -111,22 +111,26 @@ def _validate_item_details(args, item):
# validate if sales item or service item
if args.order_type == "Maintenance":
if item.is_service_item != "Yes":
msgprint(_("Item") + (" %s: " % item.name) +
throw(_("Item") + (" %s: " % item.name) +
_("not a service item.") +
_("Please select a service item or change the order type to Sales."),
raise_exception=True)
_("Please select a service item or change the order type to Sales."))
elif item.is_sales_item != "Yes":
msgprint(_("Item") + (" %s: " % item.name) + _("not a sales item"),
raise_exception=True)
throw(_("Item") + (" %s: " % item.name) + _("not a sales item"))
def _get_basic_details(args, item_bean, warehouse_fieldname):
item = item_bean.doc
from webnotes.defaults import get_user_default_as_list
user_default_warehouse_list = get_user_default_as_list('warehouse')
user_default_warehouse = user_default_warehouse_list[0] \
if len(user_default_warehouse_list)==1 else ""
out = webnotes._dict({
"item_code": item.name,
"description": item.description_html or item.description,
warehouse_fieldname: item.default_warehouse or args.get(warehouse_fieldname),
warehouse_fieldname: user_default_warehouse or item.default_warehouse \
or args.get(warehouse_fieldname),
"income_account": item.default_income_account or args.income_account \
or webnotes.conn.get_value("Company", args.company, "default_income_account"),
"expense_account": item.purchase_account or args.expense_account \
@@ -147,7 +151,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

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

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"]
},
{

View File

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

View File

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

View File

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

@@ -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, modified=NOW() 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

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

@@ -2,11 +2,12 @@
{
"creation": "2013-01-10 16:34:30",
"docstatus": 0,
"modified": "2013-11-02 16:59:22",
"modified": "2014-01-14 15:56:22",
"modified_by": "Administrator",
"owner": "harshada@webnotestech.com"
},
{
"allow_import": 1,
"autoname": "naming_series:",
"doctype": "DocType",
"icon": "icon-bug",

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