# ShiftOps Scoring System Documentation


**Last Updated:** 2025-11-20

Complete documentation for the ShiftOps scoring system, covering all calculation methods, factors, helper functions, and configuration constants.

## Overview

The ShiftOps scoring system evaluates businesses across 5 pillars (0-20 points each) to produce a total score (0-100) and grade (A+ through F). The system uses industry-specific baselines, data completeness multipliers, and customer boost adjustments to ensure accurate and fair scoring.

### Score Ranges

- **Total Score:** 0-100 (integer)
- **Pillar Scores:** 0-20 (integer, per pillar)
- **Grade:** A+, A, A-, B+, B, B-, C+, C, C-, D+, D, D-, F

### Purpose

The scoring system provides:

- Objective assessment of operational efficiency
- Industry-specific benchmarking
- Actionable insights for improvement
- Fair comparison across business types

## Scoring Architecture

### Three Calculation Modes

The system supports three calculation modes based on available data:

1. **Full Mode** (`calculateShiftOpsScore`): Complete calculation using all available data and dependencies
2. **Partial Mode** (`calculatePartialScoreFromData`): Simplified calculation when some dependencies fail
3. **Fallback Mode** (`calculateFallbackScore`): Minimal calculation using only basic indicators

### Calculation Order

```
1. Calculate raw pillar scores (floats, 0.00-20.00)
2. Sum raw pillar scores
3. Apply data completeness multiplier (0.60-1.0)
4. Apply customer cap (max 95 for customers)
5. Round total score (customers: round up, non-customers: floor)
6. Adjust pillar scores proportionally to match total
7. Assign grade (A+ through F)
```

### Data Flow

```
Business Data (Google Places API)
    ↓
Industry Baseline Selection
    ↓
Factor Calculation (Digital Maturity, Complexity, etc.)
    ↓
Customer Boost Application (if applicable)
    ↓
Raw Pillar Scores (floats)
    ↓
Data Completeness Multiplier
    ↓
Customer Cap (if applicable)
    ↓
Total Score (integer)
    ↓
Pillar Score Adjustment
    ↓
Final Scores + Grade
```

## Pillar Scoring Details

### 1. Scheduling Efficiency (0-20)

**Purpose:** Measures how efficiently a business manages shift scheduling and workforce planning.

**Industry Baselines:**

- Healthcare (hospital, pharmacy, doctor): 5 points
- Hospitality (restaurant, cafe, bar): 6 points
- Retail (store, shopping_mall): 7 points
- General: 6 points

**Scoring Factors:**

1. **Digital Maturity (0-5 points)**

   - Website exists: +2 points
   - Website with online features (booking, ordering, payment): +1 point
   - Active Google Business (photos >10 AND reviews >50): +2 points
   - Moderate Google Business (photos >5 OR reviews >25): +1 point

2. **Operational Complexity (0-7 points)**

   - Weekly hours >= 80: +6 points
   - Weekly hours >= 60: +4 points
   - Weekly hours >= 40: +2 points
   - Multiple service types (>=3): +1 point
   - Multi-location business: +1 point

3. **Team Scale Indicators (0-3 points)**
   - Review count >500: +2 points
   - Review count >100: +1 point
   - Rating >=4.0 AND review count >100: +1 point

**Customer Boost:**

- Baseline bonus: +2 points per pillar
- Percentage boost: +20-30% per pillar
- Maximum score: 18 points
- Minimum score: 14 points (floor)

**Point Breakdown Table:**

| Factor                     | Points | Condition                           |
| -------------------------- | ------ | ----------------------------------- |
| Industry Baseline          | 3-5    | Based on business type              |
| Website                    | +2     | Website exists                      |
| Online Features            | +1     | Booking/ordering/payment indicators |
| Google Business (Active)   | +2     | Photos >10 AND reviews >50          |
| Google Business (Moderate) | +1     | Photos >5 OR reviews >25            |
| Weekly Hours (Very High)   | +6     | >=80 hours/week                     |
| Weekly Hours (High)        | +4     | 60-79 hours/week                    |
| Weekly Hours (Moderate)    | +2     | 40-59 hours/week                    |
| Service Types              | +1     | >=3 service types                   |
| Multi-location             | +1     | Chain/franchise indicators          |
| Large Operation            | +2     | Reviews >500                        |
| Medium Operation           | +1     | Reviews >100                        |
| High Performance           | +1     | Rating >=4.0 AND reviews >100       |

**Code Location:** `v2/api/shiftops.php` lines 3145-3254

### 2. Absence Stability (0-20)

**Purpose:** Evaluates how well a business manages employee absences and maintains stable operations.

**Industry Baselines:**

- Healthcare (hospital, pharmacy, doctor): 6 points
- Hospitality (restaurant, cafe, bar): 7 points
- Retail (store, shopping_mall): 8 points
- General: 7 points

**Scoring Factors:**

1. **Rating-Based Scoring (0-4 points)**

   - Rating >=4.5: +4 points
   - Rating >=4.0: +3 points
   - Rating >=3.5: +2 points
   - Rating >=3.0: +1 point

