| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- <?php
- namespace Longyi\Gift\Models;
- use Illuminate\Support\Str;
- use Longyi\Gift\Models\GiftCardUsageLog;
- use Illuminate\Database\Eloquent\Factories\HasFactory;
- use Illuminate\Database\Eloquent\Model;
- use Longyi\Gift\Contracts\GiftCards as GiftCardsContract;
- use Longyi\RewardPoints\Config\TransactionType;
- use Longyi\RewardPoints\Repositories\RewardPointRepository;
- use function Symfony\Component\Translation\t;
- use Illuminate\Support\Facades\DB;
- use Carbon\Carbon;
- class GiftCards extends Model implements GiftCardsContract
- {
- use HasFactory;
- protected $table = 'gift_cards';
- protected $fillable = [
- 'giftcard_number',
- 'giftcard_amount',
- 'used_giftcard_amount',
- 'remaining_giftcard_amount',
- 'customer_id',
- 'channel',
- 'expirationdate',
- 'giftcard_status',
- ];
- protected $casts = [
- 'giftcard_amount' => 'decimal:2',
- 'used_giftcard_amount' => 'decimal:2',
- 'remaining_giftcard_amount' => 'decimal:2',
- 'customer_id' => 'integer',
- 'expirationdate' => 'datetime',
- 'channel' => 'string',
- ];
- protected static function boot()
- {
- parent::boot();
- static::created(function ($giftCard) {
- GiftCardUsageLog::create([
- 'giftcard_number' => $giftCard->giftcard_number,
- 'customer_id' => $giftCard->customer_id,
- 'balance_before' => $giftCard->giftcard_amount,
- 'balance_after' => $giftCard->giftcard_amount,
- 'action_type' => GiftCardUsageLog::ACTION_ADD,
- 'status' => 'completed',
- 'notes' => $giftCard->channel ?: '',
- ]);
- });
- }
- public static function setGiftCardCode($giftcard)
- {
- if (!$giftcard) {
- return false;
- }
- $cart = cart()->getCart();
- $cart->giftcard_number = $giftcard->giftcard_number;
- $cart->save();
- return true;
- }
- public static function removeGiftCardCode()
- {
- $cart = cart()->getCart();
- $giftcardAmount = $cart->giftcard_amount ?? 0;
- // 清除购物车中的礼品卡标记
- $cart->giftcard_number = null;
- $cart->giftcard_amount = null;
- // 恢复购物车总额
- $cart->grand_total += $giftcardAmount;
- $cart->base_grand_total += $giftcardAmount;
- $cart->save();
- return true;
- }
- /**
- * Add a new gift card for a customer.
- *
- * @param int $customerId The ID of the customer to receive the gift card.
- * @param float $giftcardAmount The initial amount/balance of the gift card.
- * @param int $num Maximum number of gift cards allowed for this channel (0 means unlimited).
- * @param int $expirationdate Number of days until the gift card expires (default: 30 days).
- * @param string $channel The source channel or campaign identifier (default: 'activity_26_04_21').
- * @param string $notes Additional notes or description for the gift card creation.
- * @return void
- * @throws \Exception If customerId is empty, giftcardAmount is empty, or gift card limit exceeded.
- */
- public static function addGiftCard($customerId, $giftcardAmount, $num = 0, $expirationdate = 30, $channel = 'activity_26_04_21', $notes = '拉新活动添加')
- {
- if (empty($customerId)) {
- throw new \Exception('customerId is empty');
- }
- if (empty($giftcardAmount)) {
- throw new \Exception('giftcardAmount is empty');
- }
- $data = GiftCards::where('customer_id', $customerId)
- ->where('channel', $channel)
- ->count();
- if ($num != 0) {
- $giftNum =count($data);
- if($giftNum <= $num){
- throw new \Exception('gift num is not enough');
- }
- }
- $expirationDate = self::calculateExpirationDate($expirationdate);
- static::create([
- 'giftcard_number' => self::generateGiftCardNumber(),
- 'giftcard_amount' => $giftcardAmount,
- 'used_giftcard_amount' => 0,
- 'remaining_giftcard_amount' => $giftcardAmount,
- 'customer_id' => $customerId,
- 'expirationdate' => $expirationDate,
- 'giftcard_status' => 1,
- 'channel' => $channel,
- 'notes' => $notes
- ]);
- }
- /**
- * Calculate expiration date from various input types.
- *
- * @param mixed $expirationdate Days (int), date string, or Carbon instance
- * @return \Carbon\Carbon Calculated expiration date
- * @throws \Exception If the input type is invalid
- */
- protected static function calculateExpirationDate($expirationdate): Carbon
- {
- if ($expirationdate instanceof Carbon) {
- return $expirationdate;
- }
- if (is_string($expirationdate)) {
- try {
- return Carbon::parse($expirationdate);
- } catch (\Exception $e) {
- throw new \Exception("Invalid date format: {$expirationdate}. Use Y-m-d format.");
- }
- }
- if (is_int($expirationdate) || is_float($expirationdate)) {
- if ($expirationdate <= 0) {
- throw new \Exception('Expiration days must be greater than 0');
- }
- return now()->addDays((int) $expirationdate);
- }
- throw new \Exception('Invalid expiration date type. Must be integer (days), string (Y-m-d), or Carbon instance.');
- }
- public static function generateGiftCardNumber()
- {
- do {
- // Generate a random string of characters
- $randomString = Str::upper(Str::random(16));
- // Format the string into groups of four separated by dashes
- $code = implode('-', str_split($randomString, 4));
- // Check if the code already exists in the database
- $exists = GiftCards::where('giftcard_number', $code)->exists();
- } while ($exists);
- return $code;
- }
- public function giftcards()
- {
- return [
- 1 => [
- 'id' => 1,
- 'name' => 'Gift Card 1',
- 'amount' => 20.00,
- 'points' => 20,
- 'num' => 0,
- 'expirationdate' => 30,
- 'channel' => 'activity_26_04_21',
- 'notes' => ''
- ],
- 2 => [
- 'id' => 2,
- 'name' => 'Gift Card 2',
- 'amount' => 30.00,
- 'points' => 30,
- 'num' => 0,
- 'expirationdate' => 30,
- 'channel' => 'activity_26_04_21',
- 'notes' => ''
- ],
- 3 => [
- 'id' => 3,
- 'name' => 'Gift Card 3',
- 'amount' => 40.00,
- 'points' => 40,
- 'num' => 0,
- 'expirationdate' => 30,
- 'channel' => 'activity_26_04_21',
- 'notes' => ''
- ],
- 4 => [
- 'id' => 4,
- 'name' => 'Gift Card 4',
- 'amount' => 50.00,
- 'points' => 50,
- 'num' => 0,
- 'expirationdate' => 30,
- 'channel' => 'activity_26_04_21',
- 'notes' => ''
- ],
- ];
- }
- /**
- * Add a gift card for a customer using points
- *
- * @param int $id Gift card ID from giftcards() array
- * @param int $customerId Customer ID
- * @return array|true
- */
- public function add($id, $customerId)
- {
- if (empty($customerId)) {
- throw new \Exception('customer id is empty');
- }
- if (empty($id)) {
- throw new \Exception('gift card id is empty');
- }
- $gifts = $this->giftcards();
- $giftInfo = $gifts[$id] ?? null;
- if (!$giftInfo) {
- throw new \Exception("gift card not found (ID: {$id})");
- }
- $points = $giftInfo['points'] ?? 0;
- if ($points <= 0) {
- throw new \Exception("gift card points configuration error (points: {$points})");
- }
- try {
- DB::beginTransaction();
- self::addGiftCard(
- $customerId,
- $giftInfo['amount'],
- $giftInfo['num'],
- $giftInfo['expirationdate'],
- $giftInfo['channel'],
- $giftInfo['notes']
- );
- $rewardPointRepository = app(RewardPointRepository::class);
- $rewardPointRepository->deductPoints(
- $customerId,
- $points,
- TransactionType::GIFT_CARD_REDEEM,
- 'Gift Card Redeem'
- );
- DB::commit();
- return true;
- } catch (\Exception $e) {
- DB::rollBack();
- throw $e;
- }
- }
- }
|