Bitrix-D7
23.9
Загрузка...
Поиск...
Не найдено
Doctor.php
1
<?php
2
3
namespace
Bitrix\Catalog\InventoryManagement\Helpers
;
4
5
use
Bitrix\Catalog\ProductTable
;
6
use
Bitrix\Catalog\StoreProductTable
;
7
use
Bitrix\Main\Application
;
8
use
Bitrix\Main\ArgumentNullException
;
9
use
Bitrix\Main\Text\HtmlFilter
;
10
35
final
class
Doctor
36
{
44
private
function
getSql():
string
45
{
46
$conn =
Application::getConnection
();
47
$helper = $conn->getSqlHelper();
48
return
'
49
SELECT
50
cp.ID AS '
. $helper->quote(
'PRODUCT_ID'
) .
',
51
cp.QUANTITY AS '
. $helper->quote(
'PRODUCT_QUANTITY_AVAILABLE'
) .
',
52
csp.QUANTITY_AVAILABLE AS '
. $helper->quote(
'STORE_QUANTITY_AVAILABLE'
) .
',
53
cp.QUANTITY_RESERVED AS '
. $helper->quote(
'PRODUCT_QUANTITY_RESERVED'
) .
',
54
csp.QUANTITY_RESERVED AS '
. $helper->quote(
'STORE_QUANTITY_RESERVED'
) .
',
55
sbr.QUANTITY_RESERVED AS '
. $helper->quote(
'SALE_QUANTITY_RESERVED'
) .
'
56
FROM
57
b_catalog_product AS cp
58
LEFT JOIN (
59
SELECT
60
PRODUCT_ID,
61
SUM(AMOUNT) as QUANTITY,
62
SUM(QUANTITY_RESERVED) as QUANTITY_RESERVED,
63
SUM(AMOUNT - QUANTITY_RESERVED) as QUANTITY_AVAILABLE
64
FROM
65
b_catalog_store_product
66
INNER JOIN b_catalog_store ON b_catalog_store.ID = b_catalog_store_product.STORE_ID AND b_catalog_store.ACTIVE = \'Y\'
67
GROUP BY PRODUCT_ID
68
) as csp ON cp.ID = csp.PRODUCT_ID
69
LEFT JOIN (
70
SELECT
71
sb.PRODUCT_ID,
72
SUM(sbr.QUANTITY) AS QUANTITY_RESERVED
73
FROM
74
b_sale_basket AS sb
75
LEFT JOIN b_sale_basket_reservation AS sbr ON sbr.BASKET_ID = sb.ID AND sbr.QUANTITY != 0
76
WHERE
77
sb.PRODUCT_ID > 0
78
AND sbr.QUANTITY != 0
79
GROUP BY sb.PRODUCT_ID
80
) as sbr ON cp.ID = sbr.PRODUCT_ID
81
WHERE
82
(
83
cp.QUANTITY != 0
84
OR cp.QUANTITY_RESERVED != 0
85
OR csp.QUANTITY != 0
86
OR csp.QUANTITY_RESERVED != 0
87
OR csp.QUANTITY_AVAILABLE != 0
88
OR sbr.QUANTITY_RESERVED != 0
89
)
90
'
;
91
}
92
98
public
function
printProblems
(): void
99
{
100
$sql = $this->getSql() .
' AND (
101
cp.QUANTITY != csp.QUANTITY_AVAILABLE OR csp.QUANTITY_AVAILABLE IS NULL
102
OR cp.QUANTITY_RESERVED != csp.QUANTITY_RESERVED OR csp.QUANTITY_RESERVED IS NULL
103
OR sbr.QUANTITY_RESERVED > cp.QUANTITY_RESERVED
104
OR cp.QUANTITY_RESERVED < 0
105
OR csp.QUANTITY_RESERVED < 0
106
)'
;
107
108
$result = [];
109
110
$rows =
Application::getConnection
()->query($sql);
111
foreach
($rows as $row)
112
{
113
$problems = [];
114
115
$storeReserveQuantity = (float)$row[
'STORE_QUANTITY_RESERVED'
];
116
$productReserveQuantity = (float)$row[
'PRODUCT_QUANTITY_RESERVED'
];
117
118
if
((
float
)$row[
'PRODUCT_QUANTITY_AVAILABLE'
] !== (float)$row[
'STORE_QUANTITY_AVAILABLE'
])
119
{
120
$problems[] =
'Available quantity not match'
;
121
}
122
123
if
($productReserveQuantity !== $storeReserveQuantity)
124
{
125
$problems[] =
'Reserve quantity not match'
;
126
}
127
128
if
($productReserveQuantity < 0.0)
129
{
130
$problems[] =
'Product reserve quantity less than 0'
;
131
}
132
133
if
($storeReserveQuantity < 0.0)
134
{
135
$problems[] =
'Store reserve quantity less than 0'
;
136
}
137
138
if
((
float
)$row[
'SALE_QUANTITY_RESERVED'
] > $productReserveQuantity)
139
{
140
$problems[] =
'More is reserved in \'sale\' than in \'catalog\''
;
141
}
142
143
if
(empty($problems))
144
{
145
$problems[] =
'Unknown, check SQL'
;
146
}
147
148
$result[] = [
'PROBLEMS'
=> join(
'; '
, $problems)] + $row;
149
}
150
151
$this->printTable($result);
152
}
153
159
public
function
printInfo
(): void
160
{
161
$this->printTable(
162
Application::getConnection
()->query($this->getSql())->fetchAll()
163
);
164
}
165
171
private
function
printTable(array $rows): void
172
{
173
if
(empty($rows))
174
{
175
echo
'-- empty --'
;
176
return
;
177
}
178
179
$headers = array_keys(
180
current($rows)
181
);
182
183
echo
'<table border="1" cellspacing="0" cellpadding="2"><tr>'
;
184
foreach
($headers as $header)
185
{
186
echo
'<th>'
.
HtmlFilter::encode
($header) .
'</th>'
;
187
}
188
189
foreach
($rows as $row)
190
{
191
echo
'<tr>'
;
192
193
foreach
($headers as $header)
194
{
195
$value = isset($row[$header]) && $row[$header] !==
''
? $row[$header] :
'-'
;
196
echo
'<td>'
.
HtmlFilter::encode
($value) .
'</td>'
;
197
}
198
199
echo
'</td>'
;
200
}
201
202
echo
'</table>'
;
203
}
204
212
public
function
fixQuantitiesFromStores
(
int
...$productIds): void
213
{
214
if
(empty($productIds))
215
{
216
throw
new
ArgumentNullException
(
'productIds'
);
217
}
218
219
$result = [];
220
221
$productIdsSql = join(
','
, $productIds);
222
$sql =
"
223
SELECT
224
PRODUCT_ID,
225
SUM(AMOUNT) as QUANTITY
226
FROM
227
b_catalog_store_product
228
INNER JOIN b_catalog_store ON b_catalog_store.ID = b_catalog_store_product.STORE_ID AND b_catalog_store.ACTIVE = 'Y'
229
WHERE
230
PRODUCT_ID IN ({$productIdsSql})
231
GROUP BY
232
PRODUCT_ID
233
"
;
234
$rows =
Application::getConnection
()->query($sql);
235
foreach
($rows as $row)
236
{
237
$productId = (int)$row[
'PRODUCT_ID'
];
238
239
$result[$productId] = [
240
'PRODUCT_ID'
=> $productId,
241
'NEW_QUANTITY'
=> (float)$row[
'QUANTITY'
],
242
];
243
}
244
245
// fill products without store quantities
246
foreach
($productIds as $productId)
247
{
248
$result[$productId] ??= [
249
'PRODUCT_ID'
=> $productId,
250
'NEW_QUANTITY'
=> 0.0,
251
];
252
}
253
254
// update products
255
foreach
($result as $productId => &$item)
256
{
257
// or \Bitrix\Catalog\Model\Product::update ?
258
$saveResult =
ProductTable::update
($productId, [
259
'QUANTITY'
=> $item[
'NEW_QUANTITY'
],
260
]);
261
$item[
'SAVE_RESULT'
] =
262
$saveResult->isSuccess()
263
?
'ok'
264
: join(
', '
, $saveResult->getErrorMessages())
265
;
266
}
267
268
$this->printTable($result);
269
}
270
278
public
function
fixReservesFromStores
(
int
...$productIds): void
279
{
280
if
(empty($productIds))
281
{
282
throw
new
ArgumentNullException
(
'productIds'
);
283
}
284
285
$result = [];
286
287
$productIdsSql = join(
','
, $productIds);
288
$sql =
"
289
SELECT
290
PRODUCT_ID,
291
SUM(QUANTITY_RESERVED) as QUANTITY_RESERVED
292
FROM
293
b_catalog_store_product
294
INNER JOIN b_catalog_store ON b_catalog_store.ID = b_catalog_store_product.STORE_ID AND b_catalog_store.ACTIVE = 'Y'
295
WHERE
296
PRODUCT_ID IN ({$productIdsSql})
297
GROUP BY
298
PRODUCT_ID
299
"
;
300
$rows =
Application::getConnection
()->query($sql);
301
foreach
($rows as $row)
302
{
303
$productId = (int)$row[
'PRODUCT_ID'
];
304
305
$result[$productId] = [
306
'PRODUCT_ID'
=> $productId,
307
'NEW_QUANTITY_RESERVED'
=> (float)$row[
'QUANTITY_RESERVED'
],
308
];
309
}
310
311
// fill products without store quantities
312
foreach
($productIds as $productId)
313
{
314
$result[$productId] ??= [
315
'PRODUCT_ID'
=> $productId,
316
'NEW_QUANTITY_RESERVED'
=> 0.0,
317
];
318
}
319
320
// update products
321
foreach
($result as $productId => &$item)
322
{
323
// or \Bitrix\Catalog\Model\Product::update ?
324
$saveResult =
ProductTable::update
($productId, [
325
'QUANTITY_RESERVED'
=> $item[
'NEW_QUANTITY_RESERVED'
],
326
]);
327
$item[
'SAVE_RESULT'
] =
328
$saveResult->isSuccess()
329
?
'ok'
330
: join(
', '
, $saveResult->getErrorMessages())
331
;
332
}
333
334
$this->printTable($result);
335
}
336
343
public
function
fixReservesLessZero
(): void
344
{
345
$db =
Application::getConnection
();
346
347
// products
348
$db->queryExecute(
349
'UPDATE b_catalog_product SET QUANTITY_RESERVED = 0 WHERE QUANTITY_RESERVED < 0'
350
);
351
if
($db->getAffectedRowsCount() > 0)
352
{
353
ProductTable::cleanCache
();
354
}
355
356
// stores
357
$db->queryExecute(
358
'UPDATE b_catalog_store_product SET QUANTITY_RESERVED = 0 WHERE QUANTITY_RESERVED < 0'
359
);
360
if
($db->getAffectedRowsCount() > 0)
361
{
362
StoreProductTable::cleanCache
();
363
}
364
}
365
}
Bitrix\Catalog\InventoryManagement\Helpers\Doctor
Definition
Doctor.php:36
Bitrix\Catalog\InventoryManagement\Helpers\Doctor\printInfo
printInfo()
Definition
Doctor.php:159
Bitrix\Catalog\InventoryManagement\Helpers\Doctor\fixQuantitiesFromStores
fixQuantitiesFromStores(int ... $productIds)
Definition
Doctor.php:212
Bitrix\Catalog\InventoryManagement\Helpers\Doctor\fixReservesLessZero
fixReservesLessZero()
Definition
Doctor.php:343
Bitrix\Catalog\InventoryManagement\Helpers\Doctor\printProblems
printProblems()
Definition
Doctor.php:98
Bitrix\Catalog\InventoryManagement\Helpers\Doctor\fixReservesFromStores
fixReservesFromStores(int ... $productIds)
Definition
Doctor.php:278
Bitrix\Catalog\ProductTable
Definition
product.php:63
Bitrix\Catalog\StoreProductTable
Definition
storeproduct.php:39
Bitrix\Main\Application
Definition
application.php:28
Bitrix\Main\Application\getConnection
static getConnection($name="")
Definition
application.php:611
Bitrix\Main\ArgumentNullException
Definition
exception.php:54
Bitrix\Main\ORM\Data\DataManager\cleanCache
static cleanCache()
Definition
datamanager.php:1966
Bitrix\Main\ORM\Data\DataManager\update
static update($primary, array $data)
Definition
datamanager.php:1246
Bitrix\Main\Text\HtmlFilter
Definition
htmlfilter.php:11
Bitrix\Main\Text\HtmlFilter\encode
static encode($string, $flags=ENT_COMPAT, $doubleEncode=true)
Definition
htmlfilter.php:12
Bitrix\Catalog\InventoryManagement\Helpers
Definition
Doctor.php:3
modules
catalog
lib
InventoryManagement
Helpers
Doctor.php
Создано системой
1.10.0