FreightOrder.orderedBy is a free-text String with only a @NotBlank constraint. Any arbitrary
value is accepted ("me", "ops-team", ""), there is no referential integrity, and orders
cannot be queried by a specific operator. This issue replaces the string field with an Operator
entity that represents an internal system user.
New entity: Operator
id β BIGINT PK
username β VARCHAR(50), UNIQUE, NOT NULL
fullName β VARCHAR(100)
email β VARCHAR(150), UNIQUE, NOT NULL
active β BOOLEAN, DEFAULT TRUE
createdAt / updatedAt β timestamps (via BaseEntity)
New endpoints:
POST /api/v1/operators β create an operator
GET /api/v1/operators β list all operators
GET /api/v1/operators/{id} β get a single operator
Changes to FreightOrder:
- Remove
String orderedBy
- Add
@ManyToOne(fetch = LAZY) Operator operator (FK operator_id)
CreateFreightOrderRequest: replace orderedBy: String with operatorId: Long
FreightOrderResponse: expose operatorId and operatorUsername
Migration:
- Flyway
V2__add_operators.sql β creates the operators table and adds the operator_id column
to freight_orders
- If seed data contains existing
orderedBy strings, the migration should insert corresponding
Operator rows and back-fill the FK
Hints:
- This is a breaking API change β
orderedBy is removed entirely, not deprecated alongside
operatorId
Operator will be the natural entity to link to an auth identity if authentication is introduced
later; keep the model clean for that
Acceptance criteria:
FreightOrder.orderedByis a free-textStringwith only a@NotBlankconstraint. Any arbitraryvalue is accepted (
"me","ops-team",""), there is no referential integrity, and orderscannot be queried by a specific operator. This issue replaces the string field with an
Operatorentity that represents an internal system user.
New entity:
Operatoridβ BIGINT PKusernameβ VARCHAR(50), UNIQUE, NOT NULLfullNameβ VARCHAR(100)emailβ VARCHAR(150), UNIQUE, NOT NULLactiveβ BOOLEAN, DEFAULT TRUEcreatedAt/updatedAtβ timestamps (viaBaseEntity)New endpoints:
POST /api/v1/operatorsβ create an operatorGET /api/v1/operatorsβ list all operatorsGET /api/v1/operators/{id}β get a single operatorChanges to
FreightOrder:String orderedBy@ManyToOne(fetch = LAZY) Operator operator(FKoperator_id)CreateFreightOrderRequest: replaceorderedBy: StringwithoperatorId: LongFreightOrderResponse: exposeoperatorIdandoperatorUsernameMigration:
V2__add_operators.sqlβ creates theoperatorstable and adds theoperator_idcolumnto
freight_ordersorderedBystrings, the migration should insert correspondingOperatorrows and back-fill the FKHints:
orderedByis removed entirely, not deprecated alongsideoperatorIdOperatorwill be the natural entity to link to an auth identity if authentication is introducedlater; keep the model clean for that
Acceptance criteria:
Operatorentity, repository, service, and controller createdPOST,GET (list),GET (by id)endpoints working under/api/v1/operatorsFreightOrder.orderedBy(String) removed;operator(@ManyToOne) addedCreateFreightOrderRequestusesoperatorId: LongFreightOrderResponseexposesoperatorIdandoperatorUsernameV2__add_operators.sqlFlyway migration presentFreightOrderControllerTestandFreightOrderServiceTestupdated to useoperatorId