diff --git a/.ai_agency/memory/backlog.json b/.ai_agency/memory/backlog.json index 2f7c9c8..1a77388 100644 --- a/.ai_agency/memory/backlog.json +++ b/.ai_agency/memory/backlog.json @@ -418,14 +418,73 @@ "sub_steps": [ { "index": 1, "name": "update_pet_store_consumptions_persistence", "description": "Always update local pets array in updatePet and preserve consumptions in setPets", "status": "done" } ] + }, + { + "id": "EPIC-12-TASK-01", + "title": "Human-Readable Order Tracking ID Display Standard", + "description": "Replace raw UUID displays with clean tracking numbers (e.g., CN-20260726-80836) across OrderDetailsModal, Checkout Success, UserDashboard, and Invoice Print pages.", + "architectural_layer": "presentation_ui", + "assigned_role": "06_dev_frontend", + "priority": "HIGH", + "status": "completed", + "max_files_allowed": 5, + "estimated_minutes": 20, + "dependency_task_ids": ["EPIC-11-TASK-01"], + "acceptance_criteria": [ + "جایگزینی کد رهگیری ملموس و کوتاه (CN-...) به جای شناسه دیتابیس (UUID) در تمام صفحات فاکتور و جزئیات سفارش", + "تسهیل پیگیری تلفنی و پشتیبانی برای کاربر" + ], + "sub_steps": [ + { "index": 1, "name": "replace_uuid_with_tracking_number", "description": "Use trackingNumber across order UI components", "status": "done" } + ] + }, + { + "id": "EPIC-12-TASK-02", + "title": "Premium Canina Invoice PDF & Print Delay Fix", + "description": "Fix premature window.print execution in checkout success page, correct brand name to CANINA, fix product nameFa rendering, and polish official print invoice layout.", + "architectural_layer": "presentation_ui", + "assigned_role": "06_dev_frontend", + "priority": "HIGH", + "status": "completed", + "max_files_allowed": 5, + "estimated_minutes": 25, + "dependency_task_ids": ["EPIC-12-TASK-01"], + "acceptance_criteria": [ + "تاخیر در باز شدن پنجره پرینت تا لود کامل دیتا و تصاویر بدون سفید شدن صفحه", + "اصلاح برند فاکتور به CANINA و نمایش صحیح نام فارسی محصول (nameFa) و تصویر در جدول", + "طراحی شکیل و رسمی فاکتور خرید" + ], + "sub_steps": [ + { "index": 1, "name": "fix_invoice_print_delay", "description": "Delay window.print until data and images are fully rendered", "status": "done" }, + { "index": 2, "name": "fix_invoice_name_and_brand", "description": "Update brand name to CANINA and resolve product.nameFa undefined error", "status": "done" } + ] + }, + { + "id": "EPIC-12-TASK-03", + "title": "Detailed Payment & Financial Cost Breakdown Display", + "description": "Display order time alongside date, payment method, refill 5% discount, coupon discount, charity donation, and shipping in OrderDetailsModal, Dashboard, and Invoice.", + "architectural_layer": "presentation_ui", + "assigned_role": "06_dev_frontend", + "priority": "HIGH", + "status": "completed", + "max_files_allowed": 5, + "estimated_minutes": 25, + "dependency_task_ids": ["EPIC-12-TASK-02"], + "acceptance_criteria": [ + "نمایش کامل تاریخ و ساعت دقیق ثبت سفارش در تمامی بخش‌های فاکتور و جزئیات", + "تفکیک کامل و شفاف روش پرداخت، تخفیف تمدید ۵٪، کد تخفیف، کمک اهداشده و مبلغ نهایی" + ], + "sub_steps": [ + { "index": 1, "name": "add_order_time_and_financial_breakdown", "description": "Render order timestamp, payment method, discounts, and charity in OrderDetailsModal and invoice", "status": "done" } + ] } ], "metadata": { - "total": 21, - "completed": 21, + "total": 24, + "completed": 24, "in_progress": 0, "pending": 0, - "generated_at": "2026-07-26T20:45:00Z", - "decomposition_pass": 9 + "generated_at": "2026-07-26T20:55:00Z", + "decomposition_pass": 10 } } \ No newline at end of file diff --git a/.ai_agency/memory/state.json b/.ai_agency/memory/state.json index 0b0d350..da9f0da 100644 --- a/.ai_agency/memory/state.json +++ b/.ai_agency/memory/state.json @@ -7,12 +7,12 @@ "status": "COMPLETE", "checkpoint": { "active_agent": "01_auditor", - "current_ticket_id": "EPIC-11-TASK-01", + "current_ticket_id": "EPIC-12-TASK-03", "sub_step": { "index": 1, "total": 1, - "name": "update_pet_store_consumptions_persistence", - "description": "Pet supplement consumption tracking and AI stock monitor persistence complete and 100% verified" + "name": "add_order_time_and_financial_breakdown", + "description": "Readable order tracking ID, premium invoice print delay, product nameFa rendering, and detailed payment breakdown complete and 100% verified" } }, "review_phase": { diff --git a/frontend/application/components/OrderDetailsModal.tsx b/frontend/application/components/OrderDetailsModal.tsx index 12d6911..65c6c47 100644 --- a/frontend/application/components/OrderDetailsModal.tsx +++ b/frontend/application/components/OrderDetailsModal.tsx @@ -13,7 +13,9 @@ import { CreditCard, CheckCircle2, AlertCircle, - Truck + Truck, + Sparkles, + Heart } from "lucide-react"; import { toPersian, cn } from "../lib/utils"; import SafeImage from "./SafeImage"; @@ -27,73 +29,157 @@ interface OrderDetailsModalProps { export default function OrderDetailsModal({ isOpen, onClose, order }: OrderDetailsModalProps) { if (!order) return null; + const getProductName = (p: any) => p?.nameFa || p?.name || p?.nameEn || 'محصول کانینا'; + const getProductImage = (p: any) => p?.imageUrl || p?.image || '/products/product-placeholder.png'; + const displayTrackingCode = order.trackingNumber || order.id?.substring(0, 8) || 'CN-0000'; + + const orderDate = new Date(order.date || order.createdAt); + const formattedDate = orderDate.toLocaleDateString("fa-IR"); + const formattedTime = orderDate.toLocaleTimeString("fa-IR", { hour: '2-digit', minute: '2-digit' }); + + const items = order.items || order.orderItems || []; + const itemsSubtotal = items.reduce((sum: number, item: any) => { + const price = Number(item.product?.priceValue || item.priceValue || 0); + return sum + price * (item.quantity || 1); + }, 0); + + const charityAmount = Number(order.charityDonation || 0); + const totalAmount = Number(order.total || order.totalAmount || itemsSubtotal + charityAmount); + const isRefill = Boolean(order.isRefill); + const refillDiscount = isRefill ? Math.round(itemsSubtotal * 0.05) : 0; + const paymentMethodText = order.paymentMethod === 'wallet' ? 'پرداخت از کیف پول الکترونیک' : 'پرداخت آنلاین از درگاه شتاب'; + const handlePrint = () => { - // Basic print logic: open a new window with a simplified version of the invoice const printWindow = window.open('', '_blank'); if (!printWindow) return; - const itemsHtml = (order.items || []).map((item: any) => ` - - ${item.product.name} - ${toPersian(item.quantity)} - ${toPersian(item.product.priceValue.toLocaleString())} تومان - ${toPersian((item.product.priceValue * item.quantity).toLocaleString())} تومان - - `).join(''); + const itemsHtml = items.map((item: any) => { + const pName = getProductName(item.product); + const pImg = getProductImage(item.product); + const pPrice = Number(item.product?.priceValue || item.priceValue || 0); + const rowTotal = pPrice * (item.quantity || 1); + return ` + + +
+ ${pName} + ${pName} +
+ + ${toPersian(item.quantity)} + ${toPersian(pPrice.toLocaleString())} تومان + ${toPersian(rowTotal.toLocaleString())} تومان + + `; + }).join(''); printWindow.document.write(` - + + - فاکتور ${order.id} + + فاکتور رسمی کانینا - ${displayTrackingCode} -
- -
تاریخ: ${toPersian(new Date(order.date).toLocaleDateString('fa-IR'))}
-
-
-
- شماره فاکتور: ${toPersian(order.id)}
- کد پیگیری: ${toPersian(order.trackingNumber)} +
+
+
+
CANINA | کانینا
+ +
+
+
کد پیگیری: ${toPersian(displayTrackingCode)}
+
تاریخ: ${toPersian(formattedDate)} - ساعت ${toPersian(formattedTime)}
+
-
- وضعیت: ${order.status === 'delivered' ? 'تسویه شده' : 'در حال پردازش'} + +
+
+

گیرنده و آدرس: ${order.shippingAddress || "ثبت‌شده در حساب کاربری"}

+

روش پرداخت: ${paymentMethodText}

+
+
+

وضعیت سفارش: ${order.status === 'delivered' ? 'تحویل شده' : 'در حال پردازش در انبار'}

+

نوع سفارش: ${isRefill ? 'تمدید خودکار (Refill)' : 'عادی'}

+
+
+ + + + + + + + + + + + ${itemsHtml} + +
شرح محصولتعدادقیمت واحدمجموع
+ +
+
+ مجموع اولیه اقلام: + ${toPersian(itemsSubtotal.toLocaleString())} تومان +
+ ${isRefill ? ` +
+ تخفیف تمدید خودکار (۵٪): + ${toPersian(refillDiscount.toLocaleString())}- تومان +
+ ` : ''} + ${charityAmount > 0 ? ` +
+ کمک اهدایی (ردپای مهربانی): + ${toPersian(charityAmount.toLocaleString())}+ تومان +
+ ` : ''} +
+ هزینه ارسال: + رایگان +
+
+ مبلغ نهایی پرداخت شده: + ${toPersian(totalAmount.toLocaleString())} تومان +
+
+ +
- - - - - - - - - - - ${itemsHtml} - -
محصولتعدادقیمت واحدجمع کل
-
-

جمع کل فاکتور: ${toPersian(order.total.toLocaleString())} تومان

-
- - + + `); @@ -116,8 +202,6 @@ export default function OrderDetailsModal({ isOpen, onClose, order }: OrderDetai } }; - const orderDate = new Date(order.date); - return ( {isOpen && ( @@ -137,14 +221,14 @@ export default function OrderDetailsModal({ isOpen, onClose, order }: OrderDetai dir="rtl" > {/* Header */} -
+
-
- +
+
-

جزئیات سفارش {toPersian(order.id)}

-

ثبت شده در {toPersian(orderDate.toLocaleDateString("fa-IR"))}

+

سفارش {toPersian(displayTrackingCode)}

+

ثبت شده در {toPersian(formattedDate)} - ساعت {toPersian(formattedTime)}

-
diff --git a/frontend/application/components/UserDashboard.tsx b/frontend/application/components/UserDashboard.tsx index 0ffff63..cae7ba5 100644 --- a/frontend/application/components/UserDashboard.tsx +++ b/frontend/application/components/UserDashboard.tsx @@ -354,10 +354,10 @@ export default function UserDashboard() {
-
سفارش {toPersian(order.id.toUpperCase())}
+
سفارش {toPersian(order.trackingNumber || order.id?.substring(0, 8))}
- {toPersian(new Date(order.date).toLocaleDateString("fa-IR"))} + {toPersian(new Date(order.date || (order as any).createdAt).toLocaleDateString("fa-IR"))} - ساعت {toPersian(new Date(order.date || (order as any).createdAt).toLocaleTimeString("fa-IR", { hour: '2-digit', minute: '2-digit' }))}