/**
  * @param string $dateBegin datestamp (YYYYMMDD) for the date when the first customer should be created.
  * @param bool $switchDateOnNewCustomer 'true' - create customers day by day, 'false' - create all customers
  * in one day.
  */
 protected function _createDownlineCustomers($dateBegin = self::DATE_PERIOD_BEGIN, $switchDateOnNewCustomer = true)
 {
     $dtToday = $dateBegin;
     foreach ($this->DEFAULT_DWNL_TREE as $customerRef => $parentRef) {
         $customerMageId = $this->_mapCustomerMageIdByIndex[$customerRef];
         /* get magento customer data */
         $request = new CustomerAddRequest();
         $request->setCustomerId($customerMageId);
         $request->setParentId($this->_mapCustomerMageIdByIndex[$parentRef]);
         $request->setReference($this->_mapCustomerMageIdByIndex[$customerRef]);
         $request->setCountryCode(self::DEFAULT_DOWNLINE_COUNTRY_CODE);
         $request->setDate($this->_toolPeriod->getTimestampFrom($dtToday));
         /* Create customer per day or all customers in the same day. */
         if ($switchDateOnNewCustomer) {
             $dtToday = $this->_toolPeriod->getPeriodNext($dtToday);
         }
         $response = $this->_callDownlineCustomer->add($request);
         if ($response->isSucceed()) {
             $path = $response->getData(Customer::ATTR_PATH);
             $depth = $response->getData(Customer::ATTR_DEPTH);
             $this->_logger->debug("New customer #{$customerMageId} is added to path '{$path}' on depth {$depth} at '{$dtToday}'.");
         } else {
             $this->_logger->error("Cannot add new customer #{$customerMageId} to downline tree.");
         }
     }
 }
 /**
  * @param Request\GetForWriteOff $request
  *
  * @return Response\GetForWriteOff
  */
 public function getForWriteOff(Request\GetForWriteOff $request)
 {
     $result = new Response\GetForWriteOff();
     $this->_logger->info("'Get latest period for Write Off calculation' operation is started.");
     /* get the last Write Off period data */
     $calcWriteOffCode = Cfg::CODE_TYPE_CALC_PV_WRITE_OFF;
     $calcWriteOffId = $this->_subDb->getCalcIdByCode($calcWriteOffCode);
     $respWriteOffLastPeriod = $this->_subDb->getLastPeriodData($calcWriteOffId);
     $periodWriteOffData = $respWriteOffLastPeriod->getPeriodData();
     if (is_null($periodWriteOffData)) {
         $this->_logger->info("There is no period for PV Write Off calculation  yet.");
         /* calc period for PV Write Off */
         $tsFirstPv = $this->_subDb->getFirstDateForPvTransactions();
         if ($tsFirstPv === false) {
             $this->_logger->info("There is no PV transactions yet. Nothing to do.");
             $result->setHasNoPvTransactionsYet();
         } else {
             $this->_logger->info("First PV transaction was performed at '{$tsFirstPv}'.");
             $periodMonth = $this->_toolPeriod->getPeriodCurrent($tsFirstPv, ToolPeriod::TYPE_MONTH);
             $dsBegin = $this->_toolPeriod->getPeriodFirstDate($periodMonth);
             $dsEnd = $this->_toolPeriod->getPeriodLastDate($periodMonth);
             $periodWriteOffData = $this->_subDb->addNewPeriodAndCalc($calcWriteOffId, $dsBegin, $dsEnd);
             $result->setPeriodData($periodWriteOffData->getData(Sub\Db::DATA_PERIOD));
             $result->setCalcData($periodWriteOffData->getData(Sub\Db::DATA_CALC));
             $result->markSucceed();
         }
     } else {
         $result->setPeriodData($periodWriteOffData);
         $periodId = $periodWriteOffData->getId();
         $this->_logger->info("There is registered period #{$periodId} for '{$calcWriteOffCode}' calculation.");
         $calcData = $respWriteOffLastPeriod->getCalcData();
         if ($calcData === false) {
             $this->_logger->info("There is no calculation data for existing period. Use existing period data.");
             $result->markSucceed();
         } else {
             if ($calcData && $calcData->getState() == Cfg::CALC_STATE_COMPLETE) {
                 $this->_logger->info("There is complete calculation for existing period. Create new period.");
                 $periodEnd = $periodWriteOffData->getDstampEnd();
                 /* calculate new period bounds */
                 $periodNext = $this->_toolPeriod->getPeriodNext($periodEnd, ToolPeriod::TYPE_MONTH);
                 $dsNextBegin = $this->_toolPeriod->getPeriodFirstDate($periodNext);
                 $dsNextEnd = $this->_toolPeriod->getPeriodLastDate($periodNext);
                 $periodWriteOffData = $this->_subDb->addNewPeriodAndCalc($calcWriteOffId, $dsNextBegin, $dsNextEnd);
                 $result->setPeriodData($periodWriteOffData->getData(Sub\Db::DATA_PERIOD));
                 $result->setCalcData($periodWriteOffData->getData(Sub\Db::DATA_CALC));
                 $result->markSucceed();
             } else {
                 $this->_logger->info("There is no complete calculation for existing period. Use existing period data.");
                 $result->setCalcData($calcData);
                 $result->markSucceed();
             }
         }
     }
     $this->_logger->info("'Get latest period for Write Off calculation' operation is completed.");
     return $result;
 }
 /**
  * Registry next period if current period has complete calculation.
  *
  * @param \Praxigento\BonusBase\Service\Period\Response\GetForPvBasedCalc $result
  * @param int $calcTypeId
  * @param string $periodType see \Praxigento\Core\Tool\IPeriod::TYPE_*
  * @param \Praxigento\BonusBase\Data\Entity\Period $periodData
  * @return \Praxigento\BonusBase\Service\Period\Response\GetForPvBasedCalc
  */
 public function _registryNextPeriod(\Praxigento\BonusBase\Service\Period\Response\GetForPvBasedCalc $result, $calcTypeId, $periodType, \Praxigento\BonusBase\Data\Entity\Period $periodData)
 {
     $periodEnd = $periodData->getDstampEnd();
     /* calculate new period bounds */
     $periodNext = $this->_toolPeriod->getPeriodNext($periodEnd, $periodType);
     $dsNextBegin = $this->_toolPeriod->getPeriodFirstDate($periodNext);
     $dsNextEnd = $this->_toolPeriod->getPeriodLastDate($periodNext);
     /* check "right" bound according to now */
     $periodNow = $this->_toolPeriod->getPeriodCurrent(time(), $periodType);
     $dsNowEnd = $this->_toolPeriod->getPeriodLastDate($periodNow);
     if ($dsNextEnd < $dsNowEnd) {
         /* registry new period */
         /* create new period for given calculation type */
         $newPeriod = new EPeriod();
         $newPeriod->setCalcTypeId($calcTypeId);
         $newPeriod->setDstampBegin($dsNextBegin);
         $newPeriod->setDstampEnd($dsNextEnd);
         $periodId = $this->_repoPeriod->create($newPeriod);
         $newPeriod->setId($periodId);
         /* create related calculation */
         $newCalc = new ECalculation();
         $newCalc->setPeriodId($periodId);
         $dateStarted = $this->_toolDate->getUtcNowForDb();
         $newCalc->setDateStarted($dateStarted);
         $newCalc->setState(Cfg::CALC_STATE_STARTED);
         $calcId = $this->_repoCalc->create($newCalc);
         $newCalc->setId($calcId);
         $result->setPeriodData($newPeriod);
         $result->setCalcData($newCalc);
     } else {
         $msg = "New period can be registered in the past only (to register: {$dsNextBegin}-{$dsNextEnd}, " . "current end: {$dsNowEnd}).";
         $this->_logger->warning($msg);
         $result->setErrorCode(ResponsePv::ERR_PERIOD_CAN_BE_REGISTERED_IN_PAST_ONLY);
     }
     return $result;
 }