priceCents($key) !== null; } /** * Every module we sell, each answered for this customer: booked ones at * the price they were booked at, the rest at today's. * * A module can be booked more than once — storage is sold in packs, and two * orders can each carry one — and each booking keeps its own price. So the * bookings are summed rather than reduced to one row: showing a single * arbitrary price while charging for all of them would let the page and the * bill say different things. * * @return array}> */ public function forSubscription(?Subscription $subscription): array { $booked = $subscription?->addons()->active()->orderBy('id')->get()->groupBy('addon_key') ?? collect(); $keys = array_merge(array_keys((array) config('provisioning.addons')), [self::STORAGE]); $rows = []; foreach ($keys as $key) { $own = $booked->get($key) ?? collect(); $prices = $own->pluck('price_cents')->unique(); $rows[$key] = [ 'key' => $key, // Their price if they have exactly one, today's if they have // none — and null when their bookings disagree, because there // is no single honest figure to print. 'price_cents' => match (true) { $own->isEmpty() => $this->priceCents($key), $prices->count() === 1 => (int) $prices->first(), default => null, }, 'monthly_cents' => (int) $own->sum(fn ($addon) => $addon->monthlyCents()), 'booked' => $own->isNotEmpty(), // A granted module shows without a price too, the same rule as // a granted plan — "ein Plugin schenken" should not read as // "kostenlos" on the very page that sells it to everyone else. 'granted' => $own->isNotEmpty() && $own->every(fn ($addon) => $addon->isGranted()), 'quantity' => (int) $own->sum('quantity'), 'bookings' => $own->map(fn ($addon) => [ 'price_cents' => $addon->price_cents, 'quantity' => $addon->quantity, ])->values()->all(), ]; } return $rows; } }