Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Chapter 33: Tenant Lifecycle Management

Overview

This chapter defines the complete tenant lifecycle for the POS Platform, including state transitions, onboarding workflows, offboarding procedures, and billing integration.


Tenant States

State Machine Diagram

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                           TENANT STATE MACHINE                                       │
└─────────────────────────────────────────────────────────────────────────────────────┘

                              ┌───────────────┐
                              │    PROSPECT   │
                              │   (Pre-sale)  │
                              └───────┬───────┘
                                      │ Sales closes deal
                                      │ Contract signed
                                      ▼
                              ┌───────────────┐
                     ┌───────►│    TRIAL      │◄──────────┐
                     │        │  (14 days)    │           │
                     │        └───────┬───────┘           │
                     │                │                   │
                     │                │ Payment received  │ Trial extended
                     │                ▼                   │ (max 30 days)
                     │        ┌───────────────┐           │
                     │        │ PROVISIONING  │───────────┘
                     │        │ (Setup phase) │
                     │        └───────┬───────┘
                     │                │
                     │                │ Setup complete
                     │                │ Go-live approved
                     │                ▼
                     │        ┌───────────────┐
   Reactivate        │        │    ACTIVE     │
   (payment          │        │ (Production)  │◄─────────────────────────┐
    received)        │        └───────┬───────┘                          │
                     │                │                                  │
                     │    ┌───────────┼───────────┐                      │
                     │    │           │           │                      │
                     │    ▼           ▼           ▼                      │
                     │  Payment    Contract    Compliance                │
                     │  Failure    Violation   Issue                     │
                     │    │           │           │                      │
                     │    └───────────┼───────────┘                      │
                     │                │                                  │
                     │                ▼                                  │
                     │        ┌───────────────┐                          │
                     └────────│   SUSPENDED   │──────────────────────────┘
                              │ (Read-only)   │     Issue resolved
                              └───────┬───────┘
                                      │
                                      │ 30 days no resolution
                                      │ OR cancellation request
                                      ▼
                              ┌───────────────┐
                              │  CANCELLED    │
                              │ (Grace period)│
                              │   (30 days)   │
                              └───────┬───────┘
                                      │
                                      │ Grace period expired
                                      ▼
                              ┌───────────────┐
                              │   ARCHIVED    │
                              │(Data retained)│
                              │  (90 days)    │
                              └───────┬───────┘
                                      │
                                      │ Retention expired
                                      │ OR GDPR deletion
                                      ▼
                              ┌───────────────┐
                              │    PURGED     │
                              │(Permanently   │
                              │  deleted)     │
                              └───────────────┘


STATE DEFINITIONS:

┌─────────────────┬──────────────────────────────────────────────────────────────────┐
│ State           │ Description                                                      │
├─────────────────┼──────────────────────────────────────────────────────────────────┤
│ PROSPECT        │ Lead in sales pipeline, no system access                        │
│ TRIAL           │ Free trial period, limited features                             │
│ PROVISIONING    │ Database/schema being set up, training in progress              │
│ ACTIVE          │ Full production access, billing active                          │
│ SUSPENDED       │ Read-only access, no transactions, billing paused               │
│ CANCELLED       │ No access, data preserved for grace period                      │
│ ARCHIVED        │ No access, data compressed and stored offline                   │
│ PURGED          │ All data permanently deleted                                    │
└─────────────────┴──────────────────────────────────────────────────────────────────┘

State Transition Rules

// File: /src/POS.Core/Tenants/TenantStateMachine.cs

public class TenantStateMachine
{
    private static readonly Dictionary<TenantState, TenantState[]> AllowedTransitions = new()
    {
        [TenantState.Prospect] = new[] { TenantState.Trial },
        [TenantState.Trial] = new[] { TenantState.Provisioning, TenantState.Cancelled },
        [TenantState.Provisioning] = new[] { TenantState.Active, TenantState.Trial },
        [TenantState.Active] = new[] { TenantState.Suspended, TenantState.Cancelled },
        [TenantState.Suspended] = new[] { TenantState.Active, TenantState.Cancelled },
        [TenantState.Cancelled] = new[] { TenantState.Archived, TenantState.Active },
        [TenantState.Archived] = new[] { TenantState.Purged },
        [TenantState.Purged] = Array.Empty<TenantState>()
    };

    public bool CanTransition(TenantState from, TenantState to)
    {
        return AllowedTransitions.TryGetValue(from, out var allowed)
            && allowed.Contains(to);
    }

    public void Transition(Tenant tenant, TenantState newState, string reason)
    {
        if (!CanTransition(tenant.State, newState))
        {
            throw new InvalidStateTransitionException(
                $"Cannot transition from {tenant.State} to {newState}");
        }

        var previousState = tenant.State;
        tenant.State = newState;
        tenant.StateChangedAt = DateTime.UtcNow;
        tenant.StateChangeReason = reason;

        // Emit domain event
        tenant.AddDomainEvent(new TenantStateChangedEvent(
            tenant.Id,
            previousState,
            newState,
            reason
        ));
    }
}

public enum TenantState
{
    Prospect,
    Trial,
    Provisioning,
    Active,
    Suspended,
    Cancelled,
    Archived,
    Purged
}

Onboarding Workflow

Complete Onboarding Process

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                           TENANT ONBOARDING WORKFLOW                                 │
└─────────────────────────────────────────────────────────────────────────────────────┘

