Modifica della strategia

Come seguire questo capitolo

Dati richiesti: Un portafoglio esistente ammissibile, il suo stato attuale e la nuova proposta scelta.

Passaggi e risultato atteso: Scegli la proposta e prepara il contratto prima dell’invio. Conserva l’ID dell’ordine di modifica e monitoralo come descritto in Apertura del portafoglio.

Alternative e operazioni successive: Verifica HasPendingOrder e il risultato API prima di consentire un’altra modifica. L’API resta l’autorità per l’ammissibilità.

Codice sorgente dei DTO: PortfolioOrderOutputModel, PortfolioOutputModel, ProposalOutputModel, ReasonToChangeProposalOutputModel

Le variabili assegnate in un blocco precedente vengono riutilizzate nei successivi. I dati inseriti dal cliente provengono dalla tua interfaccia. Conserva identificativi e valori di riferimento nel contesto del cliente; non ricreare il contesto a ogni passaggio.

Gli esempi utilizzano classi helper condivise. Consulta Classi helper condivise: codice C# e Java completo prima di copiare un esempio.
Prima di iniziare: Un portfolioId selezionato, un token CLIENT o ADMIN autorizzato e nessun ordine in sospeso. Verifica il portafoglio e scegli una proposta alternativa.
Da conservare per il passaggio successivo: Un nuovo ordine di modifica. Monitora il suo stato prima di consentire un’altra modifica.
Il cliente può richiedere un altro modello se prodotto, ciclo di vita del portafoglio e ordini in sospeso lo consentono. Se il rischio del nuovo modello non corrisponde al profilo del cliente, fornisci gli ID delle risposte relative ai motivi di scostamento.

Importante

Verifica ciclo di vita e ordini in sospeso prima di proporre una modifica. L’API resta l’autorità per l’ammissibilità.

Selezione della proposta

Dati richiesti: Lo snapshot attuale e la selezione del cliente.
Operazione: Individua la proposta ammissibile per la modifica.
Da conservare / risultato atteso: Conserva selectedProposalId e i motivi di scostamento richiesti.
Recupera lo snapshot attuale e le proposte della categoria del portafoglio. Lascia che il cliente scelga selectedProposalId da alternativeProposals e raccogli selectedReasonIds quando necessario. Queste decisioni spettano al cliente; non scegliere automaticamente la prima proposta o il primo motivo.
								
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var clientPortfolio = await httpClient.GetFromJsonAsync<PortfolioOutputModel>($"api/v1/user-portfolios/portfolio-id/{portfolioId}?portfolio-view-as=Snapshot");
var url = $"api/v1/proposals/investment-category-id/{clientPortfolio.InvestmentCategoryId}";
var proposals = await httpClient.GetFromJsonAsync<List<ProposalOutputModel>>(url);
var alternativeProposals = proposals.Where(x => x.Id != clientPortfolio.ProposalId).ToList();

									
								
HttpRequest portfolioRequest = HttpRequest.newBuilder()
    .timeout(Duration.ofMinutes(1))
    .uri(Settings.wmsUri("user-portfolios/portfolio-id/" + portfolioId + "?portfolio-view-as=Snapshot"))
    .header("Accept-Language", "de-DE")
    .header("Authorization", "Bearer " + accessToken)
    .header("Content-Type", "application/json")
    .build();

var response = httpClient.send(portfolioRequest, BodyHandlers.ofString());
Api.requireSuccess(response);
PortfolioOutputModel clientPortfolio = new Gson().fromJson(response.body(), PortfolioOutputModel.class);

// Alternative proposals list
HttpRequest proposalsRequest = HttpRequest.newBuilder()
    .timeout(Duration.ofMinutes(1))
    .uri(Settings.wmsUri("proposals/investment-category-id/" + clientPortfolio.InvestmentCategoryId))
    .header("Accept-Language", "de-DE")
    .header("Authorization", "Bearer " + accessToken)
    .header("Content-Type", "application/json")
    .build();

response = httpClient.send(proposalsRequest, BodyHandlers.ofString());
Api.requireSuccess(response);
Type listType = new TypeToken<ArrayList<ProposalOutputModel>>(){}.getType();
List<ProposalOutputModel> proposalObjs = new Gson().fromJson(response.body(), listType);

var alternativeProposals = proposalObjs.stream().filter(x -> x.Id != clientPortfolio.ProposalId).toList();
// selectedProposalId is chosen by the client from alternativeProposals.

Preparazione del contratto

Dati richiesti: La proposta scelta e i dati del cliente.
Operazione: Prepara il contratto per il cambio di strategia.
Da conservare / risultato atteso: Conserva i byte PDF o contractPath come in Apertura del portafoglio.
Prepara un nuovo contratto per selectedProposalId, senza riutilizzare quello dell’apertura. Segui Preparazione del contratto con i dati attuali e la nuova proposta in formFields. Imposta contractPath con il PDF completo inviato qui. In C#, se il servizio PDF restituisce pdfContractAsByteArray, salva questi byte in un file distinto e usa quel percorso; non inviare il modello vuoto.

Invio dell’ordine

