mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-11 17:27:31 +02:00
Restored to 'c6c9369fcb5c7d3e28183ea74a5639cbc7677de6'
Replit-Restored-To: c6c9369fcb
This commit is contained in:
1 parent
911090fc7d
commit
15cf7f32a1
6 files changed
+31
-361
No files matched your search
+1
-1
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
@@ -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 = {
|
||||
|
||||
Reference in new issue
Block a user