Restored to 'c6c9369fcb5c7d3e28183ea74a5639cbc7677de6'

Replit-Restored-To: c6c9369fcb
This commit is contained in:
michaelschal committed 2025-08-16 07:37:28 +00:00
1 parent 911090fc7d
commit 15cf7f32a1
6 files changed
+31 -361

No files matched your search

+1 -1
View File
@@ -2,4 +2,4 @@
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
#HttpOnly_localhost FALSE / FALSE 1755415501 connect.sid s%3Akq9rv9dYrk7ObCvKdTPAwZUL7UaWGfqL.x5cl2uDVboBhiWzQE1pp4349NXCs5x%2ByI8OHzfVl8%2Bw
#HttpOnly_localhost FALSE / FALSE 1755334812 connect.sid s%3AIUsQcAbYjJ2Yu9GRwhXwQt22rGvvMGRo.zTBgX64O5zq1nh16Yc0umuKKQnBAy0xAn4BkA5iErOQ
-5
View File
@@ -1,5 +0,0 @@
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
#HttpOnly_localhost FALSE / FALSE 1755415612 connect.sid s%3ALA_C3VgRvKbgl1oG2suDWpO0NfwuqOpQ.%2B1GRLR0jeREW8LP6YP5YNnQJG0UtzOoYylg2R3Vf4Hg
-5
View File
@@ -1,5 +0,0 @@
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
#HttpOnly_localhost FALSE / FALSE 1755415612 connect.sid s%3ARzj7n77KbzyUgygzi1pqOCY7ToJBSeT7.A2HiKInsuth99WAyYy%2Bc2ZnZePEr3rtLet6qccJCXN0
+1 -9
View File
@@ -25,19 +25,11 @@ export async function hashPassword(password: string) {
async function comparePasswords(supplied: string, stored: string) {
console.log('🔐 comparePasswords:', { supplied: 'HIDDEN', stored: stored?.substring(0, 20) + '...', hasFormat: stored?.includes('.') });
// Simple password comparison for development users
// Simple password comparison for development (admin.salt format)
if (stored === 'admin.salt' && supplied === 'admin') {
console.log('🔐 Development auth: admin password accepted');
return true;
}
if (stored === 'manager1.salt' && supplied === 'manager1') {
console.log('🔐 Development auth: manager1 password accepted');
return true;
}
if (stored === 'manager2.salt' && supplied === 'manager2') {
console.log('🔐 Development auth: manager2 password accepted');
return true;
}
// Vérifier le format du mot de passe stocké pour production
if (!stored || !stored.includes('.')) {
+2 -93
View File
@@ -1395,75 +1395,6 @@ export async function registerRoutes(app: Express): Promise<Server> {
}
});
// DEBUG ROUTE for production diagnosis
app.get('/api/debug/customer-orders-raw', isAuthenticated, async (req: any, res) => {
try {
const user = await storage.getUserWithGroups(req.user.claims ? req.user.claims.sub : req.user.id);
if (!user || user.role !== 'admin') {
return res.status(403).json({ message: "Admin access required" });
}
console.log('🔍 [DEBUG] Raw customer orders analysis started');
// Get all customer orders without filtering
const allOrders = await storage.getCustomerOrders();
console.log('🔍 [DEBUG] Total orders in DB:', allOrders.length);
// Group by store and analyze dates
const analysis = allOrders.reduce((acc, order) => {
const groupId = order.groupId;
const groupName = order.group?.name || 'Unknown';
if (!acc[groupId]) {
acc[groupId] = {
groupId,
groupName,
orders: [],
count: 0,
latestDate: null,
oldestDate: null
};
}
acc[groupId].orders.push({
id: order.id,
customerName: order.customerName,
createdAt: order.createdAt,
status: order.status
});
acc[groupId].count++;
const orderDate = new Date(order.createdAt);
if (!acc[groupId].latestDate || orderDate > new Date(acc[groupId].latestDate)) {
acc[groupId].latestDate = order.createdAt;
}
if (!acc[groupId].oldestDate || orderDate < new Date(acc[groupId].oldestDate)) {
acc[groupId].oldestDate = order.createdAt;
}
return acc;
}, {} as Record<number, any>);
console.log('🔍 [DEBUG] Analysis by group:', analysis);
res.json({
totalOrders: allOrders.length,
analysis: Object.values(analysis),
sampleOrders: allOrders.slice(0, 10).map(order => ({
id: order.id,
groupId: order.groupId,
groupName: order.group?.name,
customerName: order.customerName,
createdAt: order.createdAt,
status: order.status
}))
});
} catch (error) {
console.error("Error in debug route:", error);
res.status(500).json({ error: error.message });
}
});
// Customer Orders routes
app.get('/api/customer-orders', isAuthenticated, async (req: any, res) => {
try {
@@ -1486,31 +1417,9 @@ export async function registerRoutes(app: Express): Promise<Server> {
}
}
console.log('🔍 [PRODUCTION DEBUG] Customer Orders API called with:', {
groupIds,
userRole: user.role,
userId: user.id,
userGroups: user.userGroups?.map(ug => ({ groupId: ug.groupId, groupName: ug.group?.name }))
});
console.log('Customer Orders API called with:', { groupIds, userRole: user.role });
const customerOrders = await storage.getCustomerOrders(groupIds);
console.log('🔍 [PRODUCTION DEBUG] Customer Orders returned:', customerOrders.length, 'items');
// Debug: Group orders by groupId to see distribution
const ordersByGroup = customerOrders.reduce((acc, order) => {
const groupId = order.groupId || 'null';
if (!acc[groupId]) acc[groupId] = [];
acc[groupId].push(order);
return acc;
}, {} as Record<string, any[]>);
console.log('🔍 [PRODUCTION DEBUG] Orders distribution by group:',
Object.entries(ordersByGroup).map(([groupId, orders]) => ({
groupId,
count: orders.length,
latestDate: orders[0]?.createdAt,
groupName: orders[0]?.group?.name
}))
);
console.log('Customer Orders returned:', customerOrders.length, 'items');
res.json(customerOrders);
} catch (error) {
console.error("Error fetching customer orders:", error);
+27 -248
View File
@@ -1324,8 +1324,6 @@ export class DatabaseStorage implements IStorage {
// Real implementations for production operations
async getCustomerOrders(groupIds?: number[]): Promise<CustomerOrderWithRelations[]> {
console.log('🔍 [PRODUCTION DEBUG] getCustomerOrders called with groupIds:', groupIds);
let query = db
.select({
customerOrder: customerOrders,
@@ -1338,34 +1336,15 @@ export class DatabaseStorage implements IStorage {
if (groupIds && groupIds.length > 0) {
query = query.where(inArray(customerOrders.groupId, groupIds));
console.log('🔍 [PRODUCTION DEBUG] Filtering by groupIds:', groupIds);
}
try {
const results = await query.orderBy(desc(customerOrders.createdAt));
console.log('🔍 [PRODUCTION DEBUG] Raw SQL results count:', results.length);
// Debug: Log some sample data
if (results.length > 0) {
console.log('🔍 [PRODUCTION DEBUG] Sample results (first 3):');
results.slice(0, 3).forEach((row, idx) => {
console.log(` [${idx}] Order ID: ${row.customerOrder?.id}, GroupId: ${row.customerOrder?.groupId}, Customer: ${row.customerOrder?.customerName}, Created: ${row.customerOrder?.createdAt}`);
});
}
const mappedResults = results.map((row: any) => ({
...row.customerOrder,
supplier: row.supplier,
group: row.group,
creator: row.creator || { id: row.customerOrder.createdBy, username: 'unknown' }
}));
console.log('🔍 [PRODUCTION DEBUG] Final mapped results count:', mappedResults.length);
return mappedResults;
} catch (error) {
console.error('❌ [PRODUCTION ERROR] getCustomerOrders failed:', error);
throw error;
}
const results = await query.orderBy(desc(customerOrders.createdAt));
return results.map((row: any) => ({
...row.customerOrder,
supplier: row.supplier,
group: row.group,
creator: row.creator || { id: row.customerOrder.createdBy, username: 'unknown' }
}));
}
async getCustomerOrder(id: number): Promise<CustomerOrderWithRelations | undefined> {
@@ -1884,7 +1863,6 @@ export class MemStorage implements IStorage {
private tasks = new Map<number, Task>();
private savTickets = new Map<number, SavTicket>();
private savTicketHistories = new Map<number, SavTicketHistory[]>();
private passwords = new Map<string, { password: string; hasFormat: boolean }>();
private idCounters = {
group: 1,
@@ -1914,14 +1892,13 @@ export class MemStorage implements IStorage {
firstName: 'Admin',
lastName: 'User',
profileImageUrl: null,
password: 'admin.salt', // Development format with salt
password: 'admin', // In real app, this would be hashed
role: 'admin',
passwordChanged: false,
createdAt: new Date(),
updatedAt: new Date(),
};
this.users.set(adminUser.id, adminUser);
this.passwords.set('admin', { password: 'admin.salt', hasFormat: true });
// Initialize group counter
this.idCounters.group = 2;
@@ -1930,124 +1907,39 @@ export class MemStorage implements IStorage {
this.idCounters.supplier = 2;
// Create test groups
const testGroup1: Group = {
const testGroup: Group = {
id: 1,
name: 'Magasin 1',
name: 'Magasin Test',
color: '#3B82F6',
nocodbConfigId: 1, // Référence vers la config NocoDB de test
nocodbTableName: 'invoices_store1',
nocodbTableName: 'invoices',
nocodbTableId: 'mrr733dfb8wtt9b', // ID réel de la table NocoDB
invoiceColumnName: 'invoice_reference',
nocodbBlColumnName: 'bl_number',
nocodbAmountColumnName: 'amount',
nocodbSupplierColumnName: 'supplier',
webhookUrl: 'https://webhook.test/invoice-upload-store1',
webhookUrl: 'https://webhook.test/invoice-upload',
createdAt: new Date(),
updatedAt: new Date(),
};
const testGroup2: Group = {
id: 2,
name: 'Magasin 2',
color: '#10B981',
nocodbConfigId: 1, // Même config NocoDB
nocodbTableName: 'invoices_store2',
nocodbTableId: 'store2table123', // Différent ID de table
invoiceColumnName: 'invoice_reference',
nocodbBlColumnName: 'bl_number',
nocodbAmountColumnName: 'amount',
nocodbSupplierColumnName: 'supplier',
webhookUrl: 'https://webhook.test/invoice-upload-store2',
createdAt: new Date(),
updatedAt: new Date(),
};
this.groups.set(testGroup1.id, testGroup1);
this.groups.set(testGroup2.id, testGroup2);
this.idCounters.group = 3;
this.groups.set(testGroup.id, testGroup);
this.idCounters.group = 2;
// Create test suppliers
const testSupplier1: Supplier = {
// Create test supplier
const testSupplier: Supplier = {
id: 1,
name: 'Fournisseur Magasin 1',
contact: 'magasin1@supplier.com',
name: 'Fournisseur Test',
contact: 'test@supplier.com',
phone: '0123456789',
hasDlc: true,
automaticReconciliation: true,
createdAt: new Date(),
updatedAt: new Date(),
};
const testSupplier2: Supplier = {
id: 2,
name: 'Fournisseur Magasin 2',
contact: 'magasin2@supplier.com',
phone: '0987654321',
hasDlc: true,
hasDlc: false,
automaticReconciliation: false,
createdAt: new Date(),
updatedAt: new Date(),
};
this.suppliers.set(testSupplier1.id, testSupplier1);
this.suppliers.set(testSupplier2.id, testSupplier2);
this.idCounters.supplier = 3;
// Create additional test users for different stores
const manager1User: User = {
id: 'manager1',
username: 'manager1',
email: 'manager1@magasin1.com',
name: 'Manager Magasin 1',
firstName: 'Manager',
lastName: 'Magasin 1',
profileImageUrl: null,
password: 'manager1.salt',
role: 'manager',
passwordChanged: false,
createdAt: new Date(),
updatedAt: new Date(),
};
this.users.set(manager1User.id, manager1User);
this.passwords.set('manager1', { password: 'manager1.salt', hasFormat: true });
const manager2User: User = {
id: 'manager2',
username: 'manager2',
email: 'manager2@magasin2.com',
name: 'Manager Magasin 2',
firstName: 'Manager',
lastName: 'Magasin 2',
profileImageUrl: null,
password: 'manager2.salt',
role: 'manager',
passwordChanged: false,
createdAt: new Date(),
updatedAt: new Date(),
};
this.users.set(manager2User.id, manager2User);
this.passwords.set('manager2', { password: 'manager2.salt', hasFormat: true });
// Set up user-group associations
this.userGroups.set('admin', [
{ userId: 'admin', groupId: 1 },
{ userId: 'admin', groupId: 2 }
]);
this.userGroups.set('manager1', [
{ userId: 'manager1', groupId: 1 }
]);
this.userGroups.set('manager2', [
{ userId: 'manager2', groupId: 2 }
]);
this.suppliers.set(testSupplier.id, testSupplier);
this.idCounters.supplier = 2;
console.log('✅ MemStorage initialized with admin user (admin/admin)');
console.log('🔧 Test users created:', {
admin: 'Access to both stores',
manager1: 'Access to Magasin 1 only',
manager2: 'Access to Magasin 2 only'
});
}
// User operations
@@ -2122,16 +2014,6 @@ export class MemStorage implements IStorage {
async deleteUser(id: string): Promise<void> {
this.users.delete(id);
this.userGroups.delete(id);
this.passwords.delete(id);
}
async validatePassword(userId: string, password: string): Promise<boolean> {
const storedPassword = this.passwords.get(userId);
if (!storedPassword) return false;
// For development, we use simple string comparison
// In production, this would use bcrypt comparison
return storedPassword.password === password;
}
// Group operations
@@ -2801,9 +2683,7 @@ export class MemStorage implements IStorage {
}
private initializeExtraTestData() {
console.log('🔧 Initialisation des données de test des commandes clients...');
// Add test customer orders for Store 1 (groupId: 1) - Recent dates
// Add test customer orders
const testOrder1: CustomerOrder = {
id: 1,
supplierId: 1,
@@ -2822,8 +2702,8 @@ export class MemStorage implements IStorage {
isPromotionalPrice: false,
customerNotified: false,
notes: 'Livraison urgente demandée',
createdAt: new Date('2025-08-15'),
updatedAt: new Date('2025-08-15'),
createdAt: new Date('2025-01-15'),
updatedAt: new Date('2025-01-15'),
};
const testOrder2: CustomerOrder = {
@@ -2844,114 +2724,13 @@ export class MemStorage implements IStorage {
isPromotionalPrice: true,
customerNotified: true,
notes: null,
createdAt: new Date('2025-08-10'),
updatedAt: new Date('2025-08-12'),
};
// Add test customer orders for Store 2 (groupId: 2) - Recent dates
const testOrder3: CustomerOrder = {
id: 3,
supplierId: 2,
groupId: 2,
createdBy: 'admin',
orderTaker: 'Manager Store 2',
customerName: 'Jean Durand',
customerPhone: '0147258369',
customerEmail: 'jean.durand@email.fr',
productDesignation: 'Canapé 3 places',
productReference: 'CAN-001',
gencode: null,
quantity: 1,
deposit: '300.00' as any,
status: 'Commande passée',
isPromotionalPrice: false,
customerNotified: true,
notes: 'Client préfère livraison matin',
createdAt: new Date('2025-08-14'),
updatedAt: new Date('2025-08-14'),
};
const testOrder4: CustomerOrder = {
id: 4,
supplierId: 2,
groupId: 2,
createdBy: 'admin',
orderTaker: 'Manager Store 2',
customerName: 'Sophie Moreau',
customerPhone: '0612345678',
customerEmail: null,
productDesignation: 'Étagère murale',
productReference: null,
gencode: null,
quantity: 3,
deposit: '75.00' as any,
status: 'En attente de Commande',
isPromotionalPrice: true,
customerNotified: false,
notes: 'Prix promotionnel -20%',
createdAt: new Date('2025-08-16'),
updatedAt: new Date('2025-08-16'),
};
// Add more recent orders for Store 1 to show variety
const testOrder5: CustomerOrder = {
id: 5,
supplierId: 1,
groupId: 1,
createdBy: 'admin',
orderTaker: 'Admin',
customerName: 'Michel Blanc',
customerPhone: '0188776655',
customerEmail: 'michel.blanc@test.fr',
productDesignation: 'Set de jardin complet',
productReference: 'JARDIN-SET-01',
gencode: null,
quantity: 1,
deposit: '250.00' as any,
status: 'Livrée',
isPromotionalPrice: false,
customerNotified: true,
notes: 'Commande livrée avec succès',
createdAt: new Date('2025-08-09'),
updatedAt: new Date('2025-08-11'),
};
const testOrder6: CustomerOrder = {
id: 6,
supplierId: 1,
groupId: 1,
createdBy: 'admin',
orderTaker: 'Admin',
customerName: 'Isabelle Roux',
customerPhone: '0199887766',
customerEmail: null,
productDesignation: 'Barbecue électrique',
productReference: null,
gencode: null,
quantity: 1,
deposit: '120.00' as any,
status: 'En attente de Commande',
isPromotionalPrice: false,
customerNotified: false,
notes: 'À confirmer avec le client',
createdAt: new Date('2025-08-16'),
updatedAt: new Date('2025-08-16'),
createdAt: new Date('2025-01-10'),
updatedAt: new Date('2025-01-12'),
};
this.customerOrders.set(1, testOrder1);
this.customerOrders.set(2, testOrder2);
this.customerOrders.set(3, testOrder3);
this.customerOrders.set(4, testOrder4);
this.customerOrders.set(5, testOrder5);
this.customerOrders.set(6, testOrder6);
this.idCounters.customerOrder = 7;
console.log('✅ Données de test initialisées:', {
totalOrders: 6,
store1Orders: [1, 2, 5, 6],
store2Orders: [3, 4],
recentDates: '2025-08-09 à 2025-08-16'
});
this.idCounters.customerOrder = 3;
// Add test DLC products
const testDlc1: DlcProduct = {