Tables


SchemaSpy Analysis of PerfectGym Next Enterprise Data Warehouse

Generated on Thu Oct 01 21:56 GMT 2026

XML Representation
Insertion Order Deletion Order
TABLES 37
VIEWS 0
COLUMNS 375
Constraints 0

Database Properties

Database Type: Redshift - 8.0.2

Schema preview

Preview PerfectGym Next Enterprise Data Warehouse

These are the docs for the Real-Time [preview] Data Warehouse schema. To see the docs for the current stable schema, please refer to the Real-Time [Current] schema docs.

This read-only schema provides a view to see and validate upcoming changes to the PerfectGym Next Data Warehouse schema before they are released to production. It contains new tables, columns or other changes that are not yet part of the stable schema.

Tables

Table / View Children Parents Columns Type Comments
dim_discount_campaign 7 0 7 Table

A discount campaign is a time-bound promotional discount configuration that studio administrators define and activate per studio. When active, it automatically applies a discount to contracts signed via the configured allowed sales channels (origin types). A campaign defines its validity window (active_from / active_to), how it interacts with discount vouchers (voucher_interoperability_mode), and which rate bundles / flat fees / modules it applies to.

preview__fct_checkin 0 3 12 Table

Each row represents a single gym visit by a customer. A visit is recorded at the gym the customer checked into (organization_unit_id). If a customer visits a gym other than their home gym, this is called a cross-club visit.

To identify cross-club visits: compare organization_unit_id (the visited gym) with customer_organization_unit_id (the customer’s home gym). If they differ, the visit is a cross-club visit.

Note: when a customer has privacy settings enabled, their customer_id is masked. If their data was removed due to the data retention period configured in the ERP system, both customer_id and customer_organization_unit_id may be NULL.

dim_discount_campaign_localized 0 1 6 Table

Localized public names and descriptions for discount campaigns, one row per campaign per locale. Used to display campaign information in the member’s preferred language (e.g. in the MySports app or online checkout). Follows the same pattern as dim_rate_localized and dim_cancellation_reason_localized.

dim_discount_campaign_discount_period 0 2 13 Table

Defines the discount amounts and effective periods for discount campaigns. Covers all three campaign scope types — main contract rate bundle (RATE_BUNDLE), flat-fee bundle (FLAT_FEE), and optional add-on module (MODULE) — in a single table.

Each row represents one discount tier (position) for one campaign scope entry. Multiple tiers per scope entry are possible (e.g. position 0: 100% off for 3 months, position 1: 50% off for the following 3 months).

Join to dim_discount_campaign_scope on discount_campaign_scope_id to determine which rate bundles or terms the discount applies to.

dim_rate_bundle_term 3 1 9 Table

Payment-term options for a rate bundle, such as monthly or term-based variants, including the payment frequency used to charge customers.

bridge_discount_campaign_to_allowed_origin_type 0 1 4 Table

Maps discount campaigns to their allowed sales channel origin types. One row per (campaign, origin_type) pair. Only origin types listed here are permitted to trigger the campaign discount when a contract is signed.

If a contract is created via a channel not present in this table for the active campaign, the campaign discount is not applied.

preview__dim_payment_instrument 1 0 12 Table

One row per stored payment method, resolving the customer whose account it belongs to. Standard instruments include cards, BACS/ACH/BECS direct debit, TWINT, and PayPal. The separate bank-account-backed direct-debit mechanism is represented as one payment_instrument_type = 'BANK_ACCOUNT_DIRECT_DEBIT' row per bank account, with lifecycle dates from the selected current mandate. This storage layer also underlies non-Swiss SEPA Direct Debit and Swiss LSV+/CH-DD processing; the warehouse label does not distinguish those downstream schemes. There is no flag identifying ‘the’ currently-used instrument when more than one row exists for a customer; consumers must interpret current_status and is_archived themselves. The status-history fact contains only standard payment-instrument events.

fct_rate_bundle_price 0 1 17 Table

Reporting-ready bundle prices with a default organization unit row, age bands (defaulting to 0-199), and optional term or month-day windows. final_price already applies organization unit and age adjustments.

dim_rate_term_payment_frequency_adjustment 0 0 5 Table

Price adjustments for payment frequencies, optionally scoped to a specific organization unit.

dim_date 5 0 16 Table

Date dimension covering years 1900-2099

dim_contract_payment_frequency 0 0 7 Table

Defines how often and how much is paid for an individual contract.

preview__fct_class_event 0 3 14 Table

Stores all customer events for class appointments such as booking or cancellations

dim_discount_campaign_scope 1 3 8 Table

Defines which rate bundles (and optionally which specific terms) are in scope for each discount campaign, across all three price component types: RATE_BUNDLE (main contract), FLAT_FEE (flat-fee bundle), and MODULE (optional add-on). One row per scope entry.

A NULL rate_bundle_id means the campaign applies to all rate bundles of that type. A NULL rate_bundle_term_id means the campaign applies to all terms of the rate bundle (only meaningful when rate_bundle_id is also set).

Use this table to answer: “Which rate bundles have a discount campaign set on them?” and “Does this campaign apply to all bundles or only specific ones?”

