xpeditis2.0/apps/backend
David aeb3d2a75d
Some checks failed
CI/CD Pipeline / Backend - Build, Test & Push (push) Failing after 1m33s
CI/CD Pipeline / Frontend - Build, Test & Push (push) Has been cancelled
CI/CD Pipeline / Integration Tests (push) Blocked by required conditions
CI/CD Pipeline / Deployment Summary (push) Blocked by required conditions
CI/CD Pipeline / Discord Notification (Success) (push) Blocked by required conditions
CI/CD Pipeline / Discord Notification (Failure) (push) Blocked by required conditions
fix: use company name from form instead of CSV column
Fixed CSV rate upload to use the company name provided in the upload form instead of reading it from the CSV file's companyName column. This prevents "unknown" or incorrect company names from being used.

## Changes

**Domain Layer**
- Updated `CsvRateLoaderPort` interface to accept optional `companyNameOverride` parameter
- Modified `CsvRateSearchService.loadAllRates()` to pass company name from config when loading rates

**Infrastructure Layer**
- Updated `CsvRateLoaderAdapter.loadRatesFromCsv()` to accept `companyNameOverride` parameter
- Modified `mapToCsvRate()` to use override company name if provided, otherwise fallback to CSV column value
- Added logging to show which company name is being used (from override or CSV)

**Application Layer**
- Updated CSV upload controller to pass `dto.companyName` to the loader

## Impact
- When uploading a CSV file through the admin interface, the company name from the form is now correctly used
- Existing CSV files with "unknown" in the companyName column will now show the correct company name from the database configuration
- Backward compatible: if no override is provided, the CSV column value is still used

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 19:53:45 +01:00
..
docs feature fix 2025-10-20 12:30:08 +02:00
load-tests feature 2025-11-04 07:30:15 +01:00
postman feat: Phase 4 - Production-ready security, monitoring & testing infrastructure 2025-10-14 18:46:18 +02:00
src fix: use company name from form instead of CSV column 2025-11-17 19:53:45 +01:00
test fix 2025-11-12 19:08:35 +01:00
.dockerignore fix 2025-10-15 15:14:49 +02:00
.env.example feature phase 3 2025-10-13 13:58:39 +02:00
.eslintrc.js fix 2025-11-12 19:35:13 +01:00
apps.zip ci 2025-11-17 01:03:42 +01:00
DATABASE-SCHEMA.md feature fix 2025-10-20 12:30:08 +02:00
docker-compose.yaml feature fix 2025-10-20 12:30:08 +02:00
Dockerfile ci 2025-11-17 01:58:50 +01:00
fix-domain-imports.js fix: replace relative domain imports with TypeScript path aliases 2025-11-16 19:31:37 +01:00
fix-imports.js fix: replace relative domain imports with TypeScript path aliases 2025-11-16 19:20:58 +01:00
nest-cli.json fix: configure nest build to use tsc compiler directly 2025-11-17 01:46:57 +01:00
package.json fix: configure nest build to use tsc compiler directly 2025-11-17 01:46:57 +01:00
README.md first commit 2025-10-07 18:39:32 +02:00
test-csv-api.js feature 2025-11-04 07:30:15 +01:00
test-csv-api.sh feature csv done 2025-10-24 16:01:09 +02:00
tsconfig.build.json fix: configure nest build to use tsc compiler directly 2025-11-17 01:46:57 +01:00
tsconfig.json fix: use tsc directly instead of nest build to resolve path aliases 2025-11-17 01:41:28 +01:00
tsconfig.test.json fix preprod 2025-11-12 18:10:52 +01:00

Xpeditis Backend API

NestJS-based API for the Xpeditis maritime freight booking platform, built with Hexagonal Architecture.

🏗️ Architecture

This backend follows Hexagonal Architecture (Ports & Adapters pattern):

src/
├── domain/              # 🔵 Pure business logic (NO external dependencies)
│   ├── entities/       # Business entities
│   ├── value-objects/  # Value objects (Email, PortCode, etc.)
│   ├── services/       # Domain services
│   ├── ports/
│   │   ├── in/        # API Ports (use cases exposed by domain)
│   │   └── out/       # SPI Ports (interfaces required by domain)
│   └── exceptions/    # Business exceptions
│
├── application/         # 🟢 Controllers & DTOs
│   ├── controllers/    # REST controllers
│   ├── dto/           # Data Transfer Objects
│   ├── mappers/       # DTO ↔ Domain mappers
│   └── config/        # Application configuration
│
└── infrastructure/      # 🟡 External integrations
    ├── persistence/    # TypeORM repositories
    ├── cache/         # Redis cache adapter
    ├── carriers/      # Maersk, MSC, CMA CGM connectors
    ├── email/         # Email service adapter
    ├── storage/       # S3 storage adapter
    └── config/        # Infrastructure configuration

