diff --git a/.gitignore b/.gitignore index d237420..6c4904f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .idea/* vendor +tests/logs/* composer.phar phpunit.xml composer.lock \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index e041c29..69ba8f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # bonus-server-php-sdk change log +## 0.5.1 (20.08.2018) +- исправлена ошибка с точностью в парсере timestamp `Rarus\BonusServer\Util\DateTimeParser` [issue#55](https://github.com/rarus/bonus-server-php-sdk/issues/55) +- исправлена ошибка с некорректными датами рождения при добавлении новых пользователей [issue#55](https://github.com/rarus/bonus-server-php-sdk/issues/55) +- исправлена ошибка с получением пустого логина для всех пользователей [issue#55](https://github.com/rarus/bonus-server-php-sdk/issues/55) +- подробный лог работы юнит-тестов теперь сохраняется в папке `/tests/logs/` +- в ApiClient добавлена поддержка таймзон и метод `setTimezone` который позволяет указать нужную таймзону + ## 0.5.0 (6.08.2018) - исправлен ошибочный 404 статус если нет скидок, результаты рассчёта скидок стали опциональными [issue#36](https://github.com/rarus/bonus-server-php-sdk/issues/36) - для сущности `Cards` для роли `Organization` добавлен метод `getByBarcode` [issue#31](https://github.com/rarus/bonus-server-php-sdk/issues/31) diff --git a/src/Rarus/BonusServer/ApiClient.php b/src/Rarus/BonusServer/ApiClient.php index eb8c148..681bba8 100644 --- a/src/Rarus/BonusServer/ApiClient.php +++ b/src/Rarus/BonusServer/ApiClient.php @@ -57,6 +57,10 @@ class ApiClient * @var float number of seconds to wait while trying to connect to a server. Use 0 to wait indefinitely (the default behavior). */ protected $connectTimeout; + /** + * @var \DateTimeZone временная зона в которой работает API-клиент, по умолчанию берётся зона установленная на сервере + */ + protected $timezone; /** * ApiClient constructor. @@ -67,15 +71,16 @@ class ApiClient */ public function __construct(string $apiEndpointUrl, GuzzleHttp\ClientInterface $obHttpClient, LoggerInterface $obLogger = null) { - $this->apiEndpoint = $apiEndpointUrl; - $this->httpClient = $obHttpClient; - $this->setConnectTimeout(2.0); - if ($obLogger !== null) { $this->log = $obLogger; } else { $this->log = new NullLogger(); } + $this->apiEndpoint = $apiEndpointUrl; + $this->httpClient = $obHttpClient; + $this->setConnectTimeout(2.0); + $this->setTimezone(new \DateTimeZone(date_default_timezone_get())); + $this->guzzleHandlerStack = GuzzleHttp\HandlerStack::create(); $this->log->debug( @@ -83,6 +88,7 @@ public function __construct(string $apiEndpointUrl, GuzzleHttp\ClientInterface $ [ 'url' => $apiEndpointUrl, 'connect_timeout' => $this->getConnectTimeout(), + 'timezone' => $this->getTimezone()->getName(), ] ); } @@ -97,10 +103,42 @@ public function getConnectTimeout(): float /** * @param float $connectTimeout + * + * @return ApiClient */ - public function setConnectTimeout(float $connectTimeout): void + public function setConnectTimeout(float $connectTimeout): ApiClient { + $this->log->debug('rarus.bonus.server.apiClient.setConnectTimeout.start', [ + 'connectTimeout' => $connectTimeout, + ]); $this->connectTimeout = $connectTimeout; + $this->log->debug('rarus.bonus.server.apiClient.setConnectTimeout.finish'); + + return $this; + } + + /** + * @return \DateTimeZone + */ + public function getTimezone(): \DateTimeZone + { + return $this->timezone; + } + + /** + * @param \DateTimeZone $timezone + * + * @return ApiClient + */ + public function setTimezone(\DateTimeZone $timezone): ApiClient + { + $this->log->debug('rarus.bonus.server.apiClient.setTimezone.start', [ + 'name' => $timezone->getName(), + ]); + $this->timezone = $timezone; + $this->log->debug('rarus.bonus.server.apiClient.setTimezone.finish'); + + return $this; } /** @@ -381,9 +419,15 @@ protected function getGuzzleHandlerStack(): GuzzleHttp\HandlerStack /** * @param GuzzleHttp\HandlerStack $guzzleHandlerStack + * + * @return ApiClient */ - public function setGuzzleHandlerStack(GuzzleHttp\HandlerStack $guzzleHandlerStack): void + public function setGuzzleHandlerStack(GuzzleHttp\HandlerStack $guzzleHandlerStack): ApiClient { + $this->log->debug('rarus.bonus.server.apiClient.setGuzzleHandlerStack.start'); $this->guzzleHandlerStack = $guzzleHandlerStack; + $this->log->debug('rarus.bonus.server.apiClient.setGuzzleHandlerStack.finish'); + + return $this; } } \ No newline at end of file diff --git a/src/Rarus/BonusServer/Cards/DTO/Fabric.php b/src/Rarus/BonusServer/Cards/DTO/Fabric.php index c3f11a5..e923ffc 100644 --- a/src/Rarus/BonusServer/Cards/DTO/Fabric.php +++ b/src/Rarus/BonusServer/Cards/DTO/Fabric.php @@ -19,13 +19,14 @@ class Fabric { /** - * @param array $arCard - * @param Currency $currency + * @param array $arCard + * @param Currency $currency + * @param \DateTimeZone $dateTimeZone * * @return Card * @throws \Rarus\BonusServer\Exceptions\ApiClientException */ - public static function initCardFromServerResponse(array $arCard, \Money\Currency $currency): Card + public static function initCardFromServerResponse(array $arCard, \Money\Currency $currency, \DateTimeZone $dateTimeZone): Card { $currencies = new ISOCurrencies(); $moneyParser = new DecimalMoneyParser($currencies); @@ -39,10 +40,10 @@ public static function initCardFromServerResponse(array $arCard, \Money\Currency ->setDescription((string)$arCard['description']) ->setCardLevelId(new LevelId((string)$arCard['card_level_id'])) ->setAccumSaleAmount($moneyParser->parse((string)$arCard['accum_sale_amount'], $currency->getCode())) - ->setCardStatus(Status\Fabric::initFromServerResponse($arCard)); + ->setCardStatus(Status\Fabric::initFromServerResponse($arCard, $dateTimeZone)); if ($arCard['date_last_transaction'] !== 0) { - $card->setDateLastTransaction(DateTimeParser::parseTimestampFromServerResponse((string)$arCard['date_last_transaction'])); + $card->setDateLastTransaction(DateTimeParser::parseTimestampFromServerResponse((string)$arCard['date_last_transaction'], $dateTimeZone)); } if ($arCard['last_transaction'] !== '') { $card->setLastTransaction((string)$arCard['last_transaction']); diff --git a/src/Rarus/BonusServer/Cards/DTO/Status/Fabric.php b/src/Rarus/BonusServer/Cards/DTO/Status/Fabric.php index 9985e88..f95bc5f 100644 --- a/src/Rarus/BonusServer/Cards/DTO/Status/Fabric.php +++ b/src/Rarus/BonusServer/Cards/DTO/Status/Fabric.php @@ -9,12 +9,13 @@ class Fabric { /** - * @param array $arCard + * @param array $arCard + * @param \DateTimeZone $dateTimeZone * * @return CardStatus * @throws \Rarus\BonusServer\Exceptions\ApiClientException */ - public static function initFromServerResponse(array $arCard): CardStatus + public static function initFromServerResponse(array $arCard, \DateTimeZone $dateTimeZone): CardStatus { $cardStatus = (new CardStatus()) ->setIsActive((bool)$arCard['active']) @@ -22,10 +23,10 @@ public static function initFromServerResponse(array $arCard): CardStatus ->setBlockedDescription((string)$arCard['blockeddescription']); if ($arCard['date_active'] !== 0) { - $cardStatus->setDateActivate(DateTimeParser::parseTimestampFromServerResponse((string)$arCard['date_active'])); + $cardStatus->setDateActivate(DateTimeParser::parseTimestampFromServerResponse((string)$arCard['date_active'], $dateTimeZone)); } if ($arCard['date_deactivate'] !== 0) { - $cardStatus->setDateDeactivate(DateTimeParser::parseTimestampFromServerResponse((string)$arCard['date_deactivate'])); + $cardStatus->setDateDeactivate(DateTimeParser::parseTimestampFromServerResponse((string)$arCard['date_deactivate'], $dateTimeZone)); } return $cardStatus; diff --git a/src/Rarus/BonusServer/Cards/DTO/TransactionAmount/Fabric.php b/src/Rarus/BonusServer/Cards/DTO/TransactionAmount/Fabric.php index 4336a45..acbbc02 100644 --- a/src/Rarus/BonusServer/Cards/DTO/TransactionAmount/Fabric.php +++ b/src/Rarus/BonusServer/Cards/DTO/TransactionAmount/Fabric.php @@ -17,18 +17,19 @@ class Fabric { /** - * @param Currency $currency - * @param array $arTransactionAmount + * @param Currency $currency + * @param array $arTransactionAmount + * @param \DateTimeZone $dateTimeZone * * @return TransactionAmount * @throws \Rarus\BonusServer\Exceptions\ApiClientException */ - public static function initFromServerResponse(Currency $currency, array $arTransactionAmount): TransactionAmount + public static function initFromServerResponse(Currency $currency, array $arTransactionAmount, \DateTimeZone $dateTimeZone): TransactionAmount { $moneyParser = new DecimalMoneyParser(new ISOCurrencies()); return (new TransactionAmount()) ->setTransactionSum($moneyParser->parse((string)$arTransactionAmount['sum'], $currency->getCode())) - ->setDate(DateTimeParser::parseTimestampFromServerResponse((string)$arTransactionAmount['date'])); + ->setDate(DateTimeParser::parseTimestampFromServerResponse((string)$arTransactionAmount['date'], $dateTimeZone)); } } \ No newline at end of file diff --git a/src/Rarus/BonusServer/Cards/Transport/Role/Organization/Transport.php b/src/Rarus/BonusServer/Cards/Transport/Role/Organization/Transport.php index abbe0bb..683cedb 100644 --- a/src/Rarus/BonusServer/Cards/Transport/Role/Organization/Transport.php +++ b/src/Rarus/BonusServer/Cards/Transport/Role/Organization/Transport.php @@ -113,7 +113,7 @@ public function list(BonusServer\Transport\DTO\Pagination $pagination): BonusSer $cardCollection = new BonusServer\Cards\DTO\CardCollection(); foreach ((array)$requestResult['cards'] as $card) { - $cardCollection->attach(BonusServer\Cards\DTO\Fabric::initCardFromServerResponse($card, $this->getDefaultCurrency())); + $cardCollection->attach(BonusServer\Cards\DTO\Fabric::initCardFromServerResponse($card, $this->getDefaultCurrency(), $this->apiClient->getTimezone())); } $paginationResponse = new BonusServer\Cards\Transport\DTO\PaginationResponse( @@ -146,19 +146,25 @@ public function getByUser(BonusServer\Users\DTO\User $user, ?BonusServer\Transpo 'phone' => $user->getPhone(), ]); - $requestResult = $this->apiClient->executeApiRequest( - sprintf('/organization/card?%s&calculate_count=true&user_id=%s', - BonusServer\Transport\Formatters\Pagination::toRequestUri($pagination), - $user->getUserId()->getId() - ), - RequestMethodInterface::METHOD_GET - ); - $cardCollection = new BonusServer\Cards\DTO\CardCollection(); - foreach ((array)$requestResult['cards'] as $card) { - $cardCollection->attach(BonusServer\Cards\DTO\Fabric::initCardFromServerResponse($card, $this->getDefaultCurrency())); + try { + $requestResult = $this->apiClient->executeApiRequest( + sprintf('/organization/card?%s&calculate_count=true&user_id=%s', + BonusServer\Transport\Formatters\Pagination::toRequestUri($pagination), + $user->getUserId()->getId() + ), + RequestMethodInterface::METHOD_GET + ); + foreach ((array)$requestResult['cards'] as $card) { + $cardCollection->attach(BonusServer\Cards\DTO\Fabric::initCardFromServerResponse($card, $this->getDefaultCurrency(), $this->apiClient->getTimezone())); + } + $cardCollection->rewind(); + } catch (BonusServer\Exceptions\ApiClientException $exception) { + // если карты не найдены, то сервер возврашает 404 статус выставив 114 код в данном случае мы его подавляем + if ($exception->getCode() !== 114) { + throw $exception; + } } - $cardCollection->rewind(); $this->log->debug('rarus.bonus.server.cards.transport.organization.getByUser.finish', [ 'itemsCount' => $cardCollection->count(), @@ -216,7 +222,7 @@ public function getByCardId(BonusServer\Cards\DTO\CardId $cardId): BonusServer\C RequestMethodInterface::METHOD_GET ); - $card = BonusServer\Cards\DTO\Fabric::initCardFromServerResponse($requestResult['card'], $this->getDefaultCurrency()); + $card = BonusServer\Cards\DTO\Fabric::initCardFromServerResponse($requestResult['card'], $this->getDefaultCurrency(), $this->apiClient->getTimezone()); $this->log->debug('rarus.bonus.server.cards.transport.organization.getByCardId.finish', [ 'cardId' => $card->getCardId()->getId(), @@ -546,7 +552,7 @@ public function getByBarcode(BonusServer\Cards\DTO\Barcode\Barcode $cardBarcode) RequestMethodInterface::METHOD_GET ); - $card = BonusServer\Cards\DTO\Fabric::initCardFromServerResponse($requestResult['cards'][0], $this->getDefaultCurrency()); + $card = BonusServer\Cards\DTO\Fabric::initCardFromServerResponse($requestResult['cards'][0], $this->getDefaultCurrency(), $this->apiClient->getTimezone()); $this->log->debug('rarus.bonus.server.cards.transport.organization.getByBarcode.finish', [ 'cardId' => $card->getCardId()->getId(), @@ -579,7 +585,7 @@ public function getByFilter(BonusServer\Cards\DTO\CardFilter $cardFilter): Bonus ); foreach ((array)$requestResult['cards'] as $card) { - $cardCollection->attach(BonusServer\Cards\DTO\Fabric::initCardFromServerResponse($card, $this->getDefaultCurrency())); + $cardCollection->attach(BonusServer\Cards\DTO\Fabric::initCardFromServerResponse($card, $this->getDefaultCurrency(), $this->apiClient->getTimezone())); } $this->log->debug('rarus.bonus.server.cards.transport.organization.getByFilter.finish', [ diff --git a/src/Rarus/BonusServer/Cards/Transport/Role/User/Transport.php b/src/Rarus/BonusServer/Cards/Transport/Role/User/Transport.php index f2f3160..782bae1 100644 --- a/src/Rarus/BonusServer/Cards/Transport/Role/User/Transport.php +++ b/src/Rarus/BonusServer/Cards/Transport/Role/User/Transport.php @@ -34,7 +34,7 @@ public function list(): BonusServer\Cards\DTO\CardCollection $cardCollection = new BonusServer\Cards\DTO\CardCollection(); foreach ((array)$requestResult['cards'] as $card) { - $cardCollection->attach(BonusServer\Cards\DTO\Fabric::initCardFromServerResponse($card, $this->getDefaultCurrency())); + $cardCollection->attach(BonusServer\Cards\DTO\Fabric::initCardFromServerResponse($card, $this->getDefaultCurrency(), $this->apiClient->getTimezone())); } $this->log->debug('rarus.bonus.server.cards.transport.list.finish', [ diff --git a/src/Rarus/BonusServer/Transactions/DTO/Points/Fabric.php b/src/Rarus/BonusServer/Transactions/DTO/Points/Fabric.php index 686d5e5..b9831ac 100644 --- a/src/Rarus/BonusServer/Transactions/DTO/Points/Fabric.php +++ b/src/Rarus/BonusServer/Transactions/DTO/Points/Fabric.php @@ -24,13 +24,14 @@ class Fabric { /** - * @param Currency $currency - * @param array $arPointTransaction + * @param Currency $currency + * @param array $arPointTransaction + * @param \DateTimeZone $dateTimeZone * * @return PointTransaction * @throws \Rarus\BonusServer\Exceptions\ApiClientException */ - public static function initPointTransactionFromServerResponse(Currency $currency, array $arPointTransaction): PointTransaction + public static function initPointTransactionFromServerResponse(Currency $currency, array $arPointTransaction, \DateTimeZone $dateTimeZone): PointTransaction { $currencies = new ISOCurrencies(); $moneyParser = new DecimalMoneyParser($currencies); @@ -41,7 +42,7 @@ public static function initPointTransactionFromServerResponse(Currency $currency ->setPointId(new PointId((string)$arPointTransaction['id'])) ->setCardId(new CardId((string)$arPointTransaction['card_id'])) ->setMastercardId(new CardId((string)$arPointTransaction['mastercard_id'])) - ->setTime(DateTimeParser::parseTimestampFromServerResponse((string)$arPointTransaction['time'])) + ->setTime(DateTimeParser::parseTimestampFromServerResponse((string)$arPointTransaction['time'], $dateTimeZone)) ->setSum($moneyParser->parse((string)$arPointTransaction['sum'], $currency->getCode())) ->setType($arPointTransaction['type'] === 0 ? Type\Fabric::getRefund() : Type\Fabric::getSale()) ->setAuthor((string)$arPointTransaction['author']) @@ -50,34 +51,35 @@ public static function initPointTransactionFromServerResponse(Currency $currency ->setCashRegisterId(new CashRegisterId((string)$arPointTransaction['kkm_id'])) ->setShopId(new ShopId((string)$arPointTransaction['shop_id'])) ->setDocumentTypeId((string)$arPointTransaction['doc_type']) - ->setInvalidatePeriod(DateTimeParser::parseTimestampFromServerResponse((string)$arPointTransaction['invalidate_period'])) - ->setActivationPeriod(DateTimeParser::parseTimestampFromServerResponse((string)$arPointTransaction['activation_period'])) + ->setInvalidatePeriod(DateTimeParser::parseTimestampFromServerResponse((string)$arPointTransaction['invalidate_period'], $dateTimeZone)) + ->setActivationPeriod(DateTimeParser::parseTimestampFromServerResponse((string)$arPointTransaction['activation_period'], $dateTimeZone)) ->setDiscountId(new DiscountId((string)$arPointTransaction['discount_id'])); return $pointTrx; } /** - * @param Currency $currency - * @param array $arPoint + * @param Currency $currency + * @param array $arPoint + * @param \DateTimeZone $dateTimeZone * * @return Point * @throws \Rarus\BonusServer\Exceptions\ApiClientException */ - public static function initPointFromServerResponse(Currency $currency, array $arPoint): Point + public static function initPointFromServerResponse(Currency $currency, array $arPoint, \DateTimeZone $dateTimeZone): Point { $moneyParser = new DecimalMoneyParser(new ISOCurrencies()); $point = new Point(); $point ->setSum($moneyParser->parse((string)$arPoint['sum'], $currency->getCode())) - ->setDateCreate(DateTimeParser::parseTimestampFromServerResponse((string)$arPoint['date'])); + ->setDateCreate(DateTimeParser::parseTimestampFromServerResponse((string)$arPoint['date'], $dateTimeZone)); if ($arPoint['active_from'] !== 0) { - $point->setActiveFrom(DateTimeParser::parseTimestampFromServerResponse((string)$arPoint['active_from'])); + $point->setActiveFrom(DateTimeParser::parseTimestampFromServerResponse((string)$arPoint['active_from'], $dateTimeZone)); } if ($arPoint['active_to'] !== 0) { - $point->setActiveFrom(DateTimeParser::parseTimestampFromServerResponse((string)$arPoint['active_to'])); + $point->setActiveFrom(DateTimeParser::parseTimestampFromServerResponse((string)$arPoint['active_to'], $dateTimeZone)); } return $point; diff --git a/src/Rarus/BonusServer/Users/DTO/Fabric.php b/src/Rarus/BonusServer/Users/DTO/Fabric.php index da9f69e..289ebfe 100644 --- a/src/Rarus/BonusServer/Users/DTO/Fabric.php +++ b/src/Rarus/BonusServer/Users/DTO/Fabric.php @@ -15,15 +15,17 @@ class Fabric { /** - * @param array $arUser + * @param array $arUser + * @param \DateTimeZone $dateTimeZone * * @return User * @throws \Rarus\BonusServer\Exceptions\ApiClientException */ - public static function initUserFromServerResponse(array $arUser): User + public static function initUserFromServerResponse(array $arUser, \DateTimeZone $dateTimeZone): User { $user = (new User()) ->setUserId(new UserId($arUser['id'])) + ->setLogin($arUser['login']) ->setName($arUser['name']) ->setPhone($arUser['phone']) ->setStatus(Users\DTO\Status\Fabric::initFromServerResponse($arUser)) @@ -33,7 +35,12 @@ public static function initUserFromServerResponse(array $arUser): User $user->setGender(Users\DTO\Gender\Fabric::initFromServerResponse($arUser['gender'])); } if ($arUser['birthdate'] !== 0) { - $user->setBirthdate(DateTimeParser::parseTimestampFromServerResponse((string)$arUser['birthdate'])); + $gmtOffsetInSeconds = $dateTimeZone->getOffset(new \DateTime('now', $dateTimeZone)); + $realTimestamp = (int)$arUser['birthdate']; + $birthdateWithGmt = DateTimeParser::parseTimestampFromServerResponse((string)$realTimestamp, $dateTimeZone); + $birthday = \DateTime::createFromFormat('U', (string)($birthdateWithGmt->getTimestamp() + $gmtOffsetInSeconds), $dateTimeZone); + $birthday->setTimezone($dateTimeZone); + $user->setBirthdate($birthday); } return $user; diff --git a/src/Rarus/BonusServer/Users/DTO/PersonalInfo/Fabric.php b/src/Rarus/BonusServer/Users/DTO/PersonalInfo/Fabric.php index e4873fa..6abf559 100644 --- a/src/Rarus/BonusServer/Users/DTO/PersonalInfo/Fabric.php +++ b/src/Rarus/BonusServer/Users/DTO/PersonalInfo/Fabric.php @@ -14,12 +14,13 @@ class Fabric { /** - * @param array $arUserPersonalInfo + * @param array $arUserPersonalInfo + * @param \DateTimeZone $dateTimeZone * * @return PersonalInfo * @throws \Rarus\BonusServer\Exceptions\ApiClientException */ - public static function initFromServerResponse(array $arUserPersonalInfo): PersonalInfo + public static function initFromServerResponse(array $arUserPersonalInfo, \DateTimeZone $dateTimeZone): PersonalInfo { $personalInfo = new PersonalInfo(); @@ -30,7 +31,7 @@ public static function initFromServerResponse(array $arUserPersonalInfo): Person ->setGender(Users\DTO\Gender\Fabric::initFromServerResponse($arUserPersonalInfo['gender'])) ->setReceiveNotifications($arUserPersonalInfo['recieve_notifications']); if ($arUserPersonalInfo['birthdate'] !== 0) { - $personalInfo->setBirthday(DateTimeParser::parseTimestampFromServerResponse((string)$arUserPersonalInfo['birthdate'])); + $personalInfo->setBirthday(DateTimeParser::parseTimestampFromServerResponse((string)$arUserPersonalInfo['birthdate'], $dateTimeZone)); } if ($arUserPersonalInfo['image'] !== '') { $personalInfo->setImage($arUserPersonalInfo['image']); diff --git a/src/Rarus/BonusServer/Users/Formatters/User.php b/src/Rarus/BonusServer/Users/Formatters/User.php index 885b888..8b37288 100644 --- a/src/Rarus/BonusServer/Users/Formatters/User.php +++ b/src/Rarus/BonusServer/Users/Formatters/User.php @@ -3,6 +3,7 @@ namespace Rarus\BonusServer\Users\Formatters; +use phpDocumentor\Reflection\DocBlock\Tags\Var_; use Rarus\BonusServer; /** @@ -41,37 +42,73 @@ public static function toArray(BonusServer\Users\DTO\User $user): array * * @return array */ - public static function toArrayForCreateNewUser(BonusServer\Users\DTO\User $newUser): array + public static function toArrayForViewNewUserData(BonusServer\Users\DTO\User $newUser): array { return [ + 'login' => $newUser->getLogin(), + 'name' => $newUser->getName(), + 'email' => $newUser->getEmail(), + 'phone' => $newUser->getPhone(), + 'birthday' => $newUser->getBirthdate() === null ? null : $newUser->getBirthdate()->format(\DateTime::ATOM), + 'gender' => $newUser->getGender() === null ? null : $newUser->getGender()->getCode(), + 'imageUrl' => $newUser->getImageUrl(), + ]; + } + + /** + * @param BonusServer\Users\DTO\User $newUser + * @param \DateTimeZone $dateTimeZone + * + * @return array + */ + public static function toArrayForCreateNewUser(BonusServer\Users\DTO\User $newUser, \DateTimeZone $dateTimeZone): array + { + $arNewUser = [ 'login' => $newUser->getLogin(), 'name' => $newUser->getName(), 'phone' => $newUser->getPhone(), 'email' => $newUser->getEmail(), 'gender' => $newUser->getGender() === null ? '' : $newUser->getGender()->getCode(), - 'birthdate' => $newUser->getBirthdate() === null ? 0 : BonusServer\Util\DateTimeParser::convertToServerFormatTimestamp($newUser->getBirthdate()), ]; + if ($newUser->getBirthdate() !== null) { + $gmtOffsetInSeconds = $dateTimeZone->getOffset(new \DateTime('now', $dateTimeZone)); + $gmtTimestamp = (string)($newUser->getBirthdate()->getTimestamp() - $gmtOffsetInSeconds); + $arNewUser['birthdate'] = BonusServer\Util\DateTimeParser::convertToServerFormatTimestamp(\DateTime::createFromFormat('U', $gmtTimestamp, $dateTimeZone)); + } else { + $arNewUser['birthdate'] = 0; + } + + return $arNewUser; } /** - * @param BonusServer\Users\DTO\User $user + * @param BonusServer\Users\DTO\User $newUser + * @param \DateTimeZone $dateTimeZone * * @return array */ - public static function toArrayForImportNewUser(BonusServer\Users\DTO\User $user): array + public static function toArrayForImportNewUser(BonusServer\Users\DTO\User $newUser, \DateTimeZone $dateTimeZone): array { - return [ - 'id' => $user->getUserId()->getId(), - 'login' => $user->getLogin(), - 'name' => $user->getName(), - 'phone' => $user->getPhone(), - 'email' => $user->getEmail(), - 'gender' => $user->getGender() === null ? '' : $user->getGender()->getCode(), - 'birthdate' => $user->getBirthdate() === null ? 0 : $user->getBirthdate()->getTimestamp(), - 'isConfirmed' => $user->getStatus()->isConfirmed(), - 'isBlocked' => $user->getStatus()->isBlocked(), - 'blockedDescription' => $user->getStatus()->getBlockedDescription(), - 'password' => $user->getPasswordHash() ?? '', + $arNewUser = [ + 'id' => $newUser->getUserId()->getId(), + 'login' => $newUser->getLogin(), + 'name' => $newUser->getName(), + 'phone' => $newUser->getPhone(), + 'email' => $newUser->getEmail(), + 'gender' => $newUser->getGender() === null ? '' : $newUser->getGender()->getCode(), + 'isConfirmed' => $newUser->getStatus()->isConfirmed(), + 'isBlocked' => $newUser->getStatus()->isBlocked(), + 'blockedDescription' => $newUser->getStatus()->getBlockedDescription(), + 'password' => $newUser->getPasswordHash() ?? '', ]; + if ($newUser->getBirthdate() !== null) { + $gmtOffsetInSeconds = $dateTimeZone->getOffset(new \DateTime('now', $dateTimeZone)); + $gmtTimestamp = (string)($newUser->getBirthdate()->getTimestamp() - $gmtOffsetInSeconds); + $arNewUser['birthdate'] = BonusServer\Util\DateTimeParser::convertToServerFormatTimestamp(\DateTime::createFromFormat('U', $gmtTimestamp, $dateTimeZone)); + } else { + $arNewUser['birthdate'] = 0; + } + + return $arNewUser; } } \ No newline at end of file diff --git a/src/Rarus/BonusServer/Users/Transport/Role/Organization/Transport.php b/src/Rarus/BonusServer/Users/Transport/Role/Organization/Transport.php index 0328eef..125b85d 100644 --- a/src/Rarus/BonusServer/Users/Transport/Role/Organization/Transport.php +++ b/src/Rarus/BonusServer/Users/Transport/Role/Organization/Transport.php @@ -29,7 +29,7 @@ public function addNewUser(BonusServer\Users\DTO\User $newUser): BonusServer\Use $requestResult = $this->apiClient->executeApiRequest( '/organization/user/new', RequestMethodInterface::METHOD_POST, - BonusServer\Users\Formatters\User::toArrayForCreateNewUser($newUser) + BonusServer\Users\Formatters\User::toArrayForCreateNewUser($newUser, $this->apiClient->getTimezone()) ); // вычитываем юзера с сервера @@ -65,7 +65,7 @@ public function getByUserId(BonusServer\Users\DTO\UserId $userId): BonusServer\U RequestMethodInterface::METHOD_GET ); - $user = BonusServer\Users\DTO\Fabric::initUserFromServerResponse($requestResult['user']); + $user = BonusServer\Users\DTO\Fabric::initUserFromServerResponse($requestResult['user'], $this->apiClient->getTimezone()); $this->log->debug('rarus.bonus.server.users.transport.getByUserId.start', [ 'id' => $user->getUserId()->getId(), @@ -94,7 +94,7 @@ public function addNewUserAndAttachFreeCard(BonusServer\Users\DTO\User $newUser) '/organization/user/new', RequestMethodInterface::METHOD_POST, array_merge( - BonusServer\Users\Formatters\User::toArrayForCreateNewUser($newUser), + BonusServer\Users\Formatters\User::toArrayForCreateNewUser($newUser, $this->apiClient->getTimezone()), ['attach_free_card' => true] ) ); @@ -132,7 +132,7 @@ public function importNewUsers(BonusServer\Users\DTO\UserCollection $usersCollec // собираем пакет из юзеров foreach ($usersCollection as $user) { - $arNewUsers[] = BonusServer\Users\Formatters\User::toArrayForImportNewUser($user); + $arNewUsers[] = BonusServer\Users\Formatters\User::toArrayForImportNewUser($user, $this->apiClient->getTimezone()); } $this->apiClient->executeApiRequest( diff --git a/src/Rarus/BonusServer/Users/Transport/Role/User/Transport.php b/src/Rarus/BonusServer/Users/Transport/Role/User/Transport.php index 5da5882..20156f8 100644 --- a/src/Rarus/BonusServer/Users/Transport/Role/User/Transport.php +++ b/src/Rarus/BonusServer/Users/Transport/Role/User/Transport.php @@ -31,7 +31,7 @@ public function current(): BonusServer\Users\DTO\PersonalInfo\PersonalInfo RequestMethodInterface::METHOD_GET ); - $userPersonalInfo = BonusServer\Users\DTO\PersonalInfo\Fabric::initFromServerResponse($requestResult['user']); + $userPersonalInfo = BonusServer\Users\DTO\PersonalInfo\Fabric::initFromServerResponse($requestResult['user'], $this->apiClient->getTimezone()); $this->log->debug('rarus.bonus.server.users.transport.current.start', [ 'role' => 'user', diff --git a/src/Rarus/BonusServer/Util/DateTimeParser.php b/src/Rarus/BonusServer/Util/DateTimeParser.php index 4cd117f..a947dfc 100644 --- a/src/Rarus/BonusServer/Util/DateTimeParser.php +++ b/src/Rarus/BonusServer/Util/DateTimeParser.php @@ -12,25 +12,34 @@ */ class DateTimeParser { + /** + * @var int + */ + private const MIN_TIMESTAMP_LENGTH = 12; + /** * парсим время в виде timestamp + milliseconds * - * @param string $timestampStr + * @param string $timestampStr + * @param \DateTimeZone $dateTimeZone * * @return \DateTime * @throws ApiClientException */ - public static function parseTimestampFromServerResponse(string $timestampStr): \DateTime + public static function parseTimestampFromServerResponse(string $timestampStr, \DateTimeZone $dateTimeZone): \DateTime { - if (\strlen($timestampStr) < 13) { - throw new ApiClientException(sprintf('неизвестный формат времени в ответе сервера [%s], ожидали 13 или больше символов, получили %s', + if (\strlen($timestampStr) < self::MIN_TIMESTAMP_LENGTH) { + throw new ApiClientException(sprintf('неизвестный формат времени в ответе сервера [%s], ожидали %s или больше символов, получили %s', $timestampStr, + self::MIN_TIMESTAMP_LENGTH, \strlen($timestampStr) )); } - // отделяем миллисекунды - 4 последних цифры + // отделяем миллисекунды - 3 последних цифры $timestampStr = substr($timestampStr, 0, 9) . '.' . substr($timestampStr, 9); - $timestamp = \DateTime::createFromFormat('U.u', $timestampStr); + + $timestamp = \DateTime::createFromFormat('U.u', $timestampStr, $dateTimeZone); + $timestamp->setTimezone($dateTimeZone); if (false === $timestamp) { throw new ApiClientException(sprintf('ошибка при разборе поля время в ответе сервера [%s]', $timestampStr)); } @@ -47,6 +56,8 @@ public static function parseTimestampFromServerResponse(string $timestampStr): \ */ public static function convertToServerFormatTimestamp(\DateTime $dateTime): int { - return $dateTime->getTimestamp() * 10000; + return $dateTime->getTimestamp() * 1000; } + + } \ No newline at end of file diff --git a/tests/DemoDataGenerator.php b/tests/DemoDataGenerator.php index 4b9befb..99df54d 100644 --- a/tests/DemoDataGenerator.php +++ b/tests/DemoDataGenerator.php @@ -94,8 +94,54 @@ public static function createNewUser(): \Rarus\BonusServer\Users\DTO\User '+7978 888 22 22', 'grishi@rarus.ru', Users\DTO\Gender\Fabric::getMale(), - new DateTime('06.08.1995 00:00:00') + new DateTime('06.08.1995 00:00:00', \TestEnvironmentManager::getDefaultTimezone()) + ); + } + + /** + * @return Users\DTO\User + * @throws Exception + */ + public static function createNewUserWithSummerBirthday(): \Rarus\BonusServer\Users\DTO\User + { + return \Rarus\BonusServer\Users\DTO\Fabric::createNewInstance( + 'grishi-' . random_int(0, PHP_INT_MAX), + 'Михаил Гришин', + '+7978 888 22 22', + 'grishi@rarus.ru', + Users\DTO\Gender\Fabric::getMale(), + new DateTime('06.08.1995 00:00:00', \TestEnvironmentManager::getDefaultTimezone()) + ); + } + + /** + * @return Users\DTO\User + * @throws Exception + */ + public static function createNewUserWithWinterBirthday(): \Rarus\BonusServer\Users\DTO\User + { + return \Rarus\BonusServer\Users\DTO\Fabric::createNewInstance( + 'grishi-' . random_int(0, PHP_INT_MAX), + 'Михаил Гришин', + '+7978 888 22 22', + 'grishi@rarus.ru', + Users\DTO\Gender\Fabric::getMale(), + new DateTime('06.01.1995 00:00:00', \TestEnvironmentManager::getDefaultTimezone()) + ); + } + /** + * @return Users\DTO\User + * @throws Exception + */ + public static function createNewUserWithoutBirthday(): \Rarus\BonusServer\Users\DTO\User + { + return \Rarus\BonusServer\Users\DTO\Fabric::createNewInstance( + 'grishi-' . random_int(0, PHP_INT_MAX), + 'Михаил Гришин', + '+7978 888 22 22', + 'grishi@rarus.ru', + Users\DTO\Gender\Fabric::getMale() ); } diff --git a/tests/TestEnvironmentManager.php b/tests/TestEnvironmentManager.php index 77beff0..332411d 100644 --- a/tests/TestEnvironmentManager.php +++ b/tests/TestEnvironmentManager.php @@ -36,6 +36,10 @@ class TestEnvironmentManager * @var string */ private const LOG_FILE = 'rarus-bonus-service-integration-tests.log'; + /** + * @var string + */ + private const DEFAULT_TIMEZONE = 'Europe/Moscow'; /** * @return \Rarus\BonusServer\ApiClient @@ -57,7 +61,10 @@ public static function getInstanceForRoleOrganization(): \Rarus\BonusServer\ApiC $httpClient = new \GuzzleHttp\Client(); $apiClient = new Rarus\BonusServer\ApiClient(self::URL, new \GuzzleHttp\Client(), $log); - $apiClient->setGuzzleHandlerStack($guzzleHandlerStack); + $apiClient + ->setTimezone(new \DateTimeZone(self::DEFAULT_TIMEZONE)) + ->setGuzzleHandlerStack($guzzleHandlerStack); + $newAuthToken = $apiClient->getNewAuthToken($credentials); $apiClient->setAuthToken($newAuthToken); @@ -80,7 +87,7 @@ public static function getMonologInstance(): \Psr\Log\LoggerInterface $log->pushProcessor(new IntrospectionProcessor); $log->pushProcessor(new UidProcessor()); - $log->pushHandler(new \Monolog\Handler\StreamHandler(self::LOG_FILE, Logger::DEBUG)); + $log->pushHandler(new \Monolog\Handler\StreamHandler(__DIR__ . '/logs/' . self::LOG_FILE, Logger::DEBUG)); $log->pushHandler(new \Monolog\Handler\StreamHandler('php://stdout', Logger::WARNING)); } @@ -94,4 +101,12 @@ public static function getDefaultCurrency(): \Money\Currency { return new \Money\Currency('RUB'); } + + /** + * @return DateTimeZone + */ + public static function getDefaultTimezone(): \DateTimeZone + { + return new \DateTimeZone(self::DEFAULT_TIMEZONE); + } } \ No newline at end of file diff --git a/tests/src/Rarus/BonusServer/Cards/Transport/Role/Organization/TransportTest.php b/tests/src/Rarus/BonusServer/Cards/Transport/Role/Organization/TransportTest.php index 2114a17..10bca4c 100644 --- a/tests/src/Rarus/BonusServer/Cards/Transport/Role/Organization/TransportTest.php +++ b/tests/src/Rarus/BonusServer/Cards/Transport/Role/Organization/TransportTest.php @@ -313,6 +313,8 @@ public function testCanLevelUpMethod(): void $updatedCard = $this->cardTransport->levelUp($activatedCard); $this->assertNotEquals($activatedCard->getCardLevelId()->getId(), $updatedCard->getCardLevelId()->getId()); + + $this->cardTransport->delete($updatedCard); } /** diff --git a/tests/src/Rarus/BonusServer/Cards/Transport/Role/User/TransportTest.php b/tests/src/Rarus/BonusServer/Cards/Transport/Role/User/TransportTest.php index e5a8ab1..8bdf4cf 100644 --- a/tests/src/Rarus/BonusServer/Cards/Transport/Role/User/TransportTest.php +++ b/tests/src/Rarus/BonusServer/Cards/Transport/Role/User/TransportTest.php @@ -120,8 +120,8 @@ public function testGetBalanceInfo(): void $cards = $cardsUserRoleTransport->list(); foreach ($cards as $card) { $balance = $cardsUserRoleTransport->getBalanceInfo($card, $trxCount); - $this->assertGreaterThan(0, $balance->getAvailable()->getAmount()); - $this->assertGreaterThan(0, $balance->getTotal()->getAmount()); + $this->assertGreaterThan(-1, $balance->getAvailable()->getAmount()); + $this->assertGreaterThan(-1, $balance->getTotal()->getAmount()); } $this->shopTransport->delete($shop); } diff --git a/tests/src/Rarus/BonusServer/Users/Transport/Role/Organization/TransportTest.php b/tests/src/Rarus/BonusServer/Users/Transport/Role/Organization/TransportTest.php index d0226af..ae97787 100644 --- a/tests/src/Rarus/BonusServer/Users/Transport/Role/Organization/TransportTest.php +++ b/tests/src/Rarus/BonusServer/Users/Transport/Role/Organization/TransportTest.php @@ -50,6 +50,44 @@ public function testAddNewUserMethod(): void $this->assertEquals('grishi@rarus.ru', $user->getEmail()); $this->assertEquals($newUser->getBirthdate()->getTimestamp(), $user->getBirthdate()->getTimestamp()); + $this->assertEquals($newUser->getBirthdate()->format('d.m.Y H:i:s'), $user->getBirthdate()->format('d.m.Y H:i:s')); + } + + /** + * @covers \Rarus\BonusServer\Users\Transport\Role\Organization\Transport::addNewUser() + */ + public function testAddNewUserWithSummerBirthdayMethod(): void + { + $newUser = \DemoDataGenerator::createNewUserWithSummerBirthday(); + $user = $this->userTransport->addNewUser($newUser); + + $this->assertEquals($newUser->getEmail(), $user->getEmail()); + $this->assertEquals($newUser->getBirthdate()->getTimestamp(), $user->getBirthdate()->getTimestamp()); + $this->assertEquals($newUser->getBirthdate()->format('d.m.Y H:i:s'), $user->getBirthdate()->format('d.m.Y H:i:s')); + } + + /** + * @covers \Rarus\BonusServer\Users\Transport\Role\Organization\Transport::addNewUser() + */ + public function testAddNewUserWithWinterBirthdayMethod(): void + { + $newUser = \DemoDataGenerator::createNewUserWithWinterBirthday(); + $user = $this->userTransport->addNewUser($newUser); + + $this->assertEquals($newUser->getEmail(), $user->getEmail()); + $this->assertEquals($newUser->getBirthdate()->getTimestamp(), $user->getBirthdate()->getTimestamp()); + $this->assertEquals($newUser->getBirthdate()->format('d.m.Y H:i:s'), $user->getBirthdate()->format('d.m.Y H:i:s')); + } + + /** + * @covers \Rarus\BonusServer\Users\Transport\Role\Organization\Transport::addNewUser() + */ + public function testAddNewUserWithoutBirthday(): void + { + $newUser = \DemoDataGenerator::createNewUserWithoutBirthday(); + $user = $this->userTransport->addNewUser($newUser); + + $this->assertEquals(null, $user->getBirthdate()); } /** @@ -57,9 +95,11 @@ public function testAddNewUserMethod(): void */ public function testAddNewUserAndAttachFreeCardMethod(): void { - $user = $this->userTransport->addNewUserAndAttachFreeCard(\DemoDataGenerator::createNewUser()); + $newUser = \DemoDataGenerator::createNewUser(); + $user = $this->userTransport->addNewUserAndAttachFreeCard($newUser); // юзера вычитали корректного - $this->assertEquals('grishi@rarus.ru', $user->getEmail()); + $this->assertEquals($user->getLogin(), $newUser->getLogin()); + $cards = $this->cardTransport->getByUser($user); // у него одна привязанная карта $attachedCard = $cards->current();