오늘은 고객사에서 상품을 주문하면 공휴일이나 주말일 때는 다음 영업일로 상품 발송 예정일을 띄워주고 싶다고 해서 공휴일 API를 사용해보았다.
물론 고객사 자체 휴무일이나 택배사 관련으로 휴무일을 지정해야한다면 휴무일을 다룰 수 있도록 개발하면 좋겠지만 고객사에서는 그것까진 필요하지 않다고 하니,, 공휴일 데이터를 가져와서 DB에 넣어주고 결제완료된 날짜를 가져와 공휴일인지 체크하도록 구현했다.
샘플코드에 여러 언어가 있어 사용하기에는 간편했다!
한국천문연구원_특일 정보
(천문우주정보)국경일정보, 공휴일정보, 기념일정보, 24절기정보, 잡절정보를 조회하는 서비스 입니다. 활용시 날짜, 순번, 특일정보의 분류, 공공기관 휴일 여부, 명칭을 확인할 수 있습니다.
www.data.go.kr
📦 Component
protected $service_key = '발급받은키';
public $data = array();
public function __construct () {
}
public function __destruct () {
}
/**
* holiday
*
* 공휴일 데이터 리턴
*
* @param int $year 4 length
* @param int $month 2 length
*/
public function holiday ($year,$month) {
$path = $content = $day = '';
$data = $xml = $json = $list = array();
$month = sprintf('%02d',$month);
$path = $this->url.'getHoliDeInfo?serviceKey='.$this->service_key.'&solYear='.$year.'&solMonth='.$month;
$content = file_get_contents($path);
$xml = simplexml_load_string($content,null,LIBXML_NOCDATA);
$json = json_encode($xml);
$list = json_decode($json,TRUE);
if ($list['body']['totalCount'] == 1) {
$day = mb_substr($list['body']['items']['item']['locdate'],6,2,'UTF-8');
$this->data[$day][] = $data['data'][$day][] = array(
'date'=>$year.'-'.$month.'-'.$day,
'name'=>$list['body']['items']['item']['dateName'],
'category'=>'holiday'
);
} else if ($list['body']['totalCount'] > 0) {
foreach ($list['body']['items']['item'] as $row) {
$day = mb_substr($row['locdate'],6,2,'UTF-8');
$this->data[$day][] = $data['data'][$day][] = array(
'date'=>$year.'-'.$month.'-'.$day,
'name'=>$row['dateName'],
'category'=>'holiday'
);
}
}
return $data;
}
데이터를 가공해서 날짜, 공휴일 이름, 카테고리가 들어갈 수 있게 해두었다.
🎮 Controller
class HolidayController extends \Controller\Api\Controller
{
public function index()
{
$db = \App::load('DB');
$holidayData = new HolidayData();
$allHolidayData = array();
// 시작 연도와 월
$startYear = 2024;
$startMonth = 1;
// 종료 연도와 월
$endYear = 2025;
$endMonth = 12;
for ($year = $startYear; $year <= $endYear; $year++) {
// 시작 연도일 때는 시작 월부터, 종료 연도일 때는 종료 월까지 반복
$start = ($year == $startYear) ? $startMonth : 1;
$end = ($year == $endYear) ? $endMonth : 12;
for ($month = $start; $month <= $end; $month++) {
$allHolidayData[] = $holidayData->holiday($year, $month);
}
}
foreach ($allHolidayData as $item) {
foreach ($item['data'] as $day => $data) {
foreach ($data as $info) {
$date = $info['date']; // 날짜
$name = $info['name']; // 이름
$sql = "INSERT INTO asmo_calendar (holiday, name) VALUES ('$date', '$name')";
$db->query($sql);
}
}
}
}
}
컨트롤러를 만들다 보니 카테고리는 필요 없을 것 같아서 DB에 따로 넣어주진 않았다..
데이터는 25년도까지만 존재했다!
🛢️ DB
DB에 저장 완료!
뭔가 코드가 깔끔하지 않은 것 같지만,,, 물어볼 사람이 없는 나는 오늘도 혼자 해결하고,,, 성장하는중,,,, ?
이제 결제가 완료되었을 때 발송 예정일을 넣기 위한 메소드를 Order 컴포넌트에 만들어 주고 이 메소드를 불러서 사용하면 끝이다!
//20240328 lyj 배송 예정일 계산하기
public function insertDeliveryDt($orderNo)
{
$sql = "SELECT paymentDt FROM es_order WHERE orderNo = '".$orderNo."'";
list($paymentDt) = $this->db->query_fetch($sql);
//결제 날자를 날짜와 시간으로 분리
$paymentDateTime = $paymentDt['paymentDt'];
list($paymentDate, $paymentTime) = explode(' ', $paymentDateTime);
//결제일이 무슨 요일인지 확인 (토,일은 각각 6,7 이다.)
$weekday = date('N', strtotime($paymentDate));
//공휴일 테이블에 결제날짜가 있는지 확인한다.
$sql_str= "SELECT sno FROM asmo_calendar WHERE holiday = '".$paymentDate."'";
list($isHoilday) = $this->db->query_fetch($sql_str);
//결제날짜가 공휴일이 아닌 평일 오후 1시 이전결제일 때
if(($weekday >= 1 && $weekday <= 5) && ($paymentTime <= '13:00:59') && !$isHoilday) {
$deliveryDate = date('Y-m-d');
} else {
// 결제날짜가 주말, 공휴일, 오후1시 이후 일 때 다음 영업일로 배송 예정일 설정
$nextDay = strtotime($paymentDate . '+1 day');
while (true) {
// 다음 날짜가 주말이나 공휴일인 경우 다음 날짜로 이동
$nextDayDate = date('Y-m-d', $nextDay);
$nextDayWeekday = date('N', $nextDay);
$sql_str = "SELECT sno FROM asmo_calendar WHERE holiday = '".$nextDayDate."'";
list($isHoliday) = $this->db->query_fetch($sql_str);
if ($nextDayWeekday >= 6 || $isHoliday) {
// 주말이나 공휴일이면 다음 날짜로 이동
$nextDay = strtotime($nextDayDate . '+1 day');
} else {
break;
}
}
$deliveryDate = date('Y-m-d', $nextDay);
}
//다음 상품 배송 예정일
$nextMonth = strtotime($paymentDate . '+1 month');
while (true) {
// 다음 날짜가 주말이나 공휴일인 경우 다음 날짜로 이동
$nextMonthDate = date('Y-m-d', $nextMonth);
$nextMonthWeekday = date('N', $nextMonth);
$sql_str = "SELECT sno FROM asmo_calendar WHERE holiday = '".$nextMonthDate."'";
list($isHoliday) = $this->db->query_fetch($sql_str);
if ($nextMonthWeekday >= 6 || $isHoliday) {
// 주말이나 공휴일이면 다음 날짜로 이동
$nextMonth = strtotime($nextMonthDate . '+1 day');
} else {
break;
}
}
$deliveryDtNextMonth = date('Y-m-d', $nextMonth);
//주문테이블 업데이트
$sql_str2 = "UPDATE es_order SET
originDeliveryDt = '".$deliveryDate."',
realDeliveryDt = '".$deliveryDtNextMonth."'
WHERE orderNo='".$orderNo."'";
$this->db->query($sql_str2);
}
학원 다닐 때 기본에 충실하겠다고 api 사용을 안해봤는데,, 회사와서 나름 조금씩 사용하니까 재밌는 것 같다 ㅎㅎ