From 812441a9e0434d335b385aa2e2305e2dae451e2d Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 18 Mar 2025 10:56:55 +0100 Subject: [PATCH] Add comprehensive API documentation for LCC backend This commit introduces a detailed README file outlining the LCC Backend API, including endpoint descriptions, request/response formats, and authentication methods. It covers various domains such as system configuration, transport rates, user management, calculations, and reporting. This documentation aims to assist developers in understanding and utilizing the API effectively. --- readme.md | 1708 +++++++++++++++++++++++++++++++++ src/main/resources/schema.sql | 170 ++-- 2 files changed, 1800 insertions(+), 78 deletions(-) create mode 100644 readme.md diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..1cd214d --- /dev/null +++ b/readme.md @@ -0,0 +1,1708 @@ +# LCC Backend API Documentation + +**API Version:** v1.0 +**Last Updated:** March 16, 2025 + +## Table of Contents + +1. [Overview API](#overview-api) +2. [Authentication](#authentication) +3. [Request and Response Conventions](#request-and-response-conventions) +4. [System Configuration Endpoints](#system-configuration-endpoints) +5. [Transportation Rate Endpoints](#transportation-rate-endpoints) +6. [User Management Endpoints](#user-management-endpoints) +7. [Calculation Endpoints](#calculation-endpoints) +8. [Reporting Endpoints](#reporting-endpoints) +9. [Glossary](#glossary) + +## Overview API + +This document provides a comprehensive description of the LCC Backend API endpoints, their functionality, parameters, and response formats. The API is structured around several core domains: System Configuration, Transportation Rates, User Management, and Calculation. + +## Authentication + +### Authentication Methods + +The LCC API uses two primary authentication methods: + +1. **Pre-Shared Key (PSK)** \- Required for administrative endpoints such as User Management +2. **Session-based Authentication** \- Standard user authentication for most operations + +#### Pre-Shared Key Authentication + +For endpoints that require PSK authentication, include the following header in your request: + +```javascript +Authorization: PSK your_psk_here +``` + +Contact your system administrator to obtain a valid PSK. + +#### Session-based Authentication + +Most API endpoints require a valid session, which can be obtained by authenticating through the organization's identity provider. + +## Request and Response Conventions + +### Common Response Format + +All API responses follow a consistent structure. + +#### Success Response + +- HTTP Status Code: 200 OK +- Response Body: Varies by endpoint (details provided in specific endpoint documentation) + +#### Error Response + +- HTTP Status Code: Varies (400, 401, 403, 404, 500, etc.) +- Response Body: + +```javascript +{ + "error": { + "code": "ERROR_CODE", + "message": "User-friendly message", + "details": { } + } +} +``` + +### Common HTTP Status Codes + +| Status Code | Description | +| :---- | :---- | +| 200 | Success | +| 400 | Bad Request (client error) | +| 401 | Unauthorized (authentication required) | +| 403 | Forbidden (insufficient permissions) | +| 404 | Resource Not Found | +| 409 | Conflict (e.g., resource already exists) | +| 500 | Internal Server Error | + +### Pagination + +Endpoints that return lists of resources support pagination using the following query parameters: + +- `limit`: Maximum number of items to return (default: 20, maximum: 100\) +- `offset`: Number of items to skip for pagination (default: 0\) + +Example: `/api/materials?limit=20&offset=40` will return items 41-60. + +Pagination metadata is included in the response header: + +```javascript +X-Total-Count: 243 +X-Page-Count: 13 +X-Current-Page: 3 +``` + +## System Configuration Endpoints {#system-configuration-endpoints} + +### Bulk Operations + +#### Upload Template Data + +- **URL**: `/api/bulk/upload/{$type}` +- **Method**: POST +- **Description**: Uploads a filled-out template for batch processing +- **Path Parameters**: + - `$type`: The type of data being uploaded (valid values: `container_rate`, `country_matrix`, `material`, `packaging`, `node`) +- **Response**: Returns a processing ID for status tracking + +#### Get Template + +- **URL**: `/api/bulk/templates/{$type}` +- **Method**: GET +- **Description**: Returns a template for the specified data type +- **Path Parameters**: + - `$type`: The template type (valid values: `container_rate`, `country_matrix`, `material`, `packaging`, `node`) + +#### Check Processing Status + +- **URL**: `/api/bulk/status/{$processing_id}` +- **Method**: GET +- **Description**: Returns the processing status of a bulk upload +- **Path Parameters**: + - `$processing_id`: The ID returned from a bulk upload request + +### Materials Management + +#### List Materials + +- **URL**: `/api/materials/` +- **Method**: GET +- **Description**: Returns a list of all materials +- **Query Parameters**: + - `limit`: Maximum number of items to return (default: 20\) + - `offset`: Number of items to skip (for pagination) +- **Response Format**: + +```javascript +[ + { + "id": "string", + "part_number": "string", + "name": "string" + }, + ... +] +``` + +#### Get Material Details + +- **URL**: `/api/materials/{id}` +- **Method**: GET +- **Description**: Returns detailed information about a specific material +- **Path Parameters**: + - `id`: Material ID +- **Response Format**: + +```javascript +{ + "id": "string", + "part_number": "string", + "name": "string", + "hs_code": "string", + "handling_units": [ + { + "id": "string", + "supplier_name": "string", + "parent_id": "string", + "length": "number", + "width": "number", + "height": "number", + "dimension_unit": "string", + "weight": "number", + "weight_unit": "string", + "content_unit_count": "number" + }, + ... + ] +} +``` + +#### Update Material + +- **URL**: `/api/materials/{id}` +- **Method**: PUT +- **Description**: Updates the material with the specified ID +- **Path Parameters**: + - `id`: Material ID + +#### Delete Material + +- **URL**: `/api/materials/{id}` +- **Method**: DELETE +- **Description**: Sets the material to deprecated (soft delete) +- **Path Parameters**: + - `id`: Material ID + +### Packaging Management + +#### List Packagings + +- **URL**: `/api/packaging/` +- **Method**: GET +- **Description**: Returns a list of all packagings (handling units) +- **Query Parameters**: + - `limit`: Maximum number of items to return (default: 20\) + - `offset`: Number of items to skip (for pagination) + - `supplier`: Filter by supplier ID + - `material`: Filter by material ID +- **Response Format**: + +```javascript +[ + { + "id": "string", + "supplier_name": "string", + "part_number": "string", + "material_name": "string", + "length": "number", + "width": "number", + "height": "number", + "dimension_unit": "string", + "weight": "number", + "weight_unit": "string", + "content_unit_count": "number" + }, + ... +] +``` + +#### Get Packaging Details + +- **URL**: `/api/packaging/{id}` +- **Method**: GET +- **Description**: Returns detailed information about a specific packaging +- **Path Parameters**: + - `id`: Packaging ID +- **Response Format**: + +```javascript +{ + "id": "string", + "supplier": { + "id": "string", + "country": { + "id": "string", + "iso_code": "string", + "region_code": "string" + }, + "name": "string", + "address": "string" + }, + "material": { + "id": "string", + "part_number": "string", + "name": "string", + "hs_code": "string" + }, + "handling_unit": { + "length": "number", + "width": "number", + "height": "number", + "dimension_unit": "string", + "weight": "number", + "weight_unit": "string", + "content_unit_count": "number" + }, + "small_handling_unit": { + "length": "number", + "width": "number", + "height": "number", + "dimension_unit": "string", + "weight": "number", + "weight_unit": "string", + "content_unit_count": "number" + } +} +``` + +#### Update Packaging + +- **URL**: `/api/packaging/{id}` +- **Method**: PUT +- **Description**: Updates the packaging with the specified ID +- **Path Parameters**: + - `id`: Packaging ID + +#### Delete Packaging + +- **URL**: `/api/packaging/{id}` +- **Method**: DELETE +- **Description**: Sets the packaging to deprecated (soft delete) +- **Path Parameters**: + - `id`: Packaging ID + +### Country Management + +#### List Countries + +- **URL**: `/api/country/` +- **Method**: GET +- **Description**: Returns a list of all countries +- **Query Parameters**: + - `limit`: Maximum number of items to return (default: 20\) + - `offset`: Number of items to skip (for pagination) +- **Response Format**: + +```javascript +[ + { + "id": "string", + "iso_code": "string", + "name": "string", + "region_code": "string" + }, + ... +] +``` + +#### Get Country Details + +- **URL**: `/api/country/{id}` +- **Method**: GET +- **Description**: Returns detailed information about a specific country +- **Path Parameters**: + - `id`: Country ID +- **Response Format**: + +```javascript +{ + "id": "string", + "iso_code": "string", + "name": "string", + "region_code": "string", + "properties": [ + { + "id": "string", + "mapping_id": "string", + "name": "string", + "datatype": "string", + "current_value": "any", + "draft_value": "any", + "is_required": "boolean" + }, + ... + ] +} +``` + +#### Update Country + +- **URL**: `/api/country/{id}` +- **Method**: PUT +- **Description**: Updates the country with the specified ID +- **Path Parameters**: + - `id`: Country ID + +#### Delete Country + +- **URL**: `/api/country/{id}` +- **Method**: DELETE +- **Description**: Sets the country to deprecated (soft delete) +- **Path Parameters**: + - `id`: Country ID + +### System Properties Management + +#### List System Properties + +- **URL**: `/api/properties/system/` +- **Method**: GET +- **Description**: Returns property set including properties +- **Query Parameters**: + - `limit`: Maximum number of items to return (default: 20\) + - `offset`: Number of items to skip (for pagination) +- **Response Format**: + +```javascript +[ + { + "id": "string", + "mapping_id": "string", + "name": "string", + "data_type": "string", + "current_value": "any", + "draft_value": "any" + }, + ... +] +``` + +#### Get System Property Details + +- **URL**: `/api/properties/system/{id}` +- **Method**: GET +- **Description**: Returns detailed information about a specific system property +- **Path Parameters**: + - `id`: Property ID +- **Response Format**: + +```javascript +{ + "id": "string", + "mapping_id": "string", + "name": "string", + "data_type": "string", + "current_value": "any", + "draft_value": "any" +} +``` + +#### Update System Property + +- **URL**: `/api/properties/system/{id}` +- **Method**: PUT +- **Description**: Updates the system property with the specified ID +- **Path Parameters**: + - `id`: Property ID + +#### List Property Types + +- **URL**: `/api/properties/types/{$system_part}/` +- **Method**: GET +- **Description**: Returns a list of all property types for the specified system part +- **Path Parameters**: + - `$system_part`: The system part to get properties for (valid values: `system`, `packaging`, `country`) +- **Query Parameters**: + - `limit`: Maximum number of items to return (default: 20\) + - `offset`: Number of items to skip (for pagination) +- **Response Format**: + +```javascript +[ + { + "id": "string", + "mapping_id": "string", + "name": "string", + "data_type": "string" + }, + ... +] +``` + +#### Create Property Type + +- **URL**: `/api/properties/types/{$system_part}/` +- **Method**: PUT +- **Description**: Creates a new system property type +- **Path Parameters**: + - `$system_part`: The system part to create a property for (valid values: `system`, `packaging`, `country`) + +#### Get Property Type Details + +- **URL**: `/api/properties/types/{$system_part}/{id}` +- **Method**: GET +- **Description**: Returns detailed information about a specific property type +- **Path Parameters**: + - `$system_part`: System part (valid values: `system`, `packaging`, `country`) + - `id`: Property type ID +- **Response Format**: + +```javascript +{ + "id": "string", + "mapping_id": "string", + "name": "string", + "data_type": "string" +} +``` + +#### Update Property Type + +- **URL**: `/api/properties/types/{$system_part}/{id}` +- **Method**: PUT +- **Description**: Updates the property type with the specified ID +- **Path Parameters**: + - `$system_part`: System part (valid values: `system`, `packaging`, `country`) + - `id`: Property type ID + +#### Check Staged Property Changes + +- **URL**: `/api/properties/staged_changes/` +- **Method**: GET +- **Description**: Returns true if there are any unapproved "drafts" properties, false otherwise + +#### Approve Property Changes + +- **URL**: `/api/properties/staged_changes/` +- **Method**: PUT +- **Description**: Approves drafts and sets current "draft" properties to current valid properties + +### Node Management + +#### List Nodes + +- **URL**: `/api/nodes/` +- **Method**: GET +- **Description**: Returns a list of all active nodes (with deprecated \= false) +- **Query Parameters**: + - `limit`: Maximum number of items to return (default: 20\) + - `offset`: Number of items to skip (for pagination) + - `filter`: Search text to filter nodes +- **Response Format**: + +```javascript +[ + { + "id": "string", + "country": { + "id": "string", + "iso_code": "string", + "region_code": "string", + "name": "string" + }, + "address": "string", + "location": { + "longitude": "number", + "latitude": "number" + }, + "types": ["sink", "source", "intermediate"] + }, + ... +] +``` + +#### Get Node Details + +- **URL**: `/api/nodes/{$id}` +- **Method**: GET +- **Description**: Returns detailed information about a specific node +- **Path Parameters**: + - `$id`: Node ID +- **Response Format**: + +```javascript +{ + "id": "string", + "country": { + "id": "string", + "iso_code": "string", + "region_code": "string", + "name": "string" + }, + "name": "string", + "address": "string", + "location": { + "longitude": "number", + "latitude": "number" + }, + "types": ["sink", "source", "intermediate"], + "predecessors": { + "1": { + "id": "string", + "country": { + "id": "string", + "iso_code": "string", + "region_code": "string", + "name": "string" + }, + "name": "string", + "address": "string", + "location": { + "longitude": "number", + "latitude": "number" + } + }, + "2": { ... } + }, + "outbound_countries": [ + { + "id": "string", + "iso_code": "string", + "region_code": "string", + "name": "string" + }, + ... + ] +} +``` + +#### Update Node + +- **URL**: `/api/nodes/{$id}` +- **Method**: PUT +- **Description**: Updates the node with the specified ID +- **Path Parameters**: + - `$id`: Node ID + +#### Delete Node + +- **URL**: `/api/nodes/{$id}` +- **Method**: DELETE +- **Description**: Sets the node with the specified ID to deprecated (soft delete) +- **Path Parameters**: + - `$id`: Node ID + +#### Search Nodes + +- **URL**: `/api/nodes/search` +- **Method**: GET +- **Description**: Returns a list of nodes matching the search conditions +- **Query Parameters**: + - `filter`: Search string + - `limit`: Maximum number of items to return + - `node_type`: Type filter (valid values: `source`, `sink`, `intermediate`) + - `include_user_nodes`: Boolean to include user-specific nodes +- **Response Format**: + +```javascript +[ + { + "id": "string", + "country": { + "id": "string", + "iso_code": "string", + "region_code": "string", + "name": "string" + }, + "name": "string", + "address": "string", + "location": { + "longitude": "number", + "latitude": "number" + }, + "types": ["sink", "source", "intermediate"], + "predecessors": { ... }, + "outbound_countries": [ ... ], + "is_user_node": "boolean" + }, + ... +] +``` + +## Transportation Rate Endpoints {#transportation-rate-endpoints} + +### Rate Validity Periods + +#### List Validity Periods + +- **URL**: `/api/rates/periods` +- **Method**: GET +- **Description**: Returns a list of validity periods for transportation rates +- **Response Format**: + +```javascript +[ + { + "id": "string", + "start_date": "date", + "end_date": "date", + "state": "string" + }, + ... +] +``` + +- **Note**: State can have the following values: `draft`, `valid`, `invalid`, `expired` + +#### Create Validity Period + +- **URL**: `/api/rates/periods` +- **Method**: PUT +- **Description**: Creates a new validity period (only possible if no validity period with state "draft" exists) + +#### Invalidate Validity Period + +- **URL**: `/api/rates/periods/{$id}` +- **Method**: DELETE +- **Description**: Invalidates the validity period with the specified ID (must be in state "valid" or "expired") +- **Path Parameters**: + - `$id`: Validity period ID + +### Container Rates + +#### List Container Rates + +- **URL**: `/api/rates/container/` +- **Method**: GET +- **Description**: Returns a list of container rates associated with a specific validity period +- **Query Parameters**: + - `limit`: Maximum number of items to return (default: 20\) + - `offset`: Number of items to skip (for pagination) + - `valid`: Validity period filter (values: validity\_period\_id, "current", "draft") + - `validAt`: Timestamp to find rates valid at a specific time +- **Response Format**: + +```javascript +[ + { + "id": "string", + "origin": { + "id": "string", + "country": { ... }, + "address": "string", + "location": { ... }, + "types": ["sink", "source", "intermediate"] + }, + "destination": { + "id": "string", + "country": { ... }, + "address": "string", + "location": { ... }, + "types": ["sink", "source", "intermediate"] + }, + "type": "string", + "rates": { + "40": "number", + "20": "number", + "40_HC": "number" + }, + "lead_time": "number", + "validity_period": { + "id": "string", + "start_date": "date", + "end_date": "date", + "state": "string" + } + }, + ... +] +``` + +- **Note**: Type can have the following values: `rail`, `sea`, `post-run`, `road` + +#### Get Container Rate Details + +- **URL**: `/api/rates/container/{$id}` +- **Method**: GET +- **Description**: Returns detailed information about a specific container rate +- **Path Parameters**: + - `$id`: Container rate ID +- **Response Format**: Same as list container rates + +#### Update Container Rate + +- **URL**: `/api/rates/container/{$id}` +- **Method**: PUT +- **Description**: Updates the container rate with the specified ID (only possible if the validity period is in state "draft") +- **Path Parameters**: + - `$id`: Container rate ID + +#### Delete Container Rate + +- **URL**: `/api/rates/container/{$id}` +- **Method**: DELETE +- **Description**: Deletes the container rate with the specified ID (only possible if the validity period is in state "draft") +- **Path Parameters**: + - `$id`: Container rate ID + +### Country Matrix Rates + +#### List Country Matrix Rates + +- **URL**: `/api/rates/matrix/` +- **Method**: GET +- **Description**: Returns a list of country matrix rates associated with a specific validity period +- **Query Parameters**: + - `limit`: Maximum number of items to return (default: 20\) + - `offset`: Number of items to skip (for pagination) + - `valid`: Validity period filter (values: validity\_period\_id, "current", "draft") + - `validAt`: Timestamp to find rates valid at a specific time +- **Response Format**: + +```javascript +[ + { + "id": "string", + "origin": { + "id": "string", + "country": { ... }, + "address": "string", + "location": { ... }, + "types": ["sink", "source", "intermediate"] + }, + "destination": { + "id": "string", + "country": { ... }, + "address": "string", + "location": { ... }, + "types": ["sink", "source", "intermediate"] + }, + "rate": "number" + }, + ... +] +``` + +#### Get Country Matrix Rate Details + +- **URL**: `/api/rates/matrix/{$id}` +- **Method**: GET +- **Description**: Returns detailed information about a specific country matrix rate +- **Path Parameters**: + - `$id`: Country matrix rate ID +- **Response Format**: Same as list country matrix rates + +#### Update Country Matrix Rate + +- **URL**: `/api/rates/matrix/{$id}` +- **Method**: PUT +- **Description**: Updates the country matrix rate with the specified ID (only possible if the validity period is in state "draft") +- **Path Parameters**: + - `$id`: Country matrix rate ID + +#### Delete Country Matrix Rate + +- **URL**: `/api/rates/matrix/{$id}` +- **Method**: DELETE +- **Description**: Deletes the country matrix rate with the specified ID (only possible if the validity period is in state "draft") +- **Path Parameters**: + - `$id`: Country matrix rate ID + +#### Check Staged Rate Changes + +- **URL**: `/api/rates/staged_changes/` +- **Method**: GET +- **Description**: Returns true if there are any unapproved "draft" rates, false otherwise + +#### Approve Rate Changes + +- **URL**: `/api/rates/staged_changes/` +- **Method**: PUT +- **Description**: Approves drafts and sets current "draft" validity period to current valid validity period + +## User Management Endpoints + +### User Operations {#user-operations} + +#### List Users + +- **URL**: `/api/users/` +- **Method**: GET +- **Description**: Lists all users +- **Query Parameters**: + - `limit`: Maximum number of items to return (default: 20\) + - `offset`: Number of items to skip (for pagination) +- **Authorization**: PSK (Pre-Shared Key) +- **Response Format**: + +```javascript +[ + { + "firstname": "string", + "lastname": "string", + "mail": "string", + "workday_id": "string", + "is_active": "boolean", + "groups": ["string", ...] + }, + ... +] +``` + +#### Create or Update User + +- **URL**: `/api/users/` +- **Method**: PUT +- **Description**: Updates an existing user or creates a new one +- **Authorization**: PSK (Pre-Shared Key) + +### Group Operations + +#### List Groups + +- **URL**: `/api/groups/` +- **Method**: GET +- **Description**: Lists all user groups +- **Query Parameters**: + - `limit`: Maximum number of items to return (default: 20\) + - `offset`: Number of items to skip (for pagination) +- **Authorization**: PSK (Pre-Shared Key) +- **Response Format**: + +```javascript +[ + { + "group_name": "string", + "group_description": "string" + }, + ... +] +``` + +#### Create or Update Group + +- **URL**: `/api/groups/` +- **Method**: PUT +- **Description**: Updates an existing group or creates a new one +- **Authorization**: PSK (Pre-Shared Key) + +## Calculation Endpoints {#calculation-endpoints} + +### Calculation Operations + +#### View Calculation Premises + +- **URL**: `/api/calculation/view` +- **Method**: GET +- **Description**: Lists a preview of all premises for the current user (or another user with elevated rights) +- **Query Parameters**: + - `limit`: Maximum number of items to return (default: 20\) + - `offset`: Number of items to skip (for pagination) + - `filter`: Search string + - `user`: User ID filter + - `deleted`: Boolean to include deleted premises (default: false) + - `archived`: Boolean to include archived premises (default: false) + - `done`: Boolean to include completed premises (default: true) +- **Response Format**: + +```javascript +[ + { + "id": "string", + "material": { + "id": "string", + "part_number": "string", + "name": "string" + }, + "supplier": { + "id": "string", + "country": { + "id": "string", + "iso_code": "string", + "region_code": "string" + }, + "name": "string", + "address": "string" + }, + "state": "string" + }, + ... +] +``` + +- **Note**: State can have the following values: `draft`, `completed`, `archived`, `deleted` + +#### Search for Materials and Suppliers + +- **URL**: `/api/calculation/search` +- **Method**: GET +- **Description**: Parses the given search string and returns the found materials and associated suppliers +- **Query Parameters**: + - `material`: Search string for materials +- **Response Format**: + +```javascript +{ + "materials": [ + { + "id": "string", + "part_number": "string", + "name": "string" + }, + ... + ], + "supplier": [ + { + "id": "string", + "country": { + "id": "string", + "iso_code": "string", + "region_code": "string" + }, + "name": "string", + "address": "string" + }, + ... + ], + "user_supplier": [ + { + "id": "string", + "country": { + "id": "string", + "iso_code": "string", + "region_code": "string" + }, + "name": "string", + "address": "string" + }, + ... + ] +} +``` + +#### Create Calculation Premises + +- **URL**: `/api/calculation/create` +- **Method**: GET +- **Description**: Returns a list of premises based on the provided parameters +- **Query Parameters**: + - `material`: Array of material IDs + - `supplier`: Array of supplier IDs + - `user_supplier`: Array of user supplier IDs + - `from_scratch`: Boolean to create empty premises +- **Response Format**: Detailed premise data including routes and transit nodes + +#### Edit Calculation Premises + +- **URL**: `/api/calculation/edit` +- **Method**: GET +- **Description**: Returns a list of premises based on the provided premise IDs +- **Query Parameters**: + - `premiss_ids`: Array of premise IDs +- **Response Format**: Detailed premise data including routes and transit nodes + +#### Save Calculation Premises + +- **URL**: `/api/calculation/edit` +- **Method**: PUT +- **Description**: Saves the provided premises +- **Request Body**: Array of premise objects with detailed route information + +## Reporting Endpoints + +### Reporting Operations {#reporting-operations} + +#### Download Report + +- **URL**: `/api/reports/download` +- **Method**: GET +- **Description**: Returns an Excel-file based report +- **Query Parameters**: + - `material`: Material ID + - `sources`: Array of source IDs + +#### Search Report Sources + +- **URL**: `/api/reports/search` +- **Method**: GET +- **Description**: Returns a list of source groups based on the given material ID +- **Query Parameters**: + - `material`: Material ID +- **Response Format**: + +```javascript +[ + ["source_id", ...],c + ... +] +``` + +#### View Report + +- **URL**: `/api/reports/view` +- **Method**: GET +- **Description**: Returns a detailed cost and risk report +- **Query Parameters**: + - `material`: Material ID + - `sources`: Array of source IDs +- **Response Format**: + +```javascript +[ + { + "cost": { + "material_cost": { + "total": "number", + "percentage": "number" + }, + "fca_fees": { + "total": "number", + "percentage": "number" + }, + "pre_run_cost": { + "total": "number", + "percentage": "number" + }, + "main_run_cost": { + "total": "number", + "percentage": "number" + }, + "post_run_cost": { + "total": "number", + "percentage": "number" + }, + "repacking_cost": { + "total": "number", + "percentage": "number" + }, + "handling_cost": { + "total": "number", + "percentage": "number" + }, + "storage_cost": { + "total": "number", + "percentage": "number" + }, + "captial_cost": { + "total": "number", + "percentage": "number" + }, + "disposal_cost": { + "total": "number", + "percentage": "number" + }, + "total_cost": { + "total": "number", + "percentage": "number" + } + }, + "risk": { + "air_freight_cost": { + "total": "number", + "percentage": "number" + }, + "best_case_cost": { + "total": "number", + "percentage": "number" + }, + "worst_case_cost": { + "total": "number", + "percentage": "number" + } + }, + "premisses": { + "quantities": [ + { + "destination": "string", + "quantity": "number", + "route": [ + { + "name": "string", + "type": "string", + "cost": { + "total": "number", + "percentage": "number" + } + }, + "..." + ] + } + ], + "hs_code": "string", + "custom_rate": "number", + "container": { + "type": "string", + "rate": "number", + "unit_count": "number", + "weight_exceeded": "boolean", + "utilization": "number", + "mixed": "boolean" + }, + "packaging": { + "width": "number", + "height": "number", + "length": "number", + "weight": "number", + "dimension_unit": "string", + "weight_unit": "string", + "unit_count": "number", + "layers": "number" + }, + "qouta_share": { + "oversea_share": "number", + "air_freight_share": "number", + "transport_time": "number", + "safety_stock": "number" + } + } + }, + "..." +] +``` + +## Glossary {#glossary} + +| Term | Definition | +| :---- | :---- | +| **API** | Application Programming Interface. A set of rules that allows programs to talk to each other. | +| **Calculation Premises** | The foundational data and assumptions used for logistics cost calculations. | +| **Container Rate** | Pricing for transportation of goods via standard shipping containers (20ft, 40ft, 40ft High Cube). | +| **Country Matrix** | A grid representing transportation rates between country pairs. | +| **Draft** | A working state for rates, properties, or other data that is not yet approved or in production. | +| **Handling Unit** | A physical package or container for materials (e.g., pallet, box). | +| **HS Code** | Harmonized System code. An international nomenclature for classifying traded products. | +| **LCC** | Logistics Cost Calculator, the primary system this API supports. | +| **Lead Time** | The time taken from ordering to delivery of materials. | +| **Material** | A product or component that is transported or managed in the system. | +| **Node** | A geographic location in the logistics network (could be source, sink, or intermediate). | +| **Packaging** | The physical container or wrapping for materials during transportation. | +| **Pre-Shared Key (PSK)** | A secret key shared between parties for authentication purposes. | +| **Property Type** | A definition of a characteristic that can be assigned to system entities. | +| **Rate** | The cost associated with transporting goods between locations. | +| **Sink** | A destination node in the logistics network (typically a manufacturing plant). | +| **Source** | An origin node in the logistics network (typically a supplier). | +| **System Property** | A configuration setting that affects the behavior of the LCC system. | +| **Transit Node** | An intermediate point in a transportation route. | +| **User Supplier** | A supplier that is specific to a particular user rather than system-wide. | +| **Validity Period** | A timeframe during which rates or other data are considered active and applicable. | + +# Database Documentation + +## Overview Database + +This document provides a comprehensive description of the LCC Backend Database structure. It handles property management, geographical data, user management, logistics nodes, transportation rates, packaging, materials, and calculation workflows for optimizing logistics operations. + +## Table Categories + +The database is organized into several functional areas: + +1. **Property Management** - Versioned configuration properties +2. **Geographic Data** - Countries and regions +3. **User Management** - Users, groups, and permissions +4. **Logistics Nodes** - Physical locations in the supply chain +5. **Transportation** - Distance matrices and rates +6. **Materials & Packaging** - Product and packaging information +7. **Premiss & Routes** - Supply chain scenarios and route planning +8. **Calculation** - Cost calculation jobs and results + +## Detailed Table Descriptions + +### Property Management + +#### `property_set` +Manages versioned sets of properties with temporal validity. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `start_date` | TIMESTAMP | When this property set becomes valid | +| `end_date` | TIMESTAMP | When this property set expires (NULL = no expiration) | +| `state` | CHAR(8) | Status of property set: DRAFT, VALID, INVALID, EXPIRED | + +#### `system_property_type` +Defines system-wide configuration property types. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `name` | VARCHAR(255) | Property type name | +| `external_mapping_id` | VARCHAR(16) | External system identifier | +| `data_type` | VARCHAR(16) | Data type: INT, PERCENTAGE, BOOLEAN, CURRENCY, ENUMERATION, TEXT | +| `validation_rule` | VARCHAR(64) | Optional validation rules | + +#### `system_property` +Stores system-wide configuration property values. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `property_set_id` | INT | References property_set | +| `system_property_type_id` | INT | References system_property_type | +| `property_value` | VARCHAR(500) | The value of the property | + +### Geographic Data + +#### `country` +Master data table for country information and regional classification. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `iso_code` | CHAR(2) | ISO 3166-1 alpha-2 country code | +| `region_code` | CHAR(5) | Geographic region: EMEA/LATAM/APAC/NAM | +| `name` | VARCHAR(128) | Country name | +| `is_deprecated` | BOOLEAN | Whether the country record is deprecated | + +#### `country_property_type` +Defines property types specific to countries. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `name` | VARCHAR(255) | Property type name | +| `external_mapping_id` | VARCHAR(16) | External system identifier | +| `data_type` | VARCHAR(16) | Data type: INT, PERCENTAGE, BOOLEAN, CURRENCY, ENUMERATION, TEXT | +| `validation_rule` | VARCHAR(64) | Optional validation rules | +| `is_required` | BOOLEAN | Whether the property is required | + +#### `country_property` +Stores country-specific property values with versioning support. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `country_id` | INT | References country | +| `country_property_type_id` | INT | References country_property_type | +| `property_set_id` | INT | References property_set | +| `property_value` | VARCHAR(500) | The value of the property | + +### User Management + +#### `sys_user` +Stores basic information about system users. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `workday_id` | CHAR(32) | External HR system identifier | +| `email` | VARCHAR(254) | User email | +| `firstname` | VARCHAR(100) | User first name | +| `lastname` | VARCHAR(100) | User last name | +| `is_active` | BOOLEAN | Whether the user is active | + +#### `sys_group` +Defines user groups for access management. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `group_name` | VARCHAR(64) | Group name | +| `group_description` | VARCHAR(128) | Group description | + +#### `sys_user_group_mapping` +Links users with their associated groups. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `user_id` | INT | References sys_user | +| `group_id` | INT | References sys_group | + +#### `sys_user_node` +Contains user-generated logistic nodes. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `user_id` | INT | References sys_user | +| `country_id` | INT | References country | +| `name` | VARCHAR(254) | Node name | +| `address` | VARCHAR(500) | Physical address | +| `geo_lat` | DECIMAL(7,4) | Latitude (-90 to 90) | +| `geo_lng` | DECIMAL(7,4) | Longitude (-180 to 180) | +| `is_deprecated` | BOOLEAN | Whether the node is deprecated | + +### Logistics Nodes + +#### `node` +Represents physical locations in the supply chain network. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `country_id` | INT | References country | +| `name` | VARCHAR(255) | Node name | +| `address` | VARCHAR(500) | Physical address | +| `external_mapping_id` | VARCHAR(32) | External system identifier | +| `predecessor_required` | BOOLEAN | Whether this node requires a predecessor | +| `is_sink` | BOOLEAN | Whether this node is a destination/consumption point | +| `is_source` | BOOLEAN | Whether this node is a source/production point | +| `is_intermediate` | BOOLEAN | Whether this node is a transfer point | +| `geo_lat` | DECIMAL(7,4) | Latitude (-90 to 90) | +| `geo_lng` | DECIMAL(7,4) | Longitude (-180 to 180) | +| `updated_at` | TIMESTAMP | Last update timestamp | +| `is_deprecated` | BOOLEAN | Whether the node is deprecated | + +#### `node_predecessor` +Defines predecessor relationships between nodes. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `node_id` | INT | References node | +| `predecessor_node_id` | INT | References node as a predecessor | +| `sequence_number` | INT | Position in the sequence (>0) | + +#### `outbound_country_mapping` +Maps nodes to countries they can serve. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `node_id` | INT | References node | +| `country_id` | INT | References country | + +#### `distance_matrix` +Stores distance information between nodes. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `from_node_id` | INT | References source node | +| `to_node_id` | INT | References destination node | +| `from_geo_lat` | DECIMAL(7,4) | Source latitude | +| `from_geo_lng` | DECIMAL(7,4) | Source longitude | +| `to_geo_lat` | DECIMAL(7,4) | Destination latitude | +| `to_geo_lng` | DECIMAL(7,4) | Destination longitude | +| `distance` | DECIMAL(15,2) | Travel distance in meters | +| `updated_at` | TIMESTAMP | Last update timestamp | +| `state` | CHAR(10) | Status: VALID, STALE | + +### Transportation Rates + +#### `validity_period` +Defines time periods for rate validity. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `start_date` | TIMESTAMP | When the period starts | +| `end_date` | TIMESTAMP | When the period ends (NULL = no end) | +| `state` | CHAR(8) | Status: DRAFT, VALID, INVALID, EXPIRED | + +#### `container_rate` +Stores rates for container transportation between nodes. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `from_node_id` | INT | References source node | +| `to_node_id` | INT | References destination node | +| `container_rate_type` | CHAR(8) | Type: RAIL, SEA, POST-RUN, ROAD | +| `rate_20` | DECIMAL(15,2) | Rate for 20ft container in EUR | +| `rate_40` | DECIMAL(15,2) | Rate for 40ft container in EUR | +| `rate_40_hc` | DECIMAL(15,2) | Rate for 40ft HQ container in EUR | +| `lead_time` | INT UNSIGNED | Lead time in days | +| `validity_period_id` | INT | References validity_period | + +#### `country_matrix_rate` +Stores rates for full truck load based on country pairs. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `from_country_id` | INT | References source country | +| `to_country_id` | INT | References destination country | +| `rate` | DECIMAL(15,2) | Rate for full truck load per kilometer in EUR | +| `validity_period_id` | INT | References validity_period | + +### Materials & Packaging + +#### `material` +Stores information about materials. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `part_number` | CHAR(12) | Material part number | +| `normalized_part_number` | CHAR(12) | Standardized part number (unique) | +| `hs_code` | CHAR(8) | Harmonized System code for customs | +| `name` | VARCHAR(500) | Material name | +| `is_deprecated` | BOOLEAN | Whether the material is deprecated | + +#### `packaging` +Defines packaging specifications. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `supplier_node_id` | INT | References node (supplier) | +| `material_id` | INT | References material | +| `parent_id` | INT | References parent packaging (hierarchical) | +| `type` | CHAR(3) | Type: SHU (small handling unit), HU (handling unit) | +| `length` | INT UNSIGNED | Length in mm | +| `width` | INT UNSIGNED | Width in mm | +| `height` | INT UNSIGNED | Height in mm | +| `displayed_dimension_unit` | CHAR(2) | Display unit: MM, CM, M | +| `weight` | INT UNSIGNED | Weight in g | +| `displayed_weight_unit` | CHAR(2) | Display unit: G, KG | +| `content_unit_count` | INT UNSIGNED | Number of units contained | +| `is_deprecated` | BOOLEAN | Whether the packaging is deprecated | + +#### `packaging_property_type` +Defines property types for packaging. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `name` | VARCHAR(255) | Property type name | +| `data_type` | VARCHAR(16) | Data type | +| `validation_rule` | VARCHAR(64) | Optional validation rules | +| `is_required` | BOOLEAN | Whether the property is required | + +#### `packaging_property` +Stores packaging property values. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `packaging_property_type_id` | INT | References packaging_property_type | +| `packaging_id` | INT | References packaging | +| `property_value` | VARCHAR(500) | The value of the property | + +### Premiss & Routes + +#### `premiss` +Core table for logistics scenario planning. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `material_id` | INT | References material | +| `supplier_node_id` | INT | References node (system supplier) | +| `user_supplier_node_id` | INT | References sys_user_node (user's supplier) | +| `packaging_id` | INT | References packaging | +| `user_id` | INT | References sys_user (creator) | +| `createdAt` | TIMESTAMP | Creation timestamp | +| `updatedAt` | TIMESTAMP | Last update timestamp | +| `material_cost` | DECIMAL(15,2) | Material cost in EUR (MEK_A) | +| `is_fca_enabled` | BOOLEAN | Free Carrier shipping terms enabled | +| `oversea_share` | DECIMAL(7,4) | Percentage of overseas transport | +| `hs_code` | CHAR(8) | Harmonized System code for customs | +| `custom_rate` | DECIMAL(7,4) | Custom duty rate | +| `state` | CHAR(10) | Status: DRAFT, COMPLETED, ARCHIVED, DELETED | +| `individual_hu_length` | INT UNSIGNED | Handling unit length in mm | +| `individual_hu_height` | INT UNSIGNED | Handling unit height in mm | +| `individual_hu_width` | INT UNSIGNED | Handling unit width in mm | +| `individual_hu_weight` | INT UNSIGNED | Handling unit weight in g | +| `hu_displayed_dimension_unit` | CHAR(2) | Display unit for dimensions | +| `hu_displayed_weight_unit` | CHAR(2) | Display unit for weight | +| `hu_unit_count` | INT UNSIGNED | Number of units per handling unit | +| `hu_stackable` | BOOLEAN | Whether the unit is stackable | +| `hu_mixable` | BOOLEAN | Whether the unit can be mixed with others | + +#### `premiss_sink` +Links premiss to destination nodes with volume information. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `premiss_id` | INT | References premiss | +| `annual_amount` | INT UNSIGNED | Annual amount in pieces | +| `sink_node_id` | INT | References node (destination) | + +#### `premiss_route` +Defines possible routes for a premiss_sink. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `premiss_sink_id` | INT | References premiss_sink | +| `is_fastest` | BOOLEAN | Whether this is the fastest route | +| `is_cheapest` | BOOLEAN | Whether this is the cheapest route | +| `is_selected` | BOOLEAN | Whether this route is selected/preferred | + +#### `premiss_route_node` +Defines nodes in a route. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `premiss_route_id` | INT | References premiss_route | +| `node_id` | INT | References node (system node) | +| `user_node_id` | INT | References sys_user_node (user's node) | +| `name` | VARCHAR(255) | Node name | +| `address` | VARCHAR(500) | Node address | +| `is_sink` | BOOLEAN | Whether this is a destination node | +| `is_intermediate` | BOOLEAN | Whether this is a transfer node | +| `is_source` | BOOLEAN | Whether this is a source node | +| `geo_lat` | DECIMAL(7,4) | Latitude | +| `geo_lng` | DECIMAL(7,4) | Longitude | +| `is_outdated` | BOOLEAN | Whether the node data is outdated | + +#### `premiss_route_section` +Defines transportation sections between route nodes. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `premiss_route_id` | INT | References premiss_route | +| `from_route_node_id` | INT | References premiss_route_node (source) | +| `to_route_node_id` | INT | References premiss_route_node (destination) | +| `list_position` | INT | Position in the route sequence | +| `transport_type` | CHAR(16) | Type: RAIL, SEA, ROAD, POST-RUN, MATRIX, D2D | +| `rate_d2d` | DECIMAL(15,2) | Door-to-door rate in EUR | +| `is_pre_run` | BOOLEAN | Whether this is a pre-run section | +| `is_main_run` | BOOLEAN | Whether this is a main-run section | +| `is_post_run` | BOOLEAN | Whether this is a post-run section | +| `is_outdated` | BOOLEAN | Whether the section data is outdated | + +### Calculation System + +#### `calculation_job` +Manages calculation processes. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `premiss_id` | INT | References premiss | +| `calculation_date` | TIMESTAMP | When the calculation was performed | +| `validity_period_id` | INT | References validity_period | +| `property_set_id` | INT | References property_set | +| `job_state` | CHAR(10) | Status: CREATED, SCHEDULED, VALID, INVALID, EXCEPTION | +| `user_id` | INT | References sys_user (creator) | + +#### `calculation_job_sink_result` +Stores calculation results per sink. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `calculation_job_id` | INT | References calculation_job | +| `premiss_sink_id` | INT | References premiss_sink | +| `safety_stock` | INT UNSIGNED | Safety stock in pieces | +| `shipping_frequency` | INT UNSIGNED | Annual shipping frequency | +| `total_cost` | DECIMAL(15,2) | Total cost in EUR (MEK_B) | + +#### `calculation_job_transportation_result` +Stores transportation calculation results. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `calculation_job_sink_result_id` | INT | References calculation_job_sink_result | +| `transportation_type` | CHAR(8) | Type: 20, 40, 40HC, TRUCK | +| `hu_per_layer` | INT UNSIGNED | Handling units per layer | +| `layer_structure` | JSON | Structure of a single layer | +| `layer_count` | INT UNSIGNED | Number of layers per container/truck | +| `transport_weight_exceeded` | BOOLEAN | Weight vs. volume limitation | +| `transports_per_year` | DECIMAL(15,2) | Number of transports per year | +| `annual_cost` | DECIMAL(15,2) | Annual transportation costs in EUR | + +#### `calculation_job_route_section_result` +Detailed calculation results for route sections. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `premiss_route_section_id` | INT | References premiss_route_section | +| `calculation_job_transportation_result_id` | INT | References calculation_job_transportation_result | +| `used_rule` | CHAR(8) | Calculation rule: CONTAINER, MATRIX | +| `is_unmixed_price` | BOOLEAN | Whether an unmixed pricing was used | +| `is_cbm_price` | BOOLEAN | Whether cubic meter pricing was used | +| `is_weight_price` | BOOLEAN | Whether weight-based pricing was used | +| `is_stacked` | BOOLEAN | Whether stacking was considered | +| `is_pre_run` | BOOLEAN | Whether this is a pre-run calculation | +| `is_main_run` | BOOLEAN | Whether this is a main-run calculation | +| `is_post_run` | BOOLEAN | Whether this is a post-run calculation | +| `rate` | DECIMAL(15,2) | Applied rate in EUR | +| `distance` | DECIMAL(15,2) | Section distance in meters | +| `cbm_price` | DECIMAL(15,2) | Price per cubic meter | +| `weight_price` | DECIMAL(15,2) | Price per kilogram | +| `annual_cost` | DECIMAL(15,2) | Annual costs for this section | +| `transit_time` | INT UNSIGNED | Transit time | + +#### `calculation_job_airfreight_result` +Stores air freight calculation results. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `calculation_job_sink_result_id` | INT | References calculation_job_sink_result | +| `air_freight_share_max` | DECIMAL(7,4) | Maximum air freight share | +| `air_freight_share` | DECIMAL(7,4) | Actual air freight share | +| `air_freight_volumetric_weight` | DECIMAL(15,2) | Volumetric weight | +| `air_freight_weight` | DECIMAL(15,2) | Actual weight | +| `annual_cost` | DECIMAL(15,2) | Annual air freight costs | + +#### `calculation_job_custom_result` +Stores customs duty calculation results. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `calculation_job_sink_result_id` | INT | References calculation_job_sink_result | +| `custom_value` | DECIMAL(15,2) | Customs value | +| `custom_duties` | DECIMAL(15,2) | Customs duties | +| `custom_rate` | DECIMAL(7,4) | Applied duty rate | +| `annual_cost` | DECIMAL(15,2) | Annual customs costs | + +#### `calculation_job_inventory_result` +Stores inventory calculation results. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `calculation_job_sink_result_id` | INT | References calculation_job_sink_result | +| `operational_stock` | DECIMAL(15,2) | Operational stock in pieces | +| `safety_stock` | DECIMAL(15,2) | Safety stock in pieces | +| `stocked_inventory` | DECIMAL(15,2) | Total stocked inventory | +| `in_transport_stock` | DECIMAL(15,2) | Stock in transport | +| `stock_before_payment` | DECIMAL(15,2) | Stock before payment | +| `annual_capital_cost` | DECIMAL(15,2) | Annual capital costs | +| `annual_storage_cost` | DECIMAL(15,2) | Annual storage costs | + +#### `calculation_job_handling_result` +Stores handling cost calculation results. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `calculation_job_sink_result_id` | INT | References calculation_job_sink_result | +| `is_small_unit` | BOOLEAN | Whether this is a small unit (< 0.08 cbm) | +| `annual_repacking_cost` | DECIMAL(15,2) | Annual repacking costs | +| `annual_handling_cost` | DECIMAL(15,2) | Annual handling costs | +| `annual_disposal_cost` | DECIMAL(15,2) | Annual disposal costs | + +#### `calculation_job_risk_result` +Stores risk assessment calculation results. + +| Column | Type | Description | +|--------|------|-------------| +| `id` | INT | Primary key | +| `calculation_job_sink_result_id` | INT | References calculation_job_sink_result | +| `annual_risk_cost` | DECIMAL(15,2) | Annual risk costs (worst case) | +| `annual_chance_cost` | DECIMAL(15,2) | Annual opportunity costs (best case) | + +## Entity Relationship Diagram + +The database has several key relationship patterns: + +1. The `property_set` system provides versioned configuration for both system-wide and country-specific properties +2. The `node` system forms the backbone of the logistics network +3. The `premiss` system ties together materials, packaging, suppliers, and destinations +4. The `calculation_job` system captures results of cost calculations with various components + +## Common Data Types and Conventions + +- Monetary values are stored as DECIMAL(15,2) in EUR +- Geographical coordinates are stored as DECIMAL(7,4) +- Dimensions are stored in mm (millimeters) +- Weights are stored in g (grams) +- Most tables include an `is_deprecated` flag for soft-deletion +- State/status fields use CHECK constraints to limit valid values diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index 55f9c29..d9c3ae6 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -1,5 +1,3 @@ - - -- Property management tables CREATE TABLE IF NOT EXISTS `property_set` ( @@ -14,28 +12,40 @@ CREATE TABLE IF NOT EXISTS `property_set` INDEX `idx_property_set_id` (id) ) COMMENT 'Manages versioned sets of properties with temporal validity'; +CREATE TABLE IF NOT EXISTS `system_property_type` +( + -- Stores system-wide configuration property types + `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + `name` VARCHAR(255) NOT NULL, + `external_mapping_id` VARCHAR(16), + `data_type` VARCHAR(16) NOT NULL, + `validation_rule` VARCHAR(64), + CONSTRAINT `chk_system_data_type_values` CHECK (`data_type` IN + ('INT', 'PERCENTAGE', 'BOOLEAN', 'CURRENCY', 'ENUMERATION', + 'TEXT')) +) COMMENT 'Stores system-wide configuration property types'; + CREATE TABLE IF NOT EXISTS `system_property` ( -- Stores system-wide configuration properties - `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, - `property_set_id` INT NOT NULL, - `description` VARCHAR(255) NOT NULL, - `short_description` VARCHAR(16), - `data_type` VARCHAR(16) NOT NULL, - `validation_rule` VARCHAR(64), - `property_value` VARCHAR(500), - CONSTRAINT `chk_system_data_type_values` CHECK (`data_type` IN - ('INT', 'PERCENTAGE', 'BOOLEAN', 'CURRENCY', 'ENUMERATION', 'TEXT')), - FOREIGN KEY (`property_set_id`) REFERENCES `property_set` (`id`) + `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + `property_set_id` INT NOT NULL, + `system_property_type_id` INT NOT NULL, + `property_value` VARCHAR(500), + FOREIGN KEY (`property_set_id`) REFERENCES `property_set` (`id`), + FOREIGN KEY (`system_property_type_id`) REFERENCES `system_property_type` (`id`), + INDEX `idx_system_property_type_id` (system_property_type_id), + INDEX `idx_property_set_id` (id) ) COMMENT 'Stores system-wide configuration properties'; -- country CREATE TABLE IF NOT EXISTS `country` ( - `id` INT NOT NULL AUTO_INCREMENT, - `iso_code` CHAR(2) NOT NULL COMMENT 'ISO 3166-1 alpha-2 country code', - `region_code` CHAR(5) NOT NULL COMMENT 'Geographic region code (EMEA/LATAM/APAC/NAM)', - `is_deprecated` BOOLEAN NOT NULL DEFAULT FALSE, + `id` INT NOT NULL AUTO_INCREMENT, + `iso_code` CHAR(2) NOT NULL COMMENT 'ISO 3166-1 alpha-2 country code', + `region_code` CHAR(5) NOT NULL COMMENT 'Geographic region code (EMEA/LATAM/APAC/NAM)', + `name` VARCHAR(128) NOT NULL, + `is_deprecated` BOOLEAN NOT NULL DEFAULT FALSE, PRIMARY KEY (`id`), UNIQUE INDEX `idx_country_iso_code` (`iso_code`), CONSTRAINT `chk_country_region_code` @@ -44,27 +54,28 @@ CREATE TABLE IF NOT EXISTS `country` CREATE TABLE IF NOT EXISTS `country_property_type` ( - `id` INT NOT NULL AUTO_INCREMENT, - `description` VARCHAR(255) NOT NULL, - `short_description` VARCHAR(16), - `data_type` VARCHAR(16) NOT NULL, - `validation_rule` VARCHAR(64), - `is_required` BOOLEAN NOT NULL DEFAULT FALSE, + `id` INT NOT NULL AUTO_INCREMENT, + `name` VARCHAR(255) NOT NULL, + `external_mapping_id` VARCHAR(16), + `data_type` VARCHAR(16) NOT NULL, + `validation_rule` VARCHAR(64), + `is_required` BOOLEAN NOT NULL DEFAULT FALSE, CONSTRAINT `chk_country_data_type_values` CHECK (`data_type` IN - ('INT', 'PERCENTAGE', 'BOOLEAN', 'CURRENCY', 'ENUMERATION', 'TEXT')), + ('INT', 'PERCENTAGE', 'BOOLEAN', 'CURRENCY', 'ENUMERATION', + 'TEXT')), PRIMARY KEY (`id`), INDEX `idx_property_type_data_type` (`data_type`) ) COMMENT 'Defines available property types for country-specific configurations'; CREATE TABLE IF NOT EXISTS `country_property` ( - `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, - `country_id` INT NOT NULL, - `property_type_id` INT NOT NULL, - `property_set_id` INT NOT NULL, - `property_value` VARCHAR(500), + `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + `country_id` INT NOT NULL, + `country_property_type_id` INT NOT NULL, + `property_set_id` INT NOT NULL, + `property_value` VARCHAR(500), FOREIGN KEY (`country_id`) REFERENCES `country` (`id`), - FOREIGN KEY (`property_type_id`) REFERENCES `country_property_type` (`id`), + FOREIGN KEY (`country_property_type_id`) REFERENCES `country_property_type` (`id`), FOREIGN KEY (`property_set_id`) REFERENCES `property_set` (`id`) ) COMMENT 'Stores country-specific property values with versioning support'; @@ -84,8 +95,9 @@ CREATE TABLE IF NOT EXISTS `sys_user` -- Group definitions CREATE TABLE IF NOT EXISTS `sys_group` ( - `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, - `group_name` CHAR(64) NOT NULL, + `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + `group_name` VARCHAR(64) NOT NULL, + `group_description` VARCHAR(128) NOT NULL, UNIQUE INDEX `idx_group_name` (`group_name`) ) COMMENT 'Defines user groups for access management'; @@ -103,13 +115,14 @@ CREATE TABLE IF NOT EXISTS `sys_user_group_mapping` CREATE TABLE IF NOT EXISTS `sys_user_node` ( - `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, - `user_id` INT NOT NULL, - `country_id` INT NOT NULL, - `description` VARCHAR(255) NOT NULL, - `address` VARCHAR(500) NOT NULL, - `geo_lat` DECIMAL(7, 4) CHECK (geo_lat BETWEEN -90 AND 90), - `geo_lng` DECIMAL(7, 4) CHECK (geo_lng BETWEEN -180 AND 180), + `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + `user_id` INT NOT NULL, + `country_id` INT NOT NULL, + `name` VARCHAR(254) NOT NULL, + `address` VARCHAR(500) NOT NULL, + `geo_lat` DECIMAL(7, 4) CHECK (geo_lat BETWEEN -90 AND 90), + `geo_lng` DECIMAL(7, 4) CHECK (geo_lng BETWEEN -180 AND 180), + `is_deprecated` BOOLEAN DEFAULT FALSE, FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`id`), FOREIGN KEY (`country_id`) REFERENCES `country` (`id`) ) COMMENT 'Contains user generated logistic nodes'; @@ -121,7 +134,7 @@ CREATE TABLE node ( id INT PRIMARY KEY, country_id INT NOT NULL, - description VARCHAR(255) NOT NULL, + name VARCHAR(255) NOT NULL, address VARCHAR(500) NOT NULL, external_mapping_id VARCHAR(32), predecessor_required BOOLEAN NOT NULL DEFAULT FALSE, @@ -231,7 +244,7 @@ CREATE TABLE material part_number CHAR(12) NOT NULL, normalized_part_number CHAR(12) NOT NULL, hs_code CHAR(8), - description VARCHAR(500) NOT NULL, + name VARCHAR(500) NOT NULL, is_deprecated BOOLEAN NOT NULL DEFAULT FALSE, CONSTRAINT `chk_normalized_part_number` UNIQUE (`normalized_part_number`) ); @@ -254,9 +267,9 @@ CREATE TABLE packaging CONSTRAINT `chk_type_values` CHECK (`type` IN ('SHU', 'HU')), CONSTRAINT `chk_packaging_displayed_dimension_unit` CHECK (`displayed_dimension_unit` IN - ('MM', 'CM', 'M')), + ('MM', 'CM', 'M')), CONSTRAINT `chk_packaging_displayed_weight_unit` CHECK (`displayed_weight_unit` IN - ('G', 'KG')), + ('G', 'KG')), FOREIGN KEY (supplier_node_id) REFERENCES node (id), FOREIGN KEY (material_id) REFERENCES material (id), FOREIGN KEY (parent_id) REFERENCES packaging (id), @@ -268,12 +281,13 @@ CREATE TABLE packaging CREATE TABLE packaging_property_type ( `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, - `description` VARCHAR(500) NOT NULL, - `data_type` CHAR(16), - `validation_rule` CHAR(64), + `name` VARCHAR(255) NOT NULL, + `data_type` VARCHAR(16), + `validation_rule` VARCHAR(64), `is_required` BOOLEAN NOT NULl DEFAULT FALSE, CONSTRAINT `chk_packaging_data_type_values` CHECK (`data_type` IN - ('INT', 'PERCENTAGE', 'BOOLEAN', 'CURRENCY', 'ENUMERATION', 'TEXT')) + ('INT', 'PERCENTAGE', 'BOOLEAN', 'CURRENCY', 'ENUMERATION', + 'TEXT')) ); CREATE TABLE packaging_property @@ -288,27 +302,18 @@ CREATE TABLE packaging_property INDEX idx_packaging_id (packaging_id) ); -CREATE TABLE calculation -( - id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, - material_id INT NOT NULL, - supplier_node_id INT NOT NULL, - packaging_id INT DEFAULT NULL, - FOREIGN KEY (material_id) REFERENCES material (id), - FOREIGN KEY (supplier_node_id) REFERENCES node (id), - FOREIGN KEY (packaging_id) REFERENCES packaging (id), - INDEX idx_material_id (material_id), - INDEX idx_supplier_node_id (supplier_node_id), - INDEX idx_packaging_id (packaging_id) -); - CREATE TABLE premiss ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, - calculation_id INT NOT NULL, + material_id INT NOT NULL, + supplier_node_id INT, + user_supplier_node_id INT, + packaging_id INT DEFAULT NULL, user_id INT NOT NULL, + createdAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + updatedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, material_cost DECIMAL(15, 2) COMMENT 'aka MEK_A in EUR', - is_fca_enabled BOOLEAN DEFAULT FALSE, + is_fca_enabled BOOLEAN DEFAULT FALSE, oversea_share DECIMAL(7, 4), hs_code CHAR(8), custom_rate DECIMAL(7, 4), @@ -317,21 +322,27 @@ CREATE TABLE premiss individual_hu_height INT UNSIGNED NOT NULL COMMENT 'user entered dimensions in mm (if system-wide packaging is used, packaging dimensions are copied here after creation)', individual_hu_width INT UNSIGNED NOT NULL COMMENT 'user entered dimensions in mm (if system-wide packaging is used, packaging dimensions are copied here after creation)', individual_hu_weight INT UNSIGNED NOT NULL COMMENT 'user entered weight in g (if system-wide packaging is used, packaging weight are copied here after creation)', - hu_displayed_dimension_unit CHAR(2) DEFAULT 'MM', - hu_displayed_weight_unit CHAR(2) DEFAULT 'G', - hu_unit_count INT UNSIGNED DEFAULT NULL, - hu_stackable BOOLEAN DEFAULT TRUE, - hu_mixable BOOLEAN DEFAULT TRUE, - FOREIGN KEY (calculation_id) REFERENCES calculation (id), + hu_displayed_dimension_unit CHAR(2) DEFAULT 'MM', + hu_displayed_weight_unit CHAR(2) DEFAULT 'G', + hu_unit_count INT UNSIGNED DEFAULT NULL, + hu_stackable BOOLEAN DEFAULT TRUE, + hu_mixable BOOLEAN DEFAULT TRUE, + FOREIGN KEY (material_id) REFERENCES material (id), + FOREIGN KEY (supplier_node_id) REFERENCES node (id), + FOREIGN KEY (user_supplier_node_id) REFERENCES sys_user_node (id), + FOREIGN KEY (packaging_id) REFERENCES packaging (id), FOREIGN KEY (user_id) REFERENCES sys_user (id), CONSTRAINT `chk_premiss_state_values` CHECK (`state` IN - ('DRAFT', 'COMPLETED', 'ARCHIVED', 'DELETED')), + ('DRAFT', 'COMPLETED', 'ARCHIVED', 'DELETED')), CONSTRAINT `chk_premiss_displayed_dimension_unit` CHECK (`hu_displayed_dimension_unit` IN - ('MM', 'CM', 'M')), + ('MM', 'CM', 'M')), CONSTRAINT `chk_premiss_displayed_weight_unit` CHECK (`hu_displayed_weight_unit` IN - ('G', 'KG')), - INDEX idx_calculation_id (calculation_id), - INDEX idx_user_id (user_id) + ('G', 'KG')), + INDEX idx_material_id (material_id), + INDEX idx_supplier_node_id (supplier_node_id), + INDEX idx_packaging_id (packaging_id), + INDEX idx_user_id (user_id), + INDEX idx_user_supplier_node_id (user_supplier_node_id) ); @@ -349,10 +360,12 @@ CREATE TABLE premiss_sink CREATE TABLE premiss_route ( - id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, - premiss_sink_node_id INT NOT NULL, - is_selected BOOLEAN DEFAULT FALSE, - FOREIGN KEY (premiss_sink_node_id) REFERENCES premiss_sink (id) + id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + premiss_sink_id INT NOT NULL, + is_fastest BOOLEAN DEFAULT FALSE, + is_cheapest BOOLEAN DEFAULT FALSE, + is_selected BOOLEAN DEFAULT FALSE, + FOREIGN KEY (premiss_sink_id) REFERENCES premiss_sink (id) ); CREATE TABLE premiss_route_node @@ -361,7 +374,7 @@ CREATE TABLE premiss_route_node premiss_route_id INT NOT NULL, node_id INT DEFAULT NULL, user_node_id INT DEFAULT NULL, - description VARCHAR(255) NOT NULL, + name VARCHAR(255) NOT NULL, address VARCHAR(500), is_sink BOOLEAN DEFAULT FALSE, is_intermediate BOOLEAN DEFAULT FALSE, @@ -474,6 +487,7 @@ CREATE TABLE calculation_job_route_section_result cbm_price DECIMAL(15, 2) NOT NULL COMMENT 'calculated price per cubic meter', weight_price DECIMAL(15, 2) NOT NULL COMMENT 'calculated price per kilogram', annual_cost DECIMAL(15, 2) NOT NULL COMMENT 'annual costs for this route section, result depends on calculation method (mixed or unmixed, stacked or unstacked, per volume/per weight resp. container rate/price matrix)', + transit_time INT UNSIGNED NOT NULL, FOREIGN KEY (premiss_route_section_id) REFERENCES premiss_route_section (id), FOREIGN KEY (calculation_job_transportation_result_id) REFERENCES calculation_job_transportation_result (id), INDEX idx_premiss_route_section_id (premiss_route_section_id),