Packing Slip and its patches

This commit is contained in:
Anand Doshi 2012-02-02 11:38:15 +05:30
parent 3325d0db74
commit 75d30b803f
19 changed files with 958 additions and 257 deletions

View File

@ -0,0 +1,48 @@
import webnotes
from webnotes.modules.module_manager import reload_doc
def execute():
delete_fields_dn_detail()
deploy_packing_slip()
del_packing_slip_pf()
def delete_fields_dn_detail():
"""
Delete old fields related to packing slip
"""
from webnotes.model import delete_fields
delete_fields({
'Delivery Note': [
'print_packing_slip', 'shipping_mark', 'packed_by',
'packing_checked_by', 'Text', 'pack_size'
],
'Delivery Note Detail': [
'pack_no', 'pack_gross_wt', 'weight_uom',
'pack_nett_wt', 'no_of_packs', 'pack_unit', 'pack_size',
'packed_by', 'packing_checked_by'
]
}, delete=1)
delete_fields({'Item': ['nett_weight', 'gross_weight']}, delete=1)
reload_doc('stock', 'doctype', 'delivery_note')
reload_doc('stock', 'doctype', 'delivery_note_detail')
reload_doc('stock', 'doctype', 'item')
def deploy_packing_slip():
reload_doc('stock', 'doctype', 'packing_slip')
reload_doc('stock', 'doctype', 'packing_slip_detail')
reload_doc('stock', 'Module Def', 'Stock')
reload_doc('stock', 'DocType Mapper', 'Delivery Note-Packing Slip')
def del_packing_slip_pf():
"""
Delete Print Format: 'Delivery Note Packing List Wise'
"""
webnotes.conn.sql("""\
DELETE FROM `tabDocFormat`
WHERE parent='Delivery Note'
AND format='Delivery Note Packing List Wise'""")
from webnotes.model import delete_doc
delete_doc('Print Format', 'Delivery Note Packing List Wise')

View File

@ -60,4 +60,9 @@ patch_list = [
'patch_file': 'cancel_purchase_returned', 'patch_file': 'cancel_purchase_returned',
'description': "Set docstatus = 2 where status = 'Purchase Returned' for serial no" 'description': "Set docstatus = 2 where status = 'Purchase Returned' for serial no"
}, },
{
'patch_module': 'patches.jan_mar_2012',
'patch_file': 'deploy_packing_slip',
'description': "Delete old packing slip fields & print format & deploy new doctypes related to Packing Slip"
},
] ]

View File

