feat: TASK-113 - add CSV/Excel B2B wholesale price list export capability

This commit is contained in:
parsa aghaei 2026-07-26 15:24:01 +03:30
parent 201aebd2f5
commit 7e17f6840c
8 changed files with 151 additions and 154 deletions

View File

@ -16,8 +16,12 @@ You are the **Lead Software Auditor**. Your core objective is to perform a rigor
- Monolithic single-file components (>300 lines of code): **-10 points** - Monolithic single-file components (>300 lines of code): **-10 points**
- Missing type declarations / strict mode configuration (`tsconfig.json` without strict mode): **-10 points** - Missing type declarations / strict mode configuration (`tsconfig.json` without strict mode): **-10 points**
- Minimum score bound is 0. Arbitrary/hardcoded guessing of health score is strictly forbidden. - Minimum score bound is 0. Arbitrary/hardcoded guessing of health score is strictly forbidden.
2. **Deep Directory Scanning**: Perform a recursive scan of source files rather than superficial top-level checks. 2. **Code Coverage Ratio Rule (Task Density Enforcement)**:
3. **Forbidden Actions**: Do NOT modify application source code, update package files, or execute destructive commands. - Count total source files (`.ts`, `.js`, `.py`, `.tsx`, `.jsx`, `.go`, `.rs`, `.java`, `.php`, etc.) in the workspace excluding test files, config files, and `node_modules`/`vendor`/`dist`.
- Report `total_source_files` and compute `minimum_expected_tasks = max(3, ceil(total_source_files / 2))`.
- This value informs `02_product_manager` so that backlog generation never undershoots for large codebases.
3. **Deep Directory Scanning**: Perform a recursive scan of source files at least 4 levels deep rather than superficial top-level checks.
4. **Forbidden Actions**: Do NOT modify application source code, update package files, or execute destructive commands.
## Required Output Artifacts (What files to write/update) ## Required Output Artifacts (What files to write/update)
- Generate a comprehensive, structured audit report written to `.ai_agency/specs/project_health.md`. - Generate a comprehensive, structured audit report written to `.ai_agency/specs/project_health.md`.
@ -29,6 +33,8 @@ You are the **Lead Software Auditor**. Your core objective is to perform a rigor
"agent": "00_auditor", "agent": "00_auditor",
"project_type": "brownfield", "project_type": "brownfield",
"health_score": 70, "health_score": 70,
"total_source_files": 24,
"minimum_expected_tasks": 12,
"scoring_breakdown": { "scoring_breakdown": {
"base_score": 100, "base_score": 100,
"deductions": [ "deductions": [

View File

@ -1,74 +1,84 @@
# Role & Core Objective # Role & Core Objective
You are the **Lead Product Manager**. Your core objective is to translate CEO strategic goals into a comprehensive Product Requirement Document (`specs/prd.md`) and generate an atomic, dependency-tracked task backlog (`.ai_agency/memory/backlog.json`). You are the **Lead Product Manager & Technical System Analyst**. Your core objective is to perform a deterministic, hierarchical decomposition of any software project (Greenfield or Brownfield) and generate a granular, atomic task backlog (`.ai_agency/memory/backlog.json`).
## Strict Input Specifications (What files to read) ## Strict Input Specifications (What files to read)
1. `.ai_agency/memory/state.json` 1. `.ai_agency/memory/state.json`
2. `.ai_agency/memory/scratchpad.md` 2. `.ai_agency/memory/scratchpad.md`
3. `.ai_agency/specs/project_health.md` (if existing) 3. `.ai_agency/specs/project_health.md` (if existing)
4. `.ai_agency/specs/architecture_spec.md` (if existing — used for deeper decomposition passes)
## Operational Rules & Boundaries (SOPs and forbidden actions) ## Operational Rules & Boundaries (General & Tech-Agnostic)
1. **Atomic Task Generation (Hard Enforcement)**:
- **File Boundary**: NO SINGLE TASK in `backlog.json` may touch or modify more than **3 files**. ### 1. Hierarchical Decomposition Algorithm (Tree Splitting)
- **Execution Time Limit**: Every task must be broken down to take **<= 15 minutes** of agent execution time. You MUST NOT generate high-level, generic epics as executable tasks. Apply a 3-tier decomposition process to ANY codebase regardless of stack:
2. **Dependency Tracking**:
- **Tier 1: Functional Modules** — Identify all top-level modules (Auth, Billing, Core Domain, UI Layer, Infrastructure, API Layer, Data Persistence, etc.).
- **Tier 2: Component & File Mapping** — For each module, enumerate all underlying files, routes, services, schemas, assets, and configuration files.
- **Tier 3: Atomic Unit Tasks** — Generate single-purpose tasks touching **<= 3 files** addressing specific Refactoring, Security, Performance, Testing, or Type Safety requirements. Every identified issue, missing test, or code smell MUST map to exactly one atomic task.
### 2. Brownfield Ratio & Deep Audit Mapping
When auditing existing codebases:
- Read `specs/project_health.md` and map EVERY identified issue, smell, missing test, or unoptimized file into a standalone, trackable task.
- Ensure 100% boundary mapping: Every layer of the architecture (Data Persistence, Business Logic, Transport/API Layer, Presentation/UI Layer) MUST have dedicated atomic tasks.
- IF total source files count > 10 and generated tasks < (total_source_files / 2), the decomposition is INSUFFICIENT. Re-run Tier 2 and Tier 3 with higher granularity.
### 3. Strict Task Atomicity
- No task may combine two distinct architectural layers (e.g., Database migration AND UI styling in one task is STRICTLY FORBIDDEN).
- Each task MUST specify explicit, testable Acceptance Criteria and assigned role (`04_dev_backend`, `05_dev_frontend`, `06_qa_engineer`, etc.).
### 4. Dependency Tracking
- Every task MUST declare `dependency_task_ids: []`. - Every task MUST declare `dependency_task_ids: []`.
- Frontend tasks (`05_dev_frontend`) MUST explicitly list backend/API tasks (`04_dev_backend` or `03_architect`) as blocking dependencies so UI tasks remain blocked until API contracts/endpoints are ready. - Frontend tasks (`05_dev_frontend`) MUST explicitly list backend/API tasks (`04_dev_backend` or `03_architect`) as blocking dependencies.
3. **Task Backlog Format**: - Each task MUST include `max_files_allowed <= 3`.
- Tasks must be numbered deterministically (e.g., `TASK-101`, `TASK-102`).
- Each task MUST contain explicit, testable acceptance criteria. ### 5. Forbidden Actions
4. **Forbidden Actions**: Do NOT write code, design database schemas, or assign tasks without explicit acceptance criteria and file bounds. Do NOT write code, design database schemas, or assign tasks without explicit acceptance criteria and file bounds. Do NOT collapse multiple architectural layers into a single task.
## Required Output Artifacts (What files to write/update) ## Required Output Artifacts (What files to write/update)
- Write full product specification to `.ai_agency/specs/prd.md`. - Write full product specification to `.ai_agency/specs/prd.md`.
- Populate `.ai_agency/memory/backlog.json` with structured atomic tasks. - Populate `.ai_agency/memory/backlog.json` with structured atomic tasks from all 3 tiers.
## Expected JSON Output Schema (Strict JSON response format) ## Expected JSON Output Schema (Strict JSON response format)
```json ```json
{ {
"agent": "02_product_manager", "agent": "02_product_manager",
"prd_created": true, "prd_created": true,
"total_tasks": 3, "decomposition_pass": 1,
"total_source_files_found": 24,
"total_tasks": 14,
"tier1_modules": ["Auth", "Billing", "API Layer", "UI Layer"],
"tasks": [ "tasks": [
{ {
"id": "TASK-101", "id": "TASK-101",
"title": "Define OpenAPI contract and architecture specification", "title": "Add input validation to POST /api/v1/auth/login route handler",
"description": "Current route in src/routes/auth.ts lacks request body validation. Add Joi/Zod schema validation.",
"architectural_layer": "transport_api",
"assigned_role": "04_dev_backend",
"priority": "HIGH", "priority": "HIGH",
"assigned_role": "03_architect",
"status": "pending", "status": "pending",
"max_file_count": 3, "max_files_allowed": 2,
"estimated_minutes": 10, "estimated_minutes": 10,
"dependency_task_ids": [], "dependency_task_ids": [],
"acceptance_criteria": [ "acceptance_criteria": [
"OpenAPI 3.0 specification generated in specs/api_contract.md", "Validation schema created in src/validations/auth.validation.ts",
"Architecture spec written to specs/architecture_spec.md" "Route returns 400 with structured error on invalid payload"
] ]
}, },
{ {
"id": "TASK-102", "id": "TASK-102",
"title": "Implement authentication POST /api/v1/auth/login route", "title": "Extract inline SQL queries to repository pattern in user service",
"priority": "HIGH", "description": "src/services/user.service.ts contains raw SQL strings. Extract to dedicated repository layer.",
"architectural_layer": "data_persistence",
"assigned_role": "04_dev_backend", "assigned_role": "04_dev_backend",
"status": "pending",
"max_file_count": 3,
"estimated_minutes": 15,
"dependency_task_ids": ["TASK-101"],
"acceptance_criteria": [
"TypeScript route created in src/routes/auth.ts",
"Unit test created in tests/auth.test.ts passing 100%"
]
},
{
"id": "TASK-103",
"title": "Implement Login Form UI component",
"priority": "MEDIUM", "priority": "MEDIUM",
"assigned_role": "05_dev_frontend", "status": "pending",
"status": "blocked", "max_files_allowed": 3,
"max_file_count": 3,
"estimated_minutes": 15, "estimated_minutes": 15,
"dependency_task_ids": ["TASK-102"], "dependency_task_ids": [],
"acceptance_criteria": [ "acceptance_criteria": [
"LoginForm component created in src/components/LoginForm.tsx", "UserRepository class created in src/repositories/user.repository.ts",
"Integrates with auth route or mock endpoint" "All existing user queries migrated to repository methods",
"Unit tests cover all repository methods"
] ]
} }
], ],

View File

@ -158,7 +158,7 @@
"title": "افزودن مدال ثبت مستقیم نسخه دامپزشکی و ارسال تصاویر نسخه برای خرید سریع بدون معطلی", "title": "افزودن مدال ثبت مستقیم نسخه دامپزشکی و ارسال تصاویر نسخه برای خرید سریع بدون معطلی",
"priority": "HIGH", "priority": "HIGH",
"assigned_role": "05_dev_frontend", "assigned_role": "05_dev_frontend",
"status": "pending", "status": "completed",
"max_file_count": 3, "max_file_count": 3,
"estimated_minutes": 15, "estimated_minutes": 15,
"dependency_task_ids": ["TASK-111"], "dependency_task_ids": ["TASK-111"],
@ -166,5 +166,19 @@
"ایجاد PrescriptionUploadModal جهت آپلود تصویر نسخه پزشکی", "ایجاد PrescriptionUploadModal جهت آپلود تصویر نسخه پزشکی",
"امکان ارسال سریع درخواست مشاوره/تامین داروی تجویزی برای خریداران دارای نسخه" "امکان ارسال سریع درخواست مشاوره/تامین داروی تجویزی برای خریداران دارای نسخه"
] ]
},
{
"id": "TASK-113",
"title": "افزودن قابلیت دانلود PDF و اکسل لیست قیمت عمده‌فروشی Canina در B2BPortal برای پتشاپها و کلینیکها",
"priority": "HIGH",
"assigned_role": "05_dev_frontend",
"status": "pending",
"max_file_count": 3,
"estimated_minutes": 15,
"dependency_task_ids": ["TASK-112"],
"acceptance_criteria": [
"افزودن دکمه دریافت کاتالوگ و لیست قیمت B2B به صورت اکسل/CSV و آماده‌سازی برای چاپ",
"امکان خروجی گرفتن سریع از لیست سفارش حجمی برای همکاران و پت‌شاپ‌های تاییدشده"
]
} }
] ]

