Commit ca7312ce authored by Administrator's avatar Administrator

Update 1 files via Son of Anton

parent 44998953
......@@ -22,21 +22,29 @@ class SpouseController extends Controller
return $this->redirect('/members')->withError('العضو غير موجود');
}
// BLOCK: membership_value must be set
$membershipValue = $member['membership_value'] ?? '0.00';
if (bccomp($membershipValue, '0.01', 2) < 0) {
return $this->redirect('/members/' . $memberId)
->withError('⚠ يجب ملء الاستمارة وتحديد المؤهل أولاً لحساب قيمة العضوية قبل إضافة زوج/ة');
}
$qualifications = $db->select("SELECT id, name_ar FROM qualifications WHERE is_active = 1 ORDER BY sort_order");
$countries = $db->select("SELECT nationality_ar FROM countries WHERE is_active = 1 ORDER BY name_ar");
$currentSpouseCount = Spouse::countActiveForMember((int) $memberId);
$spouseOrder = Spouse::getNextOrder((int) $memberId);
// Check max spouses
$maxSpouses = ($member['gender'] === 'male') ? 4 : 1;
if ($currentSpouseCount >= $maxSpouses) {
return $this->redirect('/members/' . $memberId)->withError('تم الوصول للحد الأقصى لعدد الأزواج');
}
// Pre-calculate fee estimate for display
$feeEstimate = SpouseFeeCalculator::calculate((int) $memberId, [
'nationality' => 'مصري',
'marriage_date' => date('Y-m-d'),
]);
return $this->view('Spouses.Views.create', [
'member' => $member,
'qualifications' => $qualifications,
'countries' => $countries,
'spouseOrder' => $currentSpouseCount + 1,
'spouseOrder' => $spouseOrder,
'feeEstimate' => $feeEstimate,
]);
}
......@@ -48,22 +56,28 @@ class SpouseController extends Controller
return $this->redirect('/members')->withError('العضو غير موجود');
}
// BLOCK: membership_value must be set
$membershipValue = $member['membership_value'] ?? '0.00';
if (bccomp($membershipValue, '0.01', 2) < 0) {
return $this->redirect('/members/' . $memberId)
->withError('⚠ يجب تحديد قيمة العضوية قبل إضافة زوج/ة');
}
$data = $request->all();
unset($data['_csrf_token']);
$errors = [];
// Required fields
if (empty(trim($data['full_name_ar'] ?? ''))) $errors[] = 'اسم الزوج/الزوجة مطلوب';
if (empty(trim($data['full_name_ar'] ?? ''))) $errors[] = 'اسم الزوج/ة مطلوب';
if (empty($data['date_of_birth'] ?? '')) $errors[] = 'تاريخ الميلاد مطلوب';
if (empty($data['gender'] ?? '')) $errors[] = 'النوع مطلوب';
if (empty($data['marriage_date'] ?? '')) $errors[] = 'تاريخ الزواج مطلوب';
// Check max spouses
$currentCount = Spouse::countActiveForMember((int) $memberId);
// Max spouse check
$existingCount = Spouse::countActiveForMember((int) $memberId);
$maxSpouses = ($member['gender'] === 'male') ? 4 : 1;
if ($currentCount >= $maxSpouses) {
$errors[] = 'تم الوصول للحد الأقصى لعدد الأزواج (' . $maxSpouses . ')';
if ($existingCount >= $maxSpouses) {
$errors[] = 'تم بلوغ الحد الأقصى لعدد الزوجات (' . $maxSpouses . ')';
}
// Parse NID if provided
......@@ -79,35 +93,33 @@ class SpouseController extends Controller
$data['gender'] = $parsed['gender'];
}
// Cannot be own spouse
// Cannot be the member themselves
if ($nid === ($member['national_id'] ?? '')) {
$errors[] = 'لا يمكن إضافة العضو نفسه كزوج';
$errors[] = 'لا يمكن إضافة العضو نفسه كزوج';
}
// Duplicate NID check
// Check duplicate
$dup = Spouse::nidExistsForOtherMember($nid, (int) $memberId);
if ($dup) {
$dupName = $dup['data']['full_name_ar'] ?? '';
$dupNum = $dup['data']['membership_number'] ?? '';
$errors[] = "الرقم القومي مسجل بالفعل: {$dupName} ({$dupNum})";
$errors[] = 'الرقم القومي مسجل بالفعل: ' . ($dup['data']['full_name_ar'] ?? '');
}
}
// Marriage date validation
if (!empty($data['marriage_date'])) {
$marriageTs = strtotime($data['marriage_date']);
if ($marriageTs > time()) {
$errors[] = 'تاريخ الزواج لا يمكن أن يكون في المستقبل';
}
// Both must be >= 18 at marriage
if (!empty($data['date_of_birth']) && !empty($member['date_of_birth'])) {
$spouseAgeAtMarriage = (int) (((new \DateTime($data['date_of_birth']))->diff(new \DateTime($data['marriage_date'])))->y);
$memberAgeAtMarriage = (int) (((new \DateTime($member['date_of_birth']))->diff(new \DateTime($data['marriage_date'])))->y);
if ($spouseAgeAtMarriage < 18) {
$errors[] = 'عمر الزوج/الزوجة عند الزواج يجب أن يكون 18 سنة على الأقل';
// Calculate age
if (!empty($data['date_of_birth']) && empty($data['age_years'])) {
$age = age_from_dob($data['date_of_birth']);
$data['age_years'] = $age['years'];
$data['age_months'] = $age['months'];
}
if ($memberAgeAtMarriage < 18) {
$errors[] = 'عمر العضو عند الزواج يجب أن يكون 18 سنة على الأقل';
// Both must be at least 18 at marriage
if (!empty($data['date_of_birth']) && !empty($data['marriage_date'])) {
$dobTs = strtotime($data['date_of_birth']);
$marriageTs = strtotime($data['marriage_date']);
if ($marriageTs && $dobTs) {
$ageAtMarriage = (int) (($marriageTs - $dobTs) / (365.25 * 86400));
if ($ageAtMarriage < 18) {
$errors[] = 'يجب أن يكون عمر الزوج/ة 18 سنة على الأقل وقت الزواج';
}
}
}
......@@ -119,20 +131,16 @@ class SpouseController extends Controller
return $this->redirect("/members/{$memberId}/spouses/create");
}
// Calculate age
if (!empty($data['date_of_birth']) && empty($data['age_years'])) {
$age = age_from_dob($data['date_of_birth']);
$data['age_years'] = $age['years'];
$data['age_months'] = $age['months'];
}
// Determine classification
$spouseAge = (int) ($data['age_years'] ?? 0);
$classification = $spouseAge >= 21 ? 'working' : 'dependent';
// Calculate fee
$feeCalc = SpouseFeeCalculator::calculate((int) $memberId, $data);
$spouseOrder = $feeCalc['spouse_order'] ?? ($currentCount + 1);
if (!empty($feeCalc['error'])) {
return $this->redirect("/members/{$memberId}/spouses/create")
->withError($feeCalc['error']);
}
$spouseOrder = $feeCalc['spouse_order'] ?? Spouse::getNextOrder((int) $memberId);
$joinDate = date('Y-m-d');
$spouse = Spouse::create([
'member_id' => (int) $memberId,
......@@ -147,49 +155,58 @@ class SpouseController extends Controller
'gender' => $data['gender'],
'nationality' => $data['nationality'] ?? 'مصري',
'religion' => $data['religion'] ?? null,
'qualification_id' => !empty($data['qualification_id']) ? (int) $data['qualification_id'] : null,
'qualification_id' => ($data['qualification_id'] ?? '') !== '' ? (int) $data['qualification_id'] : null,
'occupation' => $data['occupation'] ?? null,
'work_address' => $data['work_address'] ?? null,
'work_phone' => $data['work_phone'] ?? null,
'mobile' => $data['mobile'] ?? null,
'marriage_date' => $data['marriage_date'],
'join_date' => date('Y-m-d'),
'classification' => $classification,
'addition_fee' => $feeCalc['spouse_fee'] ?? '0.00',
'join_date' => $joinDate,
'classification' => 'working',
'addition_fee' => $feeCalc['total_fee'] ?? '0.00',
'status' => 'active',
]);
EventBus::dispatch('spouse.added', [
'member_id' => (int) $memberId,
'spouse_id' => (int) $spouse->id,
'fee' => $feeCalc['spouse_fee'] ?? '0.00',
'spouse_order' => $spouseOrder,
'fee' => $feeCalc['total_fee'] ?? '0.00',
]);
// Build success message with full breakdown
$breakdown = $feeCalc['breakdown'] ?? [];
$breakdownText = !empty($breakdown) ? "\n" . implode("\n", $breakdown) : '';
$msg = 'تم إضافة الزوج/الزوجة بنجاح';
$msg .= ' — الترتيب: #' . $spouseOrder;
$msg .= ' — الرسوم: ' . money($feeCalc['total_fee'] ?? '0');
if (!empty($feeCalc['rule_applied'])) {
$msg .= ' (' . $feeCalc['rule_applied'] . ')';
}
return $this->redirect("/members/{$memberId}")
->withSuccess('تم إضافة الزوج/الزوجة بنجاح — الرسوم: ' . money($feeCalc['spouse_fee'] ?? '0.00'));
->withSuccess($msg);
}
public function show(Request $request, string $memberId, string $id): Response
{
$spouse = Spouse::find((int) $id);
if (!$spouse || (int) $spouse->member_id !== (int) $memberId) {
return $this->redirect("/members/{$memberId}")->withError('بيانات الزوج غير موجودة');
return $this->redirect("/members/{$memberId}")->withError('بيانات الزوج غير موجودة');
}
$db = App::getInstance()->db();
$member = $db->selectOne("SELECT * FROM members WHERE id = ?", [(int) $memberId]);
return $this->view('Spouses.Views.show', [
'member' => $member,
'spouse' => $spouse,
]);
return $this->view('Spouses.Views.show', ['member' => $member, 'spouse' => $spouse]);
}
public function edit(Request $request, string $memberId, string $id): Response
{
$spouse = Spouse::find((int) $id);
if (!$spouse || (int) $spouse->member_id !== (int) $memberId) {
return $this->redirect("/members/{$memberId}")->withError('بيانات الزوج غير موجودة');
return $this->redirect("/members/{$memberId}")->withError('بيانات الزوج غير موجودة');
}
$db = App::getInstance()->db();
......@@ -209,42 +226,35 @@ class SpouseController extends Controller
{
$spouse = Spouse::find((int) $id);
if (!$spouse || (int) $spouse->member_id !== (int) $memberId) {
return $this->redirect("/members/{$memberId}")->withError('بيانات الزوج غير موجودة');
return $this->redirect("/members/{$memberId}")->withError('بيانات الزوج غير موجودة');
}
$data = $request->all();
unset($data['_csrf_token']);
$updateFields = [
'full_name_en', 'religion', 'occupation', 'work_address',
'work_phone', 'mobile', 'qualification_id',
];
$updateData = [];
foreach ($updateFields as $field) {
foreach (['full_name_en', 'occupation', 'work_address', 'work_phone', 'mobile', 'religion'] as $field) {
if (array_key_exists($field, $data)) {
$val = $data[$field];
$updateData[$field] = ($val === '' || $val === null) ? null : $val;
}
}
if (isset($data['qualification_id'])) {
$updateData['qualification_id'] = ($data['qualification_id'] !== '') ? (int) $data['qualification_id'] : null;
}
if (!empty($updateData)) {
$spouse->update($updateData);
}
EventBus::dispatch('spouse.updated', [
'member_id' => (int) $memberId,
'spouse_id' => (int) $id,
]);
return $this->redirect("/members/{$memberId}")->withSuccess('تم تحديث بيانات الزوج/الزوجة');
return $this->redirect("/members/{$memberId}")->withSuccess('تم تحديث بيانات الزوج/ة');
}
public function archive(Request $request, string $memberId, string $id): Response
{
$spouse = Spouse::find((int) $id);
if (!$spouse || (int) $spouse->member_id !== (int) $memberId) {
return $this->redirect("/members/{$memberId}")->withError('بيانات الزوج غير موجودة');
return $this->redirect("/members/{$memberId}")->withError('بيانات الزوج غير موجودة');
}
$reason = trim((string) $request->post('reason', ''));
......@@ -269,19 +279,6 @@ class SpouseController extends Controller
'reason' => $reason,
]);
return $this->redirect("/members/{$memberId}")->withSuccess('تم إزالة الزوج/الزوجة');
}
public function calculateFee(Request $request): Response
{
$memberId = (int) $request->post('member_id', 0);
$data = $request->all();
if ($memberId <= 0) {
return $this->json(['error' => 'بيانات غير صالحة'], 422);
}
$result = SpouseFeeCalculator::calculate($memberId, $data);
return $this->json($result);
return $this->redirect("/members/{$memberId}")->withSuccess('تم إزالة الزوج/ة');
}
}
\ No newline at end of file
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