Add the Team3 POB form so TMs can record doctor and chemist orders and upload invoices.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
05b2438841
commit
f67aab1fdc
|
|
@ -63,6 +63,88 @@ class FormController extends Controller
|
||||||
return $formId;
|
return $formId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function pobFormId() {
|
||||||
|
return '1791391025-cf688862-93e7-43b5-bf4e-7a29b30e3830';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function pobPrices() {
|
||||||
|
return [
|
||||||
|
'asthalin_inhaler' => 129,
|
||||||
|
'asthalin_rotacap' => 55,
|
||||||
|
'aerocort_inhaler' => 260,
|
||||||
|
'aerocort_rotacap' => 109,
|
||||||
|
'aerocort_forte_rotacap' => 99,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function pobWholeNumber($value) {
|
||||||
|
if ($value === null || $value === '') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!preg_match('/^\d+$/', trim((string) $value))) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (int) $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function applyPobAmounts(array $post) {
|
||||||
|
if (($post['form_id'] ?? '') !== $this->pobFormId()) {
|
||||||
|
return $post;
|
||||||
|
}
|
||||||
|
$prices = $this->pobPrices();
|
||||||
|
$isUpload = !empty($post['id']);
|
||||||
|
if (!$isUpload) {
|
||||||
|
$date = (string) ($post['record_date'] ?? '');
|
||||||
|
$today = date('Y-m-d');
|
||||||
|
if ($date < '2026-09-01' || $date > $today) {
|
||||||
|
return ['__error' => 'Date must be from 1 Sep 2026 through today.'];
|
||||||
|
}
|
||||||
|
if (empty($post['contact_id']) || !in_array($post['contact_type'] ?? '', ['ebt_doctor', 'ebt_chemist'], true)) {
|
||||||
|
return ['__error' => 'Select a doctor or chemist.'];
|
||||||
|
}
|
||||||
|
if (!in_array($post['supply_status'] ?? '', ['Yes', 'No'], true)) {
|
||||||
|
return ['__error' => 'Select the supply status.'];
|
||||||
|
}
|
||||||
|
$totalUnits = 0;
|
||||||
|
$totalValue = 0;
|
||||||
|
foreach ($prices as $code => $price) {
|
||||||
|
$units = $this->pobWholeNumber($post[$code.'_units'] ?? 0);
|
||||||
|
if ($units === null) {
|
||||||
|
return ['__error' => 'POB units must be a whole number.'];
|
||||||
|
}
|
||||||
|
$post[$code.'_units'] = (string) $units;
|
||||||
|
$post[$code.'_value'] = (string) ($units * $price);
|
||||||
|
$totalUnits += $units;
|
||||||
|
$totalValue += $units * $price;
|
||||||
|
}
|
||||||
|
$post['total_pob_units'] = (string) $totalUnits;
|
||||||
|
$post['total_pob_value'] = (string) $totalValue;
|
||||||
|
$post['submission_status'] = 'Order Taken';
|
||||||
|
return $post;
|
||||||
|
}
|
||||||
|
$invoice = (string) ($post['upload_invoice'] ?? '');
|
||||||
|
$extension = strtolower(pathinfo((string) parse_url($invoice, PHP_URL_PATH), PATHINFO_EXTENSION));
|
||||||
|
if ($invoice === '' || !in_array($extension, ['jpg', 'jpeg', 'png', 'pdf'], true)) {
|
||||||
|
return ['__error' => 'Upload an invoice as a JPG, JPEG, PNG, or PDF file.'];
|
||||||
|
}
|
||||||
|
$totalUnits = 0;
|
||||||
|
$totalValue = 0;
|
||||||
|
foreach ($prices as $code => $price) {
|
||||||
|
$units = $this->pobWholeNumber($post['actual_'.$code.'_units'] ?? 0);
|
||||||
|
if ($units === null) {
|
||||||
|
return ['__error' => 'Actual POB units must be a whole number.'];
|
||||||
|
}
|
||||||
|
$post['actual_'.$code.'_units'] = (string) $units;
|
||||||
|
$post['actual_'.$code.'_value'] = (string) ($units * $price);
|
||||||
|
$totalUnits += $units;
|
||||||
|
$totalValue += $units * $price;
|
||||||
|
}
|
||||||
|
$post['total_actual_pob_units'] = (string) $totalUnits;
|
||||||
|
$post['total_actual_pob_value'] = (string) $totalValue;
|
||||||
|
$post['submission_status'] = 'Invoice Uploaded';
|
||||||
|
return $post;
|
||||||
|
}
|
||||||
|
|
||||||
protected function deliverform($formdata, $questions, $id = false) {
|
protected function deliverform($formdata, $questions, $id = false) {
|
||||||
$additional_info = $this->get_additional_info($formdata);
|
$additional_info = $this->get_additional_info($formdata);
|
||||||
// if($formdata->form_id == '1711609582-e93dba24-9c98-43e7-b97a-b22d64d9b9fc') {
|
// if($formdata->form_id == '1711609582-e93dba24-9c98-43e7-b97a-b22d64d9b9fc') {
|
||||||
|
|
@ -7659,6 +7741,10 @@ class FormController extends Controller
|
||||||
|
|
||||||
|
|
||||||
if(isset($formdata) && !empty($formdata) && $formdata->user_id != '') {
|
if(isset($formdata) && !empty($formdata) && $formdata->user_id != '') {
|
||||||
|
$post = $this->applyPobAmounts($post);
|
||||||
|
if (isset($post['__error'])) {
|
||||||
|
return response()->json(['status' => 'error', 'message' => $post['__error']]);
|
||||||
|
}
|
||||||
$post = $this->processformdata($formdata->form_id, $post, $formdata->user_id, $formdata->partition);
|
$post = $this->processformdata($formdata->form_id, $post, $formdata->user_id, $formdata->partition);
|
||||||
Log::debug(print_r($post, true));
|
Log::debug(print_r($post, true));
|
||||||
$finfo = LambdaRequest::postrequest('form', 'formentity/submitmultipleform', ['formdata' => $post, 'entity_id' => $post['form_id'], 'user_id' => $formdata->user_id, 'partition' => $formdata->partition ]);
|
$finfo = LambdaRequest::postrequest('form', 'formentity/submitmultipleform', ['formdata' => $post, 'entity_id' => $post['form_id'], 'user_id' => $formdata->user_id, 'partition' => $formdata->partition ]);
|
||||||
|
|
@ -8256,6 +8342,24 @@ class FormController extends Controller
|
||||||
return response()->json(['form' => $history->data->form, 'questions' => $history->data->questions, 'submissions' => $history->data->submissions, 'form_id' => $form_id]);
|
return response()->json(['form' => $history->data->form, 'questions' => $history->data->questions, 'submissions' => $history->data->submissions, 'form_id' => $form_id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function pobhistory(Request $request) {
|
||||||
|
$formdata = $request->session()->get('formdata');
|
||||||
|
$formId = $request->input('form_id', '');
|
||||||
|
$contactId = $request->input('contact_id', '');
|
||||||
|
if (!$formdata || $formId !== $this->pobFormId() || $contactId === '') {
|
||||||
|
return response()->json(['submissions' => []]);
|
||||||
|
}
|
||||||
|
$history = LambdaRequest::postrequest('form', 'formentity/getformhistory', [
|
||||||
|
'form_id' => $formId,
|
||||||
|
'user_id' => $formdata->user_id,
|
||||||
|
'partition' => $formdata->partition,
|
||||||
|
'limit' => 100,
|
||||||
|
'filters' => ['formdata.contact_id' => $contactId],
|
||||||
|
]);
|
||||||
|
$submissions = (isset($history->data) && isset($history->data->submissions)) ? $history->data->submissions : [];
|
||||||
|
return response()->json(['submissions' => $submissions]);
|
||||||
|
}
|
||||||
|
|
||||||
public function history(Request $request) {
|
public function history(Request $request) {
|
||||||
$formdata = $request->session()->get('formdata');
|
$formdata = $request->session()->get('formdata');
|
||||||
Log::debug(print_r($formdata, true));
|
Log::debug(print_r($formdata, true));
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,499 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
@include('layouts.shared/title-meta', ['title' => 'POB'])
|
||||||
|
@include('layouts.shared/head-css', ['mode' => $mode ?? '', 'demo' => $demo ?? ''])
|
||||||
|
<link href="{{ asset('assets/libs/sweetalert2/sweetalert2.min.css') }}" rel="stylesheet" type="text/css" />
|
||||||
|
<link href="{{ asset('assets/libs/select2/select2.min.css') }}" rel="stylesheet" type="text/css" />
|
||||||
|
<style>
|
||||||
|
.pob-card .form-control { font-size: 16px; }
|
||||||
|
.pob-orders { background: #f7f9fb; }
|
||||||
|
.pob-orders td { font-size: 13px; }
|
||||||
|
#pageloader {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 9999;
|
||||||
|
background: rgba(255, 255, 255, 0.8);
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="loading">
|
||||||
|
<div id="pageloader">Loading</div>
|
||||||
|
<div class="account-pages">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-8 col-lg-6 col-xl-5 p-0">
|
||||||
|
<div class="card bg-pattern pob-card quick-action-form-card">
|
||||||
|
<div class="card-body p-3">
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||||
|
<h4 class="page-title mb-0">POB</h4>
|
||||||
|
<button type="button" class="btn btn-link pt-1 d-none" id="pob-back">Back</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="tabs-wrapper">
|
||||||
|
<ul class="nav nav-tabs nav-bordered nav-justified" role="tablist">
|
||||||
|
<li class="nav-item" role="presentation">
|
||||||
|
<a href="#doctor-tab" data-bs-toggle="tab" class="nav-link active" role="tab">Doctors</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item" role="presentation">
|
||||||
|
<a href="#chemist-tab" data-bs-toggle="tab" class="nav-link" role="tab">Chemists</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div class="tab-content">
|
||||||
|
<div class="tab-pane active show" id="doctor-tab" role="tabpanel">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-sm table-hover mb-0" id="doctor-table">
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th>Action</th>
|
||||||
|
<th>Doctor Name</th>
|
||||||
|
<th>Speciality</th>
|
||||||
|
<th>MSL Code</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody></tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tab-pane" id="chemist-tab" role="tabpanel">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-sm table-hover mb-0" id="chemist-table">
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th>Action</th>
|
||||||
|
<th>Chemist Name</th>
|
||||||
|
<th>Speciality</th>
|
||||||
|
<th>MSL Code</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody></tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="report-panel" class="d-none">
|
||||||
|
<h5 class="mt-2">POB Details (Without Visit)</h5>
|
||||||
|
<form method="POST" action="/form/submit" id="report-form" enctype="multipart/form-data">
|
||||||
|
@csrf
|
||||||
|
<input type="hidden" name="form_id" value="{{ $form_id }}">
|
||||||
|
<input type="hidden" name="user_id" value="{{ $form->user_id ?? '' }}">
|
||||||
|
<input type="hidden" name="partition" value="{{ $form->partition ?? '' }}">
|
||||||
|
<input type="hidden" name="contact_name" id="field-contact_name" value="">
|
||||||
|
<input type="hidden" name="contact_type" id="field-contact_type" value="">
|
||||||
|
<input type="hidden" name="submission_status" value="Order Taken">
|
||||||
|
|
||||||
|
<div class="mb-2">
|
||||||
|
<label class="form-label" for="field-record_date">Date <span class="text-danger">*</span></label>
|
||||||
|
<input type="date" class="form-control" id="field-record_date" name="record_date" required min="2026-09-01" max="{{ date('Y-m-d') }}">
|
||||||
|
</div>
|
||||||
|
<div class="mb-2">
|
||||||
|
<label class="form-label" for="field-contact_id" id="contact-label">Select Doctor <span class="text-danger">*</span></label>
|
||||||
|
<select class="form-control" id="field-contact_id" name="contact_id" required></select>
|
||||||
|
</div>
|
||||||
|
<div class="mb-2">
|
||||||
|
<label class="form-label" for="field-speciality">Speciality</label>
|
||||||
|
<input type="text" class="form-control" id="field-speciality" name="speciality" readonly>
|
||||||
|
</div>
|
||||||
|
<div class="mb-2">
|
||||||
|
<label class="form-label" for="field-msl_code">MSL Code</label>
|
||||||
|
<input type="text" class="form-control" id="field-msl_code" name="msl_code" readonly>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-sm mb-2">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>SKU</th>
|
||||||
|
<th>POB Units</th>
|
||||||
|
<th>POB Value</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr data-price="129">
|
||||||
|
<td>Asthalin Inhaler</td>
|
||||||
|
<td><input type="text" inputmode="numeric" class="form-control pob-units" name="asthalin_inhaler_units" value="0"></td>
|
||||||
|
<td><input type="text" class="form-control pob-value" name="asthalin_inhaler_value" value="0" readonly></td>
|
||||||
|
</tr>
|
||||||
|
<tr data-price="55">
|
||||||
|
<td>Asthalin Rotacap</td>
|
||||||
|
<td><input type="text" inputmode="numeric" class="form-control pob-units" name="asthalin_rotacap_units" value="0"></td>
|
||||||
|
<td><input type="text" class="form-control pob-value" name="asthalin_rotacap_value" value="0" readonly></td>
|
||||||
|
</tr>
|
||||||
|
<tr data-price="260">
|
||||||
|
<td>Aerocort Inhaler</td>
|
||||||
|
<td><input type="text" inputmode="numeric" class="form-control pob-units" name="aerocort_inhaler_units" value="0"></td>
|
||||||
|
<td><input type="text" class="form-control pob-value" name="aerocort_inhaler_value" value="0" readonly></td>
|
||||||
|
</tr>
|
||||||
|
<tr data-price="109">
|
||||||
|
<td>Aerocort Rotacap</td>
|
||||||
|
<td><input type="text" inputmode="numeric" class="form-control pob-units" name="aerocort_rotacap_units" value="0"></td>
|
||||||
|
<td><input type="text" class="form-control pob-value" name="aerocort_rotacap_value" value="0" readonly></td>
|
||||||
|
</tr>
|
||||||
|
<tr data-price="99">
|
||||||
|
<td>Aerocort Forte Rotacap</td>
|
||||||
|
<td><input type="text" inputmode="numeric" class="form-control pob-units" name="aerocort_forte_rotacap_units" value="0"></td>
|
||||||
|
<td><input type="text" class="form-control pob-value" name="aerocort_forte_rotacap_value" value="0" readonly></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Total</td>
|
||||||
|
<td><input type="text" class="form-control" id="field-total_pob_units" name="total_pob_units" value="0" readonly></td>
|
||||||
|
<td><input type="text" class="form-control" id="field-total_pob_value" name="total_pob_value" value="0" readonly></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="mb-2">
|
||||||
|
<label class="form-label" for="field-supply_status">Supply Status <span class="text-danger">*</span></label>
|
||||||
|
<select class="form-control" id="field-supply_status" name="supply_status" required>
|
||||||
|
<option value="">-- Select --</option>
|
||||||
|
<option value="Yes">Yes</option>
|
||||||
|
<option value="No">No</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="d-grid mt-3">
|
||||||
|
<button class="btn btn-primary" type="submit">Submit</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="upload-panel" class="d-none">
|
||||||
|
<h5 class="mt-2">Upload Invoice</h5>
|
||||||
|
<form method="POST" action="/form/submit" id="upload-form" enctype="multipart/form-data">
|
||||||
|
@csrf
|
||||||
|
<input type="hidden" name="form_id" value="{{ $form_id }}">
|
||||||
|
<input type="hidden" name="user_id" value="{{ $form->user_id ?? '' }}">
|
||||||
|
<input type="hidden" name="partition" value="{{ $form->partition ?? '' }}">
|
||||||
|
<input type="hidden" name="id" id="field-upload-id" value="">
|
||||||
|
<input type="hidden" name="submission_status" value="Invoice Uploaded">
|
||||||
|
<div class="mb-2">
|
||||||
|
<label class="form-label" for="field-upload_invoice">Upload Invoice <span class="text-danger">*</span></label>
|
||||||
|
<input type="file" class="form-control" id="field-upload_invoice" name="upload_invoice" accept=".jpg,.jpeg,.png,.pdf,image/jpeg,image/png,application/pdf" required>
|
||||||
|
</div>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-sm mb-2">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>SKU</th>
|
||||||
|
<th>Actual POB Units</th>
|
||||||
|
<th>Actual POB Value</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr data-price="129">
|
||||||
|
<td>Actual Asthalin Inhaler</td>
|
||||||
|
<td><input type="text" inputmode="numeric" class="form-control actual-units" name="actual_asthalin_inhaler_units" value="0"></td>
|
||||||
|
<td><input type="text" class="form-control actual-value" name="actual_asthalin_inhaler_value" value="0" readonly></td>
|
||||||
|
</tr>
|
||||||
|
<tr data-price="55">
|
||||||
|
<td>Actual Asthalin Rotacap</td>
|
||||||
|
<td><input type="text" inputmode="numeric" class="form-control actual-units" name="actual_asthalin_rotacap_units" value="0"></td>
|
||||||
|
<td><input type="text" class="form-control actual-value" name="actual_asthalin_rotacap_value" value="0" readonly></td>
|
||||||
|
</tr>
|
||||||
|
<tr data-price="260">
|
||||||
|
<td>Actual Aerocort Inhaler</td>
|
||||||
|
<td><input type="text" inputmode="numeric" class="form-control actual-units" name="actual_aerocort_inhaler_units" value="0"></td>
|
||||||
|
<td><input type="text" class="form-control actual-value" name="actual_aerocort_inhaler_value" value="0" readonly></td>
|
||||||
|
</tr>
|
||||||
|
<tr data-price="109">
|
||||||
|
<td>Actual Aerocort Rotacap</td>
|
||||||
|
<td><input type="text" inputmode="numeric" class="form-control actual-units" name="actual_aerocort_rotacap_units" value="0"></td>
|
||||||
|
<td><input type="text" class="form-control actual-value" name="actual_aerocort_rotacap_value" value="0" readonly></td>
|
||||||
|
</tr>
|
||||||
|
<tr data-price="99">
|
||||||
|
<td>Actual Aerocort Forte Rotacap</td>
|
||||||
|
<td><input type="text" inputmode="numeric" class="form-control actual-units" name="actual_aerocort_forte_rotacap_units" value="0"></td>
|
||||||
|
<td><input type="text" class="form-control actual-value" name="actual_aerocort_forte_rotacap_value" value="0" readonly></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Total</td>
|
||||||
|
<td><input type="text" class="form-control" id="field-total_actual_pob_units" name="total_actual_pob_units" value="0" readonly></td>
|
||||||
|
<td><input type="text" class="form-control" id="field-total_actual_pob_value" name="total_actual_pob_value" value="0" readonly></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="d-grid mt-3">
|
||||||
|
<button class="btn btn-primary" type="submit">Submit</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@include('layouts.shared/footer-script')
|
||||||
|
<script src="{{ asset('assets/libs/sweetalert2/sweetalert2.min.js') }}"></script>
|
||||||
|
<script src="{{ asset('assets/libs/select2/select2.min.js') }}"></script>
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
var hierarchy = @json($form->hierarchy_id ?? ($form->hierarchy ?? ''));
|
||||||
|
var partition = @json($form->partition ?? '');
|
||||||
|
var formId = @json($form_id);
|
||||||
|
var contacts = { ebt_doctor: [], ebt_chemist: [] };
|
||||||
|
var openContactId = '';
|
||||||
|
|
||||||
|
function esc(value) {
|
||||||
|
return String(value == null ? '' : value)
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/"/g, '"');
|
||||||
|
}
|
||||||
|
|
||||||
|
function whole(value) {
|
||||||
|
var text = String(value == null ? '' : value).trim();
|
||||||
|
if (text === '') return 0;
|
||||||
|
return /^\d+$/.test(text) ? parseInt(text, 10) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function recalc(unitClass, valueClass, totalUnits, totalValue) {
|
||||||
|
var units = 0;
|
||||||
|
var value = 0;
|
||||||
|
var valid = true;
|
||||||
|
$(unitClass).each(function () {
|
||||||
|
var row = $(this).closest('tr');
|
||||||
|
var count = whole($(this).val());
|
||||||
|
if (count === null) {
|
||||||
|
valid = false;
|
||||||
|
row.find(valueClass).val('');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var amount = count * parseInt(row.data('price'), 10);
|
||||||
|
row.find(valueClass).val(amount);
|
||||||
|
units += count;
|
||||||
|
value += amount;
|
||||||
|
});
|
||||||
|
$(totalUnits).val(valid ? units : '');
|
||||||
|
$(totalValue).val(valid ? value : '');
|
||||||
|
return valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
function fillContact(select) {
|
||||||
|
var option = select.options[select.selectedIndex];
|
||||||
|
$('#field-speciality').val(option ? (option.getAttribute('data-speciality') || '') : '');
|
||||||
|
$('#field-msl_code').val(option ? (option.getAttribute('data-code') || '') : '');
|
||||||
|
$('#field-contact_name').val(option ? (option.getAttribute('data-name') || '') : '');
|
||||||
|
$('#field-contact_type').val(option ? (option.getAttribute('data-type') || '') : '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function initContactSearch(type) {
|
||||||
|
var select = $('#field-contact_id');
|
||||||
|
if (select.data('select2')) {
|
||||||
|
select.select2('destroy');
|
||||||
|
}
|
||||||
|
select.empty().append('<option value=""></option>');
|
||||||
|
(contacts[type] || []).forEach(function (item) {
|
||||||
|
var contact = item.contact || {};
|
||||||
|
var option = document.createElement('option');
|
||||||
|
option.value = item.value;
|
||||||
|
option.textContent = item.display || contact.name || '';
|
||||||
|
option.setAttribute('data-name', item.display || contact.name || '');
|
||||||
|
option.setAttribute('data-speciality', contact.speciality || '');
|
||||||
|
option.setAttribute('data-code', contact.msl_code || '');
|
||||||
|
option.setAttribute('data-type', type);
|
||||||
|
select.append(option);
|
||||||
|
});
|
||||||
|
select.select2({
|
||||||
|
width: '100%',
|
||||||
|
dropdownParent: $('.quick-action-form-card'),
|
||||||
|
placeholder: '-- Select --',
|
||||||
|
allowClear: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function showList() {
|
||||||
|
$('#report-panel, #upload-panel').addClass('d-none');
|
||||||
|
$('#tabs-wrapper').removeClass('d-none');
|
||||||
|
$('#pob-back').addClass('d-none');
|
||||||
|
}
|
||||||
|
|
||||||
|
function showReport(type, contactId) {
|
||||||
|
$('#tabs-wrapper, #upload-panel').addClass('d-none');
|
||||||
|
$('#report-panel').removeClass('d-none');
|
||||||
|
$('#pob-back').removeClass('d-none');
|
||||||
|
$('#contact-label').html((type === 'ebt_chemist' ? 'Select Chemist' : 'Select Doctor') + ' <span class="text-danger">*</span>');
|
||||||
|
$('#report-form')[0].reset();
|
||||||
|
$('#field-contact_type').val(type);
|
||||||
|
initContactSearch(type);
|
||||||
|
if (contactId) {
|
||||||
|
$('#field-contact_id').val(contactId).trigger('change');
|
||||||
|
}
|
||||||
|
openContactId = contactId || '';
|
||||||
|
recalc('.pob-units', '.pob-value', '#field-total_pob_units', '#field-total_pob_value');
|
||||||
|
}
|
||||||
|
|
||||||
|
function showUpload(submission) {
|
||||||
|
var data = submission.formdata || {};
|
||||||
|
$('#tabs-wrapper, #report-panel').addClass('d-none');
|
||||||
|
$('#upload-panel').removeClass('d-none');
|
||||||
|
$('#pob-back').removeClass('d-none');
|
||||||
|
$('#upload-form')[0].reset();
|
||||||
|
$('#field-upload-id').val(submission.id);
|
||||||
|
var map = {
|
||||||
|
actual_asthalin_inhaler_units: 'asthalin_inhaler_units',
|
||||||
|
actual_asthalin_rotacap_units: 'asthalin_rotacap_units',
|
||||||
|
actual_aerocort_inhaler_units: 'aerocort_inhaler_units',
|
||||||
|
actual_aerocort_rotacap_units: 'aerocort_rotacap_units',
|
||||||
|
actual_aerocort_forte_rotacap_units: 'aerocort_forte_rotacap_units'
|
||||||
|
};
|
||||||
|
Object.keys(map).forEach(function (actual) {
|
||||||
|
$('#upload-form [name="' + actual + '"]').val(data[map[actual]] || 0);
|
||||||
|
});
|
||||||
|
recalc('.actual-units', '.actual-value', '#field-total_actual_pob_units', '#field-total_actual_pob_value');
|
||||||
|
openContactId = data.contact_id || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function canUpload(data) {
|
||||||
|
if (!data || data.supply_status !== 'Yes') return false;
|
||||||
|
return data.submission_status === 'Order Taken' || data.submission_status === 'Rejected';
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadOrders(row) {
|
||||||
|
var contactId = row.getAttribute('data-contact');
|
||||||
|
var holder = row.nextElementSibling;
|
||||||
|
if (holder && holder.classList.contains('pob-child') && holder.getAttribute('data-open') === 'yes') {
|
||||||
|
holder.remove();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (holder && holder.classList.contains('pob-child')) {
|
||||||
|
holder.remove();
|
||||||
|
}
|
||||||
|
var child = document.createElement('tr');
|
||||||
|
child.className = 'pob-child';
|
||||||
|
child.setAttribute('data-open', 'yes');
|
||||||
|
child.innerHTML = '<td colspan="4">Loading...</td>';
|
||||||
|
row.after(child);
|
||||||
|
$.getJSON('/form/pobhistory', { form_id: formId, contact_id: contactId }, function (data) {
|
||||||
|
var submissions = (data && data.submissions) || [];
|
||||||
|
child.innerHTML = '<td colspan="4"><div class="row fw-bold"><div class="col-3">Date</div><div class="col-3">Status</div><div class="col-3">Total Value</div><div class="col-3">Actual Total</div></div>'
|
||||||
|
+ submissions.map(function (submission) {
|
||||||
|
var info = submission.formdata || {};
|
||||||
|
var button = canUpload(info)
|
||||||
|
? '<button type="button" class="btn btn-warning btn-xs upload-invoice mt-1" data-submission="' + esc(JSON.stringify(submission)) + '">Upload Invoice</button>'
|
||||||
|
: '';
|
||||||
|
return '<div class="row mt-1"><div class="col-3">' + esc(info.record_date || '') + '</div><div class="col-3">' + esc(info.submission_status || '') + '</div><div class="col-3">' + esc(info.total_pob_value || '') + '</div><div class="col-3">' + esc(info.total_actual_pob_value || '') + button + '</div></div>';
|
||||||
|
}).join('')
|
||||||
|
+ (submissions.length ? '' : '<div class="text-muted mt-1">No orders yet.</div>')
|
||||||
|
+ '</td>';
|
||||||
|
}).fail(function () {
|
||||||
|
child.innerHTML = '<td colspan="4" class="text-danger">Could not load orders.</td>';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderTable(tableId, type) {
|
||||||
|
var body = document.querySelector('#' + tableId + ' tbody');
|
||||||
|
var rows = contacts[type] || [];
|
||||||
|
body.innerHTML = '';
|
||||||
|
if (!rows.length) {
|
||||||
|
body.innerHTML = '<tr><td colspan="4" class="text-muted">No ' + (type === 'ebt_doctor' ? 'doctors' : 'chemists') + ' yet.</td></tr>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rows.forEach(function (item) {
|
||||||
|
var contact = item.contact || {};
|
||||||
|
var tr = document.createElement('tr');
|
||||||
|
tr.setAttribute('data-contact', item.value);
|
||||||
|
tr.innerHTML = '<td><button type="button" class="btn btn-info btn-xs report-btn">Report</button></td>'
|
||||||
|
+ '<td class="pob-toggle"><i class="mdi mdi-arrow-down-drop-circle"></i> ' + esc(item.display || contact.name || '') + '</td>'
|
||||||
|
+ '<td>' + esc(contact.speciality || '') + '</td>'
|
||||||
|
+ '<td>' + esc(contact.msl_code || '') + '</td>';
|
||||||
|
tr.querySelector('.report-btn').addEventListener('click', function () {
|
||||||
|
showReport(type, item.value);
|
||||||
|
});
|
||||||
|
tr.querySelector('.pob-toggle').addEventListener('click', function () {
|
||||||
|
loadOrders(tr);
|
||||||
|
});
|
||||||
|
body.appendChild(tr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function refreshOpen() {
|
||||||
|
if (!openContactId) return;
|
||||||
|
var row = document.querySelector('tr[data-contact="' + openContactId.replace(/"/g, '\\"') + '"]');
|
||||||
|
if (!row) return;
|
||||||
|
var child = row.nextElementSibling;
|
||||||
|
if (child && child.classList.contains('pob-child')) {
|
||||||
|
child.remove();
|
||||||
|
}
|
||||||
|
loadOrders(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
function submitForm(form, done) {
|
||||||
|
if (form.id === 'report-form' && !recalc('.pob-units', '.pob-value', '#field-total_pob_units', '#field-total_pob_value')) {
|
||||||
|
Swal.fire({ icon: 'error', title: 'Check the units', text: 'POB units must be a whole number. 0 is allowed.' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (form.id === 'upload-form' && !recalc('.actual-units', '.actual-value', '#field-total_actual_pob_units', '#field-total_actual_pob_value')) {
|
||||||
|
Swal.fire({ icon: 'error', title: 'Check the units', text: 'Actual POB units must be a whole number. 0 is allowed.' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (form.id === 'report-form') {
|
||||||
|
openContactId = $('#field-contact_id').val() || openContactId;
|
||||||
|
}
|
||||||
|
$('#pageloader').css('display', 'flex').hide().fadeIn();
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
url: '/form/ajaxsubmit',
|
||||||
|
data: new FormData(form),
|
||||||
|
processData: false,
|
||||||
|
contentType: false,
|
||||||
|
success: function (data) {
|
||||||
|
$('#pageloader').fadeOut();
|
||||||
|
if (data.status === 'success') {
|
||||||
|
Swal.fire({ title: 'Great!', text: 'Your data is successfully submitted!', icon: 'success' });
|
||||||
|
showList();
|
||||||
|
refreshOpen();
|
||||||
|
if (done) done();
|
||||||
|
} else {
|
||||||
|
Swal.fire({ icon: 'error', title: 'Data not submitted', text: data.message || 'Please try again.' });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function () {
|
||||||
|
$('#pageloader').fadeOut();
|
||||||
|
Swal.fire({ icon: 'error', title: 'Data not submitted', text: 'Please try again.' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#field-contact_id').on('change', function () {
|
||||||
|
fillContact(this);
|
||||||
|
});
|
||||||
|
$('#report-form').on('input', '.pob-units', function () {
|
||||||
|
recalc('.pob-units', '.pob-value', '#field-total_pob_units', '#field-total_pob_value');
|
||||||
|
});
|
||||||
|
$('#upload-form').on('input', '.actual-units', function () {
|
||||||
|
recalc('.actual-units', '.actual-value', '#field-total_actual_pob_units', '#field-total_actual_pob_value');
|
||||||
|
});
|
||||||
|
$('#report-form').on('submit', function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
submitForm(this);
|
||||||
|
});
|
||||||
|
$('#upload-form').on('submit', function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
submitForm(this);
|
||||||
|
});
|
||||||
|
$('#pob-back').on('click', showList);
|
||||||
|
$(document).on('click', '.upload-invoice', function () {
|
||||||
|
var raw = $(this).attr('data-submission');
|
||||||
|
if (!raw) return;
|
||||||
|
showUpload(JSON.parse(raw));
|
||||||
|
});
|
||||||
|
|
||||||
|
$.getJSON('/form/getdoctorlist', { partition: partition, hierarchy: hierarchy }, function (data) {
|
||||||
|
(Array.isArray(data) ? data : []).forEach(function (item) {
|
||||||
|
var type = String((item.contact && item.contact.type) || '').toLowerCase();
|
||||||
|
if (contacts[type]) contacts[type].push(item);
|
||||||
|
});
|
||||||
|
renderTable('doctor-table', 'ebt_doctor');
|
||||||
|
renderTable('chemist-table', 'ebt_chemist');
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -236,6 +236,7 @@ foreach ($modules as $mod => $class) {
|
||||||
Route::any('/getidrivedoctowisedownload', [FormController::class, 'getidrivedoctowisedownload']);
|
Route::any('/getidrivedoctowisedownload', [FormController::class, 'getidrivedoctowisedownload']);
|
||||||
|
|
||||||
Route::get('/form/nebmitrahistory', [FormController::class, 'nebmitrahistory']);
|
Route::get('/form/nebmitrahistory', [FormController::class, 'nebmitrahistory']);
|
||||||
|
Route::get('/form/pobhistory', [FormController::class, 'pobhistory']);
|
||||||
Route::post('/form/ajaxdoctortagging', [FormController::class, 'ajaxdoctortagging']);
|
Route::post('/form/ajaxdoctortagging', [FormController::class, 'ajaxdoctortagging']);
|
||||||
|
|
||||||
Route::get('/form/pulmocarecoachingtool', [FormController::class, 'pulmocarecoachingtool']);
|
Route::get('/form/pulmocarecoachingtool', [FormController::class, 'pulmocarecoachingtool']);
|
||||||
|
|
|
||||||
|
|
@ -303,6 +303,7 @@ Route::get('/milestones/exportTeamReport', [MilestoneController::class, 'exportT
|
||||||
Route::any('/getidrivedoctowisedownload', [FormController::class, 'getidrivedoctowisedownload']);
|
Route::any('/getidrivedoctowisedownload', [FormController::class, 'getidrivedoctowisedownload']);
|
||||||
|
|
||||||
Route::get('/form/nebmitrahistory', [FormController::class, 'nebmitrahistory']);
|
Route::get('/form/nebmitrahistory', [FormController::class, 'nebmitrahistory']);
|
||||||
|
Route::get('/form/pobhistory', [FormController::class, 'pobhistory']);
|
||||||
Route::post('/form/ajaxdoctortagging', [FormController::class, 'ajaxdoctortagging']);
|
Route::post('/form/ajaxdoctortagging', [FormController::class, 'ajaxdoctortagging']);
|
||||||
|
|
||||||
Route::get('/form/pulmocarecoachingtool', [FormController::class, 'pulmocarecoachingtool']);
|
Route::get('/form/pulmocarecoachingtool', [FormController::class, 'pulmocarecoachingtool']);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue