diff --git a/fileupload_page.php b/fileupload_page.php index afc1d7d8..ad03cd8e 100644 --- a/fileupload_page.php +++ b/fileupload_page.php @@ -40,20 +40,20 @@ function checkFileType (elementName, fileTypes) { if (fileElement.value.lastIndexOf(".") > 0) { fileExtension = fileElement.value.substring(fileElement.value.lastIndexOf(".") + 1, fileElement.value.length); } - + fileExtension = fileExtension.toLowerCase(); - + var allowed = fileTypes.split(","); - + if (allowed.indexOf(fileExtension) < 0) { fileElement.value = ""; alert('Selected file type is not supported'); clearFileElement(elementName); return false; } - + return true; - + } function clearFileElement (elementName) { @@ -76,4 +76,4 @@ function clearFileElement (elementName) { - \ No newline at end of file + diff --git a/images/file-icons/json.png b/images/file-icons/json.png new file mode 100644 index 00000000..d4aaa51b Binary files /dev/null and b/images/file-icons/json.png differ diff --git a/migrations/list.php b/migrations/list.php index 7a8e0c1a..89ce6d4e 100644 --- a/migrations/list.php +++ b/migrations/list.php @@ -1,5 +1,7 @@ executeQuery($sql); + } + + public function down(){ + $sql = <<<'SQL' + alter table PayrollColumns drop column `deduction_group`; +SQL; + + return $this->executeQuery($sql); + } + +} + diff --git a/migrations/v20171003_200302_payroll_meta_export.php b/migrations/v20171003_200302_payroll_meta_export.php new file mode 100644 index 00000000..1229d405 --- /dev/null +++ b/migrations/v20171003_200302_payroll_meta_export.php @@ -0,0 +1,41 @@ +executeQuery($sql); + + + $sql = <<<'SQL' + INSERT INTO `DataImport` (`name`, `dataType`, `details`, `columns`, `updated`, `created`) VALUES + ('Payroll Data Import', 'PayrollDataImporter', '', '[]', '2016-08-14 02:51:56', '2016-08-14 02:51:56'); + +SQL; + return $this->executeQuery($sql); + } + + public function down(){ + $sql = <<<'SQL' + delete from Reports where name = 'Payroll Meta Data Export'; +SQL; + + $this->executeQuery($sql); + + $sql = <<<'SQL' + delete from DataImport where name = 'Attendance Data Import'; +SQL; + + return $this->executeQuery($sql); + } + +} + diff --git a/src/Data/Admin/Api/AbstractDataImporter.php b/src/Data/Admin/Api/AbstractDataImporter.php index 40e6485b..56217433 100644 --- a/src/Data/Admin/Api/AbstractDataImporter.php +++ b/src/Data/Admin/Api/AbstractDataImporter.php @@ -7,7 +7,7 @@ use Data\Common\Model\DataImport; use FieldNames\Common\Model\CustomField; use Utils\LogManager; -abstract class AbstractDataImporter +abstract class AbstractDataImporter implements DataImporter { protected $dataImport = null; @@ -22,7 +22,7 @@ abstract class AbstractDataImporter protected $columnsCompeted = array(); protected $relatedColumns = array(); - public function getRowObjects() + public function getResult() { return $this->rowObjects; } @@ -243,4 +243,41 @@ abstract class AbstractDataImporter return false; } abstract public function fixBeforeSave($object, $data); + + + public function process($data, $dataImportId) + { + $data = str_replace("\r", "\n", $data); + $data = str_replace("\n\n", "\n", $data); + + $lines = str_getcsv($data, "\n"); + + $headerProcessed = false; + + $counter = 0; + + LogManager::getInstance()->info("Line Count:".count($lines)); + + $res = array(); + + foreach ($lines as $line) { + $cells = str_getcsv($line, ","); + if ($headerProcessed === false) { + $this->setDataImportId($dataImportId); + $this->processHeader($cells); + $headerProcessed = true; + } else { + $result = $this->processDataRow($counter, $cells); + $res[] = array($cells,$result); + } + $counter++; + } + + return $res; + } + + public function getLastStatus() + { + return IceResponse::SUCCESS; + } } diff --git a/src/Data/Admin/Api/DataActionManager.php b/src/Data/Admin/Api/DataActionManager.php index 9df47d3f..64510317 100644 --- a/src/Data/Admin/Api/DataActionManager.php +++ b/src/Data/Admin/Api/DataActionManager.php @@ -36,15 +36,6 @@ class DataActionManager extends SubActionManager $data = file_get_contents($url); - $data = str_replace("\r", "\n", $data); - $data = str_replace("\n\n", "\n", $data); - - $lines = str_getcsv($data, "\n"); - - $headerProcessed = false; - - $counter = 0; - $dataImport = new DataImport(); $dataImport->Load("id =?", array($dataFile->data_import_definition)); if (empty($dataImport->id)) { @@ -54,27 +45,13 @@ class DataActionManager extends SubActionManager $processClass = '\\Data\Admin\Import\\'.$dataImport->dataType; $processObj = new $processClass(); - LogManager::getInstance()->info("Line Count:".count($lines)); - - $res = array(); - - foreach ($lines as $line) { - $cells = str_getcsv($line, ","); - if ($headerProcessed === false) { - $processObj->setDataImportId($dataImport->id); - $processObj->processHeader($cells); - $headerProcessed = true; - } else { - $result = $processObj->processDataRow($counter, $cells); - $res[] = array($cells,$result); - } - $counter++; + $res = $processObj->process($data, $dataImport->id); + if ($processObj->getLastStatus() === IceResponse::SUCCESS) { + $dataFile->status = "Processed"; } - - $dataFile->status = "Processed"; $dataFile->details = json_encode($res, JSON_PRETTY_PRINT); $dataFile->Save(); - return new IceResponse(IceResponse::SUCCESS, $processObj->getRowObjects()); + return new IceResponse($processObj->getLastStatus(), $processObj->getResult()); } private function processHeader($dataImportId, $data) diff --git a/src/Data/Admin/Api/DataImporter.php b/src/Data/Admin/Api/DataImporter.php new file mode 100644 index 00000000..5bc7378c --- /dev/null +++ b/src/Data/Admin/Api/DataImporter.php @@ -0,0 +1,15 @@ +model; + } + + public function process($data, $dataImporterId) + { + $compStructure = new CompanyStructure(); + $compStructure->Load("1 = 1 limit 1", array()); + if (empty($compStructure->id)) { + $this->lastStatus = IceResponse::ERROR; + return "No company structures exists"; + } + $this->model = json_decode($data); + $deductionGroup = $this->createDeductionGroup($this->model); + if (!$deductionGroup) { + $this->lastStatus = IceResponse::ERROR; + return "Deduction group already exists"; + } + $salaryComponentTypeIdMap = $this->addSalaryComponentTypes($this->model); + $salaryComponentIdMap = $this->addSalaryComponents($this->model, $salaryComponentTypeIdMap); + $payrollColumnIdMap = $this->addPayrollColumns($this->model, $deductionGroup->id, $salaryComponentIdMap); + $deductionIdMap = $this->addDeductions( + $this->model, + $deductionGroup->id, + $salaryComponentTypeIdMap, + $salaryComponentIdMap, + $payrollColumnIdMap + ); + $this->refinePayrollColumns($payrollColumnIdMap, $deductionIdMap); + $payslipTemplate = $this->addPayslipTemplate($this->model, $payrollColumnIdMap); + $this->addPayroll( + $this->model, + $payrollColumnIdMap, + $deductionGroup->id, + $payslipTemplate->id, + $compStructure->id + ); + $this->lastStatus = IceResponse::SUCCESS; + + return $this->model; + } + + protected function addPayroll($model, $payrollColumnIdMap, $deductionGroupId, $payslipId, $departmentId) + { + $samplePr = $model->samplePayroll; + $payroll = new Payroll(); + $payroll->name = $samplePr->name; + $payroll->pay_period = $samplePr->pay_period; + $payroll->date_start = $samplePr->date_start; + $payroll->date_end = $samplePr->date_end; + $payroll->columns = $this->replaceJsonIds( + $samplePr->columns, + $payrollColumnIdMap + ); + $payroll->status = $samplePr->status; + $payroll->deduction_group = $deductionGroupId; + $payroll->payslipTemplate = $payslipId; + $payroll->department = $departmentId; + $ok = $payroll->Save(); + + if (!$ok) { + LogManager::getInstance()->error($payroll->ErrorMsg()); + } + } + + protected function addPayslipTemplate($model, $payrollColumnIdMap) + { + $pst = $model->payslipTemplate; + $payslipTemplate = new PayslipTemplate(); + $payslipTemplate->name = $pst->name; + + $data = json_decode($pst->data, true); + $newData = []; + foreach ($data as $row) { + if ($row['type'] === 'Payroll Column') { + $row['payrollColumn'] = $payrollColumnIdMap[$row['payrollColumn']]; + } + $newData[] = $row; + } + + $payslipTemplate->data = json_encode($newData); + + $payslipTemplate->status = $pst->status; + $payslipTemplate->created = $pst->created; + $payslipTemplate->updated = $pst->updated; + + $payslipTemplate->Save(); + + return $payslipTemplate; + } + + protected function refinePayrollColumns($payrollColumnIdMap, $deductionIdMap) + { + $payrollColumn = new PayrollColumn(); + $columns = $payrollColumn->Find('id in ('.implode(',', array_values($payrollColumnIdMap)).')', array()); + foreach ($columns as $column) { + $column->deductions = $this->replaceJsonIds( + $column->deductions, + $deductionIdMap + ); + + $column->add_columns = $this->replaceJsonIds( + $column->add_columns, + $payrollColumnIdMap + ); + + $column->sub_columns = $this->replaceJsonIds( + $column->sub_columns, + $payrollColumnIdMap + ); + + $column->sub_columns = $this->replaceJsonIdsForCalculations( + $column->calculation_columns, + $payrollColumnIdMap + ); + + $column->Save(); + } + } + + protected function addPayrollColumns($model, $deductionGroupId, $salaryComponentIdMap) + { + $payrollColumnIdMap = []; + $payrollColumns = $model->columns; + foreach ($payrollColumns as $payrollColumn) { + $column = new PayrollColumn(); + $column->name = $payrollColumn->name; + $column->calculation_hook = $payrollColumn->calculation_hook; + $column->salary_components = $this->replaceJsonIds( + $payrollColumn->salary_components, + $salaryComponentIdMap + ); + + $column->deductions = $payrollColumn->deductions; // need to map + $column->add_columns = $payrollColumn->add_columns; // need to map + $column->sub_columns = $payrollColumn->sub_columns; // need to map + $column->colorder = $payrollColumn->colorder; + $column->editable = $payrollColumn->editable; + $column->enabled = $payrollColumn->enabled; + $column->default_value = $payrollColumn->default_value; + $column->calculation_columns = $payrollColumn->calculation_columns; // need to map + $column->calculation_function = $payrollColumn->calculation_function; + $column->deduction_group = $deductionGroupId; + + $column->Save(); + + $payrollColumnIdMap[$payrollColumn->id] = $column->id; + } + return $payrollColumnIdMap; + } + + protected function addDeductions( + $model, + $deductionGroupId, + $salaryComponentTypeIdMap, + $salaryComponentIdMap, + $payrollColumnIdMap + ) { + $deductionIdMap = []; + $deductions = $model->deductions; + + foreach ($deductions as $deduction) { + $dbDeduction = new Deduction(); + $dbDeduction->name = $deduction->name; + $dbDeduction->componentType = $this->replaceJsonIds( + $deduction->componentType, + $salaryComponentTypeIdMap + ); + $dbDeduction->component = $this->replaceJsonIds( + $deduction->component, + $salaryComponentIdMap + ); + + $dbDeduction->payrollColumn = $payrollColumnIdMap[$deduction->payrollColumn]; + $dbDeduction->rangeAmounts = $deduction->rangeAmounts; + $dbDeduction->deduction_group = $deductionGroupId; + + $dbDeduction->Save(); + $deductionIdMap[$deduction->id] = $dbDeduction->id; + } + return $deductionIdMap; + } + + protected function createDeductionGroup($model) + { + $deductionGroup = new DeductionGroup(); + $deductionGroup->Load("name = ?", array($model->name)); + if (!empty($deductionGroup->id)) { + return false; + } + + $deductionGroup->name = $model->name; + $deductionGroup->description = $model->description; + $ok = $deductionGroup->Save(); + + if (!$ok) { + return false; + } + + return $deductionGroup; + } + + /** + * @param $salaryComponentTypeIdMap + */ + protected function addSalaryComponentTypes($model) + { + $salaryComponentTypeIdMap = []; + $salaryComponentTypes = $model->salaryComponentTypes; + foreach ($salaryComponentTypes as $salaryComponentType) { + $tempSct = new SalaryComponentType(); + $tempSct->Load( + "code = ? and name = ?", + array($salaryComponentType->code, $salaryComponentType->name) + ); + + if (!empty($tempSct->id)) { + $salaryComponentTypeIdMap[$salaryComponentType->id] = $tempSct->id; + continue; + } + + $tempSct = new SalaryComponentType(); + $tempSct->code = $salaryComponentType->code; + $tempSct->name = $salaryComponentType->name; + $tempSct->Save(); + + $salaryComponentTypeIdMap[$salaryComponentType->id] = $tempSct->id; + } + + return $salaryComponentTypeIdMap; + } + + protected function addSalaryComponents($model, $salaryComponentTypeIdMap) + { + $salaryComponentIdMap = []; + $salaryComponents = $model->salaryComponents; + foreach ($salaryComponents as $salaryComponent) { + $tempSct = new SalaryComponent(); + $tempSct->Load( + "componentType = ? and name = ?", + array( + $salaryComponentTypeIdMap[$salaryComponent->componentType], + $salaryComponent->name + ) + ); + + if (!empty($tempSct->id)) { + $salaryComponentIdMap[$salaryComponent->id] = $tempSct->id; + continue; + } + + $tempSct = new SalaryComponent(); + $tempSct->name = $salaryComponent->name; + $tempSct->componentType = $salaryComponentTypeIdMap[$salaryComponent->componentType]; + $tempSct->details = $salaryComponent->details; + $tempSct->Save(); + + $salaryComponentIdMap[$salaryComponent->id] = $tempSct->id; + } + + return $salaryComponentIdMap; + } + + private function replaceJsonIds($ids, $idMap) + { + $newIds = []; + $data = json_decode($ids, true); + foreach ($data as $id) { + $newIds[] = $idMap[$id]; + } + return json_encode($newIds); + } + + private function replaceJsonIdsForCalculations($calculations, $idMap) + { + $newCalculations = []; + $data = json_decode($calculations, true); + foreach ($data as $cal) { + $cal['column'] = $idMap[$cal['column']]; + $newCalculations[] = $cal; + } + return json_encode($newCalculations); + } + + public function getLastStatus() + { + return $this->lastStatus; + } +} diff --git a/src/Model/Report.php b/src/Model/Report.php index 47d87598..b51bbecd 100644 --- a/src/Model/Report.php +++ b/src/Model/Report.php @@ -31,5 +31,21 @@ class Report extends BaseModel return $entry; } + public function getCustomFilterQuery($filter) + { + $filter = json_decode($filter, true); + if ($filter['type'] === 'Reports') { + $query = ' and report_group <> ?'; + } elseif ($filter['type'] === 'Exports') { + $query = ' and report_group = ?'; + } else { + $query = ''; + } + + $queryData = array('Payroll'); + + return array($query, $queryData); + } + public $table = 'Reports'; } diff --git a/src/Reports/Admin/Reports/PayrollDataExport.php b/src/Reports/Admin/Reports/PayrollDataExport.php new file mode 100644 index 00000000..449e9ea2 --- /dev/null +++ b/src/Reports/Admin/Reports/PayrollDataExport.php @@ -0,0 +1,155 @@ +Load("id = ?", array($request['deduction_group'])); + if (empty($deductionGroup->id)) { + return ['Calculation Group not found']; + } else { + $data = [ + 'name' => $deductionGroup->name, + 'description' => $deductionGroup->description, + ]; + } + } + + // Add Deductions + $deduction = new Deduction(); + $deductions = $deduction->Find("deduction_group = ?", array($deductionGroup->id)); + $data['deductions'] = []; + foreach ($deductions as $deduction) { + $data['deductions'][] = [ + 'id' => $deduction->id, + 'name' => $deduction->name, + 'componentType' => $deduction->componentType, + 'component' => $deduction->component, + 'payrollColumn' => $deduction->payrollColumn, + 'rangeAmounts' => $deduction->rangeAmounts, + ]; + } + + // Payroll Columns + $col = new PayrollColumn(); + $columns = $col->Find("deduction_group = ?", array($deductionGroup->id)); + $data['columns'] = []; + $salaryComponentIds = []; + foreach ($columns as $col) { + $data['columns'][] = [ + 'id' => $col->id, + 'name' => $col->name, + 'calculation_hook' => $col->calculation_hook, + 'salary_components' => $col->salary_components, // ["1"] + 'deductions' => $col->deductions, // ["1"] + 'add_columns' => $col->add_columns, // ["1"] + 'sub_columns' => $col->sub_columns, + 'colorder' => $col->colorder, + 'editable' => $col->editable, + 'enabled' => $col->enabled, + 'default_value' => $col->default_value, + 'calculation_columns' => $col->calculation_columns, //[{"name":"O","column":"107","id":"calculation_columns_1"}] + 'calculation_function' => $col->calculation_function, + ]; + + if (!empty($col->salary_components)) { + $ids = json_decode($col->salary_components, true); + foreach ($ids as $id) { + $salaryComponentIds[$id] = $id; + } + } + } + + // Get Salary Components + $data['salaryComponents'] = []; + $salaryComponentGroupIds = []; + $salaryComponent = new SalaryComponent(); + $salaryComponents = $salaryComponent->Find( + "id in (" . implode(',', array_keys($salaryComponentIds)) .")", + array() + ); + foreach ($salaryComponents as $salaryComponent) { + $data['salaryComponents'][] = [ + 'id' => $salaryComponent->id, + 'name' => $salaryComponent->name, + 'componentType' => $salaryComponent->componentType, + 'details' => $salaryComponent->details, + ]; + + $salaryComponentGroupIds[$salaryComponent->componentType] = $salaryComponent->componentType; + } + + // Get Salary Component Types + $data['salaryComponentTypes'] = []; + $salaryComponentType = new SalaryComponentType(); + $salaryComponentTypes = $salaryComponentType->Find( + "id in (" . implode(',', array_keys($salaryComponentGroupIds)) .")", + array() + ); + foreach ($salaryComponentTypes as $salaryComponentType) { + $data['salaryComponentTypes'][] = [ + 'id' => $salaryComponentType->id, + 'code' => $salaryComponentType->code, + 'name' => $salaryComponentType->name, + ]; + } + + // Get Sample Payroll + $payroll = new Payroll(); + $payroll->Load("id = ?", array($request['payroll'])); + + $data['samplePayroll'] = [ + 'name' => $payroll->name, + 'pay_period' => $payroll->pay_period, + 'columns' => $payroll->columns, + 'date_start' => $payroll->date_start, + 'date_end' => $payroll->date_end, + 'status' => $payroll->status, + ]; + + $payslipTemplate = new PayslipTemplate(); + $payslipTemplate->Load("id = ?", array($payroll->payslipTemplate)); + + $data['payslipTemplate'] = [ + 'name' => $payslipTemplate->name, + 'data' => $payslipTemplate->data, + 'status' => $payslipTemplate->status, + 'created' => $payslipTemplate->created, + 'updated' => $payslipTemplate->updated, + ]; + + return $data; + } + + public function createReportFile($report, $data) + { + $fileFirstPart = "Report_".str_replace(" ", "_", $report->name)."-".date("Y-m-d_H-i-s"); + $fileName = $fileFirstPart.".txt"; + + $fileFullName = CLIENT_BASE_PATH.'data/'.$fileName; + $fp = fopen($fileFullName, 'w'); + + fwrite($fp, json_encode($data, JSON_PRETTY_PRINT)); + + fclose($fp); + return array($fileFirstPart, $fileName, $fileFullName); + } +}