2. **Review Sentiment Analysis (0-2 points)**

   - Positive mentions > negative mentions: +2 points
   - Negative mentions > positive mentions: -2 points

3. **Seasonal Factors (0-3 points)**

   - Healthcare: +3 points (always)
   - Hospitality (high season: Jun, Jul, Aug, Dec): +1 point
   - Hospitality (other months): +2 points
   - Retail (high season: Nov, Dec): +1 point
   - Retail (other months): +2 points
   - General: +2 points

4. **Holiday Impact (-3 to 0 points)**

   - Upcoming holidays >=3: -3 points
   - Upcoming holidays >=2: -2 points
   - Upcoming holidays >=1: -1 point

5. **Weather Risk (-1 point)**

   - Weather risk detected: -1 point

6. **Multi-location Bonus (+1 point)**

   - Multi-location business: +1 point

7. **Seasonal Multiplier Bonus (+2 points)**
   - If seasonal multiplier <1.0 (low season): +2 points

**Customer Boost:**

- Baseline bonus: +3 points
- Percentage boost: +25%
- Maximum score: 20 points
- Minimum score: 15 points (floor)

**Point Breakdown Table:**

| Factor                  | Points | Condition                    |
| ----------------------- | ------ | ---------------------------- |
| Industry Baseline       | 4-6    | Based on business type       |
| Rating (Excellent)      | +4     | Rating >=4.5                 |
| Rating (Very Good)      | +3     | Rating >=4.0                 |
| Rating (Good)           | +2     | Rating >=3.5                 |
| Rating (Average)        | +1     | Rating >=3.0                 |
| Positive Sentiment      | +2     | Positive > negative mentions |
| Negative Sentiment      | -2     | Negative > positive mentions |
| Healthcare Seasonal     | +3     | Always for healthcare        |
| Hospitality Seasonal    | +1-2   | Based on month               |
| Retail Seasonal         | +1-2   | Based on month               |
| Multi-location          | +1     | Chain/franchise indicators   |
| Holiday Impact (High)   | -3     | >=3 upcoming holidays        |
| Holiday Impact (Medium) | -2     | >=2 upcoming holidays        |
| Holiday Impact (Low)    | -1     | >=1 upcoming holiday         |
| Weather Risk            | -1     | Risk conditions detected     |
| Low Season Bonus        | +2     | Seasonal multiplier <1.0     |

**Code Location:** `v2/api/shiftops.php` lines 3287-3385

### 3. Time Tracking Hygiene (0-20)

**Purpose:** Assesses the quality and consistency of time tracking practices.

**Industry Baselines:**

- Healthcare (hospital, pharmacy, doctor): 5 points
- Hospitality (restaurant, cafe, bar): 5 points
- Retail (store, shopping_mall): 6 points
- General: 6 points

**Scoring Factors:**

1. **Website Presence (+2 points)**

   - Website exists: +2 points

2. **Digital Presence Indicators (0-2 points)**

   - Active presence (photos >10 AND reviews >50): +2 points
   - Moderate presence (photos >5 OR reviews >25): +1 point

3. **Schedule Complexity (0-5 points)**

   - Very high complexity: +5 points
   - High complexity: +3 points
   - Medium complexity: +1 point

4. **Multi-location Bonus (+2 points)**

   - Multi-location business: +2 points

5. **Rating and Review Bonuses (0-3 points)**
   - Rating >=4.0: +2 points
   - Review count >100: +1 point
   - Review count >200 AND rating >3.5: +1 point

**Customer Boost:**

- Baseline bonus: +2 points per pillar
- Percentage boost: +20-30% per pillar
- Maximum score: 18 points
- Minimum score: 14 points (floor)

**Point Breakdown Table:**

| Factor                          | Points | Condition                           |
| ------------------------------- | ------ | ----------------------------------- |
| Industry Baseline               | 3-4    | Based on business type              |
| Website                         | +2     | Website exists                      |
| Active Digital Presence         | +2     | Photos >10 AND reviews >50          |
| Moderate Digital Presence       | +1     | Photos >5 OR reviews >25            |
| Schedule Complexity (Very High) | +5     | Irregular hours OR weekly hours >80 |
| Schedule Complexity (High)      | +3     | Split shifts OR weekly hours >60    |
| Schedule Complexity (Medium)    | +1     | Days open >=6 OR weekly hours >40   |
| Multi-location                  | +2     | Chain/franchise indicators          |
| High Rating                     | +2     | Rating >=4.0                        |
| Review Volume                   | +1     | Reviews >100                        |
| High Volume + Rating            | +1     | Reviews >200 AND rating >3.5        |

**Code Location:** `v2/api/shiftops.php` lines 3509-3586

### 4. Compliance Docs (0-20)

**Purpose:** Measures compliance documentation quality and regulatory adherence.

**Industry Baselines:**

- Healthcare (hospital, pharmacy, doctor): 9 points - Recognize strict compliance requirements
- Hospitality (restaurant, cafe, bar): 7 points - Recognize HACCP requirements
- Retail (store, shopping_mall): 7 points
- General: 6 points

