Skip to content

Commit

Permalink
Merge pull request #3 from pagopa/PAGOPA-1360-refactoring
Browse files Browse the repository at this point in the history
ref: fix repository issue and update API [PAGOPA-1360]
  • Loading branch information
cap-ang authored Jan 12, 2024
2 parents 2ca4aae + 8820e6b commit d9a9c47
Show file tree
Hide file tree
Showing 26 changed files with 518 additions and 51,858 deletions.
5 changes: 0 additions & 5 deletions .identity/00_data.tf
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
data "azurerm_storage_account" "tf_storage_account"{
name = "pagopainfraterraform${var.env}"
resource_group_name = "io-infra-rg"
}

data "azurerm_resource_group" "dashboards" {
name = "dashboards"
}
Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ Start the micronaut application with this command:

`mvn mn:run`

### Rule of thumb

Prevent more than 1 file in with macOS

`zip -d filename.zip __MACOSX/\*`

`zip -d filename.zip \*/.DS_Store`

`zip file.zip uncompressed`

### Micronaut Profiles

- **local**: to develop locally.
Expand Down
8 changes: 4 additions & 4 deletions helm/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
apiVersion: v2
name: pagopa-afm-calculator
description: Microservice that handles calculation for pagoPA Advanced Fees Management
name: pagopa-gpd-upload
description: Microservice that handles file upload of massive debt positions JSON object
type: application
version: 0.15.0
appVersion: 0.1.1
version: 0.19.0
appVersion: 0.1.1-4-PAGOPA-1360-refactoring
dependencies:
- name: microservice-chart
version: 2.8.0
Expand Down
13 changes: 7 additions & 6 deletions helm/values-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ microservice-chart:
fullnameOverride: ""
image:
repository: ghcr.io/pagopa/pagopa-gpd-upload
tag: "0.1.1"
tag: "0.1.1-4-PAGOPA-1360-refactoring"
pullPolicy: Always
livenessProbe:
httpGet:
Expand Down Expand Up @@ -66,6 +66,11 @@ microservice-chart:
ENV: 'azure-kubernetes-dev'
APP_LOGGING_LEVEL: 'DEBUG'
DEFAULT_LOGGING_LEVEL: 'INFO'
COSMOS_URI: "https://pagopa-d-weu-gps-cosmos-account.documents.azure.com:443/"
DB_NAME: "gpd_db"
CONTAINER_NAME: "gpd_upload_status"
POST_FILE_RETRY_AFTER: '10000'
LOG_LEVEL: "DEBUG"
# CORS_CONFIGURATION: '{"origins": ["*"], "methods": ["*"]}'
# OTEL_SERVICE_NAME: # TODO
# OTEL_RESOURCE_ATTRIBUTES: "deployment.environment=dev"
Expand All @@ -77,12 +82,8 @@ microservice-chart:
envSecret:
# APPLICATIONINSIGHTS_CONNECTION_STRING: 'ai-d-connection-string'
# OTEL_EXPORTER_OTLP_HEADERS: elastic-apm-secret-token
BLOB_SAS_URL: 'gpd-upload-blob-sas-url'
BLOB_SAS_TOKEN: 'gpd-upload-blob-sas-token'
COSMOS_URI: 'gpd-upload-cosmos-uri'
BLOB_CONNECTION_STRING: 'gpd-upload-sa-connection-string'
COSMOS_KEY: 'gpd-upload-cosmos-key'
DB_NAME: 'gpd-upload-cosmos-db-name'
CONTAINER_NAME: 'gpd-upload-cosmos-db-container-name'
keyvault:
name: "pagopa-d-gps-kv"
tenantId: "7788edaf-0346-4068-9d79-c868aed15b3d"
Expand Down
2 changes: 1 addition & 1 deletion helm/values-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ microservice-chart:
fullnameOverride: ""
image:
repository: ghcr.io/pagopa/yourname # TODO
tag: "0.1.1"
tag: "0.1.1-4-PAGOPA-1360-refactoring"
pullPolicy: Always
livenessProbe:
httpGet:
Expand Down
2 changes: 1 addition & 1 deletion helm/values-uat.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ microservice-chart:
fullnameOverride: ""
image:
repository: ghcr.io/pagopa/yourname # TODO
tag: "0.1.1"
tag: "0.1.1-4-PAGOPA-1360-refactoring"
pullPolicy: Always
livenessProbe:
httpGet:
Expand Down
2 changes: 1 addition & 1 deletion openapi/openapi.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"info": {
"version": "0.1.1"
"version": "0.1.1-4-PAGOPA-1360-refactoring"
}
}
9 changes: 8 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>it.gov.pagopa.gpd.upload</groupId>
<artifactId>pagopa-gpd-upload</artifactId>
<version>0.1.1</version>
<version>0.1.1-4-PAGOPA-1360-refactoring</version>
<packaging>${packaging}</packaging>

