packages/xml-parser/src/Xml/Parser/DespatchParser.php
<?php
/**
* Created by PhpStorm.
* User: Administrador
* Date: 30/10/2017
* Time: 05:33 PM
*/
declare(strict_types=1);
namespace Greenter\Xml\Parser;
use DateTime;
use DOMElement;
use Greenter\Model\Client\Client;
use Greenter\Model\Company\Company;
use Greenter\Model\Despatch\Despatch;
use Greenter\Model\Despatch\DespatchDetail;
use Greenter\Model\Despatch\Direction;
use Greenter\Model\Despatch\Shipment;
use Greenter\Model\Despatch\Transportist;
use Greenter\Model\DocumentInterface;
use Greenter\Model\Sale\Document;
use Greenter\Parser\DocumentParserInterface;
use Greenter\Xml\XmlReader;
/**
* Class DespatchParser
* @package Greenter\Xml\Parser
*/
class DespatchParser 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;
$guia = new Despatch();
$docGuia = explode('-', $xml->getValue('cbc:ID', $root));
$guia->setSerie($docGuia[0])
->setCorrelativo($docGuia[1])
->setTipoDoc($xml->getValue('cbc:DespatchAdviceTypeCode', $root))
->setObservacion($xml->getValue('cbc:Note', $root))
->setFechaEmision(new DateTime($xml->getValue('cbc:IssueDate', $root)))
->setCompany($this->getCompany())
->setDestinatario($this->getClient('cac:DeliveryCustomerParty'))
->setTercero($this->getClient('cac:SellerSupplierParty'))
->setEnvio($this->getShipment())
->setDetails(iterator_to_array($this->getDetails()));
$this->loadRelDocs($guia);
return $guia;
}
private function getClient(string $nodeName)
{
$xml = $this->reader;
$node = $xml->getNode($nodeName, $this->rootNode);
$docNode = $xml->getNode('cbc:CustomerAssignedAccountID', $node);
if (!$docNode) {
return null;
}
$cl = new Client();
$cl->setNumDoc($docNode->nodeValue)
->setTipoDoc($docNode->getAttribute('schemeID'))
->setRznSocial($xml->getValue('cac:Party/cac:PartyLegalEntity/cbc:RegistrationName', $node));
return $cl;
}
private function getCompany()
{
$xml = $this->reader;
$node = $xml->getNode('cac:DespatchSupplierParty', $this->rootNode);
$cl = new Company();
$cl->setRuc($xml->getValue('cbc:CustomerAssignedAccountID', $node))
->setRazonSocial($xml->getValue('cac:Party/cac:PartyLegalEntity/cbc:RegistrationName', $node));
return $cl;
}
private function loadRelDocs(Despatch $despatch)
{
$xml = $this->reader;
$bajaNode = $xml->getNode('cac:OrderReference', $this->rootNode);
if ($bajaNode) {
$baja = new Document();
$baja->setTipoDoc($xml->getValue('cbc:OrderTypeCode', $bajaNode))
->setNroDoc($xml->getValue('cbc:ID', $bajaNode));
$despatch->setDocBaja($baja);
}
$relDoc = $xml->getNode('cac:AdditionalDocumentReference', $this->rootNode);
if ($relDoc) {
$rel = new Document();
$rel->setTipoDoc($xml->getValue('cbc:OrderTypeCode', $relDoc))
->setNroDoc($xml->getValue('cbc:ID', $relDoc));
$despatch->setRelDoc($rel);
}
}
private function getShipment()
{
$xml = $this->reader;
$node = $xml->getNode('cac:Shipment', $this->rootNode);
$shp = new Shipment();
$shp->setCodTraslado($xml->getValue('cbc:HandlingCode', $node))
->setDesTraslado($xml->getValue('cbc:Information', $node))
->setNumBultos((int)$xml->getValue('cbc:TotalTransportHandlingUnitQuantity', $node, '0'))
->setIndTransbordo($xml->getValue('cbc:SplitConsignmentIndicator', $node, 'false') == 'true')
->setNumContenedor($xml->getValue('cac:TransportHandlingUnit/cbc:ID', $node))
->setCodPuerto($xml->getValue('cac:FirstArrivalPortLocation/cbc:ID', $node));
$otNode = $xml->getNode('cbc:GrossWeightMeasure', $node);
if ($otNode) {
$shp->setUndPesoTotal($otNode->getAttribute('unitCode'))
->setPesoTotal((float)$otNode->nodeValue);
}
$otNode = $xml->getNode('cac:Delivery/cac:DeliveryAddress', $node);
if ($otNode) {
$shp->setLlegada(new Direction($xml->getValue('cbc:ID', $otNode), $xml->getValue('cbc:StreetName', $otNode)));
}
$otNode = $xml->getNode('cac:OriginAddress', $node);
if ($otNode) {
$shp->setPartida(new Direction($xml->getValue('cbc:ID', $otNode), $xml->getValue('cbc:StreetName', $otNode)));
}
$otNode = $xml->getNode('cac:ShipmentStage', $node);
$shp->setModTraslado($xml->getValue('cbc:TransportModeCode', $otNode))
->setFecTraslado(new DateTime($xml->getValue('cac:TransitPeriod/cbc:StartDate', $otNode)))
->setTransportista($this->getTransportista($otNode));
return $shp;
}
/**
* @param DOMElement|null $node
*/
private function getTransportista(?DOMElement $node)
{
$xml = $this->reader;
$trans = new Transportist();
$othNode = $xml->getNode('cac:CarrierParty', $node);
if ($othNode) {
$idNode = $xml->getNode('cac:PartyIdentification/cbc:ID', $othNode);
$trans->setTipoDoc($idNode->getAttribute('schemeID'))
->setNumDoc($idNode->nodeValue)
->setRznSocial($xml->getValue('cac:PartyName/cbc:Name', $othNode));
}
$trans->setPlaca($xml->getValue('cac:TransportMeans/cac:RoadTransport/cbc:LicensePlateID', $node));
$othNode = $xml->getNode('cac:DriverPerson/cbc:ID', $node);
if ($othNode) {
$trans->setChoferTipoDoc($othNode->getAttribute('schemeID'))
->setChoferDoc($othNode->nodeValue);
}
return $trans;
}
private function getDetails()
{
$xml = $this->reader;
$nodes = $xml->getNodes('cac:DespatchLine', $this->rootNode);
foreach ($nodes as $node) {
$quantity = $xml->getNode('cbc:DeliveredQuantity', $node);
$det = new DespatchDetail();
$det->setCantidad((float)$quantity->nodeValue)
->setUnidad($quantity->getAttribute('unitCode'))
->setDescripcion($xml->getValue('cac:Item/cbc:Name', $node))
->setCodigo($xml->getValue('cac:Item/cac:SellersItemIdentification/cbc:ID', $node))
->setCodProdSunat($xml->getValue('cac:Item/cac:CommodityClassification/cbc:ItemClassificationCode', $node));
yield $det;
}
}
}