diff --git a/delivery_fedex_hibou/__init__.py b/delivery_fedex_hibou/__init__.py index 0650744f..09434554 100644 --- a/delivery_fedex_hibou/__init__.py +++ b/delivery_fedex_hibou/__init__.py @@ -1 +1,3 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + from . import models diff --git a/delivery_fedex_hibou/__manifest__.py b/delivery_fedex_hibou/__manifest__.py index 347e017a..7a99231a 100644 --- a/delivery_fedex_hibou/__manifest__.py +++ b/delivery_fedex_hibou/__manifest__.py @@ -1,9 +1,9 @@ { 'name': 'Hibou Fedex Shipping', - 'version': '13.0.1.0.0', + 'version': '13.0.1.1.0', 'category': 'Stock', 'author': "Hibou Corp.", - 'license': 'AGPL-3', + 'license': 'OPL-1', 'website': 'https://hibou.io/', 'depends': [ 'delivery_fedex', diff --git a/delivery_fedex_hibou/models/__init__.py b/delivery_fedex_hibou/models/__init__.py index cfdf1b44..bad254c1 100644 --- a/delivery_fedex_hibou/models/__init__.py +++ b/delivery_fedex_hibou/models/__init__.py @@ -1,2 +1,4 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + from . import delivery_fedex from . import stock diff --git a/delivery_fedex_hibou/models/delivery_fedex.py b/delivery_fedex_hibou/models/delivery_fedex.py index 90544864..21488d24 100644 --- a/delivery_fedex_hibou/models/delivery_fedex.py +++ b/delivery_fedex_hibou/models/delivery_fedex.py @@ -1,3 +1,5 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + import logging import pytz from odoo import fields, models, tools, _ @@ -223,6 +225,15 @@ class DeliveryFedex(models.Model): srm = FedexRequest(self.log_xml, request_type="shipping", prod_environment=self.prod_environment) superself = self.sudo() + picking_packages = picking.package_ids + package_carriers = picking_packages.mapped('carrier_id') + if package_carriers: + # only ship ours + picking_packages = picking_packages.filtered(lambda p: p.carrier_id == self and not p.carrier_tracking_ref) + + if package_carriers and not picking_packages: + continue + shipper_company = superself.get_shipper_company(picking=picking) shipper_warehouse = superself.get_shipper_warehouse(picking=picking) recipient = superself.get_recipient(picking=picking) @@ -239,7 +250,7 @@ class DeliveryFedex(models.Model): srm.transaction_detail(picking.id) - package_type = picking.package_ids and picking.package_ids[0].packaging_id.shipper_package_code or self.fedex_default_packaging_id.shipper_package_code + package_type = picking_packages and picking_packages[0].packaging_id.shipper_package_code or self.fedex_default_packaging_id.shipper_package_code srm.shipment_request(self.fedex_droppoff_type, self.fedex_service_type, package_type, self.fedex_weight_unit, self.fedex_saturday_delivery) srm.set_currency(_convert_curr_iso_fdx(picking.company_id.currency_id.name)) srm.set_shipper(shipper_company, shipper_warehouse) @@ -278,7 +289,7 @@ class DeliveryFedex(models.Model): send_etd = superself.env['ir.config_parameter'].get_param("delivery_fedex.send_etd") srm.commercial_invoice(self.fedex_document_stock_type, send_etd) - package_count = len(picking.package_ids) or 1 + package_count = len(picking_packages) or 1 # For india picking courier is not accepted without this details in label. po_number = order.display_name or False @@ -307,16 +318,17 @@ class DeliveryFedex(models.Model): package_labels = [] carrier_tracking_ref = "" - for sequence, package in enumerate(picking.package_ids, start=1): + for sequence, package in enumerate(picking_packages, start=1): package_weight = self._fedex_convert_weight(package.shipping_weight, self.fedex_weight_unit) packaging = package.packaging_id + packaging_code = packaging.shipper_package_code if (packaging.package_carrier_type == 'fedex' and packaging.shipper_package_code) else self.fedex_default_packaging_id.shipper_package_code # Hibou Delivery # Add more details to package. srm._add_package( package_weight, - package_code=packaging.shipper_package_code, + package_code=packaging_code, package_height=packaging.height, package_width=packaging.width, package_length=packaging.length, @@ -394,10 +406,11 @@ class DeliveryFedex(models.Model): # One package # ############### elif package_count == 1: - packaging = picking.package_ids[:1].packaging_id or picking.carrier_id.fedex_default_packaging_id + packaging = picking_packages[:1].packaging_id or self.fedex_default_packaging_id + packaging_code = packaging.shipper_package_code if packaging.package_carrier_type == 'fedex' else self.fedex_default_packaging_id.shipper_package_code srm._add_package( net_weight, - package_code=packaging.shipper_package_code, + package_code=packaging_code, package_height=packaging.height, package_width=packaging.width, package_length=packaging.length, @@ -457,21 +470,33 @@ class DeliveryFedex(models.Model): picking.message_post(body='Fedex Documents', attachments=fedex_documents) return res - def fedex_rate_shipment_multi(self, order=None, picking=None): + def fedex_rate_shipment_multi(self, order=None, picking=None, packages=None): + if not packages: + return self._fedex_rate_shipment_multi_package(order=order, picking=picking) + else: + rates = [] + for package in packages: + rates += self._fedex_rate_shipment_multi_package(order=order, picking=picking, package=package) + return rates + + def _fedex_rate_shipment_multi_package(self, order=None, picking=None, package=None): if order: max_weight = self._fedex_convert_weight(self.fedex_default_packaging_id.max_weight, self.fedex_weight_unit) is_india = order.partner_shipping_id.country_id.code == 'IN' and order.company_id.partner_id.country_id.code == 'IN' est_weight_value = sum([(line.product_id.weight * line.product_uom_qty) for line in order.order_line]) or 0.0 weight_value = self._fedex_convert_weight(est_weight_value, self.fedex_weight_unit) order_currency = order.currency_id - else: - # max_weight = self._fedex_convert_weight(self.fedex_default_packaging_id.max_weight, self.fedex_weight_unit) + elif not package: is_india = picking.partner_id.country_id.code == 'IN' and picking.company_id.partner_id.country_id.code == 'IN' - # TODO must be per-package eventually - # theoretically just sum of all packages weights, but the rating itself will also need to change... est_weight_value = sum([(line.product_id.weight * (line.qty_done or line.product_uom_qty)) for line in picking.move_line_ids]) or 0.0 weight_value = self._fedex_convert_weight(est_weight_value, self.fedex_weight_unit) order_currency = picking.sale_id.currency_id if picking.sale_id else picking.company_id.currency_id + else: + is_india = picking.partner_id.country_id.code == 'IN' and picking.company_id.partner_id.country_id.code == 'IN' + order_currency = picking.sale_id.currency_id if picking.sale_id else picking.company_id.currency_id + est_weight_value = self._fedex_convert_weight(package.shipping_weight or package.weight) + weight_value = self._fedex_convert_weight(est_weight_value, self.fedex_weight_unit) + price = 0.0 @@ -558,9 +583,28 @@ class DeliveryFedex(models.Model): ) srm.set_master_package(weight_value, 1) else: - for sequence, package in enumerate(picking.package_ids, start=1): - package_weight = self._fedex_convert_weight(package.shipping_weight, self.fedex_weight_unit) + if package: + package_weight = self._fedex_convert_weight(package.shipping_weight or package.weight, self.fedex_weight_unit) packaging = package.packaging_id + package_code = package.packaging_id.shipper_package_code if packaging.package_carrier_type == 'fedex' else self.fedex_default_packaging_id.shipper_package_code + + srm.add_package( + package_weight, + mode='rating', + package_code=package_code, + package_height=packaging.height, + package_width=packaging.width, + package_length=packaging.length, + sequence_number=1, + # po_number=po_number, + # dept_number=dept_number, + reference=('%s-%d' % (order_name, 1)), + insurance=insurance_value + ) + else: + # deliver all together... + package_weight = self._fedex_convert_weight(picking.shipping_weight or picking.weight, self.fedex_weight_unit) + packaging = self.fedex_default_packaging_id srm.add_package( package_weight, @@ -569,10 +613,10 @@ class DeliveryFedex(models.Model): package_height=packaging.height, package_width=packaging.width, package_length=packaging.length, - sequence_number=sequence, + sequence_number=1, # po_number=po_number, # dept_number=dept_number, - reference=('%s-%d' % (order_name, sequence)), + reference=('%s-%d' % (order_name, 1)), insurance=insurance_value ) @@ -643,6 +687,7 @@ class DeliveryFedex(models.Model): tz = pytz.timezone(self.delivery_calendar_id.tz) date_delivered = tz.localize(date_delivered).astimezone(pytz.utc).replace(tzinfo=None) result.append({'carrier': carrier, + 'package': package or self.env['stock.quant.package'].browse(), 'success': True, 'price': price, 'error_message': False, diff --git a/delivery_fedex_hibou/models/fedex_request.py b/delivery_fedex_hibou/models/fedex_request.py index 0a561abf..e5043069 100644 --- a/delivery_fedex_hibou/models/fedex_request.py +++ b/delivery_fedex_hibou/models/fedex_request.py @@ -1,3 +1,5 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + from zeep.exceptions import Fault from datetime import datetime from copy import deepcopy diff --git a/delivery_fedex_hibou/models/stock.py b/delivery_fedex_hibou/models/stock.py index 3dfb1a1f..58726f6f 100644 --- a/delivery_fedex_hibou/models/stock.py +++ b/delivery_fedex_hibou/models/stock.py @@ -1,3 +1,5 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + from odoo import api, fields, models diff --git a/delivery_gso/__init__.py b/delivery_gso/__init__.py index 0650744f..09434554 100644 --- a/delivery_gso/__init__.py +++ b/delivery_gso/__init__.py @@ -1 +1,3 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + from . import models diff --git a/delivery_gso/__manifest__.py b/delivery_gso/__manifest__.py index 2856bc7a..dc28415f 100644 --- a/delivery_gso/__manifest__.py +++ b/delivery_gso/__manifest__.py @@ -1,10 +1,10 @@ { 'name': 'Golden State Overnight (gso.com) Shipping', 'summary': 'Send your shippings through gso.com and track them online.', - 'version': '11.0.1.0.0', + 'version': '13.0.1.1.0', 'author': "Hibou Corp.", 'category': 'Warehouse', - 'license': 'AGPL-3', + 'license': 'OPL-1', 'images': [], 'website': "https://hibou.io", 'description': """ diff --git a/delivery_gso/models/__init__.py b/delivery_gso/models/__init__.py index 943392d3..c9a65a9e 100644 --- a/delivery_gso/models/__init__.py +++ b/delivery_gso/models/__init__.py @@ -1 +1,3 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + from . import delivery_gso diff --git a/delivery_gso/models/delivery_gso.py b/delivery_gso/models/delivery_gso.py index 3727bc80..3d302c4c 100644 --- a/delivery_gso/models/delivery_gso.py +++ b/delivery_gso/models/delivery_gso.py @@ -1,3 +1,5 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + import pytz from math import ceil from base64 import b64decode @@ -198,9 +200,15 @@ class ProviderGSO(models.Model): 'thermal': [], 'paper': [], } - if picking.package_ids: + picking_packages = picking.package_ids + package_carriers = picking_packages.mapped('carrier_id') + if package_carriers: + # only ship ours + picking_packages = picking_packages.filtered(lambda p: p.carrier_id == self and not p.carrier_tracking_ref) + + if picking_packages: # Every package will be a transaction - for package in picking.package_ids: + for package in picking_packages: request_body['Shipment']['Weight'] = self._gso_convert_weight(package.shipping_weight) request_body['Shipment'].update(self._gso_get_package_dimensions(package)) request_body['Shipment']['ShipmentReference'] = package.name @@ -217,7 +225,8 @@ class ProviderGSO(models.Model): cost += response['ShipmentCharges']['TotalCharge'] except HTTPError as e: raise ValidationError(e) - else: + elif not package_carriers: + # ship the whole picking request_body['Shipment']['Weight'] = self._gso_convert_weight(picking.shipping_weight) request_body['Shipment'].update(self._gso_get_package_dimensions()) request_body['Shipment']['ShipmentReference'] = picking.name @@ -234,6 +243,8 @@ class ProviderGSO(models.Model): cost += response['ShipmentCharges']['TotalCharge'] except HTTPError as e: raise ValidationError(e) + else: + continue # Handle results trackings = [l[0] for l in labels['thermal']] + [l[0] for l in labels['paper']] @@ -331,18 +342,32 @@ class ProviderGSO(models.Model): res.append('https://www.gso.com/Tracking') return res - def gso_rate_shipment_multi(self, order=None, picking=None): + def gso_rate_shipment_multi(self, order=None, picking=None, packages=None): + if not packages: + return self._gso_rate_shipment_multi_package(order=order, picking=picking) + else: + rates = [] + for package in packages: + rates += self._gso_rate_shipment_multi_package(order=order, picking=picking, package=package) + return rates + + def _gso_rate_shipment_multi_package(self, order=None, picking=None, package=None): sudoself = self.sudo() - service = sudoself._get_gso_service() + try: + service = sudoself._get_gso_service() + except HTTPError as e: + _logger.error(e) + return [{ + 'success': False, + 'price': 0.0, + 'error_message': _('GSO web service returned an error. ' + str(e)), + 'warning_message': False, + }] + from_ = sudoself.get_shipper_warehouse(order=order, picking=picking) to = sudoself.get_recipient(order=order, picking=picking) address_type = 'B' if bool(to.is_company or to.parent_id.is_company) else 'R' - - if order: - est_weight_value = self._gso_convert_weight( - sum([(line.product_id.weight * line.product_uom_qty) for line in order.order_line]) or 0.0) - else: - est_weight_value = self._gso_convert_weight(picking.shipping_weight) + package_dimensions = self._gso_get_package_dimensions(package=package) date_planned = fields.Datetime.now() if self.env.context.get('date_planned'): @@ -353,10 +378,13 @@ class ProviderGSO(models.Model): ship_date_gso = ship_date_utc.astimezone(pytz.timezone(GSO_TZ)) ship_date_gso = fields.Datetime.to_string(ship_date_gso) - if picking and picking.package_ids: - package_dimensions = self._gso_get_package_dimensions(package=picking.package_ids[0]) + if order: + est_weight_value = self._gso_convert_weight( + sum([(line.product_id.weight * line.product_uom_qty) for line in order.order_line]) or 0.0) + elif not package: + est_weight_value = self._gso_convert_weight(picking.shipping_weight) else: - package_dimensions = self._gso_get_package_dimensions() + est_weight_value = self._gso_convert_weight(package.shipping_weight or package.weight) request_body = { 'AccountNumber': sudoself.gso_account_number, @@ -395,6 +423,7 @@ class ProviderGSO(models.Model): if carrier: rates.append({ 'carrier': carrier, + 'package': package or self.env['stock.quant.package'].browse(), 'success': True, 'price': price, 'error_message': False, diff --git a/delivery_gso/models/requests_gso.py b/delivery_gso/models/requests_gso.py index e5fceb3a..4e512661 100644 --- a/delivery_gso/models/requests_gso.py +++ b/delivery_gso/models/requests_gso.py @@ -1,3 +1,5 @@ +# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details. + import requests from json import dumps diff --git a/delivery_hibou/__manifest__.py b/delivery_hibou/__manifest__.py index 4897f03c..fedb9c16 100644 --- a/delivery_hibou/__manifest__.py +++ b/delivery_hibou/__manifest__.py @@ -1,7 +1,7 @@ { 'name': 'Delivery Hibou', 'summary': 'Adds underlying pinnings for things like "RMA Return Labels"', - 'version': '13.0.1.0.0', + 'version': '13.0.1.1.0', 'author': "Hibou Corp.", 'category': 'Stock', 'license': 'AGPL-3', diff --git a/delivery_hibou/models/delivery.py b/delivery_hibou/models/delivery.py index 4b478dd8..d281fb5f 100644 --- a/delivery_hibou/models/delivery.py +++ b/delivery_hibou/models/delivery.py @@ -1,5 +1,6 @@ from odoo import fields, models from odoo.addons.stock.models.stock_move import PROCUREMENT_PRIORITIES +from odoo.exceptions import UserError class DeliveryCarrier(models.Model): @@ -161,11 +162,12 @@ class DeliveryCarrier(models.Model): # -------------------------- # # API for external providers # # -------------------------- # - def rate_shipment_multi(self, order=None, picking=None): + def rate_shipment_multi(self, order=None, picking=None, packages=None): ''' Compute the price of the order shipment :param order: record of sale.order or None :param picking: record of stock.picking or None + :param packages: recordset of stock.quant.package or None (requires picking also set) :return list: dict: { 'carrier': delivery.carrier(), 'success': boolean, @@ -176,6 +178,7 @@ class DeliveryCarrier(models.Model): 'date_delivered': a datetime for when the shipment is supposed to arrive, 'transit_days': a Float for how many days it takes in transit, 'service_code': a string that represents the service level/agreement, + 'package': stock.quant.package(), } e.g. self == delivery.carrier(5, 6) @@ -190,12 +193,53 @@ class DeliveryCarrier(models.Model): if picking: self = self.with_context(date_planned=fields.Datetime.now()) + if not packages: + packages = picking.package_ids else: + if packages: + raise UserError('Cannot rate package without picking.') self = self.with_context(date_planned=(order.date_planned or fields.Datetime.now())) res = [] for carrier in self: + carrier_packages = packages.filtered(lambda p: not p.carrier_tracking_ref and + (not p.carrier_id or p.carrier_id == carrier) and + p.packaging_id.package_carrier_type in (False, '', 'none', carrier.delivery_type)) + if packages and not carrier_packages: + continue if hasattr(carrier, '%s_rate_shipment_multi' % self.delivery_type): - carrier_rates = getattr(carrier, '%s_rate_shipment_multi' % carrier.delivery_type)(order=order, picking=picking) - res += carrier_rates + try: + res += getattr(carrier, '%s_rate_shipment_multi' % carrier.delivery_type)(order=order, + picking=picking, + packages=carrier_packages) + except TypeError: + # TODO remove catch if after Odoo 14 + # This is intended to find ones that don't support packages= kwarg + res += getattr(carrier, '%s_rate_shipment_multi' % carrier.delivery_type)(order=order, + picking=picking) + return res + + def cancel_shipment(self, pickings, packages=None): + ''' Cancel a shipment + + :param pickings: A recordset of pickings + :param packages: Optional recordset of packages (should be for this carrier) + ''' + self.ensure_one() + if hasattr(self, '%s_cancel_shipment' % self.delivery_type): + # No good way to tell if this method takes the kwarg for packages + if packages: + try: + return getattr(self, '%s_cancel_shipment' % self.delivery_type)(pickings, packages=packages) + except TypeError: + # we won't be able to cancel the packages properly + # here we will TRY to make a good call here where we put the package references into the picking + # and let the original mechanisms try to work here + tracking_ref = ','.join(packages.mapped('carrier_tracking_ref')) + pickings.write({ + 'carrier_id': self.id, + 'carrier_tracking_ref': tracking_ref, + }) + + return getattr(self, '%s_cancel_shipment' % self.delivery_type)(pickings) diff --git a/delivery_hibou/models/stock.py b/delivery_hibou/models/stock.py index 35559223..9258b4e8 100644 --- a/delivery_hibou/models/stock.py +++ b/delivery_hibou/models/stock.py @@ -1,4 +1,27 @@ -from odoo import api, fields, models +from odoo import api, fields, models, _ +from odoo.exceptions import UserError + + +class StockQuantPackage(models.Model): + _inherit = 'stock.quant.package' + + carrier_id = fields.Many2one('delivery.carrier', string='Carrier') + carrier_tracking_ref = fields.Char(string='Tracking Reference') + + def _get_active_picking(self): + picking_id = self._context.get('active_id') + picking_model = self._context.get('active_model') + if not picking_id or picking_model != 'stock.picking': + raise UserError('Cannot cancel package other than through shipment/picking.') + return self.env['stock.picking'].browse(picking_id) + + def send_to_shipper(self): + picking = self._get_active_picking() + picking.with_context(packages=self).send_to_shipper() + + def cancel_shipment(self): + picking = self._get_active_picking() + picking.with_context(packages=self).cancel_shipment() class StockPicking(models.Model): @@ -11,6 +34,22 @@ class StockPicking(models.Model): ('no', 'No'), ], string='Require Insurance', default='auto', help='If your carrier supports it, auto should be calculated off of the "Automatic Insurance Value" field.') + package_carrier_tracking_ref = fields.Char(string='Package Tracking Numbers', compute='_compute_package_carrier_tracking_ref') + + @api.depends('package_ids.carrier_tracking_ref') + def _compute_package_carrier_tracking_ref(self): + for picking in self: + package_refs = picking.package_ids.filtered('carrier_tracking_ref').mapped('carrier_tracking_ref') + if package_refs: + picking.package_carrier_tracking_ref = ','.join(package_refs) + else: + picking.package_carrier_tracking_ref = False + + @api.onchange('carrier_id') + def _onchange_carrier_id_for_priority(self): + for picking in self: + if picking.carrier_id and picking.carrier_id.procurement_priority: + picking.priority = picking.carrier_id.procurement_priority @api.depends('move_lines.priority', 'carrier_id') def _compute_priority(self): @@ -26,6 +65,11 @@ class StockPicking(models.Model): so = self.env['sale.order'].search([('name', '=', str(origin))], limit=1) if so and so.shipping_account_id: values['shipping_account_id'] = so.shipping_account_id.id + carrier_id = values.get('carrier_id') + if carrier_id: + carrier = self.env['delivery.carrier'].browse(carrier_id) + if carrier.procurement_priority: + values['priority'] = carrier.procurement_priority res = super(StockPicking, self).create(values) return res @@ -38,6 +82,85 @@ class StockPicking(models.Model): cost = sum([(l.product_id.standard_price * l.product_uom_qty) for l in self.move_lines] or [0.0]) return cost + def clear_carrier_tracking_ref(self): + self.write({'carrier_tracking_ref': False}) + + def reset_carrier_tracking_ref(self): + for picking in self: + picking.carrier_tracking_ref = picking.package_carrier_tracking_ref + + # Override to send to specific packaging carriers + def send_to_shipper(self): + packages = self._context.get('packages') + self.ensure_one() + if not packages: + packages = self.package_ids + package_carriers = packages.mapped('carrier_id') + if not package_carriers: + # Original behavior + return super().send_to_shipper() + + tracking_numbers = [] + carrier_prices = [] + order_currency = self.sale_id.currency_id or self.company_id.currency_id + for carrier in package_carriers: + self.carrier_id = carrier + carrier_packages = packages.filtered(lambda p: p.carrier_id == carrier) + res = carrier.send_shipping(self) + if res: + res = res[0] + if carrier.free_over and self.sale_id and self.sale_id._compute_amount_total_without_delivery() >= carrier.amount: + res['exact_price'] = 0.0 + carrier_price = res['exact_price'] * (1.0 + (self.carrier_id.margin / 100.0)) + carrier_prices.append(carrier_price) + tracking_number = '' + if res['tracking_number']: + tracking_number = res['tracking_number'] + tracking_numbers.append(tracking_number) + # Try to add tracking to the individual packages. + potential_tracking_numbers = tracking_number.split(',') + if len(potential_tracking_numbers) >= len(carrier_packages): + for t, p in zip(potential_tracking_numbers, carrier_packages): + p.carrier_tracking_ref = t + else: + carrier_packages.write({'carrier_tracking_ref': tracking_number}) + msg = _("Shipment sent to carrier %s for shipping with tracking number %s
Cost: %.2f %s") % (carrier.name, tracking_number, carrier_price, order_currency.name) + self.message_post(body=msg) + + self.carrier_price = sum(carrier_prices or [0.0]) + self.carrier_tracking_ref = ','.join(tracking_numbers or ['']) + self._add_delivery_cost_to_so() + + # Override to provide per-package versions... + def cancel_shipment(self): + packages = self._context.get('packages') + pickings_with_package_tracking = self.filtered(lambda p: p.package_carrier_tracking_ref) + for picking in pickings_with_package_tracking: + if packages: + current_packages = packages + else: + current_packages = picking.package_ids + # Packages without a carrier can just be cleared + packages_without_carrier = current_packages.filtered(lambda p: not p.carrier_id and p.carrier_tracking_ref) + packages_without_carrier.write({ + 'carrier_tracking_ref': False, + }) + # Packages with carrier can use the carrier method + packages_with_carrier = current_packages.filtered(lambda p: p.carrier_id and p.carrier_tracking_ref) + carriers = packages_with_carrier.mapped('carrier_id') + for carrier in carriers: + carrier_packages = packages_with_carrier.filtered(lambda p: p.carrier_id == carrier) + carrier.cancel_shipment(self, packages=carrier_packages) + package_refs = ','.join(carrier_packages.mapped('carrier_tracking_ref')) + msg = "Shipment %s cancelled" % package_refs + picking.message_post(body=msg) + carrier_packages.write({'carrier_tracking_ref': False}) + + pickings_without_package_tracking = self - pickings_with_package_tracking + if pickings_without_package_tracking: + # use original on these + super(StockPicking, pickings_without_package_tracking).cancel_shipment() + class StockMove(models.Model): _inherit = 'stock.move' diff --git a/delivery_hibou/tests/test_delivery_hibou.py b/delivery_hibou/tests/test_delivery_hibou.py index 7b47b750..2fc53309 100644 --- a/delivery_hibou/tests/test_delivery_hibou.py +++ b/delivery_hibou/tests/test_delivery_hibou.py @@ -24,11 +24,11 @@ class TestDeliveryHibou(common.TransactionCase): def test_delivery_hibou(self): # Assign a new shipping account - self.partner.shipping_account_id = self.shipping_account + self.partner.shipping_account_ids = self.shipping_account # Assign values to new Carrier test_insurance_value = 600 - test_procurement_priority = '2' + test_procurement_priority = '1' self.carrier.automatic_insurance_value = test_insurance_value self.carrier.procurement_priority = test_procurement_priority @@ -135,9 +135,9 @@ class TestDeliveryHibou(common.TransactionCase): picking_in.carrier_id = self.carrier # This relies heavily on the 'stock' demo data. # Should only have a single move_line_ids and it should not be done at all. - self.assertEqual(picking_in.move_line_ids.mapped('qty_done'), [0.0]) - self.assertEqual(picking_in.move_line_ids.mapped('product_uom_qty'), [35.0]) - self.assertEqual(picking_in.move_line_ids.mapped('product_id.standard_price'), [55.0]) + self.assertEqual(picking_in.move_line_ids.mapped('qty_done'), [0.0, 0.0, 0.0]) + self.assertEqual(picking_in.move_line_ids.mapped('product_uom_qty'), [35.0, 10.0, 12.0]) + self.assertEqual(picking_in.move_line_ids.mapped('product_id.standard_price'), [55.0, 35.0, 1700.0]) self.assertEqual(picking_in.carrier_id._classify_picking(picking=picking_in), 'in') self.assertEqual(picking_in.carrier_id.get_shipper_company(picking=picking_in), diff --git a/delivery_hibou/views/delivery_views.xml b/delivery_hibou/views/delivery_views.xml index 01208bbd..638ef921 100644 --- a/delivery_hibou/views/delivery_views.xml +++ b/delivery_hibou/views/delivery_views.xml @@ -11,4 +11,16 @@ + + + hibou.choose.delivery.package.form + choose.delivery.package + + + + [('product_id', '=', False)] + + + + \ No newline at end of file diff --git a/delivery_hibou/views/stock_views.xml b/delivery_hibou/views/stock_views.xml index 60cfdef9..f806127d 100644 --- a/delivery_hibou/views/stock_views.xml +++ b/delivery_hibou/views/stock_views.xml @@ -1,16 +1,48 @@ + + hibou.stock.quant.package.form + stock.quant.package + + + + + + + hibou.delivery.stock.picking_withcarrier.form.view stock.picking + + +