mirror of
https://gitlab.com/hibou-io/hibou-odoo/suite.git
synced 2025-01-20 12:37:31 +02:00
Merge branch 'fix/12.0/connector_opencart__date_based_search' into '12.0-test'
fix/12.0/connector_opencart__date_based_search into 12.0-test See merge request hibou-io/hibou-odoo/suite!958
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
'name': 'Opencart Connector',
|
'name': 'Opencart Connector',
|
||||||
'version': '12.0.1.2.0',
|
'version': '12.0.1.3.0',
|
||||||
'category': 'Connector',
|
'category': 'Connector',
|
||||||
'depends': [
|
'depends': [
|
||||||
'account',
|
'account',
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
import requests
|
import requests
|
||||||
from urllib.parse import urlencode
|
from urllib.parse import urlencode
|
||||||
from json import loads, dumps
|
from json import loads, dumps
|
||||||
|
from json.decoder import JSONDecodeError
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
@@ -52,7 +53,10 @@ class Opencart:
|
|||||||
elif method == 'PUT' or method == 'POST':
|
elif method == 'PUT' or method == 'POST':
|
||||||
result_text = self.session.put(url, data=body, headers=headers).text
|
result_text = self.session.put(url, data=body, headers=headers).text
|
||||||
_logger.debug('raw_text: ' + str(result_text))
|
_logger.debug('raw_text: ' + str(result_text))
|
||||||
return loads(result_text)
|
try:
|
||||||
|
return loads(result_text)
|
||||||
|
except JSONDecodeError:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
class Resource:
|
class Resource:
|
||||||
@@ -75,10 +79,13 @@ class Orders(Resource):
|
|||||||
|
|
||||||
path = 'orders'
|
path = 'orders'
|
||||||
|
|
||||||
def all(self, id_larger_than=None):
|
def all(self, id_larger_than=None, modified_from=None):
|
||||||
url = self.url
|
url = self.url
|
||||||
if id_larger_than:
|
if id_larger_than:
|
||||||
url += '/id_larger_than/%s' % id_larger_than
|
url += '/id_larger_than/%s' % id_larger_than
|
||||||
|
if modified_from:
|
||||||
|
# TODO remove details if it gets into main route
|
||||||
|
url += 'details/modified_from/%s' % modified_from
|
||||||
return self.connection.send_request(method='GET', url=url)
|
return self.connection.send_request(method='GET', url=url)
|
||||||
|
|
||||||
def get(self, id):
|
def get(self, id):
|
||||||
@@ -97,7 +104,6 @@ class Orders(Resource):
|
|||||||
))
|
))
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
def cancel(self, id):
|
def cancel(self, id):
|
||||||
url = self.connection.base_url + ('order_status/%s' % id)
|
url = self.connection.base_url + ('order_status/%s' % id)
|
||||||
return self.connection.send_request(method='POST', url=url, body=self.get_status_payload('Canceled'))
|
return self.connection.send_request(method='POST', url=url, body=self.get_status_payload('Canceled'))
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
from odoo import api, fields, models, _
|
from odoo import api, fields, models, _
|
||||||
from odoo.exceptions import UserError
|
from odoo.exceptions import UserError
|
||||||
@@ -69,8 +70,17 @@ class OpencartBackend(models.Model):
|
|||||||
product_categ_id = fields.Many2one(comodel_name='product.category', string='Product Category',
|
product_categ_id = fields.Many2one(comodel_name='product.category', string='Product Category',
|
||||||
help='Default product category for newly created products.')
|
help='Default product category for newly created products.')
|
||||||
|
|
||||||
|
# renamed, and not used when searching orders anymore
|
||||||
import_orders_after_id = fields.Integer(
|
import_orders_after_id = fields.Integer(
|
||||||
string='Import sale orders after id',
|
string='Highest Order ID',
|
||||||
|
)
|
||||||
|
# Note that Opencart may not return timestamps in UTC
|
||||||
|
import_orders_after_date = fields.Datetime(
|
||||||
|
string='Import Orders Modified After',
|
||||||
|
)
|
||||||
|
server_offset_hours = fields.Float(
|
||||||
|
string='Opencart Server Timezone Offset',
|
||||||
|
help='E.g. US Pacific is -8.0, the important thing is to either not change this during DST or to adjust the import_orders_after_date field at the same time.',
|
||||||
)
|
)
|
||||||
|
|
||||||
so_require_product_setup = fields.Boolean(string='SO Require Product Setup',
|
so_require_product_setup = fields.Boolean(string='SO Require Product Setup',
|
||||||
@@ -134,14 +144,16 @@ class OpencartBackend(models.Model):
|
|||||||
backends = self.search([
|
backends = self.search([
|
||||||
('base_url', '!=', False),
|
('base_url', '!=', False),
|
||||||
('restadmin_token', '!=', False),
|
('restadmin_token', '!=', False),
|
||||||
('import_orders_after_id', '!=', False),
|
('import_orders_after_date', '!=', False),
|
||||||
('scheduler_order_import', '=', True),
|
('scheduler_order_import', '=', True),
|
||||||
])
|
])
|
||||||
return backends.import_sale_orders()
|
return backends.import_sale_orders()
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def import_sale_orders(self):
|
def import_sale_orders(self):
|
||||||
self._import_after_id('opencart.sale.order', 'import_orders_after_id')
|
# self._import_after_id('opencart.sale.order', 'import_orders_after_id')
|
||||||
|
# import_orders_after_date
|
||||||
|
self._import_sale_orders_after_date()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
@@ -152,3 +164,28 @@ class OpencartBackend(models.Model):
|
|||||||
backend,
|
backend,
|
||||||
filters={'after_id': after_id}
|
filters={'after_id': after_id}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def _import_sale_orders_after_date(self):
|
||||||
|
for backend in self:
|
||||||
|
date = backend.date_to_opencart(backend.import_orders_after_date)
|
||||||
|
date = str(date).replace(' ', 'T')
|
||||||
|
self.env['opencart.sale.order'].with_delay().import_batch(
|
||||||
|
backend,
|
||||||
|
filters={'modified_from': date}
|
||||||
|
)
|
||||||
|
|
||||||
|
def date_to_opencart(self, date):
|
||||||
|
# date provided should be UTC and will be converted to Opencart's dates
|
||||||
|
return self._date_plus_hours(date, self.server_offset_hours or 0)
|
||||||
|
|
||||||
|
def date_to_odoo(self, date):
|
||||||
|
# date provided should be in Opencart's TZ, converted to UTC
|
||||||
|
return self._date_plus_hours(date, -(self.server_offset_hours or 0))
|
||||||
|
|
||||||
|
def _date_plus_hours(self, date, hours):
|
||||||
|
if not hours:
|
||||||
|
return date
|
||||||
|
if isinstance(date, str):
|
||||||
|
date = fields.Datetime.from_string(date)
|
||||||
|
return date + timedelta(hours=self.server_offset_hours)
|
||||||
|
|||||||
@@ -96,7 +96,12 @@ class SaleOrderAdapter(Component):
|
|||||||
|
|
||||||
def search(self, filters=None):
|
def search(self, filters=None):
|
||||||
api_instance = self.api_instance
|
api_instance = self.api_instance
|
||||||
orders_response = api_instance.orders.all(id_larger_than=filters.get('after_id'))
|
api_filters = {}
|
||||||
|
if 'after_id' in filters:
|
||||||
|
api_filters['id_larger_than'] = filters['after_id']
|
||||||
|
if 'modified_from' in filters:
|
||||||
|
api_filters['modified_from'] = filters['modified_from']
|
||||||
|
orders_response = api_instance.orders.all(**api_filters)
|
||||||
if 'error' in orders_response and orders_response['error']:
|
if 'error' in orders_response and orders_response['error']:
|
||||||
raise ValidationError(str(orders_response))
|
raise ValidationError(str(orders_response))
|
||||||
|
|
||||||
@@ -105,7 +110,7 @@ class SaleOrderAdapter(Component):
|
|||||||
|
|
||||||
orders = orders_response['data']
|
orders = orders_response['data']
|
||||||
# Note that `store_id is None` is checked as it may not be in the output.
|
# Note that `store_id is None` is checked as it may not be in the output.
|
||||||
return map(lambda o: (o['order_id'], o.get('store_id', None)), orders)
|
return map(lambda o: (o['order_id'], o.get('store_id', None), o.get('date_modified') or o.get('date_added')), orders)
|
||||||
|
|
||||||
def read(self, id):
|
def read(self, id):
|
||||||
api_instance = self.api_instance
|
api_instance = self.api_instance
|
||||||
|
|||||||
@@ -51,7 +51,11 @@ class SaleOrderBatchImporter(Component):
|
|||||||
self._import_record(ids[0], ids[1])
|
self._import_record(ids[0], ids[1])
|
||||||
if external_ids:
|
if external_ids:
|
||||||
last_id = list(sorted(external_ids, key=lambda i: i[0]))[-1][0]
|
last_id = list(sorted(external_ids, key=lambda i: i[0]))[-1][0]
|
||||||
self.backend_record.import_orders_after_id = last_id
|
last_date = list(sorted(external_ids, key=lambda i: i[2]))[-1][2]
|
||||||
|
self.backend_record.write({
|
||||||
|
'import_orders_after_id': last_id,
|
||||||
|
'import_orders_after_date': self.backend_record.date_to_odoo(last_date),
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
class SaleOrderImportMapper(Component):
|
class SaleOrderImportMapper(Component):
|
||||||
@@ -133,7 +137,10 @@ class SaleOrderImportMapper(Component):
|
|||||||
|
|
||||||
@mapping
|
@mapping
|
||||||
def date_order(self, record):
|
def date_order(self, record):
|
||||||
return {'date_order': record.get('date_added', fields.Datetime.now())}
|
date_added = record.get('date_added')
|
||||||
|
if date_added:
|
||||||
|
date_added = self.backend_record.date_to_odoo(date_added)
|
||||||
|
return {'date_order': date_added or fields.Datetime.now()}
|
||||||
|
|
||||||
@mapping
|
@mapping
|
||||||
def fiscal_position_id(self, record):
|
def fiscal_position_id(self, record):
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
<group colspan="4" col="4">
|
<group colspan="4" col="4">
|
||||||
<field name="base_url"/>
|
<field name="base_url"/>
|
||||||
<field name="restadmin_token" password="1"/>
|
<field name="restadmin_token" password="1"/>
|
||||||
|
<field name="server_offset_hours"/>
|
||||||
</group>
|
</group>
|
||||||
</page>
|
</page>
|
||||||
</notebook>
|
</notebook>
|
||||||
@@ -70,12 +71,8 @@
|
|||||||
in the menu 'Connectors > Checkpoint'.
|
in the menu 'Connectors > Checkpoint'.
|
||||||
</p>
|
</p>
|
||||||
<group name="import_since">
|
<group name="import_since">
|
||||||
<div>
|
<field name="import_orders_after_date"/>
|
||||||
<label for="import_orders_after_id" string="Import sale orders after Order ID" class="oe_inline"/>
|
<field name="import_orders_after_id"/>
|
||||||
<field name="import_orders_after_id"
|
|
||||||
class="oe_inline"
|
|
||||||
nolabel="1"/>
|
|
||||||
</div>
|
|
||||||
<button name="import_sale_orders"
|
<button name="import_sale_orders"
|
||||||
type="object"
|
type="object"
|
||||||
class="oe_highlight"
|
class="oe_highlight"
|
||||||
@@ -97,6 +94,7 @@
|
|||||||
<tree string="Opencart Backend">
|
<tree string="Opencart Backend">
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="import_orders_after_id"/>
|
<field name="import_orders_after_id"/>
|
||||||
|
<field name="import_orders_after_date"/>
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|||||||
Reference in New Issue
Block a user