insertGetId([ 'admin_user_id' => (int)($data['admin_user_id'] ?? 0), 'from_number' => (string)($data['from_number'] ?? ''), 'send_mode' => (string)($data['send_mode'] ?? 'one'), 'schedule_type' => (string)($data['schedule_type'] ?? 'now'), 'scheduled_at' => $data['scheduled_at'] ?? null, 'message_raw' => (string)($data['message_raw'] ?? ''), 'byte_len' => (int)($data['byte_len'] ?? 0), 'sms_type_hint' => (string)($data['sms_type_hint'] ?? 'auto'), 'total_count' => (int)($data['total_count'] ?? 0), 'valid_count' => (int)($data['valid_count'] ?? 0), 'duplicate_count' => (int)($data['duplicate_count'] ?? 0), 'invalid_count' => (int)($data['invalid_count'] ?? 0), 'status' => (string)($data['status'] ?? 'queued'), 'request_ip' => $data['request_ip'] ?? null, 'user_agent' => $data['user_agent'] ?? null, 'error_message' => $data['error_message'] ?? null, 'created_at' => $now, 'updated_at' => $now, ]); } /** * items: [['seq'=>1,'to_number'=>'010...','message_final'=>'...','sms_type'=>'sms','status'=>'queued', ...], ...] */ public function insertItemsChunked(int $batchId, array $items, int $chunkSize = 1000): void { $now = now(); $buf = []; foreach ($items as $it) { $buf[] = [ 'batch_id' => $batchId, 'seq' => (int)($it['seq'] ?? 0), 'to_number' => (string)($it['to_number'] ?? ''), 'message_final' => (string)($it['message_final'] ?? ''), 'sms_type' => (string)($it['sms_type'] ?? 'sms'), 'status' => (string)($it['status'] ?? 'queued'), 'provider' => (string)($it['provider'] ?? 'lguplus'), 'provider_msg_id' => $it['provider_msg_id'] ?? null, 'provider_code' => $it['provider_code'] ?? null, 'provider_message' => $it['provider_message'] ?? null, 'submitted_at' => $it['submitted_at'] ?? null, 'created_at' => $now, 'updated_at' => $now, ]; if (count($buf) >= $chunkSize) { DB::table('admin_sms_batch_items')->insert($buf); $buf = []; } } if (!empty($buf)) { DB::table('admin_sms_batch_items')->insert($buf); } } public function updateBatch(int $batchId, array $data): int { $data['updated_at'] = now(); return (int) DB::table('admin_sms_batches')->where('id', $batchId)->update($data); } public function updateItemBySeq(int $batchId, int $seq, array $data): int { $data['updated_at'] = now(); return (int) DB::table('admin_sms_batch_items') ->where('batch_id', $batchId) ->where('seq', $seq) ->update($data); } public function findBatch(int $batchId): ?object { return DB::table('admin_sms_batches')->where('id', $batchId)->first(); } public function paginateBatches(array $filters, int $perPage = 30): LengthAwarePaginator { $q = DB::table('admin_sms_batches as b') ->leftJoin('admin_users as au', 'au.id', '=', 'b.admin_user_id') ->select([ 'b.*', DB::raw('COALESCE(au.nickname, au.name, au.email) as admin_name'), DB::raw('au.email as admin_email'), ]) ->orderByDesc('b.id'); if (!empty($filters['status'])) { $q->where('b.status', (string)$filters['status']); } if (!empty($filters['send_mode'])) { $q->where('b.send_mode', (string)$filters['send_mode']); } if (!empty($filters['q'])) { $kw = '%' . (string)$filters['q'] . '%'; $q->where(function ($w) use ($kw) { $w->where('b.message_raw', 'like', $kw) ->orWhere('b.from_number', 'like', $kw) ->orWhere('b.request_ip', 'like', $kw); }); } if (!empty($filters['date_from'])) { $q->where('b.created_at', '>=', $filters['date_from'] . ' 00:00:00'); } if (!empty($filters['date_to'])) { $q->where('b.created_at', '<=', $filters['date_to'] . ' 23:59:59'); } return $q->paginate($perPage)->withQueryString(); } public function paginateItems(int $batchId, array $filters, int $perPage = 50): LengthAwarePaginator { $q = DB::table('admin_sms_batch_items') ->where('batch_id', $batchId) ->orderBy('seq'); if (!empty($filters['status'])) { $q->where('status', (string)$filters['status']); } if (!empty($filters['to'])) { $to = preg_replace('/\D+/', '', (string)$filters['to']); if ($to !== '') $q->where('to_number', 'like', '%' . $to . '%'); } if (!empty($filters['q'])) { $kw = '%' . (string)$filters['q'] . '%'; $q->where('message_final', 'like', $kw); } return $q->paginate($perPage)->withQueryString(); } }