Merge branch 'master' of github.com:webnotes/erpnext into slow

Conflicts:
	stock/doctype/purchase_receipt/purchase_receipt.js
This commit is contained in:
Rushabh Mehta
2013-07-15 20:57:26 +02:00
694 changed files with 8668 additions and 10570 deletions

View File

@@ -1,8 +1,8 @@
[
{
"creation": "2013-03-01 08:21:54",
"creation": "2013-03-05 14:50:38",
"docstatus": 0,
"modified": "2013-03-01 08:22:16",
"modified": "2013-05-01 15:49:47",
"modified_by": "Administrator",
"owner": "harshada@webnotestech.com"
},
@@ -98,24 +98,6 @@
"oldfieldname": "finished_date",
"oldfieldtype": "Date"
},
{
"doctype": "DocField",
"fieldname": "trash_reason",
"fieldtype": "Small Text",
"label": "Trash Reason",
"oldfieldname": "trash_reason",
"oldfieldtype": "Small Text",
"read_only": 1
},
{
"doctype": "DocField",
"fieldname": "file_list",
"fieldtype": "Text",
"hidden": 1,
"label": "File List",
"no_copy": 1,
"print_hide": 1
},
{
"doctype": "DocPerm"
}

View File

@@ -77,10 +77,6 @@ class DocType:
self.doc.save()
if (flt(args.get("actual_qty")) < 0 or flt(args.get("reserved_qty")) > 0) \
and args.get("is_cancelled") == 'No' and args.get("is_amended")=='No':
self.reorder_item(args.get("voucher_type"), args.get("voucher_no"))
def get_first_sle(self):
sle = sql("""
select * from `tabStock Ledger Entry`
@@ -90,82 +86,4 @@ class DocType:
order by timestamp(posting_date, posting_time) asc, name asc
limit 1
""", (self.doc.item_code, self.doc.warehouse), as_dict=1)
return sle and sle[0] or None
def reorder_item(self,doc_type,doc_name):
""" Reorder item if stock reaches reorder level"""
if not hasattr(webnotes, "auto_indent"):
webnotes.auto_indent = webnotes.conn.get_value('Global Defaults', None, 'auto_indent')
if webnotes.auto_indent:
#check if re-order is required
item_reorder = webnotes.conn.get("Item Reorder",
{"parent": self.doc.item_code, "warehouse": self.doc.warehouse})
if item_reorder:
reorder_level = item_reorder.warehouse_reorder_level
reorder_qty = item_reorder.warehouse_reorder_qty
material_request_type = item_reorder.material_request_type or "Purchase"
else:
reorder_level, reorder_qty = webnotes.conn.get_value("Item", self.doc.item_code,
["re_order_level", "re_order_qty"])
material_request_type = "Purchase"
if flt(reorder_qty) and flt(self.doc.projected_qty) < flt(reorder_level):
self.create_material_request(doc_type, doc_name, reorder_level, reorder_qty,
material_request_type)
def create_material_request(self, doc_type, doc_name, reorder_level, reorder_qty,
material_request_type="Purchase"):
""" Create indent on reaching reorder level """
defaults = webnotes.defaults.get_defaults()
item = webnotes.doc("Item", self.doc.item_code)
mr = webnotes.bean([{
"doctype": "Material Request",
"company": defaults.company,
"fiscal_year": defaults.fiscal_year,
"transaction_date": nowdate(),
"material_request_type": material_request_type,
"remark": _("This is an auto generated Material Request.") + \
_("It was raised because the (actual + ordered + indented - reserved) quantity reaches re-order level when the following record was created") + \
": " + _(doc_type) + " " + doc_name
}, {
"doctype": "Material Request Item",
"parenttype": "Material Request",
"parentfield": "indent_details",
"item_code": self.doc.item_code,
"schedule_date": add_days(nowdate(),cint(item.lead_time_days)),
"uom": self.doc.stock_uom,
"warehouse": self.doc.warehouse,
"item_name": item.item_name,
"description": item.description,
"item_group": item.item_group,
"qty": reorder_qty,
"brand": item.brand,
}])
mr.insert()
mr.submit()
msgprint("""Item: %s is to be re-ordered. Material Request %s raised.
It was generated from %s: %s""" %
(self.doc.item_code, mr.doc.name, doc_type, doc_name))
if(item.email_notify):
self.send_email_notification(doc_type, doc_name, mr)
def send_email_notification(self, doc_type, doc_name, bean):
""" Notify user about auto creation of indent"""
from webnotes.utils.email_lib import sendmail
email_list=[d[0] for d in sql("""select distinct r.parent from tabUserRole r, tabProfile p
where p.name = r.parent and p.enabled = 1 and p.docstatus < 2
and r.role in ('Purchase Manager','Material Manager')
and p.name not in ('Administrator', 'All', 'Guest')""")]
msg="""A new Material Request has been raised for Item: %s and Warehouse: %s \
on %s due to %s: %s. See %s: %s """ % (self.doc.item_code, self.doc.warehouse,
formatdate(), doc_type, doc_name, bean.doc.doctype,
get_url_to_form(bean.doc.doctype, bean.doc.name))
sendmail(email_list, subject='Auto Material Request Generation Notification', msg = msg)
return sle and sle[0] or None

View File

