Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend Invoice resource #140

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 68 additions & 8 deletions src/ApiConnectors/InvoiceApiConnector.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace PhpTwinfield\ApiConnectors;

use PhpTwinfield\Customer;
use PhpTwinfield\DomDocuments\InvoicesDocument;
use PhpTwinfield\Exception;
use PhpTwinfield\Invoice;
Expand All @@ -10,6 +11,7 @@
use PhpTwinfield\Request as Request;
use PhpTwinfield\Response\MappedResponseCollection;
use PhpTwinfield\Response\Response;
use PhpTwinfield\Services\FinderService;
use Webmozart\Assert\Assert;

/**
Expand All @@ -25,7 +27,7 @@
class InvoiceApiConnector extends BaseApiConnector
{
/**
* Requires a specific invoice based off the passed in code, invoiceNumber and optionally the office.
* Requires a specific Invoice based off the passed in code, invoiceNumber and optionally the office.
*
* @param string $code
* @param string $invoiceNumber
Expand All @@ -35,7 +37,7 @@ class InvoiceApiConnector extends BaseApiConnector
*/
public function get(string $code, string $invoiceNumber, Office $office)
{
// Make a request to read a single invoice. Set the required values
// Make a request to read a single Invoice. Set the required values
$request_invoice = new Request\Read\Invoice();
$request_invoice
->setCode($code)
Expand All @@ -57,12 +59,8 @@ public function get(string $code, string $invoiceNumber, Office $office)
*/
public function send(Invoice $invoice): Invoice
{
$invoiceResponses = $this->sendAll([$invoice]);

Assert::count($invoiceResponses, 1);

foreach ($invoiceResponses as $invoiceResponse) {
return $invoiceResponse->unwrap();
foreach($this->sendAll([$invoice]) as $each) {
return $each->unwrap();
}
}

Expand Down Expand Up @@ -93,4 +91,66 @@ public function sendAll(array $invoices): MappedResponseCollection
return InvoiceMapper::map($response);
});
}

/**
* List all sales invoices.
*
* @param string $pattern The search pattern. May contain wildcards * and ?
* @param int $field The search field determines which field or fields will be searched. The available fields
* depends on the finder type. Passing a value outside the specified values will cause an
* error.
* @param int $firstRow First row to return, useful for paging
* @param int $maxRows Maximum number of rows to return, useful for paging
* @param array $options The Finder options. Passing an unsupported name or value causes an error. It's possible
* to add multiple options. An option name may be used once, specifying an option multiple
* times will cause an error.
*
* @return Invoice[] The sales invoices found.
*/
public function listAll(
string $pattern = '*',
int $field = 0,
int $firstRow = 1,
int $maxRows = 100,
array $options = []
): array {
$optionsArrayOfString = array('ArrayOfString' => array());

foreach ($options as $key => $value) {
$optionsArrayOfString['ArrayOfString'][] = array($key, $value);
}

$response = $this->getFinderService()->searchFinder(FinderService::TYPE_LIST_OF_AVAILABLE_INVOICES, $pattern, $field, $firstRow, $maxRows, $optionsArrayOfString);

if ($response->data->TotalRows == 0) {
return [];
}

$invoices = [];

foreach ($response->data->Items->ArrayOfString as $invoiceArray) {
$invoice = new Invoice();
$customer = new Customer();

if (isset($invoiceArray->string[0])) {
$invoice->setInvoiceNumber($invoiceArray->string[0]);
$invoice->setInvoiceAmount($invoiceArray->string[1]);
$customer->setCode($invoiceArray->string[2]);
$invoice->setCustomerName($invoiceArray->string[3]);
$invoice->setDebitCredit($invoiceArray->string[4]);
} else {
$invoice->setInvoiceNumber($invoiceArray[0]);
$invoice->setInvoiceAmount($invoiceArray[1]);
$customer->setCode($invoiceArray[2]);
$invoice->setCustomerName($invoiceArray[3]);
$invoice->setDebitCredit($invoiceArray[4]);
}

$invoice->setCustomer($customer);

$invoices[] = $invoice;
}

return $invoices;
}
}
19 changes: 10 additions & 9 deletions src/DomDocuments/InvoicesDocument.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ final protected function getRootTagName(): string
/**
* Turns a passed Invoice class into the required markup for interacting
* with Twinfield.
*
*
* This method doesn't return anything, instead just adds the invoice
* to this DOMDocument instance for submission usage.
*
*
* @access public
* @param Invoice $invoice
* @return void | [Adds to this instance]
Expand All @@ -40,7 +40,7 @@ public function addInvoice(Invoice $invoice)
// Makes a child header element
$headerElement = $this->createElement('header');
$invoiceElement->appendChild($headerElement);

// Set customer element
$customer = $invoice->getCustomer();

Expand All @@ -66,20 +66,20 @@ public function addInvoice(Invoice $invoice)
'headertext' => 'getHeaderText',
'footertext' => 'getFooterText'
);

// Go through each element and use the assigned method
foreach ($headerTags as $tag => $method) {

$value = $this->getValueFromCallback([$invoice, $method]);

if(null !== $value) {
// Make text node for method value
$node = $this->createTextNode($value);

// Make the actual element and assign the node
$element = $this->createElement($tag);
$element->appendChild($node);

// Add the full element
$headerElement->appendChild($element);
}
Expand All @@ -88,14 +88,15 @@ public function addInvoice(Invoice $invoice)
// Add orders
$linesElement = $this->createElement('lines');
$invoiceElement->appendChild($linesElement);

// Elements and their associated methods for lines
$lineTags = array(
'quantity' => 'getQuantity',
'article' => 'getArticle',
'subarticle' => 'getSubArticle',
'description' => 'getDescription',
'unitspriceexcl' => 'getUnitsPriceExcl',
'unitspriceinc' => 'getUnitsPriceInc',
'units' => 'getUnits',
'vatcode' => 'getVatCode',
'freetext1' => 'getFreeText1',
Expand All @@ -116,7 +117,7 @@ public function addInvoice(Invoice $invoice)

// Go through each element and use the assigned method
foreach ($lineTags as $tag => $method) {

// Make text node for method value
$node = $this->createTextNode($this->getValueFromCallback([$line, $method]));

Expand Down
71 changes: 68 additions & 3 deletions src/Invoice.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,22 @@
*
* @see https://c3.twinfield.com/webservices/documentation/#/ApiReference/SalesInvoices
* @todo Add documentation and typehints to all properties.
* @todo Add support for VatLines.
*/
class Invoice
class Invoice extends BaseObject
{
use PeriodField;
use DueDateField;
use OfficeField;

private $customer;
private $customerName;
private $debitCredit;
private $invoiceAmount;
private $invoiceType;
private $invoiceNumber;
private $status;
private $currency;
private $invoiceDate;
private $dueDate;
private $performanceDate;
private $paymentMethod;
private $bank;
Expand Down Expand Up @@ -69,6 +71,25 @@ public function getLines(): array
return $this->lines;
}

