Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions .xsdata.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
<PostponedAnnotations>false</PostponedAnnotations>
<UnnestClasses>false</UnnestClasses>
</Output>
<Extensions>
<!--Extensions>
<Extension type="class" class=".*" import="nfelib.CommonMixin" prepend="false" applyIfDerived="false"/>
</Extensions>
</Extensions-->
<Conventions>
<ClassName case="pascalCase" safePrefix="type"/>
<FieldName case="originalCase" safePrefix="value"/>
Expand All @@ -21,6 +21,12 @@
<PackageName case="snakeCase" safePrefix="pkg"/>
</Conventions>
<Substitutions>
<!-- Because we use the originalCase options, some dataclass attributes
might have the same names as dataclass types, typically starting
with an upper case. In these few cases, we use the xsdata substitution
system to replace these attributes starting with a lower case.
-->

<!-- defaults : -->
<Substitution type="package" search="http://www.w3.org/2001/XMLSchema" replace="xs"/>
<Substitution type="package" search="http://www.w3.org/XML/1998/namespace" replace="xml"/>
Expand All @@ -31,6 +37,11 @@
<Substitution type="package" search="http://schemas.xmlsoap.org/wsdl/soap12/" replace="soap12"/>
<Substitution type="package" search="http://schemas.xmlsoap.org/soap/envelope/" replace="soapenv"/>

<!-- soap: -->
<Substitution type="field" search="Header" replace="header"/>
<Substitution type="field" search="Body" replace="body"/>
<Substitution type="field" search="Fault" replace="fault"/>

<!-- xmldsig : -->
<Substitution type="field" search="^@any_element$" replace="any_element"/>
<Substitution type="field" search="^@other_element$" replace="other_element"/>
Expand Down
Empty file.
156 changes: 156 additions & 0 deletions nfelib/cte/client/v4_0/servers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
# Auto-generated file. Do not edit manually.
# ruff: noqa: D101
# ruff: noqa: E501

from __future__ import annotations # Python 3.8 compat

from enum import Enum
from typing import TypedDict


class Endpoint(Enum):
QRCODE = "qrcode"
CTESTATUSSERVICOV4 = "CteStatusServicoV4"
CTECONSULTAV4 = "CteConsultaV4"
CTERECEPCAOEVENTOV4 = "CteRecepcaoEventoV4"
CTERECEPCAOOSV4 = "CTeRecepcaoOSV4"
CTERECEPCAOSINCV4 = "CTeRecepcaoSincV4"
CTERECEPCAOGTVEV4 = "CTeRecepcaoGTVeV4"
CTERECEPCAOSIMPV4 = "CTeRecepcaoSimpV4"


class ServerConfig(TypedDict):
prod_server: str
dev_server: str
soap_version: str
endpoints: dict[Endpoint, str]


