Passed
Push — develop ( 9324e6...f3eb57 )
by Septianata
04:31
created

ExchangeConversation::recordItem()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 50
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
eloc 30
c 0
b 0
f 0
dl 0
loc 50
ccs 0
cts 32
cp 0
rs 9.44
cc 3
nc 1
nop 4
crap 12
1
<?php
2
3
namespace App\Conversations;
4
5
use App\Models\Customer;
6
use App\Models\Denomination;
7
use App\Models\Item;
8
use App\Models\Order;
9
use BotMan\BotMan\Messages\Incoming\Answer;
10
use BotMan\BotMan\Messages\Outgoing\Actions\Button;
11
use BotMan\BotMan\Messages\Outgoing\Question;
12
use BotMan\Drivers\Telegram\Extensions\Keyboard;
13
use BotMan\Drivers\Telegram\Extensions\KeyboardButton;
14
use Illuminate\Support\Collection;
15
use Illuminate\Support\Str;
16
17
class ExchangeConversation extends Conversation
18
{
19
    /**
20
     * Start the conversation.
21
     *
22
     * @return $this
23
     */
24
    public function run()
25
    {
26
        return $this
27
            ->sayRenderable('conversations.exchange.index')
28
            ->verifyCustomer();
29
    }
30
31
    /**
32
     * Verify if the current customer has been registered or not.
33
     *
34
     * @return $this
35
     */
36
    protected function verifyCustomer()
37
    {
38
        if (!$customer = Customer::retrieveByBotManUser($this->getUser())) {
39
            $username = $this->getUser()->getUsername();
40
            $email = $this->getUserStorage('email');
41
42
            if (!$customer = Customer::retrieveByUsernameAndEmail(compact('username', 'email'))) {
43
                return $this
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->setPreviou...CustomerConversation()) returns the type void which is incompatible with the documented return type App\Conversations\ExchangeConversation.
Loading history...
Bug introduced by
Are you sure the usage of $this->setPreviousConver...CustomerConversation()) targeting App\Conversations\Conver...on::startConversation() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
44
                    ->setPreviousConversation($this)
45
                    ->sayRenderable('conversations.exchange.alert-registration-first')
46
                    ->startConversation(new RegisterCustomerConversation);
47
            }
48
        }
49
50
        return $this->displayCustomerData($customer);
51
    }
52
53
    /**
54
     * Reply with customer data.
55
     *
56
     * @param  \App\Models\Customer  $customer
57
     * @param  string|null  $validationErrorMessage
58
     * @return $this
59
     */
60
    protected function displayCustomerData(Customer $customer, string $validationErrorMessage = null)
61
    {
62
        $this->displayValidationErrorMessage($validationErrorMessage);
63
64
        if (!$this->getPreviousConversation() instanceof static) {
65
            $this->say('<em>Data anda sebelumnya sudah pernah terekam di database kami.</em>');
66
        }
67
68
        $this->destroyUserStorage(forceDestroy: true);
69
70
        $question = Question::create(view('conversations.exchange.confirm-customer_data', compact('customer'))->render())
0 ignored issues
show
Bug introduced by
It seems like view('conversations.exch...('customer'))->render() can also be of type array; however, parameter $text of BotMan\BotMan\Messages\Outgoing\Question::create() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

70
        $question = Question::create(/** @scrutinizer ignore-type */ view('conversations.exchange.confirm-customer_data', compact('customer'))->render())
Loading history...
71
            ->callbackId('exchange_confirm_customer_data')
72
            ->addButtons([
73
                Button::create(view('conversations.register-customer.reply-customer_data-yes')->render())->value('yes'),
0 ignored issues
show
Bug introduced by
It seems like view('conversations.regi...er_data-yes')->render() can also be of type array; however, parameter $text of BotMan\BotMan\Messages\O...ctions\Button::create() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

73
                Button::create(/** @scrutinizer ignore-type */ view('conversations.register-customer.reply-customer_data-yes')->render())->value('yes'),
Loading history...
74
                Button::create(view('conversations.register-customer.reply-customer_data-no')->render())->value('no'),
75
            ]);
76
77
        return $this->ask($question, next: function (Answer $answer) use ($customer) {
78
            if (!$answer->isInteractiveMessageReply()) {
79
                return;
80
            }
81
82
            if (!in_array($value = $answer->getValue(), ['yes', 'no'])) {
83
                return $this->displayCustomerData($customer, $this->fallbackMessage($answer->getText()));
84
            }
85
86
            if ($value === 'no') {
87
                $this->destroyUserStorage();
88
89
                return $this
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->setPreviousConver...CustomerConversation()) targeting App\Conversations\Conver...on::startConversation() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
90
                    ->setPreviousConversation($this)
91
                    ->startConversation(new UpdateCustomerConversation);
92
            }
93
94
            return $this->recordOrder($customer);
95
        });
96
    }
97
98
    /**
99
     * Record customer order data.
100
     *
101
     * @param  \App\Models\Customer  $customer
102
     * @param  string|null  $validationErrorMessage
103
     * @return $this
104
     */
105
    protected function recordOrder(Customer $customer, string $validationErrorMessage = null)
