Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
e974f3c
[18.0][ADD] zort_connector
TheerayutEncoder Aug 15, 2025
3861bb1
[IMP] auto update SO status
TheerayutEncoder Aug 15, 2025
aaa65f9
[IMP] pre-commit run -a
TheerayutEncoder Aug 15, 2025
ae0157b
[IMP] auto done picking and create draft inv
TheerayutEncoder Aug 17, 2025
f02deaa
[IMP] classify customer and keep API response in zort info
TheerayutEncoder Aug 17, 2025
e75147d
[IMP] Create/Update product on Zort
TheerayutEncoder Aug 17, 2025
19c309a
[IMP] Update qty to zort in picking process
TheerayutEncoder Aug 19, 2025
43768d2
[FIX] bug and error handling when update qty to zort
TheerayutEncoder Aug 21, 2025
e453a01
[IMP] cancel SO if zort was voided
TheerayutEncoder Aug 21, 2025
20d4c90
[UPD] README.rst and refactor
TheerayutEncoder Aug 21, 2025
433f152
[IMP] Add return flow
TheerayutEncoder Aug 22, 2025
4b133e2
[UPD] .pre-commit-config.yaml
TheerayutEncoder Aug 22, 2025
4ac2004
[FIX] pre-commit run -a
TheerayutEncoder Aug 22, 2025
17ef655
[ADD] Zort's default warehouse
TheerayutEncoder Aug 23, 2025
9f6a787
[FIX] get return_order_data
TheerayutEncoder Aug 23, 2025
407e611
[IMP] create credit note from return picking
TheerayutEncoder Aug 23, 2025
57497c8
[FIX] bug and refactor on sale order
TheerayutEncoder Aug 23, 2025
f51474f
[UPD] update readme
TheerayutEncoder Aug 23, 2025
6b351c0
[REV] reverse pre-commit
TheerayutEncoder Aug 23, 2025
b02325d
[IMP] refactor:process_sales_order_from_zort
TheerayutEncoder Aug 23, 2025
2d129db
[FIX] check existing zort order ids
TheerayutEncoder Sep 2, 2025
c6af2ad
[IMP] set timeout on system parameter
TheerayutEncoder Sep 2, 2025
398f7f6
[UPD] zort_connector: update readme
TheerayutEncoder Oct 4, 2025
85610ce
[ADD] e-commerce channel on sales configuration
TheerayutEncoder Oct 6, 2025
ceb3fc6
[ADD] hook method for modify SKU before search
TheerayutEncoder Oct 6, 2025
fc560f9
[ADD] fetch image from zort
TheerayutEncoder Oct 6, 2025
77e9797
[IMP] zort_connector
TheerayutEncoder Oct 19, 2025
df9d83c
[FIX] zort_connector: disable cancel warning
TheerayutEncoder Oct 25, 2025
034037f
[FIX] zort_connector: change process to update qty to zort
TheerayutEncoder Nov 10, 2025
abb7254
[FIX] zort_connector: Adjust how we link odoo product with zort product
TheerayutEncoder Dec 17, 2025
9b8a4bb
[FIX] add validate and update order line method
TheerayutEncoder Jan 15, 2026
76d73e2
[FIX] zort_connector: updated successfully notification
Pani-k-folk May 27, 2026
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
173 changes: 173 additions & 0 deletions zort_connector/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
==============
Zort Connector
==============

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:9a7fb265c67b3fca2819f2ebc2ffadda7683e67b56116044131ca90655c85d64
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-ecosoft--odoo%2Fecosoft--addons-lightgray.png?logo=github
:target: https://github.com/ecosoft-odoo/ecosoft-addons/tree/18.0/zort_connector
:alt: ecosoft-odoo/ecosoft-addons

|badge1| |badge2| |badge3|


==========================================
คู่มือการใช้งานและพัฒนาโมดูล zort_connector
==========================================

ภาพรวม
==============================

โมดูล ``zort_connector`` สำหรับ Odoo นี้ถูกออกแบบมาเพื่อเชื่อมต่อกับระบบ ZORT ผ่าน API โดยมีการทำงานหลักผ่าน Scheduled Action (Cron Job) และมีการกำหนด Action ต่าง ๆ เพื่อซิงค์ข้อมูลระหว่าง Odoo และ ZORT

การเริ่มต้นทำงานของระบบ
=====================

ระบบจะเริ่มต้นทำงานโดยอัตโนมัติผ่าน Scheduled Action (Cron Job) ที่กำหนดไว้ในไฟล์ ``data/ir_cron_data.xml`` โดยแต่ละ Action จะถูกตั้งเวลาให้ทำงานตามรอบที่กำหนด เช่น ทุก ๆ 5 นาที หรือทุก ๆ 1 ชั่วโมง

