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;
}
}