From 26db8eb60263f405a06a09314a122ac7a7db6569 Mon Sep 17 00:00:00 2001 From: yangsh Date: Fri, 23 Jan 2026 15:08:41 +0900 Subject: [PATCH] =?UTF-8?q?fax=20cron=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Controllers/Webfax/Crontab.php | 204 +++++++++++++++++++++++++++++ app/Helpers/cron_helper.php | 13 ++ app/Libraries/qrcode.php | 29 ++++ app/Models/results/AssignModel.php | 8 +- app/Models/webfax/FaxModel.php | 194 +++++++++++++++++++++++++++ 5 files changed, 443 insertions(+), 5 deletions(-) create mode 100644 app/Controllers/Webfax/Crontab.php create mode 100644 app/Helpers/cron_helper.php create mode 100644 app/Libraries/qrcode.php create mode 100644 app/Models/webfax/FaxModel.php diff --git a/app/Controllers/Webfax/Crontab.php b/app/Controllers/Webfax/Crontab.php new file mode 100644 index 0000000..b93443f --- /dev/null +++ b/app/Controllers/Webfax/Crontab.php @@ -0,0 +1,204 @@ +selectFaxListNotExistsThumb(); + $fileCnt = 0; + $receiver = 'uds_tiff'; + + if (empty($res)) { + CLI::write('No target fax images.', 'yellow'); + return; + } + + foreach ($res as $row) { + $fileCnt++; + CLI::write("\n\n[{$fileCnt}] Processing...", 'green'); + + $mid = $row['mid'] ?? null; + $file_name = $row['file_name'] ?? ''; + $save_path = $row['save_path'] ?? ''; + $caller_no = $row['caller_no'] ?? ''; + $callee_no = $row['callee_no'] ?? ''; + $tiff_file_name = $row['file_name'] ?? ''; + $tiff_file_size = $row['file_size'] ?? ''; + $recv_time = $row['recv_time'] ?? ''; + $save_time = $row['save_time'] ?? ''; + + if (empty($save_path) || empty($file_name)) { + CLI::write(' - skip: save_path or file_name empty', 'yellow'); + continue; + } + + // ✅ pathinfo로 안전하게 처리 + $ext = strtolower(pathinfo($file_name, PATHINFO_EXTENSION)); + $base = pathinfo($file_name, PATHINFO_FILENAME); + + if (!in_array($ext, ['tif', 'tiff'], true)) { + CLI::write(" - skip: not tif/tiff ({$ext})", 'yellow'); + continue; + } + + if (substr($save_path, -1) !== '/') { + $save_path .= '/'; + } + + $tiffPath = $save_path . $file_name; + if (!is_file($tiffPath)) { + CLI::write(" - skip: file not found ({$tiffPath})", 'yellow'); + continue; + } + + CLI::write(" - TIFF: {$tiffPath}"); + + try { + // ✅ TIFF 다중 페이지 안전 처리 + $im = new \Imagick(); + $im->readImage($tiffPath); + + // coalesce: 멀티프레임 안정화(특히 tiff/gif 계열) + $frames = $im->coalesceImages(); + + $index = 0; + foreach ($frames as $frame) { + try { + // 페이지별 정보 + $image_width = (int) $frame->getImageWidth(); + $image_height = (int) $frame->getImageHeight(); + $image_size = (int) $frame->getImageLength(); + + // 출력 경로 + $jpgName = "{$base}_{$index}.jpg"; + $jpgPath = $save_path . $jpgName; + $thumbName = "{$base}_{$index}_thumb.jpg"; + $thumbPath = $save_path . $thumbName; + + // ✅ JPG로 변환(페이지별로 frame clone 사용 권장) + $page = clone $frame; + + // 이미지 포맷/품질(필요시 조정) + $page->setImageFormat('jpeg'); + $page->setImageCompression(\Imagick::COMPRESSION_JPEG); + $page->setImageCompressionQuality(85); + + // ✅ 리사이즈 (가로 800 제한) + if ($image_width > 800) { + $resize_width = 800; + $ratio = $resize_width / max(1, $image_width); + $resize_height = (int) round($image_height * $ratio); + $page->resizeImage($resize_width, $resize_height, \Imagick::FILTER_LANCZOS, 1, true); + } + + if (!$page->writeImage($jpgPath)) { + CLI::write(" - fail: write jpg ({$jpgPath})", 'red'); + $page->clear(); + $page->destroy(); + $index++; + continue; + } + + // ✅ QR scan (실패해도 계속) + $qrcode_data = ''; + try { + $qrcode_data = (string) $qrCode->scan($jpgPath); + } catch (\Throwable $e) { + log_message('error', 'QR scan failed: ' . $e->getMessage()); + } + + // ✅ 썸네일은 clone으로 (원본/페이지 훼손 방지) + $thumb = clone $page; + $thumb->thumbnailImage(105, 80, true); + + if (!$thumb->writeImage($thumbPath)) { + CLI::write(" - fail: write thumb ({$thumbPath})", 'red'); + // 그래도 JPG는 만들어졌으니 다음 진행은 정책에 따라 선택 + } + + CLI::write(" - JPG: {$jpgPath}"); + CLI::write(" - THUMB: {$thumbPath}"); + + // ✅ DB 저장 (기존 시그니처 유지) + $faxModel->insertFaxImgs( + $mid, + $jpgName, + $save_path, + $thumbName, + $image_width, + $image_height, + $image_size, + $qrcode_data, + $caller_no, + $callee_no, + $tiff_file_name, + $tiffPath, + $tiff_file_size, + $recv_time, + $save_time, + $receiver + ); + + // ✅ 권한 처리 (에러 숨기지 말고 로그) + if (!@chmod($jpgPath, 0666)) { + log_message('error', "chmod failed: {$jpgPath}"); + } + if (!@chmod($thumbPath, 0666)) { + log_message('error', "chmod failed: {$thumbPath}"); + } + + log_message('debug', $jpgPath); + log_message('debug', $thumbPath); + + // ✅ 메모리 정리(프레임 단위) + $thumb->clear(); + $thumb->destroy(); + $page->clear(); + $page->destroy(); + } catch (\Throwable $e) { + log_message('error', 'Frame 처리 실패: ' . $e->getMessage()); + } + + // 다음 페이지 + $index++; + } + + // ✅ 전체 메모리 정리 + $frames->clear(); + $frames->destroy(); + + $im->clear(); + $im->destroy(); + + gc_collect_cycles(); + + CLI::write(" - done.\n", 'green'); + } catch (\Throwable $e) { + // 기존 writeLog 사용 중이면 그걸로 교체 가능 + log_message('error', 'TIFF 처리 실패: ' . $e->getMessage()); + CLI::write(" - error: " . $e->getMessage(), 'red'); + } + } + } +} diff --git a/app/Helpers/cron_helper.php b/app/Helpers/cron_helper.php new file mode 100644 index 0000000..7b68ef5 --- /dev/null +++ b/app/Helpers/cron_helper.php @@ -0,0 +1,13 @@ +scan($image); + if (!empty($barcode)) { + foreach ($barcode as $code) { + $data .= ',' . $code['data']; + } + if (!empty($data)) + $data = substr($data, 1); + } + + return $data; + } + +} \ No newline at end of file diff --git a/app/Models/results/AssignModel.php b/app/Models/results/AssignModel.php index e5ef125..7bf6f43 100644 --- a/app/Models/results/AssignModel.php +++ b/app/Models/results/AssignModel.php @@ -102,8 +102,7 @@ class AssignModel extends Model COUNT(*) AS cnt FROM result a INNER JOIN users b ON b.usr_sq = a.usr_sq - INNER JOIN receipt d ON d.rcpt_sq = a.rcpt_sq - INNER JOIN departments c ON c.dept_sq = a.dept_sq + WHERE 1=1 "; @@ -158,7 +157,7 @@ class AssignModel extends Model public function getUserList($start, $end, $data) { $sql = "SELECT - b.usr_nm, b.usr_id, b.usr_sq, c.dept_sq, c.pdept_sq, c.depth + b.usr_nm, b.usr_id, b.usr_sq , SUM(CASE WHEN a.rsrv_tm_hour IN ('00','01','02','03','04','05','06','07','08','09','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24') THEN 1 ELSE 0 END) TODAY , SUM(CASE WHEN a.rsrv_tm_ap = 'AM' AND a.rsrv_tm_hour = '09' THEN 1 ELSE 0 END) AM09 , SUM(CASE WHEN a.rsrv_tm_ap = 'AM' AND a.rsrv_tm_hour = '10' THEN 1 ELSE 0 END) AM10 @@ -175,8 +174,7 @@ class AssignModel extends Model , SUM(CASE WHEN a.rsrv_tm_ap = 'PM' AND a.rsrv_tm_hour IN ('00','08','09','10','11','12','20','21','22','23','24') THEN 1 ELSE 0 END) PMETC FROM result a INNER JOIN users b ON b.usr_sq = a.usr_sq - INNER JOIN receipt d ON d.rcpt_sq = a.rcpt_sq - INNER JOIN departments c ON c.dept_sq = a.dept_sq + WHERE 1=1 "; diff --git a/app/Models/webfax/FaxModel.php b/app/Models/webfax/FaxModel.php new file mode 100644 index 0000000..a6681ba --- /dev/null +++ b/app/Models/webfax/FaxModel.php @@ -0,0 +1,194 @@ += DATE_ADD(NOW(), INTERVAL -7 DAY)" . + " AND a.etc1 = ''" . + " limit 100"; + $this->db->query($sql, $data); + + $sql = "SELECT a.mid,a.eid,a.pages,a.caller_no,a.callee_no,a.file_name,REPLACE(a.save_path, a.file_name,'') save_path,a.file_size,a.recv_time,a.save_time" . + " FROM uds_tiff a" . + " WHERE NOT EXISTS (SELECT 'x' FROM fax_imgs a1 WHERE a1.mid = a.mid)" . + " AND a.recv_time >= DATE_ADD(NOW(), INTERVAL -7 DAY)" . + " AND a.etc1 = ?"; + $query = $this->db->query($sql, $data); + + return $query->getResultArray(); + } + + /** + * tiff 이미지 jpg로 변환 및 썸네일 생성 + */ + public function insertFaxImgs($mid, $file_name, $file_path, $thumbnail, $img_width, $img_height, $img_size, $qrcode = '', $caller_no, $callee_no, $tiff_file_name, $tiff_save_path, $tiff_file_size, $recv_time, $save_time, $receiver) + { + $sql = "INSERT INTO fax_imgs" . + " (MID, file_name, file_path, thumbnail, img_width, img_height, img_size, qrcode, caller_no, callee_no, tiff_file_name, tiff_save_path, tiff_file_size, recv_time, save_time, receiver)" . + " VALUES" . + " (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + $data = [$mid, $file_name, $file_path, $thumbnail, $img_width, $img_height, $img_size, $qrcode, $caller_no, $callee_no, $tiff_file_name, $tiff_save_path, $tiff_file_size, $recv_time, $save_time, $receiver]; + $this->db->query($sql, $data); + } + + public function insertFaxImgs2($mid, $file_name, $file_path, $thumbnail, $img_width, $img_height, $img_size, $qrcode = '', $caller_no, $callee_no, $tiff_file_name, $tiff_save_path, $tiff_file_size, $recv_time, $save_time, $receiver) + { + $sql = "INSERT INTO fax_imgs" . + " (MID, file_name, file_path, thumbnail, img_width, img_height, img_size, qrcode, caller_no, callee_no, tiff_file_name, tiff_save_path, tiff_file_size, recv_time, save_time, receiver)" . + " VALUES" . + " (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + $data = [$mid, $file_name, $file_path, $thumbnail, $img_width, $img_height, $img_size, $qrcode, $caller_no, $callee_no, $tiff_file_name, $tiff_save_path, $tiff_file_size, $recv_time, $save_time, $receiver]; + $this->db->query($sql, $data); + } + + public function selectFaxListTran() + { + + if (!isset($_SERVER["HOSTNAME"])) { + $_SERVER["HOSTNAME"] = get_linux_hostname(); + } + + $data = [$_SERVER["HOSTNAME"]]; + + $sql = "SELECT TR_MSGID, TR_TITLE, TR_SENDFAXNUM, TR_RECVFAXNUM, TR_RECVTIME, TR_FILENAMELIST" . + " FROM FC_RECV_TRAN a" . + " WHERE NOT EXISTS (SELECT 'x' FROM fax_imgs a1 WHERE a1.mid = a.TR_MSGID AND a1.receiver != 'uds_tiff')" . + " AND a.TR_RECVTIME >= DATE_FORMAT(DATE_ADD(NOW(), INTERVAL -7 DAY), '%Y%m%d%h%i%s')"; + + $query = $this->db->query($sql, $data); + return $query->getResultArray(); + } + + + /** + * FAX이미지를 홍보확인서에서 선택할 경우... + */ + public function updateImgSqOnFaxImgs($faxSq, $imgSq) + { + $sql = "UPDATE fax_imgs" . + " SET img_sq = ?" . + " WHERE fax_sq = ?"; + + $data = [$imgSq, $faxSq]; + $this->db->query($sql, $data); + } + + /** + * 홍보확인서를 재지정했을 경우 기존의 홍보확인서는 선택되지 않음으로 ... + */ + public function updateImgSqNullOnFaxImgs($imgSq) + { + $sql = "UPDATE fax_imgs" . + " SET img_sq = null" . + " WHERE img_sq = ?"; + $data = [$imgSq]; + $this->db->query($sql, $data); + } + + /** + * 비고를 지정한다. + */ + public function updateRemark($faxSq, $remark) + { + $sql = "UPDATE fax_imgs" . + " SET remark = ?" . + " WHERE fax_sq = ?"; + $data = [$remark, $faxSq]; + $this->db->query($sql, $data); + } + + /** + * 홍보확인서의 주소가 업데이트 되었을 경우 + * @param bigint $vr_sq receipt 테이블의 PK (rcpt_sq) 또는 v2_vrfc_req 테이블의 PK (vr_sq) + * @param string $address_code 법정동코드 + * @param string $address2 상세주소 + * @param string $address3 기타주소 + * @param string $hscp_no 단지번호 + * @param string $hscp_nm 단지명 + */ + public function updateAddress($vr_sq, $address_code, $address2, $address3, $hscp_no, $hscp_nm) + { + $data = []; + if (!empty($address_code)) + $data['address_code'] = $address_code; + if (!empty($address2)) + $data['address2'] = $address2; + if (!empty($address3)) + $data['address3'] = $address3; + // if (!empty($address4)) $data['address4'] = $address4; + if (!empty($hscp_no)) + $data['hscp_no'] = $hscp_no; + if (!empty($hscp_nm)) + $data['hscp_nm'] = $hscp_nm; + + if (!empty($data)) { + $where = [ + 'vr_sq' => $vr_sq + ]; + $this->db->update('fax_imgs', $data, $where); + } + } + + public function updateAddress2($vr_sq, $address_code, $address2, $address2a, $address2b, $address3, $hscp_no, $hscp_nm) + { + $data = array(); + if (!empty($address_code)) + $data['address_code'] = $address_code; + if (!empty($address2)) + $data['address2'] = $address2; + if (!empty($address2)) + $data['address2a'] = $address2a; + if (!empty($address2)) + $data['address2b'] = $address2b; + if (!empty($address3)) + $data['address3'] = $address3; + // if (!empty($address4)) $data['address4'] = $address4; + if (!empty($hscp_no)) + $data['hscp_no'] = $hscp_no; + if (!empty($hscp_nm)) + $data['hscp_nm'] = $hscp_nm; + + if (!empty($data)) { + $where = [ + 'vr_sq' => $vr_sq + ]; + $this->db->update('fax_imgs', $data, $where); + } + } + + /** + * 팩스건수 가져오기 -> 화면 최상단에 건수 보여줌. + */ + public function getFaxCount() + { + $sql = "SELECT + date_format(now(), '%H') as base_time + ,(SELECT count(*) FROM uds_tiff where save_time >= concat(date_format(now(), '%Y-%m-%d %H'), ':00:00')) as enfax_count + ,(SELECT COUNT(*) FROM FC_RECV_TRAN where TR_RECVTIME >= concat(date_format(now(), '%Y%m%d%H'), '0000')) as lgfax_count + "; + $query = $this->db->query($sql); + + $row = $query->getRowArray(); + + return $row; + } +} \ No newline at end of file -- 2.49.1