Skip to content

Commit 0758bc6

Browse files
authored
Merge pull request #86 from php-twinfield/85-return-match-set-collection
Fixes #85 - Return match set collection
2 parents 641fc3d + 176ada3 commit 0758bc6

File tree

8 files changed

+320
-20
lines changed

8 files changed

+320
-20
lines changed

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ cache:
1212
- $HOME/.composer/cache
1313

1414
install:
15-
- travis_retry composer install --no-interaction --classmap-authoritative
15+
- travis_retry composer install --no-interaction --no-suggest
1616

1717
script:
1818
- composer validate --strict
1919
- find src tests -name '*.php' | xargs -n 1 -P4 php -l
20-
- vendor/bin/phpunit
20+
- vendor/bin/phpunit --fail-on-risky

phpunit.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
44
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/6.3/phpunit.xsd"
55
backupGlobals="false"
6+
beStrictAboutOutputDuringTests="true"
67
colors="true"
78
convertErrorsToExceptions="true"
89
convertNoticesToExceptions="true"

src/ApiConnectors/MatchesApiConnector.php

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
use PhpTwinfield\DomDocuments\MatchDocument;
66
use PhpTwinfield\Exception;
7+
use PhpTwinfield\Mappers\MatchSetMapper;
78
use PhpTwinfield\MatchSet;
9+
use PhpTwinfield\Response\IndividualMappedResponse;
10+
use PhpTwinfield\Response\MappedResponseCollection;
811
use PhpTwinfield\Response\Response;
912
use Webmozart\Assert\Assert;
1013

@@ -15,19 +18,19 @@
1518
class MatchesApiConnector extends BaseApiConnector
1619
{
1720
/**
18-
* @param MatchSet $matchSet
1921
* @throws Exception
2022
*/
21-
public function send(MatchSet $matchSet): void
23+
public function send(MatchSet $matchSet): MatchSet
2224
{
23-
$this->sendAll([$matchSet]);
25+
return $this->sendAll([$matchSet])[0]->unwrap();
2426
}
2527

2628
/**
27-
* @param MatchSet[] $matchSets
29+
* @return MappedResponseCollection|IndividualMappedResponse[]
30+
*
2831
* @throws Exception
2932
*/
30-
public function sendAll(array $matchSets): void
33+
public function sendAll(array $matchSets): MappedResponseCollection
3134
{
3235
Assert::allIsInstanceOf($matchSets, MatchSet::class);
3336

@@ -45,8 +48,8 @@ public function sendAll(array $matchSets): void
4548
$responses[] = $this->sendXmlDocument($document);
4649
}
4750

48-
foreach ($responses as $response) {
49-
$response->assertSuccessful();
50-
}
51+
return $this->getProcessXmlService()->mapAll($responses, "set", function (Response $subResponse): MatchSet {
52+
return MatchSetMapper::map($subResponse->getResponseDocument());
53+
});
5154
}
5255
}

src/Mappers/BankTransactionMapper.php

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -195,14 +195,4 @@ private static function setBankTransactionLinePerformanceFields(\DOMElement $lin
195195
$line->setPerformanceDate($performanceDate);
196196
}
197197
}
198-
199-
private static function getField(\DOMElement $element, string $fieldTagName): ?string
200-
{
201-
$fieldElement = $element->getElementsByTagName($fieldTagName)->item(0);
202-
if (!isset($fieldElement)) {
203-
return null;
204-
}
205-
206-
return $fieldElement->textContent;
207-
}
208198
}

src/Mappers/BaseMapper.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,14 @@ protected static function getValueFromTag(\DOMDocument $document, string $tag):
6161

6262
return $element->textContent;
6363
}
64+
65+
protected static function getField(\DOMElement $element, string $fieldTagName): ?string
66+
{
67+
$fieldElement = $element->getElementsByTagName($fieldTagName)->item(0);
68+
if (!isset($fieldElement)) {
69+
return null;
70+
}
71+
72+
return $fieldElement->textContent;
73+
}
6474
}

