'ID', 'type_id' => false, 'pay_stub_entry_account_id' => false, 'name' => false, 'pay_stub_id' => 'PayStub', 'rate' => 'Rate', 'units' => 'Units', 'ytd_units' => 'YTDUnits', 'amount' => 'Amount', 'ytd_amount' => 'YTDAmount', 'description' => 'Description', 'pay_stub_entry_name_id' => 'PayStubEntryNameId', 'pay_stub_amendment_id' => 'PayStubAmendment', 'user_expense_id' => 'UserExpense', 'deleted' => 'Deleted', ]; return $variable_function_map; } /** * @return bool */ function getPayStubEntryAccountObject() { return $this->getGenericObject( 'PayStubEntryAccountListFactory', $this->getPayStubEntryNameID(), 'pay_stub_entry_account_obj' ); } /** * @return bool */ function getPayStubObject() { return $this->getGenericObject( 'PayStubListFactory', $this->getPayStub(), 'pay_stub_obj' ); } /** * @return bool */ function getPayStubAmendmentObject() { return $this->getGenericObject( 'PayStubAmendmentListFactory', $this->getPayStubAmendment(), 'ps_amendment_obj' ); } /** * @return bool|mixed */ function getPayStub() { return $this->getGenericDataValue( 'pay_stub_id' ); } /** * @param string $value UUID * @return bool */ function setPayStub( $value ) { $value = TTUUID::castUUID( $value ); return $this->setGenericDataValue( 'pay_stub_id', $value ); } /** * @return bool|mixed */ function getPayStubEntryNameId() { return $this->getGenericDataValue( 'pay_stub_entry_name_id' ); } /** * @param string $value UUID * @return bool */ function setPayStubEntryNameId( $value ) { $value = TTUUID::castUUID( $value ); Debug::text( 'Entry Account ID: ' . $value, __FILE__, __LINE__, __METHOD__, 10 ); return $this->setGenericDataValue( 'pay_stub_entry_name_id', $value ); } /** * @return bool|mixed */ function getPayStubAmendment() { return $this->getGenericDataValue( 'pay_stub_amendment_id' ); } /** * @param string $id UUID * @param bool $start_date * @param bool $end_date * @return bool */ function setPayStubAmendment( $id, $start_date = false, $end_date = false ) { $id = TTUUID::castUUID( $id ); if ( $id != TTUUID::getZeroID() ) { if ( $start_date == '' && $end_date == '' ) { $pay_stub_obj = $this->getPayStubObject(); if ( is_object( $pay_stub_obj ) ) { $start_date = $pay_stub_obj->getStartDate(); $end_date = $pay_stub_obj->getEndDate(); } else { return false; } unset( $pay_stub_obj ); } } Debug::text( 'PS Amendment ID: ' . $id, __FILE__, __LINE__, __METHOD__, 10 ); $psalf = TTnew( 'PayStubAmendmentListFactory' ); /** @var PayStubAmendmentListFactory $psalf */ if ( $id == TTUUID::getZeroID() || $this->getEnableCalculateYTD() == true //When recalculating YTD amounts, don't validate the PS amendment, as it should have already been validated anyways, and if it was deleted or something, we still need to be able to recalc YTDs. || ( $this->getEnableCalculateYTD() == false && $this->Validator->isResultSetWithRows( 'pay_stub_amendment_id', $psalf->getByIdAndStartDateAndEndDate( $id, $start_date, $end_date ), TTi18n::gettext( 'Pay Stub Amendment effective date is after employees pay stub end date or termination date' ) ) ) ) { $this->setGenericDataValue( 'pay_stub_amendment_id', $id ); return true; } return false; } /** * @return bool|mixed */ function getUserExpense() { return $this->getGenericDataValue( 'user_expense_id' ); } /** * @param string $value UUID * @return bool */ function setUserExpense( $value ) { $value = TTUUID::castUUID( $value ); Debug::text( 'User Expense ID: ' . $value, __FILE__, __LINE__, __METHOD__, 10 ); if ( getTTProductEdition() <= TT_PRODUCT_CORPORATE ) { $value = TTUUID::getZeroID(); } return $this->setGenericDataValue( 'user_expense_id', $value ); } /** * @return null */ function getRate() { return $this->getGenericDataValue( 'rate' ); } /** * @param $value * @return bool */ function setRate( $value ) { $value = ( $value !== null ) ? trim( $value ) : $value; if ( $value == null || $value == '' ) { return false; } return $this->setGenericDataValue( 'rate', Misc::MoneyRound( $value, 4 ) ); //DB schema limits to 4 decimal places, so make sure we round to that here, rather than let the DB truncate the value. This ensures the value in the DB always matches the value in memory, which is critical for calculating pay stub differences and avoiding being off by $0.01 } /** * @return null */ function getUnits() { return $this->getGenericDataValue( 'units' ); } /** * @param $value * @return bool */ function setUnits( $value ) { $value = trim( (string)$value ); if ( $value == null || $value == '' ) { return false; } return $this->setGenericDataValue( 'units', Misc::MoneyRound( $value, 4 ) ); //DB schema limits to 4 decimal places, so make sure we round to that here, rather than let the DB truncate the value. This ensures the value in the DB always matches the value in memory, which is critical for calculating pay stub differences and avoiding being off by $0.01 } /** * @return null */ function getYTDUnits() { return $this->getGenericDataValue( 'ytd_units' ); } /** * @param $value * @return bool */ function setYTDUnits( $value ) { $value = trim( $value ); if ( $value == null || $value == '' ) { return false; } return $this->setGenericDataValue( 'ytd_units', $value ); } /** * @return bool */ function getEnableCalculateYTD() { if ( isset( $this->enable_calc_ytd ) ) { return $this->enable_calc_ytd; } return false; } /** * @param $bool * @return bool */ function setEnableCalculateYTD( $bool ) { $this->enable_calc_ytd = $bool; return true; } /** * @return bool */ function getEnableCalculateAccrualBalance() { if ( isset( $this->enable_calc_accrual_balance ) ) { return $this->enable_calc_accrual_balance; } return false; } /** * @param $bool * @return bool */ function setEnableCalculateAccrualBalance( $bool ) { $this->enable_calc_accrual_balance = $bool; return true; } /** * @return null */ function getAmount() { return $this->getGenericDataValue( 'amount' ); } /** * @param $value * @return bool */ function setAmount( $value ) { $value = trim( $value ); //if ($value == NULL OR $value == '' OR $value < 0) { //Allow negative values for things like minusing vacation accural? if ( $value == null || $value == '' ) { return false; } return $this->setGenericDataValue( 'amount', ( is_object( $this->getPayStubObject() ) && is_object( $this->getPayStubObject()->getCurrencyObject() ) ) ? $this->getPayStubObject()->getCurrencyObject()->round( $value ) : Misc::MoneyRound( $value ) ); } /** * @return null */ function getYTDAmount() { return $this->getGenericDataValue( 'ytd_amount' ); } /** * @param $value * @return bool */ function setYTDAmount( $value ) { $value = trim( $value ); if ( $value == null || $value == '' ) { return false; } return $this->setGenericDataValue( 'ytd_amount', ( is_object( $this->getPayStubObject() ) && is_object( $this->getPayStubObject()->getCurrencyObject() ) ) ? $this->getPayStubObject()->getCurrencyObject()->round( $value ) : Misc::MoneyRound( $value ) ); } /** * @return mixed */ function getDescription() { return $this->getGenericDataValue( 'description' ); } /** * @param $value * @return bool */ function setDescription( $value ) { $value = trim( (string)$value ); return $this->setGenericDataValue( 'description', htmlspecialchars( $value ) ); } /** * @return bool */ function preSave() { Debug::text( 'Pay Stub ID: ' . $this->getPayStub() . ' Amount: '. $this->getAmount() .' Rate: '. $this->getRate() .' Units: '. $this->getUnits() .' PS Account: '. $this->getPayStubEntryNameId() .' PSA ID: '. $this->getPayStubAmendment() .' Expense: '. $this->getUserExpense() .' Calc YTD: ' . (int)$this->getEnableCalculateYTD(), __FILE__, __LINE__, __METHOD__, 10 ); if ( $this->getYTDAmount() == false ) { $this->setYTDAmount( 0 ); } if ( $this->getYTDUnits() == false ) { $this->setYTDUnits( 0 ); } return true; } /** * @param bool $ignore_warning * @return bool */ function Validate( $ignore_warning = true ) { // // BELOW: Validation code moved from set*() functions. // // Pay Stub if ( $this->getPayStub() !== false ) { $pslf = TTnew( 'PayStubListFactory' ); /** @var PayStubListFactory $pslf */ $this->Validator->isResultSetWithRows( 'pay_stub', $pslf->getByID( $this->getPayStub() ), TTi18n::gettext( 'Invalid Pay Stub' ) ); } // Entry Account Id $psealf = TTnew( 'PayStubEntryAccountListFactory' ); /** @var PayStubEntryAccountListFactory $psealf */ $this->Validator->isResultSetWithRows( 'pay_stub_entry_name_id', $psealf->getById( $this->getPayStubEntryNameId() ), TTi18n::gettext( 'Invalid Pay Stub Account' ) ); // Expense if ( $this->getUserExpense() !== false && $this->getUserExpense() != TTUUID::getZeroID() ) { $uelf = TTnew( 'UserExpenseListFactory' ); /** @var UserExpenseListFactory $uelf */ $result = $uelf->getById( $this->getUserExpense() ); $this->Validator->isResultSetWithRows( 'user_expense_id', $result, TTi18n::gettext( 'Invalid Expense' ) ); } // Rate if ( $this->getRate() != '' ) { $this->Validator->isFloat( 'rate', $this->getRate(), TTi18n::gettext( 'Invalid Rate' ) ); if ( $this->Validator->isError( 'rate' ) == false ) { $this->Validator->isLength( 'rate', $this->getRate(), TTi18n::gettext( 'Rate has too many digits' ), 0, 21 ); //Need to include decimal. } if ( $this->Validator->isError( 'rate' ) == false ) { $this->Validator->isLengthBeforeDecimal( 'rate', $this->getRate(), TTi18n::gettext( 'Rate has too many digits before the decimal' ), 0, 16 ); } } // Units if ( $this->getUnits() != '' ) { $this->Validator->isFloat( 'units', $this->getUnits(), TTi18n::gettext( 'Invalid Units' ) ); if ( $this->Validator->isError( 'units' ) == false ) { $this->Validator->isLength( 'units', $this->getUnits(), TTi18n::gettext( 'Units has too many digits' ), 0, 21 ); //Need to include decimal } if ( $this->Validator->isError( 'units' ) == false ) { $this->Validator->isLengthBeforeDecimal( 'units', $this->getUnits(), TTi18n::gettext( 'Units has too many digits before the decimal' ), 0, 16 ); } } // YTD Units if ( $this->getYTDUnits() !== false ) { $this->Validator->isFloat( 'ytd_units', $this->getYTDUnits(), TTi18n::gettext( 'Invalid YTD Units' ) ); } // Amount if ( $this->getAmount() !== false ) { $this->Validator->isFloat( 'amount', $this->getAmount(), TTi18n::gettext( 'Invalid Amount' ) ); if ( $this->Validator->isError( 'amount' ) == false ) { $this->Validator->isLength( 'amount', $this->getAmount(), TTi18n::gettext( 'Amount has too many digits' ), 0, 21 ); //Need to include decimal } if ( $this->Validator->isError( 'amount' ) == false ) { $this->Validator->isLengthBeforeDecimal( 'amount', $this->getAmount(), TTi18n::gettext( 'Amount has too many digits before the decimal' ), 0, 16 ); } } // YTD Amount if ( $this->getYTDAmount() !== false ) { $this->Validator->isFloat( 'ytd_amount', $this->getYTDAmount(), TTi18n::gettext( 'Invalid YTD Amount' ) ); } // Description if ( $this->getDescription() != '' ) { $this->Validator->isLength( 'description', $this->getDescription(), TTi18n::gettext( 'Invalid Description Length' ), 2, 100 ); } // // ABOVE: Validation code moved from set*() functions. // //Calc YTD values if they aren't already done. if ( $this->getYTDAmount() == null || $this->getYTDUnits() == null ) { $this->preSave(); } //Make sure rate * units = amount if ( $this->getAmount() === null ) { //var_dump( $this->getAmount() ); $this->Validator->isTrue( 'amount', false, TTi18n::gettext( 'Invalid Amount' ) ); } if ( $this->getPayStubEntryNameId() == '' ) { Debug::text( 'PayStubEntryNameID is NULL: ', __FILE__, __LINE__, __METHOD__, 10 ); $this->Validator->isTrue( 'pay_stub_entry_name_id', false, TTi18n::gettext( 'Invalid Pay Stub Account' ) ); } /* //Allow just units to be set. For cases like Gross Pay Units. //Make sure Units isn't set if Rate is if ( $this->getRate() != NULL AND $this->getUnits() == NULL ) { $this->Validator->isTrue( 'units', FALSE, TTi18n::gettext('Invalid Units')); } if ( $this->getUnits() != NULL AND $this->getRate() == NULL ) { $this->Validator->isTrue( 'rate', FALSE, TTi18n::gettext('Invalid Rate')); } */ /* //FIXME: For some reason the calculation done here has one less decimal digit then //the calculation done in Wage::getOverTime2Wage(). if ( $this->getRate() !== NULL AND $this->getUnits() !== NULL AND ( $this->getRate() * $this->getUnits() ) != $this->getAmount() ) { Debug::text('Validate: Rate: '. $this->getRate() .' Units: '. $this->getUnits() .' Amount: '. $this->getAmount() .' Calc: Rate: '. $this->getRate() .' Units: '. $this->getUnits() .' Total: '. ( $this->getRate() * $this->getUnits() ), __FILE__, __LINE__, __METHOD__, 10); $this->Validator->isTrue( 'amount', FALSE, TTi18n::gettext('Invalid Amount, calculation is incorrect.')); } */ //Make sure YTD values are set //YTD could be 0 though if we "cancel" out a entry like vacation accrual. if ( $this->getYTDAmount() === null ) { Debug::text( 'getYTDAmount is NULL: ', __FILE__, __LINE__, __METHOD__, 10 ); //var_dump( $this ); $this->Validator->isTrue( 'ytd_amount', false, TTi18n::gettext( 'Invalid YTD Amount' ) ); } if ( $this->getYTDUnits() === null ) { $this->Validator->isTrue( 'ytd_units', false, TTi18n::gettext( 'Invalid YTD Units' ) ); } return true; } /** * @return bool */ function postSave() { //If this entry is based off pay stub amendment, mark //PS amendment as "ACTIVE" status. //Once PS is paid, mark them as PAID. //If Pay Stub Account is attached to an accrual, handle that now. //Only calculate accrual if this is a new pay stub entry, not if we're //editing one, so we don't duplicate the accrual entry. // // **Handle this in PayStubFactory instead. // /* //This all handled in PayStubFactory::addEntry() now. if ( $this->getEnableCalculateAccrualBalance() == TRUE AND $this->getPayStubEntryAccountObject() != FALSE AND $this->getPayStubEntryAccountObject()->getAccrual() != FALSE AND $this->getPayStubEntryAccountObject()->getAccrual() != 0 ) { Debug::text('Pay Stub Account is linked to an accrual...', __FILE__, __LINE__, __METHOD__, 10); if ( $this->getPayStubEntryAccountObject()->getType() == 10 ) { $amount = $this->getAmount()*-1; //This is an earning... Reduce accrual } elseif ( $this->getPayStubEntryAccountObject()->getType() == 20 ) { $amount = $this->getAmount(); //This is a employee deduction, add to accrual. } Debug::text('Amount: '. $amount, __FILE__, __LINE__, __METHOD__, 10); if ( $amount != 0 ) { //Add entry to do the opposite to the accrual. $psef = TTnew( 'PayStubEntryFactory' ); $psef->setPayStub( $this->getPayStub() ); $psef->setPayStubEntryNameId( $this->getPayStubEntryAccountObject()->getAccrual() ); $psef->setAmount( $amount ); return $psef->Save(); } } else { Debug::text('Pay Stub Account is NOT linked to an accrual...', __FILE__, __LINE__, __METHOD__, 10); } */ return true; } /** * @param $data * @return bool */ function setObjectFromArray( $data ) { if ( is_array( $data ) ) { $variable_function_map = $this->getVariableToFunctionMap(); foreach ( $variable_function_map as $key => $function ) { if ( isset( $data[$key] ) ) { $function = 'set' . $function; switch ( $key ) { default: if ( method_exists( $this, $function ) ) { $this->$function( $data[$key] ); } break; } } } $this->setCreatedAndUpdatedColumns( $data ); return true; } return false; } /** * @param null $include_columns * @return array */ function getObjectAsArray( $include_columns = null ) { $variable_function_map = $this->getVariableToFunctionMap(); $data = []; if ( is_array( $variable_function_map ) ) { foreach ( $variable_function_map as $variable => $function_stub ) { if ( $include_columns == null || ( isset( $include_columns[$variable] ) && $include_columns[$variable] == true ) ) { $function = 'get' . $function_stub; switch ( $variable ) { case 'pay_stub_entry_account_id': case 'type_id': case 'name': $data[$variable] = $this->getColumn( $variable ); break; default: if ( method_exists( $this, $function ) ) { $data[$variable] = $this->$function(); } break; } } } $this->getCreatedAndUpdatedColumns( $data, $include_columns ); } return $data; } /** * @param $log_action * @return bool */ function addLog( $log_action ) { return TTLog::addEntry( $this->getPayStub(), $log_action, TTi18n::getText( 'Pay Stub Entry' ) . ': ' . $this->getPayStubEntryAccountObject()->getName() . ': ' . TTi18n::getText( 'Amount' ) . ': ' . $this->getAmount(), null, $this->getTable(), $this ); } } ?>