@@ -323,6 +323,17 @@ if (sys_defaults.auto_inventory_accounting) {
}
// cost center
cur_frm.cscript.cost_center = function(doc, cdt, cdn){
var d = locals[cdt][cdn];
if(d.cost_center) {
var cl = getchildren('Delivery Note Item', doc.name, cur_frm.cscript.fname, doc.doctype);
for(var i = 0; i < cl.length; i++){
if(!cl[i].cost_center) cl[i].cost_center = d.cost_center;
}
}
refresh_field(cur_frm.cscript.fname);
}
cur_frm.fields_dict.delivery_note_details.grid.get_field("cost_center").get_query = function(doc) {
return {
query: "accounts.utils.get_cost_center_list",

View File

@@ -419,4 +419,4 @@ class DocType(SellingController):
if gl_entries:
from accounts.general_ledger import make_gl_entries
make_gl_entries(gl_entries)
make_gl_entries(gl_entries, cancel=(self.doc.docstatus == 2))

View File

@@ -1,6 +1,6 @@
[
{
"creation": "2013-01-29 17:54:12",
"creation": "2013-04-02 10:50:50",
"docstatus": 0,
"modified": "2013-02-02 19:18:38",
"modified_by": "Administrator",
@@ -32,9 +32,7 @@
"parent": "Delivery Note",
"parentfield": "permissions",
"parenttype": "DocType",
"permlevel": 0,
"read": 1,
"report": 1
"read": 1
},
{
"doctype": "DocType",
@@ -1123,20 +1121,25 @@
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "file_list",
"fieldtype": "Text",
"hidden": 1,
"label": "File List",
"no_copy": 1,
"print_hide": 1,
"read_only": 0
"amend": 1,
"cancel": 1,
"create": 1,
"doctype": "DocPerm",
"permlevel": 0,
"report": 1,
"role": "Material User",
"submit": 1,
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"role": "Accounts User",
"match": "",
"permlevel": 1,
"report": 0,
"role": "Material User",
"submit": 0,
"write": 0
},
@@ -1145,31 +1148,73 @@
"cancel": 1,
"create": 1,
"doctype": "DocPerm",
"role": "Sales User",
"submit": 1,
"write": 1
},
{
"doctype": "DocPerm",
"match": "customer_name",
"role": "Customer"
},
{
"amend": 1,
"cancel": 1,
"create": 1,
"doctype": "DocPerm",
"permlevel": 0,
"report": 1,
"role": "Material Manager",
"submit": 1,
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"match": "",
"permlevel": 1,
"report": 0,
"role": "Material Manager",
"submit": 0,
"write": 0
},
{
"amend": 1,
"cancel": 1,
"create": 1,
"doctype": "DocPerm",
"role": "Material User",
"match": "",
"permlevel": 0,
"report": 1,
"role": "Sales User",
"submit": 1,
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"match": "",
"permlevel": 1,
"report": 0,
"role": "Sales User",
"submit": 0,
"write": 0
},
{
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"permlevel": 0,
"report": 1,
"role": "Accounts User",
"submit": 0,
"write": 0
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"match": "",
"permlevel": 1,
"role": "Accounts User",
"submit": 0
},
{
"doctype": "DocPerm",
"match": "customer_name",
"permlevel": 0,
"report": 1,
"role": "Customer"
}
]

View File

@@ -1,8 +1,8 @@
[
{
"creation": "2013-04-01 10:49:21",
"creation": "2013-04-22 13:15:44",
"docstatus": 0,
"modified": "2013-04-17 17:20:58",
"modified": "2013-05-22 12:05:32",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -340,6 +340,7 @@
"hidden": 1,
"in_filter": 1,
"label": "Document Type",
"no_copy": 1,
"oldfieldname": "prevdoc_doctype",
"oldfieldtype": "Data",
"print_hide": 1,
@@ -371,6 +372,7 @@
"hidden": 1,
"in_filter": 1,
"label": "Against Document Date",
"no_copy": 1,
"oldfieldname": "prevdoc_date",
"oldfieldtype": "Date",
"print_hide": 1,
@@ -383,6 +385,7 @@
"hidden": 1,
"in_filter": 1,
"label": "Against Document Detail No",
"no_copy": 1,
"oldfieldname": "prevdoc_detail_docname",
"oldfieldtype": "Data",
"print_hide": 1,

View File

@@ -14,11 +14,17 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
cur_frm.add_fetch("price_list_name", "currency", "ref_currency")
cur_frm.cscript.refresh = function(doc) {
// make sensitive fields(has_serial_no, is_stock_item, valuation_method)
// read only if any stock ledger entry exists
cur_frm.toggle_enable("item_code", doc.__islocal);
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) {
@@ -128,11 +134,7 @@ cur_frm.fields_dict.item_supplier_details.grid.get_field("supplier").get_query =
erpnext.utils.supplier_query;
cur_frm.cscript.on_remove_attachment = function(doc) {
// refresh image list before unsetting image
refresh_field("image");
if(!inList(cur_frm.fields_dict.image.df.options.split("\n"), doc.image)) {
// if the selected image is removed from attachment, unset it
cur_frm.set_value("image", "");
msgprint(wn._("Attachment removed. You may need to update: ")
+ wn.meta.get_docfield(doc.doctype, "description_html").label);
}
@@ -151,3 +153,7 @@ cur_frm.cscript.copy_from_item_group = function(doc) {
cur_frm.refresh();
});
}
cur_frm.cscript.image = function() {
refresh_field("image_view");
}

View File

@@ -23,51 +23,197 @@ from webnotes.model.bean import getlist
from webnotes import msgprint, _
from webnotes.model.controller import DocListController
class DocType(DocListController):
def get_tax_rate(self, tax_type):
rate = webnotes.conn.sql("select tax_rate from tabAccount where name = %s", tax_type)
ret = {
'tax_rate' : rate and flt(rate[0][0]) or 0
}
return ret
class PriceListCurrencyMismatch(Exception): pass
class DocType(DocListController):
def autoname(self):
if webnotes.conn.get_default("item_naming_by")=="Naming Series":
from webnotes.model.doc import make_autoname
self.doc.item_code = make_autoname(self.doc.naming_series+'.#####')
elif not self.doc.item_code:
msgprint(_("Item Code is mandatory"), raise_exception=1)
self.doc.name = self.doc.item_code
def validate(self):
if not self.doc.stock_uom:
msgprint(_("Please enter Default Unit of Measure"), raise_exception=1)
self.check_stock_uom_with_bin()
self.validate_conversion_factor()
self.add_default_uom_in_conversion_factor_table()
self.valiadte_item_type()
self.check_for_active_boms()
self.validate_price_lists()
self.fill_customer_code()
self.check_item_tax()
self.validate_barcode()
self.check_non_asset_warehouse()
self.cant_change()
self.validate_item_type_for_reorder()
if self.doc.name:
self.old_page_name = webnotes.conn.get_value('Item', self.doc.name, 'page_name')
def on_update(self):
self.validate_name_with_item_group()
# webpage updates
self.update_website()
bin = webnotes.conn.sql("select stock_uom from `tabBin` where item_code = %s",
self.doc.item_code)
if bin and cstr(bin[0][0]) and cstr(bin[0][0]) != cstr(self.doc.stock_uom):
msgprint("Please Update Stock UOM with the help of Stock UOM Replace Utility.")
raise Exception
def add_default_uom_in_conversion_factor_table(self):
uom_conv_list = [d.uom for d in self.doclist.get({"parentfield": "uom_conversion_details"})]
if self.doc.stock_uom not in uom_conv_list:
ch = addchild(self.doc, 'uom_conversion_details', 'UOM Conversion Detail', self.doclist)
ch.uom = self.doc.stock_uom
ch.conversion_factor = 1
def check_stock_uom_with_bin(self):
if not self.doc.fields.get("__islocal"):
bin = webnotes.conn.sql("select stock_uom from `tabBin` where item_code = %s",
self.doc.name)
if self.doc.stock_uom and bin and cstr(bin[0][0]) \
and cstr(bin[0][0]) != cstr(self.doc.stock_uom):
msgprint(_("Please Update Stock UOM with the help of Stock UOM Replace Utility."),
raise_exception=1)
def validate_conversion_factor(self):
check_list = []
for d in getlist(self.doclist,'uom_conversion_details'):
if not self.doc.stock_uom:
msgprint("Please enter Stock UOM first.")
raise Exception
if cstr(d.uom) in check_list:
msgprint("UOM %s has been entered more than once in Conversion Factor Details." % cstr(d.uom))
raise Exception
msgprint(_("UOM %s has been entered more than once in Conversion Factor Table." %
cstr(d.uom)), raise_exception=1)
else:
check_list.append(cstr(d.uom))
if cstr(d.uom) == cstr(self.doc.stock_uom):
if flt(d.conversion_factor) != 1:
msgprint("Conversion Factor of UOM : %s should be equal to 1. As UOM : %s is Stock UOM of Item: %s." % ( cstr(d.uom), cstr(d.uom), cstr(self.doc.name)))
raise Exception
elif cstr(d.uom) != cstr(self.doc.stock_uom) and flt(d.conversion_factor) == 1:
msgprint("Conversion Factor of UOM : %s should not be equal to 1. As UOM : %s is not Stock UOM of Item: %s." % ( cstr(d.uom), cstr(d.uom), cstr(self.doc.name)))
raise Exception
if d.uom and cstr(d.uom) == cstr(self.doc.stock_uom) and flt(d.conversion_factor) != 1:
msgprint(_("""Conversion Factor of UOM: %s should be equal to 1.
As UOM: %s is Stock UOM of Item: %s.""" %
(d.uom, d.uom, self.doc.name)), raise_exception=1)
elif d.uom and cstr(d.uom)!= self.doc.stock_uom and flt(d.conversion_factor) == 1:
msgprint(_("""Conversion Factor of UOM: %s should not be equal to 1.
As UOM: %s is not Stock UOM of Item: %s""" %
(d.uom, d.uom, self.doc.name)), raise_exception=1)
def valiadte_item_type(self):
if cstr(self.doc.is_manufactured_item) == "No":
self.doc.is_pro_applicable = "No"
if not cstr(self.doc.stock_uom) in check_list :
child = addchild( self.doc, 'uom_conversion_details',
'UOM Conversion Detail', self.doclist)
child.uom = self.doc.stock_uom
child.conversion_factor = 1
child.save()
if self.doc.is_pro_applicable == 'Yes' and self.doc.is_stock_item == 'No':
msgprint("As Production Order can be made for this Item, then Is Stock Item Should be 'Yes' as we maintain it's stock. Refer Manufacturing and Inventory section.", raise_exception=1)
if self.doc.has_serial_no == 'Yes' and self.doc.is_stock_item == 'No':
msgprint("'Has Serial No' can not be 'Yes' for non-stock item", raise_exception=1)
def check_for_active_boms(self):
def _check_for_active_boms(field_label):
if field_label in ['Is Active', 'Is Purchase Item']:
bom_mat = webnotes.conn.sql("""select distinct t1.parent
from `tabBOM Item` t1, `tabBOM` t2 where t2.name = t1.parent
and t1.item_code =%s and ifnull(t1.bom_no, '') = '' and t2.is_active = 1
and t2.docstatus = 1 and t1.docstatus =1 """, self.doc.name)
if bom_mat and bom_mat[0][0]:
msgprint(_(field_label) + _(" should be 'Yes'. As Item: ") + self.doc.name +
_(" is present in one or many Active BOMs"), raise_exception=1)
if ((field_label == 'Allow Production Order'
and self.doc.is_sub_contracted_item != 'Yes')
or (field_label == 'Is Sub Contracted Item'
and self.doc.is_manufactured_item != 'Yes')):
bom = webnotes.conn.sql("""select name from `tabBOM` where item = %s
and is_active = 1""", (self.doc.name,))
if bom and bom[0][0]:
msgprint(_(field_label) + _(" should be 'Yes'. As Item: ") + self.doc.name +
_(" is present in one or many Active BOMs"), raise_exception=1)
if not cint(self.doc.fields.get("__islocal")):
fl = {'is_manufactured_item' :'Allow Bill of Materials',
'is_sub_contracted_item':'Is Sub Contracted Item',
'is_purchase_item' :'Is Purchase Item',
'is_pro_applicable' :'Allow Production Order'}
for d in fl:
if cstr(self.doc.fields.get(d)) != 'Yes':
_check_for_active_boms(fl[d])
def validate_price_lists(self):
price_lists=[]
for d in getlist(self.doclist,'ref_rate_details'):
if d.price_list_name in price_lists:
msgprint(_("Cannot have two prices for same Price List") + ": " + d.price_list_name,
raise_exception= webnotes.DuplicateEntryError)
else:
price_list_currency = webnotes.conn.get_value("Price List", d.price_list_name, "currency")
if price_list_currency and d.ref_currency != price_list_currency:
msgprint(_("Currency does not match Price List Currency for Price List") \
+ ": " + d.price_list_name, raise_exception=PriceListCurrencyMismatch)
price_lists.append(d.price_list_name)
def fill_customer_code(self):
""" Append all the customer codes and insert into "customer_code" field of item table """
cust_code=[]
for d in getlist(self.doclist,'item_customer_details'):
cust_code.append(d.ref_code)
self.doc.customer_code=','.join(cust_code)
def check_item_tax(self):
"""Check whether Tax Rate is not entered twice for same Tax Type"""
check_list=[]
for d in getlist(self.doclist,'item_tax'):
if d.tax_type:
account_type = webnotes.conn.get_value("Account", d.tax_type, "account_type")
if account_type not in ['Tax', 'Chargeable']:
msgprint("'%s' is not Tax / Chargeable Account" % d.tax_type, raise_exception=1)
else:
if d.tax_type in check_list:
msgprint("Rate is entered twice for: '%s'" % d.tax_type, raise_exception=1)
else:
check_list.append(d.tax_type)
def validate_barcode(self):
if self.doc.barcode:
duplicate = webnotes.conn.sql("""select name from tabItem where barcode = %s
and name != %s""", (self.doc.barcode, self.doc.name))
if duplicate:
msgprint("Barcode: %s already used in item: %s" %
(self.doc.barcode, cstr(duplicate[0][0])), raise_exception = 1)
def check_non_asset_warehouse(self):
if not self.doc.__islocal and self.doc.is_asset_item == "Yes":
existing_qty = webnotes.conn.sql("select t1.warehouse, t1.actual_qty from tabBin t1, tabWarehouse t2 where t1.item_code=%s and (t2.warehouse_type!='Fixed Asset' or t2.warehouse_type is null) and t1.warehouse=t2.name and t1.actual_qty > 0", self.doc.name)
for e in existing_qty:
msgprint("%s Units exist in Warehouse %s, which is not an Asset Warehouse." %
(e[1],e[0]))
if existing_qty:
self.doc.is_asset_item = 'No'
msgprint(_("""Please transfer the above quantities to an asset warehouse \
before changing this item to an asset item"""), raise_exception=1)
def cant_change(self):
if not self.doc.fields.get("__islocal"):
vals = webnotes.conn.get_value("Item", self.doc.name,
["has_serial_no", "is_stock_item", "valuation_method"], as_dict=True)
if vals and ((self.doc.is_stock_item == "No" and vals.is_stock_item == "Yes") or
vals.has_serial_no != self.doc.has_serial_no or
vals.valuation_method != self.doc.valuation_method):
if self.check_if_sle_exists() == "exists":
webnotes.msgprint(_("As there are existing stock transactions for this \
item, you can not change the values of 'Has Serial No', \
'Is Stock Item' and 'Valuation Method'"), raise_exception=1)
def validate_item_type_for_reorder(self):
if self.doc.re_order_level or len(self.doclist.get({"parentfield": "item_reorder",
"material_request_type": "Purchase"})):
if not self.doc.is_purchase_item:
webnotes.msgprint(_("""To set reorder level, item must be Purchase Item"""),
raise_exception=1)
def check_if_sle_exists(self):
sle = webnotes.conn.sql("""select name from `tabStock Ledger Entry`
where item_code = %s and ifnull(is_cancelled, 'No') = 'No'""", self.doc.name)
return sle and 'exists' or 'not exists'
def validate_name_with_item_group(self):
if webnotes.conn.exists("Item Group", self.doc.name):
@@ -104,107 +250,17 @@ class DocType(DocListController):
webnotes.conn.set(self.doc, "page_name", None)
# On delete 1. Delete BIN (if none of the corrosponding transactions present, it gets deleted. if present, rolled back due to exception)
def on_trash(self):
webnotes.conn.sql("""delete from tabBin where item_code=%s""", self.doc.item_code)
webnotes.conn.sql("""delete from `tabStock Ledger Entry`
where item_code=%s and is_cancelled='Yes' """, self.doc.item_code)
if self.doc.page_name:
from webnotes.webutils import clear_cache
clear_cache(self.doc.page_name)
# Check whether Ref Rate is not entered twice for same Price List and Currency
def check_ref_rate_detail(self):
check_list=[]
for d in getlist(self.doclist,'ref_rate_details'):
if [cstr(d.price_list_name),cstr(d.ref_currency),cint(d.selling),cint(d.buying)] in check_list:
msgprint("Ref Rate is entered twice for Price List : '%s' and Currency : '%s'." % (d.price_list_name,d.ref_currency))
raise Exception
else:
check_list.append([cstr(d.price_list_name),cstr(d.ref_currency)])
def get_tax_rate(self, tax_type):
return { "tax_rate": webnotes.conn.get_value("Account", tax_type, "tax_rate") }
# Append all the customer codes and insert into "customer_code" field of item table
def fill_customer_code(self):
cust_code=[]
for d in getlist(self.doclist,'item_customer_details'):
cust_code.append(d.ref_code)
self.doc.customer_code=','.join(cust_code)
def prepare_template_args(self):
from website.helpers.product import get_parent_item_groups
self.parent_groups = get_parent_item_groups(self.doc.item_group) + [{"name":self.doc.name}]
self.doc.title = self.doc.item_name
def check_item_tax(self):
"""Check whether Tax Rate is not entered twice for same Tax Type"""
check_list=[]
for d in getlist(self.doclist,'item_tax'):
if d.tax_type:
account_type = webnotes.conn.get_value("Account", d.tax_type, "account_type")
if account_type not in ['Tax', 'Chargeable']:
msgprint("'%s' is not Tax / Chargeable Account" % d.tax_type, raise_exception=1)
else:
if d.tax_type in check_list:
msgprint("Rate is entered twice for: '%s'" % d.tax_type, raise_exception=1)
else:
check_list.append(d.tax_type)
def check_for_active_boms(self, field_label):
if field_label in ['Is Active', 'Is Purchase Item']:
bom_mat = webnotes.conn.sql("select distinct t1.parent from `tabBOM Item` t1, `tabBOM` t2 where t1.item_code =%s and (t1.bom_no = '' or t1.bom_no is NULL) and t2.name = t1.parent and t2.is_active = 1 and t2.docstatus = 1 and t1.docstatus =1 ", self.doc.name)
if bom_mat and bom_mat[0][0]:
msgprint("%s should be 'Yes'. As Item %s is present in one or many Active BOMs." % (cstr(field_label), cstr(self.doc.name)))
raise Exception
if ((field_label == 'Allow Production Order'
and self.doc.is_sub_contracted_item != 'Yes')
or (field_label == 'Is Sub Contracted Item'
and self.doc.is_manufactured_item != 'Yes')):
bom = webnotes.conn.sql("select name from `tabBOM` where item = %s and is_active = 1",
(self.doc.name,))
if bom and bom[0][0]:
msgprint("%s should be 'Yes'. As Item %s is present in one or many Active BOMs." % (cstr(field_label), cstr(self.doc.name)))
raise Exception
def validate_barcode(self):
if self.doc.barcode:
duplicate = webnotes.conn.sql("select name from tabItem where barcode = %s and name != %s", (self.doc.barcode, self.doc.name))
if duplicate:
msgprint("Barcode: %s already used in item: %s" % (self.doc.barcode, cstr(duplicate[0][0])), raise_exception = 1)
def validate(self):
if not cint(self.doc.fields.get("__islocal")):
fl = {'is_manufactured_item' :'Allow Bill of Materials',
'is_sub_contracted_item':'Is Sub Contracted Item',
'is_purchase_item' :'Is Purchase Item',
'is_pro_applicable' :'Allow Production Order'}
for d in fl:
if cstr(self.doc.fields.get(d)) != 'Yes':
self.check_for_active_boms(fl[d])
self.check_ref_rate_detail()
self.fill_customer_code()
self.check_item_tax()
self.validate_barcode()
self.check_non_asset_warehouse()
self.cant_change()
if cstr(self.doc.is_manufactured_item) == "No":
self.doc.is_pro_applicable = "No"
if self.doc.is_pro_applicable == 'Yes' and self.doc.is_stock_item == 'No':
msgprint("As Production Order can be made for this Item, then Is Stock Item Should be 'Yes' as we maintain it's stock. Refer Manufacturing and Inventory section.", raise_exception=1)
if self.doc.has_serial_no == 'Yes' and self.doc.is_stock_item == 'No':
msgprint("'Has Serial No' can not be 'Yes' for non-stock item", raise_exception=1)
if self.doc.name:
self.old_page_name = webnotes.conn.get_value('Item', self.doc.name, 'page_name')
def check_non_asset_warehouse(self):
if self.doc.is_asset_item == "Yes":
existing_qty = webnotes.conn.sql("select t1.warehouse, t1.actual_qty from tabBin t1, tabWarehouse t2 where t1.item_code=%s and (t2.warehouse_type!='Fixed Asset' or t2.warehouse_type is null) and t1.warehouse=t2.name and t1.actual_qty > 0", self.doc.name)
for e in existing_qty:
msgprint("%s Units exist in Warehouse %s, which is not an Asset Warehouse." % (e[1],e[0]))
if existing_qty:
msgprint("Please transfer the above quantities to an asset warehouse before changing this item to an asset item.")
self.doc.is_asset_item = 'No'
raise Exception
if self.doc.slideshow:
from website.helpers.slideshow import get_slideshow
get_slideshow(self)
def get_file_details(self, arg = ''):
file = webnotes.conn.sql("select file_group, description from tabFile where name = %s", eval(arg)['file_name'], as_dict = 1)
@@ -215,35 +271,17 @@ class DocType(DocListController):
}
return ret
def on_trash(self):
webnotes.conn.sql("""delete from tabBin where item_code=%s""", self.doc.item_code)
webnotes.conn.sql("""delete from `tabStock Ledger Entry`
where item_code=%s and is_cancelled='Yes' """, self.doc.item_code)
def check_if_sle_exists(self):
sle = webnotes.conn.sql("select name from `tabStock Ledger Entry` where item_code = %s and ifnull(is_cancelled, 'No') = 'No'", self.doc.name)
return sle and 'exists' or 'not exists'
def on_rename(self,newdn,olddn):
webnotes.conn.sql("update tabItem set item_code = %s where name = %s", (newdn, olddn))
if self.doc.page_name:
from webnotes.webutils import clear_cache
clear_cache(self.doc.page_name)
def prepare_template_args(self):
from website.helpers.product import get_parent_item_groups
self.parent_groups = get_parent_item_groups(self.doc.item_group) + [{"name":self.doc.name}]
self.doc.title = self.doc.item_name
if self.doc.slideshow:
from website.helpers.slideshow import get_slideshow
get_slideshow(self)
def cant_change(self):
if not self.doc.fields.get("__islocal"):
vals = webnotes.conn.get_value("Item", self.doc.name,
["has_serial_no", "is_stock_item", "valuation_method"], as_dict=True)
if vals and ((self.doc.is_stock_item == "No" and vals.is_stock_item == "Yes") or
vals.has_serial_no != self.doc.has_serial_no or
vals.valuation_method != self.doc.valuation_method):
if self.check_if_sle_exists() == "exists":
webnotes.msgprint(_("As there are existing stock transactions for this \
item, you can not change the values of 'Has Serial No', \
'Is Stock Item' and 'Valuation Method'"), raise_exception=1)
def on_rename(self,newdn,olddn, merge=False):
webnotes.conn.sql("update tabItem set item_code = %s where name = %s", (newdn, olddn))
if self.doc.page_name:
from webnotes.webutils import clear_cache
clear_cache(self.doc.page_name)

View File

@@ -1,8 +1,8 @@
[
{
"creation": "2013-03-07 15:53:11",
"creation": "2013-05-03 10:45:46",
"docstatus": 0,
"modified": "2013-03-20 15:10:12",
"modified": "2013-05-22 15:48:27",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -33,6 +33,7 @@
"parent": "Item",
"parentfield": "permissions",
"parenttype": "DocType",
"permlevel": 0,
"read": 1,
"report": 1,
"submit": 0
@@ -47,7 +48,16 @@
"fieldtype": "Section Break",
"label": "Item",
"no_copy": 0,
"oldfieldtype": "Section Break"
"oldfieldtype": "Section Break",
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "naming_series",
"fieldtype": "Select",
"label": "Naming Series",
"options": "\nITEM",
"read_only": 0
},
{
"description": "Item will be saved by this name in the data base.",
@@ -56,9 +66,11 @@
"fieldtype": "Data",
"in_filter": 0,
"label": "Item Code",
"no_copy": 1,
"oldfieldname": "item_code",
"oldfieldtype": "Data",
"reqd": 1,
"read_only": 0,
"reqd": 0,
"search_index": 0
},
{
@@ -70,6 +82,7 @@
"label": "Item Name",
"oldfieldname": "item_name",
"oldfieldtype": "Data",
"read_only": 0,
"reqd": 1,
"search_index": 1
},
@@ -83,6 +96,7 @@
"oldfieldname": "item_group",
"oldfieldtype": "Link",
"options": "Item Group",
"read_only": 0,
"reqd": 1
},
{
@@ -94,7 +108,8 @@
"oldfieldname": "stock_uom",
"oldfieldtype": "Link",
"options": "UOM",
"reqd": 0
"read_only": 0,
"reqd": 1
},
{
"doctype": "DocField",
@@ -106,25 +121,29 @@
"oldfieldtype": "Link",
"options": "Brand",
"print_hide": 1,
"read_only": 0,
"reqd": 0
},
{
"doctype": "DocField",
"fieldname": "barcode",
"fieldtype": "Data",
"label": "Barcode"
"label": "Barcode",
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "column_break0",
"fieldtype": "Column Break"
"fieldtype": "Column Break",
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "image",
"fieldtype": "Select",
"label": "Image",
"options": "attach_files:"
"options": "attach_files:",
"read_only": 0
},
{
"doctype": "DocField",
@@ -132,7 +151,8 @@
"fieldtype": "Image",
"in_list_view": 1,
"label": "Image View",
"options": "image"
"options": "image",
"read_only": 0
},
{
"doctype": "DocField",
@@ -143,6 +163,7 @@
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Text",
"read_only": 0,
"reqd": 1,
"search_index": 0
},
@@ -150,21 +171,24 @@
"doctype": "DocField",
"fieldname": "description_html",
"fieldtype": "Small Text",
"label": "Description HTML"
"label": "Description HTML",
"read_only": 0
},
{
"description": "Generates HTML to include selected image in the description",
"doctype": "DocField",
"fieldname": "add_image",
"fieldtype": "Button",
"label": "Generate Description HTML"
"label": "Generate Description HTML",
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "inventory",
"fieldtype": "Section Break",
"label": "Inventory",
"oldfieldtype": "Section Break"
"oldfieldtype": "Section Break",
"read_only": 0
},
{
"default": "Yes",
@@ -176,6 +200,7 @@
"oldfieldname": "is_stock_item",
"oldfieldtype": "Select",
"options": "\nYes\nNo",
"read_only": 0,
"reqd": 1
},
{
@@ -187,7 +212,8 @@
"label": "Default Reserved Warehouse",
"oldfieldname": "default_warehouse",
"oldfieldtype": "Link",
"options": "Warehouse"
"options": "Warehouse",
"read_only": 0
},
{
"depends_on": "eval:doc.is_stock_item==\"Yes\"",
@@ -197,7 +223,8 @@
"fieldtype": "Float",
"label": "Allowance Percent",
"oldfieldname": "tolerance",
"oldfieldtype": "Currency"
"oldfieldtype": "Currency",
"read_only": 0
},
{
"depends_on": "eval:doc.is_stock_item==\"Yes\"",
@@ -205,7 +232,8 @@
"fieldname": "valuation_method",
"fieldtype": "Select",
"label": "Valuation Method",
"options": "\nFIFO\nMoving Average"
"options": "\nFIFO\nMoving Average",
"read_only": 0
},
{
"default": "0.00",
@@ -217,7 +245,8 @@
"hidden": 0,
"label": "Minimum Order Qty",
"oldfieldname": "min_order_qty",
"oldfieldtype": "Currency"
"oldfieldtype": "Currency",
"read_only": 0
},
{
"depends_on": "eval:doc.is_stock_item==\"Yes\"",
@@ -225,6 +254,7 @@
"fieldname": "column_break1",
"fieldtype": "Column Break",
"oldfieldtype": "Column Break",
"read_only": 0,
"width": "50%"
},
{
@@ -238,6 +268,7 @@
"oldfieldname": "is_asset_item",
"oldfieldtype": "Select",
"options": "\nYes\nNo",
"read_only": 0,
"reqd": 1
},
{
@@ -250,6 +281,7 @@
"oldfieldname": "has_batch_no",
"oldfieldtype": "Select",
"options": "\nYes\nNo",
"read_only": 0,
"reqd": 1
},
{
@@ -264,6 +296,7 @@
"oldfieldname": "has_serial_no",
"oldfieldtype": "Select",
"options": "\nYes\nNo",
"read_only": 0,
"reqd": 1
},
{
@@ -273,7 +306,8 @@
"fieldtype": "Data",
"label": "Warranty Period (in days)",
"oldfieldname": "warranty_period",
"oldfieldtype": "Data"
"oldfieldtype": "Data",
"read_only": 0
},
{
"depends_on": "eval:doc.is_stock_item==\"Yes\"",
@@ -282,7 +316,8 @@
"fieldtype": "Date",
"label": "End of Life",
"oldfieldname": "end_of_life",
"oldfieldtype": "Date"
"oldfieldtype": "Date",
"read_only": 0
},
{
"depends_on": "eval:doc.is_stock_item==\"Yes\"",
@@ -290,7 +325,8 @@
"doctype": "DocField",
"fieldname": "net_weight",
"fieldtype": "Float",
"label": "Net Weight"
"label": "Net Weight",
"read_only": 0
},
{
"depends_on": "eval:doc.is_stock_item==\"Yes\"",
@@ -298,14 +334,16 @@
"fieldname": "weight_uom",
"fieldtype": "Link",
"label": "Weight UOM",
"options": "UOM"
"options": "UOM",
"read_only": 0
},
{
"description": "Auto-raise Material Request if quantity goes below re-order level in a warehouse",
"doctype": "DocField",
"fieldname": "reorder_section",
"fieldtype": "Section Break",
"label": "Re-order"
"label": "Re-order",
"read_only": 0
},
{
"depends_on": "eval:doc.is_stock_item==\"Yes\"",
@@ -314,47 +352,39 @@
"fieldtype": "Float",
"label": "Re-Order Level",
"oldfieldname": "re_order_level",
"oldfieldtype": "Currency"
"oldfieldtype": "Currency",
"read_only": 0
},
{
"depends_on": "eval:doc.is_stock_item==\"Yes\"",
"doctype": "DocField",
"fieldname": "re_order_qty",
"fieldtype": "Float",
"label": "Re-Order Qty"
},
{
"doctype": "DocField",
"fieldname": "column_break_31",
"fieldtype": "Column Break"
},
{
"depends_on": "eval:doc.is_stock_item==\"Yes\"",
"description": "Send an email to users of role \"Material Manager\" and \"Purchase Manager\" when re-order level is crossed.",
"doctype": "DocField",
"fieldname": "email_notify",
"fieldtype": "Check",
"label": "Notify by Email on Re-order"
"label": "Re-Order Qty",
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "section_break_31",
"fieldtype": "Section Break",
"options": "Simple"
"options": "Simple",
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "item_reorder",
"fieldtype": "Table",
"label": "Warehouse-wise Item Reorder",
"options": "Item Reorder"
"options": "Item Reorder",
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "purchase_details",
"fieldtype": "Section Break",
"label": "Purchase Details",
"oldfieldtype": "Section Break"
"oldfieldtype": "Section Break",
"read_only": 0
},
{
"default": "Yes",
@@ -366,6 +396,7 @@
"oldfieldname": "is_purchase_item",
"oldfieldtype": "Select",
"options": "\nYes\nNo",
"read_only": 0,
"reqd": 1
},
{
@@ -377,7 +408,8 @@
"label": "Lead Time Days",
"no_copy": 1,
"oldfieldname": "lead_time_days",
"oldfieldtype": "Int"
"oldfieldtype": "Int",
"read_only": 0
},
{
"depends_on": "eval:doc.is_purchase_item==\"Yes\"",
@@ -388,7 +420,8 @@
"label": "Default Expense Account",
"oldfieldname": "purchase_account",
"oldfieldtype": "Link",
"options": "Account"
"options": "Account",
"read_only": 0
},
{
"depends_on": "eval:doc.is_purchase_item==\"Yes\"",
@@ -399,7 +432,8 @@
"label": "Default Cost Center",
"oldfieldname": "cost_center",
"oldfieldtype": "Link",
"options": "Cost Center"
"options": "Cost Center",
"read_only": 0
},
{
"depends_on": "eval:doc.is_purchase_item==\"Yes\"",
@@ -419,7 +453,8 @@
"fieldtype": "Float",
"label": "Standard Rate",
"oldfieldname": "standard_rate",
"oldfieldtype": "Currency"
"oldfieldtype": "Currency",
"read_only": 0
},
{
"depends_on": "eval:doc.is_purchase_item==\"Yes\"",
@@ -427,6 +462,7 @@
"fieldname": "column_break2",
"fieldtype": "Column Break",
"oldfieldtype": "Column Break",
"read_only": 0,
"width": "50%"
},
{
@@ -438,21 +474,24 @@
"no_copy": 1,
"oldfieldname": "uom_conversion_details",
"oldfieldtype": "Table",
"options": "UOM Conversion Detail"
"options": "UOM Conversion Detail",
"read_only": 0
},
{
"depends_on": "eval:doc.is_purchase_item==\"Yes\"",
"doctype": "DocField",
"fieldname": "manufacturer",
"fieldtype": "Data",
"label": "Manufacturer"
"label": "Manufacturer",
"read_only": 0
},
{
"depends_on": "eval:doc.is_purchase_item==\"Yes\"",
"doctype": "DocField",
"fieldname": "manufacturer_part_no",
"fieldtype": "Data",
"label": "Manufacturer Part Number"
"label": "Manufacturer Part Number",
"read_only": 0
},
{
"depends_on": "eval:doc.is_purchase_item==\"Yes\"",
@@ -460,14 +499,16 @@
"fieldname": "item_supplier_details",
"fieldtype": "Table",
"label": "Item Supplier Details",
"options": "Item Supplier"
"options": "Item Supplier",
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "sales_details",
"fieldtype": "Section Break",
"label": "Sales Details",
"oldfieldtype": "Section Break"
"oldfieldtype": "Section Break",
"read_only": 0
},
{
"default": "Yes",
@@ -480,6 +521,7 @@
"oldfieldname": "is_sales_item",
"oldfieldtype": "Select",
"options": "\nYes\nNo",
"read_only": 0,
"reqd": 1
},
{
@@ -494,6 +536,7 @@
"oldfieldname": "is_service_item",
"oldfieldtype": "Select",
"options": "\nYes\nNo",
"read_only": 0,
"reqd": 1
},
{
@@ -507,6 +550,7 @@
"oldfieldname": "is_sample_item",
"oldfieldtype": "Select",
"options": "\nYes\nNo",
"read_only": 0,
"reqd": 1
},
{
@@ -516,7 +560,8 @@
"fieldtype": "Float",
"label": "Max Discount (%)",
"oldfieldname": "max_discount",
"oldfieldtype": "Currency"
"oldfieldtype": "Currency",
"read_only": 0
},
{
"depends_on": "eval:doc.is_sales_item==\"Yes\"",
@@ -524,7 +569,8 @@
"fieldname": "default_income_account",
"fieldtype": "Link",
"label": "Default Income Account",
"options": "Account"
"options": "Account",
"read_only": 0
},
{
"depends_on": "eval:doc.is_sales_item==\"Yes\"",
@@ -532,7 +578,8 @@
"fieldname": "default_sales_cost_center",
"fieldtype": "Link",
"label": "Cost Center",
"options": "Cost Center"
"options": "Cost Center",
"read_only": 0
},
{
"depends_on": "eval:doc.is_sales_item==\"Yes\"",
@@ -542,7 +589,8 @@
"hidden": 1,
"label": "Sales Rate",
"oldfieldname": "sales_rate",
"oldfieldtype": "Currency"
"oldfieldtype": "Currency",
"read_only": 0
},
{
"depends_on": "eval:doc.is_sales_item==\"Yes\"",
@@ -550,6 +598,7 @@
"fieldname": "column_break3",
"fieldtype": "Column Break",
"oldfieldtype": "Column Break",
"read_only": 0,
"width": "50%"
},
{
@@ -559,14 +608,16 @@
"fieldname": "item_customer_details",
"fieldtype": "Table",
"label": "Customer Codes",
"options": "Item Customer Detail"
"options": "Item Customer Detail",
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "item_tax_section_break",
"fieldtype": "Section Break",
"label": "Item Tax",
"oldfieldtype": "Section Break"
"oldfieldtype": "Section Break",
"read_only": 0
},
{
"doctype": "DocField",
@@ -575,13 +626,15 @@
"label": "Item Tax1",
"oldfieldname": "item_tax",
"oldfieldtype": "Table",
"options": "Item Tax"
"options": "Item Tax",
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "price_list_section",
"fieldtype": "Section Break",
"label": "Price Lists and Rates"
"label": "Price Lists and Rates",
"read_only": 0
},
{
"description": "Create a price list from Price List master and enter standard ref rates against each of them. On selection of a price list in Quotation, Sales Order or Delivery Note, corresponding ref rate will be fetched for this item.",
@@ -591,14 +644,16 @@
"label": "Item Prices",
"oldfieldname": "ref_rate_details",
"oldfieldtype": "Table",
"options": "Item Price"
"options": "Item Price",
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "inspection_criteria",
"fieldtype": "Section Break",
"label": "Inspection Criteria",
"oldfieldtype": "Section Break"
"oldfieldtype": "Section Break",
"read_only": 0
},
{
"default": "No",
@@ -610,6 +665,7 @@
"oldfieldname": "inspection_required",
"oldfieldtype": "Select",
"options": "\nYes\nNo",
"read_only": 0,
"reqd": 1
},
{
@@ -621,14 +677,16 @@
"label": "Item Quality Inspection Parameter",
"oldfieldname": "item_specification_details",
"oldfieldtype": "Table",
"options": "Item Quality Inspection Parameter"
"options": "Item Quality Inspection Parameter",
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "manufacturing",
"fieldtype": "Section Break",
"label": "Manufacturing",
"oldfieldtype": "Section Break"
"oldfieldtype": "Section Break",
"read_only": 0
},
{
"default": "No",
@@ -640,6 +698,7 @@
"oldfieldname": "is_manufactured_item",
"oldfieldtype": "Select",
"options": "\nYes\nNo",
"read_only": 0,
"reqd": 1
},
{
@@ -665,6 +724,7 @@
"oldfieldname": "is_pro_applicable",
"oldfieldtype": "Select",
"options": "\nYes\nNo",
"read_only": 0,
"reqd": 1
},
{
@@ -677,17 +737,9 @@
"oldfieldname": "is_sub_contracted_item",
"oldfieldtype": "Select",
"options": "\nYes\nNo",
"read_only": 0,
"reqd": 1
},
{
"doctype": "DocField",
"fieldname": "file_list",
"fieldtype": "Text",
"hidden": 1,
"label": "File List",
"no_copy": 1,
"print_hide": 1
},
{
"doctype": "DocField",
"fieldname": "customer_code",
@@ -696,19 +748,22 @@
"in_filter": 1,
"label": "Customer Code",
"no_copy": 1,
"print_hide": 1
"print_hide": 1,
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "website_section",
"fieldtype": "Section Break",
"label": "Website"
"label": "Website",
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "show_in_website",
"fieldtype": "Check",
"label": "Show in Website"
"label": "Show in Website",
"read_only": 0
},
{
"depends_on": "show_in_website",
@@ -726,6 +781,7 @@
"fieldname": "weightage",
"fieldtype": "Int",
"label": "Weightage",
"read_only": 0,
"search_index": 1
},
{
@@ -735,7 +791,8 @@
"fieldname": "slideshow",
"fieldtype": "Link",
"label": "Slideshow",
"options": "Website Slideshow"
"options": "Website Slideshow",
"read_only": 0
},
{
"depends_on": "show_in_website",
@@ -744,12 +801,14 @@
"fieldname": "website_image",
"fieldtype": "Select",
"label": "Image",
"options": "attach_files:"
"options": "attach_files:",
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "cb72",
"fieldtype": "Column Break"
"fieldtype": "Column Break",
"read_only": 0
},
{
"depends_on": "show_in_website",
@@ -758,7 +817,8 @@
"fieldname": "website_price_list",
"fieldtype": "Link",
"label": "Website Price List",
"options": "Price List"
"options": "Price List",
"read_only": 0
},
{
"depends_on": "show_in_website",
@@ -767,7 +827,8 @@
"fieldname": "website_warehouse",
"fieldtype": "Link",
"label": "Website Warehouse",
"options": "Warehouse"
"options": "Warehouse",
"read_only": 0
},
{
"depends_on": "show_in_website",
@@ -776,19 +837,22 @@
"fieldname": "website_item_groups",
"fieldtype": "Table",
"label": "Website Item Groups",
"options": "Website Item Group"
"options": "Website Item Group",
"read_only": 0
},
{
"depends_on": "show_in_website",
"doctype": "DocField",
"fieldname": "sb72",
"fieldtype": "Section Break"
"fieldtype": "Section Break",
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "copy_from_item_group",
"fieldtype": "Button",
"label": "Copy From Item Group"
"label": "Copy From Item Group",
"read_only": 0
},
{
"depends_on": "show_in_website",
@@ -796,37 +860,21 @@
"fieldname": "item_website_specifications",
"fieldtype": "Table",
"label": "Item Website Specifications",
"options": "Item Website Specification"
"options": "Item Website Specification",
"read_only": 0
},
{
"depends_on": "show_in_website",
"doctype": "DocField",
"fieldname": "web_long_description",
"fieldtype": "Text Editor",
"label": "Website Description"
"label": "Website Description",
"read_only": 0
},
{
"cancel": 1,
"create": 1,
"doctype": "DocPerm",
"permlevel": 0,
"role": "System Manager",
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"permlevel": 1,
"role": "Material Master Manager",
"write": 0
},
{
"cancel": 1,
"create": 1,
"doctype": "DocPerm",
"permlevel": 0,
"role": "Material Master Manager",
"write": 1
},
@@ -835,15 +883,6 @@
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"permlevel": 1,
"role": "System Manager"
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"permlevel": 1,
"role": "Material Manager",
"write": 0
},
@@ -852,25 +891,6 @@
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"permlevel": 0,
"role": "Material Manager",
"write": 0
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"permlevel": 1,
"role": "Material User",
"write": 0
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"permlevel": 0,
"role": "Material User",
"write": 0
}

