Checkpoint: Coloration des valeurs dans Factures BAP (automatique vs manuelle)
Nouvelle fonctionnalité visuelle : ✅ Valeurs remplies automatiquement par les règles : affichées en VERT ✅ Valeurs saisies manuellement : affichées en BLEU ✅ Traçage intelligent de l'origine des valeurs (automatique ou manuelle) ✅ Mise à jour automatique de la couleur lors d'une modification manuelle Architecture technique : - drizzle/schema.ts : Ajout du champ autoFilledFields (JSON) pour tracer l'origine - server/automationEngine.ts : Enregistrement des champs remplis automatiquement - server/routers.ts : Ajout de autoFilledFields dans le schéma d'update - client/src/pages/InvoicesBAP.tsx : Fonction getFieldColor() pour déterminer la couleur - Migration 0010_late_thor_girl.sql appliquée avec succès Fonctionnement : 1. **Import de facture** : Les règles d'automatisme s'appliquent et marquent les champs remplis dans autoFilledFields 2. **Affichage** : La fonction getFieldColor() analyse autoFilledFields pour déterminer la couleur : - Champ dans autoFilledFields → VERT (rempli automatiquement) - Champ avec valeur mais pas dans autoFilledFields → BLEU (rempli manuellement) - Champ vide → Pas de couleur 3. **Modification manuelle** : Lors d'une édition, le champ est retiré de autoFilledFields et passe en BLEU Bénéfices utilisateur : - Visibilité immédiate sur l'origine des données - Confiance accrue dans les automatismes (vert = validé par règle) - Identification rapide des saisies manuelles nécessitant vérification - Traçabilité complète du remplissage des champs métier Cette fonctionnalité améliore considérablement la transparence du système d'automatisation et facilite le contrôle qualité des données.
This commit is contained in:
@@ -37,6 +37,23 @@ import * as XLSX from 'xlsx';
|
||||
import { toast } from "sonner";
|
||||
import { useLocation } from "wouter";
|
||||
|
||||
// Helper function to determine field color based on origin
|
||||
const getFieldColor = (invoice: any, fieldName: string): string => {
|
||||
try {
|
||||
const autoFilledFields = invoice.autoFilledFields ? JSON.parse(invoice.autoFilledFields) : [];
|
||||
if (autoFilledFields.includes(fieldName)) {
|
||||
return "text-green-600 font-semibold"; // Auto-filled by rules
|
||||
}
|
||||
// If field has a value but is not auto-filled, it's manual
|
||||
if (invoice[fieldName]) {
|
||||
return "text-blue-600 font-semibold"; // Manually filled
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error parsing autoFilledFields:", error);
|
||||
}
|
||||
return ""; // No color for empty fields
|
||||
};
|
||||
|
||||
export default function InvoicesBAP() {
|
||||
const [, setLocation] = useLocation();
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
@@ -456,13 +473,19 @@ export default function InvoicesBAP() {
|
||||
setAddDialogOpen(true);
|
||||
e.target.value = invoice.serviceConcerne || "";
|
||||
} else {
|
||||
// Remove field from autoFilledFields when manually edited
|
||||
const autoFilledFields = invoice.autoFilledFields ? JSON.parse(invoice.autoFilledFields) : [];
|
||||
const updatedAutoFields = autoFilledFields.filter((f: string) => f !== "serviceConcerne");
|
||||
updateFieldMutation.mutate({
|
||||
id: invoice.id,
|
||||
data: { serviceConcerne: e.target.value || undefined },
|
||||
data: {
|
||||
serviceConcerne: e.target.value || undefined,
|
||||
autoFilledFields: updatedAutoFields.length > 0 ? JSON.stringify(updatedAutoFields) : null
|
||||
},
|
||||
});
|
||||
}
|
||||
}}
|
||||
className="w-full px-2 py-1 border rounded text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
className={`w-full px-2 py-1 border rounded text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 ${getFieldColor(invoice, "serviceConcerne")}`}
|
||||
>
|
||||
<option value="">-</option>
|
||||
{departments?.map((dept) => (
|
||||
@@ -475,12 +498,18 @@ export default function InvoicesBAP() {
|
||||
<select
|
||||
value={invoice.typeAchat || ""}
|
||||
onChange={(e) => {
|
||||
// Remove field from autoFilledFields when manually edited
|
||||
const autoFilledFields = invoice.autoFilledFields ? JSON.parse(invoice.autoFilledFields) : [];
|
||||
const updatedAutoFields = autoFilledFields.filter((f: string) => f !== "typeAchat");
|
||||
updateFieldMutation.mutate({
|
||||
id: invoice.id,
|
||||
data: { typeAchat: e.target.value as "CAPEX" | "OPEX" | undefined },
|
||||
data: {
|
||||
typeAchat: e.target.value as "CAPEX" | "OPEX" | undefined,
|
||||
autoFilledFields: updatedAutoFields.length > 0 ? JSON.stringify(updatedAutoFields) : null
|
||||
},
|
||||
});
|
||||
}}
|
||||
className="w-full px-2 py-1 border rounded text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
className={`w-full px-2 py-1 border rounded text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 ${getFieldColor(invoice, "typeAchat")}`}
|
||||
>
|
||||
<option value="">-</option>
|
||||
<option value="CAPEX">CAPEX</option>
|
||||
@@ -497,13 +526,19 @@ export default function InvoicesBAP() {
|
||||
setAddDialogOpen(true);
|
||||
e.target.value = invoice.ventilationComptable || "";
|
||||
} else {
|
||||
// Remove field from autoFilledFields when manually edited
|
||||
const autoFilledFields = invoice.autoFilledFields ? JSON.parse(invoice.autoFilledFields) : [];
|
||||
const updatedAutoFields = autoFilledFields.filter((f: string) => f !== "ventilationComptable");
|
||||
updateFieldMutation.mutate({
|
||||
id: invoice.id,
|
||||
data: { ventilationComptable: e.target.value || undefined },
|
||||
data: {
|
||||
ventilationComptable: e.target.value || undefined,
|
||||
autoFilledFields: updatedAutoFields.length > 0 ? JSON.stringify(updatedAutoFields) : null
|
||||
},
|
||||
});
|
||||
}
|
||||
}}
|
||||
className="w-full px-2 py-1 border rounded text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
className={`w-full px-2 py-1 border rounded text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 ${getFieldColor(invoice, "ventilationComptable")}`}
|
||||
>
|
||||
<option value="">-</option>
|
||||
{allocations?.map((alloc) => (
|
||||
|
||||
Reference in New Issue
Block a user