'integer', 'park_id' => 'integer', 'psection_id' => 'integer', 'enable_months' => 'integer', 'regular_new_count' => 'integer', 'regular_new_amount' => 'decimal:2', 'regular_new_reduction_count' => 'integer', 'regular_new_reduction_amount' => 'decimal:2', 'regular_update_count' => 'integer', 'regular_update_amount' => 'decimal:2', 'regular_update_reduction_count' => 'integer', 'regular_update_reduction_amount' => 'decimal:2', 'lumpsum_count' => 'integer', 'lumpsum' => 'decimal:2', 'refunds' => 'decimal:2', 'other_income' => 'decimal:2', 'other_spending' => 'decimal:2', 'reissue_count' => 'integer', 'reissue_amount' => 'decimal:2', 'operator_id' => 'integer', 'summary_start_date' => 'date', 'summary_end_date' => 'date', 'earnings_date' => 'date', 'created_at' => 'datetime', 'updated_at' => 'datetime' ]; /** * 日付属性 * * @var array */ protected $dates = [ 'summary_start_date', 'summary_end_date', 'earnings_date', 'created_at', 'updated_at' ]; /** * 集計タイプの定数 */ const TYPE_DAILY = '日次'; const TYPE_MONTHLY = '月次'; const TYPE_YEARLY = '年次'; /** * 駐輪場との関連 * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function park() { return $this->belongsTo(Park::class, 'park_id', 'park_id'); } /** * 車種区分との関連 * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function psection() { return $this->belongsTo(Psection::class, 'psection_id', 'psection_id'); } /** * 指定期間の売上集計データを取得 * * @param int $parkId 駐輪場ID * @param string $startDate 開始日 * @param string $endDate 終了日 * @param string|null $summaryType 集計タイプ * @return \Illuminate\Database\Eloquent\Collection */ public static function getEarningsByPeriod(int $parkId, string $startDate, string $endDate, ?string $summaryType = null) { $query = self::where('park_id', $parkId) ->whereBetween('earnings_date', [$startDate, $endDate]); if ($summaryType) { $query->where('summary_type', $summaryType); } return $query->with(['park', 'psection']) ->orderBy('earnings_date') ->orderBy('psection_id') ->get(); } /** * 駐輪場別の売上合計を取得 * * @param int $parkId 駐輪場ID * @param string $startDate 開始日 * @param string $endDate 終了日 * @return array 売上合計データ */ public static function getEarningsTotalByPark(int $parkId, string $startDate, string $endDate): array { $result = self::where('park_id', $parkId) ->whereBetween('earnings_date', [$startDate, $endDate]) ->selectRaw(' SUM(regular_new_count) as total_new_count, SUM(regular_new_amount) as total_new_amount, SUM(regular_update_count) as total_update_count, SUM(regular_update_amount) as total_update_amount, SUM(lumpsum_count) as total_lumpsum_count, SUM(lumpsum) as total_lumpsum, SUM(refunds) as total_refunds, SUM(reissue_count) as total_reissue_count, SUM(reissue_amount) as total_reissue_amount ') ->first(); return $result ? $result->toArray() : []; } /** * 最新の集計日を取得 * * @param int|null $parkId 駐輪場ID(省略時は全体) * @param string|null $summaryType 集計タイプ * @return string|null 最新集計日 */ public static function getLatestEarningsDate(?int $parkId = null, ?string $summaryType = null): ?string { $query = self::query(); if ($parkId) { $query->where('park_id', $parkId); } if ($summaryType) { $query->where('summary_type', $summaryType); } $latest = $query->max('earnings_date'); return $latest ? Carbon::parse($latest)->format('Y-m-d') : null; } /** * 期間の売上データを削除 * * @param int $parkId 駐輪場ID * @param string $startDate 開始日 * @param string $endDate 終了日 * @param string|null $summaryType 集計タイプ * @return int 削除件数 */ public static function deleteEarningsByPeriod(int $parkId, string $startDate, string $endDate, ?string $summaryType = null): int { $query = self::where('park_id', $parkId) ->where('summary_start_date', $startDate) ->where('summary_end_date', $endDate); if ($summaryType) { $query->where('summary_type', $summaryType); } return $query->delete(); } /** * 売上集計データの作成 * * @param array $data 売上データ * @return EarningsSummary 作成されたモデル */ public static function createEarningsSummary(array $data): EarningsSummary { $defaultData = [ 'regular_new_count' => 0, 'regular_new_amount' => 0.00, 'regular_new_reduction_count' => 0, 'regular_new_reduction_amount' => 0.00, 'regular_update_count' => 0, 'regular_update_amount' => 0.00, 'regular_update_reduction_count' => 0, 'regular_update_reduction_amount' => 0.00, 'lumpsum_count' => 0, 'lumpsum' => 0.00, 'refunds' => 0.00, 'other_income' => 0.00, 'other_spending' => 0.00, 'reissue_count' => 0, 'reissue_amount' => 0.00, 'operator_id' => 0 ]; $mergedData = array_merge($defaultData, $data); return self::create($mergedData); } /** * 売上合計の計算 * * @return float 売上合計 */ public function getTotalEarningsAttribute(): float { return $this->regular_new_amount + $this->regular_update_amount + $this->lumpsum + $this->reissue_amount + $this->other_income - $this->other_spending - $this->refunds; } /** * 文字列表現 * * @return string */ public function __toString(): string { return sprintf( 'EarningsSummary[ID:%d, Park:%d, Type:%s, Date:%s]', $this->earnings_summary_id, $this->park_id, $this->summary_type, $this->earnings_date ? $this->earnings_date->format('Y-m-d') : 'N/A' ); } }