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

        $shipment = $invoice->getShipment();

        // Remove unexpected good lines
        /** @var Invoice\InvoiceLineInterface $line */
        foreach ($invoice->getLinesByType(Document\DocumentLineTypes::TYPE_GOOD) as $line) {
            foreach ($shipment->getItems() as $shipmentItem) {
                if ($line->getSaleItem() === $shipmentItem->getSaleItem()) {
                    continue 2; // Shipment item found -> next invoice line
                }
            }

            // Shipment item not found -> remove line
            $invoice->removeLine($line);

            $this->persistenceHelper->remove($line, false);

            $changed = true;
        }

        $sale = $invoice->getSale();

        // Remove unexpected discount lines
        foreach ($invoice->getLinesByType(Document\DocumentLineTypes::TYPE_DISCOUNT) as $line) {
            foreach ($sale->getAdjustments(Common\AdjustmentTypes::TYPE_DISCOUNT) as $saleAdjustment) {
                if ($line->getSaleAdjustment() === $saleAdjustment) {
                    continue 2; // Sale adjustment found -> next invoice line
                }
            }

            // Sale adjustment not found -> remove line
            $invoice->removeLine($line);

            $this->persistenceHelper->remove($line, false);

            $changed = true;
        }

        // Remove unexpected shipment lines
        if (null === $sale->getShipmentMethod()) {
            foreach ($invoice->getLinesByType(Document\DocumentLineTypes::TYPE_SHIPMENT) as $line) {
                $invoice->removeLine($line);

                $this->persistenceHelper->remove($line, false);

                $changed = true;
            }
        }

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

        $shipment = $invoice->getShipment();

        // Remove unexpected good lines
        /** @var Invoice\InvoiceLineInterface $line */
        foreach ($invoice->getLinesByType(Document\DocumentLineTypes::TYPE_GOOD) as $line) {
            foreach ($shipment->getItems() as $shipmentItem) {
                if ($line->getSaleItem() === $shipmentItem->getSaleItem()) {
                    continue 2; // Shipment item found -> next invoice line
                }
            }

            // Shipment item not found -> remove line
            $invoice->removeLine($line);

            $this->persistenceHelper->remove($line, false);

            $changed = true;
        }

        $sale = $invoice->getSale();

        // Remove unexpected discount lines
        foreach ($invoice->getLinesByType(Document\DocumentLineTypes::TYPE_DISCOUNT) as $line) {
            foreach ($sale->getAdjustments(Common\AdjustmentTypes::TYPE_DISCOUNT) as $saleAdjustment) {
                if ($line->getSaleAdjustment() === $saleAdjustment) {
                    continue 2; // Sale adjustment found -> next invoice line
                }
            }

            // Sale adjustment not found -> remove line
            $invoice->removeLine($line);

            $this->persistenceHelper->remove($line, false);

            $changed = true;
        }

        // Remove unexpected shipment lines
        if (null === $sale->getShipmentMethod()) {
            foreach ($invoice->getLinesByType(Document\DocumentLineTypes::TYPE_SHIPMENT) as $line) {
                $invoice->removeLine($line);

                $this->persistenceHelper->remove($line, false);

                $changed = true;
            }
        }

        return $changed;
    }
Removes the invoice unexpected lines regarding to his associated shipment.

@param Invoice\InvoiceInterface $invoice

@return bool Whether the invoice has been changed