Skip to content
Permalink
Browse files

[IMP] account,point_of_sale: robustness

prevent editing in pos_config with active session:
    active
    module_pos_restaurant
    journal_ids
    sequence_ids
    pickint_type_id
    journal_id

prevent deletion and deactivation of models used
in pos session:
    account_account
    account_journal
    ir_sequence
    product_template
    res_partner
    res_users
    stock_picking_type

If locally stored session information does not match with the available
database information, show a popup windows explaining there is a
conflict in the data at hand. The popup gives the user the oportunity to
save the local storage data and clear the local storage so they can
continue selling.

Task id: 1879971
  • Loading branch information...
switch87 committed Jan 15, 2019
1 parent 32186ad commit 3601935a4062d76dc36fd6f317b866ff4ca0914c
@@ -337,6 +337,19 @@ def unlink(self):
partner_prop_acc = self.env['ir.property'].search([('value_reference', 'in', values)], limit=1)
if partner_prop_acc:
raise UserError(_('You cannot remove/deactivate an account which is set on a customer or vendor.'))
default_journals = self.env['account.journal'].search([
('default_credit_account_id', 'in', self.ids),
('default_debit_account_id', '=', self.ids)
])
if default_journals:
used_accounts = default_journals.mapped('default_credit_account_id')
used_accounts |= default_journals.mapped('default_debit_account_id')
used_accounts = used_accounts & self
raise UserError(
_("The account %r is already used in journal %r and cannot be removed.")
% (', '.join(account.name for account in used_accounts),
', '.join(journal.name for journal in default_journals))
)
return super(AccountAccount, self).unlink()

@api.multi
@@ -31,10 +31,6 @@
<field name="name">Chairs</field>
</record>

<record model="pos.config" id="pos_config_main">
<field name="iface_start_categ_id" ref="pos_category_chairs"/>
<field name="start_category">True</field>
</record>

<!-- Resource: product.product -->
<record id="stock.product_cable_management_box" model="product.product">
@@ -6,10 +6,13 @@
from . import account_tax
from . import barcode_rule
from . import digest
from . import ir_sequence
from . import pos_category
from . import pos_config
from . import pos_order
from . import pos_session
from . import product
from . import res_partner
from . import res_users
from . import res_config_settings
from . import stock_picking_type
@@ -1,7 +1,8 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# Copyright (C) 2004-2008 PC Solutions (<http://pcsol.be>). All Rights Reserved
from odoo import fields, models, api
from odoo import fields, models, api, _
from odoo.exceptions import UserError


