diff --git a/.gitignore b/.gitignore index 012f2eeb..830c0a03 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/var/ /vendor/ /node_modules/ /composer.lock diff --git a/CHANGELOG-3.0.md b/CHANGELOG-3.0.md new file mode 100644 index 00000000..63865d52 --- /dev/null +++ b/CHANGELOG-3.0.md @@ -0,0 +1,5 @@ +# CHANGELOG + +### v3.0.0 (2025-10-20) + +- [#394](https://github.com/Sylius/InvoicingPlugin/pull/394) Make Invoice entity mutable ([@tomkalon](https://github.com/tomkalon)) diff --git a/src/Entity/Invoice.php b/src/Entity/Invoice.php index 969e6bd8..a8d760d1 100644 --- a/src/Entity/Invoice.php +++ b/src/Entity/Invoice.php @@ -60,52 +60,98 @@ public function id(): string return $this->id; } - public function number(): string + public function getNumber(): string { return $this->number; } - public function order(): OrderInterface + public function setNumber(string $number): void + { + $this->number = $number; + } + + public function getOrder(): OrderInterface { return $this->order; } - public function issuedAt(): \DateTimeInterface + public function setOrder(OrderInterface $order): void + { + $this->order = $order; + } + + public function getIssuedAt(): \DateTimeInterface { return clone $this->issuedAt; } - public function billingData(): BillingDataInterface + public function getBillingData(): BillingDataInterface { return $this->billingData; } - public function currencyCode(): string + public function setBillingData(BillingDataInterface $billingData): void + { + $this->billingData = $billingData; + } + + public function getCurrencyCode(): string { return $this->currencyCode; } - public function localeCode(): string + public function setCurrencyCode(string $currencyCode): void + { + $this->currencyCode = $currencyCode; + } + + public function getLocaleCode(): string { return $this->localeCode; } - public function total(): int + public function setLocaleCode(string $localeCode): void + { + $this->localeCode = $localeCode; + } + + public function getTotal(): int { return $this->total; } - public function lineItems(): Collection + public function setTotal(int $total): void + { + $this->total = $total; + } + + public function getLineItems(): Collection { return $this->lineItems; } - public function taxItems(): Collection + public function addLineItem(LineItemInterface $lineItem): void + { + if (!$this->lineItems->contains($lineItem)) { + $this->lineItems->add($lineItem); + $lineItem->setInvoice($this); + } + } + + public function getTaxItems(): Collection { return $this->taxItems; } - public function subtotal(): int + public function addTaxItem(TaxItemInterface $taxItem): void + { + if (!$this->taxItems->contains($taxItem)) { + $this->taxItems->add($taxItem); + $taxItem->setInvoice($this); + } + } + + public function getSubtotal(): int { $subtotal = 0; @@ -117,7 +163,7 @@ public function subtotal(): int return $subtotal; } - public function taxesTotal(): int + public function getTaxesTotal(): int { $taxesTotal = 0; @@ -129,18 +175,33 @@ public function taxesTotal(): int return $taxesTotal; } - public function channel(): ChannelInterface + public function getChannel(): ChannelInterface { return $this->channel; } - public function shopBillingData(): InvoiceShopBillingDataInterface + public function setChannel(ChannelInterface $channel): void + { + $this->channel = $channel; + } + + public function getShopBillingData(): InvoiceShopBillingDataInterface { return $this->shopBillingData; } - public function paymentState(): string + public function setShopBillingData(InvoiceShopBillingDataInterface $shopBillingData): void + { + $this->shopBillingData = $shopBillingData; + } + + public function getPaymentState(): string { return $this->paymentState; } + + public function setPaymentState(string $paymentState): void + { + $this->paymentState = $paymentState; + } } diff --git a/src/Entity/InvoiceInterface.php b/src/Entity/InvoiceInterface.php index 0ddede9a..23ef5156 100644 --- a/src/Entity/InvoiceInterface.php +++ b/src/Entity/InvoiceInterface.php @@ -26,31 +26,53 @@ interface InvoiceInterface extends ResourceInterface public function id(): string; - public function number(): string; + public function getNumber(): string; - public function order(): OrderInterface; + public function setNumber(string $number): void; - public function issuedAt(): \DateTimeInterface; + public function getOrder(): OrderInterface; - public function billingData(): BillingDataInterface; + public function setOrder(OrderInterface $order): void; - public function currencyCode(): string; + public function getIssuedAt(): \DateTimeInterface; - public function localeCode(): string; + public function getBillingData(): BillingDataInterface; - public function total(): int; + public function setBillingData(BillingDataInterface $billingData): void; - public function lineItems(): Collection; + public function getCurrencyCode(): string; - public function taxItems(): Collection; + public function setCurrencyCode(string $currencyCode): void; - public function subtotal(): int; + public function getLocaleCode(): string; - public function taxesTotal(): int; + public function setLocaleCode(string $localeCode): void; - public function channel(): ChannelInterface; + public function getTotal(): int; - public function shopBillingData(): InvoiceShopBillingDataInterface; + public function setTotal(int $total): void; - public function paymentState(): string; + public function getLineItems(): Collection; + + public function addLineItem(LineItemInterface $lineItem): void; + + public function getTaxItems(): Collection; + + public function addTaxItem(TaxItemInterface $taxItem): void; + + public function getSubtotal(): int; + + public function getTaxesTotal(): int; + + public function getChannel(): ChannelInterface; + + public function setChannel(ChannelInterface $channel): void; + + public function getShopBillingData(): InvoiceShopBillingDataInterface; + + public function setShopBillingData(InvoiceShopBillingDataInterface $shopBillingData): void; + + public function getPaymentState(): string; + + public function setPaymentState(string $paymentState): void; } diff --git a/src/Generator/InvoiceFileNameGenerator.php b/src/Generator/InvoiceFileNameGenerator.php index 5ab62abf..6c93acca 100644 --- a/src/Generator/InvoiceFileNameGenerator.php +++ b/src/Generator/InvoiceFileNameGenerator.php @@ -21,6 +21,6 @@ final class InvoiceFileNameGenerator implements InvoiceFileNameGeneratorInterfac public function generateForPdf(InvoiceInterface $invoice): string { - return str_replace('/', '_', $invoice->number()) . self::PDF_FILE_EXTENSION; + return str_replace('/', '_', $invoice->getNumber()) . self::PDF_FILE_EXTENSION; } } diff --git a/src/Generator/InvoicePdfFileGenerator.php b/src/Generator/InvoicePdfFileGenerator.php index b211caef..1490e4f3 100644 --- a/src/Generator/InvoicePdfFileGenerator.php +++ b/src/Generator/InvoicePdfFileGenerator.php @@ -36,7 +36,7 @@ public function generate(InvoiceInterface $invoice): InvoicePdf $this->template, [ 'invoice' => $invoice, - 'channel' => $invoice->channel(), + 'channel' => $invoice->getChannel(), 'invoiceLogoPath' => $this->fileLocator->locate($this->invoiceLogoPath), ], ); diff --git a/src/Security/Voter/InvoiceVoter.php b/src/Security/Voter/InvoiceVoter.php index 11722137..8089f7f5 100644 --- a/src/Security/Voter/InvoiceVoter.php +++ b/src/Security/Voter/InvoiceVoter.php @@ -73,7 +73,7 @@ private function canAccess(UserInterface $user, InvoiceInterface $invoice): bool Assert::isInstanceOf($customer, CustomerInterface::class); - return null !== $this->orderRepository->findOneByNumberAndCustomer($invoice->order()->getNumber(), $customer); + return null !== $this->orderRepository->findOneByNumberAndCustomer($invoice->getOrder()->getNumber(), $customer); } return false; diff --git a/src/Ui/Action/Admin/ResendInvoiceAction.php b/src/Ui/Action/Admin/ResendInvoiceAction.php index 6e29ece1..2eb34ab2 100644 --- a/src/Ui/Action/Admin/ResendInvoiceAction.php +++ b/src/Ui/Action/Admin/ResendInvoiceAction.php @@ -44,7 +44,7 @@ public function __invoke(string $id): Response Assert::notNull($invoice); /** @var OrderInterface|null $order */ - $order = $this->orderRepository->findOneBy(['number' => $invoice->order()->getNumber()]); + $order = $this->orderRepository->findOneBy(['number' => $invoice->getOrder()->getNumber()]); Assert::notNull($order); /** @var CustomerInterface|null $customer */ diff --git a/tests/Behat/Context/Application/ManagingInvoicesContext.php b/tests/Behat/Context/Application/ManagingInvoicesContext.php index 765d8128..bea83900 100644 --- a/tests/Behat/Context/Application/ManagingInvoicesContext.php +++ b/tests/Behat/Context/Application/ManagingInvoicesContext.php @@ -30,7 +30,7 @@ public function theInvoiceForOrderShouldBeSavedOnTheServer(OrderInterface $order { /** @var InvoiceInterface $invoice */ $invoice = $this->invoiceRepository->findOneByOrder($order); - $filePath = $this->invoicesSavePath.'/'.str_replace('/', '_', $invoice->number()).'.pdf'; + $filePath = $this->invoicesSavePath.'/'.str_replace('/', '_', $invoice->getNumber()).'.pdf'; Assert::true(file_exists($filePath)); } diff --git a/tests/Behat/Context/Ui/Shop/CustomerBrowsingInvoicesContext.php b/tests/Behat/Context/Ui/Shop/CustomerBrowsingInvoicesContext.php index 1f2dafdd..523d78b5 100644 --- a/tests/Behat/Context/Ui/Shop/CustomerBrowsingInvoicesContext.php +++ b/tests/Behat/Context/Ui/Shop/CustomerBrowsingInvoicesContext.php @@ -53,7 +53,7 @@ public function tryToDownloadInvoiceForOrder(string $orderNumber): void /** @var InvoiceInterface $invoice */ $invoice = $this->invoiceRepository->findByOrderNumber($orderNumber)[0]; - $this->downloadInvoicePage->tryToOpen(['id' => $invoice->id()]); + $this->downloadInvoicePage->tryToOpen(['id' => $invoice->getId()]); } /** @@ -64,7 +64,7 @@ public function invoiceForOrderShouldNotBeDownloaded(string $orderNumber): void /** @var InvoiceInterface $invoice */ $invoice = $this->invoiceRepository->findByOrderNumber($orderNumber)[0]; - Assert::false($this->downloadInvoicePage->isOpen(['id' => $invoice->id()])); + Assert::false($this->downloadInvoicePage->isOpen(['id' => $invoice->getId()])); } /** diff --git a/tests/Unit/Entity/InvoiceTest.php b/tests/Unit/Entity/InvoiceTest.php index be210558..f7b3e53a 100644 --- a/tests/Unit/Entity/InvoiceTest.php +++ b/tests/Unit/Entity/InvoiceTest.php @@ -97,15 +97,15 @@ public function it_implements_resource_interface(): void public function it_has_data(): void { self::assertSame('7903c83a-4c5e-4bcf-81d8-9dc304c6a353', $this->invoice->id()); - self::assertSame('2019/01/000000001', $this->invoice->number()); - self::assertSame($this->order, $this->invoice->order()); - self::assertSame($this->billingData, $this->invoice->billingData()); - self::assertSame('USD', $this->invoice->currencyCode()); - self::assertSame('en_US', $this->invoice->localeCode()); - self::assertSame(10300, $this->invoice->total()); - self::assertEquals(new ArrayCollection([$this->lineItem]), $this->invoice->lineItems()); - $this->assertEquals(new ArrayCollection([$this->taxItem]), $this->invoice->taxItems()); - $this->assertSame($this->channel, $this->invoice->channel()); - $this->assertSame($this->shopBillingData, $this->invoice->shopBillingData()); + self::assertSame('2019/01/000000001', $this->invoice->getNumber()); + self::assertSame($this->order, $this->invoice->getOrder()); + self::assertSame($this->billingData, $this->invoice->getBillingData()); + self::assertSame('USD', $this->invoice->getCurrencyCode()); + self::assertSame('en_US', $this->invoice->getLocaleCode()); + self::assertSame(10300, $this->invoice->getTotal()); + self::assertEquals(new ArrayCollection([$this->lineItem]), $this->invoice->getLineItems()); + $this->assertEquals(new ArrayCollection([$this->taxItem]), $this->invoice->getTaxItems()); + $this->assertSame($this->channel, $this->invoice->getChannel()); + $this->assertSame($this->shopBillingData, $this->invoice->getShopBillingData()); } } diff --git a/tests/Unit/Generator/InvoiceFileNameGeneratorTest.php b/tests/Unit/Generator/InvoiceFileNameGeneratorTest.php index c2697c3a..45696dae 100644 --- a/tests/Unit/Generator/InvoiceFileNameGeneratorTest.php +++ b/tests/Unit/Generator/InvoiceFileNameGeneratorTest.php @@ -39,7 +39,7 @@ public function it_implements_invoice_file_name_generator_interface(): void public function it_generates_invoice_file_name_based_on_its_number(): void { $invoice = $this->createMock(InvoiceInterface::class); - $invoice->method('number')->willReturn('2020/01/02/000333'); + $invoice->method('getNumber')->willReturn('2020/01/02/000333'); $result = $this->generator->generateForPdf($invoice); diff --git a/tests/Unit/Generator/InvoicePdfFileGeneratorTest.php b/tests/Unit/Generator/InvoicePdfFileGeneratorTest.php index 26e830d4..5a1204c8 100644 --- a/tests/Unit/Generator/InvoicePdfFileGeneratorTest.php +++ b/tests/Unit/Generator/InvoicePdfFileGeneratorTest.php @@ -69,7 +69,7 @@ public function it_creates_invoice_pdf_with_generated_content_and_filename_basin ->with($invoice) ->willReturn('2015_05_00004444.pdf'); - $invoice->method('channel')->willReturn($channel); + $invoice->method('getChannel')->willReturn($channel); $this->fileLocator ->expects(self::once()) diff --git a/tests/Unit/Security/InvoiceVoterTest.php b/tests/Unit/Security/InvoiceVoterTest.php index 82db68db..ed5b5b4c 100644 --- a/tests/Unit/Security/InvoiceVoterTest.php +++ b/tests/Unit/Security/InvoiceVoterTest.php @@ -102,7 +102,7 @@ public function it_does_not_allow_accessing_an_invoice_if_user_has_not_placed_th $customer = $this->createMock(CustomerInterface::class); $order = $this->createMock(OrderInterface::class); - $invoice->method('order')->willReturn($order); + $invoice->method('getOrder')->willReturn($order); $order->method('getNumber')->willReturn('1337'); $token->method('getUser')->willReturn($shopUser); $shopUser->method('getCustomer')->willReturn($customer); @@ -124,7 +124,7 @@ public function it_allows_accessing_an_invoice_if_user_has_placed_the_order_rela $customer = $this->createMock(CustomerInterface::class); $order = $this->createMock(OrderInterface::class); - $invoice->method('order')->willReturn($order); + $invoice->method('getOrder')->willReturn($order); $order->method('getNumber')->willReturn('1337'); $token->method('getUser')->willReturn($shopUser); $shopUser->method('getCustomer')->willReturn($customer);