first commit
This commit is contained in:
commit
6801b2e86c
33
.gitignore
vendored
Normal file
33
.gitignore
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# Editors and IDEs
|
||||
.idea/
|
||||
.vscode/
|
||||
*.swp
|
||||
*.swo
|
||||
.DS_Store
|
||||
42
README.md
Normal file
42
README.md
Normal file
@ -0,0 +1,42 @@
|
||||
# POS Edit Payment Method
|
||||
|
||||
An Odoo 19 module designed to allow **POS Managers** to safely edit the payment method used in Point of Sale Orders under specific conditions, while maintaining strict control over other financial fields (like nominal amount and date).
|
||||
|
||||
## Key Features
|
||||
|
||||
- 👤 **Access Limitation**: Only users belonging to the **POS Manager** group (`point_of_sale.group_pos_manager`) can edit the payment method. For standard POS Users, the fields remain completely read-only.
|
||||
- 🔒 **Dynamic Checks & Rules**: Editing is only permitted if:
|
||||
- The POS Session of the order is **not closed**.
|
||||
- The POS Order state is **not Done or Cancelled**.
|
||||
- The order **does not have a posted invoice**.
|
||||
- None of the payments in the order have a **posted accounting journal entry**.
|
||||
- 🚫 **Tamper Prevention**: Other financial fields, such as **amount (nominal)**, **date**, and **card details** are strictly read-only and cannot be manually edited. Standard creation or deletion of payments from the backend list view is disabled (`create="0"` and `delete="0"`).
|
||||
- 💬 **Odoo Chatter Integration**: Seamlessly leverages Odoo's native change tracking system to automatically log changes in the POS Order chatter (e.g., *• BCA changed to BTN for Rp 17,001.00*).
|
||||
|
||||
## Installation
|
||||
|
||||
1. Place the `pos_edit_payment_method` directory inside your custom Odoo addons path.
|
||||
2. Restart your Odoo server instance.
|
||||
3. Log in to your Odoo database as an Administrator.
|
||||
4. Activate **Developer Mode** (Settings -> Activate the developer mode).
|
||||
5. Navigate to the **Apps** menu and click **Update Apps List**.
|
||||
6. Search for `POS Edit Payment Method` in the Apps search bar.
|
||||
7. Click **Activate** (or **Install**).
|
||||
|
||||
## Usage Guide
|
||||
|
||||
1. Go to **Point of Sale** -> **Orders** -> **Orders**.
|
||||
2. Open a POS order whose session is still in progress (not closed).
|
||||
3. Under the **Payments** tab, double-click or inline-edit the **Payment Method** field. Note that other fields (like **Amount** and **Date**) are strictly locked.
|
||||
4. Save the order.
|
||||
5. Review the **Chatter** on the right to see the automatic change log entry.
|
||||
6. Test using an order whose session has already been closed. Verify that the payment method field is locked and cannot be edited.
|
||||
7. Test logging in as a standard POS User (non-manager). Verify that all fields in the payments tab are locked.
|
||||
|
||||
## Technical Details
|
||||
|
||||
- **Dependencies**: `point_of_sale`
|
||||
- **Category**: `Point of Sale`
|
||||
- **License**: `LGPL-3`
|
||||
- **Author**: `Suherdy Yacob`
|
||||
- **Version**: `19.0.1.0.0`
|
||||
1
__init__.py
Normal file
1
__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from . import models
|
||||
19
__manifest__.py
Normal file
19
__manifest__.py
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
'name': 'POS Edit Payment Method',
|
||||
'version': '19.0.1.0.0',
|
||||
'category': 'Point of Sale',
|
||||
'summary': 'Allows editing the payment method of a POS Order under specific conditions',
|
||||
'description': """
|
||||
This module allows users to edit the payment method used in POS orders:
|
||||
- Only editable if the POS session is not closed and the accounting journal/entry is not posted.
|
||||
- Other payment fields (like amount/nominal) remain strictly read-only.
|
||||
- Log payment method changes in the POS Order's chatter.
|
||||
""",
|
||||
'author': 'Suherdy Yacob',
|
||||
'depends': ['point_of_sale'],
|
||||
'data': [
|
||||
'views/pos_order_views.xml',
|
||||
],
|
||||
'installable': True,
|
||||
'license': 'LGPL-3',
|
||||
}
|
||||
2
models/__init__.py
Normal file
2
models/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
from . import pos_order
|
||||
from . import pos_payment
|
||||
33
models/pos_order.py
Normal file
33
models/pos_order.py
Normal file
@ -0,0 +1,33 @@
|
||||
from odoo import models, fields, api
|
||||
|
||||
class PosOrder(models.Model):
|
||||
_inherit = 'pos.order'
|
||||
|
||||
is_payment_editable = fields.Boolean(
|
||||
compute='_compute_is_payment_editable',
|
||||
string='Is Payment Editable'
|
||||
)
|
||||
|
||||
@api.depends('session_id.state', 'state', 'account_move', 'payment_ids.account_move_id.state')
|
||||
def _compute_is_payment_editable(self):
|
||||
is_manager = self.env.user.has_group('point_of_sale.group_pos_manager')
|
||||
for order in self:
|
||||
# Only POS Managers can edit
|
||||
if not is_manager:
|
||||
order.is_payment_editable = False
|
||||
# 1. POS session must not be closed
|
||||
elif order.session_id.state == 'closed':
|
||||
order.is_payment_editable = False
|
||||
# 2. POS order state must not be done or cancel
|
||||
elif order.state in ('done', 'cancel'):
|
||||
order.is_payment_editable = False
|
||||
# 3. Order must not have a posted invoice
|
||||
elif order.account_move and order.account_move.state == 'posted':
|
||||
order.is_payment_editable = False
|
||||
else:
|
||||
# 4. None of the payments must have a posted accounting journal entry (account_move_id)
|
||||
is_any_payment_posted = any(
|
||||
p.account_move_id and p.account_move_id.state == 'posted'
|
||||
for p in order.payment_ids
|
||||
)
|
||||
order.is_payment_editable = not is_any_payment_posted
|
||||
23
models/pos_payment.py
Normal file
23
models/pos_payment.py
Normal file
@ -0,0 +1,23 @@
|
||||
from odoo import models, fields, api, _
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
class PosPayment(models.Model):
|
||||
_inherit = 'pos.payment'
|
||||
|
||||
def write(self, vals):
|
||||
if 'payment_method_id' in vals:
|
||||
# Check if current user is not a POS Manager
|
||||
if not self.env.user.has_group('point_of_sale.group_pos_manager'):
|
||||
raise ValidationError(_(
|
||||
"Only POS Managers are allowed to edit payment methods."
|
||||
))
|
||||
|
||||
for payment in self:
|
||||
# Enforce the validation rules
|
||||
if not payment.pos_order_id.is_payment_editable:
|
||||
raise ValidationError(_(
|
||||
"You cannot edit the payment method because the POS session is closed "
|
||||
"or the accounting journal has already been posted."
|
||||
))
|
||||
|
||||
return super(PosPayment, self).write(vals)
|
||||
59
views/pos_order_views.xml
Normal file
59
views/pos_order_views.xml
Normal file
@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="view_pos_pos_form_inherit_edit_payment" model="ir.ui.view">
|
||||
<field name="name">pos.order.form.inherit.edit.payment</field>
|
||||
<field name="model">pos.order</field>
|
||||
<field name="inherit_id" ref="point_of_sale.view_pos_pos_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<!-- Add is_payment_editable field so the view can evaluate its value -->
|
||||
<xpath expr="//field[@name='partner_id']" position="after">
|
||||
<field name="is_payment_editable" invisible="1"/>
|
||||
</xpath>
|
||||
|
||||
<!-- Make payment_ids dynamically editable based on our computed field -->
|
||||
<xpath expr="//field[@name='payment_ids']" position="attributes">
|
||||
<attribute name="readonly">not is_payment_editable</attribute>
|
||||
</xpath>
|
||||
|
||||
<!-- Inside the list view of payment_ids, make the sub-fields readonly as requested, except payment_method_id -->
|
||||
<!-- Also set create="0" and delete="0" on list to prevent adding or deleting payments manually -->
|
||||
<xpath expr="//field[@name='payment_ids']/list" position="attributes">
|
||||
<attribute name="create">0</attribute>
|
||||
<attribute name="delete">0</attribute>
|
||||
<attribute name="editable">bottom</attribute>
|
||||
</xpath>
|
||||
|
||||
<!-- Make date readonly -->
|
||||
<xpath expr="//field[@name='payment_ids']/list/field[@name='payment_date']" position="attributes">
|
||||
<attribute name="readonly">1</attribute>
|
||||
</xpath>
|
||||
|
||||
<!-- Make payment method editable -->
|
||||
<xpath expr="//field[@name='payment_ids']/list/field[@name='payment_method_id']" position="attributes">
|
||||
<attribute name="readonly">0</attribute>
|
||||
</xpath>
|
||||
|
||||
<!-- Make amount/nominal readonly -->
|
||||
<xpath expr="//field[@name='payment_ids']/list/field[@name='amount']" position="attributes">
|
||||
<attribute name="readonly">1</attribute>
|
||||
</xpath>
|
||||
|
||||
<!-- Make optional card and mode fields readonly -->
|
||||
<xpath expr="//field[@name='payment_ids']/list/field[@name='payment_method_payment_mode']" position="attributes">
|
||||
<attribute name="readonly">1</attribute>
|
||||
</xpath>
|
||||
|
||||
<xpath expr="//field[@name='payment_ids']/list/field[@name='card_no']" position="attributes">
|
||||
<attribute name="readonly">1</attribute>
|
||||
</xpath>
|
||||
|
||||
<xpath expr="//field[@name='payment_ids']/list/field[@name='card_brand']" position="attributes">
|
||||
<attribute name="readonly">1</attribute>
|
||||
</xpath>
|
||||
|
||||
<xpath expr="//field[@name='payment_ids']/list/field[@name='cardholder_name']" position="attributes">
|
||||
<attribute name="readonly">1</attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
Loading…
Reference in New Issue
Block a user