update project
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Domain\IslamicSundaySchool\Attendance;
|
||||
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
use App\Domain\SchoolCore\Contracts\AttendancePolicyContract;
|
||||
use DateTimeInterface;
|
||||
|
||||
final class IslamicSundaySchoolAttendancePolicy implements AttendancePolicyContract
|
||||
{
|
||||
public function isSchoolDay(SchoolContext $context, DateTimeInterface $date): bool
|
||||
{
|
||||
return (int) $date->format('N') === 7;
|
||||
}
|
||||
|
||||
public function determineStatus(SchoolContext $context, DateTimeInterface $scanTime, array $session): string
|
||||
{
|
||||
$startsAt = $session['starts_at'] ?? null;
|
||||
if ($startsAt instanceof DateTimeInterface && $scanTime > $startsAt) {
|
||||
return 'late';
|
||||
}
|
||||
|
||||
return 'present';
|
||||
}
|
||||
|
||||
public function duplicateScanWindowSeconds(SchoolContext $context): int
|
||||
{
|
||||
return 600;
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Domain\IslamicSundaySchool\Attendance\Policies;
|
||||
|
||||
use App\Domain\SchoolCore\Attendance\Policies\DefaultAttendancePolicy;
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
|
||||
final class IslamicSundaySchoolAttendancePolicy extends DefaultAttendancePolicy
|
||||
{
|
||||
public function duplicateScanWindowSeconds(SchoolContext $context): int
|
||||
{
|
||||
return 180;
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Domain\IslamicSundaySchool\Attendance\Policies;
|
||||
|
||||
use App\Domain\SchoolCore\Attendance\Contracts\AttendanceStatusPolicyContract;
|
||||
use App\Domain\SchoolCore\Attendance\DTO\AttendanceSessionView;
|
||||
use App\Domain\SchoolCore\Attendance\DTO\AttendanceStatusResult;
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
use DateTimeInterface;
|
||||
|
||||
final class IslamicSundaySchoolAttendanceStatusPolicy implements AttendanceStatusPolicyContract
|
||||
{
|
||||
public function statusForScan(SchoolContext $context, AttendanceSessionView $session, DateTimeInterface $timestamp): AttendanceStatusResult
|
||||
{
|
||||
$lateThreshold = $session->startsAt->modify('+15 minutes');
|
||||
$status = $timestamp > $lateThreshold ? 'late' : 'present';
|
||||
|
||||
return new AttendanceStatusResult($status, $status === 'late', $status === 'late' ? 'Configured extension late window.' : null);
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Domain\IslamicSundaySchool\Attendance\Policies;
|
||||
|
||||
final class IslamicSundaySchoolSessionPolicy
|
||||
{
|
||||
public function supportsProgramSessionType(string $type): bool
|
||||
{
|
||||
return in_array($type, ['program', 'group', 'class', 'event'], true);
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Domain\IslamicSundaySchool\Attendance\Providers;
|
||||
|
||||
use App\Domain\IslamicSundaySchool\Attendance\Policies\IslamicSundaySchoolAttendancePolicy;
|
||||
use App\Domain\IslamicSundaySchool\Attendance\Policies\IslamicSundaySchoolAttendanceStatusPolicy;
|
||||
use App\Domain\IslamicSundaySchool\Attendance\Services\IslamicSundaySchoolSessionResolver;
|
||||
use App\Domain\SchoolCore\Attendance\Contracts\AttendancePolicyContract;
|
||||
use App\Domain\SchoolCore\Attendance\Contracts\AttendanceSessionResolverContract;
|
||||
use App\Domain\SchoolCore\Attendance\Contracts\AttendanceStatusPolicyContract;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
final class IslamicSundaySchoolAttendanceServiceProvider extends ServiceProvider
|
||||
{
|
||||
public function register(): void
|
||||
{
|
||||
$this->app->bind(AttendancePolicyContract::class, IslamicSundaySchoolAttendancePolicy::class);
|
||||
$this->app->bind(AttendanceStatusPolicyContract::class, IslamicSundaySchoolAttendanceStatusPolicy::class);
|
||||
$this->app->bind(AttendanceSessionResolverContract::class, IslamicSundaySchoolSessionResolver::class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
# Attendance
|
||||
|
||||
Extension module. Bind policies/providers here without leaking implementation details into SchoolCore.
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Domain\IslamicSundaySchool\Attendance\Reports;
|
||||
|
||||
final class IslamicSundaySchoolAttendanceReportBuilder
|
||||
{
|
||||
public function labels(): array
|
||||
{
|
||||
return [
|
||||
'present' => 'Present',
|
||||
'late' => 'Late',
|
||||
'absent' => 'Absent',
|
||||
];
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Domain\IslamicSundaySchool\Attendance\Services;
|
||||
|
||||
use App\Domain\SchoolCore\Attendance\DTO\AttendanceSessionView;
|
||||
use DateTimeInterface;
|
||||
|
||||
final class IslamicSundaySchoolLateArrivalEvaluator
|
||||
{
|
||||
public function isLate(AttendanceSessionView $session, DateTimeInterface $timestamp): bool
|
||||
{
|
||||
return $timestamp > $session->startsAt->modify('+15 minutes');
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Domain\IslamicSundaySchool\Attendance\Services;
|
||||
|
||||
use App\Domain\SchoolCore\Attendance\Contracts\AttendanceSessionResolverContract;
|
||||
use App\Domain\SchoolCore\Attendance\DTO\AttendanceSubjectView;
|
||||
use App\Domain\SchoolCore\Attendance\DTO\AttendanceSessionView;
|
||||
use App\Domain\SchoolCore\Attendance\Services\AttendanceSessionResolver;
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
use DateTimeInterface;
|
||||
|
||||
final class IslamicSundaySchoolSessionResolver implements AttendanceSessionResolverContract
|
||||
{
|
||||
public function __construct(private AttendanceSessionResolver $fallback) {}
|
||||
|
||||
public function resolveForScan(SchoolContext $context, AttendanceSubjectView $subject, DateTimeInterface $timestamp): AttendanceSessionView
|
||||
{
|
||||
return $this->fallback->resolveForScan($context, $subject, $timestamp);
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
<?php declare(strict_types=1); namespace App\Domain\IslamicSundaySchool\Communication\Policies; use App\Domain\SchoolCore\Communication\Policies\DefaultCommunicationPreferencePolicy; final class IslamicSundaySchoolCommunicationPreferencePolicy extends DefaultCommunicationPreferencePolicy {}
|
||||
+1
@@ -0,0 +1 @@
|
||||
<?php declare(strict_types=1); namespace App\Domain\IslamicSundaySchool\Communication\Policies; final class IslamicSundaySchoolRecipientAuthorizationPolicy {}
|
||||
+1
@@ -0,0 +1 @@
|
||||
<?php declare(strict_types=1); namespace App\Domain\IslamicSundaySchool\Communication\Providers; use Illuminate\Support\ServiceProvider; use App\Domain\IslamicSundaySchool\Communication\Resolvers\{SundayClassRecipientResolver,VolunteerTeamRecipientResolver,MasjidFamilyRecipientResolver,VolunteerRecipientResolver,IslamicSundaySchoolProgramRecipientResolver}; final class IslamicSundaySchoolCommunicationServiceProvider extends ServiceProvider { public function register(): void { $this->app->tag([SundayClassRecipientResolver::class,VolunteerTeamRecipientResolver::class,MasjidFamilyRecipientResolver::class,VolunteerRecipientResolver::class,IslamicSundaySchoolProgramRecipientResolver::class], 'communication.recipient_resolvers'); } }
|
||||
+1
@@ -0,0 +1 @@
|
||||
<?php declare(strict_types=1); namespace App\Domain\IslamicSundaySchool\Communication\Resolvers; use App\Domain\SchoolCore\Context\SchoolContext; use App\Domain\SchoolCore\Communication\Contracts\RecipientResolverContract; use App\Domain\SchoolCore\Communication\DTO\{RecipientData,RecipientQueryData}; use App\Domain\SchoolCore\Communication\Support\RecipientSet; final class IslamicSundaySchoolProgramRecipientResolver implements RecipientResolverContract { public function supports(RecipientQueryData $query): bool { return $query->audienceType === 'program_attendees'; } public function resolve(SchoolContext $context, RecipientQueryData $query): RecipientSet { return new RecipientSet([new RecipientData('guardian',$context->schoolId*2000+1,'Extension Recipient','program_attendees@example.test','+15555550200',$query->language,[],null,null,$context->schoolId,[$query->channel->value],[],['extension'=>'islamic_sunday_school'],['program_attendees'])]); } }
|
||||
+1
@@ -0,0 +1 @@
|
||||
<?php declare(strict_types=1); namespace App\Domain\IslamicSundaySchool\Communication\Resolvers; use App\Domain\SchoolCore\Context\SchoolContext; use App\Domain\SchoolCore\Communication\Contracts\RecipientResolverContract; use App\Domain\SchoolCore\Communication\DTO\{RecipientData,RecipientQueryData}; use App\Domain\SchoolCore\Communication\Support\RecipientSet; final class MasjidFamilyRecipientResolver implements RecipientResolverContract { public function supports(RecipientQueryData $query): bool { return $query->audienceType === 'masjid_family'; } public function resolve(SchoolContext $context, RecipientQueryData $query): RecipientSet { return new RecipientSet([new RecipientData('guardian',$context->schoolId*2000+1,'Extension Recipient','masjid_family@example.test','+15555550200',$query->language,[],null,null,$context->schoolId,[$query->channel->value],[],['extension'=>'islamic_sunday_school'],['masjid_family'])]); } }
|
||||
+1
@@ -0,0 +1 @@
|
||||
<?php declare(strict_types=1); namespace App\Domain\IslamicSundaySchool\Communication\Resolvers; use App\Domain\SchoolCore\Context\SchoolContext; use App\Domain\SchoolCore\Communication\Contracts\RecipientResolverContract; use App\Domain\SchoolCore\Communication\DTO\{RecipientData,RecipientQueryData}; use App\Domain\SchoolCore\Communication\Support\RecipientSet; final class SundayClassRecipientResolver implements RecipientResolverContract { public function supports(RecipientQueryData $query): bool { return $query->audienceType === 'sunday_class'; } public function resolve(SchoolContext $context, RecipientQueryData $query): RecipientSet { return new RecipientSet([new RecipientData('guardian',$context->schoolId*2000+1,'Extension Recipient','sunday_class@example.test','+15555550200',$query->language,[],null,null,$context->schoolId,[$query->channel->value],[],['extension'=>'islamic_sunday_school'],['sunday_class'])]); } }
|
||||
@@ -0,0 +1 @@
|
||||
<?php declare(strict_types=1); namespace App\Domain\IslamicSundaySchool\Communication\Resolvers; use App\Domain\SchoolCore\Context\SchoolContext; use App\Domain\SchoolCore\Communication\Contracts\RecipientResolverContract; use App\Domain\SchoolCore\Communication\DTO\{RecipientData,RecipientQueryData}; use App\Domain\SchoolCore\Communication\Support\RecipientSet; final class VolunteerRecipientResolver implements RecipientResolverContract { public function supports(RecipientQueryData $query): bool { return $query->audienceType === 'volunteers'; } public function resolve(SchoolContext $context, RecipientQueryData $query): RecipientSet { return new RecipientSet([new RecipientData('guardian',$context->schoolId*2000+1,'Extension Recipient','volunteers@example.test','+15555550200',$query->language,[],null,null,$context->schoolId,[$query->channel->value],[],['extension'=>'islamic_sunday_school'],['volunteers'])]); } }
|
||||
+1
@@ -0,0 +1 @@
|
||||
<?php declare(strict_types=1); namespace App\Domain\IslamicSundaySchool\Communication\Resolvers; use App\Domain\SchoolCore\Context\SchoolContext; use App\Domain\SchoolCore\Communication\Contracts\RecipientResolverContract; use App\Domain\SchoolCore\Communication\DTO\{RecipientData,RecipientQueryData}; use App\Domain\SchoolCore\Communication\Support\RecipientSet; final class VolunteerTeamRecipientResolver implements RecipientResolverContract { public function supports(RecipientQueryData $query): bool { return $query->audienceType === 'volunteer_team'; } public function resolve(SchoolContext $context, RecipientQueryData $query): RecipientSet { return new RecipientSet([new RecipientData('guardian',$context->schoolId*2000+1,'Extension Recipient','volunteer_team@example.test','+15555550200',$query->language,[],null,null,$context->schoolId,[$query->channel->value],[],['extension'=>'islamic_sunday_school'],['volunteer_team'])]); } }
|
||||
+1
@@ -0,0 +1 @@
|
||||
<?php declare(strict_types=1); namespace App\Domain\IslamicSundaySchool\Communication\Templates; final class IslamicSundaySchoolTemplateCatalog { public function templates(): array { return ['program_class_reminder'=>['category'=>'event'], 'volunteer_reminder'=>['category'=>'event'], 'attendance_follow_up'=>['category'=>'attendance']]; } }
|
||||
@@ -0,0 +1,3 @@
|
||||
# Contracts
|
||||
|
||||
Extension module. Bind policies/providers here without leaking implementation details into SchoolCore.
|
||||
@@ -0,0 +1,3 @@
|
||||
# Curriculum
|
||||
|
||||
Extension module. Bind policies/providers here without leaking implementation details into SchoolCore.
|
||||
@@ -0,0 +1,3 @@
|
||||
# Families
|
||||
|
||||
Extension module. Bind policies/providers here without leaking implementation details into SchoolCore.
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Domain\IslamicSundaySchool\Finance\Policies;
|
||||
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
use App\Domain\SchoolCore\Finance\Contracts\PaymentAllocationPolicyContract;
|
||||
use App\Domain\SchoolCore\Finance\Support\Money;
|
||||
|
||||
final class IslamicSundaySchoolPaymentAllocationPolicy implements PaymentAllocationPolicyContract
|
||||
{
|
||||
public function allocate(SchoolContext $context, array $invoiceView, Money $paymentAmount): array
|
||||
{
|
||||
return [['invoice_id'=>$invoiceView['id'] ?? null,'amount_minor'=>$paymentAmount->minorAmount(),'currency'=>$paymentAmount->currency(),'strategy'=>'extension_policy_family_program_order']];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Domain\IslamicSundaySchool\Finance\Policies;
|
||||
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
use App\Domain\SchoolCore\Finance\Contracts\TuitionPolicyContract;
|
||||
|
||||
final class IslamicSundaySchoolTuitionPolicy implements TuitionPolicyContract
|
||||
{
|
||||
public function calculateExpectedCharges(SchoolContext $context, array $studentFinanceProfile): array
|
||||
{
|
||||
return ['profile'=>$context->domainProfile,'charges'=>[],'labels_are_extension_owned'=>true];
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Domain\IslamicSundaySchool\Finance\Providers;
|
||||
|
||||
use App\Domain\IslamicSundaySchool\Finance\Policies\IslamicSundaySchoolPaymentAllocationPolicy;
|
||||
use App\Domain\IslamicSundaySchool\Finance\Policies\IslamicSundaySchoolTuitionPolicy;
|
||||
use App\Domain\SchoolCore\Finance\Contracts\PaymentAllocationPolicyContract;
|
||||
use App\Domain\SchoolCore\Finance\Contracts\TuitionPolicyContract;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
final class IslamicSundaySchoolFinanceServiceProvider extends ServiceProvider
|
||||
{
|
||||
public function register(): void
|
||||
{
|
||||
if (! (bool) config('school_context.extensions.islamic_sunday_school.enabled', false)) { return; }
|
||||
$this->app->bind(TuitionPolicyContract::class, IslamicSundaySchoolTuitionPolicy::class);
|
||||
$this->app->bind(PaymentAllocationPolicyContract::class, IslamicSundaySchoolPaymentAllocationPolicy::class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
# Islamic Sunday School Finance Extension
|
||||
|
||||
Owns extension labels, tuition policies, allocation policies, scholarships, and local reports. It depends on SchoolCore Finance contracts. SchoolCore Finance must not depend back on this namespace.
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Domain\IslamicSundaySchool\Finance\Reports;
|
||||
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
use App\Domain\SchoolCore\Finance\Repositories\FinanceReadRepository;
|
||||
|
||||
final class IslamicSundaySchoolFinanceReportBuilder
|
||||
{
|
||||
public function __construct(private readonly FinanceReadRepository $finance) {}
|
||||
public function outstandingBalances(SchoolContext $context): array
|
||||
{
|
||||
return ['domain_profile'=>$context->domainProfile,'rows'=>$this->finance->outstandingInvoices($context)];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
# Ministry
|
||||
|
||||
Extension module. Bind policies/providers here without leaking implementation details into SchoolCore.
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Domain\IslamicSundaySchool\Policies;
|
||||
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
use App\Domain\SchoolCore\Contracts\PaymentAllocationPolicyContract;
|
||||
|
||||
final class IslamicSundaySchoolPaymentAllocationPolicy implements PaymentAllocationPolicyContract
|
||||
{
|
||||
public function allocate(SchoolContext $context, int $invoiceId, float $amount): array
|
||||
{
|
||||
return [['invoice_id' => $invoiceId, 'amount' => $amount, 'allocation_rule' => 'extension_default']];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
# Policies
|
||||
|
||||
Extension module. Bind policies/providers here without leaking implementation details into SchoolCore.
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Domain\IslamicSundaySchool\Providers;
|
||||
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
use App\Domain\SchoolCore\Contracts\AcademicCalendarProviderContract;
|
||||
use DateTimeInterface;
|
||||
|
||||
final class IslamicSundaySchoolCalendarProvider implements AcademicCalendarProviderContract
|
||||
{
|
||||
public function currentAcademicYear(SchoolContext $context): ?int
|
||||
{
|
||||
return is_numeric($context->schoolYear) ? (int) $context->schoolYear : null;
|
||||
}
|
||||
|
||||
public function currentTerm(SchoolContext $context): ?int
|
||||
{
|
||||
return is_numeric($context->term) ? (int) $context->term : null;
|
||||
}
|
||||
|
||||
public function sessionsForDate(SchoolContext $context, DateTimeInterface $date): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
# Providers
|
||||
|
||||
Extension module. Bind policies/providers here without leaking implementation details into SchoolCore.
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
<?php declare(strict_types=1);
|
||||
namespace App\Domain\IslamicSundaySchool\Reporting\ExportTemplates;
|
||||
final class FamilySummaryExportTemplate {}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
<?php declare(strict_types=1);
|
||||
namespace App\Domain\IslamicSundaySchool\Reporting\ExportTemplates;
|
||||
final class QuranProgressExportTemplate {}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<?php declare(strict_types=1);
|
||||
namespace App\Domain\IslamicSundaySchool\Reporting\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use App\Domain\IslamicSundaySchool\Reporting\Reports\{QuranProgressReport,ArabicLevelReport,IslamicStudiesProgressReport,HalaqaAttendanceReport,SundayProgramAttendanceReport,MasjidFamilySummaryReport,VolunteerTeamReport,IslamicSundaySchoolDashboardReport};
|
||||
|
||||
final class IslamicSundaySchoolReportingServiceProvider extends ServiceProvider
|
||||
{
|
||||
public function register(): void
|
||||
{
|
||||
$this->app->tag([
|
||||
QuranProgressReport::class,
|
||||
ArabicLevelReport::class,
|
||||
IslamicStudiesProgressReport::class,
|
||||
HalaqaAttendanceReport::class,
|
||||
SundayProgramAttendanceReport::class,
|
||||
MasjidFamilySummaryReport::class,
|
||||
VolunteerTeamReport::class,
|
||||
IslamicSundaySchoolDashboardReport::class,
|
||||
], 'schoolcore.reports');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<?php declare(strict_types=1);
|
||||
namespace App\Domain\IslamicSundaySchool\Reporting\ReadModels;
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
final class ArabicProgressReadModel { public function rows(SchoolContext $context, array $filters = []): array { return []; } }
|
||||
@@ -0,0 +1,4 @@
|
||||
<?php declare(strict_types=1);
|
||||
namespace App\Domain\IslamicSundaySchool\Reporting\ReadModels;
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
final class HalaqaReportReadModel { public function rows(SchoolContext $context, array $filters = []): array { return []; } }
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
<?php declare(strict_types=1);
|
||||
namespace App\Domain\IslamicSundaySchool\Reporting\ReadModels;
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
final class IslamicStudiesProgressReadModel { public function rows(SchoolContext $context, array $filters = []): array { return []; } }
|
||||
@@ -0,0 +1,4 @@
|
||||
<?php declare(strict_types=1);
|
||||
namespace App\Domain\IslamicSundaySchool\Reporting\ReadModels;
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
final class MasjidFamilyReportReadModel { public function rows(SchoolContext $context, array $filters = []): array { return []; } }
|
||||
@@ -0,0 +1,4 @@
|
||||
<?php declare(strict_types=1);
|
||||
namespace App\Domain\IslamicSundaySchool\Reporting\ReadModels;
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
final class QuranProgressReadModel { public function rows(SchoolContext $context, array $filters = []): array { return []; } }
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php declare(strict_types=1);
|
||||
namespace App\Domain\IslamicSundaySchool\Reporting\Reports;
|
||||
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
use App\Domain\SchoolCore\Reporting\DTO\ReportResultData;
|
||||
|
||||
final class ArabicLevelReport extends BaseIslamicSundaySchoolReport
|
||||
{
|
||||
public function key(): string { return 'islamic.arabic_level'; }
|
||||
public function name(): string { return 'Arabic Level'; }
|
||||
public function columns(): array { return [['key' => 'note', 'label' => 'Note', 'sensitive' => false]]; }
|
||||
public function sensitiveColumns(): array { return ['sensitive_notes']; }
|
||||
public function run(SchoolContext $context, array $filters = []): ReportResultData
|
||||
{
|
||||
return new ReportResultData($this->key(), $this->columns(), [[
|
||||
'school_id' => $context->schoolId,
|
||||
'report_key' => $this->key(),
|
||||
'note' => 'Extension report scaffold. Wire this to Islamic Sunday School read models.',
|
||||
]], null, null, null, 1, gmdate('c'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php declare(strict_types=1);
|
||||
namespace App\Domain\IslamicSundaySchool\Reporting\Reports;
|
||||
|
||||
use App\Domain\SchoolCore\Reporting\Enums\ReportCategory;
|
||||
use App\Domain\SchoolCore\Reporting\Reports\BaseReportDefinition;
|
||||
|
||||
abstract class BaseIslamicSundaySchoolReport extends BaseReportDefinition
|
||||
{
|
||||
public function category(): ReportCategory { return ReportCategory::EXTENSION; }
|
||||
public function availableForDomainProfile(?string $domainProfile): bool { return $domainProfile === 'islamic_sunday_school'; }
|
||||
public function requiredPermissions(): array { return ['report.view', 'report.islamic.view']; }
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php declare(strict_types=1);
|
||||
namespace App\Domain\IslamicSundaySchool\Reporting\Reports;
|
||||
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
use App\Domain\SchoolCore\Reporting\DTO\ReportResultData;
|
||||
|
||||
final class HalaqaAttendanceReport extends BaseIslamicSundaySchoolReport
|
||||
{
|
||||
public function key(): string { return 'islamic.halaqa_attendance'; }
|
||||
public function name(): string { return 'Halaqa Attendance'; }
|
||||
public function columns(): array { return [['key' => 'note', 'label' => 'Note', 'sensitive' => false]]; }
|
||||
public function sensitiveColumns(): array { return ['sensitive_notes']; }
|
||||
public function run(SchoolContext $context, array $filters = []): ReportResultData
|
||||
{
|
||||
return new ReportResultData($this->key(), $this->columns(), [[
|
||||
'school_id' => $context->schoolId,
|
||||
'report_key' => $this->key(),
|
||||
'note' => 'Extension report scaffold. Wire this to Islamic Sunday School read models.',
|
||||
]], null, null, null, 1, gmdate('c'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php declare(strict_types=1);
|
||||
namespace App\Domain\IslamicSundaySchool\Reporting\Reports;
|
||||
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
use App\Domain\SchoolCore\Reporting\DTO\ReportResultData;
|
||||
|
||||
final class IslamicStudiesProgressReport extends BaseIslamicSundaySchoolReport
|
||||
{
|
||||
public function key(): string { return 'islamic.studies_progress'; }
|
||||
public function name(): string { return 'Islamic Studies Progress'; }
|
||||
public function columns(): array { return [['key' => 'note', 'label' => 'Note', 'sensitive' => false]]; }
|
||||
public function sensitiveColumns(): array { return ['sensitive_notes']; }
|
||||
public function run(SchoolContext $context, array $filters = []): ReportResultData
|
||||
{
|
||||
return new ReportResultData($this->key(), $this->columns(), [[
|
||||
'school_id' => $context->schoolId,
|
||||
'report_key' => $this->key(),
|
||||
'note' => 'Extension report scaffold. Wire this to Islamic Sunday School read models.',
|
||||
]], null, null, null, 1, gmdate('c'));
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<?php declare(strict_types=1);
|
||||
namespace App\Domain\IslamicSundaySchool\Reporting\Reports;
|
||||
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
use App\Domain\SchoolCore\Reporting\DTO\ReportResultData;
|
||||
|
||||
final class IslamicSundaySchoolDashboardReport extends BaseIslamicSundaySchoolReport
|
||||
{
|
||||
public function key(): string { return 'islamic.dashboard'; }
|
||||
public function name(): string { return 'Islamic Sunday School Dashboard'; }
|
||||
public function columns(): array { return [['key' => 'note', 'label' => 'Note', 'sensitive' => false]]; }
|
||||
public function sensitiveColumns(): array { return ['sensitive_notes']; }
|
||||
public function run(SchoolContext $context, array $filters = []): ReportResultData
|
||||
{
|
||||
return new ReportResultData($this->key(), $this->columns(), [[
|
||||
'school_id' => $context->schoolId,
|
||||
'report_key' => $this->key(),
|
||||
'note' => 'Extension report scaffold. Wire this to Islamic Sunday School read models.',
|
||||
]], null, null, null, 1, gmdate('c'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php declare(strict_types=1);
|
||||
namespace App\Domain\IslamicSundaySchool\Reporting\Reports;
|
||||
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
use App\Domain\SchoolCore\Reporting\DTO\ReportResultData;
|
||||
|
||||
final class MasjidFamilySummaryReport extends BaseIslamicSundaySchoolReport
|
||||
{
|
||||
public function key(): string { return 'islamic.masjid_family_summary'; }
|
||||
public function name(): string { return 'Masjid Family Summary'; }
|
||||
public function columns(): array { return [['key' => 'note', 'label' => 'Note', 'sensitive' => false]]; }
|
||||
public function sensitiveColumns(): array { return ['sensitive_notes']; }
|
||||
public function run(SchoolContext $context, array $filters = []): ReportResultData
|
||||
{
|
||||
return new ReportResultData($this->key(), $this->columns(), [[
|
||||
'school_id' => $context->schoolId,
|
||||
'report_key' => $this->key(),
|
||||
'note' => 'Extension report scaffold. Wire this to Islamic Sunday School read models.',
|
||||
]], null, null, null, 1, gmdate('c'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php declare(strict_types=1);
|
||||
namespace App\Domain\IslamicSundaySchool\Reporting\Reports;
|
||||
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
use App\Domain\SchoolCore\Reporting\DTO\ReportResultData;
|
||||
|
||||
final class QuranProgressReport extends BaseIslamicSundaySchoolReport
|
||||
{
|
||||
public function key(): string { return 'islamic.quran_progress'; }
|
||||
public function name(): string { return "Qur'an Progress"; }
|
||||
public function columns(): array { return [['key' => 'note', 'label' => 'Note', 'sensitive' => false]]; }
|
||||
public function sensitiveColumns(): array { return ['sensitive_notes']; }
|
||||
public function run(SchoolContext $context, array $filters = []): ReportResultData
|
||||
{
|
||||
return new ReportResultData($this->key(), $this->columns(), [[
|
||||
'school_id' => $context->schoolId,
|
||||
'report_key' => $this->key(),
|
||||
'note' => 'Extension report scaffold. Wire this to Islamic Sunday School read models.',
|
||||
]], null, null, null, 1, gmdate('c'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php declare(strict_types=1);
|
||||
namespace App\Domain\IslamicSundaySchool\Reporting\Reports;
|
||||
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
use App\Domain\SchoolCore\Reporting\DTO\ReportResultData;
|
||||
|
||||
final class SundayProgramAttendanceReport extends BaseIslamicSundaySchoolReport
|
||||
{
|
||||
public function key(): string { return 'islamic.sunday_program_attendance'; }
|
||||
public function name(): string { return 'Sunday Program Attendance'; }
|
||||
public function columns(): array { return [['key' => 'note', 'label' => 'Note', 'sensitive' => false]]; }
|
||||
public function sensitiveColumns(): array { return ['sensitive_notes']; }
|
||||
public function run(SchoolContext $context, array $filters = []): ReportResultData
|
||||
{
|
||||
return new ReportResultData($this->key(), $this->columns(), [[
|
||||
'school_id' => $context->schoolId,
|
||||
'report_key' => $this->key(),
|
||||
'note' => 'Extension report scaffold. Wire this to Islamic Sunday School read models.',
|
||||
]], null, null, null, 1, gmdate('c'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php declare(strict_types=1);
|
||||
namespace App\Domain\IslamicSundaySchool\Reporting\Reports;
|
||||
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
use App\Domain\SchoolCore\Reporting\DTO\ReportResultData;
|
||||
|
||||
final class VolunteerTeamReport extends BaseIslamicSundaySchoolReport
|
||||
{
|
||||
public function key(): string { return 'islamic.volunteer_team'; }
|
||||
public function name(): string { return 'Volunteer Team'; }
|
||||
public function columns(): array { return [['key' => 'note', 'label' => 'Note', 'sensitive' => false]]; }
|
||||
public function sensitiveColumns(): array { return ['sensitive_notes']; }
|
||||
public function run(SchoolContext $context, array $filters = []): ReportResultData
|
||||
{
|
||||
return new ReportResultData($this->key(), $this->columns(), [[
|
||||
'school_id' => $context->schoolId,
|
||||
'report_key' => $this->key(),
|
||||
'note' => 'Extension report scaffold. Wire this to Islamic Sunday School read models.',
|
||||
]], null, null, null, 1, gmdate('c'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
# Reports
|
||||
|
||||
Extension module. Bind policies/providers here without leaking implementation details into SchoolCore.
|
||||
@@ -0,0 +1,4 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace App\Domain\IslamicSundaySchool\Students\DTO;
|
||||
final readonly class IslamicSundaySchoolStudentProfileData { public function __construct(public int $studentId, public ?int $familyProfileId=null, public ?int $quranLevelId=null, public ?int $arabicLevelId=null, public ?int $islamicStudiesTrackId=null, public ?int $halaqaGroupId=null, public ?string $memorizationProgressSummary=null, public ?string $recitationPlacement=null, public bool $volunteerFamilyParticipation=false, public ?string $sensitiveAdminNotes=null, public array $metadata=[]) {} }
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace App\Domain\IslamicSundaySchool\Students\Policies;
|
||||
use App\Domain\SchoolCore\Context\SchoolContext; use App\Domain\SchoolCore\Students\DTO\EnrollmentData;
|
||||
final class IslamicSundaySchoolEnrollmentPolicy { public function canEnroll(SchoolContext $context, EnrollmentData $data): bool { return $context->isIslamicSundaySchool() && $data->studentId>0; } }
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace App\Domain\IslamicSundaySchool\Students\Policies;
|
||||
use App\Domain\SchoolCore\Context\SchoolContext; use App\Domain\SchoolCore\Students\Contracts\PromotionPolicyContract; use App\Domain\SchoolCore\Students\DTO\EnrollmentView; use App\Domain\SchoolCore\Students\DTO\PromotionEvaluationResult; use App\Domain\SchoolCore\Students\DTO\StudentView;
|
||||
final class IslamicSundaySchoolPromotionPolicy implements PromotionPolicyContract { public function evaluate(SchoolContext $context, StudentView $student, EnrollmentView $enrollment): PromotionEvaluationResult { return new PromotionEvaluationResult($context->isIslamicSundaySchool() && $student->status==='active',$student->status==='active'?'promoted':'manual_review'); } }
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace App\Domain\IslamicSundaySchool\Students\Policies;
|
||||
use App\Domain\SchoolCore\Context\SchoolContext; use App\Domain\SchoolCore\Students\Contracts\StudentIdentifierGeneratorContract; use App\Domain\SchoolCore\Students\DTO\StudentIdentifier; use App\Domain\SchoolCore\Students\DTO\StudentView;
|
||||
final class IslamicSundaySchoolStudentIdentifierGenerator implements StudentIdentifierGeneratorContract { public function generateForPersistedStudent(SchoolContext $context, StudentView $student): StudentIdentifier { return new StudentIdentifier(sprintf('SS-%s-%06d',date('Y'),$student->id)); } }
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace App\Domain\IslamicSundaySchool\Students\Providers;
|
||||
use App\Domain\IslamicSundaySchool\Students\Policies\IslamicSundaySchoolPromotionPolicy; use App\Domain\IslamicSundaySchool\Students\Policies\IslamicSundaySchoolStudentIdentifierGenerator; use App\Domain\SchoolCore\Students\Contracts\PromotionPolicyContract; use App\Domain\SchoolCore\Students\Contracts\StudentIdentifierGeneratorContract; use Illuminate\Support\ServiceProvider;
|
||||
final class IslamicSundaySchoolStudentServiceProvider extends ServiceProvider { public function register(): void { if((bool)config('school_context.extensions.islamic_sunday_school.students',false)){ $this->app->bind(StudentIdentifierGeneratorContract::class,IslamicSundaySchoolStudentIdentifierGenerator::class); $this->app->bind(PromotionPolicyContract::class,IslamicSundaySchoolPromotionPolicy::class); } } }
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace App\Domain\IslamicSundaySchool\Students\Reports;
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
final class IslamicSundaySchoolStudentReportBuilder { public function buildSummary(SchoolContext $context,array $filters=[]): array { return ['domain_profile'=>$context->domainProfile,'filters'=>$filters,'labels'=>['quran_level','arabic_level','islamic_studies_track']]; } }
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace App\Domain\IslamicSundaySchool\Students\Services;
|
||||
use App\Domain\SchoolCore\Context\SchoolContext;
|
||||
final class IslamicSundaySchoolFamilyProfileService { public function summarizeForStudent(SchoolContext $context,int $studentId): array { return ['school_id'=>$context->schoolId,'student_id'=>$studentId,'extension'=>'islamic_sunday_school']; } }
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace App\Domain\IslamicSundaySchool\Students\Services;
|
||||
use App\Domain\IslamicSundaySchool\Students\DTO\IslamicSundaySchoolStudentProfileData; use App\Domain\SchoolCore\Context\SchoolContext; use Illuminate\Support\Facades\DB;
|
||||
final class IslamicSundaySchoolStudentProfileService { public function save(SchoolContext $context, IslamicSundaySchoolStudentProfileData $data): array { DB::table('islamic_sunday_school_student_profiles')->updateOrInsert(['school_id'=>$context->schoolId,'student_id'=>$data->studentId],['family_profile_id'=>$data->familyProfileId,'quran_level_id'=>$data->quranLevelId,'arabic_level_id'=>$data->arabicLevelId,'islamic_studies_track_id'=>$data->islamicStudiesTrackId,'halaqa_group_id'=>$data->halaqaGroupId,'memorization_progress_summary'=>$data->memorizationProgressSummary,'recitation_placement'=>$data->recitationPlacement,'volunteer_family_participation'=>$data->volunteerFamilyParticipation,'sensitive_admin_notes'=>$data->sensitiveAdminNotes,'metadata'=>json_encode($data->metadata),'updated_at'=>now()]); return ['student_id'=>$data->studentId,'profile'=>'islamic_sunday_school']; } }
|
||||
Reference in New Issue
Block a user