feat(quality_dashboard): manifest bump + battle test (Tasks 7-8)
Version 19.0.7.0.0 → 19.0.8.0.0 (triggers asset cache invalidation on -u so the new template + SCSS load cleanly). Battle test script: 6-check entech smoke. Validates snapshot shape, canonical section order, required section keys, open_kanban_xmlid resolves to act_window, banner item shape when items exist. Summary prints per-section counts so you can eyeball the entech state. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
|
||||
{
|
||||
'name': 'Fusion Plating — Quality (QMS)',
|
||||
'version': '19.0.7.0.0',
|
||||
'version': '19.0.8.0.0',
|
||||
'category': 'Manufacturing/Plating',
|
||||
'summary': 'Native QMS for plating shops: NCR, CAPA, calibration, AVL, FAIR, '
|
||||
'internal audits, customer specs, document control. CE + EE compatible.',
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Quality Dashboard redesign — entech smoke.
|
||||
|
||||
Spec: docs/superpowers/specs/2026-05-25-quality-dashboard-redesign-design.md
|
||||
Plan: docs/superpowers/plans/2026-05-25-quality-dashboard-redesign-plan.md
|
||||
|
||||
Run on entech via odoo-shell:
|
||||
ssh pve-worker5 "pct exec 111 -- bash -c 'echo \\\"
|
||||
exec(open(\\\\\\\"/mnt/extra-addons/custom/fusion_plating_quality/scripts/bt_quality_dashboard_redesign.py\\\\\\\").read())
|
||||
\\\" | su - odoo -s /bin/bash -c \\\"/usr/bin/odoo shell -c /etc/odoo/odoo.conf -d admin --no-http\\\"'"
|
||||
|
||||
Validates:
|
||||
1. FpQualityDashboardSnapshot helper class exists and builds
|
||||
2. Response shape (banner + sections + computed_at)
|
||||
3. Section order is canonical (cert, hold, ncr, rma, capa, check)
|
||||
4. Each section has all required keys
|
||||
5. Each section's open_kanban_xmlid resolves to a real act_window
|
||||
6. Banner items shape includes open_action that resolves to a model
|
||||
"""
|
||||
from odoo.addons.fusion_plating_quality.controllers.fp_quality_dashboard \
|
||||
import FpQualityDashboardSnapshot, SECTION_ORDER
|
||||
|
||||
|
||||
def _ok(cond, label):
|
||||
if cond:
|
||||
print('OK -', label)
|
||||
else:
|
||||
print('FAIL -', label)
|
||||
raise SystemExit(1)
|
||||
|
||||
|
||||
# ---- 1. Build snapshot ----
|
||||
snap = FpQualityDashboardSnapshot(env).build()
|
||||
_ok(isinstance(snap, dict), 'snapshot is a dict')
|
||||
|
||||
# ---- 2. Response shape ----
|
||||
for k in ('banner', 'sections', 'computed_at'):
|
||||
_ok(k in snap, f'snapshot has key {k!r}')
|
||||
_ok(isinstance(snap['sections'], list), 'sections is a list')
|
||||
_ok(isinstance(snap['banner'], dict), 'banner is a dict')
|
||||
|
||||
# ---- 3. Section order ----
|
||||
types = [s['type'] for s in snap['sections']]
|
||||
canonical_present = [t for t in SECTION_ORDER if t in types]
|
||||
_ok(types == canonical_present,
|
||||
f'section order canonical: got {types}, expected subset of {SECTION_ORDER}')
|
||||
|
||||
# ---- 4. Section keys ----
|
||||
for sec in snap['sections']:
|
||||
for k in ('type', 'label', 'icon', 'open', 'overdue', 'items',
|
||||
'open_kanban_xmlid'):
|
||||
_ok(k in sec, f'section {sec["type"]} has key {k!r}')
|
||||
|
||||
# ---- 5. open_kanban_xmlid resolves ----
|
||||
for sec in snap['sections']:
|
||||
try:
|
||||
act = env.ref(sec['open_kanban_xmlid'], raise_if_not_found=False)
|
||||
_ok(bool(act), f'section {sec["type"]} kanban xmlid resolves')
|
||||
except Exception as e:
|
||||
_ok(False, f'section {sec["type"]} xmlid: {e}')
|
||||
|
||||
# ---- 6. Banner items shape ----
|
||||
print(f' banner.all_clear = {snap["banner"]["all_clear"]}')
|
||||
print(f' banner.items = {len(snap["banner"]["items"])}')
|
||||
print(f' banner.total_matching = {snap["banner"]["total_matching"]}')
|
||||
if snap['banner']['items']:
|
||||
item = snap['banner']['items'][0]
|
||||
for k in ('type', 'id', 'name', 'customer', 'subtitle',
|
||||
'urgency', 'critical_badge', 'open_action'):
|
||||
_ok(k in item, f'banner item has key {k!r}')
|
||||
# open_action.res_model resolves to a model
|
||||
_ok(item['open_action']['res_model'] in env,
|
||||
f'banner item res_model {item["open_action"]["res_model"]!r} is installed')
|
||||
|
||||
# ---- Summary ----
|
||||
print()
|
||||
print('--- bt_quality_dashboard_redesign: ALL PASS ---')
|
||||
print(f' Sections present: {len(snap["sections"])}')
|
||||
for sec in snap['sections']:
|
||||
print(f' {sec["icon"]} {sec["label"]}: {sec["open"]} open '
|
||||
f'({sec["overdue"]} overdue), top-{len(sec["items"])} listed')
|
||||
print(f' Banner: {len(snap["banner"]["items"])} items '
|
||||
f'(of {snap["banner"]["total_matching"]} matching), '
|
||||
f'all_clear={snap["banner"]["all_clear"]}')
|
||||
Reference in New Issue
Block a user