Track each employee's Incept nebulizer allocation and reject requests that exceed their balance or the MSL cap of 10.
Specific Folder FTP Upload / ftp-deploy (push) Successful in 1m47s
Details
Specific Folder FTP Upload / ftp-deploy (push) Successful in 1m47s
Details
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
dbc3e9a32d
commit
ce802447e1
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace App\Exceptions;
|
||||
|
||||
class InceptNebLimitException extends \RuntimeException
|
||||
{
|
||||
}
|
||||
|
|
@ -18,6 +18,8 @@ use Maatwebsite\Excel\Facades\Excel;
|
|||
use App\Exports\InvoicesExport;
|
||||
use Auth;
|
||||
use App\Mail\ReportExcel;
|
||||
use App\Exceptions\InceptNebLimitException;
|
||||
use App\Services\InceptNebAllocation;
|
||||
use Mail;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Aws\Ses\SesClient;
|
||||
|
|
@ -5742,14 +5744,43 @@ class FormController extends Controller
|
|||
Log::debug(print_r($formdata, true));
|
||||
$request->session()->put('formdata', $formdata);
|
||||
if(isset($formdata) && !empty($formdata) && $formdata->user_id != '') {
|
||||
$inceptUsageId = null;
|
||||
$inceptAllocation = null;
|
||||
if (($formdata->form_id ?? '') === InceptNebAllocation::FORM_ID) {
|
||||
$inceptAllocation = new InceptNebAllocation();
|
||||
try {
|
||||
$inceptUsageId = $inceptAllocation->reserveFromSubmission($post, $formdata);
|
||||
} catch (InceptNebLimitException $e) {
|
||||
return response()->json(['status' => 'failure', 'message' => $e->getMessage()]);
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('Incept nebulizer allocation check failed: ' . $e->getMessage());
|
||||
return response()->json(['status' => 'failure', 'message' => 'Unable to check nebulizer allocation. Please try again.']);
|
||||
}
|
||||
}
|
||||
try {
|
||||
$post = $this->processformdata($formdata->form_id, $post, $formdata->user_id, $formdata->partition);
|
||||
Log::debug(print_r($post, true));
|
||||
$finfo = LambdaRequest::postrequest('form', 'formentity/submitform', ['formdata' => $post, 'entity_id' => $formdata->form_id, 'user_id' => $formdata->user_id, 'partition' => $formdata->partition ]);
|
||||
} catch (\Throwable $e) {
|
||||
if ($inceptAllocation && $inceptUsageId) {
|
||||
$inceptAllocation->release($inceptUsageId);
|
||||
Log::error('Form submit failed after nebulizer reservation: ' . $e->getMessage());
|
||||
return response()->json(['status' => 'failure', 'message' => 'Something went wrong, please try again after some time!']);
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
|
||||
Log::debug(print_r($finfo, true));
|
||||
if($finfo->status == 'success') {
|
||||
if ($inceptAllocation && $inceptUsageId) {
|
||||
$submissionId = $finfo->data->submission->id ?? '';
|
||||
$inceptAllocation->attachSubmission($inceptUsageId, $submissionId);
|
||||
}
|
||||
return response()->json(['status' => 'success']);
|
||||
} else {
|
||||
if ($inceptAllocation && $inceptUsageId) {
|
||||
$inceptAllocation->release($inceptUsageId);
|
||||
}
|
||||
if($finfo->statusCode == 401) {
|
||||
return response()->json(['status' => 'failure', 'message' => $finfo->data ]);
|
||||
}
|
||||
|
|
@ -8296,12 +8327,51 @@ class FormController extends Controller
|
|||
return [];
|
||||
break;
|
||||
|
||||
case InceptNebAllocation::FORM_ID:
|
||||
$service = new InceptNebAllocation();
|
||||
$empId = '';
|
||||
if (isset($formdata->user_info)) {
|
||||
foreach (['employee_code', 'emp_employee_code', 'emp_id'] as $key) {
|
||||
if (!empty($formdata->user_info->{$key})) {
|
||||
$empId = $formdata->user_info->{$key};
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($empId === '' && !empty($formdata->employee_code)) {
|
||||
$empId = $formdata->employee_code;
|
||||
}
|
||||
if ($empId === '' && !empty($formdata->user_id)) {
|
||||
$empId = $service->resolveEmpIdFromUser($formdata->user_id);
|
||||
}
|
||||
return ['incept_neb' => $service->summaryForEmployee($empId)];
|
||||
break;
|
||||
|
||||
default:
|
||||
return [];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function inceptNebBalance(Request $request)
|
||||
{
|
||||
$service = new InceptNebAllocation();
|
||||
$empId = trim((string) $request->input('emp_id', ''));
|
||||
if ($empId === '') {
|
||||
$empId = $service->resolveEmpIdFromUser($request->input('user_id'));
|
||||
}
|
||||
if ($empId === '') {
|
||||
$formdata = $request->session()->get('formdata');
|
||||
$empId = $service->resolveEmpId([], $formdata);
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'status' => 'success',
|
||||
'allocation' => $service->summaryForEmployee($empId),
|
||||
'msl' => $service->mslUsage($request->input('msl_code', '')),
|
||||
]);
|
||||
}
|
||||
|
||||
public function getformfielddata(Request $request) {
|
||||
$post = $request->except('_token');
|
||||
$history = LambdaRequest::postrequest('form', 'formentity/getformhistory', ['form_id' => $post['form_id'], 'user_id' => $post['user_id'], 'partition' => $post['partition'] ]);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,269 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Exceptions\InceptNebLimitException;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class InceptNebAllocation
|
||||
{
|
||||
public const FORM_ID = '1786346682-7ed41cf4-f562-4eb7-8d53-efedd0133f41';
|
||||
public const MSL_LIMIT = 10;
|
||||
|
||||
public const TYPES = [
|
||||
'robust' => ['label' => 'Robust', 'column' => 'robust_qty'],
|
||||
'mini' => ['label' => 'Mini', 'column' => 'mini_qty'],
|
||||
'control_d' => ['label' => 'Control D', 'column' => 'control_d_qty'],
|
||||
];
|
||||
|
||||
public function summaryForEmployee($empId)
|
||||
{
|
||||
$empId = $this->normalizeEmpId($empId);
|
||||
$allocation = $empId === '' ? null : DB::table('incept_neb_allocations')->where('emp_id', $empId)->first();
|
||||
$usedByType = [];
|
||||
if ($empId !== '') {
|
||||
$rows = DB::table('incept_neb_usage')
|
||||
->select('nebulizer_type', DB::raw('SUM(qty) as used_qty'))
|
||||
->where('emp_id', $empId)
|
||||
->groupBy('nebulizer_type')
|
||||
->get();
|
||||
foreach ($rows as $row) {
|
||||
$usedByType[$row->nebulizer_type] = (int) $row->used_qty;
|
||||
}
|
||||
}
|
||||
|
||||
$types = [];
|
||||
foreach (self::TYPES as $key => $meta) {
|
||||
$allocated = $allocation ? (int) ($allocation->{$meta['column']} ?? 0) : 0;
|
||||
$used = (int) ($usedByType[$key] ?? 0);
|
||||
$types[$key] = [
|
||||
'label' => $meta['label'],
|
||||
'allocated' => $allocated,
|
||||
'used' => $used,
|
||||
'balance' => max(0, $allocated - $used),
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'emp_id' => $allocation->emp_id ?? $empId,
|
||||
'emp_name' => $allocation->emp_name ?? '',
|
||||
'team' => $allocation->team ?? '',
|
||||
'designation' => $allocation->designation ?? '',
|
||||
'has_allocation' => (bool) $allocation,
|
||||
'types' => $types,
|
||||
];
|
||||
}
|
||||
|
||||
public function mslUsage($mslCode)
|
||||
{
|
||||
$mslCode = trim((string) $mslCode);
|
||||
$used = 0;
|
||||
if ($mslCode !== '') {
|
||||
$used = (int) DB::table('incept_neb_usage')->where('msl_code', $mslCode)->sum('qty');
|
||||
}
|
||||
|
||||
return [
|
||||
'msl_code' => $mslCode,
|
||||
'used' => $used,
|
||||
'limit' => self::MSL_LIMIT,
|
||||
'remaining' => max(0, self::MSL_LIMIT - $used),
|
||||
];
|
||||
}
|
||||
|
||||
public function resolveEmpIdFromUser($userId)
|
||||
{
|
||||
$userId = trim((string) $userId);
|
||||
if ($userId === '' || !Schema::hasTable('users')) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$query = DB::table('users');
|
||||
$user = (clone $query)->where('user_id', $userId)->first();
|
||||
if (!$user) {
|
||||
$user = DB::table('users')->where('id', $userId)->first();
|
||||
}
|
||||
if (!$user) {
|
||||
return '';
|
||||
}
|
||||
|
||||
foreach (['emp_employee_code', 'employee_code', 'emp_id'] as $column) {
|
||||
if (isset($user->{$column}) && trim((string) $user->{$column}) !== '') {
|
||||
return $this->normalizeEmpId($user->{$column});
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function resolveEmpId($post, $formdata = null)
|
||||
{
|
||||
$candidates = [];
|
||||
if (is_array($post)) {
|
||||
foreach (['incept_emp_id', 'emp_id', 'employee_code'] as $key) {
|
||||
if (!empty($post[$key])) {
|
||||
$candidates[] = $post[$key];
|
||||
}
|
||||
}
|
||||
if (!empty($post['user_id'])) {
|
||||
$candidates[] = $this->resolveEmpIdFromUser($post['user_id']);
|
||||
}
|
||||
}
|
||||
if (is_object($formdata) && isset($formdata->user_info)) {
|
||||
foreach (['employee_code', 'emp_employee_code', 'emp_id'] as $key) {
|
||||
if (!empty($formdata->user_info->{$key})) {
|
||||
$candidates[] = $formdata->user_info->{$key};
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_object($formdata) && !empty($formdata->employee_code)) {
|
||||
$candidates[] = $formdata->employee_code;
|
||||
}
|
||||
if (is_object($formdata) && !empty($formdata->user_id)) {
|
||||
$candidates[] = $this->resolveEmpIdFromUser($formdata->user_id);
|
||||
}
|
||||
|
||||
foreach ($candidates as $candidate) {
|
||||
$empId = $this->normalizeEmpId($candidate);
|
||||
if ($empId !== '') {
|
||||
return $empId;
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function reserveFromSubmission(array $post, $formdata)
|
||||
{
|
||||
$type = $this->typeKey($post['type_of_nebulizer'] ?? '');
|
||||
$qty = (int) ($post['no_of_nebulizer'] ?? 0);
|
||||
$mslCode = trim((string) ($post['msl_code'] ?? ''));
|
||||
$empId = $this->resolveEmpId($post, $formdata);
|
||||
|
||||
if ($type === null) {
|
||||
throw new InceptNebLimitException('Select a nebulizer type.');
|
||||
}
|
||||
if ($qty < 1) {
|
||||
throw new InceptNebLimitException('Enter the number of nebulizers.');
|
||||
}
|
||||
if ($mslCode === '') {
|
||||
throw new InceptNebLimitException('MSL code is required.');
|
||||
}
|
||||
if ($empId === '') {
|
||||
throw new InceptNebLimitException('Employee allocation could not be matched.');
|
||||
}
|
||||
|
||||
$locks = [];
|
||||
try {
|
||||
$locks[] = $this->acquireLock('incept_neb_emp_' . $empId);
|
||||
$locks[] = $this->acquireLock('incept_neb_msl_' . $mslCode);
|
||||
|
||||
return DB::transaction(function () use ($empId, $type, $qty, $mslCode) {
|
||||
$allocation = DB::table('incept_neb_allocations')->where('emp_id', $empId)->lockForUpdate()->first();
|
||||
if (!$allocation) {
|
||||
throw new InceptNebLimitException('No nebulizer allocation is set for employee ' . $empId . '.');
|
||||
}
|
||||
|
||||
$column = self::TYPES[$type]['column'];
|
||||
$allocated = (int) ($allocation->{$column} ?? 0);
|
||||
$used = (int) DB::table('incept_neb_usage')
|
||||
->where('emp_id', $empId)
|
||||
->where('nebulizer_type', $type)
|
||||
->lockForUpdate()
|
||||
->sum('qty');
|
||||
$balance = $allocated - $used;
|
||||
if ($qty > $balance) {
|
||||
throw new InceptNebLimitException(
|
||||
'Only ' . max(0, $balance) . ' ' . self::TYPES[$type]['label'] . ' nebulizer(s) are left in your allocation.'
|
||||
);
|
||||
}
|
||||
|
||||
$mslUsed = (int) DB::table('incept_neb_usage')->where('msl_code', $mslCode)->lockForUpdate()->sum('qty');
|
||||
if (($mslUsed + $qty) > self::MSL_LIMIT) {
|
||||
$remaining = max(0, self::MSL_LIMIT - $mslUsed);
|
||||
throw new InceptNebLimitException(
|
||||
'MSL ' . $mslCode . ' can take ' . $remaining . ' more nebulizer(s). The overall limit is ' . self::MSL_LIMIT . '.'
|
||||
);
|
||||
}
|
||||
|
||||
return DB::table('incept_neb_usage')->insertGetId([
|
||||
'emp_id' => $empId,
|
||||
'msl_code' => $mslCode,
|
||||
'nebulizer_type' => $type,
|
||||
'qty' => $qty,
|
||||
'submission_id' => null,
|
||||
'created_at' => date('Y-m-d H:i:s'),
|
||||
'updated_at' => date('Y-m-d H:i:s'),
|
||||
]);
|
||||
});
|
||||
} finally {
|
||||
foreach (array_reverse($locks) as $lock) {
|
||||
DB::select('SELECT RELEASE_LOCK(?)', [$lock]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function attachSubmission($usageId, $submissionId)
|
||||
{
|
||||
if (!$usageId) {
|
||||
return;
|
||||
}
|
||||
DB::table('incept_neb_usage')->where('id', $usageId)->update([
|
||||
'submission_id' => (string) $submissionId,
|
||||
'updated_at' => date('Y-m-d H:i:s'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function release($usageId)
|
||||
{
|
||||
if (!$usageId) {
|
||||
return;
|
||||
}
|
||||
DB::table('incept_neb_usage')->where('id', $usageId)->delete();
|
||||
}
|
||||
|
||||
public function typeKey($label)
|
||||
{
|
||||
$value = strtolower(trim((string) $label));
|
||||
$value = str_replace([' ', '-'], '_', $value);
|
||||
if ($value === 'robust') {
|
||||
return 'robust';
|
||||
}
|
||||
if ($value === 'mini') {
|
||||
return 'mini';
|
||||
}
|
||||
if ($value === 'control_d' || $value === 'controld') {
|
||||
return 'control_d';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function normalizeEmpId($value)
|
||||
{
|
||||
if (is_int($value) || is_float($value)) {
|
||||
if ((float) $value === floor((float) $value)) {
|
||||
return (string) (int) $value;
|
||||
}
|
||||
}
|
||||
$value = trim((string) $value);
|
||||
$value = str_replace("\xc2\xa0", ' ', $value);
|
||||
$value = trim($value);
|
||||
if ($value !== '' && is_numeric($value) && strpos($value, '.') !== false) {
|
||||
$value = (string) (int) $value;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
private function acquireLock($name)
|
||||
{
|
||||
$name = substr($name, 0, 64);
|
||||
$row = DB::selectOne('SELECT GET_LOCK(?, 10) AS locked', [$name]);
|
||||
if (!$row || (int) $row->locked !== 1) {
|
||||
throw new InceptNebLimitException('Nebulizer allocation is busy. Please try again.');
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateInceptNebTables extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
if (!Schema::hasTable('incept_neb_allocations')) {
|
||||
Schema::create('incept_neb_allocations', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->string('emp_id', 64)->unique();
|
||||
$table->string('emp_name')->default('');
|
||||
$table->string('team')->default('');
|
||||
$table->string('designation')->default('');
|
||||
$table->unsignedInteger('robust_qty')->default(0);
|
||||
$table->unsignedInteger('mini_qty')->default(0);
|
||||
$table->unsignedInteger('control_d_qty')->default(0);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
if (!Schema::hasTable('incept_neb_usage')) {
|
||||
Schema::create('incept_neb_usage', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->string('emp_id', 64)->index();
|
||||
$table->string('msl_code', 64)->index();
|
||||
$table->string('nebulizer_type', 32)->index();
|
||||
$table->unsignedInteger('qty');
|
||||
$table->string('submission_id', 128)->nullable()->index();
|
||||
$table->timestamps();
|
||||
$table->index(['emp_id', 'nebulizer_type'], 'incept_neb_usage_emp_type');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('incept_neb_usage');
|
||||
Schema::dropIfExists('incept_neb_allocations');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Services\InceptNebAllocation;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
|
||||
class InceptNebAllocationSeeder extends Seeder
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$path = '/Volumes/Storage/Downloads/Nebulizers Allocation Data.xlsx';
|
||||
if (!is_file($path)) {
|
||||
throw new \RuntimeException('Allocation workbook not found at ' . $path);
|
||||
}
|
||||
|
||||
$sheet = IOFactory::load($path)->getActiveSheet();
|
||||
$rows = $sheet->toArray(null, true, true, true);
|
||||
$service = new InceptNebAllocation();
|
||||
$now = date('Y-m-d H:i:s');
|
||||
$count = 0;
|
||||
|
||||
foreach ($rows as $index => $row) {
|
||||
if ($index === 1) {
|
||||
continue;
|
||||
}
|
||||
$empId = $service->normalizeEmpId($row['A'] ?? '');
|
||||
if ($empId === '' || strcasecmp($empId, 'EMP ID') === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DB::table('incept_neb_allocations')->updateOrInsert(
|
||||
['emp_id' => $empId],
|
||||
[
|
||||
'emp_name' => $this->clean($row['B'] ?? ''),
|
||||
'team' => $this->clean($row['C'] ?? ''),
|
||||
'designation' => $this->clean($row['D'] ?? ''),
|
||||
'robust_qty' => max(0, (int) ($row['E'] ?? 0)),
|
||||
'mini_qty' => max(0, (int) ($row['F'] ?? 0)),
|
||||
'control_d_qty' => max(0, (int) ($row['G'] ?? 0)),
|
||||
'updated_at' => $now,
|
||||
'created_at' => $now,
|
||||
]
|
||||
);
|
||||
$count++;
|
||||
}
|
||||
|
||||
if (isset($this->command)) {
|
||||
$this->command->info('Imported ' . $count . ' nebulizer allocations.');
|
||||
}
|
||||
}
|
||||
|
||||
private function clean($value)
|
||||
{
|
||||
$value = str_replace("\xc2\xa0", ' ', (string) $value);
|
||||
$value = preg_replace('/\s+/', ' ', $value);
|
||||
|
||||
return trim($value);
|
||||
}
|
||||
}
|
||||
|
|
@ -39,9 +39,64 @@
|
|||
<h6>Submitted By: {{$form->user_info->name}}</h6>
|
||||
</div>
|
||||
@endif
|
||||
@php
|
||||
$incept = (isset($additional) && isset($additional['incept_neb'])) ? $additional['incept_neb'] : null;
|
||||
$inceptTypes = $incept['types'] ?? [];
|
||||
@endphp
|
||||
<style>
|
||||
.incept-neb-table { font-size: 13px; margin-bottom: 4px; background: #fff; color: #212529; }
|
||||
.incept-neb-table th, .incept-neb-table td { text-align: center; vertical-align: middle; padding: 6px 8px; }
|
||||
.incept-neb-table thead th, .incept-neb-table tbody th { background: #0b3a4a; color: #fff; font-weight: 600; }
|
||||
.incept-neb-table tbody td { color: #212529; background: #fff; }
|
||||
</style>
|
||||
<div class="col-12 mb-2" id="incept-neb-panel"
|
||||
data-robust="{{ $inceptTypes['robust']['balance'] ?? 0 }}"
|
||||
data-mini="{{ $inceptTypes['mini']['balance'] ?? 0 }}"
|
||||
data-control-d="{{ $inceptTypes['control_d']['balance'] ?? 0 }}"
|
||||
data-msl-remaining="10">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-bordered mb-1 incept-neb-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
@foreach(['robust', 'mini', 'control_d'] as $typeKey)
|
||||
<th>{{ $inceptTypes[$typeKey]['label'] ?? $typeKey }}</th>
|
||||
@endforeach
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Allocation</th>
|
||||
@foreach(['robust', 'mini', 'control_d'] as $typeKey)
|
||||
<td class="incept-allocated" data-type="{{ $typeKey }}">{{ $inceptTypes[$typeKey]['allocated'] ?? 0 }}</td>
|
||||
@endforeach
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Submitted</th>
|
||||
@foreach(['robust', 'mini', 'control_d'] as $typeKey)
|
||||
<td class="incept-used" data-type="{{ $typeKey }}">{{ $inceptTypes[$typeKey]['used'] ?? 0 }}</td>
|
||||
@endforeach
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Balance</th>
|
||||
@foreach(['robust', 'mini', 'control_d'] as $typeKey)
|
||||
<td class="incept-balance" data-type="{{ $typeKey }}">{{ $inceptTypes[$typeKey]['balance'] ?? 0 }}</td>
|
||||
@endforeach
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@if(empty($incept['has_allocation']))
|
||||
<p class="text-danger small mb-1" id="incept-missing">No nebulizer allocation is set for this employee.</p>
|
||||
@else
|
||||
<p class="text-danger small mb-1" id="incept-missing" style="display:none;"></p>
|
||||
@endif
|
||||
<p class="small mb-0" id="incept-msl-note">Select a doctor to see how many nebulizers are left for that MSL code (limit 10).</p>
|
||||
</div>
|
||||
<form method="POST" action="/form/submit" id="report-form" enctype="multipart/form-data">
|
||||
<input type="hidden" name="form_id" value="{{$form_id}}">
|
||||
<input type="hidden" name="user_id" value="{{$form->user_id}}">
|
||||
<input type="hidden" name="incept_emp_id" id="incept-emp-input" value="{{ $incept['emp_id'] ?? '' }}">
|
||||
|
||||
@csrf
|
||||
@if($id)
|
||||
|
|
@ -53,7 +108,7 @@
|
|||
<select class="form-control" id="field-user_id" name="user_id" required>
|
||||
<option value=""> -- Select -- </option>
|
||||
@foreach($form->users as $option)
|
||||
<option value="{{$option->value}}" hierarchy="{{$option->hierarchy_id}}" {{isset($question->value) && $question->value == $option->value ? 'selected':''}}>{{$option->display}}</option>
|
||||
<option value="{{$option->value}}" hierarchy="{{$option->hierarchy_id}}" employee_code="{{ $option->employee_code ?? ($option->emp_employee_code ?? '') }}" {{isset($question->value) && $question->value == $option->value ? 'selected':''}}>{{$option->display}}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<input type="hidden" id="field-hierarchy_id" name="hierarchy_id" value="">
|
||||
|
|
@ -227,6 +282,7 @@
|
|||
|
||||
$('#field-contact_id').change(function() {
|
||||
$('#field-msl_code').val($('option:selected', this).attr('msl_code'))
|
||||
refreshInceptMsl();
|
||||
})
|
||||
|
||||
/* $('#field-msl_code,#field-speciality').attr('readonly',true); */
|
||||
|
|
@ -268,14 +324,89 @@
|
|||
});
|
||||
|
||||
|
||||
function inceptTypeKey(label) {
|
||||
var value = (label || '').toLowerCase().replace(/[\s-]+/g, '_');
|
||||
if (value === 'robust') return 'robust';
|
||||
if (value === 'mini') return 'mini';
|
||||
if (value === 'control_d' || value === 'controld') return 'control_d';
|
||||
return '';
|
||||
}
|
||||
|
||||
function paintInceptAllocation(allocation) {
|
||||
if (!allocation) return;
|
||||
$('#incept-emp-input').val(allocation.emp_id || '');
|
||||
['robust', 'mini', 'control_d'].forEach(function(key) {
|
||||
var row = (allocation.types && allocation.types[key]) ? allocation.types[key] : {allocated: 0, used: 0, balance: 0};
|
||||
$('.incept-allocated[data-type="' + key + '"]').text(row.allocated);
|
||||
$('.incept-used[data-type="' + key + '"]').text(row.used);
|
||||
$('.incept-balance[data-type="' + key + '"]').text(row.balance);
|
||||
$('#incept-neb-panel').attr('data-' + key.replace('_', '-'), row.balance);
|
||||
});
|
||||
if (!allocation.has_allocation) {
|
||||
$('#incept-missing').text('No nebulizer allocation is set for this employee.').show();
|
||||
} else {
|
||||
$('#incept-missing').hide();
|
||||
}
|
||||
}
|
||||
|
||||
function paintInceptMsl(msl) {
|
||||
if (!msl || !msl.msl_code) {
|
||||
$('#incept-msl-note').text('Select a doctor to see how many nebulizers are left for that MSL code (limit 10).');
|
||||
$('#incept-neb-panel').attr('data-msl-remaining', 10);
|
||||
return;
|
||||
}
|
||||
$('#incept-neb-panel').attr('data-msl-remaining', msl.remaining);
|
||||
$('#incept-msl-note').text('MSL ' + msl.msl_code + ' has ' + msl.used + ' of ' + msl.limit + ' nebulizers used. ' + msl.remaining + ' remaining.');
|
||||
}
|
||||
|
||||
function refreshInceptBalance(mslCode) {
|
||||
var userId = $('#field-user_id').length ? $('#field-user_id').val() : $('input[name="user_id"]').val();
|
||||
$.get('/form/inceptnebbalance', {
|
||||
user_id: userId || '',
|
||||
emp_id: $('#incept-emp-input').val() || '',
|
||||
msl_code: mslCode || $('#field-msl_code').val() || ''
|
||||
}, function(data) {
|
||||
if (data && data.allocation) paintInceptAllocation(data.allocation);
|
||||
if (data && data.msl) paintInceptMsl(data.msl);
|
||||
});
|
||||
}
|
||||
|
||||
function refreshInceptMsl() {
|
||||
refreshInceptBalance($('#field-msl_code').val() || '');
|
||||
}
|
||||
|
||||
$('#field-msl_code').on('change', refreshInceptMsl);
|
||||
|
||||
$('#field-user_id').on('change', function() {
|
||||
var code = $('option:selected', this).attr('employee_code') || '';
|
||||
$('#incept-emp-input').val(code);
|
||||
refreshInceptBalance('');
|
||||
});
|
||||
|
||||
$('#report-form').on('submit', function(event){
|
||||
event.preventDefault();
|
||||
const formData = new FormData($('#report-form')[0]);
|
||||
$('#report-form').append('<input type="hidden" name="'+ $('#field-type_of_nebulizer').val().toLowerCase() +'" value="'+$('#field-no_of_nebulizer').val()+'" />');
|
||||
// Log form data to console
|
||||
for (let [key, value] of formData.entries()) {
|
||||
console.log(key, value);
|
||||
var typeKey = inceptTypeKey($('#field-type_of_nebulizer').val());
|
||||
var qty = parseInt($('#field-no_of_nebulizer').val(), 10) || 0;
|
||||
var balance = parseInt($('#incept-neb-panel').attr('data-' + typeKey.replace('_', '-')), 10);
|
||||
var mslRemaining = parseInt($('#incept-neb-panel').attr('data-msl-remaining'), 10);
|
||||
if (!typeKey) {
|
||||
Swal.fire({ icon: 'error', title: 'Data not submitted', text: 'Select a nebulizer type.' });
|
||||
return;
|
||||
}
|
||||
if (qty < 1) {
|
||||
Swal.fire({ icon: 'error', title: 'Data not submitted', text: 'Enter the number of nebulizers.' });
|
||||
return;
|
||||
}
|
||||
if (isNaN(balance) || qty > balance) {
|
||||
Swal.fire({ icon: 'error', title: 'Data not submitted', text: 'Only ' + (isNaN(balance) ? 0 : balance) + ' nebulizer(s) of this type are left in your allocation.' });
|
||||
return;
|
||||
}
|
||||
if (!isNaN(mslRemaining) && qty > mslRemaining) {
|
||||
Swal.fire({ icon: 'error', title: 'Data not submitted', text: 'This MSL code can take only ' + mslRemaining + ' more nebulizer(s). The overall limit is 10.' });
|
||||
return;
|
||||
}
|
||||
$('#report-form input.incept-type-qty').remove();
|
||||
$('#report-form').append('<input type="hidden" class="incept-type-qty" name="'+ $('#field-type_of_nebulizer').val().toLowerCase() +'" value="'+$('#field-no_of_nebulizer').val()+'" />');
|
||||
$("#pageloader").fadeIn();
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
|
|
@ -291,15 +422,16 @@
|
|||
text: 'Your data is successfully submitted!',
|
||||
icon: 'success'
|
||||
}).then(() => {
|
||||
location.reload(); // 🔥 page refresh here
|
||||
location.reload();
|
||||
});
|
||||
$('#report-form').trigger("reset");
|
||||
} else {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Data not submitted',
|
||||
text: 'Something went wrong, please try again after some time!'
|
||||
text: (data && data.message) ? data.message : 'Something went wrong, please try again after some time!'
|
||||
})
|
||||
refreshInceptBalance($('#field-msl_code').val() || '');
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -318,6 +318,7 @@ Route::get('/form/downloadpersonalization', [FormController::class, 'downloadper
|
|||
Route::get('/form/downloadpersonalizationzip/{files}', [FormController::class, 'downloadpersonalizationzip']);
|
||||
Route::middleware('throttle:10,1')->get('/form/downloaddata', [FormController::class, 'downloaddata']);
|
||||
|
||||
Route::get('/form/inceptnebbalance', [FormController::class, 'inceptNebBalance']);
|
||||
Route::get('/form/nebmitraverification', [FormController::class, 'nebmitraverification']);
|
||||
|
||||
Route::get('/form/respidoctorsearch', [FormController::class, 'respidoctorsearch']);
|
||||
|
|
|
|||
Loading…
Reference in New Issue