servers: dict[str, ServerConfig] = {
"MT": {
"prod_server": "cte.sefaz.mt.gov.br",
"dev_server": "homologacao.sefaz.mt.gov.br",
"soap_version": "1.1",
"endpoints": {
Endpoint.QRCODE: "/cte/qrcode",
Endpoint.CTESTATUSSERVICOV4: "/ctews2/services/CTeStatusServicoV4?wsdl",
Endpoint.CTECONSULTAV4: "/ctews2/services/CTeConsultaV4?wsdl",
Endpoint.CTERECEPCAOEVENTOV4: "/ctews2/services/CTeRecepcaoEventoV4?wsdl",
Endpoint.CTERECEPCAOOSV4: "/ctews/services/CTeRecepcaoOSV4?wsdl",
Endpoint.CTERECEPCAOSINCV4: "/ctews2/services/CTeRecepcaoSincV4?wsdl",
Endpoint.CTERECEPCAOGTVEV4: "/ctews2/services/CTeRecepcaoGTVeV4?wsdl",
Endpoint.CTERECEPCAOSIMPV4: "/cte-ws/services/CTeRecepcaoSimpV4",
},
},
"MS": {
"prod_server": "producao.cte.ms.gov.br",
"dev_server": "homologacao.cte.ms.gov.br",
"soap_version": "1.1",
"endpoints": {
Endpoint.QRCODE: "/cte/qrcode",
Endpoint.CTESTATUSSERVICOV4: "/ws/CTeStatusServicoV4",
Endpoint.CTECONSULTAV4: "/ws/CTeConsultaV4",
Endpoint.CTERECEPCAOEVENTOV4: "/ws/CTeRecepcaoEventoV4",
Endpoint.CTERECEPCAOOSV4: "/ws/CTeRecepcaoOSV4",
Endpoint.CTERECEPCAOSINCV4: "/ws/CTeRecepcaoSincV4",
Endpoint.CTERECEPCAOGTVEV4: "/ws/CTeRecepcaoGTVeV4",
Endpoint.CTERECEPCAOSIMPV4: "/ws/CTeRecepcaoSimpV4",
},
},
"MG": {
"prod_server": "cte.fazenda.mg.gov.br",
"dev_server": "hcte.fazenda.mg.gov.br",
"soap_version": "1.2",
"endpoints": {
Endpoint.QRCODE: "/portalcte/sistema/qrcode.xhtml",
Endpoint.CTESTATUSSERVICOV4: "/cte/services/CTeStatusServicoV4",
Endpoint.CTECONSULTAV4: "/cte/services/CTeConsultaV4",
Endpoint.CTERECEPCAOEVENTOV4: "/cte/services/CTeRecepcaoEventoV4",
Endpoint.CTERECEPCAOOSV4: "/cte/services/CTeRecepcaoOSV4",
Endpoint.CTERECEPCAOSINCV4: "/cte/services/CTeRecepcaoSincV4",
Endpoint.CTERECEPCAOGTVEV4: "/cte/services/CTeRecepcaoGTVeV4",
Endpoint.CTERECEPCAOSIMPV4: "/cte/services/CTeRecepcaoSimpV4",
},
},
"PR": {
"prod_server": "cte.fazenda.pr.gov.br",
"dev_server": "homologacao.cte.fazenda.pr.gov.br",
"soap_version": "1.2",
"endpoints": {
Endpoint.QRCODE: "/cte/qrcode",
Endpoint.CTESTATUSSERVICOV4: "/cte4/CTeStatusServicoV4?wsdl",
Endpoint.CTECONSULTAV4: "/cte4/CTeConsultaV4?wsdl",
Endpoint.CTERECEPCAOEVENTOV4: "/cte4/CTeRecepcaoEventoV4?wsdl",
Endpoint.CTERECEPCAOOSV4: "/cte4/CTeRecepcaoOSV4?wsdl",
Endpoint.CTERECEPCAOSINCV4: "/cte4/CTeRecepcaoSincV4?wsdl",
Endpoint.CTERECEPCAOGTVEV4: "/cte4/CTeRecepcaoGTVeV4?wsdl",
Endpoint.CTERECEPCAOSIMPV4: "/cte4/CTeRecepcaoSimpV4",
},
},
"RS": {
"prod_server": "cte.svrs.rs.gov.br",
"dev_server": "cte-homologacao.svrs.rs.gov.br",
"soap_version": "1.2",
"endpoints": {
Endpoint.QRCODE: "/cte/qrCode",
Endpoint.CTESTATUSSERVICOV4: "/ws/CTeStatusServicoV4/CTeStatusServicoV4.asmx",
Endpoint.CTECONSULTAV4: "/ws/CTeConsultaV4/CTeConsultaV4.asmx",
Endpoint.CTERECEPCAOEVENTOV4: "/ws/CTeRecepcaoEventoV4/CTeRecepcaoEventoV4.asmx",
Endpoint.CTERECEPCAOOSV4: "/ws/CTeRecepcaoOSV4/CTeRecepcaoOSV4.asmx",
Endpoint.CTERECEPCAOSINCV4: "/ws/CTeRecepcaoSincV4/CTeRecepcaoSincV4.asmx",
Endpoint.CTERECEPCAOGTVEV4: "/ws/CTeRecepcaoGTVeV4/CTeRecepcaoGTVeV4.asmx",
Endpoint.CTERECEPCAOSIMPV4: "/ws/CTeRecepcaoSimpV4/CTeRecepcaoSimpV4.asmx",
},
},
"SP": {
"prod_server": "nfe.fazenda.sp.gov.br",
"dev_server": "homologacao.nfe.fazenda.sp.gov.br",
"soap_version": "1.2",
"endpoints": {
Endpoint.QRCODE: "/CTeConsulta/qrCode",
Endpoint.CTESTATUSSERVICOV4: "/CTeWS/WS/CTeStatusServicoV4.asmx",
Endpoint.CTECONSULTAV4: "/CTeWS/WS/CTeConsultaV4.asmx",
Endpoint.CTERECEPCAOEVENTOV4: "/CTeWS/WS/CTeRecepcaoEventoV4.asmx",
Endpoint.CTERECEPCAOOSV4: "/CTeWS/WS/CTeRecepcaoOSV4.asmx",
Endpoint.CTERECEPCAOSINCV4: "/CTeWS/WS/CTeRecepcaoSincV4.asmx",
Endpoint.CTERECEPCAOGTVEV4: "/CTeWS/WS/CTeRecepcaoGTVeV4.asmx",
Endpoint.CTERECEPCAOSIMPV4: "/CTeWS/WS/CTeRecepcaoSimpV4.asmx",
},
},
"SVRS": {
"prod_server": "cte.svrs.rs.gov.br",
"dev_server": "cte-homologacao.svrs.rs.gov.br",
"soap_version": "1.2",
"endpoints": {
Endpoint.QRCODE: "/cte/qrCode",
Endpoint.CTESTATUSSERVICOV4: "/ws/CTeStatusServicoV4/CTeStatusServicoV4.asmx",
Endpoint.CTECONSULTAV4: "/ws/CTeConsultaV4/CTeConsultaV4.asmx",
Endpoint.CTERECEPCAOEVENTOV4: "/ws/CTeRecepcaoEventoV4/CTeRecepcaoEventoV4.asmx",
Endpoint.CTERECEPCAOOSV4: "/ws/CTeRecepcaoOSV4/CTeRecepcaoOSV4.asmx",
Endpoint.CTERECEPCAOSINCV4: "/ws/CTeRecepcaoSincV4/CTeRecepcaoSincV4.asmx",
Endpoint.CTERECEPCAOGTVEV4: "/ws/CTeRecepcaoGTVeV4/CTeRecepcaoGTVeV4.asmx",
Endpoint.CTERECEPCAOSIMPV4: "/ws/CTeRecepcaoSimpV4/CTeRecepcaoSimpV4.asmx",
},
},
"SVSP": {
"prod_server": "nfe.fazenda.sp.gov.br",
"dev_server": "homologacao.nfe.fazenda.sp.gov.br",
"soap_version": "1.2",
"endpoints": {
Endpoint.QRCODE: "/CTeConsulta/qrCode",
Endpoint.CTESTATUSSERVICOV4: "/CTeWS/WS/CTeStatusServicoV4.asmx",
Endpoint.CTECONSULTAV4: "/CTeWS/WS/CTeConsultaV4.asmx",
Endpoint.CTERECEPCAOEVENTOV4: "/CTeWS/WS/CTeRecepcaoEventoV4.asmx",
Endpoint.CTERECEPCAOOSV4: "/CTeWS/WS/CTeRecepcaoOSV4.asmx",
Endpoint.CTERECEPCAOSINCV4: "/CTeWS/WS/CTeRecepcaoSincV4.asmx",
Endpoint.CTERECEPCAOGTVEV4: "/CTeWS/WS/CTeRecepcaoGTVeV4.asmx",
Endpoint.CTERECEPCAOSIMPV4: "/CTeWS/WS/CTeRecepcaoSimpV4.asmx",
},
},
"AN": {
"prod_server": "www1.cte.fazenda.gov.br",
"dev_server": "hom1.cte.fazenda.gov.br",
"soap_version": "1.1",
"endpoints": {},
},
}
38 changes: 38 additions & 0 deletions nfelib/cte/client/v4_0/servers_scraper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Copyright (C) 2024 Raphaël Valyi - Akretion <[email protected]>

