diff --git a/src/ApiConnectors/BankTransactionApiConnector.php b/src/ApiConnectors/BankTransactionApiConnector.php deleted file mode 100644 index 3a704632..00000000 --- a/src/ApiConnectors/BankTransactionApiConnector.php +++ /dev/null @@ -1,66 +0,0 @@ -sendAll([$bankTransaction]); - - Assert::count($bankTransactionResponses, 1); - - foreach ($bankTransactionResponses as $bankTransactionResponse) { - return $bankTransactionResponse->unwrap(); - } - } - - /** - * @param BankTransaction[] $bankTransactions - * @return MappedResponseCollection|IndividualMappedResponse[] - * @throws Exception - */ - public function sendAll(array $bankTransactions): MappedResponseCollection - { - Assert::allIsInstanceOf($bankTransactions, BankTransaction::class); - - /* - * We can have multiple documents sent, so we need to collect all documents. - */ - /** @var Response[] $responses */ - $responses = []; - - foreach ($this->getProcessXmlService()->chunk($bankTransactions) as $chunk) { - - $bankTransactionDocument = new BankTransactionDocument(); - - foreach ($chunk as $bankTransaction) { - $bankTransactionDocument->addBankTransaction($bankTransaction); - } - - $responses[] = $this->sendXmlDocument($bankTransactionDocument); - } - - return $this->getProcessXmlService()->mapAll($responses, "transaction", function(Response $subresponse): BankTransaction { - return BankTransactionMapper::map($subresponse->getResponseDocument()); - }); - } -} diff --git a/src/BankTransaction.php b/src/BankTransaction.php index 068f7773..ff2085d3 100644 --- a/src/BankTransaction.php +++ b/src/BankTransaction.php @@ -6,111 +6,57 @@ use Money\Money; use PhpTwinfield\Enums\DebitCredit; use PhpTwinfield\Enums\LineType; -use PhpTwinfield\Transactions\Transaction; -use PhpTwinfield\Transactions\TransactionFields\AutoBalanceVatField; -use PhpTwinfield\Transactions\TransactionFields\CodeNumberOfficeFields; -use PhpTwinfield\Transactions\TransactionFields\DestinyField; -use PhpTwinfield\Transactions\TransactionFields\FreeTextFields; -use PhpTwinfield\Transactions\TransactionFields\LinesField; -use PhpTwinfield\Transactions\TransactionFields\RaiseWarningField; use PhpTwinfield\Transactions\TransactionFields\StartAndCloseValueFields; use PhpTwinfield\Transactions\TransactionFields\StatementNumberField; -use PhpTwinfield\Transactions\TransactionLineFields\DateField; -use PhpTwinfield\Transactions\TransactionLineFields\PeriodField; -use Webmozart\Assert\Assert; +use PhpTwinfield\Transactions\TransactionLine; /** * @link https://c3.twinfield.com/webservices/documentation/#/ApiReference/Transactions/BankTransactions */ -class BankTransaction implements Transaction +class BankTransaction extends BaseTransaction { - use DestinyField; - use AutoBalanceVatField; - use PeriodField; - use CodeNumberOfficeFields; - use DateField; use StatementNumberField; - use RaiseWarningField; - - use StartAndCloseValueFields; - - use FreeTextFields; - - use LinesField { - addLine as protected traitAddLine; + use StartAndCloseValueFields { + setCurrency as protected traitSetCurrency; } - /** - * The date/time on which the transaction was created. - * Read-only attribute. - * - * @var \DateTimeImmutable - */ - private $inputDate; - - /** - * The bank transaction origin. - * Read-only attribute. - * - * @var mixed - */ - private $origin; - - /** - * The date/time on which the bank transaction was modified the last time. - * Read-only attribute. - * - * @var \DateTimeInterface - */ - private $modificationDate; - public function __construct() { - $this->currency = new Currency("EUR"); - $this->startvalue = new Money(0, $this->getCurrency()); + $this->startvalue = new Money(0, new Currency('EUR')); } + /** + * @return string + */ public function getLineClassName(): string { - return Transactions\BankTransactionLine\Base::class; + return BankTransactionLine::class; } /** - * The bank transaction origin. - * Read-only attribute. + * Set the currency. Can only be done when the start value is still 0. * - * @return mixed + * @param Currency $currency + * @return $this */ - public function getOrigin() - { - return $this->origin; - } - - public function getInputDate(): \DateTimeInterface + public function setCurrency(?Currency $currency): BaseTransaction { - return $this->inputDate; + $this->traitSetCurrency($currency); + return $this; } - public function addLine(Transactions\BankTransactionLine\Base $line): void + /** + * @param TransactionLine $line + * @return $this + */ + public function addLine(TransactionLine $line) { - Assert::notEmpty($this->startvalue); - - /* - * Max is 500 lines. - */ - Assert::lessThan($this->getLineCount(), 500); - - /* - * Calls the addLine() method on the LinesField trait. Uses an alias in the `use` statement at top of this - * class, because parent::addLine() doesn't work for traits. - */ - $this->traitAddLine($line); + parent::addLine($line); + /** @var BankTransactionLine $line */ if (!$line->getLineType()->equals(LineType::TOTAL())) { /* * Don't add total lines to the closevalue, they are summaries of the details and vat lines. - * - * @link https://github.com/php-twinfield/twinfield/issues/39 */ if ($line->getDebitCredit()->equals(DebitCredit::CREDIT())) { $this->closevalue = $this->getClosevalue()->add($line->getValue()); @@ -118,5 +64,7 @@ public function addLine(Transactions\BankTransactionLine\Base $line): void $this->closevalue = $this->getClosevalue()->subtract($line->getValue()); } } + + return $this; } } diff --git a/src/BankTransactionLine.php b/src/BankTransactionLine.php new file mode 100644 index 00000000..24aa0c91 --- /dev/null +++ b/src/BankTransactionLine.php @@ -0,0 +1,264 @@ +transaction, 'Attempting to set a transaction while the transaction is already set.'); + Assert::isInstanceOf($object, BankTransaction::class); + $this->transaction = $object; + } + + /** + * References the transaction this line belongs too. + * + * @return BankTransaction + */ + public function getTransaction(): BankTransaction + { + return $this->transaction; + } + + /** + * If line type = total the bank balance account. + * + * If line type = detail the customer or supplier balance account or profit and loss account. + * + * If line type = vat the VAT balance account. When an empty dim1 is entered, by default the general ledger account + * will be taken as entered at the VAT code in Twinfield. + * + * @param string|null $dim1 + * @return $this + */ + public function setDim1(?string $dim1): BaseTransactionLine + { + return parent::setDim1($dim1); + } + + /** + * If line type = total empty. + * + * If line type = detail the customer or supplier or the cost center or empty. + * + * If line type = vat empty. + * + * @param string|null $dim2 + * @return $this + * @throws Exception + */ + public function setDim2(?string $dim2): BaseTransactionLine + { + if ($dim2 !== null && + ($this->getLineType()->equals(LineType::VAT()) || $this->getLineType()->equals(LineType::TOTAL()))) { + throw Exception::invalidDimensionForLineType(2, $this); + } + + return parent::setDim2($dim2); + } + + /** + * If line type = total empty. + * + * If line type = detail the project or asset or empty. + * + * If line type = vat empty. + * + * @param string|null $dim3 + * @return $this + * @throws Exception + */ + public function setDim3(?string $dim3): BaseTransactionLine + { + if ($dim3 !== null && + ($this->getLineType()->equals(LineType::VAT()) || $this->getLineType()->equals(LineType::TOTAL()))) { + throw Exception::invalidDimensionForLineType(3, $this); + } + + return parent::setDim3($dim3); + } + + /** + * If line type = total, based on the sum of the individual bank transaction lines. + * - In case of a bank addition debit. + * - In case of a bank withdrawal credit. + * + * If line type = detail + * - In case money is received credit. + * - In case money is paid debit. + * + * If line type = vat, based on the sum of the vat amounts of the individual bank transaction lines. + * - In case of a bank addition credit. + * - In case of a bank withdrawal debit. + * + * @param DebitCredit::DEBIT() $debitCredit + * @return $this + */ + public function setDebitCredit(DebitCredit $debitCredit): BaseTransactionLine + { + return parent::setDebitCredit($debitCredit); + } + + /** + * If line type = total amount including VAT. + * + * If line type = detail amount without VAT. + * + * If line type = vat VAT amount. + * + * @param Money $value + * @return $this + */ + public function setValue(Money $value): BaseTransactionLine + { + return parent::setValue($value); + } + + /** + * Payment status of the bank transaction. If line type total or vat always notmatchable. Read-only attribute. + * + * @param string|null $matchStatus + * @return $this + * @throws Exception + */ + public function setMatchStatus(?string $matchStatus): BaseTransactionLine + { + if ( + $matchStatus !== null && + in_array($this->getLineType(), [LineType::TOTAL(), LineType::VAT()]) && + $matchStatus != self::MATCHSTATUS_NOTMATCHABLE + ) { + throw Exception::invalidMatchStatusForLineType($matchStatus, $this); + } + + return parent::setMatchStatus($matchStatus); + } + + /** + * Only if line type is detail. The level of the matchable dimension. Read-only attribute. + * + * @param int|null $matchLevel + * @return $this + * @throws Exception + */ + public function setMatchLevel(?int $matchLevel): BaseTransactionLine + { + if ($matchLevel !== null && !$this->getLineType()->equals(LineType::DETAIL())) { + throw Exception::invalidFieldForLineType('matchLevel', $this); + } + + return parent::setMatchLevel($matchLevel); + } + + /** + * Only if line type is detail. The amount still owed in base currency. Read-only attribute. + * + * @param Money|null $baseValueOpen + * @return $this + * @throws Exception + */ + public function setBaseValueOpen(?Money $baseValueOpen): BaseTransactionLine + { + if ($baseValueOpen !== null && !$this->getLineType()->equals(LineType::DETAIL())) { + throw Exception::invalidFieldForLineType('baseValueOpen', $this); + } + + return parent::setBaseValueOpen($baseValueOpen); + } + + /** + * Only if line type is vat. Amount on which VAT was calculated in the currency of the sales transaction. + * + * @param Money|null $vatTurnover + * @return $this + * @throws Exception + */ + public function setVatTurnover(?Money $vatTurnover): BaseTransactionLine + { + if (!$this->getLineType()->equals(LineType::VAT())) { + throw Exception::invalidFieldForLineType('vatturnover', $this); + } + return parent::setVatTurnOver($vatTurnover); + } + + /** + * Only if line type is vat. Amount on which VAT was calculated in base currency. + * + * @param Money|null $vatBaseTurnover + * @return $this + * @throws Exception + */ + public function setVatBaseTurnover(?Money $vatBaseTurnover): BaseTransactionLine + { + if (!$this->getLineType()->equals(LineType::VAT())) { + throw Exception::invalidFieldForLineType('vatbaseturnover', $this); + } + return parent::setVatBaseTurnover($vatBaseTurnover); + } + + /** + * Only if line type is vat. Amount on which VAT was calculated in reporting currency. + * + * @param Money|null $vatRepTurnover + * @return $this + * @throws Exception + */ + public function setVatRepTurnover(?Money $vatRepTurnover): BaseTransactionLine + { + if (!$this->getLineType()->equals(LineType::VAT())) { + throw Exception::invalidFieldForLineType('vatrepturnover', $this); + } + return parent::setVatRepTurnover($vatRepTurnover); + } + + /** + * @param string|null $invoiceNumber + * @return $this + * @throws Exception + */ + public function setInvoiceNumber(?string $invoiceNumber) + { + if (!$this->getLineType()->equals(LineType::DETAIL())) { + throw Exception::invalidFieldForLineType('invoicenumber', $this); + } + + return $this->traitSetInvoiceNumber($invoiceNumber); + } + + /** + * Returns true if a positive amount in the TOTAL line means the amount is 'debit'. Examples of incoming transaction + * types are Sales Transactions, Electronic Bank Statements and Bank Transactions. + * + * Returns false if a positive amount in the TOTAL line means the amount is 'credit'. An example of an outgoing + * transaction type is a Purchase Transaction. + * + * @return bool + */ + protected function isIncomingTransactionType(): bool + { + return true; + } +} diff --git a/src/BaseTransaction.php b/src/BaseTransaction.php index bbdc4dc2..00db0a78 100644 --- a/src/BaseTransaction.php +++ b/src/BaseTransaction.php @@ -14,20 +14,20 @@ use PhpTwinfield\Transactions\TransactionLineFields\PeriodField; /** - * @todo $modificationDate The date/time on which the sales transaction was modified the last time. Read-only attribute. - * @todo $user The user who created the sales transaction. Read-only attribute. + * @todo $modificationDate The date/time on which the transaction was modified the last time. Read-only attribute. + * @todo $user The user who created the transaction. Read-only attribute. * @todo $inputDate The date/time on which the transaction was created. Read-only attribute. */ abstract class BaseTransaction extends BaseObject implements Transaction { - use DestinyField; use AutoBalanceVatField; use CodeNumberOfficeFields; - use PeriodField; + use DestinyField; use FreeTextFields; - use DateField; - use RaiseWarningField; use LinesField; + use RaiseWarningField; + use DateField; + use PeriodField; /** * @var Currency|null The currency. diff --git a/src/DomDocuments/BankTransactionDocument.php b/src/DomDocuments/BankTransactionDocument.php deleted file mode 100644 index 0c13d577..00000000 --- a/src/DomDocuments/BankTransactionDocument.php +++ /dev/null @@ -1,180 +0,0 @@ -createElement("transaction"); - - $transaction->appendChild(new \DOMAttr("destiny", $bankTransaction->getDestiny())); - - if ($bankTransaction->isAutoBalanceVat() !== null) { - $transaction->appendChild( - $this->createBooleanAttribute("autobalancevat", $bankTransaction->isAutoBalanceVat()) - ); - } - - if ($bankTransaction->getRaiseWarning() !== null) { - $transaction->appendChild( - $this->createBooleanAttribute("raisewarning", $bankTransaction->getRaiseWarning()) - ); - } - - $header = $this->createElement("header"); - - if ($bankTransaction->getCode() !== null) { - $header->appendChild($this->createNodeWithTextContent("code", $bankTransaction->getCode())); - } - - $header->appendChild($this->createNodeWithTextContent("office", $bankTransaction->getOffice())); - - if ($bankTransaction->getNumber() !== null) { - $header->appendChild($this->createNodeWithTextContent("number", $bankTransaction->getNumber())); - } - - if ($bankTransaction->getPeriod() !== null) { - $header->appendChild($this->createNodeWithTextContent("period", $bankTransaction->getPeriod())); - } - - if ($bankTransaction->getDate() !== null) { - $this->appendDateElement($header, "date", $bankTransaction->getDate()); - } - - if ($bankTransaction->getStatementnumber() !== null) { - $header->appendChild($this->createNodeWithTextContent("statementnumber", $bankTransaction->getStatementnumber())); - } - - $this->appendStartCloseValues($header, $bankTransaction); - - $this->appendFreeTextFields($header, $bankTransaction); - $transaction->appendChild($header); - - $lines = $this->createElement("lines"); - $transaction->appendChild($lines); - - foreach ($bankTransaction->getLines() as $line) { - $lines->appendChild($this->createTransactionLineElement($line)); - } - - $this->rootElement->appendChild($transaction); - } - - protected function createTransactionLineElement(BankTransactionLine\Base $line): \DOMElement - { - $transaction = $this->createElement("line"); - $transaction->appendChild(new \DOMAttr("type", $line->getLineType())); - - if ($line->getId() !== null) { - $transaction->appendChild(new \DOMAttr("id", $line->getId())); - } - - if ($line->getDim1() !== null) { - $transaction->appendChild($this->createNodeWithTextContent("dim1", $line->getDim1())); - } - - if ($line->getDim2() !== null) { - $transaction->appendChild($this->createNodeWithTextContent("dim2", $line->getDim2())); - } - - if ($line->getDim3() !== null) { - $transaction->appendChild($this->createNodeWithTextContent("dim3", $line->getDim3())); - } - - $this->appendValueValues($transaction, $line); - - if ($line->getInvoiceNumber() !== null) { - $transaction->appendChild($this->createNodeWithTextContent("invoicenumber", $line->getInvoiceNumber())); - } - - if ($line->getDescription()) { - $transaction->appendChild($this->createNodeWithTextContent("description", $line->getDescription())); - } - - if ($line instanceof BankTransactionLine\Total) { - if ($line->getVatTotal() !== null) { - $transaction->appendChild($this->createNodeWithTextContent("vattotal", Util::formatMoney($line->getVatTotal()))); - } - - if ($line->getVatBaseTotal() !== null) { - $transaction->appendChild($this->createNodeWithTextContent("vatbasetotal", Util::formatMoney($line->getVatBaseTotal()))); - } - - if ($line->getVatRepTotal() !== null) { - $transaction->appendChild($this->createNodeWithTextContent("vatreptotal", Util::formatMoney($line->getVatRepTotal()))); - } - } - - if ($line instanceof BankTransactionLine\Vat || $line instanceof BankTransactionLine\Detail) { - if ($line->getVatCode() !== null) { - $transaction->appendChild($this->createNodeWithTextContent("vatcode", $line->getVatCode())); - } - } - - if ($line instanceof BankTransactionLine\Detail) { - if ($line->getVatValue() !== null) { - $transaction->appendChild($this->createNodeWithTextContent("vatvalue", Util::formatMoney($line->getVatValue()))); - } - - if ($line->getVatBaseValue() !== null) { - $transaction->appendChild($this->createNodeWithTextContent("vatbasevalue", Util::formatMoney($line->getVatBaseValue()))); - } - - if ($line->getVatRepValue() !== null) { - $transaction->appendChild($this->createNodeWithTextContent("vatrepvalue", Util::formatMoney($line->getVatRepValue()))); - } - } - - if ($line instanceof BankTransactionLine\Vat) { - - if ($line->getVatTurnover() !== null) { - $transaction->appendChild($this->createNodeWithTextContent("vatturnover", Util::formatMoney($line->getVatTurnover()))); - } - if ($line->getVatBaseTurnover() !== null) { - $transaction->appendChild($this->createNodeWithTextContent("vatbaseturnover", Util::formatMoney($line->getVatBaseTurnover()))); - } - if ($line->getVatRepTurnover() !== null) { - $transaction->appendChild($this->createNodeWithTextContent("vatrepturnover", Util::formatMoney($line->getVatRepTurnover()))); - } - } - - if ($line instanceof BankTransactionLine\Detail || $line instanceof BankTransactionLine\Vat) { - $this->appendPerformanceTypeFields($transaction, $line); - } - - if ($line->getDestOffice() !== null) { - $transaction->appendChild($this->createNodeWithTextContent("destoffice", $line->getDestOffice())); - } - - if ($line->getFreeChar()) { - $transaction->appendChild($this->createNodeWithTextContent("freechar", $line->getFreeChar())); - } - - if ($line->getComment()) { - $transaction->appendChild($this->createNodeWithTextContent("comment", $line->getComment())); - } - - return $transaction; - } -} \ No newline at end of file diff --git a/src/DomDocuments/TransactionsDocument.php b/src/DomDocuments/TransactionsDocument.php index 2e0d9a9b..e7f019ea 100644 --- a/src/DomDocuments/TransactionsDocument.php +++ b/src/DomDocuments/TransactionsDocument.php @@ -2,6 +2,7 @@ namespace PhpTwinfield\DomDocuments; +use PhpTwinfield\BankTransaction; use PhpTwinfield\BaseTransaction; use PhpTwinfield\BaseTransactionLine; use PhpTwinfield\CashTransaction; @@ -106,7 +107,7 @@ public function addTransaction(BaseTransaction $transaction) $headerElement->appendChild($this->createNodeWithTextContent('statementnumber', $transaction->getStatementnumber())); } - if ($transaction instanceof CashTransaction) { + if ($transaction instanceof BankTransaction || $transaction instanceof CashTransaction) { $headerElement->appendChild($this->createNodeWithTextContent('startvalue', Util::formatMoney($transaction->getStartvalue()))); $headerElement->appendChild($this->createNodeWithTextContent('closevalue', Util::formatMoney($transaction->getClosevalue()))); } diff --git a/src/Mappers/BankTransactionMapper.php b/src/Mappers/BankTransactionMapper.php deleted file mode 100644 index d4b5f027..00000000 --- a/src/Mappers/BankTransactionMapper.php +++ /dev/null @@ -1,206 +0,0 @@ -documentElement; - - if (!empty($element->getAttribute("autobalancevat"))) { - $bankTransaction->setAutoBalanceVat(Util::parseBoolean($element->getAttribute("autobalancevat"))); - } - - if (!empty($element->getAttribute("raisewarning"))) { - $bankTransaction->setRaiseWarning(Util::parseBoolean($element->getAttribute("raisewarning"))); - } - - self::setFromTagValue($document, "code", [$bankTransaction, "setCode"]); - self::setFromTagValue($document, "office", [$bankTransaction, "setOffice"]); - self::setFromTagValue($document, "date", [$bankTransaction, "setDate"]); - self::setFromTagValue($document, "period", [$bankTransaction, "setPeriod"]); - self::setFromTagValue($document, "startvalue", [$bankTransaction, "setStartValue"]); - - self::setFromTagValue($document, "statementnumber", [$bankTransaction, "setStatementNumber"]); - self::setFromTagValue($document, "number", [$bankTransaction, "setNumber"]); - - /** @var \DOMElement $lineElement */ - foreach ($element->getElementsByTagName("line") as $lineElement) { - switch ($lineElement->getAttribute("type")) { - case LineType::TOTAL(): - $bankTransaction->addLine(self::createTotalBankTransactionLine($bankTransaction, $lineElement)); - break; - case LineType::DETAIL(): - $bankTransaction->addLine(self::createDetailBankTransactionLine($bankTransaction, $lineElement)); - break; - case LineType::VAT(): - $bankTransaction->addLine(self::createVatBankTransactionLine($bankTransaction, $lineElement)); - break; - } - } - - return $bankTransaction; - } - - private static function createTotalBankTransactionLine(BankTransaction $bankTransaction, \DOMElement $lineElement): Total - { - $line = new Total(); - self::setBankTransactionLineBaseFields($bankTransaction, $lineElement, $line); - - $line->setBankBalanceAccount(self::getField($lineElement, "dim1")); - - $vatTotal = self::getField($lineElement, "vattotal"); - if ($vatTotal) { - $line->setVatTotal(Util::parseMoney($vatTotal, $bankTransaction->getCurrency())); - } - $vatBaseTotal = self::getField($lineElement, "vatbasetotal"); - if ($vatBaseTotal) { - $line->setVatBaseTotal(Util::parseMoney($vatBaseTotal, $bankTransaction->getCurrency())); - } - $vatRepTotal = self::getField($lineElement, "vatreptotal"); - if ($vatRepTotal) { - $line->setVatRepTotal(Util::parseMoney($vatRepTotal, $bankTransaction->getCurrency())); - } - - return $line; - } - - private static function createDetailBankTransactionLine(BankTransaction $bankTransaction, \DOMElement $lineElement): Detail - { - $line = new Detail(); - self::setBankTransactionLineBaseFields($bankTransaction, $lineElement, $line); - self::setBankTransactionLinePerformanceFields($lineElement, $line); - - $line->setAccount(self::getField($lineElement, "dim1")); - - $customerOrSupplierOrCostCenter = self::getField($lineElement, "dim2"); - if ($customerOrSupplierOrCostCenter !== null) { - $line->setCustomerOrSupplierOrCostCenter($customerOrSupplierOrCostCenter); - } - $vatCode = self::getField($lineElement, "vatcode"); - if ($vatCode !== null) { - $line->setVatCode($vatCode); - } - $vatValue = self::getField($lineElement, "vatvalue"); - if ($vatValue) { - $line->setVatValue(Util::parseMoney($vatValue, $bankTransaction->getCurrency())); - } - $vatBaseValue = self::getField($lineElement, "vatbasevalue"); - if ($vatBaseValue) { - $line->setVatBaseValue(Util::parseMoney($vatBaseValue, $bankTransaction->getCurrency())); - } - $vatRepValue = self::getField($lineElement, "vatrepvalue"); - if ($vatRepValue) { - $line->setVatRepValue(Util::parseMoney($vatRepValue, $bankTransaction->getCurrency())); - } - $projectOrAsset = self::getField($lineElement, "dim3"); - if ($projectOrAsset !== null) { - $line->setProjectOrAsset($projectOrAsset); - } - - return $line; - } - - private static function createVatBankTransactionLine(BankTransaction $bankTransaction, \DOMElement $lineElement): Vat - { - $line = new Vat(); - self::setBankTransactionLineBaseFields($bankTransaction, $lineElement, $line); - self::setBankTransactionLinePerformanceFields($lineElement, $line); - - $vatTurnover = self::getField($lineElement, "vatturnover"); - $line->setVatTurnover(Util::parseMoney($vatTurnover, $bankTransaction->getCurrency())); - $vatBaseTurnover = self::getField($lineElement, "vatbaseturnover"); - $line->setVatBaseTurnover(Util::parseMoney($vatBaseTurnover, $bankTransaction->getCurrency())); - - $vatRepTurnover = self::getField($lineElement, "vatrepturnover"); - if ($vatRepTurnover) { - $line->setVatRepTurnover(Util::parseMoney($vatRepTurnover, $bankTransaction->getCurrency())); - } - $vatCode = self::getField($lineElement, "vatcode"); - if ($vatCode !== null) { - $line->setVatCode($vatCode); - } - $vatBalanceAccount = self::getField($lineElement, "dim1"); - if ($vatBalanceAccount !== null) { - $line->setVatBalanceAccount($vatBalanceAccount); - } - - return $line; - } - - private static function setBankTransactionLineBaseFields( - BankTransaction $bankTransaction, - \DOMElement $lineElement, - Base $line - ): void { - /* - * When a bank transaction fails, it isn't created at Twinfield, so it is likely that they haven't generated - * any ids for the lines. - */ - $id = $lineElement->getAttribute("id"); - if (!empty($id)) { - $line->setId($id); - } - - $value = self::getField($lineElement, 'value'); - $line->setValue(Util::parseMoney($value, $bankTransaction->getCurrency())); - $line->setInvoiceNumber(self::getField($lineElement, "invoicenumber")); - - $description = self::getField($lineElement, "description"); - if ($description !== null) { - $line->setDescription($description); - } - $debitCredit = self::getField($lineElement, 'debitcredit'); - if ($debitCredit) { - $line->setDebitCredit(new DebitCredit($debitCredit)); - } - $destOffice = self::getField($lineElement, "destoffice"); - if ($destOffice) { - $line->setDestOffice(Office::fromCode($destOffice)); - } - $freeChar = self::getField($lineElement, "freechar"); - if ($freeChar) { - $line->setFreeChar($freeChar); - } - $comment = self::getField($lineElement, "comment"); - if ($comment !== null) { - $line->setComment($comment); - } - } - - private static function setBankTransactionLinePerformanceFields(\DOMElement $lineElement, Base $line): void - { - $performanceType = self::getField($lineElement, "performancetype"); - if ($performanceType) { - $line->setPerformanceType(new PerformanceType($performanceType)); - } - $performanceCountry = self::getField($lineElement, "performancecountry"); - if ($performanceCountry) { - $line->setPerformanceCountry($performanceCountry); - } - $performanceVatNumber = self::getField($lineElement, "performancevatnumber"); - if ($performanceVatNumber !== null) { - $line->setPerformanceVatNumber($performanceVatNumber); - } - $performanceDate = self::getField($lineElement, "performancedate"); - if ($performanceDate) { - $line->setPerformanceDate($performanceDate); - } - } -} \ No newline at end of file diff --git a/src/Mappers/TransactionMapper.php b/src/Mappers/TransactionMapper.php index cd928ae5..214688ef 100644 --- a/src/Mappers/TransactionMapper.php +++ b/src/Mappers/TransactionMapper.php @@ -4,6 +4,7 @@ use Money\Currency; use Money\Money; +use PhpTwinfield\BankTransaction; use PhpTwinfield\BaseTransaction; use PhpTwinfield\BaseTransactionLine; use PhpTwinfield\CashTransaction; @@ -122,7 +123,7 @@ public static function map(string $transactionClassName, Response $response): Ba if ($transaction instanceof JournalTransaction) { $transaction->setRegime(self::getField($transaction, $transactionElement, 'regime')); } - if ($transaction instanceof CashTransaction) { + if ($transaction instanceof BankTransaction || $transaction instanceof CashTransaction) { $transaction->setStartvalue( Util::parseMoney( self::getField($transaction, $transactionElement, 'startvalue'), @@ -134,103 +135,113 @@ public static function map(string $transactionClassName, Response $response): Ba // Parse the transaction lines $transactionLineClassName = $transaction->getLineClassName(); - foreach ($transactionElement->getElementsByTagName('line') as $lineElement) { - self::checkForMessage($transaction, $lineElement); - - /** @var BaseTransactionLine $transactionLine */ - $transactionLine = new $transactionLineClassName(); - $lineType = $lineElement->getAttribute('type'); - - $transactionLine - ->setLineType(new LineType($lineType)) - ->setId($lineElement->getAttribute('id')) - ->setDim1(self::getField($transaction, $lineElement, 'dim1')) - ->setDim2(self::getField($transaction, $lineElement, 'dim2')) - ->setValue(Money::EUR(100 * self::getField($transaction, $lineElement, 'value'))) - ->setDebitCredit(new DebitCredit(self::getField($transaction, $lineElement, 'debitcredit'))) - ->setBaseValue(Money::EUR(100 * self::getField($transaction, $lineElement, 'basevalue'))) - ->setRate(self::getField($transaction, $lineElement, 'rate')) - ->setRepValue(Money::EUR(100 * self::getField($transaction, $lineElement, 'repvalue'))) - ->setRepRate(self::getField($transaction, $lineElement, 'reprate')) - ->setDescription(self::getField($transaction, $lineElement, 'description')) - ->setMatchStatus(self::getField($transaction, $lineElement, 'matchstatus')) - ->setMatchLevel(self::getField($transaction, $lineElement, 'matchlevel')) - ->setVatCode(self::getField($transaction, $lineElement, 'vatcode')); - - // TODO - according to the docs, the field is called , but the examples use . - $baseValueOpen = self::getField($transaction, $lineElement, 'basevalueopen') ?: self::getField($transaction, $lineElement, 'openbasevalue'); - if ($baseValueOpen) { - $transactionLine->setBaseValueOpen(Money::EUR(100 * $baseValueOpen)); - } + $linesDOMTag = $transactionElement->getElementsByTagName('lines'); - $vatValue = self::getField($transaction, $lineElement, 'vatvalue'); - if ($lineType == LineType::DETAIL() && $vatValue) { - $transactionLine->setVatValue(Money::EUR(100 * $vatValue)); - } + if (isset($linesDOMTag) && $linesDOMTag->length > 0) { + $linesDOM = $linesDOMTag->item(0); - $baseline = self::getField($transaction, $lineElement, 'baseline'); - if ($baseline) { - $transactionLine->setBaseline($baseline); - } + foreach ($linesDOM->childNodes as $lineElement) { + if ($lineElement->nodeType !== 1) { + continue; + } + + self::checkForMessage($transaction, $lineElement); - if (Util::objectUses(FreeTextFields::class, $transactionLine)) { - $freetext1 = self::getField($transaction, $lineElement, 'freetext1'); - if ($freetext1) { - $transactionLine->setFreetext1($freetext1); + /** @var BaseTransactionLine $transactionLine */ + $transactionLine = new $transactionLineClassName(); + $lineType = $lineElement->getAttribute('type'); + + $transactionLine + ->setLineType(new LineType($lineType)) + ->setId($lineElement->getAttribute('id')) + ->setDim1(self::getField($transaction, $lineElement, 'dim1')) + ->setDim2(self::getField($transaction, $lineElement, 'dim2')) + ->setValue(Money::EUR(100 * self::getField($transaction, $lineElement, 'value'))) + ->setDebitCredit(new DebitCredit(self::getField($transaction, $lineElement, 'debitcredit'))) + ->setBaseValue(Money::EUR(100 * self::getField($transaction, $lineElement, 'basevalue'))) + ->setRate(self::getField($transaction, $lineElement, 'rate')) + ->setRepValue(Money::EUR(100 * self::getField($transaction, $lineElement, 'repvalue'))) + ->setRepRate(self::getField($transaction, $lineElement, 'reprate')) + ->setDescription(self::getField($transaction, $lineElement, 'description')) + ->setMatchStatus(self::getField($transaction, $lineElement, 'matchstatus')) + ->setMatchLevel(self::getField($transaction, $lineElement, 'matchlevel')) + ->setVatCode(self::getField($transaction, $lineElement, 'vatcode')); + + // TODO - according to the docs, the field is called , but the examples use . + $baseValueOpen = self::getField($transaction, $lineElement, 'basevalueopen') ?: self::getField($transaction, $lineElement, 'openbasevalue'); + if ($baseValueOpen) { + $transactionLine->setBaseValueOpen(Money::EUR(100 * $baseValueOpen)); } - $freetext2 = self::getField($transaction, $lineElement, 'freetext2'); - if ($freetext2) { - $transactionLine->setFreetext2($freetext2); + $vatValue = self::getField($transaction, $lineElement, 'vatvalue'); + if ($lineType == LineType::DETAIL() && $vatValue) { + $transactionLine->setVatValue(Money::EUR(100 * $vatValue)); } - $freetext3 = self::getField($transaction, $lineElement, 'freetext3'); - if ($freetext3) { - $transactionLine->setFreetext3($freetext3); + $baseline = self::getField($transaction, $lineElement, 'baseline'); + if ($baseline) { + $transactionLine->setBaseline($baseline); } - } - if (Util::objectUses(PerformanceFields::class, $transactionLine)) { - /** @var BaseTransactionLine|PerformanceFields $transactionLine */ - $performanceType = self::getField($transaction, $lineElement, 'performancetype'); - $transactionLine - ->setPerformanceType($performanceType ? new PerformanceType($performanceType) : null) - ->setPerformanceCountry(self::getField($transaction, $lineElement, 'performancecountry')) - ->setPerformanceVatNumber(self::getField($transaction, $lineElement, 'performancevatnumber')); + if (Util::objectUses(FreeTextFields::class, $transactionLine)) { + $freetext1 = self::getField($transaction, $lineElement, 'freetext1'); + if ($freetext1) { + $transactionLine->setFreetext1($freetext1); + } + + $freetext2 = self::getField($transaction, $lineElement, 'freetext2'); + if ($freetext2) { + $transactionLine->setFreetext2($freetext2); + } + + $freetext3 = self::getField($transaction, $lineElement, 'freetext3'); + if ($freetext3) { + $transactionLine->setFreetext3($freetext3); + } + } + + if (Util::objectUses(PerformanceFields::class, $transactionLine)) { + /** @var BaseTransactionLine|PerformanceFields $transactionLine */ + $performanceType = self::getField($transaction, $lineElement, 'performancetype'); + $transactionLine + ->setPerformanceType($performanceType ? new PerformanceType($performanceType) : null) + ->setPerformanceCountry(self::getField($transaction, $lineElement, 'performancecountry')) + ->setPerformanceVatNumber(self::getField($transaction, $lineElement, 'performancevatnumber')); - $performanceDate = self::getField($transaction, $lineElement, 'performancedate'); + $performanceDate = self::getField($transaction, $lineElement, 'performancedate'); - if ($performanceDate) { - $transactionLine->setPerformanceDate(Util::parseDate($performanceDate)); + if ($performanceDate) { + $transactionLine->setPerformanceDate(Util::parseDate($performanceDate)); + } } - } - if (in_array(ValueOpenField::class, class_uses($transactionLine))) { - // TODO - according to the docs, the field is called , but the examples use . - $valueOpen = self::getField($transaction, $lineElement, 'valueopen') ?: self::getField($transaction, $lineElement, 'openvalue'); - if ($valueOpen) { - $transactionLine->setValueOpen(Money::EUR(100 * $valueOpen)); + if (in_array(ValueOpenField::class, class_uses($transactionLine))) { + // TODO - according to the docs, the field is called , but the examples use . + $valueOpen = self::getField($transaction, $lineElement, 'valueopen') ?: self::getField($transaction, $lineElement, 'openvalue'); + if ($valueOpen) { + $transactionLine->setValueOpen(Money::EUR(100 * $valueOpen)); + } } - } - if (in_array(VatTotalFields::class, class_uses($transactionLine))) { - $vatTotal = self::getField($transaction, $lineElement, 'vattotal'); - if ($vatTotal) { - $transactionLine->setVatTotal(Money::EUR(100 * $vatTotal)); + if (in_array(VatTotalFields::class, class_uses($transactionLine))) { + $vatTotal = self::getField($transaction, $lineElement, 'vattotal'); + if ($vatTotal) { + $transactionLine->setVatTotal(Money::EUR(100 * $vatTotal)); + } + + $vatBaseTotal = self::getField($transaction, $lineElement, 'vatbasetotal'); + if ($vatBaseTotal) { + $transactionLine->setVatBaseTotal(Money::EUR(100 * $vatBaseTotal)); + } } - - $vatBaseTotal = self::getField($transaction, $lineElement, 'vatbasetotal'); - if ($vatBaseTotal) { - $transactionLine->setVatBaseTotal(Money::EUR(100 * $vatBaseTotal)); + if (Util::objectUses(InvoiceNumberField::class, $transactionLine)) { + /** @var InvoiceNumberField $transactionLine */ + $invoiceNumber = self::getField($transaction, $lineElement, 'invoicenumber'); + if ($invoiceNumber) { + $transactionLine->setInvoiceNumber(self::getField($transaction, $lineElement, 'invoicenumber')); + } } - } - if (Util::objectUses(InvoiceNumberField::class, $transactionLine)) { - /** @var InvoiceNumberField $transactionLine */ - $invoiceNumber = self::getField($transaction, $lineElement, 'invoicenumber'); - if ($invoiceNumber) { - $transactionLine->setInvoiceNumber(self::getField($transaction, $lineElement, 'invoicenumber')); - } - } - $transaction->addLine($transactionLine); + $transaction->addLine($transactionLine); + } } return $transaction; diff --git a/src/Transactions/BankTransactionLine/Base.php b/src/Transactions/BankTransactionLine/Base.php deleted file mode 100644 index 7d922205..00000000 --- a/src/Transactions/BankTransactionLine/Base.php +++ /dev/null @@ -1,165 +0,0 @@ -transaction; - } - - /** - * @param BankTransaction $object - */ - public function setTransaction($object): void - { - Assert::null($this->transaction, "Attempting to set a transaction while the transaction is already set."); - Assert::isInstanceOf($object, BankTransaction::class); - $this->transaction = $object; - } - - /** - * @return LineType - */ - final public function getLineType(): LineType - { - return $this->lineType; - } - - /** - * @param LineType $lineType - * @return $this - */ - final protected function setLineType(LineType $lineType) - { - $this->lineType = $lineType; - return $this; - } - - /** - * @return string - */ - public function getDescription(): ?string - { - return $this->description; - } - - /** - * @param string $description - * @return $this - */ - public function setDescription(string $description) - { - $this->description = $description; - return $this; - } - - /** - * @return null|Office - */ - public function getDestOffice(): ?Office - { - return $this->destOffice; - } - - /** - * Used for inter company transactions – here you define in which company the transaction line should be posted. - * - * @param Office $destOffice - * @return $this - */ - public function setDestOffice(Office $destOffice) - { - $this->destOffice = $destOffice; - return $this; - } - - public function getId(): ?int - { - return $this->id; - } - - /** - * @param int $id - * @return $this - */ - public function setId(int $id) - { - $this->id = $id; - return $this; - } - - public function getReference(): MatchReferenceInterface - { - $transaction = $this->getTransaction(); - - return new MatchReference( - $transaction->getOffice(), - $transaction->getCode(), - $transaction->getNumber(), - $this->getId() - ); - } - - protected function isIncomingTransactionType(): bool - { - return true; - } -} diff --git a/src/Transactions/BankTransactionLine/Detail.php b/src/Transactions/BankTransactionLine/Detail.php deleted file mode 100644 index 772784e8..00000000 --- a/src/Transactions/BankTransactionLine/Detail.php +++ /dev/null @@ -1,153 +0,0 @@ -vatValue = $vatValue; - - return $this; - } - - /** - * @param Money $vatBaseValue - * @return Detail - */ - public function setVatBaseValue(Money $vatBaseValue): Detail - { - $this->vatBaseValue = $vatBaseValue; - - return $this; - } - - /** - * @param Money $vatRepValue - * @return Detail - */ - public function setVatRepValue(Money $vatRepValue): Detail - { - $this->vatRepValue = $vatRepValue; - - return $this; - } - - /** - * VAT amount in base currency. - * - * @var Money|null - */ - private $vatBaseValue; - - /** - * VAT amount in reporting currency. - * - * @var Money|null - */ - private $vatRepValue; - - public function __construct() - { - $this->setLineType(LineType::DETAIL()); - } - - /** - * Set the customer or supplier balance account or profit and loss account. - * - * @param string $dim1 - * @return $this - */ - public function setAccount(string $dim1) - { - return $this->setDim1($dim1); - } - - /** - * Set the customer or supplier or the cost center or empty. - * - * @param string $dim2 - * @return $this - */ - public function setCustomerOrSupplierOrCostCenter(string $dim2) - { - return $this->setDim2($dim2); - } - - /** - * Set the project or asset or empty. - * - * @param string $dim3 - * @return $this - */ - public function setProjectOrAsset(string $dim3) - { - return $this->setDim3($dim3); - } - - /** - * Credit in case money is received and debit in case money is paid. - * - * @param DebitCredit $debitCredit - * @return Detail - */ - public function setDebitCredit(DebitCredit $debitCredit): self - { - return parent::setDebitCredit($debitCredit); - } - - /** - * Amount without VAT. - * - * @param Money $money - */ - public function setValue(Money $money): void - { - parent::setValue($money); - } - - - /** - * @return Money|null - */ - public function getVatValue(): ?Money - { - return $this->vatValue; - } - - /** - * @return Money|null - */ - public function getVatBaseValue(): ?Money - { - return $this->vatBaseValue; - } - - /** - * @return Money|null - */ - public function getVatRepValue(): ?Money - { - return $this->vatRepValue; - } -} \ No newline at end of file diff --git a/src/Transactions/BankTransactionLine/Total.php b/src/Transactions/BankTransactionLine/Total.php deleted file mode 100644 index 176312c0..00000000 --- a/src/Transactions/BankTransactionLine/Total.php +++ /dev/null @@ -1,115 +0,0 @@ -setLineType(LineType::TOTAL()); - } - - public function setBankBalanceAccount(string $dim1) - { - $this->setDim1($dim1); - } - - /** - * Based on the sum of the individual bank transaction lines. In case of a bank addition debit. In case of a bank - * withdrawal credit. - * - * @param DebitCredit $debitCredit - * @return $this - */ - public function setDebitCredit(DebitCredit $debitCredit) - { - return parent::setDebitCredit($debitCredit); - } - - /** - * Amount including VAT. - * - * @param Money $money - */ - public function setValue(Money $money): void - { - parent::setValue($money); - } - - /** - * @return Money|null - */ - public function getVatTotal(): ?Money - { - return $this->vatTotal; - } - - /** - * The total VAT amount in the currency of the bank transaction. - * - * @param Money $vatTotal - */ - public function setVatTotal(Money $vatTotal): void - { - $this->vatTotal = $vatTotal; - } - - /** - * @return Money|null - */ - public function getVatBaseTotal(): ?Money - { - return $this->vatBaseTotal; - } - - /** - * The total VAT amount in base currency. - * - * @param Money $vatBaseTotal - */ - public function setVatBaseTotal(Money $vatBaseTotal): void - { - $this->vatBaseTotal = $vatBaseTotal; - } - - /** - * @return Money|null - */ - public function getVatRepTotal(): ?Money - { - return $this->vatRepTotal; - } - - /** - * @param Money $vatRepTotal - */ - public function setVatRepTotal(Money $vatRepTotal): void - { - $this->vatRepTotal = $vatRepTotal; - } -} \ No newline at end of file diff --git a/src/Transactions/BankTransactionLine/Vat.php b/src/Transactions/BankTransactionLine/Vat.php deleted file mode 100644 index 23315220..00000000 --- a/src/Transactions/BankTransactionLine/Vat.php +++ /dev/null @@ -1,55 +0,0 @@ -setLineType(LineType::VAT()); - } - - /** - * Set the VAT balance account. When an empty dim1 is entered, by default the general ledger account will be taken - * as entered at the VAT code in Twinfield. - * - * @param string $dim1 - */ - public function setVatBalanceAccount(string $dim1) - { - $this->setDim1($dim1); - } - - /** - * Based on the sum of the vat amounts of the individual bank transaction lins. In case of a bank addition credit. - * In case of a bank withdrawal debit. - * - * @param DebitCredit $debitCredit - * @return Vat - */ - public function setDebitCredit(DebitCredit $debitCredit): self - { - return parent::setDebitCredit($debitCredit); - } - - /** - * VAT amount. - * - * @param Money $money - */ - public function setValue(Money $money): void - { - parent::setValue($money); - } -} \ No newline at end of file diff --git a/src/Transactions/TransactionLine.php b/src/Transactions/TransactionLine.php index 4ebf3898..9448082d 100644 --- a/src/Transactions/TransactionLine.php +++ b/src/Transactions/TransactionLine.php @@ -2,7 +2,7 @@ namespace PhpTwinfield\Transactions; -use PhpTwinfield\BankTransaction; +use PhpTwinfield\BaseTransaction; use PhpTwinfield\Enums\LineType; use PhpTwinfield\MatchReferenceInterface; @@ -23,21 +23,21 @@ public function getLineType(): LineType; public function getId(): ?int; /** - * Set the bank transaction on the line. This is needed later on. + * Set the transaction on the line. This is needed later on. * - * @param BankTransaction $object + * @param BaseTransaction $object * @throws \InvalidArgumentException If a transaction is invalid or if a transaction is already set. * @internal */ public function setTransaction($object): void; /** - * Gets the bank transaction from the line. + * Gets the transaction from the line. * * Note that you should add the return type when implementing. * * @see MatchReferenceInterface - * @return BankTransaction + * @return BaseTransaction * @internal */ public function getTransaction(); @@ -50,4 +50,4 @@ public function getTransaction(); * @return MatchReferenceInterface */ public function getReference(): MatchReferenceInterface; -} \ No newline at end of file +} diff --git a/tests/IntegrationTests/BankTransactionIntegrationTest.php b/tests/IntegrationTests/BankTransactionIntegrationTest.php new file mode 100644 index 00000000..d4add1d2 --- /dev/null +++ b/tests/IntegrationTests/BankTransactionIntegrationTest.php @@ -0,0 +1,194 @@ +transactionApiConnector = new TransactionApiConnector($this->connection); + } + + public function testGetBankTransactionWorks() + { + $response = Response::fromString(file_get_contents(__DIR__ . '/resources/bankTransactionGetResponse.xml')); + + $this->processXmlService + ->expects($this->once()) + ->method("sendDocument") + ->with($this->isInstanceOf(\PhpTwinfield\Request\Read\Transaction::class)) + ->willReturn($response); + + /** @var BankTransaction $bankTransaction */ + $bankTransaction = $this->transactionApiConnector->get(BankTransaction::class, 'BNK', '201300008', $this->office); + + $this->assertInstanceOf(BankTransaction::class, $bankTransaction); + $this->assertEquals(Destiny::TEMPORARY(), $bankTransaction->getDestiny()); + $this->assertNull($bankTransaction->isAutoBalanceVat()); + $this->assertSame(false, $bankTransaction->getRaiseWarning()); + $this->assertEquals(Office::fromCode('001'), $bankTransaction->getOffice()); + $this->assertSame('BNK', $bankTransaction->getCode()); + $this->assertSame(201300008, $bankTransaction->getNumber()); + $this->assertSame('2013/11', $bankTransaction->getPeriod()); + $this->assertEquals(new Currency('EUR'), $bankTransaction->getCurrency()); + $this->assertEquals(new DateTimeImmutable('2013-11-04'), $bankTransaction->getDate()); + $this->assertSame('import', $bankTransaction->getOrigin()); + $this->assertNull($bankTransaction->getFreetext1()); + $this->assertNull($bankTransaction->getFreetext2()); + $this->assertNull($bankTransaction->getFreetext3()); + $this->assertSame(4, $bankTransaction->getStatementnumber()); + $this->assertTrue(Money::EUR(97401)->equals($bankTransaction->getStartvalue())); + $this->assertTrue(Money::EUR(140956)->equals($bankTransaction->getClosevalue())); + + /** @var BankTransactionLine[] $bankTransactionLines */ + $bankTransactionLines = $bankTransaction->getLines(); + $this->assertCount(2, $bankTransactionLines); + [$totalLine, $detailLine] = $bankTransactionLines; + + $this->assertEquals(LineType::TOTAL(), $totalLine->getLineType()); + $this->assertSame(1, $totalLine->getId()); + $this->assertSame('1001', $totalLine->getDim1()); + $this->assertEquals(DebitCredit::DEBIT(), $totalLine->getDebitCredit()); + $this->assertEquals(Money::EUR(43555), $totalLine->getValue()); + $this->assertEquals(Money::EUR(43555), $totalLine->getBaseValue()); + $this->assertSame(1.0, $totalLine->getRate()); + $this->assertEquals(Money::EUR(65333), $totalLine->getRepValue()); + $this->assertSame(1.500000000, $totalLine->getRepRate()); + $this->assertSame(BankTransactionLine::MATCHSTATUS_NOTMATCHABLE, $totalLine->getMatchStatus()); + $this->assertNull($totalLine->getMatchLevel()); + $this->assertNull($totalLine->getBaseValueOpen()); + $this->assertNull($totalLine->getVatCode()); + $this->assertNull($totalLine->getVatValue()); + $this->assertNull($totalLine->getVatTotal()); + $this->assertNull($totalLine->getVatBaseTotal()); + $this->assertNull($totalLine->getPerformanceType()); + $this->assertNull($totalLine->getPerformanceCountry()); + $this->assertNull($totalLine->getPerformanceVatNumber()); + $this->assertNull($totalLine->getPerformanceDate()); + + $this->assertEquals(LineType::DETAIL(), $detailLine->getLineType()); + $this->assertSame(2, $detailLine->getId()); + $this->assertSame('1300', $detailLine->getDim1()); + $this->assertSame('1000', $detailLine->getDim2()); + $this->assertEquals(DebitCredit::CREDIT(), $detailLine->getDebitCredit()); + $this->assertSame('11001770', $detailLine->getInvoiceNumber()); + $this->assertEquals(Money::EUR(43555), $detailLine->getValue()); + $this->assertEquals(Money::EUR(43555), $totalLine->getBaseValue()); + $this->assertSame(1.0, $totalLine->getRate()); + $this->assertEquals(Money::EUR(65333), $totalLine->getRepValue()); + $this->assertSame(1.500000000, $totalLine->getRepRate()); + $this->assertSame('Invoice paid', $detailLine->getDescription()); + $this->assertSame(BankTransactionLine::MATCHSTATUS_AVAILABLE, $detailLine->getMatchStatus()); + $this->assertSame(2, $detailLine->getMatchLevel()); + $this->assertEquals(Money::EUR(43555), $detailLine->getBaseValueOpen()); + $this->assertEquals(Money::EUR(65333), $detailLine->getRepValue()); + $this->assertNull($detailLine->getVatCode()); + $this->assertNull($detailLine->getVatValue()); + $this->assertNull($detailLine->getVatTotal()); + $this->assertNull($detailLine->getVatBaseTotal()); + $this->assertNull($detailLine->getPerformanceType()); + $this->assertNull($detailLine->getPerformanceCountry()); + $this->assertNull($detailLine->getPerformanceVatNumber()); + $this->assertNull($detailLine->getPerformanceDate()); + } + + public function testSendBankTransactionWorks() + { + $bankTransaction = new BankTransaction(); + $bankTransaction + ->setOffice(Office::fromCode('001')) + ->setDestiny(Destiny::TEMPORARY()) + ->setRaiseWarning(false) + ->setCode('BNK') + ->setCurrency(new Currency('EUR')) + ->setDate(new DateTimeImmutable('2013-11-04')) + ->setStatementnumber(4) + ->setStartvalue(Money::EUR(97401)); + + $totalLine = new BankTransactionLine(); + $totalLine + ->setLineType(LineType::TOTAL()) + ->setId('1') + ->setDim1('1001') + ->setValue(Money::EUR(43555)); + + $detailLine = new BankTransactionLine(); + $detailLine + ->setLineType(LineType::DETAIL()) + ->setId('2') + ->setDim1('1300') + ->setDim2('1000') + ->setValue(Money::EUR(43555)) + ->setInvoiceNumber('11001770') + ->setDescription('Invoice paid'); + + $bankTransaction + ->addLine($totalLine) + ->addLine($detailLine); + + $this->processXmlService + ->expects($this->once()) + ->method("sendDocument") + ->with($this->isInstanceOf(TransactionsDocument::class)) + ->willReturnCallback(function (TransactionsDocument $transactionsDocument) { + $this->assertXmlStringEqualsXmlString( + file_get_contents(realpath(__DIR__ . '/resources/bankTransactionSendRequest.xml')), + $transactionsDocument->saveXML() + ); + + return $this->getSuccessfulResponse(); + }); + + $this->transactionApiConnector->send($bankTransaction); + } + + protected function getSuccessfulResponse(): Response + { + return Response::fromString( + ' +
+ 001 + BNK + EUR + 20131104 + 4 + 974.01 + 1409.56 + import + MARCEL + 2013/11 + 201300008 +
+
+
' + ); + } +} diff --git a/tests/IntegrationTests/resources/bankTransactionGetResponse.xml b/tests/IntegrationTests/resources/bankTransactionGetResponse.xml new file mode 100644 index 00000000..4bfdb0c8 --- /dev/null +++ b/tests/IntegrationTests/resources/bankTransactionGetResponse.xml @@ -0,0 +1,47 @@ + +
+ 001 + BNK + EUR + 20131104 + 4 + 974.01 + 1409.56 + import + MARCEL + 2013/11 + 201300008 +
+ + + 1001 + debit + 435.55 + 1 + 435.55 + 1.500000000 + 653.33 + notmatchable + + + 1300 + 1000 + credit + 435.55 + 11001770 + Invoice paid + 20131108 + 1 + 435.55 + 1.500000000 + 653.33 + + 2 + 2 + 435.55 + 435.55 + 653.33 + available + + +
diff --git a/tests/IntegrationTests/resources/bankTransactionSendRequest.xml b/tests/IntegrationTests/resources/bankTransactionSendRequest.xml new file mode 100644 index 00000000..0c1ab476 --- /dev/null +++ b/tests/IntegrationTests/resources/bankTransactionSendRequest.xml @@ -0,0 +1,28 @@ + + +
+ BNK + EUR + 20131104 + 001 + 4 + 974.01 + 1409.56 +
+ + + 1001 + debit + 435.55 + + + 1300 + 1000 + credit + 435.55 + 11001770 + Invoice paid + + +
+
diff --git a/tests/UnitTests/ApiConnectors/BankTransactionApiConnectorTest.php b/tests/UnitTests/ApiConnectors/BankTransactionApiConnectorTest.php deleted file mode 100644 index dd4f455c..00000000 --- a/tests/UnitTests/ApiConnectors/BankTransactionApiConnectorTest.php +++ /dev/null @@ -1,260 +0,0 @@ -processXmlService = $this->getMockBuilder(ProcessXmlService::class) - ->setMethods(["sendDocument"]) - ->disableOriginalConstructor() - ->getMock(); - - /** @var AuthenticatedConnection|\PHPUnit_Framework_MockObject_MockObject $connection */ - $connection = $this->createMock(AuthenticatedConnection::class); - $connection - ->expects($this->any()) - ->method("getAuthenticatedClient") - ->willReturn($this->processXmlService); - - $this->apiConnector = new BankTransactionApiConnector($connection); - $this->office = Office::fromCode("XXX101"); - } - - private function createBankTransaction(): BankTransaction - { - $banktransaction = new BankTransaction(); - $banktransaction->setDestiny(Destiny::TEMPORARY()); - $banktransaction->setOffice($this->office); - - return $banktransaction; - } - - public function testFailureResponseWithoutLineIdsThrowsResponseExceptionAndObjectCanStillBeExtracted() - { - $response = Response::fromString(file_get_contents( - __DIR__. "/resources/failed-response-without-line-ids.xml" - )); - - $this->processXmlService->expects($this->once()) - ->method("sendDocument") - ->willReturn($response); - - $mapped_responses = $this->apiConnector->sendAll([ - $this->createBankTransaction() - ]); - - self::assertCount(1, $mapped_responses); - - try { - $mapped_responses[0]->unwrap(); - - self::fail('Expected a ResponseException for a failed response'); - } catch (ResponseException $e) { - /** @var BankTransaction $bank_transaction */ - $bank_transaction = $e->getReturnedObject(); - - self::assertCount(2, $bank_transaction->getLines()); - - self::assertNull($bank_transaction->getLines()[0]->getId()); - self::assertNull($bank_transaction->getLines()[1]->getId()); - } - } - - public function testSendAllReturnsMappedObjects() - { - $response = Response::fromString(file_get_contents( - __DIR__."/resources/2-failed-and-1-successful-banktransactions.xml" - )); - - $this->processXmlService->expects($this->once()) - ->method("sendDocument") - ->willReturn($response); - - $responses = $this->apiConnector->sendAll([ - $this->createBankTransaction(), - $this->createBankTransaction(), - $this->createBankTransaction(), - ]); - - $this->assertCount(3, $responses); - - [$response1, $response2, $response3] = $responses; - - try { - $response1->unwrap(); - } catch (Exception $e) { - $this->assertEquals("De boeking is niet in balans. Er ontbreekt 0.01 debet.//De boeking balanceert niet in de basisvaluta. Er ontbreekt 0.01 debet.//De boeking balanceert niet in de rapportagevaluta. Er ontbreekt 0.01 debet.", $e->getMessage()); - } - - try { - $response2->unwrap(); - } catch (Exception $e) { - $this->assertEquals("De boeking is niet in balans. Er ontbreekt 0.01 debet.//De boeking balanceert niet in de basisvaluta. Er ontbreekt 0.01 debet.//De boeking balanceert niet in de rapportagevaluta. Er ontbreekt 0.01 debet.", $e->getMessage()); - } - - /** @var BankTransaction $banktransaction3 */ - $banktransaction3 = $response3->unwrap(); - - $this->assertEquals("BNK", $banktransaction3->getCode()); - $this->assertEquals("OFFICE001", $banktransaction3->getOffice()->getCode()); - $this->assertEquals("2017/08", $banktransaction3->getPeriod()); - $this->assertEquals(new Currency("EUR"), $banktransaction3->getCurrency()); - $this->assertEquals(Money::EUR(0), $banktransaction3->getStartvalue()); - $this->assertEquals(Money::EUR(0), $banktransaction3->getClosevalue()); - $this->assertEquals(0, $banktransaction3->getStatementnumber()); - $this->assertEquals("201700334", $banktransaction3->getNumber()); - - $lines = $banktransaction3->getLines(); - $this->assertCount(3, $lines); - - /** @var Total $line */ - $line = $lines[0]; - $this->assertEquals("1", $line->getId()); - $this->assertEquals(LineType::TOTAL(), $line->getLineType()); - $this->assertEquals("1100", $line->getDim1()); - $this->assertEquals("debit", $line->getDebitCredit()); - $this->assertEquals(Money::EUR(0), $line->getValue()); - $this->assertEquals("2017.123456", $line->getInvoiceNumber()); - $this->assertEquals("2017.123456", $line->getDescription()); - $this->assertEquals("2017.123456", $line->getComment()); - - /** @var Detail $line */ - $line = $lines[1]; - $this->assertEquals("2", $line->getId()); - $this->assertEquals(LineType::DETAIL(), $line->getLineType()); - $this->assertEquals("1800", $line->getDim1()); - $this->assertEquals("debit", $line->getDebitCredit()); - $this->assertEquals(Money::EUR(87), $line->getValue()); - $this->assertEquals("2017.123456", $line->getInvoiceNumber()); - $this->assertEquals("2017.123456", $line->getDescription()); - $this->assertEquals("2017.123456", $line->getComment()); - } - - public function testSendAllReturnsMappedObjectsAllLineTypes() - { - $response = Response::fromString(file_get_contents( - __DIR__."/resources/banktransaction-with-all-line-types.xml" - )); - - $this->processXmlService->expects($this->once()) - ->method("sendDocument") - ->willReturn($response); - - $responses = $this->apiConnector->sendAll([$this->createBankTransaction()]); - $this->assertCount(1, $responses); - $response = $responses[0]; - - /** @var BankTransaction $banktransaction */ - $banktransaction = $response->unwrap(); - - $this->assertEquals("BNK", $banktransaction->getCode()); - $this->assertEquals("OFFICE001", $banktransaction->getOffice()->getCode()); - $this->assertEquals("2017/09", $banktransaction->getPeriod()); - $this->assertEquals(new Currency("EUR"), $banktransaction->getCurrency()); - $this->assertEquals(Money::EUR(0), $banktransaction->getStartvalue()); - $this->assertEquals(Money::EUR(12100), $banktransaction->getClosevalue()); - $this->assertEquals(0, $banktransaction->getStatementnumber()); - $this->assertEquals("201700001", $banktransaction->getNumber()); - - $lines = $banktransaction->getLines(); - $this->assertCount(3, $lines); - - /** @var Total $line */ - $line = $lines[0]; - $this->assertEquals("1", $line->getId()); - $this->assertEquals(LineType::TOTAL(), $line->getLineType()); - $this->assertEquals("1100", $line->getDim1()); - $this->assertEquals("debit", $line->getDebitCredit()); - $this->assertEquals(Money::EUR(12100), $line->getValue()); - - /** @var Detail $line */ - $line = $lines[1]; - $this->assertEquals("2", $line->getId()); - $this->assertEquals(LineType::DETAIL(), $line->getLineType()); - $this->assertEquals("2200", $line->getDim1()); - $this->assertEquals("credit", $line->getDebitCredit()); - $this->assertEquals(Money::EUR(10000), $line->getValue()); - $this->assertEquals("My transaction", $line->getDescription()); - $this->assertEquals("VH", $line->getVatCode()); - $this->assertEquals(Money::EUR(2100), $line->getVatValue()); - $this->assertEquals(null, $line->getInvoiceNumber()); - $this->assertEquals(Money::EUR(2100), $line->getVatBaseValue()); - - /** @var Vat $line */ - $line = $lines[2]; - $this->assertEquals("3", $line->getId()); - $this->assertEquals(LineType::VAT(), $line->getLineType()); - $this->assertEquals("1502", $line->getDim1()); - $this->assertEquals("credit", $line->getDebitCredit()); - $this->assertEquals(Money::EUR(2100), $line->getValue()); - $this->assertEquals("VH", $line->getVatCode()); - $this->assertEquals(Money::EUR(10000), $line->getVatTurnover()); - $this->assertEquals(Money::EUR(10000), $line->getVatBaseTurnover()); - } - - /** - * @expectedException Exception - * @expectedExceptionMessage De status van de boeking moet Concept zijn - */ - public function testDeleteThrowsWhenResponseContainsErrorMessages() - { - $bookingReference = new BookingReference(Office::fromCode("OFFICE001"), "BNK", 201700006); - - $this->processXmlService->expects($this->once()) - ->method("sendDocument") - ->willReturnCallback(function(\DOMDocument $document) { - - $this->assertXmlStringEqualsXmlString(' - OFFICE001 - BNK - 201700006 -', $document->saveXML()); - - return Response::fromString(' - - OFFICE001 - BNK - 201700006 -'); - }); - - $this->apiConnector->delete($bookingReference, "It was merely a test transaction & I no longer need it."); - } -} \ No newline at end of file diff --git a/tests/UnitTests/BankTransactionLineUnitTest.php b/tests/UnitTests/BankTransactionLineUnitTest.php new file mode 100644 index 00000000..80f05e00 --- /dev/null +++ b/tests/UnitTests/BankTransactionLineUnitTest.php @@ -0,0 +1,193 @@ +line = new BankTransactionLine(); + } + + public function testSetTransaction() + { + $bankTransaction = new BankTransaction(); + $this->line->setTransaction($bankTransaction); + + $this->assertEquals($bankTransaction, $this->line->getTransaction()); + } + + public function testCanNotSetDifferentTransaction() + { + $this->expectException(InvalidArgumentException::class); + + $transaction = new SalesTransaction(); + $this->line->setTransaction($transaction); + } + + public function testCanNotSetTransactionIfTransactionIsAlreadySet() + { + $this->expectException(InvalidArgumentException::class); + + $bankTransaction1 = new BankTransaction(); + $bankTransaction2 = new BankTransaction(); + $this->line->setTransaction($bankTransaction1); + $this->line->setTransaction($bankTransaction2); + } + + public function testSetDim2() + { + $this->line->setLineType(LineType::DETAIL()); + + $this->assertEquals($this->line, $this->line->setDim2('test'), 'Fluid interface is expected'); + $this->assertSame('test', $this->line->getDim2()); + } + + public function testCanNotSetDim2IfLineTypeIsNotDetail() + { + $this->expectExceptionMessage('Dimension 2 is invalid for line class PhpTwinfield\BankTransactionLine and type \'vat\'.'); + + $this->line->setLineType(LineType::VAT()); + $this->line->setDim2('test'); + } + + public function testSetDim3() + { + $this->line->setLineType(LineType::DETAIL()); + + $this->assertEquals($this->line, $this->line->setDim3('test'), 'Fluid interface is expected'); + $this->assertSame('test', $this->line->getDim3()); + } + + public function testCanNotSetDim3IfLineTypeIsNotDetail() + { + $this->expectExceptionMessage('Dimension 3 is invalid for line class PhpTwinfield\BankTransactionLine and type \'vat\'.'); + + $this->line->setLineType(LineType::VAT()); + $this->line->setDim3('test'); + } + + public function testSetMatchStatus() + { + $this->line->setLineType(LineType::DETAIL()); + + $this->assertEquals($this->line, $this->line->setMatchStatus(BankTransactionLine::MATCHSTATUS_MATCHED), 'Fluid interface is expected'); + $this->assertSame(BankTransactionLine::MATCHSTATUS_MATCHED, $this->line->getMatchStatus()); + } + + public function testCanNotSetMatchStatusOtherThanNotMatchableIfLineTypeIsNotDetail() + { + $this->expectExceptionMessage('Invalid match status \'matched\' for line class PhpTwinfield\BankTransactionLine and type \'vat\'.'); + + $this->line->setLineType(LineType::VAT()); + $this->line->setMatchStatus(BankTransactionLine::MATCHSTATUS_MATCHED); + } + + public function testSetMatchLevel() + { + $this->line->setLineType(LineType::DETAIL()); + + $this->assertEquals($this->line, $this->line->setMatchLevel(1), 'Fluid interface is expected'); + $this->assertSame(1, $this->line->getMatchLevel()); + } + + public function testCanNotSetMatchLevelIfLineTypeIsNotDetail() + { + $this->expectExceptionMessage('Invalid field \'matchLevel\' for line class PhpTwinfield\BankTransactionLine and type \'vat\'.'); + + $this->line->setLineType(LineType::VAT()); + $this->line->setMatchLevel(1); + } + + public function testSetBaseValueOpen() + { + $this->line->setLineType(LineType::DETAIL()); + + $this->assertEquals($this->line, $this->line->setBaseValueOpen(Money::EUR(100)), 'Fluid interface is expected'); + $this->assertEquals(Money::EUR(100), $this->line->getBaseValueOpen()); + } + + public function testCanNotSetBaseValueOpenIfLineTypeIsNotDetail() + { + $this->expectExceptionMessage('Invalid field \'baseValueOpen\' for line class PhpTwinfield\BankTransactionLine and type \'vat\'.'); + + $this->line->setLineType(LineType::VAT()); + $this->line->setBaseValueOpen(Money::EUR(100)); + } + + public function testSetVatTurnover() + { + $this->line->setLineType(LineType::VAT()); + + $this->assertEquals($this->line, $this->line->setVatTurnover(Money::EUR(100)), 'Fluid interface is expected'); + $this->assertEquals(Money::EUR(100), $this->line->getVatTurnover()); + } + + public function testCanNotSetVatTurnoverIfLineTypeIsNotVat() + { + $this->expectExceptionMessage('Invalid field \'vatturnover\' for line class PhpTwinfield\BankTransactionLine and type \'detail\'.'); + + $this->line->setLineType(LineType::DETAIL()); + $this->line->setVatTurnover(Money::EUR(100)); + } + + public function testSetVatBaseTurnover() + { + $this->line->setLineType(LineType::VAT()); + + $this->assertEquals($this->line, $this->line->setVatBaseTurnover(Money::EUR(100)), 'Fluid interface is expected'); + $this->assertEquals(Money::EUR(100), $this->line->getVatBaseTurnover()); + } + + public function testCanNotSetVatBaseTurnoverIfLineTypeIsNotVat() + { + $this->expectExceptionMessage('Invalid field \'vatbaseturnover\' for line class PhpTwinfield\BankTransactionLine and type \'detail\'.'); + + $this->line->setLineType(LineType::DETAIL()); + $this->line->setVatBaseTurnover(Money::EUR(100)); + } + + public function testSetVatRepTurnover() + { + $this->line->setLineType(LineType::VAT()); + + $this->assertEquals($this->line, $this->line->setVatRepTurnover(Money::EUR(100)), 'Fluid interface is expected'); + $this->assertEquals(Money::EUR(100), $this->line->getVatRepTurnover()); + } + + public function testCanNotSetVatRepTurnoverIfLineTypeIsNotVat() + { + $this->expectExceptionMessage('Invalid field \'vatrepturnover\' for line class PhpTwinfield\BankTransactionLine and type \'detail\'.'); + + $this->line->setLineType(LineType::DETAIL()); + $this->line->setVatRepTurnover(Money::EUR(100)); + } + + public function testSetInvoiceNumber() + { + $this->line->setLineType(LineType::DETAIL()); + + $this->assertEquals($this->line, $this->line->setInvoiceNumber('11001770'), 'Fluid interface is expected'); + $this->assertSame('11001770', $this->line->getInvoiceNumber()); + } + + public function testCanNotSetInvoiceNumberIfLineTypeIsNotDetail() + { + $this->expectExceptionMessage('Invalid field \'invoicenumber\' for line class PhpTwinfield\BankTransactionLine and type \'total\'.'); + + $this->line->setLineType(LineType::TOTAL()); + $this->line->setInvoiceNumber('11001770'); + } +} diff --git a/tests/UnitTests/BankTransactionUnitTest.php b/tests/UnitTests/BankTransactionUnitTest.php index 54b66017..99aece47 100644 --- a/tests/UnitTests/BankTransactionUnitTest.php +++ b/tests/UnitTests/BankTransactionUnitTest.php @@ -1,179 +1,88 @@ setOffice(Office::fromCode("XXX99999")); - $bank->setNumber("201300003"); - $bank->getNumber(); - $bank->setCode("MEMO"); - - $line = new Detail(); - $line->setId(1); - $line->setValue(Money::EUR(1)); - - $bank->addLine($line); - - $reference = $line->getReference(); - - $this->assertEquals(Office::fromCode("XXX99999"), $reference->getOffice()); - $this->assertEquals("201300003", $reference->getNumber()); - $this->assertEquals("1", $reference->getLineId()); - $this->assertEquals("MEMO", $reference->getCode()); - } - - public function testGetLineReturnsLinesInSameOrderButAlwaysWithTotalAtTheTop() - { - $total_line_count = 287; - - $bank_transaction = new BankTransaction(); - - for ($i = 1; $i < $total_line_count; $i++) { - $this->addDetailLineWithDescription($bank_transaction, (string)$i); - } - - $this->addTotalLineWithDescription($bank_transaction, '0'); - - self::assertLinesInOrderBasedOnDescription($bank_transaction, $total_line_count); - } - - private static function assertLinesInOrderBasedOnDescription( - BankTransaction $bank_transaction, - int $expected_line_count - ) { - $i = 0; - /** @var Base $line */ - foreach ($bank_transaction->getLines() as $line) { - self::assertSame( - $i, - (int)$line->getDescription(), - 'Expected line #' . $i . ', but got line #' . $line->getDescription() . - ' of type ' . $line->getLineType()->getValue() . '. Wrong order!' - ); - $i++; - } - - self::assertSame($expected_line_count, $i, 'Number of returned lines does not match number of added lines'); - } - - private function addTotalLineWithDescription(BankTransaction $bankTransaction, string $description): Total - { - $line = new Total(); - $line->setDescription($description); - $line->setValue(Money::EUR(0)); + /** + * @var BankTransaction + */ + private $bankTransaction; - $bankTransaction->addLine($line); - - return $line; - } - - private function addDetailLineWithDescription(BankTransaction $bankTransaction, string $description): Detail + protected function setUp() { - $line = new Detail(); - $line->setDescription($description); - $line->setValue(Money::EUR(0)); - - $bankTransaction->addLine($line); - - return $line; + $this->bankTransaction = new BankTransaction(); } - public function testGetLinesReturnsLinesInTheSameOrderAsTheyWereAdded() + public function testSetStartValue() { - $total_line_count = 300; + $this->bankTransaction->setStartvalue(Money::EUR(100)); - $bank_transaction = new BankTransaction(); - - $this->addTotalLineWithDescription($bank_transaction, '0'); - - for ($i = 1; $i < $total_line_count; $i++) { - $this->addDetailLineWithDescription($bank_transaction, (string)$i); - } - - self::assertLinesInOrderBasedOnDescription($bank_transaction, $total_line_count); + $this->assertEquals(new Currency('EUR'), $this->bankTransaction->getCurrency()); + $this->assertEquals(Money::EUR(100), $this->bankTransaction->getStartvalue()); + $this->assertEquals(Money::EUR(100), $this->bankTransaction->getClosevalue()); } - public function testGetLinesReturnsEmptyArrayWhenNoLinesSet() + public function testSetCurrencyWithoutStartValue() { - $bank_transaction = new BankTransaction(); - - self::assertCount(0, $bank_transaction->getLines()); + $this->bankTransaction->setCurrency(new Currency('EUR')); + $this->assertEquals(new Currency('EUR'), $this->bankTransaction->getCurrency()); } - public function testGetLinesReturnsLinesInSameOrderWhenOnlyDetailsAdded() + public function testSetCurrencyWithZeroStartValue() { - $bank_transaction = new BankTransaction(); + $this->bankTransaction->setStartvalue(Money::EUR(0)); + $this->bankTransaction->setCurrency(new Currency('EUR')); - $this->addDetailLineWithDescription($bank_transaction, '0'); - $this->addDetailLineWithDescription($bank_transaction, '1'); - $this->addDetailLineWithDescription($bank_transaction, '2'); - - self::assertLinesInOrderBasedOnDescription($bank_transaction, 3); + $this->assertEquals(new Currency('EUR'), $this->bankTransaction->getCurrency()); } - public function testGetLinesReturnsOnlyTotalLineWhenOnlyTotalLineIsAdded() + public function testSetCurrencyWithStartValue() { - $bank_transaction = new BankTransaction(); - - $this->addTotalLineWithDescription($bank_transaction, '0'); + $this->expectException(InvalidArgumentException::class); - self::assertCount(1, $bank_transaction->getLines()); - self::assertTrue($bank_transaction->getLines()[0]->getLineType()->equals(LineType::TOTAL())); + $this->bankTransaction->setStartvalue(Money::EUR(100)); + $this->bankTransaction->setCurrency(new Currency('EUR')); } - public function testAdding1TotalLineAnd499DetailLinesToABankTransactionWorks() + public function testAddLineWithWrongTransactionLine() { - $total_line_count = 500; - - $bank_transaction = new BankTransaction(); + $this->expectException(InvalidArgumentException::class); - $this->addTotalLineWithDescription($bank_transaction, '0'); - for ($i = 1; $i < $total_line_count; $i++) { - $this->addDetailLineWithDescription($bank_transaction, (string)$i); - } - - self::assertCount($total_line_count, $bank_transaction->getLines()); + $this->bankTransaction->setStartvalue(Money::EUR(100)); + $this->bankTransaction->addLine(new SalesTransactionLine()); } - public function testAdding1TotalLineWith500DetailLinesToABankTransactionThrows() + public function testAddLineUpdatesCloseValue() { - $total_line_count = 501; - - $bank_transaction = new BankTransaction(); + $this->bankTransaction->setStartvalue(Money::EUR(100)); - $this->addTotalLineWithDescription($bank_transaction, '0'); + $totalLine = new BankTransactionLine(); + $totalLine + ->setLineType(LineType::TOTAL()) + ->setValue(Money::EUR(0)); - $this->expectException(\InvalidArgumentException::class); - - for ($i = 1; $i < $total_line_count; $i++) { - $this->addDetailLineWithDescription($bank_transaction, (string)$i); - } - } - - public function testAddLineThrowsAndIgnoresWhenAddingASecondTotalLine() - { - $bank_transaction = new BankTransaction(); + $detailLine1 = new BankTransactionLine(); + $detailLine1 + ->setLineType(LineType::DETAIL()) + ->setValue(Money::EUR(43555)); - $this->addTotalLineWithDescription($bank_transaction, '0'); + $detailLine2 = new BankTransactionLine(); + $detailLine2 + ->setLineType(LineType::DETAIL()) + ->setValue(Money::EUR(-43455)); - try { - $this->addTotalLineWithDescription($bank_transaction, '0'); + $this->bankTransaction->addLine($totalLine); + $this->bankTransaction->addLine($detailLine1); + $this->bankTransaction->addLine($detailLine2); - self::fail('An exception should have been thrown when adding a second total line'); - } catch (\InvalidArgumentException $e) { - self::assertCount(1, $bank_transaction->getLines()); - } + $this->assertEquals(Money::EUR(200), $this->bankTransaction->getClosevalue()); } } diff --git a/tests/UnitTests/DomDocuments/BankTransactionDocumentUnitTest.php b/tests/UnitTests/DomDocuments/BankTransactionDocumentUnitTest.php deleted file mode 100644 index e732c29f..00000000 --- a/tests/UnitTests/DomDocuments/BankTransactionDocumentUnitTest.php +++ /dev/null @@ -1,113 +0,0 @@ -document = new BankTransactionDocument(); - } - - public function testXmlIsCreatedPerSpec() - { - $transaction = new BankTransaction(); - $transaction->setDestiny(Destiny::TEMPORARY()); - $transaction->setAutoBalanceVat(true); - $transaction->setOffice(Office::fromCode("DEV-10000")); - $transaction->setStartvalue(Money::EUR(0)); - - $line1 = new Total(); - $line1->setValue(Money::EUR(121)); - $line1->setId(38861); - $line1->setVatTotal(Money::EUR(21)); - $line1->setVatBaseTotal(Money::EUR(21)); - $line1->setVatRepTotal(Money::EUR(21)); - $line1->setComment("Round House Kicks & Beard Fists"); - - $line2 = new Detail(); - $line2->setValue(Money::EUR(100)); - $line2->setId(38862); - $line2->setVatValue(Money::EUR(100)); // Not sure? - $line2->setVatBaseValue(Money::EUR(100)); - $line2->setVatRepValue(Money::EUR(100)); - - $line3 = new Detail(); - $line3->setValue(Money::EUR(-100)); - $line3->setId(38863); - $line3->setDestOffice(Office::fromCode("DEV-11000")); - - $line4 = new Vat(); - $line4->setValue(Money::EUR(21)); - $line4->setId(38864); - - $transaction->setLines([$line1, $line2, $line3, $line4]); - - $line3->setComment( - "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse facilisis lobortis arcu in tincidunt. Mauris urna enim, commodo nec feugiat quis, pharetra vel sem. Etiam ullamcorper eleifend tellus non viverra. Nulla facilisi. Donec sed orci aliquam." - ); - - $this->document->addBankTransaction($transaction); - - $this->assertXmlStringEqualsXmlString( - << - - -
- DEV-10000 - EUR - 0.00 - 0.21 -
- - - debit - 1.21 - 0.21 - 0.21 - 0.21 - Round House Kicks & Beard Fists - - - credit - 1.00 - 1.00 - 1.00 - 1.00 - - - debit - 1.00 - DEV-11000 - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse facilisis lobortis arcu in tincidunt. Mauris urna enim, commodo nec feugiat quis, pharetra vel sem. Etiam ullamcorper eleifend tellus non viverra. Nulla facilisi. Donec sed orci aliquam. - - - credit - 0.21 - - -
-
-XML - , - $this->document->saveXML() - ); - } -} \ No newline at end of file diff --git a/tests/UnitTests/Request/MappedResponseCollectionUnitTest.php b/tests/UnitTests/Request/MappedResponseCollectionUnitTest.php index 89bc98c8..7803c53a 100644 --- a/tests/UnitTests/Request/MappedResponseCollectionUnitTest.php +++ b/tests/UnitTests/Request/MappedResponseCollectionUnitTest.php @@ -2,7 +2,7 @@ namespace PhpTwinfield\UnitTests; -use PhpTwinfield\ApiConnectors\BankTransactionApiConnector; +use PhpTwinfield\ApiConnectors\TransactionApiConnector; use PhpTwinfield\Response\Response; use PhpTwinfield\Services\ProcessXmlService; use PHPUnit\Framework\TestCase; @@ -10,7 +10,7 @@ class MappedResponseCollectionUnitTest extends TestCase { /** - * @var BankTransactionApiConnector + * @var TransactionApiConnector */ protected $apiConnector; @@ -54,4 +54,4 @@ public function createFakeResponse() "); } -} \ No newline at end of file +}