108 lines
4.4 KiB
PHP
108 lines
4.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
final class PricingService
|
|
{
|
|
public const CATEGORIES = [
|
|
'consultation' => 'Consultation',
|
|
'surgery' => 'Chirurgie',
|
|
'identification' => 'Identification',
|
|
'test' => 'Test / analyse',
|
|
'vaccine' => 'Vaccin',
|
|
'euthanasia' => 'Euthanasie',
|
|
'cremation' => 'Crémation',
|
|
'medication' => 'Médicament',
|
|
'dewormer' => 'Vermifuge',
|
|
'other' => 'Autre',
|
|
];
|
|
public const GROUPS = [
|
|
'act' => 'Acte',
|
|
'surgery_discount' => 'Actes chirurgicaux',
|
|
'medication' => 'Médicament hors antibiotique',
|
|
'antibiotic' => 'Antibiotique',
|
|
'ape_api' => 'APE / API',
|
|
'analysis' => 'Analyse',
|
|
'fixed' => 'Tarif fixe',
|
|
'none' => 'Sans remise',
|
|
];
|
|
public static function categoryLabel(string $key): string
|
|
{
|
|
return t('pricing.category.' . $key, [], self::CATEGORIES[$key] ?? $key);
|
|
}
|
|
public static function groupLabel(string $key): string
|
|
{
|
|
return t('pricing.group.' . $key, [], self::GROUPS[$key] ?? $key);
|
|
}
|
|
public static function cents(string $v): int
|
|
{
|
|
return max(0, (int) round((float) str_replace(',', '.', trim($v)) * 100));
|
|
}
|
|
public static function adoptionFees(): array
|
|
{
|
|
$rows = DB::pdo()->query(
|
|
"SELECT s.code,s.name,s.icon,COALESCE(r.fee_before_sterilization,200) fee_before_sterilization,COALESCE(r.fee_after_sterilization,220) fee_after_sterilization,COALESCE(r.is_free,0) is_free FROM ref_species s LEFT JOIN adoption_fee_rules r ON r.species_code=s.code WHERE s.active=1 ORDER BY s.sort_order,s.name COLLATE NOCASE",
|
|
)->fetchAll(PDO::FETCH_ASSOC);
|
|
return array_column($rows, null, 'code');
|
|
}
|
|
|
|
public static function adoptionFee(string $species, bool $sterilized): ?int
|
|
{
|
|
$fees = self::adoptionFees();
|
|
$rule = $fees[SpeciesService::normalize($species)] ?? null;
|
|
if (!$rule || (int) $rule['is_free'] === 1) {
|
|
return null;
|
|
}
|
|
return (int) $rule[$sterilized ? 'fee_after_sterilization' : 'fee_before_sterilization'];
|
|
}
|
|
|
|
public static function deleteTariff(int $id): ?string
|
|
{
|
|
$db = DB::pdo();
|
|
$stmt = $db->prepare('SELECT label FROM clinic_tariffs WHERE id=:id');
|
|
$stmt->execute([':id' => $id]);
|
|
$label = $stmt->fetchColumn();
|
|
if ($label === false) {
|
|
return null;
|
|
}
|
|
$db->prepare('DELETE FROM clinic_tariffs WHERE id=:id')->execute([':id' => $id]);
|
|
return (string) $label;
|
|
}
|
|
public static function tariffs(bool $active = false): array
|
|
{
|
|
$w = $active ? 'WHERE ct.active=1 AND dc.deleted_at IS NULL' : '';
|
|
return DB::pdo()
|
|
->query(
|
|
"SELECT ct.*,dc.name clinic_name,COALESCE(dr.percent,0) discount_percent,ROUND(ct.amount_cents*(1-COALESCE(dr.percent,0)/100.0)) effective_cents FROM clinic_tariffs ct JOIN directory_contacts dc ON dc.id=ct.clinic_contact_id LEFT JOIN clinic_discount_rules dr ON dr.clinic_contact_id=ct.clinic_contact_id AND dr.discount_group=ct.discount_group $w ORDER BY dc.name COLLATE NOCASE,ct.active DESC,ct.label COLLATE NOCASE",
|
|
)
|
|
->fetchAll(PDO::FETCH_ASSOC);
|
|
}
|
|
public static function record(PDO $db, int $animal, int $tariff, float $qty, string $date, string $notes = ''): int
|
|
{
|
|
$s = $db->prepare(
|
|
'SELECT ct.*,COALESCE(dr.percent,0) discount FROM clinic_tariffs ct LEFT JOIN clinic_discount_rules dr ON dr.clinic_contact_id=ct.clinic_contact_id AND dr.discount_group=ct.discount_group WHERE ct.id=? AND ct.active=1',
|
|
);
|
|
$s->execute([$tariff]);
|
|
$t = $s->fetch(PDO::FETCH_ASSOC);
|
|
if (!$t) {
|
|
throw new RuntimeException(t('error.tariff_not_found'));
|
|
}
|
|
$qty = max(0.01, $qty);
|
|
$total = (int) round($t['amount_cents'] * $qty * (1 - (float) $t['discount'] / 100));
|
|
$db->prepare(
|
|
'INSERT INTO animal_expenses(animal_id,clinic_contact_id,tariff_id,label,occurred_on,quantity,catalog_unit_cents,discount_percent,total_cents,notes,created_by) VALUES(?,?,?,?,?,?,?,?,?,?,?)',
|
|
)->execute([
|
|
$animal,
|
|
$t['clinic_contact_id'],
|
|
$tariff,
|
|
$t['label'],
|
|
$date,
|
|
$qty,
|
|
$t['amount_cents'],
|
|
$t['discount'],
|
|
$total,
|
|
$notes ?: null,
|
|
Auth::id(),
|
|
]);
|
|
return $total;
|
|
}
|
|
}
|