moved directory structure

This commit is contained in:
Rushabh Mehta
2012-09-24 19:13:42 +05:30
parent e47a6779e9
commit 2fa2f7178d
1637 changed files with 47 additions and 11450 deletions

View File

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

144
stock/doctype/item/item.js Normal file
View File

@@ -0,0 +1,144 @@
// 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) {
// make sensitive fields(has_serial_no, is_stock_item, valuation_method)
// read only if any stock ledger entry exists
if (!doc.__islocal) {
set_field_permlevel("item_code", 1);
}
if ((!doc.__islocal) && (doc.is_stock_item == 'Yes')) {
var callback = function(r, rt) {
if (r.message == 'exists') permlevel = 1;
else permlevel = 0;
set_field_permlevel('has_serial_no', permlevel);
set_field_permlevel('is_stock_item', permlevel);
set_field_permlevel('valuation_method', permlevel);
}
$c_obj(make_doclist(doc.doctype, doc.name),'check_if_sle_exists','',callback);
}
cur_frm.cscript.hide_website_fields(doc);
}
cur_frm.cscript.hide_website_fields = function(doc) {
var website_fields_list = ['page_name', 'website_image', 'web_short_description',
'web_long_description'];
if (doc && cint(doc.show_in_website)) {
unhide_field(website_fields_list);
} else {
hide_field(website_fields_list);
}
}
cur_frm.cscript.show_in_website = function(doc, dt, dn) {
cur_frm.cscript.hide_website_fields(doc);
}
cur_frm.fields_dict['default_bom'].get_query = function(doc) {
//var d = locals[this.doctype][this.docname];
return 'SELECT DISTINCT `tabBOM`.`name` FROM `tabBOM` WHERE `tabBOM`.`item` = "' + doc.item_code + '" AND `tabBOM`.`is_active` = "No" and `tabBOM`.docstatus != 2 AND `tabBOM`.%(key)s LIKE "%s" ORDER BY `tabBOM`.`name` LIMIT 50'
}
// Expense Account
// ---------------------------------
cur_frm.fields_dict['purchase_account'].get_query = function(doc){
return 'SELECT DISTINCT `tabAccount`.`name` FROM `tabAccount` WHERE `tabAccount`.`debit_or_credit`="Debit" AND `tabAccount`.`group_or_ledger`="Ledger" AND `tabAccount`.`docstatus`!=2 AND `tabAccount`.%(key)s LIKE "%s" ORDER BY `tabAccount`.`name` LIMIT 50'
}
// Income Account
// --------------------------------
cur_frm.fields_dict['default_income_account'].get_query = function(doc) {
return 'SELECT DISTINCT `tabAccount`.`name` FROM `tabAccount` WHERE `tabAccount`.`debit_or_credit`="Credit" AND `tabAccount`.`group_or_ledger`="Ledger" AND `tabAccount`.`docstatus`!=2 AND `tabAccount`.`account_type` ="Income Account" AND `tabAccount`.%(key)s LIKE "%s" ORDER BY `tabAccount`.`name` LIMIT 50'
}
// Purchase Cost Center
// -----------------------------
cur_frm.fields_dict['cost_center'].get_query = function(doc) {
return 'SELECT `tabCost Center`.`name` FROM `tabCost Center` WHERE `tabCost Center`.%(key)s LIKE "%s" AND `tabCost Center`.`group_or_ledger` = "Ledger" AND `tabCost Center`.`docstatus`!= 2 ORDER BY `tabCost Center`.`name` ASC LIMIT 50'
}
// Sales Cost Center
// -----------------------------
cur_frm.fields_dict['default_sales_cost_center'].get_query = function(doc) {
return 'SELECT `tabCost Center`.`name` FROM `tabCost Center` WHERE `tabCost Center`.%(key)s LIKE "%s" AND `tabCost Center`.`group_or_ledger` = "Ledger" AND `tabCost Center`.`docstatus`!= 2 ORDER BY `tabCost Center`.`name` ASC LIMIT 50'
}
cur_frm.fields_dict['item_tax'].grid.get_field("tax_type").get_query = function(doc, cdt, cdn) {
return 'SELECT `tabAccount`.`name` FROM `tabAccount` WHERE `tabAccount`.`account_type` in ("Tax", "Chargeable") and `tabAccount`.`docstatus` != 2 and `tabAccount`.%(key)s LIKE "%s" ORDER BY `tabAccount`.`name` DESC LIMIT 50'
}
cur_frm.cscript.tax_type = function(doc, cdt, cdn){
var d = locals[cdt][cdn];
get_server_fields('get_tax_rate',d.tax_type,'item_tax',doc, cdt, cdn, 1);
}
//get query select item group
cur_frm.fields_dict['item_group'].get_query = function(doc,cdt,cdn) {
return 'SELECT `tabItem Group`.`name`,`tabItem Group`.`parent_item_group` FROM `tabItem Group` WHERE `tabItem Group`.`is_group` = "No" AND `tabItem Group`.`docstatus`!= 2 AND `tabItem Group`.%(key)s LIKE "%s" ORDER BY `tabItem Group`.`name` ASC LIMIT 50'
}
// for description from attachment
// takes the first attachment and creates
// a table with both image and attachment in HTML
// in the "alternate_description" field
cur_frm.cscript.add_image = function(doc, dt, dn) {
if(!doc.file_list) {
msgprint('Please attach a file first!');
}
var f = doc.file_list.split('\n')[0];
var fname = f.split(',')[0];
var fid = f.split(',')[1];
if(!in_list(['jpg','jpeg','gif','png'], fname.split('.')[1].toLowerCase())) {
msgprint('File must be of extension jpg, jpeg, gif or png'); return;
}
doc.description_html = repl('<table style="width: 100%; table-layout: fixed;">'+
'<tr><td style="width:110px"><img src="%(imgurl)s" width="100px"></td>'+
'<td>%(desc)s</td></tr>'+
'</table>', {imgurl: wn.urllib.get_file_url(fid), desc:doc.description});
refresh_field('description_html');
}
//===================== Quotation to validation - either customer or lead mandatory ====================
cur_frm.cscript.weight_to_validate = function(doc,cdt,cdn){
if((doc.nett_weight || doc.gross_weight) && !doc.weight_uom)
{
alert('Weight is mentioned,\nPlease mention "Weight UOM" too');
validated=0;
}
}
//===================validation function =================================
cur_frm.cscript.validate = function(doc,cdt,cdn){
cur_frm.cscript.weight_to_validate(doc,cdt,cdn);
}
//===========Fill Default Currency in "Item Prices====================
cur_frm.fields_dict['ref_rate_details'].grid.onrowadd = function(doc, cdt, cdn){
locals[cdt][cdn].ref_currency = sys_defaults.currency;
refresh_field('ref_currency',cdn,'ref_rate_details');
}

