# Grouped Analytics - Complete Guide

## Overview

All analytics methods now support **consistent grouping** by clinic, practitioner, procedure, patient, or technology. This allows you to analyze metrics from any perspective:

- **By Clinic**: See how different clinics perform
- **By Practitioner**: Compare doctor performance
- **By Procedure**: Analyze procedure effectiveness (doctor-specific procedures)
- **By Technology**: Aggregate all procedures using the same technology across all doctors (e.g., all Botox treatments)
- **By Patient**: Understand patient behavior patterns

## Available Grouped Methods

### 1. **Revenue Metrics by Entity** 💰

```typescript
// Revenue grouped by practitioner (doctor)
const revenueByDoctor = await analyticsService.getRevenueMetricsByEntity(
  'practitioner',
  { start: new Date('2024-01-01'), end: new Date('2024-12-31') }
);

// Returns array:
// [
//   {
//     entityId: 'practitioner-123',
//     entityName: 'Dr. Smith',
//     entityType: 'practitioner',
//     totalRevenue: 50000,
//     averageRevenuePerAppointment: 500,
//     totalAppointments: 100,
//     completedAppointments: 95,
//     currency: 'CHF',
//     unpaidRevenue: 5000,
//     refundedRevenue: 0,
//     totalTax: 4000,
//     totalSubtotal: 46000
//   },
//   ...
// ]

// Revenue grouped by clinic
const revenueByClinic = await analyticsService.getRevenueMetricsByEntity(
  'clinic',
  dateRange
);

// Revenue grouped by procedure
const revenueByProcedure = await analyticsService.getRevenueMetricsByEntity(
  'procedure',
  dateRange
);

// Revenue grouped by patient
const revenueByPatient = await analyticsService.getRevenueMetricsByEntity(
  'patient',
  dateRange
);

// Revenue grouped by technology (aggregates all procedures using same technology)
const revenueByTechnology = await analyticsService.getRevenueMetricsByEntity(
  'technology',
  dateRange
);
// Example: All Botox treatments across all doctors
```

### 2. **Product Usage by Entity** 📦

```typescript
// Product usage grouped by practitioner
const productUsageByDoctor = await analyticsService.getProductUsageMetricsByEntity(
  'practitioner',
  dateRange
);

// Returns array:
// [
//   {
//     entityId: 'practitioner-123',
//     entityName: 'Dr. Smith',
//     entityType: 'practitioner',
//     totalProductsUsed: 15,
//     uniqueProducts: 10,
//     totalProductRevenue: 25000,
//     totalProductQuantity: 500,
//     averageProductsPerAppointment: 2.5,
//     topProducts: [
//       {
//         productId: 'product-1',
//         productName: 'Product A',
//         brandName: 'Brand X',
//         totalQuantity: 100,
//         totalRevenue: 5000,
//         usageCount: 50
//       },
//       ...
//     ]
//   },
//   ...
// ]

// Product usage grouped by clinic, procedure, patient, or technology
const productUsageByClinic = await analyticsService.getProductUsageMetricsByEntity(
  'clinic',
  dateRange
);

// Product usage by technology (e.g., all Botox-related products)
const productUsageByTechnology = await analyticsService.getProductUsageMetricsByEntity(
  'technology',
  dateRange
);
```

### 3. **Time Efficiency by Entity** ⏱️

```typescript
// Time efficiency grouped by practitioner
const timeEfficiencyByDoctor = await analyticsService.getTimeEfficiencyMetricsByEntity(
  'practitioner',
  dateRange
);

// Returns array:
// [
//   {
//     entityId: 'practitioner-123',
//     entityName: 'Dr. Smith',
//     entityType: 'practitioner',
//     totalAppointments: 100,
//     appointmentsWithActualTime: 95,
//     averageBookedDuration: 60, // minutes
//     averageActualDuration: 55, // minutes
//     averageEfficiency: 91.67, // percentage
//     totalOverrun: 500, // minutes
//     totalUnderutilization: 200, // minutes
//     averageOverrun: 5, // minutes
//     averageUnderutilization: 2 // minutes
//   },
//   ...
// ]

// Time efficiency grouped by clinic, procedure, patient, or technology
const timeEfficiencyByClinic = await analyticsService.getTimeEfficiencyMetricsByEntity(
  'clinic',
  dateRange
);

// Time efficiency by technology (e.g., compare efficiency across all Botox vs. Filler treatments)
const timeEfficiencyByTechnology = await analyticsService.getTimeEfficiencyMetricsByEntity(
  'technology',
  dateRange
);
```

