SAF-T reports¶
Use this service to generate SAF-T reports. This service only works for documents issued with certified software SaphetyDoc(DOC+).
For more information on SAF-T (PT)
You can request a SAF-T generation using the service /api/Reporting/createSafT
This is an asynchrounous service: when requesting a SAF-T report you will receive an Id (GUID) that you can query for report completion.
SAF-T report generation is part of a group defined as Long running tasks. These tasks may take some time to complete, therefore their asynchrounous nature.
SAF-T query report properties¶
SAF-T reporting specifies the following parameters:
EntityCode
The entity code that issued the invoice and is responsible for SAFT-T. (Typically <country code + VAT number> ex: PT507957547)SelfInvoiceSellerEntityCode
Applyed only when issuing self-invoices. Typically <country code + VAT number>. This will generate a SAF-T file for the seller.StartDate and EndDate
The document dates interval that will define the document inclusion in the reportDocumentTypes
One of the following: INVOICE, DEBIT_NOTE, CREDIT_NOTE, DESPATCH_ADVICE, SIMPLIFIED_INVOICE, INVOICE_RECEIPT, WAYBILL
Use ALL to include all document types in SAF-T.
Requesting a SAF-T report¶
Get a token¶
Check more detail how to get a token in Services overview
# Set Environment
#Integration
server_base_adress = "doc-server-int.saphety.com/Doc.WebApi.Services"
#Quality
#server_base_adress = "doc-server-qa.saphety.com/Doc.WebApi.Services"
#Production
#server_base_adress = "doc-server.saphety.com/Doc.WebApi.Services"
#Set authorization data
#username = 'username'
#password = 'request_password'
username = 'user_api_doc'
password = 'request_password'
## Get a JWT token from your username and password
import requests
import json
service_url = "https://" + server_base_adress + "/api/Account/token"
# Auhtentication data goes in payload as json
payload = {
'Username': username,
'Password': password
}
# Payload goes in json, serialize the payloal object to json
request_data=json.dumps(payload)
# Indicate in header that payload is json
headers = {
'content-type': 'application/json'
}
# POST request to get a token
response = requests.request("POST", service_url, data=request_data, headers=headers)
# Serializethe response
json_response = json.loads(response.text)
# Your token is at:
token = json_response["Data"];
print ('Your authorization token:' + token)
Your authorization token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiI1NDM5NSIsInVuaXF1ZV9uYW1lIjoidXNlcl9hcGlfZG9jIiwic2Vzc2lvbl9pZCI6ImUxN2M4YjM4LTdmMzQtNDdmNS1hYjU0LWMxYTUyOTIwNDQ3NCIsInN5c3RlbV9hZG1pbiI6IkZhbHNlIiwiZ2xvYl9lZGl0IjoiRmFsc2UiLCJleHRlcm5hbF91c2VybmFtZSI6InVzZXJfYXBpX2RvYyIsImV4dGVybmFsX3N5c3RlbV9hdWRpZW5jZSI6Imh0dHBzOi8vd3d3LnNhcGhldHktaW50LmNvbS9Eb2NTZXJ2ZXIiLCJuYmYiOjE2MjEyNjQ0ODYsImV4cCI6MTYyMTMxNTQ4NiwiaWF0IjoxNjIxMjY0NDI2LCJpc3MiOiJodHRwczovL3d3dy5zYXBoZXR5LmNvbS8iLCJhdWQiOiJodHRwczovL3d3dy5zYXBoZXR5LWludC5jb20vRG9jU2VydmVyIn0.GScY3rDaXrJr4Uxc0DVYFQbH_HYyVaf6ZwnkDLjz-EA
Define SAFT-T criteria¶
# SAF-T criteria data goes in payload as json
saft_criteria = {
'EntityCode': "PT560333331", # The company code that you want to list the series for
'SelfInvoiceSellerEntityCode': None, # Used only when issuing self-invoices
'StartDate': "2021-04-01",
'EndDate': "2021-05-30",
'DocumentTypes': "ALL"
}
Send request and get a request Id¶
service_url = "https://" + server_base_adress + "/api/Reporting/createSafT"
# Serialize the payloal object to json
request_data=json.dumps(saft_criteria)
# Indicate in header the authorization token
headers = {
'content-type': 'application/json',
'Authorization': 'bearer ' + token
}
# POST data to request SAF-Treport
response = requests.request("POST", service_url, data=request_data, headers=headers)
# formating the response to json for visualization purposes only
json_response = json.loads(response.text)
print(json.dumps(json_response, indent=4))
{
"CorrelationId": "0fb2cce1-b131-4513-b2ef-09f3dccd096f",
"IsValid": true,
"Errors": [],
"Data": "dca09d84-359a-4358-99a1-4eb97f2428e7"
}
# your request id is at:
request_id = json_response["Data"];
print ('The request id to query on service status: ' + request_id)
The request id to query on service status: dca09d84-359a-4358-99a1-4eb97f2428e7
Check the status of your request¶
Query the LongRunningTasksMonitor
as indicate bellow.
The AsyncStatus
of your request must be set to finished
and the IsValid
property no Errors
should be present in the response.
# with the received request_id query the LongRunningTasksMonitor
service_url = "https://" + server_base_adress + "/api/LongRunningTasksMonitor/" + request_id
# build the request
headers = {
'Authorization': 'bearer ' + token
}
# POST request to send the invoice
response = requests.request("GET", service_url, headers=headers)
# formating the response to json for visualization purposes only
json_response = json.loads(response.text)
print(json.dumps(json_response, indent=4))
task_status=json_response["Data"]["AsyncStatus"]
task_errors=json_response["Errors"]
print("Your task is: " + task_status)
{
"CorrelationId": "9518f6e3-78e7-457c-bce1-8ec391819d39",
"IsValid": true,
"Errors": [],
"Data": {
"Id": "dca09d84-359a-4358-99a1-4eb97f2428e7",
"UserId": 54395,
"Queue": "DocGenerateSafT",
"AsyncStatus": "Queued",
"CreationDate": "2021-05-17 15:14:47",
"ExecutionStart": null,
"ExecutionEnd": null,
"SerializedInput": "{\"Id\":\"dca09d84-359a-4358-99a1-4eb97f2428e7\",\"Payload\":{\"EntityCode\":\"PT560333331\",\"SelfInvoiceSellerEntityCode\":null,\"StartDate\":\"2021-04-01\",\"EndDate\":\"2021-05-30\",\"DocumentTypes\":\"ALL\"}}",
"SerializedOutput": null
}
}
Your task is: Queued
Download SAF-T report¶
Report characteristics¶
Once the report task has finished with success a SAF-T report is available for download.
The report is associated to the company that request the SAFT-T. (Property EntityCode
in the SAFT-Criteria)
The report will have the following characteristics:
Report code: SAFT_PT_GENERATION
Report name: SafT_
RequesterEntitycode|SelfBillingEntityCode
_DocumentStartDate (yyMMdd)
_DocumentEndDate (yyMMdd)
.zip
Example: SafT_PT506284301_210401_210530.zip
Get a token to download report¶
Use the service /api/Reporting/SearchEntityReport to find your SAF-T report.
This service returns a token that can be use to download the report.
This service is a paginable services. More info at Services overview
This service can return more then one SAF-T report since severall requests can be done using the same criteria. Use the RestrictionCriteria
MaxCreationDate
and MinCreationDate
to find the target report.
# Search you report by defining in thesearch criteira the report characteristics
service_url = "https://" + server_base_adress + "/api/Reporting/SearchEntityReport"
# Use in the restriction criteria the report characteristics
report_name='SafT_PT560333331_210401_210530.zip'
payload = {
'RestrictionCriteria': {
'EntityCode': "PT560333331", # the entity code that requested the report generation
'Code': "SAFT_PT_GENERATION", # SAF-T report
'Name': report_name, # report name (check rule names)
'MaxCreationDate': None,
'MinCreationDate': None
},
'PageNumber': 0,
'RowsPerPage': 20
}
# Payload goes in json, serialize the payloal object to json
request_data=json.dumps(payload)
# Indicate in header the authorization token
headers = {
'content-type': 'application/json',
'Authorization': 'bearer ' + token
}
# POST request to get a token
response = requests.request("POST", service_url, data=request_data, headers=headers)
print (response)
# Serializethe response
json_response = json.loads(response.text)
print(json_response)
<Response [200]>
{'CorrelationId': 'f0c3fff4-aa45-43f1-bfd6-12d8dfbbd9b8', 'IsValid': True, 'Errors': [], 'Data': [{'Id': 73337, 'EntityCode': 'PT560333331', 'Code': 'SAFT_PT_GENERATION', 'Name': 'SafT_PT560333331_210401_210530.zip', 'Script': None, 'UsersId': 421, 'CreationDate': '2021-05-12 15:33:53', 'ExecutionDate': '2021-05-12 15:33:53', 'Status': 'PROCESSED', 'ExecutionCompleted': '2021-05-12 15:33:54', 'ReportContext': '{"StartDate":"2021-04-01T00:00:00","EndDate":"2021-05-30T00:00:00"}', 'Token': 'DSAj0vBevcCAqgKA1JMweTincsV7IklkIjo3MzMzNywiRW50aXR5Q29kZSI6IlBUNTYwMzMzMzMxIiwiVXNlcklkIjo1NDM5NX0='}, {'Id': 73507, 'EntityCode': 'PT560333331', 'Code': 'SAFT_PT_GENERATION', 'Name': 'SafT_PT560333331_210401_210530.zip', 'Script': None, 'UsersId': 421, 'CreationDate': '2021-05-17 15:14:50', 'ExecutionDate': '2021-05-17 15:14:50', 'Status': 'PROCESSED', 'ExecutionCompleted': '2021-05-17 15:14:51', 'ReportContext': '{"StartDate":"2021-04-01T00:00:00","EndDate":"2021-05-30T00:00:00"}', 'Token': '07EJGB8+0dSUQuGGIIWEqO6V5Cx7IklkIjo3MzUwNywiRW50aXR5Q29kZSI6IlBUNTYwMzMzMzMxIiwiVXNlcklkIjo1NDM5NX0='}]}
# token is at (note that more then one report may have been returned)
report_access_token =json_response["Data"][0]["Token"]
print('Token to download the report: ' + report_access_token)
Token to download the report: DSAj0vBevcCAqgKA1JMweTincsV7IklkIjo3MzMzNywiRW50aXR5Q29kZSI6IlBUNTYwMzMzMzMxIiwiVXNlcklkIjo1NDM5NX0=
Download the report¶
With the token use the service /api/Reporting/GetReportByToken to download the report
import urllib.parse
# Build the url
report_access_token = urllib.parse.quote(report_access_token);
service_url = "https://" + server_base_adress + "/api/Reporting/GetReportByToken?token=" + report_access_token;
print('SAF-T download url: ' + service_url);
# Indicate in header the authorization token
headers = {
'content-type': 'application/json',
'Authorization': 'bearer ' + token
}
# Use GET to send the request
#r = requests.get(service_url, Stream=True)
response = requests.get(service_url, allow_redirects=True)
with open(report_name,'wb') as report:
report.write(response.content)
# response = requests.request("GET", service_url, headers=headers)
# print (response)
# Serializethe response
#This service streams the report to the client.
SAF-T download url: https://doc-server-int.saphety.com/Doc.WebApi.Services/api/Reporting/GetReportByToken?token=DSAj0vBevcCAqgKA1JMweTincsV7IklkIjo3MzMzNywiRW50aXR5Q29kZSI6IlBUNTYwMzMzMzMxIiwiVXNlcklkIjo1NDM5NX0%3D