Skip to content

Frequently Asked Questions

Common questions about the Expensis automation system.


Sync Questions

Q: How often do syncs run?

A: Automatically every 5 minutes via the sync:manager cron job (*/5 * * * *).

Q: Can I run a sync manually?

A: Yes, multiple ways:

# Force sync for specific customer
php bin/console sync:manager --customer=123 --force

# Provider-specific sync
php bin/console kpn:sp16:sync --customer=123
php bin/console vodafone:sync --customer=123

Q: Why is my sync stuck in "pending" status?

A: Common causes: 1. Invoice not yet available - Too early in billing cycle (retry automatically) 2. Invalid credentials - Update credentials in sync profile 3. Provider API down - Wait for provider to restore service 4. sync:manager not running - Check cron status

Check:

SELECT id, status, error_message, retries
FROM sync_task
WHERE customer_id = 123
ORDER BY created_at DESC
LIMIT 5;

Q: How do I reset a failed sync?

A:

UPDATE sync_task
SET status = 'pending', retries = 0, error_message = NULL
WHERE id = 12345;

Then wait for next cron run or trigger manually.

Q: What providers are supported?

A: 6 providers: - KPN (SP16, EEN, GRIP platforms) - Vodafone (My Vodafone) - T-Mobile (Calvi) - Routit (Mobile) - Yielder/Odido


Totals & Billing Questions

Q: How are totals calculated?

A: 1. Query all CDRs for customer and billing cycle 2. Group by subscription and call type 3. Apply rate plans to calculate costs 4. Aggregate into totals table 5. Generate billing insights

See: Totals Calculation →

Q: Why are my totals zero?

A: Common causes: 1. No CDRs - Sync hasn't imported data yet 2. CDRs not linked - CDRs missing device_id 3. No rate plans - Subscriptions missing rate_plan_id 4. Calculation not run - Totals not calculated yet

Debug:

-- Check CDRs exist
SELECT COUNT(*) FROM call_detail_record
WHERE customer_id = 123 AND call_date >= '2025-01-01';

-- Check if linked
SELECT COUNT(*) FROM call_detail_record
WHERE customer_id = 123 AND device_id IS NULL;

Q: How do I recalculate totals?

A:

# CLI
php bin/console totals:new --customer=123 --cycle=2025-01-01

# Or via UI
# Go to Usage page → Click "Recalculate" button

Q: Why don't totals match provider invoice?

A: Common reasons: 1. Missing CDRs - Not all CDRs imported 2. Wrong rate plan - Different rates applied 3. Provider fees - Fees not in CDRs (admin fees, taxes) 4. Timing - Provider invoice includes partial month

Solution: Add manual adjustment if needed:

UPDATE totals
SET additional_fees = 25.00,
    total_cost = total_cost + 25.00
WHERE customer_id = 123 AND cycle_start_date = '2025-01-01';


Command Chain Questions

Q: What is a command chain?

A: A sequence of commands that execute automatically one after another.

Example:

$command = new SyncCommand(...);
$command->withChain([
    new CalculateTotalsCommand(...),
    new BackupCommand(...)
]);

See: Command Chaining →

Q: How do I know if a chain executed?

A: Check dependent data exists:

-- If sync completed, should have totals
SELECT st.id, t.id as totals_id
FROM sync_task st
LEFT JOIN total_usage_new_table t ON
    st.customer_id = t.customer_id
    AND st.cycle_start_date = t.cycle_start_date
WHERE st.id = 12345;

-- If totals calculated, should have backup
SELECT t.id, tb.id as backup_id
FROM total_usage_new_table t
LEFT JOIN total_usage_new_backup_table tb ON
    t.customer_id = tb.customer_id
    AND t.cycle_start_date = tb.cycle_start_date
WHERE t.id = 67890;

Q: What if chains aren't working?

A: Check MessageConsumedHandler:

ls -la src/MessageBus/MessageConsumedHandler.php
php bin/console debug:event-dispatcher | grep worker.message.handled

See: Single Points of Failure →


CDR Questions

Q: What is a CDR?

A: Call Detail Record - a record of a single telecom event (call, SMS, data session) with date, duration, destination, and cost.

See: CDRs →

Q: How many CDRs are processed daily?

