Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wms_connector: refactor with attachment_synchronize_record #11

Open
wants to merge 5 commits into
base: 14.0-wms_connector_2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions wms_connector/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@
"license": "AGPL-3",
"author": "Akretion,Odoo Community Association (OCA)",
"website": "https://github.com/OCA/wms",
"depends": ["stock", "sale", "attachment_synchronize"],
"depends": ["stock", "sale", "attachment_synchronize_record"],
"data": [
"security/wms_product_sync.xml",
"views/wms_product_sync.xml",
"views/stock_picking.xml",
"views/stock_warehouse.xml",
],
"demo": [
"demo/fs_storage.xml",
],
"demo": [],
}
12 changes: 0 additions & 12 deletions wms_connector/demo/fs_storage.xml

This file was deleted.

1 change: 0 additions & 1 deletion wms_connector/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from . import attachment_synchronize_task
from . import synchronize_importable_mixin
from . import synchronize_exportable_mixin
from . import stock_warehouse
from . import product_product
Expand Down
4 changes: 2 additions & 2 deletions wms_connector/models/stock_picking.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class StockPicking(models.Model):
compute="_compute_wms_sync_cancel_supported"
)

def _get_wms_export_task(self):
def _get_export_task(self):
return self.picking_type_id.warehouse_id.sudo().wms_export_task_id

def _compute_wms_sync_cancel_supported(self):
Expand All @@ -41,7 +41,7 @@ def action_cancel(self):
for record in self.filtered(lambda p: p.state != "cancel"):
if (
not self._context.get("skip_wms_cancel_check")
and record.wms_export_date
and record.export_date
and not record.wms_sync_cancel_supported
):
raise UserError(
Expand Down
6 changes: 3 additions & 3 deletions wms_connector/models/stock_warehouse.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
}
FILTER_DOMAINS = {
"wms_export_product_filter_id": "[]",
"wms_export_picking_in_filter_id": '[("wms_export_date", "=", False),'
"wms_export_picking_in_filter_id": '[("export_date", "=", False),'
' ("picking_type_id", "=", {}), ("state", "=", "assigned")]',
"wms_export_picking_out_filter_id": '[("wms_export_date", "=", False),'
"wms_export_picking_out_filter_id": '[("export_date", "=", False),'
' ("picking_type_id", "=", {}), ("state", "=", "assigned")]',
}

Expand Down Expand Up @@ -124,7 +124,7 @@ def _wms_domain_for(self, model_domain):
"product": [
("warehouse_id", "=", self.id),
("to_export", "=", True),
("wms_export_error", "=", False),
("export_error", "=", False),
],
"pickings_in": self.wms_export_picking_in_filter_id._get_eval_domain(),
"pickings_out": self.wms_export_picking_out_filter_id._get_eval_domain(),
Expand Down
104 changes: 4 additions & 100 deletions wms_connector/models/synchronize_exportable_mixin.py
Original file line number Diff line number Diff line change
@@ -1,108 +1,12 @@
# Copyright 2023 Akretion
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

import base64
import csv
import datetime
from io import StringIO

from odoo import api, fields, models
from odoo.tools import config
from odoo import models


class SynchronizeExportableMixin(models.AbstractModel):
_name = "synchronize.exportable.mixin"
_description = "Synchronizable export mixin"
_inherit = "synchronize.exportable.mixin"

wms_export_date = fields.Datetime(readonly=True)
wms_export_attachment_id = fields.Many2one(
"attachment.queue", index=True, readonly=True
)
wms_export_error = fields.Char(readonly=True, index=True)

@property
def record_per_file(self):
return 1

def button_trigger_export(self):
self.synchronize_export(raise_error=True)

def _get_export_data(self, raise_error=False):
data = []
records = self.browse()
sequence = 0
for rec in self:
try:
with self._cr.savepoint():
data += rec._prepare_export_data(sequence)
records |= rec
rec.wms_export_error = None
sequence += 1
except Exception as e:
if raise_error:
raise
if "pdb" in config.get("dev_mode"):
raise
rec.wms_export_error = str(e)
continue
if len(records) >= self.record_per_file:
yield records, data
data = []
records = self.browse()
sequence = 0
if len(records):
yield records, data

def synchronize_export(self, raise_error=False):
attachments = self.env["attachment.queue"]
for records, data in self._get_export_data(raise_error=raise_error):
vals = records._format_to_exportfile(data)
attachment = self.env["attachment.queue"].create(vals)
records.track_export(attachment)
attachments |= attachment
return attachments

def track_export(self, attachment):
self.wms_export_date = datetime.datetime.now()
self.wms_export_attachment_id = attachment

def _prepare_export_data(self, idx) -> list:
raise NotImplementedError

def _get_wms_export_task(self):
raise NotImplementedError

# TODO cleanup this code
# We should just have a method that return the data
# and a generic one that return the vals
def _format_to_exportfile(self, data):
return self._format_to_exportfile_csv(data)

def _format_to_exportfile_csv(self, data):
csv_file = StringIO()
delimiter = self.env.context.get("csv_delimiter") or ";"
writer = csv.DictWriter(
csv_file, fieldnames=data[0].keys(), delimiter=delimiter
)
for row in data:
writer.writerow(row)
csv_file.seek(0)
task = self._get_wms_export_task()
return {
"name": self._get_export_name(),
"datas": base64.b64encode(csv_file.getvalue().encode("utf-8")),
"task_id": task.id,
"file_type": task.file_type,
}

