# Step 6 — Lisa walks the QC checklist for a customer that requires QC. # Test: # A) Customer requires QC but no template configured → spawn fails gracefully? # B) Customer requires QC + template configured → check auto-spawns on confirm # C) Lisa walks the checklist, marks lines, action_pass # D) Job mark_done now lets through 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'] Tpl = env['fp.qc.checklist.template'] TplLine = env['fp.qc.checklist.template.line'] QC = env['fusion.plating.quality.check'] # Find or create a QC template (default, no partner_id) for the test. default_tpl = Tpl.search([('partner_id', '=', False), ('active', '=', True)], limit=1) if not default_tpl: default_tpl = Tpl.create({ 'name': 'Default QC Template (E2E)', 'active': True, }) TplLine.create({'template_id': default_tpl.id, 'sequence': 10, 'name': 'Visual inspection — appearance'}) TplLine.create({'template_id': default_tpl.id, 'sequence': 20, 'name': 'Thickness measurement (Fischerscope)'}) TplLine.create({'template_id': default_tpl.id, 'sequence': 30, 'name': 'Tape adhesion test'}) print(f'[setup] Created default QC template: {default_tpl.name} ({len(default_tpl.line_ids)} lines)') else: print(f'[setup] Using existing default QC template: {default_tpl.name}') # Mark our test customer as requires_qc. target = P.browse(2529) target.x_fc_requires_qc = True print(f'[setup] Set {target.display_name}.x_fc_requires_qc = True') # Build a fresh SO + job for QC test. 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-STEP6-001', '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) print(f'[Sarah] Confirmed SO {so.name} → job {job.name}') # Did QC auto-spawn? qcs = QC.search([('job_id', '=', job.id)]) print(f'[Lisa] QC checks auto-spawned: {len(qcs)}') for qc in qcs: print(f' {qc.name}: state={qc.state}, lines={len(qc.line_ids)}, partner_id={qc.partner_id.name}') if not qcs: print(' ❌ Customer requires QC but no check spawned!') raise SystemExit qc = qcs[0] # Lisa walks every checklist line. print() print('[Lisa] Walks the checklist:') for ln in qc.line_ids.sorted('sequence'): print(f' - {ln.name}: result before={ln.result}') ln.result = 'pass' ln.notes = 'OK on inspection' # Try to action_pass. print() print('[Lisa] Clicks "Pass":') try: qc.action_pass() print(f' ✓ QC state={qc.state}, overall_result={qc.overall_result}') except Exception as e: print(f' ❌ {e}') # Now job mark_done should work (steps need to be walked first). print() print('[Carlos+Lisa] Walking steps then marking job done:') for s in job.step_ids.sorted('sequence'): if s.state in ('pending', 'ready'): s.button_start() if s.state == 'in_progress': s.button_finish() try: job.button_mark_done() print(f' ✓ Job done — state={job.state}') except Exception as e: print(f' ❌ Job mark_done blocked: {e}') # Reset partner flag for test independence. target.x_fc_requires_qc = False env.cr.commit() print() print('== Step 6 complete ==')