PHASE 1: SALES HANDOFF (Day 0)
┌─────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                     │
│  Sales Team                        CRM System                   Onboarding Queue   │
│      │                                 │                              │            │
│      │ 1. Win opportunity              │                              │            │
│      ├────────────────────────────────►│                              │            │
│      │                                 │ 2. Create tenant record      │            │
│      │                                 ├─────────────────────────────►│            │
│      │ 3. Assign onboarding manager    │                              │            │
│      │◄────────────────────────────────┤                              │            │
│      │                                 │                              │            │
│  Deliverables:                                                                      │
│  □ Signed contract                                                                  │
│  □ Payment method on file                                                           │
│  □ Business requirements document                                                   │
│  □ Primary contact information                                                      │
│  □ Assigned onboarding manager                                                      │
│                                                                                     │
└─────────────────────────────────────────────────────────────────────────────────────┘
                                         │
                                         ▼
PHASE 2: DATABASE PROVISIONING (Day 1)
┌─────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                     │
│  Automated System                                                                   │
│      │                                                                              │
│      │ 1. Create tenant schema                                                      │
│      │    CREATE SCHEMA tenant_xyz;                                                │
│      │                                                                              │
│      │ 2. Run migrations                                                            │
│      │    Apply all schema migrations                                              │
│      │                                                                              │
│      │ 3. Seed reference data                                                       │
│      │    - Payment methods                                                         │
│      │    - Tax categories                                                          │
│      │    - Default settings                                                        │
│      │                                                                              │
│      │ 4. Create admin user                                                         │
│      │    - Generate temporary password                                             │
│      │    - Send welcome email                                                      │
│      │                                                                              │
│  Automated Checks:                                                                  │
│  □ Schema created successfully                                                      │
│  □ All tables exist                                                                 │
│  □ Admin user can login                                                             │
│  □ API key generated                                                                │
│                                                                                     │
└─────────────────────────────────────────────────────────────────────────────────────┘
                                         │
                                         ▼
PHASE 3: CONFIGURATION SETUP (Days 2-3)
┌─────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                     │
│  Onboarding Manager + Customer                                                      │
│      │                                                                              │
│      │ 1. Company profile setup                                                     │
│      │    - Business name, address, logo                                           │
│      │    - Tax settings (rates, exemptions)                                       │
│      │    - Currency and locale                                                    │
│      │                                                                              │
│      │ 2. Location configuration                                                    │
│      │    - Add store locations                                                     │
│      │    - Assign location codes                                                   │
│      │    - Set business hours                                                      │
│      │                                                                              │
│      │ 3. Payment processor setup                                                   │
│      │    - Connect Stripe account                                                  │
│      │    - Configure payment methods                                               │
│      │    - Test transactions                                                       │
│      │                                                                              │
│      │ 4. User provisioning                                                         │
│      │    - Create user accounts                                                    │
│      │    - Assign roles (Manager, Cashier, etc.)                                  │
│      │    - Configure permissions                                                   │
│      │                                                                              │
│      │ 5. Hardware setup (if applicable)                                            │
│      │    - Register POS terminals                                                  │
│      │    - Connect receipt printers                                                │
│      │    - Pair barcode scanners                                                   │
│      │                                                                              │
│  Configuration Checklist:                                                           │
│  □ Company profile complete                                                         │
│  □ At least 1 location configured                                                   │
│  □ Payment processor connected and tested                                           │
│  □ At least 1 manager user created                                                  │
│  □ Receipt template customized                                                      │
│                                                                                     │
└─────────────────────────────────────────────────────────────────────────────────────┘
                                         │
                                         ▼
PHASE 4: DATA MIGRATION (Days 3-7)
┌─────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                     │
│  Migration Team + Customer                                                          │
│      │                                                                              │
│      │ 1. Data assessment                                                           │
│      │    - Review existing data sources                                            │
│      │    - Identify data quality issues                                            │
│      │    - Plan field mappings                                                     │
│      │                                                                              │
│      │ 2. Product catalog import                                                    │
│      │    - Import products from CSV/API                                            │
│      │    - Map categories                                                          │
│      │    - Validate pricing                                                        │
│      │                                                                              │
│      │ 3. Customer data import                                                      │
│      │    - Import customer records                                                 │
│      │    - Deduplicate entries                                                     │
│      │    - Validate contact info                                                   │
│      │                                                                              │
│      │ 4. Inventory import                                                          │
│      │    - Import current stock levels                                             │
│      │    - Map to locations                                                        │
│      │    - Validate quantities                                                     │
│      │                                                                              │
│      │ 5. Historical data (optional)                                                │
│      │    - Import transaction history                                              │
│      │    - Import for reporting only                                               │
│      │                                                                              │
│  Migration Validation:                                                              │
│  □ Product count matches source                                                     │
│  □ Customer count matches (after dedup)                                             │
│  □ Inventory totals reconcile                                                       │
│  □ Sample transactions verified                                                     │
│                                                                                     │
└─────────────────────────────────────────────────────────────────────────────────────┘
                                         │
                                         ▼
