1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace Loevgaard\DandomainStockBundle\EventListener; |
6
|
|
|
|
7
|
|
|
use Doctrine\Common\EventSubscriber; |
8
|
|
|
use Doctrine\ORM\EntityManager; |
9
|
|
|
use Doctrine\ORM\Event\OnFlushEventArgs; |
10
|
|
|
use Doctrine\ORM\Events; |
11
|
|
|
use Doctrine\ORM\Mapping\ClassMetadata; |
12
|
|
|
use Doctrine\ORM\ORMException; |
13
|
|
|
use Doctrine\ORM\UnitOfWork; |
14
|
|
|
use Loevgaard\DandomainFoundation\Entity\Generated\OrderLineInterface; |
15
|
|
|
use Loevgaard\DandomainStock\Entity\Generated\StockMovementInterface; |
16
|
|
|
use Loevgaard\DandomainStock\Entity\StockMovement; |
17
|
|
|
use Loevgaard\DandomainStock\Exception\CurrencyMismatchException; |
18
|
|
|
use Loevgaard\DandomainStock\Exception\StockMovementProductMismatchException; |
19
|
|
|
use Loevgaard\DandomainStock\Exception\UndefinedPriceForCurrencyException; |
20
|
|
|
use Loevgaard\DandomainStock\Exception\UnsetCurrencyException; |
21
|
|
|
use Loevgaard\DandomainStock\Exception\UnsetProductException; |
22
|
|
|
|
23
|
|
|
class StockMovementSubscriber implements EventSubscriber |
24
|
|
|
{ |
25
|
|
|
/** |
26
|
|
|
* @var array |
27
|
|
|
*/ |
28
|
|
|
private $orderStateIds; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* @param array $orderStateIds An array of external ids for order states (use the id in the Dandomain interface) |
32
|
|
|
*/ |
33
|
1 |
|
public function __construct(array $orderStateIds) |
34
|
|
|
{ |
35
|
1 |
|
$this->orderStateIds = $orderStateIds; |
36
|
1 |
|
} |
37
|
|
|
|
38
|
1 |
|
public function getSubscribedEvents() |
39
|
|
|
{ |
40
|
|
|
return [ |
41
|
1 |
|
Events::onFlush, |
42
|
|
|
]; |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* @param OnFlushEventArgs $args |
47
|
|
|
* @throws CurrencyMismatchException |
48
|
|
|
* @throws ORMException |
49
|
|
|
* @throws StockMovementProductMismatchException |
50
|
|
|
* @throws UndefinedPriceForCurrencyException |
51
|
|
|
* @throws UnsetCurrencyException |
52
|
|
|
* @throws UnsetProductException |
53
|
|
|
*/ |
54
|
|
|
public function onFlush(OnFlushEventArgs $args) |
55
|
|
|
{ |
56
|
|
|
$em = $args->getEntityManager(); |
57
|
|
|
$uow = $em->getUnitOfWork(); |
58
|
|
|
|
59
|
|
|
foreach ($uow->getScheduledEntityInsertions() as $entity) { |
60
|
|
|
/** @var OrderLineInterface $entity */ |
61
|
|
|
if(!$this->isOrderLine($entity) || !$this->isValidState($entity)) { |
62
|
|
|
continue; |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
$stockMovement = $this->stockMovementFromOrderLine($entity); |
66
|
|
|
|
67
|
|
|
$this->persistStockMovement($stockMovement, $em, $uow); |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
foreach ($uow->getScheduledEntityUpdates() as $entity) { |
71
|
|
|
/** @var OrderLineInterface $entity */ |
72
|
|
|
if(!$this->isOrderLine($entity) || !$this->isValidState($entity)) { |
73
|
|
|
continue; |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
$stockMovement = $this->stockMovementFromOrderLine($entity); |
77
|
|
|
$effectiveStockMovement = $entity->computeEffectiveStockMovement(); |
78
|
|
|
if ($effectiveStockMovement) { |
79
|
|
|
$stockMovement = $effectiveStockMovement->diff($stockMovement); |
80
|
|
|
$stockMovement->setType(StockMovement::TYPE_REGULATION); |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
$this->persistStockMovement($stockMovement, $em, $uow); |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
foreach ($uow->getScheduledEntityDeletions() as $entity) { |
87
|
|
|
/** @var OrderLineInterface $entity */ |
88
|
|
|
if(!$this->isOrderLine($entity)) { |
89
|
|
|
continue; |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
$effectiveStockMovement = $entity->computeEffectiveStockMovement(); |
93
|
|
|
|
94
|
|
|
if ($effectiveStockMovement) { |
95
|
|
|
$stockMovement = $effectiveStockMovement->inverse(); |
96
|
|
|
$stockMovement |
97
|
|
|
->setType(StockMovement::TYPE_REGULATION) // we set the type as regulation since it is not a sale now |
98
|
|
|
->setOrderLineRemoved(true) |
99
|
|
|
->setOrderLine(null); |
100
|
|
|
|
101
|
|
|
$this->persistStockMovement($stockMovement, $em, $uow); |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
foreach ($entity->getStockMovements() as $stockMovement) { |
105
|
|
|
$stockMovement |
106
|
|
|
->setOrderLineRemoved(true) |
107
|
|
|
->setOrderLine(null); |
108
|
|
|
|
109
|
|
|
$md = $this->metaData($em, $stockMovement); |
110
|
|
|
$uow->recomputeSingleEntityChangeSet($md, $stockMovement); |
111
|
|
|
} |
112
|
|
|
} |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
private function isOrderLine($entity) : bool |
116
|
|
|
{ |
117
|
|
|
return $entity instanceof OrderLineInterface; |
|
|
|
|
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
private function isValidState(OrderLineInterface $orderLine) : bool |
121
|
|
|
{ |
122
|
|
|
return $orderLine->getOrder() |
123
|
|
|
&& $orderLine->getOrder()->getState() |
124
|
|
|
&& in_array($orderLine->getOrder()->getState()->getExternalId(), $this->orderStateIds); |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* @param OrderLineInterface $orderLine |
129
|
|
|
* @return StockMovement |
130
|
|
|
* @throws CurrencyMismatchException |
131
|
|
|
* @throws UndefinedPriceForCurrencyException |
132
|
|
|
* @throws UnsetProductException |
133
|
|
|
*/ |
134
|
|
|
private function stockMovementFromOrderLine(OrderLineInterface $orderLine) : StockMovement |
135
|
|
|
{ |
136
|
|
|
$stockMovement = new StockMovement(); |
137
|
|
|
$stockMovement->populateFromOrderLine($orderLine); |
138
|
|
|
|
139
|
|
|
return $stockMovement; |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
private function metaData(EntityManager $entityManager, $entity) : ClassMetadata |
143
|
|
|
{ |
144
|
|
|
return $entityManager->getClassMetadata(get_class($entity)); |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
/** |
148
|
|
|
* @param StockMovementInterface $stockMovement |
149
|
|
|
* @param EntityManager $entityManager |
150
|
|
|
* @param UnitOfWork $unitOfWork |
151
|
|
|
* @return boolean |
152
|
|
|
* @throws ORMException |
153
|
|
|
*/ |
154
|
|
|
private function persistStockMovement(StockMovementInterface $stockMovement, EntityManager $entityManager, UnitOfWork $unitOfWork) : bool |
155
|
|
|
{ |
156
|
|
|
// if the quantity is 0 we don't want to add a stock movement since this will just pollute the stock movement table |
157
|
|
|
if($stockMovement->getQuantity() === 0) { |
158
|
|
|
return false; |
159
|
|
|
} |
160
|
|
|
|
161
|
|
|
$stockMovement->validate(); |
162
|
|
|
$entityManager->persist($stockMovement); |
163
|
|
|
$md = $this->metaData($entityManager, $stockMovement); |
164
|
|
|
$unitOfWork->computeChangeSet($md, $stockMovement); |
165
|
|
|
|
166
|
|
|
return true; |
167
|
|
|
} |
168
|
|
|
} |
169
|
|
|
|
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.