/**
  * @inheritdoc
  */
 public function apply($model)
 {
     if ($this->isDue() && in_array($model->ClassID, [6, 12])) {
         $userID = $model->contractor->id;
         \Yii::info('Проверка и применение акции "' . self::$name . '"' . "({$this->getModel()->id})" . ' для пользователя ' . Html::a($userID, ['/user/admin/update', 'id' => $userID]), 'info');
         $settings = $this->getModel()->parseSettings();
         if (empty($settings['attributes'])) {
             return false;
         }
         ArrayHelper::multisort($settings['attributes'], 'payment', SORT_DESC);
         $account = $model->contractor->account;
         foreach ($settings['attributes'] as $attributes) {
             $discount = $this->getModel()->getDiscount();
             $discount->setAttributes($attributes);
             if ($model->CashSum >= $discount->payment) {
                 \Yii::info('Применение акции с атрибутами: ' . Json::encode($attributes), 'info');
                 $account->BonusGames = $account->BonusGames + $discount->bonusGamesCount;
                 if ($account->save(false, ['BonusGames'])) {
                     $finance = new FinanceRecord();
                     $finance->CashSum = 0;
                     $finance->ClassID = 21;
                     //Начисление бонусов
                     $finance->ContractorID = $model->ContractorID;
                     $finance->Comment = $this->getDescription();
                     $finance->save();
                     return true;
                 }
             }
         }
     } else {
         //            var_export(in_array($model->ClassID, [6, 12]));
     }
     return false;
 }
 /**
  * Creates data provider instance with search query applied
  *
  * @param array $params
  *
  * @return ActiveDataProvider
  */
 public function search($params)
 {
     $query = FinanceRecord::find();
     $dataProvider = new ActiveDataProvider(['query' => $query, 'sort' => ['defaultOrder' => ['EventTime' => SORT_DESC, 'ID' => SORT_DESC], 'attributes' => ['EventTime' => ['asc' => ['EventTime' => SORT_ASC, 'ID' => SORT_ASC], 'desc' => ['EventTime' => SORT_DESC, 'ID' => SORT_DESC]], 'ID', 'ClassID', 'CashSum', 'ObjectID', 'CancelTime', 'Comment']], 'pagination' => ['pageSize' => 50]]);
     $this->load($params);
     if (!$this->validate()) {
         // uncomment the following line if you do not want to return any records when validation fails
         // $query->where('0=1');
         return $dataProvider;
     }
     if (!empty($this->dateRange)) {
         list($this->dateFrom, $this->dateTo) = preg_split('/\\s+-\\s+/', $this->dateRange);
         $formatter = Yii::$app->formatter;
         $this->dateFrom = $formatter->asDatetime($this->dateFrom, 'yyyy-MM-dd HH:mm:ss');
         $this->dateTo = $formatter->asDatetime($this->dateTo, 'yyyy-MM-dd HH:mm:ss');
         $query->andWhere(['and', ['>=', 'EventTime', $this->dateFrom], ['<=', 'EventTime', $this->dateTo]]);
     }
     $query->andFilterWhere(['ID' => $this->ID, 'ClassID' => $this->ClassID, 'AccountantID' => $this->AccountantID, 'ContractorID' => $this->ContractorID, 'ObjectID' => $this->ObjectID, 'FunctionID' => $this->FunctionID, 'CancelAccountID' => $this->CancelAccountID, 'CancelTime' => $this->CancelTime, 'Coins' => $this->Coins, 'Safe' => $this->Safe, 'RoomID' => $this->RoomID]);
     $query->andFilterWhere(['like', 'Comment', $this->Comment]);
     if (!empty($this->CashSum)) {
         if (preg_match('/^(?:\\s*(<>|<=|>=|<|>|=)){1}(.*)$/', $this->CashSum, $matches)) {
             $value = $matches[2];
             $op = $matches[1];
         } else {
             $value = $this->CashSum;
             $op = '=';
         }
         if (!empty($value)) {
             $query->andWhere('`CashSum`' . $op . $value);
         }
     }
     return $dataProvider;
 }
 public function actionIndex()
 {
     $formatter = Yii::$app->formatter;
     $query = FinanceRecord::find()->today()->exceptCancelled();
     $data = $query->asArray()->orderBy(['ID' => SORT_ASC, 'EventTime' => SORT_ASC])->all();
     $usersPerHour = [];
     if (count($data)) {
         /** @var FinanceRecord $finance */
         $usersPerHourData = ArrayHelper::map($data, function ($finance) use($formatter) {
             return $finance['ID'];
         }, function ($finance) {
             return $finance;
         }, function ($finance) use($formatter) {
             return $formatter->asDate($finance['EventTime'], 'php:H:00');
         });
         if (count($usersPerHourData) > 0) {
             $usersPerHour = ['labels' => array_keys($usersPerHourData), 'datasets' => [['label' => 'Количество уникальных посетителей в час', 'fillColor' => "rgba(250,100,0,0.8)", 'pointColor' => "rgba(220,220,220,1)", 'pointStrokeColor' => "#0f0", 'data' => []]]];
             foreach ($usersPerHourData as $day => $hFin) {
                 $objectUses = [];
                 foreach ($hFin as $id => $f) {
                     if ($f['ClassID'] == 1) {
                         $objectUses[] = $f['ContractorID'];
                     }
                 }
                 $usersPerHour['datasets'][0]['data'][] = count(array_unique($objectUses));
                 unset($objectUses);
             }
         }
     }
     $dataProvider = (new ActionsSearch(['attributes' => ['deleted' => 0]]))->search(Yii::$app->request->queryParams);
     return $this->render('index', ['usersPerHour' => $usersPerHour, 'dataProvider' => $dataProvider, 'cashBoxCash' => \common\models\cf\FinanceRecord::todayStats()]);
 }
 /**
  * @param $financeId FinanceRecord::$ID
  * @return mixed
  */
 public function actionPrint($financeId)
 {
     /** @var FinanceRecord $finance */
     if (($finance = FinanceRecord::findOne($financeId)) === null) {
         throw new NotFoundHttpException('The requested page does not exist.');
     }
     $model = new FinanceCheckRecord();
     $model->ContractorID = $finance->contractor->ID;
     $model->FinanceID = $finance->ID;
     $model->push($finance);
     $model->save();
     return $this->render('print', ['model' => $model]);
 }
 public function actionSellAction($id, $actionId)
 {
     $model = $this->findModel($id);
     /** @var ActionsRecord $action */
     $action = ActionsRecord::findOne($actionId);
     $formatter = Yii::$app->formatter;
     /** @var SellActionForm $formModel */
     $formModel = \Yii::createObject(SellActionForm::className());
     if ($formModel->load(Yii::$app->request->post()) && $formModel->validate()) {
         $sold = new SoldDiscountRecord();
         $sold->ActionID = $action->ID;
         $sold->PersonID = $model->person->id;
         $sold->DateFrom = time();
         $sold->DateTo = time() + 3600 * $formModel->amount;
         $cost = floatval($action->getDiscount()->price);
         $sum = $cost * $formModel->amount;
         $payment = new Payment($model);
         if ($payment->pay($sum) && $model->save(true, ['Money', 'Spend', 'Bonuses', 'SpendBonuses'])) {
             /** @var FinanceRecord $finance */
             $finance = Yii::createObject(FinanceRecord::className());
             $finance->ClassID = 22;
             //Оплата услуги
             $finance->Comment = $action->getDiscount()->description . ' x ' . $formModel->amount . ' x ' . $cost . '(c' . $formatter->asDatetime($sold->DateFrom) . ' по ' . $formatter->asDatetime($sold->DateTo) . ')';
             $finance->CashSum = $payment->getSpendAmount();
             $finance->ContractorID = $model->person->ID;
             $finance->save();
             $sold->FinanceRowID = $finance->id;
             $sold->save();
             Yii::$app->getSession()->setFlash('success', 'Акция продана, ' . Yii::$app->formatter->asCurrency($payment->getSpendAmount()) . ' списано со счета');
             return $this->redirect(['/user/admin/update', 'id' => $model->person->ID]);
         } else {
             Yii::$app->getSession()->setFlash('error', 'Недостаточно денег');
         }
     }
     return $this->render('sellAction', ['formModel' => $formModel, 'model' => $model, 'action' => $action]);
 }
 /**
  * Deletes an existing User model. Absolutely remove user from db if you are admin!
  * If deletion is successful, the browser will be redirected to the 'index' page.
  * @param  integer $id
  * @return mixed
  */
 public function actionDelete($id)
 {
     if ($id == Yii::$app->user->getId()) {
         Yii::$app->getSession()->setFlash('danger', Yii::t('user', 'You can not remove your own account'));
     } else {
         /** @var PersonsRecord $model */
         $model = $this->findModel($id);
         $isAdmin = Yii::$app->user->identity->isAdmin;
         if (!$isAdmin) {
             if (!$model->isDeleted) {
                 $model->updateAttributes(['Deleted' => 1]);
                 Yii::$app->getSession()->setFlash('success', Yii::t('user', 'User has been deleted'));
             } else {
                 $model->updateAttributes(['Deleted' => 0]);
                 Yii::$app->getSession()->setFlash('success', Yii::t('user', 'User has been recovered'));
             }
         } else {
             $userName = $model->fullName;
             if ($model->account->delete()) {
                 Yii::getLogger()->log('Удален аккаунт ' . $userName, Logger::LEVEL_WARNING);
                 //                        echo 'ACCOUNT DELETE OK'."\n";
             }
             if ($model->card) {
                 $hardId = $model->card->HardID;
                 if ($model->card->delete()) {
                     Yii::getLogger()->log('Удалена карта ' . $hardId, Logger::LEVEL_WARNING);
                     //                        echo 'CARD DELETE OK'."\n";
                 }
             } else {
                 Yii::warning('Карта пользователя НЕ найдена ' . $id . ' - ' . $userName, 'info');
             }
             if ($model->delete()) {
                 Yii::getLogger()->log('Удален пользователь ' . $id . ' - ' . $userName, Logger::LEVEL_WARNING);
                 $finRows = FinanceRecord::deleteAll(['ContractorID' => $id]);
                 Yii::warning('Удалены фин. записи (' . $finRows . ') для поьзователя ' . $id . ' - ' . $userName, 'info');
             }
         }
     }
     return $this->redirect(Url::previous('actions-redirect'));
 }
 /**
  * Finds the FinanceRecord model based on its primary key value.
  * If the model is not found, a 404 HTTP exception will be thrown.
  * @param integer $id
  * @return FinanceRecord the loaded model
  * @throws NotFoundHttpException if the model cannot be found
  */
 protected function findModel($id)
 {
     if (($model = FinanceRecord::findOne($id)) !== null) {
         return $model;
     } else {
         throw new NotFoundHttpException('The requested page does not exist.');
     }
 }
 /**
  * Step 3
  * @param $hardId
  * @return string|\yii\web\Response
  * @throws HttpException
  */
 public function actionCreateAccount($hardId, $groupId = '')
 {
     /** @var PersonsGroupRecord $group */
     if ($groupId !== '') {
         $group = PersonsGroupRecord::findOne($groupId);
     } else {
         $group = PersonsGroupRecord::getDefault();
     }
     /** @var PersonsRecord $user */
     $user = Yii::createObject(['class' => PersonsRecord::className(), 'scenario' => 'create']);
     /** @var CardForm $card */
     $card = \Yii::createObject(CardForm::className());
     $card->HardID = $hardId;
     if (!$card->isExist()) {
         $card = $card->create();
     } else {
         $card = $card->find();
     }
     if (!$card->ID) {
         throw new HttpException(400, 'Не удалось сохранить номер карты');
     }
     $user->CardID = $card->id;
     $user->GroupID = $group->id;
     $user->ServiceCard = $group->IsService;
     $this->performAjaxValidation($user);
     if ($user->load(Yii::$app->request->post()) && $user->create()) {
         /** @var FinanceRecord $finance */
         $finance = Yii::createObject(FinanceRecord::className());
         $finance->ClassID = 2;
         //Регистраци карты
         $finance->ContractorID = $user->ID;
         $finance->save();
         Yii::$app->getSession()->setFlash('success', Yii::t('user', 'User has been created'));
         return $this->redirect(['/accounts/charge-balance', 'id' => $user->account->id]);
     }
     return $this->render('createAccount', ['user' => $user]);
 }
 /**
  * Отмена всех сервисных операций
  */
 public function actionServiceFinances()
 {
     $persons = PersonsRecord::find()->where(['ServiceCard' => 1])->indexBy('ID')->all();
     /** @var PersonsRecord[] $persons */
     echo "Found " . sizeof($persons) . " service persons. Updating finance records...\n";
     $success = 0;
     foreach ($persons as $id => $person) {
         $success += FinanceRecord::updateAll(['CancelAccountID' => $id], ['ContractorID' => $id]);
     }
     echo " done updated: " . $success . "\n";
 }
 public function actionChangeCardSwipe($id, $broken = false)
 {
     /** @var PersonsRecord $user */
     $user = $this->findModel($id);
     /** @var CardForm $model */
     $model = \Yii::createObject(CardForm::className());
     if ($model->load(Yii::$app->request->post(), '') && $model->validate()) {
         if (!$model->isExist()) {
             $card = $model->create();
         } else {
             $card = $model->find();
         }
         if ($user->CardID !== $card->ID) {
             $personGroup = $user->group;
             if ($broken && null !== $personGroup && $personGroup->CardRepairCost > 0) {
                 if ($user->account->Money < $personGroup->CardRepairCost) {
                     throw new HttpException(400, 'У вас не достаточно средств для замены карты. Стоимость замены карты: ' . Yii::$app->formatter->asCurrency($personGroup->CardRepairCost));
                 } else {
                     if (!$user->updateAttributes(['CardID' => $card->ID])) {
                         throw new HttpException(400, 'Не удалось обновить номер карты');
                     }
                     $user->account->Money = $user->account->Money - $personGroup->CardRepairCost;
                     if ($user->account->save(false, ['Money'])) {
                         /** @var FinanceRecord $finance */
                         $finance = Yii::createObject(['class' => FinanceRecord::className()]);
                         $finance->ClassID = 19;
                         //Плата за восстановление карты
                         $finance->CashSum = $personGroup->CardRepairCost;
                         $finance->ContractorID = $id;
                         $finance->Comment = "Замена карты для пользователя " . Html::a($id, ['/user/admin/update', 'id' => $id]);
                         Yii::getLogger()->log($finance->Comment, Logger::LEVEL_WARNING);
                         $finance->save();
                     }
                     $flashMsg = 'Замена карты выполнена, со счета сянто: ' . Yii::$app->formatter->asCurrency($personGroup->CardRepairCost);
                     Yii::getLogger()->log($flashMsg, Logger::LEVEL_WARNING);
                     Yii::$app->getSession()->setFlash('success', $flashMsg);
                 }
             } else {
                 if (!$user->updateAttributes(['CardID' => $card->ID])) {
                     throw new HttpException(400, 'Не удалось обновить номер карты');
                 }
                 Yii::getLogger()->log("Замена карты для пользователя " . Html::a($id, ['/user/admin/update', 'id' => $id]), Logger::LEVEL_WARNING);
                 Yii::getLogger()->log('Замена карты выполнена', Logger::LEVEL_WARNING);
                 Yii::getLogger()->log('Замена карты выполнена', Logger::LEVEL_WARNING);
             }
         } else {
             throw new HttpException(400, 'Проведите другую карту');
         }
     } else {
         throw new HttpException(400, $model->getFirstError('HardID'));
     }
     return $this->redirect(['/user/admin/update', 'id' => $id]);
 }
 /**
  * @inheritdoc
  */
 public function rules()
 {
     return [[['AccountantID', 'ContractorID'], 'integer'], [['Items'], 'safe'], [['CashSum'], 'number', 'min' => 0], [['CashSum'], 'default', 'value' => 0], ['FinanceID', 'exist', 'targetClass' => FinanceRecord::className(), 'targetAttribute' => 'ID']];
 }
 /**
  * @param $from
  * @param $to
  * @param $personId
  * @param $allowCancelled
  * @return string
  * @throws \yii\base\InvalidConfigException
  */
 public function actionGenerate($from, $to, $personId = null, $allowCancelled = false)
 {
     $formatter = Yii::$app->formatter;
     /** @var ReportDataModel $data */
     $data = Yii::createObject(ReportDataModel::className());
     $data->fromDate = $from;
     $data->toDate = $to;
     //приход
     $_income = 0;
     //расход
     $_expense = 0;
     $data->orderCount = 0;
     $charges = [];
     $chargesWithRegistration = [];
     $ordersCash = [];
     /** @var array $objects */
     $objects = ObjectRecord::find()->indexBy('ID')->orderBy('Name')->asArray()->all();
     foreach ($objects as $oID => $obj) {
         $objects[$oID]['cash'] = 0;
     }
     $objectsStat = $objects;
     $objectsByDay = [];
     $data->actions = FinanceClassRecord::find()->indexBy('ID')->orderBy('Type')->where(['Deleted' => '0'])->asArray()->all();
     foreach ($data->actions as $aID => $act) {
         $data->actions[$aID]['count'] = 0;
         $data->actions[$aID]['cash'] = 0;
     }
     $query = FinanceRecord::find()->with('action')->leftJoin('tpersons', 'tfinance.ContractorID=tpersons.ID')->andWhere(['tpersons.Deleted' => 0])->andWhere(['tpersons.ServiceCard' => 0])->andWhere(['>=', 'EventTime', $from])->andWhere(['<=', 'EventTime', $to])->orderBy('EventTime');
     //Включить отмененные
     if (!$allowCancelled) {
         $query->andFilterWhere(['CancelAccountID' => 0]);
     }
     $query->asArray();
     foreach ($query->each() as $row) {
         $isAccountMatched = $personId != null && $personId == $row['AccountantID'];
         $EventTime = $row['EventTime'];
         $EventDay = $formatter->asDate($EventTime, 'php:D d-m-Y');
         //Отменено ?
         $cancelled = $row['CancelAccountID'] != 0;
         //if($cancelled && !$allowCancelled) continue;
         $type = $row['action']['Type'];
         $action = $row['action'];
         $cash = $row['CashSum'];
         if (!isset($data->actions[$action['ID']])) {
             $data->actions[$action['ID']] = $action;
             $data->actions[$action['ID']]['count'] = 0;
             $data->actions[$action['ID']]['cash'] = 0;
         }
         $data->actions[$action['ID']]['count']++;
         $data->actions[$action['ID']]['cash'] += $cash;
         if ($type == FinanceClassRecord::TYPE_IN) {
             if ($personId != null) {
                 if ($isAccountMatched) {
                     $_income += $cash;
                     if ($row['ClassID'] != 14 && $row['ClassID'] != 2) {
                         if ($cash > 0) {
                             $data->orderCount++;
                             $ordersCash[] = $cash;
                         }
                     }
                 }
             } else {
                 $_income += $cash;
                 if ($row['ClassID'] != 14 && $row['ClassID'] != 2) {
                     if ($cash > 0) {
                         $data->orderCount++;
                         $ordersCash[] = $cash;
                     }
                 }
             }
             //Регистрация карты
         } else {
             if ($type == FinanceClassRecord::TYPE_OUT) {
                 if ($personId != null) {
                     if ($isAccountMatched) {
                         $_expense += $cash;
                     }
                 } else {
                     $_expense += $cash;
                 }
             } else {
             }
         }
         switch ($row['ClassID']) {
             //Использование объектов
             case 1:
                 //total money
                 $data->totalSpend += $cash;
                 $data->totalSpendWithCard += $cash;
                 if (!isset($objects[$row['ObjectID']])) {
                     throw new Exception('объект не найден: №' . $row['ObjectID']);
                 }
                 $object = $objects[$row['ObjectID']];
                 //Total objects stat
                 //                    if(!isset($objectsStat[$object['ID']]['cash'])) {
                 //                        $objectsStat[$object['ID']]['cash'] = 0;
                 //                    }
                 $objectsStat[$object['ID']]['cash'] += $cash;
                 //Objects stat by days
                 if (!isset($objectsByDay[$EventDay])) {
                     $objectsByDay[$EventDay] = $objects;
                 }
                 //                    if(!isset($objectsByDay[$EventDay][$object['ID']])) {
                 //                        $objectsByDay[$EventDay][$object['ID']] = $object;
                 //                        $objectsByDay[$EventDay][$object['ID']]['cash'] = 0;
                 //                        $objectsByDay[$EventDay][$object['ID']]['EventTime'] = $EventTime;
                 //                    }
                 $objectsByDay[$EventDay][$object['ID']]['cash'] += $cash;
                 break;
                 //Покупка услуги|акции
             //Покупка услуги|акции
             case 22:
                 if ($personId != null) {
                     if ($isAccountMatched) {
                         $data->soldService[$row['ID']] = $row;
                         $data->soldService[$row['ID']]['cash'] = $cash;
                         $data->totalSpend += $cash;
                     }
                 } else {
                     $data->soldService[$row['ID']] = $row;
                     $data->soldService[$row['ID']]['cash'] = $cash;
                     $data->totalSpend += $cash;
                 }
                 break;
                 //Регистрация карты
             //Регистрация карты
             case 2:
                 if ($personId != null) {
                     if ($isAccountMatched) {
                         $data->totalIncomeFromCardRegistration += $cash;
                     }
                 } else {
                     $data->totalIncomeFromCardRegistration += $cash;
                 }
                 break;
                 //Залог
             //Залог
             case 14:
                 //идет в доход от регистрации
                 if ($personId != null) {
                     if ($isAccountMatched) {
                         $data->totalIncomeFromCardRegistration += $cash;
                     }
                 } else {
                     $data->totalIncomeFromCardRegistration += $cash;
                 }
                 break;
                 //Пополнение простое
             //Пополнение простое
             case 6:
                 if ($personId != null) {
                     if ($isAccountMatched) {
                         $data->chargeCount++;
                         $data->totalCharge += $cash;
                         $charges[] = $cash;
                         $data->currentCardDebt += $cash;
                     }
                 } else {
                     $data->chargeCount++;
                     $data->totalCharge += $cash;
                     $charges[] = $cash;
                     $data->currentCardDebt += $cash;
                 }
                 break;
                 //Пополнение при регистрации
             //Пополнение при регистрации
             case 12:
                 if ($personId != null) {
                     if ($isAccountMatched) {
                         $data->cardRegistrationCount++;
                         //в доход от регистрации
                         $data->totalIncomeFromCardRegistration += $cash;
                         //либо в пополнения
                         //$data->totalCharge += $cash;
                         $chargesWithRegistration[] = $cash;
                         $data->currentCardDebt += $cash;
                     }
                 } else {
                     $data->cardRegistrationCount++;
                     //в доход от регистрации
                     $data->totalIncomeFromCardRegistration += $cash;
                     //либо в пополнения
                     //$data->totalCharge += $cash;
                     $chargesWithRegistration[] = $cash;
                     $data->currentCardDebt += $cash;
                 }
                 break;
                 //Пополнение при регистрации подарочной карты
             //Пополнение при регистрации подарочной карты
             case 15:
                 if ($personId != null) {
                     if ($isAccountMatched) {
                         $data->cardGiftRegistrationCount++;
                         $data->totalIncomeFromGiftCardRegistration += $cash;
                         $chargesWithRegistration[] = $cash;
                     }
                 } else {
                     $data->cardGiftRegistrationCount++;
                     $data->totalIncomeFromGiftCardRegistration += $cash;
                     $chargesWithRegistration[] = $cash;
                 }
                 break;
                 //Снятие денег с карты
             //Снятие денег с карты
             case 7:
                 if ($personId != null) {
                     if ($isAccountMatched) {
                         $data->totalMoneyBackFromCard += $cash;
                     }
                 } else {
                     $data->totalMoneyBackFromCard += $cash;
                 }
                 break;
                 //Билеты на карту
             //Билеты на карту
             case 3:
                 $data->currentTicketsEmitted += $row['Coins'];
                 break;
                 //Обмен билетов на товар
             //Обмен билетов на товар
             case 4:
                 $data->currentTicketsSpend += $row['Coins'];
                 break;
                 //Возврат залога
             //Возврат залога
             case 13:
                 //возвращается на счет поэтому не имеет фин значения (type = 0)
                 break;
                 //Акционное попоплнение
             //Акционное попоплнение
             case 18:
                 if ($personId != null) {
                     if ($isAccountMatched) {
                         $data->currentBonusesEmitted += $cash;
                     }
                 } else {
                     $data->currentBonusesEmitted += $cash;
                 }
                 break;
                 //плата за замену карты
             //плата за замену карты
             case 19:
                 break;
                 //оплата бонусами
             //оплата бонусами
             case 20:
                 $data->currentBonusesSpend += $cash;
                 break;
                 //начисление бонусов
             //начисление бонусов
             case 21:
                 $data->currentBonusesEmitted += $cash;
                 break;
         }
     }
     $data->objects = $objectsStat;
     $data->objectsByDays = $objectsByDay;
     $data->sumIncome = $_income;
     $data->sumExpense = $_expense;
     $data->income = $data->sumIncome - $data->sumExpense;
     if (count($charges) > 0) {
         $data->averageChargeAmount = array_sum($charges) / count($charges);
     }
     if (count($chargesWithRegistration) > 0) {
         $data->averageRegistrationChargeAmount = array_sum($chargesWithRegistration) / count($chargesWithRegistration);
     }
     if (count($ordersCash) > 0) {
         $ordersCash = array_filter($ordersCash);
         $data->orderCount = count($ordersCash);
         $data->orderAvg = array_sum($ordersCash) / count($ordersCash);
         $data->orderMax = max($ordersCash);
         $data->orderMin = min($ordersCash);
     }
     /*
             $data->currentCardDebtPlusBonus = AccountRecord::find()
                 ->select('Money')
                 ->leftJoin('tpersons', 'taccount.PersonID=tpersons.ID')
                 ->where(['tpersons.ServiceCard'=>0])
                 ->andWhere(['>=', 'taccount.RegisterDate', $from])
                 ->andWhere(['<=', 'taccount.RegisterDate', $to])
                 ->andWhere(['taccount.Deleted'=>0])
                 ->sum('Money');
     */
     //Текущий дебет на карточках за выбранный период
     //        $data->currentCardDebt = FinanceRecord::find()
     //            ->andWhere(['CancelAccountID'=>0])
     //            ->andWhere(['>=', 'EventTime', $from])
     //            ->andWhere(['<=', 'EventTime', $to])
     //            ->andWhere(['in', 'ClassID', [6, 12]])
     //            ->sum('CashSum');
     //Дебет без бонусов
     $data->currentCardDebt = $data->currentCardDebt - $data->totalSpend;
     $data->currentCardDebtPlusBonus = $data->currentCardDebt + $data->currentBonusesEmitted;
     //Всего начислено бонусов
     //по журналу
     $data->totalBonusesEmitted = FinanceRecord::find()->leftJoin('tpersons', 'tfinance.ContractorID=tpersons.ID')->andWhere(['<=', 'tpersons.RegisterDate', $to])->andWhere(['in', 'tfinance.ClassID', [18, 21]])->andWhere(['tfinance.CancelAccountID' => 0])->andWhere(['tpersons.Deleted' => 0, 'tpersons.ServiceCard' => 0])->sum('tfinance.CashSum');
     //фактический бонусный дебет на аккаунтах
     $data->totalCardBonusDebt = AccountRecord::find()->leftJoin(PersonsRecord::tableName() . ' person', 'person.ID=taccount.PersonID')->andWhere(['<=', 'taccount.RegisterDate', $to])->select('taccount.Bonuses')->andWhere(['person.ServiceCard' => 0])->andWhere(['taccount.Deleted' => 0])->andWhere(['person.Deleted' => 0])->sum('taccount.Bonuses');
     //Фактически денег на счетах
     $data->totalCardDebt = AccountRecord::find()->leftJoin(PersonsRecord::tableName() . ' person', 'person.ID=taccount.PersonID')->andWhere(['<=', 'taccount.RegisterDate', $to])->select('taccount.Money')->andWhere(['person.ServiceCard' => 0])->andWhere(['taccount.Deleted' => 0])->sum('taccount.Money');
     //Общий дебет на карточках с бонусами
     $data->totalCardDebtPlusBonus = $data->totalCardDebt + $data->totalCardBonusDebt;
     //Билетов на картах
     $data->totalTickets = AccountRecord::find()->andWhere(['<=', 'RegisterDate', $to])->andWhere(['Deleted' => 0])->sum('Tickets');
     //Количество зарег сервисных карт
     $data->countServiceCardWasCreated = PersonsRecord::find()->andWhere(['>=', 'RegisterDate', $from])->andWhere(['<', 'RegisterDate', $to])->andWhere(['Deleted' => 0])->andWhere(['ServiceCard' => 1])->count();
     $file = $this->_create($data, PersonsRecord::findOne($personId));
     Yii::$app->response->sendFile($file, 'Report.' . $from . '-' . $to . '.xlsx');
 }
 /**
  * Общая статистика
  * @return string
  * @throws \yii\base\InvalidConfigException
  */
 public function actionIndex()
 {
     $formatter = Yii::$app->formatter;
     $query = FinanceRecord::find()->with('action', 'contractor.account.level')->andFilterWhere(['CancelAccountID' => 0])->orderBy(['EventTime' => SORT_ASC]);
     /** @var StatisticForm $model */
     $model = Yii::createObject(StatisticForm::className());
     if ($model->load(Yii::$app->request->post()) && $model->validate()) {
         $query->andWhere(['>=', 'EventTime', $model->dateFrom])->andWhere(['<=', 'EventTime', $model->dateTo]);
     } else {
         $model->dateFrom = $model->formatDateTime(time() - 3600 * 24 * 7);
         //$model->dateTo = $model->formatDateTime(time());
         $query->andWhere(['>=', 'EventTime', $model->dateFrom]);
         //->andWhere(['<=', 'EventTime', $model->dateTo]);
     }
     $data = $query->asArray()->all();
     /** @var FinanceRecord $finance */
     $usersPerDayData = ArrayHelper::map($data, function ($finance) use($formatter) {
         return $finance['ID'];
     }, function ($finance) {
         return $finance;
     }, function ($finance) use($formatter) {
         return $formatter->asDate($finance['EventTime'], 'php:l (d-M-Y)');
     });
     $usersPerHourData = ArrayHelper::map($data, function ($finance) use($formatter) {
         return $finance['ID'];
     }, function ($finance) {
         return $finance;
     }, function ($finance) use($formatter) {
         return $formatter->asDate($finance['EventTime'], 'php:H:00 (d-M-Y)');
     });
     if (count($usersPerHourData) > 0) {
         $usersPerHour = ['labels' => array_keys($usersPerHourData), 'datasets' => [['label' => 'Количество уникальных посетителей в час', 'pointColor' => "rgba(220,220,220,1)", 'pointStrokeColor' => "#0f0", 'borderWidth' => 0, 'data' => []]]];
         $incomePerHour = ['labels' => array_keys($usersPerHourData), 'datasets' => [['label' => 'Доход в час', 'pointColor' => "rgba(220,220,220,1)", 'pointStrokeColor' => "#0f0", 'borderWidth' => 0, 'data' => []]]];
         foreach ($usersPerHourData as $day => $hFin) {
             $objectUses = [];
             $incomsPerHour = 0;
             foreach ($hFin as $id => $f) {
                 if ($f['ClassID'] == 1) {
                     $objectUses[] = $f['ContractorID'];
                 }
                 $type = $f['action']['Type'];
                 if ($type == FinanceClassRecord::TYPE_IN) {
                     $incomsPerHour += $f['CashSum'];
                 } else {
                     if ($type == FinanceClassRecord::TYPE_OUT) {
                         $incomsPerHour = $incomsPerHour - $f['CashSum'];
                     }
                 }
             }
             $usersPerHour['datasets'][0]['data'][] = count(array_unique($objectUses));
             unset($objectUses);
             $incomePerHour['datasets'][0]['data'][] = $incomsPerHour;
         }
     } else {
         $usersPerHour = [];
         $incomePerHour = [];
     }
     if (count($usersPerDayData) > 0) {
         $dayLabels = array_keys($usersPerDayData);
         //Columns define
         $usersPerDay = ['labels' => $dayLabels, 'datasets' => [['label' => 'Количество уникальных посетителей по дням недели', 'fillColor' => "rgba(0,152,250,0.8)", 'strokeColor' => "rgba(220,220,220,1)", 'pointColor' => "rgba(220,220,220,1)", 'pointStrokeColor' => "#fff", 'data' => []]]];
         $incomePerDay = ['labels' => $dayLabels, 'datasets' => [['label' => 'Доход по дням недели', 'fillColor' => "rgba(0,250,120,0.8)", 'strokeColor' => "rgba(220,220,220,1)", 'pointColor' => "rgba(220,220,220,1)", 'pointStrokeColor' => "#fff", 'data' => []]]];
         $usersByLevel = [];
         $levels = [];
         foreach ($usersPerDayData as $day => $fin) {
             //Использование объектов
             //  и
             //Общий доход
             $incomsPerDay = 0;
             $objectUses = [];
             foreach ($fin as $id => $f) {
                 $type = $f['action']['Type'];
                 if ($type == FinanceClassRecord::TYPE_IN) {
                     $incomsPerDay += $f['CashSum'];
                 } else {
                     if ($type == FinanceClassRecord::TYPE_OUT) {
                         $incomsPerDay = $incomsPerDay - $f['CashSum'];
                     }
                 }
                 if ($f['ClassID'] == 1) {
                     $objectUses[] = $f['ContractorID'];
                 }
                 if (!isset($levels[$f['contractor']['account']['level']['Name']])) {
                     $levels[$f['contractor']['account']['level']['Name']] = [];
                 }
                 $levels[$f['contractor']['account']['level']['Name']][] = $f['ContractorID'];
             }
             $usersPerDay['datasets'][0]['data'][] = count(array_unique($objectUses));
             unset($objectUses);
             $incomePerDay['datasets'][0]['data'][] = $incomsPerDay;
         }
         $levelSectorsColours = [['color' => "#FDB45C", 'highlight' => "#FFC870"], ['color' => "#F7464A", 'highlight' => "#FF5A5E"], ['color' => "#CCC", 'highlight' => "#46BFBD"]];
         $usersByLevel['labels'] = array_keys($levels);
         $usersByLevel['datasets'] = [];
         foreach ($levels as $levelName => $userIds) {
             $colors = array_pop($levelSectorsColours);
             $usersByLevel['datasets'][0]['data'][] = count(array_unique($userIds));
             $usersByLevel['datasets'][0]['backgroundColor'][] = $colors['color'];
             $usersByLevel['datasets'][0]['hoverBackgroundColor'][] = $colors['highlight'];
         }
     } else {
         $usersPerHour = [];
         $usersPerDay = [];
         $incomePerDay = [];
         $usersByLevel = [];
     }
     return $this->render('index', ['model' => $model, 'usersPerHour' => $usersPerHour, 'usersPerDay' => $usersPerDay, 'incomePerDay' => $incomePerDay, 'incomePerHour' => $incomePerHour, 'usersByLevel' => $usersByLevel]);
 }