feat(insurance): resolve coverage percent per service category
Base insurance is a percentage-only rule: patient share is now total minus the base share, and the contract franchise no longer inflates it (franchise stays meaningful for supplementary contracts only). Coverage percentages are managed centrally by admin per service category (outpatient/inpatient, extensible via the ServiceCategory enum). A tenant contract may override a category, otherwise it follows the admin default live — changing the central value immediately applies to every contract that did not override it. - add ServiceCategory enum + GET /api/v1/service-categories as the single source of the category list for every client - add insurance_coverage_defaults (+ GET/PUT admin coverage-defaults endpoints) and expose coverage_defaults on the insurance list and insurance-pricing - add tenant_insurance_category_coverage; tenant-insurances accepts optional category_coverages (needs insurances.update) and returns the effective percentages with their source - add service_items.service_category; visits always resolve as outpatient - drop the reverse-engineered percent from patient_share_rials in MyPatientsPage and align the client-side BillingCalculator mirror in CreateStep Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Central admin-managed coverage percentages per insurance and service category.
|
||||
*/
|
||||
final class Version20260725115603 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Add insurance_coverage_defaults (admin-managed coverage percent per insurance and service category)';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('CREATE TABLE insurance_coverage_defaults (id INT AUTO_INCREMENT NOT NULL, insurance_id INT NOT NULL, service_category VARCHAR(30) NOT NULL, coverage_percent NUMERIC(5, 2) NOT NULL, updated_at INT NOT NULL, UNIQUE INDEX uniq_insurance_service_category (insurance_id, service_category), PRIMARY KEY (id)) DEFAULT CHARACTER SET utf8mb4');
|
||||
|
||||
// Every insurance gets a full row set so the admin panel always shows a complete
|
||||
// grid: a missing row must never be read as "0% on purpose".
|
||||
foreach (['outpatient', 'inpatient'] as $category) {
|
||||
$this->addSql(
|
||||
'INSERT INTO insurance_coverage_defaults (insurance_id, service_category, coverage_percent, updated_at)
|
||||
SELECT i.id, :category, 0.00, UNIX_TIMESTAMP() FROM insurances i',
|
||||
['category' => $category],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('DROP TABLE insurance_coverage_defaults');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Per-service-category coverage overrides a tenant sets on its own insurance contract.
|
||||
* Rows exist only where the tenant overrode the central admin default.
|
||||
*/
|
||||
final class Version20260725120831 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Add tenant_insurance_category_coverage (contract-level coverage percent per service category)';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('CREATE TABLE tenant_insurance_category_coverage (id INT AUTO_INCREMENT NOT NULL, tenant_insurance_id INT NOT NULL, service_category VARCHAR(30) NOT NULL, coverage_percent NUMERIC(5, 2) NOT NULL, updated_at INT NOT NULL, UNIQUE INDEX uniq_tenant_insurance_category (tenant_insurance_id, service_category), PRIMARY KEY (id)) DEFAULT CHARACTER SET utf8mb4');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('DROP TABLE tenant_insurance_category_coverage');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Service kind (outpatient/inpatient) a service item belongs to. The insurance
|
||||
* coverage percentage is resolved per this value.
|
||||
*/
|
||||
final class Version20260725121548 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Add service_items.service_category (defaults every existing row to outpatient)';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql("ALTER TABLE service_items ADD service_category VARCHAR(30) DEFAULT 'outpatient' NOT NULL");
|
||||
$this->addSql("UPDATE service_items SET service_category = 'outpatient' WHERE service_category = ''");
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE service_items DROP service_category');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user