Changes
Specific Folder FTP Upload / ftp-deploy (push) Successful in 1m20s
Details
Specific Folder FTP Upload / ftp-deploy (push) Successful in 1m20s
Details
This commit is contained in:
parent
fd5b3d93e0
commit
a8af1a13d7
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace App\Helpers;
|
namespace App\Helpers;
|
||||||
|
|
||||||
|
use App\Http\Requests\LambdaRequest;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Http;
|
use Illuminate\Support\Facades\Http;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
|
@ -58,4 +60,89 @@ class TgicsHelper
|
||||||
return ['counts' => array_fill_keys($ids, 0), 'total' => 0];
|
return ['counts' => array_fill_keys($ids, 0), 'total' => 0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve a Rapport contact access token for a domain (e.g. lifemankind).
|
||||||
|
*/
|
||||||
|
public static function resolveContactAccessToken(string $domain): string
|
||||||
|
{
|
||||||
|
$domain = trim($domain);
|
||||||
|
if ($domain === '') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$tokenRows = DB::table('users')
|
||||||
|
->select('access_token')
|
||||||
|
->where('domain', $domain)
|
||||||
|
->where('permissions', 'like', '%contact_create%')
|
||||||
|
->orderBy('updated_at', 'desc')
|
||||||
|
->skip(0)
|
||||||
|
->take(1)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
if ($tokenRows->isEmpty() || empty($tokenRows[0]->access_token)) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (string) $tokenRows[0]->access_token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function isWhatsappValidatedFlag($value): bool
|
||||||
|
{
|
||||||
|
if ($value === true || $value === 1 || $value === '1') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return strtolower(trim((string) $value)) === 'yes';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map contact_id => whether WhatsApp is validated for TGICS.
|
||||||
|
*
|
||||||
|
* @param array<int, string> $contactIds
|
||||||
|
* @return array<string, bool>
|
||||||
|
*/
|
||||||
|
public static function getWhatsappValidationStatus(array $contactIds, string $domain = 'lifemankind'): array
|
||||||
|
{
|
||||||
|
$ids = array_values(array_unique(array_filter(array_map(static function ($id) {
|
||||||
|
return trim((string) $id);
|
||||||
|
}, $contactIds))));
|
||||||
|
|
||||||
|
if (count($ids) === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$accessToken = self::resolveContactAccessToken($domain);
|
||||||
|
if ($accessToken === '') {
|
||||||
|
Log::warning('TGICS WhatsApp validation: no contact access token for domain '.$domain);
|
||||||
|
return array_fill_keys($ids, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
$status = array_fill_keys($ids, false);
|
||||||
|
foreach ($ids as $id) {
|
||||||
|
try {
|
||||||
|
$resp = LambdaRequest::getrequest('contact', 'contact/get_one', ['id' => $id], $accessToken);
|
||||||
|
$item = $resp->data->item ?? null;
|
||||||
|
if ($item && self::isWhatsappValidatedFlag($item->tgics_whatsapp_validated ?? '')) {
|
||||||
|
$status[$id] = true;
|
||||||
|
}
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
Log::warning('TGICS WhatsApp validation lookup failed for '.$id.': '.$e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Single-contact validation check for poll endpoint.
|
||||||
|
*/
|
||||||
|
public static function isContactWhatsappValidated(string $contactId, string $domain = 'lifemankind'): bool
|
||||||
|
{
|
||||||
|
$contactId = trim($contactId);
|
||||||
|
if ($contactId === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$map = self::getWhatsappValidationStatus([$contactId], $domain);
|
||||||
|
return !empty($map[$contactId]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1050,6 +1050,7 @@ class FormController extends Controller
|
||||||
|
|
||||||
// Create contact on new enrolments; update linked contact on edits
|
// Create contact on new enrolments; update linked contact on edits
|
||||||
if ($currentSubmissionId === '') {
|
if ($currentSubmissionId === '') {
|
||||||
|
$contactdata['tgics_whatsapp_validated'] = 'No';
|
||||||
$cont = LambdaRequest::postrequest('contact', 'contact/create', $contactdata, $accessToken);
|
$cont = LambdaRequest::postrequest('contact', 'contact/create', $contactdata, $accessToken);
|
||||||
if (!isset($cont->status) || $cont->status !== 'success' || empty($cont->data->item->id)) {
|
if (!isset($cont->status) || $cont->status !== 'success' || empty($cont->data->item->id)) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
|
|
@ -1061,6 +1062,21 @@ class FormController extends Controller
|
||||||
$post['tgics_contact_id'] = $cont->data->item->id;
|
$post['tgics_contact_id'] = $cont->data->item->id;
|
||||||
} elseif ($linkedContactId !== '') {
|
} elseif ($linkedContactId !== '') {
|
||||||
$contactdata['id'] = $linkedContactId;
|
$contactdata['id'] = $linkedContactId;
|
||||||
|
$existingContact = LambdaRequest::getrequest('contact', 'contact/get_one', ['id' => $linkedContactId], $accessToken);
|
||||||
|
$existingItem = $existingContact->data->item ?? null;
|
||||||
|
$existingPhone = '';
|
||||||
|
if ($existingItem && !empty($existingItem->phone)) {
|
||||||
|
$existingPhone = preg_replace('/\D+/', '', (string) $existingItem->phone);
|
||||||
|
if (strlen($existingPhone) > 10) {
|
||||||
|
$existingPhone = substr($existingPhone, -10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($existingPhone !== '' && $existingPhone !== $whatsapp) {
|
||||||
|
$contactdata['tgics_whatsapp_validated'] = 'No';
|
||||||
|
} elseif ($existingItem && isset($existingItem->tgics_whatsapp_validated)) {
|
||||||
|
$contactdata['tgics_whatsapp_validated'] = $existingItem->tgics_whatsapp_validated;
|
||||||
|
}
|
||||||
|
|
||||||
$cont = LambdaRequest::postrequest('contact', 'contact/update', $contactdata, $accessToken);
|
$cont = LambdaRequest::postrequest('contact', 'contact/update', $contactdata, $accessToken);
|
||||||
if (!isset($cont->status) || $cont->status !== 'success') {
|
if (!isset($cont->status) || $cont->status !== 'success') {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
|
|
@ -13513,4 +13529,35 @@ class FormController extends Controller
|
||||||
return $labels;
|
return $labels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Poll endpoint: TGICS WhatsApp validation status for a contact.
|
||||||
|
*/
|
||||||
|
public function tgicsWhatsappStatus(Request $request)
|
||||||
|
{
|
||||||
|
$contactId = trim((string) $request->input('contact_id', ''));
|
||||||
|
$partition = trim((string) $request->input('partition', 'rapport-lifemankind'));
|
||||||
|
$domain = 'lifemankind';
|
||||||
|
if (strpos($partition, '-') !== false) {
|
||||||
|
$parts = explode('-', $partition, 2);
|
||||||
|
$domain = $parts[1] ?? $domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($contactId === '') {
|
||||||
|
return response()->json([
|
||||||
|
'status' => 'error',
|
||||||
|
'message' => 'contact_id is required.',
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
$validated = \App\Helpers\TgicsHelper::isContactWhatsappValidated($contactId, $domain);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'status' => 'success',
|
||||||
|
'data' => [
|
||||||
|
'contact_id' => $contactId,
|
||||||
|
'validated' => $validated,
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -62,6 +62,10 @@
|
||||||
$tgicsSurveyData = \App\Helpers\TgicsHelper::getSurveyCounts($tgicsContactIds);
|
$tgicsSurveyData = \App\Helpers\TgicsHelper::getSurveyCounts($tgicsContactIds);
|
||||||
$tgicsSurveyCounts = $tgicsSurveyData['counts'] ?? [];
|
$tgicsSurveyCounts = $tgicsSurveyData['counts'] ?? [];
|
||||||
$totalSurveysDone = (int) ($tgicsSurveyData['total'] ?? 0);
|
$totalSurveysDone = (int) ($tgicsSurveyData['total'] ?? 0);
|
||||||
|
$tgicsWhatsappValidated = \App\Helpers\TgicsHelper::getWhatsappValidationStatus(
|
||||||
|
$tgicsContactIds,
|
||||||
|
'lifemankind'
|
||||||
|
);
|
||||||
|
|
||||||
$tgicsCommonUserId = trim((string) ($form->user_id ?? ''));
|
$tgicsCommonUserId = trim((string) ($form->user_id ?? ''));
|
||||||
$tgicsCommonLink = $tgicsCommonUserId !== ''
|
$tgicsCommonLink = $tgicsCommonUserId !== ''
|
||||||
|
|
@ -135,23 +139,41 @@
|
||||||
$surveysDone = $tgicsContactId !== ''
|
$surveysDone = $tgicsContactId !== ''
|
||||||
? (int) ($tgicsSurveyCounts[$tgicsContactId] ?? 0)
|
? (int) ($tgicsSurveyCounts[$tgicsContactId] ?? 0)
|
||||||
: 0;
|
: 0;
|
||||||
|
$whatsappValidated = $tgicsContactId !== ''
|
||||||
|
&& !empty($tgicsWhatsappValidated[$tgicsContactId]);
|
||||||
$whatsappText = "Dear Doctor" . ($doctorName !== '' ? ' ' . $doctorName : '') . ",\nThank you for participating in TGICS (The Great Indian Cough Study).\nPlease open the link and enter your WhatsApp mobile number to continue:\n" . $doctorLink;
|
$whatsappText = "Dear Doctor" . ($doctorName !== '' ? ' ' . $doctorName : '') . ",\nThank you for participating in TGICS (The Great Indian Cough Study).\nPlease open the link and enter your WhatsApp mobile number to continue:\n" . $doctorLink;
|
||||||
$whatsappLink = ($whatsappDigits !== '' && $doctorLink !== '')
|
$whatsappLink = ($whatsappDigits !== '' && $doctorLink !== '')
|
||||||
? 'https://api.whatsapp.com/send?phone=' . $whatsappDigits . '&text=' . rawurlencode($whatsappText)
|
? 'https://api.whatsapp.com/send?phone=' . $whatsappDigits . '&text=' . rawurlencode($whatsappText)
|
||||||
: '';
|
: '';
|
||||||
|
$validateToken = $tgicsContactId !== ''
|
||||||
|
? 'CREST_VERIFY_TGICS_' . $tgicsContactId
|
||||||
|
: '';
|
||||||
|
$validateWaUrl = $validateToken !== ''
|
||||||
|
? 'https://wa.me/918142061298?text=' . rawurlencode($validateToken)
|
||||||
|
: '';
|
||||||
@endphp
|
@endphp
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
@if ($isApproved)
|
@if ($isApproved)
|
||||||
@if ($whatsappLink !== '')
|
@if ($doctorLink === '')
|
||||||
|
<span class="text-muted">Link unavailable</span>
|
||||||
|
@elseif ($whatsappDigits === '')
|
||||||
|
<span class="text-muted">No WhatsApp number</span>
|
||||||
|
@elseif ($whatsappValidated && $whatsappLink !== '')
|
||||||
<a href="{{ $whatsappLink }}" target="_blank" rel="noopener noreferrer"
|
<a href="{{ $whatsappLink }}" target="_blank" rel="noopener noreferrer"
|
||||||
class="btn btn-xs btn-success">
|
class="btn btn-xs btn-success">
|
||||||
<i class="mdi mdi-whatsapp"></i> Send WhatsApp
|
<i class="mdi mdi-whatsapp"></i> Send
|
||||||
</a>
|
</a>
|
||||||
@elseif ($doctorLink === '')
|
@elseif ($validateWaUrl !== '')
|
||||||
<span class="text-muted">Link unavailable</span>
|
<button type="button"
|
||||||
|
class="btn btn-xs btn-warning tgics-validate-wa-btn"
|
||||||
|
data-contact-id="{{ $tgicsContactId }}"
|
||||||
|
data-validate-url="{{ $validateWaUrl }}"
|
||||||
|
data-doctor-name="{{ $doctorName }}">
|
||||||
|
<i class="mdi mdi-qrcode"></i> Validate
|
||||||
|
</button>
|
||||||
@else
|
@else
|
||||||
<span class="text-muted">No WhatsApp number</span>
|
<span class="text-muted">Validation unavailable</span>
|
||||||
@endif
|
@endif
|
||||||
@else
|
@else
|
||||||
<button type="button" class="btn btn-xs btn-info edit-btn"
|
<button type="button" class="btn btn-xs btn-info edit-btn"
|
||||||
|
|
@ -399,6 +421,30 @@
|
||||||
<!-- end container -->
|
<!-- end container -->
|
||||||
</div>
|
</div>
|
||||||
<!-- end page -->
|
<!-- end page -->
|
||||||
|
|
||||||
|
<div class="modal fade" id="tgics-validate-wa-modal" tabindex="-1" role="dialog" aria-labelledby="tgics-validate-wa-title" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="tgics-validate-wa-title">Validate WhatsApp</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body text-center">
|
||||||
|
<p class="mb-2" id="tgics-validate-wa-doctor"></p>
|
||||||
|
<p class="text-muted small">Ask the doctor to scan this QR with the enrolled WhatsApp number and send the pre-filled message without changing it.</p>
|
||||||
|
<div id="tgics-validate-wa-qr" class="d-flex justify-content-center my-3"></div>
|
||||||
|
<p class="small mb-1" id="tgics-validate-wa-status">Waiting for validation…</p>
|
||||||
|
<a href="#" id="tgics-validate-wa-open" target="_blank" rel="noopener noreferrer" class="btn btn-sm btn-outline-success">
|
||||||
|
Open link instead
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
#pageloader {
|
#pageloader {
|
||||||
background: rgba(255, 255, 255, 0.8);
|
background: rgba(255, 255, 255, 0.8);
|
||||||
|
|
@ -416,9 +462,16 @@
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#tgics-validate-wa-qr canvas,
|
||||||
|
#tgics-validate-wa-qr img {
|
||||||
|
max-width: 220px;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@include('layouts.shared/footer-script')
|
@include('layouts.shared/footer-script')
|
||||||
<script src="{{ asset('assets/libs/sweetalert2/sweetalert2.min.js') }}"></script>
|
<script src="{{ asset('assets/libs/sweetalert2/sweetalert2.min.js') }}"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
|
||||||
<script src="{{ asset('js/tgics-india-geo.js') }}"></script>
|
<script src="{{ asset('js/tgics-india-geo.js') }}"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
jQuery(document).ready(function($) {
|
jQuery(document).ready(function($) {
|
||||||
|
|
@ -762,6 +815,89 @@
|
||||||
$('#field-contact_id').trigger('change');
|
$('#field-contact_id').trigger('change');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var tgicsWaPollTimer = null;
|
||||||
|
var tgicsWaPollStartedAt = 0;
|
||||||
|
|
||||||
|
function stopTgicsWaPoll() {
|
||||||
|
if (tgicsWaPollTimer) {
|
||||||
|
clearInterval(tgicsWaPollTimer);
|
||||||
|
tgicsWaPollTimer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function startTgicsWaPoll(contactId) {
|
||||||
|
stopTgicsWaPoll();
|
||||||
|
tgicsWaPollStartedAt = Date.now();
|
||||||
|
$('#tgics-validate-wa-status').text('Waiting for validation…');
|
||||||
|
|
||||||
|
tgicsWaPollTimer = setInterval(function() {
|
||||||
|
if (Date.now() - tgicsWaPollStartedAt > 120000) {
|
||||||
|
stopTgicsWaPoll();
|
||||||
|
$('#tgics-validate-wa-status').text('Still waiting. Close and try Validate again after the doctor sends the message.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$.ajax({
|
||||||
|
type: 'GET',
|
||||||
|
url: '/form/tgicswhatsappstatus',
|
||||||
|
data: {
|
||||||
|
contact_id: contactId,
|
||||||
|
partition: 'rapport-lifemankind'
|
||||||
|
},
|
||||||
|
success: function(res) {
|
||||||
|
if (res && res.status === 'success' && res.data && res.data.validated) {
|
||||||
|
stopTgicsWaPoll();
|
||||||
|
$('#tgics-validate-wa-status').text('Validated!');
|
||||||
|
Swal.fire({
|
||||||
|
icon: 'success',
|
||||||
|
title: 'WhatsApp validated',
|
||||||
|
text: 'You can now send the survey link to this doctor.',
|
||||||
|
timer: 1800,
|
||||||
|
showConfirmButton: false
|
||||||
|
}).then(function() {
|
||||||
|
window.location.reload();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).on('click', '.tgics-validate-wa-btn', function() {
|
||||||
|
var contactId = $(this).attr('data-contact-id') || '';
|
||||||
|
var validateUrl = $(this).attr('data-validate-url') || '';
|
||||||
|
var doctorName = $(this).attr('data-doctor-name') || 'Doctor';
|
||||||
|
if (!contactId || !validateUrl) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#tgics-validate-wa-doctor').text(doctorName);
|
||||||
|
$('#tgics-validate-wa-open').attr('href', validateUrl);
|
||||||
|
$('#tgics-validate-wa-qr').empty();
|
||||||
|
if (typeof QRCode !== 'undefined') {
|
||||||
|
new QRCode(document.getElementById('tgics-validate-wa-qr'), {
|
||||||
|
text: validateUrl,
|
||||||
|
width: 200,
|
||||||
|
height: 200
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
$('#tgics-validate-wa-qr').html('<p class="text-danger small">Unable to render QR. Use Open link instead.</p>');
|
||||||
|
}
|
||||||
|
|
||||||
|
var $modal = $('#tgics-validate-wa-modal');
|
||||||
|
if (typeof bootstrap !== 'undefined' && bootstrap.Modal) {
|
||||||
|
bootstrap.Modal.getOrCreateInstance($modal[0]).show();
|
||||||
|
} else if ($modal.modal) {
|
||||||
|
$modal.modal('show');
|
||||||
|
} else {
|
||||||
|
$modal.show();
|
||||||
|
}
|
||||||
|
startTgicsWaPoll(contactId);
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#tgics-validate-wa-modal').on('hidden.bs.modal hide.bs.modal', function() {
|
||||||
|
stopTgicsWaPoll();
|
||||||
|
});
|
||||||
|
|
||||||
$('#execution-form').on('submit', function(event) {
|
$('#execution-form').on('submit', function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
$("#pageloader").fadeIn();
|
$("#pageloader").fadeIn();
|
||||||
|
|
|
||||||
|
|
@ -332,6 +332,7 @@ Route::get('/form/nebmitraverification', [FormController::class, 'nebmitraverifi
|
||||||
|
|
||||||
Route::get('/form/respidoctorsearch', [FormController::class, 'respidoctorsearch']);
|
Route::get('/form/respidoctorsearch', [FormController::class, 'respidoctorsearch']);
|
||||||
Route::get('/form/addrespidoctor', [FormController::class, 'addrespidoctor']);
|
Route::get('/form/addrespidoctor', [FormController::class, 'addrespidoctor']);
|
||||||
|
Route::get('/form/tgicswhatsappstatus', [FormController::class, 'tgicsWhatsappStatus']);
|
||||||
|
|
||||||
Route::post('/form/getformfielddata', [FormController::class, 'getformfielddata']);
|
Route::post('/form/getformfielddata', [FormController::class, 'getformfielddata']);
|
||||||
Route::post('/form/submit', [FormController::class, 'submit']);
|
Route::post('/form/submit', [FormController::class, 'submit']);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue