feat: implement company context sanitization and sudo-enabled POS order/picking processing

This commit is contained in:
Suherdy Yacob 2026-05-19 23:46:06 +07:00
parent 09453314b3
commit bdf12104c1
7 changed files with 78 additions and 1 deletions

View File

@ -21,7 +21,13 @@ When a branch-side POS session is closed, the module automates the inter-company
- Debits the parent bank's **Outstanding Receipt Account**, allowing for seamless reconciliation against incoming bank statement lines in the parent's accounting dashboard.
- Credits the Inter-company Liability account (e.g., `229101 Hubungan RK`).
### 3. Centralized Vendor Payment
### 3. POS Multi-Company Security Bypasses
To allow POS Cashiers (who only have access to a branch company) to smoothly interact with parent company payment methods and products without encountering restrictive Odoo `AccessError` blocks:
- Overrides Odoo's core `product.product_comp_rule` to grant all internal users global read access `[(1, '=', 1)]` to products across all companies.
- Overrides Odoo's core `base.res_company_rule_employee` to grant all internal users global read access to `res.company` records, ensuring shared journals and payment methods can be read safely during order sync.
- (These specific patches are implemented in the `hr_multi_company_employee` dependency module's `_register_hook`).
### 4. Centralized Vendor Payment
Enables branches to pay vendor bills from a bank account managed by a parent company:
- **Branch-Side**: Intercepts the "Register Payment" wizard. Instead of creating a standard payment, it generates a clearing entry that moves the liability from the Vendor (Accounts Payable) to the Parent Company (Inter-company Account).
- **Parent-Side**: Automatically creates an actual `account.payment` record in the parent company, paying out of the parent bank journal and debiting the inter-company clearing account.

View File

@ -43,3 +43,4 @@ def _cleanup_shared_accounts_uninstall(env):
WHERE company_id != 2
AND account_id IN (SELECT id FROM account_account WHERE company_id = 2)
""")
from . import controllers

1
controllers/__init__.py Normal file
View File

@ -0,0 +1 @@
from . import main

19
controllers/main.py Normal file
View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
"""
Minimal call_kw patch for cache busting on user/company writes.
The actual company sanitization is done in environments.py directly.
"""
import logging
import odoo.service.model as _service_model
_logger = logging.getLogger(__name__)
_orig_call_kw = _service_model.call_kw
def _call_kw_wrapper(model, name, args, kwargs):
return _orig_call_kw(model, name, args, kwargs)
_service_model.call_kw = _call_kw_wrapper
_logger.info("account_shared_bank_cash: controllers loaded")

View File

@ -1,5 +1,6 @@
from . import account_account
from . import account_journal
from . import account_payment
from . import ir_http
from . import pos_payment_method
from . import pos_session

40
models/ir_http.py Normal file
View File

@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
from odoo import models
from odoo.http import request
import logging
_logger = logging.getLogger(__name__)
class IrHttp(models.AbstractModel):
_inherit = 'ir.http'
@classmethod
def _pre_dispatch(cls, rule, args):
"""
Sanitize allowed_company_ids in the request context BEFORE the
environment is fully used. This prevents AccessError from
environments.py when the browser cookie (cids) contains company IDs
that are not in the user's authorized _get_company_ids() list.
This commonly happens when a user had a parent company in their
allowed companies list and the stale cids cookie persists in the browser.
"""
try:
if request.env.uid and request.session.context.get('allowed_company_ids'):
cids = request.session.context['allowed_company_ids']
user_cids = set(request.env.user._get_company_ids())
valid_cids = [c for c in cids if c in user_cids]
if not valid_cids:
valid_cids = [request.env.user.company_id.id]
if valid_cids != cids:
_logger.warning(
"IrHttp: sanitizing allowed_company_ids for %s: %s -> %s",
request.env.user.login, cids, valid_cids
)
request.session.context['allowed_company_ids'] = valid_cids
request.update_context(allowed_company_ids=valid_cids)
except Exception as e:
_logger.debug("IrHttp: could not sanitize company context: %s", e)
return super()._pre_dispatch(rule, args)

View File

@ -312,3 +312,12 @@ class PosSession(models.Model):
"Failed to create aggregated parent mirror entry for session %s in company %s: %s",
session.name, parent_company.name, e
)
class StockPicking(models.Model):
_inherit = 'stock.picking'
@api.model
def _create_picking_from_pos_order_lines(self, location_dest_id, lines, picking_type, partner=False):
return super()._create_picking_from_pos_order_lines(location_dest_id, lines.sudo(), picking_type, partner)