package payments import ( "context" "fmt" "github.com/google/uuid" ) // CanPurchase reports whether an account may open a purchase order on rail, combining the account's // per-account override with the rail's operational switch (PurchaseGate). It is the operational // availability layer only — the caller still enforces the security gates (trusted platform, the D36 // email anchor, the VK-iOS spend freeze, the min client version). On a block, reason is localized to // lang for the user; err is only a store failure. func (s *Service) CanPurchase(ctx context.Context, accountID uuid.UUID, rail, lang string) (ok bool, reason string, err error) { ov, err := s.store.purchaseOverride(ctx, accountID) if err != nil { return false, "", err } avail, err := s.store.railAvailability(ctx, rail) if err != nil { return false, "", err } ok, reason = PurchaseGate(ov, avail, lang) return ok, reason, nil } // RailStatuses returns every known rail's operational status for the admin editor, filling a rail // with no stored row with the fail-open enabled default so the editor always shows one row per rail. func (s *Service) RailStatuses(ctx context.Context) (map[string]RailAvailability, error) { stored, err := s.store.allRailStatus(ctx) if err != nil { return nil, err } out := make(map[string]RailAvailability, len(KnownRails)) for _, rail := range KnownRails { if a, ok := stored[rail]; ok { out[rail] = a } else { out[rail] = RailAvailability{Enabled: true} } } return out, nil } // SetRailStatus upserts a rail's operational status from the admin editor. It rejects an unknown rail // key so a typo cannot create a dead row. func (s *Service) SetRailStatus(ctx context.Context, rail string, a RailAvailability) error { if !isKnownRail(rail) { return fmt.Errorf("payments: unknown rail %q", rail) } return s.store.setRailStatus(ctx, rail, a, s.clock()) } // PurchaseOverrideFor returns an account's purchase override (OverrideDefault when none is set). func (s *Service) PurchaseOverrideFor(ctx context.Context, accountID uuid.UUID) (PurchaseOverride, error) { return s.store.purchaseOverride(ctx, accountID) } // SetPurchaseOverride sets or clears an account's purchase override (OverrideDefault deletes the row). func (s *Service) SetPurchaseOverride(ctx context.Context, accountID uuid.UUID, ov PurchaseOverride) error { return s.store.setPurchaseOverride(ctx, accountID, ov, s.clock()) }