Commit b4b78902 authored by Mahmoud Aglan's avatar Mahmoud Aglan

Add board approval workflow to divorce module with fee transparency

- Divorce requests now go through board review before payment
- Board sets fee percentage based on qualification + divorce certificate
- Total fee = (percentage × membership value) + 570 form fee + annual subscription
- New member page shows old/new membership number transfer link
- Full workflow: submit → board_review → board_approved → payment → complete
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 49388c23
...@@ -32,7 +32,8 @@ class DivorceController extends Controller ...@@ -32,7 +32,8 @@ class DivorceController extends Controller
if (!$member) return $this->redirect('/members')->withError('العضو غير موجود'); if (!$member) return $this->redirect('/members')->withError('العضو غير موجود');
$spouses = $db->select("SELECT * FROM spouses WHERE member_id = ? AND is_archived = 0 AND status = 'active'", [(int) $memberId]); $spouses = $db->select("SELECT * FROM spouses WHERE member_id = ? AND is_archived = 0 AND status = 'active'", [(int) $memberId]);
if (empty($spouses)) return $this->redirect("/members/{$memberId}")->withError('لا يوجد زوج/زوجة مسجلة'); if (empty($spouses)) return $this->redirect("/members/{$memberId}")->withError('لا يوجد زوج/زوجة مسجلة');
return $this->view('Divorce.Views.create', ['member' => $member, 'spouses' => $spouses]); $qualifications = $db->select("SELECT id, name_ar FROM qualifications WHERE is_active = 1 ORDER BY sort_order");
return $this->view('Divorce.Views.create', ['member' => $member, 'spouses' => $spouses, 'qualifications' => $qualifications]);
} }
public function store(Request $request, string $memberId): Response public function store(Request $request, string $memberId): Response
...@@ -43,13 +44,39 @@ class DivorceController extends Controller ...@@ -43,13 +44,39 @@ class DivorceController extends Controller
$spouseId = (int) $request->post('spouse_id', 0); $spouseId = (int) $request->post('spouse_id', 0);
$divorceDate = trim($request->post('divorce_date', '')); $divorceDate = trim($request->post('divorce_date', ''));
$qualificationId = (int) $request->post('spouse_qualification_id', 0);
$notes = trim($request->post('notes', '')); $notes = trim($request->post('notes', ''));
$paymentMethod = trim($request->post('payment_method', 'cash'));
if (!$spouseId || !$divorceDate) { if (!$spouseId || !$divorceDate || !$qualificationId) {
return $this->redirect("/divorce/create/{$memberId}")->withError('بيانات الطلاق غير مكتملة'); return $this->redirect("/divorce/create/{$memberId}")->withError('جميع البيانات مطلوبة (الزوج/ة، التاريخ، المؤهل، قسيمة الطلاق)');
} }
// Handle divorce certificate upload
$certPath = null;
if (!empty($_FILES['divorce_certificate']['tmp_name'])) {
$file = $_FILES['divorce_certificate'];
$maxSize = 5 * 1024 * 1024;
if ($file['size'] > $maxSize) {
return $this->redirect("/divorce/create/{$memberId}")->withError('حجم الملف أكبر من 5 ميجا');
}
$allowed = ['application/pdf', 'image/jpeg', 'image/png', 'image/jpg'];
if (!in_array($file['type'], $allowed, true)) {
return $this->redirect("/divorce/create/{$memberId}")->withError('نوع الملف غير مسموح — PDF أو صور فقط');
}
$ext = pathinfo($file['name'], PATHINFO_EXTENSION);
$storedName = 'divorce_cert_' . time() . '_' . $spouseId . '.' . $ext;
$uploadDir = App::getInstance()->basePath() . '/storage/uploads/divorce/';
if (!is_dir($uploadDir)) mkdir($uploadDir, 0755, true);
if (move_uploaded_file($file['tmp_name'], $uploadDir . $storedName)) {
$certPath = 'storage/uploads/divorce/' . $storedName;
}
}
if (!$certPath) {
return $this->redirect("/divorce/create/{$memberId}")->withError('قسيمة الطلاق مطلوبة');
}
// Validate basic eligibility
$feeCalc = DivorceFeeCalculator::calculate((int) $memberId, $spouseId, $divorceDate); $feeCalc = DivorceFeeCalculator::calculate((int) $memberId, $spouseId, $divorceDate);
if (!($feeCalc['success'] ?? false)) { if (!($feeCalc['success'] ?? false)) {
return $this->redirect("/divorce/create/{$memberId}")->withError($feeCalc['error'] ?? 'خطأ'); return $this->redirect("/divorce/create/{$memberId}")->withError($feeCalc['error'] ?? 'خطأ');
...@@ -59,56 +86,109 @@ class DivorceController extends Controller ...@@ -59,56 +86,109 @@ class DivorceController extends Controller
'member_id' => (int) $memberId, 'member_id' => (int) $memberId,
'spouse_id' => $spouseId, 'spouse_id' => $spouseId,
'divorce_date' => $divorceDate, 'divorce_date' => $divorceDate,
'divorce_certificate_path' => $certPath,
'spouse_qualification_id' => $qualificationId,
'divorce_case_type' => $feeCalc['case_type'], 'divorce_case_type' => $feeCalc['case_type'],
'request_date' => date('Y-m-d'), 'request_date' => date('Y-m-d'),
'membership_acquisition_date' => substr($member['created_at'] ?? '', 0, 10), 'membership_acquisition_date' => substr($member['created_at'] ?? '', 0, 10),
'years_of_membership' => $feeCalc['years_of_membership'], 'years_of_membership' => $feeCalc['years_of_membership'],
'has_children_on_membership' => $feeCalc['has_children'] ? 1 : 0, 'has_children_on_membership' => $feeCalc['has_children'] ? 1 : 0,
'fee_percentage' => $feeCalc['fee_percentage'], 'status' => 'board_review',
'fee_amount' => $feeCalc['total_fee'],
'status' => 'submitted',
'notes' => $notes ?: null, 'notes' => $notes ?: null,
]); ]);
EventBus::dispatch('divorce.submitted', ['case_id' => (int) $case->id, 'member_id' => (int) $memberId]); EventBus::dispatch('divorce.submitted', ['case_id' => (int) $case->id, 'member_id' => (int) $memberId]);
// Send payment to cashier queue return $this->redirect("/divorce/{$case->id}")->withSuccess('تم تقديم طلب الطلاق وإرساله لمجلس الأمناء للمراجعة');
$amount = $feeCalc['total_fee'] ?? '0.00'; }
if (bccomp((string) $amount, '0', 2) > 0) {
$caseTypeLabel = DivorceCase::getCaseTypeLabel($feeCalc['case_type']); public function boardApprove(Request $request, string $id): Response
{
$db = App::getInstance()->db();
$case = $db->selectOne("SELECT * FROM divorce_cases WHERE id = ?", [(int) $id]);
if (!$case || $case['status'] !== 'board_review') {
return $this->redirect('/divorce')->withError('الحالة غير صالحة للمراجعة');
}
$feePercentage = trim($request->post('fee_percentage', ''));
$boardDecisionNumber = trim($request->post('board_decision_number', ''));
$boardDecisionDate = trim($request->post('board_decision_date', ''));
$boardNotes = trim($request->post('board_notes', ''));
if ($feePercentage === '' || !is_numeric($feePercentage)) {
return $this->redirect("/divorce/{$id}")->withError('يجب تحديد نسبة الرسوم');
}
$feePercentage = (string) $feePercentage;
$member = $db->selectOne("SELECT * FROM members WHERE id = ?", [(int) $case['member_id']]);
$membershipValue = $member['membership_value'] ?? '0.00';
// Calculate fees: percentage * membership_value + form fee (570) + annual subscription
$percentageFee = bcdiv(bcmul($membershipValue, $feePercentage, 4), '100', 2);
$formFee = DivorceFeeCalculator::getFormFee();
$annualSub = DivorceFeeCalculator::getAnnualSubscription();
$totalFee = bcadd(bcadd($percentageFee, $formFee, 2), $annualSub, 2);
$db->update('divorce_cases', [
'fee_percentage' => $feePercentage,
'fee_amount' => $percentageFee,
'form_fee' => $formFee,
'annual_subscription_fee' => $annualSub,
'total_fee' => $totalFee,
'board_decision_number' => $boardDecisionNumber ?: null,
'board_decision_date' => $boardDecisionDate ?: null,
'board_notes' => $boardNotes ?: null,
'status' => 'board_approved',
'updated_at' => date('Y-m-d H:i:s'),
], '`id` = ?', [(int) $id]);
// Auto-send payment request to cashier
$breakdown = [ $breakdown = [
'📋 نوع الحالة: ' . $caseTypeLabel, 'قيمة العضوية: ' . money($membershipValue),
'💰 قيمة العضوية: ' . money($feeCalc['membership_value']), 'النسبة المقررة: ' . $feePercentage . '%',
'📊 النسبة: ' . $feeCalc['fee_percentage'] . '%', 'رسوم الطلاق: ' . money($percentageFee),
'💵 رسوم الطلاق: ' . money($feeCalc['fee_amount']), 'رسوم استمارة (570): ' . money($formFee),
'📝 رسوم استمارة نقل: ' . money($feeCalc['form_fee']), 'اشتراك سنوي: ' . money($annualSub),
'═══════════════════════════', '═══════════════════════════',
'💵 الإجمالي: ' . money($amount), 'الإجمالي: ' . money($totalFee),
]; ];
$result = PaymentRequestService::createRequest([ PaymentRequestService::createRequest([
'member_id' => (int) $memberId, 'member_id' => (int) $case['member_id'],
'amount' => $amount, 'amount' => $totalFee,
'payment_type' => 'divorce_fee', 'payment_type' => 'divorce_fee',
'related_entity_type' => 'divorce_cases', 'related_entity_type' => 'divorce_cases',
'related_entity_id' => (int) $case->id, 'related_entity_id' => (int) $id,
'description_ar' => 'رسوم طلاق — حالة #' . $case->id, 'description_ar' => 'رسوم طلاق — حالة #' . $id . ' (قرار مجلس الأمناء)',
'notes' => json_encode(['fee_breakdown' => $breakdown], JSON_UNESCAPED_UNICODE), 'notes' => json_encode(['fee_breakdown' => $breakdown], JSON_UNESCAPED_UNICODE),
]); ]);
if ($result['success']) { EventBus::dispatch('divorce.board_approved', ['case_id' => (int) $id, 'fee_percentage' => $feePercentage]);
return $this->redirect("/divorce/{$case->id}")->withSuccess(
'تم تسجيل حالة الطلاق وإرسال طلب الدفع للخزينة — النوع: ' . DivorceCase::getCaseTypeLabel($feeCalc['case_type']) return $this->redirect("/divorce/{$id}")->withSuccess(
. ' — الرسوم: ' . money($amount) . ' — رقم الطلب: ' . $result['request_number'] 'تم اعتماد مجلس الأمناء — النسبة: ' . $feePercentage . '% — الإجمالي: ' . money($totalFee) . ' — تم إرسال طلب الدفع للخزينة'
); );
} }
return $this->redirect("/divorce/{$case->id}")->withError( public function boardReject(Request $request, string $id): Response
'تم تسجيل الحالة لكن فشل إنشاء طلب الدفع: ' . ($result['error'] ?? 'خطأ غير معروف') {
); $db = App::getInstance()->db();
$case = $db->selectOne("SELECT * FROM divorce_cases WHERE id = ?", [(int) $id]);
if (!$case || $case['status'] !== 'board_review') {
return $this->redirect('/divorce')->withError('الحالة غير صالحة');
} }
return $this->redirect("/divorce/{$case->id}")->withSuccess('تم تسجيل حالة الطلاق — النوع: ' . DivorceCase::getCaseTypeLabel($feeCalc['case_type']) . ' — الرسوم: ' . money($feeCalc['total_fee'])); $boardNotes = trim($request->post('board_notes', ''));
$db->update('divorce_cases', [
'status' => 'rejected',
'board_notes' => $boardNotes ?: 'مرفوض من مجلس الأمناء',
'updated_at' => date('Y-m-d H:i:s'),
], '`id` = ?', [(int) $id]);
EventBus::dispatch('divorce.rejected', ['case_id' => (int) $id]);
return $this->redirect("/divorce/{$id}")->withSuccess('تم رفض طلب الطلاق');
} }
public function show(Request $request, string $id): Response public function show(Request $request, string $id): Response
...@@ -116,24 +196,17 @@ class DivorceController extends Controller ...@@ -116,24 +196,17 @@ class DivorceController extends Controller
$db = App::getInstance()->db(); $db = App::getInstance()->db();
$case = $db->selectOne( $case = $db->selectOne(
"SELECT dc.*, m.full_name_ar as member_name, m.membership_number, m.membership_value, "SELECT dc.*, m.full_name_ar as member_name, m.membership_number, m.membership_value,
s.full_name_ar as spouse_name s.full_name_ar as spouse_name, q.name_ar as qualification_name
FROM divorce_cases dc JOIN members m ON m.id = dc.member_id JOIN spouses s ON s.id = dc.spouse_id WHERE dc.id = ?", FROM divorce_cases dc
JOIN members m ON m.id = dc.member_id
JOIN spouses s ON s.id = dc.spouse_id
LEFT JOIN qualifications q ON q.id = dc.spouse_qualification_id
WHERE dc.id = ?",
[(int) $id] [(int) $id]
); );
if (!$case) return $this->redirect('/divorce')->withError('الحالة غير موجودة'); if (!$case) return $this->redirect('/divorce')->withError('الحالة غير موجودة');
// Compute fee breakdown from stored data return $this->view('Divorce.Views.show', ['case' => $case]);
$membershipValue = $case['membership_value'] ?? '0.00';
$feePercentage = $case['fee_percentage'] ?? '0';
$percentageFee = bcdiv(bcmul($membershipValue, (string) $feePercentage, 4), '100', 2);
$totalFee = $case['fee_amount'] ?? '0.00';
$formFee = bcsub($totalFee, $percentageFee, 2);
return $this->view('Divorce.Views.show', [
'case' => $case,
'percentageFee' => $percentageFee,
'formFee' => $formFee,
]);
} }
public function pay(Request $request, string $id): Response public function pay(Request $request, string $id): Response
...@@ -141,11 +214,14 @@ class DivorceController extends Controller ...@@ -141,11 +214,14 @@ class DivorceController extends Controller
$db = App::getInstance()->db(); $db = App::getInstance()->db();
$case = $db->selectOne("SELECT * FROM divorce_cases WHERE id = ?", [(int) $id]); $case = $db->selectOne("SELECT * FROM divorce_cases WHERE id = ?", [(int) $id]);
if (!$case) return $this->redirect('/divorce')->withError('الحالة غير موجودة'); if (!$case) return $this->redirect('/divorce')->withError('الحالة غير موجودة');
if ($case['status'] === 'completed' || $case['status'] === 'fee_paid') { if (in_array($case['status'], ['completed', 'fee_paid'], true)) {
return $this->redirect("/divorce/{$id}")->withError('تم دفع الرسوم مسبقاً'); return $this->redirect("/divorce/{$id}")->withError('تم دفع الرسوم مسبقاً');
} }
if ($case['status'] !== 'board_approved') {
return $this->redirect("/divorce/{$id}")->withError('يجب اعتماد مجلس الأمناء أولاً');
}
$amount = $case['fee_amount'] ?? '0.00'; $amount = $case['total_fee'] ?? $case['fee_amount'] ?? '0.00';
if (bccomp((string) $amount, '0', 2) <= 0) { if (bccomp((string) $amount, '0', 2) <= 0) {
return $this->redirect("/divorce/{$id}")->withError('لا توجد رسوم مطلوبة'); return $this->redirect("/divorce/{$id}")->withError('لا توجد رسوم مطلوبة');
} }
...@@ -178,16 +254,16 @@ class DivorceController extends Controller ...@@ -178,16 +254,16 @@ class DivorceController extends Controller
{ {
$db = App::getInstance()->db(); $db = App::getInstance()->db();
$case = $db->selectOne("SELECT * FROM divorce_cases WHERE id = ?", [(int) $id]); $case = $db->selectOne("SELECT * FROM divorce_cases WHERE id = ?", [(int) $id]);
if (!$case || $case['status'] === 'completed') return $this->redirect('/divorce')->withError('الحالة غير صالحة'); if (!$case || !in_array($case['status'], ['board_approved', 'fee_paid'], true)) {
return $this->redirect('/divorce')->withError('الحالة غير صالحة — يجب اعتماد مجلس الأمناء والسداد أولاً');
}
$employee = App::getInstance()->currentEmployee(); $employee = App::getInstance()->currentEmployee();
$db->beginTransaction(); $db->beginTransaction();
try { try {
// Archive snapshot
$snapshotId = ArchiveService::takeSnapshot('members', (int) $case['member_id'], 'divorce', 'طلاق — حالة #' . $id); $snapshotId = ArchiveService::takeSnapshot('members', (int) $case['member_id'], 'divorce', 'طلاق — حالة #' . $id);
// Create new member for spouse
$spouse = $db->selectOne("SELECT * FROM spouses WHERE id = ?", [(int) $case['spouse_id']]); $spouse = $db->selectOne("SELECT * FROM spouses WHERE id = ?", [(int) $case['spouse_id']]);
$member = $db->selectOne("SELECT * FROM members WHERE id = ?", [(int) $case['member_id']]); $member = $db->selectOne("SELECT * FROM members WHERE id = ?", [(int) $case['member_id']]);
...@@ -204,9 +280,11 @@ class DivorceController extends Controller ...@@ -204,9 +280,11 @@ class DivorceController extends Controller
'membership_type' => 'working', 'membership_type' => 'working',
'member_category' => 'working_member', 'member_category' => 'working_member',
'status' => 'active', 'status' => 'active',
'qualification_id' => $spouse['qualification_id'] ?? $member['qualification_id'], 'qualification_id' => $case['spouse_qualification_id'] ?? $spouse['qualification_id'] ?? $member['qualification_id'],
'phone_mobile' => $spouse['mobile'] ?? $member['phone_mobile'], 'phone_mobile' => $spouse['mobile'] ?? $member['phone_mobile'],
'membership_value' => $member['membership_value'], 'membership_value' => $member['membership_value'],
'transferred_from_divorce_id' => (int) $id,
'original_membership_number' => $member['membership_number'],
'created_at' => date('Y-m-d H:i:s'), 'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'), 'updated_at' => date('Y-m-d H:i:s'),
'created_by' => $employee ? (int) $employee->id : null, 'created_by' => $employee ? (int) $employee->id : null,
...@@ -214,13 +292,15 @@ class DivorceController extends Controller ...@@ -214,13 +292,15 @@ class DivorceController extends Controller
$newNumber = MemberNumberGenerator::assign($newMemberId); $newNumber = MemberNumberGenerator::assign($newMemberId);
// Archive spouse // Archive spouse on original member
$db->update('spouses', ['status' => 'divorced', 'is_archived' => 1, 'archived_at' => date('Y-m-d H:i:s')], '`id` = ?', [(int) $case['spouse_id']]); $db->update('spouses', ['status' => 'divorced', 'is_archived' => 1, 'archived_at' => date('Y-m-d H:i:s')], '`id` = ?', [(int) $case['spouse_id']]);
// Update case // Update case with new membership references
$db->update('divorce_cases', [ $db->update('divorce_cases', [
'spouse_new_member_id' => $newMemberId, 'spouse_new_member_id' => $newMemberId,
'spouse_new_membership_number' => $newNumber, 'spouse_new_membership_number' => $newNumber,
'original_member_id' => (int) $case['member_id'],
'original_membership_number' => $member['membership_number'],
'archive_snapshot_id' => $snapshotId, 'archive_snapshot_id' => $snapshotId,
'status' => 'completed', 'status' => 'completed',
'updated_at' => date('Y-m-d H:i:s'), 'updated_at' => date('Y-m-d H:i:s'),
......
...@@ -16,10 +16,14 @@ class DivorceCase extends Model ...@@ -16,10 +16,14 @@ class DivorceCase extends Model
protected static bool $dispatchEvents = true; protected static bool $dispatchEvents = true;
protected static array $fillable = [ protected static array $fillable = [
'member_id', 'spouse_id', 'divorce_date', 'divorce_case_type', 'member_id', 'spouse_id', 'divorce_date', 'divorce_certificate_path',
'spouse_qualification_id', 'divorce_case_type',
'request_date', 'membership_acquisition_date', 'years_of_membership', 'request_date', 'membership_acquisition_date', 'years_of_membership',
'has_children_on_membership', 'fee_percentage', 'fee_amount', 'has_children_on_membership', 'fee_percentage', 'fee_amount',
'annual_subscription_fee', 'form_fee', 'total_fee',
'board_decision_number', 'board_decision_date', 'board_notes',
'spouse_new_member_id', 'spouse_new_membership_number', 'spouse_new_member_id', 'spouse_new_membership_number',
'original_member_id', 'original_membership_number',
'children_assignment_json', 'archive_snapshot_id', 'children_assignment_json', 'archive_snapshot_id',
'workflow_instance_id', 'status', 'notes', 'workflow_instance_id', 'status', 'notes',
]; ];
......
...@@ -6,6 +6,8 @@ return [ ...@@ -6,6 +6,8 @@ return [
['GET', '/divorce/create/{memberId}', 'Divorce\Controllers\DivorceController@create', ['auth'], 'transfer.initiate'], ['GET', '/divorce/create/{memberId}', 'Divorce\Controllers\DivorceController@create', ['auth'], 'transfer.initiate'],
['POST', '/divorce/store/{memberId}', 'Divorce\Controllers\DivorceController@store', ['auth', 'csrf'], 'transfer.initiate'], ['POST', '/divorce/store/{memberId}', 'Divorce\Controllers\DivorceController@store', ['auth', 'csrf'], 'transfer.initiate'],
['GET', '/divorce/{id}', 'Divorce\Controllers\DivorceController@show', ['auth'], 'transfer.view'], ['GET', '/divorce/{id}', 'Divorce\Controllers\DivorceController@show', ['auth'], 'transfer.view'],
['POST', '/divorce/{id}/board-approve', 'Divorce\Controllers\DivorceController@boardApprove', ['auth', 'csrf'], 'transfer.approve'],
['POST', '/divorce/{id}/board-reject', 'Divorce\Controllers\DivorceController@boardReject', ['auth', 'csrf'], 'transfer.approve'],
['POST', '/divorce/{id}/pay', 'Divorce\Controllers\DivorceController@pay', ['auth', 'csrf'], 'payment.collect'], ['POST', '/divorce/{id}/pay', 'Divorce\Controllers\DivorceController@pay', ['auth', 'csrf'], 'payment.collect'],
['POST', '/divorce/{id}/complete', 'Divorce\Controllers\DivorceController@complete',['auth', 'csrf'], 'transfer.approve'], ['POST', '/divorce/{id}/complete', 'Divorce\Controllers\DivorceController@complete', ['auth', 'csrf'], 'transfer.approve'],
]; ];
\ No newline at end of file
...@@ -5,11 +5,35 @@ namespace App\Modules\Divorce\Services; ...@@ -5,11 +5,35 @@ namespace App\Modules\Divorce\Services;
use App\Core\App; use App\Core\App;
use App\Modules\Rules\Services\RuleEngine; use App\Modules\Rules\Services\RuleEngine;
use App\Modules\ServiceCatalog\Models\ServicePrice;
final class DivorceFeeCalculator final class DivorceFeeCalculator
{ {
public static function getFormFee(): string
{
$feeData = RuleEngine::get('FORM_TRANSFER_FEE');
if ($feeData && isset($feeData['amount'])) {
return $feeData['amount'];
}
return ServicePrice::getPrice('SVC_ADDITION_FORM', '570.00');
}
public static function getAnnualSubscription(): string
{
$month = (int) date('n');
$year = (int) date('Y');
$fy = $month >= 7 ? $year . '/' . ($year + 1) : ($year - 1) . '/' . $year;
$ratesData = RuleEngine::get('membership.annual_rates.' . $fy);
$childRate = $ratesData['child'] ?? '222';
$devFee = $ratesData['dev'] ?? '35';
return bcadd($childRate, $devFee, 2);
}
/** /**
* Determine divorce case type and calculate fee. * Validate eligibility and determine case type (without calculating final fee —
* the board sets the percentage).
*/ */
public static function calculate(int $memberId, int $spouseId, string $divorceDate): array public static function calculate(int $memberId, int $spouseId, string $divorceDate): array
{ {
...@@ -52,46 +76,18 @@ final class DivorceFeeCalculator ...@@ -52,46 +76,18 @@ final class DivorceFeeCalculator
return ['success' => false, 'error' => "الحد الأدنى لسنوات العضوية {$minYears} سنوات (يُعفى في حالة وجود أبناء)"]; return ['success' => false, 'error' => "الحد الأدنى لسنوات العضوية {$minYears} سنوات (يُعفى في حالة وجود أبناء)"];
} }
// Determine case type and fee // Determine case type
$caseType = 'joined_after'; // default: most common $caseType = 'joined_after';
$feePercentage = '50.00';
$feeType = 'acquired_member';
// Case 1: Both working before marriage
// Simplified detection: if spouse join_date == member creation date (same form)
$memberCreatedDate = substr($memberCreated, 0, 10); $memberCreatedDate = substr($memberCreated, 0, 10);
$spouseJoinDateStr = substr($spouseJoinDate, 0, 10); $spouseJoinDateStr = substr($spouseJoinDate, 0, 10);
if ($memberCreatedDate === $spouseJoinDateStr) { if ($memberCreatedDate === $spouseJoinDateStr) {
// Could be Case 2: same form
$sameFormData = RuleEngine::get('DIVORCE_SAME_FORM_FEE');
$caseType = 'same_form'; $caseType = 'same_form';
$feePercentage = $sameFormData['percentage'] ?? '10.00';
$feeType = $sameFormData['treat_as'] ?? 'membership_basis';
} else {
// Case 3: joined after
$joinedAfterData = RuleEngine::get('DIVORCE_JOINED_AFTER_FEE');
$caseType = 'joined_after';
$feePercentage = $joinedAfterData['percentage'] ?? '50.00';
$feeType = $joinedAfterData['treat_as'] ?? 'acquired_member';
} }
$feeAmount = bcdiv(bcmul($membershipValue, $feePercentage, 4), '100', 2);
// Form fee
$formFeeData = RuleEngine::get('FORM_TRANSFER_FEE');
$formFee = $formFeeData['amount'] ?? '570.00';
$totalFee = bcadd($feeAmount, $formFee, 2);
return [ return [
'success' => true, 'success' => true,
'case_type' => $caseType, 'case_type' => $caseType,
'fee_type' => $feeType,
'fee_percentage' => $feePercentage,
'fee_amount' => $feeAmount,
'form_fee' => $formFee,
'total_fee' => $totalFee,
'membership_value' => $membershipValue, 'membership_value' => $membershipValue,
'years_of_membership' => $yearsMembership, 'years_of_membership' => $yearsMembership,
'has_children' => $hasChildren, 'has_children' => $hasChildren,
......
<?php $__template->layout('Layout.main'); ?> <?php $__template->layout('Layout.main'); ?>
<?php $__template->section('title'); ?>تسجيل حالة طلاق — <?= e($member['full_name_ar']) ?><?php $__template->endSection(); ?> <?php $__template->section('title'); ?>تسجيل حالة طلاق — <?= e($member['full_name_ar']) ?><?php $__template->endSection(); ?>
<?php $__template->section('content'); ?> <?php $__template->section('content'); ?>
<form method="POST" action="/divorce/store/<?= (int) $member['id'] ?>">
<div class="card" style="margin-bottom:15px;padding:15px;display:flex;justify-content:space-between;align-items:center;">
<div>
<strong>العضو:</strong> <?= e($member['full_name_ar']) ?>
&nbsp;|&nbsp; <strong>رقم العضوية:</strong> <?= e($member['membership_number'] ?? 'لم يُحدد') ?>
&nbsp;|&nbsp; <strong>قيمة العضوية:</strong> <span style="color:#0D7377;font-weight:700;"><?= money($member['membership_value'] ?? '0') ?></span>
</div>
<a href="/members/<?= (int) $member['id'] ?>" class="btn btn-outline">← العودة للعضو</a>
</div>
<form method="POST" action="/divorce/store/<?= (int) $member['id'] ?>" enctype="multipart/form-data">
<?= csrf_field() ?> <?= csrf_field() ?>
<div class="card" style="padding:20px;margin-bottom:20px;">
<div style="display:grid;grid-template-columns:1fr 1fr;gap:15px;"> <div class="card" style="margin-bottom:20px;">
<div style="padding:15px 20px;border-bottom:1px solid #E5E7EB;"><h3 style="margin:0;color:#DC2626;">بيانات الطلاق</h3></div>
<div style="padding:20px;display:grid;grid-template-columns:1fr 1fr;gap:15px;">
<div class="form-group"> <div class="form-group">
<label class="form-label">الزوج/الزوجة <span style="color:#DC2626;">*</span></label> <label class="form-label">الزوج/الزوجة <span style="color:#DC2626;">*</span></label>
<select name="spouse_id" class="form-select" required> <select name="spouse_id" class="form-select" required>
...@@ -16,6 +28,21 @@ ...@@ -16,6 +28,21 @@
<label class="form-label">تاريخ الطلاق <span style="color:#DC2626;">*</span></label> <label class="form-label">تاريخ الطلاق <span style="color:#DC2626;">*</span></label>
<input type="date" name="divorce_date" class="form-input" required max="<?= e(date('Y-m-d')) ?>"> <input type="date" name="divorce_date" class="form-input" required max="<?= e(date('Y-m-d')) ?>">
</div> </div>
<div class="form-group">
<label class="form-label">قسيمة الطلاق (صورة/ملف) <span style="color:#DC2626;">*</span></label>
<input type="file" name="divorce_certificate" class="form-input" required accept=".pdf,.jpg,.jpeg,.png">
<small style="color:#6B7280;">PDF أو صورة — الحد الأقصى 5 ميجا</small>
</div>
<div class="form-group">
<label class="form-label">المؤهل <span style="color:#DC2626;">*</span></label>
<select name="spouse_qualification_id" class="form-select" required>
<option value="">-- اختر المؤهل --</option>
<?php foreach ($qualifications as $q): ?>
<option value="<?= (int) $q['id'] ?>"><?= e($q['name_ar']) ?></option>
<?php endforeach; ?>
</select>
<small style="color:#6B7280;">المؤهل يحدد نسبة الرسوم من قيمة العضوية</small>
</div>
<div class="form-group" style="grid-column:1/-1;"> <div class="form-group" style="grid-column:1/-1;">
<label class="form-label">ملاحظات</label> <label class="form-label">ملاحظات</label>
<textarea name="notes" class="form-textarea" rows="3"></textarea> <textarea name="notes" class="form-textarea" rows="3"></textarea>
...@@ -23,23 +50,21 @@ ...@@ -23,23 +50,21 @@
</div> </div>
</div> </div>
<!-- Fee & Payment --> <div class="card" style="padding:20px;margin-bottom:20px;background:#FEF3C7;border:2px solid #F59E0B;">
<div class="card" style="padding:20px;margin-bottom:20px;background:#FFF7ED;border:2px solid #F59E0B;"> <h4 style="margin:0 0 10px;color:#D97706;">مسار الإجراء</h4>
<h4 style="margin:0 0 15px;color:#D97706;">رسوم الإجراء</h4> <ol style="margin:0;padding-right:20px;font-size:13px;color:#6B7280;line-height:2;">
<p style="font-size:13px;color:#6B7280;margin-bottom:15px;">سيتم احتساب الرسوم تلقائياً (رسوم استمارة + نسبة من قيمة العضوية حسب نوع الحالة).<br>قيمة العضوية: <strong style="color:#0D7377;"><?= money($member['membership_value'] ?? '0') ?></strong></p> <li>تقديم الطلب مع قسيمة الطلاق والمؤهل</li>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:15px;"> <li>إرسال الطلب لمجلس الأمناء للمراجعة</li>
<div class="form-group"> <li>مجلس الأمناء يحدد نسبة الرسوم من قيمة العضوية حسب المؤهل</li>
<label class="form-label">طريقة الدفع <span style="color:#DC2626;">*</span></label> <li>احتساب الرسوم: (النسبة × قيمة العضوية) + استمارة 570 + اشتراك سنوي</li>
<select name="payment_method" class="form-select" required> <li>إرسال المبلغ للخزينة والسداد</li>
<option value="cash">نقدي</option> <li>إنشاء عضوية جديدة مستقلة للمطلقة</li>
<option value="visa">فيزا</option> </ol>
<option value="bank_transfer">تحويل بنكي</option>
</select>
</div>
</div>
</div> </div>
<button type="submit" class="btn btn-primary" onclick="return confirm('سيتم تسجيل حالة الطلاق وتحصيل الرسوم. متأكد؟')">تسجيل الطلاق وتحصيل الرسوم</button> <div style="display:flex;gap:10px;">
<button type="submit" class="btn btn-primary" onclick="return confirm('سيتم تسجيل طلب الطلاق وإرساله لمجلس الأمناء. متأكد؟')">تقديم طلب الطلاق</button>
<a href="/members/<?= (int) $member['id'] ?>" class="btn btn-outline">إلغاء</a> <a href="/members/<?= (int) $member['id'] ?>" class="btn btn-outline">إلغاء</a>
</div>
</form> </form>
<?php $__template->endSection(); ?> <?php $__template->endSection(); ?>
\ No newline at end of file
...@@ -14,8 +14,12 @@ ...@@ -14,8 +14,12 @@
<td><?= e($r['spouse_name']) ?></td> <td><?= e($r['spouse_name']) ?></td>
<td style="font-size:13px;"><?= e($r['divorce_date']) ?></td> <td style="font-size:13px;"><?= e($r['divorce_date']) ?></td>
<td style="font-size:13px;"><?= e(\App\Modules\Divorce\Models\DivorceCase::getCaseTypeLabel($r['divorce_case_type'])) ?></td> <td style="font-size:13px;"><?= e(\App\Modules\Divorce\Models\DivorceCase::getCaseTypeLabel($r['divorce_case_type'])) ?></td>
<td style="font-weight:600;"><?= money($r['fee_amount'] ?? '0') ?></td> <td style="font-weight:600;"><?= money($r['total_fee'] ?? $r['fee_amount'] ?? '0') ?></td>
<td><span style="color:<?= $r['status'] === 'completed' ? '#059669' : '#D97706' ?>;font-weight:600;"><?= $r['status'] === 'completed' ? 'مكتمل' : ($r['status'] === 'submitted' ? 'مقدّم' : $r['status']) ?></span></td> <?php
$sColor = match($r['status']) { 'completed' => '#059669', 'fee_paid' => '#7C3AED', 'board_approved' => '#2563EB', 'rejected' => '#DC2626', default => '#D97706' };
$sLabel = match($r['status']) { 'completed' => 'مكتمل', 'fee_paid' => 'تم السداد', 'board_approved' => 'معتمد', 'board_review' => 'في انتظار المجلس', 'rejected' => 'مرفوض', 'submitted' => 'مقدّم', default => $r['status'] };
?>
<td><span style="color:<?= $sColor ?>;font-weight:600;"><?= $sLabel ?></span></td>
<td><a href="/divorce/<?= (int) $r['id'] ?>" class="btn btn-sm btn-outline">عرض</a></td> <td><a href="/divorce/<?= (int) $r['id'] ?>" class="btn btn-sm btn-outline">عرض</a></td>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
......
<?php $__template->layout('Layout.main'); ?> <?php $__template->layout('Layout.main'); ?>
<?php $__template->section('title'); ?>حالة طلاق #<?= (int) $case['id'] ?><?php $__template->endSection(); ?> <?php $__template->section('title'); ?>حالة طلاق #<?= (int) $case['id'] ?><?php $__template->endSection(); ?>
<?php $__template->section('content'); ?> <?php $__template->section('content'); ?>
<?php
$statusColors = [
'board_review' => '#D97706',
'board_approved' => '#2563EB',
'fee_paid' => '#7C3AED',
'completed' => '#059669',
'rejected' => '#DC2626',
];
$statusLabels = [
'board_review' => 'في انتظار مجلس الأمناء',
'board_approved' => 'تم اعتماد مجلس الأمناء — في انتظار السداد',
'fee_paid' => 'تم السداد — في انتظار الإتمام',
'completed' => 'مكتمل',
'rejected' => 'مرفوض',
'submitted' => 'مقدّم',
];
$statusColor = $statusColors[$case['status']] ?? '#6B7280';
$statusLabel = $statusLabels[$case['status']] ?? $case['status'];
?>
<!-- Case Info -->
<div class="card" style="padding:20px;margin-bottom:20px;"> <div class="card" style="padding:20px;margin-bottom:20px;">
<div style="display:flex;justify-content:space-between;align-items:start;">
<table style="width:100%;max-width:600px;font-size:14px;"> <table style="width:100%;max-width:600px;font-size:14px;">
<tr><td style="padding:6px 0;color:#6B7280;width:35%;">العضو</td><td style="padding:6px 0;"><a href="/members/<?= (int) $case['member_id'] ?>" style="color:#0D7377;font-weight:600;"><?= e($case['member_name']) ?></a></td></tr> <tr><td style="padding:6px 0;color:#6B7280;width:35%;">العضو الأصلي</td><td style="padding:6px 0;"><a href="/members/<?= (int) $case['member_id'] ?>" style="color:#0D7377;font-weight:600;"><?= e($case['member_name']) ?></a> — رقم <?= e($case['membership_number']) ?></td></tr>
<tr><td style="padding:6px 0;color:#6B7280;">الزوج/ة</td><td style="padding:6px 0;font-weight:600;"><?= e($case['spouse_name']) ?></td></tr> <tr><td style="padding:6px 0;color:#6B7280;">الزوج/ة</td><td style="padding:6px 0;font-weight:600;"><?= e($case['spouse_name']) ?></td></tr>
<tr><td style="padding:6px 0;color:#6B7280;">تاريخ الطلاق</td><td style="padding:6px 0;"><?= e($case['divorce_date']) ?></td></tr> <tr><td style="padding:6px 0;color:#6B7280;">تاريخ الطلاق</td><td style="padding:6px 0;"><?= e($case['divorce_date']) ?></td></tr>
<tr><td style="padding:6px 0;color:#6B7280;">النوع</td><td style="padding:6px 0;font-weight:600;"><?= e(\App\Modules\Divorce\Models\DivorceCase::getCaseTypeLabel($case['divorce_case_type'])) ?></td></tr> <?php if (!empty($case['qualification_name'])): ?>
<tr><td style="padding:6px 0;color:#6B7280;">الحالة</td><td style="padding:6px 0;font-weight:700;color:<?= match($case['status']) { 'completed' => '#059669', 'fee_paid' => '#2563EB', default => '#D97706' } ?>;"><?= match($case['status']) { 'completed' => 'مكتمل', 'fee_paid' => 'تم الدفع', default => 'مقدّم' } ?></td></tr> <tr><td style="padding:6px 0;color:#6B7280;">المؤهل</td><td style="padding:6px 0;font-weight:600;"><?= e($case['qualification_name']) ?></td></tr>
<?php if ($case['spouse_new_membership_number']): ?><tr><td style="padding:6px 0;color:#6B7280;">رقم العضوية الجديد</td><td style="padding:6px 0;font-weight:700;color:#0D7377;font-size:20px;"><?= e($case['spouse_new_membership_number']) ?></td></tr><?php endif; ?> <?php endif; ?>
<?php if (!empty($case['divorce_certificate_path'])): ?>
<tr><td style="padding:6px 0;color:#6B7280;">قسيمة الطلاق</td><td style="padding:6px 0;"><a href="/<?= e($case['divorce_certificate_path']) ?>" target="_blank" style="color:#2563EB;">عرض المستند</a></td></tr>
<?php endif; ?>
<tr><td style="padding:6px 0;color:#6B7280;">قيمة العضوية</td><td style="padding:6px 0;font-weight:700;color:#0D7377;"><?= money($case['membership_value'] ?? '0') ?></td></tr>
<tr><td style="padding:6px 0;color:#6B7280;">الحالة</td><td style="padding:6px 0;font-weight:700;color:<?= $statusColor ?>;"><?= $statusLabel ?></td></tr>
<?php if ($case['spouse_new_membership_number']): ?>
<tr><td style="padding:6px 0;color:#6B7280;">رقم العضوية الجديد</td><td style="padding:6px 0;"><a href="/members/<?= (int) $case['spouse_new_member_id'] ?>" style="font-weight:800;font-size:20px;color:#0D7377;"><?= e($case['spouse_new_membership_number']) ?></a></td></tr>
<tr><td style="padding:6px 0;color:#6B7280;">محوّل من عضوية</td><td style="padding:6px 0;font-weight:600;"><?= e($case['original_membership_number'] ?? $case['membership_number']) ?></td></tr>
<?php endif; ?>
</table> </table>
<a href="/divorce" class="btn btn-outline" style="white-space:nowrap;">← قائمة الطلاق</a>
</div>
</div> </div>
<!-- Workflow Progress -->
<div class="card" style="margin-bottom:20px;padding:20px;">
<div style="display:flex;gap:5px;align-items:center;font-size:12px;">
<?php
$steps = [
['key' => 'board_review', 'label' => 'تقديم الطلب'],
['key' => 'board_approved', 'label' => 'قرار مجلس الأمناء'],
['key' => 'fee_paid', 'label' => 'السداد'],
['key' => 'completed', 'label' => 'إتمام العضوية'],
];
$statusOrder = ['board_review' => 1, 'board_approved' => 2, 'fee_paid' => 3, 'completed' => 4, 'rejected' => 0];
$currentOrder = $statusOrder[$case['status']] ?? 0;
foreach ($steps as $i => $step):
$stepOrder = $statusOrder[$step['key']] ?? 0;
$done = $currentOrder >= $stepOrder;
$bg = $done ? '#059669' : '#E5E7EB';
$color = $done ? '#FFF' : '#6B7280';
?>
<div style="flex:1;text-align:center;padding:8px 4px;background:<?= $bg ?>;color:<?= $color ?>;border-radius:6px;font-weight:<?= $done ? '600' : '400' ?>;"><?= $step['label'] ?></div>
<?php if ($i < count($steps) - 1): ?><div style="color:#9CA3AF;"></div><?php endif; ?>
<?php endforeach; ?>
</div>
</div>
<?php if ($case['status'] === 'board_review'): ?>
<!-- Board Approval Panel -->
<div class="card" style="margin-bottom:20px;border:2px solid #F59E0B;">
<div style="padding:15px 20px;border-bottom:1px solid #E5E7EB;background:#FEF3C7;">
<h3 style="margin:0;color:#D97706;font-size:15px;">قرار مجلس الأمناء</h3>
<p style="margin:5px 0 0;font-size:12px;color:#6B7280;">حدد النسبة من قيمة العضوية التي ستدفعها المطلقة حسب المؤهل</p>
</div>
<div style="padding:20px;">
<form method="POST" action="/divorce/<?= (int) $case['id'] ?>/board-approve">
<?= csrf_field() ?>
<div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:15px;margin-bottom:15px;">
<div class="form-group">
<label class="form-label">النسبة من قيمة العضوية (%) <span style="color:#DC2626;">*</span></label>
<input type="number" name="fee_percentage" class="form-input" required min="0" max="100" step="0.01" style="font-size:18px;font-weight:700;" placeholder="مثال: 50">
<small style="color:#6B7280;">قيمة العضوية: <?= money($case['membership_value'] ?? '0') ?></small>
</div>
<div class="form-group">
<label class="form-label">رقم قرار المجلس</label>
<input type="text" name="board_decision_number" class="form-input">
</div>
<div class="form-group">
<label class="form-label">تاريخ القرار</label>
<input type="date" name="board_decision_date" class="form-input" value="<?= e(date('Y-m-d')) ?>">
</div>
</div>
<div class="form-group" style="margin-bottom:15px;">
<label class="form-label">ملاحظات المجلس</label>
<textarea name="board_notes" class="form-textarea" rows="2"></textarea>
</div>
<div id="fee-preview" style="background:#F0FDF4;border:1px solid #059669;border-radius:8px;padding:15px;margin-bottom:15px;display:none;">
<strong style="color:#059669;">معاينة الرسوم:</strong>
<div style="margin-top:8px;font-size:13px;" id="fee-preview-content"></div>
</div>
<div style="display:flex;gap:10px;">
<button type="submit" class="btn btn-primary" onclick="return confirm('تأكيد اعتماد مجلس الأمناء وإرسال طلب الدفع للخزينة؟')">اعتماد وإرسال للخزينة</button>
</div>
</form>
<hr style="margin:20px 0;border-color:#FDE68A;">
<form method="POST" action="/divorce/<?= (int) $case['id'] ?>/board-reject">
<?= csrf_field() ?>
<div class="form-group" style="margin-bottom:10px;">
<label class="form-label" style="color:#DC2626;">سبب الرفض</label>
<textarea name="board_notes" class="form-textarea" rows="2" placeholder="سبب رفض الطلب..."></textarea>
</div>
<button type="submit" class="btn" style="background:#DC2626;color:#FFF;" onclick="return confirm('تأكيد رفض الطلب؟')">رفض الطلب</button>
</form>
</div>
</div>
<?php endif; ?>
<?php if (!empty($case['fee_percentage']) && in_array($case['status'], ['board_approved', 'fee_paid', 'completed'], true)): ?>
<!-- Fee Breakdown --> <!-- Fee Breakdown -->
<div class="card" style="margin-bottom:20px;"> <div class="card" style="margin-bottom:20px;">
<div style="padding:15px 20px;border-bottom:1px solid #E5E7EB;display:flex;align-items:center;gap:8px;"> <div style="padding:15px 20px;border-bottom:1px solid #E5E7EB;">
<i data-lucide="receipt" style="width:18px;height:18px;color:#D97706;"></i> <h3 style="margin:0;color:#D97706;font-size:15px;">تفصيل الرسوم (قرار مجلس الأمناء)</h3>
<h3 style="margin:0;color:#D97706;font-size:15px;">تفصيل الرسوم</h3>
</div> </div>
<div style="padding:20px;"> <div style="padding:20px;">
<table style="width:100%;max-width:500px;font-size:14px;"> <table style="width:100%;max-width:500px;font-size:14px;">
<?php if (!empty($case['membership_value']) && bccomp($case['membership_value'], '0', 2) > 0): ?>
<tr> <tr>
<td style="padding:8px 0;color:#6B7280;">قيمة العضوية</td> <td style="padding:8px 0;color:#6B7280;">قيمة العضوية</td>
<td style="padding:8px 0;font-weight:600;direction:ltr;text-align:left;"><?= money($case['membership_value']) ?></td> <td style="padding:8px 0;font-weight:600;direction:ltr;text-align:left;"><?= money($case['membership_value'] ?? '0') ?></td>
</tr> </tr>
<?php endif; ?>
<tr> <tr>
<td style="padding:8px 0;color:#6B7280;">نسبة رسوم الطلاق</td> <td style="padding:8px 0;color:#6B7280;">النسبة المقررة من المجلس</td>
<td style="padding:8px 0;font-weight:600;"><?= e($case['fee_percentage'] ?? '0') ?>%</td> <td style="padding:8px 0;font-weight:700;color:#D97706;"><?= e($case['fee_percentage']) ?>%</td>
</tr> </tr>
<tr style="border-top:1px solid #E5E7EB;"> <tr style="border-top:1px solid #E5E7EB;">
<td style="padding:10px 0;color:#6B7280;">رسوم الطلاق (<?= e($case['fee_percentage'] ?? '0') ?>% من قيمة العضوية)</td> <td style="padding:8px 0;color:#6B7280;">رسوم الطلاق (<?= e($case['fee_percentage']) ?>% × قيمة العضوية)</td>
<td style="padding:10px 0;font-weight:700;direction:ltr;text-align:left;color:#0D7377;"><?= money($percentageFee ?? '0') ?></td> <td style="padding:8px 0;font-weight:600;direction:ltr;text-align:left;"><?= money($case['fee_amount'] ?? '0') ?></td>
</tr>
<tr>
<td style="padding:8px 0;color:#6B7280;">رسوم استمارة (570)</td>
<td style="padding:8px 0;font-weight:600;direction:ltr;text-align:left;"><?= money($case['form_fee'] ?? '0') ?></td>
</tr> </tr>
<tr> <tr>
<td style="padding:8px 0;color:#6B7280;">رسوم الاستمارة</td> <td style="padding:8px 0;color:#6B7280;">اشتراك سنوي</td>
<td style="padding:8px 0;font-weight:600;direction:ltr;text-align:left;"><?= money($formFee ?? '0') ?></td> <td style="padding:8px 0;font-weight:600;direction:ltr;text-align:left;"><?= money($case['annual_subscription_fee'] ?? '0') ?></td>
</tr> </tr>
<tr style="border-top:2px solid #0D7377;"> <tr style="border-top:2px solid #0D7377;">
<td style="padding:12px 0;font-weight:700;font-size:16px;">الإجمالي المطلوب</td> <td style="padding:12px 0;font-weight:700;font-size:16px;">الإجمالي المطلوب</td>
<td style="padding:12px 0;font-weight:800;font-size:22px;color:#DC2626;direction:ltr;text-align:left;"><?= money($case['fee_amount'] ?? '0') ?></td> <td style="padding:12px 0;font-weight:800;font-size:22px;color:#DC2626;direction:ltr;text-align:left;"><?= money($case['total_fee'] ?? '0') ?></td>
</tr> </tr>
</table> </table>
<?php if (!empty($case['board_decision_number'])): ?>
<div style="margin-top:15px;font-size:12px;color:#6B7280;">
قرار رقم: <?= e($case['board_decision_number']) ?>
<?php if (!empty($case['board_decision_date'])): ?> — بتاريخ: <?= e($case['board_decision_date']) ?><?php endif; ?>
</div>
<?php endif; ?>
<?php if (!empty($case['board_notes'])): ?>
<div style="margin-top:8px;font-size:12px;color:#6B7280;">ملاحظات المجلس: <?= e($case['board_notes']) ?></div>
<?php endif; ?>
</div> </div>
</div> </div>
<?php endif; ?>
<?php if (!in_array($case['status'], ['completed', 'fee_paid']) && bccomp($case['fee_amount'] ?? '0', '0', 2) > 0): ?> <?php if ($case['status'] === 'board_approved'): ?>
<!-- Pay button -->
<div class="card" style="padding:20px;margin-bottom:20px;background:#FFF7ED;border:2px solid #F59E0B;"> <div class="card" style="padding:20px;margin-bottom:20px;background:#FFF7ED;border:2px solid #F59E0B;">
<h4 style="margin:0 0 15px;color:#D97706;">💰 دفع رسوم الطلاق</h4> <h4 style="margin:0 0 15px;color:#D97706;">دفع رسوم الطلاق</h4>
<form method="POST" action="/divorce/<?= (int) $case['id'] ?>/pay"> <form method="POST" action="/divorce/<?= (int) $case['id'] ?>/pay">
<?= csrf_field() ?> <?= csrf_field() ?>
<input type="hidden" name="amount" value="<?= e($case['fee_amount']) ?>">
<div style="display:flex;gap:10px;align-items:end;"> <div style="display:flex;gap:10px;align-items:end;">
<div class="form-group"><label class="form-label">المبلغ</label><input type="text" value="<?= money($case['fee_amount']) ?>" class="form-input" style="background:#F3F4F6;font-weight:700;font-size:18px;" readonly></div> <div class="form-group"><label class="form-label">المبلغ</label><input type="text" value="<?= money($case['total_fee'] ?? '0') ?>" class="form-input" style="background:#F3F4F6;font-weight:700;font-size:18px;" readonly></div>
<div class="form-group"><label class="form-label">طريقة الدفع</label><select name="payment_method" class="form-select"><option value="cash">نقدي</option><option value="visa">فيزا</option><option value="bank_transfer">تحويل</option></select></div> <div class="form-group"><label class="form-label">طريقة الدفع</label><select name="payment_method" class="form-select"><option value="cash">نقدي</option><option value="visa">فيزا</option><option value="bank_transfer">تحويل</option></select></div>
<button type="submit" class="btn btn-primary" style="padding:10px 25px;" onclick="return confirm('تأكيد الدفع؟')">💰 ادفع</button> <button type="submit" class="btn btn-primary" style="padding:10px 25px;" onclick="return confirm('تأكيد الدفع؟')">ادفع</button>
</div> </div>
</form> </form>
</div> </div>
<?php endif; ?> <?php endif; ?>
<?php if ($case['status'] !== 'completed'): ?> <?php if ($case['status'] === 'fee_paid'): ?>
<form method="POST" action="/divorce/<?= (int) $case['id'] ?>/complete"> <!-- Complete button -->
<div class="card" style="padding:20px;margin-bottom:20px;background:#F0FDF4;border:2px solid #059669;">
<h4 style="margin:0 0 10px;color:#059669;">إتمام حالة الطلاق</h4>
<p style="font-size:13px;color:#6B7280;margin-bottom:15px;">سيتم إنشاء عضوية جديدة مستقلة وأرشفة الزوج/ة من العضوية الأصلية.</p>
<form method="POST" action="/divorce/<?= (int) $case['id'] ?>/complete">
<?= csrf_field() ?> <?= csrf_field() ?>
<button type="submit" class="btn btn-primary" onclick="return confirm('⚠ إتمام حالة الطلاق — سيتم إنشاء عضوية جديدة. متأكد؟')">✅ إتمام حالة الطلاق</button> <button type="submit" class="btn btn-primary" onclick="return confirm('سيتم إنشاء عضوية جديدة مستقلة. متأكد؟')">إتمام حالة الطلاق وإنشاء العضوية</button>
</form> </form>
</div>
<?php endif; ?> <?php endif; ?>
<script>document.addEventListener('DOMContentLoaded', function() { if (typeof lucide !== 'undefined') lucide.createIcons(); });</script>
<?php if ($case['status'] === 'rejected'): ?>
<div class="card" style="padding:20px;margin-bottom:20px;background:#FEF2F2;border:2px solid #DC2626;">
<h4 style="margin:0 0 5px;color:#DC2626;">تم رفض الطلب</h4>
<?php if (!empty($case['board_notes'])): ?><p style="margin:0;font-size:13px;color:#6B7280;"><?= e($case['board_notes']) ?></p><?php endif; ?>
</div>
<?php endif; ?>
<?php $__template->endSection(); ?>
<?php $__template->section('scripts'); ?>
<script>
document.addEventListener('DOMContentLoaded', function() {
var percInput = document.querySelector('input[name="fee_percentage"]');
if (!percInput) return;
var membershipValue = <?= json_encode((float) ($case['membership_value'] ?? 0)) ?>;
var formFee = 570;
var annualSub = 257;
percInput.addEventListener('input', function() {
var perc = parseFloat(this.value) || 0;
var percFee = (membershipValue * perc / 100);
var total = percFee + formFee + annualSub;
var preview = document.getElementById('fee-preview');
var content = document.getElementById('fee-preview-content');
if (perc > 0) {
preview.style.display = 'block';
content.innerHTML =
'رسوم الطلاق (' + perc + '% × ' + membershipValue.toLocaleString() + '): <strong>' + percFee.toLocaleString() + ' ج.م</strong><br>' +
'رسوم استمارة: <strong>' + formFee.toLocaleString() + ' ج.م</strong><br>' +
'اشتراك سنوي: <strong>' + annualSub.toLocaleString() + ' ج.م</strong><br>' +
'<hr style="margin:5px 0;border-color:#059669;"><strong style="font-size:16px;color:#DC2626;">الإجمالي: ' + total.toLocaleString() + ' ج.م</strong>';
} else {
preview.style.display = 'none';
}
});
});
</script>
<?php $__template->endSection(); ?> <?php $__template->endSection(); ?>
...@@ -202,6 +202,17 @@ class MemberController extends Controller ...@@ -202,6 +202,17 @@ class MemberController extends Controller
} }
} }
// Check if this member was created via divorce transfer
$divorceTransfer = null;
if ($member->transferred_from_divorce_id) {
$divorceTransfer = $db->selectOne(
"SELECT dc.id, dc.original_membership_number, m.full_name_ar as original_member_name, m.id as original_member_id
FROM divorce_cases dc LEFT JOIN members m ON m.id = dc.original_member_id
WHERE dc.id = ?",
[(int) $member->transferred_from_divorce_id]
);
}
return $this->view('Members.Views.show', [ return $this->view('Members.Views.show', [
'member' => $member, 'member' => $member,
'branchName' => $branch['name_ar'] ?? '—', 'branchName' => $branch['name_ar'] ?? '—',
...@@ -217,6 +228,7 @@ class MemberController extends Controller ...@@ -217,6 +228,7 @@ class MemberController extends Controller
'pendingMembership' => $pendingMembership, 'pendingMembership' => $pendingMembership,
'pendingAdditions' => $pendingAdditions, 'pendingAdditions' => $pendingAdditions,
'isSuperAdmin' => self::isSuperAdmin(), 'isSuperAdmin' => self::isSuperAdmin(),
'divorceTransfer' => $divorceTransfer,
]); ]);
} }
......
...@@ -102,6 +102,9 @@ $canEdit = !$isLocked || ($isSuperAdmin ?? false); ...@@ -102,6 +102,9 @@ $canEdit = !$isLocked || ($isSuperAdmin ?? false);
<?php if ($member->full_name_en): ?><div style="color:#6B7280;font-size:14px;margin-bottom:8px;"><?= e($member->full_name_en) ?></div><?php endif; ?> <?php if ($member->full_name_en): ?><div style="color:#6B7280;font-size:14px;margin-bottom:8px;"><?= e($member->full_name_en) ?></div><?php endif; ?>
<div style="display:flex;gap:15px;flex-wrap:wrap;font-size:13px;color:#6B7280;margin-top:10px;"> <div style="display:flex;gap:15px;flex-wrap:wrap;font-size:13px;color:#6B7280;margin-top:10px;">
<?php if ($member->membership_number): ?><span>🪪 عضوية: <strong style="color:#0D7377;font-size:16px;"><?= e($member->membership_number) ?></strong></span><?php endif; ?> <?php if ($member->membership_number): ?><span>🪪 عضوية: <strong style="color:#0D7377;font-size:16px;"><?= e($member->membership_number) ?></strong></span><?php endif; ?>
<?php if (!empty($divorceTransfer)): ?>
<span style="background:#FEF3C7;padding:2px 8px;border-radius:10px;font-size:11px;">محوّل من عضوية: <a href="/members/<?= (int) $divorceTransfer['original_member_id'] ?>" style="color:#D97706;font-weight:700;"><?= e($divorceTransfer['original_membership_number']) ?></a> (<?= e($divorceTransfer['original_member_name'] ?? '') ?>)</span>
<?php endif; ?>
<span>📋 استمارة: <strong style="color:#D97706;"><?= e($member->form_number ?? '—') ?></strong></span> <span>📋 استمارة: <strong style="color:#D97706;"><?= e($member->form_number ?? '—') ?></strong></span>
<span>🏢 <?= e($branchName) ?></span> <span>🏢 <?= e($branchName) ?></span>
<span><?= $member->gender === 'male' ? '👨' : '👩' ?> <?= $member->getGenderLabel() ?></span> <span><?= $member->gender === 'male' ? '👨' : '👩' ?> <?= $member->getGenderLabel() ?></span>
......
<?php
declare(strict_types=1);
return function (\App\Core\Database $db): void {
$table = 'divorce_cases';
$columnsToAdd = [
'divorce_certificate_path' => "VARCHAR(500) NULL AFTER `divorce_date`",
'spouse_qualification_id' => "BIGINT UNSIGNED NULL AFTER `divorce_certificate_path`",
'board_decision_number' => "VARCHAR(50) NULL AFTER `fee_amount`",
'board_decision_date' => "DATE NULL AFTER `board_decision_number`",
'board_notes' => "TEXT NULL AFTER `board_decision_date`",
'annual_subscription_fee' => "DECIMAL(15,2) NULL DEFAULT 0 AFTER `fee_amount`",
'form_fee' => "DECIMAL(15,2) NULL DEFAULT 0 AFTER `annual_subscription_fee`",
'total_fee' => "DECIMAL(15,2) NULL DEFAULT 0 AFTER `form_fee`",
'original_member_id' => "BIGINT UNSIGNED NULL AFTER `spouse_new_membership_number`",
'original_membership_number' => "VARCHAR(20) NULL AFTER `original_member_id`",
];
foreach ($columnsToAdd as $col => $definition) {
$exists = $db->selectOne(
"SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = ? AND column_name = ?",
[$table, $col]
);
if (!$exists) {
$db->raw("ALTER TABLE `{$table}` ADD COLUMN `{$col}` {$definition}");
}
}
// Add transferred_from_divorce_id to members table for linking back
$exists = $db->selectOne(
"SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'members' AND column_name = 'transferred_from_divorce_id'",
[]
);
if (!$exists) {
$db->raw("ALTER TABLE `members` ADD COLUMN `transferred_from_divorce_id` BIGINT UNSIGNED NULL");
}
$exists = $db->selectOne(
"SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'members' AND column_name = 'original_membership_number'",
[]
);
if (!$exists) {
$db->raw("ALTER TABLE `members` ADD COLUMN `original_membership_number` VARCHAR(20) NULL");
}
};
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