202 lines
6.6 KiB
PHP
202 lines
6.6 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\HR\Employee;
|
|
use App\Models\Tenants\Tenant;
|
|
use App\Models\Tenants\TenantSetting;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class AppointmentCertService
|
|
{
|
|
private ?string $koreanFontName = null;
|
|
|
|
public function __construct()
|
|
{
|
|
if (! defined('K_PATH_FONTS')) {
|
|
$tcpdfFontsDir = dirname(__DIR__, 2).'/storage/fonts/tcpdf/';
|
|
if (is_dir($tcpdfFontsDir)) {
|
|
define('K_PATH_FONTS', $tcpdfFontsDir);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 사원의 위촉증명서 정보 조회
|
|
*/
|
|
public function getCertInfo(int $userId, int $tenantId): array
|
|
{
|
|
$employee = Employee::withoutGlobalScopes()
|
|
->where('tenant_id', $tenantId)
|
|
->where('user_id', $userId)
|
|
->with(['user', 'department'])
|
|
->firstOrFail();
|
|
|
|
$tenant = Tenant::findOrFail($tenantId);
|
|
|
|
$displaySetting = TenantSetting::withoutGlobalScopes()
|
|
->where('tenant_id', $tenantId)
|
|
->where('setting_group', 'company')
|
|
->where('setting_key', 'display_company_name')
|
|
->first();
|
|
$displayName = $displaySetting?->setting_value ?? '';
|
|
$companyName = ! empty($displayName) ? $displayName : ($tenant->company_name ?? '');
|
|
|
|
$residentNumber = $employee->resident_number ?? '';
|
|
|
|
return [
|
|
'name' => $employee->user->name ?? $employee->display_name ?? '',
|
|
'resident_number' => $residentNumber,
|
|
'department' => $employee->department?->name ?? '',
|
|
'phone' => $employee->user->phone ?? '',
|
|
'hire_date' => $employee->hire_date ?? '',
|
|
'resign_date' => $employee->resign_date ?? '',
|
|
'contract_type' => '',
|
|
'company_name' => $companyName,
|
|
'ceo_name' => $tenant->ceo_name ?? '',
|
|
];
|
|
}
|
|
|
|
/**
|
|
* content JSON 기반 PDF Response 생성
|
|
*/
|
|
public function generatePdfResponse(array $content): \Illuminate\Http\Response
|
|
{
|
|
$pdf = new \TCPDF('P', 'mm', 'A4', true, 'UTF-8', false);
|
|
$pdf->SetCreator('SAM');
|
|
$pdf->SetAuthor($content['company_name'] ?? 'SAM');
|
|
$pdf->SetTitle('위촉증명서');
|
|
|
|
$pdf->setPrintHeader(false);
|
|
$pdf->setPrintFooter(false);
|
|
$pdf->SetMargins(20, 20, 20);
|
|
$pdf->SetAutoPageBreak(true, 20);
|
|
|
|
$font = $this->getKoreanFont();
|
|
|
|
$pdf->AddPage();
|
|
|
|
// 상단 여백
|
|
$pdf->Ln(10);
|
|
|
|
// 제목
|
|
$pdf->SetFont($font, 'B', 22);
|
|
$pdf->Cell(0, 20, '위 촉 증 명 서', 0, 1, 'C');
|
|
$pdf->Ln(14);
|
|
|
|
$pageWidth = $pdf->getPageWidth() - 40;
|
|
$thWidth = 30;
|
|
$rowHeight = 12;
|
|
|
|
// 성명 / (빈칸)
|
|
$this->addTableRow($pdf, $font, [
|
|
['성 명', $content['name'] ?? '-', 0],
|
|
]);
|
|
// 주민등록번호
|
|
$this->addTableRow($pdf, $font, [
|
|
['주민등록번호', $content['resident_number'] ?? '-', 0],
|
|
]);
|
|
// 소속 / 연락처
|
|
$this->addTableRow($pdf, $font, [
|
|
['소 속', $content['department'] ?? '-', 40],
|
|
['연 락 처', $content['phone'] ?? '-', 40],
|
|
]);
|
|
// 위촉기간 / 계약자격
|
|
$hireDate = $content['hire_date'] ?? '';
|
|
$resignDate = $content['resign_date'] ?? '';
|
|
$periodDisplay = $hireDate ? $hireDate.' ~ '.($resignDate ?: '현재') : '-';
|
|
$this->addTableRow($pdf, $font, [
|
|
['위촉기간', $periodDisplay, 45],
|
|
['계약자격', $content['contract_type'] ?? '-', 40],
|
|
]);
|
|
// 용도
|
|
$this->addTableRow($pdf, $font, [
|
|
['용 도', $content['purpose'] ?? '-', 0],
|
|
]);
|
|
$pdf->Ln(30);
|
|
|
|
// 증명 문구
|
|
$pdf->SetFont($font, '', 14);
|
|
$pdf->Cell(0, 12, '위와 같이 위촉하였음을 증명합니다.', 0, 1, 'C');
|
|
$pdf->Ln(20);
|
|
|
|
// 발급일
|
|
$issueDate = $content['issue_date'] ?? date('Y-m-d');
|
|
$issueDateFormatted = $this->formatDate($issueDate);
|
|
$pdf->SetFont($font, 'B', 14);
|
|
$pdf->Cell(0, 12, $issueDateFormatted, 0, 1, 'C');
|
|
$pdf->Ln(30);
|
|
|
|
// 회사명 + 대표이사
|
|
$ceoName = $content['ceo_name'] ?? '';
|
|
$pdf->SetFont($font, 'B', 16);
|
|
$pdf->Cell(0, 12, ($content['company_name'] ?? '').' 대표이사 '.$ceoName.' (인)', 0, 1, 'C');
|
|
|
|
$pdfContent = $pdf->Output('', 'S');
|
|
$fileName = '위촉증명서_'.($content['name'] ?? '').'.pdf';
|
|
|
|
return response($pdfContent, 200, [
|
|
'Content-Type' => 'application/pdf',
|
|
'Content-Disposition' => 'inline; filename="'.$fileName.'"',
|
|
]);
|
|
}
|
|
|
|
private function addTableRow(\TCPDF $pdf, string $font, array $cells): void
|
|
{
|
|
$pageWidth = $pdf->getPageWidth() - 40;
|
|
$rowHeight = 12;
|
|
$thWidth = 30;
|
|
|
|
if (count($cells) === 1) {
|
|
$pdf->SetFont($font, 'B', 12);
|
|
$pdf->SetFillColor(248, 249, 250);
|
|
$pdf->Cell($thWidth, $rowHeight, $cells[0][0], 1, 0, 'L', true);
|
|
$pdf->SetFont($font, '', 12);
|
|
$pdf->Cell($pageWidth - $thWidth, $rowHeight, $cells[0][1], 1, 1, 'L');
|
|
} else {
|
|
$tdWidth = ($pageWidth - $thWidth * 2) / 2;
|
|
foreach ($cells as $cell) {
|
|
$pdf->SetFont($font, 'B', 12);
|
|
$pdf->SetFillColor(248, 249, 250);
|
|
$pdf->Cell($thWidth, $rowHeight, $cell[0], 1, 0, 'L', true);
|
|
$pdf->SetFont($font, '', 12);
|
|
$pdf->Cell($tdWidth, $rowHeight, $cell[1], 1, 0, 'L');
|
|
}
|
|
$pdf->Ln();
|
|
}
|
|
}
|
|
|
|
private function formatDate(string $date): string
|
|
{
|
|
try {
|
|
return date('Y년 m월 d일', strtotime($date));
|
|
} catch (\Throwable) {
|
|
return $date;
|
|
}
|
|
}
|
|
|
|
private function getKoreanFont(): string
|
|
{
|
|
if ($this->koreanFontName) {
|
|
return $this->koreanFontName;
|
|
}
|
|
|
|
if (defined('K_PATH_FONTS') && file_exists(K_PATH_FONTS.'pretendard.php')) {
|
|
$this->koreanFontName = 'pretendard';
|
|
|
|
return $this->koreanFontName;
|
|
}
|
|
|
|
$fontPath = storage_path('fonts/Pretendard-Regular.ttf');
|
|
if (file_exists($fontPath)) {
|
|
try {
|
|
$this->koreanFontName = \TCPDF_FONTS::addTTFfont($fontPath, 'TrueTypeUnicode', '', 96);
|
|
} catch (\Throwable $e) {
|
|
Log::warning('TCPDF 한글 폰트 등록 실패', ['error' => $e->getMessage()]);
|
|
}
|
|
}
|
|
|
|
return $this->koreanFontName ?: 'helvetica';
|
|
}
|
|
}
|