def _get_export_name(self):
raise NotImplementedError

@api.model
def _schedule_export(self, warehouse, domain=False):
if not domain:
domain = []
recs = self.search(domain)
if not recs:
return self.env["attachment.queue"]
return recs.with_context(warehouse=warehouse).synchronize_export()
def _synchronize_context_hook(self, wh_arg):
return {"warehouse": wh_arg[0]}
22 changes: 0 additions & 22 deletions wms_connector/models/synchronize_importable_mixin.py

This file was deleted.

4 changes: 2 additions & 2 deletions wms_connector/models/wms_product_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ def _compute_to_export(self):
@api.model
def _schedule_export(self, warehouse, domain=False):
warehouse.refresh_wms_products()
return super()._schedule_export(warehouse, domain)
return super()._schedule_export(warehouse, domain=domain)

def track_export(self, attachment):
super().track_export(attachment)
self.to_export = False

def _get_wms_export_task(self):
def _get_export_task(self):
return self.warehouse_id.sudo().wms_export_task_id
4 changes: 1 addition & 3 deletions wms_connector/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
# from . import test_activate_sync

# from . import test_import
from . import test_activate_sync
from . import test_export
35 changes: 11 additions & 24 deletions wms_connector/tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,38 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

import datetime
import uuid

from odoo_test_helper import FakeModelLoader

from odoo.addons.attachment_synchronize.tests.common import SyncCommon
from odoo.addons.attachment_synchronize_record.tests.common import (
SynchronizeRecordCommon,
)


class WmsConnectorCommon(SyncCommon):
# pylint: disable=W8106
def setUp(self):
super().setUp()

class WmsConnectorCommon(SynchronizeRecordCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.backend = cls.env.ref("wms_connector.demo_wms_storage")
cls.backend.directory_path = str(uuid.uuid1()) + "/"
cls.aq_before = cls.env["attachment.queue"].search([])
cls.warehouse = cls.env.ref("stock.warehouse0")

def assertNewAttachmentQueue(self, n=1):
aq_after = self.env["attachment.queue"].search([])
self.assertEqual(len(aq_after - self.aq_before), n)
return aq_after

def setAllExported(self):
self.env["stock.picking"].search([]).wms_export_date = datetime.date.today()
self.env["wms.product.sync"].search([]).wms_export_date = datetime.date.today()
self.env["stock.picking"].search([]).export_date = datetime.date.today()
self.env["wms.product.sync"].search([]).export_date = datetime.date.today()
self.env["wms.product.sync"].search([]).to_export = False


class WmsConnectorCase(WmsConnectorCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env.ref(
"attachment_synchronize.export_to_filestore"
).backend_id = cls.backend
cls.loader = FakeModelLoader(cls.env, cls.__module__)
cls.loader.backup_registry()
from .model import StockPicking, WmsProductSync

cls.loader.update_registry(
(
WmsProductSync,
StockPicking,
)
)
cls.setUpComponent()
cls.loader.update_registry((WmsProductSync, StockPicking))

@classmethod
def tearDownClass(cls):
Expand Down
10 changes: 8 additions & 2 deletions wms_connector/tests/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
class WmsProductSync(models.Model):
_inherit = ["wms.product.sync"]

def _prepare_export_data(self):
def _prepare_export_data(self, _):
res = []
for rec in self:
res += [
Expand All @@ -20,11 +20,14 @@ def _prepare_export_data(self):
def _get_export_name(self):
return self.name

def _get_export_task(self):
return self.warehouse_id.wms_export_task_id


class StockPicking(models.Model):
_inherit = "stock.picking"

def _prepare_export_data(self):
def _prepare_export_data(self, _):
return [
{
"name": rec.name,
Expand All @@ -34,3 +37,6 @@ def _prepare_export_data(self):

def _get_export_name(self):
return self.name

def _get_export_task(self):
return self.location_id.warehouse_id.wms_export_task_id
16 changes: 8 additions & 8 deletions wms_connector/tests/test_activate_sync.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
# Copyright 2023 Akretion
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo.tests.common import SavepointCase
from odoo.tests.common import TransactionCase


class TestActivateSync(SavepointCase):
class TestActivateSync(TransactionCase):
def setUp(self):
super().setUp()
self.warehouse = self.env.ref("stock.warehouse0")

def test_active_deactivate_wms_sync(self):
self.warehouse.active_wms_sync = True
for field in (
"wms_export_cron_id",
"wms_import_confirm_reception_cron_id",
"wms_import_confirm_delivery_cron_id",
"wms_export_product_cron_id",
"wms_export_picking_in_cron_id",
"wms_export_picking_out_cron_id",
):
self.assertTrue(getattr(self.warehouse, field))
self.warehouse.active_wms_sync = False
for field in (
"wms_export_cron_id",
"wms_import_confirm_reception_cron_id",
"wms_import_confirm_delivery_cron_id",
"wms_export_product_cron_id",
"wms_export_picking_in_cron_id",
"wms_export_picking_out_cron_id",
):
self.assertFalse(getattr(self.warehouse, field).active)

Expand Down
Loading
Loading