Initial commit for new repo
All checks were successful
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Successful in 1m4s

This commit is contained in:
dhanabalan
2025-12-16 17:05:04 +05:30
commit 3f0d529640
862 changed files with 141157 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
<?php
namespace App\Filament\Pages;
use App\Filament\Widgets\CumulativeChart;
use App\Filament\Widgets\ProductionQuantityStat;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Form;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
use Filament\Tables\Filters\SelectFilter;
use Illuminate\Support\Facades\DB;
use App\Models\Plant;
use Filament\Facades\Filament;
use Filament\Widgets\Widget;
use Illuminate\Support\Facades\Auth;
class Dashboard extends \Filament\Pages\Dashboard
{
use HasFiltersForm;
protected static ?string $navigationGroup = 'Production DashBoard';
public function mount(): void
{
session()->forget(['selected_plant']);
$this->filtersForm->fill([
'plant' => null,
'success_status' => null
]);
}
public function filtersForm(Form $form): Form
{
return $form
->statePath('filters') // Store form state in 'filters'
->schema([
Select::make('plant')
->label('Select Plant')
->reactive()
// ->options(Plant::pluck('name', 'id'))
->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,callable $set) {
session(['selected_plant' => $state]); // fixed typo
//$this->dispatch('cumulativeChart'); // custom Livewire event
// Reset success_status whenever plant changes
$set('success_status', null);
session()->forget('success_status');
}),
Select::make('success_status')
->label('Select Status')
->options([
'Ok' => 'Ok',
'Not Ok' => 'Not Ok',
])
->reactive()
->afterStateUpdated(function ($state) {
session(['success_status' => $state]);
}),
]);
}
public static function getNavigationLabel(): string
{
return 'Production Line Count';
}
public function getHeading(): string
{
return 'Production Line Count';
}
public function getWidgets(): array
{
$widgets = [];
if (CumulativeChart::canView()) {
$widgets[] = CumulativeChart::class;
}
return $widgets;
}
public static function canAccess(): bool
{
return Auth::check() && Auth::user()->can('view production line count dashboard');
}
}

View File

@@ -0,0 +1,363 @@
<?php
namespace App\Filament\Pages;
use App\Models\Item;
use App\Models\Plant;
use App\Models\ProductionQuantity;
use App\Models\QualityValidation;
use App\Models\StickerMaster;
use Filament\Facades\Filament;
use Filament\Forms\Components\Actions;
use Filament\Forms\Components\Actions\Action;
use Filament\Forms\Form;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Pages\Page;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Notifications\Notification;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Auth;
class DataSendToSap extends Page implements HasForms
{
use InteractsWithForms;
public $pId , $pOrder, $pUom, $pItem, $transHeadLog, $sNums = [];
public $scanned_quantity;
public array $data = []; //Required to back form state
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static string $view = 'filament.pages.data-send-to-sap';
protected static ?string $navigationGroup = 'Send To SAP';
protected $listeners = ['updateScannedQuantity' => 'setScannedQuantity'];
public function setScannedQuantity($quantity)
{
// Set the scanned_quantity value in the Filament page/form
$this->scanned_quantity = $quantity;
$this->form->fill([
'scanned_quantity' => $quantity,
'production_order' => $this->pOrder,
'plant_id' => $this->pId,
]);
}
public function form(Form $form): Form
{
return $form
->statePath('data')
->schema([
Select::make('plant_id')
->label('Plant')
// ->options(Plant::pluck('name', 'id'))
->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();
})
->reactive()
->required()
->afterStateUpdated(function ($state, $set, callable $get) {
$plantId = $get('plant_id');
if (!$plantId) {
$set('pqPlantError', 'Please select a plant first.');
$set('production_order', null);
$set('scanned_quantity', null);
return;
}
else {
$this->pId = $plantId;
$set('production_order', null);
$set('scanned_quantity', null);
$set('validationError', null);
$set('pqPlantError', null);
}
})
->hint(fn ($get) => $get('pqPlantError') ? $get('pqPlantError') : null)
->hintColor('danger'),
TextInput::make('production_order')
->required()
->reactive()
->afterStateUpdated(function ($state, $set, callable $get) {
$productionOrder = $get('production_order');
if (!$productionOrder) {
$set('pqproducError', 'Please provide production order.');
$set('production_order', null);
$set('scanned_quantity', null);
$this->dispatch('refreshed', $this->pId, $this->pOrder);
return;
}
else {
$this->pOrder = null;
$this->dispatch('refreshed', $this->pId, $this->pOrder);
$set('scanned_quantity', null);
$set('validationError', null);
$set('pqproducError', null);
}
})
->hint(fn ($get) => $get('pqproducError') ? $get('pqproducError') : null)
->hintColor('danger')
->extraAttributes([
'wire:keydown.enter' => 'processValues($event.target.value)',
]),
TextInput::make('scanned_quantity')
->reactive() // Make it reactive to update when changed
->afterStateUpdated(function ($state, $set, $get) {
$this->scanned_quantity = $state;
})
->readOnly(),
// Add your custom action button here
Actions::make([
Action::make('send_to_sap')
->label('Send Data to SAP')
->action(function ($set, $get) {
$year = date('y'); // '25' for 2025
$month = date('m'); // '05' for May
$plantId = $get('plant_id');
$code = Plant::where('id', $plantId)->value('code');
$finalBatch = $year . $month . $code;
$transHeadLogId = $this->transHeadLog; //'3256';
$lineItemCnt = '1'; //1 hard code
$sapOrder = $get('production_order');
$itemCode = $this->pItem;
$quantity = (string)$get('scanned_quantity');
$UOM = $this->pUom;
$batchNumber = $finalBatch;
$locationName = '';
$lamiCdate = $get('lami_cdate');
$serialNumbers = $this->sNums;
// dd($batchNumber);
$currentDateTime = date('j/n/Y h:i:s A');
$header = [
'Trans_Head_Log_Id' => $transHeadLogId, //'3256',
'Line_Item_Count' => $lineItemCnt, //'1',
'SAP_Order_Number' => $sapOrder, //'12345678'
'Item_Code' => $itemCode, //'6458795'
];
// $serialNumbers = ['12024090000142', '12024090000142', '12024090000142'];
$Receipt = [
// 'Receipt' => [
[
'Quantity' => $quantity, //'1',
'UOM' => $UOM,
'Batch_Number' => $batchNumber,
'Location_Name' => $locationName,
'LAMI_Cdate' => $currentDateTime, //'9/9/2024 10:48:37 AM',
'Serial_Number' => array_map(function ($serial) {
return ['Serial_Number' => $serial];
}, $serialNumbers)
]
// ]
];
$payload = [
// ...$header,
'Receipt' => $Receipt
];
// dd($payload);
// $header = [
// 'Trans_Head_Log_Id' => '3256',
// 'Line_Item_Count' => '1',
// 'SAP_Order_Number' => '12345678',
// 'Item_Code' => '6458795'
// ];
// $serialNumbers = ['12024090000142'];
// $Receipt = [
// // 'Receipt' => [
// [
// 'Quantity' => '1',
// 'UOM' => 'EA',
// 'Batch_Number' => '',
// 'Location_Name' => '',
// 'LAMI_Cdate' => '9/9/2024 10:48:37 AM',
// 'Serial_Number' => array_map(function ($serial) {
// return ['Serial_Number' => $serial];
// }, $serialNumbers)
// ]
// // ]
// ];
// $payload = [
// // ...$header,
// 'Receipt' => $Receipt
// ];
// dd($payload);
try {
// $response = Http::withHeaders([
// 'Content-Type' => 'application/json',
// 'Trans_Head_Log_Id' => '3256',//$transHeadLogId,
// 'Line_Item_Count' => '1', // $lineItemCnt,
// 'SAP_Order_Number' => '12345678', //$sapOrder,
// 'Item_Code' => '6458795', //$itemCode,
// ])
$response = Http::withHeaders([
'Content-Type' => 'application/json',
'Trans_Head_Log_Id' => $transHeadLogId,
'Line_Item_Count' => $lineItemCnt,
'SAP_Order_Number' => $sapOrder,
'Item_Code' => $itemCode,
])
->withBasicAuth(
env('SAP_API_USERNAME'),
env('SAP_API_PASSWORD')
)
->withBody(json_encode($payload), 'application/json')
->post(env('SAP_API_URL'), $payload);
$messageCode = $response->headers()['messagecode'][0] ?? null;
if ($messageCode && str_starts_with($messageCode, 'ERROR')) {
$cleanError = str_replace('ERROR:|', '', $messageCode);
// Update rows where plant_id and production_order match
QualityValidation::where('plant_id', $get('plant_id'))
->where('production_order', $get('production_order'))
->update([
'sap_msg_status' => 'ERROR',
'sap_msg_description' => $cleanError,
]);
Notification::make()
->title('SAP Error')
->body($cleanError)
->danger()
->send();
$this->dispatch('loadItems', $this->pId, $this->pOrder);
}
else
{
$messageCode = $response->headers()['messagecode'][0] ?? null;
$sapSuccessMsg = str_replace('SUCCESS:|', '', $messageCode);
QualityValidation::where('plant_id', $get('plant_id'))
->where('production_order', $get('production_order'))
->update([
'sap_msg_status' => 'SUCCESS',
'sap_msg_description' => $sapSuccessMsg,
]);
Notification::make()
->title('SAP Success')
->body($sapSuccessMsg)
->success()
->send();
$this->dispatch('loadItems', $this->pId, $this->pOrder);
}
} catch (\Exception $e) {
Notification::make()
->title('Exception')
->body('Error sending data to SAP: ' . $e->getMessage())
->danger()
->send();
}
})
->color('success')
->outlined()
->hidden(fn (callable $get) => (!$get('scanned_quantity'))) //!$get('plant_id') && !$get('production_order') &&
->extraAttributes(['class' => 'align-to-input']),
]),
])
->columns(4);
}
public function processValues($value)
{
$this->pOrder = $value;
$plantId = trim($this->form->getState()['plant_id']) ?? null;
//$this->plantId = $plantId;
// $this->pUom = QualityValidation::where('plant_id',$this->pId)
// ->where('production_order',$this->pOrder)
// ->latest()
// ->first()
// ->value('uom');
// $this->transHeadLog = QualityValidation::where('plant_id',$this->pId)
// ->where('production_order',$this->pOrder)
// ->latest()
// ->value('id');
$latestValidation = QualityValidation::where('plant_id', $this->pId)
->where('production_order', $this->pOrder)
->latest()
->first();
if (!$latestValidation) {
Notification::make()
->title('Invalid Production Order')
->body('No data found for the selected plant and production order.')
->danger()
->send();
$this->dispatch('refreshed', $this->pId, $this->pOrder);
$this->pOrder = null;
$this->form->fill([
'plant_id' => $this->pId,
'production_order' => null,
]);
return;
}
$this->pUom = $latestValidation->uom;
$this->transHeadLog = $latestValidation->id;
$this->sNums = [];
if(!$this->pUom)
{
Notification::make()
->title('UOM Not Found')
->body('UOM not found for the production order')
->icon('heroicon-o-x-circle') // optional, to force red/error-style icon
->danger()
->send();
$this->dispatch('refreshed', $this->pId, $this->pOrder);
}
else
{
$this->pItem = Item::where('id', StickerMaster::where('id', QualityValidation::where('plant_id',$this->pId)->where('production_order',$this->pOrder)->latest()->first()->sticker_master_id)->value('item_id'))->value('code');
$this->sNums = QualityValidation::where('plant_id', $this->pId)
->where('production_order', $this->pOrder)
->pluck('serial_number')
->toArray();
//dd($this-> pItem);
$this->dispatch('loadItems', $this->pId, $this->pOrder);
}
}
public static function canAccess(): bool
{
return Auth::check() && Auth::user()->can('view quality data send to sap');
}
public static function getNavigationLabel(): string
{
return 'Quality Data';
}
}