240
stock/doctype/item/item.py Normal file
View File

@@ -0,0 +1,240 @@
# 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/>.
# Please edit this list and import only required elements
from __future__ import unicode_literals
import webnotes
from webnotes.utils import add_days, add_months, add_years, cint, cstr, date_diff, default_fields, flt, fmt_money, formatdate, generate_hash, getTraceback, get_defaults, get_first_day, get_last_day, getdate, has_common, month_name, now, nowdate, replace_newlines, sendmail, set_default, str_esc_quote, user_format, validate_email_add
from webnotes.model import db_exists
from webnotes.model.doc import Document, addchild, getchildren, make_autoname
from webnotes.model.doclist import getlist, copy_doclist
from webnotes.model.code import get_obj, get_server_obj, run_server_obj, updatedb, check_syntax
from webnotes import session, form, is_testing, msgprint, errprint
set = webnotes.conn.set
sql = webnotes.conn.sql
get_value = webnotes.conn.get_value
in_transaction = webnotes.conn.in_transaction
convert_to_lists = webnotes.conn.convert_to_lists
# -----------------------------------------------------------------------------------------
class DocType:
def __init__(self, doc, doclist=[]):
self.doc = doc
self.doclist = doclist
def get_tax_rate(self, tax_type):
rate = sql("select tax_rate from tabAccount where name = %s", tax_type)
ret = {
'tax_rate' : rate and flt(rate[0][0]) or 0
}
return ret
def on_update(self):
self.update_page_name()
bin = sql("select stock_uom from `tabBin` where item_code = '%s' " % self.doc.item_code)
if bin 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
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
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
# else set uom_exist as true
uom_exist='true'
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 not cstr(self.doc.stock_uom) in check_list :
child = addchild( self.doc, 'uom_conversion_details', 'UOM Conversion Detail', 1, self.doclist)
child.uom = self.doc.stock_uom
child.conversion_factor = 1
child.save()
self.clear_web_cache()
# 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):
sql("delete from tabBin where item_code='%s'"%(self.doc.item_code))
self.delete_web_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)] 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)])
# 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)
# Check whether Tax Rate is not entered twice for same Tax Type
def check_item_tax(self):
check_list=[]
for d in getlist(self.doclist,'item_tax'):
account_type = sql("select account_type from tabAccount where name = %s",d.tax_type)
account_type = account_type and account_type[0][0] or ''
if account_type not in ['Tax', 'Chargeable']:
msgprint("'%s' is not Tax / Chargeable Account"%(d.tax_type))
raise Exception, "Tax Account validation"
else:
if d.tax_type in check_list:
msgprint("Rate is entered twice for Tax : '%s'." % (d.tax_type))
raise Exception
else:
check_list.append(d.tax_type)
def check_for_active_boms(self, check):
if check in ['Is Active', 'Is Purchase Item']:
bom_mat = 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 = 'Yes' 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(check), cstr(self.doc.name)))
raise Exception
if check == 'Is Active' or ( check == 'Is Manufactured Item' and self.doc.is_sub_contracted_item != 'Yes') or (check == 'Is Sub Contracted Item' and self.doc.is_manufactured_item != 'Yes') :
bom = sql("select name from `tabBOM` where item = '%s' and is_active ='Yes'" % cstr(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(check), cstr(self.doc.name)))
raise Exception
def validate_barcode(self):
if self.doc.barcode:
duplicate = 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):
fl = {'is_manufactured_item' :'Is Manufactured Item',
'is_sub_contracted_item':'Is Sub Contracted Item',
'is_purchase_item' :'Is Purchase Item',
'is_pro_applicable' :'Is Pro Applicable'}
for d in fl:
if cstr(self.doc.fields[d]) != 'Yes':
self.check_for_active_boms(check = fl[d])
self.check_ref_rate_detail()
self.fill_customer_code()
self.check_item_tax()
self.validate_barcode()
if not self.doc.min_order_qty:
self.doc.min_order_qty = 0
self.check_non_asset_warehouse()
if self.doc.is_pro_applicable and self.doc.is_pro_applicable == 'Yes' and self.doc.is_manufactured_item and self.doc.is_manufactured_item != 'Yes':
msgprint("If making Production Order is allowed then, it should also allow to make Bill of Materials. Refer Manufacturing section.")
raise Exception
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.is_stock_item == "Yes" and not self.doc.default_warehouse:
msgprint("As we maintain stock of this item, its better to maintain default warehouse. To add default warehouse please go to 'Inventory' section. It will be fetched automatically while making Sales Order, Delivery Note, etc.. ", 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 = 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
def get_file_details(self, arg = ''):
file = sql("select file_group, description from tabFile where name = %s", eval(arg)['file_name'], as_dict = 1)
ret = {
'file_group' : file and file[0]['file_group'] or '',
'description' : file and file[0]['description'] or ''
}
return ret
def check_if_sle_exists(self):
"""
checks if any stock ledger entry exists for this item
"""
sle = 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):
sql("update tabItem set item_code = %s where name = %s", (newdn, olddn))
def delete_web_cache(self, page_name):
import website.web_cache
website.web_cache.delete_cache(page_name)
def clear_web_cache(self):
if hasattr(self, 'old_page_name') and self.old_page_name and \
self.doc.page_name != self.old_page_name:
self.delete_web_cache(self.doc.page_name)
if self.doc.show_in_website:
import website.web_cache
website.web_cache.create_cache(self.doc.page_name, self.doc.doctype, self.doc.name)
website.web_cache.clear_cache(self.doc.page_name, self.doc.doctype, self.doc.name)
else:
self.delete_web_cache(self.doc.page_name)
def update_page_name(self):
import website.utils
# if same name, do not repeat twice
if self.doc.name == self.doc.item_name or not self.doc.item_name:
page_name = self.doc.name
else:
page_name = self.doc.name + " " + self.doc.item_name
self.doc.page_name = website.utils.page_name(page_name)
webnotes.conn.set_value('Item', self.doc.name, 'page_name', self.doc.page_name)
# no need to check for uniqueness, as name is unique
def prepare_template_args(self):
import markdown2
self.doc.web_description_html = markdown2.markdown(self.doc.description or '',
extras=["wiki-tables"])