**Scoring Factors:**

1. **Industry Compliance Requirements (0-8 points)**

   - Healthcare: +6 points
   - Hospitality/Food: +5 points
   - Retail: +4 points
   - General: +3 points
   - Wheelchair accessible entrance: +2 points

2. **Documentation Indicators (0-4 points)**

   - Required fields complete (>=4): +2 points
   - Required fields complete (>=3): +1 point
   - Active presence (photos >5 AND reviews >25): +2 points
   - Moderate presence (photos >2 OR reviews >10): +1 point

3. **Regional Compliance Factors (0-3 points)**

   - Germany (DE): +2 points
   - Austria (AT): +1 point
   - Switzerland (CH): +1 point
   - Review count >100: +1 point

4. **Risk Assessment (0-2 points)**
   - No negative compliance mentions AND reviews >10: +1 point
   - Review count >200 AND rating >3.5: +1 point

**Customer Boost:**

- Baseline bonus: +3 points
- Percentage boost: +30%
- Maximum score: 19 points
- Minimum score: 15 points (floor)

**Point Breakdown Table:**

| Factor                   | Points | Condition                            |
| ------------------------ | ------ | ------------------------------------ |
| Industry Baseline        | 4-6    | Based on business type               |
| Healthcare Compliance    | +6     | Healthcare industry                  |
| Hospitality Compliance   | +5     | Restaurant/cafe/food                 |
| Retail Compliance        | +4     | Store/shopping_mall                  |
| General Compliance       | +3     | Other industries                     |
| Accessibility            | +2     | Wheelchair accessible                |
| Complete Fields (High)   | +2     | >=4 required fields                  |
| Complete Fields (Medium) | +1     | >=3 required fields                  |
| Active Presence          | +2     | Photos >5 AND reviews >25            |
| Moderate Presence        | +1     | Photos >2 OR reviews >10             |
| Germany                  | +2     | Country = DE                         |
| Austria/Switzerland      | +1     | Country = AT or CH                   |
| Review Volume            | +1     | Reviews >100                         |
| No Compliance Issues     | +1     | No negative mentions AND reviews >10 |
| High Quality             | +1     | Reviews >200 AND rating >3.5         |

**Code Location:** `v2/api/shiftops.php` lines 3671-3767

### 5. Payroll Readiness (0-20)

**Purpose:** Evaluates readiness for payroll processing and DATEV integration.

**Industry Baselines:**

- Healthcare (hospital, pharmacy, doctor): 6 points
- Hospitality (restaurant, cafe, bar): 6 points
- Retail (store, shopping_mall): 7 points
- General: 7 points

**Scoring Factors:**

1. **Website and Payment Features (0-4 points)**

   - Website exists: +2 points
   - Payment features detected: +2 points

2. **Digital Services (0-2 points)**

   - Digital services >=2: +2 points
   - Digital services >=1: +1 point

3. **Review Count Bonuses (0-3 points)**

   - Review count >500: +3 points
   - Review count >200: +2 points
   - Review count >100: +1 point

4. **Rating and Review Combinations (0-2 points)**

   - Review count >150 AND rating >3.8: +2 points
   - Review count >50 AND rating >3.5: +1 point

5. **Multi-location Bonus (+1 point)**

   - Multi-location business: +1 point

6. **Price Level Bonus (+2 points)**

   - Price level >0: +2 points

7. **Rating and Volume Combination (0-2 points)**

   - Rating >=4.0 AND reviews >100: +2 points
   - Rating >=3.5 AND reviews >50: +1 point

8. **Regional Factors (0-2 points)**

   - Germany (DE): +2 points
   - Austria/Switzerland (AT/CH): +1 point

9. **Standard Hours Bonus (+1 point)**

   - Standard business hours detected: +1 point

10. **Schedule Complexity Bonus (+1 point)**
    - Low or medium complexity: +1 point

**Customer Boost:**

- Baseline bonus: +3 points
- Percentage boost: +30%
- Maximum score: 18 points
- Minimum score: 14 points (floor)

**Point Breakdown Table:**

| Factor                  | Points | Condition                         |
| ----------------------- | ------ | --------------------------------- |
| Industry Baseline       | 4-5    | Based on business type            |
| Website                 | +2     | Website exists                    |
| Payment Features        | +2     | Payment/checkout indicators       |
| Digital Services (High) | +2     | >=2 digital services              |
| Digital Services (Low)  | +1     | >=1 digital service               |
| Very High Volume        | +3     | Reviews >500                      |
| High Volume             | +2     | Reviews >200                      |
| Medium Volume           | +1     | Reviews >100                      |
| Excellent Quality       | +2     | Reviews >150 AND rating >3.8      |
| Good Quality            | +1     | Reviews >50 AND rating >3.5       |
| Multi-location          | +1     | Chain/franchise indicators        |
| Price Level             | +2     | Price level >0                    |
| High Rating + Volume    | +2     | Rating >=4.0 AND reviews >100     |
| Good Rating + Volume    | +1     | Rating >=3.5 AND reviews >50      |
| Germany                 | +2     | Country = DE                      |
| Austria/Switzerland     | +1     | Country = AT or CH                |
| Standard Hours          | +1     | Standard 9-5 hours                |
| Low Complexity          | +1     | Low or medium schedule complexity |

