Skip to content

Architecture

  • Module: src/ai-chatbot/ai-chatbot.module.ts

    • Registers controller + service.
    • Makes TypeORM repositories available for:
      • AiChatbot
      • AiOperatingSchedule
      • WorkflowEnhancement
      • GptPrompt
  • Controller: src/ai-chatbot/ai-chatbot.controller.ts

    • Endpoints live under /ai-chatbot.
    • Applies @UseGuards(JwtAuthGuard) at class level.
    • Extracts userId via getUserId(req) and passes it to the service.
  • Service: src/ai-chatbot/ai-chatbot.service.ts

    • Settings orchestration:
      • create(user, dto)
      • findByUser(userId)
      • update(userId, dto)
      • remove(userId)
    • Schedule orchestration:
      • addSchedulesToChatbot(userId, schedules[])
      • getSchedules(userId)
      • getScheduleById(userId, scheduleId)
      • updateSchedule(scheduleId, userId, dto)
      • deleteScheduleFromChatbot(userId, scheduleId)
    • Correctness-critical helper:
      • validateTime(existingSchedules, newSchedule, requestedId?)

Create settings (AiChatbotService.create(user, dto))

Section titled “Create settings (AiChatbotService.create(user, dto))”
  • DTO split

    • The service destructures dto into:
      • chatbotEnhancement
      • operatingSchedule
      • scalar fields (rest)
  • Settings creation

    • Creates an AiChatbot entity linked to the provided user.
  • Prompt auto-link

    • Queries GptPrompt by user and assigns it if found.
    • The request does not choose a prompt; the service enforces this behavior.
  • Enhancement creation (optional)

    • If chatbotEnhancement exists:
      • creates a WorkflowEnhancement
      • assigns to AiChatbot.chatbotEnhancement
      • special case: is_new_template is mapped to { id: <value> } as any
  • Persistence order and rollback

    • Saves AiChatbot first.
    • Then attempts to save schedules:
      • converts each schedule DTO to an AiOperatingSchedule linked to the saved chatbot
      • saves schedule rows
    • If schedule persistence fails:
      • deletes the saved chatbot row as rollback
      • throws BAD_REQUEST (“Failed to save schedules”)

Update settings (AiChatbotService.update(userId, dto))

Section titled “Update settings (AiChatbotService.update(userId, dto))”
  • Loads the user’s AiChatbot record.
    • If missing: throws BAD_REQUEST (“Chatbot must be created first”).
  • Applies scalar updates via Object.assign(setting, otherProps).
  • Auto-links a GptPrompt if present (same behavior as create).
  • Enhancement upsert:
    • updates existing enhancement if it exists; otherwise creates and links a new one.
  • Schedule mutations when dto.operatingSchedule is present:
    • Update existing schedule when an id is provided:
      • loads schedule with relations including chatbot’s user and schedules
      • checks ownership
      • validates overlap with validateTime(...) excluding requestedId
      • saves updated schedule row
    • Create new schedule when no id is provided:
      • loads existing schedules
      • validates overlap
      • creates and saves a new schedule row linked to the chatbot
  • Saves chatbot settings and returns findByUser(userId).

Schedule-only endpoints (service behavior)

