<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* project_order_expenses.total — persisted canonical positions total.
*
* Written on every upsert (ExpenseService::computeExpenseTotal) so the expense
* list reads the figure directly with no client-side math. This migration adds
* the column and backfills all existing rows with the same canonical formula:
* per position: buying_price > 0 ? (unit / PE) * buying_price : amount
* plus delivery_amount; PE (price_unit) null/0 behaves as 1.
* Mirrors FE Frontend/src/common/utils/PositionPrice (calcPositionLineTotal).
*/
final class Version20260617130000 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add project_order_expenses.total (persisted positions total) + backfill existing rows';
}
public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE project_order_expenses ADD total NUMERIC(10, 2) DEFAULT NULL');
$this->addSql('
UPDATE project_order_expenses e
SET e.total = (
SELECT ROUND(COALESCE(SUM(
(CASE
WHEN COALESCE(p.buying_price, 0) > 0
THEN (p.unit / (CASE WHEN COALESCE(p.price_unit, 0) > 0 THEN p.price_unit ELSE 1 END)) * p.buying_price
ELSE CAST(p.amount AS DECIMAL(10, 2))
END) + COALESCE(p.delivery_amount, 0)
), 0), 2)
FROM project_order_expense_positions p
WHERE p.project_order_expense_id = e.id
)
');
}
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE project_order_expenses DROP total');
}
}