Skip to content

Commit

Permalink
feature #246 [Invoice] Add payment status (AdamKasp, Tomanhez, arti0090)
Browse files Browse the repository at this point in the history
This PR was merged into the 1.0-dev branch.

Discussion
----------

<img width="339" alt="Screenshot 2021-08-11 at 13 41 23" src="https://user-images.githubusercontent.com/29897151/129024005-ab5f60bc-484f-486d-9ad4-c1cce0ea3fb5.png">
<img width="484" alt="Screenshot 2021-08-11 at 13 41 28" src="https://user-images.githubusercontent.com/29897151/129024011-5c7fe998-60d0-4d0f-81c3-300ab9fe5da5.png">


Commits
-------

61a8f40 flag paid on invoice show and pdf
839da78 change bool to state on payment on invoce state
7c572b4 Add fixes for tests and implementations
b503fff fix static analysis and doc
  • Loading branch information
GSadee authored Aug 18, 2021
2 parents 79ee0a8 + b503fff commit b41e34f
Show file tree
Hide file tree
Showing 18 changed files with 207 additions and 0 deletions.
61 changes: 61 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,64 @@
### UPGRADE FROM 0.17.0 TO 0.18.0

Now on invoice admin and shop user can check if related order was paid before invoice generated.

1. `src/Entity/Invoice.php` model has new field (`paymentState`), and updated constructor arguments:

```dif
public function __construct(
string $id,
string $number,
OrderInterface $order,
\DateTimeInterface $issuedAt,
BillingDataInterface $billingData,
string $currencyCode,
string $localeCode,
int $total,
Collection $lineItems,
Collection $taxItems,
ChannelInterface $channel,
+ string $paymentState,
InvoiceShopBillingDataInterface $shopBillingData
) {
$this->id = $id;
$this->number = $number;
$this->order = $order;
$this->issuedAt = clone $issuedAt;
$this->billingData = $billingData;
$this->currencyCode = $currencyCode;
$this->localeCode = $localeCode;
$this->total = $total;
$this->lineItems = $lineItems;
$this->taxItems = $taxItems;
$this->channel = $channel;
+ $this->paymentState = $paymentState;
$this->shopBillingData = $shopBillingData;
```

1. New field on `src/Entity/Invoice.php` implies a database update

1. Method `createForData` from `src/Factory/InvoiceFactory.php` service was updated:

```dif
public function createForData(
string $id,
string $number,
OrderInterface $order,
\DateTimeInterface $issuedAt,
BillingDataInterface $billingData,
string $currencyCode,
string $localeCode,
int $total,
Collection $lineItems,
Collection $taxItems,
ChannelInterface $channel,
+ string $paymentState,
InvoiceShopBillingDataInterface $shopBillingData = null
): InvoiceInterface {
// ...
}
```

### UPGRADE FROM 0.16.1 TO 0.17.0

Invoices are now saved on the server during their generation (by default, when the order is paid).
Expand Down
32 changes: 32 additions & 0 deletions features/managing_invoices/seeing_payment_state_on_invoice.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
@managing_invoices
Feature: Seeing payment state of an invoice
In order to see if customer paid order
As an Administrator
I want to be able to view payment state of invoice

Background:
Given the store operates on a single channel in "United States"
And the store has "VAT" tax rate of 10% for "Clothes" within the "US" zone
And the store has a product "Angel T-Shirt" priced at "$60.00"
And it belongs to "Clothes" tax category
And the store has "UPS" shipping method with "$10.00" fee
And the store allows paying with "Cash on Delivery"
And the store allows paying with "Quick Payments"
And I am logged in as an administrator
And I set shop billing data for channel "United States" as "Ragnarok", "1100110011", "Pacific Coast Hwy", "90806" "Los Angeles", "United States"
And there is a customer "[email protected]" that placed an order "#00000666"
And the customer bought 2 "Angel T-Shirt" products
And the customer "Lucifer Morningstar" addressed it to "Seaside Fwy", "90802" "Los Angeles" in the "United States"
And for the billing address of "Mazikeen Lilim" in the "Pacific Coast Hwy", "90806" "Los Angeles", "United States"
And the customer chose "UPS" shipping method with "Cash on Delivery" payment

@ui
Scenario: Seeing unpaid invoice details
When I view the summary of the invoice for order "#00000666"
Then it should be unpaid

@ui
Scenario: Seeing invoice details after payment made
Given this order is already paid
When I view the summary of the invoice for order "#00000666"
Then it should be unpaid
1 change: 1 addition & 0 deletions spec/Entity/InvoiceSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ function let(
new ArrayCollection([$lineItem->getWrappedObject()]),
new ArrayCollection([$taxItem->getWrappedObject()]),
$channel,
InvoiceInterface::PAYMENT_STATE_COMPLETED,
$shopBillingData
);
}
Expand Down
2 changes: 2 additions & 0 deletions spec/Factory/InvoiceFactorySpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ function it_creates_an_invoice_for_given_data(
new ArrayCollection(),
new ArrayCollection(),
$channel,
InvoiceInterface::PAYMENT_STATE_COMPLETED,
$invoiceShopBillingData
)->shouldReturnAnInstanceOf(InvoiceInterface::class);
}
Expand All @@ -72,6 +73,7 @@ function it_allows_for_nullable_shop_billing_data(
new ArrayCollection(),
new ArrayCollection(),
$channel,
InvoiceInterface::PAYMENT_STATE_COMPLETED,
null
)->shouldReturnAnInstanceOf(InvoiceInterface::class);
}
Expand Down
3 changes: 3 additions & 0 deletions spec/Generator/InvoiceGeneratorSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Sylius\Component\Core\Model\AddressInterface;
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Payment\Model\PaymentInterface;
use Sylius\InvoicingPlugin\Converter\BillingDataConverterInterface;
use Sylius\InvoicingPlugin\Converter\InvoiceShopBillingDataConverterInterface;
use Sylius\InvoicingPlugin\Converter\LineItemsConverterInterface;
Expand Down Expand Up @@ -89,6 +90,7 @@ function it_generates_an_invoice_for_a_given_order(
$order->getLocaleCode()->willReturn('en_US');
$order->getTotal()->willReturn(10300);
$order->getChannel()->willReturn($channel);
$order->getPaymentState()->willReturn(PaymentInterface::STATE_COMPLETED);
$order->getBillingAddress()->willReturn($billingAddress);

$billingDataConverter->convert($billingAddress)->willReturn($billingData);
Expand All @@ -110,6 +112,7 @@ function it_generates_an_invoice_for_a_given_order(
new ArrayCollection([$unitLineItem->getWrappedObject(), $shippingLineItem->getWrappedObject()]),
new ArrayCollection([$taxItem->getWrappedObject()]),
$channel,
InvoiceInterface::PAYMENT_STATE_COMPLETED,
$invoiceShopBillingData
)->willReturn($invoice);

Expand Down
10 changes: 10 additions & 0 deletions src/Entity/Invoice.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ class Invoice implements InvoiceInterface
/** @var ChannelInterface */
protected $channel;

/** @var string */
protected $paymentState;

/** @var InvoiceShopBillingDataInterface */
protected $shopBillingData;

Expand All @@ -68,6 +71,7 @@ public function __construct(
Collection $lineItems,
Collection $taxItems,
ChannelInterface $channel,
string $paymentState,
InvoiceShopBillingDataInterface $shopBillingData
) {
$this->id = $id;
Expand All @@ -81,6 +85,7 @@ public function __construct(
$this->lineItems = $lineItems;
$this->taxItems = $taxItems;
$this->channel = $channel;
$this->paymentState = $paymentState;
$this->shopBillingData = $shopBillingData;

/** @var LineItemInterface $lineItem */
Expand Down Expand Up @@ -187,4 +192,9 @@ public function shopBillingData(): InvoiceShopBillingDataInterface
{
return $this->shopBillingData;
}

public function paymentState(): string
{
return $this->paymentState;
}
}
6 changes: 6 additions & 0 deletions src/Entity/InvoiceInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@

interface InvoiceInterface extends ResourceInterface
{
public const PAYMENT_STATE_COMPLETED = 'completed';

public const PAYMENT_STATE_PENDING = 'pending';

public function id(): string;

public function number(): string;
Expand Down Expand Up @@ -50,4 +54,6 @@ public function taxesTotal(): int;
public function channel(): ChannelInterface;

public function shopBillingData(): InvoiceShopBillingDataInterface;

public function paymentState(): string;
}
2 changes: 2 additions & 0 deletions src/Factory/InvoiceFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public function createForData(
Collection $lineItems,
Collection $taxItems,
ChannelInterface $channel,
string $paymentState,
InvoiceShopBillingDataInterface $shopBillingData = null
): InvoiceInterface {
return new Invoice(
Expand All @@ -50,6 +51,7 @@ public function createForData(
$lineItems,
$taxItems,
$channel,
$paymentState,
$shopBillingData ?? new InvoiceShopBillingData()
);
}
Expand Down
1 change: 1 addition & 0 deletions src/Factory/InvoiceFactoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public function createForData(
Collection $lineItems,
Collection $taxItems,
ChannelInterface $channel,
string $paymentState,
InvoiceShopBillingDataInterface $shopBillingData = null
): InvoiceInterface;
}
5 changes: 5 additions & 0 deletions src/Generator/InvoiceGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Sylius\Component\Core\Model\AddressInterface;
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Payment\Model\PaymentInterface;
use Sylius\InvoicingPlugin\Converter\BillingDataConverterInterface;
use Sylius\InvoicingPlugin\Converter\InvoiceShopBillingDataConverterInterface;
use Sylius\InvoicingPlugin\Converter\LineItemsConverterInterface;
Expand Down Expand Up @@ -78,6 +79,9 @@ public function generateForOrder(OrderInterface $order, \DateTimeInterface $date
/** @var ChannelInterface $channel */
$channel = $order->getChannel();

$paymentState = $order->getPaymentState() === PaymentInterface::STATE_COMPLETED ?
InvoiceInterface::PAYMENT_STATE_COMPLETED : InvoiceInterface::PAYMENT_STATE_PENDING;

return $this->invoiceFactory->createForData(
$this->uuidInvoiceIdentifierGenerator->generate(),
$this->sequentialInvoiceNumberGenerator->generate(),
Expand All @@ -93,6 +97,7 @@ public function generateForOrder(OrderInterface $order, \DateTimeInterface $date
)),
$this->taxItemsConverter->convert($order),
$channel,
$paymentState,
$this->invoiceShopBillingDataConverter->convert($channel)
);
}
Expand Down
40 changes: 40 additions & 0 deletions src/Migrations/Version20210812125029.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Sylius\InvoicingPlugin\Migrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20210812125029 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add payment_state to invoice';
}

