From 75cc5c95e79b442b133709f33c45b69f978c1ccd Mon Sep 17 00:00:00 2001 From: ukyo Date: Thu, 7 Aug 2025 14:06:02 +0800 Subject: [PATCH] feat. cafeg promocode --- .../Controllers/Admin/SettingController.php | 16 +- .../Controllers/front/MemberController.php | 72 ++-- .../Controllers/front/PromoCodeController.php | 22 +- app/Imports/PromoImport.php | 107 +++++- app/Models/Promocode.php | 21 +- ...5_08_06_102845_create_promocodes_table.php | 25 ++ resources/views/admin/member/index.blade.php | 95 +++--- .../views/admin/setting/promocode.blade.php | 66 +++- resources/views/front/member/index.blade.php | 320 +++++++++++------- routes/web.php | 4 - 10 files changed, 489 insertions(+), 259 deletions(-) create mode 100644 database/migrations/2025_08_06_102845_create_promocodes_table.php diff --git a/app/Http/Controllers/Admin/SettingController.php b/app/Http/Controllers/Admin/SettingController.php index 44fa91f..ce1f7a6 100644 --- a/app/Http/Controllers/Admin/SettingController.php +++ b/app/Http/Controllers/Admin/SettingController.php @@ -5,18 +5,18 @@ use App\Http\Controllers\Controller; use App\Imports\PromoImport; use App\Models\Promocode; +use App\Models\User; use Carbon\Carbon; use Illuminate\Http\Request; use Log; use Maatwebsite\Excel\Facades\Excel; -use App\Models\User; + class SettingController extends Controller { - public function promoCode(Request $request) { $start = Carbon::now()->month(1)->startOfMonth(); - $end = Carbon::now()->endOfMonth(); + $end = Carbon::now()->endOfMonth(); $result = Promocode::whereBetween('created_at', [$start, $end])->paginate(100); @@ -33,6 +33,7 @@ public function promoCodeCreate(Request $request) $request->validate([ 'file' => 'required|mimes:xlsx,xls,csv|max:2048', ]); + $from = $request->input('from'); // 默認來源為 cafeg if ($request->hasFile('file')) { $file = $request->file('file'); @@ -55,7 +56,7 @@ public function promoCodeCreate(Request $request) // 讀取並導入 Excel 文件 try { - Excel::import(new PromoImport, $file); + Excel::import(new PromoImport($from), $file); return back()->with('success', '促銷代碼已成功導入!'); } catch (\Exception $e) { return back()->with('error', '導入失敗: ' . $e->getMessage()); @@ -71,17 +72,16 @@ public function adminIndex(Request $request) public function loginStatus(Request $request) { - $user = User::where('id', $request->id)->first(); + $user = User::where('id', $request->id)->first(); $user->can_login = $request->can_login; $user->save(); return response()->json([ - 'status' => 'success', - 'msg' => '狀態已更新', + 'status' => 'success', + 'msg' => '狀態已更新', 'can_login' => $user->can_login, ]); - } } diff --git a/app/Http/Controllers/front/MemberController.php b/app/Http/Controllers/front/MemberController.php index ed76633..7673b17 100644 --- a/app/Http/Controllers/front/MemberController.php +++ b/app/Http/Controllers/front/MemberController.php @@ -1,13 +1,13 @@ user(); - if (isset(Auth::guard('member')->user()->id)) { - $user_id = Auth::guard('member')->user()->id; - $code = Promocode::where('used_count', $user_id)->latest()->first(); - - if (!$code) { - $code = Promocode::where('used_count', 0)->first(); - $code->give_to = '首次'; - $code->used_count = $user_id; - $code->save(); - } - - - - return view('front.member.index', ['code' => $code ]); - } else { + if (! $user) { Auth::guard('member')->logout(); return redirect()->route('login'); } + + $user_id = $user->id; + $today = Carbon::today()->format('Y-m-d'); + + // 建立一個回傳符合條件的 Promocode 的 function + $getAvailableCode = function ($from) use ($today) { + return Promocode::where('used_count', 0) + ->where('from', $from) + ->whereDate('valid_from', '<=', $today) + ->whereDate('valid_to', '>=', $today) + ->latest() + ->first(); + }; + + // 試著找一個未使用的 + $code = $getAvailableCode('cafeg'); + $teacode = $getAvailableCode('teamaster'); + + // 如果找不到,就再次找一個未使用的然後標記成首次給予 + if (! $code) { + $code = $getAvailableCode('cafeg'); + if ($code) { + $code->give_to = '首次'; + $code->used_count = $user_id; + $code->save(); + } + } + + if (! $teacode) { + $teacode = $getAvailableCode('teacode'); + if ($teacode) { + $teacode->give_to = '首次'; + $teacode->used_count = $user_id; + $teacode->save(); + } + } + + return view('front.member.index', [ + 'code' => $code, + 'teacode' => $teacode, + ]); } + /** * Summary of profile 登入後個人資訊沒有menu * @return \Illuminate\Contracts\View\View @@ -59,9 +87,9 @@ public function profileUpdate(Request $request) { // 驗證輸入的數據 $validatedData = $request->validate([ - 'email' => 'required|email', + 'email' => 'required|email', 'password' => 'nullable|min:6', // password 與 password_confirmation 必須匹配 - 'phone' => 'nullable|string|max:15', + 'phone' => 'nullable|string|max:15', ]); $auth = Member::find(Auth::guard('member')->id()); @@ -126,7 +154,7 @@ public function checkEmail(Request $request) public function changeLevel(Request $request) { - $user = Member::find($request->id); + $user = Member::find($request->id); $user->level = $request->level; $user->save(); return response()->json(['status' => 'success', '成功', 'level' => $request->level, 'name' => $user->level_name]); diff --git a/app/Http/Controllers/front/PromoCodeController.php b/app/Http/Controllers/front/PromoCodeController.php index 24685ad..3069111 100644 --- a/app/Http/Controllers/front/PromoCodeController.php +++ b/app/Http/Controllers/front/PromoCodeController.php @@ -1,11 +1,12 @@ user()->id; - $count = Promocode::where('used_count', $user_id)->count(); + $count = Promocode::where('used_count', $user_id)->count(); $give_to = $request->input('give_to'); - - $row = Promocode::where('used_count', 0)->first(); + $from = $request->input('from'); + $row = Promocode::where('used_count', 0) + ->where('from', $from) + ->where( + 'valid_from', + '<=', + now() + )->where('valid_to', '>=', now()) + ->first(); $row->used_count = $user_id; - $row->give_to = $give_to; + $row->give_to = $give_to; $row->save(); return response()->json(['status' => 'success', 'msg' => '已成功取得', 'promocode' => $row->code, 'give_to' => $row->give_to]); - } /** * Summary of morePromocode @@ -46,7 +53,7 @@ public function morePromocode() if ($user->level != 9) { throw new Exception("Error Processing Request", 401); } else { - $row = Promocode::where('used_count', 0)->first(); + $row = Promocode::where('used_count', 0)->first(); $row->used_count = $user->id; $row->save(); return response()->json(['status' => 'success', 'msg' => '已成功取得', 'promocode' => $row->code]); @@ -57,7 +64,6 @@ public function morePromocode() } } - /** * Store a newly created resource in storage. */ diff --git a/app/Imports/PromoImport.php b/app/Imports/PromoImport.php index 38e3230..22178af 100644 --- a/app/Imports/PromoImport.php +++ b/app/Imports/PromoImport.php @@ -1,4 +1,5 @@ from = $from; + } public function collection(Collection $rows) { - // 打印每一行數據(這是從 Excel 讀取的行) + if ($this->from == 'cafeg') { - foreach ($rows as $row) { + foreach ($rows as $row) { + $data = $row->toArray(); - Log::info('Row data: ', ['value' => $row->toArray()[3]]); + if ($data[3] != '提货码') { // 跳過標題行 + $code = $data[3]; - if ($row->toArray()[3] != '提货码') // 跳過第一行 - { - Promocode::create([ - 'code' => $row->toArray()[3], // 使用 "提货码" 列 - 'discount' => 100, // 假設折扣為固定值 100 - 'type' => 'percent', // 默認為百分比 - 'usage_limit' => 1, // 默認每個代碼只能使用一次 - 'valid_from' => date('Y-m-d'), // 當前日期 - 'valid_to' => date('Y-m-d', strtotime('1 day')), // 默認有效期至第二天 - 'is_active' => 1, // 默認啟用 - ]); + $promo = Promocode::where('code', $code) + ->where('from', 'cafeg') + ->first(); + + if ($promo) { + // 如果已存在,且 give_to 不為 null,就更新 + if ($promo->give_to !== null) { + $promo->update([ + 'discount' => 100, + 'type' => 'percent', + 'usage_limit' => 1, + 'valid_from' => date('Y-m-d'), + 'valid_to' => date('Y-m-d', strtotime('+1 day')), + 'is_active' => 1, + 'from' => 'cafeg', + ]); + Log::info("已更新:{$code}"); + } else { + Log::info("跳過(give_to 為 null):{$code}"); + } + } else { + // 不存在就新增 + Promocode::create([ + 'code' => $code, + 'discount' => 100, + 'type' => 'percent', + 'usage_limit' => 1, + 'valid_from' => date('Y-m-d'), + 'valid_to' => date('Y-m-d', strtotime('+1 day')), + 'is_active' => 1, + 'from' => 'cafeg', + ]); + Log::info("已新增:{$code}"); + } + } + } + } + + if ($this->from == 'teamaster') { + Log::info('import-from: teamaster'); + Log::info('row', ); + foreach ($rows->toArray() as $row) { + + $code = $row[0]; + $promo = Promocode::where('code', $code) + ->where('from', 'teamaster') + ->first(); + + if ($promo) { + // 如果已存在,且 give_to 不為 null,就更新 + if ($promo->give_to != null) { + $promo->update([ + 'discount' => 70, + 'type' => 'amount', + 'usage_limit' => 1, + 'valid_from' => date('Y-m-d'), + 'valid_to' => date('Y-m-d', strtotime('+7 day')), + 'is_active' => 1, + 'from' => 'teamaster', + ]); + Log::info("已更新:{$code}"); + } else { + Log::info("跳過(give_to 為 null):{$code}"); + } + } else { + Log::info("新增代碼:{$code}"); + // 不存在就新增 + Promocode::create([ + 'code' => $code, + 'discount' => 70, + 'type' => 'amount', + 'usage_limit' => 1, + 'valid_from' => date('Y-m-d'), + 'valid_to' => date('Y-m-d', strtotime('+7 day')), + 'is_active' => 1, + 'from' => 'teamaster', + ]); + Log::info("已新增:{$code}"); + } } } } + } diff --git a/app/Models/Promocode.php b/app/Models/Promocode.php index 2311e6b..20727e0 100644 --- a/app/Models/Promocode.php +++ b/app/Models/Promocode.php @@ -7,20 +7,19 @@ class Promocode extends Model { // - protected $table = 'promocodes'; - protected $fillable = [ - 'code', - 'discount', - 'type', - 'usage_limit', - 'used_count', - 'valid_from', - 'valid_to', - 'is_active', - ]; + protected $table = 'promocodes'; + protected $guarded = []; public function getMember() { return $this->hasOne(Member::class, 'id', 'used_count'); } + public function getFromLabelAttribute() + { + return match ($this->from) { + 'cafeg' => '朗立臣', + 'teamaster' => '飲力星球', + default => '未知來源', + }; + } } diff --git a/database/migrations/2025_08_06_102845_create_promocodes_table.php b/database/migrations/2025_08_06_102845_create_promocodes_table.php new file mode 100644 index 0000000..71bcba6 --- /dev/null +++ b/database/migrations/2025_08_06_102845_create_promocodes_table.php @@ -0,0 +1,25 @@ +enum('from', ['cafeg', 'teamaster', 'unknown'])->comment('來源')->after('id'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('promocodes'); + } +}; diff --git a/resources/views/admin/member/index.blade.php b/resources/views/admin/member/index.blade.php index 8edd33d..78f11f5 100644 --- a/resources/views/admin/member/index.blade.php +++ b/resources/views/admin/member/index.blade.php @@ -361,65 +361,48 @@ class="d-grid d-sm-flex p-4 border justify-content-center table-responsive text- }); function changeLevel(id, lv) { - - Swal.fire({ - title: "確定", - text: "你即將修改此用戶權限!", - icon: "warning", - showCancelButton: true, - confirmButtonText: "確定", - cancelButtonText: "取消" - }).then((result) => { - if (result.isConfirmed) { - $.ajax({ - type: "patch", - url: "{{ route('member.changelevel') }}", - data: { - id: id, - level: lv - }, - headers: { - 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') - }, - - success: function(response) { - if (response.status == 'success') { - console.log(lv); - // lv = response.level; - name = response.name; - var view = ''; - if (lv == 0) { - view = '' + - name; - } - if (lv == 1) { - view = '' + - name; - } - if (lv == 2) { - view = ' ' + - name; - } - if (lv == 9) { - view = - ' ' + - name; - } - $("#user-" + id).html(view); + Swal.fire({ + title: "確定", + text: "你即將修改此用戶權限!", + icon: "warning", + showCancelButton: true, + confirmButtonText: "確定", + cancelButtonText: "取消" + }).then((result) => { + if (result.isConfirmed) { + $.ajax({ + type: "patch", + url: "{{ route('member.changelevel') }}", + data: { + id: id, + level: lv + }, + headers: { + 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') + }, + success: function(response) { + if (response.status == 'success') { + let name = response.name; + let view = ''; + if (lv == 0) { + view = '' + name; + } else if (lv == 1) { + view = '' + name; + } else if (lv == 2) { + view = '' + name; + } else if (lv == 9) { + view = '' + name; } - - + $("#user-" + id).html(view); Swal.fire("成功", "修改成功", "success"); - } - }); - - } else if (result.dismiss === Swal.DismissReason.cancel) { - Swal.fire("取消", "使用者取消操作", "error"); - console.log("使用者取消操作"); - } - }); - } + } + }); + } else if (result.dismiss === Swal.DismissReason.cancel) { + Swal.fire("取消", "使用者取消操作", "error"); + } + }); + } @endsection diff --git a/resources/views/admin/setting/promocode.blade.php b/resources/views/admin/setting/promocode.blade.php index d006489..0609c76 100644 --- a/resources/views/admin/setting/promocode.blade.php +++ b/resources/views/admin/setting/promocode.blade.php @@ -49,28 +49,57 @@
-
-
+
+
+
Excel 匯入
+
-
-
- @csrf + + -
輸入檔案
-
-
- - -
+ +
- -
- - - -
+ +
+
+ @csrf +
+ + + +
+ +
+ + +
+
+ @csrf +
+ + + +
+ +
+
+
+
+
+
+
@@ -78,7 +107,7 @@ - + @@ -89,6 +118,7 @@ @foreach($data as $item) + diff --git a/resources/views/front/member/index.blade.php b/resources/views/front/member/index.blade.php index 0ea9230..10ae3a1 100644 --- a/resources/views/front/member/index.blade.php +++ b/resources/views/front/member/index.blade.php @@ -102,15 +102,17 @@ class="fw-medium">{{ Auth::guard('member')->user()->Level_Name }}
來源 優惠碼 優惠類型 折扣比例
{{$item->getFromLabelAttribute()}} {{$item->code}} {{$item->type}} {{ number_format($item->discount, 0) }}
- - +
+ +
+
+
消費紀錄
+
+
+ +
+
+
+ + - - - - - + + + + + - - - - - - + + + + + + - + - + -
訂單號日期品項金額狀態訂單號日期品項金額狀態
目前暫無資料
目前暫無資料
+ +
+ - + + + + + + - - - - - + - + - - - - - - - {{-- 一開始 Loading 使用script 判斷 --}} + + + + {{-- 一開始 Loading 使用script 判斷 --}} - -@endsection + + + + @endsection diff --git a/routes/web.php b/routes/web.php index a71f5f9..a49ddb2 100644 --- a/routes/web.php +++ b/routes/web.php @@ -6,7 +6,6 @@ use App\Http\Controllers\front\RegisterController; use App\Http\Controllers\LoginController; use App\Http\Middleware\GuestRedirect; -use App\Http\Middleware\memberAuth; use App\Http\Middleware\MemberRedirect; use Illuminate\Support\Facades\Route; @@ -48,9 +47,6 @@ Route::get('google/callback', [LoginController::class, 'handleGoogleCallback'])->name('google.redirect'); Route::patch('changelevel', [MemberController::class, 'changeLevel'])->name('member.changelevel'); - - - //前台route 登入後; Route::prefix('member') ->middleware(['auth:member']) // 使用自定义守卫的中间件