Skip to content

Commit

Permalink
Merge pull request #97 from gam04/feature/retenciones20
Browse files Browse the repository at this point in the history
Feature/retenciones20, closes #96
  • Loading branch information
eclipxe13 authored May 15, 2022
2 parents 7c501be + fe8bfe5 commit 4b03974
Show file tree
Hide file tree
Showing 28 changed files with 1,192 additions and 161 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,14 @@ composer require eclipxe/cfdiutils
- Version 3.x **future** will be released with backward compatibility breaks.
- See [docs/CHANGELOG.md](docs/CHANGELOG.md) for backward compatibility breaks.
- It may change to PHP 8.0.
- It could be possible to migrate to phpcfdi/cfdi-utils under [phpCfdi][] organization.
- It could be possible to migrate to `phpcfdi/cfdi-utils` under [phpCfdi][] organization.


## PHP Support

This library is compatible with **PHP 7.3 and above**. Please, try to use the language's full potential.

The intended support is to be aligned with oldest *Active support* PHP Branch.
The intended support is to be aligned with the oldest *Active support* PHP Branch.
See <https://www.php.net/supported-versions.php> for more details.

| CfdiUtils | PHP Supported versions | Since |
Expand Down
166 changes: 90 additions & 76 deletions docs/CHANGELOG.md

Large diffs are not rendered by default.