View File

@@ -0,0 +1,76 @@
<?php
namespace App\Filament\Pages;
use App\Filament\Widgets\GuardPatrolDayChart;
use App\Models\Plant;
use Filament\Facades\Filament;
use Filament\Pages\Page;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
use Filament\Forms\Form;
use Filament\Forms\Components\Select;
use Illuminate\Support\Facades\Auth;
class GuardPatrolDayCount extends Page
{
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static string $view = 'filament.pages.guard-patrol-day-count';
protected static ?string $navigationGroup = 'Guard DashBoard';
use HasFiltersForm;
public function mount(): void
{
session()->forget(['selected_plant']);
$this->filtersForm->fill([
'plant' => null
]);
}
public function filtersForm(Form $form): Form
{
return $form
->statePath('filters')
->schema([
Select::make('plant')
->label('Select Plant')
// ->options(Plant::pluck('name', 'id'))
->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();
})
->reactive()
->afterStateUpdated(function ($state) {
session(['selected_plant' => $state]);
$this->dispatch('patrolEntryChart');
}),
]);
}
public static function getNavigationLabel(): string
{
return 'Guard Patrol Day Count';
}
public function getHeading(): string
{
return 'Guard Patrol Day Chart';
}
public function getWidgets(): array
{
return [
GuardPatrolDayChart::class,
];
}
public static function canAccess(): bool
{
return Auth::check() && Auth::user()->can('view guard patrol day count dashboard');
}
}

View File

@@ -0,0 +1,120 @@
<?php
namespace App\Filament\Pages;
use App\Models\GuardPatrolEntry;
use App\Models\Plant;
use Carbon\Carbon;
use Filament\Facades\Filament;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\DateTimePicker;
use Filament\Forms\Components\Select;
use Filament\Forms\Form;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
use Filament\Pages\Page;
use Illuminate\Support\Facades\Auth;
class GuardPatrolEntryDashboard extends Page
{
use HasFiltersForm;
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static ?string $navigationGroup = 'Guard DashBoard';
protected static string $view = 'filament.pages.guard-patrol-entry-dashboard';
public function mount(): void
{
// session()->forget(['select_guard_plant', 'select_guard_date']);
$this->filtersForm->fill([
'plant' => null,
'date' => null,
]);
}
public function filtersForm(Form $form): Form
{
return $form
->statePath('filters') // Explicitly set where to store form data
->schema([
Select::make('plant')
->label('Select Plant')
// ->options(Plant::pluck('name', 'id'))
->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();
})
->reactive()
->required()
->afterStateUpdated(function ($state, callable $set, callable $get){
// $this->dispatch('invoiceChart');
if(!$state)
{
$set('date', now()->format('Y-m-d')); // H:i:s
// session(['select_guard_plant' => $state]);
// session(['select_guard_date' => $get('date')]);
} else {
if(!$get('date'))
{
$set('date', now()->format('Y-m-d'));
// session(['select_guard_plant' => $state]);
// session(['select_guard_date' => $get('date')]);
}
// else {
// session(['select_guard_plant' => $state]);
// session(['select_guard_date' => $get('date')]);
// }
}
$this->dispatch('loadGuardData', $state, $get('date')); //->format('Y-m-d')
}),
DatePicker::make('date')
->label('Select Date')
->placeholder('Select Date')
->reactive()
->required()
->beforeOrEqual(now())
->default(now()->format('Y-m-d'))
->afterStateUpdated(function ($state, callable $set, callable $get){
if(!$get('plant'))
{
$set('date', now()->format('Y-m-d'));
// session(['select_guard_plant' => $get('plant')]);
// session(['select_guard_date' => $state]);
} else {
if(!$get('date'))
{
$set('date', now()->format('Y-m-d'));
// session(['select_guard_plant' => $get('plant')]);
// session(['select_guard_date' => $state]);
}
// else {
// $records = GuardPatrolEntry::whereDate('patrol_time', $state)->where('plant_id', $get('plant'))->orderBy('patrol_time', 'asc')->first(); //desc
// //dd($get('plant'), $state, $records->patrol_time);//->toTimeString()
// session(['select_guard_plant' => $get('plant')]);
// session(['select_guard_date' => $state]);
// }
}
// $this->dispatch('invoiceChart');
$this->dispatch('loadGuardData', $get('plant'), $state);//->format('Y-m-d')
})
])
->columns(2);
}
public static function getNavigationLabel(): string
{
return 'Guard Patrol Status Table';
}
public function getHeading(): string
{
return 'Guard Patrol Entry Status';
}
public static function canAccess(): bool
{
return Auth::check() && Auth::user()->can('view guard patrol entry status dashboard');
}
}

View File

