add queue for process sale with pack_id
This commit is contained in:
parent
0da441338a
commit
e33d950109
172
mercado_libre.py
172
mercado_libre.py
|
@ -12,6 +12,7 @@ from web_channel import SaleWebChannel
|
||||||
import json
|
import json
|
||||||
from .exceptions import NotProductFoundError, NotProductFound
|
from .exceptions import NotProductFoundError, NotProductFound
|
||||||
from trytond.i18n import gettext
|
from trytond.i18n import gettext
|
||||||
|
from trytond.exceptions import UserError
|
||||||
|
|
||||||
HEADERS = {
|
HEADERS = {
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
|
@ -181,72 +182,19 @@ class MercadoLibre(SaleWebChannel):
|
||||||
dev_sales.append(return_sale)
|
dev_sales.append(return_sale)
|
||||||
return dev_sales
|
return dev_sales
|
||||||
|
|
||||||
def _create_sale(self, sale_):
|
def process_pack(self, sales):
|
||||||
|
for sale in sales:
|
||||||
|
sale.state = 'confirmed'
|
||||||
|
sale.save()
|
||||||
|
|
||||||
|
def create_lines_sale(self, sale, sale_, freight=False):
|
||||||
_pool = Pool()
|
_pool = Pool()
|
||||||
Sale = _pool.get('sale.sale')
|
|
||||||
sales = Sale.search([
|
|
||||||
('reference', '=', str(sale_['id']))
|
|
||||||
])
|
|
||||||
# print(sales[0].number)
|
|
||||||
|
|
||||||
if sales:
|
|
||||||
if len(sales) == 1 and sale_['status'] == 'cancelled':
|
|
||||||
sale = sales[0]
|
|
||||||
if not sale.invoices:
|
|
||||||
self.cancel_sales([sale], sale.pack_id)
|
|
||||||
else:
|
|
||||||
dev_sales = self._return_sale(sale)
|
|
||||||
self._finish_sale(dev_sales[0], type='return')
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
SaleLine = _pool.get('sale.line')
|
SaleLine = _pool.get('sale.line')
|
||||||
Party = _pool.get('party.party')
|
|
||||||
Product = _pool.get('product.product')
|
Product = _pool.get('product.product')
|
||||||
User = _pool.get('res.user')
|
|
||||||
sfm_id = sale_['shipping']['id']
|
|
||||||
shipment_ = self.get_shipment_api(sfm_id)
|
|
||||||
if sale_.get('buyer'):
|
|
||||||
billing_info = self.get_billing_info_api(sale_['id'])
|
|
||||||
customer = sale_['buyer']
|
|
||||||
dom_party = [('id_reference', '=', str(customer['id']))]
|
|
||||||
if billing_info and billing_info['billing_info'].get('doc_number'):
|
|
||||||
dom_party = [('id_number', '=', str(billing_info['billing_info']['doc_number']))]
|
|
||||||
parties = Party.search(dom_party)
|
|
||||||
if parties:
|
|
||||||
party = parties[0]
|
|
||||||
else:
|
|
||||||
customer['receiver_address'] = shipment_['receiver_address']
|
|
||||||
customer['billing_info'] = billing_info['billing_info']
|
|
||||||
for dic in customer['billing_info']['additional_info']:
|
|
||||||
customer['billing_info'][dic.values()[0].lower()] = dic.values()[1]
|
|
||||||
customer['billing_info']['additional_info'].pop()
|
|
||||||
party = self._create_party(customer)
|
|
||||||
sale_items = sale_['order_items']
|
|
||||||
create_lines = []
|
create_lines = []
|
||||||
|
sale_items = sale_['order_items']
|
||||||
ctx = self._get_context()
|
ctx = self._get_context()
|
||||||
user_ = User(ctx['user'])
|
sfm_id = sale_['shipping']['id']
|
||||||
date_created = sale_['date_created'].split('T')
|
|
||||||
year, month, day = date_created[0].split('-')
|
|
||||||
sale_date = date(int(year), int(month), int(day))
|
|
||||||
with Transaction().set_user(ctx['user']):
|
|
||||||
sale, = Sale.create([{
|
|
||||||
'payment_term': 1,
|
|
||||||
'party': party.id,
|
|
||||||
'sale_date': sale_date,
|
|
||||||
'comment': shipment_['status'],
|
|
||||||
'state': 'draft',
|
|
||||||
'company': ctx['company'],
|
|
||||||
'currency': user_.company.currency.id,
|
|
||||||
'shop': user_.shop.id,
|
|
||||||
'reference': str(sale_['id']),
|
|
||||||
'invoice_address': Party.address_get(party, type='invoice'),
|
|
||||||
'shipment_address': Party.address_get(party, type='delivery'),
|
|
||||||
'description': 'VENTA WEB ',
|
|
||||||
'channel': self.id,
|
|
||||||
'invoice_type': self.invoice_type,
|
|
||||||
'pack_id': str(sale_['pack_id']) if sale_['pack_id'] else '',
|
|
||||||
}])
|
|
||||||
|
|
||||||
with Transaction().set_context(ctx):
|
with Transaction().set_context(ctx):
|
||||||
for line in sale_items:
|
for line in sale_items:
|
||||||
item = line['item']
|
item = line['item']
|
||||||
|
@ -256,9 +204,11 @@ class MercadoLibre(SaleWebChannel):
|
||||||
generic = False
|
generic = False
|
||||||
if sku_code.count('+') > 0:
|
if sku_code.count('+') > 0:
|
||||||
codes = sku_code.split('+')
|
codes = sku_code.split('+')
|
||||||
line['unit_price'] = Decimal(round((line['unit_price'] / 2), 2))
|
line['unit_price'] = Decimal(
|
||||||
|
round((line['unit_price'] / 2), 2))
|
||||||
else:
|
else:
|
||||||
codes = [sku_code]
|
codes = [sku_code]
|
||||||
|
|
||||||
products = Product.search([
|
products = Product.search([
|
||||||
('code', 'in', codes),
|
('code', 'in', codes),
|
||||||
('active', '=', True)
|
('active', '=', True)
|
||||||
|
@ -290,9 +240,10 @@ class MercadoLibre(SaleWebChannel):
|
||||||
'taxes': [('add', product.customer_taxes_used)],
|
'taxes': [('add', product.customer_taxes_used)],
|
||||||
'description': description,
|
'description': description,
|
||||||
})
|
})
|
||||||
if self.freight_product:
|
if freight and self.freight_product:
|
||||||
product = self.freight_product
|
product = self.freight_product
|
||||||
URI = 'https://api.mercadolibre.com/shipments/%s/costs?access_token=%s' % (sfm_id, self.access_token)
|
URI = 'https://api.mercadolibre.com/shipments/%s/costs?access_token=%s' % (
|
||||||
|
sfm_id, self.access_token)
|
||||||
result = self.get_response(URI).json()
|
result = self.get_response(URI).json()
|
||||||
shipping_amount = result['receiver']['cost']
|
shipping_amount = result['receiver']['cost']
|
||||||
create_lines.append({
|
create_lines.append({
|
||||||
|
@ -306,12 +257,97 @@ class MercadoLibre(SaleWebChannel):
|
||||||
'description': 'FLETE',
|
'description': 'FLETE',
|
||||||
})
|
})
|
||||||
SaleLine.create(create_lines)
|
SaleLine.create(create_lines)
|
||||||
|
return generic
|
||||||
|
|
||||||
|
def _create_sale(self, sale_):
|
||||||
|
_pool = Pool()
|
||||||
|
Sale = _pool.get('sale.sale')
|
||||||
|
|
||||||
|
if sale_.get('pack_id'):
|
||||||
|
sales = self.search([
|
||||||
|
('pack_id', '=', sale_['pack_id'])
|
||||||
|
])
|
||||||
|
if sales:
|
||||||
|
self.create_lines_sale(
|
||||||
|
sales[0], sale_, freight=False)
|
||||||
|
return False
|
||||||
|
sales = Sale.search([
|
||||||
|
('reference', '=', str(sale_['id']))
|
||||||
|
])
|
||||||
|
|
||||||
|
if sales:
|
||||||
|
if len(sales) == 1 and sale_['status'] == 'cancelled':
|
||||||
|
sale = sales[0]
|
||||||
|
if not sale.invoices:
|
||||||
|
self.cancel_sales([sale], sale.pack_id)
|
||||||
|
else:
|
||||||
|
dev_sales = self._return_sale(sale)
|
||||||
|
self._finish_sale(dev_sales[0], type='return')
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
Party = _pool.get('party.party')
|
||||||
|
User = _pool.get('res.user')
|
||||||
|
sfm_id = sale_['shipping']['id']
|
||||||
|
shipment_ = self.get_shipment_api(sfm_id)
|
||||||
|
if sale_.get('buyer'):
|
||||||
|
billing_info = self.get_billing_info_api(sale_['id'])
|
||||||
|
customer = sale_['buyer']
|
||||||
|
dom_party = [('id_reference', '=', str(customer['id']))]
|
||||||
|
if billing_info and billing_info['billing_info'].get('doc_number'):
|
||||||
|
dom_party = [('id_number', '=', str(
|
||||||
|
billing_info['billing_info']['doc_number']))]
|
||||||
|
parties = Party.search(dom_party)
|
||||||
|
if parties:
|
||||||
|
party = parties[0]
|
||||||
|
else:
|
||||||
|
customer['receiver_address'] = shipment_['receiver_address']
|
||||||
|
customer['billing_info'] = billing_info['billing_info']
|
||||||
|
for dic in customer['billing_info']['additional_info']:
|
||||||
|
customer['billing_info'][dic.values()[0].lower()
|
||||||
|
] = dic.values()[1]
|
||||||
|
try:
|
||||||
|
customer['billing_info']['additional_info'].pop()
|
||||||
|
except Exception as e:
|
||||||
|
msg = 'sin informacion de tercero' + e
|
||||||
|
raise UserError(
|
||||||
|
gettext('sale_web_channel.msg_billing_info', msg=msg))
|
||||||
|
party = self._create_party(customer)
|
||||||
|
ctx = self._get_context()
|
||||||
|
user_ = User(ctx['user'])
|
||||||
|
date_created = sale_['date_created'].split('T')
|
||||||
|
year, month, day = date_created[0].split('-')
|
||||||
|
sale_date = date(int(year), int(month), int(day))
|
||||||
|
with Transaction().set_user(ctx['user']):
|
||||||
|
sale, = Sale.create([{
|
||||||
|
'payment_term': 1,
|
||||||
|
'party': party.id,
|
||||||
|
'sale_date': sale_date,
|
||||||
|
'comment': shipment_['status'],
|
||||||
|
'state': 'draft',
|
||||||
|
'company': ctx['company'],
|
||||||
|
'currency': user_.company.currency.id,
|
||||||
|
'shop': user_.shop.id,
|
||||||
|
'reference': str(sale_['id']),
|
||||||
|
'invoice_address': Party.address_get(party, type='invoice'),
|
||||||
|
'shipment_address': Party.address_get(party, type='delivery'),
|
||||||
|
'description': 'VENTA WEB ',
|
||||||
|
'channel': self.id,
|
||||||
|
'invoice_type': self.invoice_type,
|
||||||
|
'pack_id': str(sale_['pack_id']) if sale_['pack_id'] else '',
|
||||||
|
}])
|
||||||
|
generic = self.create_lines_sale(
|
||||||
|
sale, sale_, freight=True)
|
||||||
sale.untaxed_amount_cache = sale.untaxed_amount
|
sale.untaxed_amount_cache = sale.untaxed_amount
|
||||||
if sale_['status'] == 'cancelled':
|
if sale_['status'] == 'cancelled':
|
||||||
sale.state = 'cancelled'
|
sale.state = 'cancelled'
|
||||||
|
elif sale_.get('pack_id'):
|
||||||
|
with Transaction().set_context(
|
||||||
|
queue_name='process_pack_id',
|
||||||
|
queue_scheduled_at=10):
|
||||||
|
self.__class__.__queue__.process_pack([sale])
|
||||||
else:
|
else:
|
||||||
Sale.quote([sale])
|
Sale.quote([sale])
|
||||||
if generic:
|
if not generic:
|
||||||
sale.state = 'confirmed'
|
sale.state = 'confirmed'
|
||||||
sale.save()
|
sale.save()
|
||||||
# if shipment_['status'] in ['shipped', 'delivered']:
|
# if shipment_['status'] in ['shipped', 'delivered']:
|
||||||
|
@ -417,7 +453,8 @@ class MercadoLibre(SaleWebChannel):
|
||||||
return response
|
return response
|
||||||
|
|
||||||
if len(sales) > 1:
|
if len(sales) > 1:
|
||||||
channel.upload_note(sale, 'Error, al generar factura orden duplicada')
|
channel.upload_note(
|
||||||
|
sale, 'Error, al generar factura orden duplicada')
|
||||||
return response
|
return response
|
||||||
|
|
||||||
if shipment_.get('tracking_number'):
|
if shipment_.get('tracking_number'):
|
||||||
|
@ -500,4 +537,5 @@ class MercadoLibre(SaleWebChannel):
|
||||||
request = json.dumps(params)
|
request = json.dumps(params)
|
||||||
response = requests.post(URI, headers=HEADERS, data=request)
|
response = requests.post(URI, headers=HEADERS, data=request)
|
||||||
if not response.status_code in [200, 201, 202]:
|
if not response.status_code in [200, 201, 202]:
|
||||||
self.send_mail_notification('error al crear nota en orden ' + sale.reference)
|
self.send_mail_notification(
|
||||||
|
'error al crear nota en orden ' + sale.reference)
|
||||||
|
|
|
@ -9,5 +9,8 @@ this repository contains the full copyright notices and license terms. -->
|
||||||
<record model="ir.message" id="msg_product_generic_not_found">
|
<record model="ir.message" id="msg_product_generic_not_found">
|
||||||
<field name="text">Product Generic Not Found, Verify in Configuration</field>
|
<field name="text">Product Generic Not Found, Verify in Configuration</field>
|
||||||
</record>
|
</record>
|
||||||
|
<record model="ir.message" id="msg_billing_info">
|
||||||
|
<field name="text">Error: "(msg)s"</field>
|
||||||
|
</record>
|
||||||
</data>
|
</data>
|
||||||
</tryton>
|
</tryton>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[tryton]
|
[tryton]
|
||||||
version=6.0.0
|
version=6.0.1
|
||||||
depends:
|
depends:
|
||||||
sale_pos
|
sale_pos
|
||||||
product_reference
|
product_reference
|
||||||
|
|
|
@ -52,9 +52,9 @@ class SaleWebChannel(Workflow, ModelSQL, ModelView):
|
||||||
_rec_name = 'name'
|
_rec_name = 'name'
|
||||||
name = fields.Char('Name Channel')
|
name = fields.Char('Name Channel')
|
||||||
channel_name = fields.Selection(CHANNELS,
|
channel_name = fields.Selection(CHANNELS,
|
||||||
'Channel', select=True, required=True, states=STATES)
|
'Channel', select=True, required=True, states=STATES)
|
||||||
company = fields.Many2One('company.company', 'Company', required=True,
|
company = fields.Many2One('company.company', 'Company', required=True,
|
||||||
states=STATES)
|
states=STATES)
|
||||||
shop = fields.Many2One('sale.shop', 'Shop', domain=[
|
shop = fields.Many2One('sale.shop', 'Shop', domain=[
|
||||||
('company', '=', Eval('company'))
|
('company', '=', Eval('company'))
|
||||||
], states=STATES)
|
], states=STATES)
|
||||||
|
@ -90,7 +90,7 @@ class SaleWebChannel(Workflow, ModelSQL, ModelView):
|
||||||
('finished', 'Finished'),
|
('finished', 'Finished'),
|
||||||
], 'State', select=True, readonly=True)
|
], 'State', select=True, readonly=True)
|
||||||
freight_product = fields.Many2One('product.product', 'Freight Product',
|
freight_product = fields.Many2One('product.product', 'Freight Product',
|
||||||
states=STATES)
|
states=STATES)
|
||||||
bonus_product = fields.Many2One('product.product', 'Bonus Product', states={
|
bonus_product = fields.Many2One('product.product', 'Bonus Product', states={
|
||||||
'invisible': (Eval('channel_name') != 'mercadolibre'),
|
'invisible': (Eval('channel_name') != 'mercadolibre'),
|
||||||
'readonly': (Eval('state') != 'draft')
|
'readonly': (Eval('state') != 'draft')
|
||||||
|
@ -111,7 +111,8 @@ class SaleWebChannel(Workflow, ModelSQL, ModelView):
|
||||||
'invisible': (Eval('channel_name') != 'mercadolibre'),
|
'invisible': (Eval('channel_name') != 'mercadolibre'),
|
||||||
'readonly': (Eval('state') != 'draft')
|
'readonly': (Eval('state') != 'draft')
|
||||||
})
|
})
|
||||||
template_notification = fields.Many2One('email.template', 'Template Notification')
|
template_notification = fields.Many2One(
|
||||||
|
'email.template', 'Template Notification')
|
||||||
api_key = fields.Char('Api Key', states={
|
api_key = fields.Char('Api Key', states={
|
||||||
'invisible': (Eval('channel_name') != 'shopify'),
|
'invisible': (Eval('channel_name') != 'shopify'),
|
||||||
})
|
})
|
||||||
|
@ -123,7 +124,7 @@ class SaleWebChannel(Workflow, ModelSQL, ModelView):
|
||||||
})
|
})
|
||||||
party = fields.Many2One('party.party', 'party', required=False)
|
party = fields.Many2One('party.party', 'party', required=False)
|
||||||
payment_term = fields.Many2One('account.invoice.payment_term',
|
payment_term = fields.Many2One('account.invoice.payment_term',
|
||||||
'Payment Term')
|
'Payment Term')
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def __setup__(cls):
|
def __setup__(cls):
|
||||||
|
@ -229,9 +230,9 @@ class SynchronizeChannelOrdersStart(ModelView):
|
||||||
('company', '=', Eval('company'))
|
('company', '=', Eval('company'))
|
||||||
])
|
])
|
||||||
channel = fields.Many2One('sale.web_channel', 'Channel', required=True,
|
channel = fields.Many2One('sale.web_channel', 'Channel', required=True,
|
||||||
domain=[
|
domain=[
|
||||||
('shop', '=', Eval('shop'))
|
('shop', '=', Eval('shop'))
|
||||||
])
|
])
|
||||||
operation = fields.Selection([
|
operation = fields.Selection([
|
||||||
('', ''),
|
('', ''),
|
||||||
('orders_for_day', 'Orders for day'),
|
('orders_for_day', 'Orders for day'),
|
||||||
|
@ -268,15 +269,16 @@ class SynchronizeChannelOrders(Wizard):
|
||||||
'Synchronize Channel Orders'
|
'Synchronize Channel Orders'
|
||||||
__name__ = 'sale_web_channel.synchronize_orders'
|
__name__ = 'sale_web_channel.synchronize_orders'
|
||||||
start = StateView('sale_web_channel.synchronize_orders.start',
|
start = StateView('sale_web_channel.synchronize_orders.start',
|
||||||
'sale_web_channel.synchronize_orders_view_form', [
|
'sale_web_channel.synchronize_orders_view_form', [
|
||||||
Button('Cancel', 'end', 'tryton-cancel'),
|
Button('Cancel', 'end', 'tryton-cancel'),
|
||||||
Button('Create', 'accept', 'tryton-ok', default=True),
|
Button('Create', 'accept',
|
||||||
])
|
'tryton-ok', default=True),
|
||||||
|
])
|
||||||
accept = StateTransition()
|
accept = StateTransition()
|
||||||
done = StateView('sale_web_channel.synchronize_orders.done',
|
done = StateView('sale_web_channel.synchronize_orders.done',
|
||||||
'sale_web_channel.synchronize_orders_done', [
|
'sale_web_channel.synchronize_orders_done', [
|
||||||
Button('Done', 'end', 'tryton-ok', default=True),
|
Button('Done', 'end', 'tryton-ok', default=True),
|
||||||
])
|
])
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def __setup__(cls):
|
def __setup__(cls):
|
||||||
|
@ -300,17 +302,20 @@ class SynchronizeChannelOrders(Wizard):
|
||||||
raise ErrorSynchronizingSale(
|
raise ErrorSynchronizingSale(
|
||||||
gettext('sale_web_channel.msg_error_synchronizing_sale', s=result))
|
gettext('sale_web_channel.msg_error_synchronizing_sale', s=result))
|
||||||
sale_created = channel._create_sale(result)
|
sale_created = channel._create_sale(result)
|
||||||
generic_code = self.start.channel.generic_product.code if self.start.channel.generic_product else None
|
if sale_created:
|
||||||
product_generic = [line.product.code for line in sale_created.lines if sale_created and line.product.code == generic_code and generic_code]
|
generic_code = self.start.channel.generic_product.code if self.start.channel.generic_product else None
|
||||||
if sale_created and \
|
product_generic = [
|
||||||
not sale_created.pack_id and \
|
line.product.code for line in sale_created.lines if line.product.code == generic_code and generic_code]
|
||||||
sale_created.comment in ['shipped', 'delivered'] and \
|
if not sale_created.pack_id and \
|
||||||
len(product_generic) < 1:
|
sale_created.comment in ['shipped', 'delivered'] and \
|
||||||
Sale.process([sale_created])
|
len(product_generic) < 1:
|
||||||
|
Sale.process([sale_created])
|
||||||
else:
|
else:
|
||||||
date_from = str(self.start.date) + 'T00:00:00.000-00:00'
|
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'
|
date_to = str(self.start.date + timedelta(days=1)
|
||||||
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)
|
) + '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()
|
result = MercadoLibre.get_response(URI).json()
|
||||||
|
|
||||||
for res in result['results']:
|
for res in result['results']:
|
||||||
|
@ -344,7 +349,7 @@ class SynchronizeChannelOrders(Wizard):
|
||||||
gettext('sale_web_channel.msg_error_synchronizing_sale', s=result))
|
gettext('sale_web_channel.msg_error_synchronizing_sale', s=result))
|
||||||
sale_created = channel._create_sale(result['orders'][0])
|
sale_created = channel._create_sale(result['orders'][0])
|
||||||
if sale_created and \
|
if sale_created and \
|
||||||
sale_created.description.count('fulfilled'):
|
sale_created.description.count('fulfilled'):
|
||||||
Sale.process([sale_created])
|
Sale.process([sale_created])
|
||||||
else:
|
else:
|
||||||
date_from = str(self.start.date) + 'T00:00:00.000-00:00'
|
date_from = str(self.start.date) + 'T00:00:00.000-00:00'
|
||||||
|
@ -394,15 +399,16 @@ class FinishInvoices(Wizard):
|
||||||
'Finish Invoices'
|
'Finish Invoices'
|
||||||
__name__ = 'sale_web_channel.finish_invoices'
|
__name__ = 'sale_web_channel.finish_invoices'
|
||||||
start = StateView('sale_web_channel.finish_invoices.start',
|
start = StateView('sale_web_channel.finish_invoices.start',
|
||||||
'sale_web_channel.finish_invoices_view_form', [
|
'sale_web_channel.finish_invoices_view_form', [
|
||||||
Button('Cancel', 'end', 'tryton-cancel'),
|
Button('Cancel', 'end', 'tryton-cancel'),
|
||||||
Button('Create', 'accept', 'tryton-ok', default=True),
|
Button('Create', 'accept',
|
||||||
])
|
'tryton-ok', default=True),
|
||||||
|
])
|
||||||
accept = StateTransition()
|
accept = StateTransition()
|
||||||
done = StateView('sale_web_channel.synchronize_orders.done',
|
done = StateView('sale_web_channel.synchronize_orders.done',
|
||||||
'sale_web_channel.synchronize_orders_done', [
|
'sale_web_channel.synchronize_orders_done', [
|
||||||
Button('Done', 'end', 'tryton-ok', default=True),
|
Button('Done', 'end', 'tryton-ok', default=True),
|
||||||
])
|
])
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def __setup__(cls):
|
def __setup__(cls):
|
||||||
|
|
Loading…
Reference in New Issue