Files
wms-app/app/assets/utils/classes_ac/PostingWindowGuard.php
T
Thanakorn SandClaude Sonnet 4.6 94032dd65b fix StockManager lot/serial coercion + add document flow test suite
- StockManager: coerce lot_number/serial_number to trimmed string (fixes
  Array-to-string warnings); validate quantity > 0 on insert; tighten
  transfer pair lookup to match in/out side by column value
- PostingWindowGuard: strip time component from datetime strings before
  date-format validation
- docs/tests/doc_flow_test.php: 32-assertion document flow suite covering
  Stock In create + approve, Sales Order draft/confirm, Invoice from Order
  (with duplicate-block check), PO create/confirm, Quotation create, and
  usage increment wiring check; all 32/32 PASS against wms_codex_test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 14:20:41 +07:00

78 lines
2.4 KiB
PHP

<?php
require_once __DIR__ . '/../classes/CompanySettingManager.php';
class PostingWindowGuard
{
private CompanySettingManager $settings;
private ?array $window = null;
public function __construct(PDO $settingsPdo, int $company_id)
{
$this->settings = new CompanySettingManager($settingsPdo, $company_id);
}
public function assertOpenDate(?string $posting_date, string $context = 'GL posting'): void
{
$date = $this->normalizeDate($posting_date);
if ($date === '') {
throw new Exception("{$context} date is required for posting-window validation.");
}
$window = $this->getWindow();
$from = $window['open_from'];
$to = $window['open_to'];
if ($from !== '' && $date < $from) {
throw new Exception("{$context} date {$date} is before the open posting window ({$from} to " . ($to ?: 'no upper limit') . ").");
}
if ($to !== '' && $date > $to) {
throw new Exception("{$context} date {$date} is after the open posting window (" . ($from ?: 'no lower limit') . " to {$to}).");
}
}
private function getWindow(): array
{
if ($this->window === null) {
$open_from = $this->settings->get('posting_open_from');
if ($open_from === null || $open_from === '') {
$open_from = $this->settings->get('gl_open_from') ?: '';
}
$open_to = $this->settings->get('posting_open_to');
if ($open_to === null || $open_to === '') {
$open_to = $this->settings->get('gl_open_to') ?: '';
}
$this->window = [
'open_from' => $this->normalizeDate($open_from ?: ''),
'open_to' => $this->normalizeDate($open_to ?: ''),
];
}
return $this->window;
}
private function normalizeDate(?string $date): string
{
$date = trim((string)$date);
if ($date === '') {
return '';
}
if (preg_match('#^(\d{2})/(\d{2})/(\d{4})$#', $date, $m)) {
$date = "{$m[3]}-{$m[2]}-{$m[1]}";
}
if (preg_match("#^([0-9]{4}-[0-9]{2}-[0-9]{2})[ T]#", $date, $m)) {
$date = $m[1];
}
if (!preg_match("#^[0-9]{4}-[0-9]{2}-[0-9]{2}$#", $date)) {
throw new Exception("Invalid posting date {$date}. Use YYYY-MM-DD.");
}
return $date;
}
}