merge: integrer chore/outillage-et-format
This commit is contained in:
commit
c4c70862c1
43
.agents/skills/source-command-explore-and-plan/SKILL.md
Normal file
43
.agents/skills/source-command-explore-and-plan/SKILL.md
Normal file
@ -0,0 +1,43 @@
|
||||
---
|
||||
name: "source-command-explore-and-plan"
|
||||
description: "Explore codebase, create implementation plan, code, and test following EPCT workflow"
|
||||
---
|
||||
|
||||
# source-command-explore-and-plan
|
||||
|
||||
Use this skill when the user asks to run the migrated source command `explore-and-plan`.
|
||||
|
||||
## Command Template
|
||||
|
||||
# Explore, Plan, Code, Test Workflow
|
||||
|
||||
At the end of this message, I will ask you to do something.
|
||||
Please follow the "Explore, Plan, Code, Test" workflow when you start.
|
||||
|
||||
## Explore
|
||||
|
||||
First, use parallel subagents to find and read all files that may be useful for implementing the ticket, either as examples or as edit targets. The subagents should return relevant file paths, and any other info that may be useful.
|
||||
|
||||
## Plan
|
||||
|
||||
Next, think hard and write up a detailed implementation plan. Don't forget to include tests, lookbook components, and documentation. Use your judgement as to what is necessary, given the standards of this repo.
|
||||
|
||||
If there are things you are not sure about, use parallel subagents to do some web research. They should only return useful information, no noise.
|
||||
|
||||
If there are things you still do not understand or questions you have for the user, pause here to ask them before continuing.
|
||||
|
||||
## Code
|
||||
|
||||
When you have a thorough implementation plan, you are ready to start writing code. Follow the style of the existing codebase (e.g. we prefer clearly named variables and methods to extensive comments). Make sure to run our autoformatting script when you're done, and fix linter warnings that seem reasonable to you.
|
||||
|
||||
## Test
|
||||
|
||||
Use parallel subagents to run tests, and make sure they all pass.
|
||||
|
||||
If your changes touch the UX in a major way, use the browser to make sure that everything works correctly. Make a list of what to test for, and use a subagent for this step.
|
||||
|
||||
If your testing shows problems, go back to the planning stage and think ultrahard.
|
||||
|
||||
## Write up your work
|
||||
|
||||
When you are happy with your work, write up a short report that could be used as the PR description. Include what you set out to do, the choices you made with their brief justification, and any commands you ran in the process that may be useful for future developers to know about.
|
||||
17
.agents/skills/source-command-fix-pr-comments/SKILL.md
Normal file
17
.agents/skills/source-command-fix-pr-comments/SKILL.md
Normal file
@ -0,0 +1,17 @@
|
||||
---
|
||||
name: "source-command-fix-pr-comments"
|
||||
description: "Fetch all comments for the current pull request and fix them."
|
||||
---
|
||||
|
||||
# source-command-fix-pr-comments
|
||||
|
||||
Use this skill when the user asks to run the migrated source command `fix-pr-comments`.
|
||||
|
||||
## Command Template
|
||||
|
||||
Workflow:
|
||||
|
||||
1. Use `gh cli` to fetch the comments that are NOT resolved from the pull request.
|
||||
2. Define all the modifications you should actually make.
|
||||
3. Act and update the files.
|
||||
4. Create a commit and push.
|
||||
43
.agents/skills/source-command-quick-commit/SKILL.md
Normal file
43
.agents/skills/source-command-quick-commit/SKILL.md
Normal file
@ -0,0 +1,43 @@
|
||||
---
|
||||
name: "source-command-quick-commit"
|
||||
description: "Quickly commit all changes with an auto-generated message"
|
||||
---
|
||||
|
||||
# source-command-quick-commit
|
||||
|
||||
Use this skill when the user asks to run the migrated source command `quick-commit`.
|
||||
|
||||
## Command Template
|
||||
|
||||
Workflow for quick Git commits:
|
||||
|
||||
1. Check git status to see what changes are present
|
||||
2. Analyze changes to generate a short, clear commit message
|
||||
3. Stage all changes (tracked and untracked files)
|
||||
4. Create the commit with DH7789-dev signature
|
||||
5. Optionally push to remote if tracking branch exists
|
||||
|
||||
The commit message will be automatically generated by analyzing:
|
||||
- Modified files and their purposes (components, configs, tests, docs, etc.)
|
||||
- New files added and their function
|
||||
- Deleted files and cleanup operations
|
||||
- Overall scope of changes to determine action verb (add, update, fix, refactor, remove, etc.)
|
||||
|
||||
Commit message format: `[action] [what was changed]`
|
||||
Examples:
|
||||
- `add user authentication system`
|
||||
- `fix navigation menu responsive issues`
|
||||
- `update API endpoints configuration`
|
||||
- `refactor database connection logic`
|
||||
- `remove deprecated utility functions`
|
||||
|
||||
This command is ideal for:
|
||||
- Quick iteration cycles
|
||||
- Work-in-progress commits
|
||||
- Feature development checkpoints
|
||||
- Bug fix commits
|
||||
|
||||
The commit will include your custom signature:
|
||||
```
|
||||
Signed-off-by: DH7789-dev
|
||||
```
|
||||
25
.codex/hooks.json
Normal file
25
.codex/hooks.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"hooks": {
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "bun /Users/david/.claude/scripts/validate-command.js"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"Stop": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "afplay /Users/david/.claude/song/finish.mp3"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
277
AGENTS.md
Normal file
277
AGENTS.md
Normal file
@ -0,0 +1,277 @@
|
||||
# AGENTS.md
|
||||
|
||||
This file provides guidance to Codex (Codex.ai/code) when working with code in this repository.
|
||||
|
||||
## Project Overview
|
||||
|
||||
**Xpeditis** is a B2B SaaS maritime freight booking platform. Freight forwarders search and compare real-time shipping rates, book containers, and manage shipments. Monorepo with NestJS 10 backend (Hexagonal Architecture) and Next.js 14 frontend.
|
||||
|
||||
## Development Commands
|
||||
|
||||
All commands run from repo root unless noted otherwise.
|
||||
|
||||
```bash
|
||||
# Infrastructure (PostgreSQL 15 + Redis 7 + MinIO)
|
||||
docker-compose up -d
|
||||
|
||||
# Install all dependencies
|
||||
npm run install:all
|
||||
|
||||
# Environment setup (required on first run)
|
||||
cp apps/backend/.env.example apps/backend/.env
|
||||
cp apps/frontend/.env.example apps/frontend/.env
|
||||
|
||||
# Database migrations (from apps/backend/)
|
||||
cd apps/backend && npm run migration:run
|
||||
|
||||
# Development servers
|
||||
npm run backend:dev # http://localhost:4000, Swagger: /api/docs
|
||||
npm run frontend:dev # http://localhost:3000
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
```bash
|
||||
# Backend (from apps/backend/)
|
||||
npm test # Unit tests (Jest)
|
||||
npm test -- booking.entity.spec.ts # Single file
|
||||
npm test -- --testNamePattern="should create" # Filter by test name
|
||||
npm run test:cov # With coverage
|
||||
npm run test:integration # Integration tests (needs DB/Redis, 30s timeout)
|
||||
npm run test:e2e # E2E tests
|
||||
|
||||
# Frontend (from apps/frontend/)
|
||||
npm test
|
||||
npm run test:e2e # Playwright (chromium, firefox, webkit + mobile)
|
||||
|
||||
# From root
|
||||
npm run backend:test
|
||||
npm run frontend:test
|
||||
```
|
||||
|
||||
Backend test config is in `apps/backend/package.json` (Jest). Integration test config: `apps/backend/jest-integration.json` (covers infrastructure layer, setup in `test/setup-integration.ts`). Frontend E2E config: `apps/frontend/playwright.config.ts`.
|
||||
|
||||
### Linting, Formatting & Type Checking
|
||||
|
||||
```bash
|
||||
npm run backend:lint # ESLint backend
|
||||
npm run frontend:lint # ESLint frontend
|
||||
npm run format # Prettier (all files)
|
||||
npm run format:check # Check formatting
|
||||
# From apps/frontend/
|
||||
npm run type-check # TypeScript checking (frontend only)
|
||||
```
|
||||
|
||||
### Database Migrations
|
||||
|
||||
```bash
|
||||
cd apps/backend
|
||||
npm run migration:generate -- src/infrastructure/persistence/typeorm/migrations/MigrationName
|
||||
npm run migration:run
|
||||
npm run migration:revert
|
||||
```
|
||||
|
||||
### Build
|
||||
|
||||
```bash
|
||||
npm run backend:build # NestJS build with tsc-alias for path resolution
|
||||
npm run frontend:build # Next.js production build (standalone output)
|
||||
npm run clean # Remove all node_modules, dist, .next directories
|
||||
```
|
||||
|
||||
## Local Infrastructure
|
||||
|
||||
Docker-compose defaults (no `.env` changes needed for local dev):
|
||||
- **PostgreSQL**: `xpeditis:xpeditis_dev_password@localhost:5432/xpeditis_dev`
|
||||
- **Redis**: password `xpeditis_redis_password`, port 6379
|
||||
- **MinIO** (S3-compatible storage): `minioadmin:minioadmin`, API port 9000, console port 9001
|
||||
|
||||
Frontend env var: `NEXT_PUBLIC_API_URL` (defaults to `http://localhost:4000`) — configured in `next.config.js`.
|
||||
|
||||
## Architecture
|
||||
|
||||
### Hexagonal Architecture (Backend)
|
||||
|
||||
```
|
||||
apps/backend/src/
|
||||
├── domain/ # CORE - Pure TypeScript, NO framework imports
|
||||
│ ├── entities/ # Booking, RateQuote, Carrier, Port, Container, Notification, Webhook,
|
||||
│ │ # AuditLog, User, Organization, Subscription, License, CsvBooking,
|
||||
│ │ # CsvRate, InvitationToken
|
||||
│ ├── value-objects/ # Money, Email, BookingNumber, BookingStatus, PortCode, ContainerType,
|
||||
│ │ # Volume, DateRange, Surcharge
|
||||
│ ├── services/ # Pure domain services (csv-rate-price-calculator)
|
||||
│ ├── ports/
|
||||
│ │ ├── in/ # Use case interfaces with execute() method
|
||||
│ │ └── out/ # Repository/SPI interfaces (token constants like BOOKING_REPOSITORY = 'BookingRepository')
|
||||
│ └── exceptions/ # Domain-specific exceptions
|
||||
├── application/ # Controllers, DTOs (class-validator), Guards, Decorators, Mappers
|
||||
│ ├── [feature]/ # Feature modules: auth/, bookings/, csv-bookings, rates/, ports/,
|
||||
│ │ # organizations/, users/, dashboard/, audit/, notifications/, webhooks/,
|
||||
│ │ # gdpr/, admin/, subscriptions/
|
||||
│ ├── controllers/ # REST controllers (also nested under feature folders)
|
||||
│ ├── services/ # Application services: audit, notification, webhook,
|
||||
│ │ # booking-automation, export, fuzzy-search, brute-force-protection
|
||||
│ ├── gateways/ # WebSocket gateways (notifications.gateway.ts via Socket.IO)
|
||||
│ ├── guards/ # JwtAuthGuard, RolesGuard, CustomThrottlerGuard
|
||||
│ ├── decorators/ # @Public(), @Roles(), @CurrentUser()
|
||||
│ ├── dto/ # Request/response DTOs with class-validator
|
||||
│ ├── mappers/ # Domain ↔ DTO mappers
|
||||
│ └── interceptors/ # PerformanceMonitoringInterceptor
|
||||
└── infrastructure/ # TypeORM entities/repos/mappers, Redis cache, carrier APIs,
|
||||
# MinIO/S3, email (MJML+Nodemailer), Stripe, Sentry,
|
||||
# Pappers (French SIRET registry), PDF generation
|
||||
```
|
||||
|
||||
**Critical dependency rules**:
|
||||
- Domain layer: zero imports from NestJS, TypeORM, Redis, or any framework
|
||||
- Dependencies flow inward only: Infrastructure → Application → Domain
|
||||
- Path aliases: `@domain/*`, `@application/*`, `@infrastructure/*` (defined in `apps/backend/tsconfig.json`)
|
||||
- Domain tests run without NestJS TestingModule
|
||||
- Backend has strict TypeScript: `strict: true`, `strictNullChecks: true` (but `strictPropertyInitialization: false`)
|
||||
- Env vars validated at startup via Joi schema in `app.module.ts` — required vars include DATABASE_*, REDIS_*, JWT_SECRET, SMTP_*
|
||||
|
||||
### NestJS Modules (app.module.ts)
|
||||
|
||||
Global guards: JwtAuthGuard (all routes protected by default), CustomThrottlerGuard.
|
||||
|
||||
Feature modules: Auth, Rates, Ports, Bookings, CsvBookings, Organizations, Users, Dashboard, Audit, Notifications, Webhooks, GDPR, Admin, Subscriptions.
|
||||
|
||||
Infrastructure modules: CacheModule, CarrierModule, SecurityModule, CsvRateModule, StripeModule, PdfModule, StorageModule, EmailModule.
|
||||
|
||||
Swagger plugin enabled in `nest-cli.json` — DTOs auto-documented. Logging via `nestjs-pino` (pino-pretty in dev).
|
||||
|
||||
### Frontend (Next.js 14 App Router)
|
||||
|
||||
```
|
||||
apps/frontend/
|
||||
├── app/ # App Router pages (root-level)
|
||||
│ ├── dashboard/ # Protected routes (bookings, admin, settings, wiki, search)
|
||||
│ ├── carrier/ # Carrier portal (magic link auth — accept/reject/documents)
|
||||
│ ├── booking/ # Booking confirmation/rejection flows
|
||||
│ └── [auth pages] # login, register, forgot-password, verify-email
|
||||
└── src/
|
||||
├── app/ # Additional app pages (e.g. rates/csv-search)
|
||||
├── components/ # React components (ui/, layout/, bookings/, admin/, rate-search/, organization/)
|
||||
├── hooks/ # useBookings, useNotifications, useCsvRateSearch, useCompanies, useFilterOptions
|
||||
├── lib/
|
||||
│ ├── api/ # Fetch-based API client with auto token refresh (client.ts + per-module files)
|
||||
│ ├── context/ # Auth context, cookie context
|
||||
│ ├── providers/ # QueryProvider (TanStack Query / React Query)
|
||||
│ └── fonts.ts # Manrope (headings) + Montserrat (body)
|
||||
├── types/ # TypeScript type definitions
|
||||
├── utils/ # Export utilities (Excel, PDF)
|
||||
└── legacy-pages/ # Archived page components (BookingsManagement, CarrierManagement, CarrierMonitoring)
|
||||
```
|
||||
|
||||
Path aliases: `@/*` → `./src/*`, `@/components/*`, `@/lib/*`, `@/app/*` → `./app/*`, `@/types/*`, `@/hooks/*`, `@/utils/*`
|
||||
|
||||
**Note**: Frontend tsconfig has `strict: false`, `noImplicitAny: false`, `strictNullChecks: false` (unlike backend which is strict). Uses TanStack Query (React Query) for server state — wrap new data fetching in hooks, not bare `fetch` calls.
|
||||
|
||||
### Brand Design
|
||||
|
||||
Colors: Navy `#10183A` (primary), Turquoise `#34CCCD` (accent), Green `#067224` (success), Gray `#F2F2F2`.
|
||||
Fonts: Manrope (headings), Montserrat (body).
|
||||
Landing page is in French.
|
||||
|
||||
## Key Patterns
|
||||
|
||||
### Entity Pattern (Domain)
|
||||
Private constructor + static `create()` factory. Immutable — mutation methods return new instances. Some entities also have `fromPersistence()` for reconstitution and `toObject()` for serialization.
|
||||
```typescript
|
||||
export class Booking {
|
||||
private readonly props: BookingProps;
|
||||
static create(props: Omit<BookingProps, 'bookingNumber' | 'status'>): Booking { ... }
|
||||
updateStatus(newStatus: BookingStatus): Booking { // Returns new instance
|
||||
return new Booking({ ...this.props, status: newStatus });
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Value Object Pattern
|
||||
Immutable, self-validating via static `create()`. E.g. `Money` supports USD, EUR, GBP, CNY, JPY with arithmetic and formatting methods.
|
||||
|
||||
### Repository Pattern
|
||||
- Interface in `domain/ports/out/` with token constant (e.g. `BOOKING_REPOSITORY = 'BookingRepository'`)
|
||||
- Implementation in `infrastructure/persistence/typeorm/repositories/`
|
||||
- ORM entities: `infrastructure/persistence/typeorm/entities/*.orm-entity.ts`
|
||||
- Separate mapper classes (`infrastructure/persistence/typeorm/mappers/`) with static `toOrm()`, `toDomain()`, `toDomainMany()` methods
|
||||
|
||||
### Frontend API Client
|
||||
Custom Fetch wrapper in `src/lib/api/client.ts` — exports `get()`, `post()`, `patch()`, `del()`, `upload()`, `download()`. Auto-refreshes JWT on 401. Tokens stored in localStorage **and synced to cookies** (`accessToken` cookie) so Next.js middleware can read them server-side. Per-module files (auth.ts, bookings.ts, rates.ts, etc.) import from client.
|
||||
|
||||
### Route Protection (Middleware)
|
||||
`apps/frontend/middleware.ts` checks the `accessToken` cookie to protect routes. Public paths are defined in two lists:
|
||||
- `exactPublicPaths`: exact matches (e.g. `/`)
|
||||
- `prefixPublicPaths`: prefix matches including sub-paths (e.g. `/login`, `/carrier`, `/about`, etc.)
|
||||
|
||||
All other routes redirect to `/login?redirect=<pathname>` when the cookie is absent.
|
||||
|
||||
### Application Decorators
|
||||
- `@Public()` — skip JWT auth
|
||||
- `@Roles()` — role-based access control
|
||||
- `@CurrentUser()` — inject authenticated user
|
||||
|
||||
### API Key Authentication
|
||||
A second auth mechanism alongside JWT. `ApiKey` domain entity (`domain/entities/api-key.entity.ts`) — keys are hashed with Argon2. `ApiKeyGuard` in `application/guards/` checks the `x-api-key` header. Routes can accept either JWT or API key; see `admin.controller.ts` for examples.
|
||||
|
||||
### WebSocket (Real-time Notifications)
|
||||
Socket.IO gateway at `application/gateways/notifications.gateway.ts`. Clients connect to `/` namespace with a JWT bearer token in the handshake auth. Server emits `notification` events. The frontend `useNotifications` hook handles subscriptions.
|
||||
|
||||
### Carrier Connectors
|
||||
Five carrier connectors (Maersk, MSC, CMA CGM, Hapag-Lloyd, ONE) extending `base-carrier.connector.ts`, each with request/response mappers. Circuit breaker via `opossum` (5s timeout).
|
||||
|
||||
### Caching
|
||||
Redis with 15-min TTL for rate quotes. Key format: `rate:{origin}:{destination}:{containerType}`.
|
||||
|
||||
## Business Rules
|
||||
|
||||
- Booking number format: `WCM-YYYY-XXXXXX`
|
||||
- Booking status flow: draft → confirmed → shipped → delivered
|
||||
- Rate quotes expire after 15 minutes
|
||||
- Multi-currency: USD, EUR, GBP, CNY, JPY
|
||||
- RBAC Roles: ADMIN, MANAGER, USER, VIEWER, CARRIER
|
||||
- JWT: access token 15min, refresh token 7d
|
||||
- Password hashing: Argon2
|
||||
- OAuth providers: Google, Microsoft (configured via passport strategies)
|
||||
- Organizations can be validated via Pappers API (French SIRET/company registry) at `infrastructure/external/pappers-siret.adapter.ts`
|
||||
|
||||
### Carrier Portal Workflow
|
||||
1. Admin creates CSV booking → assigns carrier
|
||||
2. Email with magic link sent (1-hour expiry)
|
||||
3. Carrier auto-login → accept/reject booking
|
||||
4. Activity logged in `carrier_activities` table (via `CarrierProfile` + `CarrierActivity` ORM entities)
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
- Never import NestJS/TypeORM in domain layer
|
||||
- Never use `any` type in backend (strict mode enabled)
|
||||
- Never modify applied migrations — create new ones
|
||||
- Always validate DTOs with `class-validator` decorators
|
||||
- Always create separate mappers for Domain ↔ ORM conversions
|
||||
- ORM entity files must match pattern `*.orm-entity.{ts,js}` (auto-discovered by data-source)
|
||||
- Migration files must be in `infrastructure/persistence/typeorm/migrations/`
|
||||
- Database synchronize is hard-coded to `false` — always use migrations
|
||||
|
||||
## Adding a New Feature
|
||||
|
||||
1. **Domain Entity** → `domain/entities/*.entity.ts` (pure TS, unit tests)
|
||||
2. **Value Objects** → `domain/value-objects/*.vo.ts` (immutable)
|
||||
3. **In Port (Use Case)** → `domain/ports/in/*.use-case.ts` (interface with `execute()`)
|
||||
4. **Out Port (Repository)** → `domain/ports/out/*.repository.ts` (with token constant)
|
||||
5. **ORM Entity** → `infrastructure/persistence/typeorm/entities/*.orm-entity.ts`
|
||||
6. **Migration** → `npm run migration:generate -- src/infrastructure/persistence/typeorm/migrations/MigrationName`
|
||||
7. **Repository Impl** → `infrastructure/persistence/typeorm/repositories/`
|
||||
8. **Mapper** → `infrastructure/persistence/typeorm/mappers/` (static toOrm/toDomain/toDomainMany)
|
||||
9. **DTOs** → `application/dto/` (with class-validator decorators)
|
||||
10. **Controller** → `application/controllers/` (with Swagger decorators)
|
||||
11. **Module** → Register repository + use-case providers, import in `app.module.ts`
|
||||
|
||||
## Documentation
|
||||
|
||||
- API Docs: http://localhost:4000/api/docs (Swagger, when running)
|
||||
- Setup guide: `docs/installation/START-HERE.md`
|
||||
- Carrier Portal API: `apps/backend/docs/CARRIER_PORTAL_API.md`
|
||||
- Full docs index: `docs/README.md`
|
||||
- Development roadmap: `TODO.md`
|
||||
- Infrastructure configs (CI/CD, Docker): `infra/`
|
||||
@ -607,9 +607,7 @@ export class CsvRatesAdminController {
|
||||
// company's other grid (export vs import) would be deleted too.
|
||||
await this.csvConfigRepository.delete(config.companyName, config.direction);
|
||||
|
||||
this.logger.log(
|
||||
`Deleted CSV config and file for: ${config.companyName} (${config.direction})`
|
||||
);
|
||||
this.logger.log(`Deleted CSV config and file for: ${config.companyName} (${config.direction})`);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
|
||||
@ -326,9 +326,7 @@ export class RatesController {
|
||||
status: 401,
|
||||
description: 'Unauthorized - missing or invalid token',
|
||||
})
|
||||
async getAvailableOrigins(
|
||||
@Query('direction') direction?: string
|
||||
): Promise<AvailableOriginsDto> {
|
||||
async getAvailableOrigins(@Query('direction') direction?: string): Promise<AvailableOriginsDto> {
|
||||
this.logger.log(
|
||||
`Fetching available origin ports from CSV rates${direction ? ` (${direction})` : ''}`
|
||||
);
|
||||
|
||||
@ -12,7 +12,10 @@ const customConfig = {
|
||||
],
|
||||
testPathIgnorePatterns: ['<rootDir>/node_modules/', '<rootDir>/.next/', '<rootDir>/e2e/'],
|
||||
moduleNameMapper: {
|
||||
// Ces deux alias ne pointent pas vers `src/` : ils doivent precede la regle
|
||||
// generique, sans quoi `@/i18n/navigation` est cherche dans `src/i18n`.
|
||||
'^@/app/(.*)$': '<rootDir>/app/$1',
|
||||
'^@/i18n/(.*)$': '<rootDir>/i18n/$1',
|
||||
'^@/(.*)$': '<rootDir>/src/$1',
|
||||
},
|
||||
};
|
||||
|
||||
@ -20,15 +20,15 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"@/*": ["./src/*"],
|
||||
"@/app/*": ["./app/*"],
|
||||
"@/i18n/*": ["./i18n/*"],
|
||||
"@/components/*": ["./src/components/*"],
|
||||
"@/lib/*": ["./src/lib/*"],
|
||||
"@/app/*": ["./app/*"],
|
||||
"@/types/*": ["./src/types/*"],
|
||||
"@/hooks/*": ["./src/hooks/*"],
|
||||
"@/utils/*": ["./src/utils/*"],
|
||||
"@/pages/*": ["./src/pages/*"],
|
||||
"@/i18n/*": ["./i18n/*"]
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||
|
||||
@ -60,14 +60,30 @@ Expiry : 1 heure. Si expiré, l'admin doit renvoyer un nouveau lien.
|
||||
|
||||
## Statuts des réservations CSV
|
||||
|
||||
Valeurs réelles de l'énumération `CsvBookingStatus` (`domain/entities/csv-booking.entity.ts`) :
|
||||
|
||||
| Statut | Description |
|
||||
|--------|-------------|
|
||||
| pending | En attente d'assignation carrier |
|
||||
| sent | Lien magique envoyé au carrier |
|
||||
| accepted | Carrier a accepté |
|
||||
| rejected | Carrier a refusé |
|
||||
| in_transit | En cours de transport |
|
||||
| delivered | Livré |
|
||||
| PENDING_PAYMENT | Réservation créée, commission non payée |
|
||||
| PENDING_BANK_TRANSFER | Virement déclaré, en attente de validation par l'administration |
|
||||
| PENDING | Commission payée, en attente de réponse du transporteur |
|
||||
| ACCEPTED | Le transporteur a accepté |
|
||||
| REJECTED | Le transporteur a refusé |
|
||||
| CANCELLED | Annulée par l'utilisateur |
|
||||
|
||||
---
|
||||
|
||||
## Suppression d'une réservation impayée
|
||||
|
||||
`DELETE /api/v1/csv-bookings/:id` supprime définitivement une réservation **dont la commission n'a pas été payée**, c'est-à-dire au seul statut `PENDING_PAYMENT`. Seul le propriétaire peut le faire ; une réservation appartenant à quelqu'un d'autre répond `404`, sans se distinguer d'une réservation inexistante.
|
||||
|
||||
Une fois la commission payée, la réservation est partie chez le transporteur et porte une trace comptable : elle ne peut plus qu'être **annulée** (`PATCH :id/cancel`), jamais effacée. L'API répond alors `400`.
|
||||
|
||||
`PENDING_BANK_TRANSFER` est volontairement exclu : le virement déclaré peut être en cours d'acheminement, et supprimer la réservation priverait l'administration de ce qu'elle doit rapprocher à sa réception. Étendre la règle à ce statut est une décision comptable, pas technique — il suffit d'ajouter le statut à `DELETABLE_STATUSES` dans l'entité.
|
||||
|
||||
Les documents déjà téléversés restent dans le stockage objet, conformément à la politique appliquée à la suppression d'un document isolé (conservation pour l'audit). Le quota de réservations n'est pas affecté : il ne compte que les expéditions payées.
|
||||
|
||||
Côté interface, l'action « Supprimer » n'apparaît dans le menu d'une ligne que pour les réservations impayées, à côté de « Modifier » et « Payer ». Elle demande une confirmation qui nomme la réservation concernée.
|
||||
|
||||
---
|
||||
|
||||
@ -75,6 +91,7 @@ Expiry : 1 heure. Si expiré, l'admin doit renvoyer un nouveau lien.
|
||||
|
||||
| Route | Description |
|
||||
|-------|-------------|
|
||||
| /dashboard/bookings | Liste des réservations (voir, modifier, payer, supprimer) |
|
||||
| /dashboard/csv-bookings | Liste admin des réservations CSV |
|
||||
| /carrier/auth | Page d'auth carrier (via magic link) |
|
||||
| /carrier/booking | Dashboard carrier (accept/reject) |
|
||||
|
||||
Loading…
Reference in New Issue
Block a user