7 Commits

Author SHA1 Message Date
2e9a52a890 Merge pull request 'Added invoice pending reason page' (#195) from ranjith-dev into master
All checks were successful
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Successful in 11s
Reviewed-on: #195
2026-01-20 04:53:20 +00:00
dhanabalan
76afd15b3b Added invoice pending reason page
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Successful in 13s
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Successful in 10s
Gemini PR Review / Gemini PR Review (pull_request) Failing after 17s
Laravel Pint / pint (pull_request) Successful in 2m40s
Laravel Larastan / larastan (pull_request) Failing after 3m50s
2026-01-20 10:23:06 +05:30
3c34495048 Merge pull request 'changed report time for invoice transit and invoice data' (#194) from ranjith-dev into master
All checks were successful
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Successful in 12s
Reviewed-on: #194
2026-01-19 10:33:34 +00:00
dhanabalan
3788f4cd18 changed report time for invoice transit and invoice data
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Successful in 11s
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Successful in 55s
Gemini PR Review / Gemini PR Review (pull_request) Failing after 1m1s
Laravel Pint / pint (pull_request) Successful in 2m31s
Laravel Larastan / larastan (pull_request) Failing after 3m48s
2026-01-19 16:03:13 +05:30
b70907cb9f Merge pull request 'ranjith-dev' (#193) from ranjith-dev into master
All checks were successful
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Successful in 16s
Reviewed-on: #193
2026-01-19 10:03:28 +00:00
dhanabalan
7dd9f43940 Enhance StickerMasterResource: Update item selection logic, add 1. validation rules, 2. default values, 3. searchPlaceholder, and improve UI labels
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Successful in 11s
Gemini PR Review / Gemini PR Review (pull_request) Failing after 4m13s
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Successful in 4m21s
Laravel Pint / pint (pull_request) Successful in 3m24s
Laravel Larastan / larastan (pull_request) Failing after 3m58s
2026-01-19 15:29:27 +05:30
dhanabalan
b089ddd75c Add default values, searchPlaceholder and update labels in filters
All checks were successful
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Successful in 1m5s
2026-01-19 15:25:54 +05:30
6 changed files with 233 additions and 22 deletions

View File

@@ -39,6 +39,8 @@ class Scheduler extends Command
public function handle()
{
// $this->call('approval:trigger-mails');
// --- Production Rules ---
$productionRules = AlertMailRule::where('module', 'ProductionQuantities')
->where('rule_name', 'ProductionMail')
@@ -174,7 +176,7 @@ class Scheduler extends Command
}
break;
case 'Daily':
if (now()->format('H:i') == '10:00') {
if (now()->format('H:i') == '10:30') {
\Artisan::call('send:invoice-data-report', [
'schedule_type' => $rule->schedule_type,
'plant' => $rule->plant,
@@ -209,7 +211,7 @@ class Scheduler extends Command
}
break;
case 'Daily':
if (now()->format('H:i') == '10:00') {
if (now()->format('H:i') == '10:45') {
\Artisan::call('send:invoice-transit-report', [
'schedule_type' => $rule->schedule_type,
'plant' => $rule->plant,

View File

@@ -0,0 +1,179 @@
<?php
namespace App\Filament\Pages;
use App\Models\InvoiceDataValidation;
use App\Models\InvoiceOutValidation;
use App\Models\Plant;
use Filament\Pages\Page;
use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Form;
use Filament\Facades\Filament;
use Filament\Forms\Components\Hidden;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Notifications\Notification;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
use Illuminate\Support\Facades\Auth;
class InvoicePendingReason extends Page
{
use HasFiltersForm;
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static string $view = 'filament.pages.invoice-pending-reason';
protected static ?string $navigationGroup = 'Manufacturing SD';
public function mount(): void
{
$this->filtersForm->fill([
'plant_id' => null,
'document_number' => null,
'remark' => null,
]);
}
public function filtersForm(Form $form): Form
{
return $form
->statePath('filters')
->schema([
Select::make('plant_id')
->label('Plant')
->reactive()
->required()
->columnSpan(1)
->options(function (callable $get) {
$userHas = Filament::auth()->user()->plant_id;
return ($userHas && strlen($userHas) > 0) ? Plant::where('id', $userHas)->pluck('name', 'id')->toArray() : Plant::pluck('name', 'id')->toArray();
})
->afterStateUpdated(function ($state, $set, callable $get,$livewire) {
$plantId = $get('plant_id');
$set('document_number', null);
})
->hint(fn ($get) => $get('pqPlantError') ? $get('pqPlantError') : null)
->hintColor('danger'),
Select::make('document_number')
->label('Document Number')
->required()
->reactive()
->columnSpan(1)
->options(function (callable $get) {
$plantId = $get('plant_id');
if (empty($plantId)) {
return [];
}
$distributions = InvoiceDataValidation::whereNotNull('distribution_channel_desc')
->distinct()
->pluck('distribution_channel_desc')
->filter(fn ($v) => trim($v) !== '')
->values()
->toArray();
$distributions[] = '';
$pendingInvoices = collect();
foreach ($distributions as $distribution) {
$invoices = InvoiceDataValidation::where('plant_id', $plantId)
->where('distribution_channel_desc', $distribution)
->select('id', 'document_number')
->get()
->unique('document_number')
->filter(fn ($inv) =>
! empty($inv->document_number) &&
! str_contains($inv->document_number, '-')
);
if (trim($distribution) == '') {
$invoices = $invoices->filter(fn ($inv) =>
str_starts_with($inv->document_number, '7')
);
}
if ($invoices->isEmpty()) {
continue;
}
$invoiceNumbers = $invoices->pluck('document_number')
->map(fn ($n) => preg_replace('/\s+/', '', strtoupper($n)))
->toArray();
$wentOut = InvoiceOutValidation::whereIn('qr_code', $invoiceNumbers)
->distinct()
->pluck('qr_code')
->map(fn ($n) => preg_replace('/\s+/', '', strtoupper($n)))
->toArray();
$pending = $invoices->filter(function ($inv) use ($wentOut) {
$doc = preg_replace('/\s+/', '', strtoupper($inv->document_number));
return ! in_array($doc, $wentOut, true);
});
$pendingInvoices = $pendingInvoices->merge($pending);
}
return $pendingInvoices
->unique('document_number')
->pluck('document_number', 'document_number')
->toArray();
})
->afterStateUpdated(function ($state, callable $set, callable $get) {
})
->extraAttributes(fn ($get) => [
'class' => $get('pqBlockError') ? 'border-red-500' : '',
])
->hint(fn ($get) => $get('pqBlockError') ? $get('pqBlockError') : null)
->hintColor('danger'),
TextInput::make('remark')
->label('Remark')
->reactive()
->extraAttributes([
'wire:keydown.enter.prevent' => 'addRemark($event.target.value)',
])
->autofocus()
->required(),
])
->columns(3);
}
public function addRemark($value){
$plantId = $this->filters['plant_id'] ?? null;
$documentNumber = $this->filters['document_number'] ?? null;
$remark = $value;
if (! $plantId || ! $documentNumber || $remark == '') {
return;
}
InvoiceDataValidation::where('plant_id', $plantId)
->where('document_number', $documentNumber)
->update([
'remark' => $remark,
'updated_at' => now(),
]);
$this->filtersForm->fill([
'plant_id' => $plantId,
'document_number' => $documentNumber,
'remark' => null,
]);
Notification::make()
->title('Remark updated successfully')
->success()
->send();
}
public static function canAccess(): bool
{
return Auth::check() && Auth::user()->can('view invoice pending reason');
}
}

View File

@@ -197,6 +197,7 @@ class ItemResource extends Resource
->searchable(),
Tables\Columns\TextColumn::make('category')
->label('Category')
->default('-')
->alignCenter()
->sortable()
->searchable(),
@@ -217,6 +218,7 @@ class ItemResource extends Resource
->sortable(),
Tables\Columns\TextColumn::make('uom')
->label('Unit of Measure')
->default('-')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('created_at')
@@ -237,6 +239,7 @@ class ItemResource extends Resource
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
->searchPlaceholder('Search Item Code')
->filters([
Tables\Filters\TrashedFilter::make(),
Filter::make('advanced_filters')
@@ -256,7 +259,7 @@ class ItemResource extends Resource
$set('operator_id', null);
}),
Select::make('code')
->label('Search by Item Code')
->label('Search by Code')
->nullable()
// ->options(function (callable $get) {
// $plantId = $get('Plant');

View File

@@ -30,6 +30,7 @@ use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\Rule;
// use Illuminate\Validation\Rule;
@@ -93,21 +94,33 @@ class StickerMasterResource extends Resource
Forms\Components\Select::make('item_id')
->label('Item Code')
->options(function (callable $get) {
$plantId = $get('plant_id');
if (! $get('plant_id')) {
return [];
}
return \App\Models\Item::where('plant_id', $get('plant_id'))
->pluck('code', 'id')
->toArray();
if (! $get('id')) {
// whereHas
return Item::where('plant_id', $plantId)->whereDoesntHave('stickerMasters')->pluck('code', 'id');
} else {
$itemId = StickerMaster::where('id', $get('id'))->first()?->item_id;
return Item::where('plant_id', $plantId)
->where(function ($query) use ($itemId) {
$query->whereDoesntHave('stickerMasters')
->orWhere('id', $itemId);
})
->pluck('code', 'id');
}
// return Item::where('plant_id', $plantId)->pluck('code', 'id')->toArray();
})
->rule(function (callable $get) {
return Rule::unique('sticker_masters', 'item_id')
->where('plant_id', $get('plant_id'))
->ignore($get('id')); // Ignore current record during updates
})
// ->rule(function (callable $get) {
// return Rule::unique('items', 'code')
// ->where('plant_id', $get('plant_id'))
// ->ignore($get('id')); // Ignore current record during updates
// })
->required()
->nullable()
// ->nullable()
->searchable()
->reactive()
// ->disabled(fn (Get $get) => !empty($get('id')))
@@ -132,7 +145,7 @@ class StickerMasterResource extends Resource
return;
}
$availableItems = \App\Models\Item::where('plant_id', $plantId)->exists();
$availableItems = Item::where('plant_id', $plantId)->exists();
if (! $availableItems) {
$set('item_error', null);
@@ -147,7 +160,7 @@ class StickerMasterResource extends Resource
}
// Check if item exists for the selected plant
$item = \App\Models\Item::where('plant_id', $plantId)
$item = Item::where('plant_id', $plantId)
->where('id', $itemId)
->first();
@@ -161,7 +174,8 @@ class StickerMasterResource extends Resource
->where('item_id', $itemId)
->exists();
if (! $get('id')) {
$set('item_error', $duplicateSticker ? 'Item Code already exists for the selected plant.' : null);
// $set('item_error', $duplicateSticker ? 'Item Code already exists for the selected plant.' : null);
$set('item_error', null);
}
})
->extraAttributes(fn ($get) => [
@@ -177,7 +191,7 @@ class StickerMasterResource extends Resource
if ($get('id')) {
$itemId = StickerMaster::where('id', $get('id'))->first()?->item_id;
if ($itemId) {
$item = \App\Models\Item::where('id', $itemId)->first()?->description;
$item = Item::where('id', $itemId)->first()?->description;
if ($item) {
$set('item_description', $item);
} else {
@@ -525,27 +539,35 @@ class StickerMasterResource extends Resource
->sortable(),
Tables\Columns\TextColumn::make('part_validation1')
->label('Part Validation 1')
->default('-')
->alignCenter(),
Tables\Columns\TextColumn::make('part_validation2')
->label('Part Validation 2')
->default('-')
->alignCenter(),
Tables\Columns\TextColumn::make('part_validation3')
->label('Part Validation 3')
->default('-')
->alignCenter(),
Tables\Columns\TextColumn::make('part_validation4')
->label('Part Validation 4')
->default('-')
->alignCenter(),
Tables\Columns\TextColumn::make('part_validation5')
->label('Part Validation 5')
->default('-')
->alignCenter(),
Tables\Columns\TextColumn::make('laser_part_validation1')
->label('Laser Part Validation 1')
->default('-')
->alignCenter(),
Tables\Columns\TextColumn::make('laser_part_validation2')
->label('Laser Part Validation 2')
->default('-')
->alignCenter(),
Tables\Columns\TextColumn::make('panel_box_code')
->label('Panel Box Code')
->default('-')
->alignCenter(),
Tables\Columns\TextColumn::make('load_rate')
->label('Load Rate')
@@ -553,6 +575,7 @@ class StickerMasterResource extends Resource
->sortable(),
Tables\Columns\TextColumn::make('bundle_quantity')
->label('Bundle Quantity')
->default('-')
->alignCenter(),
Tables\Columns\TextColumn::make('material_type')
->label('Material Type')
@@ -587,9 +610,7 @@ class StickerMasterResource extends Resource
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
// ->filters([
// Tables\Filters\TrashedFilter::make(),
// ])
->searchPlaceholder('Search Item Code')
->filters([
Tables\Filters\TrashedFilter::make(),
Filter::make('advanced_filters')
@@ -635,7 +656,7 @@ class StickerMasterResource extends Resource
->searchable()
->reactive(),
Select::make('material_type')
->label('Material Type')
->label('Select Material Type')
->options([
1 => 'Individual',
2 => 'Bundle',
@@ -644,7 +665,7 @@ class StickerMasterResource extends Resource
->reactive(),
TextInput::make('panel_box_code')
->label('Panel Box Code')
->label('Search by Panel Box Code')
->placeholder(placeholder: 'Enter Panel Box Code'),
DateTimePicker::make(name: 'created_from')
->label('Created From')

View File

@@ -17,7 +17,7 @@
"laravel/sanctum": "^4.0",
"laravel/tinker": "^2.9",
"league/flysystem-sftp-v3": "^3.30",
"livewire/livewire": "^4.0",
"livewire/livewire": "^3.6",
"maatwebsite/excel": "^3.1",
"mike42/escpos-php": "^4.0",
"mpdf/mpdf": "^8.2",

View File

@@ -0,0 +1,6 @@
<x-filament-panels::page>
<div class="space-y-4">
{{-- {{ $this->filtersForm($this->form) }} --}}
{{ $this->filtersForm($this->form) }}
</div>
</x-filament-panels::page>