Migration Strategy

Overview

The migration strategy covers three distinct scenarios: migrating existing clients from the Cash360 Membership module to the new platform, importing data from competing products, and onboarding entirely new clients. All three scenarios must work reliably with a 4-person team, which means automation is not optional -- it is the only way to scale onboarding beyond one client at a time.


Cash360 Data Migration

Entity Mapping

The following table defines the field-level mapping between Cash360 entities and the new Membership data model. This mapping drives the automated migration tool.

MbLogin to User

Cash360 Field Membership Field Transformation
id externalId (metadata) Store as reference for cross-linking
email email Direct copy
password passwordHash Direct copy (bcrypt, compatible)
status_cd statusCd Map: ACTIVE->ACTIVE, LOCKED->LOCKED
is_verified emailVerified Direct copy
created_date createdAt Direct copy
(new) roleCd Default: MEMBER (admins mapped separately from McUser)
(new) failedLoginAttempts Default: 0
(new) locale Default from entity settings

MbConsumer to Member

Cash360 Field Membership Field Transformation
id externalId (metadata) Store as reference
first_name firstName Direct copy
last_name lastName Direct copy
gender_cd gender Map: M->MALE, F->FEMALE, D->DIVERSE
birthday dateOfBirth Direct copy
email email Direct copy
phone phone Direct copy
street + house_number street Concatenate with space
zip zip Direct copy
city city Direct copy
country_cd countryCode Map to ISO 3166-1 alpha-2
emergency_contact_name emergencyContactName Direct copy
emergency_contact_phone emergencyContactPhone Direct copy
id_responsible_person idResponsiblePerson Map via member reference table
custom_attributes (JSONB) customAttributes (JSONB) Direct copy (compatible schema)
id_mc_entity idEntity Map via entity reference table

CsrConsumer (Backend Enrichment)

The CsrConsumer entity in Cash360 contains additional backend data that supplements the member profile:

Cash360 Field Membership Field Transformation
consumer_number memberNumber Direct copy
type_cd typeCd Map: PERSON->PERSON, ORGANIZATION->COMPANY
status_cd statusCd Map: ACTIVE->ACTIVE, INACTIVE->INACTIVE
archived statusCd If archived=true -> LEFT
custom_attributes customAttributes Merge with MbConsumer custom attributes

CsrContractPreDefined to MembershipTemplate

Cash360 Field Membership Field Transformation
name name Direct copy
description description Direct copy
price price Convert to DECIMAL(19,4)
billing_interval billingIntervalMonths Map: MONTHLY->1, QUARTERLY->3, ANNUAL->12
minimum_term minimumTermMonths Direct copy
notice_period noticePeriodMonths Direct copy
auto_renew autoRenew Direct copy
vat_rate vatRate Direct copy
status_cd statusCd Map: ACTIVE->ACTIVE, ARCHIVED->ARCHIVED
(new) typeCd Default: SUBSCRIPTION
(new) visibleOnHomepage Default: true (for active templates)

CsrContract2Product to Contract

Cash360 Field Membership Field Transformation
id_csr_consumer idMember Map via member reference table
id_pp_product_snapshot idMembershipTemplate Map via template reference table
start_date startDate Direct copy
end_date endDate Direct copy
status_cd statusCd Map: ACTIVE->ACTIVE, CANCELLED->CANCELLED
price price Convert to DECIMAL(19,4)
billing_interval billingIntervalMonths Same as template mapping
(calculated) nextBillingDate Calculate from start date + billing history

CsrBankAccount to BankAccount

Cash360 Field Membership Field Transformation
id_csr_consumer idMember Map via member reference table
iban iban Direct copy (validate checksum)
bic bic Direct copy
account_owner accountHolder Direct copy
mandate_reference mandateReference Direct copy
mandate_sign_date mandateSignDate Direct copy
is_default isDefault Direct copy
status_cd statusCd Map: ACTIVE->ACTIVE
(new) mandateTypeCd Default: CORE

PmTransaction to Transaction (Historical)

Cash360 Field Membership Field Transformation
id externalTransactionId Store Cash360 ID as external reference
id_csr_consumer idMember Map via member reference table
amount amount Convert to DECIMAL(19,4)
transaction_date createdAt Direct copy
status_cd statusCd Map: PROCESSED->PROCESSED, FAILED->FAILED
type_cd typeCd Map: CHARGE->MEMBERSHIP_FEE, REFUND->REFUND
description description Direct copy

McEntity to Entity

Cash360 Field Membership Field Transformation
name name Direct copy
id_parent_mc_entity idParentEntity Map via entity reference table
street address Direct copy
zip zip Direct copy
city city Direct copy
country_cd countryCode Map to ISO 3166-1 alpha-2
phone phone Direct copy
email email Direct copy
status_cd statusCd Map: ACTIVE->ACTIVE
(new) typeCd Inferred from context (CLUB, STUDIO)
(new) timezone Default: Europe/Berlin
(new) currencyCode Default: EUR

