ShopPromotion.php 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. <?php
  2. namespace App\Module\Shop\Models;
  3. use Illuminate\Database\Eloquent\Relations\BelongsToMany;
  4. use Illuminate\Database\Eloquent\Relations\HasMany;
  5. use UCore\ModelCore;
  6. /**
  7. * 商店促销活动模型
  8. *
  9. * field start
  10. * @property int $id 促销ID,主键
  11. * @property string $name 促销名称
  12. * @property string $description 促销描述
  13. * @property string $banner 促销横幅图片
  14. * @property int $discount_type 折扣类型(1:固定折扣, 2:百分比折扣)
  15. * @property int $discount_value 折扣值(固定折扣为具体金额,百分比折扣为1-100的整数)
  16. * @property bool $is_active 是否激活(0:否, 1:是)
  17. * @property int $sort_order 排序权重
  18. * @property string $start_time 开始时间
  19. * @property string $end_time 结束时间
  20. * @property \Carbon\Carbon $created_at 创建时间
  21. * @property \Carbon\Carbon $updated_at 更新时间
  22. * field end
  23. */
  24. class ShopPromotion extends ModelCore
  25. {
  26. /**
  27. * 与模型关联的表名
  28. *
  29. * @var string
  30. */
  31. protected $table = 'shop_promotions';
  32. /**
  33. * 可批量赋值的属性
  34. *
  35. * @var array
  36. */
  37. protected $fillable = [
  38. 'name',
  39. 'description',
  40. 'banner',
  41. 'discount_type',
  42. 'discount_value',
  43. 'is_active',
  44. 'sort_order',
  45. 'start_time',
  46. 'end_time',
  47. ];
  48. /**
  49. * 应该被转换为日期的属性
  50. *
  51. * @var array
  52. */
  53. protected $dates = [
  54. 'start_time',
  55. 'end_time',
  56. 'created_at',
  57. 'updated_at',
  58. ];
  59. /**
  60. * 应该被转换为原生类型的属性
  61. *
  62. * @var array
  63. */
  64. protected $casts = [
  65. 'is_active' => 'boolean',
  66. ];
  67. /**
  68. * 折扣类型:固定折扣
  69. */
  70. const DISCOUNT_TYPE_FIXED = 1;
  71. /**
  72. * 折扣类型:百分比折扣
  73. */
  74. const DISCOUNT_TYPE_PERCENTAGE = 2;
  75. /**
  76. * 获取折扣类型文本
  77. *
  78. * @return string
  79. */
  80. public function getDiscountTypeTextAttribute(): string
  81. {
  82. return match ($this->discount_type) {
  83. self::DISCOUNT_TYPE_FIXED => '固定折扣',
  84. self::DISCOUNT_TYPE_PERCENTAGE => '百分比折扣',
  85. default => '未知',
  86. };
  87. }
  88. /**
  89. * 获取该促销活动关联的商品
  90. *
  91. * @return BelongsToMany
  92. */
  93. public function items(): BelongsToMany
  94. {
  95. return $this->belongsToMany(
  96. ShopItem::class,
  97. 'shop_promotion_items',
  98. 'promotion_id',
  99. 'shop_item_id'
  100. )->withPivot('custom_discount_value')
  101. ->withTimestamps();
  102. }
  103. /**
  104. * 获取促销活动的商品关联记录
  105. *
  106. * @return HasMany
  107. */
  108. public function promotionItems(): HasMany
  109. {
  110. return $this->hasMany(ShopPromotionItem::class, 'promotion_id');
  111. }
  112. /**
  113. * 检查促销活动是否有效
  114. *
  115. * @return bool
  116. */
  117. public function isValid(): bool
  118. {
  119. if (!$this->is_active) {
  120. return false;
  121. }
  122. $now = now();
  123. if ($this->start_time && $now < $this->start_time) {
  124. return false;
  125. }
  126. if ($this->end_time && $now > $this->end_time) {
  127. return false;
  128. }
  129. return true;
  130. }
  131. /**
  132. * 计算折扣后的价格
  133. *
  134. * @param int $originalPrice 原价
  135. * @param int|null $customDiscountValue 自定义折扣值
  136. * @return int 折扣后的价格
  137. */
  138. public function calculateDiscountedPrice(int $originalPrice, ?int $customDiscountValue = null): int
  139. {
  140. $discountValue = $customDiscountValue ?? $this->discount_value;
  141. if ($this->discount_type === self::DISCOUNT_TYPE_FIXED) {
  142. return max(0, $originalPrice - $discountValue);
  143. } elseif ($this->discount_type === self::DISCOUNT_TYPE_PERCENTAGE) {
  144. return (int)($originalPrice * (100 - $discountValue) / 100);
  145. }
  146. return $originalPrice;
  147. }
  148. }