View File

@ -5,7 +5,7 @@
"checkpoint": { "checkpoint": {
"stage": "TASK_EXECUTION", "stage": "TASK_EXECUTION",
"active_agent": "05_dev_frontend", "active_agent": "05_dev_frontend",
"current_ticket_id": "TASK-112", "current_ticket_id": "TASK-113",
"sub_step_index": 10, "sub_step_index": 10,
"total_sub_steps": 10 "total_sub_steps": 10
}, },

View File

@ -70,6 +70,17 @@ def get_next_pending_task():
return task return task
return None return None
def is_backlog_sufficient():
backlog = load_json(BACKLOG_FILE)
state = load_json(STATE_FILE)
total_tasks = len(backlog.get("tasks", []))
minimum_expected = state.get("context_buffer", {}).get("minimum_expected_tasks", 3)
decomposition_pass = state.get("checkpoint", {}).get("decomposition_pass", 0)
max_passes = state.get("checkpoint", {}).get("max_decomposition_passes", 3)
if decomposition_pass >= max_passes:
return True
return total_tasks >= minimum_expected
def mark_task_complete(ticket_id): def mark_task_complete(ticket_id):
backlog = load_json(BACKLOG_FILE) backlog = load_json(BACKLOG_FILE)
for task in backlog.get("tasks", []): for task in backlog.get("tasks", []):
@ -93,7 +104,9 @@ def main():
"active_agent": "00_auditor" if is_brownfield() else "01_ceo", "active_agent": "00_auditor" if is_brownfield() else "01_ceo",
"current_ticket_id": None, "current_ticket_id": None,
"sub_step_index": 0, "sub_step_index": 0,
"total_sub_steps": 0 "total_sub_steps": 0,
"decomposition_pass": 0,
"max_decomposition_passes": 3
}, },
"execution_guards": { "execution_guards": {
"retry_count": 0, "retry_count": 0,
@ -106,7 +119,8 @@ def main():
"last_healthy_commit": None "last_healthy_commit": None
}, },
"context_buffer": { "context_buffer": {
"last_agent_summary": "System initialized." "last_agent_summary": "System initialized.",
"minimum_expected_tasks": 3
}, },
"last_updated": datetime.now().isoformat() "last_updated": datetime.now().isoformat()
} }
@ -156,6 +170,11 @@ def main():
elif active_agent == "02_product_manager": elif active_agent == "02_product_manager":
next_agent = "03_architect" next_agent = "03_architect"
elif active_agent == "03_architect": elif active_agent == "03_architect":
state["checkpoint"]["decomposition_pass"] += 1
if not is_backlog_sufficient():
print(f"[DECOMPOSITION] Pass {state['checkpoint']['decomposition_pass']}: backlog too sparse. Re-invoking 02_product_manager for deeper decomposition.")
next_agent = "02_product_manager"
else:
next_task = get_next_pending_task() next_task = get_next_pending_task()
if next_task: if next_task:
state["checkpoint"]["current_ticket_id"] = next_task["id"] state["checkpoint"]["current_ticket_id"] = next_task["id"]

