Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 59
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
CouponController
0.00% covered (danger)
0.00%
0 / 59
0.00% covered (danger)
0.00%
0 / 5
90
0.00% covered (danger)
0.00%
0 / 1
 index
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
2
 store
0.00% covered (danger)
0.00%
0 / 21
0.00% covered (danger)
0.00%
0 / 1
6
 update
0.00% covered (danger)
0.00%
0 / 20
0.00% covered (danger)
0.00%
0 / 1
6
 destroy
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 ensureCouponBelongsToCurrentStore
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3namespace App\Http\Controllers\Admin;
4
5use App\Enums\CouponStatus;
6use App\Http\Controllers\Concerns\ResolvesContext;
7use App\Http\Controllers\Controller;
8use App\Models\Influencer;
9use App\Models\InfluencerCoupon;
10use App\Models\StoreIntegration;
11use App\Services\Nuvemshop\NuvemshopCouponService;
12use Illuminate\Http\RedirectResponse;
13use Illuminate\Http\Request;
14use Illuminate\Validation\Rule;
15use Illuminate\View\View;
16use RuntimeException;
17
18class CouponController extends Controller
19{
20    use ResolvesContext;
21
22    public function index(): View
23    {
24        $store = $this->currentStore();
25
26        return view('admin.coupons.index', [
27            'coupons' => InfluencerCoupon::with(['influencer', 'orders'])
28                ->where('store_id', $store->id)
29                ->latest()
30                ->paginate(20),
31            'influencers' => Influencer::where('store_id', $store->id)
32                ->where('status', 'active')
33                ->orderBy('name')
34                ->get(),
35        ]);
36    }
37
38    public function store(Request $request, NuvemshopCouponService $service): RedirectResponse
39    {
40        $data = $request->validate([
41            'influencer_id' => ['required', 'exists:influencers,id'],
42            'coupon_code_original' => ['required', 'alpha_num', 'max:80'],
43            'discount_percentage' => ['required', 'numeric', 'min:0.01', 'max:100'],
44        ]);
45
46        $influencer = Influencer::findOrFail($data['influencer_id']);
47
48        $integration = StoreIntegration::query()
49            ->where('store_id', $influencer->store_id)
50            ->whereHas('provider', fn ($q) => $q->where('slug', 'nuvemshop'))
51            ->firstOrFail();
52
53        try {
54            $service->createForInfluencer(
55                $influencer,
56                $integration,
57                $data['coupon_code_original'],
58                (float) $data['discount_percentage']
59            );
60        } catch (RuntimeException $exception) {
61            return back()
62                ->withInput()
63                ->withErrors(['coupon' => $exception->getMessage()]);
64        }
65
66        return back()->with('success', 'Cupom criado/vinculado com sucesso.');
67    }
68
69    public function update(Request $request, InfluencerCoupon $coupon, NuvemshopCouponService $service): RedirectResponse
70    {
71        $this->ensureCouponBelongsToCurrentStore($coupon);
72
73        $data = $request->validate([
74            'coupon_code_original' => ['required', 'alpha_num', 'max:80'],
75            'discount_percentage' => ['required', 'numeric', 'min:0.01', 'max:100'],
76            'status' => ['required', Rule::in([
77                CouponStatus::Active->value,
78                CouponStatus::Inactive->value,
79            ])],
80        ]);
81
82        try {
83            $service->updateCoupon(
84                $coupon,
85                $data['coupon_code_original'],
86                (float) $data['discount_percentage'],
87                CouponStatus::from($data['status'])
88            );
89        } catch (RuntimeException $exception) {
90            return back()
91                ->withInput()
92                ->withErrors(['coupon' => $exception->getMessage()]);
93        }
94
95        return back()->with('success', 'Cupom atualizado na Nuvemshop e no Orvox.');
96    }
97
98    public function destroy(InfluencerCoupon $coupon, NuvemshopCouponService $service): RedirectResponse
99    {
100        $this->ensureCouponBelongsToCurrentStore($coupon);
101
102        try {
103            $service->deleteCoupon($coupon);
104        } catch (RuntimeException $exception) {
105            return back()->withErrors(['coupon' => $exception->getMessage()]);
106        }
107
108        return back()->with('success', 'Cupom excluído na Nuvemshop e marcado como excluído no Orvox.');
109    }
110
111    private function ensureCouponBelongsToCurrentStore(InfluencerCoupon $coupon): void
112    {
113        if ((int) $coupon->store_id !== (int) $this->currentStore()->id) {
114            abort(404);
115        }
116    }
117}