add wizard synchronize orders for channel

This commit is contained in:
Camilo Sarmiento 2020-09-29 18:45:58 -05:00
parent 712dbca907
commit 836b57e23d
9 changed files with 268 additions and 37 deletions

View File

@ -13,12 +13,15 @@ def register():
mercado_libre.MercadoLibre,
sale.Sale,
sale.SaleForChannelStart,
web_channel.SynchronizeChannelOrdersStart,
web_channel.SynchronizeChannelOrdersDone,
party.Party,
product.Template,
module='sale_web_channel', type_='model')
Pool.register(
sale.SaleUploadInvoice,
sale.SaleForChannel,
web_channel.SynchronizeChannelOrders,
module='sale_web_channel', type_='wizard')
Pool.register(
sale.SaleForChannelReport,

View File

@ -46,6 +46,10 @@ msgctxt "error:sale.web_channel.mercado_libre:"
msgid "Product Not Found"
msgstr ""
msgctxt "error:sale_web_channel.synchronize_orders:"
msgid "%s"
msgstr "%s"
msgctxt "field:party.party,id_reference:"
msgid "ID Reference Api"
msgstr ""
@ -110,6 +114,10 @@ msgctxt "field:sale.web_channel,channel_name:"
msgid "Channel"
msgstr "Canal"
msgctxt "field:sale.web_channel,company:"
msgid "Company"
msgstr "Empresa"
msgctxt "field:sale.web_channel,create_date:"
msgid "Create Date"
msgstr "Fecha de Creación"
@ -154,6 +162,14 @@ msgctxt "field:sale.web_channel,secret_key:"
msgid "Secret Key"
msgstr ""
msgctxt "field:sale.web_channel,seller_id:"
msgid "Seller ID"
msgstr ""
msgctxt "field:sale.web_channel,shop:"
msgid "Shop"
msgstr "Tienda"
msgctxt "field:sale.web_channel,state:"
msgid "State"
msgstr "Estado"
@ -190,6 +206,10 @@ msgctxt "field:sale.web_channel.mercado_libre,channel_name:"
msgid "Channel"
msgstr "Canal"
msgctxt "field:sale.web_channel.mercado_libre,company:"
msgid "Company"
msgstr "Empresa"
msgctxt "field:sale.web_channel.mercado_libre,create_date:"
msgid "Create Date"
msgstr "Fecha de Creación"
@ -234,6 +254,14 @@ msgctxt "field:sale.web_channel.mercado_libre,secret_key:"
msgid "Secret Key"
msgstr ""
msgctxt "field:sale.web_channel.mercado_libre,seller_id:"
msgid "Seller ID"
msgstr ""
msgctxt "field:sale.web_channel.mercado_libre,shop:"
msgid "Shop"
msgstr "Tienda"
msgctxt "field:sale.web_channel.mercado_libre,state:"
msgid "State"
msgstr "Estado"
@ -278,6 +306,42 @@ msgctxt "field:sale_web_channel.sale_for_channel.start,start_date:"
msgid "Start Date"
msgstr "Inicio"
msgctxt "field:sale_web_channel.synchronize_orders.done,id:"
msgid "ID"
msgstr "UP"
msgctxt "field:sale_web_channel.synchronize_orders.done,result:"
msgid "Result"
msgstr "Resultado"
msgctxt "field:sale_web_channel.synchronize_orders.start,channel:"
msgid "Channel"
msgstr "Canal"
msgctxt "field:sale_web_channel.synchronize_orders.start,company:"
msgid "Company"
msgstr "Empresa"
msgctxt "field:sale_web_channel.synchronize_orders.start,date:"
msgid "Date"
msgstr "Fecha Transacción"
msgctxt "field:sale_web_channel.synchronize_orders.start,id:"
msgid "ID"
msgstr "UP"
msgctxt "field:sale_web_channel.synchronize_orders.start,operation:"
msgid "Operation"
msgstr "Operación"
msgctxt "field:sale_web_channel.synchronize_orders.start,order_id:"
msgid "Order ID"
msgstr "Order ID"
msgctxt "field:sale_web_channel.synchronize_orders.start,shop:"
msgid "Shop"
msgstr "Tienda"
msgctxt "model:ir.action,name:act_sale_upload_invoice"
msgid "Sale Upload Invoice"
msgstr "Subir Factura"
@ -290,6 +354,10 @@ msgctxt "model:ir.action,name:sale_for_channel_report"
msgid "Sale For Channel"
msgstr "Ventas Por Canal"
msgctxt "model:ir.action,name:synchronize_orders_wizard"
msgid "Synchronize Channel Orders"
msgstr "Sincronizar Ordenes por Canal"
msgctxt "model:ir.action,name:wizard_sale_for_channel"
msgid "Sale For Channel Report"
msgstr "Ventas Por Canal"
@ -298,6 +366,10 @@ msgctxt "model:ir.ui.menu,name:menu_sale_for_channel"
msgid "Sale For Channel Report"
msgstr "Ventas Por Canal"
msgctxt "model:ir.ui.menu,name:menu_synchronize_orders"
msgid "Synchronize Channel Orders"
msgstr "Sincronizar Ordenes por Canal"
msgctxt "model:ir.ui.menu,name:menu_web_channel"
msgid "Channels"
msgstr "Canales"
@ -314,6 +386,14 @@ msgctxt "model:sale_web_channel.sale_for_channel.start,name:"
msgid "Sale For Channel Start"
msgstr "Ventas Por Canal"
msgctxt "model:sale_web_channel.synchronize_orders.done,name:"
msgid "Synchronize Channel Orders Done"
msgstr "Sincronizar Ordenes por Canal"
msgctxt "model:sale_web_channel.synchronize_orders.start,name:"
msgid "Synchronize Channel orders Start"
msgstr "Sincronizar Ordenes por Canal"
msgctxt "report:sale_web_channel.sale_for_channel_report:"
msgid "$"
msgstr "$"
@ -666,6 +746,18 @@ msgctxt "selection:sale.web_channel.mercado_libre,status_token:"
msgid "Expired"
msgstr "Vencido"
msgctxt "selection:sale_web_channel.synchronize_orders.start,operation:"
msgid ""
msgstr ""
msgctxt "selection:sale_web_channel.synchronize_orders.start,operation:"
msgid "Especific Orders"
msgstr "Orden Especifica"
msgctxt "selection:sale_web_channel.synchronize_orders.start,operation:"
msgid "Orders for day"
msgstr "Ordenes Por Día"
msgctxt "view:sale.web_channel:"
msgid "Active"
msgstr "Activo"
@ -685,3 +777,15 @@ msgstr "Cancelar"
msgctxt "wizard_button:sale_web_channel.sale_for_channel,start,print_:"
msgid "Print"
msgstr "Imprimir"
msgctxt "wizard_button:sale_web_channel.synchronize_orders,done,end:"
msgid "Done"
msgstr "Terminado"
msgctxt "wizard_button:sale_web_channel.synchronize_orders,start,accept:"
msgid "Create"
msgstr "Crear"
msgctxt "wizard_button:sale_web_channel.synchronize_orders,start,end:"
msgid "Cancel"
msgstr "Cancelar"

View File

@ -274,10 +274,13 @@ class MercadoLibre(SaleWebChannel):
sale.untaxed_amount_cache = sale.untaxed_amount
if sale_['status'] == 'cancelled':
sale.state = 'cancel'
sale.save()
else:
Sale.quote([sale])
sale.state = 'confirmed'
sale.save()
sale.save()
if shipment_['status'] in ['shipped', 'delivered']:
self._finish_sale(sale)
return True
def _get_shipment_amount(self, order_id, shipment={}):
@ -288,8 +291,6 @@ class MercadoLibre(SaleWebChannel):
shipping_amount = 0
if sale_.get('payments'):
shipping_amount = sale_['payments'][0]['shipping_cost']
# if shipping_amount == 0 and shipment.get('shipping_option'):
# shipping_amount = shipment['shipping_option']['list_cost']
return shipping_amount
def get_access_token(self, refresh_token, client_id, client_secret):
@ -309,7 +310,8 @@ class MercadoLibre(SaleWebChannel):
res = response.json()
return res['access_token'], res['refresh_token']
def get_response(self, URI, params={}):
@classmethod
def get_response(cls, URI, params={}):
headers = {
'Accept': 'application/json',
'Content-type': 'application/json'
@ -352,8 +354,9 @@ class MercadoLibre(SaleWebChannel):
access_token, refresh_token, client_id, client_secret = channel._validate_token()
if data.get('resource') and data['resource'].count('orders'):
order_id = str(data['resource'].replace('/orders/', ''))
URI = 'https://api.mercadolibre.com/orders/%s?access_token=%s' % (order_id, access_token)
result = channel.get_response(URI).json()
URI = 'https://api.mercadolibre.com/orders/%s?access_token=%s' % (
order_id, access_token)
result = cls.get_response(URI).json()
res = channel._create_sale(result)
if res:
response = {
@ -413,8 +416,6 @@ class MercadoLibre(SaleWebChannel):
if not invoice.cufe:
return
Invoice.post([invoice])
# cursor = Transaction().connection.cursor()
# cursor.execute('UPDATE account_invoice set shop=%s where id=%s' % (ctx['shop'], invoice.id))
self.upload_invoice(sale)
def process_sale_pack(self, sale):
@ -427,28 +428,3 @@ class MercadoLibre(SaleWebChannel):
'state': 'processing',
'invoice_number': invoice_number
})
# def _create_invoice_pack(self, sale, type):
# invoice = sale._get_invoice_sale()
# Sale = Pool().get('sale.sale')
# sales = Sale.search([
# ('pack_id', '=', sale.pack_id)
# ])
# lines = []
# for sale in sales:
# if type == 'return' and sale.total_amount > 0:
# continue
# elif type == 'invoice' and sale.total_amount < 0:
# continue
# for ln in sale.lines:
# lines.append(ln.get_invoice_line())
# lines = list(chain(*lines))
# if lines:
# if getattr(invoice, 'lines', None):
# lines = list(invoice.lines) + lines
# invoice.lines = lines
# invoice.shop = None
# invoice.save()
# invoice.update_taxes([invoice])
# return invoice

View File

@ -4,10 +4,16 @@ The COPYRIGHT file at the top level of this repository contains the full copyrig
<form>
<label name="channel_name"/>
<field name="channel_name"/>
<label name="company"/>
<field name="company"/>
<label name="app_id"/>
<field name="app_id"/>
<label name="shop"/>
<field name="shop"/>
<label name="secret_key"/>
<field name="secret_key"/>
<label name="seller_id"/>
<field name="seller_id"/>
<label name="redirect_uri"/>
<field name="redirect_uri"/>
<label name="authorization_code"/>
@ -28,8 +34,6 @@ The COPYRIGHT file at the top level of this repository contains the full copyrig
<field name="bonus_product"/>
<label name="invoice_type"/>
<field name="invoice_type"/>
<!-- <label name="minimal_amount_freight"/>
<field name="minimal_amount_freight"/> -->
<group col="6" colspan="4" id="state_buttons">
<label name="state"/>
<field name="state"/>

View File

@ -3,6 +3,7 @@
The COPYRIGHT file at the top level of this repository contains the full copyright notices and license terms. -->
<tree >
<field name="channel_name"/>
<field name="shop"/>
<field name="redirect_uri"/>
<field name="access_token"/>
<field name="refresh_token"/>

View File

@ -0,0 +1,7 @@
<?xml version="1.0"?>
<!-- This file is part sale_shop module for Tryton.
The COPYRIGHT file at the top level of this repository contains the full copyright notices and license terms. -->
<form>
<label name="result"/>
<field name="result"/>
</form>

View File

@ -0,0 +1,17 @@
<?xml version="1.0"?>
<!-- This file is part sale_shop module for Tryton.
The COPYRIGHT file at the top level of this repository contains the full copyright notices and license terms. -->
<form>
<label name="company"/>
<field name="company" widget="selection"/>
<label name="shop"/>
<field name="shop" widget="selection"/>
<label name="channel"/>
<field name="channel" widget="selection"/>
<label name="operation"/>
<field name="operation"/>
<label name="order_id"/>
<field name="order_id"/>
<label name="date"/>
<field name="date"/>
</form>

View File

@ -4,11 +4,14 @@
# the full copyright notices and license terms.
from trytond.model import Workflow, ModelView, ModelSQL, fields
from trytond.pyson import Eval
from datetime import datetime
from datetime import datetime, timedelta
from trytond.pool import Pool
import requests
from trytond.wizard import (Wizard, StateTransition, StateView, Button)
from trytond.transaction import Transaction
__all__ = ['SaleWebChannel']
__all__ = ['SaleWebChannel', 'SynchronizeChannelOrdersStart',
'SynchronizeChannelOrders', 'SynchronizeChannelOrdersDone']
STATES = {
'readonly': (Eval('state') != 'draft')
@ -34,12 +37,19 @@ TYPE_INVOICE = [
('92', 'Nota Débito Eléctronica'),
]
ORDERS_CREATED = 0
class SaleWebChannel(Workflow, ModelSQL, ModelView):
'Web Channel'
__name__ = 'sale.web_channel'
_rec_name = 'channel_name'
channel_name = fields.Selection(CHANNELS, 'Channel', select=True,
required=True, states=STATES)
company = fields.Many2One('company.company', 'Company', required=True,
states=STATES)
shop = fields.Many2One('sale.shop', 'Shop', required=True, domain=[
('company', '=', Eval('company'))
], states=STATES)
secret_key = fields.Char('Secret Key', states=STATES)
app_id = fields.Char('Application ID', states=STATES)
redirect_uri = fields.Char('Redirect URI', states=STATES)
@ -63,6 +73,11 @@ class SaleWebChannel(Workflow, ModelSQL, ModelView):
report = fields.Many2One('ir.action.report', 'Report', states=STATES)
invoice_type = fields.Selection(TYPE_INVOICE, 'Type Invoice',
states=STATES)
seller_id = fields.Char('Seller ID', states={
'invisible': (Eval('channel_name') != 'mercadolibre'),
'readonly': (Eval('state') != 'draft')
})
@classmethod
def __setup__(cls):
@ -85,6 +100,10 @@ class SaleWebChannel(Workflow, ModelSQL, ModelView):
},
})
@staticmethod
def default_company():
return Transaction().context.get('company')
@classmethod
def import_data(cls, fields_names, data):
pool = Pool()
@ -176,3 +195,85 @@ class SaleWebChannel(Workflow, ModelSQL, ModelView):
report = Report.execute([record.id], {'id': record.id})
ext, data, filename, file_name = report
return data
class SynchronizeChannelOrdersStart(ModelView):
'Synchronize Channel orders Start'
__name__ = 'sale_web_channel.synchronize_orders.start'
company = fields.Many2One('company.company', 'Company', required=True)
shop = fields.Many2One('sale.shop', 'Shop', required=True, domain=[
('company', '=', Eval('company'))
])
channel = fields.Many2One('sale.web_channel', 'Channel', required=True, domain=[
('shop', '=', Eval('shop'))
])
operation = fields.Selection([
('', ''),
('orders_for_day', 'Orders for day'),
('especific_order', 'Especific Orders')
], 'Operation', required=True)
order_id = fields.Char('Order ID', states={
'invisible': (Eval('operation') != 'especific_order'),
'required': (Eval('operation') == 'especific_order'),
})
date = fields.Date('Date', states={
'invisible': (Eval('operation') != 'orders_for_day'),
'required': (Eval('operation') == 'orders_for_day'),
})
@staticmethod
def default_company():
return Transaction().context.get('company')
class SynchronizeChannelOrders(Wizard):
'Synchronize Channel Orders'
__name__ = 'sale_web_channel.synchronize_orders'
start = StateView('sale_web_channel.synchronize_orders.start',
'sale_web_channel.synchronize_orders_view_form', [
Button('Cancel', 'end', 'tryton-cancel'),
Button('Create', 'accept', 'tryton-ok', default=True),
])
accept = StateTransition()
done = StateView('sale_web_channel.synchronize_orders.done',
'sale_web_channel.synchronize_orders_done', [
Button('Done', 'end', 'tryton-ok', default=True),
])
@classmethod
def __setup__(cls):
super(SynchronizeChannelOrders, cls).__setup__()
cls._error_messages.update({
'error': ('%s'),
})
def transition_accept(self):
pool = Pool()
channel = self.start.channel
operation = self.start.operation
if channel.channel_name == 'mercadolibre':
MercadoLibre = pool.get('sale.web_channel.mercado_libre')
if operation == 'especific_order':
order_id = self.start.order_id
res = MercadoLibre.request_api({"resource":"/orders/" + order_id})
if not res:
self.raise_user_error('error', res)
else:
date_from = str(self.start.date) + 'T00:00:00.000-00:00'
date_to = str(self.start.date + timedelta(days=1)) + 'T00:00:00.000-00:00'
URI = 'https://api.mercadolibre.com/orders/search?seller=%s&order.date_created.from=%s&order.date_created.to=%s&access_token=%s&order.status=paid' % (channel.seller_id, date_from, date_to, channel.access_token)
result = MercadoLibre.get_response(URI).json()
for sale in result['results']:
channel = MercadoLibre(channel)
res = channel._create_sale(sale)
return 'done'
class SynchronizeChannelOrdersDone(ModelView):
'Synchronize Channel Orders Done'
__name__ = 'sale_web_channel.synchronize_orders.done'
result = fields.Char('Result', readonly=True)
@staticmethod
def default_result():
return 'successful synchronization'

View File

@ -31,5 +31,23 @@ The COPYRIGHT file at the top level of this repository contains the full copyrig
<menuitem action="act_sale_web_channel" parent="sale.menu_configuration"
id="menu_web_channel" sequence="90"/>
<record model="ir.action.wizard" id="synchronize_orders_wizard">
<field name="name">Synchronize Channel Orders</field>
<field name="wiz_name">sale_web_channel.synchronize_orders</field>
</record>
<record model="ir.ui.view" id="synchronize_orders_view_form">
<field name="model">sale_web_channel.synchronize_orders.start</field>
<field name="type">form</field>
<field name="name">synchronize_orders_view_form</field>
</record>
<record model="ir.ui.view" id="synchronize_orders_done">
<field name="model">sale_web_channel.synchronize_orders.done</field>
<field name="type">form</field>
<field name="name">synchronize_orders_done</field>
</record>
<menuitem action="synchronize_orders_wizard" parent="sale.menu_sale"
id="menu_synchronize_orders" sequence="100"/>
</data>
</tryton>