with('sku')->where('status', 1)->whereIn('sku_id', WaterSku::query()->where('status', 1)->select('id')); } public function present($package): array { $sku = $package->sku; return [ 'id' => (int) $package->id, 'name' => $package->name, 'sku_id' => (int) $package->sku_id, 'sku_name' => $sku?->name, 'liters' => $sku ? (float) $sku->liters : null, 'buckets' => (int) $package->buckets, 'price_cents' => (int) $package->price_cents, 'unit_price_cents' => (int) round($package->price_cents / max(1, $package->buckets)), 'category' => null, 'valid_months' => null, 'includes_device' => null, ]; } public function listing(array $input): array { $page = new Pagination($input); $query = $this->query(); $keyword = Fields::text($input, 'keyword', 120, false); Fields::choice($input, 'category', ['all'], 'all'); if ($keyword !== '') { $query->where('name', 'like', '%' . $keyword . '%'); } $total = (clone $query)->count(); return $page->result($query->orderByDesc('id')->offset($page->offset())->limit($page->pageSize)->get()->map($this->present(...))->all(), $total) + [ 'categories' => [[ 'value' => 'all', 'label' => '全部', ]], 'capabilities' => ['category_filter' => false], ]; } public function detail(int $id): array { $package = $this->query()->find($id); if (!$package) { throw new ApiException(40401, '套餐不存在或已下架', 404); } return $this->present($package); } /** Lock the complete set before SKU rows, so creating a checkout has one coherent snapshot. */ public function lockedDetails(array $ids): array { $packages = WaterPackage::query()->whereIn('id', $ids)->orderBy('id')->lockForUpdate()->get(); $skus = WaterSku::query()->whereIn('id', $packages->pluck('sku_id')->unique()->all()) ->orderBy('id')->lockForUpdate()->get()->keyBy('id'); $result = []; foreach ($packages as $package) { $sku = $skus->get($package->sku_id); if ((int) $package->status !== 1 || !$sku || (int) $sku->status !== 1) { throw new ApiException(40401, '套餐不存在或已下架', 404); } $package->setRelation('sku', $sku); $result[(int) $package->id] = $this->present($package); } if (count($result) !== count($ids)) { throw new ApiException(40401, '套餐不存在或已下架', 404); } return $result; } }