-
Notifications
You must be signed in to change notification settings - Fork 0
feat: booking #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -131,7 +131,7 @@ Stack: NestJS 11 + TypeORM + MySQL 8. yarn. Each task atomic, stop for review be | |
|
|
||
| ## Task 10 — Availability query | ||
|
|
||
| `[x]` _(depends on: Task 9)_ | ||
| `[✓]` _(depends on: Task 9)_ | ||
|
|
||
| - `src/appointment/dto/get-availability.dto.ts` — `{ serviceTypeId: string, date: string }` (query params) | ||
| - `AppointmentService.getAvailability(dealershipId, serviceTypeId, date)`: | ||
|
|
@@ -147,14 +147,14 @@ Stack: NestJS 11 + TypeORM + MySQL 8. yarn. Each task atomic, stop for review be | |
|
|
||
| ## Task 11 — Booking transaction | ||
|
|
||
| `[ ]` _(depends on: Task 10)_ | ||
| `[[✓]` _(depends on: Task 10)_ | ||
|
|
||
| - `src/appointment/dto/create-appointment.dto.ts` — `{ dealershipId, vehicleId, serviceTypeId, startAt }`; `@IsISO8601()` on `startAt` | ||
| - `AppointmentService.createAppointment(dto)`: transaction handle by typeorm-transaction | ||
| - `AppointmentService.createAppointment(dto)`: create custom repository, query by typeorm QueryBuilder | ||
| 1. Validate `startAt` aligned to fixed 15-min absolute grid and within dealership hours → 422 if not | ||
| 2. Compute slots from validated `startAt` | ||
| 3. Verify ≥1 qualified tech at dealership → 422 if none | ||
| 4. Begin transaction | ||
| 4. Begin transaction with typeorm-transaction | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
# Show targeted sections with line numbers
sed -n '145,205p' TASKS.md | cat -n
# Search for relevant references in TASKS.md
rg -n "typeorm-transaction|queryRunner|transaction" TASKS.mdRepository: hytnht/appointment-scheduler Length of output: 3416 Use one authoritative transaction mechanism in TASKS.md Task 11 still says to begin the booking transaction with 🤖 Prompt for AI Agents |
||
| 5. Candidate loop (**hotspot-safe assignment**): | ||
| - Build top-K qualified active technicians by load, randomize order | ||
| - Build top-K active free bays by load, randomize order | ||
|
|
@@ -171,18 +171,16 @@ Stack: NestJS 11 + TypeORM + MySQL 8. yarn. Each task atomic, stop for review be | |
|
|
||
| --- | ||
|
|
||
| ## Task 12 — Cancel, reschedule, fetch | ||
| ## Task 12 — Cancel, fetch | ||
|
|
||
| `[ ]` _(depends on: Task 11)_ | ||
| `[✓]` _(depends on: Task 11)_ | ||
|
|
||
| - `src/appointment/dto/patch-appointment.dto.ts` — `{ action: 'cancel' | 'reschedule', startAt?: string }` | ||
| - `AppointmentService.cancelAppointment(id)` — txn: `status = CANCELLED`, delete reservations | ||
| - `AppointmentService.rescheduleAppointment(id, newStartAt)` — txn: delete old reservations, re-run booking attempt at new time | ||
| - `AppointmentController`: | ||
| - `GET /appointments/:id` — fetch with all relations | ||
| - `PATCH /appointments/:id` — route to cancel or reschedule | ||
| - `PATCH /appointments/:id` — route to cancel | ||
|
hytnht marked this conversation as resolved.
|
||
|
|
||
| **Verify:** `yarn build`; unit tests: cancel clears reservations; reschedule retry-on-dup; reschedule outside-hours → 422; GET returns relations | ||
| **Verify:** `yarn build`; unit tests: cancel clears reservations; GET returns relations | ||
|
|
||
| --- | ||
|
|
||
|
|
@@ -195,6 +193,5 @@ Stack: NestJS 11 + TypeORM + MySQL 8. yarn. Each task atomic, stop for review be | |
| - Slot size: 15 min constant in `slot.util.ts` | ||
| - Slot grid is absolute (anchored), independent from dealership `open_time` | ||
| - No idempotency key header; duplicate request prevented by DB uniqueness + transactional reservation conflict | ||
| - PATCH body: `{ action: 'cancel' | 'reschedule', startAt?: string }` | ||
| - Out of scope: notifications, payments, frontend, auth, multi-region | ||
| - Swagger doc all API with CLI plugin, description and example for all property | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,6 +12,7 @@ export default () => ({ | |
| keepConnectionAlive: true, | ||
| extra: { connectionLimit: 10 }, | ||
| timezone: 'Z', | ||
| logging: true, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
# Map the relevant file and inspect the exact context around the cited line.
git ls-files src/configs/app.config.ts
wc -l src/configs/app.config.ts
cat -n src/configs/app.config.ts | sed -n '1,220p'
# Search for other TypeORM / logging configuration that may override or contextualize this setting.
rg -n "logging\s*:|TypeOrmModule|DataSource|typeorm" src . --glob '!node_modules' --glob '!dist' --glob '!build'Repository: hytnht/appointment-scheduler Length of output: 16060 🏁 Script executed: #!/bin/bash
set -euo pipefail
# Inspect the config interface and database wiring.
cat -n src/configs/config.interface.ts
printf '\n---\n'
cat -n src/database/database.module.ts
printf '\n---\n'
cat -n src/app.module.ts
printf '\n---\n'
cat -n src/main.ts
# Locate Swagger setup and how the config is consumed.
rg -n "SwaggerModule|createDocument|swagger\.|tagsSorter|operationsSorter|SwaggerCustomOptions|swaggerOptions|options:" src testRepository: hytnht/appointment-scheduler Length of output: 6753 Disable TypeORM logging in production
🤖 Prompt for AI AgentsSource: MCP tools |
||
| replication: { | ||
| defaultMode: 'master', | ||
| restoreNodeTimeout: 3000, | ||
|
|
@@ -39,5 +40,9 @@ export default () => ({ | |
| description: 'Appointment Scheduler Service API documentation', | ||
| version: '1.0', | ||
| path: 'api-docs', | ||
| swaggerOptions: { | ||
| tagsSorter: 'alpha', | ||
| operationsSorter: 'method', | ||
| }, | ||
| }, | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,11 @@ | ||
| import { Timestamp } from '@src/database/entities/timestamp.entity'; | ||
| import { PrimaryGeneratedColumn } from 'typeorm'; | ||
| import { CreateDateColumn, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'; | ||
|
|
||
| export abstract class BaseEntity extends Timestamp { | ||
| export abstract class BaseEntity { | ||
| @PrimaryGeneratedColumn({ type: 'int', unsigned: true }) | ||
| id: number; | ||
| @CreateDateColumn({ name: 'created_at', type: 'timestamp' }) | ||
| createdAt: Date; | ||
|
|
||
| @UpdateDateColumn({ name: 'updated_at', type: 'timestamp' }) | ||
| updatedAt: Date; | ||
| } |
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,16 +1,40 @@ | ||
| import { Controller, Get, Param, Query } from '@nestjs/common'; | ||
| import { Body, Controller, Get, Param, Patch, Post, Query } from '@nestjs/common'; | ||
| import { AppointmentService } from './appointment.service'; | ||
| import { CreateAppointmentDto } from './dtos/create-appointment.dto'; | ||
| import { GetAvailabilityDto } from './dtos/get-availability.dto'; | ||
| import { SearchAppointmentDto } from './dtos/search-appointment.dto'; | ||
| import { Appointment } from './entities/appointment.entity'; | ||
| import { AppointmentSearchResult } from './interfaces/appointment-search.type'; | ||
|
|
||
| @Controller('dealerships') | ||
| @Controller('appointments') | ||
| export class AppointmentController { | ||
| constructor(private readonly appointmentService: AppointmentService) {} | ||
|
|
||
| @Get(':id/availability') | ||
| @Get() | ||
| search(@Query() query: SearchAppointmentDto): Promise<AppointmentSearchResult> { | ||
| return this.appointmentService.search(query); | ||
| } | ||
|
|
||
| @Get('availability/:id') | ||
| getAvailability( | ||
| @Param('id') dealershipId: number, | ||
| @Query() { serviceTypeId, date }: GetAvailabilityDto, | ||
| ): Promise<string[]> { | ||
| return this.appointmentService.getAvailability(dealershipId, serviceTypeId, date); | ||
| } | ||
|
hytnht marked this conversation as resolved.
|
||
|
|
||
| @Post() | ||
| create(@Body() dto: CreateAppointmentDto): Promise<Appointment> { | ||
| return this.appointmentService.createAppointment(dto); | ||
| } | ||
|
|
||
| @Get(':id') | ||
| findOne(@Param('id') id: number): Promise<Appointment> { | ||
| return this.appointmentService.findOne(id); | ||
| } | ||
|
|
||
| @Patch(':id') | ||
| patch(@Param('id') id: number): Promise<Appointment> { | ||
| return this.appointmentService.cancelAppointment(id); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Fix the malformed Task 11 status marker.
[[✓]has an extra opening bracket and does not match the documented status format. Change it to[✓].🤖 Prompt for AI Agents