1014
stock/doctype/item/item.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,28 @@
// render
wn.doclistviews['Item'] = wn.views.ListView.extend({
init: function(d) {
this._super(d)
this.fields = this.fields.concat([
"`tabItem`.item_name",
"`tabItem`.description",
]);
this.stats = this.stats.concat(['default_warehouse', 'brand']);
},
prepare_data: function(data) {
this._super(data);
data.description = repl("%(item_name)s | %(description)s", data);
if(data.description && data.description.length > 50) {
data.description = '<span title="'+data.description+'">' +
data.description.substr(0,50) + '...</span>';
}
},
columns: [
{width: '3%', content: 'check'},
{width: '5%', content:'avatar'},
{width: '20%', content:'name'},
{width: '60%', content:'description+tags', css: {'color': '#222'}},
{width: '12%', content:'modified', css: {'text-align': 'right', 'color':'#777'}}
]
});

View File

@@ -0,0 +1,79 @@
# 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 unittest
import webnotes
import copy
from webnotes.model.doclist import DocList
from webnotes.model.doc import Document
from webnotes.model.code import get_obj
from webnotes.utils import flt
sql = webnotes.conn.sql
class TestItem(unittest.TestCase):
def setUp(self):
webnotes.conn.begin()
def tearDown(self):
webnotes.conn.rollback()
def testInsert(self):
d = DocList()
count_before = flt(sql("select count(*) from tab"+_doctype)[0][0])
if docok:
for i in docok:
d.doc = i
d.children = None
d.doc.fields['__islocal']=1
d.save(1)
count_after = flt(sql("select count(*) from tab"+_doctype)[0][0])
self.assertTrue(count_before+len(docok)==count_after)
def testFailAssert(self):
if docnotok:
with self.assertRaises(Exception) as context:
d = DocList()
d.doc = docnotok[0]
d.children = None
d.doc.fields['__islocal']=1
d.save(1)
# Test Data
tabOK = [
{'is_purchase_item': None, 'is_pro_applicable': 'No', 'is_manufactured_item': None, 'description': 'Gel Ink', 'default_warehouse': None, 'item_name': 'Gel Ink', 'item_group': 'Ink', 'item_code': 'GELINK', 'is_sub_contracted_item': None, 'is_stock_item': 'Yes', 'stock_uom': 'Nos', 'docstatus': '0'},
{'is_purchase_item': None, 'is_pro_applicable': 'No', 'is_manufactured_item': None, 'description': 'Gel Refill', 'default_warehouse': None, 'item_name': 'Gel Refill', 'item_group': 'Refill', 'item_code': 'GELREF', 'is_sub_contracted_item': None, 'is_stock_item': 'Yes', 'stock_uom': 'Nos', 'docstatus': '0'},
{'is_purchase_item': None, 'is_pro_applicable': 'No', 'is_manufactured_item': None, 'description': 'Gel Pen', 'default_warehouse': None, 'item_name': 'Gel Pen', 'item_group': 'Pen', 'item_code': 'GELPEN', 'is_sub_contracted_item': None, 'is_stock_item': 'Yes', 'stock_uom': 'Nos', 'docstatus': '0'}
]
tabNotOK = [
{'is_purchase_item': None, 'is_pro_applicable': None, 'is_manufactured_item': None, 'description': 'F Ink', 'default_warehouse': None, 'item_name': 'F Ink', 'item_group': 'F Ink', 'item_code': None, 'is_sub_contracted_item': None, 'is_stock_item': 'No', 'stock_uom': 'Nos', 'docstatus': '0'}
]
_doctype = 'Item'
for i in tabOK: i['doctype']=_doctype
for i in tabNotOK: i['doctype']=_doctype
docok = [Document(fielddata=r) for r in tabOK]
docnotok = [Document(fielddata=r) for r in tabNotOK]