2445 lines
101 KiB
PHP
2445 lines
101 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Exports\CustomInvoiceExport;
|
|
use Illuminate\Http\Request;
|
|
use App\Http\Requests\LambdaRequest;
|
|
use App\Mail\Neblogistic;
|
|
use App\Mail\NeblogisticRejection;
|
|
use App\Mail\NeblogisticSupervisor;
|
|
use Carbon\Carbon;
|
|
use DB;
|
|
use League\Csv\Reader;
|
|
use Log;
|
|
use Maatwebsite\Excel\Facades\Excel;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Illuminate\Support\Facades\Mail;
|
|
use App\Mail\NeblogisticStatusUpdate;
|
|
use Response;
|
|
use App\Services\NeblogisticAuditService;
|
|
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
|
use PhpOffice\PhpSpreadsheet\IOFactory;
|
|
use PhpOffice\PhpSpreadsheet\Shared\Date as ExcelDate;
|
|
|
|
class NeblogisticreportController extends Controller
|
|
{
|
|
public function __construct()
|
|
{
|
|
$this->_service = 'form';
|
|
$this->_module = 'formentity';
|
|
$this->_viewname = 'neblogisticreport';
|
|
$this->_title = 'Neblogistic Report';
|
|
$this->_base_url = '/neblogisticreport';
|
|
}
|
|
|
|
public function list(Request $request)
|
|
{
|
|
// $response = LambdaRequest::signedrequest('get', $this->_service, $this->_module . '/get_all');
|
|
$depot = DB::table('neblogistic')->distinct()->pluck('depot_name')->filter()->values();
|
|
$status = DB::table('neblogistic')->where('status', '!=', 'Partially Saved')->distinct()->pluck('status')->filter()->values();
|
|
|
|
// echo '<pre>'; print_r($response->data->items); exit;
|
|
$fields = $this->get_list_fields();
|
|
return view('neblogisticreport.list')->with([
|
|
'title' => $this->_title,
|
|
'fields' => $fields,
|
|
'base_url' => $this->_base_url,
|
|
// 'items' => $response->data->items,
|
|
'buttons' => $this->get_list_buttons(),
|
|
'depot' => $depot,
|
|
'status' => $status,
|
|
]);
|
|
}
|
|
|
|
protected function get_list_buttons()
|
|
{
|
|
$roles = json_decode(auth()->user()->roles ?? '[]', true);
|
|
$buttons = [
|
|
// ['title' => 'Add New', 'link' => $this->_base_url . '/addnew'],
|
|
['title' => 'Export', 'link' => $this->_base_url . '/export'],
|
|
['title' => 'Import', 'link' => $this->_base_url . '/import'],
|
|
];
|
|
// Only add 'Export Old' if user is not 'depotmanager' or 'superdepotmanager'
|
|
if (
|
|
!in_array('1733912682-7c353bf8-c309-49b3-93e7-depotmanager', $roles) &&
|
|
!in_array('1733912682-7c353bf8-c309-49b3-93e7-superdepotmanager', $roles)
|
|
) {
|
|
$buttons[] = ['title' => 'Export Old', 'link' => $this->_base_url . '/exportold'];
|
|
}
|
|
return $buttons;
|
|
}
|
|
|
|
protected function get_list_fields()
|
|
{
|
|
return [
|
|
'actions' => ['title' => 'Actions', 'buttons' => ['report' => ['icon' => 'chart-bar', 'querystring' => 'id={ID}']]],
|
|
'name' => ['title' => 'Name', 'type' => 'text'],
|
|
'type' => ['title' => 'Type', 'type' => 'text'],
|
|
'validity_start' => ['title' => 'Validity start', 'type' => 'date'],
|
|
'validity_end' => ['title' => 'Validity end', 'type' => 'date'],
|
|
'agg_type' => ['title' => 'Aggregation type', 'type' => 'text'],
|
|
];
|
|
}
|
|
|
|
public function ajaxlist(Request $request)
|
|
{
|
|
$searchValue = $request->input('search.value');
|
|
$stateFilter = $request->input('state');
|
|
$statusFilter = $request->input('status');
|
|
$fromDate = $request->input('from_date');
|
|
$toDate = $request->input('to_date');
|
|
$draw = intval($request->input('draw'));
|
|
$start = intval($request->input('start'));
|
|
$length = intval($request->input('length'));
|
|
$yesterday = now()->subDay()->format('Y-m-d');
|
|
$user = Auth::user();
|
|
|
|
$query = DB::table('neblogistic')->select('id', 'depot_name', 'emp_id', 'doctor_name', 'msl_code', 'emp_name', 'team', 'created_at', 'status')->where('status', '!=', 'Partially Saved');
|
|
$totalRecords = $query->count();
|
|
|
|
// If the user has the 'depotmanager' role, filter depot_name and status
|
|
if (in_array('1733912682-7c353bf8-c309-49b3-93e7-depotmanager', json_decode($user->roles ?? '[]', true))) {
|
|
$nameParts = explode(' ', $user->name);
|
|
$firstName = $nameParts[0] ?? '';
|
|
$query->where('depot_name', $firstName);
|
|
if (!empty($statusFilter)) {
|
|
$query->where('status', $statusFilter);
|
|
}else{
|
|
$query->where('status', 'Approved');
|
|
}
|
|
} elseif (in_array('1733912682-7c353bf8-c309-49b3-93e7-superdepotmanager', json_decode($user->roles ?? '[]', true))) {
|
|
$nameParts = explode(' ', $user->name);
|
|
$firstName = $nameParts[0] ?? '';
|
|
if (!empty($statusFilter)) {
|
|
$query->where('status', $statusFilter);
|
|
}else{
|
|
$query->where('status', 'Approved');
|
|
}
|
|
|
|
if (!empty($stateFilter)) {
|
|
$query->where('depot_name', $stateFilter);
|
|
}
|
|
} else {
|
|
if (!empty($stateFilter)) {
|
|
$query->where('depot_name', $stateFilter);
|
|
}
|
|
if (!empty($statusFilter)) {
|
|
$query->where('status', $statusFilter);
|
|
}
|
|
}
|
|
|
|
|
|
if (!empty($fromDate) && !empty($toDate)) {
|
|
$from = Carbon::parse($fromDate)->startOfDay();
|
|
$to = Carbon::parse($toDate)->endOfDay();
|
|
$query->whereBetween('created_at', [$from, $to]);
|
|
}else{
|
|
$query->whereBetween('created_at', [$yesterday . ' 00:00:00', $yesterday . ' 23:59:59']);
|
|
}
|
|
|
|
if (!empty($searchValue)) {
|
|
$query->where(function ($q) use ($searchValue) {
|
|
$q->where('emp_id', 'like', '%' . $searchValue . '%')
|
|
->orWhere('id', 'like', '%' . $searchValue . '%')
|
|
->orWhere('depot_name', 'like', '%' . $searchValue . '%')
|
|
->orWhere('emp_name', 'like', '%' . $searchValue . '%')
|
|
->orWhere('team', 'like', '%' . $searchValue . '%')
|
|
->orWhere('status', 'like', '%' . $searchValue . '%');
|
|
});
|
|
}
|
|
|
|
$filteredRecords = $query->count();
|
|
|
|
$data = $query->offset($start)->limit($length)->orderBy('id', 'DESC')->get();
|
|
|
|
return response()->json([
|
|
'draw' => $draw,
|
|
'recordsTotal' => $totalRecords,
|
|
'recordsFiltered' => $filteredRecords,
|
|
'data' => $data,
|
|
// 'yesturday' => $yesterday
|
|
]);
|
|
}
|
|
|
|
public function viewreportbyid(Request $request)
|
|
{
|
|
$params = $request->input();
|
|
$data = DB::table('neblogistic')
|
|
->where('id', $params['id'])
|
|
->first();
|
|
|
|
$docs_with_samemsl = DB::table('neblogistic')
|
|
->where('msl_code', $data->msl_code)
|
|
->where('id', '!=', $data->id)
|
|
->get();
|
|
|
|
// echo '<pre>';
|
|
// print_r($docs_with_samemsl);
|
|
// exit;
|
|
|
|
// $user = Auth::user();
|
|
// $post = ['partition' => 'rapport-' . $user->domain, 'form_id' => '1750914801-153443b9-94d0-4dcb-b3f3-4fa11588a0a9', 'id' => $params['id']];
|
|
// $history = LambdaRequest::signedrequest('get', 'form', 'formentity/getsubmissiondetails', ['form_id' => $post['form_id'], 'partition' => $post['partition'], 'id' => $post['id']]);
|
|
// echo '<pre>'; print_r($history); exit;
|
|
// echo '<pre>'; print_r($history->data->submission); exit;
|
|
if ($params['requesttype'] == 'view') {
|
|
// echo '<pre>'; print_r($history->data->submission); exit;
|
|
|
|
return view($this->_viewname . '.view')->with([
|
|
'title' => $this->_title,
|
|
// 'fields' => $fields,
|
|
// 'base_url' => $this->_base_url,
|
|
'item' => $data,
|
|
'doctors' => $docs_with_samemsl,
|
|
'buttons' => $this->get_list_buttons(),
|
|
]);
|
|
} else {
|
|
return view($this->_viewname . '.edit')->with([
|
|
'title' => $this->_title,
|
|
// 'fields' => $fields,
|
|
// 'base_url' => $this->_base_url,
|
|
'item' => $data,
|
|
'doctors' => $docs_with_samemsl,
|
|
'buttons' => $this->get_list_buttons(),
|
|
]);
|
|
}
|
|
}
|
|
|
|
public function viewnextreportbyid(Request $request)
|
|
{
|
|
$params = $request->input();
|
|
|
|
$stateFilter = $params['state'] ?? null;
|
|
$statusFilter = $params['status'] ?? null;
|
|
$fromDate = $params['from_date'] ?? null;
|
|
$toDate = $params['to_date'] ?? null;
|
|
$yesterday = now()->subDay()->format('Y-m-d');
|
|
|
|
$query = DB::table('neblogistic')
|
|
->where('id', '>', $params['id'])
|
|
->where('status', '!=', 'Partially Saved');
|
|
|
|
if (!empty($stateFilter)) {
|
|
$query->where('depot_name', $stateFilter);
|
|
}
|
|
|
|
if (!empty($statusFilter)) {
|
|
$query->where('status', $statusFilter);
|
|
}
|
|
|
|
if (!empty($fromDate) && !empty($toDate)) {
|
|
$from = Carbon::parse($fromDate)->startOfDay();
|
|
$to = Carbon::parse($toDate)->endOfDay();
|
|
$query->whereBetween('created_at', [$from, $to]);
|
|
}else{
|
|
$query->whereBetween('created_at', [$yesterday . ' 00:00:00', $yesterday . ' 23:59:59']);
|
|
}
|
|
|
|
$query->orderBy('id', 'ASC');
|
|
$query->limit(1);
|
|
$data = $query->first();
|
|
|
|
if(!$data){
|
|
return redirect()->back()->with('error', 'No further entries available.');
|
|
}
|
|
|
|
// if ($params['requesttype'] == 'view') {
|
|
// return view($this->_viewname . '.view')->with([
|
|
// 'title' => $this->_title,
|
|
// 'item' => $data,
|
|
// 'buttons' => $this->get_list_buttons(),
|
|
// ]);
|
|
// } else {
|
|
// return view($this->_viewname . '.edit')->with([
|
|
// 'title' => $this->_title,
|
|
// 'item' => $data,
|
|
// 'buttons' => $this->get_list_buttons(),
|
|
// ]);
|
|
// }
|
|
|
|
|
|
if ($params['requesttype'] == 'view') {
|
|
$redirectUrl = url('/neblogisticreport/viewreportbyid') . '?' . http_build_query([
|
|
'id' => $data->id,
|
|
'requesttype' => 'view',
|
|
'state' => $params['state'] ?? '',
|
|
'from_date' => $params['from_date'] ?? '',
|
|
'to_date' => $params['to_date'] ?? '',
|
|
'status' => $params['status'] ?? '',
|
|
]);
|
|
} else {
|
|
$redirectUrl = url('/neblogisticreport/viewreportbyid') . '?' . http_build_query([
|
|
'id' => $data->id,
|
|
'requesttype' => 'edit',
|
|
'state' => $params['state'] ?? '',
|
|
'from_date' => $params['from_date'] ?? '',
|
|
'to_date' => $params['to_date'] ?? '',
|
|
'status' => $params['status'] ?? '',
|
|
]);
|
|
}
|
|
|
|
return redirect($redirectUrl);
|
|
|
|
}
|
|
|
|
public function viewprevreportbyid(Request $request)
|
|
{
|
|
$params = $request->input();
|
|
|
|
$stateFilter = $params['state'] ?? null;
|
|
$statusFilter = $params['status'] ?? null;
|
|
$fromDate = $params['from_date'] ?? null;
|
|
$toDate = $params['to_date'] ?? null;
|
|
$yesterday = now()->subDay()->format('Y-m-d');
|
|
|
|
$query = DB::table('neblogistic')
|
|
->where('id', '<', $params['id'])
|
|
->where('status', '!=', 'Partially Saved');
|
|
|
|
if (!empty($stateFilter)) {
|
|
$query->where('depot_name', $stateFilter);
|
|
}
|
|
|
|
if (!empty($statusFilter)) {
|
|
$query->where('status', $statusFilter);
|
|
}
|
|
|
|
if (!empty($fromDate) && !empty($toDate)) {
|
|
$from = Carbon::parse($fromDate)->startOfDay();
|
|
$to = Carbon::parse($toDate)->endOfDay();
|
|
$query->whereBetween('created_at', [$from, $to]);
|
|
}else{
|
|
$query->whereBetween('created_at', [$yesterday . ' 00:00:00', $yesterday . ' 23:59:59']);
|
|
}
|
|
|
|
$query->orderBy('id', 'DESC');
|
|
$query->limit(1);
|
|
$data = $query->first();
|
|
|
|
if(!$data){
|
|
return redirect()->back()->with('error', 'No further entries available.');
|
|
}
|
|
|
|
if ($params['requesttype'] == 'view') {
|
|
$redirectUrl = url('/neblogisticreport/viewreportbyid') . '?' . http_build_query([
|
|
'id' => $data->id,
|
|
'requesttype' => 'view',
|
|
'state' => $params['state'] ?? '',
|
|
'from_date' => $params['from_date'] ?? '',
|
|
'to_date' => $params['to_date'] ?? '',
|
|
'status' => $params['status'] ?? '',
|
|
]);
|
|
} else {
|
|
$redirectUrl = url('/neblogisticreport/viewreportbyid') . '?' . http_build_query([
|
|
'id' => $data->id,
|
|
'requesttype' => 'edit',
|
|
'state' => $params['state'] ?? '',
|
|
'from_date' => $params['from_date'] ?? '',
|
|
'to_date' => $params['to_date'] ?? '',
|
|
'status' => $params['status'] ?? '',
|
|
]);
|
|
}
|
|
|
|
return redirect($redirectUrl);
|
|
}
|
|
|
|
public function posteditreport(Request $request)
|
|
{
|
|
$params = $request->all();
|
|
$datatosave = [];
|
|
// return print_r($params);
|
|
if (isset($params['status'])) {
|
|
$datatosave['status'] = $params['status'];
|
|
|
|
if ($params['status'] == 'Approved') {
|
|
$datatosave['approval_reason'] = isset($params['approve_reason']) ? $params['approve_reason'] : '';
|
|
$datatosave['approved_at'] = date("Y-m-d H:i:s", strtotime("now"));
|
|
} elseif ($params['status'] == 'L1 Approved') {
|
|
$datatosave['approval_reason'] = isset($params['approve_reason']) ? $params['approve_reason'] : '';
|
|
$datatosave['l1_approved_at'] = date("Y-m-d H:i:s", strtotime("now"));
|
|
} elseif ($params['status'] == 'L2 Approved') {
|
|
$datatosave['approval_reason'] = isset($params['approve_reason']) ? $params['approve_reason'] : '';
|
|
$datatosave['l2_approved_at'] = date("Y-m-d H:i:s", strtotime("now"));
|
|
} elseif ($params['status'] == 'L3 Approved') {
|
|
$datatosave['approval_reason'] = isset($params['approve_reason']) ? $params['approve_reason'] : '';
|
|
$datatosave['l3_approved_at'] = date("Y-m-d H:i:s", strtotime("now"));
|
|
}
|
|
if($params['status'] == 'Rejected') {
|
|
$datatosave['rejected_at'] = date("Y-m-d H:i:s", strtotime("now"));
|
|
$datatosave['rejected_reason'] = $params['rejected_reason'];
|
|
}
|
|
if($params['status'] == 'Dispatched') {
|
|
$datatosave['dispatch_at'] = date("Y-m-d H:i:s", strtotime("now"));
|
|
// Add dispatched details to $datatosave when status is Dispatched
|
|
$datatosave['order_no'] = $params['order_no'] ?? null;
|
|
$datatosave['invoice_no'] = $params['invoice_no'] ?? null;
|
|
$datatosave['courier_name'] = $params['courier_name'] ?? null;
|
|
$datatosave['lr_no'] = $params['lr_no'] ?? null;
|
|
// Format lr_date to Y-m-d if provided
|
|
if (!empty($params['lr_date'])) {
|
|
$datatosave['lr_date'] = date("Y-m-d H:i:s", strtotime($params['lr_date']));
|
|
} else {
|
|
$datatosave['lr_date'] = null;
|
|
}
|
|
|
|
}
|
|
} else {
|
|
$datatosave = [
|
|
//'record_id' => '',
|
|
// 'request_type' => $post[''],
|
|
'emp_id' => $params['emp_id'],
|
|
'emp_name' => $params['employee_name'],
|
|
'emp_phone' => $params['employee_phone'],
|
|
'emp_email' => $params['employee_email'],
|
|
'abm_name' => $params['abm_name'],
|
|
'abm_email' => $params['abm_email'],
|
|
'rbm_name' => $params['rbm_name'],
|
|
'msl_code' => $params['msl_code'],
|
|
// 'form_submit_type' => $params['form_submit_type'],
|
|
'doctor_name' => $params['dr_name'],
|
|
'doctor_phone' => $params['doctor_mobile_number'],
|
|
'doctor_speciality' => $params['speciality'],
|
|
// 'nebulizer_purpose' => $params['for_what_purpose_nebulisers_will_be_used_by_dr'],
|
|
// 'patient_name' => $params[''],
|
|
// 'patient_phone' => $params[''],
|
|
// 'type_of_nebulizer' => $params['type_of_nebuliser'],
|
|
'type_of_nebulizer' => $params['type_of_nebulizer'],
|
|
'more_than_5_nebulizer' => $params['more_than_5_nebulizer'],
|
|
|
|
'no_of_nebulizer' => $params['no_of_nebulizer'],
|
|
'value_of_parcel' => $params['value_of_the_parcel'],
|
|
// 'address_type' => $params[''],
|
|
'address_building' => $params['building_name'],
|
|
'address_type' => $params['address_type'],
|
|
'address_line_1' => $params['address_line_1'],
|
|
'address_line_2' => $params['address_line_2'],
|
|
// 'address_landmark' => $params[''],
|
|
'address_state' => $params['state'],
|
|
'address_city' => $params['city'],
|
|
'address_pin_code' => $params['pin_code'],
|
|
'clinic_hospital_name' => $params['clinic_hospital_home_name'],
|
|
|
|
// 'commented
|
|
// 'address_landmark' => $params['landmark'],
|
|
|
|
// 'pickup_type' => $params[''],
|
|
// 'pickup_building' => $params[''],
|
|
// 'pickup_line_1' => $params[''],
|
|
// 'pickup_line_2' => $params[''],
|
|
// 'pickup_landmark' => $params[''],
|
|
// 'pickup_state' => $params[''],
|
|
// 'pickup_city' => $params[''],
|
|
// 'pickup_pin_code' => $params[''],
|
|
|
|
// 'rejected_reason' => $params[''],
|
|
'team' => $params['team'],
|
|
// 'geolocation_latitude' => $params['geolocation_latitude'],
|
|
// 'geolocation_longitude' => $params['geolocation_longitude'],
|
|
// 'geolocation_address' => $params['geolocation_address'],
|
|
// 'geolocation_json' => $params['geolocation_json'],
|
|
// 'depot_id' => $depot_mapping[$params['state']] ?? NULL,
|
|
// 'depot_state' => $params['state']
|
|
|
|
'remarks' => $params['remarks'],
|
|
'paramedic_alternate_contact_number' => $params['paramedic_alternate_contact_number'],
|
|
|
|
];
|
|
}
|
|
|
|
$params['form_id'] = '1750914801-153443b9-94d0-4dcb-b3f3-4fa11588a0a9';
|
|
$files = $request->file();
|
|
if (!empty($files)) {
|
|
foreach ($files as $fname => $file) {
|
|
if ($file && $file->isValid()) {
|
|
$params[$fname] = $this->_uploadMedia($request, $fname, 'form/' . $params['form_id'] . '/' . $fname);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!empty($params['upload_request_letter'])) {
|
|
$datatosave['request_letter'] = $params['upload_request_letter'];
|
|
} elseif (!empty($params['existing_letter'])) {
|
|
$datatosave['request_letter'] = $params['existing_letter'];
|
|
}
|
|
|
|
$params['id'] = $params['submission_id'];
|
|
|
|
// Get old data before update for audit trail
|
|
$oldData = DB::table('neblogistic')->where('id', $params['record_id'])->first();
|
|
$oldDataArray = $oldData ? json_decode(json_encode($oldData), true) : null;
|
|
|
|
$dataUpdate = DB::table('neblogistic')->where('id', $params['record_id'])->update($datatosave);
|
|
|
|
// Log UPDATE operation
|
|
if ($dataUpdate) {
|
|
NeblogisticAuditService::logUpdate(
|
|
$params['record_id'],
|
|
$oldDataArray,
|
|
$datatosave,
|
|
null, // Let service calculate changed fields
|
|
$request
|
|
);
|
|
}
|
|
|
|
|
|
$data = DB::table('neblogistic')->where('id', $params['record_id'])->first();
|
|
$emailWarnings = [];
|
|
|
|
if (isset($params['status'])) {
|
|
if ($params['status'] == 'Rejected') {
|
|
$rejectWarn = $this->sendNeblogisticMailSafely(
|
|
new NeblogisticRejection((array) $data),
|
|
$data->emp_email ?? null,
|
|
$data->abm_email ?? null,
|
|
['id' => $data->id ?? null, 'mail' => 'rejection']
|
|
);
|
|
if ($rejectWarn !== null) {
|
|
$emailWarnings[] = $rejectWarn;
|
|
}
|
|
try {
|
|
Mail::to('ravigulhane1983@gmail.com')->send(new NeblogisticRejection((array) $data));
|
|
} catch (\Throwable $e) {
|
|
Log::error('Neblogistic rejection debug email failed', [
|
|
'id' => $data->id ?? null,
|
|
'message' => $e->getMessage(),
|
|
]);
|
|
}
|
|
} elseif (in_array($params['status'], ['Dispatched', 'Delivered'], true)) {
|
|
Log::info('Neblogistic status update email', [
|
|
'data' => $data,
|
|
]);
|
|
$tmWarn = $this->sendNeblogisticMailSafely(
|
|
new NeblogisticStatusUpdate((array) $data, 'tm'),
|
|
$data->emp_email ?? null,
|
|
null,
|
|
['id' => $data->id ?? null, 'mail' => 'status_tm']
|
|
);
|
|
if ($tmWarn !== null) {
|
|
$emailWarnings[] = $tmWarn;
|
|
}
|
|
$abmWarn = $this->sendNeblogisticMailSafely(
|
|
new NeblogisticStatusUpdate((array) $data, 'abm'),
|
|
$data->abm_email ?? null,
|
|
null,
|
|
['id' => $data->id ?? null, 'mail' => 'status_abm']
|
|
);
|
|
if ($abmWarn !== null) {
|
|
$emailWarnings[] = $abmWarn;
|
|
}
|
|
|
|
// Prevent cron from re-sending the same status email
|
|
DB::table('neblogistic')
|
|
->where('id', $params['record_id'])
|
|
->update(['status_email_sent' => $params['status']]);
|
|
}
|
|
}
|
|
|
|
$data->employee_name = $data->emp_name;
|
|
$data->dr_name = $data->doctor_name;
|
|
$data->doctor_mobile_number = $data->doctor_phone;
|
|
$data->building_name = $data->address_building;
|
|
$data->state = $data->address_state;
|
|
$data->city = $data->address_city;
|
|
$data->pin_code = $data->address_pin_code;
|
|
$data->clinic_hospital_home_name = $data->clinic_hospital_name;
|
|
|
|
$editWarn = $this->sendNeblogisticMailSafely(
|
|
new Neblogistic((array) $data),
|
|
$data->emp_email ?? null,
|
|
$data->abm_email ?? null,
|
|
['id' => $data->id ?? null, 'mail' => 'edit_notification']
|
|
);
|
|
if ($editWarn !== null) {
|
|
$emailWarnings[] = $editWarn;
|
|
}
|
|
//Mail::to('arbaz@stratawiz.com')->send(new NeblogisticSupervisor((array)$data));
|
|
|
|
$user = Auth::user();
|
|
$successMessage = 'Data Saved';
|
|
if (!empty($emailWarnings)) {
|
|
$successMessage .= '. ' . implode(' ', array_unique($emailWarnings));
|
|
}
|
|
|
|
if(!$params['submission_id'] == ''){
|
|
// return print_r($params);
|
|
|
|
$post = ['formdata' => $params, 'entity_id' => '1750914801-153443b9-94d0-4dcb-b3f3-4fa11588a0a9', 'user_id' => $params['user_id'], 'partition' => 'rapport-' . $user->domain];
|
|
$history = LambdaRequest::signedrequest('post', 'form', 'formentity/submitform', $post, 120);
|
|
Log::info('formsubmission after edit', [ 'history' => $history]);
|
|
if ($history->status === 'success') {
|
|
return redirect()->back()->with('message', $successMessage);
|
|
} else {
|
|
return redirect()->back()->with('error', 'Operation failed.');
|
|
}
|
|
}
|
|
|
|
// print_r($history);
|
|
// exit;
|
|
|
|
|
|
if ($dataUpdate) {
|
|
return redirect()->back()->with('message', $successMessage);
|
|
} else {
|
|
return redirect()->back()->with('error', 'Operation failed.');
|
|
}
|
|
}
|
|
|
|
public function depot()
|
|
{
|
|
$data = DB::table('team3_neblogistics_depot')->where('status', 1)->get();
|
|
return view($this->_viewname . '.depot')->with([
|
|
'title' => 'Depot',
|
|
'base_url' => '/neblogisticreport/adddepot',
|
|
'buttons' => $this->get_list_buttons(),
|
|
'data' => $data,
|
|
]);
|
|
}
|
|
|
|
public function postdepot(Request $request)
|
|
{
|
|
$post = $request->except('_token');
|
|
if ($request->has('id') && !empty($request->id)) {
|
|
$data = DB::table('team3_neblogistics_depot')
|
|
->where('id', $request->id)
|
|
->update([
|
|
'region' => $request->region,
|
|
'state' => $request->state,
|
|
'name' => $request->name,
|
|
'pincode' => $request->pincode,
|
|
]);
|
|
} else {
|
|
$data = DB::table('team3_neblogistics_depot')->insert($post);
|
|
}
|
|
if ($data) {
|
|
$redirectId = $request->id ?? DB::getPdo()->lastInsertId();
|
|
return redirect('/neblogisticreport/editdepot?id=' . $redirectId)->with('message', 'Depot is saved');
|
|
} else {
|
|
return redirect()->back()->with('error', 'Some Error Occurred');
|
|
}
|
|
}
|
|
|
|
public function editdepot($id)
|
|
{
|
|
// return $id;
|
|
$dataall = DB::table('team3_neblogistics_depot')->where('status', 1)->get();
|
|
|
|
$data = DB::table('team3_neblogistics_depot')->where('id', $id->id)->get();
|
|
return view($this->_viewname . '.depot')->with([
|
|
'title' => 'Depot',
|
|
'base_url' => '/neblogisticreport/adddepot',
|
|
'buttons' => $this->get_list_buttons(),
|
|
'data' => $dataall,
|
|
'editvalues' => $data,
|
|
]);
|
|
}
|
|
|
|
public function deletedepot($id)
|
|
{
|
|
// return $id;
|
|
$del = DB::table('team3_neblogistics_depot')
|
|
->where('id', $id->id)
|
|
->update([
|
|
'status' => 0,
|
|
]);
|
|
if ($del) {
|
|
//echo '<pre>'; print_r($response); exit;
|
|
return redirect('neblogisticreport/depot')->withMessage('Successfully Marked Deleted !!!');
|
|
} else {
|
|
return redirect('neblogisticreport/depot')->withError('Some Error occured! ' . $response->message);
|
|
//return \Redirect::back()->withMessage('Some Error occured!');
|
|
}
|
|
}
|
|
|
|
public function nebtm()
|
|
{
|
|
$depot = DB::table('team3_neblogistics_depot')->get();
|
|
$data['depot'] = $depot;
|
|
return view($this->_viewname . '.nebtm')->with([
|
|
'title' => 'TM',
|
|
'base_url' => '/neblogisticreport/nebtm',
|
|
'item' => $data,
|
|
'buttons' => $this->get_list_buttons(),
|
|
]);
|
|
}
|
|
|
|
public function export(Request $request)
|
|
{
|
|
$state = $request->query('state');
|
|
$fromDate = $request->query('from_date');
|
|
$toDate = $request->query('to_date');
|
|
$statusFilter = $request->input('status');
|
|
$yesterday = now()->subDay()->format('Y-m-d');
|
|
|
|
// $post = $request->all();
|
|
// echo '<pre>'; print_r($post); exit;
|
|
$user = Auth::user();
|
|
$query = DB::table('neblogistic')
|
|
->select([
|
|
'id', 'emp_id', 'depot_name', 'address_state', 'doctor_name', 'created_at',
|
|
'msl_code', 'no_of_nebulizer', 'address_type', 'address_line_1', 'address_line_2', 'clinic_hospital_name',
|
|
'address_building', 'address_pin_code', 'address_city', 'doctor_phone', 'approved_at', 'status', 'old_employee_code', 'transporter', 'remarks', 'paramedic_alternate_contact_number',
|
|
'order_no', 'invoice_no', 'courier_name', 'lr_no', 'lr_date'
|
|
])
|
|
->where('status', '=', 'Approved');
|
|
// If the user has the 'depotmanager' role, filter depot_name and status
|
|
if (in_array('1733912682-7c353bf8-c309-49b3-93e7-depotmanager', json_decode($user->roles ?? '[]', true))) {
|
|
$nameParts = explode(' ', $user->name);
|
|
$firstName = $nameParts[0] ?? '';
|
|
$query->where('depot_name', $firstName)
|
|
->where('status', 'Approved');
|
|
} elseif (in_array('1733912682-7c353bf8-c309-49b3-93e7-superdepotmanager', json_decode($user->roles ?? '[]', true))) {
|
|
$nameParts = explode(' ', $user->name);
|
|
$firstName = $nameParts[0] ?? '';
|
|
$query->where('status', 'Approved');
|
|
if (!empty($state)) {
|
|
$query->where('depot_name', $state);
|
|
}
|
|
} else {
|
|
if (!empty($state)) {
|
|
$query->where('depot_name', $state);
|
|
}
|
|
// if (!empty($statusFilter)) {
|
|
// $query->where('status', $statusFilter);
|
|
// }
|
|
}
|
|
|
|
if (!empty($fromDate) && !empty($toDate)) {
|
|
$query->whereBetween('created_at', [$fromDate . ' 00:00:00', $toDate . ' 23:59:59']);
|
|
}else{
|
|
$query->whereBetween('created_at', [$yesterday . ' 00:00:00', $yesterday . ' 23:59:59']);
|
|
}
|
|
|
|
$headers = [
|
|
['label' => 'TM EMP CD', 'color' => 'B71C1C'],
|
|
['label' => 'Depot Name', 'color' => 'B71C1C'],
|
|
['label' => 'State', 'color' => 'FFEB3B', 'fontcolor' => 'B71C1C'],
|
|
['label' => 'Dr Name', 'color' => 'FFEB3B', 'fontcolor' => 'B71C1C'],
|
|
['label' => 'sales org', 'color' => 'B71C1C'],
|
|
['label' => 'dist ch', 'color' => 'B71C1C'],
|
|
['label' => 'div', 'color' => 'B71C1C'],
|
|
['label' => 'Order Type', 'color' => 'B71C1C'],
|
|
['label' => 'Category', 'color' => 'B71C1C'],
|
|
['label' => 'PO DATE', 'color' => 'B71C1C'],
|
|
['label' => 'OLD DR CODE(SOLD TO)', 'color' => 'B71C1C'],
|
|
['label' => 'shipt to party code(SAP PARTY CODE)', 'color' => 'B71C1C'],
|
|
['label' => 'Supply Start Date', 'color' => 'B71C1C'],
|
|
['label' => 'Months', 'color' => 'B71C1C'],
|
|
['label' => 'Delivering Plant', 'color' => 'B71C1C'],
|
|
['label' => 'Product Code', 'color' => 'B71C1C'],
|
|
['label' => 'Quantity', 'color' => 'B71C1C'],
|
|
|
|
['label' => 'OLD employee code', 'color' => '1976D2'],
|
|
['label' => 'transporter', 'color' => '1976D2'],
|
|
['label' => 'Remarks', 'color' => '1976D2'],
|
|
|
|
['label' => 'Connect od Order', 'color' => 'B71C1C'],
|
|
['label' => 'Connect od Order Date', 'color' => 'B71C1C'],
|
|
['label' => 'BP_Address 1', 'color' => '1976D2'],
|
|
['label' => 'BP_Address 2', 'color' => '1976D2'],
|
|
['label' => 'BP_Address 3', 'color' => '1976D2'],
|
|
['label' => 'BP_Address 4', 'color' => '1976D2'],
|
|
['label' => 'BP_Pincode', 'color' => '1976D2'],
|
|
['label' => 'BP_city', 'color' => '1976D2'],
|
|
['label' => 'BP_state', 'color' => '1976D2'],
|
|
['label' => 'BP_Mobile no', 'color' => '1976D2'],
|
|
['label' => 'SP_Address 1', 'color' => '1976D2'],
|
|
['label' => 'SP_Address 2', 'color' => '1976D2'],
|
|
['label' => 'SP_Address 3', 'color' => '1976D2'],
|
|
['label' => 'SP_Address 4', 'color' => '1976D2'],
|
|
['label' => 'SP_Pincode', 'color' => '1976D2'],
|
|
['label' => 'SP_city', 'color' => '1976D2'],
|
|
['label' => 'SP_state', 'color' => '1976D2'],
|
|
['label' => 'SP_Mobile no', 'color' => '1976D2'],
|
|
// Keep any extra fields if needed
|
|
['label' => 'Paramedic/Alternate Contact number', 'color' => '1976D2'],
|
|
['label' => 'ORDER NO', 'color' => 'B71C1C'],
|
|
['label' => 'INVOICE NO', 'color' => 'B71C1C'],
|
|
['label' => 'COURIER NAME', 'color' => 'B71C1C'],
|
|
['label' => 'LR NO', 'color' => 'B71C1C'],
|
|
['label' => 'LR DATE', 'color' => 'B71C1C'],
|
|
];
|
|
|
|
$exceldata[] = array_column($headers, 'label');
|
|
|
|
$deliveringplant = [
|
|
'HYDERABAD' => [
|
|
['Plant Name' => 'CIPLA LTD HYDERABAD (RD)', 'Plant' => '1102']
|
|
],
|
|
'VIJAYWADA' => [
|
|
['Plant Name' => 'CIPLA LTD VIJAYWADA (RD)', 'Plant' => '1104']
|
|
],
|
|
'GUWAHATI' => [
|
|
['Plant Name' => 'CIPLA LTD GUWAHATI (RD)', 'Plant' => '1105']
|
|
],
|
|
'PATNA' => [
|
|
['Plant Name' => 'CIPLA LTD PATNA (RD)', 'Plant' => '1106']
|
|
],
|
|
'AHMEDABAD' => [
|
|
['Plant Name' => 'CIPLA LTD AHMEDABAD (RD)', 'Plant' => '1116']
|
|
],
|
|
'BANGALORE' => [
|
|
['Plant Name' => 'CIPLA LTD BANGALORE (RD)', 'Plant' => '1124']
|
|
],
|
|
'COCHIN' => [
|
|
['Plant Name' => 'CIPLA LTD COCHIN (RD)', 'Plant' => '1128']
|
|
],
|
|
'MUMBAi' => [
|
|
['Plant Name' => 'CIPLA LTD MUMBAI (RD)', 'Plant' => '1132']
|
|
],
|
|
'NAGPUR' => [
|
|
['Plant Name' => 'CIPLA LTD NAGPUR (RD)', 'Plant' => '1134']
|
|
],
|
|
'PUNE' => [
|
|
['Plant Name' => 'CIPLA LTD PUNE (RD)-14', 'Plant' => '1136']
|
|
],
|
|
'INDORE' => [
|
|
['Plant Name' => 'CIPLA LTD INDORE (RD)', 'Plant' => '1139']
|
|
],
|
|
'CUTTACK' => [
|
|
['Plant Name' => 'CIPLA LTD CUTTACK (RD)', 'Plant' => '1143']
|
|
],
|
|
'ZIRAKPUR' => [
|
|
['Plant Name' => 'CIPLA LTD ZIRAKPUR (RD)', 'Plant' => '1145']
|
|
],
|
|
'JAIPUR' => [
|
|
['Plant Name' => 'CIPLA LTD JAIPUR (RD)', 'Plant' => '1147']
|
|
],
|
|
'CHENNAI' => [
|
|
['Plant Name' => 'CIPLA LTD CHENNAI (RD)', 'Plant' => '1149']
|
|
],
|
|
'MADURAI' => [
|
|
['Plant Name' => 'CIPLA LTD MADURAI (RD)', 'Plant' => '1150']
|
|
],
|
|
'GHAZIABAD' => [
|
|
['Plant Name' => 'CIPLA LTD GHAZIABAD (RD)', 'Plant' => '1152']
|
|
],
|
|
'LUCKNOW' => [
|
|
['Plant Name' => 'CIPLA LTD LUCKNOW (RD)', 'Plant' => '1153']
|
|
],
|
|
'VARANASI' => [
|
|
['Plant Name' => 'CIPLA LTD VARANASI (RD)', 'Plant' => '1154']
|
|
],
|
|
'KOLKATA' => [
|
|
['Plant Name' => 'CIPLA LTD KOLKATA (RD)', 'Plant' => '1158']
|
|
],
|
|
'RANCHI' => [
|
|
['Plant Name' => 'CIPLA LTD RANCHI (RD)', 'Plant' => '1161']
|
|
],
|
|
];
|
|
|
|
$statecodes = [
|
|
'ANDHRA PRADESH' => '01',
|
|
'Arunachal Pradesh' => '02',
|
|
'Assam' => '03',
|
|
'Bihar' => '04',
|
|
'Goa' => '05',
|
|
'Gujarat' => '06',
|
|
'Haryana' => '07',
|
|
'Himachal Pradesh' => '08',
|
|
'JAMMU AND KASHMIR' => '09',
|
|
'Karnataka' => '10',
|
|
'Kerala' => '11',
|
|
'Madhya Pradesh' => '12',
|
|
'Maharashtra' => '13',
|
|
'Manipur' => '14',
|
|
'MEGHALAYA' => '15',
|
|
'Mizoram' => '16',
|
|
'Nagaland' => '17',
|
|
'ODISHA' => '18',
|
|
'Punjab' => '19',
|
|
'Rajasthan' => '20',
|
|
'Sikkim' => '21',
|
|
'Tamil Nadu' => '22',
|
|
'Tripura' => '23',
|
|
'Uttar Pradesh' => '24',
|
|
'West Bengal' => '25',
|
|
'ANDAMAN & NICOBAR IS'=> '26',
|
|
'Chandigarh' => '27',
|
|
'DADRA & NAGAR HAVELI'=> '28',
|
|
'DAMAN AND DIU' => '29',
|
|
'Delhi' => '30',
|
|
'Lakshadweep' => '31',
|
|
'PUDUCHERRY' => '32',
|
|
'CHHATTISGARH' => '33',
|
|
'Jharkhand' => '34',
|
|
'UTTARAKHAND' => '35',
|
|
'Telangana' => '36',
|
|
'LADAKH' => 'LD',
|
|
'Virtual Plant' => 'VP',
|
|
];
|
|
|
|
$normalizedStatecodes = [];
|
|
foreach ($statecodes as $state => $code) {
|
|
$key = strtolower(str_replace(' ', '', $state));
|
|
$normalizedStatecodes[$key] = $code;
|
|
}
|
|
//$query->where('id', 187142);
|
|
|
|
$query->orderBy('created_at', 'DESC')->chunk(1000, function ($records) use (&$exceldata, $deliveringplant, $normalizedStatecodes) {
|
|
foreach ($records as $res) {
|
|
$formattedDate = isset($res->created_at) ? Carbon::parse($res->created_at)->format('d-m-Y') : '';
|
|
$monthValue = isset($res->created_at) ? date('m', strtotime($res->created_at)) : '';
|
|
|
|
$stateKey = strtolower(str_replace(' ', '', $res->address_state ?? ''));
|
|
$stateCode = $normalizedStatecodes[$stateKey] ?? 'No Code Found';
|
|
|
|
// Try merging 2 address fields at a time, each <= 40 chars, else fallback to splitting full address
|
|
$addressParts = [
|
|
isset($res->clinic_hospital_name) ? str_replace(',', '', $res->clinic_hospital_name) : '',
|
|
isset($res->address_type) ? str_replace(',', '', $res->address_type) : '',
|
|
isset($res->address_building) ? str_replace(',', '', $res->address_building) : '',
|
|
isset($res->address_line_1) ? str_replace(',', '', $res->address_line_1) : '',
|
|
isset($res->address_line_2) ? str_replace(',', '', $res->address_line_2) : ''
|
|
];
|
|
|
|
// Find the two consecutive parts whose combined length is least and <= 40, merge them, leave others as is
|
|
$minLen = null;
|
|
$mergeIdx = null;
|
|
for ($i = 0; $i < count($addressParts) - 1; $i++) {
|
|
$a = trim($addressParts[$i]);
|
|
$b = trim($addressParts[$i + 1]);
|
|
if ($a === '' || $b === '') continue;
|
|
$combinedLen = mb_strlen($a . ' ' . $b);
|
|
if ($combinedLen <= 40 && ($minLen === null || $combinedLen < $minLen)) {
|
|
$minLen = $combinedLen;
|
|
$mergeIdx = $i;
|
|
}
|
|
}
|
|
$mergedAddressParts = [];
|
|
$i = 0;
|
|
while ($i < count($addressParts)) {
|
|
if ($mergeIdx !== null && $i === $mergeIdx) {
|
|
$mergedAddressParts[] = trim($addressParts[$i]) . ' ' . trim($addressParts[$i + 1]);
|
|
$i += 2;
|
|
} else {
|
|
$mergedAddressParts[] = trim($addressParts[$i]);
|
|
$i++;
|
|
}
|
|
}
|
|
// Ensure exactly 4 parts
|
|
$mergedAddressParts = array_values(array_filter($mergedAddressParts, fn($v) => $v !== ''));
|
|
|
|
if(count($mergedAddressParts) == 4) {
|
|
$addressFields = $mergedAddressParts;
|
|
} else {
|
|
$filteredParts = array_values(array_filter($addressParts, fn($v) => $v !== ''));
|
|
$addressFields = [];
|
|
$i = 0;
|
|
while ($i < count($filteredParts) && count($addressFields) < 4) {
|
|
// Try to merge current and next part if combined length <= 40
|
|
$current = $filteredParts[$i];
|
|
$next = ($i + 1 < count($filteredParts)) ? $filteredParts[$i + 1] : '';
|
|
if ($next !== '' && mb_strlen($current . ' ' . $next) <= 40) {
|
|
$addressFields[] = trim($current . ' ' . $next);
|
|
$i += 2;
|
|
} else {
|
|
if (mb_strlen($current) > 40) {
|
|
// Split long part by word, not in the middle of a word
|
|
$words = preg_split('/\s+/', $current);
|
|
$line = '';
|
|
foreach ($words as $word) {
|
|
if (mb_strlen($line . ' ' . $word) > 40) {
|
|
$addressFields[] = trim($line);
|
|
$line = $word;
|
|
if (count($addressFields) == 4) break;
|
|
} else {
|
|
$line .= ($line === '' ? '' : ' ') . $word;
|
|
}
|
|
}
|
|
if ($line !== '' && count($addressFields) < 4) {
|
|
$addressFields[] = trim($line);
|
|
}
|
|
} else {
|
|
$addressFields[] = $current;
|
|
}
|
|
$i++;
|
|
}
|
|
}
|
|
// If still less than 4, fallback: merge all and split sensibly
|
|
if (count($addressFields) < 4) {
|
|
$fullAddress = implode(', ', $filteredParts);
|
|
$splitParts = preg_split('/,\s*/', $fullAddress);
|
|
$fallbackFields = [];
|
|
foreach ($splitParts as $part) {
|
|
if (mb_strlen($part) > 40) {
|
|
$words = preg_split('/\s+/', $part);
|
|
$line = '';
|
|
foreach ($words as $word) {
|
|
if (mb_strlen($line . ' ' . $word) > 40) {
|
|
$fallbackFields[] = trim($line);
|
|
$line = $word;
|
|
if (count($fallbackFields) == 4) break;
|
|
} else {
|
|
$line .= ($line === '' ? '' : ' ') . $word;
|
|
}
|
|
}
|
|
if ($line !== '' && count($fallbackFields) < 4) {
|
|
$fallbackFields[] = trim($line);
|
|
}
|
|
} else {
|
|
$fallbackFields[] = $part;
|
|
}
|
|
if (count($fallbackFields) == 4) break;
|
|
}
|
|
while (count($fallbackFields) < 4) {
|
|
$fallbackFields[] = '';
|
|
}
|
|
$addressFields = $fallbackFields;
|
|
} else {
|
|
while (count($addressFields) < 4) {
|
|
$addressFields[] = '';
|
|
}
|
|
}
|
|
}
|
|
//echo "<pre>"; print_r($addressFields); exit;
|
|
$addressFields = array_slice($addressFields, 0, 4);
|
|
|
|
$exceldata[] = [
|
|
isset($res->emp_id) ? $res->emp_id : '',
|
|
isset($res->depot_name) ? $res->depot_name : '',
|
|
isset($res->address_state) ? $res->address_state : '',
|
|
isset($res->doctor_name) ? $res->doctor_name : '',
|
|
1000,
|
|
10,
|
|
11,
|
|
'ZMMD',
|
|
'Connect Od',
|
|
isset($res->approved_at) ? Carbon::parse($res->approved_at)->format('d.m.Y') : '',
|
|
isset($res->msl_code) ? $res->msl_code : '',
|
|
'',
|
|
isset($res->approved_at) ? Carbon::parse($res->approved_at)->format('d.m.Y') : '',
|
|
'1', //$monthValue,
|
|
|
|
isset($res->depot_name)
|
|
? (array_key_exists($res->depot_name, $deliveringplant)
|
|
? $deliveringplant[$res->depot_name][0]['Plant']
|
|
: 'No Plant Code Found')
|
|
: 'No State to Plant Mapping Found',
|
|
|
|
'',
|
|
isset($res->no_of_nebulizer) ? $res->no_of_nebulizer : '',
|
|
|
|
isset($res->emp_id) ? $res->emp_id : '',
|
|
isset($res->transporter) ? $res->transporter : '',
|
|
isset($res->remarks) ? $res->remarks : '',
|
|
|
|
isset($res->id) ? $res->id : '',
|
|
isset($res->created_at) ? Carbon::parse($res->created_at)->format('d.m.Y') : '',
|
|
|
|
$addressFields[0],
|
|
$addressFields[1],
|
|
$addressFields[2],
|
|
$addressFields[3],
|
|
|
|
isset($res->address_pin_code) ? $res->address_pin_code : '',
|
|
isset($res->address_city) ? $res->address_city : '',
|
|
isset($stateCode) ? $stateCode : '',
|
|
isset($res->doctor_phone) ? $res->doctor_phone : '',
|
|
|
|
// isset($res->address_type) ? $res->address_type : '',
|
|
// isset($res->address_building) ? $res->address_building : '',
|
|
// isset($res->address_line_1) ? $res->address_line_1 : '',
|
|
// isset($res->address_line_2) ? $res->address_line_2 : '',
|
|
$addressFields[0],
|
|
$addressFields[1],
|
|
$addressFields[2],
|
|
$addressFields[3],
|
|
|
|
isset($res->address_pin_code) ? $res->address_pin_code : '',
|
|
isset($res->address_city) ? $res->address_city : '',
|
|
isset($stateCode) ? $stateCode : '',
|
|
isset($res->doctor_phone) ? $res->doctor_phone : '',
|
|
isset($res->paramedic_alternate_contact_number) ? $res->paramedic_alternate_contact_number : '',
|
|
isset($res->order_no) ? $res->order_no : '',
|
|
isset($res->invoice_no) ? $res->invoice_no : '',
|
|
isset($res->courier_name) ? $res->courier_name : '',
|
|
isset($res->lr_no) ? $res->lr_no : '',
|
|
isset($res->lr_date) ? Carbon::parse($res->lr_date)->format('d.m.Y') : '',
|
|
|
|
];
|
|
}
|
|
});
|
|
|
|
//echo "<pre>"; print_r($exceldata); exit;
|
|
$fileName = 'neblogistic_report' .
|
|
($fromDate ? '_' . Carbon::parse($fromDate)->format('d-m-Y') : '') .
|
|
($toDate ? '_' . Carbon::parse($toDate)->format('d-m-Y') : '') .
|
|
($state ? '_' . $state : '') . '.xlsx';
|
|
|
|
return Excel::download(new CustomInvoiceExport($exceldata, $headers), $fileName);
|
|
}
|
|
|
|
public function exportOld(Request $request){
|
|
|
|
$state = $request->query('state');
|
|
$fromDate = $request->query('from_date');
|
|
$toDate = $request->query('to_date');
|
|
$statusFilter = $request->input('status');
|
|
$yesterday = now()->subDay()->format('Y-m-d');
|
|
|
|
$query = DB::table('neblogistic')
|
|
->select(
|
|
'id', 'request_type', 'emp_id', 'emp_name', 'emp_phone', 'emp_email', 'abm_name', 'abm_email', 'rbm_name', 'msl_code', 'request_letter', 'doctor_name', 'doctor_phone', 'doctor_speciality', 'patient_name', 'patient_phone', 'type_of_nebulizer', 'type_of_nebulizer', 'no_of_nebulizer', 'value_of_parcel', 'team', 'nebulizer_purpose', 'address_type', 'address_building', 'address_line_1', 'address_line_2', 'address_landmark', 'address_state', 'address_city', 'address_pin_code', 'pickup_type', 'pickup_building', 'pickup_line_1', 'pickup_line_2', 'pickup_landmark', 'pickup_state', 'pickup_city', 'pickup_pin_code', 'status', 'approved_at', 'l1_approved_at', 'l2_approved_at', 'l3_approved_at', 'approval_reason', 'dispatch_at', 'rejected_at', 'rejected_reason', 'created_at', 'clinic_hospital_name',
|
|
// New fields for export
|
|
'order_no', 'invoice_no', 'courier_name', 'lr_no', 'lr_date', 'more_than_5_nebulizer'
|
|
)
|
|
->where('status', '!=', 'Partially Saved');
|
|
|
|
if (!empty($statusFilter)) {
|
|
$query->where('status', $statusFilter);
|
|
}
|
|
|
|
if (!empty($state)) {
|
|
$query->where('depot_name', $state);
|
|
}
|
|
|
|
if (!empty($statusFilter)) {
|
|
$query->where('status', $statusFilter);
|
|
}
|
|
|
|
if (!empty($fromDate) && !empty($toDate)) {
|
|
$query->whereBetween('created_at', [$fromDate . ' 00:00:00', $toDate . ' 23:59:59']);
|
|
} else {
|
|
$query->whereBetween('created_at', [$yesterday . ' 00:00:00', $yesterday . ' 23:59:59']);
|
|
}
|
|
|
|
$query->orderBy('created_at', 'DESC');
|
|
$data = $query->get();
|
|
|
|
$fileName = 'neblogistic_report_in_old_format' .
|
|
($fromDate ? '_' . Carbon::parse($fromDate)->format('d-m-Y') : '') .
|
|
($toDate ? '_' . Carbon::parse($toDate)->format('d-m-Y') : '') .
|
|
($statusFilter ? '_' . $statusFilter : '') .
|
|
($state ? '_' . $state : '') . '.csv';
|
|
|
|
$headers = array(
|
|
"Content-type" => "text/csv",
|
|
"Content-Disposition" => "attachment; filename=". $fileName,
|
|
"Pragma" => "no-cache",
|
|
"Cache-Control" => "must-revalidate, post-check=0, pre-check=0",
|
|
"Expires" => "0"
|
|
);
|
|
|
|
// Add new columns for export
|
|
$columns = array(
|
|
'Id', 'Request Type', 'Emp Id', 'Emp Name', 'Emp Phone', 'Emp Email', 'Abm Name', 'Abm Email', 'Rbm Name', 'Msl Code', 'Request Letter', 'Doctor Name', 'Doctor Phone', 'Doctor Speciality', 'Patient Name', 'Patient Phone', 'Type Of Nebulizer', 'No Of Nebulizer', 'More than 5 Nebulizer', 'Value Of Parcel', 'Team', 'Nebulizer Purpose', 'Clinic/Hospital/Home Name', 'Address Type', 'Address Building', 'Address Line 1', 'Address Line 2', 'Address Landmark', 'Address State', 'Address City', 'Address Pin Code', 'Pickup Type', 'Pickup Building', 'Pickup Line 1', 'Pickup Line 2', 'Pickup Landmark', 'Pickup State', 'Pickup City', 'Pickup Pin Code', 'Status', 'Approved Date', 'L1 Approved Date', 'L2 Approved Date', 'L3 Approved Date', 'Approval Reason', 'Despatch Date', 'Rejected Date', 'Rejected Reason', 'Request Date',
|
|
// New columns
|
|
'Order No', 'Invoice No', 'Courier Name', 'LR No', 'LR Date'
|
|
);
|
|
|
|
$callback = function() use ($data, $columns)
|
|
{
|
|
$file = fopen('php://output', 'w');
|
|
fputcsv($file, $columns);
|
|
|
|
foreach($data as $item) {
|
|
// Format date fields
|
|
$item->created_at = date("d-M-Y, H:iA", strtotime($item->created_at) + 19800 );
|
|
|
|
$item->approved_at = !empty($item->approved_at)
|
|
? date("d-M-Y, H:iA", strtotime($item->approved_at) + 19800 )
|
|
: '';
|
|
|
|
$item->l1_approved_at = !empty($item->l1_approved_at)
|
|
? date("d-M-Y, H:iA", strtotime($item->l1_approved_at) + 19800 )
|
|
: '';
|
|
|
|
$item->l2_approved_at = !empty($item->l2_approved_at)
|
|
? date("d-M-Y, H:iA", strtotime($item->l2_approved_at) + 19800 )
|
|
: '';
|
|
|
|
$item->l3_approved_at = !empty($item->l3_approved_at)
|
|
? date("d-M-Y, H:iA", strtotime($item->l3_approved_at) + 19800 )
|
|
: '';
|
|
|
|
$item->dispatch_at = !empty($item->dispatch_at)
|
|
? date("d-M-Y, H:iA", strtotime($item->dispatch_at) + 19800 )
|
|
: '';
|
|
|
|
$item->rejected_at = !empty($item->rejected_at)
|
|
? date("d-M-Y, H:iA", strtotime($item->rejected_at) + 19800 )
|
|
: '';
|
|
|
|
// Format lr_date to Y-m-d H:i:s if provided, else null
|
|
if (!empty($item->lr_date)) {
|
|
$item->lr_date = date("Y-m-d H:i:s", strtotime($item->lr_date));
|
|
} else {
|
|
$item->lr_date = null;
|
|
}
|
|
|
|
// Prepare row in the same order as $columns
|
|
$row = [
|
|
$item->id ?? '',
|
|
$item->request_type ?? '',
|
|
$item->emp_id ?? '',
|
|
$item->emp_name ?? '',
|
|
$item->emp_phone ?? '',
|
|
$item->emp_email ?? '',
|
|
$item->abm_name ?? '',
|
|
$item->abm_email ?? '',
|
|
$item->rbm_name ?? '',
|
|
$item->msl_code ?? '',
|
|
$item->request_letter ?? '',
|
|
$item->doctor_name ?? '',
|
|
$item->doctor_phone ?? '',
|
|
$item->doctor_speciality ?? '',
|
|
$item->patient_name ?? '',
|
|
$item->patient_phone ?? '',
|
|
$item->type_of_nebulizer ?? '',
|
|
$item->no_of_nebulizer ?? '',
|
|
$item->more_than_5_nebulizer ?? '',
|
|
$item->value_of_parcel ?? '',
|
|
$item->team ?? '',
|
|
$item->nebulizer_purpose ?? '',
|
|
$item->clinic_hospital_name ?? '',
|
|
$item->address_type ?? '',
|
|
$item->address_building ?? '',
|
|
$item->address_line_1 ?? '',
|
|
$item->address_line_2 ?? '',
|
|
$item->address_landmark ?? '',
|
|
$item->address_state ?? '',
|
|
$item->address_city ?? '',
|
|
$item->address_pin_code ?? '',
|
|
$item->pickup_type ?? '',
|
|
$item->pickup_building ?? '',
|
|
$item->pickup_line_1 ?? '',
|
|
$item->pickup_line_2 ?? '',
|
|
$item->pickup_landmark ?? '',
|
|
$item->pickup_state ?? '',
|
|
$item->pickup_city ?? '',
|
|
$item->pickup_pin_code ?? '',
|
|
$item->status ?? '',
|
|
$item->approved_at ?? '',
|
|
$item->l1_approved_at ?? '',
|
|
$item->l2_approved_at ?? '',
|
|
$item->l3_approved_at ?? '',
|
|
$item->approval_reason ?? '',
|
|
$item->dispatch_at ?? '',
|
|
$item->rejected_at ?? '',
|
|
$item->rejected_reason ?? '',
|
|
$item->created_at ?? '',
|
|
// New fields
|
|
$item->order_no ?? '',
|
|
$item->invoice_no ?? '',
|
|
$item->courier_name ?? '',
|
|
$item->lr_no ?? '',
|
|
$item->lr_date ?? '',
|
|
];
|
|
|
|
fputcsv($file, $row);
|
|
}
|
|
fclose($file);
|
|
};
|
|
return Response::stream($callback, 200, $headers);
|
|
}
|
|
|
|
public function depotandtmmapping(Request $request)
|
|
{
|
|
$depot = DB::table('team3_neblogistics_depot')->select('id', 'name')->get();
|
|
|
|
return $this->view('depotandtmmapping')->with([
|
|
'title' => 'Depot & TM Mapping',
|
|
'base_url' => $this->_base_url,
|
|
'depot' => $depot,
|
|
'buttons' => $this->get_list_buttons(),
|
|
]);
|
|
}
|
|
|
|
public function abmapprove(Request $request)
|
|
{
|
|
$submission_id = $request->query('submission_id');
|
|
return redirect('/neblogisticreport/abmapprovereject?submission_id=' . $submission_id);
|
|
|
|
if (!$submission_id) {
|
|
return view('neblogisticreport.abmapprove')->with([
|
|
'success' => false,
|
|
'message' => 'Submission ID is required',
|
|
'submission_id' => null
|
|
]);
|
|
}
|
|
|
|
// Log the approval attempt
|
|
Log::info('ABM approval attempt', [
|
|
'submission_id' => $submission_id,
|
|
'ip_address' => $request->ip(),
|
|
'user_agent' => $request->userAgent()
|
|
]);
|
|
|
|
// Check if the record exists and get current status
|
|
$record = DB::table('neblogistic')
|
|
->where('submission_id', $submission_id)
|
|
->first();
|
|
|
|
//echo '<pre>'; print_r($record); exit;
|
|
|
|
if (!$record) {
|
|
Log::warning('ABM approval failed: Record not found', ['submission_id' => $submission_id]);
|
|
return view('neblogisticreport.abmapprove')->with([
|
|
'success' => false,
|
|
'message' => 'Record not found with the provided submission ID',
|
|
'submission_id' => $submission_id
|
|
]);
|
|
}
|
|
|
|
// Check if status can be changed to L1 Approved
|
|
if ($record->status === 'L1 Approved') {
|
|
Log::info('ABM approval skipped: Already approved', [
|
|
'submission_id' => $submission_id,
|
|
'current_status' => $record->status
|
|
]);
|
|
// return view('neblogisticreport.abmapprove')->with([
|
|
// 'success' => false,
|
|
// 'message' => 'Status is already L1 Approved',
|
|
// 'submission_id' => $submission_id,
|
|
// 'record' => $record
|
|
// ]);
|
|
return view('neblogisticreport.abmapprove')->with([
|
|
'success' => true,
|
|
'message' => 'Status successfully updated to L1 Approved for submission ID: ' . $submission_id,
|
|
'submission_id' => $submission_id,
|
|
'record' => $record,
|
|
'previous_status' => $record->status,
|
|
'new_status' => 'L1 Approved'
|
|
]);
|
|
}
|
|
|
|
// Check if the current status allows approval
|
|
$allowedStatuses = ['Requested','Rejected'];
|
|
if (!in_array($record->status, $allowedStatuses)) {
|
|
Log::warning('ABM approval failed: Invalid status for approval', [
|
|
'submission_id' => $submission_id,
|
|
'current_status' => $record->status,
|
|
'allowed_statuses' => $allowedStatuses
|
|
]);
|
|
return view('neblogisticreport.abmapprove')->with([
|
|
'success' => false,
|
|
'message' => 'Current status "' . $record->status . '" does not allow approval to L1 Approved',
|
|
'submission_id' => $submission_id,
|
|
'record' => $record
|
|
]);
|
|
}
|
|
|
|
// Update the status
|
|
$approveUpdate = [
|
|
'status' => 'L1 Approved',
|
|
'l1_approved_at' => date("Y-m-d H:i:s", strtotime("now")),
|
|
];
|
|
$oldDataArray = json_decode(json_encode($record), true);
|
|
$updated = DB::table('neblogistic')
|
|
->where('submission_id', $submission_id)
|
|
->update($approveUpdate);
|
|
|
|
if ($updated) {
|
|
NeblogisticAuditService::logUpdate(
|
|
$record->id,
|
|
$oldDataArray,
|
|
$approveUpdate,
|
|
null,
|
|
$request
|
|
);
|
|
Log::info('ABM approval successful', [
|
|
'submission_id' => $submission_id,
|
|
'previous_status' => $record->status,
|
|
'new_status' => 'L1 Approved'
|
|
]);
|
|
|
|
return view('neblogisticreport.abmapprove')->with([
|
|
'success' => true,
|
|
'message' => 'Status successfully updated to L1 Approved for submission ID: ' . $submission_id,
|
|
'submission_id' => $submission_id,
|
|
'record' => $record,
|
|
'previous_status' => $record->status,
|
|
'new_status' => 'L1 Approved'
|
|
]);
|
|
} else {
|
|
Log::error('ABM approval failed: Database update failed', [
|
|
'submission_id' => $submission_id
|
|
]);
|
|
return view('neblogisticreport.abmapprove')->with([
|
|
'success' => false,
|
|
'message' => 'Failed to update status. Please try again.',
|
|
'submission_id' => $submission_id,
|
|
'record' => $record
|
|
]);
|
|
}
|
|
}
|
|
|
|
public function abmapprovereject(Request $request)
|
|
{
|
|
|
|
// $exists = DB::table('neblogistic')
|
|
// ->where('submission_id', $request->query('submission_id'))
|
|
// ->where('status', 'L1 Approved')
|
|
// ->exists();
|
|
|
|
// if ($exists) {
|
|
// return view('neblogisticreport.abmapprovereject')->with([
|
|
// 'success' => false,
|
|
// 'message' => 'Record is already marked as approved',
|
|
// 'submission_id' => $request->query('submission_id')
|
|
// ]);
|
|
// }
|
|
|
|
$submission_id = $request->query('submission_id');
|
|
if (!$submission_id) {
|
|
return view('neblogisticreport.abmapprovereject')->with([
|
|
'success' => false,
|
|
'message' => 'Submission ID is required',
|
|
'submission_id' => null
|
|
]);
|
|
}
|
|
|
|
// Check if the record exists and get current status
|
|
$record = DB::table('neblogistic')
|
|
->where('submission_id', $submission_id)
|
|
->first();
|
|
//echo $submission_id; exit;
|
|
if (!$record) {
|
|
Log::warning('ABM approval/rejection failed: Record not found', ['submission_id' => $submission_id]);
|
|
return view('neblogisticreport.abmapprovereject')->with([
|
|
'success' => false,
|
|
'message' => 'Record not found with the provided submission ID',
|
|
'submission_id' => $submission_id
|
|
]);
|
|
}
|
|
|
|
|
|
|
|
// Check if the current status allows approval/rejection
|
|
$allowedStatuses = ['Requested', 'L1 Approved']; //'Rejected',
|
|
if (!in_array($record->status, $allowedStatuses)) {
|
|
Log::warning('ABM approval/rejection failed: Invalid status', [
|
|
'submission_id' => $submission_id,
|
|
'current_status' => $record->status,
|
|
'allowed_statuses' => $allowedStatuses
|
|
]);
|
|
return view('neblogisticreport.abmapprovereject')->with([
|
|
'success' => false,
|
|
'message' => 'Current status "' . $record->status . '" does not allow approval or rejection',
|
|
'submission_id' => $submission_id,
|
|
'record' => $record
|
|
]);
|
|
}
|
|
|
|
|
|
$partition = $this->normalizeNapPartition($request->query('partition'));
|
|
$form_id = $this->resolveNapFormId($request->query('form_id'));
|
|
$requestUserId = $request->query('abm_user_id') ?: $request->query('user_id');
|
|
$resolvedUserId = $this->resolveNapApproverUserId($requestUserId, (string) $submission_id, $form_id, $partition, $record);
|
|
|
|
// Show the review page for GET request
|
|
return view('neblogisticreport.abmapprovereject')->with([
|
|
'submission_id' => $submission_id,
|
|
'record' => $record,
|
|
'show_form' => true,
|
|
'user_id' => $resolvedUserId,
|
|
'form_id' => $form_id,
|
|
'partition' => $partition,
|
|
]);
|
|
}
|
|
|
|
public function postabmapproverejectajax(Request $request)
|
|
{
|
|
$userId = $request->input('user_id') ?: $request->input('abm_user_id');
|
|
$request->merge([
|
|
'user_id' => $userId,
|
|
'form_id' => $this->resolveNapFormId($request->input('form_id')),
|
|
'partition' => $this->normalizeNapPartition($request->input('partition')),
|
|
]);
|
|
|
|
return $this->postupdatenapapprovalstatusnosql($request);
|
|
}
|
|
|
|
// new function to view
|
|
public function updatenapapprovalstatus(Request $request){
|
|
$submission_id = $request->query('submission_id');
|
|
$form_id = $request->query('form_id');
|
|
$user_id = $request->query('user_id');
|
|
$partition = $request->query('partition');
|
|
|
|
// $exists = DB::table('neblogistic')
|
|
// ->where('submission_id', $request->query('submission_id'))
|
|
// ->where('status', 'L1 Approved')
|
|
// ->exists();
|
|
|
|
// if ($exists) {
|
|
// return view('neblogisticreport.abmapprovereject')->with([
|
|
// 'success' => false,
|
|
// 'message' => 'Record is already marked as approved',
|
|
// 'submission_id' => $request->query('submission_id')
|
|
// ]);
|
|
// }
|
|
|
|
$submission_id = $request->query('submission_id');
|
|
if (!$submission_id) {
|
|
return view('neblogisticreport.napapprovalstatus')->with([
|
|
'success' => false,
|
|
'message' => 'Submission ID is required',
|
|
'submission_id' => null
|
|
]);
|
|
}
|
|
|
|
// Check if the record exists and get current status
|
|
$record = DB::table('neblogistic')
|
|
->where('submission_id', $submission_id)
|
|
->first();
|
|
//echo $submission_id; exit;
|
|
if (!$record) {
|
|
Log::warning('ABM approval/rejection failed: Record not found', ['submission_id' => $submission_id]);
|
|
return view('neblogisticreport.napapprovalstatus')->with([
|
|
'success' => false,
|
|
'message' => 'Record not found with the provided submission ID',
|
|
'submission_id' => $submission_id
|
|
]);
|
|
}
|
|
|
|
|
|
|
|
// Check if the current status allows approval/rejection
|
|
$allowedStatuses = ['Requested', 'L1 Approved']; //'Rejected',
|
|
if (!in_array($record->status, $allowedStatuses)) {
|
|
Log::warning('ABM approval/rejection failed: Invalid status', [
|
|
'submission_id' => $submission_id,
|
|
'current_status' => $record->status,
|
|
'allowed_statuses' => $allowedStatuses
|
|
]);
|
|
return view('neblogisticreport.napapprovalstatus')->with([
|
|
'success' => false,
|
|
'message' => 'Current status "' . $record->status . '" does not allow approval or rejection',
|
|
'submission_id' => $submission_id,
|
|
'record' => $record
|
|
]);
|
|
}
|
|
|
|
|
|
// Show the review page for GET request
|
|
$partition = $this->normalizeNapPartition($partition);
|
|
$form_id = $this->resolveNapFormId($form_id);
|
|
$resolvedUserId = $this->resolveNapApproverUserId($user_id, (string) $submission_id, $form_id, $partition, $record);
|
|
|
|
return view('neblogisticreport.napapprovalstatus')->with([
|
|
'submission_id' => $submission_id,
|
|
'record' => $record,
|
|
'show_form' => true,
|
|
'user_id'=> $resolvedUserId,
|
|
'form_id'=> $form_id,
|
|
'partition' => $partition
|
|
]);
|
|
}
|
|
|
|
// new function to update in nosql
|
|
public function postupdatenapapprovalstatusnosql(Request $request)
|
|
{
|
|
$submission_id = $request->input('submission_id');
|
|
$form_id = $request->input('form_id');
|
|
$user_id = $request->input('user_id');
|
|
$partition = $request->input('partition');
|
|
// $parts = explode('-', $partition);
|
|
// $partition_extract = $parts[0] . '-' . $parts[1];
|
|
|
|
$action = $request->input('action');
|
|
$rejection_reason = $request->input('rejection_reason');
|
|
|
|
if (!$submission_id) { return response()->json([ 'success' => false, 'message' => 'Submission ID is required' ], 400); }
|
|
|
|
$partition = $this->normalizeNapPartition($partition);
|
|
$form_id = $this->resolveNapFormId($form_id);
|
|
|
|
$record = DB::table('neblogistic')->where('submission_id', $submission_id)->first();
|
|
if (!$record) {
|
|
Log::warning('ABM approval/rejection AJAX failed: Record not found', ['submission_id' => $submission_id]);
|
|
return response()->json(['success' => false, 'message' => 'Record not found with the provided submission ID'], 404);
|
|
}
|
|
|
|
$user_id = $this->resolveNapApproverUserId($user_id, $submission_id, $form_id, $partition, $record);
|
|
if (!$this->isValidNapApproverUserId($user_id)) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'A valid approver user_id is required.',
|
|
], 400);
|
|
}
|
|
|
|
Log::info('ABM approval/rejection AJAX attempt', [ 'submission_id' => $submission_id, 'action' => $action, 'resolved_user_id' => $user_id, 'ip_address' => $request->ip(), 'user_agent' => $request->userAgent() ]);
|
|
|
|
$allowedStatuses = ['Requested', 'L1 Approved'];
|
|
if (!in_array($record->status, $allowedStatuses)) {
|
|
Log::warning('ABM approval/rejection AJAX failed: Invalid status', [ 'submission_id' => $submission_id, 'current_status' => $record->status, 'allowed_statuses' => $allowedStatuses ]);
|
|
return response()->json([ 'success' => false, 'message' => 'Current status "' . $record->status . '" does not allow approval or rejection' ], 400);
|
|
}
|
|
|
|
if ($action === 'approve') {
|
|
$response = LambdaRequest::postrequest(
|
|
'form',
|
|
'formentity/approvereject',
|
|
[
|
|
'submission_id' => $submission_id,
|
|
'form_id' => $form_id,
|
|
'action' => 'approve',
|
|
'user_id' => $user_id,
|
|
'partition' => $partition,
|
|
]
|
|
);
|
|
Log::info('ABM approval form response', [
|
|
'submission_id' => $submission_id,
|
|
'response' => $response,
|
|
]);
|
|
|
|
if (!$this->isFormApiSuccess($response)) {
|
|
Log::warning('ABM approval aborted: form approvereject failed', [
|
|
'submission_id' => $submission_id,
|
|
'user_id' => $user_id,
|
|
'response' => $response,
|
|
]);
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Form approval failed. MySQL status was not updated. Please try again.',
|
|
], 502);
|
|
}
|
|
|
|
$approveUpdate = [
|
|
'status' => 'L1 Approved',
|
|
'l1_approved_at' => date("Y-m-d H:i:s", strtotime("now")),
|
|
];
|
|
$oldDataArray = json_decode(json_encode($record), true);
|
|
$updated = DB::table('neblogistic')
|
|
->where('submission_id', $submission_id)
|
|
->update($approveUpdate);
|
|
|
|
if (!$updated) {
|
|
Log::error('ABM approval AJAX failed: Database update failed after form success', [
|
|
'submission_id' => $submission_id,
|
|
]);
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Form approved but failed to update request status. Please contact support.',
|
|
], 500);
|
|
}
|
|
|
|
NeblogisticAuditService::logUpdate(
|
|
$record->id,
|
|
$oldDataArray,
|
|
$approveUpdate,
|
|
null,
|
|
$request
|
|
);
|
|
Log::info('ABM approval AJAX successful', [
|
|
'submission_id' => $submission_id,
|
|
'previous_status' => $record->status,
|
|
'new_status' => 'L1 Approved',
|
|
]);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => 'Request has been successfully approved',
|
|
'action' => 'approve',
|
|
'previous_status' => $record->status,
|
|
'new_status' => 'L1 Approved',
|
|
]);
|
|
}
|
|
|
|
if ($action === 'reject') {
|
|
if (empty($rejection_reason)) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Rejection reason is required',
|
|
], 400);
|
|
}
|
|
|
|
$response = LambdaRequest::postrequest(
|
|
'form',
|
|
'formentity/approvereject',
|
|
[
|
|
'submission_id' => $submission_id,
|
|
'form_id' => $form_id,
|
|
'action' => 'reject',
|
|
'user_id' => $user_id,
|
|
'partition' => $partition,
|
|
'reason' => $rejection_reason,
|
|
]
|
|
);
|
|
Log::info('ABM rejection form response', [
|
|
'submission_id' => $submission_id,
|
|
'response' => $response,
|
|
]);
|
|
|
|
if (!$this->isFormApiSuccess($response)) {
|
|
Log::warning('ABM rejection aborted: form approvereject failed', [
|
|
'submission_id' => $submission_id,
|
|
'user_id' => $user_id,
|
|
'response' => $response,
|
|
]);
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Form rejection failed. MySQL status was not updated. Please try again.',
|
|
], 502);
|
|
}
|
|
|
|
$rejectUpdate = [
|
|
'status' => 'Rejected',
|
|
'rejected_at' => date("Y-m-d H:i:s", strtotime("now")),
|
|
'rejected_reason' => $rejection_reason,
|
|
];
|
|
$oldDataArray = json_decode(json_encode($record), true);
|
|
$updated = DB::table('neblogistic')
|
|
->where('submission_id', $submission_id)
|
|
->update($rejectUpdate);
|
|
|
|
if (!$updated) {
|
|
Log::error('ABM rejection AJAX failed: Database update failed after form success', [
|
|
'submission_id' => $submission_id,
|
|
]);
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Form rejected but failed to update request status. Please contact support.',
|
|
], 500);
|
|
}
|
|
|
|
NeblogisticAuditService::logUpdate(
|
|
$record->id,
|
|
$oldDataArray,
|
|
$rejectUpdate,
|
|
null,
|
|
$request
|
|
);
|
|
Log::info('ABM rejection AJAX successful', [
|
|
'submission_id' => $submission_id,
|
|
'previous_status' => $record->status,
|
|
'new_status' => 'Rejected',
|
|
'rejection_reason' => $rejection_reason,
|
|
]);
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'message' => 'Request has been successfully rejected',
|
|
'action' => 'reject',
|
|
'previous_status' => $record->status,
|
|
'new_status' => 'Rejected',
|
|
'rejection_reason' => $rejection_reason,
|
|
]);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Invalid action specified',
|
|
], 400);
|
|
}
|
|
|
|
public function import(Request $request)
|
|
{
|
|
return view($this->_viewname . '.import')->with([
|
|
'title' => 'Import Neblogistic Data',
|
|
'base_url' => $this->_base_url,
|
|
'buttons' => $this->get_list_buttons(),
|
|
]);
|
|
}
|
|
|
|
public function postimport(Request $request)
|
|
{
|
|
try {
|
|
$request->validate([
|
|
'import_file' => 'required|file|mimes:xlsx,xls,csv|max:10240',
|
|
]);
|
|
|
|
$file = $request->file('import_file');
|
|
$extension = $file->getClientOriginalExtension();
|
|
|
|
$updatedCount = 0;
|
|
$notFoundCount = 0;
|
|
$errorCount = 0;
|
|
$errors = [];
|
|
|
|
if (in_array($extension, ['xlsx', 'xls'])) {
|
|
// Handle Excel files
|
|
$data = Excel::toArray([], $file);
|
|
|
|
if (empty($data) || empty($data[0])) {
|
|
return redirect()->back()->with('error', 'The file is empty or invalid.');
|
|
}
|
|
|
|
$rows = $data[0];
|
|
$headers = array_shift($rows); // First row is headers
|
|
|
|
// Find the index of "Connect od Order" column
|
|
$connectOrderIndex = null;
|
|
foreach ($headers as $index => $header) {
|
|
if (trim(strtolower($header)) === 'connect od order') {
|
|
$connectOrderIndex = $index;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ($connectOrderIndex === null) {
|
|
return redirect()->back()->with('error', 'Column "Connect od Order" not found in the file.');
|
|
}
|
|
|
|
// Map all other columns for update
|
|
$columnMapping = [];
|
|
$lrDateIndex = null;
|
|
foreach ($headers as $index => $header) {
|
|
$columnMapping[$index] = trim((string) $header);
|
|
if ($this->mapColumnToDbField($columnMapping[$index]) === 'lr_date') {
|
|
$lrDateIndex = $index;
|
|
}
|
|
}
|
|
|
|
$sheet = IOFactory::load($file->getRealPath())->getActiveSheet();
|
|
|
|
// Process each row
|
|
foreach ($rows as $rowIndex => $row) {
|
|
try {
|
|
$connectOrderId = trim($row[$connectOrderIndex] ?? '');
|
|
|
|
if (empty($connectOrderId)) {
|
|
continue; // Skip empty rows
|
|
}
|
|
|
|
// Check if record exists
|
|
$record = DB::table('neblogistic')->where('id', $connectOrderId)->first();
|
|
|
|
if (!$record) {
|
|
$notFoundCount++;
|
|
$errors[] = "Row " . ($rowIndex + 2) . ": Record with ID {$connectOrderId} not found.";
|
|
continue;
|
|
}
|
|
|
|
// Build update data from the row
|
|
$updateData = [];
|
|
foreach ($row as $colIndex => $value) {
|
|
if ($colIndex === $connectOrderIndex) {
|
|
continue; // Skip the ID column
|
|
}
|
|
|
|
$columnName = $columnMapping[$colIndex] ?? null;
|
|
if ($columnName && !$this->isBlankImportValue($value)) {
|
|
$dbField = $this->mapColumnToDbField($columnName);
|
|
if ($dbField) {
|
|
if ($dbField === 'lr_date' && $lrDateIndex === $colIndex) {
|
|
$colLetter = Coordinate::stringFromColumnIndex($colIndex + 1);
|
|
$cellValue = $sheet->getCell($colLetter . ($rowIndex + 2))->getFormattedValue();
|
|
$parsedDate = $this->parseLrDate($cellValue);
|
|
if ($parsedDate === null) {
|
|
continue;
|
|
}
|
|
$updateData[$dbField] = $parsedDate;
|
|
continue;
|
|
}
|
|
|
|
$updateData[$dbField] = trim((string) $value);
|
|
}
|
|
}
|
|
}
|
|
|
|
// echo '<pre>'; print_r($updateData); exit;
|
|
// Update the record if there's data to update
|
|
if (!empty($updateData)) {
|
|
// Get old data before update for audit trail
|
|
$oldRecord = DB::table('neblogistic')->where('id', $connectOrderId)->first();
|
|
$oldDataArray = $oldRecord ? json_decode(json_encode($oldRecord), true) : null;
|
|
|
|
DB::table('neblogistic')
|
|
->where('id', $connectOrderId)
|
|
->update($updateData);
|
|
|
|
// Log UPDATE operation
|
|
NeblogisticAuditService::logUpdate(
|
|
$connectOrderId,
|
|
$oldDataArray,
|
|
$updateData,
|
|
null, // Let service calculate changed fields
|
|
$request
|
|
);
|
|
|
|
$updatedCount++;
|
|
}
|
|
|
|
} catch (\Exception $e) {
|
|
$errorCount++;
|
|
$errors[] = "Row " . ($rowIndex + 2) . ": " . $e->getMessage();
|
|
Log::error('Import row error', [
|
|
'row' => $rowIndex + 2,
|
|
'error' => $e->getMessage()
|
|
]);
|
|
}
|
|
}
|
|
|
|
} elseif ($extension === 'csv') {
|
|
// Handle CSV files
|
|
$csv = Reader::createFromPath($file->getRealPath(), 'r');
|
|
$csv->setHeaderOffset(0);
|
|
|
|
$headers = $csv->getHeader();
|
|
$records = $csv->getRecords();
|
|
|
|
// Find "Connect od Order" in headers
|
|
$connectOrderKey = null;
|
|
foreach ($headers as $header) {
|
|
if (trim(strtolower($header)) === 'connect od order') {
|
|
$connectOrderKey = $header;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!$connectOrderKey) {
|
|
return redirect()->back()->with('error', 'Column "Connect od Order" not found in the file.');
|
|
}
|
|
|
|
// Process each record
|
|
$rowIndex = 0;
|
|
foreach ($records as $row) {
|
|
$rowIndex++;
|
|
try {
|
|
$connectOrderId = trim($row[$connectOrderKey] ?? '');
|
|
|
|
if (empty($connectOrderId)) {
|
|
continue;
|
|
}
|
|
|
|
// Check if record exists
|
|
$record = DB::table('neblogistic')->where('id', $connectOrderId)->first();
|
|
|
|
if (!$record) {
|
|
$notFoundCount++;
|
|
$errors[] = "Row " . ($rowIndex + 1) . ": Record with ID {$connectOrderId} not found.";
|
|
continue;
|
|
}
|
|
|
|
// Build update data
|
|
$updateData = [];
|
|
foreach ($row as $columnName => $value) {
|
|
if ($columnName === $connectOrderKey) {
|
|
continue; // Skip the ID column
|
|
}
|
|
|
|
if (!$this->isBlankImportValue($value)) {
|
|
$dbField = $this->mapColumnToDbField($columnName);
|
|
if ($dbField) {
|
|
if ($dbField === 'lr_date') {
|
|
$parsedDate = $this->parseLrDate($value);
|
|
if ($parsedDate === null) {
|
|
continue;
|
|
}
|
|
$updateData[$dbField] = $parsedDate;
|
|
continue;
|
|
}
|
|
|
|
$updateData[$dbField] = trim((string) $value);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update the record
|
|
if (!empty($updateData)) {
|
|
$oldRecord = DB::table('neblogistic')->where('id', $connectOrderId)->first();
|
|
$oldDataArray = $oldRecord ? json_decode(json_encode($oldRecord), true) : null;
|
|
|
|
DB::table('neblogistic')
|
|
->where('id', $connectOrderId)
|
|
->update($updateData);
|
|
|
|
NeblogisticAuditService::logUpdate(
|
|
$connectOrderId,
|
|
$oldDataArray,
|
|
$updateData,
|
|
null,
|
|
$request
|
|
);
|
|
$updatedCount++;
|
|
}
|
|
|
|
} catch (\Exception $e) {
|
|
$errorCount++;
|
|
$errors[] = "Row " . ($rowIndex + 1) . ": " . $e->getMessage();
|
|
Log::error('Import row error', [
|
|
'row' => $rowIndex + 1,
|
|
'error' => $e->getMessage()
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
|
|
$message = "Import completed. Updated: {$updatedCount}, Not Found: {$notFoundCount}, Errors: {$errorCount}";
|
|
|
|
if (!empty($errors) && count($errors) <= 20) {
|
|
$message .= "\n\nErrors:\n" . implode("\n", array_slice($errors, 0, 20));
|
|
}
|
|
|
|
Log::info('Import completed', [
|
|
'updated' => $updatedCount,
|
|
'not_found' => $notFoundCount,
|
|
'errors' => $errorCount
|
|
]);
|
|
|
|
return redirect()->back()->with('message', $message);
|
|
|
|
} catch (\Exception $e) {
|
|
Log::error('Import error', ['error' => $e->getMessage()]);
|
|
return redirect()->back()->with('error', 'Import failed: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
private function isBlankImportValue($value)
|
|
{
|
|
return $value === null || trim((string) $value) === '';
|
|
}
|
|
|
|
private function parseLrDate($value)
|
|
{
|
|
if ($this->isBlankImportValue($value)) {
|
|
return null;
|
|
}
|
|
|
|
if (is_int($value) || is_float($value)) {
|
|
try {
|
|
return Carbon::instance(
|
|
ExcelDate::excelToDateTimeObject((float) $value)
|
|
)->format('Y-m-d');
|
|
} catch (\Exception $e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
$trimmedValue = trim((string) $value);
|
|
|
|
if (is_numeric($trimmedValue) && !preg_match('/[\/\.\-]/', $trimmedValue)) {
|
|
try {
|
|
return Carbon::instance(
|
|
ExcelDate::excelToDateTimeObject((float) $trimmedValue)
|
|
)->format('Y-m-d');
|
|
} catch (\Exception $e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
foreach (['d/m/Y', 'd.m.Y', 'd-m-Y', 'Y-m-d'] as $format) {
|
|
$date = \DateTime::createFromFormat($format, $trimmedValue);
|
|
if ($date && $date->format($format) === $trimmedValue) {
|
|
return $date->format('Y-m-d');
|
|
}
|
|
}
|
|
|
|
try {
|
|
return Carbon::parse($trimmedValue)->format('Y-m-d');
|
|
} catch (\Exception $e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private function mapColumnToDbField($columnName)
|
|
{
|
|
// Map Excel/CSV column names to database field names (case-insensitive)
|
|
// Only allow updating these specific fields
|
|
$mapping = [
|
|
'connect od order' => 'id',
|
|
'order no' => 'order_no',
|
|
'invoice no' => 'invoice_no',
|
|
'courier name' => 'courier_name',
|
|
'lr no' => 'lr_no',
|
|
'lr date' => 'lr_date',
|
|
'status' => 'status',
|
|
];
|
|
|
|
$normalizedColumn = strtolower(trim($columnName));
|
|
return $mapping[$normalizedColumn] ?? null;
|
|
}
|
|
|
|
public function viewdoctordetails(Request $request)
|
|
{
|
|
$data = DB::table('neblogistic')
|
|
->where('id', $request->id)
|
|
->first();
|
|
|
|
if (!$data) {
|
|
return response()->json([
|
|
'success' => false,
|
|
'message' => 'Record not found'
|
|
], 404);
|
|
}
|
|
|
|
return response()->json([
|
|
'success' => true,
|
|
'data' => $data
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Neblogistic NAP approval: resolve acting approver when email link has vacant/missing user_id.
|
|
*/
|
|
protected function isFormApiSuccess($response): bool
|
|
{
|
|
return is_object($response) && ($response->status ?? '') === 'success';
|
|
}
|
|
|
|
/**
|
|
* True when value is a real mailbox (rejects empty / Vacant placeholders).
|
|
*/
|
|
protected function isValidNeblogisticEmail($email): bool
|
|
{
|
|
$email = trim((string) $email);
|
|
if ($email === '' || stripos($email, 'vacant') !== false) {
|
|
return false;
|
|
}
|
|
return (bool) filter_var($email, FILTER_VALIDATE_EMAIL);
|
|
}
|
|
|
|
/**
|
|
* Send a mailable without letting invalid Vacant/CC addresses 500 the request.
|
|
* Returns a short user-facing warning, or null when send succeeded / nothing to warn.
|
|
*
|
|
* @param mixed $mailable
|
|
* @param string|null $to
|
|
* @param string|null $cc
|
|
* @param array $context
|
|
*/
|
|
protected function sendNeblogisticMailSafely($mailable, $to, $cc = null, array $context = []): ?string
|
|
{
|
|
$validTo = $this->isValidNeblogisticEmail($to) ? trim((string) $to) : null;
|
|
$validCc = $this->isValidNeblogisticEmail($cc) ? trim((string) $cc) : null;
|
|
$warnings = [];
|
|
|
|
if ($to !== null && trim((string) $to) !== '' && $validTo === null) {
|
|
$warnings[] = 'Notification email was not sent because the recipient email is missing or invalid (e.g. Vacant).';
|
|
Log::warning('Neblogistic email skipped: invalid to address', $context + [
|
|
'to' => $to,
|
|
'cc' => $cc,
|
|
]);
|
|
} elseif ($cc !== null && trim((string) $cc) !== '' && $validCc === null) {
|
|
$warnings[] = 'ABM notification was skipped because the ABM email is missing or invalid (e.g. Vacant).';
|
|
Log::warning('Neblogistic email CC skipped: invalid cc address', $context + [
|
|
'to' => $to,
|
|
'cc' => $cc,
|
|
]);
|
|
}
|
|
|
|
if ($validTo === null) {
|
|
return $warnings[0] ?? 'Notification email was not sent because no valid recipient email was found.';
|
|
}
|
|
|
|
try {
|
|
$pending = Mail::to($validTo);
|
|
if ($validCc !== null) {
|
|
$pending->cc($validCc);
|
|
}
|
|
$pending->send($mailable);
|
|
} catch (\Swift_RfcComplianceException $e) {
|
|
Log::error('Neblogistic email RFC error', $context + [
|
|
'to' => $validTo,
|
|
'cc' => $validCc,
|
|
'message' => $e->getMessage(),
|
|
]);
|
|
return 'Notification email could not be sent due to an invalid email address.';
|
|
} catch (\Throwable $e) {
|
|
Log::error('Neblogistic email failed', $context + [
|
|
'to' => $validTo,
|
|
'cc' => $validCc,
|
|
'message' => $e->getMessage(),
|
|
]);
|
|
return 'Notification email could not be sent.';
|
|
}
|
|
|
|
return $warnings[0] ?? null;
|
|
}
|
|
|
|
protected function normalizeNapPartition(?string $partition): string
|
|
{
|
|
$partition = trim((string) $partition);
|
|
if ($partition === '' || strpos($partition, 'rapport-') !== 0) {
|
|
return (string) config('neblogistic.partition', 'rapport-team3');
|
|
}
|
|
return $partition;
|
|
}
|
|
|
|
protected function resolveNapFormId($formId): string
|
|
{
|
|
$formId = trim((string) $formId);
|
|
if ($formId === '') {
|
|
return (string) config('neblogistic.form_id', '1750914801-153443b9-94d0-4dcb-b3f3-4fa11588a0a9');
|
|
}
|
|
return $formId;
|
|
}
|
|
|
|
protected function isValidNapApproverUserId($userId): bool
|
|
{
|
|
if ($userId === null || $userId === '') {
|
|
return false;
|
|
}
|
|
$userId = trim((string) $userId);
|
|
if ($userId === '' || $userId === 'vacant' || strpos($userId, 'vacant-') === 0) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
protected function resolveNapApproverUserId($requestUserId, string $submissionId, string $formId, string $partition, $record = null): ?string
|
|
{
|
|
if ($this->isValidNapApproverUserId($requestUserId)) {
|
|
return trim((string) $requestUserId);
|
|
}
|
|
|
|
if ($record && !empty($record->abm_user_id) && $this->isValidNapApproverUserId($record->abm_user_id)) {
|
|
Log::info('NAP approver resolved from neblogistic.abm_user_id', [
|
|
'submission_id' => $submissionId,
|
|
'user_id' => $record->abm_user_id,
|
|
]);
|
|
return (string) $record->abm_user_id;
|
|
}
|
|
|
|
$fromSubmission = $this->resolveNapApproverFromSubmissionDetails($submissionId, $formId, $partition);
|
|
if ($this->isValidNapApproverUserId($fromSubmission)) {
|
|
Log::info('NAP approver resolved from submission workflow', [
|
|
'submission_id' => $submissionId,
|
|
'user_id' => $fromSubmission,
|
|
]);
|
|
return $fromSubmission;
|
|
}
|
|
|
|
$fromApprovals = $this->resolveNapApproverFromApprovalApi($submissionId, $formId, $partition);
|
|
if ($this->isValidNapApproverUserId($fromApprovals)) {
|
|
Log::info('NAP approver resolved from approval records', [
|
|
'submission_id' => $submissionId,
|
|
'user_id' => $fromApprovals,
|
|
]);
|
|
return $fromApprovals;
|
|
}
|
|
|
|
if ($record && !empty($record->abm_email)) {
|
|
$fromEmail = $this->resolveNapApproverFromAbmEmail($record->abm_email, $partition);
|
|
if ($this->isValidNapApproverUserId($fromEmail)) {
|
|
Log::info('NAP approver resolved from abm_email', [
|
|
'submission_id' => $submissionId,
|
|
'abm_email' => $record->abm_email,
|
|
'user_id' => $fromEmail,
|
|
]);
|
|
return $fromEmail;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
protected function resolveNapApproverFromSubmissionDetails(string $submissionId, string $formId, string $partition): ?string
|
|
{
|
|
try {
|
|
$timeout = (int) config('neblogistic.http_timeout', 120);
|
|
$response = LambdaRequest::getrequest(
|
|
'form',
|
|
'formentity/getsubmissiondetails',
|
|
[
|
|
'partition' => $partition,
|
|
'form_id' => $formId,
|
|
'id' => $submissionId,
|
|
],
|
|
'',
|
|
$timeout > 0 ? $timeout : null
|
|
);
|
|
|
|
if (!is_object($response) || ($response->status ?? '') !== 'success') {
|
|
return null;
|
|
}
|
|
|
|
$submission = $response->data->submission ?? null;
|
|
if (!is_object($submission)) {
|
|
return null;
|
|
}
|
|
|
|
if (!empty($submission->workflow_next_approver) && $this->isValidNapApproverUserId($submission->workflow_next_approver)) {
|
|
return (string) $submission->workflow_next_approver;
|
|
}
|
|
|
|
$approvers = $submission->workflow_approvers ?? [];
|
|
if (is_array($approvers)) {
|
|
foreach ($approvers as $approverId) {
|
|
if ($this->isValidNapApproverUserId($approverId)) {
|
|
return (string) $approverId;
|
|
}
|
|
}
|
|
}
|
|
} catch (\Throwable $e) {
|
|
Log::warning('NAP approver: getsubmissiondetails failed', [
|
|
'submission_id' => $submissionId,
|
|
'error' => $e->getMessage(),
|
|
]);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
protected function resolveNapApproverFromApprovalApi(string $submissionId, string $formId, string $partition): ?string
|
|
{
|
|
try {
|
|
$token = $this->getNapServiceAccessToken($partition);
|
|
if (empty($token)) {
|
|
return null;
|
|
}
|
|
|
|
$response = LambdaRequest::postrequest(
|
|
'form',
|
|
'formentity/allapprovers',
|
|
[
|
|
'submission_id' => $submissionId,
|
|
'form_id' => $formId,
|
|
],
|
|
$token
|
|
);
|
|
|
|
if (!is_object($response) || ($response->status ?? '') !== 'success') {
|
|
return null;
|
|
}
|
|
|
|
$approvals = $response->data->approvals ?? [];
|
|
if (!is_array($approvals)) {
|
|
return null;
|
|
}
|
|
|
|
foreach ($approvals as $approval) {
|
|
$candidate = is_object($approval) ? ($approval->user_id ?? null) : ($approval['user_id'] ?? null);
|
|
$status = is_object($approval) ? ($approval->approval_status ?? '') : ($approval['approval_status'] ?? '');
|
|
if (!$this->isValidNapApproverUserId($candidate)) {
|
|
continue;
|
|
}
|
|
if (in_array($status, ['pending', 'unapproved', ''], true)) {
|
|
return (string) $candidate;
|
|
}
|
|
}
|
|
|
|
foreach ($approvals as $approval) {
|
|
$candidate = is_object($approval) ? ($approval->user_id ?? null) : ($approval['user_id'] ?? null);
|
|
if ($this->isValidNapApproverUserId($candidate)) {
|
|
return (string) $candidate;
|
|
}
|
|
}
|
|
} catch (\Throwable $e) {
|
|
Log::warning('NAP approver: allapprovers failed', [
|
|
'submission_id' => $submissionId,
|
|
'error' => $e->getMessage(),
|
|
]);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
protected function normalizeNapEmail(?string $email): string
|
|
{
|
|
return trim(strtolower((string) $email));
|
|
}
|
|
|
|
/**
|
|
* Partitions to try when resolving ABM email (request partition + email-domain hint).
|
|
*/
|
|
protected function napEmailLookupPartitions(string $partition, string $normalizedEmail): array
|
|
{
|
|
$partitions = [$this->normalizeNapPartition($partition)];
|
|
|
|
$at = strrpos($normalizedEmail, '@');
|
|
if ($at !== false) {
|
|
$host = substr($normalizedEmail, $at + 1);
|
|
$label = explode('.', $host)[0] ?? '';
|
|
if ($label !== '') {
|
|
$partitions[] = 'rapport-' . $label;
|
|
}
|
|
}
|
|
|
|
return array_values(array_unique($partitions));
|
|
}
|
|
|
|
protected function resolveNapApproverFromAbmEmail(string $abmEmail, string $partition): ?string
|
|
{
|
|
$normalizedEmail = $this->normalizeNapEmail($abmEmail);
|
|
if ($normalizedEmail === '') {
|
|
return null;
|
|
}
|
|
|
|
foreach ($this->napEmailLookupPartitions($partition, $normalizedEmail) as $candidatePartition) {
|
|
$domain = explode('-', $candidatePartition, 2)[1] ?? null;
|
|
if (!empty($domain)) {
|
|
$userId = DB::table('users')
|
|
->where('domain', $domain)
|
|
->whereRaw('LOWER(email) = ?', [$normalizedEmail])
|
|
->whereNotNull('user_id')
|
|
->where('user_id', '!=', '')
|
|
->orderBy('updated_at', 'desc')
|
|
->value('user_id');
|
|
|
|
if ($this->isValidNapApproverUserId($userId)) {
|
|
return (string) $userId;
|
|
}
|
|
}
|
|
|
|
$fromUms = $this->resolveNapApproverFromUmsEmail($normalizedEmail, $candidatePartition);
|
|
if ($this->isValidNapApproverUserId($fromUms)) {
|
|
return $fromUms;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
protected function resolveNapApproverFromUmsEmail(string $normalizedEmail, string $partition): ?string
|
|
{
|
|
$token = $this->getNapServiceAccessToken($partition);
|
|
if (empty($token)) {
|
|
$token = env('LAMBDA_ACCESS_TOKEN');
|
|
}
|
|
if (empty($token)) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
$response = LambdaRequest::getrequest('ums', 'users/get_all', [
|
|
'start' => 0,
|
|
'length' => 25,
|
|
'keyword' => $normalizedEmail,
|
|
'search' => json_encode([]),
|
|
], $token);
|
|
|
|
if (!is_object($response) || ($response->status ?? '') !== 'success') {
|
|
return null;
|
|
}
|
|
|
|
$items = $response->data->items ?? [];
|
|
if (!is_array($items)) {
|
|
return null;
|
|
}
|
|
|
|
foreach ($items as $item) {
|
|
$email = is_object($item) ? ($item->email ?? '') : ($item['email'] ?? '');
|
|
$id = is_object($item) ? ($item->id ?? null) : ($item['id'] ?? null);
|
|
if ($this->normalizeNapEmail($email) !== $normalizedEmail) {
|
|
continue;
|
|
}
|
|
if ($this->isValidNapApproverUserId($id)) {
|
|
return (string) $id;
|
|
}
|
|
}
|
|
} catch (\Throwable $e) {
|
|
Log::warning('NAP approver: UMS email lookup failed', [
|
|
'partition' => $partition,
|
|
'email' => $normalizedEmail,
|
|
'error' => $e->getMessage(),
|
|
]);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
protected function getNapServiceAccessToken(string $partition): ?string
|
|
{
|
|
$domain = explode('-', $partition, 2)[1] ?? null;
|
|
if (empty($domain)) {
|
|
return null;
|
|
}
|
|
|
|
$user = DB::table('users')
|
|
->select('access_token')
|
|
->where('domain', $domain)
|
|
->whereNotNull('access_token')
|
|
->where('access_token', '!=', '')
|
|
->orderBy('updated_at', 'desc')
|
|
->first();
|
|
|
|
return $user ? $user->access_token : null;
|
|
}
|
|
|
|
}
|