[merge] merged with master

This commit is contained in:
Nabin Hait
2013-10-24 11:21:11 +05:30
61 changed files with 974 additions and 705 deletions

View File

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

View File

@@ -5,9 +5,7 @@ from __future__ import unicode_literals
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 @@ class DocType:
where doctype='Global Defaults' and field='default_company'
and value=%s""", (newdn, olddn))
webnotes.defaults.clear_default("company", value=olddn)
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()

View File

@@ -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"
},
@@ -175,13 +175,6 @@
"options": "Standard\nClassic\nModern\nSpartan",
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "hr",
"fieldtype": "Section Break",
"label": "HR",
"read_only": 0
},
{
"doctype": "DocPerm"
}

View File

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

View File

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

View File

@@ -2,52 +2,126 @@
{
"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",
"name": "Item Price"
},
{
"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"
}
]

View File

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

View File

@@ -5,253 +5,13 @@ $.extend(cur_frm.cscript, {
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");
}
});

View File

@@ -8,8 +8,6 @@ from webnotes.utils import comma_or, cint
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 @@ class DocType(DocListController):
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 @@ class DocType(DocListController):
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))

View File

@@ -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"
},
@@ -84,27 +84,6 @@
"options": "For Territory",
"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,

View File

@@ -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 @@ test_records = [
"parentfield": "valid_for_territories",
"territory": "All Territories"
},
{
"doctype": "Item Price",
"parentfield": "item_prices",
"item_code": "_Test Item",
"ref_rate": 100
}
],
[
{

View File

@@ -41,6 +41,7 @@ items = [
{"doctype":"UOM"},
{"doctype":"Brand"},
{"doctype":"Price List"},
{"doctype": "Item Price"},
{ "title": "Stock Settings",
"route": "Form/Stock Settings", "type": "Link", "icon": "icon-cog" },
],

View File

@@ -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"
}
]

View File

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