Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Format based on [Keep a Changelog](https://keepachangelog.com/).
- **Product types as Bill-of-Materials components** *(admin)* — a BOM line can now be a manufactured **product type** (a sub-assembly), not only a material. In the BOM editor a Material / Product type switch picks the component kind; product-type lines carry the same quantity-per-unit, step, scrap %, consumption timing and notes as materials. A product type can't be a component of itself, and each appears once per template. Lines are captured in the work-order snapshot as sub-assembly references; they're a simple component reference (they don't explode into their own BOM) and are skipped by the material stock/consumption engine. Additive — existing material BOMs are unaffected.

### Fixed
- **Saving system settings crashed on PostgreSQL** *(admin)* — the plant-timezone save wrote the raw identifier (e.g. `Europe/Warsaw`) into the JSON `system_settings.value` column, which PostgreSQL rejects (`invalid input syntax for type json`), 500-ing the whole Settings → System save; SQLite tolerated it, so tests missed it. The value is now JSON-encoded (and decoded on read, tolerating legacy raw values).
- **Header clock ignored the configured timezone** *(all users)* — the live clock top-right was hardcoded to `Europe/Warsaw`, so on any install with a different timezone it was the one timestamp in the UI that disagreed with all the others. It now goes through the same `formatDate`/`formatTime` helpers as the rest of the app.

## [0.21.0] - 2026-08-21
Expand Down
18 changes: 15 additions & 3 deletions backend/app/Support/TimezoneRegistry.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,21 @@ public static function stored(): ?string
return null;
}

if (! $row || ! self::isValid((string) $row->value)) {
if (! $row) {
return null;
}

return self::$cached = (string) $row->value;
// `system_settings.value` is a JSON column, so the stored value is
// JSON-encoded (e.g. "Europe/Warsaw"). Decode it; tolerate a legacy raw
// string too.
$decoded = json_decode((string) $row->value, true);
$value = is_string($decoded) ? $decoded : (string) $row->value;

if (! self::isValid($value)) {
return null;
}

return self::$cached = $value;
}

/**
Expand Down Expand Up @@ -95,7 +105,9 @@ public static function save(string $timezone): void

DB::table('system_settings')->updateOrInsert(
['key' => self::SETTING_KEY],
['value' => $timezone, 'updated_at' => now()],
// JSON-encode: `value` is a JSON column, so a bare string is rejected
// by Postgres (works on SQLite, which is why tests missed it).
['value' => json_encode($timezone), 'updated_at' => now()],
);

self::$cached = $timezone;
Expand Down
8 changes: 5 additions & 3 deletions backend/tests/Feature/Web/SystemSettingsTimezoneTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,14 @@ public function test_admin_can_change_the_plant_timezone(): void
->post('/settings/system', $this->payload(['app_timezone' => 'America/Argentina/Buenos_Aires']))
->assertSessionHasNoErrors();

// Stored raw, not JSON-encoded — TimezoneRegistry reads it as a plain
// identifier, so an accidental json_encode() here would break `stored()`.
// `system_settings.value` is a JSON column, so the identifier must be
// JSON-encoded — a bare string is rejected by Postgres (SQLite tolerates
// it, which is how the bug shipped). stored() decodes it back.
$this->assertDatabaseHas('system_settings', [
'key' => TimezoneRegistry::SETTING_KEY,
'value' => 'America/Argentina/Buenos_Aires',
'value' => json_encode('America/Argentina/Buenos_Aires'),
]);
TimezoneRegistry::flush();
$this->assertSame('America/Argentina/Buenos_Aires', TimezoneRegistry::stored());
}

Expand Down
Loading