119 lines
4.7 KiB
Python
119 lines
4.7 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
import logging
|
|
import pprint
|
|
|
|
from odoo import _, models
|
|
from odoo.exceptions import UserError, ValidationError
|
|
|
|
from odoo.addons.sale_gelato import utils
|
|
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class SaleOrder(models.Model):
|
|
_inherit = 'sale.order'
|
|
|
|
# === CRUD METHODS === #
|
|
|
|
def _prevent_mixing_gelato_and_non_gelato_products(self):
|
|
""" Ensure that the order lines don't mix Gelato and non-Gelato products.
|
|
|
|
This method is not a constraint and is called from the `create` and `write` methods of
|
|
`sale.order.line` to cover the cases where adding/writing on order lines would not trigger a
|
|
constraint check (e.g., adding products through the Catalog).
|
|
|
|
:return: None
|
|
:raise ValidationError: If Gelato and non-Gelato products are mixed.
|
|
"""
|
|
for order in self:
|
|
gelato_lines = order.order_line.filtered(lambda l: l.product_id.gelato_product_uid)
|
|
non_gelato_lines = (order.order_line - gelato_lines).filtered(
|
|
lambda l: l.product_id.sale_ok and l.product_id.type != 'service'
|
|
) # Filter out non-saleable (sections, etc.) and non-deliverable products.
|
|
if gelato_lines and non_gelato_lines:
|
|
raise ValidationError(
|
|
_("You cannot mix Gelato products with non-Gelato products in the same order."))
|
|
|
|
# === ACTION METHODS === #
|
|
|
|
def action_open_delivery_wizard(self):
|
|
""" Override of `delivery` to set a Gelato delivery method by default in the wizard. """
|
|
res = super().action_open_delivery_wizard()
|
|
|
|
if (
|
|
not self.env.context.get('carrier_recompute')
|
|
and any(line.product_id.gelato_product_uid for line in self.order_line)
|
|
):
|
|
gelato_delivery_method = self.env['delivery.carrier'].search(
|
|
[('delivery_type', '=', 'gelato')], limit=1
|
|
)
|
|
res['context']['default_carrier_id'] = gelato_delivery_method.id
|
|
return res
|
|
|
|
def action_confirm(self):
|
|
""" Override of `sale` to send the order to Gelato on confirmation. """
|
|
res = super().action_confirm()
|
|
for order in self.filtered(
|
|
lambda o: any(o.order_line.product_id.mapped('gelato_product_uid'))
|
|
):
|
|
order._create_order_on_gelato()
|
|
return res
|
|
|
|
# === BUSINESS METHODS === #
|
|
|
|
def _create_order_on_gelato(self):
|
|
""" Send the order creation request to Gelato and log the request result on the chatter.
|
|
|
|
:return: None
|
|
"""
|
|
delivery_line = self.order_line.filtered(
|
|
lambda l: l.is_delivery and l.product_id.default_code in ('normal', 'express')
|
|
)
|
|
payload = {
|
|
'orderType': 'order',
|
|
'orderReferenceId': self.id,
|
|
'customerReferenceId': f'Odoo Partner #{self.partner_id.id}',
|
|
'currency': self.currency_id.name,
|
|
'items': self._gelato_prepare_items_payload(),
|
|
'shipmentMethodUid': delivery_line.product_id.default_code or 'cheapest',
|
|
'shippingAddress': self.partner_shipping_id._gelato_prepare_address_payload(),
|
|
}
|
|
try:
|
|
api_key = self.company_id.sudo().gelato_api_key # In sudo mode to read on the company.
|
|
data = utils.make_request(api_key, 'order', 'v4', 'orders', payload=payload)
|
|
except UserError as e:
|
|
raise UserError(_(
|
|
"The order with reference %(order_reference)s was not sent to Gelato.\n"
|
|
"Reason: %(error_message)s",
|
|
order_reference=self.display_name,
|
|
error_message=str(e),
|
|
))
|
|
|
|
_logger.info("Notification received from Gelato with data:\n%s", pprint.pformat(data))
|
|
self.message_post(
|
|
body=_("The order has been successfully passed on Gelato."),
|
|
author_id=self.env.ref('base.partner_root').id,
|
|
)
|
|
|
|
def _gelato_prepare_items_payload(self):
|
|
""" Create the payload for the 'items' key of an 'orders' request.
|
|
|
|
:return: The items payload.
|
|
:rtype: dict
|
|
"""
|
|
items_payload = []
|
|
for gelato_line in self.order_line.filtered(lambda l: l.product_id.gelato_product_uid):
|
|
item_data = {
|
|
'itemReferenceId': gelato_line.product_id.id,
|
|
'productUid': gelato_line.product_id.gelato_product_uid,
|
|
'files': [
|
|
image._gelato_prepare_file_payload()
|
|
for image in gelato_line.product_id.product_tmpl_id.gelato_image_ids
|
|
],
|
|
'quantity': int(gelato_line.product_uom_qty),
|
|
}
|
|
items_payload.append(item_data)
|
|
return items_payload
|