feat(terminology): let each branch call its people what it actually calls them
The product calls a person who belongs to the organisation عضو and
everyone else غير عضو. That is only true for a club. The same software
runs inside residential compounds (مقيم / غير مقيم), on beaches and in
resorts (مشترك / زائر), and in hotels (نزيل / زائر), where every screen
read as though it had been written for somebody else.
The data model does not move: participants.membership_type still holds
'member' and 'non_member', every query and every enum is untouched, and
nothing about pricing or membership logic changes. Only the words shown
to a human do, and they are chosen per branch — one academy can run a
club and a compound at the same time.
Eight Arabic forms are stored per branch rather than derived, because
Arabic will not let you derive them: ال prefixes the noun in العضو but
the second word in غير العضو, and the plural of عضو is أعضاء while the
plural of مقيم is مقيمين. Everything a screen needs beyond those eight —
نوع العضوية, رقم العضوية, سعر العضو — composes from them in
Identity\Support\Terminology. Plurals are stored in the ـين form because
almost every site prints them after a preposition or in an idafa.
TerminologyService takes an explicit ?int $branchId like every other
domain service, so it stays callable from a queued notification or an
artisan report; terms()/term()/membership_label() in app/Helpers are the
adapter that reads BranchContext for a Blade file. Reads go through the
query builder rather than the model, because the sidebar consults this on
every page and BranchSetting's branch scope would filter a settings
screen editing branch B, viewed from branch A, down to nothing. The
service is bound scoped, so its memo lives exactly one request.
Presets (club, compound, resort, hotel, gym) fill the settings screen and
stay editable afterwards; the fields are stored in the existing
branch_settings table, so there is no schema change. An unconfigured
branch — and the public website, and a user in all-branches mode — gets
the default preset rather than blank labels. term() throws on an unknown
key rather than echoing it back, because a typo that printed
"membershipp_type" onto a receipt would survive review.
62 call sites converted across the sidebar, participant screens, the
registration wizard, the portal, reports, messaging, imports and the
printed card. New screen at /settings/terminology behind
permission:settings.manage.
Verified: 413 tests green, no failures.
Co-Authored-By:
Claude Opus 5 (1M context) <noreply@anthropic.com>
Showing
app/Helpers/terminology.php
0 → 100644
config/terminology.php
0 → 100644
Please register or sign in to comment