A: Typical volume: 50,000-200,000 CDRs per day across all customers.

Q: Where are CDRs stored?

A: Database table: call_detail_record

Partitioned by month for performance.

Q: How long are CDRs kept?

A: Retention policy varies by customer, typically 12-24 months.

Q: Can I reimport CDRs?

A: Yes:

# Delete existing CDRs for period
# Then trigger sync
php bin/console [provider]:sync --customer=123 --cycle=2025-01-01 --force


Architecture Questions

Q: What is the MessageBus?

A: Central nervous system for asynchronous communication. Commands are dispatched to MessageBus and routed to handlers.

See: MessageBus Architecture →

Q: What's the difference between a Command and a Handler?

A: - Command: Object representing intent (just data) - Handler: Class that executes the intent (business logic)

Example: - CalculateTotalsCommand (data: customer ID, date) - CalculateTotalsHandler (logic: query CDRs, calculate, save)

Q: What are the critical components?

A: 3 single points of failure: 1. MessageConsumedHandler - Enables all command chains 2. SyncProfileHandler - Routes all provider syncs 3. sync:manager cron - Triggers all automation

See: Single Points of Failure →

Q: Is the system scalable?

A: Yes, via: - Asynchronous processing (non-blocking) - Horizontal scaling (add more workers) - Database partitioning (CDRs by month) - Bulk operations (1000-record batches)


Troubleshooting Questions

Q: Where are error logs?

A:

# Application logs
/var/www/expensis/var/log/prod.log

# System logs
/var/log/syslog

# Cron logs
/var/log/cron.log

Q: How do I enable debug mode?

A:

# In .env.local
APP_ENV=dev
APP_DEBUG=1

Warning: Only for development/staging!

Q: How do I test if automation is working?

A:

# 1. Check cron running
sudo systemctl status cron

# 2. Check recent sync tasks
php bin/console sync:status --recent

# 3. Run manual sync
php bin/console sync:manager --customer=123 --force -vvv

# 4. Check results
php bin/console sync:status --customer=123

Q: Who do I contact for help?

A: 1. Check Common Issues 2. Follow Debugging Guide 3. Search this documentation 4. Contact development team


Operations Questions

Q: How do I add a new customer?

A: 1. Create customer record 2. Create sync profile with credentials 3. Set sync schedule 4. Enable sync profile (active = 1) 5. Wait for next cron run or trigger manually

Q: How do I update provider credentials?

A:

-- Update in sync_profile table
UPDATE sync_profile
SET credentials = 'new_encrypted_credentials'
WHERE id = 123;

Or via UI: Customer Settings → Sync Profile → Update Credentials

Q: How do I disable a sync temporarily?

A:

UPDATE sync_profile
SET active = 0
WHERE id = 123;

Re-enable:

UPDATE sync_profile
SET active = 1
WHERE id = 123;

Q: Can I change sync schedule?

A: Yes, update next_sync_date:

UPDATE sync_profile
SET next_sync_date = '2025-01-20 10:00:00'
WHERE id = 123;


Documentation Questions

Q: Where's the full documentation?

A: You're reading it! Navigate via: - Top menu for main sections - Search (press /) to find anything - Sidebar for section navigation

Q: How do I find a specific command?

A: Command Index →

Q: How do I understand a workflow?

A: Workflow Index →

Q: What's the glossary?

A: Glossary → - Defines all technical terms


Learning Questions

Q: I'm new, where do I start?

A: 1. Overview 2. Quick Start 3. Key Concepts 4. System Architecture

Q: How do I understand the codebase?

A: 1. Read System Architecture 2. Explore Components 3. Trace Workflows 4. Study Dependencies

Q: Where are the visual diagrams?

A: Throughout the documentation! Key locations: - System Architecture - Master Sync - Provider Workflows - CDR Processing


Pro Tips

Press / to search across all documentation instantly.

Tip 2: Check Logs First

tail -100 /var/www/expensis/var/log/prod.log | grep ERROR

Tip 3: Run with Verbose Output

php bin/console [command] -vvv

Tip 4: Test in Staging First

Never test fixes in production directly.

Tip 5: Read Error Messages Carefully

Error messages often contain the exact solution.


Still have questions? Check Common Issues or Debugging Guide