class AccountJournal(models.Model):
@@ -27,3 +28,55 @@ def _search(self, args, offset=0, limit=None, order=None, count=False, access_ri
def onchange_type(self):
if self.type not in ['bank', 'cash']:
self.journal_user = False

@api.multi
def write(self, vals):
""" Prevent to archive journals that are still used in an opened session """
if not vals.get('active', True):
config_ids = self.env['pos.config'].search([
'|',
('journal_id', 'in', self.ids),
('journal_ids', 'in', self.ids)
]).ids
if config_ids:
running_sessions = self.env['pos.session'].search([
('state', '!=', 'closed'),
('config_id', 'in', config_ids)
])
if running_sessions:
# find the problematic journal back from the one in self
journals = running_sessions.mapped('config_id.journal_id')
journals |= running_sessions.mapped('config_id.journal_ids')
journals = journals & self
raise UserError(
_("You cannot archive the journal %s as it is still used in the PoS sessions %s.")
% (', '.join(journal.name for journal in journals),
', '.join(session.name for session in running_sessions))
)
return super(AccountJournal, self).write(vals)

@api.multi
def unlink(self):
""" Prevent removing the journals that are still used in opened sessions """
config_ids = self.env['pos.config'].search([
'|',
('journal_id', 'in', self.ids),
('journal_ids', 'in', self.ids)
]).ids
if config_ids:
running_sessions = self.env['pos.session'].search([
('state', '!=', 'closed'),
('config_id', 'in', config_ids)
])
if running_sessions:
# find the problematic journal back from the one in self
journals = running_sessions.mapped('config_id.journal_id')
journals |= running_sessions.mapped('config_id.journal_ids')
journals = journals & self
raise UserError(
_("You cannot delete the journal %s as it is still used in the PoS sessions %s.")
% (', '.join(journal.name for journal in journals),
', '.join(session.name for session in running_sessions))
)

return super(AccountJournal, self).unlink()
@@ -0,0 +1,54 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models, api, _
from odoo.exceptions import UserError


class IrSequence(models.Model):
_inherit = 'ir.sequence'

@api.multi
def write(self, vals):
""" Prevent archiving the sequences that are still used in opened sessions """
if not vals.get('active', True):
config_ids = self.env['pos.config'].search([
('sequence_id', 'in', self.ids),
]).ids
if config_ids:
running_sessions = self.env['pos.session'].search([
('state', '!=', 'closed'),
('config_id', 'in', config_ids)
])
if running_sessions:
# find the problematic sequence back from the one in self
sequences = running_sessions.mapped('config_id.sequence_id')
sequences = sequences & self
raise UserError(
_("You cannot archive the sequence %s as it is still used in the PoS sessions %s.")
% (', '.join(sequence.name for sequence in sequences),
', '.join(session.name for session in running_sessions))
)
return super(IrSequence, self).write(vals)

@api.multi
def unlink(self):
""" Prevent removing the sequences that are still used in opened sessions """
config_ids = self.env['pos.config'].search([
('sequence_id', 'in', self.ids),
]).ids
if config_ids:
running_sessions = self.env['pos.session'].search([
('state', '!=', 'closed'),
('config_id', 'in', config_ids)
])
if running_sessions:
# find the problematic sequence back from the one in self
sequences = running_sessions.mapped('config_id.sequence_id')
sequences = sequences & self
raise UserError(
_("You cannot delete the sequence %s as it is still used in the PoS sessions %s.")
% (', '.join(sequence.name for sequence in sequences),
', '.join(session.name for session in running_sessions))
)

return super(IrSequence, self).unlink()
@@ -5,7 +5,7 @@
from uuid import uuid4

from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
from odoo.exceptions import ValidationError, UserError


class AccountCashboxLine(models.Model):
@@ -35,10 +35,16 @@ def default_get(self, fields):
vals['cashbox_lines_ids'] = [[0, 0, {'coin_value': line.coin_value, 'number': 0, 'subtotal': 0.0}] for line in lines]
return vals

# fields that cannot be modified when there is a running pos session
FORBIDDEN_CONFIG_FIELDS = set([
'active', 'journal_id', 'journal_ids', 'module_pos_restaurant', 'picking_type_id', 'sequence_id',
])

class PosConfig(models.Model):
_name = 'pos.config'
_description = 'Point of Sale Configuration'


def _default_sale_journal(self):
journal = self.env.ref('point_of_sale.pos_sale_journal', raise_if_not_found=False)
if journal and journal.sudo().company_id == self.env.user.company_id:
@@ -370,8 +376,23 @@ def create(self, values):

@api.multi
def write(self, vals):
result = super(PosConfig, self).write(vals)
forbidden_fields = set(vals) & FORBIDDEN_CONFIG_FIELDS
if forbidden_fields:
running_sessions = self.env['pos.session'].search([
('config_id', 'in', self.ids),
('state', '!=', 'closed'),
])
if running_sessions:
forbidden_configs = running_sessions.mapped('config_id') & self
fields_label = [self._fields[key].get_description(self.env)['string'] for key in forbidden_fields]
raise UserError(
_("You cannot modify the values of %s while your session is still open. "
"Close your session first before modifying the configuration of %s")
% (', '.join(fields_label),
', '.join(config.name for config in forbidden_configs))
)

result = super(PosConfig, self).write(vals)
config_display = self.filtered(lambda c: c.is_posbox and c.iface_customer_facing_display and not (c.customer_facing_display_html or '').strip())
if config_display:
super(PosConfig, config_display).write({'customer_facing_display_html': self._compute_default_customer_html()})
@@ -3,10 +3,15 @@
from odoo import api, fields, models, _
from odoo.exceptions import UserError

# fields that cannot be modified when there is a running pos session
FORBIDDEN_PRODUCT_FIELDS = set([
'available_in_pos', 'pos_categ_id'
])

class ProductTemplate(models.Model):
_inherit = 'product.template'


available_in_pos = fields.Boolean(string='Available in POS', help='Check if you want this product to appear in the Point of Sale.', default=False)
to_weight = fields.Boolean(string='To Weigh With Scale', help="Check if the product should be weighted using the hardware scale integration.")
pos_categ_id = fields.Many2one(
@@ -26,6 +31,18 @@ def _onchange_sale_ok(self):
if not self.sale_ok:
self.available_in_pos = False

@api.multi
def write(self, vals):
forbidden_fields = set(vals) & FORBIDDEN_PRODUCT_FIELDS
if forbidden_fields:
if self.env['pos.session'].search_count([('state', '!=', 'closed')]):
fields_label = [self._fields[key].get_description(self.env)['string'] for key in forbidden_fields]
raise UserError(
_("You cannot modify the fields %s while there is an active PoS session")
% ", ".join(fields_label)
)
return super(ProductTemplate, self).write(vals)


class ProductProduct(models.Model):
_inherit = 'product.product'
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
from odoo import api, fields, models, _
from odoo.exceptions import UserError


class ResPartner(models.Model):
@@ -38,3 +39,13 @@ def create_from_ui(self, partner):
partner['lang'] = self.env.user.lang
partner_id = self.create(partner).id
return partner_id

@api.multi
def unlink(self):
running_sessions = self.env['pos.session'].search([('state', '!=', 'closed')])
if running_sessions:
raise UserError(
_("You cannot delete contacts while there are active PoS sessions. Close the session(s) %s first.")
% ", ".join(session.name for session in running_sessions)
)
return super(ResPartner, self).unlink()
@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, models, _
from odoo.exceptions import UserError


class ResUsers(models.Model):
_inherit = 'res.users'

@api.multi
def unlink(self):
running_sessions = self.env['pos.session'].search([
('user_id', 'in', self.ids),
('state', '!=', 'closed')
])
if running_sessions:
users_selling = running_sessions.mapped('user_id')
raise UserError(
_("You cannot delete the user(s) %s when a PoS session is still in use (%s).")
% (", ".join(user.name for user in users_selling),
", ".join(session.name for session in running_sessions))
)
return super(ResUsers, self).unlink()
@@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models, api, _
from odoo.exceptions import UserError


class StockPickingType(models.Model):
_inherit = 'stock.picking.type'

@api.multi
def unlink(self):
linked_configs = self.env['pos.config'].search([
('picking_type_id', '=', self.ids)
])
if linked_configs:
running_sessions = self.env['pos.session'].search([
('config_id', 'in', linked_configs.idds),
('state', '!=', 'closed')
])
if running_sessions:
used_pickings = running_sessions.mapped('config_id.picking_type_id')
raise UserError(
_("You cannot delete the picking type %s as the PoS sessions %s are still active.")
% (", ".join(picking.name for picking in used_pickings),
", ".join(session.name for session in running_sessions))
)
return super(StockPickingType, self).unlink()
Oops, something went wrong.

0 comments on commit 3601935

Please sign in to comment.
You can’t perform that action at this time.