75 changes: 73 additions & 2 deletions docs/crear/cfdi-de-retenciones-e-informacion-de-pagos.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,16 @@ La estrategia para crear este un CFDI de retenciones es la misma que para [crear
Consulta la información relacionada con el uso de [elementos](../componentes/elements.md),
[nodos](../componentes/nodes.md) y [complementos no implementados](../crear/complementos-aun-no-implementados.md).

## Ejemplo de creación de un CFDI de retenciones e información de pagos
## Validaciones

Al momento de validar un CFDI de retenciones e información de pagos solamente se está comprobando que efectivamente
se siga el esquema XSD. A diferencia de la creación de CFDI Regulares donde se incluyen múltiples validadores.

## Ejemplo de creación de un CFDI de retenciones e información de pagos versión 1.0

```php
<?php
// creator es un objeto de ayuda, similar a CfdiCreator33
// creator es un objeto de ayuda, similar a CfdiCreator40
$creator = new \CfdiUtils\Retenciones\RetencionesCreator10([
'FechaExp' => '2019-01-23T08:00:00-06:00',
'CveRetenc' => '14', // Dividendos o utilidades distribuidos
Expand Down Expand Up @@ -67,3 +72,69 @@ $asserts = $creator->validate();
// guardar el precfdi
file_put_contents('precfdi.xml', $creator->asXml());
```

## Ejemplo de creación de un CFDI de retenciones e información de pagos versión 2.0

```php
// creator es un objeto de ayuda, similar a CfdiCreator40
$creator = new RetencionesCreator20([
'FechaExp' => '2022-01-13T14:15:16',
'CveRetenc' => '14', // Dividendos o utilidades distribuidos
'LugarExpRetenc' => '91778',
]);

// retenciones es un objeto de ayuda, similar a Comprobante
$retenciones = $creator->retenciones();

$retenciones->addCfdiRetenRelacionados([
'TipoRelacion' => '01',
'UUID' => '1474b7d3-61fc-41c4-a8b8-3f22e1161bb4',
]);
$retenciones->addEmisor([
'RfcE' => 'EKU9003173C9',
'NomDenRazSocE' => 'ESCUELA KEMPER URGATE',
'RegimenFiscalE' => '601',
]);
$retenciones->getReceptor()->addExtranjero([
'NumRegIdTribR' => '998877665544332211',
'NomDenRazSocR' => 'WORLD WIDE COMPANY INC',
]);
$retenciones->addPeriodo(['MesIni' => '05', 'MesFin' => '05', 'Ejercicio' => '2021']);
$retenciones->addTotales([
'MontoTotOperacion' => '55578643',
'MontoTotGrav' => '0',
'MontoTotExent' => '55578643',
'MontoTotRet' => '0',
'UtilidadBimestral' => '0.1',
'ISRCorrespondiente' => '0.1',
]);
$retenciones->addImpRetenidos([
'BaseRet' => '0',
'ImpuestoRet' => '001', // same as CFDI
'TipoPagoRet' => '01',
'MontoRet' => '200.00',
]);

$dividendos = new \CfdiUtils\Elements\Dividendos10\Dividendos();
$dividendos->addDividOUtil([
'CveTipDivOUtil' => '06', // 06 - Proviene de CUFIN al 31 de diciembre 2013
'MontISRAcredRetMexico' => '0',
'MontISRAcredRetExtranjero' => '0',
'MontRetExtDivExt' => '0',
'TipoSocDistrDiv' => 'Sociedad Nacional',
'MontISRAcredNal' => '0',
'MontDivAcumNal' => '0',
'MontDivAcumExt' => '0',
]);
$retenciones->addComplemento($dividendos);

// poner certificado y sellar el precfdi, después de sellar no debes hacer cambios
$creator->putCertificado(new \CfdiUtils\Certificado\Certificado('archivo.cer'));
$creator->addSello('file://archivo.key.pem', 'la contraseña');

// Asserts contendrá el resultado de la validación
$asserts = $creator->validate();

// guardar el precfdi
file_put_contents('precfdi.xml', $creator->asXml());
```
34 changes: 32 additions & 2 deletions docs/leer/leer-cfdi-retenciones.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,14 @@ no tendrán un impacto en el contenedor.

### Versión

El CFDI de retenciones solo tiene la versión 1.0, en caso de que se fabrique un objeto que contiene un número de versión
El CFDI de retenciones abarca las versiones 1.0 y 2.0, en caso de que se fabrique un objeto que contiene un número de versión
diferente, entonces el método `Retenciones::getVersion()` devolverá una cadena vacía. Esto es por homogeneidad con la
lectura de CFDI regulares.

Es importante notar cambios en la estructura y que muchos de los atributos usados en la versión 1.0
cambian de nombre o contenido en la versión 2.0, por lo que se recomienda utilizar
diferentes lectores según la versión del comprobante.

### Lectura formal

La lectura formal utiliza [nodos](../componentes/nodes.md), que es una representación en memoria del contenido
Expand Down Expand Up @@ -117,5 +121,31 @@ echo $nodeRetenciones->searchAttribute('retenciones:Emisor', 'RFCEmisor'); // EK

// obtener el QuickReader para lectura rápida
$qrRetenciones = $reader->getQuickReader();
echo $qrRetenciones->emisor['rfcemisor']; // EKU9003173C9
echo $qrRetenciones->emisor['NomDenRazSocE']; // Nombre del emisor
```


## Obteniendo la versión de un CFDI de Retenciones sin la clase `CfdiUtils\Retenciones\Retenciones`

Obtener la versión de un CFDI de Retenciones es sencillo con la clase `CfdiUtils\Retenciones\RetencionVersion`.

El método que usarás para obtener la versión depende de la información que ya
tengas cargada:

- `getFromXmlString()`: Cuando ya tienes el contenido del XML en una variable
- `getFromNode()`: Cuando tienes el nodo principal en un objeto de tipo `CfdiUtils\Nodes\NodeInterface`
- `getFromDOMDocument()` y `getFromDOMElement()`: Cuando tienes el contenido XML cargado en un objeto de tipo DOM.

El resultado de estos métodos será un string con el número de versión y vacío en
caso de no encontrarse un número de versión compatible.

```php
<?php
$retencionFile = '/retencion/archivo-retencion.xml';
$xmlContents = file_get_contents($retencionFile);
$cfdiVersion = new \CfdiUtils\Retenciones\RetencionVersion();
$version = $cfdiVersion->getFromXmlString($xmlContents);
```

Nota: la clase `CfdiUtils\Retenciones\Retenciones` ya realiza este proceso por lo que no es recomendado
duplicar el trabajo de averiguar la versión.
20 changes: 20 additions & 0 deletions src/CfdiUtils/Elements/Retenciones20/Addenda.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace CfdiUtils\Elements\Retenciones20;

use CfdiUtils\Elements\Common\AbstractElement;
use CfdiUtils\Nodes\NodeInterface;

class Addenda extends AbstractElement
{
public function getElementName(): string
{
return 'retenciones:Addenda';
}

public function add(NodeInterface $child): self
{
$this->children()->add($child);
return $this;
}
}
13 changes: 13 additions & 0 deletions src/CfdiUtils/Elements/Retenciones20/CfdiRetenRelacionados.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace CfdiUtils\Elements\Retenciones20;

use CfdiUtils\Elements\Common\AbstractElement;

class CfdiRetenRelacionados extends AbstractElement
{
public function getElementName(): string
{
return 'retenciones:CfdiRetenRelacionados';
}
}
20 changes: 20 additions & 0 deletions src/CfdiUtils/Elements/Retenciones20/Complemento.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace CfdiUtils\Elements\Retenciones20;

use CfdiUtils\Elements\Common\AbstractElement;
use CfdiUtils\Nodes\NodeInterface;

class Complemento extends AbstractElement
{
public function getElementName(): string
{
return 'retenciones:Complemento';
}

public function add(NodeInterface $child): self
{
$this->children()->add($child);
return $this;
}
}
13 changes: 13 additions & 0 deletions src/CfdiUtils/Elements/Retenciones20/Emisor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace CfdiUtils\Elements\Retenciones20;

use CfdiUtils\Elements\Common\AbstractElement;

class Emisor extends AbstractElement
{
public function getElementName(): string
{
return 'retenciones:Emisor';
}
}
13 changes: 13 additions & 0 deletions src/CfdiUtils/Elements/Retenciones20/Extranjero.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace CfdiUtils\Elements\Retenciones20;

use CfdiUtils\Elements\Common\AbstractElement;

class Extranjero extends AbstractElement
{
public function getElementName(): string
{
return 'retenciones:Extranjero';
}
}
13 changes: 13 additions & 0 deletions src/CfdiUtils/Elements/Retenciones20/ImpRetenidos.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace CfdiUtils\Elements\Retenciones20;

use CfdiUtils\Elements\Common\AbstractElement;

class ImpRetenidos extends AbstractElement
{
public function getElementName(): string
{
return 'retenciones:ImpRetenidos';
}
}
13 changes: 13 additions & 0 deletions src/CfdiUtils/Elements/Retenciones20/Nacional.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace CfdiUtils\Elements\Retenciones20;

use CfdiUtils\Elements\Common\AbstractElement;

class Nacional extends AbstractElement
{
public function getElementName(): string
{
return 'retenciones:Nacional';
}
}
13 changes: 13 additions & 0 deletions src/CfdiUtils/Elements/Retenciones20/Periodo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace CfdiUtils\Elements\Retenciones20;

use CfdiUtils\Elements\Common\AbstractElement;

class Periodo extends AbstractElement
{
public function getElementName(): string
{
return 'retenciones:Periodo';
}
}
45 changes: 45 additions & 0 deletions src/CfdiUtils/Elements/Retenciones20/Receptor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace CfdiUtils\Elements\Retenciones20;

use CfdiUtils\Elements\Common\AbstractElement;

class Receptor extends AbstractElement
{
public function getElementName(): string
{
return 'retenciones:Receptor';
}

public function getNacional(): Nacional
{
$nacional = $this->helperGetOrAdd(new Nacional());
$this->children()->removeAll();
$this->addChild($nacional);
$this['NacionalidadR'] = 'Nacional';
return $nacional;
}

public function addNacional(array $attributes = []): Nacional
{
$nacional = $this->getNacional();
$nacional->addAttributes($attributes);
return $nacional;
}

public function getExtranjero(): Extranjero
{
$nacional = $this->helperGetOrAdd(new Extranjero());
$this->children()->removeAll();
$this->addChild($nacional);
$this['NacionalidadR'] = 'Extranjero';
return $nacional;
}

public function addExtranjero(array $attributes = []): Extranjero
{
$extranjero = $this->getExtranjero();
$extranjero->addAttributes($attributes);
return $extranjero;
}
}
Loading

0 comments on commit 4b03974

Please sign in to comment.