@ -5,11 +5,6 @@
// cur_frm.cscript.other_fname - Other Charges fieldname // cur_frm.cscript.other_fname - Other Charges fieldname
// cur_frm.cscript.sales_team_fname - Sales Team fieldname // cur_frm.cscript.sales_team_fname - Sales Team fieldname
function roundNumber(num, dec) {
var result = Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
return result;
}
// ============== Load Default Taxes =================== // ============== Load Default Taxes ===================
cur_frm.cscript.load_taxes = function(doc, cdt, cdn) { cur_frm.cscript.load_taxes = function(doc, cdt, cdn) {
// run if this is not executed from dt_map... // run if this is not executed from dt_map...

View File

@ -0,0 +1,93 @@
# DocType Mapper, Delivery Note-Packing Slip
[
# These values are common in all dictionaries
{
'creation': '2012-02-02 11:35:53',
'docstatus': 0,
'modified': '2012-02-02 11:35:53',
'modified_by': 'Administrator',
'owner': 'Administrator'
},
# These values are common for all Table Mapper Detail
{
'doctype': 'Table Mapper Detail',
'name': '__common__',
'parent': 'Delivery Note-Packing Slip',
'parentfield': 'table_mapper_details',
'parenttype': 'DocType Mapper'
},
# These values are common for all Field Mapper Detail
{
'doctype': 'Field Mapper Detail',
'name': '__common__',
'parent': 'Delivery Note-Packing Slip',
'parentfield': 'field_mapper_details',
'parenttype': 'DocType Mapper'
},
# These values are common for all DocType Mapper
{
'doctype': u'DocType Mapper',
'from_doctype': 'Delivery Note',
'module': 'Stock',
'name': '__common__',
'ref_doc_submitted': 1,
'to_doctype': 'Packing Slip'
},
# DocType Mapper, Delivery Note-Packing Slip
{
'doctype': u'DocType Mapper',
'name': 'Delivery Note-Packing Slip'
},
# Field Mapper Detail
{
'doctype': 'Field Mapper Detail',
'from_field': 'name',
'map': 'Yes',
'match_id': 0,
'to_field': 'delivery_note'
},
# Field Mapper Detail
{
'doctype': 'Field Mapper Detail',
'from_field': 'qty',
'map': 'No',
'match_id': 1,
'to_field': 'qty'
},
# Field Mapper Detail
{
'doctype': 'Field Mapper Detail',
'from_field': 'naming_series',
'map': 'No',
'match_id': 0,
'to_field': 'naming_series'
},
# Table Mapper Detail
{
'doctype': 'Table Mapper Detail',
'from_table': 'Delivery Note',
'match_id': 0,
'to_table': 'Packing Slip',
'validation_logic': 'docstatus=1'
},
# Table Mapper Detail
{
'doctype': 'Table Mapper Detail',
'from_field': 'delivery_note_details',
'from_table': 'Delivery Note Detail',
'match_id': 1,
'to_field': 'item_details',
'to_table': 'Packing Slip Detail',
'validation_logic': 'IFNULL(packed_qty, 0) < IFNULL(qty, 0)'
}
]

View File

@ -5,7 +5,7 @@
{ {
'creation': '2011-07-01 17:40:49', 'creation': '2011-07-01 17:40:49',
'docstatus': 0, 'docstatus': 0,
'modified': '2011-10-10 17:01:34', 'modified': '2012-02-01 15:43:00',
'modified_by': 'Administrator', 'modified_by': 'Administrator',
'owner': 'Administrator' 'owner': 'Administrator'
}, },
@ -88,6 +88,16 @@
'fields': 'status\ntransaction_date\ncustomer\nterritory\ngrand_total\nper_billed' 'fields': 'status\ntransaction_date\ncustomer\nterritory\ngrand_total\nper_billed'
}, },
# Module Def Item
{
'description': 'Generate Packing Slips based on a Delivery Note',
'display_name': 'Packing Slip',
'doc_name': 'Packing Slip',
'doc_type': 'Forms',
'doctype': 'Module Def Item',
'fields': 'delivery_note\nfrom_case_no\nto_case_no\nnet_weight_pkg\ngross_weight_pkg'
},
# Module Def Item # Module Def Item
{ {
'description': 'Record of incoming material from your suppliers', 'description': 'Record of incoming material from your suppliers',

View File

@ -46,6 +46,10 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) {
cur_frm.add_custom_button('Send SMS', cur_frm.cscript['Send SMS']); cur_frm.add_custom_button('Send SMS', cur_frm.cscript['Send SMS']);
unhide_field(['SMS','Send SMS', 'message', 'customer_mobile_no', 'Repair Delivery Note']); unhide_field(['SMS','Send SMS', 'message', 'customer_mobile_no', 'Repair Delivery Note']);
} }
if(doc.docstatus==1) {
cur_frm.add_custom_button('Make Packing Slip', cur_frm.cscript['Make Packing Slip']);
}
set_print_hide(doc, cdt, cdn); set_print_hide(doc, cdt, cdn);
} }
@ -280,6 +284,23 @@ cur_frm.cscript['Make Installation Note'] = function() {
msgprint("Item installation is already completed") msgprint("Item installation is already completed")
} }
//-----------------------------------Make Sales Invoice----------------------------------------------
cur_frm.cscript['Make Packing Slip'] = function() {
var doc = cur_frm.doc
n = createLocal('Packing Slip');
$c('dt_map', args={
'docs':compress_doclist([locals['Packing Slip'][n]]),
'from_doctype':doc.doctype,
'to_doctype':'Packing Slip',
'from_docname':doc.name,
'from_to_list':"[['Delivery Note','Packing Slip'],['Delivery Note Detail','Packing Slip Detail']]"
}, function(r,rt) {
loaddoc('Packing Slip', n);
}
);
}
//get query select Territory //get query select Territory
//======================================================================================================================= //=======================================================================================================================
cur_frm.fields_dict['territory'].get_query = function(doc,cdt,cdn) { cur_frm.fields_dict['territory'].get_query = function(doc,cdt,cdn) {

View File

@ -171,9 +171,6 @@ class DocType(TransactionBase):
self.doc.in_words = sales_com_obj.get_total_in_words(dcc, self.doc.rounded_total) self.doc.in_words = sales_com_obj.get_total_in_words(dcc, self.doc.rounded_total)
self.doc.in_words_export = sales_com_obj.get_total_in_words(self.doc.currency, self.doc.rounded_total_export) self.doc.in_words_export = sales_com_obj.get_total_in_words(self.doc.currency, self.doc.rounded_total_export)
# ::::::: Set Net Weight of each Packing
self.update_pack_nett_weight()
self.print_packing_slip()
# ::::::: Set actual qty for each item in selected warehouse ::::::: # ::::::: Set actual qty for each item in selected warehouse :::::::
self.update_current_stock() self.update_current_stock()
# :::::: set DN status ::::::: # :::::: set DN status :::::::
@ -340,6 +337,7 @@ class DocType(TransactionBase):
self.update_stock_ledger(update_stock = -1) self.update_stock_ledger(update_stock = -1)
# :::::: set DN status ::::::: # :::::: set DN status :::::::
set(self.doc, 'status', 'Cancelled') set(self.doc, 'status', 'Cancelled')
self.cancel_packing_slips()
# ******************** Check Next DocStatus ************************** # ******************** Check Next DocStatus **************************
@ -355,6 +353,23 @@ class DocType(TransactionBase):
raise Exception , "Validation Error." raise Exception , "Validation Error."
def cancel_packing_slips(self):
"""
Cancel submitted packing slips related to this delivery note
"""
res = webnotes.conn.sql("""\
SELECT name, count(*) FROM `tabPacking Slip`
WHERE delivery_note = %s AND docstatus = 1
""", self.doc.name)
if res and res[0][1]>0:
from webnotes.model.doclist import DocList
for r in res:
ps = DocList(dt='Packing Slip', dn=r[0])
ps.cancel()
webnotes.msgprint("%s Packing Slip(s) Cancelled" % res[0][1])
# UPDATE STOCK LEDGER # UPDATE STOCK LEDGER
# ================================================================================================= # =================================================================================================
def update_stock_ledger(self, update_stock, is_stopped = 0): def update_stock_ledger(self, update_stock, is_stopped = 0):
@ -432,84 +447,3 @@ class DocType(TransactionBase):
def repair_delivery_note(self): def repair_delivery_note(self):
get_obj('Sales Common', 'Sales Common').repair_curr_doctype_details(self) get_obj('Sales Common', 'Sales Common').repair_curr_doctype_details(self)
# Packing Slip Related
# ==========================================
def update_pack_nett_weight(self):
for d in getlist(self.doclist, 'delivery_note_details'):
if d.item_code and not d.pack_nett_wt:
item_wt = sql("select nett_weight from `tabItem` where name = %s", (d.item_code))
d.pack_nett_wt = item_wt and flt(item_wt[0][0]) or 0
# ==========================================
def get_header(self, so_no, shipping_mark):
header = '''
<div align="center">[HEADER GOES HERE]</div>
<div><center><h2>Packing Slip</h2></center></div>
<table width="100%" class="large_font">
<tr>
<td width="20%">ORDER NO.</td>
<td width="30%">'''+cstr(so_no)+'''</td>
<td width="20%">SHIPPING MARKS</td>
<td width="30%">'''+cstr(shipping_mark)+'''</td>
</tr>
</table>''';
return header
def get_footer(self, row, tot_nett, tot_gross):
footer = '''
<table style="page-break-after:always" width="100%" class="large_font">
<tr>
<td>CASE NO</td><td>'''+cstr(row.pack_no)+'''</td>
<td>NETT WT</td><td>'''+cstr(tot_nett)+'''</td>
<td>CHECKED BY</td><td>'''+cstr(row.packing_checked_by)+'''</td>
</tr>
<tr>
<td>SIZE</td><td>'''+cstr(row.pack_size)+'''</td>
<td>GROSS WT</td><td>'''+cstr(tot_gross)+'''</td>
<td>PACKED BY</td><td>'''+cstr(row.packed_by)+'''</td>
</tr>
</table>'''
return footer
def print_packing_slip(self):
plist = {}
for d in getlist(self.doclist, 'delivery_note_details'):
if not plist.has_key(cstr(d.pack_no)):
plist[cstr(d.pack_no)] = [d]
else:
plist.get(cstr(d.pack_no)).append(d)
html=''
for d in sorted(plist.keys()):
tot_nett_wt,tot_gross_wt=0,0
# header
html += self.get_header(self.doc.sales_order_no, self.doc.shipping_mark)
# item table header
html += '''
<table class="cust_tbl" width="100%">
<tr>
<td><b>SR.NO.</b></td><td><b>CS.NO.</b></td><td><b>DESCRIPTION</b></td>
<td><b>QUANTITY</b></td><td><b>WEIGHT</b></td>
</tr>'''
# item table data
sr_no = 1
for r in plist.get(d):
html += '<tr><td>'+cstr(sr_no)+'</td><td>'+r.item_code+'</td><td>'+r.description+'</td><td>'+cstr(r.qty)+'</td><td>'+cstr(r.pack_nett_wt)+'</td></tr>'
tot_nett_wt += flt(r.pack_nett_wt)
tot_gross_wt += flt(r.pack_gross_wt)
sr_no += 1
html += '</table>'
# footer
html += self.get_footer(r, tot_nett_wt, tot_gross_wt)
self.doc.print_packing_slip=html

View File

@ -5,7 +5,7 @@
{ {
'creation': '2011-04-18 15:58:20', 'creation': '2011-04-18 15:58:20',
'docstatus': 0, 'docstatus': 0,
'modified': '2012-01-09 16:52:43', 'modified': '2012-01-30 16:52:12',
'modified_by': 'Administrator', 'modified_by': 'Administrator',
'owner': 'Administrator' 'owner': 'Administrator'
}, },
@ -21,7 +21,7 @@
# These values are common for all DocType # These values are common for all DocType
{ {
'_last_update': '1326105502', '_last_update': '1326273792',
'colour': 'White:FFF', 'colour': 'White:FFF',
'default_print_format': 'Standard', 'default_print_format': 'Standard',
'doctype': 'DocType', 'doctype': 'DocType',
@ -37,7 +37,7 @@
'show_in_menu': 0, 'show_in_menu': 0,
'subject': 'To %(customer_name)s on %(transaction_date)s | %(per_billed)s% billed', 'subject': 'To %(customer_name)s on %(transaction_date)s | %(per_billed)s% billed',
'tag_fields': 'billing_status', 'tag_fields': 'billing_status',
'version': 463 'version': 464
}, },
# These values are common for all DocFormat # These values are common for all DocFormat
@ -1433,53 +1433,5 @@
'options': 'repair_delivery_note', 'options': 'repair_delivery_note',
'permlevel': 0, 'permlevel': 0,
'print_hide': 1 'print_hide': 1
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'print_packing_slip',
'fieldtype': 'Text',
'hidden': 1,
'in_filter': 0,
'label': 'Print Packing Slip',
'permlevel': 0,
'print_hide': 1
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'shipping_mark',
'fieldtype': 'Text',
'label': 'Shipping Mark',
'permlevel': 0
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'packed_by',
'fieldtype': 'Text',
'label': 'Packed By',
'permlevel': 0
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'packing_checked_by',
'fieldtype': 'Text',
'label': 'Packing Checked By',
'permlevel': 0
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'pack_size',
'fieldtype': 'Text',
'label': 'Pack Size',
'permlevel': 0
} }
] ]

