packages/xml-parser/src/Xml/Parser/SummaryParser.php
<?php
/**
* Created by PhpStorm.
* User: Giansalex
* Date: 28/01/2018
* Time: 13:04
*/
declare(strict_types=1);
namespace Greenter\Xml\Parser;
use DateTime;
use DOMElement;
use DOMNode;
use Greenter\Model\Company\Company;
use Greenter\Model\DocumentInterface;
use Greenter\Model\Sale\Document;
use Greenter\Model\Summary\Summary;
use Greenter\Model\Summary\SummaryDetail;
use Greenter\Model\Summary\SummaryPerception;
use Greenter\Parser\DocumentParserInterface;
use Greenter\Xml\XmlReader;
/**
* Class SummaryParser
* @package Greenter\Xml\Parser
*/
class SummaryParser implements DocumentParserInterface
{
use XmlLoaderTrait;
/**
* @var XmlReader
*/
private $reader;
/**
* @var DOMElement
*/
private $rootNode;
/**
* @param mixed $value
*
* @return DocumentInterface
*/
public function parse($value): ?DocumentInterface
{
$this->reader = $this->load($value);
$xml = $this->reader;
$root = $this->rootNode = $xml->getXpath()->document->documentElement;
$id = explode('-', $xml->getValue('cbc:ID', $root));
$summary = new Summary();
$summary->setCorrelativo($id[2])
->setFecGeneracion(new DateTime($xml->getValue('cbc:ReferenceDate', $root)))
->setFecResumen(new DateTime($xml->getValue('cbc:IssueDate', $root)))
->setCompany($this->getCompany())
->setDetails(iterator_to_array($this->getDetails()));
return $summary;
}
private function getCompany()
{
$xml = $this->reader;
$node = $xml->getNode('cac:AccountingSupplierParty', $this->rootNode);
$cl = new Company();
$cl->setRuc($xml->getValue('cbc:CustomerAssignedAccountID', $node))
->setNombreComercial($xml->getValue('cac:Party/cac:PartyName/cbc:Name', $node))
->setRazonSocial($xml->getValue('cac:Party/cac:PartyLegalEntity/cbc:RegistrationName', $node));
return $cl;
}
private function getDetails()
{
$xml = $this->reader;
$nodes = $xml->getNodes('sac:SummaryDocumentsLine', $this->rootNode);
foreach ($nodes as $node) {
$det = new SummaryDetail();
$det->setTipoDoc($xml->getValue('cbc:DocumentTypeCode', $node))
->setSerieNro($xml->getValue('cbc:ID', $node))
->setEstado(trim($xml->getValue('cac:Status/cbc:ConditionCode', $node)))
->setClienteTipo(trim($xml->getValue('cac:AccountingCustomerParty/cbc:AdditionalAccountID', $node)))
->setClienteNro(trim($xml->getValue('cac:AccountingCustomerParty/cbc:CustomerAssignedAccountID', $node)))
->setTotal((float)$xml->getValue('sac:TotalAmount', $node, '0'))
->setMtoOtrosCargos((float)$xml->getValue('cac:AllowanceCharge/cbc:Amount', $node, '0'));
$ref = $xml->getNode('cac:BillingReference', $node);
if ($ref) {
$doc = new Document();
$doc->setTipoDoc(trim($xml->getValue('cac:InvoiceDocumentReference/cbc:DocumentTypeCode', $ref)))
->setNroDoc(trim($xml->getValue('cac:InvoiceDocumentReference/cbc:ID', $ref)));
$det->setDocReferencia($doc);
}
$this->loadPerception($det, $node);
$this->loadTotals($det, $node);
$this->loadTaxs($det, $node);
yield $det;
}
}
private function loadPerception(SummaryDetail $detail, ?DOMNode $node): void
{
$xml = $this->reader;
$ref = $xml->getNode('sac:SUNATPerceptionSummaryDocumentReference', $node);
if ($ref === null) {
return;
}
$perc = new SummaryPerception();
$perc->setCodReg(trim($xml->getValue('sac:SUNATPerceptionSystemCode', $ref)))
->setTasa((float)$xml->getValue('sac:SUNATPerceptionPercent', $ref, '0'))
->setMto((float)$xml->getValue('sac:TotalInvoiceAmount', $ref, '0'))
->setMtoTotal((float)$xml->getValue('sac:SUNATTotalCashed', $ref, '0'))
->setMtoBase((float)$xml->getValue('sac:TaxableAmount', $ref, '0'));
$detail->setPercepcion($perc);
}
private function loadTotals(SummaryDetail $detail, ?DOMNode $node): void
{
$xml = $this->reader;
$totals = $xml->getNodes('sac:BillingPayment', $node);
foreach ($totals as $total) {
/**@var $total \DOMElement*/
$id = trim($xml->getValue('cbc:InstructionID', $total));
$val = (float)$xml->getValue('cbc:PaidAmount', $total, '0');
switch ($id) {
case '01':
$detail->setMtoOperGravadas($val);
break;
case '02':
$detail->setMtoOperExoneradas($val);
break;
case '03':
$detail->setMtoOperInafectas($val);
break;
case '05':
$detail->setMtoOperGratuitas($val);
break;
}
}
}
private function loadTaxs(SummaryDetail $detail, ?DOMNode $node): void
{
$xml = $this->reader;
$taxs = $xml->getNodes('cac:TaxTotal', $node);
foreach ($taxs as $tax) {
$name = trim($xml->getValue('cac:TaxSubtotal/cac:TaxCategory/cac:TaxScheme/cbc:Name', $tax));
$val = (float)$xml->getValue('cbc:TaxAmount', $tax, '0');
switch ($name) {
case 'IGV':
$detail->setMtoIGV($val);
break;
case 'ISC':
$detail->setMtoISC($val);
break;
case 'OTROS':
$detail->setMtoOtrosTributos($val);
break;
}
}
}
}