106
    {
107
        $this->displayValidationErrorMessage($validationErrorMessage);
108
109
        $denominations = Denomination::all('id', 'name', 'value');
110
        $keyboard = Keyboard::create(Keyboard::TYPE_INLINE)->resizeKeyboard();
111
112
        foreach ($denominations as $denomination) {
113
            $keyboard->addRow(
114
                KeyboardButton::create(
115
                    view('conversations.exchange.reply-denomination', compact('denomination'))->render()
116
                )->callbackData($denomination->getKey())
117
            );
118
        }
119
120
        $response = $this->reply(
121
            $question = view('conversations.exchange.alert-denomination')->render(),
0 ignored issues
show
Bug introduced by
It seems like $question = view('conver...enomination')->render() can also be of type array; however, parameter $message of App\Conversations\Conversation::reply() does only seem to accept BotMan\BotMan\Messages\O...utgoing\Question|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

121
            /** @scrutinizer ignore-type */ $question = view('conversations.exchange.alert-denomination')->render(),
Loading history...
122
            $additionalParameters = $keyboard->toArray()
123
        );
124
125
        return $this->getBot()->storeConversation($this, next: function (Answer $answer) use ($response, $customer, $denominations) {
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->getBot()->storeCo... $additionalParameters) targeting BotMan\BotMan\BotMan::storeConversation() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
126
            if (!$answer->isInteractiveMessageReply()) {
127
                return;
128
            }
129
130
            /** @var \App\Models\Denomination|null $denomination */
131
            if (!$denominations->contains($answer->getValue()) ||
132
                !$denomination = Denomination::find($answer->getValue())) {
133
                return $this->recordOrder($customer, $this->fallbackMessage($answer->getText()));
134
            }
135
136
            /** @var \App\Models\Order $order */
137
            $order = Order::findOrCreateFromCode($this->getUserStorage('order_code'), $customer, function (Order $order) {
138
                $this->setUserStorage(['order_code' => $order->code]);
139
            });
140
141
            $this->recordItem($customer, $order, $denomination);
142
143
            $this->deleteTelegramMessageFromResponse($response);
144
        }, question: $question, additionalParameters: $additionalParameters);
145
    }
146
147
    /**
148
     * Record customer item data.
149
     *
150
     * @param  \App\Models\Customer  $customer
151
     * @param  \App\Models\Order  $order
152
     * @param  \App\Models\Denomination  $denomination
153
     * @param  string|null  $validationErrorMessage
154
     * @return $this
155
     */
156
    protected function recordItem(Customer $customer, Order $order, Denomination $denomination, string $validationErrorMessage = null)
157
    {
158
        $this->displayValidationErrorMessage($validationErrorMessage);
159
160
        $keyboard = Keyboard::create(Keyboard::TYPE_INLINE)->resizeKeyboard();
161
        $unit = Str::lower($denomination->type->label);
162
163
        collect($denomination->range_order_bundle)->chunk(3)->map(function (Collection $quantities) use ($keyboard, $unit) {
0 ignored issues
show
Unused Code introduced by
The import $unit is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
164
            $keyboard->addRow(...$quantities->map(fn ($quantity) => KeyboardButton::create(
165
                view('conversations.exchange.reply-bundle_quantity-quantity', compact('quantity'))->render()
166
            )->callbackData($quantity))->toArray());
167
        });
168
169
        $keyboard->addRow(
170
            KeyboardButton::create(
171
                view('components.conversations.back', ['text' => 'opsi pilih nominal uang'])->render()
172
            )->callbackData('back_to_denomination_option')
173
        );
174
175
        $response = $this->reply(
176
            $question = view('conversations.exchange.ask-bundle_quantity', compact('denomination'))->render(),
0 ignored issues
show
Bug introduced by
It seems like $question = view('conver...nomination'))->render() can also be of type array; however, parameter $message of App\Conversations\Conversation::reply() does only seem to accept BotMan\BotMan\Messages\O...utgoing\Question|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

176
            /** @scrutinizer ignore-type */ $question = view('conversations.exchange.ask-bundle_quantity', compact('denomination'))->render(),
Loading history...
177
            $additionalParameters = $keyboard->toArray()
178
        );
179
180
        return $this->getBot()->storeConversation($this, next: function (Answer $answer) use ($response, $customer, $order, $denomination) {
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->getBot()->storeCo... $additionalParameters) targeting BotMan\BotMan\BotMan::storeConversation() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
181
            $this->deleteTelegramMessageFromResponse($response);
182
183
            if ($answer->getValue() === 'back_to_denomination_option') {
184
                return $this->recordOrder($customer);
185
            }
186
187
            if (!in_array($answer->getValue(), $denomination->range_order_bundle)) {
188
                return $this->recordItem($customer, $order, $denomination, trans('validation.between.numeric', [
0 ignored issues
show
Bug introduced by
It seems like trans('validation.betwee...>maximum_order_bundle)) can also be of type array and array; however, parameter $validationErrorMessage of App\Conversations\Exchan...versation::recordItem() does only seem to accept null|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

188
                return $this->recordItem($customer, $order, $denomination, /** @scrutinizer ignore-type */ trans('validation.between.numeric', [
Loading history...
189
                    'attribute' => trans('Quantity Per Bundle'),
190
                    'min' => $denomination->minimum_order_bundle,
191
                    'max' => $denomination->maximum_order_bundle,
192
                ]));
193
            }
194
195
            $item = new Item([
196
                'quantity_per_bundle' => $denomination->quantity_per_bundle,
197
                'bundle_quantity' => $answer->getValue(),
198
            ]);
199
200
            $item->setDenominationRelationValue($denomination);
201
202
            $order->items()->save($item);
203
204
            $this->reply('thanks');
205
        }, question: $question, additionalParameters: $additionalParameters);
206
    }
207
}
208