/**
  * post import document
  *
  * 1. check organisation
  * 2. generate username
  * 3. save profile
  * @return $array of document
  */
 public function post()
 {
     set_time_limit(0);
     if (!Input::has('employee')) {
         return new JSend('error', (array) Input::all(), 'Tidak ada data employee.');
     }
     $data = Input::get('employee');
     $globalnotify = [];
     foreach ($data as $col => $row) {
         $errors = new MessageBag();
         $organisation = Organisation::code($row['work']['kode_perusahaan'])->first();
         if ($organisation) {
             DB::beginTransaction();
             $send_mail = false;
             //2. generate username
             $username = UsernameGenerator::generate($row['work']['kode_perusahaan'], 0, $row['profile']['name']);
             $row['profile']['username'] = $username;
             //3. save profile
             $person = new Employee();
             $row['profile']['date_of_birth'] = Carbon::parse($row['profile']['date_of_birth'])->format('Y-m-d H:i:s');
             $person->fill($row['profile']);
             if (!$person->save()) {
                 $errors->add('profile', $person->getError());
             }
             //4. save contact
             if (!$errors->count()) {
                 if (!empty($row['email'])) {
                     $contact = new Contact();
                     $contact->fill(['contactable_id' => $person['id'], 'contactable_type' => get_class($person), 'type' => 'email', 'value' => $row['email'], 'is_default' => true]);
                     if (!$contact->save()) {
                         $errors->add('profile', $contact->getError());
                     }
                     $send_mail = true;
                 }
                 if (!empty($row['phone'])) {
                     $contact = new Contact();
                     $contact->fill(['contactable_id' => $person['id'], 'contactable_type' => get_class($person), 'type' => 'phone', 'value' => $row['phone'], 'is_default' => true]);
                     if (!$contact->save()) {
                         $errors->add('profile', $contact->getError());
                     }
                 }
                 if (!empty($row['address'])) {
                     $contact = new Contact();
                     $contact->fill(['contactable_id' => $person['id'], 'contactable_type' => get_class($person), 'type' => 'address', 'value' => $row['address'], 'is_default' => true]);
                     if (!$contact->save()) {
                         $errors->add('profile', $contact->getError());
                     }
                 }
             }
             //5. save marital status
             if (!$errors->count()) {
                 if (!empty($row['marital_status'])) {
                     $marital = new MaritalStatus();
                     $marital->fill(['person_id' => $person['id'], 'status' => $row['marital_status'], 'ondate' => Carbon::now()->format('Y-m-d H:i:s')]);
                     if (!$marital->save()) {
                         $errors->add('profile', $marital->getError());
                     }
                 }
             }
             //6. save work
             if (!$errors->count()) {
                 //6a. check branch
                 $branch = Branch::organisationid($organisation['id'])->name($row['work']['kantor'])->first();
                 if (!$branch) {
                     $branch = new Branch();
                     $branch->fill(['name' => $row['work']['kantor'], 'organisation_id' => $organisation['id']]);
                     if (!$branch->save()) {
                         $errors->add('work', $branch->getError());
                     }
                 }
                 //6b. check chart
                 if (!$errors->count()) {
                     $chart = Chart::branchid($branch['id'])->name($row['work']['jabatan'])->first();
                     if (!$chart) {
                         $chart = new Chart();
                         $chart->fill(['name' => $row['work']['jabatan'], 'branch_id' => $branch['id']]);
                         if (!$chart->save()) {
                             $errors->add('work', $chart->getError());
                         }
                     }
                 }
                 //6c. save work
                 if (!$errors->count()) {
                     $join_year = Carbon::parse($row['work']['tanggal_mulai_status'])->format('y');
                     $nik = NIKGenerator::generate($organisation['code'], $person['id'], $join_year);
                     $row['work']['chart_id'] = $chart['id'];
                     $row['work']['person_id'] = $person['id'];
                     $row['work']['nik'] = $nik;
                     $row['work']['status'] = $row['work']['status_kerja'];
                     $row['work']['start'] = Carbon::parse($row['work']['tanggal_mulai_status'])->format('Y-m-d H:i:s');
                     if (strtotime($row['work']['tanggal_akhir_status'])) {
                         $row['work']['end'] = Carbon::parse($row['work']['tanggal_akhir_status'])->format('Y-m-d H:i:s');
                     }
                     $row['work']['reason_end_job'] = $row['work']['alasan_akhir_status'];
                     $work = new Work();
                     $work->fill($row['work']);
                     if (!$work->save()) {
                         $errors->add('work', $work->getError());
                     }
                 }
             }
             //7. save relative
             foreach ($row['relatives'] as $key => $value) {
                 if (!$errors->count() && empty($value)) {
                     $relative = new Person();
                     $value['date_of_birth'] = Carbon::parse($value['date_of_birth'])->format('Y-m-d H:i:s');
                     $relative->fill($value);
                     if (!$relative->save()) {
                         $errors->add('relatives', $relative->getError());
                     } else {
                         $relation = new Relative();
                         $relation->fill(['relative_id' => $relative['id'], 'person_id' => $person['id'], 'relationship' => $value['relationship']]);
                         if (!$relation->save()) {
                             $errors->add('relative', $relation->getError());
                         }
                     }
                 }
             }
             //8. save document
             foreach ($row['document'] as $key => $value) {
                 if (!$errors->count()) {
                     $document = new PersonDocument();
                     $doc['person_id'] = $person['id'];
                     $doc['documents'] = array_merge(['code' => $key], ['document' => $value]);
                     $validating_document = new VOD();
                     if (!$validating_document->validate($doc['documents'])) {
                         $errors->add('PersonDocument', $validating_document->getError());
                     } else {
                         $doc['documents'] = json_encode($doc['documents']);
                         $document = $document->fill($doc);
                         if (!$document->save()) {
                             $errors->add('PersonDocument', $document->getError());
                         }
                     }
                 }
             }
             if (!$errors->count()) {
                 DB::commit();
                 $globalnotify[$col] = json_encode(['status' => 'sukses', 'data' => $col, 'message' => ['Data Karyawan Tersimpan']]);
                 if ($send_mail) {
                     Event::fire(new EmployeeCreated($final_employee));
                 }
             } else {
                 DB::rollback();
                 $globalnotify[$col] = json_encode(['status' => 'error', 'data' => $col, 'message' => $errors]);
             }
         } else {
             $globalnotify[$col] = json_encode(['status' => 'error', 'data' => $col, 'message' => ['Kode Perusahaan tidak valid']]);
         }
     }
     return new JSend('success', $globalnotify);
 }
 /**
  * Store an employeer
  *
  * 1. Save Employee
  * 2. Save Contacts
  * 3. Save Person Documents
  * 4. Save Works
  * 5. Save Relatives
  * 6. Save Marital Status
  * @return Response
  */
 public function store($org_id = null)
 {
     if (!Input::has('employee')) {
         return new JSend('error', (array) Input::all(), 'Tidak ada data employee.');
     }
     $errors = new MessageBag();
     DB::beginTransaction();
     //1. Validate employee Parameter
     $employee = Input::get('employee');
     if (empty($employee['id']) || is_null($employee['id']) || $employee['id'] == '' || $employee['id'] == 'null') {
         $is_new = true;
     } else {
         $is_new = false;
     }
     $employee_rules = ['username' => 'max:255', 'name' => 'required|max:255', 'prefix_title' => 'max:255', 'suffix_title' => 'max:255', 'place_of_birth' => 'max:255', 'date_of_birth' => 'date_format:"Y-m-d H:i:s"', 'gender' => 'in:female,male', 'password' => 'max:255'];
     //1a. Get original data
     $employee_data = \App\ThunderID\EmploymentSystemV1\Models\Employee::findornew($employee['id']);
     //1b. Validate Basic Employee Parameter
     $validator = Validator::make($employee, $employee_rules);
     if (!$validator->passes()) {
         $errors->add('Employee', $validator->errors());
     } else {
         if (isset($employee['last_password_updated_at']) && !strtotime($employee['last_password_updated_at'])) {
             unset($employee['last_password_updated_at']);
         }
         //if validator passed, save Employee
         $employee_data = $employee_data->fill($employee);
         if (!$employee_data->save()) {
             $errors->add('Employee', $employee_data->getError());
         }
     }
     //End of validate Employee
     //2. Validate Employee contact Parameter
     if (!$errors->count() && isset($employee['contacts'])) {
         if (!is_array($employee['contacts'])) {
             $employee['contacts'] = [];
         }
         $contact_current_ids = [];
         foreach ($employee['contacts'] as $key => $value) {
             if (!$errors->count()) {
                 $contact_data = \App\ThunderID\OrganisationManagementV1\Models\Contact::findornew($value['id']);
                 $contact_rules = ['contactable_id' => 'exists:hrps_persons,id|' . ($is_new ? '' : 'in:' . $employee_data['id']), 'contactable_type' => !$contact_data ? '' : 'in:' . get_class($employee_data), 'type' => 'required|max:255', 'is_default' => 'boolean'];
                 $validator = Validator::make($value, $contact_rules);
                 //if there was contact and validator false
                 if (!$validator->passes()) {
                     $errors->add('contact', $validator->errors());
                 } else {
                     $value['contactable_id'] = $employee_data['id'];
                     $value['contactable_type'] = get_class($employee_data);
                     $contact_data = $contact_data->fill($value);
                     if (!$contact_data->save()) {
                         $errors->add('contact', $contact_data->getError());
                     } else {
                         $contact_current_ids[] = $contact_data['id'];
                     }
                 }
             }
         }
         //if there was no error, check if there were things need to be delete
         if (!$errors->count()) {
             $contacts = \App\ThunderID\OrganisationManagementV1\Models\Contact::ContactableID($employee['id'])->ContactableType(get_class($employee_data))->get(['id'])->toArray();
             $contact_should_be_ids = [];
             foreach ($contacts as $key => $value) {
                 $contact_should_be_ids[] = $value['id'];
             }
             $difference_contact_ids = array_diff($contact_should_be_ids, $contact_current_ids);
             if ($difference_contact_ids) {
                 foreach ($difference_contact_ids as $key => $value) {
                     $contact_data = \App\ThunderID\OrganisationManagementV1\Models\Contact::find($value);
                     if (!$contact_data->delete()) {
                         $errors->add('contact', $contact_data->getError());
                     }
                 }
             }
         }
     }
     //End of validate employee contact
     //3. Validate Employee document Parameter
     if (!$errors->count() && isset($employee['persondocuments'])) {
         if (!is_array($employee['persondocuments'])) {
             $employee['persondocuments'] = [];
         }
         $document_current_ids = [];
         foreach ($employee['persondocuments'] as $key => $value) {
             if (!$errors->count()) {
                 $document_data = \App\ThunderID\PersonSystemV1\Models\PersonDocument::findornew($value['id']);
                 $document_rules = ['person_id' => 'exists:hrps_persons,id|' . ($is_new ? '' : 'in:' . $employee_data['id']), 'documents' => 'required'];
                 $validator = Validator::make($value, $document_rules);
                 //if there was contact and validator false
                 if (!$validator->passes()) {
                     $errors->add('PersonDocument', $validator->errors());
                 } else {
                     $validating_document = new VOD();
                     if (!$validating_document->validate(json_decode($value['documents'], true))) {
                         $errors->add('PersonDocument', $validating_document->getError());
                     } else {
                         $value['person_id'] = $employee_data['id'];
                         $document_data = $document_data->fill($value);
                         if (!$document_data->save()) {
                             $errors->add('PersonDocument', $document_data->getError());
                         } else {
                             $document_current_ids[] = $document_data['id'];
                         }
                     }
                 }
             }
         }
         //if there was no error, check if there were things need to be delete
         if (!$errors->count()) {
             $persondocuments = \App\ThunderID\PersonSystemV1\Models\PersonDocument::personid($employee['id'])->get(['id'])->toArray();
             $document_should_be_ids = [];
             foreach ($persondocuments as $key => $value) {
                 $document_should_be_ids[] = $value['id'];
             }
             $difference_contact_ids = array_diff($document_should_be_ids, $document_current_ids);
             if ($difference_contact_ids) {
                 foreach ($difference_contact_ids as $key => $value) {
                     $document_data = \App\ThunderID\PersonSystemV1\Models\PersonDocument::find($value);
                     if (!$document_data->delete()) {
                         $errors->add('contact', $document_data->getError());
                     }
                 }
             }
         }
     }
     //End of validate employee privatedocument
     //4. Validate Employee Work Parameter
     if (!$errors->count() && isset($employee['works'])) {
         if (!is_array($employee['works'])) {
             $employee['works'] = [];
         }
         $work_current_ids = [];
         foreach ($employee['works'] as $key => $value) {
             if (!$errors->count()) {
                 $work_data = \App\ThunderID\EmploymentSystemV1\Models\Work::findornew($value['id']);
                 $work_rules = ['person_id' => 'exists:hrps_persons,id|' . ($is_new ? '' : 'in:' . $employee_data['id']), 'chart_id' => 'exists:hrom_charts,id', 'grade' => 'numeric', 'status' => 'required|in:contract,probation,internship,permanent,others,admin', 'start' => 'required|date_format:"Y-m-d H:i:s"'];
                 $validator = Validator::make($value, $work_rules);
                 //if there was work and validator false
                 if (!$validator->passes()) {
                     $errors->add('Work', $validator->errors());
                 } else {
                     $value['person_id'] = $employee_data['id'];
                     if (!strtotime($value['end'])) {
                         unset($value['end']);
                     }
                     $work_data = $work_data->fill($value);
                     if (!$work_data->save()) {
                         $errors->add('Work', $work_data->getError());
                     } elseif (isset($value['grade']) && !empty($value['grade'])) {
                         $grade_data = \App\ThunderID\EmploymentSystemV1\Models\GradeLog::workid($value['id'])->orderby('updated_at', 'asc')->first();
                         if (!$grade_data || $grade_data != $value['grade']) {
                             $grade_data = new \App\ThunderID\EmploymentSystemV1\Models\GradeLog();
                             $grade_data->fill(['grade' => $value['grade'], 'work_id' => $work_data['id']]);
                             if (!$grade_data->save()) {
                                 $errors->add('Work', $grade_data->getError());
                             }
                         }
                     }
                     if (!$errors->count() && isset($value['contractworks']) && is_array($value['contractworks'])) {
                         $contract_current_ids = [];
                         foreach ($value['contractworks'] as $key => $value2) {
                             if (!$errors->count()) {
                                 $contract_data = \App\ThunderID\EmploymentSystemV1\Models\ContractWork::findornew($value2['id']);
                                 $contract_rules = ['work_id' => 'exists:hres_contracts_works,id|' . ($is_new ? '' : 'in:' . $work_data['id']), 'contract_element_id' => 'exists:hres_contract_elements,id|' . ($contract_data != null ? '' : 'in:' . $contract_data['contract_element_id']), 'value' => 'required|max:255'];
                                 $validator = Validator::make($value2, $contract_rules);
                                 //if there was contract and validator false
                                 if (!$validator->passes()) {
                                     $errors->add('contract', $validator->errors());
                                 } else {
                                     $value2['work_id'] = $work_data['id'];
                                     $contract_data = $contract_data->fill($value2);
                                     if (!$contract_data->save()) {
                                         $errors->add('contract', $contract_data->getError());
                                     } else {
                                         $contract_current_ids[] = $contract_data['id'];
                                     }
                                 }
                             }
                         }
                         //if there was no error, check if there were things need to be delete
                         if (!$errors->count()) {
                             $contractworks = \App\ThunderID\EmploymentSystemV1\Models\ContractWork::workid($value['id'])->get(['id'])->toArray();
                             $contract_should_be_ids = [];
                             foreach ($contractworks as $key => $value2) {
                                 $contract_should_be_ids[] = $value2['id'];
                             }
                             $difference_contract_ids = array_diff($contract_should_be_ids, $contract_current_ids);
                             if ($difference_contract_ids) {
                                 foreach ($difference_contract_ids as $key => $value2) {
                                     $contract_data = \App\ThunderID\EmploymentSystemV1\Models\ContractWork::find($value2);
                                     if (!$contract_data->delete()) {
                                         $errors->add('contract', $contract_data->getError());
                                     }
                                 }
                             }
                         }
                     }
                     $work_current_ids[] = $work_data['id'];
                 }
             }
         }
         //if there was no error, check if there were things need to be delete
         if (!$errors->count()) {
             $works = \App\ThunderID\EmploymentSystemV1\Models\Work::personid($employee['id'])->get(['id'])->toArray();
             $work_should_be_ids = [];
             foreach ($works as $key => $value) {
                 $work_should_be_ids[] = $value['id'];
             }
             $difference_work_ids = array_diff($work_should_be_ids, $work_current_ids);
             if ($difference_work_ids) {
                 foreach ($difference_work_ids as $key => $value) {
                     $work_data = \App\ThunderID\EmploymentSystemV1\Models\Work::find($value);
                     if (!$work_data->delete()) {
                         $errors->add('Work', $work_data->getError());
                     }
                 }
             }
         }
     }
     //End of validate employee career
     //5. Validate Employee relatives Parameter
     if (!$errors->count() && isset($employee['relatives'])) {
         if (!is_array($employee['relatives'])) {
             $employee['relatives'] = [];
         }
         $relative_current_ids = [];
         foreach ($employee['relatives'] as $key => $value) {
             if (!$errors->count()) {
                 $relative_data = \App\ThunderID\PersonSystemV1\Models\Relative::findornew($value['id']);
                 $relative_rules = ['person_id' => 'exists:hrps_persons,id|' . ($is_new ? '' : 'in:' . $employee_data['id']), 'relative_id' => 'exists:hrps_persons,id|' . ($relative_data['relative_id'] == null ? '' : 'in:' . $relative_data['relative_id']), 'relationship' => 'required|max:255', 'relative.name' => 'required|max:255', 'relative.prefix_title' => 'max:255', 'relative.suffix_title' => 'max:255', 'relative.place_of_birth' => 'max:255', 'relative.date_of_birth' => 'required|date_format:"Y-m-d H:i:s"', 'relative.gender' => 'in:female,male'];
                 $validator = Validator::make($value, $relative_rules);
                 //if there was workexperience and validator false
                 if (!$validator->passes()) {
                     $errors->add('workexperience', $validator->errors());
                 } else {
                     $employee_relative_data = \App\ThunderID\EmploymentSystemV1\Models\Employee::findornew($relative_data['relative']['id']);
                     $validator = Validator::make($employee, $employee_rules);
                     if (!$validator->passes()) {
                         $errors->add('Employee', $validator->errors());
                     } else {
                         if (isset($value['relative']['last_password_updated_at']) && !strtotime($value['relative']['last_password_updated_at'])) {
                             unset($value['relative']['last_password_updated_at']);
                         }
                         //if validator passed, save Employee
                         $employee_relative_data = $employee_relative_data->fill($value['relative']);
                         if (!$employee_relative_data->save()) {
                             $errors->add('Employee', $employee_relative_data->getError());
                         }
                     }
                     if (!$errors->count()) {
                         $value['person_id'] = $employee_data['id'];
                         $value['relative_id'] = $employee_relative_data['id'];
                         $relative_data = $relative_data->fill($value);
                         if (!$relative_data->save()) {
                             $errors->add('Relative', $relative_data->getError());
                         } else {
                             $relative_current_ids[] = $relative_data['id'];
                         }
                     }
                 }
             }
         }
         //if there was no error, check if there were things need to be delete
         if (!$errors->count()) {
             $relatives = \App\ThunderID\PersonSystemV1\Models\Relative::personid($employee_data['id'])->get(['id'])->toArray();
             $relative_should_be_ids = [];
             foreach ($relatives as $key => $value) {
                 $relative_should_be_ids[] = $value['id'];
             }
             $difference_relative_ids = array_diff($relative_should_be_ids, $relative_current_ids);
             if ($difference_relative_ids) {
                 foreach ($difference_relative_ids as $key => $value) {
                     $relative_data = \App\ThunderID\PersonSystemV1\Models\Relative::find($value);
                     if (!$relative_data->delete()) {
                         $errors->add('relative', $relative_data->getError());
                     }
                 }
             }
         }
     }
     //End of validate employee relatives
     //6. Validate Employee ms Parameter
     if (!$errors->count() && isset($employee['maritalstatuses'])) {
         if (!is_array($employee['maritalstatuses'])) {
             $employee['maritalstatuses'] = [];
         }
         $ms_current_ids = [];
         foreach ($employee['maritalstatuses'] as $key => $value) {
             if (!$errors->count()) {
                 $ms_data = \App\ThunderID\PersonSystemV1\Models\MaritalStatus::findornew($value['id']);
                 $ms_rules = ['person_id' => 'exists:hrps_persons,id|' . ($is_new ? '' : 'in:' . $employee_data['id']), 'status' => 'required|max:255', 'ondate' => 'required|date_format:"Y-m-d H:i:s"'];
                 $validator = Validator::make($value, $ms_rules);
                 //if there was ms and validator false
                 if (!$validator->passes()) {
                     $errors->add('MaritalStatus', $validator->errors());
                 } else {
                     $value['person_id'] = $employee_data['id'];
                     $ms_data = $ms_data->fill($value);
                     if (!$ms_data->save()) {
                         $errors->add('ms', $ms_data->getError());
                     } else {
                         $ms_current_ids[] = $ms_data['id'];
                     }
                 }
             }
         }
         //if there was no error, check if there were things need to be delete
         if (!$errors->count()) {
             $mss = \App\ThunderID\PersonSystemV1\Models\MaritalStatus::personid($employee['id'])->get(['id'])->toArray();
             $ms_should_be_ids = [];
             foreach ($mss as $key => $value) {
                 $ms_should_be_ids[] = $value['id'];
             }
             $difference_ms_ids = array_diff($ms_should_be_ids, $ms_current_ids);
             if ($difference_ms_ids) {
                 foreach ($difference_ms_ids as $key => $value) {
                     $ms_data = \App\ThunderID\PersonSystemV1\Models\MaritalStatus::find($value);
                     if (!$ms_data->delete()) {
                         $errors->add('MaritalStatus', $ms_data->getError());
                     }
                 }
             }
         }
     }
     //End of validate employee MaritalStatus
     if ($errors->count()) {
         DB::rollback();
         return new JSend('error', (array) Input::all(), $errors);
     }
     DB::commit();
     $final_employee = \App\ThunderID\EmploymentSystemV1\Models\Employee::id($employee_data['id'])->organisationid($org_id)->currentgrade(true)->currentmaritalstatus(true)->with(['persondocuments', 'maritalstatuses', 'relatives', 'relatives.relative', 'contacts', 'works', 'works.contractworks', 'works.contractworks.contractelement'])->first()->toArray();
     if ($is_new && $final_employee['email'] != 'not available') {
         Event::fire(new EmployeeCreated($final_employee));
     }
     return new JSend('success', (array) $final_employee);
 }