<parent>
Expand All @@ -18,6 +18,7 @@
<release.version>17</release.version>
<micronaut.version>4.2.0</micronaut.version>
<lombok.version>1.18.22</lombok.version>
<mockito-junit.version>4.1.0</mockito-junit.version>
<micronaut.aot.enabled>false</micronaut.aot.enabled>
<micronaut.aot.packageName>it.gov.pagopa.gpd.upload.aot.generated</micronaut.aot.packageName>
<micronaut.runtime>netty</micronaut.runtime>
Expand All @@ -32,6 +33,12 @@
</repositories>

<dependencies>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito-junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-server-netty</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package it.gov.pagopa.gpd.upload.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import io.micronaut.context.annotation.Value;
import io.micronaut.http.HttpHeaders;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.HttpStatus;
import io.micronaut.http.MediaType;
Expand All @@ -18,12 +22,16 @@
import it.gov.pagopa.gpd.upload.model.ProblemJson;
import it.gov.pagopa.gpd.upload.service.FileStatusService;
import it.gov.pagopa.gpd.upload.service.FileUploadService;
import jakarta.annotation.PostConstruct;
import jakarta.inject.Inject;
import jakarta.validation.constraints.NotBlank;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;


import java.io.IOException;
import java.net.URI;
import java.text.SimpleDateFormat;

@ExecuteOn(TaskExecutors.IO)
@Controller()
Expand All @@ -36,12 +44,24 @@ public class FileController {
@Inject
FileStatusService fileStatusService;

@Value("${post.file.response.headers.retry_after.millis}")
private int retryAfter;
private ObjectMapper objectMapper;

@PostConstruct
public void init() {
objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-ddHH:mm:ss.SSS"));
}

@SneakyThrows
@Operation(summary = "The Organization creates the debt positions listed in the file.", security = {@SecurityRequirement(name = "ApiKey"), @SecurityRequirement(name = "Authorization")}, operationId = "createMassivePositions")
@ApiResponses(value = {
@ApiResponse(responseCode = "201", description = "Request created."),
@ApiResponse(responseCode = "202", description = "Request accepted."),
@ApiResponse(responseCode = "400", description = "Malformed request.", content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = ProblemJson.class))),
@ApiResponse(responseCode = "401", description = "Wrong or missing function key.", content = @Content(schema = @Schema())),
@ApiResponse(responseCode = "409", description = "Conflict: duplicate debt position found.", content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = ProblemJson.class))),
@ApiResponse(responseCode = "409", description = "Conflict: duplicate file found.", content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = ProblemJson.class))),
@ApiResponse(responseCode = "500", description = "Service unavailable.", content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = ProblemJson.class)))})
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Post("/organizations/{organizationFiscalCode}/debtpositions/file")
Expand All @@ -50,30 +70,33 @@ public HttpResponse uploadDebtPositionFile(@Parameter(description = "The organiz
String key = fileUploadService.upload(organizationFiscalCode, file);
log.debug("A file with name: " + file.getFilename() + " has been uploaded");

return HttpResponse.status(HttpStatus.OK)
.body(key);
String uri = "/organizations/" + organizationFiscalCode +"/debtpositions/file/" + key +"/status";
HttpResponse response = HttpResponse.accepted(new URI(uri));

return response.toMutableResponse().header(HttpHeaders.RETRY_AFTER, retryAfter + " ms");
}

@SneakyThrows
@Operation(summary = "Returns the upload status of debt positions uploaded via file.", security = {@SecurityRequirement(name = "ApiKey"), @SecurityRequirement(name = "Authorization")}, operationId = "createMassivePositions")
@ApiResponses(value = {
@ApiResponse(responseCode = "201", description = "Request created."),
@ApiResponse(responseCode = "200", description = "Upload found."),
@ApiResponse(responseCode = "400", description = "Malformed request.", content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = ProblemJson.class))),
@ApiResponse(responseCode = "401", description = "Wrong or missing function key.", content = @Content(schema = @Schema())),
@ApiResponse(responseCode = "409", description = "Conflict: duplicate debt position found.", content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = ProblemJson.class))),
@ApiResponse(responseCode = "404", description = "Upload not found.", content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = ProblemJson.class))),
@ApiResponse(responseCode = "500", description = "Service unavailable.", content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = ProblemJson.class)))})
@Get(value = "/organizations/{organizationFiscalCode}/debtpositions/file/{fileId}/status",
produces = MediaType.APPLICATION_JSON)
HttpResponse<FileStatus> getFileSatus(
HttpResponse<String> getFileSatus(
@Parameter(description = "The organization fiscal code", required = true)
@NotBlank @PathVariable String organizationFiscalCode,
@Parameter(description = "The fiscal code of the Organization.", required = true)
@NotBlank @PathVariable String fileId) {

FileStatus fileStatus = fileStatusService.getStatus(fileId);
FileStatus fileStatus = fileStatusService.getStatus(fileId, organizationFiscalCode);
log.debug("The Status related to file-id " + fileId + " has been found");

return HttpResponse.status(HttpStatus.OK)
.body(fileStatus);
.contentType(MediaType.APPLICATION_JSON)
.body(objectMapper.writeValueAsString(fileStatus));
}

}
16 changes: 16 additions & 0 deletions src/main/java/it/gov/pagopa/gpd/upload/entity/FailedIUPD.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package it.gov.pagopa.gpd.upload.entity;

