Files
clinicpro/migrations/Version20260818131524.php
T
hamedandClaude Opus 5 1f64b516d2 fix(insurance): let a clinic owner save the visit price of a member doctor
The pricing rows are keyed by the *target* tenant, but the tenant filter pins
every read to the environment of whoever is asking. A clinic owner setting the
free-visit price for one of their doctors was therefore blind to the row that
already existed: each save inserted another one — the unique key does not stop
it, because insurance_id is NULL for the free-visit row and MySQL does not treat
NULLs as equal — and the following read was blind in the same way, so the panel
kept showing the old value. From the outside it simply looked like the field
would not save.

Reads now run outside the filter, the same exception the tenant-insurance
repository already makes for the same reason, with authorization still coming
from resolveTargetEntity(). findOneForInsurance() takes the newest row so a
tenant that already accumulated duplicates converges on the last value the user
entered, and a migration collapses those leftovers.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 16:52:04 +03:30

49 lines
1.9 KiB
PHP

<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* پاک‌سازی ردیف‌های تکراریِ «قیمت ویزیت آزاد».
*
* قید یکتای (entity_type, entity_id, insurance_id) ردیف ویزیت آزاد را نمی‌پوشاند،
* چون `insurance_id` آنجا NULL است و MySQL چند NULL را تکراری نمی‌شمارد. تا وقتی
* خواندنِ ردیفِ موجود زیر TenantFilter کور بود، هر بار ذخیره یک ردیف تازه می‌ساخت.
* تازه‌ترین ردیف همان چیزی است که کاربر آخرین‌بار ثبت کرده، پس بقیه حذف می‌شوند.
*/
final class Version20260818131524 extends AbstractMigration
{
public function getDescription(): string
{
return 'Collapse duplicate free-visit pricing rows to the newest one per tenant';
}
public function up(Schema $schema): void
{
$this->addSql(<<<'SQL'
DELETE p FROM entity_insurance_pricing p
JOIN (
SELECT entity_type, entity_id, MAX(id) AS keep_id
FROM entity_insurance_pricing
WHERE insurance_id IS NULL
GROUP BY entity_type, entity_id
HAVING COUNT(*) > 1
) newest
ON newest.entity_type = p.entity_type
AND newest.entity_id = p.entity_id
WHERE p.insurance_id IS NULL
AND p.id <> newest.keep_id
SQL);
}
public function down(Schema $schema): void
{
// ردیف‌های حذف‌شده تکراری بودند؛ برگرداندنشان همان وضعیت خراب را باز می‌سازد.
$this->throwIrreversibleMigrationException('Duplicate pricing rows are not restored.');
}
}