-- Dumping data for table `hr_mod_roster`
--

INSERT INTO `hr_mod_roster` VALUES (1,1,'2026-07-08','day',514,546,'2026-07-08 20:14:02','2026-07-08 20:14:02'),(2,1,'2026-07-08','night',504,546,'2026-07-08 20:14:02','2026-07-08 20:14:02'),(3,1,'2026-07-09','day',514,546,'2026-07-08 20:14:02','2026-07-08 20:14:02'),(4,1,'2026-07-09','night',504,546,'2026-07-08 20:14:02','2026-07-08 20:14:02'),(5,1,'2026-07-10','day',514,546,'2026-07-08 20:14:02','2026-07-08 20:14:02'),(6,1,'2026-07-10','night',504,546,'2026-07-08 20:14:02','2026-07-08 20:14:02');

--
-- Table structure for table `hr_onboarding`
--

CREATE TABLE `hr_onboarding` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `employee_id` int(10) unsigned NOT NULL,
  `checklist` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'json: d1/d7/d30/d60/d90' CHECK (json_valid(`checklist`)),
  `buddy_id` int(10) unsigned DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_hr_onboarding_employee` (`employee_id`),
  KEY `idx_hr_onboarding_buddy` (`buddy_id`),
  CONSTRAINT `fk_hr_onboarding_buddy` FOREIGN KEY (`buddy_id`) REFERENCES `hr_employees` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_hr_onboarding_employee` FOREIGN KEY (`employee_id`) REFERENCES `hr_employees` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `hr_onboarding`
--

INSERT INTO `hr_onboarding` VALUES (1,6,'{\"d1\": [{\"label\": \"Serah terima seragam & locker\", \"done\": true}, {\"label\": \"Perkenalan tim & buddy\", \"done\": true}, {\"label\": \"Tur area kerja\", \"done\": true}], \"d7\": [{\"label\": \"Selesai course faculty GEN\", \"done\": true}, {\"label\": \"Cek kelengkapan dokumen\", \"done\": false}], \"d30\": [{\"label\": \"Review kinerja awal dengan supervisor\", \"done\": false}], \"d60\": [{\"label\": \"Assessment kompetensi dasar posisi\", \"done\": false}], \"d90\": [{\"label\": \"Evaluasi akhir masa percobaan\", \"done\": false}]}',3,'2026-07-08 20:14:02','2026-07-08 20:14:02');

--
-- Table structure for table `hr_payroll_items`
--

CREATE TABLE `hr_payroll_items` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `period_id` int(10) unsigned NOT NULL,
  `employee_id` int(10) unsigned NOT NULL,
  `earnings` text DEFAULT NULL COMMENT 'ciphertext JSON',
  `deductions` text DEFAULT NULL COMMENT 'ciphertext JSON',
  `employer_costs` text DEFAULT NULL COMMENT 'ciphertext JSON',
  `gross` text DEFAULT NULL COMMENT 'ciphertext (nominal)',
  `net` text DEFAULT NULL COMMENT 'ciphertext (nominal)',
  `pph21` text DEFAULT NULL COMMENT 'ciphertext (nominal)',
  `published_at` datetime DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_hr_payroll_items_period_employee` (`period_id`,`employee_id`),
  KEY `idx_hr_payroll_items_employee` (`employee_id`),
  CONSTRAINT `fk_hr_payroll_items_employee` FOREIGN KEY (`employee_id`) REFERENCES `hr_employees` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_hr_payroll_items_period` FOREIGN KEY (`period_id`) REFERENCES `hr_payroll_periods` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `hr_payroll_items`
--


--
-- Table structure for table `hr_payroll_params`
--

CREATE TABLE `hr_payroll_params` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `param_key` varchar(60) NOT NULL COMMENT 'bpjs_kes_pct|jht_pct|jp_cap|umk|ot_divisor|...',
  `value` varchar(60) NOT NULL,
  `effective_from` date NOT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_hr_payroll_params_property_key_from` (`property_id`,`param_key`,`effective_from`),
  CONSTRAINT `fk_hr_payroll_params_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `hr_payroll_params`
--

INSERT INTO `hr_payroll_params` VALUES (1,1,'bpjs_kes_employee_pct','1','2026-01-01','2026-07-08 18:57:12'),(2,1,'bpjs_kes_employer_pct','4','2026-01-01','2026-07-08 18:57:12'),(3,1,'bpjs_kes_cap','12000000','2026-01-01','2026-07-08 18:57:12'),(4,1,'jht_employee_pct','2','2026-01-01','2026-07-08 18:57:12'),(5,1,'jht_employer_pct','3.7','2026-01-01','2026-07-08 18:57:12'),(6,1,'jp_employee_pct','1','2026-01-01','2026-07-08 18:57:12'),(7,1,'jp_employer_pct','2','2026-01-01','2026-07-08 18:57:12'),(8,1,'jkk_pct','0.24','2026-01-01','2026-07-08 18:57:12'),(9,1,'jkm_pct','0.3','2026-01-01','2026-07-08 18:57:12'),(10,1,'ot_divisor','173','2026-01-01','2026-07-08 18:57:12'),(11,1,'umk','0','2026-01-01','2026-07-08 18:57:12');

--
-- Table structure for table `hr_payroll_periods`
--

CREATE TABLE `hr_payroll_periods` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `month` char(7) NOT NULL COMMENT 'YYYY-MM',
  `cutoff` date NOT NULL,
  `status` enum('draft','review','approved','locked') NOT NULL DEFAULT 'draft',
  `approvals` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`approvals`)),
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_hr_payroll_periods_property_month` (`property_id`,`month`),
  CONSTRAINT `fk_hr_payroll_periods_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `hr_payroll_periods`
--

INSERT INTO `hr_payroll_periods` VALUES (1,1,'2026-06','2026-06-30','draft',NULL,'2026-07-08 20:14:02','2026-07-08 20:14:02');

--
-- Table structure for table `hr_positions`
--

CREATE TABLE `hr_positions` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `name` varchar(150) NOT NULL,
  `department` varchar(60) NOT NULL,
  `level` enum('staff','coordinator','hod','manager','director') NOT NULL DEFAULT 'staff',
  `jobdesc_code` varchar(30) DEFAULT NULL COMMENT 'kode jobdesk mis. HK-RA-01 (dokumen versi di hotelcrew/docs/jobdesk)',
  `jobdesc_version` int(10) unsigned DEFAULT NULL,
  `required_competencies` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'array kode kompetensi wajib mis. ["HK-01","HK-18"]' CHECK (json_valid(`required_competencies`)),
  `min_wage_grade` varchar(30) DEFAULT NULL,
  `active` tinyint(1) NOT NULL DEFAULT 1,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_hr_positions_property_dept` (`property_id`,`department`),
  CONSTRAINT `fk_hr_positions_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `hr_positions`
--

INSERT INTO `hr_positions` VALUES (1,1,'Room Attendant','housekeeping','staff','HK-RA-01',3,'[\"GEN-CORE\",\"HK-01\",\"HK-03\",\"HK-04\",\"HK-08\",\"HK-14\",\"HK-15\",\"GEN-18\"]',NULL,1,'2026-07-08 18:57:12','2026-07-08 19:12:49'),(2,1,'Public Area Attendant','housekeeping','staff','HK-PA-01',2,'[\"GEN-CORE\",\"HK-08\",\"HK-09\",\"HK-10\",\"HK-14\",\"HK-16\",\"HK-17\",\"GEN-18\"]',NULL,1,'2026-07-08 18:57:12','2026-07-08 19:12:49'),(3,1,'Linen Attendant','housekeeping','staff','HK-LN-01',2,'[\"GEN-CORE\",\"HK-12\",\"HK-20\",\"HK-13\"]',NULL,1,'2026-07-08 18:57:12','2026-07-08 19:12:49'),(4,1,'HK Coordinator','housekeeping','coordinator','HK-CRD-01',2,'[\"GEN-CORE\",\"HK-01\",\"HK-18\",\"HK-19\",\"HK-10\",\"HK-20\",\"LDR-01\",\"LDR-02\",\"LDR-04\",\"LDR-05\",\"LDR-07\"]',NULL,1,'2026-07-08 18:57:12','2026-07-08 19:12:49'),(5,1,'Executive Housekeeper','housekeeping','hod','HK-EHK-01',2,'[\"GEN-CORE\",\"HK-01\",\"HK-18\",\"HK-19\",\"HK-20\",\"LDR-01\",\"LDR-02\",\"LDR-04\",\"LDR-07\"]',NULL,1,'2026-07-08 18:57:12','2026-07-08 19:12:49');

--
-- Table structure for table `hr_roster`
--

CREATE TABLE `hr_roster` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `employee_id` int(10) unsigned NOT NULL,
  `date` date NOT NULL,
  `shift_id` int(10) unsigned NOT NULL,
  `published_at` datetime DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_hr_roster_employee_date` (`employee_id`,`date`),
  KEY `idx_hr_roster_property_date` (`property_id`,`date`),
  KEY `idx_hr_roster_shift` (`shift_id`),
  CONSTRAINT `fk_hr_roster_employee` FOREIGN KEY (`employee_id`) REFERENCES `hr_employees` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_hr_roster_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_hr_roster_shift` FOREIGN KEY (`shift_id`) REFERENCES `hr_shifts` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=85 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `hr_roster`
--

INSERT INTO `hr_roster` VALUES (1,1,3,'2026-07-07',1,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(2,1,3,'2026-07-08',1,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(3,1,3,'2026-07-09',1,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(4,1,3,'2026-07-10',2,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(5,1,3,'2026-07-11',2,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(6,1,3,'2026-07-12',5,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(7,1,3,'2026-07-13',1,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(8,1,4,'2026-07-07',2,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(9,1,4,'2026-07-08',2,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(10,1,4,'2026-07-09',5,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(11,1,4,'2026-07-10',1,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(12,1,4,'2026-07-11',1,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(13,1,4,'2026-07-12',1,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(14,1,4,'2026-07-13',2,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(15,1,5,'2026-07-07',1,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(16,1,5,'2026-07-08',5,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(17,1,5,'2026-07-09',1,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(18,1,5,'2026-07-10',1,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(19,1,5,'2026-07-11',2,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(20,1,5,'2026-07-12',2,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(21,1,5,'2026-07-13',2,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(22,1,6,'2026-07-07',2,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(23,1,6,'2026-07-08',2,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(24,1,6,'2026-07-09',2,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(25,1,6,'2026-07-10',5,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(26,1,6,'2026-07-11',1,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(27,1,6,'2026-07-12',1,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(28,1,6,'2026-07-13',1,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(29,1,7,'2026-07-07',1,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(30,1,7,'2026-07-08',1,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(31,1,7,'2026-07-09',1,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(32,1,7,'2026-07-10',1,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(33,1,7,'2026-07-11',1,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(34,1,7,'2026-07-12',5,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(35,1,7,'2026-07-13',2,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(36,1,8,'2026-07-07',1,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(37,1,8,'2026-07-08',1,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(38,1,8,'2026-07-09',1,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(39,1,8,'2026-07-10',1,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(40,1,8,'2026-07-11',5,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(41,1,8,'2026-07-12',1,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(42,1,8,'2026-07-13',1,'2026-07-05 10:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(43,1,3,'2026-07-14',2,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(44,1,3,'2026-07-15',2,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(45,1,3,'2026-07-16',5,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(46,1,3,'2026-07-17',1,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(47,1,3,'2026-07-18',1,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(48,1,3,'2026-07-19',1,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(49,1,3,'2026-07-20',2,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(50,1,4,'2026-07-14',1,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(51,1,4,'2026-07-15',1,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(52,1,4,'2026-07-16',1,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(53,1,4,'2026-07-17',2,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(54,1,4,'2026-07-18',5,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(55,1,4,'2026-07-19',2,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(56,1,4,'2026-07-20',1,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(57,1,5,'2026-07-14',2,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(58,1,5,'2026-07-15',2,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(59,1,5,'2026-07-16',2,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(60,1,5,'2026-07-17',5,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(61,1,5,'2026-07-18',1,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(62,1,5,'2026-07-19',1,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(63,1,5,'2026-07-20',2,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(64,1,6,'2026-07-14',1,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(65,1,6,'2026-07-15',5,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(66,1,6,'2026-07-16',1,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(67,1,6,'2026-07-17',2,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(68,1,6,'2026-07-18',2,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(69,1,6,'2026-07-19',1,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(70,1,6,'2026-07-20',1,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(71,1,7,'2026-07-14',1,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(72,1,7,'2026-07-15',1,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(73,1,7,'2026-07-16',1,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(74,1,7,'2026-07-17',1,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(75,1,7,'2026-07-18',5,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(76,1,7,'2026-07-19',2,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(77,1,7,'2026-07-20',1,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(78,1,8,'2026-07-14',1,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(79,1,8,'2026-07-15',1,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(80,1,8,'2026-07-16',5,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(81,1,8,'2026-07-17',1,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(82,1,8,'2026-07-18',1,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(83,1,8,'2026-07-19',2,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46'),(84,1,8,'2026-07-20',1,'2026-07-08 19:08:46','2026-07-08 19:08:46','2026-07-08 19:08:46');

--
-- Table structure for table `hr_service_charge`
--

CREATE TABLE `hr_service_charge` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `period_id` int(10) unsigned NOT NULL,
  `total_collected` decimal(16,2) NOT NULL DEFAULT 0.00,
  `risk_pct` decimal(5,2) NOT NULL DEFAULT 0.00,
  `hr_dev_pct` decimal(5,2) NOT NULL DEFAULT 0.00,
  `dist_method` enum('point','equal','grade_weighted') NOT NULL DEFAULT 'point',
  `point_value` decimal(14,4) DEFAULT NULL,
  `detail` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'per employee: {employee_id, points, amount}' CHECK (json_valid(`detail`)),
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_hr_service_charge_period` (`period_id`),
  CONSTRAINT `fk_hr_service_charge_period` FOREIGN KEY (`period_id`) REFERENCES `hr_payroll_periods` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `hr_service_charge`
--

INSERT INTO `hr_service_charge` VALUES (1,1,42000000.00,5.00,3.00,'point',966000.0000,'[{\"employee_id\": 1, \"points\": 5, \"amount\": 4830000, \"note\": \"DUMMY demo\"}, {\"employee_id\": 2, \"points\": 5, \"amount\": 4830000, \"note\": \"DUMMY demo\"}, {\"employee_id\": 3, \"points\": 5, \"amount\": 4830000, \"note\": \"DUMMY demo\"}, {\"employee_id\": 4, \"points\": 5, \"amount\": 4830000, \"note\": \"DUMMY demo\"}, {\"employee_id\": 5, \"points\": 5, \"amount\": 4830000, \"note\": \"DUMMY demo\"}, {\"employee_id\": 6, \"points\": 5, \"amount\": 4830000, \"note\": \"DUMMY demo\"}, {\"employee_id\": 7, \"points\": 5, \"amount\": 4830000, \"note\": \"DUMMY demo\"}, {\"employee_id\": 8, \"points\": 5, \"amount\": 4830000, \"note\": \"DUMMY demo\"}]','2026-07-08 20:14:02','2026-07-08 20:14:02');

--
-- Table structure for table `hr_shift_swaps`
--

CREATE TABLE `hr_shift_swaps` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `requester_id` int(10) unsigned NOT NULL,
  `partner_id` int(10) unsigned NOT NULL,
  `date` date NOT NULL,
  `status` enum('pending','approved','rejected','cancelled') NOT NULL DEFAULT 'pending',
  `approvals` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`approvals`)),
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_hr_shift_swaps_property_date` (`property_id`,`date`),
  KEY `idx_hr_shift_swaps_requester` (`requester_id`),
  KEY `idx_hr_shift_swaps_partner` (`partner_id`),
  CONSTRAINT `fk_hr_shift_swaps_partner` FOREIGN KEY (`partner_id`) REFERENCES `hr_employees` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_hr_shift_swaps_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_hr_shift_swaps_requester` FOREIGN KEY (`requester_id`) REFERENCES `hr_employees` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `hr_shift_swaps`
--

INSERT INTO `hr_shift_swaps` VALUES (1,1,4,5,'2026-07-11','pending',NULL,'2026-07-08 20:14:02','2026-07-08 20:14:02');

--
-- Table structure for table `hr_shifts`
--

CREATE TABLE `hr_shifts` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `department` varchar(60) NOT NULL,
  `code` enum('M','A','N','M2','OFF','PH') NOT NULL,
  `start_time` time DEFAULT NULL,
  `end_time` time DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_hr_shifts_property_dept_code` (`property_id`,`department`,`code`),
  KEY `idx_hr_shifts_property_dept` (`property_id`,`department`),
  CONSTRAINT `fk_hr_shifts_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `hr_shifts`
--

INSERT INTO `hr_shifts` VALUES (1,1,'housekeeping','M','07:00:00','15:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(2,1,'housekeeping','A','14:00:00','22:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(3,1,'housekeeping','N','22:00:00','06:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(4,1,'housekeeping','M2','09:00:00','17:00:00','2026-07-08 18:57:12','2026-07-08 18:57:12'),(5,1,'housekeeping','OFF',NULL,NULL,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(6,1,'housekeeping','PH',NULL,NULL,'2026-07-08 18:57:12','2026-07-08 18:57:12');

--
-- Table structure for table `hr_task_stage_log`
--

CREATE TABLE `hr_task_stage_log` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `task_id` bigint(20) unsigned NOT NULL,
  `stage` varchar(50) NOT NULL,
  `note` varchar(255) DEFAULT NULL,
  `by_user_id` int(10) unsigned DEFAULT NULL,
  `at` datetime NOT NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_hr_task_stage_log_task_at` (`task_id`,`at`),
  KEY `fk_hr_task_stage_log_user` (`by_user_id`),
  CONSTRAINT `fk_hr_task_stage_log_task` FOREIGN KEY (`task_id`) REFERENCES `hr_tasks` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_hr_task_stage_log_user` FOREIGN KEY (`by_user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `hr_task_stage_log`
--

INSERT INTO `hr_task_stage_log` VALUES (1,9,'diminta','Linen Attendant melapor stok amenities tinggal 3 hari (DUMMY demo).',530,'2026-07-05 23:34:49'),(2,9,'di_po','PO diajukan ke purchasing, menunggu konfirmasi vendor (DUMMY demo).',546,'2026-07-07 23:34:49'),(3,6,'reminder','Reminder H-60 otomatis dari cron kontrak SELL (DUMMY demo).',NULL,'2026-07-01 23:34:49');

--
-- Table structure for table `hr_task_templates`
--

CREATE TABLE `hr_task_templates` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `department` varchar(60) NOT NULL COMMENT 'kode departemen (match hr_departments.code / hr_tasks.department / hr_kpi_definitions.department) — dipakai kaitan KPI otomatis',
  `jobdesk_id` int(10) unsigned DEFAULT NULL COMMENT 'FK hr_positions(id). "jobdesk" = posisi (tak ada tabel hr_jobdesks). NULL = tugas lintas jobdesk',
  `title` varchar(200) NOT NULL,
  `description` text DEFAULT NULL,
  `frequency_type` enum('daily','weekly','monthly') NOT NULL DEFAULT 'daily' COMMENT 'subset nilai pm_schedules.frequency_type (konsistensi)',
  `frequency_detail` varchar(20) DEFAULT NULL COMMENT 'daily=NULL; weekly=CSV hari ISO 1-7 (Sen=1, sama pm_schedules.weekly_days); monthly=tanggal 1-31 (clamp akhir bulan, sama pm_schedules.monthly_day)',
  `assignee_type` enum('employee','department') NOT NULL DEFAULT 'department' COMMENT 'employee=tugas ke 1 karyawan; department=tugas milik departemen (tampil di kolom papan per-dept, assignee kosong)',
  `assignee_ref` varchar(60) NOT NULL COMMENT 'assignee_type=employee -> hr_employees.id (di-resolve ke users.id saat generasi); assignee_type=department -> kode departemen',
  `kpi_definition_id` int(10) unsigned DEFAULT NULL COMMENT 'FK hr_kpi_definitions. NULL = auto-resolve per departemen di TaskBoardService::createTask (0019)',
  `priority` enum('low','normal','high','urgent') NOT NULL DEFAULT 'normal',
  `active` tinyint(1) NOT NULL DEFAULT 1,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_htt_property_active` (`property_id`,`active`),
  KEY `idx_htt_property_dept` (`property_id`,`department`),
  KEY `idx_htt_jobdesk` (`jobdesk_id`),
  KEY `idx_htt_kpi` (`kpi_definition_id`),
  CONSTRAINT `fk_htt_jobdesk` FOREIGN KEY (`jobdesk_id`) REFERENCES `hr_positions` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_htt_kpi` FOREIGN KEY (`kpi_definition_id`) REFERENCES `hr_kpi_definitions` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_htt_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `hr_task_templates`
--

INSERT INTO `hr_task_templates` VALUES (1,1,'housekeeping',NULL,'Cek kelengkapan & kebersihan stok linen tiap shift (DUMMY demo)','Supervisor housekeeping memeriksa stok linen (sheet, towel, pillowcase) awal shift; catat kekurangan (DUMMY demo — tugas rutin harian).','daily',NULL,'department','housekeeping',NULL,'normal',1,'2026-07-09 16:53:37','2026-07-09 16:53:37'),(2,1,'front_office',NULL,'Cek stok amenity & perlengkapan front desk tiap pagi (DUMMY demo)','Resepsionis memeriksa stok amenity welcome drink, form, kartu kunci setiap pagi; ajukan permintaan bila menipis (DUMMY demo — tugas rutin harian).','daily',NULL,'department','front_office',NULL,'low',1,'2026-07-09 16:53:37','2026-07-09 16:53:37');

--
-- Table structure for table `hr_tasks`
--

CREATE TABLE `hr_tasks` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `source` enum('briefing','intake','manual') NOT NULL DEFAULT 'manual',
  `source_app` enum('crew','sell') NOT NULL DEFAULT 'crew' COMMENT 'kontrak papan task terpadu PM-PLAN §4',
  `kind` enum('instant','staged') NOT NULL DEFAULT 'instant' COMMENT 'instant = selesai sekali aksi; staged = melalui tahapan journey_template',
  `journey_template` varchar(50) DEFAULT NULL COMMENT 'key template journey (App\\Support\\TaskJourneys) — wajib diisi bila kind=staged',
  `current_stage` varchar(50) DEFAULT NULL COMMENT 'stage aktif (key di template journey_template) — NULL bila kind=instant',
  `source_ref` varchar(100) DEFAULT NULL COMMENT 'referensi bebas ke record asal, mis. mkt_quotations:123',
  `title` varchar(200) NOT NULL,
  `description` text DEFAULT NULL,
  `department` varchar(60) DEFAULT NULL,
  `assignee_id` int(10) unsigned DEFAULT NULL,
  `due_date` date DEFAULT NULL,
  `priority` enum('low','normal','high','urgent') NOT NULL DEFAULT 'normal',
  `status` enum('open','in_progress','done','overdue','cancelled','not_done') NOT NULL DEFAULT 'open' COMMENT 'label tampilan: open=Menunggu, in_progress=On Progress, done=Done, not_done=Not Done, cancelled=Cancel. overdue DEPRECATED (baris lama saja) -- kini FLAG turunan due_date, bukan status.',
  `progress_notes` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`progress_notes`)),
  `hotelfix_wo_id` bigint(20) unsigned DEFAULT NULL,
  `kpi_definition_id` int(10) unsigned DEFAULT NULL COMMENT 'kaitan opsional ke hr_kpi_definitions — dipakai HrKpiService::completionStats()',
  `verified_by` int(10) unsigned DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_hr_tasks_property_status_due` (`property_id`,`status`,`due_date`),
  KEY `idx_hr_tasks_property_source_app` (`property_id`,`source_app`),
  KEY `idx_hr_tasks_assignee` (`assignee_id`),
  KEY `idx_hr_tasks_hotelfix_wo` (`hotelfix_wo_id`),
  KEY `fk_hr_tasks_verified_by` (`verified_by`),
  KEY `idx_hr_tasks_kpi_definition` (`kpi_definition_id`),
  KEY `idx_hr_tasks_kind` (`property_id`,`kind`),
  CONSTRAINT `fk_hr_tasks_assignee` FOREIGN KEY (`assignee_id`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_hr_tasks_hotelfix_wo` FOREIGN KEY (`hotelfix_wo_id`) REFERENCES `work_orders` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_hr_tasks_kpi_definition` FOREIGN KEY (`kpi_definition_id`) REFERENCES `hr_kpi_definitions` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_hr_tasks_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_hr_tasks_verified_by` FOREIGN KEY (`verified_by`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `hr_tasks`
--

INSERT INTO `hr_tasks` VALUES (1,1,'briefing','crew','instant',NULL,NULL,'hr_briefings:1','Follow-up komplain kebersihan kamar 1203','Extra inspeksi kamar 1203 menyusul komplain tamu minggu lalu (DUMMY demo).','housekeeping',525,'2026-07-11','high','open',NULL,NULL,7,NULL,'2026-07-08 19:08:46','2026-07-09 14:02:05'),(2,1,'manual','crew','instant',NULL,NULL,NULL,'Cross-check stok linen & amenities','Linen Attendant cross-check stok dgn PA sebelum shift siang (DUMMY demo).','housekeeping',530,'2026-07-06','normal','open',NULL,NULL,7,NULL,'2026-07-08 19:08:46','2026-07-09 14:02:05'),(3,1,'manual','crew','instant',NULL,NULL,NULL,'Update roster housekeeping minggu depan','Finalisasi roster 7 hari ke depan & publish ke tim (DUMMY demo).','housekeeping',514,'2026-07-09','normal','in_progress',NULL,NULL,7,NULL,'2026-07-08 19:08:46','2026-07-09 14:02:05'),(4,1,'manual','crew','instant',NULL,NULL,NULL,'Submit laporan inspeksi kamar mingguan','Rekap skor inspeksi 30 titik minggu ini utk KPI dept (DUMMY demo).','housekeeping',514,'2026-07-07','normal','done',NULL,NULL,7,504,'2026-07-08 19:08:46','2026-07-09 14:02:05'),(5,1,'manual','sell','instant',NULL,NULL,'mkt_quotations:2','Follow-up penawaran QT-2026-D002 (Demo Corporate Client)','Follow-up penawaran yang sudah 4 hari status follow_up tanpa update (DUMMY demo).','sales',521,'2026-07-10','high','open',NULL,NULL,8,NULL,'2026-07-08 19:08:46','2026-07-09 14:02:05'),(6,1,'manual','sell','staged','contract_renewal','reminder','mkt_contracts:1','Reminder kontrak Contoh Travel Agent A H-60','Kontrak berakhir 45 hari lagi, siapkan opsi perpanjangan (DUMMY demo).','sales',520,'2026-07-15','normal','open','[{\"at\":\"2026-07-08 23:51:15\",\"by\":900,\"note\":\"Kontrak tidak diperpanjang, mitra pindah (test verifikasi)\"}]',NULL,8,NULL,'2026-07-08 19:08:46','2026-07-09 14:02:05'),(7,1,'manual','sell','instant',NULL,NULL,'mkt_kol_visits:1','Persiapan kedatangan KOL H-10 (Demo KOL Traveler ID)','Pastikan photo release terupload sebelum kedatangan H-10 (DUMMY demo, gerbang blm lolos).','sales',582,'2026-07-11','normal','open',NULL,NULL,8,NULL,'2026-07-08 19:08:46','2026-07-09 14:02:05'),(8,1,'manual','sell','instant',NULL,NULL,'mkt_kols:2','Review konten hasil kolaborasi KOL (Demo KOL Traveler EN)','Review video & metrik reach sebelum dipublikasi ulang di kanal resort (DUMMY demo).','sales',521,'2026-07-10','normal','open',NULL,NULL,8,NULL,'2026-07-08 19:08:46','2026-07-09 14:02:05'),(9,1,'manual','crew','staged','procurement','di_po',NULL,'Pengadaan sabun & shampo amenities kamar (DUMMY demo)','Stok amenities menipis, sudah diajukan PO ke purchasing (DUMMY demo — contoh journey procurement).','housekeeping',530,'2026-07-18','normal','in_progress',NULL,NULL,5,NULL,'2026-07-08 23:34:49','2026-07-08 23:52:31'),(10,1,'manual','crew','instant',NULL,NULL,NULL,'Cek kelengkapan amenities kamar checkout (DUMMY demo)','Contoh task instant departemen housekeeping yang otomatis tertaut ke indikator KPI \"Penyelesaian task tepat waktu\" (DUMMY demo ÔÇö kaitan KPI universal).','housekeeping',514,'2026-07-10','normal','open',NULL,NULL,7,900,'2026-07-08 23:45:14','2026-07-08 23:52:31'),(11,1,'manual','crew','instant',NULL,NULL,'complaint:4','Tindak lanjuti komplain #4 (High)','QC TEST - handuk kotor tidak diganti, tamu marah.','housekeeping',NULL,NULL,'urgent','open',NULL,NULL,7,NULL,'2026-07-09 15:21:08','2026-07-10 10:00:57'),(12,1,'manual','crew','instant',NULL,NULL,'complaint:5','Tindak lanjuti komplain #5 (Medium)','QC TEST medium severity - proses checkout agak lama.','front_office',NULL,NULL,'high','open',NULL,NULL,NULL,NULL,'2026-07-09 15:23:54','2026-07-09 15:23:54'),(13,1,'manual','crew','instant',NULL,NULL,'hr_leaves:5','Cuti disetujui: Cuti Tahunan','Pengajuan 2026-07-16 s/d 2026-07-18 telah disetujui.','',900,'2026-07-16','low','open',NULL,NULL,NULL,NULL,'2026-07-09 16:04:13','2026-07-09 16:04:13'),(14,1,'manual','crew','instant',NULL,NULL,'hr_leaves:5','Cuti disetujui: Cuti Tahunan','Pengajuan 2026-07-16 s/d 2026-07-18 telah disetujui.','',900,'2026-07-16','low','open',NULL,NULL,NULL,NULL,'2026-07-09 16:04:15','2026-07-09 16:04:15');

--
-- Table structure for table `hr_test_attempts`
--

CREATE TABLE `hr_test_attempts` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `test_id` int(10) unsigned NOT NULL,
  `user_id` int(10) unsigned DEFAULT NULL,
  `candidate_id` int(10) unsigned DEFAULT NULL COMMENT '-> hr_candidates(id) bila test kandidat (FK ditambah setelah hr_candidates dibuat)',
  `score` decimal(5,2) DEFAULT NULL,
  `answers` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`answers`)),
  `passed` tinyint(1) DEFAULT NULL,
  `ts` datetime NOT NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_hr_test_attempts_test` (`test_id`),
  KEY `idx_hr_test_attempts_user` (`user_id`),
  KEY `idx_hr_test_attempts_candidate` (`candidate_id`),
  CONSTRAINT `fk_hr_test_attempts_candidate` FOREIGN KEY (`candidate_id`) REFERENCES `hr_candidates` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_hr_test_attempts_test` FOREIGN KEY (`test_id`) REFERENCES `hr_tests` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_hr_test_attempts_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `hr_test_attempts`
--

INSERT INTO `hr_test_attempts` VALUES (1,1,525,NULL,92.00,'[1, 2, 1, 2, 2]',1,'2026-07-05 19:08:46'),(2,1,526,NULL,88.00,'[1, 2, 1, 1, 2]',1,'2026-07-06 19:08:46'),(3,2,900,NULL,100.00,'[\"0\",\"0\",\"0\",\"0\",\"1\"]',1,'2026-07-08 20:10:26'),(4,3,900,NULL,0.00,'[\"9\",\"9\",\"9\",\"9\",\"9\"]',0,'2026-07-08 20:11:44'),(5,35,900,NULL,95.00,'[\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\"]',1,'2026-07-08 20:12:11'),(8,10,900,NULL,100.00,'[\"0\",\"0\",\"0\",\"0\",\"0\"]',1,'2026-07-09 14:09:22'),(9,36,900,NULL,100.00,'[\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\"]',1,'2026-07-09 14:30:11');

--
-- Table structure for table `hr_tests`
--

CREATE TABLE `hr_tests` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `course_id` int(10) unsigned DEFAULT NULL,
  `competency_id` int(10) unsigned DEFAULT NULL,
  `title` varchar(150) NOT NULL,
  `question_bank` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL COMMENT 'array soal {q, options[], answer, ...}' CHECK (json_valid(`question_bank`)),
  `pass_grade` tinyint(3) unsigned NOT NULL DEFAULT 85,
  `time_limit_minutes` smallint(5) unsigned DEFAULT NULL,
  `max_attempts` tinyint(3) unsigned NOT NULL DEFAULT 3,
  `type` enum('course','entrance','certification','placement') NOT NULL DEFAULT 'course',
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_hr_tests_property` (`property_id`),
  KEY `idx_hr_tests_course` (`course_id`),
  KEY `idx_hr_tests_competency` (`competency_id`),
  CONSTRAINT `fk_hr_tests_competency` FOREIGN KEY (`competency_id`) REFERENCES `hr_competencies` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_hr_tests_course` FOREIGN KEY (`course_id`) REFERENCES `hr_courses` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_hr_tests_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `hr_tests`
--

INSERT INTO `hr_tests` VALUES (1,1,3,5,'Test Mingguan — Checklist 30 Titik Kamar','[{\"q\": \"Berapa target waktu maksimal make-up room sesuai standar Sanggraloka?\", \"options\": [\"15 menit\", \"25 menit\", \"45 menit\", \"60 menit\"], \"answer\": 1}, {\"q\": \"Berapa target waktu maksimal check-out cleaning (kamar kotor total)?\", \"options\": [\"25 menit\", \"35 menit\", \"45 menit\", \"90 menit\"], \"answer\": 2}, {\"q\": \"Kerusakan kamar yang ditemukan Room Attendant dilaporkan lewat sistem apa?\", \"options\": [\"WhatsApp grup\", \"HotelFix (foto)\", \"Buku catatan manual\", \"Telepon Engineering langsung\"], \"answer\": 1}, {\"q\": \"Berapa persen sampling minimal kamar/hari yang diinspeksi HK Coordinator?\", \"options\": [\"10%\", \"20%\", \"30%\", \"50%\"], \"answer\": 2}, {\"q\": \"Barang temuan tamu di kamar diserahkan ke lost & found kapan?\", \"options\": [\"Akhir minggu\", \"Shift berikutnya\", \"Pada shift yang sama\", \"Setelah tamu check-out\"], \"answer\": 2}]',85,15,3,'course','2026-07-08 18:57:12','2026-07-08 18:57:12'),(2,1,4,14,'Test — HK-L1-W01 — Dunia Housekeeping: Peran, Istilah & Alur Harian','[{\"type\":\"single\",\"text\":\"Kamu masuk ke kamar yang di sistem HotelCrew tertulis status VD. Apa artinya dan apa yang kamu lakukan?\",\"options\":[\"Vacant Dirty — kamar kosong dan kotor, segera bersihkan\",\"Vacant Clean — kamar sudah bersih, langsung tinggalkan\",\"Out of Order — kamar rusak, lapor HotelFix dulu\",\"Occupied — ada tamu di dalam, jangan masuk\"],\"answer\":0,\"explanation\":\"VD = Vacant Dirty, kamar kosong tapi belum dibersihkan, jadi harus segera di-make up.\"},{\"type\":\"single\",\"text\":\"Tamu Perancis check-out pagi ini, dan ada 2 kamar lain berstatus VD dari kemarin. Kamar mana yang kamu kerjakan lebih dulu?\",\"options\":[\"Kamar bekas check-out, karena kemungkinan besar akan dijual lagi hari ini\",\"Kamar VD yang paling dekat pintu masuk area kerja\",\"Kamar mana saja, urutan tidak penting\",\"Kamar yang paling mudah dan cepat selesai\"],\"answer\":0,\"explanation\":\"Prioritas harian: kamar check-out duluan karena FO butuh menjualnya kembali secepatnya.\"},{\"type\":\"single\",\"text\":\"Kamu menemukan AC kamar 204 mati saat mulai bekerja. Apa langkah yang benar?\",\"options\":[\"Lapor kerusakan lewat HotelFix supaya ada work order perbaikan\",\"Diamkan saja, bukan urusan Housekeeping\",\"Pindahkan tamu sendiri tanpa lapor siapa pun\",\"Tulis di buku catatan pribadi untuk shift berikutnya\"],\"answer\":0,\"explanation\":\"HotelFix adalah sistem resmi untuk melaporkan kerusakan supaya ditindaklanjuti tim terkait.\"},{\"type\":\"single\",\"text\":\"Setelah selesai membersihkan kamar 112, hal pertama yang wajib kamu lakukan sebelum pindah ke kamar berikutnya:\",\"options\":[\"Update status kamar di HotelCrew menjadi bersih (VC)\",\"Langsung istirahat karena target sudah terlewati\",\"Tunggu Supervisor datang mengecek dulu\",\"Diamkan status apa adanya, nanti diperbarui di akhir shift\"],\"answer\":0,\"explanation\":\"Update status real-time penting agar Front Office tahu kamar sudah bisa dijual/dihuni.\"},{\"type\":\"truefalse\",\"text\":\"Filosofi Tri Hita Karana bagian Palemahan berarti harmoni dengan Tuhan, sehingga tidak ada hubungannya dengan kebersihan kamar.\",\"options\":[\"Benar\",\"Salah\"],\"answer\":1,\"explanation\":\"Palemahan adalah harmoni dengan alam/lingkungan — kamar bersih & alami justru wujud nyata Palemahan. Parhyangan yang berhubungan dengan Tuhan.\"}]',80,10,3,'course','2026-07-08 19:12:48','2026-07-08 19:12:48'),(3,1,5,6,'Test — HK-L1-W02 — Bed Making: Linen, Ukuran & Hospital Corner (Teori)','[{\"type\":\"single\",\"text\":\"Kamu baru saja memasang flat sheet dan mau membuat sudut kasur rapi. Teknik apa yang kamu pakai dan seperti apa hasil yang benar?\",\"options\":[\"Hospital corner — lipatan sudut 45° yang rapat dan terselip kencang\",\"Cukup diselipkan asal-asalan di bawah kasur\",\"Dibiarkan menjuntai agar terlihat elegan\",\"Diikat simpul di tiap sudut kasur\"],\"answer\":0,\"explanation\":\"Hospital corner membuat sprei kencang dan rapi, tidak mudah lepas.\"},{\"type\":\"single\",\"text\":\"Saat melepas linen kotor, kamu menemukan sebuah jam tangan terselip di sela bantal. Apa yang kamu lakukan?\",\"options\":[\"Simpan sesuai prosedur lost & found dan laporkan ke Supervisor\",\"Simpan sendiri untuk dikembalikan kalau tamu memintanya\",\"Letakkan saja di meja kamar tanpa laporan\",\"Abaikan dan lanjutkan bed making\"],\"answer\":0,\"explanation\":\"Barang tamu yang tertinggal wajib dilaporkan sesuai prosedur lost & found, bukan disimpan sendiri.\"},{\"type\":\"single\",\"text\":\"Manakah urutan bed making yang benar setelah linen kotor dilepas?\",\"options\":[\"Fitted sheet → flat sheet + hospital corner → duvet cover → pillowcase → bed runner\",\"Duvet cover → fitted sheet → pillowcase → flat sheet → bed runner\",\"Bed runner → pillowcase → fitted sheet → flat sheet → duvet cover\",\"Pillowcase → duvet cover → flat sheet → fitted sheet → bed runner\"],\"answer\":0,\"explanation\":\"Urutan standar: fitted sheet, flat sheet dengan hospital corner, duvet cover, pillowcase, lalu bed runner sebagai sentuhan akhir.\"},{\"type\":\"single\",\"text\":\"Kamu terburu-buru dan linen kotor sempat kamu letakkan sebentar di lantai sebelum dimasukkan ke trolley. Apakah ini boleh?\",\"options\":[\"Tidak boleh — linen kotor maupun bersih tidak boleh menyentuh lantai\",\"Boleh, asal cepat diangkat lagi\",\"Boleh untuk linen kotor saja\",\"Boleh asal lantai terlihat bersih\"],\"answer\":0,\"explanation\":\"Standar higienis Sanggraloka: linen tidak boleh bersentuhan dengan lantai, baik kotor maupun bersih.\"},{\"type\":\"truefalse\",\"text\":\"Setelah bed making selesai, kamu boleh langsung yakin hasilnya standar tanpa mengecek permukaan sprei, karena yang penting semua linen sudah terpasang.\",\"options\":[\"Benar\",\"Salah\"],\"answer\":1,\"explanation\":\"Standar hasil harus dicek: tanpa kerutan/gelembung, tinggi sprei konsisten, dan hospital corner tidak mudah lepas saat ditarik ringan.\"}]',80,10,3,'course','2026-07-08 19:12:48','2026-07-08 19:12:48'),(4,1,6,8,'Test — HK-L1-W03 — Chemical 101: Kode Warna, Dilusi & APD','[{\"type\":\"single\",\"text\":\"Kamu mau membersihkan minibar di dalam kamar. Botol chemical warna apa yang tepat kamu ambil dari caddy?\",\"options\":[\"Hijau — untuk area food contact seperti minibar/pantry\",\"Merah — untuk semua permukaan kamar\",\"Biru — karena minibar terbuat dari kaca\",\"Kuning — karena minibar ada di kamar\"],\"answer\":0,\"explanation\":\"Hijau khusus untuk area food contact seperti dapur/pantry/minibar agar tidak terkontaminasi chemical toilet.\"},{\"type\":\"single\",\"text\":\"Label chemical menunjukkan dilusi 1:20. Berapa ml chemical yang kamu tuang untuk membuat 1 liter larutan siap pakai?\",\"options\":[\"Sekitar 50 ml chemical + sisanya air\",\"Sekitar 500 ml chemical + sisanya air\",\"Sekitar 20 ml chemical + sisanya air\",\"1000 ml chemical murni tanpa air\"],\"answer\":0,\"explanation\":\"Dilusi 1:20 berarti sekitar 50 ml chemical per liter larutan (1000 ml dibagi 20 bagian air + 1 bagian chemical).\"},{\"type\":\"single\",\"text\":\"Kamu terburu-buru dan mau membersihkan toilet lebih cepat. Apakah menuang chemical lebih pekat dari dilusi yang ditentukan adalah ide baik?\",\"options\":[\"Tidak — terlalu pekat justru boros, berisiko merusak permukaan, dan berbahaya bagi kulit/pernapasan\",\"Ya, supaya toilet lebih cepat bersih\",\"Ya, asalkan pakai sarung tangan\",\"Tidak masalah selama botolnya berwarna merah\"],\"answer\":0,\"explanation\":\"Dilusi harus sesuai takaran; terlalu pekat boros dan berbahaya, bukan berarti lebih efektif.\"},{\"type\":\"single\",\"text\":\"Kamu menemukan chemical baru yang belum pernah dipakai di trolley. Langkah paling benar sebelum menggunakannya:\",\"options\":[\"Baca MSDS dan label dilusinya dulu di chemical store\",\"Coba semprotkan sedikit dulu ke permukaan tanpa cek apa pun\",\"Campur dengan chemical lain agar hasil lebih maksimal\",\"Tanya tamu apakah boleh dipakai\"],\"answer\":0,\"explanation\":\"MSDS (Material Safety Data Sheet) memberi info keamanan & cara pakai yang benar sebelum chemical baru digunakan.\"},{\"type\":\"truefalse\",\"text\":\"Mencampur dua chemical berbeda dalam satu botol boleh dilakukan asal keduanya sama-sama untuk membersihkan kamar mandi.\",\"options\":[\"Benar\",\"Salah\"],\"answer\":1,\"explanation\":\"Mencampur chemical berbeda berisiko menghasilkan reaksi kimia/gas berbahaya, meskipun keduanya untuk area yang sama.\"}]',80,10,3,'course','2026-07-08 19:12:48','2026-07-08 19:12:48'),(5,1,8,5,'Test — HK-L1-W05 — Make-up Room Sequence 1: Entry, Stripping, Dusting','[{\"type\":\"single\",\"text\":\"Kamu tiba di depan kamar tamu untuk make-up room. Langkah pertama yang benar adalah…\",\"options\":[\"Ketuk pintu 3x dengan buku jari sambil ucapkan jelas \\\"Housekeeping\\\"\",\"Langsung buka pakai kunci master karena lebih cepat\",\"Masuk diam-diam supaya tidak mengganggu tamu yang mungkin tidur\",\"Telepon dulu ke kamar dari HP pribadi\"],\"answer\":0,\"explanation\":\"Etika standar: ketuk 3x + sebut \\\"Housekeeping\\\" dengan jelas sebelum menyentuh pintu.\"},{\"type\":\"single\",\"text\":\"Setelah ketuk pertama dan menyebut \\\"Housekeeping\\\", tidak ada respon dari dalam kamar. Apa yang kamu lakukan?\",\"options\":[\"Beri jeda sekitar 5 detik, lalu ulangi ketuk 3x + \\\"Housekeeping\\\" sekali lagi\",\"Langsung masuk karena sudah ketuk sekali\",\"Tinggalkan kamar dan jangan kembali seharian\",\"Ketuk terus-menerus tanpa jeda sampai ada yang buka\"],\"answer\":0,\"explanation\":\"Beri jeda dengar respon, lalu ulangi proses ketuk sebelum memutuskan langkah berikutnya.\"},{\"type\":\"single\",\"text\":\"Kamu melihat tanda DND (Do Not Disturb) tergantung di gagang pintu Premiere Suite. Apa tindakan yang tepat?\",\"options\":[\"Jangan ketuk, jangan masuk — catat statusnya di HotelCrew dan lanjut ke kamar lain\",\"Ketuk pelan sekali untuk memastikan, baru lanjut\",\"Masuk saja untuk taruh amenities lalu keluar cepat\",\"Tunggu di depan pintu sampai tamu keluar sendiri\"],\"answer\":0,\"explanation\":\"DND artinya jangan diganggu sama sekali; catat dan lanjutkan ke kamar berikutnya sesuai rute.\"},{\"type\":\"single\",\"text\":\"Saat proses stripping linen kotor dari tempat tidur, kamu menemukan sebuah jam tangan terselip di antara sheet. Apa yang seharusnya kamu lakukan?\",\"options\":[\"Berhenti sejenak, amankan barang tersebut, dan proses sesuai prosedur lost-found — jangan sampai ikut terbuang ke kantong linen kotor\",\"Masukkan saja ke kantong linen kotor, nanti ketemu di laundry\",\"Simpan dulu di kantong seragam sendiri, laporkan kalau sempat\",\"Abaikan saja karena bukan tugas housekeeping untuk urus barang tamu\"],\"answer\":0,\"explanation\":\"Barang tamu yang terselip harus diamankan dan diproses lewat prosedur lost-found, tidak boleh ikut terbawa linen kotor.\"},{\"type\":\"single\",\"text\":\"Setelah kamar dipastikan kosong dan tirai sudah dibuka, kamu mulai dusting. Urutan arah yang benar adalah…\",\"options\":[\"Dari titik tertinggi ke terendah, bergerak searah jarum jam mengelilingi kamar\",\"Dari lantai ke atas, arah bebas asal cepat selesai\",\"Acak sesuai furniture yang terlihat kotor duluan\",\"Berlawanan arah jarum jam, dari terendah ke tertinggi\"],\"answer\":0,\"explanation\":\"Standar dusting Sanggraloka: atas ke bawah, searah jarum jam, supaya tidak ada titik yang terlewat atau dua kali dikerjakan.\"}]',80,10,3,'course','2026-07-08 19:12:48','2026-07-08 19:12:48'),(6,1,9,7,'Test — HK-L1-W06 — Make-up Room Sequence 2: Bathroom & Finishing','[{\"type\":\"single\",\"text\":\"Kamu mulai bersihkan bathroom Deluxe Suite. Urutan arah kerja yang benar adalah…\",\"options\":[\"Dari atas ke bawah, dari area paling bersih ke paling kotor\",\"Dari bawah ke atas supaya debu tidak jatuh ke area bersih\",\"Toilet dulu karena paling kotor, biar cepat selesai\",\"Bebas asal semua titik akhirnya tersentuh\"],\"answer\":0,\"explanation\":\"Prinsip bathroom: atas ke bawah, bersih ke kotor, supaya kotoran tidak berpindah ke area yang sudah dibersihkan.\"},{\"type\":\"single\",\"text\":\"Di antara wastafel, shower, dan toilet, mana yang seharusnya dikerjakan paling akhir?\",\"options\":[\"Toilet\",\"Wastafel\",\"Cermin\",\"Shower area\"],\"answer\":0,\"explanation\":\"Toilet adalah titik paling kotor sehingga dikerjakan terakhir, dengan lap dan chemical khusus.\"},{\"type\":\"single\",\"text\":\"Setelah kamu lap wastafel, permukaannya terlihat kering tapi saat diraba masih ada bercak air tipis. Apakah ini sudah memenuhi standar Sanggraloka?\",\"options\":[\"Belum — standar kering artinya benar-benar bebas noda, bukan sekadar kelihatan kering\",\"Sudah, karena sudah tidak basah\",\"Sudah, asal tamu tidak komplain\",\"Belum, tapi boleh dilanjut nanti di kunjungan berikutnya\"],\"answer\":0,\"explanation\":\"Standar kering Sanggraloka adalah bebas noda total, termasuk water spot dan bercak halus, bukan hanya tampilan permukaan.\"},{\"type\":\"single\",\"text\":\"Manakah dari berikut ini yang TERMASUK dalam checklist finishing 10 titik make-up room?\",\"options\":[\"Handuk terlipat rapi sesuai standar folding Sanggraloka\",\"Mengganti seluruh linen meski kamar masih stay-over tanpa request\",\"Menyemprot parfum ruangan berlebihan agar wangi menyengat\",\"Memindahkan barang pribadi tamu ke laci lain agar terlihat rapi\"],\"answer\":0,\"explanation\":\"Handuk terlipat rapi adalah salah satu dari 10 titik finishing standar; opsi lain bukan bagian checklist atau melanggar privasi/prosedur tamu.\"},{\"type\":\"single\",\"text\":\"Kamu mengelap toilet dengan lap yang sama yang tadi dipakai untuk wastafel. Apa dampaknya?\",\"options\":[\"Berisiko kontaminasi silang — lap toilet dan lap wastafel harus dipisahkan\",\"Tidak masalah selama lap terlihat bersih\",\"Lebih efisien dan dianjurkan untuk menghemat waktu\",\"Hanya masalah kecil yang tidak perlu dilaporkan\"],\"answer\":0,\"explanation\":\"Lap untuk toilet dan area lain harus dipisahkan untuk mencegah kontaminasi silang, sesuai standar kebersihan resort.\"}]',80,10,3,'course','2026-07-08 19:12:48','2026-07-08 19:12:48'),(7,1,10,9,'Test — HK-L1-W07 — Alat Kerja: Vacuum, Caddy & Perawatannya','[{\"type\":\"single\",\"text\":\"Sebelum mulai memakai vacuum cleaner di kamar, kamu melihat kabelnya sedikit terkelupas. Apa yang harus kamu lakukan?\",\"options\":[\"Jangan dipaksakan pakai, laporkan lewat HotelFix sebagai work order\",\"Tetap pakai selama masih bisa menyala\",\"Lapisi kabel pakai selotip sendiri lalu lanjut kerja\",\"Pakai tapi hindari menyentuh bagian yang terkelupas\"],\"answer\":0,\"explanation\":\"Alat dengan kabel terkelupas berbahaya dan tidak boleh dipaksakan; wajib dilaporkan lewat HotelFix, bukan diakali sendiri.\"},{\"type\":\"single\",\"text\":\"Kapan waktu yang tepat untuk mengosongkan kantong debu/tabung vacuum?\",\"options\":[\"Setiap akhir shift, jangan tunggu sampai penuh\",\"Hanya kalau sudah penuh sesak dan berat\",\"Sekali seminggu saja sudah cukup\",\"Tidak perlu dikosongkan selama vacuum masih menyala\"],\"answer\":0,\"explanation\":\"Kantong debu dikosongkan tiap akhir shift agar daya hisap tetap optimal dan alat lebih awet.\"},{\"type\":\"single\",\"text\":\"Kenapa lap untuk bathroom dan lap untuk kamar di dalam caddy harus dipisahkan?\",\"options\":[\"Untuk mencegah kontaminasi silang antara area kotor dan area bersih\",\"Supaya caddy terlihat lebih rapi saat diperiksa supervisor\",\"Karena warna lap bathroom harus mencolok\",\"Tidak ada alasan khusus, hanya kebiasaan lama\"],\"answer\":0,\"explanation\":\"Pemisahan lap mencegah kotoran/bakteri dari bathroom berpindah ke permukaan kamar yang seharusnya bersih.\"},{\"type\":\"single\",\"text\":\"Vacuum cleaner tiba-tiba mati total saat kamu sedang bekerja di sebuah Premiere Suite. Langkah yang benar adalah…\",\"options\":[\"Buat work order di HotelFix, foto kerusakan, lalu informasikan ke Supervisor shift\",\"Membongkar vacuum sendiri untuk diperbaiki di tempat\",\"Meninggalkan vacuum di kamar tamu dan lanjut ke kamar lain tanpa lapor\",\"Menukar vacuum diam-diam dengan milik rekan tanpa memberi tahu siapa pun\"],\"answer\":0,\"explanation\":\"Kerusakan alat wajib dilaporkan resmi lewat HotelFix dengan foto dan info ke Supervisor, agar alat pengganti bisa disiapkan cepat.\"},{\"type\":\"single\",\"text\":\"Setelah selesai memakai vacuum di area dekat outdoor shower villa, di mana sebaiknya vacuum disimpan?\",\"options\":[\"Di tempat kering, jauh dari air\",\"Di dekat outdoor shower supaya mudah diambil lagi besok\",\"Di lantai kamar tamu selama belum ada waktu untuk kembali ke store\",\"Di manapun asal kabel sudah digulung\"],\"answer\":0,\"explanation\":\"Vacuum harus disimpan di tempat kering karena bukan alat untuk area basah dan rawan rusak bila terkena air.\"}]',80,10,3,'course','2026-07-08 19:12:48','2026-07-08 19:12:48'),(8,1,12,NULL,'Test — HK-L1-W09 — Turndown & Sentuhan Bali','[{\"type\":\"single\",\"text\":\"Kamu lihat tanda DND tergantung di pintu villa saat jam turndown. Apa yang kamu lakukan?\",\"options\":[\"Catat kamar itu dan coba turndown lagi nanti, tidak masuk paksa\",\"Ketuk lebih keras karena turndown wajib selesai jam segitu\",\"Masuk pelan-pelan tanpa ketuk supaya tidak mengganggu\",\"Minta rekan kerja lain yang masuk saja\"],\"answer\":0,\"explanation\":\"Tanda DND harus dihormati penuh — turndown ditunda, dicatat, dicoba lagi di kesempatan berikut tanpa memaksa masuk.\"},{\"type\":\"single\",\"text\":\"Waktu standar pelaksanaan turndown service di Sanggraloka adalah…\",\"options\":[\"Sore hari, sekitar pukul 18.00–20.00\",\"Pagi hari bersamaan dengan make-up room\",\"Tengah malam setelah tamu tidur\",\"Kapan saja asal sebelum tamu check-out\"],\"answer\":0,\"explanation\":\"Turndown dilakukan sore hari saat tamu biasanya sedang makan malam/bersantai di luar kamar.\"},{\"type\":\"single\",\"text\":\"Petal art dasar Level 1 di Sanggraloka menggunakan prinsip apa?\",\"options\":[\"Bunga/daun dari farm organik resort, pola sederhana, ditabur tipis dan natural\",\"Bunga plastik impor supaya tahan lama semalaman\",\"Pola serumit mungkin supaya terlihat mewah\",\"Bunga ditabur banyak-banyak menutupi seluruh kasur\"],\"answer\":0,\"explanation\":\"Signature Sanggraloka adalah kesan natural elegant memakai bahan dari farm organik sendiri, pola sederhana dan tipis — bukan berlebihan.\"},{\"type\":\"single\",\"text\":\"Saat turndown, kamu menemukan pakaian tamu tercecer di lantai. Tindakan yang benar?\",\"options\":[\"Lipat rapi dan letakkan di kursi, jangan simpan ke dalam lemari\",\"Simpan langsung ke dalam lemari tamu supaya kamar terlihat rapi\",\"Biarkan saja karena itu bukan tugas turndown\",\"Kumpulkan dan bawa ke laundry tanpa konfirmasi\"],\"answer\":0,\"explanation\":\"Barang tamu dirapikan di tempat yang terlihat (kursi), tidak dipindah ke lemari atau area tertutup — menjaga privasi & menghindari kesan barang \\\"disembunyikan\\\".\"},{\"type\":\"single\",\"text\":\"Bagian dari amenities malam standar turndown di Sanggraloka adalah…\",\"options\":[\"Air mineral, snack lokal, dan aroma natural dari farm organik seperti sereh\",\"Minuman beralkohol gratis untuk semua tipe kamar\",\"Hanya mengganti handuk kamar mandi\",\"Menyalakan TV otomatis ke channel berita\"],\"answer\":0,\"explanation\":\"Amenities malam khas kita menonjolkan sentuhan alami resort: air mineral, snack lokal, dan aroma natural dari kebun organik.\"}]',80,10,3,'course','2026-07-08 19:12:48','2026-07-08 19:12:48'),(9,1,13,13,'Test — HK-L1-W10 — Guest Request, Privasi Kamar & Lost-Found','[{\"type\":\"single\",\"text\":\"Kamu menemukan dompet berisi uang tunai tertinggal di bawah bantal saat make-up room. Langkah pertama yang benar?\",\"options\":[\"Catat langsung di modul Lost & Found HotelCrew dengan detail lokasi & waktu\",\"Simpan dulu di kantong seragam sampai selesai shift\",\"Tanya rekan kerja lain siapa pemiliknya\",\"Tinggalkan di tempat karena bukan urusan Housekeeping\"],\"answer\":0,\"explanation\":\"Prosedur wajib: catat dulu di sistem HotelCrew begitu ditemukan, sebelum dibawa dan disimpan.\"},{\"type\":\"single\",\"text\":\"Pintu kamar bertanda DND saat jam kerjamu. Sikap yang benar adalah…\",\"options\":[\"Tidak masuk sama sekali kecuali ada instruksi darurat resmi dari Supervisor/MOD\",\"Mengetuk pelan dan masuk kalau tidak ada jawaban dalam 5 detik\",\"Masuk untuk cek cepat lalu keluar lagi\",\"Menunggu di depan pintu sampai tamu keluar sendiri\"],\"answer\":0,\"explanation\":\"DND berarti privasi mutlak — hanya bisa dilanggar dengan instruksi resmi darurat, bukan keputusan sendiri.\"},{\"type\":\"single\",\"text\":\"Saat merapikan kamar, kamu melihat laptop dan paspor tamu di meja kerja. Tindakan yang tepat?\",\"options\":[\"Biarkan di posisi asal, jangan dipindahkan atau dirapikan sendiri\",\"Pindahkan ke laci supaya kamar terlihat lebih rapi\",\"Foto sebagai bukti barang ada di kamar\",\"Simpan sementara di HK office untuk keamanan\"],\"answer\":0,\"explanation\":\"Barang berharga tamu tidak boleh disentuh/dipindahkan tanpa izin — menjaga privasi dan menghindari tuduhan yang tidak perlu.\"},{\"type\":\"single\",\"text\":\"Tamu minta tambahan extra bed melalui Front Office. Standar waktu respon Housekeeping untuk request ini adalah…\",\"options\":[\"≤ 30 menit\",\"≤ 2 jam\",\"Kapan saja asal sebelum malam\",\"Tidak ada standar waktu\"],\"answer\":0,\"explanation\":\"Extra bed/baby cot punya standar waktu respon maksimal 30 menit di Sanggraloka.\"},{\"type\":\"single\",\"text\":\"Barang berharga (uang tunai/elektronik) yang ditemukan dan sudah dicatat di HotelCrew, kemudian diserahkan ke Supervisor dengan cara…\",\"options\":[\"Serah terima ganda (double-witness) dengan tanda tangan di app\",\"Cukup lisan tanpa pencatatan tambahan\",\"Dititipkan ke rekan shift berikutnya secara informal\",\"Disimpan sendiri sampai ada yang menanyakan\"],\"answer\":0,\"explanation\":\"Barang berharga wajib melalui serah terima ganda dengan bukti tanda tangan di sistem, untuk melindungi integritas semua pihak.\"}]',80,10,3,'course','2026-07-08 19:12:48','2026-07-08 19:12:48'),(10,1,14,11,'Test — HK-L1-W11 — Minibar, Linen Count & Komunikasi Status','[{\"type\":\"single\",\"text\":\"Kamu menemukan 1 kaleng soft drink minibar sudah diminum tamu occupied. Tindakan yang benar?\",\"options\":[\"Posting langsung ke tagihan tamu di HotelCrew saat itu juga\",\"Catat di kertas dan posting nanti sebelum tamu check-out\",\"Diamkan saja, biar bagian kasir yang urus semua saat check-out\",\"Tanya tamu dulu apakah boleh ditagih\"],\"answer\":0,\"explanation\":\"Posting harus langsung dilakukan setiap kali ditemukan item terpakai supaya billing akurat dan tidak ada selisih saat check-out.\"},{\"type\":\"single\",\"text\":\"Saat cek minibar mingguan, kamu menemukan snack yang sudah lewat expiry date. Langkah tepat?\",\"options\":[\"Buang dan catat sebagai item kadaluarsa, ganti dengan stok baru\",\"Letakkan di belakang rak supaya tidak terlihat tamu\",\"Biarkan karena kemasannya masih terlihat bagus\",\"Pindahkan ke kamar lain yang minibar-nya kosong\"],\"answer\":0,\"explanation\":\"Item kadaluarsa wajib dibuang dan dicatat, tidak boleh tetap diletakkan atau dipindah ke kamar lain.\"},{\"type\":\"single\",\"text\":\"Kamu menemukan sheet dengan noda darah saat strip linen. Cara penanganan yang benar?\",\"options\":[\"Pisahkan ke kantong berlabel \\\"stain\\\" terpisah dari linen normal\",\"Campur saja dengan linen lain karena akan dicuci bersama\",\"Cuci sendiri di floor sebelum dikirim ke laundry\",\"Buang linen tersebut karena tidak bisa dipakai lagi\"],\"answer\":0,\"explanation\":\"Linen bernoda berat harus dipisahkan dalam kantong khusus berlabel supaya laundry bisa menanganinya dengan proses yang tepat.\"},{\"type\":\"single\",\"text\":\"Tamu baru saja check-out dari kamarnya. Status apa yang harus segera kamu update di HotelCrew sebelum mulai membersihkan?\",\"options\":[\"VD (Vacant Dirty)\",\"VC (Vacant Clean)\",\"OOO (Out of Order)\",\"OOS (Out of Service)\"],\"answer\":0,\"explanation\":\"Begitu tamu check-out, kamar berstatus Vacant Dirty sampai selesai dibersihkan dan diubah ke VC.\"},{\"type\":\"single\",\"text\":\"Mengapa update room status harus dilakukan real-time, bukan menunggu akhir shift?\",\"options\":[\"Supaya Front Office bisa langsung menjual/check-in kamar yang sudah VC\",\"Supaya laporan Housekeeping terlihat lebih rapi\",\"Karena aturan HotelCrew mewajibkan update setiap jam\",\"Tidak ada alasan khusus, hanya kebiasaan\"],\"answer\":0,\"explanation\":\"Data status kamar yang real-time memungkinkan Front Office segera menjual atau check-in tamu baru tanpa delay.\"}]',80,10,3,'course','2026-07-08 19:12:48','2026-07-08 19:12:48'),(11,1,15,5,'Test — HK-L1-W12 — UJI PRAKTEK LEVEL 1','[{\"type\":\"single\",\"text\":\"Kamu selesai membersihkan kamar bekas tamu check-out. Status apa yang kamu input di HotelCrew?\",\"options\":[\"VC (Vacant Clean)\",\"VD (Vacant Dirty)\",\"OOO (Out of Order)\",\"OOS (Out of Service)\"],\"answer\":0,\"explanation\":\"Setelah selesai dibersihkan dan lolos self-check, kamar berstatus Vacant Clean, siap dijual/dihuni.\"},{\"type\":\"single\",\"text\":\"Ditemukan AC rusak berat di kamar sehingga tidak bisa dijual. Status yang benar sekaligus tindakan pelaporannya?\",\"options\":[\"OOO, lapor via HotelFix\",\"VD, tunggu shift berikutnya\",\"VC, biarkan tetap dijual\",\"OOS, tidak perlu lapor\"],\"answer\":0,\"explanation\":\"Kerusakan yang membuat kamar tidak bisa dijual berstatus Out of Order dan wajib dilaporkan lewat HotelFix.\"},{\"type\":\"single\",\"text\":\"Urutan bed making yang benar untuk membentuk hospital corner rapi adalah…\",\"options\":[\"Pasang sheet dasar rapi dulu, tarik kencang di sudut, baru lipat membentuk sudut 45°\",\"Pasang selimut dulu baru sheet dasar\",\"Lipat sudut sheet asal cepat tanpa ditarik kencang\",\"Pasang bed runner sebelum sheet dasar\"],\"answer\":0,\"explanation\":\"Hospital corner rapi dihasilkan dari sheet dasar yang ditarik kencang lalu dilipat membentuk sudut 45° yang presisi.\"},{\"type\":\"single\",\"text\":\"Jenis linen yang termasuk kategori dihitung terpisah dari bed sheet saat linen count adalah…\",\"options\":[\"Bath towel, hand towel, face towel, dan bath mat\",\"Hanya duvet cover\",\"Hanya pillow case\",\"Seragam staf Housekeeping\"],\"answer\":0,\"explanation\":\"Linen count mencakup kategori sheet, duvet cover, pillow case, dan kelompok towel/bath mat yang dihitung terpisah.\"},{\"type\":\"single\",\"text\":\"Chemical berkode warna tertentu untuk permukaan kaca digunakan sesuai kode warnanya karena…\",\"options\":[\"Mencegah salah pakai chemical yang bisa merusak permukaan atau membahayakan pengguna\",\"Supaya botol terlihat lebih menarik\",\"Karena aturan pabrik saja, tidak ada alasan keamanan\",\"Kode warna hanya untuk dekorasi trolley\"],\"answer\":0,\"explanation\":\"Sistem kode warna chemical adalah standar keselamatan untuk mencegah kesalahan pemakaian pada permukaan yang salah.\"},{\"type\":\"single\",\"text\":\"Sebelum memakai chemical pembersih kamar mandi, APD minimal yang wajib dipakai adalah…\",\"options\":[\"Sarung tangan karet dan menjaga ventilasi ruangan tetap terbuka\",\"Tidak perlu APD apapun jika sudah terbiasa\",\"Masker saja tanpa sarung tangan\",\"Kacamata renang\"],\"answer\":0,\"explanation\":\"APD dasar untuk chemical adalah sarung tangan, dengan ruangan berventilasi agar aman dari uap kimia.\"},{\"type\":\"single\",\"text\":\"Saat akan masuk kamar occupied untuk make-up room, etika entry yang benar adalah…\",\"options\":[\"Ketuk pintu, sebut identitas & tujuan, tunggu respon sebelum masuk\",\"Langsung masuk menggunakan master key tanpa mengetuk\",\"Masuk kalau pintu tidak terkunci saja\",\"Menelepon kamar dulu tanpa perlu mengetuk saat tiba\"],\"answer\":0,\"explanation\":\"Etika entry standar: ketuk pintu, sebut identitas dan tujuan dengan jelas, beri waktu tamu merespon sebelum masuk.\"},{\"type\":\"single\",\"text\":\"Urutan dusting yang benar dalam sequence make-up room adalah…\",\"options\":[\"Searah jarum jam dari titik masuk supaya tidak ada bagian yang terlewat\",\"Acak sesuai barang yang terlihat kotor duluan\",\"Mulai dari lantai kamar mandi\",\"Dari luar kamar ke dalam\"],\"answer\":0,\"explanation\":\"Dusting dilakukan searah jarum jam mengikuti alur ruangan agar sistematis dan tidak ada titik yang terlewat.\"},{\"type\":\"single\",\"text\":\"Urutan pembersihan kamar mandi yang benar mengikuti prinsip…\",\"options\":[\"Dari area atas ke bawah, dan dari area bersih ke area paling kotor (toilet terakhir)\",\"Dari lantai dulu baru wastafel\",\"Toilet dibersihkan pertama supaya cepat selesai\",\"Acak sesuai kenyamanan petugas\"],\"answer\":0,\"explanation\":\"Standar kebersihan & higienitas: kerjakan dari atas ke bawah dan dari area paling bersih ke area paling kotor, toilet dikerjakan paling akhir.\"},{\"type\":\"single\",\"text\":\"Vacuum cleaner yang kamu pakai mengeluarkan bau gosong ringan. Tindakan yang benar?\",\"options\":[\"Hentikan pemakaian dan laporkan kerusakan via HotelFix\",\"Lanjutkan pemakaian sampai kamar selesai dulu\",\"Perbaiki sendiri dengan membuka komponen mesin\",\"Tukar dengan vacuum kamar lain tanpa lapor\"],\"answer\":0,\"explanation\":\"Indikasi kerusakan alat harus segera dihentikan pemakaiannya dan dilaporkan lewat HotelFix agar tidak membahayakan dan segera ditangani teknisi.\"},{\"type\":\"single\",\"text\":\"Turndown service di Sanggraloka standarnya dilaksanakan pada waktu…\",\"options\":[\"Sore hari, sekitar pukul 18.00–20.00\",\"Pagi hari bersamaan checkout\",\"Tengah malam\",\"Segera setelah check-in\"],\"answer\":0,\"explanation\":\"Turndown dilakukan sore hari saat tamu biasanya sedang di luar kamar (makan malam/bersantai).\"},{\"type\":\"single\",\"text\":\"Petal art dasar Level 1 khas Sanggraloka menekankan pada…\",\"options\":[\"Bahan dari farm organik resort, pola sederhana, kesan natural elegant\",\"Bunga plastik berwarna mencolok dalam jumlah banyak\",\"Pola serumit mungkin di seluruh kamar\",\"Tidak menggunakan bunga sama sekali\"],\"answer\":0,\"explanation\":\"Signature turndown Sanggraloka memakai bahan dari farm organik sendiri dengan pola sederhana dan tabur tipis natural.\"},{\"type\":\"single\",\"text\":\"Tamu memasang tanda DND di pintu kamarnya. Sikap Housekeeping yang benar adalah…\",\"options\":[\"Tidak masuk kecuali ada instruksi darurat resmi dari Supervisor/MOD\",\"Masuk pelan-pelan tanpa mengetuk untuk turndown\",\"Mengetuk berulang sampai ada jawaban\",\"Menunggu di depan pintu sampai tamu keluar\"],\"answer\":0,\"explanation\":\"DND adalah privasi mutlak tamu — hanya bisa dilanggar dengan instruksi resmi darurat, bukan keputusan sendiri.\"},{\"type\":\"single\",\"text\":\"Kamu menemukan barang berharga (uang tunai) tertinggal saat make-up room. Urutan prosedur lost & found yang benar adalah…\",\"options\":[\"Catat di HotelCrew, simpan di HK office, serah terima ganda ke Supervisor\",\"Simpan di loker pribadi sampai ada yang menanyakan\",\"Tanya rekan kerja siapa pemiliknya sebelum dicatat\",\"Serahkan langsung ke tamu lain di kamar sebelah\"],\"answer\":0,\"explanation\":\"Prosedur baku: catat-simpan-serah terima, dengan barang berharga wajib serah terima ganda (double-witness).\"},{\"type\":\"single\",\"text\":\"Extra bed yang diminta tamu melalui Front Office punya standar waktu respon Housekeeping selama…\",\"options\":[\"≤ 30 menit\",\"≤ 2 jam\",\"Tidak ada standar waktu\",\"Sesuai kapan sempat\"],\"answer\":0,\"explanation\":\"Extra bed/baby cot punya standar waktu respon maksimal 30 menit di Sanggraloka.\"},{\"type\":\"single\",\"text\":\"Kamu menemukan minuman minibar sudah dikonsumsi tamu occupied. Tindakan yang tepat?\",\"options\":[\"Posting langsung ke tagihan tamu di HotelCrew saat itu juga\",\"Catat manual, posting nanti sebelum check-out\",\"Diamkan, biarkan kasir yang cek semua saat check-out\",\"Tanya dulu ke tamu apakah boleh ditagih\"],\"answer\":0,\"explanation\":\"Posting minibar harus dilakukan saat itu juga agar billing akurat dan tidak ada selisih di check-out.\"},{\"type\":\"single\",\"text\":\"Item minibar yang sudah melewati expiry date wajib…\",\"options\":[\"Dibuang dan dicatat sebagai item kadaluarsa, diganti stok baru\",\"Dibiarkan karena kemasan masih terlihat bagus\",\"Dipindahkan ke kamar lain yang kekurangan stok\",\"Disimpan untuk pemakaian staf\"],\"answer\":0,\"explanation\":\"Item kadaluarsa harus dibuang dan dicatat sebagai bagian dari kontrol par stock, tidak boleh dipertahankan.\"},{\"type\":\"single\",\"text\":\"Linen dengan noda berat (darah/minyak/tinta) ditangani dengan cara…\",\"options\":[\"Dipisahkan ke kantong berlabel khusus terpisah dari linen normal\",\"Dicampur dengan linen lain karena akan dicuci bersama\",\"Dicuci sendiri di floor sebelum dikirim laundry\",\"Langsung dibuang tanpa dicatat\"],\"answer\":0,\"explanation\":\"Linen bernoda berat wajib dipisahkan dalam kantong khusus berlabel agar penanganan laundry sesuai standar.\"},{\"type\":\"single\",\"text\":\"Target waktu make-up room standar untuk Room Attendant Level 1 adalah…\",\"options\":[\"≤ 40 menit per kamar\",\"≤ 10 menit per kamar\",\"≤ 2 jam per kamar\",\"Tidak ada target waktu\"],\"answer\":0,\"explanation\":\"Target Level 1 yang ditetapkan Sanggraloka adalah menyelesaikan make-up room standar dalam maksimal 40 menit.\"},{\"type\":\"single\",\"text\":\"Syarat kelulusan Level 1 Housekeeping di Sanggraloka mencakup…\",\"options\":[\"9 kuis mingguan lulus, 2 praktek terbimbing lulus, uji praktek W12 ≥80, dan ujian teori akhir ≥80\",\"Hanya kehadiran penuh 12 minggu\",\"Cukup lulus ujian teori saja\",\"Rekomendasi dari rekan kerja\"],\"answer\":0,\"explanation\":\"Kelulusan Level 1 mensyaratkan seluruh komponen: kuis mingguan, 2 sesi praktek terbimbing, uji praktek final, dan ujian teori akhir — semuanya harus lulus.\"}]',80,30,3,'course','2026-07-08 19:12:48','2026-07-08 19:12:48'),(12,1,NULL,NULL,'HK — Placement Level 1','[{\"type\":\"single\",\"text\":\"Kamu ditugaskan membersihkan 8 kamar hari ini: 3 occupied, 2 check-out (VD), 2 VC yang minta extra towel, dan 1 OOO. Urutan prioritas kerja yang paling tepat adalah…\",\"options\":[\"Kamar check-out (VD) dulu supaya cepat dijual FO, baru occupied, VC hanya diantar towel, OOO dilewati (bukan tugas RA)\",\"Occupied dulu semua karena tamu ada di dalam, VD dan VC belakangan\",\"OOO dikerjakan dulu karena statusnya paling mencolok di sistem\",\"Acak saja sesuai nomor kamar dari terkecil ke terbesar\"],\"answer\":0,\"explanation\":\"VD (check-out) diprioritaskan karena FO butuh kamar itu segera bisa dijual ke tamu baru; occupied menyusul dengan jadwal fleksibel; VC hanya perlu dikirim extra towel; OOO memang bukan tugas make-up room RA — itu urusan Engineering via HotelFix.\",\"competency\":\"HK-15\"},{\"type\":\"single\",\"text\":\"Room attendant baru menyelesaikan sequence make-up room dengan urutan: strip linen → bathroom → dusting → vacuuming. Apa masalah utama urutan ini?\",\"options\":[\"Bathroom seharusnya dikerjakan setelah dusting dan vacuuming, bukan sebelum, karena prinsipnya bersih ke kotor dan debu kamar tidak boleh mengotori bathroom yang sudah selesai\",\"Tidak ada masalah, urutan ini sudah standar Sanggraloka\",\"Strip linen seharusnya dilakukan paling akhir setelah vacuuming\",\"Vacuuming harus dilakukan sebelum dusting supaya debu dari furniture langsung tersedot\"],\"answer\":0,\"explanation\":\"Prinsip make-up room adalah bersih ke kotor dan area basah/kotor (bathroom) dikerjakan setelah area kering (dusting) selesai, dan vacuuming selalu paling akhir supaya debu yang jatuh dari dusting ikut tersedot, bukan sebaliknya.\",\"competency\":\"HK-01\"},{\"type\":\"single\",\"text\":\"Kamu mengetuk pintu Deluxe Suite, menyebut \\\"Housekeeping\\\", dan tidak ada jawaban. Kamu masuk, ternyata tamu sedang tidur di kamar. Apa yang seharusnya kamu lakukan SEBELUM ini terjadi?\",\"options\":[\"Ketuk dan sebut identitas 2 kali dengan jeda, tunggu respon; jika tetap sunyi, buka perlahan sambil menyebut ulang sebelum melangkah masuk sepenuhnya\",\"Langsung masuk setelah ketukan pertama karena kamar sudah lewat jam checkout housekeeping\",\"Gunakan master key tanpa mengetuk karena lebih cepat\",\"Tunggu di depan pintu selama minimal 10 menit tanpa mengetuk\"],\"answer\":0,\"explanation\":\"Etika entry yang benar adalah mengetuk dan menyebut identitas minimal dua kali dengan jeda sebelum membuka perlahan — ini mencegah situasi tidak nyaman seperti masuk saat tamu masih di dalam kamar.\",\"competency\":\"HK-07\"},{\"type\":\"single\",\"text\":\"Kamu menuang chemical pembersih kaca ke botol semprot tanpa melihat kode warna label, hanya mengandalkan baunya. Apa risiko utama tindakan ini?\",\"options\":[\"Salah chemical bisa merusak permukaan (misal chemical kamar mandi dipakai di kaca menyebabkan buram/gores) dan berisiko K3 karena tidak sesuai APD/penggunaan yang ditentukan\",\"Tidak ada risiko selama baunya mirip\",\"Risiko hanya pada waktu pengerjaan yang lebih lambat\",\"Kode warna hanya untuk keperluan estetika trolley, tidak berpengaruh ke penggunaan\"],\"answer\":0,\"explanation\":\"Kode warna chemical adalah sistem keselamatan dan efektivitas: tiap warna diformulasikan untuk permukaan tertentu. Salah pakai bisa merusak material dan membahayakan pengguna karena kandungan kimianya berbeda.\",\"competency\":\"HK-08\"},{\"type\":\"single\",\"text\":\"Label chemical toilet bowl cleaner menyatakan dilusi 1:40. Untuk membuat 2 liter larutan siap pakai, berapa ml chemical pekat yang dibutuhkan?\",\"options\":[\"50 ml\",\"40 ml\",\"80 ml\",\"20 ml\"],\"answer\":0,\"explanation\":\"Dilusi 1:40 berarti 1 bagian chemical untuk 40 bagian total larutan. Untuk 2000 ml total: 2000 ÷ 41 ≈ 48-50 ml chemical (dibulatkan ke takaran praktis 50 ml), sisanya air.\",\"competency\":\"HK-08\"},{\"type\":\"single\",\"text\":\"Saat membersihkan kamar occupied, kamu melihat charger laptop tamu tergeletak di lantai dekat stop kontak. Tindakan paling tepat adalah…\",\"options\":[\"Biarkan di tempatnya atau rapikan di posisi yang sama tanpa memindah ke lokasi lain, tanpa menyentuh barang pribadi lain milik tamu\",\"Pindahkan ke laci meja kerja supaya terlihat lebih rapi\",\"Cabut dan simpan di trolley untuk keamanan sampai tamu kembali\",\"Laporkan ke Supervisor sebagai temuan lost & found karena tergeletak di lantai\"],\"answer\":0,\"explanation\":\"Barang pribadi tamu di kamar occupied tidak boleh dipindah lokasi tanpa izin — cukup dirapikan di tempat yang sama. Memindah ke tempat lain (apalagi laci atau trolley) berisiko dianggap kehilangan barang oleh tamu.\",\"competency\":\"HK-07\"},{\"type\":\"single\",\"text\":\"Tamu Korea memasang tanda DND di pintu Premiere Suite sejak pagi. Sudah lewat jam 14.00 dan kamar itu belum pernah dibersihkan hari ini. Apa langkah yang benar?\",\"options\":[\"Tetap hormati DND, jangan mengetuk atau masuk; informasikan situasi ke Supervisor/FO untuk dicatat, jangan mengambil keputusan sendiri untuk membuka pintu\",\"Ketuk pintu untuk memastikan tamu baik-baik saja karena sudah lewat 14.00\",\"Gunakan master key untuk memeriksa kondisi kamar secara diam-diam\",\"Tunggu sampai jam checkout keesokan harinya baru dilaporkan\"],\"answer\":0,\"explanation\":\"DND adalah privasi mutlak tamu — RA tidak boleh mengetuk atau masuk sendiri meski sudah lama. Jika ada kekhawatiran (misal keselamatan), eskalasi dilakukan lewat Supervisor/FO sesuai prosedur resort, bukan keputusan sepihak RA.\",\"competency\":\"HK-07\"},{\"type\":\"single\",\"text\":\"Setelah bed making, kamu menekan permukaan sheet dan merasakan lipatan sudut kasur mudah lepas saat ditarik ringan. Apa artinya?\",\"options\":[\"Hospital corner belum terbentuk dengan benar dan perlu diulang karena tidak akan bertahan rapi sepanjang hari\",\"Ini kondisi normal, hospital corner memang didesain longgar\",\"Masalah hanya kosmetik, tidak perlu diulang selama kasur terlihat rapi dari jauh\",\"Ini menandakan linen terlalu tebal, bukan masalah teknik\"],\"answer\":0,\"explanation\":\"Hospital corner yang benar harus kencang dan tidak mudah lepas — jika lipatan longgar saat ditarik ringan, teknik pelipatan belum tepat dan berisiko berantakan sebelum tamu masuk kamar.\",\"competency\":\"HK-03\"},{\"type\":\"single\",\"text\":\"Kamu menemukan noda kuning pada sprei saat strip linen di kamar check-out, kemungkinan noda organik. Penanganan yang benar adalah…\",\"options\":[\"Pisahkan ke kantong linen khusus noda (bukan digabung linen biasa) dan catat/informasikan sesuai SOP linen ternoda, jangan dicuci sendiri di area kamar\",\"Coba gosok noda dengan chemical kamar mandi sebelum dimasukkan ke trolley linen\",\"Gabungkan dengan linen kotor biasa karena laundry akan memilah otomatis\",\"Rendam sebentar di wastafel kamar supaya noda tidak menyebar ke linen lain\"],\"answer\":0,\"explanation\":\"Linen dengan noda berat (darah/organik/minyak/tinta) harus dipisahkan dalam kantong khusus sesuai SOP agar mendapat penanganan laundry yang tepat, dan tidak boleh dicuci/direndam di kamar karena berisiko kontaminasi dan bukan wewenang RA.\",\"competency\":\"HK-12\"},{\"type\":\"single\",\"text\":\"Kamu mengecek minibar kamar occupied dan menemukan satu kaleng bir sudah kosong, sementara tamu sedang keluar kamar. Langkah yang benar adalah…\",\"options\":[\"Catat konsumsi di HotelCrew untuk posting ke folio tamu, ganti stok sesuai par, tanpa perlu menunggu tamu kembali\",\"Tunggu tamu kembali dan tanyakan langsung sebelum mencatat apapun\",\"Ganti stok dulu, catat nanti di akhir shift jika sempat\",\"Abaikan karena minibar bukan tanggung jawab housekeeping harian\"],\"answer\":0,\"explanation\":\"Item minibar yang terkonsumsi dicatat segera di HotelCrew untuk posting billing yang akurat dan stok direplenish sesuai par — ini bagian rutin housekeeping, tidak perlu menunggu konfirmasi tamu untuk konsumsi yang jelas terlihat.\",\"competency\":\"HK-13\"},{\"type\":\"single\",\"text\":\"Snack minibar yang kamu cek minggu ini ternyata expired 3 hari lalu, namun kemasannya masih terlihat bagus. Tindakan yang tepat?\",\"options\":[\"Tarik dari minibar dan ganti dengan stok baru, laporkan sesuai prosedur, jangan dijual ke tamu meski kemasan terlihat baik\",\"Biarkan karena kemasan masih bagus dan belum ada komplain tamu\",\"Pindahkan ke kamar lain yang minibar-nya kosong supaya tidak terbuang\",\"Simpan di pantry staff untuk dikonsumsi karyawan\"],\"answer\":0,\"explanation\":\"Expiry date adalah batas keamanan pangan mutlak — item harus ditarik begitu lewat tanggal berapapun kondisi kemasannya, tidak boleh dipindah ke kamar lain atau dikonsumsi staff karena tetap berisiko kesehatan dan pelanggaran standar F&B.\",\"competency\":\"HK-13\"},{\"type\":\"single\",\"text\":\"Vacuum cleaner yang kamu pakai tiba-tiba mengeluarkan bau gosong ringan saat dipakai di Premiere Suite. Langkah yang benar adalah…\",\"options\":[\"Matikan segera, jangan dipaksa lanjut, cabut dari stop kontak, dan laporkan kerusakan via HotelFix, gunakan unit cadangan\",\"Lanjutkan pemakaian sampai kamar selesai karena bau gosong ringan biasanya hilang sendiri\",\"Kecilkan daya hisap supaya mesin tidak terlalu panas lalu lanjut bekerja\",\"Buka casing motor sendiri untuk memeriksa penyebabnya sebelum melapor\"],\"answer\":0,\"explanation\":\"Bau gosong adalah tanda bahaya (motor overheat/korsleting) — mesin harus dimatikan segera demi keselamatan, dilaporkan lewat HotelFix untuk penanganan teknisi, RA tidak berwenang membongkar mesin sendiri.\",\"competency\":\"HK-09\"},{\"type\":\"single\",\"text\":\"Sebelum mulai menggunakan vacuum cleaner, kamu melihat kabel power sedikit terkelupas di bagian tengah. Apa yang harus dilakukan?\",\"options\":[\"Jangan gunakan mesin tersebut, laporkan segera via HotelFix, dan ambil unit pengganti yang aman\",\"Gunakan saja dengan hati-hati karena kerusakan masih kecil\",\"Bungkus bagian terkelupas dengan lakban sendiri lalu lanjut memakainya\",\"Gunakan hanya untuk kamar yang lantainya kering saja\"],\"answer\":0,\"explanation\":\"Kabel terkelupas adalah risiko tersengat listrik — mesin tidak boleh dipakai sama sekali sebelum diperbaiki teknisi resmi. Perbaikan sendiri (lakban) bukan solusi aman dan melanggar standar K3.\",\"competency\":\"HK-09\"},{\"type\":\"truefalse\",\"text\":\"Benar atau Salah: Saat turndown service, jika ditemukan tanda DND terpasang di pintu villa, RA tetap boleh masuk selama hanya untuk memasang petal art tanpa menyentuh area lain.\",\"options\":[\"Benar\",\"Salah\"],\"answer\":1,\"explanation\":\"Salah. DND berlaku mutlak untuk semua jenis kunjungan HK termasuk turndown — tidak ada pengecualian untuk petal art atau tugas singkat lainnya.\",\"competency\":\"HK-02\"},{\"type\":\"single\",\"text\":\"Manakah yang termasuk bagian dari checklist finishing standar make-up room Sanggraloka (bukan sekadar \'terlihat rapi\')?\",\"options\":[\"Cermin bebas noda, permukaan meja bebas debu, sudut lantai bebas rambut/sampah, amenities tersusun sesuai standar\",\"Hanya memastikan tempat tidur terlihat rapi dari pintu masuk\",\"Hanya memastikan bau ruangan wangi tanpa mengecek detail permukaan\",\"Cukup memastikan lampu menyala semua\"],\"answer\":0,\"explanation\":\"Checklist finishing mencakup detail spesifik dan terukur (cermin, permukaan, sudut lantai, amenities) — bukan penilaian visual sekilas, karena standar 5-star menuntut inspeksi titik demi titik.\",\"competency\":\"HK-04\"},{\"type\":\"single\",\"text\":\"Kamu menemukan dompet berisi uang tunai di bawah bantal saat make-up room di kamar check-out. Urutan prosedur lost & found yang benar adalah…\",\"options\":[\"Jangan disentuh sendirian tanpa saksi bila memungkinkan, catat di HotelCrew segera, serahkan ke Supervisor untuk disimpan sesuai SOP, jangan disimpan di loker pribadi\",\"Simpan dulu di tas pribadi sampai akhir shift baru dilaporkan\",\"Serahkan langsung ke tamu berikutnya yang masuk kamar tersebut siapa tahu itu miliknya\",\"Simpan di laci kamar itu saja menunggu tamu lama menghubungi\"],\"answer\":0,\"explanation\":\"Barang berharga wajib dicatat segera di modul lost & found HotelCrew dan diserahkan ke Supervisor untuk disimpan sesuai SOP — ini melindungi integritas RA dan memastikan barang tamu tertelusur, bukan disimpan sendiri.\",\"competency\":\"HK-14\"},{\"type\":\"single\",\"text\":\"Tamu Perancis check-in di Deluxe Private Pool Villa meminta extra pillow melalui Front Office. Berapa standar waktu respon Housekeeping untuk guest request seperti ini di Sanggraloka?\",\"options\":[\"15 menit\",\"60 menit\",\"2 jam\",\"Kapan saja sebelum akhir shift\"],\"answer\":0,\"explanation\":\"Standar respon guest request di Sanggraloka adalah cepat (15 menit) untuk menjaga pengalaman tamu eco-luxury 5-star, terutama untuk permintaan sederhana seperti extra pillow/towel.\",\"competency\":\"HK-06\"},{\"type\":\"single\",\"text\":\"Room attendant menargetkan menyelesaikan make-up room standar dalam waktu berapa lama sesuai standar Level 1 Sanggraloka?\",\"options\":[\"≤ 40 menit per kamar standar\",\"≤ 15 menit per kamar standar\",\"≤ 90 menit per kamar standar\",\"Tidak ada target waktu, yang penting hasil bersih\"],\"answer\":0,\"explanation\":\"Target Level 1 Sanggraloka adalah menyelesaikan make-up room ≤40 menit per kamar standar, diuji lewat sesi praktek W08 dengan checklist 30 titik dan stopwatch.\",\"competency\":\"HK-01\"},{\"type\":\"single\",\"text\":\"Filosofi Tri Hita Karana bagian Palemahan yang relevan dengan pekerjaan Housekeeping di Sanggraloka adalah…\",\"options\":[\"Harmoni dengan alam — diwujudkan lewat kamar bersih, alami, dan praktik housekeeping yang ramah lingkungan\",\"Harmoni dengan Tuhan lewat doa sebelum kerja, tidak terkait kebersihan kamar\",\"Harmoni antar sesama karyawan saja, tidak terkait tugas fisik kamar\",\"Konsep ini hanya berlaku untuk departemen F&B, bukan Housekeeping\"],\"answer\":0,\"explanation\":\"Palemahan adalah harmoni dengan alam dalam filosofi Tri Hita Karana — di Housekeeping ini diwujudkan lewat kamar yang bersih dan alami serta praktik ramah lingkungan (green housekeeping), sejalan dengan identitas eco-luxury Sanggraloka.\",\"competency\":\"HK-08\"},{\"type\":\"single\",\"text\":\"Kamu membersihkan bathroom Premiere Suite dan sudah mengelap wastafel serta shower area, lalu berpindah mengelap toilet bowl. Tanpa sadar kamu memakai lap yang sama untuk ketiganya tanpa dibilas di antara penggunaan. Apa dampak paling signifikan dari kebiasaan ini?\",\"options\":[\"Kontaminasi silang — kotoran/bakteri dari toilet bowl bisa berpindah ke wastafel/shower (area kontak tangan & tubuh tamu), melanggar prinsip bersih-ke-kotor dan sanitasi\",\"Tidak ada dampak selama lap terlihat masih bersih secara visual\",\"Dampaknya hanya lap jadi lebih cepat kotor, tidak terkait sanitasi tamu\",\"Ini praktik yang dianjurkan karena menghemat jumlah lap yang dipakai\"],\"answer\":0,\"explanation\":\"Prinsip bathroom cleaning adalah bersih ke kotor dengan lap terpisah per area (terutama toilet bowl harus lap khusus) untuk mencegah kontaminasi silang — memakai satu lap untuk semua permukaan berisiko memindahkan bakteri ke area yang sering bersentuhan langsung dengan tamu.\",\"competency\":\"HK-04\"}]',85,20,3,'placement','2026-07-08 19:12:48','2026-07-08 19:12:48'),(13,1,NULL,NULL,'HK — Placement Level 2','[{\"type\":\"single\",\"text\":\"Jadwal deep cleaning bulanan menunjukkan kamar 305 (Deluxe Suite) harus deep clean hari ini, tapi kamar tersebut baru check-out siang ini dan ada reservasi masuk sore. Apa keputusan terbaik sebagai RA yang bekerja dengan supervisi?\",\"options\":[\"Informasikan konflik jadwal ke Supervisor untuk keputusan reschedule deep clean atau blocking kamar, jangan memutuskan sendiri melewati atau memaksakan deep clean penuh dalam waktu sempit\",\"Tetap paksakan deep clean penuh dalam waktu singkat agar jadwal tidak meleset\",\"Lewati deep clean minggu ini tanpa lapor karena kamar akan terisi\",\"Batalkan reservasi tamu masuk sore demi menyelesaikan jadwal deep clean\"],\"answer\":0,\"explanation\":\"Level 2 berarti bekerja dengan supervisi — konflik jadwal seperti ini harus dieskalasi ke Supervisor untuk keputusan (reschedule/blocking), bukan diputuskan sepihak oleh RA yang bisa berdampak pada availability kamar atau kualitas deep clean.\",\"competency\":\"HK-05\"},{\"type\":\"single\",\"text\":\"Saat deep cleaning kamar mandi, kamu menemukan noda kerak air (watermark) membandel di sekitar keran yang tidak hilang dengan chemical harian biasa. Langkah yang tepat adalah…\",\"options\":[\"Gunakan chemical descaler khusus sesuai dilusi dan APD yang benar, bukan menambah takaran chemical harian di luar dilusi standar\",\"Tuang chemical harian dua kali lipat dari dilusi normal supaya lebih kuat\",\"Gosok dengan sikat kawat logam agar cepat hilang tanpa chemical tambahan\",\"Biarkan saja karena watermark dianggap wajar untuk kamar mandi lama\"],\"answer\":0,\"explanation\":\"Noda kerak air butuh chemical descaler khusus, bukan menambah takaran chemical biasa di luar dilusi (berisiko merusak permukaan/K3) atau sikat kawat logam yang bisa menggores material. Deep cleaning menuntut pemilihan chemical yang tepat sasaran.\",\"competency\":\"HK-08\"},{\"type\":\"single\",\"text\":\"Kamu ditugaskan membersihkan lobby area menjelang jam check-in ramai. Karpet lobby terlihat basah bekas hujan dari sepatu tamu. Prioritas tindakan yang benar adalah…\",\"options\":[\"Pasang wet floor sign dan segera keringkan area basah lebih dulu sebelum melanjutkan tugas cleaning lain, demi keselamatan tamu yang lalu-lalang\",\"Lanjutkan jadwal cleaning area lain dulu, karpet basah dikeringkan nanti setelah selesai semua\",\"Tutup akses lobby sepenuhnya sampai karpet benar-benar kering\",\"Taburi karpet dengan pengharum tanpa mengeringkan area basah\"],\"answer\":0,\"explanation\":\"Public area cleaning mengutamakan keselamatan tamu — area basah berisiko slip harus segera ditangani dengan wet floor sign dan pengeringan, apalagi menjelang jam ramai check-in, sebelum tugas cleaning lain dilanjutkan.\",\"competency\":\"HK-10\"},{\"type\":\"single\",\"text\":\"Kamu membersihkan outdoor shower di Deluxe Private Pool Villa. Area ini berlumut tipis di lantai batu alam. Pendekatan yang tepat adalah…\",\"options\":[\"Gunakan chemical anti-lumut yang aman untuk batu alam dengan dilusi sesuai label, sikat manual di sela batu, hindari chemical korosif yang bisa merusak material outdoor\",\"Gunakan chemical toilet bowl pekat karena sama-sama area basah\",\"Semprot pemutih pekat langsung ke batu alam agar lumut hilang total dan cepat\",\"Biarkan lumut karena outdoor shower dianggap area non-prioritas\"],\"answer\":0,\"explanation\":\"Outdoor shower villa memakai material alami (batu alam) yang bisa rusak oleh chemical korosif/pemutih pekat — perlu chemical khusus outdoor dengan dilusi tepat dan sikat manual, bukan chemical indoor yang salah peruntukan.\",\"competency\":\"HK-11\"},{\"type\":\"single\",\"text\":\"Di sekitar kolam privat Premiere Private Pool Villa, kamu melihat serangga kecil berkerumun di dekat saluran air. Langkah pertama yang tepat adalah…\",\"options\":[\"Laporkan temuan ke Supervisor/tim pest control sesuai prosedur awareness, jangan menyemprot chemical pembasmi sendiri tanpa otorisasi\",\"Semprotkan chemical pembersih kamar mandi ke area tersebut agar serangga pergi\",\"Abaikan karena serangga di area outdoor villa dianggap wajar\",\"Tutup saluran air dengan lakban agar serangga tidak bisa masuk\"],\"answer\":0,\"explanation\":\"Pest control awareness berarti RA melaporkan temuan hama ke pihak berwenang (Supervisor/tim pest control), bukan menangani sendiri dengan chemical yang salah peruntukan — penanganan hama butuh metode dan produk khusus yang bukan wewenang RA harian.\",\"competency\":\"HK-16\"},{\"type\":\"single\",\"text\":\"Program green housekeeping Sanggraloka menawarkan opsi reuse linen untuk tamu yang menginap lebih dari 1 malam. Bagaimana penerapan yang benar saat tamu TIDAK meletakkan kartu reuse dan handuk tergantung rapi (bukan di lantai)?\",\"options\":[\"Anggap tamu ingin linen/handuk tetap dipakai (tidak diganti) mengikuti konvensi internasional, ganti hanya bila diminta eksplisit atau memang kotor berat\",\"Selalu ganti semua linen dan handuk setiap hari tanpa memandang posisi/kartu, program reuse hanya formalitas\",\"Ganti hanya sprei, handuk tidak pernah diganti sampai check-out\",\"Tanyakan by phone ke tamu setiap hari sebelum masuk kamar\"],\"answer\":0,\"explanation\":\"Konvensi green housekeeping: handuk tergantung rapi = tetap dipakai, handuk di lantai = minta diganti. Ini prinsip standar industri untuk menghemat air/energi sekaligus menghormati preferensi tamu tanpa harus bertanya setiap hari.\",\"competency\":\"HK-17\"},{\"type\":\"single\",\"text\":\"Kamu diminta menangani keluhan tamu bahwa AC kamar Presidential Pool Villa berbunyi berisik saat malam, dan tamu juga meminta pergantian bantal tambahan. Urutan penanganan yang tepat sebagai guest request adalah…\",\"options\":[\"Catat kedua permintaan, tangani yang bisa langsung (antar bantal) sambil melaporkan kerusakan AC via HotelFix agar Engineering menindaklanjuti, informasikan estimasi ke tamu lewat FO\",\"Tangani AC sendiri karena RA dianggap mampu memperbaiki masalah teknis ringan\",\"Abaikan keluhan AC karena bukan permintaan barang, cukup antar bantal saja\",\"Minta tamu pindah kamar tanpa koordinasi dengan FO/Engineering\"],\"answer\":0,\"explanation\":\"Guest request yang melibatkan isu teknis harus dipisah: permintaan barang (bantal) ditangani langsung HK, sedangkan kerusakan AC dilaporkan via HotelFix ke Engineering — RA tidak berwenang memperbaiki AC sendiri, dan komunikasi ke tamu dikoordinasikan lewat FO.\",\"competency\":\"HK-06\"},{\"type\":\"single\",\"text\":\"Chemical disinfectant kamar mandi berlabel dilusi 1:100 untuk permukaan umum, namun untuk area toilet bowl label merekomendasikan 1:10 (lebih pekat). Seorang RA baru mencampur semuanya di satu botol dengan dilusi 1:50 \'rata-rata\'. Apa kesalahan dalam keputusan ini?\",\"options\":[\"Dilusi harus mengikuti label sesuai permukaan targetnya masing-masing; membuat \'rata-rata\' sendiri bukan praktik yang benar dan berisiko under-dilusi (kurang efektif) atau over-dilusi (merusak/boros)\",\"Tidak masalah, dilusi rata-rata selalu aman untuk semua permukaan\",\"Masalahnya hanya soal biaya, bukan soal efektivitas atau keamanan\",\"1:50 justru dilusi paling ideal untuk semua permukaan kamar mandi\"],\"answer\":0,\"explanation\":\"Setiap dilusi dirancang untuk permukaan dan tingkat kontaminasi tertentu (MSDS/label produk). Membuat dilusi \'rata-rata\' sendiri bukan keputusan berbasis SOP — bisa membuat toilet bowl kurang terdisinfeksi atau permukaan lain rusak/boros chemical.\",\"competency\":\"HK-08\"},{\"type\":\"single\",\"text\":\"Kamu bertugas deep cleaning karpet function room yang akan dipakai event besok pagi. Karpet basah setelah proses shampoo dan waktu pengeringan alami butuh 8 jam, sedangkan event dimulai 6 jam lagi. Apa yang harus dilakukan?\",\"options\":[\"Gunakan alat pengering (extractor/blower) untuk mempercepat proses dan laporkan progres ke Supervisor; jika tetap tidak cukup waktu, eskalasi opsi lain (venue alternatif) sebelum event dimulai\",\"Biarkan event tetap berjalan di atas karpet basah tanpa penanganan tambahan\",\"Batalkan deep cleaning dan biarkan karpet kotor untuk event\",\"Percepat dengan menyiram karpet air bersih tambahan supaya proses shampoo \'terulang\' lebih cepat\"],\"answer\":0,\"explanation\":\"Deep cleaning terjadwal yang berbenturan dengan operasional harus ditangani proaktif: pakai alat pengering untuk mempercepat, dan eskalasi ke Supervisor bila risiko tetap ada — bukan membiarkan karpet basah dipakai (bahaya slip, bau lembap) atau mengorbankan hasil kerja.\",\"competency\":\"HK-05\"},{\"type\":\"single\",\"text\":\"Public area toilet tamu di dekat Sunken Pool Bar perlu dibersihkan saat jam operasional ramai. Pendekatan kerja yang tepat adalah…\",\"options\":[\"Cek okupansi toilet dulu, pasang tanda cleaning in progress, bekerja cepat dan efisien tanpa mengganggu tamu yang lalu-lalang, tetap menjaga privasi pengguna\",\"Kunci akses toilet sepenuhnya selama satu jam penuh tanpa pemberitahuan\",\"Bersihkan sambil pintu terbuka lebar agar tamu tahu sedang dikerjakan\",\"Tunda pembersihan sampai jam sepi walau kondisi sudah kotor berat\"],\"answer\":0,\"explanation\":\"Public area cleaning di jam ramai butuh keseimbangan: memberi tanda peringatan, bekerja cepat, dan menjaga privasi pengguna toilet — bukan menutup akses lama tanpa pemberitahuan atau menunda pembersihan yang justru berisiko kebersihan.\",\"competency\":\"HK-10\"},{\"type\":\"single\",\"text\":\"Linen villa yang dipakai untuk outdoor shower (handuk pool) ditemukan berbau apek meski terlihat bersih secara visual. Tindakan yang tepat sesuai handling linen adalah…\",\"options\":[\"Pisahkan sebagai linen bermasalah (bukan dipakai ulang), kembalikan ke proses londri dengan catatan khusus, jangan disemprot pewangi saja untuk menutupi bau\",\"Semprot pewangi ruangan langsung ke handuk supaya bau hilang lalu pakai kembali\",\"Jemur sebentar di bawah matahari villa lalu langsung dipakai ulang tanpa dicuci\",\"Anggap wajar karena area outdoor shower memang lembap\"],\"answer\":0,\"explanation\":\"Bau apek menandakan linen belum tercuci/kering sempurna (kemungkinan masalah proses laundry) — solusinya bukan menutupi dengan pewangi, tapi memisahkan dan mengembalikan ke proses laundry yang benar demi standar higienitas linen tamu.\",\"competency\":\"HK-12\"},{\"type\":\"single\",\"text\":\"Seorang RA level 2 diminta membantu shift malam menangani turndown di area villa sekaligus memantau kebersihan jalur pedestrian menuju kolam umum. Ia menemukan lampu taman padam di satu titik jalur. Tindakan yang tepat adalah…\",\"options\":[\"Laporkan segera via HotelFix untuk perbaikan (risiko keselamatan tamu berjalan malam) sambil tetap menyelesaikan tugas turndown sesuai jadwal\",\"Perbaiki sendiri sambungan lampu karena dianggap tugas ringan\",\"Abaikan karena bukan bagian dari checklist turndown resmi\",\"Hentikan turndown dan fokus penuh menunggu teknisi datang di lokasi lampu\"],\"answer\":0,\"explanation\":\"Public area/keselamatan tamu adalah tanggung jawab bersama — RA melaporkan kerusakan penerangan via HotelFix segera karena berisiko keselamatan malam hari, namun tetap menyelesaikan tugas utamanya (turndown) sesuai jadwal, bukan memperbaiki sendiri atau meninggalkan tugas.\",\"competency\":\"HK-10\"},{\"type\":\"single\",\"text\":\"Kamu ditugaskan deep cleaning mattress kamar Two Bedroom Presidential Pool Villa yang akan kosong 2 hari. Urutan kerja yang tepat mempertimbangkan waktu pengeringan adalah…\",\"options\":[\"Vacuum debu dulu, aplikasikan treatment/chemical sesuai noda, biarkan waktu pengeringan cukup sebelum linen dipasang kembali, manfaatkan window 2 hari kosong secara maksimal\",\"Pasang linen dulu baru dibersihkan di baliknya\",\"Lakukan semua proses dalam satu jam agar kamar cepat siap dijual kembali\",\"Cukup semprot pewangi ke mattress tanpa treatment noda karena waktu terbatas\"],\"answer\":0,\"explanation\":\"Deep cleaning mattress butuh urutan logis (vacuum → treatment → pengeringan) dan window waktu kosong dimanfaatkan untuk memastikan mattress benar-benar kering sebelum linen dipasang — memaksakan waktu terlalu singkat berisiko lembap/bau/jamur.\",\"competency\":\"HK-05\"},{\"type\":\"single\",\"text\":\"Kolam privat di Deluxe Private Pool Villa terlihat keruh saat kamu bertugas membersihkan area villa. Tindakan yang benar sebagai RA (bukan teknisi pool) adalah…\",\"options\":[\"Laporkan kondisi kolam via HotelFix ke tim terkait (Engineering/Pool), jangan menambahkan chemical kolam sendiri karena bukan kompetensi/wewenang HK\",\"Tuang chemical kamar mandi ke kolam untuk menjernihkan air\",\"Kuras kolam sendiri menggunakan selang villa\",\"Abaikan karena bukan bagian dari villa yang perlu dilaporkan\"],\"answer\":0,\"explanation\":\"Perawatan kimia kolam renang adalah kompetensi khusus (bukan chemical kamar mandi/HK) dan berisiko jika ditangani sembarangan — RA melaporkan via HotelFix ke tim yang berwenang, sesuai batas tanggung jawab villa & private pool area.\",\"competency\":\"HK-11\"},{\"type\":\"single\",\"text\":\"Manakah skenario yang PALING menggambarkan penerapan green housekeeping yang benar, bukan sekadar penghematan sepihak?\",\"options\":[\"Menawarkan opsi reuse linen ke tamu sesuai kartu/preferensi, tetap mengganti bila diminta atau linen kotor berat, sambil tetap menjaga standar kebersihan\",\"Mengurangi frekuensi penggantian handuk tanpa mengecek preferensi tamu demi menghemat air\",\"Menggunakan chemical seadanya asal murah tanpa mempertimbangkan dampak lingkungan\",\"Menolak permintaan linen baru dari tamu dengan alasan program hijau\"],\"answer\":0,\"explanation\":\"Green housekeeping yang benar tetap menghormati preferensi dan kebutuhan tamu (linen diganti bila diminta/kotor berat) sambil menawarkan opsi ramah lingkungan — bukan memaksakan penghematan yang mengorbankan kenyamanan atau kebersihan tamu.\",\"competency\":\"HK-17\"},{\"type\":\"single\",\"text\":\"Seekor semut api ditemukan di beberapa titik dekat pintu masuk villa garden saat kamu bertugas. Ini bukan kasus darurat tapi berulang di titik yang sama tiap minggu. Langkah yang tepat sebagai kesadaran pest control adalah…\",\"options\":[\"Catat pola temuan (lokasi & frekuensi) dan laporkan ke Supervisor/tim pest control agar ditindaklanjuti dengan penanganan terjadwal, bukan hanya dibersihkan sesaat\",\"Semprot insektisida rumah tangga sendiri setiap menemukannya\",\"Tutup celah pintu dengan lakban sebagai solusi permanen\",\"Tidak perlu dilaporkan karena bukan kejadian darurat\"],\"answer\":0,\"explanation\":\"Pest control awareness level 2 mencakup kemampuan mengenali pola (lokasi & frekuensi berulang) dan melaporkannya secara terstruktur ke pihak berwenang untuk penanganan preventif terjadwal, bukan hanya reaksi sesaat atau solusi sementara yang tidak menyasar akar masalah.\",\"competency\":\"HK-16\"},{\"type\":\"single\",\"text\":\"RA ditugaskan membersihkan gym & area umum lain sebelum jam buka pukul 06.00. Ia menemukan cermin dinding retak kecil di sudut. Prioritas tindakannya adalah…\",\"options\":[\"Selesaikan cleaning area lain sesuai jadwal, laporkan kerusakan cermin via HotelFix agar dicek Engineering sebelum jam buka demi keselamatan tamu\",\"Tempel cermin retak dengan lakban sendiri sebagai solusi sementara tanpa lapor\",\"Tutup akses gym sepenuhnya tanpa berkoordinasi dengan siapapun\",\"Abaikan retakan kecil karena dianggap tidak berbahaya\"],\"answer\":0,\"explanation\":\"Kerusakan yang berpotensi bahaya (cermin retak) harus dilaporkan via HotelFix agar ditindaklanjuti Engineering sebelum area dibuka ke tamu, sementara tugas cleaning utama tetap diselesaikan sesuai jadwal — bukan solusi darurat sendiri atau mengabaikan risiko.\",\"competency\":\"HK-10\"},{\"type\":\"single\",\"text\":\"Kamu memasang tanda reuse towel tapi tamu tetap meminta penggantian handuk baru setiap hari secara eksplisit lewat request FO. Apa sikap yang tepat sebagai penerapan green housekeeping?\",\"options\":[\"Hormati permintaan eksplisit tamu dan tetap ganti handuk setiap hari — program reuse bersifat opsional bagi tamu, bukan kewajiban\",\"Tolak permintaan tamu dan tetap jalankan program reuse demi target keberlanjutan resort\",\"Ganti handuk hanya setiap 2 hari sekali sebagai kompromi tanpa memberitahu tamu\",\"Laporkan tamu ke Supervisor karena dianggap tidak mendukung program hijau\"],\"answer\":0,\"explanation\":\"Green housekeeping menawarkan pilihan, bukan memaksakan — jika tamu secara eksplisit meminta penggantian harian, permintaan itu harus dihormati sebagai bagian dari guest request standar, bukan diabaikan demi target program.\",\"competency\":\"HK-17\"},{\"type\":\"single\",\"text\":\"Kamu bertugas deep cleaning grouting lantai kamar mandi Deluxe Suite yang menghitam akibat jamur di sela nat. Sikat manual biasa tidak mempan. Pendekatan yang tepat sesuai deep cleaning terjadwal adalah…\",\"options\":[\"Gunakan chemical anti-jamur/mold remover khusus grouting dengan dilusi dan waktu kontak sesuai label serta APD lengkap, bukan menambah tekanan sikat secara berlebihan\",\"Gosok sekuat tenaga dengan sikat kawat baja sampai nat terlihat rusak asal jamur hilang\",\"Tuang pemutih pekat tanpa dilusi langsung ke seluruh lantai kamar mandi\",\"Biarkan karena jamur pada nat dianggap tidak memengaruhi penilaian kebersihan\"],\"answer\":0,\"explanation\":\"Jamur membandel pada grouting butuh chemical khusus dengan waktu kontak yang cukup (bukan sekadar gosokan kasar yang merusak nat atau chemical pekat tanpa dilusi yang berisiko K3) — deep cleaning yang benar memilih produk sesuai masalah, bukan kekuatan fisik semata.\",\"competency\":\"HK-05\"},{\"type\":\"single\",\"text\":\"Kamu ditugaskan membersihkan area koridor dekat Nirvanaloka Spa & Wellness yang licin karena tumpahan minyak aromaterapi dari tamu yang baru keluar treatment. Prioritas tindakan yang benar adalah…\",\"options\":[\"Pasang wet floor sign segera, bersihkan tumpahan dengan chemical degreaser yang sesuai lantai, baru lanjutkan rute cleaning area lain\",\"Lap seadanya dengan air biasa tanpa tanda peringatan karena area dianggap jarang dilalui\",\"Tunggu shift berikutnya membersihkan karena bukan area kamar tamu\",\"Taburkan pengharum ruangan di atas tumpahan agar bau minyak tidak tercium\"],\"answer\":0,\"explanation\":\"Public area cleaning memprioritaskan keselamatan (tanda peringatan) dan penggunaan chemical yang tepat (degreaser untuk minyak, bukan air biasa yang tidak efektif) — menunda atau hanya menutupi bau tidak menghilangkan risiko tamu terpeleset.\",\"competency\":\"HK-10\"}]',85,20,3,'placement','2026-07-08 19:12:48','2026-07-08 19:12:48'),(14,1,NULL,NULL,'HK — Placement Level 3','[{\"type\":\"single\",\"text\":\"Sebagai SPV, kamu melakukan inspeksi kamar dengan checklist 30 titik pada Deluxe Suite yang baru selesai dikerjakan RA. Kamu menemukan 4 titik gagal: debu di bawah nakas, noda air di cermin kamar mandi, hospital corner longgar, dan remote TV tidak disinfeksi. Bagaimana keputusan status kamar dan tindak lanjutnya?\",\"options\":[\"Kamar TIDAK lulus inspeksi — kembalikan ke RA untuk perbaikan 4 titik tersebut sebelum status diubah ke VC, catat hasil inspeksi sebagai bagian KPI RA\",\"Kamar tetap diloloskan ke VC karena 4 dari 30 titik dianggap toleransi kecil\",\"Perbaiki sendiri ke-4 titik tanpa melibatkan RA agar cepat selesai\",\"Naikkan status ke VC dulu, baru minta RA memperbaiki setelah tamu komplain\"],\"answer\":0,\"explanation\":\"SPV yang menemukan kegagalan pada checklist 30 titik wajib mengembalikan kamar untuk diperbaiki RA sebelum diloloskan sebagai VC — meloloskan kamar gagal demi kecepatan atau memperbaiki sendiri tanpa melibatkan RA menghilangkan fungsi coaching dan KPI yang jadi tujuan inspeksi.\",\"competency\":\"HK-18\"},{\"type\":\"single\",\"text\":\"Tim maintenance mengajukan PPM (Preventive Planned Maintenance) untuk servis AC di 6 kamar Premiere Suite pekan depan, bertepatan dengan okupansi diperkirakan 85%. Sebagai SPV HK yang mengoordinasikan dengan FO dan Engineering, langkah pertama yang tepat adalah…\",\"options\":[\"Cross-check forecast okupansi dengan FO, ajukan blocking kamar bertahap (bukan 6 kamar sekaligus) ke Engineering agar dampak ke revenue dan kenyamanan tamu diminimalkan\",\"Setujui PPM 6 kamar sekaligus tanpa cek forecast okupansi karena itu urusan Engineering\",\"Tolak seluruh rencana PPM karena okupansi tinggi, tanpa memberi alternatif jadwal\",\"Biarkan Engineering langsung mengerjakan tanpa koordinasi dengan FO\"],\"answer\":0,\"explanation\":\"Koordinasi PPM kamar yang baik melibatkan cross-check forecast okupansi dengan FO dan pengaturan blocking bertahap dengan Engineering — bukan menyetujui/menolak secara sepihak tanpa data, yang bisa merugikan revenue atau menunda maintenance penting.\",\"competency\":\"HK-19\"},{\"type\":\"single\",\"text\":\"Sanggraloka tidak memiliki mesin laundry sendiri di resort (laundry di-outsource ke vendor eksternal). Saat serah terima linen kotor harian ke vendor, apa yang WAJIB dilakukan sebelum truk vendor berangkat?\",\"options\":[\"Hitung dan catat jumlah linen per kategori sesuai checklist serah terima, cocokkan dengan catatan vendor, keduanya menandatangani sebelum truk berangkat\",\"Serahkan saja karung linen tanpa hitung karena vendor yang akan menghitung sendiri di laundry mereka\",\"Cukup catat total karung tanpa rincian kategori linen\",\"Serah terima dilakukan lisan saja tanpa dokumen karena vendor sudah dipercaya lama\"],\"answer\":0,\"explanation\":\"Karena laundry di-outsource, checklist serah terima dengan hitungan rinci per kategori dan tanda tangan kedua pihak adalah kontrol wajib untuk mencegah selisih/kehilangan linen — tanpa dokumentasi ini, resort tidak punya bukti jika terjadi ketidaksesuaian jumlah saat linen kembali.\",\"competency\":\"HK-20\"},{\"type\":\"single\",\"text\":\"Linen bersih dari vendor laundry outsource kembali ke resort, namun jumlah yang diterima 15 pcs lebih sedikit dari yang dikirim menurut checklist. Sebagai SPV, langkah yang tepat adalah…\",\"options\":[\"Cocokkan checklist penerimaan dengan checklist pengiriman, catat selisih secara tertulis, konfirmasi ke vendor untuk klarifikasi/tindak lanjut sebelum linen dianggap \'diterima lengkap\'\",\"Terima saja apa adanya dan anggap selisih akan terkoreksi di siklus pengiriman berikutnya\",\"Tandatangani bukti terima lengkap agar administrasi tidak ribet, urus selisih belakangan\",\"Salahkan RA yang menghitung linen kotor saat pengiriman tanpa mengecek data vendor\"],\"answer\":0,\"explanation\":\"Selisih jumlah linen harus didokumentasikan dan diklarifikasi ke vendor sebelum tanda terima final ditandatangani — menandatangani \'lengkap\' padahal ada selisih menghilangkan dasar klaim jika linen benar-benar hilang di pihak vendor.\",\"competency\":\"HK-20\"},{\"type\":\"single\",\"text\":\"Seorang tamu Perancis komplain langsung ke SPV bahwa kamarnya (One Bedroom Presidential Pool Villa) \'terasa kurang bersih\' meski RA sudah menyatakan selesai dan lulus checklist. SPV tidak punya assessor lain yang bisa dipanggil saat itu. Tindakan paling tepat adalah…\",\"options\":[\"SPV langsung melakukan re-inspeksi kamar bersama/didampingi tamu bila memungkinkan, identifikasi titik spesifik yang dikeluhkan, perbaiki saat itu juga, dan sampaikan permintaan maaf serta tindak lanjut\",\"Menyalahkan RA di depan tamu dan berjanji mengganti RA lain tanpa mengecek kamar\",\"Menolak komplain karena kamar sudah lulus checklist internal\",\"Menjadwalkan ulang pengecekan besok karena SPV sedang tidak ada assessor lain\"],\"answer\":0,\"explanation\":\"SPV harus mengambil keputusan mandiri saat tidak ada atasan/assessor lain: re-inspeksi langsung, identifikasi masalah konkret, dan perbaiki segera — menyalahkan staf di depan tamu atau menunda respons merusak pengalaman tamu 5-star dan reputasi resort.\",\"competency\":\"HK-18\"},{\"type\":\"single\",\"text\":\"Noda minyak esensial aromaterapi (dari amenity spa) menempel di sprei putih Premiere Private Pool Villa dan sudah mengering lebih dari 24 jam. Chemical noda standar tidak mempan. Sebagai penanggung jawab shift, langkah yang tepat adalah…\",\"options\":[\"Pisahkan linen dengan label detail jenis noda dan lama waktu untuk penanganan khusus vendor laundry outsource (pre-treatment tertentu), jangan dipaksakan dengan chemical kamar biasa\",\"Gosok dengan chemical toilet bowl pekat karena sifatnya lebih kuat\",\"Rendam sendiri di ember kamar dengan pemutih pekat sampai noda hilang\",\"Buang linen tersebut sebagai kerugian karena noda minyak dianggap permanen\"],\"answer\":0,\"explanation\":\"Noda minyak yang mengering butuh pre-treatment khusus yang bukan kapasitas chemical harian HK maupun vendor tanpa informasi — linen harus dilabeli detail (jenis noda, durasi) agar vendor laundry outsource bisa memilih metode yang tepat, bukan ditangani sembarangan atau langsung dianggap rugi.\",\"competency\":\"HK-12\"},{\"type\":\"single\",\"text\":\"Terjadi outbreak keluhan bau tidak sedap dari saluran pembuangan pada blok villa yang sama (3 unit berdekatan) dalam 2 hari terakhir. Sebagai SPV, pendekatan investigasi yang tepat adalah…\",\"options\":[\"Koordinasikan dengan Engineering untuk cek saluran pembuangan blok tersebut sekaligus (bukan kamar per kamar terpisah), karena pola berdekatan mengindikasikan kemungkinan masalah sistem bersama\",\"Tangani tiap villa terpisah dengan pengharum ruangan tanpa melibatkan Engineering\",\"Anggap kebetulan dan tunggu keluhan lebih banyak sebelum bertindak\",\"Pindahkan tamu di 3 villa tersebut tanpa menyelidiki penyebabnya\"],\"answer\":0,\"explanation\":\"Pola keluhan yang mengelompok di blok berdekatan mengindikasikan kemungkinan masalah sistem (saluran bersama), bukan kasus individual — koordinasi PPM dengan Engineering untuk investigasi blok sekaligus lebih efektif daripada menutupi gejala dengan pengharum di tiap unit.\",\"competency\":\"HK-19\"},{\"type\":\"single\",\"text\":\"Saat inspeksi SPV di Two Bedroom Presidential Pool Villa, kamu menemukan RA sudah menyelesaikan make-up room dalam waktu 25 menit — lebih cepat dari target 40 menit, namun 6 dari 30 titik checklist gagal. Bagaimana kamu menilai kinerja ini untuk KPI?\",\"options\":[\"Kecepatan tidak menggantikan kualitas — kamar dinyatakan gagal inspeksi dan dicatat sebagai area perbaikan KPI RA meski waktunya lebih cepat dari target\",\"Nilai RA sebagai sangat baik karena jauh melebihi target waktu 40 menit\",\"Abaikan 6 titik gagal karena kecepatan dianggap lebih penting untuk operasional\",\"Berikan toleransi penuh karena villa besar sulit dikerjakan sempurna\"],\"answer\":0,\"explanation\":\"KPI inspeksi SPV menilai kualitas (30 titik) bukan semata kecepatan — kamar yang gagal di 6 titik tetap harus dicatat sebagai area perbaikan, karena target waktu ≤40 menit dimaksudkan untuk standar kualitas penuh, bukan sekadar cepat selesai.\",\"competency\":\"HK-18\"},{\"type\":\"single\",\"text\":\"Tamu Korea di Deluxe Suite komplain lewat FO bahwa AC berisik sejak semalam dan ia sudah lapor ke RA pagi ini tapi belum ada tindak lanjut sampai siang. Sebagai SPV yang menerima eskalasi dari FO, langkah pertama yang tepat adalah…\",\"options\":[\"Cek status laporan HotelFix (apakah RA benar sudah membuat laporan), percepat koordinasi dengan Engineering, dan informasikan progres nyata ke FO untuk disampaikan ke tamu\",\"Menyalahkan FO karena baru melapor siang hari\",\"Minta tamu menunggu tanpa memberi informasi progres apapun\",\"Pindahkan tamu ke kamar lain tanpa mengecek dulu status laporan kerusakan\"],\"answer\":0,\"explanation\":\"SPV harus melakukan investigasi cepat (cek apakah laporan HotelFix memang dibuat, di mana bottleneck-nya) dan mengoordinasikan percepatan dengan Engineering, sambil menjaga komunikasi transparan lewat FO — bukan menyalahkan pihak lain atau membiarkan tamu tanpa informasi.\",\"competency\":\"HK-19\"},{\"type\":\"single\",\"text\":\"Vendor laundry outsource melaporkan bahwa beberapa linen villa datang dengan noda lipstik yang menempel permanen setelah dicuci standar (noda tidak hilang, bahkan makin melebar). Sebagai SPV, evaluasi yang tepat terhadap situasi ini adalah…\",\"options\":[\"Cek kembali proses pelabelan linen bernoda saat serah terima (apakah noda lipstik dilaporkan sebagai noda khusus atau tercampur linen biasa), lalu diskusikan dengan vendor soal metode pre-treatment yang seharusnya dipakai\",\"Langsung menyalahkan vendor sepenuhnya tanpa mengecek proses internal serah terima\",\"Anggap linen tidak bisa diselamatkan dan langsung dibuang tanpa evaluasi proses\",\"Diamkan saja karena noda lipstik dianggap risiko normal operasional\"],\"answer\":0,\"explanation\":\"Troubleshooting kasus laundry outsource butuh evaluasi dua arah: proses internal (apakah noda dilaporkan/dilabel dengan benar saat serah terima) dan proses vendor (metode pre-treatment) — bukan asumsi sepihak menyalahkan vendor atau membiarkan tanpa evaluasi akar masalah.\",\"competency\":\"HK-20\"},{\"type\":\"single\",\"text\":\"Saat SPV melakukan blocking kamar untuk PPM AC terjadwal, FO menginformasikan ada walk-in group besar mendadak yang butuh kamar tambahan hari yang sama. Sebagai koordinator PPM kamar, keputusan yang tepat adalah…\",\"options\":[\"Evaluasi ulang prioritas bersama FO dan Engineering — kamar PPM non-kritis bisa ditunda beberapa jam/hari, sementara kerusakan berat (safety issue) tetap harus diblok meski walk-in group menekan\",\"Batalkan seluruh rencana PPM demi mengakomodasi walk-in group tanpa mempertimbangkan urgensi maintenance\",\"Tolak seluruh permintaan FO karena jadwal PPM sudah difinalkan dan tidak bisa diubah\",\"Biarkan FO dan Engineering menyelesaikan sendiri tanpa keterlibatan SPV HK\"],\"answer\":0,\"explanation\":\"Koordinasi PPM yang matang mempertimbangkan trade-off: PPM non-kritis fleksibel dijadwal ulang untuk mengakomodasi kebutuhan bisnis mendesak, tapi isu safety-critical tetap tidak bisa dikompromikan — keputusan ini butuh evaluasi bersama, bukan pembatalan/penolakan sepihak.\",\"competency\":\"HK-19\"},{\"type\":\"single\",\"text\":\"Seorang RA baru dipromosikan menjadi SPV dan melakukan inspeksi pertamanya sendirian (tanpa didampingi SPV senior) karena SPV senior cuti. Ia ragu apakah noda samar di karpet Deluxe Suite lolos standar atau tidak. Keputusan paling tepat adalah…\",\"options\":[\"Gunakan checklist 30 titik dan standar foto referensi sebagai acuan objektif untuk memutuskan sendiri, dokumentasikan keputusan (foto before/after) untuk transparansi jika perlu ditinjau nanti\",\"Tunda inspeksi sampai SPV senior kembali dari cuti, meski kamar harus segera dijual\",\"Loloskan otomatis karena ragu-ragu dianggap tanda kondisi \'cukup baik\'\",\"Minta RA yang mengerjakan kamar tersebut yang memutuskan lolos-tidaknya\"],\"answer\":0,\"explanation\":\"SPV baru harus mampu mengambil keputusan mandiri berbasis standar objektif (checklist 30 titik, foto referensi) tanpa menunggu atasan — mendokumentasikan keputusan menjaga akuntabilitas, sementara menunda inspeksi atau melimpahkan ke RA yang mengerjakan menghilangkan fungsi kontrol independen SPV.\",\"competency\":\"HK-18\"},{\"type\":\"single\",\"text\":\"Dua kamar Premiere Suite bersebelahan dibooking oleh grup yang sama dan mereka meminta kedua kamar dibersihkan bersamaan dengan koneksi antar-kamar (connecting door) dibuka untuk keperluan acara pribadi. Sebagai SPV, hal yang perlu dikoordinasikan sebelum menyetujui adalah…\",\"options\":[\"Cek kebijakan resort soal connecting door dan privasi, koordinasi dengan FO soal persetujuan tamu dan keamanan, baru atur jadwal RA untuk kedua kamar secara bersamaan\",\"Langsung setujui dan buka connecting door tanpa mengecek kebijakan atau berkoordinasi FO\",\"Tolak permintaan tanpa penjelasan kepada tamu\",\"Serahkan sepenuhnya keputusan ke RA yang bertugas hari itu\"],\"answer\":0,\"explanation\":\"Permintaan koordinasi blok kamar/connecting door menyentuh aspek keamanan dan kebijakan resort — SPV wajib memverifikasi kebijakan dan berkoordinasi dengan FO sebelum mengatur pelaksanaan teknis oleh RA, bukan diputuskan otomatis atau dilimpahkan begitu saja.\",\"competency\":\"HK-19\"},{\"type\":\"single\",\"text\":\"Vendor laundry outsource baru saja mengganti jenis deterjen tanpa pemberitahuan sebelumnya, dan sejak itu beberapa tamu dengan kulit sensitif komplain gatal setelah memakai handuk resort. Sebagai SPV, langkah investigasi awal yang tepat adalah…\",\"options\":[\"Konfirmasi ke vendor soal perubahan deterjen dan minta MSDS/spesifikasi produk baru, laporkan temuan ke manajemen untuk keputusan lanjutan (tetap pakai/reject/reklamasi)\",\"Ganti semua handuk yang sudah dicuci vendor tanpa berkomunikasi dulu dengan vendor\",\"Anggap komplain tamu tidak terkait deterjen dan cari penyebab lain saja\",\"Diamkan karena vendor sudah dipercaya, tidak perlu dikonfirmasi\"],\"answer\":0,\"explanation\":\"Ketika ada perubahan mendadak dari vendor outsource yang berdampak ke tamu, SPV harus melakukan investigasi berbasis dokumen (MSDS/spesifikasi produk) langsung ke sumbernya (vendor) dan mengeskalasi ke manajemen — bukan berasumsi atau mengabaikan korelasi yang jelas.\",\"competency\":\"HK-20\"},{\"type\":\"single\",\"text\":\"Selama inspeksi rutin, SPV menemukan pola berulang: RA tertentu selalu gagal di titik yang sama (bagian bawah nakas) selama 3 hari berturut-turut meski sudah diberi feedback lisan. Tindakan manajerial yang tepat adalah…\",\"options\":[\"Berikan coaching terstruktur dengan demonstrasi langsung di titik yang gagal, dokumentasikan sebagai bagian catatan kinerja/KPI, tinjau ulang setelah periode tertentu\",\"Diamkan saja karena feedback lisan sudah cukup dan tidak perlu tindak lanjut lagi\",\"Langsung berikan sanksi tanpa coaching tambahan\",\"Pindahkan RA tersebut ke tugas public area tanpa evaluasi penyebab kegagalan\"],\"answer\":0,\"explanation\":\"Pola kegagalan berulang meski sudah diberi feedback lisan menunjukkan perlu pendekatan coaching lebih terstruktur (demonstrasi langsung) dan dokumentasi KPI — bukan dibiarkan, dihukum langsung tanpa pembinaan, atau dipindahtugaskan tanpa evaluasi akar masalah.\",\"competency\":\"HK-18\"},{\"type\":\"single\",\"text\":\"Sebagai SPV yang menerima keluhan tamu Perancis tentang kebersihan kamar, kamu perlu menuliskan laporan singkat untuk manajemen. Manakah struktur laporan yang paling tepat mencerminkan penanganan profesional?\",\"options\":[\"Deskripsi masalah spesifik, tindakan langsung yang diambil, akar penyebab (proses RA/checklist), dan tindak lanjut pencegahan ke depan\",\"Hanya menuliskan bahwa tamu komplain tanpa detail tindakan atau penyebab\",\"Fokus membela kinerja RA tanpa menyebutkan tindakan perbaikan ke tamu\",\"Menyalahkan tamu sebagai terlalu sensitif tanpa evaluasi internal\"],\"answer\":0,\"explanation\":\"Laporan SPV yang baik bersifat aksi dan berorientasi solusi: masalah, tindakan, akar penyebab, dan pencegahan — bukan sekadar mencatat kejadian, membela diri, atau menyalahkan tamu, karena tujuannya perbaikan sistem berkelanjutan.\",\"competency\":\"HK-18\"},{\"type\":\"single\",\"text\":\"Karena resort tidak memiliki mesin laundry sendiri, terjadi keterlambatan pengiriman linen bersih dari vendor outsource pada hari dengan okupansi tinggi, sehingga stok linen bersih di gudang menipis drastis. Sebagai SPV, langkah mitigasi jangka pendek yang tepat adalah…\",\"options\":[\"Hubungi vendor untuk klarifikasi ETA, prioritaskan distribusi linen tersisa ke kamar check-in/VD mendesak dulu, informasikan situasi ke Manager HK untuk keputusan lebih lanjut (misal linen darurat/cadangan)\",\"Tunda semua make-up room sampai linen datang tanpa memberi informasi ke siapapun\",\"Gunakan linen dari kategori berbeda (misal linen restoran) sebagai pengganti tanpa evaluasi kesesuaian\",\"Biarkan RA menentukan sendiri kamar mana yang dapat linen tanpa arahan prioritas\"],\"answer\":0,\"explanation\":\"Keterlambatan vendor outsource pada situasi par stock kritis butuh mitigasi terkoordinasi: klarifikasi ETA ke vendor, prioritisasi distribusi berbasis urgensi kamar, dan eskalasi ke manajemen — bukan solusi ad-hoc yang tidak sesuai standar (linen dari departemen lain) atau dibiarkan tanpa arahan.\",\"competency\":\"HK-20\"},{\"type\":\"single\",\"text\":\"Kamu SPV yang harus memutuskan penempatan RA baru hasil placement test ini: satu kandidat lulus L1 dan L2 teori dengan skor tinggi tapi belum ada uji praktek assessor untuk sesi fisik (W04/W08/W12). Keputusan penempatan yang tepat adalah…\",\"options\":[\"Anggap hasil sebagai level teori provisional saja — tetap jadwalkan uji praktek assessor sebelum skill matrix final dan penempatan definitif diputuskan\",\"Langsung tempatkan di level tertinggi yang lulus teori tanpa uji praktek karena skor placement sudah cukup meyakinkan\",\"Abaikan hasil placement test sepenuhnya dan mulai dari level 1 praktek tanpa pertimbangan skor teori\",\"Minta kandidat mengulang placement test teori berkali-kali sampai yakin, tanpa pernah menjadwalkan praktek\"],\"answer\":0,\"explanation\":\"Sesuai aturan placement test Sanggraloka, hasil teori bersifat provisional — konfirmasi akhir penempatan tetap memerlukan uji praktek assessor pada sesi fisik sebelum skill matrix terisi definitif, tidak cukup hanya mengandalkan skor teori setinggi apapun.\",\"competency\":\"HK-18\"},{\"type\":\"single\",\"text\":\"SPV menerima laporan dari dua RA berbeda pada hari yang sama: RA A menyelesaikan 9 kamar dengan rata-rata 3 titik gagal per kamar, RA B menyelesaikan 6 kamar dengan 0 titik gagal. Bagaimana SPV menilai kedua kinerja ini secara adil untuk skill matrix?\",\"options\":[\"Nilai keduanya berdasarkan kombinasi kualitas (tingkat kegagalan checklist) dan produktivitas (jumlah kamar), bukan hanya salah satu — beri catatan spesifik: RA A perlu perbaikan kualitas, RA B bisa ditingkatkan produktivitasnya\",\"RA A otomatis dinilai lebih baik karena menyelesaikan lebih banyak kamar\",\"RA B otomatis dinilai lebih baik dan RA A dianggap gagal total tanpa melihat detail titik yang gagal\",\"Abaikan keduanya karena jumlah kamar dan tingkat kegagalan tidak bisa dibandingkan\"],\"answer\":0,\"explanation\":\"Penilaian kinerja SPV yang matang mempertimbangkan dua dimensi (kualitas dan produktivitas) secara seimbang dan memberi feedback spesifik untuk pengembangan masing-masing — bukan menilai sepihak dari satu angka saja, karena itu bisa mendorong RA mengorbankan kualitas demi kecepatan atau sebaliknya.\",\"competency\":\"HK-18\"},{\"type\":\"single\",\"text\":\"Manager HK meminta SPV mengevaluasi apakah kontrak vendor laundry outsource saat ini masih layak dilanjutkan, setelah beberapa bulan terakhir muncul berulang kali masalah (keterlambatan, selisih linen, komplain kualitas cuci). Pendekatan evaluasi yang tepat adalah…\",\"options\":[\"Kumpulkan data terdokumentasi (checklist serah terima, catatan selisih, komplain tamu terkait linen) selama periode tertentu sebagai dasar objektif rekomendasi ke manajemen, bukan opini sesaat\",\"Merekomendasikan putus kontrak berdasarkan kesan umum tanpa data pendukung tertulis\",\"Mempertahankan vendor tanpa evaluasi karena mengganti vendor dianggap merepotkan\",\"Menyerahkan keputusan sepenuhnya ke bagian purchasing tanpa memberi input dari sisi operasional HK\"],\"answer\":0,\"explanation\":\"Evaluasi vendor outsource yang kredibel harus berbasis data terdokumentasi dari waktu ke waktu (bukan kesan sesaat atau menghindari keputusan) — SPV HK punya peran penting memberi input operasional berbasis bukti karena merekalah yang berhadapan langsung dengan dampak masalah vendor sehari-hari.\",\"competency\":\"HK-20\"}]',85,25,3,'placement','2026-07-08 19:12:48','2026-07-08 19:12:48'),(15,1,19,NULL,'Test — GEN-L1-W01 — Grooming & Aturan Kerja: Kesan Pertama Sanggraloka','[{\"type\":\"single\",\"text\":\"Berapa lama tamu membentuk kesan pertama?\",\"options\":[\"7 detik\",\"5 menit\",\"1 jam\",\"Setelah check-out\"],\"answer\":0,\"explanation\":\"Kesan terbentuk sebelum Anda berbicara.\"},{\"type\":\"single\",\"text\":\"Name tag dipakai di…\",\"options\":[\"Dada kiri\",\"Dada kanan\",\"Saku celana\",\"Bebas\"],\"answer\":0,\"explanation\":\"Name tag selalu dipakai di dada kiri agar mudah terlihat tamu dan menunjukkan identitas kita dengan rapi—ini bagian dari standar penampilan profesional di Sanggraloka Ubud.\"},{\"type\":\"single\",\"text\":\"Menitipkan absen fingerprint ke teman termasuk…\",\"options\":[\"Pelanggaran berat\",\"Boleh jika terburu-buru\",\"Boleh sekali sebulan\",\"Kebiasaan wajar\"],\"answer\":0,\"explanation\":\"Integritas absensi adalah dasar kepercayaan.\"},{\"type\":\"single\",\"text\":\"Standar kuku untuk staf F&B/Spa:\",\"options\":[\"Pendek, bersih, tanpa kutek\",\"Boleh kutek bening panjang\",\"Bebas asal bersih\",\"Panjang rapi\"],\"answer\":0,\"explanation\":\"Kuku pendek, bersih, dan tanpa kutek wajib bagi staf F&B/Spa demi menjaga higienitas makanan dan kenyamanan tamu saat perawatan di Nirvanaloka Spa; kutek atau kuku panjang berisiko menyembunyikan kotoran atau terlepas ke makanan/tubuh tamu.\"},{\"type\":\"single\",\"text\":\"HP pribadi di area tamu:\",\"options\":[\"Tidak dipakai\",\"Boleh untuk chat singkat\",\"Boleh jika penting\",\"Boleh dengan earphone\"],\"answer\":0,\"explanation\":\"HP pribadi tidak digunakan di area tamu karena bisa mengurangi fokus pelayanan dan terkesan tidak profesional di mata tamu; sekalipun terasa sebentar atau penting, tamu tetap layak mendapat perhatian penuh kita.\"}]',80,10,3,'course','2026-07-08 19:12:48','2026-07-08 19:12:48'),(16,1,20,NULL,'Test — GEN-L1-W02 — Greeting, 10/5 Rule & Salam Sanggraloka','[{\"type\":\"single\",\"text\":\"Pada jarak 5 langkah dari tamu, Anda harus…\",\"options\":[\"Menyapa lebih dulu\",\"Menunduk\",\"Menunggu disapa\",\"Menyingkir\"],\"answer\":0,\"explanation\":\"Pada jarak 5 langkah, kita menyapa tamu lebih dulu dengan senyum agar tamu merasa disambut dan diperhatikan sejak awal; menunggu disapa atau menyingkir justru membuat tamu merasa diabaikan.\"},{\"type\":\"single\",\"text\":\"Pengganti kalimat \\\"I don\'t know\\\":\",\"options\":[\"Let me check for you\",\"Ask reception\",\"Maybe\",\"Sorry, no idea\"],\"answer\":0,\"explanation\":\"\\\"Let me check for you\\\" tetap menunjukkan kepedulian dan tanggung jawab meski kita belum tahu jawabannya, sedangkan jawaban seperti \\\"sorry, no idea\\\" atau melempar ke pihak lain terkesan lepas tangan dan kurang hangat di mata tamu.\"},{\"type\":\"single\",\"text\":\"Salam khas sambutan Sanggraloka:\",\"options\":[\"Om Swastiastu + anjali\",\"Halo bos\",\"Selamat datang saja\",\"High five\"],\"answer\":0,\"explanation\":\"Salam khas Sanggraloka Ubud adalah ucapan \\\"Om Swastiastu\\\" disertai gerakan anjali (tangan menangkup), yang mencerminkan filosofi Tri Hita Karana dan memberi kesan sambutan yang tulus serta khas Bali; sapaan umum seperti \\\"halo bos\\\" tidak mewakili identitas resort kita.\"},{\"type\":\"single\",\"text\":\"Pada jarak 10 langkah:\",\"options\":[\"Kontak mata + senyum\",\"Berteriak menyapa\",\"Pura-pura sibuk\",\"Foto tamu\"],\"answer\":0,\"explanation\":\"Pada jarak 10 langkah, cukup lakukan kontak mata dan senyum agar tamu merasa diperhatikan tanpa terkesan berlebihan; berteriak menyapa dari jauh justru kurang sopan dan bisa mengganggu suasana tenang resort.\"},{\"type\":\"single\",\"text\":\"Cara terbaik menyapa tamu yang namanya kita tahu:\",\"options\":[\"Good morning, Mr Kim\",\"Hey mister\",\"Pak/Bu saja\",\"Tidak perlu nama\"],\"answer\":0,\"explanation\":\"Nama = personal recognition.\"}]',80,10,3,'course','2026-07-08 19:12:48','2026-07-08 19:12:48'),(17,1,21,NULL,'Test — GEN-L1-W03 — Telephone Manner & Aplikasi Kerja','[{\"type\":\"single\",\"text\":\"Telepon harus diangkat maksimal…\",\"options\":[\"3 dering\",\"5 dering\",\"10 dering\",\"Kapan sempat\"],\"answer\":0,\"explanation\":\"Standar Sanggraloka adalah mengangkat telepon maksimal 3 dering agar tamu tidak menunggu lama dan merasa diprioritaskan; menunggu lebih dari itu bisa memberi kesan pelayanan yang lambat.\"},{\"type\":\"single\",\"text\":\"Sebelum hold, Anda harus…\",\"options\":[\"Minta ijin & maks 30 detik\",\"Langsung hold\",\"Tutup saja\",\"Diamkan\"],\"answer\":0,\"explanation\":\"Selalu minta izin dulu sebelum hold dan batasi maksimal 30 detik, karena tamu berhak tahu kenapa ditahan dan tidak dibiarkan menunggu tanpa kepastian; langsung hold tanpa izin terasa tidak menghargai waktu tamu.\"},{\"type\":\"single\",\"text\":\"Melihat lampu koridor mati, Anda…\",\"options\":[\"Lapor via HotelFix dgn foto\",\"Abaikan, bukan tugas saya\",\"Tunggu ada yang komplain\",\"Bilang lisan kapan-kapan\"],\"answer\":0,\"explanation\":\"Segera laporkan lewat aplikasi HotelFix disertai foto agar tim maintenance punya bukti jelas dan bisa langsung menindaklanjuti; menunggu komplain tamu atau menganggap bukan tugas kita bisa berdampak pada kenyamanan dan keselamatan tamu.\"},{\"type\":\"single\",\"text\":\"Slip gaji dilihat di…\",\"options\":[\"HotelCrew dengan PIN\",\"Kertas dari HR\",\"Email umum\",\"WhatsApp grup\"],\"answer\":0,\"explanation\":\"Slip gaji diakses lewat aplikasi HotelCrew dengan PIN pribadi agar data gaji tetap rahasia dan hanya bisa dilihat oleh yang bersangkutan; menyebarkannya lewat email umum atau grup WhatsApp berisiko membuka informasi pribadi ke pihak yang tidak berhak.\"},{\"type\":\"single\",\"text\":\"Mengakhiri telepon dengan tamu:\",\"options\":[\"Tamu menutup lebih dulu\",\"Tutup cepat agar hemat\",\"Katakan bye lalu banting\",\"Hold selamanya\"],\"answer\":0,\"explanation\":\"Biarkan tamu yang menutup telepon lebih dulu sebagai bentuk sopan santun dan penghormatan, karena bisa jadi tamu masih ingin menyampaikan sesuatu; menutup telepon terburu-buru bisa terkesan tidak sabar melayani.\"}]',80,10,3,'course','2026-07-08 19:12:49','2026-07-08 19:12:49'),(18,1,23,NULL,'Test — GEN-L1-W05 — Product Knowledge: Resort & Ubud di Genggamanmu','[{\"type\":\"single\",\"text\":\"Restoran farm-to-table kita bernama…\",\"options\":[\"Meditera\",\"Segening\",\"Sunken\",\"Nirvanaloka\"],\"answer\":0,\"explanation\":\"Meditera Restaurant/Bar adalah outlet farm-to-table kita yang menyajikan hasil kebun lokal; Segening dan Sunken Pool Bar adalah outlet F&B lain, sementara Nirvanaloka justru nama spa kita, bukan restoran.\"},{\"type\":\"single\",\"text\":\"Spa & wellness center kita bernama…\",\"options\":[\"Nirvanaloka\",\"Anandam\",\"Sanggraloka Spa\",\"Meditera Spa\"],\"answer\":0,\"explanation\":\"Nirvanaloka Spa adalah nama resmi spa & wellness center Sanggraloka Ubud; nama-nama lain seperti Meditera Spa hanya menggabungkan istilah restoran kita secara keliru, bukan nama outlet spa yang sebenarnya.\"},{\"type\":\"single\",\"text\":\"Tamu tanya jam breakfast. Jawaban:\",\"options\":[\"07.00–10.30\",\"06.00–09.00\",\"08.00–12.00\",\"24 jam\"],\"answer\":0,\"explanation\":\"Jam breakfast resmi Sanggraloka adalah pukul 07.00–10.30, jadi ini jawaban yang perlu selalu kita ingat dan sampaikan dengan pasti agar tamu bisa mengatur rencana paginya dengan nyaman.\"},{\"type\":\"single\",\"text\":\"Jarak ke pusat Ubud kira-kira…\",\"options\":[\"20 menit\",\"5 menit\",\"2 jam\",\"10 jam\"],\"answer\":0,\"explanation\":\"Dari lokasi kita di Bresela-Payangan, pusat Ubud dapat ditempuh sekitar 20 menit berkendara, informasi penting yang sering ditanyakan tamu yang ingin berkeliling; jawaban lain terlalu singkat atau terlalu jauh dari kenyataan.\"},{\"type\":\"single\",\"text\":\"Tamu ingin tur sawah. Respon terbaik:\",\"options\":[\"Tawarkan bantuan booking via concierge\",\"Suruh cari di Google\",\"Bilang tidak tahu\",\"Abaikan\"],\"answer\":0,\"explanation\":\"Menawarkan bantuan booking lewat concierge menunjukkan kepedulian aktif kita terhadap kebutuhan tamu, sesuai semangat pelayanan Sanggraloka; menyuruh tamu mencari sendiri di Google membuat tamu merasa dilepas begitu saja.\"}]',80,10,3,'course','2026-07-08 19:12:49','2026-07-08 19:12:49'),(19,1,24,NULL,'Test — GEN-L1-W06 — Tri Hita Karana: Jiwa Pelayanan Sanggraloka','[{\"type\":\"single\",\"text\":\"Palemahan berarti harmoni dengan…\",\"options\":[\"Alam\",\"Tuhan\",\"Manusia\",\"Uang\"],\"answer\":0,\"explanation\":\"Palemahan adalah salah satu pilar Tri Hita Karana yang berarti harmoni manusia dengan alam; harmoni dengan Tuhan disebut Parhyangan dan harmoni dengan sesama manusia disebut Pawongan.\"},{\"type\":\"single\",\"text\":\"Melihat canang di lantai, Anda…\",\"options\":[\"Tidak melangkahinya\",\"Melangkahi saja\",\"Menendang pelan\",\"Membuangnya\"],\"answer\":0,\"explanation\":\"Canang adalah persembahan suci, jadi kita menghindari melangkahinya sebagai bentuk hormat pada nilai spiritual Bali dan filosofi Tri Hita Karana; melangkahi, menendang, atau membuangnya dianggap tidak sopan secara adat.\"},{\"type\":\"single\",\"text\":\"Wujud palemahan di kerja harian:\",\"options\":[\"Matikan lampu area kosong\",\"Nyalakan semua AC\",\"Buang sampah campur\",\"Cetak kertas banyak\"],\"answer\":0,\"explanation\":\"Mematikan lampu di area kosong adalah wujud nyata palemahan (harmoni dengan alam) yang sejalan dengan nilai eco-luxury Sanggraloka; kebiasaan seperti menyalakan semua AC atau boros kertas justru bertentangan dengan prinsip ini.\"},{\"type\":\"single\",\"text\":\"Pawongan tercermin saat…\",\"options\":[\"Rekan kerja diperlakukan sehangat tamu\",\"Hanya ramah ke tamu\",\"Ramah ke atasan saja\",\"Diam ke semua\"],\"answer\":0,\"explanation\":\"Pawongan adalah harmoni antar sesama manusia, sehingga sikap ramah semestinya berlaku untuk semua orang termasuk rekan kerja, bukan hanya kepada tamu atau atasan saja.\"},{\"type\":\"single\",\"text\":\"Positioning Sanggraloka:\",\"options\":[\"Eco-luxury farm-to-table\",\"Hotel bisnis kota\",\"Hostel backpacker\",\"Casino resort\"],\"answer\":0,\"explanation\":\"Sanggraloka Ubud memposisikan diri sebagai eco-luxury resort dengan konsep farm-to-table di kawasan Bresela-Payangan, sangat berbeda dari hotel bisnis kota atau hostel backpacker yang tidak mencerminkan identitas kita.\"}]',80,10,3,'course','2026-07-08 19:12:49','2026-07-08 19:12:49'),(20,1,25,NULL,'Test — GEN-L1-W07 — Handling Complaint: Metode L.E.A.R.N & Upselling Halus','[{\"type\":\"single\",\"text\":\"Huruf pertama LEARN berarti…\",\"options\":[\"Listen\",\"Laugh\",\"Leave\",\"Lie\"],\"answer\":0,\"explanation\":\"Huruf L pada metode LEARN berarti Listen (dengarkan), langkah pertama menangani komplain agar tamu merasa didengar sebelum kita merespons; pilihan lain seperti Laugh atau Leave tidak sesuai dengan tujuan metode ini.\"},{\"type\":\"single\",\"text\":\"Tamu marah AC mati. Langkah pertama:\",\"options\":[\"Dengarkan penuh tanpa memotong\",\"Salahkan engineering\",\"Jelaskan panjang lebar\",\"Pergi diam-diam\"],\"answer\":0,\"explanation\":\"Langkah pertama adalah mendengarkan penuh tanpa memotong agar tamu merasa keluhannya dihargai, sesuai huruf L (Listen) pada metode LEARN; menyalahkan departemen lain atau langsung menjelaskan panjang lebar membuat tamu merasa tidak didengarkan.\"},{\"type\":\"single\",\"text\":\"\\\"Menyalahkan departemen lain di depan tamu\\\" adalah…\",\"options\":[\"Dilarang\",\"Boleh jika benar\",\"Wajib\",\"Lucu\"],\"answer\":0,\"explanation\":\"Menyalahkan departemen lain di depan tamu dilarang karena bagi tamu, kita semua adalah satu tim Sanggraloka; sekalipun kesalahan memang ada di departemen lain, sebaiknya diselesaikan secara internal, bukan di hadapan tamu.\"},{\"type\":\"single\",\"text\":\"Upselling terbaik dilakukan…\",\"options\":[\"Sesuai kebutuhan tamu, satu kalimat\",\"Berkali-kali sampai mau\",\"Dengan menakut-nakuti\",\"Ke semua tamu sama\"],\"answer\":0,\"explanation\":\"Upselling paling efektif dilakukan singkat dan relevan dengan kebutuhan tamu, misalnya menawarkan paket spa di Nirvanaloka saat tamu terlihat lelah; memaksa berkali-kali atau menyamaratakan semua tamu justru terasa mengganggu.\"},{\"type\":\"single\",\"text\":\"Setelah masalah selesai (N pada LEARN):\",\"options\":[\"Pastikan tamu tahu + catat\",\"Diam saja\",\"Minta tip\",\"Cerita ke rekan\"],\"answer\":0,\"explanation\":\"Tahap terakhir LEARN adalah memastikan tamu tahu masalah sudah selesai serta mencatatnya untuk pembelajaran ke depan; berdiam diri atau hanya bercerita ke rekan tidak menyelesaikan siklus penanganan komplain dengan baik.\"}]',80,10,3,'course','2026-07-08 19:12:49','2026-07-08 19:12:49'),(21,1,27,NULL,'Test — GEN-L1-W09 — K3 & Fire Safety: Bekerja Aman Setiap Hari','[{\"type\":\"single\",\"text\":\"Saat kebakaran, lift…\",\"options\":[\"Tidak boleh dipakai\",\"Boleh jika buru-buru\",\"Khusus tamu VIP\",\"Paling aman\"],\"answer\":0,\"explanation\":\"Lift tidak boleh dipakai saat kebakaran karena berisiko mati listrik dan membuat penumpang terjebak; gunakan tangga darurat menuju titik kumpul meskipun terasa lebih lama, demi keselamatan bersama.\"},{\"type\":\"single\",\"text\":\"P.A.S.S: huruf A berarti…\",\"options\":[\"Aim ke dasar api\",\"Alarm\",\"Ambil air\",\"Awas\"],\"answer\":0,\"explanation\":\"Huruf A pada teknik P.A.S.S berarti Aim, yaitu mengarahkan nozzle APAR ke dasar api (bukan ke atas kobaran), karena dasar api adalah sumber pembakaran yang perlu dipadamkan langsung.\"},{\"type\":\"single\",\"text\":\"Lantai baru dipel, langkah pertama…\",\"options\":[\"Pasang wet floor sign\",\"Biarkan cepat kering\",\"Tunggu ada yg jatuh\",\"Lap pakai gorden\"],\"answer\":0,\"explanation\":\"Pasang wet floor sign segera setelah mengepel agar tamu dan rekan kerja waspada terhadap lantai licin dan terhindar dari risiko terpeleset; menunggu sampai ada yang jatuh baru bertindak sudah terlambat dan berbahaya.\"},{\"type\":\"single\",\"text\":\"Near-miss (hampir celaka) sebaiknya…\",\"options\":[\"Dilaporkan\",\"Dirahasiakan\",\"Ditertawakan\",\"Diabaikan\"],\"answer\":0,\"explanation\":\"Near-miss tetap perlu dilaporkan meskipun tidak ada yang terluka, karena ini menjadi peringatan dini agar kejadian serupa tidak berulang dan bisa segera diperbaiki; merahasiakan atau mengabaikannya justru membiarkan bahaya tetap ada.\"},{\"type\":\"single\",\"text\":\"Chemical pembersih dipindah ke botol air mineral:\",\"options\":[\"Dilarang keras\",\"Boleh asal diberi label kecil\",\"Hemat tempat\",\"Praktis\"],\"answer\":0,\"explanation\":\"Ini dilarang keras karena sangat berbahaya—chemical dalam botol air mineral bisa tertukar dan tertelan siapa saja yang mengira isinya air minum; gunakan selalu wadah asli atau botol khusus berlabel jelas demi keselamatan bersama.\"}]',80,10,3,'course','2026-07-08 19:12:49','2026-07-08 19:12:49'),(22,1,28,NULL,'Test — GEN-L1-W10 — Hygiene, Privasi Tamu & Saling Menghormati','[{\"type\":\"single\",\"text\":\"Penelepon menanyakan nomor kamar tamu:\",\"options\":[\"Tidak diberikan, tawarkan sambungkan\",\"Beri jika mengaku keluarga\",\"Beri jika memaksa\",\"Tulis di kertas\"],\"answer\":0,\"explanation\":\"Demi privasi dan keamanan tamu, nomor kamar tidak pernah diberikan langsung—cukup tawarkan untuk menyambungkan telepon ke kamar tamu; mengaku keluarga atau memaksa bukan jaminan identitas yang bisa kita percaya begitu saja.\"},{\"type\":\"single\",\"text\":\"Memfoto tamu untuk story pribadi:\",\"options\":[\"Dilarang\",\"Boleh jika tamu terkenal\",\"Boleh tanpa wajah\",\"Boleh malam hari\"],\"answer\":0,\"explanation\":\"Memfoto tamu untuk kepentingan pribadi dilarang karena melanggar privasi tamu, sekalipun tamu tersebut terkenal atau wajahnya tidak terlihat jelas dalam foto; privasi tamu harus selalu dihormati tanpa pengecualian.\"},{\"type\":\"single\",\"text\":\"Cuci tangan yang benar minimal…\",\"options\":[\"20 detik\",\"3 detik\",\"1 menit tiap jam\",\"Hanya jika kotor\"],\"answer\":0,\"explanation\":\"Cuci tangan yang efektif membutuhkan waktu minimal 20 detik dengan sabun agar kuman benar-benar hilang, terutama penting bagi staf F&B; mencuci hanya 3 detik atau menunggu tangan terlihat kotor tidak cukup menjaga higienitas.\"},{\"type\":\"single\",\"text\":\"Mengalami pelecehan dari tamu, Anda…\",\"options\":[\"Lapor kanal rahasia di app\",\"Diam karena tamu raja\",\"Balas di medsos\",\"Resign\"],\"answer\":0,\"explanation\":\"Pelapor dilindungi.\"},{\"type\":\"single\",\"text\":\"Staf F&B terkena diare sebaiknya…\",\"options\":[\"Lapor SPV sebelum shift\",\"Masuk sambil minum obat\",\"Diam saja\",\"Tukar shift diam-diam\"],\"answer\":0,\"explanation\":\"Staf F&B yang terkena diare wajib lapor SPV sebelum shift karena berisiko menularkan lewat makanan yang disajikan ke tamu; tetap masuk kerja sambil minum obat atau menyembunyikannya membahayakan kesehatan tamu dan rekan kerja.\"}]',80,10,3,'course','2026-07-08 19:12:49','2026-07-08 19:12:49'),(23,1,29,2,'Test — GEN-L1-W11 — Bonjour & Annyeonghaseyo: 15 Frasa Pertamamu','[{\"type\":\"single\",\"text\":\"Sapaan malam hari utk tamu Perancis:\",\"options\":[\"Bonsoir\",\"Bonjour\",\"Bon appétit\",\"Merci\"],\"answer\":0,\"explanation\":\"\\\"Bonsoir\\\" adalah sapaan yang tepat untuk malam hari kepada tamu Perancis, sedangkan \\\"Bonjour\\\" dipakai untuk pagi/siang, \\\"Bon appétit\\\" berarti selamat makan, dan \\\"Merci\\\" berarti terima kasih—masing-masing punya konteks berbeda.\"},{\"type\":\"single\",\"text\":\"\\\"Terima kasih\\\" dalam bahasa Korea:\",\"options\":[\"Gamsahamnida\",\"Annyeonghaseyo\",\"Jamsimanyo\",\"Ne\"],\"answer\":0,\"explanation\":\"\\\"Gamsahamnida\\\" adalah cara mengucapkan terima kasih dalam bahasa Korea, berguna saat melayani tamu Korea yang menjadi salah satu tamu utama Sanggraloka; \\\"Annyeonghaseyo\\\" berarti salam/halo, bukan terima kasih.\"},{\"type\":\"single\",\"text\":\"Tamu bernama Kim Min-jun disapa…\",\"options\":[\"Mr Kim\",\"Mr Jun\",\"Mr Min\",\"Kim saja\"],\"answer\":0,\"explanation\":\"Dalam nama Korea, kata pertama (Kim) adalah nama keluarga/marga sehingga sapaan formal yang benar adalah \\\"Mr Kim\\\", bukan \\\"Mr Jun\\\" atau \\\"Mr Min\\\" yang merupakan bagian dari nama depan Min-jun.\"},{\"type\":\"single\",\"text\":\"Saat menyajikan makanan ke tamu Korea:\",\"options\":[\"Masitge deuseyo\",\"Jamsimanyo\",\"Gamsahamnida\",\"Annyeong\"],\"answer\":0,\"explanation\":\"\\\"Masitge deuseyo\\\" berarti \\\"selamat menikmati\\\" dalam bahasa Korea, ucapan hangat yang pas saat menyajikan hidangan di Meditera atau Segening; pilihan lain seperti \\\"Gamsahamnida\\\" (terima kasih) tidak sesuai konteks penyajian makanan.\"},{\"type\":\"single\",\"text\":\"\\\"Sama-sama\\\" dalam bahasa Perancis:\",\"options\":[\"Je vous en prie\",\"Bonsoir\",\"Attention\",\"Oui\"],\"answer\":0,\"explanation\":\"\\\"Je vous en prie\\\" adalah ungkapan sopan untuk \\\"sama-sama\\\" dalam bahasa Perancis, cocok digunakan saat tamu Perancis berterima kasih kepada kita; \\\"Bonsoir\\\" berarti selamat malam dan \\\"Oui\\\" berarti ya, jadi maknanya berbeda.\"}]',80,10,3,'course','2026-07-08 19:12:49','2026-07-08 19:12:49'),(24,1,30,2,'Test — GEN-L1-W12 — UJI LEVEL 1: Drill Evakuasi, P3K & Ujian Akhir','[{\"type\":\"single\",\"text\":\"Saat alarm berbunyi, tamu diarahkan ke…\",\"options\":[\"Jalur evakuasi & titik kumpul\",\"Lobby untuk foto\",\"Kamar masing-masing\",\"Lift terdekat\"],\"answer\":0,\"explanation\":\"Saat alarm berbunyi, tamu diarahkan tenang menuju jalur evakuasi dan titik kumpul yang telah ditentukan demi keselamatan bersama; kembali ke kamar atau menggunakan lift justru berisiko tinggi saat keadaan darurat.\"},{\"type\":\"single\",\"text\":\"Orang pingsan namun bernapas → posisikan…\",\"options\":[\"Posisi pemulihan (miring)\",\"Duduk tegak\",\"Berdiri\",\"Telungkup\"],\"answer\":0,\"explanation\":\"Posisi pemulihan (miring) menjaga jalan napas tetap terbuka dan mencegah tersedak jika muntah, sehingga menjadi posisi teraman untuk orang pingsan yang masih bernapas; posisi duduk atau telungkup tidak melindungi jalan napasnya.\"},{\"type\":\"single\",\"text\":\"Standar sapa jarak 5 langkah + tamu Perancis pagi hari:\",\"options\":[\"Senyum + Bonjour\",\"Diam\",\"Lambaian\",\"Bonsoir\"],\"answer\":0,\"explanation\":\"Pada jarak 5 langkah, sapa tamu lebih dulu dengan senyum dan ucapan \\\"Bonjour\\\" karena itu sapaan pagi/siang yang tepat untuk tamu Perancis; \\\"Bonsoir\\\" hanya digunakan pada malam hari.\"},{\"type\":\"single\",\"text\":\"Komplain ditangani dengan metode…\",\"options\":[\"LEARN\",\"SPEED\",\"PASS\",\"GROW\"],\"answer\":0,\"explanation\":\"Metode LEARN (Listen, Empathize, Apologize, Resolve, Notify) adalah kerangka kerja kita untuk menangani komplain tamu secara sistematis; PASS sendiri adalah teknik penggunaan APAR, jadi keduanya punya fungsi berbeda.\"},{\"type\":\"single\",\"text\":\"Data kamar tamu boleh diberikan kepada…\",\"options\":[\"Tidak siapa pun di luar kebutuhan kerja\",\"Keluarga penelepon\",\"Sesama staf grup WA\",\"Teman dekat\"],\"answer\":0,\"explanation\":\"Data kamar tamu bersifat rahasia dan hanya boleh diakses untuk kebutuhan pekerjaan resmi; membagikannya ke pihak yang mengaku keluarga, grup WhatsApp, atau teman dekat melanggar privasi dan keamanan tamu.\"},{\"type\":\"single\",\"text\":\"APAR digunakan dengan teknik…\",\"options\":[\"PASS\",\"LEARN\",\"THK\",\"QRIS\"],\"answer\":0,\"explanation\":\"Teknik PASS (Pull, Aim, Squeeze, Sweep) adalah cara benar menggunakan APAR untuk memadamkan api; LEARN sendiri adalah metode menangani komplain tamu, bukan untuk pemadaman kebakaran.\"},{\"type\":\"single\",\"text\":\"Palemahan diwujudkan dengan…\",\"options\":[\"Hemat energi & pilah sampah\",\"Menyapa tamu\",\"Sembahyang\",\"Diskon\"],\"answer\":0,\"explanation\":\"Palemahan (harmoni dengan alam) diwujudkan lewat tindakan nyata seperti hemat energi dan memilah sampah, sejalan dengan semangat eco-luxury Sanggraloka; menyapa tamu justru lebih dekat pada nilai Pawongan.\"},{\"type\":\"single\",\"text\":\"Breakfast Sanggraloka pukul…\",\"options\":[\"07.00–10.30\",\"05.00–08.00\",\"09.00–14.00\",\"24 jam\"],\"answer\":0,\"explanation\":\"Jam breakfast resmi Sanggraloka adalah pukul 07.00–10.30, informasi dasar yang perlu diingat setiap staf agar bisa menjawab pertanyaan tamu dengan sigap dan tepat.\"},{\"type\":\"single\",\"text\":\"Lapor kerusakan memakai aplikasi…\",\"options\":[\"HotelFix\",\"HotelCrew\",\"WhatsApp\",\"Email\"],\"answer\":0,\"explanation\":\"HotelFix adalah aplikasi khusus untuk melaporkan kerusakan atau kebutuhan maintenance agar tercatat rapi dan cepat ditindaklanjuti; HotelCrew digunakan untuk urusan operasional lain seperti absensi dan slip gaji.\"},{\"type\":\"single\",\"text\":\"Syarat lulus Level 1:\",\"options\":[\"Kuis + 2 praktek + ujian ≥80 + drill\",\"Hadir saja\",\"Bayar\",\"Kenal HR\"],\"answer\":0,\"explanation\":\"Kelulusan Level 1 ditentukan dari kombinasi kuis mingguan, dua sesi praktek, nilai ujian minimal 80, dan drill—bukan sekadar hadir, membayar, atau kenal HR—karena tujuannya memastikan kesiapan nyata sebelum bertugas.\"}]',80,10,3,'course','2026-07-08 19:12:49','2026-07-08 19:12:49'),(25,1,31,3,'Test — GEN-L2-W01 — Grooming & Courtesy: Naik Kelas','[{\"type\":\"single\",\"text\":\"SPV mengecek grooming kamu mendadak saat kamu sedang bawa tray minuman tanpa pemberitahuan sebelumnya. Sikap yang benar:\",\"options\":[\"Terima sebagai bagian normal dari standar Level 2, tetap tenang dan lanjutkan tugas\",\"Menegur SPV karena mendadak\",\"Minta jadwal cek grooming diberi tahu dulu\",\"Berhenti kerja sampai cek selesai\"],\"answer\":0,\"explanation\":\"Level 2 menilai konsistensi nyata di shift, bukan performa saat diberi tahu.\"},{\"type\":\"single\",\"text\":\"Target grooming Level 2 dalam seminggu penuh adalah:\",\"options\":[\"0 koreksi selama 7 hari kerja berturut-turut\",\"Maksimal 3 koreksi per minggu\",\"1 kali cek saja di awal minggu\",\"Tidak ada target khusus\"],\"answer\":0,\"explanation\":\"Konsistensi penuh 7 hari adalah standar naik kelas dari L1 ke L2.\"},{\"type\":\"single\",\"text\":\"Kamu sedang terburu-buru membawa linen berat menuju kamar tamu dan berpapasan dengan tamu di jarak 5 langkah. Tindakan yang tepat:\",\"options\":[\"Tetap kontak mata, sapa duluan walau tangan penuh\",\"Lewat cepat tanpa menyapa karena tangan penuh\",\"Menunduk agar tidak terlihat tamu\",\"Berhenti total dan taruh linen dulu\"],\"answer\":0,\"explanation\":\"10/5 rule harus jadi refleks bahkan dalam kondisi sibuk — itu bedanya sekadar tahu dan terbukti bisa.\"},{\"type\":\"single\",\"text\":\"Rekan kerja menunjuk name tag kamu yang miring sebelum shift dimulai. Respons paling tepat di level supervisi:\",\"options\":[\"Segera dibenerkan, berterima kasih — lebih baik ketahuan rekan daripada SPV\",\"Diabaikan karena cuma miring sedikit\",\"Ditunda sampai istirahat\",\"Marah karena merasa ditegur\"],\"answer\":0,\"explanation\":\"Detail kecil berulang mulai dicatat di skill matrix Level 2; saling ingatkan sesama rekan itu wajar dan positif.\"},{\"type\":\"single\",\"text\":\"Sepasang tamu Perancis baru kembali ke lobby setelah Gowes Sawah, terlihat kepanasan dan lelah. Tindakan small hospitality yang paling tepat — yang membedakan kita dari city hotel:\",\"options\":[\"Segera tawarkan cold towel & welcome drink herbal dari farm tanpa menunggu diminta, sambil sapa dengan nama mereka\",\"Menunggu mereka menghampiri meja dan bertanya dulu baru dibantu\",\"Menyapa \'Sir/Madam\' seadanya lalu lanjut kerja\",\"Menunjuk arah kamar: \'Your villa is over there\'\"],\"answer\":0,\"explanation\":\"Inti small hospitality ultra-luxury adalah antisipasi sebelum diminta + personal recognition (menyebut nama) — city hotel cenderung menunggu tamu meminta dan menyapa generik. Menyodorkan cold towel & welcome drink herbal khas Sanggraloka saat tamu jelas kepanasan adalah wujud membaca isyarat tamu (GEN-20).\"}]',80,10,3,'course','2026-07-08 19:12:49','2026-07-08 19:12:49'),(26,1,32,NULL,'Test — GEN-L2-W02 — Telepon & English: Praktek Harian','[{\"type\":\"single\",\"text\":\"Tamu Korea menelepon menanyakan upgrade kamar, kamu perlu cek ke Reservation dan itu akan makan waktu lebih dari 60 detik. Tindakan yang tepat:\",\"options\":[\"Kembali dulu ke tamu sebelum 60 detik, minta izin hold lagi\",\"Terus hold sampai info didapat walau lebih dari 2 menit\",\"Tutup telepon dan telepon balik nanti\",\"Alihkan ke rekan tanpa penjelasan\"],\"answer\":0,\"explanation\":\"Hold maksimal 60 detik tanpa update; jika butuh lebih lama, kembali dulu dan minta izin hold ulang.\"},{\"type\":\"single\",\"text\":\"Tamu di kamar meminta disambungkan ke Spa untuk booking treatment di Nirvanaloka. Langkah transfer yang benar:\",\"options\":[\"Informasikan nama tamu & keperluan ke tim Spa dulu, baru sambungkan\",\"Langsung sambungkan tanpa penjelasan, biar tamu jelaskan sendiri\",\"Minta tamu telepon ulang ke nomor Spa langsung\",\"Catat pesan saja tanpa transfer\"],\"answer\":0,\"explanation\":\"Transfer tidak boleh \'buta\' — penerima harus tahu konteks sebelum tersambung ke tamu.\"},{\"type\":\"single\",\"text\":\"Teman tamu menelepon menitipkan pesan soal reservasi dinner di Meditera Restaurant untuk tamu yang sedang keluar. Langkah terakhir yang WAJIB sebelum menutup telepon:\",\"options\":[\"Mengulang isi pesan ke penelepon untuk konfirmasi\",\"Langsung menutup telepon setelah mencatat\",\"Meminta penelepon menelepon ulang nanti\",\"Meneruskan ke rekan kerja secara lisan saja\"],\"answer\":0,\"explanation\":\"Pesan yang tidak diulang balik adalah kesalahan paling sering terjadi dan berisiko salah info.\"},{\"type\":\"single\",\"text\":\"Kamu tidak yakin jawaban bahasa Inggris atas pertanyaan tamu Perancis soal jam breakfast. Respons paling tepat level supervisi (tanpa bantuan rekan):\",\"options\":[\"\\\"Let me check that for you\\\" lalu cari info dan kembali menjawab\",\"Menjawab asal supaya terdengar percaya diri\",\"Memanggil rekan untuk menjawabkan\",\"Bilang \\\"I don\'t know\\\" saja\"],\"answer\":0,\"explanation\":\"Level 2 menuntut kamu menangani sendiri tanpa bantuan — tetap sopan dan cari jawaban pasti.\"},{\"type\":\"single\",\"text\":\"Yang dicek SPV dalam checklist praktek W02 minggu ini:\",\"options\":[\"Minimal 3 telepon nyata ditangani sesuai script hold, 1x transfer benar, 1x pesan diulang balik\",\"Menghafal semua frasa Inggris dari Level 1\",\"Menonton video telepon tanpa praktek\",\"Mengerjakan kuis saja tanpa praktek nyata\"],\"answer\":0,\"explanation\":\"Checklist L2 menilai praktek nyata di shift, bukan sekadar hafalan teori.\"}]',80,10,3,'course','2026-07-08 19:12:49','2026-07-08 19:12:49'),(27,1,33,4,'Test — GEN-L2-W03 — Product & Area Expert: Jago Jawab Tamu','[{\"type\":\"single\",\"text\":\"Tamu bertanya, \\\"Which villa has the biggest private pool?\\\" Jawaban yang tepat:\",\"options\":[\"One/Two Bedroom Presidential Pool Villa\",\"Deluxe Suite\",\"Premiere Suite\",\"Deluxe Private Pool Villa\"],\"answer\":0,\"explanation\":\"Presidential Pool Villa adalah tipe dengan private pool paling luas.\"},{\"type\":\"single\",\"text\":\"Tamu Korea menanyakan, \\\"Is this Svara Nadi thing some kind of massage?\\\" tapi kamu tidak yakin detail lengkap treatment-nya hari itu. Respons paling tepat:\",\"options\":[\"\\\"Let me confirm the details with our Spa team for you\\\" lalu benar-benar cek\",\"Menjawab asal supaya tamu tidak menunggu\",\"Bilang \\\"I don\'t know\\\" lalu diam\",\"Mengarahkan tamu bertanya sendiri ke Spa tanpa membantu\"],\"answer\":0,\"explanation\":\"Level 2 melarang jawaban ngasal — lebih baik konfirmasi dulu ke tim terkait (Nirvanaloka Spa).\"},{\"type\":\"single\",\"text\":\"Tamu Perancis hanya punya satu pagi bebas dan minta rekomendasi kegiatan santai dekat resort. Rekomendasi yang paling sesuai:\",\"options\":[\"Rice Paddies Experience pagi hari, lanjut Svara Nadi Treatment sore untuk relaksasi\",\"Menyuruh tamu ke Ubud center naik taksi sendiri tanpa arahan\",\"Menjawab tidak ada kegiatan pagi di resort\",\"Menyarankan drill evakuasi sebagai hiburan\"],\"answer\":0,\"explanation\":\"Kombinasi ini sesuai waktu pagi yang tersedia dan menonjolkan experience unggulan resort.\"},{\"type\":\"single\",\"text\":\"Tamu menunjuk tanaman dan bertanya kenapa Sanggraloka menanamnya. Kamu tahu itu Aristolochia (tanaman inang). Penjelasan paling tepat:\",\"options\":[\"Itu tanaman inang tempat kupu-kupu bertelur dan makanan ulat — bagian dari butterfly sanctuary kami\",\"Itu tanaman nektar sumber madu untuk kupu dewasa\",\"Itu tanaman hias biasa tanpa fungsi khusus\",\"Itu gulma yang belum sempat dicabut\"],\"answer\":0,\"explanation\":\"Tanaman inang (Aristolochia) adalah tempat kupu bertelur dan satu-satunya makanan ulat Troides helena; berbeda dari tanaman nektar (Ixora/Lantana) yang jadi makanan kupu dewasa. Keduanya sengaja ditanam karena kita butterfly sanctuary.\"},{\"type\":\"single\",\"text\":\"Seorang tamu hendak menangkap seekor Troides helena (Common Birdwing) untuk difoto dari dekat. Sikap kamu:\",\"options\":[\"Cegah dengan sopan dan jelaskan kupu ini dilindungi hukum, tawarkan foto dari jarak dekat tanpa menyentuh\",\"Membantu menangkapnya agar tamu senang\",\"Diam saja karena itu hak tamu\",\"Menyuruh tamu menangkap yang lain saja\"],\"answer\":0,\"explanation\":\"Troides helena termasuk satwa dilindungi (PP No. 7/1999 & CITES Appendix II) — tidak boleh ditangkap. Kita jelaskan dengan ramah dan arahkan tamu menikmatinya tanpa menyentuh; ini juga wujud Palemahan (harmoni dengan alam).\"}]',80,10,3,'course','2026-07-08 19:12:49','2026-07-08 19:12:49'),(28,1,35,NULL,'Test — GEN-L2-W05 — THK dalam Tindakan: Saat Tamu Kecewa, Kamu Turun Tangan','[{\"type\":\"single\",\"text\":\"Tamu Perancis komplain suara serangga & aliran sungai terlalu keras malam hari dekat kamarnya. Langkah PERTAMA yang benar sesuai LEARN:\",\"options\":[\"Dengarkan penuh keluhannya tanpa memotong, catat detailnya\",\"Langsung jelaskan bahwa itu memang suasana alami resort eco-luxury\",\"Tawarkan pindah kamar tanpa bertanya dulu apa masalahnya\",\"Minta tamu menghubungi SPV langsung\"],\"answer\":0,\"explanation\":\"L = Listen. Sebelum menjelaskan atau menyelesaikan apapun, dengarkan dulu sampai tuntas — ini menunjukkan tamu dihargai dan mencegah kesalahpahaman.\"},{\"type\":\"single\",\"text\":\"Setelah mendengarkan, langkah Empathize yang paling tepat kamu ucapkan adalah:\",\"options\":[\"\\\"Saya paham ini mengganggu istirahat Bapak/Ibu, maaf atas ketidaknyamanannya.\\\"\",\"\\\"Itu memang bunyi alami, semua tamu juga dengar begitu.\\\"\",\"\\\"Saya akan panggil SPV, ini bukan urusan saya.\\\"\",\"\\\"Coba tutup jendela saja, Pak/Bu.\\\"\"],\"answer\":0,\"explanation\":\"Empathize berarti mengakui perasaan tamu secara tulus sebelum masuk ke solusi — bukan membela diri atau meremehkan keluhan.\"},{\"type\":\"single\",\"text\":\"Tamu meminta refund satu malam penuh karena kejadian tadi. Kamu sebagai staff dgn wewenang terbatas sebaiknya:\",\"options\":[\"Sampaikan permintaan itu dicatat & akan dieskalasi ke SPV/Duty Manager untuk keputusan\",\"Langsung janjikan refund penuh agar tamu senang\",\"Tolak langsung karena bukan kesalahan resort\",\"Diamkan saja dan berharap tamu lupa\"],\"answer\":0,\"explanation\":\"React sesuai wewenang: kompensasi besar seperti refund selalu dieskalasi ke SPV, jangan pernah dijanjikan sendiri di luar wewenangmu.\"},{\"type\":\"single\",\"text\":\"Setelah kasus selesai ditangani bersama SPV, langkah Notify yang wajib kamu lakukan:\",\"options\":[\"Laporkan kasus & tindak lanjutnya di HotelCrew agar tercatat dan tidak terulang\",\"Cukup ceritakan ke rekan kerja saat istirahat\",\"Tidak perlu dilaporkan karena sudah selesai\",\"Laporkan hanya jika tamu memberi review buruk\"],\"answer\":0,\"explanation\":\"Notify berarti setiap komplain, sekecil apapun, dicatat di HotelCrew — ini membantu resort belajar dan mencegah masalah berulang.\"},{\"type\":\"single\",\"text\":\"Manakah yang PALING menggambarkan hubungan Palemahan dalam kasus komplain suara sungai di atas?\",\"options\":[\"Melaporkan agar area kamar dekat sungai itu dievaluasi demi kenyamanan tamu berikutnya\",\"Menyalahkan tamu karena terlalu sensitif\",\"Diam saja karena bukan tanggung jawabmu\",\"Meminta tamu memberi rating bagus meski belum puas\"],\"answer\":0,\"explanation\":\"Palemahan = menjaga keharmonisan dengan lingkungan/resort secara berkelanjutan — melaporkan demi perbaikan jangka panjang adalah wujud nyatanya.\"}]',80,10,3,'course','2026-07-08 19:12:49','2026-07-08 19:12:49'),(29,1,36,NULL,'Test — GEN-L2-W06 — K3, Kebakaran & Gempa: Mata Awasmu Melindungi Semua Orang','[{\"type\":\"single\",\"text\":\"Kamu hampir tersandung kabel listrik yang menyilang jalur tamu, tapi tidak ada yang cedera. Tindakan yang benar:\",\"options\":[\"Laporkan sebagai near-miss di HotelCrew hari itu juga dengan lokasi & foto\",\"Diamkan saja karena tidak ada yang terluka\",\"Cerita ke rekan kerja saat istirahat saja, cukup itu\",\"Pindahkan kabel sendiri lalu lupakan\"],\"answer\":0,\"explanation\":\"Near-miss wajib dilaporkan segera di HotelCrew agar tim K3 memperbaiki sebelum benar-benar terjadi kecelakaan.\"},{\"type\":\"single\",\"text\":\"Urutan yang benar saat menggunakan APAR (prinsip PASS):\",\"options\":[\"Pull pin, Aim ke dasar api, Squeeze tuas, Sweep menyapu\",\"Squeeze dulu, baru Aim ke atas api\",\"Sweep dulu ke seluruh ruangan, baru Pull pin\",\"Aim ke asap, lalu Pull pin\"],\"answer\":0,\"explanation\":\"PASS = Pull, Aim (ke dasar api, bukan asap/atas), Squeeze, Sweep — urutan ini memastikan pemadaman efektif.\"},{\"type\":\"single\",\"text\":\"Alarm kebakaran berbunyi saat kamu sedang mengantar tamu Korea di area villa lembah. Langkah yang tepat:\",\"options\":[\"Arahkan tamu mengikuti jalur evakuasi & rambu, gunakan gestur jelas karena kendala bahasa\",\"Suruh tamu jalan sendiri lewat tebing agar lebih cepat\",\"Tunggu tamu selesai foto-foto dulu baru evakuasi\",\"Abaikan karena bukan tugasmu\"],\"answer\":0,\"explanation\":\"Ikuti jalur evakuasi resmi, jangan potong lewat tebing/sungai; gunakan gestur karena tamu asing mungkin tak paham rambu Bahasa Indonesia.\"},{\"type\":\"single\",\"text\":\"Saat guncangan gempa terasa kuat di area kerja, langkah PERTAMA yang benar:\",\"options\":[\"Drop — segera merunduk ke lantai\",\"Langsung berlari keluar gedung secepatnya\",\"Berdiri di dekat jendela untuk melihat situasi\",\"Naik ke tempat tinggi untuk menghindari air\"],\"answer\":0,\"explanation\":\"Drop-Cover-Hold: langkah pertama adalah merunduk (Drop), baru berlindung (Cover) dan berpegangan (Hold) sampai guncangan berhenti.\"},{\"type\":\"single\",\"text\":\"Setelah guncangan gempa berhenti dan kamu akan evakuasi menuju titik kumpul, yang harus diperhatikan di area resort kita:\",\"options\":[\"Hindari jalur tebing & tepi sungai yang berpotensi longsor, ikuti jalur aman ke titik kumpul\",\"Lari lewat jalan pintas tebing agar lebih cepat sampai\",\"Menyusuri tepi sungai karena lebih landai\",\"Tetap di kamar menunggu instruksi lebih lanjut tanpa bergerak\"],\"answer\":0,\"explanation\":\"Area resort berbukit lembah sungai rawan longsor pasca gempa — jalur evakuasi resmi menghindari tebing & tepi sungai.\"}]',80,10,3,'course','2026-07-08 19:12:49','2026-07-08 19:12:49'),(30,1,37,NULL,'Test — GEN-L2-W07 — P3K & Hygiene: Siap Bertindak di 60 Detik Pertama','[{\"type\":\"single\",\"text\":\"Seorang tamu terpeleset dan lukanya berdarah cukup banyak & dalam di area kepala. Tindakan yang tepat:\",\"options\":[\"Jangan bersihkan sendiri, segera panggil bantuan medis/SPV\",\"Bersihkan lukanya sendiri lalu tutup dengan plester biasa\",\"Suruh tamu ke kamar mandi membersihkan sendiri\",\"Tunggu sampai tamu meminta bantuan\"],\"answer\":0,\"explanation\":\"Luka berdarah banyak/dalam di area kepala termasuk kondisi yang wajib segera dieskalasi ke bantuan medis, bukan ditangani staf sendiri.\"},{\"type\":\"single\",\"text\":\"Kamu menemukan rekan kerja pingsan di area dapur. Langkah pertama yang benar:\",\"options\":[\"Pastikan area aman, baringkan dan cek respons serta pernapasannya\",\"Langsung beri minum air putih agar sadar\",\"Angkat dan gendong ke ruang lain sendirian\",\"Foto dulu untuk laporan baru bertindak\"],\"answer\":0,\"explanation\":\"Langkah pertama adalah amankan area & baringkan korban, cek kesadaran dan napas — jangan beri minum ke orang yang belum sadar penuh.\"},{\"type\":\"single\",\"text\":\"Tamu di restoran tiba-tiba mencengkeram lehernya, tidak bisa bicara atau batuk, wajah mulai membiru. Ini tanda:\",\"options\":[\"Tersedak berat — segera panggil staf terlatih P3K/medis tanpa menunda\",\"Sedang bercanda, abaikan saja\",\"Alergi ringan, cukup beri air minum\",\"Kelelahan biasa, suruh istirahat\"],\"answer\":0,\"explanation\":\"Tidak bisa bicara/batuk dan wajah membiru adalah tanda tersedak total (sumbatan jalan napas total) — kondisi darurat yang wajib segera ditangani bantuan terlatih.\"},{\"type\":\"single\",\"text\":\"Kamu bertugas di outlet F&B dan pagi ini mengalami diare & sedikit demam. Yang seharusnya kamu lakukan:\",\"options\":[\"Tidak masuk kerja dulu, laporkan ke SPV & HR sesuai protokol sakit menular\",\"Tetap masuk kerja tapi pakai masker saja\",\"Masuk kerja seperti biasa karena hanya gejala ringan\",\"Minta rekan kerja menggantikan tanpa lapor SPV\"],\"answer\":0,\"explanation\":\"Staf F&B dengan gejala sakit menular (demam, diare, muntah) wajib tidak masuk kerja dan melapor ke SPV/HR demi keamanan pangan & tamu.\"},{\"type\":\"single\",\"text\":\"Manakah dari berikut ini yang PALING tepat sebagai kondisi wajib segera memanggil bantuan, bukan ditangani staf sendiri?\",\"options\":[\"Tamu kejang, nyeri dada, atau tidak sadarkan diri lebih dari 1 menit\",\"Tamu minta plester untuk luka gores kecil di jari\",\"Tamu ingin tahu lokasi kotak P3K\",\"Tamu bertanya jam operasional klinik resort\"],\"answer\":0,\"explanation\":\"Kejang, nyeri dada, dan pingsan lebih dari 1 menit adalah kondisi darurat serius yang harus segera dieskalasi ke bantuan medis, bukan ditangani sendiri oleh staf.\"}]',80,10,3,'course','2026-07-08 19:12:49','2026-07-08 19:12:49'),(31,1,39,NULL,'Test — GEN-L2-W09 — Respect at Work & Privasi Tamu: Jaga Martabat, Jaga Data','[{\"type\":\"single\",\"text\":\"Kamu melihat rekan kerja diejek terus-menerus soal logat daerahnya oleh seorang senior, tapi yang diejek diam karena takut. Sikap yang tepat sebagai saksi adalah…\",\"options\":[\"Melaporkan lewat HR Hotline/HotelCrew meski bukan korban langsung\",\"Diam saja karena bukan urusanmu\",\"Menegur senior tersebut di depan umum agar viral\",\"Menasihati korban supaya lebih tahan mental saja\"],\"answer\":0,\"explanation\":\"Saksi pelanggaran wajib melapor lewat kanal resmi — pembiaran juga bentuk pelanggaran terhadap keharmonisan sesama manusia.\"},{\"type\":\"single\",\"text\":\"Seorang kreator konten mendekatimu di area kolam villa dan minta izin syuting cepat karena mengaku sudah kenal owner. Tindakan yang benar?\",\"options\":[\"Tetap ramah, jelaskan semua kreator wajib terdaftar di Creators Program lewat Sales/Marketing, arahkan ke sana\",\"Izinkan saja karena mengaku kenal owner\",\"Izinkan asal syuting singkat tidak sampai 10 menit\",\"Minta bayaran pribadi dulu sebelum mengizinkan\"],\"answer\":0,\"explanation\":\"Semua kreator/influencer harus terdaftar resmi lewat Creators Program via Sales/Marketing — staf tidak berwenang memberi izin sendiri, apa pun alasannya.\"},{\"type\":\"single\",\"text\":\"Kamu mengetahui seorang tamu adalah selebriti nasional yang menginap di salah satu villa. Teman satu kos menanyakan identitas tamu itu lewat chat pribadi. Sikap yang benar?\",\"options\":[\"Tidak menjawab atau mengonfirmasi apa pun, termasuk ke teman dekat\",\"Menjawab asal tidak difoto\",\"Menjawab tapi minta temanmu merahasiakannya\",\"Mengonfirmasi hanya nama depan tamu saja\"],\"answer\":0,\"explanation\":\"Identitas dan privasi tamu adalah kerahasiaan mutlak sesuai UU PDP — tidak boleh dibagikan ke siapa pun di luar keperluan kerja.\"},{\"type\":\"single\",\"text\":\"Dokumen paspor tamu perlu didata saat check-in. Cara yang sesuai standar privasi adalah…\",\"options\":[\"Di-scan lewat sistem resmi hotel, tidak difoto dengan HP pribadi\",\"Difoto dengan HP pribadi lalu dihapus setelah dipakai\",\"Dicatat manual nomor paspornya di buku catatan pribadi staf\",\"Diminta fotokopinya untuk disimpan staf yang bertugas\"],\"answer\":0,\"explanation\":\"Dokumen identitas tamu hanya boleh diproses lewat sistem resmi perusahaan — tidak lewat perangkat pribadi staf, sesuai UU PDP.\"},{\"type\":\"single\",\"text\":\"Kamu ingin melaporkan dugaan pelecehan verbal oleh atasan langsung, tapi takut ada balas dendam terhadap kariermu. Apa yang benar tentang kanal lapor resmi Sanggraloka?\",\"options\":[\"Laporan bisa disampaikan lewat HR Hotline atau menu Lapor Insiden di HotelCrew secara anonim, dan tidak boleh ada balas dendam terhadap pelapor\",\"Kamu wajib melapor lewat atasan yang bersangkutan dulu\",\"Laporan hanya sah jika disertai nama lengkap dan tidak bisa anonim\",\"Sebaiknya tidak usah dilaporkan karena berisiko bagi karier\"],\"answer\":0,\"explanation\":\"Sanggraloka menjamin kerahasiaan dan perlindungan anti-retaliasi bagi pelapor; kanal HR Hotline dan menu Lapor Insiden di HotelCrew bisa diakses secara anonim.\"}]',80,10,3,'course','2026-07-08 19:12:49','2026-07-08 19:12:49'),(32,1,40,NULL,'Test — GEN-L2-W10 — Aturan Main & Sustainability: Cerita Hijau Sanggraloka','[{\"type\":\"single\",\"text\":\"Rekan kerjamu mengajak tukar shift langsung tanpa lapor Supervisor, dengan alasan \'cuma sekali ini\'. Sikap yang benar?\",\"options\":[\"Tolak dengan sopan — tukar shift harus disetujui Supervisor tertulis di HotelCrew\",\"Setuju karena hanya sekali dan tidak akan ketahuan\",\"Setuju tapi minta rekan yang bertanggung jawab jika ada masalah\",\"Tanya rekan lain dulu baru diputuskan berdua\"],\"answer\":0,\"explanation\":\"Tukar shift wajib disetujui dan tercatat resmi oleh Supervisor demi kejelasan tanggung jawab dan absensi, bukan kesepakatan informal antar staf.\"},{\"type\":\"single\",\"text\":\"Sisa makanan dari dapur/restoran Sanggraloka dibuang ke tong warna apa, dan diteruskan ke mana?\",\"options\":[\"Tong hijau (organik), diteruskan ke farm resort untuk dikompos\",\"Tong hitam (residu), langsung ke TPA\",\"Tong biru (daur ulang), ke bank sampah\",\"Dicampur semua tong karena akan dipilah ulang di TPA\"],\"answer\":0,\"explanation\":\"Sampah organik dipisah ke tong hijau dan diproses menjadi kompos di farm Sanggraloka, mendukung siklus farm-to-table.\"},{\"type\":\"single\",\"text\":\"Contoh penerapan bebas plastik sekali pakai yang benar di Sanggraloka adalah…\",\"options\":[\"Amenities kamar mandi memakai dispenser isi ulang, bukan botol mini sekali pakai\",\"Tetap memakai sedotan plastik asal disediakan atas permintaan tamu\",\"Air minum tamu memakai botol plastik kemasan sekali pakai bermerek\",\"Kemasan take-away outlet memakai plastik tebal agar tidak bocor\"],\"answer\":0,\"explanation\":\"Standar Sanggraloka menggunakan dispenser isi ulang untuk amenities dan bahan biodegradable/kertas untuk kemasan, menghindari plastik sekali pakai.\"},{\"type\":\"single\",\"text\":\"Saat menyajikan sayur di restoran, cara eco-storytelling yang natural (bukan menggurui) kepada tamu adalah…\",\"options\":[\"\\\"Selada ini kami petik pagi tadi dari farm kami sendiri, pupuknya dari kompos dapur kami sendiri.\\\"\",\"\\\"Tamu wajib tahu bahwa kami sangat peduli lingkungan dan tamu harus ikut aturan kami.\\\"\",\"Tidak perlu menjelaskan apa pun, cukup sajikan makanan\",\"Memberi ceramah panjang tentang UU lingkungan sebelum makanan disajikan\"],\"answer\":0,\"explanation\":\"Eco-storytelling efektif itu singkat, personal, dan disampaikan sambil bekerja — bukan menggurui atau mewajibkan tamu.\"},{\"type\":\"single\",\"text\":\"Kamu menemukan keran bocor ringan di area belakang saat shift. Tindakan yang sesuai standar hemat air adalah…\",\"options\":[\"Laporkan segera via HotelFix agar cepat ditangani, tidak dibiarkan\",\"Dibiarkan karena bocornya kecil dan bukan area tamu\",\"Diperbaiki sendiri tanpa melapor ke teknisi\",\"Ditutup manual dengan lakban tanpa laporan resmi\"],\"answer\":0,\"explanation\":\"Kebocoran air sekecil apa pun harus segera dilaporkan lewat HotelFix agar ditangani teknisi dan mendukung komitmen hemat sumber daya resort.\"}]',80,10,3,'course','2026-07-08 19:12:49','2026-07-08 19:12:49'),(33,1,41,2,'Test — GEN-L2-W11 — Upselling Natural, Apps & Frasa FR/KR Lancar','[{\"type\":\"single\",\"text\":\"Tamu terlihat ragu-ragu dua kali saat kamu tawarkan upgrade villa dengan private pool. Sikap upselling natural yang benar?\",\"options\":[\"Berhenti menawarkan, beri ruang, dan pastikan tamu tetap merasa nyaman dengan kamar saat ini\",\"Mengulang tawaran sekali lagi dengan diskon besar mendadak\",\"Menekankan tamu akan menyesal jika tidak upgrade\",\"Melaporkan keraguan tamu ke Supervisor sebagai keluhan\"],\"answer\":0,\"explanation\":\"Upselling natural membaca sinyal tamu — bila sudah ragu dua kali, berhenti menawarkan agar tidak terasa memaksa.\"},{\"type\":\"single\",\"text\":\"Contoh kalimat upselling natural yang sesuai standar Sanggraloka adalah…\",\"options\":[\"\\\"Villa Meditera dengan private pool sedang tersedia, Pak, cocok untuk momen ini — atau kamar saat ini juga sudah sangat nyaman kok.\\\"\",\"\\\"Bapak harus upgrade sekarang atau kehilangan kesempatan terbaik.\\\"\",\"\\\"Semua tamu VIP pasti upgrade, masa Bapak tidak?\\\"\",\"Langsung menyebutkan harga upgrade tanpa menjelaskan pengalamannya\"],\"answer\":0,\"explanation\":\"Upselling yang baik menonjolkan pengalaman/manfaat lebih dulu dan tetap memberi pilihan tanpa tekanan ke tamu.\"},{\"type\":\"single\",\"text\":\"Ciri staf Level 2 dalam penggunaan HotelCrew & HotelFix adalah…\",\"options\":[\"Bisa mengoperasikan keduanya tanpa bantuan dan mampu membimbing staf baru Level 1\",\"Hanya bisa memakai HotelCrew, tidak perlu HotelFix\",\"Masih perlu didampingi SPV setiap kali membuka aplikasi\",\"Cukup tahu nama aplikasinya tanpa perlu praktik langsung\"],\"answer\":0,\"explanation\":\"Level 2 menuntut kemahiran mandiri di kedua aplikasi, termasuk kemampuan membantu staf baru yang masih Level 1.\"},{\"type\":\"single\",\"text\":\"Tamu bernama Kim Min-jun check-in. Cara menyapa yang benar sesuai kartu frasa GEN-18 adalah…\",\"options\":[\"Mr. Kim\",\"Mr. Min-jun\",\"Mr. Jun\",\"Memanggil nama depan saja tanpa gelar\"],\"answer\":0,\"explanation\":\"Nama Korea disusun keluarga dulu, sehingga sapaan yang benar mengambil nama keluarga: Kim Min-jun disapa Mr. Kim.\"},{\"type\":\"single\",\"text\":\"Kamu ingin menawarkan menu farm-to-table malam ini ke tamu Perancis yang baru tiba sore hari (pukul 19.00). Sapaan pembuka yang tepat dalam bahasa Perancis adalah…\",\"options\":[\"Bonsoir\",\"Bonjour\",\"Bon appétit\",\"Bonne journée\"],\"answer\":0,\"explanation\":\"Pukul 19.00 sudah masuk waktu malam, sehingga sapaan yang tepat adalah Bonsoir, bukan Bonjour yang dipakai pagi/siang.\"}]',80,10,3,'course','2026-07-08 19:12:49','2026-07-08 19:12:49'),(34,1,42,2,'Test — GEN-L2-W12 — UJI PRAKTEK LEVEL 2','[{\"type\":\"single\",\"text\":\"Standar 10/5 rule di Sanggraloka berarti…\",\"options\":[\"Senyum & kontak mata dalam radius 10 langkah, menyapa dengan kata-kata dalam radius 5 langkah\",\"Melayani tamu maksimal 10 menit, istirahat 5 menit\",\"10 titik grooming dicek setiap 5 jam\",\"Menyapa tamu hanya bila jaraknya kurang dari 5 meter\"],\"answer\":0,\"explanation\":\"10/5 rule: beri senyum & kontak mata saat tamu berjarak 10 langkah, dan sapa dengan kata-kata saat berjarak 5 langkah.\"},{\"type\":\"single\",\"text\":\"Saat menerima telepon dan perlu mentransfer ke departemen lain, urutan yang benar adalah…\",\"options\":[\"Salam & identitas diri, dengarkan kebutuhan, minta izin hold, transfer dengan info yang jelas ke penerima\",\"Langsung transfer tanpa bertanya keperluan penelepon\",\"Minta penelepon menutup telepon dan menelepon ulang ke nomor lain\",\"Transfer dulu baru menjelaskan siapa yang menelepon\"],\"answer\":0,\"explanation\":\"Script standar: salam-identitas, dengarkan, minta izin hold, lalu transfer dengan menyampaikan konteks ke penerima agar tamu tidak mengulang cerita.\"},{\"type\":\"single\",\"text\":\"Tamu bertanya rekomendasi pengalaman budaya di sekitar Ubud. Jawaban yang sesuai product knowledge Sanggraloka mencakup…\",\"options\":[\"Menyebutkan experience resort seperti Art & Earth atau Rice Paddies yang relevan dengan minat tamu\",\"Menjawab tidak tahu dan menyuruh tamu mencari sendiri di internet\",\"Hanya menyebutkan nama restoran resort\",\"Mengarahkan tamu ke resort kompetitor karena lebih terkenal\"],\"answer\":0,\"explanation\":\"Staf Level 2 diharapkan menguasai product & area expert termasuk experience resort seperti Art & Earth, Elevator & Ecosystem, Rice Paddies, dan Svara Nadi.\"},{\"type\":\"single\",\"text\":\"Filosofi Tri Hita Karana (THK) yang mendasari layanan Sanggraloka terdiri dari tiga hubungan harmoni, yaitu…\",\"options\":[\"Parhyangan (dengan Tuhan), Pawongan (dengan sesama manusia), Palemahan (dengan alam)\",\"Grooming, greeting, dan komunikasi\",\"Kebersihan, kerapian, dan kecepatan\",\"Profit, planet, dan people versi Barat\"],\"answer\":0,\"explanation\":\"THK adalah filosofi Bali tentang tiga harmoni: dengan Tuhan (Parhyangan), sesama manusia (Pawongan), dan alam (Palemahan) — mendasari nilai kerja Sanggraloka.\"},{\"type\":\"single\",\"text\":\"Saat menangani komplain tamu menggunakan prinsip LEARN/HEART, langkah pertama yang tepat adalah…\",\"options\":[\"Listen — dengarkan keluhan tamu sepenuhnya tanpa memotong\",\"Langsung menawarkan kompensasi sebelum mendengarkan detail\",\"Membela tindakan staf lain di depan tamu\",\"Meminta tamu menulis komplain tertulis dulu sebelum ditanggapi\"],\"answer\":0,\"explanation\":\"LEARN/HEART dimulai dari Listen — mendengarkan penuh empati sebelum merespons, agar tamu merasa didengar.\"},{\"type\":\"single\",\"text\":\"Saat alarm kebakaran berbunyi dan kamu sedang bertugas di area tamu, tindakan pertama yang tepat adalah…\",\"options\":[\"Tetap tenang, arahkan tamu ke jalur evakuasi terdekat menuju titik kumpul\",\"Menunggu instruksi dari tamu\",\"Menggunakan lift untuk evakuasi lebih cepat\",\"Kembali ke loker mengambil barang pribadi dulu\"],\"answer\":0,\"explanation\":\"Staf wajib tenang dan membantu mengarahkan tamu ke jalur evakuasi menuju titik kumpul, tidak menggunakan lift saat kebakaran.\"},{\"type\":\"single\",\"text\":\"Saat terjadi gempa dan kamu berada di dalam bangunan, respons standar yang benar adalah…\",\"options\":[\"Drop-Cover-Hold: merunduk, berlindung di bawah benda kokoh, berpegangan sampai getaran berhenti\",\"Berlari keluar secepatnya walau masih bergetar\",\"Berdiri di dekat jendela kaca untuk melihat situasi\",\"Naik ke lantai teratas gedung\"],\"answer\":0,\"explanation\":\"Protokol gempa standar adalah Drop-Cover-Hold, berlindung di tempat aman sampai getaran benar-benar berhenti sebelum evakuasi.\"},{\"type\":\"single\",\"text\":\"Menemukan tamu tersedak saat makan di outlet. Tindakan pertama yang tepat sesuai P3K dasar adalah…\",\"options\":[\"Terapkan manuver Heimlich bila terlatih, dan segera minta bantuan medis/Supervisor\",\"Menepuk punggung sekuat mungkin tanpa henti tanpa memanggil bantuan\",\"Memberi air minum agar makanan turun\",\"Menunggu tamu batuk sendiri tanpa tindakan apa pun\"],\"answer\":0,\"explanation\":\"P3K dasar tersedak: lakukan manuver yang sesuai pelatihan dan segera memanggil bantuan medis/Supervisor, jangan memberi air minum saat tersedak.\"},{\"type\":\"single\",\"text\":\"Kamu melihat rekan kerja terus-menerus diejek soal logat daerahnya oleh senior, namun korban diam karena takut. Sikap yang tepat sebagai saksi?\",\"options\":[\"Melaporkan lewat HR Hotline/HotelCrew meski bukan korban langsung\",\"Diam saja karena bukan urusanmu\",\"Ikut menertawakan agar tidak dianggap aneh\",\"Menasihati korban agar lebih tahan mental\"],\"answer\":0,\"explanation\":\"Saksi pelanggaran wajib melapor lewat kanal resmi; pembiaran juga bentuk pelanggaran terhadap keharmonisan sesama manusia.\"},{\"type\":\"single\",\"text\":\"Seorang kreator konten meminta izin syuting cepat di area villa dengan alasan kenal owner. Tindakan yang benar?\",\"options\":[\"Tetap ramah, arahkan ke Sales/Marketing karena semua kreator wajib terdaftar di Creators Program\",\"Izinkan saja karena mengaku kenal owner\",\"Izinkan asal syuting singkat\",\"Minta bayaran pribadi dulu sebelum mengizinkan\"],\"answer\":0,\"explanation\":\"Semua kreator/influencer harus terdaftar resmi lewat Creators Program via Sales/Marketing — staf tidak berwenang memberi izin sendiri.\"},{\"type\":\"single\",\"text\":\"Kamu mengetahui identitas tamu selebriti yang menginap, lalu ditanya teman lewat chat pribadi. Sikap yang benar?\",\"options\":[\"Tidak menjawab atau mengonfirmasi apa pun, termasuk ke teman dekat\",\"Menjawab asal tidak difoto\",\"Menjawab tapi minta dirahasiakan\",\"Mengonfirmasi nama depan saja\"],\"answer\":0,\"explanation\":\"Identitas dan privasi tamu adalah kerahasiaan mutlak sesuai UU PDP, tidak boleh dibagikan ke siapa pun di luar keperluan kerja.\"},{\"type\":\"single\",\"text\":\"Rekan kerja mengajak tukar shift langsung tanpa lapor Supervisor. Sikap yang benar?\",\"options\":[\"Tolak dengan sopan — tukar shift harus disetujui Supervisor tertulis di HotelCrew\",\"Setuju karena hanya sekali dan tidak akan ketahuan\",\"Setuju tapi minta rekan bertanggung jawab bila ada masalah\",\"Tanya rekan lain dulu baru diputuskan berdua\"],\"answer\":0,\"explanation\":\"Tukar shift wajib disetujui dan tercatat resmi oleh Supervisor demi kejelasan tanggung jawab dan absensi.\"},{\"type\":\"single\",\"text\":\"Sisa makanan dari dapur/restoran Sanggraloka dibuang ke tong warna apa, dan diteruskan ke mana?\",\"options\":[\"Tong hijau (organik), diteruskan ke farm resort untuk dikompos\",\"Tong hitam (residu), langsung ke TPA\",\"Tong biru (daur ulang), ke bank sampah\",\"Dicampur semua tong karena akan dipilah ulang di TPA\"],\"answer\":0,\"explanation\":\"Sampah organik dipisah ke tong hijau dan diproses menjadi kompos di farm Sanggraloka, mendukung siklus farm-to-table.\"},{\"type\":\"single\",\"text\":\"Contoh eco-storytelling natural (bukan menggurui) kepada tamu saat menyajikan sayur adalah…\",\"options\":[\"\\\"Selada ini kami petik pagi tadi dari farm kami sendiri, pupuknya dari kompos dapur kami.\\\"\",\"\\\"Tamu wajib tahu kami sangat peduli lingkungan dan tamu harus ikut aturan kami.\\\"\",\"Tidak perlu menjelaskan apa pun\",\"Memberi ceramah panjang tentang UU lingkungan sebelum makanan disajikan\"],\"answer\":0,\"explanation\":\"Eco-storytelling efektif itu singkat, personal, dan disampaikan sambil bekerja — bukan menggurui atau mewajibkan tamu.\"},{\"type\":\"single\",\"text\":\"Tamu terlihat ragu-ragu dua kali saat kamu tawarkan upgrade villa. Sikap upselling natural yang benar?\",\"options\":[\"Berhenti menawarkan, beri ruang, pastikan tamu tetap nyaman dengan kamar saat ini\",\"Mengulang tawaran dengan diskon besar mendadak\",\"Menekankan tamu akan menyesal jika tidak upgrade\",\"Melaporkan keraguan tamu sebagai keluhan ke Supervisor\"],\"answer\":0,\"explanation\":\"Upselling natural membaca sinyal tamu — bila sudah ragu dua kali, berhenti menawarkan agar tidak terasa memaksa.\"},{\"type\":\"single\",\"text\":\"Ciri staf Level 2 dalam penggunaan HotelCrew & HotelFix adalah…\",\"options\":[\"Bisa mengoperasikan keduanya tanpa bantuan dan mampu membimbing staf baru Level 1\",\"Hanya bisa memakai HotelCrew, tidak perlu HotelFix\",\"Masih perlu didampingi SPV setiap kali membuka aplikasi\",\"Cukup tahu nama aplikasinya tanpa praktik langsung\"],\"answer\":0,\"explanation\":\"Level 2 menuntut kemahiran mandiri di kedua aplikasi, termasuk kemampuan membantu staf baru yang masih Level 1.\"},{\"type\":\"single\",\"text\":\"Tamu bernama Kim Min-jun check-in. Cara menyapa yang benar adalah…\",\"options\":[\"Mr. Kim\",\"Mr. Min-jun\",\"Mr. Jun\",\"Memanggil nama depan saja tanpa gelar\"],\"answer\":0,\"explanation\":\"Nama Korea disusun keluarga dulu, sehingga sapaan yang benar mengambil nama keluarga: Kim Min-jun disapa Mr. Kim.\"},{\"type\":\"single\",\"text\":\"Tamu Perancis tiba pukul 19.00. Sapaan pembuka yang tepat adalah…\",\"options\":[\"Bonsoir\",\"Bonjour\",\"Bon appétit\",\"Bonne journée\"],\"answer\":0,\"explanation\":\"Pukul 19.00 sudah masuk waktu malam, sapaan yang tepat adalah Bonsoir, bukan Bonjour yang dipakai pagi/siang.\"},{\"type\":\"single\",\"text\":\"Dokumen paspor tamu perlu didata saat check-in. Cara yang sesuai standar privasi adalah…\",\"options\":[\"Di-scan lewat sistem resmi hotel, tidak difoto dengan HP pribadi\",\"Difoto dengan HP pribadi lalu dihapus setelah dipakai\",\"Dicatat manual nomor paspornya di buku catatan pribadi staf\",\"Diminta fotokopinya untuk disimpan staf yang bertugas\"],\"answer\":0,\"explanation\":\"Dokumen identitas tamu hanya boleh diproses lewat sistem resmi perusahaan, tidak lewat perangkat pribadi staf, sesuai UU PDP.\"},{\"type\":\"single\",\"text\":\"Syarat kelulusan Level 2 General Studies di Sanggraloka mencakup…\",\"options\":[\"9 kuis mingguan lulus (≥80), 2 praktek terbimbing lulus, uji praktek W12 ≥80, dan ujian teori akhir ≥80\",\"Hanya kehadiran penuh 12 minggu\",\"Cukup lulus ujian teori saja\",\"Rekomendasi dari rekan kerja\"],\"answer\":0,\"explanation\":\"Kelulusan Level 2 mensyaratkan seluruh komponen: kuis mingguan, praktek terbimbing, uji praktek final, dan ujian teori akhir — semuanya harus lulus.\"}]',80,30,3,'course','2026-07-08 19:12:49','2026-07-08 19:12:49'),(35,1,NULL,NULL,'GEN — Placement Level 1','[{\"type\":\"single\",\"text\":\"Fungsi utama seragam dan grooming rapi bagi staf Sanggraloka adalah…\",\"options\":[\"Membangun kepercayaan tamu sejak pandangan pertama\",\"Memenuhi aturan HR semata\",\"Membedakan staf dari tamu\",\"Supaya foto seragam terlihat bagus\"],\"answer\":0,\"explanation\":\"Grooming rapi adalah sinyal profesionalisme yang membangun kepercayaan tamu sebelum kata pertama diucapkan; alasan administratif semata bukan tujuan utamanya.\",\"competency\":\"GEN-01\"},{\"type\":\"single\",\"text\":\"Rambut panjang bagi staf F&B/Kitchen wajib…\",\"options\":[\"Diikat rapi atau ditutup hairnet\",\"Dibiarkan tergerai asal disisir\",\"Diikat hanya saat ada tamu VIP\",\"Bebas asal wangi\"],\"answer\":0,\"explanation\":\"Rambut panjang wajib diikat rapi atau ditutup hairnet untuk mencegah rambut jatuh ke makanan; dibiarkan tergerai berisiko kontaminasi meskipun terlihat rapi.\",\"competency\":\"GEN-01\"},{\"type\":\"truefalse\",\"text\":\"Parfum yang menyengat diperbolehkan asal harum, karena tamu suka wangi kuat.\",\"options\":[\"Benar\",\"Salah\"],\"answer\":1,\"explanation\":\"Salah — parfum menyengat justru bisa mengganggu tamu yang sensitif atau alergi; standar grooming meminta wangi lembut/netral, bukan kuat.\",\"competency\":\"GEN-01\"},{\"type\":\"single\",\"text\":\"Anjali (menangkupkan tangan) dilakukan bersamaan dengan ucapan…\",\"options\":[\"Om Swastiastu\",\"Terima kasih\",\"Selamat tinggal\",\"Permisi\"],\"answer\":0,\"explanation\":\"Anjali adalah gestur yang menyertai salam khas \\\"Om Swastiastu\\\" sebagai representasi keramahan berbasis budaya Bali; ucapan lain tidak memiliki gestur baku ini.\",\"competency\":\"GEN-02\"},{\"type\":\"single\",\"text\":\"Aturan jarak sapa 10/5 dimaksudkan agar…\",\"options\":[\"Tamu merasa diperhatikan sejak jauh, disapa penuh saat dekat\",\"Staf tidak perlu menyapa tamu yang jauh\",\"Staf menghitung langkah secara harfiah dengan penggaris\",\"Hanya berlaku untuk tamu VIP\"],\"answer\":0,\"explanation\":\"Aturan 10/5 membangun kesan diperhatikan secara bertahap — kontak mata & senyum dari jauh, sapaan verbal saat dekat — bukan sekadar hitungan langkah kaku.\",\"competency\":\"GEN-02\"},{\"type\":\"single\",\"text\":\"Telepon internal antar-departemen sebaiknya diangkat dalam…\",\"options\":[\"Maksimal 3 dering, sama seperti telepon tamu\",\"Boleh dibiarkan lebih lama karena bukan tamu\",\"Hanya jika sempat\",\"Setelah 10 dering\"],\"answer\":0,\"explanation\":\"Standar 3 dering berlaku untuk semua panggilan masuk termasuk internal, karena kecepatan respons mencerminkan budaya kerja yang sama, bukan hanya untuk tamu.\",\"competency\":\"GEN-03\"},{\"type\":\"single\",\"text\":\"Saat mencatat pesan telepon untuk tamu, informasi minimal yang wajib dicatat adalah…\",\"options\":[\"Nama penelepon, waktu, isi pesan, dan nomor kontak balik\",\"Cukup nama penelepon saja\",\"Cukup isi pesan tanpa waktu\",\"Tidak perlu dicatat, cukup diingat\"],\"answer\":0,\"explanation\":\"Pesan telepon lengkap butuh nama, waktu, isi, dan kontak balik agar tamu bisa ditindaklanjuti dengan akurat; mengandalkan ingatan saja berisiko informasi hilang atau keliru.\",\"competency\":\"GEN-03\"},{\"type\":\"single\",\"text\":\"Kalimat bahasa Inggris yang tepat untuk menawarkan bantuan membawakan barang tamu:\",\"options\":[\"May I help you with your luggage?\",\"Give me your bag\",\"You carry it yourself\",\"Bag, please\"],\"answer\":0,\"explanation\":\"\\\"May I help you with your luggage?\\\" adalah kalimat sopan yang menawarkan bantuan, sesuai standar hospitality; kalimat pendek dan langsung terasa memerintah tamu.\",\"competency\":\"GEN-04\"},{\"type\":\"single\",\"text\":\"Total ada berapa tipe kamar/villa utama yang menjadi product knowledge dasar staf Sanggraloka?\",\"options\":[\"6 tipe\",\"3 tipe\",\"10 tipe\",\"2 tipe\"],\"answer\":0,\"explanation\":\"Sanggraloka memiliki 6 tipe kamar/villa utama yang wajib dihafal setiap staf agar bisa menjawab pertanyaan tamu dan melakukan rekomendasi dengan tepat.\",\"competency\":\"GEN-05\"},{\"type\":\"single\",\"text\":\"Outlet bar di area kolam utama bernama…\",\"options\":[\"Sunken Pool Bar\",\"Meditera\",\"Segening\",\"Nirvanaloka\"],\"answer\":0,\"explanation\":\"Sunken Pool Bar adalah outlet bar di area kolam; Meditera dan Segening adalah outlet F&B lain, sementara Nirvanaloka adalah spa, bukan bar.\",\"competency\":\"GEN-05\"},{\"type\":\"single\",\"text\":\"Lokasi Sanggraloka Ubud secara administratif berada di kawasan…\",\"options\":[\"Bresela–Payangan\",\"Kuta\",\"Sanur\",\"Nusa Dua\"],\"answer\":0,\"explanation\":\"Sanggraloka berlokasi di kawasan Bresela, Payangan — area pedesaan asri di luar pusat kota Ubud yang menjadi bagian dari daya tarik eco-luxury resort.\",\"competency\":\"GEN-06\"},{\"type\":\"single\",\"text\":\"Ubud terkenal secara umum sebagai pusat…\",\"options\":[\"Seni, budaya, dan wellness\",\"Pusat perbelanjaan modern\",\"Kawasan industri\",\"Pelabuhan\"],\"answer\":0,\"explanation\":\"Ubud dikenal dunia sebagai pusat seni, budaya, dan wellness Bali, sejalan dengan positioning eco-luxury Sanggraloka yang berdekatan dengan kawasan ini.\",\"competency\":\"GEN-06\"},{\"type\":\"single\",\"text\":\"Ketiga pilar Tri Hita Karana adalah Parhyangan, Pawongan, dan…\",\"options\":[\"Palemahan\",\"Paramanusia\",\"Parahita\",\"Pawisata\"],\"answer\":0,\"explanation\":\"Tiga pilar THK adalah Parhyangan (harmoni dengan Tuhan), Pawongan (harmoni dengan manusia), dan Palemahan (harmoni dengan alam) — dasar filosofi kerja Sanggraloka.\",\"competency\":\"GEN-07\"},{\"type\":\"single\",\"text\":\"Huruf E pada metode LEARN berarti…\",\"options\":[\"Empathize\",\"Explain\",\"Exit\",\"Excuse\"],\"answer\":0,\"explanation\":\"E pada LEARN berarti Empathize (berempati), langkah setelah mendengarkan untuk menunjukkan kita memahami perasaan tamu, bukan sekadar menjelaskan situasi.\",\"competency\":\"GEN-08\"},{\"type\":\"single\",\"text\":\"Menggunakan APD (alat pelindung diri) sesuai tugas termasuk bagian dari…\",\"options\":[\"K3 (Kesehatan dan Keselamatan Kerja)\",\"Product knowledge\",\"Upselling\",\"THK\"],\"answer\":0,\"explanation\":\"Penggunaan APD adalah bagian dari penerapan K3 dasar untuk melindungi diri sendiri dari risiko kerja, terpisah dari topik product knowledge atau upselling.\",\"competency\":\"GEN-09\"},{\"type\":\"single\",\"text\":\"Titik kumpul (assembly point) evakuasi berfungsi sebagai tempat untuk…\",\"options\":[\"Menghitung dan memastikan semua orang aman setelah evakuasi\",\"Tempat menunggu bus jemputan\",\"Tempat menyimpan APAR\",\"Ruang istirahat karyawan\"],\"answer\":0,\"explanation\":\"Titik kumpul digunakan untuk memastikan semua staf dan tamu berhasil dievakuasi dengan aman lewat penghitungan jumlah orang, bukan sekadar tempat berkumpul biasa.\",\"competency\":\"GEN-10\"},{\"type\":\"single\",\"text\":\"Isi kotak P3K standar minimal mencakup…\",\"options\":[\"Perban, antiseptik, plester, sarung tangan\",\"Obat resep dokter untuk semua penyakit\",\"Alat bedah kecil\",\"Obat tidur\"],\"answer\":0,\"explanation\":\"Kotak P3K standar berisi perlengkapan pertolongan pertama dasar seperti perban, antiseptik, plester, dan sarung tangan — bukan obat resep atau alat medis lanjutan yang memerlukan tenaga medis.\",\"competency\":\"GEN-11\"},{\"type\":\"single\",\"text\":\"Sebelum menangani makanan, staf F&B wajib…\",\"options\":[\"Mencuci tangan dengan sabun minimal 20 detik\",\"Mengelap tangan ke seragam\",\"Menyemprot parfum ke tangan\",\"Memakai sarung tangan tanpa cuci tangan dulu\"],\"answer\":0,\"explanation\":\"Cuci tangan dengan sabun minimal 20 detik adalah standar higienitas dasar sebelum menangani makanan; sarung tangan tidak menggantikan kewajiban cuci tangan terlebih dahulu.\",\"competency\":\"GEN-12\"},{\"type\":\"single\",\"text\":\"Komentar bernada seksual dari rekan kerja kepada staf lain termasuk kategori…\",\"options\":[\"Pelecehan yang wajib dilaporkan\",\"Candaan biasa antar rekan\",\"Hal wajar di tempat kerja hospitality\",\"Bukan urusan perusahaan\"],\"answer\":0,\"explanation\":\"Komentar bernada seksual tergolong pelecehan yang wajib dilaporkan lewat kanal resmi, bukan dianggap candaan biasa meskipun terjadi antar rekan kerja yang akrab.\",\"competency\":\"GEN-13\"},{\"type\":\"single\",\"text\":\"UU PDP (Perlindungan Data Pribadi) mengatur tentang…\",\"options\":[\"Perlindungan data pribadi termasuk data tamu hotel\",\"Peraturan lalu lintas\",\"Pajak penghasilan\",\"Standar bangunan hotel\"],\"answer\":0,\"explanation\":\"UU PDP mengatur perlindungan data pribadi warga negara termasuk data tamu yang dikelola hotel seperti nomor kamar, paspor, dan riwayat menginap.\",\"competency\":\"GEN-14\"}]',85,20,3,'placement','2026-07-08 19:12:49','2026-07-08 19:12:49'),(36,1,NULL,NULL,'GEN — Placement Level 2','[{\"type\":\"single\",\"text\":\"Kamu sedang membawa nampan berisi welcome drink saat seorang tamu lewat berjarak sekitar 10 langkah, tangan penuh dan kamu tidak bisa menyapa dengan tangan. Tindakan yang tepat:\",\"options\":[\"Beri kontak mata dan senyum tulus, sapa verbal saat jarak sudah 5 langkah\",\"Menunduk fokus ke nampan sampai tamu lewat\",\"Berhenti total menaruh nampan demi menyapa formal\",\"Menyapa dengan suara keras dari jauh agar terdengar jelas\"],\"answer\":0,\"explanation\":\"Kontak mata dan senyum di jarak 10 langkah tetap bisa dilakukan meski tangan penuh, lalu sapaan verbal menyusul di jarak 5 langkah; menunduk membuat tamu merasa diabaikan.\",\"competency\":\"GEN-02\"},{\"type\":\"single\",\"text\":\"Tamu keluarga besar tiba bersamaan dengan tamu individu di lobby pada waktu yang hampir sama. Kamu sendirian bertugas menyambut. Prioritas yang tepat:\",\"options\":[\"Sapa keduanya dengan kontak mata, beri tahu akan segera dilayani bergantian tanpa membuat siapa pun menunggu tanpa sapaan\",\"Fokus hanya ke keluarga besar karena rombongannya lebih banyak\",\"Abaikan sampai rekan datang membantu\",\"Minta salah satu tamu menunggu tanpa penjelasan apa pun\"],\"answer\":0,\"explanation\":\"Sapaan awal ke semua pihak penting agar tidak ada yang merasa diabaikan, baru dilayani bergantian sesuai urutan kedatangan; memilih berdasarkan jumlah rombongan bukan prinsip yang benar.\",\"competency\":\"GEN-02\"},{\"type\":\"single\",\"text\":\"Telepon berdering saat kamu sedang menjawab pertanyaan tamu langsung di depanmu. Tindakan yang tepat:\",\"options\":[\"Minta izin sebentar ke tamu di depan, angkat telepon dengan salam standar, lalu selesaikan secepat mungkin\",\"Biarkan telepon berdering sampai tamu di depan selesai\",\"Angkat telepon tanpa bilang apa-apa ke tamu di depan\",\"Minta tamu di depan menjawab teleponnya\"],\"answer\":0,\"explanation\":\"Tamu yang hadir langsung tetap dihargai lewat izin sebentar, sementara telepon tetap direspons cepat sesuai standar 3 dering — keduanya tidak boleh diabaikan begitu saja.\",\"competency\":\"GEN-03\"},{\"type\":\"single\",\"text\":\"Tamu di telepon meminta informasi harga kamar untuk tanggal tertentu, tapi kamu tidak yakin apakah ada promo aktif. Respons yang tepat:\",\"options\":[\"\\\"Let me check the current rate for you\\\" lalu konfirmasi ke Reservation sebelum menjawab\",\"Menyebutkan harga normal tanpa mengecek promo\",\"Bilang harga bisa dicek sendiri di website\",\"Menebak kisaran harga supaya cepat\"],\"answer\":0,\"explanation\":\"Mengecek dulu ke Reservation memastikan info harga akurat termasuk promo aktif; menebak atau menyebutkan harga tanpa verifikasi berisiko menimbulkan komplain saat tamu check-in.\",\"competency\":\"GEN-04\"},{\"type\":\"single\",\"text\":\"Tamu bertanya apakah bisa memesan private dinner romantis di tepi sungai. Respons paling tepat sesuai product knowledge:\",\"options\":[\"Tawarkan opsi private dining yang tersedia dan arahkan detail ke tim F&B/Events untuk konfirmasi lokasi & waktu\",\"Jawab tidak tersedia tanpa mengecek dulu\",\"Menjanjikan lokasi spesifik tanpa koordinasi tim lain\",\"Menyuruh tamu memesan restoran di luar resort\"],\"answer\":0,\"explanation\":\"Staf perlu tahu resort punya layanan private dining dan mengarahkan detail teknis ke tim terkait untuk konfirmasi; menjanjikan sepihak tanpa koordinasi berisiko tidak bisa dipenuhi.\",\"competency\":\"GEN-05\"},{\"type\":\"single\",\"text\":\"Tamu baru tiba dari bandara terlihat lelah dan bertanya arah menuju pusat Ubud untuk makan malam. Respons paling membantu:\",\"options\":[\"Informasikan estimasi waktu tempuh dan tawarkan bantuan pemesanan transportasi resort\",\"Hanya menyebutkan arah tanpa detail waktu\",\"Menyarankan tamu jalan kaki karena dekat\",\"Menyuruh tamu bertanya ke satpam gerbang\"],\"answer\":0,\"explanation\":\"Memberi estimasi waktu tempuh sekaligus menawarkan bantuan transportasi menunjukkan inisiatif pelayanan penuh, terutama untuk tamu yang baru tiba dan lelah; menyarankan jalan kaki tidak realistis mengingat jarak dan medan.\",\"competency\":\"GEN-06\"},{\"type\":\"single\",\"text\":\"Tamu bertanya kenapa air kolam di resort tidak berbau kaporit menyengat seperti hotel lain. Jawaban yang mencerminkan nilai Palemahan:\",\"options\":[\"Jelaskan resort menggunakan sistem pengolahan air ramah lingkungan sesuai komitmen eco-luxury\",\"Jawab tidak tahu dan alihkan topik\",\"Bilang itu kebetulan saja\",\"Menjelaskan itu urusan teknis yang tidak perlu diketahui tamu\"],\"answer\":0,\"explanation\":\"Menjelaskan komitmen ramah lingkungan resort adalah bentuk eco-storytelling yang selaras dengan Palemahan; menjawab tidak tahu melewatkan kesempatan memperkuat citra resort.\",\"competency\":\"GEN-07\"},{\"type\":\"single\",\"text\":\"Tamu komplain bahwa AC di kamarnya berisik sepanjang malam. Kamu belum bisa memastikan penyebabnya. Langkah pertama sesuai LEARN:\",\"options\":[\"Dengarkan detail keluhan tamu dulu sebelum menjelaskan atau menjanjikan solusi\",\"Langsung menjanjikan teknisi datang dalam 5 menit tanpa mengecek jadwal\",\"Menjelaskan bahwa AC memang sudah tua\",\"Menyarankan tamu pindah kamar tanpa mendengar detail dulu\"],\"answer\":0,\"explanation\":\"Mendengarkan detail dulu (Listen) mencegah kita menjanjikan sesuatu yang tidak bisa dipenuhi dan membantu memahami akar masalah sebelum bertindak.\",\"competency\":\"GEN-08\"},{\"type\":\"single\",\"text\":\"Tamu marah karena merasa proses check-in terlalu lama akibat sistem lambat. Kamu tidak berwenang memberi kompensasi. Tindakan tepat:\",\"options\":[\"Minta maaf tulus, jelaskan sedang diusahakan, dan eskalasi ke Duty Manager untuk keputusan kompensasi\",\"Janjikan kompensasi sendiri agar tamu tenang\",\"Menyalahkan sistem IT secara terbuka di depan tamu\",\"Diam saja menunggu tamu selesai marah\"],\"answer\":0,\"explanation\":\"Permintaan maaf tulus dan eskalasi ke pihak berwenang adalah tindakan yang tepat sesuai batas wewenang staf; menjanjikan kompensasi sendiri berisiko melampaui otoritas.\",\"competency\":\"GEN-08\"},{\"type\":\"single\",\"text\":\"Kamu melihat lantai koridor tergenang air hujan yang masuk lewat celah pintu. Tindakan pertama yang tepat:\",\"options\":[\"Pasang wet floor sign dan laporkan via HotelFix agar segera ditangani\",\"Biarkan karena akan kering sendiri\",\"Lap dengan kain tapi tidak lapor\",\"Tunggu shift berikutnya melaporkan\"],\"answer\":0,\"explanation\":\"Wet floor sign mencegah kecelakaan langsung sementara laporan HotelFix memastikan penanganan tuntas oleh tim terkait; menunda laporan membiarkan risiko tetap ada.\",\"competency\":\"GEN-09\"},{\"type\":\"single\",\"text\":\"Alarm kebakaran berbunyi saat kamu sedang membantu tamu lansia yang berjalan lambat menggunakan tongkat. Tindakan tepat:\",\"options\":[\"Tetap tenang, dampingi dan bantu tamu menuju jalur evakuasi sesuai kemampuannya\",\"Tinggalkan tamu untuk menyelamatkan diri lebih dulu\",\"Menyuruh tamu berjalan cepat tanpa bantuan\",\"Menunggu tamu lain membantu terlebih dahulu\"],\"answer\":0,\"explanation\":\"Staf bertanggung jawab membantu tamu yang membutuhkan pendampingan ekstra saat evakuasi, terutama lansia; meninggalkan tamu demi keselamatan diri sendiri bertentangan dengan prinsip pelayanan dan keselamatan bersama.\",\"competency\":\"GEN-10\"},{\"type\":\"single\",\"text\":\"Kamu menemukan botol chemical pembersih tanpa label di area kerja. Tindakan yang tepat:\",\"options\":[\"Jangan digunakan, laporkan ke SPV untuk diidentifikasi dan diberi label yang benar\",\"Cium dulu untuk menebak isinya\",\"Gunakan saja karena terlihat seperti chemical biasa\",\"Buang ke wastafel agar aman\"],\"answer\":0,\"explanation\":\"Chemical tanpa label berisiko tinggi disalahgunakan atau tertukar, sehingga harus dilaporkan untuk diidentifikasi oleh yang berwenang; mencium atau membuang sembarangan justru membahayakan diri dan lingkungan.\",\"competency\":\"GEN-09\"},{\"type\":\"single\",\"text\":\"Rekan kerja tiba-tiba mengeluh nyeri dada dan sesak napas saat bertugas. Tindakan pertama yang tepat:\",\"options\":[\"Minta rekan duduk tenang, segera panggil bantuan medis/SPV, jangan biarkan sendirian\",\"Suruh rekan tetap bekerja sambil istirahat sebentar\",\"Beri obat sembarangan dari kotak P3K\",\"Catat dulu di HotelCrew baru bertindak\"],\"answer\":0,\"explanation\":\"Nyeri dada dan sesak napas adalah gejala serius yang butuh penanganan medis segera; menyuruh tetap bekerja atau memberi obat sembarangan bisa berakibat fatal.\",\"competency\":\"GEN-11\"},{\"type\":\"single\",\"text\":\"Kamu batuk pilek ringan tapi tidak demam, dan hari ini bertugas di outlet F&B yang sedang kekurangan staf. Sikap yang tepat:\",\"options\":[\"Tetap lapor kondisi ke SPV untuk keputusan bersama, gunakan masker bila diizinkan bekerja\",\"Tetap masuk tanpa lapor karena hanya gejala ringan\",\"Izin mendadak tanpa memberi tahu siapa pun\",\"Memutuskan sendiri untuk tetap bekerja penuh tanpa masker\"],\"answer\":0,\"explanation\":\"Melapor ke SPV memastikan keputusan diambil bersama mempertimbangkan risiko penularan dan kebutuhan operasional; memutuskan sendiri tanpa komunikasi berisiko bagi kesehatan tamu dan rekan kerja.\",\"competency\":\"GEN-12\"},{\"type\":\"single\",\"text\":\"Tamu pria berulang kali menyentuh tangan staf perempuan saat berbicara meski sudah dijauhkan halus. Tindakan tepat staf tersebut:\",\"options\":[\"Jaga jarak profesional, laporkan insiden ke SPV/HR lewat kanal resmi\",\"Diam saja karena tamu adalah raja\",\"Membalas dengan sikap kasar di depan tamu lain\",\"Menghindar total tanpa melapor\"],\"answer\":0,\"explanation\":\"Menjaga jarak profesional sambil melaporkan lewat kanal resmi melindungi staf dan memastikan tindak lanjut sesuai kebijakan anti-harassment; membiarkan tanpa laporan membiarkan pola berulang.\",\"competency\":\"GEN-13\"},{\"type\":\"single\",\"text\":\"Penelepon mengaku dari media lokal dan meminta konfirmasi apakah seorang tokoh publik menginap hari ini. Respons tepat:\",\"options\":[\"Tidak mengonfirmasi identitas tamu, arahkan ke Public Relations/Manajemen\",\"Mengonfirmasi karena media berhak tahu\",\"Memberi info parsial seperti nomor kamar saja\",\"Menutup telepon tanpa penjelasan\"],\"answer\":0,\"explanation\":\"Privasi tamu tetap dijaga dari pihak eksternal termasuk media; permintaan semacam ini diarahkan ke PR/Manajemen yang berwenang menentukan kebijakan komunikasi publik.\",\"competency\":\"GEN-14\"},{\"type\":\"single\",\"text\":\"Kamu menawarkan upgrade ke Deluxe Private Pool Villa dan tamu langsung tertarik serta bertanya harga. Sikap lanjutan yang tepat:\",\"options\":[\"Konfirmasi ketersediaan & harga aktual ke Reservation sebelum memastikan ke tamu\",\"Langsung menyebutkan harga dari ingatan tanpa cek ketersediaan\",\"Menjanjikan upgrade gratis agar tamu senang\",\"Mengalihkan ke penawaran lain karena ragu\"],\"answer\":0,\"explanation\":\"Ketersediaan kamar dan harga bisa berubah sewaktu-waktu, sehingga konfirmasi ke Reservation penting sebelum memastikan ke tamu; menyebutkan angka dari ingatan berisiko keliru.\",\"competency\":\"GEN-16\"},{\"type\":\"single\",\"text\":\"Tamu tiba dengan pakaian formal dan menyapa staf terlebih dahulu dengan \\\"Bonjour\\\". Respons paling tepat:\",\"options\":[\"Membalas \\\"Bonjour\\\" dengan senyum dan melanjutkan dalam bahasa Inggris/Indonesia sesuai kenyamanan tamu\",\"Membalas dalam bahasa Indonesia saja tanpa menghiraukan sapaannya\",\"Diam karena tidak paham bahasa Perancis\",\"Menjawab \\\"Bonsoir\\\" karena terdengar mirip\"],\"answer\":0,\"explanation\":\"Membalas sapaan dalam bahasanya menunjukkan penghargaan personal sebelum melanjutkan komunikasi dalam bahasa yang nyaman bagi kedua pihak; menjawab dengan sapaan waktu yang salah (Bonsoir untuk situasi bukan malam) justru kurang tepat.\",\"competency\":\"GEN-18\"},{\"type\":\"single\",\"text\":\"Tamu bertanya soal Butterfly Sanctuary dan menunjuk bunga Ixora yang banyak dikerumuni kupu-kupu dewasa. Penjelasan paling tepat:\",\"options\":[\"Itu tanaman nektar sumber makanan kupu-kupu dewasa, berbeda dari tanaman inang tempat bertelur\",\"Itu tanaman inang tempat kupu bertelur\",\"Itu tanaman hias tanpa fungsi ekologis\",\"Itu tanaman yang seharusnya dicabut karena mengundang serangga\"],\"answer\":0,\"explanation\":\"Ixora/Lantana adalah tanaman nektar untuk kupu dewasa, berbeda fungsi dari tanaman inang (seperti Aristolochia) yang jadi tempat bertelur dan makanan ulat; keduanya sengaja ditanam untuk mendukung sanctuary.\",\"competency\":\"GEN-21\"},{\"type\":\"single\",\"text\":\"Seorang tamu bertanya kenapa amenity di kamar mandi villa memakai botol besar isi ulang, bukan botol kecil sekali pakai seperti di hotel lain yang pernah ia inapi. Jawaban paling tepat yang sekaligus mempromosikan nilai resort:\",\"options\":[\"Jelaskan ini bagian dari komitmen bebas plastik sekali pakai sesuai prinsip eco-luxury Sanggraloka\",\"Jawab itu untuk menghemat biaya operasional saja\",\"Bilang tidak tahu alasannya dan alihkan topik\",\"Menjanjikan akan mengganti dengan botol kecil jika tamu memintanya\"],\"answer\":0,\"explanation\":\"Menjelaskan komitmen bebas plastik sekali pakai memperkuat citra eco-luxury sekaligus mengedukasi tamu secara positif; mengaitkannya semata dengan penghematan biaya mengurangi nilai cerita keberlanjutan resort.\",\"competency\":\"GEN-19\"}]',85,20,3,'placement','2026-07-08 19:12:49','2026-07-08 19:12:49'),(37,1,NULL,NULL,'GEN — Placement Level 3','[{\"type\":\"single\",\"text\":\"Dua tamu datang bersamaan tanpa reservasi saat kamu bertugas sendirian di front desk pada malam hari tanpa SPV standby. Satu tamu tampak kelelahan dan satu lagi tergesa mengejar acara. Kamar tersisa hanya satu. Prioritas keputusan yang paling tepat:\",\"options\":[\"Tangani berdasarkan urutan kedatangan sambil tetap ramah ke keduanya, tawarkan solusi alternatif (resort/mitra terdekat) untuk yang tidak kebagian\",\"Berikan ke tamu yang terlihat lebih penting secara subjektif\",\"Minta keduanya menunggu tanpa keputusan sampai SPV datang meski butuh waktu lama\",\"Menolak keduanya untuk menghindari konflik\"],\"answer\":0,\"explanation\":\"Tanpa atasan, keputusan adil berbasis urutan kedatangan paling objektif dan bisa dipertanggungjawabkan; tetap sediakan solusi lain agar tamu yang tidak kebagian kamar tidak merasa ditinggalkan begitu saja.\",\"competency\":\"GEN-08\"},{\"type\":\"single\",\"text\":\"Kamu menemukan rekan kerja shift malam tertidur di area belakang saat jam kerja, sementara tamu VIP baru saja meminta bantuan dan tidak ada staf lain yang available. Tindakan paling tepat secara berurutan:\",\"options\":[\"Segera layani tamu VIP dulu, lalu bicarakan baik-baik dengan rekan setelahnya dan laporkan sesuai kebijakan bila berulang\",\"Foto rekan tidur untuk bukti dan langsung kirim ke grup WA kantor\",\"Abaikan tamu VIP demi membangunkan rekan dulu\",\"Diam saja dan tidak melakukan apa pun terhadap keduanya\"],\"answer\":0,\"explanation\":\"Prioritas pertama tetap pelayanan tamu yang sedang membutuhkan bantuan; masalah rekan kerja diselesaikan secara pribadi dan profesional, bukan dipermalukan lewat media sosial internal yang bisa merusak hubungan kerja.\",\"competency\":\"GEN-15\"},{\"type\":\"single\",\"text\":\"Tamu bersikeras merokok di dalam villa non-smoking dan menolak berpindah ke area yang disediakan, sambil mengancam akan memberi review buruk. Kamu sendirian menangani tanpa SPV di lokasi. Tindakan paling tepat:\",\"options\":[\"Tetap sopan jelaskan kebijakan & konsekuensi biaya pembersihan, tawarkan area smoking terdekat, dan eskalasi ke Duty Manager via telepon bila tamu tetap menolak\",\"Mengizinkan demi menghindari review buruk\",\"Berdebat keras mempertahankan aturan tanpa solusi\",\"Diam saja dan membiarkan tamu merokok\"],\"answer\":0,\"explanation\":\"Kebijakan tetap dijelaskan dengan tenang disertai solusi alternatif; ancaman review buruk bukan alasan melanggar kebijakan keselamatan/kebersihan, dan eskalasi ke Duty Manager tetap perlu dilakukan meski tidak berada di lokasi.\",\"competency\":\"GEN-08\"},{\"type\":\"single\",\"text\":\"Saat gempa cukup kuat terjadi malam hari, kamu sedang membantu tamu di area villa dekat tebing sungai sementara jalur evakuasi resmi melewati jalan memutar yang lebih jauh. Tamu panik ingin lewat jalan pintas dekat tebing. Keputusan tepat:\",\"options\":[\"Tetap arahkan tamu lewat jalur evakuasi resmi meski memutar, jelaskan singkat risiko longsor di jalur tebing\",\"Ikuti keinginan tamu lewat jalan pintas demi kecepatan\",\"Biarkan tamu memilih sendiri tanpa arahan\",\"Diam menunggu instruksi meski situasi mendesak\"],\"answer\":0,\"explanation\":\"Keselamatan jangka panjang lebih penting dari kecepatan sesaat — jalur tebing berisiko longsor pasca gempa; staf harus tegas mengarahkan meski tamu panik dan jalurnya terasa lebih jauh.\",\"competency\":\"GEN-10\"},{\"type\":\"single\",\"text\":\"Tamu mengalami reaksi alergi ringan (gatal-gatal) setelah makan malam, namun menolak dibawa ke klinik dan hanya minta didiamkan saja di kamar. Sebagai staf yang menemukan kondisi ini, sikap yang tepat:\",\"options\":[\"Hormati keputusan tamu untuk gejala ringan, tapi tetap informasikan SPV/klinik agar dipantau dan siap bila memburuk\",\"Memaksa tamu ke klinik meski menolak\",\"Diam total tanpa melapor karena tamu sudah menolak bantuan\",\"Memberi obat alergi pribadi tanpa sepengetahuan tim medis\"],\"answer\":0,\"explanation\":\"Hak tamu menolak perawatan dihormati untuk gejala ringan, namun staf tetap wajib menginformasikan pihak terkait agar ada pemantauan jika kondisi memburuk; memberi obat pribadi tanpa otorisasi medis berisiko berbahaya.\",\"competency\":\"GEN-11\"},{\"type\":\"single\",\"text\":\"Kamu mendapati indikasi kuat seorang rekan kerja mencuri barang tamu dari kamar yang sedang dibersihkan, namun tidak ada bukti foto/video langsung. Langkah paling tepat:\",\"options\":[\"Laporkan kecurigaan dengan detail observasi ke SPV/HR melalui kanal resmi untuk diinvestigasi lebih lanjut\",\"Konfrontasi langsung ke rekan tersebut sendirian\",\"Diam karena tidak ada bukti kuat\",\"Menyebarkan kecurigaan ke rekan-rekan lain dulu sebelum lapor\"],\"answer\":0,\"explanation\":\"Laporan resmi ke pihak berwenang memungkinkan investigasi yang adil dan terverifikasi; konfrontasi langsung atau menyebar gosip berisiko merusak proses investigasi dan hubungan kerja.\",\"competency\":\"GEN-15\"},{\"type\":\"single\",\"text\":\"Dua departemen (F&B dan Housekeeping) saling menyalahkan soal keterlambatan setup private dinner untuk tamu honeymoon, sementara waktu acara tinggal 15 menit lagi dan kamu adalah staf yang paling dekat lokasi. Tindakan paling tepat:\",\"options\":[\"Fokus membantu menyelesaikan setup semampunya sekarang, laporkan akar masalah koordinasi ke SPV setelah acara selesai\",\"Ikut menyalahkan salah satu pihak di depan tamu\",\"Menunggu kedua departemen selesai berdebat dulu\",\"Membatalkan acara sepihak tanpa konsultasi\"],\"answer\":0,\"explanation\":\"Prioritas mendesak adalah menyelamatkan momen tamu yang tersisa sedikit waktu; evaluasi akar masalah koordinasi antar-departemen dilakukan setelahnya lewat jalur yang tepat, bukan di tengah krisis.\",\"competency\":\"GEN-08\"},{\"type\":\"single\",\"text\":\"Tamu VIP meminta staf memberikan diskon besar di luar kewenangan dengan alasan kenal dekat pemilik resort, dan tidak ada SPV yang bisa dihubungi saat itu. Sikap paling tepat:\",\"options\":[\"Sampaikan permintaan akan diteruskan untuk konfirmasi resmi begitu SPV/Manajemen bisa dihubungi, tanpa menjanjikan apa pun sekarang\",\"Memberikan diskon langsung karena takut mengecewakan tamu penting\",\"Menolak mentah-mentah tanpa penjelasan apa pun\",\"Berjanji pasti disetujui meski belum ada konfirmasi\"],\"answer\":0,\"explanation\":\"Keputusan finansial di luar wewenang staf tidak boleh dijanjikan sepihak meski tamu mengaku kenal pemilik; penundaan dengan komunikasi jujur adalah langkah paling aman secara profesional.\",\"competency\":\"GEN-16\"},{\"type\":\"single\",\"text\":\"Kamu melihat wisatawan asing (bukan tamu resort) mencoba menangkap kupu-kupu Troides helena di area Butterfly Sanctuary yang bisa diakses publik terbatas. Tindakan paling tepat:\",\"options\":[\"Tegur sopan, jelaskan status dilindungi (PP 7/1999 & CITES App. II) dan risiko hukum, laporkan ke pengelola area jika menolak berhenti\",\"Biarkan karena bukan tamu resort\",\"Menangkap sendiri kupu itu agar aman dari orang tersebut\",\"Mendiamkan dan hanya mengawasi dari jauh tanpa bertindak\"],\"answer\":0,\"explanation\":\"Perlindungan spesies dilindungi berlaku untuk siapa pun, bukan hanya tamu resort; edukasi sopan disertai eskalasi ke pengelola bila diabaikan adalah tindakan yang bertanggung jawab sekaligus menjaga hubungan baik.\",\"competency\":\"GEN-21\"},{\"type\":\"single\",\"text\":\"Sistem HotelCrew mengalami down total saat kamu perlu mengecek jadwal shift dan melaporkan insiden K3 mendesak. Tidak ada SPV IT yang standby. Langkah paling tepat:\",\"options\":[\"Gunakan prosedur manual/cadangan sesuai SOP darurat, catat detail insiden untuk diinput begitu sistem pulih, informasikan pihak terkait via kanal lain (telepon/radio)\",\"Menunda laporan insiden sampai sistem pulih sepenuhnya\",\"Mengabaikan insiden karena tidak bisa dicatat di app\",\"Mencatat di kertas lalu membuangnya karena dianggap tidak resmi\"],\"answer\":0,\"explanation\":\"Insiden K3 mendesak tidak boleh menunggu sistem digital pulih — SOP darurat/manual dan komunikasi lewat kanal lain harus tetap dijalankan, dengan pencatatan resmi menyusul begitu sistem kembali normal.\",\"competency\":\"GEN-17\"},{\"type\":\"single\",\"text\":\"Tamu Korea senior (formal) dan tamu Perancis santai berada di meja bersebelahan di Meditera, keduanya butuh perhatianmu bersamaan saat kamu sendirian menjaga outlet. Pendekatan komunikasi lintas budaya paling tepat:\",\"options\":[\"Sesuaikan gaya: lebih formal & hormat ke tamu Korea (mis. sapaan nama keluarga), lebih santai namun tetap sopan ke tamu Perancis, tanpa mengabaikan salah satu\",\"Gunakan gaya yang sama persis untuk kedua tamu demi konsistensi\",\"Prioritaskan salah satu berdasarkan siapa yang terlihat lebih senior\",\"Minta salah satu menunggu tanpa penjelasan hingga selesai dengan yang lain\"],\"answer\":0,\"explanation\":\"Sensitivitas budaya berarti menyesuaikan gaya komunikasi tanpa mengorbankan kualitas layanan ke tamu lain; menyamaratakan gaya komunikasi kadang mengabaikan norma budaya yang penting bagi masing-masing tamu.\",\"competency\":\"GEN-18\"},{\"type\":\"single\",\"text\":\"Tamu menuduh stafmu telah mengambil barang berharga dari kamarnya, padahal kamu tahu rekan tersebut jujur dan CCTV area itu sedang tidak berfungsi. Tindakan paling tepat sebagai staf yang dituduh terlibat secara tidak langsung:\",\"options\":[\"Tetap tenang, sampaikan akan dieskalasi ke Duty Manager/Security untuk investigasi resmi, tidak membela diri secara emosional di depan tamu\",\"Membela rekan secara emosional dan menyalahkan tamu langsung\",\"Diam saja tanpa melaporkan apa pun ke atasan\",\"Menyalahkan tamu lain yang menginap di kamar sebelah tanpa dasar\"],\"answer\":0,\"explanation\":\"Situasi tanpa bukti CCTV membutuhkan investigasi formal yang adil bagi semua pihak; membela diri secara emosional di depan tamu berisiko memperburuk situasi, sementara diam saja mengabaikan tanggung jawab pelaporan.\",\"competency\":\"GEN-14\"},{\"type\":\"single\",\"text\":\"Kamu menemukan bahwa prosedur pemadaman kebakaran di outlet dapur ternyata berbeda antara pelatihan lama dan SOP baru yang baru diperbarui, dan kamu ragu mana yang berlaku saat kondisi darurat sungguhan terjadi. Sikap paling tepat saat itu juga:\",\"options\":[\"Gunakan SOP terbaru yang tervalidasi (PASS) dan segera bertindak, klarifikasi perbedaan prosedur ke SPV K3 setelah situasi aman\",\"Berhenti bertindak karena bingung memilih prosedur\",\"Menggunakan prosedur lama karena lebih familiar\",\"Menunggu konfirmasi SPV dulu sebelum bertindak apa pun\"],\"answer\":0,\"explanation\":\"Dalam kondisi darurat nyata, bertindak cepat dengan SOP resmi terbaru (PASS) lebih penting daripada menunda karena keraguan administratif; klarifikasi kebijakan dilakukan setelah situasi aman terkendali.\",\"competency\":\"GEN-09\"},{\"type\":\"single\",\"text\":\"Tamu meminta staf menghapus review negatif yang baru saja ditulisnya di platform online sebagai syarat agar dia tidak membuat keributan di lobby. Sikap paling tepat:\",\"options\":[\"Jelaskan staf tidak berwenang menghapus review pihak ketiga, tetap tawarkan penyelesaian keluhan aslinya dan eskalasi ke Manajemen/PR untuk respons resmi\",\"Berjanji akan menghapus review meski tidak mungkin dilakukan\",\"Mengabaikan permintaan dan meninggalkan tamu begitu saja\",\"Meminta staf lain ikut menekan tamu agar diam\"],\"answer\":0,\"explanation\":\"Staf tidak memiliki kewenangan atas platform pihak ketiga sehingga tidak boleh menjanjikan hal mustahil; fokus tetap pada penyelesaian akar masalah dan meneruskan ke pihak yang berwenang menangani reputasi online.\",\"competency\":\"GEN-08\"},{\"type\":\"single\",\"text\":\"Kamu diminta rekan kerja untuk menandatangani absen kehadirannya di HotelCrew karena dia terlambat dan takut kena sanksi, dengan alasan \'saling bantu sesama staf\'. Sikap paling tepat:\",\"options\":[\"Tolak dengan tegas namun tetap suportif, sarankan rekan lapor jujur ke SPV karena integritas absensi tidak bisa dikompromikan\",\"Bantu menandatangani karena kasihan dan hanya sekali\",\"Bantu asal rekan berjanji membalas budi lain waktu\",\"Laporkan rekan ke seluruh tim tanpa membicarakan langsung dulu\"],\"answer\":0,\"explanation\":\"Integritas absensi adalah prinsip yang tidak bisa dikompromikan meski dengan alasan solidaritas; penolakan tegas namun tetap suportif membantu rekan menghadapi konsekuensi secara jujur, bukan menutupinya.\",\"competency\":\"GEN-15\"},{\"type\":\"single\",\"text\":\"Tamu jangka panjang (long-stay) mulai menunjukkan sikap posesif berlebihan ke salah satu staf, sering meminta staf tersebut secara khusus di luar jam kerja untuk urusan pribadi non-hotel. Langkah paling tepat bagi staf yang bersangkutan:\",\"options\":[\"Tetapkan batasan profesional dengan sopan, laporkan pola ini ke SPV agar penugasan staf diatur ulang bila perlu\",\"Menuruti semua permintaan demi menjaga hubungan baik dengan tamu\",\"Menghindari tamu secara drastis tanpa penjelasan\",\"Menceritakan ke tamu lain sebagai bahan obrolan\"],\"answer\":0,\"explanation\":\"Batasan profesional harus dijaga meski tamu bersikap ramah berlebihan; melapor ke SPV memungkinkan penyesuaian penugasan yang melindungi staf tanpa harus bersikap kasar ke tamu.\",\"competency\":\"GEN-13\"},{\"type\":\"single\",\"text\":\"Terjadi kebocoran gas kecil di dapur outlet saat jam sibuk, tercium bau menyengat namun belum ada api. Tidak ada Chef/SPV di lokasi saat itu. Urutan tindakan paling tepat:\",\"options\":[\"Matikan sumber gas bila aman dilakukan, evakuasi area, jangan nyalakan listrik/api, laporkan ke Security/Engineering segera\",\"Tetap masak sambil membuka jendela sedikit\",\"Menunggu Chef datang baru bertindak\",\"Menyalakan exhaust fan listrik untuk mengusir bau\"],\"answer\":0,\"explanation\":\"Kebocoran gas berisiko ledakan bila terkena percikan listrik/api, sehingga mematikan sumber gas (bila aman), evakuasi, dan menghindari saklar listrik adalah langkah keselamatan utama sebelum menunggu bantuan ahli.\",\"competency\":\"GEN-09\"},{\"type\":\"single\",\"text\":\"Tamu meminta rekomendasi kegiatan sore, dan kamu tahu dua pilihan: Rice Paddies Experience (butuh reservasi H-1) dan jalan santai mandiri ke area farm organik (bebas kapan saja). Tamu baru memutuskan mendadak sore ini. Rekomendasi paling realistis:\",\"options\":[\"Sarankan jalan santai ke farm organik sore ini, tawarkan bantu reservasi Rice Paddies Experience untuk esok hari\",\"Memaksakan Rice Paddies Experience hari ini meski belum reservasi\",\"Menjawab tidak ada kegiatan yang bisa dilakukan sore ini\",\"Menyuruh tamu ke Ubud tanpa alternatif di resort\"],\"answer\":0,\"explanation\":\"Memberi solusi yang benar-benar bisa dilakukan hari itu (farm organik) sambil menawarkan opsi terjadwal untuk esok menunjukkan problem-solving yang realistis, bukan menjanjikan sesuatu yang melanggar syarat reservasi.\",\"competency\":\"GEN-05\"},{\"type\":\"single\",\"text\":\"Seorang tamu food blogger meminta staf memberi komentar on-record tentang chef atau manajemen untuk kontennya, sambil merekam video langsung tanpa pemberitahuan sebelumnya. Sikap paling tepat:\",\"options\":[\"Tetap ramah, sampaikan tidak berwenang memberi pernyataan resmi mewakili resort, arahkan permintaan wawancara ke PR/Marketing\",\"Memberi komentar spontan karena merasa itu pendapat pribadi saja\",\"Menolak kasar dan meminta rekaman dihapus paksa\",\"Diam total tanpa memberi penjelasan apa pun ke tamu\"],\"answer\":0,\"explanation\":\"Pernyataan mewakili resort harus melalui kanal resmi PR/Marketing; staf yang memberi komentar spontan berisiko menimbulkan pernyataan yang tidak akurat atau merugikan resort meski diniatkan sebagai pendapat pribadi.\",\"competency\":\"GEN-15\"},{\"type\":\"single\",\"text\":\"Kamu memimpin sementara shift F&B karena SPV sedang cuti mendadak, lalu mendapati satu staf baru tetap memegang pegangan tangga dengan tangan yang sama saat menyentuh makanan setelah mengangkut galon air minum, tanpa cuci tangan ulang. Tidak ada waktu menunggu SPV kembali karena outlet ramai. Tindakan paling tepat sebagai penanggung jawab shift saat itu:\",\"options\":[\"Hentikan sebentar staf tersebut, minta cuci tangan ulang 20 detik sebelum lanjut menyentuh makanan, lalu ingatkan seluruh tim soal titik kontak yang wajib diikuti cuci tangan\",\"Biarkan saja karena outlet sedang ramai dan tidak ada waktu\",\"Tegur keras di depan tamu agar jadi pelajaran cepat\",\"Diamkan dan baru dibahas nanti setelah SPV kembali dari cuti\"],\"answer\":0,\"explanation\":\"Higienitas pangan tidak bisa ditunda meski outlet sedang sibuk — koreksi cepat namun tetap dilakukan secara pribadi (bukan mempermalukan di depan tamu) adalah keputusan yang harus diambil mandiri oleh penanggung jawab shift saat itu juga.\",\"competency\":\"GEN-12\"}]',85,25,3,'placement','2026-07-08 19:12:49','2026-07-08 19:12:49');

--
-- Table structure for table `hr_trainees`
--

CREATE TABLE `hr_trainees` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `full_name` varchar(150) NOT NULL,
  `school` varchar(150) DEFAULT NULL,
  `mou_file` varchar(255) DEFAULT NULL,
  `mentor_id` int(10) unsigned DEFAULT NULL,
  `batch` varchar(30) DEFAULT NULL,
  `start_date` date DEFAULT NULL,
  `end_date` date DEFAULT NULL,
  `monthly_scores` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`monthly_scores`)),
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_hr_trainees_property` (`property_id`),
  KEY `idx_hr_trainees_mentor` (`mentor_id`),
  CONSTRAINT `fk_hr_trainees_mentor` FOREIGN KEY (`mentor_id`) REFERENCES `hr_employees` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_hr_trainees_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `hr_trainees`
--

INSERT INTO `hr_trainees` VALUES (1,1,'Putu Trainee Satu (DUMMY demo)','SMK Pariwisata Ubud (DUMMY demo)','hr_trainees/mou-1-demo.pdf (DUMMY)',2,'2026-A','2026-06-08','2026-09-06','{\"bulan1\": 82}','2026-07-08 20:14:02','2026-07-08 20:14:02'),(2,1,'Ayu Trainee Dua (DUMMY demo)','SMK Pariwisata Ubud (DUMMY demo)','hr_trainees/mou-2-demo.pdf (DUMMY)',1,'2026-A','2026-06-23','2026-09-21',NULL,'2026-07-08 20:14:02','2026-07-08 20:14:02');

--
-- Table structure for table `hr_vacancies`
--

CREATE TABLE `hr_vacancies` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `position_id` int(10) unsigned NOT NULL,
  `headcount` smallint(5) unsigned NOT NULL DEFAULT 1,
  `budget_approved` tinyint(1) NOT NULL DEFAULT 0,
  `status` enum('open','on_hold','closed','filled') NOT NULL DEFAULT 'open',
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_hr_vacancies_property_status` (`property_id`,`status`),
  KEY `idx_hr_vacancies_position` (`position_id`),
  CONSTRAINT `fk_hr_vacancies_position` FOREIGN KEY (`position_id`) REFERENCES `hr_positions` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_hr_vacancies_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `hr_vacancies`
--

INSERT INTO `hr_vacancies` VALUES (1,1,1,2,1,'open','2026-07-08 20:14:02','2026-07-08 20:14:02');

--
-- Table structure for table `inv_items`
--

CREATE TABLE `inv_items` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `code` varchar(40) NOT NULL,
  `name` varchar(150) NOT NULL,
  `category` enum('linen','fnb','beverage','guest_supplies','general') NOT NULL DEFAULT 'general',
  `unit` varchar(30) NOT NULL DEFAULT 'pcs',
  `par_level` decimal(12,3) DEFAULT NULL COMMENT 'stok ideal minimum (par); NULL = tak ditetapkan',
  `department` varchar(60) DEFAULT NULL COMMENT 'dept pemilik, match kode hr_departments.code',
  `storage` varchar(120) DEFAULT NULL COMMENT 'gudang/lokasi simpan (teks bebas)',
  `unit_cost` decimal(14,2) DEFAULT NULL COMMENT 'harga satuan; NULL = belum ditetapkan (anti-karang)',
  `active` tinyint(1) NOT NULL DEFAULT 1,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_inv_items_property_code` (`property_id`,`code`),
  KEY `idx_inv_items_property_category` (`property_id`,`category`),
  KEY `idx_inv_items_property_department` (`property_id`,`department`),
  CONSTRAINT `fk_inv_items_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `inv_items`
--

INSERT INTO `inv_items` VALUES (1,1,'LIN-SHEET-Q','DUMMY — Sprei Queen','linen','lembar',40.000,'housekeeping','Gudang Linen',NULL,1,'2026-07-09 16:13:38','2026-07-09 16:13:38'),(2,1,'LIN-TOWEL-B','DUMMY — Handuk Mandi','linen','lembar',60.000,'housekeeping','Gudang Linen',NULL,1,'2026-07-09 16:13:38','2026-07-09 16:13:38'),(3,1,'FNB-BERAS','DUMMY — Beras Premium 5kg','fnb','karung',20.000,'fnb','Gudang F&B',NULL,1,'2026-07-09 16:13:38','2026-07-09 16:13:38'),(4,1,'FNB-MINYAK','DUMMY — Minyak Goreng 2L','fnb','botol',24.000,'fnb','Gudang F&B',NULL,1,'2026-07-09 16:13:38','2026-07-09 16:13:38'),(5,1,'BEV-KOPI','DUMMY — Kopi Bubuk Arabika 1kg','beverage','pak',15.000,'fnb','Gudang F&B',NULL,1,'2026-07-09 16:13:38','2026-07-09 16:13:38'),(6,1,'BEV-TEH','DUMMY — Teh Celup (box 25)','beverage','box',20.000,'fnb','Gudang F&B',NULL,1,'2026-07-09 16:13:38','2026-07-09 16:13:38'),(7,1,'BEV-AQUA','DUMMY — Air Mineral 600ml','beverage','dus',30.000,'fnb','Gudang F&B',NULL,1,'2026-07-09 16:13:38','2026-07-09 16:13:38'),(8,1,'GS-SABUN','DUMMY — Sabun Batang 25g','guest_supplies','pcs',200.000,'housekeeping','Gudang GS',NULL,1,'2026-07-09 16:13:38','2026-07-09 16:13:38'),(9,1,'GS-DENTAL','DUMMY — Dental Kit','guest_supplies','set',150.000,'housekeeping','Gudang GS',NULL,1,'2026-07-09 16:13:38','2026-07-09 16:13:38'),(10,1,'GS-SHAMPOO','DUMMY — Sampo Sachet 30ml','guest_supplies','pcs',200.000,'housekeeping','Gudang GS',NULL,1,'2026-07-09 16:13:38','2026-07-09 16:13:38'),(11,1,'GEN-TISU','DUMMY — Tisu Gulung','general','roll',100.000,'engineering','Gudang Umum',NULL,1,'2026-07-09 16:13:38','2026-07-09 16:13:38'),(12,1,'GEN-KANTONG','DUMMY — Kantong Sampah 60x90','general','pak',40.000,'engineering','Gudang Umum',NULL,1,'2026-07-09 16:13:38','2026-07-09 16:13:38');

--
-- Table structure for table `inv_opname_lines`
--

CREATE TABLE `inv_opname_lines` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `opname_id` int(10) unsigned NOT NULL,
  `item_id` int(10) unsigned NOT NULL,
  `qty_system` decimal(14,3) NOT NULL DEFAULT 0.000 COMMENT 'saldo sistem saat opname dibuat',
  `qty_actual` decimal(14,3) DEFAULT NULL COMMENT 'hasil hitung fisik; NULL = belum dihitung',
  `note` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_inv_opname_lines` (`opname_id`,`item_id`),
  KEY `idx_inv_opname_lines_item` (`item_id`),
  CONSTRAINT `fk_inv_opname_lines_item` FOREIGN KEY (`item_id`) REFERENCES `inv_items` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_inv_opname_lines_opname` FOREIGN KEY (`opname_id`) REFERENCES `inv_opnames` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `inv_opname_lines`
--

INSERT INTO `inv_opname_lines` VALUES (1,1,1,50.000,48.000,'DUMMY — 2 hilang/rusak'),(2,1,2,80.000,80.000,NULL),(3,2,5,18.000,NULL,NULL),(4,2,6,22.000,NULL,NULL);

--
-- Table structure for table `inv_opnames`
--

CREATE TABLE `inv_opnames` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `department` varchar(60) DEFAULT NULL,
  `storage` varchar(120) DEFAULT NULL,
  `status` enum('draft','counting','review','closed') NOT NULL DEFAULT 'draft',
  `created_by` int(10) unsigned DEFAULT NULL,
  `closed_by` int(10) unsigned DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `closed_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_inv_opnames_property_status` (`property_id`,`status`),
  KEY `fk_inv_opnames_created_by` (`created_by`),
  KEY `fk_inv_opnames_closed_by` (`closed_by`),
  CONSTRAINT `fk_inv_opnames_closed_by` FOREIGN KEY (`closed_by`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_inv_opnames_created_by` FOREIGN KEY (`created_by`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_inv_opnames_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `inv_opnames`
--

INSERT INTO `inv_opnames` VALUES (1,1,'housekeeping','Gudang Linen','closed',1,1,'2026-07-09 16:13:38','2026-07-09 16:13:38'),(2,1,'fnb','Gudang F&B','draft',1,NULL,'2026-07-09 16:13:38',NULL);

--
-- Table structure for table `inv_request_lines`
--

CREATE TABLE `inv_request_lines` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `request_id` int(10) unsigned NOT NULL,
  `item_id` int(10) unsigned NOT NULL,
  `qty_requested` decimal(14,3) NOT NULL DEFAULT 0.000,
  `qty_issued` decimal(14,3) DEFAULT NULL COMMENT 'jumlah yang benar-benar diserahkan; NULL = belum',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_inv_request_lines` (`request_id`,`item_id`),
  KEY `idx_inv_request_lines_item` (`item_id`),
  CONSTRAINT `fk_inv_request_lines_item` FOREIGN KEY (`item_id`) REFERENCES `inv_items` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_inv_request_lines_request` FOREIGN KEY (`request_id`) REFERENCES `inv_requests` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `inv_request_lines`
--

INSERT INTO `inv_request_lines` VALUES (1,1,8,50.000,50.000),(2,1,9,40.000,40.000),(3,2,5,10.000,NULL),(4,2,7,15.000,NULL);

--
-- Table structure for table `inv_requests`
--

CREATE TABLE `inv_requests` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `department` varchar(60) DEFAULT NULL COMMENT 'dept peminta, match kode hr_departments.code',
  `request_date` date NOT NULL,
  `status` enum('diajukan','disiapkan','diserahkan','selesai','ditolak') NOT NULL DEFAULT 'diajukan',
  `requested_by` int(10) unsigned DEFAULT NULL,
  `handled_by` int(10) unsigned DEFAULT NULL,
  `note` varchar(255) DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_inv_requests_property_status` (`property_id`,`status`),
  KEY `idx_inv_requests_property_dept` (`property_id`,`department`),
  KEY `fk_inv_requests_requested_by` (`requested_by`),
  KEY `fk_inv_requests_handled_by` (`handled_by`),
  CONSTRAINT `fk_inv_requests_handled_by` FOREIGN KEY (`handled_by`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_inv_requests_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_inv_requests_requested_by` FOREIGN KEY (`requested_by`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `inv_requests`
--

INSERT INTO `inv_requests` VALUES (1,1,'housekeeping','2026-07-09','selesai',1,1,'DUMMY — permintaan guest supplies harian','2026-07-09 16:13:38','2026-07-09 16:13:38'),(2,1,'fnb','2026-07-09','diajukan',1,NULL,'DUMMY — permintaan beverage restoran','2026-07-09 16:13:38','2026-07-09 16:13:38');

--
-- Table structure for table `inv_stock_moves`
--

CREATE TABLE `inv_stock_moves` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `item_id` int(10) unsigned NOT NULL,
  `qty` decimal(14,3) NOT NULL COMMENT 'boleh negatif (keluar/koreksi turun)',
  `move_type` enum('in','out','adjust_opname','requisition') NOT NULL DEFAULT 'in',
  `ref` varchar(60) DEFAULT NULL COMMENT 'mis. opname:3, request:7',
  `note` varchar(255) DEFAULT NULL,
  `by_user` int(10) unsigned DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_inv_moves_property_item` (`property_id`,`item_id`),
  KEY `idx_inv_moves_ref` (`property_id`,`ref`),
  KEY `fk_inv_moves_item` (`item_id`),
  KEY `fk_inv_moves_user` (`by_user`),
  CONSTRAINT `fk_inv_moves_item` FOREIGN KEY (`item_id`) REFERENCES `inv_items` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_inv_moves_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_inv_moves_user` FOREIGN KEY (`by_user`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `inv_stock_moves`
--

INSERT INTO `inv_stock_moves` VALUES (1,1,1,50.000,'in',NULL,'DUMMY — stok awal',1,'2026-07-09 16:13:38'),(2,1,2,80.000,'in',NULL,'DUMMY — stok awal',1,'2026-07-09 16:13:38'),(3,1,3,25.000,'in',NULL,'DUMMY — stok awal',1,'2026-07-09 16:13:38'),(4,1,4,30.000,'in',NULL,'DUMMY — stok awal',1,'2026-07-09 16:13:38'),(5,1,5,18.000,'in',NULL,'DUMMY — stok awal',1,'2026-07-09 16:13:38'),(6,1,6,22.000,'in',NULL,'DUMMY — stok awal',1,'2026-07-09 16:13:38'),(7,1,7,40.000,'in',NULL,'DUMMY — stok awal',1,'2026-07-09 16:13:38'),(8,1,8,250.000,'in',NULL,'DUMMY — stok awal',1,'2026-07-09 16:13:38'),(9,1,9,180.000,'in',NULL,'DUMMY — stok awal',1,'2026-07-09 16:13:38'),(10,1,10,260.000,'in',NULL,'DUMMY — stok awal',1,'2026-07-09 16:13:38'),(11,1,11,120.000,'in',NULL,'DUMMY — stok awal',1,'2026-07-09 16:13:38'),(12,1,12,45.000,'in',NULL,'DUMMY — stok awal',1,'2026-07-09 16:13:38'),(13,1,8,-50.000,'requisition','request:1','DUMMY — diserahkan ke HK',1,'2026-07-09 16:13:38'),(14,1,9,-40.000,'requisition','request:1','DUMMY — diserahkan ke HK',1,'2026-07-09 16:13:38'),(15,1,1,-2.000,'adjust_opname','opname:1','DUMMY — koreksi hasil opname',1,'2026-07-09 16:13:38');

--
-- Table structure for table `laundry_handover_items`
--

CREATE TABLE `laundry_handover_items` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `handover_id` int(10) unsigned NOT NULL,
  `item_type` varchar(60) NOT NULL COMMENT 'teks bebas, mis. Sprei/Handuk/Taplak/Seragam — bukan ENUM baku',
  `qty_sent` int(10) unsigned NOT NULL,
  `qty_returned` int(10) unsigned DEFAULT NULL COMMENT 'NULL = belum dicatat penerimaannya',
  `qty_damaged` int(10) unsigned NOT NULL DEFAULT 0,
  `qty_lost` int(10) unsigned NOT NULL DEFAULT 0,
  `claim_status` enum('tidak_ada','diajukan','disetujui','ditolak') NOT NULL DEFAULT 'tidak_ada',
  `claim_notes` text DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_laundry_items_handover` (`handover_id`),
  CONSTRAINT `fk_laundry_items_handover` FOREIGN KEY (`handover_id`) REFERENCES `laundry_handovers` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `laundry_handover_items`
--

INSERT INTO `laundry_handover_items` VALUES (1,1,'DUMMY — Sprei',40,40,0,0,'tidak_ada',NULL),(2,1,'DUMMY — Handuk Mandi',60,60,0,0,'tidak_ada',NULL),(4,2,'DUMMY — Seragam Housekeeping',20,20,3,0,'diajukan','DUMMY — 3 seragam robek/luntur, klaim diajukan ke vendor'),(5,2,'DUMMY — Handuk Mandi',30,27,0,3,'tidak_ada',NULL),(6,3,'DUMMY — Sprei',35,NULL,0,0,'tidak_ada',NULL),(7,3,'DUMMY — Sarung Bantal',70,NULL,0,0,'tidak_ada',NULL);

--
-- Table structure for table `laundry_handovers`
--

CREATE TABLE `laundry_handovers` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `vendor_id` int(10) unsigned NOT NULL,
  `sent_at` datetime NOT NULL,
  `expected_return_date` date DEFAULT NULL,
  `received_at` datetime DEFAULT NULL COMMENT 'diisi otomatis saat baris pertama dicatat diterima',
  `status` enum('dikirim','diterima_sebagian','selesai','ada_klaim') NOT NULL DEFAULT 'dikirim',
  `notes` text DEFAULT NULL,
  `created_by` int(10) unsigned DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_laundry_handovers_property_status` (`property_id`,`status`),
  KEY `idx_laundry_handovers_property_vendor` (`property_id`,`vendor_id`),
  KEY `fk_laundry_handovers_vendor` (`vendor_id`),
  KEY `fk_laundry_handovers_created_by` (`created_by`),
  CONSTRAINT `fk_laundry_handovers_created_by` FOREIGN KEY (`created_by`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_laundry_handovers_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_laundry_handovers_vendor` FOREIGN KEY (`vendor_id`) REFERENCES `vendors` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `laundry_handovers`
--

INSERT INTO `laundry_handovers` VALUES (1,1,1,'2026-07-04 16:46:28','2026-07-07','2026-07-07 16:46:28','selesai','DUMMY — laundry mingguan housekeeping, semua kembali utuh',1,'2026-07-09 16:46:28','2026-07-09 16:46:28'),(2,1,1,'2026-07-06 16:46:28','2026-07-08','2026-07-08 16:46:28','ada_klaim','DUMMY — ditemukan seragam rusak & handuk kurang saat diterima',1,'2026-07-09 16:46:28','2026-07-09 16:46:28'),(3,1,1,'2026-07-09 16:46:28','2026-07-12',NULL,'dikirim','DUMMY — pengiriman linen mingguan, menunggu vendor',1,'2026-07-09 16:46:28','2026-07-09 16:46:28');

--
-- Table structure for table `locations`
--

CREATE TABLE `locations` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `code` varchar(30) NOT NULL,
  `name` varchar(150) NOT NULL,
  `building` varchar(60) DEFAULT NULL,
  `wing` varchar(60) DEFAULT NULL,
  `floor` varchar(20) DEFAULT NULL,
  `type` enum('room','public_area','back_of_house','external') NOT NULL,
  `active` tinyint(1) NOT NULL DEFAULT 1,
  `oo_status` enum('ok','ooo','oos') NOT NULL DEFAULT 'ok',
  `oo_reason` varchar(255) DEFAULT NULL,
  `oo_since` datetime DEFAULT NULL,
  `oo_set_by` int(10) unsigned DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_locations_property_code` (`property_id`,`code`),
  KEY `idx_locations_property_type` (`property_id`,`type`),
  KEY `idx_locations_oo_status` (`property_id`,`oo_status`),
  KEY `fk_locations_oo_set_by` (`oo_set_by`),
  CONSTRAINT `fk_locations_oo_set_by` FOREIGN KEY (`oo_set_by`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_locations_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `locations`
--

INSERT INTO `locations` VALUES (1,1,'RM-1201','Kamar 1201','Main Tower','A','12','room',1,'ok',NULL,NULL,NULL,'2026-07-08 18:57:08','2026-07-08 23:19:07'),(2,1,'RM-1202','Kamar 1202','Main Tower','A','12','room',1,'ok',NULL,NULL,NULL,'2026-07-08 18:57:08','2026-07-08 18:57:08'),(3,1,'RM-1203','Kamar 1203','Main Tower','A','12','room',1,'ok',NULL,NULL,NULL,'2026-07-08 18:57:08','2026-07-08 18:57:08'),(4,1,'RM-0801','Kamar 0801','Main Tower','B','08','room',1,'ok',NULL,NULL,NULL,'2026-07-08 18:57:08','2026-07-08 18:57:08'),(5,1,'RM-0802','Kamar 0802','Main Tower','B','08','room',1,'ok',NULL,NULL,NULL,'2026-07-08 18:57:08','2026-07-08 18:57:08'),(6,1,'LOBBY','Lobby Utama','Main Tower',NULL,'GF','public_area',1,'ok',NULL,NULL,NULL,'2026-07-08 18:57:08','2026-07-08 18:57:08'),(7,1,'CORR-12','Koridor Lantai 12','Main Tower','A','12','public_area',1,'ok',NULL,NULL,NULL,'2026-07-08 18:57:08','2026-07-08 18:57:08'),(8,1,'POOL','Area Kolam Renang','Podium',NULL,'2','public_area',1,'ok',NULL,NULL,NULL,'2026-07-08 18:57:08','2026-07-08 18:57:08'),(9,1,'GYM','Gym / Fitness','Podium',NULL,'2','public_area',1,'ok',NULL,NULL,NULL,'2026-07-08 18:57:08','2026-07-08 18:57:08'),(10,1,'RESTO','Restoran Utama','Podium',NULL,'1','public_area',1,'ok',NULL,NULL,NULL,'2026-07-08 18:57:08','2026-07-08 18:57:08'),(11,1,'ENG-RM','Ruang Engineering','BOH',NULL,'B1','back_of_house',1,'ok',NULL,NULL,NULL,'2026-07-08 18:57:08','2026-07-08 18:57:08'),(12,1,'GENSET-RM','Ruang Genset','BOH',NULL,'B1','back_of_house',1,'ok',NULL,NULL,NULL,'2026-07-08 18:57:08','2026-07-08 18:57:08'),(13,1,'KITCHEN','Dapur Utama','BOH',NULL,'GF','back_of_house',1,'ok',NULL,NULL,NULL,'2026-07-08 18:57:08','2026-07-08 18:57:08'),(14,1,'LAUNDRY','Ruang Laundry','BOH',NULL,'B1','back_of_house',1,'ok',NULL,NULL,NULL,'2026-07-08 18:57:08','2026-07-08 18:57:08'),(15,1,'SERVER-RM','Ruang Server IT','BOH',NULL,'3','back_of_house',1,'ok',NULL,NULL,NULL,'2026-07-08 18:57:08','2026-07-08 18:57:08'),(16,1,'PARKIR-B1','Area Parkir Basement','BOH',NULL,'B1','external',1,'ok',NULL,NULL,NULL,'2026-07-08 18:57:08','2026-07-08 18:57:08'),(17,1,'ROOFTOP','Area Rooftop','Main Tower',NULL,'RF','external',1,'ok',NULL,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(18,1,'CORR-05','Koridor Lantai 5','Main Tower','A','05','public_area',1,'ok',NULL,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(19,1,'CORR-08','Koridor Lantai 8','Main Tower','B','08','public_area',1,'ok',NULL,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(20,1,'RM-0803','Kamar 0803','Main Tower','B','08','room',1,'ooo','Renovasi kamar mandi — DUMMY','2026-07-05 23:10:04',507,'2026-07-08 18:57:09','2026-07-08 23:10:04'),(21,1,'RM-0805','Kamar 0805','Main Tower','B','08','room',1,'ooo','Renovasi kamar mandi — DUMMY','2026-07-05 23:10:04',507,'2026-07-08 18:57:09','2026-07-08 23:10:04'),(22,1,'RM-1207','Kamar 1207','Main Tower','A','12','room',1,'ok',NULL,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(23,1,'RM-1501','Kamar 1501 (balkon)','Main Tower','A','15','room',1,'ok',NULL,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(24,1,'CORR-03','Koridor Lantai 3','Main Tower','A','03','public_area',1,'ok',NULL,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(25,1,'BASEMENT','Basement Parkir & Servis','Main Tower',NULL,'B1','back_of_house',1,'ok',NULL,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09');

--
-- Table structure for table `meter_readings`
--

CREATE TABLE `meter_readings` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `asset_id` int(10) unsigned NOT NULL,
  `value` decimal(14,2) NOT NULL,
  `read_at` datetime NOT NULL,
  `read_by` int(10) unsigned DEFAULT NULL,
  `source` enum('manual','wo') NOT NULL DEFAULT 'manual',
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_meter_readings_asset_read_at` (`asset_id`,`read_at`),
  KEY `fk_meter_readings_read_by` (`read_by`),
  CONSTRAINT `fk_meter_readings_asset` FOREIGN KEY (`asset_id`) REFERENCES `assets` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_meter_readings_read_by` FOREIGN KEY (`read_by`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `meter_readings`
--

INSERT INTO `meter_readings` VALUES (1,1,4700.00,'2026-06-03 18:57:09',4,'manual','2026-07-08 18:57:09'),(2,1,4726.00,'2026-06-10 18:57:09',4,'manual','2026-07-08 18:57:09'),(3,1,4752.50,'2026-06-17 18:57:09',4,'manual','2026-07-08 18:57:09'),(4,1,4779.00,'2026-06-24 18:57:09',4,'manual','2026-07-08 18:57:09'),(5,1,4805.00,'2026-07-01 18:57:09',4,'wo','2026-07-08 18:57:09'),(6,1,4830.50,'2026-07-07 18:57:09',4,'manual','2026-07-08 18:57:09'),(7,21,41200.00,'2026-03-10 18:57:09',4,'manual','2026-07-08 18:57:09'),(8,21,42600.00,'2026-04-09 18:57:09',4,'manual','2026-07-08 18:57:09'),(9,21,44100.00,'2026-05-09 18:57:09',4,'manual','2026-07-08 18:57:09'),(10,21,45500.00,'2026-06-08 18:57:09',4,'manual','2026-07-08 18:57:09'),(11,21,46850.00,'2026-07-07 18:57:09',4,'manual','2026-07-08 18:57:09');

--
-- Table structure for table `mkt_ai_chats`
--

CREATE TABLE `mkt_ai_chats` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `user_id` int(10) unsigned NOT NULL,
  `persona` enum('event_menu','keyword_campaign') NOT NULL,
  `title` varchar(200) DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_mkt_ai_chats_property_user` (`property_id`,`user_id`),
  KEY `fk_mkt_ai_chats_user` (`user_id`),
  CONSTRAINT `fk_mkt_ai_chats_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_mkt_ai_chats_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `mkt_ai_chats`
--

INSERT INTO `mkt_ai_chats` VALUES (1,1,520,'event_menu','Brainstorm ide sunset event Q3 (DUMMY demo)','2026-07-08 20:14:02','2026-07-08 20:14:02');

--
-- Table structure for table `mkt_ai_messages`
--

CREATE TABLE `mkt_ai_messages` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `chat_id` bigint(20) unsigned NOT NULL,
  `role` enum('system','user','assistant') NOT NULL,
  `content` mediumtext NOT NULL,
  `tokens_in` int(10) unsigned DEFAULT NULL,
  `tokens_out` int(10) unsigned DEFAULT NULL,
  `cost_idr` decimal(12,2) DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_mkt_ai_messages_chat` (`chat_id`,`created_at`),
  CONSTRAINT `fk_mkt_ai_messages_chat` FOREIGN KEY (`chat_id`) REFERENCES `mkt_ai_chats` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `mkt_ai_messages`
--

INSERT INTO `mkt_ai_messages` VALUES (1,1,'user','Kita butuh ide event romantic sunset untuk promo Q3, ada saran untuk Sanggraloka? (DUMMY demo)',NULL,NULL,NULL,'2026-07-08 20:14:02'),(2,1,'assistant','Beberapa ide: (1) Sunset Movie Night di Valley dengan picnic set, (2) Romantic dinner tepi kolam infinity, (3) Sesi foto golden hour di Butterfly Sanctuary (DUMMY demo, contoh jawaban AI).',180,96,420.00,'2026-07-08 20:14:02'),(3,1,'user','Menarik — tolong detailkan konsep venue dan menu ringan untuk opsi (1). (DUMMY demo)',NULL,NULL,NULL,'2026-07-08 20:14:02'),(4,1,'assistant','Venue: area rumput tepi valley dekat Sunken Pool Bar, layar portable + proyektor, alas piknik & bantal. Menu ringan: sharing platter hasil farm, mocktail Herbal Elixir, dessert buah organik (DUMMY demo, contoh jawaban AI).',210,130,540.00,'2026-07-08 20:14:02');

--
-- Table structure for table `mkt_bookings`
--

CREATE TABLE `mkt_bookings` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `product_id` int(10) unsigned NOT NULL,
  `event_date` date NOT NULL,
  `event_time` time DEFAULT NULL,
  `pax` int(10) unsigned DEFAULT NULL,
  `guest_name` varchar(160) NOT NULL,
  `source` enum('direct','partner','walk_in','web') NOT NULL DEFAULT 'direct',
  `partner_id` int(10) unsigned DEFAULT NULL,
  `status` enum('tentative','confirmed','executed','completed','cancelled','no_show') NOT NULL DEFAULT 'tentative',
  `value` decimal(14,2) NOT NULL DEFAULT 0.00,
  `deposit_paid` decimal(14,2) NOT NULL DEFAULT 0.00,
  `deposit_due_date` date DEFAULT NULL,
  `theme` varchar(160) DEFAULT NULL COMMENT 'wedding: tema',
  `vendor_notes` text DEFAULT NULL COMMENT 'wedding: vendor/rundown (BEO penuh = fase 2)',
  `rundown_file` varchar(255) DEFAULT NULL,
  `notes` text DEFAULT NULL,
  `pms_ref` varchar(60) DEFAULT NULL COMMENT 'batas tegas: HotelSell tidak pernah menulis reservasi kamar PMS',
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_mkt_bookings_property_date` (`property_id`,`event_date`),
  KEY `idx_mkt_bookings_property_status` (`property_id`,`status`),
  KEY `idx_mkt_bookings_product` (`product_id`),
  KEY `idx_mkt_bookings_partner` (`partner_id`),
  CONSTRAINT `fk_mkt_bookings_partner` FOREIGN KEY (`partner_id`) REFERENCES `mkt_partners` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_mkt_bookings_product` FOREIGN KEY (`product_id`) REFERENCES `mkt_products` (`id`) ON UPDATE CASCADE,
  CONSTRAINT `fk_mkt_bookings_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `mkt_bookings`
--

INSERT INTO `mkt_bookings` VALUES (1,1,22,'2026-08-17','16:00:00',120,'Demo Bride & Groom — Wedding A','direct',NULL,'tentative',250000000.00,50000000.00,'2026-07-18','Garden Romance (DUMMY tema)',NULL,NULL,'Nominal & tema DUMMY demo — bukan booking nyata.',NULL,'2026-07-08 19:08:46','2026-07-08 19:08:46'),(2,1,22,'2026-09-21','17:00:00',150,'Demo Bride & Groom — Wedding B','partner',3,'confirmed',320000000.00,100000000.00,'2026-07-28','Tropical Elegance (DUMMY tema)',NULL,NULL,'Nominal & tema DUMMY demo — bukan booking nyata.',NULL,'2026-07-08 19:08:46','2026-07-08 19:08:46'),(3,1,20,'2026-07-05','07:00:00',2,'Demo Guest — Honeymoon Couple','direct',NULL,'executed',2800000.00,2800000.00,NULL,NULL,NULL,NULL,'DUMMY demo, sudah terlaksana.',NULL,'2026-07-08 19:08:46','2026-07-08 19:08:46'),(4,1,4,'2026-07-02','10:00:00',4,'Demo Guest — Family Group','web',NULL,'executed',3200000.00,3200000.00,NULL,NULL,NULL,NULL,'DUMMY demo, sudah terlaksana.',NULL,'2026-07-08 19:08:46','2026-07-08 19:08:46'),(5,1,13,'2026-07-23','12:00:00',6,'Demo Guest — Corporate Outing (batal)','partner',1,'cancelled',4500000.00,500000.00,NULL,NULL,NULL,NULL,'Dibatalkan klien, deposit hangus sebagian (DUMMY skenario demo).',NULL,'2026-07-08 19:08:46','2026-07-08 19:08:46');

--
-- Table structure for table `mkt_contracts`
--

CREATE TABLE `mkt_contracts` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `partner_id` int(10) unsigned NOT NULL,
  `title` varchar(200) NOT NULL,
  `start_date` date NOT NULL,
  `end_date` date NOT NULL,
  `commission_pct` decimal(5,2) NOT NULL DEFAULT 0.00,
  `allotment` int(10) unsigned DEFAULT NULL,
  `file` varchar(255) DEFAULT NULL,
  `notes` text DEFAULT NULL,
  `status` enum('draft','active','expired','terminated') NOT NULL DEFAULT 'draft',
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_mkt_contracts_property_end` (`property_id`,`end_date`),
  KEY `idx_mkt_contracts_partner` (`partner_id`),
  CONSTRAINT `fk_mkt_contracts_partner` FOREIGN KEY (`partner_id`) REFERENCES `mkt_partners` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_mkt_contracts_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `mkt_contracts`
--

INSERT INTO `mkt_contracts` VALUES (1,1,1,'Kontrak Alokasi Kamar Contoh Travel Agent A (DUMMY demo)','2025-08-22','2026-08-22',12.00,5,NULL,'Berakhir 45 hari lagi -> memicu reminder H-60 (DUMMY demo, lihat hr_tasks id=6).','active','2026-07-08 19:08:46','2026-07-08 19:08:46'),(2,1,2,'Kontrak Kerjasama Contoh OTA B (DUMMY demo, aktif 1 tahun)','2026-07-08','2027-07-08',15.00,NULL,NULL,'Kontrak baru berjalan, belum masuk jendela reminder (DUMMY demo).','active','2026-07-08 19:08:46','2026-07-08 19:08:46');

--
-- Table structure for table `mkt_event_ideas`
--

CREATE TABLE `mkt_event_ideas` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `title` varchar(200) NOT NULL,
  `target_date` date DEFAULT NULL,
  `concept` text DEFAULT NULL,
  `status` enum('ide','disetujui_gm','dieksekusi','evaluasi') NOT NULL DEFAULT 'ide',
  `source_chat_id` bigint(20) unsigned DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_mkt_event_ideas_property_status` (`property_id`,`status`),
  KEY `idx_mkt_event_ideas_source_chat` (`source_chat_id`),
  CONSTRAINT `fk_mkt_event_ideas_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_mkt_event_ideas_source_chat` FOREIGN KEY (`source_chat_id`) REFERENCES `mkt_ai_chats` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `mkt_event_ideas`
--

INSERT INTO `mkt_event_ideas` VALUES (1,1,'Sunset Movie Night Valley (DUMMY demo)','2026-08-22','Nonton film outdoor tepi valley dgn picnic set, tema romantic, dari brainstorm Studio AI (DUMMY demo).','ide',1,'2026-07-08 20:14:02','2026-07-08 20:14:02'),(2,1,'Family Fun Day Farm (DUMMY demo)','2026-09-16','Aktivitas keluarga di farm organik: panen mini, feeding time, cooking class anak (DUMMY demo).','disetujui_gm',NULL,'2026-07-08 20:14:02','2026-07-08 20:14:02'),(3,1,'Chef Table Preview Meditera (DUMMY demo)','2026-10-16','Preview menu degustasi baru Meditera Restaurant, tamu undangan terbatas (DUMMY demo).','ide',NULL,'2026-07-08 20:14:02','2026-07-08 20:14:02');

--
-- Table structure for table `mkt_generated_content`
--

CREATE TABLE `mkt_generated_content` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `type` enum('blog','gads','ig') NOT NULL,
  `month` char(7) NOT NULL COMMENT 'YYYY-MM',
  `content` mediumtext DEFAULT NULL,
  `status` enum('draft','direview','disetujui','dipublikasikan') NOT NULL DEFAULT 'draft',
  `reviewer_id` int(10) unsigned DEFAULT NULL,
  `notes` varchar(500) DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_mkt_generated_content_property_month` (`property_id`,`month`,`type`),
  KEY `idx_mkt_generated_content_status` (`property_id`,`status`),
  KEY `idx_mkt_generated_content_reviewer` (`reviewer_id`),
  CONSTRAINT `fk_mkt_generated_content_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_mkt_generated_content_reviewer` FOREIGN KEY (`reviewer_id`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `mkt_generated_content`
--

INSERT INTO `mkt_generated_content` VALUES (1,1,'blog','2026-07','Draft artikel blog: \"5 Alasan Sanggraloka Ubud Cocok untuk Family Retreat\" (DUMMY demo, draft AI belum direview).','draft',NULL,NULL,'2026-07-08 20:14:02','2026-07-08 20:14:02'),(2,1,'gads','2026-07','Draft RSA Google Ads: headline & deskripsi kampanye eco-luxury Ubud (DUMMY demo).','direview',562,NULL,'2026-07-08 20:14:02','2026-07-08 20:14:02'),(3,1,'ig','2026-07','12 ide caption Instagram bulan ini (DUMMY demo).','dipublikasikan',562,'Disetujui & dipublikasikan tim design (DUMMY demo).','2026-07-08 20:14:02','2026-07-08 20:14:02');

--
-- Table structure for table `mkt_keywords`
--

CREATE TABLE `mkt_keywords` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `keyword` varchar(200) NOT NULL,
  `cluster` varchar(100) DEFAULT NULL,
  `market` enum('EN','FR','KR','ID') NOT NULL DEFAULT 'EN',
  `intent` enum('informational','navigational','transactional') DEFAULT NULL,
  `target_page` varchar(255) DEFAULT NULL,
  `last_position` smallint(5) unsigned DEFAULT NULL,
  `checked_at` date DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_mkt_keywords_property_market` (`property_id`,`market`),
  KEY `idx_mkt_keywords_cluster` (`cluster`),
  CONSTRAINT `fk_mkt_keywords_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `mkt_keywords`
--

INSERT INTO `mkt_keywords` VALUES (1,1,'eco luxury resort ubud','eco-luxury-ubud','EN','navigational','/',8,'2026-07-03','2026-07-08 20:14:02','2026-07-08 20:14:02'),(2,1,'farm to table dining bali','farm-dining','EN','informational','/meditera-restaurant',NULL,NULL,'2026-07-08 20:14:02','2026-07-08 20:14:02'),(3,1,'hotel luxe bali foret','luxe-bali-fr','FR','informational','/',NULL,NULL,'2026-07-08 20:14:02','2026-07-08 20:14:02'),(4,1,'resort bio bali romantique','bio-romantique-fr','FR','navigational','/',14,'2026-07-03','2026-07-08 20:14:02','2026-07-08 20:14:02'),(5,1,'발리 럭셔리 리조트','bali-luxury-kr','KR','navigational','/',11,'2026-07-03','2026-07-08 20:14:02','2026-07-08 20:14:02'),(6,1,'발리 신혼여행 호텔','honeymoon-kr','KR','transactional','/book',NULL,NULL,'2026-07-08 20:14:02','2026-07-08 20:14:02'),(7,1,'resort organik ubud','resort-organik-ubud','ID','navigational','/',6,'2026-07-03','2026-07-08 20:14:02','2026-07-08 20:14:02'),(8,1,'villa kolam pribadi ubud','villa-private-pool-ubud','ID','transactional','/book',9,'2026-07-03','2026-07-08 20:14:02','2026-07-08 20:14:02');

--
-- Table structure for table `mkt_kol_docs`
--

CREATE TABLE `mkt_kol_docs` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `kol_id` int(10) unsigned NOT NULL,
  `visit_id` int(10) unsigned DEFAULT NULL,
  `type` enum('kontrak','photo_release','lainnya') NOT NULL,
  `file` varchar(255) NOT NULL,
  `uploaded_by` int(10) unsigned DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_mkt_kol_docs_kol` (`kol_id`),
  KEY `idx_mkt_kol_docs_visit` (`visit_id`),
  KEY `fk_mkt_kol_docs_uploaded_by` (`uploaded_by`),
  CONSTRAINT `fk_mkt_kol_docs_kol` FOREIGN KEY (`kol_id`) REFERENCES `mkt_kols` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_mkt_kol_docs_uploaded_by` FOREIGN KEY (`uploaded_by`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_mkt_kol_docs_visit` FOREIGN KEY (`visit_id`) REFERENCES `mkt_kol_visits` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `mkt_kol_docs`
--

INSERT INTO `mkt_kol_docs` VALUES (1,1,1,'kontrak','kol_docs/demo_kontrak_kol1.pdf',521,'2026-07-08 19:08:46'),(2,2,2,'kontrak','kol_docs/demo_kontrak_kol2.pdf',582,'2026-07-08 19:08:46'),(3,2,2,'photo_release','kol_docs/demo_photo_release_kol2.pdf',582,'2026-07-08 19:08:46');

--
-- Table structure for table `mkt_kol_results`
--

CREATE TABLE `mkt_kol_results` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `kol_id` int(10) unsigned NOT NULL,
  `visit_id` int(10) unsigned DEFAULT NULL,
  `content_link` varchar(255) DEFAULT NULL,
  `reach` bigint(20) unsigned DEFAULT NULL,
  `promo_code` varchar(40) DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_mkt_kol_results_kol` (`kol_id`),
  KEY `idx_mkt_kol_results_visit` (`visit_id`),
  CONSTRAINT `fk_mkt_kol_results_kol` FOREIGN KEY (`kol_id`) REFERENCES `mkt_kols` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_mkt_kol_results_visit` FOREIGN KEY (`visit_id`) REFERENCES `mkt_kol_visits` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `mkt_kol_results`
--

INSERT INTO `mkt_kol_results` VALUES (1,2,2,'https://youtube.com/demo-kol-en-sanggraloka (DUMMY link)',125000,'DEMOKOLEN10','2026-07-08 19:08:46'),(2,1,NULL,'https://instagram.com/p/demo-kol-id-sanggraloka (DUMMY link)',48000,'DEMOKOLID15','2026-07-08 20:14:02');

--
-- Table structure for table `mkt_kol_visits`
--

CREATE TABLE `mkt_kol_visits` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `kol_id` int(10) unsigned NOT NULL,
  `arrival_date` date NOT NULL,
  `departure_date` date NOT NULL,
  `program` text DEFAULT NULL COMMENT 'program/deliverable yang disepakati',
  `status` enum('dijadwalkan','berlangsung','selesai','batal') NOT NULL DEFAULT 'dijadwalkan',
  `room` varchar(20) DEFAULT NULL,
  `host_user_id` int(10) unsigned DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_mkt_kol_visits_property_arrival` (`property_id`,`arrival_date`),
  KEY `idx_mkt_kol_visits_kol` (`kol_id`),
  KEY `idx_mkt_kol_visits_host` (`host_user_id`),
  CONSTRAINT `fk_mkt_kol_visits_host` FOREIGN KEY (`host_user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_mkt_kol_visits_kol` FOREIGN KEY (`kol_id`) REFERENCES `mkt_kols` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_mkt_kol_visits_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `mkt_kol_visits`
--

INSERT INTO `mkt_kol_visits` VALUES (1,1,1,'2026-07-18','2026-07-20','2 malam stay + konten Butterfly Sanctuary & Valley Floating Brunch (DUMMY demo).','dijadwalkan',NULL,521,'2026-07-08 19:08:46','2026-07-08 19:08:46'),(2,1,2,'2026-06-18','2026-06-21','3 malam stay + konten Nirvanaloka Spa & Farm Taster (DUMMY demo).','selesai',NULL,582,'2026-07-08 19:08:46','2026-07-08 19:08:46');

--
-- Table structure for table `mkt_kols`
--

CREATE TABLE `mkt_kols` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `name` varchar(160) NOT NULL,
  `platform` varchar(60) DEFAULT NULL COMMENT 'Instagram/TikTok/YouTube dst',
  `niche` varchar(100) DEFAULT NULL,
  `market` varchar(60) DEFAULT NULL COMMENT 'ID/EN/FR/KR dst',
  `tier` enum('nano','micro','mid','macro','mega') DEFAULT NULL,
  `relationship_status` enum('belum_dihubungi','dihubungi','nego','deal','delivered','evaluasi','ditolak') NOT NULL DEFAULT 'belum_dihubungi' COMMENT '⬜→?→?→✅→?→⭐/❌ KOL-DATABASE.xlsx',
  `pic_user_id` int(10) unsigned DEFAULT NULL COMMENT 'penanggung jawab (sales/EWM) ÔÇö NULL = belum di-assign',
  `rate_card` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT 'per format, HANYA dari penawaran tertulis' CHECK (json_valid(`rate_card`)),
  `contact` varchar(160) DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_mkt_kols_property_status` (`property_id`,`relationship_status`),
  KEY `idx_mkt_kols_pic` (`property_id`,`pic_user_id`),
  KEY `fk_mkt_kols_pic` (`pic_user_id`),
  CONSTRAINT `fk_mkt_kols_pic` FOREIGN KEY (`pic_user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL,
  CONSTRAINT `fk_mkt_kols_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `mkt_kols`
--

INSERT INTO `mkt_kols` VALUES (1,1,'Demo KOL Traveler ID','Instagram','Travel & Lifestyle (DUMMY)','ID','micro','deal',NULL,'{\"reel\": 5000000, \"story\": 1500000}','demo.kol.id@example.com','2026-07-08 19:08:46','2026-07-09 17:13:04'),(2,1,'Demo KOL Traveler EN','YouTube','Wellness & Travel (DUMMY)','EN','mid','delivered',NULL,'{\"video\": 15000000}','demo.kol.en@example.com','2026-07-08 19:08:46','2026-07-08 19:08:46');

--
-- Table structure for table `mkt_menus`
--

CREATE TABLE `mkt_menus` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `name` varchar(160) NOT NULL,
  `outlet` varchar(100) DEFAULT NULL COMMENT 'Meditera Restaurant/Bar/Segening/Sunken Pool Bar',
  `items` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`items`)),
  `proposed_price` decimal(14,2) DEFAULT NULL,
  `status` enum('draft','disetujui_gm','aktif','arsip') NOT NULL DEFAULT 'draft',
  `source_chat_id` bigint(20) unsigned DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_mkt_menus_property_status` (`property_id`,`status`),
  KEY `idx_mkt_menus_source_chat` (`source_chat_id`),
  CONSTRAINT `fk_mkt_menus_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_mkt_menus_source_chat` FOREIGN KEY (`source_chat_id`) REFERENCES `mkt_ai_chats` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `mkt_menus`
--

INSERT INTO `mkt_menus` VALUES (1,1,'Meditera Harvest Tasting Menu (DUMMY demo)','Meditera Restaurant','[\"Amuse bouche hasil kebun organik\", \"Ikan bakar bumbu Mediterania\", \"Dessert buah farm\"]',850000.00,'draft',1,'2026-07-08 20:14:02','2026-07-08 20:14:02'),(2,1,'Sunken Pool Bar Mocktail Set (DUMMY demo)','Sunken Pool Bar','[\"Butterfly Pea Fizz\", \"Herbal Elixir Cooler\"]',95000.00,'disetujui_gm',NULL,'2026-07-08 20:14:02','2026-07-08 20:14:02');

--
-- Table structure for table `mkt_otb_snapshots`
--

CREATE TABLE `mkt_otb_snapshots` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `report_year` smallint(5) unsigned NOT NULL,
  `report_date` date NOT NULL,
  `filename` varchar(255) NOT NULL,
  `rows_total` int(10) unsigned NOT NULL DEFAULT 0,
  `rows_new` int(10) unsigned NOT NULL DEFAULT 0,
  `rows_changed` int(10) unsigned NOT NULL DEFAULT 0,
  `rows_cancelled` int(10) unsigned NOT NULL DEFAULT 0,
  `otb_json` mediumtext DEFAULT NULL COMMENT 'snapshot OTB per bulan utk pickup/forecast',
  `uploaded_by` int(10) unsigned DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_mkt_otb_snapshots_property_year_date` (`property_id`,`report_year`,`report_date`),
  KEY `idx_mkt_otb_snapshots_uploaded_by` (`uploaded_by`),
  CONSTRAINT `fk_mkt_otb_snapshots_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_mkt_otb_snapshots_uploaded_by` FOREIGN KEY (`uploaded_by`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `mkt_otb_snapshots`
--

INSERT INTO `mkt_otb_snapshots` VALUES (1,1,2026,'2026-07-01','reservations_2026_snapshot_lama-demo.xlsx (DUMMY)',24,24,0,2,'{\"2026-07\":{\"n\":4,\"rn\":12,\"rev\":64042000},\"2026-08\":{\"n\":3,\"rn\":10,\"rev\":67650000},\"2026-09\":{\"n\":4,\"rn\":20,\"rev\":104960000},\"2026-10\":{\"n\":3,\"rn\":7,\"rev\":45018000},\"2026-11\":{\"n\":3,\"rn\":16,\"rev\":76014000},\"2026-12\":{\"n\":4,\"rn\":15,\"rev\":64534000}}',562,'2026-07-08 20:14:02'),(2,1,2026,'2026-07-08','reservations_2026_snapshot_terkini-demo.xlsx (DUMMY)',30,6,3,3,'{\"2026-07\":{\"n\":5,\"rn\":14,\"rev\":78100000},\"2026-08\":{\"n\":4,\"rn\":12,\"rev\":82500000},\"2026-09\":{\"n\":5,\"rn\":22,\"rev\":128000000},\"2026-10\":{\"n\":4,\"rn\":9,\"rev\":54900000},\"2026-11\":{\"n\":4,\"rn\":18,\"rev\":92700000},\"2026-12\":{\"n\":5,\"rn\":17,\"rev\":78700000}}',562,'2026-07-08 20:14:02');

--
-- Table structure for table `mkt_partners`
--

CREATE TABLE `mkt_partners` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `name` varchar(160) NOT NULL,
  `pms_name` varchar(160) DEFAULT NULL COMMENT 'nama persis di report PMS utk auto-match reservasi',
  `type` enum('travel_agent','ota','wholesaler','corporate','community','local') NOT NULL DEFAULT 'travel_agent',
  `pic_name` varchar(120) DEFAULT NULL,
  `contact_person` varchar(120) DEFAULT NULL,
  `phone` varchar(60) DEFAULT NULL,
  `email` varchar(160) DEFAULT NULL,
  `notes` text DEFAULT NULL,
  `source` enum('manual','pms_auto') NOT NULL DEFAULT 'manual',
  `active` tinyint(1) NOT NULL DEFAULT 1,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_mkt_partners_property_pms_name` (`property_id`,`pms_name`),
  KEY `idx_mkt_partners_property_type` (`property_id`,`type`),
  CONSTRAINT `fk_mkt_partners_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `mkt_partners`
--

INSERT INTO `mkt_partners` VALUES (1,1,'Contoh Travel Agent A','CONTOH TRAVEL AGENT A','travel_agent','Contoh PIC A','Contoh Kontak A','+62800000001','contoh.a@example.com','Data contoh generik utk seed — bukan mitra nyata, diganti tim S&M.','manual',1,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(2,1,'Contoh Online Travel Agent B','CONTOH OTA B','ota','Contoh PIC B','Contoh Kontak B','+62800000002','contoh.b@example.com','Data contoh generik utk seed — bukan mitra nyata, diganti tim S&M.','manual',1,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(3,1,'Contoh Wedding Organizer C','CONTOH WO C','wholesaler','Contoh PIC C','Contoh Kontak C','+62800000003','contoh.c@example.com','Data contoh generik utk seed — bukan mitra nyata, diganti tim S&M.','manual',1,'2026-07-08 18:57:12','2026-07-08 18:57:12');

--
-- Table structure for table `mkt_payments`
--

CREATE TABLE `mkt_payments` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `booking_id` bigint(20) unsigned NOT NULL,
  `paid_date` date NOT NULL,
  `amount` decimal(14,2) NOT NULL,
  `proof_file` varchar(255) DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_mkt_payments_booking` (`booking_id`),
  CONSTRAINT `fk_mkt_payments_booking` FOREIGN KEY (`booking_id`) REFERENCES `mkt_bookings` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `mkt_payments`
--

INSERT INTO `mkt_payments` VALUES (1,1,'2026-06-28',50000000.00,'payments/demo_wedding_a_dp1.jpg','2026-07-08 19:08:46'),(2,2,'2026-07-03',100000000.00,'payments/demo_wedding_b_dp1.jpg','2026-07-08 19:08:46'),(3,3,'2026-07-05',2800000.00,'payments/demo_valley_brunch.jpg','2026-07-08 19:08:46'),(4,4,'2026-07-02',3200000.00,'payments/demo_cooking_class.jpg','2026-07-08 19:08:46'),(5,5,'2026-06-18',500000.00,'payments/demo_corporate_outing_dp.jpg','2026-07-08 19:08:46');

--
-- Table structure for table `mkt_products`
--

CREATE TABLE `mkt_products` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `code` varchar(40) NOT NULL,
  `name` varchar(160) NOT NULL,
  `category` enum('wedding','experience','daypass','retreat','mice') NOT NULL,
  `public_price` decimal(14,2) DEFAULT NULL COMMENT 'NULL = diisi S&M, jangan dikarang',
  `partner_price` decimal(14,2) DEFAULT NULL,
  `capacity` int(10) unsigned DEFAULT NULL,
  `venue` varchar(120) DEFAULT NULL,
  `active` tinyint(1) NOT NULL DEFAULT 1,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_mkt_products_property_code` (`property_id`,`code`),
  KEY `idx_mkt_products_property_category` (`property_id`,`category`),
  CONSTRAINT `fk_mkt_products_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `mkt_products`
--

INSERT INTO `mkt_products` VALUES (1,1,'EXP-ANYAMAN-SARI','Anyaman Sari','experience',NULL,NULL,NULL,NULL,1,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(2,1,'EXP-ART-EARTH','Art & Earth Experience','experience',NULL,NULL,NULL,NULL,1,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(3,1,'EXP-BUTTERFLY','Butterfly Sanctuary','experience',NULL,NULL,NULL,'Butterfly Sanctuary',1,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(4,1,'EXP-COOKING-CLASS','Cooking Class','experience',NULL,NULL,NULL,NULL,1,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(5,1,'EXP-ELEVATOR-ECO','Elevator & Ecosystem','experience',NULL,NULL,NULL,NULL,1,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(6,1,'EXP-FARM-TASTER','Farm Taster','experience',NULL,NULL,NULL,'Farm organik on-site',1,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(7,1,'EXP-GOWES-SAWAH','Gowes Sawah Bali','experience',NULL,NULL,NULL,NULL,1,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(8,1,'EXP-HERBAL-ELIXIR','Herbal Elixir','experience',NULL,NULL,NULL,NULL,1,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(9,1,'EXP-MAKING-CANANG','Making Canang','experience',NULL,NULL,NULL,NULL,1,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(10,1,'EXP-ORGANIC-FRUITS','Organic Fruits','experience',NULL,NULL,NULL,'Farm organik on-site',1,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(11,1,'EXP-ORGANIC-HERBS','Organic Herbs','experience',NULL,NULL,NULL,'Farm organik on-site',1,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(12,1,'EXP-ORGANIC-VEGETABLES','Organic Vegetables','experience',NULL,NULL,NULL,'Farm organik on-site',1,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(13,1,'EXP-PICNIC-LUNCH','Picnic Lunch','experience',NULL,NULL,NULL,NULL,1,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(14,1,'EXP-PREWEDDING-SPOT','Pre-Wedding Spot','experience',NULL,NULL,NULL,NULL,1,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(15,1,'EXP-PURIFICATION','Purification (melukat)','experience',NULL,NULL,NULL,NULL,1,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(16,1,'EXP-RICE-PADDIES','Rice Paddies','experience',NULL,NULL,NULL,NULL,1,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(17,1,'EXP-RIVER-HOLY-WATER','River & Holy Water','experience',NULL,NULL,NULL,NULL,1,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(18,1,'EXP-RUPA-SARI','Rupa Sari','experience',NULL,NULL,NULL,NULL,1,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(19,1,'EXP-SPIRIT-WALK','Spirit Walk','experience',NULL,NULL,NULL,NULL,1,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(20,1,'EXP-VALLEY-FLOATING','Valley Floating Brunch','experience',NULL,NULL,NULL,NULL,1,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(21,1,'EXP-VALLEY-HIGH-TEA','Valley High Tea','experience',NULL,NULL,NULL,NULL,1,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(22,1,'WED-ANANDAM','Wedding Anandam Chapel','wedding',NULL,NULL,NULL,'Anandam Wedding Chapel',1,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(23,1,'MICE-MEDITERA','MICE/Private Dining Meditera','mice',NULL,NULL,NULL,'Meditera Restaurant',1,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(24,1,'EXP-YOGA-SHALA','Yoga Shala Session','experience',NULL,NULL,NULL,'Yoga Shala',1,'2026-07-08 18:57:12','2026-07-08 18:57:12');

--
-- Table structure for table `mkt_quotations`
--

CREATE TABLE `mkt_quotations` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `quote_no` varchar(30) NOT NULL,
  `partner_id` int(10) unsigned DEFAULT NULL,
  `client` varchar(160) NOT NULL DEFAULT '',
  `product_id` int(10) unsigned DEFAULT NULL,
  `value` decimal(15,2) NOT NULL DEFAULT 0.00,
  `sent_date` date NOT NULL,
  `valid_until` date DEFAULT NULL COMMENT 'default H+30 (EXPIRED otomatis lewat tanggal ini)',
  `status` enum('draft','sent','follow_up','nego','won','lost','expired') NOT NULL DEFAULT 'draft',
  `last_status_change` datetime NOT NULL DEFAULT current_timestamp() COMMENT 'dasar aturan reminder 3/5/7 hari',
  `lost_reason` enum('harga','tanggal_penuh','kompetitor','lainnya') DEFAULT NULL,
  `lost_reason_detail` varchar(255) DEFAULT NULL COMMENT 'nama kompetitor (Key set) atau catatan bebas',
  `pic_user_id` int(10) unsigned DEFAULT NULL,
  `proposal_file` varchar(255) DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_mkt_quotations_property_quote_no` (`property_id`,`quote_no`),
  KEY `idx_mkt_quotations_property_status` (`property_id`,`status`,`last_status_change`),
  KEY `idx_mkt_quotations_partner` (`partner_id`),
  KEY `idx_mkt_quotations_product` (`product_id`),
  KEY `idx_mkt_quotations_pic` (`pic_user_id`),
  CONSTRAINT `fk_mkt_quotations_partner` FOREIGN KEY (`partner_id`) REFERENCES `mkt_partners` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_mkt_quotations_pic` FOREIGN KEY (`pic_user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_mkt_quotations_product` FOREIGN KEY (`product_id`) REFERENCES `mkt_products` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_mkt_quotations_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `mkt_quotations`
--

INSERT INTO `mkt_quotations` VALUES (1,1,'QT-2026-D001',NULL,'Demo Corporate Client — PT Demo Sejahtera',23,15000000.00,'2026-07-08','2026-08-07','sent','2026-07-08 19:08:46',NULL,NULL,520,NULL,'2026-07-08 19:08:46','2026-07-08 19:08:46'),(2,1,'QT-2026-D002',NULL,'Demo Corporate Client — PT Demo Sejahtera Grup',16,8000000.00,'2026-07-02','2026-08-01','follow_up','2026-07-04 19:08:46',NULL,NULL,521,NULL,'2026-07-08 19:08:46','2026-07-09 17:13:04'),(3,1,'QT-2026-D003',3,'Demo Wedding Client — Keluarga Demo C',22,280000000.00,'2026-06-26','2026-07-26','nego','2026-06-30 19:08:46',NULL,NULL,562,NULL,'2026-07-08 19:08:46','2026-07-09 17:13:04'),(4,1,'QT-2026-D004',NULL,'Demo Corporate Client — PT Demo Nusantara',13,6000000.00,'2026-06-28','2026-07-28','won','2026-07-06 19:08:46',NULL,NULL,520,NULL,'2026-07-08 19:08:46','2026-07-08 19:08:46'),(5,1,'QT-2026-D005',2,'Demo OTA Group Booking — Contoh OTA B',24,4000000.00,'2026-06-29','2026-07-29','lost','2026-07-02 19:08:46','kompetitor','Four Seasons Sayan (Key set contoh, referensi sanggraloka.md §10, DUMMY demo)',521,NULL,'2026-07-08 19:08:46','2026-07-08 19:08:46'),(6,1,'QT-2026-D006',NULL,'Demo Corporate Client — PT Demo Abadi',6,5000000.00,'2026-06-03','2026-07-03','expired','2026-07-03 19:08:46',NULL,NULL,582,NULL,'2026-07-08 19:08:46','2026-07-08 19:08:46');

--
-- Table structure for table `mkt_quote_log`
--

CREATE TABLE `mkt_quote_log` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `quotation_id` int(10) unsigned NOT NULL,
  `from_status` varchar(20) DEFAULT NULL,
  `to_status` varchar(20) NOT NULL,
  `note` varchar(500) DEFAULT NULL COMMENT 'catatan singkat wajib saat pindah kartu kanban',
  `changed_by` int(10) unsigned DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_mkt_quote_log_quotation` (`quotation_id`,`created_at`),
  KEY `idx_mkt_quote_log_changed_by` (`changed_by`),
  CONSTRAINT `fk_mkt_quote_log_changed_by` FOREIGN KEY (`changed_by`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_mkt_quote_log_quotation` FOREIGN KEY (`quotation_id`) REFERENCES `mkt_quotations` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `mkt_quote_log`
--

INSERT INTO `mkt_quote_log` VALUES (1,1,NULL,'sent','Penawaran dikirim ke klien (DUMMY demo).',520,'2026-07-08 19:08:46'),(2,2,'sent','follow_up','Follow-up H+3 belum ada respon, lanjut ke follow_up (DUMMY demo).',521,'2026-07-04 19:08:46'),(3,3,'follow_up','nego','Klien nego harga venue wedding (DUMMY demo).',562,'2026-06-30 19:08:46'),(4,4,'nego','won','Deal, PO diterima klien (DUMMY demo).',520,'2026-07-06 19:08:46'),(5,5,'nego','lost','Klien memilih kompetitor Key set (DUMMY demo).',521,'2026-07-02 19:08:46'),(6,6,'sent','expired','Lewat valid_until tanpa keputusan klien, auto-expired (DUMMY demo).',NULL,'2026-07-03 19:08:46');

--
-- Table structure for table `mkt_reservations`
--

CREATE TABLE `mkt_reservations` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `report_year` smallint(5) unsigned NOT NULL,
  `resv_no` varchar(60) NOT NULL,
  `guest_name` varchar(160) NOT NULL DEFAULT '',
  `partner_id` int(10) unsigned DEFAULT NULL,
  `agent_raw` varchar(160) NOT NULL DEFAULT '' COMMENT 'nama mitra persis di report PMS sebelum di-match',
  `arrival` date NOT NULL,
  `departure` date DEFAULT NULL,
  `nights` decimal(6,1) NOT NULL DEFAULT 0.0,
  `room_type` varchar(80) NOT NULL DEFAULT '',
  `pax` decimal(5,1) NOT NULL DEFAULT 0.0,
  `status_raw` varchar(60) NOT NULL DEFAULT '',
  `cancelled` tinyint(1) NOT NULL DEFAULT 0,
  `rate` decimal(15,2) NOT NULL DEFAULT 0.00,
  `revenue` decimal(15,2) NOT NULL DEFAULT 0.00,
  `segment` varchar(80) NOT NULL DEFAULT '',
  `created_pms` date DEFAULT NULL,
  `first_seen` date NOT NULL,
  `last_seen` date NOT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_mkt_reservations_property_year_resv` (`property_id`,`report_year`,`resv_no`),
  KEY `idx_mkt_reservations_property_arrival` (`property_id`,`report_year`,`arrival`),
  KEY `idx_mkt_reservations_partner` (`partner_id`,`report_year`),
  CONSTRAINT `fk_mkt_reservations_partner` FOREIGN KEY (`partner_id`) REFERENCES `mkt_partners` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_mkt_reservations_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `mkt_reservations`
--

INSERT INTO `mkt_reservations` VALUES (1,1,2026,'RSV-2026-0001','Demo Guest - Kim Household 1',NULL,'','2026-07-08','2026-07-10',2.0,'Premiere Suite',3.0,'Confirmed',0,7700000.00,15400000.00,'Direct','2026-06-17','2026-06-17','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(2,1,2026,'RSV-2026-0002','Demo Guest - Park Wedding Party 2',NULL,'','2026-07-15','2026-07-17',2.0,'Deluxe Private Pool Villa',4.0,'Confirmed',0,6800000.00,13600000.00,'Travel Agent','2026-06-23','2026-06-23','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(3,1,2026,'RSV-2026-0003','Demo Guest - Martin Honeymoon 3',1,'','2026-07-22','2026-07-25',3.0,'Premiere Private Pool Villa',2.0,'Confirmed',0,5900000.00,17700000.00,'Corporate','2026-06-29','2026-06-29','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(4,1,2026,'RSV-2026-0004','Demo Guest - Lee Corporate Group 4',NULL,'','2026-07-02','2026-07-05',3.0,'One-Bedroom Presidential Pool Villa',3.0,'Confirmed',0,5000000.00,15000000.00,'Wholesaler','2026-06-08','2026-06-08','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(5,1,2026,'RSV-2026-0005','Demo Guest - Fontaine Couple 5',NULL,'','2026-07-09','2026-07-13',4.0,'Two-Bedroom Presidential Pool Villa',4.0,'Confirmed',0,4100000.00,16400000.00,'OTA','2026-06-14','2026-06-14','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(6,1,2026,'RSV-2026-0006','Demo Guest - Choi Retreat 6',2,'','2026-08-16','2026-08-21',5.0,'Deluxe Suite',2.0,'Cancelled',1,3200000.00,0.00,'Direct','2026-07-21','2026-07-21','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(7,1,2026,'RSV-2026-0007','Demo Guest - Laurent Family 7',NULL,'','2026-08-23','2026-08-30',7.0,'Premiere Suite',3.0,'Tentative',0,7700000.00,53900000.00,'Travel Agent','2026-07-27','2026-07-27','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(8,1,2026,'RSV-2026-0008','Demo Guest - Han Business Trip 8',NULL,'','2026-08-03','2026-08-04',1.0,'Deluxe Private Pool Villa',4.0,'Tentative',0,6800000.00,6800000.00,'Corporate','2026-07-06','2026-07-06','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(9,1,2026,'RSV-2026-0009','Demo Guest - Bernard Anniversary 9',3,'','2026-08-10','2026-08-12',2.0,'Premiere Private Pool Villa',2.0,'Tentative',0,5900000.00,11800000.00,'Wholesaler','2026-07-12','2026-07-12','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(10,1,2026,'RSV-2026-0010','Demo Guest - Yoon Solo Traveler 10',NULL,'','2026-08-17','2026-08-19',2.0,'One-Bedroom Presidential Pool Villa',3.0,'Tentative',0,5000000.00,10000000.00,'OTA','2026-07-18','2026-07-18','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(11,1,2026,'RSV-2026-0011','Demo Guest - Moreau Group 11',NULL,'','2026-09-24','2026-09-27',3.0,'Two-Bedroom Presidential Pool Villa',4.0,'Tentative',0,4100000.00,12300000.00,'Direct','2026-08-24','2026-08-24','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(12,1,2026,'RSV-2026-0012','Demo Guest - Dubois Family 12',1,'','2026-09-04','2026-09-07',3.0,'Deluxe Suite',2.0,'Tentative',0,3200000.00,9600000.00,'Travel Agent','2026-08-03','2026-08-03','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(13,1,2026,'RSV-2026-0013','Demo Guest - Kim Household 13',NULL,'','2026-09-11','2026-09-15',4.0,'Premiere Suite',3.0,'Tentative',0,7700000.00,30800000.00,'Corporate','2026-08-09','2026-08-09','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(14,1,2026,'RSV-2026-0014','Demo Guest - Park Wedding Party 14',NULL,'','2026-09-18','2026-09-23',5.0,'Deluxe Private Pool Villa',4.0,'Tentative',0,6800000.00,34000000.00,'Wholesaler','2026-08-15','2026-08-15','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(15,1,2026,'RSV-2026-0015','Demo Guest - Martin Honeymoon 15',2,'','2026-09-25','2026-10-02',7.0,'Premiere Private Pool Villa',2.0,'Tentative',0,5900000.00,41300000.00,'OTA','2026-08-21','2026-08-21','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(16,1,2026,'RSV-2026-0016','Demo Guest - Lee Corporate Group 16',NULL,'','2026-10-05','2026-10-06',1.0,'One-Bedroom Presidential Pool Villa',3.0,'Tentative',0,5000000.00,5000000.00,'Direct','2026-08-30','2026-08-30','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(17,1,2026,'RSV-2026-0017','Demo Guest - Fontaine Couple 17',NULL,'','2026-10-12','2026-10-14',2.0,'Two-Bedroom Presidential Pool Villa',4.0,'Cancelled',1,4100000.00,0.00,'Travel Agent','2026-09-05','2026-09-05','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(18,1,2026,'RSV-2026-0018','Demo Guest - Choi Retreat 18',3,'','2026-10-19','2026-10-21',2.0,'Deluxe Suite',2.0,'Tentative',0,3200000.00,6400000.00,'Corporate','2026-09-11','2026-09-11','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(19,1,2026,'RSV-2026-0019','Demo Guest - Laurent Family 19',NULL,'','2026-10-26','2026-10-29',3.0,'Premiere Suite',3.0,'Tentative',0,7700000.00,23100000.00,'Wholesaler','2026-09-17','2026-09-17','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(20,1,2026,'RSV-2026-0020','Demo Guest - Han Business Trip 20',NULL,'','2026-10-06','2026-10-09',3.0,'Deluxe Private Pool Villa',4.0,'Tentative',0,6800000.00,20400000.00,'OTA','2026-08-27','2026-08-27','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(21,1,2026,'RSV-2026-0021','Demo Guest - Bernard Anniversary 21',1,'','2026-11-13','2026-11-17',4.0,'Premiere Private Pool Villa',2.0,'Tentative',0,5900000.00,23600000.00,'Direct','2026-10-03','2026-10-03','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(22,1,2026,'RSV-2026-0022','Demo Guest - Yoon Solo Traveler 22',NULL,'','2026-11-20','2026-11-25',5.0,'One-Bedroom Presidential Pool Villa',3.0,'Tentative',0,5000000.00,25000000.00,'Travel Agent','2026-10-09','2026-10-09','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(23,1,2026,'RSV-2026-0023','Demo Guest - Moreau Group 23',NULL,'','2026-11-27','2026-12-04',7.0,'Two-Bedroom Presidential Pool Villa',4.0,'Tentative',0,4100000.00,28700000.00,'Corporate','2026-10-15','2026-10-15','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(24,1,2026,'RSV-2026-0024','Demo Guest - Dubois Family 24',2,'','2026-11-07','2026-11-08',1.0,'Deluxe Suite',2.0,'Cancelled',1,3200000.00,0.00,'Wholesaler','2026-09-24','2026-09-24','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(25,1,2026,'RSV-2026-0025','Demo Guest - Kim Household 25',NULL,'','2026-11-14','2026-11-16',2.0,'Premiere Suite',3.0,'Tentative',0,7700000.00,15400000.00,'OTA','2026-09-30','2026-09-30','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(26,1,2026,'RSV-2026-0026','Demo Guest - Park Wedding Party 26',NULL,'','2026-12-21','2026-12-23',2.0,'Deluxe Private Pool Villa',4.0,'Tentative',0,6800000.00,13600000.00,'Direct','2026-11-05','2026-11-05','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(27,1,2026,'RSV-2026-0027','Demo Guest - Martin Honeymoon 27',3,'','2026-12-01','2026-12-04',3.0,'Premiere Private Pool Villa',2.0,'Tentative',0,5900000.00,17700000.00,'Travel Agent','2026-10-15','2026-10-15','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(28,1,2026,'RSV-2026-0028','Demo Guest - Lee Corporate Group 28',NULL,'','2026-12-08','2026-12-11',3.0,'One-Bedroom Presidential Pool Villa',3.0,'Tentative',0,5000000.00,15000000.00,'Corporate','2026-10-21','2026-10-21','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(29,1,2026,'RSV-2026-0029','Demo Guest - Fontaine Couple 29',NULL,'','2026-12-15','2026-12-19',4.0,'Two-Bedroom Presidential Pool Villa',4.0,'Tentative',0,4100000.00,16400000.00,'Wholesaler','2026-10-27','2026-10-27','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02'),(30,1,2026,'RSV-2026-0030','Demo Guest - Choi Retreat 30',1,'','2026-12-22','2026-12-27',5.0,'Deluxe Suite',2.0,'Tentative',0,3200000.00,16000000.00,'OTA','2026-11-02','2026-11-02','2026-07-08','2026-07-08 20:14:02','2026-07-08 20:14:02');

--
-- Table structure for table `mkt_upload_maps`
--

CREATE TABLE `mkt_upload_maps` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `report_year` smallint(5) unsigned NOT NULL,
  `map_json` text NOT NULL COMMENT 'pemetaan header kolom xlsx/csv -> field mkt_reservations',
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_mkt_upload_maps_property_year` (`property_id`,`report_year`),
  CONSTRAINT `fk_mkt_upload_maps_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `mkt_upload_maps`
--

INSERT INTO `mkt_upload_maps` VALUES (1,1,2026,'{\"resv_no\":0,\"guest_name\":1,\"agent_name\":2,\"arrival\":3,\"departure\":4,\"nights\":5,\"room_type\":6,\"pax\":7,\"status\":8,\"rate\":9,\"revenue\":10,\"segment\":11,\"created\":12}','2026-07-08 20:14:02','2026-07-08 20:14:02');

--
-- Table structure for table `notifications`
--

CREATE TABLE `notifications` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `user_id` int(10) unsigned NOT NULL,
  `type` varchar(60) NOT NULL,
  `severity` enum('info','warning','critical') NOT NULL DEFAULT 'info',
  `title` varchar(150) NOT NULL,
  `body` varchar(1000) DEFAULT NULL,
  `link` varchar(255) DEFAULT NULL,
  `read_at` datetime DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_notifications_property_user_read` (`property_id`,`user_id`,`read_at`),
  KEY `fk_notifications_user` (`user_id`),
  CONSTRAINT `fk_notifications_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_notifications_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=166 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `notifications`
--

INSERT INTO `notifications` VALUES (1,1,3,'sla_breach','critical','WO urgent melewati SLA','WO-000010 Lift Tamu 1 melewati due date dan belum ditugaskan','/wo/10',NULL,'2026-07-08 16:57:09'),(2,1,3,'pm_missed','warning','PM terlewat','Fire safety rute bulanan (WO-000017) dan cooling tower (WO-000018) lewat jatuh tempo','/wo/17',NULL,'2026-07-08 08:57:09'),(3,1,3,'wo_pending_verification','info','WO menunggu verifikasi','WO-000003, WO-000004, WO-000029 selesai kemarin menunggu verifikasi','/wo?status=done','2026-07-08 17:57:09','2026-07-07 22:57:09'),(4,1,3,'contract_expiry','warning','Kontrak lift berakhir 45 hari lagi','Kontrak Servis Lift Tahunan (PT Lift Nusantara) berakhir dalam 45 hari','/contracts/1',NULL,'2026-07-07 18:57:09'),(5,1,3,'cert_expiry','warning','Sertifikat AK3 Candra segera habis','Sertifikat AK3 listrik tech.candra habis dalam 45 hari - satu-satunya certified genset','/users/4',NULL,'2026-07-07 18:57:09'),(6,1,3,'checklist_fail','critical','Checklist fail pada aset critical','Suhu freezer kitchen di luar ambang HACCP (-12C), WO korektif otomatis dibuat','/wo/4','2026-07-07 17:57:09','2026-07-07 12:57:09'),(7,1,4,'wo_assigned','info','Tugas baru: PM mingguan genset','WO-000014 ditugaskan kepada Anda, due hari ini','/wo/14',NULL,'2026-07-08 10:57:09'),(8,1,4,'pm_due_today','warning','PM due hari ini belum dimulai','6 tugas PM jatuh tempo hari ini belum dimulai','/wo?due=today',NULL,'2026-07-08 14:57:09'),(9,1,4,'part_available','info','Part tersedia untuk WO-000007','Filter AC Split tersedia di gudang, WO waiting_parts bisa dilanjutkan','/wo/7','2026-07-08 12:57:09','2026-07-07 18:57:09'),(10,1,4,'cert_expiry','warning','Sertifikat AK3 Anda segera habis','Sertifikat AK3 listrik Anda habis dalam 45 hari, segera ajukan perpanjangan','/profile',NULL,'2026-07-07 18:57:09'),(11,1,5,'report_resolved','info','Laporan Anda selesai: AC kamar 1201','Laporan AC kamar 1201 telah diperbaiki dan diverifikasi','/wo/1',NULL,'2026-07-07 16:57:09'),(12,1,5,'report_resolved','info','Laporan Anda selesai: sealant kamar 0801','Laporan sealant wastafel kamar 0801 telah diperbaiki dan diverifikasi','/wo/2','2026-07-07 23:57:09','2026-07-07 22:57:09'),(13,1,7,'wo_assigned','info','Tugas baru: PM AC cassette lobby 2','WO-000110 ditugaskan kepada Anda, due hari ini','/wo/110',NULL,'2026-07-08 10:57:09'),(14,1,8,'wo_assigned','warning','WO urgent: Combi oven error E13','WO-000123 combi oven dapur utama tidak menyala, tangani segera','/wo/123',NULL,'2026-07-08 17:27:09'),(15,1,9,'pm_due_today','warning','PM due hari ini','PM mingguan pompa kolam (WO-000115) jatuh tempo hari ini','/wo/115',NULL,'2026-07-08 14:57:09'),(16,1,10,'wo_assigned','info','Tugas baru: AP lantai 3 mati','WO-000101 ditugaskan kepada Anda, prioritas high','/wo/101','2026-07-08 16:57:09','2026-07-08 15:57:09'),(17,1,11,'wo_assigned','info','Tugas baru: PM CCTV basement','WO-000117 ditugaskan kepada Anda, due hari ini','/wo/117',NULL,'2026-07-08 12:57:09'),(18,1,12,'wo_assigned','info','Tugas baru: cat koridor lantai 5','WO-000105 ditugaskan kepada Anda','/wo/105','2026-07-08 13:57:09','2026-07-07 18:57:09'),(19,1,13,'wo_assigned','info','Tugas baru: poles marmer lobby','WO-000107 ditugaskan kepada Anda, due 3 hari lagi','/wo/107',NULL,'2026-07-08 08:57:09'),(20,1,13,'cert_expiry','warning','Sertifikat aplikator waterproofing segera habis','Sertifikat Anda habis dalam 40 hari, segera ajukan perpanjangan','/profile',NULL,'2026-07-07 18:57:09'),(21,1,525,'task_assigned','info','Task baru: Follow-up komplain kebersihan kamar 1203','Anda ditugaskan task CREW baru (DUMMY demo).','/tasks.php?id=1',NULL,'2026-07-08 17:08:46'),(22,1,514,'leave_pending','warning','Cuti menunggu persetujuan Anda (SPV)','Pengajuan Ijin Adat Bali dari Ni Luh Made Satya Utami Putri menunggu approval SPV (DUMMY demo).','/leaves.php?id=2',NULL,'2026-07-07 19:08:46'),(23,1,520,'contract_reminder','warning','Kontrak Contoh Travel Agent A berakhir 45 hari lagi','Reminder H-60: siapkan opsi perpanjangan sebelum kontrak expired (DUMMY demo).','/mkt/contracts.php?id=1',NULL,'2026-07-08 13:08:46'),(24,1,562,'quotation_followup','critical','Penawaran QT-2026-D003 belum update 8 hari','Status nego sudah 8 hari tanpa update — wajib follow-up segera (DUMMY demo).','/mkt/quotations.php?id=3',NULL,'2026-07-07 19:08:46'),(25,1,521,'kol_visit_reminder','info','Kedatangan KOL H-10: Demo KOL Traveler ID','Persiapkan welcome & pastikan photo release terupload sebelum kedatangan (DUMMY demo).','/mkt/kols.php?id=1',NULL,'2026-07-08 16:08:46'),(26,1,530,'discipline_ack_pending','warning','Anda perlu acknowledge coaching note','Coaching note keterlambatan menunggu tanda tangan digital Anda (DUMMY demo).','/hr/discipline.php?id=1',NULL,'2026-07-07 19:08:46'),(27,1,504,'kpi_published','info','Skor KPI Housekeeping periode ini terbit','Skor KPI departemen Housekeeping bulan berjalan sudah bisa direview (DUMMY demo).','/hr/kpi.php?dept=housekeeping',NULL,'2026-07-08 07:08:46'),(28,1,531,'location_oo','warning','Kamar OOO: Kamar 1201','Kamar Kamar 1201 ditandai Out of Order — Bocor pipa kamar mandi - TEST verifikasi',NULL,NULL,'2026-07-08 23:18:27'),(29,1,532,'location_oo','warning','Kamar OOO: Kamar 1201','Kamar Kamar 1201 ditandai Out of Order — Bocor pipa kamar mandi - TEST verifikasi',NULL,NULL,'2026-07-08 23:18:27'),(30,1,533,'location_oo','warning','Kamar OOO: Kamar 1201','Kamar Kamar 1201 ditandai Out of Order — Bocor pipa kamar mandi - TEST verifikasi',NULL,NULL,'2026-07-08 23:18:27'),(31,1,563,'location_oo','warning','Kamar OOO: Kamar 1201','Kamar Kamar 1201 ditandai Out of Order — Bocor pipa kamar mandi - TEST verifikasi',NULL,NULL,'2026-07-08 23:18:27'),(32,1,566,'location_oo','warning','Kamar OOO: Kamar 1201','Kamar Kamar 1201 ditandai Out of Order — Bocor pipa kamar mandi - TEST verifikasi',NULL,NULL,'2026-07-08 23:18:27'),(33,1,572,'location_oo','warning','Kamar OOO: Kamar 1201','Kamar Kamar 1201 ditandai Out of Order — Bocor pipa kamar mandi - TEST verifikasi',NULL,NULL,'2026-07-08 23:18:27'),(34,1,574,'location_oo','warning','Kamar OOO: Kamar 1201','Kamar Kamar 1201 ditandai Out of Order — Bocor pipa kamar mandi - TEST verifikasi',NULL,NULL,'2026-07-08 23:18:27'),(35,1,578,'location_oo','warning','Kamar OOO: Kamar 1201','Kamar Kamar 1201 ditandai Out of Order — Bocor pipa kamar mandi - TEST verifikasi',NULL,NULL,'2026-07-08 23:18:27'),(36,1,587,'location_oo','warning','Kamar OOO: Kamar 1201','Kamar Kamar 1201 ditandai Out of Order — Bocor pipa kamar mandi - TEST verifikasi',NULL,NULL,'2026-07-08 23:18:27'),(37,1,588,'location_oo','warning','Kamar OOO: Kamar 1201','Kamar Kamar 1201 ditandai Out of Order — Bocor pipa kamar mandi - TEST verifikasi',NULL,NULL,'2026-07-08 23:18:27'),(38,1,5,'location_oo','warning','Kamar OOO: Kamar 1201','Kamar Kamar 1201 ditandai Out of Order — Bocor pipa kamar mandi - TEST verifikasi',NULL,NULL,'2026-07-08 23:18:27'),(39,1,504,'location_oo','warning','Kamar OOO: Kamar 1201','Kamar Kamar 1201 ditandai Out of Order — Bocor pipa kamar mandi - TEST verifikasi',NULL,NULL,'2026-07-08 23:18:27'),(40,1,514,'location_oo','warning','Kamar OOO: Kamar 1201','Kamar Kamar 1201 ditandai Out of Order — Bocor pipa kamar mandi - TEST verifikasi',NULL,NULL,'2026-07-08 23:18:27'),(41,1,525,'location_oo','warning','Kamar OOO: Kamar 1201','Kamar Kamar 1201 ditandai Out of Order — Bocor pipa kamar mandi - TEST verifikasi',NULL,NULL,'2026-07-08 23:18:27'),(42,1,526,'location_oo','warning','Kamar OOO: Kamar 1201','Kamar Kamar 1201 ditandai Out of Order — Bocor pipa kamar mandi - TEST verifikasi',NULL,NULL,'2026-07-08 23:18:27'),(43,1,527,'location_oo','warning','Kamar OOO: Kamar 1201','Kamar Kamar 1201 ditandai Out of Order — Bocor pipa kamar mandi - TEST verifikasi',NULL,NULL,'2026-07-08 23:18:27'),(44,1,528,'location_oo','warning','Kamar OOO: Kamar 1201','Kamar Kamar 1201 ditandai Out of Order — Bocor pipa kamar mandi - TEST verifikasi',NULL,NULL,'2026-07-08 23:18:27'),(45,1,529,'location_oo','warning','Kamar OOO: Kamar 1201','Kamar Kamar 1201 ditandai Out of Order — Bocor pipa kamar mandi - TEST verifikasi',NULL,NULL,'2026-07-08 23:18:27'),(46,1,530,'location_oo','warning','Kamar OOO: Kamar 1201','Kamar Kamar 1201 ditandai Out of Order — Bocor pipa kamar mandi - TEST verifikasi',NULL,NULL,'2026-07-08 23:18:27'),(47,1,580,'location_oo','warning','Kamar OOO: Kamar 1201','Kamar Kamar 1201 ditandai Out of Order — Bocor pipa kamar mandi - TEST verifikasi',NULL,NULL,'2026-07-08 23:18:27'),(48,1,904,'location_oo','warning','Kamar OOO: Kamar 1201','Kamar Kamar 1201 ditandai Out of Order — Bocor pipa kamar mandi - TEST verifikasi',NULL,NULL,'2026-07-08 23:18:27'),(49,1,905,'location_oo','warning','Kamar OOO: Kamar 1201','Kamar Kamar 1201 ditandai Out of Order — Bocor pipa kamar mandi - TEST verifikasi',NULL,NULL,'2026-07-08 23:18:27'),(50,1,1,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(51,1,2,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(52,1,3,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(53,1,4,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(54,1,5,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(55,1,6,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(56,1,7,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(57,1,8,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(58,1,9,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(59,1,10,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(60,1,11,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(61,1,12,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(62,1,13,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(63,1,501,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(64,1,502,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(65,1,503,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(66,1,504,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(67,1,505,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(68,1,506,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(69,1,507,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(70,1,508,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(71,1,509,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(72,1,510,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(73,1,511,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(74,1,512,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(75,1,513,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(76,1,514,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(77,1,515,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(78,1,516,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(79,1,517,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(80,1,518,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(81,1,519,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(82,1,520,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(83,1,521,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(84,1,522,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(85,1,523,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(86,1,524,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(87,1,525,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(88,1,526,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(89,1,527,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(90,1,528,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(91,1,529,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(92,1,530,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(93,1,531,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(94,1,532,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(95,1,533,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(96,1,534,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(97,1,535,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(98,1,536,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(99,1,537,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(100,1,538,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(101,1,539,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(102,1,540,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(103,1,541,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(104,1,542,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(105,1,543,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(106,1,544,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(107,1,545,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(108,1,546,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(109,1,547,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(110,1,548,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(111,1,549,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(112,1,550,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(113,1,551,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(114,1,552,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(115,1,553,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(116,1,554,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(117,1,555,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(118,1,556,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(119,1,557,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(120,1,558,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(121,1,559,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(122,1,560,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(123,1,561,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(124,1,562,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(125,1,563,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(126,1,564,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(127,1,565,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(128,1,566,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(129,1,567,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(130,1,568,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(131,1,569,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(132,1,570,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(133,1,571,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(134,1,572,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(135,1,573,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(136,1,574,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(137,1,575,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(138,1,576,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(139,1,577,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(140,1,578,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(141,1,579,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(142,1,580,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(143,1,581,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(144,1,582,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(145,1,583,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(146,1,584,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(147,1,585,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(148,1,586,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(149,1,587,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(150,1,588,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(151,1,589,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(152,1,590,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(153,1,591,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(154,1,592,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(155,1,901,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(156,1,902,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(157,1,903,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(158,1,904,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(159,1,905,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(160,1,906,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(161,1,907,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(162,1,908,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(163,1,909,'broadcast','info','Uji broadcast GM — DUMMY','Tes hak kirim GM (task #9). Abaikan.',NULL,NULL,'2026-07-09 13:55:01'),(164,1,504,'complaint','critical','Komplain baru perlu tindak lanjut','Departemen housekeeping: QC TEST - handuk kotor tidak diganti, tamu marah.','/complaint.php?id=4',NULL,'2026-07-09 15:21:08'),(165,1,578,'complaint','warning','Komplain baru perlu tindak lanjut','Departemen front_office: QC TEST medium severity - proses checkout agak lama.','/complaint.php?id=5',NULL,'2026-07-09 15:23:54');

--
-- Table structure for table `parts`
--

CREATE TABLE `parts` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `code` varchar(40) NOT NULL,
  `name` varchar(150) NOT NULL,
  `unit` varchar(30) NOT NULL,
  `stock_qty` decimal(12,2) NOT NULL DEFAULT 0.00,
  `min_stock` decimal(12,2) NOT NULL DEFAULT 0.00,
  `unit_price` decimal(14,2) NOT NULL DEFAULT 0.00,
  `bin_location` varchar(60) DEFAULT NULL,
  `department` varchar(60) DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_parts_property_code` (`property_id`,`code`),
  KEY `idx_parts_property_stock` (`property_id`,`stock_qty`),
  CONSTRAINT `fk_parts_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `parts`
--

INSERT INTO `parts` VALUES (1,1,'PRT-0001','Filter AC Split (universal)','pcs',25.00,5.00,45000.00,'Rak A1','engineering','2026-07-08 18:57:08','2026-07-08 18:57:08'),(2,1,'PRT-0002','Oli Mesin Genset 15W-40','liter',40.00,10.00,65000.00,'Rak B2','engineering','2026-07-08 18:57:08','2026-07-08 18:57:08'),(3,1,'PRT-0003','Lampu Emergency LED','pcs',15.00,3.00,120000.00,'Rak C1','engineering','2026-07-08 18:57:08','2026-07-08 18:57:08');

--
-- Table structure for table `photos`
--

CREATE TABLE `photos` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `wo_id` bigint(20) unsigned NOT NULL,
  `type` enum('before','after','evidence') NOT NULL,
  `filename` varchar(255) NOT NULL,
  `uploaded_by` int(10) unsigned DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_photos_wo` (`wo_id`),
  KEY `idx_photos_uploaded_by` (`uploaded_by`),
  CONSTRAINT `fk_photos_uploaded_by` FOREIGN KEY (`uploaded_by`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_photos_wo` FOREIGN KEY (`wo_id`) REFERENCES `work_orders` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `photos`
--

INSERT INTO `photos` VALUES (1,21,'before','wo_photos/21/before-demo.jpg (DUMMY)',4,'2026-07-08 20:14:02'),(2,21,'after','wo_photos/21/after-demo.jpg (DUMMY)',4,'2026-07-08 20:14:02'),(3,1,'evidence','wo_photos/1/evidence-demo.jpg (DUMMY)',7,'2026-07-08 20:14:02');

--
-- Table structure for table `pm_schedules`
--

CREATE TABLE `pm_schedules` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `name` varchar(150) NOT NULL,
  `scope` enum('asset','location','category') NOT NULL,
  `asset_id` int(10) unsigned DEFAULT NULL,
  `location_id` int(10) unsigned DEFAULT NULL,
  `category_id` int(10) unsigned DEFAULT NULL,
  `department` varchar(60) NOT NULL,
  `checklist_id` int(10) unsigned DEFAULT NULL,
  `frequency_type` enum('daily','weekly','monthly','quarterly','semiannual','yearly','custom_days','meter') NOT NULL,
  `frequency_value` int(10) unsigned DEFAULT NULL,
  `weekly_days` varchar(20) DEFAULT NULL,
  `monthly_day` tinyint(3) unsigned DEFAULT NULL,
  `lead_time_days` smallint(5) unsigned NOT NULL DEFAULT 3,
  `grace_days` smallint(5) unsigned NOT NULL DEFAULT 0,
  `schedule_base` enum('fixed','floating') NOT NULL DEFAULT 'fixed',
  `executor` enum('internal','vendor','either') NOT NULL DEFAULT 'internal',
  `vendor_id` int(10) unsigned DEFAULT NULL,
  `auto_assign` tinyint(1) NOT NULL DEFAULT 0,
  `spread` tinyint(1) NOT NULL DEFAULT 0,
  `estimated_minutes` int(10) unsigned DEFAULT NULL,
  `priority` enum('low','normal','high','urgent') NOT NULL DEFAULT 'normal',
  `active` tinyint(1) NOT NULL DEFAULT 1,
  `next_due_date` date DEFAULT NULL,
  `next_due_meter` decimal(14,2) DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_pm_schedules_property_active_due` (`property_id`,`active`,`next_due_date`),
  KEY `idx_pm_schedules_asset` (`asset_id`),
  KEY `idx_pm_schedules_location` (`location_id`),
  KEY `idx_pm_schedules_category` (`category_id`),
  KEY `idx_pm_schedules_checklist` (`checklist_id`),
  KEY `idx_pm_schedules_vendor` (`vendor_id`),
  CONSTRAINT `fk_pm_schedules_asset` FOREIGN KEY (`asset_id`) REFERENCES `assets` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_pm_schedules_category` FOREIGN KEY (`category_id`) REFERENCES `asset_categories` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_pm_schedules_checklist` FOREIGN KEY (`checklist_id`) REFERENCES `checklists` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_pm_schedules_location` FOREIGN KEY (`location_id`) REFERENCES `locations` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_pm_schedules_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_pm_schedules_vendor` FOREIGN KEY (`vendor_id`) REFERENCES `vendors` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `pm_schedules`
--

INSERT INTO `pm_schedules` VALUES (1,1,'Genset - Servis 250 Jam','asset',1,NULL,NULL,'engineering',NULL,'meter',250,NULL,NULL,3,2,'floating','internal',NULL,0,0,180,'high',1,NULL,5000.00,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(2,1,'Genset - Mingguan','asset',1,NULL,NULL,'engineering',1,'weekly',1,'mon',NULL,3,1,'fixed','internal',NULL,1,0,45,'high',1,'2026-07-11',NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(3,1,'AC Split - Bulanan (semua unit)','category',NULL,NULL,4,'engineering',2,'monthly',1,NULL,5,3,3,'fixed','internal',NULL,1,1,45,'normal',1,'2026-07-10',NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(4,1,'PPM Kamar - 3 Bulanan (30 titik)','location',NULL,1,NULL,'engineering',3,'quarterly',1,NULL,NULL,5,5,'floating','internal',NULL,0,1,90,'normal',1,'2026-07-15',NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(11,1,'HACCP Suhu - Harian Dapur','category',NULL,NULL,26,'kitchen',4,'daily',1,NULL,NULL,1,0,'fixed','internal',NULL,1,0,20,'high',1,'2026-07-09',NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(12,1,'Pompa Kolam - Mingguan','asset',66,NULL,NULL,'engineering',NULL,'weekly',1,'thu',NULL,2,1,'fixed','internal',NULL,0,0,30,'normal',1,'2026-07-15',NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09');

--
-- Table structure for table `pr_request_lines`
--

CREATE TABLE `pr_request_lines` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `pr_request_id` int(10) unsigned NOT NULL,
  `item_name` varchar(200) NOT NULL,
  `qty` decimal(14,3) NOT NULL DEFAULT 0.000,
  `unit` varchar(30) NOT NULL DEFAULT 'pcs',
  `notes` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_pr_request_lines_request` (`pr_request_id`),
  CONSTRAINT `fk_pr_request_lines_request` FOREIGN KEY (`pr_request_id`) REFERENCES `pr_requests` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `pr_request_lines`
--

INSERT INTO `pr_request_lines` VALUES (1,1,'DUMMY — Mechanical seal pompa 2 inch',2.000,'pcs','merek setara Grundfos'),(2,1,'DUMMY — Bearing 6205 ZZ',4.000,'pcs',NULL),(3,1,'DUMMY — Gasket set',1.000,'set',NULL),(4,2,'DUMMY — Trolley linen stainless',2.000,'unit','dengan penutup kanvas'),(5,2,'DUMMY — Roda castor 4 inch',8.000,'pcs','cadangan');

--
-- Table structure for table `pr_requests`
--

CREATE TABLE `pr_requests` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `department` varchar(60) DEFAULT NULL COMMENT 'dept peminta, match kode hr_departments.code',
  `requested_by` int(10) unsigned DEFAULT NULL COMMENT 'FK hr_employees.id (karyawan pengaju)',
  `title` varchar(200) NOT NULL,
  `description` text DEFAULT NULL,
  `priority` enum('low','normal','urgent') NOT NULL DEFAULT 'normal',
  `status` enum('diminta','di_po','indent','barang_datang','diserahkan','selesai','ditolak') NOT NULL DEFAULT 'diminta',
  `journal_po_ref` varchar(60) DEFAULT NULL COMMENT 'nomor PO journal.id (catatan silang manual; BUKAN logika PO)',
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_pr_requests_property_status` (`property_id`,`status`),
  KEY `idx_pr_requests_property_dept` (`property_id`,`department`),
  KEY `fk_pr_requests_requested_by` (`requested_by`),
  CONSTRAINT `fk_pr_requests_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_pr_requests_requested_by` FOREIGN KEY (`requested_by`) REFERENCES `hr_employees` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `pr_requests`
--

INSERT INTO `pr_requests` VALUES (1,1,'engineering',1,'DUMMY — Pembelian spare part pompa kolam','Kebutuhan mendesak perbaikan pompa filter kolam utama.','urgent','di_po','PO-JID-2026-0141','2026-07-09 16:46:28','2026-07-09 16:46:28'),(2,1,'housekeeping',1,'DUMMY — Pengadaan trolley linen baru','Penggantian 2 trolley linen yang sudah rusak.','normal','diminta',NULL,'2026-07-09 16:46:28','2026-07-09 16:46:28');

--
-- Table structure for table `properties`
--

CREATE TABLE `properties` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `code` varchar(20) NOT NULL,
  `name` varchar(150) NOT NULL,
  `address` varchar(255) DEFAULT NULL,
  `timezone` varchar(64) NOT NULL DEFAULT 'Asia/Jakarta',
  `logo` varchar(255) DEFAULT NULL,
  `active` tinyint(1) NOT NULL DEFAULT 1,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_properties_code` (`code`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `properties`
--

INSERT INTO `properties` VALUES (1,'HTL1','Hotel Demo Satu','Jl. Contoh Raya No. 1, Jakarta','Asia/Jakarta',NULL,1,'2026-07-08 18:57:08','2026-07-08 18:57:08');

--
-- Table structure for table `schema_migrations`
--

CREATE TABLE `schema_migrations` (
  `filename` varchar(255) NOT NULL,
  `applied_at` datetime NOT NULL,
  PRIMARY KEY (`filename`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

--
-- Dumping data for table `schema_migrations`
--

INSERT INTO `schema_migrations` VALUES ('0001_init.sql','2026-07-08 18:57:08'),('0002_seed_master.sql','2026-07-08 18:57:08'),('0003_seed_checklists.sql','2026-07-08 18:57:08'),('0004_seed_demo.sql','2026-07-08 18:57:09'),('0005_seed_expand.sql','2026-07-08 18:57:09'),('0006_seed_real_users.sql','2026-07-08 18:57:09'),('0007_password_policy.sql','2026-07-08 18:57:09'),('0008_hr_init.sql','2026-07-08 18:57:11'),('0009_mkt_init.sql','2026-07-08 18:57:12'),('0010_seed_hr_hk.sql','2026-07-08 18:57:12'),('0011_seed_mkt.sql','2026-07-08 18:57:12'),('0012_sell_theme_followups.sql','2026-07-08 18:57:12'),('0013_broadcast_app_source.sql','2026-07-08 18:57:12'),('0014_crew_sell_role_enum_seed.sql','2026-07-08 18:57:12'),('0015_role_assignment.sql','2026-07-08 19:02:25'),('0016_seed_dummy_demo.sql','2026-07-08 19:08:46'),('0017_seed_dummy_full.sql','2026-07-08 20:14:02'),('0018_location_oo.sql','2026-07-08 23:10:04'),('0019_universal_task.sql','2026-07-08 23:34:49'),('0020_backfill_employees.sql','2026-07-08 23:58:35'),('0021_candidate_name.sql','2026-07-09 07:04:16'),('0022_departments.sql','2026-07-09 13:48:51'),('0023_clean_competency_names.sql','2026-07-09 13:48:16'),('0024_kpi_task_seed_backfill.sql','2026-07-09 14:02:05'),('0025_complaints.sql','2026-07-09 14:09:43'),('0026_lostfound_seed.sql','2026-07-09 16:13:38'),('0027_inventory.sql','2026-07-09 16:13:38'),('0028_asset_custody.sql','2026-07-09 16:46:28'),('0029_purchase_requests.sql','2026-07-09 16:46:28'),('0030_laundry_handovers.sql','2026-07-09 16:46:28'),('0031_hr_task_templates.sql','2026-07-09 16:53:37'),('0032_night_audit.sql','2026-07-09 17:04:54'),('0033_kol_pic.sql','2026-07-09 17:07:58'),('0034_night_audit_raw_json.sql','2026-07-10 14:47:27');

--
-- Table structure for table `skills`
--

CREATE TABLE `skills` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(10) unsigned NOT NULL,
  `category_id` int(10) unsigned NOT NULL,
  `level` enum('basic','advanced','certified') NOT NULL,
  `cert_document` varchar(255) DEFAULT NULL,
  `valid_until` date DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_skills_user_category` (`user_id`,`category_id`),
  KEY `idx_skills_category` (`category_id`),
  CONSTRAINT `fk_skills_category` FOREIGN KEY (`category_id`) REFERENCES `asset_categories` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_skills_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `skills`
--

INSERT INTO `skills` VALUES (1,4,5,'certified','sertifikat_ak3_listrik_candra.pdf','2026-08-22','2026-07-08 18:57:08','2026-07-08 18:57:09'),(2,4,4,'advanced',NULL,NULL,'2026-07-08 18:57:08','2026-07-08 18:57:08'),(3,4,8,'advanced',NULL,NULL,'2026-07-08 18:57:08','2026-07-08 18:57:08'),(4,3,4,'advanced',NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(5,3,6,'advanced',NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(6,7,4,'advanced',NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(7,7,8,'advanced',NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(8,8,4,'advanced',NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(9,8,7,'advanced',NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(10,9,4,'basic',NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(11,9,8,'advanced',NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(12,10,22,'advanced',NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(13,11,23,'advanced','sertifikat_cctv_joko.pdf','2027-01-24','2026-07-08 18:57:09','2026-07-08 18:57:09'),(14,11,24,'advanced',NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(15,12,18,'advanced',NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(16,12,19,'advanced',NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(17,13,20,'advanced',NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(18,13,21,'certified','sertifikat_aplikator_waterproofing_wawan.pdf','2026-08-17','2026-07-08 18:57:09','2026-07-08 18:57:09');

--
-- Table structure for table `user_property_access`
--

CREATE TABLE `user_property_access` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(10) unsigned NOT NULL,
  `property_id` int(10) unsigned NOT NULL,
  `role` enum('super_admin','property_admin','dept_head','technician','reporter','viewer','gm','hr_admin','hr_staff','fc','supervisor','employee','sales_manager','sales','ewm','design') NOT NULL,
  `department` varchar(60) DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_upa_user_property_role_dept` (`user_id`,`property_id`,`role`,`department`),
  KEY `idx_upa_property_role` (`property_id`,`role`),
  KEY `idx_upa_user` (`user_id`),
  CONSTRAINT `fk_upa_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_upa_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=120 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `user_property_access`
--

INSERT INTO `user_property_access` VALUES (1,1,1,'super_admin',NULL,'2026-07-08 18:57:08','2026-07-08 18:57:08'),(2,2,1,'property_admin',NULL,'2026-07-08 18:57:08','2026-07-08 18:57:08'),(3,3,1,'dept_head','engineering','2026-07-08 18:57:08','2026-07-08 18:57:08'),(4,4,1,'technician','engineering','2026-07-08 18:57:08','2026-07-08 18:57:08'),(5,5,1,'reporter','housekeeping','2026-07-08 18:57:08','2026-07-08 18:57:08'),(6,6,1,'viewer',NULL,'2026-07-08 18:57:08','2026-07-08 18:57:08'),(7,7,1,'technician','engineering','2026-07-08 18:57:09','2026-07-08 18:57:09'),(8,8,1,'technician','engineering','2026-07-08 18:57:09','2026-07-08 18:57:09'),(9,9,1,'technician','engineering','2026-07-08 18:57:09','2026-07-08 18:57:09'),(10,10,1,'technician','it','2026-07-08 18:57:09','2026-07-08 18:57:09'),(11,11,1,'technician','it','2026-07-08 18:57:09','2026-07-08 18:57:09'),(12,12,1,'technician','engineering','2026-07-08 18:57:09','2026-07-08 18:57:09'),(13,13,1,'technician','engineering','2026-07-08 18:57:09','2026-07-08 18:57:09'),(14,501,1,'gm',NULL,'2026-07-08 18:57:09','2026-07-08 19:02:25'),(15,502,1,'fc',NULL,'2026-07-08 18:57:09','2026-07-08 19:02:25'),(16,503,1,'employee','admin','2026-07-08 18:57:09','2026-07-08 19:02:25'),(17,504,1,'dept_head','housekeeping','2026-07-08 18:57:09','2026-07-08 18:57:09'),(18,505,1,'employee','admin','2026-07-08 18:57:09','2026-07-08 19:02:25'),(19,506,1,'dept_head','fnb','2026-07-08 18:57:09','2026-07-08 18:57:09'),(20,507,1,'dept_head','engineering','2026-07-08 18:57:09','2026-07-08 18:57:09'),(21,508,1,'supervisor','spa','2026-07-08 18:57:09','2026-07-08 19:02:25'),(22,509,1,'employee','admin','2026-07-08 18:57:09','2026-07-08 19:02:25'),(23,510,1,'employee','spa','2026-07-08 18:57:09','2026-07-08 19:02:25'),(24,511,1,'employee','spa','2026-07-08 18:57:09','2026-07-08 19:02:25'),(25,512,1,'employee','fnb','2026-07-08 18:57:09','2026-07-08 19:02:25'),(26,513,1,'technician','kitchen','2026-07-08 18:57:09','2026-07-08 18:57:09'),(27,514,1,'employee','housekeeping','2026-07-08 18:57:09','2026-07-08 19:02:25'),(28,515,1,'employee','spa','2026-07-08 18:57:09','2026-07-08 19:02:25'),(29,516,1,'technician','engineering','2026-07-08 18:57:09','2026-07-08 18:57:09'),(30,517,1,'technician','engineering','2026-07-08 18:57:09','2026-07-08 18:57:09'),(31,518,1,'technician','engineering','2026-07-08 18:57:09','2026-07-08 18:57:09'),(32,519,1,'supervisor','engineering','2026-07-08 18:57:09','2026-07-08 19:02:25'),(33,520,1,'sales','sales','2026-07-08 18:57:09','2026-07-08 19:02:25'),(34,521,1,'sales','sales','2026-07-08 18:57:09','2026-07-08 19:02:25'),(35,522,1,'supervisor','kitchen','2026-07-08 18:57:09','2026-07-08 19:02:25'),(36,523,1,'supervisor','fnb','2026-07-08 18:57:09','2026-07-08 19:02:25'),(37,524,1,'supervisor','fnb','2026-07-08 18:57:09','2026-07-08 19:02:25'),(38,525,1,'supervisor','housekeeping','2026-07-08 18:57:09','2026-07-08 19:02:25'),(39,526,1,'employee','housekeeping','2026-07-08 18:57:09','2026-07-08 19:02:25'),(40,527,1,'employee','housekeeping','2026-07-08 18:57:09','2026-07-08 19:02:25'),(41,528,1,'employee','housekeeping','2026-07-08 18:57:09','2026-07-08 19:02:25'),(42,529,1,'employee','housekeeping','2026-07-08 18:57:09','2026-07-08 19:02:25'),(43,530,1,'employee','housekeeping','2026-07-08 18:57:09','2026-07-08 19:02:25'),(44,531,1,'employee','front_office','2026-07-08 18:57:09','2026-07-08 19:02:25'),(45,532,1,'employee','front_office','2026-07-08 18:57:09','2026-07-08 19:02:25'),(46,533,1,'employee','front_office','2026-07-08 18:57:09','2026-07-08 19:02:25'),(47,534,1,'dept_head','it','2026-07-08 18:57:09','2026-07-08 18:57:09'),(48,535,1,'supervisor','fnb','2026-07-08 18:57:09','2026-07-08 19:02:25'),(49,536,1,'employee','kitchen','2026-07-08 18:57:09','2026-07-08 19:02:25'),(50,537,1,'employee','kitchen','2026-07-08 18:57:09','2026-07-08 19:02:25'),(51,538,1,'employee','kitchen','2026-07-08 18:57:09','2026-07-08 19:02:25'),(52,539,1,'employee','kitchen','2026-07-08 18:57:09','2026-07-08 19:02:25'),(53,540,1,'employee','fnb','2026-07-08 18:57:09','2026-07-08 19:02:25'),(54,541,1,'employee','fnb','2026-07-08 18:57:09','2026-07-08 19:02:25'),(55,542,1,'technician','kitchen','2026-07-08 18:57:09','2026-07-08 18:57:09'),(56,543,1,'technician','kitchen','2026-07-08 18:57:09','2026-07-08 18:57:09'),(57,544,1,'design','sales','2026-07-08 18:57:09','2026-07-08 19:02:25'),(58,545,1,'employee','admin','2026-07-08 18:57:09','2026-07-08 19:02:25'),(59,546,1,'hr_admin',NULL,'2026-07-08 18:57:09','2026-07-08 19:02:25'),(60,547,1,'employee','security','2026-07-08 18:57:09','2026-07-08 19:02:25'),(61,548,1,'supervisor','spa','2026-07-08 18:57:09','2026-07-08 19:02:25'),(62,549,1,'employee','kitchen','2026-07-08 18:57:09','2026-07-08 19:02:25'),(63,550,1,'technician','engineering','2026-07-08 18:57:09','2026-07-08 18:57:09'),(64,551,1,'employee','security','2026-07-08 18:57:09','2026-07-08 19:02:25'),(65,552,1,'employee','fnb','2026-07-08 18:57:09','2026-07-08 19:02:25'),(66,553,1,'employee','fnb','2026-07-08 18:57:09','2026-07-08 19:02:25'),(67,554,1,'employee','kitchen','2026-07-08 18:57:09','2026-07-08 19:02:25'),(68,555,1,'employee','kitchen','2026-07-08 18:57:09','2026-07-08 19:02:25'),(69,556,1,'supervisor','admin','2026-07-08 18:57:09','2026-07-08 19:02:25'),(70,557,1,'technician','engineering','2026-07-08 18:57:09','2026-07-08 18:57:09'),(71,558,1,'hr_staff','hrd','2026-07-08 18:57:09','2026-07-08 19:02:25'),(72,559,1,'supervisor','security','2026-07-08 18:57:09','2026-07-08 19:02:25'),(73,560,1,'employee','security','2026-07-08 18:57:09','2026-07-08 19:02:25'),(74,561,1,'employee','kitchen','2026-07-08 18:57:09','2026-07-08 19:02:25'),(75,562,1,'sales_manager',NULL,'2026-07-08 18:57:09','2026-07-08 19:02:25'),(76,563,1,'employee','front_office','2026-07-08 18:57:09','2026-07-08 19:02:25'),(77,564,1,'employee','security','2026-07-08 18:57:09','2026-07-08 19:02:25'),(78,565,1,'technician','engineering','2026-07-08 18:57:09','2026-07-08 18:57:09'),(79,566,1,'employee','front_office','2026-07-08 18:57:09','2026-07-08 19:02:25'),(80,567,1,'technician','engineering','2026-07-08 18:57:09','2026-07-08 18:57:09'),(81,568,1,'technician','engineering','2026-07-08 18:57:09','2026-07-08 18:57:09'),(82,569,1,'employee','spa','2026-07-08 18:57:09','2026-07-08 19:02:25'),(83,570,1,'technician','engineering','2026-07-08 18:57:09','2026-07-08 18:57:09'),(84,571,1,'technician','engineering','2026-07-08 18:57:09','2026-07-08 18:57:09'),(85,572,1,'employee','front_office','2026-07-08 18:57:09','2026-07-08 19:02:25'),(86,573,1,'employee','kitchen','2026-07-08 18:57:09','2026-07-08 19:02:25'),(87,574,1,'employee','front_office','2026-07-08 18:57:09','2026-07-08 19:02:25'),(88,575,1,'employee','spa','2026-07-08 18:57:09','2026-07-08 19:02:25'),(89,576,1,'technician','engineering','2026-07-08 18:57:09','2026-07-08 18:57:09'),(90,577,1,'employee','spa','2026-07-08 18:57:09','2026-07-08 19:02:25'),(91,578,1,'dept_head','front_office','2026-07-08 18:57:09','2026-07-08 18:57:09'),(92,579,1,'employee','spa','2026-07-08 18:57:09','2026-07-08 19:02:25'),(93,580,1,'employee','housekeeping','2026-07-08 18:57:09','2026-07-08 19:02:25'),(94,581,1,'employee','spa','2026-07-08 18:57:09','2026-07-08 19:02:25'),(95,582,1,'sales','sales','2026-07-08 18:57:09','2026-07-08 19:02:25'),(96,583,1,'employee','admin','2026-07-08 18:57:09','2026-07-08 19:02:25'),(97,584,1,'technician','engineering','2026-07-08 18:57:09','2026-07-08 18:57:09'),(98,585,1,'technician','engineering','2026-07-08 18:57:09','2026-07-08 18:57:09'),(99,586,1,'employee','security','2026-07-08 18:57:09','2026-07-08 19:02:25'),(100,587,1,'employee','front_office','2026-07-08 18:57:09','2026-07-08 19:02:25'),(101,588,1,'employee','front_office','2026-07-08 18:57:09','2026-07-08 19:02:25'),(102,589,1,'employee','spa','2026-07-08 18:57:09','2026-07-08 19:02:25'),(103,590,1,'ewm','sales','2026-07-08 18:57:09','2026-07-08 19:02:25'),(104,591,1,'employee','admin','2026-07-08 18:57:09','2026-07-08 19:02:25'),(105,592,1,'technician','engineering','2026-07-08 18:57:09','2026-07-08 18:57:09'),(106,900,1,'gm',NULL,'2026-07-08 18:57:12','2026-07-08 18:57:12'),(107,901,1,'hr_admin','hr','2026-07-08 18:57:12','2026-07-08 18:57:12'),(108,902,1,'hr_staff','hr','2026-07-08 18:57:12','2026-07-08 18:57:12'),(109,903,1,'fc','finance','2026-07-08 18:57:12','2026-07-08 18:57:12'),(110,904,1,'supervisor','housekeeping','2026-07-08 18:57:12','2026-07-08 18:57:12'),(111,905,1,'employee','housekeeping','2026-07-08 18:57:12','2026-07-08 18:57:12'),(112,906,1,'sales_manager','sales','2026-07-08 18:57:12','2026-07-08 18:57:12'),(113,907,1,'sales','sales','2026-07-08 18:57:12','2026-07-08 18:57:12'),(114,908,1,'ewm','sales','2026-07-08 18:57:12','2026-07-08 18:57:12'),(115,909,1,'design','sales','2026-07-08 18:57:12','2026-07-08 18:57:12'),(116,910,1,'property_admin',NULL,'2026-07-09 16:52:05','2026-07-09 16:52:05');

--
-- Table structure for table `utility_meters`
--

CREATE TABLE `utility_meters` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `code` varchar(40) NOT NULL,
  `name` varchar(150) NOT NULL,
  `utility_type` enum('electricity','water','gas','fuel') NOT NULL,
  `unit` enum('kWh','m3','liter') NOT NULL,
  `location_id` int(10) unsigned DEFAULT NULL,
  `area_served` varchar(150) DEFAULT NULL,
  `is_submeter` tinyint(1) NOT NULL DEFAULT 0,
  `parent_meter_id` int(10) unsigned DEFAULT NULL,
  `tariff_per_unit` decimal(14,4) DEFAULT NULL,
  `fixed_charge` decimal(14,2) DEFAULT NULL,
  `provider` varchar(100) DEFAULT NULL,
  `account_no` varchar(60) DEFAULT NULL,
  `active` tinyint(1) NOT NULL DEFAULT 1,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_utility_meters_property_code` (`property_id`,`code`),
  KEY `idx_utility_meters_property_type` (`property_id`,`utility_type`),
  KEY `idx_utility_meters_location` (`location_id`),
  KEY `idx_utility_meters_parent` (`parent_meter_id`),
  CONSTRAINT `fk_utility_meters_location` FOREIGN KEY (`location_id`) REFERENCES `locations` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_utility_meters_parent` FOREIGN KEY (`parent_meter_id`) REFERENCES `utility_meters` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_utility_meters_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `utility_meters`
--

INSERT INTO `utility_meters` VALUES (1,1,'UTM-PLN-01','Meteran PLN Induk','electricity','kWh',NULL,'Seluruh gedung',0,NULL,1444.7000,0.00,'PLN','541234567890',1,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(2,1,'UTM-PLN-L1','Submeter Listrik Lantai 1','electricity','kWh',6,'Lantai 1 - Lobby & Resto',1,1,1444.7000,0.00,'PLN (internal submeter)',NULL,1,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(3,1,'UTM-PDAM-01','Meteran Air PDAM','water','m3',NULL,'Seluruh gedung',0,NULL,12550.0000,150000.00,'PDAM','PD-88123456',1,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(4,1,'UTM-SOLAR-01','Meter Solar Tangki Genset','fuel','liter',12,'Genset & boiler',0,NULL,6800.0000,0.00,'Pertamina Patra Niaga',NULL,1,'2026-07-08 18:57:09','2026-07-08 18:57:09');

--
-- Table structure for table `utility_readings`
--

CREATE TABLE `utility_readings` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `meter_id` int(10) unsigned NOT NULL,
  `period_month` date NOT NULL COMMENT 'disimpan sebagai tanggal 1 bulan berjalan, mis. 2026-07-01',
  `reading_value` decimal(14,2) NOT NULL,
  `prev_reading` decimal(14,2) DEFAULT NULL,
  `consumption` decimal(14,2) DEFAULT NULL,
  `tariff_snapshot` decimal(14,4) DEFAULT NULL,
  `cost` decimal(14,2) DEFAULT NULL,
  `read_at` datetime NOT NULL,
  `read_by` int(10) unsigned DEFAULT NULL,
  `photo` varchar(255) DEFAULT NULL,
  `note` varchar(500) DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_utility_readings_meter_period` (`meter_id`,`period_month`),
  KEY `idx_utility_readings_read_by` (`read_by`),
  CONSTRAINT `fk_utility_readings_meter` FOREIGN KEY (`meter_id`) REFERENCES `utility_meters` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_utility_readings_read_by` FOREIGN KEY (`read_by`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `utility_readings`
--

INSERT INTO `utility_readings` VALUES (1,1,'2026-03-01',1118000.00,1000000.00,118000.00,1444.7000,170474600.00,'2026-03-08 18:57:09',4,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(2,1,'2026-04-01',1233500.00,1118000.00,115500.00,1444.7000,166862850.00,'2026-04-08 18:57:09',4,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(3,1,'2026-05-01',1352300.00,1233500.00,118800.00,1444.7000,171630360.00,'2026-05-08 18:57:09',4,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(4,1,'2026-06-01',1472100.00,1352300.00,119800.00,1444.7000,173075060.00,'2026-06-08 18:57:09',4,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(5,2,'2026-03-01',218500.00,200000.00,18500.00,1444.7000,26726950.00,'2026-03-08 18:57:09',4,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(6,2,'2026-04-01',237200.00,218500.00,18700.00,1444.7000,27015890.00,'2026-04-08 18:57:09',4,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(7,2,'2026-05-01',255600.00,237200.00,18400.00,1444.7000,26582480.00,'2026-05-08 18:57:09',4,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(8,2,'2026-06-01',279600.00,255600.00,24000.00,1444.7000,34672800.00,'2026-06-08 18:57:09',4,NULL,'Lonjakan +30% vs rata-rata 3 bulan - dicurigai AHU lobby tidak efisien','2026-07-08 18:57:09','2026-07-08 18:57:09'),(9,3,'2026-03-01',53850.00,50000.00,3850.00,12550.0000,48467500.00,'2026-03-08 18:57:09',4,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(10,3,'2026-04-01',57760.00,53850.00,3910.00,12550.0000,49220500.00,'2026-04-08 18:57:09',4,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(11,3,'2026-05-01',61590.00,57760.00,3830.00,12550.0000,48216500.00,'2026-05-08 18:57:09',4,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(12,3,'2026-06-01',65530.00,61590.00,3940.00,12550.0000,49597000.00,'2026-06-08 18:57:09',4,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(13,4,'2026-03-01',13150.00,12000.00,1150.00,6800.0000,7820000.00,'2026-03-08 18:57:09',4,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(14,4,'2026-04-01',14280.00,13150.00,1130.00,6800.0000,7684000.00,'2026-04-08 18:57:09',4,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(15,4,'2026-05-01',15420.00,14280.00,1140.00,6800.0000,7752000.00,'2026-05-08 18:57:09',4,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(16,4,'2026-06-01',16600.00,15420.00,1180.00,6800.0000,8024000.00,'2026-06-08 18:57:09',4,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09');

--
-- Table structure for table `vendors`
--

CREATE TABLE `vendors` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned DEFAULT NULL,
  `name` varchar(150) NOT NULL,
  `contact` varchar(150) DEFAULT NULL,
  `phone` varchar(30) DEFAULT NULL,
  `email` varchar(150) DEFAULT NULL,
  `specialty` varchar(150) DEFAULT NULL,
  `rating_avg` decimal(3,2) DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_vendors_property` (`property_id`),
  CONSTRAINT `fk_vendors_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `vendors`
--

INSERT INTO `vendors` VALUES (1,1,'CV Sejahtera Teknik','Pak Joko','0812111222','sales@sejahterateknik.co.id','Genset & Panel Listrik',4.50,'2026-07-08 18:57:08','2026-07-08 18:57:08'),(2,1,'PT Lift Nusantara','Bu Dewi','0812333444','cs@liftnusantara.co.id','Lift & Eskalator',4.20,'2026-07-08 18:57:08','2026-07-08 18:57:08');

--
-- Table structure for table `wo_checklist_results`
--

CREATE TABLE `wo_checklist_results` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `wo_id` bigint(20) unsigned NOT NULL,
  `item_id` int(10) unsigned NOT NULL,
  `result` enum('ok','fail','na') NOT NULL,
  `value_numeric` decimal(12,4) DEFAULT NULL,
  `note` varchar(500) DEFAULT NULL,
  `photo` varchar(255) DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_wo_checklist_results_wo_item` (`wo_id`,`item_id`),
  KEY `idx_wo_checklist_results_item` (`item_id`),
  CONSTRAINT `fk_wcr_item` FOREIGN KEY (`item_id`) REFERENCES `checklist_items` (`id`) ON UPDATE CASCADE,
  CONSTRAINT `fk_wcr_wo` FOREIGN KEY (`wo_id`) REFERENCES `work_orders` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `wo_checklist_results`
--

INSERT INTO `wo_checklist_results` VALUES (1,21,1,'ok',NULL,NULL,NULL,'2026-07-08 20:14:02','2026-07-08 20:14:02'),(2,21,2,'ok',NULL,NULL,NULL,'2026-07-08 20:14:02','2026-07-08 20:14:02'),(3,21,3,'ok',NULL,NULL,NULL,'2026-07-08 20:14:02','2026-07-08 20:14:02'),(4,21,4,'ok',12.6000,'Tegangan aki starter normal (DUMMY demo)',NULL,'2026-07-08 20:14:02','2026-07-08 20:14:02'),(5,21,5,'ok',NULL,NULL,NULL,'2026-07-08 20:14:02','2026-07-08 20:14:02'),(6,22,48,'ok',2.1000,'Suhu cold room 1 dlm rentang aman (DUMMY demo)',NULL,'2026-07-08 20:14:02','2026-07-08 20:14:02'),(7,22,49,'ok',2.4000,'Suhu cold room 2 dlm rentang aman (DUMMY demo)',NULL,'2026-07-08 20:14:02','2026-07-08 20:14:02');

--
-- Table structure for table `wo_costs`
--

CREATE TABLE `wo_costs` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `wo_id` bigint(20) unsigned NOT NULL,
  `kind` enum('part','labor','vendor','material','other') NOT NULL,
  `description` varchar(255) DEFAULT NULL,
  `qty` decimal(12,2) DEFAULT NULL,
  `unit_price` decimal(14,2) DEFAULT NULL,
  `amount` decimal(14,2) NOT NULL,
  `incurred_at` datetime NOT NULL,
  `entered_by` int(10) unsigned DEFAULT NULL,
  `invoice_file` varchar(255) DEFAULT NULL,
  `approved_by` int(10) unsigned DEFAULT NULL,
  `approved_at` datetime DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_wo_costs_wo` (`wo_id`),
  KEY `idx_wo_costs_kind` (`wo_id`,`kind`),
  KEY `idx_wo_costs_entered_by` (`entered_by`),
  KEY `idx_wo_costs_approved_by` (`approved_by`),
  CONSTRAINT `fk_wo_costs_approved_by` FOREIGN KEY (`approved_by`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_wo_costs_entered_by` FOREIGN KEY (`entered_by`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_wo_costs_wo` FOREIGN KEY (`wo_id`) REFERENCES `work_orders` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `wo_costs`
--

INSERT INTO `wo_costs` VALUES (1,1,'part','Filter AC Split x2',2.00,45000.00,90000.00,'2026-07-06 18:57:09',4,NULL,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(2,1,'labor','Jasa teknisi 60 menit',NULL,NULL,50000.00,'2026-07-06 18:57:09',4,NULL,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(3,2,'material','Sealant silikon (beli toko)',1.00,150000.00,150000.00,'2026-07-07 15:57:09',4,NULL,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(4,2,'labor','Jasa teknisi 90 menit',NULL,NULL,75000.00,'2026-07-07 15:57:09',4,NULL,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(5,3,'part','Lampu Emergency LED x1',1.00,120000.00,120000.00,'2026-07-07 17:57:09',4,NULL,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(6,19,'vendor','Servis bulanan lift - invoice vendor',NULL,NULL,2500000.00,'2026-07-05 18:57:09',3,NULL,3,'2026-07-05 20:57:09','2026-07-08 18:57:09','2026-07-08 18:57:09'),(7,25,'vendor','Jasa perbaikan heat exchanger vendor',NULL,NULL,4000000.00,'2026-07-06 17:57:09',3,NULL,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(8,25,'material','Gasket set & material pendukung',1.00,2600000.00,2600000.00,'2026-07-06 17:57:09',3,NULL,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(9,29,'material','Belt washer (beli toko)',1.00,450000.00,450000.00,'2026-07-07 20:57:09',4,NULL,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(10,29,'labor','Jasa teknisi 120 menit',NULL,NULL,100000.00,'2026-07-07 20:57:09',4,NULL,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(11,103,'labor','Jasa IT 45 menit',NULL,NULL,50000.00,'2026-07-07 18:57:09',11,NULL,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(12,112,'material','Kapasitor fan indoor',1.00,175000.00,175000.00,'2026-07-06 08:57:09',7,NULL,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(13,112,'labor','Jasa teknisi 45 menit',NULL,NULL,45000.00,'2026-07-06 08:57:09',7,NULL,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(14,113,'material','Bearing exhaust fan',1.00,250000.00,250000.00,'2026-07-06 14:57:09',8,NULL,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(15,113,'labor','Jasa teknisi 120 menit',NULL,NULL,100000.00,'2026-07-06 14:57:09',8,NULL,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(16,114,'material','Seal pompa sump pit',1.00,150000.00,150000.00,'2026-07-07 15:57:09',9,NULL,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(17,114,'labor','Jasa teknisi 90 menit',NULL,NULL,75000.00,'2026-07-07 15:57:09',9,NULL,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09'),(18,119,'part','Lampu Emergency LED x1',1.00,120000.00,120000.00,'2026-07-08 01:57:09',8,NULL,NULL,NULL,'2026-07-08 18:57:09','2026-07-08 18:57:09');

--
-- Table structure for table `wo_parts`
--

CREATE TABLE `wo_parts` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `wo_id` bigint(20) unsigned NOT NULL,
  `part_id` int(10) unsigned NOT NULL,
  `qty` decimal(12,2) NOT NULL,
  `unit_price_snapshot` decimal(14,2) NOT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  PRIMARY KEY (`id`),
  KEY `idx_wo_parts_wo` (`wo_id`),
  KEY `idx_wo_parts_part` (`part_id`),
  CONSTRAINT `fk_wo_parts_part` FOREIGN KEY (`part_id`) REFERENCES `parts` (`id`) ON UPDATE CASCADE,
  CONSTRAINT `fk_wo_parts_wo` FOREIGN KEY (`wo_id`) REFERENCES `work_orders` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `wo_parts`
--

INSERT INTO `wo_parts` VALUES (1,1,1,2.00,45000.00,'2026-07-08 18:57:09'),(2,3,3,1.00,120000.00,'2026-07-08 18:57:09'),(3,7,1,1.00,45000.00,'2026-07-08 18:57:09'),(4,119,3,1.00,120000.00,'2026-07-08 18:57:09');

--
-- Table structure for table `work_orders`
--

CREATE TABLE `work_orders` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `property_id` int(10) unsigned NOT NULL,
  `wo_number` varchar(40) NOT NULL,
  `type` enum('corrective','preventive','inspection','vendor','project') NOT NULL,
  `source` enum('report','schedule','checklist_fail','manual') NOT NULL,
  `asset_id` int(10) unsigned DEFAULT NULL,
  `location_id` int(10) unsigned DEFAULT NULL,
  `category_id` int(10) unsigned DEFAULT NULL,
  `schedule_id` int(10) unsigned DEFAULT NULL,
  `checklist_version_id` int(10) unsigned DEFAULT NULL,
  `reporter_id` int(10) unsigned DEFAULT NULL,
  `assignee_id` int(10) unsigned DEFAULT NULL,
  `vendor_id` int(10) unsigned DEFAULT NULL,
  `supervisor_id` int(10) unsigned DEFAULT NULL,
  `description` text DEFAULT NULL,
  `priority` enum('low','normal','high','urgent') NOT NULL DEFAULT 'normal',
  `status` enum('scheduled','reported','in_progress','waiting_parts','done','verified','rejected','skipped') NOT NULL DEFAULT 'reported',
  `skip_reason` varchar(255) DEFAULT NULL,
  `repair_note` text DEFAULT NULL,
  `created_at` datetime NOT NULL DEFAULT current_timestamp(),
  `due_date` date DEFAULT NULL,
  `started_at` datetime DEFAULT NULL,
  `done_at` datetime DEFAULT NULL,
  `verified_at` datetime DEFAULT NULL,
  `downtime_start` datetime DEFAULT NULL,
  `downtime_end` datetime DEFAULT NULL,
  `meter_at_service` decimal(14,2) DEFAULT NULL,
  `labor_minutes` int(10) unsigned DEFAULT NULL,
  `cost_parts` decimal(14,2) NOT NULL DEFAULT 0.00,
  `cost_vendor` decimal(14,2) NOT NULL DEFAULT 0.00,
  `cost_other` decimal(14,2) NOT NULL DEFAULT 0.00,
  `updated_at` datetime NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_work_orders_property_number` (`property_id`,`wo_number`),
  KEY `idx_wo_property_status_due` (`property_id`,`status`,`due_date`),
  KEY `idx_wo_property_asset` (`property_id`,`asset_id`),
  KEY `idx_wo_property_location` (`property_id`,`location_id`),
  KEY `idx_wo_property_assignee` (`property_id`,`assignee_id`),
  KEY `idx_wo_property_type` (`property_id`,`type`),
  KEY `idx_wo_schedule` (`schedule_id`),
  KEY `idx_wo_checklist_version` (`checklist_version_id`),
  KEY `idx_wo_vendor` (`vendor_id`),
  KEY `fk_wo_asset` (`asset_id`),
  KEY `fk_wo_location` (`location_id`),
  KEY `fk_wo_category` (`category_id`),
  KEY `fk_wo_reporter` (`reporter_id`),
  KEY `fk_wo_assignee` (`assignee_id`),
  KEY `fk_wo_supervisor` (`supervisor_id`),
  CONSTRAINT `fk_wo_asset` FOREIGN KEY (`asset_id`) REFERENCES `assets` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_wo_assignee` FOREIGN KEY (`assignee_id`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_wo_category` FOREIGN KEY (`category_id`) REFERENCES `asset_categories` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_wo_checklist_version` FOREIGN KEY (`checklist_version_id`) REFERENCES `checklists` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_wo_location` FOREIGN KEY (`location_id`) REFERENCES `locations` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_wo_property` FOREIGN KEY (`property_id`) REFERENCES `properties` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_wo_reporter` FOREIGN KEY (`reporter_id`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_wo_schedule` FOREIGN KEY (`schedule_id`) REFERENCES `pm_schedules` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_wo_supervisor` FOREIGN KEY (`supervisor_id`) REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE,
  CONSTRAINT `fk_wo_vendor` FOREIGN KEY (`vendor_id`) REFERENCES `vendors` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=130 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

--
-- Dumping data for table `work_orders`
--

INSERT INTO `work_orders` VALUES (1,1,'WO-000001','corrective','report',11,1,4,NULL,NULL,5,4,NULL,3,'AC kamar 1201 tidak dingin, hembusan lemah','high','verified',NULL,'Cuci filter & evaporator, ganti filter baru, tekanan freon normal','2026-07-05 18:57:09','2026-07-06','2026-07-06 16:57:09','2026-07-06 18:57:09','2026-07-07 16:57:09',NULL,NULL,NULL,60,90000.00,0.00,50000.00,'2026-07-08 18:57:09'),(2,1,'WO-000002','corrective','report',NULL,4,21,NULL,NULL,5,4,NULL,3,'Sealant wastafel kamar 0801 bocor, air merembes ke kabinet','normal','verified',NULL,'Kupas sealant lama, aplikasi sealant silikon baru, uji rendam OK','2026-07-06 18:57:09','2026-07-07','2026-07-07 12:57:09','2026-07-07 15:57:09','2026-07-07 22:57:09',NULL,NULL,NULL,90,0.00,0.00,225000.00,'2026-07-08 18:57:09'),(3,1,'WO-000003','corrective','report',NULL,7,14,NULL,NULL,5,4,NULL,NULL,'Emergency lamp koridor lantai 12 mati','normal','done',NULL,'Ganti unit emergency lamp LED baru, tes tombol OK','2026-07-07 14:57:09','2026-07-07','2026-07-07 16:57:09','2026-07-07 17:57:09',NULL,NULL,NULL,NULL,30,120000.00,0.00,0.00,'2026-07-08 18:57:09'),(4,1,'WO-000004','corrective','checklist_fail',18,13,26,NULL,NULL,NULL,4,NULL,3,'Suhu freezer kitchen naik ke -12C (ambang -18C) dari checklist HACCP','urgent','done',NULL,'Bersihkan kondensor, ganti karet pintu, suhu kembali -19C stabil','2026-07-07 10:57:09','2026-07-07','2026-07-07 12:57:09','2026-07-07 16:57:09',NULL,'2026-07-07 12:57:09','2026-07-07 16:57:09',NULL,240,0.00,0.00,0.00,'2026-07-08 18:57:09'),(5,1,'WO-000005','corrective','report',12,2,4,NULL,NULL,5,4,NULL,NULL,'AC kamar 1202 menetes air dari unit indoor','normal','in_progress',NULL,NULL,'2026-07-08 14:57:09','2026-07-08','2026-07-08 16:57:09',NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(6,1,'WO-000006','corrective','manual',14,11,8,NULL,NULL,NULL,4,NULL,NULL,'Pompa booster bunyi kasar, dicurigai bearing aus','high','in_progress',NULL,NULL,'2026-07-08 11:57:09','2026-07-08','2026-07-08 13:57:09',NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(7,1,'WO-000007','corrective','report',13,4,4,NULL,NULL,5,4,NULL,NULL,'AC kamar 0801 tidak dingin, filter rusak perlu penggantian','high','waiting_parts',NULL,NULL,'2026-07-07 18:57:09','2026-07-08','2026-07-07 22:57:09',NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(8,1,'WO-000008','corrective','report',NULL,3,8,NULL,NULL,5,NULL,NULL,NULL,'Wastafel kamar 1203 mampet','normal','reported',NULL,NULL,'2026-07-08 15:57:09','2026-07-09',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(9,1,'WO-000009','corrective','report',NULL,2,24,NULL,NULL,5,NULL,NULL,NULL,'TV kamar 1202 tidak ada sinyal (aset belum ter-link)','normal','reported',NULL,NULL,'2026-07-08 16:57:09','2026-07-09',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(10,1,'WO-000010','corrective','report',3,6,11,NULL,NULL,5,NULL,NULL,NULL,'Lift tamu 1 bunyi berdecit dan pintu menutup lambat','urgent','reported',NULL,NULL,'2026-07-07 12:57:09','2026-07-07',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(11,1,'WO-000011','corrective','checklist_fail',17,13,26,NULL,NULL,NULL,4,NULL,NULL,'Suhu cold room naik ke 9C - pendinginan tidak tercapai','urgent','in_progress',NULL,NULL,'2026-07-08 16:57:09','2026-07-08','2026-07-08 17:57:09',NULL,NULL,'2026-07-08 17:27:09',NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(12,1,'WO-000012','preventive','schedule',11,1,4,3,2,NULL,4,NULL,NULL,'PM bulanan AC split kamar 1201','normal','scheduled',NULL,NULL,'2026-07-05 18:57:09','2026-07-08',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(13,1,'WO-000013','preventive','schedule',12,2,4,3,2,NULL,4,NULL,NULL,'PM bulanan AC split kamar 1202','normal','scheduled',NULL,NULL,'2026-07-05 18:57:09','2026-07-08',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(14,1,'WO-000014','preventive','schedule',1,12,5,2,1,NULL,4,NULL,NULL,'PM mingguan genset','high','scheduled',NULL,NULL,'2026-07-05 18:57:09','2026-07-08',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(15,1,'WO-000015','preventive','schedule',19,8,15,NULL,7,NULL,4,NULL,NULL,'Checklist harian kolam renang & jacuzzi','normal','scheduled',NULL,NULL,'2026-07-08 12:57:09','2026-07-08',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(16,1,'WO-000016','preventive','schedule',16,15,22,NULL,6,NULL,4,NULL,NULL,'PM bulanan server room & backup','normal','scheduled',NULL,NULL,'2026-07-05 18:57:09','2026-07-08',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(17,1,'WO-000017','preventive','schedule',NULL,6,14,NULL,8,NULL,4,NULL,NULL,'Rute bulanan fire safety area publik','high','scheduled',NULL,NULL,'2026-07-04 18:57:09','2026-07-07',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(18,1,'WO-000018','preventive','schedule',9,11,2,NULL,10,NULL,4,NULL,NULL,'PM mingguan cooling tower','normal','scheduled',NULL,NULL,'2026-07-04 18:57:09','2026-07-07',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(19,1,'WO-000019','vendor','manual',3,6,11,NULL,NULL,NULL,NULL,2,3,'Servis bulanan lift tamu oleh vendor (kontrak)','normal','done',NULL,'Servis rutin vendor: pelumasan rel, kalibrasi pintu. Berita acara diterima, pendamping internal hadir','2026-07-04 18:57:09','2026-07-05','2026-07-05 14:57:09','2026-07-05 16:57:09',NULL,NULL,NULL,NULL,NULL,0.00,2500000.00,0.00,'2026-07-08 18:57:09'),(20,1,'WO-000020','preventive','schedule',NULL,1,NULL,4,3,NULL,4,NULL,NULL,'PPM kamar 1201 (30 titik)','normal','skipped','Kamar occupied - tamu long stay, reschedule minggu depan',NULL,'2026-07-05 18:57:09','2026-07-06',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(21,1,'WO-000021','preventive','schedule',1,12,5,2,1,NULL,4,NULL,3,'PM mingguan genset','high','verified',NULL,'Semua parameter normal, test run 12 menit OK, aki 12.7V','2026-06-28 18:57:09','2026-07-01','2026-07-01 16:57:09','2026-07-01 18:57:09','2026-07-02 18:57:09',NULL,NULL,4805.00,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(22,1,'WO-000022','preventive','schedule',NULL,13,26,NULL,4,NULL,4,NULL,3,'HACCP suhu harian (shift pagi)','normal','verified',NULL,'Semua suhu dalam ambang kecuali freezer 1 (ditindaklanjuti WO-000004)','2026-07-07 12:57:09','2026-07-07','2026-07-07 14:57:09','2026-07-07 16:57:09','2026-07-07 18:57:09',NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(23,1,'WO-000023','preventive','schedule',15,15,23,NULL,5,NULL,4,NULL,NULL,'PM bulanan CCTV & access control','normal','done',NULL,'Semua kamera live, playback OK, retensi 32 hari, 3 kamar baterai lock < 20% dicatat','2026-07-03 18:57:09','2026-07-06','2026-07-06 12:57:09','2026-07-06 14:57:09',NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(24,1,'WO-000024','preventive','schedule',2,12,6,NULL,11,NULL,4,NULL,3,'PM bulanan panel listrik & trafo','high','verified',NULL,'Beban fasa seimbang (ketimpangan 8%), suhu ruang 29C, tidak ada bau abnormal','2026-06-22 18:57:09','2026-06-24','2026-06-24 16:57:09','2026-06-24 18:57:09','2026-06-25 18:57:09',NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(25,1,'WO-000025','corrective','manual',7,11,9,NULL,NULL,NULL,NULL,1,3,'Boiler water heater bocor pada heat exchanger','high','done',NULL,'Perbaikan heat exchanger oleh vendor, penggantian gasket set lengkap','2026-07-04 18:57:09','2026-07-06','2026-07-06 06:57:09','2026-07-06 16:57:09',NULL,NULL,NULL,NULL,NULL,0.00,4000000.00,2600000.00,'2026-07-08 18:57:09'),(26,1,'WO-000026','corrective','report',11,1,4,NULL,NULL,5,NULL,NULL,NULL,'AC kamar 1201 tidak dingin (laporan kedua)','normal','rejected','Duplikat dari WO-000001',NULL,'2026-07-05 18:57:09','2026-07-06',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(27,1,'WO-000027','preventive','schedule',NULL,2,NULL,4,3,NULL,4,NULL,NULL,'PPM kamar 1202 (30 titik)','normal','scheduled',NULL,NULL,'2026-07-07 18:57:09','2026-07-15',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(28,1,'WO-000028','preventive','schedule',10,7,3,NULL,NULL,NULL,4,NULL,NULL,'PM bulanan AHU lantai 12','normal','scheduled',NULL,NULL,'2026-07-07 18:57:09','2026-07-11',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(29,1,'WO-000029','corrective','report',20,14,16,NULL,NULL,5,4,NULL,NULL,'Belt washer laundry putus','high','done',NULL,'Ganti belt baru (beli toko), alignment pulley, uji jalan 2 siklus OK','2026-07-07 16:57:09','2026-07-07','2026-07-07 18:57:09','2026-07-07 20:57:09',NULL,NULL,NULL,NULL,120,0.00,0.00,550000.00,'2026-07-08 18:57:09'),(30,1,'WO-000030','preventive','schedule',21,16,30,NULL,12,NULL,4,NULL,NULL,'PM bulanan kendaraan operasional (Avanza)','normal','scheduled',NULL,NULL,'2026-07-05 18:57:09','2026-07-08',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(101,1,'WO-000101','corrective','report',94,24,22,NULL,NULL,5,10,NULL,NULL,'AP lantai 3 mati - tamu komplain Wi-Fi koridor','high','in_progress',NULL,NULL,'2026-07-08 15:57:09','2026-07-08','2026-07-08 17:57:09',NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(102,1,'WO-000102','corrective','report',92,25,23,NULL,NULL,5,NULL,NULL,NULL,'CCTV basement gambar blur/berembun','normal','reported',NULL,NULL,'2026-07-08 13:57:09','2026-07-09',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(103,1,'WO-000103','corrective','report',NULL,21,24,NULL,NULL,5,11,NULL,NULL,'Telepon kamar 0805 mati (PABX)','normal','done',NULL,'Re-punch kabel ekstensi di MDF, tes panggilan keluar-masuk OK','2026-07-07 12:57:09','2026-07-07','2026-07-07 16:57:09','2026-07-07 18:57:09',NULL,NULL,NULL,NULL,45,0.00,0.00,50000.00,'2026-07-08 18:57:09'),(104,1,'WO-000104','corrective','report',NULL,22,24,NULL,NULL,5,NULL,NULL,NULL,'Key card reader kamar 1207 error - tamu tidak bisa masuk','urgent','reported',NULL,NULL,'2026-07-08 10:57:09','2026-07-08',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(105,1,'WO-000105','corrective','report',NULL,18,18,NULL,NULL,5,12,NULL,NULL,'Cat koridor lantai 5 mengelupas area depan lift','normal','in_progress',NULL,NULL,'2026-07-07 18:57:09','2026-07-08','2026-07-08 14:57:09',NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(106,1,'WO-000106','corrective','report',NULL,20,21,NULL,NULL,5,NULL,NULL,NULL,'Sealant kamar mandi 0803 berjamur','normal','reported',NULL,NULL,'2026-07-08 12:57:09','2026-07-10',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(107,1,'WO-000107','preventive','manual',NULL,6,20,NULL,NULL,NULL,13,NULL,NULL,'Poles marmer lobby (3-bulanan)','normal','scheduled',NULL,NULL,'2026-07-07 18:57:09','2026-07-11',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(108,1,'WO-000108','corrective','report',NULL,23,21,NULL,NULL,5,13,NULL,NULL,'Waterproofing balkon kamar 1501 rembes saat hujan','high','waiting_parts',NULL,NULL,'2026-07-06 18:57:09','2026-07-08','2026-07-07 18:57:09',NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(109,1,'WO-000109','corrective','report',61,6,4,NULL,NULL,5,7,NULL,NULL,'AC cassette lobby 1 kurang dingin','normal','in_progress',NULL,NULL,'2026-07-08 13:57:09','2026-07-08','2026-07-08 16:57:09',NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(110,1,'WO-000110','preventive','schedule',62,6,4,3,2,NULL,7,NULL,NULL,'PM bulanan AC cassette lobby 2','normal','scheduled',NULL,NULL,'2026-07-05 18:57:09','2026-07-08',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(111,1,'WO-000111','preventive','schedule',78,15,4,3,2,NULL,8,NULL,NULL,'PM bulanan AC presisi ruang server','high','scheduled',NULL,NULL,'2026-07-05 18:57:09','2026-07-08',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(112,1,'WO-000112','corrective','report',11,1,4,NULL,NULL,5,7,NULL,3,'AC kamar 1201 bunyi berisik dari unit indoor','normal','verified',NULL,'Ganti kapasitor fan indoor, bersihkan blower, bunyi hilang','2026-07-05 18:57:09','2026-07-06','2026-07-06 06:57:09','2026-07-06 08:57:09','2026-07-07 12:57:09',NULL,NULL,NULL,45,0.00,0.00,220000.00,'2026-07-08 18:57:09'),(113,1,'WO-000113','corrective','manual',85,17,35,NULL,NULL,NULL,8,NULL,3,'Exhaust fan rooftop bunyi kasar','normal','verified',NULL,'Ganti bearing, balancing impeller, vibrasi normal kembali','2026-07-05 18:57:09','2026-07-06','2026-07-06 11:57:09','2026-07-06 14:57:09','2026-07-07 14:57:09',NULL,NULL,NULL,120,0.00,0.00,350000.00,'2026-07-08 18:57:09'),(114,1,'WO-000114','corrective','manual',93,25,8,NULL,NULL,NULL,9,NULL,3,'Pompa sump pit basement macet','high','verified',NULL,'Bersihkan impeller dari lumpur, ganti seal, tes float switch OK','2026-07-06 18:57:09','2026-07-07','2026-07-07 12:57:09','2026-07-07 15:57:09','2026-07-07 22:57:09',NULL,NULL,NULL,90,0.00,0.00,225000.00,'2026-07-08 18:57:09'),(115,1,'WO-000115','preventive','schedule',66,8,15,12,NULL,NULL,9,NULL,NULL,'PM mingguan pompa sirkulasi kolam 2','normal','scheduled',NULL,NULL,'2026-07-06 18:57:09','2026-07-08',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(116,1,'WO-000116','preventive','manual',86,9,29,NULL,NULL,NULL,7,NULL,NULL,'PM bulanan treadmill 1','normal','scheduled',NULL,NULL,'2026-07-06 18:57:09','2026-07-08',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(117,1,'WO-000117','preventive','manual',92,25,23,NULL,5,NULL,11,NULL,NULL,'PM bulanan CCTV basement','normal','scheduled',NULL,NULL,'2026-07-06 18:57:09','2026-07-08',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(118,1,'WO-000118','corrective','report',NULL,21,8,NULL,NULL,5,9,NULL,NULL,'Kran air panas kamar 0805 menetes','normal','in_progress',NULL,NULL,'2026-07-08 12:57:09','2026-07-08','2026-07-08 15:57:09',NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(119,1,'WO-000119','corrective','report',NULL,19,14,NULL,NULL,5,8,NULL,NULL,'Emergency lamp koridor lantai 8 mati','normal','done',NULL,'Ganti unit emergency lamp LED, tes tombol OK','2026-07-07 22:57:09','2026-07-07','2026-07-08 00:57:09','2026-07-08 01:57:09',NULL,NULL,NULL,NULL,30,120000.00,0.00,0.00,'2026-07-08 18:57:09'),(120,1,'WO-000120','corrective','report',70,13,26,NULL,NULL,5,NULL,NULL,NULL,'Ice maker produksi es lambat','high','reported',NULL,NULL,'2026-07-08 14:57:09','2026-07-09',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(121,1,'WO-000121','corrective','report',87,9,29,NULL,NULL,5,NULL,NULL,NULL,'Treadmill 2 belt selip saat dipakai','normal','reported',NULL,NULL,'2026-07-08 11:57:09','2026-07-09',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(122,1,'WO-000122','corrective','manual',68,8,15,NULL,NULL,NULL,9,NULL,NULL,'Dosing pump chlorine tidak menyedot','high','in_progress',NULL,NULL,'2026-07-08 16:57:09','2026-07-08','2026-07-08 17:57:09',NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(123,1,'WO-000123','corrective','manual',71,13,27,NULL,NULL,NULL,8,NULL,NULL,'Combi oven error E13 - burner tidak menyala','urgent','in_progress',NULL,NULL,'2026-07-08 17:27:09','2026-07-08','2026-07-08 18:27:09',NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(124,1,'WO-000124','preventive','schedule',NULL,13,26,11,4,NULL,4,NULL,NULL,'HACCP suhu harian dapur (besok pagi)','high','scheduled',NULL,NULL,'2026-07-08 12:57:09','2026-07-09',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09'),(125,1,'WO-000125','preventive','schedule',66,8,15,12,NULL,NULL,9,NULL,NULL,'PM mingguan pompa sirkulasi kolam 2 (minggu depan)','normal','scheduled',NULL,NULL,'2026-07-08 12:57:09','2026-07-15',NULL,NULL,NULL,NULL,NULL,NULL,NULL,0.00,0.00,0.00,'2026-07-08 18:57:09');

--
-- Dumping events for database 'sanggraloka_one'
--

--
-- Dumping routines for database 'sanggraloka_one'
--


