Initial commit: Sistema de comisiones y gastos personales

This commit is contained in:
2026-04-19 09:59:57 -06:00
commit dc964d6bce
103 changed files with 15859 additions and 0 deletions

11
resources/css/app.css Executable file
View File

@@ -0,0 +1,11 @@
@import 'tailwindcss';
@source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php';
@source '../../storage/framework/views/*.php';
@source '../**/*.blade.php';
@source '../**/*.js';
@theme {
--font-sans: 'Instrument Sans', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
'Segoe UI Symbol', 'Noto Color Emoji';
}

1
resources/js/app.js Executable file
View File

@@ -0,0 +1 @@
//

View File

@@ -0,0 +1,53 @@
@extends('layouts.guest')
@section('title', 'Iniciar Sesión')
@section('content')
<div class="auth-card p-4">
<h3 class="text-center mb-4">
<i class="bi bi-person-circle"></i> Nómina Pegaso
</h3>
@if ($errors->any())
<div class="alert alert-danger">
<ul class="mb-0">
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
@if(session('success'))
<div class="alert alert-success">
{{ session('success') }}
</div>
@endif
<form method="POST" action="{{ route('login') }}">
@csrf
<div class="mb-3">
<label for="username" class="form-label">Usuario</label>
<input type="text" class="form-control" id="username" name="username"
value="{{ old('username') }}" required autofocus>
</div>
<div class="mb-3">
<label for="password" class="form-label">Contraseña</label>
<input type="password" class="form-control" id="password" name="password" required>
</div>
<div class="mb-3 form-check">
<input type="checkbox" class="form-check-input" id="remember" name="remember">
<label class="form-check-label" for="remember">Recordarme</label>
</div>
<button type="submit" class="btn btn-primary w-100">Iniciar Sesión</button>
</form>
<div class="text-center mt-3">
<a href="{{ route('register') }}">¿No tienes cuenta? Regístrate</a>
</div>
</div>
@endsection

View File

@@ -0,0 +1,84 @@
@extends('layouts.guest')
@section('title', 'Registrarse')
@section('content')
<div class="auth-card p-4">
<h3 class="text-center mb-4">
<i class="bi bi-person-plus"></i> Registrarse
</h3>
@if ($errors->any())
<div class="alert alert-danger">
<ul class="mb-0">
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form method="POST" action="{{ route('register') }}">
@csrf
<div class="mb-3">
<label for="username" class="form-label">Nombre de Usuario</label>
<input type="text" class="form-control" id="username" name="username"
value="{{ old('username') }}" required>
<small class="text-muted">Único - sin espacios ni acentos</small>
</div>
<div class="mb-3">
<label for="name" class="form-label">Nombre Completo</label>
<input type="text" class="form-control" id="name" name="name"
value="{{ old('name') }}" required>
</div>
<div class="mb-3">
<label for="email" class="form-label">Correo Electrónico</label>
<input type="email" class="form-control" id="email" name="email"
value="{{ old('email') }}" required>
</div>
<div class="mb-3">
<label for="password" class="form-label">Contraseña</label>
<input type="password" class="form-control" id="password" name="password" required>
<small class="text-muted">Mínimo 8 caracteres</small>
</div>
<div class="mb-3">
<label for="password_confirmation" class="form-label">Confirmar Contraseña</label>
<input type="password" class="form-control" id="password_confirmation"
name="password_confirmation" required>
</div>
<hr>
<h5 class="mb-3">Configuración de Comisión</h5>
<div class="mb-3">
<label for="commission_percentage" class="form-label">Porcentaje de Comisión (%)</label>
<input type="number" class="form-control" id="commission_percentage"
name="commission_percentage" value="{{ old('commission_percentage', 10) }}"
min="0" max="100" step="0.01" required>
<small class="text-muted">Porcentaje que recibirás sobre tus ventas</small>
</div>
<div class="mb-3">
<label for="monthly_salary" class="form-label">Salario Mensual Base</label>
<div class="input-group">
<span class="input-group-text">$</span>
<input type="number" class="form-control" id="monthly_salary"
name="monthly_salary" value="{{ old('monthly_salary', 0) }}"
min="0" step="0.01" required>
</div>
</div>
<button type="submit" class="btn btn-success w-100">Registrarse</button>
</form>
<div class="text-center mt-3">
<a href="{{ route('login') }}">¿Ya tienes cuenta? Inicia Sesión</a>
</div>
</div>
@endsection

View File

