217 lines
8.4 KiB
PHP
217 lines
8.4 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
require_once __DIR__ . '/../config.php';
|
|
|
|
if (!function_exists('financial_documents_schema_sync_20260502_run')) {
|
|
function financial_documents_schema_sync_20260502_run(): void
|
|
{
|
|
$pdo = db();
|
|
|
|
$columns = [
|
|
'invoices' => [
|
|
'transaction_no' => 'VARCHAR(50) DEFAULT NULL',
|
|
'payment_type' => 'VARCHAR(100) DEFAULT NULL',
|
|
'vat_amount' => 'DECIMAL(15,3) DEFAULT 0.000',
|
|
'total_with_vat' => 'DECIMAL(15,3) DEFAULT 0.000',
|
|
'terms_conditions' => 'TEXT NULL',
|
|
'paid_amount' => 'DECIMAL(15,3) DEFAULT 0.000',
|
|
'status' => "ENUM('paid','unpaid','partially_paid','refunded','cancelled') DEFAULT 'unpaid'",
|
|
'register_session_id' => 'INT(11) DEFAULT NULL',
|
|
'is_pos' => 'TINYINT(1) DEFAULT 0',
|
|
'discount_amount' => 'DECIMAL(15,3) DEFAULT 0.000',
|
|
'loyalty_points_earned' => 'DECIMAL(15,3) DEFAULT 0.000',
|
|
'loyalty_points_redeemed' => 'DECIMAL(15,3) DEFAULT 0.000',
|
|
'created_by' => 'INT(11) DEFAULT NULL',
|
|
'outlet_id' => 'INT(11) DEFAULT NULL',
|
|
],
|
|
'purchases' => [
|
|
'payment_type' => 'VARCHAR(100) DEFAULT NULL',
|
|
'total_amount' => 'DECIMAL(15,3) DEFAULT 0.000',
|
|
'vat_amount' => 'DECIMAL(15,3) DEFAULT 0.000',
|
|
'total_with_vat' => 'DECIMAL(15,3) DEFAULT 0.000',
|
|
'terms_conditions' => 'TEXT NULL',
|
|
'paid_amount' => 'DECIMAL(15,3) DEFAULT 0.000',
|
|
'status' => "ENUM('paid','unpaid','partially_paid') DEFAULT 'unpaid'",
|
|
'register_session_id' => 'INT(11) DEFAULT NULL',
|
|
'due_date' => 'DATE DEFAULT NULL',
|
|
'outlet_id' => 'INT(11) DEFAULT 1',
|
|
],
|
|
'lpos' => [
|
|
'delivery_date' => 'DATE DEFAULT NULL',
|
|
'status' => "ENUM('pending','converted','cancelled') DEFAULT 'pending'",
|
|
'total_amount' => 'DECIMAL(15,3) DEFAULT 0.000',
|
|
'vat_amount' => 'DECIMAL(15,3) DEFAULT 0.000',
|
|
'total_with_vat' => 'DECIMAL(15,3) DEFAULT 0.000',
|
|
'terms_conditions' => 'TEXT NULL',
|
|
'outlet_id' => 'INT(11) DEFAULT NULL',
|
|
],
|
|
'quotations' => [
|
|
'status' => "ENUM('pending','converted','expired','cancelled') DEFAULT 'pending'",
|
|
'total_amount' => 'DECIMAL(15,3) DEFAULT 0.000',
|
|
'vat_amount' => 'DECIMAL(15,3) DEFAULT 0.000',
|
|
'total_with_vat' => 'DECIMAL(15,3) DEFAULT 0.000',
|
|
'terms_conditions' => 'TEXT NULL',
|
|
'outlet_id' => 'INT(11) DEFAULT NULL',
|
|
],
|
|
];
|
|
|
|
foreach ($columns as $table => $tableColumns) {
|
|
if (!financial_documents_schema_sync_20260502_table_exists($pdo, $table)) {
|
|
continue;
|
|
}
|
|
|
|
foreach ($tableColumns as $column => $definition) {
|
|
if (financial_documents_schema_sync_20260502_column_exists($pdo, $table, $column)) {
|
|
continue;
|
|
}
|
|
|
|
$statement = sprintf(
|
|
'ALTER TABLE `%s` ADD COLUMN `%s` %s',
|
|
str_replace('`', '', $table),
|
|
str_replace('`', '', $column),
|
|
$definition
|
|
);
|
|
|
|
financial_documents_schema_sync_20260502_exec($pdo, $statement);
|
|
}
|
|
}
|
|
|
|
foreach (['invoices', 'purchases', 'lpos', 'quotations'] as $table) {
|
|
financial_documents_schema_sync_20260502_backfill_total_with_vat($pdo, $table);
|
|
}
|
|
|
|
foreach (['invoices', 'purchases'] as $table) {
|
|
financial_documents_schema_sync_20260502_backfill_paid_amount($pdo, $table);
|
|
}
|
|
|
|
foreach (['purchases', 'lpos', 'quotations'] as $table) {
|
|
financial_documents_schema_sync_20260502_default_outlet_id($pdo, $table);
|
|
}
|
|
}
|
|
|
|
function financial_documents_schema_sync_20260502_table_exists(PDO $pdo, string $table): bool
|
|
{
|
|
$stmt = $pdo->prepare(
|
|
'SELECT 1 FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = :table LIMIT 1'
|
|
);
|
|
$stmt->execute(['table' => $table]);
|
|
|
|
return (bool) $stmt->fetchColumn();
|
|
}
|
|
|
|
function financial_documents_schema_sync_20260502_column_exists(PDO $pdo, string $table, string $column): bool
|
|
{
|
|
$stmt = $pdo->prepare(
|
|
'SELECT 1 FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = :table AND COLUMN_NAME = :column LIMIT 1'
|
|
);
|
|
$stmt->execute([
|
|
'table' => $table,
|
|
'column' => $column,
|
|
]);
|
|
|
|
return (bool) $stmt->fetchColumn();
|
|
}
|
|
|
|
function financial_documents_schema_sync_20260502_exec(PDO $pdo, string $statement): void
|
|
{
|
|
try {
|
|
$pdo->exec($statement);
|
|
} catch (PDOException $exception) {
|
|
if (financial_documents_schema_sync_20260502_is_ignorable($exception)) {
|
|
return;
|
|
}
|
|
|
|
throw $exception;
|
|
}
|
|
}
|
|
|
|
function financial_documents_schema_sync_20260502_is_ignorable(PDOException $exception): bool
|
|
{
|
|
$driverCode = isset($exception->errorInfo[1]) ? (int) $exception->errorInfo[1] : null;
|
|
$message = strtolower($exception->getMessage());
|
|
$ignorableCodes = [1050, 1060, 1061, 1062, 1091, 1826];
|
|
$ignorableSnippets = [
|
|
'already exists',
|
|
'duplicate column name',
|
|
'duplicate key name',
|
|
'duplicate entry',
|
|
'duplicate foreign key constraint name',
|
|
'duplicate key on write or update',
|
|
'errno: 121',
|
|
'check that column/key exists',
|
|
];
|
|
|
|
if ($driverCode !== null && in_array($driverCode, $ignorableCodes, true)) {
|
|
return true;
|
|
}
|
|
|
|
foreach ($ignorableSnippets as $snippet) {
|
|
if (str_contains($message, $snippet)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function financial_documents_schema_sync_20260502_backfill_total_with_vat(PDO $pdo, string $table): void
|
|
{
|
|
if (
|
|
!financial_documents_schema_sync_20260502_table_exists($pdo, $table)
|
|
|| !financial_documents_schema_sync_20260502_column_exists($pdo, $table, 'total_amount')
|
|
|| !financial_documents_schema_sync_20260502_column_exists($pdo, $table, 'vat_amount')
|
|
|| !financial_documents_schema_sync_20260502_column_exists($pdo, $table, 'total_with_vat')
|
|
) {
|
|
return;
|
|
}
|
|
|
|
$sql = sprintf(
|
|
'UPDATE `%1$s` SET `total_with_vat` = COALESCE(`total_amount`, 0) + COALESCE(`vat_amount`, 0) WHERE `total_with_vat` IS NULL OR (`total_with_vat` = 0 AND (COALESCE(`total_amount`, 0) <> 0 OR COALESCE(`vat_amount`, 0) <> 0))',
|
|
str_replace('`', '', $table)
|
|
);
|
|
|
|
$pdo->exec($sql);
|
|
}
|
|
|
|
function financial_documents_schema_sync_20260502_backfill_paid_amount(PDO $pdo, string $table): void
|
|
{
|
|
if (
|
|
!financial_documents_schema_sync_20260502_table_exists($pdo, $table)
|
|
|| !financial_documents_schema_sync_20260502_column_exists($pdo, $table, 'status')
|
|
|| !financial_documents_schema_sync_20260502_column_exists($pdo, $table, 'paid_amount')
|
|
|| !financial_documents_schema_sync_20260502_column_exists($pdo, $table, 'total_with_vat')
|
|
) {
|
|
return;
|
|
}
|
|
|
|
$sql = sprintf(
|
|
'UPDATE `%1$s` SET `paid_amount` = COALESCE(`total_with_vat`, 0) WHERE `status` = \'paid\' AND (`paid_amount` IS NULL OR `paid_amount` = 0)',
|
|
str_replace('`', '', $table)
|
|
);
|
|
|
|
$pdo->exec($sql);
|
|
}
|
|
|
|
function financial_documents_schema_sync_20260502_default_outlet_id(PDO $pdo, string $table): void
|
|
{
|
|
if (
|
|
!financial_documents_schema_sync_20260502_table_exists($pdo, $table)
|
|
|| !financial_documents_schema_sync_20260502_column_exists($pdo, $table, 'outlet_id')
|
|
) {
|
|
return;
|
|
}
|
|
|
|
$sql = sprintf(
|
|
'UPDATE `%1$s` SET `outlet_id` = 1 WHERE `outlet_id` IS NULL',
|
|
str_replace('`', '', $table)
|
|
);
|
|
|
|
$pdo->exec($sql);
|
|
}
|
|
}
|
|
|
|
financial_documents_schema_sync_20260502_run();
|
|
|
|
return true;
|