Allow to specify an informational field during a part stock operation, where the user can specify, when this operation was really performed

Fixes issue #416
This commit is contained in:
Jan Böhmer 2023-11-25 19:10:18 +01:00
parent 6cff19358a
commit b447a69dae
6 changed files with 89 additions and 16 deletions

View file

@ -401,22 +401,33 @@ class PartController extends AbstractController
$comment = $request->request->get('comment');
$action = $request->request->get('action');
$timestamp = null;
$timestamp_str = $request->request->getString('timestamp', '');
//Try to parse the timestamp
if($timestamp_str !== '') {
$timestamp = new DateTime($timestamp_str);
}
//Ensure that the timestamp is not in the future
if($timestamp !== null && $timestamp > new DateTime("+20min")) {
throw new \LogicException("The timestamp must not be in the future!");
}
try {
switch ($action) {
case "withdraw":
case "remove":
$this->denyAccessUnlessGranted('withdraw', $partLot);
$withdrawAddHelper->withdraw($partLot, $amount, $comment);
$withdrawAddHelper->withdraw($partLot, $amount, $comment, $timestamp);
break;
case "add":
$this->denyAccessUnlessGranted('add', $partLot);
$withdrawAddHelper->add($partLot, $amount, $comment);
$withdrawAddHelper->add($partLot, $amount, $comment, $timestamp);
break;
case "move":
$this->denyAccessUnlessGranted('move', $partLot);
$this->denyAccessUnlessGranted('move', $targetLot);
$withdrawAddHelper->move($partLot, $targetLot, $amount, $comment);
$withdrawAddHelper->move($partLot, $targetLot, $amount, $comment, $timestamp);
break;
default:
throw new \RuntimeException("Unknown action!");

View file

@ -41,8 +41,10 @@ class PartStockChangedLogEntry extends AbstractLogEntry
* @param float $new_total_part_instock The new total instock of the part.
* @param string $comment The comment associated with the change.
* @param PartLot|null $move_to_target The target lot if the type is TYPE_MOVE.
* @param \DateTimeInterface|null $action_timestamp The optional timestamp, where the action happened. Useful if the action happened in the past, and the log entry is created afterwards.
*/
protected function __construct(PartStockChangeType $type, PartLot $lot, float $old_stock, float $new_stock, float $new_total_part_instock, string $comment, ?PartLot $move_to_target = null)
protected function __construct(PartStockChangeType $type, PartLot $lot, float $old_stock, float $new_stock, float $new_total_part_instock, string $comment, ?PartLot $move_to_target = null,
?\DateTimeInterface $action_timestamp = null)
{
parent::__construct();
@ -62,6 +64,11 @@ class PartStockChangedLogEntry extends AbstractLogEntry
$this->extra['c'] = mb_strimwidth($comment, 0, self::COMMENT_MAX_LENGTH, '...');
}
if ($action_timestamp instanceof \DateTimeInterface) {
//The action timestamp is saved as an ISO 8601 string
$this->extra['a'] = $action_timestamp->format(\DateTimeInterface::ATOM);
}
if ($move_to_target instanceof PartLot) {
if ($type !== PartStockChangeType::MOVE) {
throw new \InvalidArgumentException('The move_to_target parameter can only be set if the type is "move"!');
@ -78,11 +85,12 @@ class PartStockChangedLogEntry extends AbstractLogEntry
* @param float $new_stock The new stock of the lot.
* @param float $new_total_part_instock The new total instock of the part.
* @param string $comment The comment associated with the change.
* @param \DateTimeInterface|null $action_timestamp The optional timestamp, where the action happened. Useful if the action happened in the past, and the log entry is created afterwards.
* @return self
*/
public static function add(PartLot $lot, float $old_stock, float $new_stock, float $new_total_part_instock, string $comment): self
public static function add(PartLot $lot, float $old_stock, float $new_stock, float $new_total_part_instock, string $comment, ?\DateTimeInterface $action_timestamp = null): self
{
return new self(PartStockChangeType::ADD, $lot, $old_stock, $new_stock, $new_total_part_instock, $comment);
return new self(PartStockChangeType::ADD, $lot, $old_stock, $new_stock, $new_total_part_instock, $comment, action_timestamp: $action_timestamp);
}
/**
@ -92,11 +100,12 @@ class PartStockChangedLogEntry extends AbstractLogEntry
* @param float $new_stock The new stock of the lot.
* @param float $new_total_part_instock The new total instock of the part.
* @param string $comment The comment associated with the change.
* @param \DateTimeInterface|null $action_timestamp The optional timestamp, where the action happened. Useful if the action happened in the past, and the log entry is created afterwards.
* @return self
*/
public static function withdraw(PartLot $lot, float $old_stock, float $new_stock, float $new_total_part_instock, string $comment): self
public static function withdraw(PartLot $lot, float $old_stock, float $new_stock, float $new_total_part_instock, string $comment, ?\DateTimeInterface $action_timestamp = null): self
{
return new self(PartStockChangeType::WITHDRAW, $lot, $old_stock, $new_stock, $new_total_part_instock, $comment);
return new self(PartStockChangeType::WITHDRAW, $lot, $old_stock, $new_stock, $new_total_part_instock, $comment, action_timestamp: $action_timestamp);
}
/**
@ -107,10 +116,12 @@ class PartStockChangedLogEntry extends AbstractLogEntry
* @param float $new_total_part_instock The new total instock of the part.
* @param string $comment The comment associated with the change.
* @param PartLot $move_to_target The target lot.
* @param \DateTimeInterface|null $action_timestamp The optional timestamp, where the action happened. Useful if the action happened in the past, and the log entry is created afterwards.
* @return self
*/
public static function move(PartLot $lot, float $old_stock, float $new_stock, float $new_total_part_instock, string $comment, PartLot $move_to_target): self
public static function move(PartLot $lot, float $old_stock, float $new_stock, float $new_total_part_instock, string $comment, PartLot $move_to_target, ?\DateTimeInterface $action_timestamp = null): self
{
return new self(PartStockChangeType::MOVE, $lot, $old_stock, $new_stock, $new_total_part_instock, $comment, $move_to_target);
return new self(PartStockChangeType::MOVE, $lot, $old_stock, $new_stock, $new_total_part_instock, $comment, $move_to_target, action_timestamp: $action_timestamp);
}
/**
@ -169,4 +180,18 @@ class PartStockChangedLogEntry extends AbstractLogEntry
{
return $this->extra['m'] ?? null;
}
/**
* Returns the timestamp when this action was performed and not when the log entry was created.
* This is useful if the action happened in the past, and the log entry is created afterwards.
* If the timestamp is not set, null is returned.
* @return \DateTimeInterface|null
*/
public function getActionTimestamp(): ?\DateTimeInterface
{
if (!empty($this->extra['a'])) {
return \DateTimeImmutable::createFromFormat(\DateTimeInterface::ATOM, $this->extra['a']);
}
return null;
}
}

View file

@ -193,6 +193,10 @@ class LogEntryExtraFormatter
htmlspecialchars($this->elementTypeNameGenerator->getLocalizedTypeLabel(PartLot::class))
.' ' . $context->getMoveToTargetID();
}
if ($context->getActionTimestamp()) {
$formatter = new \IntlDateFormatter($this->translator->getLocale(), \IntlDateFormatter::SHORT, \IntlDateFormatter::SHORT);
$array['log.part_stock_changed.timestamp'] = $formatter->format($context->getActionTimestamp());
}
}
return $array;

View file

@ -53,9 +53,10 @@ final class PartLotWithdrawAddHelper
* @param PartLot $partLot The partLot from which the instock should be taken (which value should be decreased)
* @param float $amount The amount of parts that should be taken from the part lot
* @param string|null $comment The optional comment describing the reason for the withdrawal
* @param \DateTimeInterface|null $action_timestamp The optional timestamp, where the action happened. Useful if the action happened in the past, and the log entry is created afterwards.
* @return PartLot The modified part lot
*/
public function withdraw(PartLot $partLot, float $amount, ?string $comment = null): PartLot
public function withdraw(PartLot $partLot, float $amount, ?string $comment = null, ?\DateTimeInterface $action_timestamp = null): PartLot
{
//Ensure that amount is positive
if ($amount <= 0) {
@ -83,7 +84,7 @@ final class PartLotWithdrawAddHelper
$oldAmount = $partLot->getAmount();
$partLot->setAmount($oldAmount - $amount);
$event = PartStockChangedLogEntry::withdraw($partLot, $oldAmount, $partLot->getAmount(), $part->getAmountSum() , $comment);
$event = PartStockChangedLogEntry::withdraw($partLot, $oldAmount, $partLot->getAmount(), $part->getAmountSum() , $comment, $action_timestamp);
$this->eventLogger->log($event);
//Apply the comment also to global events, so it gets associated with the elementChanged log entry
@ -100,9 +101,10 @@ final class PartLotWithdrawAddHelper
* @param PartLot $partLot The partLot from which the instock should be taken (which value should be decreased)
* @param float $amount The amount of parts that should be taken from the part lot
* @param string|null $comment The optional comment describing the reason for the withdrawal
* @param \DateTimeInterface|null $action_timestamp The optional timestamp, where the action happened. Useful if the action happened in the past, and the log entry is created afterwards.
* @return PartLot The modified part lot
*/
public function add(PartLot $partLot, float $amount, ?string $comment = null): PartLot
public function add(PartLot $partLot, float $amount, ?string $comment = null, ?\DateTimeInterface $action_timestamp = null): PartLot
{
if ($amount <= 0) {
throw new \InvalidArgumentException('Amount must be positive');
@ -123,7 +125,7 @@ final class PartLotWithdrawAddHelper
$oldAmount = $partLot->getAmount();
$partLot->setAmount($oldAmount + $amount);
$event = PartStockChangedLogEntry::add($partLot, $oldAmount, $partLot->getAmount(), $part->getAmountSum() , $comment);
$event = PartStockChangedLogEntry::add($partLot, $oldAmount, $partLot->getAmount(), $part->getAmountSum() , $comment, $action_timestamp);
$this->eventLogger->log($event);
//Apply the comment also to global events, so it gets associated with the elementChanged log entry
@ -141,8 +143,9 @@ final class PartLotWithdrawAddHelper
* @param PartLot $target The part lot to which the parts should be added
* @param float $amount The amount of parts that should be moved
* @param string|null $comment A comment describing the reason for the move
* @param \DateTimeInterface|null $action_timestamp The optional timestamp, where the action happened. Useful if the action happened in the past, and the log entry is created afterwards.
*/
public function move(PartLot $origin, PartLot $target, float $amount, ?string $comment = null): void
public function move(PartLot $origin, PartLot $target, float $amount, ?string $comment = null, ?\DateTimeInterface $action_timestamp = null): void
{
if ($amount <= 0) {
throw new \InvalidArgumentException('Amount must be positive');
@ -177,7 +180,7 @@ final class PartLotWithdrawAddHelper
//And add it to the target
$target->setAmount($target->getAmount() + $amount);
$event = PartStockChangedLogEntry::move($origin, $oldOriginAmount, $origin->getAmount(), $part->getAmountSum() , $comment, $target);
$event = PartStockChangedLogEntry::move($origin, $oldOriginAmount, $origin->getAmount(), $part->getAmountSum() , $comment, $target, $action_timestamp);
$this->eventLogger->log($event);
//Apply the comment also to global events, so it gets associated with the elementChanged log entry