@@ -0,0 +1,271 @@
<?php
namespace App\Filament\Pages;
use App\Filament\Widgets\GuardPatrolHourlyChart;
use App\Models\CheckPointName;
use App\Models\CheckPointTime;
use App\Models\GuardPatrolEntry;
use App\Models\Plant;
use Carbon\Carbon;
use Filament\Facades\Filament;
use Filament\Pages\Page;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
use Filament\Forms\Form;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\DatePicker;
use Illuminate\Support\Facades\Auth;
class GuardPatrolHourlyCount extends Page
{
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static string $view = 'filament.pages.guard-patrol-hourly-count';
protected static ?string $navigationGroup = 'Guard DashBoard';
use HasFiltersForm;
public function mount(): void
{
session()->forget(['selected_plant']);
session()->forget(['selected_date']);
session()->forget(['selected_name']);
session()->forget(['selected_time']);
session()->forget(['valid_sessions']);
$this->filtersForm->fill([
'plant' => null,
'date' => null,
'time_range' => null,
'guard_name' => null
]);
}
public function filtersForm(Form $form): Form
{
return $form
->statePath('filters')
->schema([
Select::make('plant')
->label('Select Plant')
//->options(Plant::pluck('name', 'id'))
->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();
})
->reactive()
->required()
->afterStateUpdated(function ($state,callable $set) {
if (is_null($state)) {
session()->forget('selected_plant');
} else {
session(['selected_plant' => $state]);
}
session(['selected_plant' => $state]);
$set('date', null);
session()->forget('selected_date');
$set('guard_name', null);
session()->forget('selected_name');
$set('time_range', null);
session()->forget('selected_time');
session()->forget('valid_sessions');
// $this->dispatch('patrolEntryChart');
}),
DatePicker::make('date')
->label('Select Date')
->placeholder('Select Date')
->reactive()
->required()
->beforeOrEqual(now())
->default(now()->format('Y-m-d'))
->afterStateUpdated(function ($state,callable $set) {
session(['selected_date' => $state]);
$set('guard_name', null);
session()->forget('selected_name');
$set('time_range', null);
session()->forget('selected_time');
session()->forget('valid_sessions');
// $this->dispatch('patrolEntryChart');
}),
Select::make('guard_name')
->label('Guard Name')
->options(function (callable $get) {
$plantId = $get('plant');
$Date = $get('date');
if (!$plantId || !$Date) {
return [];
}
return GuardPatrolEntry::with('guardNames')->where('plant_id', $plantId)
->whereDate('patrol_time', $Date)->orderBy('patrol_time','asc')
->get()
->unique('guard_name_id')
->pluck('guardNames.name', 'guard_name_id')
->toArray();
})
->reactive()
->required()
->afterStateUpdated(function ($state,callable $set)
{
if (is_null($state))
{
session()->forget('selected_name');
}
else
{
session(['selected_name' => $state]);
}
// Clear the time range field and its session
$set('time_range', null);
session()->forget('selected_time');
session()->forget('valid_sessions');
}),
// Select::make('time_range')
// ->label('Patrol Time Range')
// ->options(function (callable $get) {
// $plantId = $get('plant');
// $guardId = $get('guard_name');
// $date = $get('date');
// if (!$plantId || !$guardId || !$date) {
// return [];
// }
// $patrols = GuardPatrolEntry::where('plant_id', $plantId)
// ->where('guard_name_id', $guardId)
// ->whereDate('patrol_time', $date)
// ->orderBy('patrol_time', 'asc')
// ->get(['patrol_time']);
// if ($patrols->isEmpty())
// {
// return [];
// }
// $chunkSize = CheckPointTime::where('plant_id', $plantId)->count()+ 1;;
// $chunks = $patrols->chunk($chunkSize);
// $options = [];
// foreach ($chunks as $index => $chunk) {
// $first = $chunk->first();
// $last = $chunk->last();
// $start = Carbon::parse($first->patrol_time)->format('H:i:s');
// $end = Carbon::parse($last->patrol_time)->format('H:i:s');
// $timeRange = "$start - $end";
// $options[$timeRange] = $timeRange;
// }
// return $options;
// })
// ->reactive()
// ->required()
// ->afterStateUpdated(function ($state) {
// session(['selected_time' => $state]);
// })
Select::make('time_range')
->label('Patrol Time Range')
->options(function (callable $get) {
$plantId = $get('plant');
$guardId = $get('guard_name');
$date = $get('date');
if (!$plantId || !$guardId || !$date) {
session(['valid_sessions' => []]);
return [];
}
// Get patrols with checkpoints
$patrols = GuardPatrolEntry::where('plant_id', $plantId)
->where('guard_name_id', $guardId)
->whereDate('patrol_time', $date)
->orderBy('patrol_time', 'asc')
->get(['patrol_time', 'check_point_name_id']);
if ($patrols->isEmpty()) {
session(['valid_sessions' => []]);
return [];
}
// Get checkpoint sequence
$checkPointTimes = CheckPointTime::where('plant_id', $plantId)
->orderBy('sequence_number')
->get(['check_point1_id', 'check_point2_id']);
// Build expected sequence
$expectedSequence = [];
foreach ($checkPointTimes as $row) {
$expectedSequence[] = $row->check_point1_id;
}
if ($checkPointTimes->isNotEmpty()) {
$expectedSequence[] = $checkPointTimes->last()->check_point2_id;
}
$chunkSize = $checkPointTimes->count() + 1;
$chunks = $patrols->chunk($chunkSize);
$options = [];
$validSessions = [];
foreach ($chunks as $index => $chunk) {
$first = $chunk->first();
$last = $chunk->last();
$start = Carbon::parse($first->patrol_time)->format('H:i:s');
$end = Carbon::parse($last->patrol_time)->format('H:i:s');
$timeRange = "$start - $end";
// Validate sequence for this chunk
$currentSeqIndex = 0;
$isValid = true;
$anyMatch = false;
foreach ($chunk as $patrol) {
if ($currentSeqIndex < count($expectedSequence) &&
$patrol->check_point_name_id == $expectedSequence[$currentSeqIndex]) {
$currentSeqIndex++;
$anyMatch = true;
} else {
$isValid = false;
}
}
// Consider valid only if at least one checkpoint matches
$isValid = $isValid && $anyMatch;
$validSessions[$timeRange] = $isValid;
$options[$timeRange] = $timeRange;
}
session(['valid_sessions' => $validSessions]);
return $options;
})
->reactive()
->required()
->afterStateUpdated(function ($state) {
session(['selected_time' => $state]);
})
])
->columns(4);
}
public function getWidgets(): array
{
return [
GuardPatrolHourlyChart::class,
];
}
public static function canAccess(): bool
{
return Auth::check() && Auth::user()->can('view guard patrol hourly count dashboard');
}
}

View File

@@ -0,0 +1,138 @@
<?php
namespace App\Filament\Pages;
use App\Filament\Widgets\ItemOverview;
use App\Models\Plant;
use Filament\Facades\Filament;
use Filament\Forms\Components\Select;
use Filament\Forms\Form;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
use Filament\Pages\Page;
use Filament\Tables\Concerns\HasFilters;
use Illuminate\Support\Facades\Auth;
use Filament\Pages\Dashboard;
class HourlyProduction extends page
{
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static string $view = 'filament.pages.hourly-production';
protected static ?string $navigationGroup = 'Production DashBoard';
use HasFiltersForm;
public $selectedPlant;
public $selectedLine;
public $selectedFilter = 'today';
public function mount(): void
{
//session()->forget(['selected_plant', 'selected_line','selected_status']);
session()->forget(['selected_plant', 'selected_line']);
session()->forget(['select_plant', 'select_line']);
$plantId = session('selected_plant', null); // Default to the first plant if not selected
$lineId = session('selected_line', null);
//$successStatus = session('selected_status', null);
$this->filtersForm->fill([
//'plant' => Plant::first()?->id // Default to first plant
'plant' => $plantId,
'line' => $lineId,
//'success_status' => $successStatus,
]);
}
public function filtersForm(Form $form): Form
{
return $form
->statePath('filters')
->schema([
Select::make('plant')
->label('Select Plant')
->reactive()
//->options(Plant::pluck('name', 'id'))
->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) {
session(['selected_plant' => $state]);
// Clear production quantity Dashboard session keys to avoid conflict
//session()->forget(['select_plant', 'select_line']);
$this->triggerChartUpdate();
$this->dispatch('filtersUpdated', [
'plant' => $state,
'line' => session('selected_line') ?? null,
'filter' => session('selected_filter') ?? 'today',
]);
}),
// Line Filter
Select::make('line')
->options(function ($get) {
$plantId = $get('plant');
return $plantId ? Plant::find($plantId)->getLineNames()->pluck('name', 'id') : [];
})
->label('Select Line')
->reactive()
->afterStateUpdated(function ($state) {
session(['selected_line' => $state]);
$this->triggerChartUpdate();
$this->dispatch('filtersUpdated', [
'plant' => session('selected_plant') ?? null,
'line' => $state,
'filter' => session('selected_filter') ?? 'today',
]);
}),
// Select::make('success_status')
// ->label('Select Status')
// ->options([
// 'Ok' => 'Ok',
// 'Not Ok' => 'Not Ok',
// ])
// ->reactive()
// ->afterStateUpdated(function ($state) {
// session(['selected_status' => $state]); // fixed typo
// //$this->dispatch('cumulativeChart'); // custom Livewire event
// }),
])
->columns(3);
}
// public function triggerChartUpdate(): void
// {
// if (session()->has('selected_plant') && session()->has('selected_line') && session()->has('selected_status')) {
// $this->dispatch('filtersUpdated');
// }
// }
public function triggerChartUpdate(): void
{
if (session()->has('selected_plant') && session()->has('selected_line')) {
$this->dispatch('filtersUpdated');
}
}
public static function getNavigationLabel(): string
{
return 'Production Hourly Count';
}
public static function canAccess(): bool
{
return Auth::check() && Auth::user()->can('view production hourly count dashboard');
}
// public function getWidgets(): array
// {
// return [
// ItemOverview::class,
// ];
// }
}

View File

@@ -0,0 +1,80 @@
<?php
namespace App\Filament\Pages;
use App\Models\Plant;
use Filament\Facades\Filament;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Form;
use Filament\Pages\Page;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
use Illuminate\Support\Facades\Auth;
class InvoiceDashboard extends Page
{
use HasFiltersForm;
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static ?string $navigationGroup = 'Invoice DashBoard';
protected static string $view = 'filament.pages.invoice-dashboard';
public function mount(): void
{
session()->forget(['selec_plant', 'select_invoice']);
$this->filtersForm->fill([
'plant' => null,
'invoice' => null,
]);
}
public function filtersForm(Form $form): Form
{
return $form
->statePath('filters') // Explicitly set where to store form data
->schema([
Select::make('plant')
->label('Select Plant')
//->options(Plant::pluck('name', 'id'))
->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();
})
->reactive()
->afterStateUpdated(function ($state) {
session(['selec_plant' => $state]);
$this->dispatch('invoiceChart');
}),
Select::make('invoice')
->options([
'serial_invoice' => 'Serial Invoice',
'individual_material' => 'Individual Material Invoice',
'bundle_material' => 'Bundle Material Invoice',
])
->label('Select Invoice')
->reactive()
->default(0)
->afterStateUpdated(function ($state) {
session(['select_invoice' => $state]);
$this->dispatch('invoiceChart');
})
])
->columns(2);
}
public static function getNavigationLabel(): string
{
return 'Invoice';
}
public static function canAccess(): bool
{
return Auth::check() && Auth::user()->can('view invoice dashboard');
}
}