ตัวอย่าง Scheduled Action ที่มีในระบบ
------------------------------------

- **ซิงค์สินค้า (Sync Product)**
- ดึงข้อมูลสินค้าใหม่/อัปเดตจาก ZORT เข้ามาใน Odoo
- **ซิงค์ออเดอร์ (Sync Sale Order)**
- ดึงข้อมูลออเดอร์ใหม่จาก ZORT
- **ซิงค์สต็อก (Sync Stock Picking)**
- อัปเดตสถานะสต็อกจาก Odoo ไปยัง ZORT
- **ซิงค์พาร์ทเนอร์ (Sync Partner)**
- ดึงข้อมูลลูกค้า/ซัพพลายเออร์
- **ซิงค์ BOM (Sync BOM)**
- ดึงข้อมูล BOM จาก ZORT

Action เหล่านี้สามารถดูรายละเอียดและแก้ไขได้ที่ไฟล์ ``data/ir_cron_data.xml`` และโค้ดที่เกี่ยวข้องในโฟลเดอร์ ``models/``

การทำงานของแต่ละ Action
==============================

แต่ละ Action จะมีฟังก์ชันหลักในไฟล์ Python ที่เกี่ยวข้อง เช่น
- ``models/product_product.py`` สำหรับซิงค์สินค้า
- ``models/sale_order.py`` สำหรับซิงค์ออเดอร์
- ``models/stock_picking.py`` สำหรับซิงค์สต็อก
- ``models/partner.py`` สำหรับซิงค์พาร์ทเนอร์
- ``models/mrp_bom.py`` สำหรับซิงค์ BOM

โดยแต่ละฟังก์ชันจะเรียกใช้งาน API ผ่านโมดูล ``zort_api``

API Specification
=================

รายละเอียดของ API ที่ใช้เชื่อมต่อกับ ZORT ถูกกำหนดไว้ในโฟลเดอร์ ``zort_api/`` โดยเฉพาะไฟล์ ``zort_api/zort_api.py`` ซึ่งจะมีฟังก์ชันสำหรับเรียกใช้งาน API ของ ZORT เช่น
- การดึงข้อมูลสินค้า
- การดึงข้อมูลออเดอร์
- การอัปเดตสต็อก
- การดึงข้อมูล BOM

หากต้องการแก้ไขหรือเพิ่ม endpoint ใหม่ ให้แก้ไขที่ไฟล์นี้ และควรเขียน docstring อธิบายแต่ละฟังก์ชันให้ชัดเจน

แนวทางสำหรับ Developer
========================

1. **เพิ่ม/แก้ไข Action**
- เพิ่ม/แก้ไข cron job ที่ไฟล์ ``data/ir_cron_data.xml``
- เขียนฟังก์ชันในไฟล์ Python ที่เกี่ยวข้องใน ``models/``
2. **ปรับปรุง API**
- แก้ไขหรือเพิ่มฟังก์ชันใน ``zort_api/zort_api.py``
- ตรวจสอบและทดสอบการเชื่อมต่อกับ ZORT
3. **การตั้งค่า**
- สามารถตั้งค่าการเชื่อมต่อ (API Key, URL ฯลฯ) ได้ที่เมนูตั้งค่าของ Odoo หรือไฟล์ ``data/ir_config_parameter_data.xml``
4. **การทดสอบ**
- ทดสอบการทำงานของแต่ละ Action โดยดู log หรือผลลัพธ์ใน Odoo

อธิบายโครงสร้างข้อมูลสำคัญ
===========================

Zort Product
------------

``zort.product`` คือโมเดลที่ใช้เก็บข้อมูลสินค้าในฝั่ง ZORT โดยจะมีฟิลด์ ``id_zort_product`` ซึ่งเป็นรหัสอ้างอิงสินค้าจาก ZORT (Zort Product ID) และมีฟิลด์ ``product_id`` ที่ผูกกับสินค้าใน Odoo (``product.product``) อีกที

**เหตุผลที่ต้องมี zort.product**

- ZORT มีรหัสสินค้า (id_zort_product) ที่ไม่ซ้ำกับ SKU และ SKU อาจซ้ำกันหรือเปลี่ยนแปลงได้
- การซิงค์ออเดอร์จาก ZORT เข้ามาใน Odoo จะใช้ id_zort_product ในการจับคู่กับสินค้าใน Odoo ได้แม่นยำกว่าการใช้ SKU
- ช่วยให้การ mapping ข้อมูลระหว่าง 2 ระบบถูกต้อง แม้ SKU จะไม่ unique หรือเปลี่ยนแปลงได้

Zort eCommerce Channel
----------------------

``zort.ecommerce.channel`` คือโมเดลที่ใช้เก็บข้อมูลช่องทางการขาย (eCommerce Channel) ที่เชื่อมต่อกับ ZORT เช่น Lazada, Shopee, Facebook เป็นต้น