Section titled “Schedule-only endpoints (service behavior)”
  • Batch add (addSchedulesToChatbot)

    • Loads chatbot with existing schedules.
    • Validates that the input is an array.
    • Validates each new schedule against existing ones (overlap).
    • Creates schedule entities, pushes them into chatbot.operatingSchedule, saves chatbot.
  • Update by id (updateSchedule)

    • Loads schedule + chatbot schedules.
    • Computes effective values (dto overrides existing) and validates overlap.
    • Saves schedule.
  • The module is request-synchronous: no queueing, no background jobs.
  • The service is the orchestration point and contains:
    • cross-entity concerns (prompt linking + enhancement + schedules)
    • correctness rules (schedule overlap validation)
  • Non-existent

    • GET /ai-chatbotNOT_FOUND
    • PATCH /ai-chatbotBAD_REQUEST
  • Created

    • Exactly one row per user enforced by @Unique(['user']).
    • Optional relations may be empty/null (prompt, chatbotEnhancement, operatingSchedule).
  • Updated

    • Scalar fields overwritten by assignment.
    • Enhancement upserted.
    • Schedules updated/created via repository operations.
  • Deleted

    • Removing chatbot cascades schedule deletion (AiOperatingSchedule has onDelete: 'CASCADE').
  • Created in bulk and individually.
  • Ownership is enforced through the linked chatbot’s user.
  • Updated with overlap validation and optional self-exclusion (requestedId).
  • No jobs/queues/async workflows are implemented inside this module.
  • One chatbot per user

    • Pros: simple retrieval (findByUser), simple UI, single source of truth.
    • Cons: multi-bot per user would require schema + API redesign.
  • Prompt selection is implicit

    • Pros: easy API; prompt follows “user’s prompt” rule.
    • Cons: becomes ambiguous if the system later supports multiple prompts per user.
  • Schedule correctness enforced centrally

    • Pros: consistent behavior across endpoints and UI.
    • Cons: complex timezone/DST edge cases; requires strong tests.
  • Manual rollback instead of transaction

    • Pros: simple implementation.
    • Cons: not fully atomic across all write operations and failure modes.

  • Module: src/ai-chatbot/ai-chatbot.module.ts

    • Registers controller + service and TypeORM repositories for:
      • AiChatbot, AiOperatingSchedule, WorkflowEnhancement, GptPrompt
  • Controller: src/ai-chatbot/ai-chatbot.controller.ts

    • Route prefix: /ai-chatbot
    • Enforces authentication with JwtAuthGuard.
    • Resolves user identity using getUserId(req).
    • Delegates all business logic to the service.
  • Service: src/ai-chatbot/ai-chatbot.service.ts

    • Orchestrates settings CRUD and schedule CRUD.
    • Performs schedule overlap validation with timezone conversion.

Create settings (AiChatbotService.create(user, dto))

Section titled “Create settings (AiChatbotService.create(user, dto))”
  • Creates an AiChatbot entity tied to the authenticated user.
  • Auto-links prompt:
    • Looks up a GptPrompt by user.id and assigns it if present.
  • Enhancement (optional):
    • If dto.chatbotEnhancement exists, creates a WorkflowEnhancement and assigns to AiChatbot.chatbotEnhancement.
    • Special case: is_new_template is coerced into { id: ... } as any to represent a relation-like reference.
  • Saves AiChatbot.
  • Saves schedules if provided:
    • Creates AiOperatingSchedule rows linked to the saved chatbot.
    • On failure to save schedules, deletes the chatbot row as a manual rollback.

Update settings (AiChatbotService.update(userId, dto))

Section titled “Update settings (AiChatbotService.update(userId, dto))”
  • Loads the user’s AiChatbot row.
    • If missing: throws BAD_REQUEST (“Chatbot must be created first”).
  • Applies scalar changes (Object.assign(setting, otherProps)).
  • Repeats prompt auto-link behavior.
  • Upserts enhancement if provided (update in-place if exists, otherwise create new).
  • Applies schedule mutations if provided:
    • Updates by schedule id (ownership + overlap validation).
    • Creates new schedule rows for items without id.

Schedule validation (validateTime(existingSchedules, newSchedule, requestedId?))

Section titled “Schedule validation (validateTime(existingSchedules, newSchedule, requestedId?))”
  • Rejects:
    • startHour === endHour
    • end <= start (after timezone conversion)
    • overlaps with existing schedules on the same day (excluding requestedId during updates)
  • Implementation uses:
    • formatInTimeZone(...) to compute a date part
    • fromZonedTime(...) to compare UTC instants
  • AiChatbot

    • One per user (DB unique constraint).
    • Optional relations: prompt, enhancement, schedule list.
    • Deleting chatbot cascades schedule deletion (DB onDelete: 'CASCADE' on schedules).
  • AiOperatingSchedule

    • Owned through AiChatbot → user.
    • Schedule operations enforce ownership (the user must match schedule.ai_chatbot.user.id).
  • None. All work is synchronous in request handlers.
  • Single settings object per user

    • Simplifies reads and UI, but makes “multiple chatbots” a breaking change.
  • Prompt selection is implicit

    • Service chooses a prompt automatically; the API does not accept a promptId.
    • Works under the current assumption of one prompt per user (explicit comment in service).
  • Manual rollback instead of DB transactions

    • Keeps implementation lightweight, but is not fully atomic in all failure modes.