Passed
Pull Request — master (#21)
by Maximo
04:23
created

AppsPlansController   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 227
Duplicated Lines 0 %

Test Coverage

Coverage 62.86%

Importance

Changes 0
Metric Value
eloc 105
dl 0
loc 227
ccs 66
cts 105
cp 0.6286
rs 10
c 0
b 0
f 0
wmc 23

4 Methods

Rating   Name   Duplication   Size   Complexity  
C create() 0 91 11
A onConstruct() 0 6 1
A delete() 0 28 4
B edit() 0 57 7
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Gewaer\Api\Controllers;
6
7
use Gewaer\Models\AppsPlans;
8
use Gewaer\Exception\UnauthorizedHttpException;
9
use Gewaer\Exception\NotFoundHttpException;
10
use Stripe\Token as StripeToken;
11
use Phalcon\Http\Response;
12
use Phalcon\Validation;
13
use Phalcon\Validation\Validator\PresenceOf;
14
use Gewaer\Exception\UnprocessableEntityHttpException;
15
use Phalcon\Cashier\Subscription;
16
use Gewaer\Models\UserCompanyApps;
17
use function Gewaer\Core\paymentGatewayIsActive;
18
19
/**
20
 * Class LanguagesController
21
 *
22
 * @package Gewaer\Api\Controllers
23
 *
24
 * @property Users $userData
25
 * @property Request $request
26
 * @property Config $config
27
 * @property Apps $app
28
 * @property \Phalcon\Db\Adapter\Pdo\Mysql $db
29
 */
30
class AppsPlansController extends BaseController
31
{
32
    /*
33
     * fields we accept to create
34
     *
35
     * @var array
36
     */
37
    protected $createFields = [];
38
39
    /*
40
     * fields we accept to create
41
     *
42
     * @var array
43
     */
44
    protected $updateFields = [];
45
46
    /**
47
     * set objects
48
     *
49
     * @return void
50
     */
51 4
    public function onConstruct()
52
    {
53 4
        $this->model = new AppsPlans();
54 4
        $this->additionalSearchFields = [
55 4
            ['is_deleted', ':', 0],
56 4
            ['apps_id', ':', $this->app->getId()],
57
        ];
58 4
    }
59
60
    /**
61
     * Given the app plan stripe id , subscribe the current company to this aps
62
     *
63
     * @return Response
64
     */
65 1
    public function create(): Response
66
    {
67 1
        if (!$this->userData->hasRole('Default.Admins')) {
68
            throw new UnauthorizedHttpException(_('You dont have permission to subscribe this apps'));
69
        }
70
71
        //Ok let validate user password
72 1
        $validation = new Validation();
73 1
        $validation->add('stripe_id', new PresenceOf(['message' => _('The plan is required.')]));
74 1
        $validation->add('number', new PresenceOf(['message' => _('Credit Card Number is required.')]));
75 1
        $validation->add('exp_month', new PresenceOf(['message' => _('Credit Card Number is required.')]));
76 1
        $validation->add('exp_year', new PresenceOf(['message' => _('Credit Card Number is required.')]));
77 1
        $validation->add('cvc', new PresenceOf(['message' => _('CVC is required.')]));
78
79
        //validate this form for password
80 1
        $messages = $validation->validate($this->request->getPost());
81 1
        if (count($messages)) {
82
            foreach ($messages as $message) {
83
                throw new UnprocessableEntityHttpException($message);
84
            }
85
        }
86
87 1
        $stripeId = $this->request->getPost('stripe_id');
88 1
        $company = $this->userData->defaultCompany;
89 1
        $cardNumber = $this->request->getPost('number');
90 1
        $expMonth = $this->request->getPost('exp_month');
91 1
        $expYear = $this->request->getPost('exp_year');
92 1
        $cvc = $this->request->getPost('cvc');
93
94 1
        $appPlan = $this->model->findFirstByStripeId($stripeId);
95
96 1
        if (!is_object($appPlan)) {
97
            throw new NotFoundHttpException(_('This plan doesnt exist'));
98
        }
99
100 1
        $userSubscription = Subscription::findFirst([
101 1
            'conditions' => 'user_id = ?0 and company_id = ?1 and apps_id = ?2 and is_deleted  = 0',
102 1
            'bind' => [$this->userData->getId(), $this->userData->default_company, $this->app->getId()]
103
        ]);
104
105 1
        if (is_object($userSubscription)) {
106
            throw new NotFoundHttpException(_('You are already subscribed to this plan'));
107
        }
108
109
        //we can only run stripe paymenta gateway if we have the key
110 1
        if (paymentGatewayIsActive()) {
111
            $card = StripeToken::create([
112
                'card' => [
113
                    'number' => $cardNumber,
114
                    'exp_month' => $expMonth,
115
                    'exp_year' => $expYear,
116
                    'cvc' => $cvc,
117
                ],
118
            ], [
119
                'api_key' => $this->config->stripe->secret
120
            ])->id;
121
122
            $this->db->begin();
123
124
            if ($appPlan->free_trial_dates == 0) {
125
                $this->userData->newSubscription($appPlan->name, $appPlan->stripe_id, $company, $this->app)->create($card);
126
            } else {
127
                $this->userData->newSubscription($appPlan->name, $appPlan->stripe_id, $company, $this->app)->trialDays($appPlan->free_trial_dates)->create($card);
128
            }
129
130
            //update company app
131
            $companyApp = UserCompanyApps::getCurrentApp();
132
133
            //update the company app to the new plan
134
            if (is_object($companyApp)) {
135
                $subscription = $this->userData->subscription($appPlan->stripe_plan);
136
                $companyApp->stripe_id = $stripeId;
137
                $companyApp->subscriptions_id = $subscription->getId();
138
                if (!$companyApp->update()) {
139
                    $this->db->rollback();
140
                    throw new UnprocessableEntityHttpException((string)current($companyApp->getMessages()));
141
                }
142
143
                //update the subscription with the plan
144
                $subscription->apps_plans_id = $appPlan->getId();
145
                if (!$subscription->update()) {
146
                    $this->db->rollback();
147
                    throw new UnprocessableEntityHttpException((string)current($subscription->getMessages()));
148
                }
149
            }
150
151
            $this->db->commit();
152
        }
153
154
        //sucess
155 1
        return $this->response($appPlan);
156
    }
157
158
    /**
159
     * Update a given subscription
160
     *
161
     * @param string $stripeId
162
     * @return Response
163
     */
164 2
    public function edit($stripeId) : Response
165
    {
166 2
        $appPlan = $this->model->findFirstByStripeId($stripeId);
167
168 2
        if (!is_object($appPlan)) {
169
            throw new NotFoundHttpException(_('This plan doesnt exist'));
170
        }
171
172 2
        $userSubscription = Subscription::findFirst([
173 2
            'conditions' => 'user_id = ?0 and company_id = ?1 and apps_id = ?2 and is_deleted  = 0',
174 2
            'bind' => [$this->userData->getId(), $this->userData->default_company, $this->app->getId()]
175
        ]);
176
177 2
        if (!is_object($userSubscription)) {
178
            throw new NotFoundHttpException(_('No current subscription found'));
179
        }
180
181 2
        $this->db->begin();
182
183 2
        $subscription = $this->userData->subscription($userSubscription->name);
184
185 2
        if ($subscription->onTrial()) {
186 2
            $subscription->name = $appPlan->name;
187 2
            $subscription->stripe_id = $appPlan->stripe_id;
188 2
            $subscription->stripe_plan = $appPlan->stripe_plan;
189
        } else {
190
            $subscription->swap($stripeId);
191
        }
192
193
        //update company app
194 2
        $companyApp = UserCompanyApps::getCurrentApp();
195
196
        //update the company app to the new plan
197 2
        if (is_object($companyApp)) {
198 2
            $subscription->name = $stripeId;
199 2
            $subscription->save();
200
201 2
            $companyApp->stripe_id = $stripeId;
202 2
            $companyApp->subscriptions_id = $subscription->getId();
203 2
            if (!$companyApp->update()) {
204
                $this->db->rollback();
205
                throw new UnprocessableEntityHttpException((string) current($companyApp->getMessages()));
206
            }
207
208
            //update the subscription with the plan
209 2
            $subscription->apps_plans_id = $appPlan->getId();
210 2
            if (!$subscription->update()) {
211
                $this->db->rollback();
212
213
                throw new UnprocessableEntityHttpException((string) current($subscription->getMessages()));
214
            }
215
        }
216
217 2
        $this->db->commit();
218
219
        //return the new subscription plan
220 2
        return $this->response($appPlan);
221
    }
222
223
    /**
224
     * Cancel a given subscription
225
     *
226
     * @param string $stripeId
227
     * @return Response
228
     */
229 1
    public function delete($stripeId): Response
230
    {
231 1
        $appPlan = $this->model->findFirstByStripeId($stripeId);
232
233 1
        if (!is_object($appPlan)) {
234
            throw new NotFoundHttpException(_('This plan doesnt exist'));
235
        }
236
237 1
        $userSubscription = Subscription::findFirst([
238 1
            'conditions' => 'user_id = ?0 and company_id = ?1 and apps_id = ?2 and is_deleted  = 0',
239 1
            'bind' => [$this->userData->getId(), $this->userData->default_company, $this->app->getId()]
240
        ]);
241
242 1
        if (!is_object($userSubscription)) {
243
            throw new NotFoundHttpException(_('No current subscription found'));
244
        }
245
246 1
        $subscription = $this->userData->subscription($userSubscription->name);
247
248
        //if on trial you can cancel without going to stripe
249 1
        if (!$subscription->onTrial()) {
250
            $subscription->cancel();
251
        }
252
253 1
        $subscription->is_deleted = 1;
254 1
        $subscription->update();
255
256 1
        return $this->response($appPlan);
257
    }
258
}
259