Mandats : origin→FK identité + nomination auto + boutons + tests intégration
- origin TEXT → origin_id UUID FK duniter_identities (migration e3f4a5b6c7d8) - GET /auth/identities?q= : recherche d'identités par nom/adresse - MandateCreate.nomination_mode : auto (auto-assign auteur), collective, postpone - Wizard new.vue : champ origine = picker identité, checkbox "Démarrer maintenant" - [id].vue : modal "Assigner" = search-picker (résout UUID vs adresse SS58), affiche origin_display_name + mandatee_display_name, inputs natifs (<input>/<textarea>) - Erreurs API visibles dans l'UI (plus de catch silencieux) - test_mandate_flows.py : 17 tests intégration SQLite réels (origin, nomination, assign, lifecycle, revocation, interactions croisées) — 241 tests total OK Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,3 @@
|
||||
/**
|
||||
* Mandates store: governance mandates and their lifecycle steps.
|
||||
*
|
||||
* Maps to the backend /api/v1/mandates endpoints.
|
||||
*/
|
||||
|
||||
export interface MandateStep {
|
||||
id: string
|
||||
mandate_id: string
|
||||
@@ -20,11 +14,13 @@ export interface MandateStep {
|
||||
export interface Mandate {
|
||||
id: string
|
||||
title: string
|
||||
origin: string | null
|
||||
origin_id: string | null
|
||||
origin_display_name: string | null
|
||||
description: string | null
|
||||
mandate_type: string
|
||||
status: string
|
||||
mandatee_id: string | null
|
||||
mandatee_display_name: string | null
|
||||
decision_id: string | null
|
||||
starts_at: string | null
|
||||
ends_at: string | null
|
||||
@@ -35,9 +31,10 @@ export interface Mandate {
|
||||
|
||||
export interface MandateCreate {
|
||||
title: string
|
||||
origin?: string | null
|
||||
origin_id?: string | null
|
||||
description?: string | null
|
||||
mandate_type: string
|
||||
nomination_mode?: string
|
||||
decision_id?: string | null
|
||||
starts_at?: string | null
|
||||
ends_at?: string | null
|
||||
@@ -45,6 +42,7 @@ export interface MandateCreate {
|
||||
|
||||
export interface MandateUpdate {
|
||||
title?: string
|
||||
origin_id?: string | null
|
||||
description?: string | null
|
||||
mandate_type?: string
|
||||
starts_at?: string | null
|
||||
@@ -52,6 +50,7 @@ export interface MandateUpdate {
|
||||
}
|
||||
|
||||
export interface MandateStepCreate {
|
||||
step_order: number
|
||||
step_type: string
|
||||
title?: string | null
|
||||
description?: string | null
|
||||
@@ -73,31 +72,20 @@ export const useMandatesStore = defineStore('mandates', {
|
||||
}),
|
||||
|
||||
getters: {
|
||||
byStatus: (state) => {
|
||||
return (status: string) => state.list.filter(m => m.status === status)
|
||||
},
|
||||
activeMandates: (state): Mandate[] => {
|
||||
return state.list.filter(m => m.status === 'active')
|
||||
},
|
||||
completedMandates: (state): Mandate[] => {
|
||||
return state.list.filter(m => m.status === 'completed')
|
||||
},
|
||||
byStatus: (state) => (status: string) => state.list.filter(m => m.status === status),
|
||||
activeMandates: (state): Mandate[] => state.list.filter(m => m.status === 'active'),
|
||||
completedMandates: (state): Mandate[] => state.list.filter(m => m.status === 'completed'),
|
||||
},
|
||||
|
||||
actions: {
|
||||
/**
|
||||
* Fetch all mandates with optional filters.
|
||||
*/
|
||||
async fetchAll(params?: { mandate_type?: string; status?: string }) {
|
||||
this.loading = true
|
||||
this.error = null
|
||||
|
||||
try {
|
||||
const { $api } = useApi()
|
||||
const query: Record<string, string> = {}
|
||||
if (params?.mandate_type) query.mandate_type = params.mandate_type
|
||||
if (params?.status) query.status = params.status
|
||||
|
||||
this.list = await $api<Mandate[]>('/mandates/', { query })
|
||||
} catch (err: any) {
|
||||
this.error = err?.data?.detail || err?.message || 'Erreur lors du chargement des mandats'
|
||||
@@ -106,13 +94,9 @@ export const useMandatesStore = defineStore('mandates', {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetch a single mandate by ID with all its steps.
|
||||
*/
|
||||
async fetchById(id: string) {
|
||||
this.loading = true
|
||||
this.error = null
|
||||
|
||||
try {
|
||||
const { $api } = useApi()
|
||||
this.current = await $api<Mandate>(`/mandates/${id}`)
|
||||
@@ -123,19 +107,12 @@ export const useMandatesStore = defineStore('mandates', {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a new mandate.
|
||||
*/
|
||||
async create(payload: MandateCreate) {
|
||||
this.loading = true
|
||||
this.error = null
|
||||
|
||||
try {
|
||||
const { $api } = useApi()
|
||||
const mandate = await $api<Mandate>('/mandates/', {
|
||||
method: 'POST',
|
||||
body: payload,
|
||||
})
|
||||
const mandate = await $api<Mandate>('/mandates/', { method: 'POST', body: payload })
|
||||
this.list.unshift(mandate)
|
||||
return mandate
|
||||
} catch (err: any) {
|
||||
@@ -146,18 +123,11 @@ export const useMandatesStore = defineStore('mandates', {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Update an existing mandate.
|
||||
*/
|
||||
async update(id: string, data: MandateUpdate) {
|
||||
this.error = null
|
||||
|
||||
try {
|
||||
const { $api } = useApi()
|
||||
const updated = await $api<Mandate>(`/mandates/${id}`, {
|
||||
method: 'PUT',
|
||||
body: data,
|
||||
})
|
||||
const updated = await $api<Mandate>(`/mandates/${id}`, { method: 'PUT', body: data })
|
||||
if (this.current?.id === id) this.current = updated
|
||||
const idx = this.list.findIndex(m => m.id === id)
|
||||
if (idx >= 0) this.list[idx] = updated
|
||||
@@ -168,12 +138,8 @@ export const useMandatesStore = defineStore('mandates', {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete a mandate.
|
||||
*/
|
||||
async delete(id: string) {
|
||||
this.error = null
|
||||
|
||||
try {
|
||||
const { $api } = useApi()
|
||||
await $api(`/mandates/${id}`, { method: 'DELETE' })
|
||||
@@ -185,17 +151,11 @@ export const useMandatesStore = defineStore('mandates', {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Advance the mandate to the next step in its workflow.
|
||||
*/
|
||||
async advance(id: string) {
|
||||
this.error = null
|
||||
|
||||
try {
|
||||
const { $api } = useApi()
|
||||
const updated = await $api<Mandate>(`/mandates/${id}/advance`, {
|
||||
method: 'POST',
|
||||
})
|
||||
const updated = await $api<Mandate>(`/mandates/${id}/advance`, { method: 'POST' })
|
||||
if (this.current?.id === id) this.current = updated
|
||||
const idx = this.list.findIndex(m => m.id === id)
|
||||
if (idx >= 0) this.list[idx] = updated
|
||||
@@ -206,21 +166,12 @@ export const useMandatesStore = defineStore('mandates', {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a step to a mandate.
|
||||
*/
|
||||
async addStep(id: string, step: MandateStepCreate) {
|
||||
this.error = null
|
||||
|
||||
try {
|
||||
const { $api } = useApi()
|
||||
const newStep = await $api<MandateStep>(`/mandates/${id}/steps`, {
|
||||
method: 'POST',
|
||||
body: step,
|
||||
})
|
||||
if (this.current?.id === id) {
|
||||
this.current.steps.push(newStep)
|
||||
}
|
||||
const newStep = await $api<MandateStep>(`/mandates/${id}/steps`, { method: 'POST', body: step })
|
||||
if (this.current?.id === id) this.current.steps.push(newStep)
|
||||
return newStep
|
||||
} catch (err: any) {
|
||||
this.error = err?.data?.detail || err?.message || 'Erreur lors de l\'ajout de l\'etape'
|
||||
@@ -228,12 +179,8 @@ export const useMandatesStore = defineStore('mandates', {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Assign a mandatee to the mandate.
|
||||
*/
|
||||
async assignMandatee(id: string, mandateeId: string) {
|
||||
this.error = null
|
||||
|
||||
try {
|
||||
const { $api } = useApi()
|
||||
const updated = await $api<Mandate>(`/mandates/${id}/assign`, {
|
||||
@@ -250,17 +197,11 @@ export const useMandatesStore = defineStore('mandates', {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Revoke the mandate.
|
||||
*/
|
||||
async revoke(id: string) {
|
||||
this.error = null
|
||||
|
||||
try {
|
||||
const { $api } = useApi()
|
||||
const updated = await $api<Mandate>(`/mandates/${id}/revoke`, {
|
||||
method: 'POST',
|
||||
})
|
||||
const updated = await $api<Mandate>(`/mandates/${id}/revoke`, { method: 'POST' })
|
||||
if (this.current?.id === id) this.current = updated
|
||||
const idx = this.list.findIndex(m => m.id === id)
|
||||
if (idx >= 0) this.list[idx] = updated
|
||||
@@ -271,9 +212,6 @@ export const useMandatesStore = defineStore('mandates', {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear the current mandate.
|
||||
*/
|
||||
clearCurrent() {
|
||||
this.current = null
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user