From 9a6ad8c4c5c6dd39b62808882718976e649e33c8 Mon Sep 17 00:00:00 2001 From: velz Date: Tue, 18 Nov 2025 15:56:34 +0530 Subject: [PATCH] FEAT_COMMISSION_UPLOAD --- app/Controllers/RuleImportController.php | 87 +++++++++++++++++++++--- 1 file changed, 77 insertions(+), 10 deletions(-) diff --git a/app/Controllers/RuleImportController.php b/app/Controllers/RuleImportController.php index 678e59c6..6e9a5bfc 100644 --- a/app/Controllers/RuleImportController.php +++ b/app/Controllers/RuleImportController.php @@ -102,7 +102,7 @@ class RuleImportController extends AdminController $insurerId = $this->request->getPost('insurer_id'); $department = $this->request->getPost('department'); $commissionMonth = $this->request->getPost('commission_month'); - $overwrite = $this->request->getPost('overwrite') ?? 0; + $overwrite = $this->request->getPost('overwrite') ?? 1; $createdBy = get_session_userid(); if (empty($insurerId) || empty($department) || empty($commissionMonth)) { @@ -135,10 +135,12 @@ class RuleImportController extends AdminController // 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; + + // $movedFullPath = $uploadDir . $safeName; - $file->move($uploadDir, $targetFileName); + $file->move($uploadDir, $safeName); + $targetFileName = $file->getName(); + $movedFullPath = $uploadDir . $targetFileName; if (!file_exists($movedFullPath)) { $this->myLogger->logme('error', "RuleImportController::upload - Failed to move uploaded file to {$movedFullPath}"); return $this->respond(['status' => false, 'code' => 404, 'message' => 'Failed to store uploaded file.'], 500); @@ -225,13 +227,16 @@ class RuleImportController extends AdminController $rulesCount = count($rulesArray); // Save JSON to WRITEPATH . 'uploads/commission/json/{insurer_id}_{department}.json' - $jsonDir = WRITEPATH . 'uploads/commission/json/'; + $month_path = strtoupper(date('M', strtotime($commissionMonth))) . date('Y', strtotime($commissionMonth)); + $jsonDir = WRITEPATH . 'uploads/commission/rules/'.$month_path . '/'; if (!is_dir($jsonDir)) { if (!mkdir($jsonDir, 0755, true) && !is_dir($jsonDir)) { throw new \RuntimeException("Failed to create JSON output directory: {$jsonDir}"); } } + $this->myLogger->logme('error', 'RuleImportController::jsonDir' . $jsonDir); + $deptSlug = preg_replace('/[^a-zA-Z0-9_\-]/', '_', strtolower($department)); $jsonName = (int)$insurerId . '_' . $deptSlug . '.json'; $jsonPath = $jsonDir . $jsonName; @@ -254,7 +259,65 @@ class RuleImportController extends AdminController ], 200); } - if (file_put_contents($jsonPath, $jsonData) === false) { + // handle existing JSON file based on $override (bool) + if (file_exists($jsonPath)) { + if ($overwrite) { + // delete existing file before writing (deterministic overwrite) + if (!@unlink($jsonPath)) { + $this->myLogger->logme('warning', 'RuleImportController::upload - Failed to delete existing JSON before overwrite', ['json_path' => $jsonPath]); + // proceed to overwrite anyway by writing to the same path + } + $finalJson = $jsonData; + } else { + // append: merge existing JSON with new JSON data + $existingRaw = @file_get_contents($jsonPath); + if ($existingRaw === false) { + $this->myLogger->logme('warning', 'RuleImportController::upload - Could not read existing JSON, will replace with new data', ['json_path' => $jsonPath]); + $finalJson = $jsonData; + } else { + $existingDecoded = json_decode($existingRaw, true); + $newDecoded = json_decode($jsonData, true); + + // if decoding fails, treat as empty array/object and log + if (json_last_error() !== JSON_ERROR_NONE && !is_array($existingDecoded) && !is_object($existingDecoded)) { + $this->myLogger->logme('warning', 'RuleImportController::upload - Existing JSON decode failed; replacing with new data', ['json_path' => $jsonPath, 'json_error' => json_last_error_msg()]); + $finalJson = $jsonData; + } else { + // normalize to PHP arrays for easy merging + if (!is_array($existingDecoded)) { + $existingDecoded = [$existingDecoded]; + } + if (!is_array($newDecoded)) { + $newDecoded = [$newDecoded]; + } + + // merge arrays (preserves numeric keys by reindexing) + $merged = array_merge($existingDecoded, $newDecoded); + $this->myLogger->logme('error', 'RuleImportController::JSON MERGED'); + $finalJson = json_encode($merged, JSON_PRETTY_PRINT); + if ($finalJson === false) { + $this->myLogger->logme('error', 'RuleImportController::upload - Failed to encode merged JSON', ['json_path' => $jsonPath, 'merge_count' => count($merged)]); + $this->commissionFilesModel->update($insertId, [ + 'file_status' => 'failed', + 'updated_by' => (int)$createdBy, + 'updated_at' => date('Y-m-d H:i:s'), + ]); + return $this->respond([ + 'status' => false, + 'code' => 500, + 'message' => 'Failed to encode merged rules JSON.' + ], 500); + } + } + } + } + } else { + // file doesn't exist, just write new data + $finalJson = $jsonData; + } + + // write final JSON to disk with exclusive lock + if (file_put_contents($jsonPath, $finalJson, LOCK_EX) === false) { $this->myLogger->logme('error', 'RuleImportController::upload - Failed to write rules JSON file', ['json_path' => $jsonPath]); $this->commissionFilesModel->update($insertId, [ 'file_status' => 'failed', @@ -263,11 +326,15 @@ class RuleImportController extends AdminController ]); return $this->respond([ 'status' => false, - 'code' => 404, + 'code' => 404, 'message' => 'Failed to store rules JSON file.' ], 500); } + // success continues... + $this->myLogger->logme('info', 'RuleImportController::upload - Rules JSON file written', ['json_path' => $jsonPath, 'overwrite' => (bool)$overwrite]); + + $this->myLogger->logme('info', 'RuleImportController::upload - Rules JSON written', [ 'file_id' => $insertId, 'json_path' => $jsonPath, @@ -306,7 +373,7 @@ class RuleImportController extends AdminController $errors = $result['errors'] ?? []; $updateData = [ - 'file_status' => 'validation_failed', + 'file_status' => 'failed', 'rules_count' => 0, // do not save rules 'updated_by' => (int)$createdBy, 'updated_at' => date('Y-m-d H:i:s'), @@ -347,8 +414,8 @@ class RuleImportController extends AdminController return $this->respond([ 'status' => false, 'code' => 404, - 'message' => 'Unexpected import service result.' - ], 500); + 'message' => $result['message'] + ], 200); } catch (\Throwable $ex) { $this->myLogger->logme('critical', 'RuleImportController::upload exception: ' . $ex->getMessage(), [ 'trace' => $ex->getTraceAsString()