NETBien.backend/app/Http/Controllers/Netbien/SimCardController.php
2025-11-19 16:21:26 -06:00

345 lines
9.7 KiB
PHP

<?php
namespace App\Http\Controllers\Netbien;
/**
* @copyright (c) 2025 Notsoweb Software (https://notsoweb.com) - All Rights Reserved
*/
use App\Http\Controllers\Controller;
use App\Http\Requests\Netbien\SimCardStoreRequest;
use App\Http\Requests\Netbien\SimCardUpdateRequest;
use App\Models\SimCard;
use App\Models\Client;
use App\Models\ClientSim;
use App\Models\Packages;
use App\Enums\SimCardStatus;
use Illuminate\Http\Request;
use PhpOffice\PhpSpreadsheet\IOFactory;
use Illuminate\Support\Facades\DB;
use Notsoweb\ApiResponse\Enums\ApiResponse;
/**
*
*/
class SimCardController extends Controller
{
public function index()
{
$simCards = SimCard::with('packSims.package:id,name')->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::create([
'name' => $type,
'price' => (float) $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] ?? '',
];
}
}