[minor] merge conflict fixed

This commit is contained in:
Nabin Hait 2013-11-21 12:28:50 +05:30
commit 8eb0c61649
25 changed files with 225 additions and 226 deletions

View File

@ -192,41 +192,40 @@ class DocType:
if self.check_gle_exists(): if self.check_gle_exists():
msgprint("""Account with existing transaction (Sales Invoice / Purchase Invoice / \ msgprint("""Account with existing transaction (Sales Invoice / Purchase Invoice / \
Journal Voucher) can not be trashed""", raise_exception=1) Journal Voucher) can not be deleted""", raise_exception=1)
if self.check_if_child_exists(): if self.check_if_child_exists():
msgprint("Child account exists for this account. You can not trash this account.", msgprint("Child account exists for this account. You can not delete this account.",
raise_exception=1) raise_exception=1)
def on_trash(self): def on_trash(self):
self.validate_trash() self.validate_trash()
self.update_nsm_model() self.update_nsm_model()
def on_rename(self, new, old, merge=False): def before_rename(self, old, new, merge=False):
company_abbr = webnotes.conn.get_value("Company", self.doc.company, "abbr") # Add company abbr if not provided
parts = new.split(" - ") from setup.doctype.company.company import get_name_with_abbr
new_account = get_name_with_abbr(new, self.doc.company)
if parts[-1].lower() != company_abbr.lower():
parts.append(company_abbr)
# rename account name
new_account_name = " - ".join(parts[:-1])
webnotes.conn.sql("update `tabAccount` set account_name = %s where name = %s", (new_account_name, old))
# Validate properties before merging
if merge: if merge:
new_name = " - ".join(parts) val = list(webnotes.conn.get_value("Account", new_account,
val = list(webnotes.conn.get_value("Account", new_name,
["group_or_ledger", "debit_or_credit", "is_pl_account"])) ["group_or_ledger", "debit_or_credit", "is_pl_account"]))
if val != [self.doc.group_or_ledger, self.doc.debit_or_credit, self.doc.is_pl_account]: if val != [self.doc.group_or_ledger, self.doc.debit_or_credit, self.doc.is_pl_account]:
msgprint(_("""Merging is only possible if following \ webnotes.throw(_("""Merging is only possible if following \
properties are same in both records. properties are same in both records.
Group or Ledger, Debit or Credit, Is PL Account"""), raise_exception=1) Group or Ledger, Debit or Credit, Is PL Account"""))
return new_account
def after_rename(self, old, new, merge=False):
if not merge:
webnotes.conn.set_value("Account", new, "account_name",
" - ".join(new.split(" - ")[:-1]))
else:
from webnotes.utils.nestedset import rebuild_tree from webnotes.utils.nestedset import rebuild_tree
rebuild_tree("Account", "parent_account") rebuild_tree("Account", "parent_account")
return " - ".join(parts)
def get_master_name(doctype, txt, searchfield, start, page_len, filters): def get_master_name(doctype, txt, searchfield, start, page_len, filters):
conditions = (" and company='%s'"% filters["company"]) if doctype == "Warehouse" else "" conditions = (" and company='%s'"% filters["company"]) if doctype == "Warehouse" else ""

View File

@ -73,18 +73,20 @@ class DocType(DocTypeNestedSet):
self.validate_mandatory() self.validate_mandatory()
self.validate_budget_details() self.validate_budget_details()
def on_rename(self, new, old, merge=False): def before_rename(self, olddn, newdn, merge=False):
company_abbr = webnotes.conn.get_value("Company", self.doc.company, "abbr") # Add company abbr if not provided
parts = new.split(" - ") from setup.doctype.company.company import get_name_with_abbr
new_cost_center = get_name_with_abbr(newdn, self.doc.company)
if parts[-1].lower() != company_abbr.lower(): # Validate properties before merging
parts.append(company_abbr) super(DocType, self).before_rename(olddn, new_cost_center, merge, "group_or_ledger")
# rename account name return new_cost_center
cost_center_name = " - ".join(parts[:-1])
webnotes.conn.sql("update `tabCost Center` set cost_center_name = %s where name = %s", \
(cost_center_name, old))
super(DocType, self).on_rename(new, old, merge, "group_or_ledger") def after_rename(self, olddn, newdn, merge=False):
if not merge:
webnotes.conn.set_value("Cost Center", newdn, "cost_center_name",
" - ".join(newdn.split(" - ")[:-1]))
else:
super(DocType, self).after_rename(olddn, newdn, merge)
return " - ".join(parts)

View File

