Merged with 4.0-wip

This commit is contained in:
Nabin Hait 2014-01-28 15:52:25 +05:30
commit 21d324c597
195 changed files with 2109 additions and 1272 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-30 12:49:46",
"docstatus": 0,
"modified": "2013-12-20 19:23:54",
"modified": "2014-01-20 17:48:20",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -28,6 +28,7 @@
},
{
"amend": 0,
"cancel": 0,
"doctype": "DocPerm",
"name": "__common__",
"parent": "Account",
@ -254,8 +255,8 @@
"read_only": 1
},
{
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"permlevel": 0,
@ -264,8 +265,8 @@
"write": 1
},
{
"cancel": 0,
"create": 0,
"delete": 0,
"doctype": "DocPerm",
"email": 1,
"permlevel": 0,
@ -274,8 +275,8 @@
"write": 0
},
{
"cancel": 0,
"create": 0,
"delete": 0,
"doctype": "DocPerm",
"email": 1,
"permlevel": 0,
@ -284,8 +285,8 @@
"write": 0
},
{
"cancel": 0,
"create": 0,
"delete": 0,
"doctype": "DocPerm",
"email": 1,
"permlevel": 0,
@ -294,16 +295,16 @@
"write": 0
},
{
"cancel": 0,
"create": 0,
"delete": 0,
"doctype": "DocPerm",
"permlevel": 2,
"role": "Auditor",
"write": 0
},
{
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"export": 0,
@ -315,16 +316,16 @@
"write": 1
},
{
"cancel": 0,
"create": 0,
"delete": 0,
"doctype": "DocPerm",
"permlevel": 2,
"role": "Accounts Manager",
"write": 1
},
{
"cancel": 0,
"create": 0,
"delete": 0,
"doctype": "DocPerm",
"permlevel": 2,
"role": "Accounts User",

View File

@ -6,6 +6,7 @@
from __future__ import unicode_literals
import webnotes
from webnotes import _
from webnotes.utils import cint
class DocType:
def __init__(self, d, dl):
@ -14,7 +15,12 @@ class DocType:
def on_update(self):
webnotes.conn.set_default("auto_accounting_for_stock", self.doc.auto_accounting_for_stock)
if self.doc.auto_accounting_for_stock:
if cint(self.doc.auto_accounting_for_stock):
# set default perpetual account in company
for company in webnotes.conn.sql("select name from tabCompany"):
webnotes.bean("Company", company[0]).save()
# Create account head for warehouses
warehouse_list = webnotes.conn.sql("select name, company from tabWarehouse", as_dict=1)
warehouse_with_no_company = [d.name for d in warehouse_list if not d.company]
if warehouse_with_no_company:

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-10 16:34:05",
"docstatus": 0,
"modified": "2013-12-20 19:23:58",
"modified": "2014-01-20 17:48:27",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -24,6 +24,7 @@
"permlevel": 0
},
{
"cancel": 0,
"doctype": "DocPerm",
"name": "__common__",
"parent": "Budget Distribution",
@ -79,8 +80,8 @@
},
{
"amend": 0,
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"permlevel": 0,
@ -88,6 +89,7 @@
"write": 1
},
{
"delete": 0,
"doctype": "DocPerm",
"permlevel": 2
}

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-23 19:57:17",
"docstatus": 0,
"modified": "2013-12-20 19:24:00",
"modified": "2014-01-20 17:48:30",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -30,6 +30,7 @@
},
{
"amend": 0,
"cancel": 0,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",
@ -185,15 +186,15 @@
"report_hide": 1
},
{
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"role": "Accounts Manager",
"write": 1
},
{
"cancel": 0,
"create": 0,
"delete": 0,
"doctype": "DocPerm",
"role": "Accounts User",
"write": 0

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-22 16:50:25",
"docstatus": 0,
"modified": "2013-12-20 19:24:08",
"modified": "2014-01-20 17:48:46",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -81,8 +81,9 @@
"reqd": 0
},
{
"cancel": 1,
"cancel": 0,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"report": 1,
"role": "System Manager",
@ -90,6 +91,7 @@
"write": 1
},
{
"delete": 0,
"doctype": "DocPerm",
"role": "All"
}

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 who can create / modify entries against this account"))
elif frozen_accounts_modifier not in webnotes.user.get_roles():

View File

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

View File

