/**
  * Create fiscal year and periods
  *
  * @param array $input
  * 	An array as follows: array(year => $year);
  *
  * @return JSON encoded string
  *  A string as follows:
  *	In case of success: {"success" : form.defaultSuccessOperationMessage}
  */
 public function generatePeriods(array $input)
 {
     $this->DB->transaction(function () use($input) {
         $loggedUserId = $this->AuthenticationManager->getLoggedUserId();
         $organizationId = $this->AuthenticationManager->getCurrentUserOrganization('id');
         $Setting = $this->Setting->byOrganization($organizationId)->first();
         $firstDayYear = date($input['year'] . '-01-01');
         $lastDayYear = date($input['year'] . '-12-31');
         $FiscalYear = $this->FiscalYear->create(array('year' => $input['year'], 'start_date' => $firstDayYear, 'end_date' => $lastDayYear, 'organization_id' => $organizationId));
         $Journal = $this->Journal->create(array('journalized_id' => $FiscalYear->id, 'journalized_type' => $this->FiscalYear->getTable(), 'user_id' => $loggedUserId, 'organization_id' => $organizationId));
         $this->Journal->attachDetail($Journal->id, array('note' => $this->Lang->get('decima-accounting::initial-accounting-setup.fiscalYearAddedJournal', array('year' => $input['year']))), $Journal);
         if (!empty($Setting->create_opening_period)) {
             $Period = $this->Period->create(array('month' => 0, 'start_date' => $firstDayYear, 'end_date' => $firstDayYear, 'fiscal_year_id' => $FiscalYear->id, 'organization_id' => $organizationId));
             $Journal = $this->Journal->create(array('journalized_id' => $Period->id, 'journalized_type' => $this->Period->getTable(), 'user_id' => $loggedUserId, 'organization_id' => $organizationId));
             $this->Journal->attachDetail($Journal->id, array('note' => $this->Lang->get('decima-accounting::initial-accounting-setup.periodAddedJournal', array('period' => 0))), $Journal);
         }
         for ($i = 1; $i <= 12; $i++) {
             $Date = new \DateTime($input['year'] . '-' . $i . '-01');
             $firstDay = $Date->format('Y-m-d');
             $Date->modify('last day of this month');
             $lastDay = $Date->format('Y-m-d');
             $Period = $this->Period->create(array('month' => $i, 'start_date' => $firstDay, 'end_date' => $lastDay, 'fiscal_year_id' => $FiscalYear->id, 'organization_id' => $organizationId));
             $Journal = $this->Journal->create(array('journalized_id' => $Period->id, 'journalized_type' => $this->Period->getTable(), 'user_id' => $loggedUserId, 'organization_id' => $organizationId));
             $this->Journal->attachDetail($Journal->id, array('note' => $this->Lang->get('decima-accounting::initial-accounting-setup.periodAddedJournal', array('period' => $i))), $Journal);
         }
         if (!empty($Setting->create_closing_period)) {
             $Period = $this->Period->create(array('month' => 13, 'start_date' => $lastDayYear, 'end_date' => $lastDayYear, 'fiscal_year_id' => $FiscalYear->id, 'organization_id' => $organizationId));
             $Journal = $this->Journal->create(array('journalized_id' => $Period->id, 'journalized_type' => $this->Period->getTable(), 'user_id' => $loggedUserId, 'organization_id' => $organizationId));
             $this->Journal->attachDetail($Journal->id, array('note' => $this->Lang->get('decima-accounting::initial-accounting-setup.periodAddedJournal', array('period' => 13))), $Journal);
         }
     });
     return json_encode(array('success' => $this->Lang->get('form.defaultSuccessOperationMessage')));
 }
 /**
  * Create closing balance voucher
  *
  * @param array $input
  * 	An array as follows: array('fiscal_year_id'=>$id, 'date'=> $date, 'period_id' => periodId, 'voucher_type_id' => $voucherTypeId, 'remark' => $remark, 'cost_center_id' => $costCenterId, 'account_id' => $accountId );
  *
  * @return JSON encoded string
  *  A string as follows:
  *	In case of success: {"success" : form.defaultSuccessSaveMessage}
  */
 public function createClosingBalanceVoucher(array $input)
 {
     $loggedUserId = $this->AuthenticationManager->getLoggedUserId();
     $organizationId = $this->AuthenticationManager->getCurrentUserOrganizationId();
     $input = eloquent_array_filter_for_insert($input);
     $input = array_add($input, 'organization_id', $organizationId);
     $this->DB->transaction(function () use($input, $loggedUserId, $organizationId, &$resultClosing, &$resultOpening) {
         $resultClosing = json_decode($this->JournalManagerService->saveJournalVoucher(array('notransaction' => '', 'status' => 'B', 'date' => $input['date_closing'], 'remark' => $input['remark_closing'], 'period_id' => $input['period_id_closing'], 'voucher_type_id' => $input['voucher_type_id_closing'])), true);
         $resultOpening = json_decode($this->JournalManagerService->saveJournalVoucher(array('notransaction' => '', 'status' => 'B', 'date' => $input['date_opening'], 'remark' => $input['remark_opening'], 'period_id' => $input['period_id_opening'], 'voucher_type_id' => $input['voucher_type_id_opening'])), true);
         $entries = $this->JournalEntry->getJournalEntriesGroupedByPlBsCategoryByOrganizationAndByFiscalYear(array('D', 'E'), $organizationId, $input['fiscal_year_id']);
         $voucherClosingEntries = array();
         $voucherOpeningEntries = array();
         foreach ($entries as $Entry) {
             //$Entry->balance_type
             //Deudor,Receivable:D and Acreedor,Payable: A
             if ($Entry->balance_type == 'D') {
                 $credit = round($Entry->debit - $Entry->credit, 2);
                 $debit = 0;
             } else {
                 $debit = round($Entry->credit - $Entry->debit, 2);
                 $credit = 0;
             }
             if ($debit != 0 || $credit != 0) {
                 array_push($voucherClosingEntries, array('debit' => $debit, 'credit' => $credit, 'cost_center_id' => $Entry->cost_center_id, 'account_id' => $Entry->account_id, 'journal_voucher_id' => $resultClosing['id']));
                 array_push($voucherOpeningEntries, array('debit' => $credit, 'credit' => $debit, 'cost_center_id' => $Entry->cost_center_id, 'account_id' => $Entry->account_id, 'journal_voucher_id' => $resultOpening['id']));
             }
         }
         $this->JournalEntry->massCreate($voucherClosingEntries);
         $this->JournalEntry->massCreate($voucherOpeningEntries);
         $Journal = $this->Journal->create(array('journalized_id' => $input['fiscal_year_id'], 'journalized_type' => $this->FiscalYear->getTable(), 'user_id' => $loggedUserId, 'organization_id' => $organizationId));
         $this->Journal->attachDetail($Journal->id, array('note' => $this->Lang->get('decima-accounting::close-fiscal-year.closingBalanceAddedJournal', array('number' => $resultClosing['number'], 'period' => $input['period_label_closing'])), $Journal));
         $this->JournalManagerService->updateJournalVoucherStatus($resultClosing['id']);
         $Journal = $this->Journal->create(array('journalized_id' => $input['fiscal_year_id_opening'], 'journalized_type' => $this->FiscalYear->getTable(), 'user_id' => $loggedUserId, 'organization_id' => $organizationId));
         $this->Journal->attachDetail($Journal->id, array('note' => $this->Lang->get('decima-accounting::close-fiscal-year.openingBalanceAddedJournal', array('number' => $resultOpening['number'], 'period' => $input['period_label_opening'])), $Journal));
         $this->JournalManagerService->updateJournalVoucherStatus($resultOpening['id']);
     });
     return json_encode(array('success' => $this->Lang->get('decima-accounting::close-fiscal-year.closingBalanceAddedJournal', array('number' => $resultClosing['number'], 'period' => $input['period_label_closing'])) . '<br>' . $this->Lang->get('decima-accounting::close-fiscal-year.closingBalanceAddedJournal', array('number' => $resultOpening['number'], 'period' => $input['period_label_opening']))));
 }
 /**
  * Update accounting setting
  *
  * @param array $input
  *   An array as follows: array('courses'=> array($id0, $id1,…), 'costCenters'=> array($key0, $key1,…));
  *
  * @return JSON encoded string
  *  A string as follows:
  *  {
  *  	totalEmployees: $totalEmployees
  *  	payrollEmployees: $payrollEmployees
  *  	serviceEmployees: $serviceEmployees
  *  }
  */
 public function updateAccountingSettings(array $input = array())
 {
     $organizationId = $this->AuthenticationManager->getCurrentUserOrganization('id');
     $loggedUserId = $this->AuthenticationManager->getLoggedUserId();
     $Setting = $this->Setting->byOrganization($organizationId)->first();
     $this->DB->transaction(function () use($Setting, $input, $organizationId, $loggedUserId) {
         $SettingJournal = $this->Journal->create(array('journalized_id' => $Setting->id, 'journalized_type' => $this->Setting->getTable(), 'user_id' => $loggedUserId, 'organization_id' => $organizationId));
         if (empty($Setting->is_configured)) {
             $organizationAccountsType = array();
             $this->SystemAccountType->all()->each(function ($AccountType) use($organizationId, &$organizationAccountsType, $loggedUserId) {
                 $accountType = $AccountType->toArray();
                 $accountType = array_add($accountType, 'organization_id', $organizationId);
                 $accountType['name'] = $this->Lang->has($accountType['lang_key']) ? $this->Lang->get($accountType['lang_key']) : $accountType['name'];
                 unset($accountType['id'], $accountType['created_at'], $accountType['updated_at'], $accountType['deleted_at']);
                 $AccountType = $this->AccountType->create($accountType);
                 $organizationAccountsType = array_add($organizationAccountsType, $AccountType->key, $AccountType->id);
                 $Journal = $this->Journal->create(array('journalized_id' => $AccountType->id, 'journalized_type' => $this->AccountType->getTable(), 'user_id' => $loggedUserId, 'organization_id' => $organizationId));
                 $this->Journal->attachDetail($Journal->id, array('note' => $this->Lang->get('decima-accounting::initial-accounting-setup.accountTypeAddedJournal', array('type' => $this->Lang->has($AccountType->lang_key) ? $this->Lang->get($AccountType->lang_key) : $AccountType->name))), $Journal);
             });
             $this->Journal->attachDetail($SettingJournal->id, array('note' => $this->Lang->get('decima-accounting::initial-accounting-setup.accountTypeSettingAddedJournal')), $SettingJournal);
             $this->SystemVoucherType->all()->each(function ($VoucherType) use($organizationId, $loggedUserId) {
                 $voucherType = $VoucherType->toArray();
                 $voucherType = array_add($voucherType, 'organization_id', $organizationId);
                 $voucherType['name'] = $this->Lang->has($voucherType['lang_key']) ? $this->Lang->get($voucherType['lang_key']) : $voucherType['name'];
                 unset($voucherType['id'], $voucherType['created_at'], $voucherType['updated_at'], $voucherType['deleted_at']);
                 $VoucherType = $this->VoucherType->create($voucherType);
                 $Journal = $this->Journal->create(array('journalized_id' => $VoucherType->id, 'journalized_type' => $this->VoucherType->getTable(), 'user_id' => $loggedUserId, 'organization_id' => $organizationId));
                 $this->Journal->attachDetail($Journal->id, array('note' => $this->Lang->get('decima-accounting::initial-accounting-setup.voucherTypeAddedJournal', array('type' => $this->Lang->has($VoucherType->lang_key) ? $this->Lang->get($VoucherType->lang_key) : $VoucherType->name))), $Journal);
             });
             $this->Journal->attachDetail($SettingJournal->id, array('note' => $this->Lang->get('decima-accounting::initial-accounting-setup.voucherTypeSettingAddedJournal')), $SettingJournal);
             $firstDayYear = date($input['year'] . '-01-01');
             $lastDayYear = date($input['year'] . '-12-31');
             $FiscalYear = $this->FiscalYear->create(array('year' => $input['year'], 'start_date' => $firstDayYear, 'end_date' => $lastDayYear, 'organization_id' => $organizationId));
             $Journal = $this->Journal->create(array('journalized_id' => $FiscalYear->id, 'journalized_type' => $this->FiscalYear->getTable(), 'user_id' => $loggedUserId, 'organization_id' => $organizationId));
             $this->Journal->attachDetail($Journal->id, array('note' => $this->Lang->get('decima-accounting::initial-accounting-setup.fiscalYearAddedJournal', array('year' => $input['year']))), $Journal);
             $this->Journal->attachDetail($SettingJournal->id, array('note' => $this->Lang->get('decima-accounting::initial-accounting-setup.fiscalYearAddedJournal', array('year' => $input['year']))), $SettingJournal);
             if ($input['create_opening_period'] == '1') {
                 $Period = $this->Period->create(array('month' => 0, 'start_date' => $firstDayYear, 'end_date' => $firstDayYear, 'fiscal_year_id' => $FiscalYear->id, 'organization_id' => $organizationId));
                 $Journal = $this->Journal->create(array('journalized_id' => $Period->id, 'journalized_type' => $this->Period->getTable(), 'user_id' => $loggedUserId, 'organization_id' => $organizationId));
                 $this->Journal->attachDetail($Journal->id, array('note' => $this->Lang->get('decima-accounting::initial-accounting-setup.periodAddedJournal', array('period' => 0))), $Journal);
             }
             for ($i = 1; $i <= 12; $i++) {
                 $Date = new \DateTime($input['year'] . '-' . $i . '-01');
                 $firstDay = $Date->format('Y-m-d');
                 $Date->modify('last day of this month');
                 $lastDay = $Date->format('Y-m-d');
                 $Period = $this->Period->create(array('month' => $i, 'start_date' => $firstDay, 'end_date' => $lastDay, 'fiscal_year_id' => $FiscalYear->id, 'organization_id' => $organizationId));
                 $Journal = $this->Journal->create(array('journalized_id' => $Period->id, 'journalized_type' => $this->Period->getTable(), 'user_id' => $loggedUserId, 'organization_id' => $organizationId));
                 $this->Journal->attachDetail($Journal->id, array('note' => $this->Lang->get('decima-accounting::initial-accounting-setup.periodAddedJournal', array('period' => $i))), $Journal);
             }
             if ($input['create_closing_period'] == '1') {
                 $Period = $this->Period->create(array('month' => 13, 'start_date' => $lastDayYear, 'end_date' => $lastDayYear, 'fiscal_year_id' => $FiscalYear->id, 'organization_id' => $organizationId));
                 $Journal = $this->Journal->create(array('journalized_id' => $Period->id, 'journalized_type' => $this->Period->getTable(), 'user_id' => $loggedUserId, 'organization_id' => $organizationId));
                 $this->Journal->attachDetail($Journal->id, array('note' => $this->Lang->get('decima-accounting::initial-accounting-setup.periodAddedJournal', array('period' => 13))), $Journal);
             }
             $this->Journal->attachDetail($SettingJournal->id, array('note' => $this->Lang->get('decima-accounting::initial-accounting-setup.periodAddedSettingJournal')), $SettingJournal);
             $CostCenter = $this->CostCenter->create(array('name' => $this->AuthenticationManager->getCurrentUserOrganizationName(), 'key' => $this->Config->get('accounting-general.default_organization_cc_key'), 'is_group' => true, 'organization_id' => $organizationId));
             $Journal = $this->Journal->create(array('journalized_id' => $CostCenter->id, 'journalized_type' => $this->CostCenter->getTable(), 'user_id' => $loggedUserId, 'organization_id' => $organizationId));
             $this->Journal->attachDetail($Journal->id, array('note' => $this->Lang->get('decima-accounting::initial-accounting-setup.costCenterAddedJournal', array('costCenter' => $CostCenter->key . ' ' . $CostCenter->name))), $Journal);
             $CostCenter = $this->CostCenter->create(array('name' => $this->Lang->get('decima-accounting::cost-center.main'), 'key' => $this->Config->get('accounting-general.default_main_cc_key'), 'is_group' => false, 'parent_cc_id' => $CostCenter->id, 'organization_id' => $organizationId));
             $Journal = $this->Journal->create(array('journalized_id' => $CostCenter->id, 'journalized_type' => $this->CostCenter->getTable(), 'user_id' => $loggedUserId, 'organization_id' => $organizationId));
             $this->Journal->attachDetail($Journal->id, array('note' => $this->Lang->get('decima-accounting::initial-accounting-setup.costCenterAddedJournal', array('costCenter' => $CostCenter->key . ' ' . $CostCenter->name))), $Journal);
             $this->Journal->attachDetail($SettingJournal->id, array('note' => $this->Lang->get('decima-accounting::initial-accounting-setup.costCenterAddedSettingJournal')), $SettingJournal);
             $organizationAccounts = array();
             $this->SystemAccount->accountsByAccountChartsTypes($input['account_chart_type_id'])->each(function ($SystemAccount) use($organizationId, $organizationAccountsType, &$organizationAccounts, &$systemAccountsCounter, $loggedUserId) {
                 $account = $SystemAccount->toArray();
                 $account = array_add($account, 'organization_id', $organizationId);
                 $account = array_add($account, 'account_type_id', $organizationAccountsType[$account['account_type_key']]);
                 if (!empty($account['parent_key'])) {
                     $account = array_add($account, 'parent_account_id', $organizationAccounts[$account['parent_key']]);
                 }
                 unset($account['id'], $account['parent_key'], $account['account_type_key'], $account['account_chart_type_id'], $account['created_at'], $account['updated_at'], $account['deleted_at']);
                 $OrganizationAccount = $this->Account->create($account);
                 $Journal = $this->Journal->create(array('journalized_id' => $OrganizationAccount->id, 'journalized_type' => $this->Account->getTable(), 'user_id' => $loggedUserId, 'organization_id' => $organizationId));
                 $this->Journal->attachDetail($Journal->id, array('note' => $this->Lang->get('decima-accounting::initial-accounting-setup.accountAddedJournal', array('account' => $OrganizationAccount->key . ' ' . $OrganizationAccount->name))), $Journal);
                 $organizationAccounts[$OrganizationAccount->key] = $OrganizationAccount->id;
             });
             if (!empty($organizationAccounts)) {
                 $AccountChartType = $this->AccountChartType->byId($input['account_chart_type_id']);
                 $this->Journal->attachDetail($SettingJournal->id, array('note' => $this->Lang->get('decima-accounting::initial-accounting-setup.accountAddedSettingJournal', array('catalog' => $AccountChartType->name))), $SettingJournal);
             }
             $input['id'] = $Setting->id;
             $input['initial_year'] = $input['year'];
             $input['is_configured'] = true;
             unset($input['_token'], $input['year']);
             $this->Setting->update($input);
         } else {
             $input['id'] = $Setting->id;
             $unchangedSettingValues = $Setting->toArray();
             unset($input['_token'], $input['year'], $input['account_chart_type_id']);
             $this->Setting->update($input);
             $diff = 0;
             foreach ($input as $key => $value) {
                 if ($unchangedSettingValues[$key] != $value) {
                     $diff++;
                     if ($diff == 1) {
                         $Journal = $this->Journal->create(array('journalized_id' => $Setting->id, 'journalized_type' => $this->Setting->getTable(), 'user_id' => $loggedUserId, 'organization_id' => $organizationId));
                     }
                     $fieldLangKey = 'decima-accounting::initial-accounting-setup.' . camel_case($key);
                     if ($key == 'voucher_numeration_type') {
                         $this->Journal->attachDetail($Journal->id, array('field' => $this->Lang->get($fieldLangKey), 'field_lang_key' => $fieldLangKey, 'old_value' => $this->Lang->get('decima-accounting::initial-accounting-setup.' . $unchangedSettingValues[$key]), 'new_value' => $this->Lang->get('decima-accounting::initial-accounting-setup.' . $value)), $Journal);
                     } else {
                         $this->Journal->attachDetail($Journal->id, array('field' => $this->Lang->get($fieldLangKey), 'field_lang_key' => $fieldLangKey, 'old_value' => $this->Lang->get('journal.' . $unchangedSettingValues[$key]), 'new_value' => $this->Lang->get('journal.' . $value)), $Journal);
                     }
                 }
             }
         }
     });
     return json_encode(array('success' => $this->Lang->get('decima-accounting::initial-accounting-setup.successUpdateMessage')));
 }
 /**
  * Get organization fiscal years
  *
  * @return array
  *  An array of arrays as follows: array( $label0, label1,…)
  */
 public function getFiscalYears()
 {
     $fiscalYears = array();
     $this->FiscalYear->byOrganization($this->AuthenticationManager->getCurrentUserOrganizationId())->each(function ($FiscalYear) use(&$fiscalYears) {
         array_push($fiscalYears, $FiscalYear->year);
     });
     return $fiscalYears;
 }