Modifier la stratégie
Comment suivre ce chapitre
Entrées : Un portefeuille existant admissible, son état actuel et la nouvelle proposition choisie.
Étapes et résultat attendu : Choisissez la proposition et préparez le contrat avant l’envoi. Conservez l’identifiant de l’ordre de modification et suivez-le comme dans Ouvrir un portefeuille.
Alternatives et actions ultérieures : Vérifiez HasPendingOrder et le résultat API avant de permettre une autre modification. L’API reste l’autorité pour l’admissibilité.
Code source des DTO : PortfolioOrderOutputModel, PortfolioOutputModel, ProposalOutputModel, ReasonToChangeProposalOutputModel
Les variables affectées dans un bloc précédent sont réutilisées dans les suivants. Les saisies du client proviennent de votre interface. Conservez les identifiants et les valeurs de référence dans le contexte du client ; ne recréez pas ce contexte à chaque étape.
Important
Sélectionner une proposition
Action : Identifiez la proposition admissible pour la modification.
À conserver / résultat attendu : Conservez selectedProposalId et les motifs d’écart requis.
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.
Préparer le contrat
Action : Préparez le contrat de changement de stratégie.
À conserver / résultat attendu : Conservez les octets PDF ou contractPath comme dans Ouvrir un portefeuille.
Envoyer l’ordre
Action : Envoyez l’ordre de modification.
À conserver / résultat attendu : Conservez modificationOrderId et suivez l’ordre avant de considérer le changement comme terminé.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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;
Reconnaître le résultat
Extrait illustratif d’une réponse de modification. Conservez ce nouvel identifiant ; le succès HTTP ne signifie pas l’achèvement du changement d’investissement.
{"id":457,"portfolioId":789,"orderStatusId":1}Le catalogue des DTO contient les autres propriétés de la réponse. Traitez une demande échouée avant de poursuivre ; consultez Gestion des erreurs.