bid = $bid; $this->month = $month; $this->currentMonthFirstDate = $this->month . '-01'; $this->lastMonthLastDate = date_sub(date_create($this->currentMonthFirstDate), date_interval_create_from_date_string('1 day'))->format('Y-m-d'); $this->currentMonthLastDate = date_sub(date_add(date_create($this->month), date_interval_create_from_date_string('1 month')), date_interval_create_from_date_string('1 day'))->format('Y-m-d'); $this->logger = CustomizeLogger::getLogger('bookMonthSettlement', 'debug'); $this->traceContext = app(TraceContext::class); } private function initSettlementModeInfo() { $record = DB::table('book_settlement_mode_history') ->where(['bid' => $this->bid, 'is_enabled' => 1]) ->where('effective_date', '<', $this->currentMonthFirstDate) ->orderBy('id', 'desc') ->first(); if(!$record) { $bookInfo = DB::table('books') ->where(['id' => $this->bid]) ->select('id', 'settlement_type', 'bottomline') ->first(); $modeInfo = [ 'settlement_mode' => $bookInfo->settlement_type, 'bottomline' => $bookInfo->bottomline, 'effective_date' => '2000-01-01', 'total_amount' => 0, 'change_reason' => 'manual', ]; } else { $modeInfo = [ 'settlement_mode' => $record->settlement_mode, 'bottomline' => $record->bottomline, 'effective_date' => $record->effective_date, 'total_amount' => $record->total_amount, 'change_reason' => $record->change_reason, ]; } if('bottomline' == $modeInfo['settlement_mode']) { if('manual' == $modeInfo['change_reason']) { $modeInfo['total_amount'] = $this->getBookTotalAmount($modeInfo['effective_date']); } if($modeInfo['total_amount'] >= $modeInfo['bottomline']) { $modeInfo['settlement_mode'] = 'out_bottomline'; } } $this->logger->debug('初始结算状态', [ 'traceInfo' => $this->traceContext->getTraceInfo(), 'modeInfo' => $modeInfo]); return $modeInfo; } private function getBookTotalAmount($effectiveDate) { return DB::table('cp_subscribe_statistic_data') ->where([ ['settlement_date', '>=', $effectiveDate], ['settlement_date', '<=', $this->lastMonthLastDate], ['bid' , '=', $this->bid], ])->sum('yesterday_final_amount'); } private function getInitialSettlementModeInfo(){ if(is_null($this->initialSettlementModeInfo)) { $this->initialSettlementModeInfo = $this->initSettlementModeInfo(); } return $this->initialSettlementModeInfo; } /** * 获取本月可用结算模式 * @return null */ private function getSettlementModes() { if(is_null($this->settlementModeInfos)) { $initSettlementMode = $this->getInitialSettlementModeInfo(); $this->settlementModeInfos[$initSettlementMode['effective_date']] = $initSettlementMode; $historyList = DB::table('book_settlement_mode_history') ->whereBetween('effective_date', [$this->currentMonthFirstDate, $this->currentMonthLastDate]) ->where(['is_enabled' => 1, 'bid' => $this->bid]) ->orderBy('id', 'asc') ->get(); foreach ($historyList as $history) { $this->settlementModeInfos[$history->effective_date] = [ 'settlement_mode' => $history->settlement_mode, 'bottomline' => $history->bottomline, 'effective_date' => $history->effective_date, 'total_amount' => $history->total_amount ]; } } return $this->settlementModeInfos; } /** * 获取本月每日原始应结算金额明细 * @return \Illuminate\Support\Collection */ private function getFinalAmounts() { if (is_null($this->finalAmounts)) { $this->finalAmounts = DB::table('cp_subscribe_statistic_data') ->whereBetween('settlement_date', [$this->currentMonthFirstDate, $this->currentMonthLastDate]) ->select('yesterday_final_amount', 'settlement_date', 'bid') ->where(['bid' => $this->bid]) ->get()->keyBy('settlement_date'); } return $this->finalAmounts; } /** * 获取 {month} 中各天的应结算金额 * @return array *
     * [
     *      "2023-03-01"=> 2.5,
     *      "2023-03-02"=> 2.5,
     *      ...
     *      "2023-03-30"=> 2.5,
     *      "2023-03-31"=> 2.5,
     * ]
     * 
*/ public function detail() { $this->logger->debug('开始处理书籍', [ 'traceInfo' => $this->traceContext->getTraceInfo(), 'bid' => $this->bid, 'month' => $this->month, ]); $date = $this->currentMonthFirstDate; $settlementModes = $this->getSettlementModes(); $this->logger->debug('结算状态集合', ['traceInfo' => $this->traceContext->getTraceInfo(), 'settlementModeInfos' => $settlementModes]); $finalAmounts = $this->getFinalAmounts(); $this->logger->debug('原始应结算金额', ['traceInfo' => $this->traceContext->getTraceInfo(), 'sourceFinalAmounts' => $finalAmounts->toArray()]); while ($date <= $this->currentMonthLastDate) { $this->logger->debug('开始处理日期:'. $date, ['traceInfo' => $this->traceContext->getTraceInfo(), 'date' => $date]); $nextDate = date_add(date_create($date), date_interval_create_from_date_string('1 day')) ->format('Y-m-d'); if($finalAmounts->has($date)) { $currentSettlementMode = null; ksort($settlementModes); foreach ($settlementModes as $settlementMode) { if($date >= $settlementMode['effective_date']) { $currentSettlementMode = $settlementMode; } } $sourceFinalAmount = $finalAmounts->get($date)->yesterday_final_amount; $this->logger->debug('该天有原始应结算金额数据', ['traceInfo' => $this->traceContext->getTraceInfo(), 'sourceFinalAmount' => $sourceFinalAmount]); $this->logger->debug('该日期可用的结算模式', ['traceInfo' => $this->traceContext->getTraceInfo(), 'settlementMode' => $currentSettlementMode]); if('bottomline' == $currentSettlementMode['settlement_mode']) { $settlementModes[$currentSettlementMode['effective_date']]['total_amount'] += $sourceFinalAmount; if($settlementModes[$currentSettlementMode['effective_date']]['total_amount'] > $settlementModes[$currentSettlementMode['effective_date']]['bottomline']) { $this->settlementResult[$date] = $settlementModes[$currentSettlementMode['effective_date']]['total_amount'] - $settlementModes[$currentSettlementMode['effective_date']]['bottomline']; $this->logger->debug('当前原始应结算金额累计超出书籍保底金额', ['traceInfo' => $this->traceContext->getTraceInfo(), 'currentSettlementMode' => $settlementModes[$currentSettlementMode['effective_date']], 'realFinalAmount' => $this->settlementResult[$date]]); if(!key_exists($nextDate, $settlementModes)) { $this->logger->debug('下一天没有对应结算模式故可增加一个超保底结算模式,保证下一天按超保底结算', ['traceInfo' => $this->traceContext->getTraceInfo(), 'nextDate' => $nextDate]); $settlementModes[$nextDate] = [ 'settlement_mode' => 'out_bottomline', 'effective_date' => $nextDate, 'total_amount' => 0, 'bottomline' => 0, ]; } } else { $this->logger->debug('当前原始应结算金额没有超出书籍保底金额', ['traceInfo' => $this->traceContext->getTraceInfo(), 'realFinalAmount' => 0]); $this->settlementResult[$date] = 0; } } elseif ('buyout' == $currentSettlementMode['settlement_mode']) { $this->logger->debug('当前书籍结算模式为买断,故该天最终结算0', ['traceInfo' => $this->traceContext->getTraceInfo(), 'realFinalAmount' => 0]); $this->settlementResult[$date] = 0; } else { $this->logger->debug('其他的结算模式,应结算金额保持不变', ['traceInfo' => $this->traceContext->getTraceInfo(), 'realFinalAmount' => $sourceFinalAmount]); $this->settlementResult[$date] = $sourceFinalAmount; } } else { $this->settlementResult[$date] = 0; } $date = $nextDate; } ksort($settlementModes); $lastMonthLastDateSettlementMode = \last($settlementModes); $now = date('Y-m-d H:i:s'); if('out_bottomline' == $lastMonthLastDateSettlementMode['settlement_mode']) { $this->logger->debug('入库保存本月最后一个结算模式', ['traceInfo' => $this->traceContext->getTraceInfo(), 'lastMonthLastDateSettlementMode' => $lastMonthLastDateSettlementMode]); DB::table('book_settlement_mode_history') ->insert([ 'bid' => $this->bid, 'effective_date' => $this->currentMonthLastDate, 'settlement_mode' => $lastMonthLastDateSettlementMode['settlement_mode'], 'bottomline' => $lastMonthLastDateSettlementMode['bottomline'], 'total_amount' => $lastMonthLastDateSettlementMode['total_amount'], 'change_reason' => 'auto', 'created_at' => $now, 'updated_at' => $now ]); } return $this->settlementResult; } }