import lombok.*;

import java.util.List;

@Builder(toBuilder = true)
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class FailedIUPD {
private int errorCode;
private String details;
private List<String> skippedIUPDs;
}
6 changes: 5 additions & 1 deletion src/main/java/it/gov/pagopa/gpd/upload/entity/Upload.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@ public class Upload {
private int current;
private int total;
private ArrayList<String> successIUPD;
private ArrayList<String> failedIUPD;
private ArrayList<FailedIUPD> failedIUPDs;
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
private LocalDateTime start;
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
private LocalDateTime end;

public void addFailures(FailedIUPD failedIUPD) {
this.failedIUPDs.add(failedIUPD);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class ErrorHandler implements ExceptionHandler<AppException, HttpResponse

@Override
public HttpResponse handle(HttpRequest request, AppException exception) {
log.error("[ERROR] AppException raised: ", exception);
log.error("[ERROR] AppException raised: ", exception.toString());

ProblemJson errorResponse = ProblemJson.builder()
.status(exception.getHttpStatus().getCode())
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/it/gov/pagopa/gpd/upload/model/FileStatus.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class FileStatus {
public String fileId;
public int processed;
public int uploaded;
private ArrayList<String> successIUPD;
private ArrayList<String> failedIUPD;
private LocalDateTime uploadTime;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,8 @@
@Slf4j
public class BlobStorageRepository implements FileRepository {

@Value("${blob.sas.url}")
private String blobURL;

@Value("${blob.sas.token}")
private String blobToken;
@Value("${blob.sas.connection}")
private String connectionString;

@Value("${blob.container.input}")
private String inputContainer;
Expand All @@ -40,8 +37,7 @@ public class BlobStorageRepository implements FileRepository {
@PostConstruct
public void init() {
blobServiceClient = new BlobServiceClientBuilder()
.endpoint(blobURL)
.sasToken(blobToken)
.connectionString(connectionString)
.buildClient();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.azure.cosmos.CosmosClientBuilder;
import com.azure.cosmos.CosmosClient;
import com.azure.cosmos.CosmosContainer;
import com.azure.cosmos.CosmosException;
import com.azure.cosmos.models.CosmosItemResponse;
import com.azure.cosmos.models.PartitionKey;
import io.micronaut.context.annotation.Context;
Expand Down Expand Up @@ -44,20 +45,28 @@ public void init() {
}

public Status saveStatus(Status status) {
CosmosItemResponse<Status> response = container.createItem(status);
if (response.getStatusCode() != HttpStatus.CREATED.getCode()) {
log.error("the Status saving was not successful: " + response);
throw new AppException(HttpStatus.SERVICE_UNAVAILABLE, "COSMOS UNAVAILABLE", "the Status saving was not successful");
try {
CosmosItemResponse<Status> response = container.createItem(status);
return response.getItem();
} catch (CosmosException ex) {
log.error("the Status retrieval was not successful: " + ex.getStatusCode());
if(ex.getStatusCode() == HttpStatus.INTERNAL_SERVER_ERROR.getCode())
throw new AppException(HttpStatus.INTERNAL_SERVER_ERROR, HttpStatus.INTERNAL_SERVER_ERROR.name(), "Status saving unavailable");
else
throw new AppException(HttpStatus.valueOf(ex.getStatusCode()), String.valueOf(ex.getStatusCode()), "Status saving failed");
}
return response.getItem();
}

public Status findStatusById(String id) {
CosmosItemResponse<Status> response = container.readItem(id, PartitionKey.NONE, Status.class);
if (response.getStatusCode() != HttpStatus.OK.getCode()) {
log.error("the Status retrieval was not successful: " + response);
throw new AppException(HttpStatus.SERVICE_UNAVAILABLE, "COSMOS UNAVAILABLE", "the Status retrieval was not successful");
public Status findStatusById(String id, String fiscalCode) {
try {
CosmosItemResponse<Status> response = container.readItem(id, new PartitionKey(fiscalCode), Status.class);
return response.getItem();
} catch (CosmosException ex) {
log.error("the Status retrieval was not successful: " + ex.getStatusCode());
if(ex.getStatusCode() == HttpStatus.INTERNAL_SERVER_ERROR.getCode())
throw new AppException(HttpStatus.INTERNAL_SERVER_ERROR, HttpStatus.INTERNAL_SERVER_ERROR.name(), "Status saving unavailable");
else
throw new AppException(HttpStatus.valueOf(ex.getStatusCode()), String.valueOf(ex.getStatusCode()), "Status retrieval failed");
}
return response.getItem();
}
}
Loading

0 comments on commit d9a9c47

Please sign in to comment.