mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-26 08:24:47 +00:00
Merge remote-tracking branch 'upstream/wsgi' into HEAD
Conflicts: public/js/complete_setup.js setup/doctype/setup_control/setup_control.py
This commit is contained in:
@@ -5,7 +5,6 @@ from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes.utils import add_days, cint,flt, nowdate, get_url_to_form, formatdate
|
||||
from webnotes import msgprint, _
|
||||
sql = webnotes.conn.sql
|
||||
|
||||
import webnotes.defaults
|
||||
|
||||
@@ -61,7 +60,7 @@ class DocType:
|
||||
self.doc.save()
|
||||
|
||||
def get_first_sle(self):
|
||||
sle = sql("""
|
||||
sle = webnotes.conn.sql("""
|
||||
select * from `tabStock Ledger Entry`
|
||||
where item_code = %s
|
||||
and warehouse = %s
|
||||
|
||||
@@ -9,7 +9,7 @@ cur_frm.cscript.sales_team_fname = "sales_team";
|
||||
|
||||
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");
|
||||
@@ -22,24 +22,24 @@ erpnext.stock.DeliveryNoteController = erpnext.selling.SellingController.extend(
|
||||
var from_sales_invoice = false;
|
||||
from_sales_invoice = cur_frm.get_doclist({parentfield: "delivery_note_details"})
|
||||
.some(function(item) {
|
||||
return item.prevdoc_doctype==="Sales Invoice" ? true : false;
|
||||
return item.against_sales_invoice ? true : false;
|
||||
});
|
||||
|
||||
if(!from_sales_invoice)
|
||||
cur_frm.add_custom_button('Make Invoice', this.make_sales_invoice);
|
||||
cur_frm.add_custom_button(wn._('Make Invoice'), this.make_sales_invoice);
|
||||
}
|
||||
|
||||
if(flt(doc.per_installed, 2) < 100 && doc.docstatus==1)
|
||||
cur_frm.add_custom_button('Make Installation Note', this.make_installation_note);
|
||||
cur_frm.add_custom_button(wn._('Make Installation Note'), this.make_installation_note);
|
||||
|
||||
if (doc.docstatus==1) {
|
||||
cur_frm.add_custom_button('Send SMS', cur_frm.cscript.send_sms);
|
||||
cur_frm.add_custom_button(wn._('Send SMS'), cur_frm.cscript.send_sms);
|
||||
this.show_stock_ledger();
|
||||
this.show_general_ledger();
|
||||
}
|
||||
|
||||
if(doc.docstatus==0 && !doc.__islocal) {
|
||||
cur_frm.add_custom_button('Make Packing Slip', cur_frm.cscript['Make Packing Slip']);
|
||||
cur_frm.add_custom_button(wn._('Make Packing Slip'), cur_frm.cscript['Make Packing Slip']);
|
||||
}
|
||||
|
||||
set_print_hide(doc, dt, dn);
|
||||
@@ -113,13 +113,6 @@ cur_frm.fields_dict['project_name'].get_query = function(doc, cdt, cdn) {
|
||||
}
|
||||
}
|
||||
|
||||
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" }
|
||||
@@ -181,12 +174,12 @@ cur_frm.pformat.sales_order_no= function(doc, cdt, cdn){
|
||||
if(cl.length){
|
||||
prevdoc_list = new Array();
|
||||
for(var i=0;i<cl.length;i++){
|
||||
if(cl[i].prevdoc_doctype == 'Sales Order' && cl[i].prevdoc_docname && prevdoc_list.indexOf(cl[i].prevdoc_docname) == -1) {
|
||||
prevdoc_list.push(cl[i].prevdoc_docname);
|
||||
if(cl[i].against_sales_order && prevdoc_list.indexOf(cl[i].against_sales_order) == -1) {
|
||||
prevdoc_list.push(cl[i].against_sales_order);
|
||||
if(prevdoc_list.length ==1)
|
||||
out += make_row(cl[i].prevdoc_doctype, cl[i].prevdoc_docname, cl[i].prevdoc_date,0);
|
||||
out += make_row("Sales Order", cl[i].against_sales_order, null, 0);
|
||||
else
|
||||
out += make_row('', cl[i].prevdoc_docname, cl[i].prevdoc_date,0);
|
||||
out += make_row('', cl[i].against_sales_order, null,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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, _
|
||||
@@ -28,7 +28,7 @@ class DocType(SellingController):
|
||||
'target_parent_field': 'per_delivered',
|
||||
'target_ref_field': 'qty',
|
||||
'source_field': 'qty',
|
||||
'percent_join_field': 'prevdoc_docname',
|
||||
'percent_join_field': 'against_sales_order',
|
||||
'status_field': 'delivery_status',
|
||||
'keyword': 'Delivered'
|
||||
}]
|
||||
@@ -42,14 +42,6 @@ class DocType(SellingController):
|
||||
|
||||
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,23 +49,11 @@ class DocType(SellingController):
|
||||
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 get_rate(self,arg):
|
||||
return get_obj('Sales Common').get_rate(arg)
|
||||
|
||||
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':
|
||||
for d in getlist(self.doclist,'delivery_note_details'):
|
||||
if not d.prevdoc_docname:
|
||||
if not d.against_sales_order:
|
||||
msgprint("Sales Order No. required against item %s"%d.item_code)
|
||||
raise Exception
|
||||
|
||||
@@ -86,46 +66,38 @@ class DocType(SellingController):
|
||||
|
||||
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)
|
||||
sales_com_obj.get_prevdoc_date(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')
|
||||
|
||||
|
||||
# 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'
|
||||
if not self.doc.installation_status: self.doc.installation_status = 'Not Installed'
|
||||
|
||||
def validate_with_previous_doc(self):
|
||||
prev_doctype = [d.prevdoc_doctype for d in self.doclist.get({
|
||||
"parentfield": "delivery_note_details"}) if cstr(d.prevdoc_doctype) != ""]
|
||||
|
||||
if prev_doctype:
|
||||
super(DocType, self).validate_with_previous_doc(self.tname, {
|
||||
prev_doctype[0]: {
|
||||
"ref_dn_field": "prevdoc_docname",
|
||||
"compare_fields": [["customer", "="], ["company", "="], ["project_name", "="],
|
||||
["currency", "="]],
|
||||
},
|
||||
})
|
||||
if cint(webnotes.defaults.get_global_default('maintain_same_sales_rate')):
|
||||
items = self.doclist.get({"parentfield": "delivery_note_details"})
|
||||
|
||||
for fn in (("Sales Order", "against_sales_order"), ("Sales Invoice", "against_sales_invoice")):
|
||||
if items.get_distinct_values(fn[1]):
|
||||
super(DocType, self).validate_with_previous_doc(self.tname, {
|
||||
prev_doctype[0] + " Item": {
|
||||
"ref_dn_field": "prevdoc_detail_docname",
|
||||
"compare_fields": [["export_rate", "="]],
|
||||
"is_child_table": True
|
||||
}
|
||||
fn[0]: {
|
||||
"ref_dn_field": fn[1],
|
||||
"compare_fields": [["customer", "="], ["company", "="], ["project_name", "="],
|
||||
["currency", "="]],
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
if cint(webnotes.defaults.get_global_default('maintain_same_sales_rate')):
|
||||
super(DocType, self).validate_with_previous_doc(self.tname, {
|
||||
fn[0] + " Item": {
|
||||
"ref_dn_field": "prevdoc_detail_docname",
|
||||
"compare_fields": [["export_rate", "="]],
|
||||
"is_child_table": True
|
||||
}
|
||||
})
|
||||
|
||||
def validate_proj_cust(self):
|
||||
"""check for does customer belong to same project as entered.."""
|
||||
if self.doc.project_name and self.doc.customer:
|
||||
@@ -137,8 +109,8 @@ class DocType(SellingController):
|
||||
def validate_for_items(self):
|
||||
check_list, chk_dupl_itm = [], []
|
||||
for d in getlist(self.doclist,'delivery_note_details'):
|
||||
e = [d.item_code, d.description, d.warehouse, d.prevdoc_docname or '', d.batch_no or '']
|
||||
f = [d.item_code, d.description, d.prevdoc_docname or '']
|
||||
e = [d.item_code, d.description, d.warehouse, d.against_sales_order or d.against_sales_invoice, d.batch_no or '']
|
||||
f = [d.item_code, d.description, d.against_sales_order or d.against_sales_invoice]
|
||||
|
||||
if webnotes.conn.get_value("Item", d.item_code, "is_stock_item") == 'Yes':
|
||||
if e in check_list:
|
||||
@@ -172,7 +144,8 @@ class DocType(SellingController):
|
||||
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()
|
||||
@@ -195,8 +168,7 @@ class DocType(SellingController):
|
||||
|
||||
|
||||
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()
|
||||
@@ -285,18 +257,15 @@ class DocType(SellingController):
|
||||
}
|
||||
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
|
||||
for d in getlist(self.doclist, 'delivery_note_details'):
|
||||
if not d.prevdoc_docname:
|
||||
if not (d.against_sales_order or d.against_sales_invoice):
|
||||
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}"""
|
||||
@@ -344,7 +313,7 @@ def make_sales_invoice(source_name, target_doclist=None):
|
||||
"name": "dn_detail",
|
||||
"parent": "delivery_note",
|
||||
"prevdoc_detail_docname": "so_detail",
|
||||
"prevdoc_docname": "sales_order",
|
||||
"against_sales_order": "sales_order",
|
||||
"serial_no": "serial_no"
|
||||
},
|
||||
"postprocess": update_item
|
||||
@@ -368,7 +337,6 @@ def make_sales_invoice(source_name, target_doclist=None):
|
||||
def make_installation_note(source_name, target_doclist=None):
|
||||
def update_item(obj, target, source_parent):
|
||||
target.qty = flt(obj.qty) - flt(obj.installed_qty)
|
||||
target.prevdoc_date = source_parent.posting_date
|
||||
target.serial_no = obj.serial_no
|
||||
|
||||
doclist = get_mapped_doclist("Delivery Note", source_name, {
|
||||
|
||||
@@ -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
|
||||
},
|
||||
|
||||
@@ -9,20 +9,22 @@ import webnotes.defaults
|
||||
from webnotes.utils import cint
|
||||
from stock.doctype.purchase_receipt.test_purchase_receipt import get_gl_entries, set_perpetual_inventory, test_records as pr_test_records
|
||||
|
||||
def _insert_purchase_receipt(item_code=None):
|
||||
if not item_code:
|
||||
item_code = pr_test_records[0][1]["item_code"]
|
||||
|
||||
pr = webnotes.bean(copy=pr_test_records[0])
|
||||
pr.doclist[1].item_code = item_code
|
||||
pr.insert()
|
||||
pr.submit()
|
||||
|
||||
class TestDeliveryNote(unittest.TestCase):
|
||||
def _insert_purchase_receipt(self, item_code=None):
|
||||
pr = webnotes.bean(copy=pr_test_records[0])
|
||||
if item_code:
|
||||
pr.doclist[1].item_code = item_code
|
||||
pr.insert()
|
||||
pr.submit()
|
||||
|
||||
def test_over_billing_against_dn(self):
|
||||
self.clear_stock_account_balance()
|
||||
self._insert_purchase_receipt()
|
||||
_insert_purchase_receipt()
|
||||
|
||||
from stock.doctype.delivery_note.delivery_note import make_sales_invoice
|
||||
self._insert_purchase_receipt()
|
||||
_insert_purchase_receipt()
|
||||
dn = webnotes.bean(copy=test_records[0]).insert()
|
||||
|
||||
self.assertRaises(webnotes.ValidationError, make_sales_invoice,
|
||||
@@ -44,7 +46,7 @@ class TestDeliveryNote(unittest.TestCase):
|
||||
set_perpetual_inventory(0)
|
||||
self.assertEqual(cint(webnotes.defaults.get_global_default("auto_accounting_for_stock")), 0)
|
||||
|
||||
self._insert_purchase_receipt()
|
||||
_insert_purchase_receipt()
|
||||
|
||||
dn = webnotes.bean(copy=test_records[0])
|
||||
dn.insert()
|
||||
@@ -69,7 +71,7 @@ class TestDeliveryNote(unittest.TestCase):
|
||||
self.assertEqual(cint(webnotes.defaults.get_global_default("auto_accounting_for_stock")), 1)
|
||||
webnotes.conn.set_value("Item", "_Test Item", "valuation_method", "FIFO")
|
||||
|
||||
self._insert_purchase_receipt()
|
||||
_insert_purchase_receipt()
|
||||
|
||||
dn = webnotes.bean(copy=test_records[0])
|
||||
dn.doclist[1].expense_account = "Cost of Goods Sold - _TC"
|
||||
@@ -123,8 +125,8 @@ class TestDeliveryNote(unittest.TestCase):
|
||||
self.clear_stock_account_balance()
|
||||
set_perpetual_inventory()
|
||||
|
||||
self._insert_purchase_receipt()
|
||||
self._insert_purchase_receipt("_Test Item Home Desktop 100")
|
||||
_insert_purchase_receipt()
|
||||
_insert_purchase_receipt("_Test Item Home Desktop 100")
|
||||
|
||||
dn = webnotes.bean(copy=test_records[0])
|
||||
dn.doclist[1].item_code = "_Test Sales BOM Item"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-04-22 13:15:44",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-08-29 16:58:16",
|
||||
"modified": "2013-10-10 17:03:11",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@@ -350,48 +350,17 @@
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "prevdoc_doctype",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 1,
|
||||
"in_filter": 1,
|
||||
"label": "Document Type",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "prevdoc_doctype",
|
||||
"oldfieldtype": "Data",
|
||||
"print_hide": 1,
|
||||
"print_width": "150px",
|
||||
"read_only": 1,
|
||||
"search_index": 1,
|
||||
"width": "150px"
|
||||
"fieldname": "against_sales_order",
|
||||
"fieldtype": "Link",
|
||||
"label": "Against Sales Order",
|
||||
"options": "Sales Order"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "prevdoc_docname",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"in_filter": 1,
|
||||
"label": "Against Document No",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "prevdoc_docname",
|
||||
"oldfieldtype": "Data",
|
||||
"print_hide": 1,
|
||||
"print_width": "150px",
|
||||
"read_only": 1,
|
||||
"search_index": 1,
|
||||
"width": "150px"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "prevdoc_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 1,
|
||||
"in_filter": 1,
|
||||
"label": "Against Document Date",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "prevdoc_date",
|
||||
"oldfieldtype": "Date",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
"fieldname": "against_sales_invoice",
|
||||
"fieldtype": "Link",
|
||||
"label": "Against Sales Invoice",
|
||||
"options": "Sales Invoice"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
@@ -420,6 +389,17 @@
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "buying_amount",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 1,
|
||||
"label": "Buying Amount",
|
||||
"no_copy": 1,
|
||||
"options": "Company:company:default_currency",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"doctype": "DocField",
|
||||
|
||||
@@ -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.
|
||||
@@ -1 +0,0 @@
|
||||
from __future__ import unicode_literals
|
||||
@@ -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
|
||||
@@ -6,20 +6,18 @@ cur_frm.cscript.refresh = function(doc) {
|
||||
// read only if any stock ledger entry exists
|
||||
|
||||
cur_frm.cscript.make_dashboard()
|
||||
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();
|
||||
|
||||
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)
|
||||
|
||||
|
||||
if ((!doc.__islocal) && (doc.is_stock_item == 'Yes')) {
|
||||
var callback = function(r, rt) {
|
||||
var enabled = (r.message == 'exists') ? false : true;
|
||||
cur_frm.toggle_enable(['has_serial_no', 'is_stock_item', 'valuation_method'], enabled);
|
||||
}
|
||||
return $c_obj(make_doclist(doc.doctype, doc.name),'check_if_sle_exists','',callback);
|
||||
if (!doc.__islocal && doc.is_stock_item == 'Yes') {
|
||||
cur_frm.toggle_enable(['has_serial_no', 'is_stock_item', 'valuation_method'],
|
||||
doc.__sle_exists=="exists" ? false : true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +124,7 @@ cur_frm.fields_dict['item_group'].get_query = function(doc,cdt,cdn) {
|
||||
// in the "alternate_description" field
|
||||
cur_frm.cscript.add_image = function(doc, dt, dn) {
|
||||
if(!doc.image) {
|
||||
msgprint('Please select an "Image" first');
|
||||
msgprint(wn._('Please select an "Image" first'));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -142,7 +140,7 @@ cur_frm.cscript.weight_to_validate = function(doc,cdt,cdn){
|
||||
|
||||
if((doc.nett_weight || doc.gross_weight) && !doc.weight_uom)
|
||||
{
|
||||
alert('Weight is mentioned,\nPlease mention "Weight UOM" too');
|
||||
alert(wn._('Weight is mentioned,\nPlease mention "Weight UOM" too'));
|
||||
validated=0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,9 @@ from webnotes.model.controller import DocListController
|
||||
class WarehouseNotSet(Exception): pass
|
||||
|
||||
class DocType(DocListController):
|
||||
def onload(self):
|
||||
self.doc.fields["__sle_exists"] = self.check_if_sle_exists()
|
||||
|
||||
def autoname(self):
|
||||
if webnotes.conn.get_default("item_naming_by")=="Naming Series":
|
||||
from webnotes.model.doc import make_autoname
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ window.get_product_list = function() {
|
||||
|
||||
$.ajax({
|
||||
method: "GET",
|
||||
url: "server.py",
|
||||
url: "/",
|
||||
dataType: "json",
|
||||
data: {
|
||||
cmd: "selling.utils.product.get_product_list",
|
||||
|
||||
@@ -31,7 +31,7 @@ test_records = [
|
||||
"is_sales_item": "Yes",
|
||||
"is_service_item": "No",
|
||||
"inspection_required": "No",
|
||||
"is_pro_applicable": "No",
|
||||
"is_pro_applicable": "Yes",
|
||||
"is_sub_contracted_item": "No",
|
||||
"stock_uom": "_Test UOM",
|
||||
"default_income_account": "Sales - _TC",
|
||||
@@ -45,6 +45,26 @@ test_records = [
|
||||
"material_request_type": "Purchase"
|
||||
},
|
||||
],
|
||||
[{
|
||||
"doctype": "Item",
|
||||
"item_code": "_Test Item 2",
|
||||
"item_name": "_Test Item 2",
|
||||
"description": "_Test Item 2",
|
||||
"item_group": "_Test Item Group",
|
||||
"is_stock_item": "Yes",
|
||||
"is_asset_item": "No",
|
||||
"has_batch_no": "No",
|
||||
"has_serial_no": "No",
|
||||
"is_purchase_item": "Yes",
|
||||
"is_sales_item": "Yes",
|
||||
"is_service_item": "No",
|
||||
"inspection_required": "No",
|
||||
"is_pro_applicable": "Yes",
|
||||
"is_sub_contracted_item": "No",
|
||||
"stock_uom": "_Test UOM",
|
||||
"default_income_account": "Sales - _TC",
|
||||
"default_warehouse": "_Test Warehouse - _TC",
|
||||
}],
|
||||
[{
|
||||
"doctype": "Item",
|
||||
"item_code": "_Test Item Home Desktop 100",
|
||||
@@ -63,6 +83,7 @@ test_records = [
|
||||
"inspection_required": "No",
|
||||
"is_pro_applicable": "No",
|
||||
"is_sub_contracted_item": "No",
|
||||
"is_manufactured_item": "No",
|
||||
"stock_uom": "_Test UOM"
|
||||
},
|
||||
{
|
||||
@@ -88,6 +109,7 @@ test_records = [
|
||||
"inspection_required": "No",
|
||||
"is_pro_applicable": "No",
|
||||
"is_sub_contracted_item": "No",
|
||||
"is_manufactured_item": "No",
|
||||
"stock_uom": "_Test UOM"
|
||||
}],
|
||||
[{
|
||||
@@ -182,8 +204,49 @@ test_records = [
|
||||
"is_sales_item": "Yes",
|
||||
"is_service_item": "No",
|
||||
"inspection_required": "No",
|
||||
"is_pro_applicable": "No",
|
||||
"is_pro_applicable": "Yes",
|
||||
"is_sub_contracted_item": "No",
|
||||
"stock_uom": "_Test UOM"
|
||||
}],
|
||||
[{
|
||||
"doctype": "Item",
|
||||
"item_code": "_Test Item Home Desktop Manufactured",
|
||||
"item_name": "_Test Item Home Desktop Manufactured",
|
||||
"description": "_Test Item Home Desktop Manufactured",
|
||||
"item_group": "_Test Item Group Desktops",
|
||||
"default_warehouse": "_Test Warehouse - _TC",
|
||||
"default_income_account": "Sales - _TC",
|
||||
"is_stock_item": "Yes",
|
||||
"is_asset_item": "No",
|
||||
"has_batch_no": "No",
|
||||
"has_serial_no": "No",
|
||||
"is_purchase_item": "Yes",
|
||||
"is_sales_item": "Yes",
|
||||
"is_service_item": "No",
|
||||
"inspection_required": "No",
|
||||
"is_pro_applicable": "Yes",
|
||||
"is_sub_contracted_item": "No",
|
||||
"is_manufactured_item": "Yes",
|
||||
"stock_uom": "_Test UOM"
|
||||
}],
|
||||
[{
|
||||
"doctype": "Item",
|
||||
"item_code": "_Test FG Item 2",
|
||||
"item_name": "_Test FG Item 2",
|
||||
"description": "_Test FG Item 2",
|
||||
"item_group": "_Test Item Group Desktops",
|
||||
"is_stock_item": "Yes",
|
||||
"default_warehouse": "_Test Warehouse - _TC",
|
||||
"default_income_account": "Sales - _TC",
|
||||
"is_asset_item": "No",
|
||||
"has_batch_no": "No",
|
||||
"has_serial_no": "No",
|
||||
"is_purchase_item": "Yes",
|
||||
"is_sales_item": "Yes",
|
||||
"is_service_item": "No",
|
||||
"inspection_required": "No",
|
||||
"is_pro_applicable": "Yes",
|
||||
"is_sub_contracted_item": "Yes",
|
||||
"stock_uom": "_Test UOM"
|
||||
}],
|
||||
]
|
||||
@@ -21,23 +21,27 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten
|
||||
+ wn._("Fulfilled"), cint(doc.per_ordered));
|
||||
}
|
||||
|
||||
if(doc.docstatus == 1 && doc.status != 'Stopped'){
|
||||
if(doc.docstatus==0) {
|
||||
cur_frm.add_custom_button(wn._("Get Items from BOM"), cur_frm.cscript.get_items_from_bom, "icon-sitemap");
|
||||
}
|
||||
|
||||
if(doc.docstatus == 1 && doc.status != 'Stopped') {
|
||||
if(doc.material_request_type === "Purchase")
|
||||
cur_frm.add_custom_button("Make Supplier Quotation",
|
||||
cur_frm.add_custom_button(wn._("Make Supplier Quotation"),
|
||||
this.make_supplier_quotation);
|
||||
|
||||
if(doc.material_request_type === "Transfer" && doc.status === "Submitted")
|
||||
cur_frm.add_custom_button("Transfer Material", this.make_stock_entry);
|
||||
cur_frm.add_custom_button(wn._("Transfer Material"), this.make_stock_entry);
|
||||
|
||||
if(flt(doc.per_ordered, 2) < 100) {
|
||||
if(doc.material_request_type === "Purchase")
|
||||
cur_frm.add_custom_button('Make Purchase Order',
|
||||
cur_frm.add_custom_button(wn._('Make Purchase Order'),
|
||||
this.make_purchase_order);
|
||||
|
||||
cur_frm.add_custom_button('Stop Material Request',
|
||||
cur_frm.add_custom_button(wn._('Stop Material Request'),
|
||||
cur_frm.cscript['Stop Material Request']);
|
||||
}
|
||||
cur_frm.add_custom_button('Send SMS', cur_frm.cscript.send_sms);
|
||||
cur_frm.add_custom_button(wn._('Send SMS'), cur_frm.cscript.send_sms);
|
||||
|
||||
}
|
||||
|
||||
@@ -58,11 +62,58 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten
|
||||
}
|
||||
|
||||
if(doc.docstatus == 1 && doc.status == 'Stopped')
|
||||
cur_frm.add_custom_button('Unstop Material Request',
|
||||
cur_frm.add_custom_button(wn._('Unstop Material Request'),
|
||||
cur_frm.cscript['Unstop Material Request']);
|
||||
|
||||
},
|
||||
|
||||
schedule_date: function(doc, cdt, cdn) {
|
||||
var val = locals[cdt][cdn].schedule_date;
|
||||
if(val) {
|
||||
$.each(wn.model.get("Material Request Item", { parent: cur_frm.doc.name }), function(i, d) {
|
||||
if(!d.schedule_date) {
|
||||
d.schedule_date = val;
|
||||
}
|
||||
});
|
||||
refresh_field("indent_details");
|
||||
}
|
||||
},
|
||||
|
||||
get_items_from_bom: function() {
|
||||
var d = new wn.ui.Dialog({
|
||||
title: wn._("Get Items from BOM"),
|
||||
fields: [
|
||||
{"fieldname":"bom", "fieldtype":"Link", "label":wn._("BOM"),
|
||||
options:"BOM"},
|
||||
{"fieldname":"fetch_exploded", "fieldtype":"Check",
|
||||
"label":wn._("Fetch exploded BOM (including sub-assemblies)"), "default":1},
|
||||
{fieldname:"fetch", "label":wn._("Get Items from BOM"), "fieldtype":"Button"}
|
||||
]
|
||||
});
|
||||
d.get_input("fetch").on("click", function() {
|
||||
var values = d.get_values();
|
||||
if(!values) return;
|
||||
|
||||
wn.call({
|
||||
method:"manufacturing.doctype.bom.bom.get_bom_items",
|
||||
args: values,
|
||||
callback: function(r) {
|
||||
$.each(r.message, function(i, item) {
|
||||
var d = wn.model.add_child(cur_frm.doc, "Material Request Item", "indent_details");
|
||||
d.item_code = item.item_code;
|
||||
d.description = item.description;
|
||||
d.warehouse = item.default_warehouse;
|
||||
d.uom = item.stock_uom;
|
||||
d.qty = item.qty;
|
||||
});
|
||||
d.hide();
|
||||
refresh_field("indent_details");
|
||||
}
|
||||
});
|
||||
});
|
||||
d.show();
|
||||
},
|
||||
|
||||
tc_name: function() {
|
||||
this.get_terms();
|
||||
},
|
||||
@@ -103,12 +154,12 @@ $.extend(cur_frm.cscript, new erpnext.buying.MaterialRequestController({frm: cur
|
||||
cur_frm.cscript.qty = function(doc, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
if (flt(d.qty) < flt(d.min_order_qty))
|
||||
alert("Warning: Material Requested Qty is less than Minimum Order Qty");
|
||||
alert(wn._("Warning: Material Requested Qty is less than Minimum Order Qty"));
|
||||
};
|
||||
|
||||
cur_frm.cscript['Stop Material Request'] = function() {
|
||||
var doc = cur_frm.doc;
|
||||
var check = confirm("Do you really want to STOP this Material Request?");
|
||||
var check = confirm(wn._("Do you really want to STOP this Material Request?"));
|
||||
|
||||
if (check) {
|
||||
return $c('runserverobj', args={'method':'update_status', 'arg': 'Stopped', 'docs': wn.model.compress(make_doclist(doc.doctype, doc.name))}, function(r,rt) {
|
||||
@@ -119,7 +170,7 @@ cur_frm.cscript['Stop Material Request'] = function() {
|
||||
|
||||
cur_frm.cscript['Unstop Material Request'] = function(){
|
||||
var doc = cur_frm.doc;
|
||||
var check = confirm("Do you really want to UNSTOP this Material Request?");
|
||||
var check = confirm(wn._("Do you really want to UNSTOP this Material Request?"));
|
||||
|
||||
if (check) {
|
||||
return $c('runserverobj', args={'method':'update_status', 'arg': 'Submitted','docs': wn.model.compress(make_doclist(doc.doctype, doc.name))}, function(r,rt) {
|
||||
|
||||
@@ -20,10 +20,6 @@ class DocType(BuyingController):
|
||||
self.tname = 'Material Request Item'
|
||||
self.fname = 'indent_details'
|
||||
|
||||
# get available qty at warehouse
|
||||
def get_bin_details(self, arg = ''):
|
||||
return get_obj(dt='Purchase Common').get_bin_details(arg)
|
||||
|
||||
def check_if_already_pulled(self):
|
||||
pass#if self.[d.sales_order_no for d in getlist(self.doclist, 'indent_details')]
|
||||
|
||||
@@ -100,9 +96,6 @@ class DocType(BuyingController):
|
||||
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)
|
||||
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
{
|
||||
"creation": "2013-03-07 14:48:38",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-08-08 14:22:27",
|
||||
"modified": "2013-10-02 14:24:42",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
{
|
||||
"allow_attach": 1,
|
||||
"allow_import": 1,
|
||||
"allow_print": 0,
|
||||
"autoname": "naming_series:",
|
||||
"doctype": "DocType",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-02-22 01:28:02",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-08-07 14:45:11",
|
||||
"modified": "2013-10-11 14:21:32",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@@ -138,7 +138,7 @@
|
||||
"oldfieldname": "item_name",
|
||||
"oldfieldtype": "Data",
|
||||
"print_width": "100px",
|
||||
"reqd": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"width": "100px"
|
||||
},
|
||||
|
||||
0
stock/doctype/packed_item/__init__.py
Normal file
0
stock/doctype/packed_item/__init__.py
Normal file
105
stock/doctype/packed_item/packed_item.py
Normal file
105
stock/doctype/packed_item/packed_item.py
Normal file
@@ -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
|
||||
@@ -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",
|
||||
@@ -45,13 +45,13 @@ cur_frm.cscript.validate = function(doc, cdt, cdn) {
|
||||
cur_frm.cscript.validate_case_nos = function(doc) {
|
||||
doc = locals[doc.doctype][doc.name];
|
||||
if(cint(doc.from_case_no)==0) {
|
||||
msgprint("Case No. cannot be 0")
|
||||
msgprint(wn._("Case No. cannot be 0"))
|
||||
validated = false;
|
||||
} else if(!cint(doc.to_case_no)) {
|
||||
doc.to_case_no = doc.from_case_no;
|
||||
refresh_field('to_case_no');
|
||||
} else if(cint(doc.to_case_no) < cint(doc.from_case_no)) {
|
||||
msgprint("'To Case No.' cannot be less than 'From Case No.'");
|
||||
msgprint(wn._("'To Case No.' cannot be less than 'From Case No.'"));
|
||||
validated = false;
|
||||
}
|
||||
}
|
||||
@@ -72,14 +72,14 @@ cur_frm.cscript.validate_duplicate_items = function(doc, ps_detail) {
|
||||
for(var i=0; i<ps_detail.length; i++) {
|
||||
for(var j=0; j<ps_detail.length; j++) {
|
||||
if(i!=j && ps_detail[i].item_code && ps_detail[i].item_code==ps_detail[j].item_code) {
|
||||
msgprint("You have entered duplicate items. Please rectify and try again.");
|
||||
msgprint(wn._("You have entered duplicate items. Please rectify and try again."));
|
||||
validated = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(flt(ps_detail[i].qty)<=0) {
|
||||
msgprint("Invalid quantity specified for item " + ps_detail[i].item_code +
|
||||
". Quantity should be greater than 0.");
|
||||
msgprint(wn._("Invalid quantity specified for item ") + ps_detail[i].item_code +
|
||||
"."+wn._(" Quantity should be greater than 0."));
|
||||
validated = false;
|
||||
}
|
||||
}
|
||||
@@ -95,9 +95,9 @@ cur_frm.cscript.calc_net_total_pkg = function(doc, ps_detail) {
|
||||
for(var i=0; i<ps_detail.length; i++) {
|
||||
var item = ps_detail[i];
|
||||
if(item.weight_uom != doc.net_weight_uom) {
|
||||
msgprint("Different UOM for items will lead to incorrect \
|
||||
(Total) Net Weight value. Make sure that Net Weight of each item is \
|
||||
in the same UOM.")
|
||||
msgprint(wn._("Different UOM for items will lead to incorrect")+
|
||||
wn._("(Total) Net Weight value. Make sure that Net Weight of each item is")+
|
||||
wn._("in the same UOM."))
|
||||
validated = false;
|
||||
}
|
||||
net_weight_pkg += flt(item.net_weight) * flt(item.qty);
|
||||
|
||||
@@ -17,15 +17,15 @@ erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend
|
||||
|
||||
if(this.frm.doc.docstatus == 1) {
|
||||
if(!this.frm.doc.__billing_complete) {
|
||||
cur_frm.add_custom_button('Make Purchase Invoice',
|
||||
cur_frm.add_custom_button(wn._('Make Purchase Invoice'),
|
||||
this.make_purchase_invoice);
|
||||
}
|
||||
cur_frm.add_custom_button('Send SMS', cur_frm.cscript['Send SMS']);
|
||||
cur_frm.add_custom_button(wn._('Send SMS'), cur_frm.cscript['Send SMS']);
|
||||
|
||||
this.show_stock_ledger();
|
||||
this.show_general_ledger();
|
||||
} else {
|
||||
cur_frm.add_custom_button(wn._('From Purchase Order'),
|
||||
cur_frm.add_custom_button(wn._(wn._('From Purchase Order')),
|
||||
function() {
|
||||
wn.model.map_current_doc({
|
||||
method: "buying.doctype.purchase_order.purchase_order.make_purchase_receipt",
|
||||
@@ -140,7 +140,7 @@ cur_frm.fields_dict['purchase_receipt_details'].grid.get_field('batch_no').get_q
|
||||
}
|
||||
}
|
||||
else{
|
||||
alert("Please enter Item Code.");
|
||||
alert(wn._("Please enter Item Code."));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,10 +38,6 @@ class DocType(BuyingController):
|
||||
total_qty = sum((item.qty for item in self.doclist.get({"parentfield": "purchase_receipt_details"})))
|
||||
self.doc.fields["__billing_complete"] = billed_qty[0][0] == total_qty
|
||||
|
||||
# get available qty at warehouse
|
||||
def get_bin_details(self, arg = ''):
|
||||
return get_obj(dt='Purchase Common').get_bin_details(arg)
|
||||
|
||||
def validate(self):
|
||||
super(DocType, self).validate()
|
||||
|
||||
@@ -63,7 +59,6 @@ class DocType(BuyingController):
|
||||
|
||||
pc_obj = get_obj(dt='Purchase Common')
|
||||
pc_obj.validate_for_items(self)
|
||||
pc_obj.get_prevdoc_date(self)
|
||||
self.check_for_stopped_status(pc_obj)
|
||||
|
||||
# sub-contracting
|
||||
@@ -232,7 +227,6 @@ class DocType(BuyingController):
|
||||
# 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)
|
||||
@@ -290,10 +284,6 @@ class DocType(BuyingController):
|
||||
bin = webnotes.conn.sql("select actual_qty from `tabBin` where item_code = %s and warehouse = %s", (d.rm_item_code, self.doc.supplier_warehouse), as_dict = 1)
|
||||
d.current_stock = bin and flt(bin[0]['actual_qty']) or 0
|
||||
|
||||
|
||||
def get_rate(self,arg):
|
||||
return get_obj('Purchase Common').get_rate(arg,self)
|
||||
|
||||
def get_gl_entries_for_stock(self, warehouse_account=None):
|
||||
against_stock_account = self.get_company_default("stock_received_but_not_billed")
|
||||
|
||||
|
||||
@@ -104,6 +104,7 @@ class TestPurchaseReceipt(unittest.TestCase):
|
||||
pr.doclist[1].received_qty = 1
|
||||
pr.insert()
|
||||
pr.submit()
|
||||
|
||||
self.assertEquals(webnotes.conn.get_value("Serial No", pr.doclist[1].serial_no,
|
||||
"supplier"), pr.doc.supplier)
|
||||
|
||||
@@ -112,7 +113,7 @@ class TestPurchaseReceipt(unittest.TestCase):
|
||||
def test_serial_no_cancel(self):
|
||||
pr = self.test_serial_no_supplier()
|
||||
pr.cancel()
|
||||
|
||||
|
||||
self.assertFalse(webnotes.conn.get_value("Serial No", pr.doclist[1].serial_no,
|
||||
"warehouse"))
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"creation": "2013-05-24 19:29:10",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-09-20 11:36:55",
|
||||
"modified": "2013-10-10 17:02:51",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
@@ -424,19 +424,6 @@
|
||||
"search_index": 1,
|
||||
"width": "150px"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "prevdoc_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 1,
|
||||
"in_filter": 1,
|
||||
"label": "Purchase Order Date",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "prevdoc_date",
|
||||
"oldfieldtype": "Date",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "rm_supp_cost",
|
||||
|
||||
@@ -22,9 +22,9 @@ class SerialNoNotExistsError(ValidationError): pass
|
||||
class SerialNoDuplicateError(ValidationError): pass
|
||||
|
||||
class DocType(StockController):
|
||||
def __init__(self, doc, doclist=[]):
|
||||
def __init__(self, doc, doclist=None):
|
||||
self.doc = doc
|
||||
self.doclist = doclist
|
||||
self.doclist = doclist or []
|
||||
self.via_stock_ledger = False
|
||||
|
||||
def validate(self):
|
||||
@@ -36,7 +36,6 @@ class DocType(StockController):
|
||||
self.validate_amc_status()
|
||||
self.validate_warehouse()
|
||||
self.validate_item()
|
||||
|
||||
self.on_stock_ledger_entry()
|
||||
|
||||
def validate_amc_status(self):
|
||||
@@ -180,6 +179,15 @@ class DocType(StockController):
|
||||
self.set_purchase_details()
|
||||
self.set_sales_details()
|
||||
|
||||
def on_stock_ledger_entry(self):
|
||||
if self.via_stock_ledger and not self.doc.fields.get("__islocal"):
|
||||
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)
|
||||
validate_serial_no(sle, item_det)
|
||||
@@ -236,7 +244,6 @@ def update_serial_nos(sle, item_det):
|
||||
serial_nos = []
|
||||
for i in xrange(cint(sle.actual_qty)):
|
||||
serial_nos.append(make_autoname(item_det.serial_no_series))
|
||||
|
||||
webnotes.conn.set(sle, "serial_no", "\n".join(serial_nos))
|
||||
|
||||
if sle.serial_no:
|
||||
@@ -286,4 +293,4 @@ def update_serial_nos_after_submit(controller, parentfield):
|
||||
|
||||
if d.serial_no != serial_no:
|
||||
d.serial_no = serial_no
|
||||
webnotes.conn.set_value(d.doctype, d.name, "serial_no", serial_no)
|
||||
webnotes.conn.set_value(d.doctype, d.name, "serial_no", serial_no)
|
||||
|
||||
@@ -70,10 +70,10 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
|
||||
if(this.frm.doc.docstatus === 1 &&
|
||||
wn.boot.profile.can_create.indexOf("Journal Voucher")!==-1) {
|
||||
if(this.frm.doc.purpose === "Sales Return") {
|
||||
this.frm.add_custom_button("Make Credit Note", function() { me.make_return_jv(); });
|
||||
this.frm.add_custom_button(wn._("Make Credit Note"), function() { me.make_return_jv(); });
|
||||
this.add_excise_button();
|
||||
} else if(this.frm.doc.purpose === "Purchase Return") {
|
||||
this.frm.add_custom_button("Make Debit Note", function() { me.make_return_jv(); });
|
||||
this.frm.add_custom_button(wn._("Make Debit Note"), function() { me.make_return_jv(); });
|
||||
this.add_excise_button();
|
||||
}
|
||||
}
|
||||
@@ -195,7 +195,7 @@ erpnext.stock.StockEntry = erpnext.stock.StockController.extend({
|
||||
|
||||
add_excise_button: function() {
|
||||
if(wn.boot.control_panel.country === "India")
|
||||
this.frm.add_custom_button("Make Excise Invoice", function() {
|
||||
this.frm.add_custom_button(wn._("Make Excise Invoice"), function() {
|
||||
var excise = wn.model.make_new_doc_and_get_name('Journal Voucher');
|
||||
excise = locals['Journal Voucher'][excise];
|
||||
excise.voucher_type = 'Excise Voucher';
|
||||
@@ -318,7 +318,7 @@ cur_frm.fields_dict['mtn_details'].grid.get_field('batch_no').get_query = functi
|
||||
}
|
||||
}
|
||||
} else {
|
||||
msgprint("Please enter Item Code to get batch no");
|
||||
msgprint(wn._("Please enter Item Code to get batch no"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,7 +372,7 @@ cur_frm.cscript.validate = function(doc, cdt, cdn) {
|
||||
cur_frm.cscript.validate_items = function(doc) {
|
||||
cl = getchildren('Stock Entry Detail', doc.name, 'mtn_details');
|
||||
if (!cl.length) {
|
||||
alert("Item table can not be blank");
|
||||
alert(wn._("Item table can not be blank"));
|
||||
validated = false;
|
||||
}
|
||||
}
|
||||
@@ -391,4 +391,4 @@ cur_frm.fields_dict.customer.get_query = function(doc, cdt, cdn) {
|
||||
|
||||
cur_frm.fields_dict.supplier.get_query = function(doc, cdt, cdn) {
|
||||
return{ query:"controllers.queries.supplier_query" }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ from stock.stock_ledger import get_previous_sle
|
||||
from controllers.queries import get_match_cond
|
||||
import json
|
||||
|
||||
sql = webnotes.conn.sql
|
||||
|
||||
class NotUpdateStockError(webnotes.ValidationError): pass
|
||||
class StockOverReturnError(webnotes.ValidationError): pass
|
||||
@@ -56,7 +55,6 @@ class DocType(StockController):
|
||||
|
||||
from stock.doctype.serial_no.serial_no import update_serial_nos_after_submit
|
||||
update_serial_nos_after_submit(self, "mtn_details")
|
||||
|
||||
self.update_production_order()
|
||||
self.make_gl_entries()
|
||||
|
||||
@@ -368,8 +366,7 @@ class DocType(StockController):
|
||||
|
||||
def get_item_details(self, arg):
|
||||
arg = json.loads(arg)
|
||||
|
||||
item = sql("""select stock_uom, description, item_name,
|
||||
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)
|
||||
@@ -397,7 +394,7 @@ class DocType(StockController):
|
||||
|
||||
def get_uom_details(self, arg = ''):
|
||||
arg, ret = eval(arg), {}
|
||||
uom = sql("""select conversion_factor from `tabUOM Conversion Detail`
|
||||
uom = webnotes.conn.sql("""select conversion_factor from `tabUOM Conversion Detail`
|
||||
where parent = %s and uom = %s""", (arg['item_code'], arg['uom']), as_dict = 1)
|
||||
if not uom or not flt(uom[0].conversion_factor):
|
||||
msgprint("There is no Conversion Factor for UOM '%s' in Item '%s'" % (arg['uom'],
|
||||
@@ -487,77 +484,16 @@ class DocType(StockController):
|
||||
self.get_stock_and_rate()
|
||||
|
||||
def get_bom_raw_materials(self, qty):
|
||||
"""
|
||||
get all items from flat bom except
|
||||
child items of sub-contracted and sub assembly items
|
||||
and sub assembly items itself.
|
||||
"""
|
||||
from manufacturing.doctype.bom.bom import get_bom_items_as_dict
|
||||
|
||||
# item dict = { item_code: {qty, description, stock_uom} }
|
||||
item_dict = {}
|
||||
item_dict = get_bom_items_as_dict(self.doc.bom_no, qty=qty, fetch_exploded = self.doc.use_multi_level_bom)
|
||||
|
||||
def _make_items_dict(items_list):
|
||||
"""makes dict of unique items with it's qty"""
|
||||
for item in items_list:
|
||||
if item_dict.has_key(item.item_code):
|
||||
item_dict[item.item_code]["qty"] += flt(item.qty)
|
||||
else:
|
||||
item_dict[item.item_code] = {
|
||||
"qty": flt(item.qty),
|
||||
"item_name": item.item_name,
|
||||
"description": item.description,
|
||||
"stock_uom": item.stock_uom,
|
||||
"from_warehouse": item.default_warehouse,
|
||||
"expense_account": item.purchase_account,
|
||||
"cost_center": item.cost_center
|
||||
}
|
||||
|
||||
if self.doc.use_multi_level_bom:
|
||||
# get all raw materials with sub assembly childs
|
||||
fl_bom_sa_child_item = sql("""select
|
||||
fb.item_code,
|
||||
ifnull(sum(fb.qty_consumed_per_unit),0)*%s as qty,
|
||||
fb.description,
|
||||
fb.stock_uom,
|
||||
it.item_name,
|
||||
it.default_warehouse,
|
||||
it.purchase_account,
|
||||
it.cost_center
|
||||
from
|
||||
`tabBOM Explosion Item` fb,`tabItem` it
|
||||
where
|
||||
it.name = fb.item_code
|
||||
and ifnull(it.is_pro_applicable, 'No') = 'No'
|
||||
and ifnull(it.is_sub_contracted_item, 'No') = 'No'
|
||||
and fb.docstatus < 2
|
||||
and fb.parent=%s group by item_code, stock_uom""",
|
||||
(qty, self.doc.bom_no), as_dict=1)
|
||||
|
||||
if fl_bom_sa_child_item:
|
||||
_make_items_dict(fl_bom_sa_child_item)
|
||||
else:
|
||||
# get only BOM items
|
||||
fl_bom_sa_items = sql("""select
|
||||
`tabItem`.item_code,
|
||||
`tabItem`.item_name,
|
||||
ifnull(sum(`tabBOM Item`.qty_consumed_per_unit), 0) *%s as qty,
|
||||
`tabItem`.description,
|
||||
`tabItem`.stock_uom,
|
||||
`tabItem`.default_warehouse,
|
||||
`tabItem`.purchase_account,
|
||||
`tabItem`.cost_center
|
||||
from
|
||||
`tabBOM Item`, `tabItem`
|
||||
where
|
||||
`tabBOM Item`.parent = %s and
|
||||
`tabBOM Item`.item_code = tabItem.name and
|
||||
`tabBOM Item`.docstatus < 2
|
||||
group by item_code""", (qty, self.doc.bom_no), as_dict=1)
|
||||
|
||||
if fl_bom_sa_items:
|
||||
_make_items_dict(fl_bom_sa_items)
|
||||
for item in item_dict.values():
|
||||
item.from_warehouse = item.default_warehouse
|
||||
|
||||
return item_dict
|
||||
|
||||
|
||||
def get_pending_raw_materials(self, pro_obj):
|
||||
"""
|
||||
issue (item quantity) that is pending to issue or desire to transfer,
|
||||
@@ -597,7 +533,7 @@ class DocType(StockController):
|
||||
|
||||
def get_issued_qty(self):
|
||||
issued_item_qty = {}
|
||||
result = sql("""select t1.item_code, sum(t1.qty)
|
||||
result = webnotes.conn.sql("""select t1.item_code, sum(t1.qty)
|
||||
from `tabStock Entry Detail` t1, `tabStock Entry` t2
|
||||
where t1.parent = t2.name and t2.production_order = %s and t2.docstatus = 1
|
||||
and t2.purpose = 'Material Transfer'
|
||||
@@ -654,7 +590,7 @@ class DocType(StockController):
|
||||
|
||||
def get_cust_addr(self):
|
||||
from utilities.transaction_base import get_default_address, get_address_display
|
||||
res = sql("select customer_name from `tabCustomer` where name = '%s'"%self.doc.customer)
|
||||
res = webnotes.conn.sql("select customer_name from `tabCustomer` where name = '%s'"%self.doc.customer)
|
||||
address_display = None
|
||||
customer_address = get_default_address("customer", self.doc.customer)
|
||||
if customer_address:
|
||||
@@ -675,7 +611,7 @@ class DocType(StockController):
|
||||
|
||||
def get_supp_addr(self):
|
||||
from utilities.transaction_base import get_default_address, get_address_display
|
||||
res = sql("""select supplier_name from `tabSupplier`
|
||||
res = webnotes.conn.sql("""select supplier_name from `tabSupplier`
|
||||
where name=%s""", self.doc.supplier)
|
||||
address_display = None
|
||||
supplier_address = get_default_address("customer", self.doc.customer)
|
||||
@@ -914,8 +850,7 @@ def make_return_jv_from_delivery_note(se, ref):
|
||||
ref.doclist[0].name)
|
||||
|
||||
if not invoices_against_delivery:
|
||||
sales_orders_against_delivery = [d.prevdoc_docname for d in
|
||||
ref.doclist.get({"prevdoc_doctype": "Sales Order"}) if d.prevdoc_docname]
|
||||
sales_orders_against_delivery = [d.against_sales_order for d in ref.doclist if d.against_sales_order]
|
||||
|
||||
if sales_orders_against_delivery:
|
||||
invoices_against_delivery = get_invoice_list("Sales Invoice Item", "sales_order",
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
# ERPNext - web based ERP (http://erpnext.com)
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes, unittest
|
||||
from webnotes.utils import flt
|
||||
@@ -47,7 +44,6 @@ class TestStockEntry(unittest.TestCase):
|
||||
self._clear_stock_account_balance()
|
||||
webnotes.bean("Profile", "test2@example.com").get_controller()\
|
||||
.add_roles("Sales User", "Sales Manager", "Material User", "Material Manager")
|
||||
|
||||
webnotes.session.user = "test2@example.com"
|
||||
|
||||
from stock.utils import InvalidWarehouseCompany
|
||||
@@ -67,7 +63,6 @@ class TestStockEntry(unittest.TestCase):
|
||||
|
||||
webnotes.bean("Profile", "test2@example.com").get_controller()\
|
||||
.add_roles("Sales User", "Sales Manager", "Material User", "Material Manager")
|
||||
|
||||
webnotes.session.user = "test@example.com"
|
||||
st1 = webnotes.bean(copy=test_records[0])
|
||||
st1.doc.company = "_Test Company 1"
|
||||
|
||||
57
stock/doctype/stock_ledger/stock_ledger.py
Normal file
57
stock/doctype/stock_ledger/stock_ledger.py
Normal file
@@ -0,0 +1,57 @@
|
||||
# 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 add_days, cstr, flt, nowdate, cint, now
|
||||
from webnotes.model.doc import Document
|
||||
from webnotes.model.bean import getlist
|
||||
from webnotes.model.code import get_obj
|
||||
from webnotes import session, msgprint
|
||||
from stock.utils import get_valid_serial_nos
|
||||
|
||||
|
||||
class DocType:
|
||||
def __init__(self, doc, doclist=[]):
|
||||
self.doc = doc
|
||||
self.doclist = doclist
|
||||
|
||||
def update_stock(self, values, is_amended = 'No'):
|
||||
for v in values:
|
||||
sle_id = ''
|
||||
|
||||
# reverse quantities for cancel
|
||||
if v.get('is_cancelled') == 'Yes':
|
||||
v['actual_qty'] = -flt(v['actual_qty'])
|
||||
# cancel matching entry
|
||||
webnotes.conn.sql("""update `tabStock Ledger Entry` set is_cancelled='Yes',
|
||||
modified=%s, modified_by=%s
|
||||
where voucher_no=%s and voucher_type=%s""",
|
||||
(now(), webnotes.session.user, v['voucher_no'], v['voucher_type']))
|
||||
|
||||
if v.get("actual_qty"):
|
||||
sle_id = self.make_entry(v)
|
||||
|
||||
args = v.copy()
|
||||
args.update({
|
||||
"sle_id": sle_id,
|
||||
"is_amended": is_amended
|
||||
})
|
||||
|
||||
get_obj('Warehouse', v["warehouse"]).update_bin(args)
|
||||
|
||||
|
||||
def make_entry(self, args):
|
||||
args.update({"doctype": "Stock Ledger Entry"})
|
||||
sle = webnotes.bean([args])
|
||||
sle.ignore_permissions = 1
|
||||
sle.insert()
|
||||
return sle.doc.name
|
||||
|
||||
def repost(self):
|
||||
"""
|
||||
Repost everything!
|
||||
"""
|
||||
for wh in webnotes.conn.sql("select name from tabWarehouse"):
|
||||
get_obj('Warehouse', wh[0]).repost_stock()
|
||||
@@ -14,7 +14,6 @@ class DocType(DocListController):
|
||||
|
||||
def validate(self):
|
||||
from stock.utils import validate_warehouse_user, validate_warehouse_company
|
||||
|
||||
self.validate_mandatory()
|
||||
self.validate_item()
|
||||
validate_warehouse_user(self.doc.warehouse)
|
||||
|
||||
@@ -48,13 +48,13 @@ erpnext.stock.StockReconciliation = erpnext.stock.StockController.extend({
|
||||
this.show_download_template();
|
||||
this.show_upload();
|
||||
if(this.frm.doc.reconciliation_json) {
|
||||
this.frm.set_intro("You can submit this Stock Reconciliation.");
|
||||
this.frm.set_intro(wn._("You can submit this Stock Reconciliation."));
|
||||
} else {
|
||||
this.frm.set_intro("Download the Template, fill appropriate data and \
|
||||
attach the modified file.");
|
||||
this.frm.set_intro(wn._("Download the Template, fill appropriate data and \
|
||||
attach the modified file."));
|
||||
}
|
||||
} else if(this.frm.doc.docstatus == 1) {
|
||||
this.frm.set_intro("Cancelling this Stock Reconciliation will nullify its effect.");
|
||||
this.frm.set_intro(wn._("Cancelling this Stock Reconciliation will nullify its effect."));
|
||||
this.show_stock_ledger();
|
||||
this.show_general_ledger();
|
||||
} else {
|
||||
@@ -66,20 +66,20 @@ erpnext.stock.StockReconciliation = erpnext.stock.StockController.extend({
|
||||
|
||||
show_download_template: function() {
|
||||
var me = this;
|
||||
this.frm.add_custom_button("Download Template", function() {
|
||||
this.title = "Stock Reconcilation Template";
|
||||
wn.tools.downloadify([["Stock Reconciliation"],
|
||||
this.frm.add_custom_button(wn._("Download Template"), function() {
|
||||
this.title = wn._("Stock Reconcilation Template");
|
||||
wn.tools.downloadify([[wn._("Stock Reconciliation")],
|
||||
["----"],
|
||||
["Stock Reconciliation can be used to update the stock on a particular date,"
|
||||
+ " usually as per physical inventory."],
|
||||
["When submitted, the system creates difference entries"
|
||||
+ " to set the given stock and valuation on this date."],
|
||||
["It can also be used to create opening stock entries and to fix stock value."],
|
||||
[wn._("Stock Reconciliation can be used to update the stock on a particular date, ")
|
||||
+ wn._("usually as per physical inventory.")],
|
||||
[wn._("When submitted, the system creates difference entries ")
|
||||
+ wn._("to set the given stock and valuation on this date.")],
|
||||
[wn._("It can also be used to create opening stock entries and to fix stock value.")],
|
||||
["----"],
|
||||
["Notes:"],
|
||||
["Item Code and Warehouse should already exist."],
|
||||
["You can update either Quantity or Valuation Rate or both."],
|
||||
["If no change in either Quantity or Valuation Rate, leave the cell blank."],
|
||||
[wn._("Notes:")],
|
||||
[wn._("Item Code and Warehouse should already exist.")],
|
||||
[wn._("You can update either Quantity or Valuation Rate or both.")],
|
||||
[wn._("If no change in either Quantity or Valuation Rate, leave the cell blank.")],
|
||||
["----"],
|
||||
["Item Code", "Warehouse", "Quantity", "Valuation Rate"]], null, this);
|
||||
return false;
|
||||
@@ -113,8 +113,8 @@ erpnext.stock.StockReconciliation = erpnext.stock.StockController.extend({
|
||||
show_download_reconciliation_data: function() {
|
||||
var me = this;
|
||||
if(this.frm.doc.reconciliation_json) {
|
||||
this.frm.add_custom_button("Download Reconcilation Data", function() {
|
||||
this.title = "Stock Reconcilation Data";
|
||||
this.frm.add_custom_button(wn._("Download Reconcilation Data"), function() {
|
||||
this.title = wn._("Stock Reconcilation Data");
|
||||
wn.tools.downloadify(JSON.parse(me.frm.doc.reconciliation_json), null, this);
|
||||
return false;
|
||||
}, "icon-download");
|
||||
|
||||
@@ -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 @@ class DocType:
|
||||
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)
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ from webnotes.model.bean import copy_doclist
|
||||
from webnotes.model.code import get_obj
|
||||
from webnotes import msgprint, _
|
||||
|
||||
sql = webnotes.conn.sql
|
||||
|
||||
class DocType:
|
||||
def __init__(self, d, dl=[]):
|
||||
@@ -34,7 +33,7 @@ class DocType:
|
||||
msgprint("Please Enter Conversion Factor.")
|
||||
raise Exception
|
||||
|
||||
stock_uom = sql("select stock_uom from `tabItem` where name = '%s'" % self.doc.item_code)
|
||||
stock_uom = webnotes.conn.sql("select stock_uom from `tabItem` where name = '%s'" % self.doc.item_code)
|
||||
stock_uom = stock_uom and stock_uom[0][0]
|
||||
if cstr(self.doc.new_stock_uom) == cstr(stock_uom):
|
||||
msgprint("Item Master is already updated with New Stock UOM " + cstr(self.doc.new_stock_uom))
|
||||
@@ -50,9 +49,9 @@ class DocType:
|
||||
def update_bin(self):
|
||||
# update bin
|
||||
if flt(self.doc.conversion_factor) != flt(1):
|
||||
sql("update `tabBin` set stock_uom = '%s' , indented_qty = ifnull(indented_qty,0) * %s, ordered_qty = ifnull(ordered_qty,0) * %s, reserved_qty = ifnull(reserved_qty,0) * %s, planned_qty = ifnull(planned_qty,0) * %s, projected_qty = actual_qty + ordered_qty + indented_qty + planned_qty - reserved_qty where item_code = '%s'" % (self.doc.new_stock_uom, self.doc.conversion_factor, self.doc.conversion_factor, self.doc.conversion_factor, self.doc.conversion_factor, self.doc.item_code) )
|
||||
webnotes.conn.sql("update `tabBin` set stock_uom = '%s' , indented_qty = ifnull(indented_qty,0) * %s, ordered_qty = ifnull(ordered_qty,0) * %s, reserved_qty = ifnull(reserved_qty,0) * %s, planned_qty = ifnull(planned_qty,0) * %s, projected_qty = actual_qty + ordered_qty + indented_qty + planned_qty - reserved_qty where item_code = '%s'" % (self.doc.new_stock_uom, self.doc.conversion_factor, self.doc.conversion_factor, self.doc.conversion_factor, self.doc.conversion_factor, self.doc.item_code) )
|
||||
else:
|
||||
sql("update `tabBin` set stock_uom = '%s' where item_code = '%s'" % (self.doc.new_stock_uom, self.doc.item_code) )
|
||||
webnotes.conn.sql("update `tabBin` set stock_uom = '%s' where item_code = '%s'" % (self.doc.new_stock_uom, self.doc.item_code) )
|
||||
|
||||
# acknowledge user
|
||||
msgprint(" All Bins Updated Successfully.")
|
||||
@@ -62,16 +61,16 @@ class DocType:
|
||||
from stock.stock_ledger import update_entries_after
|
||||
|
||||
if flt(self.doc.conversion_factor) != flt(1):
|
||||
sql("update `tabStock Ledger Entry` set stock_uom = '%s', actual_qty = ifnull(actual_qty,0) * '%s' where item_code = '%s' " % (self.doc.new_stock_uom, self.doc.conversion_factor, self.doc.item_code))
|
||||
webnotes.conn.sql("update `tabStock Ledger Entry` set stock_uom = '%s', actual_qty = ifnull(actual_qty,0) * '%s' where item_code = '%s' " % (self.doc.new_stock_uom, self.doc.conversion_factor, self.doc.item_code))
|
||||
else:
|
||||
sql("update `tabStock Ledger Entry` set stock_uom = '%s' where item_code = '%s' " % (self.doc.new_stock_uom, self.doc.item_code))
|
||||
webnotes.conn.sql("update `tabStock Ledger Entry` set stock_uom = '%s' where item_code = '%s' " % (self.doc.new_stock_uom, self.doc.item_code))
|
||||
|
||||
# acknowledge user
|
||||
msgprint("Stock Ledger Entries Updated Successfully.")
|
||||
|
||||
# update item valuation
|
||||
if flt(self.doc.conversion_factor) != flt(1):
|
||||
wh = sql("select name from `tabWarehouse`")
|
||||
wh = webnotes.conn.sql("select name from `tabWarehouse`")
|
||||
for w in wh:
|
||||
update_entries_after({"item_code": self.doc.item_code, "warehouse": w[0]})
|
||||
|
||||
|
||||
@@ -7,11 +7,11 @@ cur_frm.cscript.refresh = function(doc) {
|
||||
|
||||
cur_frm.cscript.merge = function(doc, cdt, cdn) {
|
||||
if (!doc.merge_with) {
|
||||
msgprint("Please enter the warehouse to which you want to merge?");
|
||||
msgprint(wn._("Please enter the warehouse to which you want to merge?"));
|
||||
return;
|
||||
}
|
||||
var check = confirm("Are you sure you want to merge this warehouse into "
|
||||
+ doc.merge_with + "?");
|
||||
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', '', '');
|
||||
}
|
||||
|
||||
@@ -3,12 +3,9 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
from webnotes.utils import cint, validate_email_add
|
||||
from webnotes import msgprint, _
|
||||
|
||||
sql = webnotes.conn.sql
|
||||
|
||||
class DocType:
|
||||
def __init__(self, doc, doclist=[]):
|
||||
self.doc = doc
|
||||
@@ -31,8 +28,8 @@ class DocType:
|
||||
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.__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",
|
||||
@@ -58,7 +55,16 @@ class DocType:
|
||||
else:
|
||||
webnotes.throw(_("Please enter account group under which account \
|
||||
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
|
||||
@@ -93,14 +99,15 @@ class DocType:
|
||||
|
||||
def on_trash(self):
|
||||
# delete bin
|
||||
bins = 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']:
|
||||
msgprint("""Warehouse: %s can not be deleted as qty exists for item: %s"""
|
||||
% (self.doc.name, d['item_code']), raise_exception=1)
|
||||
else:
|
||||
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",
|
||||
{"account_type": "Warehosue", "master_name": self.doc.name})
|
||||
@@ -108,19 +115,10 @@ class DocType:
|
||||
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""",
|
||||
self.doc.name):
|
||||
msgprint("""Warehosue can not be deleted as stock ledger entry
|
||||
exists for this warehouse.""", raise_exception=1)
|
||||
else:
|
||||
sql("delete from `tabStock Ledger Entry` where warehouse = %s", self.doc.name)
|
||||
|
||||
def on_rename(self, newdn, olddn, merge=False):
|
||||
account = webnotes.conn.get_value("Account", {"account_type": "Warehouse",
|
||||
"master_name": olddn})
|
||||
webnotes.conn.set_value("Account", account, "master_name", newdn)
|
||||
|
||||
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""", newdn):
|
||||
update_entries_after({"item_code": item_code, "warehouse": newdn})
|
||||
webnotes.conn.sql("delete from `tabStock Ledger Entry` where warehouse = %s",
|
||||
self.doc.name)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
wn.pages['stock-ageing'].onload = function(wrapper) {
|
||||
wn.ui.make_app_page({
|
||||
parent: wrapper,
|
||||
title: 'Stock Ageing',
|
||||
title: wn._('Stock Ageing'),
|
||||
single_column: true
|
||||
});
|
||||
|
||||
@@ -21,7 +21,7 @@ wn.require("app/js/stock_grid_report.js");
|
||||
erpnext.StockAgeing = erpnext.StockGridReport.extend({
|
||||
init: function(wrapper) {
|
||||
this._super({
|
||||
title: "Stock Ageing",
|
||||
title: wn._("Stock Ageing"),
|
||||
page: wrapper,
|
||||
parent: $(wrapper).find('.layout-main'),
|
||||
appframe: wrapper.appframe,
|
||||
@@ -30,37 +30,37 @@ erpnext.StockAgeing = erpnext.StockGridReport.extend({
|
||||
},
|
||||
setup_columns: function() {
|
||||
this.columns = [
|
||||
{id: "name", name: "Item", field: "name", width: 300,
|
||||
{id: "name", name: wn._("Item"), field: "name", width: 300,
|
||||
link_formatter: {
|
||||
open_btn: true,
|
||||
doctype: '"Item"'
|
||||
}},
|
||||
{id: "item_name", name: "Item Name", field: "item_name",
|
||||
{id: "item_name", name: wn._("Item Name"), field: "item_name",
|
||||
width: 100, formatter: this.text_formatter},
|
||||
{id: "description", name: "Description", field: "description",
|
||||
{id: "description", name: wn._("Description"), field: "description",
|
||||
width: 200, formatter: this.text_formatter},
|
||||
{id: "brand", name: "Brand", field: "brand", width: 100},
|
||||
{id: "average_age", name: "Average Age", field: "average_age",
|
||||
{id: "brand", name: wn._("Brand"), field: "brand", width: 100},
|
||||
{id: "average_age", name: wn._("Average Age"), field: "average_age",
|
||||
formatter: this.currency_formatter},
|
||||
{id: "earliest", name: "Earliest", field: "earliest",
|
||||
{id: "earliest", name: wn._("Earliest"), field: "earliest",
|
||||
formatter: this.currency_formatter},
|
||||
{id: "latest", name: "Latest", field: "latest",
|
||||
{id: "latest", name: wn._("Latest"), field: "latest",
|
||||
formatter: this.currency_formatter},
|
||||
{id: "stock_uom", name: "UOM", field: "stock_uom", width: 100},
|
||||
];
|
||||
},
|
||||
filters: [
|
||||
{fieldtype:"Select", label: "Warehouse", link:"Warehouse",
|
||||
{fieldtype:"Select", label: wn._("Warehouse"), link:"Warehouse",
|
||||
default_value: "Select Warehouse..."},
|
||||
{fieldtype:"Select", label: "Brand", link:"Brand",
|
||||
{fieldtype:"Select", label: wn._("Brand"), link:"Brand",
|
||||
default_value: "Select Brand...", filter: function(val, item, opts) {
|
||||
return val == opts.default_value || item.brand == val;
|
||||
}, link_formatter: {filter_input: "brand"}},
|
||||
{fieldtype:"Select", label: "Plot By",
|
||||
{fieldtype:"Select", label: wn._("Plot By"),
|
||||
options: ["Average Age", "Earliest", "Latest"]},
|
||||
{fieldtype:"Date", label: "To Date"},
|
||||
{fieldtype:"Button", label: "Refresh", icon:"icon-refresh icon-white", cssClass:"btn-info"},
|
||||
{fieldtype:"Button", label: "Reset Filters"}
|
||||
{fieldtype:"Date", label: wn._("To Date")},
|
||||
{fieldtype:"Button", label: wn._("Refresh"), icon:"icon-refresh icon-white", cssClass:"btn-info"},
|
||||
{fieldtype:"Button", label: wn._("Reset Filters")}
|
||||
],
|
||||
setup_filters: function() {
|
||||
var me = this;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
wn.pages['stock-analytics'].onload = function(wrapper) {
|
||||
wn.ui.make_app_page({
|
||||
parent: wrapper,
|
||||
title: 'Stock Analytics',
|
||||
title: wn._('Stock Analytics'),
|
||||
single_column: true
|
||||
});
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ wn.require("app/js/stock_analytics.js");
|
||||
wn.pages['stock-balance'].onload = function(wrapper) {
|
||||
wn.ui.make_app_page({
|
||||
parent: wrapper,
|
||||
title: 'Stock Balance',
|
||||
title: wn._('Stock Balance'),
|
||||
single_column: true
|
||||
});
|
||||
|
||||
@@ -20,58 +20,58 @@ wn.pages['stock-balance'].onload = function(wrapper) {
|
||||
erpnext.StockBalance = erpnext.StockAnalytics.extend({
|
||||
init: function(wrapper) {
|
||||
this._super(wrapper, {
|
||||
title: "Stock Balance",
|
||||
title: wn._("Stock Balance"),
|
||||
doctypes: ["Item", "Item Group", "Warehouse", "Stock Ledger Entry", "Brand",
|
||||
"Stock Entry", "Project"],
|
||||
});
|
||||
},
|
||||
setup_columns: function() {
|
||||
this.columns = [
|
||||
{id: "name", name: "Item", field: "name", width: 300,
|
||||
{id: "name", name: wn._("Item"), field: "name", width: 300,
|
||||
formatter: this.tree_formatter},
|
||||
{id: "item_name", name: "Item Name", field: "item_name", width: 100},
|
||||
{id: "description", name: "Description", field: "description", width: 200,
|
||||
{id: "item_name", name: wn._("Item Name"), field: "item_name", width: 100},
|
||||
{id: "description", name: wn._("Description"), field: "description", width: 200,
|
||||
formatter: this.text_formatter},
|
||||
{id: "brand", name: "Brand", field: "brand", width: 100},
|
||||
{id: "stock_uom", name: "UOM", field: "stock_uom", width: 100},
|
||||
{id: "opening_qty", name: "Opening Qty", field: "opening_qty", width: 100,
|
||||
{id: "brand", name: wn._("Brand"), field: "brand", width: 100},
|
||||
{id: "stock_uom", name: wn._("UOM"), field: "stock_uom", width: 100},
|
||||
{id: "opening_qty", name: wn._("Opening Qty"), field: "opening_qty", width: 100,
|
||||
formatter: this.currency_formatter},
|
||||
{id: "inflow_qty", name: "In Qty", field: "inflow_qty", width: 100,
|
||||
{id: "inflow_qty", name: wn._("In Qty"), field: "inflow_qty", width: 100,
|
||||
formatter: this.currency_formatter},
|
||||
{id: "outflow_qty", name: "Out Qty", field: "outflow_qty", width: 100,
|
||||
{id: "outflow_qty", name: wn._("Out Qty"), field: "outflow_qty", width: 100,
|
||||
formatter: this.currency_formatter},
|
||||
{id: "closing_qty", name: "Closing Qty", field: "closing_qty", width: 100,
|
||||
{id: "closing_qty", name: wn._("Closing Qty"), field: "closing_qty", width: 100,
|
||||
formatter: this.currency_formatter},
|
||||
|
||||
{id: "opening_value", name: "Opening Value", field: "opening_value", width: 100,
|
||||
{id: "opening_value", name: wn._("Opening Value"), field: "opening_value", width: 100,
|
||||
formatter: this.currency_formatter},
|
||||
{id: "inflow_value", name: "In Value", field: "inflow_value", width: 100,
|
||||
{id: "inflow_value", name: wn._("In Value"), field: "inflow_value", width: 100,
|
||||
formatter: this.currency_formatter},
|
||||
{id: "outflow_value", name: "Out Value", field: "outflow_value", width: 100,
|
||||
{id: "outflow_value", name: wn._("Out Value"), field: "outflow_value", width: 100,
|
||||
formatter: this.currency_formatter},
|
||||
{id: "closing_value", name: "Closing Value", field: "closing_value", width: 100,
|
||||
{id: "closing_value", name: wn._("Closing Value"), field: "closing_value", width: 100,
|
||||
formatter: this.currency_formatter},
|
||||
];
|
||||
},
|
||||
|
||||
filters: [
|
||||
{fieldtype:"Select", label: "Brand", link:"Brand",
|
||||
{fieldtype:"Select", label: wn._("Brand"), link:"Brand",
|
||||
default_value: "Select Brand...", filter: function(val, item, opts) {
|
||||
return val == opts.default_value || item.brand == val || item._show;
|
||||
}, link_formatter: {filter_input: "brand"}},
|
||||
{fieldtype:"Select", label: "Warehouse", link:"Warehouse",
|
||||
{fieldtype:"Select", label: wn._("Warehouse"), link:"Warehouse",
|
||||
default_value: "Select Warehouse...", filter: function(val, item, opts, me) {
|
||||
return me.apply_zero_filter(val, item, opts, me);
|
||||
}},
|
||||
{fieldtype:"Select", label: "Project", link:"Project",
|
||||
{fieldtype:"Select", label: wn._("Project"), link:"Project",
|
||||
default_value: "Select Project...", filter: function(val, item, opts, me) {
|
||||
return me.apply_zero_filter(val, item, opts, me);
|
||||
}, link_formatter: {filter_input: "project"}},
|
||||
{fieldtype:"Date", label: "From Date"},
|
||||
{fieldtype:"Label", label: "To"},
|
||||
{fieldtype:"Date", label: "To Date"},
|
||||
{fieldtype:"Button", label: "Refresh", icon:"icon-refresh icon-white", cssClass:"btn-info"},
|
||||
{fieldtype:"Button", label: "Reset Filters"}
|
||||
{fieldtype:"Date", label: wn._("From Date")},
|
||||
{fieldtype:"Label", label: wn._("To")},
|
||||
{fieldtype:"Date", label: wn._("To Date")},
|
||||
{fieldtype:"Button", label: wn._("Refresh"), icon:"icon-refresh icon-white", cssClass:"btn-info"},
|
||||
{fieldtype:"Button", label: wn._("Reset Filters")}
|
||||
],
|
||||
|
||||
setup_plot_check: function() {
|
||||
|
||||
@@ -111,7 +111,7 @@ wn.module_page["Stock"] = [
|
||||
"label": wn._("Stock Settings"),
|
||||
"route": "Form/Stock Settings",
|
||||
"doctype":"Stock Settings",
|
||||
"description": "Settings for Stock Module"
|
||||
"description": wn._("Settings for Stock Module")
|
||||
},
|
||||
{
|
||||
"route":"Sales Browser/Item Group",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
wn.pages['stock-ledger'].onload = function(wrapper) {
|
||||
wn.ui.make_app_page({
|
||||
parent: wrapper,
|
||||
title: 'Stock Ledger',
|
||||
title: wn._('Stock Ledger'),
|
||||
single_column: true
|
||||
});
|
||||
|
||||
@@ -17,7 +17,7 @@ wn.require("app/js/stock_grid_report.js");
|
||||
erpnext.StockLedger = erpnext.StockGridReport.extend({
|
||||
init: function(wrapper) {
|
||||
this._super({
|
||||
title: "Stock Ledger",
|
||||
title: wn._("Stock Ledger"),
|
||||
page: wrapper,
|
||||
parent: $(wrapper).find('.layout-main'),
|
||||
appframe: wrapper.appframe,
|
||||
@@ -28,29 +28,29 @@ erpnext.StockLedger = erpnext.StockGridReport.extend({
|
||||
setup_columns: function() {
|
||||
this.hide_balance = (this.is_default("item_code") || this.voucher_no) ? true : false;
|
||||
this.columns = [
|
||||
{id: "posting_datetime", name: "Posting Date", field: "posting_datetime", width: 120,
|
||||
{id: "posting_datetime", name: wn._("Posting Date"), field: "posting_datetime", width: 120,
|
||||
formatter: this.date_formatter},
|
||||
{id: "item_code", name: "Item Code", field: "item_code", width: 160,
|
||||
{id: "item_code", name: wn._("Item Code"), field: "item_code", width: 160,
|
||||
link_formatter: {
|
||||
filter_input: "item_code",
|
||||
open_btn: true,
|
||||
doctype: '"Item"',
|
||||
}},
|
||||
{id: "description", name: "Description", field: "description", width: 200,
|
||||
{id: "description", name: wn._("Description"), field: "description", width: 200,
|
||||
formatter: this.text_formatter},
|
||||
{id: "warehouse", name: "Warehouse", field: "warehouse", width: 100,
|
||||
{id: "warehouse", name: wn._("Warehouse"), field: "warehouse", width: 100,
|
||||
link_formatter: {filter_input: "warehouse"}},
|
||||
{id: "brand", name: "Brand", field: "brand", width: 100},
|
||||
{id: "stock_uom", name: "UOM", field: "stock_uom", width: 100},
|
||||
{id: "qty", name: "Qty", field: "qty", width: 100,
|
||||
{id: "brand", name: wn._("Brand"), field: "brand", width: 100},
|
||||
{id: "stock_uom", name: wn._("UOM"), field: "stock_uom", width: 100},
|
||||
{id: "qty", name: wn._("Qty"), field: "qty", width: 100,
|
||||
formatter: this.currency_formatter},
|
||||
{id: "balance", name: "Balance Qty", field: "balance", width: 100,
|
||||
{id: "balance", name: wn._("Balance Qty"), field: "balance", width: 100,
|
||||
formatter: this.currency_formatter,
|
||||
hidden: this.hide_balance},
|
||||
{id: "balance_value", name: "Balance Value", field: "balance_value", width: 100,
|
||||
{id: "balance_value", name: wn._("Balance Value"), field: "balance_value", width: 100,
|
||||
formatter: this.currency_formatter, hidden: this.hide_balance},
|
||||
{id: "voucher_type", name: "Voucher Type", field: "voucher_type", width: 120},
|
||||
{id: "voucher_no", name: "Voucher No", field: "voucher_no", width: 160,
|
||||
{id: "voucher_type", name: wn._("Voucher Type"), field: "voucher_type", width: 120},
|
||||
{id: "voucher_no", name: wn._("Voucher No"), field: "voucher_no", width: 160,
|
||||
link_formatter: {
|
||||
filter_input: "voucher_no",
|
||||
open_btn: true,
|
||||
@@ -60,11 +60,11 @@ erpnext.StockLedger = erpnext.StockGridReport.extend({
|
||||
|
||||
},
|
||||
filters: [
|
||||
{fieldtype:"Select", label: "Warehouse", link:"Warehouse",
|
||||
{fieldtype:"Select", label: wn._("Warehouse"), link:"Warehouse",
|
||||
default_value: "Select Warehouse...", filter: function(val, item, opts) {
|
||||
return item.warehouse == val || val == opts.default_value;
|
||||
}},
|
||||
{fieldtype:"Link", label: "Item Code", link:"Item", default_value: "Select Item...",
|
||||
{fieldtype:"Link", label: wn._("Item Code"), link:"Item", default_value: "Select Item...",
|
||||
filter: function(val, item, opts) {
|
||||
return item.item_code == val || !val;
|
||||
}},
|
||||
@@ -72,20 +72,20 @@ erpnext.StockLedger = erpnext.StockGridReport.extend({
|
||||
default_value: "Select Brand...", filter: function(val, item, opts) {
|
||||
return val == opts.default_value || item.brand == val || item._show;
|
||||
}, link_formatter: {filter_input: "brand"}},
|
||||
{fieldtype:"Data", label: "Voucher No",
|
||||
{fieldtype:"Data", label: wn._("Voucher No"),
|
||||
filter: function(val, item, opts) {
|
||||
if(!val) return true;
|
||||
return (item.voucher_no && item.voucher_no.indexOf(val)!=-1);
|
||||
}},
|
||||
{fieldtype:"Date", label: "From Date", filter: function(val, item) {
|
||||
{fieldtype:"Date", label: wn._("From Date"), filter: function(val, item) {
|
||||
return dateutil.str_to_obj(val) <= dateutil.str_to_obj(item.posting_date);
|
||||
}},
|
||||
{fieldtype:"Label", label: "To"},
|
||||
{fieldtype:"Date", label: "To Date", filter: function(val, item) {
|
||||
{fieldtype:"Label", label: wn._("To")},
|
||||
{fieldtype:"Date", label: wn._("To Date"), filter: function(val, item) {
|
||||
return dateutil.str_to_obj(val) >= dateutil.str_to_obj(item.posting_date);
|
||||
}},
|
||||
{fieldtype:"Button", label: "Refresh", icon:"icon-refresh icon-white", cssClass:"btn-info"},
|
||||
{fieldtype:"Button", label: "Reset Filters"}
|
||||
{fieldtype:"Button", label: wn._("Refresh"), icon:"icon-refresh icon-white", cssClass:"btn-info"},
|
||||
{fieldtype:"Button", label: wn._("Reset Filters")}
|
||||
],
|
||||
|
||||
setup_filters: function() {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
wn.pages['stock-level'].onload = function(wrapper) {
|
||||
wn.ui.make_app_page({
|
||||
parent: wrapper,
|
||||
title: 'Stock Level',
|
||||
title: wn._('Stock Level'),
|
||||
single_column: true
|
||||
});
|
||||
|
||||
@@ -22,7 +22,7 @@ erpnext.StockLevel = erpnext.StockGridReport.extend({
|
||||
var me = this;
|
||||
|
||||
this._super({
|
||||
title: "Stock Level",
|
||||
title: wn._("Stock Level"),
|
||||
page: wrapper,
|
||||
parent: $(wrapper).find('.layout-main'),
|
||||
appframe: wrapper.appframe,
|
||||
@@ -37,70 +37,70 @@ erpnext.StockLevel = erpnext.StockGridReport.extend({
|
||||
Projected Qty = Actual Qty + Planned Qty + Requested Qty \
|
||||
+ Ordered Qty - Reserved Qty </li> \
|
||||
<ul> \
|
||||
<li>Actual Qty: Quantity available in the warehouse. </li> \
|
||||
<li>Planned Qty: Quantity, for which, Production Order has been raised, \
|
||||
but is pending to be manufactured. </li> \
|
||||
<li>Requested Qty: Quantity requested for purchase, but not ordered. </li> \
|
||||
<li>Ordered Qty: Quantity ordered for purchase, but not received.</li> \
|
||||
<li>Reserved Qty: Quantity ordered for sale, but not delivered. </li> \
|
||||
</ul> \
|
||||
<li>"+wn._("Actual Qty: Quantity available in the warehouse.") +"</li>"+
|
||||
"<li>"+wn._("Planned Qty: Quantity, for which, Production Order has been raised,")+
|
||||
wn._("but is pending to be manufactured.")+ "</li> " +
|
||||
"<li>"+wn._("Requested Qty: Quantity requested for purchase, but not ordered.") + "</li>" +
|
||||
"<li>" + wn._("Ordered Qty: Quantity ordered for purchase, but not received.")+ "</li>" +
|
||||
"<li>" + wn._("Reserved Qty: Quantity ordered for sale, but not delivered.") + "</li>" +
|
||||
"</ul> \
|
||||
</ul>");
|
||||
});
|
||||
},
|
||||
|
||||
setup_columns: function() {
|
||||
this.columns = [
|
||||
{id: "item_code", name: "Item Code", field: "item_code", width: 160,
|
||||
{id: "item_code", name: wn._("Item Code"), field: "item_code", width: 160,
|
||||
link_formatter: {
|
||||
filter_input: "item_code",
|
||||
open_btn: true,
|
||||
doctype: '"Item"',
|
||||
}},
|
||||
{id: "item_name", name: "Item Name", field: "item_name", width: 100,
|
||||
{id: "item_name", name: wn._("Item Name"), field: "item_name", width: 100,
|
||||
formatter: this.text_formatter},
|
||||
{id: "description", name: "Description", field: "description", width: 200,
|
||||
{id: "description", name: wn._("Description"), field: "description", width: 200,
|
||||
formatter: this.text_formatter},
|
||||
{id: "brand", name: "Brand", field: "brand", width: 100,
|
||||
{id: "brand", name: wn._("Brand"), field: "brand", width: 100,
|
||||
link_formatter: {filter_input: "brand"}},
|
||||
{id: "warehouse", name: "Warehouse", field: "warehouse", width: 100,
|
||||
{id: "warehouse", name: wn._("Warehouse"), field: "warehouse", width: 100,
|
||||
link_formatter: {filter_input: "warehouse"}},
|
||||
{id: "uom", name: "UOM", field: "uom", width: 60},
|
||||
{id: "actual_qty", name: "Actual Qty",
|
||||
{id: "uom", name: wn._("UOM"), field: "uom", width: 60},
|
||||
{id: "actual_qty", name: wn._("Actual Qty"),
|
||||
field: "actual_qty", width: 80, formatter: this.currency_formatter},
|
||||
{id: "planned_qty", name: "Planned Qty",
|
||||
{id: "planned_qty", name: wn._("Planned Qty"),
|
||||
field: "planned_qty", width: 80, formatter: this.currency_formatter},
|
||||
{id: "requested_qty", name: "Requested Qty",
|
||||
{id: "requested_qty", name: wn._("Requested Qty"),
|
||||
field: "requested_qty", width: 80, formatter: this.currency_formatter},
|
||||
{id: "ordered_qty", name: "Ordered Qty",
|
||||
{id: "ordered_qty", name: wn._("Ordered Qty"),
|
||||
field: "ordered_qty", width: 80, formatter: this.currency_formatter},
|
||||
{id: "reserved_qty", name: "Reserved Qty",
|
||||
{id: "reserved_qty", name: wn._("Reserved Qty"),
|
||||
field: "reserved_qty", width: 80, formatter: this.currency_formatter},
|
||||
{id: "projected_qty", name: "Projected Qty",
|
||||
{id: "projected_qty", name: wn._("Projected Qty"),
|
||||
field: "projected_qty", width: 80, formatter: this.currency_formatter},
|
||||
{id: "re_order_level", name: "Re-Order Level",
|
||||
{id: "re_order_level", name: wn._("Re-Order Level"),
|
||||
field: "re_order_level", width: 80, formatter: this.currency_formatter},
|
||||
{id: "re_order_qty", name: "Re-Order Qty",
|
||||
{id: "re_order_qty", name: wn._("Re-Order Qty"),
|
||||
field: "re_order_qty", width: 80, formatter: this.currency_formatter},
|
||||
];
|
||||
},
|
||||
|
||||
filters: [
|
||||
{fieldtype:"Link", label: "Item Code", link:"Item", default_value: "Select Item...",
|
||||
{fieldtype:"Link", label: wn._("Item Code"), link:"Item", default_value: "Select Item...",
|
||||
filter: function(val, item, opts) {
|
||||
return item.item_code == val || !val;
|
||||
}},
|
||||
|
||||
{fieldtype:"Select", label: "Warehouse", link:"Warehouse",
|
||||
{fieldtype:"Select", label: wn._("Warehouse"), link:"Warehouse",
|
||||
default_value: "Select Warehouse...", filter: function(val, item, opts) {
|
||||
return item.warehouse == val || val == opts.default_value;
|
||||
}},
|
||||
|
||||
{fieldtype:"Select", label: "Brand", link:"Brand",
|
||||
{fieldtype:"Select", label: wn._("Brand"), link:"Brand",
|
||||
default_value: "Select Brand...", filter: function(val, item, opts) {
|
||||
return val == opts.default_value || item.brand == val;
|
||||
}},
|
||||
{fieldtype:"Button", label: "Refresh", icon:"icon-refresh icon-white", cssClass:"btn-info"},
|
||||
{fieldtype:"Button", label: "Reset Filters"}
|
||||
{fieldtype:"Button", label: wn._("Refresh"), icon:"icon-refresh icon-white", cssClass:"btn-info"},
|
||||
{fieldtype:"Button", label: wn._("Reset Filters")}
|
||||
],
|
||||
|
||||
setup_filters: function() {
|
||||
|
||||
@@ -5,14 +5,14 @@ wn.query_reports["Batch-Wise Balance History"] = {
|
||||
"filters": [
|
||||
{
|
||||
"fieldname":"from_date",
|
||||
"label": "From Date",
|
||||
"label": wn._("From Date"),
|
||||
"fieldtype": "Date",
|
||||
"width": "80",
|
||||
"default": sys_defaults.year_start_date,
|
||||
},
|
||||
{
|
||||
"fieldname":"to_date",
|
||||
"label": "To Date",
|
||||
"label": wn._("To Date"),
|
||||
"fieldtype": "Date",
|
||||
"width": "80",
|
||||
"default": wn.datetime.get_today()
|
||||
|
||||
@@ -5,13 +5,13 @@ wn.query_reports["Itemwise Recommended Reorder Level"] = {
|
||||
"filters": [
|
||||
{
|
||||
"fieldname":"from_date",
|
||||
"label": "From Date",
|
||||
"label": wn._("From Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": sys_defaults.year_start_date
|
||||
},
|
||||
{
|
||||
"fieldname":"to_date",
|
||||
"label": "To Date",
|
||||
"label": wn._("To Date"),
|
||||
"fieldtype": "Date",
|
||||
"default": get_today()
|
||||
}
|
||||
|
||||
@@ -5,14 +5,14 @@ wn.query_reports["Warehouse-Wise Stock Balance"] = {
|
||||
"filters": [
|
||||
{
|
||||
"fieldname":"from_date",
|
||||
"label": "From Date",
|
||||
"label": wn._("From Date"),
|
||||
"fieldtype": "Date",
|
||||
"width": "80",
|
||||
"default": sys_defaults.year_start_date,
|
||||
},
|
||||
{
|
||||
"fieldname":"to_date",
|
||||
"label": "To Date",
|
||||
"label": wn._("To Date"),
|
||||
"fieldtype": "Date",
|
||||
"width": "80",
|
||||
"default": wn.datetime.get_today()
|
||||
|
||||
@@ -10,6 +10,9 @@ import json
|
||||
# future reposting
|
||||
class NegativeStockError(webnotes.ValidationError): pass
|
||||
|
||||
_exceptions = webnotes.local('stockledger_exceptions')
|
||||
# _exceptions = []
|
||||
|
||||
def make_sl_entries(sl_entries, is_amended=None):
|
||||
if sl_entries:
|
||||
from stock.utils import update_bin
|
||||
@@ -55,7 +58,6 @@ def delete_cancelled_entry(voucher_type, voucher_no):
|
||||
webnotes.conn.sql("""delete from `tabStock Ledger Entry`
|
||||
where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
|
||||
|
||||
_exceptions = []
|
||||
def update_entries_after(args, verbose=1):
|
||||
"""
|
||||
update valution rate and qty after transaction
|
||||
@@ -68,8 +70,8 @@ def update_entries_after(args, verbose=1):
|
||||
"posting_time": "12:00"
|
||||
}
|
||||
"""
|
||||
global _exceptions
|
||||
_exceptions = []
|
||||
if not _exceptions:
|
||||
webnotes.local.stockledger_exceptions = []
|
||||
|
||||
previous_sle = get_sle_before_datetime(args)
|
||||
|
||||
@@ -190,10 +192,12 @@ def validate_negative_stock(qty_after_transaction, sle):
|
||||
will not consider cancelled entries
|
||||
"""
|
||||
diff = qty_after_transaction + flt(sle.actual_qty)
|
||||
|
||||
if not _exceptions:
|
||||
webnotes.local.stockledger_exceptions = []
|
||||
|
||||
if diff < 0 and abs(diff) > 0.0001:
|
||||
# negative stock!
|
||||
global _exceptions
|
||||
exc = sle.copy().update({"diff": diff})
|
||||
_exceptions.append(exc)
|
||||
return False
|
||||
@@ -327,4 +331,4 @@ def get_previous_sle(args, for_update=False):
|
||||
sle = get_stock_ledger_entries(args, ["name != %(sle)s",
|
||||
"timestamp(posting_date, posting_time) <= timestamp(%(posting_date)s, %(posting_time)s)"],
|
||||
"desc", "limit 1", for_update=for_update)
|
||||
return sle and sle[0] or {}
|
||||
return sle and sle[0] or {}
|
||||
|
||||
@@ -252,10 +252,10 @@ def get_buying_amount(voucher_type, voucher_no, item_row, stock_ledger_entries):
|
||||
|
||||
def reorder_item():
|
||||
""" Reorder item if stock reaches reorder level"""
|
||||
if not hasattr(webnotes, "auto_indent"):
|
||||
webnotes.auto_indent = cint(webnotes.conn.get_value('Stock Settings', None, 'auto_indent'))
|
||||
if getattr(webnotes.local, "auto_indent", None) is None:
|
||||
webnotes.local.auto_indent = cint(webnotes.conn.get_value('Stock Settings', None, 'auto_indent'))
|
||||
|
||||
if webnotes.auto_indent:
|
||||
if webnotes.local.auto_indent:
|
||||
material_requests = {}
|
||||
bin_list = webnotes.conn.sql("""select item_code, warehouse, projected_qty
|
||||
from tabBin where ifnull(item_code, '') != '' and ifnull(warehouse, '') != ''
|
||||
@@ -340,18 +340,18 @@ def create_material_request(material_requests):
|
||||
mr_list.append(mr_bean)
|
||||
|
||||
except:
|
||||
if webnotes.message_log:
|
||||
exceptions_list.append([] + webnotes.message_log)
|
||||
webnotes.message_log = []
|
||||
if webnotes.local.message_log:
|
||||
exceptions_list.append([] + webnotes.local.message_log)
|
||||
webnotes.local.message_log = []
|
||||
else:
|
||||
exceptions_list.append(webnotes.getTraceback())
|
||||
|
||||
if mr_list:
|
||||
if not hasattr(webnotes, "reorder_email_notify"):
|
||||
webnotes.reorder_email_notify = cint(webnotes.conn.get_value('Stock Settings', None,
|
||||
if getattr(webnotes.local, "reorder_email_notify", None) is None:
|
||||
webnotes.local.reorder_email_notify = cint(webnotes.conn.get_value('Stock Settings', None,
|
||||
'reorder_email_notify'))
|
||||
|
||||
if(webnotes.reorder_email_notify):
|
||||
if(webnotes.local.reorder_email_notify):
|
||||
send_email_notification(mr_list)
|
||||
|
||||
if exceptions_list:
|
||||
@@ -393,4 +393,4 @@ def notify_errors(exceptions_list):
|
||||
Administrator""" % ("\n\n".join(["\n".join(msg) for msg in exceptions_list]),)
|
||||
|
||||
from webnotes.profile import get_system_managers
|
||||
sendmail(get_system_managers(), subject=subject, msg=msg)
|
||||
sendmail(get_system_managers(), subject=subject, msg=msg)
|
||||
|
||||
Reference in New Issue
Block a user