View File

@@ -20,6 +20,22 @@ import webnotes
test_ignore = ["BOM"]
class TestItem(unittest.TestCase):
def test_duplicate_price_list(self):
item = webnotes.bean(copy=test_records[0])
item.doc.item_code = "_Test Item 10"
item_price = item.doclist.get({"doctype": "Item Price"})[0]
item.doclist.append(webnotes.doc(item_price.fields.copy()))
self.assertRaises(webnotes.DuplicateEntryError, item.insert)
def test_price_list_mismatch(self):
from stock.doctype.item.item import PriceListCurrencyMismatch
item = webnotes.bean(copy=test_records[0])
item.doc.item_code = "_Test Item 11"
item_price = item.doclist.get({"doctype": "Item Price"})[0].ref_currency="USD"
self.assertRaises(PriceListCurrencyMismatch, item.insert)
test_records = [
[{
"doctype": "Item",
@@ -45,7 +61,14 @@ test_records = [
"warehouse": "_Test Warehouse",
"warehouse_reorder_level": 20,
"warehouse_reorder_qty": 20
}],
}, {
"doctype": "Item Price",
"parentfield": "ref_rate_details",
"price_list_name": "_Test Price List",
"ref_rate": 100,
"ref_currency": "INR"
}
],
[{
"doctype": "Item",
"item_code": "_Test Item Home Desktop 100",

View File

@@ -1,8 +1,8 @@
[
{
"creation": "2013-03-08 15:37:16",
"creation": "2013-04-29 15:18:04",
"docstatus": 0,
"modified": "2013-03-21 17:29:15",
"modified": "2013-04-29 19:16:45",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -68,13 +68,13 @@
"doctype": "DocField",
"fieldname": "selling",
"fieldtype": "Check",
"label": "For Selling"
"label": "Valid For Selling"
},
{
"description": "Allow this price in purchase related forms",
"doctype": "DocField",
"fieldname": "buying",
"fieldtype": "Check",
"label": "For Buying"
"label": "Valid For Buying"
}
]

View File

@@ -1,6 +1,6 @@
[
{
"creation": "2013-02-21 14:15:25",
"creation": "2013-03-07 14:48:38",
"docstatus": 0,
"modified": "2013-02-25 15:38:02",
"modified_by": "Administrator",
@@ -331,15 +331,6 @@
"options": "Print Heading",
"print_hide": 1
},
{
"doctype": "DocField",
"fieldname": "file_list",
"fieldtype": "Text",
"hidden": 1,
"label": "File List",
"no_copy": 1,
"print_hide": 1
},
{
"amend": 0,
"cancel": 0,

View File

@@ -263,6 +263,12 @@ class TestMaterialRequest(unittest.TestCase):
se = webnotes.bean(copy=se_doclist)
self.assertRaises(webnotes.MappingMismatchError, se.insert)
def test_warehouse_company_validation(self):
from controllers.buying_controller import WrongWarehouseCompany
mr = webnotes.bean(copy=test_records[0])
mr.doc.company = "_Test Company 1"
self.assertRaises(WrongWarehouseCompany, mr.insert)
test_records = [
[
{

View File

@@ -1,6 +1,6 @@
[
{
"creation": "2013-01-22 15:24:18",
"creation": "2013-03-25 16:01:29",
"docstatus": 0,
"modified": "2013-02-02 19:09:37",
"modified_by": "Administrator",
@@ -31,9 +31,7 @@
"parent": "Purchase Receipt",
"parentfield": "permissions",
"parenttype": "DocType",
"permlevel": 0,
"read": 1,
"report": 1
"read": 1
},
{
"doctype": "DocType",
@@ -886,44 +884,78 @@
"read_only": 1
},
{
"doctype": "DocField",
"fieldname": "file_list",
"fieldtype": "Text",
"hidden": 1,
"label": "File List",
"no_copy": 1,
"print_hide": 1
},
{
"amend": 1,
"cancel": 1,
"create": 1,
"doctype": "DocPerm",
"role": "Purchase User",
"submit": 1,
"write": 1
},
{
"doctype": "DocPerm",
"match": "supplier",
"role": "Supplier"
"amend": 0,
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"match": "",
"permlevel": 1,
"report": 0,
"role": "Material Manager",
"submit": 0,
"write": 0
},
{
"amend": 1,
"cancel": 1,
"create": 1,
"doctype": "DocPerm",
"permlevel": 0,
"report": 1,
"role": "Material Manager",
"submit": 1,
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"match": "",
"permlevel": 1,
"report": 0,
"role": "Material User",
"submit": 0,
"write": 0
},
{
"amend": 1,
"cancel": 1,
"create": 1,
"doctype": "DocPerm",
"permlevel": 0,
"report": 1,
"role": "Material User",
"submit": 1,
"write": 1
},
{
"amend": 1,
"cancel": 1,
"create": 1,
"doctype": "DocPerm",
"match": "",
"permlevel": 0,
"report": 1,
"role": "Purchase User",
"submit": 1,
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"match": "",
"permlevel": 1,
"role": "Purchase User",
"submit": 0
},
{
"doctype": "DocPerm",
"match": "supplier",
"permlevel": 0,
"report": 1,
"role": "Supplier"
}
]

View File

@@ -1,8 +1,8 @@
[
{
"creation": "2013-02-22 01:28:03",
"creation": "2013-03-07 11:42:59",
"docstatus": 0,
"modified": "2013-03-07 07:03:28",
"modified": "2013-05-22 12:01:08",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -35,6 +35,7 @@
"oldfieldtype": "Link",
"options": "Item",
"print_width": "100px",
"read_only": 0,
"reqd": 1,
"search_index": 1,
"width": "100px"
@@ -48,6 +49,7 @@
"oldfieldname": "item_name",
"oldfieldtype": "Data",
"print_hide": 1,
"read_only": 0,
"reqd": 1,
"search_index": 0
},
@@ -59,6 +61,7 @@
"oldfieldname": "description",
"oldfieldtype": "Text",
"print_width": "300px",
"read_only": 0,
"reqd": 1,
"width": "300px"
},
@@ -72,6 +75,7 @@
"oldfieldtype": "Currency",
"print_hide": 1,
"print_width": "100px",
"read_only": 0,
"reqd": 1,
"width": "100px"
},
@@ -84,6 +88,7 @@
"oldfieldname": "qty",
"oldfieldtype": "Currency",
"print_width": "100px",
"read_only": 0,
"width": "100px"
},
{
@@ -97,6 +102,7 @@
"oldfieldtype": "Currency",
"print_hide": 1,
"print_width": "100px",
"read_only": 0,
"search_index": 0,
"width": "100px"
},
@@ -110,6 +116,7 @@
"options": "UOM",
"print_hide": 1,
"print_width": "100px",
"read_only": 0,
"reqd": 1,
"width": "100px"
},
@@ -119,14 +126,16 @@
"fieldtype": "Currency",
"label": "Ref Rate ",
"options": "currency",
"print_hide": 1
"print_hide": 1,
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "discount_rate",
"fieldtype": "Float",
"label": "Discount %",
"print_hide": 1
"print_hide": 1,
"read_only": 0
},
{
"default": "0.00",
@@ -139,6 +148,7 @@
"options": "currency",
"print_hide": 0,
"print_width": "100px",
"read_only": 0,
"width": "100px"
},
{
@@ -157,7 +167,8 @@
"fieldtype": "Currency",
"label": "Ref Rate*",
"options": "Company:company:default_currency",
"print_hide": 1
"print_hide": 1,
"read_only": 0
},
{
"default": "0.00",
@@ -170,6 +181,7 @@
"options": "Company:company:default_currency",
"print_hide": 1,
"print_width": "100px",
"read_only": 0,
"reqd": 1,
"width": "100px"
},
@@ -184,6 +196,7 @@
"options": "Company:company:default_currency",
"print_hide": 1,
"print_width": "100px",
"read_only": 0,
"reqd": 0,
"width": "100px"
},
@@ -198,6 +211,7 @@
"options": "Warehouse",
"print_hide": 1,
"print_width": "100px",
"read_only": 0,
"width": "100px"
},
{
@@ -209,6 +223,7 @@
"oldfieldtype": "Currency",
"print_hide": 1,
"print_width": "100px",
"read_only": 0,
"reqd": 1,
"width": "100px"
},
@@ -235,6 +250,7 @@
"oldfieldname": "serial_no",
"oldfieldtype": "Text",
"print_hide": 0,
"read_only": 0,
"report_hide": 0
},
{
@@ -242,7 +258,8 @@
"fieldname": "rejected_serial_no",
"fieldtype": "Text",
"label": "Rejected Serial No",
"print_hide": 1
"print_hide": 1,
"read_only": 0
},
{
"doctype": "DocField",
@@ -252,7 +269,8 @@
"oldfieldname": "batch_no",
"oldfieldtype": "Link",
"options": "Batch",
"print_hide": 1
"print_hide": 1,
"read_only": 0
},
{
"doctype": "DocField",
@@ -278,6 +296,7 @@
"oldfieldname": "schedule_date",
"oldfieldtype": "Date",
"print_hide": 1,
"read_only": 0,
"report_hide": 0,
"reqd": 0
},
@@ -288,7 +307,8 @@
"in_filter": 1,
"label": "Project Name",
"options": "Project",
"print_hide": 1
"print_hide": 1,
"read_only": 0
},
{
"doctype": "DocField",
@@ -299,7 +319,8 @@
"oldfieldname": "qa_no",
"oldfieldtype": "Link",
"options": "Quality Inspection",
"print_hide": 1
"print_hide": 1,
"read_only": 0
},
{
"doctype": "DocField",
@@ -336,6 +357,7 @@
"oldfieldtype": "Currency",
"print_hide": 1,
"print_width": "100px",
"read_only": 0,
"width": "100px"
},
{
@@ -344,9 +366,11 @@
"fieldtype": "Data",
"hidden": 1,
"label": "Prevdoc Doctype",
"no_copy": 1,
"oldfieldname": "prevdoc_doctype",
"oldfieldtype": "Data",
"print_hide": 1
"print_hide": 1,
"read_only": 0
},
{
"doctype": "DocField",
@@ -355,7 +379,7 @@
"hidden": 0,
"in_filter": 1,
"label": "PO No",
"no_copy": 0,
"no_copy": 1,
"oldfieldname": "prevdoc_docname",
"oldfieldtype": "Link",
"options": "Purchase Order",
@@ -373,6 +397,7 @@
"hidden": 1,
"in_filter": 1,
"label": "PO Date",
"no_copy": 1,
"oldfieldname": "prevdoc_date",
"oldfieldtype": "Date",
"print_hide": 1,
@@ -418,7 +443,7 @@
"hidden": 1,
"in_filter": 1,
"label": "Purchase Order Item No",
"no_copy": 0,
"no_copy": 1,
"oldfieldname": "prevdoc_detail_docname",
"oldfieldtype": "Data",
"print_hide": 1,
@@ -479,6 +504,7 @@
"label": "Page Break",
"oldfieldname": "page_break",
"oldfieldtype": "Check",
"print_hide": 1
"print_hide": 1,
"read_only": 0
}
]

View File

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

View File

@@ -1,11 +0,0 @@
[
"Package Items",
"Sales BOM Items",
"Aggregate group of **Items** into another **Item**. This is useful if you are bundling a certain **Items** into a package and you maintain stock of the packed **Items** and not the aggregate **Item**. \n\nThe package **Item** will have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\".\n\nFor Example: If you are selling Laptops and Backpacks separately and have a special price if the customer buys both, then the Laptop + Backpack will be a new Sales BOM Item.\n\nNote: BOM = Bill of Materials",
"List items that form the package.",
"The Item that represents the Package. This Item must have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\"",
"Sales BOM Item",
"Sales BOM",
"Parent Item",
"Stock"
]

View File

@@ -1,11 +0,0 @@
{
"Aggregate group of **Items** into another **Item**. This is useful if you are bundling a certain **Items** into a package and you maintain stock of the packed **Items** and not the aggregate **Item**. The package **Item** will have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\".For Example: If you are selling Laptops and Backpacks separately and have a special price if the customer buys both, then the Laptop + Backpack will be a new Sales BOM Item.Note: BOM = Bill of Materials": "\u0625\u062c\u0645\u0627\u0644\u064a \u0645\u062c\u0645\u0648\u0639\u0629 \u0645\u0646 \u0627\u0644\u0639\u0646\u0627\u0635\u0631 ** ** ** \u0641\u064a \u0628\u0646\u062f \u0622\u062e\u0631. ** \u0647\u0630\u0627 \u0645\u0641\u064a\u062f \u0625\u0630\u0627 \u0643\u0646\u062a \u062a\u062c\u0645\u064a\u0639 \u0639\u0646\u0627\u0635\u0631 \u0645\u0639\u064a\u0646\u0629 ** ** \u0641\u064a \u062d\u0632\u0645\u0629 \u0648\u064a\u0645\u0643\u0646\u0643 \u0627\u0644\u062d\u0641\u0627\u0638 \u0639\u0644\u0649 \u0627\u0644\u0645\u062e\u0632\u0648\u0646 \u0645\u0646 \u0627\u0644\u0623\u0635\u0646\u0627\u0641 ** ** \u0645\u0639\u0628\u0623\u0629 \u0648\u0644\u064a\u0633 \u0627\u0644\u0643\u0644\u064a ** \u0627\u0644\u0633\u0644\u0639\u0629 **. \u0627\u0644\u062d\u0632\u0645\u0629 \u0627\u0644\u0633\u0644\u0639\u0629 ** ** \u0633\u064a\u0643\u0648\u0646 &quot;\u0647\u0648 \u0627\u0644\u0645\u062e\u0632\u0648\u0646 \u0627\u0644\u0633\u0644\u0639\u0629&quot; \u0628 &quot;\u0644\u0627&quot; \u0648 &quot;\u0647\u0644 \u0627\u0644\u0645\u0628\u064a\u0639\u0627\u062a \u0627\u0644\u0633\u0644\u0639\u0629&quot; \u0628 &quot;\u0646\u0639\u0645&quot; \u0639\u0644\u0649 \u0633\u0628\u064a\u0644 \u0627\u0644\u0645\u062b\u0627\u0644: \u0625\u0630\u0627 \u0643\u0646\u062a \u062a\u0628\u064a\u0639 \u0623\u062c\u0647\u0632\u0629 \u0627\u0644\u0643\u0645\u0628\u064a\u0648\u062a\u0631 \u0627\u0644\u0645\u062d\u0645\u0648\u0644\u0629 \u0648\u062d\u0642\u0627\u0626\u0628 \u062a\u062d\u0645\u0644 \u0639\u0644\u0649 \u0627\u0644\u0638\u0647\u0631 \u0628\u0634\u0643\u0644 \u0645\u0646\u0641\u0635\u0644 \u0648\u0644\u0647\u0627 \u0633\u0639\u0631 \u062e\u0627\u0635 \u0627\u0630\u0627 \u0643\u0627\u0646 \u0627\u0644\u0632\u0628\u0648\u0646 \u064a\u0634\u062a\u0631\u064a \u0643\u0644 \u060c \u062b\u0645 \u0633\u064a\u0642\u0648\u0645 \u0627\u0644\u0643\u0645\u0628\u064a\u0648\u062a\u0631 \u0627\u0644\u0645\u062d\u0645\u0648\u0644 + \u062d\u0642\u064a\u0628\u0629 \u0627\u0644\u0638\u0647\u0631 \u062a\u0643\u0648\u0646 \u062c\u062f\u064a\u062f\u0629 \u0627\u0644\u0645\u0628\u064a\u0639\u0627\u062a BOM Item.Note: BOM = \u0628\u064a\u0644 \u0627\u0644\u0645\u0648\u0627\u062f",
"List items that form the package.": "\u0639\u0646\u0627\u0635\u0631 \u0627\u0644\u0642\u0627\u0626\u0645\u0629 \u0627\u0644\u062a\u064a \u062a\u0634\u0643\u0644 \u0627\u0644\u062d\u0632\u0645\u0629.",
"Package Items": "\u062d\u0632\u0645\u0629 \u0627\u0644\u0628\u0646\u0648\u062f",
"Parent Item": "\u0627\u0644\u0623\u0645 \u0627\u0644\u0645\u062f\u064a\u0646\u0629",
"Sales BOM": "\u0645\u0628\u064a\u0639\u0627\u062a BOM",
"Sales BOM Item": "\u0645\u0628\u064a\u0639\u0627\u062a \u0627\u0644\u0633\u0644\u0639\u0629 BOM",
"Sales BOM Items": "\u0639\u0646\u0627\u0635\u0631 \u0645\u0628\u064a\u0639\u0627\u062a BOM",
"Stock": "\u0627\u0644\u0623\u0648\u0631\u0627\u0642 \u0627\u0644\u0645\u0627\u0644\u064a\u0629",
"The Item that represents the Package. This Item must have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\"": "\u0627\u0644\u0639\u0646\u0635\u0631 \u0627\u0644\u0630\u064a \u064a\u0645\u062b\u0644 \u0627\u0644\u062d\u0632\u0645\u0629. \u064a\u062c\u0628 \u0623\u0646 \u064a\u0643\u0648\u0646 \u0644\u062f\u0649 \u0647\u0630\u0627 \u0627\u0644\u0628\u0646\u062f &quot;\u0647\u0648 \u0627\u0644\u0645\u062e\u0632\u0648\u0646 \u0627\u0644\u0633\u0644\u0639\u0629&quot; \u0628 &quot;\u0644\u0627&quot; \u0648 &quot;\u0647\u0644 \u0627\u0644\u0645\u0628\u064a\u0639\u0627\u062a \u0627\u0644\u0633\u0644\u0639\u0629&quot; \u0628 &quot;\u0646\u0639\u0645&quot;"
}