PHASE 5: TRAINING (Days 5-10)
┌─────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                     │
│  Training Team + Customer Staff                                                     │
│      │                                                                              │
│      │ 1. Administrator training (2 hours)                                          │
│      │    - System configuration                                                    │
│      │    - User management                                                         │
│      │    - Reports and analytics                                                   │
│      │                                                                              │
│      │ 2. Manager training (2 hours)                                                │
│      │    - Day-to-day operations                                                   │
│      │    - Inventory management                                                    │
│      │    - Staff management                                                        │
│      │                                                                              │
│      │ 3. Cashier training (1 hour)                                                 │
│      │    - Transaction processing                                                  │
│      │    - Customer lookup                                                         │
│      │    - Returns and exchanges                                                   │
│      │                                                                              │
│      │ 4. Hands-on practice                                                         │
│      │    - Practice transactions                                                   │
│      │    - Test edge cases                                                         │
│      │    - Q&A session                                                             │
│      │                                                                              │
│  Training Completion:                                                               │
│  □ Admin training complete                                                          │
│  □ Manager training complete                                                        │
│  □ All cashiers trained                                                             │
│  □ Practice transactions successful                                                 │
│  □ Training materials provided                                                      │
│                                                                                     │
└─────────────────────────────────────────────────────────────────────────────────────┘
                                         │
                                         ▼
PHASE 6: GO-LIVE (Day 10-14)
┌─────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                     │
│  All Teams                                                                          │
│      │                                                                              │
│      │ 1. Pre-go-live checklist                                                     │
│      │    - All configuration verified                                              │
│      │    - Data migration validated                                                │
│      │    - Staff trained and ready                                                 │
│      │    - Backup of old system                                                    │
│      │                                                                              │
│      │ 2. Go-live execution                                                         │
│      │    - Cutover at scheduled time                                               │
│      │    - First transaction verified                                              │
│      │    - Monitor for issues                                                      │
│      │                                                                              │
│      │ 3. Hypercare period (Days 1-7)                                              │
│      │    - On-call support                                                         │
│      │    - Daily check-ins                                                         │
│      │    - Rapid issue resolution                                                  │
│      │                                                                              │
│      │ 4. Transition to BAU                                                         │
│      │    - Hand off to support team                                                │
│      │    - Schedule first review                                                   │
│      │    - Close onboarding project                                                │
│      │                                                                              │
│  Go-Live Criteria:                                                                  │
│  □ Sign-off from customer                                                           │
│  □ First successful transaction                                                     │
│  □ End-of-day close successful                                                      │
│  □ Support handoff complete                                                         │
│                                                                                     │
└─────────────────────────────────────────────────────────────────────────────────────┘

Automated Provisioning Script

#!/bin/bash
# File: /pos-platform/scripts/tenants/provision-tenant.sh
# Automated tenant provisioning

set -e

TENANT_ID=$1
TENANT_NAME=$2
ADMIN_EMAIL=$3
PLAN_TYPE=${4:-standard}

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] PROVISION: $1"
}

#=============================================
# STEP 1: CREATE TENANT SCHEMA
#=============================================
create_schema() {
    log "Creating schema for tenant: $TENANT_ID"

    docker exec postgres-primary psql -U pos_admin -d pos_db << EOF
-- Create tenant schema
CREATE SCHEMA IF NOT EXISTS "tenant_${TENANT_ID}";

-- Set search path
SET search_path TO "tenant_${TENANT_ID}";

-- Run migrations (tables created here)
\i /migrations/001_create_tables.sql
\i /migrations/002_create_indexes.sql
\i /migrations/003_seed_reference_data.sql

-- Grant permissions
GRANT ALL PRIVILEGES ON SCHEMA "tenant_${TENANT_ID}" TO pos_app;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA "tenant_${TENANT_ID}" TO pos_app;
EOF

    log "Schema created"
}

#=============================================
# STEP 2: SEED TENANT DATA
#=============================================
seed_data() {
    log "Seeding tenant data..."

    docker exec postgres-primary psql -U pos_admin -d pos_db << EOF
SET search_path TO "tenant_${TENANT_ID}";

-- Insert tenant record in shared schema
INSERT INTO shared.tenants (id, name, schema_name, state, plan_type, created_at)
VALUES ('${TENANT_ID}', '${TENANT_NAME}', 'tenant_${TENANT_ID}', 'provisioning', '${PLAN_TYPE}', NOW());

-- Insert default settings
INSERT INTO settings (key, value) VALUES
    ('company_name', '${TENANT_NAME}'),
    ('timezone', 'America/New_York'),
    ('currency', 'USD'),
    ('tax_rate', '0.0825'),
    ('receipt_footer', 'Thank you for your business!');

-- Insert default payment methods
INSERT INTO payment_methods (code, name, is_active) VALUES
    ('CASH', 'Cash', true),
    ('CARD', 'Credit/Debit Card', true),
    ('GIFT', 'Gift Card', true);

-- Insert default roles
INSERT INTO roles (name, permissions) VALUES
    ('admin', '["*"]'),
    ('manager', '["transactions", "inventory", "reports", "customers"]'),
    ('cashier', '["transactions", "customers"]');
EOF

    log "Data seeded"
}

