fix(representation): count only online bookings in the agent panel

The agent's own dashboard (dashboard/summary and doctors/performance) counted
every appointment belonging to their doctors, so the bookings a secretary types
into the panel — which earn the agent nothing — sat next to a commission column
that ignored them. Both now count only bookings that came from the agent's own
site, matching the monthly/yearly report. The per-doctor income column is also
scoped to this agent, since a doctor may have been under another one before.

Adds a backfill for the bookings paid before city domains resolved to an agent:
they carry neither booking_representation_id nor a FinancialBreakdown, and
neither can be recovered by replaying the request. Both are derived from
payments.frontend_address, the address the payment was started from. The
recovered breakdown is dated to the payment, not to the run, or a year of
commission would land in "today". Dry-run by default; re-running is a no-op,
and a payment whose domain does not match the doctor's owner is reported and
skipped rather than retried forever.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
hamed
2026-08-19 23:24:48 +03:30
co-authored by Claude Opus 5
parent be12502873
commit f863b39a74
5 changed files with 244 additions and 6 deletions
@@ -134,6 +134,28 @@ class OnlineAppointmentCommissionTest extends ApiTestCase
self::assertCount(1, $rows, 'ثبت باید idempotent بماند');
}
/** پنل خودِ نماینده هم همان قاعده را دارد، نه فقط گزارش ماهانه/سالانه. */
public function testRepresentationPanelSummaryCountsOnlyOnlineAppointments(): void
{
[$rep, , $doctor] = $this->makeRepWithCityAndDoctor();
$start = time() + 86400;
$online = $this->newAppointment($doctor, $this->createUser(), $start, $start + 900);
$online->setBookingRepresentationId($rep->getId());
$this->em->persist($online);
$manual = $this->newAppointment($doctor, $this->createUser(), $start + 3600, $start + 4500);
$this->em->persist($manual);
$this->em->flush();
$body = $this->authJson('GET', '/api/v1/representation/dashboard/summary', $rep->getUser());
self::assertSame(1, $body['data']['appointments']['total']);
$perf = $this->authJson('GET', '/api/v1/representation/doctors/performance?limit=100', $rep->getUser());
$row = current(array_filter($perf['data'], fn(array $r) => $r['uuid'] === $doctor->getUuid()));
self::assertSame(1, $row['appointments']['total']);
}
public function testDashboardCountsOnlyOnlineAppointments(): void
{
[$rep, , $doctor] = $this->makeRepWithCityAndDoctor();