**Code Location:** `v2/api/shiftops.php` lines 3785-3896

## Total Score Calculation

### Step-by-Step Process

#### Step 1: Calculate Raw Pillar Scores

Each pillar score is calculated independently as a float (0.00-20.00):

```php
$rawScores = [
    'scheduling_efficiency' => calculateSchedulingScoreRaw($businessData, $isOrdioCustomer),
    'absence_stability' => calculateAbsenceScoreRaw($businessData, $isOrdioCustomer),
    'time_tracking_hygiene' => calculateTimeTrackingScoreRaw($businessData, $isOrdioCustomer),
    'compliance_docs' => calculateComplianceScoreRaw($businessData, $isOrdioCustomer),
    'payroll_readiness' => calculatePayrollScoreRaw($businessData, $isOrdioCustomer)
];
```

#### Step 2: Sum Raw Scores

Simple addition of all raw pillar scores:

```php
$rawTotalScore = array_sum($rawScores);
```

#### Step 3: Apply Data Completeness Multiplier

The multiplier is based on available data fields:

**Fields Checked:**

- Website (exists)
- Opening hours (exists)
- Reviews (exists and count >0)
- Photos (exists and count >0)

**Multiplier Calculation:**

| Complete Fields | Percentage | Multiplier | Confidence | Impact |
| --------------- | ---------- | ---------- | ---------- | ------ |
| 4 fields        | 100%       | 1.0        | High       | None   |
| 3 fields        | 75%        | 0.90       | Medium     | Low    |
| 2 fields        | 50%        | 0.75       | Medium     | Medium |
| 1 field         | 25%        | 0.65       | Low        | High   |
| 0 fields        | 0%         | 0.60       | Low        | High   |

**Customer Adjustment:**

For Ordio customers, a more lenient multiplier is applied:

- If website missing AND multiplier <1.0: Use 0.94 multiplier
- If website exists OR other digital indicators: Use max(0.98, multiplier)

```php
if ($isOrdioCustomer) {
    $missingWebsite = empty($businessData['website']);
    if ($missingWebsite && $dataCompleteness['multiplier'] < 1.0) {
        $adjustedScore = $rawTotalScore * 0.94;
    } else {
        $adjustedScore = $rawTotalScore * max(0.98, $dataCompleteness['multiplier']);
    }
} else {
    $adjustedScore = $rawTotalScore * $dataCompleteness['multiplier'];
}
```

**Code Location:** `v2/api/shiftops.php` lines 3087-3125

#### Step 4: Apply Customer Cap

Ordio customers are capped at 95 points maximum (maintains credibility):

```php
if ($isOrdioCustomer) {
    if (defined('MAX_TOTAL_SCORE')) {
        $adjustedScore = min(MAX_TOTAL_SCORE, $adjustedScore); // MAX_TOTAL_SCORE = 95
    }
}
```

**Rationale:** Customers shouldn't score 100 (implies no improvement needed). Maintains credibility while recognizing good practices.

#### Step 5: Round Total Score

Different rounding rules for customers vs non-customers:

```php
if ($isOrdioCustomer) {
    $finalTotalScore = (int)round($adjustedScore); // Rounds up
} else {
    $finalTotalScore = (int)floor($adjustedScore); // Rounds down
}
```

#### Step 6: Adjust Pillar Scores Proportionally

Pillar scores are adjusted so their rounded sum equals the total score:

**Algorithm:**

1. Calculate adjustment ratio: `$ratio = $targetTotal / $rawSum`
2. Apply ratio to each pillar score: `$adjustedScore = $rawScore * $ratio`
3. Floor all scores initially
4. Calculate difference: `$difference = $targetTotal - $sumOfAdjusted`
5. If difference >0: Round up pillars with highest fractional parts
6. If difference <0: Round down pillars with lowest fractional parts
7. Final verification: Adjust largest/smallest pillar if needed

**Code Location:** `v2/api/shiftops.php` lines 2912-3011

#### Step 7: Assign Grade

Grade assignment based on total score:

| Score Range | Grade |
| ----------- | ----- |
| 90-100      | A+    |
| 85-89       | A     |
| 80-84       | A-    |
| 75-79       | B+    |
| 70-74       | B     |
| 65-69       | B-    |
| 60-64       | C+    |
| 55-59       | C     |
| 50-54       | C-    |
| 45-49       | D+    |
| 40-44       | D     |
| 35-39       | D-    |
| 0-34        | F     |

**Code Location:** `v2/api/shiftops.php` lines 4767-4782

## Helper Methods

### adjustPillarScoresToMatchTotal()

**Purpose:** Adjusts pillar scores proportionally so their rounded sum equals the target total.

**Parameters:**

- `$rawScores` (array): Raw pillar scores before rounding
- `$targetTotal` (int): Target total score
- `$isCustomer` (bool): Whether this is for an Ordio customer

