Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
reducestorebatchamountaction.php
1<?php
2
4
6use Bitrix\Catalog\EO_StoreBatchDocumentElement;
7use Bitrix\Catalog\EO_StoreDocumentElement;
8use Bitrix\Catalog\EO_StoreBatch;
20
25{
27
28 protected int $storeId;
29
30 protected int $productId;
31 protected ?EO_StoreDocumentElement $storeDocumentElement;
32 public function __construct(int $documentElementId)
33 {
34 $this->storeDocumentElement = StoreDocumentElementTable::getList([
35 'filter' => [
36 '=ID' => $documentElementId,
37 ],
38 'select' => ['*', 'DOCUMENT'],
39 'limit' => 1
40 ])
41 ->fetchObject()
42 ;
43
44 if ($this->storeDocumentElement)
45 {
46 $this->productId = $this->storeDocumentElement->getElementId();
47 }
48 }
49
53 public function canExecute(): Result
54 {
55 if ($this->storeDocumentElement)
56 {
57 $this->storeId = $this->storeDocumentElement->getStoreTo();
58 }
59
60 return $this->checkStoreAmount($this->storeDocumentElement);
61 }
62
66 public function execute(): Result
67 {
68 $storeBatches = StoreBatchTable::getList([
69 'filter' => [
70 '=S_BATCH_ELEMENT.DOCUMENT_ELEMENT_ID' => $this->storeDocumentElement->getId(),
71 '>S_BATCH_ELEMENT.AMOUNT' => 0,
72 ],
73 'runtime' => [
74 new Reference(
75 'S_BATCH_ELEMENT',
76 StoreBatchDocumentElementTable::class,
77 Join::on('this.ID', 'ref.PRODUCT_BATCH_ID')
78 )
79 ],
80 'select' => ['*', 'S_BATCH_ELEMENT'],
81 ])
82 ->fetchCollection()
83 ;
84
85 $batchIds = $storeBatches->getIdList();
86 if (empty($batchIds))
87 {
88 return new Result();
89 }
90
91 foreach ($storeBatches as $batch)
92 {
93 if (CostPriceCalculator::getMethod() === CostPriceCalculator::METHOD_FIFO)
94 {
95 if ($this->storeDocumentElement->getAmount() > $batch->getAvailableAmount())
96 {
97 $this->rebindWriteOffValues($batch, $batchIds);
98 }
99
100 $resultDelete = $batch->delete();
101 if (!$resultDelete->isSuccess())
102 {
103 return $resultDelete;
104 }
105 }
106 else
107 {
109 $oldBatchElement = $batch->get('S_BATCH_ELEMENT');
110 $purchasingPrice = $oldBatchElement->getBatchPrice();
111 if (
112 $this->storeDocumentElement->getDocument()
113 && $this->storeDocumentElement->getDocument()->getCurrency() !== $batch->getPurchasingCurrency()
114 && Loader::includeModule('currency')
115 )
116 {
117 $purchasingPrice = \CCurrencyRates::convertCurrency(
118 $this->storeDocumentElement->getPurchasingPrice(),
119 $this->storeDocumentElement->getDocument()->getCurrency(),
120 $batch->getPurchasingCurrency()
121 );
122 }
123
124 $newAmount = max($batch->getAvailableAmount() - $oldBatchElement->getAmount(), 0);
125 if ($newAmount > 0)
126 {
127 $newSum = $batch->getAvailableAmount() * $batch->getPurchasingPrice() - $oldBatchElement->getAmount() * $purchasingPrice;
128 $newPurchasingPrice = $newSum / $newAmount;
129 $precision = (int)Option::get('sale', 'value_precision', 2);
130 $newPurchasingPrice = round($newPurchasingPrice, $precision);
131 $batch->setPurchasingPrice($newPurchasingPrice);
132 }
133 $batch->setAvailableAmount($newAmount);
134 $batch->save();
135 }
136 }
137
139 'filter' => [
140 '=PRODUCT_BATCH_ID' => $batchIds,
141 '=DOCUMENT_ELEMENT_ID' => $this->storeDocumentElement->getId(),
142 '>AMOUNT' => 0,
143 ]
144 ]);
145
146 while ($binding = $bindings->fetch())
147 {
149 }
150
151 return new Result();
152 }
153
162 private function rebindWriteOffValues(EO_StoreBatch $oldBatch, array $prohibitedBatchIds = []): void
163 {
164 $batchManager = new BatchManager($oldBatch->getElementId());
165 $currentStoreCollection = $batchManager->getAvailableStoreCollection($oldBatch->getStoreId());
167 'filter' => [
168 'PRODUCT_BATCH_ID' => $oldBatch->getId(),
169 '<AMOUNT' => 0,
170 ],
171 ]);
172
173 $prohibitedBatchIds[] = $oldBatch->getId();
174 while ($binding = $bindings->fetch())
175 {
176 $amountBindingValue = abs($binding['AMOUNT']);
177 $oldAmount = $amountBindingValue;
178 foreach ($currentStoreCollection as $batchItem)
179 {
180 if (in_array($batchItem->getId(), $prohibitedBatchIds, true))
181 {
182 continue;
183 }
184
185 $storeAmount = $batchItem->getAvailableAmount();
186 if ($oldAmount <= 0)
187 {
188 break;
189 }
190
191 $outStoreQuantity = ($storeAmount > $oldAmount) ? $oldAmount : $storeAmount;
192 $newAvailableAmount = $storeAmount - $outStoreQuantity;
193 $batchItem->setAvailableAmount($newAvailableAmount);
194 if ($oldAmount === $amountBindingValue)
195 {
196 $updateFields = [
197 'PRODUCT_BATCH_ID' => $batchItem->getId(),
198 'AMOUNT' => -$outStoreQuantity,
199 ];
200
201 StoreBatchDocumentElementTable::update($binding['ID'], $updateFields);
202 }
203 else
204 {
206 'DOCUMENT_ELEMENT_ID' => $binding['DOCUMENT_ELEMENT_ID'],
207 'SHIPMENT_ITEM_STORE_ID' => $binding['SHIPMENT_ITEM_STORE_ID'],
208 'AMOUNT' => -$outStoreQuantity,
209 'PRODUCT_BATCH_ID' => $batchItem->getId(),
210 'BATCH_PRICE' => $binding['BATCH_PRICE'],
211 'BATCH_CURRENCY' => $binding['BATCH_CURRENCY'],
212 ]);
213 }
214
215 $oldAmount -= $storeAmount;
216 }
217 }
218
219 $currentStoreCollection->save();
220 }
221}
static getList(array $parameters=array())
static update($primary, array $data)
checkStoreAmount(EO_StoreDocumentElement $storeDocumentElement=null)