Created a checkpoint

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 1e4433b5-47ab-464c-b663-fea2e53367dd
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Event-Id: 0a1b1aa1-ca7d-4f74-8ecb-8057b6feb3f6
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/1e4433b5-47ab-464c-b663-fea2e53367dd/7RN8LqE
This commit is contained in:
michaelschal committed 2025-10-31 09:03:53 +00:00
1 parent 345a2d968f
commit 0cf817e03f
18 files changed
+658 -33310

No files matched your search

+59
View File
@@ -41,10 +41,12 @@ import {
insertWeatherDataSchema,
insertWeatherSettingsSchema,
insertWebhookBapConfigSchema,
insertUtilitiesSchema,
insertAvoirSchema,
insertReconciliationCommentSchema,
users, groups, userGroups, suppliers, orders, deliveries, publicities, publicityParticipations,
customerOrders, nocodbConfig, dlcProducts, tasks, invoiceVerificationCache, dashboardMessages, webhookBapConfig,
utilities,
avoirs
} from "@shared/schema";
import { hasPermission } from "@shared/permissions";
@@ -219,6 +221,63 @@ export async function registerRoutes(app: Express): Promise<Server> {
}
});
// Routes pour configuration utilities
app.get('/api/utilities', isAuthenticated, async (req: any, res) => {
try {
const userId = req.user?.claims?.sub || req.user?.id;
if (!userId) {
return res.status(401).json({ error: 'Utilisateur non authentifié' });
}
const user = await storage.getUser(userId);
if (!user || (user.role !== 'admin' && user.role !== 'directeur')) {
return res.status(403).json({ error: 'Accès refusé - Admin ou Directeur uniquement' });
}
const config = await storage.getUtilities();
res.json(config || null);
} catch (error: any) {
console.error('❌ Erreur récupération utilities:', error);
res.status(500).json({ error: 'Erreur serveur', details: error.message });
}
});
app.post('/api/utilities', isAuthenticated, async (req: any, res) => {
try {
const userId = req.user?.claims?.sub || req.user?.id;
if (!userId) {
return res.status(401).json({ error: 'Utilisateur non authentifié' });
}
const user = await storage.getUser(userId);
if (!user || (user.role !== 'admin' && user.role !== 'directeur')) {
return res.status(403).json({ error: 'Accès refusé - Admin ou Directeur uniquement' });
}
const validatedData = insertUtilitiesSchema.parse(req.body);
const existingConfig = await storage.getUtilities();
let config: any;
if (existingConfig) {
config = await storage.updateUtilities(existingConfig.id, validatedData);
} else {
config = await storage.createUtilities(validatedData);
}
console.log('✅ Configuration utilities sauvegardée:', {
id: config.id,
salesAnalysisUrl: config.salesAnalysisUrl
});
res.json(config);
} catch (error: any) {
console.error('❌ Erreur sauvegarde utilities:', error);
res.status(500).json({ error: 'Erreur serveur', details: error.message });
}
});
// Route BAP pour envoi webhook n8n
app.post('/api/bap/send-webhook', isAuthenticated, async (req: any, res) => {
try {
+54
View File
@@ -73,6 +73,9 @@ import {
webhookBapConfig,
type WebhookBapConfig,
type InsertWebhookBapConfig,
utilities,
type Utilities,
type InsertUtilities,
avoirs,
type Avoir,
type InsertAvoir,
@@ -260,6 +263,11 @@ export interface IStorage {
createWebhookBapConfig(config: InsertWebhookBapConfig): Promise<WebhookBapConfig>;
updateWebhookBapConfig(id: number, config: Partial<InsertWebhookBapConfig>): Promise<WebhookBapConfig>;
// Utilities operations
getUtilities(): Promise<Utilities | undefined>;
createUtilities(utilities: InsertUtilities): Promise<Utilities>;
updateUtilities(id: number, utilities: Partial<InsertUtilities>): Promise<Utilities>;
// Reconciliation Comments operations
getReconciliationComments(deliveryId: number): Promise<ReconciliationCommentWithRelations[]>;
getReconciliationCommentById(id: number): Promise<ReconciliationCommentWithRelations | undefined>;
@@ -2812,6 +2820,26 @@ export class DatabaseStorage implements IStorage {
return config;
}
// Utilities operations
async getUtilities(): Promise<Utilities | undefined> {
const [result] = await db.select().from(utilities).limit(1);
return result;
}
async createUtilities(utilitiesData: InsertUtilities): Promise<Utilities> {
const [result] = await db.insert(utilities).values(utilitiesData).returning();
return result;
}
async updateUtilities(id: number, utilitiesData: Partial<InsertUtilities>): Promise<Utilities> {
const [result] = await db
.update(utilities)
.set({ ...utilitiesData, updatedAt: new Date() })
.where(eq(utilities.id, id))
.returning();
return result;
}
// Reconciliation Comments operations
async getReconciliationComments(deliveryId: number): Promise<ReconciliationCommentWithRelations[]> {
const comments = await db
@@ -5041,6 +5069,32 @@ export class MemStorage implements IStorage {
};
}
// Utilities operations
async getUtilities(): Promise<Utilities | undefined> {
// MemStorage ne stocke pas les utilities, retourne undefined
return undefined;
}
async createUtilities(utilitiesData: InsertUtilities): Promise<Utilities> {
// MemStorage ne supporte pas la création de utilities
return {
id: 1,
salesAnalysisUrl: utilitiesData.salesAnalysisUrl ?? null,
createdAt: new Date(),
updatedAt: new Date()
};
}
async updateUtilities(id: number, utilitiesData: Partial<InsertUtilities>): Promise<Utilities> {
// MemStorage ne supporte pas la mise à jour de utilities
return {
id,
salesAnalysisUrl: utilitiesData.salesAnalysisUrl ?? null,
createdAt: new Date(),
updatedAt: new Date()
};
}
// Announcement operations
async createAnnouncement(announcementData: InsertAnnouncement): Promise<Announcement> {
const announcementStorage = getAnnouncementStorage(