Dati richiesti: portfolioId, selectedProposalId, motivi di scostamento e contratto PDF.
Operazione: Invia l’ordine di modifica.
Da conservare / risultato atteso: Conserva modificationOrderId e monitora l’ordine prima di considerare il cambiamento concluso.
L’esempio invia la richiesta con il nuovo ID della proposta scelto dal cliente. L’API registra un ordine di modifica; la strategia cambia dopo l’elaborazione successiva.
								
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Please note:
//   Provide the completed contract required for this modification.
//   The client chooses selectedProposalId and selectedReasonIds.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var currentPortfolio = await httpClient.GetFromJsonAsync<PortfolioOutputModel>($"api/v1/user-portfolios/portfolio-id/{portfolioId}?portfolio-view-as=Snapshot");
if (currentPortfolio.HasPendingOrder)
{
    throw new InvalidOperationException("A portfolio order is pending");
}
var reasonToChangeProposalUrl = $"api/v1/reason-to-change-proposed-proposal/investment-category-id/{currentPortfolio.InvestmentCategoryId}/active";
var reasonToChangeProposal = await httpClient.GetFromJsonAsync<ReasonToChangeProposalOutputModel>(reasonToChangeProposalUrl);
var orderPortfolioModificationInputModel = new
{
    PortfolioId = portfolioId,
    // Assume this is the new portfolio model selected by client
    ProposalId = selectedProposalId,
    // Assume this is reason to change proposal selected by client
    ReasonToChangeProposalResponsesIds = selectedReasonIds
};
// contractPath points to the completed contract for this modification.
var byteArray = await File.ReadAllBytesAsync(contractPath);
using var httpContent = GuideHttp.CreateMultipartContent(orderPortfolioModificationInputModel, byteArray);
var httpResponseMessage = await httpClient.PostAsync("api/v1/user-portfolio-orders/modification", httpContent);
httpResponseMessage.EnsureSuccessStatusCode();
var modificationOrder = JsonConvert.DeserializeObject<PortfolioOrderOutputModel>(await httpResponseMessage.Content.ReadAsStringAsync());
var modificationOrderId = modificationOrder.Id;

									
								
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Please note:
//   Provide the completed contract required for this modification.
//   The client chooses selectedProposalId and selectedReasonIds.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

HttpRequest reasonToChangeRequest = HttpRequest.newBuilder()
    .timeout(Duration.ofMinutes(1))
    .uri(Settings.wmsUri("reason-to-change-proposed-proposal/investment-category-id/" + clientPortfolio.InvestmentCategoryId + "/active"))
    .header("Accept-Language", "de-DE")
    .header("Authorization", "Bearer " + accessToken)
    .header("Content-Type", "application/json")
    .build();

response = httpClient.send(reasonToChangeRequest, BodyHandlers.ofString());
Api.requireSuccess(response);
ReasonToChangeProposalOutputModel reasonToChangeProposalObj = new Gson().fromJson(response.body(), ReasonToChangeProposalOutputModel.class);
// selectedReasonIds contains the reasons selected by the client.

JsonObject orderPortfolioModificationInputModel = new JsonObject();
orderPortfolioModificationInputModel.addProperty("PortfolioId", portfolioId);
orderPortfolioModificationInputModel.addProperty("ProposalId", selectedProposalId);
orderPortfolioModificationInputModel.add("ReasonToChangeProposalResponsesIds", new Gson().toJsonTree(selectedReasonIds));

// contractPath points to the completed contract for this modification.
var contractBytes = Files.readAllBytes(contractPath);

MultiPartBodyPublisher multipartBody = new MultiPartBodyPublisher()
    .addPart("jsonPayload", orderPortfolioModificationInputModel.toString())
    .addPart("userContracts", () -> new ByteArrayInputStream(contractBytes), "Contract.pdf", "application/pdf");

HttpRequest planChangeRequest = HttpRequest.newBuilder()
    .timeout(Duration.ofMinutes(1))
    .uri(Settings.wmsUri("user-portfolio-orders/modification"))
    .header("Accept-Language", "de-DE")
    .header("Authorization", "Bearer " + accessToken)
    .header("Content-Type", "multipart/form-data; boundary=" + multipartBody.getBoundary())
    .POST(multipartBody.build())
    .build();

response = httpClient.send(planChangeRequest, BodyHandlers.ofString());
Api.requireSuccess(response);
PortfolioOrderOutputModel modificationOrder = new Gson().fromJson(response.body(), PortfolioOrderOutputModel.class);
var modificationOrderId = modificationOrder.Id;

Dopo il successo, conserva modificationOrderId e leggi il suo stato tramite la procedura di monitoraggio dell’ordine. Aggiorna il portafoglio per osservare HasPendingOrder durante l’elaborazione.
Quando HasPendingOrder è TRUE, non è consentita alcuna modifica della strategia.
Aggiorna portafoglio e stato dopo l’elaborazione. Prosegui solo se HasPendingOrder è false e il ciclo di vita consente un’altra modifica; l’API ne verifica comunque l’ammissibilità.

Riconoscere il risultato

Estratto illustrativo della risposta di modifica. Conserva questo nuovo ID; il successo HTTP non significa il completamento del cambio d’investimento.

{"id":457,"portfolioId":789,"orderStatusId":1}

Il catalogo DTO contiene le altre proprietà della risposta. Gestisci una richiesta non riuscita prima di proseguire; consulta Gestione degli errori.