'integer', 'class_section_id' => 'integer', 'link_id' => 'integer', 'sent_at' => 'datetime', ]; /* ============================================================ * Status constants (optional but helpful) * ============================================================ */ public const STATUS_SENT = 'sent'; public const STATUS_FAILED = 'failed'; /* ============================================================ * Relationships (optional) * ============================================================ */ public function parent(): BelongsTo { // If "parents" are users in your DB, keep User::class. // If you have a Parent model/table, change it accordingly. return $this->belongsTo(User::class, 'parent_id'); } public function link(): BelongsTo { // Link row (whatsapp_group_links) return $this->belongsTo(WhatsappGroupLink::class, 'link_id'); } public function classSection(): BelongsTo { // Adjust keys if your ClassSection model uses a different PK return $this->belongsTo(ClassSection::class, 'class_section_id', 'class_section_id'); } /* ============================================================ * Scopes * ============================================================ */ public function scopeForParent(Builder $q, int $parentId): Builder { return $q->where('parent_id', $parentId); } public function scopeForSection(Builder $q, int $classSectionId): Builder { return $q->where('class_section_id', $classSectionId); } public function scopeStatus(Builder $q, string $status): Builder { return $q->where('status', $status); } public function scopeLatestFirst(Builder $q): Builder { return $q->orderByDesc('sent_at')->orderByDesc('id'); } /* ============================================================ * legacy-compatible helpers * ============================================================ */ /** * Log a successful send. */ public static function logSuccess( int $parentId, string $email, ?int $classSectionId = null, ?int $linkId = null ): bool { static::query()->create([ 'parent_id' => $parentId, 'email' => $email, 'class_section_id' => $classSectionId, 'link_id' => $linkId, 'status' => self::STATUS_SENT, 'error_message' => null, 'sent_at' => now(), ]); return true; } /** * Log a failure with error message. */ public static function logFailure( int $parentId, string $email, string $error, ?int $classSectionId = null, ?int $linkId = null ): bool { static::query()->create([ 'parent_id' => $parentId, 'email' => $email, 'class_section_id' => $classSectionId, 'link_id' => $linkId, 'status' => self::STATUS_FAILED, 'error_message' => $error, 'sent_at' => now(), ]); return true; } /** * Get logs for a parent and/or section. * legacy: getLogs($parentId = null, $classSectionId = null) */ public static function getLogs(?int $parentId = null, ?int $classSectionId = null): array { $q = static::query(); if ($parentId) { $q->forParent($parentId); } if ($classSectionId) { $q->forSection($classSectionId); } return $q->latestFirst()->get()->all(); } /* ============================================================ * Optional validation helper (FormRequest/controller) * Mirrors legacy validation intent * ============================================================ */ public static function rules(bool $updating = false): array { $req = $updating ? 'sometimes' : 'required'; return [ 'parent_id' => [$req, 'integer', 'min:1'], 'email' => [$req, 'email', 'max:255'], 'status' => [$req, 'string', 'max:20'], 'class_section_id' => ['nullable', 'integer'], 'link_id' => ['nullable', 'integer'], 'error_message' => ['nullable', 'string', 'max:5000'], 'sent_at' => ['nullable', 'date'], ]; } }