Add patient file attachments: a new PatientAttachment entity (record-scoped,
CASCADE) + repository, and endpoints GET /patient/{uuid}/attachments,
POST /patient/{uuid}/attachment (raw-body upload) and DELETE
/patient/attachment/{uuid} (owner-scoped). Factor the shared raw-body upload
logic into FileUploadService. Wire the "ضمیمه" tab in PatientDetailPage
(upload + list + delete). PHPUnit covers list/delete/ownership; Vitest covers
the tab. API docs updated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
63 lines
2.2 KiB
PHP
63 lines
2.2 KiB
PHP
<?php
|
|
|
|
namespace App\Tests\Patient;
|
|
|
|
use App\Doctor\Entity\Doctor;
|
|
use App\Patient\Entity\PatientAttachment;
|
|
use App\Patient\Entity\PatientRecord;
|
|
use App\Tests\ApiTestCase;
|
|
|
|
/**
|
|
* Patient attachments: list, delete, and tenant ownership scoping.
|
|
*/
|
|
class PatientAttachmentTest extends ApiTestCase
|
|
{
|
|
/** @return array{0: \App\Auth\Entity\User, 1: PatientRecord} */
|
|
private function recordFor(): array
|
|
{
|
|
$owner = $this->createUser(['ROLE_DOCTOR']);
|
|
$doctor = new Doctor($owner, 'دکتر');
|
|
$this->em->persist($doctor);
|
|
$this->em->flush();
|
|
|
|
$patient = $this->createUser(['ROLE_USER']);
|
|
$record = new PatientRecord('doctor', $doctor->getId(), $patient, 'doctor', $doctor->getId());
|
|
$this->em->persist($record);
|
|
$this->em->flush();
|
|
|
|
return [$owner, $record];
|
|
}
|
|
|
|
public function testListAndDelete(): void
|
|
{
|
|
[$owner, $record] = $this->recordFor();
|
|
$att = new PatientAttachment($record, 'آزمایش.pdf', '/uploads/patients/attachments/x.pdf', 'application/pdf', 1234);
|
|
$this->em->persist($att);
|
|
$this->em->flush();
|
|
$attUuid = $att->getUuid();
|
|
|
|
$list = $this->authJson('GET', '/api/v1/patient/' . $record->getUuid() . '/attachments', $owner);
|
|
self::assertSame(200, $this->responseCode());
|
|
self::assertCount(1, $list['data']);
|
|
self::assertSame('آزمایش.pdf', $list['data'][0]['name']);
|
|
|
|
$this->authJson('DELETE', '/api/v1/patient/attachment/' . $attUuid, $owner);
|
|
self::assertSame(200, $this->responseCode());
|
|
|
|
$after = $this->authJson('GET', '/api/v1/patient/' . $record->getUuid() . '/attachments', $owner);
|
|
self::assertCount(0, $after['data']);
|
|
}
|
|
|
|
public function testCannotDeleteAnotherTenantsAttachment(): void
|
|
{
|
|
[, $record] = $this->recordFor();
|
|
$att = new PatientAttachment($record, 'x.pdf', '/uploads/x.pdf');
|
|
$this->em->persist($att);
|
|
$this->em->flush();
|
|
|
|
[$otherOwner] = $this->recordFor();
|
|
$this->authJson('DELETE', '/api/v1/patient/attachment/' . $att->getUuid(), $otherOwner);
|
|
self::assertSame(404, $this->responseCode());
|
|
}
|
|
}
|