@ -30,6 +30,11 @@ cur_frm.pformat.purchase_tax_details= function(doc){
return new_val; return new_val;
} }
function print_hide(fieldname) {
var doc_field = wn.meta.get_docfield(doc.doctype, fieldname, doc.name);
return doc_field.print_hide;
}
var cl = getchildren('Purchase Taxes and Charges',doc.name,'purchase_tax_details'); var cl = getchildren('Purchase Taxes and Charges',doc.name,'purchase_tax_details');
// outer table // outer table
@ -38,7 +43,9 @@ cur_frm.pformat.purchase_tax_details= function(doc){
// main table // main table
out +='<table class="noborder" style="width:100%">' out +='<table class="noborder" style="width:100%">'
+make_row('Net Total',convert_rate(doc.net_total),1); if(!print_hide('net_total')) {
out += make_row('Net Total', convert_rate(doc.net_total), 1);
}
// add rows // add rows
if(cl.length){ if(cl.length){
@ -46,10 +53,11 @@ cur_frm.pformat.purchase_tax_details= function(doc){
out += make_row(cl[i].description,convert_rate(cl[i].tax_amount),0); out += make_row(cl[i].description,convert_rate(cl[i].tax_amount),0);
} }
} }
// grand total // grand total
out +=make_row('Grand Total',doc.grand_total_import,1) if(!print_hide('grand_total_import')) {
if(doc.in_words_import){ out += make_row('Grand Total', doc.grand_total_import, 1);
}
if(doc.in_words_import && !print_hide('in_words_import')){
out +='</table></td></tr>'; out +='</table></td></tr>';
out += '<tr><td colspan = "2">'; out += '<tr><td colspan = "2">';
out += '<table><tr><td style="width:25%;"><b>In Words</b></td>'; out += '<table><tr><td style="width:25%;"><b>In Words</b></td>';

View File

@ -73,10 +73,10 @@ def get_costcenter_target_details(filters):
def get_target_distribution_details(filters): def get_target_distribution_details(filters):
target_details = {} target_details = {}
for d in webnotes.conn.sql("""select bd.name, bdd.month, bdd.percentage_allocation \ for d in webnotes.conn.sql("""select bd.name, bdd.month, bdd.percentage_allocation
from `tabBudget Distribution Detail` bdd, `tabBudget Distribution` bd from `tabBudget Distribution Detail` bdd, `tabBudget Distribution` bd
where bdd.parent=bd.name and bd.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1): where bdd.parent=bd.name and bd.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1):
target_details.setdefault(d.name, {}).setdefault(d.month, d.percentage_allocation) target_details.setdefault(d.name, {}).setdefault(d.month, flt(d.percentage_allocation))
return target_details return target_details
@ -113,10 +113,11 @@ def get_costcenter_account_month_map(filters):
})) }))
tav_dict = cam_map[ccd.name][ccd.account][month] tav_dict = cam_map[ccd.name][ccd.account][month]
month_percentage = ccd.distribution_id and \
tdd.get(ccd.distribution_id, {}).get(month, 0) or 100.0/12
tav_dict.target = flt(ccd.budget_allocated) * month_percentage /100 month_percentage = tdd.get(ccd.distribution_id, {}).get(month, 0) \
if ccd.distribution_id else 100.0/12
tav_dict.target = flt(ccd.budget_allocated) * month_percentage / 100
for ad in actual_details.get(ccd.name, {}).get(ccd.account, []): for ad in actual_details.get(ccd.name, {}).get(ccd.account, []):
if ad.month_name == month: if ad.month_name == month:

View File

@ -23,8 +23,8 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
cur_frm.dashboard.add_progress(cint(doc.per_billed) + wn._("% Billed"), cur_frm.dashboard.add_progress(cint(doc.per_billed) + wn._("% Billed"),
doc.per_billed); doc.per_billed);
cur_frm.add_custom_button('Send SMS', cur_frm.cscript.send_sms);
cur_frm.appframe.add_button(wn._('Send SMS'), cur_frm.cscript['Send SMS'], "icon-mobile-phone");
if(flt(doc.per_received, 2) < 100) if(flt(doc.per_received, 2) < 100)
cur_frm.add_custom_button(wn._('Make Purchase Receipt'), this.make_purchase_receipt); cur_frm.add_custom_button(wn._('Make Purchase Receipt'), this.make_purchase_receipt);
if(flt(doc.per_billed, 2) < 100) if(flt(doc.per_billed, 2) < 100)

View File

@ -148,29 +148,21 @@ class DocType(TransactionBase):
self.delete_supplier_contact() self.delete_supplier_contact()
self.delete_supplier_account() self.delete_supplier_account()
def on_rename(self, new, old, merge=False): def after_rename(self, old, new, merge=False):
#update supplier_name if not naming series #update supplier_name if not naming series
if webnotes.defaults.get_global_default('supp_master_name') == 'Supplier Name': if webnotes.defaults.get_global_default('supp_master_name') == 'Supplier Name':
update_fields = [ webnotes.conn.set(self.doc, "supplier_name", new)
('Supplier', 'name'),
('Address', 'supplier'),
('Contact', 'supplier'),
('Purchase Invoice', 'supplier'),
('Purchase Order', 'supplier'),
('Purchase Receipt', 'supplier'),
('Serial No', 'supplier')]
for rec in update_fields:
webnotes.conn.sql("update `tab%s` set supplier_name = %s where `%s` = %s" % \
(rec[0], '%s', rec[1], '%s'), (new, old))
for account in webnotes.conn.sql("""select name, account_name from for account in webnotes.conn.sql("""select name, account_name from
tabAccount where master_name=%s and master_type='Supplier'""", old, as_dict=1): tabAccount where master_name=%s and master_type='Supplier'""", old, as_dict=1):
if account.account_name != new: if account.account_name != new:
webnotes.rename_doc("Account", account.name, new, merge=merge) merge_account = True if merge and webnotes.conn.get_value("Account",
{"master_name": new, "master_type": "Supplier"}) else False
webnotes.rename_doc("Account", account.name, new, merge=merge_account)
#update master_name in doctype account #update master_name in doctype account
webnotes.conn.sql("""update `tabAccount` set master_name = %s, webnotes.conn.sql("""update `tabAccount` set master_name = %s,
master_type = 'Supplier' where master_name = %s""" , (new,old)) master_type = 'Supplier' where master_name = %s""" , (new, old))
@webnotes.whitelist() @webnotes.whitelist()
def get_dashboard_info(supplier): def get_dashboard_info(supplier):

View File

