Skip to content

Commit

Permalink
Added more tests while ensuring schematron tests pass for all profile…
Browse files Browse the repository at this point in the history
…s (and fixed formating)
  • Loading branch information
rahal committed Feb 6, 2025
1 parent 5008994 commit 08594cb
Show file tree
Hide file tree
Showing 9 changed files with 344 additions and 265 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ vendor
.idea
.DS_Store
.vscode
test/examples/basic-*
154 changes: 85 additions & 69 deletions src/FacturX.php

Large diffs are not rendered by default.

92 changes: 47 additions & 45 deletions src/Invoice.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@

namespace DigitalInvoice;


use Easybill\ZUGFeRD211\Model\DateTime;


class Invoice
{
public const FACTURX_MINIMUM = FacturX::MINIMUM;
Expand All @@ -21,7 +19,7 @@ class Invoice
public const UBL_NLCIUS = Ubl::NLCIUS;
public const UBL_CIUS_RO = Ubl::CIUS_RO;
public const UBL_CIUS_IT = Ubl::CIUS_IT;
public const UBL_CIUS_ES_FACE = Ubl::CIUS_ES_FACE;
public const UBL_CIUS_ES_FACE = Ubl::CIUS_ES_FACE;
public const UBL_CIUS_AT_GOV = Ubl::CIUS_AT_GOV;
public const UBL_CIUS_AT_NAT = Ubl::CIUS_AT_NAT;

Expand All @@ -37,7 +35,7 @@ class Invoice
public XmlGenerator $xmlGenerator;


protected $invoiceInformations=[];
protected $invoiceInformations = [];

public function __construct(
string $invoiceId,
Expand All @@ -47,49 +45,46 @@ public function __construct(
$profile = self::FACTURX_MINIMUM,
string|InvoiceTypeCode $invoiceType = InvoiceTypeCode::COMMERCIAL_INVOICE
) {
if(is_string($currency)) {
if (is_string($currency)) {
try {
$currency = CurrencyCode::from($currency);
} catch (\ValueError $e) {
throw new \Exception("$currency is not a valid Currency");
}
}
if(is_string($invoiceType)) {
if (is_string($invoiceType)) {
try {
$invoiceType = InvoiceTypeCode::from($invoiceType);
} catch (\ValueError $e) {
throw new \Exception("$invoiceType is not a valid Invoice Type");
}
}
$this->profile = $profile;
if ( in_array($profile, [Ubl::PEPPOL, Ubl::NLCIUS, Ubl::CIUS_RO, Ubl::CIUS_IT, Ubl::CIUS_ES_FACE, Ubl::CIUS_AT_GOV, Ubl::CIUS_AT_NAT] ) ){
if (in_array($profile, [Ubl::PEPPOL, Ubl::NLCIUS, Ubl::CIUS_RO, Ubl::CIUS_IT, Ubl::CIUS_ES_FACE, Ubl::CIUS_AT_GOV, Ubl::CIUS_AT_NAT])) {
$this->xmlGenerator = new Ubl($profile, $currency);
$this->profile = (new $profile)->getSpecification();
} elseif ( in_array($profile , [FacturX::MINIMUM , FacturX::BASIC_WL, FacturX::BASIC, FacturX::EN16931, FacturX::EXTENDED, FacturX::XRECHNUNG] ) ){
$this->profile = (new $profile())->getSpecification();
} elseif (in_array($profile, [FacturX::MINIMUM , FacturX::BASIC_WL, FacturX::BASIC, FacturX::EN16931, FacturX::EXTENDED, FacturX::XRECHNUNG])) {
$this->xmlGenerator = new FacturX($profile, $currency);
} else {
$this->xmlGenerator = new Zugferd($profile , $currency);
$this->xmlGenerator = new Zugferd($profile, $currency);
}
$this->invoiceInformations['profile'] = $profile;
$this->invoiceInformations['invoiceId'] = $invoiceId;
$this->invoiceInformations['date'] = $issueDate->format('Y-m-d');
$this->invoiceInformations['docTypeName'] = $invoiceType->value;
$this->xmlGenerator->initDocument( $invoiceId , $issueDate, $invoiceType, $deliveryDate);

$this->invoiceInformations['profile'] = $profile;
$this->invoiceInformations['invoiceId'] = $invoiceId;
$this->invoiceInformations['date'] = $issueDate->format('Y-m-d');
$this->invoiceInformations['docTypeName'] = $invoiceType->value;
$this->xmlGenerator->initDocument($invoiceId, $issueDate, $invoiceType, $deliveryDate);
}

public function getProfileLevel()
{
return $this->xmlGenerator->getProfileLevel();
}


public function setPrice(float $totalBasis, float $tax = 0)
{
$this->xmlGenerator->setPrice( $totalBasis, $tax );
$this->xmlGenerator->setPrice($totalBasis, $tax);
}


public function getXml()
{
return $this->xmlGenerator->getXml();
Expand All @@ -100,23 +95,20 @@ protected static function convertDate(\DateTime $date)
return DateTime::create(102, $date->format('Ymd'));
}


public function setBuyer(string $buyerReference, string $name, string $id = null)
{
$this->xmlGenerator->setBuyer( $buyerReference, $name, $id);

$this->xmlGenerator->setBuyer($buyerReference, $name, $id);
}

public function createAddress(string $postCode, string $city, string $countryCode, string $lineOne, ?string $lineTwo = null, ?string $lineThree = null)
{

return $this->xmlGenerator->createAddress( $postCode, $city, $countryCode, $lineOne, $lineTwo, $lineThree);
return $this->xmlGenerator->createAddress($postCode, $city, $countryCode, $lineOne, $lineTwo, $lineThree);
}


public function setBuyerAddress(string $lineOne, string $postCode, string $city, string $countryCode, ?string $lineTwo = null, ?string $lineThree = null)
{
$this->xmlGenerator->setBuyerAddress( $lineOne, $postCode, $city, $countryCode, $lineTwo, $lineThree);
$this->xmlGenerator->setBuyerAddress($lineOne, $postCode, $city, $countryCode, $lineTwo, $lineThree);
}

public function setSeller(string $id, string $idType, string $name, $tradingName = null)
Expand All @@ -127,13 +119,12 @@ public function setSeller(string $id, string $idType, string $name, $tradingName
throw new \Exception("$idType is an Invalide InternationalCodeDesignator");
}
$this->invoiceInformations['seller'] = $name;
$this->xmlGenerator->setSeller( $id, $idType, $name, $tradingName);

$this->xmlGenerator->setSeller($id, $idType, $name, $tradingName);
}

public function setSellerContact(?string $personName = null, ?string $telephone = null, ?string $email = null, ?string $departmentName = null)
{
$this->xmlGenerator->setSellerContact( $personName , $telephone, $email, $departmentName );

$this->xmlGenerator->setSellerContact($personName, $telephone, $email, $departmentName);
}

public function setSellerTaxRegistration(string $id, string $schemeID)
Expand All @@ -143,7 +134,8 @@ public function setSellerTaxRegistration(string $id, string $schemeID)

public function setSellerAddress(string $lineOne, string $postCode, string $city, string $countryCode, ?string $lineTwo = null, ?string $lineThree = null)
{
$this->xmlGenerator->setSellerAddress( $lineOne, $postCode, $city, $countryCode, $lineTwo, $lineThree);
$this->xmlGenerator->setSellerAddress($lineOne, $postCode, $city, $countryCode, $lineTwo, $lineThree);

return $this;
}

Expand All @@ -155,26 +147,32 @@ public function addItem(string $name, float $price, float $taxRatePercent, float
throw new \Exception("$unit is not a valide Unit of Unit Of Measurement");
}

$totalLineBasis = $this->xmlGenerator->addItem( $name, $price, $taxRatePercent, $quantity, $unit , $globalID , $globalIDCode);
// To be able to calc easily the invoice totals
$this->xmlGenerator->addTaxLine($taxRatePercent, $totalLineBasis);
$totalLineBasis = $this->xmlGenerator->addItem($name, $price, $taxRatePercent, $quantity, $unit, $globalID, $globalIDCode);
if ($totalLineBasis != 0) {
// To be able to calc easily the invoice totals
$this->xmlGenerator->addTaxLine($taxRatePercent, $totalLineBasis);
}
}

public function addPaymentMean(string $typeCode, ?string $ibanId = null,?string $accountName = null, ?string $bicId = null)
public function addPaymentMean(string $typeCode, ?string $ibanId = null, ?string $accountName = null, ?string $bicId = null)
{
try {
$typeCode = PaymentMeansCode::from($typeCode);
} catch (\ValueError $e) {
throw new \Exception("$typeCode is not a valide Unit of Unit Of Measurement");
}

$this->xmlGenerator->addPaymentMean($typeCode, $ibanId , $accountName, $bicId);
$this->xmlGenerator->addPaymentMean($typeCode, $ibanId, $accountName, $bicId);
}

public function setPaymentTerms(\DateTime $dueDate, ?string $description = null)
{
$this->xmlGenerator->setPaymentTerms($dueDate, $description);
}

public function addNote(string $content, ?string $subjectCode = null, ?string $contentCode = null)
{
$this->xmlGenerator->addNote( $content, $subjectCode, $contentCode);
$this->xmlGenerator->addNote($content, $subjectCode, $contentCode);
}

/**
Expand All @@ -189,34 +187,38 @@ public function validate(string $xml, bool $schematron = false): mixed
return $this->xmlGenerator->validate($xml, $schematron);
}


/**
* Generates a pdf string to be saved
*
* @param string $pdf
* @param boolean $addFacturxLogo
* @param bool $addFacturxLogo
* @param array $fpdiParams
* @return string
*/
public function getPdf($pdf , $addFacturxLogo = false )
public function getPdf($pdf, $addFacturxLogo = false, $fpdiParams = [])
{
if ( in_array( $this->profile, [static::ZUGFERD_BASIC, static::ZUGFERD_CONFORT, static::ZUGFERD_EXTENDED]) ){
if (in_array($this->profile, [static::ZUGFERD_BASIC, static::ZUGFERD_CONFORT, static::ZUGFERD_EXTENDED])) {
// Ensure false, there is no logo for those profiles
$addFacturxLogo = false;
}
$factureX = new PdfWriter();
$factureX->setPdfMetaData( $this->invoiceInformations);
$factureX->setPdfMetaData($this->invoiceInformations);

return $factureX->generateFacturxFromFiles(
$pdf,
$this->getXml(),
null,
true,
'',
[],
$addFacturxLogo );
$addFacturxLogo,
'Data',
$fpdiParams
);
}

public function addEmbeddedAttachment( ?string $id, ?string $scheme, ?string $filename, ?string $contents, ?string $mimeCode, ?string $description ){
$this->xmlGenerator->addEmbeddedAttachment( $id,$scheme, $filename, $contents, $mimeCode, $description );
public function addEmbeddedAttachment(?string $id, ?string $scheme, ?string $filename, ?string $contents, ?string $mimeCode, ?string $description)
{
$this->xmlGenerator->addEmbeddedAttachment($id, $scheme, $filename, $contents, $mimeCode, $description);
}

}
19 changes: 10 additions & 9 deletions src/Types.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ trait EnumToArray
public static function valueArray(): array
{
foreach (self::cases() as $enum) {
$values[$enum->value] = str_replace( '_' , ' ', $enum->name);
$values[$enum->value] = str_replace('_', ' ', $enum->name);
}

return $values;
Expand All @@ -27,17 +27,18 @@ public static function valueArray(): array
* Helper Types class to access type enum values.
* Can be used to generate select boxes easily.
*/
class Types {

public static function getInternationalCodes(){
return InternationalCodeDesignator::valueArray();
}
class Types
{
public static function getInternationalCodes()
{
return InternationalCodeDesignator::valueArray();
}
}

enum PaymentMeansCode: string
{
use EnumToArray;

case INSTRUMENT_NOT_DEFINED = "1";
case AUTOMATED_CLEARING_HOUSE_CREDIT = "2";
case AUTOMATED_CLEARING_HOUSE_DEBIT = "3";
Expand Down Expand Up @@ -2435,7 +2436,7 @@ enum CurrencyCode: string
case SOMONI = "TJS";
case TURKMENISTAN_NEW_MANAT = "TMT";
case TUNISIAN_DINAR = "TND";
case PA_ANGA = "TOP";
case PA_ANGA = "TOP";
case TURKISH_LIRA = "TRY";
case TRINIDAD_AND_TOBAGO_DOLLAR = "TTD";
case NEW_TAIWAN_DOLLAR = "TWD";
Expand Down Expand Up @@ -2479,7 +2480,7 @@ enum CurrencyCode: string
enum InvoiceTypeCode: string
{
use EnumToArray;

// https://service.unece.org/trade/untdid/d16b/tred/tred1001.htm
case DEBIT_NOTE_RELATED_TO_GOODS_OR_SERVICES = '80';
case CREDIT_NOTE_RELATED_TO_GOODS_OR_SERVICES = '81';
Expand Down
Loading

0 comments on commit 08594cb

Please sign in to comment.