add more controller
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Reports;
|
||||
|
||||
use App\Models\Configuration;
|
||||
use App\Models\User;
|
||||
|
||||
class SlipPrinterConfigService
|
||||
{
|
||||
public function context(): array
|
||||
{
|
||||
return [
|
||||
'school_year' => Configuration::getConfig('school_year'),
|
||||
'semester' => Configuration::getConfig('semester'),
|
||||
];
|
||||
}
|
||||
|
||||
public function currentAdminName(?int $userId): string
|
||||
{
|
||||
if ($userId && $userId > 0) {
|
||||
$user = User::query()->select('firstname', 'lastname')->find($userId);
|
||||
if ($user) {
|
||||
$full = trim(($user->firstname ?? '') . ' ' . ($user->lastname ?? ''));
|
||||
if ($full !== '') {
|
||||
return $full;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function printerConfig(): array
|
||||
{
|
||||
$get = function ($keys, $default = null) {
|
||||
$keys = is_array($keys) ? $keys : [$keys];
|
||||
foreach ($keys as $key) {
|
||||
$val = env($key);
|
||||
if ($val !== null && $val !== '') {
|
||||
return $val;
|
||||
}
|
||||
}
|
||||
return $default;
|
||||
};
|
||||
|
||||
return [
|
||||
'chars_per_line' => (int) $get(['printer.chars_per_line', 'PRINTER_CHARS_PER_LINE'], 48),
|
||||
'feed_lines' => (int) $get(['printer.feed_lines', 'PRINTER_FEED_LINES'], 3),
|
||||
'paper' => (string) $get(['printer.paper', 'SLIP_PAPER'], 'card'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Reports;
|
||||
|
||||
class SlipPrinterFormatterService
|
||||
{
|
||||
public function toDbDate(?string $value): ?string
|
||||
{
|
||||
$value = trim((string) $value);
|
||||
if ($value === '') {
|
||||
return null;
|
||||
}
|
||||
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $value)) {
|
||||
return $value;
|
||||
}
|
||||
if (preg_match('/^\d{1,2}\/\d{1,2}\/\d{4}$/', $value)) {
|
||||
$dt = \DateTime::createFromFormat('!m/d/Y', $value);
|
||||
return $dt ? $dt->format('Y-m-d') : null;
|
||||
}
|
||||
if (preg_match('/^\d{1,2}-\d{1,2}-\d{4}$/', $value)) {
|
||||
$dt = \DateTime::createFromFormat('!m-d-Y', $value);
|
||||
return $dt ? $dt->format('Y-m-d') : null;
|
||||
}
|
||||
$ts = strtotime($value);
|
||||
return $ts ? date('Y-m-d', $ts) : null;
|
||||
}
|
||||
|
||||
public function toDbTime(?string $value): ?string
|
||||
{
|
||||
$value = trim((string) $value);
|
||||
if ($value === '') {
|
||||
return null;
|
||||
}
|
||||
$ts = strtotime($value);
|
||||
return $ts ? date('H:i:s', $ts) : null;
|
||||
}
|
||||
|
||||
public function formatDisplayDate(?string $value): string
|
||||
{
|
||||
$value = trim((string) $value);
|
||||
if ($value === '' || $value === '0000-00-00') {
|
||||
return '';
|
||||
}
|
||||
$ts = strtotime($value);
|
||||
return $ts ? date('m/d/Y', $ts) : '';
|
||||
}
|
||||
|
||||
public function formatDisplayTime(?string $value): string
|
||||
{
|
||||
$value = trim((string) $value);
|
||||
if ($value === '') {
|
||||
return '';
|
||||
}
|
||||
$ts = strtotime($value);
|
||||
if ($ts === false) {
|
||||
$ts = strtotime('today ' . $value);
|
||||
}
|
||||
return $ts ? date('h:i A', $ts) : '';
|
||||
}
|
||||
|
||||
public function fitLine(string $line, int $width): string
|
||||
{
|
||||
$line = (string) $line;
|
||||
if (strlen($line) > $width) {
|
||||
return substr($line, 0, $width);
|
||||
}
|
||||
return $line . str_repeat(' ', $width - strlen($line));
|
||||
}
|
||||
|
||||
public function buildSlipLines(array $data, int $width): array
|
||||
{
|
||||
$lines = [];
|
||||
$lines[] = $this->fitLine('Student Name: ' . (string) ($data['student_name'] ?? ''), $width);
|
||||
$lines[] = $this->fitLine('Date: ' . (string) ($data['date'] ?? '') . ' Time In: ' . (string) ($data['time_in'] ?? ''), $width);
|
||||
$lines[] = $this->fitLine('Grade: ' . (string) ($data['grade'] ?? ''), $width);
|
||||
$lines[] = $this->fitLine('Reason: ' . (string) ($data['reason'] ?? ''), $width);
|
||||
$lines[] = $this->fitLine('Admin: ' . (string) ($data['admin_name'] ?? ''), $width);
|
||||
return $lines;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Reports;
|
||||
|
||||
use Dompdf\Dompdf;
|
||||
use Dompdf\Options;
|
||||
|
||||
class SlipPrinterPdfService
|
||||
{
|
||||
public function __construct(private SlipPrinterConfigService $configService)
|
||||
{
|
||||
}
|
||||
|
||||
public function render(array $data, array $lines, array $options = []): array
|
||||
{
|
||||
$paper = strtolower((string) ($options['paper'] ?? $this->configService->printerConfig()['paper'] ?? 'card'));
|
||||
$fontPt = (float) ($options['font_pt'] ?? env('SLIP_FONT_PT', 13.0));
|
||||
$lineH = (float) ($options['line_h'] ?? env('SLIP_LINE_H', 2.0));
|
||||
$linesCount = (int) ($options['rows'] ?? count($lines));
|
||||
if ($linesCount < 1) {
|
||||
$linesCount = count($lines);
|
||||
}
|
||||
|
||||
$ptPerLine = $fontPt * $lineH;
|
||||
$mmPerPt = 25.4 / 72.0;
|
||||
$contentMm = $ptPerLine * $linesCount * $mmPerPt;
|
||||
$pageMarginsMm = 6.0;
|
||||
$fudgeMm = (float) ($options['fudge_mm'] ?? env('SLIP_FUDGE_MM', 12.0));
|
||||
$dynHeightMm = $contentMm + $pageMarginsMm + $fudgeMm;
|
||||
|
||||
switch ($paper) {
|
||||
case 'cardp':
|
||||
case 'card-portrait':
|
||||
$wMm = 53.98;
|
||||
$hMm = max($dynHeightMm, 40.0);
|
||||
break;
|
||||
case 'receipt80':
|
||||
$wMm = 72.0;
|
||||
$hMm = 90.0;
|
||||
break;
|
||||
case 'receipt58':
|
||||
$wMm = 58.0;
|
||||
$hMm = 80.0;
|
||||
break;
|
||||
case 'card':
|
||||
default:
|
||||
$wMm = 85.60;
|
||||
$hMm = max($dynHeightMm, 40.0);
|
||||
}
|
||||
|
||||
$hOverride = $options['height_mm'] ?? $options['h'] ?? null;
|
||||
if (is_numeric($hOverride)) {
|
||||
$hMm = max(30.0, min(200.0, (float) $hOverride));
|
||||
}
|
||||
|
||||
if ($hMm < $dynHeightMm) {
|
||||
$hMm = $dynHeightMm;
|
||||
}
|
||||
|
||||
$html = view('slips/slip_pdf', [
|
||||
'entry' => $data,
|
||||
'lines' => $lines,
|
||||
'page' => ['w_mm' => $wMm, 'h_mm' => $hMm],
|
||||
]);
|
||||
|
||||
$optionsObj = new Options();
|
||||
$optionsObj->set('isRemoteEnabled', true);
|
||||
$optionsObj->set('defaultFont', 'Courier');
|
||||
|
||||
$dompdf = new Dompdf($optionsObj);
|
||||
$dompdf->loadHtml($html, 'UTF-8');
|
||||
|
||||
$mmToPt = 72 / 25.4;
|
||||
$wPt = $wMm * $mmToPt;
|
||||
$hPt = $hMm * $mmToPt;
|
||||
$dompdf->setPaper([0, 0, $wPt, $hPt]);
|
||||
$dompdf->render();
|
||||
|
||||
$filename = 'LateSlip_' . preg_replace('/[^A-Za-z0-9]+/', '_', (string) ($data['student_name'] ?? 'slip')) . '_' . date('Ymd_His') . '.pdf';
|
||||
|
||||
return [
|
||||
'content' => $dompdf->output(),
|
||||
'filename' => $filename,
|
||||
'width_mm' => $wMm,
|
||||
'height_mm' => $hMm,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Reports;
|
||||
|
||||
use App\Models\LateSlipLog;
|
||||
|
||||
class SlipPrinterService
|
||||
{
|
||||
public function __construct(
|
||||
private SlipPrinterConfigService $configService,
|
||||
private SlipPrinterFormatterService $formatter,
|
||||
private SlipPrinterPdfService $pdfService
|
||||
) {
|
||||
}
|
||||
|
||||
public function print(array $input, ?int $userId): array
|
||||
{
|
||||
$data = $this->buildData($input, $userId);
|
||||
if ($data['student_name'] === '') {
|
||||
return ['ok' => false, 'message' => 'Student name is required.'];
|
||||
}
|
||||
|
||||
$this->logSlip($data, $userId);
|
||||
|
||||
$lines = $this->formatter->buildSlipLines($data, $this->lineWidth());
|
||||
$pdf = $this->pdfService->render($data, $lines, $this->paperOptions($input));
|
||||
|
||||
return [
|
||||
'ok' => true,
|
||||
'data' => $data,
|
||||
'pdf' => $pdf['content'],
|
||||
'filename' => $pdf['filename'],
|
||||
];
|
||||
}
|
||||
|
||||
public function preview(array $input, ?int $userId): array
|
||||
{
|
||||
$data = $this->buildData($input, $userId);
|
||||
$width = $this->lineWidth();
|
||||
$feedLines = $this->configService->printerConfig()['feed_lines'] ?? 3;
|
||||
|
||||
$header = "Al Rahma School at ISGL\nSchool Year: {$data['school_year']}\n\n";
|
||||
$body = implode("\n", $this->formatter->buildSlipLines($data, $width));
|
||||
$footer = str_repeat("\n", (int) $feedLines);
|
||||
|
||||
return [
|
||||
'ok' => true,
|
||||
'text' => $header . $body . $footer,
|
||||
'width' => $width,
|
||||
];
|
||||
}
|
||||
|
||||
public function logs(?string $schoolYear = null, ?string $semester = null): array
|
||||
{
|
||||
$query = LateSlipLog::query();
|
||||
if ($schoolYear !== null && trim($schoolYear) !== '') {
|
||||
$query->where('school_year', trim($schoolYear));
|
||||
}
|
||||
|
||||
$semester = strtolower(trim((string) $semester));
|
||||
if ($semester !== '') {
|
||||
if ($semester === 'fall') {
|
||||
$query->whereIn('semester', ['fall', '1', 1]);
|
||||
} elseif ($semester === 'spring') {
|
||||
$query->whereIn('semester', ['spring', '2', 2]);
|
||||
}
|
||||
}
|
||||
|
||||
$rows = $query->orderByDesc('id')->limit(50)->get()->toArray();
|
||||
|
||||
$out = [];
|
||||
foreach ($rows as $row) {
|
||||
$dispDate = $this->formatter->formatDisplayDate($row['slip_date'] ?? '');
|
||||
if ($dispDate === '') {
|
||||
$dispDate = $this->formatter->formatDisplayDate($row['printed_at'] ?? '');
|
||||
}
|
||||
|
||||
$dispTime = $this->formatter->formatDisplayTime($row['time_in'] ?? '');
|
||||
|
||||
$out[] = [
|
||||
'id' => (int) ($row['id'] ?? 0),
|
||||
'school_year' => (string) ($row['school_year'] ?? ''),
|
||||
'semester' => (string) ($row['semester'] ?? ''),
|
||||
'student_name' => (string) ($row['student_name'] ?? ''),
|
||||
'date' => $dispDate,
|
||||
'time_in' => $dispTime,
|
||||
'grade' => (string) ($row['grade'] ?? ''),
|
||||
'reason' => (string) ($row['reason'] ?? ''),
|
||||
'admin_name' => (string) ($row['admin_name'] ?? ''),
|
||||
'printed_at' => (string) ($row['printed_at'] ?? ''),
|
||||
];
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
public function reprint(int $id, ?int $userId): array
|
||||
{
|
||||
$row = LateSlipLog::query()->find($id);
|
||||
if (!$row) {
|
||||
return ['ok' => false, 'message' => 'Slip not found.'];
|
||||
}
|
||||
|
||||
$data = [
|
||||
'school_year' => (string) ($row->school_year ?? ''),
|
||||
'student_name' => (string) ($row->student_name ?? ''),
|
||||
'date' => $this->formatter->formatDisplayDate($row->slip_date ?? '') ?: date('m/d/Y'),
|
||||
'time_in' => $this->formatter->formatDisplayTime($row->time_in ?? '') ?: date('h:i A'),
|
||||
'grade' => (string) ($row->grade ?? ''),
|
||||
'reason' => (string) ($row->reason ?? ''),
|
||||
'admin_name' => (string) ($row->admin_name ?? ''),
|
||||
];
|
||||
|
||||
$adminFromDb = $this->configService->currentAdminName($userId);
|
||||
if ($adminFromDb !== '') {
|
||||
$data['admin_name'] = $adminFromDb;
|
||||
}
|
||||
|
||||
$lines = $this->formatter->buildSlipLines($data, $this->lineWidth());
|
||||
$pdf = $this->pdfService->render($data, $lines, []);
|
||||
|
||||
$this->logSlip($data, $userId);
|
||||
|
||||
return [
|
||||
'ok' => true,
|
||||
'data' => $data,
|
||||
'pdf' => $pdf['content'],
|
||||
'filename' => $pdf['filename'],
|
||||
];
|
||||
}
|
||||
|
||||
private function buildData(array $input, ?int $userId): array
|
||||
{
|
||||
$context = $this->configService->context();
|
||||
$schoolYear = trim((string) ($input['school_year'] ?? $context['school_year'] ?? ''));
|
||||
|
||||
$data = [
|
||||
'school_year' => $schoolYear,
|
||||
'student_name' => trim((string) ($input['student_name'] ?? '')),
|
||||
'date' => trim((string) ($input['date'] ?? date('m/d/Y'))),
|
||||
'time_in' => trim((string) ($input['time_in'] ?? date('h:i A'))),
|
||||
'grade' => trim((string) ($input['grade'] ?? '')),
|
||||
'reason' => trim((string) ($input['reason'] ?? '')),
|
||||
'admin_name' => trim((string) ($input['admin_name'] ?? '')),
|
||||
];
|
||||
|
||||
$adminFromDb = $this->configService->currentAdminName($userId);
|
||||
if ($adminFromDb !== '') {
|
||||
$data['admin_name'] = $adminFromDb;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function logSlip(array $data, ?int $userId): void
|
||||
{
|
||||
$context = $this->configService->context();
|
||||
$logData = [
|
||||
'school_year' => $data['school_year'],
|
||||
'semester' => (string) ($context['semester'] ?? ''),
|
||||
'student_name' => $data['student_name'],
|
||||
'slip_date' => $this->formatter->toDbDate($data['date']),
|
||||
'time_in' => $this->formatter->toDbTime($data['time_in']),
|
||||
'grade' => $data['grade'],
|
||||
'reason' => $data['reason'],
|
||||
'admin_name' => $data['admin_name'],
|
||||
];
|
||||
|
||||
LateSlipLog::logSlip($logData, $userId);
|
||||
}
|
||||
|
||||
private function lineWidth(): int
|
||||
{
|
||||
$cfg = $this->configService->printerConfig();
|
||||
$width = (int) ($cfg['chars_per_line'] ?? 48);
|
||||
return $width > 0 ? $width : 48;
|
||||
}
|
||||
|
||||
private function paperOptions(array $input): array
|
||||
{
|
||||
return [
|
||||
'paper' => $input['paper'] ?? null,
|
||||
'font_pt' => $input['font_pt'] ?? null,
|
||||
'line_h' => $input['line_h'] ?? null,
|
||||
'rows' => $input['rows'] ?? null,
|
||||
'height_mm' => $input['height_mm'] ?? null,
|
||||
'h' => $input['h'] ?? null,
|
||||
'fudge_mm' => $input['fudge_mm'] ?? null,
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user