View File

@@ -0,0 +1,124 @@
<?php
namespace App\Filament\Pages;
use App\Filament\Widgets\InvoiceDataChart;
use App\Models\InvoiceDataValidation;
use App\Models\Plant;
use Filament\Pages\Page;
use Filament\Forms\Form;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
use Filament\Forms\Components\Select;
use Illuminate\Support\Facades\Auth;
use Filament\Facades\Filament;
use Filament\Forms\Components\Section;
class InvoiceDataDashboard extends Page
{
use HasFiltersForm;
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static string $view = 'filament.pages.invoice-data-dashboard';
protected static ?string $navigationGroup = 'Invoice Management';
public function mount(): void
{
session()->forget(['selected_plant','dist_channel']);
$this->filtersForm->fill([
'plant' => null,
'distribution_channel' => null,
]);
}
public function filtersForm(Form $form): Form
{
return $form
->statePath('filters') // Store form state in 'filters'
->schema([
Section::make('')
->schema([
Select::make('plant')
->label('Select Plant')
->reactive()
// ->options(Plant::pluck('name', 'id'))
->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,callable $set) {
session(['selected_plant' => $state]);
$set('distribution_channel', null);
session()->forget('distribution_channel');
}),
Select::make('distribution_channel')
->label('Distribution Channel')
// ->options(function (callable $get) {
// $plant = $get('plant');
// if (!$plant) {
// return [];
// }
// $options = InvoiceDataValidation::where('plant_id', $plant)
// ->whereNotNull('distribution_channel_desc')
// ->where('distribution_channel_desc', '!=', '')
// ->select('distribution_channel_desc')
// ->distinct()
// ->pluck('distribution_channel_desc', 'distribution_channel_desc')
// ->toArray();
// $hasEmpty = InvoiceDataValidation::where('plant_id', $plant)
// ->where(function ($q) {
// $q->whereNull('distribution_channel_desc')
// ->orWhere('distribution_channel_desc', '');
// })
// ->exists();
// if ($hasEmpty) {
// $options['Challan'] = 'Challan';
// }
// return $options;
// })
->options(function (callable $get) {
$plant = $get('plant');
if (!$plant) {
return [];
}
// Fetch unique, non-empty distribution_channel_desc values
return InvoiceDataValidation::where('plant_id', $plant)
->whereNotNull('distribution_channel_desc')
->where('distribution_channel_desc', '!=', '')
->distinct()
->pluck('distribution_channel_desc', 'distribution_channel_desc')
->toArray();
})
->afterStateUpdated(callback: function ($state,callable $set) {
session(['dist_channel' => $state]);
})
->reactive(),
])
->columns(2),
]);
}
public static function getNavigationLabel(): string
{
return 'Invoice Data Dashboard';
}
public function getHeading(): string
{
return 'Invoice Data Dashboard';
}
public static function canAccess(): bool
{
return Auth::check() && Auth::user()->can('view invoice data dashboard');
}
}

View File

@@ -0,0 +1,225 @@
<?php
namespace App\Filament\Pages;
use App\Models\LocatorInvoiceValidation;
use App\Models\PalletValidation;
use App\Models\Plant;
use Filament\Facades\Filament;
use Illuminate\Support\Facades\Auth;
use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Pages\Page;
use Filament\Forms\Form;
use Filament\Forms\Components\Section;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Notifications\Notification;
class InvoiceFinder extends Page implements HasForms
{
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static string $view = 'filament.pages.invoice-finder';
protected static ?string $navigationGroup = 'Export Dispatch';
protected static ?int $navigationSort = 6;
//use InteractsWithForms;
public $pId, $invoiceNumber;
public array $invoiceOverviewData = [];
public array $filters = [];
public function form(Form $form): Form
{
return $form
->statePath('filters')
->schema([
Section::make('') // You can give your section a title or leave it blank
->schema([
Select::make('plant_id')
->label('Plant')
//->options(Plant::pluck('name', 'id'))
->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();
})
->reactive()
->required(),
TextInput::make('scan_invoice')
->label('Scan Invoice')
->required()
->reactive()
->extraAttributes([
'wire:keydown.enter' => 'processInvoiceNo($event.target.value)',
]),
TextInput::make('scan_quantity')
->label('Scanned Quantity ')
->readOnly()
->reactive(),
TextInput::make('pending_quantity')
->label('Pending Quantity')
->readOnly()
->reactive(),
TextInput::make('total_sno_quantity')
->label('Invoice Quantity')
->readOnly()
->reactive(),
])
->columns(5)
]);
}
public function processInvoiceNo($invoiceNo)
{
$plantId = $this->form->getState()['plant_id'];
if(!$invoiceNo)
{
Notification::make()
->title("Invoice number '$invoiceNo' can't be empty!")
->danger()
->duration(5000)
->send();
$this->dispatch('loadData', '', [], [], [], [], $plantId);
$this->form->fill([
'plant_id' => $plantId,
'scan_invoice' => $invoiceNo,
'total_sno_quantity' => 0,
'pending_quantity' => 0,
'scan_quantity' => 0
]);
return;
}
$invoiceExists = LocatorInvoiceValidation::where('plant_id', $plantId)
->where('invoice_number', $invoiceNo)
->first();
if(!$invoiceExists)
{
Notification::make()
->title("Invoice number '$invoiceNo' does not exist in locator invoice table!")
->danger()
->duration(5000)
->send();
$this->dispatch('loadData', '', [], [], [], [], $plantId);
$this->form->fill([
'plant_id' => $plantId,
'scan_invoice' => null,//$invoiceNo,
'total_sno_quantity' => 0,
'pending_quantity' => 0,
'scan_quantity' => 0
]);
return;
}
$invoiceCompleted = LocatorInvoiceValidation::where('plant_id', $plantId)
->where('invoice_number', $invoiceNo)
->whereNull('scanned_status')
->orWhere('scanned_status', '=','')
->first();
if(!$invoiceCompleted)
{
// $count = LocatorInvoiceValidation::where('invoice_number', $invoiceNo)
// ->where('plant_id', $plantId)
// ->count();
Notification::make()
->title("Invoice number '$invoiceNo' already completed the scanning process..!")
->success()
->duration(5000)
->send();
$this->dispatch('loadData', '', [], [], [], [], $plantId);
$this->form->fill([
'plant_id' => $plantId,
'scan_invoice' => null,//$invoiceNo,
'total_sno_quantity' => 0,//$count,
'pending_quantity' => 0,//0,
'scan_quantity' => 0//$count
]);
return;
}
$serialNumbers = LocatorInvoiceValidation::where('plant_id', $plantId)
->where('invoice_number', $invoiceNo)
->pluck('serial_number');
$notFoundSerials = [];
$incompleteSerials = [];
$scannedSerials = [];
$foundSerials = [];
foreach ($serialNumbers as $serial)
{
$locatorRecord = LocatorInvoiceValidation::where('serial_number', $serial)
->where('plant_id', $plantId)
->first();
//$scannedStatus = $locatorRecord->scanned_status ?? null;
if ($locatorRecord->scanned_status == 'Scanned')
{
$scannedSerials[] = $serial;
continue;
}
$palletRecord = palletValidation::where('serial_number', $serial)
->where('plant_id', $plantId)
->first();
if (!$palletRecord)
{
$notFoundSerials[] = $serial;
continue;
}
$palletStatus = $palletRecord->pallet_status ?? null;
if (strlen($palletRecord->pallet_number) > 1 && ($palletStatus == '' || $palletStatus == null))
{
$incompleteSerials[] = $serial;
continue;
}
$foundSerials[] = $serial;
}
$count = LocatorInvoiceValidation::where('invoice_number', $invoiceNo)
->where('plant_id', $plantId)
->count();
$pendingCount = LocatorInvoiceValidation::where('invoice_number', $invoiceNo)
->where('plant_id', $plantId)
->whereNull('scanned_status')
->orWhere('scanned_status', '=', '')
->count();
$scannedCount = LocatorInvoiceValidation::where('invoice_number', $invoiceNo)
->where('plant_id', $plantId)
->where('scanned_status', '=', 'Scanned')
->count();
$this->form->fill([
'plant_id' => $plantId,
'scan_invoice' => $invoiceNo,
'total_sno_quantity' => $count,
'pending_quantity' => $pendingCount,
'scan_quantity' => $scannedCount,
]);
$this->dispatch('loadData', $invoiceNo, $notFoundSerials, $incompleteSerials, $scannedSerials, $foundSerials, $plantId);
}
public static function canAccess(): bool
{
return Auth::check() && Auth::user()->can('view invoice finder page');
}
}

View File