#=============================================
# STEP 3: CREATE ADMIN USER
#=============================================
create_admin() {
    log "Creating admin user..."

    # Generate temporary password
    TEMP_PASSWORD=$(openssl rand -base64 12)
    PASSWORD_HASH=$(echo -n "$TEMP_PASSWORD" | argon2 $(openssl rand -base64 16) -id -t 3 -m 16 -p 4 -l 32 -e)

    docker exec postgres-primary psql -U pos_admin -d pos_db << EOF
SET search_path TO "tenant_${TENANT_ID}";

INSERT INTO users (email, password_hash, role, must_change_password, created_at)
VALUES ('${ADMIN_EMAIL}', '${PASSWORD_HASH}', 'admin', true, NOW());
EOF

    # Send welcome email
    send_welcome_email "$ADMIN_EMAIL" "$TEMP_PASSWORD"

    log "Admin user created"
}

#=============================================
# STEP 4: GENERATE API KEY
#=============================================
generate_api_key() {
    log "Generating API key..."

    API_KEY=$(openssl rand -hex 32)
    API_KEY_HASH=$(echo -n "$API_KEY" | sha256sum | cut -d' ' -f1)

    docker exec postgres-primary psql -U pos_admin -d pos_db << EOF
INSERT INTO shared.api_keys (tenant_id, key_hash, name, created_at)
VALUES ('${TENANT_ID}', '${API_KEY_HASH}', 'Primary API Key', NOW());
EOF

    # Store API key securely (send to customer)
    echo "$API_KEY" > "/secure/keys/${TENANT_ID}.key"
    chmod 400 "/secure/keys/${TENANT_ID}.key"

    log "API key generated"
}

#=============================================
# STEP 5: UPDATE STATE
#=============================================
update_state() {
    log "Updating tenant state to 'active'..."

    docker exec postgres-primary psql -U pos_admin -d pos_db << EOF
UPDATE shared.tenants
SET state = 'active', activated_at = NOW()
WHERE id = '${TENANT_ID}';
EOF

    log "Tenant activated"
}

#=============================================
# HELPER: SEND WELCOME EMAIL
#=============================================
send_welcome_email() {
    EMAIL=$1
    PASSWORD=$2

    curl -X POST "$EMAIL_API_URL/send" \
        -H "Authorization: Bearer $EMAIL_API_KEY" \
        -H "Content-Type: application/json" \
        -d "{
            \"to\": \"$EMAIL\",
            \"template\": \"welcome\",
            \"data\": {
                \"tenant_name\": \"$TENANT_NAME\",
                \"login_url\": \"https://pos.example.com/login\",
                \"temp_password\": \"$PASSWORD\"
            }
        }"
}

#=============================================
# MAIN
#=============================================
main() {
    if [ -z "$TENANT_ID" ] || [ -z "$TENANT_NAME" ] || [ -z "$ADMIN_EMAIL" ]; then
        echo "Usage: $0 <tenant_id> <tenant_name> <admin_email> [plan_type]"
        exit 1
    fi

    log "=========================================="
    log "Provisioning tenant: $TENANT_NAME"
    log "=========================================="

    create_schema
    seed_data
    create_admin
    generate_api_key
    update_state

    log "=========================================="
    log "Provisioning complete!"
    log "=========================================="
}

main "$@"

Offboarding Workflow

Offboarding Process

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                           TENANT OFFBOARDING WORKFLOW                                │
└─────────────────────────────────────────────────────────────────────────────────────┘

STEP 1: CANCELLATION REQUEST (Day 0)
┌─────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                     │
│  □ Cancellation request received (email/portal/phone)                               │
│  □ Reason documented                                                                │
│  □ Contract terms reviewed (notice period, penalties)                               │
│  □ Retention offer made (if applicable)                                             │
│  □ Final decision confirmed in writing                                              │
│  □ Cancellation effective date set                                                  │
│                                                                                     │
└─────────────────────────────────────────────────────────────────────────────────────┘
                                         │
                                         ▼
STEP 2: DATA EXPORT (Days 1-7)
┌─────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                     │
│  □ Customer requests data export (GDPR right to portability)                        │
│  □ Generate export package:                                                         │
│      - Transactions (CSV)                                                           │
│      - Products (CSV)                                                               │
│      - Customers (CSV)                                                              │
│      - Inventory history (CSV)                                                      │
│      - Reports (PDF)                                                                │
│  □ Export package delivered securely                                                │
│  □ Customer confirms receipt                                                        │
│                                                                                     │
└─────────────────────────────────────────────────────────────────────────────────────┘
                                         │
                                         ▼
STEP 3: ACCESS TERMINATION (Effective Date)
┌─────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                     │
│  □ Tenant state set to CANCELLED                                                    │
│  □ All user sessions terminated                                                     │
│  □ API keys revoked                                                                 │
│  □ Webhook endpoints removed                                                        │
│  □ Payment processor disconnected                                                   │
│  □ Customer notified of access termination                                          │
│                                                                                     │
└─────────────────────────────────────────────────────────────────────────────────────┘
                                         │
                                         ▼
STEP 4: GRACE PERIOD (30 Days)
┌─────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                     │
│  During this period:                                                                │
│  □ Data remains intact (no modifications)                                           │
│  □ Customer can request reactivation                                                │
│  □ Additional data exports available on request                                     │
│  □ Billing stopped                                                                  │
│                                                                                     │
│  At end of grace period:                                                            │
│  □ Final notification sent                                                          │
│  □ State changed to ARCHIVED                                                        │
│                                                                                     │
└─────────────────────────────────────────────────────────────────────────────────────┘
                                         │
                                         ▼
