1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
|
4
|
|
|
namespace Stockbase\Integration\StockbaseApi\Client; |
5
|
|
|
|
6
|
|
|
use Magento\Sales\Api\Data\OrderItemInterface; |
7
|
|
|
use Webmozart\Assert\Assert; |
8
|
|
|
use DivideBV\PHPDivideIQ\DivideIQ; |
9
|
|
|
use Magento\Sales\Api\Data\OrderInterface; |
10
|
|
|
use Stockbase\Integration\Model\Config\StockbaseConfiguration; |
11
|
|
|
use Stockbase\Integration\Model\StockItemReserve; |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* Stockbase API client. |
15
|
|
|
*/ |
16
|
|
|
class StockbaseClient |
17
|
|
|
{ |
18
|
|
|
const STOCKBASE_STOCK_ENDPOINT = 'stockbase_stock'; |
19
|
|
|
const STOCKBASE_IMAGES_ENDPOINT = 'stockbase_images'; |
20
|
|
|
const STOCKBASE_ORDER_REQUEST_ENDPOINT = 'stockbase_orderrequest'; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* @var DivideIQ |
24
|
|
|
*/ |
25
|
|
|
private $divideIqClient; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* @var StockbaseConfiguration |
29
|
|
|
*/ |
30
|
|
|
private $stockbaseConfiguration; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* StockbaseClient constructor. |
34
|
|
|
* @param DivideIQ $divideIqClient |
35
|
|
|
* @param StockbaseConfiguration $stockbaseConfiguration |
36
|
4 |
|
*/ |
37
|
|
|
public function __construct( |
38
|
|
|
DivideIQ $divideIqClient, |
39
|
|
|
StockbaseConfiguration $stockbaseConfiguration |
40
|
4 |
|
) { |
41
|
4 |
|
$this->divideIqClient = $divideIqClient; |
42
|
4 |
|
$this->stockbaseConfiguration = $stockbaseConfiguration; |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* Gets current Stockbase stock state. |
47
|
|
|
* |
48
|
|
|
* @param \DateTime|null $since |
49
|
|
|
* @param \DateTime|null $until |
50
|
|
|
* @return object |
51
|
|
|
* @throws \Exception |
52
|
1 |
|
*/ |
53
|
|
|
public function getStock(\DateTime $since = null, \DateTime $until = null) |
54
|
1 |
|
{ |
55
|
1 |
|
$data = []; |
56
|
1 |
|
if ($since !== null) { |
57
|
|
|
$data['Since'] = $since->getTimestamp(); |
58
|
1 |
|
} |
59
|
1 |
|
if ($until !== null) { |
60
|
|
|
$data['Until'] = $until->getTimestamp(); |
61
|
|
|
} |
62
|
1 |
|
|
63
|
|
|
return $this->divideIqClient->request(self::STOCKBASE_STOCK_ENDPOINT, $data); |
64
|
|
|
} |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* Gets images for specified EANs. |
68
|
|
|
* |
69
|
|
|
* @param string[] $eans |
70
|
|
|
* @return object |
71
|
|
|
* @throws \Exception |
72
|
1 |
|
*/ |
73
|
|
|
public function getImages(array $eans) |
74
|
1 |
|
{ |
75
|
|
|
Assert::allNumeric($eans); |
76
|
|
|
|
77
|
1 |
|
$data = [ |
78
|
|
|
'ean' => implode(',', $eans), |
79
|
|
|
]; |
80
|
1 |
|
|
81
|
|
|
return $this->divideIqClient->request(self::STOCKBASE_IMAGES_ENDPOINT, $data); |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* Downloads a file using current client configuration and saves it at the specified destination. |
86
|
|
|
* |
87
|
|
|
* @param string|\GuzzleHttp\Url $uri File URI. |
88
|
|
|
* @param string|resource|\GuzzleHttp\Stream\StreamInterface $destination Destination where the file should be saved to. |
89
|
|
|
* @return null |
90
|
|
|
*/ |
91
|
|
|
public function downloadImage($uri, $destination) |
92
|
|
|
{ |
93
|
|
|
return $this->divideIqClient->download($uri, $destination); |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* Creates an order on Stockbase from reserved items for specified Magento order. |
98
|
|
|
* |
99
|
|
|
* @param OrderInterface $order |
100
|
|
|
* @param StockItemReserve[] $reservedStockbaseItems |
101
|
|
|
* @return object |
102
|
|
|
* @throws \Exception |
103
|
2 |
|
*/ |
104
|
|
|
public function createOrder(OrderInterface $order, array $reservedStockbaseItems) |
105
|
2 |
|
{ |
106
|
2 |
|
$orderPrefix = $this->stockbaseConfiguration->getOrderPrefix(); |
107
|
2 |
|
$shippingAddress = $order->getShippingAddress(); |
108
|
2 |
|
$now = new \DateTime('now', new \DateTimeZone('UTC')); |
109
|
|
|
$orderLines = []; |
110
|
2 |
|
|
111
|
2 |
|
$orderLineNumber = 0; |
112
|
2 |
|
foreach ($reservedStockbaseItems as $reserve) { |
113
|
2 |
|
$orderLineNumber++; |
114
|
2 |
|
$orderLineData = [ |
115
|
2 |
|
'Number' => $orderLineNumber, // Number starting from 1 |
116
|
2 |
|
'EAN' => $reserve->getEan(), |
117
|
|
|
'Amount' => (int) $reserve->getAmount(), |
118
|
|
|
]; |
119
|
|
|
|
120
|
|
|
/** @var OrderItemInterface $orderItem */ |
121
|
2 |
|
$orderItem = $this->_getOrderItemById($order, $reserve->getOrderItemId()); |
122
|
2 |
|
if ($orderItem && $orderItem->getRowTotal() !== null) { |
123
|
2 |
|
$orderLineData['Price'] = $orderItem->getRowTotal(); |
124
|
|
|
} |
125
|
|
|
$orderLines[] = $orderLineData; |
126
|
|
|
} |
127
|
|
|
|
128
|
2 |
|
$orderHeader = [ |
129
|
2 |
|
'OrderNumber' => $orderPrefix.'#'.$order->getRealOrderId(), |
130
|
2 |
|
'TimeStamp' => $now->format('Y-m-d h:i:s'), |
131
|
|
|
'Attention' => $order->getCustomerNote() ? $order->getCustomerNote() : ' ', |
132
|
|
|
]; |
133
|
2 |
|
|
134
|
2 |
|
$orderDelivery = [ |
135
|
2 |
|
'Person' => [ |
136
|
2 |
|
'FirstName' => $shippingAddress->getFirstname(), |
137
|
2 |
|
'Surname' => $shippingAddress->getLastname(), |
138
|
|
|
'Company' => $shippingAddress->getCompany() ?: ' ', |
139
|
|
|
], |
140
|
|
|
'Address' => [ |
141
|
|
|
'Street' => $shippingAddress->getStreetLine(1), |
142
|
2 |
|
'StreetNumber' => $shippingAddress->getStreetLine(2) ?: '-', |
143
|
2 |
|
'ZipCode' => $shippingAddress->getPostcode(), |
144
|
2 |
|
'City' => $shippingAddress->getCity(), |
145
|
|
|
'CountryCode' => $shippingAddress->getCountryId(), |
146
|
|
|
], |
147
|
2 |
|
]; |
148
|
2 |
|
|
149
|
1 |
|
$orderRequest = [ |
150
|
1 |
|
'OrderHeader' => $orderHeader, |
151
|
1 |
|
'OrderLines' => $orderLines, |
152
|
1 |
|
'OrderDelivery' => $orderDelivery, |
153
|
1 |
|
]; |
154
|
|
|
|
155
|
|
|
$response = $this->divideIqClient->request(self::STOCKBASE_ORDER_REQUEST_ENDPOINT, $orderRequest, 'POST'); |
156
|
|
|
if ($response->{'StatusCode'} != 1) { |
157
|
1 |
|
$message = ''; |
158
|
|
|
if (isset($response->{'Items'}) && is_array($response->{'Items'})) { |
159
|
|
|
foreach ($response->{'Items'} as $item) { |
160
|
1 |
|
if ($item->{'StatusCode'} != 1) { |
161
|
|
|
$message .= ' '.trim($item->{'ExceptionMessage'}); |
162
|
|
|
} |
163
|
|
|
} |
164
|
|
|
} |
165
|
|
|
throw new StockbaseClientException('Failed sending order to stockbase.'.$message); |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
return $response; |
169
|
|
|
} |
170
|
|
|
|
171
|
|
|
private function _getOrderItemById(OrderInterface $order, $orderItemId) |
172
|
|
|
{ |
173
|
|
|
if ($order instanceof \Magento\Sales\Model\Order) { |
|
|
|
|
174
|
|
|
return $order->getItemById($orderItemId); |
175
|
|
|
} else { |
176
|
|
|
/** @var OrderItemInterface $orderItem */ |
177
|
|
|
$orderItem = array_filter((array) $order->getItems(), function (OrderItemInterface $item) use ($orderItemId) { |
178
|
|
|
return $item->getItemId() == $orderItemId; |
179
|
|
|
}); |
180
|
|
|
|
181
|
|
|
return reset($orderItem); |
182
|
|
|
} |
183
|
|
|
} |
184
|
|
|
} |
185
|
|
|
|
This error could be the result of:
1. Missing dependencies
PHP Analyzer uses your
composer.json
file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects thecomposer.json
to be in the root folder of your repository.Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the
require
orrequire-dev
section?2. Missing use statement
PHP does not complain about undefined classes in
ìnstanceof
checks. For example, the following PHP code will work perfectly fine:If you have not tested against this specific condition, such errors might go unnoticed.