ProyectoGrupal/VerifactuMidAPI/verifactu/xml.go

323 lines
10 KiB
Go

package verifactu
import (
"encoding/xml"
"fmt"
"time"
)
type AltaRequest struct {
XMLName xml.Name `xml:"sum:RegFactuSistemaFacturacion"`
Cabecera Cabecera `xml:"sum:Cabecera"`
RegistroFactura AltaRegistroFactura `xml:"sum:RegistroFactura"`
}
type AltaRegistroFactura struct {
RegistroAlta RegistroAlta `xml:"sum1:RegistroAlta"`
}
type Cabecera struct {
ObligadoEmision ObligadoEmision `xml:"sum1:ObligadoEmision"`
}
type ObligadoEmision struct {
NombreRazon string `xml:"sum1:NombreRazon"`
NIF string `xml:"sum1:NIF"`
}
type RegistroAlta struct {
IDVersion string `xml:"sum1:IDVersion"`
IDFactura IDFactura `xml:"sum1:IDFactura"`
NombreRazonEmisor string `xml:"sum1:NombreRazonEmisor"`
TipoFactura string `xml:"sum1:TipoFactura"`
DescripcionOperacion string `xml:"sum1:DescripcionOperacion"`
Destinatarios *Destinatarios `xml:"sum1:Destinatarios,omitempty"`
Desglose Desglose `xml:"sum1:Desglose"`
CuotaTotal string `xml:"sum1:CuotaTotal"`
ImporteTotal string `xml:"sum1:ImporteTotal"`
Encadenamiento Encadenamiento `xml:"sum1:Encadenamiento"`
SistemaInformatico SistemaInformatico `xml:"sum1:SistemaInformatico"`
FechaHoraHusoGenRegistro string `xml:"sum1:FechaHoraHusoGenRegistro"`
TipoHuella string `xml:"sum1:TipoHuella"`
Huella string `xml:"sum1:Huella"`
}
type IDFactura struct {
IDEmisorFactura string `xml:"sum1:IDEmisorFactura"`
NumSerieFactura string `xml:"sum1:NumSerieFactura"`
FechaExpedicionFactura string `xml:"sum1:FechaExpedicionFactura"`
}
type Destinatarios struct {
IDDestinatario []IDDestinatario `xml:"sum1:IDDestinatario"`
}
type IDDestinatario struct {
NombreRazon string `xml:"sum1:NombreRazon"`
NIF string `xml:"sum1:NIF"`
}
type Desglose struct {
DetalleDesglose []DetalleDesglose `xml:"sum1:DetalleDesglose"`
}
type DetalleDesglose struct {
ClaveRegimen string `xml:"sum1:ClaveRegimen"`
CalificacionOperacion string `xml:"sum1:CalificacionOperacion"`
TipoImpositivo string `xml:"sum1:TipoImpositivo"`
BaseImponibleOimporteNoSujeto string `xml:"sum1:BaseImponibleOimporteNoSujeto"`
CuotaRepercutida string `xml:"sum1:CuotaRepercutida"`
}
type Encadenamiento struct {
PrimerRegistro string `xml:"sum1:PrimerRegistro,omitempty"`
RegistroAnterior *RegistroAnterior `xml:"sum1:RegistroAnterior,omitempty"`
}
type RegistroAnterior struct {
IDEmisorFactura string `xml:"sum1:IDEmisorFactura"`
NumSerieFactura string `xml:"sum1:NumSerieFactura"`
FechaExpedicionFactura string `xml:"sum1:FechaExpedicionFactura"`
Huella string `xml:"sum1:Huella"`
}
type SistemaInformatico struct {
NombreRazon string `xml:"sum1:NombreRazon"`
NIF string `xml:"sum1:NIF"`
NombreSistemaInformatico string `xml:"sum1:NombreSistemaInformatico"`
IdSistemaInformatico string `xml:"sum1:IdSistemaInformatico"`
Version string `xml:"sum1:Version"`
NumeroInstalacion string `xml:"sum1:NumeroInstalacion"`
TipoUsoPosibleSoloVerifactu string `xml:"sum1:TipoUsoPosibleSoloVerifactu"`
TipoUsoPosibleMultiOT string `xml:"sum1:TipoUsoPosibleMultiOT"`
IndicadorMultiplesOT string `xml:"sum1:IndicadorMultiplesOT"`
}
type AnulacionRequest struct {
XMLName xml.Name `xml:"sum:RegFactuSistemaFacturacion"`
Cabecera Cabecera `xml:"sum:Cabecera"`
RegistroFactura AnulacionRegistroFactura `xml:"sum:RegistroFactura"`
}
type AnulacionRegistroFactura struct {
RegistroAnulacion RegistroAnulacion `xml:"sum1:RegistroAnulacion"`
}
type RegistroAnulacion struct {
IDVersion string `xml:"sum1:IDVersion"`
IDFacturaAnulada IDFacturaAnulada `xml:"sum1:IDFacturaAnulada"`
Encadenamiento Encadenamiento `xml:"sum1:Encadenamiento"`
SistemaInformatico SistemaInformatico `xml:"sum1:SistemaInformatico"`
FechaHoraHusoGenRegistro string `xml:"sum1:FechaHoraHusoGenRegistro"`
TipoHuella string `xml:"sum1:TipoHuella"`
Huella string `xml:"sum1:Huella"`
}
type IDFacturaAnulada struct {
IDEmisorFacturaAnulada string `xml:"sum1:IDEmisorFacturaAnulada"`
NumSerieFacturaAnulada string `xml:"sum1:NumSerieFacturaAnulada"`
FechaExpedicionFacturaAnulada string `xml:"sum1:FechaExpedicionFacturaAnulada"`
}
type Response struct {
XMLName xml.Name `xml:"Envelope"`
Body ResponseBody
}
type ResponseBody struct {
XMLName xml.Name `xml:"Body"`
Fault *Fault `xml:"Fault"`
Respuesta *RespuestaRegFactu `xml:"RespuestaRegFactuSistemaFacturacion"`
}
type Fault struct {
FaultCode string `xml:"faultcode"`
FaultString string `xml:"faultstring"`
}
type RespuestaRegFactu struct {
CSV string `xml:"CSV"`
EstadoEnvio string `xml:"EstadoEnvio"`
RespuestaLineas []RespuestaLinea `xml:"RespuestaLinea"`
}
type RespuestaLinea struct {
EstadoRegistro string `xml:"EstadoRegistro"`
CodigoError string `xml:"CodigoErrorRegistro"`
DescripcionError string `xml:"DescripcionErrorRegistro"`
}
type AltaData struct {
EmisorNombre string
EmisorNIF string
NumSerie string
FechaExpedicion time.Time
TipoFactura string
Descripcion string
DestinatarioNombre string
DestinatarioNIF string
IVA []IVARegularizacionData
CuotaTotal float64
ImporteTotal float64
Sistema SistemaData
Huella string
FechaGen time.Time
PrevHash string
PrevNumSerie string
PrevFecha time.Time
}
type IVARegularizacionData struct {
Base float64
Cuota float64
Tipo float64
ClaveRegimen string
Calificacion string
}
type SistemaData struct {
Nombre string
NIFProveedor string
NombreSistema string
Version string
NumeroInstalacion string
TipoUsoVerifactu string
}
func BuildAltaRequest(data AltaData) *AltaRequest {
fechaExp := data.FechaExpedicion.Format("02-01-2006")
fechaGen := data.FechaGen.Format("2006-01-02T15:04:05-07:00")
ivaList := make([]DetalleDesglose, len(data.IVA))
for i, iva := range data.IVA {
ivaList[i] = DetalleDesglose{
ClaveRegimen: iva.ClaveRegimen,
CalificacionOperacion: iva.Calificacion,
TipoImpositivo: fmt.Sprintf("%.2f", iva.Tipo),
BaseImponibleOimporteNoSujeto: fmt.Sprintf("%.2f", iva.Base),
CuotaRepercutida: fmt.Sprintf("%.2f", iva.Cuota),
}
}
var enc Encadenamiento
if data.PrevHash == "" {
enc = Encadenamiento{PrimerRegistro: "S"}
} else {
enc = Encadenamiento{
RegistroAnterior: &RegistroAnterior{
IDEmisorFactura: data.EmisorNIF,
NumSerieFactura: data.PrevNumSerie,
FechaExpedicionFactura: data.PrevFecha.Format("02-01-2006"),
Huella: data.PrevHash,
},
}
}
var destinatarios *Destinatarios
if data.DestinatarioNIF != "" {
destinatarios = &Destinatarios{
IDDestinatario: []IDDestinatario{
{NombreRazon: data.DestinatarioNombre, NIF: data.DestinatarioNIF},
},
}
}
req := &AltaRequest{
Cabecera: Cabecera{
ObligadoEmision: ObligadoEmision{
NombreRazon: data.EmisorNombre,
NIF: data.EmisorNIF,
},
},
RegistroFactura: AltaRegistroFactura{
RegistroAlta: RegistroAlta{
IDVersion: "1.0",
IDFactura: IDFactura{
IDEmisorFactura: data.EmisorNIF,
NumSerieFactura: data.NumSerie,
FechaExpedicionFactura: fechaExp,
},
NombreRazonEmisor: data.EmisorNombre,
TipoFactura: data.TipoFactura,
DescripcionOperacion: data.Descripcion,
Destinatarios: destinatarios,
Desglose: Desglose{
DetalleDesglose: ivaList,
},
CuotaTotal: fmt.Sprintf("%.2f", data.CuotaTotal),
ImporteTotal: fmt.Sprintf("%.2f", data.ImporteTotal),
Encadenamiento: enc,
SistemaInformatico: SistemaInformatico{
NombreRazon: data.Sistema.Nombre,
NIF: data.Sistema.NIFProveedor,
NombreSistemaInformatico: data.Sistema.NombreSistema,
IdSistemaInformatico: "01",
Version: data.Sistema.Version,
NumeroInstalacion: data.Sistema.NumeroInstalacion,
TipoUsoPosibleSoloVerifactu: data.Sistema.TipoUsoVerifactu,
TipoUsoPosibleMultiOT: "N",
IndicadorMultiplesOT: "N",
},
FechaHoraHusoGenRegistro: fechaGen,
TipoHuella: "01",
Huella: data.Huella,
},
},
}
return req
}
func BuildAnulacionRequest(data AltaData) *AnulacionRequest {
fechaExp := data.FechaExpedicion.Format("02-01-2006")
fechaGen := data.FechaGen.Format("2006-01-02T15:04:05-07:00")
var enc Encadenamiento
if data.PrevHash == "" {
enc = Encadenamiento{PrimerRegistro: "S"}
} else {
enc = Encadenamiento{
RegistroAnterior: &RegistroAnterior{
IDEmisorFactura: data.EmisorNIF,
NumSerieFactura: data.PrevNumSerie,
FechaExpedicionFactura: data.PrevFecha.Format("02-01-2006"),
Huella: data.PrevHash,
},
}
}
req := &AnulacionRequest{
Cabecera: Cabecera{
ObligadoEmision: ObligadoEmision{
NombreRazon: data.EmisorNombre,
NIF: data.EmisorNIF,
},
},
RegistroFactura: AnulacionRegistroFactura{RegistroAnulacion: RegistroAnulacion{
IDVersion: "1.0",
IDFacturaAnulada: IDFacturaAnulada{
IDEmisorFacturaAnulada: data.EmisorNIF,
NumSerieFacturaAnulada: data.NumSerie,
FechaExpedicionFacturaAnulada: fechaExp,
},
Encadenamiento: enc,
SistemaInformatico: SistemaInformatico{
NombreRazon: data.Sistema.Nombre,
NIF: data.Sistema.NIFProveedor,
NombreSistemaInformatico: data.Sistema.NombreSistema,
IdSistemaInformatico: "01",
Version: data.Sistema.Version,
NumeroInstalacion: data.Sistema.NumeroInstalacion,
TipoUsoPosibleSoloVerifactu: data.Sistema.TipoUsoVerifactu,
TipoUsoPosibleMultiOT: "N",
IndicadorMultiplesOT: "N",
},
FechaHoraHusoGenRegistro: fechaGen,
TipoHuella: "01",
Huella: data.Huella,
}},
}
return req
}