diff --git a/attached_assets/image_1752921333407.png b/attached_assets/image_1752921333407.png
new file mode 100644
index 0000000..04316c9
Binary files /dev/null and b/attached_assets/image_1752921333407.png differ
diff --git a/client/src/components/SaleDetailsModal.tsx b/client/src/components/SaleDetailsModal.tsx
index ccb6a5b..963a33b 100644
--- a/client/src/components/SaleDetailsModal.tsx
+++ b/client/src/components/SaleDetailsModal.tsx
@@ -43,13 +43,24 @@ export default function SaleDetailsModal({ isOpen, sale, onClose }: SaleDetailsM
{/* Product Information */}
-
Informations Produit
-
-
Type d'article: {sale.typeArticle}
-
Catégorie: {sale.categorie}
-
Quantité: {sale.quantite}
-
Code produit: {sale.gencode || 'Non spécifié'}
-
+
Informations Produits
+ {sale.products && sale.products.length > 0 ? (
+
+ {sale.products.map((product: any, index: number) => (
+
+
Produit {index + 1}
+
+
Type d'article: {product.typeArticle}
+
Catégorie: {product.categorie}
+
Quantité: {product.quantite}
+
Code produit: {product.gencode || 'Non spécifié'}
+
+
+ ))}
+
+ ) : (
+
Aucun produit associé
+ )}
{/* Customer Information */}
diff --git a/server/storage.ts b/server/storage.ts
index 83406c4..f50eccf 100644
--- a/server/storage.ts
+++ b/server/storage.ts
@@ -201,6 +201,89 @@ export class DatabaseStorage implements IStorage {
return salesWithProducts;
}
+ async getAllSales(storeId?: number): Promise {
+ // Récupérer les ventes avec leurs produits
+ const query = db
+ .select({
+ // Sale fields
+ id: sales.id,
+ storeId: sales.storeId,
+ userId: sales.userId,
+ timestamp: sales.timestamp,
+ vendeur: sales.vendeur,
+ nom: sales.nom,
+ prenom: sales.prenom,
+ dateNaissance: sales.dateNaissance,
+ lieuNaissance: sales.lieuNaissance,
+ modePaiement: sales.modePaiement,
+ typeIdentite: sales.typeIdentite,
+ numeroIdentite: sales.numeroIdentite,
+ autoriteDelivrance: sales.autoriteDelivrance,
+ dateDelivrance: sales.dateDelivrance,
+ photo_recto: sales.photo_recto,
+ photo_verso: sales.photo_verso,
+ photo_ticket: sales.photo_ticket,
+ // Product fields
+ productId: saleProducts.id,
+ typeArticle: saleProducts.typeArticle,
+ categorie: saleProducts.categorie,
+ quantite: saleProducts.quantite,
+ gencode: saleProducts.gencode
+ })
+ .from(sales)
+ .leftJoin(saleProducts, eq(sales.id, saleProducts.saleId));
+
+ if (storeId) {
+ const results = await query.where(eq(sales.storeId, storeId)).orderBy(desc(sales.timestamp));
+ return this.groupSalesByProducts(results);
+ }
+
+ const results = await query.orderBy(desc(sales.timestamp));
+ return this.groupSalesByProducts(results);
+ }
+
+ private groupSalesByProducts(results: any[]): any[] {
+ const salesMap = new Map();
+
+ results.forEach(row => {
+ if (!salesMap.has(row.id)) {
+ salesMap.set(row.id, {
+ id: row.id,
+ storeId: row.storeId,
+ userId: row.userId,
+ timestamp: row.timestamp,
+ vendeur: row.vendeur,
+ nom: row.nom,
+ prenom: row.prenom,
+ dateNaissance: row.dateNaissance,
+ lieuNaissance: row.lieuNaissance,
+ modePaiement: row.modePaiement,
+ typeIdentite: row.typeIdentite,
+ numeroIdentite: row.numeroIdentite,
+ autoriteDelivrance: row.autoriteDelivrance,
+ dateDelivrance: row.dateDelivrance,
+ photo_recto: row.photo_recto,
+ photo_verso: row.photo_verso,
+ photo_ticket: row.photo_ticket,
+ products: []
+ });
+ }
+
+ // Ajouter le produit s'il existe
+ if (row.productId) {
+ salesMap.get(row.id).products.push({
+ id: row.productId,
+ typeArticle: row.typeArticle,
+ categorie: row.categorie,
+ quantite: row.quantite,
+ gencode: row.gencode
+ });
+ }
+ });
+
+ return Array.from(salesMap.values());
+ }
+
async deleteSale(id: number): Promise {
// Delete sale products first (cascade should handle this, but being explicit)
await db.delete(saleProducts).where(eq(saleProducts.saleId, id));