@ -4,7 +4,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import webnotes import webnotes
from webnotes import msgprint, _ from webnotes import msgprint, _
from webnotes.utils import getdate, flt, add_days from webnotes.utils import getdate, flt, add_days, cstr
import json import json
@webnotes.whitelist() @webnotes.whitelist()
@ -94,7 +94,6 @@ def _get_price_list_rate(args, item_bean, meta):
(args.buying_price_list, args.item_code), as_dict=1) (args.buying_price_list, args.item_code), as_dict=1)
if price_list_rate: if price_list_rate:
from utilities.transaction_base import validate_currency
validate_currency(args, item_bean.doc, meta) validate_currency(args, item_bean.doc, meta)
out.import_ref_rate = flt(price_list_rate[0].ref_rate) * \ out.import_ref_rate = flt(price_list_rate[0].ref_rate) * \
@ -132,7 +131,7 @@ def _validate_item_details(args, item):
_("Please select a sub-contracted item or do not sub-contract the transaction."), _("Please select a sub-contracted item or do not sub-contract the transaction."),
raise_exception=True) raise_exception=True)
def get_last_purchase_details(item_code, doc_name, conversion_rate=1.0): def get_last_purchase_details(item_code, doc_name=None, conversion_rate=1.0):
"""returns last purchase details in stock uom""" """returns last purchase details in stock uom"""
# get last purchase order item details # get last purchase order item details
last_purchase_order = webnotes.conn.sql("""\ last_purchase_order = webnotes.conn.sql("""\
@ -143,7 +142,7 @@ def get_last_purchase_details(item_code, doc_name, conversion_rate=1.0):
where po.docstatus = 1 and po_item.item_code = %s and po.name != %s and where po.docstatus = 1 and po_item.item_code = %s and po.name != %s and
po.name = po_item.parent po.name = po_item.parent
order by po.transaction_date desc, po.name desc order by po.transaction_date desc, po.name desc
limit 1""", (item_code, doc_name), as_dict=1) limit 1""", (item_code, cstr(doc_name)), as_dict=1)
# get last purchase receipt item details # get last purchase receipt item details
last_purchase_receipt = webnotes.conn.sql("""\ last_purchase_receipt = webnotes.conn.sql("""\
@ -154,7 +153,7 @@ def get_last_purchase_details(item_code, doc_name, conversion_rate=1.0):
where pr.docstatus = 1 and pr_item.item_code = %s and pr.name != %s and where pr.docstatus = 1 and pr_item.item_code = %s and pr.name != %s and
pr.name = pr_item.parent pr.name = pr_item.parent
order by pr.posting_date desc, pr.posting_time desc, pr.name desc order by pr.posting_date desc, pr.posting_time desc, pr.name desc
limit 1""", (item_code, doc_name), as_dict=1) limit 1""", (item_code, cstr(doc_name)), as_dict=1)
purchase_order_date = getdate(last_purchase_order and last_purchase_order[0].transaction_date \ purchase_order_date = getdate(last_purchase_order and last_purchase_order[0].transaction_date \
or "1900-01-01") or "1900-01-01")

View File

@ -48,7 +48,7 @@ class StockController(AccountsController):
"against": detail.expense_account, "against": detail.expense_account,
"cost_center": detail.cost_center, "cost_center": detail.cost_center,
"remarks": self.doc.remarks or "Accounting Entry for Stock", "remarks": self.doc.remarks or "Accounting Entry for Stock",
"debit": sle.stock_value_difference "debit": flt(sle.stock_value_difference, 2)
})) }))
# to target warehouse / expense account # to target warehouse / expense account
@ -57,7 +57,7 @@ class StockController(AccountsController):
"against": warehouse_account[sle.warehouse], "against": warehouse_account[sle.warehouse],
"cost_center": detail.cost_center, "cost_center": detail.cost_center,
"remarks": self.doc.remarks or "Accounting Entry for Stock", "remarks": self.doc.remarks or "Accounting Entry for Stock",
"credit": sle.stock_value_difference "credit": flt(sle.stock_value_difference, 2)
})) }))
elif sle.warehouse not in warehouse_with_no_account: elif sle.warehouse not in warehouse_with_no_account:
warehouse_with_no_account.append(sle.warehouse) warehouse_with_no_account.append(sle.warehouse)

View File

@ -11,7 +11,6 @@ def execute():
try: try:
sr_bean = webnotes.bean("Serial No", sr[0]) sr_bean = webnotes.bean("Serial No", sr[0])
sr_bean.make_controller().via_stock_ledger = True sr_bean.make_controller().via_stock_ledger = True
sr_bean.run_method("validate")
sr_bean.save() sr_bean.save()
webnotes.conn.commit() webnotes.conn.commit()
except: except:

View File

