Merge branch 'i18n' of git://github.com/bperretti/erpnext into bperretti-i18n
diff --git a/accounts/doctype/journal_voucher/journal_voucher.js b/accounts/doctype/journal_voucher/journal_voucher.js
index ae15f93..15fad3f 100644
--- a/accounts/doctype/journal_voucher/journal_voucher.js
+++ b/accounts/doctype/journal_voucher/journal_voucher.js
@@ -12,10 +12,13 @@
load_defaults: function() {
if(this.frm.doc.__islocal && this.frm.doc.company) {
wn.model.set_default_values(this.frm.doc);
- $.each(wn.model.get_doclist(this.frm.doc.doctype, this.frm.doc.name, {parentfield: "entries"}),
- function(i, jvd) { wn.model.set_default_values(jvd); });
+ $.each(wn.model.get_doclist(this.frm.doc.doctype,
+ this.frm.doc.name, {parentfield: "entries"}), function(i, jvd) {
+ wn.model.set_default_values(jvd);
+ }
+ );
- this.frm.doc.posting_date = get_today();
+ if(!this.frm.doc.amended_from) this.frm.doc.posting_date = get_today();
}
},
diff --git a/accounts/doctype/purchase_invoice/purchase_invoice.py b/accounts/doctype/purchase_invoice/purchase_invoice.py
index c65b9ac..ba6f5a4 100644
--- a/accounts/doctype/purchase_invoice/purchase_invoice.py
+++ b/accounts/doctype/purchase_invoice/purchase_invoice.py
@@ -293,20 +293,14 @@
reconcile_against_document(lst)
def on_submit(self):
- purchase_controller = webnotes.get_obj("Purchase Common")
- purchase_controller.is_item_table_empty(self)
-
self.check_prev_docstatus()
- # Check for Approving Authority
- get_obj('Authorization Control').validate_approving_authority(self.doc.doctype,self.doc.company, self.doc.grand_total)
-
+ get_obj('Authorization Control').validate_approving_authority(self.doc.doctype,
+ self.doc.company, self.doc.grand_total)
# this sequence because outstanding may get -negative
self.make_gl_entries()
-
self.update_against_document_in_jv()
-
self.update_prevdoc_status()
def make_gl_entries(self):
@@ -353,6 +347,7 @@
# 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):
@@ -361,9 +356,13 @@
# expense will be booked in sales invoice
stock_item_and_auto_accounting_for_stock = True
- valuation_amt = (flt(item.amount, self.precision("amount", item)) +
+ valuation_amt = flt(flt(item.valuation_rate) * flt(item.qty) * \
+ flt(item.conversion_factor), self.precision("valuation_rate", item))
+
+ rounding_diff += (flt(item.amount, self.precision("amount", item)) +
flt(item.item_tax_amount, self.precision("item_tax_amount", item)) +
- flt(item.rm_supp_cost, self.precision("rm_supp_cost", item)))
+ flt(item.rm_supp_cost, self.precision("rm_supp_cost", item)) -
+ valuation_amt)
gl_entries.append(
self.get_gl_dict({
@@ -392,6 +391,12 @@
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(
self.get_gl_dict({
diff --git a/accounts/doctype/sales_invoice/pos.js b/accounts/doctype/sales_invoice/pos.js
index c68b991..043fe90 100644
--- a/accounts/doctype/sales_invoice/pos.js
+++ b/accounts/doctype/sales_invoice/pos.js
@@ -167,7 +167,7 @@
"fieldtype": "Data",
"label": "Barcode",
"fieldname": "pos_barcode",
- "placeholder": "Barcode"
+ "placeholder": "Barcode / Serial No"
},
parent: this.wrapper.find(".barcode-area")
});
@@ -228,7 +228,7 @@
}
});
},
- add_to_cart: function(item_code) {
+ add_to_cart: function(item_code, serial_no) {
var me = this;
var caught = false;
@@ -239,39 +239,46 @@
if (no_of_items != 0) {
$.each(wn.model.get_children(this.frm.doctype + " Item", this.frm.doc.name,
this.frm.cscript.fname, this.frm.doctype), function(i, d) {
- if (d.item_code == item_code)
+ 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 duplicate row then append the qty
- if (caught) {
- me.update_qty(item_code, 1);
- }
- else {
+ // if item not found then add new item
+ if (!caught) {
var child = wn.model.add_child(me.frm.doc, this.frm.doctype + " Item",
this.frm.cscript.fname);
child.item_code = item_code;
- me.frm.cscript.item_code(me.frm.doc, child.doctype, child.name);
+
+ if (serial_no)
+ child.serial_no = serial_no;
+
+ me.frm.script_manager.trigger("item_code", child.doctype, child.name);
}
+ me.refresh();
},
- update_qty: function(item_code, qty, textbox_qty) {
+ update_qty: function(item_code, qty) {
var me = this;
$.each(wn.model.get_children(this.frm.doctype + " Item", this.frm.doc.name,
this.frm.cscript.fname, this.frm.doctype), function(i, d) {
if (d.item_code == item_code) {
- if (textbox_qty) {
- if (qty == 0 && d.item_code == item_code)
- wn.model.clear_doc(d.doctype, d.name);
+ if (qty == 0)
+ wn.model.clear_doc(d.doctype, d.name);
+ else {
d.qty = qty;
+ me.frm.script_manager.trigger("qty", d.doctype, d.name);
}
- else
- d.qty += 1;
-
- me.frm.cscript.qty(me.frm.doc, d.doctype, d.name);
}
});
- me.frm.dirty();
me.refresh();
},
refresh: function() {
@@ -352,7 +359,7 @@
// 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;
- me.update_qty(item_code, $(this).val(), true);
+ me.update_qty(item_code, $(this).val());
});
// on td click toggle the highlighting of row
@@ -407,11 +414,14 @@
var me = this;
me.barcode_timeout = null;
wn.call({
- method: 'accounts.doctype.sales_invoice.pos.get_item_from_barcode',
- args: {barcode: this.barcode.$input.val()},
+ method: 'accounts.doctype.sales_invoice.pos.get_item_code',
+ args: {barcode_serial_no: this.barcode.$input.val()},
callback: function(r) {
if (r.message) {
- me.add_to_cart(r.message[0].name);
+ if (r.message[1] == "serial_no")
+ me.add_to_cart(r.message[0][0].item_code, r.message[0][0].name);
+ else
+ me.add_to_cart(r.message[0][0].name);
}
else
msgprint(wn._("Invalid Barcode"));
@@ -443,7 +453,6 @@
});
this.frm.fields_dict[this.frm.cscript.fname].grid.refresh();
this.frm.script_manager.trigger("calculate_taxes_and_totals");
- me.frm.dirty();
me.refresh();
},
make_payment: function() {
diff --git a/accounts/doctype/sales_invoice/pos.py b/accounts/doctype/sales_invoice/pos.py
index 44fe40d..7bebbd2 100644
--- a/accounts/doctype/sales_invoice/pos.py
+++ b/accounts/doctype/sales_invoice/pos.py
@@ -20,25 +20,30 @@
condition += " and i.name='%s'" % item
return webnotes.conn.sql("""select i.name, i.item_name, i.image,
- pl_items.ref_rate, pl_items.currency
+ item_det.ref_rate, item_det.currency
from `tabItem` i LEFT JOIN
- (select ip.item_code, ip.ref_rate, pl.currency from
- `tabItem Price` ip, `tabPrice List` pl
- where ip.parent=%s and ip.parent = pl.name) pl_items
+ (select item_code, ref_rate, currency from
+ `tabItem Price` where price_list=%s) item_det
ON
- pl_items.item_code=i.name
+ item_det.item_code=i.name
where
%s""" % ('%s', condition), (price_list), as_dict=1)
@webnotes.whitelist()
-def get_item_from_barcode(barcode):
- return webnotes.conn.sql("""select name from `tabItem` where barcode=%s""",
- (barcode), as_dict=1)
+def get_item_code(barcode_serial_no):
+ input_via = "serial_no"
+ item_code = webnotes.conn.sql("""select name, item_code from `tabSerial No` where
+ name=%s""", (barcode_serial_no), as_dict=1)
-@webnotes.whitelist()
-def get_item_from_serial_no(serial_no):
- return webnotes.conn.sql("""select name, item_code from `tabSerial No` where
- name=%s""", (serial_no), as_dict=1)
+ if not item_code:
+ input_via = "barcode"
+ item_code = webnotes.conn.sql("""select name from `tabItem` where barcode=%s""",
+ (barcode_serial_no), as_dict=1)
+
+ if item_code:
+ return item_code, input_via
+ else:
+ webnotes.throw("Invalid Barcode / Serial No")
@webnotes.whitelist()
def get_mode_of_payment():
diff --git a/accounts/doctype/sales_invoice/sales_invoice.js b/accounts/doctype/sales_invoice/sales_invoice.js
index a926e31..9afa33d 100644
--- a/accounts/doctype/sales_invoice/sales_invoice.js
+++ b/accounts/doctype/sales_invoice/sales_invoice.js
@@ -11,28 +11,28 @@
wn.require('app/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js');
wn.require('app/utilities/doctype/sms_control/sms_control.js');
-wn.require('app/selling/doctype/sales_common/sales_common.js');
+wn.require('app/selling/sales_common.js');
wn.require('app/accounts/doctype/sales_invoice/pos.js');
wn.provide("erpnext.accounts");
erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.extend({
onload: function() {
this._super();
-
- if(!this.frm.doc.__islocal) {
+
+ if(!this.frm.doc.__islocal && !this.frm.doc.customer && this.frm.doc.debit_to) {
// show debit_to in print format
- if(!this.frm.doc.customer && this.frm.doc.debit_to) {
- this.frm.set_df_property("debit_to", "print_hide", 0);
- }
+ this.frm.set_df_property("debit_to", "print_hide", 0);
}
// 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) &&
- cint(wn.defaults.get_user_defaults("fs_pos_view"))===1) {
- if(this.frm.doc.__islocal && !this.frm.doc.amended_from) {
- this.frm.set_value("is_pos", 1);
- this.is_pos(function() {cur_frm.cscript.toggle_pos(true);});
- }
+ if ((cint(wn.defaults.get_user_defaults("is_pos"))===1 || cur_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() {
+ if (cint(wn.defaults.get_user_defaults("fs_pos_view"))===1)
+ cur_frm.cscript.toggle_pos(true);
+ });
+ }
}
// if document is POS then change default print format to "POS Invoice"
@@ -44,7 +44,7 @@
refresh: function(doc, dt, dn) {
this._super();
-
+
cur_frm.cscript.is_opening(doc, dt, dn);
cur_frm.dashboard.reset();
@@ -141,6 +141,10 @@
callback: function(r) {
if(!r.exc) {
me.frm.script_manager.trigger("update_stock");
+ me.set_default_values();
+ me.set_dynamic_labels();
+ me.calculate_taxes_and_totals();
+
if(callback_fn) callback_fn()
}
}
@@ -350,7 +354,7 @@
// warehouse in detail table
//----------------------------
-cur_frm.fields_dict['entries'].grid.get_field('warehouse').get_query= function(doc, cdt, cdn) {
+cur_frm.fields_dict['entries'].grid.get_field('warehouse').get_query = function(doc, cdt, cdn) {
var d = locals[cdt][cdn];
return{
filters:[
@@ -371,34 +375,16 @@
}
}
-cur_frm.cscript.income_account = function(doc, cdt, cdn){
+cur_frm.cscript.income_account = function(doc, cdt, cdn) {
cur_frm.cscript.copy_account_in_all_row(doc, cdt, cdn, "income_account");
}
-cur_frm.cscript.expense_account = function(doc, cdt, cdn){
+cur_frm.cscript.expense_account = function(doc, cdt, cdn) {
cur_frm.cscript.copy_account_in_all_row(doc, cdt, cdn, "expense_account");
}
-cur_frm.cscript.copy_account_in_all_row = function(doc, cdt, cdn, fieldname) {
- var d = locals[cdt][cdn];
- if(d[fieldname]){
- var cl = getchildren('Sales Invoice Item', doc.name, cur_frm.cscript.fname, doc.doctype);
- for(var i = 0; i < cl.length; i++){
- if(!cl[i][fieldname]) cl[i][fieldname] = d[fieldname];
- }
- }
- refresh_field(cur_frm.cscript.fname);
-}
-
-cur_frm.cscript.cost_center = function(doc, cdt, cdn){
- var d = locals[cdt][cdn];
- if(d.cost_center){
- var cl = getchildren('Sales Invoice Item', doc.name, cur_frm.cscript.fname, doc.doctype);
- for(var i = 0; i < cl.length; i++){
- if(!cl[i].cost_center) cl[i].cost_center = d.cost_center;
- }
- }
- refresh_field(cur_frm.cscript.fname);
+cur_frm.cscript.cost_center = function(doc, cdt, cdn) {
+ cur_frm.cscript.copy_account_in_all_row(doc, cdt, cdn, "cost_center");
}
cur_frm.cscript.on_submit = function(doc, cdt, cdn) {
diff --git a/accounts/doctype/sales_invoice/sales_invoice.py b/accounts/doctype/sales_invoice/sales_invoice.py
index 92c1680..cdae74e 100644
--- a/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/accounts/doctype/sales_invoice/sales_invoice.py
@@ -48,12 +48,7 @@
self.validate_proj_cust()
self.validate_with_previous_doc()
self.validate_uom_is_integer("stock_uom", "qty")
-
- sales_com_obj = get_obj('Sales Common')
- sales_com_obj.check_stop_sales_order(self)
- sales_com_obj.check_active_sales_items(self)
- sales_com_obj.check_conversion_rate(self)
- sales_com_obj.validate_max_discount(self, 'entries')
+ self.check_stop_sales_order("sales_order")
self.validate_customer_account()
self.validate_debit_acc()
self.validate_fixed_asset_account()
@@ -111,8 +106,7 @@
if cint(self.doc.update_stock) == 1:
self.update_stock_ledger()
- sales_com_obj = get_obj(dt = 'Sales Common')
- sales_com_obj.check_stop_sales_order(self)
+ self.check_stop_sales_order("sales_order")
from accounts.utils import remove_against_link_from_jv
remove_against_link_from_jv(self.doc.doctype, self.doc.name, "against_invoice")
@@ -256,19 +250,7 @@
else:
due_date = self.doc.posting_date
- return due_date
-
- def get_barcode_details(self, barcode):
- return get_obj('Sales Common').get_barcode_details(barcode)
-
-
- def get_adj_percent(self, arg=''):
- """Fetch ref rate from item master as per selected price list"""
- get_obj('Sales Common').get_adj_percent(self)
-
- def get_comm_rate(self, sales_partner):
- """Get Commission rate of Sales Partner"""
- return get_obj('Sales Common').get_comm_rate(sales_partner, self)
+ return due_date
def get_advances(self):
super(DocType, self).get_advances(self.doc.debit_to,
@@ -471,10 +453,6 @@
w = ps[0][1]
return w
-
- def make_packing_list(self):
- get_obj('Sales Common').make_packing_list(self,'entries')
-
def on_update(self):
if cint(self.doc.update_stock) == 1:
# Set default warehouse from pos setting
@@ -485,7 +463,8 @@
if not d.warehouse:
d.warehouse = cstr(w)
- self.make_packing_list()
+ from stock.doctype.packed_item.packed_item import make_packing_list
+ make_packing_list(self, 'entries')
else:
self.doclist = self.doc.clear_table(self.doclist, 'packing_details')
@@ -517,8 +496,7 @@
def update_stock_ledger(self):
sl_entries = []
- items = get_obj('Sales Common').get_item_list(self)
- for d in items:
+ for d in self.get_item_list():
if webnotes.conn.get_value("Item", d.item_code, "is_stock_item") == "Yes" \
and d.warehouse:
sl_entries.append(self.get_sl_entries(d, {
@@ -861,7 +839,6 @@
def notify_errors(inv, owner):
import webnotes
- import website
exception_msg = """
Dear User,
diff --git a/accounts/doctype/sales_invoice/sales_invoice.txt b/accounts/doctype/sales_invoice/sales_invoice.txt
index 331a503..3419188 100644
--- a/accounts/doctype/sales_invoice/sales_invoice.txt
+++ b/accounts/doctype/sales_invoice/sales_invoice.txt
@@ -2,7 +2,7 @@
{
"creation": "2013-05-24 19:29:05",
"docstatus": 0,
- "modified": "2013-10-11 13:12:38",
+ "modified": "2013-10-18 13:12:38",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -323,7 +323,7 @@
"fieldname": "packing_details",
"fieldtype": "Table",
"label": "Packing Details",
- "options": "Delivery Note Packing Item",
+ "options": "Packed Item",
"print_hide": 1,
"read_only": 0
},
diff --git a/accounts/general_ledger.py b/accounts/general_ledger.py
index 995fdc0..b0c585a 100644
--- a/accounts/general_ledger.py
+++ b/accounts/general_ledger.py
@@ -30,8 +30,12 @@
entry.credit = flt(entry.credit, 2)
# toggle debit, credit if negative entry
- if flt(entry.debit) < 0 or flt(entry.credit) < 0:
- entry.debit, entry.credit = abs(flt(entry.credit)), abs(flt(entry.debit))
+ if flt(entry.debit) < 0:
+ entry.credit = flt(entry.credit) - flt(entry.debit)
+ entry.debit = 0.0
+ if flt(entry.credit) < 0:
+ entry.debit = flt(entry.debit) - flt(entry.credit)
+ entry.credit = 0.0
return gl_map
diff --git a/accounts/report/gross_profit/gross_profit.py b/accounts/report/gross_profit/gross_profit.py
index 9917b69..6d01af4 100644
--- a/accounts/report/gross_profit/gross_profit.py
+++ b/accounts/report/gross_profit/gross_profit.py
@@ -75,7 +75,7 @@
for d in webnotes.conn.sql("""select parenttype, parent, parent_item,
item_code, warehouse, -1*qty as total_qty, parent_detail_docname
- from `tabDelivery Note Packing Item` where docstatus=1""", as_dict=True):
+ from `tabPacked Item` where docstatus=1""", as_dict=True):
item_sales_bom.setdefault(d.parenttype, webnotes._dict()).setdefault(d.parent,
webnotes._dict()).setdefault(d.parent_item, []).append(d)
diff --git a/buying/doctype/buying_settings/buying_settings.py b/buying/doctype/buying_settings/buying_settings.py
index 3f4f96d..efca339 100644
--- a/buying/doctype/buying_settings/buying_settings.py
+++ b/buying/doctype/buying_settings/buying_settings.py
@@ -13,4 +13,7 @@
def validate(self):
for key in ["supplier_type", "supp_master_name", "maintain_same_rate", "buying_price_list"]:
webnotes.conn.set_default(key, self.doc.fields.get(key, ""))
-
\ No newline at end of file
+
+ from setup.doctype.naming_series.naming_series import set_by_naming_series
+ set_by_naming_series("Supplier", "supplier_name",
+ self.doc.get("supp_master_name")=="Naming Series", hide_name_field=False)
diff --git a/buying/doctype/purchase_common/purchase_common.py b/buying/doctype/purchase_common/purchase_common.py
index 8637e5f..4d2bc00 100644
--- a/buying/doctype/purchase_common/purchase_common.py
+++ b/buying/doctype/purchase_common/purchase_common.py
@@ -16,25 +16,6 @@
def __init__(self, doc, doclist=None):
self.doc = doc
self.doclist = doclist
-
- def is_item_table_empty(self, obj):
- if not len(obj.doclist.get({"parentfield": obj.fname})):
- msgprint(_("You need to put at least one item in the item table."), raise_exception=True)
-
- def get_supplier_details(self, name = ''):
- details = webnotes.conn.sql("select supplier_name,address from `tabSupplier` where name = '%s' and docstatus != 2" %(name), as_dict = 1)
- if details:
- ret = {
- 'supplier_name' : details and details[0]['supplier_name'] or '',
- 'supplier_address' : details and details[0]['address'] or ''
- }
- # ********** get primary contact details (this is done separately coz. , in case there is no primary contact thn it would not be able to fetch customer details in case of join query)
- contact_det = webnotes.conn.sql("select contact_name, contact_no, email_id from `tabContact` where supplier = '%s' and is_supplier = 1 and is_primary_contact = 'Yes' and docstatus != 2" %(name), as_dict = 1)
- ret['contact_person'] = contact_det and contact_det[0]['contact_name'] or ''
- return ret
- else:
- msgprint("Supplier : %s does not exists" % (name))
- raise Exception
def update_last_purchase_rate(self, obj, is_submit):
"""updates last_purchase_rate in item table for each item"""
diff --git a/buying/doctype/purchase_order/purchase_order.py b/buying/doctype/purchase_order/purchase_order.py
index cf207bb..d3555fc 100644
--- a/buying/doctype/purchase_order/purchase_order.py
+++ b/buying/doctype/purchase_order/purchase_order.py
@@ -147,7 +147,6 @@
def on_submit(self):
purchase_controller = webnotes.get_obj("Purchase Common")
- purchase_controller.is_item_table_empty(self)
self.update_prevdoc_status()
self.update_bin(is_submit = 1, is_stopped = 0)
diff --git a/buying/doctype/supplier/supplier.js b/buying/doctype/supplier/supplier.js
index a4c6de0..1512dec 100644
--- a/buying/doctype/supplier/supplier.js
+++ b/buying/doctype/supplier/supplier.js
@@ -9,10 +9,7 @@
cur_frm.cscript.refresh = function(doc,dt,dn) {
cur_frm.cscript.make_dashboard(doc);
- if(sys_defaults.supp_master_name == 'Supplier Name')
- hide_field('naming_series');
- else
- unhide_field('naming_series');
+ erpnext.hide_naming_series();
if(doc.__islocal){
hide_field(['address_html','contact_html']);
diff --git a/buying/doctype/supplier_quotation/supplier_quotation.py b/buying/doctype/supplier_quotation/supplier_quotation.py
index 8c5224e..67c8360 100644
--- a/buying/doctype/supplier_quotation/supplier_quotation.py
+++ b/buying/doctype/supplier_quotation/supplier_quotation.py
@@ -26,9 +26,6 @@
self.validate_uom_is_integer("uom", "qty")
def on_submit(self):
- purchase_controller = webnotes.get_obj("Purchase Common")
- purchase_controller.is_item_table_empty(self)
-
webnotes.conn.set(self.doc, "status", "Submitted")
def on_cancel(self):
diff --git a/buying/page/buying_home/buying_home.js b/buying/page/buying_home/buying_home.js
index f41f619..3af91a0 100644
--- a/buying/page/buying_home/buying_home.js
+++ b/buying/page/buying_home/buying_home.js
@@ -67,10 +67,15 @@
},
{
label: wn._("Price List"),
- description: wn._("Mupltiple Item prices."),
+ description: wn._("Multiple Price list."),
doctype:"Price List"
},
{
+ label: wn._("Item Price"),
+ description: wn._("Multiple Item prices."),
+ doctype:"Item Price"
+ },
+ {
"doctype":"Supplier Type",
"label": wn._("Supplier Type"),
"description": wn._("Supplier classification.")
diff --git a/buying/utils.py b/buying/utils.py
index 115b023..385a8c7 100644
--- a/buying/utils.py
+++ b/buying/utils.py
@@ -89,10 +89,9 @@
# try fetching from price list
if args.buying_price_list and args.price_list_currency:
- price_list_rate = webnotes.conn.sql("""select ip.ref_rate from `tabItem Price` ip,
- `tabPrice List` pl where ip.parent = pl.name and ip.parent=%s and
- ip.item_code=%s and pl.buying_or_selling='Buying'""",
- (args.buying_price_list, args.item_code), as_dict=1)
+ 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'""",
+ (args.buying_price_list, args.item_code), as_dict=1)
if price_list_rate:
from utilities.transaction_base import validate_currency
diff --git a/controllers/accounts_controller.py b/controllers/accounts_controller.py
index 5121d69..9b2e28b 100644
--- a/controllers/accounts_controller.py
+++ b/controllers/accounts_controller.py
@@ -52,7 +52,7 @@
msgprint(_("Account for this ") + fieldname + _(" has been freezed. ") +
self.doc.doctype + _(" can not be made."), raise_exception=1)
- def set_price_list_currency(self, buying_or_selling, for_validate=False):
+ def set_price_list_currency(self, buying_or_selling):
if self.meta.get_field("currency"):
company_currency = get_company_currency(self.doc.company)
@@ -66,7 +66,7 @@
if self.doc.price_list_currency == company_currency:
self.doc.plc_conversion_rate = 1.0
- elif not self.doc.plc_conversion_rate or not for_validate:
+ elif not self.doc.plc_conversion_rate:
self.doc.plc_conversion_rate = self.get_exchange_rate(
self.doc.price_list_currency, company_currency)
@@ -76,7 +76,7 @@
self.doc.conversion_rate = self.doc.plc_conversion_rate
elif self.doc.currency == company_currency:
self.doc.conversion_rate = 1.0
- elif not self.doc.conversion_rate or not for_validate:
+ elif not self.doc.conversion_rate:
self.doc.conversion_rate = self.get_exchange_rate(self.doc.currency,
company_currency)
diff --git a/controllers/buying_controller.py b/controllers/buying_controller.py
index 5176b16..2677252 100644
--- a/controllers/buying_controller.py
+++ b/controllers/buying_controller.py
@@ -2,7 +2,7 @@
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
-import webnotes, json
+import webnotes
from webnotes import _, msgprint
from webnotes.utils import flt, _round
@@ -12,7 +12,6 @@
from controllers.stock_controller import StockController
class BuyingController(StockController):
-
def onload_post_render(self):
# contact, address, item details
self.set_missing_values()
@@ -22,6 +21,7 @@
if self.doc.supplier and not self.doc.supplier_name:
self.doc.supplier_name = webnotes.conn.get_value("Supplier",
self.doc.supplier, "supplier_name")
+ self.is_item_table_empty()
self.validate_stock_or_nonstock_items()
self.validate_warehouse()
@@ -29,7 +29,7 @@
super(BuyingController, self).set_missing_values(for_validate)
self.set_supplier_from_item_default()
- self.set_price_list_currency("Buying", for_validate)
+ self.set_price_list_currency("Buying")
# set contact and address details for supplier, if they are not mentioned
if self.doc.supplier and not (self.doc.contact_person and self.doc.supplier_address):
@@ -279,3 +279,8 @@
(", ".join((["%s"]*len(item_codes))),), item_codes)]
return self._purchase_items
+
+
+ def is_item_table_empty(self):
+ if not len(self.doclist.get({"parentfield": self.fname})):
+ webnotes.throw(_("Item table can not be blank"))
\ No newline at end of file
diff --git a/controllers/queries.py b/controllers/queries.py
index 637d5e1..ed44f9b 100644
--- a/controllers/queries.py
+++ b/controllers/queries.py
@@ -174,4 +174,36 @@
"fcond": get_filters_cond(doctype, filters, []),
"mcond": get_match_cond(doctype),
"start": "%(start)s", "page_len": "%(page_len)s", "txt": "%(txt)s"
- }, { "start": start, "page_len": page_len, "txt": ("%%%s%%" % txt) })
\ No newline at end of file
+ }, { "start": start, "page_len": page_len, "txt": ("%%%s%%" % txt) })
+
+def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
+ from controllers.queries import get_match_cond
+
+ if filters.has_key('warehouse'):
+ return webnotes.conn.sql("""select batch_no from `tabStock Ledger Entry` sle
+ where item_code = '%(item_code)s'
+ and warehouse = '%(warehouse)s'
+ and batch_no like '%(txt)s'
+ and exists(select * from `tabBatch`
+ where name = sle.batch_no
+ and (ifnull(expiry_date, '')='' or expiry_date >= '%(posting_date)s')
+ and docstatus != 2)
+ %(mcond)s
+ group by batch_no having sum(actual_qty) > 0
+ order by batch_no desc
+ limit %(start)s, %(page_len)s """ % {'item_code': filters['item_code'],
+ 'warehouse': filters['warehouse'], 'posting_date': filters['posting_date'],
+ 'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype, searchfield),
+ 'start': start, 'page_len': page_len})
+ else:
+ return webnotes.conn.sql("""select name from tabBatch
+ where docstatus != 2
+ and item = '%(item_code)s'
+ and (ifnull(expiry_date, '')='' or expiry_date >= '%(posting_date)s')
+ and name like '%(txt)s'
+ %(mcond)s
+ order by name desc
+ limit %(start)s, %(page_len)s""" % {'item_code': filters['item_code'],
+ 'posting_date': filters['posting_date'], 'txt': "%%%s%%" % txt,
+ 'mcond':get_match_cond(doctype, searchfield),'start': start,
+ 'page_len': page_len})
\ No newline at end of file
diff --git a/controllers/selling_controller.py b/controllers/selling_controller.py
index 5c7b66c..61bd032 100644
--- a/controllers/selling_controller.py
+++ b/controllers/selling_controller.py
@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import webnotes
-from webnotes.utils import cint, flt, comma_or, _round, add_days, cstr
+from webnotes.utils import cint, flt, comma_or, _round, cstr
from setup.utils import get_company_currency
from selling.utils import get_item_details
from webnotes import msgprint, _
@@ -14,6 +14,11 @@
def onload_post_render(self):
# contact, address, item details and pos details (if applicable)
self.set_missing_values()
+
+ def validate(self):
+ super(SellingController, self).validate()
+ self.validate_max_discount()
+ check_active_sales_items(self)
def get_sender(self, comm):
return webnotes.conn.get_value('Sales Email Settings', None, 'email_id')
@@ -23,7 +28,7 @@
# set contact and address details for customer, if they are not mentioned
self.set_missing_lead_customer_details()
- self.set_price_list_and_item_details(for_validate)
+ self.set_price_list_and_item_details()
if self.doc.fields.get("__islocal"):
self.set_taxes("other_charges", "charge")
@@ -41,8 +46,8 @@
if not self.doc.fields.get(fieldname) and self.meta.get_field(fieldname):
self.doc.fields[fieldname] = val
- def set_price_list_and_item_details(self, for_validate=False):
- self.set_price_list_currency("Selling", for_validate)
+ def set_price_list_and_item_details(self):
+ self.set_price_list_currency("Selling")
self.set_missing_item_details(get_item_details)
def get_other_charges(self):
@@ -237,3 +242,120 @@
elif self.doc.order_type not in valid_types:
msgprint(_(self.meta.get_label("order_type")) + " " +
_("must be one of") + ": " + comma_or(valid_types), raise_exception=True)
+
+ def check_credit(self, grand_total):
+ customer_account = webnotes.conn.get_value("Account", {"company": self.doc.company,
+ "master_name": self.doc.customer}, "name")
+ if customer_account:
+ total_outstanding = 0
+ total_outstanding = webnotes.conn.sql("""select
+ sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))
+ from `tabGL Entry` where account = %s""", customer_account)[0][0]
+
+ outstanding_including_current = flt(total_outstanding) + flt(grand_total)
+ webnotes.bean('Account', customer_account).run_method("check_credit_limit",
+ customer_account, self.doc.company, outstanding_including_current)
+
+ def validate_max_discount(self):
+ for d in self.doclist.get({"parentfield": self.fname}):
+ discount = flt(webnotes.conn.get_value("Item", d.item_code, "max_discount"))
+
+ if discount and flt(d.adj_rate) > discount:
+ webnotes.throw(_("You cannot give more than ") + cstr(discount) + "% " +
+ _("discount on Item Code") + ": " + cstr(d.item_code))
+
+ def get_item_list(self):
+ il = []
+ for d in self.doclist.get({"parentfield": self.fname}):
+ reserved_warehouse = ""
+ reserved_qty_for_main_item = 0
+
+ if self.doc.doctype == "Sales Order":
+ if (webnotes.conn.get_value("Item", d.item_code, "is_stock_item") == 'Yes' or
+ self.has_sales_bom(d.item_code)) and not d.reserved_warehouse:
+ webnotes.throw(_("Please enter Reserved Warehouse for item ") +
+ d.item_code + _(" as it is stock Item or packing item"))
+ reserved_warehouse = d.reserved_warehouse
+ if flt(d.qty) > flt(d.delivered_qty):
+ reserved_qty_for_main_item = flt(d.qty) - flt(d.delivered_qty)
+
+ if self.doc.doctype == "Delivery Note" and d.against_sales_order:
+ # if SO qty is 10 and there is tolerance of 20%, then it will allow DN of 12.
+ # But in this case reserved qty should only be reduced by 10 and not 12
+
+ already_delivered_qty = self.get_already_delivered_qty(self.doc.name,
+ d.against_sales_order, d.prevdoc_detail_docname)
+ so_qty, reserved_warehouse = self.get_so_qty_and_warehouse(d.prevdoc_detail_docname)
+
+ if already_delivered_qty + d.qty > so_qty:
+ reserved_qty_for_main_item = -(so_qty - already_delivered_qty)
+ else:
+ reserved_qty_for_main_item = -flt(d.qty)
+
+ if self.has_sales_bom(d.item_code):
+ for p in self.doclist.get({"parentfield": "packing_details"}):
+ if p.parent_detail_docname == d.name and p.parent_item == d.item_code:
+ # the packing details table's qty is already multiplied with parent's qty
+ il.append(webnotes._dict({
+ 'warehouse': p.warehouse,
+ 'reserved_warehouse': reserved_warehouse,
+ 'item_code': p.item_code,
+ 'qty': flt(p.qty),
+ 'reserved_qty': (flt(p.qty)/flt(d.qty)) * reserved_qty_for_main_item,
+ 'uom': p.uom,
+ 'batch_no': cstr(p.batch_no).strip(),
+ 'serial_no': cstr(p.serial_no).strip(),
+ 'name': d.name
+ }))
+ else:
+ il.append(webnotes._dict({
+ 'warehouse': d.warehouse,
+ 'reserved_warehouse': reserved_warehouse,
+ 'item_code': d.item_code,
+ 'qty': d.qty,
+ 'reserved_qty': reserved_qty_for_main_item,
+ 'uom': d.stock_uom,
+ 'batch_no': cstr(d.batch_no).strip(),
+ 'serial_no': cstr(d.serial_no).strip(),
+ 'name': d.name
+ }))
+ return il
+
+ def has_sales_bom(self, item_code):
+ return webnotes.conn.sql("""select name from `tabSales BOM`
+ where new_item_code=%s and docstatus != 2""", item_code)
+
+ def get_already_delivered_qty(self, dn, so, so_detail):
+ qty = webnotes.conn.sql("""select sum(qty) from `tabDelivery Note Item`
+ where prevdoc_detail_docname = %s and docstatus = 1
+ and against_sales_order = %s
+ and parent != %s""", (so_detail, so, dn))
+ return qty and flt(qty[0][0]) or 0.0
+
+ def get_so_qty_and_warehouse(self, so_detail):
+ so_item = webnotes.conn.sql("""select qty, reserved_warehouse from `tabSales Order Item`
+ where name = %s and docstatus = 1""", so_detail, as_dict=1)
+ so_qty = so_item and flt(so_item[0]["qty"]) or 0.0
+ so_warehouse = so_item and so_item[0]["reserved_warehouse"] or ""
+ return so_qty, so_warehouse
+
+ def check_stop_sales_order(self, ref_fieldname):
+ for d in self.doclist.get({"parentfield": self.fname}):
+ if d.fields.get(ref_fieldname):
+ status = webnotes.conn.get_value("Sales Order", d.fields[ref_fieldname], "status")
+ if status == "Stopped":
+ webnotes.throw(self.doc.doctype +
+ _(" can not be created/modified against stopped Sales Order ") +
+ d.fields[ref_fieldname])
+
+def check_active_sales_items(obj):
+ for d in obj.doclist.get({"parentfield": obj.fname}):
+ if d.item_code:
+ item = webnotes.conn.sql("""select docstatus, is_sales_item,
+ is_service_item, default_income_account from tabItem where name = %s""",
+ d.item_code, as_dict=True)[0]
+ if item.is_sales_item == 'No' and item.is_service_item == 'No':
+ webnotes.throw(_("Item is neither Sales nor Service Item") + ": " + d.item_code)
+ if d.income_account and not item.default_income_account:
+ webnotes.conn.set_value("Item", d.item_code, "default_income_account",
+ d.income_account)
diff --git a/controllers/stock_controller.py b/controllers/stock_controller.py
index d4c92a9..359dc9e 100644
--- a/controllers/stock_controller.py
+++ b/controllers/stock_controller.py
@@ -12,18 +12,17 @@
class StockController(AccountsController):
def make_gl_entries(self):
- if not cint(webnotes.defaults.get_global_default("auto_accounting_for_stock")):
- return
-
- warehouse_account = self.get_warehouse_account()
-
- if self.doc.docstatus==1:
- gl_entries = self.get_gl_entries_for_stock(warehouse_account)
- make_gl_entries(gl_entries)
- else:
+ if self.doc.docstatus == 2:
delete_gl_entries(voucher_type=self.doc.doctype, voucher_no=self.doc.name)
+
+ if cint(webnotes.defaults.get_global_default("auto_accounting_for_stock")):
+ warehouse_account = self.get_warehouse_account()
- self.update_gl_entries_after(warehouse_account)
+ if self.doc.docstatus==1:
+ gl_entries = self.get_gl_entries_for_stock(warehouse_account)
+ make_gl_entries(gl_entries)
+
+ self.update_gl_entries_after(warehouse_account)
def get_gl_entries_for_stock(self, warehouse_account=None, default_expense_account=None,
default_cost_center=None):
@@ -91,15 +90,11 @@
return stock_ledger
def get_warehouse_account(self):
- for d in webnotes.conn.sql("select name from tabWarehouse"):
- webnotes.bean("Warehouse", d[0]).save()
-
warehouse_account = dict(webnotes.conn.sql("""select master_name, name from tabAccount
where account_type = 'Warehouse' and ifnull(master_name, '') != ''"""))
return warehouse_account
def update_gl_entries_after(self, warehouse_account=None):
- from accounts.utils import get_stock_and_account_difference
future_stock_vouchers = self.get_future_stock_vouchers()
gle = self.get_voucherwise_gl_entries(future_stock_vouchers)
if not warehouse_account:
diff --git a/docs/user/customer_portal/docs.user.customer_portal.login.md b/docs/user/customer_portal/docs.user.customer_portal.login.md
new file mode 100644
index 0000000..c0c5e78
--- /dev/null
+++ b/docs/user/customer_portal/docs.user.customer_portal.login.md
@@ -0,0 +1,8 @@
+---
+{
+ "_label": "Login"
+}
+---
+To login into the customer account, the customer has to use his email id and the password sent by ERPNext; generated through the sign-up process.
+
+
\ No newline at end of file
diff --git a/docs/user/customer_portal/docs.user.customer_portal.md b/docs/user/customer_portal/docs.user.customer_portal.md
new file mode 100644
index 0000000..fc886f1
--- /dev/null
+++ b/docs/user/customer_portal/docs.user.customer_portal.md
@@ -0,0 +1,16 @@
+---
+{
+ "_label": "Customer Portal",
+ "_toc": [
+ "docs.user.customer_portal.sign_up",
+ "docs.user.customer_portal.login",
+ "docs.user.customer_portal.orders",
+ "docs.user.customer_portal.tickets"
+ ]
+}
+---
+
+Customer Portal is designed to give easy accesibility to customers of a company.
+
+
+
diff --git a/docs/user/customer_portal/docs.user.customer_portal.orders.md b/docs/user/customer_portal/docs.user.customer_portal.orders.md
new file mode 100644
index 0000000..d24d038
--- /dev/null
+++ b/docs/user/customer_portal/docs.user.customer_portal.orders.md
@@ -0,0 +1,30 @@
+---
+{
+ "_label": "Customer Orders, Invoices, and Shipping Status"
+}
+---
+ERPNext Web Portal gives your customers quick access to their Orders, Invoices and Shipments
+Customers can check the status of their orders, invoices, and shipping status by logging on to the web.
+
+
+
+
+
+
+Once an order is raised, either using the Shopping Cart or from within ERPNext, your customer can view the order and keep an eye on the billing and shipment status. When the invoice and payment against these orders are submitted, the customer can see the updated status on the portal, at a glance.
+
+
+
+
+
+#### Invoice with paid status.
+
+
+
+
+
+#### Invoice with billed status.
+
+
+
+
diff --git a/docs/user/customer_portal/docs.user.customer_portal.sign_up.md b/docs/user/customer_portal/docs.user.customer_portal.sign_up.md
new file mode 100644
index 0000000..9574f65
--- /dev/null
+++ b/docs/user/customer_portal/docs.user.customer_portal.sign_up.md
@@ -0,0 +1,25 @@
+---
+{
+ "_label": "Sign-Up"
+}
+---
+Customers have to log-in to the Company Website, and sign-up as a customer.
+
+#### Step 1: Click on Login Icon
+
+
+
+<br>
+
+#### Step 2: Click on Sign Up Icon
+
+
+
+<br>
+
+#### Step 3: Enter Customer Name and ID
+
+
+
+After the sign up process, a mail will be sent to the customers email id with the password details.
+
diff --git a/docs/user/customer_portal/docs.user.customer_portal.tickets.md b/docs/user/customer_portal/docs.user.customer_portal.tickets.md
new file mode 100644
index 0000000..6ac8a37
--- /dev/null
+++ b/docs/user/customer_portal/docs.user.customer_portal.tickets.md
@@ -0,0 +1,28 @@
+---
+{
+ "_label": "Support Tickets"
+}
+---
+
+The customer portal makes it very easy for a customer to raise concerns. A simple and intuitive interface facilitates your customer to report their concerns as Support Tickets. They can view the complete thread of their conversation.
+
+#### Empty Ticket List
+
+
+
+
+
+#### New Support Ticket
+
+
+
+
+#### Open Support Ticket
+
+
+
+
+#### Reply on Support Ticket
+
+
+
diff --git a/docs/user/customize/docs.user.customize.custom_field.md b/docs/user/customize/docs.user.customize.custom_field.md
index a457f07..c5aac31 100644
--- a/docs/user/customize/docs.user.customize.custom_field.md
+++ b/docs/user/customize/docs.user.customize.custom_field.md
@@ -7,18 +7,20 @@
> Setup > Custom Field > New Custom Field
-
+
In the form:
- Select the Document on which you want to add the Custom Field.
-- Select the Type of field and the Options (see section on field types).
+- Select the Type of field and the Options .
- Select where you want the field to appear in the Form (“after field” section).
and save the Custom Field. When you open a new / existing form of the type you selected in step 1, you will see it with the Custom Fields.
+To understand Custom Fields in detail, visit [DocType-Fields](docs.user.knowledge.doctype_fields.html)
+
#### Naming
Many times you want your fields to be carried over from one form to another. For example, you may have added a Custom Field in Quotation that you want to include in Sales Order when a Sales Order is created from the Quotation. This is simple in ERPNext, just make sure the fields have the same “fieldname”
diff --git a/docs/user/customize/docs.user.customize.custom_form.md b/docs/user/customize/docs.user.customize.custom_form.md
index 6b37bd1..f418430 100644
--- a/docs/user/customize/docs.user.customize.custom_form.md
+++ b/docs/user/customize/docs.user.customize.custom_form.md
@@ -3,12 +3,13 @@
"_label": "Customize Form"
}
---
-Please read ERPNext Structure before you start customizing.
You can Customize Forms by changing its layout, making certain fields mandatory, hiding others and changing permission levels on fields by going to:
> Setup > Customize ERPNext > Customize Forms
+#### Step 1: Select the required Form Type for Customization.
+

@@ -24,12 +25,14 @@
You can also allow attachments, set max number of attachments and set the default Print Format.
+#### Step 2: Replace Fields with required changes.

<br>
+To understand field definitions, visit [Doctype-Fields](docs.user.knowledge.doctype_fields.html)
> Though we want you to do everything you can to customize your ERP based on your business needs, we recommend that you do not make “wild” changes to the forms. This is because, these changes may affect certain operations and may mess up your forms. Make small changes and see its effect before doing some more.
\ No newline at end of file
diff --git a/docs/user/docs.user.md b/docs/user/docs.user.md
index 5c65882..1b79ee7 100644
--- a/docs/user/docs.user.md
+++ b/docs/user/docs.user.md
@@ -17,8 +17,9 @@
"docs.user.website",
"docs.user.tools",
"docs.user.customize",
- "docs.user.knowledge"
- ],
+ "docs.user.knowledge",
+ "docs.user.customer_portal"
+ ],
"_no_toc": 1
}
---
@@ -70,6 +71,7 @@
1. [Terms and Conditions](docs.user.selling.terms.html)
1. [Price Lists](docs.user.setup.price_list.html)
1. [Discount](docs.user.selling.discount.html)
+ 1. [Shopping Cart](docs.user.selling.shopping_cart.html)
1. [Customers](docs.user.selling.customer.html)
1. [Lead](docs.user.selling.lead.html)
1. [Opportunity](docs.user.selling.opportunity.html)
@@ -88,6 +90,7 @@
1. [Warehouse](docs.user.stock.warehouse.html)
1. [Item Group](docs.user.stock.item_group.html)
1. [Item](docs.user.stock.item.html)
+ 1. [Product Listing on Website](docs.user.stock.product_listing_on_website.html)
1. [Serialized Inventory](docs.user.stock.serialized.html)
1. [Purchase Receipt](docs.user.stock.purchase_receipt.html)
1. [Delivery Note](docs.user.stock.delivery_note.html)
@@ -159,5 +162,11 @@
1. [Accounting Knowledge](docs.user.knowledge.accounting.html)
1. [Accounting Entries](docs.user.knowledge.accounting_entries.html)
1. [DocType Definitions](docs.user.knowledge.doctype.html)
+ 1. [DocType Fields](docs.user.knowledge.doctype_fields.html)
1. [Attachment and CSV Files](docs.user.knowledge.attachment_csv.html)
1. [Format using Markdown](docs.user.knowledge.markdown.html)
+1. [Customer Portal](docs.user.customer_portal.html)
+ 1. [Sign Up](docs.user.customer_portal.sign_up.html)
+ 2. [Login](docs.user.customer_portal.login.html)
+ 3. [Customer Orders](docs.user.customer_portal.orders.html)
+ 4. [Support Tickets](docs.user.customer_portal.tickets.html)
diff --git a/docs/user/knowledge/docs.user.knowledge.doctype.md b/docs/user/knowledge/docs.user.knowledge.doctype.md
index a2550d4..8614fdf 100644
--- a/docs/user/knowledge/docs.user.knowledge.doctype.md
+++ b/docs/user/knowledge/docs.user.knowledge.doctype.md
@@ -71,197 +71,3 @@
There are a certain type of DocTypes that are “Single”, i.e. they have no table associated and have only one record of its fields. DocTypes such as Global Defaults, Production Planning Tool are “Single” DocTypes.
-#### Field Columns
-
-In the fields table, there are many columns, here is an explanation of the columns of the field table.
-
-<table class="table table-bordered text-left">
- <thead>
- <tr class="active">
- <td width="30%">Column</td>
- <td>Description</td>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>Label</td>
- <td>Field Label (that appears in the form).</td>
- </tr>
- <tr>
- <td>Type</td>
- <td>Field Type</td>
- </tr>
- <tr>
- <td>Name</td>
- <td>Column name in the database, must be code friendly with no white spaces, special characters and capital letters.</td>
- </tr>
- <tr>
- <td>options</td>
- <td>Field settings:<br>
- For Select: List of options (each on a new line).<br>
- For Link: DocType that is “linked”.<br>
- For HTML: HTML Content
- </tr>
- <tr>
- <td>Perm Level</td>
- <td>Permission level (number) of the field. You can group fields by numbers, called levels, and apply rules on the levels.</td>
- </tr>
- <tr>
- <td>Width</td>
- <td>Width of the field (in pixels) - useful for “Table” types.</td>
- </tr>
- <tr>
- <td>Reqd</td>
- <td>Checked if field is mandatory (required).</td>
- </tr>
- <tr>
- <td>In Filter</td>
- <td>Checked if field appears as a standard filter in old style reports.</td>
- </tr>
- <tr>
- <td>Hidden</td>
- <td>Checked if field is hidden.</td>
- </tr>
- <tr>
- <td>Print Hide</td>
- <td>Checked if field is hidden in Print Formats.</td>
- </tr>
- <tr>
- <td>Report Hide</td>
- <td>Checked if field is hidden in old style reports.</td>
- </tr>
- <tr>
- <td>Allow on Submit</td>
- <td>Checked if this field can be edited after the document is “Submitted”.</td>
- </tr>
- <tr>
- <td>Depends On</td>
- <td>The fieldname of the field that will decide whether this field will be shown or hidden. It is useful to hide un-necessary fields.</td>
- </tr>
- <tr>
- <td>Description</td>
- <td>Description of the field</td>
- </tr>
- <tr>
- <td>Default</td>
- <td>Default value when a new record is created.<br>
- Note: “user” will set the current user as default and “today” will set today’s date (if the field is a Date field).</td>
- </tr>
- <tbody>
-<table>
-
-#### Field Types and Options
-
-Here is a list of the different types of fields used to make / customize forms in ERPNext.
-
-<table class="table table-bordered text-left">
- <thead>
- <tr class="active">
- <td width="30%">Type</td>
- <td>Description</td>
- <td>Options/Setting</td>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td>Data</td>
- <td>Single line text field with 180 characters</td>
- <td> </td>
- </tr>
- <tr>
- <td>Select</td>
- <td>Select from a pre-determined items in a drop-down.</td>
- <td>The “Options” contains the drop-down items, each on a new row</td>
- </tr>
- <tr>
- <td>Link</td>
- <td>Link an existing document / record</td>
- <td>Options contains the name of the type of document (DocType)</td>
- </tr>
- <tr>
- <td>Currency</td>
- <td>Number with 2 decimal places, that will be shown separated by commas for thousands etc. in Print.</td>
- <td>e.g. 1,000,000.00</td>
- </tr>
- <tr>
- <td>Float</td>
- <td>Number with 6 decimal places.</td>
- <td>e.g. 3.141593</td>
- </tr>
- <tr>
- <td>Int</td>
- <td>Integer (no decimals)</td>
- <td>e.g. 100</td>
- </tr>
- <tr>
- <td>Date</td>
- <td>Date</td>
- <td>Format can be selected in Global Defaults</td>
- </tr>
- <tr>
- <td>Time</td>
- <td>Time</td>
- <td></td>
- </tr>
- <tr>
- <td colspan="3" class="active">Text</td>
- </tr>
- <tr>
- <td>Text</td>
- <td>Multi-line text box without formatting features</td>
- <td></td>
- </tr>
- <tr>
- <td>Text editor</td>
- <td>Multi-line text box with formatting toolbar etc</td>
- <td></td>
- </tr>
- <tr>
- <td>Code</td>
- <td>Code Editor</td>
- <td>Options can include the type of language for syntax formatting.
- Eg JS / Python / HTML</td>
- </tr>
- <tr>
- <td colspan="3" class="active">Table (Grid)</td>
- </tr>
- <tr>
- <td>Table</td>
- <td>Table of child items linked to the record.</td>
- <td>Options contains the name of the DocType of the child table. For example “Sales Invoice Item” for “Sales Invoice”</td>
- </tr>
- <tr>
- <td colspan="3" class="active">Layout</td>
- </tr>
- <tr>
- <td>Section Break</td>
- <td>Break into a new horizontal section.</td>
- <td>The layout in ERPNext is evaluated from top to bottom.</td>
- </tr>
- <tr>
- <td>Column Break</td>
- <td>Break into a new vertical column.</td>
- <td></td>
- </tr>
- <tr>
- <td>HTML</td>
- <td>Add a static text / help / link etc in HTML</td>
- <td>Options contains the HTML.</td>
- </tr>
- <tr>
- <td colspan="3" class="active">Action</td>
- </tr>
- <tr>
- <td>Button</td>
- <td>Button</td>
- <td>[for developers only]</td>
- </tr>
- <tbody>
- <table>
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/user/knowledge/docs.user.knowledge.doctype_fields.md b/docs/user/knowledge/docs.user.knowledge.doctype_fields.md
new file mode 100644
index 0000000..dcc6d4e
--- /dev/null
+++ b/docs/user/knowledge/docs.user.knowledge.doctype_fields.md
@@ -0,0 +1,201 @@
+---
+{
+ "_label": "DocType-Fields"
+}
+---
+
+#### Field Columns
+
+In the fields table, there are many columns. The columns of the field table are explained below:
+
+<table class="table table-bordered text-left">
+ <thead>
+ <tr class="active">
+ <td width="30%">Column</td>
+ <td>Description</td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>Label</td>
+ <td>Field Label (that appears in the form).</td>
+ </tr>
+ <tr>
+ <td>Type</td>
+ <td>Field Type</td>
+ </tr>
+ <tr>
+ <td>Name</td>
+ <td>Column name in the database, must be code friendly with no white spaces, special characters and capital letters.</td>
+ </tr>
+ <tr>
+ <td>options</td>
+ <td>Field settings:<br>
+ For Select: List of options (each on a new line).<br>
+ For Link: DocType that is “linked”.<br>
+ For HTML: HTML Content
+ </tr>
+ <tr>
+ <td>Perm Level</td>
+ <td>Permission level (number) of the field. You can group fields by numbers, called levels, and apply rules on the levels.</td>
+ </tr>
+ <tr>
+ <td>Width</td>
+ <td>Width of the field (in pixels) - useful for “Table” types.</td>
+ </tr>
+ <tr>
+ <td>Reqd</td>
+ <td>Checked if field is mandatory (required).</td>
+ </tr>
+ <tr>
+ <td>In Filter</td>
+ <td>Checked if field appears as a standard filter in old style reports.</td>
+ </tr>
+ <tr>
+ <td>Hidden</td>
+ <td>Checked if field is hidden.</td>
+ </tr>
+ <tr>
+ <td>Print Hide</td>
+ <td>Checked if field is hidden in Print Formats.</td>
+ </tr>
+ <tr>
+ <td>Report Hide</td>
+ <td>Checked if field is hidden in old style reports.</td>
+ </tr>
+ <tr>
+ <td>Allow on Submit</td>
+ <td>Checked if this field can be edited after the document is “Submitted”.</td>
+ </tr>
+ <tr>
+ <td>Depends On</td>
+ <td>The fieldname of the field that will decide whether this field will be shown or hidden. It is useful to hide un-necessary fields.</td>
+ </tr>
+ <tr>
+ <td>Description</td>
+ <td>Description of the field</td>
+ </tr>
+ <tr>
+ <td>Default</td>
+ <td>Default value when a new record is created.<br>
+ Note: “user” will set the current user as default and “today” will set today’s date (if the field is a Date field).</td>
+ </tr>
+ <tbody>
+<table>
+
+
+#### Field Types and Options
+
+Here is a list of the different types of fields used to make / customize forms in ERPNext.
+
+<table class="table table-bordered text-left">
+ <thead>
+ <tr class="active">
+ <td width="30%">Type</td>
+ <td>Description</td>
+ <td>Options/Setting</td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>Data</td>
+ <td>Single line text field with 180 characters</td>
+ <td> </td>
+ </tr>
+ <tr>
+ <td>Select</td>
+ <td>Select from a pre-determined items in a drop-down.</td>
+ <td>The “Options” contains the drop-down items, each on a new row</td>
+ </tr>
+ <tr>
+ <td>Link</td>
+ <td>Link an existing document / record</td>
+ <td>Options contains the name of the type of document (DocType)</td>
+ </tr>
+ <tr>
+ <td>Currency</td>
+ <td>Number with 2 decimal places, that will be shown separated by commas for thousands etc. in Print.</td>
+ <td>e.g. 1,000,000.00</td>
+ </tr>
+ <tr>
+ <td>Float</td>
+ <td>Number with 6 decimal places.</td>
+ <td>e.g. 3.141593</td>
+ </tr>
+ <tr>
+ <td>Int</td>
+ <td>Integer (no decimals)</td>
+ <td>e.g. 100</td>
+ </tr>
+ <tr>
+ <td>Date</td>
+ <td>Date</td>
+ <td>Format can be selected in Global Defaults</td>
+ </tr>
+ <tr>
+ <td>Time</td>
+ <td>Time</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td colspan="3" class="active">Text</td>
+ </tr>
+ <tr>
+ <td>Text</td>
+ <td>Multi-line text box without formatting features</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>Text editor</td>
+ <td>Multi-line text box with formatting toolbar etc</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>Code</td>
+ <td>Code Editor</td>
+ <td>Options can include the type of language for syntax formatting.
+ Eg JS / Python / HTML</td>
+ </tr>
+ <tr>
+ <td colspan="3" class="active">Table (Grid)</td>
+ </tr>
+ <tr>
+ <td>Table</td>
+ <td>Table of child items linked to the record.</td>
+ <td>Options contains the name of the DocType of the child table. For example “Sales Invoice Item” for “Sales Invoice”</td>
+ </tr>
+ <tr>
+ <td colspan="3" class="active">Layout</td>
+ </tr>
+ <tr>
+ <td>Section Break</td>
+ <td>Break into a new horizontal section.</td>
+ <td>The layout in ERPNext is evaluated from top to bottom.</td>
+ </tr>
+ <tr>
+ <td>Column Break</td>
+ <td>Break into a new vertical column.</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td>HTML</td>
+ <td>Add a static text / help / link etc in HTML</td>
+ <td>Options contains the HTML.</td>
+ </tr>
+ <tr>
+ <td colspan="3" class="active">Action</td>
+ </tr>
+ <tr>
+ <td>Button</td>
+ <td>Button</td>
+ <td>[for developers only]</td>
+ </tr>
+ <tbody>
+ <table>
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/user/knowledge/docs.user.knowledge.md b/docs/user/knowledge/docs.user.knowledge.md
index 11dc995..1fa88d9 100644
--- a/docs/user/knowledge/docs.user.knowledge.md
+++ b/docs/user/knowledge/docs.user.knowledge.md
@@ -6,6 +6,7 @@
"docs.user.knowledge.accounting",
"docs.user.knowledge.accounting_entries",
"docs.user.knowledge.doctype",
+ "docs.user.knowledge.doctype_fields",
"docs.user.knowledge.attachment_csv",
"docs.user.knowledge.markdown"
]
diff --git a/docs/user/selling/docs.user.selling.md b/docs/user/selling/docs.user.selling.md
index 9794556..86a07a8 100644
--- a/docs/user/selling/docs.user.selling.md
+++ b/docs/user/selling/docs.user.selling.md
@@ -9,6 +9,9 @@
"docs.user.selling.sales_person",
"docs.user.selling.campaign",
"docs.user.selling.terms",
+ "docs.user.setup.price_list",
+ "docs.user.selling.discount",
+ "docs.user.selling.shopping_cart",
"docs.user.selling. customer",
"docs.user.selling.lead",
"docs.user.selling.opportunity",
diff --git a/docs/user/selling/docs.user.selling.shopping_cart.md b/docs/user/selling/docs.user.selling.shopping_cart.md
new file mode 100644
index 0000000..cf55f76
--- /dev/null
+++ b/docs/user/selling/docs.user.selling.shopping_cart.md
@@ -0,0 +1,41 @@
+---
+{
+ "_label": "Shopping Cart"
+}
+---
+On the Webpage, a shopping cart is an icon that allows you to store all the things that you have earmarked for purchasing. It is a graphical representation of a shopping basket or a shopping cart that allows you to save the items you intend to buy.
+
+This software displays the price of the product . It also displays shipping and handling charges, along with taxes, if applicable.
+
+To set up a shopping cart, go to the selling module.
+
+> Selling > Shopping Cart Settings
+
+
+#### Step 1: Enter Company Details and Default Territory.
+
+
+
+
+<br>
+
+#### Step 2: Enter Price List, Tax Master and Shipping Rule.
+
+
+
+
+<br>
+
+#### Shopping Cart Display
+
+On the Website, the shopping cart image will be seen below the Item price. Customers can click on the cart and enter the amount of quantity they wish to buy. The Item number will be stored on the right hand corner of the page, next to the flower sign.
+
+
+
+<br>
+
+Click on the flower sign on the right hand side to see the cart details. Click on the cart to get the final amount details.
+
+
+
+
diff --git a/docs/user/setup/docs.user.setup.price_list.md b/docs/user/setup/docs.user.setup.price_list.md
index 7214fff..a1fbf89 100644
--- a/docs/user/setup/docs.user.setup.price_list.md
+++ b/docs/user/setup/docs.user.setup.price_list.md
@@ -20,7 +20,7 @@
> Setup > Item Price
-- Enter Price List and Item Code, Valid for Buying or Selling, Item Name & Item Description will be automatically fetched.
+- Enter Price List and Item Code, Valid for Buying or Selling, Item Name and Item Description will be automatically fetched.
- Enter Rate and save the document.

diff --git a/docs/user/setup/docs.user.setup.taxes.md b/docs/user/setup/docs.user.setup.taxes.md
index 91ed591..7043429 100644
--- a/docs/user/setup/docs.user.setup.taxes.md
+++ b/docs/user/setup/docs.user.setup.taxes.md
@@ -7,14 +7,18 @@
### Tax Accounts
-For Tax Accounts that you want to use in the tax templates, you must mention them as type “Tax” in your Chart of Accounts. Some Item-tax features are given below :
+For Tax Accounts that you want to use in the tax templates, you must go to Chart of Accounts and mention them as type “Tax” in your Chart of Item.
-- **Discount**: The maximum Discount that can be applied on an Item can be fixed in the Item master. Read [Discount](docs.user.selling.discount.html)
+## Item Tax
+
+If some of your Items require different tax rates as compared to others, mention them in the Item tax table. Even if you have selected your sales and purchase taxes as default tax rates, the system will pull the Item tax rate for calculations. Item tax will get preference over other sales or purchase taxes. However, if you wish to apply default sales and purchase taxes, do not mention item tax rates in the Item master. The system will then select the sales or purchase tax rate specified by you as default rates.
+
+
+
+
- **Inclusive and Exclusive Tax**: ERPNext allows you to enter Item rates which are tax inclusive.
-- **Flat Discount**: This feature will be added soon.
- **Exception to the rule**: Item tax settings are required only if a particular Item has a different tax rate than the rate defined in the standard tax Account
-
-
+- **Item tax is overwrite-able**: You can overwrite or change the item tax rate by going to the Item master in the Item tax table.
## Sales Taxes and Charges Master
@@ -22,6 +26,8 @@
The way ERPNext sets up taxes is via templates. Other types of charges that may apply to your invoices (like shipping, insurance etc.) can also be configured as taxes.
+Select template and modify as per your need.
+
To create a new sales tax template called Sales Taxes and Charges Master, you have to go to:
> Setup > Accounts > Sales Taxes and Charge Master
@@ -38,9 +44,11 @@
In each row, you have to mention:
- Calculation Type:
- - This can be on net total (that is your basic amount).
- - On previous row total / amount (for cumulative taxes or charges). If you select this option, the tax will be applied as a percentage of the previous row (in the tax table) amount or total.
- - Actual (as mentioned).
+ - On Net Total : This can be on net total (total amount without taxes).
+ - On Previous Row Total/Amount: You can apply taxes on previous row total / amount. If you select this option, the tax will be applied as a percentage of the previous row (in the tax table) amount or total. Previous row amount means a particular tax amount.And, previous row total means net total plus taxes applied up to that row. In the Enter Row Field, mention row number on which you want to apply the current tax. If you want to apply the tax on the 3rd row, mention "3" in the Enter Row field.
+
+ - Actual : Enter as per actual amount in rate column.
+
- Account Head: The Account ledger under which this tax will be booked
- Cost Center: If the tax / charge is an income (like shipping) it needs to be booked against - a Cost Center.
- Description: Description of the tax (that will be printed in invoices / quotes).
diff --git a/docs/user/stock/docs.user.stock.item.md b/docs/user/stock/docs.user.stock.item.md
index f7746c4..14c1831 100644
--- a/docs/user/stock/docs.user.stock.item.md
+++ b/docs/user/stock/docs.user.stock.item.md
@@ -38,11 +38,11 @@
### Serialized and Batched Inventory
-These numbers help to track individual units or batches of Items which you sell. It also tracks warranty and returns. In case any individual Item is recalled by the supplier the number system helps to track individual Item. The numbering system also manages expiry dates. Please note that if you sell your items in thousands, and if the items are very small like pens or erasers, you need not serialize them. In ERPNext, you will have to mention the serial number in some accounting entries. To create serial numbers you will have to manually create all the numbers in your entries. If your product is not a big consumer durable Item, if it has no warranty and has no chances of being recalled, avoid giving serial numbers.
+These numbers help to track individual units or batches of Items which you sell. It also tracks warranty and returns. In case any individual Item is recalled by the supplier the number system helps to track individual Item. The numbering system also manages expiry dates. Please note that if you sell your items in thousands, and if the items are very small like pens or erasers, you need not serialize them. In ERPNext, you will have to mention the serial number in some accounting entries. To create serial numbers you will have to manually create all the numbers in your entries. If your product is not a big consumer durable Item, if it has no warranty and has no chances of being recalled, avoid giving serial numbers.
> Important: Once you mark an item as serialized or batched or neither, you cannot change it after you have made any stock entry.
-- [Disucssion on Serialized Inventory](docs.user.stock.serialized.html)
+- [Discussion on Serialized Inventory](docs.user.stock.serialized.html)
### Re Ordering
@@ -92,58 +92,4 @@
Visit [Manufacturing](docs.user.mfg.html) and [Website](docs.user.website.html) to understand these topics in detail.
-### Listing Item on Website
-
-To list your Item on the Website, fill the Item details and save the file. Once the file is saved, a plus (+) button will appear next to the Image icon. Click on the plus button and add your Item image. The html code will be generated automatically.
-
-##### Step 1: Save Image
-
-
-
-<br>
-
-##### Step 2: Check the 'Show in Website' box.
-
-Under the Website section, please check the box that says 'show in Website'. Once the box is checked, the page will display other fields for entering information.
-
-
-
-<br>
-
-
-##### Step 3: Enter Website Details
-
-
-
-
-The page name will be generated automatically. Mention the Item-Group under which the Item will be displayed.
-
-#### Item Groups
-
-Mention the Item Group under this column. If you wish to list your Item under the broad category products, name your Item Group as Products. In case you have various varieties of Item and want to classify them under different names, make Item Groups with those names and check the box that says 'show in Website'. For Example, if you wish to create a category called 'Bags', create a Item Group named Bags.
-
-
-
-
-Once the Item Group is created go to the Website Settings page under Website. Enter the Label, Url, and Parent Label.
-
-
-
-
-<br>
-
-#### Webpage labels
-
-
-
-Add more Items under a particular Item Group.
-
-To add more Items under a certain Label, mention the Item Group on the Item Page. The Items will be added automatically on the Webpage, under the Item Group Label. For Example, To add Item-Kiddies Bag and Butterfly Print Bag, check the 'Show in Website'box. The Items will be placed under the Label Bags on the Webpage.
-
-
-
-<br>
-
-Item Group Display
-
-
\ No newline at end of file
+To list your products on the website and understand this process in detail, visit [Product Listing On Website](docs.user.stock.product_listing_on_website.html)
diff --git a/docs/user/stock/docs.user.stock.md b/docs/user/stock/docs.user.stock.md
index a8c74c9..d0ab146 100644
--- a/docs/user/stock/docs.user.stock.md
+++ b/docs/user/stock/docs.user.stock.md
@@ -5,6 +5,7 @@
"docs.user.stock.warehouse",
"docs.user.stock.item_group",
"docs.user.stock.item",
+ "docs.user.stock.product_listing_on_website",
"docs.user.stock.serialized",
"docs.user.stock.purchase_receipt",
"docs.user.stock.delivery_note",
diff --git a/docs/user/stock/docs.user.stock.product_listing_on_website.md b/docs/user/stock/docs.user.stock.product_listing_on_website.md
new file mode 100644
index 0000000..6a544a1
--- /dev/null
+++ b/docs/user/stock/docs.user.stock.product_listing_on_website.md
@@ -0,0 +1,61 @@
+---
+{
+ "_label": "Product Listing on Website"
+}
+---
+
+### Listing Item on Website
+
+To list your Item on the Website, fill the Item details and save the file. Once the file is saved, a plus (+) button will appear next to the Image icon. Click on the plus button and add your Item image. The html code will be generated automatically.
+
+##### Step 1: Save Image
+
+
+
+<br>
+
+##### Step 2: Check the 'Show in Website' box.
+
+Under the Website section, please check the box that says 'show in Website'. Once the box is checked, the page will display other fields for entering information.
+
+
+
+<br>
+
+
+##### Step 3: Enter Website Details
+
+
+
+
+The page name will be generated automatically. Mention the Item-Group under which the Item will be displayed.
+
+#### Item Groups
+
+Mention the Item Group under this column. If you wish to list your Item under the broad category products, name your Item Group as Products. In case you have various varieties of Item and want to classify them under different names, make Item Groups with those names and check the box that says 'show in Website'. For Example, if you wish to create a category called 'Bags', create a Item Group named Bags.
+
+
+
+
+Once the Item Group is created go to the Website Settings page under Website. Enter the Label, Url, and Parent Label.
+
+
+
+
+<br>
+
+#### Webpage labels
+
+
+
+Add more Items under a particular Item Group.
+
+To add more Items under a certain Label, mention the Item Group on the Item Page. The Items will be added automatically on the Webpage, under the Item Group Label. For Example, To add Item-Kiddies Bag and Butterfly Print Bag, check the 'Show in Website'box. The Items will be placed under the Label Bags on the Webpage.
+
+
+
+<br>
+
+Item Group Display
+
+
\ No newline at end of file
diff --git a/home/page/latest_updates/latest_updates.py b/home/page/latest_updates/latest_updates.py
index 4eb208f..b4e3f44 100644
--- a/home/page/latest_updates/latest_updates.py
+++ b/home/page/latest_updates/latest_updates.py
@@ -14,6 +14,7 @@
out.seek(0)
last_commit = None
for l in out.readlines():
+ l = l.decode('utf-8')
if last_commit is not None:
if l.startswith("Date:"):
last_commit["date"] = l[8:-1]
@@ -59,4 +60,4 @@
lufile.write(json.dumps(logs, indent=1, sort_keys=True))
if __name__=="__main__":
- make()
\ No newline at end of file
+ make()
diff --git a/hr/doctype/employee/employee.py b/hr/doctype/employee/employee.py
index b46123a..56dfb35 100644
--- a/hr/doctype/employee/employee.py
+++ b/hr/doctype/employee/employee.py
@@ -20,12 +20,8 @@
webnotes.throw(_("Please setup Employee Naming System in Human Resource > HR Settings"))
else:
if naming_method=='Naming Series':
- if not self.doc.naming_series:
- webnotes.throw(_("Please select Naming Neries"))
self.doc.name = make_autoname(self.doc.naming_series + '.####')
elif naming_method=='Employee Number':
- if not self.doc.employee_number:
- webnotes.throw(_("Please enter Employee Number"))
self.doc.name = self.doc.employee_number
self.doc.employee = self.doc.name
diff --git a/hr/doctype/hr_settings/hr_settings.py b/hr/doctype/hr_settings/hr_settings.py
index 101905c..20edd16 100644
--- a/hr/doctype/hr_settings/hr_settings.py
+++ b/hr/doctype/hr_settings/hr_settings.py
@@ -13,12 +13,18 @@
self.doc, self.doclist = d, dl
def validate(self):
- self.original_stop_birthday_reminders = cint(webnotes.conn.get_value("HR Settings",
- None, "stop_birthday_reminders"))
+ self.update_birthday_reminders()
+
+ from setup.doctype.naming_series.naming_series import set_by_naming_series
+ set_by_naming_series("Employee", "employee_number",
+ self.doc.get("emp_created_by")=="Naming Series", hide_name_field=True)
- def on_update(self):
+ def update_birthday_reminders(self):
+ original_stop_birthday_reminders = cint(webnotes.conn.get_value("HR Settings",
+ None, "stop_birthday_reminders"))
+
# reset birthday reminders
- if cint(self.doc.stop_birthday_reminders) != self.original_stop_birthday_reminders:
+ if cint(self.doc.stop_birthday_reminders) != original_stop_birthday_reminders:
webnotes.conn.sql("""delete from `tabEvent` where repeat_on='Every Year' and ref_type='Employee'""")
if not self.doc.stop_birthday_reminders:
diff --git a/install_erpnext.py b/install_erpnext.py
index 79f79d7..7f3b8c3 100644
--- a/install_erpnext.py
+++ b/install_erpnext.py
@@ -332,9 +332,11 @@
stdout.seek(0)
out = stdout.read()
+ if out: out = out.decode('utf-8')
stderr.seek(0)
err = stderr.read()
+ if err: err = err.decode('utf-8')
if err and any((kw in err.lower() for kw in ["traceback", "error", "exception"])):
print out
@@ -345,4 +347,4 @@
return out
if __name__ == "__main__":
- install()
\ No newline at end of file
+ install()
diff --git a/manufacturing/doctype/bom/bom.py b/manufacturing/doctype/bom/bom.py
index 97a2f96..785851d 100644
--- a/manufacturing/doctype/bom/bom.py
+++ b/manufacturing/doctype/bom/bom.py
@@ -120,7 +120,7 @@
elif self.doc.rm_cost_as_per == "Price List":
if not self.doc.buying_price_list:
webnotes.throw(_("Please select Price List"))
- rate = webnotes.conn.get_value("Item Price", {"parent": self.doc.buying_price_list,
+ rate = webnotes.conn.get_value("Item Price", {"price_list": self.doc.buying_price_list,
"item_code": arg["item_code"]}, "ref_rate") or 0
elif self.doc.rm_cost_as_per == 'Standard Rate':
rate = arg['standard_rate']
@@ -413,7 +413,9 @@
ifnull(sum(bom_item.qty_consumed_per_unit),0) * %(qty)s as qty,
item.description,
item.stock_uom,
- item.default_warehouse
+ item.default_warehouse,
+ item.purchase_account as expense_account,
+ item.cost_center
from
`tab%(table)s` bom_item, `tabItem` item
where
@@ -452,4 +454,4 @@
def get_bom_items(bom, qty=1, fetch_exploded=1):
items = get_bom_items_as_dict(bom, qty, fetch_exploded).values()
items.sort(lambda a, b: a.item_code > b.item_code and 1 or -1)
- return items
\ No newline at end of file
+ return items
diff --git a/manufacturing/doctype/production_order/production_order.py b/manufacturing/doctype/production_order/production_order.py
index 36cbc64..9d4ff32 100644
--- a/manufacturing/doctype/production_order/production_order.py
+++ b/manufacturing/doctype/production_order/production_order.py
@@ -69,7 +69,7 @@
where parent = %s and item_code = %s""",
(self.doc.sales_order, self.doc.production_item))[0][0]
# get qty from Packing Item table
- dnpi_qty = webnotes.conn.sql("""select sum(qty) from `tabDelivery Note Packing Item`
+ dnpi_qty = webnotes.conn.sql("""select sum(qty) from `tabPacked Item`
where parent = %s and parenttype = 'Sales Order' and item_code = %s""",
(self.doc.sales_order, self.doc.production_item))[0][0]
# total qty in SO
diff --git a/manufacturing/doctype/production_planning_tool/production_planning_tool.py b/manufacturing/doctype/production_planning_tool/production_planning_tool.py
index 6f15d4c..277e53a 100644
--- a/manufacturing/doctype/production_planning_tool/production_planning_tool.py
+++ b/manufacturing/doctype/production_planning_tool/production_planning_tool.py
@@ -72,7 +72,7 @@
and (exists (select name from `tabItem` item where item.name=so_item.item_code
and (ifnull(item.is_pro_applicable, 'No') = 'Yes'
or ifnull(item.is_sub_contracted_item, 'No') = 'Yes') %s)
- or exists (select name from `tabDelivery Note Packing Item` dnpi
+ or exists (select name from `tabPacked Item` dnpi
where dnpi.parent = so.name and dnpi.parent_item = so_item.item_code
and exists (select name from `tabItem` item where item.name=dnpi.item_code
and (ifnull(item.is_pro_applicable, 'No') = 'Yes'
@@ -119,7 +119,7 @@
dnpi_items = webnotes.conn.sql("""select distinct dnpi.parent, dnpi.item_code, dnpi.warehouse as reserved_warhouse,
(((so_item.qty - ifnull(so_item.delivered_qty, 0)) * dnpi.qty) / so_item.qty)
as pending_qty
- from `tabSales Order Item` so_item, `tabDelivery Note Packing Item` dnpi
+ from `tabSales Order Item` so_item, `tabPacked Item` dnpi
where so_item.parent = dnpi.parent and so_item.docstatus = 1
and dnpi.parent_item = so_item.item_code
and so_item.parent in (%s) and ifnull(so_item.qty, 0) > ifnull(so_item.delivered_qty, 0)
diff --git a/patches/march_2013/p06_remove_sales_purchase_return_tool.py b/patches/march_2013/p06_remove_sales_purchase_return_tool.py
index ed8fbc8..ac11ecc 100644
--- a/patches/march_2013/p06_remove_sales_purchase_return_tool.py
+++ b/patches/march_2013/p06_remove_sales_purchase_return_tool.py
@@ -4,5 +4,7 @@
import webnotes
def execute():
- webnotes.delete_doc("DocType", "Sales and Purchase Return Item")
- webnotes.delete_doc("DocType", "Sales and Purchase Return Tool")
\ No newline at end of file
+ if webnotes.conn.exists("DocType", "Sales and Purchase Return Item"):
+ webnotes.delete_doc("DocType", "Sales and Purchase Return Item")
+ if webnotes.conn.exists("DocType", "Sales and Purchase Return Tool"):
+ webnotes.delete_doc("DocType", "Sales and Purchase Return Tool")
\ No newline at end of file
diff --git a/patches/november_2012/update_delivered_billed_percentage_for_pos.py b/patches/november_2012/update_delivered_billed_percentage_for_pos.py
index 0703f94..ffba0f9 100644
--- a/patches/november_2012/update_delivered_billed_percentage_for_pos.py
+++ b/patches/november_2012/update_delivered_billed_percentage_for_pos.py
@@ -3,10 +3,6 @@
def execute():
import webnotes
- from webnotes.model.code import get_obj
-
- #sc_obj = get_obj("Sales Common")
- from selling.doctype.sales_common import sales_common
si = webnotes.conn.sql("""select distinct si.name
from `tabSales Invoice` si, `tabSales Invoice Item` si_item
@@ -16,5 +12,4 @@
and ifnull(si_item.sales_order, '') != ''
""")
for d in si:
- sales_common.StatusUpdater(get_obj("Sales Invoice", d[0], with_children=1), \
- 1).update_all_qty()
\ No newline at end of file
+ webnotes.bean("Sales Invoice", d[0]).run_method("update_qty")
\ No newline at end of file
diff --git a/patches/october_2012/fix_cancelled_gl_entries.py b/patches/october_2012/fix_cancelled_gl_entries.py
index b610985..475ea1c 100644
--- a/patches/october_2012/fix_cancelled_gl_entries.py
+++ b/patches/october_2012/fix_cancelled_gl_entries.py
@@ -11,6 +11,7 @@
and docstatus=2""" % (entry['voucher_type'], "%s"), entry['voucher_no'])
is_cancelled = docstatus and 'Yes' or None
if is_cancelled:
+ print entry['voucher_type'], entry['voucher_no']
webnotes.conn.sql("""update `tabGL Entry` set is_cancelled = 'Yes'
where voucher_type = %s and voucher_no = %s""",
(entry['voucher_type'], entry['voucher_no']))
diff --git a/patches/october_2013/p02_update_price_list_and_item_details_in_item_price.py b/patches/october_2013/p02_update_price_list_and_item_details_in_item_price.py
new file mode 100644
index 0000000..209ebf3
--- /dev/null
+++ b/patches/october_2013/p02_update_price_list_and_item_details_in_item_price.py
@@ -0,0 +1,20 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import webnotes
+
+def execute():
+ webnotes.reload_doc("setup", "doctype", "item_price")
+
+ webnotes.conn.sql("""update `tabItem Price` ip, `tabItem` i
+ set ip.item_name=i.item_name, ip.item_description=i.description
+ 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""")
+
+ webnotes.conn.sql("""update `tabItem Price`
+ set parent=null, parenttype=null, parentfield=null, idx=null""")
\ No newline at end of file
diff --git a/patches/october_2013/p03_remove_sales_and_purchase_return_tool.py b/patches/october_2013/p03_remove_sales_and_purchase_return_tool.py
new file mode 100644
index 0000000..e0965ab
--- /dev/null
+++ b/patches/october_2013/p03_remove_sales_and_purchase_return_tool.py
@@ -0,0 +1,8 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+
+def execute():
+ from patches.march_2013 import p06_remove_sales_purchase_return_tool
+ p06_remove_sales_purchase_return_tool.execute()
\ No newline at end of file
diff --git a/patches/october_2013/p04_update_report_permission.py b/patches/october_2013/p04_update_report_permission.py
new file mode 100644
index 0000000..1a9f99d
--- /dev/null
+++ b/patches/october_2013/p04_update_report_permission.py
@@ -0,0 +1,9 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
+# License: GNU General Public License v3. See license.txt
+
+import webnotes
+
+def execute():
+ webnotes.conn.sql("""update tabDocPerm set `create`=1 where
+ parent='Report'
+ and role in ('Administrator', 'Report Manager', 'System Manager')""")
\ No newline at end of file
diff --git a/patches/october_2013/p05_delete_gl_entries_for_cancelled_vouchers.py b/patches/october_2013/p05_delete_gl_entries_for_cancelled_vouchers.py
new file mode 100644
index 0000000..1d8657a
--- /dev/null
+++ b/patches/october_2013/p05_delete_gl_entries_for_cancelled_vouchers.py
@@ -0,0 +1,16 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
+# License: GNU General Public License v3. See license.txt
+
+def execute():
+ import webnotes
+ entries = webnotes.conn.sql("""select voucher_type, voucher_no
+ from `tabGL Entry` group by voucher_type, voucher_no""", as_dict=1)
+ for entry in entries:
+ try:
+ cancelled_voucher = webnotes.conn.sql("""select name from `tab%s` where name = %s
+ and docstatus=2""" % (entry['voucher_type'], "%s"), entry['voucher_no'])
+ if cancelled_voucher:
+ webnotes.conn.sql("""delete from `tabGL Entry` where voucher_type = %s and
+ voucher_no = %s""", (entry['voucher_type'], entry['voucher_no']))
+ except:
+ pass
\ No newline at end of file
diff --git a/patches/october_2013/p06_rename_packing_list_doctype.py b/patches/october_2013/p06_rename_packing_list_doctype.py
new file mode 100644
index 0000000..d7c5c12
--- /dev/null
+++ b/patches/october_2013/p06_rename_packing_list_doctype.py
@@ -0,0 +1,21 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import webnotes, os
+
+def execute():
+ webnotes.reload_doc("core", "doctype", "doctype")
+
+ tables = webnotes.conn.sql_list("show tables")
+
+ if "tabPacked Item" not in tables:
+ webnotes.rename_doc("DocType", "Delivery Note Packing Item", "Packed Item", force=True)
+
+ webnotes.reload_doc("stock", "doctype", "packed_item")
+
+ if os.path.exists("app/stock/doctype/delivery_note_packing_item"):
+ os.system("rm -rf app/stock/doctype/delivery_note_packing_item")
+
+ if webnotes.conn.exists("DocType", "Delivery Note Packing Item"):
+ webnotes.delete_doc("DocType", "Delivery Note Packing Item")
\ No newline at end of file
diff --git a/patches/october_2013/p09_update_naming_series_settings.py b/patches/october_2013/p09_update_naming_series_settings.py
new file mode 100644
index 0000000..57b48da
--- /dev/null
+++ b/patches/october_2013/p09_update_naming_series_settings.py
@@ -0,0 +1,10 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import webnotes
+
+def execute():
+ # reset property setters for series
+ for name in ("Stock Settings", "Selling Settings", "Buying Settings", "HR Settings"):
+ webnotes.bean(name, name).save()
\ No newline at end of file
diff --git a/patches/patch_list.py b/patches/patch_list.py
index 9851986..5138b47 100644
--- a/patches/patch_list.py
+++ b/patches/patch_list.py
@@ -226,4 +226,12 @@
"patches.october_2013.p05_server_custom_script_to_file",
"patches.october_2013.repost_ordered_qty",
"patches.october_2013.repost_planned_qty",
+ "patches.october_2013.p06_rename_packing_list_doctype",
+ "execute:webnotes.delete_doc('DocType', 'Sales Common')",
+ "patches.october_2013.p09_update_naming_series_settings",
+ "patches.october_2013.p02_update_price_list_and_item_details_in_item_price",
+ "execute:webnotes.delete_doc('Report', 'Item-wise Price List')",
+ "patches.october_2013.p03_remove_sales_and_purchase_return_tool",
+ "patches.october_2013.p04_update_report_permission",
+ "patches.october_2013.p05_delete_gl_entries_for_cancelled_vouchers",
]
\ No newline at end of file
diff --git a/public/js/controllers/stock_controller.js b/public/js/controllers/stock_controller.js
index 6fe3815..01a73a2 100644
--- a/public/js/controllers/stock_controller.js
+++ b/public/js/controllers/stock_controller.js
@@ -18,6 +18,7 @@
}
},
+
show_general_ledger: function() {
var me = this;
if(this.frm.doc.docstatus===1 && cint(wn.defaults.get_default("auto_accounting_for_stock"))) {
@@ -30,5 +31,16 @@
wn.set_route("general-ledger");
});
}
+ },
+
+ copy_account_in_all_row: function(doc, dt, dn, fieldname) {
+ var d = locals[dt][dn];
+ if(d[fieldname]){
+ var cl = getchildren(this.frm.cscript.tname, doc.name, this.frm.cscript.fname, doc.doctype);
+ for(var i = 0; i < cl.length; i++) {
+ if(!cl[i][fieldname]) cl[i][fieldname] = d[fieldname];
+ }
+ }
+ refresh_field(this.frm.cscript.fname);
}
});
\ No newline at end of file
diff --git a/public/js/transaction.js b/public/js/transaction.js
index db93e9f..b120190 100644
--- a/public/js/transaction.js
+++ b/public/js/transaction.js
@@ -24,11 +24,9 @@
}, function(fieldname, value) {
if(me.frm.fields_dict[fieldname] && !me.frm.doc[fieldname])
me.frm.set_value(fieldname, value);
- });
-
- me.frm.script_manager.trigger("company");
+ });
}
-
+
if(this.other_fname) {
this[this.other_fname + "_remove"] = this.calculate_taxes_and_totals;
}
@@ -39,9 +37,9 @@
},
onload_post_render: function() {
- if(this.frm.doc.__islocal && this.frm.doc.company &&
- !this.frm.doc.customer && !this.frm.doc.is_pos) {
- var me = this;
+ var me = this;
+ if(this.frm.doc.__islocal && this.frm.doc.company && !this.frm.doc.is_pos) {
+ if(!this.frm.doc.customer || !this.frm.doc.supplier) {
return this.frm.call({
doc: this.frm.doc,
method: "onload_post_render",
@@ -50,8 +48,12 @@
// remove this call when using client side mapper
me.set_default_values();
me.set_dynamic_labels();
+ me.calculate_taxes_and_totals();
}
});
+ } else {
+ this.calculate_taxes_and_totals();
+ }
}
},
@@ -112,6 +114,40 @@
this.frm.refresh();
}
},
+
+ serial_no: function(doc, cdt, cdn) {
+ var me = this;
+ var item = wn.model.get_doc(cdt, cdn);
+
+ if (item.serial_no) {
+ if (!item.item_code) {
+ this.frm.script_manager.trigger("item_code", cdt, cdn);
+ }
+ else {
+ var sr_no = [];
+
+ // Replacing all occurences of comma with carriage return
+ var serial_nos = item.serial_no.trim().replace(/,/g, '\n');
+
+ serial_nos = serial_nos.trim().split('\n');
+
+ // Trim each string and push unique string to new list
+ for (var x=0; x<=serial_nos.length - 1; x++) {
+ if (serial_nos[x].trim() != "" && sr_no.indexOf(serial_nos[x].trim()) == -1) {
+ sr_no.push(serial_nos[x].trim());
+ }
+ }
+
+ // Add the new list to the serial no. field in grid with each in new line
+ item.serial_no = "";
+ for (var x=0; x<=sr_no.length - 1; x++)
+ item.serial_no += sr_no[x] + '\n';
+
+ refresh_field("serial_no", item.name, item.parentfield);
+ wn.model.set_value(item.doctype, item.name, "qty", sr_no.length);
+ }
+ }
+ },
validate: function() {
this.calculate_taxes_and_totals();
@@ -169,12 +205,12 @@
conversion_rate: function() {
if(this.frm.doc.currency === this.get_company_currency()) {
this.frm.set_value("conversion_rate", 1.0);
- } else if(this.frm.doc.currency === this.frm.doc.price_list_currency &&
+ }
+ if(this.frm.doc.currency === this.frm.doc.price_list_currency &&
this.frm.doc.plc_conversion_rate !== this.frm.doc.conversion_rate) {
this.frm.set_value("plc_conversion_rate", this.frm.doc.conversion_rate);
}
-
- this.calculate_taxes_and_totals();
+ if(flt(this.frm.doc.conversion_rate)>0.0) this.calculate_taxes_and_totals();
},
get_price_list_currency: function(buying_or_selling) {
@@ -224,7 +260,8 @@
plc_conversion_rate: function() {
if(this.frm.doc.price_list_currency === this.get_company_currency()) {
this.frm.set_value("plc_conversion_rate", 1.0);
- } else if(this.frm.doc.price_list_currency === this.frm.doc.currency) {
+ }
+ if(this.frm.doc.price_list_currency === this.frm.doc.currency) {
this.frm.set_value("conversion_rate", this.frm.doc.plc_conversion_rate);
this.calculate_taxes_and_totals();
}
diff --git a/public/js/utils.js b/public/js/utils.js
index e14a54c..2e5eea5 100644
--- a/public/js/utils.js
+++ b/public/js/utils.js
@@ -13,7 +13,7 @@
},
hide_naming_series: function() {
- if(cur_frm.fields_dict.naming_series) {
+ if(cur_frm.fields_dict.naming_series && !wn.meta.get_docfield(cur_frm.doctype, "naming_series")) {
cur_frm.toggle_display("naming_series", cur_frm.doc.__islocal?true:false);
}
},
diff --git a/selling/doctype/customer/customer.js b/selling/doctype/customer/customer.js
index ef02d46..0828adf 100644
--- a/selling/doctype/customer/customer.js
+++ b/selling/doctype/customer/customer.js
@@ -20,10 +20,7 @@
cur_frm.cscript.refresh = function(doc,dt,dn) {
cur_frm.cscript.setup_dashboard(doc);
- if(sys_defaults.cust_master_name == 'Customer Name')
- hide_field('naming_series');
- else
- unhide_field('naming_series');
+ erpnext.hide_naming_series();
if(doc.__islocal){
hide_field(['address_html','contact_html']);
diff --git a/selling/doctype/customer/customer.txt b/selling/doctype/customer/customer.txt
index b25c0bd..5d3a508 100644
--- a/selling/doctype/customer/customer.txt
+++ b/selling/doctype/customer/customer.txt
@@ -2,7 +2,7 @@
{
"creation": "2013-06-11 14:26:44",
"docstatus": 0,
- "modified": "2013-09-10 10:50:50",
+ "modified": "2013-10-18 16:49:20",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -50,6 +50,16 @@
},
{
"doctype": "DocField",
+ "fieldname": "naming_series",
+ "fieldtype": "Select",
+ "label": "Document Numbering Series",
+ "no_copy": 1,
+ "options": "\nCUST\nCUSTMUM",
+ "permlevel": 0,
+ "print_hide": 0
+ },
+ {
+ "doctype": "DocField",
"fieldname": "customer_name",
"fieldtype": "Data",
"hidden": 0,
@@ -77,16 +87,6 @@
"reqd": 1
},
{
- "doctype": "DocField",
- "fieldname": "naming_series",
- "fieldtype": "Select",
- "label": "Document Numbering Series",
- "no_copy": 1,
- "options": "\nCUST\nCUSTMUM",
- "permlevel": 0,
- "print_hide": 0
- },
- {
"description": "Fetch lead which will be converted into customer.",
"doctype": "DocField",
"fieldname": "lead_name",
diff --git a/selling/doctype/installation_note/installation_note.py b/selling/doctype/installation_note/installation_note.py
index 02b7247..17c3691 100644
--- a/selling/doctype/installation_note/installation_note.py
+++ b/selling/doctype/installation_note/installation_note.py
@@ -6,7 +6,6 @@
from webnotes.utils import cstr, getdate
from webnotes.model.bean import getlist
-from webnotes.model.code import get_obj
from webnotes import msgprint
from stock.utils import get_valid_serial_nos
@@ -36,8 +35,9 @@
self.validate_fiscal_year()
self.validate_installation_date()
self.check_item_table()
- sales_com_obj = get_obj(dt = 'Sales Common')
- sales_com_obj.check_active_sales_items(self)
+
+ from controllers.selling_controller import check_active_sales_items
+ check_active_sales_items(self)
def validate_fiscal_year(self):
from accounts.utils import validate_fiscal_year
diff --git a/selling/doctype/opportunity/opportunity.py b/selling/doctype/opportunity/opportunity.py
index 37672f2..ecba077 100644
--- a/selling/doctype/opportunity/opportunity.py
+++ b/selling/doctype/opportunity/opportunity.py
@@ -59,16 +59,6 @@
msgprint("Customer : %s does not exist in system." % (name))
raise Exception
- def get_contact_details(self, arg):
- arg = eval(arg)
- contact = webnotes.conn.sql("select contact_no, email_id from `tabContact` where contact_name = '%s' and customer_name = '%s'" %(arg['contact_person'],arg['customer']), as_dict = 1)
- ret = {
- 'contact_no' : contact and contact[0]['contact_no'] or '',
- 'email_id' : contact and contact[0]['email_id'] or ''
- }
- return ret
-
-
def on_update(self):
self.add_calendar_event()
diff --git a/selling/doctype/quotation/quotation.js b/selling/doctype/quotation/quotation.js
index a104f34..7761672 100644
--- a/selling/doctype/quotation/quotation.js
+++ b/selling/doctype/quotation/quotation.js
@@ -10,7 +10,7 @@
wn.require('app/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js');
wn.require('app/utilities/doctype/sms_control/sms_control.js');
-wn.require('app/selling/doctype/sales_common/sales_common.js');
+wn.require('app/selling/sales_common.js');
wn.require('app/accounts/doctype/sales_invoice/pos.js');
erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({
diff --git a/selling/doctype/quotation/quotation.py b/selling/doctype/quotation/quotation.py
index 78afb97..5353127 100644
--- a/selling/doctype/quotation/quotation.py
+++ b/selling/doctype/quotation/quotation.py
@@ -19,46 +19,10 @@
self.doclist = doclist
self.tname = 'Quotation Item'
self.fname = 'quotation_details'
-
- # Get contact person details based on customer selected
- # ------------------------------------------------------
- def get_contact_details(self):
- return get_obj('Sales Common').get_contact_details(self,0)
-
- # Get Item Details
- # -----------------
- def get_item_details(self, args=None):
- import json
- args = args and json.loads(args) or {}
- if args.get('item_code'):
- return get_obj('Sales Common').get_item_details(args, self)
- else:
- obj = get_obj('Sales Common')
- for doc in self.doclist:
- if doc.fields.get('item_code'):
- arg = {
- 'item_code': doc.fields.get('item_code'),
- 'income_account': doc.fields.get('income_account'),
- 'cost_center': doc.fields.get('cost_center'),
- 'warehouse': doc.fields.get('warehouse')
- }
- res = obj.get_item_details(arg, self) or {}
- for r in res:
- if not doc.fields.get(r):
- doc.fields[r] = res[r]
-
def has_sales_order(self):
return webnotes.conn.get_value("Sales Order Item", {"prevdoc_docname": self.doc.name, "docstatus": 1})
-
-
- # Re-calculates Basic Rate & amount based on Price List Selected
- # --------------------------------------------------------------
- def get_adj_percent(self, arg=''):
- get_obj('Sales Common').get_adj_percent(self)
-
- # Does not allow same item code to be entered twice
- # -------------------------------------------------
+
def validate_for_items(self):
chk_dupl_itm = []
for d in getlist(self.doclist,'quotation_details'):
@@ -68,9 +32,6 @@
else:
chk_dupl_itm.append([cstr(d.item_code),cstr(d.description)])
-
- #do not allow sales item in maintenance quotation and service item in sales quotation
- #-----------------------------------------------------------------------------------------------
def validate_order_type(self):
super(DocType, self).validate_order_type()
@@ -96,22 +57,12 @@
self.set_status()
self.validate_order_type()
self.validate_for_items()
-
self.validate_uom_is_integer("stock_uom", "qty")
- sales_com_obj = get_obj('Sales Common')
- sales_com_obj.check_active_sales_items(self)
- sales_com_obj.validate_max_discount(self,'quotation_details')
- sales_com_obj.check_conversion_rate(self)
-
- #update enquiry
- #------------------
def update_opportunity(self):
for opportunity in self.doclist.get_distinct_values("prevdoc_docname"):
webnotes.bean("Opportunity", opportunity).get_controller().set_status(update=True)
- # declare as order lost
- #-------------------------
def declare_order_lost(self, arg):
if not self.has_sales_order():
webnotes.conn.set(self.doc, 'status', 'Lost')
@@ -120,15 +71,11 @@
else:
webnotes.throw(_("Cannot set as Lost as Sales Order is made."))
- #check if value entered in item table
- #--------------------------------------
def check_item_table(self):
if not getlist(self.doclist, 'quotation_details'):
msgprint("Please enter item details")
raise Exception
- # ON SUBMIT
- # =========================================================================
def on_submit(self):
self.check_item_table()
@@ -138,16 +85,11 @@
#update enquiry status
self.update_opportunity()
-
-# ON CANCEL
-# ==========================================================================
def on_cancel(self):
#update enquiry status
self.set_status()
self.update_opportunity()
-# Print other charges
-# ===========================================================================
def print_other_charges(self,docname):
print_lst = []
for d in getlist(self.doclist,'other_charges'):
diff --git a/selling/doctype/sales_common/README.md b/selling/doctype/sales_common/README.md
deleted file mode 100644
index 1c029d2..0000000
--- a/selling/doctype/sales_common/README.md
+++ /dev/null
@@ -1 +0,0 @@
-Common scripts used in Sales Cycle.
\ No newline at end of file
diff --git a/selling/doctype/sales_common/__init__.py b/selling/doctype/sales_common/__init__.py
deleted file mode 100644
index baffc48..0000000
--- a/selling/doctype/sales_common/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/selling/doctype/sales_common/sales_common.py b/selling/doctype/sales_common/sales_common.py
deleted file mode 100644
index 01718dd..0000000
--- a/selling/doctype/sales_common/sales_common.py
+++ /dev/null
@@ -1,331 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import webnotes
-
-from webnotes.utils import cint, cstr, flt
-from webnotes.model.doc import addchild
-from webnotes.model.bean import getlist
-from webnotes.model.code import get_obj
-from webnotes import msgprint, _
-from setup.utils import get_company_currency
-
-get_value = webnotes.conn.get_value
-
-from utilities.transaction_base import TransactionBase
-
-class DocType(TransactionBase):
- def __init__(self,d,dl):
- self.doc, self.doclist = d, dl
-
-
- def get_contact_details(self, obj = '', primary = 0):
- cond = " and contact_name = '"+cstr(obj.doc.contact_person)+"'"
- if primary: cond = " and is_primary_contact = 'Yes'"
- contact = webnotes.conn.sql("select contact_name, contact_no, email_id, contact_address from `tabContact` where customer = '%s' and docstatus != 2 %s" %(obj.doc.customer, cond), as_dict = 1)
- if not contact:
- return
- c = contact[0]
- obj.doc.contact_person = c['contact_name'] or ''
- obj.doc.contact_no = c['contact_no'] or ''
- obj.doc.email_id = c['email_id'] or ''
- obj.doc.customer_mobile_no = c['contact_no'] or ''
- if c['contact_address']:
- obj.doc.customer_address = c['contact_address']
-
- def get_invoice_details(self, obj = ''):
- if obj.doc.company:
- acc_head = webnotes.conn.sql("select name from `tabAccount` where name = '%s' and docstatus != 2" % (cstr(obj.doc.customer) + " - " + webnotes.conn.get_value('Company', obj.doc.company, 'abbr')))
- obj.doc.debit_to = acc_head and acc_head[0][0] or ''
-
- def get_tax_details(self, item_code, obj):
- import json
- tax = webnotes.conn.sql("select tax_type, tax_rate from `tabItem Tax` where parent = %s" , item_code)
- t = {}
- for x in tax: t[x[0]] = flt(x[1])
- ret = {
- 'item_tax_rate' : tax and json.dumps(t) or ''
- }
- return ret
-
- def get_serial_details(self, serial_no, obj):
- import json
- item = webnotes.conn.sql("select item_code, make, label,brand, description from `tabSerial No` where name = '%s' and docstatus != 2" %(serial_no), as_dict=1)
- tax = webnotes.conn.sql("select tax_type, tax_rate from `tabItem Tax` where parent = %s" , item[0]['item_code'])
- t = {}
- for x in tax: t[x[0]] = flt(x[1])
- ret = {
- 'item_code' : item and item[0]['item_code'] or '',
- 'make' : item and item[0]['make'] or '',
- 'label' : item and item[0]['label'] or '',
- 'brand' : item and item[0]['brand'] or '',
- 'description' : item and item[0]['description'] or '',
- 'item_tax_rate' : json.dumps(t)
- }
- return ret
-
- # To verify whether rate entered in details table does not exceed max discount %
- # =======================================================================================
- def validate_max_discount(self,obj, detail_table):
- for d in getlist(obj.doclist, detail_table):
- discount = webnotes.conn.sql("select max_discount from tabItem where name = '%s'" %(d.item_code),as_dict = 1)
- if discount and discount[0]['max_discount'] and (flt(d.adj_rate)>flt(discount[0]['max_discount'])):
- msgprint("You cannot give more than " + cstr(discount[0]['max_discount']) + " % discount on Item Code : "+cstr(d.item_code))
- raise Exception
-
- # Check Conversion Rate (i.e. it will not allow conversion rate to be 1 for Currency other than default currency set in Global Defaults)
- # ===========================================================================
- def check_conversion_rate(self, obj):
- default_currency = get_company_currency(obj.doc.company)
- if not default_currency:
- msgprint('Message: Please enter default currency in Company Master')
- raise Exception
- if (obj.doc.currency == default_currency and flt(obj.doc.conversion_rate) != 1.00) or not obj.doc.conversion_rate or (obj.doc.currency != default_currency and flt(obj.doc.conversion_rate) == 1.00):
- msgprint("Please Enter Appropriate Conversion Rate for Customer's Currency to Base Currency (%s --> %s)" % (obj.doc.currency, default_currency), raise_exception = 1)
-
- if (obj.doc.price_list_currency == default_currency and flt(obj.doc.plc_conversion_rate) != 1.00) or not obj.doc.plc_conversion_rate or (obj.doc.price_list_currency != default_currency and flt(obj.doc.plc_conversion_rate) == 1.00):
- msgprint("Please Enter Appropriate Conversion Rate for Price List Currency to Base Currency (%s --> %s)" % (obj.doc.price_list_currency, default_currency), raise_exception = 1)
-
- def get_item_list(self, obj, is_stopped=0):
- """get item list"""
- il = []
- for d in getlist(obj.doclist, obj.fname):
- reserved_warehouse = ""
- reserved_qty_for_main_item = 0
-
- if obj.doc.doctype == "Sales Order":
- if (webnotes.conn.get_value("Item", d.item_code, "is_stock_item") == 'Yes' or
- self.has_sales_bom(d.item_code)) and not d.reserved_warehouse:
- webnotes.throw(_("Please enter Reserved Warehouse for item ") +
- d.item_code + _(" as it is stock Item or packing item"))
- reserved_warehouse = d.reserved_warehouse
- if flt(d.qty) > flt(d.delivered_qty):
- reserved_qty_for_main_item = flt(d.qty) - flt(d.delivered_qty)
-
- if obj.doc.doctype == "Delivery Note" and d.against_sales_order:
- # if SO qty is 10 and there is tolerance of 20%, then it will allow DN of 12.
- # But in this case reserved qty should only be reduced by 10 and not 12
-
- already_delivered_qty = self.get_already_delivered_qty(obj.doc.name,
- d.against_sales_order, d.prevdoc_detail_docname)
- so_qty, reserved_warehouse = self.get_so_qty_and_warehouse(d.prevdoc_detail_docname)
-
- if already_delivered_qty + d.qty > so_qty:
- reserved_qty_for_main_item = -(so_qty - already_delivered_qty)
- else:
- reserved_qty_for_main_item = -flt(d.qty)
-
- if self.has_sales_bom(d.item_code):
- for p in getlist(obj.doclist, 'packing_details'):
- if p.parent_detail_docname == d.name and p.parent_item == d.item_code:
- # the packing details table's qty is already multiplied with parent's qty
- il.append(webnotes._dict({
- 'warehouse': p.warehouse,
- 'reserved_warehouse': reserved_warehouse,
- 'item_code': p.item_code,
- 'qty': flt(p.qty),
- 'reserved_qty': (flt(p.qty)/flt(d.qty)) * reserved_qty_for_main_item,
- 'uom': p.uom,
- 'batch_no': cstr(p.batch_no).strip(),
- 'serial_no': cstr(p.serial_no).strip(),
- 'name': d.name
- }))
- else:
- il.append(webnotes._dict({
- 'warehouse': d.warehouse,
- 'reserved_warehouse': reserved_warehouse,
- 'item_code': d.item_code,
- 'qty': d.qty,
- 'reserved_qty': reserved_qty_for_main_item,
- 'uom': d.stock_uom,
- 'batch_no': cstr(d.batch_no).strip(),
- 'serial_no': cstr(d.serial_no).strip(),
- 'name': d.name
- }))
- return il
-
- def get_already_delivered_qty(self, dn, so, so_detail):
- qty = webnotes.conn.sql("""select sum(qty) from `tabDelivery Note Item`
- where prevdoc_detail_docname = %s and docstatus = 1
- and against_sales_order = %s
- and parent != %s""", (so_detail, so, dn))
- return qty and flt(qty[0][0]) or 0.0
-
- def get_so_qty_and_warehouse(self, so_detail):
- so_item = webnotes.conn.sql("""select qty, reserved_warehouse from `tabSales Order Item`
- where name = %s and docstatus = 1""", so_detail, as_dict=1)
- so_qty = so_item and flt(so_item[0]["qty"]) or 0.0
- so_warehouse = so_item and so_item[0]["reserved_warehouse"] or ""
- return so_qty, so_warehouse
-
- def has_sales_bom(self, item_code):
- return webnotes.conn.sql("select name from `tabSales BOM` where new_item_code=%s and docstatus != 2", item_code)
-
- def get_sales_bom_items(self, item_code):
- return webnotes.conn.sql("""select t1.item_code, t1.qty, t1.uom
- from `tabSales BOM Item` t1, `tabSales BOM` t2
- where t2.new_item_code=%s and t1.parent = t2.name""", item_code, as_dict=1)
-
- def get_packing_item_details(self, item):
- return webnotes.conn.sql("select item_name, description, stock_uom from `tabItem` where name = %s", item, as_dict = 1)[0]
-
- def get_bin_qty(self, item, warehouse):
- det = webnotes.conn.sql("select actual_qty, projected_qty from `tabBin` where item_code = '%s' and warehouse = '%s'" % (item, warehouse), as_dict = 1)
- return det and det[0] or ''
-
- def update_packing_list_item(self,obj, packing_item_code, qty, warehouse, line):
- bin = self.get_bin_qty(packing_item_code, warehouse)
- item = self.get_packing_item_details(packing_item_code)
-
- # check if exists
- exists = 0
- for d in getlist(obj.doclist, 'packing_details'):
- if d.parent_item == line.item_code and d.item_code == packing_item_code and d.parent_detail_docname == line.name:
- pi, exists = d, 1
- break
-
- if not exists:
- pi = addchild(obj.doc, 'packing_details', 'Delivery Note Packing Item',
- obj.doclist)
-
- pi.parent_item = line.item_code
- pi.item_code = packing_item_code
- pi.item_name = item['item_name']
- pi.parent_detail_docname = line.name
- pi.description = item['description']
- pi.uom = item['stock_uom']
- pi.qty = flt(qty)
- pi.actual_qty = bin and flt(bin['actual_qty']) or 0
- pi.projected_qty = bin and flt(bin['projected_qty']) or 0
- if not pi.warehouse:
- pi.warehouse = warehouse
- if not pi.batch_no:
- pi.batch_no = cstr(line.batch_no)
- pi.idx = self.packing_list_idx
-
- # saved, since this function is called on_update of delivery note
- pi.save()
-
- self.packing_list_idx += 1
-
-
- def make_packing_list(self, obj, fname):
- """make packing list for sales bom item"""
- self.packing_list_idx = 0
- parent_items = []
- for d in getlist(obj.doclist, fname):
- warehouse = fname == "sales_order_details" and d.reserved_warehouse or d.warehouse
- if self.has_sales_bom(d.item_code):
- for i in self.get_sales_bom_items(d.item_code):
- self.update_packing_list_item(obj, i['item_code'], flt(i['qty'])*flt(d.qty), warehouse, d)
-
- if [d.item_code, d.name] not in parent_items:
- parent_items.append([d.item_code, d.name])
-
- obj.doclist = self.cleanup_packing_list(obj, parent_items)
-
- return obj.doclist
-
- def cleanup_packing_list(self, obj, parent_items):
- """Remove all those child items which are no longer present in main item table"""
- delete_list = []
- for d in getlist(obj.doclist, 'packing_details'):
- if [d.parent_item, d.parent_detail_docname] not in parent_items:
- # mark for deletion from doclist
- delete_list.append(d.name)
-
- if not delete_list:
- return obj.doclist
-
- # delete from doclist
- obj.doclist = webnotes.doclist(filter(lambda d: d.name not in delete_list, obj.doclist))
-
- # delete from db
- webnotes.conn.sql("""\
- delete from `tabDelivery Note Packing Item`
- where name in (%s)"""
- % (", ".join(["%s"] * len(delete_list))),
- tuple(delete_list))
-
- return obj.doclist
-
-
- def get_month(self,date):
- """Get month based on date (required in sales person and sales partner)"""
- month_list = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
- month_idx = cint(cstr(date).split('-')[1])-1
- return month_list[month_idx]
-
-
- # **** Check for Stop SO as no transactions can be made against Stopped SO. Need to unstop it. ***
- def check_stop_sales_order(self,obj):
- for d in getlist(obj.doclist,obj.fname):
- ref_doc_name = ''
- if d.fields.has_key('against_sales_order') and d.against_sales_order:
- ref_doc_name = d.against_sales_order
- elif d.fields.has_key('sales_order') and d.sales_order and not d.delivery_note:
- ref_doc_name = d.sales_order
- if ref_doc_name:
- so_status = webnotes.conn.sql("select status from `tabSales Order` where name = %s",ref_doc_name)
- so_status = so_status and so_status[0][0] or ''
- if so_status == 'Stopped':
- msgprint("You cannot do any transaction against Sales Order : '%s' as it is Stopped." %(ref_doc_name))
- raise Exception
-
- def check_active_sales_items(self,obj):
- for d in getlist(obj.doclist, obj.fname):
- if d.item_code:
- item = webnotes.conn.sql("""select docstatus, is_sales_item,
- is_service_item, default_income_account from tabItem where name = %s""",
- d.item_code, as_dict=True)[0]
- if item.is_sales_item == 'No' and item.is_service_item == 'No':
- msgprint("Item : '%s' is neither Sales nor Service Item" % (d.item_code))
- raise Exception
- if d.income_account and not item.default_income_account:
- webnotes.conn.set_value("Item", d.item_code, "default_income_account", d.income_account)
-
-
- def check_credit(self,obj,grand_total):
- acc_head = webnotes.conn.sql("select name from `tabAccount` where company = '%s' and master_name = '%s'"%(obj.doc.company, obj.doc.customer))
- if acc_head:
- tot_outstanding = 0
- dbcr = webnotes.conn.sql("""select sum(debit), sum(credit) from `tabGL Entry`
- where account = %s""", acc_head[0][0])
- if dbcr:
- tot_outstanding = flt(dbcr[0][0])-flt(dbcr[0][1])
-
- exact_outstanding = flt(tot_outstanding) + flt(grand_total)
- get_obj('Account',acc_head[0][0]).check_credit_limit(acc_head[0][0], obj.doc.company, exact_outstanding)
-
-def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
- from controllers.queries import get_match_cond
-
- if filters.has_key('warehouse'):
- return webnotes.conn.sql("""select batch_no from `tabStock Ledger Entry` sle
- where item_code = '%(item_code)s'
- and warehouse = '%(warehouse)s'
- and batch_no like '%(txt)s'
- and exists(select * from `tabBatch`
- where name = sle.batch_no
- and (ifnull(expiry_date, '')='' or expiry_date >= '%(posting_date)s')
- and docstatus != 2)
- %(mcond)s
- group by batch_no having sum(actual_qty) > 0
- order by batch_no desc
- limit %(start)s, %(page_len)s """ % {'item_code': filters['item_code'],
- 'warehouse': filters['warehouse'], 'posting_date': filters['posting_date'],
- 'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype, searchfield),
- 'start': start, 'page_len': page_len})
- else:
- return webnotes.conn.sql("""select name from tabBatch
- where docstatus != 2
- and item = '%(item_code)s'
- and (ifnull(expiry_date, '')='' or expiry_date >= '%(posting_date)s')
- and name like '%(txt)s'
- %(mcond)s
- order by name desc
- limit %(start)s, %(page_len)s""" % {'item_code': filters['item_code'],
- 'posting_date': filters['posting_date'], 'txt': "%%%s%%" % txt,
- 'mcond':get_match_cond(doctype, searchfield),'start': start,
- 'page_len': page_len})
diff --git a/selling/doctype/sales_common/sales_common.txt b/selling/doctype/sales_common/sales_common.txt
deleted file mode 100644
index a407493..0000000
--- a/selling/doctype/sales_common/sales_common.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-[
- {
- "creation": "2012-03-27 14:36:14",
- "docstatus": 0,
- "modified": "2013-07-10 14:54:19",
- "modified_by": "Administrator",
- "owner": "Administrator"
- },
- {
- "doctype": "DocType",
- "issingle": 1,
- "module": "Selling",
- "name": "__common__"
- },
- {
- "doctype": "DocType",
- "name": "Sales Common"
- }
-]
\ No newline at end of file
diff --git a/selling/doctype/sales_order/sales_order.js b/selling/doctype/sales_order/sales_order.js
index bf23b9c..4033870 100644
--- a/selling/doctype/sales_order/sales_order.js
+++ b/selling/doctype/sales_order/sales_order.js
@@ -9,7 +9,7 @@
cur_frm.cscript.sales_team_fname = "sales_team";
-wn.require('app/selling/doctype/sales_common/sales_common.js');
+wn.require('app/selling/sales_common.js');
wn.require('app/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js');
wn.require('app/utilities/doctype/sms_control/sms_control.js');
wn.require('app/accounts/doctype/sales_invoice/pos.js');
diff --git a/selling/doctype/sales_order/sales_order.py b/selling/doctype/sales_order/sales_order.py
index 1c22c08..7bad121 100644
--- a/selling/doctype/sales_order/sales_order.py
+++ b/selling/doctype/sales_order/sales_order.py
@@ -11,8 +11,6 @@
from webnotes import msgprint
from webnotes.model.mapper import get_mapped_doclist
-
-
from controllers.selling_controller import SellingController
class DocType(SellingController):
@@ -26,18 +24,6 @@
self.partner_tname = 'Partner Target Detail'
self.territory_tname = 'Territory Target Detail'
- def get_contact_details(self):
- get_obj('Sales Common').get_contact_details(self,0)
-
- def get_comm_rate(self, sales_partner):
- return get_obj('Sales Common').get_comm_rate(sales_partner, self)
-
- def get_adj_percent(self, arg=''):
- get_obj('Sales Common').get_adj_percent(self)
-
- def get_available_qty(self,args):
- return get_obj('Sales Common').get_available_qty(eval(args))
-
def validate_mandatory(self):
# validate transaction date v/s delivery date
if self.doc.delivery_date:
@@ -124,13 +110,10 @@
self.validate_uom_is_integer("stock_uom", "qty")
self.validate_for_items()
self.validate_warehouse()
- sales_com_obj = get_obj(dt = 'Sales Common')
- sales_com_obj.check_active_sales_items(self)
- sales_com_obj.check_conversion_rate(self)
- sales_com_obj.validate_max_discount(self,'sales_order_details')
- self.doclist = sales_com_obj.make_packing_list(self,'sales_order_details')
-
+ from stock.doctype.packed_item.packed_item import make_packing_list
+ self.doclist = make_packing_list(self,'sales_order_details')
+
self.validate_with_previous_doc()
if not self.doc.status:
@@ -172,14 +155,14 @@
for quotation in self.doclist.get_distinct_values("prevdoc_docname"):
bean = webnotes.bean("Quotation", quotation)
if bean.doc.docstatus==2:
- webnotes.throw(d.prevdoc_docname + ": " + webnotes._("Quotation is cancelled."))
+ webnotes.throw(quotation + ": " + webnotes._("Quotation is cancelled."))
bean.get_controller().set_status(update=True)
def on_submit(self):
self.update_stock_ledger(update_stock = 1)
- get_obj('Sales Common').check_credit(self,self.doc.grand_total)
+ self.check_credit(self.doc.grand_total)
get_obj('Authorization Control').validate_approving_authority(self.doc.doctype, self.doc.grand_total, self)
@@ -235,21 +218,21 @@
def stop_sales_order(self):
self.check_modified_date()
- self.update_stock_ledger(update_stock = -1,is_stopped = 1)
+ self.update_stock_ledger(-1)
webnotes.conn.set(self.doc, 'status', 'Stopped')
msgprint("""%s: %s has been Stopped. To make transactions against this Sales Order
you need to Unstop it.""" % (self.doc.doctype, self.doc.name))
def unstop_sales_order(self):
self.check_modified_date()
- self.update_stock_ledger(update_stock = 1,is_stopped = 1)
+ self.update_stock_ledger(1)
webnotes.conn.set(self.doc, 'status', 'Submitted')
msgprint("%s: %s has been Unstopped" % (self.doc.doctype, self.doc.name))
- def update_stock_ledger(self, update_stock, is_stopped = 0):
+ def update_stock_ledger(self, update_stock):
from stock.utils import update_bin
- for d in self.get_item_list(is_stopped):
+ for d in self.get_item_list():
if webnotes.conn.get_value("Item", d['item_code'], "is_stock_item") == "Yes":
args = {
"item_code": d['item_code'],
@@ -261,10 +244,6 @@
"is_amended": self.doc.amended_from and 'Yes' or 'No'
}
update_bin(args)
-
-
- def get_item_list(self, is_stopped):
- return get_obj('Sales Common').get_item_list( self, is_stopped)
def on_update(self):
pass
diff --git a/selling/doctype/sales_order/sales_order.txt b/selling/doctype/sales_order/sales_order.txt
index c27f8ff..bfbcd94 100644
--- a/selling/doctype/sales_order/sales_order.txt
+++ b/selling/doctype/sales_order/sales_order.txt
@@ -361,7 +361,7 @@
"label": "Packing Details",
"oldfieldname": "packing_details",
"oldfieldtype": "Table",
- "options": "Delivery Note Packing Item",
+ "options": "Packed Item",
"print_hide": 1,
"read_only": 1
},
diff --git a/selling/doctype/selling_settings/selling_settings.py b/selling/doctype/selling_settings/selling_settings.py
index 9386652..620721d 100644
--- a/selling/doctype/selling_settings/selling_settings.py
+++ b/selling/doctype/selling_settings/selling_settings.py
@@ -14,3 +14,7 @@
for key in ["cust_master_name", "customer_group", "territory", "maintain_same_sales_rate",
"editable_price_list_rate", "selling_price_list"]:
webnotes.conn.set_default(key, self.doc.fields.get(key, ""))
+
+ from setup.doctype.naming_series.naming_series import set_by_naming_series
+ set_by_naming_series("Customer", "customer_name",
+ self.doc.get("cust_master_name")=="Naming Series", hide_name_field=False)
diff --git a/selling/page/selling_home/selling_home.js b/selling/page/selling_home/selling_home.js
index 6e6283d..ad264c9 100644
--- a/selling/page/selling_home/selling_home.js
+++ b/selling/page/selling_home/selling_home.js
@@ -83,10 +83,15 @@
},
{
label: wn._("Price List"),
- description: wn._("Mupltiple Item prices."),
+ description: wn._("Multiple Price list."),
doctype:"Price List"
},
{
+ label: wn._("Item Price"),
+ description: wn._("Multiple Item prices."),
+ doctype:"Item Price"
+ },
+ {
label: wn._("Sales BOM"),
description: wn._("Bundle items at time of sale."),
doctype:"Sales BOM"
@@ -167,6 +172,11 @@
icon: "icon-list",
items: [
{
+ "label":wn._("Lead Details"),
+ route: "query-report/Lead Details",
+ doctype: "Lead"
+ },
+ {
"label":wn._("Customer Addresses And Contacts"),
route: "query-report/Customer Addresses And Contacts",
doctype: "Contact"
diff --git a/setup/report/item_wise_price_list/__init__.py b/selling/report/lead_details/__init__.py
similarity index 100%
rename from setup/report/item_wise_price_list/__init__.py
rename to selling/report/lead_details/__init__.py
diff --git a/selling/report/lead_details/lead_details.txt b/selling/report/lead_details/lead_details.txt
new file mode 100644
index 0000000..6da9b79
--- /dev/null
+++ b/selling/report/lead_details/lead_details.txt
@@ -0,0 +1,22 @@
+[
+ {
+ "creation": "2013-10-22 11:58:16",
+ "docstatus": 0,
+ "modified": "2013-10-22 12:08:18",
+ "modified_by": "Administrator",
+ "owner": "Administrator"
+ },
+ {
+ "doctype": "Report",
+ "is_standard": "Yes",
+ "name": "__common__",
+ "query": "SELECT\n `tabLead`.name as \"Lead Id:Link/Lead:120\",\n `tabLead`.lead_name as \"Lead Name::120\",\n\t`tabLead`.company_name as \"Company Name::120\",\n\t`tabLead`.status as \"Status::120\",\n\tconcat_ws(', ', \n\t\ttrim(',' from `tabAddress`.address_line1), \n\t\ttrim(',' from tabAddress.address_line2), \n\t\ttabAddress.state, tabAddress.pincode, tabAddress.country\n\t) as 'Address::180',\n\t`tabLead`.phone as \"Phone::100\",\n\t`tabLead`.mobile_no as \"Mobile No::100\",\n\t`tabLead`.email_id as \"Email Id::120\",\n\t`tabLead`.lead_owner as \"Lead Owner::120\",\n\t`tabLead`.source as \"Source::120\",\n\t`tabLead`.territory as \"Territory::120\"\nFROM\n\t`tabLead`\n\tleft join `tabAddress` on (\n\t\t`tabAddress`.lead=`tabLead`.name\n\t)\nWHERE\n\t`tabLead`.docstatus<2\nORDER BY\n\t`tabLead`.name asc",
+ "ref_doctype": "Lead",
+ "report_name": "Lead Details",
+ "report_type": "Query Report"
+ },
+ {
+ "doctype": "Report",
+ "name": "Lead Details"
+ }
+]
\ No newline at end of file
diff --git a/selling/doctype/sales_common/sales_common.js b/selling/sales_common.js
similarity index 96%
rename from selling/doctype/sales_common/sales_common.js
rename to selling/sales_common.js
index 6a4b228..89b60b7 100644
--- a/selling/doctype/sales_common/sales_common.js
+++ b/selling/sales_common.js
@@ -73,23 +73,15 @@
if(!item.item_code) {
wn.throw(wn._("Please enter Item Code to get batch no"));
} else {
- if(item.warehouse) {
- return {
- query : "selling.doctype.sales_common.sales_common.get_batch_no",
- filters: {
- 'item_code': item.item_code,
- 'warehouse': item.warehouse,
- 'posting_date': me.frm.doc.posting_date
- }
- }
- } else {
- return{
- query : "selling.doctype.sales_common.sales_common.get_batch_no",
- filters: {
- 'item_code': item.item_code,
- 'posting_date': me.frm.doc.posting_date
- }
- }
+ filters = {
+ 'item_code': item.item_code,
+ 'posting_date': me.frm.doc.posting_date,
+ }
+ if(item.warehouse) filters["warehouse"] = item.warehouse
+
+ return {
+ query : "controllers.queries.get_batch_no",
+ filters: filters
}
}
});
@@ -161,7 +153,7 @@
item_code: function(doc, cdt, cdn) {
var me = this;
var item = wn.model.get_doc(cdt, cdn);
- if(item.item_code || item.barcode) {
+ if(item.item_code || item.barcode || item.serial_no) {
if(!this.validate_company_and_party("customer")) {
cur_frm.fields_dict[me.frm.cscript.fname].grid.grid_rows[item.idx - 1].remove();
} else {
@@ -172,6 +164,7 @@
args: {
item_code: item.item_code,
barcode: item.barcode,
+ serial_no: item.serial_no,
warehouse: item.warehouse,
doctype: me.frm.doc.doctype,
parentfield: item.parentfield,
@@ -628,7 +621,7 @@
// Help for Sales BOM items
var set_sales_bom_help = function(doc) {
if(!cur_frm.fields_dict.packing_list) return;
- if (getchildren('Delivery Note Packing Item', doc.name, 'packing_details').length) {
+ if (getchildren('Packed Item', doc.name, 'packing_details').length) {
$(cur_frm.fields_dict.packing_list.row.wrapper).toggle(true);
if (inList(['Delivery Note', 'Sales Invoice'], doc.doctype)) {
diff --git a/selling/utils/__init__.py b/selling/utils/__init__.py
index 6e74ac4..fd9c492 100644
--- a/selling/utils/__init__.py
+++ b/selling/utils/__init__.py
@@ -40,7 +40,9 @@
args = webnotes._dict(args)
if args.barcode:
- args.item_code = _get_item_code(args.barcode)
+ args.item_code = _get_item_code(barcode=args.barcode)
+ elif not args.item_code and args.serial_no:
+ args.item_code = _get_item_code(serial_no=args.serial_no)
item_bean = webnotes.bean("Item", args.item_code)
@@ -88,15 +90,17 @@
"qty": cint(args.qty)
}))
-def _get_item_code(barcode):
- item_code = webnotes.conn.sql_list("""select name from `tabItem` where barcode=%s""", barcode)
+def _get_item_code(barcode=None, serial_no=None):
+ if barcode:
+ input_type = "Barcode"
+ item_code = webnotes.conn.sql_list("""select name from `tabItem` where barcode=%s""", barcode)
+ elif serial_no:
+ input_type = "Serial No"
+ item_code = webnotes.conn.sql_list("""select item_code from `tabSerial No`
+ where name=%s""", serial_no)
if not item_code:
- msgprint(_("No Item found with Barcode") + ": %s" % barcode, raise_exception=True)
-
- elif len(item_code) > 1:
- msgprint(_("Items") + " %s " % comma_and(item_code) +
- _("have the same Barcode") + " %s" % barcode, raise_exception=True)
+ msgprint(_("No Item found with ") + input_type + ": %s" % (barcode or serial_no), raise_exception=True)
return item_code[0]
@@ -142,9 +146,8 @@
return out
def _get_price_list_rate(args, item_bean, meta):
- ref_rate = webnotes.conn.sql("""select ip.ref_rate from `tabItem Price` ip,
- `tabPrice List` pl where ip.parent = pl.name and ip.parent=%s and
- ip.item_code=%s and pl.buying_or_selling='Selling'""",
+ ref_rate = webnotes.conn.sql("""select ref_rate from `tabItem Price`
+ where price_list=%s and item_code=%s and buying_or_selling='Selling'""",
(args.selling_price_list, args.item_code), as_dict=1)
if not ref_rate:
diff --git a/selling/utils/product.py b/selling/utils/product.py
index 3432170..df5f16d 100644
--- a/selling/utils/product.py
+++ b/selling/utils/product.py
@@ -27,9 +27,8 @@
else:
in_stock = -1
- price = price_list and webnotes.conn.sql("""select ip.ref_rate, pl.currency from
- `tabItem Price` ip, `tabPrice List` pl where ip.parent = pl.name and
- ip.item_code=%s and ip.parent=%s""",
+ price = price_list and webnotes.conn.sql("""select ref_rate, currency from
+ `tabItem Price` where item_code=%s and price_list=%s""",
(item_code, price_list), as_dict=1) or []
price = price and price[0] or None
diff --git a/setup/doctype/company/company.js b/setup/doctype/company/company.js
index 217cf86..0c864fa 100644
--- a/setup/doctype/company/company.js
+++ b/setup/doctype/company/company.js
@@ -2,14 +2,53 @@
// License: GNU General Public License v3. See license.txt
cur_frm.cscript.refresh = function(doc, cdt, cdn) {
- if(doc.abbr && !doc.__islocal)
- cur_frm.set_df_property("abbr", "read_only", 1)
+ if(doc.abbr && !doc.__islocal) {
+ cur_frm.set_df_property("abbr", "read_only", 1);
+ if(in_list(user_roles, "System Manager"))
+ cur_frm.add_custom_button("Replace Abbreviation", cur_frm.cscript.replace_abbr)
+ }
if(!doc.__islocal) {
cur_frm.toggle_enable("default_currency", !cur_frm.doc.__transactions_exist);
}
}
+cur_frm.cscript.replace_abbr = function() {
+ var dialog = new wn.ui.Dialog({
+ title: "Replace Abbr",
+ fields: [
+ {"fieldtype": "Data", "label": "New Abbreviation", "fieldname": "new_abbr",
+ "reqd": 1 },
+ {"fieldtype": "Button", "label": "Update", "fieldname": "update"},
+ ]
+ });
+
+ dialog.fields_dict.update.$input.click(function() {
+ args = dialog.get_values();
+ if(!args) return;
+ return wn.call({
+ method: "setup.doctype.company.company.replace_abbr",
+ args: {
+ "company": cur_frm.doc.name,
+ "old": cur_frm.doc.abbr,
+ "new": args.new_abbr
+ },
+ callback: function(r) {
+ if(r.exc) {
+ msgprint(wn._("There were errors."));
+ return;
+ } else {
+ cur_frm.set_value("abbr", args.new_abbr);
+ }
+ dialog.hide();
+ cur_frm.refresh();
+ },
+ btn: this
+ })
+ });
+ dialog.show();
+}
+
cur_frm.cscript.has_special_chars = function(t) {
var iChars = "!@#$%^*+=-[]\\\';,/{}|\":<>?";
for (var i = 0; i < t.length; i++) {
diff --git a/setup/doctype/company/company.py b/setup/doctype/company/company.py
index da220cc..dff5569 100644
--- a/setup/doctype/company/company.py
+++ b/setup/doctype/company/company.py
@@ -5,9 +5,7 @@
import webnotes
from webnotes import _, msgprint
-from webnotes.utils import cstr, cint
-from webnotes.model.doc import Document
-from webnotes.model.code import get_obj
+from webnotes.utils import cstr
import webnotes.defaults
@@ -315,4 +313,19 @@
where doctype='Global Defaults' and field='default_company'
and value=%s""", (newdn, olddn))
- webnotes.defaults.clear_default("company", value=olddn)
\ No newline at end of file
+ webnotes.defaults.clear_default("company", value=olddn)
+
+@webnotes.whitelist()
+def replace_abbr(company, old, new):
+ webnotes.conn.set_value("Company", company, "abbr", new)
+
+ def _rename_record(dt):
+ for d in webnotes.conn.sql("select name from `tab%s` where company=%s" % (dt, '%s'), company):
+ parts = d[0].split(" - ")
+ if parts[-1].lower() == old.lower():
+ name_without_abbr = " - ".join(parts[:-1])
+ webnotes.rename_doc(dt, d[0], name_without_abbr + " - " + new)
+
+ for dt in ["Account", "Cost Center", "Warehouse"]:
+ _rename_record(dt)
+ webnotes.conn.commit()
diff --git a/setup/doctype/global_defaults/global_defaults.txt b/setup/doctype/global_defaults/global_defaults.txt
index fbfa8ca..a8a80b1 100644
--- a/setup/doctype/global_defaults/global_defaults.txt
+++ b/setup/doctype/global_defaults/global_defaults.txt
@@ -2,7 +2,7 @@
{
"creation": "2013-05-02 17:53:24",
"docstatus": 0,
- "modified": "2013-08-06 11:22:22",
+ "modified": "2013-10-23 10:22:44",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -176,13 +176,6 @@
"read_only": 0
},
{
- "doctype": "DocField",
- "fieldname": "hr",
- "fieldtype": "Section Break",
- "label": "HR",
- "read_only": 0
- },
- {
"doctype": "DocPerm"
}
]
\ No newline at end of file
diff --git a/setup/doctype/item_group/templates/generators/item_group.html b/setup/doctype/item_group/templates/generators/item_group.html
index 48db596..459c989 100644
--- a/setup/doctype/item_group/templates/generators/item_group.html
+++ b/setup/doctype/item_group/templates/generators/item_group.html
@@ -8,7 +8,7 @@
{% include "lib/website/doctype/website_slideshow/templates/includes/slideshow.html" %}
{% endif %}
{% if description %}<!-- description -->
- <div>{{ description or ""}}</div>
+ <div itemprop="description">{{ description or ""}}</div>
{% else %}
<h3>{{ name }}</h3>
{% endif %}
@@ -38,5 +38,13 @@
<div class="alert alert-warning">No items listed.</div>
{% endif %}
</div>
+<script>
+$(function() {
+ if(window.logged_in && getCookie("system_user")==="yes") {
+ wn.require("lib/js/wn/website/editable.js");
+ wn.make_editable($('[itemprop="description"]'), "Item Group", "{{ name }}", "description");
+ }
+})
+</script>
{% endblock %}
\ No newline at end of file
diff --git a/setup/doctype/item_price/item_price.js b/setup/doctype/item_price/item_price.js
new file mode 100644
index 0000000..0a08c98
--- /dev/null
+++ b/setup/doctype/item_price/item_price.js
@@ -0,0 +1,16 @@
+// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
+// License: GNU General Public License v3. See license.txt
+
+$.extend(cur_frm.cscript, {
+
+ onload: function () {
+
+ // Fetch price list details
+ cur_frm.add_fetch("price_list", "buying_or_selling", "buying_or_selling");
+ cur_frm.add_fetch("price_list", "currency", "currency");
+
+ // Fetch item details
+ cur_frm.add_fetch("item_code", "item_name", "item_name");
+ cur_frm.add_fetch("item_code", "description", "item_description");
+ }
+});
\ No newline at end of file
diff --git a/setup/doctype/item_price/item_price.py b/setup/doctype/item_price/item_price.py
index 3256c80..ddde87e 100644
--- a/setup/doctype/item_price/item_price.py
+++ b/setup/doctype/item_price/item_price.py
@@ -5,7 +5,36 @@
from __future__ import unicode_literals
import webnotes
+from webnotes import _
+
+class ItemPriceDuplicateItem(Exception): pass
class DocType:
def __init__(self, d, dl):
- self.doc, self.doclist = d, dl
\ No newline at end of file
+ self.doc, self.doclist = d, dl
+
+ def on_update(self):
+ self.update_price_list_details()
+ self.update_item_details()
+ self.check_duplicate_item()
+
+ def update_price_list_details(self):
+ self.doc.buying_or_selling = webnotes.conn.get_value("Price List", self.doc.price_list,
+ "buying_or_selling")
+
+ self.doc.currency = webnotes.conn.get_value("Price List", self.doc.price_list,
+ "currency")
+
+ def update_item_details(self):
+ self.doc.item_name = webnotes.conn.get_value("Item", self.doc.item_code, "item_name")
+
+ self.doc.item_description = webnotes.conn.get_value("Item", self.doc.item_code,
+ "description")
+
+ def check_duplicate_item(self):
+ if webnotes.conn.sql("""select name from `tabItem Price`
+ where item_code=%s and price_list=%s and name!=%s""",
+ (self.doc.item_code, self.doc.price_list, self.doc.name)):
+ webnotes.throw(_("Duplicate Item: ") + self.doc.item_code +
+ _(" already available in Price List: ") + self.doc.price_list,
+ ItemPriceDuplicateItem)
\ No newline at end of file
diff --git a/setup/doctype/item_price/item_price.txt b/setup/doctype/item_price/item_price.txt
index 4ff5124..779bbd4 100644
--- a/setup/doctype/item_price/item_price.txt
+++ b/setup/doctype/item_price/item_price.txt
@@ -2,29 +2,42 @@
{
"creation": "2013-05-02 16:29:48",
"docstatus": 0,
- "modified": "2013-09-13 11:50:02",
+ "modified": "2013-10-21 15:11:20",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"autoname": "RFD/.#####",
+ "description": "Multiple Item prices.",
"doctype": "DocType",
+ "document_type": "Master",
+ "icon": "icon-flag",
"in_create": 0,
- "istable": 1,
+ "istable": 0,
"module": "Setup",
"name": "__common__",
"read_only": 0
},
{
"doctype": "DocField",
- "in_filter": 1,
- "in_list_view": 1,
"name": "__common__",
"parent": "Item Price",
"parentfield": "fields",
"parenttype": "DocType",
+ "permlevel": 0
+ },
+ {
+ "cancel": 1,
+ "create": 1,
+ "doctype": "DocPerm",
+ "name": "__common__",
+ "parent": "Item Price",
+ "parentfield": "permissions",
+ "parenttype": "DocType",
"permlevel": 0,
- "reqd": 1
+ "read": 1,
+ "report": 1,
+ "write": 1
},
{
"doctype": "DocType",
@@ -32,22 +45,83 @@
},
{
"doctype": "DocField",
+ "fieldname": "price_list",
+ "fieldtype": "Link",
+ "in_filter": 1,
+ "label": "Price List",
+ "options": "Price List",
+ "reqd": 1
+ },
+ {
+ "doctype": "DocField",
"fieldname": "item_code",
"fieldtype": "Link",
+ "in_filter": 1,
+ "in_list_view": 1,
"label": "Item Code",
"oldfieldname": "price_list_name",
"oldfieldtype": "Select",
"options": "Item",
+ "reqd": 1,
"search_index": 1
},
{
"doctype": "DocField",
"fieldname": "ref_rate",
"fieldtype": "Currency",
+ "in_filter": 1,
+ "in_list_view": 1,
"label": "Rate",
"oldfieldname": "ref_rate",
"oldfieldtype": "Currency",
"options": "currency",
+ "reqd": 1,
"search_index": 0
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "col_br_1",
+ "fieldtype": "Column Break"
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "buying_or_selling",
+ "fieldtype": "Select",
+ "in_filter": 1,
+ "in_list_view": 1,
+ "label": "Valid for Buying or Selling?",
+ "options": "Selling\nBuying",
+ "reqd": 0
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "item_name",
+ "fieldtype": "Data",
+ "label": "Item Name",
+ "read_only": 1
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "item_description",
+ "fieldtype": "Text",
+ "label": "Item Description",
+ "read_only": 1
+ },
+ {
+ "doctype": "DocField",
+ "fieldname": "currency",
+ "fieldtype": "Link",
+ "hidden": 1,
+ "label": "Currency",
+ "options": "Currency",
+ "read_only": 1
+ },
+ {
+ "doctype": "DocPerm",
+ "role": "Sales Master Manager"
+ },
+ {
+ "doctype": "DocPerm",
+ "role": "Purchase Master Manager"
}
]
\ No newline at end of file
diff --git a/setup/doctype/item_price/test_item_price.py b/setup/doctype/item_price/test_item_price.py
new file mode 100644
index 0000000..43694da
--- /dev/null
+++ b/setup/doctype/item_price/test_item_price.py
@@ -0,0 +1,23 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
+# License: GNU General Public License v3. See license.txt
+
+from __future__ import unicode_literals
+import unittest
+import webnotes
+from setup.doctype.item_price.item_price import ItemPriceDuplicateItem
+
+class TestItem(unittest.TestCase):
+ def test_duplicate_item(self):
+ item_price = webnotes.bean(copy=test_records[0])
+ self.assertRaises(ItemPriceDuplicateItem, item_price.insert)
+
+test_records = [
+ [
+ {
+ "doctype": "Item Price",
+ "price_list": "_Test Price List",
+ "item_code": "_Test Item",
+ "ref_rate": 100
+ }
+ ]
+]
\ No newline at end of file
diff --git a/setup/doctype/naming_series/naming_series.py b/setup/doctype/naming_series/naming_series.py
index 4e85b15..36d6a84 100644
--- a/setup/doctype/naming_series/naming_series.py
+++ b/setup/doctype/naming_series/naming_series.py
@@ -134,3 +134,34 @@
msgprint("Series Updated Successfully")
else:
msgprint("Please select prefix first")
+
+def set_by_naming_series(doctype, fieldname, naming_series, hide_name_field=True):
+ from core.doctype.property_setter.property_setter import make_property_setter
+ if naming_series:
+ make_property_setter(doctype, "naming_series", "hidden", 0, "Check")
+ make_property_setter(doctype, "naming_series", "reqd", 1, "Check")
+
+ # set values for mandatory
+ webnotes.conn.sql("""update `tab{doctype}` set naming_series={s} where
+ ifnull(naming_series, '')=''""".format(doctype=doctype, s="%s"), get_default_naming_series(doctype))
+
+ if hide_name_field:
+ make_property_setter(doctype, fieldname, "reqd", 0, "Check")
+ make_property_setter(doctype, fieldname, "hidden", 1, "Check")
+ else:
+ make_property_setter(doctype, "naming_series", "reqd", 0, "Check")
+ make_property_setter(doctype, "naming_series", "hidden", 1, "Check")
+
+ if hide_name_field:
+ make_property_setter(doctype, fieldname, "hidden", 0, "Check")
+ make_property_setter(doctype, fieldname, "reqd", 1, "Check")
+
+ # set values for mandatory
+ webnotes.conn.sql("""update `tab{doctype}` set `{fieldname}`=`name` where
+ ifnull({fieldname}, '')=''""".format(doctype=doctype, fieldname=fieldname))
+
+def get_default_naming_series(doctype):
+ from webnotes.model.doctype import get_property
+ naming_series = get_property(doctype, "options", "naming_series")
+ naming_series = naming_series.split("\n")
+ return naming_series[0] or naming_series[1]
\ No newline at end of file
diff --git a/setup/doctype/price_list/price_list.js b/setup/doctype/price_list/price_list.js
index 67090bc..84c4c2f 100644
--- a/setup/doctype/price_list/price_list.js
+++ b/setup/doctype/price_list/price_list.js
@@ -5,253 +5,13 @@
onload: function() {
erpnext.add_for_territory();
},
-});
-cur_frm.cscript.refresh = function(doc, cdt, cdn) {
- cur_frm.cscript.show_item_prices();
-}
-
-cur_frm.cscript.show_item_prices = function() {
- var item_price = wn.model.get("Item Price", {parent: cur_frm.doc.name});
-
- $(cur_frm.fields_dict.item_prices_html.wrapper).empty();
-
- new wn.ui.form.TableGrid({
- parent: cur_frm.fields_dict.item_prices_html.wrapper,
- frm: cur_frm,
- table_field: wn.meta.get_docfield("Price List", "item_prices", cur_frm.doc.name)
- });
-}
-
-wn.ui.form.TableGrid = Class.extend({
- init: function(opts) {
- $.extend(this, opts);
- this.fields = wn.meta.get_docfields("Item Price", cur_frm.doc.name);
- this.make_table();
- },
- make_table: function() {
- var me = this;
- // Creating table & assigning attributes
- var grid_table = document.createElement("table");
- grid_table.className = "table table-hover table-bordered table-grid";
-
- // Appending header & rows to table
- grid_table.appendChild(this.make_table_headers());
- grid_table.appendChild(this.make_table_rows());
-
- // Creating button to add new row
- var btn_div = document.createElement("div");
- var new_row_btn = document.createElement("button");
- new_row_btn.className = "btn btn-success table-new-row";
- new_row_btn.title = "Add new row";
-
- var btn_icon = document.createElement("i");
- btn_icon.className = "icon-plus";
- new_row_btn.appendChild(btn_icon);
- new_row_btn.innerHTML += " Add new row";
- btn_div.appendChild(new_row_btn);
-
- // Appending table & button to parent
- var $grid_table = $(grid_table).appendTo($(this.parent));
- var $btn_div = $(btn_div).appendTo($(this.parent));
-
- $btn_div.on("click", ".table-new-row", function() {
- me.make_dialog();
- return false;
- });
-
- $grid_table.on("click", ".table-row", function() {
- me.make_dialog(this);
- return false;
- });
- },
- make_table_headers: function() {
- var me = this;
- var header = document.createElement("thead");
-
- // Creating header row
- var row = document.createElement("tr");
- row.className = "active";
-
- // Creating head first cell
- var th = document.createElement("th");
- th.width = "8%";
- th.className = "text-center";
- th.innerHTML = "#";
- row.appendChild(th);
-
- // Make other headers with label as heading
- for(var i=0, l=this.fields.length; i<l; i++) {
- var df = this.fields[i];
-
- if(!!!df.hidden && df.in_list_view === 1) {
- var th = document.createElement("th");
-
- // If currency then move header to right
- if(["Int", "Currency", "Float"].indexOf(df.fieldtype) !== -1) th.className = "text-right";
-
- th.innerHTML = wn._(df.label);
- row.appendChild(th);
- }
- }
-
- header.appendChild(row);
-
- return header;
- },
- make_table_rows: function() {
- var me = this;
-
- // Creating table body
- var table_body = document.createElement("tbody");
-
- var item_prices = wn.model.get_children(this.table_field.options, this.frm.doc.name,
- this.table_field.fieldname, this.frm.doctype);
-
- for(var i=0, l=item_prices.length; i<l; i++) {
- var d = item_prices[i];
-
- // Creating table row
- var tr = this.add_new_row(d);
-
- // append row to table body
- table_body.appendChild(tr);
- }
-
- this.table_body = table_body;
-
- return table_body;
- },
- make_dialog: function(row) {
- var me = this;
-
- this.dialog = new wn.ui.Dialog({
- title: this.table_field.options,
- fields: this.fields
- });
-
- if (row)
- this.dialog.set_values(this.make_dialog_values(row));
-
- $a(this.dialog.body, 'div', '', '', this.make_dialog_buttons(row));
- this.dialog.show();
-
- this.dialog.$wrapper.find('button.update').on('click', function() {
- me.update_row(row);
- });
-
- this.dialog.$wrapper.find('button.delete').on('click', function() {
- me.delete_row(row);
- });
- return row;
- },
- make_dialog_values: function(row) {
- var me = this;
- var dialog_values = {};
-
- $.each(this.fields, function(i, item) {
- dialog_values[item.fieldname] = $(row).find('td[data-fieldname="'+ item.fieldname +'"]').attr('data-fieldvalue');
- });
-
- return dialog_values;
- },
- make_dialog_buttons: function(row) {
- var me = this;
- var buttons = '<button class="btn btn-primary update">Update</button>';
-
- // if user can delete then only add the delete button in dialog
- if (wn.model.can_delete(me.frm.doc.doctype) && row)
- buttons += ' <button class="btn btn-default delete">Delete</button>';
-
- return buttons;
- },
- update_row: function(row) {
- var me = this;
-
- if (!row) {
- var d = wn.model.add_child(this.frm.doc, this.table_field.options,
- this.table_field.fieldname);
- refresh_field(this.table_field.fieldname);
- this.update_item_price(d.name);
- var tr = this.add_new_row(d);
- this.table_body.appendChild(tr);
- }
- else {
- this.update_item_price(null, row);
- }
-
- this.dialog.hide();
- },
-
- update_item_price: function(docname, row) {
- var me = this;
- if(!docname && row) docname = $(row).attr("data-docname");
- $.each(me.fields, function(i, df) {
- var val = me.dialog.get_values()[df.fieldname];
-
- if(["Currency", "Float"].indexOf(df.fieldtype)!==-1) {
- val = flt(val);
- } else if(["Int", "Check"].indexOf(df.fieldtype)!==-1) {
- val = cint(val);
- }
-
- wn.model.set_value(me.table_field.options, docname,
- df.fieldname, val);
-
- if(row) {
- var $td = $(row).find('td[data-fieldname="'+ df.fieldname +'"]');
- $td.attr('data-fieldvalue', val);
- // If field type is currency the update with format currency
- $td.html(wn.format(val, df));
- }
- });
- },
-
- delete_row: function(row) {
- var me = this;
- var docname = $(row).find('td:last').attr('data-docname');
- wn.model.clear_doc(me.table_field.options, docname);
- $(row).remove();
-
- // Re-assign idx
- $.each($(this.parent).find("tbody tr"), function(idx, data) {
- var $td = $(data).find('td:first');
- $td.html(idx + 1);
- });
- this.dialog.hide();
- },
-
- add_new_row: function(d) {
- var tr = document.createElement("tr");
- tr.className = "table-row";
- tr.setAttribute("data-docname", d.name);
-
- // Creating table data & appending to row
- var td = document.createElement("td");
- td.className = "text-center";
- td.innerHTML = d.idx;
- tr.appendChild(td);
-
- for(var f=0, lf=this.fields.length; f<lf; f++) {
- var df = this.fields[f];
- if(!!!df.hidden && df.in_list_view===1) {
- var td = document.createElement("td");
- td.setAttribute("data-fieldname", df.fieldname);
- td.setAttribute("data-fieldvalue", d[df.fieldname]);
- td.setAttribute("data-docname", d.name);
-
- // If currency then move header to right
- if(["Int", "Currency", "Float"].indexOf(df.fieldtype) !== -1) {
- td.className = "text-right";
- }
-
- // format and set display
- td.innerHTML = wn.format(d[df.fieldname], df);
-
- // append column to tabel row
- tr.appendChild(td);
- }
- }
- return tr;
+ refresh: function() {
+ cur_frm.add_custom_button("Add / Edit Prices", function() {
+ wn.route_options = {
+ "price_list": cur_frm.doc.name
+ };
+ wn.set_route("Report", "Item Price");
+ }, "icon-money");
}
});
\ No newline at end of file
diff --git a/setup/doctype/price_list/price_list.py b/setup/doctype/price_list/price_list.py
index 2fcaf21..d94b78e 100644
--- a/setup/doctype/price_list/price_list.py
+++ b/setup/doctype/price_list/price_list.py
@@ -8,8 +8,6 @@
from webnotes.model.controller import DocListController
import webnotes.defaults
-class PriceListDuplicateItem(Exception): pass
-
class DocType(DocListController):
def validate(self):
if self.doc.buying_or_selling not in ["Buying", "Selling"]:
@@ -27,23 +25,13 @@
else:
# at least one territory
self.validate_table_has_rows("valid_for_territories")
-
- # check for duplicate items
- self.check_duplicate_items()
def on_update(self):
self.set_default_if_missing()
+ self.update_item_price()
cart_settings = webnotes.get_obj("Shopping Cart Settings")
if cint(cart_settings.doc.enabled):
cart_settings.validate_price_lists()
-
- def check_duplicate_items(self):
- item_codes = []
- for d in self.doclist.get({"parentfield": "item_prices"}):
- if d.item_code not in item_codes:
- item_codes.append(d.item_code)
- else:
- msgprint(_("Duplicate Item ") + ": " + d.item_code, raise_exception=PriceListDuplicateItem)
def set_default_if_missing(self):
if self.doc.buying_or_selling=="Selling":
@@ -54,3 +42,7 @@
if not webnotes.conn.get_value("Buying Settings", None, "buying_price_list"):
webnotes.set_value("Buying Settings", "Buying Settings", "buying_price_list", self.doc.name)
+ def update_item_price(self):
+ webnotes.conn.sql("""update `tabItem Price` set currency=%s,
+ buying_or_selling=%s where price_list=%s""",
+ (self.doc.currency, self.doc.buying_or_selling, self.doc.name))
\ No newline at end of file
diff --git a/setup/doctype/price_list/price_list.txt b/setup/doctype/price_list/price_list.txt
index df91bd9..b93cfcc 100644
--- a/setup/doctype/price_list/price_list.txt
+++ b/setup/doctype/price_list/price_list.txt
@@ -2,7 +2,7 @@
{
"creation": "2013-01-25 11:35:09",
"docstatus": 0,
- "modified": "2013-10-02 11:36:09",
+ "modified": "2013-10-18 13:33:07",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -85,27 +85,6 @@
"reqd": 1
},
{
- "description": "To change row values, click on the respective row",
- "doctype": "DocField",
- "fieldname": "item_prices_section",
- "fieldtype": "Section Break",
- "hidden": 0,
- "label": "Item Prices"
- },
- {
- "doctype": "DocField",
- "fieldname": "item_prices_html",
- "fieldtype": "HTML"
- },
- {
- "doctype": "DocField",
- "fieldname": "item_prices",
- "fieldtype": "Table",
- "hidden": 1,
- "label": "Item Prices",
- "options": "Item Price"
- },
- {
"amend": 0,
"cancel": 0,
"create": 0,
diff --git a/setup/doctype/price_list/test_price_list.py b/setup/doctype/price_list/test_price_list.py
index b1174d3..d5174ed 100644
--- a/setup/doctype/price_list/test_price_list.py
+++ b/setup/doctype/price_list/test_price_list.py
@@ -2,16 +2,7 @@
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
-import unittest
import webnotes
-from setup.doctype.price_list.price_list import PriceListDuplicateItem
-
-class TestItem(unittest.TestCase):
- def test_duplicate_item(self):
- price_list = webnotes.bean(copy=test_records[0])
- item_price = price_list.doclist.get({"doctype": "Item Price"})[0]
- price_list.doclist.append(webnotes.doc(item_price.fields.copy()))
- self.assertRaises(PriceListDuplicateItem, price_list.insert)
# test_ignore = ["Item"]
@@ -28,12 +19,6 @@
"parentfield": "valid_for_territories",
"territory": "All Territories"
},
- {
- "doctype": "Item Price",
- "parentfield": "item_prices",
- "item_code": "_Test Item",
- "ref_rate": 100
- }
],
[
{
diff --git a/setup/page/setup/setup.py b/setup/page/setup/setup.py
index 6e6be31..1569ef0 100644
--- a/setup/page/setup/setup.py
+++ b/setup/page/setup/setup.py
@@ -41,6 +41,7 @@
{"doctype":"UOM"},
{"doctype":"Brand"},
{"doctype":"Price List"},
+ {"doctype": "Item Price"},
{ "title": "Stock Settings",
"route": "Form/Stock Settings", "type": "Link", "icon": "icon-cog" },
],
diff --git a/setup/page/setup_wizard/setup_wizard.js b/setup/page/setup_wizard/setup_wizard.js
index 648958e..bec2828 100644
--- a/setup/page/setup_wizard/setup_wizard.js
+++ b/setup/page/setup_wizard/setup_wizard.js
@@ -69,7 +69,10 @@
onload: function(slide) {
if(user!=="Administrator") {
slide.form.fields_dict.password.$wrapper.toggle(false);
- slide.form.fields_dict.email_id.$wrapper.toggle(false);
+ slide.form.fields_dict.email.$wrapper.toggle(false);
+ slide.form.fields_dict.first_name.set_input(wn.boot.profile.first_name);
+ slide.form.fields_dict.last_name.set_input(wn.boot.profile.last_name);
+
delete slide.form.fields_dict.email;
delete slide.form.fields_dict.password;
}
@@ -97,7 +100,7 @@
var parts = slide.get_input("company_name").val().split(" ");
var abbr = $.map(parts, function(p) { return p ? p.substr(0,1) : null }).join("");
slide.get_input("company_abbr").val(abbr.toUpperCase());
- });
+ }).val(wn.boot.control_panel.company_name || "").trigger("change");
}
},
diff --git a/setup/report/item_wise_price_list/item_wise_price_list.txt b/setup/report/item_wise_price_list/item_wise_price_list.txt
deleted file mode 100644
index 44118c8..0000000
--- a/setup/report/item_wise_price_list/item_wise_price_list.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-[
- {
- "creation": "2013-09-25 10:29:04",
- "docstatus": 0,
- "modified": "2013-09-25 10:29:04",
- "modified_by": "Administrator",
- "owner": "Administrator"
- },
- {
- "doctype": "Report",
- "is_standard": "Yes",
- "json": "{\"filters\":[[\"Item Price\",\"item_code\",\"like\",\"%\"],[\"Price List\",\"price_list_name\",\"like\",\"%\"]],\"columns\":[[\"item_code\",\"Item Price\"],[\"price_list_name\",\"Price List\"],[\"currency\",\"Price List\"],[\"ref_rate\",\"Item Price\"],[\"buying_or_selling\",\"Price List\"],[\"name\",\"Price List\"]],\"sort_by\":\"Price List.modified\",\"sort_order\":\"desc\",\"sort_by_next\":\"\",\"sort_order_next\":\"desc\"}",
- "name": "__common__",
- "ref_doctype": "Price List",
- "report_name": "Item-Wise Price List",
- "report_type": "Report Builder"
- },
- {
- "doctype": "Report",
- "name": "Item-Wise Price List"
- }
-]
\ No newline at end of file
diff --git a/setup/report/item_wise_price_list_rate/item_wise_price_list_rate.txt b/setup/report/item_wise_price_list_rate/item_wise_price_list_rate.txt
index 08b1bef..888203d 100644
--- a/setup/report/item_wise_price_list_rate/item_wise_price_list_rate.txt
+++ b/setup/report/item_wise_price_list_rate/item_wise_price_list_rate.txt
@@ -2,14 +2,14 @@
{
"creation": "2013-09-25 10:21:15",
"docstatus": 0,
- "modified": "2013-09-25 10:24:57",
+ "modified": "2013-10-21 16:06:22",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"doctype": "Report",
"is_standard": "Yes",
- "json": "{\"filters\":[[\"Item Price\",\"item_code\",\"like\",\"%\"],[\"Price List\",\"price_list_name\",\"like\",\"%\"]],\"columns\":[[\"item_code\",\"Item Price\"],[\"price_list_name\",\"Price List\"],[\"currency\",\"Price List\"],[\"ref_rate\",\"Item Price\"],[\"buying_or_selling\",\"Price List\"],[\"name\",\"Price List\"]],\"sort_by\":\"Price List.modified\",\"sort_order\":\"desc\",\"sort_by_next\":\"\",\"sort_order_next\":\"desc\"}",
+ "json": "{\"filters\":[[\"Item Price\",\"price_list\",\"like\",\"%\"],[\"Item Price\",\"item_code\",\"like\",\"%\"]],\"columns\":[[\"name\",\"Item Price\"],[\"price_list\",\"Item Price\"],[\"item_code\",\"Item Price\"],[\"item_name\",\"Item Price\"],[\"item_description\",\"Item Price\"],[\"ref_rate\",\"Item Price\"],[\"buying_or_selling\",\"Item Price\"],[\"currency\",\"Item Price\"]],\"sort_by\":\"Item Price.modified\",\"sort_order\":\"desc\",\"sort_by_next\":\"\",\"sort_order_next\":\"desc\"}",
"name": "__common__",
"ref_doctype": "Price List",
"report_name": "Item-wise Price List Rate",
diff --git a/stock/doctype/delivery_note/delivery_note.js b/stock/doctype/delivery_note/delivery_note.js
index c3fc0ac..210b392 100644
--- a/stock/doctype/delivery_note/delivery_note.js
+++ b/stock/doctype/delivery_note/delivery_note.js
@@ -9,7 +9,7 @@
wn.require('app/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js');
wn.require('app/utilities/doctype/sms_control/sms_control.js');
-wn.require('app/selling/doctype/sales_common/sales_common.js');
+wn.require('app/selling/sales_common.js');
wn.require('app/accounts/doctype/sales_invoice/pos.js');
wn.provide("erpnext.stock");
@@ -113,13 +113,6 @@
}
}
-cur_frm.cscript.serial_no = function(doc, cdt, cdn) {
- var d = locals[cdt][cdn];
- if (d.serial_no) {
- return get_server_fields('get_serial_details',d.serial_no,'delivery_note_details',doc,cdt,cdn,1);
- }
-}
-
cur_frm.fields_dict['transporter_name'].get_query = function(doc) {
return{
filters: { 'supplier_type': "transporter" }
diff --git a/stock/doctype/delivery_note/delivery_note.py b/stock/doctype/delivery_note/delivery_note.py
index deaf024..4c8068a 100644
--- a/stock/doctype/delivery_note/delivery_note.py
+++ b/stock/doctype/delivery_note/delivery_note.py
@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import webnotes
-from webnotes.utils import cstr, flt, cint, add_days
+from webnotes.utils import cstr, flt, cint
from webnotes.model.bean import getlist
from webnotes.model.code import get_obj
from webnotes import msgprint, _
@@ -42,14 +42,6 @@
def get_portal_page(self):
return "shipment" if self.doc.docstatus==1 else None
-
- def get_contact_details(self):
- return get_obj('Sales Common').get_contact_details(self,0)
-
-
- def get_comm_rate(self, sales_partner):
- """Get Commission rate of Sales Partner"""
- return get_obj('Sales Common').get_comm_rate(sales_partner, self)
def set_actual_qty(self):
for d in getlist(self.doclist, 'delivery_note_details'):
@@ -57,15 +49,6 @@
actual_qty = webnotes.conn.sql("select actual_qty from `tabBin` where item_code = '%s' and warehouse = '%s'" % (d.item_code, d.warehouse))
d.actual_qty = actual_qty and flt(actual_qty[0][0]) or 0
-
- def get_barcode_details(self, barcode):
- return get_obj('Sales Common').get_barcode_details(barcode)
-
-
- def get_adj_percent(self, arg=''):
- """Re-calculates Basic Rate & amount based on Price List Selected"""
- get_obj('Sales Common').get_adj_percent(self)
-
def so_required(self):
"""check in manage account if sales order required or not"""
if webnotes.conn.get_value("Selling Settings", None, 'so_required') == 'Yes':
@@ -83,19 +66,11 @@
self.so_required()
self.validate_proj_cust()
- sales_com_obj = get_obj(dt = 'Sales Common')
- sales_com_obj.check_stop_sales_order(self)
- sales_com_obj.check_active_sales_items(self)
+ self.check_stop_sales_order("against_sales_order")
self.validate_for_items()
self.validate_warehouse()
self.validate_uom_is_integer("stock_uom", "qty")
-
- sales_com_obj.validate_max_discount(self, 'delivery_note_details')
- sales_com_obj.check_conversion_rate(self)
-
- # Set actual qty for each item in selected warehouse
- self.update_current_stock()
-
+ self.update_current_stock()
self.validate_with_previous_doc()
self.doc.status = 'Draft'
@@ -169,7 +144,8 @@
d.projected_qty = bin and flt(bin[0]['projected_qty']) or 0
def on_update(self):
- self.doclist = get_obj('Sales Common').make_packing_list(self,'delivery_note_details')
+ from stock.doctype.packed_item.packed_item import make_packing_list
+ self.doclist = make_packing_list(self, 'delivery_note_details')
def on_submit(self):
self.validate_packed_qty()
@@ -192,8 +168,7 @@
def on_cancel(self):
- sales_com_obj = get_obj(dt = 'Sales Common')
- sales_com_obj.check_stop_sales_order(self)
+ self.check_stop_sales_order("against_sales_order")
self.check_next_docstatus()
self.update_prevdoc_status()
@@ -282,9 +257,6 @@
}
update_bin(args)
- def get_item_list(self):
- return get_obj('Sales Common').get_item_list(self)
-
def credit_limit(self):
"""check credit limit of items in DN Detail which are not fetched from sales order"""
amount, total = 0, 0
@@ -293,7 +265,7 @@
amount += d.amount
if amount != 0:
total = (amount/self.doc.net_total)*self.doc.grand_total
- get_obj('Sales Common').check_credit(self, total)
+ self.check_credit(total)
def get_invoiced_qty_map(delivery_note):
"""returns a map: {dn_detail: invoiced_qty}"""
diff --git a/stock/doctype/delivery_note/delivery_note.txt b/stock/doctype/delivery_note/delivery_note.txt
index 6834365..037b4fb 100644
--- a/stock/doctype/delivery_note/delivery_note.txt
+++ b/stock/doctype/delivery_note/delivery_note.txt
@@ -355,7 +355,7 @@
"label": "Packing Details",
"oldfieldname": "packing_details",
"oldfieldtype": "Table",
- "options": "Delivery Note Packing Item",
+ "options": "Packed Item",
"print_hide": 1,
"read_only": 1
},
diff --git a/stock/doctype/delivery_note_packing_item/README.md b/stock/doctype/delivery_note_packing_item/README.md
deleted file mode 100644
index 20c343a..0000000
--- a/stock/doctype/delivery_note_packing_item/README.md
+++ /dev/null
@@ -1 +0,0 @@
-Item packed in parent Delivery Note. If shipped Items are of type Sales BOM, then this table contains the exploded list of Items shipped.
\ No newline at end of file
diff --git a/stock/doctype/delivery_note_packing_item/__init__.py b/stock/doctype/delivery_note_packing_item/__init__.py
deleted file mode 100644
index baffc48..0000000
--- a/stock/doctype/delivery_note_packing_item/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from __future__ import unicode_literals
diff --git a/stock/doctype/delivery_note_packing_item/delivery_note_packing_item.py b/stock/doctype/delivery_note_packing_item/delivery_note_packing_item.py
deleted file mode 100644
index 26d0f76..0000000
--- a/stock/doctype/delivery_note_packing_item/delivery_note_packing_item.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
-# License: GNU General Public License v3. See license.txt
-
-from __future__ import unicode_literals
-import webnotes
-
-class DocType:
- def __init__(self, d, dl):
- self.doc, self.doclist = d, dl
\ No newline at end of file
diff --git a/stock/doctype/item/item.js b/stock/doctype/item/item.js
index 9e5430b..d8ee45f 100644
--- a/stock/doctype/item/item.js
+++ b/stock/doctype/item/item.js
@@ -6,17 +6,14 @@
// read only if any stock ledger entry exists
cur_frm.cscript.make_dashboard()
-
- cur_frm.toggle_display("naming_series", sys_defaults.item_naming_by=="Naming Series"
- && doc.__islocal)
- cur_frm.toggle_display("item_code", sys_defaults.item_naming_by!="Naming Series"
- && doc.__islocal)
+ erpnext.hide_naming_series();
if(!doc.__islocal && doc.show_in_website) {
cur_frm.add_custom_button("View In Website", function() {
window.open(doc.page_name);
}, "icon-globe");
}
+ cur_frm.cscript.edit_prices_button();
if (!doc.__islocal && doc.is_stock_item == 'Yes') {
cur_frm.toggle_enable(['has_serial_no', 'is_stock_item', 'valuation_method'],
@@ -30,6 +27,15 @@
return;
}
+cur_frm.cscript.edit_prices_button = function() {
+ cur_frm.add_custom_button("Add / Edit Prices", function() {
+ wn.route_options = {
+ "item_code": cur_frm.doc.name
+ };
+ wn.set_route("Report", "Item Price");
+ }, "icon-money");
+}
+
cur_frm.cscript.item_code = function(doc) {
if(!doc.item_name) cur_frm.set_value("item_name", doc.item_code);
if(!doc.description) cur_frm.set_value("description", doc.item_code);
diff --git a/stock/doctype/item/templates/generators/item.html b/stock/doctype/item/templates/generators/item.html
index 7056068..eab1b73 100644
--- a/stock/doctype/item/templates/generators/item.html
+++ b/stock/doctype/item/templates/generators/item.html
@@ -3,6 +3,14 @@
{% block javascript %}
<script>
{% include "app/stock/doctype/item/templates/includes/product_page.js" %}
+
+ $(function() {
+ if(window.logged_in && getCookie("system_user")==="yes") {
+ wn.require("lib/js/wn/website/editable.js");
+ wn.make_editable($('[itemprop="description"]'), "Item", "{{ name }}", "web_long_description");
+ }
+ })
+
</script>
{% endblock %}
diff --git a/stock/doctype/item/templates/includes/product_list.js b/stock/doctype/item/templates/includes/product_list.js
index 2856bde..efcbe0b 100644
--- a/stock/doctype/item/templates/includes/product_list.js
+++ b/stock/doctype/item/templates/includes/product_list.js
@@ -12,7 +12,7 @@
$.ajax({
method: "GET",
- url: "server.py",
+ url: "/",
dataType: "json",
data: {
cmd: "selling.utils.product.get_product_list",
diff --git a/stock/doctype/material_request/material_request.py b/stock/doctype/material_request/material_request.py
index 7aea336..4af86da 100644
--- a/stock/doctype/material_request/material_request.py
+++ b/stock/doctype/material_request/material_request.py
@@ -96,9 +96,6 @@
update_bin(args)
def on_submit(self):
- purchase_controller = webnotes.get_obj("Purchase Common")
- purchase_controller.is_item_table_empty(self)
-
webnotes.conn.set(self.doc,'status','Submitted')
self.update_bin(is_submit = 1, is_stopped = 0)
diff --git a/setup/report/item_wise_price_list/__init__.py b/stock/doctype/packed_item/__init__.py
similarity index 100%
copy from setup/report/item_wise_price_list/__init__.py
copy to stock/doctype/packed_item/__init__.py
diff --git a/stock/doctype/packed_item/packed_item.py b/stock/doctype/packed_item/packed_item.py
new file mode 100644
index 0000000..fc25958
--- /dev/null
+++ b/stock/doctype/packed_item/packed_item.py
@@ -0,0 +1,105 @@
+# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
+# MIT License. See license.txt
+
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import webnotes
+from webnotes.utils import cstr, flt
+from webnotes.model.doc import addchild
+from webnotes.model.bean import getlist
+
+class DocType:
+ def __init__(self, d, dl):
+ self.doc, self.doclist = d, dl
+
+def get_sales_bom_items(item_code):
+ return webnotes.conn.sql("""select t1.item_code, t1.qty, t1.uom
+ from `tabSales BOM Item` t1, `tabSales BOM` t2
+ where t2.new_item_code=%s and t1.parent = t2.name""", item_code, as_dict=1)
+
+def get_packing_item_details(item):
+ return webnotes.conn.sql("""select item_name, description, stock_uom from `tabItem`
+ where name = %s""", item, as_dict = 1)[0]
+
+def get_bin_qty(item, warehouse):
+ det = webnotes.conn.sql("""select actual_qty, projected_qty from `tabBin`
+ where item_code = %s and warehouse = %s""", (item, warehouse), as_dict = 1)
+ return det and det[0] or ''
+
+def update_packing_list_item(obj, packing_item_code, qty, warehouse, line, packing_list_idx):
+ bin = get_bin_qty(packing_item_code, warehouse)
+ item = get_packing_item_details(packing_item_code)
+
+ # check if exists
+ exists = 0
+ for d in getlist(obj.doclist, 'packing_details'):
+ if d.parent_item == line.item_code and d.item_code == packing_item_code and d.parent_detail_docname == line.name:
+ pi, exists = d, 1
+ break
+
+ if not exists:
+ pi = addchild(obj.doc, 'packing_details', 'Packed Item', obj.doclist)
+
+ pi.parent_item = line.item_code
+ pi.item_code = packing_item_code
+ pi.item_name = item['item_name']
+ pi.parent_detail_docname = line.name
+ pi.description = item['description']
+ pi.uom = item['stock_uom']
+ pi.qty = flt(qty)
+ pi.actual_qty = bin and flt(bin['actual_qty']) or 0
+ pi.projected_qty = bin and flt(bin['projected_qty']) or 0
+ if not pi.warehouse:
+ pi.warehouse = warehouse
+ if not pi.batch_no:
+ pi.batch_no = cstr(line.batch_no)
+ pi.idx = packing_list_idx
+
+ # saved, since this function is called on_update of delivery note
+ pi.save()
+
+ packing_list_idx += 1
+
+
+def make_packing_list(obj, item_table_fieldname):
+ """make packing list for sales bom item"""
+ packing_list_idx = 0
+ parent_items = []
+ for d in obj.doclist.get({"parentfield": item_table_fieldname}):
+ warehouse = (item_table_fieldname == "sales_order_details") \
+ and d.reserved_warehouse or d.warehouse
+ if webnotes.conn.get_value("Sales BOM", {"new_item_code": d.item_code}):
+ for i in get_sales_bom_items(d.item_code):
+ update_packing_list_item(obj, i['item_code'], flt(i['qty'])*flt(d.qty),
+ warehouse, d, packing_list_idx)
+
+ if [d.item_code, d.name] not in parent_items:
+ parent_items.append([d.item_code, d.name])
+
+ obj.doclist = cleanup_packing_list(obj, parent_items)
+
+ return obj.doclist
+
+def cleanup_packing_list(obj, parent_items):
+ """Remove all those child items which are no longer present in main item table"""
+ delete_list = []
+ for d in obj.doclist.get({"parentfield": "packing_details"}):
+ if [d.parent_item, d.parent_detail_docname] not in parent_items:
+ # mark for deletion from doclist
+ delete_list.append(d.name)
+
+ if not delete_list:
+ return obj.doclist
+
+ # delete from doclist
+ obj.doclist = webnotes.doclist(filter(lambda d: d.name not in delete_list, obj.doclist))
+
+ # delete from db
+ webnotes.conn.sql("""\
+ delete from `tabPacked Item`
+ where name in (%s)"""
+ % (", ".join(["%s"] * len(delete_list))),
+ tuple(delete_list))
+
+ return obj.doclist
\ No newline at end of file
diff --git a/stock/doctype/delivery_note_packing_item/delivery_note_packing_item.txt b/stock/doctype/packed_item/packed_item.txt
similarity index 95%
rename from stock/doctype/delivery_note_packing_item/delivery_note_packing_item.txt
rename to stock/doctype/packed_item/packed_item.txt
index 441b13a..8320502 100644
--- a/stock/doctype/delivery_note_packing_item/delivery_note_packing_item.txt
+++ b/stock/doctype/packed_item/packed_item.txt
@@ -2,7 +2,7 @@
{
"creation": "2013-02-22 01:28:00",
"docstatus": 0,
- "modified": "2013-07-10 14:54:08",
+ "modified": "2013-10-16 16:37:31",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -15,14 +15,14 @@
{
"doctype": "DocField",
"name": "__common__",
- "parent": "Delivery Note Packing Item",
+ "parent": "Packed Item",
"parentfield": "fields",
"parenttype": "DocType",
"permlevel": 0
},
{
"doctype": "DocType",
- "name": "Delivery Note Packing Item"
+ "name": "Packed Item"
},
{
"doctype": "DocField",
diff --git a/stock/doctype/purchase_receipt/purchase_receipt.py b/stock/doctype/purchase_receipt/purchase_receipt.py
index 1379406..99cbd0b 100644
--- a/stock/doctype/purchase_receipt/purchase_receipt.py
+++ b/stock/doctype/purchase_receipt/purchase_receipt.py
@@ -227,7 +227,6 @@
# on submit
def on_submit(self):
purchase_controller = webnotes.get_obj("Purchase Common")
- purchase_controller.is_item_table_empty(self)
# Check for Approving Authority
get_obj('Authorization Control').validate_approving_authority(self.doc.doctype, self.doc.company, self.doc.grand_total)
diff --git a/stock/doctype/serial_no/serial_no.py b/stock/doctype/serial_no/serial_no.py
index 22a16b5..9496d6a 100644
--- a/stock/doctype/serial_no/serial_no.py
+++ b/stock/doctype/serial_no/serial_no.py
@@ -189,6 +189,9 @@
self.set_status()
self.set_purchase_details()
self.set_sales_details()
+
+ def on_communication(self):
+ return
def process_serial_no(sle):
item_det = get_item_details(sle.item_code)
diff --git a/stock/doctype/stock_entry/stock_entry.js b/stock/doctype/stock_entry/stock_entry.js
index e451f89..007e986 100644
--- a/stock/doctype/stock_entry/stock_entry.js
+++ b/stock/doctype/stock_entry/stock_entry.js
@@ -1,6 +1,9 @@
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
// License: GNU General Public License v3. See license.txt
+cur_frm.cscript.tname = "Stock Entry Detail";
+cur_frm.cscript.fname = "mtn_details";
+
wn.require("public/app/js/controllers/stock_controller.js");
wn.provide("erpnext.stock");
@@ -112,12 +115,6 @@
}
},
- entries_add: function(doc, cdt, cdn) {
- var row = wn.model.get_doc(cdt, cdn);
- this.frm.script_manager.copy_from_first_row("mtn_details", row,
- ["expense_account", "cost_center"]);
- },
-
clean_up: function() {
// Clear Production Order record from locals, because it is updated via Stock Entry
if(this.frm.doc.production_order &&
@@ -147,11 +144,18 @@
},
production_order: function() {
+ var me = this;
this.toggle_enable_bom();
return this.frm.call({
method: "get_production_order_details",
- args: {production_order: this.frm.doc.production_order}
+ args: {production_order: this.frm.doc.production_order},
+ callback: function(r) {
+ if (!r.exc) {
+ if (me.frm.doc.purpose == "Material Transfer" && !me.frm.doc.to_warehouse)
+ me.frm.set_value("to_warehouse", r.message["wip_warehouse"]);
+ }
+ }
});
},
@@ -224,6 +228,8 @@
mtn_details_add: function(doc, cdt, cdn) {
var row = wn.model.get_doc(cdt, cdn);
+ this.frm.script_manager.copy_from_first_row("mtn_details", row,
+ ["expense_account", "cost_center"]);
if(!row.s_warehouse) row.s_warehouse = this.frm.doc.from_warehouse;
if(!row.t_warehouse) row.t_warehouse = this.frm.doc.to_warehouse;
@@ -260,24 +266,29 @@
}
}
-cur_frm.cscript.delivery_note_no = function(doc,cdt,cdn){
- if(doc.delivery_note_no) return get_server_fields('get_cust_values','','',doc,cdt,cdn,1);
+cur_frm.cscript.delivery_note_no = function(doc, cdt, cdn) {
+ if(doc.delivery_note_no)
+ return get_server_fields('get_cust_values', '', '', doc, cdt, cdn, 1);
}
-cur_frm.cscript.sales_invoice_no = function(doc,cdt,cdn){
- if(doc.sales_invoice_no) return get_server_fields('get_cust_values','','',doc,cdt,cdn,1);
+cur_frm.cscript.sales_invoice_no = function(doc, cdt, cdn) {
+ if(doc.sales_invoice_no)
+ return get_server_fields('get_cust_values', '', '', doc, cdt, cdn, 1);
}
-cur_frm.cscript.customer = function(doc,cdt,cdn){
- if(doc.customer) return get_server_fields('get_cust_addr','','',doc,cdt,cdn,1);
+cur_frm.cscript.customer = function(doc, cdt, cdn) {
+ if(doc.customer)
+ return get_server_fields('get_cust_addr', '', '', doc, cdt, cdn, 1);
}
-cur_frm.cscript.purchase_receipt_no = function(doc,cdt,cdn){
- if(doc.purchase_receipt_no) return get_server_fields('get_supp_values','','',doc,cdt,cdn,1);
+cur_frm.cscript.purchase_receipt_no = function(doc, cdt, cdn) {
+ if(doc.purchase_receipt_no)
+ return get_server_fields('get_supp_values', '', '', doc, cdt, cdn, 1);
}
-cur_frm.cscript.supplier = function(doc,cdt,cdn){
- if(doc.supplier) return get_server_fields('get_supp_addr','','',doc,cdt,cdn,1);
+cur_frm.cscript.supplier = function(doc, cdt, cdn) {
+ if(doc.supplier)
+ return get_server_fields('get_supp_addr', '', '', doc, cdt, cdn, 1);
}
@@ -314,13 +325,17 @@
cur_frm.cscript.item_code = function(doc, cdt, cdn) {
var d = locals[cdt][cdn];
args = {
- 'item_code' : d.item_code,
- 'warehouse' : cstr(d.s_warehouse) || cstr(d.t_warehouse),
- 'transfer_qty' : d.transfer_qty,
- 'serial_no' : d.serial_no,
- 'bom_no' : d.bom_no
+ 'item_code' : d.item_code,
+ 'warehouse' : cstr(d.s_warehouse) || cstr(d.t_warehouse),
+ 'transfer_qty' : d.transfer_qty,
+ 'serial_no' : d.serial_no,
+ 'bom_no' : d.bom_no,
+ 'expense_account' : d.expense_account,
+ 'cost_center' : d.cost_center,
+ 'company' : cur_frm.doc.company
};
- return get_server_fields('get_item_details',JSON.stringify(args),'mtn_details',doc,cdt,cdn,1);
+ return get_server_fields('get_item_details', JSON.stringify(args),
+ 'mtn_details', doc, cdt, cdn, 1);
}
cur_frm.cscript.s_warehouse = function(doc, cdt, cdn) {
@@ -343,7 +358,8 @@
var d = locals[cdt][cdn];
if(d.uom && d.item_code){
var arg = {'item_code':d.item_code, 'uom':d.uom, 'qty':d.qty}
- return get_server_fields('get_uom_details',JSON.stringify(arg),'mtn_details', doc, cdt, cdn, 1);
+ return get_server_fields('get_uom_details', JSON.stringify(arg),
+ 'mtn_details', doc, cdt, cdn, 1);
}
}
@@ -354,15 +370,25 @@
}
cur_frm.cscript.validate_items = function(doc) {
- cl = getchildren('Stock Entry Detail',doc.name,'mtn_details');
+ cl = getchildren('Stock Entry Detail', doc.name, 'mtn_details');
if (!cl.length) {
alert(wn._("Item table can not be blank"));
validated = false;
}
}
-cur_frm.fields_dict.customer.get_query = function(doc,cdt,cdn) {
- return{ query:"controllers.queries.customer_query" } }
+cur_frm.cscript.expense_account = function(doc, cdt, cdn) {
+ cur_frm.cscript.copy_account_in_all_row(doc, cdt, cdn, "expense_account");
+}
-cur_frm.fields_dict.supplier.get_query = function(doc,cdt,cdn) {
- return{ query:"controllers.queries.supplier_query" } }
+cur_frm.cscript.cost_center = function(doc, cdt, cdn) {
+ cur_frm.cscript.copy_account_in_all_row(doc, cdt, cdn, "cost_center");
+}
+
+cur_frm.fields_dict.customer.get_query = function(doc, cdt, cdn) {
+ return{ query:"controllers.queries.customer_query" }
+}
+
+cur_frm.fields_dict.supplier.get_query = function(doc, cdt, cdn) {
+ return{ query:"controllers.queries.supplier_query" }
+}
diff --git a/stock/doctype/stock_entry/stock_entry.py b/stock/doctype/stock_entry/stock_entry.py
index 217a0aa..3837ca1 100644
--- a/stock/doctype/stock_entry/stock_entry.py
+++ b/stock/doctype/stock_entry/stock_entry.py
@@ -366,8 +366,8 @@
def get_item_details(self, arg):
arg = json.loads(arg)
-
- item = webnotes.conn.sql("""select stock_uom, description, item_name from `tabItem`
+ item = webnotes.conn.sql("""select stock_uom, description, item_name,
+ purchase_account, cost_center from `tabItem`
where name = %s and (ifnull(end_of_life,'')='' or end_of_life ='0000-00-00'
or end_of_life > now())""", (arg.get('item_code')), as_dict = 1)
if not item:
@@ -378,6 +378,9 @@
'stock_uom' : item and item[0]['stock_uom'] or '',
'description' : item and item[0]['description'] or '',
'item_name' : item and item[0]['item_name'] or '',
+ 'expense_account' : item and item[0]['purchase_account'] or arg.get("expense_account") \
+ or webnotes.conn.get_value("Company", arg.get("company"), "default_expense_account"),
+ 'cost_center' : item and item[0]['cost_center'] or arg.get("cost_center"),
'qty' : 0,
'transfer_qty' : 0,
'conversion_factor' : 1,
@@ -466,11 +469,12 @@
if self.doc.purpose=="Material Receipt":
self.doc.from_warehouse = ""
- item = webnotes.conn.sql("""select item, description, uom from `tabBOM`
- where name=%s""", (self.doc.bom_no,), as_dict=1)
+ item = webnotes.conn.sql("""select name, item_name, description, uom
+ from `tabItem` where name=%s""", (self.doc.bom_no), as_dict=1)
self.add_to_stock_entry_detail({
item[0]["item"] : {
"qty": self.doc.fg_completed_qty,
+ "item_name": item[0].item_name,
"description": item[0]["description"],
"stock_uom": item[0]["uom"],
"from_warehouse": ""
@@ -478,7 +482,6 @@
}, bom_no=self.doc.bom_no)
self.get_stock_and_rate()
-
def get_bom_raw_materials(self, qty):
from manufacturing.doctype.bom.bom import get_bom_items_as_dict
@@ -541,16 +544,24 @@
return issued_item_qty
def add_to_stock_entry_detail(self, item_dict, bom_no=None):
+ idx = 1
+ expense_account, cost_center = webnotes.conn.get_values("Company", self.doc.company, \
+ ["default_expense_account", "cost_center"])[0]
+
for d in item_dict:
se_child = addchild(self.doc, 'mtn_details', 'Stock Entry Detail',
self.doclist)
+ se_child.idx = idx
se_child.s_warehouse = item_dict[d].get("from_warehouse", self.doc.from_warehouse)
se_child.t_warehouse = item_dict[d].get("to_warehouse", self.doc.to_warehouse)
se_child.item_code = cstr(d)
+ se_child.item_name = item_dict[d]["item_name"]
se_child.description = item_dict[d]["description"]
se_child.uom = item_dict[d]["stock_uom"]
se_child.stock_uom = item_dict[d]["stock_uom"]
se_child.qty = flt(item_dict[d]["qty"])
+ se_child.expense_account = item_dict[d]["expense_account"] or expense_account
+ se_child.cost_center = item_dict[d]["cost_center"] or cost_center
# in stock uom
se_child.transfer_qty = flt(item_dict[d]["qty"])
@@ -559,6 +570,9 @@
# to be assigned for finished item
se_child.bom_no = bom_no
+ # increment idx by 1
+ idx += 1
+
def get_cust_values(self):
"""fetches customer details"""
if self.doc.delivery_note_no:
@@ -624,8 +638,8 @@
@webnotes.whitelist()
def get_production_order_details(production_order):
result = webnotes.conn.sql("""select bom_no,
- ifnull(qty, 0) - ifnull(produced_qty, 0) as fg_completed_qty, use_multi_level_bom
- from `tabProduction Order` where name = %s""", production_order, as_dict=1)
+ ifnull(qty, 0) - ifnull(produced_qty, 0) as fg_completed_qty, use_multi_level_bom,
+ wip_warehouse from `tabProduction Order` where name = %s""", production_order, as_dict=1)
return result and result[0] or {}
def query_sales_return_doc(doctype, txt, searchfield, start, page_len, filters):
diff --git a/stock/doctype/stock_entry_detail/stock_entry_detail.txt b/stock/doctype/stock_entry_detail/stock_entry_detail.txt
index b400cdd..5218c1a 100644
--- a/stock/doctype/stock_entry_detail/stock_entry_detail.txt
+++ b/stock/doctype/stock_entry_detail/stock_entry_detail.txt
@@ -2,7 +2,7 @@
{
"creation": "2013-03-29 18:22:12",
"docstatus": 0,
- "modified": "2013-08-28 19:25:38",
+ "modified": "2013-10-23 14:35:46",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -67,6 +67,14 @@
},
{
"doctype": "DocField",
+ "fieldname": "item_name",
+ "fieldtype": "Data",
+ "label": "Item Name",
+ "print_hide": 1,
+ "read_only": 1
+ },
+ {
+ "doctype": "DocField",
"fieldname": "description",
"fieldtype": "Text",
"in_list_view": 1,
@@ -154,6 +162,7 @@
"print_hide": 1
},
{
+ "default": ":Company",
"depends_on": "eval:sys_defaults.auto_accounting_for_stock",
"doctype": "DocField",
"fieldname": "cost_center",
diff --git a/stock/doctype/stock_settings/stock_settings.py b/stock/doctype/stock_settings/stock_settings.py
index bc7dcba..e457257 100644
--- a/stock/doctype/stock_settings/stock_settings.py
+++ b/stock/doctype/stock_settings/stock_settings.py
@@ -6,6 +6,7 @@
from __future__ import unicode_literals
import webnotes
+
class DocType:
def __init__(self, d, dl):
self.doc, self.doclist = d, dl
@@ -14,3 +15,8 @@
for key in ["item_naming_by", "item_group", "stock_uom",
"allow_negative_stock"]:
webnotes.conn.set_default(key, self.doc.fields.get(key, ""))
+
+ from setup.doctype.naming_series.naming_series import set_by_naming_series
+ set_by_naming_series("Item", "item_code",
+ self.doc.get("item_naming_by")=="Naming Series", hide_name_field=True)
+
diff --git a/stock/doctype/warehouse/warehouse.py b/stock/doctype/warehouse/warehouse.py
index 97a8826..89d2ee1 100644
--- a/stock/doctype/warehouse/warehouse.py
+++ b/stock/doctype/warehouse/warehouse.py
@@ -3,11 +3,9 @@
from __future__ import unicode_literals
import webnotes
-
-from webnotes.utils import cint, flt, validate_email_add
+from webnotes.utils import cint, validate_email_add
from webnotes import msgprint, _
-
class DocType:
def __init__(self, doc, doclist=[]):
self.doc = doc
@@ -30,8 +28,8 @@
if not webnotes.conn.get_value("Account", {"account_type": "Warehouse",
"master_name": self.doc.name}) and not webnotes.conn.get_value("Account",
{"account_name": self.doc.warehouse_name}):
- if self.doc.fields.get("__islocal") or not webnotes.conn.get_value("Stock Ledger Entry",
- {"warehouse": self.doc.name}):
+ if self.doc.fields.get("__islocal") or not webnotes.conn.get_value(
+ "Stock Ledger Entry", {"warehouse": self.doc.name}):
self.validate_parent_account()
ac_bean = webnotes.bean({
"doctype": "Account",
@@ -101,7 +99,8 @@
def on_trash(self):
# delete bin
- bins = webnotes.conn.sql("select * from `tabBin` where warehouse = %s", self.doc.name, as_dict=1)
+ bins = webnotes.conn.sql("select * from `tabBin` where warehouse = %s",
+ self.doc.name, as_dict=1)
for d in bins:
if d['actual_qty'] or d['reserved_qty'] or d['ordered_qty'] or \
d['indented_qty'] or d['projected_qty'] or d['planned_qty']:
@@ -116,8 +115,10 @@
webnotes.delete_doc("Account", warehouse_account)
# delete cancelled sle
- if webnotes.conn.sql("""select name from `tabStock Ledger Entry` where warehouse = %s""", self.doc.name):
+ if webnotes.conn.sql("""select name from `tabStock Ledger Entry` where warehouse = %s""",
+ self.doc.name):
msgprint("""Warehosue can not be deleted as stock ledger entry
exists for this warehouse.""", raise_exception=1)
else:
- webnotes.conn.sql("delete from `tabStock Ledger Entry` where warehouse = %s", self.doc.name)
+ webnotes.conn.sql("delete from `tabStock Ledger Entry` where warehouse = %s",
+ self.doc.name)
diff --git a/stock/page/stock_home/stock_home.js b/stock/page/stock_home/stock_home.js
index e99c1fc..4998a19 100644
--- a/stock/page/stock_home/stock_home.js
+++ b/stock/page/stock_home/stock_home.js
@@ -77,7 +77,12 @@
{
"doctype":"Price List",
"label": wn._("Price List"),
- "description": wn._("Multiple Item Prices")
+ "description": wn._("Multiple Price list.")
+ },
+ {
+ "doctype":"Item Price",
+ "label": wn._("Item Price"),
+ "description": wn._("Multiple Item prices.")
},
{
"doctype":"Quality Inspection",
@@ -202,8 +207,8 @@
},
{
"label":wn._("Item-wise Price List Rate"),
- route: "Report/Price List/Item-Wise Price List",
- doctype: "Price List"
+ route: "Report/Item Price/Item-wise Price List Rate",
+ doctype: "Item Price"
},
{
"label":wn._("Purchase In Transit"),
diff --git a/stock/report/item_prices/item_prices.py b/stock/report/item_prices/item_prices.py
index 70c0677..2bb3779 100644
--- a/stock/report/item_prices/item_prices.py
+++ b/stock/report/item_prices/item_prices.py
@@ -57,10 +57,9 @@
rate = {}
- price_list = webnotes.conn.sql("""select ip.item_code, pl.buying_or_selling,
- concat(pl.name, " - ", pl.currency, " ", ip.ref_rate) as price
- from `tabItem Price` ip, `tabPrice List` pl where
- ip.parent = pl.name and pl.docstatus<2""", as_dict=1)
+ price_list = webnotes.conn.sql("""select item_code, buying_or_selling,
+ concat(price_list, " - ", currency, " ", ref_rate) as price
+ from `tabItem Price`""", as_dict=1)
for j in price_list:
if j.price:
diff --git a/support/doctype/newsletter/newsletter.py b/support/doctype/newsletter/newsletter.py
index 8e45768..b480b7d 100644
--- a/support/doctype/newsletter/newsletter.py
+++ b/support/doctype/newsletter/newsletter.py
@@ -111,6 +111,7 @@
def create_lead(email_id):
"""create a lead if it does not exist"""
from email.utils import parseaddr
+ from webnotes.model.doc import get_default_naming_series
real_name, email_id = parseaddr(email_id)
if webnotes.conn.get_value("Lead", {"email_id": email_id}):
@@ -121,24 +122,8 @@
"email_id": email_id,
"lead_name": real_name or email_id,
"status": "Contacted",
- "naming_series": get_lead_naming_series(),
+ "naming_series": get_default_naming_series("Lead"),
"company": webnotes.conn.get_default("company"),
"source": "Email"
})
- lead.insert()
-
-def get_lead_naming_series():
- """gets lead's default naming series"""
- lead_naming_series = None
- naming_series_field = webnotes.get_doctype("Lead").get_field("naming_series")
- if naming_series_field.default:
- lead_naming_series = naming_series_field.default
- else:
- latest_naming_series = webnotes.conn.sql("""select naming_series
- from `tabLead` order by creation desc limit 1""")
- if latest_naming_series:
- lead_naming_series = latest_naming_series[0][0]
- else:
- lead_naming_series = filter(None, naming_series_field.options.split("\n"))[0]
-
- return lead_naming_series
+ lead.insert()
\ No newline at end of file
diff --git a/translations/ar.csv b/translations/ar.csv
index 9e075a8..9856580 100644
--- a/translations/ar.csv
+++ b/translations/ar.csv
@@ -814,7 +814,7 @@
Delivery Note Items,ملاحظة عناصر التسليم
Delivery Note Message,ملاحظة تسليم رسالة
Delivery Note No,ملاحظة لا تسليم
-Delivery Note Packing Item,ملاحظة التوصيل التغليف
+Packed Item,ملاحظة التوصيل التغليف
Delivery Note Required,ملاحظة التسليم المطلوبة
Delivery Note Trends,ملاحظة اتجاهات التسليم
Delivery Status,حالة التسليم
diff --git a/translations/de.csv b/translations/de.csv
index ccb2c88..7cf514e 100644
--- a/translations/de.csv
+++ b/translations/de.csv
@@ -814,7 +814,7 @@
Delivery Note Items,Lieferscheinpositionen
Delivery Note Message,Lieferschein Nachricht
Delivery Note No,Lieferschein Nein
-Delivery Note Packing Item,Lieferschein Verpackung Artikel
+Packed Item,Lieferschein Verpackung Artikel
Delivery Note Required,Lieferschein erforderlich
Delivery Note Trends,Lieferschein Trends
Delivery Status,Lieferstatus
diff --git a/translations/el.csv b/translations/el.csv
index 7d429bb..8b604e7 100644
--- a/translations/el.csv
+++ b/translations/el.csv
@@ -827,7 +827,7 @@
Delivery Note Items,Σημείωση Στοιχεία Παράδοσης
Delivery Note Message,Αποστολή μηνύματος Σημείωση
Delivery Note No,Σημείωση παράδοσης αριθ.
-Delivery Note Packing Item,Παράδοση Θέση Συσκευασία Σημείωση
+Packed Item,Παράδοση Θέση Συσκευασία Σημείωση
Delivery Note Required,Σημείωση παράδοσης Απαιτείται
Delivery Note Trends,Τάσεις Σημείωση Παράδοση
Delivery Status,Κατάσταση παράδοσης
diff --git a/translations/es.csv b/translations/es.csv
index d30649d..4ab32b5 100644
--- a/translations/es.csv
+++ b/translations/es.csv
@@ -814,7 +814,7 @@
Delivery Note Items,Artículos de entrega Nota
Delivery Note Message,Entrega de mensajes Nota
Delivery Note No,Entrega Nota No
-Delivery Note Packing Item,Nota de Entrega Embalaje artículo
+Packed Item,Nota de Entrega Embalaje artículo
Delivery Note Required,Nota de entrega requerida
Delivery Note Trends,Tendencias albarán
Delivery Status,Estado de entrega
diff --git a/translations/fr.csv b/translations/fr.csv
index dacdd2f..d9c0d87 100644
--- a/translations/fr.csv
+++ b/translations/fr.csv
@@ -814,7 +814,7 @@
Delivery Note Items,Articles bordereau de livraison
Delivery Note Message,Note Message de livraison
Delivery Note No,Remarque Aucune livraison
-Delivery Note Packing Item,Article d'emballage de livraison Note
+Packed Item,Article d'emballage de livraison Note
Delivery Note Required,Remarque livraison requis
Delivery Note Trends,Bordereau de livraison Tendances
Delivery Status,Delivery Status
diff --git a/translations/hi.csv b/translations/hi.csv
index 6f9576c..8e2fcaf 100644
--- a/translations/hi.csv
+++ b/translations/hi.csv
@@ -814,7 +814,7 @@
Delivery Note Items,डिलिवरी नोट आइटम
Delivery Note Message,डिलिवरी नोट संदेश
Delivery Note No,डिलिवरी नोट
-Delivery Note Packing Item,डिलिवरी नोट पैकिंग आइटम
+Packed Item,डिलिवरी नोट पैकिंग आइटम
Delivery Note Required,डिलिवरी नोट आवश्यक
Delivery Note Trends,डिलिवरी नोट रुझान
Delivery Status,डिलिवरी स्थिति
diff --git a/translations/hr.csv b/translations/hr.csv
index d60f85b..20b5cc7 100644
--- a/translations/hr.csv
+++ b/translations/hr.csv
@@ -814,7 +814,7 @@
Delivery Note Items,Način Napomena Stavke
Delivery Note Message,Otpremnica Poruka
Delivery Note No,Dostava Napomena Ne
-Delivery Note Packing Item,Dostava Napomena Pakiranje artikla
+Packed Item,Dostava Napomena Pakiranje artikla
Delivery Note Required,Dostava Napomena Obavezno
Delivery Note Trends,Otpremnici trendovi
Delivery Status,Status isporuke
diff --git a/translations/it.csv b/translations/it.csv
index c91fc84..e9e2106 100644
--- a/translations/it.csv
+++ b/translations/it.csv
Binary files differ
diff --git a/translations/nl.csv b/translations/nl.csv
index 3cc7152..c9b5aa2 100644
--- a/translations/nl.csv
+++ b/translations/nl.csv
@@ -814,7 +814,7 @@
Delivery Note Items,Levering Opmerking Items
Delivery Note Message,Levering Opmerking Bericht
Delivery Note No,Levering aantekening
-Delivery Note Packing Item,Levering Opmerking Verpakking Item
+Packed Item,Levering Opmerking Verpakking Item
Delivery Note Required,Levering Opmerking Verplicht
Delivery Note Trends,Delivery Note Trends
Delivery Status,Delivery Status
diff --git a/translations/pt-BR.csv b/translations/pt-BR.csv
index 274c7d4..7dfb0a2 100644
--- a/translations/pt-BR.csv
+++ b/translations/pt-BR.csv
@@ -814,7 +814,7 @@
Delivery Note Items,Itens da Guia de Remessa
Delivery Note Message,Mensagem da Guia de Remessa
Delivery Note No,Nº da Guia de Remessa
-Delivery Note Packing Item,Item do Pacote da Guia de Remessa
+Packed Item,Item do Pacote da Guia de Remessa
Delivery Note Required,Guia de Remessa Obrigatória
Delivery Note Trends,Nota de entrega Trends
Delivery Status,Estado da entrega
diff --git a/translations/pt.csv b/translations/pt.csv
index 31d20bc..900d4da 100644
--- a/translations/pt.csv
+++ b/translations/pt.csv
@@ -814,7 +814,7 @@
Delivery Note Items,Nota Itens de entrega
Delivery Note Message,Mensagem Nota de Entrega
Delivery Note No,Nota de Entrega Não
-Delivery Note Packing Item,Entrega do item embalagem Nota
+Packed Item,Entrega do item embalagem Nota
Delivery Note Required,Nota de Entrega Obrigatório
Delivery Note Trends,Nota de entrega Trends
Delivery Status,Estado entrega
diff --git a/translations/sr.csv b/translations/sr.csv
index aa14049..fc9513b 100644
--- a/translations/sr.csv
+++ b/translations/sr.csv
@@ -814,7 +814,7 @@
Delivery Note Items,Достава Напомена Ставке
Delivery Note Message,Испорука Напомена порука
Delivery Note No,Испорука Напомена Не
-Delivery Note Packing Item,Испорука Напомена Паковање јединице
+Packed Item,Испорука Напомена Паковање јединице
Delivery Note Required,Испорука Напомена Обавезно
Delivery Note Trends,Достава Напомена трендови
Delivery Status,Статус испоруке
diff --git a/translations/ta.csv b/translations/ta.csv
index 74cc74b..f21f27b 100644
--- a/translations/ta.csv
+++ b/translations/ta.csv
@@ -814,7 +814,7 @@
Delivery Note Items,டெலிவரி குறிப்பு உருப்படிகள்
Delivery Note Message,டெலிவரி குறிப்பு செய்தி
Delivery Note No,டெலிவரி குறிப்பு இல்லை
-Delivery Note Packing Item,டெலிவரி குறிப்பு தடைக்காப்பு பொருள்
+Packed Item,டெலிவரி குறிப்பு தடைக்காப்பு பொருள்
Delivery Note Required,டெலிவரி குறிப்பு தேவை
Delivery Note Trends,பந்து குறிப்பு போக்குகள்
Delivery Status,விநியோக நிலைமை
diff --git a/translations/th.csv b/translations/th.csv
index 7a461f0..3cf2d9c 100644
--- a/translations/th.csv
+++ b/translations/th.csv
@@ -814,7 +814,7 @@
Delivery Note Items,รายการจัดส่งสินค้าหมายเหตุ
Delivery Note Message,ข้อความหมายเหตุจัดส่งสินค้า
Delivery Note No,หมายเหตุจัดส่งสินค้าไม่มี
-Delivery Note Packing Item,จัดส่งสินค้าบรรจุหมายเหตุ
+Packed Item,จัดส่งสินค้าบรรจุหมายเหตุ
Delivery Note Required,หมายเหตุจัดส่งสินค้าที่จำเป็น
Delivery Note Trends,แนวโน้มหมายเหตุการจัดส่งสินค้า
Delivery Status,สถานะการจัดส่งสินค้า
diff --git a/utilities/repost_stock.py b/utilities/repost_stock.py
index 7359304..8b69675 100644
--- a/utilities/repost_stock.py
+++ b/utilities/repost_stock.py
@@ -13,8 +13,11 @@
"""
webnotes.conn.auto_commit_on_many_writes = 1
- for d in webnotes.conn.sql("select item_code, warehouse from tabBin"):
- repost_stock(d[0], d[1])
+ for d in webnotes.conn.sql("""select distinct item_code, warehouse from
+ (select item_code, warehouse from tabBin
+ union
+ select item_code, warehouse from `tabStock Ledger Entry`) a"""):
+ repost_stock(d[0], d[1])
webnotes.conn.auto_commit_on_many_writes = 0
@@ -31,7 +34,10 @@
def repost_actual_qty(item_code, warehouse):
from stock.stock_ledger import update_entries_after
- update_entries_after({ "item_code": item_code, "warehouse": warehouse })
+ try:
+ update_entries_after({ "item_code": item_code, "warehouse": warehouse })
+ except:
+ pass
def get_reserved_qty(item_code, warehouse):
reserved_qty = webnotes.conn.sql("""
@@ -53,7 +59,7 @@
from
(
select qty, parent_detail_docname, parent, name
- from `tabDelivery Note Packing Item` dnpi_in
+ from `tabPacked Item` dnpi_in
where item_code = %s and warehouse = %s
and parenttype="Sales Order"
and item_code != parent_item