Repository: horstoeko/zugferd (php)

Issue:
[ENHANCEMENT] Issue with Adding Multiple BT-29 Using ->setDocumentSeller() in BASIC Profile
Hi @horstoeko, 
**Describe the bug**

In the BASIC profile, I can't add multiple BT-29 with ->setDocumentSeller().
Only the last sellertradeparty taken into account is correct.
```xml
<ram:SellerTradeParty>
        <ram:ID>910</ram:ID>
        <ram:Name>Lieferant GmbH</ram:Name>
        <ram:PostalTradeAddress>
          <ram:CountryID>FR</ram:CountryID>
        </ram:PostalTradeAddress>
        <ram:SpecifiedTaxRegistration>
          <ram:ID schemeID="VA">6</ram:ID>
        </ram:SpecifiedTaxRegistration>
</ram:SellerTradeParty>
```

**To Reproduce**
```php 
$document
                ->setDocumentSeller("Lieferant GmbH", "549910")
                ->setDocumentSeller("Lieferant GmbH", "910");
```


Pull request description:
Added methods "addDocumentSellerId" and "addDocumentBuyerId" for adding additional ids (not global ids) for seller and buyer (#90)
Added methods "addDocumentSellerId" and "addDocumentBuyerId" for adding additional ids (not global ids) for seller and buyer (#90)

fixed #90 

Patch:
diff --git a/src/ZugferdDocumentBuilder.php b/src/ZugferdDocumentBuilder.php
index 0846c2e..d4f6be0 100644
--- a/src/ZugferdDocumentBuilder.php
+++ b/src/ZugferdDocumentBuilder.php
@@ -412,6 +412,19 @@ class ZugferdDocumentBuilder extends ZugferdDocument
         return $this;
     }
 
+    /**
+     * Add an id to the document seller
+     *
+     * @param  string|null $id          __BT-29, From BASIC WL__ An identifier of the seller. In many systems, seller identification is key information. Multiple seller IDs can be assigned or specified. They can be differentiated by using different identification schemes. If no scheme is given, it should be known to the buyer and seller, e.g. a previously exchanged, buyer-assigned identifier of the seller
+     * @return ZugferdDocumentBuilder
+     */
+    public function addDocumentSellerId(string $id): ZugferdDocumentBuilder
+    {
+        $sellerTradeParty = $this->getObjectHelper()->tryCallAndReturn($this->headerTradeAgreement, "getSellerTradeParty");
+        $this->getObjectHelper()->tryCall($sellerTradeParty, "addToID", $this->getObjectHelper()->getIdType($id));
+        return $this;
+    }
+
     /**
      * Add a global id for the seller
      *
@@ -556,6 +569,19 @@ class ZugferdDocumentBuilder extends ZugferdDocument
         return $this;
     }
 
+    /**
+     * Add an id to the document buyer
+     *
+     * @param  string|null $id          __BT-46, From BASIC WL__ An identifier of the buyer. In many systems, buyer identification is key information. Multiple buyer IDs can be assigned or specified. They can be differentiated by using different identification schemes. If no scheme is given, it should be known to the buyer and buyer, e.g. a previously exchanged, seller-assigned identifier of the buyer
+     * @return ZugferdDocumentBuilder
+     */
+    public function addDocumentBuyerId(string $id): ZugferdDocumentBuilder
+    {
+        $buyerTradeParty = $this->getObjectHelper()->tryCallAndReturn($this->headerTradeAgreement, "getBuyerTradeParty");
+        $this->getObjectHelper()->tryCall($buyerTradeParty, "addToID", $this->getObjectHelper()->getIdType($id));
+        return $this;
+    }
+
     /**
      * Add a global id for the buyer
      *


Test patch:
diff --git a/tests/testcases/BuilderEn16931Test.php b/tests/testcases/BuilderEn16931Test.php
index a804728..6633e1b 100644
--- a/tests/testcases/BuilderEn16931Test.php
+++ b/tests/testcases/BuilderEn16931Test.php
@@ -186,6 +186,21 @@ class BuilderEn16931Test extends TestCase
         $this->assertXPathNotExists('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:Name');
     }
 
+    /**
+     * @covers \horstoeko\zugferd\ZugferdDocumentBuilder::addDocumentSellerId
+     */
+    public function testAddDocumentSellerId(): void
+    {
+        $this->assertXPathValueWithIndex('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:ID', 0, "5499103");
+        $this->assertXPathNotExistsWithIndex('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:ID', 1);
+
+        (self::$document)->addDocumentSellerId('5499104');
+
+        $this->disableRenderXmlContent();
+        $this->assertXPathValueWithIndex('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:ID', 0, "5499103");
+        $this->assertXPathValueWithIndex('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:ID', 1, "5499104");
+    }
+
     /**
      * @covers \horstoeko\zugferd\ZugferdDocumentBuilder::addDocumentSellerGlobalId
      */
@@ -334,6 +349,21 @@ class BuilderEn16931Test extends TestCase
         $this->assertXPathValue('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:Name', "Kunden AG Mitte");
     }
 
