Initial local backup snapshot
This commit is contained in:
commit
acd9e14ba5
367 changed files with 118038 additions and 0 deletions
280
server/dsu.test.ts
Normal file
280
server/dsu.test.ts
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
|
||||
// Mock the database module
|
||||
vi.mock('./db', () => ({
|
||||
getRequestById: vi.fn(),
|
||||
updateRequest: vi.fn(),
|
||||
createRequestHistory: vi.fn(),
|
||||
createAuditLog: vi.fn(),
|
||||
}));
|
||||
|
||||
import * as db from './db';
|
||||
|
||||
describe('DSU (Direction des Services aux Usagers) - Cadre réservé', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('Merging DSU data into formData', () => {
|
||||
it('should merge DSU data into existing formData for demande_salle', () => {
|
||||
const existingFormData = {
|
||||
nomAssociation: 'Association Test',
|
||||
sallesSelectionnees: ['Salle TOUCAN'],
|
||||
dateReservation: '2026-04-15',
|
||||
motifReservation: 'Réunion annuelle',
|
||||
formulaireType: 'reservation_salle_mjs',
|
||||
};
|
||||
|
||||
const dsuData = {
|
||||
dateReception: '2026-03-10',
|
||||
avisDSU: 'favorable' as const,
|
||||
conditionsParticulieres: 'Nettoyage obligatoire',
|
||||
cautionRequise: true,
|
||||
montantCaution: '500',
|
||||
assuranceRequise: true,
|
||||
horairesImposes: '8h00 - 22h00',
|
||||
responsableDSU: 'Jean Dupont',
|
||||
dateDecision: '2026-03-11',
|
||||
observationsDSU: 'RAS',
|
||||
};
|
||||
|
||||
// Simulate the merge logic from routers.ts
|
||||
const merged = { ...existingFormData };
|
||||
(merged as any).cadreDSU = {
|
||||
...dsuData,
|
||||
rempliPar: 1,
|
||||
dateRemplissage: new Date().toISOString(),
|
||||
};
|
||||
|
||||
const result = JSON.parse(JSON.stringify(merged));
|
||||
|
||||
// Verify original data is preserved
|
||||
expect(result.nomAssociation).toBe('Association Test');
|
||||
expect(result.sallesSelectionnees).toEqual(['Salle TOUCAN']);
|
||||
expect(result.dateReservation).toBe('2026-04-15');
|
||||
expect(result.motifReservation).toBe('Réunion annuelle');
|
||||
|
||||
// Verify DSU data is added
|
||||
expect(result.cadreDSU).toBeDefined();
|
||||
expect(result.cadreDSU.avisDSU).toBe('favorable');
|
||||
expect(result.cadreDSU.dateReception).toBe('2026-03-10');
|
||||
expect(result.cadreDSU.conditionsParticulieres).toBe('Nettoyage obligatoire');
|
||||
expect(result.cadreDSU.cautionRequise).toBe(true);
|
||||
expect(result.cadreDSU.montantCaution).toBe('500');
|
||||
expect(result.cadreDSU.assuranceRequise).toBe(true);
|
||||
expect(result.cadreDSU.horairesImposes).toBe('8h00 - 22h00');
|
||||
expect(result.cadreDSU.responsableDSU).toBe('Jean Dupont');
|
||||
expect(result.cadreDSU.dateDecision).toBe('2026-03-11');
|
||||
expect(result.cadreDSU.observationsDSU).toBe('RAS');
|
||||
expect(result.cadreDSU.rempliPar).toBe(1);
|
||||
expect(result.cadreDSU.dateRemplissage).toBeDefined();
|
||||
});
|
||||
|
||||
it('should not add DSU data for non-salle request types', () => {
|
||||
const requestType = 'subvention_fonctionnement';
|
||||
const dsuData = {
|
||||
avisDSU: 'favorable' as const,
|
||||
responsableDSU: 'Jean Dupont',
|
||||
};
|
||||
|
||||
// Simulate the condition check from routers.ts
|
||||
const shouldAddDsu = requestType === 'demande_salle';
|
||||
expect(shouldAddDsu).toBe(false);
|
||||
});
|
||||
|
||||
it('should handle empty existing formData gracefully', () => {
|
||||
const existingFormData = null;
|
||||
const dsuData = {
|
||||
avisDSU: 'defavorable' as const,
|
||||
responsableDSU: 'Marie Martin',
|
||||
observationsDSU: 'Salle non disponible',
|
||||
};
|
||||
|
||||
// Simulate the merge logic
|
||||
const parsed = existingFormData ? JSON.parse(existingFormData) : {};
|
||||
parsed.cadreDSU = {
|
||||
...dsuData,
|
||||
rempliPar: 2,
|
||||
dateRemplissage: new Date().toISOString(),
|
||||
};
|
||||
|
||||
const result = JSON.parse(JSON.stringify(parsed));
|
||||
expect(result.cadreDSU).toBeDefined();
|
||||
expect(result.cadreDSU.avisDSU).toBe('defavorable');
|
||||
expect(result.cadreDSU.responsableDSU).toBe('Marie Martin');
|
||||
});
|
||||
|
||||
it('should handle favorable_avec_reserves avis correctly', () => {
|
||||
const existingFormData = { nomAssociation: 'Test' };
|
||||
const dsuData = {
|
||||
avisDSU: 'favorable_avec_reserves' as const,
|
||||
conditionsParticulieres: 'Sous réserve de présentation de l\'attestation d\'assurance',
|
||||
cautionRequise: true,
|
||||
montantCaution: '1000',
|
||||
};
|
||||
|
||||
const merged = { ...existingFormData, cadreDSU: { ...dsuData, rempliPar: 1, dateRemplissage: new Date().toISOString() } };
|
||||
const result = JSON.parse(JSON.stringify(merged));
|
||||
|
||||
expect(result.cadreDSU.avisDSU).toBe('favorable_avec_reserves');
|
||||
expect(result.cadreDSU.conditionsParticulieres).toContain('attestation d\'assurance');
|
||||
expect(result.cadreDSU.cautionRequise).toBe(true);
|
||||
expect(result.cadreDSU.montantCaution).toBe('1000');
|
||||
});
|
||||
|
||||
it('should merge financial decision into an existing salle request dossier', () => {
|
||||
const existingFormData = {
|
||||
nomAssociation: 'Association Test',
|
||||
sallesSelectionnees: ['Salle TOUCAN'],
|
||||
dateReservation: '2026-06-20',
|
||||
cadreDSU: {
|
||||
responsableDSU: 'Agent DSU',
|
||||
},
|
||||
};
|
||||
|
||||
const financialDecision = {
|
||||
financialMode: 'location_payante' as const,
|
||||
depositRequired: true,
|
||||
depositAmountCents: 45000,
|
||||
rentalAmountCents: 12500,
|
||||
pricingNotes: 'Facturation exceptionnelle pour occupation prolongée',
|
||||
contractStatus: 'a_generer' as const,
|
||||
};
|
||||
|
||||
const merged = structuredClone(existingFormData) as any;
|
||||
merged.cadreDSU = {
|
||||
...merged.cadreDSU,
|
||||
cautionRequise: financialDecision.depositRequired,
|
||||
montantCaution: String(financialDecision.depositAmountCents / 100),
|
||||
materielEvent: {
|
||||
financialDecision,
|
||||
},
|
||||
};
|
||||
|
||||
expect(merged.cadreDSU.cautionRequise).toBe(true);
|
||||
expect(merged.cadreDSU.montantCaution).toBe('450');
|
||||
expect(merged.cadreDSU.materielEvent.financialDecision.financialMode).toBe('location_payante');
|
||||
expect(merged.cadreDSU.materielEvent.financialDecision.rentalAmountCents).toBe(12500);
|
||||
});
|
||||
|
||||
it('should merge material financial decision into the existing material request data', () => {
|
||||
const existingFormData = {
|
||||
commune: 'Kourou',
|
||||
service: 'Vie associative',
|
||||
quantitesDemandees: { tente3x3: '2' },
|
||||
cadreDSU: {
|
||||
dateReception: '2026-05-10',
|
||||
materielEvent: {
|
||||
itemsAccordes: { tente3x3: true },
|
||||
quantitesAccordees: { tente3x3: '2' },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const financialDecision = {
|
||||
financialMode: 'location_payante' as const,
|
||||
depositRequired: true,
|
||||
depositAmountCents: 25000,
|
||||
rentalAmountCents: 9500,
|
||||
pricingNotes: 'Tarif exceptionnel pour événement intercommunal',
|
||||
contractStatus: 'a_generer' as const,
|
||||
};
|
||||
|
||||
const merged = structuredClone(existingFormData) as any;
|
||||
merged.cadreDSU = {
|
||||
...merged.cadreDSU,
|
||||
responsableDSU: 'Admin Logistique',
|
||||
materielEvent: {
|
||||
...merged.cadreDSU.materielEvent,
|
||||
financialDecision,
|
||||
},
|
||||
};
|
||||
|
||||
expect(merged.cadreDSU.materielEvent.itemsAccordes.tente3x3).toBe(true);
|
||||
expect(merged.cadreDSU.materielEvent.quantitesAccordees.tente3x3).toBe('2');
|
||||
expect(merged.cadreDSU.materielEvent.financialDecision.financialMode).toBe('location_payante');
|
||||
expect(merged.cadreDSU.materielEvent.financialDecision.depositRequired).toBe(true);
|
||||
expect(merged.cadreDSU.materielEvent.financialDecision.depositAmountCents).toBe(25000);
|
||||
expect(merged.cadreDSU.materielEvent.financialDecision.rentalAmountCents).toBe(9500);
|
||||
expect(merged.cadreDSU.materielEvent.financialDecision.pricingNotes).toContain('Tarif exceptionnel');
|
||||
});
|
||||
});
|
||||
|
||||
describe('DSU avis labels mapping', () => {
|
||||
const avisDSULabels: Record<string, { label: string; className: string }> = {
|
||||
favorable: { label: 'Favorable', className: 'bg-green-100 text-green-800 border-green-200' },
|
||||
defavorable: { label: 'Défavorable', className: 'bg-red-100 text-red-800 border-red-200' },
|
||||
favorable_avec_reserves: { label: 'Favorable avec réserves', className: 'bg-amber-100 text-amber-800 border-amber-200' },
|
||||
};
|
||||
|
||||
it('should have correct labels for all avis types', () => {
|
||||
expect(avisDSULabels.favorable.label).toBe('Favorable');
|
||||
expect(avisDSULabels.defavorable.label).toBe('Défavorable');
|
||||
expect(avisDSULabels.favorable_avec_reserves.label).toBe('Favorable avec réserves');
|
||||
});
|
||||
|
||||
it('should have appropriate CSS classes for visual distinction', () => {
|
||||
expect(avisDSULabels.favorable.className).toContain('green');
|
||||
expect(avisDSULabels.defavorable.className).toContain('red');
|
||||
expect(avisDSULabels.favorable_avec_reserves.className).toContain('amber');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Process mutation with DSU data', () => {
|
||||
it('should call updateRequest with merged formData when DSU data is provided', async () => {
|
||||
const mockRequest = {
|
||||
id: 1,
|
||||
type: 'demande_salle',
|
||||
status: 'soumise',
|
||||
formData: JSON.stringify({
|
||||
nomAssociation: 'Test Asso',
|
||||
sallesSelectionnees: ['Salle TOUCAN'],
|
||||
}),
|
||||
};
|
||||
|
||||
(db.getRequestById as any).mockResolvedValue(mockRequest);
|
||||
(db.updateRequest as any).mockResolvedValue(undefined);
|
||||
(db.createRequestHistory as any).mockResolvedValue(undefined);
|
||||
(db.createAuditLog as any).mockResolvedValue(undefined);
|
||||
|
||||
const dsuData = {
|
||||
avisDSU: 'favorable' as const,
|
||||
responsableDSU: 'Admin Test',
|
||||
dateReception: '2026-03-10',
|
||||
dateDecision: '2026-03-11',
|
||||
};
|
||||
|
||||
// Simulate the process logic
|
||||
const existingFormData = JSON.parse(mockRequest.formData);
|
||||
existingFormData.cadreDSU = {
|
||||
...dsuData,
|
||||
rempliPar: 1,
|
||||
dateRemplissage: new Date().toISOString(),
|
||||
};
|
||||
const updatedFormData = JSON.stringify(existingFormData);
|
||||
|
||||
await db.updateRequest(mockRequest.id, {
|
||||
status: 'validee' as any,
|
||||
commentaireAdmin: 'Approuvé',
|
||||
traitePar: 1,
|
||||
dateTraitement: new Date(),
|
||||
formData: updatedFormData,
|
||||
});
|
||||
|
||||
expect(db.updateRequest).toHaveBeenCalledWith(
|
||||
1,
|
||||
expect.objectContaining({
|
||||
status: 'validee',
|
||||
formData: expect.stringContaining('cadreDSU'),
|
||||
})
|
||||
);
|
||||
|
||||
// Verify the formData contains the DSU data
|
||||
const callArgs = (db.updateRequest as any).mock.calls[0][1];
|
||||
const parsedFormData = JSON.parse(callArgs.formData);
|
||||
expect(parsedFormData.cadreDSU.avisDSU).toBe('favorable');
|
||||
expect(parsedFormData.cadreDSU.responsableDSU).toBe('Admin Test');
|
||||
expect(parsedFormData.nomAssociation).toBe('Test Asso');
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue