1<?php
2
3/**
4 * OrangeHRM is a comprehensive Human Resource Management (HRM) System that captures
5 * all the essential functionalities required for any enterprise.
6 * Copyright (C) 2006 OrangeHRM Inc., http://www.orangehrm.com
7 *
8 * OrangeHRM is free software; you can redistribute it and/or modify it under the terms of
9 * the GNU General Public License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * OrangeHRM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with this program;
17 * if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA  02110-1301, USA
19 */
20
21class EmployeeDirectoryDao extends BaseDao{
22
23    /**
24     * Mapping of search field names to database fields
25     * @var array
26     */
27    protected static $searchMapping = array(
28            'id' => 'e.employee_id',
29            'employee_name' => 'concat_ws(\' \', e.emp_firstname,e.emp_middle_name,e.emp_lastname)',
30            'middleName' => 'e.emp_middle_name',
31            'lastName' => 'e.emp_lastName',
32            'job_title' => 'j.job_title',
33        'emp_work_telephone' => 'e.emp_work_telephone',
34        'emp_work_email' => 'e.emp_work_email',
35            'employee_status' => 'es.estat_name',
36            'sub_unit' => 'cs.name',
37            'termination' => 'e.termination_id',
38            'location' => 'l.location_id',
39            'employee_id_list' => 'e.emp_number',
40    );
41
42    /**
43     * Mapping of sort field names to database fields
44     * @var array
45     */
46    protected static $sortMapping = array(
47            'firstName' => 'e.emp_firstname',
48            'middleName' => 'e.emp_middle_name',
49            'firstMiddleName' => array('e.emp_firstname','e.emp_middle_name'),
50            'lastName' => 'e.emp_lastName',
51            'fullName' => array('e.emp_firstname', 'e.emp_middle_name', 'e.emp_lastName'),
52            'jobTitle' => 'j.job_title',
53            'empLocation' => 'loc.name',
54            'employeeStatus' => 'es.name',
55            'subDivision' => 'cs.name',
56    );
57
58    /**
59     * Get employee list after sorting and filtering using given parameters.
60     *
61     * @param array $sortField
62     * @param $sortOrder
63     * @param $filters
64     * @return array
65     */
66    public function getSearchEmployeeCount(array $filters = null) {
67
68        $select = '';
69        $query = '';
70        $bindParams = array();
71        $orderBy = '';
72
73        $this->_getEmployeeListQuery($select, $query, $bindParams, $orderBy, null, null, $filters);
74
75        $countQuery = 'SELECT COUNT(*) FROM (' . $select . ' ' . $query . ' ) AS countqry';
76
77        if (sfConfig::get('sf_logging_enabled')) {
78            $msg = 'COUNT: ' . $countQuery;
79            if (count($bindParams) > 0 ) {
80                $msg .=  ' (' . implode(',', $bindParams) . ')';
81            }
82            sfContext::getInstance()->getLogger()->info($msg);
83        }
84
85        $conn = Doctrine_Manager::connection();
86        $statement = $conn->prepare($countQuery);
87        $result = $statement->execute($bindParams);
88        $count = 0;
89        if ($result) {
90            if ($statement->rowCount() > 0) {
91                $count = $statement->fetchColumn();
92            }
93        }
94
95        return $count;
96    }
97
98       /**
99     * Get SQL Query which can be used fetch employee list with the given
100     * sorting and filtering options
101     *
102     * @param &$select select part of query
103     * @param &$query  query
104     * @param &$bindParams bind params for query
105     * @param &$orderBy order by part of query
106     * @param array $sortField
107     * @param $sortOrder
108     * @param $filters
109     * @return none
110     */
111    private function _getEmployeeListQuery(&$select, &$query, array &$bindParams, &$orderBy,
112            $sortField = null, $sortOrder = null, array $filters = null) {
113
114        $searchByTerminated = EmployeeSearchForm::WITHOUT_TERMINATED;
115
116        /*
117	     * Using direct SQL since it is difficult to use Doctrine DQL or RawSQL to get an efficient
118	     * query taht searches the company structure tree and supervisors.
119        */
120
121
122
123        $select = 'SELECT e.emp_number AS empNumber, e.employee_id AS employeeId, ' .
124                'e.emp_firstname AS firstName, e.emp_lastname AS lastName, ' .
125                'e.emp_middle_name AS middleName, e.termination_id AS terminationId, ' .
126                'cs.name AS subDivision, cs.id AS subDivisionId,' .
127                'j.job_title AS jobTitle, j.id AS jobTitleId, j.is_deleted AS isDeleted, ' .
128                'es.name AS employeeStatus, es.id AS employeeStatusId, '.
129                'e.emp_hm_telephone,  e.emp_mobile, e.emp_work_telephone, e.emp_work_email, e.emp_oth_email, '.
130
131                'GROUP_CONCAT(DISTINCT loc.id, \'##\',loc.name) AS locationIds';
132
133
134        $query = 'FROM hs_hr_employee e ' .
135                '  LEFT JOIN ohrm_subunit cs ON cs.id = e.work_station ' .
136                '  LEFT JOIN ohrm_job_title j on j.id = e.job_title_code ' .
137                '  LEFT JOIN ohrm_employment_status es on e.emp_status = es.id ' .
138                '  LEFT JOIN hs_hr_emp_locations l ON l.emp_number = e.emp_number ' .
139                '  LEFT JOIN ohrm_location loc ON l.location_id = loc.id';
140
141        /* search filters */
142        $conditions = array();
143
144        if (!empty($filters)) {
145
146            $filterCount = 0;
147
148            foreach ($filters as $searchField=>$searchBy ) {
149                if (!empty($searchField) && !empty($searchBy)
150                        && array_key_exists($searchField, self::$searchMapping) ) {
151                    $field = self::$searchMapping[$searchField];
152
153                    if ($searchField == 'sub_unit') {
154
155                        /*
156                         * Not efficient if searching substations by more than one value, but
157                         * we only have the facility to search by one value in the UI.
158                        */
159                        $conditions[] =  'e.work_station IN (SELECT n.id FROM ohrm_subunit n ' .
160                                'INNER JOIN ohrm_subunit p WHERE n.lft >= p.lft ' .
161                                'AND n.rgt <= p.rgt AND p.id = ? )';
162                        $bindParams[] = $searchBy;
163                    } else if ($searchField == 'id') {
164                        $conditions[] = ' e.employee_id LIKE ? ';
165                        $bindParams[] = $searchBy;
166                    } else if ($searchField == 'job_title') {
167                        $conditions[] = ' j.id = ? ';
168                        $bindParams[] = $searchBy;
169                    } else if ($searchField == 'employee_status') {
170                        $conditions[] = ' es.id = ? ';
171                        $bindParams[] = $searchBy;
172                    } else if ($searchField == 'employee_id_list') {
173                        $conditions[] = ' e.emp_number IN (' . implode(',', $searchBy) . ') ';
174                    } else if ($searchField == 'employee_name') {
175                        $conditions[] = $field . ' LIKE ? ';
176                        // Replace multiple spaces in string with wildcards
177                        $value = preg_replace('!\s+!', '%', $searchBy);
178                        $bindParams[] = '%' . $value . '%';
179                    }elseif( $searchField == 'location' ){
180                        //print_r($filters['location']);
181
182                        $locIds = $filters['location'];
183                        $idArray = explode(',', $locIds);
184
185                        if($idArray[0] > 0){
186                             $conditions[] = ' l.location_id IN (' . $searchBy . ') ';
187
188                        }
189                    }
190
191                    $filterCount++;
192
193                    if ($searchField == 'termination') {
194                        $searchByTerminated = $searchBy;
195                    }
196                }
197            }
198        }
199
200        /* If not searching by employee status, hide terminated employees */
201        if ($searchByTerminated == EmployeeSearchForm::WITHOUT_TERMINATED) {
202            $conditions[] = "( e.termination_id IS NULL )";
203        }
204
205        if ($searchByTerminated == EmployeeSearchForm::ONLY_TERMINATED) {
206            $conditions[] = "( e.termination_id IS NOT NULL )";
207        }
208
209        /* Build the query */
210        $numConditions = 0;
211        foreach ($conditions as $condition) {
212            $numConditions++;
213
214            if ($numConditions == 1) {
215                $query .= ' WHERE ' . $condition;
216            } else {
217                $query .= ' AND ' . $condition;
218            }
219        }
220
221        /* Group by */
222        $query .= ' GROUP BY e.emp_number ';
223
224        /* sorting */
225        $order = array();
226
227        if( !empty($sortField) && !empty($sortOrder) ) {
228            if( array_key_exists($sortField, self::$sortMapping) ) {
229                $field = self::$sortMapping[$sortField];
230                if (is_array($field)) {
231                    foreach ($field as $name) {
232                        $order[$name] = $sortOrder;
233                    }
234                } else {
235                    $order[$field] = $sortOrder;
236                }
237            }
238        }
239
240        /* Default sort by emp_number, makes resulting order predictable, useful for testing */
241        $order['e.emp_lastname'] = 'asc';
242
243        $order['e.emp_number'] = 'asc';
244
245        /* Build the order by part */
246        $numOrderBy = 0;
247        foreach ($order as $field=>$dir) {
248            $numOrderBy++;
249            if ($numOrderBy == 1) {
250                $orderBy = ' ORDER BY ' . $field . ' ' . $dir;
251            } else {
252                $orderBy .= ', ' . $field . ' ' . $dir;
253            }
254        }
255
256    }
257
258
259
260    /**
261     * Get employee list after sorting and filtering using given parameters.
262     *
263     * @param EmployeeSearchParameterHolder $parameterHolder
264     */
265    public function searchEmployees(EmployeeSearchParameterHolder $parameterHolder) {
266
267        $sortField  = $parameterHolder->getOrderField();
268        $sortOrder  = $parameterHolder->getOrderBy();
269        $offset     = $parameterHolder->getOffset();
270        $limit      = $parameterHolder->getLimit();
271        $filters    = $parameterHolder->getFilters();
272        $returnType = $parameterHolder->getReturnType();
273
274        $select = '';
275        $query = '';
276        $bindParams = array();
277        $orderBy = '';
278
279        $this->_getEmployeeListQuery($select, $query, $bindParams, $orderBy,
280                $sortField, $sortOrder, $filters);
281
282        $completeQuery = $select . ' ' . $query . ' ' . $orderBy;
283
284        if (!is_null($offset) && !is_null($limit)) {
285            $completeQuery .= ' LIMIT ' . $offset . ', ' . $limit;
286        }
287
288        if (sfConfig::get('sf_logging_enabled')) {
289            $msg = $completeQuery;
290            if (count($bindParams) > 0 ) {
291                $msg .=  ' (' . implode(',', $bindParams) . ')';
292            }
293            sfContext::getInstance()->getLogger()->info($msg);
294        }
295//print_r($completeQuery);
296//print_r($bindParams);
297        $conn = Doctrine_Manager::connection();
298        $statement = $conn->prepare($completeQuery);
299        $result = $statement->execute($bindParams);
300
301        if ($returnType == EmployeeSearchParameterHolder::RETURN_TYPE_OBJECT) {
302            $employees = new Doctrine_Collection(Doctrine::getTable('Employee'));
303
304            if ($result) {
305                while ($row = $statement->fetch() ) {
306                    //print_r();
307                    $employee = new Employee();
308
309                    $employee->setEmpNumber($row['empNumber']);
310                    $employee->setEmployeeId($row['employeeId']);
311                    $employee->setFirstName($row['firstName']);
312                    $employee->setMiddleName($row['middleName']);
313                    $employee->setLastName($row['lastName']);
314                    $employee->setTerminationId($row['terminationId']);
315                    $employee->setEmpHmTelephone($row['emp_hm_telephone']);
316                    $employee->setEmpMobile($row['emp_mobile']);
317                    $employee->setEmpWorkTelephone($row['emp_work_telephone']);
318                    $employee->setEmpWorkEmail($row['emp_work_email']);
319                    $employee->setEmpOthEmail($row['emp_oth_email']);
320
321                    $jobTitle = new JobTitle();
322                    $jobTitle->setId($row['jobTitleId']);
323                    $jobTitle->setJobTitleName($row['jobTitle']);
324                    $jobTitle->setIsDeleted($row['isDeleted']);
325                    $employee->setJobTitle($jobTitle);
326
327                    $employeeStatus = new EmploymentStatus();
328                    $employeeStatus->setId($row['employeeStatusId']);
329                    $employeeStatus->setName($row['employeeStatus']);
330                    $employee->setEmployeeStatus($employeeStatus);
331
332                    $workStation = new SubUnit();
333                    $workStation->setName($row['subDivision']);
334                    $workStation->setId($row['subDivisionId']);
335                    $employee->setSubDivision($workStation);
336
337                    $supervisorList = isset($row['supervisors'])?$row['supervisors']:'';
338
339                    if (!empty($supervisorList)) {
340
341                        $supervisors = new Doctrine_Collection(Doctrine::getTable('Employee'));
342
343                        $supervisorArray = explode(',', $supervisorList);
344                        foreach ($supervisorArray as $supervisor) {
345                            list($first, $middle, $last) = explode('##', $supervisor);
346                            $supervisor = new Employee();
347                            $supervisor->setFirstName($first);
348                            $supervisor->setMiddleName($middle);
349                            $supervisor->setLastName($last);
350                            $employee->supervisors[] = $supervisor;
351                        }
352                    }
353
354                    $locationList = $row['locationIds'];
355
356                    if (!empty($locationList)) {
357
358    //                    $locations = new Doctrine_Collection(Doctrine::getTable('EmpLocations'));
359
360                        $locationArray = explode(',', $locationList);
361                        foreach ($locationArray as $location) {
362                            list($id, $name) = explode('##', $location);
363                            $empLocation = new Location();
364                            $empLocation->setId($id);
365                            $empLocation->setName($name);
366                            $employee->locations[] = $empLocation;
367                        }
368                    }
369
370                    $employees[] = $employee;
371                }
372            }
373        }
374        else {
375            return $statement->fetchAll();
376        }
377        return $employees;
378
379    }
380
381}