**วัตถุประสงค์**

- ใช้เก็บการตั้งค่าของแต่ละช่องทาง เช่น รหัส channel (``code``), ลูกค้า platform (``partner_id``), การสร้างลูกค้าอัตโนมัติ (``auto_create_customer``)
- ใช้สำหรับ mapping ข้อมูล order ที่มาจากแต่ละช่องทาง เพื่อให้สามารถแยกจัดการและตั้งค่าพิเศษได้ในแต่ละ channel
- รองรับการขยายช่องทางขายใหม่ ๆ ในอนาคต

สรุป
====

- ระบบเริ่มทำงานด้วย Scheduled Action (Cron Job)
- Action หลัก ๆ ได้แก่ ซิงค์สินค้า ออเดอร์ สต็อก พาร์ทเนอร์ BOM
- มีโครงสร้างข้อมูลสำคัญ ได้แก่ zort.product (สำหรับ mapping สินค้า) และ zort.ecommerce.channel (สำหรับจัดการช่องทางขาย)
- API spec และโค้ดการเชื่อมต่ออยู่ที่ ``zort_api/zort_api.py``
- Developer สามารถต่อยอดหรือแก้ไขได้ตามแนวทางข้างต้น

**Table of contents**

.. contents::
:local:

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/ecosoft-odoo/ecosoft-addons/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/ecosoft-odoo/ecosoft-addons/issues/new?body=module:%20zort_connector%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

=======


Credits
=======

Authors
-------

* Ecosoft


Contributors
------------

- Theerayut A. <theerayuta@ecosoft.co.th>


Maintainers
-----------

.. |maintainer-theerayuta@ecosoft.co.th| image:: https://github.com/theerayuta@ecosoft.co.th.png?size=40px
:target: https://github.com/theerayuta@ecosoft.co.th
:alt: theerayuta@ecosoft.co.th

Current maintainer:

|maintainer-theerayuta@ecosoft.co.th|

This module is part of the `ecosoft-odoo/ecosoft-addons <https://github.com/ecosoft-odoo/ecosoft-addons/tree/18.0/zort_connector>`_ project on GitHub.