View File

@@ -1,10 +0,0 @@
{
"List items that form the package.": "Diese Liste Artikel bilden das Paket.",
"Package Items": "Package Angebote",
"Parent Item": "\u00dcbergeordneter Artikel",
"Sales BOM": "Vertrieb BOM",
"Sales BOM Item": "Vertrieb St\u00fccklistenposition",
"Sales BOM Items": "Vertrieb St\u00fccklistenpositionen",
"Stock": "Lager",
"The Item that represents the Package. This Item must have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\"": "Das Element, das das Paket darstellt. Dieser Artikel muss \"Ist Stock Item\" als \"Nein\" und \"Ist Vertrieb Item\" als \"Ja\""
}

View File

@@ -1,11 +0,0 @@
{
"Aggregate group of **Items** into another **Item**. This is useful if you are bundling a certain **Items** into a package and you maintain stock of the packed **Items** and not the aggregate **Item**. The package **Item** will have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\".For Example: If you are selling Laptops and Backpacks separately and have a special price if the customer buys both, then the Laptop + Backpack will be a new Sales BOM Item.Note: BOM = Bill of Materials": "Grupo global de productos ** ** en otro art\u00edculo **. ** Esto es \u00fatil si usted est\u00e1 empaquetando un cierto ** ** Los productos en un paquete y usted mantiene un balance de los art\u00edculos envasados \u200b\u200b** ** y no el agregado del art\u00edculo **. ** El paquete ** art\u00edculo ** habr\u00e1 &quot;es el tema de&quot; como &quot;No&quot; y &quot;\u00bfSales Item&quot; como &quot;S\u00ed&quot;, por ejemplo:. Si usted est\u00e1 vendiendo computadoras port\u00e1tiles y Mochilas por separado y recibir un descuento si el cliente compra a la vez , entonces el ordenador port\u00e1til + Mochila ser\u00e1 una nueva lista de materiales de ventas Item.Note: BOM = Bill de Materiales",
"List items that form the package.": "Lista de tareas que forman el paquete.",
"Package Items": "Art\u00edculos del embalaje",
"Parent Item": "Art\u00edculo principal",
"Sales BOM": "Ventas BOM",
"Sales BOM Item": "Ventas de art\u00edculo de lista de materiales",
"Sales BOM Items": "Los productos que la lista de materiales de ventas",
"Stock": "Valores",
"The Item that represents the Package. This Item must have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\"": "El punto que representa el paquete. Este elemento debe tener &quot;es el tema de&quot; como &quot;No&quot; y &quot;\u00bfSales Item&quot; como &quot;S\u00ed&quot;"
}

View File

@@ -1,11 +0,0 @@
{
"Aggregate group of **Items** into another **Item**. This is useful if you are bundling a certain **Items** into a package and you maintain stock of the packed **Items** and not the aggregate **Item**. The package **Item** will have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\".For Example: If you are selling Laptops and Backpacks separately and have a special price if the customer buys both, then the Laptop + Backpack will be a new Sales BOM Item.Note: BOM = Bill of Materials": "Groupe global de ** ** Articles dans un autre article **. ** Ceci est utile si vous mettez en place un certains articles ** ** dans un paquet et vous maintenir le stock des articles emball\u00e9s ** ** et non pas le total ** Article **. Le paquet ** ** Point aura \u00abEst Produit en stock&quot; comme &quot;No&quot; et &quot;Est Point de vente&quot; que &quot;Oui&quot; Par exemple:. Si vous vendez des ordinateurs portables et sacs \u00e0 dos s\u00e9par\u00e9ment et un prix sp\u00e9cial si le client ach\u00e8te \u00e0 la fois , puis l&#39;ordinateur portable Sac \u00e0 dos + sera une nouvelle nomenclature des ventes Item.Note: BOM = Bill of Materials",
"List items that form the package.": "Liste des articles qui composent le paquet.",
"Package Items": "Articles paquet",
"Parent Item": "Article Parent",
"Sales BOM": "BOM ventes",
"Sales BOM Item": "Article nomenclature des ventes",
"Sales BOM Items": "Articles ventes de nomenclature",
"Stock": "Stock",
"The Item that represents the Package. This Item must have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\"": "L&#39;article qui repr\u00e9sente le package. Cet article doit avoir \u00abEst Produit en stock&quot; comme &quot;No&quot; et &quot;Est Point de vente&quot; que &quot;Oui&quot;"
}

View File

@@ -1,11 +0,0 @@
{
"Aggregate group of **Items** into another **Item**. This is useful if you are bundling a certain **Items** into a package and you maintain stock of the packed **Items** and not the aggregate **Item**. The package **Item** will have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\".For Example: If you are selling Laptops and Backpacks separately and have a special price if the customer buys both, then the Laptop + Backpack will be a new Sales BOM Item.Note: BOM = Bill of Materials": "** \u0906\u0907\u091f\u092e \u0915\u0947 \u0938\u0915\u0932 \u0938\u092e\u0942\u0939 \u092e\u0947\u0902 \u090f\u0915 \u0914\u0930 \u0906\u0907\u091f\u092e ** **. \u092f\u0939 \u0909\u092a\u092f\u094b\u0917\u0940 \u0939\u0948 \u0905\u0917\u0930 \u0906\u092a \u090f\u0915 \u092a\u0948\u0915\u0947\u091c \u092e\u0947\u0902 ** \u0915\u0941\u091b ** \u0906\u0907\u091f\u092e bundling \u0939\u0948\u0902 \u0914\u0930 \u0906\u092a \u092a\u0948\u0915 ** \u0914\u0930 \u0928\u0939\u0940\u0902 \u0915\u0941\u0932 ** \u0906\u0907\u091f\u092e ** ** \u0906\u0907\u091f\u092e \u0915\u0947 \u0938\u094d\u091f\u0949\u0915 \u0915\u094b \u092c\u0928\u093e\u090f \u0930\u0916\u0928\u0947. \u092a\u0948\u0915\u0947\u091c ** \u0906\u0907\u091f\u092e ** \u0939\u0948 &quot;\u0938\u094d\u091f\u0949\u0915 \u0906\u0907\u091f\u092e \u0939\u0948&quot; &quot;\u0928\u0939\u0940\u0902&quot; \u0915\u0947 \u0930\u0942\u092a \u092e\u0947\u0902 \u0914\u0930 \u0915\u0947 \u0930\u0942\u092a \u092e\u0947\u0902 &quot;\u0939\u093e\u0901&quot; &quot;\u092c\u093f\u0915\u094d\u0930\u0940 \u0906\u0907\u091f\u092e \u0939\u0948,&quot; \u0909\u0926\u093e\u0939\u0930\u0923 \u0915\u0947 \u0932\u093f\u090f: \u092f\u0926\u093f \u0906\u092a \u0932\u0948\u092a\u091f\u0949\u092a \u0914\u0930 Backpacks \u092c\u0947\u091a \u0930\u0939\u0947 \u0939\u0948\u0902 \u0914\u0930 \u0905\u0932\u0917 \u0938\u0947 \u090f\u0915 \u0935\u093f\u0936\u0947\u0937 \u092e\u0942\u0932\u094d\u092f \u0939\u0948 \u0905\u0917\u0930 \u0917\u094d\u0930\u093e\u0939\u0915 \u0926\u094b\u0928\u094b\u0902 \u0916\u0930\u0940\u0926\u0924\u093e BOM = \u0935\u093f\u0927\u0947\u092f\u0915 \u0915\u0940 \u0938\u093e\u092e\u0917\u094d\u0930\u0940:, \u0924\u094b \u090f\u0915 \u0928\u092f\u093e \u0932\u0948\u092a\u091f\u0949\u092a + \u092c\u0948\u0917 \u092c\u093f\u0915\u094d\u0930\u0940 \u092c\u0940\u0913\u090f\u092e Item.Note \u0939\u094b\u0917\u093e",
"List items that form the package.": "\u0938\u0942\u091a\u0940 \u0906\u0907\u091f\u092e \u0939\u0948 \u0915\u093f \u092a\u0948\u0915\u0947\u091c \u0915\u093e \u092b\u093e\u0930\u094d\u092e.",
"Package Items": "\u092a\u0948\u0915\u0947\u091c \u0906\u0907\u091f\u092e",
"Parent Item": "\u092e\u0942\u0932 \u0906\u0907\u091f\u092e",
"Sales BOM": "\u092c\u093f\u0915\u094d\u0930\u0940 \u092c\u0940\u0913\u090f\u092e",
"Sales BOM Item": "\u092c\u093f\u0915\u094d\u0930\u0940 \u092c\u0940\u0913\u090f\u092e \u0906\u0907\u091f\u092e",
"Sales BOM Items": "\u092c\u093f\u0915\u094d\u0930\u0940 \u092c\u0940\u0913\u090f\u092e \u0906\u0907\u091f\u092e",
"Stock": "\u0938\u094d\u091f\u0949\u0915",
"The Item that represents the Package. This Item must have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\"": "\u0906\u0907\u091f\u092e \u0939\u0948 \u0915\u093f \u092a\u0948\u0915\u0947\u091c \u0915\u093e \u092a\u094d\u0930\u0924\u093f\u0928\u093f\u0927\u093f\u0924\u094d\u0935 \u0915\u0930\u0924\u093e \u0939\u0948. \u0907\u0938 \u092e\u0926 &quot;\u0938\u094d\u091f\u0949\u0915 \u0906\u0907\u091f\u092e&quot; &quot;\u0928\u0939\u0940\u0902&quot; \u0915\u0947 \u0930\u0942\u092a \u092e\u0947\u0902 \u0914\u0930 \u0915\u0947 \u0930\u0942\u092a \u092e\u0947\u0902 &quot;\u0939\u093e\u0901&quot; &quot;\u092c\u093f\u0915\u094d\u0930\u0940 \u0906\u0907\u091f\u092e \u0939\u0948&quot;"
}

View File

@@ -1,11 +0,0 @@
{
"Aggregate group of **Items** into another **Item**. This is useful if you are bundling a certain **Items** into a package and you maintain stock of the packed **Items** and not the aggregate **Item**. The package **Item** will have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\".For Example: If you are selling Laptops and Backpacks separately and have a special price if the customer buys both, then the Laptop + Backpack will be a new Sales BOM Item.Note: BOM = Bill of Materials": "Agregat skupina ** stavki ** u drugoj to\u010dki ** **. To je korisno ako ste vezanje odre\u0111ene artikle ** ** u paketu i odr\u017eavanje zalihe pakiran ** stavki ** a ne agregata ** artikla **. Paket ** artikla ** \u0107e &quot;Je katalo\u0161ki Stavka&quot; kao &quot;Ne&quot; i &quot;Je li prodaja artikla&quot; kao &quot;Da&quot;, na primjer:. Ako prodajete Prijenosna ra\u010dunala i Ruksaci odvojeno i imaju posebnu cijenu ako kupac kupuje oboje , onda laptop + ruksak \u0107e biti novi Prodaja BOM Item.Note: BOM = Bill materijala",
"List items that form the package.": "Popis stavki koje \u010dine paket.",
"Package Items": "Paket Proizvodi",
"Parent Item": "Roditelj artikla",
"Sales BOM": "Prodaja BOM",
"Sales BOM Item": "Prodaja BOM artikla",
"Sales BOM Items": "Prodaja BOM Proizvodi",
"Stock": "Zaliha",
"The Item that represents the Package. This Item must have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\"": "Stavka koja predstavlja paket. Ova stavka mora imati &quot;Je katalo\u0161ki Stavka&quot; kao &quot;Ne&quot; i &quot;Je li prodaja artikla&quot; kao &quot;Da&quot;"
}

View File

@@ -1,11 +0,0 @@
{
"Aggregate group of **Items** into another **Item**. This is useful if you are bundling a certain **Items** into a package and you maintain stock of the packed **Items** and not the aggregate **Item**. The package **Item** will have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\".For Example: If you are selling Laptops and Backpacks separately and have a special price if the customer buys both, then the Laptop + Backpack will be a new Sales BOM Item.Note: BOM = Bill of Materials": "De totale groep van ** Items ** in een andere ** Item **. Dit is handig als u de bundeling van een bepaalde ** Items ** in een pakket en u onderhoudt voorraad van de verpakte ** Items ** en niet de totale ** Item **. Het pakket ** Item ** zal hebben &quot;Is Stock Item&quot; als &quot;No&quot; en &quot;Is Sales Item&quot; als &quot;Ja&quot; Bijvoorbeeld:. Als je verkoopt laptops en Rugzakken apart en hebben een speciale prijs als de klant koopt zowel , dan is de laptop + Rugzak zal een nieuwe Sales BOM Item.Note: BOM = Bill of Materials",
"List items that form the package.": "Lijst items die het pakket vormen.",
"Package Items": "Pakket Artikelen",
"Parent Item": "Parent Item",
"Sales BOM": "Verkoop BOM",
"Sales BOM Item": "Verkoop BOM Item",
"Sales BOM Items": "Verkoop BOM Items",
"Stock": "Voorraad",
"The Item that represents the Package. This Item must have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\"": "Het item dat het pakket vertegenwoordigt. Dit artikel moet hebben &quot;Is Stock Item&quot; als &quot;No&quot; en &quot;Is Sales Item&quot; als &quot;Yes&quot;"
}

View File

@@ -1,10 +0,0 @@
{
"List items that form the package.": "Lista de itens que comp\u00f5em o pacote.",
"Package Items": "Itens do pacote",
"Parent Item": "Item Pai",
"Sales BOM": "LDM de Vendas",
"Sales BOM Item": "Item da LDM de Vendas",
"Sales BOM Items": "Itens da LDM de Vendas",
"Stock": "Estoque",
"The Item that represents the Package. This Item must have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\"": "O item que representa o pacote. Este item deve ter &quot;\u00c9 Item de Estoque&quot; como &quot;N\u00e3o&quot; e &quot;\u00c9 Item de Venda&quot; como &quot;Sim&quot;"
}

View File

@@ -1,11 +0,0 @@
{
"Aggregate group of **Items** into another **Item**. This is useful if you are bundling a certain **Items** into a package and you maintain stock of the packed **Items** and not the aggregate **Item**. The package **Item** will have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\".For Example: If you are selling Laptops and Backpacks separately and have a special price if the customer buys both, then the Laptop + Backpack will be a new Sales BOM Item.Note: BOM = Bill of Materials": "Grupo agregado de Itens ** ** em outro item **. ** Isso \u00e9 \u00fatil se voc\u00ea est\u00e1 empacotando um certo ** ** Itens em um pacote e voc\u00ea manter o estoque dos itens embalados ** ** e n\u00e3o agregar o item **. ** O pacote ** ** item ter\u00e1 &quot;\u00e9 o item da&quot; como &quot;N\u00e3o&quot; e &quot;\u00e9 o item de vendas&quot; como &quot;Sim&quot;, por exemplo:. Se voc\u00ea est\u00e1 vendendo laptops e mochilas separadamente e t\u00eam um pre\u00e7o especial se o cliente compra tanto , ent\u00e3o o Laptop Backpack + ser\u00e1 uma nova Vendas BOM Item.Note: BOM = Bill of Materials",
"List items that form the package.": "Lista de itens que comp\u00f5em o pacote.",
"Package Items": "Itens do pacote",
"Parent Item": "Item Pai",
"Sales BOM": "BOM vendas",
"Sales BOM Item": "Vendas item BOM",
"Sales BOM Items": "Vendas Itens BOM",
"Stock": "Estoque",
"The Item that represents the Package. This Item must have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\"": "O item que representa o pacote. Este item deve ter &quot;\u00e9 o item da&quot; como &quot;N\u00e3o&quot; e &quot;\u00e9 o item de vendas&quot; como &quot;Sim&quot;"
}

View File

@@ -1,11 +0,0 @@
{
"Aggregate group of **Items** into another **Item**. This is useful if you are bundling a certain **Items** into a package and you maintain stock of the packed **Items** and not the aggregate **Item**. The package **Item** will have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\".For Example: If you are selling Laptops and Backpacks separately and have a special price if the customer buys both, then the Laptop + Backpack will be a new Sales BOM Item.Note: BOM = Bill of Materials": "\u0410\u0433\u0440\u0435\u0433\u0430\u0442 \u0433\u0440\u0443\u043f\u0430 ** ** \u0458\u0435\u0434\u0438\u043d\u0438\u0446\u0435 \u0443 \u0434\u0440\u0443\u0433\u0443 ** ** \u0442\u0430\u0447\u043a\u0435. \u041e\u0432\u043e \u0458\u0435 \u043a\u043e\u0440\u0438\u0441\u043d\u043e \u0430\u043a\u043e \u0441\u0442\u0435 \u0433\u0440\u0443\u043f\u0438\u0441\u0430\u045a\u0435 \u043e\u0434\u0440\u0435\u0452\u0435\u043d\u0435 \u0441\u0442\u0430\u0432\u043a\u0435 ** ** \u0443 \u043f\u0430\u043a\u0435\u0442\u0443 \u0438 \u0434\u0430 \u043e\u0434\u0440\u0436\u0438 \u0437\u0430\u043b\u0438\u0445\u0435 \u0443\u043f\u0430\u043a\u043e\u0432\u0430\u043d\u0438\u0445 ** ** \u0441\u0442\u0430\u0432\u043a\u0438, \u0430 \u043d\u0435 \u0430\u0433\u0440\u0435\u0433\u0430\u0442 ** ** \u0442\u0430\u0447\u043a\u0430. \u041f\u0430\u043a\u0435\u0442 ** ** \u0448\u0438\u0444\u0440\u0430 \u045b\u0435 &quot;\u0414\u0430 \u043b\u0438 \u0458\u0435 \u0431\u0435\u0440\u0437\u0430 \u0421\u0442\u0430\u0432\u043a\u0430&quot; \u043a\u0430\u043e &quot;\u043d\u0435&quot; \u0438 &quot;\u0414\u0430 \u043b\u0438 \u0458\u0435 \u043f\u0440\u043e\u0434\u0430\u0458\u0435 \u0421\u0442\u0430\u0432\u043a\u0430&quot; \u043a\u0430\u043e &quot;\u0414\u0430&quot; \u0417\u0430 \u041f\u0440\u0438\u043c\u0435\u0440: \u0410\u043a\u043e \u0441\u0435 \u043f\u0440\u043e\u0434\u0430\u0458\u0435 \u043b\u0430\u043f\u0442\u043e\u043f \u0438 \u0440\u0430\u043d\u0447\u0435\u0432\u0438 \u043e\u0434\u0432\u043e\u0458\u0435\u043d\u043e \u0438 \u0438\u043c\u0430\u0458\u0443 \u043f\u043e\u0441\u0435\u0431\u043d\u0443 \u0446\u0435\u043d\u0443 \u0443\u043a\u043e\u043b\u0438\u043a\u043e \u043a\u0443\u043f\u0430\u0446 \u043a\u0443\u043f\u0443\u0458\u0435 \u043e\u0431\u043e\u0458\u0435. , \u043e\u043d\u0434\u0430 \u043b\u0430\u043f\u0442\u043e\u043f + \u0420\u0430\u043d\u0430\u0446 \u045b\u0435 \u0431\u0438\u0442\u0438 \u043d\u043e\u0432\u0438 \u041f\u0440\u043e\u0434\u0430\u0458\u0430 \u0411\u041e\u041c \u0418\u0442\u0435\u043c.\u041d\u043e\u0442\u0435: \u0411\u041e\u041c = \u0421\u0430\u0441\u0442\u0430\u0432\u043d\u0438\u0446\u0435",
"List items that form the package.": "\u041b\u0438\u0441\u0442\u0430 \u0441\u0442\u0432\u0430\u0440\u0438 \u043a\u043e\u0458\u0435 \u0447\u0438\u043d\u0435 \u043f\u0430\u043a\u0435\u0442.",
"Package Items": "\u041f\u0430\u043a\u0435\u0442 \u0410\u0440\u0442\u0438\u043a\u043b\u0438",
"Parent Item": "\u0420\u043e\u0434\u0438\u0442\u0435\u0459 \u0448\u0438\u0444\u0440\u0430",
"Sales BOM": "\u041f\u0440\u043e\u0434\u0430\u0458\u0430 \u0411\u041e\u041c",
"Sales BOM Item": "\u041f\u0440\u043e\u0434\u0430\u0458\u0430 \u0411\u041e\u041c \u0448\u0438\u0444\u0440\u0430",
"Sales BOM Items": "\u041f\u0440\u043e\u0434\u0430\u0458\u0430 \u0411\u041e\u041c \u0410\u0440\u0442\u0438\u043a\u043b\u0438",
"Stock": "\u0417\u0430\u043b\u0438\u0445\u0430",
"The Item that represents the Package. This Item must have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\"": "\u0421\u0442\u0430\u0432\u043a\u0430 \u043a\u043e\u0458\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0459\u0430 \u043f\u0430\u043a\u0435\u0442. \u041e\u0432\u0430 \u0442\u0430\u0447\u043a\u0430 \u043c\u043e\u0440\u0430 \u0434\u0430 &quot;\u0417\u0430\u0440 \u0431\u0435\u0440\u0437\u0430 \u0421\u0442\u0430\u0432\u043a\u0430&quot; \u043a\u0430\u043e &quot;\u043d\u0435&quot; \u0438 &quot;\u0414\u0430 \u043b\u0438 \u0458\u0435 \u043f\u0440\u043e\u0434\u0430\u0458\u0435 \u0442\u0430\u0447\u043a\u0430&quot; \u043a\u0430\u043e &quot;\u0414\u0430&quot;"
}

