Complete Dentistry commercial suite with PMS depth.
Deploy Ladill Care / deploy (push) Successful in 31s
Deploy Ladill Care / deploy (push) Successful in 31s
Add plan lifecycle, visit stages with chair/recovery points, primary dentition charting, imaging void, revenue reports, perio exams, lab cases, and recalls. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Care\Dentistry;
|
||||
|
||||
use App\Models\DentalLabCase;
|
||||
use App\Models\Organization;
|
||||
use App\Models\Patient;
|
||||
use App\Models\Visit;
|
||||
use App\Services\Care\AuditLogger;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class DentalLabCaseService
|
||||
{
|
||||
/**
|
||||
* @return Collection<int, DentalLabCase>
|
||||
*/
|
||||
public function casesForPatient(Organization $organization, Patient $patient, string $ownerRef, int $limit = 30): Collection
|
||||
{
|
||||
return DentalLabCase::owned($ownerRef)
|
||||
->where('organization_id', $organization->id)
|
||||
->where('patient_id', $patient->id)
|
||||
->latest('id')
|
||||
->limit($limit)
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array{case_type: string, lab_name?: ?string, tooth_codes?: list<string>, plan_item_id?: ?int, due_at?: ?string, notes?: ?string, status?: string} $data
|
||||
*/
|
||||
public function create(
|
||||
Organization $organization,
|
||||
Patient $patient,
|
||||
string $ownerRef,
|
||||
array $data,
|
||||
?Visit $visit = null,
|
||||
?string $actorRef = null,
|
||||
): DentalLabCase {
|
||||
$type = (string) ($data['case_type'] ?? '');
|
||||
if (! array_key_exists($type, DentalCatalog::labCaseTypes())) {
|
||||
throw new \InvalidArgumentException("Invalid lab case type [{$type}].");
|
||||
}
|
||||
|
||||
$status = (string) ($data['status'] ?? DentalLabCase::STATUS_DRAFT);
|
||||
if (! array_key_exists($status, DentalCatalog::labCaseStatuses())) {
|
||||
throw new \InvalidArgumentException("Invalid lab case status [{$status}].");
|
||||
}
|
||||
|
||||
$toothCodes = array_values(array_filter(
|
||||
$data['tooth_codes'] ?? [],
|
||||
fn ($c) => DentalCatalog::isValidToothCode((string) $c),
|
||||
));
|
||||
|
||||
$case = DentalLabCase::create([
|
||||
'owner_ref' => $ownerRef,
|
||||
'organization_id' => $organization->id,
|
||||
'patient_id' => $patient->id,
|
||||
'visit_id' => $visit?->id,
|
||||
'plan_item_id' => $data['plan_item_id'] ?? null,
|
||||
'tooth_codes' => $toothCodes,
|
||||
'case_type' => $type,
|
||||
'lab_name' => $data['lab_name'] ?? null,
|
||||
'status' => $status,
|
||||
'ordered_at' => in_array($status, [DentalLabCase::STATUS_ORDERED, DentalLabCase::STATUS_SENT], true) ? now() : null,
|
||||
'due_at' => $data['due_at'] ?? null,
|
||||
'notes' => $data['notes'] ?? null,
|
||||
'created_by' => $actorRef ?? $ownerRef,
|
||||
]);
|
||||
|
||||
AuditLogger::record($ownerRef, 'dental.lab.created', $organization->id, $actorRef, DentalLabCase::class, $case->id);
|
||||
|
||||
return $case;
|
||||
}
|
||||
|
||||
public function transition(
|
||||
DentalLabCase $case,
|
||||
string $status,
|
||||
string $ownerRef,
|
||||
?string $actorRef = null,
|
||||
): DentalLabCase {
|
||||
if (! array_key_exists($status, DentalCatalog::labCaseStatuses())) {
|
||||
throw new \InvalidArgumentException("Invalid lab case status [{$status}].");
|
||||
}
|
||||
|
||||
$updates = ['status' => $status];
|
||||
if (in_array($status, [DentalLabCase::STATUS_ORDERED, DentalLabCase::STATUS_SENT], true) && ! $case->ordered_at) {
|
||||
$updates['ordered_at'] = now();
|
||||
}
|
||||
if (in_array($status, [DentalLabCase::STATUS_RECEIVED, DentalLabCase::STATUS_FITTED], true) && ! $case->received_at) {
|
||||
$updates['received_at'] = now();
|
||||
}
|
||||
|
||||
$case->update($updates);
|
||||
|
||||
AuditLogger::record($ownerRef, 'dental.lab.transitioned', $case->organization_id, $actorRef, DentalLabCase::class, $case->id, [
|
||||
'status' => $status,
|
||||
]);
|
||||
|
||||
return $case->fresh();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user