|
|
@@ -0,0 +1,484 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+ namespace App\Controllers;
|
|
|
+
|
|
|
+ use CodeIgniter\RESTful\ResourceController;
|
|
|
+
|
|
|
+ class Winner extends ResourceController
|
|
|
+ {
|
|
|
+ //당첨자 리스트
|
|
|
+ public function winnerlist()
|
|
|
+ {
|
|
|
+ $db = \Config\Database::connect();
|
|
|
+
|
|
|
+ // POST JSON 파라미터 받기
|
|
|
+ $request = $this->request->getJSON(true);
|
|
|
+ if (!isset($request['compId'])) {
|
|
|
+ return $this->respond([
|
|
|
+ 'status' => 'fail',
|
|
|
+ 'message' => 'filter(compId)가 누락되었습니다.'
|
|
|
+ ], 400);
|
|
|
+ }
|
|
|
+ $status = isset($request['status']) ? $request['status'] : null;
|
|
|
+ $compId = $request['compId'];
|
|
|
+ // 쿼리 빌더
|
|
|
+ $builder = $db->table('EVT_LIST');
|
|
|
+ // compId가 '0-000000'이 아닐 때만 COMP_ID 조건 추가
|
|
|
+ if ($compId !== '0-000000') {
|
|
|
+ $builder->where('COMP_ID', $compId);
|
|
|
+ }
|
|
|
+ if ($status !== null) {
|
|
|
+ // status가 넘어오면 해당 값만 검색
|
|
|
+ $builder->where('status', $status);
|
|
|
+ }
|
|
|
+
|
|
|
+ $lists = $builder->get()->getResultArray();
|
|
|
+
|
|
|
+ foreach ($lists as &$row) {
|
|
|
+ if (isset($row['STARTDATE']) && !empty($row['STARTDATE'])) {
|
|
|
+ $row['STARTDATE'] = date('Y-m-d', strtotime($row['STARTDATE']));
|
|
|
+ }
|
|
|
+ if (isset($row['ENDDATE']) && !empty($row['ENDDATE'])) {
|
|
|
+ $row['ENDDATE'] = date('Y-m-d', strtotime($row['ENDDATE']));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // 반환 데이터 가공 (필요시)
|
|
|
+ $filtered = array_reverse($lists);
|
|
|
+
|
|
|
+ return $this->respond($filtered, 200);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ //이벤트 마감 체크
|
|
|
+ public function winnerChk()
|
|
|
+ {
|
|
|
+ $db = \Config\Database::connect();
|
|
|
+
|
|
|
+ $seq = null;
|
|
|
+ $requestJson = $this->request->getJSON(true);
|
|
|
+ if (is_array($requestJson) && isset($requestJson['seq'])) {
|
|
|
+ $seq = $requestJson['seq'];
|
|
|
+ }
|
|
|
+
|
|
|
+ if (empty($seq)) {
|
|
|
+ return $this->respond(['status' => 'fail', 'message' => '필수 파라미터 누락'], 400);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // EVT_ITEM에서 해당 seq 로 아이템과 WIN_QTY 조회
|
|
|
+ $items = $db->table('EVT_ITEM')
|
|
|
+ ->select('ITEM_SEQ, WIN_QTY')
|
|
|
+ ->where('EVT_SEQ', $seq)
|
|
|
+ ->get()->getResultArray();
|
|
|
+
|
|
|
+ // 아이템별 최대 당첨자수 배열 구성
|
|
|
+ $maxWinners = [];
|
|
|
+ foreach ($items as $idx => $item) {
|
|
|
+ $rank = $idx + 1; // 1등부터 시작
|
|
|
+ $maxWinners[$rank] = (int)$item['WIN_QTY'];
|
|
|
+ }
|
|
|
+
|
|
|
+ // PARTICIPATION_LIST에서 seq로 당첨자 집계 (RANK별 COUNT)
|
|
|
+ $counts = [];
|
|
|
+ $results = $db->table('PARTICIPATION_LIST')
|
|
|
+ ->select('RANK, COUNT(*) as cnt')
|
|
|
+ ->where('EVT_SEQ', $seq)
|
|
|
+ ->groupBy('RANK')
|
|
|
+ ->get()->getResultArray();
|
|
|
+ foreach ($results as $row) {
|
|
|
+ $counts[(int)$row['RANK']] = (int)$row['cnt'];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 모든 RANK의 당첨자수가 max와 같거나 크면 "마감"
|
|
|
+ $isClosed = true;
|
|
|
+ foreach ($maxWinners as $rank => $qty) {
|
|
|
+ $curr = isset($counts[$rank]) ? $counts[$rank] : 0;
|
|
|
+ if ($curr < $qty) {
|
|
|
+ $isClosed = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($isClosed) {
|
|
|
+ return $this->respond(['status' => 'closed', 'message' => '마감되었습니다'], 200);
|
|
|
+ } else {
|
|
|
+ return $this->respond(['status' => 'open', 'message' => '아직 마감 아님'], 200);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ //당첨자 등록 및 랭크 반환
|
|
|
+ public function winnerReg()
|
|
|
+ {
|
|
|
+ $db = \Config\Database::connect();
|
|
|
+
|
|
|
+ // 파라미터 추출
|
|
|
+ $seq = null;
|
|
|
+ $name = null;
|
|
|
+ $phone = null;
|
|
|
+
|
|
|
+ $request = $this->request->getJSON(true);
|
|
|
+ if (is_array($request) && isset($request['seq'])) {
|
|
|
+ $seq = $request['seq'];
|
|
|
+ $name = $request['name'];
|
|
|
+ $phone = $request['phone'];
|
|
|
+ } else {
|
|
|
+ $seq = $this->request->getPost('seq');
|
|
|
+ $name = $this->request->getPost('name');
|
|
|
+ $phone = $this->request->getPost('phone');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 등수별 설정 및 ITEM_NAME 매핑
|
|
|
+ $rankConfigs = [];
|
|
|
+ $itemNames = [];
|
|
|
+
|
|
|
+ if (!empty($seq)) {
|
|
|
+ $builder = $db->table('EVT_ITEM');
|
|
|
+ $builder->select('WIN_RATE, WIN_QTY, ITEM_NAME');
|
|
|
+ $builder->where('EVT_SEQ', $seq);
|
|
|
+ $builder->orderBy('ITEM_SEQ', 'ASC');
|
|
|
+ $rows = $builder->get()->getResultArray();
|
|
|
+
|
|
|
+ foreach ($rows as $i => $row) {
|
|
|
+ $rank = $i + 1; // 1등부터 시작
|
|
|
+ $rankConfigs[$rank] = [
|
|
|
+ 'percent' => (int)$row['WIN_RATE'],
|
|
|
+ 'max' => (int)$row['WIN_QTY']
|
|
|
+ ];
|
|
|
+ $itemNames[$rank] = $row['ITEM_NAME'];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 등수별 참여자 집계
|
|
|
+ $builder = $db->table('PARTICIPATION_LIST')
|
|
|
+ ->select('RANK, COUNT(*) AS cnt')
|
|
|
+ ->where('EVT_SEQ', $seq)
|
|
|
+ ->groupBy('RANK');
|
|
|
+ $result = $builder->get()->getResultArray();
|
|
|
+
|
|
|
+ $winnerCounts = [];
|
|
|
+ foreach ($result as $row) {
|
|
|
+ $winnerCounts[(int)$row['RANK']] = (int)$row['cnt'];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 가능한 등수 구하기
|
|
|
+ $availableRanks = [];
|
|
|
+ $totalPercent = 0;
|
|
|
+ foreach ($rankConfigs as $rank => $cfg) {
|
|
|
+ $cnt = isset($winnerCounts[$rank]) ? $winnerCounts[$rank] : 0;
|
|
|
+ if ($cnt < $cfg['max']) {
|
|
|
+ $availableRanks[] = [
|
|
|
+ 'rank' => $rank,
|
|
|
+ 'percent' => $cfg['percent']
|
|
|
+ ];
|
|
|
+ $totalPercent += $cfg['percent'];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // if (empty($availableRanks)) {
|
|
|
+ // return $this->respond(['status' => 'fail', 'message' => '모든 등수 당첨자가 마감되었습니다.'], 200);
|
|
|
+ // }
|
|
|
+
|
|
|
+ if (empty($availableRanks)) {
|
|
|
+ // 등수 마감 상태 => rank 0으로 처리
|
|
|
+ $selectedRank = 0;
|
|
|
+ $selectedItemName = "꽝";
|
|
|
+ $rankIndex = 0;
|
|
|
+ } else {
|
|
|
+ // 기존 랜덤 등수 추출
|
|
|
+ $rand = mt_rand() / mt_getrandmax() * $totalPercent;
|
|
|
+ foreach ($availableRanks as $cfg) {
|
|
|
+ if ($rand < $cfg['percent']) {
|
|
|
+ $selectedRank = $cfg['rank'];
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ $rand -= $cfg['percent'];
|
|
|
+ }
|
|
|
+ if (!isset($selectedRank)) {
|
|
|
+ $selectedRank = $availableRanks[count($availableRanks) - 1]['rank'];
|
|
|
+ }
|
|
|
+ $selectedItemName = isset($itemNames[$selectedRank]) ? $itemNames[$selectedRank] : null;
|
|
|
+
|
|
|
+ // RANK_INDEX 구하기
|
|
|
+ $builder = $db->table('PARTICIPATION_LIST');
|
|
|
+ $builder->selectMax('RANK_INDEX');
|
|
|
+ $builder->where('EVT_SEQ', $seq);
|
|
|
+ $builder->where('RANK', $selectedRank);
|
|
|
+ $rankIndexRow = $builder->get()->getRowArray();
|
|
|
+ $rankIndex = isset($rankIndexRow['RANK_INDEX']) && $rankIndexRow['RANK_INDEX'] ? ((int)$rankIndexRow['RANK_INDEX']) + 1 : 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // DB 저장
|
|
|
+ $insertData = [
|
|
|
+ 'EVT_SEQ' => $seq,
|
|
|
+ 'RANK' => $selectedRank,
|
|
|
+ 'ITEM_NAME' => $selectedItemName,
|
|
|
+ 'NAME' => $name,
|
|
|
+ 'PHONE' => $phone,
|
|
|
+ 'RANK_INDEX' => $rankIndex,
|
|
|
+ 'PRIVACY_AGREE' => 1,
|
|
|
+ 'THIRDPARTY_AGREE' => 1
|
|
|
+ ];
|
|
|
+ $db->table('PARTICIPATION_LIST')->insert($insertData);
|
|
|
+
|
|
|
+ // 응답
|
|
|
+ return $this->respond([
|
|
|
+ 'rank' => $selectedRank,
|
|
|
+ 'item_name' => $selectedItemName,
|
|
|
+ 'rank_index' => $rankIndex,
|
|
|
+ 'name' => $name,
|
|
|
+ 'phone' => $phone,
|
|
|
+ ], 200);
|
|
|
+ }
|
|
|
+
|
|
|
+ //아이템 리스트
|
|
|
+ public function itemCount()
|
|
|
+ {
|
|
|
+ $db = \Config\Database::connect();
|
|
|
+ // POST 파라미터 JSON 또는 폼에서 받기 (JSON 우선)
|
|
|
+ $seq = null;
|
|
|
+ $request = $this->request->getJSON(true);
|
|
|
+ if (is_array($request) && isset($request['seq'])) {
|
|
|
+ $seq = $request['seq'];
|
|
|
+ } else {
|
|
|
+ $seq = $this->request->getPost('seq'); // 폼 방식 대비
|
|
|
+ }
|
|
|
+
|
|
|
+ if (empty($seq)) {
|
|
|
+ return $this->respond(['status' => 'fail', 'message' => 'seq 파라미터가 필요합니다.'], 400);
|
|
|
+ }
|
|
|
+
|
|
|
+ $builder = $db->table('EVT_ITEM');
|
|
|
+ $builder->select('ITEM_NAME');
|
|
|
+ $builder->where('EVT_SEQ', $seq);
|
|
|
+ $query = $builder->get();
|
|
|
+ $items = [];
|
|
|
+ foreach ($query->getResultArray() as $row) {
|
|
|
+ $items[] = $row['ITEM_NAME'];
|
|
|
+ }
|
|
|
+
|
|
|
+ $count = count($items);
|
|
|
+
|
|
|
+ return $this->respond([
|
|
|
+ 'count' => $count,
|
|
|
+ 'items' => $items
|
|
|
+ ], 200);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ //당첨자 상세
|
|
|
+ public function winnerDetail($seq)
|
|
|
+ {
|
|
|
+ $db = \Config\Database::connect();
|
|
|
+
|
|
|
+ // 이벤트 + 아이템 목록 조인 조회
|
|
|
+ $builder = $db->table('EVT_LIST E');
|
|
|
+ $builder->join('EVT_ITEM I', 'E.SEQ = I.EVT_SEQ', 'left');
|
|
|
+ $builder->join('PARTICIPATION_LIST P', 'E.SEQ = P.EVT_SEQ', 'left');
|
|
|
+ $builder->select(
|
|
|
+ 'E.SEQ, E.TITLE, E.STARTDATE, E.ENDDATE, E.REGDATE, ' .
|
|
|
+ 'I.ITEM_SEQ, I.ITEM_NAME AS ITEM_ITEM_NAME, I.WIN_QTY, I.WIN_RATE,' .
|
|
|
+ 'P.PART_SEQ, P.RANK, P.ITEM_NAME AS PART_ITEM_NAME, P.ID, P.NAME, P.PHONE, P.WINNER_DATE, P.RANK_INDEX, P.PRIVACY_AGREE, P.THIRDPARTY_AGREE'
|
|
|
+ );
|
|
|
+ $builder->where('E.SEQ', $seq);
|
|
|
+
|
|
|
+ $rows = $builder->get()->getResultArray();
|
|
|
+
|
|
|
+ if (empty($rows)) {
|
|
|
+ return $this->respond(['status' => 'fail', 'message' => '해당 이벤트가 없습니다.'], 404);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 이벤트(게시글) 정보와 아이템 배열로 가공하여 응답
|
|
|
+ $event = [
|
|
|
+ 'seq' => $rows[0]['SEQ'],
|
|
|
+ 'title' => $rows[0]['TITLE'],
|
|
|
+ 'startdate' => date('Y-m-d', strtotime( $rows[0]['STARTDATE'])),
|
|
|
+ 'enddate' => date('Y-m-d', strtotime( $rows[0]['ENDDATE'])),
|
|
|
+ 'regdate' =>date('Y-m-d', strtotime( $rows[0]['REGDATE'])),
|
|
|
+ 'items' => [],
|
|
|
+ 'participations' => [],
|
|
|
+ 'participations_cal' => []
|
|
|
+ ];
|
|
|
+
|
|
|
+ // 중복방지용
|
|
|
+ $itemSeqSet = [];
|
|
|
+ $partSeqSet = [];
|
|
|
+
|
|
|
+ foreach ($rows as $row) {
|
|
|
+ // 아이템 중복 체크 및 추가
|
|
|
+ if ($row['ITEM_SEQ'] !== null && !isset($itemSeqSet[$row['ITEM_SEQ']])) {
|
|
|
+ $event['items'][] = [
|
|
|
+ 'item_seq' => $row['ITEM_SEQ'],
|
|
|
+ 'name' => $row['ITEM_ITEM_NAME'], // 반드시! EVT_ITEM 테이블의 컬럼명 별칭
|
|
|
+ 'qty' => $row['WIN_QTY'],
|
|
|
+ 'rate' => $row['WIN_RATE']
|
|
|
+ ];
|
|
|
+ $itemSeqSet[$row['ITEM_SEQ']] = true;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // 참여자 중복 체크 및 추가
|
|
|
+ if ($row['PART_SEQ'] !== null && !isset($partSeqSet[$row['PART_SEQ']])) {
|
|
|
+ $event['participations'][] = [
|
|
|
+ 'part_seq' => $row['PART_SEQ'],
|
|
|
+ 'rank' => $row['RANK'],
|
|
|
+ 'item_name' => $row['PART_ITEM_NAME'],
|
|
|
+ 'id' => $row['ID'],
|
|
|
+ 'name' => $row['NAME'],
|
|
|
+ 'phone' => $row['PHONE'],
|
|
|
+ 'winner_date' => $row['WINNER_DATE'] = date('Y-m-d', strtotime($row['WINNER_DATE'])),
|
|
|
+ 'rank_index' => $row['RANK_INDEX'],
|
|
|
+ 'privacy_agree' => $row['PRIVACY_AGREE'],
|
|
|
+ 'thirdparty_agree' => $row['THIRDPARTY_AGREE']
|
|
|
+ ];
|
|
|
+ $partSeqSet[$row['PART_SEQ']] = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // 중복되는 rank에서 part_seq가 가장 낮은 값만 participations_cal에 담기
|
|
|
+ // 유니크 참여자 배열 만들기
|
|
|
+ $participations = [];
|
|
|
+ foreach ($rows as $row) {
|
|
|
+ if (
|
|
|
+ !array_key_exists('PART_SEQ', $row) ||
|
|
|
+ !array_key_exists('RANK', $row) ||
|
|
|
+ $row['PART_SEQ'] === null ||
|
|
|
+ $row['RANK'] === null ||
|
|
|
+ $row['RANK'] == 0
|
|
|
+ ) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ $participations[$row['PART_SEQ']] = $row;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 등수별 인원수 카운트
|
|
|
+ $rankCounts = [];
|
|
|
+ foreach ($participations as $part) {
|
|
|
+ $rank = $part['RANK'];
|
|
|
+ if (!isset($rankCounts[$rank])) {
|
|
|
+ $rankCounts[$rank] = 0;
|
|
|
+ }
|
|
|
+ $rankCounts[$rank]++;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 중복 등수에서 part_seq가 가장 낮은 값만 participations_cal에 담기 (참여자 기준)
|
|
|
+ $rankMinPartSeq = [];
|
|
|
+ foreach ($participations as $part) {
|
|
|
+ $rank = $part['RANK'];
|
|
|
+ $partSeq = $part['PART_SEQ'];
|
|
|
+ if (!isset($rankMinPartSeq[$rank]) || $partSeq < $rankMinPartSeq[$rank]['part_seq']) {
|
|
|
+ $rankMinPartSeq[$rank] = [
|
|
|
+ 'part_seq' => $partSeq,
|
|
|
+ 'rank' => $part['RANK'],
|
|
|
+ 'item_name' => $part['PART_ITEM_NAME'],
|
|
|
+ 'id' => $part['ID'],
|
|
|
+ 'name' => $part['NAME'],
|
|
|
+ 'phone' => $part['PHONE'],
|
|
|
+ 'winner_date' => $part['WINNER_DATE'],
|
|
|
+ 'rank_index' => $part['RANK_INDEX'],
|
|
|
+ 'privacy_agree' => $part['PRIVACY_AGREE'],
|
|
|
+ 'thirdparty_agree' => $part['THIRDPARTY_AGREE'],
|
|
|
+ 'count' => $rankCounts[$rank]
|
|
|
+ ];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $event['participations_cal'] = array_values($rankMinPartSeq);
|
|
|
+
|
|
|
+ return $this->respond($event, 200);
|
|
|
+ }
|
|
|
+
|
|
|
+ //참여자 리스트
|
|
|
+ public function getParticipationByItem()
|
|
|
+ {
|
|
|
+ $db = \Config\Database::connect();
|
|
|
+ $request = $this->request->getJSON(true);
|
|
|
+
|
|
|
+ // 파라미터 추출
|
|
|
+ $seq = isset($request['seq']) ? $request['seq'] : null;
|
|
|
+ $itemName = isset($request['item_name']) ? $request['item_name'] : null;
|
|
|
+
|
|
|
+ if (empty($seq)) {
|
|
|
+ return $this->respond(['status' => 'fail', 'message' => 'seq는 필수입니다.'], 400);
|
|
|
+ }
|
|
|
+
|
|
|
+ // PARTICIPATION_LIST에서 EVT_SEQ와 ITEM_NAME으로 필터링
|
|
|
+ $builder = $db->table('PARTICIPATION_LIST');
|
|
|
+ $builder->where('EVT_SEQ', $seq);
|
|
|
+ if (!empty($itemName)) {
|
|
|
+ $builder->where('ITEM_NAME', $itemName);
|
|
|
+ }
|
|
|
+
|
|
|
+ $filterList = $builder->get()->getResultArray();
|
|
|
+
|
|
|
+ // 키를 모두 소문자로 변환
|
|
|
+ $filterListLower = [];
|
|
|
+ foreach ($filterList as $row) {
|
|
|
+ $filterListLower[] = array_change_key_case($row, CASE_LOWER);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ return $this->respond([
|
|
|
+ 'status' => 'success',
|
|
|
+ 'list' => $filterListLower
|
|
|
+ ], 200);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 이벤트 참가 여부 체크
|
|
|
+ public function matchedUser()
|
|
|
+ {
|
|
|
+ $data = $this->request->getJSON(true);
|
|
|
+
|
|
|
+ $seq = $data['seq'] ?? null;
|
|
|
+ $name = $data['name'] ?? null;
|
|
|
+ $phone = $data['phone'] ?? null;
|
|
|
+
|
|
|
+
|
|
|
+ if (!$seq || !$name || !$phone) {
|
|
|
+ return $this->fail('필수 값이 누락되었습니다.', 400);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ $db = \Config\Database::connect();
|
|
|
+ $builder = $db->table('PARTICIPATION_LIST');
|
|
|
+
|
|
|
+
|
|
|
+ $existing = $builder
|
|
|
+ ->where('EVT_SEQ', $seq)
|
|
|
+ ->where('NAME', $name)
|
|
|
+ ->where('PHONE', $phone)
|
|
|
+ ->get()
|
|
|
+ ->getRowArray();
|
|
|
+
|
|
|
+ if ($existing) {
|
|
|
+ // 동일한 사람이 이미 존재할 경우
|
|
|
+ return $this->respond([
|
|
|
+ 'result' => 'matched'
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ $phoneSame = $builder
|
|
|
+ ->where('EVT_SEQ', $seq)
|
|
|
+ ->where('NAME !=', $name)
|
|
|
+ ->where('PHONE', $phone)
|
|
|
+ ->get()
|
|
|
+ ->getRowArray();
|
|
|
+
|
|
|
+ if ($phoneSame) {
|
|
|
+ return $this->respond([
|
|
|
+ 'result' => 'phonesame'
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 일치하는 정보가 없을 때 (필요에 따라 처리)
|
|
|
+ return $this->respond([
|
|
|
+ 'result' => 'not_found'
|
|
|
+ ]);
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|