@@ -0,0 +1,75 @@
<?php
namespace App\Filament\Pages;
use App\Models\Plant;
use Filament\Facades\Filament;
use Filament\Pages\Page;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
use Filament\Forms\Form;
use Filament\Forms\Components\Select;
use Illuminate\Support\Facades\Auth;
class InvoiceQuantityDashboard extends Page
{
use HasFiltersForm;
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static ?string $navigationGroup = 'Invoice DashBoard';
protected static string $view = 'filament.pages.invoice-quantity-dashboard';
public function mount(): void
{
session()->forget(['selec_plant', 'select_invoice']);
$this->filtersForm->fill([
'plant' => null,
'invoice' => null,
]);
}
public function filtersForm(Form $form): Form
{
return $form
->statePath('filters') // Explicitly set where to store form data
->schema([
Select::make('plant')
->label('Select Plant')
//->options(Plant::pluck('name', 'id'))
->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();
})
->reactive()
->afterStateUpdated(function ($state) {
session(['selec_plant' => $state]);
$this->dispatch('invoiceChart');
}),
Select::make('invoice')
->options([
'serial_invoice' => 'Serial Invoice',
'individual_material' => 'Individual Material Invoice',
'bundle_material' => 'Bundle Material Invoice',
])
->label('Select Invoice')
->reactive()
->default(0)
->afterStateUpdated(function ($state) {
session(['select_invoice' => $state]);
$this->dispatch('invoiceChart');
})
])
->columns(2);
}
public static function getNavigationLabel(): string
{
return 'Invoice Quantity';
}
public static function canAccess(): bool
{
return Auth::check() && Auth::user()->can('view invoice serial quantity dashboard');
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,375 @@
<?php
namespace App\Filament\Pages;
use App\Models\Item;
use App\Models\Plant;
use App\Models\ProductionQuantity;
use App\Models\QualityValidation;
use App\Models\StickerMaster;
use Filament\Facades\Filament;
use Filament\Forms\Components\Actions;
use Filament\Forms\Components\Actions\Action;
use Filament\Forms\Form;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Pages\Page;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Notifications\Notification;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Auth;
class ProductionDataSap extends Page implements HasForms
{
use InteractsWithForms;
public $pId , $pOrder, $pUom, $pItem, $transHeadLog, $sNums = [];
public $scanned_quantity;
public array $data = []; //Required to back form state
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static string $view = 'filament.pages.production-data-sap';
protected static ?string $navigationGroup = 'Send To SAP';
protected $listeners = ['updateScannedQuantity' => 'setScannedQuantity'];
public function setScannedQuantity($quantity)
{
// Set the scanned_quantity value in the Filament page/form
$this->scanned_quantity = $quantity;
$this->form->fill([
'scanned_quantity' => $quantity,
'production_order' => $this->pOrder,
'plant_id' => $this->pId,
]);
}
public function form(Form $form): Form
{
return $form
->statePath('data')
->schema([
Select::make('plant_id')
->label('Plant')
->reactive()
->required()
//->options(Plant::pluck('name', 'id'))
->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) {
$plantId = $get('plant_id');
if (!$plantId) {
$set('pqPlantError', 'Please select a plant first.');
$set('production_order', null);
$set('scanned_quantity', null);
return;
}
else {
$this->pId = $plantId;
$set('production_order', null);
$set('scanned_quantity', null);
$set('validationError', null);
$set('pqPlantError', null);
}
})
->hint(fn ($get) => $get('pqPlantError') ? $get('pqPlantError') : null)
->hintColor('danger'),
TextInput::make('production_order')
->required()
->reactive()
->afterStateUpdated(function ($state, $set, callable $get) {
$productionOrder = $get('production_order');
if (!$productionOrder) {
$set('pqproducError', 'Please provide production order.');
$set('scanned_quantity', null);
$this->dispatch('refreshed', $this->pId, $this->pOrder);
return;
}
else {
$this->pOrder = null;
$this->dispatch('refreshed', $this->pId, $this->pOrder);
$set('scanned_quantity', null);
$set('validationError', null);
$set('pqproducError', null);
}
})
->hint(fn ($get) => $get('pqproducError') ? $get('pqproducError') : null)
->hintColor('danger')
->extraAttributes([
'wire:keydown.enter' => 'processValues($event.target.value)',
]),
TextInput::make('scanned_quantity')
->reactive() // Make it reactive to update when changed
->afterStateUpdated(function ($state, $set, $get) {
$this->scanned_quantity = $state;
})
->readOnly()
->required(),
// Add your custom action button here
Actions::make([
Action::make('send_to_sap')
->label('Send Data to SAP')
->action(function ($set, $get) {
$plantId = $get('plant_id');
$plantWarehouseCodes = [
// plant_id => warehouse_code
1 => '110', // Ransar I
2 => '101', // Ransar II
3 => '102', // Chola Pumps
4 => '104', // Tuff Pumps
//5 => '107', //WH-Nark
5 => '200', // Go-flex
//7 => '301', // Krisgo II
];
$year = date('y'); // '25' for 2025
$month = date('m'); // '05' for May
$transHeadLogId = $this->transHeadLog; //'3256';
$lineItemCnt = '1'; //1 hard code
$sapOrder = $get('production_order');
$itemCode = $this->pItem;
$quantity = (string)$get('scanned_quantity');
$UOM = $this->pUom;
$locationName = '';
$lamiCdate = $get('lami_cdate');
$serialNumbers = $this->sNums;
$warehouseCode = $plantWarehouseCodes[$plantId] ?? null;
$finalBatch = $warehouseCode . $year . $month;
$batchNumber = $finalBatch;
//dd($batchNumber);
$currentDateTime = date('j/n/Y h:i:s A');
$header = [
'Trans_Head_Log_Id' => $transHeadLogId, //'3256',
'Line_Item_Count' => $lineItemCnt, //'1',
'SAP_Order_Number' => $sapOrder, //'12345678'
'Item_Code' => $itemCode, //'6458795'
];
// $serialNumbers = ['12024090000142', '12024090000142', '12024090000142'];
$Receipt = [
// 'Receipt' => [
[
'Quantity' => $quantity, //'1',
'UOM' => $UOM,
'Batch_Number' => $batchNumber,
'Location_Name' => $locationName,
'LAMI_Cdate' => $currentDateTime, //'9/9/2024 10:48:37 AM',
'Serial_Number' => array_map(function ($serial) {
return ['Serial_Number' => $serial];
}, $serialNumbers)
]
// ]
];
$payload = [
// ...$header,
'Receipt' => $Receipt
];
// dd($payload);
// $header = [
// 'Trans_Head_Log_Id' => '3256',
// 'Line_Item_Count' => '1',
// 'SAP_Order_Number' => '12345678',
// 'Item_Code' => '6458795'
// ];
// $serialNumbers = ['12024090000142'];
// $Receipt = [
// // 'Receipt' => [
// [
// 'Quantity' => '1',
// 'UOM' => 'EA',
// 'Batch_Number' => '',
// 'Location_Name' => '',
// 'LAMI_Cdate' => '9/9/2024 10:48:37 AM',
// 'Serial_Number' => array_map(function ($serial) {
// return ['Serial_Number' => $serial];
// }, $serialNumbers)
// ]
// // ]
// ];
// $payload = [
// // ...$header,
// 'Receipt' => $Receipt
// ];
// dd($payload);
try {
// $response = Http::withHeaders([
// 'Content-Type' => 'application/json',
// 'Trans_Head_Log_Id' => '3256',//$transHeadLogId,
// 'Line_Item_Count' => '1', // $lineItemCnt,
// 'SAP_Order_Number' => '12345678', //$sapOrder,
// 'Item_Code' => '6458795', //$itemCode,
// ])
$response = Http::withHeaders([
'Content-Type' => 'application/json',
'Trans_Head_Log_Id' => $transHeadLogId,
'Line_Item_Count' => $lineItemCnt,
'SAP_Order_Number' => $sapOrder,
'Item_Code' => $itemCode,
])
->withBasicAuth(
'sb-eba140ab-74bb-44a4-8d92-70a636940def!b1182|it-rt-dev-cri-stjllphr!b68',
'616d8991-307b-4ab1-be37-7894a8c6db9d$0p0fE2I7w1Ve23-lVSKQF0ka3mKrTVcKPJYELr-i4nE='
)
->withBody(json_encode($payload), 'application/json')
//->dump()
->post('https://dev-cri-stjllphr.it-cpi004-rt.cfapps.ap11.hana.ondemand.com/http/LA2CRI/GoodsReceiptAgFG', $payload);
// dump($response->transferStats->getRequest());
// dd(json_encode($payload, JSON_PRETTY_PRINT));
//dd($response->status(), $response->body());
// dump($response);
$messageCode = $response->headers()['messagecode'][0] ?? null;
if ($messageCode && str_starts_with($messageCode, 'ERROR')) {
$cleanError = str_replace('ERROR:|', '', $messageCode);
// Update rows where plant_id and production_order match
ProductionQuantity::where('plant_id', $get('plant_id'))
->where('production_order', $get('production_order'))
->update([
'sap_msg_status' => 'ERROR',
'sap_msg_description' => $cleanError,
]);
Notification::make()
->title('SAP Error')
->body($cleanError)
->danger()
->send();
$this->dispatch('loadItems', $this->pId, $this->pOrder);
}
else
{
$messageCode = $response->headers()['messagecode'][0] ?? null;
$sapSuccessMsg = str_replace('SUCCESS:|', '', $messageCode);
ProductionQuantity::where('plant_id', $get('plant_id'))
->where('production_order', $get('production_order'))
->update([
'sap_msg_status' => 'SUCCESS',
'sap_msg_description' => $sapSuccessMsg,
]);
Notification::make()
->title('SAP Success')
->body($sapSuccessMsg)
->success()
->send();
}
} catch (\Exception $e) {
Notification::make()
->title('Exception')
->body('Error sending data to SAP: ' . $e->getMessage())
->danger()
->send();
}
})
->color('success')
->outlined()
->hidden(fn (callable $get) => (!$get('scanned_quantity'))) //!$get('plant_id') && !$get('production_order') &&
->extraAttributes(['class' => 'align-to-input']),
]),
])
->columns(4);
}
public function processValues($value)
{
$this->pOrder = $value;
$latestValidation = ProductionQuantity::where('plant_id', $this->pId)
->where('production_order', $this->pOrder)
->latest()
->first();
if (!$latestValidation) {
Notification::make()
->title('Invalid Production Order')
->body('No data found for the selected plant and production order.')
->danger()
->send();
$this->dispatch('refreshed', $this->pId, $this->pOrder);
return;
}
// $this->pUom = $latestValidation->uom;
$this->transHeadLog = $latestValidation->id;
$itemId = $latestValidation->item_id;
$this->pUom = Item::where('id', $itemId)->value('uom');
$this->sNums = [];
if(!$this->pUom)
{
Notification::make()
->title('UOM Not Found')
->body('UOM not found for the production order')
->icon('heroicon-o-x-circle')
->danger()
->send();
$this->dispatch('refreshed', $this->pId, $this->pOrder);
}
else
{
$latestProduction = ProductionQuantity::where('plant_id', $this->pId)
->where('production_order', $this->pOrder)
->latest()
->first();
$this->pItem = $latestProduction
? Item::where('id', $latestProduction->item_id)->value('code')
: null;
$this->sNums = ProductionQuantity::where('plant_id', $this->pId)
->where('production_order', $this->pOrder)
->pluck('serial_number')
->toArray();
$this->dispatch('loadItems', $this->pId, $this->pOrder);
}
}
public static function canAccess(): bool
{
return Auth::check() && Auth::user()->can('view production data send to sap');
}
public static function getNavigationLabel(): string
{
return 'Production Data';
}
}

