Skip to content

Core Services ConfigOptionSetupService

Jordan edited this page Aug 17, 2026 · 4 revisions

ConfigOptionSetupService

Preserved Qoder snapshot. This deep-dive page is retained so the earlier Wiki work and its source trail are not lost. For the reconciled implementation, Architecture Overview is canonical; references below to retired controllers, listeners, services, or API shapes are historical.

**Referenced Files in This Document** - [ConfigOptionSetupService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/ConfigOptionSetupService.php) - [SliderConfigReaderService.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/SliderConfigReaderService.php) - [AuditsExtensionActions.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Services/Concerns/AuditsExtensionActions.php) - [PricingController.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Controllers/Api/PricingController.php) - [StoreReservationRequest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/Http/Requests/StoreReservationRequest.php) - [2025_01_01_000002_create_ptero_pricing_configs_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000002_create_ptero_pricing_configs_table.php) - [2025_01_01_000005_drop_ptero_pricing_configs_table.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/database/migrations/2025_01_01_000005_drop_ptero_pricing_configs_table.php) - [ConfigOptionSetupServiceTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Unit/ConfigOptionSetupServiceTest.php) - [SetupWizardValidationTest.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/Feature/SetupWizardValidationTest.php) - [LaravelTestCase.php](https://github.com/ObsidianNetwork/dynamic-pterodactyl/blob/6b7f83bda6f7c3fe014d52428b31af1638daa6cc/tests/LaravelTestCase.php)

Table of Contents

  1. Introduction
  2. Project Structure
  3. Core Components
  4. Architecture Overview
  5. Detailed Component Analysis
  6. Dependency Analysis
  7. Performance Considerations
  8. Troubleshooting Guide
  9. Conclusion
  10. Appendices

Introduction

This document explains the ConfigOptionSetupService, which creates and configures dynamic slider options for Paymenter products. It focuses on how the service builds slider metadata (ranges, steps, defaults), validates pricing configuration, integrates with Paymenter’s pricing engine by storing metadata consumed by core pricing methods, and manages optional location options. It also covers migration procedures that moved slider configuration from a dedicated table to native ConfigOption metadata, common configuration patterns, and troubleshooting invalid setups.

Project Structure

The extension is a nested Paymenter “Other” extension. Slider setup lives under Services, with supporting services for reading slider configurations and auditing actions. The service interacts with Paymenter’s core models (ConfigOption, Product) and uses database transactions to ensure atomicity when creating or updating multiple slider options.

graph TB
A["Admin Setup Wizard"] --> B["ConfigOptionSetupService"]
B --> C["Paymenter Core: ConfigOption"]
B --> D["Database Transaction"]
B --> E["AuditsExtensionActions"]
F["SliderConfigReaderService"] --> C
G["PricingController"] --> C
H["StoreReservationRequest"] --> C
Loading

Diagram sources

Section sources

Core Components

  • ConfigOptionSetupService: Creates/updates dynamic_slider ConfigOptions for memory, CPU, disk, and optionally Location; validates pricing metadata; audits setup runs.
  • SliderConfigReaderService: Reads configured sliders per product for API/frontend consumption.
  • AuditsExtensionActions: Safely logs setup actions even if audit logging fails.

Key responsibilities:

  • Build resource metadata with min/max/step/default values and display units.
  • Validate pricing model parameters via Paymenter’s rule.
  • Upsert existing slider options to avoid duplication.
  • Create location dropdown options as child entries under a parent “Location” option.
  • Provide helpers to detect existing slider options and count products with sliders.

Section sources

Architecture Overview

The service orchestrates slider creation within a single transaction. For each enabled resource type, it either updates an existing dynamic_slider option or creates a new one, attaching it to the product. Pricing metadata is validated before persisting. If locations are provided, a Location select option and its child options are created. After success, an audit entry is recorded.

sequenceDiagram
participant Admin as "Setup Wizard"
participant Svc as "ConfigOptionSetupService"
participant DB as "Database"
participant Core as "Paymenter Core : ConfigOption"
participant Audit as "AuditLogService"
Admin->>Svc : createDynamicSliderOptions(productId, config, locations)
Svc->>DB : beginTransaction()
loop For each resource (memory, cpu, disk)
Svc->>Core : findExistingOption(productId, resourceType)
alt exists
Svc->>Core : update(type=dynamic_slider, metadata)
else not exists
Svc->>Core : create(name, type=dynamic_slider, env_variable, sort, metadata)
Svc->>Core : attach to product
end
end
opt locations provided
Svc->>Core : create/update Location parent + children
end
Svc->>DB : commit()
Svc->>Audit : log setup_run with summary
Svc-->>Admin : created options map
Loading

Diagram sources

Detailed Component Analysis

Creating and configuring dynamic slider options

  • Entry point: createDynamicSliderOptions accepts productId, configuration array, and optional locations.
  • Iterates over memory, cpu, disk; skips any resource whose enable flag is false.
  • Builds metadata using defaults and user-provided values, then validates pricing metadata through Paymenter’s rule.
  • Upserts ConfigOption with type dynamic_slider and attaches to the product.
  • Optionally creates a Location select option and child options for each location.
  • Wraps all writes in a transaction; rolls back on any failure.
  • Audits successful runs with a summary of configured sliders.

Common configuration inputs:

  • Base price and pricing_model (linear, tiered, base_addon).
  • Per-resource min, max, step, default values.
  • Per-resource rate or tiers depending on model.
  • Optional locations list with id, short, long identifiers.

Output:

  • Map of resource types to created/updated ConfigOption instances, plus location if created.

Section sources

Validating configuration constraints

  • Pricing metadata validation is delegated to Paymenter’s DynamicSliderPricingRule during buildResourceMetadata.
  • Validation errors are collected and thrown as an InvalidArgumentException with concatenated messages.
  • Range and step normalization applies divisor scaling to align internal vs display units.

Validation rules enforced at setup time include:

  • Non-negative base_price and rates.
  • Tier ordering and final tier handling for tiered models.
  • Included amounts non-negative for base_addon model.

These rules mirror those used elsewhere in the system to ensure consistency between setup and runtime.

Section sources

Integrating with Paymenter’s pricing engine

  • The service does not calculate prices. It stores metadata consumed by Paymenter core pricing methods:
    • Plan::dynamicSliderBasePrice() for shared base charge per plan/product.
    • ConfigOption::calculateDynamicPriceDelta() for marginal charges per slider value.
  • SliderConfigReaderService exposes slider metadata for frontend/API consumption.
  • PricingController reads configured sliders and validates request values against slider ranges and steps.
  • StoreReservationRequest enforces slider range and step constraints at reservation submission.
flowchart TD
Start(["Setup Wizard"]) --> BuildMeta["Build metadata<br/>min/max/step/default/display"]
BuildMeta --> ValidatePricing["Validate pricing metadata"]
ValidatePricing --> Persist["Persist ConfigOption(s)<br/>attach to product"]
Persist --> ReadCfg["SliderConfigReaderService.getConfig()"]
ReadCfg --> Api["PricingController preview"]
Api --> Submit["StoreReservationRequest validate"]
Submit --> End(["Checkout/Reservation"])
Loading

Diagram sources

Section sources

Relationship between slider configurations and product definitions

  • Each dynamic_slider ConfigOption is linked to a product via the pivot table.
  • Existing options are identified by name or metadata.resource_type to support idempotent re-runs.
  • Sorting order ensures consistent UI presentation (memory first, then cpu, then disk).
  • Location options are hierarchical: a parent “Location” option with child options representing available locations.

Section sources

Migration procedures for updating existing slider setups

  • Historical ptero_pricing_configs table was removed; slider configuration now lives in ConfigOption metadata.
  • To migrate or reconfigure:
    • Run the Setup Wizard to create dynamic_slider ConfigOptions for the target product.
    • Re-run is safe due to upsert logic that updates existing options rather than duplicating them.
    • Use checkExistingOptions to inspect current slider presence and IDs.
    • Audit logs record setup runs for traceability.

Migration notes:

  • The drop migration removes the legacy table and documents data loss on rollback; reconfiguration should be done via the Setup Wizard after rollback.

Section sources

Common configuration patterns

  • Linear pricing: set base_price and per-resource rates (e.g., memory_rate, cpu_rate, disk_rate).
  • Tiered pricing: define tiers per resource with ascending up_to boundaries and a final tier with null upper bound.
  • Base + addon: specify included units and overage rate per resource.
  • Location selection: provide a list of locations to generate a dropdown under the Location option.

Examples validated by tests:

  • Full happy path creating memory, cpu, disk, and location sliders.
  • Rollback behavior when tiered pricing contains invalid tiers.
  • Audit logging of setup runs with correct payload.

Section sources

Troubleshooting invalid setups

Symptoms and causes:

  • Invalid tiered pricing (non-ascending or missing final open-ended tier) triggers an InvalidArgumentException during setup.
  • Mismatched slider values at checkout/reservation time fail validation if they violate min/max or step constraints.
  • Missing required slider fields in requests produce field-specific errors indicating required resources.

Resolution steps:

  • Fix pricing model parameters to satisfy validation rules.
  • Ensure slider values respect configured min, max, and step.
  • Confirm all required slider fields are present in the request for the product.

Recovery:

  • Re-run the Setup Wizard with corrected configuration; the service will update existing options atomically.
  • Inspect audit logs to confirm successful setup runs.

Section sources

Dependency Analysis

  • External dependencies:
    • Paymenter core models: ConfigOption, Product.
    • Paymenter core pricing rules: DynamicSliderPricingRule.
    • Database transactions for atomicity.
    • AuditLogService via AuditsExtensionActions.
  • Internal dependencies:
    • SliderConfigReaderService for reading slider metadata.
    • HTTP layer components rely on slider metadata for validation and pricing previews.
classDiagram
class ConfigOptionSetupService {
+createDynamicSliderOptions(productId, config, locations) array
+checkExistingOptions(productId) array
+getProductsWithSlidersCount() int
-createResourceOption(productId, resourceType, config) ConfigOption
-buildResourceMetadata(resourceType, config, defaults) array
-buildPricingMetadata(resourceType, pricingModel, config) array
-createLocationOption(productId, locations) ConfigOption
-findExistingOption(productId, name) ConfigOption?
}
class SliderConfigReaderService {
+getConfig(productId) array
-getDynamicSliderOptions(productId) Collection
}
class AuditsExtensionActions {
+safeAudit(action, entityType, entityId, newValues) void
}
ConfigOptionSetupService ..> AuditsExtensionActions : "uses trait"
ConfigOptionSetupService --> SliderConfigReaderService : "conceptual read path"
Loading

Diagram sources

Section sources

Performance Considerations

  • All slider creations/updates occur within a single database transaction to minimize partial writes and simplify rollback.
  • Option lookup uses direct joins and JSON extraction to efficiently identify existing sliders by name or resource_type.
  • Avoids redundant storage by leveraging native ConfigOption metadata instead of a separate pricing configs table.
  • Real-time availability decisions are outside this service; however, the design avoids caching Pterodactyl responses elsewhere in the extension.

[No sources needed since this section provides general guidance]

Troubleshooting Guide

  • Validation failures during setup:
    • Check pricing model parameters (base_price, rates, tiers, included units).
    • Ensure tiered pricing has ascending up_to values and a final tier with null upper bound.
    • Review error messages thrown by the pricing rule validator.
  • Checkout/reservation validation failures:
    • Verify slider values fall within configured min/max and adhere to step increments.
    • Ensure all required slider fields are present in the request.
  • Re-running setup:
    • Use the Setup Wizard again; the service will update existing sliders without duplication.
    • Confirm audit logs show a successful setup_run action.

Section sources

Conclusion

ConfigOptionSetupService centralizes the creation and validation of dynamic slider options for Paymenter products. It standardizes slider metadata, enforces pricing constraints via core rules, and integrates seamlessly with downstream components that read slider configuration and perform pricing previews and validations. The migration to native ConfigOption metadata simplifies the architecture and improves maintainability. Administrators can safely re-run setup to update configurations while preserving data integrity through transactions and robust validation.

[No sources needed since this section summarizes without analyzing specific files]

Appendices

Data flow overview for slider setup and usage

sequenceDiagram
participant Admin as "Admin"
participant Wizard as "Setup Wizard"
participant Service as "ConfigOptionSetupService"
participant Core as "ConfigOption"
participant Reader as "SliderConfigReaderService"
participant API as "PricingController"
participant Req as "StoreReservationRequest"
Admin->>Wizard : Configure sliders
Wizard->>Service : createDynamicSliderOptions(...)
Service->>Core : Upsert dynamic_slider options
Note over Service,Core : Metadata includes ranges, steps, pricing
API->>Reader : getConfig(productId)
Reader-->>API : Slider metadata
API-->>Admin : Pricing preview
Admin->>Req : Submit reservation with slider values
Req->>Req : Validate min/max/step
Req-->>Admin : Success or validation errors
Loading

Diagram sources

Clone this wiki locally