**Returns:** `array` - Adjusted pillar scores (integers) that sum to target total

**Algorithm:**

1. Calculate raw sum: `$rawSum = array_sum($rawScores)`
2. If raw sum is zero, return zeros
3. Calculate ratio: `$ratio = $targetTotal / $rawSum`
4. Apply ratio to each score: `$adjustedScore = $rawScore * $ratio`
5. Floor all scores initially
6. Calculate difference: `$difference = $targetTotal - $sumOfAdjusted`
7. If difference >0: Round up pillars with highest fractional parts
8. If difference <0: Round down pillars with lowest fractional parts
9. Final verification: Adjust largest/smallest pillar if needed

**Code Location:** `v2/api/shiftops.php` lines 2912-3011

### applyCustomerBoostRaw()

**Purpose:** Applies customer boost to a raw score without rounding.

**Parameters:**

- `$score` (float): Original score
- `$boostPercent` (float): Boost percentage (e.g., 35 for +35%)
- `$maxScore` (float): Maximum allowed score for this pillar
- `$minScore` (float|null): Optional minimum floor score for customers

**Returns:** `float` - Boosted score (not rounded)

**Formula:**

```php
if ($score <= 0) {
    return $score; // Don't boost zero scores
}

$boost = $score * ($boostPercent / 100);
$boostedScore = $score + $boost;

// Apply minimum floor if specified
if ($minScore !== null && $boostedScore < $minScore) {
    $boostedScore = $minScore;
}

// Cap at maximum
$boostedScore = min($maxScore, $boostedScore);

return $boostedScore;
```

**Code Location:** `v2/api/shiftops.php` lines 3022-3054

### calculateDataCompleteness()

**Purpose:** Calculates data completeness multiplier based on available fields.

**Parameters:**

- `$businessData` (array): Business data from Google Places API

**Returns:** `array` - Completeness data with percentage, multiplier, confidence, impact, missing_fields

**Fields Checked:**

- Website (exists)
- Opening hours (exists)
- Reviews (exists and count >0)
- Photos (exists and count >0)

**Code Location:** `v2/api/shiftops.php` lines 3087-3125

### getGradeFromScore()

**Purpose:** Assigns grade based on total score.

**Parameters:**

- `$score` (int): Total score (0-100)

**Returns:** `string` - Grade (A+, A, A-, B+, B, B-, C+, C, C-, D+, D, D-, F)

**Code Location:** `v2/api/shiftops.php` lines 4767-4782

### getBenchmarkComparison()

**Purpose:** Compares score against industry benchmarks.

**Parameters:**

- `$score` (int): Total score
- `$types` (array): Business types

**Returns:** `array` - Benchmark comparison with industry, industry_average, difference, percentile

**Industry Benchmarks:**

- Hospitality: 72
- Retail: 68
- Healthcare: 75
- General: 70

**Code Location:** `v2/api/shiftops.php` lines 4784-4810

### analyzeBusinessHours()

**Purpose:** Analyzes business hours to determine schedule complexity and weekly hours.

**Parameters:**

- `$businessData` (array): Business data

**Returns:** `array` - Hours analysis with weekly_hours, schedule_complexity, hours_completeness, etc.

**Schedule Complexity Levels:**

- `very_high`: Irregular hours OR weekly hours >80
- `high`: Split shifts OR weekly hours >60
- `medium`: Days open >=6 OR weekly hours >40
- `low`: Other

**Code Location:** `v2/api/shiftops.php` lines 4653-4765

### analyzeReviewSentiment()

**Purpose:** Analyzes review sentiment to identify positive/negative mentions.

**Parameters:**

- `$reviews` (array): Array of review objects

**Returns:** `array` - Sentiment analysis with positive_mentions, negative_mentions, staff_mentions, service_mentions, sentiment_score

**Keywords:**

- Positive: gut, toll, super, perfekt, freundlich, schnell, lecker, empfehlenswert, good, great, excellent, friendly, fast, delicious
- Negative: schlecht, langsam, unfreundlich, teuer, schmutzig, laut, bad, slow, unfriendly, expensive, dirty, loud

**Code Location:** `v2/api/shiftops.php` lines 2452-2506

### getSeasonalMultiplier()

**Purpose:** Gets seasonal multiplier based on business type and current month.

**Parameters:**

- `$businessType` (string): Primary business type
- `$month` (int): Current month (1-12)

**Returns:** `float` - Seasonal multiplier (typically 0.6-1.4)

**Code Location:** `v2/api/shiftops.php` lines 3443-3469

### hasWeatherRisk()

**Purpose:** Detects weather risk conditions in forecast.

**Parameters:**

- `$weatherData` (array): Weather data with forecast

**Returns:** `bool` - True if weather risk detected

**Risk Conditions:** snow, storm, rain, thunderstorm

**Code Location:** `v2/api/shiftops.php` lines 3485-3504

## Configuration Constants

### Boost Percentages

Defined in `v2/config/shiftops-customers.php`:

