function getBonusPercents()
 {
     $result = [];
     $calcTypeId = $this->_repoTypeCalc->getIdByCode(Cfg::CODE_TYPE_CALC_BONUS);
     $where = ECfgGeneration::ATTR_CALC_TYPE_ID . '=' . (int) $calcTypeId;
     $rows = $this->_repoBonusCfgGen->get($where);
     foreach ($rows as $row) {
         $rankId = $row[ECfgGeneration::ATTR_RANK_ID];
         $gen = $row[ECfgGeneration::ATTR_GENERATION];
         $percent = $row[ECfgGeneration::ATTR_PERCENT];
         $result[$rankId][$gen] = $percent;
     }
     return $result;
 }
 public function registerPeriod(Request\RegisterPeriod $request)
 {
     $result = new Response\RegisterPeriod();
     $calcTypeId = $request->getCalcTypeId();
     $calcTypeCode = $request->getCalcTypeCode();
     $dsBegin = $request->getDateStampBegin();
     $dsEnd = $request->getDateStampEnd();
     $msgParams = is_null($calcTypeId) ? "type code '{$calcTypeCode}'" : "type ID #{$calcTypeId}";
     $this->_logger->info("'Register Period' operation is started in bonus base module ({$msgParams}; {$dsBegin}-{$dsEnd}).");
     if (is_null($calcTypeId)) {
         /* get calculation type ID by type code */
         $calcTypeId = $this->_repoTypeCalc->getIdByCode($calcTypeCode);
         $this->_logger->info("There is only calculation type code ({$calcTypeCode}) in request, calculation type id = {$calcTypeId}.");
     }
     $reqAddCalc = new Request\AddCalc();
     $reqAddCalc->setCalcTypeId($calcTypeId);
     $reqAddCalc->setDateStampBegin($dsBegin);
     $reqAddCalc->setDateStampEnd($dsEnd);
     $data = $this->addCalc($reqAddCalc);
     $result->setPeriodData($data->getPeriod());
     $result->setCalcData($data->getCalculation());
     $result->markSucceed();
     $this->_logger->info("'Register Period' operation is completed in bonus base module.");
     return $result;
 }
 public function getLastCalculationIdForPeriod($calcTypeCode, $dsBegin, $dsEnd)
 {
     /* get calculation type ID for type code */
     $calcTypeId = $this->_repoTypeCalc->getIdByCode($calcTypeCode);
     /* aliases and tables */
     $asPeriod = 'pbbp';
     $asCalc = 'pbbc';
     $tblPeriod = $this->_resource->getTableName(Period::ENTITY_NAME);
     $tblCalc = $this->_resource->getTableName(Calculation::ENTITY_NAME);
     // FROM prxgt_bon_base_period
     $query = $this->_conn->select();
     $cols = [];
     $query->from([$asPeriod => $tblPeriod], $cols);
     // LEFT JOIN prxgt_bon_base_calc pbbc ON pbbp.id = pbbc.period_id
     $on = "{$asPeriod}." . Period::ATTR_ID . "={$asCalc}." . Calculation::ATTR_PERIOD_ID;
     $cols = [Calculation::ATTR_ID];
     $query->joinLeft([$asCalc => $tblCalc], $on, $cols);
     // where
     $whereCalcType = "({$asPeriod}." . Period::ATTR_CALC_TYPE_ID . "=:calcTypeId)";
     $wherePeriodBegin = "({$asPeriod}." . Period::ATTR_DSTAMP_BEGIN . "=:dsBegin)";
     $wherePeriodEnd = "({$asPeriod}." . Period::ATTR_DSTAMP_END . "=:dsEnd)";
     $query->where("{$whereCalcType} AND {$wherePeriodBegin} AND {$wherePeriodEnd}");
     // order by calculation id desc
     $query->order(Calculation::ATTR_ID . ' DESC');
     // limit
     $query->limit(1);
     // $sql = (string)$query;
     $result = $this->_conn->fetchOne($query, ['calcTypeId' => $calcTypeId, 'dsBegin' => $dsBegin, 'dsEnd' => $dsEnd]);
     return $result;
 }
 private function _setBonusLevelsTeam()
 {
     $calTypeId = $this->_repoTypeCalc->getIdByCode(Cfg::CODE_TYPE_CALC_BONUS_TEAM_DEF);
     $data = [[Level::ATTR_CALC_TYPE_ID => $calTypeId, Level::ATTR_LEVEL => 0, Level::ATTR_PERCENT => 0], [Level::ATTR_CALC_TYPE_ID => $calTypeId, Level::ATTR_LEVEL => 500, Level::ATTR_PERCENT => 0.1], [Level::ATTR_CALC_TYPE_ID => $calTypeId, Level::ATTR_LEVEL => 1000, Level::ATTR_PERCENT => 0.15]];
     foreach ($data as $item) {
         $this->_repoBasic->addEntity(Level::ENTITY_NAME, $item);
     }
     $this->_logger->debug("Team Bonus levels are set.");
 }
 private function _setPercents()
 {
     $PERCENTS = [self::RANK_BY_PV => [0.05], self::RANK_BY_GV => [0.1], self::RANK_BY_PSAA => [0.15, 0.1]];
     foreach ($PERCENTS as $rank => $percents) {
         $calcTypeId = $this->_repoBonusTypeCalc->getIdByCode(Cfg::CODE_TYPE_CALC_BONUS);
         $rankId = $this->_repoBonusRank->getIdByCode($rank);
         $bind = [Generation::ATTR_RANK_ID => $rankId, Generation::ATTR_CALC_TYPE_ID => $calcTypeId];
         $gen = 1;
         foreach ($percents as $percent) {
             $bind[Generation::ATTR_PERCENT] = $percent;
             $bind[Generation::ATTR_GENERATION] = $gen++;
             $this->_repoCore->addEntity(Generation::ENTITY_NAME, $bind);
         }
     }
     $this->_logger->debug("Configuration parameters for Loyalty bonus are set.");
 }
 /**
  * @param Request\Bonus $req
  *
  * @return Response\Bonus
  */
 public function bonus(Request\Bonus $req)
 {
     $result = new Response\Bonus();
     $datePerformed = $req->getDatePerformed();
     $dateApplied = $req->getDateApplied();
     $this->_logger->info("'Loyalty Bonus' calculation is started. Performed at: {$datePerformed}, applied at: {$dateApplied}.");
     $reqGetPeriod = new PeriodGetForDependentCalcRequest();
     $calcTypeBase = Cfg::CODE_TYPE_CALC_QUALIFICATION;
     $calcType = Cfg::CODE_TYPE_CALC_BONUS;
     $reqGetPeriod->setBaseCalcTypeCode($calcTypeBase);
     $reqGetPeriod->setDependentCalcTypeCode($calcType);
     $respGetPeriod = $this->_callBasePeriod->getForDependentCalc($reqGetPeriod);
     if ($respGetPeriod->isSucceed()) {
         $def = $this->_manTrans->begin();
         try {
             $periodDataDepend = $respGetPeriod->getDependentPeriodData();
             $calcDataDepend = $respGetPeriod->getDependentCalcData();
             $calcIdDepend = $calcDataDepend->getId();
             $dsBegin = $periodDataDepend->getDstampBegin();
             $dsEnd = $periodDataDepend->getDstampEnd();
             /* collect data to process bonus */
             $calcTypeIdCompress = $this->_repoBonusTypeCalc->getIdByCode(Cfg::CODE_TYPE_CALC_COMPRESSION);
             $calcDataCompress = $this->_repoBonusService->getLastCalcForPeriodByDates($calcTypeIdCompress, $dsBegin, $dsEnd);
             $calcIdCompress = $calcDataCompress->getId();
             $params = $this->_repoMod->getConfigParams();
             $percents = $this->_repoMod->getBonusPercents();
             $treeCompressed = $this->_repoMod->getCompressedTreeWithQualifications($calcIdCompress);
             $orders = $this->_repoMod->getSalesOrdersForPeriod($dsBegin, $dsEnd);
             /* calculate bonus */
             $updates = $this->_subBonus->calc($treeCompressed, $orders, $params, $percents);
             /* create new operation with bonus transactions and save sales log */
             $respAdd = $this->_createBonusOperation($updates);
             $transLog = $respAdd->getTransactionsIds();
             $this->_repoMod->saveLogSaleOrders($transLog);
             /* mark calculation as completed and finalize bonus */
             $this->_repoBonusService->markCalcComplete($calcIdDepend);
             $this->_manTrans->commit($def);
             $result->setPeriodId($periodDataDepend->getId());
             $result->setCalcId($calcIdDepend);
             $result->markSucceed();
         } finally {
             $this->_manTrans->end($def);
         }
     }
     $this->_logger->info("'Loyalty Bonus' calculation is complete.");
     return $result;
 }
 /**
  * Add periods for PTC, TV & OV and related calculations.
  */
 private function _setPeriodAndCalcs()
 {
     /* get calculation types */
     $calcTypeIdPtc = $this->_repoTypeCalc->getIdByCode(Cfg::CODE_TYPE_CALC_COMPRESS_FOR_PTC);
     $calcTypeIdTv = $this->_repoTypeCalc->getIdByCode(Cfg::CODE_TYPE_CALC_VALUE_TV);
     $calcTypeIdOv = $this->_repoTypeCalc->getIdByCode(Cfg::CODE_TYPE_CALC_VALUE_OV);
     /* add periods */
     // PTC
     $bind = [Period::ATTR_CALC_TYPE_ID => $calcTypeIdPtc, Period::ATTR_DSTAMP_BEGIN => self::PERIOD_DS_BEGIN, Period::ATTR_DSTAMP_END => self::PERIOD_DS_END];
     $periodIdPtc = $this->_repoBasic->addEntity(Period::ENTITY_NAME, $bind);
     $this->_logger->debug("Period for calculation " . Cfg::CODE_TYPE_CALC_COMPRESS_FOR_PTC . " is added with ID={$periodIdPtc}.");
     // TV
     $bind[Period::ATTR_CALC_TYPE_ID] = $calcTypeIdTv;
     $periodIdTv = $this->_repoBasic->addEntity(Period::ENTITY_NAME, $bind);
     $this->_logger->debug("Period for calculation " . Cfg::CODE_TYPE_CALC_VALUE_TV . " is added with ID={$periodIdTv}.");
     // OV
     $bind[Period::ATTR_CALC_TYPE_ID] = $calcTypeIdOv;
     $periodIdOv = $this->_repoBasic->addEntity(Period::ENTITY_NAME, $bind);
     $this->_logger->debug("Period for calculation " . Cfg::CODE_TYPE_CALC_VALUE_OV . " is added with ID={$periodIdOv}.");
     /* add calculations*/
     $bind = [Calculation::ATTR_STATE => Cfg::CALC_STATE_COMPLETE];
     // PTC
     $bind[Calculation::ATTR_PERIOD_ID] = $periodIdPtc;
     $calcPtcId = $this->_repoBasic->addEntity(Calculation::ENTITY_NAME, $bind);
     $this->_logger->debug("Calculation " . Cfg::CODE_TYPE_CALC_COMPRESS_FOR_PTC . " is added with ID={$calcPtcId}.");
     // TV
     $bind[Calculation::ATTR_PERIOD_ID] = $periodIdTv;
     $calcTvId = $this->_repoBasic->addEntity(Calculation::ENTITY_NAME, $bind);
     $this->_logger->debug("Calculation " . Cfg::CODE_TYPE_CALC_VALUE_TV . " is added with ID={$calcTvId}.");
     // OV
     $bind[Calculation::ATTR_PERIOD_ID] = $periodIdOv;
     $calcOvId = $this->_repoBasic->addEntity(Calculation::ENTITY_NAME, $bind);
     $this->_logger->debug("Calculation " . Cfg::CODE_TYPE_CALC_VALUE_OV . " is added with ID={$calcOvId}.");
     /* save intermediary test data */
     $this->_testCalcIdPtc = $calcPtcId;
 }
 /**
  * @param $calcCode
  *
  * @return int|null
  */
 public function getCalcIdByCode($calcCode)
 {
     $result = $this->_repoTypeCalc->getIdByCode($calcCode);
     return $result;
 }