protected function buildItem(SaleItemInterface $saleItem, ShipmentInterface $shipment)
    {
        // If compound with only private children
        if ($saleItem->isCompound()) {
            // Resolve available and expected quantities by building children
            $available = $expected = null;
            foreach ($saleItem->getChildren() as $childSaleItem) {
                if (null !== $child = $this->buildItem($childSaleItem, $shipment)) {
                    $saleItemQty = $childSaleItem->getQuantity();

                    $e = $child->getExpected() / $saleItemQty;
                    if (null === $expected || $expected > $e) {
                        $expected = $e;
                    }

                    $a = $child->getAvailable() / $saleItemQty;
                    if (null === $available || $available > $a) {
                        $available = $a;
                    }
                }
            }

            // If any children is expected
            if (0 < $expected) {
                return $this->findOrCreateItem($shipment, $saleItem, $expected, $available);
            }

            return null;
        }

        $item = null;

        // Skip compound with only public children
        if (!($saleItem->isCompound() && !$saleItem->hasPrivateChildren())) {
            $expected = $shipment->isReturn()
                ? $this->calculator->calculateReturnableQuantity($saleItem, $shipment)
                : $this->calculator->calculateShippableQuantity($saleItem, $shipment);

            if (0 < $expected) {
                $item = $this->findOrCreateItem($shipment, $saleItem, $expected);
            }
        }

        // Build children
        if ($saleItem->hasChildren()) {
            foreach ($saleItem->getChildren() as $childSaleItem) {
                $this->buildItem($childSaleItem, $shipment);
            }
        }

        return $item;
    }