Key Principles

  1. Domain is isolated: No imports of NestJS, TypeORM, or any framework in domain layer
  2. Dependencies point inward: Infrastructure → Application → Domain
  3. Testable: Domain can be tested without any framework
  4. Flexible: Change database, framework, or external services without touching domain

🚀 Quick Start

Prerequisites

  • Node.js 20+
  • PostgreSQL 15+
  • Redis 7+
  • Docker (optional, for local development)

Install Dependencies

npm install

Setup Environment

cp .env.example .env
# Edit .env with your configuration

Start Development Server

npm run dev

Server runs on: http://localhost:4000

API Documentation: http://localhost:4000/api/docs

📝 Available Scripts

Development

  • npm run dev - Start development server with hot reload
  • npm run start - Start server
  • npm run start:debug - Start with debugging
  • npm run build - Build for production
  • npm run start:prod - Start production server

Testing

  • npm test - Run unit tests
  • npm run test:watch - Run tests in watch mode
  • npm run test:cov - Run tests with coverage
  • npm run test:e2e - Run end-to-end tests
  • npm run test:debug - Debug tests

Code Quality

  • npm run lint - Lint code
  • npm run format - Format code with Prettier

Database

  • npm run migration:generate -- src/infrastructure/persistence/migrations/MigrationName - Generate migration
  • npm run migration:run - Run migrations
  • npm run migration:revert - Revert last migration

🔑 Environment Variables

See .env.example for all available variables.

Required:

  • DATABASE_HOST, DATABASE_PORT, DATABASE_USER, DATABASE_PASSWORD, DATABASE_NAME
  • REDIS_HOST, REDIS_PORT, REDIS_PASSWORD
  • JWT_SECRET

Optional (for production):

  • OAuth credentials (Google, Microsoft)
  • Carrier API keys (Maersk, MSC, CMA CGM, etc.)
  • AWS S3 credentials
  • Email service credentials
  • Sentry DSN

📚 API Documentation

Swagger/OpenAPI documentation is available at /api/docs when the server is running.

Endpoints:

Health

  • GET /api/v1/health - Health check
  • GET /api/v1/health/ready - Readiness check
  • GET /api/v1/health/live - Liveness check

(More endpoints will be added in Phase 1)

🧪 Testing

Unit Tests

Test domain logic without any external dependencies:

npm test

Example (domain/services/booking.service.spec.ts):

describe('BookingService', () => {
  it('should create booking with valid rate quote', () => {
    const service = new BookingService(mockRepository);
    const result = service.createBooking(validInput);
    expect(result.bookingNumber).toMatch(/^WCM-\d{4}-[A-Z0-9]{6}$/);
  });
});

Integration Tests

Test infrastructure adapters with real dependencies:

npm run test:e2e

Coverage

npm run test:cov

Targets:

  • Domain: 90%+
  • Application: 80%+
  • Infrastructure: 70%+

🏛️ Hexagonal Architecture Guidelines

DO

  • Domain layer:

    • Pure TypeScript classes
    • Define interfaces (ports)
    • Implement business logic
    • Throw domain exceptions
  • Application layer:

    • Import from @domain/* only
    • Validate DTOs
    • Map DTOs ↔ Domain entities
    • Handle HTTP-specific concerns
  • Infrastructure layer:

    • Import from @domain/* only
    • Implement port interfaces
    • Handle framework-specific code
    • Map ORM entities ↔ Domain entities

DON'T

  • Import NestJS decorators in domain
  • Import TypeORM in domain
  • Put business logic in controllers
  • Put business logic in repositories
  • Use any type
  • Skip tests

🔒 Security

  • Passwords hashed with bcrypt (12 rounds)
  • JWT tokens (access: 15min, refresh: 7 days)
  • Helmet.js for security headers
  • CORS configured
  • Rate limiting enabled
  • Input validation with class-validator
  • SQL injection prevention (TypeORM)
  • XSS protection

📊 Logging

Using Pino logger with structured JSON logs.

Log levels:

  • Development: debug
  • Production: info

Pretty print in development with pino-pretty.

🚢 Carrier Integrations

MVP supports these carriers:

  • Maersk
  • MSC
  • CMA CGM
  • Hapag-Lloyd
  • ONE (Ocean Network Express)

Each connector implements CarrierConnectorPort with:

  • Circuit breaker (5s timeout)
  • Retry logic
  • Rate limiting
  • Error normalization

📖 Further Reading

🤝 Contributing

  1. Follow hexagonal architecture principles
  2. Write tests (domain: 90%+, application: 80%+)
  3. Use TypeScript strict mode
  4. Format with Prettier
  5. Lint with ESLint
  6. Document API with Swagger decorators

📝 License

Proprietary - All rights reserved


Built with ❤️ using NestJS and Hexagonal Architecture