GWM : commission amount update api
This commit is contained in:
parent
bfc0a54d57
commit
114f697fb9
@ -130,7 +130,9 @@ $routes->group('api', ['filter' => 'appSignature'], function ($routes) {
|
|||||||
$routes->get("policy/vehicleTypeMaster", "PolicyController::vehicleTypeMaster");
|
$routes->get("policy/vehicleTypeMaster", "PolicyController::vehicleTypeMaster");
|
||||||
$routes->get("policy/fuelTypeMaster", "PolicyController::fuelTypeMaster");
|
$routes->get("policy/fuelTypeMaster", "PolicyController::fuelTypeMaster");
|
||||||
$routes->get("policy/softdelete", "PolicyController::softdelete");
|
$routes->get("policy/softdelete", "PolicyController::softdelete");
|
||||||
|
$routes->get('policy/downloadPendingCommissionExcel', 'PolicyController::downloadPendingCommissionExcel');
|
||||||
|
$routes->post('policy/uploadCommissionExcel', 'PolicyController::uploadCommissionExcel');
|
||||||
|
$routes->post('policy/payoutInilneEditUpdate', 'PolicyController::payoutInilneEditUpdate');
|
||||||
|
|
||||||
//claims
|
//claims
|
||||||
$routes->get('claim/ClaimList', 'ClaimController::ClaimList');
|
$routes->get('claim/ClaimList', 'ClaimController::ClaimList');
|
||||||
|
|||||||
@ -5,6 +5,8 @@ use CodeIgniter\RESTful\ResourceController;
|
|||||||
use App\Models\PolicyModel;
|
use App\Models\PolicyModel;
|
||||||
use App\Models\EnquiryModel;
|
use App\Models\EnquiryModel;
|
||||||
use App\Models\QuotationModel;
|
use App\Models\QuotationModel;
|
||||||
|
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||||
|
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||||
|
|
||||||
class PolicyController extends ResourceController
|
class PolicyController extends ResourceController
|
||||||
{
|
{
|
||||||
@ -1411,14 +1413,331 @@ class PolicyController extends ResourceController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stream a simple XLSX (title row, header row, data rows) without totals row.
|
||||||
|
*/
|
||||||
|
private function streamPendingCommissionExcel(array $header, array $data, string $title, string $fileName): void
|
||||||
|
{
|
||||||
|
while (ob_get_level() > 0) {
|
||||||
|
ob_end_clean();
|
||||||
|
}
|
||||||
|
|
||||||
|
$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
|
||||||
|
$columnCount = count($header);
|
||||||
|
$lastCol = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($columnCount);
|
||||||
|
|
||||||
|
$sheet->mergeCells("A1:{$lastCol}1");
|
||||||
|
$sheet->setCellValue('A1', $title);
|
||||||
|
$sheet->getStyle('A1')->getFont()->setBold(true)->setSize(14);
|
||||||
|
$sheet->getStyle('A1')->getAlignment()->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
|
||||||
|
|
||||||
|
$sheet->fromArray($header, null, 'A2');
|
||||||
|
$sheet->getStyle("A2:{$lastCol}2")->getFont()->setBold(true);
|
||||||
|
$sheet->getStyle("A2:{$lastCol}2")->getFill()
|
||||||
|
->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)
|
||||||
|
->getStartColor()->setARGB('F2F2F2');
|
||||||
|
|
||||||
|
if ($data !== []) {
|
||||||
|
$sheet->fromArray($data, null, 'A3');
|
||||||
|
}
|
||||||
|
|
||||||
|
for ($i = 1; $i <= $columnCount; $i++) {
|
||||||
|
$col = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($i);
|
||||||
|
$sheet->getColumnDimension($col)->setAutoSize(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||||||
|
header("Content-Disposition: attachment; filename=\"{$fileName}\"");
|
||||||
|
header('Cache-Control: max-age=0');
|
||||||
|
|
||||||
|
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
|
||||||
|
$writer->save('php://output');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET: from_date, to_date (optional), agent_code (optional) — at least one filter required.
|
||||||
|
* Exports policies where commission_amount is NULL or 0 (active policies only).
|
||||||
|
*/
|
||||||
|
public function downloadPendingCommissionExcel()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$fromDate = $this->request->getGet('from_date');
|
||||||
|
$toDate = $this->request->getGet('to_date');
|
||||||
|
$agentCode = $this->request->getGet('agent_code');
|
||||||
|
$agentCode = $agentCode !== null && $agentCode !== '' ? trim((string) $agentCode) : null;
|
||||||
|
|
||||||
|
if ($fromDate === null || $fromDate === '') {
|
||||||
|
$fromDate = null;
|
||||||
|
}
|
||||||
|
if ($toDate === null || $toDate === '') {
|
||||||
|
$toDate = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($fromDate === null && $toDate === null && $agentCode === null) {
|
||||||
|
return $this->respond([
|
||||||
|
'status' => 'failed',
|
||||||
|
'code' => 400,
|
||||||
|
'data' => 'Provide at least one of: from_date, to_date, or agent_code',
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = \Config\Database::connect();
|
||||||
|
$builder = $db->table('partner_policy pp');
|
||||||
|
$builder->select('pa.agent_code, pp.policy_number');
|
||||||
|
$builder->join('partner_agent pa', 'pa.id = pp.agent_id', 'left');
|
||||||
|
$builder->where('pp.is_active', 1);
|
||||||
|
$builder->groupStart()
|
||||||
|
->where('pp.commission_amount', null)
|
||||||
|
->orWhere('pp.commission_amount', 0)
|
||||||
|
->groupEnd();
|
||||||
|
|
||||||
|
if ($fromDate !== null) {
|
||||||
|
$builder->where('pp.issued_date >=', date('Y-m-d', strtotime((string) $fromDate)));
|
||||||
|
}
|
||||||
|
if ($toDate !== null) {
|
||||||
|
$builder->where('pp.issued_date <=', date('Y-m-d', strtotime((string) $toDate)));
|
||||||
|
}
|
||||||
|
if ($agentCode !== null) {
|
||||||
|
$builder->where('pa.agent_code', $agentCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
$builder->orderBy('pa.agent_code', 'ASC');
|
||||||
|
$builder->orderBy('pp.policy_number', 'ASC');
|
||||||
|
|
||||||
|
$rows = $builder->get()->getResultArray();
|
||||||
|
|
||||||
|
$dataRows = [];
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
$dataRows[] = [
|
||||||
|
$row['agent_code'] ?? '',
|
||||||
|
$row['policy_number'] ?? '',
|
||||||
|
'',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$header = ['Agent Code', 'Policy Number', 'Payout Amount'];
|
||||||
|
|
||||||
|
$fromPart = $fromDate !== null ? date('Y-m-d', strtotime((string) $fromDate)) : 'na';
|
||||||
|
$toPart = $toDate !== null ? date('Y-m-d', strtotime((string) $toDate)) : 'na';
|
||||||
|
$agentPart = $agentCode !== null
|
||||||
|
? preg_replace('/[^A-Za-z0-9_-]+/', '_', $agentCode)
|
||||||
|
: 'all_agents';
|
||||||
|
$fileName = "commission_pending_{$fromPart}_{$toPart}_{$agentPart}.xlsx";
|
||||||
|
|
||||||
|
$title = 'Pending commission payout (fill Payout Amount and re-upload)';
|
||||||
|
|
||||||
|
$this->streamPendingCommissionExcel($header, $dataRows, $title, $fileName);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return $this->respond([
|
||||||
|
'status' => 'failed',
|
||||||
|
'code' => 500,
|
||||||
|
'message' => $e->getMessage(),
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST multipart field: commission_excel (xlsx). Updates partner_policy.commission_amount by policy number.
|
||||||
|
*/
|
||||||
|
public function uploadCommissionExcel()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$file = $this->request->getFile('commission_excel');
|
||||||
|
if ($file === null || ! $file->isValid()) {
|
||||||
|
return $this->respond([
|
||||||
|
'status' => 'failed',
|
||||||
|
'code' => 400,
|
||||||
|
'data' => 'commission_excel file is required (xlsx)',
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
$ext = strtolower((string) $file->getClientExtension());
|
||||||
|
if ($ext !== 'xlsx') {
|
||||||
|
return $this->respond([
|
||||||
|
'status' => 'failed',
|
||||||
|
'code' => 400,
|
||||||
|
'data' => 'Only .xlsx files are supported',
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
$spreadsheet = IOFactory::load($file->getTempName());
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
$highestRow = (int) $sheet->getHighestDataRow();
|
||||||
|
|
||||||
|
$headerRowNum = null;
|
||||||
|
for ($r = 1; $r <= min(5, $highestRow); $r++) {
|
||||||
|
$a = strtolower(trim((string) $sheet->getCell(Coordinate::stringFromColumnIndex(1) . $r)->getValue()));
|
||||||
|
$b = strtolower(trim((string) $sheet->getCell(Coordinate::stringFromColumnIndex(2) . $r)->getValue()));
|
||||||
|
if ($a === 'agent code' && str_contains($b, 'policy')) {
|
||||||
|
$headerRowNum = $r;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($headerRowNum === null) {
|
||||||
|
return $this->respond([
|
||||||
|
'status' => 'failed',
|
||||||
|
'code' => 400,
|
||||||
|
'data' => 'Could not find header row (Agent Code, Policy Number)',
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
$db = \Config\Database::connect();
|
||||||
|
$db->transStart();
|
||||||
|
|
||||||
|
$updated = 0;
|
||||||
|
$skipped = 0;
|
||||||
|
$errors = [];
|
||||||
|
|
||||||
|
for ($r = $headerRowNum + 1; $r <= $highestRow; $r++) {
|
||||||
|
$policyNumber = trim((string) $sheet->getCell('B' . $r)->getFormattedValue());
|
||||||
|
$payoutRaw = $sheet->getCell('C' . $r)->getCalculatedValue();
|
||||||
|
|
||||||
|
if ($policyNumber === '') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($payoutRaw === null || $payoutRaw === '') {
|
||||||
|
$skipped++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_numeric($payoutRaw)) {
|
||||||
|
$amount = (float) $payoutRaw;
|
||||||
|
} else {
|
||||||
|
$amount = (float) str_replace([',', ' '], '', (string) $payoutRaw);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($amount < 0 || is_nan($amount)) {
|
||||||
|
$errors[] = "Row {$r}: invalid payout for policy {$policyNumber}";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$policy = $this->PolicyModel->where('policy_number', $policyNumber)->where('is_active', 1)->first();
|
||||||
|
if (! $policy) {
|
||||||
|
$errors[] = "Row {$r}: policy not found: {$policyNumber}";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->PolicyModel->update((int) $policy['id'], ['commission_amount' => $amount]);
|
||||||
|
$updated++;
|
||||||
|
}
|
||||||
|
|
||||||
|
$db->transComplete();
|
||||||
|
|
||||||
|
if ($db->transStatus() === false) {
|
||||||
|
return $this->respond([
|
||||||
|
'status' => 'failed',
|
||||||
|
'code' => 500,
|
||||||
|
'data' => 'Transaction failed',
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->respond([
|
||||||
|
'status' => 'success',
|
||||||
|
'code' => 200,
|
||||||
|
'data' => [
|
||||||
|
'updated_rows' => $updated,
|
||||||
|
'skipped_empty_payout' => $skipped,
|
||||||
|
'errors' => $errors,
|
||||||
|
],
|
||||||
|
], 200);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return $this->respond([
|
||||||
|
'status' => 'failed',
|
||||||
|
'code' => 500,
|
||||||
|
'message' => $e->getMessage(),
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST JSON: id (partner_policy.id), commission_amount (number or null).
|
||||||
|
*/
|
||||||
|
public function payoutInilneEditUpdate()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$data = $this->request->getJSON(true);
|
||||||
|
if (! is_array($data)) {
|
||||||
|
return $this->respond([
|
||||||
|
'status' => 'failed',
|
||||||
|
'code' => 400,
|
||||||
|
'data' => 'Invalid JSON body',
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! isset($data['id']) || $data['id'] === '' || $data['id'] === null) {
|
||||||
|
return $this->respond([
|
||||||
|
'status' => 'failed',
|
||||||
|
'code' => 400,
|
||||||
|
'data' => 'id is required',
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! array_key_exists('commission_amount', $data)) {
|
||||||
|
return $this->respond([
|
||||||
|
'status' => 'failed',
|
||||||
|
'code' => 400,
|
||||||
|
'data' => 'commission_amount is required',
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
$id = (int) $data['id'];
|
||||||
|
$policy = $this->PolicyModel->find($id);
|
||||||
|
if (! $policy) {
|
||||||
|
return $this->respond([
|
||||||
|
'status' => 'failed',
|
||||||
|
'code' => 404,
|
||||||
|
'data' => 'Data Not Found',
|
||||||
|
], 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$raw = $data['commission_amount'];
|
||||||
|
if ($raw === null || $raw === '') {
|
||||||
|
$commission = null;
|
||||||
|
} elseif (is_numeric($raw)) {
|
||||||
|
$commission = (float) $raw;
|
||||||
|
} else {
|
||||||
|
$clean = str_replace([',', ' '], '', (string) $raw);
|
||||||
|
if ($clean === '' || ! is_numeric($clean)) {
|
||||||
|
return $this->respond([
|
||||||
|
'status' => 'failed',
|
||||||
|
'code' => 400,
|
||||||
|
'data' => 'commission_amount must be numeric or null',
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
$commission = (float) $clean;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($commission !== null && ($commission < 0 || is_nan($commission))) {
|
||||||
|
return $this->respond([
|
||||||
|
'status' => 'failed',
|
||||||
|
'code' => 400,
|
||||||
|
'data' => 'commission_amount cannot be negative',
|
||||||
|
], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->PolicyModel->update($id, ['commission_amount' => $commission]);
|
||||||
|
|
||||||
|
return $this->respond([
|
||||||
|
'status' => 'success',
|
||||||
|
'code' => 200,
|
||||||
|
'data' => [
|
||||||
|
'id' => $id,
|
||||||
|
'commission_amount' => $commission,
|
||||||
|
],
|
||||||
|
], 200);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return $this->respond([
|
||||||
|
'status' => 'failed',
|
||||||
|
'code' => 500,
|
||||||
|
'message' => $e->getMessage(),
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user