11package it .gov .pagopa .idpay .transactions .service ;
22
33import it .gov .pagopa .common .web .exception .ClientExceptionNoBody ;
4+ import it .gov .pagopa .common .web .exception .ClientExceptionWithBody ;
45import it .gov .pagopa .idpay .transactions .connector .rest .UserRestClient ;
56import it .gov .pagopa .idpay .transactions .connector .rest .dto .FiscalCodeInfoPDV ;
67import it .gov .pagopa .idpay .transactions .dto .DownloadInvoiceResponseDTO ;
910import it .gov .pagopa .idpay .transactions .model .RewardTransaction ;
1011import it .gov .pagopa .idpay .transactions .repository .RewardTransactionRepository ;
1112import it .gov .pagopa .idpay .transactions .storage .InvoiceStorageClient ;
13+ import it .gov .pagopa .idpay .transactions .utils .ExceptionConstants ;
14+ import it .gov .pagopa .idpay .transactions .utils .Utilities ;
1215import lombok .extern .slf4j .Slf4j ;
1316import org .apache .commons .lang3 .StringUtils ;
1417import org .springframework .data .domain .Page ;
1518import org .springframework .data .domain .PageImpl ;
1619import org .springframework .data .domain .Pageable ;
1720import org .springframework .http .HttpStatus ;
21+ import org .springframework .http .codec .multipart .FilePart ;
1822import org .springframework .stereotype .Service ;
1923import reactor .core .publisher .Mono ;
2024
25+ import java .io .IOException ;
26+ import java .io .InputStream ;
27+ import java .nio .file .Files ;
28+ import java .nio .file .Path ;
29+ import java .nio .file .Paths ;
30+
2131import static it .gov .pagopa .idpay .transactions .utils .ExceptionConstants .ExceptionMessage .TRANSACTION_MISSING_INVOICE ;
2232
2333@ Service
@@ -29,7 +39,7 @@ public class PointOfSaleTransactionServiceImpl implements PointOfSaleTransaction
2939 private final InvoiceStorageClient invoiceStorageClient ;
3040
3141 protected PointOfSaleTransactionServiceImpl (
32- UserRestClient userRestClient , RewardTransactionRepository rewardTransactionRepository , InvoiceStorageClient invoiceStorageClient ) {
42+ UserRestClient userRestClient , RewardTransactionRepository rewardTransactionRepository , InvoiceStorageClient invoiceStorageClient ) {
3343 this .userRestClient = userRestClient ;
3444 this .rewardTransactionRepository = rewardTransactionRepository ;
3545 this .invoiceStorageClient = invoiceStorageClient ;
@@ -91,7 +101,79 @@ public Mono<DownloadInvoiceResponseDTO> downloadTransactionInvoice(
91101 });
92102 }
93103
94- private Mono <Page <RewardTransaction >> getTransactions (String merchantId , String initiativeId , String pointOfSaleId , String userId , String productGtin , String status , Pageable pageable ) {
104+ @ Override
105+ public Mono <Void > updateInvoiceTransaction (String transactionId , String merchantId , String pointOfSaleId , FilePart file , String docNumber ) {
106+ try {
107+ Utilities .checkFileExtensionOrThrow (file );
108+
109+ return rewardTransactionRepository .findTransaction (merchantId , pointOfSaleId , transactionId )
110+ .switchIfEmpty (Mono .error (new ClientExceptionNoBody (HttpStatus .BAD_REQUEST , TRANSACTION_MISSING_INVOICE )))
111+ .flatMap (rewardTransaction -> {
112+ String status = rewardTransaction .getStatus ();
113+ InvoiceData oldDocumentData = null ;
114+
115+ if (SyncTrxStatus .INVOICED .name ().equalsIgnoreCase (status )) {
116+ oldDocumentData = rewardTransaction .getInvoiceData ();
117+ } else {
118+ throw new ClientExceptionNoBody (HttpStatus .BAD_REQUEST , TRANSACTION_MISSING_INVOICE );
119+ }
120+ if (!rewardTransaction .getMerchantId ().equals (merchantId )) {
121+ throw new ClientExceptionWithBody (HttpStatus .BAD_REQUEST , ExceptionConstants .ExceptionCode .GENERIC_ERROR ,
122+ "The merchant with id [%s] associated to the transaction is not equal to the merchant with id [%s]" .formatted (
123+ rewardTransaction .getMerchantId (), merchantId ));
124+ }
125+ if (!rewardTransaction .getPointOfSaleId ().equals (pointOfSaleId )) {
126+ throw new ClientExceptionWithBody (HttpStatus .BAD_REQUEST , ExceptionConstants .ExceptionCode .GENERIC_ERROR ,
127+ "The pointOfSaleId with id [%s] associated to the transaction is not equal to the pointOfSaleId with id [%s]" .formatted (
128+ rewardTransaction .getPointOfSaleId (), pointOfSaleId ));
129+ }
130+
131+ String oldFilename = oldDocumentData .getFilename ();
132+
133+ String blobPath = String .format (
134+ "invoices/merchant/%s/pos/%s/transaction/%s/invoice/%s" ,
135+ merchantId , pointOfSaleId , transactionId , file .filename ());
136+ String oldBlobPath = String .format (
137+ "invoices/merchant/%s/pos/%s/transaction/%s/invoice/%s" ,
138+ merchantId , pointOfSaleId , transactionId , oldFilename );
139+ Path tempPath = Paths .get (System .getProperty ("java.io.tmpdir" ), file .filename ());
140+
141+ return file .transferTo (tempPath )
142+ .then (Mono .fromCallable (() -> {
143+ // Delete old file from storage
144+ invoiceStorageClient .deleteFile (oldBlobPath );
145+
146+ // Upload new file on storage
147+ try (InputStream is = Files .newInputStream (tempPath )) {
148+ String contentType = file .headers ().getContentType () != null
149+ ? file .headers ().getContentType ().toString ()
150+ : null ;
151+ invoiceStorageClient .upload (is , blobPath , contentType );
152+ }
153+
154+ return null ;
155+ }))
156+ .onErrorMap (IOException .class , e -> {
157+ log .error ("Error uploading file to storage for transaction [{}]" , Utilities .sanitizeString (transactionId ), e );
158+ throw new ClientExceptionWithBody (HttpStatus .INTERNAL_SERVER_ERROR ,
159+ ExceptionConstants .ExceptionCode .GENERIC_ERROR , "Error uploading invoice file" , e );
160+ })
161+ .then (Mono .fromRunnable (() ->
162+ // Update Transaction document
163+ rewardTransaction .setInvoiceData (InvoiceData .builder ()
164+ .filename (file .filename ())
165+ .docNumber (docNumber )
166+ .build ())
167+ ))
168+ .then (rewardTransactionRepository .save (rewardTransaction ).then ());
169+ });
170+ } catch (Exception e ) {
171+ throw new ClientExceptionWithBody (HttpStatus .INTERNAL_SERVER_ERROR ,
172+ ExceptionConstants .ExceptionCode .GENERIC_ERROR , "Error uploading invoice file" , e );
173+ }
174+ }
175+
176+ private Mono <Page <RewardTransaction >> getTransactions (String merchantId , String initiativeId , String pointOfSaleId , String userId , String productGtin , String status , Pageable pageable ) {
95177 return rewardTransactionRepository .findByFilterTrx (merchantId , initiativeId , pointOfSaleId , userId , productGtin , status , pageable )
96178 .collectList ()
97179 .zipWith (rewardTransactionRepository .getCount (merchantId , initiativeId , pointOfSaleId , userId , productGtin , status ))
0 commit comments