@ -2,7 +2,7 @@
{
"creation": "2013-03-25 10:53:52",
"docstatus": 0,
"modified": "2013-12-20 19:24:11",
"modified": "2014-01-20 17:48:51",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -474,6 +474,7 @@
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"role": "Accounts User",
"submit": 1,
@ -483,6 +484,7 @@
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"role": "Accounts Manager",
"submit": 1,
@ -492,6 +494,7 @@
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"doctype": "DocPerm",
"role": "Auditor",
"submit": 0,

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

@ -2,7 +2,7 @@
{
"creation": "2013-01-10 16:34:07",
"docstatus": 0,
"modified": "2013-12-20 19:24:15",
"modified": "2014-01-20 17:48:59",
"modified_by": "Administrator",
"owner": "jai@webnotestech.com"
},
@ -27,6 +27,7 @@
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",

View File

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

View File

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

View File

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

View File

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

View File

@ -2,7 +2,7 @@
{
"creation": "2013-05-21 16:16:39",
"docstatus": 0,
"modified": "2013-12-20 19:24:18",
"modified": "2014-01-20 17:49:04",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -771,6 +771,7 @@
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"doctype": "DocPerm",
"role": "Accounts User",
"submit": 0,
@ -780,6 +781,7 @@
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"doctype": "DocPerm",
"role": "Purchase User",
"submit": 0,
@ -789,6 +791,7 @@
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"doctype": "DocPerm",
"role": "Supplier",
"submit": 0,
@ -798,6 +801,7 @@
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"role": "Accounts Manager",
"submit": 1,
@ -807,6 +811,7 @@
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"doctype": "DocPerm",
"role": "Auditor",
"submit": 0,

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-10 16:34:08",
"docstatus": 0,
"modified": "2013-12-20 19:24:24",
"modified": "2014-01-20 17:49:14",
"modified_by": "Administrator",
"owner": "wasim@webnotestech.com"
},
@ -25,6 +25,7 @@
"permlevel": 0
},
{
"cancel": 0,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",
@ -78,15 +79,15 @@
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"doctype": "DocPerm",
"role": "Purchase Manager",
"write": 0
},
{
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"role": "Purchase Master Manager",
"write": 1

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>\
@ -30,12 +32,14 @@ erpnext.POS = Class.extend({
</div>\
<br>\
<div class="totals-area" style="margin-left: 40%;">\
<table class="table table-condensed">\
<tr>\
<td><b>Net Total</b></td>\
<td style="text-align: right;" class="net-total"></td>\
</tr>\
</table>\
<div class="net-total-area">\
<table class="table table-condensed">\
<tr>\
<td><b>Net Total</b></td>\
<td style="text-align: right;" class="net-total"></td>\
</tr>\
</table>\
</div>\
<div class="tax-table" style="display: none;">\
<table class="table table-condensed">\
<thead>\
@ -48,6 +52,18 @@ erpnext.POS = Class.extend({
</tbody>\
</table>\
</div>\
<div class="discount-amount-area">\
<table class="table table-condensed">\
<tr>\
<td style="vertical-align: middle;" width="50%"><b>Discount Amount</b></td>\
<td width="20%"></td>\
<td style="text-align: right;">\
<input type="text" class="form-control discount-amount" \
style="text-align: right;">\
</td>\
</tr>\
</table>\
</div>\
<div class="grand-total-area">\
<table class="table table-condensed">\
<tr>\
@ -60,10 +76,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 +104,11 @@ erpnext.POS = Class.extend({
me.refresh();
});
this.call_function("delete-items", function() {me.remove_selected_item();});
this.wrapper.find('input.discount-amount').on("change", function() {
wn.model.set_value(me.frm.doctype, me.frm.docname, "discount_amount", this.value);
});
this.call_function("remove-items", function() {me.remove_selected_items();});
this.call_function("make-payment", function() {me.make_payment();});
},
check_transaction_type: function() {
@ -101,6 +127,7 @@ erpnext.POS = Class.extend({
this.party = party;
this.price_list = (party == "Customer" ?
this.frm.doc.selling_price_list : this.frm.doc.buying_price_list);
this.price_list_field = (party == "Customer" ? "selling_price_list" : "buying_price_list");
this.sales_or_purchase = (party == "Customer" ? "Sales" : "Purchase");
this.net_total = "net_total_" + export_or_import;
this.grand_total = "grand_total_" + export_or_import;
@ -112,9 +139,9 @@ erpnext.POS = Class.extend({
},
make: function() {
this.make_party();
this.make_item_group();
this.make_search();
this.make_barcode();
this.make_search();
this.make_item_group();
this.make_item_list();
},
make_party: function() {
@ -137,23 +164,23 @@ erpnext.POS = Class.extend({
me.party.toLowerCase(), this.value);
});
},
make_item_group: function() {
make_barcode: function() {
var me = this;
this.item_group = wn.ui.form.make_control({
this.barcode = wn.ui.form.make_control({
df: {
"fieldtype": "Link",
"options": "Item Group",
"label": "Item Group",
"fieldname": "pos_item_group",
"placeholder": "Item Group"
"fieldtype": "Data",
"label": "Barcode",
"fieldname": "pos_barcode",
"placeholder": "Barcode / Serial No"
},
parent: this.wrapper.find(".item-group-area"),
parent: this.wrapper.find(".barcode-area"),
only_input: true,
});
this.item_group.make_input();
this.item_group.$input.on("change", function() {
if(!me.item_group.autocomplete_open)
me.make_item_list();
this.barcode.make_input();
this.barcode.$input.on("keypress", function() {
if(me.barcode_timeout)
clearTimeout(me.barcode_timeout);
me.barcode_timeout = setTimeout(function() { me.add_item_thru_barcode(); }, 1000);
});
},
make_search: function() {
@ -176,23 +203,23 @@ erpnext.POS = Class.extend({
me.item_timeout = setTimeout(function() { me.make_item_list(); }, 1000);
});
},
make_barcode: function() {
make_item_group: function() {
var me = this;
this.barcode = wn.ui.form.make_control({
this.item_group = wn.ui.form.make_control({
df: {
"fieldtype": "Data",
"label": "Barcode",
"fieldname": "pos_barcode",
"placeholder": "Barcode / Serial No"
"fieldtype": "Link",
"options": "Item Group",
"label": "Item Group",
"fieldname": "pos_item_group",
"placeholder": "Item Group"
},
parent: this.wrapper.find(".barcode-area"),
parent: this.wrapper.find(".item-group-area"),
only_input: true,
});
this.barcode.make_input();
this.barcode.$input.on("keypress", function() {
if(me.barcode_timeout)
clearTimeout(me.barcode_timeout);
me.barcode_timeout = setTimeout(function() { me.add_item_thru_barcode(); }, 1000);
this.item_group.make_input();
this.item_group.$input.on("change", function() {
if(!me.item_group.autocomplete_open)
me.make_item_list();
});
},
make_item_list: function() {
@ -261,22 +288,17 @@ erpnext.POS = Class.extend({
this.frm.cscript.fname, this.frm.doctype), function(i, d) {
if (d.item_code == item_code) {
caught = true;
if (serial_no) {
d.serial_no += '\n' + serial_no;
me.frm.script_manager.trigger("serial_no", d.doctype, d.name);
}
else {
d.qty += 1;
me.frm.script_manager.trigger("qty", d.doctype, d.name);
}
if (serial_no)
wn.model.set_value(d.doctype, d.name, "serial_no", d.serial_no + '\n' + serial_no);
else
wn.model.set_value(d.doctype, d.name, "qty", d.qty + 1);
}
});
}
// if item not found then add new item
if (!caught) {
if (!caught)
this.add_new_item_to_grid(item_code, serial_no);
}
this.refresh();
this.refresh_search_box();
@ -311,16 +333,18 @@ erpnext.POS = Class.extend({
wn.model.clear_doc(d.doctype, d.name);
me.refresh_grid();
} else {
d.qty = qty;
me.frm.script_manager.trigger("qty", d.doctype, d.name);
wn.model.set_value(d.doctype, d.name, "qty", qty);
}
}
});
me.refresh();
this.refresh();
},
refresh: function() {
var me = this;
this.refresh_item_list();
this.party_field.set_input(this.frm.doc[this.party.toLowerCase()]);
this.wrapper.find('input.discount-amount').val(this.frm.doc.discount_amount);
this.barcode.set_input("");
this.show_items_in_item_cart();
@ -333,7 +357,7 @@ erpnext.POS = Class.extend({
}
this.disable_text_box_and_button();
this.make_payment_button();
this.hide_payment_button();
// If quotation to is not Customer then remove party
if (this.frm.doctype == "Quotation") {
@ -342,6 +366,14 @@ erpnext.POS = Class.extend({
this.make_party();
}
},
refresh_item_list: function() {
var me = this;
// refresh item list on change of price list
if (this.frm.doc[this.price_list_field] != this.price_list) {
this.price_list = this.frm.doc[this.price_list_field];
this.make_item_list();
}
},
show_items_in_item_cart: function() {
var me = this;
var $items = this.wrapper.find("#cart tbody").empty();
@ -351,8 +383,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 +406,31 @@ erpnext.POS = Class.extend({
}
)).appendTo($items);
});
this.wrapper.find("input.qty").on("focus", function() {
$(this).select();
});
},
show_taxes: function() {
var me = this;
var taxes = wn.model.get_children(this.sales_or_purchase + " Taxes and Charges",
this.frm.doc.name, this.frm.cscript.other_fname, this.frm.doctype);
$(this.wrapper).find(".tax-table")
.toggle((taxes && taxes.length &&
flt(me.frm.doc.other_charges_total_export ||
me.frm.doc.other_charges_added_import) != 0.0) ? true : false)
.toggle((taxes && taxes.length) ? true : false)
.find("tbody").empty();
$.each(taxes, function(i, d) {
$(repl('<tr>\
<td>%(description)s %(rate)s</td>\
<td style="text-align: right;">%(tax_amount)s</td>\
<tr>', {
description: d.description,
rate: ((d.charge_type == "Actual") ? '' : ("(" + d.rate + "%)")),
tax_amount: format_currency(flt(d.tax_amount)/flt(me.frm.doc.conversion_rate),
me.frm.doc.currency)
})).appendTo(".tax-table tbody");
if (d.tax_amount) {
$(repl('<tr>\
<td>%(description)s %(rate)s</td>\
<td style="text-align: right;">%(tax_amount)s</td>\
<tr>', {
description: d.description,
rate: ((d.charge_type == "Actual") ? '' : ("(" + d.rate + "%)")),
tax_amount: format_currency(flt(d.tax_amount)/flt(me.frm.doc.conversion_rate),
me.frm.doc.currency)
})).appendTo(".tax-table tbody");
}
});
},
set_totals: function() {
@ -399,10 +445,16 @@ erpnext.POS = Class.extend({
// append quantity to the respective item after change from input box
$(this.wrapper).find("input.qty").on("change", function() {
var item_code = $(this).closest("tr")[0].id;
var item_code = $(this).closest("tr").attr("id");
me.update_qty(item_code, $(this).val());
});
// increase/decrease qty on plus/minus button
$(this.wrapper).find(".increase-qty, .decrease-qty").on("click", function() {
var tr = $(this).closest("tr");
me.increase_decrease_qty(tr, $(this).attr("class"));
});
// on td click toggle the highlighting of row
$(this.wrapper).find("#cart tbody tr td").on("click", function() {
var row = $(this).closest("tr");
@ -420,6 +472,15 @@ erpnext.POS = Class.extend({
me.refresh_delete_btn();
this.barcode.$input.focus();
},
increase_decrease_qty: function(tr, operation) {
var item_code = tr.attr("id");
var item_qty = cint(tr.find("input.qty").val());
if (operation == "increase-qty")
this.update_qty(item_code, item_qty + 1);
else if (operation == "decrease-qty" && item_qty != 1)
this.update_qty(item_code, item_qty - 1);
},
disable_text_box_and_button: function() {
var me = this;
// if form is submitted & cancelled then disable all input box & buttons
@ -427,7 +488,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 +498,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 +527,7 @@ erpnext.POS = Class.extend({
}
});
},
remove_selected_item: function() {
remove_selected_items: function() {
var me = this;
var selected_items = [];
var no_of_items = $(this.wrapper).find("#cart tbody tr").length;
@ -487,9 +548,11 @@ erpnext.POS = Class.extend({
}
}
});
this.refresh_grid();
},
refresh_grid: function() {
this.frm.dirty();
this.frm.fields_dict[this.frm.cscript.fname].grid.refresh();
this.frm.script_manager.trigger("calculate_taxes_and_totals");
this.refresh();

View File

@ -25,7 +25,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
}
// toggle to pos view if is_pos is 1 in user_defaults
if ((cint(wn.defaults.get_user_defaults("is_pos"))===1 || cur_frm.doc.is_pos)) {
if ((cint(wn.defaults.get_user_defaults("is_pos"))===1 || this.frm.doc.is_pos)) {
if(this.frm.doc.__islocal && !this.frm.doc.amended_from && !this.frm.doc.customer) {
this.frm.set_value("is_pos", 1);
this.is_pos(function() {
@ -54,7 +54,8 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
"voucher_no": doc.name,
"from_date": doc.posting_date,
"to_date": doc.posting_date,
"company": doc.company
"company": doc.company,
group_by_voucher: 0
};
wn.set_route("query-report", "General Ledger");
}, "icon-table");
@ -145,8 +146,8 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
me.set_default_values();
me.set_dynamic_labels();
me.calculate_taxes_and_totals();
if(callback_fn) callback_fn()
if(callback_fn) callback_fn();
}
}
});
@ -253,8 +254,8 @@ cur_frm.cscript.hide_fields = function(doc) {
cur_frm.cscript.mode_of_payment = function(doc) {
return cur_frm.call({
method: "get_bank_cash_account",
args: { mode_of_payment: doc.mode_of_payment }
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.get_bank_cash_account",
args: { mode_of_payment: doc.mode_of_payment },
});
}
@ -267,9 +268,6 @@ cur_frm.cscript.is_opening = function(doc, dt, dn) {
if (doc.is_opening == 'Yes') unhide_field('aging_date');
}
//Make Delivery Note Button
//-----------------------------
cur_frm.cscript['Make Delivery Note'] = function() {
wn.model.open_mapped_doc({
method: "erpnext.accounts.doctype.sales_invoice.sales_invoice.make_delivery_note",
@ -347,7 +345,7 @@ cur_frm.fields_dict['project_name'].get_query = function(doc, cdt, cdn) {
// --------------------------------
cur_frm.set_query("income_account", "entries", function(doc) {
return{
query: "accounts.doctype.sales_invoice.sales_invoice.get_income_account",
query: "erpnext.accounts.doctype.sales_invoice.sales_invoice.get_income_account",
filters: {'company': doc.company}
}
});

View File

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

View File

@ -2,7 +2,7 @@
{
"creation": "2013-05-24 19:29:05",
"docstatus": 0,
"modified": "2013-12-20 19:24:29",
"modified": "2014-01-20 17:49:20",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -455,6 +455,14 @@
"print_hide": 1,
"read_only": 1
},
{
"doctype": "DocField",
"fieldname": "discount_amount",
"fieldtype": "Currency",
"label": "Discount Amount",
"options": "Company:company:default_currency",
"print_hide": 0
},
{
"doctype": "DocField",
"fieldname": "totals",
@ -1094,7 +1102,7 @@
"fieldtype": "Select",
"label": "Recurring Type",
"no_copy": 1,
"options": "Monthly\nQuarterly\nHalf-yearly\nYearly",
"options": "\nMonthly\nQuarterly\nHalf-yearly\nYearly",
"print_hide": 1,
"read_only": 0
},
@ -1206,6 +1214,7 @@
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"role": "Accounts Manager",
"submit": 1,
@ -1215,12 +1224,14 @@
"amend": 1,
"cancel": 0,
"create": 1,
"delete": 0,
"doctype": "DocPerm",
"role": "Accounts User",
"submit": 1,
"write": 1
},
{
"delete": 0,
"doctype": "DocPerm",
"role": "Customer"
}

View File

@ -44,7 +44,6 @@ class TestSalesInvoice(unittest.TestCase):
def test_sales_invoice_calculation_base_currency(self):
si = webnotes.bean(copy=test_records[2])
si.run_method("calculate_taxes_and_totals")
si.insert()
expected_values = {
@ -136,7 +135,114 @@ class TestSalesInvoice(unittest.TestCase):
self.assertEquals(si.doc.grand_total, 1627.05)
self.assertEquals(si.doc.grand_total_export, 32.54)
def test_sales_invoice_discount_amount(self):
si = webnotes.bean(copy=test_records[3])
si.doc.discount_amount = 104.95
si.doclist.append({
"doctype": "Sales Taxes and Charges",
"parentfield": "other_charges",
"charge_type": "On Previous Row Amount",
"account_head": "_Test Account Service Tax - _TC",
"cost_center": "_Test Cost Center - _TC",
"description": "Service Tax",
"rate": 10,
"row_id": 8,
"idx": 9
})
si.insert()
expected_values = {
"keys": ["ref_rate", "adj_rate", "export_rate", "export_amount",
"base_ref_rate", "basic_rate", "amount"],
"_Test Item Home Desktop 100": [62.5, 0, 62.5, 625.0, 50, 50, 465.37],
"_Test Item Home Desktop 200": [190.66, 0, 190.66, 953.3, 150, 150, 698.08],
}
# check if children are saved
self.assertEquals(len(si.doclist.get({"parentfield": "entries"})),
len(expected_values)-1)
# check if item values are calculated
for d in si.doclist.get({"parentfield": "entries"}):
for i, k in enumerate(expected_values["keys"]):
self.assertEquals(d.fields.get(k), expected_values[d.item_code][i])
# check net total
self.assertEquals(si.doc.net_total, 1163.45)
self.assertEquals(si.doc.net_total_export, 1578.3)
# check tax calculation
expected_values = {
"keys": ["tax_amount", "tax_amount_after_discount_amount", "total"],
"_Test Account Excise Duty - _TC": [140, 130.31, 1293.76],
"_Test Account Education Cess - _TC": [2.8, 2.61, 1296.37],
"_Test Account S&H Education Cess - _TC": [1.4, 1.31, 1297.68],
"_Test Account CST - _TC": [27.88, 25.96, 1323.64],
"_Test Account VAT - _TC": [156.25, 145.43, 1469.07],
"_Test Account Customs Duty - _TC": [125, 116.35, 1585.42],
"_Test Account Shipping Charges - _TC": [100, 100, 1685.42],
"_Test Account Discount - _TC": [-180.33, -168.54, 1516.88],
"_Test Account Service Tax - _TC": [-18.03, -16.88, 1500]
}
for d in si.doclist.get({"parentfield": "other_charges"}):
for i, k in enumerate(expected_values["keys"]):
self.assertEquals(d.fields.get(k), expected_values[d.account_head][i])
self.assertEquals(si.doc.grand_total, 1500)
self.assertEquals(si.doc.grand_total_export, 1500)
def test_discount_amount_gl_entry(self):
si = webnotes.bean(copy=test_records[3])
si.doc.discount_amount = 104.95
si.doclist.append({
"doctype": "Sales Taxes and Charges",
"parentfield": "other_charges",
"charge_type": "On Previous Row Amount",
"account_head": "_Test Account Service Tax - _TC",
"cost_center": "_Test Cost Center - _TC",
"description": "Service Tax",
"rate": 10,
"row_id": 8,
"idx": 9
})
si.insert()
si.submit()
gl_entries = webnotes.conn.sql("""select account, debit, credit
from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
order by account asc""", si.doc.name, as_dict=1)
self.assertTrue(gl_entries)
expected_values = sorted([
[si.doc.debit_to, 1500, 0.0],
[test_records[3][1]["income_account"], 0.0, 1163.45],
[test_records[3][3]["account_head"], 0.0, 130.31],
[test_records[3][4]["account_head"], 0.0, 2.61],
[test_records[3][5]["account_head"], 0.0, 1.31],
[test_records[3][6]["account_head"], 0.0, 25.96],
[test_records[3][7]["account_head"], 0.0, 145.43],
[test_records[3][8]["account_head"], 0.0, 116.35],
[test_records[3][9]["account_head"], 0.0, 100],
[test_records[3][10]["account_head"], 168.54, 0.0],
["_Test Account Service Tax - _TC", 16.88, 0.0],
])
for i, gle in enumerate(gl_entries):
self.assertEquals(expected_values[i][0], gle.account)
self.assertEquals(expected_values[i][1], gle.debit)
self.assertEquals(expected_values[i][2], gle.credit)
# cancel
si.cancel()
gle = webnotes.conn.sql("""select * from `tabGL Entry`
where voucher_type='Sales Invoice' and voucher_no=%s""", si.doc.name)
self.assertFalse(gle)
def test_inclusive_rate_validations(self):
si = webnotes.bean(copy=test_records[2])
for i, tax in enumerate(si.doclist.get({"parentfield": "other_charges"})):
@ -148,16 +254,15 @@ class TestSalesInvoice(unittest.TestCase):
si.doclist[i].included_in_print_rate = 1
# tax type "Actual" cannot be inclusive
self.assertRaises(webnotes.ValidationError, si.run_method, "calculate_taxes_and_totals")
self.assertRaises(webnotes.ValidationError, si.insert)
# taxes above included type 'On Previous Row Total' should also be included
si.doclist[3].included_in_print_rate = 0
self.assertRaises(webnotes.ValidationError, si.run_method, "calculate_taxes_and_totals")
self.assertRaises(webnotes.ValidationError, si.insert)
def test_sales_invoice_calculation_base_currency_with_tax_inclusive_price(self):
# prepare
si = webnotes.bean(copy=test_records[3])
si.run_method("calculate_taxes_and_totals")
si.insert()
expected_values = {
@ -195,7 +300,7 @@ class TestSalesInvoice(unittest.TestCase):
for d in si.doclist.get({"parentfield": "other_charges"}):
for i, k in enumerate(expected_values["keys"]):
self.assertEquals(flt(d.fields.get(k), 6), expected_values[d.account_head][i])
self.assertEquals(d.fields.get(k), expected_values[d.account_head][i])
self.assertEquals(si.doc.grand_total, 1622.98)
self.assertEquals(si.doc.grand_total_export, 1622.98)
@ -211,7 +316,6 @@ class TestSalesInvoice(unittest.TestCase):
si.doclist[2].adj_rate = 20
si.doclist[9].rate = 5000
si.run_method("calculate_taxes_and_totals")
si.insert()
expected_values = {
@ -249,7 +353,7 @@ class TestSalesInvoice(unittest.TestCase):
for d in si.doclist.get({"parentfield": "other_charges"}):
for i, k in enumerate(expected_values["keys"]):
self.assertEquals(flt(d.fields.get(k), 6), expected_values[d.account_head][i])
self.assertEquals(d.fields.get(k), expected_values[d.account_head][i])
self.assertEquals(si.doc.grand_total, 65205.16)
self.assertEquals(si.doc.grand_total_export, 1304.1)
@ -403,7 +507,6 @@ class TestSalesInvoice(unittest.TestCase):
pr = webnotes.bean(copy=pr_test_records[0])
pr.doc.naming_series = "_T-Purchase Receipt-"
pr.doclist[1].warehouse = "_Test Warehouse No Account - _TC"
pr.run_method("calculate_taxes_and_totals")
pr.insert()
pr.submit()
@ -448,7 +551,7 @@ class TestSalesInvoice(unittest.TestCase):
self.assertFalse(gle)
set_perpetual_inventory(0)
def test_sales_invoice_gl_entry_with_aii_no_item_code(self):
def test_sales_invoice_gl_entry_with_aii_no_item_code(self):
self.clear_stock_account_balance()
set_perpetual_inventory()
@ -508,7 +611,6 @@ class TestSalesInvoice(unittest.TestCase):
as pr_test_records
pr = webnotes.bean(copy=pr_test_records[0])
pr.doc.naming_series = "_T-Purchase Receipt-"
pr.run_method("calculate_taxes_and_totals")
pr.insert()
pr.submit()
@ -565,16 +667,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 erpnext.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

@ -2,7 +2,7 @@
{
"creation": "2013-04-24 11:39:32",
"docstatus": 0,
"modified": "2013-12-31 17:51:47",
"modified": "2014-01-03 15:04:25",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -132,12 +132,21 @@
"report_hide": 1,
"width": "150px"
},
{
"doctype": "DocField",
"fieldname": "tax_amount_after_discount_amount",
"fieldtype": "Currency",
"hidden": 1,
"label": "Tax Amount After Discount Amount",
"options": "Company:company:default_currency",
"read_only": 1
},
{
"doctype": "DocField",
"fieldname": "item_wise_tax_detail",
"fieldtype": "Small Text",
"hidden": 1,
"label": "Item Wise Tax Detail ",
"label": "Item Wise Tax Detail",
"oldfieldname": "item_wise_tax_detail",
"oldfieldtype": "Small Text",
"read_only": 1

View File

@ -19,6 +19,10 @@ cur_frm.pformat.net_total_export = function(doc) {
return '';
}
cur_frm.pformat.discount_amount = function(doc) {
return '';
}
cur_frm.pformat.grand_total_export = function(doc) {
return '';
}
@ -33,10 +37,10 @@ cur_frm.pformat.in_words_export = function(doc) {
cur_frm.pformat.other_charges= function(doc){
//function to make row of table
var make_row = function(title,val,bold){
var make_row = function(title, val, bold){
var bstart = '<b>'; var bend = '</b>';
return '<tr><td style="width:50%;">'+(bold?bstart:'')+title+(bold?bend:'')+'</td>'
+'<td style="width:50%;text-align:right;">'+format_currency(val, doc.currency)+'</td>'
return '<tr><td style="width:50%;">' + (bold?bstart:'') + title + (bold?bend:'') + '</td>'
+'<td style="width:50%;text-align:right;">' + format_currency(val, doc.currency) + '</td>'
+'</tr>'
}
@ -52,7 +56,7 @@ cur_frm.pformat.other_charges= function(doc){
out ='';
if (!doc.print_without_amount) {
var cl = getchildren('Sales Taxes and Charges',doc.name,'other_charges');
var cl = getchildren('Sales Taxes and Charges', doc.name, 'other_charges');
// outer table
var out='<div><table class="noborder" style="width:100%"><tr><td style="width: 60%"></td><td>';
@ -60,6 +64,7 @@ cur_frm.pformat.other_charges= function(doc){
// main table
out +='<table class="noborder" style="width:100%">';
if(!print_hide('net_total_export')) {
out += make_row('Net Total', doc.net_total_export, 1);
}
@ -68,26 +73,31 @@ cur_frm.pformat.other_charges= function(doc){
if(cl.length){
for(var i=0;i<cl.length;i++){
if(convert_rate(cl[i].tax_amount)!=0 && !cl[i].included_in_print_rate)
out += make_row(cl[i].description,convert_rate(cl[i].tax_amount),0);
out += make_row(cl[i].description, convert_rate(cl[i].tax_amount), 0);
}
}
// Discount Amount
if(!print_hide('discount_amount') && doc.discount_amount) {
out += make_row('Discount Amount', convert_rate(doc.discount_amount), 0);
}
// grand total
if(!print_hide('grand_total_export')) {
out += make_row('Grand Total',doc.grand_total_export,1);
out += make_row('Grand Total', doc.grand_total_export, 1);
}
if(!print_hide('rounded_total_export')) {
out += make_row('Rounded Total',doc.rounded_total_export,1);
out += make_row('Rounded Total', doc.rounded_total_export, 1);
}
if(doc.in_words_export && !print_hide('in_words_export')){
out +='</table></td></tr>';
out += '<tr><td colspan = "2">';
out += '<table><tr><td style="width:25%;"><b>In Words</b></td>'
out+= '<td style="width:50%;">'+doc.in_words_export+'</td></tr>'
out += '<td style="width:50%;">' + doc.in_words_export + '</td></tr>'
}
out +='</table></td></tr></table></div>';
out += '</table></td></tr></table></div>';
}
return out;
}
@ -99,7 +109,7 @@ cur_frm.cscript.charge_type = function(doc, cdt, cdn) {
d.charge_type = '';
}
validated = false;
refresh_field('charge_type',d.name,'other_charges');
refresh_field('charge_type', d.name, 'other_charges');
cur_frm.cscript.row_id(doc, cdt, cdn);
cur_frm.cscript.rate(doc, cdt, cdn);
cur_frm.cscript.tax_amount(doc, cdt, cdn);
@ -122,7 +132,7 @@ cur_frm.cscript.row_id = function(doc, cdt, cdn) {
}
}
validated = false;
refresh_field('row_id',d.name,'other_charges');
refresh_field('row_id', d.name, 'other_charges');
}
/*---------------------- Get rate if account_head has account_type as TAX or CHARGEABLE-------------------------------------*/
@ -152,7 +162,7 @@ cur_frm.cscript.rate = function(doc, cdt, cdn) {
d.rate = '';
}
validated = false;
refresh_field('rate',d.name,'other_charges');
refresh_field('rate', d.name, 'other_charges');
}
cur_frm.cscript.tax_amount = function(doc, cdt, cdn) {
@ -166,5 +176,5 @@ cur_frm.cscript.tax_amount = function(doc, cdt, cdn) {
d.tax_amount = '';
}
validated = false;
refresh_field('tax_amount',d.name,'other_charges');
refresh_field('tax_amount', d.name, 'other_charges');
};

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-10 16:34:09",
"docstatus": 0,
"modified": "2013-12-20 19:24:34",
"modified": "2014-01-20 17:49:25",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -26,6 +26,7 @@
},
{
"amend": 0,
"cancel": 0,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",
@ -101,22 +102,22 @@
"reqd": 1
},
{
"cancel": 0,
"create": 0,
"delete": 0,
"doctype": "DocPerm",
"role": "Sales User",
"write": 0
},
{
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"role": "Accounts Manager",
"write": 1
},
{
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"role": "Sales Master Manager",
"write": 1

View File

@ -2,7 +2,7 @@
{
"creation": "2013-06-25 11:48:03",
"docstatus": 0,
"modified": "2013-12-20 19:24:35",
"modified": "2014-01-20 17:49:27",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -133,16 +133,19 @@
"reqd": 1
},
{
"delete": 0,
"doctype": "DocPerm",
"role": "Accounts User"
},
{
"delete": 0,
"doctype": "DocPerm",
"role": "Sales User"
},
{
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"role": "Accounts Manager",
"write": 1
@ -150,6 +153,7 @@
{
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"role": "Sales Master Manager",
"write": 1

View File

@ -9,18 +9,20 @@ from erpnext.accounts.report.accounts_receivable.accounts_receivable import get_
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()
voucher_detail_map = get_voucher_details()
# Age of the invoice on this date
age_on = getdate(filters.get("report_date")) > getdate(nowdate()) \
and nowdate() or filters.get("report_date")
@ -37,9 +39,7 @@ def execute(filters=None):
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),
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]
@ -50,21 +50,38 @@ def execute(filters=None):
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 = []
@ -101,10 +118,10 @@ 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_voucher_details():

View File

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

View File

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

View File

@ -3,13 +3,14 @@
from __future__ import unicode_literals
import webnotes
from webnotes import _, msgprint
from webnotes.utils import flt
def execute(filters=None):
if not filters: filters = {}
columns = get_columns()
debit_or_credit = webnotes.conn.get_value("Account", filters["account"], "debit_or_credit")
columns = get_columns()
data = get_entries(filters)
from erpnext.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

@ -34,7 +34,7 @@ def validate_filters(filters, account_details):
def get_columns():
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"]
"Against Account::120", "Cost Center:Link/Cost Center:100", "Remarks::400"]
def get_result(filters, account_details):
gl_entries = get_gl_entries(filters)
@ -51,7 +51,7 @@ def get_gl_entries(filters):
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
voucher_type, voucher_no, cost_center, remarks, is_opening, against
from `tabGL Entry`
where company=%(company)s {conditions}
{group_by_condition}
@ -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 ""
@ -133,10 +138,10 @@ def get_accountwise_gle(filters, gl_entries, gle_map):
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"):
or cstr(gle.is_opening) == "Yes"):
gle_map[gle.account].opening += amount
opening += amount
elif gle.posting_date < filters.to_date:
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)

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

@ -79,7 +79,7 @@ def get_columns(invoice_list):
tax_accounts = webnotes.conn.sql_list("""select distinct account_head
from `tabSales Taxes and Charges` where parenttype = 'Sales Invoice'
and docstatus = 1 and ifnull(tax_amount, 0) != 0
and docstatus = 1 and ifnull(tax_amount_after_discount_amount, 0) != 0
and parent in (%s) order by account_head""" %
', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]))
@ -126,7 +126,8 @@ def get_invoice_income_map(invoice_list):
return invoice_income_map
def get_invoice_tax_map(invoice_list, invoice_income_map, income_accounts):
tax_details = webnotes.conn.sql("""select parent, account_head, sum(tax_amount) as tax_amount
tax_details = webnotes.conn.sql("""select parent, account_head,
sum(tax_amount_after_discount_amount) as tax_amount
from `tabSales Taxes and Charges` where parent in (%s) group by parent, account_head""" %
', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)

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

View File

@ -22,7 +22,7 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
if(this.frm.fields_dict.buying_price_list) {
this.frm.set_query("buying_price_list", function() {
return{
filters: { 'buying_or_selling': "Buying" }
filters: { 'buying': 1 }
}
});
}
@ -302,11 +302,11 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
calculate_totals: function() {
var tax_count = this.frm.tax_doclist.length;
this.frm.doc.grand_total = flt(
tax_count ? this.frm.tax_doclist[tax_count - 1].total : this.frm.doc.net_total,
this.frm.doc.grand_total = flt(tax_count ?
this.frm.tax_doclist[tax_count - 1].total : this.frm.doc.net_total,
precision("grand_total"));
this.frm.doc.grand_total_import = flt(this.frm.doc.grand_total / this.frm.doc.conversion_rate,
precision("grand_total_import"));
this.frm.doc.grand_total_import = flt(this.frm.doc.grand_total /
this.frm.doc.conversion_rate, precision("grand_total_import"));
this.frm.doc.total_tax = flt(this.frm.doc.grand_total - this.frm.doc.net_total,
precision("total_tax"));
@ -321,20 +321,26 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
}
// other charges added/deducted
this.frm.doc.other_charges_added = 0.0
this.frm.doc.other_charges_deducted = 0.0
if(tax_count) {
this.frm.doc.other_charges_added = wn.utils.sum($.map(this.frm.tax_doclist,
function(tax) { return (tax.add_deduct_tax == "Add" && in_list(["Valuation and Total", "Total"], tax.category)) ? tax.tax_amount : 0.0; }));
function(tax) { return (tax.add_deduct_tax == "Add"
&& in_list(["Valuation and Total", "Total"], tax.category)) ?
tax.tax_amount : 0.0; }));
this.frm.doc.other_charges_deducted = wn.utils.sum($.map(this.frm.tax_doclist,
function(tax) { return (tax.add_deduct_tax == "Deduct" && in_list(["Valuation and Total", "Total"], tax.category)) ? tax.tax_amount : 0.0; }));
function(tax) { return (tax.add_deduct_tax == "Deduct"
&& in_list(["Valuation and Total", "Total"], tax.category)) ?
tax.tax_amount : 0.0; }));
wn.model.round_floats_in(this.frm.doc, ["other_charges_added", "other_charges_deducted"]);
this.frm.doc.other_charges_added_import = flt(this.frm.doc.other_charges_added / this.frm.doc.conversion_rate,
precision("other_charges_added_import"));
this.frm.doc.other_charges_deducted_import = flt(this.frm.doc.other_charges_deducted / this.frm.doc.conversion_rate,
precision("other_charges_deducted_import"));
wn.model.round_floats_in(this.frm.doc,
["other_charges_added", "other_charges_deducted"]);
}
this.frm.doc.other_charges_added_import = flt(this.frm.doc.other_charges_added /
this.frm.doc.conversion_rate, precision("other_charges_added_import"));
this.frm.doc.other_charges_deducted_import = flt(this.frm.doc.other_charges_deducted /
this.frm.doc.conversion_rate, precision("other_charges_deducted_import"));
},
_cleanup: function() {
@ -360,6 +366,14 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({
});
}
}
if(this.frm.tax_doclist.length) {
if(!wn.meta.get_docfield(this.frm.tax_doclist[0].doctype, "tax_amount_after_discount_amount", this.frm.doctype)) {
$.each(this.frm.tax_doclist, function(i, tax) {
delete tax["tax_amount_after_discount_amount"];
});
}
}
},
calculate_outstanding_amount: function() {

View File

@ -2,7 +2,7 @@
{
"creation": "2013-05-21 16:16:39",
"docstatus": 0,
"modified": "2013-12-20 19:24:20",
"modified": "2014-01-20 17:49:08",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -672,6 +672,7 @@
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"doctype": "DocPerm",
"role": "Material User",
"submit": 0,
@ -681,6 +682,7 @@
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"role": "Purchase Manager",
"submit": 1,
@ -690,12 +692,14 @@
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"role": "Purchase User",
"submit": 1,
"write": 1
},
{
"delete": 0,
"doctype": "DocPerm",
"role": "Supplier"
}

View File

@ -1,7 +1,6 @@
# 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 unittest
import webnotes
@ -22,7 +21,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 +51,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 +65,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()
@ -74,7 +74,7 @@ class TestPurchaseOrder(unittest.TestCase):
self.assertEquals(flt(webnotes.conn.get_value("Bin", {"item_code": "_Test Item",
"warehouse": "_Test Warehouse - _TC"}, "ordered_qty")), 0.0)
def test_make_purchase_invocie(self):
def test_make_purchase_invoice(self):
from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_invoice
po = webnotes.bean(copy=test_records[0]).insert()
@ -88,7 +88,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

@ -2,7 +2,7 @@
{
"creation": "2013-04-30 13:13:03",
"docstatus": 0,
"modified": "2013-12-20 19:24:24",
"modified": "2014-01-20 17:49:14",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -27,6 +27,7 @@
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",

View File

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

View File

@ -214,7 +214,4 @@ def get_supplier_details(supplier):
out.currency = supplier.default_currency
out.buying_price_list = supplier.default_price_list
return out
return out

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-10 16:34:11",
"docstatus": 0,
"modified": "2013-12-20 19:24:36",
"modified": "2014-01-20 17:49:29",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -28,6 +28,7 @@
},
{
"amend": 0,
"cancel": 0,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",
@ -210,15 +211,15 @@
"print_hide": 1
},
{
"cancel": 0,
"create": 0,
"delete": 0,
"doctype": "DocPerm",
"role": "Purchase Manager",
"write": 0
},
{
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"role": "Purchase Master Manager",
"write": 1

View File

@ -2,7 +2,7 @@
{
"creation": "2013-05-21 16:16:45",
"docstatus": 0,
"modified": "2013-12-20 19:24:36",
"modified": "2014-01-20 17:49:29",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -598,6 +598,7 @@
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"role": "Manufacturing Manager",
"submit": 1,
@ -607,6 +608,7 @@
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"role": "Purchase Manager",
"submit": 1,
@ -616,6 +618,7 @@
"amend": 1,
"cancel": 0,
"create": 1,
"delete": 0,
"doctype": "DocPerm",
"role": "Purchase User",
"submit": 0,
@ -625,6 +628,7 @@
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"doctype": "DocPerm",
"role": "Material User",
"submit": 0,
@ -634,6 +638,7 @@
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"doctype": "DocPerm",
"role": "Supplier",
"submit": 0,

View File

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

View File

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

View File

@ -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 erpnext.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 erpnext.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"):
@ -133,6 +132,13 @@ class AccountsController(TransactionBase):
self.doclist.append(tax)
def calculate_taxes_and_totals(self):
self.discount_amount_applied = False
self._calculate_taxes_and_totals()
if self.meta.get_field("discount_amount"):
self.apply_discount_amount()
def _calculate_taxes_and_totals(self):
# validate conversion rate
company_currency = get_company_currency(self.doc.company)
if not self.doc.currency or self.doc.currency == company_currency:
@ -141,7 +147,7 @@ class AccountsController(TransactionBase):
else:
validate_conversion_rate(self.doc.currency, self.doc.conversion_rate,
self.meta.get_label("conversion_rate"), self.doc.company)
self.doc.conversion_rate = flt(self.doc.conversion_rate)
self.item_doclist = self.doclist.get({"parentfield": self.fname})
self.tax_doclist = self.doclist.get({"parentfield": self.other_fname})
@ -157,17 +163,19 @@ class AccountsController(TransactionBase):
self.calculate_totals()
self._cleanup()
# TODO
# print format: show net_total_export instead of net_total
def initialize_taxes(self):
for tax in self.tax_doclist:
tax.item_wise_tax_detail = {}
for fieldname in ["tax_amount", "total",
"tax_amount_for_current_item", "grand_total_for_current_item",
"tax_fraction_for_current_item", "grand_total_fraction_for_current_item"]:
tax.fields[fieldname] = 0.0
tax_fields = ["total", "tax_amount_after_discount_amount",
"tax_amount_for_current_item", "grand_total_for_current_item",
"tax_fraction_for_current_item", "grand_total_fraction_for_current_item"]
if not self.discount_amount_applied:
tax_fields.append("tax_amount")
for fieldname in tax_fields:
tax.fields[fieldname] = 0.0
self.validate_on_previous_row(tax)
self.validate_inclusive_tax(tax)
self.round_floats_in(tax)
@ -179,17 +187,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 +208,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,46 +221,49 @@ 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):
not cint(self.tax_doclist[cint(tax.row_id) - 1].included_in_print_rate):
# referred row should also be inclusive
_on_previous_row_error(tax.row_id)
elif tax.charge_type == "On Previous Row Total" and \
not all([cint(t.included_in_print_rate) for t in self.tax_doclist[:tax.row_id - 1]]):
not all([cint(t.included_in_print_rate) for t in self.tax_doclist[:cint(tax.row_id) - 1]]):
# all rows about the reffered tax should be inclusive
_on_previous_row_error("1 - %d" % (tax.row_id,))
def calculate_taxes(self):
for item in self.item_doclist:
# maintain actual tax rate based on idx
actual_tax_dict = dict([[tax.idx, tax.rate] for tax in self.tax_doclist
if tax.charge_type == "Actual"])
for n, item in enumerate(self.item_doclist):
item_tax_map = self._load_item_tax_rate(item.item_tax_rate)
for i, tax in enumerate(self.tax_doclist):
# tax_amount represents the amount of tax for the current step
current_tax_amount = self.get_current_tax_amount(item, tax, item_tax_map)
if hasattr(self, "set_item_tax_amount"):
self.set_item_tax_amount(item, tax, current_tax_amount)
# case when net total is 0 but there is an actual type charge
# in this case add the actual amount to tax.tax_amount
# and tax.grand_total_for_current_item for the first such iteration
if tax.charge_type=="Actual" and \
not (current_tax_amount or self.doc.net_total or tax.tax_amount):
zero_net_total_adjustment = flt(tax.rate, self.precision("tax_amount", tax))
current_tax_amount += zero_net_total_adjustment
# Adjust divisional loss to the last item
if tax.charge_type == "Actual":
actual_tax_dict[tax.idx] -= current_tax_amount
if n == len(self.item_doclist) - 1:
current_tax_amount += actual_tax_dict[tax.idx]
# store tax_amount for current item as it will be used for
# charge type = 'On Previous Row Amount'
tax.tax_amount_for_current_item = current_tax_amount
# accumulate tax amount into tax.tax_amount
tax.tax_amount += current_tax_amount
if not self.discount_amount_applied:
tax.tax_amount += current_tax_amount
tax.tax_amount_after_discount_amount += current_tax_amount
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
@ -260,17 +271,36 @@ class AccountsController(TransactionBase):
# note: grand_total_for_current_item contains the contribution of
# item's amount, previously applied tax and the current tax on that item
if i==0:
tax.grand_total_for_current_item = flt(item.amount +
current_tax_amount, self.precision("total", tax))
tax.grand_total_for_current_item = flt(item.amount + current_tax_amount,
self.precision("total", tax))
else:
tax.grand_total_for_current_item = \
flt(self.tax_doclist[i-1].grand_total_for_current_item +
flt(self.tax_doclist[i-1].grand_total_for_current_item +
current_tax_amount, self.precision("total", tax))
# 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:
self.round_off_totals(tax)
# adjust Discount Amount loss in last tax iteration
if i == (len(self.tax_doclist) - 1) and self.discount_amount_applied:
self.adjust_discount_amount_loss(tax)
def round_off_totals(self, tax):
tax.total = flt(tax.total, self.precision("total", tax))
tax.tax_amount = flt(tax.tax_amount, self.precision("tax_amount", tax))
tax.tax_amount_after_discount_amount = flt(tax.tax_amount_after_discount_amount,
self.precision("tax_amount", tax))
def adjust_discount_amount_loss(self, tax):
discount_amount_loss = self.doc.grand_total - flt(self.doc.discount_amount) - tax.total
tax.tax_amount_after_discount_amount = flt(tax.tax_amount_after_discount_amount +
discount_amount_loss, self.precision("tax_amount", tax))
tax.total = flt(tax.total + discount_amount_loss, self.precision("total", tax))
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
@ -289,9 +319,9 @@ class AccountsController(TransactionBase):
elif tax.charge_type == "On Previous Row Total":
current_tax_amount = (tax_rate / 100.0) * \
self.tax_doclist[cint(tax.row_id) - 1].grand_total_for_current_item
current_tax_amount = flt(current_tax_amount, self.precision("tax_amount", tax))
# store tax breakup for each item
key = item.item_code or item.item_name
if tax.item_wise_tax_detail.get(key):
@ -384,24 +414,45 @@ class AccountsController(TransactionBase):
})
def validate_multiple_billing(self, ref_dt, item_ref_dn, based_on, parentfield):
from erpnext.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 erpnext.accounts.utils import get_company_default
return get_company_default(self.doc.company, fieldname)

View File

@ -5,7 +5,6 @@ from __future__ import unicode_literals
import webnotes
from webnotes import _, msgprint
from webnotes.utils import flt, _round
from erpnext.buying.utils import get_item_details
from erpnext.setup.utils import get_company_currency
@ -122,8 +121,8 @@ class BuyingController(StockController):
self.round_floats_in(self.doc, ["net_total", "net_total_import"])
def calculate_totals(self):
self.doc.grand_total = flt(self.tax_doclist and \
self.tax_doclist[-1].total or self.doc.net_total, self.precision("grand_total"))
self.doc.grand_total = flt(self.tax_doclist[-1].total if self.tax_doclist
else self.doc.net_total, self.precision("grand_total"))
self.doc.grand_total_import = flt(self.doc.grand_total / self.doc.conversion_rate,
self.precision("grand_total_import"))
@ -135,6 +134,24 @@ class BuyingController(StockController):
if self.meta.get_field("rounded_total_import"):
self.doc.rounded_total_import = _round(self.doc.grand_total_import)
if self.meta.get_field("other_charges_added"):
self.doc.other_charges_added = flt(sum([flt(d.tax_amount) for d in self.tax_doclist
if d.add_deduct_tax=="Add" and d.category in ["Valuation and Total", "Total"]]),
self.precision("other_charges_added"))
if self.meta.get_field("other_charges_deducted"):
self.doc.other_charges_deducted = flt(sum([flt(d.tax_amount) for d in self.tax_doclist
if d.add_deduct_tax=="Deduct" and d.category in ["Valuation and Total", "Total"]]),
self.precision("other_charges_deducted"))
if self.meta.get_field("other_charges_added_import"):
self.doc.other_charges_added_import = flt(self.doc.other_charges_added /
self.doc.conversion_rate, self.precision("other_charges_added_import"))
if self.meta.get_field("other_charges_deducted_import"):
self.doc.other_charges_deducted_import = flt(self.doc.other_charges_deducted /
self.doc.conversion_rate, self.precision("other_charges_deducted_import"))
def calculate_outstanding_amount(self):
if self.doc.doctype == "Purchase Invoice" and self.doc.docstatus < 2:
@ -148,7 +165,7 @@ class BuyingController(StockController):
def _cleanup(self):
super(BuyingController, self)._cleanup()
# except in purchase invoice, rate field is purchase_rate
# except in purchase invoice, rate field is purchase_rate
# reset fieldname of rate
if self.doc.doctype != "Purchase Invoice":
df = self.meta.get_field("rate", parentfield=self.fname)
@ -162,29 +179,53 @@ class BuyingController(StockController):
for item in self.item_doclist:
del item.fields["item_tax_amount"]
def set_item_tax_amount(self, item, tax, current_tax_amount):
if not self.meta.get_field("tax_amount_after_discount_amount",
parentfield=self.other_fname):
for tax in self.tax_doclist:
del tax.fields["tax_amount_after_discount_amount"]
# update valuation rate
def update_valuation_rate(self, parentfield):
"""
item_tax_amount is the total tax amount applied on that item
stored for valuation
TODO: rename item_tax_amount to valuation_tax_amount
"""
if tax.category in ["Valuation", "Valuation and Total"] and \
self.meta.get_field("item_tax_amount", parentfield=self.fname):
item.item_tax_amount += flt(current_tax_amount, self.precision("item_tax_amount", item))
# update valuation rate
def update_valuation_rate(self, parentfield):
for item in self.doclist.get({"parentfield": parentfield}):
item.conversion_factor = item.conversion_factor or flt(webnotes.conn.get_value(
"UOM Conversion Detail", {"parent": item.item_code, "uom": item.uom},
"conversion_factor")) or 1
stock_items = self.get_stock_items()
stock_items_qty, stock_items_amount = 0, 0
last_stock_item_idx = 1
for d in self.doclist.get({"parentfield": parentfield}):
if d.item_code and d.item_code in stock_items:
stock_items_qty += flt(d.qty)
stock_items_amount += flt(d.amount)
last_stock_item_idx = d.idx
if item.item_code and item.qty:
total_valuation_amount = sum([flt(d.tax_amount) for d in
self.doclist.get({"parentfield": "purchase_tax_details"})
if d.category in ["Valuation", "Valuation and Total"]])
valuation_amount_adjustment = total_valuation_amount
for i, item in enumerate(self.doclist.get({"parentfield": parentfield})):
if item.item_code and item.qty and item.item_code in stock_items:
item_proportion = flt(item.amount) / stock_items_amount if stock_items_amount \
else flt(item.qty) / stock_items_qty
if i == (last_stock_item_idx - 1):
item.item_tax_amount = flt(valuation_amount_adjustment,
self.precision("item_tax_amount", item))
else:
item.item_tax_amount = flt(item_proportion * total_valuation_amount,
self.precision("item_tax_amount", item))
valuation_amount_adjustment -= item.item_tax_amount
self.round_floats_in(item)
# if no item code, which is sometimes the case in purchase invoice,
# then it is not possible to track valuation against it
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)

View File

@ -122,7 +122,7 @@ class SellingController(StockController):
cumulated_tax_fraction += tax.tax_fraction_for_current_item
if cumulated_tax_fraction:
if cumulated_tax_fraction and not self.discount_amount_applied:
item.amount = flt((item.export_amount * self.doc.conversion_rate) /
(1 + cumulated_tax_fraction), self.precision("amount", item))
@ -159,22 +159,23 @@ class SellingController(StockController):
return current_tax_fraction
def calculate_item_values(self):
for item in self.item_doclist:
self.round_floats_in(item)
if item.adj_rate == 100:
item.export_rate = 0
elif not item.export_rate:
item.export_rate = flt(item.ref_rate * (1.0 - (item.adj_rate / 100.0)),
self.precision("export_rate", item))
item.export_amount = flt(item.export_rate * item.qty,
self.precision("export_amount", item))
if not self.discount_amount_applied:
for item in self.item_doclist:
self.round_floats_in(item)
if item.adj_rate == 100:
item.export_rate = 0
elif not item.export_rate:
item.export_rate = flt(item.ref_rate * (1.0 - (item.adj_rate / 100.0)),
self.precision("export_rate", item))
item.export_amount = flt(item.export_rate * item.qty,
self.precision("export_amount", item))
self._set_in_company_currency(item, "ref_rate", "base_ref_rate")
self._set_in_company_currency(item, "export_rate", "basic_rate")
self._set_in_company_currency(item, "export_amount", "amount")
self._set_in_company_currency(item, "ref_rate", "base_ref_rate")
self._set_in_company_currency(item, "export_rate", "basic_rate")
self._set_in_company_currency(item, "export_amount", "amount")
def calculate_net_total(self):
self.doc.net_total = self.doc.net_total_export = 0.0
@ -192,12 +193,42 @@ class SellingController(StockController):
self.doc.other_charges_total = flt(self.doc.grand_total - self.doc.net_total,
self.precision("other_charges_total"))
self.doc.other_charges_total_export = flt(self.doc.grand_total_export - self.doc.net_total_export,
self.doc.other_charges_total_export = flt(self.doc.grand_total_export -
self.doc.net_total_export + flt(self.doc.discount_amount),
self.precision("other_charges_total_export"))
self.doc.rounded_total = _round(self.doc.grand_total)
self.doc.rounded_total_export = _round(self.doc.grand_total_export)
def apply_discount_amount(self):
if self.doc.discount_amount:
grand_total_for_discount_amount = self.get_grand_total_for_discount_amount()
if grand_total_for_discount_amount:
# calculate item amount after Discount Amount
for item in self.item_doclist:
distributed_amount = flt(self.doc.discount_amount) * item.amount / grand_total_for_discount_amount
item.amount = flt(item.amount - distributed_amount, self.precision("amount", item))
self.discount_amount_applied = True
self._calculate_taxes_and_totals()
def get_grand_total_for_discount_amount(self):
actual_taxes_dict = {}
for tax in self.tax_doclist:
if tax.charge_type == "Actual":
actual_taxes_dict.setdefault(tax.idx, tax.tax_amount)
elif tax.row_id in actual_taxes_dict:
actual_tax_amount = flt(actual_taxes_dict.get(tax.row_id, 0)) * \
flt(tax.rate) / 100
actual_taxes_dict.setdefault(tax.idx, actual_tax_amount)
grand_total_for_discount_amount = flt(self.doc.grand_total - sum(actual_taxes_dict.values()),
self.precision("grand_total"))
return grand_total_for_discount_amount
def calculate_outstanding_amount(self):
# NOTE:
# write_off_amount is only for POS Invoice

View File

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

View File

@ -46,17 +46,14 @@ standard_queries = Customer:erpnext.selling.utils.get_customer_list
scheduler_event = all:erpnext.support.doctype.support_ticket.get_support_mails.get_support_mails
scheduler_event = all:erpnext.hr.doctype.job_applicant.get_job_applications.get_job_applications
scheduler_event = all:erpnext.selling.doctype.lead.get_leads.get_leads
scheduler_event = all:webnotes.utils.email_lib.bulk.flush
#### Daily
scheduler_event = daily:webnotes.core.doctype.event.event.send_event_digest
scheduler_event = daily:webnotes.core.doctype.notification_count.notification_count.delete_event_notification_count
scheduler_event = daily:webnotes.utils.email_lib.bulk.clear_outbox
scheduler_event = daily:erpnext.accounts.doctype.sales_invoice.sales_invoice.manage_recurring_invoices
scheduler_event = daily:erpnext.setup.doctype.backup_manager.backup_manager.take_backups_daily
scheduler_event = daily:erpnext.stock.utils.reorder_item
scheduler_event = daily:erpnext.setup.doctype.email_digest.email_digest.send
scheduler_event = daily:support.doctype.support_ticket.support_ticket.auto_close_tickets
#### Weekly

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-10 16:34:12",
"docstatus": 0,
"modified": "2013-12-20 19:23:55",
"modified": "2014-01-22 16:05:34",
"modified_by": "Administrator",
"owner": "ashwini@webnotestech.com"
},
@ -230,14 +230,17 @@
"width": "150px"
},
{
"cancel": 0,
"delete": 0,
"doctype": "DocPerm",
"match": "owner",
"restricted": 1,
"role": "Employee",
"submit": 0
},
{
"amend": 1,
"cancel": 1,
"delete": 1,
"doctype": "DocPerm",
"role": "System Manager",
"submit": 1
@ -245,6 +248,7 @@
{
"amend": 1,
"cancel": 1,
"delete": 1,
"doctype": "DocPerm",
"role": "HR User",
"submit": 1

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-10 16:34:13",
"docstatus": 0,
"modified": "2013-12-20 19:23:55",
"modified": "2014-01-20 17:48:23",
"modified_by": "Administrator",
"owner": "ashwini@webnotestech.com"
},
@ -28,6 +28,7 @@
{
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-10 16:34:13",
"docstatus": 0,
"modified": "2013-12-20 19:23:57",
"modified": "2014-01-20 17:48:26",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -25,8 +25,9 @@
"permlevel": 0
},
{
"cancel": 1,
"cancel": 0,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-22 16:50:30",
"docstatus": 0,
"modified": "2013-12-20 19:24:02",
"modified": "2014-01-20 17:48:34",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -25,8 +25,9 @@
"permlevel": 0
},
{
"cancel": 1,
"cancel": 0,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",

View File

@ -2,7 +2,7 @@
{
"creation": "2013-02-05 11:48:26",
"docstatus": 0,
"modified": "2013-12-20 19:24:04",
"modified": "2014-01-20 17:48:38",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -24,8 +24,9 @@
"permlevel": 0
},
{
"cancel": 1,
"cancel": 0,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-10 16:34:13",
"docstatus": 0,
"modified": "2013-12-20 19:24:04",
"modified": "2014-01-20 17:48:38",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -25,8 +25,9 @@
"permlevel": 0
},
{
"cancel": 1,
"cancel": 0,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-24 11:03:32",
"docstatus": 0,
"modified": "2013-12-20 19:24:05",
"modified": "2014-01-20 17:48:38",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -25,8 +25,9 @@
"permlevel": 0
},
{
"cancel": 1,
"cancel": 0,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",

View File

@ -4,10 +4,10 @@
wn.provide("erpnext.hr");
erpnext.hr.EmployeeController = wn.ui.form.Controller.extend({
setup: function() {
this.frm.fields_dict.user_id.get_query = function(doc,cdt,cdn) {
return { query:"webnotes.core.doctype.profile.profile.profile_query"} }
this.frm.fields_dict.reports_to.get_query = function(doc,cdt,cdn) {
return{ query: "erpnext.controllers.queries.employee_query"} }
this.frm.fields_dict.user_id.get_query = function(doc, cdt, cdn) {
return { query:"webnotes.core.doctype.profile.profile.profile_query"} }
this.frm.fields_dict.reports_to.get_query = function(doc, cdt, cdn) {
return { query: "erpnext.controllers.queries.employee_query"} }
},
onload: function() {
@ -93,4 +93,4 @@ erpnext.hr.EmployeeController = wn.ui.form.Controller.extend({
});
},
});
cur_frm.cscript = new erpnext.hr.EmployeeController({frm: cur_frm});
cur_frm.cscript = new erpnext.hr.EmployeeController({frm: cur_frm});

View File

@ -2,7 +2,7 @@
{
"creation": "2013-03-07 09:04:18",
"docstatus": 0,
"modified": "2013-12-23 19:35:27",
"modified": "2014-01-20 17:48:40",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -28,6 +28,7 @@
},
{
"amend": 0,
"cancel": 0,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",
@ -750,23 +751,23 @@
"read_only": 1
},
{
"cancel": 0,
"create": 0,
"delete": 0,
"doctype": "DocPerm",
"role": "Employee",
"write": 0
},
{
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"restrict": 0,
"role": "HR User",
"write": 1
},
{
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"restrict": 1,
"role": "HR Manager",

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-10 16:34:14",
"docstatus": 0,
"modified": "2013-12-20 19:24:07",
"modified": "2014-01-20 17:48:43",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -24,8 +24,9 @@
"permlevel": 0
},
{
"cancel": 1,
"cancel": 0,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-10 16:34:14",
"docstatus": 0,
"modified": "2013-12-20 19:24:07",
"modified": "2014-01-22 16:05:34",
"modified_by": "Administrator",
"owner": "harshada@webnotestech.com"
},
@ -221,13 +221,15 @@
"width": "160px"
},
{
"delete": 0,
"doctype": "DocPerm",
"match": "owner",
"restricted": 1,
"role": "Employee"
},
{
"amend": 1,
"cancel": 1,
"delete": 1,
"doctype": "DocPerm",
"role": "Expense Approver",
"submit": 1
@ -235,6 +237,7 @@
{
"amend": 1,
"cancel": 1,
"delete": 1,
"doctype": "DocPerm",
"role": "HR User",
"submit": 1

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-10 16:34:14",
"docstatus": 0,
"modified": "2013-12-20 19:24:08",
"modified": "2014-01-20 17:48:46",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -30,8 +30,9 @@
"reqd": 1
},
{
"cancel": 1,
"cancel": 0,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",

View File

@ -8,9 +8,7 @@ from webnotes.utils import add_days, add_years, cint, getdate
from webnotes.model import db_exists
from webnotes.model.doc import addchild, make_autoname
from webnotes.model.bean import copy_doclist
from webnotes import msgprint
from webnotes import msgprint, throw, _
import datetime
class DocType:
@ -19,7 +17,7 @@ class DocType:
self.doclist = doclist
def autoname(self):
self.doc.name = make_autoname(self.doc.fiscal_year +"/"+ self.doc.holiday_list_name+"/.###")
self.doc.name = make_autoname(self.doc.fiscal_year + "/" + self.doc.holiday_list_name + "/.###")
def validate(self):
self.update_default_holiday_list()
@ -38,11 +36,9 @@ class DocType:
def validate_values(self):
if not self.doc.fiscal_year:
msgprint("Please select Fiscal Year")
raise Exception
throw(_("Please select Fiscal Year"))
if not self.doc.weekly_off:
msgprint("Please select weekly off day")
raise Exception
throw(_("Please select weekly off day"))
def get_fy_start_end_dates(self):
return webnotes.conn.sql("""select year_start_date, year_end_date

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-10 16:34:14",
"docstatus": 0,
"modified": "2013-12-20 19:24:08",
"modified": "2014-01-20 17:48:46",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -23,8 +23,9 @@
"permlevel": 0
},
{
"cancel": 1,
"cancel": 0,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-29 19:25:37",
"docstatus": 0,
"modified": "2013-12-20 19:24:10",
"modified": "2014-01-20 17:48:50",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -27,6 +27,7 @@
{
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-15 16:13:36",
"docstatus": 0,
"modified": "2013-12-20 19:24:11",
"modified": "2014-01-20 17:48:51",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -26,6 +26,7 @@
{
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",

View File

@ -2,7 +2,7 @@
{
"creation": "2013-02-20 19:10:38",
"docstatus": 0,
"modified": "2013-12-20 19:24:12",
"modified": "2014-01-22 16:05:35",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -28,6 +28,7 @@
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",
@ -170,7 +171,7 @@
},
{
"doctype": "DocPerm",
"match": "owner",
"restricted": 1,
"role": "HR User"
},
{

View File

@ -2,7 +2,7 @@
{
"creation": "2013-02-20 11:18:11",
"docstatus": 0,
"modified": "2013-12-23 19:53:41",
"modified": "2014-01-20 17:48:55",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -230,6 +230,7 @@
},
{
"create": 1,
"delete": 0,
"doctype": "DocPerm",
"email": 1,
"permlevel": 0,
@ -242,6 +243,7 @@
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"doctype": "DocPerm",
"permlevel": 1,
"role": "All",
@ -251,6 +253,7 @@
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"permlevel": 0,
@ -265,6 +268,7 @@
"amend": 1,
"cancel": 0,
"create": 0,
"delete": 0,
"doctype": "DocPerm",
"email": 1,
"permlevel": 0,
@ -278,6 +282,7 @@
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"doctype": "DocPerm",
"permlevel": 1,
"report": 1,
@ -289,6 +294,7 @@
"amend": 0,
"cancel": 0,
"create": 0,
"delete": 0,
"doctype": "DocPerm",
"permlevel": 1,
"report": 1,

View File

@ -2,7 +2,7 @@
{
"creation": "2013-02-21 09:55:58",
"docstatus": 0,
"modified": "2013-12-20 19:24:13",
"modified": "2014-01-20 17:48:56",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -24,8 +24,9 @@
"permlevel": 0
},
{
"cancel": 1,
"cancel": 0,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",

View File

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

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-10 16:34:15",
"docstatus": 0,
"modified": "2013-12-20 19:24:27",
"modified": "2014-01-20 17:49:18",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -390,12 +390,14 @@
},
{
"amend": 0,
"delete": 0,
"doctype": "DocPerm",
"role": "HR User"
},
{
"amend": 1,
"cancel": 1,
"delete": 1,
"doctype": "DocPerm",
"role": "HR Manager"
}

View File

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

View File

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

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-22 15:11:38",
"docstatus": 0,
"modified": "2013-12-20 19:23:57",
"modified": "2014-01-20 17:48:26",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -36,6 +36,7 @@
{
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-10 16:34:16",
"docstatus": 0,
"modified": "2013-12-20 19:24:16",
"modified": "2014-01-20 17:49:01",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -28,6 +28,7 @@
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",

View File

@ -35,6 +35,8 @@ class TestProductionOrder(unittest.TestCase):
stock_entry = webnotes.bean(stock_entry)
stock_entry.doc.fiscal_year = "_Test Fiscal Year 2013"
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()
@ -51,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")

View File

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

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-10 16:34:17",
"docstatus": 0,
"modified": "2013-12-20 19:24:41",
"modified": "2014-01-20 17:49:35",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -24,8 +24,9 @@
"permlevel": 0
},
{
"cancel": 1,
"cancel": 0,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",

View File

@ -1,3 +1,22 @@
erpnext.patches.1401.enable_all_price_list
erpnext.patches.4_0.update_user_properties
erpnext.patches.4_0.move_warehouse_user_to_restrictions
erpnext.patches.4_0.new_permissions
erpnext.patches.4_0.new_permissions
erpnext.patches.4_0.update_incharge_name_to_sales_person_in_maintenance_schedule
execute:webnotes.reload_doc('accounts', 'doctype', 'sales_invoice') # 2014-01-03
execute:webnotes.reload_doc('selling', 'doctype', 'sales_order') # 2014-01-03
execute:webnotes.reload_doc('selling', 'doctype', 'quotation') # 2014-01-03
execute:webnotes.reload_doc('stock', 'doctype', 'delivery_note') # 2014-01-03
execute:webnotes.reload_doc('accounts', 'Print Format', 'POS Invoice') # 2014-01-03
execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Classic') # 2014-01-03
execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Modern') # 2014-01-03
execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Spartan') # 2014-01-03
execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Classic') # 2014-01-03
execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Modern') # 2014-01-03
execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Spartan') # 2014-01-03
execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Classic') # 2014-01-03
execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Modern') # 2014-01-03
execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Spartan') # 2014-01-03
execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Classic') # 2014-01-03
execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Modern') # 2014-01-03
execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Spartan') # 2014-01-03

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,12 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import webnotes
def execute():
webnotes.reload_doc("support", "doctype", "maintenance_schedule_detail")
webnotes.reload_doc("support", "doctype", "maintenance_schedule_item")
webnotes.conn.sql("""update `tabMaintenance Schedule Detail` set sales_person=incharge_name""")
webnotes.conn.sql("""update `tabMaintenance Schedule Item` set sales_person=incharge_name""")

View File

@ -45,7 +45,11 @@ def update_user_match():
for profile in webnotes.conn.sql_list("""select name from `tabProfile`
where enabled=1 and user_type='System User'"""):
perms = webnotes.permissions.get_user_perms(meta, "read", profile)
user_roles = webnotes.get_roles(profile)
perms = meta.get({"doctype": "DocPerm", "permlevel": 0,
"role": ["in", [["All"] + user_roles]], "read": 1})
# user does not have required roles
if not perms:
continue

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

@ -172,18 +172,18 @@ patch_list = [
"patches.july_2013.p05_custom_doctypes_in_list_view",
"patches.july_2013.p06_same_sales_rate",
"patches.july_2013.p07_repost_billed_amt_in_sales_cycle",
"execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Classic') # 2013-07-22",
"execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Modern') # 2013-07-22",
"execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Spartan') # 2013-07-22",
"execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Classic') # 2013-07-22",
"execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Modern') # 2013-07-22",
"execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Spartan') # 2013-07-22",
"execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Classic') # 2013-07-22",
"execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Modern') # 2013-07-22",
"execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Spartan') # 2013-07-22",
"execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Classic') # 2013-07-22",
"execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Modern') # 2013-07-22",
"execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Spartan') # 2013-07-22",
"execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Classic') # 2013-12-26",
"execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Modern') # 2013-12-26",
"execute:webnotes.reload_doc('accounts', 'Print Format', 'Sales Invoice Spartan') # 2013-12-26",
"execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Classic') # 2013-12-26",
"execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Modern') # 2013-12-26",
"execute:webnotes.reload_doc('selling', 'Print Format', 'Quotation Spartan') # 2013-12-26",
"execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Classic') # 2013-12-26",
"execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Modern') # 2013-12-26",
"execute:webnotes.reload_doc('selling', 'Print Format', 'Sales Order Spartan') # 2013-12-26",
"execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Classic') # 2013-12-26",
"execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Modern') # 2013-12-26",
"execute:webnotes.reload_doc('stock', 'Print Format', 'Delivery Note Spartan') # 2013-12-26",
"patches.july_2013.p08_custom_print_format_net_total_export",
"patches.july_2013.p09_remove_website_pyc",
"patches.july_2013.p10_change_partner_user_to_website_user",
@ -262,4 +262,13 @@ patch_list = [
"execute:webnotes.delete_doc('DocType', 'Warehouse Type')",
"patches.1312.p01_delete_old_stock_reports",
"patches.1312.p02_update_item_details_in_item_price",
"patches.1401.p01_move_related_property_setters_to_custom_field",
"patches.1401.p01_make_buying_selling_as_check_box_in_price_list",
"patches.1401.update_billing_status_for_zero_value_order",
"execute:webnotes.reload_doc('accounts', 'Print Format', 'POS Invoice') # 2013-12-26",
"execute:webnotes.reload_doc('accounts', 'doctype', 'sales_invoice') # 2013-12-26",
"execute:webnotes.reload_doc('selling', 'doctype', 'sales_order') # 2013-12-26",
"execute:webnotes.reload_doc('selling', 'doctype', 'quotation') # 2013-12-26",
"execute:webnotes.reload_doc('stock', 'doctype', 'delivery_note') # 2013-12-26",
"patches.1401.enable_all_price_list",
]

View File

@ -2,7 +2,7 @@
{
"creation": "2013-03-07 11:55:07",
"docstatus": 0,
"modified": "2013-12-20 19:24:17",
"modified": "2014-01-20 17:49:02",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -28,6 +28,7 @@
},
{
"amend": 0,
"cancel": 0,
"doctype": "DocPerm",
"name": "__common__",
"parent": "Project",
@ -289,8 +290,8 @@
"search_index": 1
},
{
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"permlevel": 0,
@ -299,8 +300,8 @@
"write": 1
},
{
"cancel": 0,
"create": 0,
"delete": 0,
"doctype": "DocPerm",
"permlevel": 1,
"role": "All"

View File

@ -2,7 +2,7 @@
{
"creation": "2013-01-29 19:25:50",
"docstatus": 0,
"modified": "2013-12-20 19:24:38",
"modified": "2014-01-24 13:01:46",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -15,7 +15,9 @@
"icon": "icon-check",
"max_attachments": 5,
"module": "Projects",
"name": "__common__"
"name": "__common__",
"search_fields": "subject",
"title_field": "subject"
},
{
"doctype": "DocField",
@ -26,8 +28,9 @@
"permlevel": 0
},
{
"cancel": 1,
"cancel": 0,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",

View File

@ -2,7 +2,7 @@
{
"creation": "2013-04-03 16:38:41",
"docstatus": 0,
"modified": "2013-12-20 19:24:39",
"modified": "2014-01-22 16:05:35",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -28,6 +28,7 @@
{
"amend": 1,
"cancel": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",
@ -204,7 +205,7 @@
{
"create": 1,
"doctype": "DocPerm",
"match": "owner",
"restricted": 1,
"role": "Projects User"
},
{

View File

@ -2,7 +2,7 @@
{
"creation": "2013-02-28 17:57:33",
"docstatus": 0,
"modified": "2013-12-20 19:24:39",
"modified": "2014-01-20 17:49:34",
"modified_by": "Administrator",
"owner": "Administrator"
},
@ -28,6 +28,7 @@
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"doctype": "DocPerm",
"email": 1,
"name": "__common__",

View File

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

View File

@ -28,7 +28,8 @@ erpnext.stock.StockController = wn.ui.form.Controller.extend({
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
company: me.frm.doc.company,
group_by_voucher: false
};
wn.set_route("query-report", "General Ledger");
}, "icon-table");

View File

@ -1,15 +1,3 @@
h1, h2, h3, h4, h5 {
font-family: Arial, Helvetica, sans-serif;
}
body {
font-family: Arial, Helvetica, sans-serif;
}
span, div, td, input, textarea, button, select {
font-family: inherit;
}
.small {
font-size: 11.5px;
}

View File

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

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