DATA/UPBIT/daemon/target_day/db_trading.php
<?php
// =============================================================
// db_trading.php - 매매 기록 장부
// =============================================================

function record_trading($db_upbit, $params = []) {

    if (!is_object($db_upbit)) return;

    try {
        // response 배열 보장
        $upbit_resp = isset($params['response']) && is_array($params['response']) 
                      ? $params['response'] 
                      : [];

        $result       = $params['result']  ?? 'fail';
        $upbit_uuid   = $upbit_resp['uuid']            ?? $upbit_resp['id']        ?? null;
        $state        = $upbit_resp['state']            ?? null;
        $executed_vol = isset($upbit_resp['executed_volume']) ? (float)$upbit_resp['executed_volume'] : null;
        $avg_price    = isset($upbit_resp['avg_buy_price'])   ? (float)$upbit_resp['avg_buy_price']
                      : (isset($upbit_resp['avg_price'])      ? (float)$upbit_resp['avg_price'] : null);
        $paid_fee     = isset($upbit_resp['paid_fee'])        ? (float)$upbit_resp['paid_fee']   : null;

        // response_json UTF-8 안전 인코딩
        $response_json = json_encode(
            $upbit_resp,
            JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_INVALID_UTF8_SUBSTITUTE
        );

        // message: 파라미터 우선, 없으면 response 에러 메시지 추출
        $message = $params['message'] 
                   ?? $upbit_resp['error']['message'] 
                   ?? null;

        $sql = "INSERT INTO daemon_trading
                    (cron_id, market, side, step_code, step_code_val,
                     trigger_type, trigger_value, ord_type,
                     req_price, req_volume, upbit_uuid, state,
                     executed_volume, avg_price, paid_fee,
                     response_json, result, message, timestamp)
                VALUES
                    (:cron_id, :market, :side, NULL, '0',
                     :trigger_type, :trigger_value, :ord_type,
                     :req_price, :req_volume, :upbit_uuid, :state,
                     :executed_volume, :avg_price, :paid_fee,
                     :response_json, :result, :message, NOW())";

        $stmt = $db_upbit->prepare($sql);
        $stmt->execute([
            ':cron_id'         => $params['cron_id']       ?? '',
            ':market'          => $params['market']        ?? '',
            ':side'            => $params['side']          ?? 'bid',
            ':trigger_type'    => $params['trigger_type']  ?? '',
            ':trigger_value'   => $params['trigger_value'] ?? null,
            ':ord_type'        => $params['ord_type']      ?? 'price',
            ':req_price'       => $params['req_price']     ?? null,
            ':req_volume'      => $params['req_volume']    ?? null,
            ':upbit_uuid'      => $upbit_uuid,
            ':state'           => $state,
            ':executed_volume' => $executed_vol,
            ':avg_price'       => $avg_price,
            ':paid_fee'        => $paid_fee,
            ':response_json'   => $response_json,
            ':result'          => $result,
            ':message'         => $message,
        ]);

    } catch (Throwable $e) {
        // 조용히 실패
        return;
    }
}
?>