FEAT_ECARD_S3MIG

This commit is contained in:
velz 2025-12-24 18:41:31 +05:30
parent 56680331b3
commit c63d11299f
7 changed files with 709 additions and 183 deletions

View File

@ -214,6 +214,7 @@ $routes->group("/employee", ["filter" => "authMVC"], function ($routes) {
$routes->get("retail-endorsement-list", "EmployeeController::retailendorsementlist");
$routes->post("retail-endorsement-save", "EmployeeController::retailendorsementsave");
$routes->get("getTPADataVariationReport/(:num)", "EmployeeController::getTPADataVariationReport/$1");
$routes->get("bulkGenerateEcardAndStoreinS3", "EmployeeController::bulkGenerateEcardAndStoreinS3");
});
@ -509,6 +510,8 @@ $routes->get('cli/sendZeptoMail', 'MasterController::testZeptoSMTP');
$routes->cli('cli/processjob', 'JobWorker::processJob');
$routes->cli('cli/processjobs', 'JobWorker::processJobs');
$routes->cli('cli/bulkGenerateEcardAndStoreinS3', 'EmployeeController::bulkGenerateEcardAndStoreinS3');
$routes->get("processjob", "JobWorker::processJob");
$routes->cli('cli/new_gmail_token', 'MasterController::generateNewGmailAPIToken');
$routes->cli('cli/send_mail_cli', 'MasterController::testGmailAPIViaCLI');

View File