McUser to User (Admin Roles)

Cash360 Field Membership Field Transformation
email email Direct copy
password passwordHash Direct copy (bcrypt compatible)
first_name + last_name (user profile) Stored in separate admin profile
role_cd roleCd Map: ADMIN->ADMIN, SUPER_ADMIN->SYSTEM_ADMIN
id_mc_entity idEntity Direct copy
status_cd statusCd Map: ACTIVE->ACTIVE

Migration Tool Architecture

The migration tool is a standalone Spring Boot application that reads from Cash360's database (read-only) and writes to the Membership database:

flowchart TB subgraph "Migration Tool" CONFIG[Migration Config] READ[Cash360 Reader] TRANSFORM[Transformer] VALIDATE[Validator] WRITE[Membership Writer] REPORT[Report Generator] end subgraph "Sources" C360[(Cash360 DB - read only)] FILES[CSV/Excel Files] end subgraph "Target" MBR[(Membership DB)] end CONFIG --> READ C360 --> READ FILES --> READ READ --> TRANSFORM TRANSFORM --> VALIDATE VALIDATE --> WRITE WRITE --> MBR VALIDATE --> REPORT WRITE --> REPORT REPORT --> LOG[Migration Report]

Migration Execution Process

Step 1 -- Pre-migration analysis: - Connect to Cash360 database (read-only) - Count records per entity type - Identify data quality issues (missing required fields, orphaned records, encoding problems) - Generate pre-migration report

Step 2 -- Entity migration (order matters): 1. Entities (McEntity) -- must exist before anything else (tenant context) 2. Users (McUser) -- admin users, no member link yet 3. Members (MbConsumer + CsrConsumer merge) -- personal profiles 4. User-Member links (MbLogin -> User, link to Member) 5. Membership templates (CsrContractPreDefined) 6. Contracts (CsrContract2Product) 7. Bank accounts (CsrBankAccount) 8. Transaction history (PmTransaction)

Step 3 -- Post-migration validation: - Count check: source records vs. migrated records per type - Referential integrity: all FKs resolve - Sample validation: spot-check 10 random members with all linked data - Financial consistency: sum of transactions in Cash360 matches sum in Membership

Step 4 -- Migration report: - Total records migrated per type - Records skipped (with reasons) - Data quality issues encountered - Duration and performance metrics


Transaction History Migration

Transaction history is critical for continuity: members and admins need to see past payments even after migration.

Strategy

  • Active transactions (PENDING, SUBMITTED): Remain in Cash360 for processing. The new system creates a read-only reference. Once processed, the status update propagates to Membership via the normal webhook/polling mechanism.
  • Historical transactions (PROCESSED, FAILED, CANCELLED): Migrated as read-only records. The externalTransactionId field links back to Cash360 for audit purposes.
  • Ongoing transactions post-migration: New transactions are created in Membership and submitted to Cash360 via API. The transition date is recorded per entity.

Financial Reconciliation

Before and after migration, the following totals must match:

Metric Cash360 Membership Tolerance
Total members with active contracts COUNT COUNT 0
Total transaction amount (all time) SUM SUM 0.01 (rounding)
Open balance per member Per-member SUM Per-member SUM 0.01
Active SEPA mandates COUNT COUNT 0

Bank Account and SEPA Mandate Migration

SEPA mandates are legally binding documents. Migration must preserve:

  1. Mandate reference: Exact same reference number (mandate references are communicated to banks and cannot change)
  2. Mandate sign date: Original signature date (required in SEPA XML)
  3. Mandate type: CORE or B2B (determines processing rules)

After migration, the mandate is re-registered with Cash360 using the new Membership entity's context but the same reference number. This ensures continuity of direct debit collections without requiring members to sign new mandates.


Data Import Tooling

CSV Import System

For clubs that are not coming from Cash360 but from spreadsheets or competing products:

stateDiagram-v2 [*] --> Uploaded: Upload CSV Uploaded --> Detecting: Auto-detect format Detecting --> Mapping: Show detected columns Mapping --> TemplatesSaved: Save mapping template Mapping --> Validating: Validate data Validating --> Ready: Validation passed Validating --> Mapping: Fix errors Ready --> Executing: Select mode and run Executing --> Completed: All rows processed Executing --> PartiallyCompleted: Some rows failed Completed --> [*] PartiallyCompleted --> [*]: Download error report

Import Modes

Mode Behavior Use Case
New Only Insert records that do not exist (match by email/member number). Skip existing. Initial import
New + Update Insert new records and update existing ones with data from CSV. Periodic sync from federation
Update Only Only update existing records. Skip rows that do not match any existing record. Bulk data correction

