Commit eec03363 authored by Mahmoud Aglan's avatar Mahmoud Aglan

go

parent 6fb137f8
...@@ -75,6 +75,7 @@ class RetroactiveWizardController extends Controller ...@@ -75,6 +75,7 @@ class RetroactiveWizardController extends Controller
'form_fee' => $data['form_fee_amount'] ?? '0.00', 'form_fee' => $data['form_fee_amount'] ?? '0.00',
'spouses_count' => count($data['spouses'] ?? []), 'spouses_count' => count($data['spouses'] ?? []),
'children_count' => count($data['children'] ?? []), 'children_count' => count($data['children'] ?? []),
'temp_members_count' => count($data['temporary_members'] ?? []),
'subscriptions' => $data['subscriptions'] ?? [], 'subscriptions' => $data['subscriptions'] ?? [],
'violations' => $data['violations'] ?? [], 'violations' => $data['violations'] ?? [],
'has_installment' => ($data['membership_payment_method'] ?? 'cash') === 'installment', 'has_installment' => ($data['membership_payment_method'] ?? 'cash') === 'installment',
...@@ -222,6 +223,26 @@ class RetroactiveWizardController extends Controller ...@@ -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 // Step 6: Subscriptions
$data['subscriptions'] = []; $data['subscriptions'] = [];
$subCount = (int) ($post['subscription_count'] ?? 0); $subCount = (int) ($post['subscription_count'] ?? 0);
...@@ -229,8 +250,9 @@ class RetroactiveWizardController extends Controller ...@@ -229,8 +250,9 @@ class RetroactiveWizardController extends Controller
if (!empty($post["sub_year_{$i}"])) { if (!empty($post["sub_year_{$i}"])) {
$data['subscriptions'][] = [ $data['subscriptions'][] = [
'financial_year' => $post["sub_year_{$i}"], 'financial_year' => $post["sub_year_{$i}"],
'person_type' => 'member', 'person_type' => $post["sub_person_type_{$i}"] ?? 'member',
'person_name' => $data['full_name_ar'], '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', 'base_amount' => $post["sub_base_{$i}"] ?? '492.00',
'development_fee' => $post["sub_dev_fee_{$i}"] ?? '35.00', 'development_fee' => $post["sub_dev_fee_{$i}"] ?? '35.00',
'total_amount' => $post["sub_total_{$i}"] ?? '527.00', 'total_amount' => $post["sub_total_{$i}"] ?? '527.00',
......
...@@ -223,9 +223,65 @@ final class RetroactiveMembershipService ...@@ -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 // 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'])) { if (!empty($data['subscriptions'])) {
foreach ($data['subscriptions'] as $sub) { 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); $subId = self::createRetroactiveSubscription($memberId, $sub);
$result['subscriptions'][] = $subId; $result['subscriptions'][] = $subId;
} }
...@@ -485,7 +541,7 @@ final class RetroactiveMembershipService ...@@ -485,7 +541,7 @@ final class RetroactiveMembershipService
'member_id' => $memberId, 'member_id' => $memberId,
'financial_year' => $sub['financial_year'], 'financial_year' => $sub['financial_year'],
'person_type' => $sub['person_type'] ?? 'member', 'person_type' => $sub['person_type'] ?? 'member',
'person_id' => $memberId, 'person_id' => $sub['person_id'] ?? $memberId,
'person_name' => $sub['person_name'] ?? '', 'person_name' => $sub['person_name'] ?? '',
'base_amount' => $sub['base_amount'] ?? '0.00', 'base_amount' => $sub['base_amount'] ?? '0.00',
'development_fee' => $sub['development_fee'] ?? '35.00', 'development_fee' => $sub['development_fee'] ?? '35.00',
......
...@@ -590,12 +590,13 @@ class TutorialController extends Controller ...@@ -590,12 +590,13 @@ class TutorialController extends Controller
$tmpOutput = tempnam(sys_get_temp_dir(), 'pdf_out_') . '.pdf'; $tmpOutput = tempnam(sys_get_temp_dir(), 'pdf_out_') . '.pdf';
file_put_contents($tmpInput, $html); 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' . ' --encoding utf-8 --page-size A4'
. ' --margin-top 15 --margin-bottom 15 --margin-left 12 --margin-right 12' . ' --margin-top 15 --margin-bottom 15 --margin-left 12 --margin-right 12'
. ' --disable-local-file-access' . ' --enable-local-file-access'
. ' --disable-javascript'
. ' --no-stop-slow-scripts' . ' --no-stop-slow-scripts'
. ' --javascript-delay 100'
. ' --image-quality 70' . ' --image-quality 70'
. ' --image-dpi 150' . ' --image-dpi 150'
. ' --print-media-type' . ' --print-media-type'
...@@ -604,6 +605,11 @@ class TutorialController extends Controller ...@@ -604,6 +605,11 @@ class TutorialController extends Controller
. ' 2>&1'; . ' 2>&1';
exec($cmd, $output, $returnCode); exec($cmd, $output, $returnCode);
if ($returnCode > 1) {
error_log('wkhtmltopdf failed (code ' . $returnCode . '): ' . implode("\n", $output));
}
@unlink($tmpInput); @unlink($tmpInput);
if (($returnCode === 0 || $returnCode === 1) && file_exists($tmpOutput) && filesize($tmpOutput) > 0) { if (($returnCode === 0 || $returnCode === 1) && file_exists($tmpOutput) && filesize($tmpOutput) > 0) {
...@@ -722,70 +728,22 @@ class TutorialController extends Controller ...@@ -722,70 +728,22 @@ class TutorialController extends Controller
if (!file_exists($path)) { if (!file_exists($path)) {
return $m[0]; return $m[0];
} }
$resized = $this->resizeForPdf($path); $raw = file_get_contents($path);
if ($raw === false) {
return $m[0];
}
$mime = match (strtolower($m[2])) { $mime = match (strtolower($m[2])) {
'jpg', 'jpeg' => 'image/jpeg', 'jpg', 'jpeg' => 'image/jpeg',
'gif' => 'image/gif', 'gif' => 'image/gif',
'webp' => 'image/webp', 'webp' => 'image/webp',
default => 'image/png', default => 'image/png',
}; };
return 'src="data:' . $mime . ';base64,' . base64_encode($resized) . '"'; return 'src="data:' . $mime . ';base64,' . base64_encode($raw) . '"';
}, },
$html $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 private function extractTutorialContent(string $raw): string
{ {
$start = strpos($raw, '<div class="tut-page">'); $start = strpos($raw, '<div class="tut-page">');
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
upload_max_filesize = 20M upload_max_filesize = 20M
post_max_size = 25M post_max_size = 25M
memory_limit = 1024M memory_limit = 2048M
max_execution_time = 1800 max_execution_time = 1800
max_input_time = 240 max_input_time = 240
max_input_vars = 5000 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