| Constant                      | Value | Pillar                |
| ----------------------------- | ----- | --------------------- |
| `BOOST_SCHEDULING_EFFICIENCY` | 35    | Scheduling Efficiency |
| `BOOST_TIME_TRACKING`         | 35    | Time Tracking Hygiene |
| `BOOST_COMPLIANCE_DOCS`       | 30    | Compliance Docs       |
| `BOOST_ABSENCE_STABILITY`     | 25    | Absence Stability     |
| `BOOST_PAYROLL_READINESS`     | 30    | Payroll Readiness     |

### Maximum Scores

| Constant                  | Value | Pillar                |
| ------------------------- | ----- | --------------------- |
| `MAX_SCORE_SCHEDULING`    | 18    | Scheduling Efficiency |
| `MAX_SCORE_TIME_TRACKING` | 18    | Time Tracking Hygiene |
| `MAX_SCORE_COMPLIANCE`    | 19    | Compliance Docs       |
| `MAX_SCORE_ABSENCE`       | 20    | Absence Stability     |
| `MAX_SCORE_PAYROLL`       | 18    | Payroll Readiness     |
| `MAX_TOTAL_SCORE`         | 95    | Total Score           |

### Minimum Customer Scores

| Constant                           | Value | Pillar                |
| ---------------------------------- | ----- | --------------------- |
| `MIN_SCORE_SCHEDULING_CUSTOMER`    | 14    | Scheduling Efficiency |
| `MIN_SCORE_TIME_TRACKING_CUSTOMER` | 14    | Time Tracking Hygiene |
| `MIN_SCORE_COMPLIANCE_CUSTOMER`    | 15    | Compliance Docs       |
| `MIN_SCORE_ABSENCE_CUSTOMER`       | 15    | Absence Stability     |
| `MIN_SCORE_PAYROLL_CUSTOMER`       | 14    | Payroll Readiness     |

### Baseline Bonus

| Constant                  | Value | Description                                         |
| ------------------------- | ----- | --------------------------------------------------- |
| `CUSTOMER_BASELINE_BONUS` | 3     | Points added to each pillar before percentage boost |

**Code Location:** `v2/config/shiftops-customers.php` lines 41-64

## Industry Benchmarks

### Industry-Specific Baselines

**Scheduling Efficiency:**

- Healthcare: 3 points
- Hospitality: 4 points
- Retail: 5 points
- General: 5 points

**Absence Stability:**

- Healthcare: 4 points
- Hospitality: 5 points
- Retail: 6 points
- General: 6 points

**Time Tracking Hygiene:**

- Healthcare: 3 points
- Hospitality: 3 points
- Retail: 4 points
- General: 4 points

**Compliance Docs:**

- Healthcare: 6 points
- Hospitality: 4 points
- Retail: 5 points
- General: 5 points

**Payroll Readiness:**

- Healthcare: 4 points
- Hospitality: 4 points
- Retail: 5 points
- General: 5 points

### Seasonal Factors

**Hospitality:**

- High season (Jun, Jul, Aug, Dec): Multiplier 1.4
- Low season (Jan, Feb, Nov): Multiplier 0.6

**Retail:**

- High season (Nov, Dec): Multiplier 1.5
- Back to school (Aug, Sep): Multiplier 1.3
- Low season (Jan, Feb): Multiplier 0.7

**Code Location:** `v2/data/industry_benchmarks.php`

## Calculation Examples

### Example 1: Non-Customer Business

**Business Data:**

- Type: Restaurant
- Rating: 4.2
- Reviews: 150
- Website: Yes
- Opening hours: Yes
- Photos: 8
- Weekly hours: 65

**Step 1: Calculate Raw Pillar Scores**

**Scheduling Efficiency:**

- Baseline: 4
- Website: +2
- Moderate Google Business: +1
- Weekly hours (60-80): +4
- Reviews >100: +1
- Rating >=4.0 AND reviews >100: +1
- **Raw Score: 13.0**

**Absence Stability:**

- Baseline: 5
- Rating >=4.0: +3
- Positive sentiment: +2
- Hospitality (non-high season): +2
- **Raw Score: 12.0**

**Time Tracking Hygiene:**

- Baseline: 3
- Website: +2
- Moderate presence: +1
- Schedule complexity (high): +3
- Rating >=4.0: +2
- Reviews >100: +1
- **Raw Score: 12.0**

**Compliance Docs:**

- Baseline: 4
- Hospitality compliance: +5
- Complete fields (>=4): +2
- Moderate presence: +1
- Germany: +2
- Reviews >100: +1
- **Raw Score: 15.0**

**Payroll Readiness:**

- Baseline: 4
- Website: +2
- Digital services (>=1): +1
- Reviews >100: +1
- Reviews >50 AND rating >3.5: +1
- Germany: +2
- **Raw Score: 11.0**

**Step 2: Sum Raw Scores**

- Total: 13.0 + 12.0 + 12.0 + 15.0 + 11.0 = **63.0**

**Step 3: Apply Data Completeness Multiplier**

