diff --git a/erpnext/patches/jan_mar_2012/deploy_packing_slip.py b/erpnext/patches/jan_mar_2012/deploy_packing_slip.py new file mode 100644 index 0000000000..94bda6eea5 --- /dev/null +++ b/erpnext/patches/jan_mar_2012/deploy_packing_slip.py @@ -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') diff --git a/erpnext/patches/patch_list.py b/erpnext/patches/patch_list.py index c05912b098..f5698130da 100644 --- a/erpnext/patches/patch_list.py +++ b/erpnext/patches/patch_list.py @@ -60,4 +60,9 @@ patch_list = [ 'patch_file': 'cancel_purchase_returned', '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" + }, ] diff --git a/erpnext/selling/doctype/sales_common/sales_common.js b/erpnext/selling/doctype/sales_common/sales_common.js index a2f276036c..8876fa48f7 100644 --- a/erpnext/selling/doctype/sales_common/sales_common.js +++ b/erpnext/selling/doctype/sales_common/sales_common.js @@ -5,11 +5,6 @@ // cur_frm.cscript.other_fname - Other Charges 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 =================== cur_frm.cscript.load_taxes = function(doc, cdt, cdn) { // run if this is not executed from dt_map... diff --git a/erpnext/stock/DocType Mapper/Delivery Note-Packing Slip/Delivery Note-Packing Slip.txt b/erpnext/stock/DocType Mapper/Delivery Note-Packing Slip/Delivery Note-Packing Slip.txt new file mode 100644 index 0000000000..171e08f807 --- /dev/null +++ b/erpnext/stock/DocType Mapper/Delivery Note-Packing Slip/Delivery Note-Packing Slip.txt @@ -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)' + } +] \ No newline at end of file diff --git a/erpnext/stock/Module Def/Stock/Stock.txt b/erpnext/stock/Module Def/Stock/Stock.txt index 4fc8790480..991d4100b3 100644 --- a/erpnext/stock/Module Def/Stock/Stock.txt +++ b/erpnext/stock/Module Def/Stock/Stock.txt @@ -5,7 +5,7 @@ { 'creation': '2011-07-01 17:40:49', 'docstatus': 0, - 'modified': '2011-10-10 17:01:34', + 'modified': '2012-02-01 15:43:00', 'modified_by': 'Administrator', 'owner': 'Administrator' }, @@ -88,6 +88,16 @@ '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 { 'description': 'Record of incoming material from your suppliers', diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js index 5cb4276ba1..59dff8a954 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.js +++ b/erpnext/stock/doctype/delivery_note/delivery_note.js @@ -46,6 +46,10 @@ cur_frm.cscript.refresh = function(doc, cdt, cdn) { cur_frm.add_custom_button('Send SMS', cur_frm.cscript['Send SMS']); 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); } @@ -280,6 +284,23 @@ cur_frm.cscript['Make Installation Note'] = function() { 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 //======================================================================================================================= cur_frm.fields_dict['territory'].get_query = function(doc,cdt,cdn) { diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index 8fc1abcb2f..f7918939cc 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -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_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 ::::::: self.update_current_stock() # :::::: set DN status ::::::: @@ -340,6 +337,7 @@ class DocType(TransactionBase): self.update_stock_ledger(update_stock = -1) # :::::: set DN status ::::::: set(self.doc, 'status', 'Cancelled') + self.cancel_packing_slips() # ******************** Check Next DocStatus ************************** @@ -355,6 +353,23 @@ class DocType(TransactionBase): 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 # ================================================================================================= def update_stock_ledger(self, update_stock, is_stopped = 0): @@ -432,84 +447,3 @@ class DocType(TransactionBase): def repair_delivery_note(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 = ''' -
[HEADER GOES HERE]
-

Packing Slip

