HEX
Server: Apache/2.4.58 (Ubuntu)
System: Linux Bradford-Sitios 6.14.0-1017-azure #17~24.04.1-Ubuntu SMP Mon Dec 1 20:10:50 UTC 2025 x86_64
User: www-data (33)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: /var/www/matriculas_api_dev/app/Http/Controllers/PeriodPricingController.php
<?php

namespace App\Http\Controllers;

use App\Models\PaymentConceptDetail;
use App\Services\PeriodPricingService;
use Illuminate\Http\Request;
use Exception;

class PeriodPricingController extends Controller
{
    protected $periodPricingService;

    public function __construct(PeriodPricingService $periodPricingService)
    {
        $this->periodPricingService = $periodPricingService;
    }

    /**
     * Listar configuraciones de precios por periodo.
     */
    public function list($periodId)
    {
        $configs = $this->periodPricingService->list($periodId);
        return genericResponse(['data' => $configs, 'message' => 'ok', 'code' => 200], 200);
    }

    /**
     * Crear configuración de precio.
     */
    public function store(Request $request)
    {
        $request->validate([
            'period_id' => 'required|integer',
            'config_type' => 'required|string',
            'concept_code' => 'required|string',
            'currency_type' => 'required|string',
        ]);

        try {
            $config = $this->periodPricingService->store($request->all());
            return genericResponse(['data' => $config, 'message' => 'Configuración creada', 'code' => 201], 201);
        } catch (Exception $e) {
            return genericResponse(['data' => null, 'message' => $e->getMessage(), 'code' => $e->getCode() ?: 500], $e->getCode() ?: 500);
        }
    }

    /**
     * Actualizar configuración de precio.
     */
    public function update($id, Request $request)
    {
        $config = $this->periodPricingService->update($id, $request->all());
        return genericResponse(['data' => $config, 'message' => 'Configuración actualizada', 'code' => 200], 200);
    }

    /**
     * Eliminar configuración de precio.
     */
    public function destroy($id)
    {
        $this->periodPricingService->destroy($id);
        return genericResponse(['data' => null, 'message' => 'Configuración eliminada', 'code' => 200], 200);
    }

    /**
     * Copiar configuraciones de un periodo a otro.
     */
    public function copy(Request $request)
    {
        $request->validate([
            'from_period_id' => 'required|integer',
            'to_period_id' => 'required|integer',
        ]);

        $result = $this->periodPricingService->copy($request->from_period_id, $request->to_period_id);
        $message = "Copiados {$result['created']} conceptos" . ($result['skipped'] > 0 ? " ({$result['skipped']} ya existían)" : "");
        return genericResponse(['data' => $result, 'message' => $message, 'code' => 200], 200);
    }

    /**
     * Eliminar múltiples configuraciones.
     */
    public function bulkDelete(Request $request)
    {
        $request->validate(['ids' => 'required|array']);
        $this->periodPricingService->bulkDelete($request->ids);
        return genericResponse(['data' => null, 'message' => 'Configuraciones eliminadas', 'code' => 200], 200);
    }

    /**
     * Guardar configuraciones masivas.
     */
    public function bulkSave(Request $request)
    {
        $request->validate([
            'period_id' => 'required|integer',
            'configs' => 'required|array',
        ]);

        $result = $this->periodPricingService->bulkSave($request->period_id, $request->configs);
        $message = count($result['skipped']) > 0
            ? 'Configuraciones guardadas. ' . count($result['skipped']) . ' duplicado(s) omitido(s).'
            : 'Configuraciones guardadas';
        return genericResponse(['data' => $result, 'message' => $message, 'code' => 200], 200);
    }

    /**
     * Importar configuraciones de precios desde Excel.
     */
    public function importExcel(Request $request)
    {
        $request->validate([
            'period_id' => 'required|integer|exists:periods,id',
            'file' => 'required|file|mimes:xlsx,xls|max:5120',
        ]);

        try {
            $result = $this->periodPricingService->importFromExcel(
                $request->period_id,
                $request->file('file')
            );

            $message = "Importación completada: {$result['created']} creados, {$result['updated']} actualizados";
            if (count($result['errors']) > 0) {
                $message .= ", " . count($result['errors']) . " errores";
            }

            return genericResponse([
                'data' => $result,
                'message' => $message,
                'code' => 200,
            ], 200);
        } catch (Exception $e) {
            return genericResponse(['error' => $e->getMessage()], $e->getCode() ?: 500);
        }
    }

    /**
     * Listar códigos de conceptos de pago disponibles.
     */
    public function conceptCodes()
    {
        $concepts = PaymentConceptDetail::where('status', 1)
            ->select('code', 'description')
            ->orderBy('description')
            ->get();

        return genericResponse(['data' => $concepts, 'message' => 'ok', 'code' => 200], 200);
    }

    /**
     * Exportar configuraciones de precios a Excel.
     */
    public function exportExcel($periodId)
    {
        try {
            $result = $this->periodPricingService->exportToExcel($periodId);

            return response()->download($result['tempFile'], $result['fileName'], [
                'Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            ])->deleteFileAfterSend(true);
        } catch (Exception $e) {
            return genericResponse(['error' => $e->getMessage()], $e->getCode() ?: 500);
        }
    }
}