View File

@@ -1,11 +0,0 @@
{
"Aggregate group of **Items** into another **Item**. This is useful if you are bundling a certain **Items** into a package and you maintain stock of the packed **Items** and not the aggregate **Item**. The package **Item** will have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\".For Example: If you are selling Laptops and Backpacks separately and have a special price if the customer buys both, then the Laptop + Backpack will be a new Sales BOM Item.Note: BOM = Bill of Materials": "\u0bae\u0ba4\u0bbf\u0baa\u0bcd\u0baa\u0bc0\u0b9f\u0bcd\u0b9f\u0bc1 ** \u0bb5\u0bbf\u0b9f\u0baf\u0b99\u0bcd\u0b95\u0bb3\u0bcd \u0b95\u0bc1\u0bb4\u0bc1 ** \u0bae\u0bb1\u0bcd\u0bb1\u0bc6\u0bbe\u0bb0\u0bc1 ** \u0baa\u0bc6\u0bbe\u0bb0\u0bc1\u0bb3\u0bcd \u0b95\u0bc6\u0bbe\u0ba3\u0bcd\u0b9f\u0bc1 **. \u0ba8\u0bc0\u0b99\u0bcd\u0b95\u0bb3\u0bcd ** \u0b92\u0bb0\u0bc1 \u0ba4\u0bc6\u0bbe\u0b95\u0bc1\u0baa\u0bcd\u0baa\u0bc1 \u0b92\u0bb0\u0bc1 \u0b95\u0bc1\u0bb1\u0bbf\u0baa\u0bcd\u0baa\u0bbf\u0b9f\u0bcd\u0b9f ** \u0baa\u0bc6\u0bbe\u0bb0\u0bc1\u0b9f\u0bcd\u0b95\u0bb3\u0bc8 \u0b92\u0ba9\u0bcd\u0bb1\u0bc1 \u0b95\u0bc2\u0b9f\u0bcd\u0b9f\u0bc1\u0ba4\u0bb2\u0bcd \u0b87\u0bb0\u0bc1\u0ba8\u0bcd\u0ba4\u0bbe\u0bb2\u0bcd \u0b87\u0ba8\u0bcd\u0ba4 \u0baa\u0baf\u0ba9\u0bc1\u0bb3\u0bcd\u0bb3\u0ba4\u0bbe\u0b95 \u0b87\u0bb0\u0bc1\u0b95\u0bcd\u0b95\u0bc1\u0bae\u0bcd \u0ba8\u0bc0\u0b99\u0bcd\u0b95\u0bb3\u0bcd ** \u0bae\u0bb1\u0bcd\u0bb1\u0bc1\u0bae\u0bcd \u0bae\u0ba4\u0bbf\u0baa\u0bcd\u0baa\u0bc0\u0b9f\u0bcd\u0b9f\u0bc1 ** \u0baa\u0bc6\u0bbe\u0bb0\u0bc1\u0bb3\u0bcd ** \u0baa\u0bc7\u0b95\u0bcd ** \u0baa\u0bc6\u0bbe\u0bb0\u0bc1\u0b9f\u0bcd\u0b95\u0bb3\u0bc8 \u0baa\u0b99\u0bcd\u0b95\u0bc1 \u0bb5\u0bc8\u0ba4\u0bcd\u0ba4\u0bc1. \u0ba4\u0bc6\u0bbe\u0b95\u0bc1\u0baa\u0bcd\u0baa\u0bc1 ** \u0baa\u0bc6\u0bbe\u0bb0\u0bc1\u0bb3\u0bcd ** &quot;\u0b87\u0bb2\u0bcd\u0bb2\u0bc8&quot; \u0b8e\u0ba9 &quot;\u0baa\u0b99\u0bcd\u0b95\u0bc1 \u0b89\u0bb0\u0bc1\u0baa\u0bcd\u0baa\u0b9f\u0bbf \u0b87\u0bb2\u0bcd\u0bb2\u0bc8&quot; \u0bae\u0bb1\u0bcd\u0bb1\u0bc1\u0bae\u0bcd &quot;\u0b86\u0bae\u0bcd&quot; \u0b8e\u0ba9 &quot;\u0bb5\u0bbf\u0bb1\u0bcd\u0baa\u0ba9\u0bc8 \u0baa\u0bc6\u0bbe\u0bb0\u0bc1\u0bb3\u0bbe\u0b95 \u0b89\u0bb3\u0bcd\u0bb3\u0ba4\u0bc1&quot; \u0b89\u0ba4\u0bbe\u0bb0\u0ba3\u0bae\u0bbe\u0b95:. \u0ba8\u0bc0\u0b99\u0bcd\u0b95\u0bb3\u0bcd \u0ba4\u0ba9\u0bbf\u0baf\u0bbe\u0b95 \u0bae\u0b9f\u0bbf\u0b95\u0bcd\u0b95\u0ba3\u0bbf\u0ba9\u0bbf\u0b95\u0bb3\u0bcd \u0bae\u0bb1\u0bcd\u0bb1\u0bc1\u0bae\u0bcd \u0bae\u0bc1\u0ba4\u0bc1\u0b95\u0bbf\u0bb2\u0bcd \u0b9a\u0bc1\u0bae\u0bc8 \u0baa\u0bc8\u0baf\u0bc1\u0b9f\u0ba9\u0bc1\u0bae\u0bcd \u0bb5\u0bbf\u0bb1\u0bcd\u0baa\u0ba9\u0bc8 \u0bae\u0bb1\u0bcd\u0bb1\u0bc1\u0bae\u0bcd \u0b92\u0bb0\u0bc1 \u0b9a\u0bbf\u0bb1\u0baa\u0bcd\u0baa\u0bc1 \u0bb5\u0bbf\u0bb2\u0bc8 \u0b87\u0bb2\u0bcd\u0bb2\u0bc8 \u0b8e\u0ba9\u0bcd\u0bb1\u0bbe\u0bb2\u0bcd \u0bb5\u0bbe\u0b9f\u0bbf\u0b95\u0bcd\u0b95\u0bc8\u0baf\u0bbe\u0bb3\u0bb0\u0bcd \u0b87\u0bb0\u0bc1 \u0bb5\u0bbe\u0b99\u0bcd\u0b95\u0bc1\u0bae\u0bcd \u0baa\u0bc7\u0bbe\u0ba4\u0bc1 \u0baa\u0bc6\u0bbe\u0bb0\u0bc1\u0b9f\u0bcd\u0b95\u0bb3\u0bc8 BOM = \u0baa\u0bbf\u0bb2\u0bcd:, \u0baa\u0bbf\u0ba9\u0bcd\u0ba9\u0bb0\u0bcd \u0bb2\u0bc7\u0baa\u0bcd\u0b9f\u0bbe\u0baa\u0bcd + \u0baa\u0bc8\u0baf\u0bc1\u0b9f\u0ba9\u0bc1\u0bae\u0bcd \u0b92\u0bb0\u0bc1 \u0baa\u0bc1\u0ba4\u0bbf\u0baf \u0bb5\u0bbf\u0bb1\u0bcd\u0baa\u0ba9\u0bc8 BOM Item.Note \u0b87\u0bb0\u0bc1\u0b95\u0bcd\u0b95\u0bc1\u0bae\u0bcd",
"List items that form the package.": "\u0ba4\u0bc6\u0bbe\u0b95\u0bc1\u0baa\u0bcd\u0baa\u0bc1 \u0b85\u0bae\u0bc8\u0b95\u0bcd\u0b95 \u0b8e\u0ba9\u0bcd\u0bb1\u0bc1 \u0baa\u0b9f\u0bcd\u0b9f\u0bbf\u0baf\u0bb2\u0bcd \u0b89\u0bb0\u0bc1\u0baa\u0bcd\u0baa\u0b9f\u0bbf\u0b95\u0bb3\u0bcd.",
"Package Items": "\u0ba4\u0bc6\u0bbe\u0b95\u0bc1\u0baa\u0bcd\u0baa\u0bc1 \u0b89\u0bb0\u0bc1\u0baa\u0bcd\u0baa\u0b9f\u0bbf\u0b95\u0bb3\u0bcd",
"Parent Item": "\u0baa\u0bc6\u0bb1\u0bcd\u0bb1\u0bc7\u0bbe\u0bb0\u0bcd \u0baa\u0bc6\u0bbe\u0bb0\u0bc1\u0bb3\u0bcd",
"Sales BOM": "\u0bb5\u0bbf\u0bb1\u0bcd\u0baa\u0ba9\u0bc8 BOM",
"Sales BOM Item": "\u0bb5\u0bbf\u0bb1\u0bcd\u0baa\u0ba9\u0bc8 BOM \u0baa\u0bc6\u0bbe\u0bb0\u0bc1\u0bb3\u0bcd",
"Sales BOM Items": "\u0bb5\u0bbf\u0bb1\u0bcd\u0baa\u0ba9\u0bc8 BOM \u0b89\u0bb0\u0bc1\u0baa\u0bcd\u0baa\u0b9f\u0bbf\u0b95\u0bb3\u0bcd",
"Stock": "\u0baa\u0b99\u0bcd\u0b95\u0bc1",
"The Item that represents the Package. This Item must have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\"": "\u0ba4\u0bc6\u0bbe\u0b95\u0bc1\u0baa\u0bcd\u0baa\u0bc1 \u0baa\u0bbf\u0bb0\u0ba4\u0bbf\u0baa\u0bb2\u0bbf\u0b95\u0bcd\u0b95\u0bbf\u0bb1\u0ba4\u0bc1 \u0b8e\u0ba9\u0bcd\u0bb1\u0bc1 \u0baa\u0bc6\u0bbe\u0bb0\u0bc1\u0bb3\u0bcd. \u0b87\u0ba8\u0bcd\u0ba4 \u0baa\u0bc6\u0bbe\u0bb0\u0bc1\u0bb3\u0bcd &quot;\u0b87\u0bb2\u0bcd\u0bb2\u0bc8&quot; \u0b8e\u0ba9 &quot;\u0baa\u0b99\u0bcd\u0b95\u0bc1 \u0b89\u0bb0\u0bc1\u0baa\u0bcd\u0baa\u0b9f\u0bbf \u0b87\u0bb2\u0bcd\u0bb2\u0bc8&quot; \u0bae\u0bb1\u0bcd\u0bb1\u0bc1\u0bae\u0bcd &quot;\u0b86\u0bae\u0bcd&quot; \u0b8e\u0ba9 &quot;\u0bb5\u0bbf\u0bb1\u0bcd\u0baa\u0ba9\u0bc8 \u0baa\u0bc6\u0bbe\u0bb0\u0bc1\u0bb3\u0bcd \u0b87\u0bb2\u0bcd\u0bb2\u0bc8&quot;"
}

View File

@@ -1,11 +0,0 @@
{
"Aggregate group of **Items** into another **Item**. This is useful if you are bundling a certain **Items** into a package and you maintain stock of the packed **Items** and not the aggregate **Item**. The package **Item** will have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\".For Example: If you are selling Laptops and Backpacks separately and have a special price if the customer buys both, then the Laptop + Backpack will be a new Sales BOM Item.Note: BOM = Bill of Materials": "\u0e01\u0e25\u0e38\u0e48\u0e21\u0e23\u0e27\u0e21\u0e02\u0e2d\u0e07\u0e23\u0e32\u0e22\u0e01\u0e32\u0e23 ** ** \u0e40\u0e02\u0e49\u0e32\u0e44\u0e1b\u0e2d\u0e35\u0e01\u0e23\u0e32\u0e22\u0e01\u0e32\u0e23 ** ** \u0e19\u0e35\u0e49\u0e08\u0e30\u0e40\u0e1b\u0e47\u0e19\u0e1b\u0e23\u0e30\u0e42\u0e22\u0e0a\u0e19\u0e4c\u0e16\u0e49\u0e32\u0e04\u0e38\u0e13\u0e01\u0e33\u0e25\u0e31\u0e07 bundling \u0e23\u0e32\u0e22\u0e01\u0e32\u0e23 ** ** \u0e1a\u0e32\u0e07\u0e40\u0e1b\u0e47\u0e19\u0e41\u0e1e\u0e04\u0e40\u0e01\u0e08\u0e41\u0e25\u0e30\u0e04\u0e38\u0e13\u0e23\u0e31\u0e01\u0e29\u0e32\u0e2a\u0e15\u0e47\u0e2d\u0e01\u0e02\u0e2d\u0e07\u0e1a\u0e23\u0e23\u0e08\u0e38\u0e23\u0e32\u0e22\u0e01\u0e32\u0e23 ** ** \u0e41\u0e25\u0e30\u0e44\u0e21\u0e48\u0e23\u0e27\u0e21\u0e23\u0e32\u0e22\u0e01\u0e32\u0e23 ** ** \u0e41\u0e1e\u0e04\u0e40\u0e01\u0e08\u0e2a\u0e34\u0e19\u0e04\u0e49\u0e32 ** ** \u0e08\u0e30\u0e21\u0e35 &quot;\u0e23\u0e32\u0e22\u0e01\u0e32\u0e23\u0e2a\u0e34\u0e19\u0e04\u0e49\u0e32&quot; \u0e02\u0e13\u0e30\u0e17\u0e35\u0e48 &quot;\u0e44\u0e21\u0e48\u0e21\u0e35&quot; \u0e41\u0e25\u0e30 &quot;\u0e23\u0e32\u0e22\u0e01\u0e32\u0e23\u0e02\u0e32\u0e22&quot; \u0e40\u0e1b\u0e47\u0e19 &quot;\u0e43\u0e0a\u0e48&quot; \u0e15\u0e31\u0e27\u0e2d\u0e22\u0e48\u0e32\u0e07:. \u0e16\u0e49\u0e32\u0e04\u0e38\u0e13\u0e01\u0e33\u0e25\u0e31\u0e07\u0e02\u0e32\u0e22\u0e41\u0e25\u0e47\u0e1b\u0e17\u0e47\u0e2d\u0e1b\u0e41\u0e25\u0e30\u0e40\u0e1b\u0e49\u0e2a\u0e30\u0e1e\u0e32\u0e22\u0e2b\u0e25\u0e31\u0e07\u0e41\u0e22\u0e01\u0e41\u0e25\u0e30\u0e21\u0e35\u0e23\u0e32\u0e04\u0e32\u0e1e\u0e34\u0e40\u0e28\u0e29\u0e2b\u0e32\u0e01\u0e25\u0e39\u0e01\u0e04\u0e49\u0e32\u0e0b\u0e37\u0e49\u0e2d\u0e17\u0e31\u0e49\u0e07 \u0e41\u0e25\u0e49\u0e27\u0e41\u0e25\u0e47\u0e1b\u0e17\u0e47\u0e2d\u0e1b\u0e01\u0e23\u0e30\u0e40\u0e1b\u0e4b\u0e32\u0e40\u0e1b\u0e49\u0e2a\u0e30\u0e1e\u0e32\u0e22\u0e2b\u0e25\u0e31\u0e07 + \u0e08\u0e30\u0e02\u0e32\u0e22\u0e43\u0e2b\u0e21\u0e48 BOM Item.Note: BOM \u0e1a\u0e34\u0e25\u0e02\u0e2d\u0e07\u0e27\u0e31\u0e2a\u0e14\u0e38 =",
"List items that form the package.": "\u0e23\u0e32\u0e22\u0e01\u0e32\u0e23\u0e17\u0e35\u0e48\u0e2a\u0e23\u0e49\u0e32\u0e07\u0e41\u0e1e\u0e04\u0e40\u0e01\u0e08",
"Package Items": "\u0e23\u0e32\u0e22\u0e01\u0e32\u0e23\u0e41\u0e1e\u0e04\u0e40\u0e01\u0e08",
"Parent Item": "\u0e23\u0e32\u0e22\u0e01\u0e32\u0e23\u0e2b\u0e25\u0e31\u0e01",
"Sales BOM": "BOM \u0e02\u0e32\u0e22",
"Sales BOM Item": "\u0e23\u0e32\u0e22\u0e01\u0e32\u0e23 BOM \u0e02\u0e32\u0e22",
"Sales BOM Items": "\u0e02\u0e32\u0e22\u0e2a\u0e34\u0e19\u0e04\u0e49\u0e32 BOM",
"Stock": "\u0e04\u0e25\u0e31\u0e07\u0e2a\u0e34\u0e19\u0e04\u0e49\u0e32",
"The Item that represents the Package. This Item must have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\"": "\u0e23\u0e32\u0e22\u0e01\u0e32\u0e23\u0e17\u0e35\u0e48\u0e41\u0e2a\u0e14\u0e07\u0e16\u0e36\u0e07\u0e41\u0e1e\u0e04\u0e40\u0e01\u0e08 \u0e23\u0e32\u0e22\u0e01\u0e32\u0e23\u0e19\u0e35\u200b\u200b\u0e49\u0e08\u0e30\u0e15\u0e49\u0e2d\u0e07\u0e21\u0e35 &quot;\u0e23\u0e32\u0e22\u0e01\u0e32\u0e23\u0e2a\u0e34\u0e19\u0e04\u0e49\u0e32&quot; \u0e02\u0e13\u0e30\u0e17\u0e35\u0e48 &quot;\u0e44\u0e21\u0e48\u0e21\u0e35&quot; \u0e41\u0e25\u0e30 &quot;\u0e23\u0e32\u0e22\u0e01\u0e32\u0e23\u0e02\u0e32\u0e22&quot; \u0e40\u0e1b\u0e47\u0e19 &quot;\u0e43\u0e0a\u0e48&quot;"
}

View File

@@ -1,39 +0,0 @@
// ERPNext - web based ERP (http://erpnext.com)
// Copyright (C) 2012 Web Notes Technologies Pvt Ltd
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
cur_frm.cscript.refresh = function(doc, cdt, cdn) {
cur_frm.toggle_enable('new_item_code', doc.__islocal);
if(!doc.__islocal) {
cur_frm.add_custom_button("Check for Duplicates", function() {
cur_frm.call_server('check_duplicate', 1)
}, 'icon-search')
}
}
cur_frm.fields_dict.new_item_code.get_query = function() {
return 'select name, description from tabItem where is_stock_item="No" and is_sales_item="Yes"\
and name not in (select name from `tabSales BOM`)\
and `%(key)s` like "%s"'
}
cur_frm.fields_dict.new_item_code.query_description = 'Select Item where "Is Stock Item" is "No" \
and "Is Sales Item" is "Yes" and there is no other Sales BOM';
cur_frm.cscript.item_code = function(doc, dt, dn) {
var d = locals[dt][dn];
if (d.item_code){
get_server_fields('get_item_details', d.item_code, 'sales_bom_items', doc ,dt, dn, 1);
}
}

View File

@@ -1,85 +0,0 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
import webnotes
from webnotes.utils import flt
from webnotes.model.utils import getlist
class DocType:
def __init__(self,d,dl):
self.doc, self.doclist = d,dl
def autoname(self):
self.doc.name = self.doc.new_item_code
def validate(self):
# check for duplicate
self.check_duplicate()
self.validate_main_item()
def validate_main_item(self):
"""main item must have Is Stock Item as No and Is Sales Item as Yes"""
if not webnotes.conn.sql("""select name from tabItem where name=%s and
ifnull(is_stock_item,'')='No' and ifnull(is_sales_item,'')='Yes'""", self.doc.new_item_code):
webnotes.msgprint("""Parent Item %s is either a Stock Item or a not a Sales Item""",
raise_exception=1)
def get_item_details(self, name):
det = webnotes.conn.sql("""select description, stock_uom from `tabItem`
where name = %s""", name)
rate = webnotes.conn.sql("""select ref_rate from `tabItem Price`
where price_list_name = %s and parent = %s
and ref_currency = %s""", (self.doc.price_list, name, self.doc.currency))
return {
'description' : det and det[0][0] or '',
'uom': det and det[0][1] or '',
'rate': rate and flt(rate[0][0]) or 0.00
}
def check_duplicate(self, finder=0):
il = getlist(self.doclist, "sales_bom_items")
if not il:
webnotes.msgprint("Add atleast one item")
return
# get all Sales BOM that have the first item
sbl = webnotes.conn.sql("""select distinct parent from `tabSales BOM Item` where item_code=%s
and parent != %s and docstatus != 2""", (il[0].item_code, self.doc.name))
# check all siblings
sub_items = [[d.item_code, flt(d.qty)] for d in il]
for s in sbl:
t = webnotes.conn.sql("""select item_code, qty from `tabSales BOM Item` where parent=%s and
docstatus != 2""", s[0])
t = [[d[0], flt(d[1])] for d in t]
if self.has_same_items(sub_items, t):
webnotes.msgprint("%s has the same Sales BOM details" % s[0])
raise Exception
if finder:
webnotes.msgprint("There is no Sales BOM present with the following Combination.")
def has_same_items(self, l1, l2):
if len(l1)!=len(l2): return 0
for l in l2:
if l not in l1:
return 0
for l in l1:
if l not in l2:
return 0
return 1

View File