- Fields complete: 4 (website, hours, reviews, photos)
- Multiplier: 1.0
- Adjusted: 63.0 \* 1.0 = **63.0**

**Step 4: Apply Customer Cap**

- Not a customer, skip

**Step 5: Round Total Score**

- Non-customer: floor(63.0) = **63**

**Step 6: Adjust Pillar Scores**

- Ratio: 63 / 63.0 = 1.0
- Adjusted scores: [13, 12, 12, 15, 11] = **63** ✓

**Step 7: Assign Grade**

- Score 63: **C**

**Final Result:**

- Total Score: 63
- Pillar Scores: [13, 12, 12, 15, 11]
- Grade: C

### Example 2: Ordio Customer Business

**Business Data:**

- Type: Restaurant
- Rating: 4.5
- Reviews: 200
- Website: Yes
- Opening hours: Yes
- Photos: 15
- Weekly hours: 70
- Is Ordio Customer: Yes

**Step 1: Calculate Raw Pillar Scores**

**Scheduling Efficiency:**

- Baseline: 4
- Website: +2
- Online features: +1
- Active Google Business: +2
- Weekly hours (60-80): +4
- Reviews >100: +1
- Rating >=4.0 AND reviews >100: +1
- **Raw Score: 15.0**
- Customer boost: +3 baseline = 18.0
- Percentage boost: 18.0 \* 1.35 = 24.3
- Capped at max: min(24.3, 18) = **18.0**

**Absence Stability:**

- Baseline: 5
- Rating >=4.5: +4
- Positive sentiment: +2
- Hospitality (non-high season): +2
- **Raw Score: 13.0**
- Customer boost: +3 baseline = 16.0
- Percentage boost: 16.0 \* 1.25 = 20.0
- Capped at max: min(20.0, 20) = **20.0**

**Time Tracking Hygiene:**

- Baseline: 3
- Website: +2
- Active presence: +2
- Schedule complexity (high): +3
- Rating >=4.0: +2
- Reviews >100: +1
- Reviews >200 AND rating >3.5: +1
- **Raw Score: 14.0**
- Customer boost: +3 baseline = 17.0
- Percentage boost: 17.0 \* 1.35 = 22.95
- Capped at max: min(22.95, 18) = **18.0**

**Compliance Docs:**

- Baseline: 4
- Hospitality compliance: +5
- Complete fields (>=4): +2
- Active presence: +2
- Germany: +2
- Reviews >100: +1
- **Raw Score: 16.0**
- Customer boost: +3 baseline = 19.0
- Percentage boost: 19.0 \* 1.30 = 24.7
- Capped at max: min(24.7, 19) = **19.0**

**Payroll Readiness:**

- Baseline: 4
- Website: +2
- Payment features: +2
- Digital services (>=2): +2
- Reviews >200: +2
- Reviews >150 AND rating >3.8: +2
- Germany: +2
- **Raw Score: 16.0**
- Customer boost: +3 baseline = 19.0
- Percentage boost: 19.0 \* 1.30 = 24.7
- Capped at max: min(24.7, 18) = **18.0**

**Step 2: Sum Raw Scores**

- Total: 18.0 + 20.0 + 18.0 + 19.0 + 18.0 = **93.0**

**Step 3: Apply Data Completeness Multiplier**

- Fields complete: 4
- Multiplier: 1.0
- Customer adjustment: max(0.98, 1.0) = 1.0
- Adjusted: 93.0 \* 1.0 = **93.0**

**Step 4: Apply Customer Cap**

- Customer cap: min(93.0, 95) = **93.0**

**Step 5: Round Total Score**

- Customer: round(93.0) = **93**

**Step 6: Adjust Pillar Scores**

- Ratio: 93 / 93.0 = 1.0
- Adjusted scores: [18, 20, 18, 19, 18] = **93** ✓

**Step 7: Assign Grade**

- Score 93: **A+**

**Final Result:**

- Total Score: 93
- Pillar Scores: [18, 20, 18, 19, 18]
- Grade: A+

### Example 3: Partial Data Mode

**Business Data:**

- Type: Store
- Rating: 3.8
- Reviews: 50
- Website: Yes
- Opening hours: No
- Photos: 3
- Weekly hours: Unknown

**Calculation Mode:** Partial (simplified)

**Scheduling Efficiency:**

- Base: 5
- Website: +3
- Moderate presence: +1
- Opening hours: +2 (has opening hours data)
- **Raw Score: 11.0**

**Absence Stability:**

- Base: 6
- Rating >=3.5: +2
- Reviews >50: +1
- **Raw Score: 9.0**

**Time Tracking Hygiene:**

- Base: 4
- Website: +3
- Moderate presence: +1
- Opening hours: +2
- Reviews >100: +1
- **Raw Score: 11.0**

**Compliance Docs:**

- Base: 5
- Complete fields (>=3): +2
- Moderate presence: +1
- **Raw Score: 8.0**

**Payroll Readiness:**

- Base: 5
- Website: +3
- Reviews >50: +1
- **Raw Score: 9.0**

**Total:** 11.0 + 9.0 + 11.0 + 8.0 + 9.0 = **48.0**

