Commit eec03363 authored by Mahmoud Aglan's avatar Mahmoud Aglan

go

parent 6fb137f8
......@@ -75,6 +75,7 @@ class RetroactiveWizardController extends Controller
'form_fee' => $data['form_fee_amount'] ?? '0.00',
'spouses_count' => count($data['spouses'] ?? []),
'children_count' => count($data['children'] ?? []),
'temp_members_count' => count($data['temporary_members'] ?? []),
'subscriptions' => $data['subscriptions'] ?? [],
'violations' => $data['violations'] ?? [],
'has_installment' => ($data['membership_payment_method'] ?? 'cash') === 'installment',
......@@ -222,6 +223,26 @@ class RetroactiveWizardController extends Controller
}
}
$data['temporary_members'] = [];
$tempCount = (int) ($post['temp_member_count'] ?? 0);
for ($i = 1; $i <= $tempCount; $i++) {
if (!empty($post["temp_name_{$i}"])) {
$data['temporary_members'][] = [
'full_name_ar' => $post["temp_name_{$i}"],
'national_id' => $post["temp_nid_{$i}"] ?? null,
'date_of_birth' => $post["temp_dob_{$i}"] ?? null,
'gender' => $post["temp_gender_{$i}"] ?? 'male',
'category' => $post["temp_category_{$i}"] ?? 'parent',
'relationship_to_member' => $post["temp_relationship_{$i}"] ?? null,
'join_date' => $post["temp_join_date_{$i}"] ?? ($post['join_date'] ?? date('Y-m-d')),
'addition_fee' => $post["temp_fee_{$i}"] ?? '0.00',
'has_separate_fee' => !empty($post["temp_separate_fee_{$i}"]),
'payment_method' => $post["temp_pay_method_{$i}"] ?? 'cash',
'payment_date' => $post["temp_pay_date_{$i}"] ?? null,
];
}
}
// Step 6: Subscriptions
$data['subscriptions'] = [];
$subCount = (int) ($post['subscription_count'] ?? 0);
......@@ -229,8 +250,9 @@ class RetroactiveWizardController extends Controller
if (!empty($post["sub_year_{$i}"])) {
$data['subscriptions'][] = [
'financial_year' => $post["sub_year_{$i}"],
'person_type' => 'member',
'person_name' => $data['full_name_ar'],
'person_type' => $post["sub_person_type_{$i}"] ?? 'member',
'person_index' => (int) ($post["sub_person_index_{$i}"] ?? 0),
'person_name' => $post["sub_person_name_{$i}"] ?? $data['full_name_ar'],
'base_amount' => $post["sub_base_{$i}"] ?? '492.00',
'development_fee' => $post["sub_dev_fee_{$i}"] ?? '35.00',
'total_amount' => $post["sub_total_{$i}"] ?? '527.00',
......
......@@ -223,9 +223,65 @@ final class RetroactiveMembershipService
}
}
if (!empty($data['temporary_members'])) {
foreach ($data['temporary_members'] as $temp) {
$tempJoinDate = self::emptyToNull($temp['join_date'] ?? null) ?? $joinDate;
$tempId = $db->insert('temporary_members', [
'member_id' => $memberId,
'full_name_ar' => $temp['full_name_ar'],
'national_id' => self::emptyToNull($temp['national_id'] ?? null),
'date_of_birth' => self::emptyToNull($temp['date_of_birth'] ?? null),
'gender' => $temp['gender'] ?? 'male',
'category' => $temp['category'] ?? 'parent',
'relationship_to_member' => self::emptyToNull($temp['relationship_to_member'] ?? null),
'status' => 'active',
'join_date' => $tempJoinDate,
'addition_fee' => $temp['addition_fee'] ?? '0.00',
'is_archived' => 0,
'created_at' => $tempJoinDate . ' 09:00:00',
'updated_at' => $ts,
]);
if (!empty($temp['addition_fee']) && bccomp($temp['addition_fee'], '0', 2) > 0 && !empty($temp['has_separate_fee'])) {
$tPayId = self::createRetroactivePayment($memberId, [
'payment_type' => 'addition_fee',
'amount' => $temp['addition_fee'],
'payment_method' => $temp['payment_method'] ?? 'cash',
'payment_date' => $temp['payment_date'] ?? $joinDate,
'related_entity_type' => 'temporary_members',
'related_entity_id' => $tempId,
'description' => 'رسوم إضافة عضو مؤقت — إدخال بأثر رجعي',
]);
}
$result['dependents'][] = ['type' => 'temporary', 'id' => $tempId, 'name' => $temp['full_name_ar']];
}
}
// Step 5: Create retroactive subscriptions
// Build person_id map for dependents
$personIdMap = [
'member' => [$memberId],
'spouse' => [],
'child' => [],
'temporary' => [],
];
foreach ($result['dependents'] as $dep) {
$personIdMap[$dep['type']][] = $dep['id'];
}
if (!empty($data['subscriptions'])) {
foreach ($data['subscriptions'] as $sub) {
$personType = $sub['person_type'] ?? 'member';
$personIndex = (int) ($sub['person_index'] ?? 0);
$personId = $memberId;
if ($personType !== 'member' && isset($personIdMap[$personType][$personIndex])) {
$personId = $personIdMap[$personType][$personIndex];
}
$sub['person_id'] = $personId;
$subId = self::createRetroactiveSubscription($memberId, $sub);
$result['subscriptions'][] = $subId;
}
......@@ -485,7 +541,7 @@ final class RetroactiveMembershipService
'member_id' => $memberId,
'financial_year' => $sub['financial_year'],
'person_type' => $sub['person_type'] ?? 'member',
'person_id' => $memberId,
'person_id' => $sub['person_id'] ?? $memberId,
'person_name' => $sub['person_name'] ?? '',
'base_amount' => $sub['base_amount'] ?? '0.00',
'development_fee' => $sub['development_fee'] ?? '35.00',
......
......@@ -590,12 +590,13 @@ class TutorialController extends Controller
$tmpOutput = tempnam(sys_get_temp_dir(), 'pdf_out_') . '.pdf';
file_put_contents($tmpInput, $html);
$cmd = escapeshellarg($wkhtmltopdf)
$cmd = 'xvfb-run --auto-servernum --server-args="-screen 0 1280x1024x24" '
. escapeshellarg($wkhtmltopdf)
. ' --encoding utf-8 --page-size A4'
. ' --margin-top 15 --margin-bottom 15 --margin-left 12 --margin-right 12'
. ' --disable-local-file-access'
. ' --disable-javascript'
. ' --enable-local-file-access'
. ' --no-stop-slow-scripts'
. ' --javascript-delay 100'
. ' --image-quality 70'
. ' --image-dpi 150'
. ' --print-media-type'
......@@ -604,6 +605,11 @@ class TutorialController extends Controller
. ' 2>&1';
exec($cmd, $output, $returnCode);
if ($returnCode > 1) {
error_log('wkhtmltopdf failed (code ' . $returnCode . '): ' . implode("\n", $output));
}
@unlink($tmpInput);
if (($returnCode === 0 || $returnCode === 1) && file_exists($tmpOutput) && filesize($tmpOutput) > 0) {
......@@ -722,70 +728,22 @@ class TutorialController extends Controller
if (!file_exists($path)) {
return $m[0];
}
$resized = $this->resizeForPdf($path);
$raw = file_get_contents($path);
if ($raw === false) {
return $m[0];
}
$mime = match (strtolower($m[2])) {
'jpg', 'jpeg' => 'image/jpeg',
'gif' => 'image/gif',
'webp' => 'image/webp',
default => 'image/png',
};
return 'src="data:' . $mime . ';base64,' . base64_encode($resized) . '"';
return 'src="data:' . $mime . ';base64,' . base64_encode($raw) . '"';
},
$html
);
}
private function resizeForPdf(string $path): string
{
$info = @getimagesize($path);
if (!$info) {
return (string) file_get_contents($path);
}
[$origW, $origH, $type] = $info;
$maxW = 1200;
if ($origW <= $maxW) {
$img = match ($type) {
IMAGETYPE_PNG => @imagecreatefrompng($path),
IMAGETYPE_JPEG => @imagecreatefromjpeg($path),
IMAGETYPE_GIF => @imagecreatefromgif($path),
IMAGETYPE_WEBP => @imagecreatefromwebp($path),
default => null,
};
if (!$img) {
return (string) file_get_contents($path);
}
ob_start();
imagejpeg($img, null, 65);
imagedestroy($img);
return (string) ob_get_clean();
}
$newW = $maxW;
$newH = (int) round($origH * ($maxW / $origW));
$src = match ($type) {
IMAGETYPE_PNG => @imagecreatefrompng($path),
IMAGETYPE_JPEG => @imagecreatefromjpeg($path),
IMAGETYPE_GIF => @imagecreatefromgif($path),
IMAGETYPE_WEBP => @imagecreatefromwebp($path),
default => null,
};
if (!$src) {
return (string) file_get_contents($path);
}
$dst = imagecreatetruecolor($newW, $newH);
imagecopyresampled($dst, $src, 0, 0, 0, 0, $newW, $newH, $origW, $origH);
imagedestroy($src);
ob_start();
imagejpeg($dst, null, 65);
imagedestroy($dst);
return (string) ob_get_clean();
}
private function extractTutorialContent(string $raw): string
{
$start = strpos($raw, '<div class="tut-page">');
......
......@@ -2,7 +2,7 @@
upload_max_filesize = 20M
post_max_size = 25M
memory_limit = 1024M
memory_limit = 2048M
max_execution_time = 1800
max_input_time = 240
max_input_vars = 5000
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment