Tables


SchemaSpy Analysis of PerfectGym Next Enterprise Data Warehouse

Generated on Tue Oct 06 16:43 GMT 2026

XML Representation
Insertion Order Deletion Order
TABLES 101
VIEWS 0
COLUMNS 1218
Constraints 194

Database Properties

Database Type: Redshift - 8.0.2

Schema erp_v2

Real-Time PerfectGym Next Enterprise Data Warehouse

These are the docs for the new erp_v2 Data Warehouse schema that is served in near real time. To see the docs for the old schema, please refer to the legacy schema documentation.

This read-only schema provides selected business relevant data of PerfectGym Next in an unaggregated per-event grain in the form of multiple fact and dimension tables (star/galaxy/fact-constellation schema).

It’s targeted to use for analytical purposes in BI tools like PowerBI, time uncritical direct queries or as source for a custom pipeline, where data can be further enriched or prepared for fast access.

Authentication

  • Connection is restricted to a static IP address we need from you
  • A single USER & PASSWORD + HOST are provided
  • User has access to a single database of the same name

Connection

Please fill in the arguments, as provided by us.

Via odbc see aws documentation

Driver={Amazon Redshift (x64)};Server=<HOST>;Database=<USER>;UID=<USER>;PWD=<PASSWORD>;Port=5439

Via jdbc see aws documentation

jdbc:redshift://<HOST>:5439/<USER>

Updates

Tables are synced incrementally (inserts/updates/deletes) every few minutes

Non-Breaking Changes

  • New tables are announced in the Changelog on the same date they are added
  • New columns on existing tables are announced in the Changelog on the same date they are added

Breaking Changes

  • Tables are marked as deprecated in their documentation before they are deleted, to allow users to adapt beforehand
  • Columns are marked as deprecated in their documentation before they are deleted, to allow users to adapt beforehand
  • Deprecations are announced in the Changelog on the same date

For Data Extractions

Use data_landing_time as the incremental extraction watermark. It is the UTC timestamp assigned when a row is applied to the Data Warehouse.

Rows applied in the same table batch share one value. Table batches are applied sequentially across the schema, so values are non-decreasing in warehouse application order across tables. A full refresh also assigns a new landing timestamp to the refreshed rows. The value represents warehouse application time, not source-event time.

For independent table loads:

SELECT *
FROM perfectgym_next.your_table
WHERE data_landing_time > :last_watermark;

Advance the watermark only after the extraction and destination load succeed.

If referential consistency across multiple tables is required, use one common cutoff for the extraction run:

SELECT *
FROM perfectgym_next.your_table
WHERE data_landing_time > :last_watermark
  AND data_landing_time <= :cutoff;

Set :cutoff once for the run, optionally excluding recent data:

CURRENT_TIMESTAMP - INTERVAL '1 hour'

This allows related tables to be extracted consistently up to the same point. An overlap, such as subtracting one hour from :last_watermark, is an alternative defensive strategy for retries or partial loads; overlapping rows must be processed idempotently.

data_landing_time differs from last_updated: data_landing_time records warehouse application time and is the recommended extraction watermark, while last_updated records the upstream row update or processing timestamp and is not a reliable replacement.

data_landing_time does not retain deleted rows. Use periodic reconciliation or another deletion-handling strategy when deletes must be captured.

Anonymization / Access Level

Generally all data-privacy settings from the source System, like anonymizing checkins after a certain time period, are also applied on this Data Warehouse.
Additionally, there are 3 different types of access level we provide:

  • Owner: Client that owns the whole tenant in the source System. All data is provided.
  • Franchisee: Client that owns a subset of the tenants studios in the source System. Only fact data of selected studios is provided. Dimensional data of other studios can appear but is anonymized.
  • Franchise System: Client that owns the whole tenant in the source System but doesn’t operate studios directly. All fact data is provided but anonymized.

Your accounts access level will be defined during setup with your account manager.

Best Practices

Using Views

To ensure our ETL process can properly refresh the underlying tables, it is critical that you create views using the WITH NO SCHEMA BINDING option.
This type of view, also known as a late-binding view, does not create a dependency between the view and the underlying tables. This allows us to drop and recreate tables without affecting your views.

To create a late-binding view in Redshift, use the following syntax:

CREATE VIEW public.your_view_name
AS
SELECT
    column1,
    column2,
    ...
FROM
    perfectgym_next.dim_or_fact_table_name
WITH NO SCHEMA BINDING;

By adhering to this practice, you will prevent issues with our data refresh process and ensure the continuous availability of your data.

Contact

  • For feedback and issues, please contact your account manager

Tables

Table / View Children Parents Columns Type Comments
fct_trainer_class_appointments 0 7 10 Table
dim_inclusive_contingent 3 0 9 Table
dim_discount_campaign_discount_period 0 2 14 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.

fct_payment_run 0 5 15 Table
dim_employee 5 0 22 Table

Table contains all employees and their relevant information

dim_contract_voucher_definition 3 3 23 Table

A definition of a voucher that can be generated into voucher codes and applied to a contract to get a discount or credit. Vouchers can be used to grant discounts on contracts, waive fees, or provide credit.

fct_revenue_cash_based 0 6 29 Table
dim_purchased_contingent 4 4 23 Table
fct_idle_period 0 8 21 Table
dim_customer_dunning_configuration 0 1 14 Table

Dimension table exposing the dunning and billing stop configuration per customer. Each customer has at most one row. All four stop types are sourced from a single record configured manually by studio operators.

Stop types use a three-value LimitType pattern: - DISABLED — the stop is not active - UNLIMITED — the stop is permanently active (until_date is NULL) - LIMITED — the stop is active until until_date (inclusive)

To test whether a stop is currently active as of a reference date, apply: _limit_type = ‘UNLIMITED’ OR (_limit_type = ‘LIMITED’ AND _until_date >= <reference_date>)

Important: This table covers only manually configured stops set by studio operators. Dunning-engine-triggered collection stops (automatically set when a dunning level is reached) are stored in fct_dunning_step (collection_stop column). Combine both sources for a complete collection stop picture:

-- All customers with an active collection stop as of a reference date:
SELECT customer_id FROM dim_customer_dunning_configuration
WHERE collection_stop_limit_type = 'UNLIMITED'
   OR (collection_stop_limit_type = 'LIMITED' AND collection_stop_until_date >= '<ref_date>')
UNION
SELECT customer_id FROM fct_dunning_step
WHERE collection_stop IS TRUE
  AND dunning_date <= '<ref_date>'
  AND (withdrawn_date IS NULL OR withdrawn_date::date > '<ref_date>')

Use cases: - Active billable member counts: exclude customers where collection_stop_limit_type is UNLIMITED or (LIMITED and collection_stop_until_date >= reference_date) - Dunning portfolio analysis: identify customers where dunning is paused - Debt collection oversight: track customers blocked from external collection handover - Invoice audit: identify customers where invoice generation is suppressed

dim_customer_group_member_discount 0 1 7 Table

Defines the group discount schedule for a customer group. Each row is one step in the schedule: when the number of eligible group members reaches or exceeds min_member_count, that step’s discount_value becomes the group discount applied to all eligible members’ contracts. The highest matching step is always used — for example, with thresholds at 2 members (5%) and 4 members (10%), a group of 4 eligible members receives a 10% group discount. dim_customer_group.discount_value is then added on top of the matched step’s value. Join to dim_customer_group on customer_group_id to get the group type and discount_type (percentage or absolute) that applies to all steps.

dim_date 24 0 17 Table

Date dimension covering years 1900-2099

dim_studio_starter_package_adjustment 0 3 7 Table
fct_pos_saleposition 2 3 23 Table
dim_contract_term 1 0 5 Table

The term of the contract.

bridge_organization_unit_to_organization_unit_code 0 2 5 Table

Link organization unit (gym) to all its organization unit codes (tags).

fct_rate_term_payment_frequency_price_adjustment 0 3 15 Table
bridge_rate_bundle_to_company 0 2 7 Table

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

dim_device 2 0 7 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.

dim_trainer_appointment_status 1 0 4 Table
dim_rate_term_configuration 6 1 23 Table
dim_rate_localized 0 1 7 Table
fct_contract_voucher 1 4 24 Table
dim_campaign 3 0 8 Table

Campaign dimension

bridge_rate_bundle_to_payment_choice 0 1 5 Table

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

bridge_rate_to_rate_code 0 2 5 Table

Bridge table linking rates to their assigned rate codes (tags). A rate can have multiple codes and a code can be assigned to multiple rates.

fct_payment_instrument_status_history 0 4 13 Table
fct_rate_bundle_term_availability 0 2 7 Table
dim_cancellation_reason 3 0 7 Table

DEPRECATED. Use dim_contract_cancellation_reason instead.

A reason for contract cancellation

bridge_revenue_to_purchased_contingent 0 2 5 Table

Bridge table linking revenue transactions to purchased contingents (day passes, class packs, etc.). Handles many-to-many relationships where one sale position may create multiple contingents (e.g., bundle products, family packs). Use this table to analyze revenue by specific purchased contingent while avoiding grain issues and revenue duplication.

Example use cases: - “Show revenue generated from day pass sales with their utilization rates” - “Analyze which purchased contingents contribute most to revenue” - “Track revenue for bundle products that create multiple contingents”

dim_organization_unit_code 1 0 5 Table
dim_contract_voucher_rate_discount_period 0 5 15 Table

A period during which a discount is applied in the context of a contract voucher. Discounts are defined at a hierarchical granularity: rate → term configuration → payment frequency. A null at any level means the discount applies to all values at that level and below. For example, a null rate_id means the discount covers all rates; a set rate_id with a null rate_term_configuration_id means all term configurations of that rate.

dim_rate_bundle_term 3 3 7 Table
bridge_pos_saleposition_to_payment 0 1 5 Table

Bridge table linking each POS sale position to every payment actively settling it. A single sale position can be split across multiple payments (e.g. partial settlements or split payment methods), so this table has a many-to-many grain: one row per active sale-position-to-payment link. Use this table instead of the deprecated fct_pos_saleposition.internal_payment_id, which collapses splits down to a single link and loses this granularity.

dim_class 3 0 10 Table

A class that a customer can participate in, e.g. yoga, dance class, etc

dim_service 6 0 12 Table
dim_dunning_level 1 0 7 Table

Dimension table for dunning levels configured in the Magicline dunning engine. Each row represents one level in a dunning escalation ladder, as defined by a studio’s dunning configuration template.

Two level types exist (dunning_level_type): - DUNNING — a standard escalation step with configurable rules and actions. dunning_levels_order = 0 is the “No Dunning Level” baseline. - DEBT_COLLECTION — the terminal level representing handoff to an external debt collection agency. Has no configurable dunning rules.

Join from fct_dunning_step.dunning_level_id to obtain the level’s position in the escalation sequence and its type. Archived levels may appear on historical fct_dunning_step rows but are no longer assigned to new dunning steps.

fct_invoice 1 7 32 Table
bridge_service_to_organization_unit 0 2 6 Table

Access control mapping that defines which services are available at which gym locations. Services must be explicitly whitelisted for a gym before they can be booked or used there. This enables multi-location businesses to offer different service menus at different facilities (e.g., specialized classes only at flagship locations, or region-specific offerings).

dim_contract_property 1 0 10 Table

A set of basic contract properties, e.g whether or not contract is signed, via which service it was created, is contract disabled, which payment type was used for the contract, etc.

dim_rate 15 0 7 Table
dim_appointment 5 0 10 Table

The unique event of an appointment on the calendar with its properties.

dim_loss_reason 1 0 5 Table
dim_rate_term_payment_frequency 4 2 10 Table
bridge_discount_campaign_to_organization_unit 0 2 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.

fct_payment 0 4 21 Table
fct_class_appointment 0 6 15 Table
dim_payment_instrument 1 2 12 Table
fct_revenue_invoice_based 0 9 25 Table
fct_class_event 0 10 14 Table
dim_customer 31 0 33 Table

A customer is a person who signed up to a studio owned by you or your franchise.

dim_discount_campaign_localized 0 1 7 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_cash_register 1 1 10 Table

A physical or virtual point-of-sale register, used to process sales and issue receipts.

dim_daytime 0 0 7 Table

This table contains all times of a day from 00:00:00 to 23:59:59 with the granularity of one second.

dim_payment_run_property 1 0 7 Table
dim_idle_period_property 1 1 10 Table
dim_closing_hours 0 1 10 Table

Irregular or recurring closure times for an organization unit (gym). Defines exceptions to the regular opening hours, including one-time closures and yearly recurring closures (holidays, maintenance, etc.). YEARLY entries are expanded into specific datetime ranges based on creation/archival dates.

dim_lead_stage 2 0 8 Table
dim_revenue_group 3 0 5 Table
dim_contract_payment_frequency 1 0 8 Table

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

dim_contract_voucher_definition_localized 0 1 11 Table

Localized text for contract voucher definitions, one row per definition per locale. Includes the public-facing name and description shown to members, plus the staff-only internal description used to categorise a promotion or voucher (not visible to members).

dim_discount_campaign_scope 1 3 9 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_employee_access 0 2 7 Table
fct_lead_stage_history 0 4 13 Table
dim_rate_bundle 4 0 8 Table
dim_class_event_property 1 0 6 Table

The table contains simple properties of class events. This is a junk dimension that stores distinct combinations of event status, source, and booked_for_free flag.

dim_customer_code 1 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.

bridge_customer_group_to_customer 0 2 11 Table

Records each customer’s membership in a customer group, one row per membership event. Captures the validity period, the member’s individual discount eligibility, and — for Shared Contract type groups — the relationship role within the group. A customer may appear multiple times for the same group across non-overlapping periods. Join to dim_customer_group on customer_group_id to determine the group type, discount configuration, and member limits. Join to dim_customer on customer_id for customer attributes.

dim_organization_unit 40 0 16 Table
fct_dunning_step 0 2 18 Table
dim_cancellation_reason_localized 0 1 6 Table

The localized version of a cancellation reason, defining translated information of a cancellation reason per locale. One cancellation reason can have multiple localized versions.

fct_customer_studio_history 0 2 8 Table
dim_contract_cancellation_reason 1 1 9 Table

Contract cancellations with their reasons. Built from actual contract cancellations that occurred in the system. Includes information about how the cancellation was initiated, the type of cancellation, and the reason.

dim_company_code 1 0 6 Table

Company codes (tags) that can be assigned to companies for categorization and filtering purposes. Similar to customer codes but for partner companies.

dim_contract_cancellation_property 1 0 5 Table

DEPRECATED. Use dim_contract_cancellation_reason instead.

A set of basic properties of cancellation such as origin and if the cancellation was extraordinary. This is a junk dimension containing all distinct combinations of cancellation properties.

dim_opening_hours 0 1 8 Table
fct_customer_appointment 0 6 17 Table
dim_discount_campaign 6 0 8 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.

bridge_company_to_company_code 0 2 5 Table

Bridge table linking companies to their assigned company codes (tags). A company can have multiple codes and a code can be assigned to multiple companies.

bridge_customer_to_customer_code 0 2 5 Table

Link customer to all his customer codes.

fct_checkin 0 6 12 Table
bridge_discount_campaign_to_allowed_origin_type 0 1 5 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.

dim_company 8 0 36 Table

A ‘partner company’ that contracts can be related to for the Corporate Fitness program. Only includes companies that are currently whitelisted for the studios related to this DWH instance.

fct_contract_cancellation 0 10 14 Table
dim_product 7 1 18 Table
fct_lead_lifetime 0 4 19 Table
fct_trainer_appointment 0 4 18 Table
bridge_product_to_organization_unit 0 2 6 Table

Access control mapping that defines which products are available at which gym locations. Products can be made available at gyms through whitelisting (for MATERIAL, VOUCHER, and VIRTUAL types) or by being sold there (for dynamic ad-hoc products). This bridge table replaces the single organization_unit_id foreign key in dim_product to support the many-to-many relationship where products can be available at multiple locations.

dim_currency 8 0 6 Table

All available currencies

fct_contract 11 19 33 Table
fct_customer_referral 0 2 15 Table
dim_customer_custom_field 0 1 9 Table

Custom field values assigned to customers on lead or member level.

dim_customer_communication_consent 0 2 15 Table

Dimension table that tracks customer communication consent preferences across different message categories. This table combines customer-level and organization-level communication configurations, with customer-level settings taking priority over organization-level defaults.

fct_contract_price_history 0 3 19 Table
fct_service_usage 0 7 14 Table
dim_rate_code 1 0 8 Table
fct_revenue 1 8 17 Table
bridge_company_to_organization_unit 0 2 9 Table

Bridge table linking companies to organization units (gyms) they are whitelisted for. Represents access permissions for gyms on companies.

fct_contract_term_dates 0 3 8 Table
fct_rate_term_payment_frequency_price 0 4 18 Table
dim_customer_group 2 2 16 Table

One row per customer group configured in the system. Customer groups classify customers by membership arrangement and determine whether group discounts apply to their contracts. Groups belong to an organization unit and come in three types: Customer (a generic grouping for shared discounts), Premium (an elevated-tier group linking a referred customer to a referrer), and Shared Contract (a family plan in which all members share a single contract). The group type governs discount behaviour, member capacity limits, and contract linking throughout the model.