From 30a7a6becde12e843f42120512249841229ef678 Mon Sep 17 00:00:00 2001 From: rckrdmrd Date: Fri, 16 Jan 2026 08:30:07 -0600 Subject: [PATCH] [MULTI-REPO] Convertir a estructura multi-repo con submodules -v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - backend → miinventario-backend-v2.git - database → miinventario-database-v2.git - mobile → miinventario-mobile-v2.git Estandarización arquitectura multi-repo Co-Authored-By: Claude Opus 4.5 --- .gitmodules | 11 + apps/backend/.dockerignore | 50 -- apps/backend/.env.example | 50 -- apps/backend/.env.test | 16 - apps/backend/.eslintrc.js | 30 - apps/backend/.prettierrc | 10 - apps/backend/Dockerfile | 56 -- apps/backend/nest-cli.json | 8 - apps/backend/package.json | 107 ---- apps/backend/src/app.module.ts | 71 --- .../src/common/decorators/roles.decorator.ts | 5 - apps/backend/src/common/guards/roles.guard.ts | 44 -- .../authenticated-request.interface.ts | 12 - apps/backend/src/config/database.config.ts | 18 - apps/backend/src/config/redis.config.ts | 21 - apps/backend/src/config/typeorm.config.ts | 20 - apps/backend/src/database/seed.ts | 75 --- apps/backend/src/main.ts | 75 --- .../1736502000000-CreateFeedbackTables.ts | 201 ------ .../1736600000000-CreateAdminTables.ts | 136 ---- .../src/migrations/1768099560565-Init.ts | 122 ---- .../1768200000000-CreateExportsTables.ts | 91 --- .../1768200001000-CreateInventoryMovements.ts | 156 ----- .../1768200002000-CreatePosIntegrations.ts | 261 -------- .../src/modules/admin/admin.controller.ts | 248 ------- .../backend/src/modules/admin/admin.module.ts | 53 -- .../src/modules/admin/dto/dashboard.dto.ts | 66 -- .../src/modules/admin/dto/moderation.dto.ts | 39 -- .../src/modules/admin/dto/package.dto.ts | 80 --- .../src/modules/admin/dto/promotion.dto.ts | 137 ---- .../src/modules/admin/dto/provider.dto.ts | 42 -- .../admin/entities/audit-log.entity.ts | 51 -- .../admin/entities/ia-provider.entity.ts | 46 -- .../admin/entities/promotion.entity.ts | 90 --- .../admin/services/admin-dashboard.service.ts | 206 ------ .../services/admin-moderation.service.ts | 264 -------- .../admin/services/admin-packages.service.ts | 101 --- .../services/admin-promotions.service.ts | 151 ----- .../admin/services/admin-providers.service.ts | 82 --- .../admin/services/audit-log.service.ts | 57 -- .../src/modules/auth/auth.controller.ts | 52 -- apps/backend/src/modules/auth/auth.module.ts | 34 - apps/backend/src/modules/auth/auth.service.ts | 259 -------- .../backend/src/modules/auth/dto/login.dto.ts | 22 - .../src/modules/auth/dto/refresh-token.dto.ts | 11 - .../src/modules/auth/dto/register.dto.ts | 23 - .../src/modules/auth/dto/verify-otp.dto.ts | 49 -- .../src/modules/auth/entities/otp.entity.ts | 42 -- .../auth/entities/refresh-token.entity.ts | 44 -- .../src/modules/auth/guards/jwt-auth.guard.ts | 9 - .../modules/auth/strategies/jwt.strategy.ts | 27 - .../src/modules/credits/credits.controller.ts | 72 --- .../src/modules/credits/credits.module.ts | 17 - .../src/modules/credits/credits.service.ts | 211 ------ .../credits/entities/credit-balance.entity.ts | 41 -- .../credits/entities/credit-package.entity.ts | 43 -- .../entities/credit-transaction.entity.ts | 57 -- .../modules/exports/dto/export-request.dto.ts | 77 --- .../modules/exports/dto/export-status.dto.ts | 47 -- .../exports/entities/export-job.entity.ts | 103 --- .../src/modules/exports/exports.controller.ts | 127 ---- .../src/modules/exports/exports.module.ts | 23 - .../src/modules/exports/exports.processor.ts | 30 - .../src/modules/exports/exports.service.ts | 413 ------------ .../feedback/dto/correct-quantity.dto.ts | 12 - .../modules/feedback/dto/correct-sku.dto.ts | 23 - .../feedback/dto/submit-product.dto.ts | 46 -- .../feedback/entities/correction.entity.ts | 67 -- .../feedback/entities/ground-truth.entity.ts | 86 --- .../entities/product-submission.entity.ts | 91 --- .../modules/feedback/feedback.controller.ts | 170 ----- .../src/modules/feedback/feedback.module.ts | 25 - .../src/modules/feedback/feedback.service.ts | 239 ------- .../src/modules/health/health.controller.ts | 27 - .../src/modules/health/health.module.ts | 7 - .../modules/ia-provider/ia-provider.module.ts | 8 - .../ia-provider/ia-provider.service.ts | 548 ---------------- .../entities/pos-integration.entity.ts | 95 --- .../entities/pos-sync-log.entity.ts | 77 --- .../integrations/integrations.module.ts | 22 - .../pos/adapters/base-pos.adapter.ts | 85 --- .../pos/interfaces/pos-adapter.interface.ts | 87 --- .../pos/interfaces/pos-webhook.interface.ts | 90 --- .../integrations/pos/pos.controller.ts | 310 --------- .../pos/services/inventory-sync.service.ts | 348 ---------- .../pos/services/pos-webhook.service.ts | 263 -------- .../dto/update-inventory-item.dto.ts | 82 --- .../entities/inventory-item.entity.ts | 80 --- .../modules/inventory/inventory.controller.ts | 135 ---- .../src/modules/inventory/inventory.module.ts | 19 - .../modules/inventory/inventory.service.ts | 230 ------- .../entities/notification.entity.ts | 57 -- .../notifications/notifications.controller.ts | 100 --- .../notifications/notifications.module.ts | 17 - .../notifications/notifications.service.ts | 228 ------- .../payments/dto/create-payment.dto.ts | 29 - .../payments/entities/payment.entity.ts | 92 --- .../modules/payments/payments.controller.ts | 103 --- .../src/modules/payments/payments.module.ts | 21 - .../src/modules/payments/payments.service.ts | 416 ------------ .../referrals/entities/referral.entity.ts | 85 --- .../modules/referrals/referrals.controller.ts | 96 --- .../src/modules/referrals/referrals.module.ts | 21 - .../modules/referrals/referrals.service.ts | 286 --------- .../src/modules/reports/dto/reports.dto.ts | 175 ----- .../entities/inventory-movement.entity.ts | 92 --- .../src/modules/reports/reports.controller.ts | 117 ---- .../src/modules/reports/reports.module.ts | 18 - .../services/inventory-reports.service.ts | 377 ----------- .../modules/stores/dto/create-store.dto.ts | 86 --- .../modules/stores/dto/update-store.dto.ts | 4 - .../stores/entities/store-user.entity.ts | 44 -- .../modules/stores/entities/store.entity.ts | 50 -- .../src/modules/stores/stores.controller.ts | 82 --- .../src/modules/stores/stores.module.ts | 14 - .../src/modules/stores/stores.service.ts | 82 --- .../src/modules/users/dto/create-user.dto.ts | 31 - .../src/modules/users/dto/update-user.dto.ts | 29 - .../src/modules/users/entities/user.entity.ts | 60 -- .../src/modules/users/users.controller.ts | 40 -- .../backend/src/modules/users/users.module.ts | 13 - .../src/modules/users/users.service.ts | 54 -- .../validations/dto/submit-validation.dto.ts | 42 -- .../entities/validation-request.entity.ts | 90 --- .../entities/validation-response.entity.ts | 59 -- .../validations/validation-engine.service.ts | 138 ---- .../validations/validations.controller.ts | 101 --- .../modules/validations/validations.module.ts | 30 - .../validations/validations.service.ts | 245 ------- apps/backend/test/admin.e2e-spec.ts | 432 ------------- apps/backend/test/auth.e2e-spec.ts | 324 ---------- apps/backend/test/credits.e2e-spec.ts | 223 ------- apps/backend/test/feedback.e2e-spec.ts | 202 ------ apps/backend/test/health.e2e-spec.ts | 49 -- apps/backend/test/inventory.e2e-spec.ts | 348 ---------- apps/backend/test/jest-e2e.json | 25 - apps/backend/test/setup.ts | 13 - apps/backend/test/stores.e2e-spec.ts | 323 ---------- apps/backend/test/users.e2e-spec.ts | 186 ------ apps/backend/test/utils/index.ts | 2 - apps/backend/test/utils/test-app.ts | 81 --- apps/backend/test/utils/test-fixtures.ts | 155 ----- apps/backend/test/validations.e2e-spec.ts | 271 -------- apps/backend/tsconfig.json | 27 - apps/mobile/.env.example | 5 - apps/mobile/.eslintrc.js | 47 -- apps/mobile/.prettierrc | 11 - apps/mobile/app.json | 55 -- apps/mobile/babel.config.js | 25 - apps/mobile/jest.config.js | 37 -- apps/mobile/jest.setup.js | 71 --- apps/mobile/package.json | 63 -- apps/mobile/src/__mocks__/apiClient.mock.ts | 49 -- apps/mobile/src/app/(auth)/_layout.tsx | 16 - apps/mobile/src/app/(auth)/login.tsx | 134 ---- apps/mobile/src/app/(auth)/register.tsx | 136 ---- apps/mobile/src/app/(auth)/verify-otp.tsx | 129 ---- apps/mobile/src/app/(tabs)/_layout.tsx | 48 -- apps/mobile/src/app/(tabs)/index.tsx | 542 ---------------- apps/mobile/src/app/(tabs)/inventory.tsx | 554 ---------------- apps/mobile/src/app/(tabs)/profile.tsx | 531 --------------- apps/mobile/src/app/(tabs)/scan.tsx | 467 -------------- apps/mobile/src/app/_layout.tsx | 50 -- apps/mobile/src/app/credits/_layout.tsx | 23 - apps/mobile/src/app/credits/buy.tsx | 434 ------------- apps/mobile/src/app/credits/history.tsx | 221 ------- apps/mobile/src/app/help/index.tsx | 292 --------- apps/mobile/src/app/index.tsx | 12 - apps/mobile/src/app/inventory/[id].tsx | 603 ------------------ apps/mobile/src/app/inventory/_layout.tsx | 23 - apps/mobile/src/app/inventory/export.tsx | 492 -------------- apps/mobile/src/app/legal/privacy.tsx | 197 ------ apps/mobile/src/app/legal/terms.tsx | 164 ----- apps/mobile/src/app/notifications/_layout.tsx | 19 - apps/mobile/src/app/notifications/index.tsx | 312 --------- apps/mobile/src/app/payments/methods.tsx | 288 --------- apps/mobile/src/app/profile/edit.tsx | 316 --------- apps/mobile/src/app/referrals/_layout.tsx | 19 - apps/mobile/src/app/referrals/index.tsx | 460 ------------- apps/mobile/src/app/reports/_layout.tsx | 31 - apps/mobile/src/app/reports/categories.tsx | 479 -------------- apps/mobile/src/app/reports/index.tsx | 150 ----- apps/mobile/src/app/reports/movements.tsx | 371 ----------- apps/mobile/src/app/reports/valuation.tsx | 381 ----------- apps/mobile/src/app/stores/[id].tsx | 264 -------- apps/mobile/src/app/stores/_layout.tsx | 27 - apps/mobile/src/app/stores/index.tsx | 301 --------- apps/mobile/src/app/stores/new.tsx | 221 ------- apps/mobile/src/app/support/index.tsx | 317 --------- apps/mobile/src/app/validation/_layout.tsx | 27 - apps/mobile/src/app/validation/complete.tsx | 165 ----- apps/mobile/src/app/validation/items.tsx | 301 --------- .../components/feedback/ConfirmItemButton.tsx | 57 -- .../feedback/CorrectQuantityModal.tsx | 203 ------ .../components/feedback/CorrectSkuModal.tsx | 220 ------- .../feedback/CorrectionHistoryCard.tsx | 147 ----- .../skeletons/CreditCardSkeleton.tsx | 137 ---- .../skeletons/InventoryItemSkeleton.tsx | 86 --- .../skeletons/NotificationSkeleton.tsx | 75 --- .../skeletons/StoreCardSkeleton.tsx | 80 --- .../mobile/src/components/ui/AnimatedList.tsx | 154 ----- .../src/components/ui/OfflineBanner.tsx | 114 ---- apps/mobile/src/components/ui/Skeleton.tsx | 215 ------- .../validation/ValidationItemCard.tsx | 317 --------- .../validation/ValidationProgressBar.tsx | 63 -- .../validation/ValidationPromptModal.tsx | 184 ------ apps/mobile/src/hooks/useAnimations.ts | 186 ------ apps/mobile/src/hooks/useNetworkStatus.ts | 73 --- .../api/__tests__/auth.service.spec.ts | 112 ---- .../api/__tests__/inventory.service.spec.ts | 119 ---- .../api/__tests__/reports.service.spec.ts | 175 ----- apps/mobile/src/services/api/auth.service.ts | 62 -- apps/mobile/src/services/api/client.ts | 58 -- .../src/services/api/credits.service.ts | 61 -- .../src/services/api/exports.service.ts | 143 ----- .../src/services/api/feedback.service.ts | 115 ---- .../src/services/api/inventory.service.ts | 61 -- .../src/services/api/notifications.service.ts | 66 -- .../src/services/api/payments.service.ts | 76 --- .../src/services/api/referrals.service.ts | 75 --- .../src/services/api/reports.service.ts | 171 ----- .../mobile/src/services/api/stores.service.ts | 70 -- apps/mobile/src/services/api/users.service.ts | 35 - .../src/services/api/validations.service.ts | 70 -- .../mobile/src/services/api/videos.service.ts | 87 --- .../src/stores/__tests__/auth.store.spec.ts | 198 ------ .../stores/__tests__/credits.store.spec.ts | 98 --- .../stores/__tests__/feedback.store.spec.ts | 162 ----- .../stores/__tests__/inventory.store.spec.ts | 200 ------ .../__tests__/notifications.store.spec.ts | 100 --- .../stores/__tests__/payments.store.spec.ts | 152 ----- .../stores/__tests__/referrals.store.spec.ts | 95 --- .../src/stores/__tests__/stores.store.spec.ts | 149 ----- .../__tests__/validations.store.spec.ts | 146 ----- apps/mobile/src/stores/auth.store.ts | 137 ---- apps/mobile/src/stores/credits.store.ts | 138 ---- apps/mobile/src/stores/feedback.store.ts | 129 ---- apps/mobile/src/stores/inventory.store.ts | 141 ---- apps/mobile/src/stores/notifications.store.ts | 129 ---- apps/mobile/src/stores/payments.store.ts | 105 --- apps/mobile/src/stores/referrals.store.ts | 101 --- apps/mobile/src/stores/stores.store.ts | 164 ----- apps/mobile/src/stores/validations.store.ts | 158 ----- apps/mobile/src/theme/ThemeContext.tsx | 76 --- apps/mobile/src/types/index.ts | 234 ------- apps/mobile/src/utils/formatters.ts | 58 -- apps/mobile/src/utils/validators.ts | 42 -- apps/mobile/tsconfig.json | 22 - backend | 1 + database | 1 + mobile | 1 + 251 files changed, 14 insertions(+), 31419 deletions(-) create mode 100644 .gitmodules delete mode 100644 apps/backend/.dockerignore delete mode 100644 apps/backend/.env.example delete mode 100644 apps/backend/.env.test delete mode 100644 apps/backend/.eslintrc.js delete mode 100644 apps/backend/.prettierrc delete mode 100644 apps/backend/Dockerfile delete mode 100644 apps/backend/nest-cli.json delete mode 100644 apps/backend/package.json delete mode 100644 apps/backend/src/app.module.ts delete mode 100644 apps/backend/src/common/decorators/roles.decorator.ts delete mode 100644 apps/backend/src/common/guards/roles.guard.ts delete mode 100644 apps/backend/src/common/interfaces/authenticated-request.interface.ts delete mode 100644 apps/backend/src/config/database.config.ts delete mode 100644 apps/backend/src/config/redis.config.ts delete mode 100644 apps/backend/src/config/typeorm.config.ts delete mode 100644 apps/backend/src/database/seed.ts delete mode 100644 apps/backend/src/main.ts delete mode 100644 apps/backend/src/migrations/1736502000000-CreateFeedbackTables.ts delete mode 100644 apps/backend/src/migrations/1736600000000-CreateAdminTables.ts delete mode 100644 apps/backend/src/migrations/1768099560565-Init.ts delete mode 100644 apps/backend/src/migrations/1768200000000-CreateExportsTables.ts delete mode 100644 apps/backend/src/migrations/1768200001000-CreateInventoryMovements.ts delete mode 100644 apps/backend/src/migrations/1768200002000-CreatePosIntegrations.ts delete mode 100644 apps/backend/src/modules/admin/admin.controller.ts delete mode 100644 apps/backend/src/modules/admin/admin.module.ts delete mode 100644 apps/backend/src/modules/admin/dto/dashboard.dto.ts delete mode 100644 apps/backend/src/modules/admin/dto/moderation.dto.ts delete mode 100644 apps/backend/src/modules/admin/dto/package.dto.ts delete mode 100644 apps/backend/src/modules/admin/dto/promotion.dto.ts delete mode 100644 apps/backend/src/modules/admin/dto/provider.dto.ts delete mode 100644 apps/backend/src/modules/admin/entities/audit-log.entity.ts delete mode 100644 apps/backend/src/modules/admin/entities/ia-provider.entity.ts delete mode 100644 apps/backend/src/modules/admin/entities/promotion.entity.ts delete mode 100644 apps/backend/src/modules/admin/services/admin-dashboard.service.ts delete mode 100644 apps/backend/src/modules/admin/services/admin-moderation.service.ts delete mode 100644 apps/backend/src/modules/admin/services/admin-packages.service.ts delete mode 100644 apps/backend/src/modules/admin/services/admin-promotions.service.ts delete mode 100644 apps/backend/src/modules/admin/services/admin-providers.service.ts delete mode 100644 apps/backend/src/modules/admin/services/audit-log.service.ts delete mode 100644 apps/backend/src/modules/auth/auth.controller.ts delete mode 100644 apps/backend/src/modules/auth/auth.module.ts delete mode 100644 apps/backend/src/modules/auth/auth.service.ts delete mode 100644 apps/backend/src/modules/auth/dto/login.dto.ts delete mode 100644 apps/backend/src/modules/auth/dto/refresh-token.dto.ts delete mode 100644 apps/backend/src/modules/auth/dto/register.dto.ts delete mode 100644 apps/backend/src/modules/auth/dto/verify-otp.dto.ts delete mode 100644 apps/backend/src/modules/auth/entities/otp.entity.ts delete mode 100644 apps/backend/src/modules/auth/entities/refresh-token.entity.ts delete mode 100644 apps/backend/src/modules/auth/guards/jwt-auth.guard.ts delete mode 100644 apps/backend/src/modules/auth/strategies/jwt.strategy.ts delete mode 100644 apps/backend/src/modules/credits/credits.controller.ts delete mode 100644 apps/backend/src/modules/credits/credits.module.ts delete mode 100644 apps/backend/src/modules/credits/credits.service.ts delete mode 100644 apps/backend/src/modules/credits/entities/credit-balance.entity.ts delete mode 100644 apps/backend/src/modules/credits/entities/credit-package.entity.ts delete mode 100644 apps/backend/src/modules/credits/entities/credit-transaction.entity.ts delete mode 100644 apps/backend/src/modules/exports/dto/export-request.dto.ts delete mode 100644 apps/backend/src/modules/exports/dto/export-status.dto.ts delete mode 100644 apps/backend/src/modules/exports/entities/export-job.entity.ts delete mode 100644 apps/backend/src/modules/exports/exports.controller.ts delete mode 100644 apps/backend/src/modules/exports/exports.module.ts delete mode 100644 apps/backend/src/modules/exports/exports.processor.ts delete mode 100644 apps/backend/src/modules/exports/exports.service.ts delete mode 100644 apps/backend/src/modules/feedback/dto/correct-quantity.dto.ts delete mode 100644 apps/backend/src/modules/feedback/dto/correct-sku.dto.ts delete mode 100644 apps/backend/src/modules/feedback/dto/submit-product.dto.ts delete mode 100644 apps/backend/src/modules/feedback/entities/correction.entity.ts delete mode 100644 apps/backend/src/modules/feedback/entities/ground-truth.entity.ts delete mode 100644 apps/backend/src/modules/feedback/entities/product-submission.entity.ts delete mode 100644 apps/backend/src/modules/feedback/feedback.controller.ts delete mode 100644 apps/backend/src/modules/feedback/feedback.module.ts delete mode 100644 apps/backend/src/modules/feedback/feedback.service.ts delete mode 100644 apps/backend/src/modules/health/health.controller.ts delete mode 100644 apps/backend/src/modules/health/health.module.ts delete mode 100644 apps/backend/src/modules/ia-provider/ia-provider.module.ts delete mode 100644 apps/backend/src/modules/ia-provider/ia-provider.service.ts delete mode 100644 apps/backend/src/modules/integrations/entities/pos-integration.entity.ts delete mode 100644 apps/backend/src/modules/integrations/entities/pos-sync-log.entity.ts delete mode 100644 apps/backend/src/modules/integrations/integrations.module.ts delete mode 100644 apps/backend/src/modules/integrations/pos/adapters/base-pos.adapter.ts delete mode 100644 apps/backend/src/modules/integrations/pos/interfaces/pos-adapter.interface.ts delete mode 100644 apps/backend/src/modules/integrations/pos/interfaces/pos-webhook.interface.ts delete mode 100644 apps/backend/src/modules/integrations/pos/pos.controller.ts delete mode 100644 apps/backend/src/modules/integrations/pos/services/inventory-sync.service.ts delete mode 100644 apps/backend/src/modules/integrations/pos/services/pos-webhook.service.ts delete mode 100644 apps/backend/src/modules/inventory/dto/update-inventory-item.dto.ts delete mode 100644 apps/backend/src/modules/inventory/entities/inventory-item.entity.ts delete mode 100644 apps/backend/src/modules/inventory/inventory.controller.ts delete mode 100644 apps/backend/src/modules/inventory/inventory.module.ts delete mode 100644 apps/backend/src/modules/inventory/inventory.service.ts delete mode 100644 apps/backend/src/modules/notifications/entities/notification.entity.ts delete mode 100644 apps/backend/src/modules/notifications/notifications.controller.ts delete mode 100644 apps/backend/src/modules/notifications/notifications.module.ts delete mode 100644 apps/backend/src/modules/notifications/notifications.service.ts delete mode 100644 apps/backend/src/modules/payments/dto/create-payment.dto.ts delete mode 100644 apps/backend/src/modules/payments/entities/payment.entity.ts delete mode 100644 apps/backend/src/modules/payments/payments.controller.ts delete mode 100644 apps/backend/src/modules/payments/payments.module.ts delete mode 100644 apps/backend/src/modules/payments/payments.service.ts delete mode 100644 apps/backend/src/modules/referrals/entities/referral.entity.ts delete mode 100644 apps/backend/src/modules/referrals/referrals.controller.ts delete mode 100644 apps/backend/src/modules/referrals/referrals.module.ts delete mode 100644 apps/backend/src/modules/referrals/referrals.service.ts delete mode 100644 apps/backend/src/modules/reports/dto/reports.dto.ts delete mode 100644 apps/backend/src/modules/reports/entities/inventory-movement.entity.ts delete mode 100644 apps/backend/src/modules/reports/reports.controller.ts delete mode 100644 apps/backend/src/modules/reports/reports.module.ts delete mode 100644 apps/backend/src/modules/reports/services/inventory-reports.service.ts delete mode 100644 apps/backend/src/modules/stores/dto/create-store.dto.ts delete mode 100644 apps/backend/src/modules/stores/dto/update-store.dto.ts delete mode 100644 apps/backend/src/modules/stores/entities/store-user.entity.ts delete mode 100644 apps/backend/src/modules/stores/entities/store.entity.ts delete mode 100644 apps/backend/src/modules/stores/stores.controller.ts delete mode 100644 apps/backend/src/modules/stores/stores.module.ts delete mode 100644 apps/backend/src/modules/stores/stores.service.ts delete mode 100644 apps/backend/src/modules/users/dto/create-user.dto.ts delete mode 100644 apps/backend/src/modules/users/dto/update-user.dto.ts delete mode 100644 apps/backend/src/modules/users/entities/user.entity.ts delete mode 100644 apps/backend/src/modules/users/users.controller.ts delete mode 100644 apps/backend/src/modules/users/users.module.ts delete mode 100644 apps/backend/src/modules/users/users.service.ts delete mode 100644 apps/backend/src/modules/validations/dto/submit-validation.dto.ts delete mode 100644 apps/backend/src/modules/validations/entities/validation-request.entity.ts delete mode 100644 apps/backend/src/modules/validations/entities/validation-response.entity.ts delete mode 100644 apps/backend/src/modules/validations/validation-engine.service.ts delete mode 100644 apps/backend/src/modules/validations/validations.controller.ts delete mode 100644 apps/backend/src/modules/validations/validations.module.ts delete mode 100644 apps/backend/src/modules/validations/validations.service.ts delete mode 100644 apps/backend/test/admin.e2e-spec.ts delete mode 100644 apps/backend/test/auth.e2e-spec.ts delete mode 100644 apps/backend/test/credits.e2e-spec.ts delete mode 100644 apps/backend/test/feedback.e2e-spec.ts delete mode 100644 apps/backend/test/health.e2e-spec.ts delete mode 100644 apps/backend/test/inventory.e2e-spec.ts delete mode 100644 apps/backend/test/jest-e2e.json delete mode 100644 apps/backend/test/setup.ts delete mode 100644 apps/backend/test/stores.e2e-spec.ts delete mode 100644 apps/backend/test/users.e2e-spec.ts delete mode 100644 apps/backend/test/utils/index.ts delete mode 100644 apps/backend/test/utils/test-app.ts delete mode 100644 apps/backend/test/utils/test-fixtures.ts delete mode 100644 apps/backend/test/validations.e2e-spec.ts delete mode 100644 apps/backend/tsconfig.json delete mode 100644 apps/mobile/.env.example delete mode 100644 apps/mobile/.eslintrc.js delete mode 100644 apps/mobile/.prettierrc delete mode 100644 apps/mobile/app.json delete mode 100644 apps/mobile/babel.config.js delete mode 100644 apps/mobile/jest.config.js delete mode 100644 apps/mobile/jest.setup.js delete mode 100644 apps/mobile/package.json delete mode 100644 apps/mobile/src/__mocks__/apiClient.mock.ts delete mode 100644 apps/mobile/src/app/(auth)/_layout.tsx delete mode 100644 apps/mobile/src/app/(auth)/login.tsx delete mode 100644 apps/mobile/src/app/(auth)/register.tsx delete mode 100644 apps/mobile/src/app/(auth)/verify-otp.tsx delete mode 100644 apps/mobile/src/app/(tabs)/_layout.tsx delete mode 100644 apps/mobile/src/app/(tabs)/index.tsx delete mode 100644 apps/mobile/src/app/(tabs)/inventory.tsx delete mode 100644 apps/mobile/src/app/(tabs)/profile.tsx delete mode 100644 apps/mobile/src/app/(tabs)/scan.tsx delete mode 100644 apps/mobile/src/app/_layout.tsx delete mode 100644 apps/mobile/src/app/credits/_layout.tsx delete mode 100644 apps/mobile/src/app/credits/buy.tsx delete mode 100644 apps/mobile/src/app/credits/history.tsx delete mode 100644 apps/mobile/src/app/help/index.tsx delete mode 100644 apps/mobile/src/app/index.tsx delete mode 100644 apps/mobile/src/app/inventory/[id].tsx delete mode 100644 apps/mobile/src/app/inventory/_layout.tsx delete mode 100644 apps/mobile/src/app/inventory/export.tsx delete mode 100644 apps/mobile/src/app/legal/privacy.tsx delete mode 100644 apps/mobile/src/app/legal/terms.tsx delete mode 100644 apps/mobile/src/app/notifications/_layout.tsx delete mode 100644 apps/mobile/src/app/notifications/index.tsx delete mode 100644 apps/mobile/src/app/payments/methods.tsx delete mode 100644 apps/mobile/src/app/profile/edit.tsx delete mode 100644 apps/mobile/src/app/referrals/_layout.tsx delete mode 100644 apps/mobile/src/app/referrals/index.tsx delete mode 100644 apps/mobile/src/app/reports/_layout.tsx delete mode 100644 apps/mobile/src/app/reports/categories.tsx delete mode 100644 apps/mobile/src/app/reports/index.tsx delete mode 100644 apps/mobile/src/app/reports/movements.tsx delete mode 100644 apps/mobile/src/app/reports/valuation.tsx delete mode 100644 apps/mobile/src/app/stores/[id].tsx delete mode 100644 apps/mobile/src/app/stores/_layout.tsx delete mode 100644 apps/mobile/src/app/stores/index.tsx delete mode 100644 apps/mobile/src/app/stores/new.tsx delete mode 100644 apps/mobile/src/app/support/index.tsx delete mode 100644 apps/mobile/src/app/validation/_layout.tsx delete mode 100644 apps/mobile/src/app/validation/complete.tsx delete mode 100644 apps/mobile/src/app/validation/items.tsx delete mode 100644 apps/mobile/src/components/feedback/ConfirmItemButton.tsx delete mode 100644 apps/mobile/src/components/feedback/CorrectQuantityModal.tsx delete mode 100644 apps/mobile/src/components/feedback/CorrectSkuModal.tsx delete mode 100644 apps/mobile/src/components/feedback/CorrectionHistoryCard.tsx delete mode 100644 apps/mobile/src/components/skeletons/CreditCardSkeleton.tsx delete mode 100644 apps/mobile/src/components/skeletons/InventoryItemSkeleton.tsx delete mode 100644 apps/mobile/src/components/skeletons/NotificationSkeleton.tsx delete mode 100644 apps/mobile/src/components/skeletons/StoreCardSkeleton.tsx delete mode 100644 apps/mobile/src/components/ui/AnimatedList.tsx delete mode 100644 apps/mobile/src/components/ui/OfflineBanner.tsx delete mode 100644 apps/mobile/src/components/ui/Skeleton.tsx delete mode 100644 apps/mobile/src/components/validation/ValidationItemCard.tsx delete mode 100644 apps/mobile/src/components/validation/ValidationProgressBar.tsx delete mode 100644 apps/mobile/src/components/validation/ValidationPromptModal.tsx delete mode 100644 apps/mobile/src/hooks/useAnimations.ts delete mode 100644 apps/mobile/src/hooks/useNetworkStatus.ts delete mode 100644 apps/mobile/src/services/api/__tests__/auth.service.spec.ts delete mode 100644 apps/mobile/src/services/api/__tests__/inventory.service.spec.ts delete mode 100644 apps/mobile/src/services/api/__tests__/reports.service.spec.ts delete mode 100644 apps/mobile/src/services/api/auth.service.ts delete mode 100644 apps/mobile/src/services/api/client.ts delete mode 100644 apps/mobile/src/services/api/credits.service.ts delete mode 100644 apps/mobile/src/services/api/exports.service.ts delete mode 100644 apps/mobile/src/services/api/feedback.service.ts delete mode 100644 apps/mobile/src/services/api/inventory.service.ts delete mode 100644 apps/mobile/src/services/api/notifications.service.ts delete mode 100644 apps/mobile/src/services/api/payments.service.ts delete mode 100644 apps/mobile/src/services/api/referrals.service.ts delete mode 100644 apps/mobile/src/services/api/reports.service.ts delete mode 100644 apps/mobile/src/services/api/stores.service.ts delete mode 100644 apps/mobile/src/services/api/users.service.ts delete mode 100644 apps/mobile/src/services/api/validations.service.ts delete mode 100644 apps/mobile/src/services/api/videos.service.ts delete mode 100644 apps/mobile/src/stores/__tests__/auth.store.spec.ts delete mode 100644 apps/mobile/src/stores/__tests__/credits.store.spec.ts delete mode 100644 apps/mobile/src/stores/__tests__/feedback.store.spec.ts delete mode 100644 apps/mobile/src/stores/__tests__/inventory.store.spec.ts delete mode 100644 apps/mobile/src/stores/__tests__/notifications.store.spec.ts delete mode 100644 apps/mobile/src/stores/__tests__/payments.store.spec.ts delete mode 100644 apps/mobile/src/stores/__tests__/referrals.store.spec.ts delete mode 100644 apps/mobile/src/stores/__tests__/stores.store.spec.ts delete mode 100644 apps/mobile/src/stores/__tests__/validations.store.spec.ts delete mode 100644 apps/mobile/src/stores/auth.store.ts delete mode 100644 apps/mobile/src/stores/credits.store.ts delete mode 100644 apps/mobile/src/stores/feedback.store.ts delete mode 100644 apps/mobile/src/stores/inventory.store.ts delete mode 100644 apps/mobile/src/stores/notifications.store.ts delete mode 100644 apps/mobile/src/stores/payments.store.ts delete mode 100644 apps/mobile/src/stores/referrals.store.ts delete mode 100644 apps/mobile/src/stores/stores.store.ts delete mode 100644 apps/mobile/src/stores/validations.store.ts delete mode 100644 apps/mobile/src/theme/ThemeContext.tsx delete mode 100644 apps/mobile/src/types/index.ts delete mode 100644 apps/mobile/src/utils/formatters.ts delete mode 100644 apps/mobile/src/utils/validators.ts delete mode 100644 apps/mobile/tsconfig.json create mode 160000 backend create mode 160000 database create mode 160000 mobile diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..3806f74 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,11 @@ +[submodule "backend"] + path = backend + url = git@gitea-server:rckrdmrd/miinventario-backend-v2.git + +[submodule "database"] + path = database + url = git@gitea-server:rckrdmrd/miinventario-database-v2.git + +[submodule "mobile"] + path = mobile + url = git@gitea-server:rckrdmrd/miinventario-mobile-v2.git diff --git a/apps/backend/.dockerignore b/apps/backend/.dockerignore deleted file mode 100644 index 157d621..0000000 --- a/apps/backend/.dockerignore +++ /dev/null @@ -1,50 +0,0 @@ -# Dependencies -node_modules -npm-debug.log -yarn-debug.log -yarn-error.log - -# Build output (will be recreated in Docker) -dist - -# Test files -*.spec.ts -*.test.ts -__tests__ -coverage -.nyc_output -junit.xml - -# Development files -.env -.env.local -.env.development -.env.test - -# IDE -.idea -.vscode -*.swp -*.swo - -# OS -.DS_Store -Thumbs.db - -# Git -.git -.gitignore - -# Docker -Dockerfile -docker-compose*.yml -.dockerignore - -# Documentation -*.md -docs/ - -# Misc -*.log -.eslintcache -.prettierignore diff --git a/apps/backend/.env.example b/apps/backend/.env.example deleted file mode 100644 index 9229691..0000000 --- a/apps/backend/.env.example +++ /dev/null @@ -1,50 +0,0 @@ -# Server -NODE_ENV=development -BACKEND_PORT=3142 - -# Database -DATABASE_HOST=localhost -DATABASE_PORT=5433 -DATABASE_USER=miinventario -DATABASE_PASSWORD=miinventario_dev -DATABASE_NAME=miinventario - -# Redis -REDIS_HOST=localhost -REDIS_PORT=6380 - -# JWT -JWT_SECRET=your-jwt-secret-change-in-production -JWT_REFRESH_SECRET=your-refresh-secret-change-in-production -JWT_EXPIRES_IN=15m -JWT_REFRESH_EXPIRES_IN=7d - -# Storage (MinIO/S3) -S3_ENDPOINT=http://localhost:9002 -S3_ACCESS_KEY=miinventario -S3_SECRET_KEY=miinventario_dev -S3_BUCKET_VIDEOS=miinventario-videos -S3_REGION=us-east-1 - -# Stripe -STRIPE_SECRET_KEY=sk_test_your_stripe_key -STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret - -# Conekta (7-Eleven) -CONEKTA_API_KEY=key_your_conekta_key - -# Firebase (FCM) -FIREBASE_PROJECT_ID=miinventario -FIREBASE_CLIENT_EMAIL=firebase-adminsdk@miinventario.iam.gserviceaccount.com -FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nYOUR_KEY_HERE\n-----END PRIVATE KEY-----" - -# OpenAI -OPENAI_API_KEY=sk-your-openai-key - -# Claude (Anthropic) -ANTHROPIC_API_KEY=sk-ant-your-anthropic-key - -# SMS (Twilio) -TWILIO_ACCOUNT_SID=your_account_sid -TWILIO_AUTH_TOKEN=your_auth_token -TWILIO_PHONE_NUMBER=+1234567890 diff --git a/apps/backend/.env.test b/apps/backend/.env.test deleted file mode 100644 index 3cffb0b..0000000 --- a/apps/backend/.env.test +++ /dev/null @@ -1,16 +0,0 @@ -# Test Database -DATABASE_HOST=localhost -DATABASE_PORT=5433 -DATABASE_NAME=miinventario_test -DATABASE_USER=postgres -DATABASE_PASSWORD=postgres - -# JWT -JWT_SECRET=test-secret -JWT_EXPIRES_IN=15m -JWT_REFRESH_SECRET=test-refresh-secret -JWT_REFRESH_EXPIRES_IN=7d - -# App -NODE_ENV=development -PORT=3143 diff --git a/apps/backend/.eslintrc.js b/apps/backend/.eslintrc.js deleted file mode 100644 index 93b9e06..0000000 --- a/apps/backend/.eslintrc.js +++ /dev/null @@ -1,30 +0,0 @@ -module.exports = { - parser: '@typescript-eslint/parser', - parserOptions: { - project: 'tsconfig.json', - tsconfigRootDir: __dirname, - sourceType: 'module', - }, - plugins: ['@typescript-eslint/eslint-plugin'], - extends: [ - 'plugin:@typescript-eslint/recommended', - 'plugin:prettier/recommended', - ], - root: true, - env: { - node: true, - jest: true, - }, - ignorePatterns: ['.eslintrc.js', 'dist', 'node_modules'], - rules: { - '@typescript-eslint/interface-name-prefix': 'off', - '@typescript-eslint/explicit-function-return-type': 'off', - '@typescript-eslint/explicit-module-boundary-types': 'off', - '@typescript-eslint/no-explicit-any': 'warn', - '@typescript-eslint/no-unused-vars': [ - 'error', - { argsIgnorePattern: '^_' }, - ], - 'no-console': ['warn', { allow: ['warn', 'error'] }], - }, -}; diff --git a/apps/backend/.prettierrc b/apps/backend/.prettierrc deleted file mode 100644 index 73267ea..0000000 --- a/apps/backend/.prettierrc +++ /dev/null @@ -1,10 +0,0 @@ -{ - "singleQuote": true, - "trailingComma": "all", - "printWidth": 80, - "tabWidth": 2, - "semi": true, - "bracketSpacing": true, - "arrowParens": "always", - "endOfLine": "lf" -} diff --git a/apps/backend/Dockerfile b/apps/backend/Dockerfile deleted file mode 100644 index 6b637ad..0000000 --- a/apps/backend/Dockerfile +++ /dev/null @@ -1,56 +0,0 @@ -# Build stage -FROM node:18-alpine AS builder - -WORKDIR /app - -# Install build dependencies -RUN apk add --no-cache python3 make g++ - -# Copy package files -COPY package*.json ./ - -# Install all dependencies (including dev) -RUN npm ci - -# Copy source code -COPY . . - -# Build the application -RUN npm run build - -# Prune dev dependencies -RUN npm prune --production - -# Production stage -FROM node:18-alpine AS production - -# Install ffmpeg for video processing -RUN apk add --no-cache ffmpeg - -WORKDIR /app - -# Create non-root user -RUN addgroup -g 1001 -S nodejs && \ - adduser -S nestjs -u 1001 - -# Copy built application from builder -COPY --from=builder --chown=nestjs:nodejs /app/dist ./dist -COPY --from=builder --chown=nestjs:nodejs /app/node_modules ./node_modules -COPY --from=builder --chown=nestjs:nodejs /app/package.json ./package.json - -# Set environment variables -ENV NODE_ENV=production -ENV PORT=3142 - -# Switch to non-root user -USER nestjs - -# Expose port -EXPOSE 3142 - -# Health check -HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ - CMD wget --no-verbose --tries=1 --spider http://localhost:3142/api/v1/health || exit 1 - -# Start the application -CMD ["node", "dist/main.js"] diff --git a/apps/backend/nest-cli.json b/apps/backend/nest-cli.json deleted file mode 100644 index f9aa683..0000000 --- a/apps/backend/nest-cli.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/nest-cli", - "collection": "@nestjs/schematics", - "sourceRoot": "src", - "compilerOptions": { - "deleteOutDir": true - } -} diff --git a/apps/backend/package.json b/apps/backend/package.json deleted file mode 100644 index ab66c62..0000000 --- a/apps/backend/package.json +++ /dev/null @@ -1,107 +0,0 @@ -{ - "name": "@miinventario/backend", - "version": "0.1.0", - "description": "MiInventario Backend API", - "author": "MiInventario Team", - "private": true, - "license": "UNLICENSED", - "scripts": { - "build": "nest build", - "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", - "start": "nest start", - "start:dev": "nest start --watch", - "start:debug": "nest start --debug --watch", - "start:prod": "node dist/main", - "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", - "test": "jest", - "test:watch": "jest --watch", - "test:cov": "jest --coverage", - "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", - "test:e2e": "jest --config ./test/jest-e2e.json", - "typeorm": "typeorm-ts-node-commonjs", - "migration:generate": "npm run typeorm -- migration:generate -d src/config/typeorm.config.ts", - "migration:run": "npm run typeorm -- migration:run -d src/config/typeorm.config.ts", - "migration:revert": "npm run typeorm -- migration:revert -d src/config/typeorm.config.ts", - "migration:create": "npm run typeorm -- migration:create", - "schema:sync": "npm run typeorm -- schema:sync -d src/config/typeorm.config.ts", - "schema:drop": "npm run typeorm -- schema:drop -d src/config/typeorm.config.ts", - "seed": "ts-node src/database/seed.ts", - "db:setup": "npm run migration:run && npm run seed" - }, - "dependencies": { - "@anthropic-ai/sdk": "^0.71.2", - "@aws-sdk/client-s3": "^3.450.0", - "@aws-sdk/s3-request-presigner": "^3.450.0", - "@nestjs/bull": "^10.0.0", - "@nestjs/common": "^10.0.0", - "@nestjs/config": "^3.1.0", - "@nestjs/core": "^10.0.0", - "@nestjs/jwt": "^10.2.0", - "@nestjs/passport": "^10.0.2", - "@nestjs/platform-express": "^10.0.0", - "@nestjs/swagger": "^7.1.0", - "@nestjs/typeorm": "^10.0.0", - "@types/fluent-ffmpeg": "^2.1.28", - "bcrypt": "^5.1.1", - "bull": "^4.11.0", - "class-transformer": "^0.5.1", - "class-validator": "^0.14.0", - "exceljs": "^4.4.0", - "fast-csv": "^5.0.5", - "firebase-admin": "^11.11.0", - "fluent-ffmpeg": "^2.1.3", - "ioredis": "^5.3.0", - "openai": "^6.16.0", - "passport": "^0.6.0", - "passport-jwt": "^4.0.1", - "pg": "^8.11.0", - "reflect-metadata": "^0.1.13", - "rxjs": "^7.8.1", - "stripe": "^14.0.0", - "typeorm": "^0.3.17", - "uuid": "^9.0.0" - }, - "devDependencies": { - "@nestjs/cli": "^10.0.0", - "@nestjs/schematics": "^10.0.0", - "@nestjs/testing": "^10.0.0", - "@types/bcrypt": "^5.0.0", - "@types/express": "^4.17.17", - "@types/jest": "^29.5.2", - "@types/node": "^20.3.1", - "@types/passport-jwt": "^3.0.10", - "@types/supertest": "^6.0.3", - "@types/uuid": "^9.0.0", - "@typescript-eslint/eslint-plugin": "^6.0.0", - "@typescript-eslint/parser": "^6.0.0", - "eslint": "^8.42.0", - "eslint-config-prettier": "^9.0.0", - "eslint-plugin-prettier": "^5.0.0", - "jest": "^29.5.0", - "prettier": "^3.0.0", - "source-map-support": "^0.5.21", - "supertest": "^6.3.3", - "ts-jest": "^29.1.0", - "ts-loader": "^9.4.3", - "ts-node": "^10.9.1", - "tsconfig-paths": "^4.2.0", - "typescript": "^5.1.3" - }, - "jest": { - "moduleFileExtensions": [ - "js", - "json", - "ts" - ], - "rootDir": "src", - "testRegex": ".*\\.spec\\.ts$", - "transform": { - "^.+\\.(t|j)s$": "ts-jest" - }, - "collectCoverageFrom": [ - "**/*.(t|j)s" - ], - "coverageDirectory": "../coverage", - "testEnvironment": "node" - } -} diff --git a/apps/backend/src/app.module.ts b/apps/backend/src/app.module.ts deleted file mode 100644 index 8d2db98..0000000 --- a/apps/backend/src/app.module.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { Module } from '@nestjs/common'; -import { ConfigModule, ConfigService } from '@nestjs/config'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { BullModule } from '@nestjs/bull'; - -// Config -import { databaseConfig } from './config/database.config'; -import { redisConfig } from './config/redis.config'; - -// Modules -import { AuthModule } from './modules/auth/auth.module'; -import { UsersModule } from './modules/users/users.module'; -import { StoresModule } from './modules/stores/stores.module'; -import { VideosModule } from './modules/videos/videos.module'; -import { InventoryModule } from './modules/inventory/inventory.module'; -import { CreditsModule } from './modules/credits/credits.module'; -import { PaymentsModule } from './modules/payments/payments.module'; -import { ReferralsModule } from './modules/referrals/referrals.module'; -import { NotificationsModule } from './modules/notifications/notifications.module'; -import { IAProviderModule } from './modules/ia-provider/ia-provider.module'; -import { HealthModule } from './modules/health/health.module'; -import { FeedbackModule } from './modules/feedback/feedback.module'; -import { ValidationsModule } from './modules/validations/validations.module'; -import { AdminModule } from './modules/admin/admin.module'; -import { ExportsModule } from './modules/exports/exports.module'; -import { ReportsModule } from './modules/reports/reports.module'; -import { IntegrationsModule } from './modules/integrations/integrations.module'; - -@Module({ - imports: [ - // Configuration - ConfigModule.forRoot({ - isGlobal: true, - envFilePath: ['.env.local', '.env'], - }), - - // Database - TypeOrmModule.forRootAsync({ - imports: [ConfigModule], - useFactory: databaseConfig, - inject: [ConfigService], - }), - - // Redis & Bull Queue - BullModule.forRootAsync({ - imports: [ConfigModule], - useFactory: redisConfig, - inject: [ConfigService], - }), - - // Feature Modules - HealthModule, - AuthModule, - UsersModule, - StoresModule, - VideosModule, - InventoryModule, - CreditsModule, - PaymentsModule, - ReferralsModule, - NotificationsModule, - IAProviderModule, - FeedbackModule, - ValidationsModule, - AdminModule, - ExportsModule, - ReportsModule, - IntegrationsModule, - ], -}) -export class AppModule {} diff --git a/apps/backend/src/common/decorators/roles.decorator.ts b/apps/backend/src/common/decorators/roles.decorator.ts deleted file mode 100644 index e0d8bd5..0000000 --- a/apps/backend/src/common/decorators/roles.decorator.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { SetMetadata } from '@nestjs/common'; -import { UserRole } from '../../modules/users/entities/user.entity'; - -export const ROLES_KEY = 'roles'; -export const Roles = (...roles: UserRole[]) => SetMetadata(ROLES_KEY, roles); diff --git a/apps/backend/src/common/guards/roles.guard.ts b/apps/backend/src/common/guards/roles.guard.ts deleted file mode 100644 index 1a4e97f..0000000 --- a/apps/backend/src/common/guards/roles.guard.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { Injectable, CanActivate, ExecutionContext, ForbiddenException } from '@nestjs/common'; -import { Reflector } from '@nestjs/core'; -import { UserRole } from '../../modules/users/entities/user.entity'; -import { ROLES_KEY } from '../decorators/roles.decorator'; - -// Role hierarchy - higher number = more permissions -const ROLE_HIERARCHY: Record = { - [UserRole.USER]: 0, - [UserRole.VIEWER]: 1, - [UserRole.MODERATOR]: 2, - [UserRole.ADMIN]: 3, - [UserRole.SUPER_ADMIN]: 4, -}; - -@Injectable() -export class RolesGuard implements CanActivate { - constructor(private reflector: Reflector) {} - - canActivate(context: ExecutionContext): boolean { - const requiredRoles = this.reflector.getAllAndOverride(ROLES_KEY, [ - context.getHandler(), - context.getClass(), - ]); - - if (!requiredRoles || requiredRoles.length === 0) { - return true; - } - - const { user } = context.switchToHttp().getRequest(); - - if (!user || !user.role) { - throw new ForbiddenException('No tienes permisos para acceder a este recurso'); - } - - const userRoleLevel = ROLE_HIERARCHY[user.role as UserRole] ?? 0; - const minRequiredLevel = Math.min(...requiredRoles.map(role => ROLE_HIERARCHY[role])); - - if (userRoleLevel < minRequiredLevel) { - throw new ForbiddenException('No tienes permisos suficientes para esta accion'); - } - - return true; - } -} diff --git a/apps/backend/src/common/interfaces/authenticated-request.interface.ts b/apps/backend/src/common/interfaces/authenticated-request.interface.ts deleted file mode 100644 index c4c2f99..0000000 --- a/apps/backend/src/common/interfaces/authenticated-request.interface.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Request } from 'express'; - -export interface AuthenticatedUser { - id: string; - phone: string; - email?: string; - role: string; -} - -export interface AuthenticatedRequest extends Request { - user: AuthenticatedUser; -} diff --git a/apps/backend/src/config/database.config.ts b/apps/backend/src/config/database.config.ts deleted file mode 100644 index fc5ea5a..0000000 --- a/apps/backend/src/config/database.config.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { ConfigService } from '@nestjs/config'; -import { TypeOrmModuleOptions } from '@nestjs/typeorm'; - -export const databaseConfig = ( - configService: ConfigService, -): TypeOrmModuleOptions => ({ - type: 'postgres', - host: configService.get('DB_HOST', 'localhost'), - port: configService.get('DB_PORT', 5433), - username: configService.get('DB_USER', 'miinventario'), - password: configService.get('DB_PASSWORD', 'miinventario_pass'), - database: configService.get('DB_NAME', 'miinventario_db'), - entities: [__dirname + '/../**/*.entity{.ts,.js}'], - migrations: [__dirname + '/../migrations/*{.ts,.js}'], - synchronize: configService.get('NODE_ENV') === 'development', - logging: configService.get('NODE_ENV') === 'development', - ssl: configService.get('DB_SSL') === 'true' ? { rejectUnauthorized: false } : false, -}); diff --git a/apps/backend/src/config/redis.config.ts b/apps/backend/src/config/redis.config.ts deleted file mode 100644 index 07892bb..0000000 --- a/apps/backend/src/config/redis.config.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { ConfigService } from '@nestjs/config'; -import { BullModuleOptions } from '@nestjs/bull'; - -export const redisConfig = ( - configService: ConfigService, -): BullModuleOptions => ({ - redis: { - host: configService.get('REDIS_HOST', 'localhost'), - port: configService.get('REDIS_PORT', 6380), - password: configService.get('REDIS_PASSWORD'), - }, - defaultJobOptions: { - attempts: 3, - backoff: { - type: 'exponential', - delay: 5000, - }, - removeOnComplete: 100, - removeOnFail: 50, - }, -}); diff --git a/apps/backend/src/config/typeorm.config.ts b/apps/backend/src/config/typeorm.config.ts deleted file mode 100644 index 497e379..0000000 --- a/apps/backend/src/config/typeorm.config.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { DataSource, DataSourceOptions } from 'typeorm'; -import { config } from 'dotenv'; - -config(); - -export const dataSourceOptions: DataSourceOptions = { - type: 'postgres', - host: process.env.DATABASE_HOST || 'localhost', - port: parseInt(process.env.DATABASE_PORT || '5433', 10), - username: process.env.DATABASE_USER || 'postgres', - password: process.env.DATABASE_PASSWORD || 'postgres', - database: process.env.DATABASE_NAME || 'miinventario_dev', - entities: ['dist/**/*.entity.js'], - migrations: ['dist/migrations/*.js'], - synchronize: false, - logging: process.env.NODE_ENV === 'development', -}; - -const dataSource = new DataSource(dataSourceOptions); -export default dataSource; diff --git a/apps/backend/src/database/seed.ts b/apps/backend/src/database/seed.ts deleted file mode 100644 index 2cd4227..0000000 --- a/apps/backend/src/database/seed.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { DataSource } from 'typeorm'; -import { dataSourceOptions } from '../config/typeorm.config'; - -async function seed() { - const dataSource = new DataSource(dataSourceOptions); - - try { - await dataSource.initialize(); - console.log('Database connected for seeding'); - - // Seed Credit Packages - console.log('Seeding credit packages...'); - await dataSource.query(` - INSERT INTO credit_packages (id, name, description, credits, "priceMXN", "isPopular", "isActive", "sortOrder") - VALUES - (uuid_generate_v4(), 'Starter', 'Perfecto para probar', 10, 49.00, false, true, 1), - (uuid_generate_v4(), 'Basico', 'Para uso regular', 30, 129.00, false, true, 2), - (uuid_generate_v4(), 'Popular', 'El mas vendido', 75, 299.00, true, true, 3), - (uuid_generate_v4(), 'Pro', 'Para negocios activos', 150, 549.00, false, true, 4), - (uuid_generate_v4(), 'Enterprise', 'Uso intensivo', 300, 999.00, false, true, 5) - ON CONFLICT DO NOTHING; - `); - console.log('Credit packages seeded'); - - // Create test user (development only) - if (process.env.NODE_ENV === 'development') { - console.log('Creating test user...'); - - // Check if test user exists - const existingUser = await dataSource.query(` - SELECT id FROM users WHERE phone = '+521234567890' - `); - - if (existingUser.length === 0) { - const userResult = await dataSource.query(` - INSERT INTO users (id, phone, name, "businessName", role, "isActive") - VALUES (uuid_generate_v4(), '+521234567890', 'Usuario Demo', 'Tiendita Demo', 'USER', true) - RETURNING id; - `); - const userId = userResult[0].id; - - // Create test store - await dataSource.query(` - INSERT INTO stores (id, "ownerId", name, giro, address, "isActive") - VALUES (uuid_generate_v4(), $1, 'Mi Tiendita Demo', 'Abarrotes', 'Av. Principal 123, Col. Centro', true); - `, [userId]); - - // Create credit balance with bonus credits - await dataSource.query(` - INSERT INTO credit_balances (id, "userId", balance, "totalPurchased", "totalConsumed", "totalFromReferrals") - VALUES (uuid_generate_v4(), $1, 50, 0, 0, 50); - `, [userId]); - - // Create welcome notification - await dataSource.query(` - INSERT INTO notifications (id, "userId", type, title, body, "isRead") - VALUES (uuid_generate_v4(), $1, 'SYSTEM', 'Bienvenido a MiInventario', 'Tu cuenta ha sido creada. Tienes 50 creditos de bienvenida para comenzar.', false); - `, [userId]); - - console.log('Test user created with ID:', userId); - } else { - console.log('Test user already exists'); - } - } - - console.log('Seeding completed successfully!'); - } catch (error) { - console.error('Error seeding database:', error); - process.exit(1); - } finally { - await dataSource.destroy(); - } -} - -seed(); diff --git a/apps/backend/src/main.ts b/apps/backend/src/main.ts deleted file mode 100644 index 3f7e034..0000000 --- a/apps/backend/src/main.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { NestFactory } from '@nestjs/core'; -import { ValidationPipe } from '@nestjs/common'; -import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; -import { AppModule } from './app.module'; - -async function bootstrap() { - const app = await NestFactory.create(AppModule, { - // Enable raw body for Stripe webhook signature verification - rawBody: true, - }); - - // Global prefix - app.setGlobalPrefix('api/v1'); - - // Validation pipe - app.useGlobalPipes( - new ValidationPipe({ - whitelist: true, - forbidNonWhitelisted: true, - transform: true, - transformOptions: { - enableImplicitConversion: true, - }, - }), - ); - - // CORS - app.enableCors({ - origin: process.env.CORS_ORIGINS?.split(',') || ['http://localhost:8082'], - credentials: true, - }); - - // Swagger documentation - if (process.env.NODE_ENV !== 'production') { - const config = new DocumentBuilder() - .setTitle('MiInventario API') - .setDescription('API para gestion de inventario automatico por video') - .setVersion('1.0') - .addBearerAuth() - .addTag('auth', 'Autenticacion y registro') - .addTag('users', 'Gestion de usuarios') - .addTag('stores', 'Gestion de tiendas') - .addTag('inventory', 'Sesiones de inventario') - .addTag('videos', 'Upload y procesamiento de videos') - .addTag('credits', 'Wallet y creditos') - .addTag('payments', 'Pagos y paquetes') - .addTag('referrals', 'Sistema de referidos') - .addTag('exports', 'Exportacion de datos CSV/Excel') - .addTag('reports', 'Reportes avanzados') - .addTag('admin', 'Panel de administracion') - .addTag('feedback', 'Feedback y correcciones') - .addTag('validations', 'Validaciones crowdsourced') - .addTag('notifications', 'Sistema de notificaciones') - .addTag('health', 'Health checks') - .build(); - - const document = SwaggerModule.createDocument(app, config); - SwaggerModule.setup('api/docs', app, document); - } - - const port = process.env.BACKEND_PORT || 3142; - await app.listen(port); - - console.log(` - ╔══════════════════════════════════════════════════════════╗ - ║ MIINVENTARIO API ║ - ╠══════════════════════════════════════════════════════════╣ - ║ Server running on: http://localhost:${port} ║ - ║ API Docs: http://localhost:${port}/api/docs ║ - ║ Environment: ${process.env.NODE_ENV || 'development'} ║ - ╚══════════════════════════════════════════════════════════╝ - `); -} - -bootstrap(); diff --git a/apps/backend/src/migrations/1736502000000-CreateFeedbackTables.ts b/apps/backend/src/migrations/1736502000000-CreateFeedbackTables.ts deleted file mode 100644 index 02dc5e6..0000000 --- a/apps/backend/src/migrations/1736502000000-CreateFeedbackTables.ts +++ /dev/null @@ -1,201 +0,0 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; - -export class CreateFeedbackTables1736502000000 implements MigrationInterface { - name = 'CreateFeedbackTables1736502000000' - - public async up(queryRunner: QueryRunner): Promise { - // ENUMs - await queryRunner.query(`CREATE TYPE "public"."corrections_type_enum" AS ENUM('QUANTITY', 'SKU', 'CONFIRMATION')`); - await queryRunner.query(`CREATE TYPE "public"."ground_truth_status_enum" AS ENUM('PENDING', 'APPROVED', 'REJECTED')`); - await queryRunner.query(`CREATE TYPE "public"."product_submissions_status_enum" AS ENUM('PENDING', 'APPROVED', 'REJECTED')`); - await queryRunner.query(`CREATE TYPE "public"."validation_requests_status_enum" AS ENUM('PENDING', 'COMPLETED', 'SKIPPED', 'EXPIRED')`); - - // Corrections table - Historial de correcciones de usuario - await queryRunner.query(`CREATE TABLE "corrections" ( - "id" uuid NOT NULL DEFAULT uuid_generate_v4(), - "inventoryItemId" uuid NOT NULL, - "userId" uuid NOT NULL, - "storeId" uuid NOT NULL, - "type" "public"."corrections_type_enum" NOT NULL, - "previousValue" jsonb NOT NULL, - "newValue" jsonb NOT NULL, - "reason" character varying(255), - "createdAt" TIMESTAMP NOT NULL DEFAULT now(), - CONSTRAINT "PK_corrections" PRIMARY KEY ("id") - )`); - await queryRunner.query(`CREATE INDEX "IDX_corrections_item" ON "corrections" ("inventoryItemId")`); - await queryRunner.query(`CREATE INDEX "IDX_corrections_user" ON "corrections" ("userId")`); - await queryRunner.query(`CREATE INDEX "IDX_corrections_store" ON "corrections" ("storeId")`); - await queryRunner.query(`CREATE INDEX "IDX_corrections_type" ON "corrections" ("type", "createdAt")`); - - // Ground Truth table - Datos validados para entrenamiento - await queryRunner.query(`CREATE TABLE "ground_truth" ( - "id" uuid NOT NULL DEFAULT uuid_generate_v4(), - "inventoryItemId" uuid NOT NULL, - "videoId" uuid NOT NULL, - "storeId" uuid NOT NULL, - "originalDetection" jsonb NOT NULL, - "correctedData" jsonb NOT NULL, - "frameTimestamp" integer, - "boundingBox" jsonb, - "status" "public"."ground_truth_status_enum" NOT NULL DEFAULT 'PENDING', - "validatedBy" uuid, - "validationScore" numeric(5,2), - "createdAt" TIMESTAMP NOT NULL DEFAULT now(), - "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), - CONSTRAINT "PK_ground_truth" PRIMARY KEY ("id") - )`); - await queryRunner.query(`CREATE INDEX "IDX_ground_truth_item" ON "ground_truth" ("inventoryItemId")`); - await queryRunner.query(`CREATE INDEX "IDX_ground_truth_video" ON "ground_truth" ("videoId")`); - await queryRunner.query(`CREATE INDEX "IDX_ground_truth_status" ON "ground_truth" ("status")`); - await queryRunner.query(`CREATE INDEX "IDX_ground_truth_store" ON "ground_truth" ("storeId")`); - - // Product Submissions table - Nuevos productos etiquetados por usuarios - await queryRunner.query(`CREATE TABLE "product_submissions" ( - "id" uuid NOT NULL DEFAULT uuid_generate_v4(), - "userId" uuid NOT NULL, - "storeId" uuid NOT NULL, - "videoId" uuid, - "name" character varying(255) NOT NULL, - "category" character varying(100), - "barcode" character varying(50), - "imageUrl" character varying(500), - "frameTimestamp" integer, - "boundingBox" jsonb, - "status" "public"."product_submissions_status_enum" NOT NULL DEFAULT 'PENDING', - "reviewedBy" uuid, - "reviewNotes" text, - "createdAt" TIMESTAMP NOT NULL DEFAULT now(), - "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), - CONSTRAINT "PK_product_submissions" PRIMARY KEY ("id") - )`); - await queryRunner.query(`CREATE INDEX "IDX_product_submissions_user" ON "product_submissions" ("userId")`); - await queryRunner.query(`CREATE INDEX "IDX_product_submissions_store" ON "product_submissions" ("storeId")`); - await queryRunner.query(`CREATE INDEX "IDX_product_submissions_status" ON "product_submissions" ("status")`); - await queryRunner.query(`CREATE INDEX "IDX_product_submissions_barcode" ON "product_submissions" ("barcode")`); - - // Validation Requests table - Solicitudes de micro-auditoria - await queryRunner.query(`CREATE TABLE "validation_requests" ( - "id" uuid NOT NULL DEFAULT uuid_generate_v4(), - "videoId" uuid NOT NULL, - "userId" uuid NOT NULL, - "storeId" uuid NOT NULL, - "totalItems" integer NOT NULL DEFAULT '0', - "itemsValidated" integer NOT NULL DEFAULT '0', - "triggerReason" character varying(100) NOT NULL, - "probabilityScore" numeric(5,2) NOT NULL, - "status" "public"."validation_requests_status_enum" NOT NULL DEFAULT 'PENDING', - "expiresAt" TIMESTAMP NOT NULL, - "completedAt" TIMESTAMP, - "creditsRewarded" integer NOT NULL DEFAULT '0', - "createdAt" TIMESTAMP NOT NULL DEFAULT now(), - "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), - CONSTRAINT "PK_validation_requests" PRIMARY KEY ("id") - )`); - await queryRunner.query(`CREATE INDEX "IDX_validation_requests_video" ON "validation_requests" ("videoId")`); - await queryRunner.query(`CREATE INDEX "IDX_validation_requests_user" ON "validation_requests" ("userId")`); - await queryRunner.query(`CREATE INDEX "IDX_validation_requests_store" ON "validation_requests" ("storeId")`); - await queryRunner.query(`CREATE INDEX "IDX_validation_requests_status" ON "validation_requests" ("status", "expiresAt")`); - - // Validation Responses table - Respuestas de validacion por item - await queryRunner.query(`CREATE TABLE "validation_responses" ( - "id" uuid NOT NULL DEFAULT uuid_generate_v4(), - "requestId" uuid NOT NULL, - "inventoryItemId" uuid NOT NULL, - "userId" uuid NOT NULL, - "isCorrect" boolean, - "correctedQuantity" integer, - "correctedName" character varying(255), - "responseTimeMs" integer, - "createdAt" TIMESTAMP NOT NULL DEFAULT now(), - CONSTRAINT "PK_validation_responses" PRIMARY KEY ("id") - )`); - await queryRunner.query(`CREATE INDEX "IDX_validation_responses_request" ON "validation_responses" ("requestId")`); - await queryRunner.query(`CREATE INDEX "IDX_validation_responses_item" ON "validation_responses" ("inventoryItemId")`); - await queryRunner.query(`CREATE INDEX "IDX_validation_responses_user" ON "validation_responses" ("userId")`); - - // Foreign Keys - await queryRunner.query(`ALTER TABLE "corrections" ADD CONSTRAINT "FK_corrections_item" FOREIGN KEY ("inventoryItemId") REFERENCES "inventory_items"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "corrections" ADD CONSTRAINT "FK_corrections_user" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "corrections" ADD CONSTRAINT "FK_corrections_store" FOREIGN KEY ("storeId") REFERENCES "stores"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - - await queryRunner.query(`ALTER TABLE "ground_truth" ADD CONSTRAINT "FK_ground_truth_item" FOREIGN KEY ("inventoryItemId") REFERENCES "inventory_items"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "ground_truth" ADD CONSTRAINT "FK_ground_truth_video" FOREIGN KEY ("videoId") REFERENCES "videos"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "ground_truth" ADD CONSTRAINT "FK_ground_truth_store" FOREIGN KEY ("storeId") REFERENCES "stores"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "ground_truth" ADD CONSTRAINT "FK_ground_truth_validator" FOREIGN KEY ("validatedBy") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - - await queryRunner.query(`ALTER TABLE "product_submissions" ADD CONSTRAINT "FK_product_submissions_user" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "product_submissions" ADD CONSTRAINT "FK_product_submissions_store" FOREIGN KEY ("storeId") REFERENCES "stores"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "product_submissions" ADD CONSTRAINT "FK_product_submissions_video" FOREIGN KEY ("videoId") REFERENCES "videos"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "product_submissions" ADD CONSTRAINT "FK_product_submissions_reviewer" FOREIGN KEY ("reviewedBy") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - - await queryRunner.query(`ALTER TABLE "validation_requests" ADD CONSTRAINT "FK_validation_requests_video" FOREIGN KEY ("videoId") REFERENCES "videos"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "validation_requests" ADD CONSTRAINT "FK_validation_requests_user" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "validation_requests" ADD CONSTRAINT "FK_validation_requests_store" FOREIGN KEY ("storeId") REFERENCES "stores"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - - await queryRunner.query(`ALTER TABLE "validation_responses" ADD CONSTRAINT "FK_validation_responses_request" FOREIGN KEY ("requestId") REFERENCES "validation_requests"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "validation_responses" ADD CONSTRAINT "FK_validation_responses_item" FOREIGN KEY ("inventoryItemId") REFERENCES "inventory_items"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "validation_responses" ADD CONSTRAINT "FK_validation_responses_user" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - } - - public async down(queryRunner: QueryRunner): Promise { - // Drop Foreign Keys - await queryRunner.query(`ALTER TABLE "validation_responses" DROP CONSTRAINT "FK_validation_responses_user"`); - await queryRunner.query(`ALTER TABLE "validation_responses" DROP CONSTRAINT "FK_validation_responses_item"`); - await queryRunner.query(`ALTER TABLE "validation_responses" DROP CONSTRAINT "FK_validation_responses_request"`); - - await queryRunner.query(`ALTER TABLE "validation_requests" DROP CONSTRAINT "FK_validation_requests_store"`); - await queryRunner.query(`ALTER TABLE "validation_requests" DROP CONSTRAINT "FK_validation_requests_user"`); - await queryRunner.query(`ALTER TABLE "validation_requests" DROP CONSTRAINT "FK_validation_requests_video"`); - - await queryRunner.query(`ALTER TABLE "product_submissions" DROP CONSTRAINT "FK_product_submissions_reviewer"`); - await queryRunner.query(`ALTER TABLE "product_submissions" DROP CONSTRAINT "FK_product_submissions_video"`); - await queryRunner.query(`ALTER TABLE "product_submissions" DROP CONSTRAINT "FK_product_submissions_store"`); - await queryRunner.query(`ALTER TABLE "product_submissions" DROP CONSTRAINT "FK_product_submissions_user"`); - - await queryRunner.query(`ALTER TABLE "ground_truth" DROP CONSTRAINT "FK_ground_truth_validator"`); - await queryRunner.query(`ALTER TABLE "ground_truth" DROP CONSTRAINT "FK_ground_truth_store"`); - await queryRunner.query(`ALTER TABLE "ground_truth" DROP CONSTRAINT "FK_ground_truth_video"`); - await queryRunner.query(`ALTER TABLE "ground_truth" DROP CONSTRAINT "FK_ground_truth_item"`); - - await queryRunner.query(`ALTER TABLE "corrections" DROP CONSTRAINT "FK_corrections_store"`); - await queryRunner.query(`ALTER TABLE "corrections" DROP CONSTRAINT "FK_corrections_user"`); - await queryRunner.query(`ALTER TABLE "corrections" DROP CONSTRAINT "FK_corrections_item"`); - - // Drop Tables - await queryRunner.query(`DROP INDEX "public"."IDX_validation_responses_user"`); - await queryRunner.query(`DROP INDEX "public"."IDX_validation_responses_item"`); - await queryRunner.query(`DROP INDEX "public"."IDX_validation_responses_request"`); - await queryRunner.query(`DROP TABLE "validation_responses"`); - - await queryRunner.query(`DROP INDEX "public"."IDX_validation_requests_status"`); - await queryRunner.query(`DROP INDEX "public"."IDX_validation_requests_store"`); - await queryRunner.query(`DROP INDEX "public"."IDX_validation_requests_user"`); - await queryRunner.query(`DROP INDEX "public"."IDX_validation_requests_video"`); - await queryRunner.query(`DROP TABLE "validation_requests"`); - - await queryRunner.query(`DROP INDEX "public"."IDX_product_submissions_barcode"`); - await queryRunner.query(`DROP INDEX "public"."IDX_product_submissions_status"`); - await queryRunner.query(`DROP INDEX "public"."IDX_product_submissions_store"`); - await queryRunner.query(`DROP INDEX "public"."IDX_product_submissions_user"`); - await queryRunner.query(`DROP TABLE "product_submissions"`); - - await queryRunner.query(`DROP INDEX "public"."IDX_ground_truth_store"`); - await queryRunner.query(`DROP INDEX "public"."IDX_ground_truth_status"`); - await queryRunner.query(`DROP INDEX "public"."IDX_ground_truth_video"`); - await queryRunner.query(`DROP INDEX "public"."IDX_ground_truth_item"`); - await queryRunner.query(`DROP TABLE "ground_truth"`); - - await queryRunner.query(`DROP INDEX "public"."IDX_corrections_type"`); - await queryRunner.query(`DROP INDEX "public"."IDX_corrections_store"`); - await queryRunner.query(`DROP INDEX "public"."IDX_corrections_user"`); - await queryRunner.query(`DROP INDEX "public"."IDX_corrections_item"`); - await queryRunner.query(`DROP TABLE "corrections"`); - - // Drop ENUMs - await queryRunner.query(`DROP TYPE "public"."validation_requests_status_enum"`); - await queryRunner.query(`DROP TYPE "public"."product_submissions_status_enum"`); - await queryRunner.query(`DROP TYPE "public"."ground_truth_status_enum"`); - await queryRunner.query(`DROP TYPE "public"."corrections_type_enum"`); - } -} diff --git a/apps/backend/src/migrations/1736600000000-CreateAdminTables.ts b/apps/backend/src/migrations/1736600000000-CreateAdminTables.ts deleted file mode 100644 index 4750adb..0000000 --- a/apps/backend/src/migrations/1736600000000-CreateAdminTables.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; - -export class CreateAdminTables1736600000000 implements MigrationInterface { - name = 'CreateAdminTables1736600000000' - - public async up(queryRunner: QueryRunner): Promise { - // Extend users role enum with new roles - await queryRunner.query(`ALTER TYPE "public"."users_role_enum" ADD VALUE IF NOT EXISTS 'SUPER_ADMIN'`); - await queryRunner.query(`ALTER TYPE "public"."users_role_enum" ADD VALUE IF NOT EXISTS 'MODERATOR'`); - await queryRunner.query(`ALTER TYPE "public"."users_role_enum" ADD VALUE IF NOT EXISTS 'VIEWER'`); - - // Create promotion type enum - await queryRunner.query(`CREATE TYPE "public"."promotions_type_enum" AS ENUM('PERCENTAGE', 'FIXED_CREDITS', 'MULTIPLIER')`); - - // Create IA Providers table - await queryRunner.query(`CREATE TABLE "ia_providers" ( - "id" uuid NOT NULL DEFAULT uuid_generate_v4(), - "name" character varying(100) NOT NULL, - "code" character varying(50) NOT NULL, - "description" text, - "costPerFrame" numeric(10,6) NOT NULL DEFAULT '0', - "costPerToken" numeric(10,8) NOT NULL DEFAULT '0', - "isActive" boolean NOT NULL DEFAULT true, - "isDefault" boolean NOT NULL DEFAULT false, - "config" jsonb, - "createdAt" TIMESTAMP NOT NULL DEFAULT now(), - "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), - CONSTRAINT "UQ_ia_providers_code" UNIQUE ("code"), - CONSTRAINT "PK_ia_providers" PRIMARY KEY ("id") - )`); - await queryRunner.query(`CREATE INDEX "IDX_ia_providers_code" ON "ia_providers" ("code")`); - await queryRunner.query(`CREATE INDEX "IDX_ia_providers_active" ON "ia_providers" ("isActive")`); - - // Create Promotions table - await queryRunner.query(`CREATE TABLE "promotions" ( - "id" uuid NOT NULL DEFAULT uuid_generate_v4(), - "name" character varying(100) NOT NULL, - "code" character varying(50) NOT NULL, - "description" text, - "type" "public"."promotions_type_enum" NOT NULL, - "value" numeric(10,2) NOT NULL, - "minPurchaseAmount" numeric(10,2), - "maxDiscount" numeric(10,2), - "usageLimit" integer, - "usageCount" integer NOT NULL DEFAULT '0', - "perUserLimit" integer DEFAULT '1', - "startsAt" TIMESTAMP NOT NULL, - "endsAt" TIMESTAMP NOT NULL, - "isActive" boolean NOT NULL DEFAULT true, - "applicablePackageIds" uuid[], - "createdBy" uuid, - "createdAt" TIMESTAMP NOT NULL DEFAULT now(), - "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), - CONSTRAINT "UQ_promotions_code" UNIQUE ("code"), - CONSTRAINT "PK_promotions" PRIMARY KEY ("id") - )`); - await queryRunner.query(`CREATE INDEX "IDX_promotions_code" ON "promotions" ("code")`); - await queryRunner.query(`CREATE INDEX "IDX_promotions_active_dates" ON "promotions" ("isActive", "startsAt", "endsAt")`); - - // Create Audit Logs table - await queryRunner.query(`CREATE TABLE "audit_logs" ( - "id" uuid NOT NULL DEFAULT uuid_generate_v4(), - "userId" uuid NOT NULL, - "action" character varying(100) NOT NULL, - "resource" character varying(100) NOT NULL, - "resourceId" uuid, - "previousValue" jsonb, - "newValue" jsonb, - "ipAddress" character varying(45), - "userAgent" text, - "createdAt" TIMESTAMP NOT NULL DEFAULT now(), - CONSTRAINT "PK_audit_logs" PRIMARY KEY ("id") - )`); - await queryRunner.query(`CREATE INDEX "IDX_audit_logs_user" ON "audit_logs" ("userId")`); - await queryRunner.query(`CREATE INDEX "IDX_audit_logs_action" ON "audit_logs" ("action")`); - await queryRunner.query(`CREATE INDEX "IDX_audit_logs_resource" ON "audit_logs" ("resource", "resourceId")`); - await queryRunner.query(`CREATE INDEX "IDX_audit_logs_created" ON "audit_logs" ("createdAt")`); - - // Add fraud detection columns to referrals - await queryRunner.query(`ALTER TABLE "referrals" ADD "fraudHold" boolean NOT NULL DEFAULT false`); - await queryRunner.query(`ALTER TABLE "referrals" ADD "fraudReason" character varying(255)`); - await queryRunner.query(`ALTER TABLE "referrals" ADD "reviewedBy" uuid`); - await queryRunner.query(`ALTER TABLE "referrals" ADD "reviewedAt" TIMESTAMP`); - await queryRunner.query(`CREATE INDEX "IDX_referrals_fraud" ON "referrals" ("fraudHold")`); - - // Foreign Keys - await queryRunner.query(`ALTER TABLE "promotions" ADD CONSTRAINT "FK_promotions_creator" FOREIGN KEY ("createdBy") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "audit_logs" ADD CONSTRAINT "FK_audit_logs_user" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "referrals" ADD CONSTRAINT "FK_referrals_reviewer" FOREIGN KEY ("reviewedBy") REFERENCES "users"("id") ON DELETE SET NULL ON UPDATE NO ACTION`); - - // Seed initial IA providers - await queryRunner.query(` - INSERT INTO "ia_providers" ("name", "code", "description", "costPerFrame", "costPerToken", "isActive", "isDefault") - VALUES - ('OpenAI GPT-4 Vision', 'openai-gpt4v', 'OpenAI GPT-4 con capacidades de vision', 0.01, 0.00003, true, true), - ('Claude 3 Sonnet', 'claude-sonnet', 'Anthropic Claude 3 Sonnet para analisis de imagenes', 0.003, 0.000015, true, false), - ('Claude 3 Haiku', 'claude-haiku', 'Anthropic Claude 3 Haiku - rapido y economico', 0.00025, 0.00000125, true, false) - `); - } - - public async down(queryRunner: QueryRunner): Promise { - // Drop Foreign Keys - await queryRunner.query(`ALTER TABLE "referrals" DROP CONSTRAINT IF EXISTS "FK_referrals_reviewer"`); - await queryRunner.query(`ALTER TABLE "audit_logs" DROP CONSTRAINT "FK_audit_logs_user"`); - await queryRunner.query(`ALTER TABLE "promotions" DROP CONSTRAINT "FK_promotions_creator"`); - - // Remove fraud columns from referrals - await queryRunner.query(`DROP INDEX "public"."IDX_referrals_fraud"`); - await queryRunner.query(`ALTER TABLE "referrals" DROP COLUMN "reviewedAt"`); - await queryRunner.query(`ALTER TABLE "referrals" DROP COLUMN "reviewedBy"`); - await queryRunner.query(`ALTER TABLE "referrals" DROP COLUMN "fraudReason"`); - await queryRunner.query(`ALTER TABLE "referrals" DROP COLUMN "fraudHold"`); - - // Drop Audit Logs table - await queryRunner.query(`DROP INDEX "public"."IDX_audit_logs_created"`); - await queryRunner.query(`DROP INDEX "public"."IDX_audit_logs_resource"`); - await queryRunner.query(`DROP INDEX "public"."IDX_audit_logs_action"`); - await queryRunner.query(`DROP INDEX "public"."IDX_audit_logs_user"`); - await queryRunner.query(`DROP TABLE "audit_logs"`); - - // Drop Promotions table - await queryRunner.query(`DROP INDEX "public"."IDX_promotions_active_dates"`); - await queryRunner.query(`DROP INDEX "public"."IDX_promotions_code"`); - await queryRunner.query(`DROP TABLE "promotions"`); - - // Drop IA Providers table - await queryRunner.query(`DROP INDEX "public"."IDX_ia_providers_active"`); - await queryRunner.query(`DROP INDEX "public"."IDX_ia_providers_code"`); - await queryRunner.query(`DROP TABLE "ia_providers"`); - - // Drop ENUMs - await queryRunner.query(`DROP TYPE "public"."promotions_type_enum"`); - - // Note: Cannot remove enum values in PostgreSQL, they remain but are unused - } -} diff --git a/apps/backend/src/migrations/1768099560565-Init.ts b/apps/backend/src/migrations/1768099560565-Init.ts deleted file mode 100644 index 1ef2c99..0000000 --- a/apps/backend/src/migrations/1768099560565-Init.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { MigrationInterface, QueryRunner } from "typeorm"; - -export class Init1768099560565 implements MigrationInterface { - name = 'Init1768099560565' - - public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query(`CREATE TYPE "public"."users_role_enum" AS ENUM('USER', 'ADMIN')`); - await queryRunner.query(`CREATE TABLE "users" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "phone" character varying(20), "email" character varying(255), "passwordHash" character varying(255), "name" character varying(100), "businessName" character varying(100), "location" character varying(255), "giro" character varying(50), "role" "public"."users_role_enum" NOT NULL DEFAULT 'USER', "isActive" boolean NOT NULL DEFAULT true, "fcmToken" character varying(255), "stripeCustomerId" character varying(100), "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "UQ_a000cca60bcf04454e727699490" UNIQUE ("phone"), CONSTRAINT "UQ_97672ac88f789774dd47f7c8be3" UNIQUE ("email"), CONSTRAINT "PK_a3ffb1c0c8416b9fc6f907b7433" PRIMARY KEY ("id"))`); - await queryRunner.query(`CREATE TABLE "stores" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "ownerId" uuid NOT NULL, "name" character varying(100) NOT NULL, "giro" character varying(50), "address" character varying(255), "phone" character varying(20), "logoUrl" character varying(500), "settings" jsonb NOT NULL DEFAULT '{}', "isActive" boolean NOT NULL DEFAULT true, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_7aa6e7d71fa7acdd7ca43d7c9cb" PRIMARY KEY ("id"))`); - await queryRunner.query(`CREATE TYPE "public"."videos_status_enum" AS ENUM('PENDING', 'UPLOADING', 'UPLOADED', 'PROCESSING', 'COMPLETED', 'FAILED')`); - await queryRunner.query(`CREATE TABLE "videos" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "storeId" uuid NOT NULL, "uploadedById" uuid NOT NULL, "fileName" character varying(255) NOT NULL, "s3Key" character varying(500), "fileSize" bigint, "durationSeconds" integer, "status" "public"."videos_status_enum" NOT NULL DEFAULT 'PENDING', "processingProgress" integer NOT NULL DEFAULT '0', "itemsDetected" integer NOT NULL DEFAULT '0', "creditsUsed" integer NOT NULL DEFAULT '0', "errorMessage" text, "metadata" jsonb, "processedAt" TIMESTAMP, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_e4c86c0cf95aff16e9fb8220f6b" PRIMARY KEY ("id"))`); - await queryRunner.query(`CREATE TYPE "public"."store_users_role_enum" AS ENUM('OWNER', 'OPERATOR')`); - await queryRunner.query(`CREATE TABLE "store_users" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "store_id" uuid NOT NULL, "user_id" uuid NOT NULL, "role" "public"."store_users_role_enum" NOT NULL, "isActive" boolean NOT NULL DEFAULT true, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_6af90d774177332a7a99a7c1c9d" PRIMARY KEY ("id"))`); - await queryRunner.query(`CREATE TYPE "public"."referrals_status_enum" AS ENUM('PENDING', 'REGISTERED', 'QUALIFIED', 'REWARDED')`); - await queryRunner.query(`CREATE TABLE "referrals" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "referrerId" uuid NOT NULL, "referredId" uuid, "referralCode" character varying(20) NOT NULL, "status" "public"."referrals_status_enum" NOT NULL DEFAULT 'PENDING', "referrerBonusCredits" integer NOT NULL DEFAULT '0', "referredBonusCredits" integer NOT NULL DEFAULT '0', "registeredAt" TIMESTAMP, "qualifiedAt" TIMESTAMP, "rewardedAt" TIMESTAMP, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "UQ_13a1bad9eef9e5cfa4b61765261" UNIQUE ("referralCode"), CONSTRAINT "PK_ea9980e34f738b6252817326c08" PRIMARY KEY ("id"))`); - await queryRunner.query(`CREATE INDEX "IDX_13a1bad9eef9e5cfa4b6176526" ON "referrals" ("referralCode") `); - await queryRunner.query(`CREATE INDEX "IDX_ad6772c3fcb57375f43114b5cb" ON "referrals" ("referredId") `); - await queryRunner.query(`CREATE INDEX "IDX_59de462f9ce130da142e3b5a9f" ON "referrals" ("referrerId") `); - await queryRunner.query(`CREATE TABLE "credit_packages" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "name" character varying(100) NOT NULL, "description" character varying(255), "credits" integer NOT NULL, "priceMXN" numeric(10,2) NOT NULL, "isPopular" boolean NOT NULL DEFAULT false, "isActive" boolean NOT NULL DEFAULT true, "sortOrder" integer NOT NULL DEFAULT '0', "stripePriceId" character varying(100), "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_c10750b5b0638b06330b0c09bfd" PRIMARY KEY ("id"))`); - await queryRunner.query(`CREATE TYPE "public"."payments_method_enum" AS ENUM('CARD', 'OXXO', '7ELEVEN')`); - await queryRunner.query(`CREATE TYPE "public"."payments_status_enum" AS ENUM('PENDING', 'PROCESSING', 'COMPLETED', 'FAILED', 'REFUNDED', 'EXPIRED')`); - await queryRunner.query(`CREATE TABLE "payments" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "userId" uuid NOT NULL, "packageId" uuid, "amountMXN" numeric(10,2) NOT NULL, "creditsGranted" integer NOT NULL, "method" "public"."payments_method_enum" NOT NULL, "status" "public"."payments_status_enum" NOT NULL DEFAULT 'PENDING', "externalId" character varying(255), "provider" character varying(50), "voucherUrl" character varying(500), "voucherCode" character varying(100), "expiresAt" TIMESTAMP, "completedAt" TIMESTAMP, "errorMessage" text, "metadata" jsonb, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_197ab7af18c93fbb0c9b28b4a59" PRIMARY KEY ("id"))`); - await queryRunner.query(`CREATE INDEX "IDX_c9ca05ceb7cc5eae113c2eb57c" ON "payments" ("externalId") `); - await queryRunner.query(`CREATE INDEX "IDX_3cc6f3e2f26955eaa64fd7f9ea" ON "payments" ("status", "createdAt") `); - await queryRunner.query(`CREATE INDEX "IDX_1c9b5fb7b9f38cccddd7c5761b" ON "payments" ("userId", "createdAt") `); - await queryRunner.query(`CREATE TYPE "public"."notifications_type_enum" AS ENUM('VIDEO_PROCESSING_COMPLETE', 'VIDEO_PROCESSING_FAILED', 'LOW_CREDITS', 'PAYMENT_COMPLETE', 'PAYMENT_FAILED', 'REFERRAL_BONUS', 'PROMO', 'SYSTEM')`); - await queryRunner.query(`CREATE TABLE "notifications" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "userId" uuid NOT NULL, "type" "public"."notifications_type_enum" NOT NULL, "title" character varying(255) NOT NULL, "body" text, "isRead" boolean NOT NULL DEFAULT false, "isPushSent" boolean NOT NULL DEFAULT false, "data" jsonb, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_6a72c3c0f683f6462415e653c3a" PRIMARY KEY ("id"))`); - await queryRunner.query(`CREATE INDEX "IDX_5340fc241f57310d243e5ab20b" ON "notifications" ("userId", "isRead") `); - await queryRunner.query(`CREATE INDEX "IDX_21e65af2f4f242d4c85a92aff4" ON "notifications" ("userId", "createdAt") `); - await queryRunner.query(`CREATE TABLE "inventory_items" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "storeId" uuid NOT NULL, "detectedByVideoId" uuid, "name" character varying(255) NOT NULL, "category" character varying(100), "subcategory" character varying(100), "barcode" character varying(50), "quantity" integer NOT NULL DEFAULT '0', "minStock" integer, "price" numeric(10,2), "cost" numeric(10,2), "imageUrl" character varying(500), "detectionConfidence" numeric(5,2), "isManuallyEdited" boolean NOT NULL DEFAULT false, "metadata" jsonb, "lastCountedAt" TIMESTAMP, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_cf2f451407242e132547ac19169" PRIMARY KEY ("id"))`); - await queryRunner.query(`CREATE INDEX "IDX_e6661f3647402a7434bb2135df" ON "inventory_items" ("storeId", "barcode") `); - await queryRunner.query(`CREATE INDEX "IDX_81d46f4b3749d1db8628a33561" ON "inventory_items" ("storeId", "category") `); - await queryRunner.query(`CREATE INDEX "IDX_9ef0ca05424108394eaaa8f511" ON "inventory_items" ("storeId", "name") `); - await queryRunner.query(`CREATE TYPE "public"."credit_transactions_type_enum" AS ENUM('PURCHASE', 'CONSUMPTION', 'REFERRAL_BONUS', 'PROMO', 'REFUND')`); - await queryRunner.query(`CREATE TABLE "credit_transactions" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "userId" uuid NOT NULL, "type" "public"."credit_transactions_type_enum" NOT NULL, "amount" integer NOT NULL, "balanceAfter" integer NOT NULL, "description" character varying(255), "referenceId" uuid, "referenceType" character varying(50), "metadata" jsonb, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_a408319811d1ab32832ec86fc2c" PRIMARY KEY ("id"))`); - await queryRunner.query(`CREATE INDEX "IDX_413894b75b111744ab18f39b1e" ON "credit_transactions" ("type", "createdAt") `); - await queryRunner.query(`CREATE INDEX "IDX_f31233f25cf2015095fca7f6b6" ON "credit_transactions" ("userId", "createdAt") `); - await queryRunner.query(`CREATE TABLE "credit_balances" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "userId" uuid NOT NULL, "balance" integer NOT NULL DEFAULT '0', "totalPurchased" integer NOT NULL DEFAULT '0', "totalConsumed" integer NOT NULL DEFAULT '0', "totalFromReferrals" integer NOT NULL DEFAULT '0', "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "UQ_7f8103cfe175c66f1e5e8acfe23" UNIQUE ("userId"), CONSTRAINT "REL_7f8103cfe175c66f1e5e8acfe2" UNIQUE ("userId"), CONSTRAINT "PK_b9f1be6c9f3f23c5716fa7d8545" PRIMARY KEY ("id"))`); - await queryRunner.query(`CREATE TABLE "refresh_tokens" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "userId" uuid NOT NULL, "token" character varying(500) NOT NULL, "deviceInfo" character varying(100), "ipAddress" character varying(50), "isRevoked" boolean NOT NULL DEFAULT false, "expiresAt" TIMESTAMP NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_7d8bee0204106019488c4c50ffa" PRIMARY KEY ("id"))`); - await queryRunner.query(`CREATE INDEX "IDX_56b91d98f71e3d1b649ed6e9f3" ON "refresh_tokens" ("expiresAt") `); - await queryRunner.query(`CREATE INDEX "IDX_4542dd2f38a61354a040ba9fd5" ON "refresh_tokens" ("token") `); - await queryRunner.query(`CREATE INDEX "IDX_610102b60fea1455310ccd299d" ON "refresh_tokens" ("userId") `); - await queryRunner.query(`CREATE TYPE "public"."otps_purpose_enum" AS ENUM('REGISTRATION', 'LOGIN', 'PASSWORD_RESET')`); - await queryRunner.query(`CREATE TABLE "otps" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "phone" character varying(20) NOT NULL, "code" character varying(6) NOT NULL, "purpose" "public"."otps_purpose_enum" NOT NULL, "attempts" integer NOT NULL DEFAULT '0', "isUsed" boolean NOT NULL DEFAULT false, "expiresAt" TIMESTAMP NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_91fef5ed60605b854a2115d2410" PRIMARY KEY ("id"))`); - await queryRunner.query(`CREATE INDEX "IDX_2afebf0234962331e12c59c592" ON "otps" ("expiresAt") `); - await queryRunner.query(`CREATE INDEX "IDX_ee9e52dc460b0ae28fd9f276ce" ON "otps" ("phone", "purpose") `); - await queryRunner.query(`ALTER TABLE "stores" ADD CONSTRAINT "FK_a447ba082271c05997a61df26df" FOREIGN KEY ("ownerId") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "videos" ADD CONSTRAINT "FK_4177a2c071cf429219b7eb31a43" FOREIGN KEY ("storeId") REFERENCES "stores"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "videos" ADD CONSTRAINT "FK_159f8e5c7959016a0863ec419a3" FOREIGN KEY ("uploadedById") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "store_users" ADD CONSTRAINT "FK_3077a42ec6ad94cfb93f919359d" FOREIGN KEY ("store_id") REFERENCES "stores"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "store_users" ADD CONSTRAINT "FK_d741d647a3ef6419a31592f8ad6" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "referrals" ADD CONSTRAINT "FK_59de462f9ce130da142e3b5a9f4" FOREIGN KEY ("referrerId") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "referrals" ADD CONSTRAINT "FK_ad6772c3fcb57375f43114b5cb5" FOREIGN KEY ("referredId") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "payments" ADD CONSTRAINT "FK_d35cb3c13a18e1ea1705b2817b1" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "payments" ADD CONSTRAINT "FK_f14a98c8d21e57b7ddf02940bad" FOREIGN KEY ("packageId") REFERENCES "credit_packages"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "notifications" ADD CONSTRAINT "FK_692a909ee0fa9383e7859f9b406" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "inventory_items" ADD CONSTRAINT "FK_3677990d712c77ee30c1c7baa6c" FOREIGN KEY ("storeId") REFERENCES "stores"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "inventory_items" ADD CONSTRAINT "FK_212ff322ac6cd4bc78bec2bd3dd" FOREIGN KEY ("detectedByVideoId") REFERENCES "videos"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "credit_transactions" ADD CONSTRAINT "FK_2121be176f72337ccf7cc4ef04e" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "credit_balances" ADD CONSTRAINT "FK_7f8103cfe175c66f1e5e8acfe23" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - await queryRunner.query(`ALTER TABLE "refresh_tokens" ADD CONSTRAINT "FK_610102b60fea1455310ccd299de" FOREIGN KEY ("userId") REFERENCES "users"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.query(`ALTER TABLE "refresh_tokens" DROP CONSTRAINT "FK_610102b60fea1455310ccd299de"`); - await queryRunner.query(`ALTER TABLE "credit_balances" DROP CONSTRAINT "FK_7f8103cfe175c66f1e5e8acfe23"`); - await queryRunner.query(`ALTER TABLE "credit_transactions" DROP CONSTRAINT "FK_2121be176f72337ccf7cc4ef04e"`); - await queryRunner.query(`ALTER TABLE "inventory_items" DROP CONSTRAINT "FK_212ff322ac6cd4bc78bec2bd3dd"`); - await queryRunner.query(`ALTER TABLE "inventory_items" DROP CONSTRAINT "FK_3677990d712c77ee30c1c7baa6c"`); - await queryRunner.query(`ALTER TABLE "notifications" DROP CONSTRAINT "FK_692a909ee0fa9383e7859f9b406"`); - await queryRunner.query(`ALTER TABLE "payments" DROP CONSTRAINT "FK_f14a98c8d21e57b7ddf02940bad"`); - await queryRunner.query(`ALTER TABLE "payments" DROP CONSTRAINT "FK_d35cb3c13a18e1ea1705b2817b1"`); - await queryRunner.query(`ALTER TABLE "referrals" DROP CONSTRAINT "FK_ad6772c3fcb57375f43114b5cb5"`); - await queryRunner.query(`ALTER TABLE "referrals" DROP CONSTRAINT "FK_59de462f9ce130da142e3b5a9f4"`); - await queryRunner.query(`ALTER TABLE "store_users" DROP CONSTRAINT "FK_d741d647a3ef6419a31592f8ad6"`); - await queryRunner.query(`ALTER TABLE "store_users" DROP CONSTRAINT "FK_3077a42ec6ad94cfb93f919359d"`); - await queryRunner.query(`ALTER TABLE "videos" DROP CONSTRAINT "FK_159f8e5c7959016a0863ec419a3"`); - await queryRunner.query(`ALTER TABLE "videos" DROP CONSTRAINT "FK_4177a2c071cf429219b7eb31a43"`); - await queryRunner.query(`ALTER TABLE "stores" DROP CONSTRAINT "FK_a447ba082271c05997a61df26df"`); - await queryRunner.query(`DROP INDEX "public"."IDX_ee9e52dc460b0ae28fd9f276ce"`); - await queryRunner.query(`DROP INDEX "public"."IDX_2afebf0234962331e12c59c592"`); - await queryRunner.query(`DROP TABLE "otps"`); - await queryRunner.query(`DROP TYPE "public"."otps_purpose_enum"`); - await queryRunner.query(`DROP INDEX "public"."IDX_610102b60fea1455310ccd299d"`); - await queryRunner.query(`DROP INDEX "public"."IDX_4542dd2f38a61354a040ba9fd5"`); - await queryRunner.query(`DROP INDEX "public"."IDX_56b91d98f71e3d1b649ed6e9f3"`); - await queryRunner.query(`DROP TABLE "refresh_tokens"`); - await queryRunner.query(`DROP TABLE "credit_balances"`); - await queryRunner.query(`DROP INDEX "public"."IDX_f31233f25cf2015095fca7f6b6"`); - await queryRunner.query(`DROP INDEX "public"."IDX_413894b75b111744ab18f39b1e"`); - await queryRunner.query(`DROP TABLE "credit_transactions"`); - await queryRunner.query(`DROP TYPE "public"."credit_transactions_type_enum"`); - await queryRunner.query(`DROP INDEX "public"."IDX_9ef0ca05424108394eaaa8f511"`); - await queryRunner.query(`DROP INDEX "public"."IDX_81d46f4b3749d1db8628a33561"`); - await queryRunner.query(`DROP INDEX "public"."IDX_e6661f3647402a7434bb2135df"`); - await queryRunner.query(`DROP TABLE "inventory_items"`); - await queryRunner.query(`DROP INDEX "public"."IDX_21e65af2f4f242d4c85a92aff4"`); - await queryRunner.query(`DROP INDEX "public"."IDX_5340fc241f57310d243e5ab20b"`); - await queryRunner.query(`DROP TABLE "notifications"`); - await queryRunner.query(`DROP TYPE "public"."notifications_type_enum"`); - await queryRunner.query(`DROP INDEX "public"."IDX_1c9b5fb7b9f38cccddd7c5761b"`); - await queryRunner.query(`DROP INDEX "public"."IDX_3cc6f3e2f26955eaa64fd7f9ea"`); - await queryRunner.query(`DROP INDEX "public"."IDX_c9ca05ceb7cc5eae113c2eb57c"`); - await queryRunner.query(`DROP TABLE "payments"`); - await queryRunner.query(`DROP TYPE "public"."payments_status_enum"`); - await queryRunner.query(`DROP TYPE "public"."payments_method_enum"`); - await queryRunner.query(`DROP TABLE "credit_packages"`); - await queryRunner.query(`DROP INDEX "public"."IDX_59de462f9ce130da142e3b5a9f"`); - await queryRunner.query(`DROP INDEX "public"."IDX_ad6772c3fcb57375f43114b5cb"`); - await queryRunner.query(`DROP INDEX "public"."IDX_13a1bad9eef9e5cfa4b6176526"`); - await queryRunner.query(`DROP TABLE "referrals"`); - await queryRunner.query(`DROP TYPE "public"."referrals_status_enum"`); - await queryRunner.query(`DROP TABLE "store_users"`); - await queryRunner.query(`DROP TYPE "public"."store_users_role_enum"`); - await queryRunner.query(`DROP TABLE "videos"`); - await queryRunner.query(`DROP TYPE "public"."videos_status_enum"`); - await queryRunner.query(`DROP TABLE "stores"`); - await queryRunner.query(`DROP TABLE "users"`); - await queryRunner.query(`DROP TYPE "public"."users_role_enum"`); - } - -} diff --git a/apps/backend/src/migrations/1768200000000-CreateExportsTables.ts b/apps/backend/src/migrations/1768200000000-CreateExportsTables.ts deleted file mode 100644 index 25779ed..0000000 --- a/apps/backend/src/migrations/1768200000000-CreateExportsTables.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { MigrationInterface, QueryRunner } from 'typeorm'; - -export class CreateExportsTables1768200000000 implements MigrationInterface { - name = 'CreateExportsTables1768200000000'; - - public async up(queryRunner: QueryRunner): Promise { - // Create enum for export format - await queryRunner.query(` - CREATE TYPE "export_format_enum" AS ENUM ('CSV', 'EXCEL') - `); - - // Create enum for export type - await queryRunner.query(` - CREATE TYPE "export_type_enum" AS ENUM ( - 'INVENTORY', - 'REPORT_VALUATION', - 'REPORT_MOVEMENTS', - 'REPORT_CATEGORIES', - 'REPORT_LOW_STOCK' - ) - `); - - // Create enum for export status - await queryRunner.query(` - CREATE TYPE "export_status_enum" AS ENUM ( - 'PENDING', - 'PROCESSING', - 'COMPLETED', - 'FAILED' - ) - `); - - // Create export_jobs table - await queryRunner.query(` - CREATE TABLE "export_jobs" ( - "id" uuid NOT NULL DEFAULT uuid_generate_v4(), - "userId" uuid NOT NULL, - "storeId" uuid NOT NULL, - "format" "export_format_enum" NOT NULL DEFAULT 'CSV', - "type" "export_type_enum" NOT NULL DEFAULT 'INVENTORY', - "status" "export_status_enum" NOT NULL DEFAULT 'PENDING', - "filters" jsonb, - "s3Key" varchar(500), - "downloadUrl" varchar(1000), - "expiresAt" timestamp, - "totalRows" integer, - "errorMessage" text, - "createdAt" timestamp NOT NULL DEFAULT now(), - "updatedAt" timestamp NOT NULL DEFAULT now(), - CONSTRAINT "PK_export_jobs" PRIMARY KEY ("id"), - CONSTRAINT "FK_export_jobs_user" FOREIGN KEY ("userId") - REFERENCES "users"("id") ON DELETE CASCADE, - CONSTRAINT "FK_export_jobs_store" FOREIGN KEY ("storeId") - REFERENCES "stores"("id") ON DELETE CASCADE - ) - `); - - // Create indexes - await queryRunner.query(` - CREATE INDEX "IDX_export_jobs_userId" ON "export_jobs" ("userId") - `); - - await queryRunner.query(` - CREATE INDEX "IDX_export_jobs_storeId" ON "export_jobs" ("storeId") - `); - - await queryRunner.query(` - CREATE INDEX "IDX_export_jobs_status" ON "export_jobs" ("status") - `); - - await queryRunner.query(` - CREATE INDEX "IDX_export_jobs_createdAt" ON "export_jobs" ("createdAt") - `); - } - - public async down(queryRunner: QueryRunner): Promise { - // Drop indexes - await queryRunner.query(`DROP INDEX "IDX_export_jobs_createdAt"`); - await queryRunner.query(`DROP INDEX "IDX_export_jobs_status"`); - await queryRunner.query(`DROP INDEX "IDX_export_jobs_storeId"`); - await queryRunner.query(`DROP INDEX "IDX_export_jobs_userId"`); - - // Drop table - await queryRunner.query(`DROP TABLE "export_jobs"`); - - // Drop enums - await queryRunner.query(`DROP TYPE "export_status_enum"`); - await queryRunner.query(`DROP TYPE "export_type_enum"`); - await queryRunner.query(`DROP TYPE "export_format_enum"`); - } -} diff --git a/apps/backend/src/migrations/1768200001000-CreateInventoryMovements.ts b/apps/backend/src/migrations/1768200001000-CreateInventoryMovements.ts deleted file mode 100644 index 74aa3fb..0000000 --- a/apps/backend/src/migrations/1768200001000-CreateInventoryMovements.ts +++ /dev/null @@ -1,156 +0,0 @@ -import { MigrationInterface, QueryRunner, Table, TableIndex } from 'typeorm'; - -export class CreateInventoryMovements1768200001000 - implements MigrationInterface -{ - name = 'CreateInventoryMovements1768200001000'; - - public async up(queryRunner: QueryRunner): Promise { - // Create movement_type enum - await queryRunner.query(` - CREATE TYPE "movement_type_enum" AS ENUM ( - 'DETECTION', - 'MANUAL_ADJUST', - 'SALE', - 'PURCHASE', - 'CORRECTION', - 'INITIAL', - 'POS_SYNC' - ) - `); - - // Create trigger_type enum - await queryRunner.query(` - CREATE TYPE "trigger_type_enum" AS ENUM ( - 'USER', - 'VIDEO', - 'POS', - 'SYSTEM' - ) - `); - - // Create inventory_movements table - await queryRunner.createTable( - new Table({ - name: 'inventory_movements', - columns: [ - { - name: 'id', - type: 'uuid', - isPrimary: true, - generationStrategy: 'uuid', - default: 'uuid_generate_v4()', - }, - { - name: 'inventoryItemId', - type: 'uuid', - }, - { - name: 'storeId', - type: 'uuid', - }, - { - name: 'type', - type: 'movement_type_enum', - }, - { - name: 'quantityBefore', - type: 'int', - }, - { - name: 'quantityAfter', - type: 'int', - }, - { - name: 'quantityChange', - type: 'int', - }, - { - name: 'reason', - type: 'varchar', - length: '255', - isNullable: true, - }, - { - name: 'triggeredById', - type: 'uuid', - isNullable: true, - }, - { - name: 'triggerType', - type: 'trigger_type_enum', - default: `'SYSTEM'`, - }, - { - name: 'referenceId', - type: 'uuid', - isNullable: true, - }, - { - name: 'referenceType', - type: 'varchar', - length: '50', - isNullable: true, - }, - { - name: 'createdAt', - type: 'timestamp', - default: 'CURRENT_TIMESTAMP', - }, - ], - foreignKeys: [ - { - columnNames: ['inventoryItemId'], - referencedTableName: 'inventory_items', - referencedColumnNames: ['id'], - onDelete: 'CASCADE', - }, - { - columnNames: ['storeId'], - referencedTableName: 'stores', - referencedColumnNames: ['id'], - onDelete: 'CASCADE', - }, - { - columnNames: ['triggeredById'], - referencedTableName: 'users', - referencedColumnNames: ['id'], - onDelete: 'SET NULL', - }, - ], - }), - true, - ); - - // Create indexes - await queryRunner.createIndex( - 'inventory_movements', - new TableIndex({ - name: 'IDX_inventory_movements_store_created', - columnNames: ['storeId', 'createdAt'], - }), - ); - - await queryRunner.createIndex( - 'inventory_movements', - new TableIndex({ - name: 'IDX_inventory_movements_item_created', - columnNames: ['inventoryItemId', 'createdAt'], - }), - ); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.dropIndex( - 'inventory_movements', - 'IDX_inventory_movements_item_created', - ); - await queryRunner.dropIndex( - 'inventory_movements', - 'IDX_inventory_movements_store_created', - ); - await queryRunner.dropTable('inventory_movements'); - await queryRunner.query('DROP TYPE "trigger_type_enum"'); - await queryRunner.query('DROP TYPE "movement_type_enum"'); - } -} diff --git a/apps/backend/src/migrations/1768200002000-CreatePosIntegrations.ts b/apps/backend/src/migrations/1768200002000-CreatePosIntegrations.ts deleted file mode 100644 index f268412..0000000 --- a/apps/backend/src/migrations/1768200002000-CreatePosIntegrations.ts +++ /dev/null @@ -1,261 +0,0 @@ -import { MigrationInterface, QueryRunner, Table, TableIndex } from 'typeorm'; - -export class CreatePosIntegrations1768200002000 implements MigrationInterface { - name = 'CreatePosIntegrations1768200002000'; - - public async up(queryRunner: QueryRunner): Promise { - // Create pos_provider enum - await queryRunner.query(` - CREATE TYPE "pos_provider_enum" AS ENUM ( - 'SQUARE', - 'SHOPIFY', - 'CLOVER', - 'LIGHTSPEED', - 'TOAST', - 'CUSTOM' - ) - `); - - // Create sync_direction enum - await queryRunner.query(` - CREATE TYPE "sync_direction_enum" AS ENUM ( - 'POS_TO_INVENTORY', - 'INVENTORY_TO_POS', - 'BIDIRECTIONAL' - ) - `); - - // Create sync_log_type enum - await queryRunner.query(` - CREATE TYPE "sync_log_type_enum" AS ENUM ( - 'WEBHOOK_RECEIVED', - 'MANUAL_SYNC', - 'SCHEDULED_SYNC' - ) - `); - - // Create sync_log_status enum - await queryRunner.query(` - CREATE TYPE "sync_log_status_enum" AS ENUM ( - 'SUCCESS', - 'PARTIAL', - 'FAILED' - ) - `); - - // Create pos_integrations table - await queryRunner.createTable( - new Table({ - name: 'pos_integrations', - columns: [ - { - name: 'id', - type: 'uuid', - isPrimary: true, - generationStrategy: 'uuid', - default: 'uuid_generate_v4()', - }, - { - name: 'storeId', - type: 'uuid', - }, - { - name: 'provider', - type: 'pos_provider_enum', - }, - { - name: 'displayName', - type: 'varchar', - length: '255', - isNullable: true, - }, - { - name: 'credentials', - type: 'jsonb', - isNullable: true, - }, - { - name: 'webhookSecret', - type: 'varchar', - length: '255', - isNullable: true, - }, - { - name: 'webhookUrl', - type: 'varchar', - length: '500', - isNullable: true, - }, - { - name: 'isActive', - type: 'boolean', - default: false, - }, - { - name: 'syncEnabled', - type: 'boolean', - default: true, - }, - { - name: 'syncDirection', - type: 'sync_direction_enum', - default: `'POS_TO_INVENTORY'`, - }, - { - name: 'syncConfig', - type: 'jsonb', - isNullable: true, - }, - { - name: 'lastSyncAt', - type: 'timestamp', - isNullable: true, - }, - { - name: 'lastSyncStatus', - type: 'varchar', - length: '255', - isNullable: true, - }, - { - name: 'syncErrorCount', - type: 'int', - default: 0, - }, - { - name: 'createdAt', - type: 'timestamp', - default: 'CURRENT_TIMESTAMP', - }, - { - name: 'updatedAt', - type: 'timestamp', - default: 'CURRENT_TIMESTAMP', - }, - ], - foreignKeys: [ - { - columnNames: ['storeId'], - referencedTableName: 'stores', - referencedColumnNames: ['id'], - onDelete: 'CASCADE', - }, - ], - }), - true, - ); - - // Create unique index - await queryRunner.createIndex( - 'pos_integrations', - new TableIndex({ - name: 'IDX_pos_integrations_store_provider', - columnNames: ['storeId', 'provider'], - isUnique: true, - }), - ); - - // Create pos_sync_logs table - await queryRunner.createTable( - new Table({ - name: 'pos_sync_logs', - columns: [ - { - name: 'id', - type: 'uuid', - isPrimary: true, - generationStrategy: 'uuid', - default: 'uuid_generate_v4()', - }, - { - name: 'integrationId', - type: 'uuid', - }, - { - name: 'type', - type: 'sync_log_type_enum', - }, - { - name: 'status', - type: 'sync_log_status_enum', - }, - { - name: 'itemsProcessed', - type: 'int', - default: 0, - }, - { - name: 'itemsCreated', - type: 'int', - default: 0, - }, - { - name: 'itemsUpdated', - type: 'int', - default: 0, - }, - { - name: 'itemsSkipped', - type: 'int', - default: 0, - }, - { - name: 'itemsFailed', - type: 'int', - default: 0, - }, - { - name: 'details', - type: 'jsonb', - isNullable: true, - }, - { - name: 'errorMessage', - type: 'text', - isNullable: true, - }, - { - name: 'createdAt', - type: 'timestamp', - default: 'CURRENT_TIMESTAMP', - }, - ], - foreignKeys: [ - { - columnNames: ['integrationId'], - referencedTableName: 'pos_integrations', - referencedColumnNames: ['id'], - onDelete: 'CASCADE', - }, - ], - }), - true, - ); - - // Create index for sync logs - await queryRunner.createIndex( - 'pos_sync_logs', - new TableIndex({ - name: 'IDX_pos_sync_logs_integration_created', - columnNames: ['integrationId', 'createdAt'], - }), - ); - } - - public async down(queryRunner: QueryRunner): Promise { - await queryRunner.dropIndex( - 'pos_sync_logs', - 'IDX_pos_sync_logs_integration_created', - ); - await queryRunner.dropTable('pos_sync_logs'); - await queryRunner.dropIndex( - 'pos_integrations', - 'IDX_pos_integrations_store_provider', - ); - await queryRunner.dropTable('pos_integrations'); - await queryRunner.query('DROP TYPE "sync_log_status_enum"'); - await queryRunner.query('DROP TYPE "sync_log_type_enum"'); - await queryRunner.query('DROP TYPE "sync_direction_enum"'); - await queryRunner.query('DROP TYPE "pos_provider_enum"'); - } -} diff --git a/apps/backend/src/modules/admin/admin.controller.ts b/apps/backend/src/modules/admin/admin.controller.ts deleted file mode 100644 index 529be2b..0000000 --- a/apps/backend/src/modules/admin/admin.controller.ts +++ /dev/null @@ -1,248 +0,0 @@ -import { - Controller, - Get, - Post, - Patch, - Body, - Param, - Query, - UseGuards, - Req, - ParseUUIDPipe, -} from '@nestjs/common'; -import { Request } from 'express'; -import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; -import { RolesGuard } from '../../common/guards/roles.guard'; -import { Roles } from '../../common/decorators/roles.decorator'; -import { UserRole } from '../users/entities/user.entity'; -import { AdminDashboardService } from './services/admin-dashboard.service'; -import { AdminProvidersService } from './services/admin-providers.service'; -import { AdminPackagesService } from './services/admin-packages.service'; -import { AdminPromotionsService } from './services/admin-promotions.service'; -import { AdminModerationService } from './services/admin-moderation.service'; -import { DashboardQueryDto, DashboardPeriod } from './dto/dashboard.dto'; -import { UpdateProviderDto } from './dto/provider.dto'; -import { CreatePackageDto, UpdatePackageDto } from './dto/package.dto'; -import { CreatePromotionDto, UpdatePromotionDto, ValidatePromoCodeDto } from './dto/promotion.dto'; -import { ApproveProductDto, RejectProductDto, ApproveReferralDto, RejectReferralDto } from './dto/moderation.dto'; - -interface AuthRequest extends Request { - user: { id: string; role: string }; -} - -@Controller('admin') -@UseGuards(JwtAuthGuard, RolesGuard) -export class AdminController { - constructor( - private readonly dashboardService: AdminDashboardService, - private readonly providersService: AdminProvidersService, - private readonly packagesService: AdminPackagesService, - private readonly promotionsService: AdminPromotionsService, - private readonly moderationService: AdminModerationService, - ) {} - - // Dashboard Endpoints - - @Get('dashboard') - @Roles(UserRole.VIEWER) - async getDashboard(@Query() query: DashboardQueryDto) { - const startDate = query.startDate ? new Date(query.startDate) : undefined; - const endDate = query.endDate ? new Date(query.endDate) : undefined; - - const metrics = await this.dashboardService.getDashboardMetrics(startDate, endDate); - return { metrics }; - } - - @Get('dashboard/revenue-series') - @Roles(UserRole.ADMIN) - async getRevenueSeries(@Query() query: DashboardQueryDto) { - const now = new Date(); - const startDate = query.startDate - ? new Date(query.startDate) - : new Date(now.getFullYear(), now.getMonth() - 1, 1); - const endDate = query.endDate ? new Date(query.endDate) : now; - const period = query.period || DashboardPeriod.DAY; - - const series = await this.dashboardService.getRevenueSeries(startDate, endDate, period); - return { series }; - } - - // IA Providers Endpoints - - @Get('providers') - @Roles(UserRole.ADMIN) - async getProviders() { - const providers = await this.providersService.findAll(); - return { providers }; - } - - @Patch('providers/:id') - @Roles(UserRole.SUPER_ADMIN) - async updateProvider( - @Req() req: AuthRequest, - @Param('id', ParseUUIDPipe) id: string, - @Body() dto: UpdateProviderDto, - ) { - const provider = await this.providersService.update(id, dto, req.user.id); - return { - message: 'Proveedor actualizado exitosamente', - provider, - }; - } - - // Credit Packages Endpoints - - @Get('packages') - @Roles(UserRole.ADMIN) - async getPackages(@Query('includeInactive') includeInactive?: string) { - const packages = await this.packagesService.findAll(includeInactive === 'true'); - return { packages }; - } - - @Post('packages') - @Roles(UserRole.ADMIN) - async createPackage(@Req() req: AuthRequest, @Body() dto: CreatePackageDto) { - const pkg = await this.packagesService.create(dto, req.user.id); - return { - message: 'Paquete creado exitosamente', - package: pkg, - }; - } - - @Patch('packages/:id') - @Roles(UserRole.ADMIN) - async updatePackage( - @Req() req: AuthRequest, - @Param('id', ParseUUIDPipe) id: string, - @Body() dto: UpdatePackageDto, - ) { - const pkg = await this.packagesService.update(id, dto, req.user.id); - return { - message: 'Paquete actualizado exitosamente', - package: pkg, - }; - } - - // Promotions Endpoints - - @Get('promotions') - @Roles(UserRole.ADMIN) - async getPromotions(@Query('includeExpired') includeExpired?: string) { - const promotions = await this.promotionsService.findAll(includeExpired === 'true'); - return { promotions }; - } - - @Post('promotions') - @Roles(UserRole.ADMIN) - async createPromotion(@Req() req: AuthRequest, @Body() dto: CreatePromotionDto) { - const promotion = await this.promotionsService.create(dto, req.user.id); - return { - message: 'Promocion creada exitosamente', - promotion, - }; - } - - @Patch('promotions/:id') - @Roles(UserRole.ADMIN) - async updatePromotion( - @Req() req: AuthRequest, - @Param('id', ParseUUIDPipe) id: string, - @Body() dto: UpdatePromotionDto, - ) { - const promotion = await this.promotionsService.update(id, dto, req.user.id); - return { - message: 'Promocion actualizada exitosamente', - promotion, - }; - } - - @Post('promotions/validate') - @Roles(UserRole.VIEWER) - async validatePromoCode(@Body() dto: ValidatePromoCodeDto) { - return this.promotionsService.validateCode(dto.code, dto.packageId, dto.purchaseAmount); - } - - // Product Moderation Endpoints - - @Get('products/pending') - @Roles(UserRole.MODERATOR) - async getPendingProducts( - @Query('page') page?: string, - @Query('limit') limit?: string, - ) { - return this.moderationService.getPendingProducts( - page ? parseInt(page, 10) : 1, - limit ? parseInt(limit, 10) : 20, - ); - } - - @Post('products/:id/approve') - @Roles(UserRole.MODERATOR) - async approveProduct( - @Req() req: AuthRequest, - @Param('id', ParseUUIDPipe) id: string, - @Body() dto: ApproveProductDto, - ) { - const product = await this.moderationService.approveProduct(id, dto, req.user.id); - return { - message: 'Producto aprobado exitosamente', - product, - }; - } - - @Post('products/:id/reject') - @Roles(UserRole.MODERATOR) - async rejectProduct( - @Req() req: AuthRequest, - @Param('id', ParseUUIDPipe) id: string, - @Body() dto: RejectProductDto, - ) { - const product = await this.moderationService.rejectProduct(id, dto, req.user.id); - return { - message: 'Producto rechazado', - product, - }; - } - - // Referral Fraud Moderation Endpoints - - @Get('referrals/fraud-holds') - @Roles(UserRole.MODERATOR) - async getFraudHoldReferrals( - @Query('page') page?: string, - @Query('limit') limit?: string, - ) { - return this.moderationService.getFraudHoldReferrals( - page ? parseInt(page, 10) : 1, - limit ? parseInt(limit, 10) : 20, - ); - } - - @Post('referrals/:id/approve') - @Roles(UserRole.MODERATOR) - async approveReferral( - @Req() req: AuthRequest, - @Param('id', ParseUUIDPipe) id: string, - @Body() dto: ApproveReferralDto, - ) { - const referral = await this.moderationService.approveReferral(id, dto, req.user.id); - return { - message: 'Referido aprobado exitosamente', - referral, - }; - } - - @Post('referrals/:id/reject') - @Roles(UserRole.MODERATOR) - async rejectReferral( - @Req() req: AuthRequest, - @Param('id', ParseUUIDPipe) id: string, - @Body() dto: RejectReferralDto, - ) { - const referral = await this.moderationService.rejectReferral(id, dto, req.user.id); - return { - message: 'Referido rechazado por fraude', - referral, - }; - } -} diff --git a/apps/backend/src/modules/admin/admin.module.ts b/apps/backend/src/modules/admin/admin.module.ts deleted file mode 100644 index 71e0489..0000000 --- a/apps/backend/src/modules/admin/admin.module.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { AdminController } from './admin.controller'; -import { AdminDashboardService } from './services/admin-dashboard.service'; -import { AdminProvidersService } from './services/admin-providers.service'; -import { AdminPackagesService } from './services/admin-packages.service'; -import { AdminPromotionsService } from './services/admin-promotions.service'; -import { AdminModerationService } from './services/admin-moderation.service'; -import { AuditLogService } from './services/audit-log.service'; -import { IaProvider } from './entities/ia-provider.entity'; -import { Promotion } from './entities/promotion.entity'; -import { AuditLog } from './entities/audit-log.entity'; -import { User } from '../users/entities/user.entity'; -import { Store } from '../stores/entities/store.entity'; -import { Video } from '../videos/entities/video.entity'; -import { Payment } from '../payments/entities/payment.entity'; -import { CreditPackage } from '../credits/entities/credit-package.entity'; -import { CreditTransaction } from '../credits/entities/credit-transaction.entity'; -import { ProductSubmission } from '../feedback/entities/product-submission.entity'; -import { Referral } from '../referrals/entities/referral.entity'; - -@Module({ - imports: [ - TypeOrmModule.forFeature([ - IaProvider, - Promotion, - AuditLog, - User, - Store, - Video, - Payment, - CreditPackage, - CreditTransaction, - ProductSubmission, - Referral, - ]), - ], - controllers: [AdminController], - providers: [ - AdminDashboardService, - AdminProvidersService, - AdminPackagesService, - AdminPromotionsService, - AdminModerationService, - AuditLogService, - ], - exports: [ - AdminProvidersService, - AdminPromotionsService, - AuditLogService, - ], -}) -export class AdminModule {} diff --git a/apps/backend/src/modules/admin/dto/dashboard.dto.ts b/apps/backend/src/modules/admin/dto/dashboard.dto.ts deleted file mode 100644 index c4f6ccf..0000000 --- a/apps/backend/src/modules/admin/dto/dashboard.dto.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { IsOptional, IsDateString, IsEnum } from 'class-validator'; - -export enum DashboardPeriod { - DAY = 'day', - WEEK = 'week', - MONTH = 'month', - YEAR = 'year', -} - -export class DashboardQueryDto { - @IsOptional() - @IsDateString() - startDate?: string; - - @IsOptional() - @IsDateString() - endDate?: string; - - @IsOptional() - @IsEnum(DashboardPeriod) - period?: DashboardPeriod; -} - -export interface DashboardMetrics { - users: { - total: number; - mau: number; - dau: number; - newThisPeriod: number; - }; - stores: { - total: number; - activeThisPeriod: number; - }; - videos: { - total: number; - processedThisPeriod: number; - averageProcessingTime: number; - }; - revenue: { - total: number; - thisPeriod: number; - byPackage: { packageId: string; name: string; amount: number }[]; - }; - cogs: { - total: number; - thisPeriod: number; - byProvider: { providerId: string; name: string; cost: number }[]; - }; - margin: { - gross: number; - percentage: number; - }; - credits: { - purchased: number; - used: number; - gifted: number; - }; -} - -export interface RevenueSeriesPoint { - date: string; - revenue: number; - cogs: number; - margin: number; -} diff --git a/apps/backend/src/modules/admin/dto/moderation.dto.ts b/apps/backend/src/modules/admin/dto/moderation.dto.ts deleted file mode 100644 index 06ee7dc..0000000 --- a/apps/backend/src/modules/admin/dto/moderation.dto.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { IsString, IsOptional, IsUUID, Length } from 'class-validator'; - -export class ApproveProductDto { - @IsOptional() - @IsString() - @Length(0, 255) - notes?: string; - - @IsOptional() - @IsString() - category?: string; -} - -export class RejectProductDto { - @IsString() - @Length(2, 500) - reason: string; -} - -export class ApproveReferralDto { - @IsOptional() - @IsString() - @Length(0, 255) - notes?: string; -} - -export class RejectReferralDto { - @IsString() - @Length(2, 500) - reason: string; -} - -export class PaginationQueryDto { - @IsOptional() - page?: number; - - @IsOptional() - limit?: number; -} diff --git a/apps/backend/src/modules/admin/dto/package.dto.ts b/apps/backend/src/modules/admin/dto/package.dto.ts deleted file mode 100644 index 78c3d15..0000000 --- a/apps/backend/src/modules/admin/dto/package.dto.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { IsString, IsNumber, IsBoolean, IsOptional, Min, Max, Length } from 'class-validator'; - -export class CreatePackageDto { - @IsString() - @Length(2, 100) - name: string; - - @IsOptional() - @IsString() - @Length(0, 500) - description?: string; - - @IsNumber() - @Min(1) - credits: number; - - @IsNumber() - @Min(0) - priceMxn: number; - - @IsOptional() - @IsNumber() - @Min(0) - priceUsd?: number; - - @IsOptional() - @IsBoolean() - isPopular?: boolean; - - @IsOptional() - @IsNumber() - @Min(0) - @Max(100) - discountPercentage?: number; - - @IsOptional() - @IsBoolean() - isActive?: boolean; -} - -export class UpdatePackageDto { - @IsOptional() - @IsString() - @Length(2, 100) - name?: string; - - @IsOptional() - @IsString() - @Length(0, 500) - description?: string; - - @IsOptional() - @IsNumber() - @Min(1) - credits?: number; - - @IsOptional() - @IsNumber() - @Min(0) - priceMxn?: number; - - @IsOptional() - @IsNumber() - @Min(0) - priceUsd?: number; - - @IsOptional() - @IsBoolean() - isPopular?: boolean; - - @IsOptional() - @IsNumber() - @Min(0) - @Max(100) - discountPercentage?: number; - - @IsOptional() - @IsBoolean() - isActive?: boolean; -} diff --git a/apps/backend/src/modules/admin/dto/promotion.dto.ts b/apps/backend/src/modules/admin/dto/promotion.dto.ts deleted file mode 100644 index 2e6c254..0000000 --- a/apps/backend/src/modules/admin/dto/promotion.dto.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { - IsString, - IsNumber, - IsBoolean, - IsOptional, - IsEnum, - IsDateString, - IsArray, - IsUUID, - Min, - Max, - Length, -} from 'class-validator'; -import { PromotionType } from '../entities/promotion.entity'; - -export class CreatePromotionDto { - @IsString() - @Length(2, 100) - name: string; - - @IsString() - @Length(2, 50) - code: string; - - @IsOptional() - @IsString() - description?: string; - - @IsEnum(PromotionType) - type: PromotionType; - - @IsNumber() - @Min(0) - value: number; - - @IsOptional() - @IsNumber() - @Min(0) - minPurchaseAmount?: number; - - @IsOptional() - @IsNumber() - @Min(0) - maxDiscount?: number; - - @IsOptional() - @IsNumber() - @Min(1) - usageLimit?: number; - - @IsOptional() - @IsNumber() - @Min(1) - perUserLimit?: number; - - @IsDateString() - startsAt: string; - - @IsDateString() - endsAt: string; - - @IsOptional() - @IsBoolean() - isActive?: boolean; - - @IsOptional() - @IsArray() - @IsUUID('4', { each: true }) - applicablePackageIds?: string[]; -} - -export class UpdatePromotionDto { - @IsOptional() - @IsString() - @Length(2, 100) - name?: string; - - @IsOptional() - @IsString() - description?: string; - - @IsOptional() - @IsNumber() - @Min(0) - value?: number; - - @IsOptional() - @IsNumber() - @Min(0) - minPurchaseAmount?: number; - - @IsOptional() - @IsNumber() - @Min(0) - maxDiscount?: number; - - @IsOptional() - @IsNumber() - @Min(1) - usageLimit?: number; - - @IsOptional() - @IsNumber() - @Min(1) - perUserLimit?: number; - - @IsOptional() - @IsDateString() - startsAt?: string; - - @IsOptional() - @IsDateString() - endsAt?: string; - - @IsOptional() - @IsBoolean() - isActive?: boolean; - - @IsOptional() - @IsArray() - @IsUUID('4', { each: true }) - applicablePackageIds?: string[]; -} - -export class ValidatePromoCodeDto { - @IsString() - code: string; - - @IsOptional() - @IsUUID() - packageId?: string; - - @IsOptional() - @IsNumber() - @Min(0) - purchaseAmount?: number; -} diff --git a/apps/backend/src/modules/admin/dto/provider.dto.ts b/apps/backend/src/modules/admin/dto/provider.dto.ts deleted file mode 100644 index 7d272f7..0000000 --- a/apps/backend/src/modules/admin/dto/provider.dto.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { IsString, IsNumber, IsBoolean, IsOptional, Min } from 'class-validator'; - -export class UpdateProviderDto { - @IsOptional() - @IsString() - name?: string; - - @IsOptional() - @IsString() - description?: string; - - @IsOptional() - @IsNumber() - @Min(0) - costPerFrame?: number; - - @IsOptional() - @IsNumber() - @Min(0) - costPerToken?: number; - - @IsOptional() - @IsBoolean() - isActive?: boolean; - - @IsOptional() - @IsBoolean() - isDefault?: boolean; - - @IsOptional() - config?: Record; -} - -export interface ProviderUsageDto { - providerId: string; - providerName: string; - totalRequests: number; - totalFrames: number; - totalTokens: number; - totalCost: number; - period: string; -} diff --git a/apps/backend/src/modules/admin/entities/audit-log.entity.ts b/apps/backend/src/modules/admin/entities/audit-log.entity.ts deleted file mode 100644 index 0b4c5c0..0000000 --- a/apps/backend/src/modules/admin/entities/audit-log.entity.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { - Entity, - PrimaryGeneratedColumn, - Column, - CreateDateColumn, - ManyToOne, - JoinColumn, - Index, -} from 'typeorm'; -import { User } from '../../users/entities/user.entity'; - -@Entity('audit_logs') -@Index(['userId']) -@Index(['action']) -@Index(['resource', 'resourceId']) -@Index(['createdAt']) -export class AuditLog { - @PrimaryGeneratedColumn('uuid') - id: string; - - @Column({ type: 'uuid' }) - userId: string; - - @ManyToOne(() => User) - @JoinColumn({ name: 'userId' }) - user: User; - - @Column({ type: 'varchar', length: 100 }) - action: string; - - @Column({ type: 'varchar', length: 100 }) - resource: string; - - @Column({ type: 'uuid', nullable: true }) - resourceId: string; - - @Column({ type: 'jsonb', nullable: true }) - previousValue: Record; - - @Column({ type: 'jsonb', nullable: true }) - newValue: Record; - - @Column({ type: 'varchar', length: 45, nullable: true }) - ipAddress: string; - - @Column({ type: 'text', nullable: true }) - userAgent: string; - - @CreateDateColumn() - createdAt: Date; -} diff --git a/apps/backend/src/modules/admin/entities/ia-provider.entity.ts b/apps/backend/src/modules/admin/entities/ia-provider.entity.ts deleted file mode 100644 index ec384a9..0000000 --- a/apps/backend/src/modules/admin/entities/ia-provider.entity.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { - Entity, - PrimaryGeneratedColumn, - Column, - CreateDateColumn, - UpdateDateColumn, - Index, -} from 'typeorm'; - -@Entity('ia_providers') -@Index(['code']) -@Index(['isActive']) -export class IaProvider { - @PrimaryGeneratedColumn('uuid') - id: string; - - @Column({ type: 'varchar', length: 100 }) - name: string; - - @Column({ type: 'varchar', length: 50, unique: true }) - code: string; - - @Column({ type: 'text', nullable: true }) - description: string; - - @Column({ type: 'numeric', precision: 10, scale: 6, default: 0 }) - costPerFrame: number; - - @Column({ type: 'numeric', precision: 10, scale: 8, default: 0 }) - costPerToken: number; - - @Column({ type: 'boolean', default: true }) - isActive: boolean; - - @Column({ type: 'boolean', default: false }) - isDefault: boolean; - - @Column({ type: 'jsonb', nullable: true }) - config: Record; - - @CreateDateColumn() - createdAt: Date; - - @UpdateDateColumn() - updatedAt: Date; -} diff --git a/apps/backend/src/modules/admin/entities/promotion.entity.ts b/apps/backend/src/modules/admin/entities/promotion.entity.ts deleted file mode 100644 index 309b547..0000000 --- a/apps/backend/src/modules/admin/entities/promotion.entity.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { - Entity, - PrimaryGeneratedColumn, - Column, - CreateDateColumn, - UpdateDateColumn, - ManyToOne, - JoinColumn, - Index, -} from 'typeorm'; -import { User } from '../../users/entities/user.entity'; - -export enum PromotionType { - PERCENTAGE = 'PERCENTAGE', - FIXED_CREDITS = 'FIXED_CREDITS', - MULTIPLIER = 'MULTIPLIER', -} - -@Entity('promotions') -@Index(['code']) -@Index(['isActive', 'startsAt', 'endsAt']) -export class Promotion { - @PrimaryGeneratedColumn('uuid') - id: string; - - @Column({ type: 'varchar', length: 100 }) - name: string; - - @Column({ type: 'varchar', length: 50, unique: true }) - code: string; - - @Column({ type: 'text', nullable: true }) - description: string; - - @Column({ type: 'enum', enum: PromotionType }) - type: PromotionType; - - @Column({ type: 'numeric', precision: 10, scale: 2 }) - value: number; - - @Column({ type: 'numeric', precision: 10, scale: 2, nullable: true }) - minPurchaseAmount: number; - - @Column({ type: 'numeric', precision: 10, scale: 2, nullable: true }) - maxDiscount: number; - - @Column({ type: 'int', nullable: true }) - usageLimit: number; - - @Column({ type: 'int', default: 0 }) - usageCount: number; - - @Column({ type: 'int', nullable: true, default: 1 }) - perUserLimit: number; - - @Column({ type: 'timestamp' }) - startsAt: Date; - - @Column({ type: 'timestamp' }) - endsAt: Date; - - @Column({ type: 'boolean', default: true }) - isActive: boolean; - - @Column({ type: 'uuid', array: true, nullable: true }) - applicablePackageIds: string[]; - - @Column({ type: 'uuid', nullable: true }) - createdBy: string; - - @ManyToOne(() => User, { nullable: true }) - @JoinColumn({ name: 'createdBy' }) - creator: User; - - @CreateDateColumn() - createdAt: Date; - - @UpdateDateColumn() - updatedAt: Date; - - isValid(): boolean { - const now = new Date(); - return ( - this.isActive && - this.startsAt <= now && - this.endsAt >= now && - (this.usageLimit === null || this.usageCount < this.usageLimit) - ); - } -} diff --git a/apps/backend/src/modules/admin/services/admin-dashboard.service.ts b/apps/backend/src/modules/admin/services/admin-dashboard.service.ts deleted file mode 100644 index 642ed67..0000000 --- a/apps/backend/src/modules/admin/services/admin-dashboard.service.ts +++ /dev/null @@ -1,206 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository, Between, MoreThanOrEqual } from 'typeorm'; -import { User } from '../../users/entities/user.entity'; -import { Store } from '../../stores/entities/store.entity'; -import { Video } from '../../videos/entities/video.entity'; -import { Payment, PaymentStatus } from '../../payments/entities/payment.entity'; -import { CreditTransaction, TransactionType } from '../../credits/entities/credit-transaction.entity'; -import { DashboardMetrics, RevenueSeriesPoint, DashboardPeriod } from '../dto/dashboard.dto'; - -@Injectable() -export class AdminDashboardService { - constructor( - @InjectRepository(User) - private userRepository: Repository, - @InjectRepository(Store) - private storeRepository: Repository, - @InjectRepository(Video) - private videoRepository: Repository