@ -9,6 +9,7 @@ use App\Libraries\GmailAPI;
use App\Libraries\MyGoogleDrive;
use App\Libraries\RuleImportService;
use App\Libraries\DataServiceSqlite;
use App\Libraries\S3Service;
use App\Controllers\Home;
/**
@ -90,5 +91,14 @@ class Services extends BaseService
return new RuleImportService();
}
public static function getS3Service($getShared = true)
{
if ($getShared) {
return static::getSharedInstance('getS3Service');
}
return new S3Service();
}
}

View File

@ -101,6 +101,14 @@ class EmployeeController extends AdminController
public function list()
{
// $s3 = \Config\Services::getS3Service();
// $file = WRITEPATH.'uploads/excel/inception.ods';
// print_rr($s3->exists('inception_1766475604.ods'));
// print_rr($s3->getPresignedUrl('inception_1766.ods'));
// print_rr($s3->upload($file));
// print_rr($s3->download('inception_1766475604.ods',__DIR__));
// die();
// $model = new UserModel();
$data = [];
$data['status'] = ['draft' => 'Draft', 'enrolled' => 'Enrolled', 'active' => 'Active', 'inactive' => 'In-Active', 'pending' => 'Pending'];
@ -1429,7 +1437,10 @@ class EmployeeController extends AdminController
//E-CARD DOWNLOAD FUNCTION USING DOM PDF ( CURRENTLY USING THIS ) Dompdf
public function generateIDCardForEmployee($rand_string, $people = 0, $mode = 0)
{
// dd($rand_string, $people);
$mode = (int)$mode;
// dd($rand_string, $people,$mode);
$this->myLogger->logme('error', 'generateIDCardForEmployee params .' . json_encode(["rand_string" => $rand_string, "people" => $people, "mode" => $mode]));
try {
$this->myLogger->logme('error', 'generateIDCardForEmployee function started.');
@ -1438,7 +1449,7 @@ class EmployeeController extends AdminController
$this->myLogger->logme('error', 'Fetching employee code and client policy ID.');
$get_emp_code_and_client_policy_id = $this->employeePolicyModel
->select('employee_polices.client_policy_id, employees.emp_code, tpa.short_name,employees.client_id')
->select('employee_polices.client_policy_id, employees.emp_code,employees.name, employee_polices.tpa_id,tpa.short_name,employees.client_id')
->join('client_policy', 'client_policy.id = employee_polices.client_policy_id')
->join('employees', 'employees.id = employee_polices.employee_id')
->join('tpa', 'tpa.id = client_policy.tpa_id')
@ -1465,7 +1476,44 @@ class EmployeeController extends AdminController
$client_policy_id = $get_emp_code_and_client_policy_id['client_policy_id'];
$emp_code = $get_emp_code_and_client_policy_id['emp_code'];
$client_id = $get_emp_code_and_client_policy_id['client_id'];
//new step check in S3 if yes then fetch from S3 bucket
$s3_key = 'ecard_'.$get_emp_code_and_client_policy_id['name'].'('.$get_emp_code_and_client_policy_id['emp_code'].')'.'_'.$get_emp_code_and_client_policy_id['tpa_id'].'.pdf';
// echo $s3_key;die();
$s3 = \Config\Services::getS3Service();
if($s3->exists($s3_key) && $mode != 2) //2 => for bulk generate so skip s3 check and generate PDF
{
//get pre signed url & make it download
$s3_url = $s3->getPresignedUrl($s3_key );
$pdf = file_get_contents($s3_url['url']);
if ($mode == 1) {
// Inline view
return $this->response
->setHeader('Content-Type', 'application/pdf')
->setHeader('Content-Disposition', 'inline; filename="' . $s3_key . '"')
->setBody($pdf);
} else if($mode == 0){
// echo 'Force download';//die();
return $this->response
->setHeader('Content-Type', 'application/pdf')
->setHeader('Content-Disposition', 'attachment; filename="' . $s3_key . '"')
->setBody($pdf);
}
// exit();
}
else
{
if($mode !== 2)
{
$data['message'] = 'Inprogress... Comeback later! or Contact support';
return view('errors/404', $data);
}
}
//in else generate PDF and upload it in s3
// echo 'else';
// exit();
// Step 2: Fetch ECard data
$this->myLogger->logme('error', 'Fetching ECard data using client_policy_id: ' . $client_policy_id . ' and emp_code: ' . $emp_code);
$data = $this->employeePolicyModel->getECardDataUsingMd5($client_policy_id, $emp_code,$client_id);
@ -1562,6 +1610,7 @@ class EmployeeController extends AdminController
}
// return $html;
// echo $html;die();
// DomPdf
$options = new Options();
$options->set('isRemoteEnabled', true);
@ -1585,28 +1634,34 @@ class EmployeeController extends AdminController
$dompdf->addInfo("Title", "E-Card");
$filename = 'ecard_' . date('Y-m-d_H-i-s') . '.pdf';
$temp_local_path = WRITEPATH.'/tmp/'.$s3_key;
file_put_contents(($temp_local_path),$dompdf->output());
// if($mode == 1){
// $dompdf->stream($filename, ['Attachment' => false]); // Inline view
// }else{
// $dompdf->stream($filename, ['Attachment' => true]); // Force download
// }
$aws_upload_res = $s3->upload(($temp_local_path));
// print_rr($aws_upload_res);
// echo '<br>PDF generated and uploaded to S3 successfully.<br>';
unlink($temp_local_path);
if ($mode == 1) {
// Inline view
return $this->response
->setHeader('Content-Type', 'application/pdf')
->setHeader('Content-Disposition', 'inline; filename="' . $filename . '"')
->setBody($dompdf->output());
} else {
// Force download
return $this->response
->setHeader('Content-Type', 'application/pdf')
->setHeader('Content-Disposition', 'attachment; filename="' . $filename . '"')
->setBody($dompdf->output());
}
// exit();
// if ($mode == 1) {
// // Inline view
// return $this->response
// ->setHeader('Content-Type', 'application/pdf')
// ->setHeader('Content-Disposition', 'inline; filename="' . $filename . '"')
// ->setBody($dompdf->output());
// } else {
// // Force download
// return $this->response
// ->setHeader('Content-Type', 'application/pdf')
// ->setHeader('Content-Disposition', 'attachment; filename="' . $filename . '"')
// ->setBody($dompdf->output());
// }
$this->myLogger->logme('error', 'generateIDCardForEmployee function completed successfully.');
// $this->myLogger->logme('error', 'generateIDCardForEmployee function completed successfully.');
} catch (\Exception $e) {
$this->myLogger->logme('error', 'Exception occurred: ' . $e->getMessage());
@ -3764,206 +3819,389 @@ class EmployeeController extends AdminController
array $notInTPA,
array $notInNhance,
array $reviewNeeded,
string $filename = 'employee_review.xlsx'
) {
string $filename = 'employee_review.xlsx')
{
function setCell($sheet, int $col, int $row, $value)
{
$cell = Coordinate::stringFromColumnIndex($col) . $row;
$sheet->setCellValue($cell, $value);
}
function setCell($sheet, int $col, int $row, $value)
{
$cell = Coordinate::stringFromColumnIndex($col) . $row;
$sheet->setCellValue($cell, $value);
}
$EXPORT_COLUMNS = [
$EXPORT_COLUMNS = [
// Sheet 1 — Not in TPA
'not_in_tpa' => [
'emp_code' => 'Employee Code',
'name' => 'Employee Name',
'relationship' => 'Relation',
'dob' => 'Date of Birth',
'gender' => 'Gender',
'mobile' => 'Mobile No',
'email_corporate' => 'Corporate Email',
'policy_no' => 'Policy No',
'tpa_name' => 'TPA Name',
'change_event' => 'Change Event',
],
// Sheet 1 — Not in TPA
'not_in_tpa' => [
'emp_code' => 'Employee Code',
'name' => 'Employee Name',
'relationship' => 'Relation',
'dob' => 'Date of Birth',
'gender' => 'Gender',
'mobile' => 'Mobile No',
'email_corporate' => 'Corporate Email',
'policy_no' => 'Policy No',
'tpa_name' => 'TPA Name',
'change_event' => 'Change Event',
],
// Sheet 2 — Not in Nhance
'not_in_nhance' => [
'emp_code' => 'Employee Code',
'name' => 'Employee Name',
'relation' => 'Relation',
'dob' => 'Date of Birth',
'gender' => 'Gender',
'age' => 'Age',
'tpa_id' => 'TPA Member ID',
],
// Sheet 2 — Not in Nhance
'not_in_nhance' => [
'emp_code' => 'Employee Code',
'name' => 'Employee Name',
'relation' => 'Relation',
'dob' => 'Date of Birth',
'gender' => 'Gender',
'age' => 'Age',
'tpa_id' => 'TPA Member ID',
],
// Sheet 3 — Review Needed (DB side)
'review_main' => [
'emp_code' => 'Employee Code',
'name' => 'Employee Name',
'relationship' => 'Relation',
'dob' => 'Date of Birth',
'gender' => 'Gender',
'policy_no' => 'Policy No',
'uhid' => 'UHID',
'change_event' => 'Change event'
],
// Sheet 3 — Review Needed (DB side)
'review_main' => [
'emp_code' => 'Employee Code',
'name' => 'Employee Name',
'relationship' => 'Relation',
'dob' => 'Date of Birth',
'gender' => 'Gender',
'policy_no' => 'Policy No',
'uhid' => 'UHID',
'change_event' => 'Change event'
],
// Sheet 3 — Review Needed (TPA side)
'review_tpa' => [
'emp_code' => 'TPA Employee Code',
'name' => 'TPA Name',
'relation' => 'TPA Relation',
'dob' => 'TPA DOB',
'gender' => 'TPA Gender',
'tpa_id' => 'TPA Member ID',
'age' => 'TPA Age',
],
];
// Sheet 3 — Review Needed (TPA side)
'review_tpa' => [
'emp_code' => 'TPA Employee Code',
'name' => 'TPA Name',
'relation' => 'TPA Relation',
'dob' => 'TPA DOB',
'gender' => 'TPA Gender',
'tpa_id' => 'TPA Member ID',
'age' => 'TPA Age',
],
];
$spreadsheet = new Spreadsheet();
$spreadsheet = new Spreadsheet();
/* =========================================================
* SHEET 1 NOT IN TPA
* ========================================================= */
$sheet1 = $spreadsheet->getActiveSheet();
$sheet1->setTitle('Not in TPA');
/* =========================================================
* SHEET 1 NOT IN TPA
* ========================================================= */
$sheet1 = $spreadsheet->getActiveSheet();
$sheet1->setTitle('Not in TPA');
$cols = $EXPORT_COLUMNS['not_in_tpa'];
$cols = $EXPORT_COLUMNS['not_in_tpa'];
$colNo = 1;
foreach ($cols as $label) {
setCell($sheet1, $colNo++, 1, $label);
}
$rowNo = 2;
foreach ($notInTPA as $row) {
$colNo = 1;
foreach ($cols as $key => $label) {
setCell($sheet1, $colNo++, $rowNo, $row[$key] ?? '');
foreach ($cols as $label) {
setCell($sheet1, $colNo++, 1, $label);
}
$rowNo++;
}
foreach (range(1, count($cols)) as $c) {
$sheet1->getColumnDimension(Coordinate::stringFromColumnIndex($c))->setAutoSize(true);
}
$rowNo = 2;
foreach ($notInTPA as $row) {
$colNo = 1;
foreach ($cols as $key => $label) {
setCell($sheet1, $colNo++, $rowNo, $row[$key] ?? '');
}
$rowNo++;
}
/* =========================================================
* SHEET 2 NOT IN NHANCE
* ========================================================= */
$sheet2 = $spreadsheet->createSheet();
$sheet2->setTitle('Not in Nhance');
foreach (range(1, count($cols)) as $c) {
$sheet1->getColumnDimension(Coordinate::stringFromColumnIndex($c))->setAutoSize(true);
}
$cols = $EXPORT_COLUMNS['not_in_nhance'];
/* =========================================================
* SHEET 2 NOT IN NHANCE
* ========================================================= */
$sheet2 = $spreadsheet->createSheet();
$sheet2->setTitle('Not in Nhance');
$colNo = 1;
foreach ($cols as $label) {
setCell($sheet2, $colNo++, 1, $label);
}
$cols = $EXPORT_COLUMNS['not_in_nhance'];
$rowNo = 2;
foreach ($notInNhance as $row) {
$colNo = 1;
foreach ($cols as $key => $label) {
setCell($sheet2, $colNo++, $rowNo, $row[$key] ?? '');
foreach ($cols as $label) {
setCell($sheet2, $colNo++, 1, $label);
}
$rowNo++;
}
foreach (range(1, count($cols)) as $c) {
$sheet2->getColumnDimension(Coordinate::stringFromColumnIndex($c))->setAutoSize(true);
}
$rowNo = 2;
foreach ($notInNhance as $row) {
$colNo = 1;
foreach ($cols as $key => $label) {
setCell($sheet2, $colNo++, $rowNo, $row[$key] ?? '');
}
$rowNo++;
}
/* =========================================================
* SHEET 3 REVIEW NEEDED
* ========================================================= */
$sheet3 = $spreadsheet->createSheet();
$sheet3->setTitle('Review Needed');
foreach (range(1, count($cols)) as $c) {
$sheet2->getColumnDimension(Coordinate::stringFromColumnIndex($c))->setAutoSize(true);
}
$mainCols = $EXPORT_COLUMNS['review_main'];
$tpaCols = $EXPORT_COLUMNS['review_tpa'];
/* =========================================================
* SHEET 3 REVIEW NEEDED
* ========================================================= */
$sheet3 = $spreadsheet->createSheet();
$sheet3->setTitle('Review Needed');
// headers
$colNo = 1;
foreach ($mainCols as $label) {
setCell($sheet3, $colNo++, 1, $label);
}
foreach ($tpaCols as $label) {
setCell($sheet3, $colNo++, 1, $label);
}
$mainCols = $EXPORT_COLUMNS['review_main'];
$tpaCols = $EXPORT_COLUMNS['review_tpa'];
// rows
$rowNo = 2;
foreach ($reviewNeeded as $row) {
// main (DB)
// headers
$colNo = 1;
foreach ($mainCols as $key => $label) {
setCell($sheet3, $colNo++, $rowNo, $row[$key] ?? '');
foreach ($mainCols as $label) {
setCell($sheet3, $colNo++, 1, $label);
}
foreach ($tpaCols as $label) {
setCell($sheet3, $colNo++, 1, $label);
}
$tpaData = [];
$notMatching = [];
// rows
$rowNo = 2;
foreach ($reviewNeeded as $row) {
if (($row['match']['status'] ?? '') === 'matched') {
$tpaData = $row['match']['tpa_record'] ?? [];
$notMatching = $row['match']['not_matching'] ?? [];
}
// TPA
foreach ($tpaCols as $key => $label) {
setCell($sheet3, $colNo++, $rowNo, $tpaData[$key] ?? '');
}
// highlight mismatches
foreach ($notMatching as $field) {
if (isset($mainCols[$field])) {
$idx = array_keys($mainCols);
$pos = array_search($field, $idx);
$cell = Coordinate::stringFromColumnIndex($pos + 1) . $rowNo;
$sheet3->getStyle($cell)->getFill()
->setFillType(Fill::FILL_SOLID)
->getStartColor()->setARGB('FFFFFF00');
// main (DB)
$colNo = 1;
foreach ($mainCols as $key => $label) {
setCell($sheet3, $colNo++, $rowNo, $row[$key] ?? '');
}
if (isset($tpaCols[$field])) {
$idx = array_keys($tpaCols);
$pos = array_search($field, $idx);
$cell = Coordinate::stringFromColumnIndex(count($mainCols) + $pos + 1) . $rowNo;
$sheet3->getStyle($cell)->getFill()
->setFillType(Fill::FILL_SOLID)
->getStartColor()->setARGB('FFFFFF00');
$tpaData = [];
$notMatching = [];
if (($row['match']['status'] ?? '') === 'matched') {
$tpaData = $row['match']['tpa_record'] ?? [];
$notMatching = $row['match']['not_matching'] ?? [];
}
// TPA
foreach ($tpaCols as $key => $label) {
setCell($sheet3, $colNo++, $rowNo, $tpaData[$key] ?? '');
}
// highlight mismatches
foreach ($notMatching as $field) {
if (isset($mainCols[$field])) {
$idx = array_keys($mainCols);
$pos = array_search($field, $idx);
$cell = Coordinate::stringFromColumnIndex($pos + 1) . $rowNo;
$sheet3->getStyle($cell)->getFill()
->setFillType(Fill::FILL_SOLID)
->getStartColor()->setARGB('FFFFFF00');
}
if (isset($tpaCols[$field])) {
$idx = array_keys($tpaCols);
$pos = array_search($field, $idx);
$cell = Coordinate::stringFromColumnIndex(count($mainCols) + $pos + 1) . $rowNo;
$sheet3->getStyle($cell)->getFill()
->setFillType(Fill::FILL_SOLID)
->getStartColor()->setARGB('FFFFFF00');
}
}
$rowNo++;
}
$rowNo++;
foreach (range(1, count($mainCols) + count($tpaCols)) as $c) {
$sheet3->getColumnDimension(Coordinate::stringFromColumnIndex($c))->setAutoSize(true);
}
/* =========================================================
* OUTPUT
* ========================================================= */
$writer = new Xlsx($spreadsheet);
if (ob_get_length()) ob_end_clean();
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Cache-Control: max-age=0');
$writer->save('php://output');
exit;
}
foreach (range(1, count($mainCols) + count($tpaCols)) as $c) {
$sheet3->getColumnDimension(Coordinate::stringFromColumnIndex($c))->setAutoSize(true);
public function bulkGenerateEcardAndStoreinS3(array $params = [])
{
/**
* ---------------------------
* 1. Detect mode + collect inputs
* ---------------------------
*/
$client_policy_id = $params['client_policy_id'] ?? null;
$emp_code = $params['emp_code'] ?? null;
$emp_pk = $params['emp_pk'] ?? null;
$batch_size = $params['batch_size'] ?? null;
$batch_no = $params['batch_no'] ?? null;
$execution_mode = $params['execution_mode'] ?? 'sequential';//parallel
$total_batches = $params['total_batches'] ?? 0;//parallel
if (is_cli()) {
$mode = 'CLI';
} elseif (empty($params) && $this->request->getMethod() === 'get') {
$mode = 'WEB';
$client_policy_id = $this->request->getGet('client_policy_id');
$emp_code = $this->request->getGet('emp_code');
$emp_pk = $this->request->getGet('emp_pk');
$execution_mode = $this->request->getGet('execution_mode') ?? 'sequential';
$batch_size = (int) ($this->request->getGet('batch_size') ?? 100);
if($client_policy_id == null || empty($client_policy_id) || $client_policy_id == '')
{
return $this->respond(['status' => false, 'code' => 200, 'message' => 'client_policy_id is necessary'], 200);
}
/**
* ---------------------------
* 2. Calculate total records
* ---------------------------
*/
$total = $this->employeePolicyModel
->join('employees', 'employees.id = employee_polices.employee_id')
->where('employees.emp_status', 'active')
->where('employees.is_active', '1')
->where("employee_polices.tpa_id IS NOT NULL AND employee_polices.tpa_id <> ''")
->where('employee_polices.status', 'active')
->where('employee_polices.is_active', '1')
->where('employee_polices.client_policy_id', $client_policy_id)
->countAllResults();
$total_batches = (int) ceil($total / $batch_size);
// echo $total_batches;die();
/**
* ---------------------------
* 3. Push JOB per batch
* ---------------------------
*/
if ($execution_mode === 'parallel') {
for ($batch_no = 1; $batch_no <= $total_batches; $batch_no++) {
Jobs::addJob([
'job_name' => 'bulkGenerateEcardAndStoreinS3',
'payload' => [
'client_policy_id' => $client_policy_id,
'emp_code' => $emp_code,
'emp_pk' => $emp_pk,
'batch_size' => $batch_size,
'batch_no' => $batch_no,
'total_batches' => $total_batches,
'execution_mode' => 'parallel',
],
]);
}
}
if ($execution_mode === 'sequential') {
Jobs::addJob([
'job_name' => 'bulkGenerateEcardAndStoreinS3',
'payload' => [
'client_policy_id' => $client_policy_id,
'batch_size' => $batch_size,
'batch_no' => $batch_no ?? 1,
'total_batches' => $total_batches,
'execution_mode' => 'sequential',
],
]);
}
return $this->respond(['status' => true, 'code' => 200, 'message' => 'E-card generation started',
'total' => $total,
'batches' => $total_batches,], 200);
// return [
// 'status' => true,
// 'message' => 'E-card generation started',
// 'total' => $total,
// 'batches' => $total_batches,
// ];
}
//else {
// return true;
// }
/**
* ---------------------------
* 4. Build query (CLI execution)
* ---------------------------
*/
$builder = $this->employeePolicyModel
->select('
employee_polices.client_policy_id,
employees.emp_code,
tpa.short_name,
employees.client_id,
employee_polices.rand_string,
employees.id as emp_id
')
->join('client_policy', 'client_policy.id = employee_polices.client_policy_id')
->join('employees', 'employees.id = employee_polices.employee_id')
->join('tpa', 'tpa.id = client_policy.tpa_id')
->where('employees.emp_status', 'active')
->where('employees.is_active', '1')
->where("employee_polices.tpa_id IS NOT NULL AND employee_polices.tpa_id <> ''")
->where('employee_polices.status', 'active')
->where('employee_polices.is_active', '1')
->where('employee_polices.client_policy_id', $client_policy_id);
if (!empty($emp_code)) {
$builder->where('employees.emp_code', $emp_code);
}
if (!empty($emp_pk)) {
$builder->where('employees.id', $emp_pk);
}
/**
* ---------------------------
* 5. Apply batching (only if provided)
* ---------------------------
*/
if (!empty($batch_size) && !empty($batch_no)) {
$offset = ($batch_no - 1) * $batch_size;
$builder->limit($batch_size, $offset);
}
$res = $builder->findAll();
/**
* ---------------------------
* 6. Process batch
* ---------------------------
*/
foreach ($res as $row) {
$ecard_gen_res = $this->generateIDCardForEmployee(
$row['rand_string'],
0,
2 // skip S3 check, force regenerate
);
// print_rr([
// 'batch' => $batch_no,
// 'emp' => $row['emp_code'],
// 'res' => $ecard_gen_res,
// ]);
// echo date('Y-m-d H:i:s') . PHP_EOL;
}
if ($execution_mode === 'sequential' && $batch_no < $total_batches) {
Jobs::addJob([
'job_name' => 'bulkGenerateEcardAndStoreinS3',
'payload' => [
'client_policy_id' => $client_policy_id,
'batch_size' => $batch_size,
'batch_no' => ($batch_no + 1),
'total_batches' => $total_batches,
'execution_mode' => 'sequential',
],
]);
}
// echo "BATCH {$batch_no} COMPLETED @ " . date('Y-m-d H:i:s') . PHP_EOL;
return array($batch_no);
}
/* =========================================================
* OUTPUT
* ========================================================= */
$writer = new Xlsx($spreadsheet);
if (ob_get_length()) ob_end_clean();
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Cache-Control: max-age=0');
$writer->save('php://output');
exit;
}
}

View File

@ -1029,7 +1029,7 @@ class EmployeeMultiEventServiceController extends BaseController
//check physical file
if (!file_exists($file_name_with_path)) {
//file not found update status and reason
$message = "Physcial file not found";
$message = "Physcial file not found - " . $file_name_with_path;
// echo $message;
$this->myLogger->logme('error', ($message . ' for file id ' . $file_id));
$this->fileModel->where('id', $file_id)->set(['status' => 'failed', 'reason' => json_encode(['error_summary' => array_count_values([5]), 'error_data' => $message])])->update();
@ -1402,7 +1402,7 @@ class EmployeeMultiEventServiceController extends BaseController
//check physical file
if (!file_exists($file_name_with_path)) {
//file not found update status and reason
$message = "Physcial file not found";
$message = "Physcial file not found - " . $file_name_with_path;
$this->myLogger->logme('error', ($message . ' for file id ' . $file_id));
$this->fileModel->where('id', $file_id)->set(['status' => 'failed', 'reason' => json_encode(['error_summary' => array_count_values([5]), 'error_data' => $message])])->update();
return array('error_summary' => [5], 'error_data' => $message);

View File

@ -194,6 +194,10 @@ class JobWorker extends AdminController
'type' => 'CC', // Handler Category
'handler' => 'App\Controllers\MediAssistApiController',
],
'bulkGenerateEcardAndStoreinS3' => [
'type' => 'CC', // Handler Category
'handler' => 'App\Controllers\EmployeeController',
]
];
@ -253,6 +257,8 @@ class JobWorker extends AdminController
// print_r($jobdata);
// echo 'listen';
// die();
// $jobdata = ['id' => 11954,'uuid' => '001700c2-8127-4d02-80b3-ea26e7603ccf'];
// dd($job);
$query = "
SELECT id, name, payload, uuid
FROM jobs

268
app/Libraries/S3Service.php Normal file
View File

@ -0,0 +1,268 @@
<?php
namespace App\Libraries;
use Aws\S3\S3Client;
use Aws\Exception\AwsException;
use CodeIgniter\HTTP\ResponseInterface;
class S3Service
{
protected $s3Client;
protected $bucket;
protected $region;
protected $baseUrl;
public function __construct()
{
$this->bucket = getenv('AWS_BUCKET');
$this->region = getenv('AWS_DEFAULT_REGION');
$this->s3Client = new S3Client([
'version' => 'latest',
'region' => $this->region,
'credentials' => [
'key' => getenv('AWS_ACCESS_KEY_ID'),
'secret' => getenv('AWS_SECRET_ACCESS_KEY'),
],
]);
$this->baseUrl = "https://{$this->bucket}.s3.{$this->region}.amazonaws.com/";
// echo $this->baseUrl;die();
}
/**
* Upload file to S3
*
* @param mixed $file File object or file path
* @param string $folder Folder path in S3 bucket (optional)
* @param string $fileName Custom file name (optional)
* @return array ['success' => bool, 'url' => string, 'key' => string, 'message' => string]
*/
public function upload($file, string $folder = '', string $fileName = null): array
{
try {
// Handle CodeIgniter file upload object
if (is_object($file) && method_exists($file, 'isValid')) {
if (!$file->isValid()) {
return [
'success' => false,
'message' => 'Invalid file upload',
'url' => null,
'key' => null
];
}
$filePath = $file->getTempName();
$originalName = $fileName ?? $file->getClientName();
} else {
// Handle file path string
$filePath = $file;
$originalName = $fileName ?? basename($file);
}
// Generate unique file name
$extension = pathinfo($originalName, PATHINFO_EXTENSION);
// $uniqueName = pathinfo($originalName, PATHINFO_FILENAME) . '_' . time() . '.' . $extension;
$uniqueName = pathinfo($originalName, PATHINFO_FILENAME) . '.' . $extension;
// Build S3 key (path)
$key = $folder ? rtrim($folder, '/') . '/' . $uniqueName : $uniqueName;
// Upload to S3
// NEW - Faster with streaming and proper content type
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $filePath);
finfo_close($finfo);
$result = $this->s3Client->putObject([
'Bucket' => $this->bucket,
'Key' => $key,
'Body' => fopen($filePath, 'rb'), // Stream instead of loading into memory
'ContentType' => $mimeType,
// 'ACL' => 'public-read',
]);
return [
'success' => true,
'url' => $this->baseUrl . $key,
'key' => $key,
'message' => 'File uploaded successfully'
];
} catch (AwsException $e) {
log_message('error', 'S3 Upload Error: ' . $e->getMessage());
return [
'success' => false,
'message' => 'Upload failed: ' . $e->getMessage(),
'url' => null,
'key' => null
];
}
}
/**
* Download file from S3
*
* @param string $key S3 object key (file path in bucket)
* @param string $savePath Local path to save the file (optional)
* @return array ['success' => bool, 'path' => string, 'content' => string, 'message' => string]
*/
public function download(string $key, string $savePath = null): array
{
try {
$result = $this->s3Client->getObject([
'Bucket' => $this->bucket,
'Key' => $key,
]);
$content = (string) $result['Body'];
// If save path is provided, save to local file
if ($savePath) {
$directory = dirname($savePath);
if (!is_dir($directory)) {
mkdir($directory, 0755, true);
}
file_put_contents($savePath, $content);
return [
'success' => true,
'path' => $savePath,
'content' => $content,
'message' => 'File downloaded successfully'
];
}
return [
'success' => true,
'path' => null,
'content' => $content,
'message' => 'File content retrieved successfully'
];
} catch (AwsException $e) {
log_message('error', 'S3 Download Error: ' . $e->getMessage());
return [
'success' => false,
'path' => null,
'content' => null,
'message' => 'Download failed: ' . $e->getMessage()
];
}
}
/**
* Get a pre-signed URL for temporary access to a private file
*
* @param string $key S3 object key
* @param int $expiration Expiration time in minutes (default: 60)
* @return array ['success' => bool, 'url' => string, 'message' => string]
*/
public function getPresignedUrl(string $key, int $expiration = 60): array
{
try {
$cmd = $this->s3Client->getCommand('GetObject', [
'Bucket' => $this->bucket,
'Key' => $key
]);
$request = $this->s3Client->createPresignedRequest($cmd, "+{$expiration} minutes");
$presignedUrl = (string) $request->getUri();
return [
'success' => true,
'url' => $presignedUrl,
'message' => 'Pre-signed URL generated successfully'
];
} catch (AwsException $e) {
log_message('error', 'S3 Presigned URL Error: ' . $e->getMessage());
return [
'success' => false,
'url' => null,
'message' => 'Failed to generate URL: ' . $e->getMessage()
];
}
}
/**
* Delete file from S3
*
* @param string $key S3 object key
* @return array ['success' => bool, 'message' => string]
*/
public function delete(string $key): array
{
try {
$this->s3Client->deleteObject([
'Bucket' => $this->bucket,
'Key' => $key,
]);
return [
'success' => true,
'message' => 'File deleted successfully'
];
} catch (AwsException $e) {
log_message('error', 'S3 Delete Error: ' . $e->getMessage());
return [
'success' => false,
'message' => 'Delete failed: ' . $e->getMessage()
];
}
}
/**
* Check if file exists in S3
*
* @param string $key S3 object key
* @return bool
*/
public function exists(string $key): bool
{
return $this->s3Client->doesObjectExist($this->bucket, $key);
}
/**
* List files in S3 bucket
*
* @param string $prefix Folder prefix (optional)
* @return array ['success' => bool, 'files' => array, 'message' => string]
*/
public function listFiles(string $prefix = ''): array
{
try {
$result = $this->s3Client->listObjectsV2([
'Bucket' => $this->bucket,
'Prefix' => $prefix,
]);
$files = [];
if (isset($result['Contents'])) {
foreach ($result['Contents'] as $object) {
$files[] = [
'key' => $object['Key'],
'size' => $object['Size'],
'last_modified' => $object['LastModified']->format('Y-m-d H:i:s'),
'url' => $this->baseUrl . $object['Key']
];
}
}
return [
'success' => true,
'files' => $files,
'message' => 'Files retrieved successfully'
];
} catch (AwsException $e) {
log_message('error', 'S3 List Error: ' . $e->getMessage());
return [
'success' => false,
'files' => [],
'message' => 'Failed to list files: ' . $e->getMessage()
];
}
}
}

View File

@ -14,6 +14,7 @@
"ext-intl": "*",
"ext-json": "*",
"ext-mbstring": "*",
"aws/aws-sdk-php": "^3.369",
"botman/botman": "^2.8",
"botman/driver-web": "^1.5",
"dompdf/dompdf": "^2.0",
@ -72,7 +73,7 @@
]
},
"config": {
"optimize-autoloader": true,
"optimize-autoloader": false,
"preferred-install": "dist",
"sort-packages": true,
"process-timeout": 900