STEP 5: DATA ARCHIVAL (Day 30)
┌─────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                     │
│  □ Create final backup                                                              │
│  □ Encrypt backup with archival key                                                 │
│  □ Move to cold storage (Glacier)                                                   │
│  □ Drop active schema                                                               │
│  □ Release database resources                                                       │
│  □ Archive tenant record                                                            │
│                                                                                     │
└─────────────────────────────────────────────────────────────────────────────────────┘
                                         │
                                         ▼
STEP 6: DATA RETENTION (90 Days)
┌─────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                     │
│  Retained data:                                                                     │
│  □ Transaction records (legal requirement)                                          │
│  □ Audit logs                                                                       │
│  □ Financial reports                                                                │
│                                                                                     │
│  Purpose:                                                                           │
│  □ Tax/audit compliance                                                             │
│  □ Legal disputes                                                                   │
│  □ Fraud investigation                                                              │
│                                                                                     │
└─────────────────────────────────────────────────────────────────────────────────────┘
                                         │
                                         ▼
STEP 7: GDPR DELETION (On Request or Day 120)
┌─────────────────────────────────────────────────────────────────────────────────────┐
│                                                                                     │
│  GDPR "Right to be Forgotten" Process:                                             │
│                                                                                     │
│  □ Deletion request received and verified                                           │
│  □ Legal hold check (no active litigation)                                          │
│  □ Tax record retention verified (if applicable, retain 7 years)                    │
│  □ Personal data identified:                                                        │
│      - Customer PII                                                                 │
│      - Employee data                                                                │
│      - Contact information                                                          │
│  □ Pseudonymization applied where deletion not possible                             │
│  □ Backup copies identified and purged                                              │
│  □ Deletion certificate generated                                                   │
│  □ Customer notified of completion                                                  │
│                                                                                     │
└─────────────────────────────────────────────────────────────────────────────────────┘

Data Export Script

#!/bin/bash
# File: /pos-platform/scripts/tenants/export-tenant-data.sh
# Export all tenant data for offboarding

set -e

TENANT_ID=$1
OUTPUT_DIR="/exports/${TENANT_ID}"

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] EXPORT: $1"
}

mkdir -p "$OUTPUT_DIR"

#=============================================
# EXPORT TRANSACTIONS
#=============================================
export_transactions() {
    log "Exporting transactions..."

    docker exec postgres-primary psql -U pos_admin -d pos_db -c "
        COPY (
            SELECT
                t.id,
                t.transaction_number,
                t.created_at,
                t.total,
                t.tax,
                t.payment_method,
                t.status,
                c.email as customer_email,
                c.name as customer_name
            FROM tenant_${TENANT_ID}.transactions t
            LEFT JOIN tenant_${TENANT_ID}.customers c ON t.customer_id = c.id
            ORDER BY t.created_at
        ) TO STDOUT WITH CSV HEADER
    " > "${OUTPUT_DIR}/transactions.csv"

    log "Exported $(wc -l < ${OUTPUT_DIR}/transactions.csv) transactions"
}

#=============================================
# EXPORT PRODUCTS
#=============================================
export_products() {
    log "Exporting products..."

    docker exec postgres-primary psql -U pos_admin -d pos_db -c "
        COPY (
            SELECT
                id,
                sku,
                name,
                description,
                price,
                cost,
                category,
                barcode,
                is_active,
                created_at
            FROM tenant_${TENANT_ID}.products
            ORDER BY name
        ) TO STDOUT WITH CSV HEADER
    " > "${OUTPUT_DIR}/products.csv"

    log "Exported $(wc -l < ${OUTPUT_DIR}/products.csv) products"
}

#=============================================
# EXPORT CUSTOMERS
#=============================================
export_customers() {
    log "Exporting customers..."

    docker exec postgres-primary psql -U pos_admin -d pos_db -c "
        COPY (
            SELECT
                id,
                email,
                name,
                phone,
                address,
                city,
                state,
                postal_code,
                total_purchases,
                last_purchase_at,
                created_at
            FROM tenant_${TENANT_ID}.customers
            ORDER BY name
        ) TO STDOUT WITH CSV HEADER
    " > "${OUTPUT_DIR}/customers.csv"

    log "Exported $(wc -l < ${OUTPUT_DIR}/customers.csv) customers"
}

#=============================================
# EXPORT INVENTORY
#=============================================
export_inventory() {
    log "Exporting inventory..."

    docker exec postgres-primary psql -U pos_admin -d pos_db -c "
        COPY (
            SELECT
                i.product_id,
                p.sku,
                p.name as product_name,
                l.name as location_name,
                i.quantity,
                i.last_updated
            FROM tenant_${TENANT_ID}.inventory i
            JOIN tenant_${TENANT_ID}.products p ON i.product_id = p.id
            JOIN tenant_${TENANT_ID}.locations l ON i.location_id = l.id
            ORDER BY p.name, l.name
        ) TO STDOUT WITH CSV HEADER
    " > "${OUTPUT_DIR}/inventory.csv"

    log "Exported inventory data"
}