View File

@@ -0,0 +1,74 @@
<?php
namespace App\Filament\Pages;
use App\Models\Plant;
use Filament\Facades\Filament;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Form;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
use Filament\Pages\Page;
use Illuminate\Support\Facades\Auth;
class ProductionLineStopCount extends Page
{
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static string $view = 'filament.pages.production-line-stop-count';
protected static ?string $navigationGroup = 'Production DashBoard';
use HasFiltersForm;
public function mount(): void
{
session()->forget(['selected_plant', 'selected_line']);
$this->filtersForm->fill([
//'plant' => Plant::first()?->id // Default to first plant
'plant' => null,
'line' => null,
]);
}
public function filtersForm(Form $form): Form
{
return $form
->statePath('filters')
->schema([
Select::make('plant')
->label('Select Plant')
//->options(Plant::pluck('name', 'id'))
->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();
})
->reactive()
->afterStateUpdated(function ($state) {
session(['selected_plant' => $state]);
}),
// Line Filter
Select::make('line')
->options(function ($get) {
$plantId = $get('plant');
return $plantId ? Plant::find($plantId)->getLineNames()->pluck('name', 'id') : [];
})
->label('Select Line')
->reactive()
->afterStateUpdated(function ($state) {
session(['selected_line' => $state]);
}),
])
->columns(2);
}
public static function canAccess(): bool
{
return Auth::check() && Auth::user()->can('view production line stop count dashboard');
}
}

View File

@@ -0,0 +1,110 @@
<?php
namespace App\Filament\Pages;
use App\Models\Plant;
use Filament\Facades\Filament;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Form;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
use Filament\Pages\Page;
use Filament\Tables\Concerns\HasFilters;
use Illuminate\Support\Facades\Auth;
class ProductionOrderCount extends Page
{
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static string $view = 'filament.pages.production-order-count';
protected static ?string $navigationGroup = 'Production DashBoard';
use HasFiltersForm;
public function mount(): void
{
session()->forget(['selected_plant', 'selected_line', 'selected_status', 'production_order']);
$this->filtersForm->fill([
'plant' => null,
'line' => null,
'selected_status' => null,
'production_order' => null,
]);
}
public function filtersForm(Form $form): Form
{
return $form
->statePath('filters') // Explicitly set where to store form data
->schema([
Select::make('plant')
->label('Select Plant')
->reactive()
//->options(Plant::pluck('name', 'id'))
->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) {
session(['selected_plant' => $state]);
$this->triggerChartUpdate();
}),
// Line Filter
Select::make('line')
->options(function ($get) {
$plantId = $get('plant');
return $plantId ? Plant::find($plantId)->getLineNames()->pluck('name', 'id') : [];
})
->label('Select Line')
->reactive()
->afterStateUpdated(function ($state) {
session(['selected_line' => $state]); // Store in session
$this->triggerChartUpdate();
}),
Select::make('success_status')
->label('Select Status')
->options([
'Ok' => 'Ok',
'Not Ok' => 'Not Ok',
])
->reactive()
->afterStateUpdated(function ($state) {
session(['selected_status' => $state]); // fixed typo
//$this->dispatch('cumulativeChart'); // custom Livewire event
}),
// Production Order Text Input
TextInput::make('production_order')
->label('Production Order')
->reactive()
->afterStateUpdated(function ($state) {
session(['production_order' => $state]);
$this->triggerChartUpdate();
}),
])
->columns(4);
}
// public function triggerChartUpdate(): void
// {
// if (session()->has('selected_plant') && session()->has('selected_line') && session()->has('production_order')) {
// $this->dispatch('productionOrderChart');
// }
// }
public function triggerChartUpdate(): void
{
$filters = $this->filtersForm->getState();
if (!empty($filters['plant']) && !empty($filters['line']) && !empty($filters['production_order']) && !empty($filters['success_status'])) {
$this->dispatch('productionOrderChart', filters: $filters);
}
}
public static function canAccess(): bool
{
return Auth::check() && Auth::user()->can('view production order count dashboard');
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,133 @@
<?php
namespace App\Filament\Pages;
use App\Filament\Widgets\TrendChartAnalysis;
use App\Models\MfmMeter;
use Filament\Facades\Filament;
use Filament\Pages\Page;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
use App\Models\Plant;
use Filament\Forms\Components\Select;
use Filament\Forms\Form;
use Filament\Forms\Components\DateTimePicker;
use Illuminate\Support\Facades\Auth;
class TrendChartAnalys extends Page
{
use HasFiltersForm;
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static string $view = 'filament.pages.trend-chart-analys';
protected static ?string $navigationGroup = 'EMS DashBoard';
// use HasFiltersForm;
public function mount(): void
{
session()->forget(['selected_plant', 'selected_meter', 'from_datetime', 'to_datetime', 'parameter']);
$this->filtersForm->fill([
'selected_plant' => null,
'selected_meter' => null,
'from_datetime' => null,
'to_datetime' => null,
'parameter' => null,
]);
}
public function filtersForm(Form $form): Form
{
return $form
->statePath('filters')
->schema([
DateTimePicker::make('from_datetime')
->label('From DateTime')
->required()
->before('to_datetime')
->reactive()
->afterStateUpdated(function ($state) {
$formatted = \Carbon\Carbon::parse($state)->format('Y-m-d H:i:s');
session(['from_datetime' => $formatted]);
}),
DateTimePicker::make('to_datetime')
->label('To DateTime')
->required()
->after('from_datetime')
->reactive()
->afterStateUpdated(function ($state) {
$formatted = \Carbon\Carbon::parse($state)->format('Y-m-d H:i:s');
session(['to_datetime' => $formatted]);
}),
Select::make('plant')
->label('Select Plant')
->reactive()
->required()
//->options(Plant::pluck('name', 'id'))
->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, callable $set) {
session(['selected_plant' => $state]);
// When plant changes, also reset meter_name
$set('meter_name', null);
session(['selected_meter' => null]);
// dd($state);
}),
Select::make('meter_name')
->options(function ($get) {
$plantId = $get('plant');
// Return meter name/id pairs from mfm_meters where plant_id matches selected plant
return $plantId ? MfmMeter::where('plant_id', $plantId)->pluck('name', 'id') : [];
})
->label('Select Meter')
->reactive()
->required()
->afterStateUpdated(function ($state) {
session(['selected_meter' => $state]);
}),
Select::make('parameter')
->options([
'Phase Voltage' => 'Phase Voltage',
'Line Voltage' => 'Line Voltage',
'Current' => 'Current',
'Active Power' => 'Active Power',
'Power Factor' => 'Power Factor',
'Units' => 'Units',
])
->label('Select Parameter')
->reactive()
->required()
->afterStateUpdated(function ($state) {
session(['parameter' => $state]);
}),
])
->columns(5);
}
public static function getNavigationLabel(): string
{
return 'Trend Chart Analysis';
}
public function getHeading(): string
{
return 'Trend Chart Analysis';
}
public function getWidgets(): array
{
$widgets = [];
if (TrendChartAnalysis::canView()) {
$widgets[] = TrendChartAnalysis::class;
}
return $widgets;
}
public static function canAccess(): bool
{
return Auth::check() && Auth::user()->can('view ems trend chart analysis dashboard');
}
}