@ -11,7 +11,7 @@ erpnext.StockAnalytics = erpnext.StockGridReport.extend({
parent: $(wrapper).find('.layout-main'), parent: $(wrapper).find('.layout-main'),
appframe: wrapper.appframe, appframe: wrapper.appframe,
doctypes: ["Item", "Item Group", "Warehouse", "Stock Ledger Entry", "Brand", doctypes: ["Item", "Item Group", "Warehouse", "Stock Ledger Entry", "Brand",
"Fiscal Year"], "Fiscal Year", "Serial No"],
tree_grid: { tree_grid: {
show: true, show: true,
parent_field: "parent_item_group", parent_field: "parent_item_group",

View File

@ -34,11 +34,14 @@ erpnext.StockGridReport = wn.views.TreeGridReport.extend({
if(add_qty) if(add_qty)
wh.fifo_stack.push([add_qty, sl.incoming_rate, sl.posting_date]); wh.fifo_stack.push([add_qty, sl.incoming_rate, sl.posting_date]);
} else { } else {
// called everytime for maintaining fifo stack
var fifo_value_diff = this.get_fifo_value_diff(wh, sl);
// outgoing // outgoing
if(sl.serial_no) { if(sl.serial_no) {
var value_diff = -1 * this.get_serialized_value_diff(sl); var value_diff = -1 * this.get_serialized_value_diff(sl);
} else if(is_fifo) { } else if(is_fifo) {
var value_diff = this.get_fifo_value_diff(wh, sl); var value_diff = fifo_value_diff;
} else { } else {
// average rate for weighted average // average rate for weighted average
var rate = (wh.balance_qty.toFixed(2) == 0.00 ? 0 : var rate = (wh.balance_qty.toFixed(2) == 0.00 ? 0 :
@ -84,11 +87,6 @@ erpnext.StockGridReport = wn.views.TreeGridReport.extend({
qty = qty - batch[0]; qty = qty - batch[0];
} }
} }
if(qty) {
// msgprint("Negative values not allowed for FIFO valuation!\
// Item " + sl.item_code.bold() + " on " + dateutil.str_to_user(sl.posting_datetime).bold() +
// " becomes negative. Values computed will not be accurate.");
}
// reset the updated stack // reset the updated stack
wh.fifo_stack = fifo_stack.reverse(); wh.fifo_stack = fifo_stack.reverse();
@ -112,9 +110,11 @@ erpnext.StockGridReport = wn.views.TreeGridReport.extend({
get_serialized_buying_rates: function() { get_serialized_buying_rates: function() {
var serialized_buying_rates = {}; var serialized_buying_rates = {};
if (wn.report_dump.data["Serial No"]) {
$.each(wn.report_dump.data["Serial No"], function(i, sn) { $.each(wn.report_dump.data["Serial No"], function(i, sn) {
serialized_buying_rates[sn.name.toLowerCase()] = flt(sn.incoming_rate); serialized_buying_rates[sn.name.toLowerCase()] = flt(sn.incoming_rate);
}); });
}
return serialized_buying_rates; return serialized_buying_rates;
}, },

View File

@ -4,7 +4,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import webnotes import webnotes
from webnotes.utils import cstr
from webnotes.model.doc import Document, make_autoname from webnotes.model.doc import Document, make_autoname
from webnotes import msgprint, _ from webnotes import msgprint, _
import webnotes.defaults import webnotes.defaults
@ -144,20 +143,21 @@ class DocType(TransactionBase):
if self.doc.lead_name: if self.doc.lead_name:
webnotes.conn.sql("update `tabLead` set status='Interested' where name=%s",self.doc.lead_name) webnotes.conn.sql("update `tabLead` set status='Interested' where name=%s",self.doc.lead_name)
def on_rename(self, new, old, merge=False): def after_rename(self, old, new, merge=False):
#update customer_name if not naming series #update customer_name if not naming series
if webnotes.defaults.get_global_default('cust_master_name') == 'Customer Name': if webnotes.defaults.get_global_default('cust_master_name') == 'Customer Name':
webnotes.conn.sql("""update `tabCustomer` set customer_name = %s where name = %s""", webnotes.conn.set(self.doc, "customer_name", new)
(new, old))
for account in webnotes.conn.sql("""select name, account_name from for account in webnotes.conn.sql("""select name, account_name from
tabAccount where master_name=%s and master_type='Customer'""", old, as_dict=1): tabAccount where master_name=%s and master_type='Customer'""", old, as_dict=1):
if account.account_name != new: if account.account_name != new:
webnotes.rename_doc("Account", account.name, new, merge=merge) merge_account = True if merge and webnotes.conn.get_value("Account",
{"master_name": new, "master_type": "Customer"}) else False
webnotes.rename_doc("Account", account.name, new, merge=merge_account)
#update master_name in doctype account #update master_name in account record
webnotes.conn.sql("""update `tabAccount` set master_name = %s, webnotes.conn.sql("""update `tabAccount` set master_name = %s,
master_type = 'Customer' where master_name = %s""", (new,old)) master_type = 'Customer' where master_name = %s""", (new, old))
@webnotes.whitelist() @webnotes.whitelist()
def get_dashboard_info(customer): def get_dashboard_info(customer):

View File

@ -76,7 +76,7 @@ def get_target_distribution_details(filters):
for d in webnotes.conn.sql("""select bd.name, bdd.month, bdd.percentage_allocation for d in webnotes.conn.sql("""select bd.name, bdd.month, bdd.percentage_allocation
from `tabBudget Distribution Detail` bdd, `tabBudget Distribution` bd from `tabBudget Distribution Detail` bdd, `tabBudget Distribution` bd
where bdd.parent=bd.name and bd.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1): where bdd.parent=bd.name and bd.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1):
target_details.setdefault(d.name, {}).setdefault(d.month, d.percentage_allocation) target_details.setdefault(d.name, {}).setdefault(d.month, flt(d.percentage_allocation))
return target_details return target_details
@ -115,8 +115,8 @@ def get_salesperson_item_month_map(filters):
})) }))
tav_dict = sim_map[sd.name][sd.item_group][month] tav_dict = sim_map[sd.name][sd.item_group][month]
month_percentage = sd.distribution_id and \ month_percentage = tdd.get(sd.distribution_id, {}).get(month, 0) \
tdd.get(sd.distribution_id, {}).get(month, 0) or 100.0/12 if sd.distribution_id else 100.0/12
for ad in achieved_details.get(sd.name, {}).get(sd.item_group, []): for ad in achieved_details.get(sd.name, {}).get(sd.item_group, []):
if (filters["target_on"] == "Quantity"): if (filters["target_on"] == "Quantity"):

View File

@ -73,7 +73,7 @@ def get_target_distribution_details(filters):
for d in webnotes.conn.sql("""select bd.name, bdd.month, bdd.percentage_allocation for d in webnotes.conn.sql("""select bd.name, bdd.month, bdd.percentage_allocation
from `tabBudget Distribution Detail` bdd, `tabBudget Distribution` bd from `tabBudget Distribution Detail` bdd, `tabBudget Distribution` bd
where bdd.parent=bd.name and bd.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1): where bdd.parent=bd.name and bd.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1):
target_details.setdefault(d.name, {}).setdefault(d.month, d.percentage_allocation) target_details.setdefault(d.name, {}).setdefault(d.month, flt(d.percentage_allocation))
return target_details return target_details
@ -113,8 +113,8 @@ def get_territory_item_month_map(filters):
})) }))
tav_dict = tim_map[td.name][td.item_group][month] tav_dict = tim_map[td.name][td.item_group][month]
month_percentage = td.distribution_id and \ month_percentage = tdd.get(td.distribution_id, {}).get(month, 0) \
tdd.get(td.distribution_id, {}).get(month, 0) or 100.0/12 if td.distribution_id else 100.0/12
for ad in achieved_details.get(td.name, {}).get(td.item_group, []): for ad in achieved_details.get(td.name, {}).get(td.item_group, []):
if (filters["target_on"] == "Quantity"): if (filters["target_on"] == "Quantity"):