Supported Source Formats

Format Detection Notes
CSV (comma) Automatic Most common
CSV (semicolon) Automatic Common in German Excel exports
TSV (tab) Automatic Federation data exports
UTF-8 Automatic Default assumption
ISO-8859-1 Automatic fallback Legacy German systems
Windows-1252 Automatic fallback Older Windows exports

Mapping Template Library

Pre-built mapping templates for common source systems:

Source System Template Fields Mapped
easyVerein import-easyverein.json Member name, address, email, phone, membership type
ClubDesk import-clubdesk.json Member name, address, membership, bank account
MEINVEREIN import-meinverein.json Member data, contribution, bank details
SportMember import-sportmember.json Member, team, payment
Generic (German) import-generic-de.json Vorname, Nachname, Strasse, PLZ, Ort, Email, IBAN
Generic (English) import-generic-en.json First Name, Last Name, Address, ZIP, City, Email, IBAN

Templates are JSON files defining column name patterns to entity field mappings, with optional value transformations (e.g., "m" -> "MALE", "w" -> "FEMALE" for German gender codes).


Phased Rollout Strategy

Phase 1 -- Controlled Soft Launch (Month 1-3)

Aspect Detail
Target < 10 hand-selected clients
Selection criteria Existing Cash360 customers, willing to provide feedback, < 500 members each
Onboarding White-glove: migration run by development team, 1:1 video call for setup
Pricing Free or heavily discounted during validation
Support Direct Slack/Teams channel with development team
Feedback Weekly check-in calls, in-app feedback widget
Exit criteria 3+ clients actively using system for > 30 days, NPS > 30, < 5 critical bugs

Phase 2 -- Market Entry (Month 4-6)

Aspect Detail
Target 10-50 clients
Channel Website with self-service registration, product landing page
Onboarding Self-service setup wizard + documentation, CSV import tool available
Pricing Published pricing tiers (Free/Starter/Professional)
Support Email support, knowledge base, community forum
Marketing Content marketing (blog posts, guides), SEO, social media
Exit criteria 20+ paying clients, positive unit economics on Starter tier

Phase 3 -- Growth (Month 7-12)

Aspect Detail
Target 50-200 clients
Channel Direct sales, partner network, trade shows (FIBO)
Onboarding Self-service + optional paid onboarding packages
Pricing Full pricing model including Enterprise tier
Support Tiered support (email, phone for Professional+, dedicated for Enterprise)
Marketing Google Ads, trade publications, referral program, case studies

Parallel Operation Period

During migration, both systems run simultaneously for a configurable overlap period (recommended: 30 days):

gantt title Migration Timeline per Client dateFormat YYYY-MM-DD section Preparation Pre-migration analysis :a1, 2026-03-01, 2d Data cleanup in Cash360 :a2, after a1, 3d section Migration Run migration tool :b1, after a2, 1d Validate migrated data :b2, after b1, 2d Fix issues :b3, after b2, 2d section Parallel Operation Both systems live :c1, after b3, 30d Staff training :c2, after b3, 5d Member communication :c3, after b3, 3d section Cutover Final sync :d1, after c1, 1d DNS switch :d2, after d1, 1d Cash360 set to read-only :d3, after d2, 1d section Post-Cutover Monitor :e1, after d3, 14d Decommission Cash360 access:e2, after e1, 1d

During parallel operation: - New member registrations happen in Membership only - Billing continues in Cash360 until cutover date - Both systems are accessible (old links redirect with notice) - An incremental sync job runs nightly to catch any new Cash360 data


Rollback Strategy

If migration fails or the new system has critical issues:

Scenario Rollback Action Data Loss
Pre-cutover issues Abandon migration, stay on Cash360 None (Cash360 was never modified)
Post-cutover, < 7 days Re-enable Cash360, sync new data back Minimal (only new registrations need manual transfer)
Post-cutover, > 7 days Forward-fix in Membership Not applicable (rollback too risky)

Key principle: Cash360 is never modified during migration. The migration tool only reads from Cash360. This means rollback to Cash360 is always possible by simply switching DNS back.


Team Constraints and Automation

With a 4-person team (PM, Frontend dev, Backend dev, QA), manual onboarding does not scale. Every migration step must be automated:

Task Manual Time Automated Time
Pre-migration analysis 4 hours 5 minutes (automated report)
Data migration 2 days 30 minutes (migration tool)
Post-migration validation 4 hours 15 minutes (automated checks)
Member communication 2 hours 5 minutes (template-based bulk email)
Staff training 2 hours Self-service (video + docs)

Target: Onboard a new client (from initial contact to fully operational) in < 1 week of calendar time with < 4 hours of team effort.