Architecture
Detailed How It Works
Section titled “Detailed How It Works”Key modules, services, and functions
Section titled “Key modules, services, and functions”-
Module:
src/ai-chatbot/ai-chatbot.module.ts- Registers controller + service.
- Makes TypeORM repositories available for:
AiChatbotAiOperatingScheduleWorkflowEnhancementGptPrompt
-
Controller:
src/ai-chatbot/ai-chatbot.controller.ts- Endpoints live under
/ai-chatbot. - Applies
@UseGuards(JwtAuthGuard)at class level. - Extracts
userIdviagetUserId(req)and passes it to the service.
- Endpoints live under
-
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?)
- Settings orchestration:
Internal execution flow
Section titled “Internal execution flow”Create settings (AiChatbotService.create(user, dto))
Section titled “Create settings (AiChatbotService.create(user, dto))”-
DTO split
- The service destructures
dtointo:chatbotEnhancementoperatingSchedule- scalar fields (rest)
- The service destructures
-
Settings creation
- Creates an
AiChatbotentity linked to the provideduser.
- Creates an
-
Prompt auto-link
- Queries
GptPromptby user and assigns it if found. - The request does not choose a prompt; the service enforces this behavior.
- Queries
-
Enhancement creation (optional)
- If
chatbotEnhancementexists:- creates a
WorkflowEnhancement - assigns to
AiChatbot.chatbotEnhancement - special case:
is_new_templateis mapped to{ id: <value> } as any
- creates a
- If
-
Persistence order and rollback
- Saves
AiChatbotfirst. - Then attempts to save schedules:
- converts each schedule DTO to an
AiOperatingSchedulelinked to the saved chatbot - saves schedule rows
- converts each schedule DTO to an
- If schedule persistence fails:
- deletes the saved chatbot row as rollback
- throws
BAD_REQUEST(“Failed to save schedules”)
- Saves
Update settings (AiChatbotService.update(userId, dto))
Section titled “Update settings (AiChatbotService.update(userId, dto))”- Loads the user’s
AiChatbotrecord.- If missing: throws
BAD_REQUEST(“Chatbot must be created first”).
- If missing: throws
- Applies scalar updates via
Object.assign(setting, otherProps). - Auto-links a
GptPromptif present (same behavior as create). - Enhancement upsert:
- updates existing enhancement if it exists; otherwise creates and links a new one.
- Schedule mutations when
dto.operatingScheduleis present:- Update existing schedule when an
idis provided:- loads schedule with relations including chatbot’s user and schedules
- checks ownership
- validates overlap with
validateTime(...)excludingrequestedId - saves updated schedule row
- Create new schedule when no
idis provided:- loads existing schedules
- validates overlap
- creates and saves a new schedule row linked to the chatbot
- Update existing schedule when an
- 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.
Control flow and orchestration notes
Section titled “Control flow and orchestration notes”- 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)
State Management
Section titled “State Management”Lifecycle: AiChatbot
Section titled “Lifecycle: AiChatbot”-
Non-existent
GET /ai-chatbot→NOT_FOUNDPATCH /ai-chatbot→BAD_REQUEST
-
Created
- Exactly one row per user enforced by
@Unique(['user']). - Optional relations may be empty/null (
prompt,chatbotEnhancement,operatingSchedule).
- Exactly one row per user enforced by
-
Updated
- Scalar fields overwritten by assignment.
- Enhancement upserted.
- Schedules updated/created via repository operations.
-
Deleted
- Removing chatbot cascades schedule deletion (
AiOperatingSchedulehasonDelete: 'CASCADE').
- Removing chatbot cascades schedule deletion (
Lifecycle: AiOperatingSchedule
Section titled “Lifecycle: AiOperatingSchedule”- Created in bulk and individually.
- Ownership is enforced through the linked chatbot’s user.
- Updated with overlap validation and optional self-exclusion (
requestedId).
Background Processing
Section titled “Background Processing”- No jobs/queues/async workflows are implemented inside this module.
Design Decisions
Section titled “Design Decisions”-
One chatbot per user
- Pros: simple retrieval (
findByUser), simple UI, single source of truth. - Cons: multi-bot per user would require schema + API redesign.
- Pros: simple retrieval (
-
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.
title: Architecture sidebar: order: 2
Section titled “title: Architecture sidebar: order: 2”Detailed How It Works
Section titled “Detailed How It Works”Components and responsibilities
Section titled “Components and responsibilities”-
Module:
src/ai-chatbot/ai-chatbot.module.ts- Registers controller + service and TypeORM repositories for:
AiChatbot,AiOperatingSchedule,WorkflowEnhancement,GptPrompt
- Registers controller + service and TypeORM repositories for:
-
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.
- Route prefix:
-
Service:
src/ai-chatbot/ai-chatbot.service.ts- Orchestrates settings CRUD and schedule CRUD.
- Performs schedule overlap validation with timezone conversion.
Internal execution flow
Section titled “Internal execution flow”Create settings (AiChatbotService.create(user, dto))
Section titled “Create settings (AiChatbotService.create(user, dto))”- Creates an
AiChatbotentity tied to the authenticated user. - Auto-links prompt:
- Looks up a
GptPromptbyuser.idand assigns it if present.
- Looks up a
- Enhancement (optional):
- If
dto.chatbotEnhancementexists, creates aWorkflowEnhancementand assigns toAiChatbot.chatbotEnhancement. - Special case:
is_new_templateis coerced into{ id: ... } as anyto represent a relation-like reference.
- If
- Saves
AiChatbot. - Saves schedules if provided:
- Creates
AiOperatingSchedulerows linked to the saved chatbot. - On failure to save schedules, deletes the chatbot row as a manual rollback.
- Creates
Update settings (AiChatbotService.update(userId, dto))
Section titled “Update settings (AiChatbotService.update(userId, dto))”- Loads the user’s
AiChatbotrow.- If missing: throws
BAD_REQUEST(“Chatbot must be created first”).
- If missing: throws
- 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.
- Updates by schedule
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(excludingrequestedIdduring updates)
- Implementation uses:
formatInTimeZone(...)to compute a date partfromZonedTime(...)to compare UTC instants
State Management
Section titled “State Management”-
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).
- Owned through
Background Processing
Section titled “Background Processing”- None. All work is synchronous in request handlers.
Design Decisions (as implemented)
Section titled “Design Decisions (as implemented)”-
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).
- Service chooses a prompt automatically; the API does not accept a
-
Manual rollback instead of DB transactions
- Keeps implementation lightweight, but is not fully atomic in all failure modes.