Files
sam-manage/app/Services/EmploymentCertService.php
김보곤 dde0acad72 feat: [approval] 재직증명서 기안 기능 추가
- EmploymentCertService: 사원 정보 조회, DOCX 생성, 파일 레코드 생성
- API 엔드포인트: cert-info/{userId}, generate-cert-docx
- _certificate-form: 인적사항/재직사항/발급정보 입력 폼
- _certificate-show: 재직증명서 읽기전용 표시 파셜
- create/edit/show에 employment_cert 양식 분기 처리
- phpoffice/phpword 패키지 추가
2026-03-05 18:54:03 +09:00

122 lines
4.3 KiB
PHP

<?php
namespace App\Services;
use App\Models\Commons\File;
use App\Models\HR\Employee;
use App\Models\Tenants\Tenant;
use Illuminate\Support\Str;
use PhpOffice\PhpWord\TemplateProcessor;
class EmploymentCertService
{
/**
* 사원의 재직증명서 정보 조회
*/
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);
$residentNumber = $employee->resident_number;
$maskedResident = $residentNumber
? substr($residentNumber, 0, 8).'******'
: '';
return [
'name' => $employee->user->name ?? $employee->display_name ?? '',
'resident_number' => $maskedResident,
'resident_number_full' => $residentNumber ?? '',
'address' => $employee->address ?? '',
'department' => $employee->department?->name ?? '',
'position' => $employee->position_label ?? '',
'hire_date' => $employee->hire_date ?? '',
'company_name' => $tenant->company_name ?? '',
'business_num' => $tenant->business_num ?? '',
'ceo_name' => $tenant->ceo_name ?? '',
'phone' => $tenant->phone ?? '',
'company_address' => $tenant->address ?? '',
];
}
/**
* DOCX 생성
*/
public function generateDocx(array $data, int $tenantId): string
{
$templatePath = storage_path('app/templates/employment_cert.docx');
if (! file_exists($templatePath)) {
throw new \RuntimeException('재직증명서 템플릿 파일이 없습니다.');
}
$template = new TemplateProcessor($templatePath);
$hireDateFormatted = '';
if (! empty($data['hire_date'])) {
try {
$hireDateFormatted = date('Y년 m월 d일', strtotime($data['hire_date']));
} catch (\Throwable) {
$hireDateFormatted = $data['hire_date'];
}
}
$issueDateFormatted = date('Y년 m월 d일');
$template->setValue('name', $data['name'] ?? '');
$template->setValue('resident_number', $data['resident_number_full'] ?? '');
$template->setValue('address', $data['address'] ?? '');
$template->setValue('company_name', $data['company_name'] ?? '');
$template->setValue('business_num', $data['business_num'] ?? '');
$template->setValue('ceo_name', $data['ceo_name'] ?? '');
$template->setValue('phone', $data['phone'] ?? '');
$template->setValue('company_address', $data['company_address'] ?? '');
$template->setValue('department', $data['department'] ?? '');
$template->setValue('position', $data['position'] ?? '');
$template->setValue('hire_date', $hireDateFormatted);
$template->setValue('purpose', $data['purpose'] ?? '');
$template->setValue('issue_date', $issueDateFormatted);
$outputDir = storage_path("app/approvals/{$tenantId}");
if (! is_dir($outputDir)) {
mkdir($outputDir, 0755, true);
}
$fileName = '재직증명서_'.($data['name'] ?? 'unknown').'_'.date('Ymd').'.docx';
$storedName = Str::random(40).'.docx';
$storagePath = "approvals/{$tenantId}/{$storedName}";
$fullPath = storage_path("app/{$storagePath}");
$template->saveAs($fullPath);
return $storagePath;
}
/**
* 파일 레코드 생성 및 approval에 첨부
*/
public function createFileRecord(string $storagePath, string $displayName, int $tenantId): File
{
$fullPath = storage_path("app/{$storagePath}");
return File::create([
'tenant_id' => $tenantId,
'document_type' => 'approval_attachment',
'display_name' => $displayName,
'original_name' => $displayName,
'stored_name' => basename($storagePath),
'file_path' => $storagePath,
'mime_type' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'file_size' => filesize($fullPath),
'file_type' => 'docx',
'is_temp' => false,
'uploaded_by' => auth()->id(),
]);
}
}