src/Mappers/MatchSetMapper.php

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
namespace PhpTwinfield\Mappers;
3+
4+
use Money\Currency;
5+
use Money\Money;
6+
use PhpTwinfield\Enums\MatchCode;
7+
use PhpTwinfield\MatchLine;
8+
use PhpTwinfield\MatchReference;
9+
use PhpTwinfield\MatchReferenceInterface;
10+
use PhpTwinfield\MatchSet;
11+
use PhpTwinfield\Office;
12+
use PhpTwinfield\Util;
13+
14+
class MatchSetMapper extends BaseMapper
15+
{
16+
/**
17+
* TODO: This does not contain all fields from the MatchLine
18+
*
19+
* @return MatchSet
20+
*/
21+
public static function map(\DOMDocument $document): MatchSet
22+
{
23+
$matchSet = self::createMatchSetFrom($document);
24+
25+
self::addLines($document, $matchSet);
26+
27+
return $matchSet;
28+
}
29+
30+
private static function createMatchSetFrom(\DOMDocument $document): MatchSet
31+
{
32+
$matchSet = new MatchSet();
33+
34+
$matchSet->setOffice(Office::fromCode(self::getValueFromTag($document, "office")));
35+
$matchSet->setMatchCode(new MatchCode(self::getValueFromTag($document, "matchcode")));
36+
$matchSet->setMatchDate(
37+
\DateTimeImmutable::createFromFormat("Ymd", self::getValueFromTag($document, "matchdate"))
38+
);
39+
40+
return $matchSet;
41+
}
42+
43+
private static function addLines(\DOMDocument $document, MatchSet $matchSet): void
44+
{
45+
$element = $document->documentElement;
46+
47+
/** @var \DOMElement $lineElement */
48+
foreach ($element->getElementsByTagName("line") as $lineElement) {
49+
MatchLine::addToMatchSet(
50+
$matchSet,
51+
self::getMatchReferenceFrom($lineElement, $matchSet->getOffice()),
52+
self::getMatchValueFrom($lineElement)
53+
);
54+
}
55+
}
56+
57+
private static function getMatchReferenceFrom(
58+
\DOMElement $lineElement,
59+
Office $office
60+
): MatchReferenceInterface {
61+
return new MatchReference(
62+
$office,
63+
self::getField($lineElement, 'transcode'),
64+
self::getField($lineElement, 'transnumber'),
65+
self::getField($lineElement, 'transline')
66+
);
67+
}
68+
69+
private static function getMatchValueFrom(\DOMElement $lineElement): ?Money
70+
{
71+
$matchValue = self::getField($lineElement, 'matchvalue');
72+
73+
if ($matchValue === null) {
74+
return null;
75+
}
76+
77+
// TODO: Perhaps not hard code this to EUR, but the element doesn't seem to contain a currency
78+
return Util::parseMoney($matchValue, new Currency('EUR'));
79+
}
80+
}
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
<?php
2+
3+
namespace PhpTwinfield\UnitTests;
4+
5+
use Money\Currency;
6+
use Money\Money;
7+
use PhpTwinfield\ApiConnectors\BankTransactionApiConnector;
8+
use PhpTwinfield\ApiConnectors\MatchesApiConnector;
9+
use PhpTwinfield\BankTransaction;
10+
use PhpTwinfield\Enums\Destiny;
11+
use PhpTwinfield\Enums\LineType;
12+
use PhpTwinfield\Enums\MatchCode;
13+
use PhpTwinfield\Exception;
14+
use PhpTwinfield\MatchLine;
15+
use PhpTwinfield\MatchSet;
16+
use PhpTwinfield\Office;
17+
use PhpTwinfield\Response\Response;
18+
use PhpTwinfield\Response\ResponseException;
19+
use PhpTwinfield\Secure\AuthenticatedConnection;
20+
use PhpTwinfield\Services\ProcessXmlService;
21+
use PhpTwinfield\Transactions\BankTransactionLine\Detail;
22+
use PhpTwinfield\Transactions\BankTransactionLine\Total;
23+
use PhpTwinfield\Transactions\BankTransactionLine\Vat;
24+
use PHPUnit\Framework\TestCase;
25+
26+
class MatchesApiConnectorTest extends TestCase
27+
{
28+
/**
29+
* @var MatchesApiConnector
30+
*/
31+
protected $apiConnector;
32+
33+
/**
34+
* @var ProcessXmlService|\PHPUnit_Framework_MockObject_MockObject
35+
*/
36+
protected $processXmlService;
37+
38+
protected function setUp()
39+
{
40+
parent::setUp();
41+
42+
$this->processXmlService = $this->getMockBuilder(ProcessXmlService::class)
43+
->setMethods(["sendDocument"])
44+
->disableOriginalConstructor()
45+
->getMock();
46+
47+
/** @var AuthenticatedConnection|\PHPUnit_Framework_MockObject_MockObject $connection */
48+
$connection = $this->createMock(AuthenticatedConnection::class);
49+
$connection
50+
->expects($this->any())
51+
->method("getAuthenticatedClient")
52+
->willReturn($this->processXmlService);
53+
54+
$this->apiConnector = new MatchesApiConnector($connection);
55+
}
56+
57+
private function createMatchSet(): MatchSet
58+
{
59+
$matchSet = new MatchSet();
60+
$matchSet->setOffice(Office::fromCode("OFFICE001"));
61+
$matchSet->setMatchCode(MatchCode::CUSTOMERS());
62+
$matchSet->setMatchDate(new \DateTimeImmutable("2018-02-19"));
63+
64+
return $matchSet;
65+
}
66+
67+
public function testSendAllReturnsMappedObjects()
68+
{
69+
$response = Response::fromString(file_get_contents(
70+
__DIR__."/resources/single-matchset.xml"
71+
));
72+
73+
$this->processXmlService->expects($this->once())
74+
->method("sendDocument")
75+
->willReturn($response);
76+
77+
$responses = $this->apiConnector->sendAll([
78+
$this->createMatchSet(),
79+
$this->createMatchSet()
80+
]);
81+
82+
$this->assertCount(2, $responses);
83+
84+
self::assertSame(1, $responses->countFailedResponses());
85+
self::assertSame(1, $responses->countSuccessfulResponses());
86+
87+
[$response1, $response2] = $responses;
88+
89+
/** @var MatchSet $matchSet */
90+
$matchSet = $response1->unwrap();
91+
92+
$this->assertEquals("OFFICE001", $matchSet->getOffice()->getCode());
93+
$this->assertEquals(MatchCode::CUSTOMERS(), $matchSet->getMatchCode());
94+
$this->assertEquals("2018-02-19", $matchSet->getMatchDate()->format('Y-m-d'));
95+
96+
$lines = $matchSet->getLines();
97+
$this->assertCount(2, $lines);
98+
99+
$line = $lines[0];
100+
$this->assertEquals("VRK", $line->getTranscode());
101+
$this->assertSame(201700103, $line->getTransnumber());
102+
$this->assertSame(1, $line->getTransline());
103+
$this->assertEquals(Money::EUR(526), $line->getMatchValue());
104+
105+
$line = $lines[1];
106+
$this->assertEquals("DUM2", $line->getTranscode());
107+
$this->assertSame(201700029, $line->getTransnumber());
108+
$this->assertSame(79, $line->getTransline());
109+
$this->assertEquals(Money::EUR(-526), $line->getMatchValue());
110+
111+
/** @var MatchSet $matchSet */
112+
try {
113+
$matchSet = $response2->unwrap();
114+
} catch (ResponseException $e) {
115+
$matchSet = $e->getReturnedObject();
116+
}
117+
118+
$this->assertEquals("OFFICE001", $matchSet->getOffice()->getCode());
119+
$this->assertEquals(MatchCode::CUSTOMERS(), $matchSet->getMatchCode());
120+
$this->assertEquals("2018-02-19", $matchSet->getMatchDate()->format('Y-m-d'));
121+
122+
$lines = $matchSet->getLines();
123+
$this->assertCount(2, $lines);
124+
125+
$line = $lines[0];
126+
$this->assertEquals("VRK", $line->getTranscode());
127+
$this->assertSame(201700100, $line->getTransnumber());
128+
$this->assertSame(1, $line->getTransline());
129+
$this->assertEquals(Money::EUR(140), $line->getMatchValue());
130+
131+
$line = $lines[1];
132+
$this->assertEquals("DUM2", $line->getTranscode());
133+
$this->assertSame(201700029, $line->getTransnumber());
134+
$this->assertSame(64, $line->getTransline());
135+
$this->assertEquals(Money::EUR(-140), $line->getMatchValue());
136+
}
137+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?xml version="1.0"?>
2+
<sets>
3+
<set result="1">
4+
<office>OFFICE001</office>
5+
<matchcode name="Debiteuren afletteren">170</matchcode>
6+
<matchdate>20180219</matchdate>
7+
<lines>
8+
<line result="1">
9+
<transcode name="Verkoopfactuur" shortname="Verkoop">VRK</transcode>
10+
<transnumber>201700103</transnumber>
11+
<transline>1</transline>
12+
<matchvalue>5.26</matchvalue>
13+
<origin>import</origin>
14+
<status>temporary</status>
15+
<dim1>130000</dim1>
16+
<dim2>D158871</dim2>
17+
<matchlevel>2</matchlevel>
18+
<basevalueopen>12.63</basevalueopen>
19+
<repvalueopen>12.63</repvalueopen>
20+
<valueopen>12.63</valueopen>
21+
<matchvaluerep>5.26</matchvaluerep>
22+
<matchvaluecur>5.26</matchvaluecur>
23+
</line>
24+
<line result="1">
25+
<transcode name="Some Dummy Bank Account" shortname="Some Dummy Bank Acco">DUM2</transcode>
26+
<transnumber>201700029</transnumber>
27+
<transline>79</transline>
28+
<matchvalue>-5.26</matchvalue>
29+
<origin>import</origin>
30+
<status>temporary</status>
31+
<dim1>130000</dim1>
32+
<dim2>1234567</dim2>
33+
<matchlevel>2</matchlevel>
34+
<basevalueopen>-5.26</basevalueopen>
35+
<repvalueopen>-5.26</repvalueopen>
36+
<valueopen>-5.26</valueopen>
37+
<matchvaluerep>-5.26</matchvaluerep>
38+
<matchvaluecur>-5.26</matchvaluecur>
39+
</line>
40+
</lines>
41+
<dimensions>
42+
<dimension level="2" matchnumber="1">1234567</dimension>
43+
</dimensions>
44+
<value>0.00</value>
45+
</set>
46+
<set result="0">
47+
<office>OFFICE001</office>
48+
<matchcode name="Debiteuren afletteren">170</matchcode>
49+
<matchdate>20180219</matchdate>
50+
<lines result="0">
51+
<line msgtype="error" msg="De regel bestaat niet." result="0">
52+
<transcode>VRK</transcode>
53+
<transnumber>201700100</transnumber>
54+
<transline>1</transline>
55+
<matchvalue>1.40</matchvalue>
56+
</line>
57+
<line result="1">
58+
<transcode name="Some Dummy Bank Account" shortname="Some Dummy Bank Acco">DUM2</transcode>
59+
<transnumber>201700029</transnumber>
60+
<transline>64</transline>
61+
<matchvalue>-1.40</matchvalue>
62+
<origin>import</origin>
63+
<status>temporary</status>
64+
<dim1>130000</dim1>
65+
<dim2>12345678</dim2>
66+
<matchlevel>2</matchlevel>
67+
<basevalueopen>-1.40</basevalueopen>
68+
<repvalueopen>-1.40</repvalueopen>
69+
<valueopen>-1.40</valueopen>
70+
<matchvaluerep>-1.40</matchvaluerep>
71+
<matchvaluecur>-1.40</matchvaluecur>
72+
</line>
73+
</lines>
74+
<dimensions>
75+
<dimension level="2">12345678</dimension>
76+
</dimensions>
77+
<value>-1.40</value>
78+
</set>
79+
</sets>

0 commit comments

Comments
 (0)