From 725a02527ac71011ae01e7ae5e0e0126ee1e1428 Mon Sep 17 00:00:00 2001 From: chattie Date: Sun, 23 Aug 2026 09:41:21 +0200 Subject: [PATCH] fix: selfpayMode state vars + monolith.sh TPV port + closures report - Add missing selfpayMode/closePin state vars in admin POS page - Add selfpayMode/closeSessionRequiresPin/closeSessionPin to PosTerminal interface - Fix ClosedSession type in reporting/closures to match cash-close endpoint - Add smtpReportEmail to admin StoreSettings interface - monolith.sh: add TPV service (port 3002), reorder ports: API 3000, ADMIN 3001, TPV 3002, FRONTEND 3003, STOREFRONT 3004 - Add apps/pos to install_dependencies in monolith.sh --- .../admin/src/app/(dashboard)/pos/page.tsx | 9 ++++++ .../(dashboard)/reporting/closures/page.tsx | 21 +++++++++----- project/apps/admin/src/lib/api-client.ts | 1 + project/scripts/monolith.sh | 28 +++++++++++++------ 4 files changed, 43 insertions(+), 16 deletions(-) diff --git a/project/apps/admin/src/app/(dashboard)/pos/page.tsx b/project/apps/admin/src/app/(dashboard)/pos/page.tsx index b35805e..3a024da 100644 --- a/project/apps/admin/src/app/(dashboard)/pos/page.tsx +++ b/project/apps/admin/src/app/(dashboard)/pos/page.tsx @@ -19,6 +19,9 @@ interface PosTerminal { touchNavigationEnabled?: boolean; quickProductVariantIds?: Array; lineDiscountsEnabled?: boolean; + selfpayMode?: boolean; + closeSessionRequiresPin?: boolean; + closeSessionPin?: string; }; } interface CatalogOption { @@ -94,6 +97,12 @@ export default function PosAdminPage() { ); const [savingTouch, setSavingTouch] = useState(false); const [touchMessage, setTouchMessage] = useState(''); + // F-203: cash close security settings + const [selfpayMode, setSelfpayMode] = useState(false); + const [closePinRequired, setClosePinRequired] = useState(false); + const [closePinValue, setClosePinValue] = useState(''); + const [savingSecurity, setSavingSecurity] = useState(false); + const [securityMessage, setSecurityMessage] = useState(''); const [paymentMethods, setPaymentMethods] = useState([]); const [cashiers, setCashiers] = useState([]); const [newCashier, setNewCashier] = useState({ email: '', password: '' }); diff --git a/project/apps/admin/src/app/(dashboard)/reporting/closures/page.tsx b/project/apps/admin/src/app/(dashboard)/reporting/closures/page.tsx index c47e991..9622d62 100644 --- a/project/apps/admin/src/app/(dashboard)/reporting/closures/page.tsx +++ b/project/apps/admin/src/app/(dashboard)/reporting/closures/page.tsx @@ -3,6 +3,16 @@ import { useCallback, useEffect, useState } from 'react'; import { api } from '@/lib/api-client'; +interface SalesSummary { + totalCount: number; + completedCount: number; + completedTotalCents: number; + pendingCount: number; + refundedCount: number; + refundedTotalCents: number; + byState: Record; +} + interface ClosedSession { id: string; openedAt: string; @@ -13,12 +23,9 @@ interface ClosedSession { closingCashCents: number | null; actualCashCents: number | null; differenceCents: number | null; - salesCount: number; - salesTotalCents: number; - salesByState: Record; + sales: SalesSummary; paymentsByMethod: Array<{ methodCode: string; methodName: string; totalCents: number; count: number }>; - itemsSold: number; - uniqueProductsSold: number; + items: { soldCount: number; uniqueProducts: number }; } function fmt(cents: number): string { @@ -240,11 +247,11 @@ export default function ReportingClosuresPage() { ))}

Artículos vendidos

-

{report.itemsSold}

+

{report.items.soldCount}

Productos únicos

-

{report.uniqueProductsSold}

+

{report.items.uniqueProducts}

diff --git a/project/apps/admin/src/lib/api-client.ts b/project/apps/admin/src/lib/api-client.ts index 4831bc9..9c1f8b3 100644 --- a/project/apps/admin/src/lib/api-client.ts +++ b/project/apps/admin/src/lib/api-client.ts @@ -384,6 +384,7 @@ export interface StoreSettings { smtpPass: string; smtpPassConfigured?: boolean; smtpFrom: string; + smtpReportEmail: string; couriers?: string[]; } diff --git a/project/scripts/monolith.sh b/project/scripts/monolith.sh index 4cac23c..190684b 100755 --- a/project/scripts/monolith.sh +++ b/project/scripts/monolith.sh @@ -11,13 +11,14 @@ ACTION="${2:-}" RUNTIME_ROOT="${MDV_RUNTIME_DIR:-$PROJECT_DIR/.runtime}" RUNTIME_DIR="$RUNTIME_ROOT/$MODE" BACKEND_PORT="${BACKEND_PORT:-3000}" +ADMIN_PORT="${ADMIN_PORT:-3001}" +TPV_PORT="${TPV_PORT:-3002}" FRONTEND_PORT="${FRONTEND_PORT:-3003}" -ADMIN_PORT="${ADMIN_PORT:-3004}" -STOREFRONT_PORT="${STOREFRONT_PORT:-3005}" +STOREFRONT_PORT="${STOREFRONT_PORT:-3004}" START_TIMEOUT="${START_TIMEOUT:-90}" WATCH_INTERVAL="${WATCH_INTERVAL:-5}" -SERVICES=(backend frontend admin storefront) +SERVICES=(backend admin tpv frontend storefront) usage() { cat <<'EOF' @@ -75,10 +76,11 @@ API_PUBLIC_URL="${API_PUBLIC_URL:-http://$LAN_ADDRESS:$BACKEND_PORT}" service_port() { case "$1" in - backend) echo "$BACKEND_PORT" ;; - frontend) echo "$FRONTEND_PORT" ;; - admin) echo "$ADMIN_PORT" ;; - storefront) echo "$STOREFRONT_PORT" ;; + backend) echo "$BACKEND_PORT" ;; + admin) echo "$ADMIN_PORT" ;; + tpv) echo "$TPV_PORT" ;; + frontend) echo "$FRONTEND_PORT" ;; + storefront) echo "$STOREFRONT_PORT" ;; esac } @@ -185,7 +187,7 @@ start_infrastructure() { install_dependencies() { local install_command=(npm install) [[ "$MODE" == "prod" ]] && install_command=(npm ci) - for dir in "$PROJECT_DIR" "$PROJECT_DIR/apps/admin" "$PROJECT_DIR/frontend" "$PROJECT_DIR/storefront"; do + for dir in "$PROJECT_DIR" "$PROJECT_DIR/apps/admin" "$PROJECT_DIR/apps/pos" "$PROJECT_DIR/frontend" "$PROJECT_DIR/storefront"; do echo "[INFO] ${install_command[*]} — ${dir#$PROJECT_DIR/}" (cd "$dir" && "${install_command[@]}") done @@ -257,6 +259,12 @@ spawn_service() { prod:admin) (cd "$PROJECT_DIR/apps/admin" && nohup env NEXT_PUBLIC_API_URL="$API_PUBLIC_URL" node node_modules/next/dist/bin/next start --hostname 0.0.0.0 --port "$port" >"$log" 2>&1 < /dev/null & disown; echo $! >"$pidfile") ;; + dev:tpv) + (cd "$PROJECT_DIR/apps/pos" && nohup env NEXT_PUBLIC_API_URL="$API_PUBLIC_URL" node node_modules/next/dist/bin/next dev --hostname 0.0.0.0 --port "$port" >"$log" 2>&1 < /dev/null & disown; echo $! >"$pidfile") + ;; + prod:tpv) + (cd "$PROJECT_DIR/apps/pos" && nohup env NEXT_PUBLIC_API_URL="$API_PUBLIC_URL" node node_modules/next/dist/bin/next start --hostname 0.0.0.0 --port "$port" >"$log" 2>&1 < /dev/null & disown; echo $! >"$pidfile") + ;; dev:frontend) (cd "$PROJECT_DIR/frontend" && nohup env NEXT_PUBLIC_API_URL="$API_PUBLIC_URL" node node_modules/next/dist/bin/next dev --hostname 0.0.0.0 --port "$port" >"$log" 2>&1 < /dev/null & disown; echo $! >"$pidfile") ;; @@ -384,8 +392,10 @@ print_urls() { Mode: $MODE LAN IP: $LAN_ADDRESS -Customer frontend: http://$LAN_ADDRESS:$FRONTEND_PORT/ +Backend (API): http://$LAN_ADDRESS:$BACKEND_PORT/health Admin backoffice: http://$LAN_ADDRESS:$ADMIN_PORT/ +POS TPV: http://$LAN_ADDRESS:$TPV_PORT/ +Customer frontend: http://$LAN_ADDRESS:$FRONTEND_PORT/ SEO storefront: http://$LAN_ADDRESS:$STOREFRONT_PORT/ Backend health: http://$LAN_ADDRESS:$BACKEND_PORT/health Swagger/OpenAPI: http://$LAN_ADDRESS:$BACKEND_PORT/docs