View File

@@ -0,0 +1,131 @@
<?php
namespace App\Filament\Pages;
use App\Filament\Widgets\TrendLineChart;
use Filament\Facades\Filament;
use Filament\Pages\Page;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
use App\Models\Plant;
use Filament\Forms\Components\Select;
use Filament\Forms\Form;
use Filament\Forms\Components\DateTimePicker;
use App\Models\MfmMeter;
use Illuminate\Support\Facades\Auth;
class TrendLineAnalysis extends Page
{
use HasFiltersForm;
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static string $view = 'filament.pages.trend-line-analysis';
protected static ?string $navigationGroup = 'EMS DashBoard';
public function mount(): void
{
session()->forget(['selected_plant', 'selected_meter', 'from_datetime', 'to_datetime', 'parameter']);
$this->filtersForm->fill([
'selected_plant' => null,
'selected_meter' => null,
'from_datetime' => null,
'to_datetime' => null,
'parameter' => null,
]);
}
public function filtersForm(Form $form): Form
{
return $form
->statePath('filters')
->schema([
DateTimePicker::make('from_datetime')
->label('From DateTime')
->required()
->before('to_datetime')
->reactive()
->afterStateUpdated(function ($state) {
$formatted = \Carbon\Carbon::parse($state)->format('Y-m-d H:i:s');
session(['from_datetime' => $formatted]);
}),
DateTimePicker::make('to_datetime')
->label('To DateTime')
->required()
->after('from_datetime')
->reactive()
->afterStateUpdated(function ($state) {
$formatted = \Carbon\Carbon::parse($state)->format('Y-m-d H:i:s');
session(['to_datetime' => $formatted]);
}),
Select::make('plant')
->label('Select Plant')
->reactive()
->required()
//->options(Plant::pluck('name', 'id'))
->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, callable $set) {
session(['selected_plant' => $state]);
// When plant changes, also reset meter_name
$set('meter_name', null);
session(['selected_meter' => null]);
// dd($state);
}),
Select::make('meter_name')
->options(function ($get) {
$plantId = $get('plant');
// Return meter name/id pairs from mfm_meters where plant_id matches selected plant
return $plantId ? MfmMeter::where('plant_id', $plantId)->pluck('name', 'id') : [];
})
->label('Select Meter')
->reactive()
->required()
->afterStateUpdated(function ($state) {
session(['selected_meter' => $state]);
}),
Select::make('parameter')
->options([
'Phase Voltage' => 'Phase Voltage',
'Line Voltage' => 'Line Voltage',
'Current' => 'Current',
'Active Power' => 'Active Power',
'Power Factor' => 'Power Factor',
'Units' => 'Units',
])
->label('Select Parameter')
->reactive()
->required()
->afterStateUpdated(function ($state) {
session(['parameter' => $state]);
}),
])
->columns(5);
}
// public static function getNavigationLabel(): string
// {
// return 'Trend Chart Analysis';
// }
// public function getHeading(): string
// {
// return 'Trend Chart Analysis';
// }
public function getWidgets(): array
{
$widgets = [];
if (TrendLineChart::canView()) {
$widgets[] = TrendLineChart::class;
}
return $widgets;
}
public static function canAccess(): bool
{
return Auth::check() && Auth::user()->can('view ems trend line analysis dashboard');
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,516 @@
<?php
namespace App\Filament\Pages;
use App\Models\Item;
use App\Models\Plant;
use Filament\Pages\Page;
use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
use Filament\Forms\Form;
use Filament\Notifications\Notification;
use Filament\Forms\Components\Actions\Action;
use Filament\Facades\Filament;
use Filament\Forms\Components\Actions;
use Filament\Forms\Components\Field;
use Filament\Forms\Components\Hidden;
use Filament\Forms\Components\Section;
use Filament\Forms\Components\Select;
use Filament\Forms\Contracts\HasForms;
use Illuminate\Support\Facades\Auth;
use Smalot\PdfParser\Parser;
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
use Storage;
use SimpleSoftwareIO\QrCode\Facades\QrCode;
use setasign\Fpdi\Fpdi;
class WebcamCapture extends Page implements HasForms
{
use InteractsWithForms;
use HasFiltersForm;
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static string $view = 'filament.pages.webcam-capture';
public $photo;
// public function filtersForm(Form $form): Form
// {
// return $form
// ->statePath('filters')
// ->schema([
// FileUpload::make('photo')
// ->dehydrated(false)
// ->label('Capture from Webcam')
// ->disk('local')
// ->directory('uploads')
// ->preserveFilenames()
// ->image()
// ->helperText('You can take a picture from your webcam'),
// Actions::make([
// Action::make('uploadNow')
// ->label('Upload PDF Now')
// ->action(function ($get, callable $set) {
// $uploadedFiles = $get('photo');
// if (is_array($uploadedFiles) && count($uploadedFiles) > 0)
// {
// $uploaded = reset($uploadedFiles);
// if ($uploaded instanceof TemporaryUploadedFile) {
// $originalName = $uploaded->getClientOriginalName();
// $path = 'uploads/OCR/' . $originalName;
// // Check if file already exists
// if (Storage::disk('local')->exists($path)) {
// Notification::make()
// ->title('Duplicate File')
// ->body("The file '{$originalName}' already exists in uploads/OCR.")
// ->warning()
// ->send();
// return; // Stop here
// }
// $storedPath = $uploaded->storeAs(
// 'uploads/OCR',
// $originalName,
// 'local'
// );
// // $fullPath = storage_path('app/' . $storedPath);
// $fullPath = storage_path('app/' . $storedPath);
// // Parse PDF using smalot/pdfparser
// $parser = new Parser();
// $pdf = $parser->parseContent(file_get_contents($uploaded->getRealPath()));
// $text = $pdf->getText();
// dd($text);
// }
// }
// else
// {
// Notification::make()
// ->title('No file selected to upload')
// ->warning()
// ->send();
// return;
// }
// }),
// Action::make('downloadAttachment')
// ->label('Download PDF')
// ->action(function ($get) {
// $equipmentNumber = $get('process_order');
// if (!$equipmentNumber) {
// Notification::make()
// ->title('No process order entered')
// ->danger()
// ->send();
// return;
// }
// $files = Storage::disk('local')->files('uploads/ProcessOrder');
// $fileToDownload = null;
// foreach ($files as $file) {
// if (str_contains($file, $equipmentNumber)) {
// $fileToDownload = $file;
// break;
// }
// }
// if (!$fileToDownload) {
// Notification::make()
// ->title('PDF not found for this process order')
// ->danger()
// ->send();
// return;
// }
// return response()->download(Storage::disk('local')->path($fileToDownload));
// }),
// // Action::make('removeAttachment')
// // ->label('Remove PDF')
// // ->action(function ($get) {
// // $equipmentNumber = $get('process_order');
// // if (!$equipmentNumber) {
// // Notification::make()
// // ->title('No process order entered')
// // ->danger()
// // ->send();
// // return;
// // }
// // // Get all files from uploads/temp
// // $files = Storage::disk('local')->files('uploads/ProcessOrder');
// // $fileToDelete = null;
// // foreach ($files as $file) {
// // if (str_contains($file, $equipmentNumber)) {
// // $fileToDelete = $file;
// // break;
// // }
// // }
// // if (!$fileToDelete) {
// // Notification::make()
// // ->title('PDF not found for this process order')
// // ->danger()
// // ->send();
// // return;
// // }
// // // Delete the matched file
// // Storage::disk('local')->delete($fileToDelete);
// // Notification::make()
// // ->title('PDF removed successfully')
// // ->body("File for process order {$equipmentNumber} has been deleted.")
// // ->success()
// // ->send();
// // }),
// ]),
// ])
// ->columns(1);
// }
public function filtersForm(Form $form): Form
{
return $form
->statePath('filters')
->schema([
Section::make('') // You can give your section a title or leave it blank
->schema([
Select::make('plant_id')
->label('Plant')
->reactive()
//->relationship('plant', 'name')
->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();
})
->required(),
Select::make('item_id')
->label('Item Code')
->reactive()
->searchable()
->options(function (callable $get) {
if (!$get('plant_id')) {
return [];
}
return Item::where('plant_id', $get('plant_id'))
->pluck('code', 'id')
->toArray();
})
->required(),
TextInput::make('gr_number')
->label('GR Number')
->minLength(7)
->required(),
Actions::make([
// Action::make('uploadNow1')
// ->label('Upload OCR')
// ->action(function ($get, callable $set) {
// $uploadedFiles = $get('photo');
// // $serialNumbers = [
// // $get('serial_1'),
// // $get('serial_2'),
// // $get('serial_3'),
// // $get('serial_4'),
// // ];
// if (is_array($uploadedFiles) && count($uploadedFiles) > 0)
// {
// $uploaded = reset($uploadedFiles);
// if ($uploaded instanceof TemporaryUploadedFile) {
// $grNumber = $get('gr_number');
// $safeName = preg_replace('/[^A-Za-z0-9_\-]/', '_', $grNumber);
// // $originalName = $uploaded->getClientOriginalName();
// // $path = 'uploads/GRNumber/' . $originalName;
// $finalFileName = $safeName . '.jpg';
// $finalPath = 'uploads/OCR/' . $finalFileName;
// $storedPath = $uploaded->storeAs(
// 'uploads/OCR',
// $finalFileName,
// 'local'
// );
// // $storedPath = $uploaded->storeAs('uploads/OCR', $finalFileName, 'local');
// // $fullPath = storage_path('app/' . $storedPath);
// $storedPath = $uploaded->storeAs('uploads/OCR', $finalFileName, 'local');
// $fullPath = storage_path('app/private/' . $storedPath);
// $text = (new TesseractOCR($fullPath))->lang('eng')->run();
// $rawText = $text;
// preg_match_all('/\d+/', $rawText, $matches);
// $serialNumbers = $matches[0];
// $serialNumbers = array_slice($serialNumbers, 0, 4);
// //dd($serialNumbers);
// $processOrder = $get('gr_number');
// $itemId = $get('item_id');
// $plant = $get('plant_id');
// $item = Item::find($itemId);
// $plant = Plant::find($plant);
// $templatePath = storage_path('app/private/uploads/StickerTemplateOcr/multi.pdf');
// $outputPath = storage_path('app/private/uploads/StickerTemplateOcr/multi_filled.pdf');
// $storedPath = $uploaded->storeAs(
// 'uploads/GRNumber',
// $finalFileName,
// 'local'
// );
// $pdf = new Fpdi('P', 'mm', [90, 90]);
// $templateId = $pdf->setSourceFile($templatePath);
// $templatePage = $pdf->importPage(1);
// $pdf->AddPage();
// $pdf->useTemplate($templatePage, 0, 0, 90, 90);
// $pdf->SetFont('Helvetica', '', 10);
// $pdf->SetTextColor(0, 0, 0);
// $slots = [
// ['x' => 5.7, 'y' => 41.9, 'w' => 46.5, 'h' => 3.5], // 1st serial
// ['x' => 50, 'y' => 41.5, 'w' => 46.6, 'h' => 3.9], // 2nd serial
// ['x' => 5.7, 'y' => 60, 'w' => 46.5, 'h' => 3.5], // 3rd serial
// ['x' => 50, 'y' => 60, 'w' => 46.6, 'h' => 3.5], // 4rd serial
// ];
// $qrSlots = [
// ['x' => 17.3, 'y' => 29.2, 'size' => 11.4],
// ['x' => 61.5, 'y' => 29, 'size' => 11.5],
// ['x' => 17.7, 'y' => 46.7, 'size' => 11.4],
// ['x' => 61.7, 'y' => 46.7, 'size' => 11.4],
// ];
// foreach ($serialNumbers as $i => $serial) {
// if (!isset($slots[$i]) || !isset($qrSlots[$i])) continue;
// // Erase old QR completely (slightly larger)
// $pdf->SetFillColor(255, 255, 255);
// $pdf->Rect($qrSlots[$i]['x']-1, $qrSlots[$i]['y']-1, $qrSlots[$i]['size']+2, $qrSlots[$i]['size']+2, 'F');
// // Generate new QR code
// $qrPath = storage_path("app/private/uploads/QR/qr_$serial.png");
// $qrDir = storage_path('app/private/uploads/QR');
// if (!file_exists($qrDir)) mkdir($qrDir, 0777, true);
// QrCode::format('png')->size(100)->generate($serial, $qrPath);
// // Place QR code
// $pdf->Image($qrPath, $qrSlots[$i]['x'], $qrSlots[$i]['y'], $qrSlots[$i]['size'], $qrSlots[$i]['size']);
// // Erase old serial
// $pdf->SetFillColor(255, 255, 255);
// $pdf->Rect($slots[$i]['x'], $slots[$i]['y'], $slots[$i]['w'], $slots[$i]['h'], 'F');
// // Write new serial
// $pdf->SetXY($slots[$i]['x'], $slots[$i]['y']);
// $pdf->Cell($slots[$i]['w'], $slots[$i]['h'], $serial, 0, 0, 'L');
// }
// // Save the final PDF
// $pdf->Output('F', $outputPath);
// // Download
// return response()->download($outputPath);
// }
// }
// else
// {
// Notification::make()
// ->title('No file selected to upload')
// ->warning()
// ->send();
// return;
// }
// }),
Action::make('uploadNow1')
->label('Upload OCR')
->action(function ($get, callable $set) {
// $serialNumbers = [
// $get('serial_1'),
// $get('serial_2'),
// $get('serial_3'),
// $get('serial_4'),
// ];
// $hasSerial = collect($serialNumbers)->some(fn($s) => !empty($s));
$serialNumbersJson = $get('serialNumbers'); // input name matches hidden input
$serialNumbers = json_decode($serialNumbersJson, true) ?? [];
if (empty($serialNumbers)) {
Notification::make()
->title('Serial numbers cannot be empty!')
->danger()
->send();
return;
}
// Now you can proceed with your PDF logic
//$serialNumbers = array_slice($serialNumbers, 0, 4);
$serialNumbers = array_slice($serialNumbers, 0, 4);
//dd($serialNumbers);
$itemId = $get('item_id');
$plant = $get('plant_id');
$item = Item::find($itemId);
$plant = Plant::find($plant);
$templatePath = storage_path('app/private/uploads/StickerTemplateOcr/multi.pdf');
$outputPath = storage_path('app/private/uploads/StickerTemplateOcr/multi_filled.pdf');
// $storedPath = $uploaded->storeAs(
// 'uploads/GRNumber',
// $finalFileName,
// 'local'
// );
$pdf = new Fpdi('P', 'mm', [90, 90]);
$templateId = $pdf->setSourceFile($templatePath);
$templatePage = $pdf->importPage(1);
$pdf->AddPage();
$pdf->useTemplate($templatePage, 0, 0, 90, 90);
$pdf->SetFont('Helvetica', '', 10);
$pdf->SetTextColor(0, 0, 0);
$slots = [
['x' => 5.7, 'y' => 41.9, 'w' => 46.5, 'h' => 3.5], // 1st serial
['x' => 50, 'y' => 41.5, 'w' => 46.6, 'h' => 3.9], // 2nd serial
['x' => 5.7, 'y' => 60, 'w' => 46.5, 'h' => 3.5], // 3rd serial
['x' => 50, 'y' => 60, 'w' => 46.6, 'h' => 3.5], // 4rd serial
];
$qrSlots = [
['x' => 17.3, 'y' => 29.2, 'size' => 11.4],
['x' => 61.5, 'y' => 29, 'size' => 11.5],
['x' => 17.7, 'y' => 46.7, 'size' => 11.4],
['x' => 61.7, 'y' => 46.7, 'size' => 11.4],
];
foreach ($serialNumbers as $i => $serial) {
if (!isset($slots[$i]) || !isset($qrSlots[$i])) continue;
// Erase old QR completely (slightly larger)
$pdf->SetFillColor(255, 255, 255);
$pdf->Rect($qrSlots[$i]['x']-1, $qrSlots[$i]['y']-1, $qrSlots[$i]['size']+2, $qrSlots[$i]['size']+2, 'F');
// Generate new QR code
$qrPath = storage_path("app/private/uploads/QR/qr_$serial.png");
$qrDir = storage_path('app/private/uploads/QR');
if (!file_exists($qrDir)) mkdir($qrDir, 0777, true);
QrCode::format('png')->size(100)->generate($serial, $qrPath);
// Place QR code
$pdf->Image($qrPath, $qrSlots[$i]['x'], $qrSlots[$i]['y'], $qrSlots[$i]['size'], $qrSlots[$i]['size']);
// Erase old serial
$pdf->SetFillColor(255, 255, 255);
$pdf->Rect($slots[$i]['x'], $slots[$i]['y'], $slots[$i]['w'], $slots[$i]['h'], 'F');
// Write new serial
$pdf->SetXY($slots[$i]['x'], $slots[$i]['y']);
$pdf->Cell($slots[$i]['w'], $slots[$i]['h'], $serial, 0, 0, 'L');
}
// Save the final PDF
$pdf->Output('F', $outputPath);
// Download
return response()->download($outputPath);
}),
Action::make('downloadAttachment')
->label('Download PDF')
->action(function ($get) {
$equipmentNumber = $get('gr_number');
if (!$equipmentNumber) {
Notification::make()
->title('No GR Number entered')
->danger()
->send();
return;
}
$files = Storage::disk('local')->files('uploads/GRNumber');
$fileToDownload = null;
foreach ($files as $file) {
if (str_contains($file, $equipmentNumber)) {
$fileToDownload = $file;
break;
}
}
if (!$fileToDownload) {
Notification::make()
->title('PDF not found for this process order')
->danger()
->send();
return;
}
return response()->download(Storage::disk('local')->path($fileToDownload));
}),
]),
Field::make('camera_capture')
->view('fields.web-camera-capture'),
Hidden::make('created_by')
->label('Created By')
->default(Filament::auth()->user()?->name),
Hidden::make('updated_by')
->default(Filament::auth()->user()?->name),
])->columns(1),
]);
}
public static function canAccess(): bool
{
return Auth::check() && Auth::user()->can('create web capture page');
}
}