import sys
from pathlib import Path

from nfelib.utils.servers_scraper import fetch_servers, save_servers
from nfelib.utils.soap_generator import generate_soap

# Constants
PROD_URL = "https://www.cte.fazenda.gov.br/portal/webServices.aspx"
DEV_URL = "https://hom.cte.fazenda.gov.br/portal/webServices.aspx"
OUTPUT_FILE = Path("nfelib/cte/client/v4_0/servers.py")


def main():
"""Cli entry point."""
download = False
if "--download" in sys.argv:
download = True
sys.argv.remove(
"--download"
) # Remove the --download flag to avoid interfering with argparse

generate = False
if "--generate" in sys.argv:
generate = True
sys.argv.remove(
"--generate"
) # Remove the --generate flag to avoid interfering with argparse

servers, endpoints = fetch_servers(PROD_URL, DEV_URL)
if servers:
save_servers(servers, endpoints, OUTPUT_FILE)
generate_soap(servers, endpoints, download, generate)


if __name__ == "__main__":
main()
Empty file.
43 changes: 43 additions & 0 deletions nfelib/mdfe/client/v3_0/servers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Auto-generated file. Do not edit manually.
# ruff: noqa: D101
# ruff: noqa: E501

from __future__ import annotations # Python 3.8 compat

from enum import Enum
from typing import TypedDict


class Endpoint(Enum):
MDFERECEPCAOEVENTO = "MDFeRecepcaoEvento"
MDFECONSULTA = "MDFeConsulta"
MDFESTATUSSERVICO = "MDFeStatusServico"
MDFECONSNAOENC = "MDFeConsNaoEnc"
MDFEDISTRIBUICAODFE = "MDFeDistribuicaoDFe"
MDFERECEPCAOSINC = "MDFeRecepcaoSinc"
QRCODE = "QR Code"


