user(); if (! $user->isStoreMaster()) { throw new RuntimeException('非店长不可上报数据'); } // 是否是彩票店数据上报 $isLotteryLedger = $user->store?->isLotteryStore(); $validated = $request->validate( rules: [ 'date' => ['bail', 'required', 'date_format:Y-m-d'], 'items' => $isLotteryLedger ? ['bail', 'required', 'array'] : ['bail', 'array'], 'new_customers' => ['bail', 'required', 'int', 'min:0'], 'sales' => ['bail', 'required', 'numeric', 'min:0'], 'expenditure' => ['bail', 'required', 'numeric', 'min:0'], 'handover_amount' => ['bail', 'required', 'numeric', 'min:0'], 'photos' => ['bail', 'required', 'array'], ], attributes: [ 'date' => '日期', 'items' => '彩种数据', 'new_customers' => '新增客户', 'sales' => '销售合计', 'expenditure' => $isLotteryLedger ? '兑奖合计' : '支出合计', 'handover_amount' => '交账金额', 'photos' => '时段报表照片', ], ); /** @var \Illuminate\Database\Eloquent\Collection */ $lotteryTypes = Keyword::filter(['parent_key' => 'lottery_type']) ->oldest('sort') ->get(); // 上报数据项的格式: // [ // ['id' => '上报数据类型1', 'sales' => '销售金额', 'expenditure' => '兑奖金额'], // ['id' => '上报数据类型2', 'sales' => '销售金额', 'expenditure' => '兑奖金额'], // ] if ($isLotteryLedger) { $items = collect($validated['items'])->keyBy('id'); /** @var \App\Models\Keyword */ foreach ($lotteryTypes as $lotteryType) { $item = $items->get($lotteryType->key); if (is_null($item)) { throw new RuntimeException("{$lotteryType->name}未填写上报数据"); } Validator::validate( data: $item, rules: [ 'sales' => ['bail', 'required', 'numeric', 'min:0'], 'expenditure' => ['bail', 'required', 'numeric', 'min:0'], ], attributes: [ 'sales' => "[$lotteryType->name]销售金额", 'expenditure' => "[$lotteryType->name]兑奖金额", ], ); } } $date = Carbon::createFromFormat('Y-m-d', $validated['date']); /** @var \App\Models\Ledger|null */ $ledger = Ledger::where('store_id', $user->store_id) ->where('date', $date->format('Y-m-d')) ->first(); if ($ledger && ! $ledger->allowReReport()) { throw new RuntimeException('上报数据已更新,不可重新上传'); } $ratio = bcdiv($user->store->profit_ratio, 100, 4); // 计算预期佣金 $validated['expected_commission'] = bcmul($validated['sales'], $ratio, 2); // 计算预期收益 $validated['expected_income'] = bcsub($validated['expected_commission'], $validated['expenditure'], 2); try { DB::beginTransaction(); if (is_null($ledger)) { $ledger = Ledger::create( array_merge($validated, ['store_id' => $user->store_id]) ); } else { $ledger->update($validated); $ledger->items()->delete(); } LedgerItem::insert( collect( $isLotteryLedger ? $validated['items'] : [ [ 'id' => 'ledger_item_type_other', 'sales' => $ledger->sales, 'expenditure' => $ledger->expenditure, ], ] )->map(fn ($item) => [ 'date' => $ledger->date, 'store_id' => $ledger->store_id, 'ledger_id' => $ledger->id, 'ledger_item_type_id' => $item['id'], 'sales' => $item['sales'], 'expenditure' => $item['expenditure'], 'created_at' => $ledger->updated_at, 'updated_at' => $ledger->updated_at, ])->all() ); // 总账录入任务 /** @var \App\Models\TaskLedger */ $taskLedger = TaskLedger::where('store_id', $user->store_id) ->where('date', $ledger->date) ->first(); if ($taskLedger) { /** @var \App\Models\Task */ $task = $taskLedger->task; if (! $task->isSuccess()) { $task->markAsSuccess(); } } // 业绩指标任务 /** @var \App\Models\TaskPerformance */ $taskPerformance = TaskPerformance::where('store_id', $ledger->store_id) ->where('month', $date->format('Y-m')) ->first(); if ($taskPerformance) { $actualPerformance = Ledger::where('store_id', $ledger->store_id) ->whereBetween('date', [$date->copy()->startOfMonth()->format('Y-m-d'), $date->copy()->endOfMonth()->format('Y-m-d')]) ->sum('sales'); $taskPerformance->update([ 'actual_performance' => $actualPerformance, ]); if ($taskPerformance->isSuccess()) { /** @var \App\Models\Task */ $task = $taskPerformance->task; if (! $task->isSuccess()) { $task->markAsSuccess(); } } } DB::commit(); } catch (Throwable $e) { DB::rollBack(); throw tap($e, fn ($e) => report($e)); } return response()->noContent(); } public function show(string $date, Request $request) { /** @var \App\Models\Employee */ $user = $request->user(); /** @var \App\Models\Ledger|null */ $ledger = Ledger::with(['items']) ->where('store_id', $user->store_id) ->where('date', $date) ->first(); $items = []; if ($user->store?->isLotteryStore()) { /** @var \Illuminate\Database\Eloquent\Collection */ $lotteryTypes = Keyword::filter(['parent_key' => 'lottery_type']) ->oldest('sort') ->get(); $ledgerItems = collect(); if ($ledger) { $ledgerItems = $ledger->items->keyBy('ledger_item_type_id'); } $items = $lotteryTypes->map(function ($lotteryType) use ($ledgerItems) { $ledgerItem = $ledgerItems->get($lotteryType->key); return [ 'id' => $lotteryType->key, 'name' => $lotteryType->name, 'sales' => $ledgerItem?->sales, 'expenditure' => $ledgerItem?->expenditure, ]; })->all(); } return [ 'date' => $date, 'items' => $items, 'new_customers' => $ledger?->new_customers, 'sales' => $ledger?->sales, 'expenditure' => $ledger?->expenditure, 'handover_amount' => $ledger?->handover_amount, 'photos' => $ledger?->photos ?: [], 'allow_rereport' => is_null($ledger) ? true : $ledger->allowReReport(), ]; } }