/**
* @var InvoiceVatLine[]
*/
private $vatlines = [];

public function addVatLine(InvoiceVatLine $vatline)
{
$this->vatlines[] = $vatline;
return $this;
}

/**
* @return InvoiceVatLine[]
*/
public function getVatLines(): array
{
return $this->vatlines;
}

public function getCustomer(): Customer
{
return $this->customer;
Expand All @@ -80,6 +101,28 @@ public function setCustomer(Customer $customer)
return $this;
}

public function getCustomerName()
{
return $this->customerName;
}

public function setCustomerName($customerName)
{
$this->customerName = $customerName;
return $this;
}

public function getDebitCredit()
iranl marked this conversation as resolved.
Show resolved Hide resolved
{
return $this->debitCredit;
}

public function setDebitCredit($debitCredit)
{
$this->debitCredit = $debitCredit;
return $this;
}

public function setTotals(InvoiceTotals $totals)
{
$this->totals = $totals;
Expand All @@ -91,6 +134,17 @@ public function getTotals(): InvoiceTotals
return $this->totals;
}

public function getInvoiceAmount()
iranl marked this conversation as resolved.
Show resolved Hide resolved
{
return $this->invoiceAmount;
}

public function setInvoiceAmount($invoiceAmount)
{
$this->invoiceAmount = $invoiceAmount;
return $this;
}

public function getInvoiceType()
{
return $this->invoiceType;
Expand Down Expand Up @@ -146,6 +200,17 @@ public function setInvoiceDate($invoiceDate)
return $this;
}

public function getDueDate()
iranl marked this conversation as resolved.
Show resolved Hide resolved
{
return $this->dueDate;
}

public function setDueDate($dueDate)
{
$this->dueDate = $dueDate;
return $this;
}

public function getPerformanceDate()
{
return $this->performanceDate;
Expand Down
55 changes: 55 additions & 0 deletions src/InvoiceVatLine.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php
namespace PhpTwinfield;

use PhpTwinfield\Enums\PerformanceType;
use PhpTwinfield\Transactions\TransactionLineFields\VatCodeField;

/**
* @see https://c3.twinfield.com/webservices/documentation/#/ApiReference/SalesInvoices
* @todo Add documentation and typehints to all properties.
*/
class InvoiceVatLine
{
use VatCodeField;

private $vatValue;
private $performanceDate;

/**
* @var PerformanceType|null Mandatory in case of an ICT VAT code.
*/
private $performanceType;

public function getVatValue()
iranl marked this conversation as resolved.
Show resolved Hide resolved
{
return $this->vatValue;
}

public function setVatValue($vatValue)
{
$this->vatValue = $vatValue;
return $this;
}

public function getPerformanceDate()
iranl marked this conversation as resolved.
Show resolved Hide resolved
{
return $this->performanceDate;
}

public function setPerformanceDate($performanceDate)
iranl marked this conversation as resolved.
Show resolved Hide resolved
{
$this->performanceDate = $performanceDate;
return $this;
}

public function getPerformanceType(): ?PerformanceType
{
return $this->performanceType;
}

public function setPerformanceType(?PerformanceType $performanceType): self
{
$this->performanceType = $performanceType;
return $this;
}
}
Loading