@@ -1,97 +0,0 @@
[
{
"creation": "2013-01-10 16:34:29",
"docstatus": 0,
"modified": "2013-01-22 14:57:23",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"description": "Aggregate group of **Items** into another **Item**. This is useful if you are bundling a certain **Items** into a package and you maintain stock of the packed **Items** and not the aggregate **Item**. \n\nThe package **Item** will have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\".\n\nFor Example: If you are selling Laptops and Backpacks separately and have a special price if the customer buys both, then the Laptop + Backpack will be a new Sales BOM Item.\n\nNote: BOM = Bill of Materials",
"doctype": "DocType",
"document_type": "Master",
"is_submittable": 0,
"module": "Stock",
"name": "__common__"
},
{
"doctype": "DocField",
"name": "__common__",
"parent": "Sales BOM",
"parentfield": "fields",
"parenttype": "DocType",
"permlevel": 0
},
{
"amend": 0,
"doctype": "DocPerm",
"name": "__common__",
"parent": "Sales BOM",
"parentfield": "permissions",
"parenttype": "DocType",
"permlevel": 0,
"read": 1,
"report": 1,
"submit": 0
},
{
"doctype": "DocType",
"name": "Sales BOM"
},
{
"doctype": "DocField",
"fieldname": "basic_section",
"fieldtype": "Section Break",
"label": "Sales BOM Item"
},
{
"description": "The Item that represents the Package. This Item must have \"Is Stock Item\" as \"No\" and \"Is Sales Item\" as \"Yes\"",
"doctype": "DocField",
"fieldname": "new_item_code",
"fieldtype": "Link",
"label": "Parent Item",
"no_copy": 1,
"oldfieldname": "new_item_code",
"oldfieldtype": "Data",
"options": "Item",
"reqd": 1
},
{
"description": "List items that form the package.",
"doctype": "DocField",
"fieldname": "item_section",
"fieldtype": "Section Break",
"label": "Package Items"
},
{
"doctype": "DocField",
"fieldname": "sales_bom_items",
"fieldtype": "Table",
"label": "Sales BOM Items",
"oldfieldname": "sales_bom_items",
"oldfieldtype": "Table",
"options": "Sales BOM Item",
"reqd": 1
},
{
"cancel": 1,
"create": 1,
"doctype": "DocPerm",
"role": "Material Manager",
"write": 1
},
{
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"role": "Material User",
"write": 0
},
{
"cancel": 1,
"create": 1,
"doctype": "DocPerm",
"role": "Sales User",
"write": 1
}
]

View File

@@ -1,20 +0,0 @@
test_records = [
[
{
"doctype": "Sales BOM",
"new_item_code": "_Test Sales BOM Item"
},
{
"doctype": "Sales BOM Item",
"item_code": "_Test Item",
"parentfield": "sales_bom_items",
"qty": 5.0
},
{
"doctype": "Sales BOM Item",
"item_code": "_Test Item Home Desktop 100",
"parentfield": "sales_bom_items",
"qty": 2.0
}
],
]

View File

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

View File

@@ -1,9 +0,0 @@
[
"Description",
"Item",
"Qty",
"Sales BOM Item",
"Rate",
"UOM",
"Stock"
]

View File

@@ -1,9 +0,0 @@
{
"Description": "\u0648\u0635\u0641",
"Item": "\u0628\u0646\u062f",
"Qty": "\u0627\u0644\u0643\u0645\u064a\u0629",
"Rate": "\u0645\u0639\u062f\u0644",
"Sales BOM Item": "\u0645\u0628\u064a\u0639\u0627\u062a \u0627\u0644\u0633\u0644\u0639\u0629 BOM",
"Stock": "\u0627\u0644\u0623\u0648\u0631\u0627\u0642 \u0627\u0644\u0645\u0627\u0644\u064a\u0629",
"UOM": "UOM"
}

View File

@@ -1,9 +0,0 @@
{
"Description": "Beschreibung",
"Item": "Artikel",
"Qty": "Menge",
"Rate": "Rate",
"Sales BOM Item": "Vertrieb St\u00fccklistenposition",
"Stock": "Lager",
"UOM": "UOM"
}

View File

@@ -1,9 +0,0 @@
{
"Description": "Descripci\u00f3n",
"Item": "Art\u00edculo",
"Qty": "Cantidad",
"Rate": "Velocidad",
"Sales BOM Item": "Ventas de art\u00edculo de lista de materiales",
"Stock": "Valores",
"UOM": "UOM"
}

View File

@@ -1,9 +0,0 @@
{
"Description": "Description",
"Item": "Article",
"Qty": "Qt\u00e9",
"Rate": "Taux",
"Sales BOM Item": "Article nomenclature des ventes",
"Stock": "Stock",
"UOM": "Emballage"
}

View File

@@ -1,9 +0,0 @@
{
"Description": "\u0935\u093f\u0935\u0930\u0923",
"Item": "\u092e\u0926",
"Qty": "\u092e\u093e\u0924\u094d\u0930\u093e",
"Rate": "\u0926\u0930",
"Sales BOM Item": "\u092c\u093f\u0915\u094d\u0930\u0940 \u092c\u0940\u0913\u090f\u092e \u0906\u0907\u091f\u092e",
"Stock": "\u0938\u094d\u091f\u0949\u0915",
"UOM": "UOM"
}

View File

@@ -1,9 +0,0 @@
{
"Description": "Opis",
"Item": "Stavka",
"Qty": "Kol",
"Rate": "Stopa",
"Sales BOM Item": "Prodaja BOM artikla",
"Stock": "Zaliha",
"UOM": "UOM"
}

View File

@@ -1,9 +0,0 @@
{
"Description": "Beschrijving",
"Item": "Item",
"Qty": "Aantal",
"Rate": "Tarief",
"Sales BOM Item": "Verkoop BOM Item",
"Stock": "Voorraad",
"UOM": "Verpakking"
}

View File

@@ -1,9 +0,0 @@
{
"Description": "Descri\u00e7\u00e3o",
"Item": "Item",
"Qty": "Qtde.",
"Rate": "Taxa",
"Sales BOM Item": "Item da LDM de Vendas",
"Stock": "Estoque",
"UOM": "UDM"
}

View File

@@ -1,9 +0,0 @@
{
"Description": "Descri\u00e7\u00e3o",
"Item": "Item",
"Qty": "Qty",
"Rate": "Taxa",
"Sales BOM Item": "Vendas item BOM",
"Stock": "Estoque",
"UOM": "UOM"
}

View File

@@ -1,9 +0,0 @@
{
"Description": "\u041e\u043f\u0438\u0441",
"Item": "\u0421\u0442\u0430\u0432\u043a\u0430",
"Qty": "\u041a\u043e\u043b",
"Rate": "\u0421\u0442\u043e\u043f\u0430",
"Sales BOM Item": "\u041f\u0440\u043e\u0434\u0430\u0458\u0430 \u0411\u041e\u041c \u0448\u0438\u0444\u0440\u0430",
"Stock": "\u0417\u0430\u043b\u0438\u0445\u0430",
"UOM": "\u0423\u041e\u041c"
}

View File

@@ -1,9 +0,0 @@
{
"Description": "\u0bb5\u0bbf\u0bb3\u0b95\u0bcd\u0b95\u0bae\u0bcd",
"Item": "\u0b89\u0bb0\u0bc1\u0baa\u0bcd\u0baa\u0b9f\u0bbf",
"Qty": "\u0b85\u0bb3\u0bb5\u0bc1",
"Rate": "\u0bb5\u0bbf\u0bb2\u0bc8",
"Sales BOM Item": "\u0bb5\u0bbf\u0bb1\u0bcd\u0baa\u0ba9\u0bc8 BOM \u0baa\u0bc6\u0bbe\u0bb0\u0bc1\u0bb3\u0bcd",
"Stock": "\u0baa\u0b99\u0bcd\u0b95\u0bc1",
"UOM": "\u0bae\u0bc6\u0bbe\u0bb1\u0b9f\u0bcd\u0b9f\u0bc1\u0bb5 \u0baa\u0bb2\u0bcd\u0b95\u0bb2\u0bc8\u0b95\u0bb4\u0b95\u0bae\u0bcd"
}

View File

@@ -1,9 +0,0 @@
{
"Description": "\u0e25\u0e31\u0e01\u0e29\u0e13\u0e30",
"Item": "\u0e0a\u0e34\u0e49\u0e19",
"Qty": "\u0e08\u0e33\u0e19\u0e27\u0e19",
"Rate": "\u0e2d\u0e31\u0e15\u0e23\u0e32",
"Sales BOM Item": "\u0e23\u0e32\u0e22\u0e01\u0e32\u0e23 BOM \u0e02\u0e32\u0e22",
"Stock": "\u0e04\u0e25\u0e31\u0e07\u0e2a\u0e34\u0e19\u0e04\u0e49\u0e32",
"UOM": "UOM"
}

View File

@@ -1,75 +0,0 @@
[
{
"creation": "2013-02-22 01:28:03",
"docstatus": 0,
"modified": "2013-03-07 07:03:30",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"doctype": "DocType",
"istable": 1,
"module": "Stock",
"name": "__common__"
},
{
"doctype": "DocField",
"name": "__common__",
"parent": "Sales BOM Item",
"parentfield": "fields",
"parenttype": "DocType",
"permlevel": 0
},
{
"doctype": "DocType",
"name": "Sales BOM Item"
},
{
"doctype": "DocField",
"fieldname": "item_code",
"fieldtype": "Link",
"label": "Item",
"oldfieldname": "item_code",
"oldfieldtype": "Link",
"options": "Item",
"reqd": 1
},
{
"doctype": "DocField",
"fieldname": "qty",
"fieldtype": "Float",
"label": "Qty",
"oldfieldname": "qty",
"oldfieldtype": "Currency",
"reqd": 1
},
{
"doctype": "DocField",
"fieldname": "description",
"fieldtype": "Text",
"label": "Description",
"oldfieldname": "description",
"oldfieldtype": "Text",
"print_width": "300px",
"width": "300px"
},
{
"doctype": "DocField",
"fieldname": "rate",
"fieldtype": "Float",
"label": "Rate",
"oldfieldname": "rate",
"oldfieldtype": "Currency"
},
{
"doctype": "DocField",
"fieldname": "uom",
"fieldtype": "Link",
"label": "UOM",
"oldfieldname": "uom",
"oldfieldtype": "Link",
"options": "UOM",
"read_only": 1,
"search_index": 0
}
]

View File

@@ -19,7 +19,7 @@ import webnotes
from webnotes.utils import cint, getdate, nowdate
import datetime
from webnotes import msgprint
from webnotes import msgprint, _
from controllers.stock_controller import StockController
@@ -117,8 +117,11 @@ class DocType(StockController):
self.make_stock_ledger_entry(1)
self.make_gl_entries()
def on_rename(self, new, old):
def on_rename(self, new, old, merge=False):
"""rename serial_no text fields"""
if merge:
msgprint(_("Sorry. Serial Nos. cannot be merged"), raise_exception=True)
for dt in webnotes.conn.sql("""select parent from tabDocField
where fieldname='serial_no' and fieldtype='Text'"""):
@@ -139,7 +142,8 @@ class DocType(StockController):
gl_entries = self.get_gl_entries_for_stock(against_stock_account, self.doc.purchase_rate)
for entry in gl_entries:
entry["posting_date"] = self.doc.purchase_date
entry["posting_date"] = self.doc.purchase_date or (self.doc.creation and
self.doc.creation.split(' ')[0]) or nowdate()
if gl_entries:
make_gl_entries(gl_entries, cancel)

View File

@@ -1,14 +1,14 @@
[
{
"creation": "2013-01-10 16:34:29",
"creation": "2013-05-16 10:59:15",
"docstatus": 0,
"modified": "2013-01-29 16:27:57",
"modified": "2013-06-20 11:23:01",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"allow_attach": 1,
"allow_rename": 1,
"allow_rename": 0,
"autoname": "field:serial_no",
"description": "Distinct unit of an Item",
"doctype": "DocType",
@@ -32,7 +32,9 @@
"parentfield": "permissions",
"parenttype": "DocType",
"permlevel": 0,
"read": 1
"read": 1,
"report": 1,
"submit": 0
},
{
"doctype": "DocType",
@@ -43,12 +45,14 @@
"fieldname": "details",
"fieldtype": "Section Break",
"label": "Details",
"oldfieldtype": "Section Break"
"oldfieldtype": "Section Break",
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "column_break0",
"fieldtype": "Column Break"
"fieldtype": "Column Break",
"read_only": 0
},
{
"default": "In Store",
@@ -75,6 +79,7 @@
"no_copy": 1,
"oldfieldname": "serial_no",
"oldfieldtype": "Data",
"read_only": 0,
"reqd": 1,
"search_index": 1
},
@@ -88,13 +93,15 @@
"oldfieldname": "item_code",
"oldfieldtype": "Link",
"options": "Item",
"read_only": 0,
"reqd": 1,
"search_index": 0
},
{
"doctype": "DocField",
"fieldname": "column_break1",
"fieldtype": "Column Break"
"fieldtype": "Column Break",
"read_only": 0
},
{
"doctype": "DocField",
@@ -146,12 +153,14 @@
"doctype": "DocField",
"fieldname": "purchase_details",
"fieldtype": "Section Break",
"label": "Purchase Details"
"label": "Purchase Details",
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "column_break2",
"fieldtype": "Column Break",
"read_only": 0,
"width": "50%"
},
{
@@ -160,7 +169,8 @@
"fieldtype": "Select",
"label": "Purchase Document Type",
"no_copy": 1,
"options": "\nPurchase Receipt\nStock Entry"
"options": "\nPurchase Receipt\nStock Entry",
"read_only": 0
},
{
"doctype": "DocField",
@@ -168,7 +178,8 @@
"fieldtype": "Data",
"hidden": 0,
"label": "Purchase Document No",
"no_copy": 1
"no_copy": 1,
"read_only": 0
},
{
"doctype": "DocField",
@@ -179,6 +190,7 @@
"no_copy": 1,
"oldfieldname": "purchase_date",
"oldfieldtype": "Date",
"read_only": 0,
"reqd": 0,
"search_index": 0
},
@@ -188,6 +200,7 @@
"fieldtype": "Time",
"label": "Incoming Time",
"no_copy": 1,
"read_only": 0,
"reqd": 1
},
{
@@ -200,6 +213,7 @@
"oldfieldname": "purchase_rate",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"read_only": 0,
"reqd": 1,
"search_index": 0
},
@@ -207,6 +221,7 @@
"doctype": "DocField",
"fieldname": "column_break3",
"fieldtype": "Column Break",
"read_only": 0,
"width": "50%"
},
{
@@ -220,6 +235,7 @@
"oldfieldname": "warehouse",
"oldfieldtype": "Link",
"options": "Warehouse",
"read_only": 0,
"reqd": 0,
"search_index": 1
},
@@ -230,7 +246,8 @@
"in_filter": 1,
"label": "Supplier",
"no_copy": 1,
"options": "Supplier"
"options": "Supplier",
"read_only": 0
},
{
"doctype": "DocField",
@@ -254,12 +271,14 @@
"fieldname": "delivery_details",
"fieldtype": "Section Break",
"label": "Delivery Details",
"oldfieldtype": "Column Break"
"oldfieldtype": "Column Break",
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "column_break4",
"fieldtype": "Column Break",
"read_only": 0,
"width": "50%"
},
{
@@ -318,12 +337,14 @@
"oldfieldname": "is_cancelled",
"oldfieldtype": "Select",
"options": "\nYes\nNo",
"read_only": 0,
"report_hide": 1
},
{
"doctype": "DocField",
"fieldname": "column_break5",
"fieldtype": "Column Break",
"read_only": 0,
"width": "50%"
},
{
@@ -378,12 +399,14 @@
"doctype": "DocField",
"fieldname": "warranty_amc_details",
"fieldtype": "Section Break",
"label": "Warranty / AMC Details"
"label": "Warranty / AMC Details",
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "column_break6",
"fieldtype": "Column Break",
"read_only": 0,
"width": "50%"
},
{
@@ -396,6 +419,7 @@
"oldfieldname": "maintenance_status",
"oldfieldtype": "Select",
"options": "\nUnder Warranty\nOut of Warranty\nUnder AMC\nOut of AMC",
"read_only": 0,
"search_index": 1,
"width": "150px"
},
@@ -406,12 +430,14 @@
"label": "Warranty Period (Days)",
"oldfieldname": "warranty_period",
"oldfieldtype": "Int",
"read_only": 0,
"width": "150px"
},
{
"doctype": "DocField",
"fieldname": "column_break7",
"fieldtype": "Column Break",
"read_only": 0,
"width": "50%"
},
{
@@ -422,6 +448,7 @@
"label": "Warranty Expiry Date",
"oldfieldname": "warranty_expiry_date",
"oldfieldtype": "Date",
"read_only": 0,
"width": "150px"
},
{
@@ -432,6 +459,7 @@
"label": "AMC Expiry Date",
"oldfieldname": "amc_expiry_date",
"oldfieldtype": "Date",
"read_only": 0,
"search_index": 0,
"width": "150px"
},
@@ -439,13 +467,15 @@
"doctype": "DocField",
"fieldname": "more_info",
"fieldtype": "Section Break",
"label": "More Info"
"label": "More Info",
"read_only": 0
},
{
"doctype": "DocField",
"fieldname": "serial_no_details",
"fieldtype": "Text Editor",
"label": "Serial No Details"
"label": "Serial No Details",
"read_only": 0
},
{
"doctype": "DocField",
@@ -454,6 +484,7 @@
"in_filter": 1,
"label": "Company",
"options": "link:Company",
"read_only": 0,
"reqd": 1,
"search_index": 1
},
@@ -464,6 +495,7 @@
"in_filter": 1,
"label": "Fiscal Year",
"options": "link:Fiscal Year",
"read_only": 0,
"reqd": 1,
"search_index": 1
},
@@ -476,15 +508,6 @@
"oldfieldtype": "Small Text",
"read_only": 1
},
{
"doctype": "DocField",
"fieldname": "file_list",
"fieldtype": "Text",
"hidden": 1,
"label": "File List",
"no_copy": 1,
"print_hide": 1
},
{
"doctype": "DocField",
"fieldname": "sle_exists",
@@ -500,21 +523,30 @@
"cancel": 1,
"create": 1,
"doctype": "DocPerm",
"report": 1,
"role": "Material User",
"submit": 0,
"role": "System Manager",
"write": 1
},
{
"cancel": 1,
"create": 1,
"doctype": "DocPerm",
"role": "Sales User"
"role": "Material Master Manager",
"write": 1
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"role": "Purchase User"
"role": "Material Manager",
"write": 0
},
{
"amend": 0,
"cancel": 0,
"create": 0,
"doctype": "DocPerm",
"role": "Accounts User"
"role": "Material User",
"write": 0
}
]

View File

@@ -57,6 +57,7 @@ class DocType(StockController):
self.validate_return_reference_doc()
self.validate_with_material_request()
self.validate_fiscal_year()
self.set_total_amount()
def on_submit(self):
self.update_serial_no(1)
@@ -174,6 +175,9 @@ class DocType(StockController):
elif self.doc.purpose != "Material Transfer":
self.doc.production_order = None
def set_total_amount(self):
self.doc.total_amount = sum([flt(item.amount) for item in self.doclist.get({"parentfield": "mtn_details"})])
def make_gl_entries(self):
if not cint(webnotes.defaults.get_global_default("auto_inventory_accounting")):
return
@@ -194,10 +198,10 @@ class DocType(StockController):
total_valuation_amount = 0
for item in self.doclist.get({"parentfield": "mtn_details"}):
if item.t_warehouse and not item.s_warehouse:
total_valuation_amount += flt(item.incoming_rate) * flt(item.transfer_qty)
total_valuation_amount += flt(item.incoming_rate, 2) * flt(item.transfer_qty)
if item.s_warehouse and not item.t_warehouse:
total_valuation_amount -= flt(item.incoming_rate) * flt(item.transfer_qty)
total_valuation_amount -= flt(item.incoming_rate, 2) * flt(item.transfer_qty)
return total_valuation_amount
@@ -220,7 +224,7 @@ class DocType(StockController):
if not flt(d.incoming_rate):
d.incoming_rate = self.get_incoming_rate(args)
d.amount = flt(d.qty) * flt(d.incoming_rate)
d.amount = flt(d.transfer_qty) * flt(d.incoming_rate)
def get_incoming_rate(self, args):
incoming_rate = 0
@@ -502,17 +506,13 @@ class DocType(StockController):
if self.doc.use_multi_level_bom:
# get all raw materials with sub assembly childs
fl_bom_sa_child_item = sql("""select
item_code,ifnull(sum(qty_consumed_per_unit),0)*%s as qty,
description,stock_uom
from ( select distinct fb.name, fb.description, fb.item_code,
fb.qty_consumed_per_unit, fb.stock_uom
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
) a
group by item_code, stock_uom""" , (qty, self.doc.bom_no), as_dict=1)
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
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)
@@ -520,10 +520,10 @@ class DocType(StockController):
# Get all raw materials considering multi level BOM,
# if multi level bom consider childs of Sub-Assembly items
fl_bom_sa_items = sql("""select item_code,
ifnull(sum(qty_consumed_per_unit), 0) * '%s' as qty,
ifnull(sum(qty_consumed_per_unit), 0) *%s as qty,
description, stock_uom from `tabBOM Item`
where parent = '%s' and docstatus < 2
group by item_code""" % (qty, self.doc.bom_no), as_dict=1)
where parent = %s and 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)
@@ -607,7 +607,7 @@ class DocType(StockController):
'voucher_no': self.doc.name,
'voucher_detail_no': d.name,
'actual_qty': qty,
'incoming_rate': flt(d.incoming_rate) or 0,
'incoming_rate': flt(d.incoming_rate, 2) or 0,
'stock_uom': d.stock_uom,
'company': self.doc.company,
'is_cancelled': (is_cancelled ==1) and 'Yes' or 'No',

