Issues (3641)

Spryker/Zed/PriceProduct/Business/Model/Writer.php (1 issue)

1
<?php
2
3
/**
4
 * Copyright © 2016-present Spryker Systems GmbH. All rights reserved.
5
 * Use of this software requires acceptance of the Evaluation License Agreement. See LICENSE file.
6
 */
7
8
namespace Spryker\Zed\PriceProduct\Business\Model;
9
10
use Generated\Shared\Transfer\PriceProductCriteriaTransfer;
11
use Generated\Shared\Transfer\PriceProductTransfer;
12
use Orm\Zed\PriceProduct\Persistence\SpyPriceProduct;
13
use Spryker\Zed\PriceProduct\Business\Exception\MissingPriceException;
14
use Spryker\Zed\PriceProduct\Business\Exception\ProductPriceChangeException;
15
use Spryker\Zed\PriceProduct\Business\Model\PriceType\PriceProductTypeReaderInterface;
16
use Spryker\Zed\PriceProduct\Business\Model\Product\PriceProductStoreWriterInterface;
17
use Spryker\Zed\PriceProduct\Dependency\Facade\PriceProductToProductFacadeInterface;
18
use Spryker\Zed\PriceProduct\Dependency\Facade\PriceProductToTouchFacadeInterface;
19
use Spryker\Zed\PriceProduct\Persistence\PriceProductQueryContainerInterface;
20
use Spryker\Zed\PriceProduct\PriceProductConfig;
21
use Spryker\Zed\PropelOrm\Business\Transaction\DatabaseTransactionHandlerTrait;
22
23
class Writer implements WriterInterface
24
{
25
    use DatabaseTransactionHandlerTrait;
0 ignored issues
show
Deprecated Code introduced by
The trait Spryker\Zed\PropelOrm\Bu...TransactionHandlerTrait has been deprecated: Use {@link \Spryker\Zed\Kernel\Persistence\EntityManager\TransactionTrait} instead. ( Ignorable by Annotation )

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

25
    use /** @scrutinizer ignore-deprecated */ DatabaseTransactionHandlerTrait;

This trait has been deprecated. The supplier of the trait has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the trait will be removed and what other trait to use instead.

Loading history...
26
27
    /**
28
     * @var string
29
     */
30
    public const TOUCH_PRODUCT = 'product';
31
32
    /**
33
     * @var \Spryker\Zed\PriceProduct\Persistence\PriceProductQueryContainerInterface
34
     */
35
    protected $queryContainer;
36
37
    /**
38
     * @var \Spryker\Zed\PriceProduct\Dependency\Facade\PriceProductToTouchFacadeInterface
39
     */
40
    protected $touchFacade;
41
42
    /**
43
     * @var \Spryker\Zed\PriceProduct\PriceProductConfig
44
     */
45
    protected $priceConfig;
46
47
    /**
48
     * @var \Spryker\Zed\PriceProduct\Dependency\Facade\PriceProductToProductFacadeInterface
49
     */
50
    protected $productFacade;
51
52
    /**
53
     * @var \Spryker\Zed\PriceProduct\Business\Model\PriceType\PriceProductTypeReaderInterface
54
     */
55
    protected $priceTypeReader;
56
57
    /**
58
     * @var \Spryker\Zed\PriceProduct\Business\Model\Product\PriceProductStoreWriterInterface
59
     */
60
    protected $priceProductStoreWriter;
61
62
    /**
63
     * @param \Spryker\Zed\PriceProduct\Persistence\PriceProductQueryContainerInterface $queryContainer
64
     * @param \Spryker\Zed\PriceProduct\Dependency\Facade\PriceProductToTouchFacadeInterface $touchFacade
65
     * @param \Spryker\Zed\PriceProduct\PriceProductConfig $priceConfig
66
     * @param \Spryker\Zed\PriceProduct\Dependency\Facade\PriceProductToProductFacadeInterface $productFacade
67
     * @param \Spryker\Zed\PriceProduct\Business\Model\PriceType\PriceProductTypeReaderInterface $priceTypeReader
68
     * @param \Spryker\Zed\PriceProduct\Business\Model\Product\PriceProductStoreWriterInterface $priceProductStoreWriter
69
     */
70
    public function __construct(
71
        PriceProductQueryContainerInterface $queryContainer,
72
        PriceProductToTouchFacadeInterface $touchFacade,
73
        PriceProductConfig $priceConfig,
74
        PriceProductToProductFacadeInterface $productFacade,
75
        PriceProductTypeReaderInterface $priceTypeReader,
76
        PriceProductStoreWriterInterface $priceProductStoreWriter
77
    ) {
78
        $this->queryContainer = $queryContainer;
79
        $this->touchFacade = $touchFacade;
80
        $this->priceConfig = $priceConfig;
81
        $this->productFacade = $productFacade;
82
        $this->priceTypeReader = $priceTypeReader;
83
        $this->priceProductStoreWriter = $priceProductStoreWriter;
84
    }
85
86
    /**
87
     * @param \Generated\Shared\Transfer\PriceProductTransfer $priceProductTransfer
88
     *
89
     * @throws \Spryker\Zed\PriceProduct\Business\Exception\ProductPriceChangeException
90
     *
91
     * @return \Generated\Shared\Transfer\PriceProductTransfer
92
     */
93
    public function createPriceForProduct(PriceProductTransfer $priceProductTransfer)
94
    {
95
        $priceProductTransfer
96
            ->requireMoneyValue()
97
            ->requirePriceDimension();
98
99
        $priceProductTransfer = $this->setPriceType($priceProductTransfer);
100
        if ($this->havePriceAlreadyAssignedForCouple($priceProductTransfer)) {
101
            throw new ProductPriceChangeException('This couple product price type is already set');
102
        }
103
104
        $this->loadPriceProductTransfer($priceProductTransfer);
105
106
        $priceProductTransfer = $this->savePriceProductEntity($priceProductTransfer, new SpyPriceProduct());
107
        if ($priceProductTransfer->getIdProduct()) {
108
            /** @var int $idProduct */
109
            $idProduct = $priceProductTransfer->getIdProduct();
110
            $this->insertTouchRecord(static::TOUCH_PRODUCT, $idProduct);
111
        }
112
113
        $priceProductTransfer->setIdPriceProduct($priceProductTransfer->getIdPriceProduct());
114
115
        return $priceProductTransfer;
116
    }
117
118
    /**
119
     * @param \Generated\Shared\Transfer\PriceProductTransfer $priceProductTransfer
120
     *
121
     * @throws \Spryker\Zed\PriceProduct\Business\Exception\ProductPriceChangeException
122
     *
123
     * @return void
124
     */
125
    public function setPriceForProduct(PriceProductTransfer $priceProductTransfer)
126
    {
127
        $priceProductTransfer->requireMoneyValue();
128
129
        $priceProductTransfer = $this->setPriceType($priceProductTransfer);
130
131
        if (!$this->havePriceInAnyCouple($priceProductTransfer)) {
132
            throw new ProductPriceChangeException('There is no price assigned for selected product!');
133
        }
134
135
        $this->loadPriceProductTransfer($priceProductTransfer);
136
137
        /** @var int $idPriceProduct */
138
        $idPriceProduct = $priceProductTransfer->requireIdPriceProduct()->getIdPriceProduct();
139
        $priceProductEntity = $this->getPriceProductById($idPriceProduct);
140
        $this->savePriceProductEntity($priceProductTransfer, $priceProductEntity);
141
142
        if ($priceProductTransfer->getIdProduct()) {
143
            /** @var int $idProduct */
144
            $idProduct = $priceProductTransfer->getIdProduct();
145
            $this->insertTouchRecord(static::TOUCH_PRODUCT, $idProduct);
146
        }
147
    }
148
149
    /**
150
     * @param \Generated\Shared\Transfer\PriceProductTransfer $priceProductTransfer
151
     *
152
     * @return void
153
     */
154
    protected function loadPriceProductTransfer(PriceProductTransfer $priceProductTransfer)
155
    {
156
        $this->loadProductAbstractIdForPriceProductTransfer($priceProductTransfer);
157
        $this->loadProductConcreteIdForPriceProductTransfer($priceProductTransfer);
158
    }
159
160
    /**
161
     * @param \Generated\Shared\Transfer\PriceProductTransfer $priceProductTransfer
162
     *
163
     * @return void
164
     */
165
    protected function loadProductAbstractIdForPriceProductTransfer(PriceProductTransfer $priceProductTransfer)
166
    {
167
        if ($priceProductTransfer->getIdProductAbstract() !== null) {
168
            return;
169
        }
170
171
        /** @var string $skuProductAbstract */
172
        $skuProductAbstract = $priceProductTransfer->requireSkuProductAbstract()->getSkuProductAbstract();
173
        $priceProductTransfer->setIdProductAbstract(
174
            $this->productFacade->findProductAbstractIdBySku($skuProductAbstract),
175
        );
176
    }
177
178
    /**
179
     * @param \Generated\Shared\Transfer\PriceProductTransfer $priceProductTransfer
180
     *
181
     * @return void
182
     */
183
    protected function loadProductConcreteIdForPriceProductTransfer(PriceProductTransfer $priceProductTransfer)
184
    {
185
        /** @var string $skuProduct */
186
        $skuProduct = $priceProductTransfer->getSkuProduct();
187
188
        if (
189
            $priceProductTransfer->getIdProduct() === null &&
190
            $this->productFacade->hasProductConcrete($skuProduct)
191
        ) {
192
            /** @var int $idProduct */
193
            $idProduct = $this->productFacade->findProductConcreteIdBySku($skuProduct);
194
            $priceProductTransfer->setIdProduct($idProduct);
195
        }
196
    }
197
198
    /**
199
     * @param \Generated\Shared\Transfer\PriceProductTransfer $priceProductTransfer
200
     * @param \Orm\Zed\PriceProduct\Persistence\SpyPriceProduct $priceProductEntity
201
     *
202
     * @return \Generated\Shared\Transfer\PriceProductTransfer
203
     */
204
    protected function savePriceProductEntity(PriceProductTransfer $priceProductTransfer, SpyPriceProduct $priceProductEntity): PriceProductTransfer
205
    {
206
        /** @var string $priceTypeName */
207
        $priceTypeName = $priceProductTransfer->requirePriceTypeName()->getPriceTypeName();
208
        $priceType = $this->priceTypeReader->getPriceTypeByName($priceTypeName);
209
        $priceProductEntity->setPriceType($priceType);
210
211
        if ($priceProductTransfer->getIdProduct()) {
212
            $priceProductEntity->setFkProduct($priceProductTransfer->getIdProduct());
213
        } else {
214
            $priceProductEntity->setFkProductAbstract($priceProductTransfer->getIdProductAbstract());
215
        }
216
217
        $priceProductEntity->save();
218
219
        $priceProductTransfer->setIdPriceProduct($priceProductEntity->getIdPriceProduct());
220
221
        return $this->priceProductStoreWriter->persistPriceProductStore($priceProductTransfer);
222
    }
223
224
    /**
225
     * @param string $itemType
226
     * @param int $itemId
227
     *
228
     * @return void
229
     */
230
    protected function insertTouchRecord($itemType, $itemId)
231
    {
232
        $this->touchFacade->touchActive($itemType, $itemId);
233
    }
234
235
    /**
236
     * @param \Generated\Shared\Transfer\PriceProductTransfer $priceProductTransfer
237
     *
238
     * @return \Generated\Shared\Transfer\PriceProductTransfer
239
     */
240
    protected function setPriceType(PriceProductTransfer $priceProductTransfer)
241
    {
242
        if ($priceProductTransfer->getPriceTypeName() === null) {
243
            $priceProductTransfer->setPriceTypeName(
244
                $this->priceConfig->getPriceTypeDefaultName(),
245
            );
246
        }
247
248
        return $priceProductTransfer;
249
    }
250
251
    /**
252
     * @param int $idPriceProduct
253
     *
254
     * @throws \Spryker\Zed\PriceProduct\Business\Exception\MissingPriceException
255
     *
256
     * @return \Orm\Zed\PriceProduct\Persistence\SpyPriceProduct
257
     */
258
    protected function getPriceProductById($idPriceProduct)
259
    {
260
        $priceProductEntity = $this->queryContainer
261
            ->queryPriceProductEntity($idPriceProduct)
262
            ->findOne();
263
264
        if ($priceProductEntity === null) {
265
            throw new MissingPriceException(
266
                sprintf(
267
                    'There are no prices for product with id "%s"',
268
                    $idPriceProduct,
269
                ),
270
            );
271
        }
272
273
        return $priceProductEntity;
274
    }
275
276
    /**
277
     * @param \Generated\Shared\Transfer\PriceProductTransfer $priceProductTransfer
278
     *
279
     * @return bool
280
     */
281
    protected function isPriceTypeExistingForProductAbstract(PriceProductTransfer $priceProductTransfer)
282
    {
283
        $priceProductTransfer->requireSkuProductAbstract();
284
285
        $priceProductCriteriaTransfer = $this->createPriceProductCriteriaFor($priceProductTransfer);
286
287
        /** @var string $skuProductAbstract */
288
        $skuProductAbstract = $priceProductTransfer->requireSkuProductAbstract()->getSkuProductAbstract();
289
        $priceEntities = $this->queryContainer
290
            ->queryPriceEntityForProductAbstract(
291
                $skuProductAbstract,
292
                $priceProductCriteriaTransfer,
293
            )->findOne();
294
295
        return ($priceEntities !== null);
296
    }
297
298
    /**
299
     * @param \Generated\Shared\Transfer\PriceProductTransfer $priceProductTransfer
300
     *
301
     * @return bool
302
     */
303
    protected function isPriceTypeExistingForProductConcrete(PriceProductTransfer $priceProductTransfer)
304
    {
305
        /** @var string $skuProduct */
306
        $skuProduct = $priceProductTransfer->requireSkuProduct()->getSkuProduct();
307
308
        $priceProductCriteriaTransfer = $this->createPriceProductCriteriaFor($priceProductTransfer);
309
310
        $priceEntities = $this->queryContainer
311
            ->queryPriceEntityForProductConcrete(
312
                $skuProduct,
313
                $priceProductCriteriaTransfer,
314
            );
315
316
        return ($priceEntities->count() > 0);
317
    }
318
319
    /**
320
     * @param \Generated\Shared\Transfer\PriceProductTransfer $priceProductTransfer
321
     *
322
     * @return bool
323
     */
324
    protected function havePriceAlreadyAssignedForCouple(PriceProductTransfer $priceProductTransfer)
325
    {
326
        return $this->isPriceTypeExistingForProductAbstract($priceProductTransfer)
327
            && $this->isPriceTypeExistingForProductConcrete($priceProductTransfer);
328
    }
329
330
    /**
331
     * @param \Generated\Shared\Transfer\PriceProductTransfer $priceProductTransfer
332
     *
333
     * @return bool
334
     */
335
    protected function havePriceInAnyCouple(PriceProductTransfer $priceProductTransfer)
336
    {
337
        return $this->isPriceTypeExistingForProductConcrete($priceProductTransfer)
338
            || $this->isPriceTypeExistingForProductAbstract($priceProductTransfer);
339
    }
340
341
    /**
342
     * @param \Generated\Shared\Transfer\PriceProductTransfer $priceProductTransfer
343
     *
344
     * @return \Generated\Shared\Transfer\PriceProductCriteriaTransfer
345
     */
346
    protected function createPriceProductCriteriaFor(PriceProductTransfer $priceProductTransfer)
347
    {
348
        /** @var \Generated\Shared\Transfer\MoneyValueTransfer $moneyValueTransfer */
349
        $moneyValueTransfer = $priceProductTransfer->requireMoneyValue()->getMoneyValue();
350
        /** @var string $priceTypeName */
351
        $priceTypeName = $priceProductTransfer->requirePriceTypeName()->getPriceTypeName();
352
        $priceTypeEntity = $this->priceTypeReader->getPriceTypeByName($priceTypeName);
353
354
        return (new PriceProductCriteriaTransfer())
355
            ->setIdCurrency($moneyValueTransfer->getFkCurrency())
356
            ->setIdStore($moneyValueTransfer->getFkStore())
357
            ->setPriceType($priceTypeEntity->getName());
358
    }
359
}
360