### 4. **Patient Behavior by Entity** 👥

```typescript
// Patient behavior (no-shows, cancellations) grouped by practitioner
const patientBehaviorByDoctor = await analyticsService.getPatientBehaviorMetricsByEntity(
  'practitioner',
  dateRange
);

// Returns array:
// [
//   {
//     entityId: 'practitioner-123',
//     entityName: 'Dr. Smith',
//     entityType: 'practitioner',
//     totalPatients: 50,
//     patientsWithNoShows: 10,
//     patientsWithCancellations: 15,
//     averageNoShowRate: 8.5, // percentage
//     averageCancellationRate: 12.3, // percentage
//     topNoShowPatients: [
//       {
//         patientId: 'patient-1',
//         patientName: 'John Doe',
//         noShowCount: 3,
//         totalAppointments: 10,
//         noShowRate: 30.0
//       },
//       ...
//     ],
//     topCancellationPatients: [
//       {
//         patientId: 'patient-2',
//         patientName: 'Jane Smith',
//         cancellationCount: 5,
//         totalAppointments: 15,
//         cancellationRate: 33.3
//       },
//       ...
//     ]
//   },
//   ...
// ]

// Patient behavior grouped by clinic or procedure
const patientBehaviorByClinic = await analyticsService.getPatientBehaviorMetricsByEntity(
  'clinic',
  dateRange
);
```

### 5. **Cancellation Metrics by Entity** ❌

```typescript
// Already exists - cancellations grouped by entity
const cancellationsByDoctor = await analyticsService.getCancellationMetrics(
  'practitioner',
  dateRange
);

// Also supports: 'clinic', 'patient', 'procedure', 'technology'
```

### 6. **No-Show Metrics by Entity** 🚫

```typescript
// Already exists - no-shows grouped by entity
const noShowsByDoctor = await analyticsService.getNoShowMetrics(
  'practitioner',
  dateRange
);

// Also supports: 'clinic', 'patient', 'procedure', 'technology'
```

## Real-World Use Cases

### Use Case 1: Revenue Comparison Across Doctors

```typescript
// Compare revenue generated by each doctor
const revenueByDoctor = await analyticsService.getRevenueMetricsByEntity(
  'practitioner',
  { start: new Date('2024-01-01'), end: new Date('2024-12-31') }
);

// Sort by revenue (highest first)
const topPerformers = revenueByDoctor
  .sort((a, b) => b.totalRevenue - a.totalRevenue)
  .slice(0, 10);

console.log('Top 10 Revenue Generators:');
topPerformers.forEach((doctor, index) => {
  console.log(`${index + 1}. ${doctor.entityName}: ${doctor.totalRevenue} ${doctor.currency}`);
  console.log(`   Avg per appointment: ${doctor.averageRevenuePerAppointment.toFixed(2)}`);
  console.log(`   Appointments: ${doctor.completedAppointments}`);
});
```

### Use Case 2: Product Usage by Procedure

```typescript
// See which products are used most for each procedure
const productUsageByProcedure = await analyticsService.getProductUsageMetricsByEntity(
  'procedure',
  dateRange
);

productUsageByProcedure.forEach(procedure => {
  console.log(`\n${procedure.entityName}:`);
  console.log(`  Total Products Used: ${procedure.totalProductsUsed}`);
  console.log(`  Total Product Revenue: ${procedure.totalProductRevenue}`);
  console.log(`  Top Products:`);
  procedure.topProducts.slice(0, 5).forEach(product => {
    console.log(`    - ${product.productName}: ${product.totalQuantity} units, ${product.totalRevenue} revenue`);
  });
});
```

### Use Case 3: Time Efficiency by Clinic

```typescript
// Compare time efficiency across clinics
const timeEfficiencyByClinic = await analyticsService.getTimeEfficiencyMetricsByEntity(
  'clinic',
  dateRange
);

timeEfficiencyByClinic.forEach(clinic => {
  console.log(`${clinic.entityName}:`);
  console.log(`  Efficiency: ${clinic.averageEfficiency.toFixed(1)}%`);
  console.log(`  Avg Booked: ${clinic.averageBookedDuration} min`);
  console.log(`  Avg Actual: ${clinic.averageActualDuration} min`);
  console.log(`  Avg Overrun: ${clinic.averageOverrun} min`);
});
```

