mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-24 07:28:19 +02:00
fix(dlc): filter stockEpuise products from DLC stats and invalidate stats cache
This commit is contained in:
1 parent
16ef17957d
commit
cb1a1a933c
2 files changed
+32
-27
No files matched your search
@@ -82,6 +82,7 @@ export function DlcAlertModal({ isOpen, onClose, dlcStats, selectedStoreId }: Dl
|
|||||||
});
|
});
|
||||||
// Refresh DLC stats and products
|
// Refresh DLC stats and products
|
||||||
queryClient.invalidateQueries({ queryKey: ["/api/dlc-products"] });
|
queryClient.invalidateQueries({ queryKey: ["/api/dlc-products"] });
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["/api/dlc-products/stats"] });
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: () => {
|
||||||
toast({
|
toast({
|
||||||
|
|||||||
+31
-27
@@ -1520,20 +1520,20 @@ export class DatabaseStorage implements IStorage {
|
|||||||
// LOG: Debug des publicités récupérées
|
// LOG: Debug des publicités récupérées
|
||||||
console.log(`📋 PUBLICITES FETCHED: ${results.length} résultats pour année ${year || 'toutes'}`);
|
console.log(`📋 PUBLICITES FETCHED: ${results.length} résultats pour année ${year || 'toutes'}`);
|
||||||
if (results.length > 0) {
|
if (results.length > 0) {
|
||||||
console.log('🔍 PREMIERS RESULTATS:', results.slice(0, 3).map((p, i) => `${i+1}. N°${p.pubNumber} - ${p.designation}`));
|
console.log('🔍 PREMIERS RESULTATS:', results.slice(0, 3).map((p, i) => `${i + 1}. N°${p.pubNumber} - ${p.designation}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
const publicityIds = results.map((p: any) => p.id);
|
const publicityIds = results.map((p: any) => p.id);
|
||||||
const participations = publicityIds.length > 0
|
const participations = publicityIds.length > 0
|
||||||
? await db
|
? await db
|
||||||
.select({
|
.select({
|
||||||
publicityId: publicityParticipations.publicityId,
|
publicityId: publicityParticipations.publicityId,
|
||||||
groupId: publicityParticipations.groupId,
|
groupId: publicityParticipations.groupId,
|
||||||
group: groups,
|
group: groups,
|
||||||
})
|
})
|
||||||
.from(publicityParticipations)
|
.from(publicityParticipations)
|
||||||
.leftJoin(groups, eq(publicityParticipations.groupId, groups.id))
|
.leftJoin(groups, eq(publicityParticipations.groupId, groups.id))
|
||||||
.where(inArray(publicityParticipations.publicityId, publicityIds))
|
.where(inArray(publicityParticipations.publicityId, publicityIds))
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
// Sort by pubNumber as integer on the server side for consistency
|
// Sort by pubNumber as integer on the server side for consistency
|
||||||
@@ -2127,16 +2127,19 @@ export class DatabaseStorage implements IStorage {
|
|||||||
WHEN ${dlcProducts.expiryDate} > ${today.toISOString().split('T')[0]}
|
WHEN ${dlcProducts.expiryDate} > ${today.toISOString().split('T')[0]}
|
||||||
AND ${dlcProducts.status} != 'valides'
|
AND ${dlcProducts.status} != 'valides'
|
||||||
AND (${dlcProducts.processedUntilExpiry} IS NULL OR ${dlcProducts.processedUntilExpiry} = false)
|
AND (${dlcProducts.processedUntilExpiry} IS NULL OR ${dlcProducts.processedUntilExpiry} = false)
|
||||||
|
AND (${dlcProducts.stockEpuise} IS NULL OR ${dlcProducts.stockEpuise} = false)
|
||||||
THEN 1 END)`,
|
THEN 1 END)`,
|
||||||
expiringSoon: sql<number>`COUNT(CASE
|
expiringSoon: sql<number>`COUNT(CASE
|
||||||
WHEN ${dlcProducts.expiryDate} BETWEEN ${today.toISOString().split('T')[0]} AND ${alertDate.toISOString().split('T')[0]}
|
WHEN ${dlcProducts.expiryDate} BETWEEN ${today.toISOString().split('T')[0]} AND ${alertDate.toISOString().split('T')[0]}
|
||||||
AND ${dlcProducts.status} != 'valides'
|
AND ${dlcProducts.status} != 'valides'
|
||||||
AND (${dlcProducts.processedUntilExpiry} IS NULL OR ${dlcProducts.processedUntilExpiry} = false)
|
AND (${dlcProducts.processedUntilExpiry} IS NULL OR ${dlcProducts.processedUntilExpiry} = false)
|
||||||
|
AND (${dlcProducts.stockEpuise} IS NULL OR ${dlcProducts.stockEpuise} = false)
|
||||||
THEN 1 END)`,
|
THEN 1 END)`,
|
||||||
expired: sql<number>`COUNT(CASE
|
expired: sql<number>`COUNT(CASE
|
||||||
WHEN ${dlcProducts.expiryDate} <= ${today.toISOString().split('T')[0]}
|
WHEN ${dlcProducts.expiryDate} <= ${today.toISOString().split('T')[0]}
|
||||||
AND ${dlcProducts.status} != 'valides'
|
AND ${dlcProducts.status} != 'valides'
|
||||||
AND (${dlcProducts.processedUntilExpiry} IS NULL OR ${dlcProducts.processedUntilExpiry} = false)
|
AND (${dlcProducts.processedUntilExpiry} IS NULL OR ${dlcProducts.processedUntilExpiry} = false)
|
||||||
|
AND (${dlcProducts.stockEpuise} IS NULL OR ${dlcProducts.stockEpuise} = false)
|
||||||
THEN 1 END)`
|
THEN 1 END)`
|
||||||
})
|
})
|
||||||
.from(dlcProducts)
|
.from(dlcProducts)
|
||||||
@@ -3075,8 +3078,8 @@ export class DatabaseStorage implements IStorage {
|
|||||||
count: sql<number>`COUNT(${deliveries.id})`,
|
count: sql<number>`COUNT(${deliveries.id})`,
|
||||||
amount: sql<number>`COALESCE(SUM(CAST(${deliveries.blAmount} AS NUMERIC)), 0)`
|
amount: sql<number>`COALESCE(SUM(CAST(${deliveries.blAmount} AS NUMERIC)), 0)`
|
||||||
})
|
})
|
||||||
.from(deliveries)
|
.from(deliveries)
|
||||||
.innerJoin(suppliers, eq(deliveries.supplierId, suppliers.id));
|
.innerJoin(suppliers, eq(deliveries.supplierId, suppliers.id));
|
||||||
|
|
||||||
if (deliveryConditions.length) supplierQuery.where(and(...deliveryConditions));
|
if (deliveryConditions.length) supplierQuery.where(and(...deliveryConditions));
|
||||||
const topSuppliers = await supplierQuery
|
const topSuppliers = await supplierQuery
|
||||||
@@ -3091,9 +3094,9 @@ export class DatabaseStorage implements IStorage {
|
|||||||
orders: sql<number>`COUNT(DISTINCT ${orders.id})`,
|
orders: sql<number>`COUNT(DISTINCT ${orders.id})`,
|
||||||
deliveries: sql<number>`COUNT(DISTINCT ${deliveries.id})`
|
deliveries: sql<number>`COUNT(DISTINCT ${deliveries.id})`
|
||||||
})
|
})
|
||||||
.from(groups)
|
.from(groups)
|
||||||
.leftJoin(orders, eq(groups.id, orders.groupId))
|
.leftJoin(orders, eq(groups.id, orders.groupId))
|
||||||
.leftJoin(deliveries, eq(groups.id, deliveries.groupId));
|
.leftJoin(deliveries, eq(groups.id, deliveries.groupId));
|
||||||
|
|
||||||
if (filters.groupIds?.length) {
|
if (filters.groupIds?.length) {
|
||||||
storeQuery.where(inArray(groups.id, filters.groupIds));
|
storeQuery.where(inArray(groups.id, filters.groupIds));
|
||||||
@@ -3137,7 +3140,7 @@ export class DatabaseStorage implements IStorage {
|
|||||||
}): Promise<Array<{ date: string; orders: number; deliveries: number }>> {
|
}): Promise<Array<{ date: string; orders: number; deliveries: number }>> {
|
||||||
const granularity = filters.granularity || 'day';
|
const granularity = filters.granularity || 'day';
|
||||||
const dateFormat = granularity === 'day' ? 'YYYY-MM-DD' :
|
const dateFormat = granularity === 'day' ? 'YYYY-MM-DD' :
|
||||||
granularity === 'week' ? 'YYYY-IW' : 'YYYY-MM';
|
granularity === 'week' ? 'YYYY-IW' : 'YYYY-MM';
|
||||||
|
|
||||||
// Build WHERE clauses with direct value substitution
|
// Build WHERE clauses with direct value substitution
|
||||||
const orderConditions: string[] = [];
|
const orderConditions: string[] = [];
|
||||||
@@ -3226,8 +3229,8 @@ export class DatabaseStorage implements IStorage {
|
|||||||
deliveries: sql<number>`COUNT(${deliveries.id})`,
|
deliveries: sql<number>`COUNT(${deliveries.id})`,
|
||||||
amount: sql<number>`COALESCE(SUM(CAST(${deliveries.blAmount} AS NUMERIC)), 0)`
|
amount: sql<number>`COALESCE(SUM(CAST(${deliveries.blAmount} AS NUMERIC)), 0)`
|
||||||
})
|
})
|
||||||
.from(deliveries)
|
.from(deliveries)
|
||||||
.innerJoin(suppliers, eq(deliveries.supplierId, suppliers.id));
|
.innerJoin(suppliers, eq(deliveries.supplierId, suppliers.id));
|
||||||
|
|
||||||
if (conditions.length) query.where(and(...conditions));
|
if (conditions.length) query.where(and(...conditions));
|
||||||
|
|
||||||
@@ -3980,7 +3983,7 @@ export class MemStorage implements IStorage {
|
|||||||
|
|
||||||
async getUserGroups(): Promise<UserGroup[]> { return []; }
|
async getUserGroups(): Promise<UserGroup[]> { return []; }
|
||||||
async assignUserToGroup(): Promise<UserGroup> { return {} as UserGroup; }
|
async assignUserToGroup(): Promise<UserGroup> { return {} as UserGroup; }
|
||||||
async removeUserFromGroup(): Promise<void> {}
|
async removeUserFromGroup(): Promise<void> { }
|
||||||
|
|
||||||
async getMonthlyStats(): Promise<any> {
|
async getMonthlyStats(): Promise<any> {
|
||||||
return {
|
return {
|
||||||
@@ -4030,9 +4033,9 @@ export class MemStorage implements IStorage {
|
|||||||
async getPublicity(): Promise<PublicityWithRelations | undefined> { return undefined; }
|
async getPublicity(): Promise<PublicityWithRelations | undefined> { return undefined; }
|
||||||
async createPublicity(): Promise<Publicity> { return {} as Publicity; }
|
async createPublicity(): Promise<Publicity> { return {} as Publicity; }
|
||||||
async updatePublicity(): Promise<Publicity> { return {} as Publicity; }
|
async updatePublicity(): Promise<Publicity> { return {} as Publicity; }
|
||||||
async deletePublicity(): Promise<void> {}
|
async deletePublicity(): Promise<void> { }
|
||||||
async getPublicityParticipations(): Promise<PublicityParticipation[]> { return []; }
|
async getPublicityParticipations(): Promise<PublicityParticipation[]> { return []; }
|
||||||
async setPublicityParticipations(): Promise<void> {}
|
async setPublicityParticipations(): Promise<void> { }
|
||||||
|
|
||||||
async getCustomerOrders(groupIds?: number[]): Promise<CustomerOrderWithRelations[]> {
|
async getCustomerOrders(groupIds?: number[]): Promise<CustomerOrderWithRelations[]> {
|
||||||
let orders = Array.from(this.customerOrders.values());
|
let orders = Array.from(this.customerOrders.values());
|
||||||
@@ -4103,9 +4106,9 @@ export class MemStorage implements IStorage {
|
|||||||
// Find orders where client not notified and status is 'Disponible'
|
// Find orders where client not notified and status is 'Disponible'
|
||||||
const pendingOrders = orders.filter(order => {
|
const pendingOrders = orders.filter(order => {
|
||||||
return !order.customerNotified &&
|
return !order.customerNotified &&
|
||||||
(order.status === 'Disponible' || order.status === 'disponible' ||
|
(order.status === 'Disponible' || order.status === 'disponible' ||
|
||||||
order.status === 'Arrivé' || order.status === 'arrivé' ||
|
order.status === 'Arrivé' || order.status === 'arrivé' ||
|
||||||
order.status === 'Prêt' || order.status === 'prêt');
|
order.status === 'Prêt' || order.status === 'prêt');
|
||||||
});
|
});
|
||||||
|
|
||||||
return pendingOrders.map(order => ({
|
return pendingOrders.map(order => ({
|
||||||
@@ -4151,7 +4154,7 @@ export class MemStorage implements IStorage {
|
|||||||
products = products.filter(product => {
|
products = products.filter(product => {
|
||||||
const supplier = this.suppliers.get(product.supplierId);
|
const supplier = this.suppliers.get(product.supplierId);
|
||||||
return product.productName.toLowerCase().includes(searchTerm) ||
|
return product.productName.toLowerCase().includes(searchTerm) ||
|
||||||
(supplier && supplier.name.toLowerCase().includes(searchTerm));
|
(supplier && supplier.name.toLowerCase().includes(searchTerm));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4299,17 +4302,18 @@ export class MemStorage implements IStorage {
|
|||||||
active: products.filter(p =>
|
active: products.filter(p =>
|
||||||
new Date(p.expiryDate) > today &&
|
new Date(p.expiryDate) > today &&
|
||||||
p.status !== 'valides' &&
|
p.status !== 'valides' &&
|
||||||
!p.processedUntilExpiry
|
!p.processedUntilExpiry &&
|
||||||
|
!p.stockEpuise
|
||||||
).length,
|
).length,
|
||||||
expiringSoon: products.filter(p => {
|
expiringSoon: products.filter(p => {
|
||||||
const expiry = new Date(p.expiryDate);
|
const expiry = new Date(p.expiryDate);
|
||||||
const isExpiringSoon = expiry >= today && expiry <= alertDate;
|
const isExpiringSoon = expiry >= today && expiry <= alertDate;
|
||||||
return isExpiringSoon && p.status !== 'valides' && !p.processedUntilExpiry;
|
return isExpiringSoon && p.status !== 'valides' && !p.processedUntilExpiry && !p.stockEpuise;
|
||||||
}).length,
|
}).length,
|
||||||
expired: products.filter(p => {
|
expired: products.filter(p => {
|
||||||
const expiry = new Date(p.expiryDate);
|
const expiry = new Date(p.expiryDate);
|
||||||
const isExpired = expiry <= today;
|
const isExpired = expiry <= today;
|
||||||
return isExpired && p.status !== 'valides' && !p.processedUntilExpiry;
|
return isExpired && p.status !== 'valides' && !p.processedUntilExpiry && !p.stockEpuise;
|
||||||
}).length
|
}).length
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user