Files
dnssash/adm/order_manage/lib/notification_helper.php
2026-06-11 18:47:38 +09:00

441 lines
18 KiB
PHP

<?php
if (!defined('_GNUBOARD_'))
exit;
// ❗ [핵심] NotificationSender 클래스 포함
if (file_exists(__DIR__ . '/notification_sender.php')) {
require_once(__DIR__ . '/notification_sender.php');
}
/**
* 주문 설정값을 가져옵니다.
*/
function get_order_config($key, $default = '')
{
$result = sql_fetch("SELECT config_value FROM order_config WHERE config_key = '" . sql_real_escape_string($key) . "'");
return $result ? $result['config_value'] : $default;
}
function write_debug_log($message)
{
$log_dir = G5_PATH . '/log';
// 1. 디렉토리 존재 여부 확인 및 생성
if (!is_dir($log_dir)) {
if (!@mkdir($log_dir, 0755, true) && !is_dir($log_dir)) {
error_log("--- NotificationSender ERROR: 디버그 로그 디렉토리 생성 실패. '{$log_dir}' 경로를 확인하거나 수동으로 생성 후 웹서버 쓰기 권한을 부여해주세요.");
return;
}
}
// 2. 디렉토리 쓰기 권한 확인
if (!is_writable($log_dir)) {
error_log("--- NotificationSender ERROR: 디버그 로그 쓰기 오류. '{$log_dir}' 디렉토리에 쓰기 권한이 없습니다. 웹서버의 폴더 권한을 확인해주세요.");
return;
}
// 3. 로그 파일에 내용 기록
$log_file = $log_dir . '/notification_debug.log';
$log_message = date("[Y-m-d H:i:s]") . " " . $message . "\n";
if (file_put_contents($log_file, $log_message, FILE_APPEND | LOCK_EX) === false) {
error_log("--- NotificationSender ERROR: 디버그 로그 파일 쓰기 실패. '{$log_file}' 파일에 내용을 쓸 수 없습니다.");
}
}
/**
* ❗ [핵심 수정] 1. 견적 상태 변경 시 알림 발송
* @param int $wr_id 상태가 변경된 게시물 ID (원본 또는 답변글)
* @param string $new_status 새로 변경된 상태
*/
function notify_by_status($wr_id, $new_status)
{
global $config;
$post = sql_fetch("SELECT * FROM {$GLOBALS['g5']['write_prefix']}order WHERE wr_id = '{$wr_id}'");
if (!$post) return false;
write_debug_log("[notify_by_status] 원본 견적(estimate) 시작 : {$wr_id}");
// 원본글 정보 조회
$origin_post = sql_fetch("SELECT * FROM {$GLOBALS['g5']['write_prefix']}order WHERE wr_num = '{$post['wr_num']}' AND wr_reply = ''");
if (!$origin_post) return false;
$customer = get_member($origin_post['mb_id']);
if (!$customer) return false;
// 템플릿에 사용할 공통 변수 (영문 키로 표준화)
$common_vars = [
'customer_name' => $customer['mb_name'],
'request_title' => $origin_post['wr_subject'],
'request_date' => date('Y-m-d', strtotime($origin_post['wr_datetime'])),
'write_url' => get_pretty_url('order', $origin_post['wr_id']),
'site_name' => $config['cf_title'] ?? '우리집창호', // 사이트 이름 추가
];
if (!class_exists('NotificationSender')) return false;
$sender = new NotificationSender();
// ❗ [추가] 결제 및 진행상태 관련 알림을 위한 공통 변수 처리
$payment_statuses = ['계약금입금완료', '중도금입금예정', '중도금입금완료', '시공완료'];
$payment_vars = [];
$agent_member = null;
$bid_dealer_id = null;
if (in_array($new_status, $payment_statuses)) {
// ❗ [핵심 수정] estimate_bidding을 사용하지 않고, 채택된 답변글에서 직접 정보를 가져옵니다.
// 1. 원본글의 estimate 정보를 가져옵니다. (시공일, 중도금일 등)
$origin_estimate = sql_fetch("SELECT * FROM estimate WHERE wr_id = '{$origin_post['wr_id']}'");
if (!$origin_estimate) {
write_debug_log("[notify_by_status] 원본 견적(estimate) 정보를 찾을 수 없습니다. wr_id: {$origin_post['wr_id']}");
return false;
}
// 2. 채택된 답변글(대리점 제안) 정보를 찾습니다.
$selected_reply_sql = "
SELECT
w.mb_id as dealer_id,
e.commission_fee as total_amount
FROM
{$GLOBALS['g5']['write_prefix']}order w
JOIN
estimate e ON w.wr_id = e.wr_id
WHERE
w.wr_num = '{$origin_post['wr_num']}'
AND w.wr_reply != ''
AND e.status = '견적채택'
LIMIT 1
";
$selected_bid_info = sql_fetch($selected_reply_sql);
if ($selected_bid_info) {
$bid_dealer_id = $selected_bid_info['dealer_id'];
$agent_member = get_member($bid_dealer_id);
$total_amount = (int) $selected_bid_info['total_amount']; // 답변글의 estimate.commission_fee를 총액으로 사용
$deposit_rate = (float) get_order_config('contract_deposit_rate', 10);
$interim_rate = (float) get_order_config('middle_payment_rate', 40);
$deposit_amount = (int) ($total_amount * $deposit_rate / 100);
$interim_amount = (int) ($total_amount * $interim_rate / 100);
$payment_vars = array_merge($common_vars, [
'deposit_amount' => number_format($deposit_amount) . '원',
'interim_amount' => number_format($interim_amount) . '원',
'agent_name' => $agent_member['mb_name'] ?? '담당 대리점',
'construction_date' => $origin_estimate['temp_6'] ?? '미정',
'interim_payment_date' => $origin_estimate['temp_7'] ?? '미정',
'account_info' => get_order_config('payment_account_info', '계좌 정보 미설정'),
]);
}
if (empty($payment_vars)) { // 필수 정보가 없으면 발송 중단
write_debug_log("[notify_by_status] 결제 정보 부족으로 '{$new_status}' 알림 발송을 건너뜁니다. wr_id: {$wr_id}");
return false;
}
}
switch ($new_status) {
case '작성완료':
// 1. 고객에게 알림
$sender->send([
'target_type' => 'single',
'member_id' => $customer['mb_id'],
'email_template_key' => 'customer_request_complete',
'sms_template_key' => 'customer_request_complete',
'vars' => $common_vars,
]);
// 2. 모든 대리점에게 알림
$sender->send([
'target_type' => 'bulk',
'member_levels' => [9,10],
'email_template_key' => 'agent_new_request',
'sms_template_key' => 'agent_new_request',
'vars' => $common_vars,
]);
break;
case '견적채택':
$agent_member = get_member($post['mb_id']);
write_debug_log("[notify_by_status] agent_member=> ".$agent_member['mb_id'].', name'.$agent_member['mb_name'].', id '.$post['mb_id'].', w_id '.$wr_id);
if (!$agent_member) break;
// 🔥 [핵심 수정] 채택된 답변글(wr_id)의 estimate 레코드에서 최종 금액을 가져옵니다.
$agent_estimate = sql_fetch("SELECT id, commission_fee FROM estimate WHERE wr_id = '{$post['wr_id']}'");
$final_amount = $agent_estimate ? (int)$agent_estimate['commission_fee'] : 0;
// [수정] 입찰 정보를 바탕으로 변수를 설정합니다.
$bid_vars = array_merge($common_vars, [
'agent_name' => $agent_member['mb_name'],
'dealer_name' => $agent_member['mb_name'], // 템플릿 호환용
'deposit_amount' => number_format($final_amount) . '원', // 최종 금액을 입금 안내
'bid_amount' => number_format($final_amount), // 템플릿 호환용
'account_info' => get_order_config('payment_account_info', '계좌 정보 미설정'),
'estimate_id' => $agent_estimate ? $agent_estimate['id'] : 'N/A',
'selected_date' => date('Y-m-d H:i'),
'estimate_url' => get_pretty_url('order', $origin_post['wr_id']),
]);
// 1. 채택된 대리점에게 알림 (축하 메시지)
$sender->send([
'target_type' => 'single',
'member_id' => $agent_member['mb_id'],
'email_template_key' => 'bid_selected_email',
'sms_template_key' => 'bid_selected_sms',
'vars' => $bid_vars,
]);
// 2. 고객에게 알림 (선택 완료 및 입금 안내)
$sender->send([
'target_type' => 'single',
'member_id' => $customer['mb_id'],
'email_template_key' => 'customer_quote_selected',
'sms_template_key' => 'customer_quote_selected',
'vars' => $bid_vars,
]);
break;
case '계약금입금완료':
$sender->send([
'target_type' => 'single',
'member_id' => $customer['mb_id'],
'email_template_key' => 'payment_deposit_complete_customer',
'sms_template_key' => 'payment_deposit_complete_customer',
'vars' => $payment_vars,
]);
break;
case '중도금입금예정':
$sender->send([
'target_type' => 'single',
'member_id' => $customer['mb_id'],
'email_template_key' => 'payment_interim_due_customer',
'sms_template_key' => 'payment_interim_due_customer',
'vars' => $payment_vars,
]);
break;
case '중도금입금완료':
$sender->send([
'target_type' => 'single',
'member_id' => $customer['mb_id'],
'email_template_key' => 'payment_interim_complete_customer',
'sms_template_key' => 'payment_interim_complete_customer',
'vars' => $payment_vars,
]);
break;
case '시공완료':
// 고객에게 알림
$sender->send([
'target_type' => 'single',
'member_id' => $customer['mb_id'],
'email_template_key' => 'construction_complete_customer',
'sms_template_key' => 'construction_complete_customer',
'vars' => $payment_vars,
]);
// 대리점에게 알림
if ($bid_dealer_id) {
$sender->send([
'target_type' => 'single',
'member_id' => $bid_dealer_id,
'email_template_key' => 'construction_complete_agent',
'sms_template_key' => 'construction_complete_agent',
'vars' => $payment_vars,
]);
}
break;
}
return true;
}
/**
* ❗ [신규] 2. 입금 관련 알림 발송 (관리자, 고객)
* @param int $wr_id 원본 게시물 ID
* @param string $payment_status 입금 상태 (예: '계약금입금완료')
* @param array $payment_info 추가 결제 정보 (금액 등)
*/
function notify_for_payment($wr_id, $payment_status, $payment_info = [])
{
$origin_post = sql_fetch("SELECT * FROM {$GLOBALS['g5']['write_prefix']}order WHERE wr_id = '{$wr_id}'");
if (!$origin_post) return false;
$customer = get_member($origin_post['mb_id']);
if (!$customer) return false;
$common_vars = array_merge([
'customer_name' => $customer['mb_name'],
'estimate_subject' => $origin_post['wr_subject'],
], $payment_info);
if (!class_exists('NotificationSender')) return false;
$sender = new NotificationSender();
// 1. 고객에게 알림
$sender->send([
'target_type' => 'single',
'member_id' => $customer['mb_id'],
'email_template_key' => 'payment_status_update_customer', // 예시 템플릿 키
'sms_template_key' => 'payment_status_update_customer',
'vars' => $common_vars,
]);
// 2. 관리자에게 알림
$sender->send([
'target_type' => 'bulk',
'member_levels' => [10], // 관리자 레벨
'email_template_key' => 'payment_status_update_admin', // 예시 템플릿 키
'sms_template_key' => 'payment_status_update_admin',
'vars' => $common_vars,
]);
return true;
}
/**
* ❗ [신규] 3. 전문가 방문 예약 관련 알림 발송 (고객, 전문가, 관리자)
* @param int $reservation_id 예약 ID
* @param string $visit_status 방문 상태 (예: '신규예약', '예약확정', '예약취소')
*/
function notify_for_expert_visit($reservation_id, $visit_status)
{
// 예약 정보 조회
$reservation = sql_fetch("SELECT * FROM expert_visit_reservations WHERE id = '{$reservation_id}'");
if (!$reservation) return false;
// 💡 [수정] 고객 정보 조회 (회원/비회원 구분)
$customer = get_member($reservation['customer_id']);
$is_guest = empty($customer['mb_id']);
// 비회원일 경우 예약 정보에서 직접 가져옴
$customer_name = $is_guest ? $reservation['customer_name'] : $customer['mb_name'];
$customer_hp = $is_guest ? $reservation['customer_phone'] : $customer['mb_hp'];
$customer_email = $is_guest ? $reservation['customer_email'] : $customer['mb_email'];
$expert = get_member($reservation['expert_id']);
$common_vars = [
'customer_name' => $customer_name,
'visit_date' => $reservation['visit_date'],
'visit_time' => $reservation['visit_time'],
'expert_name' => $expert['mb_name'] ?? '미지정',
];
if (!class_exists('NotificationSender')) return false;
$sender = new NotificationSender();
switch ($visit_status) {
case '신규예약':
// 1. 고객에게 신청 완료 알림
$send_params = [
'email_template_key' => 'expert_visit_request_new',
'sms_template_key' => 'expert_visit_request_new',
'vars' => array_merge($common_vars, [
'reservation_id' => $reservation_id,
'expert_visit_fee' => number_format($reservation['payment_amount']) . '원',
'account_info' => get_order_config('expert_visit_account_info', '계좌 정보 미설정'),
]),
];
if ($is_guest) {
// 비회원: 직접 수신자 정보 지정
$send_params['target_type'] = 'direct';
$send_params['receivers'] = [
[
'mb_name' => $customer_name,
'mb_hp' => $customer_hp,
'mb_email' => $customer_email,
'mb_sms' => 1, // SMS 수신 동의 가정
'mb_mailling' => 1 // 메일 수신 동의 가정
]
];
} else {
// 회원: member_id 사용
$send_params['target_type'] = 'single';
$send_params['member_id'] = $customer['mb_id'];
}
$sender->send($send_params);
// 2. 관리자에게 알림
$sender->send([
'target_type' => 'bulk',
'member_levels' => [10],
'email_template_key' => 'admin_new_visit_request',
'sms_template_key' => 'admin_new_visit_request',
'vars' => array_merge($common_vars, [
'customer_phone' => $customer_hp,
'request_memo' => $reservation['request_memo'],
]),
]);
break;
case '예약확정':
// 1. 고객에게 예약 확정 알림
$send_params = [
'email_template_key' => 'expert_visit_confirmed',
'sms_template_key' => 'expert_visit_confirmed',
'vars' => $common_vars,
];
if ($is_guest) {
$send_params['target_type'] = 'direct';
$send_params['receivers'] = [
[
'mb_name' => $customer_name,
'mb_hp' => $customer_hp,
'mb_email' => $customer_email,
'mb_sms' => 1,
'mb_mailling' => 1
]
];
} else {
$send_params['target_type'] = 'single';
$send_params['member_id'] = $customer['mb_id'];
}
$sender->send($send_params);
// 2. 배정된 전문가에게 알림
if ($expert) {
$sender->send([
'target_type' => 'single',
'member_id' => $expert['mb_id'],
'email_template_key' => 'expert_new_assignment',
'sms_template_key' => 'expert_new_assignment',
'vars' => $common_vars,
]);
}
break;
case '예약취소':
// 1. 고객에게 예약 취소 알림
$send_params = [
'email_template_key' => 'expert_visit_cancelled',
'sms_template_key' => 'expert_visit_cancelled',
'vars' => $common_vars,
];
if ($is_guest) {
$send_params['target_type'] = 'direct';
$send_params['receivers'] = [
[
'mb_name' => $customer_name,
'mb_hp' => $customer_hp,
'mb_email' => $customer_email,
'mb_sms' => 1,
'mb_mailling' => 1
]
];
} else {
$send_params['target_type'] = 'single';
$send_params['member_id'] = $customer['mb_id'];
}
$sender->send($send_params);
// 2. 관리자에게 알림
$sender->send([
'target_type' => 'bulk',
'member_levels' => [10],
'email_template_key' => 'admin_visit_cancelled',
'sms_template_key' => 'admin_visit_cancelled',
'vars' => $common_vars,
]);
break;
}
return true;
}
?>