Join with dim_discount_campaign_discount_period on discount_campaign_scope_id to get the actual discount amounts for each scoped entry.

fct_rate_term_payment_frequency_price_adjustment 0 1 14 Table

Dynamic price adjustment rules configured on a rate term payment frequency. Each row represents one rule that modifies the membership fee under specific conditions (a calendar date, a contract extension, a recurring interval, or a limited period). Rules define the adjustment type and value relative to the base price of the payment frequency; they are not pre-resolved to a final charge.

bridge_rate_bundle_term_availability 0 1 5 Table

Bridge table listing which organization units can sell each rate bundle term, driven by the bundle whitelist and active bundle group configuration.

bridge_rate_bundle_to_company 0 1 7 Table

Bridge table linking rate bundles to partner companies for corporate deals, including any cooperation identifier used for that partnership.

bridge_rate_bundle_payment_choice 0 1 4 Table

Bridge table listing which payment choices are allowed when selling a rate bundle.

dim_rate_bundle 5 0 7 Table

Rate bundle (offer) header that defines which contract package can be sold and the contract timing rules tied to it.

preview__bridge_discount_campaign_to_organization_unit 0 1 5 Table

Maps studios (organization units) to their currently active discount campaign. One row per studio — at most one active discount campaign per studio is represented here. This is a point-in-time snapshot sourced from active_organization_unit_configuration, which holds at most one active discount campaign configuration per studio at any given time.

Important limitation: When a studio deactivates a discount campaign, the corresponding row is hard-deleted — no historical record is preserved.

dim_device 1 0 6 Table

A device connected to the system, which enables registering customers using certain areas (the whole gym, the gym sauna) or machines (eg a massage bed) of a gym.

preview__dim_service 0 0 12 Table

A general service (a class, a personal training, the replacement of a member card…), that can be provided to a customer. The service could be included in the customers contract(s), with a limiting contingent (eg when its a Sauna subscription) or be booked individually (eg when its a class).

dim_rate_term_payment_frequency_age_based_adjustment 0 0 7 Table

Age-based price adjustments for payment frequencies.

preview__dim_customer_code 0 0 8 Table

Dimension table containing customer codes (tags) used to categorize customers. Customer codes help organize and filter customers based on business-defined categories. Each customer code has a unique identifier and can be associated with multiple customers.

dim_rate_term_payment_frequency_month_days 0 0 5 Table

Payment frequency pricing that varies by specific days of the month.

dim_rate_term_payment_frequency 0 0 10 Table

Payment frequency options available for rate terms, including price, cadence, and calculation settings.

preview__fct_rate_term_payment_frequency_price 0 1 18 Table
bridge_discount_campaign_to_organization_unit 0 1 4 Table

Maps studios (organization units) to their currently registered discount campaigns. A studio can have multiple campaigns registered simultaneously, provided their active_from / active_to validity windows do not overlap (enforced at application level). Join with dim_discount_campaign and filter on the campaign’s validity window to determine which campaign is effective at a given point in time.

Important limitation: This is a point-in-time snapshot. When a studio deactivates a discount campaign, the corresponding row is hard-deleted — no historical record is preserved.

dim_rate_term_configuration 3 0 20 Table

Configuration of contract terms, extensions, cancellations and idle periods for a rate. This table details the rules governing the lifecycle of a contract associated with a specific rate, including initial duration, renewal policies, cancellation notice periods, and allowances for pausing the contract (idle periods).

preview__fct_payment_instrument_status_history 0 1 13 Table
dim_campaign 0 0 7 Table

Campaign dimension

dim_discount_campaign_rate_bundle_scope 0 3 9 Table

Unified dimension defining which rate bundles (and optionally which specific terms) are in scope for each discount campaign, across all three restriction types (RATE_BUNDLE, FLAT_FEE, MODULE). One row per restriction entry. The restriction_type column disambiguates which price component is scoped.

A NULL rate_bundle_id means the campaign applies to all rate bundles of that type. A NULL rate_bundle_term_id means the campaign applies to all terms of the rate bundle (only valid when rate_bundle_id is also set).

Use this table to answer: “Which rate bundles have a discount campaign set on them?” and “Does this campaign apply to all bundles or specific ones?”

Join with dim_discount_campaign_discount_period on restriction_id + restriction_type to get the actual discount amounts for each scoped restriction.

preview__dim_currency 2 0 6 Table

All available currencies

preview__dim_revenue_group 2 0 5 Table

A hierarchical categorization of revenues into a broad main_group and a finer grained sub_group.

preview__fct_lead_lifetime 0 0 19 Table
fct_revenue_invoice_based 0 2 23 Table

Invoice-based accrued revenue. Revenue is recorded when postings are emitted by the invoicing process. Only generated for studios whose configuration enables INVOICE-based accounting. Use this for invoice-led revenue reporting and reconciliation against fct_invoice. For the standard accrual view use fct_revenue; for actual cash inflows use fct_revenue_cash_based.

dim_rate_term_payment_frequency_term_to_price 0 0 6 Table

Price definitions for payment frequencies based on term length.

preview__fct_revenue_invoice_based 0 2 25 Table