normalizeDailyPayload($data, $existing ?: null); $data = $this->hydrateDailySnapshot($data, $existing ?: null); // estquantity 자동 계산 if (empty($data['d_estquantity'])) { $data['d_estquantity'] = $this->calculateEstQuantity($data, $existing); } // note 백업 (tbl_note 로 전달할 값) $noteForUpsert = $data['d_note'] ?? ''; $pickupNoteForUpsert = $data['d_pickupnote'] ?? ''; $level = $data['d_level'] ?? 9; // ========================= // 컬럼 필터링 // ========================= $allowed = $this->getDailyColumns(); $data = array_intersect_key($data, array_flip($allowed)); // ========================= // UPDATE // ========================= if ($isUpdate) { $setParts = []; foreach ($data as $k => $v) { if (in_array($k, ['d_orderdate','d_accountno','d_jobtype'], true)) continue; if (!array_key_exists($k, $existing)) continue; $setParts[] = "{$k}='" . mysqli_real_escape_string($connect, (string)$v) . "'"; } $setParts[] = "d_modifydate='{$now14}'"; if (!empty($setParts)) { // update는 무조건 d_uid 기준으로 $uid = (int)$existing['d_uid']; $sql = " UPDATE tbl_daily SET " . implode(",", $setParts) . " WHERE d_uid='{$uid}' LIMIT 1 "; if (!mysqli_query($connect, $sql)) { throw new Exception(mysqli_error($connect)); } } } // ========================= // INSERT // ========================= else { $cols = []; $vals = []; foreach ($data as $k => $v) { $cols[] = $k; $vals[] = "'" . mysqli_real_escape_string($connect, (string)$v) . "'"; } if (!in_array('d_modifydate', $cols)) { $cols[] = 'd_modifydate'; $vals[] = "'{$now14}'"; } $sql = " INSERT INTO tbl_daily (" . implode(",", $cols) . ") VALUES (" . implode(",", $vals) . ") "; if (!mysqli_query($connect, $sql)) { throw new Exception(mysqli_error($connect)); } } // ========================= // AFTER RELOAD (uid 기준) // ========================= if ($isUpdate) { $uid = (int)$existing['d_uid']; $res = mysqli_query($connect, " SELECT * FROM tbl_daily WHERE d_uid='{$uid}' LIMIT 1 "); } else { $res = mysqli_query($connect, " SELECT * FROM tbl_daily WHERE d_orderdate='{$d_orderdate}' AND d_accountno='{$d_accountno}' AND d_jobtype = '{$d_jobtype}' ORDER BY d_uid DESC LIMIT 1 "); } $afterData = mysqli_fetch_assoc($res); // note if ($noteForUpsert !== '') { $afterData['d_note'] = $noteForUpsert; $afterData['d_level'] = $level; } if ($pickupNoteForUpsert !== '') { $afterData['d_pickupnote'] = $pickupNoteForUpsert; $afterData['d_level'] = $level; } // ========================= // ERP OUTBOX // ========================= $event_type = $isUpdate ? 'DAILY_UPDATED' : 'DAILY_CREATED'; $payload = mysqli_real_escape_string( $connect, json_encode([ 'key' => [ 'd_orderdate'=>$afterData['d_orderdate'], 'd_accountno'=>$afterData['d_accountno'], 'd_jobtype'=>$afterData['d_jobtype'] ], 'before'=>$beforeData, 'after'=>$afterData ], JSON_UNESCAPED_UNICODE) ); mysqli_query($connect, " INSERT INTO tbl_erp_outbox (eo_event_type, eo_key_date, eo_key_accountno, eo_key_jobtype, eo_payload, eo_status, eo_created_at) VALUES ('{$event_type}', '{$afterData['d_orderdate']}', '{$afterData['d_accountno']}', '{$afterData['d_jobtype']}', '{$payload}', 'PENDING', NOW()) "); // ========================= // AFTER WORK // ========================= $this->runAfterSave($beforeData, $afterData, $opt); // ========================= // COMMIT // ========================= if (!$inTx) { mysqli_query($connect, "COMMIT"); } return $afterData; } catch (Exception $e) { if (!$inTx) { mysqli_query($connect, "ROLLBACK"); } throw $e; } } private function isDuplicate($orderdate, $accountno, $jobtype): bool { $connect = $GLOBALS['conn']; $res = mysqli_query($connect, " SELECT 1 FROM tbl_daily WHERE d_orderdate='{$orderdate}' AND d_accountno='{$accountno}' AND d_jobtype = '{$jobtype}' LIMIT 1 "); return (bool)mysqli_fetch_assoc($res); } private function normalizeDailyPayload(array $data, ?array $existing = null): array { // 날짜 정리 if (isset($data['d_orderdate'])) { $data['d_orderdate'] = preg_replace('/[^0-9]/', '', $data['d_orderdate']); } if (isset($data['d_visitdate'])) { $data['d_visitdate'] = preg_replace('/[^0-9]/', '', $data['d_visitdate']); } // 숫자 필드 기본값 $intFields = [ 'd_quantity', 'd_sludge' ]; foreach ($intFields as $f) { if (isset($data[$f])) { $data[$f] = ($data[$f] === '' || $data[$f] === null) ? 0 : (int)$data[$f]; } } // 문자열 trim $strFields = [ 'd_pickupnote', 'd_note' ]; foreach ($strFields as $f) { if (isset($data[$f])) { $data[$f] = trim((string)$data[$f]); } } return $data; } private function hydrateDailySnapshot(array $data, ?array $existing = null): array { $connect = $GLOBALS['conn'] ?? null; if (!$connect) { throw new Exception("DB connection not found"); } // ========================= // DRIVER SNAPSHOT // ========================= $druid = isset($data['d_druid']) ? (int)$data['d_druid'] : (int)($existing['d_druid'] ?? 0); // fallback: legacy member uid -> current driver uid if ($druid <= 0) { $driverUid = isset($data['d_driveruid']) ? (int)$data['d_driveruid'] : (int)($existing['d_driveruid'] ?? 0); if ($driverUid > 0) { $sqMap = qry(" SELECT m.m_currentdriver AS dr_uid, d.dr_initial FROM tbl_member m LEFT JOIN tbl_driver d ON d.dr_uid = m.m_currentdriver WHERE m.m_uid = '{$driverUid}' LIMIT 1 "); $map = fetch_array($sqMap); if ($map && (int)$map['dr_uid'] > 0) { $druid = (int)$map['dr_uid']; $data['d_druid'] = $druid; $data['d_drinitial'] = $map['dr_initial'] ?? ''; } } } // druid가 있으면 driver snapshot 확정 if ($druid > 0) { $sqDriver = qry(" SELECT dr_initial FROM tbl_driver WHERE dr_uid = '{$druid}' LIMIT 1 "); $driver = fetch_array($sqDriver); if ($driver && !empty($driver['dr_initial'])) { $data['d_druid'] = $druid; $data['d_drinitial'] = $driver['dr_initial']; } elseif ($existing) { $data['d_druid'] = $existing['d_druid'] ?? 0; $data['d_drinitial'] = $existing['d_drinitial'] ?? ''; } } // ========================= // CUSTOMER SNAPSHOT (확장) // ========================= $customerUid = isset($data['d_customeruid']) ? (int)$data['d_customeruid'] : (int)($existing['d_customeruid'] ?? 0); if ($customerUid > 0) { $sqCustomer = qry(" SELECT c_regionuid, c_region, c_fullcycle, c_fullcycleforced, c_fullcycleflag, c_lastpickupdate, c_lastpickupquantity, c_lastpaiddate, c_name, c_paymenttype, c_paymentcycle, c_rate, c_form_eu, c_form_corsia, c_maincontainer, c_container, c_location, c_phone, c_address, c_city, c_postal, c_area FROM tbl_customer WHERE c_uid = '{$customerUid}' LIMIT 1 "); $customer = fetch_array($sqCustomer); if ($customer) { $data['d_name'] = $customer['c_name'] ?? ''; $data['d_form_eu'] = $customer['c_form_eu'] ?? ''; $data['d_form_corsia'] = $customer['c_form_corsia'] ?? ''; $data['d_maincontainer'] = $customer['c_maincontainer'] ?? ''; $data['d_container'] = $customer['c_container'] ?? ''; $data['d_location'] = $customer['c_location'] ?? ''; $data['d_phone'] = $customer['c_phone'] ?? ''; $data['d_address'] = $customer['c_address'] ?? ''; $data['d_city'] = $customer['c_city'] ?? ''; $data['d_postal'] = $customer['c_postal'] ?? ''; $data['d_area'] = $customer['c_area'] ?? ''; $data['d_regionuid'] = (int)($customer['c_regionuid'] ?? 0); $data['d_region'] = $customer['c_region'] ?? ''; $data['d_fullcycle'] = $customer['c_fullcycle'] ?? 0; $data['d_fullcycleforced'] = $customer['c_fullcycleforced'] ?? 0; $data['d_fullcycleflag'] = $customer['c_fullcycleflag'] ?? 0; $data['d_lastpickupdate'] = $customer['c_lastpickupdate'] ?? ''; $data['d_lastpickupquantity'] = $customer['c_lastpickupquantity'] ?? 0; $data['d_lastpaiddate'] = $customer['c_lastpaiddate'] ?? ''; $data['d_paymenttype'] = $customer['c_paymenttype'] ?? ''; $data['d_cycle'] = $customer['c_paymentcycle'] ?? ''; $data['d_rate'] = $customer['c_rate'] ?? ''; if (!isset($data['d_oil_2y'])) $data['d_oil_2y'] = 0; if (!isset($data['d_oil_1y'])) $data['d_oil_1y'] = 0; if (!isset($data['d_oil_0y'])) $data['d_oil_0y'] = 0; } } return $data; } private function getDailyColumns(): array { return [ 'd_uid', // key 'd_orderdate', 'd_accountno', 'd_customeruid', 'd_jobtype', // driver / region 'd_driveruid', 'd_druid', 'd_drinitial', 'd_regionuid', 'd_region', // basic status 'd_ordertype', 'd_visitdate', 'd_visit', 'd_status', // qty / sludge / payment 'd_quantity', 'd_sludge', 'd_paymenttype', 'd_payamount', 'd_payeename', 'd_paystatus', // customer snapshot 'd_name', 'd_form_eu', 'd_form_corsia', 'd_maincontainer', 'd_container', 'd_location', 'd_phone', 'd_address', 'd_city', 'd_postal', 'd_area', // oil / cycle history snapshot 'd_oil_2y', 'd_oil_1y', 'd_oil_0y', 'd_fullcycle', 'd_fullcycleforced', 'd_fullcycleflag', 'd_lastpickupdate', 'd_lastpickupquantity', 'd_lastpaiddate', // pricing / estimate 'd_cycle', 'd_rate', 'd_estquantity', // audit 'd_createruid', 'd_createddate', 'd_inputdate', 'd_modifydate', 'd_ruid', // misc 'd_payeesign', 'd_is_transfer' ]; } private function calculateEstQuantity(array $data, ?array $existing = null): int { $customerUid = $data['d_customeruid'] ?? ($existing['d_customeruid'] ?? 0); $orderdate = $data['d_orderdate'] ?? ($existing['d_orderdate'] ?? ''); if (!$customerUid || !$orderdate) return 0; $sqCus = qry(" SELECT c_fullquantity, c_fullquantitydaily FROM tbl_customer WHERE c_uid = '{$customerUid}' LIMIT 1 "); $customer = fetch_array($sqCus); if (!$customer) return 0; $today = new DateTime(date("Y-m-d")); $searchDate = new DateTime(substr($orderdate,0,4)."-".substr($orderdate,4,2)."-".substr($orderdate,6,2)); $interval = $today->diff($searchDate); $days = (int)$interval->days; return max( 0, ($customer['c_fullquantity'] - $customer['c_fullquantitydaily']) + ($days * $customer['c_fullquantitydaily']) ); } private function runAfterSave(?array $before, array $after, array $opt = []): void { $this->updateCustomerFromDaily($before, $after); $this->updateRequestFromDaily($after); $this->upsertDailyNote($after); $this->handlePickupCleanup($before, $after); $this->handlePickupReset($before, $after); } private function runAfterDelete(array $before, array $opt = []): void { $connect = $GLOBALS['conn']; if (empty($before['d_customeruid'])) { return; } $customerUid = mysqli_real_escape_string($connect, $before['d_customeruid']); $orderdate = mysqli_real_escape_string($connect, $before['d_orderdate'] ?? ''); // 1) REQUEST 삭제 $this->deleteRequestByDaily($before); // 2) CUSTOMER 재계산 (lastpick, lastpaid 등 포함) $this->recalcCustomerFromDailyHistory($customerUid); // 3) GHOST 재판정 $this->reEvaluateGhost($customerUid); } private function deleteRequestByDaily(array $before): void { $connect = $GLOBALS['conn']; $customerUid = (int)($before['d_customeruid'] ?? 0); $orderdate = preg_replace('/[^0-9]/', '', $before['d_orderdate'] ?? ''); if ($customerUid <= 0 || $orderdate === '') { return; } mysqli_query($connect, " DELETE FROM tbl_request WHERE r_customeruid = '{$customerUid}' AND r_requestdate = '{$orderdate}' "); } private function updateCustomerFromDaily($before, $after) { $connect = $GLOBALS['conn']; if (empty($after['d_customeruid'])) return; $customer_uid = mysqli_real_escape_string($connect, $after['d_customeruid']); // 고객 현재 상태 조회 $qr = mysqli_query($connect, " SELECT c_paymenttype, c_is_top, c_fpickup, c_schedule, c_scheduleday FROM tbl_customer WHERE c_uid = '{$customer_uid}' LIMIT 1 "); $customer = mysqli_fetch_assoc($qr); if (!$customer) return; $updateFields = []; $ordertype = $after['d_ordertype'] ?? 'N'; $orderdate = $after['d_orderdate'] ?? ''; $visitdate = $after['d_visitdate'] ?? ''; $quantity = (int)($after['d_quantity'] ?? 0); $paystatus = $after['d_paystatus'] ?? ''; $paymenttype = $after['d_paymenttype'] ?? ''; $isTop = $customer['c_is_top'] ?? ''; // -------------------------------------------------- // 0) Ghost Check // -------------------------------------------------- if ($quantity < 10 && $isTop !== 'G') { $updateFields[] = "c_is_top = 'G'"; } if ($isTop === 'G' && $quantity >= 10) { $updateFields[] = "c_is_top = ''"; } // -------------------------------------------------- // 1) c_fpickup 처리 // -------------------------------------------------- if (!empty($orderdate)) { $currentFpickup = $customer['c_fpickup'] ?? ''; if (empty($currentFpickup) || $currentFpickup < $orderdate) { $updateFields[] = "c_fpickup = '{$orderdate}'"; } } // -------------------------------------------------- // 2) orderflag 처리 // -------------------------------------------------- if (!empty($after['d_visit']) && $after['d_visit'] === 'Y') { $updateFields[] = "c_orderdate = ''"; $updateFields[] = "c_orderflag = 0"; } else { $updateFields[] = "c_orderdate = '{$orderdate}'"; $updateFields[] = "c_orderflag = 1"; } // -------------------------------------------------- // 3) Scheduled 처리 (d_ordertype == 'S') // -------------------------------------------------- if ($ordertype === 'S' && !empty($visitdate)) { $schedule = $customer['c_schedule'] ?? ''; $scheduleDay = $customer['c_scheduleday'] ?? ''; if ($schedule > '1W' && $schedule <= '6W') { $weekCount = (int)substr($schedule, 0, 1); if ($weekCount > 0 && !empty($scheduleDay)) { $dayParts = explode('|', $scheduleDay); $dayOfWeek = $dayParts[0] ?? ''; $calcStr = "+{$weekCount} week {$dayOfWeek}"; $nextDate = date('Ymd', strtotime($calcStr, strtotime($visitdate))); $updateFields[] = "c_schedulebasic = '{$nextDate}'"; } } } // -------------------------------------------------- // UPDATE 실행 // -------------------------------------------------- if (!empty($updateFields)) { mysqli_query($connect, " UPDATE tbl_customer SET " . implode(",", $updateFields) . " WHERE c_uid = '{$customer_uid}' LIMIT 1 "); } } private function updateRequestFromDaily(array $after): void { $connect = $GLOBALS['conn']; if (empty($after['d_ordertype']) || $after['d_ordertype'] !== 'R') { return; } if (empty($after['d_ruid'])) { return; } // pickup 완료 조건 (방문 완료 + 상태 F) if ( empty($after['d_visit']) || $after['d_visit'] !== 'Y' || empty($after['d_status']) || $after['d_status'] !== 'F' ) { return; } $r_uid = mysqli_real_escape_string($connect, $after['d_ruid']); mysqli_query($connect, " UPDATE tbl_request SET r_status = 'F' WHERE r_uid = '{$r_uid}' LIMIT 1 "); } private function upsertDailyNote(array $after): void { $connect = $GLOBALS['conn']; if (empty($after['d_uid'])) return; // note는 saveDaily payload에 포함되어 있어야 함 if (empty($after['d_pickupnote']) && empty($after['d_note'])) { return; } $noteText = trim($after['d_pickupnote'] ?? $after['d_note'] ?? ''); if (strlen($noteText) <= 1) return; $dailyuid = mysqli_real_escape_string($connect, $after['d_uid']); $customeruid = mysqli_real_escape_string($connect, $after['d_customeruid'] ?? ''); $memberuid = mysqli_real_escape_string($connect, $after['d_driveruid'] ?? ''); $noteEsc = mysqli_real_escape_string($connect, $noteText); $now14 = date('YmdHis'); $level = mysqli_real_escape_string($connect, $after['d_level'] ?? 9); // 기존 note 존재 여부 확인 $qr = mysqli_query($connect, " SELECT n_uid FROM tbl_note WHERE n_dailyuid = '{$dailyuid}' LIMIT 1 "); $existing = mysqli_fetch_assoc($qr); if ($existing) { // UPDATE mysqli_query($connect, " UPDATE tbl_note SET n_memberuid = '{$memberuid}', n_customeruid = '{$customeruid}', n_type = 'D', n_level = {$level}, n_view = 1, n_note = '{$noteEsc}', n_createddate = '{$now14}' WHERE n_dailyuid = '{$dailyuid}' LIMIT 1 "); } else { // INSERT mysqli_query($connect, " INSERT INTO tbl_note ( n_memberuid, n_customeruid, n_dailyuid, n_type, n_level, n_view, n_note, n_createddate ) VALUES ( '{$memberuid}', '{$customeruid}', '{$dailyuid}', 'D', {$level}, 1, '{$noteEsc}', '{$now14}' ) "); } } private function handlePickupCleanup(?array $before, array $after): void { $connect = $GLOBALS['conn']; $beforeQty = (int)($before['d_quantity'] ?? 0); $afterQty = (int)($after['d_quantity'] ?? 0); $status = $after['d_status'] ?? ''; $visit = $after['d_visit'] ?? ''; // 최초 pickup $isFirstPickup = ($beforeQty < 10 && $afterQty >= 10); if (!$isFirstPickup) return; if ($status !== 'F' || $visit !== 'Y') return; $customerUid = mysqli_real_escape_string($connect, $after['d_customeruid']); $today = date('Ymd'); $jobtype = mysqli_real_escape_string($connect, $after['d_jobtype'] ?? 'UCO'); // ========================= // 삭제 대상 조회 // ========================= $res = mysqli_query($connect, " SELECT d_orderdate, d_accountno, d_jobtype FROM tbl_daily WHERE d_customeruid = '{$customerUid}' AND d_orderdate > '{$today}' AND d_status = 'A' AND d_jobtype = '{$jobtype}' "); if (!$res) { throw new Exception(mysqli_error($connect)); } // ========================= // 하나씩 deleteDaily 호출 // ========================= while ($row = mysqli_fetch_assoc($res)) { try { $this->deleteDaily( $row['d_orderdate'], $row['d_accountno'], $row['d_jobtype'], ['in_tx' => true] ); } catch (Exception $e) { // 여기서 실패하면 전체 rollback 유도 throw $e; } } error_log("[PickupCleanup] ERP-safe delete completed for customer={$customerUid}"); } private function handlePickupReset(?array $before, array $after): void { $connect = $GLOBALS['conn']; $beforeQty = (int)($before['d_quantity'] ?? 0); $afterQty = (int)($after['d_quantity'] ?? 0); $status = $after['d_status'] ?? ''; $visit = $after['d_visit'] ?? ''; $isFirstPickup = ($beforeQty < 10 && $afterQty >= 10); if (!$isFirstPickup) return; if ($status !== 'F' || $visit !== 'Y') return; $customerUid = mysqli_real_escape_string($connect, $after['d_customeruid']); $sql = " UPDATE tbl_customer SET c_fullquantity = 0 WHERE c_uid = '{$customerUid}' "; mysqli_query($connect, $sql); error_log("[PickupReset] customer={$customerUid} reset fullquantity"); } public function deleteDaily(string $orderdate, string $accountno, string $jobtype, array $opt = []) { $connect = $GLOBALS['conn'] ?? null; if (!$connect) { throw new Exception("DB connection not found"); } $inTx = !empty($opt['in_tx']); // ========================= // KEY NORMALIZE // ========================= $orderdate = preg_replace('/[^0-9]/', '', $orderdate); if (strlen($orderdate) !== 8) { throw new Exception("invalid orderdate"); } $accountno = mysqli_real_escape_string($connect, trim($accountno)); if ($accountno === '') { throw new Exception("invalid accountno"); } $jobtype = mysqli_real_escape_string($connect, trim($jobtype)); if ($jobtype === '') { $jobtype = 'UCO'; } if (!$inTx) { mysqli_query($connect, "START TRANSACTION"); } try { // ========================= // 1. 기존 데이터 조회 // ========================= $res = mysqli_query($connect, " SELECT * FROM tbl_daily WHERE d_orderdate='{$orderdate}' AND d_accountno='{$accountno}' AND d_jobtype = '{$jobtype}' LIMIT 1 "); if (!$res) throw new Exception(mysqli_error($connect)); $existing = mysqli_fetch_assoc($res); if (!$existing) { throw new Exception("Daily record not found"); } // ========================= // 2. ERP OUTBOX 기록 // ========================= $payload = mysqli_real_escape_string( $connect, json_encode([ 'key'=>[ 'd_orderdate'=>$orderdate, 'd_accountno'=>$accountno, 'd_jobtype' =>$jobtype ], 'before'=>$existing ], JSON_UNESCAPED_UNICODE) ); if (!mysqli_query($connect, " INSERT INTO tbl_erp_outbox (eo_event_type, eo_key_date, eo_key_accountno, eo_key_jobtype, eo_payload, eo_status, eo_created_at) VALUES ('DAILY_DELETED','{$orderdate}','{$accountno}','{$jobtype}','{$payload}','PENDING',NOW()) ")) { throw new Exception(mysqli_error($connect)); } // ========================= // 3. 물리 삭제 // ========================= if (!mysqli_query($connect, " DELETE FROM tbl_daily WHERE d_orderdate='{$orderdate}' AND d_accountno='{$accountno}' AND d_jobtype = '{$jobtype}' LIMIT 1 ")) { throw new Exception(mysqli_error($connect)); } if (mysqli_affected_rows($connect) === 0) { throw new Exception("Delete failed"); } // ========================= // AFTER WORK 중앙화 // ========================= $this->runAfterDelete($existing, $opt); // ========================= // COMMIT // ========================= if (!$inTx) { mysqli_query($connect, "COMMIT"); } return true; } catch (Exception $e) { if (!$inTx) { mysqli_query($connect, "ROLLBACK"); } throw $e; } } private function reEvaluateGhost(int $customerUid): void { $connect = $GLOBALS['conn']; $res = mysqli_query($connect, " SELECT d_quantity FROM tbl_daily WHERE d_customeruid = '{$customerUid}' AND d_status = 'F' ORDER BY d_orderdate DESC LIMIT 1 "); $row = mysqli_fetch_assoc($res); if (!$row) { // 데이터 없으면 ghost 해제 mysqli_query($connect, " UPDATE tbl_customer SET c_is_top = '' WHERE c_uid = '{$customerUid}' "); return; } $qty = (int)$row['d_quantity']; if ($qty < 10) { mysqli_query($connect, " UPDATE tbl_customer SET c_is_top = 'G' WHERE c_uid = '{$customerUid}' "); } else { mysqli_query($connect, " UPDATE tbl_customer SET c_is_top = '' WHERE c_uid = '{$customerUid}' "); } } private function recalcCustomerFromDailyHistory(string $customerUid): void { $connect = $GLOBALS['conn']; $customerUidEsc = mysqli_real_escape_string($connect, $customerUid); // 0) "오늘 포함 이후" 오더장 존재 여부 체크 (남아있으면 리셋 금지) $today = date('Ymd'); $resFuture = mysqli_query($connect, " SELECT 1 FROM tbl_daily WHERE d_customeruid = '{$customerUidEsc}' AND d_orderdate >= '{$today}' AND d_status = 'A' LIMIT 1 "); if (!$resFuture) { throw new Exception(mysqli_error($connect)); } $hasFutureOrder = (bool)mysqli_fetch_assoc($resFuture); // 1) 마지막 완료 주문(F) 기준으로 last pickup 재계산 $res = mysqli_query($connect, " SELECT d_orderdate, d_quantity, d_sludge, d_paymenttype, d_paystatus FROM tbl_daily WHERE d_customeruid = '{$customerUidEsc}' AND d_status = 'F' ORDER BY d_orderdate DESC LIMIT 1 "); if (!$res) { throw new Exception(mysqli_error($connect)); } $last = mysqli_fetch_assoc($res); $lastPickupDate = ''; $lastPickupQty = 0; $lastSludge = ''; $lastPaidDate = ''; if ($last) { $lastPickupDate = $last['d_orderdate']; $lastPickupQty = (int)$last['d_quantity']; $lastSludge = (string)$last['d_sludge']; if ($last['d_paymenttype'] === 'CA' && $last['d_paystatus'] === 'P') { $lastPaidDate = $last['d_orderdate']; } } // 2) 마지막 주문이 cash paid가 아니면, cash paid 마지막을 다시 찾음 if ($lastPaidDate === '') { $res2 = mysqli_query($connect, " SELECT d_orderdate FROM tbl_daily WHERE d_customeruid = '{$customerUidEsc}' AND d_status = 'F' AND d_paymenttype = 'CA' AND d_paystatus = 'P' ORDER BY d_orderdate DESC LIMIT 1 "); if (!$res2) { throw new Exception(mysqli_error($connect)); } $paid = mysqli_fetch_assoc($res2); if ($paid) { $lastPaidDate = $paid['d_orderdate']; } } // 3) UPDATE 구성 $setParts = []; $setParts[] = "c_lastpickupdate=" . ($lastPickupDate ? "'{$lastPickupDate}'" : "''"); $setParts[] = "c_lastpickupquantity='{$lastPickupQty}'"; $setParts[] = "c_lastpaiddate=" . ($lastPaidDate ? "'{$lastPaidDate}'" : "''"); $setParts[] = "c_sludge='" . mysqli_real_escape_string($connect, $lastSludge) . "'"; // 4) orderflag/orderdate 리셋 정책 반영 // - 오늘 포함 이후 오더장이 남아있으면 유지 (아무것도 안함) // - 없으면 리셋 if (!$hasFutureOrder) { $setParts[] = "c_orderdate=''"; $setParts[] = "c_orderflag=0"; } $sql = " UPDATE tbl_customer SET " . implode(",", $setParts) . " WHERE c_uid = '{$customerUidEsc}' LIMIT 1 "; if (!mysqli_query($connect, $sql)) { throw new Exception(mysqli_error($connect)); } } /* =============================== * 공통 JSON 응답 * =============================== */ private function jsonSuccess($data = []) { return json_encode([ 'result' => 'success', 'data' => $data ]); } private function jsonError($msg) { return json_encode([ 'result' => 'error', 'message'=> $msg ]); } }