View File

@ -302,18 +302,17 @@ class DocType:
where doctype='Global Defaults' and field='default_company' where doctype='Global Defaults' and field='default_company'
and value=%s""", self.doc.name) and value=%s""", self.doc.name)
def on_rename(self,newdn,olddn, merge=False): def before_rename(self, olddn, newdn, merge=False):
if merge: if merge:
msgprint(_("Sorry. Companies cannot be merged"), raise_exception=True) webnotes.throw(_("Sorry, companies cannot be merged"))
webnotes.conn.sql("""update `tabCompany` set company_name=%s def after_rename(self, olddn, newdn, merge=False):
where name=%s""", (newdn, olddn)) webnotes.conn.set(self.doc, "company_name", newdn)
webnotes.conn.sql("""update `tabSingles` set value=%s webnotes.conn.sql("""update `tabDefaultValue` set defvalue=%s
where doctype='Global Defaults' and field='default_company' where defkey='Company' and defvalue=%s""", (newdn, olddn))
and value=%s""", (newdn, olddn))
webnotes.defaults.clear_default("company", value=olddn) webnotes.defaults.clear_cache()
@webnotes.whitelist() @webnotes.whitelist()
def replace_abbr(company, old, new): def replace_abbr(company, old, new):
@ -329,3 +328,12 @@ def replace_abbr(company, old, new):
for dt in ["Account", "Cost Center", "Warehouse"]: for dt in ["Account", "Cost Center", "Warehouse"]:
_rename_record(dt) _rename_record(dt)
webnotes.conn.commit() webnotes.conn.commit()
def get_name_with_abbr(name, company):
company_abbr = webnotes.conn.get_value("Company", company, "abbr")
parts = name.split(" - ")
if parts[-1].lower() != company_abbr.lower():
parts.append(company_abbr)
return " - ".join(parts)

View File

@ -253,14 +253,44 @@ class DocType(DocListController, WebsiteGenerator):
webnotes.conn.sql("""delete from tabBin where item_code=%s""", self.doc.item_code) webnotes.conn.sql("""delete from tabBin where item_code=%s""", self.doc.item_code)
WebsiteGenerator.on_trash(self) WebsiteGenerator.on_trash(self)
def on_rename(self, newdn, olddn, merge=False): def before_rename(self, olddn, newdn, merge=False):
webnotes.conn.sql("update tabItem set item_code = %s where name = %s", (newdn, olddn)) if merge:
# Validate properties before merging
field_list = ["stock_uom", "is_stock_item", "has_serial_no", "has_batch_no"]
new_properties = [cstr(d) for d in webnotes.conn.get_value("Item", newdn, field_list)]
if new_properties != [cstr(self.doc.fields[fld]) for fld in field_list]:
webnotes.throw(_("To merge, following properties must be same for both items")
+ ": \n" + ", ".join([self.meta.get_label(fld) for fld in field_list]))
webnotes.conn.sql("delete from `tabBin` where item_code=%s", olddn)
def after_rename(self, olddn, newdn, merge):
webnotes.conn.set_value("Item", newdn, "item_code", newdn)
self.update_website_page_name()
if merge:
self.set_last_purchase_rate(newdn)
self.recalculate_bin_qty(newdn)
def update_website_page_name(self):
if self.doc.page_name: if self.doc.page_name:
self.update_website()
from webnotes.webutils import clear_cache from webnotes.webutils import clear_cache
clear_cache(self.doc.page_name) clear_cache(self.doc.page_name)
if merge: def set_last_purchase_rate(self, newdn):
from stock.stock_ledger import update_entries_after from buying.utils import get_last_purchase_details
for wh in webnotes.conn.sql("""select warehouse from `tabBin` last_purchase_rate = get_last_purchase_details(newdn).get("purchase_rate", 0)
where item_code=%s""", newdn): webnotes.conn.set_value("Item", newdn, "last_purchase_rate", last_purchase_rate)
update_entries_after({"item_code": newdn, "warehouse": wh[0]})
def recalculate_bin_qty(self, newdn):
from utilities.repost_stock import repost_stock
webnotes.conn.auto_commit_on_many_writes = 1
webnotes.conn.set_default("allow_negative_stock", 1)
for warehouse in webnotes.conn.sql("select name from `tabWarehouse`"):
repost_stock(newdn, warehouse[0])
webnotes.conn.set_default("allow_negative_stock",
webnotes.conn.get_value("Stock Settings", None, "allow_negative_stock"))
webnotes.conn.auto_commit_on_many_writes = 0

View File