+    /**
+     * @covers \horstoeko\zugferd\ZugferdDocumentBuilder::addDocumentBuyerId
+     */
+    public function testAddDocumentBuyerId(): void
+    {
+        $this->assertXPathValueWithIndex('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:ID', 0, "549910");
+        $this->assertXPathNotExistsWithIndex('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:ID', 1);
+
+        (self::$document)->addDocumentBuyerId('549911');
+
+        $this->disableRenderXmlContent();
+        $this->assertXPathValueWithIndex('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:ID', 0, "549910");
+        $this->assertXPathValueWithIndex('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:ID', 1, "549911");
+    }
+
     /**
      * @covers \horstoeko\zugferd\ZugferdDocumentBuilder::addDocumentBuyerGlobalId
      */
diff --git a/tests/testcases/BuilderExtendedTest.php b/tests/testcases/BuilderExtendedTest.php
index e9e9380..fd335e2 100644
--- a/tests/testcases/BuilderExtendedTest.php
+++ b/tests/testcases/BuilderExtendedTest.php
@@ -175,6 +175,21 @@ class BuilderExtendedTest extends TestCase
         $this->assertXPathValue('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:Name', "Lieferant GmbH");
     }
 
+    /**
+     * @covers \horstoeko\zugferd\ZugferdDocumentBuilder::addDocumentSellerId
+     */
+    public function testAddDocumentSellerId(): void
+    {
+        $this->assertXPathValueWithIndex('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:ID', 0, "549910");
+        $this->assertXPathNotExistsWithIndex('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:ID', 1);
+
+        (self::$document)->addDocumentSellerId('549911');
+
+        $this->disableRenderXmlContent();
+        $this->assertXPathValueWithIndex('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:ID', 0, "549910");
+        $this->assertXPathValueWithIndex('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:ID', 1, "549911");
+    }
+
     /**
      * @covers \horstoeko\zugferd\ZugferdDocumentBuilder::addDocumentSellerGlobalId
      */
@@ -328,6 +343,21 @@ class BuilderExtendedTest extends TestCase
         $this->assertXPathValue('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:Name', "Kunden AG Mitte");
     }
 
+    /**
+     * @covers \horstoeko\zugferd\ZugferdDocumentBuilder::addDocumentBuyerId
+     */
+    public function testAddDocumentBuyerId(): void
+    {
+        $this->assertXPathValueWithIndex('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:ID', 0, "549910");
+        $this->assertXPathNotExistsWithIndex('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:ID', 1);
+
+        (self::$document)->addDocumentBuyerId('549911');
+
+        $this->disableRenderXmlContent();
+        $this->assertXPathValueWithIndex('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:ID', 0, "549910");
+        $this->assertXPathValueWithIndex('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:ID', 1, "549911");
+    }
+
     /**
      * @covers \horstoeko\zugferd\ZugferdDocumentBuilder::addDocumentBuyerGlobalId
      */
diff --git a/tests/testcases/BuilderMinimumTest.php b/tests/testcases/BuilderMinimumTest.php
index a04c063..ee20254 100644
--- a/tests/testcases/BuilderMinimumTest.php
+++ b/tests/testcases/BuilderMinimumTest.php
@@ -189,6 +189,21 @@ class BuilderMinimumTest extends TestCase
         $this->assertXPathNotExists('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:Name');
     }
 
+    /**
+     * @covers \horstoeko\zugferd\ZugferdDocumentBuilder::addDocumentSellerId
+     */
+    public function testAddDocumentSellerId(): void
+    {
+        $this->assertXPathNotExists('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:ID', 0);
+        $this->assertXPathNotExists('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:ID', 1);
+
+        (self::$document)->addDocumentSellerId('549911');
+
+        $this->disableRenderXmlContent();
+        $this->assertXPathNotExists('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:ID', 0);
+        $this->assertXPathNotExists('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:ID', 1);
+    }
+
     /**
      * @covers \horstoeko\zugferd\ZugferdDocumentBuilder::addDocumentSellerGlobalId
      */
@@ -337,6 +352,21 @@ class BuilderMinimumTest extends TestCase
         $this->assertXPathValue('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:Name', "Kunden AG Mitte");
     }
 
+    /**
+     * @covers \horstoeko\zugferd\ZugferdDocumentBuilder::addDocumentBuyerId
+     */
+    public function testAddDocumentBuyerId(): void
+    {
+        $this->assertXPathNotExistsWithIndex('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:ID', 0);
+        $this->assertXPathNotExistsWithIndex('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:ID', 1);
+
+        (self::$document)->addDocumentBuyerId('549911');
+
+        $this->disableRenderXmlContent();
+        $this->assertXPathNotExistsWithIndex('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:ID', 0);
+        $this->assertXPathNotExistsWithIndex('/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:BuyerTradeParty/ram:ID', 1);
+    }
+
     /**
      * @covers \horstoeko\zugferd\ZugferdDocumentBuilder::addDocumentBuyerGlobalId
      */