**Data Completeness:**

- Fields complete: 3 (website, reviews, photos)
- Multiplier: 0.85
- Adjusted: 48.0 \* 0.85 = **40.8**

**Rounded:** floor(40.8) = **40**

**Adjusted Pillars:** [9, 8, 9, 7, 7] = **40** ✓

**Grade:** D

### Example 4: Fallback Mode

**Business Data:**

- Type: Unknown
- Rating: 4.0
- Reviews: 25
- Website: Yes
- Opening hours: Unknown
- Photos: 2

**Calculation Mode:** Fallback (minimal)

**Base Score:** 40

**Adjustments:**

- Rating >=4.0: +10
- Reviews >0: +1
- Website: +5
- Photos >0: +2

**Total:** 40 + 10 + 1 + 5 + 2 = **58**

**Clamped:** max(20, min(95, 58)) = **58**

**Distributed:** [12, 12, 12, 11, 11] = **58** ✓

**Grade:** C

## Edge Cases

### Zero Scores Handling

If a pillar score is 0 or negative:

- Customer boost is NOT applied
- Score remains 0
- Pillar adjustment algorithm handles zeros correctly

### Missing Data Handling

**Partial Mode:**

- Uses simplified calculations
- Avoids complex dependencies
- Still applies data completeness multiplier

**Fallback Mode:**

- Uses minimal indicators
- Distributes score evenly across pillars
- Applies basic data completeness check

### Customer Boost Edge Cases

**Zero Score:**

- No boost applied
- Score remains 0

**Score Below Minimum:**

- Minimum floor applied after boost
- Ensures customers meet minimum standards

**Score Above Maximum:**

- Maximum cap applied
- Maintains realism

### Data Completeness Edge Cases

**All Fields Missing:**

- Multiplier: 0.50
- High impact on final score

**Customer with Missing Website:**

- Uses 0.94 multiplier (instead of 0.85)
- Reflects digital tool usage

**Customer with Website:**

- Uses max(0.98, multiplier)
- Minimal penalty for missing other fields

## Partial and Fallback Scoring

### Partial Score Calculation

**When Used:** When full calculation fails but basic data is available

**Method:** `calculatePartialScoreFromData()`

**Characteristics:**

- Simplified pillar calculations
- Avoids complex dependencies
- Still applies customer boost (simplified: +25% per pillar)
- Uses data completeness multiplier
- Adjusts pillar scores proportionally

**Code Location:** `v2/api/shiftops.php` lines 2716-2823

### Fallback Score Calculation

**When Used:** When both full and partial calculations fail

**Method:** `calculateFallbackScore()`

**Characteristics:**

- Very basic scoring based on minimal indicators
- Base score: 40
- Adjustments based on rating, review count, digital presence
- Distributes evenly across pillars
- Clamps to valid range (20-95)

**Code Location:** `v2/api/shiftops.php` lines 2829-2902

## Related Documentation

- [ShiftOps Architecture](SHIFTOPS_ARCHITECTURE.md) - System architecture overview
- [ShiftOps Components](SHIFTOPS_COMPONENTS.md) - Component documentation
- [ShiftOps Developer Guide](SHIFTOPS_DEVELOPER_GUIDE.md) - Development workflow
- [ShiftOps Quick Reference](SHIFTOPS_ai//QUICK_REFERENCE.md) - Quick lookup guide

## Code Locations

### Main Scoring Methods

- `calculateShiftOpsScore()`: `v2/api/shiftops.php` lines 2594-2710
- `calculateSchedulingScoreRaw()`: `v2/api/shiftops.php` lines 3145-3254
- `calculateAbsenceScoreRaw()`: `v2/api/shiftops.php` lines 3287-3385
- `calculateTimeTrackingScoreRaw()`: `v2/api/shiftops.php` lines 3509-3586
- `calculateComplianceScoreRaw()`: `v2/api/shiftops.php` lines 3671-3767
- `calculatePayrollScoreRaw()`: `v2/api/shiftops.php` lines 3785-3896

### Helper Methods

- `adjustPillarScoresToMatchTotal()`: `v2/api/shiftops.php` lines 2912-3011
- `applyCustomerBoostRaw()`: `v2/api/shiftops.php` lines 3022-3054
- `calculateDataCompleteness()`: `v2/api/shiftops.php` lines 3087-3125
- `getGradeFromScore()`: `v2/api/shiftops.php` lines 4767-4782
- `getBenchmarkComparison()`: `v2/api/shiftops.php` lines 4784-4810
- `analyzeBusinessHours()`: `v2/api/shiftops.php` lines 4653-4765
- `analyzeReviewSentiment()`: `v2/api/shiftops.php` lines 2452-2506
- `getSeasonalMultiplier()`: `v2/api/shiftops.php` lines 3443-3469
- `hasWeatherRisk()`: `v2/api/shiftops.php` lines 3485-3504

### Configuration

- Configuration constants: `v2/config/shiftops-customers.php` lines 41-64
- Industry benchmarks: `v2/data/industry_benchmarks.php`
