Stock/Updater/StockUnitUpdater.php
private function handleOverflow(StockUnitInterface $stockUnit)
    {
        // TODO Abort if stock unit is new ...

        // We don't care about shipped quantities because of the 'ordered > received > shipped' rule.
        $overflow = $stockUnit->getSoldQuantity()
            - $stockUnit->getOrderedQuantity()
            - $stockUnit->getAdjustedQuantity();

        // Abort if no overflow
        if (0 == $overflow) {
            return false;
        }

        $subject = $stockUnit->getSubject();

        // Positive case : too much sold quantity
        if (0 < $overflow) {
            // Try to move sold overflow to other pending/ready stock units
            // TODO prefer ready units with enough quantity
            $targetStockUnits = $this->unitResolver->findPendingOrReady($subject);
            foreach ($targetStockUnits as $targetStockUnit) {
                // Skip the stock unit we're applying
                if ($targetStockUnit === $stockUnit) {
                    continue;
                }

                $overflow -= $this->assignmentDispatcher->moveAssignments($stockUnit, $targetStockUnit, $overflow);

                if (0 == $overflow) {
                    return true; // We're done dispatching sold quantity
                }
            }

            // Try to move sold overflow to a linkable stock unit
            if (null !== $targetStockUnit = $this->unitResolver->findLinkable($subject)) {
                if ($targetStockUnit !== $stockUnit) {
                    $overflow -= $this->assignmentDispatcher->moveAssignments($stockUnit, $targetStockUnit, $overflow);
                }
            }

            // Move sold overflow to a new stock unit
            if (0 < $overflow) {
                $newStockUnit = $this->unitResolver->createBySubject($subject, $stockUnit);

                // Pre persist stock unit
                $this->persistenceHelper->persistAndRecompute($newStockUnit, false);

                $overflow -= $this->assignmentDispatcher->moveAssignments($stockUnit, $newStockUnit, $overflow);
            }

            if (0 != $overflow) {
                throw new StockLogicException("Failed to fix stock unit sold quantity overflow.");
            }

            return true;
        }

        // Negative case : not enough sold quantity
        if (null !== $sourceUnit = $this->unitResolver->findLinkable($subject)) {
            if ($sourceUnit === $stockUnit) {
                return false;
            }
            if (0 != $this->assignmentDispatcher->moveAssignments($sourceUnit, $stockUnit, -$overflow, SORT_ASC)) {
                return true;
            }
        }

        return false;
    }
private function handleOverflow(StockUnitInterface $stockUnit)
    {
        // TODO Abort if stock unit is new ...

        // We don't care about shipped quantities because of the 'ordered > received > shipped' rule.
        $overflow = $stockUnit->getSoldQuantity()
            - $stockUnit->getOrderedQuantity()
            - $stockUnit->getAdjustedQuantity();

        // Abort if no overflow
        if (0 == $overflow) {
            return false;
        }

        $subject = $stockUnit->getSubject();

        // Positive case : too much sold quantity
        if (0 < $overflow) {
            // Try to move sold overflow to other pending/ready stock units
            // TODO prefer ready units with enough quantity
            $targetStockUnits = $this->unitResolver->findPendingOrReady($subject);
            foreach ($targetStockUnits as $targetStockUnit) {
                // Skip the stock unit we're applying
                if ($targetStockUnit === $stockUnit) {
                    continue;
                }

                $overflow -= $this->assignmentDispatcher->moveAssignments($stockUnit, $targetStockUnit, $overflow);

                if (0 == $overflow) {
                    return true; // We're done dispatching sold quantity
                }
            }

            // Try to move sold overflow to a linkable stock unit
            if (null !== $targetStockUnit = $this->unitResolver->findLinkable($subject)) {
                if ($targetStockUnit !== $stockUnit) {
                    $overflow -= $this->assignmentDispatcher->moveAssignments($stockUnit, $targetStockUnit, $overflow);
                }
            }

            // Move sold overflow to a new stock unit
            if (0 < $overflow) {
                $newStockUnit = $this->unitResolver->createBySubject($subject, $stockUnit);

                // Pre persist stock unit
                $this->persistenceHelper->persistAndRecompute($newStockUnit, false);

                $overflow -= $this->assignmentDispatcher->moveAssignments($stockUnit, $newStockUnit, $overflow);
            }

            if (0 != $overflow) {
                throw new StockLogicException("Failed to fix stock unit sold quantity overflow.");
            }

            return true;
        }

        // Negative case : not enough sold quantity
        if (null !== $sourceUnit = $this->unitResolver->findLinkable($subject)) {
            if ($sourceUnit === $stockUnit) {
                return false;
            }
            if (0 != $this->assignmentDispatcher->moveAssignments($sourceUnit, $stockUnit, -$overflow, SORT_ASC)) {
                return true;
            }
        }

        return false;
    }
private function handleOverflow ( StockUnitInterface $ stockUnit ) { // TODO Abort if stock unit is new ... // We don't care about shipped quantities because of the 'ordered > received > shipped' rule. $ overflow = $ stockUnit -> getSoldQuantity ( ) - $ stockUnit -> getOrderedQuantity ( ) - $ stockUnit -> getAdjustedQuantity ( ) ; // Abort if no overflow if ( 0 == $ overflow ) { return false ; } $ subject = $ stockUnit -> getSubject ( ) ; // Positive case : too much sold quantity if ( 0 < $ overflow ) { // Try to move sold overflow to other pending/ready stock units // TODO prefer ready units with enough quantity $ targetStockUnits = $ this -> unitResolver -> findPendingOrReady ( $ subject ) ; foreach ( $ targetStockUnits as $ targetStockUnit ) { // Skip the stock unit we're applying if ( $ targetStockUnit === $ stockUnit ) { continue ; } $ overflow -= $ this -> assignmentDispatcher -> moveAssignments ( $ stockUnit , $ targetStockUnit , $ overflow ) ; if ( 0 == $ overflow ) { return true ; // We're done dispatching sold quantity } } // Try to move sold overflow to a linkable stock unit if ( null !== $ targetStockUnit = $ this -> unitResolver -> findLinkable ( $ subject ) ) { if ( $ targetStockUnit !== $ stockUnit ) { $ overflow -= $ this -> assignmentDispatcher -> moveAssignments ( $ stockUnit , $ targetStockUnit , $ overflow ) ; } } // Move sold overflow to a new stock unit if ( 0 < $ overflow ) { $ newStockUnit = $ this -> unitResolver -> createBySubject ( $ subject , $ stockUnit ) ; // Pre persist stock unit $ this -> persistenceHelper -> persistAndRecompute ( $ newStockUnit , false ) ; $ overflow -= $ this -> assignmentDispatcher -> moveAssignments ( $ stockUnit , $ newStockUnit , $ overflow ) ; } if ( 0 != $ overflow ) { throw new StockLogicException ( "Failed to fix stock unit sold quantity overflow." ) ; } return true ; } // Negative case : not enough sold quantity if ( null !== $ sourceUnit = $ this -> unitResolver -> findLinkable ( $ subject ) ) { if ( $ sourceUnit === $ stockUnit ) { return false ; } if ( 0 != $ this -> assignmentDispatcher -> moveAssignments ( $ sourceUnit , $ stockUnit , - $ overflow , SORT_ASC ) ) { return true ; } } return false ; }
Checks stock unit overflow (sold > ordered + adjusted) and fixes assignments if needed.

@param StockUnitInterface $stockUnit

@return bool Whether assignment(s) has been moved.

@throws StockLogicException
Checks stock unit overflow ( sold > ordered + adjusted ) and fixes assignments if needed .