[FIX] point_of_sale: repair rescue session system

Rev 87a3fe92de revamped the
rescue session system in an attempt to simplify it, but
created new problems.

The rescue system is designed for accepting POS orders
that belong to a POS session that is already closed.

After 87a3fe92de:

- The system tried to automatically reuse an existing session
that matches the properties of the closed one. This will often
come as a surprise to the POS users, with orders appearing
from nowhere in a live session, possibly invalidating the cash
control steps, etc. Using a separate new session with an obvious
"RESCUE" name is much better for users. They will be able to
review the rescued order separately as well.

- When no open session was available, the system tried to create
a new one (without the rescue flag). This could often fail
because existing sessions could conflict with the new one, completely
breaking the recovery. (E.g. a session from the same POS but
with a different user) The rescue flag was designed to avoid this
pitfall, allowing multiple extra rescue sessions to coexist with
live ones.

This patch restores the use of the RESCUE flag for recovery
sessions, and forces the creation of a new session for every
recovered session. Recovery sessions will also be labelled as
"RESCUE" now, making it things more obvious for end users.
This commit is contained in:
Olivier Dony
2016-12-14 14:12:25 +01:00
parent 43a0decb3a
commit e892c57482
+19 -26
View File
@@ -536,8 +536,12 @@ class pos_session(osv.osv):
}
statements.append(create_statement(st_values, context=context))
unique_name = self.pool['ir.sequence'].next_by_code(cr, uid, 'pos.session', context=context)
if values.get('name'):
unique_name += ' ' + values['name']
values.update({
'name': self.pool['ir.sequence'].next_by_code(cr, uid, 'pos.session', context=context),
'name': unique_name,
'statement_ids': [(6, 0, statements)],
'config_id': config_id
})
@@ -681,41 +685,30 @@ class pos_order(osv.osv):
}
# This deals with orders that belong to a closed session. In order
# to recover from this we:
# - assign the order to another compatible open session
# - if that doesn't exist, create a new one
# to recover from this situation we create a new rescue session,
# making it obvious that something went wrong.
# A new, separate, rescue session is preferred for every such recovery,
# to avoid adding unrelated orders to live sessions.
def _get_valid_session(self, cr, uid, order, context=None):
session = self.pool.get('pos.session')
closed_session = session.browse(cr, uid, order['pos_session_id'], context=context)
open_sessions = session.search(cr, uid, [('state', '=', 'opened'),
('config_id', '=', closed_session.config_id.id),
('user_id', '=', closed_session.user_id.id)],
limit=1, order="start_at DESC", context=context)
_logger.warning('session %s (ID: %s) was closed but received order %s (total: %s) belonging to it',
closed_session.name,
closed_session.id,
order['name'],
order['amount_total'])
_logger.warning('attempting to create recovery session for saving order %s', order['name'])
new_session_id = session.create(cr, uid, {
'config_id': closed_session.config_id.id,
'name': _('(RESCUE FOR %(session)s)') % {'session': closed_session.name},
'rescue': True, # avoid conflict with live sessions
}, context=context)
new_session = session.browse(cr, uid, new_session_id, context=context)
if open_sessions:
open_session = session.browse(cr, uid, open_sessions[0], context=context)
_logger.warning('using session %s (ID: %s) for order %s instead',
open_session.name,
open_session.id,
order['name'])
return open_session.id
else:
_logger.warning('attempting to create new session for order %s', order['name'])
new_session_id = session.create(cr, uid, {
'config_id': closed_session.config_id.id,
}, context=context)
new_session = session.browse(cr, uid, new_session_id, context=context)
# bypass opening_control (necessary when using cash control)
new_session.signal_workflow('open')
# bypass opening_control (necessary when using cash control)
new_session.signal_workflow('open')
return new_session_id
return new_session_id
def _match_payment_to_invoice(self, cr, uid, order, context=None):
account_precision = self.pool.get('decimal.precision').precision_get(cr, uid, 'Account')