#=============================================
# CREATE EXPORT PACKAGE
#=============================================
create_package() {
    log "Creating export package..."

    # Create manifest
    cat > "${OUTPUT_DIR}/manifest.json" << EOF
{
    "tenant_id": "${TENANT_ID}",
    "export_date": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
    "files": [
        {"name": "transactions.csv", "description": "All transactions"},
        {"name": "products.csv", "description": "Product catalog"},
        {"name": "customers.csv", "description": "Customer records"},
        {"name": "inventory.csv", "description": "Current inventory levels"}
    ]
}
EOF

    # Create encrypted zip
    zip -r -e "${OUTPUT_DIR}.zip" "$OUTPUT_DIR" -P "$EXPORT_PASSWORD"

    # Generate download link
    DOWNLOAD_URL=$(aws s3 presign "s3://pos-exports/${TENANT_ID}.zip" --expires-in 604800)

    log "Export package created"
    log "Download URL (valid 7 days): $DOWNLOAD_URL"
}

#=============================================
# MAIN
#=============================================
main() {
    if [ -z "$TENANT_ID" ]; then
        echo "Usage: $0 <tenant_id>"
        exit 1
    fi

    log "=========================================="
    log "Exporting data for tenant: $TENANT_ID"
    log "=========================================="

    export_transactions
    export_products
    export_customers
    export_inventory
    create_package

    log "=========================================="
    log "Export complete!"
    log "=========================================="
}

main "$@"

Billing Integration

Billing Events

// File: /src/POS.Core/Billing/BillingEvents.cs

public record TenantSubscriptionCreated(
    string TenantId,
    string PlanId,
    string StripeSubscriptionId,
    DateTime StartDate,
    decimal MonthlyPrice
);

public record TenantPaymentReceived(
    string TenantId,
    string StripePaymentId,
    decimal Amount,
    DateTime PaidAt
);

public record TenantPaymentFailed(
    string TenantId,
    string StripePaymentId,
    string FailureReason,
    int AttemptCount,
    DateTime NextRetryAt
);

public record TenantPlanChanged(
    string TenantId,
    string OldPlanId,
    string NewPlanId,
    DateTime EffectiveDate,
    bool IsUpgrade
);

public record TenantSubscriptionCancelled(
    string TenantId,
    string Reason,
    DateTime CancellationDate,
    DateTime EffectiveEndDate
);

Stripe Webhook Handler

// File: /src/POS.Api/Webhooks/StripeWebhookController.cs

[ApiController]
[Route("webhooks/stripe")]
public class StripeWebhookController : ControllerBase
{
    private readonly ITenantBillingService _billingService;
    private readonly ILogger<StripeWebhookController> _logger;

    [HttpPost]
    public async Task<IActionResult> HandleWebhook()
    {
        var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync();

        var stripeEvent = EventUtility.ConstructEvent(
            json,
            Request.Headers["Stripe-Signature"],
            _webhookSecret
        );

        switch (stripeEvent.Type)
        {
            case Events.InvoicePaid:
                var invoice = stripeEvent.Data.Object as Invoice;
                await HandleInvoicePaid(invoice);
                break;

            case Events.InvoicePaymentFailed:
                var failedInvoice = stripeEvent.Data.Object as Invoice;
                await HandlePaymentFailed(failedInvoice);
                break;

            case Events.CustomerSubscriptionDeleted:
                var subscription = stripeEvent.Data.Object as Subscription;
                await HandleSubscriptionCancelled(subscription);
                break;
        }

        return Ok();
    }

    private async Task HandlePaymentFailed(Invoice invoice)
    {
        var tenantId = invoice.Metadata["tenant_id"];
        var attemptCount = invoice.AttemptCount;

        _logger.LogWarning(
            "Payment failed for tenant {TenantId}, attempt {Attempt}",
            tenantId, attemptCount);

        if (attemptCount >= 3)
        {
            // Suspend tenant after 3 failed attempts
            await _billingService.SuspendTenantAsync(
                tenantId,
                "Payment failed after 3 attempts"
            );
        }
    }
}

Support Tier Definitions

┌─────────────────────────────────────────────────────────────────────────────────────┐
│                           SUPPORT TIER DEFINITIONS                                   │
└─────────────────────────────────────────────────────────────────────────────────────┘

┌─────────────────┬──────────────┬──────────────┬──────────────┬──────────────────────┐
│ Feature         │ Starter      │ Professional │ Enterprise   │ Premium              │
├─────────────────┼──────────────┼──────────────┼──────────────┼──────────────────────┤
│ Monthly Price   │ $49/month    │ $149/month   │ $499/month   │ $999/month           │
├─────────────────┼──────────────┼──────────────┼──────────────┼──────────────────────┤
│ Locations       │ 1            │ 3            │ 10           │ Unlimited            │
│ Users           │ 3            │ 10           │ 50           │ Unlimited            │
│ Transactions    │ 1,000/mo     │ 10,000/mo    │ 100,000/mo   │ Unlimited            │
├─────────────────┼──────────────┼──────────────┼──────────────┼──────────────────────┤
│ Support Hours   │ Business     │ Extended     │ 24/5         │ 24/7                 │
│ Response Time   │ 24 hours     │ 8 hours      │ 4 hours      │ 1 hour               │
│ Phone Support   │ No           │ Yes          │ Yes          │ Priority Line        │
│ Dedicated CSM   │ No           │ No           │ Yes          │ Yes                  │
├─────────────────┼──────────────┼──────────────┼──────────────┼──────────────────────┤
│ Onboarding      │ Self-service │ Guided       │ White-glove  │ Custom               │
│ Training        │ Videos       │ Live session │ On-site      │ Unlimited            │
│ Data Migration  │ Self-service │ Assisted     │ Managed      │ Managed              │
├─────────────────┼──────────────┼──────────────┼──────────────┼──────────────────────┤
│ Integrations    │ Basic        │ Standard     │ All          │ All + Custom         │
│ API Access      │ Limited      │ Full         │ Full         │ Full + Priority      │
│ Custom Reports  │ No           │ 3/month      │ 10/month     │ Unlimited            │
├─────────────────┼──────────────┼──────────────┼──────────────┼──────────────────────┤
│ SLA             │ 99.5%        │ 99.9%        │ 99.95%       │ 99.99%               │
│ Backup Freq.    │ Daily        │ Daily        │ Hourly       │ Real-time            │
│ Data Retention  │ 1 year       │ 2 years      │ 5 years      │ 7 years              │
└─────────────────┴──────────────┴──────────────┴──────────────┴──────────────────────┘