public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE sylius_invoicing_plugin_invoice ADD payment_state VARCHAR(255) NOT NULL');
}

public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE sylius_invoicing_plugin_invoice DROP payment_state');
}
}
1 change: 1 addition & 0 deletions src/Resources/config/doctrine/Invoice.orm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<field name="currencyCode" column="currency_code" length="3" />
<field name="localeCode" column="locale_code" />
<field name="total" column="total" type="integer" />
<field name="paymentState" column="payment_state" />

<one-to-one field="billingData" target-entity="Sylius\InvoicingPlugin\Entity\BillingDataInterface">
<cascade>
Expand Down
4 changes: 4 additions & 0 deletions src/Resources/translations/messages.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ sylius_invoicing_plugin:
net_value: 'Net value'
no: 'No.'
order_number: 'Order number'
payment:
paid: 'Paid'
yes: 'Yes'
no: 'No'
resend_invoice: 'Resend'
seller: 'Seller'
tax_amount: 'Tax amount'
Expand Down
11 changes: 11 additions & 0 deletions src/Resources/views/Invoice/Download/pdf.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,17 @@
<td>{{ '%0.2f'|format(invoice.total/100) }}</td>
<td>{{ invoice.currencyCode }}</td>
</tr>
<tr class="paid">
<td colspan="5"></td>
<td colspan="2" class="bold">{{ 'sylius_invoicing_plugin.ui.payment.paid'|trans }}:</td>
<td>
{% if invoice.paymentState() is constant('Sylius\\InvoicingPlugin\\Entity\\InvoiceInterface::PAYMENT_STATE_COMPLETED') %}
{{ 'sylius_invoicing_plugin.ui.payment.yes'|trans }}
{% else %}
{{ 'sylius_invoicing_plugin.ui.payment.no'|trans }}
{% endif %}
</td>
</tr>

{% if invoice.taxItems.count() > 0 %}
<tr>
Expand Down
12 changes: 12 additions & 0 deletions src/Resources/views/Invoice/show.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -146,5 +146,17 @@
</tfoot>
</table>
</div>
<div class="right floated left aligned four wide column">
<div class="ui segment" {{ sylius_test_html_attribute('invoice-is-paid') }}>
<strong>{{ 'sylius_invoicing_plugin.ui.payment.paid'|trans }}: </strong>
<span>
{% if invoice.paymentState() is constant('Sylius\\InvoicingPlugin\\Entity\\InvoiceInterface::PAYMENT_STATE_COMPLETED') %}
{{ 'sylius_invoicing_plugin.ui.payment.yes'|trans }}
{% else %}
{{ 'sylius_invoicing_plugin.ui.payment.no'|trans }}
{% endif %}
</span>
</div>
</div>
</div>
{% endblock %}
8 changes: 8 additions & 0 deletions tests/Behat/Context/Ui/Admin/ManagingInvoicesContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -332,4 +332,12 @@ public function itShouldHaveItemsWithUnitPriceNetValueTaxTotalAndTotalInCurrency
): void {
Assert::true($this->showPage->hasItemWithData($name, $unitPrice, $quantity, $taxTotal, $total, $currencyCode, $netValue));
}

/**
* @Then it should be unpaid
*/
public function itShouldBeUnpaid(): void
{
Assert::false($this->showPage->isPaid());
}
}
6 changes: 6 additions & 0 deletions tests/Behat/Page/Admin/Invoice/ShowPage.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,11 @@ public function goBack(): void
$this->getElement('back')->click();
}

public function isPaid(): bool
{
return str_contains($this->getElement('paid')->getHtml(), 'Yes');
}

protected function getDefinedElements(): array
{
return array_merge(parent::getDefinedElements(), [
Expand All @@ -170,6 +175,7 @@ protected function getDefinedElements(): array
'invoice_total' => '[data-test-invoice-total]',
'invoice_total_currency_code' => '[data-test-invoice-total-currency-code]',
'issued_at' => '#invoice-issued-at',
'paid' => '[data-test-invoice-is-paid]',
'shop_billing_data' => '#shop-billing-data',
'table' => '.table',
]);
Expand Down
2 changes: 2 additions & 0 deletions tests/Behat/Page/Admin/Invoice/ShowPageInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,6 @@ public function download(): void;
public function resend(): void;

public function goBack(): void;

public function isPaid(): bool;
}

0 comments on commit b41e34f

Please sign in to comment.