diff --git a/source/packages/com_mokosuitefield/admin/src/Model/DispatchModel.php b/source/packages/com_mokosuitefield/admin/src/Model/DispatchModel.php new file mode 100644 index 0000000..a6c00a1 --- /dev/null +++ b/source/packages/com_mokosuitefield/admin/src/Model/DispatchModel.php @@ -0,0 +1,37 @@ +getDatabase(); + $db->setQuery($db->getQuery(true) + ->select('t.id AS tech_id, cd.name AS tech_name, t.trade, t.status AS tech_status') + ->select('(SELECT COUNT(*) FROM #__mokosuitefield_work_orders wo WHERE wo.technician_id = t.id AND wo.scheduled_date = CURDATE() AND wo.status NOT IN (' . $db->quote('completed') . ',' . $db->quote('cancelled') . ')) AS pending_jobs') + ->select('(SELECT COUNT(*) FROM #__mokosuitefield_work_orders wo WHERE wo.technician_id = t.id AND wo.scheduled_date = CURDATE() AND wo.status = ' . $db->quote('completed') . ') AS completed_jobs') + ->from($db->quoteName('#__mokosuitefield_technicians', 't')) + ->join('LEFT', $db->quoteName('#__contact_details', 'cd') . ' ON cd.id = t.contact_id') + ->where($db->quoteName('t.status') . ' != ' . $db->quote('inactive')) + ->order('cd.name ASC')); + return $db->loadObjectList() ?: []; + } + + public function getGpsLog(int $techId, string $date = ''): array + { + $db = $this->getDatabase(); + $date = $date ?: date('Y-m-d'); + + $db->setQuery($db->getQuery(true) + ->select('*') + ->from('#__mokosuitefield_dispatch_log') + ->where('technician_id = ' . $techId) + ->where('DATE(recorded_at) = ' . $db->quote($date)) + ->order('recorded_at ASC')); + return $db->loadObjectList() ?: []; + } +} diff --git a/source/packages/com_mokosuitefield/admin/src/Model/EquipmentModel.php b/source/packages/com_mokosuitefield/admin/src/Model/EquipmentModel.php new file mode 100644 index 0000000..2f244ad --- /dev/null +++ b/source/packages/com_mokosuitefield/admin/src/Model/EquipmentModel.php @@ -0,0 +1,29 @@ +getDatabase(); + $query = $db->getQuery(true) + ->select('eq.*, loc.name AS location_name, loc.address, cd.name AS customer_name') + ->from($db->quoteName('#__mokosuitefield_equipment', 'eq')) + ->join('LEFT', $db->quoteName('#__mokosuitefield_locations', 'loc') . ' ON loc.id = eq.location_id') + ->join('LEFT', $db->quoteName('#__contact_details', 'cd') . ' ON cd.id = eq.contact_id') + ->order('eq.name ASC'); + + if ($type) $query->where($db->quoteName('eq.type') . ' = ' . $db->quote($type)); + if ($status) $query->where($db->quoteName('eq.status') . ' = ' . $db->quote($status)); + if ($locationId) $query->where('eq.location_id = ' . $locationId); + if ($search) $query->where('(' . $db->quoteName('eq.name') . ' LIKE ' . $db->quote('%' . $search . '%') + . ' OR ' . $db->quoteName('eq.serial_number') . ' LIKE ' . $db->quote('%' . $search . '%') . ')'); + + $db->setQuery($query, 0, $limit); + return $db->loadObjectList() ?: []; + } +} diff --git a/source/packages/com_mokosuitefield/admin/src/Model/EstimatesModel.php b/source/packages/com_mokosuitefield/admin/src/Model/EstimatesModel.php new file mode 100644 index 0000000..7332a46 --- /dev/null +++ b/source/packages/com_mokosuitefield/admin/src/Model/EstimatesModel.php @@ -0,0 +1,28 @@ +getDatabase(); + $query = $db->getQuery(true) + ->select('e.*, cd.name AS customer_name, loc.address') + ->from($db->quoteName('#__mokosuitefield_estimates', 'e')) + ->join('LEFT', $db->quoteName('#__contact_details', 'cd') . ' ON cd.id = e.contact_id') + ->join('LEFT', $db->quoteName('#__mokosuitefield_locations', 'loc') . ' ON loc.id = e.location_id') + ->order('e.created DESC'); + + if ($status) $query->where($db->quoteName('e.status') . ' = ' . $db->quote($status)); + if ($techId) $query->where('e.technician_id = ' . $techId); + if ($search) $query->where('(' . $db->quoteName('cd.name') . ' LIKE ' . $db->quote('%' . $search . '%') + . ' OR ' . $db->quoteName('e.estimate_number') . ' LIKE ' . $db->quote('%' . $search . '%') . ')'); + + $db->setQuery($query, 0, $limit); + return $db->loadObjectList() ?: []; + } +} diff --git a/source/packages/com_mokosuitefield/admin/src/Model/ServiceAgreementsModel.php b/source/packages/com_mokosuitefield/admin/src/Model/ServiceAgreementsModel.php new file mode 100644 index 0000000..c01a746 --- /dev/null +++ b/source/packages/com_mokosuitefield/admin/src/Model/ServiceAgreementsModel.php @@ -0,0 +1,39 @@ +getDatabase(); + $query = $db->getQuery(true) + ->select('sa.*, cd.name AS customer_name, loc.address') + ->from($db->quoteName('#__mokosuitefield_service_agreements', 'sa')) + ->join('LEFT', $db->quoteName('#__contact_details', 'cd') . ' ON cd.id = sa.contact_id') + ->join('LEFT', $db->quoteName('#__mokosuitefield_locations', 'loc') . ' ON loc.id = sa.location_id') + ->order('sa.end_date ASC'); + + if ($status) $query->where($db->quoteName('sa.status') . ' = ' . $db->quote($status)); + if ($search) $query->where($db->quoteName('cd.name') . ' LIKE ' . $db->quote('%' . $search . '%')); + + $db->setQuery($query, 0, $limit); + return $db->loadObjectList() ?: []; + } + + public function getExpiringSoon(int $days = 30): array + { + $db = $this->getDatabase(); + $db->setQuery($db->getQuery(true) + ->select('sa.*, cd.name AS customer_name') + ->from($db->quoteName('#__mokosuitefield_service_agreements', 'sa')) + ->join('LEFT', $db->quoteName('#__contact_details', 'cd') . ' ON cd.id = sa.contact_id') + ->where($db->quoteName('sa.status') . ' = ' . $db->quote('active')) + ->where($db->quoteName('sa.end_date') . ' BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL ' . $days . ' DAY)') + ->order('sa.end_date ASC')); + return $db->loadObjectList() ?: []; + } +} diff --git a/source/packages/com_mokosuitefield/admin/src/Model/TechniciansModel.php b/source/packages/com_mokosuitefield/admin/src/Model/TechniciansModel.php new file mode 100644 index 0000000..6a32578 --- /dev/null +++ b/source/packages/com_mokosuitefield/admin/src/Model/TechniciansModel.php @@ -0,0 +1,27 @@ +getDatabase(); + $query = $db->getQuery(true) + ->select('t.*, cd.name AS tech_name, cd.email_to, cd.telephone') + ->select('(SELECT COUNT(*) FROM #__mokosuitefield_work_orders wo WHERE wo.technician_id = t.id AND wo.status IN (' . $db->quote('dispatched') . ',' . $db->quote('in_progress') . ')) AS active_jobs') + ->from($db->quoteName('#__mokosuitefield_technicians', 't')) + ->join('LEFT', $db->quoteName('#__contact_details', 'cd') . ' ON cd.id = t.contact_id') + ->order('cd.name ASC'); + + if ($status) $query->where($db->quoteName('t.status') . ' = ' . $db->quote($status)); + if ($trade) $query->where($db->quoteName('t.trade') . ' = ' . $db->quote($trade)); + if ($search) $query->where($db->quoteName('cd.name') . ' LIKE ' . $db->quote('%' . $search . '%')); + + $db->setQuery($query, 0, $limit); + return $db->loadObjectList() ?: []; + } +} diff --git a/source/packages/com_mokosuitefield/admin/src/Model/VehiclesModel.php b/source/packages/com_mokosuitefield/admin/src/Model/VehiclesModel.php new file mode 100644 index 0000000..0429c3a --- /dev/null +++ b/source/packages/com_mokosuitefield/admin/src/Model/VehiclesModel.php @@ -0,0 +1,26 @@ +getDatabase(); + $query = $db->getQuery(true) + ->select('v.*, cd.name AS tech_name') + ->from($db->quoteName('#__mokosuitefield_vehicles', 'v')) + ->join('LEFT', $db->quoteName('#__mokosuitefield_technicians', 't') . ' ON t.id = v.technician_id') + ->join('LEFT', $db->quoteName('#__contact_details', 'cd') . ' ON cd.id = t.contact_id') + ->order('v.vehicle_name ASC'); + + if ($status) $query->where($db->quoteName('v.status') . ' = ' . $db->quote($status)); + if ($techId) $query->where('v.technician_id = ' . $techId); + + $db->setQuery($query, 0, $limit); + return $db->loadObjectList() ?: []; + } +} diff --git a/source/packages/com_mokosuitefield/admin/src/Model/WorkOrdersModel.php b/source/packages/com_mokosuitefield/admin/src/Model/WorkOrdersModel.php new file mode 100644 index 0000000..6d34474 --- /dev/null +++ b/source/packages/com_mokosuitefield/admin/src/Model/WorkOrdersModel.php @@ -0,0 +1,61 @@ +getDatabase(); + $query = $db->getQuery(true) + ->select('wo.*, cd.name AS customer_name, loc.address, loc.city, loc.state, loc.zip') + ->select('t_cd.name AS tech_name') + ->from($db->quoteName('#__mokosuitefield_work_orders', 'wo')) + ->join('LEFT', $db->quoteName('#__contact_details', 'cd') . ' ON cd.id = wo.contact_id') + ->join('LEFT', $db->quoteName('#__mokosuitefield_locations', 'loc') . ' ON loc.id = wo.location_id') + ->join('LEFT', $db->quoteName('#__mokosuitefield_technicians', 't') . ' ON t.id = wo.technician_id') + ->join('LEFT', $db->quoteName('#__contact_details', 't_cd') . ' ON t_cd.id = t.contact_id') + ->order('wo.scheduled_date DESC, wo.priority DESC'); + + if ($status) $query->where($db->quoteName('wo.status') . ' = ' . $db->quote($status)); + if ($trade) $query->where($db->quoteName('wo.trade') . ' = ' . $db->quote($trade)); + if ($techId) $query->where('wo.technician_id = ' . $techId); + if ($date) $query->where('wo.scheduled_date = ' . $db->quote($date)); + if ($search) { + $query->where('(' . $db->quoteName('wo.wo_number') . ' LIKE ' . $db->quote('%' . $search . '%') + . ' OR ' . $db->quoteName('wo.description') . ' LIKE ' . $db->quote('%' . $search . '%') + . ' OR ' . $db->quoteName('cd.name') . ' LIKE ' . $db->quote('%' . $search . '%') . ')'); + } + + $db->setQuery($query, $offset, $limit); + return $db->loadObjectList() ?: []; + } + + public function getWorkOrder(int $id): ?object + { + $db = $this->getDatabase(); + $db->setQuery($db->getQuery(true) + ->select('wo.*, cd.name AS customer_name, loc.*, t_cd.name AS tech_name') + ->from($db->quoteName('#__mokosuitefield_work_orders', 'wo')) + ->join('LEFT', $db->quoteName('#__contact_details', 'cd') . ' ON cd.id = wo.contact_id') + ->join('LEFT', $db->quoteName('#__mokosuitefield_locations', 'loc') . ' ON loc.id = wo.location_id') + ->join('LEFT', $db->quoteName('#__mokosuitefield_technicians', 't') . ' ON t.id = wo.technician_id') + ->join('LEFT', $db->quoteName('#__contact_details', 't_cd') . ' ON t_cd.id = t.contact_id') + ->where('wo.id = ' . $id)); + return $db->loadObject(); + } + + public function getStatusCounts(): object + { + $db = $this->getDatabase(); + $db->setQuery($db->getQuery(true) + ->select('status, COUNT(*) AS cnt') + ->from('#__mokosuitefield_work_orders') + ->group('status')); + $rows = $db->loadObjectList('status') ?: []; + return (object) array_map(fn($r) => (int) $r->cnt, (array) $rows); + } +}