fix first production issues
API CI/CD / Validate (composer + pint) (push) Failing after 1m11s
API CI/CD / Test (PHPUnit) (push) Failing after 2m30s
API CI/CD / Build frontend assets (push) Successful in 1m14s
API CI/CD / Security audit (push) Failing after 48s
API CI/CD / Deploy to shared hosting (PHP) (push) Has been skipped
API CI/CD / Validate (composer + pint) (push) Failing after 1m11s
API CI/CD / Test (PHPUnit) (push) Failing after 2m30s
API CI/CD / Build frontend assets (push) Successful in 1m14s
API CI/CD / Security audit (push) Failing after 48s
API CI/CD / Deploy to shared hosting (PHP) (push) Has been skipped
This commit is contained in:
+124
-80
@@ -1,88 +1,132 @@
|
||||
# ────────────────────────────────────
|
||||
# Docker Dev Environment
|
||||
# ────────────────────────────────────
|
||||
NODE_ENV=development
|
||||
APP_NAME=Alrahma_API
|
||||
APP_ENV=local
|
||||
APP_KEY=base64:RfIZKqgXC9seghl2Jqs2MgLh1X1Z7APRsnhUK8CgWx8=
|
||||
APP_DEBUG=true
|
||||
APP_TIMEZONE=America/New_York
|
||||
APP_URL=http://localhost:8080
|
||||
|
||||
# ────────────────────────────────────
|
||||
# DATABASE (PostgreSQL via docker)
|
||||
# ────────────────────────────────────
|
||||
DATABASE_URL=postgresql://postgres:password@postgres:5432/rentaldrivego
|
||||
APP_LOCALE=en
|
||||
APP_FALLBACK_LOCALE=en
|
||||
APP_FAKER_LOCALE=en_US
|
||||
|
||||
# ────────────────────────────────────
|
||||
APP_MAINTENANCE_DRIVER=file
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOG_LEVEL=debug
|
||||
LOG_DEPRECATIONS_CHANNEL=null
|
||||
|
||||
# ----------------------------
|
||||
# DATABASE
|
||||
# ----------------------------
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=school_api
|
||||
DB_USERNAME=root
|
||||
DB_PASSWORD=8>f398yxL
|
||||
APP_URL=http://127.0.0.1:8000
|
||||
|
||||
# ----------------------------
|
||||
# SESSION
|
||||
# ----------------------------
|
||||
SESSION_DRIVER=file
|
||||
SESSION_LIFETIME=120
|
||||
SESSION_ENCRYPT=false
|
||||
SESSION_PATH=/
|
||||
SESSION_DOMAIN=null
|
||||
|
||||
# ----------------------------
|
||||
# CACHE & QUEUE
|
||||
# ----------------------------
|
||||
CACHE_STORE=file
|
||||
QUEUE_CONNECTION=sync
|
||||
|
||||
# ----------------------------
|
||||
# REDIS
|
||||
# ────────────────────────────────────
|
||||
REDIS_URL=redis://redis:6379
|
||||
# ----------------------------
|
||||
REDIS_CLIENT=phpredis
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
# ────────────────────────────────────
|
||||
# ----------------------------
|
||||
# MAIL
|
||||
# ----------------------------
|
||||
MAIL_MAILER=log
|
||||
MAIL_PROFILE_DEFAULT=default
|
||||
MAIL_DEFAULT_HOST=smtp.gmail.com
|
||||
MAIL_DEFAULT_PORT=587
|
||||
MAIL_DEFAULT_USER=alrahma.sunday.school@gmail.com
|
||||
MAIL_DEFAULT_PASS="psnp emdq dykw ypul"
|
||||
MAIL_DEFAULT_ENCRYPTION=tls
|
||||
MAIL_DEFAULT_FROM_EMAIL="alrahma.sunday.school@gmail.com"
|
||||
MAIL_DEFAULT_FROM_NAME="Alrahma API"
|
||||
MAIL_DEFAULT_REPLY_TO="alrahma.isgl@gmail.com"
|
||||
MAIL_DEFAULT_REPLY_TO_NAME="Al Rahma Sunday School"
|
||||
MAIL_COMMUNICATION_REPLY_TO="alrahma.isgl@gmail.com"
|
||||
MAIL_COMMUNICATION_REPLY_TO_NAME="School Communications"
|
||||
MAIL_PAYMENT_REPLY_TO="alrahma.isgl@gmail.com"
|
||||
MAIL_PAYMENT_REPLY_TO_NAME="School Payments"
|
||||
MAIL_SENDERS='{"general":{"name":"Alrahma API","email":"alrahma.sunday.school@gmail.com"},"communication":{"name":"School Communications","email":"alrahma.sunday.school@gmail.com"},"payment":{"name":"School Payments","email":"alrahma.sunday.school@gmail.com"}}'
|
||||
|
||||
# Laravel mailer compatibility
|
||||
MAIL_HOST="${MAIL_DEFAULT_HOST}"
|
||||
MAIL_PORT="${MAIL_DEFAULT_PORT}"
|
||||
MAIL_USERNAME="${MAIL_DEFAULT_USER}"
|
||||
MAIL_PASSWORD="${MAIL_DEFAULT_PASS}"
|
||||
MAIL_ENCRYPTION="${MAIL_DEFAULT_ENCRYPTION}"
|
||||
MAIL_FROM_ADDRESS="${MAIL_DEFAULT_FROM_EMAIL}"
|
||||
MAIL_FROM_NAME="${MAIL_DEFAULT_FROM_NAME}"
|
||||
|
||||
# Legacy fallback keys still read by some services
|
||||
SMTP_HOST="${MAIL_DEFAULT_HOST}"
|
||||
SMTP_USER="${MAIL_DEFAULT_USER}"
|
||||
SMTP_PASS="${MAIL_DEFAULT_PASS}"
|
||||
SMTP_PORT="${MAIL_DEFAULT_PORT}"
|
||||
SMTP_ENCRYPTION="${MAIL_DEFAULT_ENCRYPTION}"
|
||||
|
||||
# ----------------------------
|
||||
# FILESYSTEM
|
||||
# ----------------------------
|
||||
FILESYSTEM_DISK=local
|
||||
|
||||
# ----------------------------
|
||||
# AWS STORAGE
|
||||
# ----------------------------
|
||||
AWS_ACCESS_KEY_ID=
|
||||
AWS_SECRET_ACCESS_KEY=
|
||||
AWS_DEFAULT_REGION=us-east-1
|
||||
AWS_BUCKET=
|
||||
AWS_USE_PATH_STYLE_ENDPOINT=false
|
||||
|
||||
# ----------------------------
|
||||
# JWT
|
||||
# ────────────────────────────────────
|
||||
JWT_SECRET=bvDokCe6RD7Jb5cxJ6P5z4rdTwS37hyUgglD8HGCE6Xwo6g3SEuZ9XNzjou53raUf6B2jMcEWxQm0Y5zcw2THw
|
||||
JWT_EXPIRY=8h
|
||||
# ----------------------------
|
||||
JWT_SECRET=Uj8rGnYcXMgeRc5qCIn9Wn03tYo1pCsBz1Biou8T9zWtaNxBYi3P4NP5vuFiXHmd
|
||||
JWT_ALGO=HS256
|
||||
JWT_TTL=60
|
||||
JWT_REFRESH_TTL=20160
|
||||
JWT_BLACKLIST_ENABLED=true
|
||||
JWT_BLACKLIST_GRACE_PERIOD=0
|
||||
|
||||
# ────────────────────────────────────
|
||||
# FILE STORAGE
|
||||
# ────────────────────────────────────
|
||||
FILE_STORAGE_ROOT=/var/lib/rentaldrivego/storage
|
||||
# ----------------------------
|
||||
# DOCS
|
||||
# ----------------------------
|
||||
DOCS_CLIENT_URL=http://localhost:3000
|
||||
DOCS_INDEX_TITLE=Alrahma API Documentation
|
||||
DOCS_INDEX_DESCRIPTION=
|
||||
|
||||
# ────────────────────────────────────
|
||||
# URLS (docker services)
|
||||
# ────────────────────────────────────
|
||||
API_URL=http://localhost:4000
|
||||
API_HOST=0.0.0.0
|
||||
API_PORT=4000
|
||||
API_INTERNAL_URL=http://api:4000
|
||||
ADMIN_URL=http://localhost:3002
|
||||
DASHBOARD_URL=http://localhost:3001
|
||||
MARKETPLACE_URL=http://localhost:3000
|
||||
NEXT_PUBLIC_ADMIN_URL=http://localhost:3002
|
||||
NEXT_PUBLIC_DASHBOARD_URL=http://localhost:3001
|
||||
NEXT_PUBLIC_MARKETPLACE_URL=http://localhost:3000
|
||||
NEXT_PUBLIC_CUSTOM_DOMAIN_TARGET=http://localhost:3000
|
||||
# ----------------------------
|
||||
# BADGE
|
||||
# ----------------------------
|
||||
BADGE_SCHOOL_NAME=Al Rahma Sunday School
|
||||
BADGE_HEADER_SUBTITLE=
|
||||
BADGE_MOTTO=
|
||||
BADGE_MOTTO_FALLBACK=
|
||||
BADGE_ROLE_LABEL=Student
|
||||
BADGE_FOOTER_ADDRESS=5 Courthouse Lane, Chelmsford, MA 01824, USA
|
||||
|
||||
# ────────────────────────────────────
|
||||
# CORS
|
||||
# ────────────────────────────────────
|
||||
CORS_ORIGINS=http://localhost:3000,http://localhost:3001,http://localhost:3002
|
||||
|
||||
# ────────────────────────────────────
|
||||
# MAIL (log driver in dev)
|
||||
# ────────────────────────────────────
|
||||
MAIL_HOST=mailhog
|
||||
MAIL_PORT=1025
|
||||
MAIL_USERNAME=
|
||||
MAIL_PASSWORD=
|
||||
MAIL_ENCRYPTION=none
|
||||
MAIL_FROM_ADDRESS=dev@rentaldrivego.local
|
||||
MAIL_FROM_NAME="RentalDriveGo Dev"
|
||||
MAIL_REPLY_TO_ADDRESS=dev@rentaldrivego.local
|
||||
MAIL_REPLY_TO_NAME="RentalDriveGo Dev"
|
||||
|
||||
# ────────────────────────────────────
|
||||
# ADMIN SEED (initial dev account)
|
||||
# ────────────────────────────────────
|
||||
ADMIN_SEED_EMAIL=admin@rentaldrivego.dev
|
||||
ADMIN_SEED_FIRST_NAME=Dev
|
||||
ADMIN_SEED_LAST_NAME=Admin
|
||||
ADMIN_SEED_PASSWORD=password
|
||||
|
||||
# ────────────────────────────────────
|
||||
# EXTERNAL SERVICES (blank in dev)
|
||||
# ────────────────────────────────────
|
||||
AMANPAY_BASE_URL=
|
||||
AMANPAY_MERCHANT_ID=
|
||||
AMANPAY_SECRET_KEY=
|
||||
AMANPAY_WEBHOOK_SECRET=
|
||||
PAYPAL_BASE_URL=
|
||||
PAYPAL_CLIENT_ID=
|
||||
PAYPAL_CLIENT_SECRET=
|
||||
PAYPAL_WEBHOOK_ID=
|
||||
TWILIO_ACCOUNT_SID=
|
||||
TWILIO_AUTH_TOKEN=
|
||||
TWILIO_PHONE_NUMBER=
|
||||
TWILIO_WHATSAPP_NUMBER=
|
||||
FIREBASE_CLIENT_EMAIL=
|
||||
FIREBASE_PRIVATE_KEY=
|
||||
FIREBASE_PROJECT_ID=
|
||||
RESEND_API_KEY=
|
||||
EMAIL_FROM=
|
||||
EMAIL_FROM_NAME=
|
||||
# ----------------------------
|
||||
# FRONT-END
|
||||
# ----------------------------
|
||||
VITE_APP_NAME="${APP_NAME}"
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
VITE_API_URL=https://api.alrahmaisgl.org/api
|
||||
Vendored
BIN
Binary file not shown.
@@ -6,10 +6,17 @@ class LoginActivity extends BaseModel
|
||||
{
|
||||
protected $table = 'login_activity';
|
||||
|
||||
// ✅ legacy: useTimestamps = true (created_at/updated_at)
|
||||
public $timestamps = true;
|
||||
|
||||
protected $fillable = ['user_id', 'email', 'login_time', 'logout_time', 'ip_address', 'user_agent', 'created_at', 'updated_at', 'semester', 'school_year'];
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'email',
|
||||
'login_time',
|
||||
'logout_time',
|
||||
'ip_address',
|
||||
'user_agent',
|
||||
'school_year',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'user_id' => 'integer',
|
||||
@@ -17,15 +24,11 @@ class LoginActivity extends BaseModel
|
||||
'logout_time' => 'datetime',
|
||||
];
|
||||
|
||||
/* Optional relationship */
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent of legacy getLastActivities()
|
||||
*/
|
||||
public static function getLastActivities(int $limit = 4)
|
||||
{
|
||||
return static::query()
|
||||
|
||||
+66
-36
@@ -132,25 +132,36 @@ class Student extends BaseModel
|
||||
|
||||
/**
|
||||
* legacy: getNewStudentsWithParentsAndEmergency()
|
||||
* Picks one emergency contact via MIN(...) with groupBy student.
|
||||
* Aggregates emergency contacts by parent before joining, avoiding
|
||||
* duplicate student rows and ONLY_FULL_GROUP_BY violations.
|
||||
*/
|
||||
public static function getNewStudentsWithParentsAndEmergency(): array
|
||||
{
|
||||
$emergencyContacts = DB::table('emergency_contacts')
|
||||
->select([
|
||||
'parent_id',
|
||||
DB::raw('MIN(emergency_contact_name) AS emergency_name'),
|
||||
DB::raw('MIN(relation) AS emergency_relationship'),
|
||||
DB::raw('MIN(cellphone) AS emergency_phone'),
|
||||
])
|
||||
->groupBy('parent_id');
|
||||
|
||||
return DB::table('students')
|
||||
->selectRaw('
|
||||
students.*,
|
||||
u.firstname AS parent_firstname,
|
||||
u.lastname AS parent_lastname,
|
||||
u.email AS parent_email,
|
||||
u.cellphone AS parent_phone,
|
||||
MIN(ec.emergency_contact_name) AS emergency_name,
|
||||
MIN(ec.relation) AS emergency_relationship,
|
||||
MIN(ec.cellphone) AS emergency_phone
|
||||
')
|
||||
->leftJoin('users as u', 'u.id', '=', 'students.parent_id')
|
||||
->leftJoin('emergency_contacts as ec', 'ec.parent_id', '=', 'students.parent_id')
|
||||
->leftJoinSub($emergencyContacts, 'ec', function ($join): void {
|
||||
$join->on('ec.parent_id', '=', 'students.parent_id');
|
||||
})
|
||||
->select([
|
||||
'students.*',
|
||||
'u.firstname as parent_firstname',
|
||||
'u.lastname as parent_lastname',
|
||||
'u.email as parent_email',
|
||||
'u.cellphone as parent_phone',
|
||||
'ec.emergency_name',
|
||||
'ec.emergency_relationship',
|
||||
'ec.emergency_phone',
|
||||
])
|
||||
->where('students.is_new', 1)
|
||||
->groupBy('students.id')
|
||||
->orderBy('students.lastname', 'asc')
|
||||
->orderBy('students.firstname', 'asc')
|
||||
->get()
|
||||
@@ -163,46 +174,65 @@ class Student extends BaseModel
|
||||
*/
|
||||
public static function getStudentsWithParentsAndEmergency(?string $schoolYear = null, ?int $isNew = null): array
|
||||
{
|
||||
$q = DB::table('students')
|
||||
->selectRaw('
|
||||
students.*,
|
||||
u.firstname AS parent_firstname,
|
||||
u.lastname AS parent_lastname,
|
||||
u.email AS parent_email,
|
||||
u.cellphone AS parent_phone,
|
||||
MIN(ec.emergency_contact_name) AS emergency_name,
|
||||
MIN(ec.relation) AS emergency_relationship,
|
||||
MIN(ec.cellphone) AS emergency_phone
|
||||
')
|
||||
->leftJoin('users as u', 'u.id', '=', 'students.parent_id')
|
||||
->leftJoin('emergency_contacts as ec', 'ec.parent_id', '=', 'students.parent_id');
|
||||
$emergencyContacts = DB::table('emergency_contacts')
|
||||
->select([
|
||||
'parent_id',
|
||||
DB::raw('MIN(emergency_contact_name) AS emergency_name'),
|
||||
DB::raw('MIN(relation) AS emergency_relationship'),
|
||||
DB::raw('MIN(cellphone) AS emergency_phone'),
|
||||
])
|
||||
->groupBy('parent_id');
|
||||
|
||||
$q = DB::table('students')
|
||||
->leftJoin('users as u', 'u.id', '=', 'students.parent_id')
|
||||
->leftJoinSub($emergencyContacts, 'ec', function ($join): void {
|
||||
$join->on('ec.parent_id', '=', 'students.parent_id');
|
||||
})
|
||||
->select([
|
||||
'students.*',
|
||||
'u.firstname as parent_firstname',
|
||||
'u.lastname as parent_lastname',
|
||||
'u.email as parent_email',
|
||||
'u.cellphone as parent_phone',
|
||||
'ec.emergency_name',
|
||||
'ec.emergency_relationship',
|
||||
'ec.emergency_phone',
|
||||
]);
|
||||
|
||||
// is_new filter
|
||||
if ($isNew === 0 || $isNew === 1) {
|
||||
$q->where('students.is_new', $isNew);
|
||||
} else {
|
||||
$q->whereIn('students.is_new', [0, 1]);
|
||||
}
|
||||
|
||||
// Students are global identities; year rosters come from yearly class/enrollment rows.
|
||||
if ($schoolYear !== null && strtolower($schoolYear) !== 'all') {
|
||||
$q->where(function ($yearQuery) use ($schoolYear) {
|
||||
$yearQuery->whereExists(function ($sub) use ($schoolYear) {
|
||||
$normalizedSchoolYear = $schoolYear !== null
|
||||
? trim($schoolYear)
|
||||
: null;
|
||||
|
||||
if (
|
||||
$normalizedSchoolYear !== null
|
||||
&& $normalizedSchoolYear !== ''
|
||||
&& strtolower($normalizedSchoolYear) !== 'all'
|
||||
) {
|
||||
$q->where(function ($yearQuery) use ($normalizedSchoolYear): void {
|
||||
$yearQuery
|
||||
->whereExists(function ($sub) use ($normalizedSchoolYear): void {
|
||||
$sub->selectRaw('1')
|
||||
->from('student_class as sc')
|
||||
->whereColumn('sc.student_id', 'students.id')
|
||||
->where('sc.school_year', $schoolYear);
|
||||
})->orWhereExists(function ($sub) use ($schoolYear) {
|
||||
->where('sc.school_year', $normalizedSchoolYear);
|
||||
})
|
||||
->orWhereExists(function ($sub) use ($normalizedSchoolYear): void {
|
||||
$sub->selectRaw('1')
|
||||
->from('enrollments as e')
|
||||
->whereColumn('e.student_id', 'students.id')
|
||||
->where('e.school_year', $schoolYear);
|
||||
->where('e.school_year', $normalizedSchoolYear);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return $q->groupBy('students.id')
|
||||
->orderByDesc('students.is_new') // new first
|
||||
return $q
|
||||
->orderByDesc('students.is_new')
|
||||
->orderBy('students.lastname', 'asc')
|
||||
->orderBy('students.firstname', 'asc')
|
||||
->get()
|
||||
|
||||
@@ -22,7 +22,10 @@ class ApiLoginSecurityService
|
||||
|
||||
public function isIpBlocked(string $ip): bool
|
||||
{
|
||||
$row = IpAttempt::query()->where('ip_address', $ip)->first();
|
||||
$row = IpAttempt::query()
|
||||
->where('ip_address', $ip)
|
||||
->first();
|
||||
|
||||
if (! $row || ! $row->blocked_until) {
|
||||
return false;
|
||||
}
|
||||
@@ -35,14 +38,16 @@ class ApiLoginSecurityService
|
||||
$now = CarbonImmutable::now('UTC');
|
||||
$nowStr = $now->toDateTimeString();
|
||||
|
||||
$attempt = IpAttempt::query()->where('ip_address', $ip)->first();
|
||||
$attempt = IpAttempt::query()
|
||||
->where('ip_address', $ip)
|
||||
->first();
|
||||
|
||||
if ($attempt) {
|
||||
$previouslyBlocked = $attempt->blocked_until
|
||||
? CarbonImmutable::parse($attempt->blocked_until, 'UTC')->isFuture()
|
||||
: false;
|
||||
|
||||
// If the previous block has already expired, start a fresh window
|
||||
// so we don't perma-ban an IP after its first 10 lifetime failures.
|
||||
// If the previous block has expired, begin a fresh failure window.
|
||||
$attempts = $previouslyBlocked
|
||||
? ((int) $attempt->attempts) + 1
|
||||
: 1;
|
||||
@@ -64,14 +69,19 @@ class ApiLoginSecurityService
|
||||
'ip_address' => $ip,
|
||||
'attempts' => 1,
|
||||
'last_attempt_at' => $nowStr,
|
||||
'blocked_until' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
public function handleFailedLogin(User $user, string $email, string $ip): void
|
||||
{
|
||||
public function handleFailedLogin(
|
||||
User $user,
|
||||
string $email,
|
||||
string $ip
|
||||
): void {
|
||||
$user->refresh();
|
||||
|
||||
$failedAttempts = ((int) ($user->failed_attempts ?? 0)) + 1;
|
||||
|
||||
$data = [
|
||||
'failed_attempts' => $failedAttempts,
|
||||
'last_failed_at' => utc_now(),
|
||||
@@ -79,8 +89,14 @@ class ApiLoginSecurityService
|
||||
|
||||
if ($failedAttempts >= 3) {
|
||||
$data['is_suspended'] = true;
|
||||
// Password-reset delivery can be wired here when the suspension workflow is finalized.
|
||||
Log::notice('api_login: account suspended after failed attempts', ['email' => $email, 'user_id' => $user->id]);
|
||||
|
||||
Log::notice(
|
||||
'api_login: account suspended after failed attempts',
|
||||
[
|
||||
'email' => $email,
|
||||
'user_id' => $user->id,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
$user->fill($data);
|
||||
@@ -96,10 +112,16 @@ class ApiLoginSecurityService
|
||||
$user->save();
|
||||
}
|
||||
|
||||
public function logSuccessfulLogin(User $user, Request $request): void
|
||||
{
|
||||
$schoolYear = trim((string) (Configuration::getConfig('school_year') ?? date('Y')));
|
||||
$semester = trim((string) (Configuration::getConfig('semester') ?? 'Fall'));
|
||||
public function logSuccessfulLogin(
|
||||
User $user,
|
||||
Request $request
|
||||
): void {
|
||||
$schoolYear = trim(
|
||||
(string) (
|
||||
Configuration::getConfig('school_year')
|
||||
?? date('Y')
|
||||
)
|
||||
);
|
||||
|
||||
LoginActivity::query()->create([
|
||||
'user_id' => $user->id,
|
||||
@@ -107,21 +129,24 @@ class ApiLoginSecurityService
|
||||
'login_time' => utc_now(),
|
||||
'ip_address' => $request->ip(),
|
||||
'user_agent' => (string) ($request->userAgent() ?? ''),
|
||||
'school_year' => $schoolYear,
|
||||
'semester' => $semester !== '' ? $semester : 'Fall',
|
||||
'school_year' => $schoolYear !== ''
|
||||
? $schoolYear
|
||||
: date('Y'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns roles as an object map {"RoleName": true}.
|
||||
* Returns roles as an object map:
|
||||
* {"RoleName": true}
|
||||
*
|
||||
* @param list<string> $roleNames
|
||||
*/
|
||||
public function rolesToObjectMap(array $roleNames): object
|
||||
{
|
||||
$rolesMap = [];
|
||||
foreach ($roleNames as $r) {
|
||||
$rolesMap[$r] = true;
|
||||
|
||||
foreach ($roleNames as $roleName) {
|
||||
$rolesMap[$roleName] = true;
|
||||
}
|
||||
|
||||
return (object) $rolesMap;
|
||||
@@ -130,19 +155,40 @@ class ApiLoginSecurityService
|
||||
/**
|
||||
* Top-level JSON body for API login success responses.
|
||||
*
|
||||
* @return array{status: true, token: string, access_token: string, token_type: string, expires_in: int, user: array{id: int, name: string, firstname: ?string, lastname: ?string, email: ?string, roles: object, class_section_id: ?int, class_section_name: ?string}}
|
||||
* @return array{
|
||||
* status: true,
|
||||
* token: string,
|
||||
* access_token: string,
|
||||
* token_type: string,
|
||||
* expires_in: int,
|
||||
* user: array{
|
||||
* id: int,
|
||||
* name: string,
|
||||
* firstname: ?string,
|
||||
* lastname: ?string,
|
||||
* email: ?string,
|
||||
* roles: object,
|
||||
* class_section_id: ?int,
|
||||
* class_section_name: ?string
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
public function buildLoginResponse(User $user, string $jwtToken): array
|
||||
{
|
||||
public function buildLoginResponse(
|
||||
User $user,
|
||||
string $jwtToken
|
||||
): array {
|
||||
$roleNames = $user->roleNames();
|
||||
$fullName = trim(($user->firstname ?? '').' '.($user->lastname ?? ''));
|
||||
|
||||
$fullName = trim(
|
||||
($user->firstname ?? '')
|
||||
.' '.
|
||||
($user->lastname ?? '')
|
||||
);
|
||||
|
||||
$teacherContext = $user->teacherSessionContext();
|
||||
|
||||
return [
|
||||
'status' => true,
|
||||
// Keep both names. Older clients read `token`; JWT-aware clients often read
|
||||
// `access_token`. Removing either one just makes login fail in a new and
|
||||
// irritatingly avoidable way.
|
||||
'token' => $jwtToken,
|
||||
'access_token' => $jwtToken,
|
||||
'token_type' => 'bearer',
|
||||
|
||||
@@ -4,7 +4,9 @@ namespace App\Services\Families;
|
||||
|
||||
use App\Models\StudentClass;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Database\Query\Builder as QueryBuilder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class ParentProfileAdminQueryService
|
||||
{
|
||||
@@ -12,7 +14,53 @@ class ParentProfileAdminQueryService
|
||||
|
||||
public function index(string $schoolYear, string $search = '', int $perPage = 25): LengthAwarePaginator
|
||||
{
|
||||
$familyCounts = DB::table('family_guardians')
|
||||
->select('user_id', DB::raw('COUNT(DISTINCT family_id) AS families_count'))
|
||||
->groupBy('user_id');
|
||||
|
||||
$familyStudentMap = DB::table('family_guardians as pfg')
|
||||
->join('family_students as pfs', 'pfs.family_id', '=', 'pfg.family_id')
|
||||
->joinSub($this->schoolYearStudentIds($schoolYear), 'pys', function ($join): void {
|
||||
$join->on('pys.student_id', '=', 'pfs.student_id');
|
||||
})
|
||||
->selectRaw('pfg.user_id AS parent_id, pfs.student_id AS student_id');
|
||||
|
||||
$directStudentMap = DB::table('students as ps')
|
||||
->joinSub($this->schoolYearStudentIds($schoolYear), 'dys', function ($join): void {
|
||||
$join->on('dys.student_id', '=', 'ps.id');
|
||||
})
|
||||
->whereNotNull('ps.parent_id')
|
||||
->selectRaw('ps.parent_id AS parent_id, ps.id AS student_id');
|
||||
|
||||
$parentStudentCounts = DB::query()
|
||||
->fromSub(
|
||||
$familyStudentMap->union($directStudentMap),
|
||||
'parent_students'
|
||||
)
|
||||
->select(
|
||||
'parent_id',
|
||||
DB::raw('COUNT(DISTINCT student_id) AS selected_year_students_count')
|
||||
)
|
||||
->groupBy('parent_id');
|
||||
|
||||
$invoiceBalances = DB::table('invoices')
|
||||
->select('parent_id', DB::raw('COALESCE(SUM(balance), 0) AS balance'))
|
||||
->whereNotNull('parent_id');
|
||||
|
||||
$this->applySchoolYearFilter($invoiceBalances, 'school_year', $schoolYear);
|
||||
|
||||
$invoiceBalances->groupBy('parent_id');
|
||||
|
||||
$query = DB::table('users as u')
|
||||
->leftJoinSub($familyCounts, 'fc', function ($join): void {
|
||||
$join->on('fc.user_id', '=', 'u.id');
|
||||
})
|
||||
->leftJoinSub($parentStudentCounts, 'psc', function ($join): void {
|
||||
$join->on('psc.parent_id', '=', 'u.id');
|
||||
})
|
||||
->leftJoinSub($invoiceBalances, 'ib', function ($join): void {
|
||||
$join->on('ib.parent_id', '=', 'u.id');
|
||||
})
|
||||
->select(
|
||||
'u.id',
|
||||
'u.firstname',
|
||||
@@ -20,40 +68,52 @@ class ParentProfileAdminQueryService
|
||||
'u.email',
|
||||
'u.cellphone',
|
||||
'u.status',
|
||||
DB::raw('COUNT(DISTINCT fg.family_id) as families_count'),
|
||||
DB::raw('COUNT(DISTINCT s.id) as selected_year_students_count'),
|
||||
DB::raw('COALESCE(SUM(DISTINCT i.balance), 0) as balance')
|
||||
DB::raw('COALESCE(fc.families_count, 0) AS families_count'),
|
||||
DB::raw('COALESCE(psc.selected_year_students_count, 0) AS selected_year_students_count'),
|
||||
DB::raw('COALESCE(ib.balance, 0) AS balance')
|
||||
)
|
||||
->leftJoin('family_guardians as fg', 'fg.user_id', '=', 'u.id')
|
||||
->leftJoin('family_students as fs', 'fs.family_id', '=', 'fg.family_id')
|
||||
->leftJoin('students as s', function ($join) use ($schoolYear) {
|
||||
$join->on('s.id', '=', 'fs.student_id')
|
||||
->where('s.school_year', '=', $schoolYear);
|
||||
})
|
||||
->leftJoin('invoices as i', function ($join) use ($schoolYear) {
|
||||
$join->on('i.parent_id', '=', 'u.id')
|
||||
->where('i.school_year', '=', $schoolYear);
|
||||
})
|
||||
->where($this->relevantParentConstraint($schoolYear))
|
||||
->groupBy('u.id', 'u.firstname', 'u.lastname', 'u.email', 'u.cellphone', 'u.status')
|
||||
->orderBy('u.lastname')
|
||||
->orderBy('u.firstname');
|
||||
|
||||
$search = trim($search);
|
||||
|
||||
if ($search !== '') {
|
||||
$needle = '%'.str_replace(['%', '_'], ['\\%', '\\_'], $search).'%';
|
||||
$query->where(function ($inner) use ($needle) {
|
||||
$inner->whereRaw("CONCAT_WS(' ', u.firstname, u.lastname) LIKE ?", [$needle])
|
||||
|
||||
$query->where(function ($inner) use ($needle, $schoolYear): void {
|
||||
$inner
|
||||
->whereRaw("CONCAT_WS(' ', u.firstname, u.lastname) LIKE ?", [$needle])
|
||||
->orWhere('u.email', 'like', $needle)
|
||||
->orWhere('u.cellphone', 'like', $needle)
|
||||
->orWhereExists(function ($exists) use ($needle) {
|
||||
->orWhereExists(function ($exists) use ($needle, $schoolYear): void {
|
||||
$exists->selectRaw('1')
|
||||
->from('family_guardians as sfg')
|
||||
->join('family_students as sfs', 'sfs.family_id', '=', 'sfg.family_id')
|
||||
->join('students as ss', 'ss.id', '=', 'sfs.student_id')
|
||||
->whereColumn('sfg.user_id', 'u.id')
|
||||
->where(function ($student) use ($needle) {
|
||||
$student->whereRaw("CONCAT_WS(' ', ss.firstname, ss.lastname) LIKE ?", [$needle]);
|
||||
});
|
||||
->whereRaw("CONCAT_WS(' ', ss.firstname, ss.lastname) LIKE ?", [$needle]);
|
||||
|
||||
$this->constrainStudentToSchoolYear(
|
||||
$exists,
|
||||
'ss.id',
|
||||
$schoolYear
|
||||
);
|
||||
})
|
||||
->orWhereExists(function ($exists) use ($needle, $schoolYear): void {
|
||||
$exists->selectRaw('1')
|
||||
->from('students as direct_search_students')
|
||||
->whereColumn('direct_search_students.parent_id', 'u.id')
|
||||
->whereRaw(
|
||||
"CONCAT_WS(' ', direct_search_students.firstname, direct_search_students.lastname) LIKE ?",
|
||||
[$needle]
|
||||
);
|
||||
|
||||
$this->constrainStudentToSchoolYear(
|
||||
$exists,
|
||||
'direct_search_students.id',
|
||||
$schoolYear
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -76,7 +136,18 @@ class ParentProfileAdminQueryService
|
||||
public function show(int $parentId, string $schoolYear): ?array
|
||||
{
|
||||
$parent = DB::table('users')
|
||||
->select('id', 'firstname', 'lastname', 'email', 'cellphone', 'address_street', 'city', 'state', 'zip', 'status')
|
||||
->select(
|
||||
'id',
|
||||
'firstname',
|
||||
'lastname',
|
||||
'email',
|
||||
'cellphone',
|
||||
'address_street',
|
||||
'city',
|
||||
'state',
|
||||
'zip',
|
||||
'status'
|
||||
)
|
||||
->where('id', $parentId)
|
||||
->first();
|
||||
|
||||
@@ -91,13 +162,14 @@ class ParentProfileAdminQueryService
|
||||
'lastname' => $parent->lastname,
|
||||
],
|
||||
];
|
||||
|
||||
$finance = $this->finance->loadFinancialsForParents([$parentId], $schoolYear);
|
||||
|
||||
return [
|
||||
'parent' => (array) $parent,
|
||||
'families' => $this->familiesForParent($parentId, $schoolYear),
|
||||
'students' => $this->studentsForParent($parentId, $schoolYear),
|
||||
'emergency_contacts' => $this->emergencyContactsForParents($guardians, $schoolYear),
|
||||
'emergency_contacts' => $this->emergencyContactsForParents($guardians),
|
||||
'invoices' => $finance['invoices'],
|
||||
'payments' => $finance['payments'],
|
||||
'finance_summary' => $finance['summary'],
|
||||
@@ -131,6 +203,7 @@ class ParentProfileAdminQueryService
|
||||
public function parentSummary(array $row, string $schoolYear): array
|
||||
{
|
||||
$balance = (float) ($row['balance'] ?? 0);
|
||||
|
||||
$primaryFamily = DB::table('family_guardians as fg')
|
||||
->join('families as f', 'f.id', '=', 'fg.family_id')
|
||||
->where('fg.user_id', (int) ($row['id'] ?? 0))
|
||||
@@ -159,35 +232,66 @@ class ParentProfileAdminQueryService
|
||||
|
||||
private function relevantParentConstraint(string $schoolYear): callable
|
||||
{
|
||||
return function ($query) use ($schoolYear) {
|
||||
$query->whereExists(function ($exists) use ($schoolYear) {
|
||||
$schoolYearId = $this->schoolYearId($schoolYear);
|
||||
|
||||
return function ($query) use ($schoolYear, $schoolYearId): void {
|
||||
$query
|
||||
->whereExists(function ($exists) use ($schoolYear): void {
|
||||
$exists->selectRaw('1')
|
||||
->from('family_guardians as rfg')
|
||||
->join('family_students as rfs', 'rfs.family_id', '=', 'rfg.family_id')
|
||||
->join('students as rs', 'rs.id', '=', 'rfs.student_id')
|
||||
->whereColumn('rfg.user_id', 'u.id')
|
||||
->where('rs.school_year', $schoolYear);
|
||||
})->orWhereExists(function ($exists) use ($schoolYear) {
|
||||
->whereColumn('rfg.user_id', 'u.id');
|
||||
|
||||
$this->constrainStudentToSchoolYear(
|
||||
$exists,
|
||||
'rfs.student_id',
|
||||
$schoolYear
|
||||
);
|
||||
})
|
||||
->orWhereExists(function ($exists) use ($schoolYear): void {
|
||||
$exists->selectRaw('1')
|
||||
->from('students as direct_students')
|
||||
->whereColumn('direct_students.parent_id', 'u.id')
|
||||
->where('direct_students.school_year', $schoolYear);
|
||||
})->orWhereExists(function ($exists) use ($schoolYear) {
|
||||
->whereColumn('direct_students.parent_id', 'u.id');
|
||||
|
||||
$this->constrainStudentToSchoolYear(
|
||||
$exists,
|
||||
'direct_students.id',
|
||||
$schoolYear
|
||||
);
|
||||
})
|
||||
->orWhereExists(function ($exists) use ($schoolYear): void {
|
||||
$exists->selectRaw('1')
|
||||
->from('invoices as ri')
|
||||
->whereColumn('ri.parent_id', 'u.id')
|
||||
->where('ri.school_year', $schoolYear);
|
||||
})->orWhereExists(function ($exists) use ($schoolYear) {
|
||||
->whereColumn('ri.parent_id', 'u.id');
|
||||
|
||||
$this->applySchoolYearFilter(
|
||||
$exists,
|
||||
'ri.school_year',
|
||||
$schoolYear
|
||||
);
|
||||
});
|
||||
|
||||
if (! Schema::hasTable('parent_accounts')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->isAllSchoolYears($schoolYear)) {
|
||||
$query->orWhereExists(function ($exists): void {
|
||||
$exists->selectRaw('1')
|
||||
->from('parent_accounts as pa')
|
||||
->whereColumn('pa.parent_id', 'u.id');
|
||||
});
|
||||
} elseif (
|
||||
$schoolYearId !== null
|
||||
&& Schema::hasColumn('parent_accounts', 'school_year_id')
|
||||
) {
|
||||
$query->orWhereExists(function ($exists) use ($schoolYearId): void {
|
||||
$exists->selectRaw('1')
|
||||
->from('parent_accounts as pa')
|
||||
->whereColumn('pa.parent_id', 'u.id')
|
||||
->where('pa.school_year', $schoolYear);
|
||||
})->orWhereExists(function ($exists) use ($schoolYear) {
|
||||
$exists->selectRaw('1')
|
||||
->from('emergency_contacts as ec')
|
||||
->whereColumn('ec.parent_id', 'u.id')
|
||||
->where('ec.school_year', $schoolYear);
|
||||
->where('pa.school_year_id', $schoolYearId);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -196,15 +300,25 @@ class ParentProfileAdminQueryService
|
||||
return DB::table('family_guardians as fg')
|
||||
->join('families as f', 'f.id', '=', 'fg.family_id')
|
||||
->where('fg.user_id', $parentId)
|
||||
->whereExists(function ($exists) use ($schoolYear) {
|
||||
->whereExists(function ($exists) use ($schoolYear): void {
|
||||
$exists->selectRaw('1')
|
||||
->from('family_students as fs')
|
||||
->join('students as s', 's.id', '=', 'fs.student_id')
|
||||
->whereColumn('fs.family_id', 'f.id')
|
||||
->where('s.school_year', $schoolYear);
|
||||
->whereColumn('fs.family_id', 'f.id');
|
||||
|
||||
$this->constrainStudentToSchoolYear(
|
||||
$exists,
|
||||
'fs.student_id',
|
||||
$schoolYear
|
||||
);
|
||||
})
|
||||
->orderBy('f.household_name')
|
||||
->select('f.*', 'fg.relation', 'fg.is_primary', 'fg.receive_emails', 'fg.receive_sms')
|
||||
->select(
|
||||
'f.*',
|
||||
'fg.relation',
|
||||
'fg.is_primary',
|
||||
'fg.receive_emails',
|
||||
'fg.receive_sms'
|
||||
)
|
||||
->get()
|
||||
->map(fn ($row) => (array) $row)
|
||||
->all();
|
||||
@@ -212,19 +326,27 @@ class ParentProfileAdminQueryService
|
||||
|
||||
private function studentsForParent(int $parentId, string $schoolYear): array
|
||||
{
|
||||
$rows = DB::table('students as s')
|
||||
$rowsQuery = DB::table('students as s')
|
||||
->select('s.id', 's.firstname', 's.lastname', 's.parent_id')
|
||||
->where('s.school_year', $schoolYear)
|
||||
->where(function ($query) use ($parentId) {
|
||||
$query->where('s.parent_id', $parentId)
|
||||
->orWhereExists(function ($exists) use ($parentId) {
|
||||
->where(function ($query) use ($parentId): void {
|
||||
$query
|
||||
->where('s.parent_id', $parentId)
|
||||
->orWhereExists(function ($exists) use ($parentId): void {
|
||||
$exists->selectRaw('1')
|
||||
->from('family_guardians as fg')
|
||||
->join('family_students as fs', 'fs.family_id', '=', 'fg.family_id')
|
||||
->whereColumn('fs.student_id', 's.id')
|
||||
->where('fg.user_id', $parentId);
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
$this->constrainStudentToSchoolYear(
|
||||
$rowsQuery,
|
||||
's.id',
|
||||
$schoolYear
|
||||
);
|
||||
|
||||
$rows = $rowsQuery
|
||||
->orderBy('s.lastname')
|
||||
->orderBy('s.firstname')
|
||||
->get()
|
||||
@@ -233,9 +355,11 @@ class ParentProfileAdminQueryService
|
||||
|
||||
foreach ($rows as &$row) {
|
||||
$studentId = (int) ($row['id'] ?? 0);
|
||||
|
||||
$classSectionName = $studentId > 0
|
||||
? (string) (StudentClass::getClassSectionsByStudentId($studentId, $schoolYear) ?? '')
|
||||
: '';
|
||||
|
||||
$row['class_section_name'] = $classSectionName;
|
||||
$row['grade'] = $classSectionName;
|
||||
}
|
||||
@@ -244,10 +368,10 @@ class ParentProfileAdminQueryService
|
||||
return $rows;
|
||||
}
|
||||
|
||||
private function emergencyContactsForParents(array $guardians, string $schoolYear): array
|
||||
private function emergencyContactsForParents(array $guardians): array
|
||||
{
|
||||
$parentIds = array_values(array_filter(array_map(
|
||||
static fn ($g) => (int) ($g['user_id'] ?? 0),
|
||||
static fn ($guardian) => (int) ($guardian['user_id'] ?? 0),
|
||||
$guardians
|
||||
)));
|
||||
|
||||
@@ -256,12 +380,105 @@ class ParentProfileAdminQueryService
|
||||
}
|
||||
|
||||
return DB::table('emergency_contacts')
|
||||
->select('id', 'parent_id', 'emergency_contact_name', 'relation', 'cellphone', 'email', 'school_year', 'semester', 'created_at', 'updated_at')
|
||||
->select(
|
||||
'id',
|
||||
'parent_id',
|
||||
'emergency_contact_name',
|
||||
'relation',
|
||||
'cellphone',
|
||||
'email',
|
||||
'created_at',
|
||||
'updated_at'
|
||||
)
|
||||
->whereIn('parent_id', $parentIds)
|
||||
->where('school_year', $schoolYear)
|
||||
->orderByDesc('updated_at')
|
||||
->get()
|
||||
->map(fn ($row) => (array) $row)
|
||||
->all();
|
||||
}
|
||||
|
||||
private function schoolYearStudentIds(string $schoolYear): QueryBuilder
|
||||
{
|
||||
$studentClass = DB::table('student_class')
|
||||
->select('student_id');
|
||||
|
||||
$enrollments = DB::table('enrollments')
|
||||
->select('student_id');
|
||||
|
||||
if (! $this->isAllSchoolYears($schoolYear)) {
|
||||
$studentClass->where('school_year', $schoolYear);
|
||||
$enrollments->where('school_year', $schoolYear);
|
||||
}
|
||||
|
||||
return $studentClass->union($enrollments);
|
||||
}
|
||||
|
||||
private function constrainStudentToSchoolYear(
|
||||
QueryBuilder $query,
|
||||
string $studentIdColumn,
|
||||
string $schoolYear
|
||||
): void {
|
||||
if ($this->isAllSchoolYears($schoolYear)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$query->where(function ($yearQuery) use ($studentIdColumn, $schoolYear): void {
|
||||
$yearQuery
|
||||
->whereExists(function ($exists) use ($studentIdColumn, $schoolYear): void {
|
||||
$exists->selectRaw('1')
|
||||
->from('student_class as year_sc')
|
||||
->whereColumn('year_sc.student_id', $studentIdColumn)
|
||||
->where('year_sc.school_year', $schoolYear);
|
||||
})
|
||||
->orWhereExists(function ($exists) use ($studentIdColumn, $schoolYear): void {
|
||||
$exists->selectRaw('1')
|
||||
->from('enrollments as year_e')
|
||||
->whereColumn('year_e.student_id', $studentIdColumn)
|
||||
->where('year_e.school_year', $schoolYear);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private function schoolYearId(string $schoolYear): ?int
|
||||
{
|
||||
if ($this->isAllSchoolYears($schoolYear) || ! Schema::hasTable('school_years')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$schoolYear = trim($schoolYear);
|
||||
|
||||
foreach (['school_year', 'name', 'year', 'label'] as $column) {
|
||||
if (! Schema::hasColumn('school_years', $column)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$id = DB::table('school_years')
|
||||
->where($column, $schoolYear)
|
||||
->value('id');
|
||||
|
||||
if ($id !== null) {
|
||||
return (int) $id;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function applySchoolYearFilter(
|
||||
QueryBuilder $query,
|
||||
string $column,
|
||||
string $schoolYear
|
||||
): void {
|
||||
if (! $this->isAllSchoolYears($schoolYear)) {
|
||||
$query->where($column, $schoolYear);
|
||||
}
|
||||
}
|
||||
|
||||
private function isAllSchoolYears(string $schoolYear): bool
|
||||
{
|
||||
$schoolYear = trim($schoolYear);
|
||||
|
||||
return $schoolYear === '' || strtolower($schoolYear) === 'all';
|
||||
}
|
||||
}
|
||||
Vendored
-56
@@ -1,56 +0,0 @@
|
||||
<?php return array (
|
||||
'laravel/pail' =>
|
||||
array (
|
||||
'providers' =>
|
||||
array (
|
||||
0 => 'Laravel\\Pail\\PailServiceProvider',
|
||||
),
|
||||
),
|
||||
'laravel/sail' =>
|
||||
array (
|
||||
'providers' =>
|
||||
array (
|
||||
0 => 'Laravel\\Sail\\SailServiceProvider',
|
||||
),
|
||||
),
|
||||
'laravel/sanctum' =>
|
||||
array (
|
||||
'providers' =>
|
||||
array (
|
||||
0 => 'Laravel\\Sanctum\\SanctumServiceProvider',
|
||||
),
|
||||
),
|
||||
'nesbot/carbon' =>
|
||||
array (
|
||||
'providers' =>
|
||||
array (
|
||||
0 => 'Carbon\\Laravel\\ServiceProvider',
|
||||
),
|
||||
),
|
||||
'nunomaduro/collision' =>
|
||||
array (
|
||||
'providers' =>
|
||||
array (
|
||||
0 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider',
|
||||
),
|
||||
),
|
||||
'nunomaduro/termwind' =>
|
||||
array (
|
||||
'providers' =>
|
||||
array (
|
||||
0 => 'Termwind\\Laravel\\TermwindServiceProvider',
|
||||
),
|
||||
),
|
||||
'php-open-source-saver/jwt-auth' =>
|
||||
array (
|
||||
'aliases' =>
|
||||
array (
|
||||
'JWTAuth' => 'PHPOpenSourceSaver\\JWTAuth\\Facades\\JWTAuth',
|
||||
'JWTFactory' => 'PHPOpenSourceSaver\\JWTAuth\\Facades\\JWTFactory',
|
||||
),
|
||||
'providers' =>
|
||||
array (
|
||||
0 => 'PHPOpenSourceSaver\\JWTAuth\\Providers\\LaravelServiceProvider',
|
||||
),
|
||||
),
|
||||
);
|
||||
Vendored
-264
@@ -1,264 +0,0 @@
|
||||
<?php return array (
|
||||
'providers' =>
|
||||
array (
|
||||
0 => 'Illuminate\\Auth\\AuthServiceProvider',
|
||||
1 => 'Illuminate\\Broadcasting\\BroadcastServiceProvider',
|
||||
2 => 'Illuminate\\Bus\\BusServiceProvider',
|
||||
3 => 'Illuminate\\Cache\\CacheServiceProvider',
|
||||
4 => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
5 => 'Illuminate\\Concurrency\\ConcurrencyServiceProvider',
|
||||
6 => 'Illuminate\\Cookie\\CookieServiceProvider',
|
||||
7 => 'Illuminate\\Database\\DatabaseServiceProvider',
|
||||
8 => 'Illuminate\\Encryption\\EncryptionServiceProvider',
|
||||
9 => 'Illuminate\\Filesystem\\FilesystemServiceProvider',
|
||||
10 => 'Illuminate\\Foundation\\Providers\\FoundationServiceProvider',
|
||||
11 => 'Illuminate\\Hashing\\HashServiceProvider',
|
||||
12 => 'Illuminate\\Mail\\MailServiceProvider',
|
||||
13 => 'Illuminate\\Notifications\\NotificationServiceProvider',
|
||||
14 => 'Illuminate\\Pagination\\PaginationServiceProvider',
|
||||
15 => 'Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider',
|
||||
16 => 'Illuminate\\Pipeline\\PipelineServiceProvider',
|
||||
17 => 'Illuminate\\Queue\\QueueServiceProvider',
|
||||
18 => 'Illuminate\\Redis\\RedisServiceProvider',
|
||||
19 => 'Illuminate\\Session\\SessionServiceProvider',
|
||||
20 => 'Illuminate\\Translation\\TranslationServiceProvider',
|
||||
21 => 'Illuminate\\Validation\\ValidationServiceProvider',
|
||||
22 => 'Illuminate\\View\\ViewServiceProvider',
|
||||
23 => 'Laravel\\Pail\\PailServiceProvider',
|
||||
24 => 'Laravel\\Sail\\SailServiceProvider',
|
||||
25 => 'Laravel\\Sanctum\\SanctumServiceProvider',
|
||||
26 => 'Carbon\\Laravel\\ServiceProvider',
|
||||
27 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider',
|
||||
28 => 'Termwind\\Laravel\\TermwindServiceProvider',
|
||||
29 => 'PHPOpenSourceSaver\\JWTAuth\\Providers\\LaravelServiceProvider',
|
||||
30 => 'App\\Providers\\AppServiceProvider',
|
||||
31 => 'App\\Providers\\EventServiceProvider',
|
||||
32 => 'Laravel\\Sanctum\\SanctumServiceProvider',
|
||||
),
|
||||
'eager' =>
|
||||
array (
|
||||
0 => 'Illuminate\\Auth\\AuthServiceProvider',
|
||||
1 => 'Illuminate\\Cookie\\CookieServiceProvider',
|
||||
2 => 'Illuminate\\Database\\DatabaseServiceProvider',
|
||||
3 => 'Illuminate\\Encryption\\EncryptionServiceProvider',
|
||||
4 => 'Illuminate\\Filesystem\\FilesystemServiceProvider',
|
||||
5 => 'Illuminate\\Foundation\\Providers\\FoundationServiceProvider',
|
||||
6 => 'Illuminate\\Notifications\\NotificationServiceProvider',
|
||||
7 => 'Illuminate\\Pagination\\PaginationServiceProvider',
|
||||
8 => 'Illuminate\\Session\\SessionServiceProvider',
|
||||
9 => 'Illuminate\\View\\ViewServiceProvider',
|
||||
10 => 'Laravel\\Pail\\PailServiceProvider',
|
||||
11 => 'Laravel\\Sanctum\\SanctumServiceProvider',
|
||||
12 => 'Carbon\\Laravel\\ServiceProvider',
|
||||
13 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider',
|
||||
14 => 'Termwind\\Laravel\\TermwindServiceProvider',
|
||||
15 => 'PHPOpenSourceSaver\\JWTAuth\\Providers\\LaravelServiceProvider',
|
||||
16 => 'App\\Providers\\AppServiceProvider',
|
||||
17 => 'App\\Providers\\EventServiceProvider',
|
||||
18 => 'Laravel\\Sanctum\\SanctumServiceProvider',
|
||||
),
|
||||
'deferred' =>
|
||||
array (
|
||||
'Illuminate\\Broadcasting\\BroadcastManager' => 'Illuminate\\Broadcasting\\BroadcastServiceProvider',
|
||||
'Illuminate\\Contracts\\Broadcasting\\Factory' => 'Illuminate\\Broadcasting\\BroadcastServiceProvider',
|
||||
'Illuminate\\Contracts\\Broadcasting\\Broadcaster' => 'Illuminate\\Broadcasting\\BroadcastServiceProvider',
|
||||
'Illuminate\\Bus\\Dispatcher' => 'Illuminate\\Bus\\BusServiceProvider',
|
||||
'Illuminate\\Contracts\\Bus\\Dispatcher' => 'Illuminate\\Bus\\BusServiceProvider',
|
||||
'Illuminate\\Contracts\\Bus\\QueueingDispatcher' => 'Illuminate\\Bus\\BusServiceProvider',
|
||||
'Illuminate\\Bus\\BatchRepository' => 'Illuminate\\Bus\\BusServiceProvider',
|
||||
'Illuminate\\Bus\\DatabaseBatchRepository' => 'Illuminate\\Bus\\BusServiceProvider',
|
||||
'cache' => 'Illuminate\\Cache\\CacheServiceProvider',
|
||||
'cache.store' => 'Illuminate\\Cache\\CacheServiceProvider',
|
||||
'cache.psr6' => 'Illuminate\\Cache\\CacheServiceProvider',
|
||||
'memcached.connector' => 'Illuminate\\Cache\\CacheServiceProvider',
|
||||
'Illuminate\\Cache\\RateLimiter' => 'Illuminate\\Cache\\CacheServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\AboutCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Cache\\Console\\ClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Cache\\Console\\ForgetCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\ClearCompiledCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Auth\\Console\\ClearResetsCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\ConfigCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\ConfigClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\ConfigShowCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Database\\Console\\DbCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Database\\Console\\MonitorCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Database\\Console\\PruneCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Database\\Console\\ShowCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Database\\Console\\TableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Database\\Console\\WipeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\DownCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\EnvironmentCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\EnvironmentDecryptCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\EnvironmentEncryptCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\EventCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\EventClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\EventListCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Concurrency\\Console\\InvokeSerializedClosureCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\KeyGenerateCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\OptimizeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\OptimizeClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\PackageDiscoverCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Cache\\Console\\PruneStaleTagsCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Queue\\Console\\ClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Queue\\Console\\ListFailedCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Queue\\Console\\FlushFailedCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Queue\\Console\\ForgetFailedCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Queue\\Console\\ListenCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Queue\\Console\\MonitorCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Queue\\Console\\PauseCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Queue\\Console\\PruneBatchesCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Queue\\Console\\PruneFailedJobsCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Queue\\Console\\RestartCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Queue\\Console\\ResumeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Queue\\Console\\RetryCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Queue\\Console\\RetryBatchCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Queue\\Console\\WorkCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\ReloadCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\RouteCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\RouteClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\RouteListCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Database\\Console\\DumpCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Database\\Console\\Seeds\\SeedCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Console\\Scheduling\\ScheduleFinishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Console\\Scheduling\\ScheduleListCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Console\\Scheduling\\ScheduleRunCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Console\\Scheduling\\ScheduleClearCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Console\\Scheduling\\ScheduleTestCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Console\\Scheduling\\ScheduleWorkCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Console\\Scheduling\\ScheduleInterruptCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Database\\Console\\ShowModelCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\StorageLinkCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\StorageUnlinkCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\UpCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\ViewCacheCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\ViewClearCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\ApiInstallCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\BroadcastingInstallCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Cache\\Console\\CacheTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\CastMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\ChannelListCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\ChannelMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\ClassMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\ComponentMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\ConfigMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\ConfigPublishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\ConsoleMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Routing\\Console\\ControllerMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\DocsCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\EnumMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\EventGenerateCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\EventMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\ExceptionMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Database\\Console\\Factories\\FactoryMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\InterfaceMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\JobMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\JobMiddlewareMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\LangPublishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\ListenerMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\MailMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Routing\\Console\\MiddlewareMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\ModelMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\NotificationMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Notifications\\Console\\NotificationTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\ObserverMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\PolicyMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\ProviderMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Queue\\Console\\FailedTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Queue\\Console\\TableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Queue\\Console\\BatchesTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\RequestMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\ResourceMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\RuleMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\ScopeMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Database\\Console\\Seeds\\SeederMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Session\\Console\\SessionTableCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\ServeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\StubPublishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\TestMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\TraitMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\VendorPublishCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Foundation\\Console\\ViewMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'migrator' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'migration.repository' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'migration.creator' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Database\\Migrations\\Migrator' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Database\\Console\\Migrations\\MigrateCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Database\\Console\\Migrations\\FreshCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Database\\Console\\Migrations\\InstallCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Database\\Console\\Migrations\\RefreshCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Database\\Console\\Migrations\\ResetCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Database\\Console\\Migrations\\RollbackCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Database\\Console\\Migrations\\StatusCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Database\\Console\\Migrations\\MigrateMakeCommand' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'composer' => 'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider',
|
||||
'Illuminate\\Concurrency\\ConcurrencyManager' => 'Illuminate\\Concurrency\\ConcurrencyServiceProvider',
|
||||
'hash' => 'Illuminate\\Hashing\\HashServiceProvider',
|
||||
'hash.driver' => 'Illuminate\\Hashing\\HashServiceProvider',
|
||||
'mail.manager' => 'Illuminate\\Mail\\MailServiceProvider',
|
||||
'mailer' => 'Illuminate\\Mail\\MailServiceProvider',
|
||||
'Illuminate\\Mail\\Markdown' => 'Illuminate\\Mail\\MailServiceProvider',
|
||||
'auth.password' => 'Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider',
|
||||
'auth.password.broker' => 'Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider',
|
||||
'Illuminate\\Contracts\\Pipeline\\Hub' => 'Illuminate\\Pipeline\\PipelineServiceProvider',
|
||||
'pipeline' => 'Illuminate\\Pipeline\\PipelineServiceProvider',
|
||||
'queue' => 'Illuminate\\Queue\\QueueServiceProvider',
|
||||
'queue.connection' => 'Illuminate\\Queue\\QueueServiceProvider',
|
||||
'queue.failer' => 'Illuminate\\Queue\\QueueServiceProvider',
|
||||
'queue.listener' => 'Illuminate\\Queue\\QueueServiceProvider',
|
||||
'queue.worker' => 'Illuminate\\Queue\\QueueServiceProvider',
|
||||
'redis' => 'Illuminate\\Redis\\RedisServiceProvider',
|
||||
'redis.connection' => 'Illuminate\\Redis\\RedisServiceProvider',
|
||||
'translator' => 'Illuminate\\Translation\\TranslationServiceProvider',
|
||||
'translation.loader' => 'Illuminate\\Translation\\TranslationServiceProvider',
|
||||
'validator' => 'Illuminate\\Validation\\ValidationServiceProvider',
|
||||
'validation.presence' => 'Illuminate\\Validation\\ValidationServiceProvider',
|
||||
'Illuminate\\Contracts\\Validation\\UncompromisedVerifier' => 'Illuminate\\Validation\\ValidationServiceProvider',
|
||||
'Laravel\\Sail\\Console\\InstallCommand' => 'Laravel\\Sail\\SailServiceProvider',
|
||||
'Laravel\\Sail\\Console\\PublishCommand' => 'Laravel\\Sail\\SailServiceProvider',
|
||||
),
|
||||
'when' =>
|
||||
array (
|
||||
'Illuminate\\Broadcasting\\BroadcastServiceProvider' =>
|
||||
array (
|
||||
),
|
||||
'Illuminate\\Bus\\BusServiceProvider' =>
|
||||
array (
|
||||
),
|
||||
'Illuminate\\Cache\\CacheServiceProvider' =>
|
||||
array (
|
||||
),
|
||||
'Illuminate\\Foundation\\Providers\\ConsoleSupportServiceProvider' =>
|
||||
array (
|
||||
),
|
||||
'Illuminate\\Concurrency\\ConcurrencyServiceProvider' =>
|
||||
array (
|
||||
),
|
||||
'Illuminate\\Hashing\\HashServiceProvider' =>
|
||||
array (
|
||||
),
|
||||
'Illuminate\\Mail\\MailServiceProvider' =>
|
||||
array (
|
||||
),
|
||||
'Illuminate\\Auth\\Passwords\\PasswordResetServiceProvider' =>
|
||||
array (
|
||||
),
|
||||
'Illuminate\\Pipeline\\PipelineServiceProvider' =>
|
||||
array (
|
||||
),
|
||||
'Illuminate\\Queue\\QueueServiceProvider' =>
|
||||
array (
|
||||
),
|
||||
'Illuminate\\Redis\\RedisServiceProvider' =>
|
||||
array (
|
||||
),
|
||||
'Illuminate\\Translation\\TranslationServiceProvider' =>
|
||||
array (
|
||||
),
|
||||
'Illuminate\\Validation\\ValidationServiceProvider' =>
|
||||
array (
|
||||
),
|
||||
'Laravel\\Sail\\SailServiceProvider' =>
|
||||
array (
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -29,12 +29,15 @@ return new class extends Migration
|
||||
if (! Schema::hasColumn('school_years', 'reopened_at')) {
|
||||
$table->timestamp('reopened_at')->nullable()->after('closed_by');
|
||||
}
|
||||
|
||||
if (! Schema::hasColumn('school_years', 'reopened_by')) {
|
||||
$table->unsignedBigInteger('reopened_by')->nullable()->after('reopened_at');
|
||||
}
|
||||
|
||||
if (! Schema::hasColumn('school_years', 'archived_at')) {
|
||||
$table->timestamp('archived_at')->nullable()->after('reopened_by');
|
||||
}
|
||||
|
||||
if (! Schema::hasColumn('school_years', 'archived_by')) {
|
||||
$table->unsignedBigInteger('archived_by')->nullable()->after('archived_at');
|
||||
}
|
||||
@@ -51,9 +54,21 @@ return new class extends Migration
|
||||
$table->string('status', 30)->default('enrolled')->index();
|
||||
$table->unsignedBigInteger('promoted_from_enrollment_id')->nullable();
|
||||
$table->timestamps();
|
||||
$table->unique(['student_id', 'school_year_id'], 'uniq_student_year');
|
||||
$table->index('school_year_id', 'idx_enrollment_school_year');
|
||||
$table->index('student_id', 'idx_enrollment_student');
|
||||
|
||||
$table->unique(
|
||||
['student_id', 'school_year_id'],
|
||||
'uniq_student_year'
|
||||
);
|
||||
|
||||
$table->index(
|
||||
'school_year_id',
|
||||
'idx_enrollment_school_year'
|
||||
);
|
||||
|
||||
$table->index(
|
||||
'student_id',
|
||||
'idx_enrollment_student'
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -66,14 +81,27 @@ return new class extends Migration
|
||||
$table->decimal('opening_balance', 12, 2)->default(0);
|
||||
$table->decimal('current_balance', 12, 2)->default(0);
|
||||
$table->timestamps();
|
||||
$table->unique(['parent_id', 'school_year'], 'uniq_parent_school_year_name');
|
||||
$table->index('parent_id', 'idx_parent_account_parent');
|
||||
$table->index('school_year_id', 'idx_parent_account_school_year_id');
|
||||
|
||||
$table->unique(
|
||||
['parent_id', 'school_year'],
|
||||
'uniq_parent_school_year_name'
|
||||
);
|
||||
|
||||
$table->index(
|
||||
'parent_id',
|
||||
'idx_parent_account_parent'
|
||||
);
|
||||
|
||||
$table->index(
|
||||
'school_year_id',
|
||||
'idx_parent_account_school_year_id'
|
||||
);
|
||||
});
|
||||
} else {
|
||||
Schema::table('parent_accounts', function (Blueprint $table): void {
|
||||
if (! Schema::hasColumn('parent_accounts', 'school_year_id')) {
|
||||
$table->unsignedBigInteger('school_year_id')->nullable()->after('school_year');
|
||||
$table->unsignedBigInteger('school_year_id')
|
||||
->nullable();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -97,31 +125,60 @@ return new class extends Migration
|
||||
$table->text('reversal_reason')->nullable();
|
||||
$table->unsignedBigInteger('created_by')->nullable();
|
||||
$table->timestamps();
|
||||
$table->unique(['parent_id', 'from_school_year', 'to_school_year'], 'uniq_parent_year_transfer_name');
|
||||
$table->index('parent_id', 'idx_balance_transfer_parent');
|
||||
$table->index('from_school_year_id', 'idx_balance_transfer_from_year_id');
|
||||
$table->index('to_school_year_id', 'idx_balance_transfer_to_year_id');
|
||||
|
||||
$table->unique(
|
||||
['parent_id', 'from_school_year', 'to_school_year'],
|
||||
'uniq_parent_year_transfer_name'
|
||||
);
|
||||
|
||||
$table->index(
|
||||
'parent_id',
|
||||
'idx_balance_transfer_parent'
|
||||
);
|
||||
|
||||
$table->index(
|
||||
'from_school_year_id',
|
||||
'idx_balance_transfer_from_year_id'
|
||||
);
|
||||
|
||||
$table->index(
|
||||
'to_school_year_id',
|
||||
'idx_balance_transfer_to_year_id'
|
||||
);
|
||||
});
|
||||
} else {
|
||||
Schema::table('parent_balance_transfers', function (Blueprint $table): void {
|
||||
if (! Schema::hasColumn('parent_balance_transfers', 'from_school_year_id')) {
|
||||
$table->unsignedBigInteger('from_school_year_id')->nullable()->after('to_school_year');
|
||||
$table->unsignedBigInteger('from_school_year_id')
|
||||
->nullable();
|
||||
}
|
||||
|
||||
if (! Schema::hasColumn('parent_balance_transfers', 'to_school_year_id')) {
|
||||
$table->unsignedBigInteger('to_school_year_id')->nullable()->after('from_school_year_id');
|
||||
$table->unsignedBigInteger('to_school_year_id')
|
||||
->nullable()
|
||||
->after('from_school_year_id');
|
||||
}
|
||||
|
||||
if (! Schema::hasColumn('parent_balance_transfers', 'source_summary')) {
|
||||
$table->json('source_summary')->nullable()->after('source_summary_json');
|
||||
$table->json('source_summary')
|
||||
->nullable()
|
||||
->after('source_summary_json');
|
||||
}
|
||||
|
||||
if (! Schema::hasColumn('parent_balance_transfers', 'old_balance_invoice_id')) {
|
||||
$table->unsignedBigInteger('old_balance_invoice_id')->nullable()->after('new_invoice_id');
|
||||
$table->unsignedBigInteger('old_balance_invoice_id')
|
||||
->nullable()
|
||||
->after('new_invoice_id');
|
||||
}
|
||||
|
||||
if (! Schema::hasColumn('parent_balance_transfers', 'reversed_at')) {
|
||||
$table->timestamp('reversed_at')->nullable();
|
||||
}
|
||||
|
||||
if (! Schema::hasColumn('parent_balance_transfers', 'reversed_by')) {
|
||||
$table->unsignedBigInteger('reversed_by')->nullable();
|
||||
}
|
||||
|
||||
if (! Schema::hasColumn('parent_balance_transfers', 'reversal_reason')) {
|
||||
$table->text('reversal_reason')->nullable();
|
||||
}
|
||||
@@ -131,23 +188,36 @@ return new class extends Migration
|
||||
if (Schema::hasTable('invoices')) {
|
||||
Schema::table('invoices', function (Blueprint $table): void {
|
||||
if (! Schema::hasColumn('invoices', 'school_year_id')) {
|
||||
$table->unsignedBigInteger('school_year_id')->nullable()->after('school_year');
|
||||
$table->unsignedBigInteger('school_year_id')
|
||||
->nullable();
|
||||
}
|
||||
|
||||
if (! Schema::hasColumn('invoices', 'parent_id')) {
|
||||
$table->unsignedBigInteger('parent_id')->nullable();
|
||||
}
|
||||
|
||||
if (! Schema::hasColumn('invoices', 'student_id')) {
|
||||
$table->unsignedBigInteger('student_id')->nullable()->after('parent_id');
|
||||
$table->unsignedBigInteger('student_id')
|
||||
->nullable()
|
||||
->after('parent_id');
|
||||
}
|
||||
|
||||
if (! Schema::hasColumn('invoices', 'invoice_type')) {
|
||||
$table->string('invoice_type', 50)->nullable()->after('invoice_number');
|
||||
$table->string('invoice_type', 50)
|
||||
->nullable()
|
||||
->after('invoice_number');
|
||||
}
|
||||
|
||||
if (! Schema::hasColumn('invoices', 'balance_transfer_id')) {
|
||||
$table->unsignedBigInteger('balance_transfer_id')->nullable()->after('invoice_type');
|
||||
$table->unsignedBigInteger('balance_transfer_id')
|
||||
->nullable()
|
||||
->after('invoice_type');
|
||||
}
|
||||
|
||||
if (! Schema::hasColumn('invoices', 'locked_at')) {
|
||||
$table->timestamp('locked_at')->nullable();
|
||||
}
|
||||
|
||||
if (! Schema::hasColumn('invoices', 'locked_by')) {
|
||||
$table->unsignedBigInteger('locked_by')->nullable();
|
||||
}
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
if (
|
||||
Schema::hasTable('login_activity')
|
||||
&& ! Schema::hasColumn('login_activity', 'school_year')
|
||||
) {
|
||||
Schema::table('login_activity', function (Blueprint $table): void {
|
||||
$table->string('school_year', 50)->nullable();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
if (
|
||||
Schema::hasTable('login_activity')
|
||||
&& Schema::hasColumn('login_activity', 'school_year')
|
||||
) {
|
||||
Schema::table('login_activity', function (Blueprint $table): void {
|
||||
$table->dropColumn('school_year');
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user