diff --git a/.github/workflows/f6-1-apply-cancel-ux.yml b/.github/workflows/f6-1-apply-cancel-ux.yml deleted file mode 100644 index 96d1802..0000000 --- a/.github/workflows/f6-1-apply-cancel-ux.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: F6.1 apply cancellation UX - -on: - push: - branches: - - hotfix/f6-1-operator-cancel-ux - paths: - - .github/workflows/f6-1-apply-cancel-ux.yml - -permissions: - contents: write - -jobs: - apply: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: hotfix/f6-1-operator-cancel-ux - fetch-depth: 0 - - name: Apply targeted patch - run: python scripts/f6-1-apply-cancel-ux.py - - name: Commit cancellation UX - run: | - rm .github/workflows/f6-1-apply-cancel-ux.yml scripts/f6-1-apply-cancel-ux.py - git config user.name 'github-actions[bot]' - git config user.email '41898282+github-actions[bot]@users.noreply.github.com' - git add web-v2/src/pages/InspectionVisitEditorF4Page.tsx .github/workflows/f6-1-apply-cancel-ux.yml scripts/f6-1-apply-cancel-ux.py - git diff --cached --check - git commit -m 'fix(F6.1): add explicit audited inspection cancellation form' - git push origin HEAD:hotfix/f6-1-operator-cancel-ux diff --git a/scripts/f6-1-apply-cancel-ux.py b/scripts/f6-1-apply-cancel-ux.py deleted file mode 100644 index c0e6a46..0000000 --- a/scripts/f6-1-apply-cancel-ux.py +++ /dev/null @@ -1,77 +0,0 @@ -from pathlib import Path -import re - -path = Path('web-v2/src/pages/InspectionVisitEditorF4Page.tsx') -text = path.read_text() - -state_before = " const [success, setSuccess] = useState('');\n" -state_after = """ const [success, setSuccess] = useState(''); - const [showCancelForm, setShowCancelForm] = useState(false); - const [cancelReason, setCancelReason] = useState(''); -""" -if text.count(state_before) != 1: - raise SystemExit('Could not locate success state exactly once') -text = text.replace(state_before, state_after) - -lifecycle_pattern = re.compile( - r" const lifecycleAction = async \(action: 'PLAN' \| 'UNPLAN' \| 'CANCEL'\) => \{.*?\n \};\n\n if \(loading\)", - re.S, -) -lifecycle_replacement = """ const lifecycleAction = async (action: 'PLAN' | 'UNPLAN') => { - if (!id) return; - setBusy(true); setError(''); setSuccess(''); - try { - let updated: InspectionVisit; - if (action === 'PLAN') { - updated = await planInspectionVisit(id); - setSuccess('Inspección planificada. Ya puede iniciarse desde la APK.'); - } else { - updated = await unplanInspectionVisit(id); - setSuccess('La Inspección volvió a borrador para corregir la planificación.'); - } - applyVisit(updated); - } catch (requestError) { setError(errorMessage(requestError)); } - finally { setBusy(false); } - }; - - const cancelCurrentVisit = async (event: FormEvent) => { - event.preventDefault(); - if (!id) return; - const reason = cancelReason.trim(); - if (reason.length < 10) { - setError('El motivo de cancelación debe tener al menos 10 caracteres.'); - return; - } - if (reason.length > 500) { - setError('El motivo de cancelación no puede superar los 500 caracteres.'); - return; - } - setBusy(true); setError(''); setSuccess(''); - try { - const updated = await cancelInspectionVisit(id, reason); - applyVisit(updated); - setCancelReason(''); - setShowCancelForm(false); - setSuccess('Inspección cancelada. El motivo quedó registrado y auditado.'); - } catch (requestError) { setError(errorMessage(requestError)); } - finally { setBusy(false); } - }; - - if (loading)""" -text, count = lifecycle_pattern.subn(lifecycle_replacement, text, count=1) -if count != 1: - raise SystemExit(f'Lifecycle block replacements: {count}') - -actions_pattern = re.compile( - r" \{visit &&
.*?
\}\n", - re.S, -) -actions_replacement = """ {visit &&
Flujo de la Inspección

La oficina planifica. El inicio y cierre operativo se realizan desde la APK. Una Inspección no puede cerrarse hasta que todas sus Actas estén selladas.

{canManage && visit.status === 'DRAFT' && }{canManage && visit.status === 'PLANNED' && }{canManage && ['DRAFT', 'PLANNED', 'IN_PROGRESS'].includes(visit.status) && }
} - - {visit && showCancelForm && ['DRAFT', 'PLANNED', 'IN_PROGRESS'].includes(visit.status) &&
CANCELACIÓN

Cancelar inspección

La cancelación es definitiva y queda auditada. No se permite si la Inspección ya tiene un Acta sellada.