-
Mahmoud Aglan authored
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>
e8def3f5