Files
suite/connector_amazon_sp/models/stock_picking/common.py
2022-02-04 13:25:45 -08:00

148 lines
6.1 KiB
Python

# © 2021 Hibou Corp.
from base64 import b64encode
from odoo import api, models, fields, _
from odoo.addons.queue_job.job import job, related_action
from odoo.addons.component.core import Component
import logging
_logger = logging.getLogger(__name__)
class AmazonStockPicking(models.Model):
_name = 'amazon.stock.picking'
_inherit = 'amazon.binding'
_inherits = {'stock.picking': 'odoo_id'}
_description = 'Amazon Delivery Order'
odoo_id = fields.Many2one(comodel_name='stock.picking',
string='Stock Picking',
required=True,
ondelete='cascade')
amazon_order_id = fields.Many2one(comodel_name='amazon.sale.order',
string='Amazon Sale Order',
ondelete='set null')
@job(default_channel='root.amazon')
@related_action(action='related_action_unwrap_binding')
@api.multi
def export_picking_done(self):
""" Export a complete or partial delivery order. """
self.ensure_one()
self = self.sudo()
with self.backend_id.work_on(self._name) as work:
exporter = work.component(usage='record.exporter')
return exporter.run(self)
class StockPicking(models.Model):
_inherit = 'stock.picking'
amazon_bind_ids = fields.One2many(
comodel_name='amazon.stock.picking',
inverse_name='odoo_id',
string="Amazon Bindings",
)
def has_amazon_pii(self):
self.ensure_one()
partner = self.partner_id
if not partner or not partner.email:
return False
return partner.email.find('@marketplace.amazon.com') >= 0
class StockPickingAdapter(Component):
_name = 'amazon.stock.picking.adapter'
_inherit = 'amazon.adapter'
_apply_on = 'amazon.stock.picking'
def _api(self):
return self.api_instance.feeds()
def create(self, amazon_picking, carrier_code, carrier_name, shipping_method, tracking):
amazon_order = amazon_picking.amazon_order_id
# api_instance = self.api_instance
# feeds_api = self._api()
order_line_qty = self._process_picking_items(amazon_picking)
feed_root, _message = self._order_fulfillment_feed(amazon_picking, amazon_order, order_line_qty, carrier_code, carrier_name, shipping_method, tracking)
feed_data = self._feed_string(feed_root)
feed = self.env['amazon.feed'].create({
'backend_id': amazon_order.backend_id.id,
'type': 'POST_ORDER_FULFILLMENT_DATA',
'content_type': 'text/xml',
'data': b64encode(feed_data),
'amazon_stock_picking_id': amazon_picking.id,
})
feed.with_delay(priority=20).submit_feed()
_logger.info('Feed for Amazon Order %s for tracking number %s created.' % (amazon_order.external_id, tracking))
return True
def _process_picking_items(self, amazon_picking):
amazon_order_line_to_qty = {}
amazon_so_lines = amazon_picking.move_lines.mapped('sale_line_id.amazon_bind_ids')
for so_line in amazon_so_lines:
stock_moves = amazon_picking.move_lines.filtered(lambda sm: sm.sale_line_id.amazon_bind_ids in so_line and sm.quantity_done)
if stock_moves:
amazon_order_line_to_qty[so_line.external_id] = sum(stock_moves.mapped('quantity_done'))
return amazon_order_line_to_qty
def _order_fulfillment_feed(self, amazon_picking, amazon_order, order_line_qty, carrier_code, carrier_name, shipping_method, tracking):
root, message = self._feed('OrderFulfillment', amazon_order.backend_id)
order_fulfillment = self.ElementTree.SubElement(message, 'OrderFulfillment')
self.ElementTree.SubElement(order_fulfillment, 'AmazonOrderID').text = amazon_order.external_id
self.ElementTree.SubElement(order_fulfillment, 'FulfillmentDate').text = fields.Datetime.from_string(amazon_picking.create_date).isoformat()
fulfillment_data = self.ElementTree.SubElement(order_fulfillment, 'FulfillmentData')
self.ElementTree.SubElement(fulfillment_data, 'CarrierCode').text = carrier_code
self.ElementTree.SubElement(fulfillment_data, 'CarrierName').text = carrier_name
self.ElementTree.SubElement(fulfillment_data, 'ShippingMethod').text = shipping_method
self.ElementTree.SubElement(fulfillment_data, 'ShipperTrackingNumber').text = tracking
for num, qty in order_line_qty.items():
item = self.ElementTree.SubElement(order_fulfillment, 'Item')
self.ElementTree.SubElement(item, 'AmazonOrderItemCode').text = num
self.ElementTree.SubElement(item, 'Quantity').text = str(int(qty)) # always whole
return root, message
class AmazonBindingStockPickingListener(Component):
_name = 'amazon.binding.stock.picking.listener'
_inherit = 'base.event.listener'
_apply_on = ['amazon.stock.picking']
def on_record_create(self, record, fields=None):
record.with_delay(priority=10).export_picking_done()
class AmazonStockPickingListener(Component):
_name = 'amazon.stock.picking.listener'
_inherit = 'base.event.listener'
_apply_on = ['stock.picking']
def on_picking_dropship_done(self, record, picking_method):
return self.on_picking_out_done(record, picking_method)
def on_picking_out_done(self, record, picking_method):
"""
Create a ``amazon.stock.picking`` record. This record will then
be exported to Amazon.
:param picking_method: picking_method, can be 'complete' or 'partial'
:type picking_method: str
"""
sale = record.sale_id
if not sale:
return
if record.carrier_id.delivery_type == 'amazon_sp_mfn':
# buying postage through Amazon already marks it shipped.
return
for amazon_sale in sale.amazon_bind_ids:
self.env['amazon.stock.picking'].sudo().create({
'backend_id': amazon_sale.backend_id.id,
'odoo_id': record.id,
'amazon_order_id': amazon_sale.id,
})