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.
Importante
Selezione della proposta
Operazione: Individua la proposta ammissibile per la modifica.
Da conservare / risultato atteso: Conserva selectedProposalId e i motivi di scostamento richiesti.
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
Operazione: Prepara il contratto per il cambio di strategia.
Da conservare / risultato atteso: Conserva i byte PDF o contractPath come in Apertura del portafoglio.
Invio dell’ordine
Operazione: Invia l’ordine di modifica.
Da conservare / risultato atteso: Conserva modificationOrderId e monitora l’ordine prima di considerare il cambiamento concluso.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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;
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.