adserver-dashboard 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.ci/staging.yml +191 -0
- package/.dockerignore +117 -0
- package/.env +40 -0
- package/.env.staging +38 -0
- package/.gitlab-ci.yml +16 -0
- package/DEMO_STATUS.md +579 -0
- package/Dockerfile +61 -0
- package/Influence-MW-AdServer-12-02-2026/client/index.html +17 -0
- package/Influence-MW-AdServer-12-02-2026/client/public/favicon.png +0 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/App.tsx +91 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/advanced-map-drawer.tsx +1131 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ai-recommendation-panel.tsx +379 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/app-sidebar.tsx +183 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/auto-optimize-button.tsx +184 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/availability-drawer.tsx +385 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/brand-insights-panel.tsx +87 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/create-agency-drawer.tsx +198 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/create-brand-drawer.tsx +275 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/creative-assignment.tsx +526 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/data-table-toolbar.tsx +148 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/data-table.tsx +158 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/filter-drawer.tsx +356 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/form-insights-panel.tsx +82 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/geography-selector.tsx +699 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/header-user-menu.tsx +178 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/history-drawer.tsx +313 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/inventory-availability-section.tsx +176 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/inventory-format-drawer.tsx +173 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/inventory-selector.tsx +401 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/manual-inventory-drawer.tsx +368 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/mapbox-map.tsx +368 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/market-insights-panel.tsx +202 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/media-owner-drawer.tsx +217 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/metric-card.tsx +58 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/page-header.tsx +27 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/player-status-indicator.tsx +137 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/poi-targeting-drawer.tsx +298 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/recommendation-score-badge.tsx +102 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/recommended-inventories-panel.tsx +248 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/searchable-combobox.tsx +134 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/signal-visualizations.tsx +407 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/status-badge.tsx +35 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/theme-provider.tsx +73 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/theme-toggle.tsx +37 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/traffic-slider.tsx +75 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/accordion.tsx +56 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/alert-dialog.tsx +139 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/alert.tsx +59 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/aspect-ratio.tsx +5 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/avatar.tsx +51 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/badge.tsx +38 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/breadcrumb.tsx +115 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/button.tsx +62 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/calendar.tsx +68 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/card.tsx +85 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/carousel.tsx +260 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/chart.tsx +365 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/checkbox.tsx +28 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/collapsible.tsx +11 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/command.tsx +151 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/context-menu.tsx +198 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/dialog.tsx +122 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/drawer.tsx +118 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/dropdown-menu.tsx +198 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/form.tsx +178 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/hover-card.tsx +29 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/input-otp.tsx +69 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/input.tsx +23 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/label.tsx +24 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/menubar.tsx +256 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/navigation-menu.tsx +128 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/pagination.tsx +117 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/popover.tsx +29 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/progress.tsx +28 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/radio-group.tsx +42 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/resizable.tsx +45 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/scroll-area.tsx +46 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/select.tsx +160 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/separator.tsx +29 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/sheet.tsx +140 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/sidebar.tsx +727 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/skeleton.tsx +15 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/slider.tsx +26 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/switch.tsx +27 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/table.tsx +117 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/tabs.tsx +53 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/textarea.tsx +22 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/toast.tsx +127 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/toaster.tsx +33 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/toggle-group.tsx +61 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/toggle.tsx +43 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/ui/tooltip.tsx +30 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/vendor-stores-modal.tsx +336 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/venue-type-drawer.tsx +359 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/components/venue-type-selector.tsx +436 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/hooks/use-mobile.tsx +19 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/hooks/use-toast.ts +191 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/index.css +244 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/lib/queryClient.ts +57 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/lib/utils.ts +39 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/lib/venue-taxonomy.ts +532 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/main.tsx +5 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/assign-creative.tsx +781 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/content-hub.tsx +995 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/custom-pois.tsx +431 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/dashboard.tsx +620 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/deal-detail.tsx +1062 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/deal-form.tsx +1570 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/deals.tsx +716 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/edit-creative-assignment.tsx +1051 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/geotargeting.tsx +675 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/integrations.tsx +425 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/line-item-creatives.tsx +622 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/line-item-form.tsx +3132 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/line-items.tsx +530 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/not-found.tsx +21 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/proof-of-play-upload.tsx +479 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/proof-of-play.tsx +880 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/reports.tsx +235 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/settings.tsx +652 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/signal-form.tsx +1117 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/signals.tsx +366 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/tags.tsx +332 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/pages/venues.tsx +381 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/types/mapbox-gl-draw.d.ts +37 -0
- package/Influence-MW-AdServer-12-02-2026/client/src/types/react-simple-maps.d.ts +57 -0
- package/Influence-MW-AdServer-12-02-2026/components.json +20 -0
- package/Influence-MW-AdServer-12-02-2026/docs/PRD.md +3373 -0
- package/Influence-MW-AdServer-12-02-2026/docs/influence-feature-mapping.csv +498 -0
- package/Influence-MW-AdServer-12-02-2026/drizzle.config.ts +14 -0
- package/Influence-MW-AdServer-12-02-2026/package-lock.json +9672 -0
- package/Influence-MW-AdServer-12-02-2026/package.json +118 -0
- package/Influence-MW-AdServer-12-02-2026/postcss.config.js +6 -0
- package/Influence-MW-AdServer-12-02-2026/replit.md +91 -0
- package/Influence-MW-AdServer-12-02-2026/script/build.ts +67 -0
- package/Influence-MW-AdServer-12-02-2026/scripts/create-miro-diagrams.cjs +318 -0
- package/Influence-MW-AdServer-12-02-2026/scripts/create-remaining-diagrams.cjs +270 -0
- package/Influence-MW-AdServer-12-02-2026/server/index.ts +103 -0
- package/Influence-MW-AdServer-12-02-2026/server/recommendation-service.ts +319 -0
- package/Influence-MW-AdServer-12-02-2026/server/routes.ts +1890 -0
- package/Influence-MW-AdServer-12-02-2026/server/static.ts +19 -0
- package/Influence-MW-AdServer-12-02-2026/server/storage.ts +2058 -0
- package/Influence-MW-AdServer-12-02-2026/server/vite.ts +58 -0
- package/Influence-MW-AdServer-12-02-2026/shared/schema.ts +1595 -0
- package/Influence-MW-AdServer-12-02-2026/tailwind.config.ts +107 -0
- package/Influence-MW-AdServer-12-02-2026/tsconfig.json +23 -0
- package/Influence-MW-AdServer-12-02-2026/vite.config.ts +40 -0
- package/LINE_ITEM_BUDGET_FIELD_MAPPING.md +178 -0
- package/PCM/.env.example +92 -0
- package/PCM/README.md +558 -0
- package/PCM/docs/TEST_CASES.md +422 -0
- package/PCM/index.js +106 -0
- package/PCM/package-lock.json +3282 -0
- package/PCM/package.json +32 -0
- package/PCM/replit.md +64 -0
- package/PCM/schema.sql +495 -0
- package/PCM/scripts/export-schema.js +183 -0
- package/PCM/scripts/seed-comprehensive.js +631 -0
- package/PCM/scripts/seed-production.js +477 -0
- package/PCM/src/config/db.js +56 -0
- package/PCM/src/config/swagger.js +5975 -0
- package/PCM/src/dto/EmailRequestDTO.js +166 -0
- package/PCM/src/middleware/errorHandler.js +52 -0
- package/PCM/src/middleware/logger.js +26 -0
- package/PCM/src/migrations/001_add_campaign_mode_fields.sql +36 -0
- package/PCM/src/migrations/002_create_deal_id_counters.sql +22 -0
- package/PCM/src/migrations/003_update_publishers_column.sql +15 -0
- package/PCM/src/migrations/004_add_direct_dealtype_and_advertiser.sql +5 -0
- package/PCM/src/migrations/005_add_programmatic_fields_and_update_enums.sql +31 -0
- package/PCM/src/migrations/006_add_line_item_programmatic_fields.sql +12 -0
- package/PCM/src/migrations/007_add_line_item_direct_fields.sql +15 -0
- package/PCM/src/migrations/008_add_inventory_fields.sql +45 -0
- package/PCM/src/migrations/009_move_inventory_fields_to_metadata.sql +32 -0
- package/PCM/src/migrations/010_add_draft_status_and_line_items_count.sql +23 -0
- package/PCM/src/migrations/011_add_planning_field.sql +21 -0
- package/PCM/src/migrations/012_fix_inventory_composite_pk.sql +17 -0
- package/PCM/src/migrations/013_make_external_id_optional.sql +3 -0
- package/PCM/src/migrations/014_create_change_history.sql +38 -0
- package/PCM/src/migrations/016_create_publisher_insertion_orders.sql +33 -0
- package/PCM/src/migrations/017_fix_line_item_id_fk_reference.sql +86 -0
- package/PCM/src/migrations/018_create_approval_tables.sql +44 -0
- package/PCM/src/migrations/019_add_encrypted_token_column.sql +2 -0
- package/PCM/src/migrations/020_add_rejection_reason_to_deals.sql +10 -0
- package/PCM/src/migrations/021_add_publisher_external_id_to_inventories.sql +12 -0
- package/PCM/src/migrations/022_add_line_item_extended_fields.sql +24 -0
- package/PCM/src/migrations/023_add_base_price_fields.sql +8 -0
- package/PCM/src/migrations/run-migrations.js +46 -0
- package/PCM/src/models/ApprovalOTP.js +51 -0
- package/PCM/src/models/ApprovalToken.js +79 -0
- package/PCM/src/models/ChangeHistory.js +107 -0
- package/PCM/src/models/Deal.js +186 -0
- package/PCM/src/models/DealIdCounter.js +28 -0
- package/PCM/src/models/LineItem.js +227 -0
- package/PCM/src/models/LineItemCreative.js +89 -0
- package/PCM/src/models/LineItemInventory.js +115 -0
- package/PCM/src/models/PublisherInsertionOrder.js +93 -0
- package/PCM/src/models/TransactionHistory.js +34 -0
- package/PCM/src/models/associations.js +81 -0
- package/PCM/src/routes/approval.js +321 -0
- package/PCM/src/routes/creatives.js +437 -0
- package/PCM/src/routes/deals.js +1638 -0
- package/PCM/src/routes/digitalSignage.js +242 -0
- package/PCM/src/routes/insertionOrders.js +380 -0
- package/PCM/src/routes/lineItems.js +926 -0
- package/PCM/src/routes/system.js +384 -0
- package/PCM/src/services/ApprovalService.js +885 -0
- package/PCM/src/services/CampaignImportConverter.js +631 -0
- package/PCM/src/services/CampaignModeService.js +273 -0
- package/PCM/src/services/CampaignStatusService.js +395 -0
- package/PCM/src/services/ChangeHistoryService.js +316 -0
- package/PCM/src/services/DealIdService.js +94 -0
- package/PCM/src/services/DealResponseFormatter.js +90 -0
- package/PCM/src/services/EmailNotificationService.js +315 -0
- package/PCM/src/services/LineItemResponseFormatter.js +122 -0
- package/PCM/src/services/LineItemStatusService.js +380 -0
- package/PCM/src/tests/comprehensiveTestRunner.js +360 -0
- package/PCM/src/tests/comprehensiveTests.js +1277 -0
- package/PCM/src/tests/dealTypeUnitTests.js +1058 -0
- package/PCM/src/tests/testRunner.js +248 -0
- package/PCM/src/utils/caseConverter.js +92 -0
- package/PCM/src/utils/dealCalculations.js +206 -0
- package/PCM/src/utils/lineItemPayloadNormalizer.js +41 -0
- package/PCM/src/utils/payloadNormalizer.js +34 -0
- package/PCM/src/utils/sourceNormalizer.js +56 -0
- package/PCM/src/validators/creativeValidator.js +27 -0
- package/PCM/src/validators/dealValidator.js +203 -0
- package/PCM/src/validators/lineItemValidator.js +489 -0
- package/PCM/tests/approval-flows.test.js +238 -0
- package/PCM/tests/approval-workflow.test.js +291 -0
- package/PCM/tests/campaign-import-converter.test.js +543 -0
- package/PCM/tests/campaign-import-e2e.test.js +520 -0
- package/PCM/tests/campaign-status.test.js +539 -0
- package/PCM/tests/direct-publisher-split-reimport.test.js +460 -0
- package/PCM/tests/e2e/digital-signage.test.js +145 -0
- package/PCM/tests/e2e/search-filter-pagination.test.js +399 -0
- package/PCM/tests/e2e-comprehensive.test.js +3446 -0
- package/PCM/tests/edge-cases.test.js +340 -0
- package/PCM/tests/line-item-status.test.js +340 -0
- package/PCM/tests/seller-account-external-ids.test.js +877 -0
- package/PCM/tests/source-validation.test.js +324 -0
- package/PRD.md +3373 -0
- package/README.md +186 -0
- package/client/index.html +35 -0
- package/client/public/DEMO_STATUS.md +579 -0
- package/client/public/img/MW-logo-trans_1754045676555.png +0 -0
- package/client/public/locales/ar/approval.json +144 -0
- package/client/public/locales/ar/buyer.json +61 -0
- package/client/public/locales/ar/campaigns.json +1 -0
- package/client/public/locales/ar/common.json +218 -0
- package/client/public/locales/ar/contentHub.json +266 -0
- package/client/public/locales/ar/creatives.json +79 -0
- package/client/public/locales/ar/dashboard.json +57 -0
- package/client/public/locales/ar/deals.json +886 -0
- package/client/public/locales/ar/dsp.json +131 -0
- package/client/public/locales/ar/inventory.json +201 -0
- package/client/public/locales/ar/lineItems.json +553 -0
- package/client/public/locales/ar/navigation.json +48 -0
- package/client/public/locales/ar/wizard.json +1 -0
- package/client/public/locales/en/approval.json +144 -0
- package/client/public/locales/en/buyer.json +65 -0
- package/client/public/locales/en/campaigns.json +1 -0
- package/client/public/locales/en/common.json +218 -0
- package/client/public/locales/en/contentHub.json +266 -0
- package/client/public/locales/en/creatives.json +79 -0
- package/client/public/locales/en/dashboard.json +57 -0
- package/client/public/locales/en/deals.json +886 -0
- package/client/public/locales/en/dsp.json +131 -0
- package/client/public/locales/en/inventory.json +201 -0
- package/client/public/locales/en/lineItems.json +659 -0
- package/client/public/locales/en/navigation.json +48 -0
- package/client/public/locales/en/wizard.json +1 -0
- package/client/public/locales/ja/approval.json +144 -0
- package/client/public/locales/ja/buyer.json +61 -0
- package/client/public/locales/ja/campaigns.json +1 -0
- package/client/public/locales/ja/common.json +218 -0
- package/client/public/locales/ja/contentHub.json +266 -0
- package/client/public/locales/ja/creatives.json +79 -0
- package/client/public/locales/ja/dashboard.json +57 -0
- package/client/public/locales/ja/deals.json +886 -0
- package/client/public/locales/ja/dsp.json +131 -0
- package/client/public/locales/ja/inventory.json +201 -0
- package/client/public/locales/ja/lineItems.json +553 -0
- package/client/public/locales/ja/navigation.json +48 -0
- package/client/public/locales/ja/wizard.json +1 -0
- package/client/public/locales/zh/approval.json +144 -0
- package/client/public/locales/zh/buyer.json +61 -0
- package/client/public/locales/zh/campaigns.json +1 -0
- package/client/public/locales/zh/common.json +218 -0
- package/client/public/locales/zh/contentHub.json +266 -0
- package/client/public/locales/zh/creatives.json +79 -0
- package/client/public/locales/zh/dashboard.json +57 -0
- package/client/public/locales/zh/deals.json +886 -0
- package/client/public/locales/zh/dsp.json +131 -0
- package/client/public/locales/zh/inventory.json +201 -0
- package/client/public/locales/zh/lineItems.json +553 -0
- package/client/public/locales/zh/navigation.json +48 -0
- package/client/public/locales/zh/wizard.json +1 -0
- package/client/public/manifest.json +36 -0
- package/client/src/App.tsx +464 -0
- package/client/src/components/app-sidebar.tsx +312 -0
- package/client/src/components/approval/approval-decision-form.test.tsx +294 -0
- package/client/src/components/approval/approval-decision-form.tsx +326 -0
- package/client/src/components/approval/approval-sheet.tsx +631 -0
- package/client/src/components/approval/line-item-details-sheet.tsx +371 -0
- package/client/src/components/approval/otp-verification.test.tsx +337 -0
- package/client/src/components/approval/otp-verification.tsx +180 -0
- package/client/src/components/content-hub/bulk-transcode-dialog.tsx +379 -0
- package/client/src/components/content-hub/content-hub-manager-v2.tsx +574 -0
- package/client/src/components/content-hub/content-hub-manager.tsx +330 -0
- package/client/src/components/content-hub/creative-card.tsx +456 -0
- package/client/src/components/content-hub/creative-detail-sheet.tsx +685 -0
- package/client/src/components/content-hub/creative-filters.tsx +457 -0
- package/client/src/components/content-hub/creative-grid.tsx +329 -0
- package/client/src/components/content-hub/creative-selector.tsx +415 -0
- package/client/src/components/content-hub/creative-upload.tsx +547 -0
- package/client/src/components/content-hub/folder-dialogs.tsx +445 -0
- package/client/src/components/content-hub/folder-list.tsx +280 -0
- package/client/src/components/content-hub/review-dialogs.tsx +268 -0
- package/client/src/components/content-hub/transcode-dialog.tsx +226 -0
- package/client/src/components/creative-library/creative-details-view.tsx +446 -0
- package/client/src/components/creative-library/creative-filters-panel.tsx +203 -0
- package/client/src/components/creative-library/creative-list.tsx +360 -0
- package/client/src/components/creative-library/creative-status-badge.tsx +71 -0
- package/client/src/components/creative-library/folder-card.tsx +78 -0
- package/client/src/components/creative-library/index.ts +27 -0
- package/client/src/components/creative-library/new-creative-card.tsx +211 -0
- package/client/src/components/creative-library/upload-creative-dialog.tsx +261 -0
- package/client/src/components/dashboard-overview.tsx +109 -0
- package/client/src/components/deals/approval-history-panel.test.tsx +240 -0
- package/client/src/components/deals/approval-history-panel.tsx +156 -0
- package/client/src/components/deals/deal-status-badge.tsx +92 -0
- package/client/src/components/deals/import-from-planner-dialog.tsx +399 -0
- package/client/src/components/deals/market-insights-panel.tsx +237 -0
- package/client/src/components/deals/reopen-deal-sheet.tsx +191 -0
- package/client/src/components/deals/request-approval-sheet.test.tsx +323 -0
- package/client/src/components/deals/request-approval-sheet.tsx +136 -0
- package/client/src/components/deals/resend-approval-sheet.tsx +201 -0
- package/client/src/components/direct-campaigns/campaign-card.tsx +283 -0
- package/client/src/components/direct-campaigns/deal-filter-panel.tsx +325 -0
- package/client/src/components/inventory/advanced-filters-panel.tsx +273 -0
- package/client/src/components/inventory/csv-upload-modal.tsx +639 -0
- package/client/src/components/inventory/inventory-availability-view.tsx +486 -0
- package/client/src/components/inventory/inventory-details-sheet.tsx +376 -0
- package/client/src/components/inventory/inventory-map-view.tsx +596 -0
- package/client/src/components/inventory/inventory-settings-menu.tsx +52 -0
- package/client/src/components/language-switcher.tsx +53 -0
- package/client/src/components/line-items/campaign-forecast-panel.tsx +138 -0
- package/client/src/components/line-items/form-insights.tsx +89 -0
- package/client/src/components/line-items/geofencing/LocationCsvUploadDrawer.tsx +100 -0
- package/client/src/components/line-items/geofencing/POIDropdown.tsx +379 -0
- package/client/src/components/line-items/geofencing/SelectedLocationsSidebar.tsx +436 -0
- package/client/src/components/line-items/geofencing/ViewFileLocationDrawer.tsx +199 -0
- package/client/src/components/line-items/geofencing/components/ExistingFilesTab.tsx +268 -0
- package/client/src/components/line-items/geofencing/components/TemplateDownloadSection.tsx +59 -0
- package/client/src/components/line-items/geofencing/components/UploadTab.tsx +215 -0
- package/client/src/components/line-items/geofencing-map.tsx +1270 -0
- package/client/src/components/line-items/inventory-availability-section.tsx +178 -0
- package/client/src/components/line-items/line-item-schedule-manager.tsx +313 -0
- package/client/src/components/line-items/manual-inventory-drawer.tsx +346 -0
- package/client/src/components/line-items/planner-inventory-card.tsx +495 -0
- package/client/src/components/line-items/planner-schedule-grid.tsx +495 -0
- package/client/src/components/line-items/schedule-rule-editor.tsx +649 -0
- package/client/src/components/line-items/schedule-rule-types.ts +122 -0
- package/client/src/components/line-items/steps/creatives-step.tsx +681 -0
- package/client/src/components/line-items/steps/inventory-schedule-step.tsx +1596 -0
- package/client/src/components/line-items/steps/inventory-step.tsx +1533 -0
- package/client/src/components/line-items/steps/line-item-details-step.tsx +916 -0
- package/client/src/components/line-items/steps/schedule-step.tsx +273 -0
- package/client/src/components/line-items/steps/summary-step.tsx +680 -0
- package/client/src/components/line-items/steps/targeting-step.tsx +1708 -0
- package/client/src/components/product-switcher.tsx +105 -0
- package/client/src/components/protected-route.tsx +49 -0
- package/client/src/components/skip-link.tsx +22 -0
- package/client/src/components/stat-card.tsx +53 -0
- package/client/src/components/status-badge.tsx +96 -0
- package/client/src/components/ui/hierarchical-venue-selector.tsx +389 -0
- package/client/src/components/ui/toaster.tsx +111 -0
- package/client/src/contexts/auth-context.tsx +181 -0
- package/client/src/contexts/sidebar-state.tsx +50 -0
- package/client/src/contexts/theme-context.tsx +66 -0
- package/client/src/data/campaign-data.json +107 -0
- package/client/src/data/countries.json +22 -0
- package/client/src/hooks/use-approval.ts +366 -0
- package/client/src/hooks/use-keyboard-shortcuts.ts +74 -0
- package/client/src/hooks/use-media-query.ts +46 -0
- package/client/src/hooks/use-mobile.tsx +19 -0
- package/client/src/hooks/use-page-title.ts +21 -0
- package/client/src/hooks/use-toast.ts +195 -0
- package/client/src/index.css +694 -0
- package/client/src/lib/__tests__/accessibility.test.ts +104 -0
- package/client/src/lib/__tests__/date-utils.test.ts +199 -0
- package/client/src/lib/__tests__/dsp-buyer-api.test.ts +127 -0
- package/client/src/lib/__tests__/dsp-buyer-integration.test.ts +247 -0
- package/client/src/lib/__tests__/storage-utils.test.ts +167 -0
- package/client/src/lib/__tests__/utils.test.ts +57 -0
- package/client/src/lib/accessibility.ts +141 -0
- package/client/src/lib/api-config.ts +9 -0
- package/client/src/lib/auth-service.ts +209 -0
- package/client/src/lib/campaign-creative-api.ts +82 -0
- package/client/src/lib/company-api.ts +61 -0
- package/client/src/lib/content-hub-api.ts +407 -0
- package/client/src/lib/creative-mapper.ts +61 -0
- package/client/src/lib/date-utils.ts +119 -0
- package/client/src/lib/deal-helpers.ts +220 -0
- package/client/src/lib/dsp-buyer-api.ts +196 -0
- package/client/src/lib/geo-import-api.ts +151 -0
- package/client/src/lib/google-poi-api.ts +305 -0
- package/client/src/lib/i18n/__tests__/formatting.test.ts +202 -0
- package/client/src/lib/i18n/formatting.ts +130 -0
- package/client/src/lib/i18n/index.ts +8 -0
- package/client/src/lib/i18n-compat.ts +76 -0
- package/client/src/lib/influence-deals-api.ts +896 -0
- package/client/src/lib/inventory-api.ts +399 -0
- package/client/src/lib/oauth-service.ts +678 -0
- package/client/src/lib/poi-types.ts +75 -0
- package/client/src/lib/queryClient.ts +144 -0
- package/client/src/lib/recommendation-api.ts +380 -0
- package/client/src/lib/storage-utils.ts +104 -0
- package/client/src/lib/tolgee.ts +85 -0
- package/client/src/lib/utils.ts +0 -0
- package/client/src/main.tsx +67 -0
- package/client/src/mapbox-draw-modes.d.ts +32 -0
- package/client/src/pages/all-folders.tsx +203 -0
- package/client/src/pages/auth-callback.tsx +115 -0
- package/client/src/pages/buyer-form.tsx +339 -0
- package/client/src/pages/buyer-list.tsx +622 -0
- package/client/src/pages/content-hub.tsx +1358 -0
- package/client/src/pages/create-deal.tsx +2093 -0
- package/client/src/pages/creative-assignment-page.tsx +548 -0
- package/client/src/pages/creatives.tsx +5 -0
- package/client/src/pages/custom-pois.tsx +425 -0
- package/client/src/pages/dashboard.tsx +615 -0
- package/client/src/pages/deal-history.tsx +434 -0
- package/client/src/pages/deal-line-items.tsx +1703 -0
- package/client/src/pages/demo-status.tsx +113 -0
- package/client/src/pages/direct-campaign-details.tsx +361 -0
- package/client/src/pages/direct-campaigns-new.tsx +824 -0
- package/client/src/pages/dsp-form.tsx +803 -0
- package/client/src/pages/dsp-list.tsx +239 -0
- package/client/src/pages/folder-content.tsx +336 -0
- package/client/src/pages/integrations.tsx +429 -0
- package/client/src/pages/line-item-creatives.tsx +789 -0
- package/client/src/pages/line-item-detail-page.tsx +684 -0
- package/client/src/pages/line-item-form-page.tsx +3261 -0
- package/client/src/pages/line-item-wizard.tsx +1207 -0
- package/client/src/pages/login.tsx +154 -0
- package/client/src/pages/not-found.tsx +23 -0
- package/client/src/pages/proof-of-play.tsx +397 -0
- package/client/src/pages/public-approval.tsx +551 -0
- package/client/src/pages/reports.tsx +231 -0
- package/client/src/pages/settings.tsx +760 -0
- package/client/src/pages/signals.tsx +389 -0
- package/client/src/pages/tags.tsx +318 -0
- package/client/src/pages/test-results.tsx +328 -0
- package/client/src/store/hooks.ts +5 -0
- package/client/src/store/index.ts +15 -0
- package/client/src/store/mapMarkerLocationsSlice.ts +241 -0
- package/client/src/styles/design-tokens.css +324 -0
- package/client/src/test/setup.ts +261 -0
- package/client/src/test/test-utils.tsx +40 -0
- package/client/src/types/approval.ts +221 -0
- package/client/src/types/content-hub.ts +209 -0
- package/client/src/types/geofencing.ts +67 -0
- package/client/src/types/transcoding.ts +140 -0
- package/client/src/vite-env.d.ts +18 -0
- package/components.json +20 -0
- package/creative-api.json +1 -0
- package/docs/AI_REFERENCE.md +459 -0
- package/docs/MWDesign-Prompt.md +132 -0
- package/docs/MWDesign-System.md +344 -0
- package/docs/test-plan.md +277 -0
- package/e2e/AUTONOMOUS-TESTING.md +406 -0
- package/e2e/README.md +219 -0
- package/e2e/autonomous-flow.spec.ts +308 -0
- package/e2e/debug-sso.spec.ts +163 -0
- package/e2e/direct-campaigns.spec.ts +219 -0
- package/e2e/explore-sso.spec.ts +149 -0
- package/e2e/fixtures/auth.ts +26 -0
- package/e2e/fixtures/enhanced-test.ts +331 -0
- package/e2e/pagination.spec.ts +280 -0
- package/e2e/view-toggle.spec.ts +312 -0
- package/generated-icon.png +0 -0
- package/i18next-scanner.config.cjs +46 -0
- package/package.json +141 -0
- package/playwright.config.ts +93 -0
- package/postcss.config.js +6 -0
- package/replit.md +196 -0
- package/screenshot-after-login.png +0 -0
- package/screenshot-contenthub-grid.png +0 -0
- package/screenshot-contenthub-list-fixed.png +0 -0
- package/screenshot-contenthub-list.png +0 -0
- package/screenshot-create-deal.png +0 -0
- package/screenshot-dashboard.png +0 -0
- package/screenshot-deals.png +0 -0
- package/screenshot-login-filled.png +0 -0
- package/screenshot-login.png +0 -0
- package/screenshot.mjs +24 -0
- package/scripts/deploy-stg.sh +185 -0
- package/shared/direct-io-schema.ts +383 -0
- package/shared/schema.ts +439 -0
- package/shared/screen-types.ts +149 -0
- package/springdocDefault.json +1 -0
- package/swagger-ui-bundle.js +2 -0
- package/swagger-ui-init.js +10316 -0
- package/tailwind.config.ts +282 -0
- package/terraform/README.md +306 -0
- package/terraform/cloudfront.tf +289 -0
- package/terraform/ecs.tf +727 -0
- package/terraform/environments/dev.tfvars +59 -0
- package/terraform/environments/production.tfvars +60 -0
- package/terraform/main.tf +47 -0
- package/terraform/outputs.tf +145 -0
- package/terraform/s3.tf +192 -0
- package/terraform/variables.tf +226 -0
- package/terraform/waf.tf +165 -0
- package/terraform-frontend/.terraform.lock.hcl +25 -0
- package/terraform-frontend/README.md +85 -0
- package/terraform-frontend/cloudfront.tf +125 -0
- package/terraform-frontend/main.tf +31 -0
- package/terraform-frontend/outputs.tf +24 -0
- package/terraform-frontend/terraform.tfvars +12 -0
- package/terraform-frontend/variables.tf +53 -0
- package/tsconfig.json +23 -0
- package/vite.config.ts +226 -0
- package/vitest.config.ts +56 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
-- Migration: Fix line_item_id FK references to use line_items.id (UUID) instead of external_id
|
|
2
|
+
-- This migration converts the line_item_id column in line_item_inventories and line_item_creatives
|
|
3
|
+
-- from TEXT (referencing external_id) to UUID (referencing id)
|
|
4
|
+
|
|
5
|
+
-- Check if migration is already applied by checking if line_item_id is already UUID type
|
|
6
|
+
DO $$
|
|
7
|
+
DECLARE
|
|
8
|
+
inv_col_type TEXT;
|
|
9
|
+
creative_col_type TEXT;
|
|
10
|
+
BEGIN
|
|
11
|
+
-- Check line_item_inventories column type
|
|
12
|
+
SELECT data_type INTO inv_col_type
|
|
13
|
+
FROM information_schema.columns
|
|
14
|
+
WHERE table_name = 'line_item_inventories' AND column_name = 'line_item_id';
|
|
15
|
+
|
|
16
|
+
-- Check line_item_creatives column type
|
|
17
|
+
SELECT data_type INTO creative_col_type
|
|
18
|
+
FROM information_schema.columns
|
|
19
|
+
WHERE table_name = 'line_item_creatives' AND column_name = 'line_item_id';
|
|
20
|
+
|
|
21
|
+
-- Migrate line_item_inventories if needed
|
|
22
|
+
IF inv_col_type = 'text' THEN
|
|
23
|
+
-- Add temporary UUID column
|
|
24
|
+
ALTER TABLE line_item_inventories ADD COLUMN IF NOT EXISTS line_item_uuid UUID;
|
|
25
|
+
|
|
26
|
+
-- Populate with UUIDs by joining with line_items
|
|
27
|
+
UPDATE line_item_inventories inv
|
|
28
|
+
SET line_item_uuid = li.id
|
|
29
|
+
FROM line_items li
|
|
30
|
+
WHERE inv.line_item_id = li.external_id AND inv.line_item_uuid IS NULL;
|
|
31
|
+
|
|
32
|
+
-- Drop old FK constraint if exists
|
|
33
|
+
ALTER TABLE line_item_inventories
|
|
34
|
+
DROP CONSTRAINT IF EXISTS line_item_inventories_line_item_id_fkey;
|
|
35
|
+
|
|
36
|
+
-- Drop old PK constraint
|
|
37
|
+
ALTER TABLE line_item_inventories
|
|
38
|
+
DROP CONSTRAINT IF EXISTS line_item_inventories_pkey;
|
|
39
|
+
|
|
40
|
+
-- Drop old column and rename new one
|
|
41
|
+
ALTER TABLE line_item_inventories DROP COLUMN line_item_id;
|
|
42
|
+
ALTER TABLE line_item_inventories RENAME COLUMN line_item_uuid TO line_item_id;
|
|
43
|
+
|
|
44
|
+
-- Recreate PK constraint
|
|
45
|
+
ALTER TABLE line_item_inventories
|
|
46
|
+
ADD CONSTRAINT line_item_inventories_pkey PRIMARY KEY (id, line_item_id);
|
|
47
|
+
|
|
48
|
+
-- Add new FK constraint referencing line_items.id
|
|
49
|
+
ALTER TABLE line_item_inventories
|
|
50
|
+
ADD CONSTRAINT line_item_inventories_line_item_id_fkey
|
|
51
|
+
FOREIGN KEY (line_item_id) REFERENCES line_items(id) ON DELETE CASCADE;
|
|
52
|
+
|
|
53
|
+
RAISE NOTICE 'Migrated line_item_inventories.line_item_id to UUID';
|
|
54
|
+
ELSE
|
|
55
|
+
RAISE NOTICE 'line_item_inventories.line_item_id already migrated (type: %)', inv_col_type;
|
|
56
|
+
END IF;
|
|
57
|
+
|
|
58
|
+
-- Migrate line_item_creatives if needed
|
|
59
|
+
IF creative_col_type = 'text' THEN
|
|
60
|
+
-- Add temporary UUID column
|
|
61
|
+
ALTER TABLE line_item_creatives ADD COLUMN IF NOT EXISTS line_item_uuid UUID;
|
|
62
|
+
|
|
63
|
+
-- Populate with UUIDs by joining with line_items
|
|
64
|
+
UPDATE line_item_creatives c
|
|
65
|
+
SET line_item_uuid = li.id
|
|
66
|
+
FROM line_items li
|
|
67
|
+
WHERE c.line_item_id = li.external_id AND c.line_item_uuid IS NULL;
|
|
68
|
+
|
|
69
|
+
-- Drop old FK constraint if exists
|
|
70
|
+
ALTER TABLE line_item_creatives
|
|
71
|
+
DROP CONSTRAINT IF EXISTS line_item_creatives_line_item_id_fkey;
|
|
72
|
+
|
|
73
|
+
-- Drop old column and rename new one
|
|
74
|
+
ALTER TABLE line_item_creatives DROP COLUMN line_item_id;
|
|
75
|
+
ALTER TABLE line_item_creatives RENAME COLUMN line_item_uuid TO line_item_id;
|
|
76
|
+
|
|
77
|
+
-- Add new FK constraint referencing line_items.id
|
|
78
|
+
ALTER TABLE line_item_creatives
|
|
79
|
+
ADD CONSTRAINT line_item_creatives_line_item_id_fkey
|
|
80
|
+
FOREIGN KEY (line_item_id) REFERENCES line_items(id) ON DELETE CASCADE;
|
|
81
|
+
|
|
82
|
+
RAISE NOTICE 'Migrated line_item_creatives.line_item_id to UUID';
|
|
83
|
+
ELSE
|
|
84
|
+
RAISE NOTICE 'line_item_creatives.line_item_id already migrated (type: %)', creative_col_type;
|
|
85
|
+
END IF;
|
|
86
|
+
END $$;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
-- Create approval_tokens table for campaign approval workflow
|
|
2
|
+
CREATE TABLE IF NOT EXISTS approval_tokens (
|
|
3
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
4
|
+
deal_id TEXT NOT NULL REFERENCES deals(deal_id) ON DELETE CASCADE,
|
|
5
|
+
approver_email TEXT NOT NULL,
|
|
6
|
+
token TEXT NOT NULL UNIQUE,
|
|
7
|
+
status VARCHAR(20) NOT NULL DEFAULT 'PENDING' CHECK (status IN ('PENDING', 'APPROVED', 'REJECTED')),
|
|
8
|
+
rejection_reason TEXT,
|
|
9
|
+
decision_at TIMESTAMP WITH TIME ZONE,
|
|
10
|
+
expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
11
|
+
otp_verified BOOLEAN NOT NULL DEFAULT FALSE,
|
|
12
|
+
request_id TEXT,
|
|
13
|
+
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
14
|
+
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
CREATE INDEX IF NOT EXISTS idx_approval_tokens_deal_id ON approval_tokens(deal_id);
|
|
18
|
+
CREATE INDEX IF NOT EXISTS idx_approval_tokens_token ON approval_tokens(token);
|
|
19
|
+
CREATE INDEX IF NOT EXISTS idx_approval_tokens_approver_email ON approval_tokens(approver_email);
|
|
20
|
+
CREATE INDEX IF NOT EXISTS idx_approval_tokens_status ON approval_tokens(status);
|
|
21
|
+
|
|
22
|
+
-- Create approval_otps table for OTP verification
|
|
23
|
+
CREATE TABLE IF NOT EXISTS approval_otps (
|
|
24
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
25
|
+
approval_token_id UUID NOT NULL REFERENCES approval_tokens(id) ON DELETE CASCADE,
|
|
26
|
+
otp_code TEXT NOT NULL,
|
|
27
|
+
expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
28
|
+
verified BOOLEAN NOT NULL DEFAULT FALSE,
|
|
29
|
+
attempts INTEGER NOT NULL DEFAULT 0,
|
|
30
|
+
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
31
|
+
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
CREATE INDEX IF NOT EXISTS idx_approval_otps_approval_token_id ON approval_otps(approval_token_id);
|
|
35
|
+
CREATE INDEX IF NOT EXISTS idx_approval_otps_otp_code ON approval_otps(otp_code);
|
|
36
|
+
|
|
37
|
+
-- Add approval_emails column to deals table if not exists
|
|
38
|
+
DO $$
|
|
39
|
+
BEGIN
|
|
40
|
+
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
41
|
+
WHERE table_name = 'deals' AND column_name = 'approval_emails') THEN
|
|
42
|
+
ALTER TABLE deals ADD COLUMN approval_emails JSONB DEFAULT '[]'::jsonb;
|
|
43
|
+
END IF;
|
|
44
|
+
END $$;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
-- Add rejection_reason column to deals table for storing the reason when a campaign is rejected
|
|
2
|
+
DO $$
|
|
3
|
+
BEGIN
|
|
4
|
+
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
5
|
+
WHERE table_name = 'deals' AND column_name = 'rejection_reason') THEN
|
|
6
|
+
ALTER TABLE deals ADD COLUMN rejection_reason TEXT;
|
|
7
|
+
END IF;
|
|
8
|
+
END $$;
|
|
9
|
+
|
|
10
|
+
CREATE INDEX IF NOT EXISTS idx_deals_rejection_reason ON deals(rejection_reason) WHERE rejection_reason IS NOT NULL;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
-- Migration 021: Add publisher_external_id column to line_item_inventories table
|
|
2
|
+
|
|
3
|
+
DO $$
|
|
4
|
+
BEGIN
|
|
5
|
+
IF NOT EXISTS (SELECT 1 FROM information_schema.columns
|
|
6
|
+
WHERE table_name = 'line_item_inventories' AND column_name = 'publisher_external_id') THEN
|
|
7
|
+
ALTER TABLE line_item_inventories ADD COLUMN publisher_external_id TEXT;
|
|
8
|
+
END IF;
|
|
9
|
+
END $$;
|
|
10
|
+
|
|
11
|
+
CREATE INDEX IF NOT EXISTS idx_line_item_inventories_publisher_external_id
|
|
12
|
+
ON line_item_inventories(publisher_external_id) WHERE publisher_external_id IS NOT NULL;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
-- Migration: Add extended fields to line_items table
|
|
2
|
+
-- Fields: priority, custom_fees, frequency_cap, traffic_allocation, inventory_source
|
|
3
|
+
|
|
4
|
+
-- Add priority field (integer 1-10)
|
|
5
|
+
ALTER TABLE line_items ADD COLUMN IF NOT EXISTS priority INTEGER;
|
|
6
|
+
|
|
7
|
+
-- Add custom_fees field (JSONB array of fee objects)
|
|
8
|
+
ALTER TABLE line_items ADD COLUMN IF NOT EXISTS custom_fees JSONB;
|
|
9
|
+
|
|
10
|
+
-- Add frequency_cap field (JSONB object with period and target)
|
|
11
|
+
ALTER TABLE line_items ADD COLUMN IF NOT EXISTS frequency_cap JSONB;
|
|
12
|
+
|
|
13
|
+
-- Add traffic_allocation field (percentage 0-100)
|
|
14
|
+
ALTER TABLE line_items ADD COLUMN IF NOT EXISTS traffic_allocation DECIMAL(5,2);
|
|
15
|
+
|
|
16
|
+
-- Add inventory_source field (string)
|
|
17
|
+
ALTER TABLE line_items ADD COLUMN IF NOT EXISTS inventory_source TEXT;
|
|
18
|
+
|
|
19
|
+
-- Add check constraints for validation
|
|
20
|
+
ALTER TABLE line_items DROP CONSTRAINT IF EXISTS check_priority_range;
|
|
21
|
+
ALTER TABLE line_items ADD CONSTRAINT check_priority_range CHECK (priority IS NULL OR (priority >= 1 AND priority <= 10));
|
|
22
|
+
|
|
23
|
+
ALTER TABLE line_items DROP CONSTRAINT IF EXISTS check_traffic_allocation_range;
|
|
24
|
+
ALTER TABLE line_items ADD CONSTRAINT check_traffic_allocation_range CHECK (traffic_allocation IS NULL OR (traffic_allocation >= 0 AND traffic_allocation <= 100));
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
-- Migration: Add base price fields to line_items table
|
|
2
|
+
-- Fields: bid_floor_base (PROGRAMMATIC), pricing (DIRECT with estimatedCostBase, cpmBase)
|
|
3
|
+
|
|
4
|
+
-- Add bid_floor_base field for PROGRAMMATIC mode (base price before custom fees)
|
|
5
|
+
ALTER TABLE line_items ADD COLUMN IF NOT EXISTS bid_floor_base DECIMAL(12, 2);
|
|
6
|
+
|
|
7
|
+
-- Add pricing JSONB field for DIRECT mode (contains estimatedCostBase, cpmBase)
|
|
8
|
+
ALTER TABLE line_items ADD COLUMN IF NOT EXISTS pricing JSONB;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import sequelize from '../config/db.js';
|
|
5
|
+
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = path.dirname(__filename);
|
|
8
|
+
|
|
9
|
+
async function runMigrations() {
|
|
10
|
+
try {
|
|
11
|
+
await sequelize.authenticate();
|
|
12
|
+
console.log('Database connection established for migrations.');
|
|
13
|
+
|
|
14
|
+
const migrationsDir = __dirname;
|
|
15
|
+
const sqlFiles = fs.readdirSync(migrationsDir)
|
|
16
|
+
.filter(f => f.endsWith('.sql'))
|
|
17
|
+
.sort();
|
|
18
|
+
|
|
19
|
+
let hasErrors = false;
|
|
20
|
+
for (const file of sqlFiles) {
|
|
21
|
+
console.log(`Running migration: ${file}`);
|
|
22
|
+
const sql = fs.readFileSync(path.join(migrationsDir, file), 'utf8');
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
await sequelize.query(sql);
|
|
26
|
+
console.log(` ✓ Migration ${file} completed successfully`);
|
|
27
|
+
} catch (error) {
|
|
28
|
+
console.error(` ✗ Migration ${file} failed: ${error.message}`);
|
|
29
|
+
hasErrors = true;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (hasErrors) {
|
|
34
|
+
console.error('Some migrations failed. Please review errors above.');
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
console.log('All migrations completed successfully.');
|
|
39
|
+
process.exit(0);
|
|
40
|
+
} catch (error) {
|
|
41
|
+
console.error('Migration failed:', error.message);
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
runMigrations();
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { DataTypes } from 'sequelize';
|
|
2
|
+
import sequelize from '../config/db.js';
|
|
3
|
+
|
|
4
|
+
const ApprovalOTP = sequelize.define('ApprovalOTP', {
|
|
5
|
+
id: {
|
|
6
|
+
type: DataTypes.UUID,
|
|
7
|
+
defaultValue: DataTypes.UUIDV4,
|
|
8
|
+
primaryKey: true
|
|
9
|
+
},
|
|
10
|
+
approval_token_id: {
|
|
11
|
+
type: DataTypes.UUID,
|
|
12
|
+
field: 'approval_token_id',
|
|
13
|
+
allowNull: false,
|
|
14
|
+
references: {
|
|
15
|
+
model: 'approval_tokens',
|
|
16
|
+
key: 'id'
|
|
17
|
+
},
|
|
18
|
+
onDelete: 'CASCADE'
|
|
19
|
+
},
|
|
20
|
+
otp_code: {
|
|
21
|
+
type: DataTypes.TEXT,
|
|
22
|
+
field: 'otp_code',
|
|
23
|
+
allowNull: false
|
|
24
|
+
},
|
|
25
|
+
expires_at: {
|
|
26
|
+
type: DataTypes.DATE,
|
|
27
|
+
field: 'expires_at',
|
|
28
|
+
allowNull: false
|
|
29
|
+
},
|
|
30
|
+
verified: {
|
|
31
|
+
type: DataTypes.BOOLEAN,
|
|
32
|
+
allowNull: false,
|
|
33
|
+
defaultValue: false
|
|
34
|
+
},
|
|
35
|
+
attempts: {
|
|
36
|
+
type: DataTypes.INTEGER,
|
|
37
|
+
allowNull: false,
|
|
38
|
+
defaultValue: 0
|
|
39
|
+
}
|
|
40
|
+
}, {
|
|
41
|
+
tableName: 'approval_otps',
|
|
42
|
+
timestamps: true,
|
|
43
|
+
createdAt: 'created_at',
|
|
44
|
+
updatedAt: 'updated_at',
|
|
45
|
+
indexes: [
|
|
46
|
+
{ fields: ['approval_token_id'] },
|
|
47
|
+
{ fields: ['otp_code'] }
|
|
48
|
+
]
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
export default ApprovalOTP;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { DataTypes } from 'sequelize';
|
|
2
|
+
import sequelize from '../config/db.js';
|
|
3
|
+
|
|
4
|
+
const ApprovalToken = sequelize.define('ApprovalToken', {
|
|
5
|
+
id: {
|
|
6
|
+
type: DataTypes.UUID,
|
|
7
|
+
defaultValue: DataTypes.UUIDV4,
|
|
8
|
+
primaryKey: true
|
|
9
|
+
},
|
|
10
|
+
deal_id: {
|
|
11
|
+
type: DataTypes.TEXT,
|
|
12
|
+
field: 'deal_id',
|
|
13
|
+
allowNull: false,
|
|
14
|
+
references: {
|
|
15
|
+
model: 'deals',
|
|
16
|
+
key: 'deal_id'
|
|
17
|
+
},
|
|
18
|
+
onDelete: 'CASCADE'
|
|
19
|
+
},
|
|
20
|
+
approver_email: {
|
|
21
|
+
type: DataTypes.TEXT,
|
|
22
|
+
field: 'approver_email',
|
|
23
|
+
allowNull: false
|
|
24
|
+
},
|
|
25
|
+
token: {
|
|
26
|
+
type: DataTypes.TEXT,
|
|
27
|
+
allowNull: false,
|
|
28
|
+
unique: true
|
|
29
|
+
},
|
|
30
|
+
encrypted_token: {
|
|
31
|
+
type: DataTypes.TEXT,
|
|
32
|
+
field: 'encrypted_token',
|
|
33
|
+
allowNull: true
|
|
34
|
+
},
|
|
35
|
+
status: {
|
|
36
|
+
type: DataTypes.ENUM('PENDING', 'APPROVED', 'REJECTED'),
|
|
37
|
+
allowNull: false,
|
|
38
|
+
defaultValue: 'PENDING'
|
|
39
|
+
},
|
|
40
|
+
rejection_reason: {
|
|
41
|
+
type: DataTypes.TEXT,
|
|
42
|
+
field: 'rejection_reason',
|
|
43
|
+
allowNull: true
|
|
44
|
+
},
|
|
45
|
+
decision_at: {
|
|
46
|
+
type: DataTypes.DATE,
|
|
47
|
+
field: 'decision_at',
|
|
48
|
+
allowNull: true
|
|
49
|
+
},
|
|
50
|
+
expires_at: {
|
|
51
|
+
type: DataTypes.DATE,
|
|
52
|
+
field: 'expires_at',
|
|
53
|
+
allowNull: false
|
|
54
|
+
},
|
|
55
|
+
otp_verified: {
|
|
56
|
+
type: DataTypes.BOOLEAN,
|
|
57
|
+
field: 'otp_verified',
|
|
58
|
+
allowNull: false,
|
|
59
|
+
defaultValue: false
|
|
60
|
+
},
|
|
61
|
+
request_id: {
|
|
62
|
+
type: DataTypes.TEXT,
|
|
63
|
+
field: 'request_id',
|
|
64
|
+
allowNull: true
|
|
65
|
+
}
|
|
66
|
+
}, {
|
|
67
|
+
tableName: 'approval_tokens',
|
|
68
|
+
timestamps: true,
|
|
69
|
+
createdAt: 'created_at',
|
|
70
|
+
updatedAt: 'updated_at',
|
|
71
|
+
indexes: [
|
|
72
|
+
{ fields: ['deal_id'] },
|
|
73
|
+
{ fields: ['token'] },
|
|
74
|
+
{ fields: ['approver_email'] },
|
|
75
|
+
{ fields: ['status'] }
|
|
76
|
+
]
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
export default ApprovalToken;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { DataTypes } from 'sequelize';
|
|
2
|
+
import sequelize from '../config/db.js';
|
|
3
|
+
|
|
4
|
+
const ChangeHistory = sequelize.define('ChangeHistory', {
|
|
5
|
+
id: {
|
|
6
|
+
type: DataTypes.UUID,
|
|
7
|
+
defaultValue: DataTypes.UUIDV4,
|
|
8
|
+
primaryKey: true
|
|
9
|
+
},
|
|
10
|
+
entity_type: {
|
|
11
|
+
type: DataTypes.ENUM('DEAL', 'LINE_ITEM'),
|
|
12
|
+
allowNull: false,
|
|
13
|
+
field: 'entity_type'
|
|
14
|
+
},
|
|
15
|
+
entity_id: {
|
|
16
|
+
type: DataTypes.UUID,
|
|
17
|
+
allowNull: false,
|
|
18
|
+
field: 'entity_id'
|
|
19
|
+
},
|
|
20
|
+
deal_id: {
|
|
21
|
+
type: DataTypes.TEXT,
|
|
22
|
+
allowNull: true,
|
|
23
|
+
field: 'deal_id'
|
|
24
|
+
},
|
|
25
|
+
line_item_id: {
|
|
26
|
+
type: DataTypes.TEXT,
|
|
27
|
+
allowNull: true,
|
|
28
|
+
field: 'line_item_id'
|
|
29
|
+
},
|
|
30
|
+
action: {
|
|
31
|
+
type: DataTypes.ENUM('CREATE', 'UPDATE', 'DELETE', 'STATUS_CHANGE'),
|
|
32
|
+
allowNull: false
|
|
33
|
+
},
|
|
34
|
+
field_name: {
|
|
35
|
+
type: DataTypes.TEXT,
|
|
36
|
+
allowNull: true,
|
|
37
|
+
field: 'field_name'
|
|
38
|
+
},
|
|
39
|
+
previous_value: {
|
|
40
|
+
type: DataTypes.JSONB,
|
|
41
|
+
allowNull: true,
|
|
42
|
+
field: 'previous_value'
|
|
43
|
+
},
|
|
44
|
+
current_value: {
|
|
45
|
+
type: DataTypes.JSONB,
|
|
46
|
+
allowNull: true,
|
|
47
|
+
field: 'current_value'
|
|
48
|
+
},
|
|
49
|
+
changed_by: {
|
|
50
|
+
type: DataTypes.TEXT,
|
|
51
|
+
allowNull: true,
|
|
52
|
+
field: 'changed_by'
|
|
53
|
+
},
|
|
54
|
+
changed_by_email: {
|
|
55
|
+
type: DataTypes.TEXT,
|
|
56
|
+
allowNull: true,
|
|
57
|
+
field: 'changed_by_email'
|
|
58
|
+
},
|
|
59
|
+
request_id: {
|
|
60
|
+
type: DataTypes.TEXT,
|
|
61
|
+
allowNull: true,
|
|
62
|
+
field: 'request_id'
|
|
63
|
+
},
|
|
64
|
+
ip_address: {
|
|
65
|
+
type: DataTypes.TEXT,
|
|
66
|
+
allowNull: true,
|
|
67
|
+
field: 'ip_address'
|
|
68
|
+
},
|
|
69
|
+
user_agent: {
|
|
70
|
+
type: DataTypes.TEXT,
|
|
71
|
+
allowNull: true,
|
|
72
|
+
field: 'user_agent'
|
|
73
|
+
},
|
|
74
|
+
summary: {
|
|
75
|
+
type: DataTypes.TEXT,
|
|
76
|
+
allowNull: true
|
|
77
|
+
},
|
|
78
|
+
metadata: {
|
|
79
|
+
type: DataTypes.JSONB,
|
|
80
|
+
allowNull: true,
|
|
81
|
+
defaultValue: {}
|
|
82
|
+
}
|
|
83
|
+
}, {
|
|
84
|
+
tableName: 'change_history',
|
|
85
|
+
timestamps: true,
|
|
86
|
+
createdAt: 'created_at',
|
|
87
|
+
updatedAt: false,
|
|
88
|
+
indexes: [
|
|
89
|
+
{
|
|
90
|
+
fields: ['entity_type', 'entity_id']
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
fields: ['deal_id']
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
fields: ['line_item_id']
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
fields: ['created_at']
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
fields: ['action']
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
export default ChangeHistory;
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { DataTypes } from 'sequelize';
|
|
2
|
+
import sequelize from '../config/db.js';
|
|
3
|
+
|
|
4
|
+
const Deal = sequelize.define('Deal', {
|
|
5
|
+
id: {
|
|
6
|
+
type: DataTypes.UUID,
|
|
7
|
+
defaultValue: DataTypes.UUIDV4,
|
|
8
|
+
primaryKey: true
|
|
9
|
+
},
|
|
10
|
+
source: {
|
|
11
|
+
type: DataTypes.TEXT,
|
|
12
|
+
allowNull: false
|
|
13
|
+
},
|
|
14
|
+
external_id: {
|
|
15
|
+
type: DataTypes.TEXT,
|
|
16
|
+
allowNull: true,
|
|
17
|
+
field: 'external_id'
|
|
18
|
+
},
|
|
19
|
+
deal_id: {
|
|
20
|
+
type: DataTypes.TEXT,
|
|
21
|
+
field: 'deal_id',
|
|
22
|
+
unique: true
|
|
23
|
+
},
|
|
24
|
+
name: {
|
|
25
|
+
type: DataTypes.TEXT
|
|
26
|
+
},
|
|
27
|
+
deal_type: {
|
|
28
|
+
type: DataTypes.ENUM('GUARANTEED', 'PREFERRED_DEAL', 'PRIVATE_AUCTION', 'EVERGREEN_PMP', 'DIRECT'),
|
|
29
|
+
field: 'deal_type'
|
|
30
|
+
},
|
|
31
|
+
transaction_type: {
|
|
32
|
+
type: DataTypes.ENUM('SPOT', 'AUDIENCE'),
|
|
33
|
+
field: 'transaction_type'
|
|
34
|
+
},
|
|
35
|
+
auction_type: {
|
|
36
|
+
type: DataTypes.SMALLINT,
|
|
37
|
+
field: 'auction_type'
|
|
38
|
+
},
|
|
39
|
+
buyers: {
|
|
40
|
+
type: DataTypes.JSONB
|
|
41
|
+
},
|
|
42
|
+
advertiser: {
|
|
43
|
+
type: DataTypes.JSONB
|
|
44
|
+
},
|
|
45
|
+
seller: {
|
|
46
|
+
type: DataTypes.JSONB
|
|
47
|
+
},
|
|
48
|
+
currency: {
|
|
49
|
+
type: DataTypes.TEXT
|
|
50
|
+
},
|
|
51
|
+
cost_type: {
|
|
52
|
+
type: DataTypes.ENUM('CPD', 'CPM', 'CPS'),
|
|
53
|
+
field: 'cost_type'
|
|
54
|
+
},
|
|
55
|
+
delivery_goal: {
|
|
56
|
+
type: DataTypes.BIGINT,
|
|
57
|
+
field: 'delivery_goal'
|
|
58
|
+
},
|
|
59
|
+
net_cost: {
|
|
60
|
+
type: DataTypes.DECIMAL(14, 2),
|
|
61
|
+
field: 'net_cost'
|
|
62
|
+
},
|
|
63
|
+
net_cost_per_day: {
|
|
64
|
+
type: DataTypes.DECIMAL(14, 2),
|
|
65
|
+
field: 'net_cost_per_day'
|
|
66
|
+
},
|
|
67
|
+
timezone_id: {
|
|
68
|
+
type: DataTypes.TEXT,
|
|
69
|
+
field: 'timezone_id'
|
|
70
|
+
},
|
|
71
|
+
start_date: {
|
|
72
|
+
type: DataTypes.DATEONLY,
|
|
73
|
+
field: 'start_date'
|
|
74
|
+
},
|
|
75
|
+
end_date: {
|
|
76
|
+
type: DataTypes.DATEONLY,
|
|
77
|
+
field: 'end_date'
|
|
78
|
+
},
|
|
79
|
+
impressions: {
|
|
80
|
+
type: DataTypes.BIGINT
|
|
81
|
+
},
|
|
82
|
+
account: {
|
|
83
|
+
type: DataTypes.JSONB
|
|
84
|
+
},
|
|
85
|
+
country: {
|
|
86
|
+
type: DataTypes.TEXT
|
|
87
|
+
},
|
|
88
|
+
status: {
|
|
89
|
+
type: DataTypes.ENUM('DRAFT', 'REQUESTED', 'GENERATED', 'PENDING', 'APPROVED', 'REJECTED', 'CANCELED', 'DELETED', 'PENDING_CREATIVES', 'LIVE', 'COMPLETED', 'IN_ACTIVE', 'REOPENED', 'ARCHIVED', 'EXPIRED'),
|
|
90
|
+
defaultValue: 'GENERATED'
|
|
91
|
+
},
|
|
92
|
+
line_items_count: {
|
|
93
|
+
type: DataTypes.INTEGER,
|
|
94
|
+
defaultValue: 0,
|
|
95
|
+
field: 'line_items_count'
|
|
96
|
+
},
|
|
97
|
+
active: {
|
|
98
|
+
type: DataTypes.BOOLEAN,
|
|
99
|
+
defaultValue: true
|
|
100
|
+
},
|
|
101
|
+
is_playing: {
|
|
102
|
+
type: DataTypes.BOOLEAN,
|
|
103
|
+
defaultValue: false,
|
|
104
|
+
field: 'is_playing'
|
|
105
|
+
},
|
|
106
|
+
publishers: {
|
|
107
|
+
type: DataTypes.JSONB,
|
|
108
|
+
field: 'publishers'
|
|
109
|
+
},
|
|
110
|
+
metadata: {
|
|
111
|
+
type: DataTypes.JSONB
|
|
112
|
+
},
|
|
113
|
+
version: {
|
|
114
|
+
type: DataTypes.INTEGER,
|
|
115
|
+
defaultValue: 1
|
|
116
|
+
},
|
|
117
|
+
brand: {
|
|
118
|
+
type: DataTypes.TEXT
|
|
119
|
+
},
|
|
120
|
+
client_type: {
|
|
121
|
+
type: DataTypes.TEXT,
|
|
122
|
+
field: 'client_type'
|
|
123
|
+
},
|
|
124
|
+
mode: {
|
|
125
|
+
type: DataTypes.TEXT
|
|
126
|
+
},
|
|
127
|
+
approval_emails: {
|
|
128
|
+
type: DataTypes.ARRAY(DataTypes.TEXT),
|
|
129
|
+
field: 'approval_emails'
|
|
130
|
+
},
|
|
131
|
+
market_selection: {
|
|
132
|
+
type: DataTypes.JSONB,
|
|
133
|
+
field: 'market_selection'
|
|
134
|
+
},
|
|
135
|
+
budget_setup: {
|
|
136
|
+
type: DataTypes.JSONB,
|
|
137
|
+
field: 'budget_setup'
|
|
138
|
+
},
|
|
139
|
+
campaign_goal: {
|
|
140
|
+
type: DataTypes.JSONB,
|
|
141
|
+
field: 'campaign_goal'
|
|
142
|
+
},
|
|
143
|
+
planning: {
|
|
144
|
+
type: DataTypes.JSONB,
|
|
145
|
+
field: 'planning'
|
|
146
|
+
},
|
|
147
|
+
published: {
|
|
148
|
+
type: DataTypes.BOOLEAN,
|
|
149
|
+
defaultValue: false
|
|
150
|
+
},
|
|
151
|
+
reopened: {
|
|
152
|
+
type: DataTypes.BOOLEAN,
|
|
153
|
+
defaultValue: false
|
|
154
|
+
},
|
|
155
|
+
non_billable: {
|
|
156
|
+
type: DataTypes.BOOLEAN,
|
|
157
|
+
defaultValue: false,
|
|
158
|
+
field: 'non_billable'
|
|
159
|
+
},
|
|
160
|
+
stop_bid_requests: {
|
|
161
|
+
type: DataTypes.BOOLEAN,
|
|
162
|
+
defaultValue: false,
|
|
163
|
+
field: 'stop_bid_requests'
|
|
164
|
+
},
|
|
165
|
+
imp_multiplier_type: {
|
|
166
|
+
type: DataTypes.ENUM('MAD', 'CUSTOM'),
|
|
167
|
+
field: 'imp_multiplier_type'
|
|
168
|
+
},
|
|
169
|
+
rejection_reason: {
|
|
170
|
+
type: DataTypes.TEXT,
|
|
171
|
+
field: 'rejection_reason'
|
|
172
|
+
}
|
|
173
|
+
}, {
|
|
174
|
+
tableName: 'deals',
|
|
175
|
+
timestamps: true,
|
|
176
|
+
createdAt: 'created_at',
|
|
177
|
+
updatedAt: 'updated_at',
|
|
178
|
+
indexes: [
|
|
179
|
+
{
|
|
180
|
+
unique: true,
|
|
181
|
+
fields: ['source', 'external_id']
|
|
182
|
+
}
|
|
183
|
+
]
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
export default Deal;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { DataTypes } from 'sequelize';
|
|
2
|
+
import sequelize from '../config/db.js';
|
|
3
|
+
|
|
4
|
+
const DealIdCounter = sequelize.define('DealIdCounter', {
|
|
5
|
+
id: {
|
|
6
|
+
type: DataTypes.INTEGER,
|
|
7
|
+
primaryKey: true,
|
|
8
|
+
autoIncrement: true
|
|
9
|
+
},
|
|
10
|
+
prefix: {
|
|
11
|
+
type: DataTypes.STRING(10),
|
|
12
|
+
allowNull: false,
|
|
13
|
+
unique: true
|
|
14
|
+
},
|
|
15
|
+
current_value: {
|
|
16
|
+
type: DataTypes.BIGINT,
|
|
17
|
+
allowNull: false,
|
|
18
|
+
defaultValue: 0,
|
|
19
|
+
field: 'current_value'
|
|
20
|
+
}
|
|
21
|
+
}, {
|
|
22
|
+
tableName: 'deal_id_counters',
|
|
23
|
+
timestamps: true,
|
|
24
|
+
createdAt: 'created_at',
|
|
25
|
+
updatedAt: 'updated_at'
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export default DealIdCounter;
|