@ -20,7 +20,7 @@ erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend
cur_frm.add_custom_button(wn._('Make Purchase Invoice'), cur_frm.add_custom_button(wn._('Make Purchase Invoice'),
this.make_purchase_invoice); this.make_purchase_invoice);
} }
cur_frm.add_custom_button(wn._('Send SMS'), cur_frm.cscript['Send SMS'], "icon-mobile-phone"); cur_frm.add_custom_button('Send SMS', cur_frm.cscript.send_sms);
this.show_stock_ledger(); this.show_stock_ledger();
this.show_general_ledger(); this.show_general_ledger();

View File

@ -6,7 +6,7 @@ import webnotes
from webnotes.utils import cint, getdate, cstr, flt, add_days from webnotes.utils import cint, getdate, cstr, flt, add_days
import datetime import datetime
from webnotes import msgprint, _, ValidationError from webnotes import _, ValidationError
from controllers.stock_controller import StockController from controllers.stock_controller import StockController
@ -157,11 +157,12 @@ class DocType(StockController):
webnotes.throw(_("Cannot delete Serial No in warehouse. \ webnotes.throw(_("Cannot delete Serial No in warehouse. \
First remove from warehouse, then delete.") + ": " + self.doc.name) First remove from warehouse, then delete.") + ": " + self.doc.name)
def on_rename(self, new, old, merge=False): def before_rename(self, old, new, merge=False):
"""rename serial_no text fields"""
if merge: if merge:
msgprint(_("Sorry. Serial Nos. cannot be merged"), raise_exception=True) webnotes.throw(_("Sorry, Serial Nos cannot be merged"))
def after_rename(self, old, new, merge=False):
"""rename serial_no text fields"""
for dt in webnotes.conn.sql("""select parent from tabDocField for dt in webnotes.conn.sql("""select parent from tabDocField
where fieldname='serial_no' and fieldtype='Text'"""): where fieldname='serial_no' and fieldtype='Text'"""):

View File

