From 3022b8ed59e8ade59abfada55c8b695ad27e0cda Mon Sep 17 00:00:00 2001 From: gsinghpal Date: Thu, 2 Apr 2026 10:45:07 -0400 Subject: [PATCH] CHANGES --- .../models/woo_category_map.py | 1 + .../fusion_woocommerce/models/woo_conflict.py | 1 + .../fusion_woocommerce/models/woo_customer.py | 1 + .../fusion_woocommerce/models/woo_instance.py | 6 +- .../fusion_woocommerce/models/woo_order.py | 140 +++++++++++++++++- .../models/woo_pricelist_map.py | 1 + .../models/woo_product_map.py | 1 + .../fusion_woocommerce/models/woo_return.py | 1 + .../fusion_woocommerce/models/woo_shipment.py | 1 + .../fusion_woocommerce/models/woo_sync_log.py | 1 + .../fusion_woocommerce/models/woo_tax_map.py | 1 + .../views/woo_order_views.xml | 27 +++- 12 files changed, 171 insertions(+), 11 deletions(-) diff --git a/fusion-woo-odoo/fusion_woocommerce/models/woo_category_map.py b/fusion-woo-odoo/fusion_woocommerce/models/woo_category_map.py index 89530f5e..f2e411d5 100644 --- a/fusion-woo-odoo/fusion_woocommerce/models/woo_category_map.py +++ b/fusion-woo-odoo/fusion_woocommerce/models/woo_category_map.py @@ -5,6 +5,7 @@ class WooCategoryMap(models.Model): _name = 'woo.category.map' _description = 'WooCommerce Category Mapping' _order = 'odoo_category_id' + _rec_name = 'woo_category_name' instance_id = fields.Many2one('woo.instance', required=True, ondelete='cascade') odoo_category_id = fields.Many2one('product.category', string='Odoo Category') diff --git a/fusion-woo-odoo/fusion_woocommerce/models/woo_conflict.py b/fusion-woo-odoo/fusion_woocommerce/models/woo_conflict.py index 2f1ce317..0d279e05 100644 --- a/fusion-woo-odoo/fusion_woocommerce/models/woo_conflict.py +++ b/fusion-woo-odoo/fusion_woocommerce/models/woo_conflict.py @@ -9,6 +9,7 @@ _logger = logging.getLogger(__name__) class WooConflict(models.Model): _name = 'woo.conflict' _description = 'WooCommerce Sync Conflict' + _rec_name = 'field_name' instance_id = fields.Many2one('woo.instance', required=True, ondelete='cascade') conflict_type = fields.Selection([ diff --git a/fusion-woo-odoo/fusion_woocommerce/models/woo_customer.py b/fusion-woo-odoo/fusion_woocommerce/models/woo_customer.py index f75b93b3..b7977a6c 100644 --- a/fusion-woo-odoo/fusion_woocommerce/models/woo_customer.py +++ b/fusion-woo-odoo/fusion_woocommerce/models/woo_customer.py @@ -8,6 +8,7 @@ _logger = logging.getLogger(__name__) class WooCustomer(models.Model): _name = 'woo.customer' _description = 'WooCommerce Customer' + _rec_name = 'woo_email' instance_id = fields.Many2one('woo.instance', required=True, ondelete='cascade') partner_id = fields.Many2one('res.partner', required=True) diff --git a/fusion-woo-odoo/fusion_woocommerce/models/woo_instance.py b/fusion-woo-odoo/fusion_woocommerce/models/woo_instance.py index 75e7167a..ed76ffa1 100644 --- a/fusion-woo-odoo/fusion_woocommerce/models/woo_instance.py +++ b/fusion-woo-odoo/fusion_woocommerce/models/woo_instance.py @@ -686,13 +686,15 @@ class WooInstance(models.Model): # Create woo.order tracking record FIRST to prevent infinite retries # if action_confirm or invoicing fails later. + wc_status = wc_order.get('status', '') + odoo_state = self.env['woo.order'].WC_STATUS_TO_STATE.get(wc_status, 'confirmed') woo_order = self.env['woo.order'].create({ 'instance_id': self.id, 'sale_order_id': sale_order.id, 'woo_order_id': woo_order_id, 'woo_order_number': wc_order.get('number', str(woo_order_id)), - 'woo_status': wc_order.get('status', ''), - 'state': 'confirmed', + 'woo_status': wc_status if wc_status in dict(self.env['woo.order']._fields['woo_status'].selection) else False, + 'state': odoo_state, 'company_id': self.company_id.id, }) diff --git a/fusion-woo-odoo/fusion_woocommerce/models/woo_order.py b/fusion-woo-odoo/fusion_woocommerce/models/woo_order.py index 153433fb..778e9ada 100644 --- a/fusion-woo-odoo/fusion_woocommerce/models/woo_order.py +++ b/fusion-woo-odoo/fusion_woocommerce/models/woo_order.py @@ -1,7 +1,7 @@ import base64 import logging -from odoo import fields, models +from odoo import api, fields, models from odoo.exceptions import UserError _logger = logging.getLogger(__name__) @@ -10,12 +10,25 @@ _logger = logging.getLogger(__name__) class WooOrder(models.Model): _name = 'woo.order' _description = 'WooCommerce Order' + _inherit = ['mail.thread', 'mail.activity.mixin'] + _rec_name = 'display_name' + _order = 'id desc' + display_name = fields.Char(compute='_compute_display_name', store=True) instance_id = fields.Many2one('woo.instance', required=True, ondelete='cascade') sale_order_id = fields.Many2one('sale.order') woo_order_id = fields.Integer(index=True) - woo_order_number = fields.Char() - woo_status = fields.Char() + woo_order_number = fields.Char(string='WC Order #') + woo_status = fields.Selection([ + ('pending', 'Pending Payment'), + ('processing', 'Processing'), + ('on-hold', 'On Hold'), + ('completed', 'Completed'), + ('cancelled', 'Cancelled'), + ('refunded', 'Refunded'), + ('failed', 'Failed'), + ('trash', 'Trashed'), + ], string='WC Status', tracking=True) invoice_id = fields.Many2one('account.move') invoice_synced = fields.Boolean() company_id = fields.Many2one( @@ -27,9 +40,123 @@ class WooOrder(models.Model): ('shipped', 'Shipped'), ('completed', 'Completed'), ('cancelled', 'Cancelled'), - ], default='new') + ], default='new', tracking=True) + + WC_STATUS_TO_STATE = { + 'pending': 'new', + 'on-hold': 'new', + 'processing': 'confirmed', + 'completed': 'completed', + 'cancelled': 'cancelled', + 'refunded': 'cancelled', + 'failed': 'cancelled', + 'trash': 'cancelled', + } + + @api.onchange('woo_status') + def _onchange_woo_status(self): + if self.woo_status: + self.state = self.WC_STATUS_TO_STATE.get(self.woo_status, self.state) + + def _set_woo_status(self, wc_status): + """Set woo_status and auto-map to Odoo state.""" + vals = {} + if wc_status: + vals['woo_status'] = wc_status + mapped_state = self.WC_STATUS_TO_STATE.get(wc_status) + if mapped_state: + vals['state'] = mapped_state + if vals: + self.write(vals) shipment_ids = fields.One2many('woo.shipment', 'order_id') + delivery_count = fields.Integer(compute='_compute_delivery_count') + invoice_count = fields.Integer(compute='_compute_invoice_count') + + @api.depends('woo_order_number', 'sale_order_id', 'sale_order_id.name') + def _compute_display_name(self): + for rec in self: + parts = [] + if rec.woo_order_number: + parts.append('WC#%s' % rec.woo_order_number) + if rec.sale_order_id: + parts.append(rec.sale_order_id.name) + rec.display_name = ' — '.join(parts) if parts else 'WC Order #%s' % rec.id + + @api.depends('sale_order_id') + def _compute_delivery_count(self): + for rec in self: + if rec.sale_order_id: + rec.delivery_count = self.env['stock.picking'].search_count([ + ('origin', '=', rec.sale_order_id.name), + ]) + else: + rec.delivery_count = 0 + + @api.depends('sale_order_id') + def _compute_invoice_count(self): + for rec in self: + if rec.sale_order_id: + rec.invoice_count = self.env['account.move'].search_count([ + ('invoice_origin', '=', rec.sale_order_id.name), + ('move_type', 'in', ['out_invoice', 'out_refund']), + ]) + else: + rec.invoice_count = 0 + + def action_view_sale_order(self): + self.ensure_one() + if not self.sale_order_id: + return + return { + 'type': 'ir.actions.act_window', + 'res_model': 'sale.order', + 'res_id': self.sale_order_id.id, + 'views': [(False, 'form')], + } + + def action_view_deliveries(self): + self.ensure_one() + pickings = self.env['stock.picking'].search([ + ('origin', '=', self.sale_order_id.name), + ]) + if len(pickings) == 1: + return { + 'type': 'ir.actions.act_window', + 'res_model': 'stock.picking', + 'res_id': pickings.id, + 'views': [(False, 'form')], + } + return { + 'type': 'ir.actions.act_window', + 'name': 'Deliveries', + 'res_model': 'stock.picking', + 'view_mode': 'list,form', + 'domain': [('origin', '=', self.sale_order_id.name)], + } + + def action_view_invoices(self): + self.ensure_one() + invoices = self.env['account.move'].search([ + ('invoice_origin', '=', self.sale_order_id.name), + ('move_type', 'in', ['out_invoice', 'out_refund']), + ]) + if len(invoices) == 1: + return { + 'type': 'ir.actions.act_window', + 'res_model': 'account.move', + 'res_id': invoices.id, + 'views': [(False, 'form')], + } + return { + 'type': 'ir.actions.act_window', + 'name': 'Invoices', + 'res_model': 'account.move', + 'view_mode': 'list,form', + 'domain': [('invoice_origin', '=', self.sale_order_id.name), + ('move_type', 'in', ['out_invoice', 'out_refund'])], + } + # ------------------------------------------------------------------ # Push methods (Task 20) # ------------------------------------------------------------------ @@ -58,7 +185,7 @@ class WooOrder(models.Model): update_data['meta_data'] = meta client.update_order(self.woo_order_id, update_data) - self.woo_status = 'completed' + self._set_woo_status('completed') self.state = 'shipped' self.instance_id._log_sync( @@ -71,8 +198,7 @@ class WooOrder(models.Model): self.ensure_one() client = self.instance_id._get_client() client.update_order(self.woo_order_id, {'status': 'completed'}) - self.woo_status = 'completed' - self.state = 'completed' + self._set_woo_status('completed') self.instance_id._log_sync( 'order', 'odoo_to_woo', self.sale_order_id.name, diff --git a/fusion-woo-odoo/fusion_woocommerce/models/woo_pricelist_map.py b/fusion-woo-odoo/fusion_woocommerce/models/woo_pricelist_map.py index 0f033905..f483c4dd 100644 --- a/fusion-woo-odoo/fusion_woocommerce/models/woo_pricelist_map.py +++ b/fusion-woo-odoo/fusion_woocommerce/models/woo_pricelist_map.py @@ -4,6 +4,7 @@ from odoo import api, fields, models class WooPricelistMap(models.Model): _name = 'woo.pricelist.map' _description = 'WooCommerce Pricelist Mapping' + _rec_name = 'woo_role_name' instance_id = fields.Many2one('woo.instance', required=True, ondelete='cascade') pricelist_id = fields.Many2one('product.pricelist', required=True) diff --git a/fusion-woo-odoo/fusion_woocommerce/models/woo_product_map.py b/fusion-woo-odoo/fusion_woocommerce/models/woo_product_map.py index 2df7c98d..6cd6375a 100644 --- a/fusion-woo-odoo/fusion_woocommerce/models/woo_product_map.py +++ b/fusion-woo-odoo/fusion_woocommerce/models/woo_product_map.py @@ -14,6 +14,7 @@ _logger = logging.getLogger(__name__) class WooProductMap(models.Model): _name = 'woo.product.map' _description = 'WooCommerce Product Mapping' + _rec_name = 'woo_product_name' instance_id = fields.Many2one('woo.instance', required=True, ondelete='cascade') product_id = fields.Many2one('product.product') diff --git a/fusion-woo-odoo/fusion_woocommerce/models/woo_return.py b/fusion-woo-odoo/fusion_woocommerce/models/woo_return.py index 6b0feadb..53acf19c 100644 --- a/fusion-woo-odoo/fusion_woocommerce/models/woo_return.py +++ b/fusion-woo-odoo/fusion_woocommerce/models/woo_return.py @@ -9,6 +9,7 @@ _logger = logging.getLogger(__name__) class WooReturn(models.Model): _name = 'woo.return' _description = 'WooCommerce Return' + _rec_name = 'order_id' instance_id = fields.Many2one('woo.instance', required=True, ondelete='cascade') order_id = fields.Many2one('woo.order', required=True) diff --git a/fusion-woo-odoo/fusion_woocommerce/models/woo_shipment.py b/fusion-woo-odoo/fusion_woocommerce/models/woo_shipment.py index 9a4d19cd..72f4e94a 100644 --- a/fusion-woo-odoo/fusion_woocommerce/models/woo_shipment.py +++ b/fusion-woo-odoo/fusion_woocommerce/models/woo_shipment.py @@ -4,6 +4,7 @@ from odoo import fields, models class WooShipment(models.Model): _name = 'woo.shipment' _description = 'WooCommerce Shipment' + _rec_name = 'tracking_number' order_id = fields.Many2one('woo.order', required=True, ondelete='cascade') picking_id = fields.Many2one('stock.picking') diff --git a/fusion-woo-odoo/fusion_woocommerce/models/woo_sync_log.py b/fusion-woo-odoo/fusion_woocommerce/models/woo_sync_log.py index 4ce09116..39ccadd8 100644 --- a/fusion-woo-odoo/fusion_woocommerce/models/woo_sync_log.py +++ b/fusion-woo-odoo/fusion_woocommerce/models/woo_sync_log.py @@ -5,6 +5,7 @@ class WooSyncLog(models.Model): _name = 'woo.sync.log' _description = 'WooCommerce Sync Log' _order = 'create_date desc' + _rec_name = 'record_ref' instance_id = fields.Many2one('woo.instance', ondelete='cascade') sync_type = fields.Selection([ diff --git a/fusion-woo-odoo/fusion_woocommerce/models/woo_tax_map.py b/fusion-woo-odoo/fusion_woocommerce/models/woo_tax_map.py index 78360edf..042cb65a 100644 --- a/fusion-woo-odoo/fusion_woocommerce/models/woo_tax_map.py +++ b/fusion-woo-odoo/fusion_woocommerce/models/woo_tax_map.py @@ -4,6 +4,7 @@ from odoo import api, fields, models class WooTaxMap(models.Model): _name = 'woo.tax.map' _description = 'WooCommerce Tax Mapping' + _rec_name = 'woo_tax_class_name' instance_id = fields.Many2one('woo.instance', required=True, ondelete='cascade') tax_id = fields.Many2one('account.tax', string='Odoo Tax') diff --git a/fusion-woo-odoo/fusion_woocommerce/views/woo_order_views.xml b/fusion-woo-odoo/fusion_woocommerce/views/woo_order_views.xml index 24d39448..e8d07410 100644 --- a/fusion-woo-odoo/fusion_woocommerce/views/woo_order_views.xml +++ b/fusion-woo-odoo/fusion_woocommerce/views/woo_order_views.xml @@ -31,10 +31,32 @@ statusbar_visible="new,confirmed,shipped,completed"/> +
+ + + +
+
+

+ +

+
- - @@ -60,6 +82,7 @@
+