---

## API Access Explained

**What is API Access?**

API Access means programmatic access to the POS Platform via REST API endpoints. Instead of using the Admin Portal or POS Client UI, developers can write code that directly interacts with the system.

### Why Tenants Want API Access

┌─────────────────────────────────────────────────────────────────────────────────────┐ │ COMMON API ACCESS USE CASES │ └─────────────────────────────────────────────────────────────────────────────────────┘

  1. CUSTOM INTEGRATIONS ┌──────────────────────────────────────────────────────────────────────────────────┐ │ Example: Connect POS to custom ERP system │ │ │ │ ┌─────────────┐ API Call ┌─────────────┐ Update ┌──────────┐ │ │ │ Custom ERP │ ───────────────► │ POS API │ ─────────────► │ Inventory│ │ │ │ System │ POST /products │ Endpoint │ │ Database │ │ │ └─────────────┘ └─────────────┘ └──────────┘ │ │ │ │ Without API: Manual CSV export/import between systems │ │ With API: Real-time automated sync │ └──────────────────────────────────────────────────────────────────────────────────┘

  2. AUTOMATION SCRIPTS ┌──────────────────────────────────────────────────────────────────────────────────┐ │ Example: Nightly inventory reconciliation │ │ │ │ ┌─────────────┐ GET /inventory ┌─────────────┐ │ │ │ Cron Job │ ────────────────────► │ POS API │ │ │ │ (Midnight) │ │ │ │ │ └─────────────┘ └─────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────┐ │ │ │ Compare to │ → Generate discrepancy report → Email to manager │ │ │ physical │ │ │ │ count sheet │ │ │ └─────────────┘ │ └──────────────────────────────────────────────────────────────────────────────────┘

  3. CUSTOM REPORTING ┌──────────────────────────────────────────────────────────────────────────────────┐ │ Example: Executive dashboard with custom KPIs │ │ │ │ ┌─────────────┐ ┌─────────────┐ │ │ │ BI Tool │ ─ GET /sales ───► │ POS API │ │ │ │ (Tableau) │ ─ GET /inventory ─►│ │ │ │ └─────────────┘ └─────────────┘ │ │ │ │ │ ▼ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ Custom Dashboard: Profit margins, vendor performance, trends │ │ │ └─────────────────────────────────────────────────────────────────┘ │ └──────────────────────────────────────────────────────────────────────────────────┘

  4. MOBILE APP DEVELOPMENT ┌──────────────────────────────────────────────────────────────────────────────────┐ │ Example: Custom customer-facing app │ │ │ │ ┌─────────────┐ API Calls ┌─────────────┐ │ │ │ Custom │ ─────────────────►│ POS API │ │ │ │ Mobile App │ │ │ │ │ └─────────────┘ └─────────────┘ │ │ │ │ Features enabled: │ │ • Check loyalty points │ │ • View purchase history │ │ • Scan product for price/availability │ └──────────────────────────────────────────────────────────────────────────────────┘


### Why API Access is Tiered

API Access is restricted to higher tiers for several important reasons:

┌─────────────────────────────────────────────────────────────────────────────────────┐ │ WHY API ACCESS IS ENTERPRISE-TIER+ │ └─────────────────────────────────────────────────────────────────────────────────────┘

  1. INFRASTRUCTURE COST ┌──────────────────────────────────────────────────────────────────────────────────┐ │ API calls consume server resources: │ │ • Each request = CPU cycles + memory + database queries │ │ • Automation scripts can make thousands of requests/hour │ │ • Rate limiting and monitoring infrastructure needed │ │ │ │ Enterprise tenants pay more → covers infrastructure cost │ └──────────────────────────────────────────────────────────────────────────────────┘

  2. SUPPORT BURDEN ┌──────────────────────────────────────────────────────────────────────────────────┐ │ API users need: │ │ • Technical documentation │ │ • Developer support (different skillset than cashier support) │ │ • Debugging assistance when integrations break │ │ • Webhook troubleshooting │ │ │ │ Enterprise tier includes dedicated CSM → can handle developer questions │ └──────────────────────────────────────────────────────────────────────────────────┘

  3. SECURITY RISK ┌──────────────────────────────────────────────────────────────────────────────────┐ │ API keys are powerful: │ │ • Can read/write ALL business data │ │ • If leaked, entire system compromised │ │ • Need audit logging, key rotation, IP whitelisting │ │ │ │ Enterprise tenants have: │ │ • More sophisticated security needs │ │ • Dedicated IT staff to manage keys │ │ • Compliance requirements (SOC 2, PCI) │ └──────────────────────────────────────────────────────────────────────────────────┘

  4. BUSINESS DIFFERENTIATION ┌──────────────────────────────────────────────────────────────────────────────────┐ │ Creates clear value ladder: │ │ │ │ Starter ($49) → UI only, simple use case │ │ Professional ($149) → Limited API, basic integrations │ │ Enterprise ($499) → Full API, custom integrations │ │ Premium ($999) → Priority API, highest rate limits │ │ │ │ Tenants who NEED API access → likely larger businesses → can afford higher tier │ └──────────────────────────────────────────────────────────────────────────────────┘


