nhance/app/Controllers/RuleImportController.php
2025-11-17 12:05:29 +05:30

351 lines
16 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Controllers;
class RuleImportController extends AdminController
{
protected $ruleImportService;
public function __construct()
{
$this->ruleImportService = \Config\Services::ruleImportService();
}
/**
* Upload endpoint for form (POST)
* Input form field: 'rules_file'
*/
public function uploadORI()
{
// echo 'hi';
!dd($result = $this->ruleImportService->processUpload(['id' => 1,'file_name' => 'sample_commission.csv','insurer_id' => 5, 'department' => 'motor' ,'commission_month' => '2025-11-10']));die;
try {
$file = $this->request->getFile('rules_file');
if (!$file || !$file->isValid()) {
return $this->response->setJSON(['status'=>'error','message'=>'No file uploaded or upload error']);
}
// Move uploaded file to writable temp location
$tmpPath = WRITEPATH . 'uploads/' . $file->getRandomName();
$file->move(WRITEPATH . 'uploads', $file->getName()); // keep original name inside uploads
$uploadedFullPath = $file->getTempName(); // Note: CI may store in tmp; we will use moved file path instead
$movedPath = WRITEPATH . 'uploads/' . $file->getName();
// Process file
$result = $this->ruleImportService->processUpload($movedPath, $file->getName());
// Return JSON with annotated file link if present
if (isset($result['annotated_file']) && $result['annotated_file']) {
$annotUrl = base_url('writable/uploads/annotated/' . basename($result['annotated_file']));
$result['annotated_url'] = $annotUrl;
}
return $this->response->setJSON($result);
} catch (\Throwable $e) {
log_message('critical', 'RuleImportController::upload ' . $e->getMessage());
return $this->response->setJSON(['status'=>'exception','message'=>$e->getMessage()]);
}
}
public function upload()
{
// Make sure filesystem helpers available if you need them
helper(['filesystem']);
// CommissionFilesModel adjust namespace if different
$commissionFilesModel = new \App\Models\CommissionFilesModel();
try {
// ---------------------------------------------------------
// 1. Get uploaded file
// ---------------------------------------------------------
$file = $this->request->getFile('rules_file');
if (!$file || !$file->isValid()) {
log_message('warning', 'RuleImportController::upload - No file or invalid upload.');
return $this->respond([
'status' => 'error',
'message' => 'No file uploaded or upload error.'
], 400);
}
// ---------------------------------------------------------
// 2. Read POST fields
// ---------------------------------------------------------
$insurerId = $this->request->getPost('insurer_id');
$department = $this->request->getPost('department');
$commissionMonth = $this->request->getPost('commission_month');
$createdBy = $this->request->getPost('created_by');
if (empty($insurerId) || empty($department) || empty($commissionMonth) || empty($createdBy)) {
log_message('warning', 'RuleImportController::upload - Missing required POST data.', [
'insurer_id' => $insurerId,
'department' => $department,
'commission_month' => $commissionMonth,
'created_by' => $createdBy,
]);
return $this->respond([
'status' => 'error',
'message' => 'Missing required fields: insurer_id, department, commission_month, created_by.'
], 400);
}
// Optional / default fields
$postedFileName = $this->request->getPost('file_name') ?: $file->getClientName();
$fileStatus = $this->request->getPost('file_status') ?: 'pending';
$isActive = $this->request->getPost('is_active') !== null ? (int)$this->request->getPost('is_active') : 1;
// rules_count is given by user but we will override it after processing on success
$postedRulesCount = $this->request->getPost('rules_count') !== null
? (int)$this->request->getPost('rules_count')
: 0;
// ---------------------------------------------------------
// 3. Move file to WRITEPATH/uploads/commission/files using user filename
// (no random name as per your requirement)
// ---------------------------------------------------------
$uploadDir = WRITEPATH . 'uploads/commission/files/';
if (!is_dir($uploadDir)) {
if (!mkdir($uploadDir, 0755, true) && !is_dir($uploadDir)) {
throw new \RuntimeException("Failed to create upload directory: {$uploadDir}");
}
}
// sanitize user file name but keep it deterministic (no random, no timestamp)
$safeName = preg_replace('/[^a-zA-Z0-9_\-\.]/', '_', $postedFileName);
$targetFileName = $safeName;
$movedFullPath = $uploadDir . $targetFileName;
$file->move($uploadDir, $targetFileName);
if (!file_exists($movedFullPath)) {
log_message('error', "RuleImportController::upload - Failed to move uploaded file to {$movedFullPath}");
return $this->respond([
'status' => 'error',
'message' => 'Failed to store uploaded file.'
], 500);
}
log_message('info', "RuleImportController::upload - File moved to {$movedFullPath}");
// ---------------------------------------------------------
// 4. Insert commission_files row with status pending
// ---------------------------------------------------------
$insertData = [
'file_name' => $targetFileName,
'insurer_id' => (int)$insurerId,
'department' => $department,
'commission_month'=> $commissionMonth,
'rules_count' => 0, // will update on success
'file_status' => $fileStatus, // 'pending' by default
'is_active' => $isActive,
'created_by' => (int)$createdBy,
'created_at' => date('Y-m-d H:i:s'),
];
$commissionFilesModel->insert($insertData);
$insertId = $commissionFilesModel->getInsertID();
if (empty($insertId)) {
log_message('error', 'RuleImportController::upload - Failed to insert commission_files record', ['data' => $insertData]);
return $this->respond([
'status' => 'error',
'message' => 'Failed to record upload in database.'
], 500);
}
log_message('info', "RuleImportController::upload - commission_files inserted id={$insertId}", $insertData);
// ---------------------------------------------------------
// 5. Call ruleImportService->processUpload with inserted file info
// As per your spec:
// $this->ruleImportService->processUpload([
// 'id' => 1,
// 'file_name' => 'sample_commission.csv',
// 'insurer_id' => 5,
// 'department' => 'motor',
// 'commission_month' => '2025-11-10'
// ])
// ---------------------------------------------------------
$payload = [
'id' => (int)$insertId,
'file_name' => $targetFileName,
'insurer_id' => (int)$insurerId,
'department' => $department,
'commission_month' => $commissionMonth,
];
log_message('info', 'RuleImportController::upload - Calling ruleImportService->processUpload', ['payload' => $payload]);
$result = $this->ruleImportService->processUpload($payload);
if (!is_array($result) || !isset($result['status'])) {
log_message('error', 'RuleImportController::upload - Invalid service response', ['response' => $result]);
// update file status as failed
$commissionFilesModel->update($insertId, [
'file_status' => 'failed',
'updated_by' => (int)$createdBy,
'updated_at' => date('Y-m-d H:i:s'),
]);
return $this->respond([
'status' => 'error',
'message' => 'Invalid response from import service.'
], 500);
}
// ---------------------------------------------------------
// 6. Handle SUCCESS
// - result['rules'] exists
// - result['errors'] empty
// - NO annotated_file
// - Save rules as JSON in WRITEPATH/uploads/commission/json/{insurer_id}_{department}.json
// ---------------------------------------------------------
if ($result['status'] === 'success') {
$rulesArray = isset($result['rules']) && is_array($result['rules']) ? $result['rules'] : [];
$rulesCount = count($rulesArray);
// Save JSON to WRITEPATH . 'uploads/commission/json/{insurer_id}_{department}.json'
$jsonDir = WRITEPATH . 'uploads/commission/json/';
if (!is_dir($jsonDir)) {
if (!mkdir($jsonDir, 0755, true) && !is_dir($jsonDir)) {
throw new \RuntimeException("Failed to create JSON output directory: {$jsonDir}");
}
}
$deptSlug = preg_replace('/[^a-zA-Z0-9_\-]/', '_', strtolower($department));
$jsonName = (int)$insurerId . '_' . $deptSlug . '.json';
$jsonPath = $jsonDir . $jsonName;
$jsonData = json_encode($rulesArray, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
if ($jsonData === false) {
log_message('error', 'RuleImportController::upload - json_encode failed for rules', [
'last_error' => json_last_error_msg()
]);
// mark as failed since we cannot save rules
$commissionFilesModel->update($insertId, [
'file_status' => 'failed',
'updated_by' => (int)$createdBy,
'updated_at' => date('Y-m-d H:i:s'),
]);
return $this->respond([
'status' => 'error',
'message' => 'Failed to encode rules as JSON.'
], 500);
}
if (file_put_contents($jsonPath, $jsonData) === false) {
log_message('error', 'RuleImportController::upload - Failed to write rules JSON file', ['json_path' => $jsonPath]);
$commissionFilesModel->update($insertId, [
'file_status' => 'failed',
'updated_by' => (int)$createdBy,
'updated_at' => date('Y-m-d H:i:s'),
]);
return $this->respond([
'status' => 'error',
'message' => 'Failed to store rules JSON file.'
], 500);
}
log_message('info', 'RuleImportController::upload - Rules JSON written', [
'file_id' => $insertId,
'json_path' => $jsonPath,
'rules_cnt' => $rulesCount,
]);
// Update DB: status, rules_count, updated_by
$commissionFilesModel->update($insertId, [
'file_status' => 'processed',
'rules_count' => $rulesCount,
'updated_by' => (int)$createdBy,
'updated_at' => date('Y-m-d H:i:s'),
// If you have a column for JSON path, uncomment:
// 'json_file_path' => $jsonPath,
]);
return $this->respond([
'status' => 'success',
'message' => 'File processed successfully.',
'file_id' => $insertId,
'rules_count' => $rulesCount,
'json_file' => $jsonPath,
'service' => $result, // optional: return full service response if you want
], 200);
}
// ---------------------------------------------------------
// 7. Handle ERROR (validation failed etc.)
// - Do NOT save any rules JSON
// - Update file_status to validation_failed
// - Store annotated_file path if you have such a column
// ---------------------------------------------------------
if ($result['status'] === 'error') {
$annotatedPath = $result['annotated_file'] ?? null;
$errors = $result['errors'] ?? [];
$updateData = [
'file_status' => 'validation_failed',
'rules_count' => 0, // do not save rules
'updated_by' => (int)$createdBy,
'updated_at' => date('Y-m-d H:i:s'),
];
// If you have a column for annotated file path, e.g. annotated_file_path
if ($annotatedPath) {
$updateData['annotated_file_path'] = $annotatedPath;
}
$commissionFilesModel->update($insertId, $updateData);
log_message('warning', "RuleImportController::upload - Validation failed for file_id={$insertId}", [
'errors' => $errors,
'annotated_file' => $annotatedPath
]);
return $this->respond([
'status' => 'error',
'message' => 'Validation failed. No rules saved.',
'file_id' => $insertId,
'errors' => $errors,
'annotated_file' => $annotatedPath,
], 422);
}
// ---------------------------------------------------------
// 8. Unexpected status
// ---------------------------------------------------------
log_message('error', 'RuleImportController::upload - Unexpected result status from service', ['result' => $result]);
$commissionFilesModel->update($insertId, [
'file_status' => 'failed',
'updated_by' => (int)$createdBy,
'updated_at' => date('Y-m-d H:i:s'),
]);
return $this->respond([
'status' => 'error',
'message' => 'Unexpected import service result.'
], 500);
} catch (\Throwable $ex) {
log_message('critical', 'RuleImportController::upload exception: ' . $ex->getMessage(), [
'trace' => $ex->getTraceAsString()
]);
// Try to update the commission_files record if insertId exists
if (isset($insertId) && !empty($insertId)) {
try {
$commissionFilesModel->update($insertId, [
'file_status' => 'failed',
'updated_by' => isset($createdBy) ? (int)$createdBy : null,
'updated_at' => date('Y-m-d H:i:s'),
'notes' => 'Upload exception: ' . $ex->getMessage(),
]);
} catch (\Throwable $e2) {
log_message('error', 'RuleImportController::upload - failed to update commission_files after exception: ' . $e2->getMessage());
}
}
return $this->respond([
'status' => 'exception',
'message' => $ex->getMessage(),
], 500);
}
}
}