# Database reference

Generated from the live schema by `backend/scripts/generate_db_reference.py`. Do not edit by hand; re-run the script after a migration.

Key: **PK** primary key, **U** unique, **→** references (foreign key).

## Contents

- [Users and access](#users-and-access) (6 tables)
- [Dropdown lists (admin-managed)](#dropdown-lists-admin-managed) (18 tables)
- [Plant layout](#plant-layout) (5 tables)
- [Chassis and yard](#chassis-and-yard) (13 tables)
- [Production](#production) (6 tables)
- [Quality (QA)](#quality-qa) (12 tables)
- [Dispatch](#dispatch) (4 tables)
- [Products, BOM and configuration](#products-bom-and-configuration) (14 tables)
- [Sales and customers](#sales-and-customers) (17 tables)
- [Dealer portal](#dealer-portal) (12 tables)
- [Raw material, stores and procurement](#raw-material-stores-and-procurement) (19 tables)
- [Vendor portal](#vendor-portal) (16 tables)
- [Maintenance](#maintenance) (14 tables)

## Users and access

### `login_users`

Every person who can log in (staff). Holds name, employee code, email, password hash and role.

Model: `app/models/core_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `user_id` | uuid | no | PK |
| `employee_code` | varchar(30) | yes | U |
| `name` | varchar(255) | no |  |
| `mobile` | varchar(20) | yes |  |
| `email` | varchar(255) | yes |  |
| `password_hash` | varchar(255) | no |  |
| `role_code` | varchar(50) | yes |  |
| `is_active` | boolean | no |  |
| `last_login_at` | timestamptz | yes |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `role_master`

Roles (ADMIN, QA_INSPECTOR, OPERATOR, ...). A user has one role.

Model: `app/models/access_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `role_id` | uuid | no | PK |
| `role_code` | varchar(50) | no | U |
| `role_name` | varchar(150) | no |  |
| `description` | varchar(500) | yes |  |
| `is_system_role` | boolean | no |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |

### `module_master`

Application modules that permissions are granted on (PRODUCTION, QA, YARD, ...).

Model: `app/models/access_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `module_id` | uuid | no | PK |
| `module_code` | varchar(50) | no | U |
| `module_name` | varchar(150) | no |  |
| `description` | varchar(500) | yes |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |

### `role_module_permission`

What each role may do per module (view / create / edit / delete / approve).

Model: `app/models/access_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `role_code` | varchar(50) | no | U |
| `module_code` | varchar(50) | no | U |
| `can_view` | boolean | no |  |
| `can_create` | boolean | no |  |
| `can_edit` | boolean | no |  |
| `can_delete` | boolean | no |  |
| `can_approve` | boolean | no |  |
| `updated_at` | timestamptz | yes |  |

### `user_permission_override`

Per-user exceptions to the role permissions (grant or revoke one action).

Model: `app/models/access_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `user_id` | uuid | no | U → `login_users.user_id` |
| `module_code` | varchar(50) | no | U |
| `can_view` | boolean | yes |  |
| `can_create` | boolean | yes |  |
| `can_edit` | boolean | yes |  |
| `can_delete` | boolean | yes |  |
| `can_approve` | boolean | yes |  |
| `granted_by` | uuid | yes |  |
| `granted_at` | timestamptz | yes |  |
| `note` | varchar(255) | yes |  |

### `station_user_assignment`

Which user works at which station, as OPERATOR or QA. Drives My Station and QA Inspection.

Model: `app/models/station_work_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `assignment_id` | uuid | no | PK |
| `user_id` | uuid | no | U → `login_users.user_id` |
| `station_id` | uuid | no | U → `station_master.station_id` |
| `role` | varchar(20) | no | U |
| `is_active` | boolean | no |  |
| `created_by` | uuid | yes | → `login_users.user_id` |
| `created_at` | timestamptz | yes |  |

## Dropdown lists (admin-managed)

### `master_list_registry`

Index of the dropdown lists: list code, table name, label, description, display order.

Model: `app/models/master_list_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `list_code` | varchar(60) | no | PK |
| `table_name` | varchar(80) | no | U |
| `label` | varchar(150) | no |  |
| `description` | text | yes |  |
| `sort_order` | integer | no |  |

### `production_line_master`

Dropdown list: production lines.

Model: `app/models/master_list_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `code` | varchar(120) | no | U |
| `label` | varchar(300) | no |  |
| `sort_order` | integer | no |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `ac_make_master`

Dropdown list: AC makes fitted to buses.

Model: `app/models/master_list_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `code` | varchar(120) | no | U |
| `label` | varchar(300) | no |  |
| `sort_order` | integer | no |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `interior_work_master`

Dropdown list: interior work types.

Model: `app/models/master_list_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `code` | varchar(120) | no | U |
| `label` | varchar(300) | no |  |
| `sort_order` | integer | no |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `yard_location_master`

Dropdown list: yard locations used on chassis inward.

Model: `app/models/master_list_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `code` | varchar(120) | no | U |
| `label` | varchar(300) | no |  |
| `sort_order` | integer | no |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `machine_type_master`

Dropdown list: machine types (maintenance).

Model: `app/models/master_list_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `code` | varchar(120) | no | U |
| `label` | varchar(300) | no |  |
| `sort_order` | integer | no |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `incoming_material_category_master`

Dropdown list: incoming material categories (maintenance).

Model: `app/models/master_list_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `code` | varchar(120) | no | U |
| `label` | varchar(300) | no |  |
| `sort_order` | integer | no |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `rental_vendor_master`

Dropdown list: equipment rental vendors (maintenance).

Model: `app/models/master_list_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `code` | varchar(120) | no | U |
| `label` | varchar(300) | no |  |
| `sort_order` | integer | no |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `rental_equipment_type_master`

Dropdown list: rental equipment types (maintenance).

Model: `app/models/master_list_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `code` | varchar(120) | no | U |
| `label` | varchar(300) | no |  |
| `sort_order` | integer | no |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `qa_verification_method_master`

Dropdown list: QA verification methods (visual, gauge, ...).

Model: `app/models/master_list_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `code` | varchar(120) | no | U |
| `label` | varchar(300) | no |  |
| `sort_order` | integer | no |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `production_hold_type_master`

Dropdown list: reasons a chassis is put on hold in production.

Model: `app/models/master_list_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `code` | varchar(120) | no | U |
| `label` | varchar(300) | no |  |
| `sort_order` | integer | no |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `payment_terms_master`

Dropdown list: payment terms (sales / procurement).

Model: `app/models/master_list_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `code` | varchar(120) | no | U |
| `label` | varchar(300) | no |  |
| `sort_order` | integer | no |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `region_master`

Dropdown list: sales regions.

Model: `app/models/master_list_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `code` | varchar(120) | no | U |
| `label` | varchar(300) | no |  |
| `sort_order` | integer | no |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `enquiry_type_master`

Dropdown list: sales enquiry types.

Model: `app/models/master_list_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `code` | varchar(120) | no | U |
| `label` | varchar(300) | no |  |
| `sort_order` | integer | no |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `enquiry_source_master`

Dropdown list: sales enquiry sources.

Model: `app/models/master_list_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `code` | varchar(120) | no | U |
| `label` | varchar(300) | no |  |
| `sort_order` | integer | no |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `chassis_document_type_master`

Dropdown list: document types collected at chassis arrival.

Model: `app/models/master_list_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `code` | varchar(120) | no | U |
| `label` | varchar(300) | no |  |
| `sort_order` | integer | no |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `gate_pass_item_master`

Dropdown list: items printed on the dispatch gate pass (with default quantity and print row).

Model: `app/models/master_list_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `code` | varchar(120) | no | U |
| `label` | varchar(300) | no |  |
| `sort_order` | integer | no |  |
| `default_qty` | integer | no |  |
| `print_row` | integer | no |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `thermal_check_item_master`

Dropdown list: checkpoints on the dispatch thermal checksheet.

Model: `app/models/master_list_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `code` | varchar(120) | no | U |
| `label` | varchar(300) | no |  |
| `sort_order` | integer | no |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

## Plant layout

### `chassis_location_master`

Macro factory locations in order (Chassis Inward, Production, FVI, PDI, Dispatch, ...).

Model: `app/models/location_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `location_id` | uuid | no | PK |
| `location_code` | varchar(50) | no | U |
| `location_name` | varchar(150) | no |  |
| `sequence_no` | integer | no |  |
| `description` | text | yes |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |

### `station_master`

Production stations, their sequence number, location and line. The order chassis move through.

Model: `app/models/rm_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `station_id` | uuid | no | PK |
| `station_code` | varchar(50) | no | U |
| `station_name` | varchar(255) | no |  |
| `station_description` | text | yes |  |
| `location_id` | uuid | yes | → `chassis_location_master.location_id` |
| `operation_id` | uuid | yes |  |
| `primary_operator_id` | uuid | yes |  |
| `sequence_no` | integer | yes |  |
| `requires_qa` | boolean | no |  |
| `is_rework_station` | boolean | no |  |
| `backflush_enabled` | boolean | no |  |
| `standard_cycle_time_min` | integer | yes |  |
| `alert_threshold_min` | integer | yes |  |
| `is_active` | boolean | no |  |
| `custom_fields` | jsonb | yes |  |
| `created_at` | timestamptz | yes |  |

### `store_master`

Stores (warehouses) that hold raw material.

Model: `app/models/rm_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `store_id` | uuid | no | PK |
| `store_name` | varchar(150) | no |  |
| `location` | varchar(200) | yes |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |

### `yard_checkpoint_master`

Named physical stops a chassis passes (yard, unit gate, main gate, dispatched).

Model: `app/models/yard_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `checkpoint_id` | uuid | no | PK |
| `checkpoint_code` | varchar(50) | no | U |
| `checkpoint_name` | varchar(150) | no |  |
| `sequence_no` | integer | no |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |

### `yard_slot_master`

Parking bays in the yard and their occupancy.

Model: `app/models/yard_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `slot_id` | uuid | no | PK |
| `slot_code` | varchar(20) | no | U |
| `zone` | varchar(5) | yes |  |
| `slot_type` | varchar(20) | yes |  |
| `is_occupied` | boolean | no |  |
| `current_chassis` | varchar(30) | yes |  |
| `notes` | text | yes |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |

## Chassis and yard

### `chassis_master`

One row per chassis (bus). Customer, model, current status, current station / location, key dates.

Model: `app/models/yard_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `chassis_id` | uuid | no | PK |
| `chassis_no` | varchar(100) | no | U |
| `model_id` | uuid | yes | → `vehicle_model_master.model_id` |
| `fuel_type` | varchar(20) | no |  |
| `light_type` | varchar(30) | yes |  |
| `voltage` | varchar(20) | yes |  |
| `transport_id` | varchar(50) | yes | → `transport_master.transport_id` |
| `dealer_id` | varchar(50) | yes | → `customer_master.customer_id` |
| `client_id` | varchar(50) | yes | → `client_master.client_id` |
| `source_type` | varchar(20) | no |  |
| `build_order_id` | uuid | yes |  |
| `dealer_order_vehicle_id` | uuid | yes | → `dealer_order_vehicle.order_vehicle_id` |
| `fuel_receiving_qty` | numeric | yes |  |
| `arrival_date` | date | no |  |
| `arrival_remark` | text | yes |  |
| `yard_location` | varchar(100) | yes |  |
| `da_lite_status` | varchar(20) | no |  |
| `da_lite_checked_at` | timestamptz | yes |  |
| `da_lite_checked_by` | uuid | yes | → `login_users.user_id` |
| `da_lite_photo_url` | text | yes |  |
| `da_lite_remarks` | text | yes |  |
| `current_status` | varchar(30) | no |  |
| `procurement_status` | varchar(30) | no |  |
| `tracking_status` | varchar(20) | no |  |
| `dispatch_photo_url` | text | yes |  |
| `dispatched_at` | timestamptz | yes |  |
| `handed_to_production_at` | timestamptz | yes |  |
| `handed_to_production_by` | uuid | yes | → `login_users.user_id` |
| `scheduled_induction_date` | date | yes |  |
| `scheduled_by` | uuid | yes | → `login_users.user_id` |
| `scheduled_at` | timestamptz | yes |  |
| `remarks` | text | yes |  |
| `created_by` | uuid | yes | → `login_users.user_id` |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |
| `driver_name` | varchar(150) | yes |  |
| `driver_license` | varchar(50) | yes |  |
| `driver_phone` | varchar(20) | yes |  |
| `inbound_vehicle_no` | varchar(20) | yes |  |
| `chassis_condition` | varchar(20) | yes |  |
| `chassis_odometer` | integer | yes |  |
| `inspection_done` | boolean | yes |  |
| `inspection_by` | uuid | yes | → `login_users.user_id` |
| `inspection_at` | timestamptz | yes |  |
| `yard_slot_id` | uuid | yes | → `yard_slot_master.slot_id` |
| `enquiry_id` | uuid | yes | → `sales_enquiry.enquiry_id` |
| `oem` | varchar(50) | yes |  |
| `year_of_manufacture` | smallint | yes |  |
| `transport_company` | varchar(100) | yes |  |
| `build_spec_id` | uuid | yes |  |
| `current_location_id` | uuid | yes | → `chassis_location_master.location_id` |
| `current_station_id` | uuid | yes | → `station_master.station_id` |
| `production_hold_status` | varchar(20) | no |  |
| `station_arrived_at` | timestamptz | yes |  |
| `station_completed_at` | timestamptz | yes |  |

### `chassis_status_log`

History of every status change on a chassis.

Model: `app/models/yard_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `log_id` | uuid | no | PK |
| `chassis_id` | uuid | no | → `chassis_master.chassis_id` |
| `station_id` | uuid | yes | → `station_master.station_id` |
| `station_code` | varchar(50) | yes |  |
| `scan_mode` | varchar(20) | yes |  |
| `from_status` | varchar(20) | yes |  |
| `to_status` | varchar(20) | no |  |
| `changed_by` | uuid | yes | → `login_users.user_id` |
| `changed_at` | timestamptz | no |  |
| `scan_location` | varchar(150) | yes |  |
| `remarks` | text | yes |  |

### `chassis_movement_log`

History of physical movements between yard checkpoints.

Model: `app/models/yard_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `movement_id` | uuid | no | PK |
| `chassis_id` | uuid | no | → `chassis_master.chassis_id` |
| `checkpoint_id` | uuid | no | → `yard_checkpoint_master.checkpoint_id` |
| `responsible_person` | varchar(150) | yes |  |
| `movement_date` | date | yes |  |
| `in_time` | time without time zone | yes |  |
| `out_time` | time without time zone | yes |  |
| `fuel_qty` | numeric | yes |  |
| `remark` | text | yes |  |
| `signature_name` | varchar(150) | yes |  |
| `created_at` | timestamptz | yes |  |

### `chassis_movement_checklist_result`

Answers to the checklist filled on each movement.

Model: `app/models/yard_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `result_id` | uuid | no | PK |
| `movement_id` | uuid | no | → `chassis_movement_log.movement_id` |
| `item_id` | uuid | no | → `movement_checklist_item_master.item_id` |
| `is_ok` | boolean | yes |  |
| `value_text` | varchar(100) | yes |  |

### `movement_checklist_item_master`

Checklist questions asked when a chassis moves.

Model: `app/models/yard_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `item_id` | uuid | no | PK |
| `item_code` | varchar(50) | no | U |
| `item_label` | varchar(150) | no |  |
| `sequence_no` | integer | no |  |
| `is_active` | boolean | no |  |

### `chassis_arrival_document`

Documents received with a chassis on arrival (uploaded files).

Model: `app/models/yard_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `doc_id` | uuid | no | PK |
| `chassis_id` | uuid | no | → `chassis_master.chassis_id` |
| `document_type` | varchar(30) | no |  |
| `document_number` | varchar(100) | yes |  |
| `issue_date` | date | yes |  |
| `valid_until` | date | yes |  |
| `issuing_authority` | varchar(150) | yes |  |
| `file_path` | varchar(500) | yes |  |
| `verification_status` | varchar(20) | no |  |
| `rejection_reason` | text | yes |  |
| `verified_by` | uuid | yes | → `login_users.user_id` |
| `verified_at` | timestamptz | yes |  |
| `created_at` | timestamptz | yes |  |

### `chassis_qa_checklist_result`

Answers to the yard QA checklist on chassis inward.

Model: `app/models/yard_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `result_id` | uuid | no | PK |
| `chassis_id` | uuid | no | → `chassis_master.chassis_id` |
| `item_id` | uuid | no | → `yard_qa_checklist_item_master.item_id` |
| `yard_ok` | boolean | yes |  |
| `yard_remark` | varchar(255) | yes |  |
| `bhagirath_ok` | boolean | yes |  |
| `bhagirath_remark` | varchar(255) | yes |  |
| `fvi_ok` | boolean | yes |  |
| `fvi_remark` | varchar(255) | yes |  |
| `fvi_rework_ok` | boolean | yes |  |
| `fvi_rework_remark` | varchar(255) | yes |  |
| `fvi_rework_pending_ok` | boolean | yes |  |
| `fvi_rework_pending_remark` | varchar(255) | yes |  |
| `updated_at` | timestamptz | yes |  |

### `yard_qa_checklist_item_master`

Questions on the yard QA checklist.

Model: `app/models/yard_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `item_id` | uuid | no | PK |
| `zone_name` | varchar(150) | no |  |
| `checkpoint_text` | text | no |  |
| `sequence_no` | integer | no |  |
| `is_active` | boolean | no |  |

### `customer_supplied_part`

Parts sent by the customer with the chassis (FAPS, AC, seats, ...).

Model: `app/models/yard_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `csp_id` | uuid | no | PK |
| `chassis_id` | uuid | no | → `chassis_master.chassis_id` |
| `rm_id` | uuid | yes | → `rm_master.rm_id` |
| `item_description` | varchar(255) | no |  |
| `item_code` | varchar(100) | yes |  |
| `quantity_received` | numeric | no |  |
| `quantity_verified` | numeric | yes |  |
| `unit_of_measurement` | varchar(50) | yes |  |
| `target_station` | varchar(30) | yes |  |
| `storage_location` | varchar(100) | yes |  |
| `status` | varchar(25) | no |  |
| `damaged_qty` | numeric | yes |  |
| `damage_description` | text | yes |  |
| `issued_to_station` | varchar(30) | yes |  |
| `issued_at` | timestamptz | yes |  |
| `issued_by` | uuid | yes | → `login_users.user_id` |
| `received_by` | uuid | yes | → `login_users.user_id` |
| `received_at` | timestamptz | yes |  |
| `notes` | text | yes |  |
| `created_at` | timestamptz | yes |  |

### `chassis_store_handover`

Header of the store hand-over sheet for a chassis (one per chassis).

Model: `app/models/yard_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `handover_id` | uuid | no | PK |
| `chassis_id` | uuid | no | U → `chassis_master.chassis_id` |
| `store_keeper_id` | uuid | yes | → `login_users.user_id` |
| `handover_date` | date | yes |  |
| `is_locked` | boolean | no |  |
| `signed_store_person` | boolean | no |  |
| `signed_yard_supervisor` | boolean | no |  |
| `store_manager_approved_by` | uuid | yes | → `login_users.user_id` |
| `store_manager_approved_at` | timestamptz | yes |  |
| `yard_supervisor_approved_by` | uuid | yes | → `login_users.user_id` |
| `yard_supervisor_approved_at` | timestamptz | yes |  |
| `created_at` | timestamptz | yes |  |

### `chassis_store_handover_part`

Parts listed on a chassis store hand-over sheet.

Model: `app/models/yard_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `result_id` | uuid | no | PK |
| `handover_id` | uuid | no | U → `chassis_store_handover.handover_id` |
| `part_id` | uuid | no | U → `store_handover_part_master.part_id` |
| `status` | varchar(10) | yes |  |
| `qty` | integer | yes |  |
| `created_at` | timestamptz | yes |  |

### `store_handover_part_master`

Standard parts that appear on the store hand-over sheet.

Model: `app/models/yard_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `part_id` | uuid | no | PK |
| `sr_no` | integer | yes |  |
| `part_name` | varchar(150) | no |  |
| `fuel_applicability` | varchar(20) | no |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |

### `vehicle_model_master`

Chassis / vehicle models (model number and name).

Model: `app/models/yard_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `model_id` | uuid | no | PK |
| `model_number` | varchar(100) | no | U |
| `image_url` | varchar(255) | yes |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |

## Production

### `chassis_station_log`

Check-in and check-out of a chassis at each station, with timings and operator.

Model: `app/models/production_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `log_id` | uuid | no | PK |
| `chassis_id` | uuid | no | → `chassis_master.chassis_id` |
| `station_id` | uuid | no | → `station_master.station_id` |
| `event_type` | varchar(20) | no |  |
| `scanned_at` | timestamptz | no |  |
| `scanned_by` | uuid | yes | → `login_users.user_id` |
| `scan_mode` | varchar(20) | no |  |
| `elapsed_minutes` | integer | yes |  |
| `is_overdue` | boolean | no |  |
| `delay_reason_id` | uuid | yes | → `delay_reason_master.delay_reason_id` |
| `delay_remarks` | text | yes |  |
| `delay_logged_by` | uuid | yes | → `login_users.user_id` |
| `delay_logged_at` | timestamptz | yes |  |
| `status` | varchar(20) | no |  |
| `remarks` | text | yes |  |
| `created_at` | timestamptz | yes |  |

### `chassis_station_handoff`

Hand-over of a chassis from one station to the next; the QA gate (AWAITING_QA, QA_PASSED, RELEASED, RECEIVED).

Model: `app/models/station_work_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `handoff_id` | uuid | no | PK |
| `chassis_id` | uuid | no | → `chassis_master.chassis_id` |
| `from_station_id` | uuid | no | → `station_master.station_id` |
| `to_station_id` | uuid | yes | → `station_master.station_id` |
| `status` | varchar(20) | no |  |
| `completed_at` | timestamptz | yes |  |
| `completed_by` | uuid | yes | → `login_users.user_id` |
| `released_at` | timestamptz | yes |  |
| `released_by` | uuid | yes | → `login_users.user_id` |
| `received_at` | timestamptz | yes |  |
| `remarks` | text | yes |  |

### `production_hold`

Holds placed on a chassis in production, with type, reason and release.

Model: `app/models/production_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `hold_id` | uuid | no | PK |
| `chassis_id` | uuid | no | → `chassis_master.chassis_id` |
| `station_id` | uuid | yes | → `station_master.station_id` |
| `hold_type` | varchar(50) | no |  |
| `hold_reason` | text | no |  |
| `raised_by` | uuid | no | → `login_users.user_id` |
| `raised_at` | timestamptz | yes |  |
| `resolved_by` | uuid | yes | → `login_users.user_id` |
| `resolved_at` | timestamptz | yes |  |
| `resolution_notes` | text | yes |  |
| `status` | varchar(20) | no |  |
| `created_at` | timestamptz | yes |  |

### `delay_reason_master`

Reasons recorded when a station runs over its standard time.

Model: `app/models/production_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `delay_reason_id` | uuid | no | PK |
| `reason_code` | varchar(50) | no | U |
| `reason_label` | varchar(200) | no |  |
| `category` | varchar(50) | no |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |

### `production_report_manual_entry`

Columns of the production report that staff type in by hand, one row per chassis.

Model: `app/models/production_report_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `chassis_id` | uuid | no | U → `chassis_master.chassis_id` |
| `contractor_group` | varchar(10) | yes |  |
| `ac_make` | varchar(50) | yes |  |
| `interior_work` | varchar(50) | yes |  |
| `driver_request` | text | yes |  |
| `document_pending` | text | yes |  |
| `seat_fitting_pending` | text | yes |  |
| `remark` | text | yes |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `chassis_bom_snapshot`

Frozen bill of materials for one chassis: part, quantity, station, reserved / consumed quantity.

Model: `app/models/procurement_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `chassis_id` | uuid | no | → `chassis_master.chassis_id` |
| `rm_id` | uuid | no | → `rm_master.rm_id` |
| `quantity` | numeric | no |  |
| `reserved_qty` | numeric | no |  |
| `consumed_qty` | numeric | no |  |
| `station_id` | uuid | yes | → `station_master.station_id` |
| `created_at` | timestamptz | yes |  |

## Quality (QA)

### `qa_checksheet_template`

QA checksheet definitions (name, version, applicability flags).

Model: `app/models/qa_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `template_id` | uuid | no | PK |
| `template_code` | varchar(50) | no | U |
| `template_name` | varchar(200) | no |  |
| `station_id` | uuid | yes | → `station_master.station_id` |
| `format_no` | varchar(50) | yes |  |
| `revision` | varchar(20) | yes |  |
| `revision_date` | date | yes |  |
| `description` | text | yes |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `qa_checksheet_section`

Sections within a checksheet template.

Model: `app/models/qa_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `section_id` | uuid | no | PK |
| `template_id` | uuid | no | → `qa_checksheet_template.template_id` |
| `section_no` | integer | no |  |
| `section_name` | varchar(200) | no |  |
| `description` | text | yes |  |
| `sort_order` | integer | yes |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |

### `qa_checkpoint_item`

Individual checkpoints within a section (what to check, specification, mandatory flag).

Model: `app/models/qa_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `item_id` | uuid | no | PK |
| `section_id` | uuid | no | → `qa_checksheet_section.section_id` |
| `item_no` | integer | no |  |
| `area_desc` | varchar(255) | yes |  |
| `checkpoint_desc` | text | no |  |
| `checkpoint_class` | varchar(20) | no |  |
| `verification_method` | varchar(100) | yes |  |
| `standard_specification` | text | yes |  |
| `requires_measurement` | boolean | no |  |
| `min_value` | numeric | yes |  |
| `max_value` | numeric | yes |  |
| `unit_of_measure` | varchar(20) | yes |  |
| `special_feature_flag` | varchar(100) | yes |  |
| `frequency` | varchar(100) | yes |  |
| `sort_order` | integer | yes |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |

### `qa_station_template_map`

Which checksheet templates apply at which station.

Model: `app/models/qa_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `map_id` | uuid | no | PK |
| `station_id` | uuid | no | → `station_master.station_id` |
| `template_id` | uuid | no | → `qa_checksheet_template.template_id` |
| `model_id` | uuid | yes | → `vehicle_model_master.model_id` |
| `model_ids` | jsonb | yes |  |
| `body_type_id` | uuid | yes | → `body_type_master.body_type_id` |
| `body_type_ids` | jsonb | yes |  |
| `sort_order` | integer | yes |  |
| `is_mandatory` | boolean | no |  |
| `created_at` | timestamptz | yes |  |

### `qa_checksheet_instance`

A checksheet being filled for one chassis at one station, with status and overall remarks.

Model: `app/models/qa_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `instance_id` | uuid | no | PK |
| `template_id` | uuid | no | → `qa_checksheet_template.template_id` |
| `chassis_id` | uuid | no | → `chassis_master.chassis_id` |
| `chassis_no` | varchar(50) | yes |  |
| `station_id` | uuid | no | → `station_master.station_id` |
| `station_log_id` | uuid | yes | → `chassis_station_log.log_id` |
| `inspector_id` | uuid | yes | → `login_users.user_id` |
| `inspection_date` | timestamptz | yes |  |
| `shift` | varchar(20) | yes |  |
| `status` | varchar(20) | yes |  |
| `overall_result` | varchar(20) | no |  |
| `station_qa_status` | varchar(20) | no |  |
| `remarks` | text | yes |  |
| `rework_notes` | text | yes |  |
| `completed_at` | timestamptz | yes |  |
| `passed_by` | uuid | yes | → `login_users.user_id` |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `qa_checkpoint_response`

Answer to one checkpoint on an instance (OK / NOT OK / NA, value, remark).

Model: `app/models/qa_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `response_id` | uuid | no | PK |
| `instance_id` | uuid | no | → `qa_checksheet_instance.instance_id` |
| `item_id` | uuid | no | → `qa_checkpoint_item.item_id` |
| `status` | varchar(20) | no |  |
| `measured_value` | numeric | yes |  |
| `observation` | text | yes |  |
| `rework_status` | varchar(20) | yes |  |
| `after_rework_observation` | text | yes |  |
| `after_rework_verified_by` | uuid | yes | → `login_users.user_id` |
| `na_reason` | text | yes |  |
| `is_flagged` | boolean | no |  |
| `flagged_by` | uuid | yes | → `login_users.user_id` |
| `flagged_at` | timestamptz | yes |  |
| `created_at` | timestamptz | yes |  |

### `qa_response_photo`

Photos attached to a checkpoint answer.

Model: `app/models/station_work_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `photo_id` | uuid | no | PK |
| `instance_id` | uuid | no | → `qa_checksheet_instance.instance_id` |
| `item_id` | uuid | no | → `qa_checkpoint_item.item_id` |
| `photo_url` | text | no |  |
| `uploaded_by` | uuid | yes | → `login_users.user_id` |
| `uploaded_at` | timestamptz | yes |  |

### `qa_section_remark`

Inspector remark on a whole section of a checksheet instance.

Model: `app/models/station_work_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `remark_id` | uuid | no | PK |
| `instance_id` | uuid | no | U → `qa_checksheet_instance.instance_id` |
| `section_id` | uuid | no | U → `qa_checksheet_section.section_id` |
| `remark` | text | no |  |
| `updated_by` | uuid | yes | → `login_users.user_id` |
| `updated_at` | timestamptz | yes |  |

### `qa_checksheet_signoff`

Sign-off of a checksheet instance (who, when, outcome).

Model: `app/models/qa_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `signoff_id` | uuid | no | PK |
| `instance_id` | uuid | no | → `qa_checksheet_instance.instance_id` |
| `signoff_type` | varchar(50) | no |  |
| `signed_by_user_id` | uuid | yes | → `login_users.user_id` |
| `signed_by_name` | varchar(255) | no |  |
| `signed_by` | uuid | yes | → `login_users.user_id` |
| `role` | varchar(50) | yes |  |
| `signed_at` | timestamptz | yes |  |
| `remarks` | text | yes |  |

### `qa_shortage_log`

Parts found short during QA, and their resolution.

Model: `app/models/qa_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `shortage_id` | uuid | no | PK |
| `chassis_id` | uuid | no | → `chassis_master.chassis_id` |
| `station_id` | uuid | no | → `station_master.station_id` |
| `bom_snapshot_id` | uuid | yes | → `chassis_bom_snapshot.id` |
| `rm_id` | uuid | no | → `rm_master.rm_id` |
| `required_qty` | numeric | no |  |
| `fitted_qty` | numeric | no |  |
| `status` | varchar(20) | no |  |
| `noted_by` | uuid | no | → `login_users.user_id` |
| `noted_at` | timestamptz | yes |  |
| `resolved_by` | uuid | yes | → `login_users.user_id` |
| `resolved_at` | timestamptz | yes |  |
| `remarks` | text | yes |  |
| `created_at` | timestamptz | yes |  |

### `station_qa_checklist_item_master`

Older per-station QA checklist questions (kept for history).

Model: `app/models/location_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `item_id` | uuid | no | PK |
| `station_id` | uuid | no | → `station_master.station_id` |
| `zone_name` | varchar(150) | no |  |
| `checkpoint_text` | text | no |  |
| `specification` | text | yes |  |
| `sequence_no` | integer | no |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |

### `chassis_station_qa_result`

Older per-station QA results per chassis scan (kept for history).

Model: `app/models/location_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `result_id` | uuid | no | PK |
| `chassis_id` | uuid | no | → `chassis_master.chassis_id` |
| `station_id` | uuid | no | → `station_master.station_id` |
| `item_id` | uuid | no | → `station_qa_checklist_item_master.item_id` |
| `is_ok` | boolean | no |  |
| `remark` | varchar(255) | yes |  |
| `inspected_by` | uuid | yes | → `login_users.user_id` |
| `inspected_at` | timestamptz | yes |  |

## Dispatch

### `dispatch_gate_pass`

Gate pass issued when a bus leaves the plant.

Model: `app/models/dispatch_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `gate_pass_id` | uuid | no | PK |
| `checksheet_id` | uuid | yes | → `dispatch_thermal_checksheet.checksheet_id` |
| `chassis_id` | uuid | no | → `chassis_master.chassis_id` |
| `chassis_no` | varchar(100) | no |  |
| `generated_at` | timestamptz | yes |  |
| `fuel_before_ltr` | numeric | yes |  |
| `filling_fuel_qty_ltr` | numeric | yes |  |
| `driver_name` | varchar(255) | yes |  |
| `driver_photo_url` | text | yes |  |
| `dispatch_authority` | varchar(255) | yes |  |
| `created_by` | uuid | yes | → `login_users.user_id` |
| `created_at` | timestamptz | yes |  |

### `dispatch_gate_pass_item`

Items listed on a gate pass, with quantities.

Model: `app/models/dispatch_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `gate_pass_item_id` | uuid | no | PK |
| `gate_pass_id` | uuid | no | → `dispatch_gate_pass.gate_pass_id` |
| `item_key` | varchar(50) | no |  |
| `item_label` | varchar(100) | no |  |
| `is_checked` | boolean | no |  |
| `qty` | integer | no |  |

### `dispatch_thermal_checksheet`

Thermal (AC) checksheet filled before dispatch.

Model: `app/models/dispatch_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `checksheet_id` | uuid | no | PK |
| `chassis_id` | uuid | no | → `chassis_master.chassis_id` |
| `chassis_no` | varchar(100) | no |  |
| `model` | varchar(100) | yes |  |
| `engine_type` | varchar(50) | yes |  |
| `check_date` | date | yes |  |
| `signature` | varchar(255) | yes |  |
| `photo_front` | text | yes |  |
| `photo_rear` | text | yes |  |
| `photo_rh` | text | yes |  |
| `photo_lh` | text | yes |  |
| `all_ok` | boolean | no |  |
| `submitted_by` | uuid | yes | → `login_users.user_id` |
| `submitted_at` | timestamptz | yes |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `dispatch_thermal_checksheet_item`

Readings / answers on a thermal checksheet.

Model: `app/models/dispatch_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `item_result_id` | uuid | no | PK |
| `checksheet_id` | uuid | no | → `dispatch_thermal_checksheet.checksheet_id` |
| `item_no` | integer | no |  |
| `item_text` | text | yes |  |
| `is_ok` | boolean | no |  |
| `photo_url` | text | yes |  |
| `authority_name` | varchar(255) | yes |  |
| `fault_type` | varchar(30) | yes |  |
| `remarks` | text | yes |  |
| `mail_screenshot_url` | text | yes |  |

## Products, BOM and configuration

### `product_master`

Sellable products (body type + segment + model combinations).

Model: `app/models/bom_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `product_id` | uuid | no | PK |
| `name` | varchar(255) | no |  |
| `product_code` | varchar(100) | yes | U |
| `description` | text | yes |  |
| `unit_of_measurement` | varchar(50) | no |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | no |  |
| `updated_at` | timestamptz | no |  |

### `bom_master`

Bill of materials header per product.

Model: `app/models/bom_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `bom_id` | uuid | no | PK |
| `product_id` | uuid | no | → `product_master.product_id` |
| `bom_number` | varchar(100) | no | U |
| `description` | text | yes |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | no |  |
| `updated_at` | timestamptz | no |  |

### `bom_detail`

Parts and quantities in a BOM, and the station that consumes them.

Model: `app/models/bom_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `bom_detail_id` | uuid | no | PK |
| `bom_id` | uuid | no | → `bom_master.bom_id` |
| `rm_id` | uuid | no | → `rm_master.rm_id` |
| `quantity` | numeric | no |  |
| `uom` | varchar(50) | yes |  |
| `created_at` | timestamptz | no |  |

### `special_feature_master`

Optional features a customer can choose (door type, AC, dicky, ...).

Model: `app/models/dealer_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `feature_id` | uuid | no | PK |
| `section` | varchar(100) | no |  |
| `feature_name` | varchar(200) | no |  |
| `input_type` | varchar(20) | no |  |
| `sequence_no` | integer | no |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |

### `special_feature_option_master`

Choices available for each special feature.

Model: `app/models/dealer_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `option_id` | uuid | no | PK |
| `feature_id` | uuid | no | → `special_feature_master.feature_id` |
| `option_value` | varchar(150) | no |  |
| `image_url` | varchar(500) | yes |  |
| `sequence_no` | integer | no |  |
| `is_active` | boolean | no |  |
| `restricted_model_ids` | jsonb | yes |  |
| `restricted_body_type_ids` | jsonb | yes |  |
| `restricted_segment_ids` | jsonb | yes |  |
| `restricted_combinations` | jsonb | yes |  |

### `special_feature_bom`

Extra parts required when a feature option is chosen.

Model: `app/models/bom_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `option_id` | uuid | no | U → `special_feature_option_master.option_id` |
| `rm_id` | uuid | no | U → `rm_master.rm_id` |
| `quantity` | numeric | no |  |
| `uom` | varchar(50) | yes |  |
| `created_at` | timestamptz | no |  |
| `updated_at` | timestamptz | no |  |

### `feature_segment_map`

Which customer segments see a given special feature.

Model: `app/models/dealer_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `feature_id` | uuid | no | U → `special_feature_master.feature_id` |
| `segment_id` | uuid | no | U → `customer_segment_master.segment_id` |

### `body_type_master`

Bus body types.

Model: `app/models/dealer_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `body_type_id` | uuid | no | PK |
| `name` | varchar(100) | no | U |
| `image_url` | varchar(500) | yes |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |

### `customer_segment_master`

Customer segments (school, staff, tourist, ...).

Model: `app/models/dealer_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `segment_id` | uuid | no | PK |
| `name` | varchar(100) | no | U |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |

### `model_body_type_map`

Which body types are offered on which chassis model.

Model: `app/models/dealer_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `model_id` | uuid | no | U → `vehicle_model_master.model_id` |
| `body_type_id` | uuid | no | U → `body_type_master.body_type_id` |

### `model_segment_map`

Which segments are offered on which chassis model.

Model: `app/models/dealer_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `model_id` | uuid | no | U → `vehicle_model_master.model_id` |
| `segment_id` | uuid | no | U → `customer_segment_master.segment_id` |

### `seating_layout_master`

Seating layouts (seat count and arrangement, with image).

Model: `app/models/dealer_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `layout_id` | uuid | no | PK |
| `layout_no` | varchar(100) | no | U |
| `chassis_model` | varchar(100) | no |  |
| `body_type` | varchar(100) | no |  |
| `segment` | varchar(100) | no |  |
| `door_type` | varchar(100) | no |  |
| `seat_type` | varchar(100) | no |  |
| `seating_type` | varchar(100) | no |  |
| `seating_capacity` | varchar(100) | no |  |
| `image_url` | varchar(500) | yes |  |
| `pdf_url` | varchar(500) | yes |  |
| `created_at` | timestamptz | yes |  |

### `seat_model_configuration`

Valid seat model, supplier and dimensions for a body type, seat type and layout size.

Model: `app/models/dealer_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `body_type_id` | uuid | no | → `body_type_master.body_type_id` |
| `seat_type` | varchar(100) | no |  |
| `layout_size` | varchar(50) | no |  |
| `seat_model_option_id` | uuid | no | → `special_feature_option_master.option_id` |
| `supplier_option_id` | uuid | no | → `special_feature_option_master.option_id` |
| `dimensions_option_id` | uuid | no | → `special_feature_option_master.option_id` |
| `image_url` | varchar(500) | yes |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |

### `rto_master`

RTO (vehicle registration office) list.

Model: `app/models/dealer_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `rto_id` | uuid | no | PK |
| `name` | varchar(150) | no |  |
| `description` | text | yes |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |

## Sales and customers

### `customer_master`

Customers and dealers (company, contact, GST, type, region).

Model: `app/models/sales_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `customer_id` | varchar(50) | no | PK |
| `name` | varchar(200) | no |  |
| `type_code` | varchar(50) | yes | → `customer_type_master.type_code` |
| `goodwill_reason` | text | yes |  |
| `gstin` | varchar(50) | yes |  |
| `pan` | varchar(50) | yes |  |
| `billing_address` | text | yes |  |
| `shipping_address` | text | yes |  |
| `city` | varchar(100) | yes |  |
| `state` | varchar(100) | yes |  |
| `pincode` | varchar(20) | yes |  |
| `region` | varchar(50) | yes |  |
| `is_active` | boolean | yes |  |
| `portal_enabled` | boolean | no |  |
| `allow_chassis_tracking` | boolean | no |  |
| `portal_username` | varchar(100) | yes | U |
| `portal_password_hash` | varchar(255) | yes |  |
| `created_at` | timestamp | yes |  |
| `updated_at` | timestamp | yes |  |

### `customer_type_master`

Customer types (DEALER, DIRECT, ...).

Model: `app/models/sales_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `type_code` | varchar(50) | no | PK |
| `name` | varchar(100) | no |  |
| `is_active` | boolean | yes |  |

### `customer_contact`

Additional contact people for a customer.

Model: `app/models/sales_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `contact_id` | varchar(50) | no | PK |
| `customer_id` | varchar(50) | no | → `customer_master.customer_id` |
| `name` | varchar(100) | no |  |
| `designation` | varchar(100) | yes |  |
| `email` | varchar(100) | yes |  |
| `phone` | varchar(20) | yes |  |
| `is_primary` | boolean | yes |  |
| `is_active` | boolean | yes |  |
| `created_at` | timestamp | yes |  |
| `updated_at` | timestamp | yes |  |

### `client_master`

End clients bought for through a dealer (sales side).

Model: `app/models/sales_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `client_id` | varchar(50) | no | PK |
| `name` | varchar(200) | no |  |
| `contact_person` | varchar(150) | yes |  |
| `phone` | varchar(20) | yes |  |
| `email` | varchar(150) | yes |  |
| `address` | text | yes |  |
| `city` | varchar(100) | yes |  |
| `state` | varchar(100) | yes |  |
| `is_active` | boolean | no |  |
| `created_by_user_id` | uuid | yes | → `login_users.user_id` |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `dealer_client_map`

Which dealer serves which client.

Model: `app/models/sales_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `map_id` | uuid | no | PK |
| `dealer_id` | varchar(50) | no | → `customer_master.customer_id` |
| `client_id` | varchar(50) | no | → `client_master.client_id` |
| `created_at` | timestamptz | yes |  |

### `transport_master`

Transporters used for delivery.

Model: `app/models/sales_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `transport_id` | varchar(50) | no | PK |
| `name` | varchar(200) | no |  |
| `contact_person` | varchar(100) | yes |  |
| `contact_number` | varchar(20) | yes |  |
| `vehicle_type` | varchar(50) | yes |  |
| `active` | boolean | yes |  |
| `created_at` | timestamp | yes |  |

### `sales_enquiry`

Sales enquiries (lead pipeline).

Model: `app/models/sales_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `enquiry_id` | uuid | no | PK |
| `customer_id` | varchar(50) | no | → `customer_master.customer_id` |
| `request_details` | text | no |  |
| `status` | varchar(20) | no |  |
| `created_by` | uuid | no | → `login_users.user_id` |
| `assigned_to` | uuid | yes | → `login_users.user_id` |
| `created_at` | timestamp | yes |  |
| `updated_at` | timestamp | yes |  |
| `total_chassis_ordered` | integer | yes |  |
| `chassis_arrived_count` | integer | yes |  |
| `expected_arrival_start` | date | yes |  |
| `expected_arrival_end` | date | yes |  |

### `sales_activity_log`

Activity history on sales enquiries and orders.

Model: `app/models/sales_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `log_id` | uuid | no | PK |
| `entity_type` | varchar(50) | no |  |
| `entity_id` | uuid | no |  |
| `activity_type` | varchar(50) | no |  |
| `old_value` | text | yes |  |
| `new_value` | text | yes |  |
| `remarks` | text | yes |  |
| `performed_by` | uuid | yes |  |
| `created_at` | timestamp | yes |  |

### `sales_vehicle_template`

Saved vehicle configurations for internal sales use.

Model: `app/models/sales_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `template_id` | uuid | no | PK |
| `name` | varchar(100) | no |  |
| `model_id` | uuid | yes | → `vehicle_model_master.model_id` |
| `body_type_id` | uuid | yes | → `body_type_master.body_type_id` |
| `segment_id` | uuid | yes | → `customer_segment_master.segment_id` |
| `created_by_user_id` | uuid | yes | → `login_users.user_id` |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `sales_vehicle_template_feature`

Feature choices stored in a sales vehicle template.

Model: `app/models/sales_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `template_id` | uuid | no | → `sales_vehicle_template.template_id` |
| `feature_id` | uuid | no | → `special_feature_master.feature_id` |
| `feature_option_id` | uuid | yes | → `special_feature_option_master.option_id` |
| `bool_value` | boolean | yes |  |
| `text_value` | text | yes |  |
| `image_url` | varchar(500) | yes |  |

### `payment_receipt`

Payments received from customers.

Model: `app/models/sales_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `payment_id` | uuid | no | PK |
| `customer_id` | varchar(50) | yes | → `customer_master.customer_id` |
| `order_id` | uuid | yes | → `dealer_order.order_id` |
| `amount` | float8 | no |  |
| `payment_mode` | varchar(20) | yes |  |
| `reference_no` | varchar(100) | yes |  |
| `status` | varchar(20) | yes |  |
| `recorded_by` | uuid | yes | → `login_users.user_id` |
| `created_at` | timestamp | yes |  |
| `updated_at` | timestamp | yes |  |

### `customer_payment_log`

Payment ledger entries per customer / order.

Model: `app/models/sales_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `payment_id` | uuid | no | PK |
| `customer_id` | varchar(50) | no | → `customer_master.customer_id` |
| `order_id` | uuid | yes | → `dealer_order.order_id` |
| `amount` | float8 | no |  |
| `payment_mode` | varchar(50) | no |  |
| `reference_no` | varchar(100) | yes |  |
| `status` | varchar(20) | no |  |
| `recorded_by` | uuid | no |  |
| `confirmed_by` | uuid | yes |  |
| `created_at` | timestamp | yes |  |

### `goodwill_approval_log`

Approvals for goodwill (discount / free-of-cost) requests.

Model: `app/models/sales_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `approval_id` | uuid | no | PK |
| `entity_type` | varchar(50) | no |  |
| `entity_id` | uuid | no |  |
| `requested_by` | uuid | no |  |
| `reason` | text | no |  |
| `status` | varchar(20) | no |  |
| `manager_id` | uuid | yes |  |
| `manager_notes` | text | yes |  |
| `created_at` | timestamp | yes |  |

### `da_lite_hold_log`

Holds and releases on an order under the DA-Lite process.

Model: `app/models/sales_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `log_id` | uuid | no | PK |
| `order_id` | uuid | no | → `dealer_order.order_id` |
| `action` | varchar(50) | no |  |
| `reason` | text | no |  |
| `performed_by` | uuid | yes |  |
| `created_at` | timestamp | yes |  |

### `service_order`

After-sales service orders.

Model: `app/models/sales_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `service_id` | uuid | no | PK |
| `order_id` | uuid | yes | → `dealer_order.order_id` |
| `customer_id` | varchar(50) | no | → `customer_master.customer_id` |
| `chassis_no` | varchar(100) | yes |  |
| `service_type` | varchar(50) | no |  |
| `status` | varchar(20) | no |  |
| `notes` | text | yes |  |
| `cost` | float8 | no |  |
| `created_at` | timestamp | yes |  |

### `spare_parts_order`

Spare parts orders from customers.

Model: `app/models/sales_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `order_id` | uuid | no | PK |
| `customer_id` | varchar(50) | no | → `customer_master.customer_id` |
| `total_amount` | float8 | no |  |
| `payment_status` | varchar(20) | no |  |
| `status` | varchar(20) | no |  |
| `created_by` | uuid | no | → `login_users.user_id` |
| `created_at` | timestamp | yes |  |

### `spare_parts_order_detail`

Lines of a spare parts order.

Model: `app/models/sales_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `detail_id` | uuid | no | PK |
| `order_id` | uuid | no | → `spare_parts_order.order_id` |
| `rm_id` | uuid | no | → `rm_master.rm_id` |
| `qty` | float8 | no |  |
| `unit_price` | float8 | no |  |
| `line_amount` | float8 | no |  |

## Dealer portal

### `dealer_order`

Orders placed by dealers (header, status, totals).

Model: `app/models/dealer_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `order_id` | uuid | no | PK |
| `order_no` | varchar(50) | no | U |
| `dealer_id` | varchar(50) | no | → `customer_master.customer_id` |
| `client_id` | varchar(50) | no | → `client_master.client_id` |
| `status` | varchar(30) | no |  |
| `remarks` | text | yes |  |
| `rep_name` | varchar(100) | yes |  |
| `rep_contact` | varchar(50) | yes |  |
| `billing_by` | varchar(10) | yes |  |
| `submitted_at` | timestamptz | yes |  |
| `confirmed_at` | timestamptz | yes |  |
| `build_order_id` | uuid | yes |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `dealer_order_vehicle`

Vehicles (configured buses) within a dealer order.

Model: `app/models/dealer_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `order_vehicle_id` | uuid | no | PK |
| `order_id` | uuid | no | → `dealer_order.order_id` |
| `model_id` | uuid | no | → `vehicle_model_master.model_id` |
| `body_type_id` | uuid | no | → `body_type_master.body_type_id` |
| `segment_id` | uuid | no | → `customer_segment_master.segment_id` |
| `rto_id` | uuid | yes | → `rto_master.rto_id` |
| `qty` | integer | no |  |
| `sequence_no` | integer | no |  |
| `notes` | text | yes |  |
| `is_edited` | boolean | no |  |
| `edited_fields` | jsonb | yes |  |

### `dealer_order_vehicle_feature`

Feature choices for a vehicle on a dealer order.

Model: `app/models/dealer_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `order_vehicle_id` | uuid | no | U → `dealer_order_vehicle.order_vehicle_id` |
| `feature_id` | uuid | no | U → `special_feature_master.feature_id` |
| `feature_option_id` | uuid | yes | → `special_feature_option_master.option_id` |
| `bool_value` | boolean | yes |  |
| `text_value` | text | yes |  |
| `image_url` | varchar(500) | yes |  |

### `dealer_order_vehicle_chassis`

Chassis allocated to a vehicle line on a dealer order.

Model: `app/models/dealer_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `order_vehicle_id` | uuid | no | → `dealer_order_vehicle.order_vehicle_id` |
| `seq_no` | integer | no |  |
| `chassis_no` | varchar(100) | yes |  |
| `expected_delivery_date` | date | yes |  |

### `dealer_order_activity_log`

History of actions on a dealer order.

Model: `app/models/dealer_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `order_id` | uuid | no | → `dealer_order.order_id` |
| `action` | varchar(30) | no |  |
| `performed_by_dealer` | boolean | no |  |
| `performed_by_user_id` | uuid | yes | → `login_users.user_id` |
| `notes` | text | yes |  |
| `created_at` | timestamptz | yes |  |

### `dealer_client_master`

A dealer's own clients, shared by the dealer portal and the sales portal.

Model: `app/models/dealer_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `client_id` | varchar(50) | no | PK |
| `dealer_id` | varchar(50) | no | → `customer_master.customer_id` |
| `name` | varchar(200) | no |  |
| `contact_person` | varchar(150) | yes |  |
| `phone` | varchar(20) | yes |  |
| `email` | varchar(150) | yes |  |
| `address` | text | yes |  |
| `city` | varchar(100) | yes |  |
| `state` | varchar(100) | yes |  |
| `is_active` | boolean | no |  |
| `created_by_dealer` | boolean | no |  |
| `created_by_user_id` | uuid | yes | → `login_users.user_id` |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `dealer_request`

Requests raised by dealers (new feature, change, query).

Model: `app/models/dealer_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `request_id` | uuid | no | PK |
| `dealer_id` | varchar(50) | no | → `customer_master.customer_id` |
| `request_type` | varchar(50) | no |  |
| `details` | text | no |  |
| `photo_url` | varchar(500) | yes |  |
| `photo_urls` | jsonb | yes |  |
| `status` | varchar(30) | no |  |
| `acknowledged_by` | uuid | yes | → `login_users.user_id` |
| `acknowledged_at` | timestamptz | yes |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `dealer_vehicle_template`

Vehicle configurations saved by a dealer.

Model: `app/models/dealer_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `template_id` | uuid | no | PK |
| `dealer_id` | varchar(50) | no | → `customer_master.customer_id` |
| `name` | varchar(100) | no |  |
| `model_id` | uuid | no | → `vehicle_model_master.model_id` |
| `body_type_id` | uuid | no | → `body_type_master.body_type_id` |
| `segment_id` | uuid | no | → `customer_segment_master.segment_id` |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `dealer_vehicle_template_feature`

Feature choices stored in a dealer vehicle template.

Model: `app/models/dealer_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `template_id` | uuid | no | U → `dealer_vehicle_template.template_id` |
| `feature_id` | uuid | no | U → `special_feature_master.feature_id` |
| `feature_option_id` | uuid | yes | → `special_feature_option_master.option_id` |
| `bool_value` | boolean | yes |  |
| `text_value` | text | yes |  |
| `image_url` | varchar(500) | yes |  |

### `dealer_portal_log`

Dealer portal login / session log.

Model: `app/models/dealer_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `log_id` | uuid | no | PK |
| `dealer_id` | varchar(50) | no | → `customer_master.customer_id` |
| `session_token` | varchar(128) | no | U |
| `ip_address` | varchar(50) | yes |  |
| `user_agent` | text | yes |  |
| `issued_at` | timestamptz | no |  |
| `expires_at` | timestamptz | no |  |
| `invalidated_at` | timestamptz | yes |  |

### `dealer_portal_action_log`

Actions performed by dealers in the portal.

Model: `app/models/dealer_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `action_id` | uuid | no | PK |
| `dealer_id` | varchar(50) | no | → `customer_master.customer_id` |
| `action_type` | varchar(50) | no |  |
| `entity_type` | varchar(50) | yes |  |
| `entity_id` | varchar(50) | yes |  |
| `action_details` | jsonb | yes |  |
| `ip_address` | varchar(50) | yes |  |
| `created_at` | timestamptz | yes |  |

### `dealer_portal_admin_action_log`

Actions performed by staff on dealer portal data.

Model: `app/models/dealer_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `action_id` | uuid | no | PK |
| `admin_user_id` | uuid | no |  |
| `dealer_id` | varchar(50) | yes | → `customer_master.customer_id` |
| `action_type` | varchar(50) | no |  |
| `action_details` | jsonb | yes |  |
| `ip_address` | varchar(50) | yes |  |
| `created_at` | timestamptz | yes |  |

## Raw material, stores and procurement

### `rm_master`

Raw material (part) master: part number, description, unit, group, reorder levels.

Model: `app/models/rm_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `rm_id` | uuid | no | PK |
| `name` | varchar(255) | no |  |
| `part_no` | varchar(100) | yes | U |
| `unit_of_measurement` | varchar(50) | no |  |
| `description` | text | yes |  |
| `material_type_id` | uuid | yes | → `material_type_master.id` |
| `procurement_source_id` | uuid | yes | → `procurement_source_master.id` |
| `station_id` | uuid | yes | → `station_master.station_id` |
| `minimum_stock` | numeric | yes |  |
| `lead_time_days` | integer | yes |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | no |  |
| `updated_at` | timestamptz | no |  |

### `material_type_master`

Raw material types.

Model: `app/models/rm_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `name` | varchar(100) | no |  |
| `description` | text | yes |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | no |  |

### `rm_store_mapping`

Which store holds which raw material.

Model: `app/models/rm_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `mapping_id` | uuid | no | PK |
| `rm_id` | uuid | no | U → `rm_master.rm_id` |
| `store_id` | uuid | no | U → `store_master.store_id` |
| `min_stock_level` | numeric | yes |  |
| `max_stock_level` | numeric | yes |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |

### `rm_vendor_mapping`

Approved vendors for each raw material, with rate and lead time.

Model: `app/models/rm_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `mapping_id` | uuid | no | PK |
| `rm_id` | uuid | no | U → `rm_master.rm_id` |
| `vendor_id` | uuid | no | U → `vendor_master.vendor_id` |
| `standard_cost` | numeric | yes |  |
| `lead_time_days` | integer | yes |  |
| `is_active` | boolean | no |  |
| `description` | text | yes |  |
| `created_at` | timestamptz | yes |  |

### `rm_inventory`

Current stock of each raw material per store.

Model: `app/models/rm_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `inventory_id` | uuid | no | PK |
| `rm_id` | uuid | no | U → `rm_master.rm_id` |
| `store_id` | uuid | no | U → `store_master.store_id` |
| `current_qty` | numeric | no |  |
| `reserved_qty` | numeric | yes |  |
| `in_transit_qty` | numeric | yes |  |
| `last_updated` | timestamptz | no |  |

### `rm_inventory_log`

Every stock movement (receipt, issue, adjustment) with before / after quantity.

Model: `app/models/rm_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `log_id` | uuid | no | PK |
| `rm_id` | uuid | no | → `rm_master.rm_id` |
| `store_id` | uuid | no | → `store_master.store_id` |
| `transaction_type` | varchar(50) | no |  |
| `qty` | numeric | no |  |
| `balance_before` | numeric | no |  |
| `balance_after` | numeric | no |  |
| `reference_type` | varchar(50) | yes |  |
| `reference_id` | uuid | yes |  |
| `remarks` | text | yes |  |
| `created_at` | timestamptz | yes |  |

### `rm_consumption_log`

Material consumed against a chassis / station.

Model: `app/models/rm_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `consumption_id` | uuid | no | PK |
| `rm_id` | uuid | no | → `rm_master.rm_id` |
| `store_id` | uuid | no | → `store_master.store_id` |
| `qty_used` | numeric | no |  |
| `consumption_type` | varchar(50) | no |  |
| `consumed_date` | date | no |  |
| `description` | text | yes |  |
| `remarks` | text | yes |  |
| `created_at` | timestamptz | yes |  |

### `rm_receiving_log`

Goods received at stores against purchase orders.

Model: `app/models/rm_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `grn_id` | uuid | no | PK |
| `grn_number` | varchar(50) | yes | U |
| `po_id` | uuid | yes | → `rm_purchase_order.po_id` |
| `vendor_id` | uuid | yes | → `vendor_master.vendor_id` |
| `asn_id` | uuid | yes | → `asn_log.asn_id` |
| `received_date` | date | no |  |
| `vehicle_number` | varchar(50) | yes |  |
| `dc_number` | varchar(100) | yes |  |
| `grn_status` | varchar(30) | yes |  |
| `remarks` | text | yes |  |
| `created_by` | uuid | yes |  |
| `approved_by` | uuid | yes |  |
| `approved_at` | timestamptz | yes |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `grn_detail`

Goods receipt note lines.

Model: `app/models/rm_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `grn_detail_id` | uuid | no | PK |
| `grn_id` | uuid | yes | → `rm_receiving_log.grn_id` |
| `po_detail_id` | uuid | yes | → `rm_purchase_order_detail.po_detail_id` |
| `rm_id` | uuid | yes | → `rm_master.rm_id` |
| `received_qty` | numeric | no |  |
| `accepted_qty` | numeric | yes |  |
| `rejected_qty` | numeric | yes |  |
| `rejection_reason` | text | yes |  |
| `store_id` | uuid | yes | → `store_master.store_id` |
| `created_at` | timestamptz | yes |  |

### `rm_purchase_request`

Purchase requests (header).

Model: `app/models/procurement_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `request_id` | uuid | no | PK |
| `request_number` | varchar(50) | yes | U |
| `status` | varchar(30) | yes |  |
| `requested_by` | uuid | yes | → `login_users.user_id` |
| `vendor_id` | uuid | yes | → `vendor_master.vendor_id` |
| `created_at` | timestamptz | yes |  |

### `rm_purchase_request_detail`

Lines of a purchase request.

Model: `app/models/procurement_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `request_detail_id` | uuid | no | PK |
| `request_id` | uuid | yes | → `rm_purchase_request.request_id` |
| `rm_id` | uuid | yes | → `rm_master.rm_id` |
| `shortage_qty` | numeric | yes |  |
| `affected_chassis` | jsonb | yes |  |
| `reason` | varchar(200) | yes |  |

### `rm_purchase_order`

Purchase orders to vendors (header).

Model: `app/models/rm_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `po_id` | uuid | no | PK |
| `po_number` | varchar(50) | yes | U |
| `vendor_id` | uuid | yes | → `vendor_master.vendor_id` |
| `order_date` | date | no |  |
| `expected_delivery_date` | date | yes |  |
| `status_id` | uuid | yes | → `po_status_master.id` |
| `total_amount` | numeric | yes |  |
| `notes` | text | yes |  |
| `created_by` | uuid | yes |  |
| `approved_by` | uuid | yes |  |
| `approved_at` | timestamptz | yes |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `rm_purchase_order_detail`

Lines of a purchase order.

Model: `app/models/rm_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `po_detail_id` | uuid | no | PK |
| `po_id` | uuid | no | → `rm_purchase_order.po_id` |
| `rm_id` | uuid | no | → `rm_master.rm_id` |
| `order_qty` | numeric | no |  |
| `received_qty` | numeric | yes |  |
| `unit_price` | numeric | no |  |
| `gst_percent` | numeric | yes |  |
| `line_amount` | numeric | yes |  |
| `line_status` | varchar(30) | yes |  |
| `created_at` | timestamptz | yes |  |

### `rm_po_history`

Historic purchase prices / orders per raw material.

Model: `app/models/rm_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `history_id` | uuid | no | PK |
| `po_id` | uuid | no | → `rm_purchase_order.po_id` |
| `action` | varchar(50) | no |  |
| `description` | text | yes |  |
| `created_by_name` | varchar(100) | yes |  |
| `created_at` | timestamptz | yes |  |

### `po_status_master`

Purchase order statuses.

Model: `app/models/rm_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `name` | varchar(100) | no |  |
| `code` | varchar(50) | no | U |
| `description` | text | yes |  |
| `created_at` | timestamptz | yes |  |

### `procurement_source_master`

Procurement sources (local, import, customer supplied, ...).

Model: `app/models/rm_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `name` | varchar(100) | no |  |
| `description` | text | yes |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | no |  |

### `monthly_procurement_plan`

Monthly procurement plan shared with a vendor (header).

Model: `app/models/rm_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `plan_id` | uuid | no | PK |
| `vendor_id` | uuid | no | U → `vendor_master.vendor_id` |
| `plan_year` | integer | no | U |
| `plan_month` | integer | no | U |
| `notes` | text | yes |  |
| `created_by` | uuid | yes |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

### `monthly_procurement_plan_line`

Lines of a monthly procurement plan.

Model: `app/models/rm_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `line_id` | uuid | no | PK |
| `plan_id` | uuid | no | U → `monthly_procurement_plan.plan_id` |
| `rm_id` | uuid | no | U → `rm_master.rm_id` |
| `planned_qty` | numeric | no |  |
| `created_at` | timestamptz | yes |  |

### `vendor_master`

Suppliers, with contacts and vendor portal login.

Model: `app/models/rm_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `vendor_id` | uuid | no | PK |
| `vendor_code` | varchar(50) | yes | U |
| `name` | varchar(255) | no |  |
| `contact_person` | varchar(150) | yes |  |
| `phones` | jsonb | no |  |
| `emails` | jsonb | no |  |
| `gst_number` | varchar(30) | yes | U |
| `address_line1` | varchar(255) | yes |  |
| `city` | varchar(100) | yes |  |
| `state` | varchar(100) | yes |  |
| `payment_terms` | varchar(100) | yes |  |
| `portal_enabled` | boolean | no |  |
| `portal_username` | varchar(100) | yes | U |
| `portal_password_hash` | varchar(255) | yes |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | yes |  |
| `updated_at` | timestamptz | yes |  |

## Vendor portal

### `asn_log`

Advance shipping notices sent by vendors (header).

Model: `app/models/vendor_portal.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `asn_id` | uuid | no | PK |
| `asn_number` | varchar(50) | no | U |
| `vendor_id` | uuid | no | → `vendor_master.vendor_id` |
| `po_id` | uuid | no | → `rm_purchase_order.po_id` |
| `expected_date` | date | no |  |
| `delivery_mode` | varchar(50) | no |  |
| `courier_name` | varchar(100) | yes |  |
| `tracking_number` | varchar(100) | yes |  |
| `vehicle_number` | varchar(50) | yes |  |
| `driver_name` | varchar(100) | yes |  |
| `driver_phone` | varchar(20) | yes |  |
| `arrival_window` | varchar(50) | yes |  |
| `status` | varchar(30) | no |  |
| `created_at` | timestamptz | yes |  |

### `asn_detail`

Lines of an advance shipping notice.

Model: `app/models/vendor_portal.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `asn_detail_id` | uuid | no | PK |
| `asn_id` | uuid | no | → `asn_log.asn_id` |
| `po_detail_id` | uuid | no | → `rm_purchase_order_detail.po_detail_id` |
| `qty_shipped` | numeric | no |  |
| `vendor_batch_ref` | varchar(100) | yes |  |

### `po_tracking_log`

Status updates on purchase orders from the vendor side.

Model: `app/models/vendor_portal.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `tracking_id` | uuid | no | PK |
| `po_id` | uuid | no | → `rm_purchase_order.po_id` |
| `event_type` | varchar(50) | no |  |
| `event_date` | timestamptz | no |  |
| `tracking_ref` | varchar(100) | yes |  |
| `notes` | text | yes |  |
| `created_by` | uuid | yes |  |

### `inspection_document`

Inspection documents uploaded by vendors.

Model: `app/models/vendor_portal.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `doc_id` | uuid | no | PK |
| `entity_type` | varchar(50) | no |  |
| `entity_id` | uuid | no |  |
| `doc_type` | varchar(50) | no |  |
| `file_path` | text | no |  |
| `uploaded_by` | uuid | no |  |
| `uploaded_at` | timestamptz | yes |  |

### `rejection_log`

Material rejected at incoming inspection (header).

Model: `app/models/vendor_portal.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `rejection_id` | uuid | no | PK |
| `grn_id` | uuid | no | → `rm_receiving_log.grn_id` |
| `vendor_id` | uuid | no | → `vendor_master.vendor_id` |
| `rln` | varchar(50) | no | U |
| `reason_code` | varchar(50) | no | → `rejection_reason_master.reason_code` |
| `total_qty` | numeric | no |  |
| `status` | varchar(50) | no |  |
| `disposition_deadline` | timestamptz | yes |  |
| `vendor_response` | varchar(50) | yes |  |
| `vendor_responded_at` | timestamptz | yes |  |
| `created_at` | timestamptz | yes |  |

### `rejection_log_detail`

Lines of a material rejection.

Model: `app/models/vendor_portal.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `rejection_detail_id` | uuid | no | PK |
| `rejection_id` | uuid | no | → `rejection_log.rejection_id` |
| `grn_detail_id` | uuid | no | → `grn_detail.grn_detail_id` |
| `qty` | numeric | no |  |
| `defect_detail` | text | yes |  |

### `rejection_photo`

Photos of rejected material.

Model: `app/models/vendor_portal.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `photo_id` | uuid | no | PK |
| `rejection_id` | uuid | no | → `rejection_log.rejection_id` |
| `file_path` | text | no |  |
| `uploaded_by` | uuid | no |  |
| `uploaded_at` | timestamptz | yes |  |

### `rejection_reason_master`

Reasons for rejecting material.

Model: `app/models/vendor_portal.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `reason_code` | varchar(50) | no | PK |
| `description` | varchar(255) | no |  |
| `is_active` | boolean | no |  |

### `debit_note`

Debit notes raised on vendors.

Model: `app/models/vendor_portal.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `debit_note_id` | uuid | no | PK |
| `vendor_id` | uuid | no | → `vendor_master.vendor_id` |
| `rejection_id` | uuid | yes | → `rejection_log.rejection_id` |
| `dn_number` | varchar(50) | no | U |
| `amount` | numeric | no |  |
| `reason` | text | no |  |
| `status` | varchar(30) | no |  |
| `created_by` | uuid | yes |  |
| `approved_by` | uuid | yes |  |
| `approved_at` | timestamptz | yes |  |
| `created_at` | timestamptz | yes |  |

### `ncr_log`

Non-conformance reports raised on vendors.

Model: `app/models/vendor_portal.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `ncr_id` | uuid | no | PK |
| `rejection_id` | uuid | no | → `rejection_log.rejection_id` |
| `vendor_id` | uuid | no | → `vendor_master.vendor_id` |
| `ncr_number` | varchar(50) | no | U |
| `defect_description` | text | no |  |
| `disposition_code` | varchar(50) | yes |  |
| `car_due` | timestamptz | yes |  |
| `car_submitted_at` | timestamptz | yes |  |
| `car_root_cause` | text | yes |  |
| `car_action_taken` | text | yes |  |
| `car_prevention` | text | yes |  |
| `status` | varchar(50) | no |  |
| `created_at` | timestamptz | yes |  |

### `vendor_dispute_log`

Disputes raised by vendors and their resolution.

Model: `app/models/vendor_portal.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `dispute_id` | uuid | no | PK |
| `vendor_id` | uuid | no | → `vendor_master.vendor_id` |
| `entity_type` | varchar(30) | no |  |
| `entity_id` | uuid | no |  |
| `dispute_type` | varchar(50) | no |  |
| `description` | text | no |  |
| `status` | varchar(30) | no |  |
| `resolution_note` | text | yes |  |
| `resolved_by` | uuid | yes |  |
| `resolved_at` | timestamptz | yes |  |
| `created_at` | timestamptz | yes |  |

### `vendor_scorecard`

Vendor performance scores per period.

Model: `app/models/vendor_portal.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `scorecard_id` | uuid | no | PK |
| `vendor_id` | uuid | no | → `vendor_master.vendor_id` |
| `period_start` | date | no |  |
| `period_end` | date | no |  |
| `deliveries_total` | integer | no |  |
| `deliveries_on_time` | integer | no |  |
| `batches_total` | integer | no |  |
| `batches_first_pass` | integer | no |  |
| `rejection_count` | integer | no |  |
| `ncr_count` | integer | no |  |
| `avg_lead_time_days` | numeric | yes |  |
| `calculated_at` | timestamptz | yes |  |

### `notification_log`

Notifications sent to vendors / users.

Model: `app/models/vendor_portal.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `notification_id` | uuid | no | PK |
| `vendor_id` | uuid | yes | → `vendor_master.vendor_id` |
| `recipient` | varchar(255) | no |  |
| `notification_type` | varchar(50) | no |  |
| `subject` | varchar(255) | yes |  |
| `content` | text | yes |  |
| `status` | varchar(30) | no |  |
| `sent_at` | timestamptz | yes |  |
| `created_at` | timestamptz | yes |  |

### `vendor_portal_log`

Vendor portal login / session log.

Model: `app/models/vendor_portal.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `log_id` | uuid | no | PK |
| `vendor_id` | uuid | no | → `vendor_master.vendor_id` |
| `session_token` | varchar(128) | no | U |
| `ip_address` | varchar(50) | yes |  |
| `user_agent` | text | yes |  |
| `issued_at` | timestamptz | no |  |
| `expires_at` | timestamptz | no |  |
| `invalidated_at` | timestamptz | yes |  |

### `vendor_portal_action_log`

Actions performed by vendors in the portal.

Model: `app/models/vendor_portal.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `action_id` | uuid | no | PK |
| `vendor_id` | uuid | no | → `vendor_master.vendor_id` |
| `action_type` | varchar(50) | no |  |
| `entity_type` | varchar(50) | yes |  |
| `entity_id` | uuid | yes |  |
| `action_details` | jsonb | yes |  |
| `ip_address` | varchar(50) | yes |  |
| `created_at` | timestamptz | yes |  |

### `vendor_portal_admin_action_log`

Actions performed by staff on vendor portal data.

Model: `app/models/vendor_portal.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `action_id` | uuid | no | PK |
| `admin_user_id` | uuid | no |  |
| `vendor_id` | uuid | yes | → `vendor_master.vendor_id` |
| `action_type` | varchar(50) | no |  |
| `action_details` | jsonb | yes |  |
| `ip_address` | varchar(50) | yes |  |
| `created_at` | timestamptz | yes |  |

## Maintenance

### `maintenance_asset`

Machines and equipment that are maintained.

Model: `app/models/maintenance_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `name` | varchar(200) | no |  |
| `machine_number` | integer | yes |  |
| `machine_type` | varchar(50) | yes |  |
| `year_of_commissioning` | integer | yes |  |
| `location` | varchar(200) | yes |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | no |  |
| `updated_at` | timestamptz | yes |  |

### `maintenance_record`

Breakdown and maintenance jobs on an asset.

Model: `app/models/maintenance_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `asset_id` | uuid | no | → `maintenance_asset.id` |
| `wo_number` | varchar(30) | yes |  |
| `record_date` | date | no |  |
| `maintenance_type` | varchar(10) | no |  |
| `status` | varchar(20) | no |  |
| `priority` | varchar(20) | no |  |
| `assigned_technician` | varchar(150) | yes |  |
| `estimated_time` | varchar(50) | yes |  |
| `problem_faced` | text | yes |  |
| `root_cause` | text | yes |  |
| `material_used` | text | yes |  |
| `material_cost` | numeric | yes |  |
| `time_taken` | varchar(50) | yes |  |
| `supervisor_name` | varchar(150) | yes |  |
| `remarks` | text | yes |  |
| `photo_url` | varchar(500) | yes |  |
| `created_at` | timestamptz | no |  |
| `updated_at` | timestamptz | yes |  |

### `maintenance_record_action`

Actions taken on a maintenance job.

Model: `app/models/maintenance_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `record_id` | uuid | no | → `maintenance_record.id` |
| `sr_no` | integer | yes |  |
| `action_taken` | text | no |  |
| `is_ok` | boolean | no |  |
| `created_at` | timestamptz | no |  |

### `maintenance_checklist_item`

Checklist items for preventive maintenance.

Model: `app/models/maintenance_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `machine_type` | varchar(50) | no |  |
| `sr_no` | integer | yes |  |
| `check_point` | text | no |  |
| `specification` | text | yes |  |
| `is_active` | boolean | no |  |
| `created_at` | timestamptz | no |  |

### `maintenance_pm_schedule`

Preventive maintenance schedule per asset.

Model: `app/models/maintenance_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `asset_id` | uuid | no | → `maintenance_asset.id` |
| `scheduled_date` | date | no |  |
| `year` | integer | no |  |
| `month` | integer | no |  |
| `status` | varchar(20) | no |  |
| `completed_date` | date | yes |  |
| `notes` | text | yes |  |
| `created_at` | timestamptz | no |  |
| `updated_at` | timestamptz | yes |  |

### `maintenance_incoming_material`

Material received for maintenance use.

Model: `app/models/maintenance_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `entry_date` | date | no |  |
| `vendor` | varchar(200) | yes |  |
| `category` | varchar(100) | yes |  |
| `material_name` | varchar(300) | no |  |
| `quantity` | numeric | no |  |
| `rate` | numeric | yes |  |
| `total_amount` | numeric | yes |  |
| `bill_no` | varchar(100) | yes |  |
| `discount` | numeric | yes |  |
| `challan_no` | varchar(100) | yes |  |
| `remarks` | text | yes |  |
| `asset_id` | uuid | yes | → `maintenance_asset.id` |
| `bill_photo_url` | varchar(500) | yes |  |
| `created_at` | timestamptz | no |  |
| `updated_at` | timestamptz | yes |  |

### `maintenance_daily_consumable_stock`

Daily stock of maintenance consumables.

Model: `app/models/maintenance_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `record_date` | date | no |  |
| `consumable_type` | varchar(50) | no |  |
| `opening_stock` | numeric | no |  |
| `received_stock` | numeric | no |  |
| `total_stock` | numeric | no |  |
| `consumed_stock` | numeric | no |  |
| `closing_stock` | numeric | no |  |
| `remark` | text | yes |  |
| `created_at` | timestamptz | no |  |
| `updated_at` | timestamptz | yes |  |

### `maintenance_monthly_stock`

Monthly stock position of maintenance items.

Model: `app/models/maintenance_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `stock_month` | integer | no |  |
| `stock_year` | integer | no |  |
| `category` | varchar(100) | no |  |
| `category_order` | integer | no |  |
| `material_name` | varchar(300) | no |  |
| `uom` | varchar(50) | no |  |
| `cost` | numeric | no |  |
| `opening_qty` | numeric | no |  |
| `opening_amount` | numeric | no |  |
| `incoming_qty` | numeric | no |  |
| `incoming_amount` | numeric | no |  |
| `total_qty` | numeric | no |  |
| `total_amount` | numeric | no |  |
| `consumption_qty` | numeric | no |  |
| `consumption_amount` | numeric | no |  |
| `closing_qty` | numeric | no |  |
| `closing_amount` | numeric | no |  |
| `created_at` | timestamptz | no |  |
| `updated_at` | timestamptz | yes |  |

### `maintenance_machine_consumption_cost`

Monthly consumption cost per machine.

Model: `app/models/maintenance_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `machine_name` | varchar(300) | no |  |
| `display_order` | integer | no |  |
| `year` | integer | no |  |
| `jan_cost` | numeric | no |  |
| `feb_cost` | numeric | no |  |
| `mar_cost` | numeric | no |  |
| `apr_cost` | numeric | no |  |
| `may_cost` | numeric | no |  |
| `jun_cost` | numeric | no |  |
| `jul_cost` | numeric | no |  |
| `aug_cost` | numeric | no |  |
| `sep_cost` | numeric | no |  |
| `oct_cost` | numeric | no |  |
| `nov_cost` | numeric | no |  |
| `dec_cost` | numeric | no |  |
| `created_at` | timestamptz | no |  |
| `updated_at` | timestamptz | yes |  |

### `maintenance_equipment_purchase`

Equipment purchased for maintenance.

Model: `app/models/maintenance_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `purchase_month` | integer | no |  |
| `purchase_year` | integer | no |  |
| `equipment_name` | varchar(300) | no |  |
| `quantity` | numeric | no |  |
| `unit_price` | numeric | no |  |
| `total_amount` | numeric | no |  |
| `remarks` | text | yes |  |
| `created_at` | timestamptz | no |  |
| `updated_at` | timestamptz | yes |  |

### `maintenance_equipment_rental`

Equipment rented, with vendor, period and cost.

Model: `app/models/maintenance_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `rental_date` | date | no |  |
| `vendor` | varchar(200) | no |  |
| `equipment_type` | varchar(100) | no |  |
| `in_time` | varchar(20) | yes |  |
| `out_time` | varchar(20) | yes |  |
| `hours` | numeric | yes |  |
| `work_description` | text | yes |  |
| `bill_no` | varchar(100) | yes |  |
| `amount` | numeric | yes |  |
| `created_at` | timestamptz | no |  |
| `updated_at` | timestamptz | yes |  |

### `maintenance_diesel_record`

Diesel usage records.

Model: `app/models/maintenance_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `entry_date` | date | no |  |
| `dg_set_no` | varchar(50) | no |  |
| `diesel_ltr` | numeric | no |  |
| `oil_ltr` | numeric | yes |  |
| `created_at` | timestamptz | no |  |
| `updated_at` | timestamptz | yes |  |

### `maintenance_lpg_gas_record`

LPG gas usage records.

Model: `app/models/maintenance_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `entry_date` | date | no |  |
| `gas_name` | varchar(100) | no |  |
| `quantity` | integer | no |  |
| `kg` | numeric | no |  |
| `price` | numeric | yes |  |
| `total_amount` | numeric | yes |  |
| `bill_no` | varchar(100) | yes |  |
| `created_at` | timestamptz | no |  |
| `updated_at` | timestamptz | yes |  |

### `maintenance_solar_record`

Solar generation records.

Model: `app/models/maintenance_models.py`

| Column | Type | Null | Key / reference |
|---|---|---|---|
| `id` | uuid | no | PK |
| `entry_date` | date | no |  |
| `part_name` | varchar(200) | no |  |
| `quantity` | numeric | no |  |
| `price` | numeric | no |  |
| `total_amount` | numeric | no |  |
| `bill_no` | varchar(100) | yes |  |
| `created_at` | timestamptz | no |  |
| `updated_at` | timestamptz | yes |  |
