Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinkhao committed Oct 12, 2023
1 parent ae7bf5f commit 8eb16d1
Show file tree
Hide file tree
Showing 15 changed files with 276 additions and 89 deletions.
5 changes: 5 additions & 0 deletions wms_connector/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,17 @@
"website": "https://www.akretion.com",
"depends": ["stock", "sale", "attachment_synchronize", "pydantic", "extendable"],
"data": [
"security/wms_product_sync.xml",
"views/wms_product_sync.xml",
"data/cron.xml",
"data/ir_filters.xml",
"views/attachment_queue.xml",
"views/stock_picking.xml",
"views/product_product.xml",
"views/stock_warehouse.xml",
],
"demo": [
"demo/wms_product_sync.xml",
"demo/attachment_queue.xml",
"demo/stock_picking.xml",
"demo/product_product.xml",
Expand Down
11 changes: 11 additions & 0 deletions wms_connector/data/cron.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2023 Akretion
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->

<odoo noupdate="1">

<record model="ir.cron" id="errors_email_alert">
<field name="name">WMS: Errors email alert</field>
</record>

</odoo>
12 changes: 12 additions & 0 deletions wms_connector/data/ir_filters.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2023 Akretion
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->

<odoo noupdate="1">

<record model="ir.filters" id="default_empty_filter">
<field name="name">WMS default empty filter</field>
<field name="active" eval="False"/>
</record>

</odoo>
13 changes: 13 additions & 0 deletions wms_connector/demo/wms_product_sync.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2023 Akretion
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->

<odoo noupdate="1">

<!-- TODO
<record model="wms.product.sync" id="wms_product_sync_demo_1">
<field name="name">...</field>
</record>
-->

</odoo>
1 change: 1 addition & 0 deletions wms_connector/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
from . import product_product
from . import stock_picking
from . import attachment_queue
from . import wms_product_sync
8 changes: 7 additions & 1 deletion wms_connector/models/ir_cron.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,10 @@
class IrCron(models.Model):
_inherit = "ir.cron"

warehouse_ids = fields.One2many("stock.warehouse", "sync_cron_id")
warehouse_export_ids = fields.One2many("stock.warehouse", "wms_export_cron_id")
warehouse_import_confirm_reception_ids = fields.One2many(
"stock.warehouse", "wms_import_confirm_reception_cron_id"
)
warehouse_import_confirm_delivery_ids = fields.One2many(
"stock.warehouse", "wms_import_confirm_delivery_cron_id"
)
9 changes: 7 additions & 2 deletions wms_connector/models/stock_picking.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,10 @@
class StockPicking(models.Model):
_inherit = ["stock.picking", "synchronize.exportable.mixin"]

def _prepare_export_data(self):
return StockPickingExporter.from_orm(self)
def button_create_aq(self):
self.synchronize_export()

def _get_export_name(self):
if self.file_creation_mode == "per_record":
return self.name + ".csv"
return super()._get_export_name()
122 changes: 83 additions & 39 deletions wms_connector/models/stock_warehouse.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,58 +3,102 @@

from odoo import fields, models

TASKS = [
("export", "exports (products, awaiting receptions, preparation orders"),
("import_confirm_reception", "reception confirmation"),
("import_confirm_delivery", "delivery confirmation"),
]
TASK_FIELDNAME = "wms_{}_task_id"
CRON_FIELDNAME = "wms_{}_cron_id"


class StockWarehouse(models.Model):
_inherit = "stock.warehouse"

active_wms_sync = fields.Boolean(
inverse="_inverse_active_wms_sync", readonly=False, store=True
)
sync_task_id = fields.Many2one("attachment.synchronize.task", readonly=True)
sync_cron_id = fields.Many2one("ir.cron")
wms_export_task_id = fields.Many2one("attachment.synchronize.task", readonly=True)
wms_import_confirm_reception_task_id = fields.Many2one(
"attachment.synchronize.task", readonly=True
)
wms_import_confirm_delivery_task_id = fields.Many2one(
"attachment.synchronize.task", readonly=True
)
wms_export_cron_id = fields.Many2one("ir.cron", readonly=True)
wms_import_confirm_reception_cron_id = fields.Many2one("ir.cron", readonly=True)
wms_import_confirm_delivery_cron_id = fields.Many2one("ir.cron", readonly=True)
wms_product_filter_id = fields.Many2one(
"ir.filters",
required=True,
default=lambda r: r.env.ref("wms_connector.default_empty_filter"),
)
wms_picking_ar_filter_id = fields.Many2one(
"ir.filters",
required=True,
default=lambda r: r.env.ref("wms_connector.default_empty_filter"),
)
wms_picking_prp_filter_id = fields.Many2one(
"ir.filters",
required=True,
default=lambda r: r.env.ref("wms_connector.default_empty_filter"),
)

def _inverse_active_wms_sync(self):
for rec in self:
if rec.active_wms_sync:
rec._activate_cron_task()
rec._activate_crons_tasks()
else:
rec._deactivate_cron_task()

def _activate_cron_task(self):
if self.sync_task_id:
self.sync_task_id.active = True
else:
self.sync_task_id = self.env["attachment.synchronize.task"].create(
{
"name": "WMS Sync {}".format(self.name),
"method_type": "export",
"filepath": "OUT/",
"backend_id": self.env.ref(
"storage_backend.default_storage_backend"
rec._deactivate_crons_tasks()

def _activate_crons_tasks(self):
for kind in TASKS:
task_field_name = TASK_FIELDNAME.format(kind[0])
task = getattr(self, task_field_name)
if task:
task.active = True
else:
setattr(
self,
task_field_name,
self.env["attachment.synchronize.task"].create(
{
"name": "WMS task for {} ({})".format(self.name, kind[1]),
"method_type": "export",
"filepath": "OUT/",
"backend_id": self.env.ref(
"storage_backend.default_storage_backend"
),
}
),
}
)
if self.sync_cron_id:
self.sync_cron_id.active = True
else:
self.sync_cron_id = self.env["ir.cron"].create(
{
"name": "WMS Sync {}".format(self.name),
"active": False,
"interval_type": "days",
"interval_number": 1,
"model_id": self.env.ref(
"attachment_synchronize.model_attachment_synchronize_task"
).id,
"state": "code",
"code": "", # TODO
}
)

def _deactivate_cron_task(self):
self.sync_task_id.active = False
if not self.sync_cron_id.warehouse_ids:
self.sync_cron_id.active = False
)
cron_field_name = CRON_FIELDNAME.format(kind[0])
cron = getattr(self, cron_field_name)
if cron:
cron.active = True
else:
setattr(
self,
cron_field_name,
self.env["ir.cron"].create(
{
"name": "WMS cron for {} ({})".format(self.name, kind[1]),
"active": False,
"interval_type": "days",
"interval_number": 1,
"model_id": self.env.ref(
"attachment_synchronize.model_attachment_synchronize_task"
).id,
"state": "code",
"code": "", # TODO
}
),
)

def _deactivate_crons_tasks(self):
for kind in TASKS:
setattr(self, TASK_FIELDNAME.format(kind[0]), False)
setattr(self, CRON_FIELDNAME.format(kind[0]), False)

def action_open_flows(self):
raise NotImplementedError
Expand Down
57 changes: 41 additions & 16 deletions wms_connector/models/synchronize_exportable_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,49 @@ class SynchronizeExportableMixin(models.AbstractModel):
_name = "synchronize.exportable.mixin"
_description = "Synchronizable export mixin"
wms_export_date = fields.Date()
wms_export_attachment = fields.Char()
wms_export_state = fields.Selection(
[("to_send", "To send"), ("sent", "Sent"), ("error", "Error")]
)
wms_export_attachment = fields.Many2one("attachment.queue", index=True)
wms_export_error = fields.Char()
file_creation_mode = fields.Selection(
[("per_record", "Per Record"), ("per_recordset", "Per recordset")],
default="per_record",
)

def synchronize_export(self):
try:
data = self._prepare_export_data()
if not data:
return self.env["attachment.queue"]
attachment = self._format_to_exportfile(data)
self.track_export(attachment)
self.wms_export_state = "sent"
return attachment
except Exception as e:
self.wms_export_error = str(e)
self.wms_export_state = "error"
if self.file_creation_mode == "per_record":
res = self.env["attachment.queue"]
for rec in self:
try:
rec.wms_export_error = ""
data = rec._prepare_export_data()
if not data:
continue
attachment = rec._format_to_exportfile(data)
rec.track_export(attachment)
res += attachment
except Exception as e:
rec.wms_export_error = str(e)
return res

if self.file_creation_mode == "per_recordset":
data = []
for rec in self:
try:
rec.wms_export_error = ""
data += rec._prepare_export_data()
if not data:
continue
except Exception as e:
self.wms_export_error = "Error during data preparation:\n{}".format(
str(e)
)
try:
attachment = self._format_to_exportfile(data)
self.track_export(attachment)
return attachment
except Exception as e:
self.wms_export_error = "Error during file formatting:\n{}".format(
str(e)
)

def track_export(self, attachment):
self.wms_export_date = datetime.datetime.now()
Expand Down Expand Up @@ -62,4 +87,4 @@ def _format_to_exportfile_csv(self, data):
return self.env["attachment.queue"].create(vals)

def _get_export_name(self):
return str(uuid.uuid4())
raise NotImplementedError
4 changes: 2 additions & 2 deletions wms_connector/models/synchronize_importable_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ class SynchronizeImportableMixin(models.AbstractModel):
import_date = fields.Date()
import_file_id = fields.Many2one("attachment.queue")

def track_model_import(self):
def track_model_import(self, attachment_queue):
self.write(
{
"import_date": datetime.datetime.now(),
"import_file_id": self.env.context.get("attachment_queue"),
"import_file_id": attachment_queue.id,
}
)
14 changes: 14 additions & 0 deletions wms_connector/models/wms_product_sync.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright 2023 Akretion
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from odoo import _, api, fields, models


class WmsProductSync(models.Model):
_inherit = ["synchronize.exportable.mixin"]
_name = "wms.product.sync"
_description = "Wms Product Sync"

name = fields.Char()
product_id = fields.Many2one("product.product")
warehouse_id = fields.Many2one("stock.warehouse")
14 changes: 0 additions & 14 deletions wms_connector/pydantic_models/naive_orm_model.py

This file was deleted.

15 changes: 0 additions & 15 deletions wms_connector/pydantic_models/stock_picking.py

This file was deleted.

18 changes: 18 additions & 0 deletions wms_connector/security/wms_product_sync.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2023 Akretion
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->

<odoo>

<record model="ir.model.access" id="wms_product_sync_access_name"> <!-- TODO acl id -->
<field name="name">wms.product.sync access name</field> <!-- TODO acl name -->
<field name="model_id" ref="model_wms_product_sync"/>
<!-- TODO review and adapt -->
<field name="group_id" ref="base.group_user"/>
<field name="perm_read" eval="1"/>
<field name="perm_create" eval="0"/>
<field name="perm_write" eval="0"/>
<field name="perm_unlink" eval="0"/>
</record>

</odoo>
Loading

0 comments on commit 8eb16d1

Please sign in to comment.