Checkpoint: Transformation des cellules Service, Type d'achat et Ventilation en menus déroulants éditables directement dans la liste des factures. Les modifications sont sauvegardées automatiquement avec notification de succès.

This commit is contained in:
Manus
2026-02-11 09:11:07 -05:00
parent e217ac06ce
commit 69ba92b12a
2 changed files with 70 additions and 3 deletions

View File

@@ -37,6 +37,8 @@ export default function Invoices() {
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
const [invoiceToDelete, setInvoiceToDelete] = useState<number | null>(null); const [invoiceToDelete, setInvoiceToDelete] = useState<number | null>(null);
const { data: invoices, isLoading } = trpc.invoices.list.useQuery(); const { data: invoices, isLoading } = trpc.invoices.list.useQuery();
const { data: departments } = trpc.departments.getByUser.useQuery();
const { data: allocations } = trpc.accountingAllocations.getByUser.useQuery();
const utils = trpc.useUtils(); const utils = trpc.useUtils();
const exportExcelMutation = trpc.sftp.exportToExcel.useMutation({ const exportExcelMutation = trpc.sftp.exportToExcel.useMutation({
@@ -101,6 +103,16 @@ export default function Invoices() {
}, },
}); });
const updateFieldMutation = trpc.invoices.update.useMutation({
onSuccess: () => {
toast.success("Facture mise à jour");
utils.invoices.list.invalidate();
},
onError: (error) => {
toast.error(error.message || "Erreur lors de la mise à jour");
},
});
const filteredInvoices = invoices?.filter((inv) => { const filteredInvoices = invoices?.filter((inv) => {
// Filter by search query // Filter by search query
if (searchQuery) { if (searchQuery) {
@@ -365,9 +377,56 @@ export default function Invoices() {
? `${parseFloat(invoice.totalAmount as string).toFixed(2)}` ? `${parseFloat(invoice.totalAmount as string).toFixed(2)}`
: "-"} : "-"}
</TableCell> </TableCell>
<TableCell className="text-sm">{invoice.serviceConcerne || "-"}</TableCell> <TableCell className="text-sm">
<TableCell className="text-sm">{invoice.typeAchat || "-"}</TableCell> <select
<TableCell className="text-sm">{invoice.ventilationComptable || "-"}</TableCell> value={invoice.serviceConcerne || ""}
onChange={(e) => {
updateFieldMutation.mutate({
id: invoice.id,
data: { serviceConcerne: e.target.value || undefined },
});
}}
className="w-full px-2 py-1 border rounded text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
>
<option value="">-</option>
{departments?.map((dept) => (
<option key={dept.id} value={dept.name}>{dept.name}</option>
))}
</select>
</TableCell>
<TableCell className="text-sm">
<select
value={invoice.typeAchat || ""}
onChange={(e) => {
updateFieldMutation.mutate({
id: invoice.id,
data: { typeAchat: e.target.value as "CAPEX" | "OPEX" | undefined },
});
}}
className="w-full px-2 py-1 border rounded text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
>
<option value="">-</option>
<option value="CAPEX">CAPEX</option>
<option value="OPEX">OPEX</option>
</select>
</TableCell>
<TableCell className="text-sm">
<select
value={invoice.ventilationComptable || ""}
onChange={(e) => {
updateFieldMutation.mutate({
id: invoice.id,
data: { ventilationComptable: e.target.value || undefined },
});
}}
className="w-full px-2 py-1 border rounded text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
>
<option value="">-</option>
{allocations?.map((alloc) => (
<option key={alloc.id} value={alloc.name}>{alloc.name}</option>
))}
</select>
</TableCell>
<TableCell>{getQualityBadge(invoice.qualityScore)}</TableCell> <TableCell>{getQualityBadge(invoice.qualityScore)}</TableCell>
<TableCell>{getExportStatusBadge(invoice.exportStatus || "not_exported")}</TableCell> <TableCell>{getExportStatusBadge(invoice.exportStatus || "not_exported")}</TableCell>
<TableCell> <TableCell>

View File

@@ -222,3 +222,11 @@
- [x] Ajouter un bouton "Supprimer" avec confirmation (AlertDialog) - [x] Ajouter un bouton "Supprimer" avec confirmation (AlertDialog)
- [x] Utiliser la route tRPC existante pour supprimer une facture - [x] Utiliser la route tRPC existante pour supprimer une facture
- [x] Tester la suppression avec confirmation - [x] Tester la suppression avec confirmation
## Édition directe des champs métier dans la liste
- [x] Charger les listes de services et ventilations dans la page Invoices
- [x] Transformer la cellule Service en menu déroulant éditable
- [x] Transformer la cellule Type d'achat en menu déroulant éditable
- [x] Transformer la cellule Ventilation en menu déroulant éditable
- [x] Sauvegarder automatiquement les modifications (mutation updateFieldMutation)
- [x] Afficher une notification de succès après sauvegarde