222 lines
6.6 KiB
PHP
222 lines
6.6 KiB
PHP
<?php namespace App\Http\Controllers\App;
|
|
|
|
|
|
use Illuminate\Http\Request;
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Client;
|
|
use App\Services\ClientTierService;
|
|
use Notsoweb\ApiResponse\Enums\ApiResponse;
|
|
|
|
class ClientController extends Controller
|
|
{
|
|
protected ClientTierService $clientTierService;
|
|
|
|
public function __construct(ClientTierService $clientTierService)
|
|
{
|
|
$this->clientTierService = $clientTierService;
|
|
}
|
|
public function index(Request $request)
|
|
{
|
|
$query = Client::query();
|
|
|
|
if ($request->has('with')) {
|
|
$relations = explode(',', $request->with);
|
|
$query->with($relations);
|
|
}
|
|
|
|
if ($request->has('q') && $request->q) {
|
|
$query->where(function($q) use ($request) {
|
|
$q->where('name', 'like', "%{$request->q}%")
|
|
->orWhere('email', 'like', "%{$request->q}%")
|
|
->orWhere('rfc', 'like', "%{$request->q}%");
|
|
});
|
|
}
|
|
|
|
return ApiResponse::OK->response([
|
|
'clients' => $query->paginate(config('app.pagination')),
|
|
]);
|
|
}
|
|
|
|
public function show(Client $client)
|
|
{
|
|
return ApiResponse::OK->response([
|
|
'client' => $client
|
|
]);
|
|
}
|
|
|
|
public function store(Request $request)
|
|
{
|
|
$request->validate([
|
|
'name' => 'nullable|string|max:255',
|
|
'email' => 'nullable|email|max:255',
|
|
'phone' => 'nullable|string|max:20',
|
|
'address' => 'nullable|string|max:500',
|
|
'rfc' => 'nullable|string|max:13',
|
|
],[
|
|
'email.unique' => 'El correo electrónico ya está en uso por otro cliente.',
|
|
'phone.unique' => 'El teléfono ya está en uso por otro cliente.',
|
|
'rfc.unique' => 'El RFC ya está en uso por otro cliente.',
|
|
]);
|
|
|
|
try{
|
|
$data = $request->only([
|
|
'name',
|
|
'email',
|
|
'phone',
|
|
'address',
|
|
'rfc',
|
|
]);
|
|
|
|
// Generar client_number automáticamente
|
|
$data['client_number'] = $this->clientTierService->generateClientNumber();
|
|
|
|
$client = Client::create($data);
|
|
|
|
// Cargar relación tier
|
|
$client->load('tier');
|
|
|
|
return ApiResponse::OK->response([
|
|
'client' => $client,
|
|
'message' => 'Cliente creado correctamente.'
|
|
]);
|
|
|
|
}catch(\Exception $e){
|
|
return ApiResponse::BAD_REQUEST->response([
|
|
'message' => 'Error al crear el cliente.'
|
|
]);
|
|
}
|
|
}
|
|
|
|
public function update(Request $request, Client $client)
|
|
{
|
|
$request->validate([
|
|
'name' => 'nullable|string|max:255',
|
|
'email' => 'nullable|email|max:255',
|
|
'phone' => 'nullable|string|max:20',
|
|
'address' => 'nullable|string|max:500',
|
|
'rfc' => 'nullable|string|max:13',
|
|
],[
|
|
'email.unique' => 'El correo electrónico ya está en uso por otro cliente.',
|
|
'phone.unique' => 'El teléfono ya está en uso por otro cliente.',
|
|
'rfc.unique' => 'El RFC ya está en uso por otro cliente.',
|
|
]);
|
|
|
|
try{
|
|
|
|
$client->update($request->only([
|
|
'name',
|
|
'email',
|
|
'phone',
|
|
'address',
|
|
'rfc',
|
|
]));
|
|
|
|
return ApiResponse::OK->response([
|
|
'client' => $client,
|
|
'message' => 'Cliente actualizado correctamente.'
|
|
]);
|
|
|
|
}catch(\Exception $e){
|
|
return ApiResponse::BAD_REQUEST->response([
|
|
'message' => 'Error al actualizar el cliente.'
|
|
]);
|
|
}
|
|
}
|
|
|
|
public function destroy(Client $client)
|
|
{
|
|
try{
|
|
$client->delete();
|
|
|
|
return ApiResponse::OK->response([
|
|
'message' => 'Cliente eliminado correctamente.'
|
|
]);
|
|
|
|
}catch(\Exception $e){
|
|
return ApiResponse::BAD_REQUEST->response([
|
|
'message' => 'Error al eliminar el cliente.'
|
|
]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Obtener estadísticas de compra del cliente
|
|
*/
|
|
public function stats(Client $client)
|
|
{
|
|
try {
|
|
$stats = $this->clientTierService->getClientStats($client);
|
|
|
|
return ApiResponse::OK->response([
|
|
'stats' => $stats
|
|
]);
|
|
} catch(\Exception $e) {
|
|
return ApiResponse::BAD_REQUEST->response([
|
|
'message' => 'Error al obtener estadísticas del cliente.'
|
|
]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Obtener historial de cambios de tier del cliente
|
|
*/
|
|
public function tierHistory(Client $client)
|
|
{
|
|
try {
|
|
$history = $client->tierHistory()
|
|
->with(['oldTier', 'newTier'])
|
|
->orderBy('changed_at', 'desc')
|
|
->get();
|
|
|
|
return ApiResponse::OK->response([
|
|
'history' => $history
|
|
]);
|
|
} catch(\Exception $e) {
|
|
return ApiResponse::BAD_REQUEST->response([
|
|
'message' => 'Error al obtener historial del cliente.'
|
|
]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Obtener ventas con descuento de un cliente
|
|
*/
|
|
public function salesWithDiscounts(Client $client, Request $request)
|
|
{
|
|
try {
|
|
$query = $client->sales()
|
|
->where('discount_amount', '>', 0)
|
|
->with(['details', 'user:id,name'])
|
|
->orderBy('created_at', 'desc');
|
|
|
|
// Filtro por rango de fechas
|
|
if ($request->has('date_from')) {
|
|
$query->where('created_at', '>=', $request->date_from);
|
|
}
|
|
|
|
if ($request->has('date_to')) {
|
|
$query->where('created_at', '<=', $request->date_to);
|
|
}
|
|
|
|
$sales = $query->paginate($request->per_page ?? 15);
|
|
|
|
// Calcular totales
|
|
$totals = [
|
|
'total_sales' => $client->sales()->where('discount_amount', '>', 0)->count(),
|
|
'total_amount' => $client->sales()->where('discount_amount', '>', 0)->sum('total'),
|
|
'total_discounts' => $client->sales()->where('discount_amount', '>', 0)->sum('discount_amount'),
|
|
];
|
|
|
|
return ApiResponse::OK->response([
|
|
'sales' => $sales,
|
|
'totals' => $totals
|
|
]);
|
|
} catch(\Exception $e) {
|
|
return ApiResponse::BAD_REQUEST->response([
|
|
'message' => 'Error al obtener ventas con descuentos.',
|
|
'error' => $e->getMessage()
|
|
]);
|
|
}
|
|
}
|
|
}
|