add test batches
This commit is contained in:
@@ -9,7 +9,9 @@ use RuntimeException;
|
||||
|
||||
class ReimbursementBatchAssignmentService
|
||||
{
|
||||
public function __construct(private ReimbursementLookupService $lookupService) {}
|
||||
public function __construct(private ReimbursementLookupService $lookupService)
|
||||
{
|
||||
}
|
||||
|
||||
public function updateAssignment(
|
||||
int $expenseId,
|
||||
@@ -33,7 +35,7 @@ class ReimbursementBatchAssignmentService
|
||||
if ($batchId <= 0) {
|
||||
if ($activeItem) {
|
||||
$activeItem->update(['unassigned_at' => $now]);
|
||||
if (! $reimbursementId && ! empty($activeItem->reimbursement_id)) {
|
||||
if (!$reimbursementId && !empty($activeItem->reimbursement_id)) {
|
||||
$reimbursementId = (int) $activeItem->reimbursement_id;
|
||||
}
|
||||
}
|
||||
@@ -46,7 +48,7 @@ class ReimbursementBatchAssignmentService
|
||||
}
|
||||
|
||||
$batch = ReimbursementBatch::query()->find($batchId);
|
||||
if (! $batch || strtolower((string) $batch->status) !== ReimbursementBatch::STATUS_OPEN) {
|
||||
if (!$batch || strtolower((string) $batch->status) !== ReimbursementBatch::STATUS_OPEN) {
|
||||
throw new RuntimeException('Batch not found or already closed.');
|
||||
}
|
||||
|
||||
@@ -61,7 +63,7 @@ class ReimbursementBatchAssignmentService
|
||||
}
|
||||
|
||||
if ($activeSameBatch) {
|
||||
if (! $reimbursementId) {
|
||||
if (!$reimbursementId) {
|
||||
$reimbursementId = $activeItem->reimbursement_id
|
||||
? (int) $activeItem->reimbursement_id
|
||||
: $this->lookupService->findReimbursementIdForExpense($expenseId);
|
||||
@@ -83,12 +85,12 @@ class ReimbursementBatchAssignmentService
|
||||
|
||||
if ($activeItem) {
|
||||
$activeItem->update(['unassigned_at' => $now]);
|
||||
if (! $reimbursementId && ! empty($activeItem->reimbursement_id)) {
|
||||
if (!$reimbursementId && !empty($activeItem->reimbursement_id)) {
|
||||
$reimbursementId = (int) $activeItem->reimbursement_id;
|
||||
}
|
||||
}
|
||||
|
||||
if (! $reimbursementId) {
|
||||
if (!$reimbursementId) {
|
||||
$reimbursementId = $this->lookupService->findReimbursementIdForExpense($expenseId);
|
||||
}
|
||||
|
||||
@@ -103,7 +105,7 @@ class ReimbursementBatchAssignmentService
|
||||
'semester' => $semester,
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('Failed to assign expense to batch: '.$e->getMessage(), [
|
||||
Log::error('Failed to assign expense to batch: ' . $e->getMessage(), [
|
||||
'expense_id' => $expenseId,
|
||||
'batch_id' => $batchId,
|
||||
]);
|
||||
|
||||
@@ -12,7 +12,9 @@ use RuntimeException;
|
||||
|
||||
class ReimbursementBatchService
|
||||
{
|
||||
public function __construct(private ReimbursementLookupService $lookupService) {}
|
||||
public function __construct(private ReimbursementLookupService $lookupService)
|
||||
{
|
||||
}
|
||||
|
||||
public function createBatch(?string $title, int $userId, string $schoolYear, string $semester): array
|
||||
{
|
||||
@@ -29,7 +31,7 @@ class ReimbursementBatchService
|
||||
'yearly_batch_number' => $sequence,
|
||||
]);
|
||||
|
||||
$label = trim((string) $batch->title) !== '' ? (string) $batch->title : ('Batch #'.$sequence);
|
||||
$label = trim((string) $batch->title) !== '' ? (string) $batch->title : ('Batch #' . $sequence);
|
||||
if (trim((string) $batch->title) === '') {
|
||||
$batch->title = $label;
|
||||
$batch->save();
|
||||
@@ -45,7 +47,7 @@ class ReimbursementBatchService
|
||||
public function lockBatch(int $batchId, int $userId, string $schoolYear, string $semester): void
|
||||
{
|
||||
$batch = ReimbursementBatch::query()->find($batchId);
|
||||
if (! $batch || strtolower((string) $batch->status) !== ReimbursementBatch::STATUS_OPEN) {
|
||||
if (!$batch || strtolower((string) $batch->status) !== ReimbursementBatch::STATUS_OPEN) {
|
||||
throw new RuntimeException('Batch not found or already closed.');
|
||||
}
|
||||
|
||||
@@ -58,7 +60,7 @@ class ReimbursementBatchService
|
||||
$adminIds = array_values(array_unique($adminRows->pluck('admin_id')->map(fn ($id) => (int) $id)->all()));
|
||||
$requiredAdmins = array_values(array_filter($adminIds, static fn ($adminId) => $adminId > 0));
|
||||
|
||||
if (! empty($requiredAdmins)) {
|
||||
if (!empty($requiredAdmins)) {
|
||||
$uploadedAdminIds = ReimbursementBatchAdminFile::query()
|
||||
->where('batch_id', $batchId)
|
||||
->whereIn('admin_id', $requiredAdmins)
|
||||
@@ -69,7 +71,7 @@ class ReimbursementBatchService
|
||||
->all();
|
||||
|
||||
foreach ($requiredAdmins as $adminId) {
|
||||
if (! in_array($adminId, $uploadedAdminIds, true)) {
|
||||
if (!in_array($adminId, $uploadedAdminIds, true)) {
|
||||
throw new RuntimeException('All admin sections must have a check file before submitting the batch.');
|
||||
}
|
||||
}
|
||||
@@ -92,7 +94,7 @@ class ReimbursementBatchService
|
||||
|
||||
$reimbId = $item->batch_reimb_id ?: ($item->expense_reimb_id ?: $this->lookupService->findReimbursementIdForExpense($expenseId));
|
||||
|
||||
if (! $reimbId) {
|
||||
if (!$reimbId) {
|
||||
$payload = [
|
||||
'expense_id' => $expenseId,
|
||||
'amount' => (float) ($item->amount ?? 0),
|
||||
@@ -120,7 +122,7 @@ class ReimbursementBatchService
|
||||
]);
|
||||
|
||||
Expense::query()->where('id', $expenseId)->update(['reimbursement_id' => $reimbId]);
|
||||
if (! empty($item->batch_item_id)) {
|
||||
if (!empty($item->batch_item_id)) {
|
||||
ReimbursementBatchItem::query()->where('id', (int) $item->batch_item_id)->update([
|
||||
'reimbursement_id' => $reimbId,
|
||||
]);
|
||||
|
||||
@@ -17,11 +17,11 @@ class ReimbursementDonationService
|
||||
}
|
||||
|
||||
$expense = Expense::query()->find($expenseId);
|
||||
if (! $expense) {
|
||||
if (!$expense) {
|
||||
throw new RuntimeException('Expense not found.');
|
||||
}
|
||||
|
||||
if (! empty($expense->reimbursement_id)) {
|
||||
if (!empty($expense->reimbursement_id)) {
|
||||
throw new RuntimeException('Expense is already tied to a reimbursement.');
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ class ReimbursementDonationService
|
||||
DB::commit();
|
||||
} catch (\Throwable $e) {
|
||||
DB::rollBack();
|
||||
Log::error('Failed to mark donation: '.$e->getMessage(), ['expense_id' => $expenseId]);
|
||||
Log::error('Failed to mark donation: ' . $e->getMessage(), ['expense_id' => $expenseId]);
|
||||
throw new RuntimeException('Unable to mark donation right now.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,9 @@ use ZipArchive;
|
||||
|
||||
class ReimbursementEmailService
|
||||
{
|
||||
public function __construct(private ReimbursementRecipientService $recipients) {}
|
||||
public function __construct(private ReimbursementRecipientService $recipients)
|
||||
{
|
||||
}
|
||||
|
||||
public function sendBatchEmail(
|
||||
int $batchId,
|
||||
@@ -21,14 +23,14 @@ class ReimbursementEmailService
|
||||
array $checkIds
|
||||
): bool {
|
||||
$batch = ReimbursementBatch::query()->find($batchId);
|
||||
if (! $batch) {
|
||||
if (!$batch) {
|
||||
throw new \RuntimeException('Requested batch was not found.');
|
||||
}
|
||||
|
||||
$receiptRows = ! empty($receiptIds) ? $this->fetchBatchReceiptRows($batchId, $receiptIds) : [];
|
||||
$receiptRows = !empty($receiptIds) ? $this->fetchBatchReceiptRows($batchId, $receiptIds) : [];
|
||||
|
||||
$checkRows = [];
|
||||
if (! empty($checkIds)) {
|
||||
if (!empty($checkIds)) {
|
||||
$checkRows = ReimbursementBatchAdminFile::query()
|
||||
->select('id as file_id', 'admin_id', 'filename', 'original_filename', 'uploaded_at')
|
||||
->where('batch_id', $batchId)
|
||||
@@ -38,29 +40,29 @@ class ReimbursementEmailService
|
||||
|
||||
$adminLookup = [];
|
||||
foreach ($this->recipients->adminRoster() as $admin) {
|
||||
$adminLookup[(int) ($admin['id'] ?? 0)] = trim((string) (($admin['firstname'] ?? '').' '.($admin['lastname'] ?? '')));
|
||||
$adminLookup[(int) ($admin['id'] ?? 0)] = trim((string) (($admin['firstname'] ?? '') . ' ' . ($admin['lastname'] ?? '')));
|
||||
}
|
||||
foreach ($checkRows as &$row) {
|
||||
$aid = (int) ($row['admin_id'] ?? 0);
|
||||
$row['admin'] = $adminLookup[$aid] ?? ($aid > 0 ? 'Admin #'.$aid : 'Admin');
|
||||
$row['admin'] = $adminLookup[$aid] ?? ($aid > 0 ? 'Admin #' . $aid : 'Admin');
|
||||
}
|
||||
unset($row);
|
||||
}
|
||||
|
||||
$tempDir = storage_path('tmp');
|
||||
if (! is_dir($tempDir)) {
|
||||
if (!is_dir($tempDir)) {
|
||||
mkdir($tempDir, 0755, true);
|
||||
}
|
||||
|
||||
$cleanupPaths = [];
|
||||
|
||||
$batchLabel = trim((string) ($batch->title ?? '')) ?: ('Batch #'.((int) ($batch->yearly_batch_number ?? $batchId)));
|
||||
$batchLabel = trim((string) ($batch->title ?? '')) ?: ('Batch #' . ((int) ($batch->yearly_batch_number ?? $batchId)));
|
||||
$batchFileLabel = $this->sanitizeAttachmentComponent($batchLabel);
|
||||
|
||||
$csvPath = tempnam($tempDir, 'batch_csv_');
|
||||
$cleanupPaths[] = $csvPath;
|
||||
$csvHandle = fopen($csvPath, 'w');
|
||||
if (! $csvHandle) {
|
||||
if (!$csvHandle) {
|
||||
if (is_file($csvPath)) {
|
||||
@unlink($csvPath);
|
||||
}
|
||||
@@ -72,31 +74,31 @@ class ReimbursementEmailService
|
||||
$this->writeBatchCsvSummary($csvHandle, $receiptRows, $batchClosedDate);
|
||||
fclose($csvHandle);
|
||||
|
||||
$csvAttachmentName = $batchFileLabel.'_summary.csv';
|
||||
$csvAttachmentName = $batchFileLabel . '_summary.csv';
|
||||
|
||||
$receiptsArchivePath = null;
|
||||
$receiptZipCreated = false;
|
||||
if (! empty($receiptRows)) {
|
||||
$archivePath = $tempDir.'/batch_receipts_'.$batchId.'_'.date('Ymd_His').'_'.bin2hex(random_bytes(4)).'.zip';
|
||||
$zip = new ZipArchive;
|
||||
if (!empty($receiptRows)) {
|
||||
$archivePath = $tempDir . '/batch_receipts_' . $batchId . '_' . date('Ymd_His') . '_' . bin2hex(random_bytes(4)) . '.zip';
|
||||
$zip = new ZipArchive();
|
||||
$added = 0;
|
||||
$usedNames = [];
|
||||
if ($zip->open($archivePath, ZipArchive::CREATE | ZipArchive::OVERWRITE) === true) {
|
||||
foreach ($receiptRows as $row) {
|
||||
$sourcePath = storage_path('uploads/receipts/'.basename((string) ($row['receipt_filename'] ?? '')));
|
||||
if (! is_file($sourcePath)) {
|
||||
$sourcePath = storage_path('uploads/receipts/' . basename((string) ($row['receipt_filename'] ?? '')));
|
||||
if (!is_file($sourcePath)) {
|
||||
continue;
|
||||
}
|
||||
$firstName = $row['purchaser_firstname'] ?? '';
|
||||
if (trim($firstName) === '' && ! empty($row['purchaser_lastname'] ?? '')) {
|
||||
if (trim($firstName) === '' && !empty($row['purchaser_lastname'] ?? '')) {
|
||||
$firstName = $row['purchaser_lastname'];
|
||||
}
|
||||
$firstName = $this->sanitizeAttachmentComponent($firstName);
|
||||
$vendorPart = $this->sanitizeAttachmentComponent($row['retailor'] ?? '');
|
||||
$datePart = $this->formatAttachmentDate($row['purchase_date'] ?? '');
|
||||
$extension = pathinfo($sourcePath, PATHINFO_EXTENSION);
|
||||
$extPart = $extension !== '' ? ('.'.strtolower($extension)) : '';
|
||||
$baseName = $firstName.'_'.$vendorPart.'_'.$datePart;
|
||||
$extPart = $extension !== '' ? ('.' . strtolower($extension)) : '';
|
||||
$baseName = $firstName . '_' . $vendorPart . '_' . $datePart;
|
||||
$entryName = $this->uniqueZipEntryName($baseName, $extPart, $usedNames);
|
||||
if ($zip->addFile($sourcePath, $entryName)) {
|
||||
$added++;
|
||||
@@ -115,21 +117,21 @@ class ReimbursementEmailService
|
||||
|
||||
$checksArchivePath = null;
|
||||
$checksAdded = 0;
|
||||
if (! empty($checkRows)) {
|
||||
$archivePath = $tempDir.'/batch_checks_'.$batchId.'_'.date('Ymd_His').'_'.bin2hex(random_bytes(4)).'.zip';
|
||||
$zip = new ZipArchive;
|
||||
if (!empty($checkRows)) {
|
||||
$archivePath = $tempDir . '/batch_checks_' . $batchId . '_' . date('Ymd_His') . '_' . bin2hex(random_bytes(4)) . '.zip';
|
||||
$zip = new ZipArchive();
|
||||
$usedNames = [];
|
||||
if ($zip->open($archivePath, ZipArchive::CREATE | ZipArchive::OVERWRITE) === true) {
|
||||
foreach ($checkRows as $row) {
|
||||
$sourcePath = storage_path('uploads/reimbursements/'.basename((string) ($row['filename'] ?? '')));
|
||||
if (! is_file($sourcePath)) {
|
||||
$sourcePath = storage_path('uploads/reimbursements/' . basename((string) ($row['filename'] ?? '')));
|
||||
if (!is_file($sourcePath)) {
|
||||
continue;
|
||||
}
|
||||
$adminLabel = $row['admin'] ?? 'Admin';
|
||||
$firstToken = strtok($adminLabel, ' ');
|
||||
$namePart = $this->sanitizeAttachmentComponent($firstToken ?: $adminLabel);
|
||||
$extension = pathinfo($sourcePath, PATHINFO_EXTENSION);
|
||||
$extPart = $extension !== '' ? ('.'.strtolower($extension)) : '';
|
||||
$extPart = $extension !== '' ? ('.' . strtolower($extension)) : '';
|
||||
$entryName = $this->uniqueZipEntryName($namePart, $extPart, $usedNames);
|
||||
if ($zip->addFile($sourcePath, $entryName)) {
|
||||
$checksAdded++;
|
||||
@@ -153,14 +155,14 @@ class ReimbursementEmailService
|
||||
$attachmentSummary[] = 'Check Scans';
|
||||
}
|
||||
|
||||
$subject = 'Reimbursement Batch Export: '.$batchLabel;
|
||||
$subject = 'Reimbursement Batch Export: ' . $batchLabel;
|
||||
$bodyParts = [
|
||||
'<p>Please find attached the export for <strong>'.htmlspecialchars($batchLabel, ENT_QUOTES, 'UTF-8').'</strong>.</p>',
|
||||
'<p>Please find attached the export for <strong>' . htmlspecialchars($batchLabel, ENT_QUOTES, 'UTF-8') . '</strong>.</p>',
|
||||
];
|
||||
if (trim($message) !== '') {
|
||||
$bodyParts[] = '<p><strong>Message:</strong><br>'.nl2br(htmlspecialchars($message, ENT_QUOTES, 'UTF-8')).'</p>';
|
||||
$bodyParts[] = '<p><strong>Message:</strong><br>' . nl2br(htmlspecialchars($message, ENT_QUOTES, 'UTF-8')) . '</p>';
|
||||
}
|
||||
$bodyParts[] = '<p>Attachments: '.htmlspecialchars(implode(', ', $attachmentSummary), ENT_QUOTES, 'UTF-8').'.</p>';
|
||||
$bodyParts[] = '<p>Attachments: ' . htmlspecialchars(implode(', ', $attachmentSummary), ENT_QUOTES, 'UTF-8') . '.</p>';
|
||||
$bodyParts[] = '<p>Regards,<br>Al Rahma Sunday School</p>';
|
||||
$htmlBody = implode("\n", $bodyParts);
|
||||
|
||||
@@ -168,10 +170,10 @@ class ReimbursementEmailService
|
||||
['path' => $csvPath, 'name' => $csvAttachmentName],
|
||||
];
|
||||
if ($receiptsArchivePath) {
|
||||
$attachments[] = ['path' => $receiptsArchivePath, 'name' => $batchFileLabel.'_receipts.zip'];
|
||||
$attachments[] = ['path' => $receiptsArchivePath, 'name' => $batchFileLabel . '_receipts.zip'];
|
||||
}
|
||||
if ($checksArchivePath) {
|
||||
$attachments[] = ['path' => $checksArchivePath, 'name' => $batchFileLabel.'_checks.zip'];
|
||||
$attachments[] = ['path' => $checksArchivePath, 'name' => $batchFileLabel . '_checks.zip'];
|
||||
}
|
||||
|
||||
$sender = $this->resolveSender('general');
|
||||
@@ -179,11 +181,11 @@ class ReimbursementEmailService
|
||||
try {
|
||||
Mail::html($htmlBody, function ($message) use ($recipientEmail, $subject, $sender, $attachments) {
|
||||
$message->to($recipientEmail)->subject($subject);
|
||||
if (! empty($sender['email'])) {
|
||||
if (!empty($sender['email'])) {
|
||||
$message->from($sender['email'], $sender['name']);
|
||||
}
|
||||
foreach ($attachments as $file) {
|
||||
if (! empty($file['path']) && is_file($file['path'])) {
|
||||
if (!empty($file['path']) && is_file($file['path'])) {
|
||||
$message->attach($file['path'], ['as' => $file['name'] ?? basename($file['path'])]);
|
||||
}
|
||||
}
|
||||
@@ -191,8 +193,7 @@ class ReimbursementEmailService
|
||||
|
||||
return true;
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('Failed to send batch export email: '.$e->getMessage());
|
||||
|
||||
Log::error('Failed to send batch export email: ' . $e->getMessage());
|
||||
return false;
|
||||
} finally {
|
||||
foreach ($cleanupPaths as $path) {
|
||||
@@ -211,7 +212,7 @@ class ReimbursementEmailService
|
||||
->leftJoin('users as u', 'u.id', '=', 'e.purchased_by')
|
||||
->where('bi.batch_id', $batchId);
|
||||
|
||||
if (! empty($receiptIds)) {
|
||||
if (!empty($receiptIds)) {
|
||||
$builder->whereIn('e.id', $receiptIds);
|
||||
}
|
||||
|
||||
@@ -229,7 +230,7 @@ class ReimbursementEmailService
|
||||
'purchaser_lastname' => $row->purchaser_lastname ?? null,
|
||||
];
|
||||
}, $rows), static function ($row) {
|
||||
return ! empty($row['receipt_filename']);
|
||||
return !empty($row['receipt_filename']);
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -246,7 +247,7 @@ class ReimbursementEmailService
|
||||
{
|
||||
$receiptTotalsByRecipient = [];
|
||||
foreach ($receiptRows as $row) {
|
||||
$recipientName = trim(($row['purchaser_firstname'] ?? '').' '.($row['purchaser_lastname'] ?? ''));
|
||||
$recipientName = trim(($row['purchaser_firstname'] ?? '') . ' ' . ($row['purchaser_lastname'] ?? ''));
|
||||
if ($recipientName === '') {
|
||||
$recipientName = 'Unknown';
|
||||
}
|
||||
@@ -270,7 +271,7 @@ class ReimbursementEmailService
|
||||
implode(' | ', $descriptionParts),
|
||||
]);
|
||||
}
|
||||
if (! empty($receiptTotalsByRecipient)) {
|
||||
if (!empty($receiptTotalsByRecipient)) {
|
||||
fputcsv($handle, []);
|
||||
fputcsv($handle, ['Totals by Recipient', '', '', '', '', '', '', '']);
|
||||
foreach ($receiptTotalsByRecipient as $recipient => $total) {
|
||||
@@ -293,46 +294,42 @@ class ReimbursementEmailService
|
||||
{
|
||||
$clean = preg_replace('/[^A-Za-z0-9]+/', '_', trim((string) $value));
|
||||
$clean = trim($clean, '_');
|
||||
|
||||
return $clean === '' ? 'unknown' : $clean;
|
||||
}
|
||||
|
||||
private function formatAttachmentDate(?string $value): string
|
||||
{
|
||||
if (! $value) {
|
||||
if (!$value) {
|
||||
return 'unknown';
|
||||
}
|
||||
$timestamp = strtotime($value);
|
||||
if ($timestamp === false) {
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
return date('Ymd', $timestamp);
|
||||
}
|
||||
|
||||
private function uniqueZipEntryName(string $base, string $extension, array &$used): string
|
||||
{
|
||||
$candidate = $base.$extension;
|
||||
$candidate = $base . $extension;
|
||||
$counter = 1;
|
||||
while (isset($used[$candidate])) {
|
||||
$candidate = $base.'_'.$counter.$extension;
|
||||
$candidate = $base . '_' . $counter . $extension;
|
||||
$counter++;
|
||||
}
|
||||
$used[$candidate] = true;
|
||||
|
||||
return $candidate;
|
||||
}
|
||||
|
||||
private function formatCsvDate(?string $value): string
|
||||
{
|
||||
if (! $value) {
|
||||
if (!$value) {
|
||||
return '';
|
||||
}
|
||||
$timestamp = strtotime($value);
|
||||
if ($timestamp === false) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return date('m-d-Y', $timestamp);
|
||||
}
|
||||
|
||||
@@ -344,7 +341,6 @@ class ReimbursementEmailService
|
||||
|
||||
if (is_array($senders) && isset($senders[$fromKey])) {
|
||||
$info = $senders[$fromKey];
|
||||
|
||||
return [
|
||||
'name' => (string) ($info['name'] ?? 'Sender'),
|
||||
'email' => (string) ($info['email'] ?? ''),
|
||||
|
||||
@@ -8,7 +8,9 @@ use RuntimeException;
|
||||
|
||||
class ReimbursementExportService
|
||||
{
|
||||
public function __construct(private ReimbursementRecipientService $recipients) {}
|
||||
public function __construct(private ReimbursementRecipientService $recipients)
|
||||
{
|
||||
}
|
||||
|
||||
public function buildUnderProcessingCsv(): array
|
||||
{
|
||||
@@ -25,12 +27,12 @@ class ReimbursementExportService
|
||||
|
||||
foreach ($records as $row) {
|
||||
$personId = (int) ($row->purchased_by ?? 0);
|
||||
$name = trim(($row->purchaser_firstname ?? '').' '.($row->purchaser_lastname ?? ''));
|
||||
$name = trim(($row->purchaser_firstname ?? '') . ' ' . ($row->purchaser_lastname ?? ''));
|
||||
if ($name === '') {
|
||||
$name = $row->purchaser_firstname ?? $row->purchaser_lastname ?? 'Unknown';
|
||||
}
|
||||
$key = $personId > 0 ? 'id_'.$personId : 'name_'.strtolower($name);
|
||||
if (! isset($grouped[$key])) {
|
||||
$key = $personId > 0 ? 'id_' . $personId : 'name_' . strtolower($name);
|
||||
if (!isset($grouped[$key])) {
|
||||
$grouped[$key] = [
|
||||
'name' => $name ?: 'Unknown',
|
||||
'total' => 0.0,
|
||||
@@ -43,12 +45,12 @@ class ReimbursementExportService
|
||||
$grouped[$key]['total'] += $amount;
|
||||
|
||||
$vendor = trim((string) ($row->retailor ?? ''));
|
||||
if ($vendor !== '' && ! in_array($vendor, $grouped[$key]['vendors'], true)) {
|
||||
if ($vendor !== '' && !in_array($vendor, $grouped[$key]['vendors'], true)) {
|
||||
$grouped[$key]['vendors'][] = $vendor;
|
||||
}
|
||||
|
||||
$desc = trim((string) ($row->description ?? ''));
|
||||
if ($desc !== '' && ! in_array($desc, $grouped[$key]['descriptions'], true)) {
|
||||
if ($desc !== '' && !in_array($desc, $grouped[$key]['descriptions'], true)) {
|
||||
$grouped[$key]['descriptions'][] = $desc;
|
||||
}
|
||||
}
|
||||
@@ -76,16 +78,16 @@ class ReimbursementExportService
|
||||
->select('reimbursements.*', 'u.firstname as reimb_firstname', 'u.lastname as reimb_lastname')
|
||||
->leftJoin('users as u', 'u.id', '=', 'reimbursements.reimbursed_to');
|
||||
|
||||
if (! empty($filters['semester'])) {
|
||||
if (!empty($filters['semester'])) {
|
||||
$builder->where('reimbursements.semester', $filters['semester']);
|
||||
}
|
||||
if (! empty($filters['status'])) {
|
||||
if (!empty($filters['status'])) {
|
||||
$builder->where('reimbursements.status', $filters['status']);
|
||||
}
|
||||
if (! empty($filters['user_id'])) {
|
||||
if (!empty($filters['user_id'])) {
|
||||
$builder->where('reimbursements.reimbursed_to', $filters['user_id']);
|
||||
}
|
||||
if (! empty($filters['school_year'])) {
|
||||
if (!empty($filters['school_year'])) {
|
||||
$builder->where('reimbursements.school_year', $filters['school_year']);
|
||||
}
|
||||
|
||||
@@ -94,8 +96,8 @@ class ReimbursementExportService
|
||||
$rows[] = ['Amount', 'Reimbursed To', 'Status', 'Method', 'Check #', 'School Year', 'Semester', 'Date'];
|
||||
|
||||
foreach ($records as $row) {
|
||||
$hasName = trim(($row->reimb_firstname ?? '').' '.($row->reimb_lastname ?? '')) !== '';
|
||||
if (! $hasName) {
|
||||
$hasName = trim(($row->reimb_firstname ?? '') . ' ' . ($row->reimb_lastname ?? '')) !== '';
|
||||
if (!$hasName) {
|
||||
$label = $this->recipients->specialRecipientLabel($row->reimbursed_to ?? null);
|
||||
if ($label !== null) {
|
||||
$row->reimb_firstname = $label;
|
||||
@@ -105,7 +107,7 @@ class ReimbursementExportService
|
||||
|
||||
$rows[] = [
|
||||
$row->amount,
|
||||
trim(($row->reimb_firstname ?? '').' '.($row->reimb_lastname ?? '')),
|
||||
trim(($row->reimb_firstname ?? '') . ' ' . ($row->reimb_lastname ?? '')),
|
||||
$row->status,
|
||||
$row->reimbursement_method ?? '-',
|
||||
$row->check_number ?? '-',
|
||||
@@ -124,11 +126,11 @@ class ReimbursementExportService
|
||||
public function buildBatchCsv(int $batchId): array
|
||||
{
|
||||
$batch = ReimbursementBatch::query()->find($batchId);
|
||||
if (! $batch) {
|
||||
if (!$batch) {
|
||||
throw new RuntimeException('Batch not found.');
|
||||
}
|
||||
|
||||
$batchLabel = trim((string) ($batch->title ?? '')) ?: ('Batch #'.$batchId);
|
||||
$batchLabel = trim((string) ($batch->title ?? '')) ?: ('Batch #' . $batchId);
|
||||
$receiptRows = $this->fetchBatchReceiptRows($batchId);
|
||||
|
||||
$rows = [];
|
||||
@@ -149,14 +151,14 @@ class ReimbursementExportService
|
||||
->leftJoin('users as u', 'u.id', '=', 'e.purchased_by')
|
||||
->where('bi.batch_id', $batchId);
|
||||
|
||||
if (! empty($receiptIds)) {
|
||||
if (!empty($receiptIds)) {
|
||||
$builder->whereIn('e.id', $receiptIds);
|
||||
}
|
||||
|
||||
$rows = $builder->get()->toArray();
|
||||
|
||||
return array_values(array_filter($rows, static function ($row) {
|
||||
return ! empty($row->receipt_filename);
|
||||
return !empty($row->receipt_filename);
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -173,7 +175,7 @@ class ReimbursementExportService
|
||||
{
|
||||
$receiptTotalsByRecipient = [];
|
||||
foreach ($receiptRows as $row) {
|
||||
$recipientName = trim(($row->purchaser_firstname ?? '').' '.($row->purchaser_lastname ?? ''));
|
||||
$recipientName = trim(($row->purchaser_firstname ?? '') . ' ' . ($row->purchaser_lastname ?? ''));
|
||||
if ($recipientName === '') {
|
||||
$recipientName = 'Unknown';
|
||||
}
|
||||
@@ -198,7 +200,7 @@ class ReimbursementExportService
|
||||
];
|
||||
}
|
||||
|
||||
if (! empty($receiptTotalsByRecipient)) {
|
||||
if (!empty($receiptTotalsByRecipient)) {
|
||||
$rows[] = [];
|
||||
$rows[] = ['Totals by Recipient', '', '', '', '', '', '', ''];
|
||||
foreach ($receiptTotalsByRecipient as $recipient => $total) {
|
||||
@@ -219,14 +221,13 @@ class ReimbursementExportService
|
||||
|
||||
private function formatCsvDate(?string $value): string
|
||||
{
|
||||
if (! $value) {
|
||||
if (!$value) {
|
||||
return '';
|
||||
}
|
||||
$timestamp = strtotime($value);
|
||||
if ($timestamp === false) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return date('m-d-Y', $timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@ class ReimbursementFileService
|
||||
{
|
||||
public function __construct(
|
||||
private ApplicationUrlService $urls
|
||||
) {}
|
||||
) {
|
||||
}
|
||||
|
||||
public function receiptUrl(?string $filename): ?string
|
||||
{
|
||||
@@ -31,7 +32,7 @@ class ReimbursementFileService
|
||||
|
||||
public function storeReceipt(?UploadedFile $file): ?string
|
||||
{
|
||||
if (! $file || ! $file->isValid()) {
|
||||
if (!$file || !$file->isValid()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -41,10 +42,10 @@ class ReimbursementFileService
|
||||
|
||||
$dir = $this->ensureUploadDir();
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$extension = $extension !== '' ? '.'.strtolower($extension) : '';
|
||||
$filename = 'reimb_'.date('Ymd_His').'_'.Str::random(8).$extension;
|
||||
$extension = $extension !== '' ? '.' . strtolower($extension) : '';
|
||||
$filename = 'reimb_' . date('Ymd_His') . '_' . Str::random(8) . $extension;
|
||||
|
||||
if (! $file->move($dir, $filename)) {
|
||||
if (!$file->move($dir, $filename)) {
|
||||
throw new RuntimeException('Unable to save uploaded file.');
|
||||
}
|
||||
|
||||
@@ -55,10 +56,10 @@ class ReimbursementFileService
|
||||
{
|
||||
$dir = $this->ensureUploadDir();
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$extension = $extension !== '' ? '.'.strtolower($extension) : '';
|
||||
$filename = 'batch_check_'.date('Ymd_His').'_'.Str::random(8).$extension;
|
||||
$extension = $extension !== '' ? '.' . strtolower($extension) : '';
|
||||
$filename = 'batch_check_' . date('Ymd_His') . '_' . Str::random(8) . $extension;
|
||||
|
||||
if (! $file->move($dir, $filename)) {
|
||||
if (!$file->move($dir, $filename)) {
|
||||
throw new RuntimeException('Unable to save uploaded file.');
|
||||
}
|
||||
|
||||
@@ -67,8 +68,8 @@ class ReimbursementFileService
|
||||
->where('admin_id', $adminId)
|
||||
->first();
|
||||
|
||||
if ($existing && ! empty($existing->filename)) {
|
||||
$oldPath = $dir.DIRECTORY_SEPARATOR.$existing->filename;
|
||||
if ($existing && !empty($existing->filename)) {
|
||||
$oldPath = $dir . DIRECTORY_SEPARATOR . $existing->filename;
|
||||
if (is_file($oldPath)) {
|
||||
@unlink($oldPath);
|
||||
}
|
||||
@@ -101,13 +102,13 @@ class ReimbursementFileService
|
||||
{
|
||||
$dir = storage_path('uploads/reimbursements');
|
||||
|
||||
if (! is_dir($dir)) {
|
||||
if (! @mkdir($dir, 0755, true) && ! is_dir($dir)) {
|
||||
if (!is_dir($dir)) {
|
||||
if (!@mkdir($dir, 0755, true) && !is_dir($dir)) {
|
||||
throw new RuntimeException('Upload directory is not available.');
|
||||
}
|
||||
}
|
||||
|
||||
if (! is_writable($dir)) {
|
||||
if (!is_writable($dir)) {
|
||||
throw new RuntimeException('Upload directory is not writable.');
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,8 @@ class ReimbursementQueryService
|
||||
public function __construct(
|
||||
private ReimbursementRecipientService $recipients,
|
||||
private ReimbursementFileService $files
|
||||
) {}
|
||||
) {
|
||||
}
|
||||
|
||||
public function underProcessing(): array
|
||||
{
|
||||
@@ -44,7 +45,7 @@ class ReimbursementQueryService
|
||||
}
|
||||
|
||||
$receiptUrl = $this->files->expenseReceiptUrl($row->expense_receipt ?? null);
|
||||
$fullName = trim(($row->purchaser_firstname ?? '').' '.($row->purchaser_lastname ?? '')) ?: 'Unknown';
|
||||
$fullName = trim(($row->purchaser_firstname ?? '') . ' ' . ($row->purchaser_lastname ?? '')) ?: 'Unknown';
|
||||
|
||||
$item = [
|
||||
'id' => $expenseId,
|
||||
@@ -95,16 +96,16 @@ class ReimbursementQueryService
|
||||
}
|
||||
|
||||
$receiptUrl = $this->files->expenseReceiptUrl($row->expense_receipt ?? null);
|
||||
$purchaser = trim(($row->purchaser_firstname ?? '').' '.($row->purchaser_lastname ?? '')) ?: 'Unknown';
|
||||
$purchaser = trim(($row->purchaser_firstname ?? '') . ' ' . ($row->purchaser_lastname ?? '')) ?: 'Unknown';
|
||||
$yearlyNumber = (int) ($row->batch_year_number ?? 0);
|
||||
$batchLabel = trim((string) ($row->batch_title ?? ''));
|
||||
if ($batchLabel === '') {
|
||||
$fallbackNumber = $yearlyNumber > 0 ? $yearlyNumber : $batchId;
|
||||
$batchLabel = 'Batch #'.$fallbackNumber;
|
||||
$batchLabel = 'Batch #' . $fallbackNumber;
|
||||
}
|
||||
$adminId = $row->admin_id ? (int) $row->admin_id : 0;
|
||||
$adminName = $adminId > 0
|
||||
? (trim(($row->admin_firstname ?? '').' '.($row->admin_lastname ?? '')) ?: 'Admin')
|
||||
? (trim(($row->admin_firstname ?? '') . ' ' . ($row->admin_lastname ?? '')) ?: 'Admin')
|
||||
: 'Unassigned';
|
||||
$batchStatus = strtolower(trim((string) ($row->batch_status ?? ''))) ?: 'open';
|
||||
|
||||
@@ -126,7 +127,7 @@ class ReimbursementQueryService
|
||||
|
||||
$itemsMap[$expenseId] = $item;
|
||||
|
||||
if (! isset($batchStructures[$batchId])) {
|
||||
if (!isset($batchStructures[$batchId])) {
|
||||
$batchStructures[$batchId] = [
|
||||
'batchId' => $batchId,
|
||||
'label' => $batchLabel,
|
||||
@@ -142,7 +143,7 @@ class ReimbursementQueryService
|
||||
}
|
||||
|
||||
$slotKey = $adminId ?: 0;
|
||||
if (! isset($batchStructures[$batchId]['slots'][$slotKey])) {
|
||||
if (!isset($batchStructures[$batchId]['slots'][$slotKey])) {
|
||||
$batchStructures[$batchId]['slots'][$slotKey] = [
|
||||
'admin_id' => $adminId ?: 0,
|
||||
'admin_name' => $adminId > 0 ? $adminName : 'Unassigned',
|
||||
@@ -154,7 +155,7 @@ class ReimbursementQueryService
|
||||
}
|
||||
|
||||
$adminFileMap = [];
|
||||
if (! empty($batchStructures)) {
|
||||
if (!empty($batchStructures)) {
|
||||
$batchIds = array_keys($batchStructures);
|
||||
$files = ReimbursementBatchAdminFile::query()
|
||||
->select('batch_id', 'admin_id', 'filename', 'original_filename')
|
||||
@@ -187,7 +188,6 @@ class ReimbursementQueryService
|
||||
$existingBatches = array_map(static function (array $batch) {
|
||||
$normalizedSlots = array_map(static function (array $slot) {
|
||||
$slot['items'] = array_values(array_map('intval', $slot['items']));
|
||||
|
||||
return $slot;
|
||||
}, array_values($batch['slots']));
|
||||
|
||||
@@ -238,13 +238,13 @@ class ReimbursementQueryService
|
||||
->where('b.status', 'closed')
|
||||
->whereNull('bi.unassigned_at');
|
||||
|
||||
if (! empty($filters['school_year'])) {
|
||||
if (!empty($filters['school_year'])) {
|
||||
$batchQuery->where(function ($q) use ($filters) {
|
||||
$q->where('b.school_year', $filters['school_year'])
|
||||
->orWhere('e.school_year', $filters['school_year']);
|
||||
});
|
||||
}
|
||||
if (! empty($filters['user_id'])) {
|
||||
if (!empty($filters['user_id'])) {
|
||||
$batchQuery->where('e.purchased_by', $filters['user_id']);
|
||||
}
|
||||
|
||||
@@ -255,10 +255,10 @@ class ReimbursementQueryService
|
||||
continue;
|
||||
}
|
||||
$labelNumber = (int) ($row->yearly_batch_number ?? $bid);
|
||||
if (! isset($batchSummaries[$bid])) {
|
||||
if (!isset($batchSummaries[$bid])) {
|
||||
$batchSummaries[$bid] = [
|
||||
'batch_id' => $bid,
|
||||
'title' => trim((string) ($row->batch_title ?? '')) ?: ('Batch #'.$labelNumber),
|
||||
'title' => trim((string) ($row->batch_title ?? '')) ?: ('Batch #' . $labelNumber),
|
||||
'sequence' => $labelNumber,
|
||||
'closed_at' => $row->closed_at ?? null,
|
||||
'amount' => 0.0,
|
||||
@@ -269,7 +269,7 @@ class ReimbursementQueryService
|
||||
$batchSummaries[$bid]['amount'] += (float) $amount;
|
||||
$batchSummaries[$bid]['items'] += 1;
|
||||
|
||||
if (! isset($batchDetails[$bid])) {
|
||||
if (!isset($batchDetails[$bid])) {
|
||||
$batchDetails[$bid] = [
|
||||
'title' => $batchSummaries[$bid]['title'],
|
||||
'sequence' => $labelNumber,
|
||||
@@ -278,7 +278,7 @@ class ReimbursementQueryService
|
||||
'checks' => [],
|
||||
];
|
||||
}
|
||||
if (! isset($batchAttachments[$bid])) {
|
||||
if (!isset($batchAttachments[$bid])) {
|
||||
$batchAttachments[$bid] = [
|
||||
'receipts' => [],
|
||||
'checks' => [],
|
||||
@@ -289,7 +289,7 @@ class ReimbursementQueryService
|
||||
'amount' => (float) $amount,
|
||||
'description' => $row->description ?? '',
|
||||
'vendor' => $row->retailor ?? '',
|
||||
'purchased_by' => trim(($row->purchaser_firstname ?? '').' '.($row->purchaser_lastname ?? '')),
|
||||
'purchased_by' => trim(($row->purchaser_firstname ?? '') . ' ' . ($row->purchaser_lastname ?? '')),
|
||||
'receipt_url' => $this->files->expenseReceiptUrl($row->expense_receipt ?? null),
|
||||
];
|
||||
|
||||
@@ -309,7 +309,7 @@ class ReimbursementQueryService
|
||||
}
|
||||
}
|
||||
|
||||
if (! empty($batchSummaries)) {
|
||||
if (!empty($batchSummaries)) {
|
||||
$batchIds = array_keys($batchSummaries);
|
||||
$files = ReimbursementBatchAdminFile::query()
|
||||
->select('id as file_id', 'batch_id', 'admin_id', 'filename', 'original_filename', 'uploaded_at')
|
||||
@@ -319,22 +319,22 @@ class ReimbursementQueryService
|
||||
$adminNames = $this->recipients->adminRoster();
|
||||
$adminNameMap = [];
|
||||
foreach ($adminNames as $admin) {
|
||||
$adminNameMap[(int) $admin['id']] = trim(($admin['firstname'] ?? '').' '.($admin['lastname'] ?? ''));
|
||||
$adminNameMap[(int) $admin['id']] = trim(($admin['firstname'] ?? '') . ' ' . ($admin['lastname'] ?? ''));
|
||||
}
|
||||
|
||||
foreach ($files as $file) {
|
||||
$bid = (int) ($file->batch_id ?? 0);
|
||||
if ($bid <= 0 || ! isset($batchDetails[$bid])) {
|
||||
if ($bid <= 0 || !isset($batchDetails[$bid])) {
|
||||
continue;
|
||||
}
|
||||
$aid = (int) ($file->admin_id ?? 0);
|
||||
$batchDetails[$bid]['checks'][] = [
|
||||
'admin' => $adminNameMap[$aid] ?? ($aid > 0 ? 'Admin #'.$aid : 'Unassigned'),
|
||||
'admin' => $adminNameMap[$aid] ?? ($aid > 0 ? 'Admin #' . $aid : 'Unassigned'),
|
||||
'filename' => $file->filename,
|
||||
'original' => $file->original_filename ?? $file->filename,
|
||||
'url' => $this->files->adminFileUrl($file->filename ?? '', 'inline'),
|
||||
];
|
||||
if (! isset($batchAttachments[$bid])) {
|
||||
if (!isset($batchAttachments[$bid])) {
|
||||
$batchAttachments[$bid] = [
|
||||
'receipts' => [],
|
||||
'checks' => [],
|
||||
@@ -344,19 +344,18 @@ class ReimbursementQueryService
|
||||
'file_id' => (int) ($file->file_id ?? 0),
|
||||
'filename' => $file->filename,
|
||||
'original_filename' => $file->original_filename ?? $file->filename,
|
||||
'admin' => $adminNameMap[$aid] ?? ($aid > 0 ? 'Admin #'.$aid : 'Unassigned'),
|
||||
'admin' => $adminNameMap[$aid] ?? ($aid > 0 ? 'Admin #' . $aid : 'Unassigned'),
|
||||
'url' => $this->files->adminFileUrl($file->filename ?? '', 'inline'),
|
||||
'uploaded_at' => $file->uploaded_at ?? null,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (! empty($batchSummaries)) {
|
||||
if (!empty($batchSummaries)) {
|
||||
$batchSummaries = array_values($batchSummaries);
|
||||
usort($batchSummaries, static function ($a, $b) {
|
||||
$aSeq = (int) ($a['sequence'] ?? 0);
|
||||
$bSeq = (int) ($b['sequence'] ?? 0);
|
||||
|
||||
return $bSeq <=> $aSeq;
|
||||
});
|
||||
}
|
||||
@@ -372,16 +371,16 @@ class ReimbursementQueryService
|
||||
->leftJoin('users as u', 'u.id', '=', 'e.purchased_by')
|
||||
->where('e.category', 'Donation');
|
||||
|
||||
if (! empty($filters['school_year'])) {
|
||||
if (!empty($filters['school_year'])) {
|
||||
$donationQuery->where('e.school_year', $filters['school_year']);
|
||||
}
|
||||
if (! empty($filters['semester'])) {
|
||||
if (!empty($filters['semester'])) {
|
||||
$donationQuery->where('e.semester', $filters['semester']);
|
||||
}
|
||||
if (! empty($filters['user_id'])) {
|
||||
if (!empty($filters['user_id'])) {
|
||||
$donationQuery->where('e.purchased_by', $filters['user_id']);
|
||||
}
|
||||
if (! empty($filters['status'])) {
|
||||
if (!empty($filters['status'])) {
|
||||
$donationQuery->where(function ($q) use ($filters) {
|
||||
$q->where('e.status', $filters['status'])
|
||||
->orWhere('e.status', strtolower((string) $filters['status']))
|
||||
@@ -395,7 +394,7 @@ class ReimbursementQueryService
|
||||
foreach ($donationRows as $row) {
|
||||
$amount = (float) ($row->expense_amount ?? 0);
|
||||
$donationTotal += $amount;
|
||||
$purchaser = trim(($row->purchaser_firstname ?? '').' '.($row->purchaser_lastname ?? ''));
|
||||
$purchaser = trim(($row->purchaser_firstname ?? '') . ' ' . ($row->purchaser_lastname ?? ''));
|
||||
if ($purchaser === '') {
|
||||
$purchaser = 'Unknown';
|
||||
}
|
||||
@@ -429,8 +428,8 @@ class ReimbursementQueryService
|
||||
}
|
||||
|
||||
$recipientId = $e['reimb_recipient_id'] ?? ($e['reimbursed_to'] ?? null);
|
||||
$hasName = trim(($e['reimb_firstname'] ?? '').' '.($e['reimb_lastname'] ?? '')) !== '';
|
||||
if (! $hasName) {
|
||||
$hasName = trim(($e['reimb_firstname'] ?? '') . ' ' . ($e['reimb_lastname'] ?? '')) !== '';
|
||||
if (!$hasName) {
|
||||
$label = $this->recipients->specialRecipientLabel($recipientId);
|
||||
if ($label !== null) {
|
||||
$e['reimb_firstname'] = $label;
|
||||
|
||||
@@ -29,7 +29,7 @@ class ReimbursementRecipientService
|
||||
if ($id <= 0 || in_array($roleName, $excludedRoles, true)) {
|
||||
continue;
|
||||
}
|
||||
if (! isset($staff[$id])) {
|
||||
if (!isset($staff[$id])) {
|
||||
$staff[$id] = [
|
||||
'id' => $id,
|
||||
'firstname' => $row->firstname ?? '',
|
||||
@@ -39,9 +39,8 @@ class ReimbursementRecipientService
|
||||
}
|
||||
|
||||
uasort($staff, static function (array $a, array $b) {
|
||||
$nameA = trim(($a['firstname'] ?? '').' '.($a['lastname'] ?? ''));
|
||||
$nameB = trim(($b['firstname'] ?? '').' '.($b['lastname'] ?? ''));
|
||||
|
||||
$nameA = trim(($a['firstname'] ?? '') . ' ' . ($a['lastname'] ?? ''));
|
||||
$nameB = trim(($b['firstname'] ?? '') . ' ' . ($b['lastname'] ?? ''));
|
||||
return strcasecmp($nameA, $nameB);
|
||||
});
|
||||
|
||||
@@ -56,7 +55,7 @@ class ReimbursementRecipientService
|
||||
public function adminRoster(): array
|
||||
{
|
||||
$admins = $this->staffUsers();
|
||||
if (! empty($admins)) {
|
||||
if (!empty($admins)) {
|
||||
return $admins;
|
||||
}
|
||||
|
||||
@@ -65,12 +64,11 @@ class ReimbursementRecipientService
|
||||
|
||||
public function specialRecipientLabel($value): ?string
|
||||
{
|
||||
if ($value === null || ! is_numeric($value)) {
|
||||
if ($value === null || !is_numeric($value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$id = (int) $value;
|
||||
|
||||
return self::SPECIAL_RECIPIENTS[$id] ?? null;
|
||||
}
|
||||
|
||||
@@ -81,7 +79,7 @@ class ReimbursementRecipientService
|
||||
}, $users);
|
||||
|
||||
foreach (self::SPECIAL_RECIPIENTS as $id => $label) {
|
||||
if (! in_array($id, $existingIds, true)) {
|
||||
if (!in_array($id, $existingIds, true)) {
|
||||
$users[] = [
|
||||
'id' => $id,
|
||||
'firstname' => $label,
|
||||
|
||||
Reference in New Issue
Block a user