Shipment/Builder/InvoiceSynchronizer.php
private function feedShipmentInvoice(Invoice\InvoiceInterface $invoice)
    {
        $changed = false;

        $shipment = $invoice->getShipment();

        $calculator = $this->invoiceBuilder->getInvoiceCalculator();

        // Add expected good lines
        /** @var Invoice\InvoiceLineInterface $line */
        foreach ($shipment->getItems() as $shipmentItem) {
            $saleItem = $shipmentItem->getSaleItem();

            $max = $shipment->isReturn()
                ? $calculator->calculateCreditableQuantity($saleItem)
                : $calculator->calculateInvoiceableQuantity($saleItem);

            if (0 < $quantity = min($max, $shipmentItem->getQuantity())) {
                $line = $this->invoiceBuilder->findOrCreateGoodLine($invoice, $saleItem, $max);
                if ($line->getQuantity() !== $quantity) {
                    $line->setQuantity($quantity);
                    $changed = true;
                }
            } /*else {
                // TODO find and remove line ?
                $invoice->removeLine($line);
                $changed = true;
            }*/
        }

        if ($invoice->hasLineByType(Document\DocumentLineTypes::TYPE_GOOD)) {
            // Add expected discount lines
            $sale = $invoice->getSale();
            foreach ($sale->getAdjustments(Common\AdjustmentTypes::TYPE_DISCOUNT) as $saleAdjustment) {
                foreach ($invoice->getLinesByType(Document\DocumentLineTypes::TYPE_DISCOUNT) as $line) {
                    if ($saleAdjustment === $line->getSaleAdjustment()) {
                        continue 2; // Invoice line found -> next sale adjustment
                    }
                }

                // Invoice line not found -> create it
                $this->invoiceBuilder->buildDiscountLine($saleAdjustment, $invoice);

                $changed = true;
            }

            // Add expected shipment line
            if (null !== $sale->getShipmentMethod() && !$this->isShipmentAmountInvoiced($invoice)) {
                $this->invoiceBuilder->buildShipmentLine($invoice);
            }
        }

        return $changed;
    }
private function feedShipmentInvoice(Invoice\InvoiceInterface $invoice)
    {
        $changed = false;

        $shipment = $invoice->getShipment();

        $calculator = $this->invoiceBuilder->getInvoiceCalculator();

        // Add expected good lines
        /** @var Invoice\InvoiceLineInterface $line */
        foreach ($shipment->getItems() as $shipmentItem) {
            $saleItem = $shipmentItem->getSaleItem();

            $max = $shipment->isReturn()
                ? $calculator->calculateCreditableQuantity($saleItem)
                : $calculator->calculateInvoiceableQuantity($saleItem);

            if (0 < $quantity = min($max, $shipmentItem->getQuantity())) {
                $line = $this->invoiceBuilder->findOrCreateGoodLine($invoice, $saleItem, $max);
                if ($line->getQuantity() !== $quantity) {
                    $line->setQuantity($quantity);
                    $changed = true;
                }
            } /*else {
                // TODO find and remove line ?
                $invoice->removeLine($line);
                $changed = true;
            }*/
        }

        if ($invoice->hasLineByType(Document\DocumentLineTypes::TYPE_GOOD)) {
            // Add expected discount lines
            $sale = $invoice->getSale();
            foreach ($sale->getAdjustments(Common\AdjustmentTypes::TYPE_DISCOUNT) as $saleAdjustment) {
                foreach ($invoice->getLinesByType(Document\DocumentLineTypes::TYPE_DISCOUNT) as $line) {
                    if ($saleAdjustment === $line->getSaleAdjustment()) {
                        continue 2; // Invoice line found -> next sale adjustment
                    }
                }

                // Invoice line not found -> create it
                $this->invoiceBuilder->buildDiscountLine($saleAdjustment, $invoice);

                $changed = true;
            }

            // Add expected shipment line
            if (null !== $sale->getShipmentMethod() && !$this->isShipmentAmountInvoiced($invoice)) {
                $this->invoiceBuilder->buildShipmentLine($invoice);
            }
        }

        return $changed;
    }
Creates invoice expected lines regarding to his associated shipment.

@param Invoice\InvoiceInterface $invoice

@return bool Whether the invoice has been changed