### API Access by Tier

┌─────────────────┬─────────────────────────────────────────────────────────────────────┐ │ Tier │ API Access Details │ ├─────────────────┼─────────────────────────────────────────────────────────────────────┤ │ Starter │ ❌ NO API ACCESS │ │ ($49/mo) │ • Admin Portal and POS Client only │ │ │ • Cannot generate API keys │ │ │ • No programmatic access │ ├─────────────────┼─────────────────────────────────────────────────────────────────────┤ │ Professional │ ⚠️ LIMITED API ACCESS │ │ ($149/mo) │ • Read-only endpoints: GET /products, GET /sales, GET /inventory │ │ │ • 100 requests/hour rate limit │ │ │ • 1 API key maximum │ │ │ • No webhook subscriptions │ │ │ • Basic documentation access │ ├─────────────────┼─────────────────────────────────────────────────────────────────────┤ │ Enterprise │ ✅ FULL API ACCESS │ │ ($499/mo) │ • All endpoints: GET, POST, PUT, DELETE │ │ │ • 1,000 requests/hour rate limit │ │ │ • 5 API keys with scopes │ │ │ • Webhook subscriptions (10 max) │ │ │ • Full developer documentation │ │ │ • Sandbox environment for testing │ ├─────────────────┼─────────────────────────────────────────────────────────────────────┤ │ Premium │ ✅ PRIORITY API ACCESS │ │ ($999/mo) │ • All Enterprise features PLUS: │ │ │ • 10,000 requests/hour rate limit │ │ │ • Unlimited API keys │ │ │ • Unlimited webhooks │ │ │ • Dedicated API endpoint (isolated) │ │ │ • Custom endpoint development available │ │ │ • Priority support queue for API issues │ └─────────────────┴─────────────────────────────────────────────────────────────────────┘


### API Key Management

Enterprise and Premium tenants manage API keys through Admin Portal:

ADMIN PORTAL → Settings → API Keys

┌─────────────────────────────────────────────────────────────────────────────────────┐ │ API KEYS [+ Create Key] │ ├─────────────────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌───────────────────────────────────────────────────────────────────────────────┐ │ │ │ Name: ERP Integration │ │ │ │ Key: sk_live_abc123…def789 [Copy] [Regenerate] │ │ │ │ Scopes: products:read, inventory:read, inventory:write │ │ │ │ Created: 2025-01-15 │ │ │ │ Last Used: 2025-01-28 14:32:05 UTC │ │ │ │ Requests Today: 847 │ │ │ │ [Revoke Key] │ │ │ └───────────────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌───────────────────────────────────────────────────────────────────────────────┐ │ │ │ Name: Reporting Dashboard │ │ │ │ Key: sk_live_xyz456…uvw012 [Copy] [Regenerate] │ │ │ │ Scopes: sales:read, reports:read │ │ │ │ Created: 2025-01-20 │ │ │ │ Last Used: 2025-01-28 08:00:00 UTC │ │ │ │ Requests Today: 24 │ │ │ │ [Revoke Key] │ │ │ └───────────────────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────────────────┘


---

RESPONSE TIME SLA BY SEVERITY:

┌───────────────┬─────────────┬─────────────┬─────────────┬─────────────────────────────┐
│ Severity      │ Starter     │ Professional│ Enterprise  │ Premium                     │
├───────────────┼─────────────┼─────────────┼─────────────┼─────────────────────────────┤
│ P1 (Critical) │ 8 hours     │ 4 hours     │ 1 hour      │ 15 minutes                  │
│ P2 (High)     │ 24 hours    │ 8 hours     │ 4 hours     │ 1 hour                      │
│ P3 (Medium)   │ 48 hours    │ 24 hours    │ 8 hours     │ 4 hours                     │
│ P4 (Low)      │ 5 days      │ 48 hours    │ 24 hours    │ 8 hours                     │
└───────────────┴─────────────┴─────────────┴─────────────┴─────────────────────────────┘

Summary

This chapter provides complete tenant lifecycle management:

  1. State Machine: 8 states with defined transitions
  2. Onboarding Workflow: 6-phase process with checklists
  3. Automated Provisioning: Scripts for schema creation and setup
  4. Offboarding Workflow: 7-step process including GDPR compliance
  5. Data Export: Complete export scripts for portability
  6. Billing Integration: Stripe webhook handlers
  7. Support Tiers: 4 tiers with feature comparison

Next Chapter: Chapter 34: Claude Code Command Reference


“The beginning and end of a customer relationship deserve equal attention.”