### Use Case 4: Patient No-Show Patterns by Doctor

```typescript
// See which patients have highest no-show rates for each doctor
const patientBehaviorByDoctor = await analyticsService.getPatientBehaviorMetricsByEntity(
  'practitioner',
  dateRange
);

patientBehaviorByDoctor.forEach(doctor => {
  console.log(`\n${doctor.entityName}:`);
  console.log(`  Total Patients: ${doctor.totalPatients}`);
  console.log(`  Patients with No-Shows: ${doctor.patientsWithNoShows}`);
  console.log(`  Average No-Show Rate: ${doctor.averageNoShowRate}%`);
  console.log(`  Top No-Show Patients:`);
  doctor.topNoShowPatients.forEach(patient => {
    console.log(`    - ${patient.patientName}: ${patient.noShowRate.toFixed(1)}% (${patient.noShowCount}/${patient.totalAppointments})`);
  });
});
```

### Use Case 5: Revenue by Patient

```typescript
// See which patients generate the most revenue
const revenueByPatient = await analyticsService.getRevenueMetricsByEntity(
  'patient',
  dateRange
);

const topPatients = revenueByPatient
  .sort((a, b) => b.totalRevenue - a.totalRevenue)
  .slice(0, 20);

console.log('Top 20 Patients by Revenue:');
topPatients.forEach((patient, index) => {
  console.log(`${index + 1}. ${patient.entityName}: ${patient.totalRevenue} ${patient.currency}`);
  console.log(`   Appointments: ${patient.completedAppointments}`);
  console.log(`   Avg per appointment: ${patient.averageRevenuePerAppointment.toFixed(2)}`);
});
```

### Use Case 6: Product Usage by Clinic

```typescript
// Compare product usage across clinics
const productUsageByClinic = await analyticsService.getProductUsageMetricsByEntity(
  'clinic',
  dateRange
);

productUsageByClinic.forEach(clinic => {
  console.log(`\n${clinic.entityName}:`);
  console.log(`  Unique Products: ${clinic.uniqueProducts}`);
  console.log(`  Total Product Revenue: ${clinic.totalProductRevenue}`);
  console.log(`  Avg Products per Appointment: ${clinic.averageProductsPerAppointment.toFixed(2)}`);
  console.log(`  Top Products:`);
  clinic.topProducts.forEach(product => {
    console.log(`    - ${product.productName}: ${product.totalQuantity} units`);
  });
});
```

### Use Case 7: Combined Analysis - Doctor Performance Dashboard

```typescript
// Get multiple metrics for each doctor
const dateRange = { start: new Date('2024-01-01'), end: new Date('2024-12-31') };

const [
  revenueByDoctor,
  timeEfficiencyByDoctor,
  cancellationsByDoctor,
  noShowsByDoctor,
  patientBehaviorByDoctor,
] = await Promise.all([
  analyticsService.getRevenueMetricsByEntity('practitioner', dateRange),
  analyticsService.getTimeEfficiencyMetricsByEntity('practitioner', dateRange),
  analyticsService.getCancellationMetrics('practitioner', dateRange),
  analyticsService.getNoShowMetrics('practitioner', dateRange),
  analyticsService.getPatientBehaviorMetricsByEntity('practitioner', dateRange),
]);

// Combine into comprehensive doctor performance report
const doctorPerformance = revenueByDoctor.map(revenue => {
  const timeEfficiency = timeEfficiencyByDoctor.find(t => t.entityId === revenue.entityId);
  const cancellation = Array.isArray(cancellationsByDoctor)
    ? cancellationsByDoctor.find(c => c.entityId === revenue.entityId)
    : null;
  const noShow = Array.isArray(noShowsByDoctor)
    ? noShowsByDoctor.find(n => n.entityId === revenue.entityId)
    : null;
  const patientBehavior = patientBehaviorByDoctor.find(p => p.entityId === revenue.entityId);

  return {
    doctorId: revenue.entityId,
    doctorName: revenue.entityName,
    revenue: revenue.totalRevenue,
    timeEfficiency: timeEfficiency?.averageEfficiency || 0,
    cancellationRate: cancellation?.cancellationRate || 0,
    noShowRate: noShow?.noShowRate || 0,
    patientRetention: patientBehavior?.totalPatients || 0,
    averageNoShowRate: patientBehavior?.averageNoShowRate || 0,
  };
});

// Sort by revenue
doctorPerformance.sort((a, b) => b.revenue - a.revenue);

console.log('Doctor Performance Dashboard:');
doctorPerformance.forEach((doctor, index) => {
  console.log(`\n${index + 1}. ${doctor.doctorName}`);
  console.log(`   Revenue: ${doctor.revenue} CHF`);
  console.log(`   Time Efficiency: ${doctor.timeEfficiency.toFixed(1)}%`);
  console.log(`   Cancellation Rate: ${doctor.cancellationRate.toFixed(1)}%`);
  console.log(`   No-Show Rate: ${doctor.noShowRate.toFixed(1)}%`);
  console.log(`   Patient Retention: ${doctor.patientRetention} patients`);
});
```

