feat(tax): implement tax rate history tracking and API endpoints

This commit is contained in:
hamed
2026-06-24 13:17:08 +03:30
parent 148d033114
commit 89e4a424f8
7 changed files with 186 additions and 82 deletions
+28 -3
View File
@@ -16,8 +16,6 @@ use OpenApi\Attributes as OA;
class SiteConfigController extends BaseController
{
private const ALLOWED_KEYS = [
'commission_enabled',
'commission_percent',
// financial engine
'appointment_commission_enabled',
'upgrade_commission_enabled',
@@ -47,6 +45,7 @@ class SiteConfigController extends BaseController
public function __construct(
private readonly SiteConfigRepository $configRepo,
private readonly \App\Config\Repository\TaxRateHistoryRepository $taxHistoryRepo,
private readonly EntityManagerInterface $em,
) {}
@@ -57,10 +56,14 @@ class SiteConfigController extends BaseController
}
#[Route('/api/v1/admin/settings', methods: ['PATCH'])]
public function patch(Request $request): JsonResponse
public function patch(Request $request, #[\Symfony\Component\Security\Http\Attribute\CurrentUser] \App\Auth\Entity\User $admin): JsonResponse
{
$data = json_decode($request->getContent(), true) ?? [];
// مقادیر فعلی مالیات برای تشخیص تغییر و ثبت تاریخچه.
$prevTaxPercent = $this->configRepo->get('tax_percent');
$prevTaxEnabled = $this->configRepo->get('tax_enabled');
foreach ($data as $key => $value) {
if (!in_array($key, self::ALLOWED_KEYS, true)) {
continue;
@@ -70,6 +73,28 @@ class SiteConfigController extends BaseController
$this->em->flush();
$newTaxPercent = $this->configRepo->get('tax_percent');
$newTaxEnabled = $this->configRepo->get('tax_enabled');
if ($newTaxPercent !== $prevTaxPercent || $newTaxEnabled !== $prevTaxEnabled) {
$this->taxHistoryRepo->save(new \App\Config\Entity\TaxRateHistory(
(string) $newTaxPercent,
$newTaxEnabled === '1',
$admin,
));
}
return $this->success($this->configRepo->getAll());
}
#[Route('/api/v1/admin/settings/tax-history', methods: ['GET'])]
public function taxHistory(): JsonResponse
{
$rows = $this->taxHistoryRepo->findBy([], ['changedAt' => 'DESC'], 50);
return $this->success(array_map(
fn(\App\Config\Entity\TaxRateHistory $h) => $h->toArray(),
$rows,
));
}
}
+54
View File
@@ -0,0 +1,54 @@
<?php
namespace App\Config\Entity;
use App\Auth\Entity\User;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity]
#[ORM\Table(name: 'tax_rate_history')]
#[ORM\Index(columns: ['changed_at'], name: 'idx_tax_history_date')]
class TaxRateHistory
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private ?int $id = null;
#[ORM\Column(name: 'tax_percent', type: 'decimal', precision: 5, scale: 2)]
private string $taxPercent;
#[ORM\Column(name: 'enabled', type: 'boolean')]
private bool $enabled;
#[ORM\ManyToOne(targetEntity: User::class)]
#[ORM\JoinColumn(name: 'changed_by', referencedColumnName: 'id', nullable: true, onDelete: 'SET NULL')]
private ?User $changedBy = null;
#[ORM\Column(name: 'changed_at', type: 'integer')]
private int $changedAt;
public function __construct(string $taxPercent, bool $enabled, ?User $changedBy)
{
$this->taxPercent = $taxPercent;
$this->enabled = $enabled;
$this->changedBy = $changedBy;
$this->changedAt = time();
}
public function getId(): ?int { return $this->id; }
public function getTaxPercent(): string { return $this->taxPercent; }
public function isEnabled(): bool { return $this->enabled; }
public function getChangedBy(): ?User { return $this->changedBy; }
public function getChangedAt(): int { return $this->changedAt; }
public function toArray(): array
{
return [
'tax_percent' => (float) $this->taxPercent,
'enabled' => $this->enabled,
'changed_by_name' => $this->changedBy?->getRealName(),
'changed_at' => $this->changedAt,
];
}
}
@@ -10,8 +10,6 @@ class SiteConfigRepository extends ServiceEntityRepository
{
// Default values returned when a key is missing from DB
private const DEFAULTS = [
'commission_enabled' => '0',
'commission_percent' => '0',
// financial engine
'appointment_commission_enabled' => '0',
'upgrade_commission_enabled' => '0',
@@ -0,0 +1,21 @@
<?php
namespace App\Config\Repository;
use App\Config\Entity\TaxRateHistory;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
class TaxRateHistoryRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, TaxRateHistory::class);
}
public function save(TaxRateHistory $entity, bool $flush = true): void
{
$this->getEntityManager()->persist($entity);
if ($flush) $this->getEntityManager()->flush();
}
}