B134 — allow empty rationale on movimento allocation decisions

- Relax AllocationDecision.rationale required flag; validate in hook
- Fix empty-motivo int test to use first movement from null

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
This commit is contained in:
Cursor Agent 2026-08-02 23:08:52 +00:00
parent 5335f69b43
commit f40957f101
No known key found for this signature in database
2 changed files with 12 additions and 12 deletions

View file

@ -32,6 +32,13 @@ const validateAllocationDecision: CollectionBeforeValidateHook = ({
throw new APIError('Informe a leitura alternativa ao descartar a sugestão.', 400)
}
if (
nextData.outcome !== 'movimento' &&
(typeof nextData.rationale !== 'string' || !nextData.rationale.trim())
) {
throw new APIError('Informe a justificativa.', 400)
}
try {
const serializedSnapshot = JSON.stringify(nextData.snapshot)
if (
@ -116,7 +123,8 @@ export const AllocationDecision: CollectionConfig = {
name: 'rationale',
type: 'textarea',
label: 'Justificativa',
required: true,
// E14 movimento may omit motivo (B134); triage outcomes validate in beforeValidate.
required: false,
maxLength: 2000,
},
{

View file

@ -71,22 +71,14 @@ describe('municipality engagement level (E14)', () => {
const coordinator = await fixtures.createCampaignUser('coordinator')
const municipality = await fixtures.getMunicipality()
await payload.update({
collection: 'municipality',
id: municipality.id,
data: { engagementLevel: 'n1', levelNote: 'Nota anterior.' },
depth: 0,
})
fixtures.touchMunicipality(municipality.id)
const updated = await setMunicipalityEngagementLevelRecord(payload, coordinator, {
municipality: municipality.id,
level: 'n2',
level: 'n1',
note: null,
})
fixtures.touchMunicipality(municipality.id)
expect(updated.engagementLevel).toBe('n2')
expect(updated.engagementLevel).toBe('n1')
expect(updated.levelNote).toBeNull()
const decisions = await findDecisions(municipality.id)
@ -94,7 +86,7 @@ describe('municipality engagement level (E14)', () => {
const decision = decisions.docs[0]!
fixtures.own('allocationDecision', decision.id)
expect(decision.rationale).toBe('')
expect(decision.snapshot).toMatchObject({ from: 'n1', to: 'n2' })
expect(decision.snapshot).toMatchObject({ from: null, to: 'n1' })
expect(decision.snapshot).not.toHaveProperty('reversalSignals')
})