class ServerConfig(TypedDict):
prod_server: str
dev_server: str
soap_version: str
endpoints: dict[Endpoint, str]


servers: dict[str, ServerConfig] = {
"SVRS": {
"prod_server": "mdfe.svrs.rs.gov.br",
"dev_server": "mdfe-homologacao.svrs.rs.gov.br",
"soap_version": "1.1",
"endpoints": {
Endpoint.MDFERECEPCAOEVENTO: "/ws/MDFeRecepcaoEvento/MDFeRecepcaoEvento.asmx",
Endpoint.MDFECONSULTA: "/ws/MDFeConsulta/MDFeConsulta.asmx",
Endpoint.MDFESTATUSSERVICO: "/ws/MDFeStatusServico/MDFeStatusServico.asmx",
Endpoint.MDFECONSNAOENC: "/ws/MDFeConsNaoEnc/MDFeConsNaoEnc.asmx",
Endpoint.MDFEDISTRIBUICAODFE: "/ws/MDFeDistribuicaoDFe/MDFeDistribuicaoDFe.asmx",
Endpoint.MDFERECEPCAOSINC: "/ws/MDFeRecepcaoSinc/MDFeRecepcaoSinc.asmx",
Endpoint.QRCODE: "/mdfe/qrCode",
},
},
}
109 changes: 109 additions & 0 deletions nfelib/mdfe/client/v3_0/servers_scraper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# Copyright (C) 2024 Raphaël Valyi - Akretion <[email protected]>

from __future__ import annotations # Python 3.8 compat

import logging
import sys
from pathlib import Path
from typing import Any

import requests # type: ignore[import-untyped]
from bs4 import BeautifulSoup

from nfelib.utils.servers_scraper import save_servers
from nfelib.utils.soap_generator import generate_soap

# Constants
MDFE_SVRS_URL = "https://dfe-portal.svrs.rs.gov.br/Mdfe/Servicos"
OUTPUT_FILE = Path("nfelib/mdfe/client/v3_0/servers.py")

# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


def fetch_mdfe_servers(url: str) -> dict[Any, Any]:
"""Fetches the MDFe server actions for production and homologation."""
# Fetch the page content
response = requests.get(url)
response.raise_for_status() # Raise an exception for HTTP errors

# Parse the HTML content
soup = BeautifulSoup(response.content, "lxml")

# Initialize dictionaries to store server actions
servers: dict[Any, Any] = {
"SVRS": {
"prod_server": "mdfe.svrs.rs.gov.br",
"dev_server": "mdfe-homologacao.svrs.rs.gov.br",
"soap_version": "1.1",
"endpoints": {},
}
}

# Find all tables with server information
tables = soup.find_all("table")
for table in tables:
# Determine if the table is for production or homologation
caption = table.find("caption")
if not caption:
continue

# Extract server actions from the table
rows = table.find_all("tr")[1:] # Skip the header row
for row in rows:
cols = row.find_all("td")
if len(cols) < 4: # Ensure there are enough columns
continue

service_name = cols[1].text.strip()
service_url = cols[3].text.strip()

# Add the service to the servers dictionary
if service_name not in servers["SVRS"]["endpoints"]:
servers["SVRS"]["endpoints"][service_name] = {}

servers["SVRS"]["endpoints"][service_name] = "/" + "/".join(
service_url.split("/")[3:]
)

logger.info("Successfully fetched MDFe servers.")
return servers


def main():
"""Cli entry point."""
download = False
if "--download" in sys.argv:
download = True
sys.argv.remove(
"--download"
) # Remove the --download flag to avoid interfering with argparse

generate = False
if "--generate" in sys.argv:
generate = True
sys.argv.remove(
"--generate"
) # Remove the --generate flag to avoid interfering with argparse

# Fetch the MDFe server actions
servers = fetch_mdfe_servers(MDFE_SVRS_URL)
endpoints = {
"MDFERECEPCAOEVENTO": "MDFeRecepcaoEvento",
"MDFECONSULTA": "MDFeConsulta",
"MDFESTATUSSERVICO": "MDFeStatusServico",
"MDFECONSNAOENC": "MDFeConsNaoEnc",
"MDFEDISTRIBUICAODFE": "MDFeDistribuicaoDFe",
"MDFERECEPCAOSINC": "MDFeRecepcaoSinc",
"QRCODE": "QR Code",
}

# Save the results to a file
if servers:
save_servers(servers, endpoints, OUTPUT_FILE)
generate_soap(servers, endpoints, download, generate)


if __name__ == "__main__":
main()
Empty file.
Loading
Loading