1
# -*- coding: utf-8 -*-
2
##############################################################################
4
# OpenERP, Open Source Management Solution
5
# Copyright (C) 2011 NovaPoint Group LLC (<http://www.novapointgroup.com>)
6
# Copyright (C) 2004-2010 OpenERP SA (<http://www.openerp.com>)
8
# This program is free software: you can redistribute it and/or modify
9
# it under the terms of the GNU General Public License as published by
10
# the Free Software Foundation, either version 3 of the License, or
11
# (at your option) any later version.
13
# This program is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
# GNU General Public License for more details.
18
# You should have received a copy of the GNU General Public License
19
# along with this program. If not, see <http://www.gnu.org/licenses/>
21
##############################################################################
27
from osv import fields, osv
29
class stock_picking(osv.osv):
30
_inherit = "stock.picking"
32
def onchange_logis_company(self, cr, uid, ids, logistic_company_id, context=None):
34
if logistic_company_id:
35
logistic_company_obj = self.pool.get('logistic.company')
36
company_code = logistic_company_obj.read(cr, uid, logistic_company_id, ['ship_company_code'], context=context )['ship_company_code']
37
res = {'value': {'ship_company_code': company_code}}
41
cr.execute('alter table stock_picking alter column tot_ship_weight type numeric(16,3)')
43
def copy(self, cr, uid, id, default=None, context=None):
44
default['ship_state'] = 'draft'
45
res=super(stock_picking, self).copy(cr, uid, id, default, context=context)
48
def distribute_weight(self, cr, uid, ids, context=None):
49
pack_ids_list = self.read(cr, uid, ids,['packages_ids', 'tot_del_order_weight'], context=context)
50
for pack_ids in pack_ids_list:
51
if pack_ids['tot_del_order_weight'] and pack_ids['packages_ids']:
52
avg_weight = pack_ids['tot_del_order_weight'] / len(pack_ids['packages_ids'])
53
self.pool.get('stock.packages').write(cr, uid, pack_ids['packages_ids'], {'weight': avg_weight}, context=context)
56
def _total_weight_net(self, cr, uid, ids, field_name, arg, context=None):
57
"""Compute the total net weight of the given Delivery order."""
59
for pick in self.browse(cr, uid, ids, context=context):
61
for line in pick.packages_ids:
63
result[pick.id] += line.weight
66
def _total_ord_weight_net(self, cr, uid, ids, field_name, arg, context=None):
67
"""Compute the total net weight of the given Delivery order."""
69
for pick in self.browse(cr, uid, ids, context=context):
71
for line in pick.move_lines:
73
result[pick.id] += line.product_qty * line.product_id.weight_net
76
def _get_move_order(self, cr, uid, ids, context=None):
77
"""Get the picking ids of the given Stock Moves."""
79
for line in self.pool.get('stock.move').browse(cr, uid, ids, context=context):
80
result[line.picking_id.id] = True
83
def _get_order(self, cr, uid, ids, context=None):
84
"""Get the picking ids of the given Stock Packages."""
86
for line in self.pool.get('stock.packages').browse(cr, uid, ids, context=None):
87
result[line.pick_id.id] = True
90
def _get_company_code(self, cr, user, context=None):
94
'logis_company': fields.many2one('logistic.company', 'Logistics Company', help='Name of the Logistics company providing the shipper services.'),
95
'freight': fields.boolean('Shipment', help='Indicates if the shipment is a freight shipment.'),
96
'sat_delivery': fields.boolean('Saturday Delivery', help='Indicates is it is appropriate to send delivery on Saturday.'),
97
'package_type': fields.selection([
99
('02', 'Customer Supplied Package'),
102
('21', 'ExpressBox'),
106
('2a', 'Small Express Box'),
107
('2b', 'Medium Express Box'),
108
('2c', 'Large Express Box')
109
],'Package Type', help='Indicates the type of package'),
110
'bill_shipping': fields.selection([
111
('shipper', 'Shipper'),
112
('receiver', 'Receiver'),
113
('thirdparty', 'Third Party')
114
], 'Bill Shipping to', help='Shipper, Receiver, or Third Party.'),
115
'with_ret_service': fields.boolean('With Return Services', help='Include Return Shipping Information in the package.'),
116
'tot_ship_weight': fields.function(_total_weight_net, method=True, type='float', digits=(16, 3), string='Total Shipment Weight',
118
'stock.picking': (lambda self, cr, uid, ids, c={}: ids,['packages_ids'], -10),
119
'stock.packages': (_get_order, ['weight'], -10),
120
}, help="Adds the Total Weight of all the packages in the Packages Table.",
122
'tot_del_order_weight': fields.function(_total_ord_weight_net, method=True, readonly=True, string='Total Order Weight', store=False,
123
help="Adds the Total Weight of all the packages in the Packages Table."),
124
'packages_ids': fields.one2many("stock.packages", 'pick_id', 'Packages Table'),
125
'ship_state': fields.selection([
127
('in_process', 'In Process'),
128
('ready_pick', 'Ready for Pickup'),
129
('shipped', 'Shipped'),
130
('delivered', 'Delivered'),
133
('cancelled', 'Cancelled')
134
], 'Shipping Status', readonly=True, help='The current status of the shipment'),
135
'trade_mark': fields.text('Trademarks AREA'),
136
'ship_message': fields.text('Message'),
137
'address_validate': fields.selection([
138
('validate', 'Validate'),
139
('nonvalidate', 'No Validation')
140
], 'Address Validation', help=''' No Validation = No address validation.
141
Validate = Fail on failed address validation.
142
Defaults to validate. Note: Full address validation is not performed. Therefore, it is
143
the responsibility of the Shipping Tool User to ensure the address entered is correct to
144
avoid an address correction fee.''' ),
145
'ship_description': fields.text('Description'),
146
'ship_from': fields.boolean('Ship From', help='Required if pickup location is different from the shipper\'s address..'),
147
'ship_from_tax_id_no': fields.char('Ship From Tax Identification Number', size=64 , select=1),
148
'ship_from_address': fields.many2one('res.partner.address', 'Ship From Address'),
149
'tot_order_weight': fields.related('sale_id', 'total_weight_net', type='float', relation='sale.order', string='Total Order Weight'),
150
'comm_inv': fields.boolean('Commercial Invoice'),
151
'cer_orig': fields.boolean('U.S. Certificate of Origin'),
152
'nafta_cer_orig': fields.boolean('NAFTA Certificate of Origin'),
153
'sed': fields.boolean('Shipper Export Declaration (SED)'),
154
'prod_option': fields.selection([
155
('01', 'AVAILABLE TO CUSTOMS UPON REQUEST'),
156
('02', 'SAME AS EXPORTER'),
157
('03', 'ATTACHED LIST'),
161
'prod_company': fields.char('CompanyName', size=256, help='Only applicable when producer option is empty or not present.'),
162
'prod_tax_id_no': fields.char('TaxIdentificationNumber', size=256, help='Only applicable when producer option is empty or not present.'),
163
'prod_address_id': fields.many2one('res.partner.address', 'Producer Address', help='Only applicable when producer option is empty or not present.'),
164
'inv_option': fields.selection([
168
], 'Sold to Option'),
169
'inv_company': fields.char('CompanyName', size=256, help='Only applicable when Sold to option is empty or not present.'),
170
'inv_tax_id_no': fields.char('TaxIdentificationNumber', size=256, help='Only applicable when Sold to option is empty or not present.'),
171
'inv_att_name': fields.char('AttentionName', size=256, help='Only applicable when Sold to option is empty or not present.'),
172
'inv_address_id': fields.many2one('res.partner.address', 'Sold To Address', help='Only applicable when Sold to option is empty or not present.'),
173
'blanket_begin_date': fields.date('Blanket Begin Date'),
174
'blanket_end_date': fields.date('Blanket End Date'),
175
'comm_code': fields.char('Commodity Code', size=256,),
176
'exp_carrier': fields.char('ExportingCarrier', size=256),
177
'ship_company_code': fields.selection(_get_company_code, 'Ship Company', method=True, size=64),
181
'address_validate': 'nonvalidate',
184
'nafta_cer_orig': False,
186
'ship_state' : 'draft',
187
'bill_shipping': 'shipper'
190
def process_ship(self, cr, uid, ids, context=None):
193
def print_labels(self, cr, uid, ids, context=None):
194
if not ids: return []
196
'type': 'ir.actions.report.xml',
197
'report_name': 'multiple.label.print',
199
'model': 'stock.picking',
200
'id': ids and ids[0] or False,
207
def print_packing_slips(self, cr, uid, ids, context=None):
208
if not ids: return []
210
for package in self.browse(cr, uid, ids[0]).packages_ids:
211
packages_ids.append(package.id)
213
'type': 'ir.actions.report.xml',
214
'report_name': 'package.packing.slip.print',
216
'model': 'stock.packages',
217
'id': ids and ids[0] or False,
224
def process_void(self, cr, uid, ids, context=None):
227
def cancel_ship(self, cr, uid, ids, context=None):
228
self.write(cr, uid, ids, {'ship_state': 'cancelled'}, context=context)
231
def _get_account_analytic_invoice(self, cursor, user, picking, move_line):
232
partner_id = picking.address_id and picking.address_id.partner_id and picking.address_id.partner_id.id or False
233
analytic_obj = self.pool.get('account.analytic.default')
234
rec = analytic_obj.account_get(cursor, user, move_line.product_id.id, partner_id, user, time.strftime('%Y-%m-%d'), context={})
236
return rec.analytic_id.id
237
return super(stock_picking, self)._get_account_analytic_invoice(cursor, user, picking, move_line)
239
def send_conf_mail(self, cr, uid, ids, context=None):
242
obj = self.browse(cr, uid, id)
243
if obj and obj.address_id and obj.address_id.email:
244
email_temp_obj = self.pool.get('email.template')
245
template_id = email_temp_obj.search(cr, uid, [('object_name.model', '=', 'stock.picking'), ('ship_mail', '=', True)], context=context)
247
template_obj_list = email_temp_obj.browse(cr, uid, template_id)
248
for template_obj in template_obj_list:
249
subj = self.get_value(obj, template_obj, 'def_subject') or ''
251
'email_to': self.get_value(cr, uid, obj, template_obj.def_to, context) or '',
252
'body_text': self.get_value(cr, uid, obj, template_obj.def_body_text) or '',
253
'body_html': self.get_value(cr, uid, obj, template_obj.def_body_html) or '',
254
'account_id': template_obj.from_account.id,
257
'subject': self.get_value(cr, uid, obj, template_obj.def_subject) or '',
258
'email_cc': self.get_value(cr, uid, obj, template_obj.def_cc) or '',
259
'email_bcc': self.get_value(cr, uid, obj, template_obj.def_bcc) or '',
260
'email_from': template_obj.from_account.email_id or '',
261
'reply_to': self.get_value(cr, uid, obj, template_obj.reply_to) or '' ,
262
'date_mail': time.strftime('%Y-%m-%d %H:%M:%S'),
264
if vals['email_to'] and vals['account_id']:
265
mail_id = self.pool.get('email_template.mailbox').create(cr, uid, vals, context=context)
267
data['model'] = 'stock.picking'
268
if template_obj.report_template:
269
reportname = 'report.' + self.pool.get('ir.actions.report.xml').read(cr, uid, template_obj.report_template.id,
270
['report_name'], context=context)['report_name']
271
service = netsvc.LocalService(reportname)
272
(result, format) = service.create(cr, uid, [id], data, context=context)
273
email_temp_obj._add_attachment(cr, uid, mail_id, subj, base64.b64encode(result),
274
template_obj.file_name or 'Order.pdf', context=context)
279
class stock_partial_picking(osv.osv_memory):
280
_inherit = "stock.partial.picking"
282
def do_partial(self, cr, uid, ids, context=None):
283
ret = super(stock_partial_picking, self).do_partial(cr, uid, ids, context=context)
284
pick_obj = self.pool.get('stock.picking')
287
picking_ids = context.get('active_ids', False)
289
for pick in pick_obj.browse(cr, uid, picking_ids, context=context):
290
if pick.backorder_id:
291
new_pick_ids.append(pick.backorder_id.id)
294
model_obj = self.pool.get('ir.model.data')
295
view_obj = self.pool.get('ir.ui.view')
296
model_id = model_obj._get_id(cr, uid, 'stock', 'view_picking_out_form')
297
view_id = model_obj.read(cr, uid, [model_id], ['res_id'])[0]['res_id']
298
domain = "[('id', 'in', [" + ','.join(map(str, new_pick_ids)) + "])]"
300
"type": "ir.actions.act_window",
301
"res_model": "stock.picking",
303
"view_mode": "tree,form",
304
"name": "Delivery Order",
306
"context": {'search_default_available': 0},
307
'views': [(False, 'tree'),(view_id, 'form')]
311
logger = netsvc.Logger()
312
logger.notifyChannel("Warning", netsvc.LOG_WARNING,
313
"Issue with opening the processed delivery order. %s." % e)
318
stock_partial_picking()
320
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: