# Scenario 9 — Carlos starts step, Bob (supervisor) reassigns to Mike. # Verify chatter audit trail. from odoo import fields W = env['fp.direct.order.wizard'] Line = env['fp.direct.order.line'] P = env['res.partner'] Part = env['fp.part.catalog'] target = P.browse(2529) part = Part.search([('x_fc_default_coating_config_id', '!=', False)], limit=1) w = W.create({ 'partner_id': target.id, 'po_pending': True, 'po_number': 'PO-S9-' + fields.Datetime.now().strftime('%H%M%S'), 'invoice_strategy': 'net_terms', }) w._onchange_partner_id() Line.create({ 'wizard_id': w.id, 'part_catalog_id': part.id, 'coating_config_id': part.x_fc_default_coating_config_id.id, 'quantity': 5, 'unit_price': 20.0, }) r = w.action_create_order() so = env['sale.order'].browse(r['res_id']) so.action_confirm() job = env['fp.job'].search([('sale_order_id', '=', so.id)], limit=1) step = job.step_ids.sorted('sequence')[0] # Pretend Carlos owns this step. step.assigned_user_id = env.user.id step.button_start() print(f'[Carlos] Started step "{step.name}" (state={step.state})') print(f' assigned_user_id: {step.assigned_user_id.name}') # Count chatter messages on the JOB before Bob reassigns. before_count = len(job.message_ids) print(f' Job chatter messages before reassign: {before_count}') # Bob reassigns to "another user" — for the test we just write to ourselves # to simulate, but the field write IS the operation. print() print('[Bob] Reassigning step to a different operator...') # Use a different user if available. other = env['res.users'].search([('id', '!=', env.user.id), ('share', '=', False)], limit=1) if not other: other = env.user # fallback — at least the write fires step.assigned_user_id = other.id step.invalidate_recordset() job.invalidate_recordset() after_count = len(job.message_ids) print(f' After reassign: assigned_user_id={step.assigned_user_id.name}') print(f' Job chatter messages: {after_count} (delta: {after_count - before_count})') reassign_msgs = job.message_ids.filtered( lambda m: 'reassign' in (m.body or '').lower() ) print(f' Reassign-flagged chatter posts: {len(reassign_msgs)}') if reassign_msgs: print(f' ✓ Audit trail captured') else: print(f' ❌ GAP: silent reassignment, no chatter trail') env.cr.commit()