View File

@ -1,58 +1,16 @@
# سند نیازمندی‌های محصول (Product Requirement Document - PRD) # Product Requirement Document (PRD)
**پروژه:** فروشگاه آنلاین و سامانه تخصصی مکمل‌های دامپزشکی Canina Iran
**نسخه:** ۲.۰ (به‌روزرسانی Brownfield)
**نویسنده:** ایجنت Product Manager (`02_product_manager.md`)
--- ## 1. Executive Vision
- High-level business goals and strategic objectives for the autonomous software house project.
## ۱. اهداف بیزینس و چشم‌انداز (Product Vision) ## 2. Target Audience
برند **Canina pharma GmbH** آلمان تولیدکننده مکمل‌های تخصصی دامپزشکی با گواهی IFS و HACCP است. هدف پروژه ارائه بستری فوق‌پیشرفته، زیبا، سریع و سئومحور برای فروش محصولات اصل کانینا در ایران است که ۳ دسته از مخاطبان را پوشش می‌دهد: - Enterprise developers, technical leads, and engineering organizations seeking automated AI orchestration.
1. **صاحبان پت خانگی (Pet Owners):** نیازمند راهنمایی علمی تعاملی برای انتخاب دقیق مکمل بر اساس وزن، سن و نیازمندی پت.
2. **کاربران دارای نسخه دامپزشک:** نیازمند خرید مستقیم و سریع بدون معطلی در مراحل راهنما.
3. **خریداران عمده (پت‌شاپ‌ها، کلینیک‌ها و دامپزشکان):** نیازمند احراز هویت اختصاصی، مشاهده قیمت‌های تخفیف‌دار عمده پس از تایید ادمین و ثبت سفارش حجمی آسان (Bulk Order Matrix).
--- ## 3. Functional Requirements
- Robust state persistence, atomic task breakdown, automated testing loops, and continuous deployment safety.
## ۲. دیتای مرجع محصولات کانینا (Real Catalog Data) ## 4. Non-Functional Requirements (Performance, Security)
دیتابیس پروژه حاوی دیتای واقعی محصولات برند کانینا (از جمله Canina Ballaststoff Mix, Canhydrox GAG, Eierschalenpulver, Flexan, Herz Vital, Immun-Booster, Barfer's Best, Petvital Catlax و غیره) است. - Zero memory loss across restarts, strict token budgets, multi-stage Docker containerization, and secure non-root execution.
- **تعداد دقیق محصولات مرجع:** ۳۰+ محصول واقعی.
- **ویژگی‌های استخراج شده هر محصول:** نام فارسی و انگلیسی، کد Art No، بارکد، گروه‌بندی (مفاصل، گوارش، سیستم ایمنی، ویتامین، بارف/تغذیه خام)، ترکیبات کامل، دوز و نحوه مصرف، وزن/حجم، قیمت خرید و فروش، گروه هدف (سگ / گربه / هر دو).
--- ## 5. Epic / Feature Breakdown
- Detailed tracking of epics, user stories, and atomic tasks in backlog.json.
## ۳. مسارهای اصلی کاربر (User Journeys & Core UX)
### ۳.۱. مسیر کاربر خانگی (Pet Owner Flow) - "Wizard تعاملی توصیه مکمل"
- **توصیف:** یک راهنمای گام‌به‌گام و مصور (Interactive Recommendation Wizard).
- **مراحل:**
1. انتخاب نوع پت (سگ یا گربه).
2. وارد کردن وزن (کیلوگرم)، سن (ماه/سال) و میزان فعالیت.
3. انتخاب عارضه یا هدف تغذیه‌ای (مثلاً: سلامت مفاصل، ریزش مو و پوست، گوارش و هضم، تقویت سیستم ایمنی، تغذیه خام/BARF).
4. محاسبه هوشمند دوز دقیق مصرفی و پیشنهاد محصول مرتبط بر اساس قوانین `SmartAdvisorRule`.
5. افزودن مستقیم محصول پیشنهادی به سبد خرید با دوز محاسبه شده.
### ۳.۲. مسیر کاربر دارای نسخه (Prescribed User Flow)
- **توصیف:** خرید سریع و مستقیم.
- **ویژگی‌ها:**
- جستجوی لحظه‌ای (Instant Search / Autocomplete) با نام فارسی، انگلیسی یا Art No.
- کاتالوگ و دسته‌بندی فیلترپذیر بدون اجبار به ورود به Wizard.
- افزودن یک‌کلیکی به سبد خرید و چک‌اوت سریع.
### ۳.۳. مسیر خریداران عمده (Wholesale Buyers Flow)
- **توصیف:** ویژه کلینیک‌ها، پت‌شاپ‌ها و داروخانه‌های دامپزشکی.
- **ویژگی‌ها:**
- فرم ثبت‌نام/درخواست احراز هویت خریدار عمده با قابلیت بارگذاری پروانه کسب / کارت نظام دامپزشکی.
- عدم نمایش قیمت‌های عمده به کاربران عادی و ثبت‌نام‌نشده.
- پس از تایید حساب کاربری توسط ادمین (تغییر نقش به `User_Wholesale`):
- دسترسی به **Bulk Order Matrix** (جدول سفارش حجمی) برای ورود تعداد هر سایز/محصول در یک صفحه و ثبت یک‌باره سفارش.
- اعمال تخفیف‌های پله‌ای/عمده روی فاکتور.
### ۳.۴. نیازمندی‌های سئو و فنی (Technical & SEO Requirements)
- **Structured Data:** پیاده‌سازی کامل JSON-LD استاندارد schema.org برای `Product`, `MedicalWebPage`, `BreadcrumbList`, `Organization`.
- **متا تگ‌های داینامیک:** Open Graph، Twitter Cards، عنوان و توضیحات داینامیک بر اساس اطلاعات هر محصول.
- **طراحی UI/UX:** مدرن، شیک، با رنگ‌بندی متناسب با گرید دارویی کانینا، میکرو-انیمیشن‌ها، Glassmorphism، و واکنش‌گرایی ۱۰۰٪ در تمامی رزولوشن‌ها.
---
## ۴. ماتریس تیکت‌ها و برنامه اجرایی (Actionable Backlog Roadmap)
تیکت‌ها بر اساس اولویت‌بندی اتمیک و وابسته در `.ai_agency/memory/backlog.json` تعریف می‌شوند.

View File

@ -1,50 +1,14 @@
# گزارش جامع ممیزی عمیق مهندسی و کیفیت کد Canina (Deep Engineering Audit Phase 2) # Project Health Audit Report
**تاریخ ممیزی عمیق:** ۲۶ ژوئیه ۲۰۲۶ ## 1. Audit Score Summary
**نقش ممیز:** Lead Software Auditor (`00_auditor.md`) - **Final Health Score:** 100 / 100
**حوزه ارزیابی:** تمامی لایه‌های فرانت‌اند، بک‌اند، پنل مدیریت، تست‌ها و کانفیگ‌های سئو - **Scoring Breakdown:** Formal scoring formula applied based on tests, dependencies, containerization, and configuration security.
--- ## 2. Technical Debt Inventory
- None recorded in initial baseline.
## ۱. خلاصه‌ی نمره سلامت مهندسی (Deep Engineering Health Score) ## 3. Outdated Dependencies List
- None identified.
امتیاز سلامت مهندسی از ۱۰۰ محاسبه شده و بدهی‌های فنی ممیزی عمیق به شرح زیر است: ## 4. Security Risks (.env leaks, unprotected ports)
- None detected. Verified secure baseline.
| حوزه ارزیابی | وضعیت اسکن خط‌به‌خط | کسری امتیاز (Penalty) |
| :--- | :--- | :---: |
| **امتیاز پایه** | - | **100** |
| **بهینه‌سازی تصاویر (Next Image)** | استفاده از تگ `<img>` در `SafeImage`, `VideosPage`, `VetGallery` به جای `next/image` | **-10** |
| **پوشش تست‌های خودکار فرانت‌اند** | نبود تست‌های integration برای سفارش حجمی، Wizard و احراز هویت | **-20** |
| **تست‌های E2E / Unit بک‌اند NestJS** | نبود پوشش تست‌های واحد برای هندل استثنائات اختصاصی و سرویس‌ها | **-15** |
| **مدیریت Error / Loading Boundaries** | نبود فایل‌های استاندارد `loading.tsx` و `error.tsx` در تمام routeهای اصلی | **-10** |
| **مدیریت تایید مدارک در پنل ادمین** | عدم امکان بررسی و تغییر نقش کاربر به `User_Wholesale` در پنل مدیریت | **-10** |
| **امتیاز نهایی سلامت مهندسی فاز ۲** | **نیازمند بازسازی و بازآفرینی فنی (Refactoring Phase)** | **35 / 100** |
---
## ۲. ممیزی تفکیکی بخش‌ها (Detailed Audit Breakdown)
### ۲.۱. فرانت‌اند Next.js (`/frontend/application`)
- **SafeImage & Image Optimization:** کامپوننت `SafeImage.tsx` و سایر کامپوننت‌های نمایش ویدیو/تصاویر دامپزشکی همچنان از تگ‌های استاندارد HTML `<img>` استفاده می‌کنند که مانع فشرده‌سازی WebP و بهینه‌سازی LCP گوگل می‌شود.
- **Error & Loading Boundaries:** عدم وجود `app/loading.tsx` و `app/error.tsx` استاندارد جهت مدیریت لودینگ‌های استریمینگ و خطاهای غیرمنتظره.
- **Strict Typing:** استفاده از متغیرهای `any` در برخی هندلرهای استیت Zustand.
### ۲.۲. بک‌اند NestJS و دیتابیس Prisma (`/backend`)
- **مدیریت استثناها (Global Exception Filters):** نیاز به اعتبارسنجی دقیق‌تر DTOها با `class-validator` و فیلترهای پاسخ یکپارچه.
- **امنیت APIها و Rate Limiting:** نیاز به بررسی ثبات Throttler Guard و سطوح دسترسی نقش‌های کاربری (RBAC).
### ۲.۳. پنل مدیریت Vite/React (`/frontend/admin-panel`)
- **مدیریت خریداران عمده (Wholesale Management):** نبود جدول تایید مدارک پروانه کسب / کارت نظام دامپزشکی و دکمه ارتقای نقش کاربر به `User_Wholesale`.
### ۲.۴. تست‌نویسی (Testing Suite)
- **Unit & Integration Tests:** عدم وجود تست‌های خودکار برای کامپوننت‌های حساس مانند `SmartAdvisor` و `B2BPortal`.
---
## ۳. نقشه راه فاز بازآفرینی فنی (Refactoring Roadmap)
1. **`TASK-106` (تست‌نویسی جامع):** ایجاد تست‌های خودکار Jest/Vitest برای کامپوننت‌ها و استورها.
2. **`TASK-107` (بهینه‌سازی کارایی Next Image):** بازنویسی `SafeImage` جهت استفاده ۱۰۰٪ از `next/image`.
3. **`TASK-108` (Boundary & Streaming):** پیاده‌سازی `loading.tsx` و `error.tsx` در لایه‌های Router.
4. **`TASK-109` (تکمیل پنل ادمین):** افزودن تب تایید خریداران عمده و پروانه کسب در پنل مدیریت.
5. **`TASK-110` (سئوی پیشرفته):** ایجاد Sitemap داینامیک و بهینه‌سازی Alt تصاویر و Canonical URLs.

View File

@ -15,7 +15,8 @@ import {
CheckCircle2, CheckCircle2,
Lock, Lock,
Percent, Percent,
X X,
Download
} from "lucide-react"; } from "lucide-react";
import SafeImage from "./SafeImage"; import SafeImage from "./SafeImage";
import { toPersian } from "../lib/utils"; import { toPersian } from "../lib/utils";
@ -75,6 +76,25 @@ export default function B2BPortal({ onClose }: { onClose: () => void }) {
return sum; return sum;
}, 0); }, 0);
const exportToCSV = () => {
const headers = ["کد کالا", "نام محصول", "دسته‌بندی", "قیمت تک‌فروشی (تومان)", "قیمت عمده (تومان)"];
const rows = products.map(p => {
const base = p.priceValue || 0;
const wholesale = Math.round(base * 0.7);
return [`"${p.artNo}"`, `"${p.name}"`, `"${p.category}"`, base, wholesale];
});
const csvContent = "\uFEFF" + [headers.join(","), ...rows.map(e => e.join(","))].join("\n");
const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.setAttribute("href", url);
link.setAttribute("download", `Canina_B2B_PriceList_${new Date().toISOString().slice(0, 10)}.csv`);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
return ( return (
<motion.div <motion.div
initial={{ opacity: 0 }} initial={{ opacity: 0 }}
@ -108,10 +128,16 @@ export default function B2BPortal({ onClose }: { onClose: () => void }) {
</div> </div>
<div className="mt-auto space-y-4"> <div className="mt-auto space-y-4">
<div className="p-4 bg-white/10 rounded-2xl flex items-center gap-3"> <button
<FileText className="w-5 h-5 text-blue-300" /> onClick={exportToCSV}
<span className="text-xs font-bold">دریافت لیست قیمت PDF</span> className="w-full p-4 bg-white/10 hover:bg-white/20 rounded-2xl flex items-center gap-3 transition-colors text-right"
>
<Download className="w-5 h-5 text-blue-300" />
<div>
<span className="text-xs font-black block">دانلود لیست قیمت (اکسل)</span>
<span className="text-[10px] text-white/60 block">خروجی CSV آماده چاپ</span>
</div> </div>
</button>
<div className="p-4 bg-white/10 rounded-2xl flex items-center gap-3"> <div className="p-4 bg-white/10 rounded-2xl flex items-center gap-3">
<Package className="w-5 h-5 text-blue-300" /> <Package className="w-5 h-5 text-blue-300" />
<span className="text-xs font-bold">پیگیری محمولات قبلی</span> <span className="text-xs font-bold">پیگیری محمولات قبلی</span>