| REPOSITORY | |
|---|---|
| REPOSITORY | OCA/l10n-thailand |
| GIT | |
| GIT | https://github.com/OCA/l10n-thailand.git |
| GIT FOLDER | |
| GIT FOLDER | https://github.com/OCA/l10n-thailand/tree/18.0/l10n_th_gov_purchase_request |
| VERSION | |
| VERSION | 1.0.0 |
| CATEGORY | |
| CATEGORY | Localization / Purchase |
| LICENSE | |
| LICENSE | AGPL-3 |
| APPLICATION | |
| APPLICATION | No |
| AUTO-INSTALLABLE | |
| AUTO-INSTALLABLE | No |
| AUTHORS | |
| AUTHORS | Odoo Community Association (OCA), Ecosoft |
| MAINTAINERS | |
| MAINTAINERS | Odoo Community Association (OCA), Ecosoft |
| COMMITTERS | |
| COMMITTERS | OCA-git-bot, oca-ci, Saran440, ROBBYHOOD9 |
| WEBSITE | |
| WEBSITE | https://github.com/OCA/l10n-thailand |
| LAST TRACKING UPDATE | |
| LAST TRACKING UPDATE | 2026-07-06 19:30:13 |
| ODOO DEPENDENCIES | |
| ODOO DEPENDENCIES |
OCA/purchase-workflow: - purchase_exception - purchase_request_exception - purchase_request - purchase_request_substate - purchase_request_to_requisition OCA/server-tools: - base_exception OCA/server-ux: - base_substate odoo/odoo: - hr - base_setup - base - web - digest - bus - web_tour - html_editor - portal - web_editor - http_routing - auth_signup - resource - phone_validation - resource_mail - purchase - account - onboarding - product - uom - analytic - purchase_stock - stock_account - stock - barcodes_gs1_nomenclature - barcodes - purchase_requisition_stock - purchase_requisition |
| PYTHON DEPENDENCIES | |
| PYTHON DEPENDENCIES | Not have |
| SYSTEM DEPENDENCIES | |
| SYSTEM DEPENDENCIES | Not have |
| DESCRIPTION | |
| DESCRIPTION | This module add following features to Purchase Request document, aimed
to follow Thai Government procurement regulation.
1. Add following data to Purchase Request
1.1 Procurement Type (ประเภท)
- ซื้อ/จ้าง/เช่า
- จ้างที่ปรึกษา
- จ้างออกแบบและควบคุมงานก่อสร้าง
1.2 Purchase Type (ระเบียบ)
- จัดซื้อจัดจ้างผ่านพัสดุ
- วงเงินเล็กน้อย
- 79 วรรคสอง
- ว.119
1.3 Procurement Method (วิธีการ)
- เฉพาะเจาะจง
- E-bidding
- คัดเลือก
- ประกาศเชิญชวนทั่วไป
2. Use substate to add an extra step, to verify document before approved
The states of normal purchase request is,
- Draft \> To Approve \> Approved
Now changed to
- Draft \> To Approve (To Verify) \> To Approve (Verified) \>
Approved
3. Add/edit following user fields to keep tracks of who is doing what
- Prepared By (create_uid)
- Requested By (requested_by)
- Purchase Representative (assigned_to)
- Verified By (verified_by)
- Approved By (approved_by)
4. Add new Committee tab for both Procurement (คณะกรรมการจัดซื้อจัดจ้าง) and
Work Acceptance (คณะกรรมการตรวจรับ)
5. Check exception logics when sent to approve
The exception logic are based on Thai Government procurement regulation year 2560, in summary,
- จ้างที่ปรึกษา ต้องมีกรรมการจัดซื้อจัดจ้างอย่างน้อย 5 คน และกรรมการตรวจรับอย่างน้อย
5 คน
- จ้างออกแบบและควบคุมงานก่อสร้าง ต้องมีกรรมการจัดซื้อจัดจ้างอย่างน้อย 3 คน
และกรรมการตรวจรับอย่างน้อย 3 คน
- ระเบียบ วงเงินเล็กน้อย ไม่เกิน 100,000 บาท และต้องมีกรรมการตรวจรับอย่างน้อย 1
คน
- ระเบียบ 79 วรรคสอง ไม่เกิน 500,000 บาท
- ระเบียบ ว.119 ไม่เกิน 10,000 บาท และต้องมีกรรมการตรวจรับอย่างน้อย 1 คน
- ซื้อ/จ้าง/เช่า ไม่เกิน 500,000 บาท ต้องมีกรรมการตรวจรับอย่างน้อย 3 คน
- ซื้อ/จ้าง/เช่า เกิน 500,000 บาท ต้องมีกรรมการจัดซื้อจัดจ้างอย่างน้อย 3 คน
และกรรมการตรวจรับอย่างน้อย 3 คน |
| XML ID | Name | Model | Type | Status |
|---|---|---|---|---|
procurement_method_view_form |
procurement.method.view.form | procurement.method | form | New |
procurement_method_view_list |
procurement.method.view.list | procurement.method | list | New |
procurement_type_view_form |
procurement.type.view.form | procurement.type | form | New |
procurement_type_view_list |
procurement.type.view.list | procurement.type | list | New |
purchase_type_view_form |
purchase.type.view.form | purchase.type | form | New |
purchase_type_view_list |
purchase.type.view.list | purchase.type | list | New |
view_purchase_request_form |
purchase.request.form | purchase.request | button | Inherits purchase_request.view_purchase_request_form |
view_purchase_request_form_substate |
view.purchase.request.form.substate | purchase.request | field | Inherits purchase_request_substate.view_purchase_request_form |
view_purchase_request_search |
purchase.request.list.select | purchase.request | field | Inherits purchase_request.view_purchase_request_search |
view_purchase_request_tree |
purchase.request.tree | purchase.request | field | Inherits purchase_request.view_purchase_request_tree |
approve_role
Selection
required=True
selection=[('chairman', 'Chairman'), ('committee', 'Committee')]
string='Role'
committee_type
Selection
selection=[('procurement', 'Procurement Committee'), ('work_acceptance', 'Work Acceptance Committee')]
department_id
Many2one
related='employee_id.department_id'
email
Char
related='employee_id.work_email'
employee_id
Many2one → hr.employee
comodel_name='hr.employee'
index=True
ondelete='restrict'
string='Employee'
name
Char
compute='_compute_default_name'
index=True
readonly=False
required=True
store=True
string='Committee Name'
note
Text
phone
Char
related='employee_id.work_phone'
request_id
Many2one → purchase.request
comodel_name='purchase.request'
index=True
ondelete='cascade'
string='Purchase Request'
No public methods.
active
Boolean
default=True
description
Text
translate=True
name
Char
required=True
sequence
Integer
default=10
No public methods.
active
Boolean
default=True
description
Text
translate=True
name
Char
required=True
product_id
Many2one → product.product
comodel_name='product.product'
help='Default product for purchase request line'
sequence
Integer
default=10
No public methods.
approved_by
Many2one → res.users
comodel_name='res.users'
copy=False
index=True
tracking=True
assigned_to
Many2one
copy=False
string='Purchase Representative'
date_approved
Date
copy=False
string='Approved Date'
date_verified
Date
copy=False
string='Verified Date'
expense_reason
Text
string='Reason'
procurement_committee_ids
One2many → procurement.committee
comodel_name='procurement.committee'
copy=True
domain=[('committee_type', '=', 'procurement')]
inverse_name='request_id'
string='Procurement Committees'
procurement_method_id
Many2one → procurement.method
comodel_name='procurement.method'
index=True
ondelete='restrict'
string='Procurement Method'
procurement_method_ids
Many2many
related='purchase_type_id.procurement_method_ids'
procurement_type_id
Many2one → procurement.type
comodel_name='procurement.type'
index=True
ondelete='restrict'
string='Procurement Type'
purchase_type_id
Many2one → purchase.type
comodel_name='purchase.type'
default=<expr>
domain=<expr>
index=True
ondelete='restrict'
string='Purchase Type'
substate_sequence
Integer
related='substate_id.sequence'
to_create
Selection
related='purchase_type_id.to_create'
verified_by
Many2one → res.users
comodel_name='res.users'
copy=False
index=True
tracking=True
work_acceptance_committee_ids
One2many → procurement.committee
comodel_name='procurement.committee'
copy=True
domain=[('committee_type', '=', 'work_acceptance')]
inverse_name='request_id'
string='Work Acceptance Committees'
action_to_substate(self)
button_approved(self)
button_draft(self)
button_rejected(self)
get_estimated_cost_currency(self, date=False)
product_id
Many2one
compute='_compute_default_product_id'
readonly=False
store=True
No public methods.
No new fields.
Public methods (1)default_get(self, fields)
active
Boolean
default=True
code
Char
description
Text
translate=True
is_default
Boolean
help='Default purchase type on the purchase request'
string='Default'
name
Char
required=True
procurement_method_ids
Many2many → procurement.method
comodel_name='procurement.method'
help='This field will help to filter procurement method in each purchase type on the purchase request'
required=True
string='Allowed Procurement Method'
sequence
Integer
default=10
to_create
Selection
help='Create purchase agreement or expense when pr is approved'
required=True
selection=[('purchase_agreement', 'Purchase Agreement'), ('expense', 'Expense')]
visible_on_expense
Boolean
string='Expense'
visible_on_purchase_request
Boolean
string='Purchase Request'
No public methods.
| REPOSITORY | |
|---|---|
| REPOSITORY | OCA/l10n-thailand |
| GIT | |
| GIT | https://github.com/OCA/l10n-thailand.git |
| GIT FOLDER | |
| GIT FOLDER | https://github.com/OCA/l10n-thailand/tree/15.0/l10n_th_gov_purchase_request |
| VERSION | |
| VERSION | 2.0.1 |
| CATEGORY | |
| CATEGORY | Localization / Purchase |
| LICENSE | |
| LICENSE | AGPL-3 |
| APPLICATION | |
| APPLICATION | No |
| AUTO-INSTALLABLE | |
| AUTO-INSTALLABLE | No |
| AUTHORS | |
| AUTHORS | Odoo Community Association (OCA), Ecosoft |
| MAINTAINERS | |
| MAINTAINERS | Odoo Community Association (OCA), Ecosoft |
| COMMITTERS | |
| COMMITTERS | OCA-git-bot, oca-ci, Saran440 |
| WEBSITE | |
| WEBSITE | https://github.com/OCA/l10n-thailand |
| LAST TRACKING UPDATE | |
| LAST TRACKING UPDATE | 2026-07-06 00:46:35 |
| ODOO DEPENDENCIES | |
| ODOO DEPENDENCIES |
OCA/purchase-workflow: - purchase_exception - purchase_request_exception - purchase_request - purchase_request_substate - purchase_request_to_requisition OCA/server-tools: - base_exception OCA/server-ux: - base_substate odoo/odoo: - hr - base_setup - base - web - bus - web_tour - resource - purchase - account - product - uom - analytic - portal - web_editor - http_routing - auth_signup - digest - purchase_stock - stock_account - stock - barcodes - purchase_requisition_stock - purchase_requisition |
| PYTHON DEPENDENCIES | |
| PYTHON DEPENDENCIES | Not have |
| SYSTEM DEPENDENCIES | |
| SYSTEM DEPENDENCIES | Not have |
| DESCRIPTION | |
| DESCRIPTION | |
| XML ID | Name | Model | Type | Status |
|---|---|---|---|---|
procurement_method_view_form |
procurement.method.view.form | procurement.method | form | New |
procurement_method_view_tree |
procurement.method.view.tree | procurement.method | tree | New |
procurement_type_view_form |
procurement.type.view.form | procurement.type | form | New |
procurement_type_view_tree |
procurement.type.view.tree | procurement.type | tree | New |
purchase_type_view_form |
purchase.type.view.form | purchase.type | form | New |
purchase_type_view_tree |
purchase.type.view.tree | purchase.type | tree | New |
view_purchase_request_form |
purchase.request.form | purchase.request | button | Inherits purchase_request.view_purchase_request_form |
view_purchase_request_form_substate |
view.purchase.request.form.substate | purchase.request | field | Inherits purchase_request_substate.view_purchase_request_form |
view_purchase_request_search |
purchase.request.list.select | purchase.request | field | Inherits purchase_request.view_purchase_request_search |
view_purchase_request_tree |
purchase.request.tree | purchase.request | field | Inherits purchase_request.view_purchase_request_tree |
approve_role
Selection
required=True
selection=[('chairman', 'Chairman'), ('committee', 'Committee')]
string='Role'
committee_type
Selection
selection=[('procurement', 'Procurement Committee'), ('work_acceptance', 'Work Acceptance Committee')]
department_id
Many2one
related='employee_id.department_id'
email
Char
related='employee_id.work_email'
employee_id
Many2one → hr.employee
comodel_name='hr.employee'
index=True
ondelete='restrict'
string='Employee'
name
Char
compute='_compute_default_name'
index=True
readonly=False
required=True
store=True
string='Committee Name'
note
Text
phone
Char
related='employee_id.work_phone'
request_id
Many2one → purchase.request
comodel_name='purchase.request'
index=True
ondelete='cascade'
string='Purchase Request'
No public methods.
active
Boolean
default=True
description
Text
translate=True
name
Char
required=True
sequence
Integer
default=10
No public methods.
active
Boolean
default=True
description
Text
translate=True
name
Char
required=True
product_id
Many2one → product.product
comodel_name='product.product'
help='Default product for purchase request line'
sequence
Integer
default=10
No public methods.
approved_by
Many2one → res.users
comodel_name='res.users'
copy=False
index=True
tracking=True
assigned_to
Many2one
copy=False
string='Purchase Representative'
date_approved
Date
copy=False
string='Approved Date'
date_verified
Date
copy=False
string='Verified Date'
expense_reason
Text
string='Reason'
procurement_committee_ids
One2many → procurement.committee
comodel_name='procurement.committee'
copy=True
domain=[('committee_type', '=', 'procurement')]
inverse_name='request_id'
string='Procurement Committees'
procurement_method_id
Many2one → procurement.method
comodel_name='procurement.method'
index=True
ondelete='restrict'
string='Procurement Method'
procurement_method_ids
Many2many
related='purchase_type_id.procurement_method_ids'
procurement_type_id
Many2one → procurement.type
comodel_name='procurement.type'
index=True
ondelete='restrict'
string='Procurement Type'
purchase_type_id
Many2one → purchase.type
comodel_name='purchase.type'
default=<expr>
domain=<expr>
index=True
ondelete='restrict'
string='Purchase Type'
substate_sequence
Integer
related='substate_id.sequence'
to_create
Selection
related='purchase_type_id.to_create'
verified_by
Many2one → res.users
comodel_name='res.users'
copy=False
index=True
tracking=True
work_acceptance_committee_ids
One2many → procurement.committee
comodel_name='procurement.committee'
copy=True
domain=[('committee_type', '=', 'work_acceptance')]
inverse_name='request_id'
string='Work Acceptance Committees'
action_to_substate(self)
button_approved(self)
button_draft(self)
button_rejected(self)
get_estimated_cost_currency(self, date=False)
product_id
Many2one
compute='_compute_default_product_id'
readonly=False
store=True
No public methods.
No new fields.
Public methods (1)view_init(self, fields)
active
Boolean
default=True
code
Char
description
Text
translate=True
is_default
Boolean
default=False
help='Default purchase type on the purchase request'
string='Default'
name
Char
required=True
procurement_method_ids
Many2many → procurement.method
comodel_name='procurement.method'
help='This field will help to filter procurement method in each purchase type on the purchase request'
required=True
string='Allowed Procurement Method'
sequence
Integer
default=10
to_create
Selection
help='Create purchase agreement or expense when pr is approved'
required=True
selection=[('purchase_agreement', 'Purchase Agreement'), ('expense', 'Expense')]
visible_on_expense
Boolean
string='Expense'
visible_on_purchase_request
Boolean
string='Purchase Request'
No public methods.
| REPOSITORY | |
|---|---|
| REPOSITORY | OCA/l10n-thailand |
| GIT | |
| GIT | https://github.com/OCA/l10n-thailand.git |
| GIT FOLDER | |
| GIT FOLDER | https://github.com/OCA/l10n-thailand/tree/14.0/l10n_th_gov_purchase_request |
| VERSION | |
| VERSION | 1.0.0 |
| CATEGORY | |
| CATEGORY | Localization / Purchase |
| LICENSE | |
| LICENSE | AGPL-3 |
| APPLICATION | |
| APPLICATION | No |
| AUTO-INSTALLABLE | |
| AUTO-INSTALLABLE | No |
| AUTHORS | |
| AUTHORS | Odoo Community Association (OCA), Ecosoft |
| MAINTAINERS | |
| MAINTAINERS | Odoo Community Association (OCA), Ecosoft |
| COMMITTERS | |
| COMMITTERS | oca-travis, OCA-git-bot, Saran440 |
| WEBSITE | |
| WEBSITE | https://github.com/OCA/l10n-thailand |
| LAST TRACKING UPDATE | |
| LAST TRACKING UPDATE | 2026-07-06 00:41:02 |
| ODOO DEPENDENCIES | |
| ODOO DEPENDENCIES |
OCA/purchase-workflow: - purchase_request_exception - purchase_request - purchase_request_substate - purchase_request_to_requisition OCA/server-tools: - base_exception OCA/server-ux: - base_substate odoo/odoo: - hr - base_setup - base - web - bus - web_tour - resource - purchase - account - product - uom - analytic - portal - web_editor - http_routing - auth_signup - digest - purchase_stock - stock_account - stock - barcodes - purchase_requisition |
| PYTHON DEPENDENCIES | |
| PYTHON DEPENDENCIES | Not have |
| SYSTEM DEPENDENCIES | |
| SYSTEM DEPENDENCIES | Not have |
| DESCRIPTION | |
| DESCRIPTION | |
| XML ID | Name | Model | Type | Status |
|---|---|---|---|---|
procurement_method_view_form |
procurement.method.view.form | procurement.method | form | New |
procurement_method_view_tree |
procurement.method.view.tree | procurement.method | tree | New |
procurement_type_view_form |
procurement.type.view.form | procurement.type | form | New |
procurement_type_view_tree |
procurement.type.view.tree | procurement.type | tree | New |
purchase_type_view_form |
purchase.type.view.form | purchase.type | form | New |
purchase_type_view_tree |
purchase.type.view.tree | purchase.type | tree | New |
view_purchase_request_form |
purchase.request.form | purchase.request | field | Inherits purchase_request.view_purchase_request_form |
view_purchase_request_form_substate |
view.purchase.request.form.substate | purchase.request | field | Inherits purchase_request_substate.view_purchase_request_form |
view_purchase_request_search |
purchase.request.list.select | purchase.request | field | Inherits purchase_request.view_purchase_request_search |
view_purchase_request_tree |
purchase.request.tree | purchase.request | field | Inherits purchase_request.view_purchase_request_tree |
approve_role
Selection
required=True
selection=[('chairman', 'Chairman'), ('committee', 'Committee')]
string='Role'
committee_type
Selection
selection=[('procurement', 'Procurement Committee'), ('work_acceptance', 'Work Acceptance Committee')]
string='Committee Type'
department_id
Many2one
related='employee_id.department_id'
email
Char
related='employee_id.work_email'
employee_id
Many2one → hr.employee
comodel_name='hr.employee'
index=True
ondelete='restrict'
required=True
string='Employee'
name
Char
related='employee_id.name'
note
Text
string='Note'
phone
Char
related='employee_id.work_phone'
request_id
Many2one → purchase.request
comodel_name='purchase.request'
index=True
ondelete='cascade'
string='Purchase Request'
No public methods.
active
Boolean
default=True
string='Active'
description
Text
string='Description'
translate=True
name
Char
required=True
string='Name'
sequence
Integer
default=10
string='Sequence'
No public methods.
active
Boolean
default=True
string='Active'
description
Text
string='Description'
translate=True
name
Char
required=True
string='Name'
product_id
Many2one → product.product
comodel_name='product.product'
help='Default product for purchase request line'
sequence
Integer
default=10
string='Sequence'
No public methods.
approved_by
Many2one → res.users
comodel_name='res.users'
copy=False
index=True
string='Approved By'
tracking=True
assigned_to
Many2one
copy=False
string='Purchase Representative'
date_approved
Date
copy=False
string='Approved Date'
date_verified
Date
copy=False
string='Verified Date'
expense_reason
Text
string='Reason'
procurement_committee_ids
One2many → procurement.committee
comodel_name='procurement.committee'
copy=True
domain=[('committee_type', '=', 'procurement')]
inverse_name='request_id'
string='Procurement Committees'
procurement_method_id
Many2one → procurement.method
comodel_name='procurement.method'
index=True
ondelete='restrict'
string='Procurement Method'
procurement_method_ids
Many2many
related='purchase_type_id.procurement_method_ids'
procurement_type_id
Many2one → procurement.type
comodel_name='procurement.type'
index=True
ondelete='restrict'
string='Procurement Type'
purchase_type_id
Many2one → purchase.type
comodel_name='purchase.type'
default=<expr>
index=True
ondelete='restrict'
string='Purchase Type'
substate_sequence
Integer
related='substate_id.sequence'
to_create
Selection
related='purchase_type_id.to_create'
verified_by
Many2one → res.users
comodel_name='res.users'
copy=False
index=True
string='Verified By'
tracking=True
work_acceptance_committee_ids
One2many → procurement.committee
comodel_name='procurement.committee'
copy=True
domain=[('committee_type', '=', 'work_acceptance')]
inverse_name='request_id'
string='Work Acceptance Committees'
action_to_substate(self)
button_approved(self)
product_id
Many2one
compute='_compute_default_product_id'
readonly=False
store=True
No public methods.
No new fields.
Public methods (1)view_init(self, fields)
active
Boolean
default=True
string='Active'
description
Text
string='Description'
translate=True
is_default
Boolean
default=False
help='Default purchase type on the purchase request'
string='Default'
name
Char
required=True
string='Name'
procurement_method_ids
Many2many → procurement.method
comodel_name='procurement.method'
help='This field will help to filter procurement method in each purchase type on the purchase request'
required=True
string='Allowed Procurement Method'
sequence
Integer
default=10
string='Sequence'
to_create
Selection
help='Create purchase agreement or expense when pr is approved'
required=True
selection=[('purchase_agreement', 'Purchase Agreement'), ('expense', 'Expense')]
string='To Create'
No public methods.