You are welcome to contribute.
3 changes: 3 additions & 0 deletions zort_connector/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import zort_api
from . import controllers
from . import models
28 changes: 28 additions & 0 deletions zort_connector/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Copyright 2025 Ecosoft Co., Ltd (https://ecosoft.co.th)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

{
"name": "Zort Connector",
"summary": "Connects Odoo with Zort",
"version": "18.0.1.0.0",
"license": "AGPL-3",
"author": "Ecosoft, Odoo Community Association (OCA)",
"maintainers": ["theerayuta@ecosoft.co.th"],
"website": "https://github.com/ecosoft-odoo/ecosoft-addons",
"depends": ["stock", "sale_management", "mrp"],
"data": [
"security/ir.model.access.csv",
"data/ir_actions_server_data.xml",
"data/ir_config_parameter_data.xml",
"data/ir_cron_data.xml",
"data/partner_data.xml",
"data/product_data.xml",
"views/res_config_settings_view.xml",
"views/sale_order_view.xml",
"views/stock_picking_view.xml",
"views/zort_ecommerce_channel_views.xml",
"views/mrp_bom_views.xml",
"views/zort_product_view.xml",
"views/product_product_view.xml",
],
}
1 change: 1 addition & 0 deletions zort_connector/controllers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import controllers
36 changes: 36 additions & 0 deletions zort_connector/controllers/controllers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from odoo import http
from odoo.http import Response, request


class ZortConnector(http.Controller):
@http.route(
"/zort_connector/view_zort_order_json/<int:sale_order_id>",
type="http",
auth="user",
)
def view_zort_order_json(self, sale_order_id, **kwargs):
sale_order = request.env["sale.order"].sudo().browse(sale_order_id)
if not sale_order.exists():
return Response("Sale Order not found", status=404)
import json

return Response(
json.dumps(sale_order.zort_order_data, indent=2, ensure_ascii=False),
mimetype="application/json",
)

@http.route(
"/zort_connector/view_zort_return_order_json/<int:picking_id>",
type="http",
auth="user",
)
def view_zort_return_order_json(self, picking_id, **kwargs):
picking = request.env["stock.picking"].sudo().browse(picking_id)
if not picking.exists():
return Response("Picking not found", status=404)
import json

return Response(
json.dumps(picking.zort_return_data, indent=2, ensure_ascii=False),
mimetype="application/json",
)
25 changes: 25 additions & 0 deletions zort_connector/data/ir_actions_server_data.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo noupdate="1">
<record id="action_update_qty_to_zort" model="ir.actions.server">
<field name="name">Update Quantity to Zort</field>
<field name="model_id" ref="stock.model_stock_picking" />
<field name="binding_model_id" ref="stock.model_stock_picking" />
<field name="binding_type">action</field>
<field name="state">code</field>
<field name="code">
# If update qty in stock.picking fail this allow user to manually trigger the update
if record.state == 'done' and not record.updated_qty_to_zort:
record.action_sync_qty_to_zort()
</field>
</record>

<record id="action_fetch_image_from_zort_product" model="ir.actions.server">
<field name="name">Update image from zort product</field>
<field name="model_id" ref="product.model_product_product" />
<field name="state">code</field>
<field name="code">
for product in records:
product.action_fetch_and_update_image_from_zort()
</field>
</record>
</odoo>
11 changes: 11 additions & 0 deletions zort_connector/data/ir_config_parameter_data.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo noupdate="1">
<record id="zort_connector_limit_timeout" model="ir.config_parameter">
<field name="key">zort_connector.limit_timeout</field>
<field name="value">10</field>
</record>
<record id="zort_connector_order_sync_days_back" model="ir.config_parameter">
<field name="key">zort_connector.order_sync_days_back</field>
<field name="value">10</field>
</record>
</odoo>
28 changes: 28 additions & 0 deletions zort_connector/data/ir_cron_data.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo noupdate="1">
<!-- need more implementation, this is just an example -->
<record id="ir_cron_auto_sync_zort_order" model="ir.cron">
<field name="name">Auto Sync Zort Order</field>
<field name="model_id" ref="model_sale_order" />
<field name="state">code</field>
<field name="code">model.process_sales_order_from_zort()</field>
<field name="interval_number">10</field>
<field name="interval_type">minutes</field>
</record>
<record id="ir_cron_auto_sync_zort_return_order" model="ir.cron">
<field name="name">Auto Sync Zort Return Order</field>
<field name="model_id" ref="model_stock_picking" />
<field name="state">code</field>
<field name="code">model.action_create_return_picking()</field>
<field name="interval_number">10</field>
<field name="interval_type">minutes</field>
</record>
<record id="ir_cron_auto_update_bom_qty_available" model="ir.cron">
<field name="name">Auto Update BOM Qty Available</field>
<field name="model_id" ref="model_mrp_bom" />
<field name="state">code</field>
<field name="code">model.update_bom_qty_to_zort()</field>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
</record>
</odoo>
23 changes: 23 additions & 0 deletions zort_connector/data/partner_data.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo noupdate="1">
<record id="marketplace_customer_1" model="res.partner">
<field name="name">Marketplace Customer</field>
<field name="is_company" eval="True" />
<field name="company_type">company</field>
</record>
<record id="marketplace_customer_2" model="res.partner">
<field name="name">Shoppee Customer</field>
<field name="is_company" eval="True" />
<field name="company_type">company</field>
</record>
<record id="marketplace_customer_3" model="res.partner">
<field name="name">Lazada Customer</field>
<field name="is_company" eval="True" />
<field name="company_type">company</field>
</record>
<record id="marketplace_customer_4" model="res.partner">
<field name="name">Tiktok Customer</field>
<field name="is_company" eval="True" />
<field name="company_type">company</field>
</record>
</odoo>
33 changes: 33 additions & 0 deletions zort_connector/data/product_data.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo noupdate="1">
<record id="product_shipping_fee" model="product.template">
<field name="name">Shipping Fee</field>
<field name="type">service</field>
<field name="purchase_ok" eval="False" />
<field name="taxes_id" eval="False" />
<field name="list_price">0.0</field>
<field name="standard_price">0.0</field>
<field name="default_code">shipping_fee</field>
<field name="invoice_policy">order</field>
</record>
<record id="product_discount" model="product.template">
<field name="name">Discount</field>
<field name="type">service</field>
<field name="purchase_ok" eval="False" />
<field name="taxes_id" eval="False" />
<field name="list_price">0.0</field>
<field name="standard_price">0.0</field>
<field name="default_code">zort_discount</field>
<field name="invoice_policy">order</field>
</record>
<record id="voucher_amount_zort" model="product.template">
<field name="name">Zort Voucher</field>
<field name="type">service</field>
<field name="purchase_ok" eval="False" />
<field name="taxes_id" eval="False" />
<field name="list_price">0.0</field>
<field name="standard_price">0.0</field>
<field name="default_code">zort_voucher</field>
<field name="invoice_policy">order</field>
</record>
</odoo>
8 changes: 8 additions & 0 deletions zort_connector/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from . import ecommerce_channel
from . import mrp_bom
from . import product_product
from . import res_company
from . import res_config_settings
from . import sale_order
from . import stock_picking
from . import zort_product
Loading
Loading