Modificaciones a usuarios y roles #2
@ -5,6 +5,7 @@
|
|||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\CashClose;
|
use App\Models\CashClose;
|
||||||
use App\Models\Sale;
|
use App\Models\Sale;
|
||||||
|
use App\Models\SaleItem;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Notsoweb\ApiResponse\Enums\ApiResponse;
|
use Notsoweb\ApiResponse\Enums\ApiResponse;
|
||||||
@ -35,28 +36,59 @@ public function index(Request $request)
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function closeCashClose($id)
|
public function closeCashClose(Request $request)
|
||||||
{
|
{
|
||||||
$today = now()->format('Y-m-d');
|
$request ->validate([
|
||||||
|
'exit' => 'sometimes|numeric|min:0',
|
||||||
|
]);
|
||||||
|
|
||||||
$cashClose = CashClose::findOrFail($id);
|
$cashClose = CashClose::open()->first();
|
||||||
|
|
||||||
$totalSales = Sale::where('cash_close_id', $id)->sum('total_amount');
|
if(!$cashClose) {
|
||||||
$paymentMethods = Sale::where('cash_close_id', $id)
|
return ApiResponse::NOT_FOUND->response([
|
||||||
|
'message' => 'No hay un corte de caja abierto para cerrar.',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$totalSales = Sale::where('cash_close_id', $cashClose->id)->sum('total_amount');
|
||||||
|
|
||||||
|
$paymentMethods = Sale::where('cash_close_id', $cashClose->id)
|
||||||
->select('payment_method', DB::raw('SUM(total_amount) as total'))
|
->select('payment_method', DB::raw('SUM(total_amount) as total'))
|
||||||
->groupBy('payment_method')
|
->groupBy('payment_method')
|
||||||
->get();
|
->pluck('total', 'payment_method');
|
||||||
|
|
||||||
|
$exit = $request->input('exit', 0);
|
||||||
|
|
||||||
$cashClose->update([
|
$cashClose->update([
|
||||||
|
'closed_at' => now(),
|
||||||
'income' => $totalSales,
|
'income' => $totalSales,
|
||||||
'balance' => $totalSales - $cashClose->exit,
|
'exit' => $exit,
|
||||||
|
'income_cash' => $paymentMethods->get('cash', 0),
|
||||||
|
'income_card' => $paymentMethods->get('card', 0),
|
||||||
|
'income_transfer' => $paymentMethods->get('transfer', 0),
|
||||||
'status' => 'closed',
|
'status' => 'closed',
|
||||||
'close_date' => $today,
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$balanceFinal = $cashClose->initial_balance + $totalSales - $exit;
|
||||||
|
|
||||||
return ApiResponse::OK->response([
|
return ApiResponse::OK->response([
|
||||||
'message' => 'Corte de caja cerrado exitosamente.',
|
'message' => 'Corte de caja cerrado exitosamente.',
|
||||||
'data' => $cashClose,
|
'cash_close' => $cashClose->fresh('user'),
|
||||||
|
'resumen' => [
|
||||||
|
'periodo' => [
|
||||||
|
'apertura' => $cashClose->opened_at,
|
||||||
|
'cierre' => $cashClose->closed_at,
|
||||||
|
],
|
||||||
|
'totales' => [
|
||||||
|
'fondo_inicial' => $cashClose->initial_balance,
|
||||||
|
'total_ventas' => $totalSales,
|
||||||
|
'efectivo' => $paymentMethods->get('cash', 0),
|
||||||
|
'tarjeta' => $paymentMethods->get('card', 0),
|
||||||
|
'transferencia' => $paymentMethods->get('transfer', 0),
|
||||||
|
'egresos' => $exit,
|
||||||
|
'balance_final' => $balanceFinal,
|
||||||
|
],
|
||||||
|
],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,6 +21,29 @@ public function index()
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function search(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'filter' => 'required|string|min:2',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$search = $request->input('filter');
|
||||||
|
|
||||||
|
$clients = Client::with('simCards:id,msisdn')
|
||||||
|
->where(function($q) use ($search) {
|
||||||
|
$q->whereRaw("CONCAT(name, ' ', paternal, ' ', maternal) LIKE ?", ["%{$search}%"])
|
||||||
|
->orWhere('rfc', 'like', "%{$search}%")
|
||||||
|
->orWhere('email', 'like', "%{$search}%")
|
||||||
|
->orWhere('phone', 'like', "%{$search}%");
|
||||||
|
})
|
||||||
|
->orderBy('id', 'asc')
|
||||||
|
->paginate(config('app.pagination'));
|
||||||
|
|
||||||
|
return ApiResponse::OK->response([
|
||||||
|
'data' => $clients,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
public function show(Client $client)
|
public function show(Client $client)
|
||||||
{
|
{
|
||||||
$client->load('simCards:id,msisdn');
|
$client->load('simCards:id,msisdn');
|
||||||
|
|||||||
@ -1,27 +1,31 @@
|
|||||||
<?php namespace App\Models;
|
<?php namespace App\Models;
|
||||||
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class CashClose extends Model
|
class CashClose extends Model
|
||||||
{
|
{
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'balance',
|
'user_id',
|
||||||
|
'opened_at',
|
||||||
|
'closed_at',
|
||||||
|
'initial_balance',
|
||||||
'income',
|
'income',
|
||||||
'exit',
|
'exit',
|
||||||
'close_date',
|
'income_cash',
|
||||||
|
'income_card',
|
||||||
|
'income_transfer',
|
||||||
'status',
|
'status',
|
||||||
'user_id',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'balance' => 'decimal:2',
|
'initial_balance' => 'decimal:2',
|
||||||
'income' => 'decimal:2',
|
'income' => 'decimal:2',
|
||||||
'exit' => 'decimal:2',
|
'exit' => 'decimal:2',
|
||||||
'close_date' => 'date',
|
'income_cash' => 'decimal:2',
|
||||||
|
'income_card' => 'decimal:2',
|
||||||
|
'income_transfer' => 'decimal:2',
|
||||||
|
'opened_at' => 'datetime',
|
||||||
|
'closed_at' => 'datetime',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -55,26 +59,4 @@ public function scopeClosed($query)
|
|||||||
{
|
{
|
||||||
return $query->where('status', 'closed');
|
return $query->where('status', 'closed');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Scope para cortes de una fecha específica
|
|
||||||
*/
|
|
||||||
public function scopeByDate($query, $date)
|
|
||||||
{
|
|
||||||
return $query->whereDate('close_date', $date);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calcula automáticamente el balance
|
|
||||||
*/
|
|
||||||
public function calculateBalance()
|
|
||||||
{
|
|
||||||
$this->balance = $this->income - $this->exit;
|
|
||||||
|
|
||||||
if ($this->expected_balance) {
|
|
||||||
$this->difference = $this->balance - $this->expected_balance;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->balance;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,17 +12,19 @@ class CashCloseService
|
|||||||
*/
|
*/
|
||||||
public static function getOrCreateOpenCashClose()
|
public static function getOrCreateOpenCashClose()
|
||||||
{
|
{
|
||||||
$today = now()->format('Y-m-d');
|
$cashClose = CashClose::open()->first();
|
||||||
$cashClose = CashClose::open()->byDate($today)->first();
|
|
||||||
|
|
||||||
if (!$cashClose) {
|
if (!$cashClose) {
|
||||||
$cashClose = CashClose::create([
|
$cashClose = CashClose::create([
|
||||||
'close_date' => $today,
|
'user_id' => Auth::id(),
|
||||||
|
'opened_at' => now(),
|
||||||
|
'initial_balance' => 0,
|
||||||
'income' => 0,
|
'income' => 0,
|
||||||
'exit' => 0,
|
'exit' => 0,
|
||||||
'balance' => 0,
|
'income_cash' => 0,
|
||||||
|
'income_card' => 0,
|
||||||
|
'income_transfer' => 0,
|
||||||
'status' => 'open',
|
'status' => 'open',
|
||||||
'user_id' => Auth::id(),
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,7 @@ public function up(): void
|
|||||||
$table->decimal('balance', 10, 2);
|
$table->decimal('balance', 10, 2);
|
||||||
$table->decimal('income', 10, 2);
|
$table->decimal('income', 10, 2);
|
||||||
$table->decimal('exit', 10, 2)->default(0);
|
$table->decimal('exit', 10, 2)->default(0);
|
||||||
$table->enum('status', ['open', 'closed', 'reviewed'])->default('open')->comment('Estado del corte');
|
$table->enum('status', ['open', 'closed'])->default('open')->comment('Estado del corte');
|
||||||
$table->timestamp('close_date');
|
$table->timestamp('close_date');
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('clients', function (Blueprint $table) {
|
||||||
|
$table->string('rfc', 13)->unique()->change();
|
||||||
|
$table->string('phone')->unique()->change();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('cash_closes', function (Blueprint $table) {
|
||||||
|
$table->timestamp('opened_at')->nullable()->after('user_id');
|
||||||
|
|
||||||
|
$table->decimal('initial_balance', 10, 2)->default(0)->after('user_id');
|
||||||
|
|
||||||
|
$table->dropColumn('balance');
|
||||||
|
|
||||||
|
$table->decimal('income_cash', 10, 2)->default(0)->after('income');
|
||||||
|
$table->decimal('income_card', 10, 2)->default(0)->after('income_cash');
|
||||||
|
$table->decimal('income_transfer', 10, 2)->default(0)->after('income_card');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Renombrar y hacer nullable en una segunda operación
|
||||||
|
Schema::table('cash_closes', function (Blueprint $table) {
|
||||||
|
$table->renameColumn('close_date', 'closed_at');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Modificar closed_at para que sea nullable
|
||||||
|
Schema::table('cash_closes', function (Blueprint $table) {
|
||||||
|
$table->timestamp('closed_at')->nullable()->change();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('cash_closes', function (Blueprint $table) {
|
||||||
|
$table->timestamp('closed_at')->nullable(false)->change();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('cash_closes', function (Blueprint $table) {
|
||||||
|
$table->renameColumn('closed_at', 'close_date');
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('cash_closes', function (Blueprint $table) {
|
||||||
|
$table->dropColumn([
|
||||||
|
'opened_at',
|
||||||
|
'initial_balance',
|
||||||
|
'income_cash',
|
||||||
|
'income_card',
|
||||||
|
'income_transfer',
|
||||||
|
]);
|
||||||
|
$table->decimal('balance', 10, 2)->after('user_id');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -34,6 +34,7 @@ public function run(): void
|
|||||||
'maternal' => 'Cruz',
|
'maternal' => 'Cruz',
|
||||||
'email' => 'maria.hernandez@example.com',
|
'email' => 'maria.hernandez@example.com',
|
||||||
'phone' => '555-1003',
|
'phone' => '555-1003',
|
||||||
|
'rfc' => 'MAHC910203XXX',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => 'Carlos',
|
'name' => 'Carlos',
|
||||||
@ -41,6 +42,7 @@ public function run(): void
|
|||||||
'maternal' => 'Ruiz',
|
'maternal' => 'Ruiz',
|
||||||
'email' => 'carlos.sanchez@example.com',
|
'email' => 'carlos.sanchez@example.com',
|
||||||
'phone' => '555-1004',
|
'phone' => '555-1004',
|
||||||
|
'rfc' => 'CASR910203XXX',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'name' => 'Laura',
|
'name' => 'Laura',
|
||||||
@ -48,6 +50,7 @@ public function run(): void
|
|||||||
'maternal' => 'Flores',
|
'maternal' => 'Flores',
|
||||||
'email' => 'laura.gomez@example.com',
|
'email' => 'laura.gomez@example.com',
|
||||||
'phone' => '555-1005',
|
'phone' => '555-1005',
|
||||||
|
'rfc' => 'LAGF910203XXX',
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@ -7,9 +7,9 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Seeder de desarrollo
|
* Seeder de desarrollo
|
||||||
*
|
*
|
||||||
* @author Moisés Cortés C. <moises.cortes@notsoweb.com>
|
* @author Moisés Cortés C. <moises.cortes@notsoweb.com>
|
||||||
*
|
*
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
*/
|
*/
|
||||||
class DevSeeder extends Seeder
|
class DevSeeder extends Seeder
|
||||||
@ -22,5 +22,9 @@ public function run(): void
|
|||||||
$this->call(RoleSeeder::class);
|
$this->call(RoleSeeder::class);
|
||||||
$this->call(UserSeeder::class);
|
$this->call(UserSeeder::class);
|
||||||
$this->call(SettingSeeder::class);
|
$this->call(SettingSeeder::class);
|
||||||
|
|
||||||
|
$this->call(ClientSeeder::class);
|
||||||
|
$this->call(SimCardSeeder::class);
|
||||||
|
$this->call(PackageSeeder::class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,9 +19,9 @@ services:
|
|||||||
mem_limit: 512m
|
mem_limit: 512m
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- "host.docker.internal:host-gateway"
|
- "host.docker.internal:host-gateway"
|
||||||
# depends_on:
|
depends_on:
|
||||||
# mysql:
|
mysql:
|
||||||
# condition: service_healthy
|
condition: service_healthy
|
||||||
|
|
||||||
nginx:
|
nginx:
|
||||||
image: nginx:alpine
|
image: nginx:alpine
|
||||||
@ -36,37 +36,37 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- netbien-backend
|
- netbien-backend
|
||||||
|
|
||||||
# mysql:
|
mysql:
|
||||||
# image: mysql:8.0
|
image: mysql:8.0
|
||||||
# environment:
|
environment:
|
||||||
# MYSQL_DATABASE: ${DB_DATABASE}
|
MYSQL_DATABASE: ${DB_DATABASE}
|
||||||
# MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
|
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
|
||||||
# MYSQL_PASSWORD: ${DB_PASSWORD}
|
MYSQL_PASSWORD: ${DB_PASSWORD}
|
||||||
# MYSQL_USER: ${DB_USERNAME}
|
MYSQL_USER: ${DB_USERNAME}
|
||||||
# ports:
|
ports:
|
||||||
# - "${DB_PORT}:3306"
|
- "${DB_PORT}:3306"
|
||||||
# volumes:
|
volumes:
|
||||||
# - mysql_data:/var/lib/mysql
|
- mysql_data:/var/lib/mysql
|
||||||
# networks:
|
networks:
|
||||||
# - netbien-network
|
- netbien-network
|
||||||
# mem_limit: 512m
|
mem_limit: 512m
|
||||||
# healthcheck:
|
healthcheck:
|
||||||
# test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
||||||
# timeout: 15s
|
timeout: 15s
|
||||||
# retries: 10
|
retries: 10
|
||||||
|
|
||||||
# phpmyadmin:
|
phpmyadmin:
|
||||||
# image: phpmyadmin/phpmyadmin
|
image: phpmyadmin/phpmyadmin
|
||||||
# environment:
|
environment:
|
||||||
# PMA_HOST: mysql
|
PMA_HOST: mysql
|
||||||
# PMA_PORT: 3306
|
PMA_PORT: 3306
|
||||||
# ports:
|
ports:
|
||||||
# - "${PMA_PORT}:80"
|
- "${PMA_PORT}:80"
|
||||||
# depends_on:
|
depends_on:
|
||||||
# - mysql
|
- mysql
|
||||||
# networks:
|
networks:
|
||||||
# - netbien-network
|
- netbien-network
|
||||||
# mem_limit: 512m
|
mem_limit: 512m
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
mysql_data:
|
mysql_data:
|
||||||
|
|||||||
@ -28,12 +28,13 @@
|
|||||||
|
|
||||||
Route::resource('packages', PackagesController::class);
|
Route::resource('packages', PackagesController::class);
|
||||||
|
|
||||||
|
Route::get('clients/search', [ClientController::class, 'search']);
|
||||||
Route::resource('clients', ClientController::class);
|
Route::resource('clients', ClientController::class);
|
||||||
|
|
||||||
Route::resource('sales', SaleController::class);
|
Route::resource('sales', SaleController::class);
|
||||||
|
|
||||||
Route::get('cash-closes', [CashCloseController::class, 'index']);
|
Route::get('cash-closes', [CashCloseController::class, 'index']);
|
||||||
Route::put('cash-closes/{id}/close', [CashCloseController::class, 'CloseCashClose']);
|
Route::put('cash-closes/close', [CashCloseController::class, 'CloseCashClose']);
|
||||||
Route::get('cash-closes/{id}/report', [CashCloseController::class, 'report']);
|
Route::get('cash-closes/{id}/report', [CashCloseController::class, 'report']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user