orderBy('id', 'asc')->paginate(config('app.pagination')); return ApiResponse::OK->response([ 'data' => $simCards, ]); } public function show(SimCard $simCard) { $simCard->load('packSims.package:id,name'); return ApiResponse::OK->response([ 'data' => $simCard, ]); } public function store(SimCardStoreRequest $request) { try { DB::beginTransaction(); $simCard = SimCard::create($request->validated()); if ($request->has('package_id')) { // Asignar el paquete con fecha de activación $simCard->packages()->attach($request->package_id, [ 'activated_at' => now(), 'is_active' => true, ]); } DB::commit(); $simCard->load('activePackage'); return ApiResponse::CREATED->response([ 'data' => $simCard, ]); } catch (\Exception $e) { DB::rollBack(); return ApiResponse::INTERNAL_ERROR->response([ 'message' => 'Error al crear SIM card', 'error' => $e->getMessage(), ]); } } public function update(SimCardUpdateRequest $request, SimCard $simCard) { $simCard->update($request->validated()); return ApiResponse::OK->response([ 'data' => $simCard, ]); } public function destroy(SimCard $simCard) { try { DB::beginTransaction(); $simCard->delete(); DB::commit(); return ApiResponse::NO_CONTENT->response(); } catch (\Exception $e) { DB::rollBack(); return ApiResponse::INTERNAL_ERROR->response([ 'message' => 'Error al eliminar SIM card', 'error' => $e->getMessage(), ]); } } /* ---------------------Importar Excel--------------------------- */ private $packageCache = []; private $stats = [ 'created' => 0, 'assigned' => 0, 'packages_created' => 0, 'clients_created' => 0, 'errors' => [], ]; public function import(Request $request) { $request->validate([ 'file' => 'required|mimes:xlsx,xls,csv|max:10240', ]); try { $file = $request->file('file'); $spreadsheet = IOFactory::load($file->getRealPath()); $sheet = $spreadsheet->getActiveSheet(); $rows = $sheet->toArray(); foreach ($rows as $index => $row) { if ($index === 0) continue; $this->processRow([ 'iccid' => $row[4] ?? null, 'msisdn' => $row[5] ?? null, 'estado_de_la_sim' => $row[9] ?? null, 'usuario' => $row[8] ?? null, ]); } return ApiResponse::OK->response([ 'success' => true, 'message' => 'Importación completada', 'stats' => $this->stats, 'packages_created' => array_values(array_map(fn($p) => [ 'name' => $p->name, 'price' => $p->price ], $this->packageCache)), ]); } catch (\Exception $e) { return ApiResponse::BAD_REQUEST->response([ 'success' => false, 'message' => 'Error en la importación', 'error' => $e->getMessage(), 'line' => $e->getLine(), ], 500); } } private function processRow(array $row) { // Validar campos requeridos if (empty($row['iccid']) || empty($row['msisdn'])) { return; } try { DB::transaction(function () use ($row) { // Buscar o crear la SIM $sim = SimCard::where('iccid', $row['iccid'])->first(); if (!$sim) { // No existe, crearla $sim = SimCard::create([ 'iccid' => $row['iccid'], 'msisdn' => $row['msisdn'], 'status' => SimCardStatus::AVAILABLE, ]); $this->stats['created']++; } $this->processPackageFromText($sim, $row); // Asignar cliente $this->assignToClient($sim, $row); }); } catch (\Exception $e) { $this->stats['errors'][] = [ 'iccid' => $row['iccid'] ?? 'N/A', 'error' => $e->getMessage(), ]; } } private function processPackageFromText(SimCard $sim, array $row) { $estadoSim = trim($row['estado_de_la_sim'] ?? ''); if (empty($estadoSim)) { return; } $packageInfo = $this->parsePackageText($estadoSim); if (!$packageInfo) { $this->stats['errors'][] = [ 'iccid' => $sim->iccid, 'estado_sim' => $estadoSim, 'reason' => 'No se pudo parsear el paquete' ]; return; } $package = $this->getOrCreatePackage( $packageInfo['type'], $packageInfo['price'] ); $sim->packages()->attach($package->id, [ 'activated_at' => now(), 'is_active' => true, ]); } private function parsePackageText(string $text): ?array { $text = strtolower($text); $type = null; if (str_contains($text, 'precarga') || str_contains($text, 'pre carga')) { $type = 'Precarga'; } elseif (str_contains($text, 'prepago') || str_contains($text, 'pre pago')) { $type = 'Prepago'; } if (!$type) { return null; } preg_match('/\$?\s*(\d+)(?:\.\d+)?/', $text, $matches); $price = isset($matches[1]) ? (float) $matches[1] : 0; return ['type' => $type, 'price' => $price]; } private function getOrCreatePackage(string $type, float $price): Packages { $cacheKey = "{$type}_{$price}"; if (isset($this->packageCache[$cacheKey])) { return $this->packageCache[$cacheKey]; } $package = Packages::firstOrCreate( ['name' => $type, 'price' => $price], ['period' => 0, 'data_limit' => 0] ); if ($package->wasRecentlyCreated) { $this->stats['packages_created']++; } $this->packageCache[$cacheKey] = $package; return $package; } private function assignToClient(SimCard $sim, array $row) { $usuario = trim($row['usuario'] ?? ''); if (empty($usuario) || strtolower($usuario) === 'si' || strtolower($usuario) === 'no') { return; } $client = Client::where('full_name', $usuario)->first() ?? Client::where('full_name', 'LIKE', "%{$usuario}%")->first() ?? Client::where(function ($query) use ($usuario) { $query->whereRaw("CONCAT(name, ' ', IFNULL(paternal,''), ' ', IFNULL(maternal,'')) LIKE ?", ["%{$usuario}%"]); })->first(); if (!$client) { $nameParts = $this->splitFullName($usuario); try { $client = Client::create([ 'full_name' => $usuario, 'name' => $nameParts['name'], 'paternal' => $nameParts['paternal'], 'maternal' => $nameParts['maternal'], ]); $this->stats['clients_created']++; } catch (\Exception $e) { $this->stats['errors'][] = [ 'usuario' => $usuario, 'error' => 'Error al crear cliente: ' . $e->getMessage() ]; return; } } $existingRelation = ClientSim::where('client_id', $client->id) ->where('sim_card_id', $sim->id) ->where('is_active', true) ->exists(); if ($existingRelation) { return; } try { ClientSim::create([ 'client_id' => $client->id, 'sim_card_id' => $sim->id, 'assigned_at' => now(), 'is_active' => true, ]); $sim->update(['status' => SimCardStatus::ASSIGNED]); $this->stats['assigned']++; } catch (\Exception $e) { $this->stats['errors'][] = [ 'iccid' => $sim->iccid, 'usuario' => $usuario, 'error' => 'Error al asignar cliente: ' . $e->getMessage() ]; } } private function splitFullName(string $fullName): array { $parts = array_filter(explode(' ', trim($fullName))); $parts = array_values($parts); return [ 'name' => $parts[0] ?? '', 'paternal' => $parts[1] ?? '', 'maternal' => $parts[2] ?? '', ]; } }