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:
Pratik Vyas
2013-10-25 14:07:48 +05:30
313 changed files with 3813 additions and 3018 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1 +0,0 @@
from __future__ import unicode_literals

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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