mdb = $mdb; else { global $mdb; $this -> mdb = $mdb; } } public function getClientsWithUnsettledTasks() { $clients = $this -> mdb -> select( 'crm_client', '*', [ 'ORDER' => [ 'firm' => 'ASC' ] ] ); $work_time = []; if ( !is_array( $clients ) or !count( $clients ) ) return $work_time; foreach ( $clients as $client ) { $task_rows = $this -> getClientTaskRows( (int)$client['id'] ); $client['tasks'] = self::buildClientTasksByMonth( $task_rows, function( $task_id, $month ) { return (int)$this -> getTaskTotalTimeByMonth( $task_id, $month ); } ); if ( is_array( $client['tasks'] ) and count( $client['tasks'] ) ) krsort( $client['tasks'] ); $work_time[] = $client; } return $work_time; } public static function buildClientTasksByMonth( array $task_rows, callable $task_time_provider ) { $tasks = []; $seen = []; foreach ( $task_rows as $row ) { if ( !isset( $row['month'] ) or !isset( $row['id'] ) ) continue; $month = (string)$row['month']; $task_id = (int)$row['id']; $dedupe_key = $task_id . ':' . $month; if ( isset( $seen[$dedupe_key] ) ) continue; $seen[$dedupe_key] = true; $tasks[ $month ][] = [ 'id' => $task_id, 'name' => $row['name'], 'pay_rate' => $row['pay_rate'], 'time' => (int)call_user_func( $task_time_provider, $task_id, $month ) ]; } return $tasks; } private function getClientTaskRows( $client_id ) { $statuses = implode( ',', self::UNSETTLED_TASK_STATUSES ); return $this -> mdb -> query( 'SELECT DISTINCT ' . 't.id, t.name, t.pay_rate, DATE_FORMAT(tw.date_end, \'%Y-%m\') AS month ' . 'FROM tasks AS t ' . 'INNER JOIN tasks_work AS tw ON t.id = tw.task_id ' . 'WHERE t.status IN (' . $statuses . ') ' . 'AND t.client_id = ' . (int)$client_id . ' ' . 'AND tw.deleted = 0 ' . 'AND tw.date_end IS NOT NULL ' . 'ORDER BY month DESC, t.date_add DESC' ) -> fetchAll( \PDO::FETCH_ASSOC ); } public static function getUnsettledTaskStatuses() { return self::UNSETTLED_TASK_STATUSES; } private function getTaskTotalTimeByMonth( $task_id, $month ) { $seconds = 0; $date_from = $month . '-01 00:00:00'; $date_to = $month . '-' . date( 't', strtotime( $month ) ) . ' 23:59:59'; $rows = $this -> mdb -> select( 'tasks_work', [ 'date_start', 'date_end' ], [ 'AND' => [ 'deleted' => 0, 'task_id' => (int)$task_id, 'date_end[>=]' => $date_from, 'date_end[<=]' => $date_to ], 'ORDER' => [ 'id' => 'ASC' ] ] ); if ( !is_array( $rows ) or !count( $rows ) ) return 0; foreach ( $rows as $row ) { if ( !$row['date_end'] ) $row['date_end'] = date( 'Y-m-d H:i:s' ); $seconds += strtotime( $row['date_end'] ) - strtotime( $row['date_start'] ); } return $seconds; } }