157 lines
6.1 KiB
Python
157 lines
6.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Sub 12 Phase F — end-to-end smoke test.
|
|
#
|
|
# Run via odoo-shell:
|
|
# /usr/bin/odoo shell -c /etc/odoo/odoo.conf -d admin
|
|
# >>> exec(open('/mnt/extra-addons/custom/fusion_plating_quality/scripts/sub12_smoke_test.py').read())
|
|
#
|
|
# Walks the full Sub 12 lifecycle and asserts at each step.
|
|
|
|
import logging
|
|
|
|
_log = logging.getLogger(__name__)
|
|
|
|
|
|
def _resolve_test_partner(env):
|
|
"""Pick a partner with at least one sale order so the RMA can bind."""
|
|
so = env['sale.order'].search([('state', 'in', ('sale', 'done'))], limit=1)
|
|
if not so:
|
|
raise RuntimeError('No confirmed sale.order found — seed one first.')
|
|
return so.partner_id, so
|
|
|
|
|
|
def smoke():
|
|
e = env # noqa -- env injected by odoo-shell
|
|
print('--- Sub 12 smoke test ---')
|
|
|
|
# Reset any stale half-completed test artefacts so the script is idempotent.
|
|
e['fusion.plating.rma'].search([('name', 'like', 'RMA/SUB12-SMOKE-%')]).unlink()
|
|
|
|
partner, so = _resolve_test_partner(e)
|
|
print(f' Using partner: {partner.display_name} (SO {so.name})')
|
|
|
|
# 1. Create RMA (draft)
|
|
rma = e['fusion.plating.rma'].create({
|
|
'partner_id': partner.id,
|
|
'sale_order_id': so.id,
|
|
'sale_order_line_ids': [(6, 0, so.order_line[:1].ids)] if so.order_line else False,
|
|
'trigger_source': 'customer_complaint',
|
|
'severity': 'high',
|
|
'qty_returned': 5,
|
|
'complaint_description': '<p>Smoke-test RMA. Auto-issued for Sub 12 verification.</p>',
|
|
})
|
|
print(f' ✓ Created RMA {rma.name} (state={rma.state})')
|
|
assert rma.state == 'draft', f'Expected draft, got {rma.state}'
|
|
|
|
# 2. Authorise
|
|
rma.action_authorise()
|
|
assert rma.state == 'authorised'
|
|
print(f' ✓ Authorised — state={rma.state}, qr_code present={bool(rma.qr_code)}')
|
|
|
|
# 3. Mark shipped
|
|
rma.action_mark_shipped_to_us()
|
|
assert rma.state == 'shipped_to_us'
|
|
print(f' ✓ Customer shipped — state={rma.state}')
|
|
|
|
# 4. Auto-receive via fp.receiving create. The RMA-link create-hook
|
|
# walks the receiving from draft → counted → staged → closed in one
|
|
# shot so the SO's x_fc_receiving_status flips to "received".
|
|
receiving = e['fp.receiving'].create({
|
|
'sale_order_id': so.id,
|
|
'rma_id': rma.id,
|
|
'box_count_in': 1,
|
|
'expected_qty': 5,
|
|
'received_qty': 5,
|
|
})
|
|
print(f' ✓ Created fp.receiving {receiving.name} → RMA state={rma.state}, recv state={receiving.state}, SO status={so.x_fc_receiving_status}')
|
|
assert rma.state == 'received', f'Expected received, got {rma.state}'
|
|
assert receiving.state == 'closed', f'Expected receiving closed, got {receiving.state}'
|
|
assert so.x_fc_receiving_status == 'received', \
|
|
f'Expected SO status received, got {so.x_fc_receiving_status}'
|
|
|
|
# 5. Verify auto-spawn fired
|
|
assert rma.linked_ncr_ids, 'Auto-NCR was not spawned'
|
|
assert rma.linked_hold_ids, 'Auto-Hold was not spawned'
|
|
ncr = rma.linked_ncr_ids[0]
|
|
hold = rma.linked_hold_ids[0]
|
|
print(f' ✓ Auto-spawned NCR {ncr.name} + Hold {hold.name}')
|
|
|
|
# 6. Set resolution + triage
|
|
rma.resolution_type = 'rework'
|
|
rma.action_triage_complete()
|
|
assert rma.state == 'triaged'
|
|
print(f' ✓ Triage complete — state={rma.state}, resolution=rework')
|
|
|
|
# 7. Start resolving
|
|
rma.action_start_resolving()
|
|
assert rma.state == 'resolving'
|
|
print(f' ✓ Resolving — state={rma.state}')
|
|
|
|
# 8. NCR walk: open → containment → root cause → close
|
|
ncr.action_open()
|
|
ncr.action_containment()
|
|
ncr.containment = '<p>Smoke-test: parts segregated for re-rack.</p>'
|
|
ncr.action_disposition()
|
|
ncr.disposition = 'rework'
|
|
ncr.root_cause = '<p>Smoke-test: rack contact loss during transit.</p>'
|
|
|
|
# 9. Spawn CAPA from NCR (uses severity gate — high passes)
|
|
spawn_action = ncr.action_spawn_capa()
|
|
capa = e['fusion.plating.capa'].browse(spawn_action.get('res_id'))
|
|
print(f' ✓ Spawned CAPA {capa.name} from NCR')
|
|
assert capa.ncr_id == ncr, 'CAPA not linked to NCR'
|
|
|
|
# 10. Walk CAPA: analysis → implementation → verification → effective
|
|
capa.action_start_analysis()
|
|
capa.root_cause_analysis = '<p>Smoke-test: 5 Whys → packaging gap.</p>'
|
|
capa.action_start_implementation()
|
|
capa.action_plan = '<p>Smoke-test: revise packaging SOP.</p>'
|
|
capa.action_start_verification()
|
|
capa.effectiveness_notes = '<p>Smoke-test: 30 days no recurrence.</p>'
|
|
capa.action_mark_effective()
|
|
print(f' ✓ CAPA marked effective — state={capa.state}')
|
|
assert capa.state == 'effective'
|
|
|
|
# 11. Close NCR
|
|
ncr.action_close()
|
|
assert ncr.state == 'closed'
|
|
print(f' ✓ NCR closed — state={ncr.state}')
|
|
|
|
# 11b. Release the auto-spawned Hold (rework path) so the RMA close
|
|
# gate doesn't block. action_close on RMA refuses if any Hold is
|
|
# still on_hold or under_review.
|
|
hold.action_send_to_rework()
|
|
print(f' ✓ Hold sent to rework — state={hold.state}')
|
|
|
|
# 12. Resolve RMA (will spawn replacement job for rework)
|
|
rma.action_resolve()
|
|
print(f' ✓ RMA resolved — state={rma.state}, replacement_job={rma.replacement_job_id.name if rma.replacement_job_id else None}')
|
|
assert rma.state == 'resolved'
|
|
|
|
# 13. Close RMA
|
|
rma.action_close()
|
|
assert rma.state == 'closed'
|
|
print(f' ✓ RMA closed — state={rma.state}')
|
|
|
|
# 14. Stage_id sync sanity
|
|
print(f' ✓ NCR stage_id={ncr.stage_id.name if ncr.stage_id else "(none)"}')
|
|
print(f' ✓ RMA stage_id={rma.stage_id.name if rma.stage_id else "(none)"}')
|
|
|
|
# 15. Counts smoke (read directly — controller needs http context).
|
|
open_holds = e['fusion.plating.quality.hold'].search_count([
|
|
('state', 'in', ('on_hold', 'under_review')),
|
|
])
|
|
open_ncrs = e['fusion.plating.ncr'].search_count([
|
|
('state', 'in', ('open', 'containment', 'disposition')),
|
|
])
|
|
open_rmas = e['fusion.plating.rma'].search_count([
|
|
('state', 'not in', ('closed', 'cancelled')),
|
|
])
|
|
print(f' ✓ Dashboard counts (post-test): holds={open_holds}, ncrs={open_ncrs}, rmas={open_rmas}')
|
|
|
|
e.cr.commit()
|
|
print('--- Sub 12 smoke test PASSED ---')
|
|
|
|
|
|
smoke()
|