Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
Clubphp
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Clubphp
Commits
e1b6511d
Commit
e1b6511d
authored
May 23, 2026
by
Mahmoud Aglan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
koko
parent
c4b271c6
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
77 additions
and
13 deletions
+77
-13
RetroactiveWizardController.php
...dules/Members/Controllers/RetroactiveWizardController.php
+1
-0
RetroactiveMembershipService.php
...Modules/Members/Services/RetroactiveMembershipService.php
+1
-0
retroactive-wizard.php
app/Modules/Members/Views/retroactive-wizard.php
+75
-13
No files found.
app/Modules/Members/Controllers/RetroactiveWizardController.php
View file @
e1b6511d
...
@@ -192,6 +192,7 @@ class RetroactiveWizardController extends Controller
...
@@ -192,6 +192,7 @@ class RetroactiveWizardController extends Controller
'full_name_ar'
=>
$post
[
"spouse_name_
{
$i
}
"
],
'full_name_ar'
=>
$post
[
"spouse_name_
{
$i
}
"
],
'national_id'
=>
$post
[
"spouse_nid_
{
$i
}
"
]
??
null
,
'national_id'
=>
$post
[
"spouse_nid_
{
$i
}
"
]
??
null
,
'date_of_birth'
=>
$post
[
"spouse_dob_
{
$i
}
"
]
??
null
,
'date_of_birth'
=>
$post
[
"spouse_dob_
{
$i
}
"
]
??
null
,
'nationality'
=>
$post
[
"spouse_nationality_
{
$i
}
"
]
??
'مصري'
,
'marriage_date'
=>
$post
[
"spouse_marriage_date_
{
$i
}
"
]
??
null
,
'marriage_date'
=>
$post
[
"spouse_marriage_date_
{
$i
}
"
]
??
null
,
'phone_mobile'
=>
$post
[
"spouse_phone_
{
$i
}
"
]
??
null
,
'phone_mobile'
=>
$post
[
"spouse_phone_
{
$i
}
"
]
??
null
,
'join_date'
=>
$post
[
"spouse_join_date_
{
$i
}
"
]
??
(
$post
[
'join_date'
]
??
date
(
'Y-m-d'
)),
'join_date'
=>
$post
[
"spouse_join_date_
{
$i
}
"
]
??
(
$post
[
'join_date'
]
??
date
(
'Y-m-d'
)),
...
...
app/Modules/Members/Services/RetroactiveMembershipService.php
View file @
e1b6511d
...
@@ -159,6 +159,7 @@ final class RetroactiveMembershipService
...
@@ -159,6 +159,7 @@ final class RetroactiveMembershipService
'full_name_ar'
=>
$spouse
[
'full_name_ar'
],
'full_name_ar'
=>
$spouse
[
'full_name_ar'
],
'national_id'
=>
self
::
emptyToNull
(
$spouse
[
'national_id'
]
??
null
),
'national_id'
=>
self
::
emptyToNull
(
$spouse
[
'national_id'
]
??
null
),
'date_of_birth'
=>
self
::
emptyToNull
(
$spouse
[
'date_of_birth'
]
??
null
),
'date_of_birth'
=>
self
::
emptyToNull
(
$spouse
[
'date_of_birth'
]
??
null
),
'nationality'
=>
self
::
emptyToNull
(
$spouse
[
'nationality'
]
??
null
)
??
'مصري'
,
'marriage_date'
=>
self
::
emptyToNull
(
$spouse
[
'marriage_date'
]
??
null
)
??
$joinDate
,
'marriage_date'
=>
self
::
emptyToNull
(
$spouse
[
'marriage_date'
]
??
null
)
??
$joinDate
,
'phone_mobile'
=>
self
::
emptyToNull
(
$spouse
[
'phone_mobile'
]
??
null
),
'phone_mobile'
=>
self
::
emptyToNull
(
$spouse
[
'phone_mobile'
]
??
null
),
'status'
=>
'active'
,
'status'
=>
'active'
,
...
...
app/Modules/Members/Views/retroactive-wizard.php
View file @
e1b6511d
...
@@ -646,32 +646,94 @@ function addCheque() {
...
@@ -646,32 +646,94 @@ function addCheque() {
</div>`
;
</div>`
;
}
}
// Spouses
// Spouses — Pricing Rules from system:
// SPOUSE_BASE_MEMBER_FEE: 15% of membership_value (1st spouse, base member)
// SPOUSE_2ND_FEE: 10% + 150/year
// SPOUSE_3RD_FEE: 20% + 200/year
// SPOUSE_4TH_FEE: 30% + 300/year
// SPOUSE_FOREIGN_FEE: 15% of membership_value (foreign nationality)
// SPOUSE_ACQUIRED_MEMBER_FEE: 50% (acquired member)
const
SPOUSE_FEE_RULES
=
{
1
:
{
pct
:
15
,
label
:
'زوجة أولى — 15%'
},
2
:
{
pct
:
10
,
annual
:
150
,
label
:
'زوجة ثانية — 10% + 150/سنة'
},
3
:
{
pct
:
20
,
annual
:
200
,
label
:
'زوجة ثالثة — 20% + 200/سنة'
},
4
:
{
pct
:
30
,
annual
:
300
,
label
:
'زوجة رابعة — 30% + 300/سنة'
},
};
const
SPOUSE_FOREIGN_PCT
=
15
;
function
calcSpouseFee
(
idx
)
{
const
membershipValue
=
parseFloat
(
document
.
querySelector
(
'[name=membership_value]'
).
value
)
||
150000
;
const
nationality
=
document
.
querySelector
(
`[name=spouse_nationality_
${
idx
}
]`
).
value
;
const
marriageDate
=
document
.
querySelector
(
`[name=spouse_marriage_date_
${
idx
}
]`
).
value
;
const
joinDate
=
document
.
querySelector
(
'[name=join_date]'
).
value
;
const
feeInput
=
document
.
querySelector
(
`[name=spouse_fee_
${
idx
}
]`
);
const
feeHint
=
document
.
getElementById
(
`spouseFeeHint
${
idx
}
`
);
let
fee
=
0
;
let
hint
=
''
;
if
(
nationality
&&
nationality
!==
'مصري'
&&
nationality
!==
'egyptian'
)
{
fee
=
membershipValue
*
(
SPOUSE_FOREIGN_PCT
/
100
);
hint
=
`أجنبي:
${
SPOUSE_FOREIGN_PCT
}
% ×
${
membershipValue
.
toLocaleString
()}
=
${
fee
.
toLocaleString
()}
ج.م`
;
}
else
{
const
rule
=
SPOUSE_FEE_RULES
[
idx
]
||
SPOUSE_FEE_RULES
[
4
];
fee
=
membershipValue
*
(
rule
.
pct
/
100
);
hint
=
`
${
rule
.
label
}
×
${
membershipValue
.
toLocaleString
()}
=
${
fee
.
toLocaleString
()}
ج.م`
;
if
(
rule
.
annual
&&
marriageDate
&&
joinDate
)
{
const
baseDate
=
new
Date
(
Math
.
max
(
new
Date
(
marriageDate
),
new
Date
(
joinDate
)));
const
now
=
new
Date
();
const
years
=
Math
.
max
(
1
,
Math
.
ceil
((
now
-
baseDate
)
/
(
365.25
*
24
*
60
*
60
*
1000
)));
const
annualTotal
=
rule
.
annual
*
years
;
fee
+=
annualTotal
;
hint
+=
` +
${
rule
.
annual
}
×
${
years
}
سنة =
${
fee
.
toLocaleString
()}
ج.م`
;
}
}
feeInput
.
value
=
fee
.
toFixed
(
2
);
if
(
feeHint
)
feeHint
.
textContent
=
hint
;
}
let
spouseIdx
=
0
;
let
spouseIdx
=
0
;
function
addSpouse
()
{
function
addSpouse
()
{
spouseIdx
++
;
spouseIdx
++
;
document
.
getElementById
(
'spouseCount'
).
value
=
spouseIdx
;
document
.
getElementById
(
'spouseCount'
).
value
=
spouseIdx
;
const
joinDate
=
document
.
querySelector
(
'[name=join_date]'
).
value
||
''
;
const
joinDate
=
document
.
querySelector
(
'[name=join_date]'
).
value
||
''
;
const
idx
=
spouseIdx
;
document
.
getElementById
(
'spousesList'
).
innerHTML
+=
`
document
.
getElementById
(
'spousesList'
).
innerHTML
+=
`
<div style="padding:12px;background:#F9FAFB;border-radius:8px;border:1px solid #E5E7EB;margin-bottom:10px;" id="spouseRow
${
spouseI
dx
}
">
<div style="padding:12px;background:#F9FAFB;border-radius:8px;border:1px solid #E5E7EB;margin-bottom:10px;" id="spouseRow
${
i
dx
}
">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;">
<span style="font-size:13px;font-weight:600;color:#374151;">زوجة #
${
spouseI
dx
}
</span>
<span style="font-size:13px;font-weight:600;color:#374151;">زوجة #
${
i
dx
}
</span>
<button type="button" onclick="document.getElementById('spouseRow
${
spouseI
dx
}
').remove()" style="padding:2px 8px;background:#FEE2E2;border:1px solid #FECACA;border-radius:4px;color:#DC2626;cursor:pointer;font-size:12px;">حذف</button>
<button type="button" onclick="document.getElementById('spouseRow
${
i
dx
}
').remove()" style="padding:2px 8px;background:#FEE2E2;border:1px solid #FECACA;border-radius:4px;color:#DC2626;cursor:pointer;font-size:12px;">حذف</button>
</div>
</div>
<div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px;">
<div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:10px;">
<div><label style="font-size:11px;color:#6B7280;">الاسم *</label><input type="text" name="spouse_name_
${
spouseIdx
}
" required class="form-input" style="width:100%;padding:6px 8px;border:1px solid #D1D5DB;border-radius:4px;font-size:12px;"></div>
<div><label style="font-size:11px;color:#6B7280;">الاسم *</label><input type="text" name="spouse_name_
${
idx
}
" required class="form-input" style="width:100%;padding:6px 8px;border:1px solid #D1D5DB;border-radius:4px;font-size:12px;"></div>
<div><label style="font-size:11px;color:#6B7280;">الرقم القومي</label><input type="text" name="spouse_nid_
${
spouseIdx
}
" class="form-input" style="width:100%;padding:6px 8px;border:1px solid #D1D5DB;border-radius:4px;font-size:12px;direction:ltr;"></div>
<div><label style="font-size:11px;color:#6B7280;">الرقم القومي</label><input type="text" name="spouse_nid_
${
idx
}
" class="form-input" style="width:100%;padding:6px 8px;border:1px solid #D1D5DB;border-radius:4px;font-size:12px;direction:ltr;"></div>
<div><label style="font-size:11px;color:#6B7280;">تاريخ الميلاد</label><input type="date" name="spouse_dob_
${
spouseIdx
}
" class="form-input" style="width:100%;padding:6px 8px;border:1px solid #D1D5DB;border-radius:4px;font-size:12px;"></div>
<div><label style="font-size:11px;color:#6B7280;">تاريخ الميلاد</label><input type="date" name="spouse_dob_
${
idx
}
" class="form-input" style="width:100%;padding:6px 8px;border:1px solid #D1D5DB;border-radius:4px;font-size:12px;"></div>
<div><label style="font-size:11px;color:#6B7280;">تاريخ الزواج *</label><input type="date" name="spouse_marriage_date_
${
spouseIdx
}
" required class="form-input" style="width:100%;padding:6px 8px;border:1px solid #D1D5DB;border-radius:4px;font-size:12px;"></div>
<div>
<div><label style="font-size:11px;color:#6B7280;">الهاتف</label><input type="text" name="spouse_phone_
${
spouseIdx
}
" class="form-input" style="width:100%;padding:6px 8px;border:1px solid #D1D5DB;border-radius:4px;font-size:12px;direction:ltr;"></div>
<label style="font-size:11px;color:#6B7280;">الجنسية *</label>
<div><label style="font-size:11px;color:#6B7280;">تاريخ الانضمام</label><input type="date" name="spouse_join_date_
${
spouseIdx
}
" value="
${
joinDate
}
" class="form-input" style="width:100%;padding:6px 8px;border:1px solid #D1D5DB;border-radius:4px;font-size:12px;"></div>
<select name="spouse_nationality_
${
idx
}
" class="form-input" style="width:100%;padding:6px 8px;border:1px solid #D1D5DB;border-radius:4px;font-size:12px;" onchange="calcSpouseFee(
${
idx
}
)">
<div><label style="font-size:11px;color:#6B7280;">رسوم الإضافة</label><input type="number" name="spouse_fee_
${
spouseIdx
}
" value="0" step="0.01" class="form-input" style="width:100%;padding:6px 8px;border:1px solid #D1D5DB;border-radius:4px;font-size:12px;"></div>
<option value="مصري">مصري</option>
<option value="أجنبي">أجنبي</option>
</select>
</div>
<div><label style="font-size:11px;color:#6B7280;">تاريخ الزواج *</label><input type="date" name="spouse_marriage_date_
${
idx
}
" required class="form-input" style="width:100%;padding:6px 8px;border:1px solid #D1D5DB;border-radius:4px;font-size:12px;" onchange="calcSpouseFee(
${
idx
}
)"></div>
<div><label style="font-size:11px;color:#6B7280;">الهاتف</label><input type="text" name="spouse_phone_
${
idx
}
" class="form-input" style="width:100%;padding:6px 8px;border:1px solid #D1D5DB;border-radius:4px;font-size:12px;direction:ltr;"></div>
<div><label style="font-size:11px;color:#6B7280;">تاريخ الانضمام</label><input type="date" name="spouse_join_date_
${
idx
}
" value="
${
joinDate
}
" class="form-input" style="width:100%;padding:6px 8px;border:1px solid #D1D5DB;border-radius:4px;font-size:12px;"></div>
<div>
<label style="font-size:11px;color:#6B7280;">رسوم الإضافة (ج.م)</label>
<input type="number" name="spouse_fee_
${
idx
}
" value="0" step="0.01" class="form-input" style="width:100%;padding:6px 8px;border:1px solid #D1D5DB;border-radius:4px;font-size:12px;">
<div id="spouseFeeHint
${
idx
}
" style="font-size:10px;color:#2563EB;margin-top:2px;"></div>
</div>
<div style="display:flex;align-items:end;">
<button type="button" onclick="calcSpouseFee(
${
idx
}
)" style="padding:5px 10px;background:#EFF6FF;border:1px solid #93C5FD;border-radius:4px;font-size:11px;cursor:pointer;color:#1D4ED8;">حساب الرسوم تلقائياً</button>
</div>
</div>
</div>
<div style="margin-top:8px;display:flex;align-items:center;gap:12px;">
<div style="margin-top:8px;display:flex;align-items:center;gap:12px;">
<label style="font-size:11px;color:#6B7280;display:flex;align-items:center;gap:4px;"><input type="checkbox" name="spouse_separate_fee_
${
spouseI
dx
}
" value="1"> رسوم إضافة منفصلة (ليست ضمن العضوية)</label>
<label style="font-size:11px;color:#6B7280;display:flex;align-items:center;gap:4px;"><input type="checkbox" name="spouse_separate_fee_
${
i
dx
}
" value="1"> رسوم إضافة منفصلة (ليست ضمن العضوية)</label>
<select name="spouse_pay_method_
${
spouseI
dx
}
" style="font-size:11px;padding:4px 8px;border:1px solid #D1D5DB;border-radius:4px;"><option value="cash">نقدي</option><option value="check">شيك</option></select>
<select name="spouse_pay_method_
${
i
dx
}
" style="font-size:11px;padding:4px 8px;border:1px solid #D1D5DB;border-radius:4px;"><option value="cash">نقدي</option><option value="check">شيك</option></select>
</div>
</div>
</div>`
;
</div>`
;
calcSpouseFee
(
idx
);
}
}
// Children
// Children
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment