mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-23 06:58:19 +02:00
7 files changed
+249
-1010
No files matched your search
+140
@@ -0,0 +1,140 @@
|
|||||||
|
|
||||||
|
|
||||||
|
🔗 Database initialization: {
|
||||||
|
|
||||||
|
NODE_ENV: 'production',
|
||||||
|
|
||||||
|
isProduction: true,
|
||||||
|
|
||||||
|
hasDbUrl: true,
|
||||||
|
|
||||||
|
dbHost: 'logiflow-db'
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
🐳 PRODUCTION: Using standard PostgreSQL
|
||||||
|
|
||||||
|
✅ PostgreSQL connection test successful
|
||||||
|
|
||||||
|
🐳 PRODUCTION: Using PostgreSQL storage
|
||||||
|
|
||||||
|
🐳 PRODUCTION: Local auth configured with PostgreSQL sessions
|
||||||
|
|
||||||
|
🐳 PRODUCTION: Starting LogiFlow application
|
||||||
|
|
||||||
|
🐳 Environment: { NODE_ENV: 'production', DATABASE_URL: 'Present', PORT: '3000' }
|
||||||
|
|
||||||
|
🔍 Using development storage and authentication
|
||||||
|
|
||||||
|
🔧 Using memory session store for development
|
||||||
|
|
||||||
|
Warning: connect.session() MemoryStore is not
|
||||||
|
|
||||||
|
designed for a production environment, as it will leak
|
||||||
|
|
||||||
|
memory, and will not scale past a single process.
|
||||||
|
|
||||||
|
🐳 Serving static files from: /app/dist/public
|
||||||
|
|
||||||
|
🐳 PRODUCTION: LogiFlow serving on port 3000
|
||||||
|
|
||||||
|
✅ Production admin user found: { id: 'admin_local', username: 'admin', passwordFormat: 'present' }
|
||||||
|
|
||||||
|
✅ Admin user exists, preserving current password
|
||||||
|
|
||||||
|
HEAD /api/health 200 in 5ms
|
||||||
|
|
||||||
|
📄 SPA: Serving index.html for /bl-reconciliation
|
||||||
|
|
||||||
|
🔍 PRODUCTION /api/user - req.user: {
|
||||||
|
|
||||||
|
id: 'admin_local',
|
||||||
|
|
||||||
|
role: 'admin',
|
||||||
|
|
||||||
|
hasUserGroups: true,
|
||||||
|
|
||||||
|
userGroupsLength: 0,
|
||||||
|
|
||||||
|
userGroups: []
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
GET /api/user 304 in 10ms
|
||||||
|
|
||||||
|
🔍 PRODUCTION /api/user - req.user: {
|
||||||
|
|
||||||
|
id: 'admin_local',
|
||||||
|
|
||||||
|
role: 'admin',
|
||||||
|
|
||||||
|
hasUserGroups: true,
|
||||||
|
|
||||||
|
userGroupsLength: 0,
|
||||||
|
|
||||||
|
userGroups: []
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
GET /api/user 304 in 9ms
|
||||||
|
|
||||||
|
GET /api/suppliers 304 in 19ms
|
||||||
|
|
||||||
|
🔍 PRODUCTION /api/user - req.user: {
|
||||||
|
|
||||||
|
id: 'admin_local',
|
||||||
|
|
||||||
|
role: 'admin',
|
||||||
|
|
||||||
|
hasUserGroups: true,
|
||||||
|
|
||||||
|
userGroupsLength: 0,
|
||||||
|
|
||||||
|
userGroups: []
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
GET /api/user 304 in 20ms
|
||||||
|
|
||||||
|
🔍 PRODUCTION /api/user - req.user: {
|
||||||
|
|
||||||
|
id: 'admin_local',
|
||||||
|
|
||||||
|
role: 'admin',
|
||||||
|
|
||||||
|
hasUserGroups: true,
|
||||||
|
|
||||||
|
userGroupsLength: 0,
|
||||||
|
|
||||||
|
userGroups: []
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
GET /api/user 304 in 8ms
|
||||||
|
|
||||||
|
Deliveries API called with: {
|
||||||
|
|
||||||
|
startDate: undefined,
|
||||||
|
|
||||||
|
endDate: undefined,
|
||||||
|
|
||||||
|
storeId: undefined,
|
||||||
|
|
||||||
|
withBL: undefined,
|
||||||
|
|
||||||
|
userRole: 'admin'
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Admin filtering deliveries with groupIds: undefined
|
||||||
|
|
||||||
|
Fetching all deliveries
|
||||||
|
|
||||||
|
Deliveries returned: 81 items
|
||||||
|
|
||||||
|
GET /api/deliveries 304 in 50ms
|
||||||
|
|
||||||
|
GET /api/groups 304 in 36ms
|
||||||
|
|
||||||
|
HEAD /api/health 200 in 1ms
|
||||||
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 289 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 510 KiB |
@@ -142,7 +142,7 @@ export default function BLReconciliation() {
|
|||||||
supplier: delivery.supplier
|
supplier: delivery.supplier
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!delivery.group?.nocodbTableName && !delivery.group?.nocodbConfigId) {
|
if (!delivery.group?.nocodbTableName && !delivery.group?.nocodbConfigId && !delivery.group?.webhookUrl) {
|
||||||
toast({
|
toast({
|
||||||
title: "Vérification non disponible",
|
title: "Vérification non disponible",
|
||||||
description: "Ce magasin n'a pas de configuration NocoDB",
|
description: "Ce magasin n'a pas de configuration NocoDB",
|
||||||
@@ -178,6 +178,11 @@ export default function BLReconciliation() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const deliveries = await response.json();
|
const deliveries = await response.json();
|
||||||
|
|
||||||
|
// Debug : examiner les données des groupes en production
|
||||||
|
console.log('🔍 DEBUG Production - Première livraison:', deliveries[0]);
|
||||||
|
console.log('🔍 DEBUG Production - Groupe de la première livraison:', deliveries[0]?.group);
|
||||||
|
console.log('🔍 DEBUG Production - Champs disponibles dans group:', deliveries[0]?.group ? Object.keys(deliveries[0].group) : 'Pas de groupe');
|
||||||
const filtered = Array.isArray(deliveries) ? deliveries.filter((d: any) => d.status === 'delivered') : [];
|
const filtered = Array.isArray(deliveries) ? deliveries.filter((d: any) => d.status === 'delivered') : [];
|
||||||
|
|
||||||
return filtered.sort((a: any, b: any) => new Date(b.deliveredDate || b.updatedAt).getTime() - new Date(a.deliveredDate || a.updatedAt).getTime());
|
return filtered.sort((a: any, b: any) => new Date(b.deliveredDate || b.updatedAt).getTime() - new Date(a.deliveredDate || a.updatedAt).getTime());
|
||||||
@@ -641,7 +646,7 @@ export default function BLReconciliation() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Icône de vérification de facture */}
|
{/* Icône de vérification de facture */}
|
||||||
{(delivery.group?.nocodbTableName || delivery.group?.nocodbConfigId) && (
|
{(delivery.group?.nocodbTableName || delivery.group?.nocodbConfigId || delivery.group?.webhookUrl) && (
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
{verifyingDeliveries.has(delivery.id) ? (
|
{verifyingDeliveries.has(delivery.id) ? (
|
||||||
<Clock className="h-4 w-4 text-blue-500 animate-spin" title="Vérification en cours..." />
|
<Clock className="h-4 w-4 text-blue-500 animate-spin" title="Vérification en cours..." />
|
||||||
|
|||||||
+21
-1008
File diff suppressed because it is too large.
Load diff
@@ -10,6 +10,8 @@ import {
|
|||||||
customerOrders,
|
customerOrders,
|
||||||
dlcProducts,
|
dlcProducts,
|
||||||
tasks,
|
tasks,
|
||||||
|
nocodbConfig,
|
||||||
|
invoiceVerificationCache,
|
||||||
type User,
|
type User,
|
||||||
type UpsertUser,
|
type UpsertUser,
|
||||||
type Group,
|
type Group,
|
||||||
@@ -42,6 +44,10 @@ import {
|
|||||||
type DlcProductWithRelations,
|
type DlcProductWithRelations,
|
||||||
type Task,
|
type Task,
|
||||||
type InsertTask,
|
type InsertTask,
|
||||||
|
type NocodbConfig,
|
||||||
|
type InsertNocodbConfig,
|
||||||
|
type InvoiceVerificationCache,
|
||||||
|
type InsertInvoiceVerificationCache,
|
||||||
} from "@shared/schema";
|
} from "@shared/schema";
|
||||||
import { db } from "./db";
|
import { db } from "./db";
|
||||||
import { eq, and, inArray, desc, sql, gte, lte } from "drizzle-orm";
|
import { eq, and, inArray, desc, sql, gte, lte } from "drizzle-orm";
|
||||||
@@ -120,10 +126,16 @@ export interface IStorage {
|
|||||||
// NocoDB Configuration operations
|
// NocoDB Configuration operations
|
||||||
getNocodbConfigs(): Promise<NocodbConfig[]>;
|
getNocodbConfigs(): Promise<NocodbConfig[]>;
|
||||||
getNocodbConfig(id: number): Promise<NocodbConfig | undefined>;
|
getNocodbConfig(id: number): Promise<NocodbConfig | undefined>;
|
||||||
|
getActiveNocodbConfig(): Promise<NocodbConfig | undefined>;
|
||||||
createNocodbConfig(config: InsertNocodbConfig): Promise<NocodbConfig>;
|
createNocodbConfig(config: InsertNocodbConfig): Promise<NocodbConfig>;
|
||||||
updateNocodbConfig(id: number, config: Partial<InsertNocodbConfig>): Promise<NocodbConfig>;
|
updateNocodbConfig(id: number, config: Partial<InsertNocodbConfig>): Promise<NocodbConfig>;
|
||||||
deleteNocodbConfig(id: number): Promise<void>;
|
deleteNocodbConfig(id: number): Promise<void>;
|
||||||
|
|
||||||
|
// Invoice Verification Cache operations
|
||||||
|
getInvoiceVerificationCache(cacheKey: string): Promise<InvoiceVerificationCache | undefined>;
|
||||||
|
createInvoiceVerificationCache(cache: InsertInvoiceVerificationCache): Promise<InvoiceVerificationCache>;
|
||||||
|
clearExpiredCache(): Promise<void>;
|
||||||
|
|
||||||
// Customer Order operations
|
// Customer Order operations
|
||||||
getCustomerOrders(groupIds?: number[]): Promise<CustomerOrderWithRelations[]>;
|
getCustomerOrders(groupIds?: number[]): Promise<CustomerOrderWithRelations[]>;
|
||||||
getCustomerOrder(id: number): Promise<CustomerOrderWithRelations | undefined>;
|
getCustomerOrder(id: number): Promise<CustomerOrderWithRelations | undefined>;
|
||||||
@@ -1104,6 +1116,26 @@ export class DatabaseStorage implements IStorage {
|
|||||||
await db.delete(nocodbConfig).where(eq(nocodbConfig.id, id));
|
await db.delete(nocodbConfig).where(eq(nocodbConfig.id, id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getActiveNocodbConfig(): Promise<NocodbConfig | undefined> {
|
||||||
|
const [config] = await db.select().from(nocodbConfig).where(eq(nocodbConfig.isActive, true));
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoice Verification Cache operations
|
||||||
|
async getInvoiceVerificationCache(cacheKey: string): Promise<InvoiceVerificationCache | undefined> {
|
||||||
|
const [cache] = await db.select().from(invoiceVerificationCache).where(eq(invoiceVerificationCache.cacheKey, cacheKey));
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
async createInvoiceVerificationCache(cache: InsertInvoiceVerificationCache): Promise<InvoiceVerificationCache> {
|
||||||
|
const [newCache] = await db.insert(invoiceVerificationCache).values(cache).returning();
|
||||||
|
return newCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
async clearExpiredCache(): Promise<void> {
|
||||||
|
await db.delete(invoiceVerificationCache).where(sql`${invoiceVerificationCache.expiresAt} < NOW()`);
|
||||||
|
}
|
||||||
|
|
||||||
// Customer Order operations
|
// Customer Order operations
|
||||||
async getCustomerOrders(groupIds?: number[]): Promise<CustomerOrderWithRelations[]> {
|
async getCustomerOrders(groupIds?: number[]): Promise<CustomerOrderWithRelations[]> {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -141,6 +141,37 @@ export const publicityParticipations = pgTable("publicity_participations", {
|
|||||||
pk: primaryKey({ columns: [table.publicityId, table.groupId] })
|
pk: primaryKey({ columns: [table.publicityId, table.groupId] })
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Configuration NocoDB globale pour la vérification des factures
|
||||||
|
export const nocodbConfig = pgTable("nocodb_config", {
|
||||||
|
id: serial("id").primaryKey(),
|
||||||
|
name: varchar("name").notNull(),
|
||||||
|
baseUrl: varchar("base_url").notNull(),
|
||||||
|
projectId: varchar("project_id").notNull(),
|
||||||
|
apiToken: varchar("api_token").notNull(),
|
||||||
|
description: text("description"),
|
||||||
|
isActive: boolean("is_active").default(true),
|
||||||
|
createdBy: varchar("created_by"),
|
||||||
|
createdAt: timestamp("created_at").defaultNow(),
|
||||||
|
updatedAt: timestamp("updated_at").defaultNow(),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Cache de vérification des factures
|
||||||
|
export const invoiceVerificationCache = pgTable("invoice_verification_cache", {
|
||||||
|
id: serial("id").primaryKey(),
|
||||||
|
cacheKey: varchar("cache_key", { length: 255 }).notNull(),
|
||||||
|
groupId: integer("group_id").notNull(),
|
||||||
|
invoiceReference: varchar("invoice_reference", { length: 255 }).notNull(),
|
||||||
|
supplierName: varchar("supplier_name", { length: 255 }),
|
||||||
|
exists: boolean("exists").notNull(),
|
||||||
|
matchType: varchar("match_type", { length: 50 }).notNull(),
|
||||||
|
errorMessage: text("error_message"),
|
||||||
|
cacheHit: boolean("cache_hit").default(false),
|
||||||
|
apiCallTime: integer("api_call_time"),
|
||||||
|
expiresAt: timestamp("expires_at").notNull(),
|
||||||
|
createdAt: timestamp("created_at").defaultNow(),
|
||||||
|
updatedAt: timestamp("updated_at").defaultNow(),
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -472,6 +503,21 @@ export const insertTaskSchema = createInsertSchema(tasks).omit({
|
|||||||
dueDate: z.coerce.date().optional().nullable(), // Convertit automatiquement les chaînes en Date
|
dueDate: z.coerce.date().optional().nullable(), // Convertit automatiquement les chaînes en Date
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const insertNocodbConfigSchema = createInsertSchema(nocodbConfig).omit({
|
||||||
|
id: true,
|
||||||
|
createdAt: true,
|
||||||
|
updatedAt: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const insertInvoiceVerificationCacheSchema = createInsertSchema(invoiceVerificationCache).omit({
|
||||||
|
id: true,
|
||||||
|
createdAt: true,
|
||||||
|
updatedAt: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
export type InsertNocodbConfig = z.infer<typeof insertNocodbConfigSchema>;
|
||||||
|
export type InsertInvoiceVerificationCache = z.infer<typeof insertInvoiceVerificationCacheSchema>;
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
export type User = typeof users.$inferSelect;
|
export type User = typeof users.$inferSelect;
|
||||||
export type UpsertUser = z.infer<typeof insertUserSchema>;
|
export type UpsertUser = z.infer<typeof insertUserSchema>;
|
||||||
@@ -586,6 +632,9 @@ export type PublicityWithRelations = Publicity & {
|
|||||||
export type NocodbConfig = typeof nocodbConfig.$inferSelect;
|
export type NocodbConfig = typeof nocodbConfig.$inferSelect;
|
||||||
export type InsertNocodbConfig = z.infer<typeof insertNocodbConfigSchema>;
|
export type InsertNocodbConfig = z.infer<typeof insertNocodbConfigSchema>;
|
||||||
|
|
||||||
|
export type InvoiceVerificationCache = typeof invoiceVerificationCache.$inferSelect;
|
||||||
|
export type InsertInvoiceVerificationCache = z.infer<typeof insertInvoiceVerificationCacheSchema>;
|
||||||
|
|
||||||
export type CustomerOrder = typeof customerOrders.$inferSelect;
|
export type CustomerOrder = typeof customerOrders.$inferSelect;
|
||||||
export type InsertCustomerOrder = z.infer<typeof insertCustomerOrderSchema>;
|
export type InsertCustomerOrder = z.infer<typeof insertCustomerOrderSchema>;
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user