[
  {
    "type": "create_table",
    "description": "Create storeStickinessDaily rollup table for the internal Stickiness Dashboard (one row per store per day)",
    "database": "kiosk_buykiosk",
    "check_query": "SHOW TABLES LIKE 'storeStickinessDaily'",
    "sql": "CREATE TABLE `storeStickinessDaily` (\n  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n  `typeNum` varchar(10) NOT NULL COMMENT 'Store identifier',\n  `snapshotDate` date NOT NULL COMMENT 'Date this snapshot represents',\n  `stickinessScore` tinyint(3) unsigned NOT NULL DEFAULT 0 COMMENT '0-100 durable-feature anchoring',\n  `churnRiskScore` tinyint(3) unsigned NOT NULL DEFAULT 0 COMMENT '0-100, higher = worse',\n  `churnRiskLabel` enum('low','medium','high','critical') NOT NULL DEFAULT 'medium',\n  `segment` varchar(40) DEFAULT NULL COMMENT 'Primary segment classification',\n  `scoreBackstock` tinyint(3) unsigned NOT NULL DEFAULT 0,\n  `scoreScheduling` tinyint(3) unsigned NOT NULL DEFAULT 0,\n  `scoreTimeclock` tinyint(3) unsigned NOT NULL DEFAULT 0,\n  `scorePayroll` tinyint(3) unsigned NOT NULL DEFAULT 0,\n  `scoreSignage` tinyint(3) unsigned NOT NULL DEFAULT 0,\n  `scoreCheckin` tinyint(3) unsigned NOT NULL DEFAULT 0,\n  `scoreHardware` tinyint(3) unsigned NOT NULL DEFAULT 0,\n  `scoreLabels` tinyint(3) unsigned NOT NULL DEFAULT 0,\n  `scoreSurveys` tinyint(3) unsigned NOT NULL DEFAULT 0,\n  `scoreReports` tinyint(3) unsigned NOT NULL DEFAULT 0,\n  `scoreMultiStore` tinyint(3) unsigned NOT NULL DEFAULT 0,\n  `replaceableDependence` tinyint(3) unsigned NOT NULL DEFAULT 0 COMMENT '0-100 share of activity in POS-replaceable features',\n  `qrDependence` tinyint(3) unsigned NOT NULL DEFAULT 0 COMMENT '0-100 QR/mobile share of check-ins',\n  `usageTrend` enum('up','flat','down') NOT NULL DEFAULT 'flat',\n  `lastCheckinAt` datetime DEFAULT NULL,\n  `lastSignageUpdateAt` datetime DEFAULT NULL,\n  `lastScheduleCreatedAt` datetime DEFAULT NULL,\n  `lastBackstockActivityAt` datetime DEFAULT NULL,\n  `lastTimePunchAt` datetime DEFAULT NULL,\n  `lastAdminLoginAt` datetime DEFAULT NULL,\n  `lastSurveyResponseAt` datetime DEFAULT NULL,\n  `lastCloseReportAt` datetime DEFAULT NULL,\n  `lastDeviceSeenAt` datetime DEFAULT NULL,\n  `deadDeviceFlag` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Was active 30-60d ago, silent in last 14d',\n  `activeDevices` smallint(5) unsigned NOT NULL DEFAULT 0,\n  `uptimePct` tinyint(3) unsigned NOT NULL DEFAULT 0,\n  `checkins30d` int(10) unsigned NOT NULL DEFAULT 0,\n  `checkinsPrev30d` int(10) unsigned NOT NULL DEFAULT 0,\n  `qrCheckins30d` int(10) unsigned NOT NULL DEFAULT 0,\n  `mrr` decimal(10,2) NOT NULL DEFAULT 0.00,\n  `billingActive` tinyint(1) NOT NULL DEFAULT 1,\n  `active` tinyint(1) NOT NULL DEFAULT 1,\n  `nextBillingDate` date DEFAULT NULL,\n  `ownerUserId` int(10) unsigned DEFAULT NULL COMMENT 'uf users.id of primary owner (for account rollup)',\n  `ownerStoreCount` smallint(5) unsigned NOT NULL DEFAULT 1,\n  `nextBestAction` varchar(120) DEFAULT NULL,\n  `computedAt` datetime NOT NULL DEFAULT current_timestamp(),\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `uk_typeNum_date` (`typeNum`, `snapshotDate`),\n  KEY `idx_date_risk` (`snapshotDate`, `churnRiskLabel`),\n  KEY `idx_owner` (`snapshotDate`, `ownerUserId`),\n  KEY `idx_segment` (`snapshotDate`, `segment`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Daily store stickiness / churn-risk rollup (internal dashboard)'"
  },
  {
    "type": "create_table",
    "description": "Create storeDeviceHeartbeat table for passive kiosk device-uptime tracking (server-side, no device code change)",
    "database": "kiosk_buykiosk",
    "check_query": "SHOW TABLES LIKE 'storeDeviceHeartbeat'",
    "sql": "CREATE TABLE `storeDeviceHeartbeat` (\n  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,\n  `typeNum` varchar(10) NOT NULL COMMENT 'Store identifier',\n  `deviceFingerprint` varchar(64) NOT NULL COMMENT 'Session id or hashed IP+UA',\n  `firstSeenAt` datetime NOT NULL DEFAULT current_timestamp(),\n  `lastSeenAt` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),\n  `lastRoute` varchar(120) DEFAULT NULL,\n  `source` enum('http','ably','checkin') NOT NULL DEFAULT 'http',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `uk_store_device` (`typeNum`, `deviceFingerprint`),\n  KEY `idx_store_lastseen` (`typeNum`, `lastSeenAt`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Passive per-device heartbeat for kiosk uptime'"
  },
  {
    "type": "insert",
    "description": "Register the nightly stickiness-rollup job definition (02:30 UTC daily)",
    "database": "kiosk_buykiosk",
    "check_query": "SELECT 1 FROM task_job_definitions WHERE name = 'stickiness:rollup' LIMIT 1",
    "sql": "INSERT IGNORE INTO `task_job_definitions` (`name`, `displayName`, `className`, `schedule`, `queue`, `scope`, `timeout`, `maxRetries`, `retryBackoff`, `config`, `isEnabled`, `notifyOnFailure`, `notifyEmails`) VALUES ('stickiness:rollup', 'Stickiness Rollup', 'BuyerKiosk\\\\Stickiness\\\\Jobs\\\\StickinessRollupJob', '30 2 * * *', 'low', 'global', 900, 2, 120, '{}', 1, 1, NULL)"
  }
]