@@ -0,0 +1,584 @@
@extends('layouts.app')
@section('title', 'Calendario')
@section('content')
<div class="row">
<div class="col-12">
<h2 class="mb-4">
<i class="bi bi-calendar3 text-primary"></i> Calendario de Ventas y Gastos
</h2>
</div>
</div>
<!-- Selector de mes -->
<div class="row mb-4">
<div class="col-md-6">
<div class="card">
<div class="card-body">
<form method="GET" class="d-flex gap-2 flex-wrap">
<select name="year" class="form-select" style="width: auto;" onchange="this.form.submit()">
@php($years = range(date('Y'), date('Y') - 5))
@foreach($years as $y)
<option value="{{ $y }}" {{ $year == $y ? 'selected' : '' }}>{{ $y }}</option>
@endforeach
</select>
<select name="month" class="form-select" style="width: auto;" onchange="this.form.submit()">
<option value="">Todos los meses</option>
@foreach(['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'] as $m)
<option value="{{ $m }}" {{ request('month') == $m ? 'selected' : '' }}>{{ $m }}</option>
@endforeach
</select>
</form>
</div>
</div>
</div>
<div class="col-md-6 text-end">
@if($currentMonth)
<span class="badge bg-primary fs-6">
<i class="bi bi-calendar"></i> {{ $currentMonth->name }} {{ $currentMonth->year }}
</span>
<span class="badge bg-{{ $currentMonth->status === 'open' ? 'success' : ($currentMonth->status === 'closed' ? 'warning' : 'info') }}">
{{ ucfirst($currentMonth->status) }}
</span>
@endif
</div>
</div>
@if($currentMonth)
<!-- Resumen del mes -->
<div class="row mb-4">
<div class="col-md-4">
<div class="card stat-card primary">
<div class="card-body">
<h6 class="text-muted">Ventas del Usuario</h6>
<h4 class="text-primary">${{ number_format($currentMonth->dailySales()->sum('user_sales'), 2) }}</h4>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card stat-card success">
<div class="card-body">
<h6 class="text-muted">Ventas del Sistema</h6>
<h4 class="text-success">${{ number_format($currentMonth->dailySales()->sum('system_sales'), 2) }}</h4>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card stat-card warning">
<div class="card-body">
<h6 class="text-muted">Total Gastos</h6>
<h4 class="text-warning">${{ number_format($currentMonth->expenses()->sum('amount'), 2) }}</h4>
</div>
</div>
</div>
</div>
<!-- Calendario FullCalendar -->
<div class="card mb-4">
<div class="card-body">
<div id="calendar"></div>
</div>
</div>
<!-- Leyenda -->
<div class="row mt-3">
<div class="col-12">
<div class="d-flex gap-3 flex-wrap">
<span class="badge bg-light text-dark border p-2">
<i class="bi bi-square text-secondary"></i> Sin datos
</span>
<span class="badge bg-success-subtle text-success border p-2">
<i class="bi bi-square text-success"></i> Con ventas
</span>
<span class="badge bg-danger-subtle text-danger border p-2">
<i class="bi bi-square text-danger"></i> Con gastos
</span>
<span class="badge bg-warning-subtle text-warning border p-2">
<i class="bi bi-square text-warning"></i> Con ambos
</span>
</div>
</div>
</div>
@else
<div class="alert alert-info">
<h5><i class="bi bi-info-circle"></i> No hay un mes seleccionado</h5>
<p>Selecciona un mes del dropdown o crea uno nuevo.</p>
<a href="{{ route('months.index') }}" class="btn btn-primary">Ver Meses</a>
</div>
@endif
<!-- Modal para capturar ventas -->
<div class="modal fade" id="dayModal" tabindex="-1" aria-labelledby="dayModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header bg-primary text-white">
<h5 class="modal-title" id="dayModalLabel">
<i class="bi bi-calendar-plus"></i> Capturar Día
</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form method="POST" id="dayForm">
@csrf
<div class="modal-body">
<input type="hidden" name="month_id" id="formMonthId" value="{{ $currentMonth->id ?? '' }}">
<input type="hidden" name="date" id="modalDate">
<div class="alert alert-info">
<i class="bi bi-info-circle"></i> Fecha: <strong id="modalDateDisplay"></strong>
</div>
<!-- Ventas -->
<h6 class="border-bottom pb-2 mb-3">
<i class="bi bi-currency-dollar text-success"></i> Ventas
</h6>
<div class="mb-3">
<label for="user_sales" class="form-label">Ventas del Usuario</label>
<div class="input-group">
<span class="input-group-text">$</span>
<input type="number" class="form-control" id="user_sales" name="user_sales"
value="0" step="0.01" min="0">
</div>
</div>
<div class="mb-3">
<label for="system_sales" class="form-label">Ventas del Sistema</label>
<div class="input-group">
<span class="input-group-text">$</span>
<input type="number" class="form-control" id="system_sales" name="system_sales"
value="0" step="0.01" min="0">
</div>
</div>
<!-- Gastos -->
<h6 class="border-bottom pb-2 mb-3 mt-4">
<i class="bi bi-receipt text-danger"></i> Gastos
</h6>
<div class="mb-3">
<label for="expense_description" class="form-label">Descripción del Gasto</label>
<input type="text" class="form-control" id="expense_description" name="expense_description"
placeholder="Opcional">
</div>
<div class="mb-3">
<label for="expense_amount" class="form-label">Monto del Gasto</label>
<div class="input-group">
<span class="input-group-text">$</span>
<input type="number" class="form-control" id="expense_amount" name="expense_amount"
value="0" step="0.01" min="0">
</div>
</div>
<div class="mb-3">
<label for="expense_type" class="form-label">Quincena del Gasto</label>
<select class="form-select" id="expense_type" name="expense_type">
<option value="q1">1ra Quincena (1-15)</option>
<option value="q2">2da Quincena (16-31)</option>
<option value="mensual">Gasto Mensual (se divide en 2)</option>
</select>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
<button type="submit" class="btn btn-primary">
<i class="bi bi-save"></i> Guardar
</button>
</div>
</form>
</div>
</div>
</div>
<!-- Modal para ver detalles del día -->
<div class="modal fade" id="dayDetailModal" tabindex="-1" aria-labelledby="dayDetailModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header bg-info text-white">
<h5 class="modal-title" id="dayDetailModalLabel">
<i class="bi bi-eye"></i> Detalles del Día
</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p class="mb-3"><strong>Fecha:</strong> <span id="detailDate"></span></p>
<div class="row mb-3">
<div class="col-6">
<div class="card bg-light">
<div class="card-body text-center">
<h6 class="text-muted">Ventas Usuario</h6>
<h5 class="text-success" id="detailUserSales">$0.00</h5>
</div>
</div>
</div>
<div class="col-6">
<div class="card bg-light">
<div class="card-body text-center">
<h6 class="text-muted">Ventas Sistema</h6>
<h5 class="text-info" id="detailSystemSales">$0.00</h5>
</div>
</div>
</div>
</div>
<div class="card bg-light">
<div class="card-body">
<h6 class="text-muted">Gastos del Día</h6>
<div id="detailExpenses">
<p class="text-muted mb-0">No hay gastos registrados</p>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cerrar</button>
<button type="button" class="btn btn-primary" id="editDayBtn">
<i class="bi bi-pencil"></i> Editar
</button>
</div>
</div>
</div>
</div>
@endsection
@push('scripts')
<script>
document.addEventListener('DOMContentLoaded', function() {
// Data for calendar events
const dailySales = @json($dailySales ?? []);
const expenses = @json($expenses ?? []);
const year = {{ $year }};
const currentMonthId = {{ $currentMonth->id ?? 0 }};
console.log('Month ID:', currentMonthId);
console.log('DailySales raw:', dailySales);
console.log('DailySales type:', typeof dailySales);
console.log('Expenses:', expenses);
// Map data to calendar events
const events = [];
// Add sales events - iterate over object values
Object.keys(dailySales).forEach(date => {
const saleData = dailySales[date];
if (saleData && saleData.user_sales > 0) {
events.push({
title: 'V: $' + parseFloat(saleData.user_sales).toLocaleString(),
start: date,
className: 'bg-success',
extendedProps: {
type: 'sale',
user_sales: saleData.user_sales,
system_sales: saleData.system_sales
}
});
}
});
// Add expense events
Object.keys(expenses).forEach(date => {
const expData = expenses[date];
if (expData && expData.amount > 0) {
events.push({
title: 'G: $' + parseFloat(expData.amount).toLocaleString(),
start: date,
className: 'bg-danger',
extendedProps: {
type: 'expense',
amount: expData.amount,
description: expData.description
}
});
}
});
console.log('Events:', events);
const calendarEl = document.getElementById('calendar');
// FullCalendar initialization
const calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'dayGridMonth',
initialDate: year + '-04-01',
locale: 'es',
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,listMonth'
},
buttonText: {
today: 'Hoy',
month: 'Mes',
list: 'Lista'
},
dayMaxEvents: true,
eventDisplay: 'block',
events: events,
dateClick: function(info) {
// Verify month exists
const monthId = {{ $currentMonth->id ?? 0 }};
if (!monthId || monthId === 0) {
console.log('No hay mes seleccionado');
return;
}
openDayModal(info.dateStr);
},
eventClick: function(info) {
showDayDetails(info.event.startStr);
},
eventDidMount: function(info) {
// Add custom styling based on data
const date = info.event.startStr;
if (dailySales[date] && expenses[date]) {
info.el.style.background = 'linear-gradient(135deg, #f39c12 0%, #e74c3c 100%)';
} else if (dailySales[date]) {
info.el.style.background = 'linear-gradient(135deg, #27ae60 0%, #2ecc71 100%)';
} else if (expenses[date]) {
info.el.style.background = 'linear-gradient(135deg, #e74c3c 0%, #c0392b 100%)';
}
}
});
calendar.render();
// Initialize selected date variable
window.selectedDate = null;
// Functions
window.openDayModal = function(dateStr) {
const modalEl = document.getElementById('dayModal');
if (!modalEl) return;
const modal = new bootstrap.Modal(modalEl);
const modalDateEl = document.getElementById('modalDate');
const modalDateDisplayEl = document.getElementById('modalDateDisplay');
if (modalDateEl && modalDateDisplayEl) {
modalDateEl.value = dateStr;
modalDateDisplayEl.textContent = formatDate(dateStr);
}
// Check if there's existing data
const userSalesEl = document.getElementById('user_sales');
const systemSalesEl = document.getElementById('system_sales');
const expenseDescEl = document.getElementById('expense_description');
const expenseAmountEl = document.getElementById('expense_amount');
if (userSalesEl && systemSalesEl) {
// Buscar coincidencia parcial
let saleData = dailySales[dateStr];
if (!saleData) {
// Buscar en claves
for (const key in dailySales) {
if (key.includes(dateStr) || dateStr.includes(key)) {
saleData = dailySales[key];
break;
}
}
}
if (saleData) {
userSalesEl.value = saleData.user_sales;
systemSalesEl.value = saleData.system_sales;
} else {
userSalesEl.value = 0;
systemSalesEl.value = 0;
}
}
if (expenseDescEl && expenseAmountEl) {
let expData = expenses[dateStr];
if (!expData) {
for (const key in expenses) {
if (key.includes(dateStr) || dateStr.includes(key)) {
expData = expenses[key];
break;
}
}
}
if (expData) {
expenseDescEl.value = expData.description || '';
expenseAmountEl.value = expData.amount;
} else {
expenseDescEl.value = '';
expenseAmountEl.value = 0;
}
}
modal.show();
};
window.showDayDetails = function(dateStr) {
const modal = new bootstrap.Modal(document.getElementById('dayDetailModal'));
document.getElementById('detailDate').textContent = formatDate(dateStr);
// Buscar en todas las claves
let foundKey = null;
for (const key in dailySales) {
if (key.includes(dateStr) || dateStr.includes(key)) {
foundKey = key;
break;
}
}
if (foundKey) {
// Found
document.getElementById('detailUserSales').textContent = '$' + dailySales[foundKey].user_sales.toLocaleString();
document.getElementById('detailSystemSales').textContent = '$' + dailySales[foundKey].system_sales.toLocaleString();
} else {
document.getElementById('detailUserSales').textContent = '$0.00';
document.getElementById('detailSystemSales').textContent = '$0.00';
}
if (expenses[dateStr]) {
document.getElementById('detailExpenses').innerHTML = `
<p class="mb-1"><strong>${expenses[dateStr].description || 'Gasto'}</strong></p>
<h5 class="text-danger mb-0">$${expenses[dateStr].amount.toLocaleString()}</h5>
`;
} else {
document.getElementById('detailExpenses').innerHTML = '<p class="text-muted mb-0">No hay gastos registrados</p>';
}
// Set up edit button
document.getElementById('editDayBtn').onclick = function() {
window.selectedDate = dateStr;
modal.hide();
setTimeout(() => openDayModal(dateStr), 300);
};
modal.show();
};
function formatDate(dateStr) {
if (!dateStr) return 'Sin fecha';
const parts = dateStr.split('-');
if (parts.length === 3) {
const year = parseInt(parts[0]);
const month = parseInt(parts[1]) - 1;
const day = parseInt(parts[2]);
const date = new Date(year, month, day);
return date.toLocaleDateString('es-ES', { year: 'numeric', month: 'long', day: 'numeric' });
}
return dateStr;
}
// Form submission handler
document.getElementById('dayForm').addEventListener('submit', function(e) {
e.preventDefault();
// Get values directly from DOM elements
const monthIdEl = document.getElementById('formMonthId');
const dateEl = document.getElementById('modalDate');
const userSalesEl = document.getElementById('user_sales');
const systemSalesEl = document.getElementById('system_sales');
const expenseAmountEl = document.getElementById('expense_amount');
const expenseDescEl = document.getElementById('expense_description');
const expenseTypeEl = document.getElementById('expense_type');
let monthId = monthIdEl ? monthIdEl.value : '';
let date = dateEl ? dateEl.value : '';
// Use window.selectedDate as fallback
if (!date && window.selectedDate) date = window.selectedDate;
// Try fallback
if (!monthId) monthId = '{{ $currentMonth->id ?? 0 }}';
const userSales = userSalesEl ? (parseFloat(userSalesEl.value) || 0) : 0;
const systemSales = systemSalesEl ? (parseFloat(systemSalesEl.value) || 0) : 0;
const expenseAmount = expenseAmountEl ? (parseFloat(expenseAmountEl.value) || 0) : 0;
const expenseDesc = expenseDescEl ? expenseDescEl.value : '';
const expenseType = expenseTypeEl ? expenseTypeEl.value : 'q1';
// Save data
if (!monthId || !date) {
return;
}
const data = {
month_id: monthId,
date: date,
user_sales: userSales,
system_sales: systemSales,
expense_description: expenseDesc,
expense_amount: expenseAmount,
expense_type: expenseType
};
// Send data via fetch
fetch('{{ route("calendar.day.store") }}', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': '{{ csrf_token() }}'
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(data => {
if (data.success) {
window.location.reload();
} else {
console.error('Error saving:', data.message);
}
})
.catch(error => {
console.error('Error:', error);
});
});
});
</script>
@endpush
@push('styles')
<style>
.fc {
font-size: 0.9rem;
}
.fc .fc-toolbar-title {
font-size: 1.2rem;
}
.fc .fc-daygrid-day-number {
padding: 8px;
}
.fc-event {
padding: 2px 4px;
font-size: 0.75rem;
border-radius: 4px;
margin: 2px 0;
}
.fc .fc-col-header-cell-cushion {
padding: 8px;
font-weight: 600;
}
.fc-daygrid-day.has-data {
background: linear-gradient(135deg, #e8f5e9 0%, #c8e6c9 100%);
}
.fc-daygrid-day.has-expense {
background: linear-gradient(135deg, #ffebee 0%, #ffcdd2 100%);
}
.fc-daygrid-day.has-both {
background: linear-gradient(135deg, #fff3e0 0%, #ffe0b2 100%);
}
.day-cell-clickable {
cursor: pointer;
transition: background 0.2s;
}
.day-cell-clickable:hover {
background: #e3f2fd !important;
}
</style>
@endpush

View File

@@ -0,0 +1,170 @@
@extends('layouts.app')
@section('title', 'Dashboard')
@section('content')
<div class="row">
<div class="col-12">
<h2 class="mb-4">Bienvenido, {{ auth()->user()->name }}</h2>
</div>
</div>
@if($currentMonth)
<div class="row mb-4">
<div class="col-md-12">
<div class="card">
<div class="card-header bg-primary text-white">
<h5 class="mb-0">
<i class="bi bi-calendar3"></i>
Resumen de {{ $currentMonth->name }} {{ $currentMonth->year }}
@if($currentMonth->status === 'open')
<span class="badge bg-success ms-2">Abierto</span>
@elseif($currentMonth->status === 'closed')
<span class="badge bg-warning ms-2">Cerrado</span>
@else
<span class="badge bg-info ms-2">Pagado</span>
@endif
</h5>
</div>
<div class="card-body">
@if($data)
<div class="row">
<div class="col-md-3">
<div class="card stat-card primary mb-3">
<div class="card-body">
<h6 class="text-muted">Ventas del Usuario</h6>
<h4>${{ number_format($data['total_user_sales'], 2) }}</h4>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card stat-card success mb-3">
<div class="card-body">
<h6 class="text-muted">Ventas del Sistema</h6>
<h4>${{ number_format($data['total_system_sales'], 2) }}</h4>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card stat-card warning mb-3">
<div class="card-body">
<h6 class="text-muted">Comisión ({{ $data['commission_percentage'] }}%)</h6>
<h4>${{ number_format($data['commission_amount'], 2) }}</h4>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card stat-card danger mb-3">
<div class="card-body">
<h6 class="text-muted">Total a Recibir</h6>
<h4>${{ number_format($data['total_earning'], 2) }}</h4>
</div>
</div>
</div>
</div>
<div class="row mt-3">
<div class="col-md-6">
<ul class="list-group">
<li class="list-group-item d-flex justify-content-between align-items-center">
Salario Mensual
<span class="badge bg-primary rounded-pill">${{ number_format($data['monthly_salary'], 2) }}</span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center">
Gastos del Mes
<span class="badge bg-danger rounded-pill">${{ number_format($data['total_expenses'], 2) }}</span>
</li>
@if($data['has_difference'])
<li class="list-group-item d-flex justify-content-between align-items-center">
Diferencia Ventas
<span class="badge bg-warning rounded-pill">${{ number_format($data['sales_difference'], 2) }}</span>
</li>
@endif
</ul>
</div>
<div class="col-md-6 text-end">
<a href="{{ route('reports.monthly', ['month_id' => $currentMonth->id]) }}" class="btn btn-primary">
<i class="bi bi-file-earmark-text"></i> Ver Reporte Mensual
</a>
<a href="{{ route('reports.biweekly', ['month_id' => $currentMonth->id, 'biweekly' => 1]) }}" class="btn btn-outline-primary">
<i class="bi bi-file-earmark-text"></i> Ver Quincena
</a>
</div>
</div>
@else
<div class="alert alert-info">
No hay datos suficientes para calcular el resumen. Agrega ventas y gastos.
</div>
@endif
</div>
</div>
</div>
</div>
@else
<div class="alert alert-warning">
<h5>No hay un mes de trabajo activo</h5>
<p>Para comenzar, crea un nuevo mes de trabajo.</p>
<a href="{{ route('months.create') }}" class="btn btn-primary">Crear Mes</a>
</div>
@endif
<!-- Últimos meses -->
<div class="row mt-4">
<div class="col-12">
<h4 class="mb-3">Meses Recientes</h4>
</div>
@forelse($recentMonths as $month)
<div class="col-md-4 col-lg-2 mb-3">
<div class="card h-100">
<div class="card-body text-center">
<h6>{{ $month->name }}</h6>
<small class="text-muted">{{ $month->year }}</small>
<div class="mt-2">
@if($month->status === 'open')
<span class="badge bg-success">Abierto</span>
@elseif($month->status === 'closed')
<span class="badge bg-warning">Cerrado</span>
@else
<span class="badge bg-info">Pagado</span>
@endif
</div>
</div>
<div class="card-footer bg-transparent">
<a href="{{ route('months.show', $month->id) }}" class="btn btn-sm btn-outline-primary w-100">Ver</a>
</div>
</div>
</div>
@empty
<div class="col-12">
<div class="alert alert-info">No hay meses registrados.</div>
</div>
@endforelse
</div>
<!-- Acceso rápido -->
<div class="row mt-4">
<div class="col-12">
<h4 class="mb-3">Acceso Rápido</h4>
</div>
<div class="col-md-3">
<a href="{{ route('sales.create') }}" class="btn btn-success w-100 mb-2">
<i class="bi bi-plus-circle"></i> Nueva Venta
</a>
</div>
<div class="col-md-3">
<a href="{{ route('expenses.create') }}" class="btn btn-warning w-100 mb-2">
<i class="bi bi-plus-circle"></i> Nuevo Gasto
</a>
</div>
<div class="col-md-3">
<a href="{{ route('calendar') }}" class="btn btn-info w-100 mb-2">
<i class="bi bi-calendar3"></i> Ver Calendario
</a>
</div>
<div class="col-md-3">
<a href="{{ route('reports.monthly') }}" class="btn btn-secondary w-100 mb-2">
<i class="bi bi-graph-up"></i> Ver Reportes
</a>
</div>
</div>
@endsection

View File

@@ -0,0 +1,63 @@
@extends('layouts.app')
@section('title', 'Nuevo Gasto')
@section('content')
<div class="row">
<div class="col-12">
<h2 class="mb-4">Nuevo Gasto</h2>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-body">
<form method="POST" action="{{ route('expenses.store') }}">
@csrf
<input type="hidden" name="month_id" value="{{ $month->id }}">
<div class="mb-3">
<label for="description" class="form-label">Descripción</label>
<input type="text" class="form-control" id="description" name="description"
value="{{ old('description') }}" required>
</div>
<div class="mb-3">
<label for="amount" class="form-label">Monto</label>
<div class="input-group">
<span class="input-group-text">$</span>
<input type="number" class="form-control" id="amount" name="amount"
value="{{ old('amount') }}" step="0.01" min="0.01" required>
</div>
</div>
<div class="mb-3">
<label for="date" class="form-label">Fecha</label>
<input type="date" class="form-control" id="date" name="date"
value="{{ old('date', now()->format('Y-m-d')) }}" required>
</div>
<div class="mb-3">
<label for="expense_type" class="form-label">Quincena</label>
<select class="form-select" id="expense_type" name="expense_type" required>
<option value="q1">1ra Quincena (1-15)</option>
<option value="q2">2da Quincena (16-31)</option>
<option value="mensual">Gasto Mensual (se divide en 2)</option>
</select>
<small class="text-muted">
Selecciona a qué quincena se restará el gasto.
Los gastos mensuales se dividen entre 2.
</small>
</div>
<div class="d-flex gap-2">
<button type="submit" class="btn btn-warning">Guardar Gasto</button>
<a href="{{ route('expenses.index', ['month_id' => $month->id]) }}" class="btn btn-secondary">Cancelar</a>
</div>
</form>
</div>
</div>
</div>
</div>
@endsection

View File

@@ -0,0 +1,59 @@
@extends('layouts.app')
@section('title', 'Editar Gasto')
@section('content')
<div class="row">
<div class="col-12">
<h2 class="mb-4">Editar Gasto</h2>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-body">
<form method="POST" action="{{ route('expenses.update', $expense->id) }}">
@csrf
@method('PUT')
<div class="mb-3">
<label for="description" class="form-label">Descripción</label>
<input type="text" class="form-control" id="description" name="description"
value="{{ old('description', $expense->description) }}" required>
</div>
<div class="mb-3">
<label for="amount" class="form-label">Monto</label>
<div class="input-group">
<span class="input-group-text">$</span>
<input type="number" class="form-control" id="amount" name="amount"
value="{{ old('amount', $expense->amount) }}" step="0.01" min="0.01" required>
</div>
</div>
<div class="mb-3">
<label for="date" class="form-label">Fecha</label>
<input type="date" class="form-control" id="date" name="date"
value="{{ old('date', $expense->date->format('Y-m-d')) }}" required>
</div>
<div class="mb-3">
<label for="expense_type" class="form-label">Quincena</label>
<select class="form-select" id="expense_type" name="expense_type" required>
<option value="q1" {{ $expense->expense_type == 'q1' ? 'selected' : '' }}>1ra Quincena (1-15)</option>
<option value="q2" {{ $expense->expense_type == 'q2' ? 'selected' : '' }}>2da Quincena (16-31)</option>
<option value="mensual" {{ $expense->expense_type == 'mensual' ? 'selected' : '' }}>Gasto Mensual (se divide en 2)</option>
</select>
</div>
<div class="d-flex gap-2">
<button type="submit" class="btn btn-primary">Actualizar</button>
<a href="{{ route('expenses.index', ['month_id' => $expense->month_id]) }}" class="btn btn-secondary">Cancelar</a>
</div>
</form>
</div>
</div>
</div>
</div>
@endsection

View File

@@ -0,0 +1,99 @@
@extends('layouts.app')
@section('title', 'Gastos')
@section('content')
<div class="row">
<div class="col-12">
<h2 class="mb-4">Gestión de Gastos</h2>
</div>
</div>
<!-- Selector de mes -->
<div class="row mb-4">
<div class="col-md-6">
<form method="GET" class="d-flex gap-2">
<select name="month_id" class="form-select" onchange="this.form.submit()">
<option value="">Todos los meses</option>
@foreach($months as $m)
<option value="{{ $m->id }}" {{ $month && $month->id == $m->id ? 'selected' : '' }}>
{{ $m->name }} {{ $m->year }}
</option>
@endforeach
</select>
<a href="{{ route('expenses.create', ['month_id' => $month?->id]) }}" class="btn btn-warning">
<i class="bi bi-plus-circle"></i> Nuevo Gasto
</a>
</form>
</div>
</div>
@if($month)
<!-- Resumen -->
<div class="row mb-4">
<div class="col-md-12">
<div class="card">
<div class="card-body">
<h6 class="text-muted">Total Gastos del Mes</h6>
<h3>${{ number_format($month->expenses()->sum('amount'), 2) }}</h3>
</div>
</div>
</div>
</div>
@endif
<!-- Lista de gastos -->
<div class="card">
<div class="card-body">
<table class="table table-hover">
<thead>
<tr>
<th>Fecha</th>
<th>Descripción</th>
<th>Monto</th>
<th>Quincena</th>
<th>Mes</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
@forelse($expenses as $expense)
<tr>
<td>{{ $expense->date->format('d/m/Y') }}</td>
<td>{{ $expense->description }}</td>
<td class="text-danger">-${{ number_format($expense->amount, 2) }}</td>
<td>
@if($expense->expense_type == 'q1')
<span class="badge bg-primary">Q1</span>
@elseif($expense->expense_type == 'q2')
<span class="badge bg-warning">Q2</span>
@else
<span class="badge bg-info">Mensual</span>
@endif
</td>
<td>{{ $expense->month->name }} {{ $expense->month->year }}</td>
<td>
<a href="{{ route('expenses.edit', $expense->id) }}" class="btn btn-sm btn-outline-primary">
<i class="bi bi-pencil"></i>
</a>
<form method="POST" action="{{ route('expenses.destroy', $expense->id) }}" class="d-inline">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-outline-danger" onclick="return confirm('¿Eliminar este gasto?')">
<i class="bi bi-trash"></i>
</button>
</form>
</td>
</tr>
@empty
<tr>
<td colspan="6" class="text-center text-muted">No hay gastos registrados.</td>
</tr>
@endforelse
</tbody>
</table>
{{ $expenses->links() }}
</div>
</div>
@endsection

View File

@@ -0,0 +1,310 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@yield('title', 'Nómina Pegaso')</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css">
<link href='https://cdn.jsdelivr.net/npm/fullcalendar@6.1.10/main.min.css' rel='stylesheet' />
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: #f8f9fa;
}
/* Sidebar Styles */
.sidebar {
min-height: 100vh;
background: linear-gradient(180deg, #2c3e50 0%, #1a252f 100%);
box-shadow: 2px 0 10px rgba(0,0,0,0.1);
}
.sidebar-brand {
padding: 1rem;
border-bottom: 1px solid rgba(255,255,255,0.1);
}
.sidebar a {
color: rgba(255,255,255,0.8);
text-decoration: none;
padding: 12px 20px;
display: block;
border-radius: 8px;
margin: 4px 12px;
transition: all 0.3s ease;
}
.sidebar a:hover {
background: rgba(255,255,255,0.1);
color: #fff;
transform: translateX(5px);
}
.sidebar a.active {
background: #3498db;
color: #fff;
}
.sidebar a i {
width: 24px;
}
/* Card Styles */
.card {
border: none;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
transition: transform 0.2s ease;
}
.card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.12);
}
.stat-card {
border-left: 4px solid;
border-radius: 8px;
}
.stat-card.primary { border-color: #3498db; }
.stat-card.success { border-color: #27ae60; }
.stat-card.warning { border-color: #f39c12; }
.stat-card.danger { border-color: #e74c3c; }
/* Calendar Styles */
.fc .fc-daygrid-day:hover {
background: #f8f9fa;
cursor: pointer;
}
.fc-event {
cursor: pointer;
border: none;
}
.day-with-sales {
background: linear-gradient(135deg, #d4edda 0%, #c3e6cb 100%) !important;
}
.day-with-expenses {
background: linear-gradient(135deg, #f8d7da 0%, #f5c6cb 100%) !important;
}
.day-empty {
background: #f8f9fa;
color: #6c757d;
}
/* Mobile Styles */
@media (max-width: 768px) {
.sidebar {
position: fixed;
top: 0;
left: -100%;
width: 280px;
z-index: 1050;
transition: left 0.3s ease;
}
.sidebar.show {
left: 0;
}
.sidebar-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.5);
z-index: 1040;
display: none;
}
.sidebar-overlay.show {
display: block;
}
.mobile-nav-btn {
display: block !important;
}
}
.mobile-nav-btn {
display: none;
position: fixed;
bottom: 20px;
left: 20px;
z-index: 1030;
width: 56px;
height: 56px;
border-radius: 50%;
box-shadow: 0 4px 12px rgba(0,0,0,0.2);
}
/* Button Styles */
.btn {
border-radius: 8px;
font-weight: 500;
transition: all 0.2s ease;
}
.btn:hover {
transform: translateY(-1px);
}
/* Form Styles */
.form-control, .form-select {
border-radius: 8px;
border: 1px solid #e0e0e0;
padding: 10px 15px;
}
.form-control:focus, .form-select:focus {
border-color: #3498db;
box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.1);
}
/* Badge Styles */
.badge {
padding: 6px 12px;
border-radius: 20px;
font-weight: 500;
}
/* Toast Styles */
.toast-container {
position: fixed;
top: 20px;
right: 20px;
z-index: 9999;
}
/* Table Styles */
.table th {
font-weight: 600;
color: #495057;
border-bottom: 2px solid #e9ecef;
}
.table-hover tbody tr:hover {
background: #f8f9fa;
}
</style>
@stack('styles')
</head>
<body>
@auth
<!-- Sidebar Overlay (Mobile) -->
<div class="sidebar-overlay" id="sidebarOverlay"></div>
<!-- Mobile Navigation Button -->
<button class="btn btn-primary mobile-nav-btn" id="mobileNavBtn">
<i class="bi bi-list"></i>
</button>
<div class="container-fluid">
<div class="row">
<!-- Sidebar -->
<nav class="col-md-2 d-none d-md-block sidebar py-3" id="sidebar">
<div class="sidebar-brand text-center mb-4">
<h5 class="text-white mb-1">
<i class="bi bi-cash-coin"></i> Nómina Pegaso
</h5>
<small class="text-white-50">{{ auth()->user()->name }}</small>
</div>
<nav>
<a href="{{ route('dashboard') }}" class="{{ request()->routeIs('dashboard') ? 'active' : '' }}">
<i class="bi bi-house-door"></i> Dashboard
</a>
<a href="{{ route('calendar') }}" class="{{ request()->routeIs('calendar*') ? 'active' : '' }}">
<i class="bi bi-calendar3"></i> Calendario
</a>
<a href="{{ route('sales.index') }}" class="{{ request()->routeIs('sales.*') ? 'active' : '' }}">
<i class="bi bi-currency-dollar"></i> Ventas
</a>
<a href="{{ route('expenses.index') }}" class="{{ request()->routeIs('expenses.*') ? 'active' : '' }}">
<i class="bi bi-receipt"></i> Gastos
</a>
<a href="{{ route('months.index') }}" class="{{ request()->routeIs('months.*') ? 'active' : '' }}">
<i class="bi bi-calendar-month"></i> Meses
</a>
<hr class="border-secondary mx-3">
<a href="{{ route('reports.monthly') }}" class="{{ request()->routeIs('reports.*') ? 'active' : '' }}">
<i class="bi bi-graph-up"></i> Reportes
</a>
<a href="{{ route('settings.index') }}" class="{{ request()->routeIs('settings.*') ? 'active' : '' }}">
<i class="bi bi-gear"></i> Configuración
</a>
<a href="{{ route('telegram.verify') }}" class="{{ request()->routeIs('telegram.*') ? 'active' : '' }}">
<i class="bi bi-telegram"></i> Telegram
</a>
<hr class="border-secondary mx-3">
<form method="POST" action="{{ route('logout') }}" class="px-3">
@csrf
<button type="submit" class="btn btn-link text-white w-100 text-start p-2">
<i class="bi bi-box-arrow-right"></i> Cerrar Sesión
</button>
</form>
</nav>
</nav>
<!-- Main content -->
<main class="col-md-10 ms-sm-auto px-4 py-4">
<!-- Mobile Header -->
<div class="d-md-none mb-4">
<div class="card">
<div class="card-body d-flex justify-content-between align-items-center">
<span class="fw-bold">Nómina Pegaso</span>
<button class="btn btn-outline-primary btn-sm" id="mobileNavBtn2">
<i class="bi bi-list"></i>
</button>
</div>
</div>
</div>
@yield('content')
</main>
</div>
</div>
@else
@yield('content')
@endauth
<!-- Toast Container -->
<div class="toast-container">
@if(session('success'))
<div class="toast show" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header bg-success text-white">
<strong class="me-auto"><i class="bi bi-check-circle"></i> Éxito</strong>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="toast"></button>
</div>
<div class="toast-body">
{{ session('success') }}
</div>
</div>
@endif
@if(session('error'))
<div class="toast show" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header bg-danger text-white">
<strong class="me-auto"><i class="bi bi-exclamation-circle"></i> Error</strong>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="toast"></button>
</div>
<div class="toast-body">
{{ session('error') }}
</div>
</div>
@endif
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/fullcalendar@6.1.10/index.global.min.js"></script>
<script src="{{ asset('js/app.js') }}"></script>
@stack('scripts')
</body>
</html>

View File

@@ -0,0 +1,35 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@yield('title', 'Nómina Pegaso')</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css">
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
}
.auth-card {
background: white;
border-radius: 10px;
box-shadow: 0 10px 40px rgba(0,0,0,0.2);
}
</style>
@stack('styles')
</head>
<body>
<div class="container">
<div class="row justify-content-center align-items-center min-vh-100">
<div class="col-md-6 col-lg-5">
@yield('content')
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
@stack('scripts')
</body>
</html>

View File

@@ -0,0 +1,53 @@
@extends('layouts.app')
@section('title', 'Crear Mes')
@section('content')
<div class="row">
<div class="col-12">
<h2 class="mb-4">Crear Nuevo Mes</h2>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-body">
<form method="POST" action="{{ route('months.store') }}">
@csrf
<div class="mb-3">
<label for="name" class="form-label">Nombre del Mes</label>
<select class="form-select" id="name" name="name" required>
<option value="">Selecciona un mes</option>
<option value="Enero">Enero</option>
<option value="Febrero">Febrero</option>
<option value="Marzo">Marzo</option>
<option value="Abril">Abril</option>
<option value="Mayo">Mayo</option>
<option value="Junio">Junio</option>
<option value="Julio">Julio</option>
<option value="Agosto">Agosto</option>
<option value="Septiembre">Septiembre</option>
<option value="Octubre">Octubre</option>
<option value="Noviembre">Noviembre</option>
<option value="Diciembre">Diciembre</option>
</select>
</div>
<div class="mb-3">
<label for="year" class="form-label">Año</label>
<input type="number" class="form-control" id="year" name="year"
value="{{ old('year', now()->year) }}" min="2020" max="2100" required>
</div>
<div class="d-flex gap-2">
<button type="submit" class="btn btn-success">Crear Mes</button>
<a href="{{ route('months.index') }}" class="btn btn-secondary">Cancelar</a>
</div>
</form>
</div>
</div>
</div>
</div>
@endsection

View File

@@ -0,0 +1,53 @@
@extends('layouts.app')
@section('title', 'Editar Mes')
@section('content')
<div class="row">
<div class="col-12">
<h2 class="mb-4">Editar Mes</h2>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-body">
<form method="POST" action="{{ route('months.update', $month->id) }}">
@csrf
@method('PUT')
<div class="mb-3">
<label for="name" class="form-label">Nombre del Mes</label>
<select class="form-select" id="name" name="name" required>
@foreach(['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'] as $m)
<option value="{{ $m }}" {{ $month->name == $m ? 'selected' : '' }}>{{ $m }}</option>
@endforeach
</select>
</div>
<div class="mb-3">
<label for="year" class="form-label">Año</label>
<input type="number" class="form-control" id="year" name="year"
value="{{ old('year', $month->year) }}" min="2020" max="2100" required>
</div>
<div class="mb-3">
<label for="status" class="form-label">Estado</label>
<select class="form-select" id="status" name="status" required>
<option value="open" {{ $month->status == 'open' ? 'selected' : '' }}>Abierto</option>
<option value="closed" {{ $month->status == 'closed' ? 'selected' : '' }}>Cerrado</option>
<option value="paid" {{ $month->status == 'paid' ? 'selected' : '' }}>Pagado</option>
</select>
</div>
<div class="d-flex gap-2">
<button type="submit" class="btn btn-primary">Actualizar</button>
<a href="{{ route('months.show', $month->id) }}" class="btn btn-secondary">Cancelar</a>
</div>
</form>
</div>
</div>
</div>
</div>
@endsection

View File

@@ -0,0 +1,58 @@
@extends('layouts.app')
@section('title', 'Meses')
@section('content')
<div class="row">
<div class="col-12">
<h2 class="mb-4">Meses de Trabajo</h2>
</div>
</div>
<div class="row mb-4">
<div class="col-md-6">
<a href="{{ route('months.create') }}" class="btn btn-primary">
<i class="bi bi-plus-circle"></i> Crear Nuevo Mes
</a>
</div>
</div>
<!-- Lista de meses -->
<div class="row">
@forelse($months as $month)
<div class="col-md-4 col-lg-3 mb-4">
<div class="card h-100">
<div class="card-header">
<h5 class="mb-0">{{ $month->name }} {{ $month->year }}</h5>
</div>
<div class="card-body">
<p class="mb-1">
<strong>Estado:</strong>
@if($month->status === 'open')
<span class="badge bg-success">Abierto</span>
@elseif($month->status === 'closed')
<span class="badge bg-warning">Cerrado</span>
@else
<span class="badge bg-info">Pagado</span>
@endif
</p>
<p class="mb-1"><small class="text-muted">Ventas: ${{ number_format($month->dailySales()->sum('user_sales'), 2) }}</small></p>
<p class="mb-0"><small class="text-muted">Gastos: ${{ number_format($month->expenses()->sum('amount'), 2) }}</small></p>
</div>
<div class="card-footer bg-transparent">
<a href="{{ route('months.show', $month->id) }}" class="btn btn-sm btn-primary">Ver Detalles</a>
</div>
</div>
</div>
@empty
<div class="col-12">
<div class="alert alert-info">
No hay meses registrados.
<a href="{{ route('months.create') }}">Crea tu primer mes</a>
</div>
</div>
@endforelse
</div>
{{ $months->links() }}
@endsection

View File

@@ -0,0 +1,142 @@
@extends('layouts.app')
@section('title', 'Detalles del Mes')
@section('content')
<div class="row">
<div class="col-12">
<h2 class="mb-4">
{{ $month->name }} {{ $month->year }}
@if($month->status === 'open')
<span class="badge bg-success">Abierto</span>
@elseif($month->status === 'closed')
<span class="badge bg-warning">Cerrado</span>
@else
<span class="badge bg-info">Pagado</span>
@endif
</h2>
</div>
</div>
<!-- Resumen -->
<div class="row mb-4">
<div class="col-md-3">
<div class="card stat-card primary">
<div class="card-body">
<h6>Ventas Usuario</h6>
<h4>${{ number_format($month->dailySales()->sum('user_sales'), 2) }}</h4>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card stat-card success">
<div class="card-body">
<h6>Ventas Sistema</h6>
<h4>${{ number_format($month->dailySales()->sum('system_sales'), 2) }}</h4>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card stat-card warning">
<div class="card-body">
<h6>Total Gastos</h6>
<h4>${{ number_format($month->expenses()->sum('amount'), 2) }}</h4>
</div>
</div>
</div>
<div class="col-md-3">
<div class="card stat-card danger">
<div class="card-body">
<h6>Días Registrados</h6>
<h4>{{ $month->dailySales()->count() }}</h4>
</div>
</div>
</div>
</div>
<!-- Acciones -->
<div class="row mb-4">
<div class="col-md-12">
<a href="{{ route('sales.create', ['month_id' => $month->id]) }}" class="btn btn-success">
<i class="bi bi-plus-circle"></i> Agregar Venta
</a>
<a href="{{ route('expenses.create', ['month_id' => $month->id]) }}" class="btn btn-warning">
<i class="bi bi-plus-circle"></i> Agregar Gasto
</a>
<a href="{{ route('reports.monthly', ['month_id' => $month->id]) }}" class="btn btn-info">
<i class="bi bi-graph-up"></i> Ver Reporte
</a>
@if($month->status === 'open')
<form method="POST" action="{{ route('months.close', $month->id) }}" class="d-inline">
@csrf
<button type="submit" class="btn btn-outline-danger" onclick="return confirm('¿Cerrar este mes?')">
<i class="bi bi-lock"></i> Cerrar Mes
</button>
</form>
@endif
</div>
</div>
<!-- Últimas ventas -->
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">Últimas Ventas</h5>
</div>
<div class="card-body">
<table class="table table-sm">
<thead>
<tr>
<th>Fecha</th>
<th>Venta Usuario</th>
<th>Venta Sistema</th>
</tr>
</thead>
<tbody>
@forelse($month->dailySales()->latest()->limit(10)->get() as $sale)
<tr>
<td>{{ $sale->date->format('d/m/Y') }}</td>
<td>${{ number_format($sale->user_sales, 2) }}</td>
<td>${{ number_format($sale->system_sales, 2) }}</td>
</tr>
@empty
<tr><td colspan="3" class="text-center">No hay ventas</td></tr>
@endforelse
</tbody>
</table>
</div>
</div>
<!-- Últimos gastos -->
<div class="card">
<div class="card-header">
<h5 class="mb-0">Últimos Gastos</h5>
</div>
<div class="card-body">
<table class="table table-sm">
<thead>
<tr>
<th>Fecha</th>
<th>Descripción</th>
<th>Monto</th>
</tr>
</thead>
<tbody>
@forelse($month->expenses()->latest()->limit(10)->get() as $expense)
<tr>
<td>{{ $expense->date->format('d/m/Y') }}</td>
<td>{{ $expense->description }}</td>
<td class="text-danger">${{ number_format($expense->amount, 2) }}</td>
</tr>
@empty
<tr><td colspan="3" class="text-center">No hay gastos</td></tr>
@endforelse
</tbody>
</table>
</div>
</div>
<div class="mt-3">
<a href="{{ route('months.index') }}" class="btn btn-secondary">Volver a Meses</a>
</div>
@endsection

View File

@@ -0,0 +1,131 @@
@extends('layouts.app')
@section('title', 'Reporte Quincenal')
@section('content')
<div class="row">
<div class="col-12">
<h2 class="mb-4">Reporte Quincenal</h2>
</div>
</div>
<!-- Selector -->
<div class="row mb-4">
<div class="col-md-4">
<form method="GET" class="d-flex gap-2">
<select name="month_id" class="form-select" onchange="this.form.submit()">
@foreach($months as $m)
<option value="{{ $m->id }}" {{ $month->id == $m->id ? 'selected' : '' }}>
{{ $m->name }} {{ $m->year }}
</option>
@endforeach
</select>
</form>
</div>
<div class="col-md-4">
<form method="GET" class="d-flex gap-2">
<input type="hidden" name="month_id" value="{{ $month->id }}">
<select name="biweekly" class="form-select" onchange="this.form.submit()">
<option value="1" {{ $biweekly == 1 ? 'selected' : '' }}>1ra Quincena (1-15) - ANTICIPO</option>
<option value="2" {{ $biweekly == 2 ? 'selected' : '' }}>2da Quincena (16-31) - LIQUIDACIÓN</option>
</select>
</form>
</div>
<div class="col-md-4 text-end">
<a href="{{ route('reports.monthly', ['month_id' => $month->id]) }}" class="btn btn-outline-primary">Ver Mensual</a>
</div>
</div>
@if($report)
<!-- Resumen Quincenal -->
<div class="row mb-4">
<div class="col-12">
<div class="card {{ $report['type'] === 'anticipo' ? 'border-success' : 'border-warning' }}">
<div class="card-header {{ $report['type'] === 'anticipo' ? 'bg-success' : 'bg-warning' }} text-white">
<h5 class="mb-0">{{ $report['period'] }}</h5>
<small>{{ $report['description'] }}</small>
</div>
<div class="card-body">
<div class="row text-center">
@if($report['type'] === 'anticipo')
<div class="col-md-4">
<h6 class="text-muted">Mitad Sueldo</h6>
<h3>${{ number_format($report['biweekly_salary'], 2) }}</h3>
</div>
<div class="col-md-4">
<h6 class="text-muted">Comisiones del Mes</h6>
<h3 class="text-success">+${{ number_format($report['commission_amount'], 2) }}</h3>
</div>
<div class="col-md-4">
<h6 class="text-muted">Total ANTICIPO</h6>
<h2 class="text-success">${{ number_format($report['total_earning'], 2) }}</h2>
</div>
@else
<div class="col-md-4">
<h6 class="text-muted">Mitad Sueldo</h6>
<h3>${{ number_format($report['biweekly_salary'], 2) }}</h3>
</div>
<div class="col-md-4">
<h6 class="text-muted">Gastos Q{{ $biweekly }}</h6>
<h3 class="text-danger">-${{ number_format($report['expenses_q2'], 2) }}</h3>
</div>
<div class="col-md-4">
<h6 class="text-muted">Total LIQUIDACIÓN</h6>
<h2 class="{{ $report['total_earning'] >= 0 ? 'text-success' : 'text-danger' }}">${{ number_format($report['total_earning'], 2) }}</h2>
</div>
@endif
</div>
</div>
</div>
</div>
</div>
<!-- Desglose de gastos -->
@if(count($expenses) > 0)
<div class="card mb-4">
<div class="card-header">
<h5>Gastos de la Quincena</h5>
</div>
<div class="card-body">
<table class="table">
<thead>
<tr>
<th>Fecha</th>
<th>Descripción</th>
<th>Tipo</th>
<th class="text-end">Monto</th>
</tr>
</thead>
<tbody>
@foreach($expenses as $expense)
<tr>
<td>{{ $expense->date->format('d/m/Y') }}</td>
<td>{{ $expense->description }}</td>
<td>
@if($expense->expense_type == 'q1')
<span class="badge bg-primary">Q1</span>
@elseif($expense->expense_type == 'q2')
<span class="badge bg-warning">Q2</span>
@else
<span class="badge bg-info">Mensual (mitad)</span>
@endif
</td>
<td class="text-end text-danger">${{ number_format($expense->expense_type == 'mensual' ? $expense->amount / 2 : $expense->amount, 2) }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
@endif
@else
<div class="alert alert-warning">No hay datos para mostrar.</div>
@endif
<div class="row mt-4">
<div class="col-12">
<a href="{{ route('dashboard') }}" class="btn btn-secondary"> Volver al Dashboard</a>
</div>
</div>
@endsection

View File

@@ -0,0 +1,199 @@
@extends('layouts.app')
@section('title', 'Reporte Mensual')
@section('content')
<div class="row">
<div class="col-12">
<h2 class="mb-4">Reporte Mensual</h2>
</div>
</div>
<!-- Selector -->
<div class="row mb-4">
<div class="col-md-6">
<form method="GET" class="d-flex gap-2">
<select name="month_id" class="form-select" onchange="this.form.submit()">
@foreach($months as $m)
<option value="{{ $m->id }}" {{ $month->id == $m->id ? 'selected' : '' }}>
{{ $m->name }} {{ $m->year }}
</option>
@endforeach
</select>
<a href="{{ route('reports.biweekly', ['month_id' => $month->id, 'biweekly' => 1]) }}" class="btn btn-outline-primary">Quincenal</a>
</form>
</div>
</div>
@if($report)
<!-- Resumen General -->
<div class="row mb-4">
<div class="col-12">
<div class="card">
<div class="card-header bg-primary text-white">
<h5 class="mb-0">{{ $report['month_name'] }}</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-3">
<h6 class="text-muted">Ventas del Usuario</h6>
<h4>${{ number_format($report['total_user_sales'], 2) }}</h4>
</div>
<div class="col-md-3">
<h6 class="text-muted">Ventas del Sistema</h6>
<h4>${{ number_format($report['total_system_sales'], 2) }}</h4>
</div>
<div class="col-md-3">
<h6 class="text-muted">Comisión ({{ $report['commission_percentage'] }}%)</h6>
<h4 class="text-success">${{ number_format($report['commission_amount'], 2) }}</h4>
</div>
<div class="col-md-3">
<h6 class="text-muted">Total a Recibir</h6>
<h4 class="text-primary">${{ number_format($report['total_earning'], 2) }}</h4>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Detalles -->
<div class="row">
<div class="col-md-6">
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">Desglose</h5>
</div>
<div class="card-body">
<table class="table">
<tr>
<td>Salario Mensual</td>
<td class="text-end">${{ number_format($report['monthly_salary'], 2) }}</td>
</tr>
<tr>
<td>Comisión ({{ $report['commission_percentage'] }}%)</td>
<td class="text-end text-success">+${{ number_format($report['commission_amount'], 2) }}</td>
</tr>
<tr>
<td>Gastos del Mes</td>
<td class="text-end text-danger">-${{ number_format($report['total_expenses'], 2) }}</td>
</tr>
<tr class="table-light">
<td><strong>Total a Recibir</strong></td>
<td class="text-end"><strong>${{ number_format($report['total_earning'], 2) }}</strong></td>
</tr>
</table>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">Diferencia de Ventas</h5>
</div>
<div class="card-body">
@if($report['has_difference'])
<div class="alert alert-{{ $report['sales_difference'] > 0 ? 'warning' : 'danger' }}">
<strong>Diferencia:</strong> ${{ number_format($report['sales_difference'], 2) }}
<br>
<small>
{{ $report['sales_difference'] > 0 ? 'Ventas del usuario mayores que sistema' : 'Ventas del sistema mayores que usuario' }}
</small>
</div>
@else
<div class="alert alert-success">
<i class="bi bi-check-circle"></i> Ventas conciliadas (sin diferencia)
</div>
@endif
</div>
</div>
</div>
</div>
<!-- Ventas Diarias -->
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">Ventas Diarias</h5>
</div>
<div class="card-body">
<table class="table table-sm table-striped">
<thead>
<tr>
<th>Fecha</th>
<th class="text-end">Venta Usuario</th>
<th class="text-end">Venta Sistema</th>
<th class="text-end">Diferencia</th>
</tr>
</thead>
<tbody>
@forelse($dailySales as $sale)
<tr>
<td>{{ $sale->date->format('d/m/Y') }}</td>
<td class="text-end">${{ number_format($sale->user_sales, 2) }}</td>
<td class="text-end">${{ number_format($sale->system_sales, 2) }}</td>
<td class="text-end">
@php $diff = $sale->user_sales - $sale->system_sales; @endphp
@if($diff != 0)
<span class="text-{{ $diff > 0 ? 'warning' : 'danger' }}">
${{ number_format($diff, 2) }}
</span>
@else
<span class="text-success">-</span>
@endif
</td>
</tr>
@empty
<tr><td colspan="4" class="text-center">No hay ventas</td></tr>
@endforelse
</tbody>
<tfoot>
<tr class="table-light">
<th>Total</th>
<th class="text-end">${{ number_format($dailySales->sum('user_sales'), 2) }}</th>
<th class="text-end">${{ number_format($dailySales->sum('system_sales'), 2) }}</th>
<th class="text-end">${{ number_format($dailySales->sum('user_sales') - $dailySales->sum('system_sales'), 2) }}</th>
</tr>
</tfoot>
</table>
</div>
</div>
<!-- Gastos -->
<div class="card">
<div class="card-header">
<h5 class="mb-0">Gastos del Mes</h5>
</div>
<div class="card-body">
<table class="table table-sm table-striped">
<thead>
<tr>
<th>Fecha</th>
<th>Descripción</th>
<th class="text-end">Monto</th>
</tr>
</thead>
<tbody>
@forelse($expenses as $expense)
<tr>
<td>{{ $expense->date->format('d/m/Y') }}</td>
<td>{{ $expense->description }}</td>
<td class="text-end text-danger">${{ number_format($expense->amount, 2) }}</td>
</tr>
@empty
<tr><td colspan="3" class="text-center">No hay gastos</td></tr>
@endforelse
</tbody>
<tfoot>
<tr class="table-light">
<th colspan="2">Total Gastos</th>
<th class="text-end">${{ number_format($expenses->sum('amount'), 2) }}</th>
</tr>
</tfoot>
</table>
</div>
</div>
@else
<div class="alert alert-warning">No hay datos disponibles para este mes.</div>
@endif
@endsection

View File

@@ -0,0 +1,109 @@
@extends('layouts.app')
@section('title', 'Reporte Anual')
@section('content')
<div class="row">
<div class="col-12">
<h2 class="mb-4">Reporte Anual</h2>
</div>
</div>
<!-- Selector de año -->
<div class="row mb-4">
<div class="col-md-4">
<form method="GET" class="d-flex gap-2">
<select name="year" class="form-select" onchange="this.form.submit()">
@foreach($years as $y)
<option value="{{ $y }}" {{ $year == $y ? 'selected' : '' }}>{{ $y }}</option>
@endforeach
</select>
</form>
</div>
</div>
@if($report)
<!-- Resumen Anual -->
<div class="row mb-4">
<div class="col-12">
<div class="card">
<div class="card-header bg-dark text-white">
<h5 class="mb-0">Resumen del Año {{ $year }}</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-2">
<h6 class="text-muted">Meses</h6>
<h4>{{ $report['months_count'] }}</h4>
</div>
<div class="col-md-2">
<h6 class="text-muted">Ventas Usuario</h6>
<h4>${{ number_format($report['total_user_sales'], 0) }}</h4>
</div>
<div class="col-md-2">
<h6 class="text-muted">Ventas Sistema</h6>
<h4>${{ number_format($report['total_system_sales'], 0) }}</h4>
</div>
<div class="col-md-2">
<h6 class="text-muted">Total Salario</h6>
<h4>${{ number_format($report['total_salary'], 2) }}</h4>
</div>
<div class="col-md-2">
<h6 class="text-muted">Total Comisión</h6>
<h4 class="text-success">${{ number_format($report['total_commission'], 2) }}</h4>
</div>
<div class="col-md-2">
<h6 class="text-muted">Total Año</h6>
<h4 class="text-primary">${{ number_format($report['total_earning'], 2) }}</h4>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Meses del año -->
<div class="card">
<div class="card-header">
<h5 class="mb-0">Detalle por Mes</h5>
</div>
<div class="card-body">
<table class="table table-sm table-striped">
<thead>
<tr>
<th>Mes</th>
<th class="text-end">Ventas Usuario</th>
<th class="text-end">Ventas Sistema</th>
<th class="text-end">Gastos</th>
<th class="text-end">Comisión</th>
<th class="text-end">Total</th>
</tr>
</thead>
<tbody>
@forelse($months as $month)
@php
$userSales = $month->dailySales()->sum('user_sales');
$systemSales = $month->dailySales()->sum('system_sales');
$expenses = $month->expenses()->sum('amount');
$commission = ($systemSales * auth()->user()->commission_percentage) / 100;
$total = auth()->user()->monthly_salary + $commission - $expenses;
@endphp
<tr>
<td>{{ $month->name }}</td>
<td class="text-end">${{ number_format($userSales, 2) }}</td>
<td class="text-end">${{ number_format($systemSales, 2) }}</td>
<td class="text-end text-danger">${{ number_format($expenses, 2) }}</td>
<td class="text-end text-success">${{ number_format($commission, 2) }}</td>
<td class="text-end"><strong>${{ number_format($total, 2) }}</strong></td>
</tr>
@empty
<tr><td colspan="6" class="text-center">No hay meses en este año</td></tr>
@endforelse
</tbody>
</table>
</div>
</div>
@else
<div class="alert alert-warning">No hay datos disponibles para este año.</div>
@endif
@endsection

View File

@@ -0,0 +1,54 @@
@extends('layouts.app')
@section('title', 'Nueva Venta')
@section('content')
<div class="row">
<div class="col-12">
<h2 class="mb-4">Nueva Venta</h2>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-body">
<form method="POST" action="{{ route('sales.store') }}">
@csrf
<input type="hidden" name="month_id" value="{{ $month->id }}">
<div class="mb-3">
<label for="date" class="form-label">Fecha</label>
<input type="date" class="form-control" id="date" name="date"
value="{{ old('date', now()->format('Y-m-d')) }}" required>
</div>
<div class="mb-3">
<label for="user_sales" class="form-label">Ventas del Usuario</label>
<div class="input-group">
<span class="input-group-text">$</span>
<input type="number" class="form-control" id="user_sales" name="user_sales"
value="{{ old('user_sales') }}" step="0.01" min="0" required>
</div>
</div>
<div class="mb-3">
<label for="system_sales" class="form-label">Ventas del Sistema (Opcional)</label>
<div class="input-group">
<span class="input-group-text">$</span>
<input type="number" class="form-control" id="system_sales" name="system_sales"
value="{{ old('system_sales', 0) }}" step="0.01" min="0">
</div>
<small class="text-muted">Ventas consolidadas del sistema</small>
</div>
<div class="d-flex gap-2">
<button type="submit" class="btn btn-success">Guardar Venta</button>
<a href="{{ route('sales.index', ['month_id' => $month->id]) }}" class="btn btn-secondary">Cancelar</a>
</div>
</form>
</div>
</div>
</div>
</div>
@endsection

View File

@@ -0,0 +1,53 @@
@extends('layouts.app')
@section('title', 'Editar Venta')
@section('content')
<div class="row">
<div class="col-12">
<h2 class="mb-4">Editar Venta</h2>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-body">
<form method="POST" action="{{ route('sales.update', $sale->id) }}">
@csrf
@method('PUT')
<div class="mb-3">
<label for="date" class="form-label">Fecha</label>
<input type="date" class="form-control" id="date" name="date"
value="{{ old('date', $sale->date->format('Y-m-d')) }}" required>
</div>
<div class="mb-3">
<label for="user_sales" class="form-label">Ventas del Usuario</label>
<div class="input-group">
<span class="input-group-text">$</span>
<input type="number" class="form-control" id="user_sales" name="user_sales"
value="{{ old('user_sales', $sale->user_sales) }}" step="0.01" min="0" required>
</div>
</div>
<div class="mb-3">
<label for="system_sales" class="form-label">Ventas del Sistema</label>
<div class="input-group">
<span class="input-group-text">$</span>
<input type="number" class="form-control" id="system_sales" name="system_sales"
value="{{ old('system_sales', $sale->system_sales) }}" step="0.01" min="0">
</div>
</div>
<div class="d-flex gap-2">
<button type="submit" class="btn btn-primary">Actualizar</button>
<a href="{{ route('sales.index', ['month_id' => $sale->month_id]) }}" class="btn btn-secondary">Cancelar</a>
</div>
</form>
</div>
</div>
</div>
</div>
@endsection

View File

@@ -0,0 +1,109 @@
@extends('layouts.app')
@section('title', 'Ventas')
@section('content')
<div class="row">
<div class="col-12">
<h2 class="mb-4">Gestión de Ventas</h2>
</div>
</div>
<!-- Selector de mes -->
<div class="row mb-4">
<div class="col-md-6">
<form method="GET" class="d-flex gap-2">
<select name="month_id" class="form-select" onchange="this.form.submit()">
@foreach($months as $m)
<option value="{{ $m->id }}" {{ $month->id == $m->id ? 'selected' : '' }}>
{{ $m->name }} {{ $m->year }} ({{ $m->status }})
</option>
@endforeach
</select>
<a href="{{ route('sales.create', ['month_id' => $month->id]) }}" class="btn btn-success">
<i class="bi bi-plus-circle"></i> Nueva Venta
</a>
</form>
</div>
<div class="col-md-6 text-end">
<div class="btn-group">
<a href="{{ route('sales.index', ['month_id' => $month->id]) }}" class="btn btn-outline-secondary">Todas</a>
<a href="{{ route('expenses.index', ['month_id' => $month->id]) }}" class="btn btn-outline-warning">Ver Gastos</a>
</div>
</div>
</div>
<!-- Resumen -->
<div class="row mb-4">
<div class="col-md-6">
<div class="card">
<div class="card-body">
<h6 class="text-muted">Total Ventas Usuario</h6>
<h3>${{ number_format($month->dailySales()->sum('user_sales'), 2) }}</h3>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-body">
<h6 class="text-muted">Total Ventas Sistema</h6>
<h3>${{ number_format($month->dailySales()->sum('system_sales'), 2) }}</h3>
</div>
</div>
</div>
</div>
<!-- Lista de ventas -->
<div class="card">
<div class="card-body">
<table class="table table-hover">
<thead>
<tr>
<th>Fecha</th>
<th>Venta Usuario</th>
<th>Venta Sistema</th>
<th>Diferencia</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
@forelse($sales as $sale)
<tr>
<td>{{ $sale->date->format('d/m/Y') }}</td>
<td>${{ number_format($sale->user_sales, 2) }}</td>
<td>${{ number_format($sale->system_sales, 2) }}</td>
<td>
@php $diff = $sale->user_sales - $sale->system_sales; @endphp
@if($diff != 0)
<span class="badge bg-{{ $diff > 0 ? 'warning' : 'danger' }}">
${{ number_format($diff, 2) }}
</span>
@else
<span class="badge bg-success">conciliada</span>
@endif
</td>
<td>
<a href="{{ route('sales.edit', $sale->id) }}" class="btn btn-sm btn-outline-primary">
<i class="bi bi-pencil"></i>
</a>
<form method="POST" action="{{ route('sales.destroy', $sale->id) }}" class="d-inline">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-sm btn-outline-danger" onclick="return confirm('¿Eliminar esta venta?')">
<i class="bi bi-trash"></i>
</button>
</form>
</td>
</tr>
@empty
<tr>
<td colspan="5" class="text-center text-muted">No hay ventas registradas.</td>
</tr>
@endforelse
</tbody>
</table>
{{ $sales->links() }}
</div>
</div>
@endsection

View File

@@ -0,0 +1,257 @@
@extends('layouts.app')
@section('title', 'Configuración')
@section('content')
<div class="row">
<div class="col-12">
<h2 class="mb-4">
<i class="bi bi-gear text-primary"></i> Configuración
</h2>
</div>
</div>
<div class="row">
<div class="col-md-8">
<!-- Datos Laborales -->
<div class="card mb-4">
<div class="card-header bg-success text-white">
<h5 class="mb-0">
<i class="bi bi-briefcase"></i> Datos Laborales
</h5>
</div>
<div class="card-body">
<form method="POST" action="{{ route('settings.update') }}">
@csrf
@method('PUT')
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label for="fecha_ingreso" class="form-label">Fecha de Ingreso</label>
<input type="date" class="form-control" id="fecha_ingreso"
name="fecha_ingreso"
value="{{ old('fecha_ingreso', auth()->user()->fecha_ingreso?->format('Y-m-d')) }}">
<small class="text-muted">Fecha en que started a trabajar en la empresa</small>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label for="razon_social" class="form-label">Razón Social</label>
<input type="text" class="form-control" id="razon_social"
name="razon_social"
value="{{ old('razon_social', auth()->user()->razon_social) }}"
placeholder="Empresa donde trabajas">
<small class="text-muted">Nombre de la empresa o negocio</small>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label for="sueldo_integro_diario" class="form-label">Sueldo Íntegro Diario</label>
<div class="input-group">
<span class="input-group-text">$</span>
<input type="number" class="form-control" id="sueldo_integro_diario"
name="sueldo_integro_diario"
value="{{ old('sueldo_integro_diario', auth()->user()->sueldo_integro_diario) }}"
min="0" step="0.01">
</div>
<small class="text-muted">Salario diario integrado (para calcular vacaciones)</small>
</div>
</div>
</div>
@php($user = auth()->user())
@if($user->fecha_ingreso)
<div class="alert alert-info">
<i class="bi bi-calendar-check"></i>
<strong>Antigüedad:</strong> {{ $user->fecha_ingreso->diffInYears(now()) }} año(s) y {{ $user->fecha_ingreso->diffInMonths(now()) % 12 }} mes(es)
</div>
@endif
<button type="submit" class="btn btn-success">
<i class="bi bi-save"></i> Guardar Datos Laborales
</button>
</form>
</div>
</div>
<!-- Configuración de Comisión -->
<div class="card mb-4">
<div class="card-header bg-primary text-white">
<h5 class="mb-0">
<i class="bi bi-percent"></i> Configuración de Comisión
</h5>
</div>
<div class="card-body">
<form method="POST" action="{{ route('settings.update') }}">
@csrf
@method('PUT')
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label for="commission_percentage" class="form-label">Porcentaje de Comisión (%)</label>
<div class="input-group">
<input type="number" class="form-control" id="commission_percentage"
name="commission_percentage"
value="{{ old('commission_percentage', auth()->user()->commission_percentage) }}"
min="0" max="100" step="0.01" required>
<span class="input-group-text">%</span>
</div>
<small class="text-muted">Porcentaje que recibirás sobre tus ventas</small>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label for="monthly_salary" class="form-label">Salario Mensual Base</label>
<div class="input-group">
<span class="input-group-text">$</span>
<input type="number" class="form-control" id="monthly_salary"
name="monthly_salary"
value="{{ old('monthly_salary', auth()->user()->monthly_salary) }}"
min="0" step="0.01" required>
</div>
<small class="text-muted">Salario base mensual sin comisiones</small>
</div>
</div>
</div>
<div class="alert alert-info">
<i class="bi bi-info-circle"></i>
<strong>Nota:</strong> Estos valores se aplicarán a partir del próximo mes.
Los meses actuales mantendrán su configuración original.
</div>
<button type="submit" class="btn btn-primary">
<i class="bi bi-save"></i> Guardar Cambios
</button>
</form>
</div>
</div>
<!-- Cambiar Contraseña -->
<div class="card mb-4">
<div class="card-header bg-secondary text-white">
<h5 class="mb-0">
<i class="bi bi-key"></i> Cambiar Contraseña
</h5>
</div>
<div class="card-body">
<form method="POST" action="{{ route('settings.update') }}">
@csrf
@method('PUT')
<div class="mb-3">
<label for="current_password" class="form-label">Contraseña Actual</label>
<input type="password" class="form-control" id="current_password"
name="current_password">
</div>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label for="password" class="form-label">Nueva Contraseña</label>
<input type="password" class="form-control" id="password"
name="password">
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label for="password_confirmation" class="form-label">Confirmar Contraseña</label>
<input type="password" class="form-control" id="password_confirmation"
name="password_confirmation">
</div>
</div>
</div>
<small class="text-muted">Deja los campos de contraseña en blanco si no deseas cambiarlo.</small>
<div class="mt-3">
<button type="submit" class="btn btn-secondary">
<i class="bi bi-key-fill"></i> Actualizar Contraseña
</button>
</div>
</form>
</div>
</div>
</div>
<div class="col-md-4">
<!-- Información del Usuario -->
<div class="card mb-4">
<div class="card-header bg-dark text-white">
<h5 class="mb-0">
<i class="bi bi-person"></i> Información del Usuario
</h5>
</div>
<div class="card-body">
<dl class="row">
<dt class="col-sm-4">Nombre:</dt>
<dd class="col-sm-8">{{ auth()->user()->name }}</dd>
<dt class="col-sm-4">Email:</dt>
<dd class="col-sm-8">{{ auth()->user()->email }}</dd>
@if(auth()->user()->razon_social)
<dt class="col-sm-4">Empresa:</dt>
<dd class="col-sm-8">{{ auth()->user()->razon_social }}</dd>
@endif
@if(auth()->user()->fecha_ingreso)
<dt class="col-sm-4">Ingreso:</dt>
<dd class="col-sm-8">{{ auth()->user()->fecha_ingreso->format('d/m/Y') }}</dd>
@endif
<dt class="col-sm-4">Comisión:</dt>
<dd class="col-sm-8">
<span class="badge bg-primary">{{ auth()->user()->commission_percentage }}%</span>
</dd>
<dt class="col-sm-4">Salario:</dt>
<dd class="col-sm-8">${{ number_format(auth()->user()->monthly_salary, 2) }}</dd>
<dt class="col-sm-4">Estado:</dt>
<dd class="col-sm-8">
@if(auth()->user()->is_active)
<span class="badge bg-success">Activo</span>
@else
<span class="badge bg-danger">Inactivo</span>
@endif
</dd>
</dl>
</div>
</div>
<!-- Ayuda -->
<div class="card">
<div class="card-header bg-light">
<h5 class="mb-0">
<i class="bi bi-question-circle"></i> Ayuda
</h5>
</div>
<div class="card-body">
<h6>¿Cómo funciona la comisión?</h6>
<p class="text-muted small">
Tu salario se calcula sumando el salary base más el {{ auth()->user()->commission_percentage }}%
de tus ventas del mes.
</p>
<h6 class="mt-3">¿Qué son las ventas del sistema?</h6>
<p class="text-muted small">
Las ventas del sistema son las ventas consolidadas automáticamente.
Si difieren de tus ventas, aparecerán en el reporte.
</p>
<h6 class="mt-3">¿Puedo cambiar estos valores?</h6>
<p class="text-muted small">
, pero los cambios se aplicarán al siguiente mes.
Los meses actuales mantendrán su configuración.
</p>
</div>
</div>
</div>
</div>
@endsection

View File

@@ -0,0 +1,78 @@
@extends('layouts.app')
@section('title', 'Vincular Telegram')
@section('content')
<div class="row">
<div class="col-12">
<h2 class="mb-4">Vincular Cuenta de Telegram</h2>
</div>
</div>
<div class="row">
<div class="col-md-8">
<div class="card">
<div class="card-body">
@if($telegramAccount->is_verified)
<div class="alert alert-success">
<h5><i class="bi bi-check-circle"></i> Cuenta Verificada</h5>
<p>Tu cuenta de Telegram está vinculada correctamente.</p>
</div>
<div class="mb-4">
<strong>Chat ID:</strong> {{ $telegramAccount->chat_id }}
</div>
<form method="POST" action="{{ route('telegram.unlink') }}">
@csrf
<button type="submit" class="btn btn-danger" onclick="return confirm('¿Desvincular cuenta de Telegram?')">
<i class="bi bi-unlink"></i> Desvincular Cuenta
</button>
</form>
@else
<div class="alert alert-info">
<h5><i class="bi bi-info-circle"></i> Vinculación de Telegram</h5>
<p>Sigue estos pasos para vincular tu cuenta de Telegram:</p>
<ol>
<li>Abre Telegram y busca el bot de Nómina Pegaso</li>
<li>Envía el código de verificación que aparece abajo</li>
<li>Recibirás una confirmación cuando esté vinculado</li>
</ol>
</div>
<div class="card bg-light mb-4">
<div class="card-body text-center">
<h6 class="text-muted">Tu Código de Verificación</h6>
<h1 class="display-4 text-primary">{{ $telegramAccount->verification_code }}</h1>
<small class="text-muted">Este código expira cuando se genera uno nuevo</small>
</div>
</div>
<form method="POST" action="{{ route('telegram.regenerate') }}">
@csrf
<button type="submit" class="btn btn-outline-primary">
<i class="bi bi-arrow-clockwise"></i> Regenerar Código
</button>
</form>
@endif
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-header">
<h5 class="mb-0">Información</h5>
</div>
<div class="card-body">
<p class="small">Al vincular tu cuenta de Telegram podrás:</p>
<ul class="small">
<li>Recibir notificaciones de tus ventas</li>
<li>Consultar tu estado de comisiones</li>
<li>Recibir recordatorios de registro</li>
</ul>
</div>
</div>
</div>
</div>
@endsection

225
resources/views/welcome.blade.php Executable file

File diff suppressed because one or more lines are too long