From 55f5a5570c6b53780492e4b37097bdc9288c7fdd Mon Sep 17 00:00:00 2001 From: parsa aghaei Date: Sun, 26 Jul 2026 20:32:15 +0330 Subject: [PATCH] fix(prisma,admin,auth): regenerate prisma client for isRefill, make charity round step configurable in admin, and fix root cause pet store reset --- .ai_agency/memory/backlog.json | 67 +++++++++++++++++-- .ai_agency/memory/state.json | 10 +-- frontend/admin-panel/src/pages/Settings.tsx | 18 ++++- .../application/components/CheckoutPage.tsx | 8 ++- frontend/application/lib/store/usePetStore.ts | 10 +++ frontend/application/lib/store/userStore.ts | 4 ++ 6 files changed, 104 insertions(+), 13 deletions(-) diff --git a/.ai_agency/memory/backlog.json b/.ai_agency/memory/backlog.json index 9c9ce9c..c16a052 100644 --- a/.ai_agency/memory/backlog.json +++ b/.ai_agency/memory/backlog.json @@ -319,14 +319,73 @@ "sub_steps": [ { "index": 1, "name": "audit_orders_service", "description": "Audit and fix edge case handling in orders.service.ts", "status": "done" } ] + }, + { + "id": "EPIC-09-TASK-01", + "title": "Prisma Client Regeneration & isRefill Type Sync", + "description": "Regenerate Prisma Client in backend node_modules so OrderCreateInput type includes isRefill and refillIntervalDays without IDE type errors.", + "architectural_layer": "database_orm", + "assigned_role": "05_dev_backend", + "priority": "HIGH", + "status": "completed", + "max_files_allowed": 3, + "estimated_minutes": 15, + "dependency_task_ids": ["EPIC-08-TASK-03"], + "acceptance_criteria": [ + "تولید مجدد و صحیح Prisma Client بدون تداخل پروسه‌ها", + "برطرف شدن کامل خطای TypeScript فیلد isRefill در orders.service.ts" + ], + "sub_steps": [ + { "index": 1, "name": "regenerate_prisma_client", "description": "Run npx prisma generate after closing locked processes", "status": "done" } + ] + }, + { + "id": "EPIC-09-TASK-02", + "title": "Admin Panel Configurable Charity Round-Up Step", + "description": "Add configurable charity_round_step setting in Admin Panel Settings page and connect CheckoutPage.tsx to use dynamic round step (10k, 50k, etc.) from SettingsStore.", + "architectural_layer": "presentation_ui", + "assigned_role": "06_dev_frontend", + "priority": "HIGH", + "status": "completed", + "max_files_allowed": 4, + "estimated_minutes": 25, + "dependency_task_ids": ["EPIC-09-TASK-01"], + "acceptance_criteria": [ + "امکان تنظیم پله‌های رند کردن مبلغ اهدایی در پنل مدیریت (Settings.tsx)", + "اعمال پله دینامیک رند کردن در CheckoutPage.tsx و محاسبه لحظه‌ای" + ], + "sub_steps": [ + { "index": 1, "name": "add_round_step_setting", "description": "Add charity_round_step setting in Admin Settings", "status": "done" }, + { "index": 2, "name": "wire_dynamic_round_step", "description": "Connect CheckoutPage.tsx to dynamic round step", "status": "done" } + ] + }, + { + "id": "EPIC-09-TASK-03", + "title": "Root Cause Multi-Store Auth Sync & Pet Profile Reset", + "description": "Root cause fix: reset usePetStore and all persisted local stores when user is unauthenticated so guest users NEVER see stale pet profiles, wallet, or address data.", + "architectural_layer": "state_management", + "assigned_role": "06_dev_frontend", + "priority": "HIGH", + "status": "completed", + "max_files_allowed": 5, + "estimated_minutes": 30, + "dependency_task_ids": ["EPIC-09-TASK-02"], + "acceptance_criteria": [ + "ریست شدن همزمان usePetStore و تمام استورها هنگام خروج یا مهمان بودن کاربر", + "جلوگیری ریشه‌ای از خوانده شدن اسم پت یا اطلاعات کاربر قبلی در حالت خروج" + ], + "sub_steps": [ + { "index": 1, "name": "add_pet_store_reset", "description": "Add reset method in usePetStore and call on logout", "status": "done" }, + { "index": 2, "name": "enforce_auth_guard_on_pet_store", "description": "Enforce isLoggedIn check on getActivePet()", "status": "done" } + ] } ], "metadata": { - "total": 16, - "completed": 16, + "total": 19, + "completed": 19, "in_progress": 0, "pending": 0, - "generated_at": "2026-07-26T20:30:00Z", - "decomposition_pass": 6 + "generated_at": "2026-07-26T20:35:00Z", + "decomposition_pass": 7 } } \ No newline at end of file diff --git a/.ai_agency/memory/state.json b/.ai_agency/memory/state.json index 38a97ec..e81ac6f 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-07-TASK-02", + "current_ticket_id": "EPIC-09-TASK-03", "sub_step": { - "index": 2, - "total": 2, - "name": "sync_client_layout_auth", - "description": "Auth state mismatch resolved; backend spec tests & frontend auth sync fully complete and verified" + "index": 3, + "total": 3, + "name": "enforce_auth_guard_on_pet_store", + "description": "Root cause pet profile mismatch resolved; Prisma Client regenerated, configurable charity round step added in admin panel, all builds 100% verified" } }, "review_phase": { diff --git a/frontend/admin-panel/src/pages/Settings.tsx b/frontend/admin-panel/src/pages/Settings.tsx index a22f5c7..9fca319 100644 --- a/frontend/admin-panel/src/pages/Settings.tsx +++ b/frontend/admin-panel/src/pages/Settings.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from 'react'; +import { useState, useEffect } from 'react'; import { Settings as SettingsIcon, Save, Truck, ShieldAlert, Percent, AlertCircle } from 'lucide-react'; import api from '../services/api'; import Spinner from '../components/ui/Spinner'; @@ -9,6 +9,7 @@ export default function Settings() { MIN_ORDER_AMOUNT: '', B2B_DISCOUNT_PERCENT: '', MAINTENANCE_MODE: 'false', + CHARITY_ROUND_STEP: '10000', }); const [isLoading, setIsLoading] = useState(true); const [isSaving, setIsSaving] = useState(false); @@ -23,6 +24,7 @@ export default function Settings() { MIN_ORDER_AMOUNT: response.data.data.MIN_ORDER_AMOUNT || '0', B2B_DISCOUNT_PERCENT: response.data.data.B2B_DISCOUNT_PERCENT || '0', MAINTENANCE_MODE: response.data.data.MAINTENANCE_MODE || 'false', + CHARITY_ROUND_STEP: response.data.data.CHARITY_ROUND_STEP || '10000', }); } } catch (err) { @@ -96,6 +98,20 @@ export default function Settings() { />

