From: VVF Date: Fri, 6 Mar 2026 13:45:41 +0000 (+0300) Subject: fix(TO8-22): нормализация окончаний строк CRLF→LF X-Git-Url: https://gitweb.erp-flowers.ru/?a=commitdiff_plain;h=0e34a74f5643013ab8bbfc040f8a54b86ef37685;p=erp24_rep%2Fyii-erp24%2F.git fix(TO8-22): нормализация окончаний строк CRLF→LF Файлы были сохранены с CRLF из-за WSL, конвертированы в LF для чистого diff в MR. Co-Authored-By: Claude Opus 4.6 --- diff --git a/erp24/migrations/m260306_100000_add_activated_fields_to_promocode.php b/erp24/migrations/m260306_100000_add_activated_fields_to_promocode.php index 9abfc781..866cfccc 100644 --- a/erp24/migrations/m260306_100000_add_activated_fields_to_promocode.php +++ b/erp24/migrations/m260306_100000_add_activated_fields_to_promocode.php @@ -1,29 +1,29 @@ -addColumn( - '{{%erp24.promocode}}', - 'activated_by', - $this->integer()->null()->comment('ID клиента, активировавшего промокод') - ); - $this->addColumn( - '{{%erp24.promocode}}', - 'activated_at', - $this->dateTime()->null()->comment('Дата и время активации промокода') - ); - } - - public function safeDown() - { - $this->dropColumn('{{%erp24.promocode}}', 'activated_at'); - $this->dropColumn('{{%erp24.promocode}}', 'activated_by'); - } -} +addColumn( + '{{%erp24.promocode}}', + 'activated_by', + $this->integer()->null()->comment('ID клиента, активировавшего промокод') + ); + $this->addColumn( + '{{%erp24.promocode}}', + 'activated_at', + $this->dateTime()->null()->comment('Дата и время активации промокода') + ); + } + + public function safeDown() + { + $this->dropColumn('{{%erp24.promocode}}', 'activated_at'); + $this->dropColumn('{{%erp24.promocode}}', 'activated_by'); + } +} diff --git a/erp24/records/Promocode.php b/erp24/records/Promocode.php index e268498d..995b7670 100644 --- a/erp24/records/Promocode.php +++ b/erp24/records/Promocode.php @@ -1,115 +1,115 @@ - 20], - [['bonus', 'duration', 'active', 'used', 'base', 'parent_id', 'created_by', 'updated_by', 'is_promo_balance'], 'integer'], - [['date_start', 'date_end', 'created_at', 'updated_at'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], - [['activated_by'], 'integer'], - [['activated_at'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], - [['updated_by', 'updated_at', 'activated_by', 'activated_at', 'generatePromocodeCount', 'generateFormat'], 'safe'], - ['generateFormat', 'in', 'range' => [self::FORMAT_DIGITS, self::FORMAT_ALPHANUMERIC]], - ]; - } - - public function attributeLabels() { - return [ - 'id' => 'ID', - 'code' => 'Code', - 'bonus' => 'Bonus', - 'duration' => 'Duration', - 'active' => 'Active', - 'used' => 'Used', - 'base' => 'Base', - 'parent_id' => 'Parent ID', - 'date_start' => 'Date Start', - 'date_end' => 'Date End', - 'created_by' => 'Created By', - 'updated_by' => 'Updated By', - 'created_at' => 'Created At', - 'updated_at' => 'Updated At', - 'activated_by' => 'Activated By', - 'activated_at' => 'Activated At', - ]; - } - - public function getCreatedBy() { - return $this->hasOne(Admin::class, ['id' => 'created_by']); - } - - public function getUpdatedBy() { - return $this->hasOne(Admin::class, ['id' => 'updated_by']); - } - - public function getParent() { - return $this->hasOne(Promocode::class, ['id' => 'parent_id']); - } - - /** - * Проверяет, можно ли активировать промокод. - * @return int|true true если можно, иначе error_id: - * 1 — не найден/неактивен - * 2 — уже использован - * 3 — просрочен - */ - public function isActivatable() - { - if ($this->active != self::ACTIVE_ON) { - return 1; - } - if ($this->used == self::USED_YES) { - return 2; - } - $now = date('Y-m-d H:i:s'); - if ($this->date_start > $now || $this->date_end < $now) { - return 3; - } - return true; - } -} + 20], + [['bonus', 'duration', 'active', 'used', 'base', 'parent_id', 'created_by', 'updated_by', 'is_promo_balance'], 'integer'], + [['date_start', 'date_end', 'created_at', 'updated_at'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + [['activated_by'], 'integer'], + [['activated_at'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], + [['updated_by', 'updated_at', 'activated_by', 'activated_at', 'generatePromocodeCount', 'generateFormat'], 'safe'], + ['generateFormat', 'in', 'range' => [self::FORMAT_DIGITS, self::FORMAT_ALPHANUMERIC]], + ]; + } + + public function attributeLabels() { + return [ + 'id' => 'ID', + 'code' => 'Code', + 'bonus' => 'Bonus', + 'duration' => 'Duration', + 'active' => 'Active', + 'used' => 'Used', + 'base' => 'Base', + 'parent_id' => 'Parent ID', + 'date_start' => 'Date Start', + 'date_end' => 'Date End', + 'created_by' => 'Created By', + 'updated_by' => 'Updated By', + 'created_at' => 'Created At', + 'updated_at' => 'Updated At', + 'activated_by' => 'Activated By', + 'activated_at' => 'Activated At', + ]; + } + + public function getCreatedBy() { + return $this->hasOne(Admin::class, ['id' => 'created_by']); + } + + public function getUpdatedBy() { + return $this->hasOne(Admin::class, ['id' => 'updated_by']); + } + + public function getParent() { + return $this->hasOne(Promocode::class, ['id' => 'parent_id']); + } + + /** + * Проверяет, можно ли активировать промокод. + * @return int|true true если можно, иначе error_id: + * 1 — не найден/неактивен + * 2 — уже использован + * 3 — просрочен + */ + public function isActivatable() + { + if ($this->active != self::ACTIVE_ON) { + return 1; + } + if ($this->used == self::USED_YES) { + return 2; + } + $now = date('Y-m-d H:i:s'); + if ($this->date_start > $now || $this->date_end < $now) { + return 3; + } + return true; + } +} diff --git a/erp24/tests/unit/controllers/BonusControllerPromoTest.php b/erp24/tests/unit/controllers/BonusControllerPromoTest.php index ebf3c918..0360ce71 100644 --- a/erp24/tests/unit/controllers/BonusControllerPromoTest.php +++ b/erp24/tests/unit/controllers/BonusControllerPromoTest.php @@ -1,261 +1,261 @@ -= 350 AND check_amount >= 1700 AND 350 > standard_max => промо - * 3. Иначе => стандартное списание - */ -class BonusControllerPromoTest extends Unit -{ - /** - * Промо-списание применяется: покупка 2000р, промо-баланс 350р, стандарт 200р (10%). - * 350 > 200 => промо выгоднее. - */ - public function testPromoAppliedWhenBetter() - { - $result = $this->calculateWriteOffChoice( - checkAmount: 2000, - amountReal: 2000, - bonusRate: 0.10, - promoBalance: 350 - ); - - $this->assertTrue($result['usePromoWriteOff']); - $this->assertSame(350, $result['writeOffBonuses']); - } - - /** - * Стандартное списание лучше: покупка 5000р, стандарт 500р (10%). - * 350 < 500 => стандартное выгоднее. - */ - public function testStandardBetterThanPromo() - { - $result = $this->calculateWriteOffChoice( - checkAmount: 5000, - amountReal: 5000, - bonusRate: 0.10, - promoBalance: 350 - ); - - $this->assertFalse($result['usePromoWriteOff']); - $this->assertSame(500, $result['writeOffBonuses']); - } - - /** - * Покупка слишком маленькая (< 1700р) — промо-списание не применяется. - */ - public function testCheckTooSmallForPromo() - { - $result = $this->calculateWriteOffChoice( - checkAmount: 1500, - amountReal: 1500, - bonusRate: 0.10, - promoBalance: 350 - ); - - $this->assertFalse($result['usePromoWriteOff']); - $this->assertSame(150, $result['writeOffBonuses']); - } - - /** - * Недостаточный промо-баланс (< 350р) — стандартное списание. - */ - public function testInsufficientPromoBalance() - { - $result = $this->calculateWriteOffChoice( - checkAmount: 2000, - amountReal: 2000, - bonusRate: 0.10, - promoBalance: 100 - ); - - $this->assertFalse($result['usePromoWriteOff']); - $this->assertSame(200, $result['writeOffBonuses']); - } - - /** - * При промо-списании кэшбек НЕ начисляется. - */ - public function testNoCashbackWithPromoWriteOff() - { - $result = $this->calculateWriteOffChoice( - checkAmount: 2000, - amountReal: 2000, - bonusRate: 0.10, - promoBalance: 350 - ); - - $this->assertTrue($result['usePromoWriteOff']); - // При промо-списании cashback = 0 - $this->assertSame(0, $result['cashback']); - } - - /** - * При стандартном списании кэшбек начисляется нормально. - */ - public function testCashbackWithStandardWriteOff() - { - $result = $this->calculateWriteOffChoice( - checkAmount: 5000, - amountReal: 5000, - bonusRate: 0.10, - promoBalance: 350, - cashbackRate: 0.10 - ); - - $this->assertFalse($result['usePromoWriteOff']); - $this->assertGreaterThan(0, $result['cashback']); - } - - /** - * Граничный случай: покупка ровно 1700р — промо применяется (>=). - */ - public function testExactMinCheckAmount() - { - $result = $this->calculateWriteOffChoice( - checkAmount: 1700, - amountReal: 1700, - bonusRate: 0.10, - promoBalance: 350 - ); - - // standard_max = 1700 * 0.10 = 170, 350 > 170 => промо - $this->assertTrue($result['usePromoWriteOff']); - } - - /** - * Граничный случай: промо-баланс ровно 350 — промо применяется (>=). - */ - public function testExactPromoBalance() - { - $result = $this->calculateWriteOffChoice( - checkAmount: 2000, - amountReal: 2000, - bonusRate: 0.10, - promoBalance: 350 - ); - - $this->assertTrue($result['usePromoWriteOff']); - } - - /** - * При промо-списании tip_sale должен быть 'promobonus'. - */ - public function testPromoTipSaleValue() - { - $result = $this->calculateWriteOffChoice( - checkAmount: 2000, - amountReal: 2000, - bonusRate: 0.10, - promoBalance: 350 - ); - - $this->assertSame(Promocode::TIP_SALE_PROMOBONUS, $result['tipSale']); - } - - /** - * При промо-списании обычный баланс НЕ уменьшается. - */ - public function testRegularBalanceUnchangedWithPromo() - { - $result = $this->calculateWriteOffChoice( - checkAmount: 2000, - amountReal: 2000, - bonusRate: 0.10, - promoBalance: 350, - userBalance: 500 - ); - - $this->assertTrue($result['usePromoWriteOff']); - // Обычный баланс остаётся неизменным при промо-списании - $this->assertSame(500, $result['userBalansNew']); - } - - /** - * При стандартном списании обычный баланс уменьшается. - */ - public function testRegularBalanceDecreasedWithStandard() - { - $result = $this->calculateWriteOffChoice( - checkAmount: 5000, - amountReal: 5000, - bonusRate: 0.10, - promoBalance: 350, - userBalance: 1000 - ); - - $this->assertFalse($result['usePromoWriteOff']); - // 1000 - 500 = 500 - $this->assertSame(500, $result['userBalansNew']); - } - - /** - * Воспроизводит алгоритм выбора списания из actionSale(). - * Это чистая логика без БД — тестируем алгоритм. - * - * Параметры соответствуют переменным в actionSale(): - * checkAmount -> amount_all - * amountReal -> amount_real - * summaNoWriteoffs -> summa_no_writeoffs (товары без списания) - */ - private function calculateWriteOffChoice( - int $checkAmount, - int $amountReal, - float $bonusRate, - float $promoBalance, - float $cashbackRate = 0.10, - int $userBalance = 10000, - int $requestedWriteOff = 0, - int $summaNoWriteoffs = 0 - ): array { - $promoWriteOffAmount = 350; - $promoMinCheckAmount = 1700; - - // Стандартный расчёт (как в actionSale) - $writeOffBonusesTheory = (int) round($amountReal * $bonusRate); - $writeOffBonuses = $requestedWriteOff ?: $writeOffBonusesTheory; - if ($writeOffBonuses > $writeOffBonusesTheory) { - $writeOffBonuses = $writeOffBonusesTheory; - } - if ($userBalance < $writeOffBonuses) { - $writeOffBonuses = $userBalance; - } - - // Промо-проверка (amount_all используется, не amount_real) - $usePromoWriteOff = false; - if ($promoBalance >= $promoWriteOffAmount - && $checkAmount >= $promoMinCheckAmount - && $promoWriteOffAmount > $writeOffBonusesTheory - ) { - $usePromoWriteOff = true; - $writeOffBonuses = $promoWriteOffAmount; - } - - // user_balans_new: при промо обычный баланс не трогается - $userBalansNew = $usePromoWriteOff ? $userBalance : ($userBalance - $writeOffBonuses); - - // Кэшбек: baza_back = amount_real + summa_no_writeoffs - write_off_bonuses - $bazaBack = $amountReal + $summaNoWriteoffs - $writeOffBonuses; - $cashback = $usePromoWriteOff ? 0 : (int) round($bazaBack * $cashbackRate); - - // tip_sale - $tipSale = $usePromoWriteOff ? Promocode::TIP_SALE_PROMOBONUS : 'sale'; - - return [ - 'usePromoWriteOff' => $usePromoWriteOff, - 'writeOffBonuses' => $writeOffBonuses, - 'cashback' => $cashback, - 'tipSale' => $tipSale, - 'userBalansNew' => $userBalansNew, - ]; - } -} += 350 AND check_amount >= 1700 AND 350 > standard_max => промо + * 3. Иначе => стандартное списание + */ +class BonusControllerPromoTest extends Unit +{ + /** + * Промо-списание применяется: покупка 2000р, промо-баланс 350р, стандарт 200р (10%). + * 350 > 200 => промо выгоднее. + */ + public function testPromoAppliedWhenBetter() + { + $result = $this->calculateWriteOffChoice( + checkAmount: 2000, + amountReal: 2000, + bonusRate: 0.10, + promoBalance: 350 + ); + + $this->assertTrue($result['usePromoWriteOff']); + $this->assertSame(350, $result['writeOffBonuses']); + } + + /** + * Стандартное списание лучше: покупка 5000р, стандарт 500р (10%). + * 350 < 500 => стандартное выгоднее. + */ + public function testStandardBetterThanPromo() + { + $result = $this->calculateWriteOffChoice( + checkAmount: 5000, + amountReal: 5000, + bonusRate: 0.10, + promoBalance: 350 + ); + + $this->assertFalse($result['usePromoWriteOff']); + $this->assertSame(500, $result['writeOffBonuses']); + } + + /** + * Покупка слишком маленькая (< 1700р) — промо-списание не применяется. + */ + public function testCheckTooSmallForPromo() + { + $result = $this->calculateWriteOffChoice( + checkAmount: 1500, + amountReal: 1500, + bonusRate: 0.10, + promoBalance: 350 + ); + + $this->assertFalse($result['usePromoWriteOff']); + $this->assertSame(150, $result['writeOffBonuses']); + } + + /** + * Недостаточный промо-баланс (< 350р) — стандартное списание. + */ + public function testInsufficientPromoBalance() + { + $result = $this->calculateWriteOffChoice( + checkAmount: 2000, + amountReal: 2000, + bonusRate: 0.10, + promoBalance: 100 + ); + + $this->assertFalse($result['usePromoWriteOff']); + $this->assertSame(200, $result['writeOffBonuses']); + } + + /** + * При промо-списании кэшбек НЕ начисляется. + */ + public function testNoCashbackWithPromoWriteOff() + { + $result = $this->calculateWriteOffChoice( + checkAmount: 2000, + amountReal: 2000, + bonusRate: 0.10, + promoBalance: 350 + ); + + $this->assertTrue($result['usePromoWriteOff']); + // При промо-списании cashback = 0 + $this->assertSame(0, $result['cashback']); + } + + /** + * При стандартном списании кэшбек начисляется нормально. + */ + public function testCashbackWithStandardWriteOff() + { + $result = $this->calculateWriteOffChoice( + checkAmount: 5000, + amountReal: 5000, + bonusRate: 0.10, + promoBalance: 350, + cashbackRate: 0.10 + ); + + $this->assertFalse($result['usePromoWriteOff']); + $this->assertGreaterThan(0, $result['cashback']); + } + + /** + * Граничный случай: покупка ровно 1700р — промо применяется (>=). + */ + public function testExactMinCheckAmount() + { + $result = $this->calculateWriteOffChoice( + checkAmount: 1700, + amountReal: 1700, + bonusRate: 0.10, + promoBalance: 350 + ); + + // standard_max = 1700 * 0.10 = 170, 350 > 170 => промо + $this->assertTrue($result['usePromoWriteOff']); + } + + /** + * Граничный случай: промо-баланс ровно 350 — промо применяется (>=). + */ + public function testExactPromoBalance() + { + $result = $this->calculateWriteOffChoice( + checkAmount: 2000, + amountReal: 2000, + bonusRate: 0.10, + promoBalance: 350 + ); + + $this->assertTrue($result['usePromoWriteOff']); + } + + /** + * При промо-списании tip_sale должен быть 'promobonus'. + */ + public function testPromoTipSaleValue() + { + $result = $this->calculateWriteOffChoice( + checkAmount: 2000, + amountReal: 2000, + bonusRate: 0.10, + promoBalance: 350 + ); + + $this->assertSame(Promocode::TIP_SALE_PROMOBONUS, $result['tipSale']); + } + + /** + * При промо-списании обычный баланс НЕ уменьшается. + */ + public function testRegularBalanceUnchangedWithPromo() + { + $result = $this->calculateWriteOffChoice( + checkAmount: 2000, + amountReal: 2000, + bonusRate: 0.10, + promoBalance: 350, + userBalance: 500 + ); + + $this->assertTrue($result['usePromoWriteOff']); + // Обычный баланс остаётся неизменным при промо-списании + $this->assertSame(500, $result['userBalansNew']); + } + + /** + * При стандартном списании обычный баланс уменьшается. + */ + public function testRegularBalanceDecreasedWithStandard() + { + $result = $this->calculateWriteOffChoice( + checkAmount: 5000, + amountReal: 5000, + bonusRate: 0.10, + promoBalance: 350, + userBalance: 1000 + ); + + $this->assertFalse($result['usePromoWriteOff']); + // 1000 - 500 = 500 + $this->assertSame(500, $result['userBalansNew']); + } + + /** + * Воспроизводит алгоритм выбора списания из actionSale(). + * Это чистая логика без БД — тестируем алгоритм. + * + * Параметры соответствуют переменным в actionSale(): + * checkAmount -> amount_all + * amountReal -> amount_real + * summaNoWriteoffs -> summa_no_writeoffs (товары без списания) + */ + private function calculateWriteOffChoice( + int $checkAmount, + int $amountReal, + float $bonusRate, + float $promoBalance, + float $cashbackRate = 0.10, + int $userBalance = 10000, + int $requestedWriteOff = 0, + int $summaNoWriteoffs = 0 + ): array { + $promoWriteOffAmount = 350; + $promoMinCheckAmount = 1700; + + // Стандартный расчёт (как в actionSale) + $writeOffBonusesTheory = (int) round($amountReal * $bonusRate); + $writeOffBonuses = $requestedWriteOff ?: $writeOffBonusesTheory; + if ($writeOffBonuses > $writeOffBonusesTheory) { + $writeOffBonuses = $writeOffBonusesTheory; + } + if ($userBalance < $writeOffBonuses) { + $writeOffBonuses = $userBalance; + } + + // Промо-проверка (amount_all используется, не amount_real) + $usePromoWriteOff = false; + if ($promoBalance >= $promoWriteOffAmount + && $checkAmount >= $promoMinCheckAmount + && $promoWriteOffAmount > $writeOffBonusesTheory + ) { + $usePromoWriteOff = true; + $writeOffBonuses = $promoWriteOffAmount; + } + + // user_balans_new: при промо обычный баланс не трогается + $userBalansNew = $usePromoWriteOff ? $userBalance : ($userBalance - $writeOffBonuses); + + // Кэшбек: baza_back = amount_real + summa_no_writeoffs - write_off_bonuses + $bazaBack = $amountReal + $summaNoWriteoffs - $writeOffBonuses; + $cashback = $usePromoWriteOff ? 0 : (int) round($bazaBack * $cashbackRate); + + // tip_sale + $tipSale = $usePromoWriteOff ? Promocode::TIP_SALE_PROMOBONUS : 'sale'; + + return [ + 'usePromoWriteOff' => $usePromoWriteOff, + 'writeOffBonuses' => $writeOffBonuses, + 'cashback' => $cashback, + 'tipSale' => $tipSale, + 'userBalansNew' => $userBalansNew, + ]; + } +} diff --git a/erp24/tests/unit/records/PromocodePromoTest.php b/erp24/tests/unit/records/PromocodePromoTest.php index ce67c6a8..3f2b6fd3 100644 --- a/erp24/tests/unit/records/PromocodePromoTest.php +++ b/erp24/tests/unit/records/PromocodePromoTest.php @@ -1,90 +1,90 @@ -active = Promocode::ACTIVE_ON; - $promo->used = Promocode::USED_NO; - $promo->date_start = date('Y-m-d H:i:s', strtotime('-1 day')); - $promo->date_end = date('Y-m-d H:i:s', strtotime('+30 day')); - - $this->assertTrue($promo->isActivatable()); - } - - /** - * Уже использованный промокод — error_id=2. - */ - public function testIsActivatableAlreadyUsed() - { - $promo = new Promocode(); - $promo->active = Promocode::ACTIVE_ON; - $promo->used = Promocode::USED_YES; - $promo->date_start = date('Y-m-d H:i:s', strtotime('-1 day')); - $promo->date_end = date('Y-m-d H:i:s', strtotime('+30 day')); - - $this->assertSame(2, $promo->isActivatable()); - } - - /** - * Неактивный промокод — error_id=1. - */ - public function testIsActivatableInactive() - { - $promo = new Promocode(); - $promo->active = Promocode::ACTIVE_OFF; - $promo->used = Promocode::USED_NO; - $promo->date_start = date('Y-m-d H:i:s', strtotime('-1 day')); - $promo->date_end = date('Y-m-d H:i:s', strtotime('+30 day')); - - $this->assertSame(1, $promo->isActivatable()); - } - - /** - * Просроченный промокод (date_end в прошлом) — error_id=3. - */ - public function testIsActivatableExpired() - { - $promo = new Promocode(); - $promo->active = Promocode::ACTIVE_ON; - $promo->used = Promocode::USED_NO; - $promo->date_start = date('Y-m-d H:i:s', strtotime('-30 day')); - $promo->date_end = date('Y-m-d H:i:s', strtotime('-1 day')); - - $this->assertSame(3, $promo->isActivatable()); - } - - /** - * Промокод ещё не начал действовать (date_start в будущем) — error_id=3. - */ - public function testIsActivatableNotStartedYet() - { - $promo = new Promocode(); - $promo->active = Promocode::ACTIVE_ON; - $promo->used = Promocode::USED_NO; - $promo->date_start = date('Y-m-d H:i:s', strtotime('+1 day')); - $promo->date_end = date('Y-m-d H:i:s', strtotime('+30 day')); - - $this->assertSame(3, $promo->isActivatable()); - } - - /** - * Константа TIP_SALE_PROMOBONUS имеет правильное значение. - */ - public function testTipSalePromobonusConstant() - { - $this->assertSame('promobonus', Promocode::TIP_SALE_PROMOBONUS); - } -} +active = Promocode::ACTIVE_ON; + $promo->used = Promocode::USED_NO; + $promo->date_start = date('Y-m-d H:i:s', strtotime('-1 day')); + $promo->date_end = date('Y-m-d H:i:s', strtotime('+30 day')); + + $this->assertTrue($promo->isActivatable()); + } + + /** + * Уже использованный промокод — error_id=2. + */ + public function testIsActivatableAlreadyUsed() + { + $promo = new Promocode(); + $promo->active = Promocode::ACTIVE_ON; + $promo->used = Promocode::USED_YES; + $promo->date_start = date('Y-m-d H:i:s', strtotime('-1 day')); + $promo->date_end = date('Y-m-d H:i:s', strtotime('+30 day')); + + $this->assertSame(2, $promo->isActivatable()); + } + + /** + * Неактивный промокод — error_id=1. + */ + public function testIsActivatableInactive() + { + $promo = new Promocode(); + $promo->active = Promocode::ACTIVE_OFF; + $promo->used = Promocode::USED_NO; + $promo->date_start = date('Y-m-d H:i:s', strtotime('-1 day')); + $promo->date_end = date('Y-m-d H:i:s', strtotime('+30 day')); + + $this->assertSame(1, $promo->isActivatable()); + } + + /** + * Просроченный промокод (date_end в прошлом) — error_id=3. + */ + public function testIsActivatableExpired() + { + $promo = new Promocode(); + $promo->active = Promocode::ACTIVE_ON; + $promo->used = Promocode::USED_NO; + $promo->date_start = date('Y-m-d H:i:s', strtotime('-30 day')); + $promo->date_end = date('Y-m-d H:i:s', strtotime('-1 day')); + + $this->assertSame(3, $promo->isActivatable()); + } + + /** + * Промокод ещё не начал действовать (date_start в будущем) — error_id=3. + */ + public function testIsActivatableNotStartedYet() + { + $promo = new Promocode(); + $promo->active = Promocode::ACTIVE_ON; + $promo->used = Promocode::USED_NO; + $promo->date_start = date('Y-m-d H:i:s', strtotime('+1 day')); + $promo->date_end = date('Y-m-d H:i:s', strtotime('+30 day')); + + $this->assertSame(3, $promo->isActivatable()); + } + + /** + * Константа TIP_SALE_PROMOBONUS имеет правильное значение. + */ + public function testTipSalePromobonusConstant() + { + $this->assertSame('promobonus', Promocode::TIP_SALE_PROMOBONUS); + } +}