View File

@ -5,7 +5,7 @@
{ {
'creation': '2010-08-08 17:08:58', 'creation': '2010-08-08 17:08:58',
'docstatus': 0, 'docstatus': 0,
'modified': '2011-10-18 16:32:44', 'modified': '2012-02-01 16:08:06',
'modified_by': 'Administrator', 'modified_by': 'Administrator',
'owner': 'Administrator' 'owner': 'Administrator'
}, },
@ -23,7 +23,7 @@
'section_style': 'Tray', 'section_style': 'Tray',
'server_code_error': ' ', 'server_code_error': ' ',
'show_in_menu': 0, 'show_in_menu': 0,
'version': 43 'version': 51
}, },
# These values are common for all DocField # These values are common for all DocField
@ -289,104 +289,6 @@
'width': '150px' 'width': '150px'
}, },
# DocField
{
'doctype': 'DocField',
'fieldname': 'pack_no',
'fieldtype': 'Data',
'label': 'Pack No',
'permlevel': 0,
'print_hide': 1
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'pack_gross_wt',
'fieldtype': 'Float',
'label': 'Pack Gross Wt',
'permlevel': 0,
'print_hide': 1
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'weight_uom',
'fieldtype': 'Link',
'label': 'Weight UOM',
'options': 'UOM',
'permlevel': 0,
'print_hide': 1
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'pack_nett_wt',
'fieldtype': 'Float',
'label': 'Pack Nett Wt',
'permlevel': 0,
'print_hide': 1
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'no_of_packs',
'fieldtype': 'Int',
'label': 'No of Packs',
'oldfieldname': 'no_of_packs',
'oldfieldtype': 'Int',
'permlevel': 0,
'print_hide': 1,
'width': '100px'
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'pack_unit',
'fieldtype': 'Data',
'label': 'Pack Unit',
'oldfieldname': 'pack_unit',
'oldfieldtype': 'Data',
'permlevel': 0,
'print_hide': 1,
'width': '100px'
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'pack_size',
'fieldtype': 'Data',
'label': 'Pack Size',
'no_copy': 0,
'permlevel': 0,
'print_hide': 1
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'packed_by',
'fieldtype': 'Data',
'label': 'Packed By',
'permlevel': 0,
'print_hide': 1
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'packing_checked_by',
'fieldtype': 'Data',
'label': 'Packing Checked By',
'permlevel': 0,
'print_hide': 1
},
# DocField # DocField
{ {
'doctype': 'DocField', 'doctype': 'DocField',
@ -504,6 +406,20 @@
'print_hide': 1 'print_hide': 1
}, },
# DocField
{
'allow_on_submit': 1,
'colour': 'White:FFF',
'default': '0',
'doctype': 'DocField',
'fieldname': 'packed_qty',
'fieldtype': 'Currency',
'label': 'Packed Quantity',
'no_copy': 1,
'permlevel': 1,
'print_hide': 1
},
# DocField # DocField
{ {
'allow_on_submit': 1, 'allow_on_submit': 1,

View File

@ -5,14 +5,14 @@
{ {
'creation': '2010-08-08 17:09:05', 'creation': '2010-08-08 17:09:05',
'docstatus': 0, 'docstatus': 0,
'modified': '2012-01-17 18:39:39', 'modified': '2012-01-30 17:34:23',
'modified_by': 'Administrator', 'modified_by': 'Administrator',
'owner': 'Administrator' 'owner': 'Administrator'
}, },
# These values are common for all DocType # These values are common for all DocType
{ {
'_last_update': '1325570647', '_last_update': '1326963484',
'allow_attach': 1, 'allow_attach': 1,
'allow_trash': 1, 'allow_trash': 1,
'autoname': 'field:item_code', 'autoname': 'field:item_code',
@ -29,7 +29,7 @@
'show_in_menu': 0, 'show_in_menu': 0,
'subject': '%(item_name)s', 'subject': '%(item_name)s',
'tag_fields': 'item_group', 'tag_fields': 'item_group',
'version': 164 'version': 165
}, },
# These values are common for all DocField # These values are common for all DocField
@ -467,19 +467,11 @@
# DocField # DocField
{ {
'description': 'Net Weight of each Item',
'doctype': 'DocField', 'doctype': 'DocField',
'fieldname': 'nett_weight', 'fieldname': 'net_weight',
'fieldtype': 'Float', 'fieldtype': 'Float',
'label': 'Nett Weight', 'label': 'Net Weight',
'permlevel': 0
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'gross_weight',
'fieldtype': 'Float',
'label': 'Gross Weight',
'permlevel': 0 'permlevel': 0
}, },

View File

@ -0,0 +1,123 @@
cur_frm.fields_dict['delivery_note'].get_query = function(doc, cdt, cdn) {
return 'SELECT name FROM `tabDelivery Note` WHERE docstatus=1 AND %(key)s LIKE "%s"';
}
cur_frm.fields_dict['item_details'].grid.get_field('item_code').get_query = function(doc, cdt, cdn) {
return 'SELECT name, description FROM `tabItem` WHERE name IN ( \
SELECT item_code FROM `tabDelivery Note Detail` \
WHERE parent="' + doc.delivery_note + '") AND %(key)s LIKE "%s" LIMIT 50';
}
// Fetch item details
cur_frm.cscript.item_code = function(doc, cdt, cdn) {
if(locals[cdt][cdn].item_code) {
$c_obj(make_doclist(cdt, cdn), 'get_item_details', doc.delivery_note, function(r, rt) {
if(r.exc) {
msgprint(r.exc);
} else {
refresh_field('item_details');
}
});
}
}
cur_frm.cscript.onload = function(doc, cdt, cdn) {
if(doc.delivery_note) {
var ps_detail = getchildren('Packing Slip Detail', doc.name, 'item_details');
if(!(flt(ps_detail[0].net_weight) && cstr(ps_detail[0].weight_uom))) {
cur_frm.cscript.update_item_details(doc);
refresh_field('naming_series');
}
}
}
cur_frm.cscript.update_item_details = function(doc) {
$c_obj(make_doclist(doc.doctype, doc.name), 'update_item_details', '', function(r, rt) {
if(r.exc) {
msgprint(r.exc);
} else {
refresh_field('item_details');
}
});
}
cur_frm.cscript.validate = function(doc, cdt, cdn) {
cur_frm.cscript.validate_case_nos(doc);
cur_frm.cscript.validate_calculate_item_details(doc);
}
// To Case No. cannot be less than From Case No.
cur_frm.cscript.validate_case_nos = function(doc) {
doc = locals[doc.doctype][doc.name];
if(cint(doc.from_case_no)==0) {
msgprint("Case No. cannot be 0")
validated = false;
} else if(!cint(doc.to_case_no)) {
doc.to_case_no = doc.from_case_no;
refresh_field('to_case_no');
} else if(cint(doc.to_case_no) < cint(doc.from_case_no)) {
msgprint("'To Case No.' cannot be less than 'From Case No.'");
validated = false;
}
}
cur_frm.cscript.validate_calculate_item_details = function(doc) {
doc = locals[doc.doctype][doc.name];
var ps_detail = getchildren('Packing Slip Detail', doc.name, 'item_details');
cur_frm.cscript.validate_duplicate_items(doc, ps_detail);
cur_frm.cscript.calc_net_total_pkg(doc, ps_detail);
}
// Do not allow duplicate items i.e. items with same item_code
// Also check for 0 qty
cur_frm.cscript.validate_duplicate_items = function(doc, ps_detail) {
for(var i=0; i<ps_detail.length; i++) {
for(var j=0; j<ps_detail.length; j++) {
if(i!=j && ps_detail[i].item_code==ps_detail[j].item_code) {
msgprint("You have entered duplicate items. Please rectify and try again.");
validated = false;
return;
}
}
if(flt(ps_detail[i].qty)<=0) {
msgprint("Invalid quantity specified for item " + ps_detail[i].item_code +
". Quantity should be greater than 0.");
validated = false;
}
}
}
// Calculate Net Weight of Package
cur_frm.cscript.calc_net_total_pkg = function(doc, ps_detail) {
var net_weight_pkg = 0;
doc.net_weight_uom = ps_detail?ps_detail[0].weight_uom:'';
doc.gross_weight_uom = doc.net_weight_uom;
for(var i=0; i<ps_detail.length; i++) {
var item = ps_detail[i];
if(item.weight_uom != doc.net_weight_uom) {
msgprint("Different UOM for items will lead to incorrect \
(Total) Net Weight value. Make sure that Net Weight of each item is \
in the same UOM.")
validated = false;
}
net_weight_pkg += flt(item.net_weight) * flt(item.qty);
}
doc.net_weight_pkg = roundNumber(net_weight_pkg, 2);
if(!flt(doc.gross_weight_pkg)) {
doc.gross_weight_pkg = doc.net_weight_pkg
}
refresh_many(['net_weight_pkg', 'net_weight_uom', 'gross_weight_uom', 'gross_weight_pkg']);
}

View File

@ -0,0 +1,156 @@
import webnotes
from webnotes.utils import flt, cint
class DocType:
def __init__(self, d, dl):
self.doc, self.doclist = d, dl
def validate(self):
"""
* Validate existence of submitted Delivery Note
* Case nos do not overlap
* Check if packed qty doesn't exceed actual qty of delivery note
It is necessary to validate case nos before checking quantity
"""
self.validate_delivery_note()
self.validate_case_nos()
self.validate_qty()
def validate_delivery_note(self):
"""
Validates if delivery note has status as submitted
"""
res = webnotes.conn.sql("""\
SELECT docstatus FROM `tabDelivery Note`
WHERE name=%(delivery_note)s
""", self.doc.fields)
if not(res and res[0][0]==1):
webnotes.msgprint("""Invalid Delivery Note. Delivery Note should exist
and should be submitted. Please rectify and try again.""", raise_exception=1)
def validate_case_nos(self):
"""
Validate if case nos overlap
If they do, recommend next case no.
"""
res = webnotes.conn.sql("""\
SELECT name FROM `tabPacking Slip`
WHERE delivery_note = %(delivery_note)s AND docstatus = 1 AND
(from_case_no BETWEEN %(from_case_no)s AND %(to_case_no)s
OR to_case_no BETWEEN %(from_case_no)s AND %(to_case_no)s)\
""", self.doc.fields)
if res:
recommended_case_no = webnotes.conn.sql("""\
SELECT MAX(to_case_no) FROM `tabPacking Slip`
WHERE delivery_note = %(delivery_note)s AND docstatus=1""", self.doc.fields)
webnotes.msgprint("""Case No(s). already in use. Please rectify and try again.
Recommended <b>From Case No. = %s</b>""" % (cint(recommended_case_no[0][0]) + 1),
raise_exception=1)
def validate_qty(self):
"""
Check packed qty across packing slips and delivery note
"""
# Get Delivery Note Details, Item Quantity Dict and No. of Cases for this Packing slip
dn_details, ps_item_qty, no_of_cases = self.get_details_for_packing()
for item in dn_details:
new_packed_qty = (flt(ps_item_qty[item['item_code']]) * no_of_cases) + flt(item['packed_qty'])
if new_packed_qty > flt(item['qty']):
self.recommend_new_qty(item, ps_item_qty, no_of_cases)
def get_details_for_packing(self):
"""
Returns
* 'Delivery Note Details' query result as a list of dict
* Item Quantity dict of current packing slip doc
* No. of Cases of this packing slip
"""
item_codes = ", ".join([('"' + d.item_code + '"') for d in self.doclist])
res = webnotes.conn.sql("""\
SELECT item_code, IFNULL(SUM(qty), 0) as qty, IFNULL(packed_qty, 0) as packed_qty, stock_uom
FROM `tabDelivery Note Detail`
WHERE parent = "%s" AND item_code IN (%s)
GROUP BY item_code""" % (self.doc.delivery_note, item_codes), as_dict=1)
ps_item_qty = dict([[d.item_code, d.qty] for d in self.doclist])
no_of_cases = cint(self.doc.to_case_no) - cint(self.doc.from_case_no) + 1
return res, ps_item_qty, no_of_cases
def recommend_new_qty(self, item, ps_item_qty, no_of_cases):
"""
Recommend a new quantity and raise a validation exception
"""
item['recommended_qty'] = (flt(item['qty']) - flt(item['packed_qty'])) / no_of_cases
item['specified_qty'] = flt(ps_item_qty[item['item_code']])
webnotes.msgprint("""\
Invalid Quantity specified (%(specified_qty)s %(stock_uom)s).
%(packed_qty)s out of %(qty)s %(stock_uom)s already packed for %(item_code)s.
<b>Recommended quantity for %(item_code)s = %(recommended_qty)s \
%(stock_uom)s</b>""" % item, raise_exception=1)
def on_submit(self):
"""
* Update packed qty for all items
"""
self.update_packed_qty(event='submit')
def on_cancel(self):
"""
* Update packed qty for all items
"""
self.update_packed_qty(event='cancel')
def update_packed_qty(self, event=''):
"""
Updates packed qty for all items
"""
if event not in ['submit', 'cancel']:
raise Exception('update_packed_quantity can only be called on submit or cancel')
# Get Delivery Note Details, Item Quantity Dict and No. of Cases for this Packing slip
dn_details, ps_item_qty, no_of_cases = self.get_details_for_packing()
for item in dn_details:
if event=='submit':
new_packed_qty = flt(item['packed_qty']) + (flt(ps_item_qty[item['item_code']]) * no_of_cases)
elif event=='cancel':
new_packed_qty = flt(item['packed_qty']) - (flt(ps_item_qty[item['item_code']]) * no_of_cases)
if (new_packed_qty < 0) or (new_packed_qty > flt(item['qty'])):
webnotes.msgprint("Invalid new packed quantity for item %s. \
Please try again or contact support@erpnext.com" % item['item_code'], raise_exception=1)
webnotes.conn.sql("""\
UPDATE `tabDelivery Note Detail`
SET packed_qty = %s
WHERE parent = %s AND item_code = %s""",
(new_packed_qty, self.doc.delivery_note, item['item_code']))
def update_item_details(self):
"""
Fill empty columns in Packing Slip Detail
"""
from webnotes.model.code import get_obj
for d in self.doclist:
psd_obj = get_obj(doc=d)
psd_obj.get_item_details(self.doc.delivery_note)

View File

@ -0,0 +1,314 @@
# DocType, Packing Slip
[
# These values are common in all dictionaries
{
'creation': '2012-01-30 12:13:10',
'docstatus': 0,
'modified': '2012-02-02 10:37:15',
'modified_by': 'Administrator',
'owner': 'Administrator'
},
# These values are common for all DocType
{
'_last_update': '1328091392',
'autoname': 'PS.#######',
'colour': 'White:FFF',
'doctype': 'DocType',
'document_type': 'Transaction',
'is_transaction_doc': 1,
'module': 'Stock',
'name': '__common__',
'read_only_onload': 1,
'search_fields': 'delivery_note',
'section_style': 'Simple',
'show_in_menu': 0,
'subject': '[%(delivery_note)s] Case Nos: %(from_case_no)s - %(to_case_no)s | Net Weight: %(net_weight_pkg)s %(net_weight_uom)s | Gross Weight: %(gross_weight_pkg)s %(gross_weight_uom)s',
'version': 40
},
# These values are common for all DocField
{
'doctype': 'DocField',
'name': '__common__',
'parent': 'Packing Slip',
'parentfield': 'fields',
'parenttype': 'DocType'
},
# These values are common for all DocPerm
{
'doctype': 'DocPerm',
'name': '__common__',
'parent': 'Packing Slip',
'parentfield': 'permissions',
'parenttype': 'DocType',
'read': 1
},
# DocType, Packing Slip
{
'doctype': 'DocType',
'name': 'Packing Slip'
},
# DocPerm
{
'amend': 1,
'cancel': 1,
'create': 1,
'doctype': 'DocPerm',
'permlevel': 0,
'role': 'Material User',
'submit': 1,
'write': 1
},
# DocPerm
{
'amend': 1,
'cancel': 1,
'create': 1,
'doctype': 'DocPerm',
'permlevel': 0,
'role': 'Sales User',
'submit': 1,
'write': 1
},
# DocPerm
{
'amend': 1,
'cancel': 1,
'create': 1,
'doctype': 'DocPerm',
'permlevel': 0,
'role': 'Material Master Manager',
'submit': 1,
'write': 1
},
# DocPerm
{
'amend': 1,
'cancel': 1,
'create': 1,
'doctype': 'DocPerm',
'permlevel': 0,
'role': 'Material Manager',
'submit': 1,
'write': 1
},
# DocPerm
{
'amend': 1,
'cancel': 1,
'create': 1,
'doctype': 'DocPerm',
'permlevel': 0,
'role': 'Sales Manager',
'submit': 1,
'write': 1
},
# DocPerm
{
'doctype': 'DocPerm',
'permlevel': 1,
'role': 'All'
},
# DocField
{
'doctype': 'DocField',
'fieldtype': 'Section Break',
'label': 'Packing Slip Details',
'permlevel': 0
},
# DocField
{
'doctype': 'DocField',
'fieldtype': 'Column Break',
'permlevel': 0
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'delivery_note',
'fieldtype': 'Link',
'label': 'Delivery Note',
'options': 'Delivery Note',
'permlevel': 0,
'reqd': 1
},
# DocField
{
'doctype': 'DocField',
'fieldtype': 'Column Break',
'permlevel': 0
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'naming_series',
'fieldtype': 'Select',
'label': 'Series',
'no_copy': 0,
'options': 'PS',
'permlevel': 0,
'print_hide': 1,
'reqd': 1
},
# DocField
{
'colour': 'White:FFF',
'doctype': 'DocField',
'fieldtype': 'Section Break',
'permlevel': 0
},
# DocField
{
'doctype': 'DocField',
'fieldtype': 'Column Break',
'permlevel': 0
},
# DocField
{
'colour': 'White:FFF',
'doctype': 'DocField',
'fieldname': 'from_case_no',
'fieldtype': 'Data',
'label': 'From Case No.',
'no_copy': 1,
'permlevel': 0,
'reqd': 1,
'width': '50px'
},
# DocField
{
'doctype': 'DocField',
'fieldtype': 'Column Break',
'permlevel': 0
},
# DocField
{
'colour': 'White:FFF',
'doctype': 'DocField',
'fieldname': 'to_case_no',
'fieldtype': 'Data',
'label': 'To Case No.',
'no_copy': 1,
'permlevel': 0,
'width': '50px'
},
# DocField
{
'doctype': 'DocField',
'fieldtype': 'Section Break',
'label': 'Package Item Details',
'permlevel': 0
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'item_details',
'fieldtype': 'Table',
'label': 'Items',
'options': 'Packing Slip Detail',
'permlevel': 0
},
# DocField
{
'doctype': 'DocField',
'fieldtype': 'Section Break',
'label': 'Package Weight Details',
'permlevel': 0
},
# DocField
{
'colour': 'White:FFF',
'doctype': 'DocField',
'fieldname': 'net_weight_pkg',
'fieldtype': 'Currency',
'label': 'Net Weight',
'no_copy': 1,
'permlevel': 1
},
# DocField
{
'colour': 'White:FFF',
'doctype': 'DocField',
'fieldname': 'net_weight_uom',
'fieldtype': 'Data',
'label': 'Net Weight UOM',
'no_copy': 1,
'permlevel': 1
},
# DocField
{
'doctype': 'DocField',
'fieldtype': 'Column Break',
'permlevel': 0
},
# DocField
{
'colour': 'White:FFF',
'doctype': 'DocField',
'fieldname': 'gross_weight_pkg',
'fieldtype': 'Currency',
'label': 'Gross Weight',
'no_copy': 1,
'permlevel': 0
},
# DocField
{
'colour': 'White:FFF',
'doctype': 'DocField',
'fieldname': 'gross_weight_uom',
'fieldtype': 'Link',
'label': 'Gross Weight UOM',
'no_copy': 1,
'options': 'UOM',
'permlevel': 0
},
# DocField
{
'depends_on': 'eval:doc.amended_from',
'doctype': 'DocField',
'fieldtype': 'Section Break',
'label': 'Misc Details',
'permlevel': 0
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'amended_from',
'fieldtype': 'Link',
'label': 'Amended From',
'no_copy': 1,
'options': 'Packing Slip',
'permlevel': 1,
'print_hide': 1
}
]

View File

@ -0,0 +1,29 @@
import webnotes
class DocType:
def __init__(self, d, dl):
self.doc, self.doclist = d, dl
def get_item_details(self, delivery_note):
res = webnotes.conn.sql("""\
SELECT item_name, SUM(IFNULL(qty, 0)) as total_qty,
IFNULL(packed_qty, 0) as packed_qty, stock_uom
FROM `tabDelivery Note Detail`
WHERE parent=%s AND item_code=%s GROUP BY item_code""",
(delivery_note, self.doc.item_code), as_dict=1)
if res and len(res)>0:
res = res[0]
res['qty'] = res['total_qty'] - res['packed_qty']
res['qty'] = self.doc.qty or (res['qty']>=0 and res['qty'] or 0)
del res['total_qty']
del res['packed_qty']
self.doc.fields.update(res)
res = webnotes.conn.sql("""\
SELECT net_weight, weight_uom FROM `tabItem`
WHERE name=%s""", self.doc.item_code, as_dict=1)
if res and len(res)>0:
res = res[0]
self.doc.fields.update(res)

View File

@ -0,0 +1,113 @@
# DocType, Packing Slip Detail
[
# These values are common in all dictionaries
{
'creation': '2012-01-30 17:40:50',
'docstatus': 0,
'modified': '2012-01-31 13:15:40',
'modified_by': 'Administrator',
'owner': 'Administrator'
},
# These values are common for all DocType
{
'autoname': 'PSD/.#######',
'colour': 'White:FFF',
'doctype': 'DocType',
'istable': 1,
'module': 'Stock',
'name': '__common__',
'section_style': 'Simple',
'show_in_menu': 0,
'version': 9
},
# These values are common for all DocField
{
'doctype': 'DocField',
'name': '__common__',
'parent': 'Packing Slip Detail',
'parentfield': 'fields',
'parenttype': 'DocType'
},
# DocType, Packing Slip Detail
{
'doctype': 'DocType',
'name': 'Packing Slip Detail'
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'item_code',
'fieldtype': 'Link',
'label': 'Item Code',
'options': 'Item',
'permlevel': 0,
'reqd': 1,
'width': '100px'
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'item_name',
'fieldtype': 'Data',
'label': 'Item Name',
'permlevel': 1,
'width': '200px'
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'qty',
'fieldtype': 'Currency',
'label': 'Quantity',
'permlevel': 0,
'reqd': 1,
'width': '100px'
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'stock_uom',
'fieldtype': 'Data',
'label': 'UOM',
'permlevel': 1,
'width': '100px'
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'net_weight',
'fieldtype': 'Float',
'label': 'Net Weight',
'permlevel': 1,
'width': '100px'
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'weight_uom',
'fieldtype': 'Link',
'label': 'Weight UOM',
'options': 'UOM',
'permlevel': 1,
'width': '100px'
},
# DocField
{
'doctype': 'DocField',
'fieldname': 'page_break',
'fieldtype': 'Check',
'label': 'Page Break',
'permlevel': 0
}
]

View File

@ -3,7 +3,7 @@
<meta charset="utf-8"> <meta charset="utf-8">
<title>ERPNext</title> <title>ERPNext</title>
<meta name="author" content=""> <meta name="author" content="">
<script type="text/javascript">window._version_number="131" <script type="text/javascript">window._version_number="140"
wn={} wn={}
wn.provide=function(namespace){var nsl=namespace.split('.');var l=nsl.length;var parent=window;for(var i=0;i<l;i++){var n=nsl[i];if(!parent[n]){parent[n]={}} wn.provide=function(namespace){var nsl=namespace.split('.');var l=nsl.length;var parent=window;for(var i=0;i<l;i++){var n=nsl[i];if(!parent[n]){parent[n]={}}

View File

@ -1 +1 @@
131 140