@fleetbase/storefront-engine 0.4.4 → 0.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/addon/components/modals/create-gateway.hbs +13 -27
- package/addon/components/schedule-manager.hbs +24 -20
- package/addon/components/settings-container.hbs +3 -2
- package/addon/components/widget/customers.hbs +56 -78
- package/addon/components/widget/orders.hbs +281 -303
- package/addon/components/widget/storefront-key-metrics.hbs +1 -1
- package/addon/components/widget/storefront-metrics.hbs +2 -2
- package/addon/controllers/settings.js +36 -0
- package/addon/services/storefront.js +6 -1
- package/addon/templates/settings/gateways.hbs +3 -3
- package/addon/templates/settings/index.hbs +322 -321
- package/addon/templates/settings/locations.hbs +2 -2
- package/addon/templates/settings.hbs +8 -30
- package/addon/utils/get-gateway-schemas.js +2 -0
- package/app/controllers/settings.js +1 -0
- package/composer.json +1 -1
- package/extension.json +1 -1
- package/package.json +2 -2
- package/server/config/storefront.php +11 -1
- package/server/src/Http/Controllers/v1/CheckoutController.php +41 -10
- package/server/src/Http/Controllers/v1/CustomerController.php +1 -1
- package/server/src/Http/Controllers/v1/OrderController.php +198 -1
- package/server/src/Http/Filter/OrderFilter.php +35 -29
- package/server/src/Http/Middleware/ThrottleRequests.php +16 -0
- package/server/src/Models/Cart.php +1 -1
- package/server/src/Providers/StorefrontServiceProvider.php +1 -1
- package/server/src/Support/QPay.php +78 -0
- package/server/src/routes.php +1 -0
|
@@ -23,10 +23,10 @@
|
|
|
23
23
|
</div>
|
|
24
24
|
|
|
25
25
|
{{#each @model as |storeLocation|}}
|
|
26
|
-
<ContentPanel @title={{storeLocation.name}} @open={{true}} @pad={{
|
|
26
|
+
<ContentPanel @title={{storeLocation.name}} @open={{true}} @pad={{false}} @wrapperClass="bordered-classic">
|
|
27
27
|
<div class="flex items-center justify-between mb-4">
|
|
28
28
|
<div>
|
|
29
|
-
<h4 class="
|
|
29
|
+
<h4 class="text-sm tracking-wide uppercase text-gray-700 dark:text-gray-400 font-semibold">{{t "storefront.settings.locations.store-hour"}}</h4>
|
|
30
30
|
</div>
|
|
31
31
|
<div class="flex items-center">
|
|
32
32
|
<Button @icon="edit" @text={{t "storefront.common.edit"}} @onClick={{fn this.editStoreLocation storeLocation}} @wrapperClass="mr-2" />
|
|
@@ -1,30 +1,8 @@
|
|
|
1
|
-
<
|
|
2
|
-
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
<FaIcon @icon="map-marker-alt" class="mr-1" />
|
|
10
|
-
<span>{{t "storefront.common.location"}}</span>
|
|
11
|
-
</LinkTo>
|
|
12
|
-
<LinkTo @route="settings.gateways" class="ui-tab">
|
|
13
|
-
<FaIcon @icon="cash-register" class="mr-1" />
|
|
14
|
-
<span>{{t "storefront.common.gateways"}}</span>
|
|
15
|
-
</LinkTo>
|
|
16
|
-
<LinkTo @route="settings.api" class="ui-tab">
|
|
17
|
-
<FaIcon @icon="code" class="mr-1" />
|
|
18
|
-
<span>{{t "storefront.common.api"}}</span>
|
|
19
|
-
</LinkTo>
|
|
20
|
-
<LinkTo @route="settings.notifications" class="ui-tab">
|
|
21
|
-
<FaIcon @icon="bell-concierge" class="mr-1" />
|
|
22
|
-
<span>{{t "storefront.common.notification"}}</span>
|
|
23
|
-
</LinkTo>
|
|
24
|
-
</nav>
|
|
25
|
-
</div>
|
|
26
|
-
</Layout::Section::Header>
|
|
27
|
-
|
|
28
|
-
<Layout::Section::Body>
|
|
29
|
-
{{outlet}}
|
|
30
|
-
</Layout::Section::Body>
|
|
1
|
+
<TabNavigation @tabs={{this.tabs}} @contentClass="scrollable" @tablistClass="px-4 flex-row-reverse">
|
|
2
|
+
<:actions>
|
|
3
|
+
<h3 class="uppercase text-xs tracking-wide text-gray-700 dark:text-gray-400 font-semibold">{{t "storefront.common.settings"}}</h3>
|
|
4
|
+
</:actions>
|
|
5
|
+
<:default>
|
|
6
|
+
{{outlet}}
|
|
7
|
+
</:default>
|
|
8
|
+
</TabNavigation>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '@fleetbase/storefront-engine/controllers/settings';
|
package/composer.json
CHANGED
package/extension.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fleetbase/storefront-engine",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.5",
|
|
4
4
|
"description": "Headless Commerce & Marketplace Extension for Fleetbase",
|
|
5
5
|
"fleetbase": {
|
|
6
6
|
"route": "storefront",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@babel/core": "^7.23.2",
|
|
47
47
|
"@fleetbase/ember-core": "^0.3.6",
|
|
48
|
-
"@fleetbase/ember-ui": "^0.3.
|
|
48
|
+
"@fleetbase/ember-ui": "^0.3.9",
|
|
49
49
|
"@fleetbase/fleetops-data": "^0.1.20",
|
|
50
50
|
"@fortawesome/ember-fontawesome": "^2.0.0",
|
|
51
51
|
"@fortawesome/fontawesome-svg-core": "6.4.0",
|
|
@@ -35,5 +35,15 @@ return [
|
|
|
35
35
|
*/
|
|
36
36
|
'connection' => [
|
|
37
37
|
'db' => env('STOREFRONT_DB_CONNECTION', 'storefront')
|
|
38
|
-
]
|
|
38
|
+
],
|
|
39
|
+
|
|
40
|
+
/*
|
|
41
|
+
|--------------------------------------------------------------------------
|
|
42
|
+
| Throttle/Rate-Limiting
|
|
43
|
+
|--------------------------------------------------------------------------
|
|
44
|
+
*/
|
|
45
|
+
'throttle' => [
|
|
46
|
+
'max_attempts' => env('STOREFRONT_THROTTLE_REQUESTS_PER_MINUTE', 500),
|
|
47
|
+
'decay_minutes' => env('STOREFRONT_THROTTLE_DECAY_MINUTES', 1),
|
|
48
|
+
],
|
|
39
49
|
];
|
|
@@ -435,7 +435,6 @@ class CheckoutController extends Controller
|
|
|
435
435
|
|
|
436
436
|
// Create qpay instance
|
|
437
437
|
$qpay = QPay::instance($gateway->config->username, $gateway->config->password, $gateway->callback_url);
|
|
438
|
-
|
|
439
438
|
if ($gateway->sandbox) {
|
|
440
439
|
$qpay = $qpay->useSandbox();
|
|
441
440
|
}
|
|
@@ -471,15 +470,44 @@ class CheckoutController extends Controller
|
|
|
471
470
|
$callbackUrl = Utils::apiUrl('storefront/v1/checkouts/capture-qpay', $callbackParams);
|
|
472
471
|
|
|
473
472
|
// Create invoice description
|
|
474
|
-
|
|
473
|
+
$ebarimtInvoiceCode = $gateway->sandbox ? 'TEST_INVOICE' : $gateway->config?->ebarimt_invoice_id ?? null;
|
|
475
474
|
$invoiceAmount = $amount;
|
|
476
|
-
$invoiceCode = $gateway->sandbox ? 'TEST_INVOICE' : $gateway->config
|
|
475
|
+
$invoiceCode = $gateway->sandbox ? 'TEST_INVOICE' : $gateway->config?->invoice_id ?? null;
|
|
477
476
|
$invoiceDescription = $about->name . ' cart checkout';
|
|
478
477
|
$invoiceReceiverCode = $checkout->public_id;
|
|
479
478
|
$senderInvoiceNo = $checkout->public_id;
|
|
479
|
+
$districtCode = $gateway->config?->district_code ?? null;
|
|
480
|
+
$invoiceReceiverData = Utils::filterArray([
|
|
481
|
+
'name' => $customer->name,
|
|
482
|
+
'email' => $customer->email ?? null,
|
|
483
|
+
'phone' => $customer->phone ?? null,
|
|
484
|
+
]);
|
|
485
|
+
$lines = [];
|
|
486
|
+
foreach ($cart->items as $item) {
|
|
487
|
+
$lines[] = [
|
|
488
|
+
'line_description' => $item->name,
|
|
489
|
+
'line_quantity' => $item->quantity ?? 1,
|
|
490
|
+
'line_unit_price' => number_format($item->price, 2, '.', ''),
|
|
491
|
+
'note' => $checkout->public_id,
|
|
492
|
+
'classification_code' => '0111100',
|
|
493
|
+
'taxes' => [
|
|
494
|
+
[
|
|
495
|
+
// 'tax_code' => 'VAT', // only works without this
|
|
496
|
+
'description' => 'НӨАТ',
|
|
497
|
+
'amount' => QPay::calculateTax($item->subtotal),
|
|
498
|
+
'note' => $checkout->public_id,
|
|
499
|
+
],
|
|
500
|
+
],
|
|
501
|
+
];
|
|
502
|
+
}
|
|
480
503
|
|
|
481
504
|
// Create qpay invoice
|
|
482
|
-
$invoice =
|
|
505
|
+
$invoice = null;
|
|
506
|
+
if ($ebarimtInvoiceCode) {
|
|
507
|
+
$invoice = $qpay->createEbarimtInvoice($ebarimtInvoiceCode, $senderInvoiceNo, $invoiceReceiverCode, $invoiceReceiverData, $invoiceDescription, '1', $districtCode, $lines);
|
|
508
|
+
} else {
|
|
509
|
+
$invoice = $qpay->createSimpleInvoice($invoiceAmount, $invoiceCode, $invoiceDescription, $invoiceReceiverCode, $senderInvoiceNo, $callbackUrl);
|
|
510
|
+
}
|
|
483
511
|
|
|
484
512
|
// Update checkout with invoice id
|
|
485
513
|
$checkout->updateOption('qpay_invoice_id', data_get($invoice, 'invoice_id'));
|
|
@@ -895,6 +923,7 @@ class CheckoutController extends Controller
|
|
|
895
923
|
'delivery_tip' => $checkout->getOption('delivery_tip'),
|
|
896
924
|
'total' => Utils::numbersOnly($amount),
|
|
897
925
|
'currency' => $currency,
|
|
926
|
+
'gateway' => $gateway->type,
|
|
898
927
|
'require_pod' => $about->getOption('require_pod'),
|
|
899
928
|
'pod_method' => $about->pod_method,
|
|
900
929
|
'is_pickup' => $checkout->is_pickup,
|
|
@@ -945,9 +974,6 @@ class CheckoutController extends Controller
|
|
|
945
974
|
// notify driver if assigned
|
|
946
975
|
$order->notifyDriverAssigned();
|
|
947
976
|
|
|
948
|
-
// notify order creation
|
|
949
|
-
Storefront::alertNewOrder($order);
|
|
950
|
-
|
|
951
977
|
// purchase service quote
|
|
952
978
|
if ($serviceQuote) {
|
|
953
979
|
$order->purchaseQuote($serviceQuote->uuid, $transactionDetails);
|
|
@@ -961,6 +987,9 @@ class CheckoutController extends Controller
|
|
|
961
987
|
}
|
|
962
988
|
}
|
|
963
989
|
|
|
990
|
+
// notify order creation
|
|
991
|
+
Storefront::alertNewOrder($order);
|
|
992
|
+
|
|
964
993
|
// update the cart with the checkout
|
|
965
994
|
$checkout->checkedout();
|
|
966
995
|
|
|
@@ -1139,6 +1168,7 @@ class CheckoutController extends Controller
|
|
|
1139
1168
|
'delivery_tip' => 0,
|
|
1140
1169
|
'total' => $subtotal,
|
|
1141
1170
|
'currency' => $currency,
|
|
1171
|
+
'gateway' => $gateway->type,
|
|
1142
1172
|
'require_pod' => $about->getOption('require_pod'),
|
|
1143
1173
|
'pod_method' => $about->pod_method,
|
|
1144
1174
|
'is_pickup' => $checkout->is_pickup,
|
|
@@ -1180,9 +1210,6 @@ class CheckoutController extends Controller
|
|
|
1180
1210
|
// purchase service quote
|
|
1181
1211
|
$order->purchaseQuote($serviceQuote->uuid, $transactionDetails);
|
|
1182
1212
|
|
|
1183
|
-
// notify order creation
|
|
1184
|
-
Storefront::alertNewOrder($order);
|
|
1185
|
-
|
|
1186
1213
|
// if order is auto accepted update status
|
|
1187
1214
|
if ($store->isOption('auto_accept_orders')) {
|
|
1188
1215
|
Storefront::autoAcceptOrder($order);
|
|
@@ -1190,6 +1217,9 @@ class CheckoutController extends Controller
|
|
|
1190
1217
|
Storefront::autoDispatchOrder($order);
|
|
1191
1218
|
}
|
|
1192
1219
|
}
|
|
1220
|
+
|
|
1221
|
+
// notify order creation
|
|
1222
|
+
Storefront::alertNewOrder($order);
|
|
1193
1223
|
}
|
|
1194
1224
|
|
|
1195
1225
|
// convert origin to Place
|
|
@@ -1225,6 +1255,7 @@ class CheckoutController extends Controller
|
|
|
1225
1255
|
'delivery_tip' => $checkout->getOption('delivery_tip'),
|
|
1226
1256
|
'total' => Utils::numbersOnly($amount),
|
|
1227
1257
|
'currency' => $currency,
|
|
1258
|
+
'gateway' => $gateway->type,
|
|
1228
1259
|
'require_pod' => $about->getOption('require_pod'),
|
|
1229
1260
|
'pod_method' => $about->pod_method,
|
|
1230
1261
|
'is_pickup' => $checkout->is_pickup,
|
|
@@ -336,7 +336,7 @@ class CustomerController extends Controller
|
|
|
336
336
|
public function query(Request $request)
|
|
337
337
|
{
|
|
338
338
|
$results = Contact::queryWithRequest($request, function (&$query, $request) {
|
|
339
|
-
$query->where(['type' => 'customer']);
|
|
339
|
+
$query->where(['type' => 'customer', 'company_uuid' => session('company')]);
|
|
340
340
|
});
|
|
341
341
|
|
|
342
342
|
return Customer::collection($results);
|
|
@@ -4,7 +4,10 @@ namespace Fleetbase\Storefront\Http\Controllers\v1;
|
|
|
4
4
|
|
|
5
5
|
use Fleetbase\FleetOps\Models\Order;
|
|
6
6
|
use Fleetbase\Http\Controllers\Controller;
|
|
7
|
+
use Fleetbase\Storefront\Models\Checkout;
|
|
8
|
+
use Fleetbase\Storefront\Support\QPay;
|
|
7
9
|
use Fleetbase\Storefront\Support\Storefront;
|
|
10
|
+
use Illuminate\Http\JsonResponse;
|
|
8
11
|
use Illuminate\Http\Request;
|
|
9
12
|
|
|
10
13
|
class OrderController extends Controller
|
|
@@ -17,8 +20,11 @@ class OrderController extends Controller
|
|
|
17
20
|
public function completeOrderPickup(Request $request)
|
|
18
21
|
{
|
|
19
22
|
$customer = Storefront::getCustomerFromToken();
|
|
20
|
-
|
|
23
|
+
if (!$customer) {
|
|
24
|
+
return response()->apiError('Customer is not authenticated.');
|
|
25
|
+
}
|
|
21
26
|
|
|
27
|
+
$order = Order::where('public_id', $request->order)->whereNull('deleted_at')->with(['customer'])->first();
|
|
22
28
|
if (!$order) {
|
|
23
29
|
return response()->apiError('No order found.');
|
|
24
30
|
}
|
|
@@ -40,4 +46,195 @@ class OrderController extends Controller
|
|
|
40
46
|
'status' => $order->status,
|
|
41
47
|
]);
|
|
42
48
|
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Get receipt for an order based on the payment method type.
|
|
52
|
+
*
|
|
53
|
+
* This method acts as a router that delegates receipt generation to the appropriate
|
|
54
|
+
* handler based on the order's payment method. It performs authentication and authorization
|
|
55
|
+
* checks before routing to the specific receipt handler.
|
|
56
|
+
*
|
|
57
|
+
* @param Request $request The HTTP request containing the order identifier
|
|
58
|
+
*
|
|
59
|
+
* @return JsonResponse The receipt data or error response
|
|
60
|
+
*/
|
|
61
|
+
public function getReceipt(Request $request)
|
|
62
|
+
{
|
|
63
|
+
// Authenticate customer
|
|
64
|
+
$customer = Storefront::getCustomerFromToken();
|
|
65
|
+
if (!$customer) {
|
|
66
|
+
return response()->apiError('Customer is not authenticated.');
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Retrieve order
|
|
70
|
+
$order = Order::where('public_id', $request->order)
|
|
71
|
+
->whereNull('deleted_at')
|
|
72
|
+
->with(['customer', 'payload'])
|
|
73
|
+
->first();
|
|
74
|
+
|
|
75
|
+
if (!$order) {
|
|
76
|
+
return response()->apiError('No order found.');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Authorize customer for this order
|
|
80
|
+
if ($order->customer_uuid !== $customer->uuid) {
|
|
81
|
+
return response()->apiError('Not authorized to get receipt for this order.');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Route to appropriate receipt handler based on payment method
|
|
85
|
+
$paymentMethod = $order->payload->payment_method ?? null;
|
|
86
|
+
|
|
87
|
+
switch ($paymentMethod) {
|
|
88
|
+
case 'qpay':
|
|
89
|
+
return $this->getQpayEbarimtReceipt($request, $order);
|
|
90
|
+
|
|
91
|
+
// Add more payment methods here in the future
|
|
92
|
+
// case 'stripe':
|
|
93
|
+
// return $this->getStripeReceipt($request, $order);
|
|
94
|
+
// case 'paypal':
|
|
95
|
+
// return $this->getPaypalReceipt($request, $order);
|
|
96
|
+
|
|
97
|
+
default:
|
|
98
|
+
return response()->json([
|
|
99
|
+
'message' => 'No receipt available for this payment method.',
|
|
100
|
+
'payment_method' => $paymentMethod,
|
|
101
|
+
]);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Get Ebarimt receipt for QPay payment.
|
|
107
|
+
*
|
|
108
|
+
* This helper method handles the complete flow of generating an Ebarimt receipt
|
|
109
|
+
* for orders paid through QPay. It validates the request parameters, retrieves
|
|
110
|
+
* the payment information from QPay, creates the Ebarimt receipt, and stores
|
|
111
|
+
* the receipt data in the order metadata.
|
|
112
|
+
*
|
|
113
|
+
* @param Request $request The HTTP request containing Ebarimt parameters
|
|
114
|
+
* @param Order $order The order instance for which to generate the receipt
|
|
115
|
+
*
|
|
116
|
+
* @return JsonResponse The Ebarimt receipt data or error response
|
|
117
|
+
*/
|
|
118
|
+
private function getQpayEbarimtReceipt(Request $request, Order $order)
|
|
119
|
+
{
|
|
120
|
+
// Extract and validate Ebarimt parameters
|
|
121
|
+
$ebarimtReceiverType = strtoupper($request->input('ebarimt_receiver_type', 'CITIZEN'));
|
|
122
|
+
$ebarimtReceiver = $request->input('ebarimt_receiver');
|
|
123
|
+
|
|
124
|
+
if ($ebarimtReceiverType === 'COMPANY' && empty($ebarimtReceiver)) {
|
|
125
|
+
return response()->apiError('Company registration number is required.');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Verify payment method is QPay
|
|
129
|
+
$order->loadMissing('payload');
|
|
130
|
+
if ($order->payload && $order->payload->payment_method !== 'qpay') {
|
|
131
|
+
return response()->apiError('This order was not paid using QPay.');
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Retrieve checkout record
|
|
135
|
+
$checkout = $order->getMeta('checkout_id')
|
|
136
|
+
? Checkout::where('public_id', $order->getMeta('checkout_id'))->first()
|
|
137
|
+
: null;
|
|
138
|
+
|
|
139
|
+
if (!$checkout) {
|
|
140
|
+
return response()->apiError('No checkout found for this order.');
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Initialize QPay gateway
|
|
144
|
+
$qpay = $this->initializeQpayGateway();
|
|
145
|
+
if ($qpay instanceof JsonResponse) {
|
|
146
|
+
return $qpay; // Return error response if gateway initialization failed
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Retrieve payment information from QPay
|
|
150
|
+
$invoiceId = $checkout->getOption('qpay_invoice_id');
|
|
151
|
+
$payment = $qpay->getPayment($invoiceId);
|
|
152
|
+
|
|
153
|
+
// Create Ebarimt receipt
|
|
154
|
+
$ebarimt = $this->createEbarimtReceipt($qpay, $payment, $ebarimtReceiverType, $ebarimtReceiver);
|
|
155
|
+
|
|
156
|
+
if ($ebarimt instanceof JsonResponse) {
|
|
157
|
+
return $ebarimt; // Return error response if creation failed
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Store receipt in order metadata
|
|
161
|
+
$order->updateMeta('ebarimt', $ebarimt);
|
|
162
|
+
|
|
163
|
+
return response()->json($ebarimt);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Initialize and configure the QPay gateway instance.
|
|
168
|
+
*
|
|
169
|
+
* This method retrieves the QPay gateway configuration, creates a QPay instance
|
|
170
|
+
* with the appropriate credentials, configures sandbox mode if enabled, and
|
|
171
|
+
* sets the authentication token.
|
|
172
|
+
*
|
|
173
|
+
* @return QPay|JsonResponse The configured QPay instance or error response
|
|
174
|
+
*/
|
|
175
|
+
private function initializeQpayGateway()
|
|
176
|
+
{
|
|
177
|
+
// Resolve gateway configuration
|
|
178
|
+
$gateway = Storefront::findGateway('qpay');
|
|
179
|
+
if (!$gateway) {
|
|
180
|
+
return response()->apiError('QPay is not configured.');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Create QPay instance with credentials
|
|
184
|
+
$qpay = QPay::instance(
|
|
185
|
+
$gateway->config->username,
|
|
186
|
+
$gateway->config->password,
|
|
187
|
+
$gateway->callback_url
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
// Configure sandbox mode if enabled
|
|
191
|
+
if ($gateway->sandbox) {
|
|
192
|
+
$qpay = $qpay->useSandbox();
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Set authentication token
|
|
196
|
+
$qpay = $qpay->setAuthToken();
|
|
197
|
+
|
|
198
|
+
return $qpay;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Create an Ebarimt receipt via QPay API.
|
|
203
|
+
*
|
|
204
|
+
* This method prepares the parameters for the Ebarimt receipt creation request,
|
|
205
|
+
* sends the request to the QPay Ebarimt API, and handles any errors that occur
|
|
206
|
+
* during the process.
|
|
207
|
+
*
|
|
208
|
+
* @param QPay $qpay The configured QPay instance
|
|
209
|
+
* @param mixed $payment The payment information retrieved from QPay
|
|
210
|
+
* @param string $receiverType The type of receiver (CITIZEN or COMPANY)
|
|
211
|
+
* @param string|null $receiver The company registration number (required if receiverType is COMPANY)
|
|
212
|
+
*
|
|
213
|
+
* @return mixed|JsonResponse The Ebarimt receipt data or error response
|
|
214
|
+
*/
|
|
215
|
+
private function createEbarimtReceipt(QPay $qpay, $payment, string $receiverType, ?string $receiver = null)
|
|
216
|
+
{
|
|
217
|
+
// Prepare request parameters
|
|
218
|
+
$params = [
|
|
219
|
+
'payment_id' => data_get($payment, 'payment_id'),
|
|
220
|
+
'ebarimt_receiver_type' => $receiverType,
|
|
221
|
+
];
|
|
222
|
+
|
|
223
|
+
// Add company registration number if receiver type is COMPANY
|
|
224
|
+
if ($receiverType === 'COMPANY' && !empty($receiver)) {
|
|
225
|
+
$params['ebarimt_receiver'] = $receiver;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Send request to QPay Ebarimt API
|
|
229
|
+
$ebarimt = $qpay->post('ebarimt_v3/create', $params);
|
|
230
|
+
|
|
231
|
+
// Check for API errors
|
|
232
|
+
if (isset($ebarimt->error)) {
|
|
233
|
+
return response()->apiError(
|
|
234
|
+
$ebarimt->error ?? $ebarimt->message ?? 'Unable to create ebarimt receipt'
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return $ebarimt;
|
|
239
|
+
}
|
|
43
240
|
}
|
|
@@ -8,35 +8,41 @@ class OrderFilter extends FleetOpsOrderFilter
|
|
|
8
8
|
{
|
|
9
9
|
public function queryForInternal()
|
|
10
10
|
{
|
|
11
|
-
$this->builder
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
function ($
|
|
21
|
-
$
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
->
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
11
|
+
$this->builder->where('company_uuid', $this->session->get('company'));
|
|
12
|
+
$this->builder->whereNotNull('meta->storefront_id');
|
|
13
|
+
|
|
14
|
+
// replace ambiguous whereRelation with qualified whereHas to avoid alias clashes
|
|
15
|
+
$this->builder->whereHas('payload', function ($payloadQuery) {
|
|
16
|
+
$payloadQuery->where(function ($q) {
|
|
17
|
+
$q->orWhereHas('pickup', function ($p) {
|
|
18
|
+
$p->whereNotNull('places.uuid');
|
|
19
|
+
});
|
|
20
|
+
$q->orWhereHas('dropoff', function ($d) {
|
|
21
|
+
$d->whereNotNull('places.uuid');
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// ensure associated tracking data exists
|
|
27
|
+
$this->builder->whereHas('trackingNumber', function ($q) {
|
|
28
|
+
$q->select('uuid');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
$this->builder->whereHas('trackingStatuses', function ($q) {
|
|
32
|
+
$q->select('uuid');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// eager load main relationships to reduce N+1 overhead
|
|
36
|
+
$this->builder->with([
|
|
37
|
+
'payload.entities',
|
|
38
|
+
'payload.waypoints',
|
|
39
|
+
'payload.pickup',
|
|
40
|
+
'payload.dropoff',
|
|
41
|
+
'payload.return',
|
|
42
|
+
'trackingNumber',
|
|
43
|
+
'trackingStatuses',
|
|
44
|
+
'driverAssigned',
|
|
45
|
+
]);
|
|
40
46
|
}
|
|
41
47
|
|
|
42
48
|
public function storefront(string $storefront)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<?php
|
|
2
|
+
|
|
3
|
+
namespace Fleetbase\Storefront\Http\Middleware;
|
|
4
|
+
|
|
5
|
+
use Illuminate\Routing\Middleware\ThrottleRequests as ThrottleRequestsMiddleware;
|
|
6
|
+
|
|
7
|
+
class ThrottleRequests extends ThrottleRequestsMiddleware
|
|
8
|
+
{
|
|
9
|
+
public function handle($request, \Closure $next, $maxAttempts = null, $decayMinutes = null, $prefix = '')
|
|
10
|
+
{
|
|
11
|
+
$maxAttempts = config('storefront.throttle.max_attempts', 500);
|
|
12
|
+
$decayMinutes = config('storefront.throttle.decay_minutes', 1);
|
|
13
|
+
|
|
14
|
+
return parent::handle($request, $next, $maxAttempts, $decayMinutes, $prefix);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -38,7 +38,7 @@ class StorefrontServiceProvider extends CoreServiceProvider
|
|
|
38
38
|
*/
|
|
39
39
|
public $middleware = [
|
|
40
40
|
'storefront.api' => [
|
|
41
|
-
|
|
41
|
+
\Fleetbase\Storefront\Http\Middleware\ThrottleRequests::class,
|
|
42
42
|
\Illuminate\Session\Middleware\StartSession::class,
|
|
43
43
|
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
|
|
44
44
|
\Fleetbase\Storefront\Http\Middleware\SetStorefrontSession::class,
|