From efb1b37390d807e60ffaa29dcbb6e06bb72fbc39 Mon Sep 17 00:00:00 2001 From: "Valeriya (vchu)" Date: Mon, 22 Dec 2025 15:25:55 +0100 Subject: [PATCH 1/2] [LINT] delivery,website_sale_collect: apply ruff formatting --- .../delivery/controllers/location_selector.py | 7 +- addons/delivery/models/__init__.py | 24 +- addons/delivery/models/delivery_carrier.py | 342 ++++++++----- addons/delivery/models/delivery_price_rule.py | 40 +- addons/delivery/models/delivery_zip_prefix.py | 16 +- addons/delivery/models/payment_provider.py | 6 +- addons/delivery/models/payment_transaction.py | 10 +- addons/delivery/models/product_category.py | 11 +- addons/delivery/models/res_partner.py | 7 +- addons/delivery/models/sale_order.py | 101 ++-- addons/delivery/models/sale_order_line.py | 10 +- addons/delivery/tests/__init__.py | 12 +- .../delivery/tests/cash_on_delivery_common.py | 1 - addons/delivery/tests/common.py | 1 - .../tests/test_delivery_availability.py | 257 +++++----- addons/delivery/tests/test_delivery_cost.py | 469 ++++++++++-------- .../delivery/tests/test_payment_provider.py | 35 +- .../tests/test_payment_transaction.py | 1 - addons/delivery/tests/test_sale_order.py | 1 - .../wizard/choose_delivery_carrier.py | 53 +- .../controllers/__init__.py | 4 +- .../controllers/delivery.py | 11 +- .../website_sale_collect/controllers/main.py | 16 +- .../controllers/payment.py | 3 +- .../website_sale_collect/models/__init__.py | 18 +- .../models/delivery_carrier.py | 22 +- .../models/payment_provider.py | 4 +- .../models/payment_transaction.py | 10 +- .../models/product_template.py | 9 +- .../models/res_config_settings.py | 4 +- .../website_sale_collect/models/sale_order.py | 27 +- addons/website_sale_collect/models/website.py | 36 +- addons/website_sale_collect/tests/__init__.py | 20 +- addons/website_sale_collect/tests/common.py | 8 +- ...test_click_and_collect_express_checkout.py | 1 - .../tests/test_click_and_collect_flow.py | 10 +- .../tests/test_delivery_carrier.py | 61 +-- .../tests/test_in_store_delivery.py | 3 +- .../tests/test_payment_provider.py | 19 +- .../tests/test_payment_transaction.py | 1 - .../tests/test_product_template.py | 1 - .../tests/test_sale_order.py | 93 ++-- .../tests/test_website.py | 1 - .../views/delivery_carrier_views.xml | 2 +- 44 files changed, 1019 insertions(+), 769 deletions(-) diff --git a/addons/delivery/controllers/location_selector.py b/addons/delivery/controllers/location_selector.py index 5222c1f47fc66..f3996128c9bcf 100644 --- a/addons/delivery/controllers/location_selector.py +++ b/addons/delivery/controllers/location_selector.py @@ -4,10 +4,9 @@ class LocationSelectorController(Controller): - @route('/delivery/set_pickup_location', type='jsonrpc', auth='user') def delivery_set_pickup_location(self, order_id, pickup_location_data): - """ Fetch the order and set the pickup location on the current order. + """Fetch the order and set the pickup location on the current order. :param int order_id: The sales order, as a `sale.order` id. :param str pickup_location_data: The JSON-formatted pickup location address. @@ -18,7 +17,7 @@ def delivery_set_pickup_location(self, order_id, pickup_location_data): @route('/delivery/get_pickup_locations', type='jsonrpc', auth='user') def delivery_get_pickup_locations(self, order_id, zip_code=None): - """ Fetch the order and return the pickup locations close to a given zip code. + """Fetch the order and return the pickup locations close to a given zip code. Determine the country based on GeoIP or fallback on the order's delivery address' country. @@ -30,7 +29,7 @@ def delivery_get_pickup_locations(self, order_id, zip_code=None): order = request.env['sale.order'].browse(order_id) if request.geoip.country_code: country = request.env['res.country'].search( - [('code', '=', request.geoip.country_code)], limit=1, + [('code', '=', request.geoip.country_code)], limit=1 ) else: country = order.partner_shipping_id.country_id diff --git a/addons/delivery/models/__init__.py b/addons/delivery/models/__init__.py index 0acd8064567d5..403f07f6ce4dd 100644 --- a/addons/delivery/models/__init__.py +++ b/addons/delivery/models/__init__.py @@ -1,13 +1,15 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. -from . import delivery_carrier -from . import delivery_price_rule -from . import delivery_zip_prefix -from . import ir_http -from . import ir_module_module -from . import payment_provider -from . import payment_transaction -from . import product_category -from . import res_partner -from . import sale_order -from . import sale_order_line +from . import ( + delivery_carrier, + delivery_price_rule, + delivery_zip_prefix, + ir_http, + ir_module_module, + payment_provider, + payment_transaction, + product_category, + res_partner, + sale_order, + sale_order_line, +) diff --git a/addons/delivery/models/delivery_carrier.py b/addons/delivery/models/delivery_carrier.py index 70b9cb9af19bc..d179da229104b 100644 --- a/addons/delivery/models/delivery_carrier.py +++ b/addons/delivery/models/delivery_carrier.py @@ -15,7 +15,7 @@ class DeliveryCarrier(models.Model): _description = "Delivery Method" _order = 'sequence, id' - ''' A Shipping Provider + """A Shipping Provider In order to add your own external provider, follow these steps: @@ -29,19 +29,15 @@ class DeliveryCarrier(models.Model): _cancel_shipment __get_default_custom_package_code (they are documented hereunder) - ''' + """ - # -------------------------------- # - # Internals for shipping providers # - # -------------------------------- # - - name = fields.Char('Delivery Method', required=True, translate=True) + name = fields.Char(string="Delivery Method", translate=True, required=True) active = fields.Boolean(default=True) sequence = fields.Integer(help="Determine the display order", default=10) - # This field will be overwritten by internal shipping providers by adding their own type (ex: 'fedex') + # This field will be overwritten by internal shipping providers by adding their own type. delivery_type = fields.Selection( - [('base_on_rule', 'Based on Rules'), ('fixed', 'Fixed Price')], - string='Provider', + string="Provider", + selection=[('base_on_rule', "Based on Rules"), ('fixed', "Fixed Price")], default='fixed', required=True, ) @@ -49,86 +45,169 @@ class DeliveryCarrier(models.Model): string="Cash on Delivery", help="Allow customers to choose Cash on Delivery as their payment method.", ) - integration_level = fields.Selection([('rate', 'Get Rate'), ('rate_and_ship', 'Get Rate and Create Shipment')], string="Integration Level", default='rate_and_ship', help="Action while validating Delivery Orders") - prod_environment = fields.Boolean("Environment", help="Set to True if your credentials are certified for production.") - debug_logging = fields.Boolean('Debug logging', help="Log requests in order to ease debugging") - company_id = fields.Many2one('res.company', string='Company', related='product_id.company_id', store=True, readonly=False) - product_id = fields.Many2one('product.product', string='Delivery Product', required=True, ondelete='restrict') - tracking_url = fields.Char(string='Tracking Link', help="This option adds a link for the customer in the portal to track their package easily. Use as a placeholder in your URL.") + integration_level = fields.Selection( + help="Action while validating Delivery Orders.", + selection=[('rate', "Get Rate"), ('rate_and_ship', "Get Rate and Create Shipment")], + default='rate_and_ship', + ) + prod_environment = fields.Boolean( + string="Environment", help="Set to True if your credentials are certified for production." + ) + debug_logging = fields.Boolean( + string="Debug logging", help="Log requests in order to ease debugging" + ) + company_id = fields.Many2one( + comodel_name='res.company', related='product_id.company_id', store=True, readonly=False + ) + product_id = fields.Many2one( + string="Delivery Product", + comodel_name='product.product', + ondelete='restrict', + required=True, + ) + tracking_url = fields.Char( + string="Tracking Link", + help="This option adds a link for the customer in the portal to track their package easily." + " Use as a placeholder in your URL.", + ) currency_id = fields.Many2one(related='product_id.currency_id') invoice_policy = fields.Selection( - selection=[('estimated', "Estimated cost")], string="Invoicing Policy", + help="Estimated Cost: the customer will be invoiced the estimated cost of the shipping.", + selection=[('estimated', "Estimated cost")], default='estimated', required=True, - help="Estimated Cost: the customer will be invoiced the estimated cost of the shipping.", ) - country_ids = fields.Many2many('res.country', 'delivery_carrier_country_rel', 'carrier_id', 'country_id', 'Countries') - state_ids = fields.Many2many('res.country.state', 'delivery_carrier_state_rel', 'carrier_id', 'state_id', 'States') + country_ids = fields.Many2many( + string="Countries", + comodel_name='res.country', + relation='delivery_carrier_country_rel', + column1='carrier_id', + column2='country_id', + ) + state_ids = fields.Many2many( + string="States", + comodel_name='res.country.state', + relation='delivery_carrier_state_rel', + column1='carrier_id', + column2='state_id', + ) zip_prefix_ids = fields.Many2many( - 'delivery.zip.prefix', 'delivery_zip_prefix_rel', 'carrier_id', 'zip_prefix_id', 'Zip Prefixes', - help="Prefixes of zip codes that this delivery method applies to. Note that regular expressions can be used to support countries with varying zip code lengths, i.e. '$' can be added to end of prefix to match the exact zip (e.g. '100$' will only match '100' and not '1000')") - - max_weight = fields.Float('Max Weight', help="If the total weight of the order is over this weight, the method won't be available.") - weight_uom_name = fields.Char(string='Weight unit of measure label', compute='_compute_weight_uom_name') - max_volume = fields.Float('Max Volume', help="If the total volume of the order is over this volume, the method won't be available.") - volume_uom_name = fields.Char(string='Volume unit of measure label', compute='_compute_volume_uom_name') - must_have_tag_ids = fields.Many2many(string='Must Have Tags', comodel_name='product.tag', relation='product_tag_delivery_carrier_must_have_rel', - help="The method is available only if at least one product of the order has one of these tags.") - excluded_tag_ids = fields.Many2many(string='Excluded Tags', comodel_name='product.tag', relation='product_tag_delivery_carrier_excluded_rel', - help="The method is NOT available if at least one product of the order has one of these tags.") + string="Zip Prefixes", + help="Prefixes of zip codes that this delivery method applies to. Note that regular" + " expressions can be used to support countries with varying zip code lengths, i.e. '$'" + " can be added to end of prefix to match the exact zip (e.g. '100$' will only match" + " '100' and not '1000')", + comodel_name='delivery.zip.prefix', + relation='delivery_zip_prefix_rel', + column1='carrier_id', + column2='zip_prefix_id', + ) + + max_weight = fields.Float( + help="If the total weight of the order is over this weight, the method won't be available." + ) + weight_uom_name = fields.Char( + string="Weight unit of measure label", compute='_compute_weight_uom_name' + ) + max_volume = fields.Float( + help="If the total volume of the order is over this volume, the method won't be available." + ) + volume_uom_name = fields.Char( + string="Volume unit of measure label", compute='_compute_volume_uom_name' + ) + must_have_tag_ids = fields.Many2many( + string="Must Have Tags", + help="The method is available only if at least one product of the order has one of these" + " tags.", + comodel_name='product.tag', + relation='product_tag_delivery_carrier_must_have_rel', + ) + excluded_tag_ids = fields.Many2many( + string="Excluded Tags", + help="The method is NOT available if at least one product of the order has one of these" + " tags.", + comodel_name='product.tag', + relation='product_tag_delivery_carrier_excluded_rel', + ) carrier_description = fields.Text( - 'Description', translate=True, - help="A description of the delivery method that you want to communicate to your customers on the Sales Order and sales confirmation email." - "E.g. instructions for customers to follow.") + string="Description", + help="A description of the delivery method that you want to communicate to your customers" + " on the Sales Order and sales confirmation email. E.g. instructions for customers to" + " follow.", + translate=True, + ) - margin = fields.Float(help='This percentage will be added to the shipping price.') - fixed_margin = fields.Float(help='This fixed amount will be added to the shipping price.') - free_over = fields.Boolean('Free if order amount is above', help="If the order total amount (shipping excluded) is above or equal to this value, the customer benefits from a free shipping", default=False) + margin = fields.Float(help="This percentage will be added to the shipping price.") + fixed_margin = fields.Float(help="This fixed amount will be added to the shipping price.") + free_over = fields.Boolean( + string="Free if order amount is above", + help="If the order total amount (shipping excluded) is above or equal to this value, the" + " customer benefits from a free shipping.", + ) amount = fields.Float( - string="Amount", + help="Amount of the order to benefit from a free shipping, expressed in the company" + " currency.", default=1000, - help="Amount of the order to benefit from a free shipping, expressed in the company currency", ) - can_generate_return = fields.Boolean(compute="_compute_can_generate_return") - return_label_on_delivery = fields.Boolean(string="Generate Return Label", help="The return label is automatically generated at the delivery.") - get_return_label_from_portal = fields.Boolean(string="Return Label Accessible from Customer Portal", help="The return label can be downloaded by the customer from the customer portal.") + can_generate_return = fields.Boolean(compute='_compute_can_generate_return') + return_label_on_delivery = fields.Boolean( + string="Generate Return Label", + help="The return label is automatically generated at the delivery.", + ) + get_return_label_from_portal = fields.Boolean( + string="Return Label Accessible from Customer Portal", + help="The return label can be downloaded by the customer from the customer portal.", + ) - supports_shipping_insurance = fields.Boolean(compute="_compute_supports_shipping_insurance") + supports_shipping_insurance = fields.Boolean(compute='_compute_supports_shipping_insurance') shipping_insurance = fields.Integer( - "Insurance Percentage", - help="Shipping insurance is a service which may reimburse senders whose parcels are lost, stolen, and/or damaged in transit.", - default=0 + string="Insurance Percentage", + help="Shipping insurance is a service which may reimburse senders whose parcels are lost," + " stolen, and/or damaged in transit.", + default=0, ) price_rule_ids = fields.One2many( - 'delivery.price.rule', 'carrier_id', 'Pricing Rules', copy=True + string="Pricing Rules", + comodel_name='delivery.price.rule', + inverse_name='carrier_id', + copy=True, ) _margin_not_under_100_percent = models.Constraint( - 'CHECK (margin >= -1)', - 'Margin cannot be lower than -100%', + 'CHECK (margin >= -1)', "Margin cannot be lower than -100%" ) _shipping_insurance_is_percentage = models.Constraint( 'CHECK(shipping_insurance >= 0 AND shipping_insurance <= 100)', - 'The shipping insurance must be a percentage between 0 and 100.', + "The shipping insurance must be a percentage between 0 and 100.", ) @api.constrains('must_have_tag_ids', 'excluded_tag_ids') def _check_tags(self): for carrier in self: if carrier.must_have_tag_ids & carrier.excluded_tag_ids: - raise UserError(_("Delivery method %(name)s cannot have the same tag in both Must Have Tags and Excluded Tags."), name=carrier.name) + raise UserError( + _( + "Delivery method %(name)s cannot have the same tag in both Must Have Tags" + " and Excluded Tags.", + name=carrier.name, + ) + ) def _compute_weight_uom_name(self): - self.weight_uom_name = self.env['product.template']._get_weight_uom_name_from_ir_config_parameter() + self.weight_uom_name = self.env[ + 'product.template' + ]._get_weight_uom_name_from_ir_config_parameter() def _compute_volume_uom_name(self): - self.volume_uom_name = self.env['product.template']._get_volume_uom_name_from_ir_config_parameter() + self.volume_uom_name = self.env[ + 'product.template' + ]._get_volume_uom_name_from_ir_config_parameter() @api.depends('delivery_type') def _compute_can_generate_return(self): @@ -196,7 +275,9 @@ def _match_address(self, partner): if self.state_ids and partner.state_id not in self.state_ids: return False if self.zip_prefix_ids: - regex = re.compile('|'.join(['^' + zip_prefix for zip_prefix in self.zip_prefix_ids.mapped('name')])) + regex = re.compile( + '|'.join(['^' + zip_prefix for zip_prefix in self.zip_prefix_ids.mapped('name')]) + ) if not partner.zip or not re.match(regex, partner.zip.upper()): return False return True @@ -210,8 +291,7 @@ def _match_must_have_tags(self, source): else: raise UserError(_("Invalid source document type")) return not self.must_have_tag_ids or any( - tag in products.all_product_tag_ids - for tag in self.must_have_tag_ids + tag in products.all_product_tag_ids for tag in self.must_have_tag_ids ) def _match_excluded_tags(self, source): @@ -228,13 +308,11 @@ def _match_weight(self, source): self.ensure_one() if source._name == 'sale.order': total_weight = sum( - line.product_id.weight * line.product_qty - for line in source.order_line + line.product_id.weight * line.product_qty for line in source.order_line ) elif source._name == 'stock.picking': total_weight = sum( - move.product_id.weight * move.product_uom_qty - for move in source.move_ids + move.product_id.weight * move.product_uom_qty for move in source.move_ids ) else: raise UserError(_("Invalid source document type")) @@ -244,13 +322,11 @@ def _match_volume(self, source): self.ensure_one() if source._name == 'sale.order': total_volume = sum( - line.product_id.volume * line.product_qty - for line in source.order_line + line.product_id.volume * line.product_qty for line in source.order_line ) elif source._name == 'stock.picking': total_volume = sum( - move.product_id.volume * move.product_uom_qty - for move in source.move_ids + move.product_id.volume * move.product_uom_qty for move in source.move_ids ) else: raise UserError(_("Invalid source document type")) @@ -281,7 +357,10 @@ def _onchange_country_ids(self): def copy_data(self, default=None): vals_list = super().copy_data(default=default) - return [dict(vals, name=self.env._("%s (copy)", carrier.name)) for carrier, vals in zip(self, vals_list)] + return [ + dict(vals, name=self.env._("%s (copy)", carrier.name)) + for carrier, vals in zip(self, vals_list) + ] def _get_delivery_type(self): """Return the delivery type. @@ -296,7 +375,11 @@ def _apply_margins(self, price, order=False): self.ensure_one() if self.delivery_type == 'fixed': return float(price) - fixed_margin_in_sale_currency = self._compute_currency(order, self.fixed_margin, 'company_to_pricelist') if order else self.fixed_margin + fixed_margin_in_sale_currency = ( + self._compute_currency(order, self.fixed_margin, 'company_to_pricelist') + if order + else self.fixed_margin + ) return float(price) * (1.0 + self.margin) + fixed_margin_in_sale_currency # -------------------------- # @@ -304,7 +387,7 @@ def _apply_margins(self, price, order=False): # -------------------------- # def rate_shipment(self, order): - ''' Compute the price of the order shipment + """Compute the price of the order shipment. :param order: record of sale.order :returns: a dict with structure @@ -315,7 +398,7 @@ def rate_shipment(self, order): 'error_message': a string containing an error message, 'warning_message': a string containing a warning message} :rtype: dict - ''' + """ # TODO maybe the currency code? self.ensure_one() if hasattr(self, '%s_rate_shipment' % self.delivery_type): @@ -329,7 +412,7 @@ def rate_shipment(self, order): 'sale', fiscal_position=order.fiscal_position_id, product_price_unit=res['price'], - product_currency=company.currency_id + product_currency=company.currency_id, ) # apply margin on computed price res['price'] = self._apply_margins(res['price'], order) @@ -341,18 +424,20 @@ def rate_shipment(self, order): res['success'] and self.free_over and self.delivery_type != 'base_on_rule' - and self._compute_currency(order, amount_without_delivery, 'pricelist_to_company') >= self.amount + and self._compute_currency(order, amount_without_delivery, 'pricelist_to_company') + >= self.amount ): - res['warning_message'] = _('The shipping is free since the order amount exceeds %.2f.', self.amount) + res['warning_message'] = _( + 'The shipping is free since the order amount exceeds %.2f.', self.amount + ) res['price'] = 0.0 return res - else: - return { - 'success': False, - 'price': 0.0, - 'error_message': _('Error: this delivery method is not available.'), - 'warning_message': False, - } + return { + 'success': False, + 'price': 0.0, + 'error_message': _('Error: this delivery method is not available.'), + 'warning_message': False, + } def log_xml(self, xml_string, func): self.ensure_one() @@ -367,14 +452,16 @@ def log_xml(self, xml_string, func): with db_registry.cursor() as cr: env = api.Environment(cr, SUPERUSER_ID, {}) IrLogging = env['ir.logging'] - IrLogging.sudo().create({'name': 'delivery.carrier', - 'type': 'server', - 'dbname': db_name, - 'level': 'DEBUG', - 'message': xml_string, - 'path': self.delivery_type, - 'func': func, - 'line': 1}) + IrLogging.sudo().create({ + 'name': 'delivery.carrier', + 'type': 'server', + 'dbname': db_name, + 'level': 'DEBUG', + 'message': xml_string, + 'path': self.delivery_type, + 'func': func, + 'line': 1, + }) except psycopg2.Error: pass @@ -382,7 +469,12 @@ def log_xml(self, xml_string, func): # Fixed price shipping, aka a very simple provider # # ------------------------------------------------ # - fixed_price = fields.Float(compute='_compute_fixed_price', inverse='_set_product_fixed_price', store=True, string='Fixed Price') + fixed_price = fields.Float( + string="Fixed Price", + compute='_compute_fixed_price', + inverse='_set_product_fixed_price', + store=True, + ) @api.depends('product_id.list_price', 'product_id.product_tmpl_id.list_price') def _compute_fixed_price(self): @@ -396,15 +488,16 @@ def _set_product_fixed_price(self): def fixed_rate_shipment(self, order): carrier = self._match_address(order.partner_shipping_id) if not carrier: - return {'success': False, - 'price': 0.0, - 'error_message': _('Error: this delivery method is not available for this address.'), - 'warning_message': False} + return { + 'success': False, + 'price': 0.0, + 'error_message': _( + 'Error: this delivery method is not available for this address.' + ), + 'warning_message': False, + } price = order.pricelist_id._get_product_price(self.product_id, 1.0) - return {'success': True, - 'price': price, - 'error_message': False, - 'warning_message': False} + return {'success': True, 'price': price, 'error_message': False, 'warning_message': False} # ----------------------------------- # # Based on rule delivery type methods # @@ -413,40 +506,52 @@ def fixed_rate_shipment(self, order): def base_on_rule_rate_shipment(self, order): carrier = self._match_address(order.partner_shipping_id) if not carrier: - return {'success': False, - 'price': 0.0, - 'error_message': _('Error: this delivery method is not available for this address.'), - 'warning_message': False} + return { + 'success': False, + 'price': 0.0, + 'error_message': _( + 'Error: this delivery method is not available for this address.' + ), + 'warning_message': False, + } try: price_unit = self._get_price_available(order) except UserError as e: - return {'success': False, - 'price': 0.0, - 'error_message': e.args[0], - 'warning_message': False} + return { + 'success': False, + 'price': 0.0, + 'error_message': e.args[0], + 'warning_message': False, + } price_unit = self._compute_currency(order, price_unit, 'company_to_pricelist') - return {'success': True, - 'price': price_unit, - 'error_message': False, - 'warning_message': False} + return { + 'success': True, + 'price': price_unit, + 'error_message': False, + 'warning_message': False, + } def _get_conversion_currencies(self, order, conversion): - company_currency = (self.company_id or self.env['res.company']._get_main_company()).currency_id + company_currency = ( + self.company_id or self.env['res.company']._get_main_company() + ).currency_id pricelist_currency = order.currency_id if conversion == 'company_to_pricelist': return company_currency, pricelist_currency - elif conversion == 'pricelist_to_company': + if conversion == 'pricelist_to_company': return pricelist_currency, company_currency def _compute_currency(self, order, price, conversion): from_currency, to_currency = self._get_conversion_currencies(order, conversion) if from_currency.id == to_currency.id: return price - return from_currency._convert(price, to_currency, order.company_id, order.date_order or fields.Date.today()) + return from_currency._convert( + price, to_currency, order.company_id, order.date_order or fields.Date.today() + ) def _get_price_available(self, order): self.ensure_one() @@ -463,7 +568,9 @@ def _get_price_available(self, order): continue if line.product_id.type == "service": continue - qty = line.product_uom_id._compute_quantity(line.product_uom_qty, line.product_id.uom_id) + qty = line.product_uom_id._compute_quantity( + line.product_uom_qty, line.product_id.uom_id + ) weight += (line.product_id.weight or 0.0) * qty volume += (line.product_id.volume or 0.0) * qty wv += (line.product_id.weight or 0.0) * (line.product_id.volume or 0.0) * qty @@ -478,18 +585,21 @@ def _get_price_available(self, order): weight = self.env.context.get('order_weight') or order.shipping_weight or weight return self._get_price_from_picking(total, weight, volume, quantity, wv=wv) - def _get_price_dict(self, total, weight, volume, quantity, wv=0.): - '''Hook allowing to retrieve dict to be used in _get_price_from_picking() function. - Hook to be overridden when we need to add some field to product and use it in variable factor from price rules. ''' + def _get_price_dict(self, total, weight, volume, quantity, wv=0.0): + """Format delivery price values. + + Hook to be overridden when we need to add some field to product and use it in variable + factor from price rules. + """ return { 'price': total, 'volume': volume, 'weight': weight, 'wv': wv or volume * weight, - 'quantity': quantity + 'quantity': quantity, } - def _get_price_from_picking(self, total, weight, volume, quantity, wv=0.): + def _get_price_from_picking(self, total, weight, volume, quantity, wv=0.0): price = 0.0 criteria_found = False price_dict = self._get_price_dict(total, weight, volume, quantity, wv=wv) diff --git a/addons/delivery/models/delivery_price_rule.py b/addons/delivery/models/delivery_price_rule.py index 20a078be5eb6d..85b182632ca37 100644 --- a/addons/delivery/models/delivery_price_rule.py +++ b/addons/delivery/models/delivery_price_rule.py @@ -3,7 +3,6 @@ from odoo import api, fields, models from odoo.tools import format_amount - VARIABLE_SELECTION = [ ('weight', "Weight"), ('volume', "Volume"), @@ -18,7 +17,15 @@ class DeliveryPriceRule(models.Model): _description = "Delivery Price Rules" _order = 'sequence, list_price, id' - @api.depends('variable', 'operator', 'max_value', 'list_base_price', 'list_price', 'variable_factor', 'currency_id') + @api.depends( + 'variable', + 'operator', + 'max_value', + 'list_base_price', + 'list_price', + 'variable_factor', + 'currency_id', + ) def _compute_name(self): for rule in self: name = 'if %s %s %.02f then' % (rule.variable, rule.operator, rule.max_value) @@ -34,20 +41,33 @@ def _compute_name(self): name = '%s %s times %s' % (name, price, rule.variable_factor) else: name = '%s fixed price %s plus %s times %s' % ( - name, base_price, price, rule.variable_factor + name, + base_price, + price, + rule.variable_factor, ) rule.name = name name = fields.Char(compute='_compute_name') sequence = fields.Integer(required=True, default=10) - carrier_id = fields.Many2one('delivery.carrier', 'Carrier', required=True, index=True, ondelete='cascade') + carrier_id = fields.Many2one( + comodel_name='delivery.carrier', ondelete='cascade', required=True, index=True + ) currency_id = fields.Many2one(related='carrier_id.currency_id') - variable = fields.Selection(selection=VARIABLE_SELECTION, required=True, default='quantity') - operator = fields.Selection([('==', '='), ('<=', '<='), ('<', '<'), ('>=', '>='), ('>', '>')], required=True, default='<=') - max_value = fields.Float('Maximum Value', required=True) - list_base_price = fields.Float(string='Sale Base Price', digits='Product Price', required=True, default=0.0) - list_price = fields.Float('Sale Price', digits='Product Price', required=True, default=0.0) + variable = fields.Selection(selection=VARIABLE_SELECTION, default='quantity', required=True) + operator = fields.Selection( + selection=[('==', '='), ('<=', '<='), ('<', '<'), ('>=', '>='), ('>', '>')], + default='<=', + required=True, + ) + max_value = fields.Float(string="Maximum Value", required=True) + list_base_price = fields.Float( + string="Sale Base Price", digits='Product Price', default=0.0, required=True + ) + list_price = fields.Float( + string="Sale Price", digits='Product Price', default=0.0, required=True + ) variable_factor = fields.Selection( - selection=VARIABLE_SELECTION, string="Variable Factor", required=True, default='weight' + selection=VARIABLE_SELECTION, default='weight', required=True ) diff --git a/addons/delivery/models/delivery_zip_prefix.py b/addons/delivery/models/delivery_zip_prefix.py index 94d8c715b5edf..25f02b4fffbea 100644 --- a/addons/delivery/models/delivery_zip_prefix.py +++ b/addons/delivery/models/delivery_zip_prefix.py @@ -4,18 +4,19 @@ class DeliveryZipPrefix(models.Model): - """ Zip prefix that a delivery.carrier will deliver to. """ + """Zip prefix that a delivery.carrier will deliver to.""" + _name = 'delivery.zip.prefix' - _description = 'Delivery Zip Prefix' + _description = "Delivery Zip Prefix" _order = 'name, id' - name = fields.Char('Prefix', required=True) + name = fields.Char(string="Prefix", required=True) @api.model_create_multi def create(self, vals_list): for vals in vals_list: - # we cannot easily convert a list of prefix names into upper to compare with partner zips - # later on, so let's ensure they are always upper + # we cannot easily convert a list of prefix names into upper to compare with partner + # zips later on, so let's ensure they are always upper vals['name'] = vals['name'].upper() return super().create(vals_list) @@ -24,7 +25,4 @@ def write(self, vals): vals['name'] = vals['name'].upper() return super().write(vals) - _name_uniq = models.Constraint( - 'unique (name)', - 'Prefix already exists!', - ) + _name_uniq = models.Constraint('unique (name)', "Prefix already exists!") diff --git a/addons/delivery/models/payment_provider.py b/addons/delivery/models/payment_provider.py index 7f85225d0bbd8..576d406a89e7a 100644 --- a/addons/delivery/models/payment_provider.py +++ b/addons/delivery/models/payment_provider.py @@ -9,12 +9,12 @@ class PaymentProvider(models.Model): _inherit = 'payment.provider' - custom_mode = fields.Selection(selection_add=[('cash_on_delivery', 'Cash On Delivery')]) + custom_mode = fields.Selection(selection_add=[('cash_on_delivery', "Cash On Delivery")]) # === CRUD METHODS === # def _get_default_payment_method_codes(self): - """ Override of `payment` to return the default payment method codes. """ + """Override of `payment` to return the default payment method codes.""" self.ensure_one() if self.custom_mode != 'cash_on_delivery': return super()._get_default_payment_method_codes() @@ -24,7 +24,7 @@ def _get_default_payment_method_codes(self): @api.model def _get_compatible_providers(self, *args, sale_order_id=None, report=None, **kwargs): - """ Override of payment to exclude COD providers if the delivery method doesn't match. + """Override of payment to exclude COD providers if the delivery method doesn't match. :param int sale_order_id: The sales order to be paid, if any, as a `sale.order` id. :param dict report: The availability report. diff --git a/addons/delivery/models/payment_transaction.py b/addons/delivery/models/payment_transaction.py index 0b26b8e4081b2..1cdabae5681eb 100644 --- a/addons/delivery/models/payment_transaction.py +++ b/addons/delivery/models/payment_transaction.py @@ -7,12 +7,12 @@ class PaymentTransaction(models.Model): _inherit = 'payment.transaction' def _post_process(self): - """ Override of `payment` to confirm orders with the cash_on_delivery payment method and - trigger a picking creation. """ + """Override of `payment` to confirm orders with the cash_on_delivery payment method and + trigger a picking creation.""" cod_pending_txs = self.filtered( lambda tx: tx.provider_id.custom_mode == 'cash_on_delivery' and tx.state == 'pending' ) - cod_pending_txs.sale_order_ids.filtered( - lambda so: so.state == 'draft' - ).with_context(send_email=True).action_confirm() + cod_pending_txs.sale_order_ids.filtered(lambda so: so.state == 'draft').with_context( + send_email=True + ).action_confirm() super()._post_process() diff --git a/addons/delivery/models/product_category.py b/addons/delivery/models/product_category.py index cff4c7ac3ff3f..cb555aa18b999 100644 --- a/addons/delivery/models/product_category.py +++ b/addons/delivery/models/product_category.py @@ -9,6 +9,13 @@ class ProductCategory(models.Model): @api.ondelete(at_uninstall=False) def _unlink_except_delivery_category(self): - delivery_category = self.env.ref('delivery.product_category_deliveries', raise_if_not_found=False) + delivery_category = self.env.ref( + 'delivery.product_category_deliveries', raise_if_not_found=False + ) if delivery_category and delivery_category in self: - raise UserError(_("You cannot delete this product category as it is used on the products linked to delivery methods.")) + raise UserError( + _( + "You cannot delete this product category as it is used on the products linked" + " to delivery methods." + ) + ) diff --git a/addons/delivery/models/res_partner.py b/addons/delivery/models/res_partner.py index dd28de04b2a56..4d932d3ae6eb2 100644 --- a/addons/delivery/models/res_partner.py +++ b/addons/delivery/models/res_partner.py @@ -7,7 +7,12 @@ class ResPartner(models.Model): _inherit = 'res.partner' - property_delivery_carrier_id = fields.Many2one('delivery.carrier', company_dependent=True, string="Delivery Method", help="Used in sales orders.") + property_delivery_carrier_id = fields.Many2one( + string="Delivery Method", + help="Used in sales orders.", + comodel_name='delivery.carrier', + company_dependent=True, + ) is_pickup_location = fields.Boolean() # Whether it is a pickup point address. def _get_delivery_address_domain(self): diff --git a/addons/delivery/models/sale_order.py b/addons/delivery/models/sale_order.py index 370b4b9b0e9e9..b3bd1fdf0fbae 100644 --- a/addons/delivery/models/sale_order.py +++ b/addons/delivery/models/sale_order.py @@ -10,15 +10,22 @@ class SaleOrder(models.Model): _inherit = 'sale.order' pickup_location_data = fields.Json() - carrier_id = fields.Many2one('delivery.carrier', string="Delivery Method", check_company=True, help="Fill this field if you plan to invoice the shipping based on picking.") + carrier_id = fields.Many2one( + string="Delivery Method", + help="Fill this field if you plan to invoice the shipping based on picking.", + comodel_name='delivery.carrier', + check_company=True, + ) delivery_message = fields.Char(readonly=True, copy=False) delivery_set = fields.Boolean(compute='_compute_delivery_state') - recompute_delivery_price = fields.Boolean('Delivery cost should be recomputed') - is_all_service = fields.Boolean("Service Product", compute="_compute_is_service_products") - shipping_weight = fields.Float("Shipping Weight", compute="_compute_shipping_weight", store=True, readonly=False) + recompute_delivery_price = fields.Boolean(string="Delivery cost should be recomputed") + is_all_service = fields.Boolean( + string="Service Product", compute='_compute_is_service_products' + ) + shipping_weight = fields.Float(compute="_compute_shipping_weight", store=True, readonly=False) def _compute_partner_shipping_id(self): - """ Override to reset the delivery address when a pickup location was selected. """ + """Override to reset the delivery address when a pickup location was selected.""" super()._compute_partner_shipping_id() for order in self: if order.partner_shipping_id.is_pickup_location: @@ -27,11 +34,14 @@ def _compute_partner_shipping_id(self): @api.depends('order_line') def _compute_is_service_products(self): for so in self: - so.is_all_service = all(line.product_id.type == 'service' for line in so.order_line.filtered(lambda x: not x.display_type)) + so.is_all_service = all( + line.product_id.type == 'service' + for line in so.order_line.filtered(lambda x: not x.display_type) + ) def _compute_amount_total_without_delivery(self): self.ensure_one() - delivery_cost = sum([l.price_total for l in self.order_line if l.is_delivery]) + delivery_cost = sum([ol.price_total for ol in self.order_line if ol.is_delivery]) return self.amount_total - delivery_cost @api.depends('order_line') @@ -47,20 +57,33 @@ def onchange_order_line(self): self.recompute_delivery_price = True def _get_update_prices_lines(self): - """ Exclude delivery lines from price list recomputation based on product instead of carrier """ + """Exclude delivery lines from pricelist recomputation based on product instead of + carrier.""" lines = super()._get_update_prices_lines() return lines.filtered(lambda line: not line.is_delivery) def _remove_delivery_line(self): - """Remove delivery products from the sales orders""" + """Remove delivery products from the sales orders.""" delivery_lines = self.order_line.filtered("is_delivery") if not delivery_lines: return to_delete = delivery_lines.filtered(lambda x: x.qty_invoiced == 0) if not to_delete: raise UserError( - _('You can not update the shipping costs on an order where it was already invoiced!\n\nThe following delivery lines (product, invoiced quantity and price) have already been processed:\n\n') - + '\n'.join(['- %s: %s x %s' % (line.product_id.with_context(display_default_code=False).display_name, line.qty_invoiced, line.price_unit) for line in delivery_lines]) + _( + 'You can not update the shipping costs on an order where it was already' + ' invoiced!\n\nThe following delivery lines (product, invoiced quantity and' + ' price) have already been processed:\n\n' + ) + + '\n'.join([ + '- %s: %s x %s' + % ( + line.product_id.with_context(display_default_code=False).display_name, + line.qty_invoiced, + line.price_unit, + ) + for line in delivery_lines + ]) ) to_delete.unlink() @@ -72,7 +95,7 @@ def set_delivery_line(self, carrier, amount): return True def _set_pickup_location(self, pickup_location_data): - """ Set the pickup location on the current order. + """Set the pickup location on the current order. Note: self.ensure_one() @@ -90,7 +113,7 @@ def _set_pickup_location(self, pickup_location_data): self.pickup_location_data = pickup_location def _get_pickup_locations(self, zip_code=None, country=None, **kwargs): - """ Return the pickup locations of the delivery method close to a given zip code. + """Return the pickup locations of the delivery method close to a given zip code. Use provided `zip_code` and `country` or the order's delivery address to determine the zip code and the country to use. @@ -141,8 +164,8 @@ def action_open_delivery_wizard(self): 'context': { 'default_order_id': self.id, 'default_carrier_id': self.carrier_id, - 'default_total_weight': self._get_estimated_weight() - } + 'default_total_weight': self._get_estimated_weight(), + }, } def _action_confirm(self): @@ -159,23 +182,29 @@ def _action_confirm(self): zip_code = order_location['zip_code'] country_code = order_location['country_code'] country = order.env['res.country'].search([('code', '=', country_code)]).id - state = order.env['res.country.state'].search([ - ('code', '=', order_location['state']), - ('country_id', '=', country), - ]).id if (order_location.get('state') and country) else None + state = None + if order_location.get('state') and country: + state = ( + order.env['res.country.state'] + .search([('code', '=', order_location['state']), ('country_id', '=', country)]) + .id + ) parent_id = order.partner_shipping_id.id email = order.partner_shipping_id.email phone = order.partner_shipping_id.phone # Check if the current partner has a partner of type 'delivery' with the same address. - existing_partner = order.env['res.partner'].search([ - ('street', '=', street), - ('city', '=', city), - ('state_id', '=', state), - ('country_id', '=', country), - ('parent_id', '=', parent_id), - ('type', '=', 'delivery'), - ], limit=1) + existing_partner = order.env['res.partner'].search( + [ + ('street', '=', street), + ('city', '=', city), + ('state_id', '=', state), + ('country_id', '=', country), + ('parent_id', '=', parent_id), + ('type', '=', 'delivery'), + ], + limit=1, + ) shipping_partner = existing_partner or order.env['res.partner'].create({ 'parent_id': parent_id, @@ -190,7 +219,9 @@ def _action_confirm(self): 'phone': phone, 'is_pickup_location': True, }) - order.with_context(update_delivery_shipping_partner=True).write({'partner_shipping_id': shipping_partner}) + order.with_context(update_delivery_shipping_partner=True).write({ + 'partner_shipping_id': shipping_partner + }) return super()._action_confirm() def _prepare_delivery_line_vals(self, carrier, price_unit): @@ -209,8 +240,7 @@ def _prepare_delivery_line_vals(self, carrier, price_unit): # Create the sales order line if carrier.product_id.description_sale: - so_description = '%s: %s' % (carrier.name, - carrier.product_id.description_sale) + so_description = '%s: %s' % (carrier.name, carrier.product_id.description_sale) else: so_description = carrier.name values = { @@ -222,7 +252,7 @@ def _prepare_delivery_line_vals(self, carrier, price_unit): 'tax_ids': [(6, 0, taxes_ids)], 'is_delivery': True, } - if carrier.free_over and self.currency_id.is_zero(price_unit) : + if carrier.free_over and self.currency_id.is_zero(price_unit): values['name'] = _('%s\nFree Shipping', values['name']) if self.order_line: values['sequence'] = self.order_line[-1].sequence + 1 @@ -241,12 +271,17 @@ def _compute_shipping_weight(self): def _get_estimated_weight(self): self.ensure_one() weight = 0.0 - for order_line in self.order_line.filtered(lambda l: l.product_id.type == 'consu' and not l.is_delivery and not l.display_type and l.product_uom_qty > 0): + for order_line in self.order_line.filtered( + lambda ol: ol.product_id.type == 'consu' + and not ol.is_delivery + and not ol.display_type + and ol.product_uom_qty > 0 + ): weight += order_line.product_qty * order_line.product_id.weight return weight def _update_order_line_info(self, product_id, quantity, **kwargs): - """ Override of `sale` to recompute the delivery prices. + """Override of `sale` to recompute the delivery prices. :param int product_id: The product, as a `product.product` id. :return: The unit price price of the product, based on the pricelist of the sale order and diff --git a/addons/delivery/models/sale_order_line.py b/addons/delivery/models/sale_order_line.py index ccd6b448d048f..6fcfce2db2d68 100644 --- a/addons/delivery/models/sale_order_line.py +++ b/addons/delivery/models/sale_order_line.py @@ -8,7 +8,7 @@ class SaleOrderLine(models.Model): is_delivery = fields.Boolean(string="Is a Delivery", default=False) product_qty = fields.Float( - string='Product Qty', compute='_compute_product_qty', digits='Product Unit' + string="Product Qty", compute='_compute_product_qty', digits='Product Unit' ) recompute_delivery_price = fields.Boolean(related='order_id.recompute_delivery_price') @@ -36,10 +36,9 @@ def _is_delivery(self): def _get_invalid_delivery_weight_lines(self): """Retrieve lines containing physical products with no weight defined.""" return self.filtered( - lambda line: - line.product_qty > 0 - and line.product_id.type not in ('service', 'combo') - and line.product_id.weight == 0, + lambda line: line.product_qty > 0 + and line.product_id.type not in ('service', 'combo') + and line.product_id.weight == 0 ) # override to allow deletion of delivery line in a confirmed order @@ -52,7 +51,6 @@ def _check_line_unlink(self): :rtype: recordset sale.order.line :returns: set of lines that cannot be deleted """ - undeletable_lines = super()._check_line_unlink() return undeletable_lines.filtered(lambda line: not line.is_delivery) diff --git a/addons/delivery/tests/__init__.py b/addons/delivery/tests/__init__.py index 59a0c5f869917..7f36e7d33c491 100644 --- a/addons/delivery/tests/__init__.py +++ b/addons/delivery/tests/__init__.py @@ -1,7 +1,9 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. -from . import test_delivery_cost -from . import test_delivery_availability -from . import test_payment_provider -from . import test_payment_transaction -from . import test_sale_order +from . import ( + test_delivery_availability, + test_delivery_cost, + test_payment_provider, + test_payment_transaction, + test_sale_order, +) diff --git a/addons/delivery/tests/cash_on_delivery_common.py b/addons/delivery/tests/cash_on_delivery_common.py index 0c3013595a37a..d5efe6ab08183 100644 --- a/addons/delivery/tests/cash_on_delivery_common.py +++ b/addons/delivery/tests/cash_on_delivery_common.py @@ -5,7 +5,6 @@ class CashOnDeliveryCommon(PaymentCustomCommon, DeliveryCommon): - @classmethod def setUpClass(cls): super().setUpClass() diff --git a/addons/delivery/tests/common.py b/addons/delivery/tests/common.py index aee1639fb500c..f11a6eee7478e 100644 --- a/addons/delivery/tests/common.py +++ b/addons/delivery/tests/common.py @@ -4,7 +4,6 @@ class DeliveryCommon(TransactionCase): - @classmethod def setUpClass(cls): super().setUpClass() diff --git a/addons/delivery/tests/test_delivery_availability.py b/addons/delivery/tests/test_delivery_availability.py index 52746817d3f16..3dff19a9259fe 100644 --- a/addons/delivery/tests/test_delivery_availability.py +++ b/addons/delivery/tests/test_delivery_availability.py @@ -9,96 +9,91 @@ @tagged('post_install', '-at_install') class TestDeliveryAvailability(DeliveryCommon, SaleCommon): - @classmethod def setUpClass(cls): super().setUpClass() - cls.must_have_tag = cls.env['product.tag'].create({ - 'name': 'Must Have', - }) - cls.exclude_tag = cls.env['product.tag'].create({ - 'name': 'Exclude', - }) + cls.must_have_tag = cls.env['product.tag'].create({'name': 'Must Have'}) + cls.exclude_tag = cls.env['product.tag'].create({'name': 'Exclude'}) cls.non_restricted_carrier = cls._prepare_carrier(cls.carrier.product_id) cls.product_line = cls.sale_order.order_line.filtered( - lambda sol: sol.product_id == cls.product, + lambda sol: sol.product_id == cls.product ) cls.product_line.product_uom_qty = 1.0 def test_00_order_with_heavy_product_simple(self): - self.carrier.write({ - 'max_weight': 10.0, - }) + self.carrier.write({'max_weight': 10.0}) - self.product.write({ - 'weight': 11.0, - }) + self.product.write({'weight': 11.0}) - delivery_wizard = Form(self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_order.id, - 'default_carrier_id': self.non_restricted_carrier.id, - })) + delivery_wizard = Form( + self.env['choose.delivery.carrier'].with_context({ + 'default_order_id': self.sale_order.id, + 'default_carrier_id': self.non_restricted_carrier.id, + }) + ) choose_delivery_carrier = delivery_wizard.save() - self.assertFalse(self.carrier.id in choose_delivery_carrier.available_carrier_ids.ids, "Product weight exceeds carrier's max weight") + self.assertFalse( + self.carrier.id in choose_delivery_carrier.available_carrier_ids.ids, + "Product weight exceeds carrier's max weight", + ) def test_01_order_with_heavy_product_different_uom(self): - self.carrier.write({ - 'max_weight': 10.0, - }) + self.carrier.write({'max_weight': 10.0}) - self.product.write({ - 'weight': 1.0, - }) + self.product.write({'weight': 1.0}) - self.product_line.write({ - 'product_uom_id': self.uom_dozen.id, - }) + self.product_line.write({'product_uom_id': self.uom_dozen.id}) - delivery_wizard = Form(self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_order.id, - 'default_carrier_id': self.non_restricted_carrier.id, - })) + delivery_wizard = Form( + self.env['choose.delivery.carrier'].with_context({ + 'default_order_id': self.sale_order.id, + 'default_carrier_id': self.non_restricted_carrier.id, + }) + ) choose_delivery_carrier = delivery_wizard.save() - self.assertFalse(self.carrier.id in choose_delivery_carrier.available_carrier_ids.ids, "Order lines should be converted to the default UoM before checking weight") + self.assertFalse( + self.carrier.id in choose_delivery_carrier.available_carrier_ids.ids, + "Order lines should be converted to the default UoM before checking weight", + ) def test_02_order_with_big_product_simple(self): - self.carrier.write({ - 'max_volume': 10.0, - }) + self.carrier.write({'max_volume': 10.0}) - self.product.write({ - 'volume': 11.0, - }) + self.product.write({'volume': 11.0}) - delivery_wizard = Form(self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_order.id, - 'default_carrier_id': self.non_restricted_carrier.id, - })) + delivery_wizard = Form( + self.env['choose.delivery.carrier'].with_context({ + 'default_order_id': self.sale_order.id, + 'default_carrier_id': self.non_restricted_carrier.id, + }) + ) choose_delivery_carrier = delivery_wizard.save() - self.assertFalse(self.carrier.id in choose_delivery_carrier.available_carrier_ids.ids, "Product volume exceeds carrier's max volume") + self.assertFalse( + self.carrier.id in choose_delivery_carrier.available_carrier_ids.ids, + "Product volume exceeds carrier's max volume", + ) def test_03_order_with_big_product_different_uom(self): - self.carrier.write({ - 'max_volume': 10.0, - }) + self.carrier.write({'max_volume': 10.0}) - self.product.write({ - 'volume': 1.0, - }) + self.product.write({'volume': 1.0}) - self.product_line.write({ - 'product_uom_id': self.uom_dozen.id, - }) + self.product_line.write({'product_uom_id': self.uom_dozen.id}) - delivery_wizard = Form(self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_order.id, - 'default_carrier_id': self.non_restricted_carrier.id, - })) + delivery_wizard = Form( + self.env['choose.delivery.carrier'].with_context({ + 'default_order_id': self.sale_order.id, + 'default_carrier_id': self.non_restricted_carrier.id, + }) + ) choose_delivery_carrier = delivery_wizard.save() - self.assertFalse(self.carrier.id in choose_delivery_carrier.available_carrier_ids.ids, "Order lines should be converted to the default UoM before checking volume") + self.assertFalse( + self.carrier.id in choose_delivery_carrier.available_carrier_ids.ids, + "Order lines should be converted to the default UoM before checking volume", + ) def test_04_check_must_have_tag(self): self.carrier.must_have_tag_ids = [ @@ -106,48 +101,60 @@ def test_04_check_must_have_tag(self): Command.link(self.must_have_tag.copy({'name': "Alt Must Have"}).id), ] - delivery_wizard = Form(self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_order.id, - 'default_carrier_id': self.non_restricted_carrier.id, - })) + delivery_wizard = Form( + self.env['choose.delivery.carrier'].with_context({ + 'default_order_id': self.sale_order.id, + 'default_carrier_id': self.non_restricted_carrier.id, + }) + ) choose_delivery_carrier = delivery_wizard.save() - self.assertFalse(self.carrier.id in choose_delivery_carrier.available_carrier_ids.ids, "Delivery method's must have tag is not set on any product in the order") + self.assertFalse( + self.carrier.id in choose_delivery_carrier.available_carrier_ids.ids, + "Delivery method's must have tag is not set on any product in the order", + ) - self.product.write({ - 'product_tag_ids': [self.must_have_tag.id], - }) - delivery_wizard = Form(self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_order.id, - 'default_carrier_id': self.non_restricted_carrier.id, - })) + self.product.write({'product_tag_ids': [self.must_have_tag.id]}) + delivery_wizard = Form( + self.env['choose.delivery.carrier'].with_context({ + 'default_order_id': self.sale_order.id, + 'default_carrier_id': self.non_restricted_carrier.id, + }) + ) choose_delivery_carrier = delivery_wizard.save() self.assertIn( self.carrier, choose_delivery_carrier.available_carrier_ids, - "Delivery method should be available if at least one must-have tag is present in the products", + "Delivery method should be available if at least one must-have tag is present in the" + " products", ) def test_05_check_excluded_tag(self): - self.carrier.write({ - 'excluded_tag_ids': [self.exclude_tag.id], - }) + self.carrier.write({'excluded_tag_ids': [self.exclude_tag.id]}) - delivery_wizard = Form(self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_order.id, - 'default_carrier_id': self.non_restricted_carrier.id, - })) + delivery_wizard = Form( + self.env['choose.delivery.carrier'].with_context({ + 'default_order_id': self.sale_order.id, + 'default_carrier_id': self.non_restricted_carrier.id, + }) + ) choose_delivery_carrier = delivery_wizard.save() - self.assertTrue(self.carrier.id in choose_delivery_carrier.available_carrier_ids.ids, "Delivery method's excluded tag is not set on any product in the order") + self.assertTrue( + self.carrier.id in choose_delivery_carrier.available_carrier_ids.ids, + "Delivery method's excluded tag is not set on any product in the order", + ) - self.product.write({ - 'product_tag_ids': [self.exclude_tag.id], - }) - delivery_wizard = Form(self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_order.id, - 'default_carrier_id': self.non_restricted_carrier.id, - })) + self.product.write({'product_tag_ids': [self.exclude_tag.id]}) + delivery_wizard = Form( + self.env['choose.delivery.carrier'].with_context({ + 'default_order_id': self.sale_order.id, + 'default_carrier_id': self.non_restricted_carrier.id, + }) + ) choose_delivery_carrier = delivery_wizard.save() - self.assertFalse(self.carrier.id in choose_delivery_carrier.available_carrier_ids.ids, "Delivery method's excluded tag is set on one product in the order") + self.assertFalse( + self.carrier.id in choose_delivery_carrier.available_carrier_ids.ids, + "Delivery method's excluded tag is set on one product in the order", + ) def test_06_check_tags_complex(self): self.carrier.write({ @@ -155,42 +162,54 @@ def test_06_check_tags_complex(self): 'excluded_tag_ids': [self.exclude_tag.id], }) - delivery_wizard = Form(self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_order.id, - 'default_carrier_id': self.non_restricted_carrier.id, - })) + delivery_wizard = Form( + self.env['choose.delivery.carrier'].with_context({ + 'default_order_id': self.sale_order.id, + 'default_carrier_id': self.non_restricted_carrier.id, + }) + ) choose_delivery_carrier = delivery_wizard.save() - self.assertFalse(self.carrier.id in choose_delivery_carrier.available_carrier_ids.ids, "Delivery method's must have tag is not set on any product in the order") + self.assertFalse( + self.carrier.id in choose_delivery_carrier.available_carrier_ids.ids, + "Delivery method's must have tag is not set on any product in the order", + ) - self.product.write({ - 'product_tag_ids': [self.must_have_tag.id], - }) - delivery_wizard = Form(self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_order.id, - 'default_carrier_id': self.non_restricted_carrier.id, - })) + self.product.write({'product_tag_ids': [self.must_have_tag.id]}) + delivery_wizard = Form( + self.env['choose.delivery.carrier'].with_context({ + 'default_order_id': self.sale_order.id, + 'default_carrier_id': self.non_restricted_carrier.id, + }) + ) choose_delivery_carrier = delivery_wizard.save() - self.assertTrue(self.carrier.id in choose_delivery_carrier.available_carrier_ids.ids, "Delivery method's must have tag is set on one product in the order") + self.assertTrue( + self.carrier.id in choose_delivery_carrier.available_carrier_ids.ids, + "Delivery method's must have tag is set on one product in the order", + ) - self.product.write({ - 'product_tag_ids': [self.exclude_tag.id, self.must_have_tag.id], - }) - delivery_wizard = Form(self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_order.id, - 'default_carrier_id': self.non_restricted_carrier.id, - })) + self.product.write({'product_tag_ids': [self.exclude_tag.id, self.must_have_tag.id]}) + delivery_wizard = Form( + self.env['choose.delivery.carrier'].with_context({ + 'default_order_id': self.sale_order.id, + 'default_carrier_id': self.non_restricted_carrier.id, + }) + ) choose_delivery_carrier = delivery_wizard.save() - self.assertFalse(self.carrier.id in choose_delivery_carrier.available_carrier_ids.ids, "Delivery method's excluded tag is set on one product in the order") + self.assertFalse( + self.carrier.id in choose_delivery_carrier.available_carrier_ids.ids, + "Delivery method's excluded tag is set on one product in the order", + ) - self.product.write({ - 'product_tag_ids': [self.must_have_tag.id], - }) - self.service_product.write({ - 'product_tag_ids': [self.exclude_tag.id], - }) - delivery_wizard = Form(self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_order.id, - 'default_carrier_id': self.non_restricted_carrier.id, - })) + self.product.write({'product_tag_ids': [self.must_have_tag.id]}) + self.service_product.write({'product_tag_ids': [self.exclude_tag.id]}) + delivery_wizard = Form( + self.env['choose.delivery.carrier'].with_context({ + 'default_order_id': self.sale_order.id, + 'default_carrier_id': self.non_restricted_carrier.id, + }) + ) choose_delivery_carrier = delivery_wizard.save() - self.assertFalse(self.carrier.id in choose_delivery_carrier.available_carrier_ids.ids, "Delivery method's excluded tag is set on one product in the order") + self.assertFalse( + self.carrier.id in choose_delivery_carrier.available_carrier_ids.ids, + "Delivery method's excluded tag is set on one product in the order", + ) diff --git a/addons/delivery/tests/test_delivery_cost.py b/addons/delivery/tests/test_delivery_cost.py index 08555ec4565d6..d072532fb9cec 100644 --- a/addons/delivery/tests/test_delivery_cost.py +++ b/addons/delivery/tests/test_delivery_cost.py @@ -12,7 +12,6 @@ @tagged('post_install', '-at_install') class TestDeliveryCost(DeliveryCommon, SaleCommon): - @classmethod def setUpClass(cls): super().setUpClass() @@ -24,8 +23,7 @@ def setUpClass(cls): cls.product.weight = 1.0 cls.product_delivery_normal = cls._prepare_carrier_product( - name='Normal Delivery Charges', - list_price=10.0, + name='Normal Delivery Charges', list_price=10.0 ) cls.normal_delivery = cls._prepare_carrier( product=cls.product_delivery_normal, @@ -35,11 +33,7 @@ def setUpClass(cls): ) cls.partner_4 = cls.env['res.partner'].create({ 'name': 'Another Customer', - 'child_ids': [ - Command.create({ - 'name': "Another Customer's Address", - }) - ] + 'child_ids': [Command.create({'name': "Another Customer's Address"})], }) cls.partner_address_13 = cls.partner_4.child_ids cls.product_uom_hour = cls.env.ref('uom.product_uom_hour') @@ -52,12 +46,7 @@ def test_00_delivery_cost(self): 'partner_id': self.partner.id, 'partner_invoice_id': self.partner.id, 'partner_shipping_id': self.partner.id, - 'order_line': [ - Command.create({ - 'product_id': self.product.id, - 'price_unit': 750.00, - }) - ], + 'order_line': [Command.create({'product_id': self.product.id, 'price_unit': 750.00})], }) # I add delivery cost in Sales order @@ -65,7 +54,7 @@ def test_00_delivery_cost(self): 'code': 'X2020', 'name': 'Product Sales - (test)', 'account_type': 'income', - 'tag_ids': [Command.set(self.env.ref('account.account_tag_operating').ids)] + 'tag_ids': [Command.set(self.env.ref('account.account_tag_operating').ids)], }) self.product_consultant = self.env['product.product'].create({ @@ -74,26 +63,39 @@ def test_00_delivery_cost(self): 'standard_price': 30.0, 'uom_id': self.product_uom_hour.id, 'name': 'Service', - 'type': 'service' + 'type': 'service', }) # I add delivery cost in Sales order - delivery_wizard = Form(self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_normal_delivery_charges.id, - 'default_carrier_id': self.normal_delivery.id - })) + delivery_wizard = Form( + self.env['choose.delivery.carrier'].with_context({ + 'default_order_id': self.sale_normal_delivery_charges.id, + 'default_carrier_id': self.normal_delivery.id, + }) + ) choose_delivery_carrier = delivery_wizard.save() choose_delivery_carrier.button_confirm() # I check sales order after added delivery cost line = self.sale_normal_delivery_charges.order_line.filtered_domain([ - ('product_id', '=', self.normal_delivery.product_id.id)]) + ('product_id', '=', self.normal_delivery.product_id.id) + ]) self.assertEqual(len(line), 1, "Delivery cost is not Added") - zin = str(delivery_wizard.display_price) + " " + str(delivery_wizard.delivery_price) + ' ' + line.company_id.country_id.code + line.company_id.name - self.assertEqual(float_compare(line.price_subtotal, 10.0, precision_digits=2), 0, - "Delivery cost does not correspond to 10.0. %s %s" % (line.price_subtotal, zin)) + zin = ( + str(delivery_wizard.display_price) + + " " + + str(delivery_wizard.delivery_price) + + ' ' + + line.company_id.country_id.code + + line.company_id.name + ) + self.assertEqual( + float_compare(line.price_subtotal, 10.0, precision_digits=2), + 0, + "Delivery cost does not correspond to 10.0. %s %s" % (line.price_subtotal, zin), + ) # I confirm the sales order @@ -114,81 +116,99 @@ def test_00_delivery_cost(self): 'product_id': self.product.id, 'product_uom_qty': 30, 'price_unit': 38.25, - }) + }), ], }) # I add free delivery cost in Sales order - delivery_wizard = Form(self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.delivery_sale_order_cost.id, - 'default_carrier_id': self.free_delivery.id - })) + delivery_wizard = Form( + self.env['choose.delivery.carrier'].with_context({ + 'default_order_id': self.delivery_sale_order_cost.id, + 'default_carrier_id': self.free_delivery.id, + }) + ) choose_delivery_carrier = delivery_wizard.save() choose_delivery_carrier.button_confirm() # I check sales order after adding delivery cost line = self.delivery_sale_order_cost.order_line.filtered_domain([ - ('product_id', '=', self.free_delivery.product_id.id)]) + ('product_id', '=', self.free_delivery.product_id.id) + ]) self.assertEqual(len(line), 1, "Delivery cost is not Added") - self.assertEqual(float_compare(line.price_subtotal, 0, precision_digits=2), 0, - "Delivery cost is not correspond.") + self.assertEqual( + float_compare(line.price_subtotal, 0, precision_digits=2), + 0, + "Delivery cost is not correspond.", + ) # I set default delivery policy self.env['res.config.settings'].create({}).execute() def test_01_delivery_cost_from_pricelist(self): - """ This test aims to validate the use of a pricelist to compute the delivery cost in the case the associated - product of the delivery method is defined in the pricelist """ - + """This test aims to validate the use of a pricelist to compute the delivery cost in the + case the associated product of the delivery method is defined in the pricelist.""" # Create pricelist with a custom price for the standard delivery method my_pricelist = self.env['product.pricelist'].create({ 'name': 'shipping_cost_change', - 'item_ids': [Command.create({ - 'compute_price': 'fixed', - 'fixed_price': 5, - 'applied_on': '0_product_variant', - 'product_id': self.normal_delivery.product_id.id, - })], + 'item_ids': [ + Command.create({ + 'compute_price': 'fixed', + 'fixed_price': 5, + 'applied_on': '0_product_variant', + 'product_id': self.normal_delivery.product_id.id, + }) + ], }) # Create sales order with Normal Delivery Charges sale_pricelist_based_delivery_charges = self.env['sale.order'].create({ 'partner_id': self.partner.id, 'pricelist_id': my_pricelist.id, - 'order_line': [Command.create({ - 'product_id': self.product.id, - 'product_uom_qty': 1, - 'price_unit': 750.00, - })], + 'order_line': [ + Command.create({ + 'product_id': self.product.id, + 'product_uom_qty': 1, + 'price_unit': 750.00, + }) + ], }) # Add of delivery cost in Sales order - delivery_wizard = Form(self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': sale_pricelist_based_delivery_charges.id, - 'default_carrier_id': self.normal_delivery.id - })) - self.assertEqual(delivery_wizard.delivery_price, 5.0, "Delivery cost does not correspond to 5.0 in wizard") + delivery_wizard = Form( + self.env['choose.delivery.carrier'].with_context({ + 'default_order_id': sale_pricelist_based_delivery_charges.id, + 'default_carrier_id': self.normal_delivery.id, + }) + ) + self.assertEqual( + delivery_wizard.delivery_price, + 5.0, + "Delivery cost does not correspond to 5.0 in wizard", + ) delivery_wizard.save().button_confirm() line = sale_pricelist_based_delivery_charges.order_line.filtered_domain([ - ('product_id', '=', self.normal_delivery.product_id.id)]) + ('product_id', '=', self.normal_delivery.product_id.id) + ]) self.assertEqual(len(line), 1, "Delivery cost hasn't been added to SO") self.assertEqual(line.price_subtotal, 5.0, "Delivery cost does not correspond to 5.0") def test_02_delivery_cost_from_different_currency(self): - """ This test aims to validate the use of a pricelist using a different currency to compute the delivery cost in - the case the associated product of the delivery method is defined in the pricelist """ - + """This test aims to validate the use of a pricelist using a different currency to compute + the delivery cost in the case the associated product of the delivery method is defined in + the pricelist.""" # Create pricelist with a custom price for the standard delivery method my_pricelist = self.env['product.pricelist'].create({ 'name': 'shipping_cost_change', - 'item_ids': [Command.create({ - 'compute_price': 'fixed', - 'fixed_price': 5, - 'applied_on': '0_product_variant', - 'product_id': self.normal_delivery.product_id.id, - })], + 'item_ids': [ + Command.create({ + 'compute_price': 'fixed', + 'fixed_price': 5, + 'applied_on': '0_product_variant', + 'product_id': self.normal_delivery.product_id.id, + }) + ], 'currency_id': self.env.ref('base.EUR').id, }) @@ -196,48 +216,60 @@ def test_02_delivery_cost_from_different_currency(self): sale_pricelist_based_delivery_charges = self.env['sale.order'].create({ 'partner_id': self.partner.id, 'pricelist_id': my_pricelist.id, - 'order_line': [Command.create({ - 'product_id': self.product.id, - 'product_uom_qty': 1, - 'price_unit': 750.00, - })], + 'order_line': [ + Command.create({ + 'product_id': self.product.id, + 'product_uom_qty': 1, + 'price_unit': 750.00, + }) + ], }) # Add of delivery cost in Sales order - delivery_wizard = Form(self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': sale_pricelist_based_delivery_charges.id, - 'default_carrier_id': self.normal_delivery.id - })) - self.assertEqual(delivery_wizard.delivery_price, 5.0, "Delivery cost does not correspond to 5.0 in wizard") + delivery_wizard = Form( + self.env['choose.delivery.carrier'].with_context({ + 'default_order_id': sale_pricelist_based_delivery_charges.id, + 'default_carrier_id': self.normal_delivery.id, + }) + ) + self.assertEqual( + delivery_wizard.delivery_price, + 5.0, + "Delivery cost does not correspond to 5.0 in wizard", + ) delivery_wizard.save().button_confirm() line = sale_pricelist_based_delivery_charges.order_line.filtered_domain([ - ('product_id', '=', self.normal_delivery.product_id.id)]) + ('product_id', '=', self.normal_delivery.product_id.id) + ]) self.assertEqual(len(line), 1, "Delivery cost hasn't been added to SO") self.assertEqual(line.price_subtotal, 5.0, "Delivery cost does not correspond to 5.0") def test_01_taxes_on_delivery_cost(self): # Creating taxes and fiscal position - self.env.ref('base.group_user').write({'implied_ids': [(4, self.env.ref('product.group_product_pricelist').id)]}) - - fiscal_position = self.env['account.fiscal.position'].create({ - 'name': 'fiscal_pos_a', + self.env.ref('base.group_user').write({ + 'implied_ids': [(4, self.env.ref('product.group_product_pricelist').id)] }) - tax_price_include, tax_price_exclude = self.env['account.tax'].create([{ - 'name': '10% inc', - 'type_tax_use': 'sale', - 'amount_type': 'percent', - 'amount': 10, - 'price_include_override': 'tax_included', - 'include_base_amount': True, - }, { - 'name': '15% exc', - 'type_tax_use': 'sale', - 'amount_type': 'percent', - 'amount': 15, - 'fiscal_position_ids': [Command.link(fiscal_position.id)], - }]) + + fiscal_position = self.env['account.fiscal.position'].create({'name': 'fiscal_pos_a'}) + tax_price_include, tax_price_exclude = self.env['account.tax'].create([ + { + 'name': '10% inc', + 'type_tax_use': 'sale', + 'amount_type': 'percent', + 'amount': 10, + 'price_include_override': 'tax_included', + 'include_base_amount': True, + }, + { + 'name': '15% exc', + 'type_tax_use': 'sale', + 'amount_type': 'percent', + 'amount': 15, + 'fiscal_position_ids': [Command.link(fiscal_position.id)], + }, + ]) tax_price_exclude.original_tax_ids = tax_price_include # Setting tax on delivery product @@ -256,11 +288,17 @@ def test_01_taxes_on_delivery_cost(self): line.product_uom_qty = 1.0 sale_order = order_form.save() - self.assertRecordValues(sale_order.order_line, [{'price_subtotal': 9.09, 'price_total': 10.45}]) + self.assertRecordValues( + sale_order.order_line, [{'price_subtotal': 9.09, 'price_total': 10.45}] + ) - # Now trying to add the delivery line using the delivery wizard, the results should be the same as before - delivery_wizard = Form(self.env['choose.delivery.carrier'].with_context(default_order_id=sale_order.id, - default_carrier_id=self.normal_delivery.id)) + # Now trying to add the delivery line using the delivery wizard, the results should be the + # same as before + delivery_wizard = Form( + self.env['choose.delivery.carrier'].with_context( + default_order_id=sale_order.id, default_carrier_id=self.normal_delivery.id + ) + ) choose_delivery_carrier = delivery_wizard.save() choose_delivery_carrier.button_confirm() @@ -279,27 +317,27 @@ def test_estimated_weight(self): sale_order = self.env['sale.order'].create({ 'partner_id': self.partner.id, 'order_line': [ - Command.create({ - 'product_id': self.product.id, - 'product_uom_qty': 1, - }), - Command.create({ - 'product_id': self.product.id, - 'product_uom_qty': -1, - }), + Command.create({'product_id': self.product.id, 'product_uom_qty': 1}), + Command.create({'product_id': self.product.id, 'product_uom_qty': -1}), ], }) shipping_weight = sale_order._get_estimated_weight() - self.assertEqual(shipping_weight, self.product.weight, "Only positive quantity products' weights should be included in estimated weight") + self.assertEqual( + shipping_weight, + self.product.weight, + "Only positive quantity products' weights should be included in estimated weight", + ) def test_get_invalid_delivery_weight_lines(self): """Ensure we can retrieve lines that contain physical products without a weight value.""" order = self.empty_order weightless_product = self._create_product(weight=0.0, list_price=50.0) - combos = self.env['product.combo'].create([{ + combos = self.env['product.combo'].create([ + { 'name': "Combo A", 'combo_item_ids': [Command.create({'product_id': self.product.id})], - }, { + }, + { 'name': "Combo B", 'combo_item_ids': [Command.create({'product_id': weightless_product.id})], }, @@ -310,11 +348,14 @@ def test_get_invalid_delivery_weight_lines(self): 'product_id': combo_product.id, }) order.order_line = [ - *[Command.create({ - 'product_id': product.id, - 'combo_item_id': combo.combo_item_ids.id, - 'linked_line_id': combo_line.id, - }) for product, combo in zip(self.product + weightless_product, combos)], + *[ + Command.create({ + 'product_id': product.id, + 'combo_item_id': combo.combo_item_ids.id, + 'linked_line_id': combo_line.id, + }) + for product, combo in zip(self.product + weightless_product, combos) + ], Command.create({'product_id': weightless_product.id, 'product_uom_qty': 0}), Command.create({'product_id': self.service_product.id}), Command.create({'display_type': 'line_section', 'name': "Misc."}), @@ -322,30 +363,27 @@ def test_get_invalid_delivery_weight_lines(self): ] error_lines = order.order_line._get_invalid_delivery_weight_lines() self.assertIn( - weightless_product, error_lines.product_id, + weightless_product, + error_lines.product_id, "The weightless product should be part of the erroneous lines", ) self.assertEqual(len(error_lines), 1, "Only 1 line should have an invalid weight") self.assertTrue(error_lines.combo_item_id, "The erroneous line should be part of a combo") def test_fixed_price_margins(self): - """ - margins should be ignored for fixed price carriers - """ + """Margins should be ignored for fixed price carriers.""" sale_order = self.env['sale.order'].create({ 'partner_id': self.partner.id, 'name': 'SO - fixed del', - 'order_line': [ - (0, 0, { - 'product_id': self.product.id, - 'product_uom_qty': 1, - }), - ] + 'order_line': [(0, 0, {'product_id': self.product.id, 'product_uom_qty': 1})], }) self.normal_delivery.fixed_margin = 100 self.normal_delivery.margin = 4.2 - delivery_wizard = Form(self.env['choose.delivery.carrier'].with_context(default_order_id=sale_order.id, - default_carrier_id=self.normal_delivery.id)) + delivery_wizard = Form( + self.env['choose.delivery.carrier'].with_context( + default_order_id=sale_order.id, default_carrier_id=self.normal_delivery.id + ) + ) choose_delivery_carrier = delivery_wizard.save() choose_delivery_carrier.button_confirm() @@ -353,7 +391,7 @@ def test_fixed_price_margins(self): self.assertEqual(line.price_unit, self.normal_delivery.fixed_price) def test_price_with_weight_volume_variable(self): - """ Test that the price is correctly computed when the variable is weight*volume. """ + """Test that the price is correctly computed when the variable is weight*volume.""" qty = 3 list_price = 2 volume = 2.5 @@ -361,27 +399,27 @@ def test_price_with_weight_volume_variable(self): sale_order = self.env['sale.order'].create({ 'partner_id': self.partner_4.id, 'order_line': [ - (0, 0, { - 'product_id': self.env['product.product'].create({ - 'name': 'wv', - 'weight': weight, - 'volume': volume, - }).id, + Command.create({ + 'product_id': self.env['product.product'] + .create({'name': 'wv', 'weight': weight, 'volume': volume}) + .id, 'product_uom_qty': qty, - }), + }) ], }) delivery = self.env['delivery.carrier'].create({ 'name': 'Delivery Charges', 'delivery_type': 'base_on_rule', 'product_id': self.product_delivery_normal.id, - 'price_rule_ids': [(0, 0, { - 'variable': 'price', - 'operator': '>=', - 'max_value': 0, - 'list_price': list_price, - 'variable_factor': 'wv', - })] + 'price_rule_ids': [ + Command.create({ + 'variable': 'price', + 'operator': '>=', + 'max_value': 0, + 'list_price': list_price, + 'variable_factor': 'wv', + }) + ], }) self.assertEqual( delivery._get_price_available(sale_order), @@ -390,8 +428,8 @@ def test_price_with_weight_volume_variable(self): ) def test_delivery_product_taxes_on_branch(self): - """ Check taxes populated on delivery line on branch company. - Taxes from the branch company should be taken with a fallback on parent company. + """Check taxes populated on delivery line on branch company. + Taxes from the branch company should be taken with a fallback on parent company. """ company = self.env.company branch = self.env['res.company'].create({ @@ -400,13 +438,10 @@ def test_delivery_product_taxes_on_branch(self): 'parent_id': company.id, }) # create taxes for the parent company and its branch - tax_groups = self.env['account.tax.group'].create([{ - 'name': 'Tax Group A', - 'company_id': company.id, - }, { - 'name': 'Tax Group B', - 'company_id': branch.id, - }]) + tax_groups = self.env['account.tax.group'].create([ + {'name': 'Tax Group A', 'company_id': company.id}, + {'name': 'Tax Group B', 'company_id': branch.id}, + ]) tax_a = self.env['account.tax'].create({ 'name': 'Tax A', 'type_tax_use': 'sale', @@ -439,10 +474,7 @@ def test_delivery_product_taxes_on_branch(self): sale_order = self.env['sale.order'].create({ 'partner_id': self.partner_4.id, 'company_id': branch.id, - 'order_line': [Command.create({ - 'product_id': self.product.id, - 'product_uom_qty': 1, - })], + 'order_line': [Command.create({'product_id': self.product.id, 'product_uom_qty': 1})], }) # add delivery wizard = self.env['choose.delivery.carrier'].create({ @@ -451,10 +483,12 @@ def test_delivery_product_taxes_on_branch(self): 'company_id': branch.id, }) wizard.button_confirm() - delivery_line = sale_order.order_line.filtered(lambda l: l.is_delivery) + delivery_line = sale_order.order_line.filtered(lambda line: line.is_delivery) # delivery line should have taxes from the branch company - self.assertRecordValues(delivery_line, [{'product_id': delivery_product.id, 'tax_ids': tax_b.ids}]) + self.assertRecordValues( + delivery_line, [{'product_id': delivery_product.id, 'tax_ids': tax_b.ids}] + ) # update delivery product by setting only the tax from parent company delivery_product.write({'taxes_id': [Command.set((tax_a).ids)]}) @@ -465,24 +499,19 @@ def test_delivery_product_taxes_on_branch(self): 'company_id': branch.id, }) wizard.button_confirm() - delivery_line = sale_order.order_line.filtered(lambda l: l.is_delivery) + delivery_line = sale_order.order_line.filtered(lambda line: line.is_delivery) - # delivery line should have taxes from the parent company as there is no tax from the branch company - self.assertRecordValues(delivery_line, [{'product_id': delivery_product.id, 'tax_ids': tax_a.ids}]) + # delivery line should have taxes from the parent company as there is no tax from the branch + # company + self.assertRecordValues( + delivery_line, [{'product_id': delivery_product.id, 'tax_ids': tax_a.ids}] + ) def test_update_weight_in_shipping_when_change_quantity(self): - product_test = self.env['product.product'].create({ - 'name': 'Test product', - 'weight': 1, - }) + product_test = self.env['product.product'].create({'name': 'Test product', 'weight': 1}) sale_order = self.env['sale.order'].create({ 'partner_id': self.partner.id, - 'order_line': [ - Command.create({ - 'product_id': product_test.id, - 'product_uom_qty': 10, - }), - ], + 'order_line': [Command.create({'product_id': product_test.id, 'product_uom_qty': 10})], }) delivery = self.env['delivery.carrier'].create({ 'name': 'Delivery Charges', @@ -502,34 +531,29 @@ def test_update_weight_in_shipping_when_change_quantity(self): 'max_value': 60, 'list_base_price': 10, 'variable_factor': 'weight', - }) - ] + }), + ], }) del_form = sale_order.action_open_delivery_wizard() - choose_delivery_carrier = self.env[del_form['res_model']].with_context(del_form['context']).create({ - 'carrier_id': delivery.id, - 'order_id': sale_order.id - }) + choose_delivery_carrier = ( + self.env[del_form['res_model']] + .with_context(del_form['context']) + .create({'carrier_id': delivery.id, 'order_id': sale_order.id}) + ) choose_delivery_carrier.button_confirm() self.assertEqual(choose_delivery_carrier.total_weight, 10) - sale_order.order_line.write({ - 'product_uom_qty': 100, - }) + sale_order.order_line.write({'product_uom_qty': 100}) updated_del_form = sale_order.action_open_delivery_wizard() self.assertEqual(updated_del_form['context']['default_total_weight'], 100) def test_base_on_rule_currency_is_converted(self): """ For based on rules delivery method without a company, check that the price - is converted from the main's company's currency to the current company's on SOs + is converted from the main's company's currency to the current company's on SOs. """ - # Create a company that uses a different currency - currency_bells = self.env['res.currency'].create({ - 'name': 'Bell', - 'symbol': 'C', - }) + currency_bells = self.env['res.currency'].create({'name': 'Bell', 'symbol': 'C'}) nook_inc = self.env['res.company'].create({ 'name': 'Nook inc.', @@ -544,44 +568,61 @@ def test_base_on_rule_currency_is_converted(self): }) # Company less delivery method - product_delivery_rule = self.env['product.product'].with_company(nook_inc).create({ - 'name': 'rule delivery charges', - 'type': 'service', - 'list_price': 10.0, - 'categ_id': self.env.ref('delivery.product_category_deliveries').id, - }) + product_delivery_rule = ( + self.env['product.product'] + .with_company(nook_inc) + .create({ + 'name': 'rule delivery charges', + 'type': 'service', + 'list_price': 10.0, + 'categ_id': self.env.ref('delivery.product_category_deliveries').id, + }) + ) - delivery = self.env['delivery.carrier'].with_company(nook_inc).create({ - 'name': 'Rule Delivery', - 'delivery_type': 'base_on_rule', - 'product_id': product_delivery_rule.id, - 'price_rule_ids': [(0, 0, { - 'variable': 'price', - 'operator': '>=', - 'max_value': 0, - 'variable_factor': 'weight', - 'list_base_price': 15, - })], - 'fixed_margin': 10, - }) + delivery = ( + self.env['delivery.carrier'] + .with_company(nook_inc) + .create({ + 'name': 'Rule Delivery', + 'delivery_type': 'base_on_rule', + 'product_id': product_delivery_rule.id, + 'price_rule_ids': [ + Command.create({ + 'variable': 'price', + 'operator': '>=', + 'max_value': 0, + 'variable_factor': 'weight', + 'list_base_price': 15, + }) + ], + 'fixed_margin': 10, + }) + ) # Create sale using the delivery method - so = self.env['sale.order'].with_company(nook_inc).create({ - 'partner_id': self.partner_4.id, - 'partner_invoice_id': self.partner_4.id, - 'partner_shipping_id': self.partner_4.id, - 'order_line': [(0, 0, { - 'name': 'PC Assamble + 2GB RAM', - 'product_id': self.product.id, - 'product_uom_qty': 1, - 'price_unit': 750.00, - })], - }) + so = ( + self.env['sale.order'] + .with_company(nook_inc) + .create({ + 'partner_id': self.partner_4.id, + 'partner_invoice_id': self.partner_4.id, + 'partner_shipping_id': self.partner_4.id, + 'order_line': [ + Command.create({ + 'name': 'PC Assamble + 2GB RAM', + 'product_id': self.product.id, + 'product_uom_qty': 1, + 'price_unit': 750.00, + }) + ], + }) + ) - delivery_wizard = Form(self.env['choose.delivery.carrier'].with_company(nook_inc).with_context({ - 'default_order_id': so.id, - 'default_carrier_id': delivery.id, - })) + delivery_wizard = Form( + self.env['choose.delivery.carrier'] + .with_company(nook_inc) + .with_context({'default_order_id': so.id, 'default_carrier_id': delivery.id}) + ) choose_delivery_carrier = delivery_wizard.save() choose_delivery_carrier.button_confirm() diff --git a/addons/delivery/tests/test_payment_provider.py b/addons/delivery/tests/test_payment_provider.py index 9d7b6917917f8..8e7bd42438295 100644 --- a/addons/delivery/tests/test_payment_provider.py +++ b/addons/delivery/tests/test_payment_provider.py @@ -7,25 +7,38 @@ @tagged('post_install', '-at_install') class TestCODPaymentProvider(CashOnDeliveryCommon): - def test_cod_provider_available_when_dm_cod_enabled(self): order = self.sale_order self.free_delivery.allow_cash_on_delivery = True order.carrier_id = self.free_delivery - compatible_providers = self.env['payment.provider'].sudo()._get_compatible_providers( - self.company.id, self.partner.id, self.amount, sale_order_id=order.id + compatible_providers = ( + self.env['payment.provider'] + .sudo() + ._get_compatible_providers( + self.company.id, self.partner.id, self.amount, sale_order_id=order.id + ) + ) + self.assertTrue( + any( + p.code == 'custom' and p.custom_mode == 'cash_on_delivery' + for p in compatible_providers + ) ) - self.assertTrue(any( - p.code == 'custom' and p.custom_mode == 'cash_on_delivery' for p in compatible_providers - )) def test_cod_provider_unavailable_when_dm_cod_disabled(self): order = self.sale_order self.free_delivery.allow_cash_on_delivery = False order.carrier_id = self.free_delivery - compatible_providers = self.env['payment.provider'].sudo()._get_compatible_providers( - self.company.id, self.partner.id, self.amount, sale_order_id=order.id + compatible_providers = ( + self.env['payment.provider'] + .sudo() + ._get_compatible_providers( + self.company.id, self.partner.id, self.amount, sale_order_id=order.id + ) + ) + self.assertFalse( + any( + p.code == 'custom' and p.custom_mode == 'cash_on_delivery' + for p in compatible_providers + ) ) - self.assertTrue(not any( - p.code == 'custom' and p.custom_mode == 'cash_on_delivery' for p in compatible_providers - )) diff --git a/addons/delivery/tests/test_payment_transaction.py b/addons/delivery/tests/test_payment_transaction.py index 25933e4bf1f58..7571ca194836d 100644 --- a/addons/delivery/tests/test_payment_transaction.py +++ b/addons/delivery/tests/test_payment_transaction.py @@ -8,7 +8,6 @@ @tagged('post_install', '-at_install') class TestCODPaymentTransaction(CashOnDeliveryCommon): - def test_choosing_cod_payment_confirms_order(self): order = self.sale_order self.free_delivery.allow_cash_on_delivery = True diff --git a/addons/delivery/tests/test_sale_order.py b/addons/delivery/tests/test_sale_order.py index 6117883fad919..386a76c4d6410 100644 --- a/addons/delivery/tests/test_sale_order.py +++ b/addons/delivery/tests/test_sale_order.py @@ -5,7 +5,6 @@ @tagged('post_install', '-at_install') class TestSaleOrder(SaleCommon): - def test_avoid_setting_pickup_location_as_default_delivery_address(self): self._create_partner(type='delivery', parent_id=self.partner.id, is_pickup_location=True) so = self.env['sale.order'].create({'partner_id': self.partner.id}) diff --git a/addons/delivery/wizard/choose_delivery_carrier.py b/addons/delivery/wizard/choose_delivery_carrier.py index a49ef08c8707b..2e4375aef570f 100644 --- a/addons/delivery/wizard/choose_delivery_carrier.py +++ b/addons/delivery/wizard/choose_delivery_carrier.py @@ -6,29 +6,37 @@ class ChooseDeliveryCarrier(models.TransientModel): _name = 'choose.delivery.carrier' - _description = 'Delivery Method Selection Wizard' + _description = "Delivery Method Selection Wizard" def _get_default_weight_uom(self): return self.env['product.template']._get_weight_uom_name_from_ir_config_parameter() - order_id = fields.Many2one('sale.order', required=True, ondelete="cascade") - partner_id = fields.Many2one('res.partner', related='order_id.partner_id', required=True) + order_id = fields.Many2one(comodel_name='sale.order', ondelete='cascade', required=True) + partner_id = fields.Many2one( + comodel_name='res.partner', related='order_id.partner_id', required=True + ) carrier_id = fields.Many2one( - 'delivery.carrier', string="Delivery Method", - required=True, + comodel_name='delivery.carrier', domain="[('id', 'in', available_carrier_ids)]", + required=True, ) delivery_type = fields.Selection(related='carrier_id.delivery_type') delivery_price = fields.Float() - display_price = fields.Float(string='Cost', readonly=True) - currency_id = fields.Many2one('res.currency', related='order_id.currency_id') - company_id = fields.Many2one('res.company', related='order_id.company_id') - available_carrier_ids = fields.Many2many("delivery.carrier", compute='_compute_available_carrier', string="Available Carriers") + display_price = fields.Float(string="Cost", readonly=True) + currency_id = fields.Many2one(comodel_name='res.currency', related='order_id.currency_id') + company_id = fields.Many2one(comodel_name='res.company', related='order_id.company_id') + available_carrier_ids = fields.Many2many( + string="Available Carriers", + comodel_name='delivery.carrier', + compute='_compute_available_carrier', + ) invoicing_message = fields.Text(compute='_compute_invoicing_message') delivery_message = fields.Text(readonly=True) - total_weight = fields.Float(string='Total Order Weight', related='order_id.shipping_weight', readonly=False) - weight_uom_name = fields.Char(readonly=True, default=_get_default_weight_uom) + total_weight = fields.Float( + string="Total Order Weight", related='order_id.shipping_weight', readonly=False + ) + weight_uom_name = fields.Char(default=_get_default_weight_uom, readonly=True) @api.onchange('carrier_id', 'total_weight') def _onchange_carrier_id(self): @@ -43,8 +51,13 @@ def _onchange_carrier_id(self): @api.onchange('order_id') def _onchange_order_id(self): - # fixed and base_on_rule delivery price will computed on each carrier change so no need to recompute here - if self.carrier_id and self.order_id.delivery_set and self.delivery_type not in ('fixed', 'base_on_rule'): + # Fixed and base_on_rule delivery price will compute on each carrier change so no need to + # recompute here + if ( + self.carrier_id + and self.order_id.delivery_set + and self.delivery_type not in ('fixed', 'base_on_rule') + ): vals = self._get_delivery_rate() if vals.get('error_message'): warning = { @@ -62,11 +75,19 @@ def _compute_invoicing_message(self): @api.depends('partner_id') def _compute_available_carrier(self): for rec in self: - carriers = self.env['delivery.carrier'].search(self.env['delivery.carrier']._check_company_domain(rec.order_id.company_id)) - rec.available_carrier_ids = carriers.available_carriers(rec.order_id.partner_shipping_id, rec.order_id) if rec.partner_id else carriers + carriers = self.env['delivery.carrier'].search( + self.env['delivery.carrier']._check_company_domain(rec.order_id.company_id) + ) + rec.available_carrier_ids = ( + carriers.available_carriers(rec.order_id.partner_shipping_id, rec.order_id) + if rec.partner_id + else carriers + ) def _get_delivery_rate(self): - vals = self.carrier_id.with_context(order_weight=self.total_weight).rate_shipment(self.order_id) + vals = self.carrier_id.with_context(order_weight=self.total_weight).rate_shipment( + self.order_id + ) if vals.get('success'): self.delivery_message = vals.get('warning_message', False) self.delivery_price = vals['price'] diff --git a/addons/website_sale_collect/controllers/__init__.py b/addons/website_sale_collect/controllers/__init__.py index 1389142f87fff..6df092ba618ae 100644 --- a/addons/website_sale_collect/controllers/__init__.py +++ b/addons/website_sale_collect/controllers/__init__.py @@ -1,5 +1,3 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. -from . import delivery -from . import main -from . import payment +from . import delivery, main, payment diff --git a/addons/website_sale_collect/controllers/delivery.py b/addons/website_sale_collect/controllers/delivery.py index f4c06aa5f6ea7..ed14e8b2dae5e 100644 --- a/addons/website_sale_collect/controllers/delivery.py +++ b/addons/website_sale_collect/controllers/delivery.py @@ -6,10 +6,9 @@ class InStoreDelivery(Delivery): - @route() def website_sale_get_pickup_locations(self, zip_code=None, **kwargs): - """ Override of `website_sale` to set the pickup in store delivery method on the order in + """Override of `website_sale` to set the pickup in store delivery method on the order in order to retrieve pickup locations when called from the product page. If there is no order create a temporary one to display pickup locations. """ @@ -20,13 +19,13 @@ def website_sale_get_pickup_locations(self, zip_code=None, **kwargs): # Create a temporary order to fetch pickup locations. temp_order = request.env['sale.order'].new({'carrier_id': in_store_dm.id}) return temp_order.sudo()._get_pickup_locations(zip_code, **kwargs) # Skip super - elif order_sudo.carrier_id.delivery_type != 'in_store': + if order_sudo.carrier_id.delivery_type != 'in_store': order_sudo.set_delivery_line(in_store_dm, in_store_dm.product_id.list_price) return super().website_sale_get_pickup_locations(zip_code, **kwargs) @route('/shop/set_click_and_collect_location', type='jsonrpc', auth='public', website=True) def shop_set_click_and_collect_location(self, pickup_location_data): - """ Set the pickup location and the in-store delivery method on the current order or created + """Set the pickup location and the in-store delivery method on the current order or created one. This route is called from location selector on /product and is distinct from @@ -43,8 +42,8 @@ def shop_set_click_and_collect_location(self, pickup_location_data): order_sudo._set_pickup_location(pickup_location_data) def _get_additional_delivery_context(self): - """ Override of `website_sale` to include the default pickup location data for in-store - delivery methods with a single warehouse. """ + """Override of `website_sale` to include the default pickup location data for in-store + delivery methods with a single warehouse.""" res = super()._get_additional_delivery_context() order_sudo = request.cart if request.website.sudo().in_store_dm_id: diff --git a/addons/website_sale_collect/controllers/main.py b/addons/website_sale_collect/controllers/main.py index c150e09e61fd6..28f6b18df6191 100644 --- a/addons/website_sale_collect/controllers/main.py +++ b/addons/website_sale_collect/controllers/main.py @@ -7,9 +7,8 @@ class WebsiteSaleCollect(WebsiteSale): - def _prepare_product_values(self, product, category, **kwargs): - """ Override of `website_sale` to configure the Click & Collect Availability widget. """ + """Override of `website_sale` to configure the Click & Collect Availability widget.""" res = super()._prepare_product_values(product, category, **kwargs) if in_store_dm_sudo := request.website.sudo().in_store_dm_id: order_sudo = request.cart @@ -21,9 +20,8 @@ def _prepare_product_values(self, product, category, **kwargs): ): selected_location_data = order_sudo.pickup_location_data elif single_location: - selected_location_data = ( - in_store_dm_sudo.warehouse_ids[0]._prepare_pickup_location_data() - ) + default_wh = in_store_dm_sudo.warehouse_ids[0] + selected_location_data = default_wh._prepare_pickup_location_data() res.update({ 'selected_location_data': selected_location_data, 'show_select_store_button': not single_location, @@ -37,8 +35,8 @@ def _prepare_product_values(self, product, category, **kwargs): return res def _prepare_checkout_page_values(self, order_sudo, **query_params): - """ Override of `website_sale` to include the unavailable products for the selected pickup - location and set the pickup location when there is only one warehouse available. """ + """Override of `website_sale` to include the unavailable products for the selected pickup + location and set the pickup location when there is only one warehouse available.""" res = super()._prepare_checkout_page_values(order_sudo, **query_params) if order_sudo.only_services: @@ -52,8 +50,8 @@ def _prepare_checkout_page_values(self, order_sudo, **query_params): return res def _get_shop_payment_errors(self, order): - """ Override of `website_sale` to includes errors if no pickup location is selected or some - products are unavailable. """ + """Override of `website_sale` to includes errors if no pickup location is selected or some + products are unavailable.""" errors = super()._get_shop_payment_errors(order) if order._has_deliverable_products() and order.carrier_id.delivery_type == 'in_store': if not order.pickup_location_data: diff --git a/addons/website_sale_collect/controllers/payment.py b/addons/website_sale_collect/controllers/payment.py index d96016ad62e0f..46ceb66c64996 100644 --- a/addons/website_sale_collect/controllers/payment.py +++ b/addons/website_sale_collect/controllers/payment.py @@ -7,9 +7,8 @@ class OnSitePaymentPortal(PaymentPortal): - def _validate_transaction_for_order(self, transaction, sale_order): - """ Override of `website_sale` to ensure the on-site payment provider is not used without + """Override of `website_sale` to ensure the on-site payment provider is not used without the in-store pickup delivery method. This also sets the warehouse of the selected pickup location on the sales order. diff --git a/addons/website_sale_collect/models/__init__.py b/addons/website_sale_collect/models/__init__.py index 10490be85ef96..6aef2a86f0244 100644 --- a/addons/website_sale_collect/models/__init__.py +++ b/addons/website_sale_collect/models/__init__.py @@ -1,10 +1,12 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. -from . import delivery_carrier -from . import payment_provider -from . import payment_transaction -from . import product_template -from . import res_config_settings -from . import sale_order -from . import stock_warehouse -from . import website +from . import ( + delivery_carrier, + payment_provider, + payment_transaction, + product_template, + res_config_settings, + sale_order, + stock_warehouse, + website, +) diff --git a/addons/website_sale_collect/models/delivery_carrier.py b/addons/website_sale_collect/models/delivery_carrier.py index 4cd8d08e241ff..569945b1ad6a6 100644 --- a/addons/website_sale_collect/models/delivery_carrier.py +++ b/addons/website_sale_collect/models/delivery_carrier.py @@ -18,11 +18,13 @@ class DeliveryCarrier(models.Model): @api.constrains('delivery_type', 'is_published', 'warehouse_ids') def _check_in_store_dm_has_warehouses_when_published(self): - if any(self.filtered( - lambda dm: dm.delivery_type == 'in_store' - and dm.is_published - and not dm.warehouse_ids - )): + if any( + self.filtered( + lambda dm: dm.delivery_type == 'in_store' + and dm.is_published + and not dm.warehouse_ids + ) + ): raise ValidationError( _("The delivery method must have at least one warehouse to be published.") ) @@ -30,8 +32,10 @@ def _check_in_store_dm_has_warehouses_when_published(self): @api.constrains('delivery_type', 'company_id', 'warehouse_ids') def _check_warehouses_have_same_company(self): for dm in self: - if dm.delivery_type == 'in_store' and dm.company_id and any( - wh.company_id and dm.company_id != wh.company_id for wh in dm.warehouse_ids + if ( + dm.delivery_type == 'in_store' + and dm.company_id + and any(wh.company_id and dm.company_id != wh.company_id for wh in dm.warehouse_ids) ): raise ValidationError( _("The delivery method and a warehouse must share the same company") @@ -52,9 +56,7 @@ def create(self, vals_list): self.env['product.product'].browse(vals.get('product_id')).company_id.id or self.env.company.id ) - warehouses = self.env['stock.warehouse'].search( - [('company_id', 'in', company_id)] - ) + warehouses = self.env['stock.warehouse'].search([('company_id', 'in', company_id)]) vals.update({ 'warehouse_ids': [Command.set(warehouses.ids)], 'is_published': bool(warehouses), diff --git a/addons/website_sale_collect/models/payment_provider.py b/addons/website_sale_collect/models/payment_provider.py index e047f1fdd7b41..88749938b02b0 100644 --- a/addons/website_sale_collect/models/payment_provider.py +++ b/addons/website_sale_collect/models/payment_provider.py @@ -14,7 +14,7 @@ class PaymentProvider(models.Model): # === CRUD METHODS === # def _get_default_payment_method_codes(self): - """ Override of `payment` to return the default payment method codes. """ + """Override of `payment` to return the default payment method codes.""" self.ensure_one() if self.custom_mode != 'on_site': return super()._get_default_payment_method_codes() @@ -26,7 +26,7 @@ def _get_default_payment_method_codes(self): def _get_compatible_providers( self, company_id, *args, sale_order_id=None, website_id=None, report=None, **kwargs ): - """ Override of payment to exclude on-site payment providers if the delivery method is not + """Override of payment to exclude on-site payment providers if the delivery method is not pick up in store. :param int company_id: The company to which providers must belong, as a `res.company` id diff --git a/addons/website_sale_collect/models/payment_transaction.py b/addons/website_sale_collect/models/payment_transaction.py index d78d97675b05b..2963c68d6d157 100644 --- a/addons/website_sale_collect/models/payment_transaction.py +++ b/addons/website_sale_collect/models/payment_transaction.py @@ -7,12 +7,12 @@ class PaymentTransaction(models.Model): _inherit = 'payment.transaction' def _post_process(self): - """ Override of `payment` to confirm orders with the on_site payment method and trigger - a picking creation. """ + """Override of `payment` to confirm orders with the on_site payment method and trigger + a picking creation.""" on_site_pending_txs = self.filtered( lambda tx: tx.provider_id.custom_mode == 'on_site' and tx.state == 'pending' ) - on_site_pending_txs.sale_order_ids.filtered( - lambda so: so.state == 'draft' - ).with_context(send_email=True).action_confirm() + on_site_pending_txs.sale_order_ids.filtered(lambda so: so.state == 'draft').with_context( + send_email=True + ).action_confirm() super()._post_process() diff --git a/addons/website_sale_collect/models/product_template.py b/addons/website_sale_collect/models/product_template.py index 83a602ba11bbb..b16ff4e7d3e84 100644 --- a/addons/website_sale_collect/models/product_template.py +++ b/addons/website_sale_collect/models/product_template.py @@ -11,7 +11,7 @@ class ProductTemplate(models.Model): def _get_additionnal_combination_info(self, product_or_template, quantity, uom, date, website): """Override of `website_sale` to add information on whether Click & Collect is enabled and - on the stock of the product. """ + on the stock of the product.""" res = super()._get_additionnal_combination_info( product_or_template, quantity, uom, date, website ) @@ -28,8 +28,11 @@ def _get_additionnal_combination_info(self, product_or_template, quantity, uom, res['uom_id'] = uom.id # Prepare the delivery stock data. - available_delivery_methods_sudo = self.env['delivery.carrier'].sudo().search([ - '|', ('website_id', '=', website.id), ('website_id', '=', False), + DeliveryCarrier = self.env['delivery.carrier'].sudo() + available_delivery_methods_sudo = DeliveryCarrier.search([ + '|', + ('website_id', '=', website.id), + ('website_id', '=', False), ('website_published', '=', True), ('delivery_type', '!=', 'in_store'), ]) diff --git a/addons/website_sale_collect/models/res_config_settings.py b/addons/website_sale_collect/models/res_config_settings.py index abb2a23660024..a592b020759b6 100644 --- a/addons/website_sale_collect/models/res_config_settings.py +++ b/addons/website_sale_collect/models/res_config_settings.py @@ -7,8 +7,8 @@ class ResConfigSettings(models.TransientModel): _inherit = 'res.config.settings' def action_view_in_store_delivery_methods(self): - """ Return an action to browse pickup delivery methods in list view, or in form view if - there is only one. """ + """Return an action to browse pickup delivery methods in list view, or in form view if + there is only one.""" in_store_dms = self.env['delivery.carrier'].search([('delivery_type', '=', 'in_store')]) if len(in_store_dms) == 1: return { diff --git a/addons/website_sale_collect/models/sale_order.py b/addons/website_sale_collect/models/sale_order.py index 5dac4b6fbba92..e37ca770e3d30 100644 --- a/addons/website_sale_collect/models/sale_order.py +++ b/addons/website_sale_collect/models/sale_order.py @@ -14,9 +14,7 @@ def _compute_warehouse_id(self): """Override of `website_sale_stock` to avoid recomputations for in_store orders when the warehouse was set by the pickup_location_data.""" in_store_orders_with_pickup_data = self.filtered( - lambda so: ( - so.carrier_id.delivery_type == 'in_store' and so.pickup_location_data - ) + lambda so: (so.carrier_id.delivery_type == 'in_store' and so.pickup_location_data) ) super(SaleOrder, self - in_store_orders_with_pickup_data)._compute_warehouse_id() for order in in_store_orders_with_pickup_data: @@ -37,7 +35,7 @@ def _compute_fiscal_position_id(self): def _set_delivery_method(self, delivery_method, rate=None): """Override of `website_sale` to recompute warehouse and fiscal position when a new - delivery method is not in-store anymore. """ + delivery method is not in-store anymore.""" self.ensure_one() was_in_store_order = ( self.carrier_id.delivery_type == 'in_store' @@ -91,22 +89,22 @@ def _get_shop_warehouse_id(self): def _check_cart_is_ready_to_be_paid(self): """Override of `website_sale` to check if all products are in stock in the selected - warehouse. """ + warehouse.""" if ( self._has_deliverable_products() and self.carrier_id.delivery_type == 'in_store' and not self._is_in_stock(self.warehouse_id.id) ): - raise ValidationError(self.env._( - "Some products are not available in the selected store." - )) + raise ValidationError( + self.env._("Some products are not available in the selected store.") + ) return super()._check_cart_is_ready_to_be_paid() # === TOOLING ===# def _prepare_in_store_default_location_data(self): """Prepare the default pickup location values for each in-store delivery method available - for the order. """ + for the order.""" default_pickup_locations = {} for dm in self._get_delivery_methods(): if ( @@ -150,23 +148,26 @@ def _get_insufficient_stock_data(self, wh_id): continue free_qty = product.with_context(warehouse_id=wh_id).free_qty for ol in ols: - free_qty_in_uom = max(int(product.uom_id._compute_quantity( + free_qty_in_uom = product.uom_id._compute_quantity( free_qty, ol.product_uom_id, rounding_method='DOWN' - )), 0) # Round down as only integer quantities can be sold. + ) + # Round down as only integer quantities can be sold. + free_qty_in_uom = max(int(free_qty_in_uom), 0) line_qty_in_uom = ol.product_uom_qty if line_qty_in_uom > free_qty_in_uom: # Not enough stock. # Set a warning on the order line. insufficient_stock_data[ol] = free_qty_in_uom ol.shop_warning = self.env._( "%(available_qty)s/%(line_qty)s available at this location", - available_qty=free_qty_in_uom, line_qty=int(line_qty_in_uom), + available_qty=free_qty_in_uom, + line_qty=int(line_qty_in_uom), ) free_qty -= ol.product_uom_id._compute_quantity(line_qty_in_uom, product.uom_id) return insufficient_stock_data def _verify_updated_quantity(self, order_line, product_id, new_qty, uom_id, **kwargs): """Override of `website_sale_stock` to skip the verification when click and collect - is activated. The quantity is verified later. """ + is activated. The quantity is verified later.""" product = self.env['product.product'].browse(product_id) if ( product.is_storable diff --git a/addons/website_sale_collect/models/website.py b/addons/website_sale_collect/models/website.py index b4e300fbb51ee..7522db38e7197 100644 --- a/addons/website_sale_collect/models/website.py +++ b/addons/website_sale_collect/models/website.py @@ -13,20 +13,25 @@ class Website(models.Model): ) def _compute_in_store_dm_id(self): - in_store_delivery_methods = self.env['delivery.carrier'].search( - [('delivery_type', '=', 'in_store'), ('is_published', '=', True)] - ) + in_store_delivery_methods = self.env['delivery.carrier'].search([ + ('delivery_type', '=', 'in_store'), + ('is_published', '=', True), + ]) for website in self: website.in_store_dm_id = in_store_delivery_methods.filtered_domain([ - '|', ('website_id', '=', False), ('website_id', '=', website.id), - '|', ('company_id', '=', False), ('company_id', '=', website.company_id.id), + '|', + ('website_id', '=', False), + ('website_id', '=', website.id), + '|', + ('company_id', '=', False), + ('company_id', '=', website.company_id.id), ])[:1] def _get_product_available_qty(self, product, **kwargs): - """ Override of `website_sale_stock` to include free quantities of the product in warehouses - of in-store delivery method and return maximum possible for one order. Needed only if a - warehouse is set on website, otherwise free quantity is already calculated from all - warehouses.""" + """Override of `website_sale_stock` to include free quantities of the product in warehouses + of in-store delivery method and return maximum possible for one order. Needed only if a + warehouse is set on website, otherwise free quantity is already calculated from all + warehouses.""" free_qty = super()._get_product_available_qty(product, **kwargs) if self.warehouse_id and self.sudo().in_store_dm_id: # If warehouse is set on website. # Check free quantities in the in-store warehouses. @@ -34,8 +39,11 @@ def _get_product_available_qty(self, product, **kwargs): return free_qty def _get_max_in_store_product_available_qty(self, product): - """ Return maximum amount of product available to deliver with in store delivery method. """ - return max([ - product.with_context(warehouse_id=wh.id).free_qty - for wh in self.sudo().in_store_dm_id.warehouse_ids - ], default=0) + """Return maximum amount of product available to deliver with in store delivery method.""" + return max( + [ + product.with_context(warehouse_id=wh.id).free_qty + for wh in self.sudo().in_store_dm_id.warehouse_ids + ], + default=0, + ) diff --git a/addons/website_sale_collect/tests/__init__.py b/addons/website_sale_collect/tests/__init__.py index b4ee93e2bf6e5..8eb80449aa41f 100644 --- a/addons/website_sale_collect/tests/__init__.py +++ b/addons/website_sale_collect/tests/__init__.py @@ -1,11 +1,13 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. -from . import test_delivery_carrier -from . import test_click_and_collect_express_checkout -from . import test_click_and_collect_flow -from . import test_in_store_delivery -from . import test_payment_provider -from . import test_payment_transaction -from . import test_product_template -from . import test_sale_order -from . import test_website +from . import ( + test_click_and_collect_express_checkout, + test_click_and_collect_flow, + test_delivery_carrier, + test_in_store_delivery, + test_payment_provider, + test_payment_transaction, + test_product_template, + test_sale_order, + test_website, +) diff --git a/addons/website_sale_collect/tests/common.py b/addons/website_sale_collect/tests/common.py index 57fbf28c9ec4d..1f557a3621d73 100644 --- a/addons/website_sale_collect/tests/common.py +++ b/addons/website_sale_collect/tests/common.py @@ -7,7 +7,6 @@ class ClickAndCollectCommon(PaymentCustomCommon, WebsiteSaleStockCommon): - @classmethod def setUpClass(cls): super().setUpClass() @@ -31,10 +30,9 @@ def _create_in_store_delivery_order(self, **values): default_values = { 'partner_id': self.partner.id, 'website_id': self.website.id, - 'order_line': [Command.create({ - 'product_id': self.storable_product.id, - 'product_uom_qty': 5.0, - })], + 'order_line': [ + Command.create({'product_id': self.storable_product.id, 'product_uom_qty': 5.0}) + ], 'carrier_id': self.in_store_dm.id, } return self.env['sale.order'].create(dict(default_values, **values)) diff --git a/addons/website_sale_collect/tests/test_click_and_collect_express_checkout.py b/addons/website_sale_collect/tests/test_click_and_collect_express_checkout.py index eb73e71e05870..827b9ff7cd709 100644 --- a/addons/website_sale_collect/tests/test_click_and_collect_express_checkout.py +++ b/addons/website_sale_collect/tests/test_click_and_collect_express_checkout.py @@ -8,7 +8,6 @@ @tagged('post_install', '-at_install') class TestClickAndCollectExpressCheckout(ClickAndCollectCommon): - def test_exclude_in_store_delivery_methods(self): express_delivery_methods = InStoreDelivery._get_delivery_methods_express_checkout(self.cart) diff --git a/addons/website_sale_collect/tests/test_click_and_collect_flow.py b/addons/website_sale_collect/tests/test_click_and_collect_flow.py index 69ed71a973368..085e12651c41a 100644 --- a/addons/website_sale_collect/tests/test_click_and_collect_flow.py +++ b/addons/website_sale_collect/tests/test_click_and_collect_flow.py @@ -1,22 +1,18 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo.tests import tagged - from odoo.tests.common import HttpCase + from odoo.addons.website_sale_collect.tests.common import ClickAndCollectCommon @tagged('post_install', '-at_install') class TestClickAndCollectFlow(HttpCase, ClickAndCollectCommon): - @classmethod def setUpClass(cls): super().setUpClass() cls.storable_product.name = "Test CAC Product" - cls.provider.write({ - 'state': 'enabled', - 'is_published': True, - }) + cls.provider.write({'state': 'enabled', 'is_published': True}) cls.in_store_dm.warehouse_ids[0].partner_id = cls.env['res.partner'].create({ **cls.dummy_partner_address_values, 'name': "Shop 1", @@ -27,7 +23,7 @@ def setUpClass(cls): def test_buy_with_click_and_collect_as_public_user(self): """ Test the basic flow of buying with click and collect as a public user with more than - one delivery method available + one delivery method available. """ self.start_tour('/', 'website_sale_collect_widget') diff --git a/addons/website_sale_collect/tests/test_delivery_carrier.py b/addons/website_sale_collect/tests/test_delivery_carrier.py index f87e2523de13b..48480f3ae1883 100644 --- a/addons/website_sale_collect/tests/test_delivery_carrier.py +++ b/addons/website_sale_collect/tests/test_delivery_carrier.py @@ -4,7 +4,7 @@ from odoo import Command from odoo.exceptions import ValidationError -from odoo.tests import Form, tagged +from odoo.tests import tagged from odoo.addons.website_sale.tests.common import MockRequest from odoo.addons.website_sale_collect.tests.common import ClickAndCollectCommon @@ -13,7 +13,6 @@ @tagged('post_install', '-at_install') class TestDeliveryCarrier(ClickAndCollectCommon, WebsiteSaleStockCommon): - def test_prevent_publishing_when_no_warehouse(self): self.in_store_dm.is_published = False self.in_store_dm.warehouse_ids = [Command.clear()] @@ -72,32 +71,38 @@ def test_in_store_get_close_locations_returned_data(self): ], }) - with patch( - 'odoo.addons.base_geolocalize.models.res_partner.ResPartner.geo_localize', - return_value=True - ), MockRequest(self.env, website=self.website, sale_order_id=so.id): + with ( + patch( + 'odoo.addons.base_geolocalize.models.res_partner.ResPartner.geo_localize', + return_value=True, + ), + MockRequest(self.env, website=self.website, sale_order_id=so.id), + ): locations = self.in_store_dm._in_store_get_close_locations(wh_address_partner) self.assertEqual( - locations, [{ - 'id': self.warehouse.id, - 'name': wh_address_partner['name'].title(), - 'street': wh_address_partner['street'].title(), - 'city': wh_address_partner.city.title(), - 'zip_code': wh_address_partner.zip, - 'state': wh_address_partner.state_id.code, - 'country_code': wh_address_partner.country_code, - 'latitude': wh_address_partner.partner_latitude, - 'longitude': wh_address_partner.partner_longitude, - 'additional_data': {'in_store_stock_data': {'in_stock': True}}, - 'opening_hours': { - '0': ['08:00 - 12:00', '13:00 - 17:00'], - '1': [], - '2': [], - '3': [], - '4': [], - '5': [], - '6': [], - }, - 'distance': 0.0, - }] + locations, + [ + { + 'id': self.warehouse.id, + 'name': wh_address_partner['name'].title(), + 'street': wh_address_partner['street'].title(), + 'city': wh_address_partner.city.title(), + 'zip_code': wh_address_partner.zip, + 'state': wh_address_partner.state_id.code, + 'country_code': wh_address_partner.country_code, + 'latitude': wh_address_partner.partner_latitude, + 'longitude': wh_address_partner.partner_longitude, + 'additional_data': {'in_store_stock_data': {'in_stock': True}}, + 'opening_hours': { + '0': ['08:00 - 12:00', '13:00 - 17:00'], + '1': [], + '2': [], + '3': [], + '4': [], + '5': [], + '6': [], + }, + 'distance': 0.0, + } + ], ) diff --git a/addons/website_sale_collect/tests/test_in_store_delivery.py b/addons/website_sale_collect/tests/test_in_store_delivery.py index b5df9e682c38d..9270f32cc6718 100644 --- a/addons/website_sale_collect/tests/test_in_store_delivery.py +++ b/addons/website_sale_collect/tests/test_in_store_delivery.py @@ -1,6 +1,7 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from unittest.mock import patch + from odoo.tests import tagged from odoo.addons.payment.tests.http_common import PaymentHttpCommon @@ -19,7 +20,7 @@ def test_order_not_created_on_fetching_pickup_location_with_empty_cart(self): url = self._build_url('/website_sale/get_pickup_locations') with patch( 'odoo.addons.website_sale_collect.models.sale_order.SaleOrder._get_pickup_locations', - return_value={} + return_value={}, ): self.make_jsonrpc_request(url, {'product_id': 1}) count_so_after = self.env['sale.order'].search_count([]) diff --git a/addons/website_sale_collect/tests/test_payment_provider.py b/addons/website_sale_collect/tests/test_payment_provider.py index 45628dd7d8495..24d043931ee6a 100644 --- a/addons/website_sale_collect/tests/test_payment_provider.py +++ b/addons/website_sale_collect/tests/test_payment_provider.py @@ -7,21 +7,22 @@ @tagged('post_install', '-at_install') class TestOnSitePaymentProvider(HttpCase, ClickAndCollectCommon): - def test_on_site_provider_available_when_in_store_delivery_is_chosen(self): order = self._create_in_store_delivery_order() - compatible_providers = self.env['payment.provider'].sudo()._get_compatible_providers( + PaymentProvider = self.env['payment.provider'].sudo() + compatible_providers = PaymentProvider._get_compatible_providers( self.company.id, self.partner.id, self.amount, sale_order_id=order.id ) - self.assertTrue(any( - p.code == 'custom' and p.custom_mode == 'on_site' for p in compatible_providers - )) + self.assertTrue( + any(p.code == 'custom' and p.custom_mode == 'on_site' for p in compatible_providers) + ) def test_on_site_provider_unavailable_when_no_in_store_delivery(self): order = self._create_in_store_delivery_order(carrier_id=self.free_delivery.id) - compatible_providers = self.env['payment.provider'].sudo()._get_compatible_providers( + PaymentProvider = self.env['payment.provider'].sudo() + compatible_providers = PaymentProvider._get_compatible_providers( self.company.id, self.partner.id, self.amount, sale_order_id=order.id ) - self.assertFalse(any( - p.code == 'custom' and p.custom_mode == 'on_site' for p in compatible_providers - )) + self.assertFalse( + any(p.code == 'custom' and p.custom_mode == 'on_site' for p in compatible_providers) + ) diff --git a/addons/website_sale_collect/tests/test_payment_transaction.py b/addons/website_sale_collect/tests/test_payment_transaction.py index 14255156f04d4..76226386203aa 100644 --- a/addons/website_sale_collect/tests/test_payment_transaction.py +++ b/addons/website_sale_collect/tests/test_payment_transaction.py @@ -8,7 +8,6 @@ @tagged('post_install', '-at_install') class TestOnSitePaymentTransaction(HttpCase, ClickAndCollectCommon): - def test_choosing_on_site_payment_confirms_order(self): order = self._create_so(carrier_id=self.carrier.id, state='draft') tx = self._create_transaction( diff --git a/addons/website_sale_collect/tests/test_product_template.py b/addons/website_sale_collect/tests/test_product_template.py index a7360e830cce3..e8a32c70cda9b 100644 --- a/addons/website_sale_collect/tests/test_product_template.py +++ b/addons/website_sale_collect/tests/test_product_template.py @@ -10,7 +10,6 @@ @tagged('post_install', '-at_install') class TestProductTemplate(ClickAndCollectCommon): - def test_out_of_stock_product_available_when_allow_continue_selling(self): product = self._create_product(allow_out_of_stock_order=True) self.free_delivery.is_published = True diff --git a/addons/website_sale_collect/tests/test_sale_order.py b/addons/website_sale_collect/tests/test_sale_order.py index 83808bb2d144c..0ab61011b6266 100644 --- a/addons/website_sale_collect/tests/test_sale_order.py +++ b/addons/website_sale_collect/tests/test_sale_order.py @@ -1,7 +1,7 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. -from odoo.fields import Command from odoo.exceptions import ValidationError +from odoo.fields import Command from odoo.tests import tagged from odoo.addons.website_sale_collect.tests.common import ClickAndCollectCommon @@ -9,7 +9,6 @@ @tagged('post_install', '-at_install') class TestSaleOrder(ClickAndCollectCommon): - @classmethod def setUpClass(cls): super().setUpClass() @@ -87,10 +86,9 @@ def test_free_qty_calculated_from_order_wh_if_dm_is_in_store(self): self.assertEqual(free_qty, 10) def test_prevent_buying_out_of_stock_products(self): - cart = self._create_in_store_delivery_order(order_line=[Command.create({ - 'product_id': self.product_2.id, - 'product_uom_qty': 5.0, - })]) + cart = self._create_in_store_delivery_order( + order_line=[Command.create({'product_id': self.product_2.id, 'product_uom_qty': 5.0})] + ) cart.warehouse_id = self.warehouse with self.assertRaises(ValidationError): cart._check_cart_is_ready_to_be_paid() @@ -98,10 +96,7 @@ def test_prevent_buying_out_of_stock_products(self): def test_product_in_stock_is_available(self): cart = self._create_in_store_delivery_order( order_line=[ - Command.create({ - 'product_id': self.storable_product.id, - 'product_uom_qty': 5.0, - }) + Command.create({'product_id': self.storable_product.id, 'product_uom_qty': 5.0}) ] ) insufficient_stock_data = cart._get_insufficient_stock_data(self.warehouse.id) @@ -110,14 +105,7 @@ def test_product_in_stock_is_available(self): def test_product_out_of_stock_continue_selling_is_available(self): self.product_2.allow_out_of_stock_order = True cart = self._create_in_store_delivery_order( - order_line=[ - Command.create( - { - 'product_id': self.product_2.id, - 'product_uom_qty': 5.0, - } - ) - ] + order_line=[Command.create({'product_id': self.product_2.id, 'product_uom_qty': 5.0})] ) insufficient_stock_data = cart._get_insufficient_stock_data(self.warehouse.id) self.assertFalse(insufficient_stock_data) @@ -125,10 +113,7 @@ def test_product_out_of_stock_continue_selling_is_available(self): def test_product_insufficient_stock_is_unavailable(self): cart = self._create_in_store_delivery_order( order_line=[ - Command.create({ - 'product_id': self.storable_product.id, - 'product_uom_qty': 15.0, - }) + Command.create({'product_id': self.storable_product.id, 'product_uom_qty': 15.0}) ] ) insufficient_stock_data = cart._get_insufficient_stock_data(self.warehouse.id) @@ -141,26 +126,22 @@ def test_insufficient_stock_with_mixed_uom_order_lines(self): # 1 pack of 6 + 5 units = 11 units in the cart cart = self._create_in_store_delivery_order( order_line=[ - Command.create( - { - 'product_id': self.storable_product.id, - 'product_uom_qty': 1.0, - 'product_uom_id': pack_of_6_id, - } - ), - Command.create( - { - 'product_id': self.storable_product.id, - 'product_uom_qty': 5.0, - 'product_uom_id': self.storable_product.uom_id.id, - } - ), + Command.create({ + 'product_id': self.storable_product.id, + 'product_uom_qty': 1.0, + 'product_uom_id': pack_of_6_id, + }), + Command.create({ + 'product_id': self.storable_product.id, + 'product_uom_qty': 5.0, + 'product_uom_id': self.storable_product.uom_id.id, + }), ] ) # 10 units available, 11 requested, so 1 unit short insufficient_stock_data = cart._get_insufficient_stock_data(self.warehouse.id) ol_unit = cart.order_line.filtered( - lambda l: l.product_uom_id == self.storable_product.uom_id + lambda line: line.product_uom_id == self.storable_product.uom_id ) # only 4 units are available for the second order line instead of 5 self.assertEqual(insufficient_stock_data[ol_unit], 4) @@ -170,30 +151,27 @@ def test_product_in_stock_with_mixed_uom_order_lines_is_available(self): empty.""" pack_of_6_id = self.ref('uom.product_uom_pack_6') # 1 pack of 6 + 4 units = 10 units in the cart - cart = self._create_in_store_delivery_order(order_line=[ - Command.create({ - 'product_id': self.storable_product.id, - 'product_uom_qty': 4.0, - 'product_uom_id': self.storable_product.uom_id.id, - }), - Command.create({ - 'product_id': self.storable_product.id, - 'product_uom_qty': 1.0, - 'product_uom_id': pack_of_6_id, - }), - ]) + cart = self._create_in_store_delivery_order( + order_line=[ + Command.create({ + 'product_id': self.storable_product.id, + 'product_uom_qty': 4.0, + 'product_uom_id': self.storable_product.uom_id.id, + }), + Command.create({ + 'product_id': self.storable_product.id, + 'product_uom_qty': 1.0, + 'product_uom_id': pack_of_6_id, + }), + ] + ) # 10 units available, 10 requested insufficient_stock_data = cart._get_insufficient_stock_data(self.warehouse.id) self.assertFalse(insufficient_stock_data) def test_out_of_stock_product_is_unavailable(self): cart = self._create_in_store_delivery_order( - order_line=[ - Command.create({ - 'product_id': self.product_2.id, - 'product_uom_qty': 5.0, - }), - ] + order_line=[Command.create({'product_id': self.product_2.id, 'product_uom_qty': 5.0})] ) insufficient_stock_data = cart._get_insufficient_stock_data(self.warehouse.id) self.assertIn(cart.order_line, insufficient_stock_data) @@ -202,10 +180,7 @@ def test_product_in_different_warehouse_is_unavailable(self): self.warehouse_2 = self._create_warehouse() cart = self._create_in_store_delivery_order( order_line=[ - Command.create({ - 'product_id': self.storable_product.id, - 'product_uom_qty': 5.0, - }) + Command.create({'product_id': self.storable_product.id, 'product_uom_qty': 5.0}) ] ) insufficient_stock_data = cart._get_insufficient_stock_data(self.warehouse_2.id) diff --git a/addons/website_sale_collect/tests/test_website.py b/addons/website_sale_collect/tests/test_website.py index 07df92096f695..b93df87d73727 100644 --- a/addons/website_sale_collect/tests/test_website.py +++ b/addons/website_sale_collect/tests/test_website.py @@ -8,7 +8,6 @@ @tagged('post_install', '-at_install') class TestWebsite(ClickAndCollectCommon): - @classmethod def setUpClass(cls): super().setUpClass() diff --git a/addons/website_sale_collect/views/delivery_carrier_views.xml b/addons/website_sale_collect/views/delivery_carrier_views.xml index 8e0e3a7b3228f..f2615329e4d35 100644 --- a/addons/website_sale_collect/views/delivery_carrier_views.xml +++ b/addons/website_sale_collect/views/delivery_carrier_views.xml @@ -1,6 +1,6 @@ - + In-store Delivery Carrier Form From bf327d47b3b252993ea9a72a2cbe7e5895a83b9b Mon Sep 17 00:00:00 2001 From: "Valeriya (vchu)" Date: Wed, 24 Dec 2025 11:43:37 +0100 Subject: [PATCH 2/2] [LINT] delivery,website_sale_collect: enforce double quotes --- .../delivery/controllers/location_selector.py | 12 +- addons/delivery/models/delivery_carrier.py | 266 ++++----- addons/delivery/models/delivery_price_rule.py | 54 +- addons/delivery/models/delivery_zip_prefix.py | 12 +- addons/delivery/models/ir_http.py | 4 +- addons/delivery/models/ir_module_module.py | 16 +- addons/delivery/models/payment_provider.py | 10 +- addons/delivery/models/payment_transaction.py | 6 +- addons/delivery/models/product_category.py | 2 +- addons/delivery/models/res_partner.py | 6 +- addons/delivery/models/sale_order.py | 162 +++--- addons/delivery/models/sale_order_line.py | 14 +- .../delivery/tests/cash_on_delivery_common.py | 8 +- addons/delivery/tests/common.py | 30 +- .../tests/test_delivery_availability.py | 118 ++-- addons/delivery/tests/test_delivery_cost.py | 506 +++++++++--------- .../delivery/tests/test_payment_provider.py | 10 +- .../tests/test_payment_transaction.py | 10 +- addons/delivery/tests/test_sale_order.py | 6 +- .../wizard/choose_delivery_carrier.py | 88 +-- .../controllers/delivery.py | 12 +- .../website_sale_collect/controllers/main.py | 22 +- .../controllers/payment.py | 6 +- .../models/delivery_carrier.py | 60 +-- .../models/payment_provider.py | 14 +- .../models/payment_transaction.py | 6 +- .../models/product_template.py | 30 +- .../models/res_config_settings.py | 22 +- .../website_sale_collect/models/sale_order.py | 44 +- .../models/stock_warehouse.py | 30 +- addons/website_sale_collect/models/website.py | 24 +- addons/website_sale_collect/tests/common.py | 16 +- ...test_click_and_collect_express_checkout.py | 2 +- .../tests/test_click_and_collect_flow.py | 30 +- .../tests/test_delivery_carrier.py | 98 ++-- .../tests/test_in_store_delivery.py | 12 +- .../tests/test_payment_provider.py | 10 +- .../tests/test_payment_transaction.py | 12 +- .../tests/test_product_template.py | 8 +- .../tests/test_sale_order.py | 76 +-- .../tests/test_website.py | 2 +- 41 files changed, 938 insertions(+), 938 deletions(-) diff --git a/addons/delivery/controllers/location_selector.py b/addons/delivery/controllers/location_selector.py index f3996128c9bcf..9ada6ec1d546f 100644 --- a/addons/delivery/controllers/location_selector.py +++ b/addons/delivery/controllers/location_selector.py @@ -4,7 +4,7 @@ class LocationSelectorController(Controller): - @route('/delivery/set_pickup_location', type='jsonrpc', auth='user') + @route("/delivery/set_pickup_location", type="jsonrpc", auth="user") def delivery_set_pickup_location(self, order_id, pickup_location_data): """Fetch the order and set the pickup location on the current order. @@ -12,10 +12,10 @@ def delivery_set_pickup_location(self, order_id, pickup_location_data): :param str pickup_location_data: The JSON-formatted pickup location address. :return: None """ - order = request.env['sale.order'].browse(order_id) + order = request.env["sale.order"].browse(order_id) order._set_pickup_location(pickup_location_data) - @route('/delivery/get_pickup_locations', type='jsonrpc', auth='user') + @route("/delivery/get_pickup_locations", type="jsonrpc", auth="user") def delivery_get_pickup_locations(self, order_id, zip_code=None): """Fetch the order and return the pickup locations close to a given zip code. @@ -26,10 +26,10 @@ def delivery_get_pickup_locations(self, order_id, zip_code=None): :return: The close pickup locations data. :rtype: dict """ - order = request.env['sale.order'].browse(order_id) + order = request.env["sale.order"].browse(order_id) if request.geoip.country_code: - country = request.env['res.country'].search( - [('code', '=', request.geoip.country_code)], limit=1 + country = request.env["res.country"].search( + [("code", "=", request.geoip.country_code)], limit=1 ) else: country = order.partner_shipping_id.country_id diff --git a/addons/delivery/models/delivery_carrier.py b/addons/delivery/models/delivery_carrier.py index d179da229104b..9ea2f91cfb24a 100644 --- a/addons/delivery/models/delivery_carrier.py +++ b/addons/delivery/models/delivery_carrier.py @@ -11,9 +11,9 @@ class DeliveryCarrier(models.Model): - _name = 'delivery.carrier' + _name = "delivery.carrier" _description = "Delivery Method" - _order = 'sequence, id' + _order = "sequence, id" """A Shipping Provider @@ -37,8 +37,8 @@ class DeliveryCarrier(models.Model): # This field will be overwritten by internal shipping providers by adding their own type. delivery_type = fields.Selection( string="Provider", - selection=[('base_on_rule', "Based on Rules"), ('fixed', "Fixed Price")], - default='fixed', + selection=[("base_on_rule", "Based on Rules"), ("fixed", "Fixed Price")], + default="fixed", required=True, ) allow_cash_on_delivery = fields.Boolean( @@ -47,8 +47,8 @@ class DeliveryCarrier(models.Model): ) integration_level = fields.Selection( help="Action while validating Delivery Orders.", - selection=[('rate', "Get Rate"), ('rate_and_ship', "Get Rate and Create Shipment")], - default='rate_and_ship', + selection=[("rate", "Get Rate"), ("rate_and_ship", "Get Rate and Create Shipment")], + default="rate_and_ship", ) prod_environment = fields.Boolean( string="Environment", help="Set to True if your credentials are certified for production." @@ -57,12 +57,12 @@ class DeliveryCarrier(models.Model): string="Debug logging", help="Log requests in order to ease debugging" ) company_id = fields.Many2one( - comodel_name='res.company', related='product_id.company_id', store=True, readonly=False + comodel_name="res.company", related="product_id.company_id", store=True, readonly=False ) product_id = fields.Many2one( string="Delivery Product", - comodel_name='product.product', - ondelete='restrict', + comodel_name="product.product", + ondelete="restrict", required=True, ) tracking_url = fields.Char( @@ -70,29 +70,29 @@ class DeliveryCarrier(models.Model): help="This option adds a link for the customer in the portal to track their package easily." " Use as a placeholder in your URL.", ) - currency_id = fields.Many2one(related='product_id.currency_id') + currency_id = fields.Many2one(related="product_id.currency_id") invoice_policy = fields.Selection( string="Invoicing Policy", help="Estimated Cost: the customer will be invoiced the estimated cost of the shipping.", - selection=[('estimated', "Estimated cost")], - default='estimated', + selection=[("estimated", "Estimated cost")], + default="estimated", required=True, ) country_ids = fields.Many2many( string="Countries", - comodel_name='res.country', - relation='delivery_carrier_country_rel', - column1='carrier_id', - column2='country_id', + comodel_name="res.country", + relation="delivery_carrier_country_rel", + column1="carrier_id", + column2="country_id", ) state_ids = fields.Many2many( string="States", - comodel_name='res.country.state', - relation='delivery_carrier_state_rel', - column1='carrier_id', - column2='state_id', + comodel_name="res.country.state", + relation="delivery_carrier_state_rel", + column1="carrier_id", + column2="state_id", ) zip_prefix_ids = fields.Many2many( string="Zip Prefixes", @@ -100,37 +100,37 @@ class DeliveryCarrier(models.Model): " expressions can be used to support countries with varying zip code lengths, i.e. '$'" " can be added to end of prefix to match the exact zip (e.g. '100$' will only match" " '100' and not '1000')", - comodel_name='delivery.zip.prefix', - relation='delivery_zip_prefix_rel', - column1='carrier_id', - column2='zip_prefix_id', + comodel_name="delivery.zip.prefix", + relation="delivery_zip_prefix_rel", + column1="carrier_id", + column2="zip_prefix_id", ) max_weight = fields.Float( help="If the total weight of the order is over this weight, the method won't be available." ) weight_uom_name = fields.Char( - string="Weight unit of measure label", compute='_compute_weight_uom_name' + string="Weight unit of measure label", compute="_compute_weight_uom_name" ) max_volume = fields.Float( help="If the total volume of the order is over this volume, the method won't be available." ) volume_uom_name = fields.Char( - string="Volume unit of measure label", compute='_compute_volume_uom_name' + string="Volume unit of measure label", compute="_compute_volume_uom_name" ) must_have_tag_ids = fields.Many2many( string="Must Have Tags", help="The method is available only if at least one product of the order has one of these" " tags.", - comodel_name='product.tag', - relation='product_tag_delivery_carrier_must_have_rel', + comodel_name="product.tag", + relation="product_tag_delivery_carrier_must_have_rel", ) excluded_tag_ids = fields.Many2many( string="Excluded Tags", help="The method is NOT available if at least one product of the order has one of these" " tags.", - comodel_name='product.tag', - relation='product_tag_delivery_carrier_excluded_rel', + comodel_name="product.tag", + relation="product_tag_delivery_carrier_excluded_rel", ) carrier_description = fields.Text( @@ -154,7 +154,7 @@ class DeliveryCarrier(models.Model): default=1000, ) - can_generate_return = fields.Boolean(compute='_compute_can_generate_return') + can_generate_return = fields.Boolean(compute="_compute_can_generate_return") return_label_on_delivery = fields.Boolean( string="Generate Return Label", help="The return label is automatically generated at the delivery.", @@ -164,7 +164,7 @@ class DeliveryCarrier(models.Model): help="The return label can be downloaded by the customer from the customer portal.", ) - supports_shipping_insurance = fields.Boolean(compute='_compute_supports_shipping_insurance') + supports_shipping_insurance = fields.Boolean(compute="_compute_supports_shipping_insurance") shipping_insurance = fields.Integer( string="Insurance Percentage", help="Shipping insurance is a service which may reimburse senders whose parcels are lost," @@ -174,20 +174,20 @@ class DeliveryCarrier(models.Model): price_rule_ids = fields.One2many( string="Pricing Rules", - comodel_name='delivery.price.rule', - inverse_name='carrier_id', + comodel_name="delivery.price.rule", + inverse_name="carrier_id", copy=True, ) _margin_not_under_100_percent = models.Constraint( - 'CHECK (margin >= -1)', "Margin cannot be lower than -100%" + "CHECK (margin >= -1)", "Margin cannot be lower than -100%" ) _shipping_insurance_is_percentage = models.Constraint( - 'CHECK(shipping_insurance >= 0 AND shipping_insurance <= 100)', + "CHECK(shipping_insurance >= 0 AND shipping_insurance <= 100)", "The shipping insurance must be a percentage between 0 and 100.", ) - @api.constrains('must_have_tag_ids', 'excluded_tag_ids') + @api.constrains("must_have_tag_ids", "excluded_tag_ids") def _check_tags(self): for carrier in self: if carrier.must_have_tag_ids & carrier.excluded_tag_ids: @@ -201,20 +201,20 @@ def _check_tags(self): def _compute_weight_uom_name(self): self.weight_uom_name = self.env[ - 'product.template' + "product.template" ]._get_weight_uom_name_from_ir_config_parameter() def _compute_volume_uom_name(self): self.volume_uom_name = self.env[ - 'product.template' + "product.template" ]._get_volume_uom_name_from_ir_config_parameter() - @api.depends('delivery_type') + @api.depends("delivery_type") def _compute_can_generate_return(self): for carrier in self: carrier.can_generate_return = False - @api.depends('delivery_type') + @api.depends("delivery_type") def _compute_supports_shipping_insurance(self): for carrier in self: carrier.supports_shipping_insurance = False @@ -228,20 +228,20 @@ def toggle_debug(self): c.debug_logging = not c.debug_logging def install_more_provider(self): - exclude_apps = ['delivery_barcode', 'delivery_stock_picking_batch', 'delivery_iot'] + exclude_apps = ["delivery_barcode", "delivery_stock_picking_batch", "delivery_iot"] return { - 'name': _('New Providers'), - 'res_model': 'ir.module.module', - 'view_mode': 'kanban,list', - 'views': [ - (self.env.ref('delivery.delivery_provider_module_kanban').id, 'kanban'), - (self.env.ref('delivery.delivery_provider_module_list').id, 'list'), + "name": _("New Providers"), + "res_model": "ir.module.module", + "view_mode": "kanban,list", + "views": [ + (self.env.ref("delivery.delivery_provider_module_kanban").id, "kanban"), + (self.env.ref("delivery.delivery_provider_module_list").id, "list"), ], - 'domain': [['name', '=like', 'delivery_%'], ['name', 'not in', exclude_apps]], - 'type': 'ir.actions.act_window', - 'help': _('''

