Files
sam-manage/app/Services/EmploymentCertService.php
김보곤 0649802ffd fix: [approvals] 재직/경력증명서 주민번호 전체 표시 (마스킹 제거)
- 재직증명서: 주민번호 뒷자리 ****** 마스킹 제거, 전체 표시
- 경력증명서: 주민등록번호 필드 추가 (폼/조회/미리보기/PDF)
- EmploymentCertService: maskedResident 로직 제거
- CareerCertService: resident_number 반환 추가, PDF 행 추가
2026-03-06 15:59:05 +09:00

232 lines
7.4 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 EmploymentCertService
{
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);
// 인쇄용 회사 표시명 조회 (설정 없으면 기본 company_name 사용)
$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,
'address' => $employee->address ?? '',
'department' => $employee->department?->name ?? '',
'position' => $employee->position_label ?? '',
'hire_date' => $employee->hire_date ?? '',
'company_name' => $companyName,
'business_num' => $tenant->business_num ?? '',
'ceo_name' => $tenant->ceo_name ?? '',
'phone' => $tenant->phone ?? '',
'company_address' => $tenant->address ?? '',
];
}
/**
* 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, 30, 20);
$pdf->SetAutoPageBreak(true, 20);
$font = $this->getKoreanFont();
$pdf->AddPage();
// 상단 여백
$pdf->Ln(10);
// 제목
$pdf->SetFont($font, 'B', 24);
$pdf->Cell(0, 20, '재 직 증 명 서', 0, 1, 'C');
$pdf->Ln(12);
// === 1. 인적사항 ===
$pdf->SetFont($font, 'B', 13);
$pdf->Cell(0, 10, '1. 인적사항', 0, 1, 'L');
$pdf->Ln(2);
$this->addTableRow($pdf, $font, [
['성 명', $content['name'] ?? '-', 40],
['주민등록번호', $content['resident_number'] ?? '-', 40],
]);
$this->addTableRow($pdf, $font, [
['주 소', $content['address'] ?? '-', 0],
]);
$pdf->Ln(8);
// === 2. 재직사항 ===
$pdf->SetFont($font, 'B', 13);
$pdf->Cell(0, 10, '2. 재직사항', 0, 1, 'L');
$pdf->Ln(2);
$this->addTableRow($pdf, $font, [
['회 사 명', $content['company_name'] ?? '-', 0],
]);
$this->addTableRow($pdf, $font, [
['사업자번호', $content['business_num'] ?? '-', 0],
]);
$this->addTableRow($pdf, $font, [
['근무부서', $content['department'] ?? '-', 40],
['직 급', $content['position'] ?? '-', 40],
]);
$hireDate = $content['hire_date'] ?? '';
$hireDateDisplay = $hireDate ? $hireDate.' ~ 현재' : '-';
$this->addTableRow($pdf, $font, [
['재직기간', $hireDateDisplay, 0],
]);
$pdf->Ln(8);
// === 3. 발급정보 ===
$pdf->SetFont($font, 'B', 13);
$pdf->Cell(0, 10, '3. 발급정보', 0, 1, 'L');
$pdf->Ln(2);
$this->addTableRow($pdf, $font, [
['사용용도', $content['purpose'] ?? '-', 0],
]);
$pdf->Ln(20);
// 증명 문구
$pdf->SetFont($font, '', 14);
$pdf->Cell(0, 12, '위 사항을 증명합니다.', 0, 1, 'C');
$pdf->Ln(10);
// 발급일
$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(20);
// 회사명 + 대표이사
$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.'"',
]);
}
/**
* 테이블 행 추가 (TCPDF)
*/
private function addTableRow(\TCPDF $pdf, string $font, array $cells): void
{
$pageWidth = $pdf->getPageWidth() - 40; // margins
$rowHeight = 10;
$thWidth = 30;
if (count($cells) === 1) {
// 단일 셀: th + td (전체 너비)
$pdf->SetFont($font, 'B', 11);
$pdf->SetFillColor(248, 249, 250);
$pdf->Cell($thWidth, $rowHeight, $cells[0][0], 1, 0, 'L', true);
$pdf->SetFont($font, '', 11);
$pdf->Cell($pageWidth - $thWidth, $rowHeight, $cells[0][1], 1, 1, 'L');
} else {
// 복수 셀: th+td + th+td
$tdWidth = ($pageWidth - $thWidth * 2) / 2;
foreach ($cells as $cell) {
$pdf->SetFont($font, 'B', 11);
$pdf->SetFillColor(248, 249, 250);
$pdf->Cell($thWidth, $rowHeight, $cell[0], 1, 0, 'L', true);
$pdf->SetFont($font, '', 11);
$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';
}
}