count($data), 'list' => $this->newEachOrderData($data), ]; } private function newEachOrderData($list): array { $result = []; if (empty($list)) return $result; foreach ($list as $item) { $result[] = [ 'uid' => getProp($item, 'uid'), 'price' => getProp($item, 'price'), 'distribution_channel_id' => getProp($item, 'distribution_channel_id'), 'trade_no' => getProp($item, 'trade_no'), 'transaction_id' => getProp($item, 'transaction_id'), 'send_order_id' => getProp($item, 'send_order_id'), 'order_type' => getProp($item, 'order_type'), 'created_at' => transDate(getProp($item, 'created_at')), ]; } return $result; } public function newBuildUserData($data): array { return [ 'count' => count($data), 'list' => $this->newEachUserData($data), ]; } private function newEachUserData($list): array { $result = []; if (empty($list)) return $result; foreach ($list as $item) { $result[] = [ 'uid' => getProp($item, 'id'), 'nickname' => getProp($item, 'nickname'), 'distribution_channel_id' => getProp($item, 'distribution_channel_id'), 'send_order_id' => getProp($item, 'send_order_id'), 'from_uid' => getProp($item, 'from_uid'), 'balance' => getProp($item, 'balance'), 'charge_balance' => getProp($item, 'charge_balance'), 'reward_balance' => getProp($item, 'reward_balance'), 'vip_limit_date' => transDate(getProp($item, 'vip_limit_date')), 'token' => getProp($item, 'token'), 'created_at' => transDate(getProp($item, 'created_at')), ]; } return $result; } public function newBuildReportData($data): array { return [ 'meta' => getMeta($data), 'list' => $this->newEachReportData($data->items()), 'header' => $data->header, ]; } private function newEachReportData($list): array { $result = []; if (empty($list)) return $result; foreach ($list as $item) { $callback_result = getProp($item, 'callback_result'); $remark = getProp($item, 'remark'); $remark = getProp($item, 'id') && $remark == '' ? '比例回传' : $remark; if (!getProp($item, 'id') && $remark == '') $remark = '回传类型过滤'; $is_enable_report = 0; if ($callback_result == '失败' && $remark == '比例过滤') $is_enable_report = 1; $result[] = [ 'report_id' => getProp($item, 'id'), 'trade_no' => getProp($item, 'trade_no'), 'send_order_id' => getProp($item, 'send_order_id'), 'advertiser_id' => getProp($item, 'advertiserid'), 'promotion_id' => getProp($item, 'promotionid'), 'callback_result' => $callback_result ? $callback_result : '失败', 'remark' => $remark, 'is_enable_report' => $is_enable_report, 'uid' => getProp($item, 'uid'), 'register_ip' => getProp($item, 'register_ip'), 'register_time' => transDate(getProp($item, 'register_time')), 'pay_time' => transDate(getProp($item, 'pay_time')), 'price' => getProp($item, 'price'), 'current_percent' => getProp($item, 'report_receive_num') ? round(getProp($item, 'report_post_num')/getProp($item, 'report_receive_num')*100, 2) : 0, 'report_percent' => (float)getProp($item, 'report_percent'), ]; } return $result; } public function newBuildSendOrderData($data): array { return [ 'meta' => getMeta($data), 'list' => $this->newEachSendOrderData($data->items()), 'header' => 'https://'.env('DOUYIN_DOMAIN').'/api/listenData?dycallback=1&channel_id='.$data->channel_id.'&adid=__AID__&creativeid=__CID__&creativetype=__CTYPE__&clickid=__CLICKID__&ip=__IP__&ua=__UA__', ]; } private function newEachSendOrderData($list): array { $result = []; if (empty($list)) return $result; $start = date('Y-m-d 00:00:00'); foreach ($list as $item) { $send_order_id = getProp($item, 'id'); // 获取今日注册人数 $today_register_num = DB::table('users')->where('send_order_id', $send_order_id)->where('created_at', '>', $start)->count('id'); // 今日订单信息 $today_order = DB::table('orders')->leftJoin('users', 'orders.uid', 'users.id')->where('users.send_order_id', $send_order_id) ->where('orders.send_order_id', $send_order_id)->where('users.created_at', '>', $start) ->where('orders.status', 'PAID')->where('orders.created_at', '>', $start)->selectRaw("count(orders.pay_num = 1) as register_pay_num, sum(orders.price) as register_pay_amount")->get(); $today_register_pay_num = getProp($today_order[0], 'register_pay_num'); $today_register_pay_amount = getProp($today_order[0], 'register_pay_amount') ? getProp($today_order[0], 'register_pay_amount') : 0; // // 获取今日注册充值人数(只计算首充) // $today_register_pay_num = DB::table('orders')->leftJoin('users', 'orders.uid', 'users.id')->where('users.send_order_id', $send_order_id) // ->where('orders.send_order_id', $send_order_id)->where('users.created_at', '>', $start) // ->where('orders.status', 'PAID')->where('orders.created_at', '>', $start)->where('orders.pay_num', 1)->count('orders.id'); // // 获取今日注册用户充值金额(包含多充) // $today_register_pay_amount = DB::table('users')->leftJoin('orders', 'orders.uid', 'users.id')->where('users.send_order_id', $send_order_id) // ->where('orders.send_order_id', $send_order_id)->where('users.created_at', '>', $start) // ->where('orders.status', 'PAID')->where('orders.created_at', '>', $start)->sum('orders.price'); // 派单uv $uv = Redis::scard('send_order_uv_'.$send_order_id); $uv = $uv ? $uv : 0; // 累计订单信息 $total_order = DB::table('orders')->where('orders.send_order_id', $send_order_id)->where('orders.status', 'PAID') ->selectRaw("count(distinct orders.uid) as pay_num, sum(orders.price) as pay_amount")->get(); $total_pay_num = getProp($total_order[0], 'pay_num'); $total_pay_amount = getProp($total_order[0], 'pay_amount') ? getProp($total_order[0], 'pay_amount') : 0; // // 累计充值人数 // $a = DB::table('orders')->where('send_order_id', $send_order_id)->where('status', 'PAID')->select('uid')->groupBy('uid')->get(); // $total_pay_num = count($a); // // 累计充值金额 // $total_pay_amount = DB::table('orders')->where('send_order_id', $send_order_id)->where('status', 'PAID')->sum('price'); $result[] = [ 'send_order_id' => $send_order_id, 'distribution_channel_id' => getProp($item, 'distribution_channel_id'), 'channel_type' => getProp($item, 'channel_type'), 'send_order_name' => getProp($item, 'name'), 'promote_user' => getProp($item, 'nickname'), 'send_order_url' => getProp($item, 'send_order_url'), 'url_params' => $this->setUrlParams(getProp($item, 'id'), getProp($item, 'distribution_channel_id'), getProp($item, 'book_id'), getProp($item, 'chapter_id')), 'bid' => getProp($item, 'book_id'), 'book_name' => getProp($item, 'book_name'), 'category_name' => getProp($item, 'category_name'), 'cid' => getProp($item, 'chapter_id'), 'chapter_name' => getProp($item, 'chapter_name'), 'cover' => addPrefix(getProp($item, 'cover')), 'intro' => filterIntro(getProp($item, 'intro')), 'report_percent' => (float)sprintf('%.2f', getProp($item, 'report_percent')), 'report_receive_num' => (int)getProp($item, 'report_receive_num'), 'report_post_num' => (int)getProp($item, 'report_post_num'), 'created_at' => transDate(getProp($item, 'created_at')), 'template_id' => (int)getProp($item, 'template_id'), 'template_name' => getProp($item, 'template_name'), 'today_register_num' => (int)$today_register_num, 'today_register_pay_num' => (int)$today_register_pay_num, 'today_register_pay_amount' => (float)sprintf('%.2f', $today_register_pay_amount), 'total_register_num' => (int)(getProp($item, 'total_register_num') + $today_register_num), 'total_register_pay_num' => (int)(getProp($item, 'total_register_pay_num') + $today_register_pay_num), 'total_register_pay_amount' => (float)sprintf('%.2f', (getProp($item, 'total_register_pay_amount') + $today_register_pay_amount)), 'uv' => $uv, 'total_pay_num' => (int)$total_pay_num, 'total_pay_amount' => (float)sprintf('%.2f', $total_pay_amount), 'total_cost' => (float)sprintf('%.2f', getProp($item, 'cost')), 'total_profit' => (float)sprintf('%.2f', getProp($item, 'total_profit')), 'total_profit_percent' => (float)getProp($item, 'cost') ? (float)sprintf('%.2f', ($total_pay_amount / getProp($item, 'cost') * 100)) : 0 ]; } return $result; } public function newBuildSendOrderDayData($data): array { return [ 'meta' => getMeta($data), 'list' => $this->newEachSendOrderDayData($data->items(), $data->start_date, $data->send_order_id), 'send_order_name' => $data->send_order_name, 'send_order_id' => $data->send_order_id, ]; } private function newEachSendOrderDayData($list, $start_date, $send_order_id): array { $result = []; if (empty($list)) return $result; $start = $start_date; $end = date('Y-m-d', strtotime($start.' +60 day')); // 获取最近2个月的数据 $data = DB::table('send_order_recharge_day_stats')->where('send_order_id', $send_order_id)->whereBetween('register_date', [$start, $end]) ->orderBy('pay_date')->get()->map(function ($value) { return (array)$value; })->toArray(); $day_stats = []; // 注册用户派单日数据初始化 foreach ($list as $item) { $day_stats[getProp($item, 'day')] = []; } // 将已有数据填充 foreach ($data as $item) { $day = $item['register_date']; $day_stats[$day]['t'.$item['day_num']] = [ 'register_pay_amount' => $item['pay_amount'], 'total_register_pay_amount' => $item['day_num'] == 0 ? $item['pay_amount'] : 0, // t0日有金额,其他日在下个循环累加 ]; } // 将当日无数据的日期占位并计算累计值 foreach ($day_stats as $day=>$value) { $today_start = date('Y-m-d 00:00:00'); $today_end = date('Y-m-d 23:59:59'); // 获取当日注册用户 if (Redis::exists('register_uids_'.$send_order_id.'_'.$day)) { //获取缓存 $day_register_uids = json_decode(Redis::get('register_uids_'.$send_order_id.'_'.$day), true); }else { $day_register_uids = DB::table('users')->where('send_order_id', $send_order_id) ->whereBetween('created_at', [date('Y-m-d 00:00:00', strtotime($day)), date('Y-m-d 23:59:59', strtotime($day))]) ->select('id')->get()->pluck('id')->toArray(); // 写入缓存 Redis::set('register_uids_'.$send_order_id.'_'.$day, json_encode($day_register_uids)); Redis::expire('register_uids_'.$send_order_id.'_'.$day, strtotime($today_end)-time()); } // 获取注册用户今日数据 $day_stats[$day]['today']['register_pay_amount'] = DB::table('orders')->where('send_order_id', $send_order_id)->where('status', 'PAID') ->whereIn('uid', $day_register_uids)->whereBetween('created_at', [$today_start, $today_end])->sum('price'); $day_stats[$day]['today']['total_register_pay_amount'] = DB::table('orders')->where('send_order_id', $send_order_id)->where('status', 'PAID') ->whereIn('uid', $day_register_uids)->where('created_at', '<=', $today_end)->sum('price'); // 获取注册用户总数据 $total_data = DB::table('orders')->where('send_order_id', $send_order_id)->where('status', 'PAID') ->whereIn('uid', $day_register_uids)->selectRaw("count(distinct uid) as pay_num, sum(price) as total_pay_amount")->get(); $day_stats[$day]['total']['pay_num'] = getProp($total_data[0], 'pay_num'); $day_stats[$day]['total']['total_pay_amount'] = getProp($total_data[0], 'total_pay_amount') ? getProp($total_data[0], 'total_pay_amount') : 0; // $day_stats[$day]['total']['pay_num'] = count(DB::table('orders')->where('send_order_id', $send_order_id)->where('orders.status', 'PAID') // ->whereIn('uid', $day_register_uids)->select('uid')->groupBy('uid')->get()); // $day_stats[$day]['total']['total_pay_amount'] = DB::table('orders')->where('send_order_id', $send_order_id)->where('orders.status', 'PAID') // ->whereIn('uid', $day_register_uids)->sum('price'); for ($i=0;$i<=29;$i++) { $diff_day = (strtotime(date('Y-m-d'))-strtotime($day))/86400; if (isset($day_stats[$day]['t'.$i])) { if ($i != 0) $day_stats[$day]['t'.$i]['total_register_pay_amount'] = round($day_stats[$day]['t'.($i-1)]['total_register_pay_amount'] + $day_stats[$day]['t'.$i]['register_pay_amount'], 2); }else { if ($i == $diff_day) { // 如果是当日则取当日数据 $day_stats[$day]['t'.$i] = [ 'register_pay_amount' => $day_stats[$day]['today']['register_pay_amount'], 'total_register_pay_amount' => 0, ]; }else { $day_stats[$day]['t'.$i] = [ 'register_pay_amount' => 0, 'total_register_pay_amount' => 0, ]; } if ($i != 0) $day_stats[$day]['t'.$i]['total_register_pay_amount'] = round($day_stats[$day]['t'.($i-1)]['total_register_pay_amount'] + $day_stats[$day]['t'.$i]['register_pay_amount'], 2); } } } foreach ($list as $item) { $send_order_id = getProp($item, 'send_order_id'); $day = getProp($item, 'day'); $cost = (float)getProp($item, 'cost'); // 获取日统计数据 $stats = $day_stats[$day]; $result[] = [ 'id' => getProp($item, 'id'), 'send_order_id' => $send_order_id, 'date' => $day, 'cost' => $cost, 'register_num' => getProp($item, 'register_num'), // 注册用户 'register_cost' => getProp($item, 'register_num') ? round($cost/getProp($item, 'register_num'), 2) : 0, // 注册成本 'register_pay_num' => getProp($item, 'register_pay_num'), // 当日注册充值人数 'register_pay_percent' => getProp($item, 'register_num') ? round(getProp($item, 'register_pay_num')/getProp($item, 'register_num')*100, 2) : 0, // 当日注册付费率 'register_pay_cost' => getProp($item, 'register_pay_num') ? round($cost/getProp($item, 'register_pay_num'), 2) : 0, // 当日转化成本 'total_register_pay_amount' => (float)sprintf('%.2f', getProp($stats, 'total')['total_pay_amount']), // 累计充值 'total_profit_percent' => (float)$cost ? round(getProp($stats, 'total')['total_pay_amount']/$cost*100, 2) : 0, //累计回本率 'total_profit_cost' => getProp($stats, 'total')['pay_num'] ? round($cost / getProp($stats, 'total')['pay_num'], 2) : 0, 't0' => [ 'register_pay_amount' => (float)$stats['t0']['register_pay_amount'], 'total_register_pay_amount' => (float)$stats['t0']['total_register_pay_amount'], 'profit_percent' => (float)$cost ? round($stats['t0']['register_pay_amount']/$cost*100, 2) : 0, //当日回本率 'total_profit_percent' => (float)$cost ? round($stats['t0']['total_register_pay_amount']/$cost*100, 2) : 0, //累计回本率 ], 't1' => [ 'register_pay_amount' => (float)$stats['t1']['register_pay_amount'], 'total_register_pay_amount' => (float)$stats['t1']['total_register_pay_amount'], 'profit_percent' => (float)$cost ? round($stats['t1']['register_pay_amount']/$cost*100, 2) : 0, //当日回本率 'total_profit_percent' => (float)$cost ? round($stats['t1']['total_register_pay_amount']/$cost*100, 2) : 0, //累计回本率 ], 't2' => [ 'register_pay_amount' => (float)$stats['t2']['register_pay_amount'], 'total_register_pay_amount' => (float)$stats['t2']['total_register_pay_amount'], 'profit_percent' => (float)$cost ? round($stats['t2']['register_pay_amount']/$cost*100, 2) : 0, //当日回本率 'total_profit_percent' => (float)$cost ? round($stats['t2']['total_register_pay_amount']/$cost*100, 2) : 0, //累计回本率 ], 't3' => [ 'register_pay_amount' => (float)$stats['t3']['register_pay_amount'], 'total_register_pay_amount' => (float)$stats['t3']['total_register_pay_amount'], 'profit_percent' => (float)$cost ? round($stats['t3']['register_pay_amount']/$cost*100, 2) : 0, //当日回本率 'total_profit_percent' => (float)$cost ? round($stats['t3']['total_register_pay_amount']/$cost*100, 2) : 0, //累计回本率 ], 't4' => [ 'register_pay_amount' => (float)$stats['t4']['register_pay_amount'], 'total_register_pay_amount' => (float)$stats['t4']['total_register_pay_amount'], 'profit_percent' => (float)$cost ? round($stats['t4']['register_pay_amount']/$cost*100, 2) : 0, //当日回本率 'total_profit_percent' => (float)$cost ? round($stats['t4']['total_register_pay_amount']/$cost*100, 2) : 0, //累计回本率 ], 't5' => [ 'register_pay_amount' => (float)$stats['t5']['register_pay_amount'], 'total_register_pay_amount' => (float)$stats['t5']['total_register_pay_amount'], 'profit_percent' => (float)$cost ? round($stats['t5']['register_pay_amount']/$cost*100, 2) : 0, //当日回本率 'total_profit_percent' => (float)$cost ? round($stats['t5']['total_register_pay_amount']/$cost*100, 2) : 0, //累计回本率 ], 't6' => [ 'register_pay_amount' => (float)$stats['t6']['register_pay_amount'], 'total_register_pay_amount' => (float)$stats['t6']['total_register_pay_amount'], 'profit_percent' => (float)$cost ? round($stats['t6']['register_pay_amount']/$cost*100, 2) : 0, //当日回本率 'total_profit_percent' => (float)$cost ? round($stats['t6']['total_register_pay_amount']/$cost*100, 2) : 0, //累计回本率 ], 't14' => [ 'register_pay_amount' => (float)$stats['t14']['register_pay_amount'], 'total_register_pay_amount' => (float)$stats['t14']['total_register_pay_amount'], 'profit_percent' => (float)$cost ? round($stats['t14']['register_pay_amount']/$cost*100, 2) : 0, //当日回本率 'total_profit_percent' => (float)$cost ? round($stats['t14']['total_register_pay_amount']/$cost*100, 2) : 0, //累计回本率 ], 't29' => [ 'register_pay_amount' => (float)$stats['t29']['register_pay_amount'], 'total_register_pay_amount' => (float)$stats['t29']['total_register_pay_amount'], 'profit_percent' => (float)$cost ? round($stats['t29']['register_pay_amount']/$cost*100, 2) : 0, //当日回本率 'total_profit_percent' => (float)$cost ? round($stats['t29']['total_register_pay_amount']/$cost*100, 2) : 0, //累计回本率 ], ]; } return $result; } /** * @param $send_order_id // 派单id * @param $distribution_channel_id // 站点id * @param $bid // 书籍id * @param $cid // 章节id * @return string */ private function setUrlParams($send_order_id, $distribution_channel_id, $bid, $cid) { $arr = [ 'bid' => $bid ? Hashids::encode($bid) : '', 'cid' => $cid ? Hashids::encode($cid) : '', 'send_order_id' => $send_order_id, 'distribution_channel_id' => $distribution_channel_id, 'jump' => 'no', ]; $path = 'pages/reader/index'; return '/' . $path . '?' . http_build_query($arr); } /** * 订单列表 * * @param $data * @return array */ public function orderList($data): array { return [ 'meta' => getMeta($data), 'list' => $this->eachOrderList($data->items()), ]; } private function eachOrderList($list): array { if (empty($list)) { return []; } $result = []; foreach ($list as $item) { $result[] = [ 'trade_no' => getProp($item, 'trade_no'), 'promote_user' => getProp($item, 'nickname'), 'uid' => getProp($item, 'uid'), 'distribution_channel_id' => getProp($item, 'distribution_channel_id'), 'register_ip' => getProp($item, 'register_ip'), 'register_at' => getProp($item, 'register_time'), 'bind_send_order_time' => getProp($item, 'bind_send_order_time') ? transDate(getProp($item, 'bind_send_order_time')) : transDate(getProp($item, 'register_time')), 'book_name' => getProp($item, 'book_name'), 'send_order_id' => getProp($item, 'send_order_id'), 'send_order_name' => getProp($item, 'send_order_name'), 'price' => (float)getProp($item, 'price'), 'status' => getProp($item, 'status'), 'order_type' => getProp($item, 'order_type'), 'created_at' => $item->created_at->format('Y-m-d H:i:s'), 'updated_at' => $item->updated_at->format('Y-m-d H:i:s'), ]; } return $result; } public function newBuildTemplateList($data): array { return [ 'meta' => getMeta($data), 'list' => $this->newEachTemplateData($data), ]; } private function newEachTemplateData($list): array { $result = []; if (empty($list)) return $result; $user_scope_arr = BaseConst::USER_SCOPE; foreach ($list as $item) { $template_id = getProp($item, 'id'); $uv = StatisticCache::getTemplateUV($template_id); // 获取uv // 获取充值产品 $product_origin = DB::table('products')->where('template_id', $template_id)->where('is_enabled', 1) ->get(); $product_ids = []; $products = []; foreach ($product_origin as $v) { $product_ids[] = getProp($v, 'id'); $coin = $v->given ? (int)round($v->price*100).'+'.$v->given : (int)round($v->price*100); $products[] = [ 'price' => (float)sprintf('%.2f', $v->price), 'coin' => (int)$coin, 'price_desc' => $v->price_desc, 'name_desc' => $v->name_desc, 'given' => (int)$v->given, 'is_default' => (int)$v->is_default, 'angle_sign_text' => $v->angle_sign_text, 'type' => $v->type, 'product_id' => (int)$v->id, ]; } $distribution_channel_id = getProp($item, 'distribution_channel_id'); $order_data = DB::table('orders')->where('status', 'PAID')->where('distribution_channel_id', $distribution_channel_id) ->whereIn('product_id', $product_ids)->selectRaw("count(distinct uid) as pay_num, sum(price) as total_pay_amount")->get(); $pay_num = (int)getProp($order_data[0], 'pay_num'); // 充值人数 $total_pay_amount = (float)sprintf('%.2f', getProp($order_data[0], 'total_pay_amount')); // 充值总额 $pay_percent = $uv ? (float)sprintf('%.2f', ($pay_num / $uv * 100)) : 0; // 充值转化 $result[] = [ 'template_id' => getProp($item, 'id'), 'template_name' => getProp($item, 'template_name'), 'distribution_channel_id' => $distribution_channel_id, 'send_order_id' => getProp($item, 'send_order_id'), 'template_type' => getProp($item, 'template_type') == 1 ? '默认模板' : '补充模板', 'user_scope' => isset($user_scope_arr[getProp($item, 'user_scope')]) ? $user_scope_arr[getProp($item, 'user_scope')] : '未知', 'orders' => (int)getProp($item, 'orders') === 0 ? '--' : getProp($item, 'orders'), 'is_enable' => getProp($item, 'is_enable'), 'UV' => (int)$uv, 'pay_num' => $pay_num, 'pay_percent' => $pay_percent, 'total_pay_amount' => $total_pay_amount, 'products' => $products, 'created_at' => transDate(getProp($item, 'created_at')), ]; } return $result; } }