+ "domain": [["name", "=like", "delivery_%"], ["name", "not in", exclude_apps]], + "type": "ir.actions.act_window", + "help": _("""

Buy Odoo Enterprise now to get more providers. -

'''), +

"""), } def _is_available_for_order(self, order): @@ -250,8 +250,8 @@ def _is_available_for_order(self, order): if not self._match(order.partner_shipping_id, order): return False - if self.delivery_type == 'base_on_rule': - return self.rate_shipment(order).get('success') + if self.delivery_type == "base_on_rule": + return self.rate_shipment(order).get("success") return True @@ -276,7 +276,7 @@ def _match_address(self, partner): return False if self.zip_prefix_ids: regex = re.compile( - '|'.join(['^' + zip_prefix for zip_prefix in self.zip_prefix_ids.mapped('name')]) + "|".join(["^" + zip_prefix for zip_prefix in self.zip_prefix_ids.mapped("name")]) ) if not partner.zip or not re.match(regex, partner.zip.upper()): return False @@ -284,10 +284,10 @@ def _match_address(self, partner): def _match_must_have_tags(self, source): self.ensure_one() - if source._name == 'sale.order': + if source._name == "sale.order": products = source.order_line.product_id - elif source._name == 'stock.picking': - products = source.move_ids.with_prefetch().mapped('product_id') + elif source._name == "stock.picking": + products = source.move_ids.with_prefetch().mapped("product_id") else: raise UserError(_("Invalid source document type")) return not self.must_have_tag_ids or any( @@ -296,21 +296,21 @@ def _match_must_have_tags(self, source): def _match_excluded_tags(self, source): self.ensure_one() - if source._name == 'sale.order': + if source._name == "sale.order": products = source.order_line.product_id - elif source._name == 'stock.picking': - products = source.move_ids.with_prefetch().mapped('product_id') + elif source._name == "stock.picking": + products = source.move_ids.with_prefetch().mapped("product_id") else: raise UserError(_("Invalid source document type")) return not any(tag in products.all_product_tag_ids for tag in self.excluded_tag_ids) def _match_weight(self, source): self.ensure_one() - if source._name == 'sale.order': + if source._name == "sale.order": total_weight = sum( line.product_id.weight * line.product_qty for line in source.order_line ) - elif source._name == 'stock.picking': + elif source._name == "stock.picking": total_weight = sum( move.product_id.weight * move.product_uom_qty for move in source.move_ids ) @@ -320,11 +320,11 @@ def _match_weight(self, source): def _match_volume(self, source): self.ensure_one() - if source._name == 'sale.order': + if source._name == "sale.order": total_volume = sum( line.product_id.volume * line.product_qty for line in source.order_line ) - elif source._name == 'stock.picking': + elif source._name == "stock.picking": total_volume = sum( move.product_id.volume * move.product_uom_qty for move in source.move_ids ) @@ -332,22 +332,22 @@ def _match_volume(self, source): raise UserError(_("Invalid source document type")) return not self.max_volume or total_volume <= self.max_volume - @api.onchange('integration_level') + @api.onchange("integration_level") def _onchange_integration_level(self): - if self.integration_level == 'rate': - self.invoice_policy = 'estimated' + if self.integration_level == "rate": + self.invoice_policy = "estimated" - @api.onchange('can_generate_return') + @api.onchange("can_generate_return") def _onchange_can_generate_return(self): if not self.can_generate_return: self.return_label_on_delivery = False - @api.onchange('return_label_on_delivery') + @api.onchange("return_label_on_delivery") def _onchange_return_label_on_delivery(self): if not self.return_label_on_delivery: self.get_return_label_from_portal = False - @api.onchange('country_ids') + @api.onchange("country_ids") def _onchange_country_ids(self): self.state_ids -= self.state_ids.filtered( lambda state: state._origin.id not in self.country_ids.state_ids.ids @@ -373,10 +373,10 @@ def _get_delivery_type(self): def _apply_margins(self, price, order=False): self.ensure_one() - if self.delivery_type == 'fixed': + if self.delivery_type == "fixed": return float(price) fixed_margin_in_sale_currency = ( - self._compute_currency(order, self.fixed_margin, 'company_to_pricelist') + self._compute_currency(order, self.fixed_margin, "company_to_pricelist") if order else self.fixed_margin ) @@ -401,42 +401,42 @@ def rate_shipment(self, order): """ # TODO maybe the currency code? self.ensure_one() - if hasattr(self, '%s_rate_shipment' % self.delivery_type): - res = getattr(self, '%s_rate_shipment' % self.delivery_type)(order) + if hasattr(self, "%s_rate_shipment" % self.delivery_type): + res = getattr(self, "%s_rate_shipment" % self.delivery_type)(order) # apply fiscal position company = self.company_id or order.company_id or self.env.company - res['price'] = self.product_id._get_tax_included_unit_price( + res["price"] = self.product_id._get_tax_included_unit_price( company, company.currency_id, order.date_order, - 'sale', + "sale", fiscal_position=order.fiscal_position_id, - product_price_unit=res['price'], + product_price_unit=res["price"], product_currency=company.currency_id, ) # apply margin on computed price - res['price'] = self._apply_margins(res['price'], order) + res["price"] = self._apply_margins(res["price"], order) # save the real price in case a free_over rule overide it to 0 - res['carrier_price'] = res['price'] + res["carrier_price"] = res["price"] # free when order is large enough amount_without_delivery = order._compute_amount_total_without_delivery() if ( - res['success'] + res["success"] and self.free_over - and self.delivery_type != 'base_on_rule' - and self._compute_currency(order, amount_without_delivery, 'pricelist_to_company') + and self.delivery_type != "base_on_rule" + and self._compute_currency(order, amount_without_delivery, "pricelist_to_company") >= self.amount ): - res['warning_message'] = _( - 'The shipping is free since the order amount exceeds %.2f.', self.amount + res["warning_message"] = _( + "The shipping is free since the order amount exceeds %.2f.", self.amount ) - res['price'] = 0.0 + res["price"] = 0.0 return res return { - 'success': False, - 'price': 0.0, - 'error_message': _('Error: this delivery method is not available.'), - 'warning_message': False, + "success": False, + "price": 0.0, + "error_message": _("Error: this delivery method is not available."), + "warning_message": False, } def log_xml(self, xml_string, func): @@ -451,16 +451,16 @@ def log_xml(self, xml_string, func): db_registry = Registry(db_name) with db_registry.cursor() as cr: env = api.Environment(cr, SUPERUSER_ID, {}) - IrLogging = env['ir.logging'] + IrLogging = env["ir.logging"] IrLogging.sudo().create({ - 'name': 'delivery.carrier', - 'type': 'server', - 'dbname': db_name, - 'level': 'DEBUG', - 'message': xml_string, - 'path': self.delivery_type, - 'func': func, - 'line': 1, + "name": "delivery.carrier", + "type": "server", + "dbname": db_name, + "level": "DEBUG", + "message": xml_string, + "path": self.delivery_type, + "func": func, + "line": 1, }) except psycopg2.Error: pass @@ -471,12 +471,12 @@ def log_xml(self, xml_string, func): fixed_price = fields.Float( string="Fixed Price", - compute='_compute_fixed_price', - inverse='_set_product_fixed_price', + compute="_compute_fixed_price", + inverse="_set_product_fixed_price", store=True, ) - @api.depends('product_id.list_price', 'product_id.product_tmpl_id.list_price') + @api.depends("product_id.list_price", "product_id.product_tmpl_id.list_price") def _compute_fixed_price(self): for carrier in self: carrier.fixed_price = carrier.product_id.list_price @@ -489,15 +489,15 @@ def fixed_rate_shipment(self, order): carrier = self._match_address(order.partner_shipping_id) if not carrier: return { - 'success': False, - 'price': 0.0, - 'error_message': _( - 'Error: this delivery method is not available for this address.' + "success": False, + "price": 0.0, + "error_message": _( + "Error: this delivery method is not available for this address." ), - 'warning_message': False, + "warning_message": False, } price = order.pricelist_id._get_product_price(self.product_id, 1.0) - return {'success': True, 'price': price, 'error_message': False, 'warning_message': False} + return {"success": True, "price": price, "error_message": False, "warning_message": False} # ----------------------------------- # # Based on rule delivery type methods # @@ -507,42 +507,42 @@ def base_on_rule_rate_shipment(self, order): carrier = self._match_address(order.partner_shipping_id) if not carrier: return { - 'success': False, - 'price': 0.0, - 'error_message': _( - 'Error: this delivery method is not available for this address.' + "success": False, + "price": 0.0, + "error_message": _( + "Error: this delivery method is not available for this address." ), - 'warning_message': False, + "warning_message": False, } try: price_unit = self._get_price_available(order) except UserError as e: return { - 'success': False, - 'price': 0.0, - 'error_message': e.args[0], - 'warning_message': False, + "success": False, + "price": 0.0, + "error_message": e.args[0], + "warning_message": False, } - price_unit = self._compute_currency(order, price_unit, 'company_to_pricelist') + price_unit = self._compute_currency(order, price_unit, "company_to_pricelist") return { - 'success': True, - 'price': price_unit, - 'error_message': False, - 'warning_message': False, + "success": True, + "price": price_unit, + "error_message": False, + "warning_message": False, } def _get_conversion_currencies(self, order, conversion): company_currency = ( - self.company_id or self.env['res.company']._get_main_company() + self.company_id or self.env["res.company"]._get_main_company() ).currency_id pricelist_currency = order.currency_id - if conversion == 'company_to_pricelist': + if conversion == "company_to_pricelist": return company_currency, pricelist_currency - if conversion == 'pricelist_to_company': + if conversion == "pricelist_to_company": return pricelist_currency, company_currency def _compute_currency(self, order, price, conversion): @@ -560,7 +560,7 @@ def _get_price_available(self, order): total = weight = volume = quantity = wv = 0 total_delivery = 0.0 for line in order.order_line: - if line.state == 'cancel': + if line.state == "cancel": continue if line.is_delivery: total_delivery += line.price_total @@ -577,12 +577,12 @@ def _get_price_available(self, order): quantity += qty total = (order.amount_total or 0.0) - total_delivery - total = self._compute_currency(order, total, 'pricelist_to_company') + total = self._compute_currency(order, total, "pricelist_to_company") # weight is either, # 1- weight chosen by user in choose.delivery.carrier wizard passed by context # 2- saved weight to use on sale order # 3- total order line weight as fallback - weight = self.env.context.get('order_weight') or order.shipping_weight or weight + weight = self.env.context.get("order_weight") or order.shipping_weight or weight return self._get_price_from_picking(total, weight, volume, quantity, wv=wv) def _get_price_dict(self, total, weight, volume, quantity, wv=0.0): @@ -592,11 +592,11 @@ def _get_price_dict(self, total, weight, volume, quantity, wv=0.0): factor from price rules. """ return { - 'price': total, - 'volume': volume, - 'weight': weight, - 'wv': wv or volume * weight, - 'quantity': quantity, + "price": total, + "volume": volume, + "weight": weight, + "wv": wv or volume * weight, + "quantity": quantity, } def _get_price_from_picking(self, total, weight, volume, quantity, wv=0.0): diff --git a/addons/delivery/models/delivery_price_rule.py b/addons/delivery/models/delivery_price_rule.py index 85b182632ca37..2e14b05b05ce4 100644 --- a/addons/delivery/models/delivery_price_rule.py +++ b/addons/delivery/models/delivery_price_rule.py @@ -4,31 +4,31 @@ from odoo.tools import format_amount VARIABLE_SELECTION = [ - ('weight', "Weight"), - ('volume', "Volume"), - ('wv', "Weight * Volume"), - ('price', "Price"), - ('quantity', "Quantity"), + ("weight", "Weight"), + ("volume", "Volume"), + ("wv", "Weight * Volume"), + ("price", "Price"), + ("quantity", "Quantity"), ] class DeliveryPriceRule(models.Model): - _name = 'delivery.price.rule' + _name = "delivery.price.rule" _description = "Delivery Price Rules" - _order = 'sequence, list_price, id' + _order = "sequence, list_price, id" @api.depends( - 'variable', - 'operator', - 'max_value', - 'list_base_price', - 'list_price', - 'variable_factor', - 'currency_id', + "variable", + "operator", + "max_value", + "list_base_price", + "list_price", + "variable_factor", + "currency_id", ) def _compute_name(self): for rule in self: - name = 'if %s %s %.02f then' % (rule.variable, rule.operator, rule.max_value) + name = "if %s %s %.02f then" % (rule.variable, rule.operator, rule.max_value) if rule.currency_id: base_price = format_amount(self.env, rule.list_base_price, rule.currency_id) price = format_amount(self.env, rule.list_price, rule.currency_id) @@ -36,11 +36,11 @@ def _compute_name(self): base_price = "%.2f" % rule.list_base_price price = "%.2f" % rule.list_price if rule.list_base_price and not rule.list_price: - name = '%s fixed price %s' % (name, base_price) + name = "%s fixed price %s" % (name, base_price) elif rule.list_price and not rule.list_base_price: - name = '%s %s times %s' % (name, price, rule.variable_factor) + name = "%s %s times %s" % (name, price, rule.variable_factor) else: - name = '%s fixed price %s plus %s times %s' % ( + name = "%s fixed price %s plus %s times %s" % ( name, base_price, price, @@ -48,26 +48,26 @@ def _compute_name(self): ) rule.name = name - name = fields.Char(compute='_compute_name') + name = fields.Char(compute="_compute_name") sequence = fields.Integer(required=True, default=10) carrier_id = fields.Many2one( - comodel_name='delivery.carrier', ondelete='cascade', required=True, index=True + comodel_name="delivery.carrier", ondelete="cascade", required=True, index=True ) - currency_id = fields.Many2one(related='carrier_id.currency_id') + currency_id = fields.Many2one(related="carrier_id.currency_id") - variable = fields.Selection(selection=VARIABLE_SELECTION, default='quantity', required=True) + variable = fields.Selection(selection=VARIABLE_SELECTION, default="quantity", required=True) operator = fields.Selection( - selection=[('==', '='), ('<=', '<='), ('<', '<'), ('>=', '>='), ('>', '>')], - default='<=', + selection=[("==", "="), ("<=", "<="), ("<", "<"), (">=", ">="), (">", ">")], + default="<=", required=True, ) max_value = fields.Float(string="Maximum Value", required=True) list_base_price = fields.Float( - string="Sale Base Price", digits='Product Price', default=0.0, required=True + string="Sale Base Price", digits="Product Price", default=0.0, required=True ) list_price = fields.Float( - string="Sale Price", digits='Product Price', default=0.0, required=True + string="Sale Price", digits="Product Price", default=0.0, required=True ) variable_factor = fields.Selection( - selection=VARIABLE_SELECTION, default='weight', required=True + selection=VARIABLE_SELECTION, default="weight", required=True ) diff --git a/addons/delivery/models/delivery_zip_prefix.py b/addons/delivery/models/delivery_zip_prefix.py index 25f02b4fffbea..bbff60ea30fff 100644 --- a/addons/delivery/models/delivery_zip_prefix.py +++ b/addons/delivery/models/delivery_zip_prefix.py @@ -6,9 +6,9 @@ class DeliveryZipPrefix(models.Model): """Zip prefix that a delivery.carrier will deliver to.""" - _name = 'delivery.zip.prefix' + _name = "delivery.zip.prefix" _description = "Delivery Zip Prefix" - _order = 'name, id' + _order = "name, id" name = fields.Char(string="Prefix", required=True) @@ -17,12 +17,12 @@ def create(self, vals_list): for vals in vals_list: # we cannot easily convert a list of prefix names into upper to compare with partner # zips later on, so let's ensure they are always upper - vals['name'] = vals['name'].upper() + vals["name"] = vals["name"].upper() return super().create(vals_list) def write(self, vals): - if 'name' in vals: - vals['name'] = vals['name'].upper() + if "name" in vals: + vals["name"] = vals["name"].upper() return super().write(vals) - _name_uniq = models.Constraint('unique (name)', "Prefix already exists!") + _name_uniq = models.Constraint("unique (name)", "Prefix already exists!") diff --git a/addons/delivery/models/ir_http.py b/addons/delivery/models/ir_http.py index 0a8db84b0ec00..7c543aeffa17f 100644 --- a/addons/delivery/models/ir_http.py +++ b/addons/delivery/models/ir_http.py @@ -4,9 +4,9 @@ class IrHttp(models.AbstractModel): - _inherit = 'ir.http' + _inherit = "ir.http" @classmethod def _get_translation_frontend_modules_name(cls): mods = super()._get_translation_frontend_modules_name() - return mods + ['delivery'] + return mods + ["delivery"] diff --git a/addons/delivery/models/ir_module_module.py b/addons/delivery/models/ir_module_module.py index 93210aba59a53..9a7ba1f3dac90 100644 --- a/addons/delivery/models/ir_module_module.py +++ b/addons/delivery/models/ir_module_module.py @@ -4,20 +4,20 @@ class IrModuleModule(models.Model): - _name = 'ir.module.module' - _inherit = ['ir.module.module'] + _name = "ir.module.module" + _inherit = ["ir.module.module"] def action_view_delivery_methods(self): self.ensure_one() module_name = self.name # e.g., delivery_dhl - if not module_name.startswith('delivery_'): + if not module_name.startswith("delivery_"): return False - delivery_type = module_name.removeprefix('delivery_') # dhl, fedex, etc. - action = self.env.ref('delivery.action_delivery_carrier_form').read()[0] - if delivery_type == 'mondialrelay': - action['context'] = {'search_default_is_mondialrelay': True} + delivery_type = module_name.removeprefix("delivery_") # dhl, fedex, etc. + action = self.env.ref("delivery.action_delivery_carrier_form").read()[0] + if delivery_type == "mondialrelay": + action["context"] = {"search_default_is_mondialrelay": True} else: - action['context'] = {'search_default_delivery_type': delivery_type} + action["context"] = {"search_default_delivery_type": delivery_type} return action diff --git a/addons/delivery/models/payment_provider.py b/addons/delivery/models/payment_provider.py index 576d406a89e7a..61d55efaeb306 100644 --- a/addons/delivery/models/payment_provider.py +++ b/addons/delivery/models/payment_provider.py @@ -7,16 +7,16 @@ class PaymentProvider(models.Model): - _inherit = 'payment.provider' + _inherit = "payment.provider" - custom_mode = fields.Selection(selection_add=[('cash_on_delivery', "Cash On Delivery")]) + custom_mode = fields.Selection(selection_add=[("cash_on_delivery", "Cash On Delivery")]) # === CRUD METHODS === # def _get_default_payment_method_codes(self): """Override of `payment` to return the default payment method codes.""" self.ensure_one() - if self.custom_mode != 'cash_on_delivery': + if self.custom_mode != "cash_on_delivery": return super()._get_default_payment_method_codes() return const.DEFAULT_PAYMENT_METHOD_CODES @@ -35,11 +35,11 @@ def _get_compatible_providers(self, *args, sale_order_id=None, report=None, **kw *args, sale_order_id=sale_order_id, report=report, **kwargs ) - sale_order = self.env['sale.order'].browse(sale_order_id).exists() + sale_order = self.env["sale.order"].browse(sale_order_id).exists() if not sale_order.carrier_id.allow_cash_on_delivery: unfiltered_providers = compatible_providers compatible_providers = compatible_providers.filtered( - lambda p: p.custom_mode != 'cash_on_delivery' + lambda p: p.custom_mode != "cash_on_delivery" ) payment_utils.add_to_report( report, diff --git a/addons/delivery/models/payment_transaction.py b/addons/delivery/models/payment_transaction.py index 1cdabae5681eb..9a4b3bb2fe074 100644 --- a/addons/delivery/models/payment_transaction.py +++ b/addons/delivery/models/payment_transaction.py @@ -4,15 +4,15 @@ class PaymentTransaction(models.Model): - _inherit = 'payment.transaction' + _inherit = "payment.transaction" def _post_process(self): """Override of `payment` to confirm orders with the cash_on_delivery payment method and trigger a picking creation.""" cod_pending_txs = self.filtered( - lambda tx: tx.provider_id.custom_mode == 'cash_on_delivery' and tx.state == 'pending' + lambda tx: tx.provider_id.custom_mode == "cash_on_delivery" and tx.state == "pending" ) - cod_pending_txs.sale_order_ids.filtered(lambda so: so.state == 'draft').with_context( + cod_pending_txs.sale_order_ids.filtered(lambda so: so.state == "draft").with_context( send_email=True ).action_confirm() super()._post_process() diff --git a/addons/delivery/models/product_category.py b/addons/delivery/models/product_category.py index cb555aa18b999..147b622645176 100644 --- a/addons/delivery/models/product_category.py +++ b/addons/delivery/models/product_category.py @@ -10,7 +10,7 @@ class ProductCategory(models.Model): @api.ondelete(at_uninstall=False) def _unlink_except_delivery_category(self): delivery_category = self.env.ref( - 'delivery.product_category_deliveries', raise_if_not_found=False + "delivery.product_category_deliveries", raise_if_not_found=False ) if delivery_category and delivery_category in self: raise UserError( diff --git a/addons/delivery/models/res_partner.py b/addons/delivery/models/res_partner.py index 4d932d3ae6eb2..ed69097fb8aea 100644 --- a/addons/delivery/models/res_partner.py +++ b/addons/delivery/models/res_partner.py @@ -5,15 +5,15 @@ class ResPartner(models.Model): - _inherit = 'res.partner' + _inherit = "res.partner" property_delivery_carrier_id = fields.Many2one( string="Delivery Method", help="Used in sales orders.", - comodel_name='delivery.carrier', + comodel_name="delivery.carrier", company_dependent=True, ) is_pickup_location = fields.Boolean() # Whether it is a pickup point address. def _get_delivery_address_domain(self): - return super()._get_delivery_address_domain() & Domain('is_pickup_location', '=', False) + return super()._get_delivery_address_domain() & Domain("is_pickup_location", "=", False) diff --git a/addons/delivery/models/sale_order.py b/addons/delivery/models/sale_order.py index b3bd1fdf0fbae..8c6b6a1d60818 100644 --- a/addons/delivery/models/sale_order.py +++ b/addons/delivery/models/sale_order.py @@ -7,20 +7,20 @@ class SaleOrder(models.Model): - _inherit = 'sale.order' + _inherit = "sale.order" pickup_location_data = fields.Json() carrier_id = fields.Many2one( string="Delivery Method", help="Fill this field if you plan to invoice the shipping based on picking.", - comodel_name='delivery.carrier', + comodel_name="delivery.carrier", check_company=True, ) delivery_message = fields.Char(readonly=True, copy=False) - delivery_set = fields.Boolean(compute='_compute_delivery_state') + delivery_set = fields.Boolean(compute="_compute_delivery_state") recompute_delivery_price = fields.Boolean(string="Delivery cost should be recomputed") is_all_service = fields.Boolean( - string="Service Product", compute='_compute_is_service_products' + string="Service Product", compute="_compute_is_service_products" ) shipping_weight = fields.Float(compute="_compute_shipping_weight", store=True, readonly=False) @@ -31,11 +31,11 @@ def _compute_partner_shipping_id(self): if order.partner_shipping_id.is_pickup_location: order.partner_shipping_id = order.partner_id - @api.depends('order_line') + @api.depends("order_line") def _compute_is_service_products(self): for so in self: so.is_all_service = all( - line.product_id.type == 'service' + line.product_id.type == "service" for line in so.order_line.filtered(lambda x: not x.display_type) ) @@ -44,15 +44,15 @@ def _compute_amount_total_without_delivery(self): delivery_cost = sum([ol.price_total for ol in self.order_line if ol.is_delivery]) return self.amount_total - delivery_cost - @api.depends('order_line') + @api.depends("order_line") def _compute_delivery_state(self): for order in self: order.delivery_set = any(line.is_delivery for line in order.order_line) - @api.onchange('order_line', 'partner_id', 'partner_shipping_id') + @api.onchange("order_line", "partner_id", "partner_shipping_id") def onchange_order_line(self): self.ensure_one() - delivery_line = self.order_line.filtered('is_delivery') + delivery_line = self.order_line.filtered("is_delivery") if delivery_line: self.recompute_delivery_price = True @@ -71,12 +71,12 @@ def _remove_delivery_line(self): if not to_delete: raise UserError( _( - 'You can not update the shipping costs on an order where it was already' - ' invoiced!\n\nThe following delivery lines (product, invoiced quantity and' - ' price) have already been processed:\n\n' + "You can not update the shipping costs on an order where it was already" + " invoiced!\n\nThe following delivery lines (product, invoiced quantity and" + " price) have already been processed:\n\n" ) - + '\n'.join([ - '- %s: %s x %s' + + "\n".join([ + "- %s: %s x %s" % ( line.product_id.with_context(display_default_code=False).display_name, line.qty_invoiced, @@ -103,7 +103,7 @@ def _set_pickup_location(self, pickup_location_data): :return: None """ self.ensure_one() - use_locations_fname = f'{self.carrier_id.delivery_type}_use_locations' + use_locations_fname = f"{self.carrier_id.delivery_type}_use_locations" if hasattr(self.carrier_id, use_locations_fname): use_location = getattr(self.carrier_id, use_locations_fname) if use_location and pickup_location_data: @@ -128,43 +128,43 @@ def _get_pickup_locations(self, zip_code=None, country=None, **kwargs): self.ensure_one() if zip_code: assert country # country is required if zip_code is provided. - partner_address = self.env['res.partner'].new({ - 'active': False, - 'country_id': country.id, - 'zip': zip_code, + partner_address = self.env["res.partner"].new({ + "active": False, + "country_id": country.id, + "zip": zip_code, }) else: partner_address = self.partner_shipping_id try: - error = {'error': _("No pick-up points are available for this delivery address.")} - function_name = f'_{self.carrier_id.delivery_type}_get_close_locations' + error = {"error": _("No pick-up points are available for this delivery address.")} + function_name = f"_{self.carrier_id.delivery_type}_get_close_locations" if not hasattr(self.carrier_id, function_name): return error pickup_locations = getattr(self.carrier_id, function_name)(partner_address, **kwargs) if not pickup_locations: return error - return {'pickup_locations': pickup_locations} + return {"pickup_locations": pickup_locations} except UserError as e: - return {'error': str(e)} + return {"error": str(e)} def action_open_delivery_wizard(self): - view_id = self.env.ref('delivery.choose_delivery_carrier_view_form').id - if self.env.context.get('carrier_recompute'): - name = _('Update shipping cost') + view_id = self.env.ref("delivery.choose_delivery_carrier_view_form").id + if self.env.context.get("carrier_recompute"): + name = _("Update shipping cost") else: - name = _('Add a delivery method') + name = _("Add a delivery method") return { - 'name': name, - 'type': 'ir.actions.act_window', - 'view_mode': 'form', - 'res_model': 'choose.delivery.carrier', - 'view_id': view_id, - 'views': [(view_id, 'form')], - 'target': 'new', - 'context': { - 'default_order_id': self.id, - 'default_carrier_id': self.carrier_id, - 'default_total_weight': self._get_estimated_weight(), + "name": name, + "type": "ir.actions.act_window", + "view_mode": "form", + "res_model": "choose.delivery.carrier", + "view_id": view_id, + "views": [(view_id, "form")], + "target": "new", + "context": { + "default_order_id": self.id, + "default_carrier_id": self.carrier_id, + "default_total_weight": self._get_estimated_weight(), }, } @@ -176,17 +176,17 @@ def _action_confirm(self): continue # Retrieve all the data : name, street, city, state, zip, country. - name = order_location.get('name') or order.partner_shipping_id.name - street = order_location['street'] - city = order_location['city'] - zip_code = order_location['zip_code'] - country_code = order_location['country_code'] - country = order.env['res.country'].search([('code', '=', country_code)]).id + name = order_location.get("name") or order.partner_shipping_id.name + street = order_location["street"] + city = order_location["city"] + zip_code = order_location["zip_code"] + country_code = order_location["country_code"] + country = order.env["res.country"].search([("code", "=", country_code)]).id state = None - if order_location.get('state') and country: + if order_location.get("state") and country: state = ( - order.env['res.country.state'] - .search([('code', '=', order_location['state']), ('country_id', '=', country)]) + order.env["res.country.state"] + .search([("code", "=", order_location["state"]), ("country_id", "=", country)]) .id ) parent_id = order.partner_shipping_id.id @@ -194,33 +194,33 @@ def _action_confirm(self): phone = order.partner_shipping_id.phone # Check if the current partner has a partner of type 'delivery' with the same address. - existing_partner = order.env['res.partner'].search( + existing_partner = order.env["res.partner"].search( [ - ('street', '=', street), - ('city', '=', city), - ('state_id', '=', state), - ('country_id', '=', country), - ('parent_id', '=', parent_id), - ('type', '=', 'delivery'), + ("street", "=", street), + ("city", "=", city), + ("state_id", "=", state), + ("country_id", "=", country), + ("parent_id", "=", parent_id), + ("type", "=", "delivery"), ], limit=1, ) - shipping_partner = existing_partner or order.env['res.partner'].create({ - 'parent_id': parent_id, - 'type': 'delivery', - 'name': name, - 'street': street, - 'city': city, - 'state_id': state, - 'zip': zip_code, - 'country_id': country, - 'email': email, - 'phone': phone, - 'is_pickup_location': True, + shipping_partner = existing_partner or order.env["res.partner"].create({ + "parent_id": parent_id, + "type": "delivery", + "name": name, + "street": street, + "city": city, + "state_id": state, + "zip": zip_code, + "country_id": country, + "email": email, + "phone": phone, + "is_pickup_location": True, }) order.with_context(update_delivery_shipping_partner=True).write({ - 'partner_shipping_id': shipping_partner + "partner_shipping_id": shipping_partner }) return super()._action_confirm() @@ -228,7 +228,7 @@ def _prepare_delivery_line_vals(self, carrier, price_unit): context = {} if self.partner_id: # set delivery detail in the customer language - context['lang'] = self.partner_id.lang + context["lang"] = self.partner_id.lang carrier = carrier.with_context(lang=self.partner_id.lang) # Apply fiscal position @@ -240,30 +240,30 @@ def _prepare_delivery_line_vals(self, carrier, price_unit): # Create the sales order line if carrier.product_id.description_sale: - so_description = '%s: %s' % (carrier.name, carrier.product_id.description_sale) + so_description = "%s: %s" % (carrier.name, carrier.product_id.description_sale) else: so_description = carrier.name values = { - 'order_id': self.id, - 'name': so_description, - 'price_unit': price_unit, - 'product_uom_qty': 1, - 'product_id': carrier.product_id.id, - 'tax_ids': [(6, 0, taxes_ids)], - 'is_delivery': True, + "order_id": self.id, + "name": so_description, + "price_unit": price_unit, + "product_uom_qty": 1, + "product_id": carrier.product_id.id, + "tax_ids": [(6, 0, taxes_ids)], + "is_delivery": True, } if carrier.free_over and self.currency_id.is_zero(price_unit): - values['name'] = _('%s\nFree Shipping', values['name']) + values["name"] = _("%s\nFree Shipping", values["name"]) if self.order_line: - values['sequence'] = self.order_line[-1].sequence + 1 + values["sequence"] = self.order_line[-1].sequence + 1 del context return values def _create_delivery_line(self, carrier, price_unit): values = self._prepare_delivery_line_vals(carrier, price_unit) - return self.env['sale.order.line'].sudo().create(values) + return self.env["sale.order.line"].sudo().create(values) - @api.depends('order_line.product_uom_qty', 'order_line.product_uom_id') + @api.depends("order_line.product_uom_qty", "order_line.product_uom_id") def _compute_shipping_weight(self): for order in self: order.shipping_weight = order._get_estimated_weight() @@ -272,7 +272,7 @@ def _get_estimated_weight(self): self.ensure_one() weight = 0.0 for order_line in self.order_line.filtered( - lambda ol: ol.product_id.type == 'consu' + lambda ol: ol.product_id.type == "consu" and not ol.is_delivery and not ol.display_type and ol.product_uom_qty > 0 diff --git a/addons/delivery/models/sale_order_line.py b/addons/delivery/models/sale_order_line.py index 6fcfce2db2d68..aad9a66e19469 100644 --- a/addons/delivery/models/sale_order_line.py +++ b/addons/delivery/models/sale_order_line.py @@ -4,18 +4,18 @@ class SaleOrderLine(models.Model): - _inherit = 'sale.order.line' + _inherit = "sale.order.line" is_delivery = fields.Boolean(string="Is a Delivery", default=False) product_qty = fields.Float( - string="Product Qty", compute='_compute_product_qty', digits='Product Unit' + string="Product Qty", compute="_compute_product_qty", digits="Product Unit" ) - recompute_delivery_price = fields.Boolean(related='order_id.recompute_delivery_price') + recompute_delivery_price = fields.Boolean(related="order_id.recompute_delivery_price") def _can_be_invoiced_alone(self): return super()._can_be_invoiced_alone() and not self.is_delivery - @api.depends('product_id', 'product_uom_id', 'product_uom_qty') + @api.depends("product_id", "product_uom_id", "product_uom_qty") def _compute_product_qty(self): for line in self: if not line.product_id or not line.product_uom_id or not line.product_uom_qty: @@ -26,7 +26,7 @@ def _compute_product_qty(self): ) def unlink(self): - self.filtered('is_delivery').order_id.filtered('carrier_id').carrier_id = False + self.filtered("is_delivery").order_id.filtered("carrier_id").carrier_id = False return super().unlink() def _is_delivery(self): @@ -37,7 +37,7 @@ def _get_invalid_delivery_weight_lines(self): """Retrieve lines containing physical products with no weight defined.""" return self.filtered( lambda line: line.product_qty > 0 - and line.product_id.type not in ('service', 'combo') + and line.product_id.type not in ("service", "combo") and line.product_id.weight == 0 ) @@ -55,6 +55,6 @@ def _check_line_unlink(self): return undeletable_lines.filtered(lambda line: not line.is_delivery) def _compute_pricelist_item_id(self): - delivery_lines = self.filtered('is_delivery') + delivery_lines = self.filtered("is_delivery") super(SaleOrderLine, self - delivery_lines)._compute_pricelist_item_id() delivery_lines.pricelist_item_id = False diff --git a/addons/delivery/tests/cash_on_delivery_common.py b/addons/delivery/tests/cash_on_delivery_common.py index d5efe6ab08183..2106a151fa158 100644 --- a/addons/delivery/tests/cash_on_delivery_common.py +++ b/addons/delivery/tests/cash_on_delivery_common.py @@ -8,8 +8,8 @@ class CashOnDeliveryCommon(PaymentCustomCommon, DeliveryCommon): @classmethod def setUpClass(cls): super().setUpClass() - cls.sale_order = cls.env['sale.order'].create({ - 'partner_id': cls.partner.id, - 'state': 'draft', + cls.sale_order = cls.env["sale.order"].create({ + "partner_id": cls.partner.id, + "state": "draft", }) - cls.cod_provider = cls._prepare_provider(code='custom', custom_mode='cash_on_delivery') + cls.cod_provider = cls._prepare_provider(code="custom", custom_mode="cash_on_delivery") diff --git a/addons/delivery/tests/common.py b/addons/delivery/tests/common.py index f11a6eee7478e..c2e98575d120d 100644 --- a/addons/delivery/tests/common.py +++ b/addons/delivery/tests/common.py @@ -8,8 +8,8 @@ class DeliveryCommon(TransactionCase): def setUpClass(cls): super().setUpClass() - cls.env['delivery.carrier'].search([]).action_archive() - cls.delivery_categ = cls.env.ref('delivery.product_category_deliveries') + cls.env["delivery.carrier"].search([]).action_archive() + cls.delivery_categ = cls.env.ref("delivery.product_category_deliveries") product = cls._prepare_carrier_product() cls.free_delivery = cls._prepare_carrier(product, fixed_price=0.0) @@ -18,22 +18,22 @@ def setUpClass(cls): @classmethod def _prepare_carrier_product(cls, **values): default_values = { - 'name': "Carrier Product", - 'type': 'service', - 'categ_id': cls.delivery_categ.id, - 'sale_ok': False, - 'purchase_ok': False, - 'invoice_policy': 'order', - 'list_price': 5.0, + "name": "Carrier Product", + "type": "service", + "categ_id": cls.delivery_categ.id, + "sale_ok": False, + "purchase_ok": False, + "invoice_policy": "order", + "list_price": 5.0, } - return cls.env['product.product'].create(dict(default_values, **values)) + return cls.env["product.product"].create(dict(default_values, **values)) @classmethod def _prepare_carrier(cls, product, **values): default_values = { - 'name': "Test Carrier", - 'fixed_price': 5.0, - 'delivery_type': 'fixed', - 'product_id': product.id, + "name": "Test Carrier", + "fixed_price": 5.0, + "delivery_type": "fixed", + "product_id": product.id, } - return cls.env['delivery.carrier'].create(dict(default_values, **values)) + return cls.env["delivery.carrier"].create(dict(default_values, **values)) diff --git a/addons/delivery/tests/test_delivery_availability.py b/addons/delivery/tests/test_delivery_availability.py index 3dff19a9259fe..ad53aa13987f9 100644 --- a/addons/delivery/tests/test_delivery_availability.py +++ b/addons/delivery/tests/test_delivery_availability.py @@ -7,14 +7,14 @@ from odoo.addons.sale.tests.common import SaleCommon -@tagged('post_install', '-at_install') +@tagged("post_install", "-at_install") class TestDeliveryAvailability(DeliveryCommon, SaleCommon): @classmethod def setUpClass(cls): super().setUpClass() - cls.must_have_tag = cls.env['product.tag'].create({'name': 'Must Have'}) - cls.exclude_tag = cls.env['product.tag'].create({'name': 'Exclude'}) + cls.must_have_tag = cls.env["product.tag"].create({"name": "Must Have"}) + cls.exclude_tag = cls.env["product.tag"].create({"name": "Exclude"}) cls.non_restricted_carrier = cls._prepare_carrier(cls.carrier.product_id) @@ -24,14 +24,14 @@ def setUpClass(cls): cls.product_line.product_uom_qty = 1.0 def test_00_order_with_heavy_product_simple(self): - self.carrier.write({'max_weight': 10.0}) + self.carrier.write({"max_weight": 10.0}) - self.product.write({'weight': 11.0}) + self.product.write({"weight": 11.0}) delivery_wizard = Form( - self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_order.id, - 'default_carrier_id': self.non_restricted_carrier.id, + self.env["choose.delivery.carrier"].with_context({ + "default_order_id": self.sale_order.id, + "default_carrier_id": self.non_restricted_carrier.id, }) ) choose_delivery_carrier = delivery_wizard.save() @@ -41,16 +41,16 @@ def test_00_order_with_heavy_product_simple(self): ) def test_01_order_with_heavy_product_different_uom(self): - self.carrier.write({'max_weight': 10.0}) + self.carrier.write({"max_weight": 10.0}) - self.product.write({'weight': 1.0}) + self.product.write({"weight": 1.0}) - self.product_line.write({'product_uom_id': self.uom_dozen.id}) + self.product_line.write({"product_uom_id": self.uom_dozen.id}) delivery_wizard = Form( - self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_order.id, - 'default_carrier_id': self.non_restricted_carrier.id, + self.env["choose.delivery.carrier"].with_context({ + "default_order_id": self.sale_order.id, + "default_carrier_id": self.non_restricted_carrier.id, }) ) choose_delivery_carrier = delivery_wizard.save() @@ -60,14 +60,14 @@ def test_01_order_with_heavy_product_different_uom(self): ) def test_02_order_with_big_product_simple(self): - self.carrier.write({'max_volume': 10.0}) + self.carrier.write({"max_volume": 10.0}) - self.product.write({'volume': 11.0}) + self.product.write({"volume": 11.0}) delivery_wizard = Form( - self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_order.id, - 'default_carrier_id': self.non_restricted_carrier.id, + self.env["choose.delivery.carrier"].with_context({ + "default_order_id": self.sale_order.id, + "default_carrier_id": self.non_restricted_carrier.id, }) ) choose_delivery_carrier = delivery_wizard.save() @@ -77,16 +77,16 @@ def test_02_order_with_big_product_simple(self): ) def test_03_order_with_big_product_different_uom(self): - self.carrier.write({'max_volume': 10.0}) + self.carrier.write({"max_volume": 10.0}) - self.product.write({'volume': 1.0}) + self.product.write({"volume": 1.0}) - self.product_line.write({'product_uom_id': self.uom_dozen.id}) + self.product_line.write({"product_uom_id": self.uom_dozen.id}) delivery_wizard = Form( - self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_order.id, - 'default_carrier_id': self.non_restricted_carrier.id, + self.env["choose.delivery.carrier"].with_context({ + "default_order_id": self.sale_order.id, + "default_carrier_id": self.non_restricted_carrier.id, }) ) choose_delivery_carrier = delivery_wizard.save() @@ -98,13 +98,13 @@ def test_03_order_with_big_product_different_uom(self): def test_04_check_must_have_tag(self): self.carrier.must_have_tag_ids = [ Command.link(self.must_have_tag.id), - Command.link(self.must_have_tag.copy({'name': "Alt Must Have"}).id), + Command.link(self.must_have_tag.copy({"name": "Alt Must Have"}).id), ] delivery_wizard = Form( - self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_order.id, - 'default_carrier_id': self.non_restricted_carrier.id, + self.env["choose.delivery.carrier"].with_context({ + "default_order_id": self.sale_order.id, + "default_carrier_id": self.non_restricted_carrier.id, }) ) choose_delivery_carrier = delivery_wizard.save() @@ -113,11 +113,11 @@ def test_04_check_must_have_tag(self): "Delivery method's must have tag is not set on any product in the order", ) - self.product.write({'product_tag_ids': [self.must_have_tag.id]}) + self.product.write({"product_tag_ids": [self.must_have_tag.id]}) delivery_wizard = Form( - self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_order.id, - 'default_carrier_id': self.non_restricted_carrier.id, + self.env["choose.delivery.carrier"].with_context({ + "default_order_id": self.sale_order.id, + "default_carrier_id": self.non_restricted_carrier.id, }) ) choose_delivery_carrier = delivery_wizard.save() @@ -129,12 +129,12 @@ def test_04_check_must_have_tag(self): ) def test_05_check_excluded_tag(self): - self.carrier.write({'excluded_tag_ids': [self.exclude_tag.id]}) + self.carrier.write({"excluded_tag_ids": [self.exclude_tag.id]}) delivery_wizard = Form( - self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_order.id, - 'default_carrier_id': self.non_restricted_carrier.id, + self.env["choose.delivery.carrier"].with_context({ + "default_order_id": self.sale_order.id, + "default_carrier_id": self.non_restricted_carrier.id, }) ) choose_delivery_carrier = delivery_wizard.save() @@ -143,11 +143,11 @@ def test_05_check_excluded_tag(self): "Delivery method's excluded tag is not set on any product in the order", ) - self.product.write({'product_tag_ids': [self.exclude_tag.id]}) + self.product.write({"product_tag_ids": [self.exclude_tag.id]}) delivery_wizard = Form( - self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_order.id, - 'default_carrier_id': self.non_restricted_carrier.id, + self.env["choose.delivery.carrier"].with_context({ + "default_order_id": self.sale_order.id, + "default_carrier_id": self.non_restricted_carrier.id, }) ) choose_delivery_carrier = delivery_wizard.save() @@ -158,14 +158,14 @@ def test_05_check_excluded_tag(self): def test_06_check_tags_complex(self): self.carrier.write({ - 'must_have_tag_ids': [self.must_have_tag.id], - 'excluded_tag_ids': [self.exclude_tag.id], + "must_have_tag_ids": [self.must_have_tag.id], + "excluded_tag_ids": [self.exclude_tag.id], }) delivery_wizard = Form( - self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_order.id, - 'default_carrier_id': self.non_restricted_carrier.id, + self.env["choose.delivery.carrier"].with_context({ + "default_order_id": self.sale_order.id, + "default_carrier_id": self.non_restricted_carrier.id, }) ) choose_delivery_carrier = delivery_wizard.save() @@ -174,11 +174,11 @@ def test_06_check_tags_complex(self): "Delivery method's must have tag is not set on any product in the order", ) - self.product.write({'product_tag_ids': [self.must_have_tag.id]}) + self.product.write({"product_tag_ids": [self.must_have_tag.id]}) delivery_wizard = Form( - self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_order.id, - 'default_carrier_id': self.non_restricted_carrier.id, + self.env["choose.delivery.carrier"].with_context({ + "default_order_id": self.sale_order.id, + "default_carrier_id": self.non_restricted_carrier.id, }) ) choose_delivery_carrier = delivery_wizard.save() @@ -187,11 +187,11 @@ def test_06_check_tags_complex(self): "Delivery method's must have tag is set on one product in the order", ) - self.product.write({'product_tag_ids': [self.exclude_tag.id, self.must_have_tag.id]}) + self.product.write({"product_tag_ids": [self.exclude_tag.id, self.must_have_tag.id]}) delivery_wizard = Form( - self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_order.id, - 'default_carrier_id': self.non_restricted_carrier.id, + self.env["choose.delivery.carrier"].with_context({ + "default_order_id": self.sale_order.id, + "default_carrier_id": self.non_restricted_carrier.id, }) ) choose_delivery_carrier = delivery_wizard.save() @@ -200,12 +200,12 @@ def test_06_check_tags_complex(self): "Delivery method's excluded tag is set on one product in the order", ) - self.product.write({'product_tag_ids': [self.must_have_tag.id]}) - self.service_product.write({'product_tag_ids': [self.exclude_tag.id]}) + self.product.write({"product_tag_ids": [self.must_have_tag.id]}) + self.service_product.write({"product_tag_ids": [self.exclude_tag.id]}) delivery_wizard = Form( - self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_order.id, - 'default_carrier_id': self.non_restricted_carrier.id, + self.env["choose.delivery.carrier"].with_context({ + "default_order_id": self.sale_order.id, + "default_carrier_id": self.non_restricted_carrier.id, }) ) choose_delivery_carrier = delivery_wizard.save() diff --git a/addons/delivery/tests/test_delivery_cost.py b/addons/delivery/tests/test_delivery_cost.py index d072532fb9cec..db3e5e7c87d5b 100644 --- a/addons/delivery/tests/test_delivery_cost.py +++ b/addons/delivery/tests/test_delivery_cost.py @@ -10,7 +10,7 @@ from odoo.addons.sale.tests.common import SaleCommon -@tagged('post_install', '-at_install') +@tagged("post_install", "-at_install") class TestDeliveryCost(DeliveryCommon, SaleCommon): @classmethod def setUpClass(cls): @@ -19,58 +19,58 @@ def setUpClass(cls): cls._enable_uom() # the tests hereunder assume all the prices in USD - cls.env.company.country_id = cls.env.ref('base.us').id + cls.env.company.country_id = cls.env.ref("base.us").id cls.product.weight = 1.0 cls.product_delivery_normal = cls._prepare_carrier_product( - name='Normal Delivery Charges', list_price=10.0 + name="Normal Delivery Charges", list_price=10.0 ) cls.normal_delivery = cls._prepare_carrier( product=cls.product_delivery_normal, - name='Normal Delivery Charges', - delivery_type='fixed', + name="Normal Delivery Charges", + delivery_type="fixed", fixed_price=10.0, ) - cls.partner_4 = cls.env['res.partner'].create({ - 'name': 'Another Customer', - 'child_ids': [Command.create({'name': "Another Customer's Address"})], + cls.partner_4 = cls.env["res.partner"].create({ + "name": "Another Customer", + "child_ids": [Command.create({"name": "Another Customer's Address"})], }) cls.partner_address_13 = cls.partner_4.child_ids - cls.product_uom_hour = cls.env.ref('uom.product_uom_hour') + cls.product_uom_hour = cls.env.ref("uom.product_uom_hour") def test_00_delivery_cost(self): # In order to test Carrier Cost # Create sales order with Normal Delivery Charges - self.sale_normal_delivery_charges = self.env['sale.order'].create({ - 'partner_id': self.partner.id, - 'partner_invoice_id': self.partner.id, - 'partner_shipping_id': self.partner.id, - 'order_line': [Command.create({'product_id': self.product.id, 'price_unit': 750.00})], + self.sale_normal_delivery_charges = self.env["sale.order"].create({ + "partner_id": self.partner.id, + "partner_invoice_id": self.partner.id, + "partner_shipping_id": self.partner.id, + "order_line": [Command.create({"product_id": self.product.id, "price_unit": 750.00})], }) # I add delivery cost in Sales order - self.a_sale = self.env['account.account'].create({ - 'code': 'X2020', - 'name': 'Product Sales - (test)', - 'account_type': 'income', - 'tag_ids': [Command.set(self.env.ref('account.account_tag_operating').ids)], + self.a_sale = self.env["account.account"].create({ + "code": "X2020", + "name": "Product Sales - (test)", + "account_type": "income", + "tag_ids": [Command.set(self.env.ref("account.account_tag_operating").ids)], }) - self.product_consultant = self.env['product.product'].create({ - 'sale_ok': True, - 'list_price': 75.0, - 'standard_price': 30.0, - 'uom_id': self.product_uom_hour.id, - 'name': 'Service', - 'type': 'service', + self.product_consultant = self.env["product.product"].create({ + "sale_ok": True, + "list_price": 75.0, + "standard_price": 30.0, + "uom_id": self.product_uom_hour.id, + "name": "Service", + "type": "service", }) # I add delivery cost in Sales order delivery_wizard = Form( - self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.sale_normal_delivery_charges.id, - 'default_carrier_id': self.normal_delivery.id, + self.env["choose.delivery.carrier"].with_context({ + "default_order_id": self.sale_normal_delivery_charges.id, + "default_carrier_id": self.normal_delivery.id, }) ) choose_delivery_carrier = delivery_wizard.save() @@ -79,7 +79,7 @@ def test_00_delivery_cost(self): # I check sales order after added delivery cost line = self.sale_normal_delivery_charges.order_line.filtered_domain([ - ('product_id', '=', self.normal_delivery.product_id.id) + ("product_id", "=", self.normal_delivery.product_id.id) ]) self.assertEqual(len(line), 1, "Delivery cost is not Added") @@ -87,7 +87,7 @@ def test_00_delivery_cost(self): str(delivery_wizard.display_price) + " " + str(delivery_wizard.delivery_price) - + ' ' + + " " + line.company_id.country_id.code + line.company_id.name ) @@ -102,29 +102,29 @@ def test_00_delivery_cost(self): self.sale_normal_delivery_charges.action_confirm() # Create one more sales order with Free Delivery Charges - self.delivery_sale_order_cost = self.env['sale.order'].create({ - 'partner_id': self.partner_4.id, - 'partner_invoice_id': self.partner_address_13.id, - 'partner_shipping_id': self.partner_address_13.id, - 'order_line': [ + self.delivery_sale_order_cost = self.env["sale.order"].create({ + "partner_id": self.partner_4.id, + "partner_invoice_id": self.partner_address_13.id, + "partner_shipping_id": self.partner_address_13.id, + "order_line": [ Command.create({ - 'product_id': self.product_consultant.id, - 'product_uom_qty': 24, - 'price_unit': 75.00, + "product_id": self.product_consultant.id, + "product_uom_qty": 24, + "price_unit": 75.00, }), Command.create({ - 'product_id': self.product.id, - 'product_uom_qty': 30, - 'price_unit': 38.25, + "product_id": self.product.id, + "product_uom_qty": 30, + "price_unit": 38.25, }), ], }) # I add free delivery cost in Sales order delivery_wizard = Form( - self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': self.delivery_sale_order_cost.id, - 'default_carrier_id': self.free_delivery.id, + self.env["choose.delivery.carrier"].with_context({ + "default_order_id": self.delivery_sale_order_cost.id, + "default_carrier_id": self.free_delivery.id, }) ) choose_delivery_carrier = delivery_wizard.save() @@ -132,7 +132,7 @@ def test_00_delivery_cost(self): # I check sales order after adding delivery cost line = self.delivery_sale_order_cost.order_line.filtered_domain([ - ('product_id', '=', self.free_delivery.product_id.id) + ("product_id", "=", self.free_delivery.product_id.id) ]) self.assertEqual(len(line), 1, "Delivery cost is not Added") @@ -143,42 +143,42 @@ def test_00_delivery_cost(self): ) # I set default delivery policy - self.env['res.config.settings'].create({}).execute() + self.env["res.config.settings"].create({}).execute() def test_01_delivery_cost_from_pricelist(self): """This test aims to validate the use of a pricelist to compute the delivery cost in the case the associated product of the delivery method is defined in the pricelist.""" # Create pricelist with a custom price for the standard delivery method - my_pricelist = self.env['product.pricelist'].create({ - 'name': 'shipping_cost_change', - 'item_ids': [ + my_pricelist = self.env["product.pricelist"].create({ + "name": "shipping_cost_change", + "item_ids": [ Command.create({ - 'compute_price': 'fixed', - 'fixed_price': 5, - 'applied_on': '0_product_variant', - 'product_id': self.normal_delivery.product_id.id, + "compute_price": "fixed", + "fixed_price": 5, + "applied_on": "0_product_variant", + "product_id": self.normal_delivery.product_id.id, }) ], }) # Create sales order with Normal Delivery Charges - sale_pricelist_based_delivery_charges = self.env['sale.order'].create({ - 'partner_id': self.partner.id, - 'pricelist_id': my_pricelist.id, - 'order_line': [ + sale_pricelist_based_delivery_charges = self.env["sale.order"].create({ + "partner_id": self.partner.id, + "pricelist_id": my_pricelist.id, + "order_line": [ Command.create({ - 'product_id': self.product.id, - 'product_uom_qty': 1, - 'price_unit': 750.00, + "product_id": self.product.id, + "product_uom_qty": 1, + "price_unit": 750.00, }) ], }) # Add of delivery cost in Sales order delivery_wizard = Form( - self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': sale_pricelist_based_delivery_charges.id, - 'default_carrier_id': self.normal_delivery.id, + self.env["choose.delivery.carrier"].with_context({ + "default_order_id": sale_pricelist_based_delivery_charges.id, + "default_carrier_id": self.normal_delivery.id, }) ) self.assertEqual( @@ -189,7 +189,7 @@ def test_01_delivery_cost_from_pricelist(self): delivery_wizard.save().button_confirm() line = sale_pricelist_based_delivery_charges.order_line.filtered_domain([ - ('product_id', '=', self.normal_delivery.product_id.id) + ("product_id", "=", self.normal_delivery.product_id.id) ]) self.assertEqual(len(line), 1, "Delivery cost hasn't been added to SO") self.assertEqual(line.price_subtotal, 5.0, "Delivery cost does not correspond to 5.0") @@ -199,37 +199,37 @@ def test_02_delivery_cost_from_different_currency(self): the delivery cost in the case the associated product of the delivery method is defined in the pricelist.""" # Create pricelist with a custom price for the standard delivery method - my_pricelist = self.env['product.pricelist'].create({ - 'name': 'shipping_cost_change', - 'item_ids': [ + my_pricelist = self.env["product.pricelist"].create({ + "name": "shipping_cost_change", + "item_ids": [ Command.create({ - 'compute_price': 'fixed', - 'fixed_price': 5, - 'applied_on': '0_product_variant', - 'product_id': self.normal_delivery.product_id.id, + "compute_price": "fixed", + "fixed_price": 5, + "applied_on": "0_product_variant", + "product_id": self.normal_delivery.product_id.id, }) ], - 'currency_id': self.env.ref('base.EUR').id, + "currency_id": self.env.ref("base.EUR").id, }) # Create sales order with Normal Delivery Charges - sale_pricelist_based_delivery_charges = self.env['sale.order'].create({ - 'partner_id': self.partner.id, - 'pricelist_id': my_pricelist.id, - 'order_line': [ + sale_pricelist_based_delivery_charges = self.env["sale.order"].create({ + "partner_id": self.partner.id, + "pricelist_id": my_pricelist.id, + "order_line": [ Command.create({ - 'product_id': self.product.id, - 'product_uom_qty': 1, - 'price_unit': 750.00, + "product_id": self.product.id, + "product_uom_qty": 1, + "price_unit": 750.00, }) ], }) # Add of delivery cost in Sales order delivery_wizard = Form( - self.env['choose.delivery.carrier'].with_context({ - 'default_order_id': sale_pricelist_based_delivery_charges.id, - 'default_carrier_id': self.normal_delivery.id, + self.env["choose.delivery.carrier"].with_context({ + "default_order_id": sale_pricelist_based_delivery_charges.id, + "default_carrier_id": self.normal_delivery.id, }) ) self.assertEqual( @@ -240,7 +240,7 @@ def test_02_delivery_cost_from_different_currency(self): delivery_wizard.save().button_confirm() line = sale_pricelist_based_delivery_charges.order_line.filtered_domain([ - ('product_id', '=', self.normal_delivery.product_id.id) + ("product_id", "=", self.normal_delivery.product_id.id) ]) self.assertEqual(len(line), 1, "Delivery cost hasn't been added to SO") self.assertEqual(line.price_subtotal, 5.0, "Delivery cost does not correspond to 5.0") @@ -248,26 +248,26 @@ def test_02_delivery_cost_from_different_currency(self): def test_01_taxes_on_delivery_cost(self): # Creating taxes and fiscal position - self.env.ref('base.group_user').write({ - 'implied_ids': [(4, self.env.ref('product.group_product_pricelist').id)] + self.env.ref("base.group_user").write({ + "implied_ids": [(4, self.env.ref("product.group_product_pricelist").id)] }) - fiscal_position = self.env['account.fiscal.position'].create({'name': 'fiscal_pos_a'}) - tax_price_include, tax_price_exclude = self.env['account.tax'].create([ + fiscal_position = self.env["account.fiscal.position"].create({"name": "fiscal_pos_a"}) + tax_price_include, tax_price_exclude = self.env["account.tax"].create([ { - 'name': '10% inc', - 'type_tax_use': 'sale', - 'amount_type': 'percent', - 'amount': 10, - 'price_include_override': 'tax_included', - 'include_base_amount': True, + "name": "10% inc", + "type_tax_use": "sale", + "amount_type": "percent", + "amount": 10, + "price_include_override": "tax_included", + "include_base_amount": True, }, { - 'name': '15% exc', - 'type_tax_use': 'sale', - 'amount_type': 'percent', - 'amount': 15, - 'fiscal_position_ids': [Command.link(fiscal_position.id)], + "name": "15% exc", + "type_tax_use": "sale", + "amount_type": "percent", + "amount": 15, + "fiscal_position_ids": [Command.link(fiscal_position.id)], }, ]) tax_price_exclude.original_tax_ids = tax_price_include @@ -277,8 +277,8 @@ def test_01_taxes_on_delivery_cost(self): # Create sales order # Required to see `pricelist_id` in the view - self.env.user.group_ids += self.env.ref('product.group_product_pricelist') - order_form = Form(self.env['sale.order'].with_context(tracking_disable=True)) + self.env.user.group_ids += self.env.ref("product.group_product_pricelist") + order_form = Form(self.env["sale.order"].with_context(tracking_disable=True)) order_form.partner_id = self.partner order_form.fiscal_position_id = fiscal_position @@ -289,13 +289,13 @@ def test_01_taxes_on_delivery_cost(self): sale_order = order_form.save() self.assertRecordValues( - sale_order.order_line, [{'price_subtotal': 9.09, 'price_total': 10.45}] + sale_order.order_line, [{"price_subtotal": 9.09, "price_total": 10.45}] ) # Now trying to add the delivery line using the delivery wizard, the results should be the # same as before delivery_wizard = Form( - self.env['choose.delivery.carrier'].with_context( + self.env["choose.delivery.carrier"].with_context( default_order_id=sale_order.id, default_carrier_id=self.normal_delivery.id ) ) @@ -303,22 +303,22 @@ def test_01_taxes_on_delivery_cost(self): choose_delivery_carrier.button_confirm() line = sale_order.order_line.filtered_domain([ - ('product_id', '=', self.normal_delivery.product_id.id), - ('is_delivery', '=', True), + ("product_id", "=", self.normal_delivery.product_id.id), + ("is_delivery", "=", True), ]) - self.assertRecordValues(line, [{'price_subtotal': 9.09, 'price_total': 10.45}]) + self.assertRecordValues(line, [{"price_subtotal": 9.09, "price_total": 10.45}]) def test_estimated_weight(self): """ Test that negative qty SO lines are not included in the estimated weight calculation of delivery method (since it's used when calculating their rates). """ - sale_order = self.env['sale.order'].create({ - 'partner_id': self.partner.id, - 'order_line': [ - Command.create({'product_id': self.product.id, 'product_uom_qty': 1}), - Command.create({'product_id': self.product.id, 'product_uom_qty': -1}), + sale_order = self.env["sale.order"].create({ + "partner_id": self.partner.id, + "order_line": [ + Command.create({"product_id": self.product.id, "product_uom_qty": 1}), + Command.create({"product_id": self.product.id, "product_uom_qty": -1}), ], }) shipping_weight = sale_order._get_estimated_weight() @@ -332,34 +332,34 @@ def test_get_invalid_delivery_weight_lines(self): """Ensure we can retrieve lines that contain physical products without a weight value.""" order = self.empty_order weightless_product = self._create_product(weight=0.0, list_price=50.0) - combos = self.env['product.combo'].create([ + combos = self.env["product.combo"].create([ { - 'name': "Combo A", - 'combo_item_ids': [Command.create({'product_id': self.product.id})], + "name": "Combo A", + "combo_item_ids": [Command.create({"product_id": self.product.id})], }, { - 'name': "Combo B", - 'combo_item_ids': [Command.create({'product_id': weightless_product.id})], + "name": "Combo B", + "combo_item_ids": [Command.create({"product_id": weightless_product.id})], }, ]) - combo_product = self._create_product(type='combo', combo_ids=combos.ids) - combo_line = self.env['sale.order.line'].create({ - 'order_id': order.id, - 'product_id': combo_product.id, + combo_product = self._create_product(type="combo", combo_ids=combos.ids) + combo_line = self.env["sale.order.line"].create({ + "order_id": order.id, + "product_id": combo_product.id, }) order.order_line = [ *[ Command.create({ - 'product_id': product.id, - 'combo_item_id': combo.combo_item_ids.id, - 'linked_line_id': combo_line.id, + "product_id": product.id, + "combo_item_id": combo.combo_item_ids.id, + "linked_line_id": combo_line.id, }) for product, combo in zip(self.product + weightless_product, combos) ], - Command.create({'product_id': weightless_product.id, 'product_uom_qty': 0}), - Command.create({'product_id': self.service_product.id}), - Command.create({'display_type': 'line_section', 'name': "Misc."}), - Command.create({'is_downpayment': True, 'price_unit': 5.0}), + Command.create({"product_id": weightless_product.id, "product_uom_qty": 0}), + Command.create({"product_id": self.service_product.id}), + Command.create({"display_type": "line_section", "name": "Misc."}), + Command.create({"is_downpayment": True, "price_unit": 5.0}), ] error_lines = order.order_line._get_invalid_delivery_weight_lines() self.assertIn( @@ -372,22 +372,22 @@ def test_get_invalid_delivery_weight_lines(self): def test_fixed_price_margins(self): """Margins should be ignored for fixed price carriers.""" - sale_order = self.env['sale.order'].create({ - 'partner_id': self.partner.id, - 'name': 'SO - fixed del', - 'order_line': [(0, 0, {'product_id': self.product.id, 'product_uom_qty': 1})], + sale_order = self.env["sale.order"].create({ + "partner_id": self.partner.id, + "name": "SO - fixed del", + "order_line": [(0, 0, {"product_id": self.product.id, "product_uom_qty": 1})], }) self.normal_delivery.fixed_margin = 100 self.normal_delivery.margin = 4.2 delivery_wizard = Form( - self.env['choose.delivery.carrier'].with_context( + self.env["choose.delivery.carrier"].with_context( default_order_id=sale_order.id, default_carrier_id=self.normal_delivery.id ) ) choose_delivery_carrier = delivery_wizard.save() choose_delivery_carrier.button_confirm() - line = sale_order.order_line.filtered('is_delivery') + line = sale_order.order_line.filtered("is_delivery") self.assertEqual(line.price_unit, self.normal_delivery.fixed_price) def test_price_with_weight_volume_variable(self): @@ -396,28 +396,28 @@ def test_price_with_weight_volume_variable(self): list_price = 2 volume = 2.5 weight = 1.5 - sale_order = self.env['sale.order'].create({ - 'partner_id': self.partner_4.id, - 'order_line': [ + sale_order = self.env["sale.order"].create({ + "partner_id": self.partner_4.id, + "order_line": [ Command.create({ - 'product_id': self.env['product.product'] - .create({'name': 'wv', 'weight': weight, 'volume': volume}) + "product_id": self.env["product.product"] + .create({"name": "wv", "weight": weight, "volume": volume}) .id, - 'product_uom_qty': qty, + "product_uom_qty": qty, }) ], }) - delivery = self.env['delivery.carrier'].create({ - 'name': 'Delivery Charges', - 'delivery_type': 'base_on_rule', - 'product_id': self.product_delivery_normal.id, - 'price_rule_ids': [ + delivery = self.env["delivery.carrier"].create({ + "name": "Delivery Charges", + "delivery_type": "base_on_rule", + "product_id": self.product_delivery_normal.id, + "price_rule_ids": [ Command.create({ - 'variable': 'price', - 'operator': '>=', - 'max_value': 0, - 'list_price': list_price, - 'variable_factor': 'wv', + "variable": "price", + "operator": ">=", + "max_value": 0, + "list_price": list_price, + "variable_factor": "wv", }) ], }) @@ -432,71 +432,71 @@ def test_delivery_product_taxes_on_branch(self): Taxes from the branch company should be taken with a fallback on parent company. """ company = self.env.company - branch = self.env['res.company'].create({ - 'name': 'Branch', - 'country_id': company.country_id.id, - 'parent_id': company.id, + branch = self.env["res.company"].create({ + "name": "Branch", + "country_id": company.country_id.id, + "parent_id": company.id, }) # create taxes for the parent company and its branch - tax_groups = self.env['account.tax.group'].create([ - {'name': 'Tax Group A', 'company_id': company.id}, - {'name': 'Tax Group B', 'company_id': branch.id}, + tax_groups = self.env["account.tax.group"].create([ + {"name": "Tax Group A", "company_id": company.id}, + {"name": "Tax Group B", "company_id": branch.id}, ]) - tax_a = self.env['account.tax'].create({ - 'name': 'Tax A', - 'type_tax_use': 'sale', - 'amount_type': 'percent', - 'amount': 10, - 'tax_group_id': tax_groups[0].id, - 'company_id': company.id, + tax_a = self.env["account.tax"].create({ + "name": "Tax A", + "type_tax_use": "sale", + "amount_type": "percent", + "amount": 10, + "tax_group_id": tax_groups[0].id, + "company_id": company.id, }) - tax_b = self.env['account.tax'].create({ - 'name': 'Tax B', - 'type_tax_use': 'sale', - 'amount_type': 'percent', - 'amount': 20, - 'tax_group_id': tax_groups[1].id, - 'company_id': branch.id, + tax_b = self.env["account.tax"].create({ + "name": "Tax B", + "type_tax_use": "sale", + "amount_type": "percent", + "amount": 20, + "tax_group_id": tax_groups[1].id, + "company_id": branch.id, }) # create delivery product with taxes from both branch and parent company - delivery_product = self.env['product.product'].create({ - 'name': 'Delivery Product', - 'taxes_id': [Command.set((tax_a + tax_b).ids)], + delivery_product = self.env["product.product"].create({ + "name": "Delivery Product", + "taxes_id": [Command.set((tax_a + tax_b).ids)], }) # create delivery - delivery = self.env['delivery.carrier'].create({ - 'name': 'Delivery Charges', - 'delivery_type': 'fixed', - 'product_id': delivery_product.id, - 'company_id': branch.id, + delivery = self.env["delivery.carrier"].create({ + "name": "Delivery Charges", + "delivery_type": "fixed", + "product_id": delivery_product.id, + "company_id": branch.id, }) # create a SO from Branch - sale_order = self.env['sale.order'].create({ - 'partner_id': self.partner_4.id, - 'company_id': branch.id, - 'order_line': [Command.create({'product_id': self.product.id, 'product_uom_qty': 1})], + sale_order = self.env["sale.order"].create({ + "partner_id": self.partner_4.id, + "company_id": branch.id, + "order_line": [Command.create({"product_id": self.product.id, "product_uom_qty": 1})], }) # add delivery - wizard = self.env['choose.delivery.carrier'].create({ - 'order_id': sale_order.id, - 'carrier_id': delivery.id, - 'company_id': branch.id, + wizard = self.env["choose.delivery.carrier"].create({ + "order_id": sale_order.id, + "carrier_id": delivery.id, + "company_id": branch.id, }) wizard.button_confirm() delivery_line = sale_order.order_line.filtered(lambda line: line.is_delivery) # delivery line should have taxes from the branch company self.assertRecordValues( - delivery_line, [{'product_id': delivery_product.id, 'tax_ids': tax_b.ids}] + delivery_line, [{"product_id": delivery_product.id, "tax_ids": tax_b.ids}] ) # update delivery product by setting only the tax from parent company - delivery_product.write({'taxes_id': [Command.set((tax_a).ids)]}) + delivery_product.write({"taxes_id": [Command.set((tax_a).ids)]}) # update delivery - wizard = self.env['choose.delivery.carrier'].create({ - 'order_id': sale_order.id, - 'carrier_id': delivery.id, - 'company_id': branch.id, + wizard = self.env["choose.delivery.carrier"].create({ + "order_id": sale_order.id, + "carrier_id": delivery.id, + "company_id": branch.id, }) wizard.button_confirm() delivery_line = sale_order.order_line.filtered(lambda line: line.is_delivery) @@ -504,48 +504,48 @@ def test_delivery_product_taxes_on_branch(self): # delivery line should have taxes from the parent company as there is no tax from the branch # company self.assertRecordValues( - delivery_line, [{'product_id': delivery_product.id, 'tax_ids': tax_a.ids}] + delivery_line, [{"product_id": delivery_product.id, "tax_ids": tax_a.ids}] ) def test_update_weight_in_shipping_when_change_quantity(self): - product_test = self.env['product.product'].create({'name': 'Test product', 'weight': 1}) - sale_order = self.env['sale.order'].create({ - 'partner_id': self.partner.id, - 'order_line': [Command.create({'product_id': product_test.id, 'product_uom_qty': 10})], + product_test = self.env["product.product"].create({"name": "Test product", "weight": 1}) + sale_order = self.env["sale.order"].create({ + "partner_id": self.partner.id, + "order_line": [Command.create({"product_id": product_test.id, "product_uom_qty": 10})], }) - delivery = self.env['delivery.carrier'].create({ - 'name': 'Delivery Charges', - 'delivery_type': 'base_on_rule', - 'product_id': product_test.id, - 'price_rule_ids': [ + delivery = self.env["delivery.carrier"].create({ + "name": "Delivery Charges", + "delivery_type": "base_on_rule", + "product_id": product_test.id, + "price_rule_ids": [ Command.create({ - 'variable': 'weight', - 'operator': '<=', - 'max_value': 30, - 'list_base_price': 5, - 'variable_factor': 'weight', + "variable": "weight", + "operator": "<=", + "max_value": 30, + "list_base_price": 5, + "variable_factor": "weight", }), Command.create({ - 'variable': 'weight', - 'operator': '>=', - 'max_value': 60, - 'list_base_price': 10, - 'variable_factor': 'weight', + "variable": "weight", + "operator": ">=", + "max_value": 60, + "list_base_price": 10, + "variable_factor": "weight", }), ], }) del_form = sale_order.action_open_delivery_wizard() choose_delivery_carrier = ( - self.env[del_form['res_model']] - .with_context(del_form['context']) - .create({'carrier_id': delivery.id, 'order_id': sale_order.id}) + self.env[del_form["res_model"]] + .with_context(del_form["context"]) + .create({"carrier_id": delivery.id, "order_id": sale_order.id}) ) choose_delivery_carrier.button_confirm() self.assertEqual(choose_delivery_carrier.total_weight, 10) - sale_order.order_line.write({'product_uom_qty': 100}) + sale_order.order_line.write({"product_uom_qty": 100}) updated_del_form = sale_order.action_open_delivery_wizard() - self.assertEqual(updated_del_form['context']['default_total_weight'], 100) + self.assertEqual(updated_del_form["context"]["default_total_weight"], 100) def test_base_on_rule_currency_is_converted(self): """ @@ -553,75 +553,75 @@ def test_base_on_rule_currency_is_converted(self): is converted from the main's company's currency to the current company's on SOs. """ # Create a company that uses a different currency - currency_bells = self.env['res.currency'].create({'name': 'Bell', 'symbol': 'C'}) + currency_bells = self.env["res.currency"].create({"name": "Bell", "symbol": "C"}) - nook_inc = self.env['res.company'].create({ - 'name': 'Nook inc.', - 'currency_id': currency_bells.id, + nook_inc = self.env["res.company"].create({ + "name": "Nook inc.", + "currency_id": currency_bells.id, }) - with freeze_time('2000-01-01'): # Make sure the rate is in the past - self.env['res.currency.rate'].with_company(nook_inc).create({ - 'currency_id': currency_bells.id, - 'company_rate': 0.5, - 'inverse_company_rate': 2, + with freeze_time("2000-01-01"): # Make sure the rate is in the past + self.env["res.currency.rate"].with_company(nook_inc).create({ + "currency_id": currency_bells.id, + "company_rate": 0.5, + "inverse_company_rate": 2, }) # Company less delivery method product_delivery_rule = ( - self.env['product.product'] + self.env["product.product"] .with_company(nook_inc) .create({ - 'name': 'rule delivery charges', - 'type': 'service', - 'list_price': 10.0, - 'categ_id': self.env.ref('delivery.product_category_deliveries').id, + "name": "rule delivery charges", + "type": "service", + "list_price": 10.0, + "categ_id": self.env.ref("delivery.product_category_deliveries").id, }) ) delivery = ( - self.env['delivery.carrier'] + self.env["delivery.carrier"] .with_company(nook_inc) .create({ - 'name': 'Rule Delivery', - 'delivery_type': 'base_on_rule', - 'product_id': product_delivery_rule.id, - 'price_rule_ids': [ + "name": "Rule Delivery", + "delivery_type": "base_on_rule", + "product_id": product_delivery_rule.id, + "price_rule_ids": [ Command.create({ - 'variable': 'price', - 'operator': '>=', - 'max_value': 0, - 'variable_factor': 'weight', - 'list_base_price': 15, + "variable": "price", + "operator": ">=", + "max_value": 0, + "variable_factor": "weight", + "list_base_price": 15, }) ], - 'fixed_margin': 10, + "fixed_margin": 10, }) ) # Create sale using the delivery method so = ( - self.env['sale.order'] + self.env["sale.order"] .with_company(nook_inc) .create({ - 'partner_id': self.partner_4.id, - 'partner_invoice_id': self.partner_4.id, - 'partner_shipping_id': self.partner_4.id, - 'order_line': [ + "partner_id": self.partner_4.id, + "partner_invoice_id": self.partner_4.id, + "partner_shipping_id": self.partner_4.id, + "order_line": [ Command.create({ - 'name': 'PC Assamble + 2GB RAM', - 'product_id': self.product.id, - 'product_uom_qty': 1, - 'price_unit': 750.00, + "name": "PC Assamble + 2GB RAM", + "product_id": self.product.id, + "product_uom_qty": 1, + "price_unit": 750.00, }) ], }) ) delivery_wizard = Form( - self.env['choose.delivery.carrier'] + self.env["choose.delivery.carrier"] .with_company(nook_inc) - .with_context({'default_order_id': so.id, 'default_carrier_id': delivery.id}) + .with_context({"default_order_id": so.id, "default_carrier_id": delivery.id}) ) choose_delivery_carrier = delivery_wizard.save() choose_delivery_carrier.button_confirm() diff --git a/addons/delivery/tests/test_payment_provider.py b/addons/delivery/tests/test_payment_provider.py index 8e7bd42438295..34f9e340dfff3 100644 --- a/addons/delivery/tests/test_payment_provider.py +++ b/addons/delivery/tests/test_payment_provider.py @@ -5,14 +5,14 @@ from odoo.addons.delivery.tests.cash_on_delivery_common import CashOnDeliveryCommon -@tagged('post_install', '-at_install') +@tagged("post_install", "-at_install") class TestCODPaymentProvider(CashOnDeliveryCommon): def test_cod_provider_available_when_dm_cod_enabled(self): order = self.sale_order self.free_delivery.allow_cash_on_delivery = True order.carrier_id = self.free_delivery compatible_providers = ( - self.env['payment.provider'] + self.env["payment.provider"] .sudo() ._get_compatible_providers( self.company.id, self.partner.id, self.amount, sale_order_id=order.id @@ -20,7 +20,7 @@ def test_cod_provider_available_when_dm_cod_enabled(self): ) self.assertTrue( any( - p.code == 'custom' and p.custom_mode == 'cash_on_delivery' + p.code == "custom" and p.custom_mode == "cash_on_delivery" for p in compatible_providers ) ) @@ -30,7 +30,7 @@ def test_cod_provider_unavailable_when_dm_cod_disabled(self): self.free_delivery.allow_cash_on_delivery = False order.carrier_id = self.free_delivery compatible_providers = ( - self.env['payment.provider'] + self.env["payment.provider"] .sudo() ._get_compatible_providers( self.company.id, self.partner.id, self.amount, sale_order_id=order.id @@ -38,7 +38,7 @@ def test_cod_provider_unavailable_when_dm_cod_disabled(self): ) self.assertFalse( any( - p.code == 'custom' and p.custom_mode == 'cash_on_delivery' + p.code == "custom" and p.custom_mode == "cash_on_delivery" for p in compatible_providers ) ) diff --git a/addons/delivery/tests/test_payment_transaction.py b/addons/delivery/tests/test_payment_transaction.py index 7571ca194836d..ef24d8592767a 100644 --- a/addons/delivery/tests/test_payment_transaction.py +++ b/addons/delivery/tests/test_payment_transaction.py @@ -6,20 +6,20 @@ from odoo.addons.delivery.tests.cash_on_delivery_common import CashOnDeliveryCommon -@tagged('post_install', '-at_install') +@tagged("post_install", "-at_install") class TestCODPaymentTransaction(CashOnDeliveryCommon): def test_choosing_cod_payment_confirms_order(self): order = self.sale_order self.free_delivery.allow_cash_on_delivery = True order.carrier_id = self.free_delivery tx = self._create_transaction( - flow='direct', + flow="direct", sale_order_ids=[order.id], - state='pending', + state="pending", provider_id=self.cod_provider.id, payment_method_id=self.cod_provider.payment_method_ids.id, ) - with mute_logger('odoo.addons.sale.models.payment_transaction'): + with mute_logger("odoo.addons.sale.models.payment_transaction"): tx._post_process() - self.assertEqual(order.state, 'sale') + self.assertEqual(order.state, "sale") diff --git a/addons/delivery/tests/test_sale_order.py b/addons/delivery/tests/test_sale_order.py index 386a76c4d6410..4f0705dc2bef5 100644 --- a/addons/delivery/tests/test_sale_order.py +++ b/addons/delivery/tests/test_sale_order.py @@ -3,9 +3,9 @@ from odoo.addons.sale.tests.common import SaleCommon -@tagged('post_install', '-at_install') +@tagged("post_install", "-at_install") class TestSaleOrder(SaleCommon): def test_avoid_setting_pickup_location_as_default_delivery_address(self): - self._create_partner(type='delivery', parent_id=self.partner.id, is_pickup_location=True) - so = self.env['sale.order'].create({'partner_id': self.partner.id}) + self._create_partner(type="delivery", parent_id=self.partner.id, is_pickup_location=True) + so = self.env["sale.order"].create({"partner_id": self.partner.id}) self.assertFalse(so.partner_shipping_id.is_pickup_location) diff --git a/addons/delivery/wizard/choose_delivery_carrier.py b/addons/delivery/wizard/choose_delivery_carrier.py index 2e4375aef570f..b467143706326 100644 --- a/addons/delivery/wizard/choose_delivery_carrier.py +++ b/addons/delivery/wizard/choose_delivery_carrier.py @@ -5,78 +5,78 @@ class ChooseDeliveryCarrier(models.TransientModel): - _name = 'choose.delivery.carrier' + _name = "choose.delivery.carrier" _description = "Delivery Method Selection Wizard" def _get_default_weight_uom(self): - return self.env['product.template']._get_weight_uom_name_from_ir_config_parameter() + return self.env["product.template"]._get_weight_uom_name_from_ir_config_parameter() - order_id = fields.Many2one(comodel_name='sale.order', ondelete='cascade', required=True) + order_id = fields.Many2one(comodel_name="sale.order", ondelete="cascade", required=True) partner_id = fields.Many2one( - comodel_name='res.partner', related='order_id.partner_id', required=True + comodel_name="res.partner", related="order_id.partner_id", required=True ) carrier_id = fields.Many2one( string="Delivery Method", - comodel_name='delivery.carrier', + comodel_name="delivery.carrier", domain="[('id', 'in', available_carrier_ids)]", required=True, ) - delivery_type = fields.Selection(related='carrier_id.delivery_type') + delivery_type = fields.Selection(related="carrier_id.delivery_type") delivery_price = fields.Float() display_price = fields.Float(string="Cost", readonly=True) - currency_id = fields.Many2one(comodel_name='res.currency', related='order_id.currency_id') - company_id = fields.Many2one(comodel_name='res.company', related='order_id.company_id') + currency_id = fields.Many2one(comodel_name="res.currency", related="order_id.currency_id") + company_id = fields.Many2one(comodel_name="res.company", related="order_id.company_id") available_carrier_ids = fields.Many2many( string="Available Carriers", - comodel_name='delivery.carrier', - compute='_compute_available_carrier', + comodel_name="delivery.carrier", + compute="_compute_available_carrier", ) - invoicing_message = fields.Text(compute='_compute_invoicing_message') + invoicing_message = fields.Text(compute="_compute_invoicing_message") delivery_message = fields.Text(readonly=True) total_weight = fields.Float( - string="Total Order Weight", related='order_id.shipping_weight', readonly=False + string="Total Order Weight", related="order_id.shipping_weight", readonly=False ) weight_uom_name = fields.Char(default=_get_default_weight_uom, readonly=True) - @api.onchange('carrier_id', 'total_weight') + @api.onchange("carrier_id", "total_weight") def _onchange_carrier_id(self): self.delivery_message = False - if self.delivery_type in ('fixed', 'base_on_rule'): + if self.delivery_type in ("fixed", "base_on_rule"): vals = self._get_delivery_rate() - if vals.get('error_message'): - return {'error': vals['error_message']} + if vals.get("error_message"): + return {"error": vals["error_message"]} else: self.display_price = 0 self.delivery_price = 0 - @api.onchange('order_id') + @api.onchange("order_id") def _onchange_order_id(self): # Fixed and base_on_rule delivery price will compute on each carrier change so no need to # recompute here if ( self.carrier_id and self.order_id.delivery_set - and self.delivery_type not in ('fixed', 'base_on_rule') + and self.delivery_type not in ("fixed", "base_on_rule") ): vals = self._get_delivery_rate() - if vals.get('error_message'): + if vals.get("error_message"): warning = { - 'title': _("%(carrier)s Error", carrier=self.carrier_id.name), - 'message': vals['error_message'], - 'type': 'notification', + "title": _("%(carrier)s Error", carrier=self.carrier_id.name), + "message": vals["error_message"], + "type": "notification", } - return {'warning': warning} + return {"warning": warning} - @api.depends('carrier_id') + @api.depends("carrier_id") def _compute_invoicing_message(self): self.ensure_one() self.invoicing_message = "" - @api.depends('partner_id') + @api.depends("partner_id") def _compute_available_carrier(self): for rec in self: - carriers = self.env['delivery.carrier'].search( - self.env['delivery.carrier']._check_company_domain(rec.order_id.company_id) + carriers = self.env["delivery.carrier"].search( + self.env["delivery.carrier"]._check_company_domain(rec.order_id.company_id) ) rec.available_carrier_ids = ( carriers.available_carriers(rec.order_id.partner_shipping_id, rec.order_id) @@ -88,30 +88,30 @@ def _get_delivery_rate(self): vals = self.carrier_id.with_context(order_weight=self.total_weight).rate_shipment( self.order_id ) - if vals.get('success'): - self.delivery_message = vals.get('warning_message', False) - self.delivery_price = vals['price'] - self.display_price = vals['carrier_price'] - return {'no_rate': vals.get('no_rate', False)} - return {'error_message': vals['error_message']} + if vals.get("success"): + self.delivery_message = vals.get("warning_message", False) + self.delivery_price = vals["price"] + self.display_price = vals["carrier_price"] + return {"no_rate": vals.get("no_rate", False)} + return {"error_message": vals["error_message"]} def update_price(self): vals = self._get_delivery_rate() - if vals.get('error_message'): - raise UserError(vals.get('error_message')) + if vals.get("error_message"): + raise UserError(vals.get("error_message")) return { - 'name': _('Add a delivery method'), - 'type': 'ir.actions.act_window', - 'view_mode': 'form', - 'res_model': 'choose.delivery.carrier', - 'res_id': self.id, - 'target': 'new', - 'context': vals, + "name": _("Add a delivery method"), + "type": "ir.actions.act_window", + "view_mode": "form", + "res_model": "choose.delivery.carrier", + "res_id": self.id, + "target": "new", + "context": vals, } def button_confirm(self): self.order_id.set_delivery_line(self.carrier_id, self.delivery_price) self.order_id.write({ - 'recompute_delivery_price': False, - 'delivery_message': self.delivery_message, + "recompute_delivery_price": False, + "delivery_message": self.delivery_message, }) diff --git a/addons/website_sale_collect/controllers/delivery.py b/addons/website_sale_collect/controllers/delivery.py index ed14e8b2dae5e..39384856be7e0 100644 --- a/addons/website_sale_collect/controllers/delivery.py +++ b/addons/website_sale_collect/controllers/delivery.py @@ -12,18 +12,18 @@ def website_sale_get_pickup_locations(self, zip_code=None, **kwargs): order to retrieve pickup locations when called from the product page. If there is no order create a temporary one to display pickup locations. """ - if kwargs.get('product_id'): # Called from the product page. + if kwargs.get("product_id"): # Called from the product page. order_sudo = request.cart in_store_dm = request.website.sudo().in_store_dm_id if not order_sudo: # Pickup location requested without a cart creation. # Create a temporary order to fetch pickup locations. - temp_order = request.env['sale.order'].new({'carrier_id': in_store_dm.id}) + temp_order = request.env["sale.order"].new({"carrier_id": in_store_dm.id}) return temp_order.sudo()._get_pickup_locations(zip_code, **kwargs) # Skip super - if order_sudo.carrier_id.delivery_type != 'in_store': + if order_sudo.carrier_id.delivery_type != "in_store": order_sudo.set_delivery_line(in_store_dm, in_store_dm.product_id.list_price) return super().website_sale_get_pickup_locations(zip_code, **kwargs) - @route('/shop/set_click_and_collect_location', type='jsonrpc', auth='public', website=True) + @route("/shop/set_click_and_collect_location", type="jsonrpc", auth="public", website=True) def shop_set_click_and_collect_location(self, pickup_location_data): """Set the pickup location and the in-store delivery method on the current order or created one. @@ -36,7 +36,7 @@ def shop_set_click_and_collect_location(self, pickup_location_data): :return: None """ order_sudo = request.cart or request.website._create_cart() - if order_sudo.carrier_id.delivery_type != 'in_store': + if order_sudo.carrier_id.delivery_type != "in_store": in_store_dm = request.website.sudo().in_store_dm_id order_sudo.set_delivery_line(in_store_dm, in_store_dm.product_id.list_price) order_sudo._set_pickup_location(pickup_location_data) @@ -55,6 +55,6 @@ def _get_delivery_methods_express_checkout(cls, order_sudo): """Override to exclude `in_store` delivery methods from exress checkout delivery options.""" dm_rate_mapping = super()._get_delivery_methods_express_checkout(order_sudo) for dm in list(dm_rate_mapping): - if dm.delivery_type == 'in_store': + if dm.delivery_type == "in_store": del dm_rate_mapping[dm] return dm_rate_mapping diff --git a/addons/website_sale_collect/controllers/main.py b/addons/website_sale_collect/controllers/main.py index 28f6b18df6191..784272c1e8b2a 100644 --- a/addons/website_sale_collect/controllers/main.py +++ b/addons/website_sale_collect/controllers/main.py @@ -15,7 +15,7 @@ def _prepare_product_values(self, product, category, **kwargs): selected_location_data = {} single_location = len(in_store_dm_sudo.warehouse_ids) == 1 if ( - order_sudo.carrier_id.delivery_type == 'in_store' + order_sudo.carrier_id.delivery_type == "in_store" and order_sudo.pickup_location_data ): selected_location_data = order_sudo.pickup_location_data @@ -23,13 +23,13 @@ def _prepare_product_values(self, product, category, **kwargs): default_wh = in_store_dm_sudo.warehouse_ids[0] selected_location_data = default_wh._prepare_pickup_location_data() res.update({ - 'selected_location_data': selected_location_data, - 'show_select_store_button': not single_location, - 'zip_code': ( # Define the zip code. + "selected_location_data": selected_location_data, + "show_select_store_button": not single_location, + "zip_code": ( # Define the zip code. order_sudo.partner_shipping_id.zip - or selected_location_data.get('zip_code') + or selected_location_data.get("zip_code") or request.geoip.postal.code - or '' # String expected for the widget. + or "" # String expected for the widget. ), }) return res @@ -43,9 +43,9 @@ def _prepare_checkout_page_values(self, order_sudo, **query_params): return res res.update(order_sudo._prepare_in_store_default_location_data()) - if order_sudo.carrier_id.delivery_type == 'in_store' and order_sudo.pickup_location_data: - res['insufficient_stock_data'] = order_sudo._get_insufficient_stock_data( - order_sudo.pickup_location_data.get('id') + if order_sudo.carrier_id.delivery_type == "in_store" and order_sudo.pickup_location_data: + res["insufficient_stock_data"] = order_sudo._get_insufficient_stock_data( + order_sudo.pickup_location_data.get("id") ) return res @@ -53,14 +53,14 @@ def _get_shop_payment_errors(self, order): """Override of `website_sale` to includes errors if no pickup location is selected or some products are unavailable.""" errors = super()._get_shop_payment_errors(order) - if order._has_deliverable_products() and order.carrier_id.delivery_type == 'in_store': + if order._has_deliverable_products() and order.carrier_id.delivery_type == "in_store": if not order.pickup_location_data: errors.append(( _("Sorry, we are unable to ship your order."), _("Please choose a store to collect your order."), )) else: - selected_wh_id = order.pickup_location_data['id'] + selected_wh_id = order.pickup_location_data["id"] if not order._is_in_stock(selected_wh_id): errors.append(( _("Sorry, we are unable to ship your order."), diff --git a/addons/website_sale_collect/controllers/payment.py b/addons/website_sale_collect/controllers/payment.py index 46ceb66c64996..41507719dbf72 100644 --- a/addons/website_sale_collect/controllers/payment.py +++ b/addons/website_sale_collect/controllers/payment.py @@ -24,9 +24,9 @@ def _validate_transaction_for_order(self, transaction, sale_order): # This should never be triggered unless the user intentionally forges a request. provider = transaction.provider_id if ( - sale_order.carrier_id.delivery_type != 'in_store' - and provider.code == 'custom' - and provider.custom_mode == 'on_site' + sale_order.carrier_id.delivery_type != "in_store" + and provider.code == "custom" + and provider.custom_mode == "on_site" ): raise ValidationError( _("You can only pay on site when selecting the pick up in store delivery method.") diff --git a/addons/website_sale_collect/models/delivery_carrier.py b/addons/website_sale_collect/models/delivery_carrier.py index 569945b1ad6a6..9a5b2dfe093fa 100644 --- a/addons/website_sale_collect/models/delivery_carrier.py +++ b/addons/website_sale_collect/models/delivery_carrier.py @@ -9,18 +9,18 @@ class DeliveryCarrier(models.Model): - _inherit = 'delivery.carrier' + _inherit = "delivery.carrier" delivery_type = fields.Selection( - selection_add=[('in_store', "Pick up in store")], ondelete={'in_store': 'set default'} + selection_add=[("in_store", "Pick up in store")], ondelete={"in_store": "set default"} ) - warehouse_ids = fields.Many2many(string="Stores", comodel_name='stock.warehouse') + warehouse_ids = fields.Many2many(string="Stores", comodel_name="stock.warehouse") - @api.constrains('delivery_type', 'is_published', 'warehouse_ids') + @api.constrains("delivery_type", "is_published", "warehouse_ids") def _check_in_store_dm_has_warehouses_when_published(self): if any( self.filtered( - lambda dm: dm.delivery_type == 'in_store' + lambda dm: dm.delivery_type == "in_store" and dm.is_published and not dm.warehouse_ids ) @@ -29,11 +29,11 @@ def _check_in_store_dm_has_warehouses_when_published(self): _("The delivery method must have at least one warehouse to be published.") ) - @api.constrains('delivery_type', 'company_id', 'warehouse_ids') + @api.constrains("delivery_type", "company_id", "warehouse_ids") def _check_warehouses_have_same_company(self): for dm in self: if ( - dm.delivery_type == 'in_store' + dm.delivery_type == "in_store" and dm.company_id and any(wh.company_id and dm.company_id != wh.company_id for wh in dm.warehouse_ids) ): @@ -44,29 +44,29 @@ def _check_warehouses_have_same_company(self): @api.model_create_multi def create(self, vals_list): for vals in vals_list: - if vals.get('delivery_type') == 'in_store': - vals['integration_level'] = 'rate' - vals['allow_cash_on_delivery'] = False + if vals.get("delivery_type") == "in_store": + vals["integration_level"] = "rate" + vals["allow_cash_on_delivery"] = False # Set the default warehouses and publish if one is found. - if 'company_id' in vals: - company_id = vals.get('company_id') + if "company_id" in vals: + company_id = vals.get("company_id") else: company_id = ( - self.env['product.product'].browse(vals.get('product_id')).company_id.id + self.env["product.product"].browse(vals.get("product_id")).company_id.id or self.env.company.id ) - warehouses = self.env['stock.warehouse'].search([('company_id', 'in', company_id)]) + warehouses = self.env["stock.warehouse"].search([("company_id", "in", company_id)]) vals.update({ - 'warehouse_ids': [Command.set(warehouses.ids)], - 'is_published': bool(warehouses), + "warehouse_ids": [Command.set(warehouses.ids)], + "is_published": bool(warehouses), }) return super().create(vals_list) def write(self, vals): - if vals.get('delivery_type') == 'in_store': - vals['integration_level'] = 'rate' - vals['allow_cash_on_delivery'] = False + if vals.get("delivery_type") == "in_store": + vals["integration_level"] = "rate" + vals["allow_cash_on_delivery"] = False return super().write(vals) # === BUSINESS METHODS ===# @@ -84,9 +84,9 @@ def _in_store_get_close_locations(self, partner_address, product_id=None, uom_id try: product_id = product_id and int(product_id) except ValueError: - product = self.env['product.product'] + product = self.env["product.product"] else: - product = self.env['product.product'].browse(product_id) + product = self.env["product.product"].browse(product_id) partner_address.geo_localize() # Calculate coordinates. @@ -99,27 +99,27 @@ def _in_store_get_close_locations(self, partner_address, product_id=None, uom_id # Prepare the stock data based on either the product or the order. if product: # Called from the product page. - uom = self.env['uom.uom'].browse(uom_id) + uom = self.env["uom.uom"].browse(uom_id) cart_qty = order_sudo._get_cart_qty(product.id) in_store_stock_data = utils.format_product_stock_values( product, wh_id=wh.id, uom=uom, cart_qty=cart_qty ) else: # Called from the checkout page. - in_store_stock_data = {'in_stock': order_sudo._is_in_stock(wh.id)} + in_store_stock_data = {"in_stock": order_sudo._is_in_stock(wh.id)} # Calculate the distance between the partner address and the warehouse location. pickup_location_values.update({ - 'additional_data': {'in_store_stock_data': in_store_stock_data}, - 'distance': utils.calculate_partner_distance(partner_address, wh.partner_id), + "additional_data": {"in_store_stock_data": in_store_stock_data}, + "distance": utils.calculate_partner_distance(partner_address, wh.partner_id), }) pickup_locations.append(pickup_location_values) - return sorted(pickup_locations, key=lambda k: k['distance']) + return sorted(pickup_locations, key=lambda k: k["distance"]) def in_store_rate_shipment(self, *_args): return { - 'success': True, - 'price': self.product_id.list_price, - 'error_message': False, - 'warning_message': False, + "success": True, + "price": self.product_id.list_price, + "error_message": False, + "warning_message": False, } diff --git a/addons/website_sale_collect/models/payment_provider.py b/addons/website_sale_collect/models/payment_provider.py index 88749938b02b0..835b4a0c88a9d 100644 --- a/addons/website_sale_collect/models/payment_provider.py +++ b/addons/website_sale_collect/models/payment_provider.py @@ -7,16 +7,16 @@ class PaymentProvider(models.Model): - _inherit = 'payment.provider' + _inherit = "payment.provider" - custom_mode = fields.Selection(selection_add=[('on_site', "Pay on site")]) + custom_mode = fields.Selection(selection_add=[("on_site", "Pay on site")]) # === CRUD METHODS === # def _get_default_payment_method_codes(self): """Override of `payment` to return the default payment method codes.""" self.ensure_one() - if self.custom_mode != 'on_site': + if self.custom_mode != "on_site": return super()._get_default_payment_method_codes() return const.DEFAULT_PAYMENT_METHOD_CODES @@ -44,16 +44,16 @@ def _get_compatible_providers( report=report, **kwargs, ) - order = self.env['sale.order'].browse(sale_order_id).exists() + order = self.env["sale.order"].browse(sale_order_id).exists() # Show on-site payment providers only if in-store delivery methods exist and the order # contains physical products. - if order.carrier_id.delivery_type != 'in_store' or not any( - product.type == 'consu' for product in order.order_line.product_id + if order.carrier_id.delivery_type != "in_store" or not any( + product.type == "consu" for product in order.order_line.product_id ): unfiltered_providers = compatible_providers compatible_providers = compatible_providers.filtered( - lambda p: p.code != 'custom' or p.custom_mode != 'on_site' + lambda p: p.code != "custom" or p.custom_mode != "on_site" ) payment_utils.add_to_report( report, diff --git a/addons/website_sale_collect/models/payment_transaction.py b/addons/website_sale_collect/models/payment_transaction.py index 2963c68d6d157..a531c86c3c40b 100644 --- a/addons/website_sale_collect/models/payment_transaction.py +++ b/addons/website_sale_collect/models/payment_transaction.py @@ -4,15 +4,15 @@ class PaymentTransaction(models.Model): - _inherit = 'payment.transaction' + _inherit = "payment.transaction" def _post_process(self): """Override of `payment` to confirm orders with the on_site payment method and trigger a picking creation.""" on_site_pending_txs = self.filtered( - lambda tx: tx.provider_id.custom_mode == 'on_site' and tx.state == 'pending' + lambda tx: tx.provider_id.custom_mode == "on_site" and tx.state == "pending" ) - on_site_pending_txs.sale_order_ids.filtered(lambda so: so.state == 'draft').with_context( + on_site_pending_txs.sale_order_ids.filtered(lambda so: so.state == "draft").with_context( send_email=True ).action_confirm() super()._post_process() diff --git a/addons/website_sale_collect/models/product_template.py b/addons/website_sale_collect/models/product_template.py index b16ff4e7d3e84..14e442b8178e0 100644 --- a/addons/website_sale_collect/models/product_template.py +++ b/addons/website_sale_collect/models/product_template.py @@ -7,7 +7,7 @@ class ProductTemplate(models.Model): - _inherit = 'product.template' + _inherit = "product.template" def _get_additionnal_combination_info(self, product_or_template, quantity, uom, date, website): """Override of `website_sale` to add information on whether Click & Collect is enabled and @@ -24,39 +24,39 @@ def _get_additionnal_combination_info(self, product_or_template, quantity, uom, order_sudo = request.cart cart_qty = order_sudo._get_cart_qty(product_sudo.id) # Enable the Click & Collect Availability widget. - res['show_click_and_collect_availability'] = True - res['uom_id'] = uom.id + res["show_click_and_collect_availability"] = True + res["uom_id"] = uom.id # Prepare the delivery stock data. - DeliveryCarrier = self.env['delivery.carrier'].sudo() + DeliveryCarrier = self.env["delivery.carrier"].sudo() available_delivery_methods_sudo = DeliveryCarrier.search([ - '|', - ('website_id', '=', website.id), - ('website_id', '=', False), - ('website_published', '=', True), - ('delivery_type', '!=', 'in_store'), + "|", + ("website_id", "=", website.id), + ("website_id", "=", False), + ("website_published", "=", True), + ("delivery_type", "!=", "in_store"), ]) if available_delivery_methods_sudo: - res['delivery_stock_data'] = utils.format_product_stock_values( + res["delivery_stock_data"] = utils.format_product_stock_values( product_sudo, uom=uom, cart_qty=cart_qty ) else: - res['delivery_stock_data'] = {} + res["delivery_stock_data"] = {} # Prepare the in-store stock data. if ( order_sudo - and order_sudo.carrier_id.delivery_type == 'in_store' + and order_sudo.carrier_id.delivery_type == "in_store" and order_sudo.pickup_location_data ): # Get stock values for the product variant in the selected store. - res['in_store_stock_data'] = utils.format_product_stock_values( + res["in_store_stock_data"] = utils.format_product_stock_values( product_sudo, uom=uom, - wh_id=order_sudo.pickup_location_data['id'], + wh_id=order_sudo.pickup_location_data["id"], cart_qty=cart_qty, ) else: - res['in_store_stock_data'] = utils.format_product_stock_values( + res["in_store_stock_data"] = utils.format_product_stock_values( product_sudo, uom=uom, free_qty=website.sudo()._get_max_in_store_product_available_qty(product_sudo), diff --git a/addons/website_sale_collect/models/res_config_settings.py b/addons/website_sale_collect/models/res_config_settings.py index a592b020759b6..f55f691b9bce6 100644 --- a/addons/website_sale_collect/models/res_config_settings.py +++ b/addons/website_sale_collect/models/res_config_settings.py @@ -4,23 +4,23 @@ class ResConfigSettings(models.TransientModel): - _inherit = 'res.config.settings' + _inherit = "res.config.settings" def action_view_in_store_delivery_methods(self): """Return an action to browse pickup delivery methods in list view, or in form view if there is only one.""" - in_store_dms = self.env['delivery.carrier'].search([('delivery_type', '=', 'in_store')]) + in_store_dms = self.env["delivery.carrier"].search([("delivery_type", "=", "in_store")]) if len(in_store_dms) == 1: return { - 'type': 'ir.actions.act_window', - 'res_model': 'delivery.carrier', - 'view_mode': 'form', - 'res_id': in_store_dms.id, + "type": "ir.actions.act_window", + "res_model": "delivery.carrier", + "view_mode": "form", + "res_id": in_store_dms.id, } return { - 'type': 'ir.actions.act_window', - 'name': _("Delivery Methods"), - 'res_model': 'delivery.carrier', - 'view_mode': 'list,form', - 'context': '{"search_default_delivery_type": "in_store"}', + "type": "ir.actions.act_window", + "name": _("Delivery Methods"), + "res_model": "delivery.carrier", + "view_mode": "list,form", + "context": '{"search_default_delivery_type": "in_store"}', } diff --git a/addons/website_sale_collect/models/sale_order.py b/addons/website_sale_collect/models/sale_order.py index e37ca770e3d30..45f182832d96a 100644 --- a/addons/website_sale_collect/models/sale_order.py +++ b/addons/website_sale_collect/models/sale_order.py @@ -8,25 +8,25 @@ class SaleOrder(models.Model): - _inherit = 'sale.order' + _inherit = "sale.order" def _compute_warehouse_id(self): """Override of `website_sale_stock` to avoid recomputations for in_store orders when the warehouse was set by the pickup_location_data.""" in_store_orders_with_pickup_data = self.filtered( - lambda so: (so.carrier_id.delivery_type == 'in_store' and so.pickup_location_data) + lambda so: (so.carrier_id.delivery_type == "in_store" and so.pickup_location_data) ) super(SaleOrder, self - in_store_orders_with_pickup_data)._compute_warehouse_id() for order in in_store_orders_with_pickup_data: - order.warehouse_id = order.pickup_location_data['id'] + order.warehouse_id = order.pickup_location_data["id"] def _compute_fiscal_position_id(self): """Override of `sale` to set the fiscal position matching the selected pickup location for pickup in-store orders.""" in_store_orders = self.filtered( - lambda so: so.carrier_id.delivery_type == 'in_store' and so.pickup_location_data + lambda so: so.carrier_id.delivery_type == "in_store" and so.pickup_location_data ) - AccountFiscalPosition = self.env['account.fiscal.position'].sudo() + AccountFiscalPosition = self.env["account.fiscal.position"].sudo() for order in in_store_orders: order.fiscal_position_id = AccountFiscalPosition._get_fiscal_position( order.partner_id, delivery=order.warehouse_id.partner_id @@ -38,8 +38,8 @@ def _set_delivery_method(self, delivery_method, rate=None): delivery method is not in-store anymore.""" self.ensure_one() was_in_store_order = ( - self.carrier_id.delivery_type == 'in_store' - and delivery_method.delivery_type != 'in_store' + self.carrier_id.delivery_type == "in_store" + and delivery_method.delivery_type != "in_store" ) super()._set_delivery_method(delivery_method, rate=rate) if was_in_store_order: @@ -52,12 +52,12 @@ def _set_pickup_location(self, pickup_location_data): taxes. """ super()._set_pickup_location(pickup_location_data) - if self.carrier_id.delivery_type != 'in_store': + if self.carrier_id.delivery_type != "in_store": return self.pickup_location_data = json.loads(pickup_location_data) if self.pickup_location_data: - self.warehouse_id = self.pickup_location_data['id'] + self.warehouse_id = self.pickup_location_data["id"] self._compute_fiscal_position_id() else: self._compute_warehouse_id() @@ -72,10 +72,10 @@ def _get_pickup_locations(self, zip_code=None, country=None, **kwargs): if zip_code and not country: country_code = None if self.pickup_location_data: - country_code = self.pickup_location_data['country_code'] + country_code = self.pickup_location_data["country_code"] elif request.geoip.country_code: country_code = request.geoip.country_code - country = self.env['res.country'].search([('code', '=', country_code)], limit=1) + country = self.env["res.country"].search([("code", "=", country_code)], limit=1) if not country: zip_code = None # Reset the zip code to skip the `assert` in the `super` call. return super()._get_pickup_locations(zip_code=zip_code, country=country, **kwargs) @@ -83,7 +83,7 @@ def _get_pickup_locations(self, zip_code=None, country=None, **kwargs): def _get_shop_warehouse_id(self): """Override of `website_sale_stock` to consider the chosen warehouse.""" self.ensure_one() - if self.carrier_id.delivery_type == 'in_store': + if self.carrier_id.delivery_type == "in_store": return self.warehouse_id.id return super()._get_shop_warehouse_id() @@ -92,7 +92,7 @@ def _check_cart_is_ready_to_be_paid(self): warehouse.""" if ( self._has_deliverable_products() - and self.carrier_id.delivery_type == 'in_store' + and self.carrier_id.delivery_type == "in_store" and not self._is_in_stock(self.warehouse_id.id) ): raise ValidationError( @@ -108,20 +108,20 @@ def _prepare_in_store_default_location_data(self): default_pickup_locations = {} for dm in self._get_delivery_methods(): if ( - dm.delivery_type == 'in_store' + dm.delivery_type == "in_store" and dm.id != self.carrier_id.id and len(dm.warehouse_ids) == 1 ): pickup_location_data = dm.warehouse_ids[0]._prepare_pickup_location_data() if pickup_location_data: default_pickup_locations[dm.id] = { - 'pickup_location_data': pickup_location_data, - 'insufficient_stock_data': self._get_insufficient_stock_data( - pickup_location_data['id'] + "pickup_location_data": pickup_location_data, + "insufficient_stock_data": self._get_insufficient_stock_data( + pickup_location_data["id"] ), } - return {'default_pickup_locations': default_pickup_locations} + return {"default_pickup_locations": default_pickup_locations} def _is_in_stock(self, wh_id): """Check whether all storable products of the cart are in stock in the given warehouse. @@ -143,13 +143,13 @@ def _get_insufficient_stock_data(self, wh_id): :rtype: dict """ insufficient_stock_data = {} - for product, ols in self.order_line.grouped('product_id').items(): + for product, ols in self.order_line.grouped("product_id").items(): if not product.is_storable or product.allow_out_of_stock_order: continue free_qty = product.with_context(warehouse_id=wh_id).free_qty for ol in ols: free_qty_in_uom = product.uom_id._compute_quantity( - free_qty, ol.product_uom_id, rounding_method='DOWN' + free_qty, ol.product_uom_id, rounding_method="DOWN" ) # Round down as only integer quantities can be sold. free_qty_in_uom = max(int(free_qty_in_uom), 0) @@ -168,11 +168,11 @@ def _get_insufficient_stock_data(self, wh_id): def _verify_updated_quantity(self, order_line, product_id, new_qty, uom_id, **kwargs): """Override of `website_sale_stock` to skip the verification when click and collect is activated. The quantity is verified later.""" - product = self.env['product.product'].browse(product_id) + product = self.env["product.product"].browse(product_id) if ( product.is_storable and not product.allow_out_of_stock_order and self.website_id.in_store_dm_id ): - return new_qty, '' + return new_qty, "" return super()._verify_updated_quantity(order_line, product_id, new_qty, uom_id, **kwargs) diff --git a/addons/website_sale_collect/models/stock_warehouse.py b/addons/website_sale_collect/models/stock_warehouse.py index 84bdbb4efb15d..6338af85f365a 100644 --- a/addons/website_sale_collect/models/stock_warehouse.py +++ b/addons/website_sale_collect/models/stock_warehouse.py @@ -5,10 +5,10 @@ class StockWarehouse(models.Model): - _inherit = 'stock.warehouse' + _inherit = "stock.warehouse" opening_hours = fields.Many2one( - string="Opening Hours", comodel_name='resource.calendar', check_company=True + string="Opening Hours", comodel_name="resource.calendar", check_company=True ) def _prepare_pickup_location_data(self): @@ -20,15 +20,15 @@ def _prepare_pickup_location_data(self): # Format the pickup location values of the warehouse. try: pickup_location_values = { - 'id': self.id, - 'name': wh_location['name'].title(), - 'street': wh_location['street'].title(), - 'city': wh_location.city.title(), - 'state': wh_location.state_id.code or '', - 'zip_code': wh_location.zip or '', - 'country_code': wh_location.country_code, - 'latitude': wh_location.partner_latitude, - 'longitude': wh_location.partner_longitude, + "id": self.id, + "name": wh_location["name"].title(), + "street": wh_location["street"].title(), + "city": wh_location.city.title(), + "state": wh_location.state_id.code or "", + "zip_code": wh_location.zip or "", + "country_code": wh_location.country_code, + "latitude": wh_location.partner_latitude, + "longitude": wh_location.partner_longitude, } except AttributeError: return {} @@ -37,11 +37,11 @@ def _prepare_pickup_location_data(self): if self.opening_hours: opening_hours_dict = {str(i): [] for i in range(7)} for att in self.opening_hours.attendance_ids: - if att.day_period in ('morning', 'afternoon'): + if att.day_period in ("morning", "afternoon"): opening_hours_dict[att.dayofweek].append( - f'{format_duration(att.hour_from)} - {format_duration(att.hour_to)}' + f"{format_duration(att.hour_from)} - {format_duration(att.hour_to)}" ) - pickup_location_values['opening_hours'] = opening_hours_dict + pickup_location_values["opening_hours"] = opening_hours_dict else: - pickup_location_values['opening_hours'] = {} + pickup_location_values["opening_hours"] = {} return pickup_location_values diff --git a/addons/website_sale_collect/models/website.py b/addons/website_sale_collect/models/website.py index 7522db38e7197..df824a36bd910 100644 --- a/addons/website_sale_collect/models/website.py +++ b/addons/website_sale_collect/models/website.py @@ -4,27 +4,27 @@ class Website(models.Model): - _inherit = 'website' + _inherit = "website" in_store_dm_id = fields.Many2one( string="In-store Delivery Method", - comodel_name='delivery.carrier', - compute='_compute_in_store_dm_id', + comodel_name="delivery.carrier", + compute="_compute_in_store_dm_id", ) def _compute_in_store_dm_id(self): - in_store_delivery_methods = self.env['delivery.carrier'].search([ - ('delivery_type', '=', 'in_store'), - ('is_published', '=', True), + in_store_delivery_methods = self.env["delivery.carrier"].search([ + ("delivery_type", "=", "in_store"), + ("is_published", "=", True), ]) for website in self: website.in_store_dm_id = in_store_delivery_methods.filtered_domain([ - '|', - ('website_id', '=', False), - ('website_id', '=', website.id), - '|', - ('company_id', '=', False), - ('company_id', '=', website.company_id.id), + "|", + ("website_id", "=", False), + ("website_id", "=", website.id), + "|", + ("company_id", "=", False), + ("company_id", "=", website.company_id.id), ])[:1] def _get_product_available_qty(self, product, **kwargs): diff --git a/addons/website_sale_collect/tests/common.py b/addons/website_sale_collect/tests/common.py index 1f557a3621d73..d10a5b4a80268 100644 --- a/addons/website_sale_collect/tests/common.py +++ b/addons/website_sale_collect/tests/common.py @@ -16,11 +16,11 @@ def setUpClass(cls): # Create the in-store delivery method. cls.dm_product = cls._prepare_carrier_product(list_price=0.0) - cls.provider = cls._prepare_provider(code='custom', custom_mode='on_site') + cls.provider = cls._prepare_provider(code="custom", custom_mode="on_site") cls.in_store_dm = cls._prepare_carrier( cls.dm_product, fixed_price=0.0, - delivery_type='in_store', + delivery_type="in_store", warehouse_ids=[Command.set([cls.warehouse.id])], name="Example in-store delivery", is_published=True, @@ -28,11 +28,11 @@ def setUpClass(cls): def _create_in_store_delivery_order(self, **values): default_values = { - 'partner_id': self.partner.id, - 'website_id': self.website.id, - 'order_line': [ - Command.create({'product_id': self.storable_product.id, 'product_uom_qty': 5.0}) + "partner_id": self.partner.id, + "website_id": self.website.id, + "order_line": [ + Command.create({"product_id": self.storable_product.id, "product_uom_qty": 5.0}) ], - 'carrier_id': self.in_store_dm.id, + "carrier_id": self.in_store_dm.id, } - return self.env['sale.order'].create(dict(default_values, **values)) + return self.env["sale.order"].create(dict(default_values, **values)) diff --git a/addons/website_sale_collect/tests/test_click_and_collect_express_checkout.py b/addons/website_sale_collect/tests/test_click_and_collect_express_checkout.py index 827b9ff7cd709..46d0052da10a1 100644 --- a/addons/website_sale_collect/tests/test_click_and_collect_express_checkout.py +++ b/addons/website_sale_collect/tests/test_click_and_collect_express_checkout.py @@ -6,7 +6,7 @@ from odoo.addons.website_sale_collect.tests.common import ClickAndCollectCommon -@tagged('post_install', '-at_install') +@tagged("post_install", "-at_install") class TestClickAndCollectExpressCheckout(ClickAndCollectCommon): def test_exclude_in_store_delivery_methods(self): express_delivery_methods = InStoreDelivery._get_delivery_methods_express_checkout(self.cart) diff --git a/addons/website_sale_collect/tests/test_click_and_collect_flow.py b/addons/website_sale_collect/tests/test_click_and_collect_flow.py index 085e12651c41a..7beb556bbc111 100644 --- a/addons/website_sale_collect/tests/test_click_and_collect_flow.py +++ b/addons/website_sale_collect/tests/test_click_and_collect_flow.py @@ -6,18 +6,18 @@ from odoo.addons.website_sale_collect.tests.common import ClickAndCollectCommon -@tagged('post_install', '-at_install') +@tagged("post_install", "-at_install") class TestClickAndCollectFlow(HttpCase, ClickAndCollectCommon): @classmethod def setUpClass(cls): super().setUpClass() cls.storable_product.name = "Test CAC Product" - cls.provider.write({'state': 'enabled', 'is_published': True}) - cls.in_store_dm.warehouse_ids[0].partner_id = cls.env['res.partner'].create({ + cls.provider.write({"state": "enabled", "is_published": True}) + cls.in_store_dm.warehouse_ids[0].partner_id = cls.env["res.partner"].create({ **cls.dummy_partner_address_values, - 'name': "Shop 1", - 'partner_latitude': 1.0, - 'partner_longitude': 2.0, + "name": "Shop 1", + "partner_latitude": 1.0, + "partner_longitude": 2.0, }) def test_buy_with_click_and_collect_as_public_user(self): @@ -25,17 +25,17 @@ def test_buy_with_click_and_collect_as_public_user(self): Test the basic flow of buying with click and collect as a public user with more than one delivery method available. """ - self.start_tour('/', 'website_sale_collect_widget') + self.start_tour("/", "website_sale_collect_widget") def test_default_location_is_set_for_pick_up_in_store(self): """ Verify that when `Pick Up In Store` is the only active delivery method with the only wh, the checkout flow automatically sets the default store location. """ - self.env['delivery.carrier'].search([]).active = False + self.env["delivery.carrier"].search([]).active = False self.in_store_dm.active = True self.in_store_dm.is_published = True - self.start_tour('/', 'website_sale_collect_buy_product_default_location_pick_up_in_store') + self.start_tour("/", "website_sale_collect_buy_product_default_location_pick_up_in_store") def test_cash_on_delivery_resets_on_in_store_type(self): """ @@ -43,11 +43,11 @@ def test_cash_on_delivery_resets_on_in_store_type(self): to the 'in_store' delivery type, the 'allow_cash_on_delivery' field is automatically reset to False. """ - carrier = self.env['delivery.carrier'].create({ - 'name': 'Test Carrier', - 'allow_cash_on_delivery': True, - 'delivery_type': 'fixed', - 'product_id': self.storable_product.id, + carrier = self.env["delivery.carrier"].create({ + "name": "Test Carrier", + "allow_cash_on_delivery": True, + "delivery_type": "fixed", + "product_id": self.storable_product.id, }) - carrier.delivery_type = 'in_store' + carrier.delivery_type = "in_store" self.assertEqual(carrier.allow_cash_on_delivery, False) diff --git a/addons/website_sale_collect/tests/test_delivery_carrier.py b/addons/website_sale_collect/tests/test_delivery_carrier.py index 48480f3ae1883..2bdb8db9abf6e 100644 --- a/addons/website_sale_collect/tests/test_delivery_carrier.py +++ b/addons/website_sale_collect/tests/test_delivery_carrier.py @@ -11,7 +11,7 @@ from odoo.addons.website_sale_stock.tests.common import WebsiteSaleStockCommon -@tagged('post_install', '-at_install') +@tagged("post_install", "-at_install") class TestDeliveryCarrier(ClickAndCollectCommon, WebsiteSaleStockCommon): def test_prevent_publishing_when_no_warehouse(self): self.in_store_dm.is_published = False @@ -21,59 +21,59 @@ def test_prevent_publishing_when_no_warehouse(self): def test_same_company_for_delivery_method_and_warehouse(self): self.in_store_dm.company_id = self.company_id - self.companyA = self.env['res.company'].create({'name': 'Company A'}) + self.companyA = self.env["res.company"].create({"name": "Company A"}) self.warehouse_2 = self._create_warehouse(company_id=self.companyA.id) with self.assertRaises(ValidationError): self.in_store_dm.warehouse_ids = [Command.set([self.warehouse_2.id])] def test_creating_in_store_delivery_method_sets_integration_level_to_rate(self): - new_in_store_carrier = self.env['delivery.carrier'].create({ - 'name': "Test Carrier", - 'delivery_type': 'in_store', - 'product_id': self.dm_product.id, + new_in_store_carrier = self.env["delivery.carrier"].create({ + "name": "Test Carrier", + "delivery_type": "in_store", + "product_id": self.dm_product.id, }) - self.assertEqual(new_in_store_carrier.integration_level, 'rate') + self.assertEqual(new_in_store_carrier.integration_level, "rate") def test_in_store_get_close_locations_returned_data(self): so = self._create_in_store_delivery_order() # Create a partner for a warehouse. - wh_address_partner = self.env['res.partner'].create({ + wh_address_partner = self.env["res.partner"].create({ **self.dummy_partner_address_values, - 'name': "Shop 1", - 'partner_latitude': 1.0, - 'partner_longitude': 2.0, + "name": "Shop 1", + "partner_latitude": 1.0, + "partner_longitude": 2.0, }) self.warehouse.partner_id = wh_address_partner.id - self.warehouse.opening_hours = self.env['resource.calendar'].create({ - 'name': 'Opening hours', - 'attendance_ids': [ + self.warehouse.opening_hours = self.env["resource.calendar"].create({ + "name": "Opening hours", + "attendance_ids": [ Command.create({ - 'name': 'Monday Morning', - 'dayofweek': '0', - 'hour_from': 8, - 'hour_to': 12, - 'day_period': 'morning', + "name": "Monday Morning", + "dayofweek": "0", + "hour_from": 8, + "hour_to": 12, + "day_period": "morning", }), Command.create({ - 'name': 'Monday Lunch', - 'dayofweek': '0', - 'hour_from': 12, - 'hour_to': 13, - 'day_period': 'lunch', + "name": "Monday Lunch", + "dayofweek": "0", + "hour_from": 12, + "hour_to": 13, + "day_period": "lunch", }), Command.create({ - 'name': 'Monday Afternoon', - 'dayofweek': '0', - 'hour_from': 13, - 'hour_to': 17, - 'day_period': 'afternoon', + "name": "Monday Afternoon", + "dayofweek": "0", + "hour_from": 13, + "hour_to": 17, + "day_period": "afternoon", }), ], }) with ( patch( - 'odoo.addons.base_geolocalize.models.res_partner.ResPartner.geo_localize', + "odoo.addons.base_geolocalize.models.res_partner.ResPartner.geo_localize", return_value=True, ), MockRequest(self.env, website=self.website, sale_order_id=so.id), @@ -83,26 +83,26 @@ def test_in_store_get_close_locations_returned_data(self): locations, [ { - 'id': self.warehouse.id, - 'name': wh_address_partner['name'].title(), - 'street': wh_address_partner['street'].title(), - 'city': wh_address_partner.city.title(), - 'zip_code': wh_address_partner.zip, - 'state': wh_address_partner.state_id.code, - 'country_code': wh_address_partner.country_code, - 'latitude': wh_address_partner.partner_latitude, - 'longitude': wh_address_partner.partner_longitude, - 'additional_data': {'in_store_stock_data': {'in_stock': True}}, - 'opening_hours': { - '0': ['08:00 - 12:00', '13:00 - 17:00'], - '1': [], - '2': [], - '3': [], - '4': [], - '5': [], - '6': [], + "id": self.warehouse.id, + "name": wh_address_partner["name"].title(), + "street": wh_address_partner["street"].title(), + "city": wh_address_partner.city.title(), + "zip_code": wh_address_partner.zip, + "state": wh_address_partner.state_id.code, + "country_code": wh_address_partner.country_code, + "latitude": wh_address_partner.partner_latitude, + "longitude": wh_address_partner.partner_longitude, + "additional_data": {"in_store_stock_data": {"in_stock": True}}, + "opening_hours": { + "0": ["08:00 - 12:00", "13:00 - 17:00"], + "1": [], + "2": [], + "3": [], + "4": [], + "5": [], + "6": [], }, - 'distance': 0.0, + "distance": 0.0, } ], ) diff --git a/addons/website_sale_collect/tests/test_in_store_delivery.py b/addons/website_sale_collect/tests/test_in_store_delivery.py index 9270f32cc6718..0a249b65fc047 100644 --- a/addons/website_sale_collect/tests/test_in_store_delivery.py +++ b/addons/website_sale_collect/tests/test_in_store_delivery.py @@ -9,19 +9,19 @@ from odoo.addons.website_sale_collect.tests.common import ClickAndCollectCommon -@tagged('post_install', '-at_install') +@tagged("post_install", "-at_install") class TestInStoreDeliveryController(PaymentHttpCommon, ClickAndCollectCommon): def setUp(self): super().setUp() self.InStoreController = InStoreDelivery() def test_order_not_created_on_fetching_pickup_location_with_empty_cart(self): - count_so_before = self.env['sale.order'].search_count([]) - url = self._build_url('/website_sale/get_pickup_locations') + count_so_before = self.env["sale.order"].search_count([]) + url = self._build_url("/website_sale/get_pickup_locations") with patch( - 'odoo.addons.website_sale_collect.models.sale_order.SaleOrder._get_pickup_locations', + "odoo.addons.website_sale_collect.models.sale_order.SaleOrder._get_pickup_locations", return_value={}, ): - self.make_jsonrpc_request(url, {'product_id': 1}) - count_so_after = self.env['sale.order'].search_count([]) + self.make_jsonrpc_request(url, {"product_id": 1}) + count_so_after = self.env["sale.order"].search_count([]) self.assertEqual(count_so_after, count_so_before) diff --git a/addons/website_sale_collect/tests/test_payment_provider.py b/addons/website_sale_collect/tests/test_payment_provider.py index 24d043931ee6a..e6989b991c4e6 100644 --- a/addons/website_sale_collect/tests/test_payment_provider.py +++ b/addons/website_sale_collect/tests/test_payment_provider.py @@ -5,24 +5,24 @@ from odoo.addons.website_sale_collect.tests.common import ClickAndCollectCommon -@tagged('post_install', '-at_install') +@tagged("post_install", "-at_install") class TestOnSitePaymentProvider(HttpCase, ClickAndCollectCommon): def test_on_site_provider_available_when_in_store_delivery_is_chosen(self): order = self._create_in_store_delivery_order() - PaymentProvider = self.env['payment.provider'].sudo() + PaymentProvider = self.env["payment.provider"].sudo() compatible_providers = PaymentProvider._get_compatible_providers( self.company.id, self.partner.id, self.amount, sale_order_id=order.id ) self.assertTrue( - any(p.code == 'custom' and p.custom_mode == 'on_site' for p in compatible_providers) + any(p.code == "custom" and p.custom_mode == "on_site" for p in compatible_providers) ) def test_on_site_provider_unavailable_when_no_in_store_delivery(self): order = self._create_in_store_delivery_order(carrier_id=self.free_delivery.id) - PaymentProvider = self.env['payment.provider'].sudo() + PaymentProvider = self.env["payment.provider"].sudo() compatible_providers = PaymentProvider._get_compatible_providers( self.company.id, self.partner.id, self.amount, sale_order_id=order.id ) self.assertFalse( - any(p.code == 'custom' and p.custom_mode == 'on_site' for p in compatible_providers) + any(p.code == "custom" and p.custom_mode == "on_site" for p in compatible_providers) ) diff --git a/addons/website_sale_collect/tests/test_payment_transaction.py b/addons/website_sale_collect/tests/test_payment_transaction.py index 76226386203aa..a2c6e4da6be09 100644 --- a/addons/website_sale_collect/tests/test_payment_transaction.py +++ b/addons/website_sale_collect/tests/test_payment_transaction.py @@ -6,17 +6,17 @@ from odoo.addons.website_sale_collect.tests.common import ClickAndCollectCommon -@tagged('post_install', '-at_install') +@tagged("post_install", "-at_install") class TestOnSitePaymentTransaction(HttpCase, ClickAndCollectCommon): def test_choosing_on_site_payment_confirms_order(self): - order = self._create_so(carrier_id=self.carrier.id, state='draft') + order = self._create_so(carrier_id=self.carrier.id, state="draft") tx = self._create_transaction( - flow='direct', + flow="direct", sale_order_ids=[order.id], - state='pending', + state="pending", payment_method_id=self.provider.payment_method_ids.id, ) - with mute_logger('odoo.addons.sale.models.payment_transaction'): + with mute_logger("odoo.addons.sale.models.payment_transaction"): tx._post_process() - self.assertEqual(order.state, 'sale') + self.assertEqual(order.state, "sale") diff --git a/addons/website_sale_collect/tests/test_product_template.py b/addons/website_sale_collect/tests/test_product_template.py index e8a32c70cda9b..4227bf2961176 100644 --- a/addons/website_sale_collect/tests/test_product_template.py +++ b/addons/website_sale_collect/tests/test_product_template.py @@ -8,18 +8,18 @@ from odoo.addons.website_sale_collect.tests.common import ClickAndCollectCommon -@tagged('post_install', '-at_install') +@tagged("post_install", "-at_install") class TestProductTemplate(ClickAndCollectCommon): def test_out_of_stock_product_available_when_allow_continue_selling(self): product = self._create_product(allow_out_of_stock_order=True) self.free_delivery.is_published = True with MockRequest(self.env, website=self.website, sale_order_id=self.cart.id): - comb_info = self.env['product.template']._get_additionnal_combination_info( + comb_info = self.env["product.template"]._get_additionnal_combination_info( product, quantity=1, date=datetime(2000, 1, 1), uom=self.uom_unit, website=self.website, ) - self.assertTrue(comb_info['delivery_stock_data']['in_stock']) - self.assertTrue(comb_info['in_store_stock_data']['in_stock']) + self.assertTrue(comb_info["delivery_stock_data"]["in_stock"]) + self.assertTrue(comb_info["in_store_stock_data"]["in_stock"]) diff --git a/addons/website_sale_collect/tests/test_sale_order.py b/addons/website_sale_collect/tests/test_sale_order.py index 0ab61011b6266..79e36795157f7 100644 --- a/addons/website_sale_collect/tests/test_sale_order.py +++ b/addons/website_sale_collect/tests/test_sale_order.py @@ -7,7 +7,7 @@ from odoo.addons.website_sale_collect.tests.common import ClickAndCollectCommon -@tagged('post_install', '-at_install') +@tagged("post_install", "-at_install") class TestSaleOrder(ClickAndCollectCommon): @classmethod def setUpClass(cls): @@ -23,54 +23,54 @@ def test_warehouse_is_updated_when_changing_delivery_line(self): def test_setting_pickup_location_assigns_warehouse(self): so = self._create_in_store_delivery_order() - so._set_pickup_location('{"id":' + str(self.warehouse.id) + '}') + so._set_pickup_location('{"id":' + str(self.warehouse.id) + "}") self.assertEqual(so.warehouse_id, self.warehouse) def test_warehouse_is_not_reset_on_public_user_checkout(self): warehouse_2 = self._create_warehouse() so = self._create_in_store_delivery_order(partner_id=self.public_user.id) - so._set_pickup_location('{"id":' + str(warehouse_2.id) + '}') + so._set_pickup_location('{"id":' + str(warehouse_2.id) + "}") # change the partner_id as would happen in a checkout so.partner_id = self.partner.id self.assertEqual(so.warehouse_id, warehouse_2) def test_warehouse_is_computed_based_on_pickup_location(self): warehouse_2 = self._create_warehouse() - so = self._create_in_store_delivery_order(pickup_location_data={'id': warehouse_2.id}) + so = self._create_in_store_delivery_order(pickup_location_data={"id": warehouse_2.id}) self.assertEqual(so.warehouse_id, warehouse_2) def test_fiscal_position_id_is_computed_from_pickup_location_partner(self): - fp_be = self.env['account.fiscal.position'].create({ - 'name': "Test BE fiscal position", - 'country_id': self.country_be.id, - 'auto_apply': True, + fp_be = self.env["account.fiscal.position"].create({ + "name": "Test BE fiscal position", + "country_id": self.country_be.id, + "auto_apply": True, }) self.default_partner.country_id = self.country_us self.warehouse.partner_id.country_id = self.country_be so = self._create_in_store_delivery_order( partner_shipping_id=self.default_partner.id, - pickup_location_data={'id': self.warehouse.id}, + pickup_location_data={"id": self.warehouse.id}, ) self.assertEqual(so.fiscal_position_id, fp_be) def test_setting_pickup_location_assigns_correct_fiscal_position(self): - fp_be = self.env['account.fiscal.position'].create({ - 'name': "Test BE fiscal position", - 'country_id': self.country_be.id, - 'auto_apply': True, + fp_be = self.env["account.fiscal.position"].create({ + "name": "Test BE fiscal position", + "country_id": self.country_be.id, + "auto_apply": True, }) so = self._create_in_store_delivery_order() self.default_partner.country_id = self.country_be warehouse = self._create_warehouse() warehouse.partner_id = self.default_partner - so._set_pickup_location('{"id":' + str(warehouse.id) + '}') + so._set_pickup_location('{"id":' + str(warehouse.id) + "}") self.assertEqual(so.fiscal_position_id, fp_be) def test_selecting_not_in_store_dm_resets_fiscal_position(self): - fp_us = self.env['account.fiscal.position'].create({ - 'name': "Test US fiscal position", - 'country_id': self.country_us.id, - 'auto_apply': True, + fp_us = self.env["account.fiscal.position"].create({ + "name": "Test US fiscal position", + "country_id": self.country_us.id, + "auto_apply": True, }) so = self._create_in_store_delivery_order() so.fiscal_position_id = fp_us @@ -87,7 +87,7 @@ def test_free_qty_calculated_from_order_wh_if_dm_is_in_store(self): def test_prevent_buying_out_of_stock_products(self): cart = self._create_in_store_delivery_order( - order_line=[Command.create({'product_id': self.product_2.id, 'product_uom_qty': 5.0})] + order_line=[Command.create({"product_id": self.product_2.id, "product_uom_qty": 5.0})] ) cart.warehouse_id = self.warehouse with self.assertRaises(ValidationError): @@ -96,7 +96,7 @@ def test_prevent_buying_out_of_stock_products(self): def test_product_in_stock_is_available(self): cart = self._create_in_store_delivery_order( order_line=[ - Command.create({'product_id': self.storable_product.id, 'product_uom_qty': 5.0}) + Command.create({"product_id": self.storable_product.id, "product_uom_qty": 5.0}) ] ) insufficient_stock_data = cart._get_insufficient_stock_data(self.warehouse.id) @@ -105,7 +105,7 @@ def test_product_in_stock_is_available(self): def test_product_out_of_stock_continue_selling_is_available(self): self.product_2.allow_out_of_stock_order = True cart = self._create_in_store_delivery_order( - order_line=[Command.create({'product_id': self.product_2.id, 'product_uom_qty': 5.0})] + order_line=[Command.create({"product_id": self.product_2.id, "product_uom_qty": 5.0})] ) insufficient_stock_data = cart._get_insufficient_stock_data(self.warehouse.id) self.assertFalse(insufficient_stock_data) @@ -113,7 +113,7 @@ def test_product_out_of_stock_continue_selling_is_available(self): def test_product_insufficient_stock_is_unavailable(self): cart = self._create_in_store_delivery_order( order_line=[ - Command.create({'product_id': self.storable_product.id, 'product_uom_qty': 15.0}) + Command.create({"product_id": self.storable_product.id, "product_uom_qty": 15.0}) ] ) insufficient_stock_data = cart._get_insufficient_stock_data(self.warehouse.id) @@ -122,19 +122,19 @@ def test_product_insufficient_stock_is_unavailable(self): def test_insufficient_stock_with_mixed_uom_order_lines(self): """Test that the insufficient stock is correctly computed when the order lines use different UoMs.""" - pack_of_6_id = self.ref('uom.product_uom_pack_6') + pack_of_6_id = self.ref("uom.product_uom_pack_6") # 1 pack of 6 + 5 units = 11 units in the cart cart = self._create_in_store_delivery_order( order_line=[ Command.create({ - 'product_id': self.storable_product.id, - 'product_uom_qty': 1.0, - 'product_uom_id': pack_of_6_id, + "product_id": self.storable_product.id, + "product_uom_qty": 1.0, + "product_uom_id": pack_of_6_id, }), Command.create({ - 'product_id': self.storable_product.id, - 'product_uom_qty': 5.0, - 'product_uom_id': self.storable_product.uom_id.id, + "product_id": self.storable_product.id, + "product_uom_qty": 5.0, + "product_uom_id": self.storable_product.uom_id.id, }), ] ) @@ -149,19 +149,19 @@ def test_insufficient_stock_with_mixed_uom_order_lines(self): def test_product_in_stock_with_mixed_uom_order_lines_is_available(self): """Test that if there is enough stock for all order lines the insufficient stock is empty.""" - pack_of_6_id = self.ref('uom.product_uom_pack_6') + pack_of_6_id = self.ref("uom.product_uom_pack_6") # 1 pack of 6 + 4 units = 10 units in the cart cart = self._create_in_store_delivery_order( order_line=[ Command.create({ - 'product_id': self.storable_product.id, - 'product_uom_qty': 4.0, - 'product_uom_id': self.storable_product.uom_id.id, + "product_id": self.storable_product.id, + "product_uom_qty": 4.0, + "product_uom_id": self.storable_product.uom_id.id, }), Command.create({ - 'product_id': self.storable_product.id, - 'product_uom_qty': 1.0, - 'product_uom_id': pack_of_6_id, + "product_id": self.storable_product.id, + "product_uom_qty": 1.0, + "product_uom_id": pack_of_6_id, }), ] ) @@ -171,7 +171,7 @@ def test_product_in_stock_with_mixed_uom_order_lines_is_available(self): def test_out_of_stock_product_is_unavailable(self): cart = self._create_in_store_delivery_order( - order_line=[Command.create({'product_id': self.product_2.id, 'product_uom_qty': 5.0})] + order_line=[Command.create({"product_id": self.product_2.id, "product_uom_qty": 5.0})] ) insufficient_stock_data = cart._get_insufficient_stock_data(self.warehouse.id) self.assertIn(cart.order_line, insufficient_stock_data) @@ -180,7 +180,7 @@ def test_product_in_different_warehouse_is_unavailable(self): self.warehouse_2 = self._create_warehouse() cart = self._create_in_store_delivery_order( order_line=[ - Command.create({'product_id': self.storable_product.id, 'product_uom_qty': 5.0}) + Command.create({"product_id": self.storable_product.id, "product_uom_qty": 5.0}) ] ) insufficient_stock_data = cart._get_insufficient_stock_data(self.warehouse_2.id) diff --git a/addons/website_sale_collect/tests/test_website.py b/addons/website_sale_collect/tests/test_website.py index b93df87d73727..f0d77c7ac9499 100644 --- a/addons/website_sale_collect/tests/test_website.py +++ b/addons/website_sale_collect/tests/test_website.py @@ -6,7 +6,7 @@ from odoo.addons.website_sale_collect.tests.common import ClickAndCollectCommon -@tagged('post_install', '-at_install') +@tagged("post_install", "-at_install") class TestWebsite(ClickAndCollectCommon): @classmethod def setUpClass(cls):