@ -5,18 +5,6 @@ cur_frm.cscript.refresh = function(doc) {
cur_frm.toggle_display('warehouse_name', doc.__islocal); cur_frm.toggle_display('warehouse_name', doc.__islocal);
} }
cur_frm.cscript.merge = function(doc, cdt, cdn) {
if (!doc.merge_with) {
msgprint(wn._("Please enter the warehouse to which you want to merge?"));
return;
}
var check = confirm(wn._("Are you sure you want to merge this warehouse into "
+ doc.merge_with + "?"));
if (check) {
return $c_obj(make_doclist(cdt, cdn), 'merge_warehouses', '', '');
}
}
cur_frm.set_query("create_account_under", function() { cur_frm.set_query("create_account_under", function() {
return { return {
filters: { filters: {

View File

@ -56,47 +56,6 @@ class DocType:
webnotes.throw(_("Please enter account group under which account \ webnotes.throw(_("Please enter account group under which account \
for warehouse ") + self.doc.name +_(" will be created")) for warehouse ") + self.doc.name +_(" will be created"))
def on_rename(self, new, old, merge=False):
webnotes.conn.set_value("Account", {"account_type": "Warehouse", "master_name": old},
"master_name", new)
if merge:
from stock.stock_ledger import update_entries_after
for item_code in webnotes.conn.sql("""select item_code from `tabBin`
where warehouse=%s""", new):
update_entries_after({"item_code": item_code, "warehouse": new})
def merge_warehouses(self):
webnotes.conn.auto_commit_on_many_writes = 1
# get items which dealt with current warehouse
items = webnotes.conn.sql("select item_code from tabBin where warehouse=%s" , self.doc.name)
# delete old bins
webnotes.conn.sql("delete from tabBin where warehouse=%s", self.doc.name)
# replace link fields
from webnotes.model import rename_doc
link_fields = rename_doc.get_link_fields('Warehouse')
rename_doc.update_link_field_values(link_fields, self.doc.name, self.doc.merge_with)
account_link_fields = rename_doc.get_link_fields('Account')
old_warehouse_account = webnotes.conn.get_value("Account", {"master_name": self.doc.name})
new_warehouse_account = webnotes.conn.get_value("Account",
{"master_name": self.doc.merge_with})
rename_doc.update_link_field_values(account_link_fields, old_warehouse_account,
new_warehouse_account)
webnotes.conn.delete_doc("Account", old_warehouse_account)
from utilities.repost_stock import repost
for item_code in items:
repost(item_code[0], self.doc.merge_with)
webnotes.conn.auto_commit_on_many_writes = 0
msgprint("Warehouse %s merged into %s. Now you can delete warehouse: %s"
% (self.doc.name, self.doc.merge_with, self.doc.name))
def on_trash(self): def on_trash(self):
# delete bin # delete bin
bins = webnotes.conn.sql("select * from `tabBin` where warehouse = %s", bins = webnotes.conn.sql("select * from `tabBin` where warehouse = %s",
@ -110,15 +69,61 @@ class DocType:
webnotes.conn.sql("delete from `tabBin` where name = %s", d['name']) webnotes.conn.sql("delete from `tabBin` where name = %s", d['name'])
warehouse_account = webnotes.conn.get_value("Account", warehouse_account = webnotes.conn.get_value("Account",
{"account_type": "Warehosue", "master_name": self.doc.name}) {"account_type": "Warehouse", "master_name": self.doc.name})
if warehouse_account: if warehouse_account:
webnotes.delete_doc("Account", warehouse_account) webnotes.delete_doc("Account", warehouse_account)
# delete cancelled sle if 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""", msgprint("""Warehouse can not be deleted as stock ledger entry
self.doc.name):
msgprint("""Warehosue can not be deleted as stock ledger entry
exists for this warehouse.""", raise_exception=1) exists for this warehouse.""", raise_exception=1)
def before_rename(self, olddn, newdn, merge=False):
# Add company abbr if not provided
from setup.doctype.company.company import get_name_with_abbr
new_warehouse = get_name_with_abbr(newdn, self.doc.company)
if merge:
if self.doc.company != webnotes.conn.get_value("Warehouse", new_warehouse, "company"):
webnotes.throw(_("Both Warehouse must belong to same Company"))
webnotes.conn.sql("delete from `tabBin` where warehouse=%s", olddn)
self.rename_account(olddn, new_warehouse, merge)
return new_warehouse
def after_rename(self, olddn, newdn, merge=False):
if merge:
self.recalculate_bin_qty(newdn)
def recalculate_bin_qty(self, newdn):
from utilities.repost_stock import repost_stock
webnotes.conn.auto_commit_on_many_writes = 1
webnotes.conn.set_default("allow_negative_stock", 1)
for item in webnotes.conn.sql("""select distinct item_code from (
select name as item_code from `tabItem` where ifnull(is_stock_item, 'Yes')='Yes'
union
select distinct item_code from tabBin) a"""):
repost_stock(item[0], newdn)
webnotes.conn.set_default("allow_negative_stock",
webnotes.conn.get_value("Stock Settings", None, "allow_negative_stock"))
webnotes.conn.auto_commit_on_many_writes = 0
def rename_account(self, olddn, newdn, merge):
old_account = webnotes.conn.get_value("Account",
{"account_type": "Warehouse", "master_name": olddn})
if old_account:
new_account = None
if not merge:
if old_account == olddn:
new_account = webnotes.rename_doc("Account", olddn, newdn)
else: else:
webnotes.conn.sql("delete from `tabStock Ledger Entry` where warehouse = %s", existing_new_account = webnotes.conn.get_value("Account",
self.doc.name) {"account_type": "Warehouse", "master_name": newdn})
new_account = webnotes.rename_doc("Account", old_account,
existing_new_account or newdn, merge=True if existing_new_account else False)
if new_account:
webnotes.conn.set_value("Account", new_account, "master_name", newdn)

View File

@ -2,7 +2,7 @@
{ {
"creation": "2013-03-07 18:50:32", "creation": "2013-03-07 18:50:32",
"docstatus": 0, "docstatus": 0,
"modified": "2013-10-28 16:42:07", "modified": "2013-11-19 12:12:33",
"modified_by": "Administrator", "modified_by": "Administrator",
"owner": "Administrator" "owner": "Administrator"
}, },
@ -20,7 +20,8 @@
"name": "__common__", "name": "__common__",
"parent": "Warehouse", "parent": "Warehouse",
"parentfield": "fields", "parentfield": "fields",
"parenttype": "DocType" "parenttype": "DocType",
"permlevel": 0
}, },
{ {
"doctype": "DocPerm", "doctype": "DocPerm",
@ -42,7 +43,6 @@
"fieldtype": "Section Break", "fieldtype": "Section Break",
"label": "Warehouse Detail", "label": "Warehouse Detail",
"oldfieldtype": "Section Break", "oldfieldtype": "Section Break",
"permlevel": 0,
"read_only": 0 "read_only": 0
}, },
{ {
@ -52,7 +52,6 @@
"label": "Warehouse Name", "label": "Warehouse Name",
"oldfieldname": "warehouse_name", "oldfieldname": "warehouse_name",
"oldfieldtype": "Data", "oldfieldtype": "Data",
"permlevel": 0,
"read_only": 0, "read_only": 0,
"reqd": 1 "reqd": 1
}, },
@ -65,7 +64,6 @@
"oldfieldname": "company", "oldfieldname": "company",
"oldfieldtype": "Link", "oldfieldtype": "Link",
"options": "Company", "options": "Company",
"permlevel": 0,
"read_only": 0, "read_only": 0,
"reqd": 1, "reqd": 1,
"search_index": 1 "search_index": 1
@ -95,7 +93,6 @@
"fieldtype": "Table", "fieldtype": "Table",
"label": "Warehouse Users", "label": "Warehouse Users",
"options": "Warehouse User", "options": "Warehouse User",
"permlevel": 0,
"read_only": 0 "read_only": 0
}, },
{ {
@ -104,7 +101,6 @@
"fieldname": "warehouse_contact_info", "fieldname": "warehouse_contact_info",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"label": "Warehouse Contact Info", "label": "Warehouse Contact Info",
"permlevel": 0,
"read_only": 0 "read_only": 0
}, },
{ {
@ -115,7 +111,6 @@
"label": "Email Id", "label": "Email Id",
"oldfieldname": "email_id", "oldfieldname": "email_id",
"oldfieldtype": "Data", "oldfieldtype": "Data",
"permlevel": 0,
"print_hide": 0, "print_hide": 0,
"read_only": 0 "read_only": 0
}, },
@ -127,7 +122,6 @@
"oldfieldname": "phone_no", "oldfieldname": "phone_no",
"oldfieldtype": "Int", "oldfieldtype": "Int",
"options": "Phone", "options": "Phone",
"permlevel": 0,
"read_only": 0 "read_only": 0
}, },
{ {
@ -138,7 +132,6 @@
"oldfieldname": "mobile_no", "oldfieldname": "mobile_no",
"oldfieldtype": "Int", "oldfieldtype": "Int",
"options": "Phone", "options": "Phone",
"permlevel": 0,
"read_only": 0 "read_only": 0
}, },
{ {
@ -146,7 +139,6 @@
"fieldname": "column_break0", "fieldname": "column_break0",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"oldfieldtype": "Column Break", "oldfieldtype": "Column Break",
"permlevel": 0,
"read_only": 0 "read_only": 0
}, },
{ {
@ -156,7 +148,6 @@
"label": "Address Line 1", "label": "Address Line 1",
"oldfieldname": "address_line_1", "oldfieldname": "address_line_1",
"oldfieldtype": "Data", "oldfieldtype": "Data",
"permlevel": 0,
"read_only": 0 "read_only": 0
}, },
{ {
@ -166,7 +157,6 @@
"label": "Address Line 2", "label": "Address Line 2",
"oldfieldname": "address_line_2", "oldfieldname": "address_line_2",
"oldfieldtype": "Data", "oldfieldtype": "Data",
"permlevel": 0,
"read_only": 0 "read_only": 0
}, },
{ {
@ -177,7 +167,6 @@
"label": "City", "label": "City",
"oldfieldname": "city", "oldfieldname": "city",
"oldfieldtype": "Data", "oldfieldtype": "Data",
"permlevel": 0,
"read_only": 0, "read_only": 0,
"reqd": 0 "reqd": 0
}, },
@ -189,7 +178,6 @@
"oldfieldname": "state", "oldfieldname": "state",
"oldfieldtype": "Select", "oldfieldtype": "Select",
"options": "Suggest", "options": "Suggest",
"permlevel": 0,
"read_only": 0 "read_only": 0
}, },
{ {
@ -199,33 +187,6 @@
"label": "PIN", "label": "PIN",
"oldfieldname": "pin", "oldfieldname": "pin",
"oldfieldtype": "Int", "oldfieldtype": "Int",
"permlevel": 0,
"read_only": 0
},
{
"description": "This feature is for merging duplicate warehouses. It will replace all the links of this warehouse by \"Merge Into\" warehouse. After merging you can delete this warehouse, as stock level for this warehouse will be zero.",
"doctype": "DocField",
"fieldname": "merge_warehouses_section",
"fieldtype": "Section Break",
"label": "Merge Warehouses",
"permlevel": 2,
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "merge_with",
"fieldtype": "Link",
"label": "Merge Into",
"options": "Warehouse",
"permlevel": 2,
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "merge",
"fieldtype": "Button",
"label": "Merge",
"permlevel": 2,
"read_only": 0 "read_only": 0
}, },
{ {

View File

@ -25,7 +25,7 @@ erpnext.StockAgeing = erpnext.StockGridReport.extend({
page: wrapper, page: wrapper,
parent: $(wrapper).find('.layout-main'), parent: $(wrapper).find('.layout-main'),
appframe: wrapper.appframe, appframe: wrapper.appframe,
doctypes: ["Item", "Warehouse", "Stock Ledger Entry", "Item Group", "Brand"], doctypes: ["Item", "Warehouse", "Stock Ledger Entry", "Item Group", "Brand", "Serial No"],
}) })
}, },
setup_columns: function() { setup_columns: function() {
@ -175,7 +175,7 @@ erpnext.StockAgeing = erpnext.StockGridReport.extend({
grid: { hoverable: true, clickable: true }, grid: { hoverable: true, clickable: true },
xaxis: { xaxis: {
ticks: $.map(me.data, function(item, idx) { return [[idx+1, item.name]] }), ticks: $.map(me.data, function(item, idx) { return [[idx+1, item.name]] }),
max: 20 max: 15
}, },
series: { downsample: { threshold: 1000 } } series: { downsample: { threshold: 1000 } }
} }

View File

@ -21,7 +21,7 @@ erpnext.StockLedger = erpnext.StockGridReport.extend({
page: wrapper, page: wrapper,
parent: $(wrapper).find('.layout-main'), parent: $(wrapper).find('.layout-main'),
appframe: wrapper.appframe, appframe: wrapper.appframe,
doctypes: ["Item", "Item Group", "Warehouse", "Stock Ledger Entry", "Brand"], doctypes: ["Item", "Item Group", "Warehouse", "Stock Ledger Entry", "Brand", "Serial No"],
}) })
}, },

View File

@ -27,7 +27,7 @@ erpnext.StockLevel = erpnext.StockGridReport.extend({
parent: $(wrapper).find('.layout-main'), parent: $(wrapper).find('.layout-main'),
appframe: wrapper.appframe, appframe: wrapper.appframe,
doctypes: ["Item", "Warehouse", "Stock Ledger Entry", "Production Order", doctypes: ["Item", "Warehouse", "Stock Ledger Entry", "Production Order",
"Material Request Item", "Purchase Order Item", "Sales Order Item", "Brand"], "Material Request Item", "Purchase Order Item", "Sales Order Item", "Brand", "Serial No"],
}); });
this.wrapper.bind("make", function() { this.wrapper.bind("make", function() {

View File

@ -7,18 +7,24 @@ import webnotes
from webnotes.utils import flt from webnotes.utils import flt
def repost(): def repost(allow_negative_stock=False):
""" """
Repost everything! Repost everything!
""" """
webnotes.conn.auto_commit_on_many_writes = 1 webnotes.conn.auto_commit_on_many_writes = 1
if allow_negative_stock:
webnotes.conn.set_default("allow_negative_stock", 1)
for d in webnotes.conn.sql("""select distinct item_code, warehouse from for d in webnotes.conn.sql("""select distinct item_code, warehouse from
(select item_code, warehouse from tabBin (select item_code, warehouse from tabBin
union union
select item_code, warehouse from `tabStock Ledger Entry`) a"""): select item_code, warehouse from `tabStock Ledger Entry`) a"""):
repost_stock(d[0], d[1]) repost_stock(d[0], d[1], allow_negative_stock)
if allow_negative_stock:
webnotes.conn.set_default("allow_negative_stock",
webnotes.conn.get_value("Stock Settings", None, "allow_negative_stock"))
webnotes.conn.auto_commit_on_many_writes = 0 webnotes.conn.auto_commit_on_many_writes = 0
def repost_stock(item_code, warehouse): def repost_stock(item_code, warehouse):