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:
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:
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:
Re-enable:
Q: Can I change sync schedule?¶
A: Yes, update next_sync_date:
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?¶
Q: How do I understand a workflow?¶
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¶
Tip 1: Use Search¶
Press / to search across all documentation instantly.
Tip 2: Check Logs First¶
Tip 3: Run with Verbose Output¶
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