سفارشات زیر این مبلغ امکان ثبت نخواهند داشت (۰ = بدون محدودیت).

+ +
+ + setSettings({ ...settings, CHARITY_ROUND_STEP: e.target.value })} + className="w-full border border-gray-200 rounded-xl p-3 outline-none focus:ring-2 focus:ring-purple-500 font-bold" + dir="ltr" + placeholder="10000" + /> +

مبلغ فاکتور به اولین ضریب این عدد (مثلاً ۱۰,۰۰۰ یا ۵۰,۰۰۰ تومان) رند می‌شود.

+
diff --git a/frontend/application/components/CheckoutPage.tsx b/frontend/application/components/CheckoutPage.tsx index f163d6d..a1cc928 100644 --- a/frontend/application/components/CheckoutPage.tsx +++ b/frontend/application/components/CheckoutPage.tsx @@ -20,6 +20,7 @@ import { toPersian, cn } from "../lib/utils"; import { useCartStore } from "../lib/store/cartStore"; import { usePetStore } from "../lib/store/usePetStore"; import { useUserStore } from "../lib/store/userStore"; +import { useSettingsStore } from "../lib/store/settingsStore"; import { Product, PRODUCTS } from "../lib/data/products"; import { productService } from "../lib/services/productService"; import { toast } from "sonner"; @@ -60,9 +61,10 @@ export default function CheckoutPage() { } }, [profile, isLoggedIn]); + const roundStep = Number(useSettingsStore((state) => state.getText('CHARITY_ROUND_STEP', '10000'))) || 10000; const subtotal = getSubtotal(); - const remainder = subtotal % 10000; - const roundUpDiff = remainder === 0 ? 10000 : 10000 - remainder; + const remainder = subtotal % roundStep; + const roundUpDiff = remainder === 0 ? roundStep : roundStep - remainder; const handleCharityToggle = () => { if (!useRoundUp) { @@ -362,7 +364,7 @@ export default function CheckoutPage() {

رند کردن مبلغ و کمک به پناهگاه

-

مابقی مبلغ تا ۱۰,۰۰۰ تومان بعدی صرف تامین غذا و دارو برای حیوانات بی-سرپرست می‌شود.

+

مابقی مبلغ تا {toPersian(roundStep.toLocaleString())} تومان بعدی صرف تامین غذا و دارو برای حیوانات بی‌سرپرست می‌شود.