Skip to content

fix: prevent orchestrator_priority null constraint violation on order creation#228

Merged
roncodes merged 2 commits intomainfrom
fix/orchestrator-priority-null-constraint
Apr 20, 2026
Merged

fix: prevent orchestrator_priority null constraint violation on order creation#228
roncodes merged 2 commits intomainfrom
fix/orchestrator-priority-null-constraint

Conversation

@roncodes
Copy link
Copy Markdown
Member

Problem

When a user creates an order via the order/form component without filling in the orchestrator constraints section (Orchestrator Priority, Required Skills, Time Window), the following error is thrown:

SQLSTATE[23000]: Integrity constraint violation: 1048
Column 'orchestrator_priority' cannot be null

Root Cause

The migration 2026_04_08_000003_add_orchestrator_columns_to_orders_table defines orchestrator_priority as NOT NULL with a database-level default(50). However, MySQL's column default is only used when the column is omitted from the INSERT statement entirely. When Eloquent receives an explicit null for the key, it includes orchestrator_priority = NULL in the INSERT, which violates the NOT NULL constraint and bypasses the DB default.

Both controllers use $request->only([..., 'orchestrator_priority']), which returns null for any key absent from the request payload. That null is then forwarded directly to Order::create() / Order::update().

Fix — Defence-in-depth across four layers

1. Order model — $attributes default

Added protected $attributes = ['orchestrator_priority' => 50] so every new Order instance starts with a valid value before any input is applied.

2. Order model — setOrchestratorPriorityAttribute mutator

A new Eloquent mutator coerces null or any non-numeric value to 50 at the model layer, ensuring the constraint can never be violated regardless of the call site — including future code paths not yet written.

3. Controllers — explicit null-guard before create / update

Both Api\v1\OrderController (create + update) and Internal\v1\OrderController (createRecord) now check whether orchestrator_priority is missing or non-numeric and default it to 50 before passing $input to Eloquent. This mirrors the existing pattern already used for type and status.

4. New migration — make column nullable for existing installations

Added 2026_04_20_000001_make_orchestrator_priority_nullable_on_orders_table which alters the column to nullable on databases that have already run the original migration. The application layer guarantees 50 is always written, so NULL will not appear in practice; the nullable flag is a belt-and-suspenders safety net.

Files Changed

File Change
server/src/Models/Order.php Added $attributes default + setOrchestratorPriorityAttribute mutator
server/src/Http/Controllers/Internal/v1/OrderController.php Null-guard in createRecord before-callback
server/src/Http/Controllers/Api/v1/OrderController.php Null-guard in both create and update methods
server/migrations/2026_04_20_000001_make_orchestrator_priority_nullable_on_orders_table.php New migration to alter column on existing DBs

Testing

To reproduce the bug before this fix:

  1. Open the order creation form
  2. Fill in all required fields but leave the Orchestrator Priority field blank
  3. Submit — the SQLSTATE[23000] error is returned

After this fix, the order is created successfully with orchestrator_priority = 50 (the default).

roncodes and others added 2 commits April 19, 2026 21:52
… creation

When a user creates an order via the order/form component without filling
in the orchestrator constraints section, the frontend sends
orchestrator_priority as null (or omits it entirely).  Both controllers
use request->only([..., 'orchestrator_priority']), which returns null for
keys absent from the request.  That explicit null is then forwarded to
Order::create() / Order::update(), bypassing MySQL's column-level default
of 50 and raising:

  SQLSTATE[23000]: Integrity constraint violation: 1048
  Column 'orchestrator_priority' cannot be null

Root cause
----------
The migration defines the column as NOT NULL with a DB default of 50, but
Eloquent's INSERT statement includes every key present in the input array —
even when the value is null — so the DB default is never used.

Fix (defence-in-depth, three layers)
--------------------------------------
1. Order model — $attributes default:
   Added protected $attributes = ['orchestrator_priority' => 50] so that
   any new Order instance starts with a valid value before any input is
   applied.

2. Order model — setOrchestratorPriorityAttribute mutator:
   Coerces null or non-numeric values to 50 at the model layer, ensuring
   the constraint can never be violated regardless of the call site.

3. Controllers — explicit null-guard before create/update:
   Both Api\v1\OrderController (create + update) and
   Internal\v1\OrderController (createRecord) now check whether
   orchestrator_priority is missing or non-numeric and set it to 50 before
   passing $input to Eloquent.  This mirrors the existing pattern used for
   'type' and 'status'.

4. Migration — make column nullable:
   Added a new migration (2026_04_20_000001) that alters the column to
   nullable on existing installations that have already run the original
   migration.  The application layer guarantees 50 is always written, so
   NULL will not appear in practice; nullable is a belt-and-suspenders
   safety net.
@roncodes roncodes merged commit 8988629 into main Apr 20, 2026
7 checks passed
@roncodes roncodes deleted the fix/orchestrator-priority-null-constraint branch April 20, 2026 09:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant