e13df69885
API CI/CD / Validate (composer + pint) (push) Successful in 3m6s
API CI/CD / Test (PHPUnit) (push) Failing after 4m53s
API CI/CD / Build frontend assets (push) Successful in 1m2s
API CI/CD / Security audit (push) Failing after 59s
API CI/CD / Deploy to shared hosting (PHP) (push) Has been skipped
172 lines
4.9 KiB
PHP
172 lines
4.9 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
|
|
class WhatsappInviteLog extends BaseModel
|
|
{
|
|
protected $table = 'whatsapp_invites_log';
|
|
|
|
/**
|
|
* legacy: timestamps disabled (we manage sent_at manually)
|
|
*/
|
|
public $timestamps = false;
|
|
|
|
protected $fillable = ['parent_id', 'email', 'class_section_id', 'link_id', 'status', 'error_message', 'sent_at'];
|
|
|
|
protected $casts = [
|
|
'parent_id' => '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'],
|
|
];
|
|
}
|
|
}
|