148 lines
7.1 KiB
Python

from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
import logging
_logger = logging.getLogger(__name__)
class PosOrderChannels(models.Model):
_inherit = 'pos.order'
# -----------------------------------------------------------
# Channel 1-5: Order Source Field
# -----------------------------------------------------------
order_source = fields.Selection([
('walk_in', 'Walk-In (Standard POS)'),
('phone', 'Telephone Order'),
('online', 'Online / eCommerce'),
('whatsapp', 'WhatsApp'),
('social_media', 'Social Media'),
('platform', 'Third-Party Platform'),
('kiosk', 'Self-Order Kiosk'),
('qr', 'QR Table Order'),
], string='Order Source', default='walk_in', index=True,
help='Channel through which this order was received')
# -----------------------------------------------------------
# All Channels: Fulfilment Type
# -----------------------------------------------------------
fulfilment_type = fields.Selection([
('dine_in', 'Dine-In'),
('pickup', 'Pickup'),
('delivery', 'Delivery'),
], string='Fulfilment Type', default='dine_in', index=True,
help='How the customer wants to receive the order')
# -----------------------------------------------------------
# Delivery Address (linked to res.partner)
# -----------------------------------------------------------
delivery_partner_id = fields.Many2one(
'res.partner', string='Delivery Address',
domain="[('type', 'in', ['delivery', 'contact', 'other'])]",
help='Delivery address for this order'
)
delivery_street = fields.Char('Delivery Street', compute='_compute_delivery_address', store=True, readonly=False)
delivery_city = fields.Char('Delivery City', compute='_compute_delivery_address', store=True, readonly=False)
delivery_zip = fields.Char('Delivery Zip', compute='_compute_delivery_address', store=True, readonly=False)
delivery_phone = fields.Char('Delivery Phone', compute='_compute_delivery_address', store=True, readonly=False)
delivery_notes = fields.Text('Delivery Notes', help='Special delivery instructions')
# -----------------------------------------------------------
# WhatsApp: sender info
# -----------------------------------------------------------
whatsapp_number = fields.Char('WhatsApp Number', help='Customer WhatsApp phone number')
whatsapp_msg_id = fields.Char('WhatsApp Msg ID', help='Original message ID for thread linking')
# -----------------------------------------------------------
# Social Media: reference
# ----------------------------------------------------------- # Social Media: reference
social_ref = fields.Char('Social Ref', help='Instagram/Facebook message/post reference')
# Telephone: customer phone for phone orders
telephone_number = fields.Char('Telephone Number', help='Customer phone number for telephone orders')
# -----------------------------------------------------------
# Computed helpers
# -----------------------------------------------------------
is_delivery_order = fields.Boolean(
string='Is Delivery', compute='_compute_is_delivery_order', store=True
)
@api.depends('fulfilment_type')
def _compute_is_delivery_order(self):
for order in self:
order.is_delivery_order = (order.fulfilment_type == 'delivery')
@api.depends('delivery_partner_id')
def _compute_delivery_address(self):
for order in self:
p = order.delivery_partner_id
if p:
order.delivery_street = p.street or ''
order.delivery_city = p.city or ''
order.delivery_zip = p.zip or ''
order.delivery_phone = p.phone or p.mobile or ''
else:
order.delivery_street = order.delivery_street or ''
order.delivery_city = order.delivery_city or ''
order.delivery_zip = order.delivery_zip or ''
order.delivery_phone = order.delivery_phone or ''
# -----------------------------------------------------------
# Validation
# -----------------------------------------------------------
@api.constrains('fulfilment_type', 'delivery_street')
def _check_delivery_address(self):
for order in self:
if order.fulfilment_type == 'delivery' and order.state == 'done':
if not (order.delivery_street or order.delivery_partner_id):
raise ValidationError(
_("A delivery address is required for delivery orders.")
)
# -----------------------------------------------------------
# Override _order_fields for POS sync (these values come from POS UI)
# -----------------------------------------------------------
@api.model
def _order_fields(self, ui_order):
fields_dict = super()._order_fields(ui_order)
fields_dict['order_source'] = ui_order.get('order_source', 'walk_in')
fields_dict['fulfilment_type'] = ui_order.get('fulfilment_type', 'dine_in')
fields_dict['delivery_street'] = ui_order.get('delivery_street', '')
fields_dict['delivery_city'] = ui_order.get('delivery_city', '')
fields_dict['delivery_zip'] = ui_order.get('delivery_zip', '')
fields_dict['delivery_phone'] = ui_order.get('delivery_phone', '')
fields_dict['delivery_notes'] = ui_order.get('delivery_notes', '')
fields_dict['whatsapp_number'] = ui_order.get('whatsapp_number', '')
fields_dict['social_ref'] = ui_order.get('social_ref', '')
fields_dict['telephone_number'] = ui_order.get('telephone_number', '')
return fields_dict
# -----------------------------------------------------------
# Export fields back to POS (needed for POS to read saved orders)
# -----------------------------------------------------------
def _export_for_ui(self, order):
result = super()._export_for_ui(order)
result['order_source'] = order.order_source
result['fulfilment_type'] = order.fulfilment_type
result['delivery_street'] = order.delivery_street or ''
result['delivery_city'] = order.delivery_city or ''
result['delivery_zip'] = order.delivery_zip or ''
result['delivery_phone'] = order.delivery_phone or ''
result['delivery_notes'] = order.delivery_notes or ''
result['whatsapp_number'] = order.whatsapp_number or ''
result['social_ref'] = order.social_ref or ''
result['telephone_number'] = order.telephone_number or ''
return result
class PosOrderLineChannels(models.Model):
_inherit = 'pos.order.line'
order_source = fields.Selection(
related='order_id.order_source', string='Order Source', store=True
)
fulfilment_type = fields.Selection(
related='order_id.fulfilment_type', string='Fulfilment Type', store=True
)