View File

@@ -1,8 +1,8 @@
[
{
"creation": "2013-03-28 15:56:40",
"creation": "2013-04-09 11:43:55",
"docstatus": 0,
"modified": "2013-03-29 15:31:42",
"modified": "2013-05-09 13:31:00",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -518,6 +518,14 @@
"read_only": 0,
"width": "50%"
},
{
"doctype": "DocField",
"fieldname": "total_amount",
"fieldtype": "Currency",
"label": "Total Amount",
"options": "Company:company:default_currency",
"read_only": 1
},
{
"doctype": "DocField",
"fieldname": "project_name",
@@ -558,6 +566,14 @@
"read_only": 0,
"reqd": 1
},
{
"doctype": "DocField",
"fieldname": "col5",
"fieldtype": "Column Break",
"print_width": "50%",
"read_only": 0,
"width": "50%"
},
{
"allow_on_submit": 0,
"doctype": "DocField",
@@ -576,14 +592,6 @@
"reqd": 1,
"search_index": 0
},
{
"doctype": "DocField",
"fieldname": "col5",
"fieldtype": "Column Break",
"print_width": "50%",
"read_only": 0,
"width": "50%"
},
{
"allow_on_submit": 0,
"doctype": "DocField",

View File

@@ -21,10 +21,15 @@ class TestStockEntry(unittest.TestCase):
st2.insert()
st2.submit()
from stock.utils import reorder_item
reorder_item()
mr_name = webnotes.conn.sql("""select parent from `tabMaterial Request Item`
where item_code='_Test Item'""")
self.assertTrue(mr_name)
webnotes.conn.set_default("company", self.old_default_company)
def test_warehouse_company_validation(self):
from stock.doctype.stock_ledger_entry.stock_ledger_entry import InvalidWarehouseCompany
@@ -71,7 +76,7 @@ class TestStockEntry(unittest.TestCase):
webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
def test_material_issue_gl_entry(self):
webnotes.conn.sql("delete from `tabStock Ledger Entry`")
self._clear_stock()
webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
mr = webnotes.bean(copy=test_records[0])
@@ -111,9 +116,10 @@ class TestStockEntry(unittest.TestCase):
)
webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
webnotes.conn.set_default("company", self.old_default_company)
def test_material_transfer_gl_entry(self):
webnotes.conn.sql("delete from `tabStock Ledger Entry`")
self._clear_stock()
webnotes.defaults.set_global_default("auto_inventory_accounting", 1)
mr = webnotes.bean(copy=test_records[0])
@@ -145,6 +151,7 @@ class TestStockEntry(unittest.TestCase):
self.assertFalse(gl_entries)
webnotes.defaults.set_global_default("auto_inventory_accounting", 0)
webnotes.conn.set_default("company", self.old_default_company)
def check_stock_ledger_entries(self, voucher_type, voucher_no, expected_sle):
# check stock ledger entries
@@ -173,6 +180,9 @@ class TestStockEntry(unittest.TestCase):
def _clear_stock(self):
webnotes.conn.sql("delete from `tabStock Ledger Entry`")
webnotes.conn.sql("""delete from `tabBin`""")
self.old_default_company = webnotes.conn.get_default("company")
webnotes.conn.set_default("company", "_Test Company")
def _insert_material_receipt(self):
self._clear_stock()
@@ -185,6 +195,8 @@ class TestStockEntry(unittest.TestCase):
se2.insert()
se2.submit()
webnotes.conn.set_default("company", self.old_default_company)
def _get_actual_qty(self):
return flt(webnotes.conn.get_value("Bin", {"item_code": "_Test Item",
"warehouse": "_Test Warehouse"}, "actual_qty"))
@@ -463,6 +475,8 @@ class TestStockEntry(unittest.TestCase):
self.assertEquals(actual_qty_1 - 5, actual_qty_2)
webnotes.conn.set_default("company", self.old_default_company)
return se, pr.doc.name
def test_over_stock_return(self):
@@ -563,6 +577,8 @@ class TestStockEntry(unittest.TestCase):
self.assertEquals(actual_qty_1 - 5, actual_qty_2)
webnotes.conn.set_default("company", self.old_default_company)
return se, pr.doc.name
test_records = [

View File

@@ -114,7 +114,8 @@ class DocType:
def update_serial_purchase_details(self, obj, d, serial_no, is_submit, purpose = '', rejected=None):
exists = webnotes.conn.sql("select name, status, docstatus from `tabSerial No` where name = '%s'" % (serial_no))
if is_submit:
if exists and exists[0][2] != 2 and purpose not in ['Material Transfer', 'Sales Return']:
if exists and exists[0][2] != 2 and \
purpose not in ['Material Transfer', "Material Receipt", 'Sales Return']:
msgprint("Serial No: %s already %s" % (serial_no, exists and exists[0][1]), raise_exception = 1)
elif exists:
s = Document('Serial No', exists and exists[0][0])

View File

@@ -1,8 +1,8 @@
[
{
"creation": "2013-03-26 06:51:17",
"creation": "2013-03-28 10:35:31",
"docstatus": 0,
"modified": "2013-03-26 08:32:03",
"modified": "2013-04-10 13:44:19",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -52,6 +52,7 @@
"fieldname": "posting_date",
"fieldtype": "Date",
"in_filter": 0,
"in_list_view": 1,
"label": "Posting Date",
"oldfieldname": "reconciliation_date",
"oldfieldtype": "Date",
@@ -63,6 +64,7 @@
"fieldname": "posting_time",
"fieldtype": "Time",
"in_filter": 0,
"in_list_view": 1,
"label": "Posting Time",
"oldfieldname": "reconciliation_time",
"oldfieldtype": "Time",
@@ -148,6 +150,7 @@
"fieldname": "stock_value_difference",
"fieldtype": "Currency",
"hidden": 1,
"in_list_view": 1,
"label": "Stock Value Difference",
"print_hide": 1
},

View File

@@ -2,7 +2,8 @@ test_records = [
[{
"doctype": "Warehouse",
"warehouse_name": "_Test Warehouse",
"warehouse_type": "_Test Warehouse Type"
"warehouse_type": "_Test Warehouse Type",
"company": "_Test Company"
}],
[{
"doctype": "Warehouse",

View File

@@ -95,6 +95,8 @@ erpnext.StockAgeing = erpnext.StockGridReport.extend({
this.data = [].concat(this._data);
this.serialized_buying_rates = this.get_serialized_buying_rates();
$.each(this.data, function(i, d) {
me.reset_item_values(d);
});

View File

@@ -119,7 +119,7 @@ erpnext.StockBalance = erpnext.StockAnalytics.extend({
var qty_diff = sl.qty;
var value_diff = me.get_value_diff(wh, sl, is_fifo);
if(sl_posting_date < from_date) {
item.opening_qty += qty_diff;
item.opening_value += value_diff;
@@ -146,6 +146,8 @@ erpnext.StockBalance = erpnext.StockAnalytics.extend({
} else {
break;
}
me.round_item_values(item);
}
}

View File

@@ -197,6 +197,42 @@ wn.module_page["Stock"] = [
route: "query-report/Item-Wise Price List",
doctype: "Item"
},
{
"label":wn._("Purchase In Transit"),
route: "query-report/Purchase In Transit",
},
{
"label":wn._("Requested Items To Be Transferred"),
route: "query-report/Requested Items To Be Transferred",
},
{
"label":wn._("Batch-Wise Balance History"),
route: "query-report/Batch-Wise Balance History",
},
{
"label":wn._("Warehouse-Wise Stock Balance"),
route: "query-report/Warehouse-Wise Stock Balance",
},
{
"label":wn._("Item Prices"),
route: "query-report/Item Prices",
},
{
"label":wn._("Itemwise Recommended Reorder Level"),
route: "query-report/Itemwise Recommended Reorder Level",
doctype: "Item"
},
{
"label":wn._("Delivery Note Trends"),
route: "query-report/Delivery Note Trends",
doctype: "Delivery Note"
},
{
"label":wn._("Purchase Receipt Trends"),
route: "query-report/Purchase Receipt Trends",
doctype: "Purchase Receipt"
},
]
}
]

View File

@@ -0,0 +1,18 @@
wn.query_reports["Batch-Wise Balance History"] = {
"filters": [
{
"fieldname":"from_date",
"label": "From Date",
"fieldtype": "Date",
"width": "80",
"default": sys_defaults.year_start_date,
},
{
"fieldname":"to_date",
"label": "To Date",
"fieldtype": "Date",
"width": "80",
"default": wn.datetime.get_today()
}
]
}

View File

@@ -0,0 +1,98 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
import webnotes
from webnotes.utils import flt
def execute(filters=None):
if not filters: filters = {}
columns = get_columns(filters)
item_map = get_item_details(filters)
iwb_map = get_item_warehouse_batch_map(filters)
data = []
for item in sorted(iwb_map):
for wh in sorted(iwb_map[item]):
for batch in sorted(iwb_map[item][wh]):
qty_dict = iwb_map[item][wh][batch]
data.append([item, item_map[item]["item_name"],
item_map[item]["description"], wh, batch,
qty_dict.opening_qty, qty_dict.in_qty,
qty_dict.out_qty, qty_dict.bal_qty
])
return columns, data
def get_columns(filters):
"""return columns based on filters"""
columns = ["Item:Link/Item:100"] + ["Item Name::150"] + ["Description::150"] + \
["Warehouse:Link/Warehouse:100"] + ["Batch:Link/Batch:100"] + ["Opening Qty::90"] + \
["In Qty::80"] + ["Out Qty::80"] + ["Balance Qty::90"]
return columns
def get_conditions(filters):
conditions = ""
if not filters.get("from_date"):
webnotes.msgprint("Please enter From Date", raise_exception=1)
if filters.get("to_date"):
conditions += " and posting_date <= '%s'" % filters["to_date"]
else:
webnotes.msgprint("Please enter To Date", raise_exception=1)
return conditions
#get all details
def get_stock_ledger_entries(filters):
conditions = get_conditions(filters)
return webnotes.conn.sql("""select item_code, batch_no, warehouse,
posting_date, actual_qty
from `tabStock Ledger Entry`
where ifnull(is_cancelled, 'No') = 'No' %s order by item_code, warehouse""" %
conditions, as_dict=1)
def get_item_warehouse_batch_map(filters):
sle = get_stock_ledger_entries(filters)
iwb_map = {}
for d in sle:
iwb_map.setdefault(d.item_code, {}).setdefault(d.warehouse, {})\
.setdefault(d.batch_no, webnotes._dict({
"opening_qty": 0.0, "in_qty": 0.0, "out_qty": 0.0, "bal_qty": 0.0
}))
qty_dict = iwb_map[d.item_code][d.warehouse][d.batch_no]
if d.posting_date < filters["from_date"]:
qty_dict.opening_qty += flt(d.actual_qty)
elif d.posting_date >= filters["from_date"] and d.posting_date <= filters["to_date"]:
if flt(d.actual_qty) > 0:
qty_dict.in_qty += flt(d.actual_qty)
else:
qty_dict.out_qty += abs(flt(d.actual_qty))
qty_dict.bal_qty += flt(d.actual_qty)
return iwb_map
def get_item_details(filters):
item_map = {}
for d in webnotes.conn.sql("select name, item_name, description from tabItem", as_dict=1):
item_map.setdefault(d.name, d)
return item_map

View File

@@ -0,0 +1,21 @@
[
{
"creation": "2013-06-04 11:03:47",
"docstatus": 0,
"modified": "2013-06-04 19:32:27",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"doctype": "Report",
"is_standard": "Yes",
"name": "__common__",
"ref_doctype": "Stock Ledger Entry",
"report_name": "Batch-Wise Balance History",
"report_type": "Script Report"
},
{
"doctype": "Report",
"name": "Batch-Wise Balance History"
}
]

View File

@@ -0,0 +1,5 @@
wn.require("app/js/sales_trends_filters.js");
wn.query_reports["Delivery Note Trends"] = {
filters: get_filters()
}

View File

@@ -16,7 +16,12 @@
from __future__ import unicode_literals
import webnotes
from controllers.trends import get_columns,get_data
class DocType:
def __init__(self, d, dl):
self.doc, self.doclist = d, dl
def execute(filters=None):
if not filters: filters ={}
data = []
conditions = get_columns(filters, "Delivery Note")
data = get_data(filters, conditions)
return conditions["columns"], data

View File

@@ -0,0 +1,21 @@
[
{
"creation": "2013-06-13 18:42:11",
"docstatus": 0,
"modified": "2013-06-13 18:42:11",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"doctype": "Report",
"is_standard": "Yes",
"name": "__common__",
"ref_doctype": "Delivery Note",
"report_name": "Delivery Note Trends",
"report_type": "Script Report"
},
{
"doctype": "Report",
"name": "Delivery Note Trends"
}
]

View File

View File

@@ -0,0 +1,150 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
import webnotes
from webnotes.utils import flt
def execute(filters=None):
if not filters: filters = {}
columns = get_columns(filters)
item_map = get_item_details()
pl = get_price_list()
last_purchase_rate = get_last_purchase_rate()
bom_rate = get_item_bom_rate()
val_rate_map = get_valuation_rate()
precision = webnotes.conn.get_value("Global Defaults", None, "float_precision") or 2
data = []
for item in sorted(item_map):
data.append([item, item_map[item]["item_name"],
item_map[item]["description"], item_map[item]["stock_uom"],
flt(last_purchase_rate.get(item, 0), precision),
flt(val_rate_map.get(item, 0), precision),
pl.get(item, {}).get("selling"),
pl.get(item, {}).get("buying"),
flt(bom_rate.get(item, 0), precision),
flt(item_map[item]["standard_rate"], precision)
])
return columns, data
def get_columns(filters):
"""return columns based on filters"""
columns = ["Item:Link/Item:100", "Item Name::150", "Description::150", "UOM:Link/UOM:80",
"Last Purchase Rate:Currency:90", "Valuation Rate:Currency:80", "Sales Price List::80",
"Purchase Price List::80", "BOM Rate:Currency:90", "Standard Rate:Currency:100"]
return columns
def get_item_details():
"""returns all items details"""
item_map = {}
for i in webnotes.conn.sql("select name, item_name, description, \
stock_uom, standard_rate from tabItem \
order by item_code", as_dict=1):
item_map.setdefault(i.name, i)
return item_map
def get_price_list():
"""Get selling & buying price list of every item"""
rate = {}
price_list = webnotes.conn.sql("""select parent, selling, buying,
concat(price_list_name, " - ", ref_currency, " ", ref_rate) as price
from `tabItem Price` where docstatus<2""", as_dict=1)
for j in price_list:
if j.price:
if j.selling:
rate.setdefault(j.parent, {}).setdefault("selling", []).append(j.price)
if j.buying:
rate.setdefault(j.parent, {}).setdefault("buying", []).append(j.price)
item_rate_map = {}
for item in rate:
item_rate_map.setdefault(item, {}).setdefault("selling",
", ".join(rate[item].get("selling", [])))
item_rate_map[item]["buying"] = ", ".join(rate[item].get("buying", []))
return item_rate_map
def get_last_purchase_rate():
item_last_purchase_rate_map = {}
query = """select * from (select
result.item_code,
result.purchase_rate
from (
(select
po_item.item_code,
po_item.item_name,
po.transaction_date as posting_date,
po_item.purchase_ref_rate,
po_item.discount_rate,
po_item.purchase_rate
from `tabPurchase Order` po, `tabPurchase Order Item` po_item
where po.name = po_item.parent and po.docstatus = 1)
union
(select
pr_item.item_code,
pr_item.item_name,
pr.posting_date,
pr_item.purchase_ref_rate,
pr_item.discount_rate,
pr_item.purchase_rate
from `tabPurchase Receipt` pr, `tabPurchase Receipt Item` pr_item
where pr.name = pr_item.parent and pr.docstatus = 1)
) result
order by result.item_code asc, result.posting_date desc) result_wrapper
group by item_code"""
for d in webnotes.conn.sql(query, as_dict=1):
item_last_purchase_rate_map.setdefault(d.item_code, d.purchase_rate)
return item_last_purchase_rate_map
def get_item_bom_rate():
"""Get BOM rate of an item from BOM"""
item_bom_map = {}
for b in webnotes.conn.sql("""select item, (total_cost/quantity) as bom_rate
from `tabBOM` where is_active=1 and is_default=1""", as_dict=1):
item_bom_map.setdefault(b.item, flt(b.bom_rate))
return item_bom_map
def get_valuation_rate():
"""Get an average valuation rate of an item from all warehouses"""
item_val_rate_map = {}
for d in webnotes.conn.sql("""select item_code,
sum(actual_qty*valuation_rate)/sum(actual_qty) as val_rate
from tabBin where actual_qty > 0 group by item_code""", as_dict=1):
item_val_rate_map.setdefault(d.item_code, d.val_rate)
return item_val_rate_map

View File

@@ -0,0 +1,21 @@
[
{
"creation": "2013-06-05 11:43:30",
"docstatus": 0,
"modified": "2013-06-05 11:43:30",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"doctype": "Report",
"is_standard": "Yes",
"name": "__common__",
"ref_doctype": "Stock Ledger Entry",
"report_name": "Item Prices",
"report_type": "Script Report"
},
{
"doctype": "Report",
"name": "Item Prices"
}
]

View File

@@ -1,8 +1,8 @@
[
{
"creation": "2013-01-02 14:22:51",
"creation": "2013-02-22 18:01:55",
"docstatus": 0,
"modified": "2013-02-22 15:53:01",
"modified": "2013-05-07 11:50:46",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -10,7 +10,7 @@
"doctype": "Report",
"is_standard": "Yes",
"name": "__common__",
"query": "select\n item.name as \"ID:Link/Item:120\", \n item.item_name as \"Item Name::120\", \n item_price.price_list_name as \"Price List::80\",\n item_price.ref_currency as \"Currency::40\", \n item_price.ref_rate as \"Rate:Currency:80\",\n item.description as \"Description::160\",\n item.item_group as \"Item Group:Link/Item Group:100\",\n item.brand as \"Brand::100\"\nfrom `tabItem` item, `tabItem Price` item_price\nwhere\n item_price.parent = item.name",
"query": "select\n item.name as \"ID:Link/Item:120\", \n item.item_name as \"Item Name::120\", \n item_price.price_list_name as \"Price List::80\",\n item_price.ref_currency as \"Currency::40\", \n item_price.ref_rate as \"Rate:Float:80\",\n item.description as \"Description::160\",\n item.item_group as \"Item Group:Link/Item Group:100\",\n item.brand as \"Brand::100\"\nfrom `tabItem` item, `tabItem Price` item_price\nwhere\n item_price.parent = item.name",
"ref_doctype": "Item",
"report_name": "Item-Wise Price List",
"report_type": "Query Report"

View File

@@ -0,0 +1,16 @@
wn.query_reports["Itemwise Recommended Reorder Level"] = {
"filters": [
{
"fieldname":"from_date",
"label": "From Date",
"fieldtype": "Date",
"default": sys_defaults.year_start_date
},
{
"fieldname":"to_date",
"label": "To Date",
"fieldtype": "Date",
"default": get_today()
}
]
}

View File

@@ -0,0 +1,104 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import webnotes
from webnotes.utils import getdate, flt
def execute(filters=None):
if not filters: filters = {}
float_preceision = webnotes.conn.get_default("float_preceision")
condition =get_condition(filters)
avg_daily_outgoing = 0
diff = ((getdate(filters.get("to_date")) - getdate(filters.get("from_date"))).days)+1
if diff <= 0:
webnotes.msgprint("To Date should not be less than eual to From Date",raise_exception=1)
columns = get_columns()
items = get_item_info()
consumed_item_map = get_consumed_items(condition)
delivered_item_map = get_delivered_items(condition)
data = []
for item in items:
total_outgoing = consumed_item_map.get(item.name, 0)+delivered_item_map.get(item.name,0)
avg_daily_outgoing = flt(total_outgoing/diff, float_preceision)
reorder_level = (avg_daily_outgoing * flt(item.lead_time_days)) + flt(item.min_order_qty)
data.append([item.name, item.item_name, item.description, item.min_order_qty, item.lead_time_days,
consumed_item_map.get(item.name, 0), delivered_item_map.get(item.name,0), total_outgoing,
avg_daily_outgoing, reorder_level])
return columns , data
def get_columns():
return[
"Item:Link/Item:120", "Item name:Data:120", "Description::160",
"Minimum Inventory Level:Float:160", "Lead Time Days:Float:120", "Consumed:Float:120",
"Delivered:Float:120", "Total Outgoing:Float:120", "Avg Daily Outgoing:Float:160",
"Reorder Level:Float:120"
]
def get_item_info():
return webnotes.conn.sql("""select name, item_name, description, min_order_qty,
lead_time_days from tabItem""", as_dict=1)
def get_consumed_items(condition):
cn_items = webnotes.conn.sql("""select se_item.item_code,
sum(se_item.actual_qty) as 'consume_qty'
from `tabStock Entry` se, `tabStock Entry Detail` se_item
where se.name = se_item.parent and se.docstatus = 1
and ifnull(se_item.t_warehouse, '') = '' %s
group by se_item.item_code""" % (condition), as_dict=1)
cn_items_map = {}
for item in cn_items:
cn_items_map.setdefault(item.item_code, item.consume_qty)
return cn_items_map
def get_delivered_items(condition):
dn_items = webnotes.conn.sql("""select dn_item.item_code, sum(dn_item.qty) as dn_qty
from `tabDelivery Note` dn, `tabDelivery Note Item` dn_item
where dn.name = dn_item.parent and dn.docstatus = 1 %s
group by dn_item.item_code""" % (condition), as_dict=1)
si_items = webnotes.conn.sql("""select si_item.item_name, sum(si_item.qty) as si_qty
from `tabSales Invoice` si, `tabSales Invoice Item` si_item
where si.name = si_item.parent and si.docstatus = 1 and
ifnull(si.update_stock, 0) = 1 and ifnull(si.is_pos, 0) = 1 %s
group by si_item.item_name""" % (condition), as_dict=1)
dn_item_map = {}
for item in dn_items:
dn_item_map.setdefault(item.item_code, item.dn_qty)
for item in si_items:
dn_item_map.setdefault(item.item_code, item.si_qty)
return dn_item_map
def get_condition(filters):
conditions = ""
if filters.get("from_date") and filters.get("to_date"):
conditions += " and posting_date between '%s' and '%s'" % (filters["from_date"],filters["to_date"])
else:
webnotes.msgprint("Please set date in from date field",raise_exception=1)
return conditions

View File

@@ -0,0 +1,21 @@
[
{
"creation": "2013-06-07 12:47:22",
"docstatus": 0,
"modified": "2013-06-07 13:03:54",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"doctype": "Report",
"is_standard": "Yes",
"name": "__common__",
"ref_doctype": "Item",
"report_name": "Itemwise Recommended Reorder Level",
"report_type": "Script Report"
},
{
"doctype": "Report",
"name": "Itemwise Recommended Reorder Level"
}
]

View File

@@ -1,8 +1,8 @@
[
{
"creation": "2013-02-21 14:26:49",
"creation": "2013-02-22 18:01:55",
"docstatus": 0,
"modified": "2013-02-22 15:53:01",
"modified": "2013-07-08 11:17:54",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -10,7 +10,7 @@
"doctype": "Report",
"is_standard": "Yes",
"name": "__common__",
"query": "select \n `tabSales Order`.`name` as \"Sales Order:Link/Sales Order:120\",\n `tabSales Order`.`customer` as \"Customer:Link/Customer:120\",\n `tabSales Order`.`status` as \"Status\",\n `tabSales Order`.`transaction_date` as \"Date:Date\",\n `tabSales Order`.`project_name` as \"Project\",\n `tabSales Order Item`.item_code as \"Item:Link/Item:120\",\n `tabSales Order Item`.qty as \"Qty:Float\",\n `tabSales Order Item`.delivered_qty as \"Delivered Qty:Float\",\n (`tabSales Order Item`.qty - ifnull(`tabSales Order Item`.delivered_qty, 0)) as \"Qty to Deliver:Float\",\n `tabSales Order Item`.item_name as \"Item Name::150\",\n `tabSales Order Item`.description as \"Description::200\"\nfrom\n `tabSales Order`, `tabSales Order Item`\nwhere\n `tabSales Order Item`.`parent` = `tabSales Order`.`name`\n and `tabSales Order`.docstatus = 1\n and `tabSales Order`.status != \"Stopped\"\n and ifnull(`tabSales Order Item`.delivered_qty,0) < ifnull(`tabSales Order Item`.qty,0)\norder by `tabSales Order`.transaction_date asc",
"query": "select \n `tabSales Order`.`name` as \"Sales Order:Link/Sales Order:120\",\n `tabSales Order`.`customer` as \"Customer:Link/Customer:120\",\n `tabSales Order`.`transaction_date` as \"Date:Date\",\n `tabSales Order`.`project_name` as \"Project\",\n `tabSales Order Item`.item_code as \"Item:Link/Item:120\",\n `tabSales Order Item`.qty as \"Qty:Float:140\",\n `tabSales Order Item`.delivered_qty as \"Delivered Qty:Float:140\",\n (`tabSales Order Item`.qty - ifnull(`tabSales Order Item`.delivered_qty, 0)) as \"Qty to Deliver:Float:140\",\n `tabSales Order Item`.amount as \"Amount:Float:140\",\n `tabSales Order`.`delivery_date` as \"Expected Delivery Date:Date:120\",\n `tabSales Order Item`.item_name as \"Item Name::150\",\n `tabSales Order Item`.description as \"Description::200\",\n `tabSales Order Item`.item_group as \"Item Group:Link/Item Group:120\"\nfrom\n `tabSales Order`, `tabSales Order Item`\nwhere\n `tabSales Order Item`.`parent` = `tabSales Order`.`name`\n and `tabSales Order`.docstatus = 1\n and `tabSales Order`.status != \"Stopped\"\n and ifnull(`tabSales Order Item`.delivered_qty,0) < ifnull(`tabSales Order Item`.qty,0)\norder by `tabSales Order`.transaction_date asc",
"ref_doctype": "Delivery Note",
"report_name": "Ordered Items To Be Delivered",
"report_type": "Query Report"

View File

@@ -0,0 +1,22 @@
[
{
"creation": "2013-05-06 12:09:05",
"docstatus": 0,
"modified": "2013-05-06 12:22:52",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"doctype": "Report",
"is_standard": "Yes",
"name": "__common__",
"query": "SELECT\n pi.name as \"Purchase Invoice:Link/Purchase Invoice:120\",\n\tpi.posting_date as \"Posting Date:Date:100\",\n\tpi.credit_to as \"Supplier Account:Link/Account:120\",\n\tpi_item.item_code as \"Item Code:Link/Item:120\",\n\tpi_item.description as \"Description:Data:140\",\n\tpi_item.qty as \"Qty:Float:120\",\n\tpi_item.amount as \"Amount:Currency:120\",\n\tpi_item.purchase_order as \"Purchase Order:Link/Purchase Order:120\",\n\tpi_item.purchase_receipt as \"Purchase Receipt:Link/Purchase Receipt:120\",\n\tpr.posting_date as \"PR Posting Date:Date:130\",\n\tpi.company as \"Company:Link/Company:120\"\nFROM\n\t`tabPurchase Invoice` pi, `tabPurchase Invoice Item` pi_item, `tabPurchase Receipt` pr\nWHERE\n\tpi.name = pi_item.parent and pi_item.purchase_receipt = pr.name\n\tand pi.docstatus = 1 and pr.posting_date > pi.posting_date\nORDER BY\n\tpi.name desc",
"ref_doctype": "Purchase Receipt",
"report_name": "Purchase In Transit",
"report_type": "Query Report"
},
{
"doctype": "Report",
"name": "Purchase In Transit"
}
]

View File

@@ -1,16 +1,17 @@
[
{
"creation": "2013-02-21 14:26:49",
"creation": "2013-02-22 18:01:55",
"docstatus": 0,
"modified": "2013-02-22 15:53:01",
"modified": "2013-05-28 16:03:15",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"add_total_row": 1,
"doctype": "Report",
"is_standard": "Yes",
"name": "__common__",
"query": "select \n `tabPurchase Order`.`name` as \"Purchase Order:Link/Purchase Order:120\",\n `tabPurchase Order`.`transaction_date` as \"Date:Date:100\",\n `tabPurchase Order`.`supplier` as \"Supplier:Link/Supplier:120\",\n `tabPurchase Order`.`project_name` as \"Project\",\n `tabPurchase Order Item`.item_code as \"Item Code:Link/Item:120\",\n `tabPurchase Order Item`.qty as \"Qty:Float:100\",\n `tabPurchase Order Item`.received_qty as \"Received Qty:Float:100\", \n (`tabPurchase Order Item`.qty - ifnull(`tabPurchase Order Item`.received_qty, 0)) as \"Qty to Receive:Float:100\",\n `tabPurchase Order Item`.item_name as \"Item Name::150\",\n `tabPurchase Order Item`.description as \"Description::200\"\nfrom\n `tabPurchase Order`, `tabPurchase Order Item`\nwhere\n `tabPurchase Order Item`.`parent` = `tabPurchase Order`.`name`\n and `tabPurchase Order`.docstatus = 1\n and `tabPurchase Order`.status != \"Stopped\"\n and ifnull(`tabPurchase Order Item`.received_qty, 0) < ifnull(`tabPurchase Order Item`.qty, 0)\norder by `tabPurchase Order`.transaction_date asc",
"query": "select \n `tabPurchase Order`.`name` as \"Purchase Order:Link/Purchase Order:120\",\n\t`tabPurchase Order`.`transaction_date` as \"Date:Date:100\",\n\t`tabPurchase Order`.`supplier` as \"Supplier:Link/Supplier:120\",\n\t`tabPurchase Order Item`.`project_name` as \"Project\",\n\t`tabPurchase Order Item`.item_code as \"Item Code:Link/Item:120\",\n\t`tabPurchase Order Item`.qty as \"Qty:Float:100\",\n\t`tabPurchase Order Item`.received_qty as \"Received Qty:Float:100\", \n\t(`tabPurchase Order Item`.qty - ifnull(`tabPurchase Order Item`.received_qty, 0)) as \"Qty to Receive:Float:100\",\n\t`tabPurchase Order Item`.item_name as \"Item Name::150\",\n\t`tabPurchase Order Item`.description as \"Description::200\"\nfrom\n\t`tabPurchase Order`, `tabPurchase Order Item`\nwhere\n\t`tabPurchase Order Item`.`parent` = `tabPurchase Order`.`name`\n\tand `tabPurchase Order`.docstatus = 1\n\tand `tabPurchase Order`.status != \"Stopped\"\n\tand ifnull(`tabPurchase Order Item`.received_qty, 0) < ifnull(`tabPurchase Order Item`.qty, 0)\norder by `tabPurchase Order`.transaction_date asc",
"ref_doctype": "Purchase Receipt",
"report_name": "Purchase Order Items To Be Received",
"report_type": "Query Report"

View File

@@ -0,0 +1,5 @@
wn.require("app/js/purchase_trends_filters.js");
wn.query_reports["Purchase Receipt Trends"] = {
filters: get_filters()
}

View File

@@ -0,0 +1,27 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
import webnotes
from controllers.trends import get_columns,get_data
def execute(filters=None):
if not filters: filters ={}
data = []
conditions = get_columns(filters, "Purchase Receipt")
data = get_data(filters, conditions)
return conditions["columns"], data

View File

@@ -0,0 +1,21 @@
[
{
"creation": "2013-06-13 18:45:44",
"docstatus": 0,
"modified": "2013-06-13 18:45:44",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"doctype": "Report",
"is_standard": "Yes",
"name": "__common__",
"ref_doctype": "Purchase Receipt",
"report_name": "Purchase Receipt Trends",
"report_type": "Script Report"
},
{
"doctype": "Report",
"name": "Purchase Receipt Trends"
}
]

View File

@@ -0,0 +1,23 @@
[
{
"creation": "2013-05-13 16:23:05",
"docstatus": 0,
"modified": "2013-05-13 16:25:08",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"add_total_row": 1,
"doctype": "Report",
"is_standard": "Yes",
"name": "__common__",
"query": "select \n mr.name as \"Material Request:Link/Material Request:120\",\n\tmr.transaction_date as \"Date:Date:100\",\n\tmr_item.item_code as \"Item Code:Link/Item:120\",\n\tmr_item.qty as \"Qty:Float:100\",\n\tmr_item.ordered_qty as \"Transferred Qty:Float:100\", \n\t(mr_item.qty - ifnull(mr_item.ordered_qty, 0)) as \"Qty to Transfer:Float:100\",\n\tmr_item.item_name as \"Item Name::150\",\n\tmr_item.description as \"Description::200\"\nfrom\n\t`tabMaterial Request` mr, `tabMaterial Request Item` mr_item\nwhere\n\tmr_item.parent = mr.name\n\tand mr.material_request_type = \"Transfer\"\n\tand mr.docstatus = 1\n\tand mr.status != \"Stopped\"\n\tand ifnull(mr_item.ordered_qty, 0) < ifnull(mr_item.qty, 0)\norder by mr.transaction_date asc",
"ref_doctype": "Stock Entry",
"report_name": "Requested Items To Be Transferred",
"report_type": "Query Report"
},
{
"doctype": "Report",
"name": "Requested Items To Be Transferred"
}
]

View File

@@ -0,0 +1,18 @@
wn.query_reports["Warehouse-Wise Stock Balance"] = {
"filters": [
{
"fieldname":"from_date",
"label": "From Date",
"fieldtype": "Date",
"width": "80",
"default": sys_defaults.year_start_date,
},
{
"fieldname":"to_date",
"label": "To Date",
"fieldtype": "Date",
"width": "80",
"default": wn.datetime.get_today()
}
]
}

View File

@@ -0,0 +1,98 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
import webnotes
from webnotes.utils import flt
def execute(filters=None):
if not filters: filters = {}
columns = get_columns(filters)
item_map = get_item_details(filters)
iwb_map = get_item_warehouse_map(filters)
data = []
for company in sorted(iwb_map):
for item in sorted(iwb_map[company]):
for wh in sorted(iwb_map[company][item]):
qty_dict = iwb_map[company][item][wh]
data.append([item, item_map[item]["item_name"],
item_map[item]["description"], wh,
qty_dict.opening_qty, qty_dict.in_qty,
qty_dict.out_qty, qty_dict.bal_qty, company
])
return columns, data
def get_columns(filters):
"""return columns based on filters"""
columns = ["Item:Link/Item:100", "Item Name::150", "Description::150", \
"Warehouse:Link/Warehouse:100", "Opening Qty::90", \
"In Qty::80", "Out Qty::80", "Balance Qty::90", "Company:Link/Company:100"]
return columns
def get_conditions(filters):
conditions = ""
if not filters.get("from_date"):
webnotes.msgprint("Please enter From Date", raise_exception=1)
if filters.get("to_date"):
conditions += " and posting_date <= '%s'" % filters["to_date"]
else:
webnotes.msgprint("Please enter To Date", raise_exception=1)
return conditions
#get all details
def get_stock_ledger_entries(filters):
conditions = get_conditions(filters)
return webnotes.conn.sql("""select item_code, warehouse,
posting_date, actual_qty, company
from `tabStock Ledger Entry`
where ifnull(is_cancelled, 'No') = 'No' %s order by item_code, warehouse""" %
conditions, as_dict=1)
def get_item_warehouse_map(filters):
sle = get_stock_ledger_entries(filters)
iwb_map = {}
for d in sle:
iwb_map.setdefault(d.company, {}).setdefault(d.item_code, {}).\
setdefault(d.warehouse, webnotes._dict({\
"opening_qty": 0.0, "in_qty": 0.0, "out_qty": 0.0, "bal_qty": 0.0
}))
qty_dict = iwb_map[d.company][d.item_code][d.warehouse]
if d.posting_date < filters["from_date"]:
qty_dict.opening_qty += flt(d.actual_qty)
elif d.posting_date >= filters["from_date"] and d.posting_date <= filters["to_date"]:
if flt(d.actual_qty) > 0:
qty_dict.in_qty += flt(d.actual_qty)
else:
qty_dict.out_qty += abs(flt(d.actual_qty))
qty_dict.bal_qty += flt(d.actual_qty)
return iwb_map
def get_item_details(filters):
item_map = {}
for d in webnotes.conn.sql("select name, item_name, description from tabItem", as_dict=1):
item_map.setdefault(d.name, d)
return item_map

View File

@@ -0,0 +1,21 @@
[
{
"creation": "2013-06-05 11:00:31",
"docstatus": 0,
"modified": "2013-06-05 11:00:31",
"modified_by": "Administrator",
"owner": "Administrator"
},
{
"doctype": "Report",
"is_standard": "Yes",
"name": "__common__",
"ref_doctype": "Stock Ledger Entry",
"report_name": "Warehouse-Wise Stock Balance",
"report_type": "Script Report"
},
{
"doctype": "Report",
"name": "Warehouse-Wise Stock Balance"
}
]

View File

@@ -35,6 +35,9 @@ def update_entries_after(args, verbose=1):
"posting_time": "12:00"
}
"""
global _exceptions
_exceptions = []
previous_sle = get_sle_before_datetime(args)
qty_after_transaction = flt(previous_sle.get("qty_after_transaction"))

View File

@@ -17,15 +17,16 @@
import webnotes
from webnotes import msgprint, _
import json
from webnotes.utils import flt, cstr
from webnotes.utils import flt, cstr, nowdate, add_days, cint
from webnotes.defaults import get_global_default
from webnotes.utils.email_lib import sendmail
def validate_end_of_life(item_code, end_of_life=None, verbose=1):
if not end_of_life:
end_of_life = webnotes.conn.get_value("Item", item_code, "end_of_life")
from webnotes.utils import getdate, now_datetime, formatdate
if end_of_life and getdate(end_of_life) > now_datetime().date():
if end_of_life and getdate(end_of_life) <= now_datetime().date():
msg = (_("Item") + " %(item_code)s: " + _("reached its end of life on") + \
" %(date)s. " + _("Please check") + ": %(end_of_life_label)s " + \
"in Item master") % {
@@ -194,4 +195,152 @@ def _get_buying_amount(voucher_type, voucher_no, item_row, item_code, warehouse,
buying_amount = previous_stock_value - flt(sle.stock_value)
return buying_amount
return 0.0
return 0.0
def reorder_item():
""" Reorder item if stock reaches reorder level"""
if not hasattr(webnotes, "auto_indent"):
webnotes.auto_indent = webnotes.conn.get_value('Global Defaults', None, 'auto_indent')
if webnotes.auto_indent:
material_requests = {}
bin_list = webnotes.conn.sql("""select item_code, warehouse, projected_qty
from tabBin where ifnull(item_code, '') != '' and ifnull(warehouse, '') != ''
and exists (select name from `tabItem`
where `tabItem`.name = `tabBin`.item_code and
is_stock_item='Yes' and (is_purchase_item='Yes' or is_sub_contracted_item='Yes') and
(ifnull(end_of_life, '')='') or end_of_life > now())""",
as_dict=True)
for bin in bin_list:
#check if re-order is required
item_reorder = webnotes.conn.get("Item Reorder",
{"parent": bin.item_code, "warehouse": bin.warehouse})
if item_reorder:
reorder_level = item_reorder.warehouse_reorder_level
reorder_qty = item_reorder.warehouse_reorder_qty
material_request_type = item_reorder.material_request_type or "Purchase"
else:
reorder_level, reorder_qty = webnotes.conn.get_value("Item", bin.item_code,
["re_order_level", "re_order_qty"])
material_request_type = "Purchase"
if flt(reorder_level) and flt(bin.projected_qty) < flt(reorder_level):
if flt(reorder_level) - flt(bin.projected_qty) > flt(reorder_qty):
reorder_qty = flt(reorder_level) - flt(bin.projected_qty)
company = webnotes.conn.get_value("Warehouse", bin.warehouse, "company") or \
webnotes.defaults.get_defaults()["company"] or \
webnotes.conn.sql("""select name from tabCompany limit 1""")[0][0]
material_requests.setdefault(material_request_type, webnotes._dict()).setdefault(
company, []).append(webnotes._dict({
"item_code": bin.item_code,
"warehouse": bin.warehouse,
"reorder_qty": reorder_qty
})
)
create_material_request(material_requests)
def create_material_request(material_requests):
""" Create indent on reaching reorder level """
mr_list = []
defaults = webnotes.defaults.get_defaults()
exceptions_list = []
for request_type in material_requests:
for company in material_requests[request_type]:
try:
items = material_requests[request_type][company]
if not items:
continue
mr = [{
"doctype": "Material Request",
"company": company,
"fiscal_year": defaults.fiscal_year,
"transaction_date": nowdate(),
"material_request_type": request_type,
"remark": _("This is an auto generated Material Request.") + \
_("""It was raised because the (actual + ordered + indented - reserved)
quantity reaches re-order level when the following record was created""")
}]
for d in items:
item = webnotes.doc("Item", d.item_code)
mr.append({
"doctype": "Material Request Item",
"parenttype": "Material Request",
"parentfield": "indent_details",
"item_code": d.item_code,
"schedule_date": add_days(nowdate(),cint(item.lead_time_days)),
"uom": item.stock_uom,
"warehouse": d.warehouse,
"item_name": item.item_name,
"description": item.description,
"item_group": item.item_group,
"qty": d.reorder_qty,
"brand": item.brand,
})
mr_bean = webnotes.bean(mr)
mr_bean.insert()
mr_bean.submit()
mr_list.append(mr_bean)
except:
if webnotes.message_log:
exceptions_list.append([] + webnotes.message_log)
webnotes.message_log = []
else:
exceptions_list.append(webnotes.getTraceback())
if mr_list:
if not hasattr(webnotes, "reorder_email_notify"):
webnotes.reorder_email_notify = webnotes.conn.get_value('Global Defaults', None,
'reorder_email_notify')
if(webnotes.reorder_email_notify):
send_email_notification(mr_list)
if exceptions_list:
notify_errors(exceptions_list)
def send_email_notification(mr_list):
""" Notify user about auto creation of indent"""
email_list = webnotes.conn.sql_list("""select distinct r.parent
from tabUserRole r, tabProfile p
where p.name = r.parent and p.enabled = 1 and p.docstatus < 2
and r.role in ('Purchase Manager','Material Manager')
and p.name not in ('Administrator', 'All', 'Guest')""")
msg="""<h3>Following Material Requests has been raised automatically \
based on item reorder level:</h3>"""
for mr in mr_list:
msg += "<p><b><u>" + mr.doc.name + """</u></b></p><table class='table table-bordered'><tr>
<th>Item Code</th><th>Warehouse</th><th>Qty</th><th>UOM</th></tr>"""
for item in mr.doclist.get({"parentfield": "indent_details"}):
msg += "<tr><td>" + item.item_code + "</td><td>" + item.warehouse + "</td><td>" + \
cstr(item.qty) + "</td><td>" + cstr(item.uom) + "</td></tr>"
msg += "</table>"
sendmail(email_list, subject='Auto Material Request Generation Notification', msg = msg)
def notify_errors(exceptions_list):
subject = "[Important] [ERPNext] Error(s) while creating Material Requests based on Re-order Levels"
msg = """Dear System Manager,
An error occured for certain Items while creating Material Requests based on Re-order level.
Please rectify these issues:
---
%s
---
Regards,
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)