- Replace _sync_orders placeholder with full WC order import pipeline - Add _sync_order_from_wc, _find_or_create_customer, _prepare_sale_order_vals, _prepare_order_line_vals, _prepare_shipping_line_vals helpers - Add push methods on woo.order: action_push_shipping, action_push_completed, action_push_invoice_pdf, action_push_delivery_pdf, _push_messages_to_wc - Override stock.picking button_validate to auto-create shipment records and push tracking/delivery PDFs to WooCommerce Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
172 lines
6.1 KiB
Python
172 lines
6.1 KiB
Python
import base64
|
|
import logging
|
|
|
|
from odoo import fields, models
|
|
from odoo.exceptions import UserError
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class WooOrder(models.Model):
|
|
_name = 'woo.order'
|
|
_description = 'WooCommerce Order'
|
|
|
|
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()
|
|
invoice_id = fields.Many2one('account.move')
|
|
invoice_synced = fields.Boolean()
|
|
company_id = fields.Many2one(
|
|
'res.company', required=True, default=lambda self: self.env.company,
|
|
)
|
|
state = fields.Selection([
|
|
('new', 'New'),
|
|
('confirmed', 'Confirmed'),
|
|
('shipped', 'Shipped'),
|
|
('completed', 'Completed'),
|
|
('cancelled', 'Cancelled'),
|
|
], default='new')
|
|
shipment_ids = fields.One2many('woo.shipment', 'order_id')
|
|
|
|
# ------------------------------------------------------------------
|
|
# Push methods (Task 20)
|
|
# ------------------------------------------------------------------
|
|
|
|
def action_push_shipping(self, tracking_number, carrier_id=False):
|
|
"""Push shipping/tracking info to WooCommerce and update status."""
|
|
self.ensure_one()
|
|
client = self.instance_id._get_client()
|
|
|
|
update_data = {
|
|
'status': 'completed',
|
|
}
|
|
|
|
# Build tracking meta
|
|
meta = [
|
|
{'key': '_tracking_number', 'value': tracking_number},
|
|
]
|
|
if carrier_id:
|
|
carrier = self.env['woo.shipping.carrier'].browse(carrier_id)
|
|
if carrier.exists():
|
|
meta.append({'key': '_tracking_provider', 'value': carrier.name})
|
|
if carrier.tracking_url:
|
|
url = carrier.tracking_url.replace('{tracking}', tracking_number)
|
|
meta.append({'key': '_tracking_url', 'value': url})
|
|
|
|
update_data['meta_data'] = meta
|
|
|
|
client.update_order(self.woo_order_id, update_data)
|
|
self.woo_status = 'completed'
|
|
self.state = 'shipped'
|
|
|
|
self.instance_id._log_sync(
|
|
'order', 'odoo_to_woo', self.sale_order_id.name,
|
|
'success', f'Shipping pushed with tracking: {tracking_number}',
|
|
)
|
|
|
|
def action_push_completed(self):
|
|
"""Mark WC order as completed."""
|
|
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.instance_id._log_sync(
|
|
'order', 'odoo_to_woo', self.sale_order_id.name,
|
|
'success', 'Order marked as completed in WC',
|
|
)
|
|
|
|
def action_push_invoice_pdf(self):
|
|
"""Render invoice PDF and push to WC via custom plugin endpoint."""
|
|
self.ensure_one()
|
|
if not self.invoice_id:
|
|
raise UserError("No invoice linked to this WC order.")
|
|
|
|
# Generate PDF report
|
|
report = self.env.ref('account.account_invoices')
|
|
pdf_content, _content_type = report._render_qweb_pdf(
|
|
report.id, [self.invoice_id.id]
|
|
)
|
|
pdf_b64 = base64.b64encode(pdf_content).decode('utf-8')
|
|
|
|
# Push to WC via order note or meta
|
|
try:
|
|
client = self.instance_id._get_client()
|
|
client.update_order(self.woo_order_id, {
|
|
'meta_data': [
|
|
{'key': '_odoo_invoice_ref', 'value': self.invoice_id.name},
|
|
{'key': '_odoo_invoice_pdf', 'value': pdf_b64},
|
|
]
|
|
})
|
|
self.invoice_synced = True
|
|
self.instance_id._log_sync(
|
|
'invoice', 'odoo_to_woo', self.invoice_id.name,
|
|
'success', 'Invoice PDF pushed to WC',
|
|
)
|
|
except Exception as e:
|
|
_logger.error("Failed to push invoice PDF to WC: %s", e)
|
|
self.instance_id._log_sync(
|
|
'invoice', 'odoo_to_woo', self.invoice_id.name,
|
|
'failed', str(e),
|
|
)
|
|
raise
|
|
|
|
def action_push_delivery_pdf(self, picking):
|
|
"""Render delivery slip PDF and push to WC."""
|
|
self.ensure_one()
|
|
report = self.env.ref('stock.action_report_delivery')
|
|
pdf_content, _content_type = report._render_qweb_pdf(
|
|
report.id, [picking.id]
|
|
)
|
|
pdf_b64 = base64.b64encode(pdf_content).decode('utf-8')
|
|
|
|
try:
|
|
client = self.instance_id._get_client()
|
|
client.update_order(self.woo_order_id, {
|
|
'meta_data': [
|
|
{'key': '_odoo_delivery_ref', 'value': picking.name},
|
|
{'key': '_odoo_delivery_pdf', 'value': pdf_b64},
|
|
]
|
|
})
|
|
self.instance_id._log_sync(
|
|
'order', 'odoo_to_woo', picking.name,
|
|
'success', 'Delivery PDF pushed to WC',
|
|
)
|
|
except Exception as e:
|
|
_logger.error("Failed to push delivery PDF to WC: %s", e)
|
|
|
|
def _push_messages_to_wc(self):
|
|
"""Extract customer-visible messages and push as WC order notes."""
|
|
self.ensure_one()
|
|
if not self.sale_order_id:
|
|
return
|
|
|
|
client = self.instance_id._get_client()
|
|
|
|
# Get messages from the sale order that are customer-visible
|
|
messages = self.env['mail.message'].search([
|
|
('res_id', '=', self.sale_order_id.id),
|
|
('model', '=', 'sale.order'),
|
|
('message_type', 'in', ['comment', 'email']),
|
|
('subtype_id.internal', '=', False),
|
|
], order='create_date asc')
|
|
|
|
for msg in messages:
|
|
note_body = msg.body or msg.preview or ''
|
|
if not note_body:
|
|
continue
|
|
try:
|
|
# WC order notes endpoint
|
|
client.post(f'orders/{self.woo_order_id}/notes', {
|
|
'note': note_body,
|
|
'customer_note': True,
|
|
})
|
|
except Exception as e:
|
|
_logger.warning(
|
|
"Failed to push message to WC order %s: %s",
|
|
self.woo_order_id, e,
|
|
)
|