- - - - - - - -
ORDER NO.'''+cstr(so_no)+'''SHIPPING MARKS'''+cstr(shipping_mark)+'''
'''; - - return header - - def get_footer(self, row, tot_nett, tot_gross): - footer = ''' - - - - - - - - - - - -
CASE NO'''+cstr(row.pack_no)+'''NETT WT'''+cstr(tot_nett)+'''CHECKED BY'''+cstr(row.packing_checked_by)+'''
SIZE'''+cstr(row.pack_size)+'''GROSS WT'''+cstr(tot_gross)+'''PACKED BY'''+cstr(row.packed_by)+'''
''' - - 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 += ''' - - - - - ''' - - # item table data - sr_no = 1 - for r in plist.get(d): - html += '' - - tot_nett_wt += flt(r.pack_nett_wt) - tot_gross_wt += flt(r.pack_gross_wt) - - sr_no += 1 - - html += '
SR.NO.CS.NO.DESCRIPTIONQUANTITYWEIGHT
'+cstr(sr_no)+''+r.item_code+''+r.description+''+cstr(r.qty)+''+cstr(r.pack_nett_wt)+'
' - - # footer - html += self.get_footer(r, tot_nett_wt, tot_gross_wt) - self.doc.print_packing_slip=html diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.txt b/erpnext/stock/doctype/delivery_note/delivery_note.txt index 3078bf6ff2..00bf9a8d19 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.txt +++ b/erpnext/stock/doctype/delivery_note/delivery_note.txt @@ -5,7 +5,7 @@ { 'creation': '2011-04-18 15:58:20', 'docstatus': 0, - 'modified': '2012-01-09 16:52:43', + 'modified': '2012-01-30 16:52:12', 'modified_by': 'Administrator', 'owner': 'Administrator' }, @@ -21,7 +21,7 @@ # These values are common for all DocType { - '_last_update': '1326105502', + '_last_update': '1326273792', 'colour': 'White:FFF', 'default_print_format': 'Standard', 'doctype': 'DocType', @@ -37,7 +37,7 @@ 'show_in_menu': 0, 'subject': 'To %(customer_name)s on %(transaction_date)s | %(per_billed)s% billed', 'tag_fields': 'billing_status', - 'version': 463 + 'version': 464 }, # These values are common for all DocFormat @@ -1433,53 +1433,5 @@ 'options': 'repair_delivery_note', 'permlevel': 0, '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 } ] \ No newline at end of file diff --git a/erpnext/stock/doctype/delivery_note_detail/delivery_note_detail.txt b/erpnext/stock/doctype/delivery_note_detail/delivery_note_detail.txt index 806803f73a..a10d1d6aca 100644 --- a/erpnext/stock/doctype/delivery_note_detail/delivery_note_detail.txt +++ b/erpnext/stock/doctype/delivery_note_detail/delivery_note_detail.txt @@ -5,7 +5,7 @@ { 'creation': '2010-08-08 17:08:58', 'docstatus': 0, - 'modified': '2011-10-18 16:32:44', + 'modified': '2012-02-01 16:08:06', 'modified_by': 'Administrator', 'owner': 'Administrator' }, @@ -23,7 +23,7 @@ 'section_style': 'Tray', 'server_code_error': ' ', 'show_in_menu': 0, - 'version': 43 + 'version': 51 }, # These values are common for all DocField @@ -289,104 +289,6 @@ '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 { 'doctype': 'DocField', @@ -504,6 +406,20 @@ '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 { 'allow_on_submit': 1, diff --git a/erpnext/stock/doctype/item/item.txt b/erpnext/stock/doctype/item/item.txt index d6ac71badd..db04bcf88a 100644 --- a/erpnext/stock/doctype/item/item.txt +++ b/erpnext/stock/doctype/item/item.txt @@ -5,14 +5,14 @@ { 'creation': '2010-08-08 17:09:05', 'docstatus': 0, - 'modified': '2012-01-17 18:39:39', + 'modified': '2012-01-30 17:34:23', 'modified_by': 'Administrator', 'owner': 'Administrator' }, # These values are common for all DocType { - '_last_update': '1325570647', + '_last_update': '1326963484', 'allow_attach': 1, 'allow_trash': 1, 'autoname': 'field:item_code', @@ -29,7 +29,7 @@ 'show_in_menu': 0, 'subject': '%(item_name)s', 'tag_fields': 'item_group', - 'version': 164 + 'version': 165 }, # These values are common for all DocField @@ -467,19 +467,11 @@ # DocField { + 'description': 'Net Weight of each Item', 'doctype': 'DocField', - 'fieldname': 'nett_weight', + 'fieldname': 'net_weight', 'fieldtype': 'Float', - 'label': 'Nett Weight', - 'permlevel': 0 - }, - - # DocField - { - 'doctype': 'DocField', - 'fieldname': 'gross_weight', - 'fieldtype': 'Float', - 'label': 'Gross Weight', + 'label': 'Net Weight', 'permlevel': 0 }, diff --git a/erpnext/stock/doctype/packing_slip/__init__.py b/erpnext/stock/doctype/packing_slip/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/stock/doctype/packing_slip/packing_slip.js b/erpnext/stock/doctype/packing_slip/packing_slip.js new file mode 100644 index 0000000000..1bf1f2e5c8 --- /dev/null +++ b/erpnext/stock/doctype/packing_slip/packing_slip.js @@ -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; iFrom Case No. = %s""" % (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. + Recommended quantity for %(item_code)s = %(recommended_qty)s \ + %(stock_uom)s""" % 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) diff --git a/erpnext/stock/doctype/packing_slip/packing_slip.txt b/erpnext/stock/doctype/packing_slip/packing_slip.txt new file mode 100644 index 0000000000..6c54a9dfb3 --- /dev/null +++ b/erpnext/stock/doctype/packing_slip/packing_slip.txt @@ -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 + } +] \ No newline at end of file diff --git a/erpnext/stock/doctype/packing_slip_detail/__init__.py b/erpnext/stock/doctype/packing_slip_detail/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/stock/doctype/packing_slip_detail/packing_slip_detail.py b/erpnext/stock/doctype/packing_slip_detail/packing_slip_detail.py new file mode 100644 index 0000000000..05f502c70f --- /dev/null +++ b/erpnext/stock/doctype/packing_slip_detail/packing_slip_detail.py @@ -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) diff --git a/erpnext/stock/doctype/packing_slip_detail/packing_slip_detail.txt b/erpnext/stock/doctype/packing_slip_detail/packing_slip_detail.txt new file mode 100644 index 0000000000..5a83b6f35f --- /dev/null +++ b/erpnext/stock/doctype/packing_slip_detail/packing_slip_detail.txt @@ -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 + } +] \ No newline at end of file diff --git a/index.html b/index.html index 94822ef44e..2793bd71b0 100644 --- a/index.html +++ b/index.html @@ -3,7 +3,7 @@ ERPNext -