## Filtering Options

All grouped methods support additional filters:

```typescript
// Revenue by practitioner, but only for a specific clinic
const revenueByDoctor = await analyticsService.getRevenueMetricsByEntity(
  'practitioner',
  dateRange,
  { clinicBranchId: 'clinic-123' }
);

// Product usage by procedure, but only for a specific practitioner
const productUsageByProcedure = await analyticsService.getProductUsageMetricsByEntity(
  'procedure',
  dateRange,
  { practitionerId: 'practitioner-123' }
);

// Time efficiency by patient, but only for a specific procedure
const timeEfficiencyByPatient = await analyticsService.getTimeEfficiencyMetricsByEntity(
  'patient',
  dateRange,
  { procedureId: 'procedure-123' }
);
```

## Performance Notes

- **Pre-computed**: Grouped metrics can be cached (when using standard date ranges)
- **Efficient**: Single query, then grouping in memory
- **Scalable**: Works well even with large datasets
- **Flexible**: Combine multiple grouped queries for comprehensive analysis

### Use Case 8: Technology-Level Analysis (Aggregating Across Doctors)

```typescript
// Analyze all Botox treatments across all doctors
const revenueByTechnology = await analyticsService.getRevenueMetricsByEntity(
  'technology',
  dateRange
);

// Find Botox technology
const botoxMetrics = revenueByTechnology.find(
  tech => tech.entityName.toLowerCase().includes('botox')
);

console.log(`Botox Revenue (All Doctors):`);
console.log(`  Total Revenue: ${botoxMetrics.totalRevenue} ${botoxMetrics.currency}`);
console.log(`  Total Appointments: ${botoxMetrics.completedAppointments}`);
console.log(`  Avg per Appointment: ${botoxMetrics.averageRevenuePerAppointment.toFixed(2)}`);

// Compare no-show rates by technology
const noShowsByTechnology = await analyticsService.getNoShowMetrics(
  'technology',
  dateRange
);

noShowsByTechnology.forEach(tech => {
  console.log(`${tech.entityName}:`);
  console.log(`  No-Show Rate: ${tech.noShowRate.toFixed(1)}%`);
  console.log(`  Total Appointments: ${tech.totalAppointments}`);
});
```

**Key Difference:**
- **Procedure grouping**: Analyzes specific procedure IDs (doctor-specific, e.g., "Dr. Smith's Botox Treatment")
- **Technology grouping**: Aggregates all procedures using the same technology across all doctors (e.g., all Botox treatments regardless of doctor)

## Summary

All analytics now support consistent grouping:

✅ **Revenue** - by clinic/practitioner/procedure/patient/technology  
✅ **Product Usage** - by clinic/practitioner/procedure/patient/technology  
✅ **Time Efficiency** - by clinic/practitioner/procedure/patient/technology  
✅ **Patient Behavior** - by clinic/practitioner/procedure/technology  
✅ **Cancellations** - by clinic/practitioner/patient/procedure/technology  
✅ **No-Shows** - by clinic/practitioner/patient/procedure/technology  

This gives you **complete flexibility** to analyze your data from any perspective!

**Note on Technology vs Procedure:**
- **Procedure**: Doctor-specific procedure (e.g., "Dr. Smith's Botox Treatment")
- **Technology**: Parent technology that groups all procedures using the same technology (e.g., "Botox" - includes all Botox procedures from all doctors)

