Scelta della proposta

Come seguire questo capitolo

Dati richiesti: Linea di attività e categoria scelte, quindi risposte del cliente.

Passaggi e risultato atteso: Risolvi i riferimenti, raccogli gli ID delle risposte, calcola il rischio e lascia che il cliente scelga una proposta. Trasmetti questi valori ad Apertura del portafoglio.

Alternative e operazioni successive: La proposta raccomandata è il percorso principale. Una scelta diversa può richiedere motivi di scostamento.

Codice sorgente dei DTO: BusinessLineOutputModel, InvestmentCategoryOutputModel, ProposalOutputModel, QuestionnaireOutputModel, ReasonToChangeProposalOutputModel, ReasonToChangeProposalResponseOutputModel, RiskCategorizationOutputModel

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 client HTTP configurato. I riferimenti possono essere letti con GUEST; conserva il contesto cliente o amministrativo per le scritture.
Da conservare per il passaggio successivo: Linea di attività, categoria, ID delle risposte, rischio e proposalId scelto.
Il cliente sceglie la categoria d’investimento desiderata. Le linee e categorie comuni sono indicate sotto. Recupera i riferimenti attivati nell’ambiente prima di proporre un prodotto:
Vorsorge (previdenza):
  • Pilastro 3a (3a)
  • Libero passaggio (FZ)
Finance (gestione patrimoniale):
  • Invest (3b)

Nota

I tipi d’investimento possono essere attivati o disattivati secondo le esigenze dell’azienda.

Consultazione delle linee di attività

Dati richiesti: Codici della linea di attività e della categoria scelti per il prodotto.
Operazione: Recupera i riferimenti corrispondenti.
Da conservare / risultato atteso: Conserva businessLineId e investmentCategoryId.
Per un cliente interessato a un portafoglio 3a, recupera l’identificativo della linea Vorsorge e quello della categoria 3A. La linea seleziona il questionario attivo e il calcolo del rischio. Categoria e ID del rischio calcolato servono a ottenere le proposte:
								
var businessLines = await httpClient.GetFromJsonAsync<IList<BusinessLineOutputModel>>("api/v1/business-lines");
var businessLineVorsorge = businessLines.First(x => x.Code == "VORSORGE");
var investmentCategories = await httpClient.GetFromJsonAsync<IList<InvestmentCategoryOutputModel>>("api/v1/investment-categories/business-line-id/" + businessLineVorsorge.Id);
var investmentCategory3A = investmentCategories.First(x => x.Code == "3A");

								
HttpRequest businessLineRequest = HttpRequest.newBuilder()
    .timeout(Duration.ofMinutes(1))
    .uri(Settings.wmsUri("business-lines/code/VORSORGE"))
    .header("Accept-Language", "de-DE")
    .header("Authorization", "Bearer " + Settings.GUEST_TOKEN)
    .header("Content-Type", "application/json")
    .build();

var response = httpClient.send(businessLineRequest, BodyHandlers.ofString());
Api.requireSuccess(response);
BusinessLineOutputModel businessLineOutputModelObj = new Gson().fromJson(response.body(), BusinessLineOutputModel.class);
var businessLineId = businessLineOutputModelObj.Id;

HttpRequest investmentCategoryRequest = HttpRequest.newBuilder()
    .timeout(Duration.ofMinutes(1))
    .uri(Settings.wmsUri("investment-categories/code/3A"))
    .header("Accept-Language", "de-DE")
    .header("Authorization", "Bearer " + Settings.GUEST_TOKEN)
    .header("Content-Type", "application/json")
    .build();

response = httpClient.send(investmentCategoryRequest, BodyHandlers.ofString());
Api.requireSuccess(response);
InvestmentCategoryOutputModel investmentCategoryObj = new Gson().fromJson(response.body(), InvestmentCategoryOutputModel.class);
var investmentCategoryId = investmentCategoryObj.Id;

Risposte al questionario

Dati richiesti: businessLineId e risposte scelte dal cliente.
Operazione: Recupera il questionario, risolvi le risposte e calcola il rischio.
Da conservare / risultato atteso: Conserva responseIds e il rischio ottenuto.
Recupera il questionario della linea di attività e le possibili risposte.

Mostra il questionario attivo e raccogli selectedResponseCodes in tutte le sezioni. L’esempio usa scelte discrete. Per risposte numeriche, usa lo schema adatto e includi ResponseValue al salvataggio. Risolvi i codici negli ID di questo questionario. L’API valida risposte obbligatorie e adeguatezza; non presumere una versione o un ordine fisso delle domande:
								
var activeQuestionnaire = await httpClient.GetFromJsonAsync<QuestionnaireOutputModel>($"api/v1/questionnaires/business-line-id/{businessLineVorsorge.Id}/active");
var availableResponses = activeQuestionnaire.Sections.SelectMany(s => s.Questions).SelectMany(q => q.Responses).ToList();
// selectedResponseCodes comes from the client answers to the displayed questionnaire.
var responseIds = selectedResponseCodes.Select(code => availableResponses.Single(r => r.Code == code).Id).ToArray();
var responsesCsv = string.Join(",", responseIds);
var risk = await httpClient.GetFromJsonAsync<RiskCategorizationOutputModel>($"api/v1/risk-categorizations/business-line-id/{businessLineVorsorge.Id}/calculate-risk?csv-response-ids={Uri.EscapeDataString(responsesCsv)}");

								
HttpRequest questionnaireRequest = HttpRequest.newBuilder()
    .uri(Settings.wmsUri("questionnaires/business-line-id/" + businessLineId + "/active"))
    .timeout(Duration.ofMinutes(1))
    .header("Authorization", "Bearer " + Settings.GUEST_TOKEN).GET().build();
var questionnaireResponse = httpClient.send(questionnaireRequest, BodyHandlers.ofString());
Api.requireSuccess(questionnaireResponse);
QuestionnaireOutputModel activeQuestionnaire = new Gson().fromJson(questionnaireResponse.body(), QuestionnaireOutputModel.class);
var availableResponses = activeQuestionnaire.Sections.stream()
    .flatMap(s -> s.Questions.stream()).flatMap(q -> q.Responses.stream()).toList();
// selectedResponseCodes comes from the client answers to the displayed questionnaire.
var responseIds = selectedResponseCodes.stream().map(code -> availableResponses.stream()
    .filter(r -> code.equals(r.Code)).findFirst()
    .orElseThrow(() -> new IllegalArgumentException("Response not in the active questionnaire")).Id).toList();
var responsesCsv = responseIds.stream().map(String::valueOf).collect(java.util.stream.Collectors.joining(","));
HttpRequest riskRequest = HttpRequest.newBuilder()
    .uri(Settings.wmsUri("risk-categorizations/business-line-id/" + businessLineId
    + "/calculate-risk?csv-response-ids=" + java.net.URLEncoder.encode(responsesCsv, StandardCharsets.UTF_8)))
    .timeout(Duration.ofMinutes(1))
    .header("Authorization", "Bearer " + Settings.GUEST_TOKEN).GET().build();
var riskResponse = httpClient.send(riskRequest, BodyHandlers.ofString());
Api.requireSuccess(riskResponse);
RiskCategorizationOutputModel riskCategorizationObj = new Gson().fromJson(riskResponse.body(), RiskCategorizationOutputModel.class);

Recupero delle proposte

Dati richiesti: investmentCategoryId e rischio calcolato.
Operazione: Recupera le proposte e raccogli la scelta del cliente.
Da conservare / risultato atteso: Conserva proposalId e gli ID dei motivi di scostamento richiesti.
Con il rischio calcolato, recupera i modelli proposti e lascia che il cliente scelga proposalId dai risultati. Se nessuna proposta o riferimento corrisponde, gestisci i dati del prodotto come non disponibili anziché scegliere un valore predefinito:
								
var proposals = await httpClient.GetFromJsonAsync<List<ProposalOutputModel>>($"api/v1/proposals/investment-category-id/{investmentCategory3A.Id}/risk-id/{risk.Id}");
// The client chooses proposalId from the displayed proposals.
var proposalSelectedByUser = proposals.Single(x => x.Id == proposalId);

								
HttpRequest proposalRequest = HttpRequest.newBuilder()
    .timeout(Duration.ofMinutes(1))
    .uri(Settings.wmsUri("proposals/investment-category-id/" + investmentCategoryId + "/risk-id/" + riskCategorizationObj.Id))
    .header("Accept-Language", "de-DE")
    .header("Authorization", "Bearer " + Settings.GUEST_TOKEN)
    .header("Content-Type", "application/json")
    .build();

response = httpClient.send(proposalRequest, BodyHandlers.ofString());
Api.requireSuccess(response);

Type listType = new TypeToken<ArrayList<ProposalOutputModel>>(){}.getType();
List<ProposalOutputModel> proposalsListObj = new Gson().fromJson(response.body(), listType);

// proposalId is selected by the client from the displayed proposals.
var proposalSelectedByUser = proposalsListObj.stream().filter(x -> x.Id == proposalId)
    .findFirst().orElseThrow(() -> new IllegalArgumentException("Select a displayed proposal"));

La proposta può essere mostrata come segue:
Esempio di proposta d’investimento
Se il cliente sceglie un modello diverso da quello proposto, indica i motivi di scostamento. Si tratta di un semplice elenco di risposte con la struttura seguente:
									
public class ReasonToChangeProposalResponseOutputModel
{
    public long Id { get; set; }
    public string Code { get; set; }
    public string Description { get; set; }
    public int Order { get; set; }
}

public class ReasonToChangeProposalOutputModel
{
    public long Id { get; set; }
    public string Code { get; set; }
    public string Name { get; set; }
    public bool IsDeleted { get; set; }
    public IList<ReasonToChangeProposalResponseOutputModel> Responses { get; set; }
}

	
									
import java.util.List;
import java.util.Map;

import com.google.gson.annotations.SerializedName;

public class ReasonToChangeProposalResponseOutputModel {
    @SerializedName("id")
    public long Id;

    @SerializedName("code")
    public String Code;

    @SerializedName("description")
    public String Description;

    @SerializedName("order")
    public int Order;
}

public class ReasonToChangeProposalOutputModel {
    @SerializedName("id")
    public long Id;

    @SerializedName("code")
    public String Code;

    @SerializedName("name")
    public String Name;

    @SerializedName("isDeleted")
    public boolean IsDeleted;

    @SerializedName("responses")
    public List<ReasonToChangeProposalResponseOutputModel> Responses;
}

Recupera questo elenco come segue:
									
var reasonsToChangeProposal = await httpClient.GetFromJsonAsync<ReasonToChangeProposalOutputModel>($"api/v1/reason-to-change-proposed-proposal/investment-category-id/{investmentCategory3A.Id}/active");

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

response = httpClient.send(reasonToChangeRequest, BodyHandlers.ofString());
Api.requireSuccess(response);
ReasonToChangeProposalOutputModel reasonToChangeProposalObj = new Gson().fromJson(response.body(), ReasonToChangeProposalOutputModel.class);

In caso di scostamento dalla proposta raccomandata, raccogli gli ID pertinenti in selectedReasonIds. Usa un elenco vuoto se non servono motivi e non sceglierli automaticamente. Invia questi ID con l’ordine di apertura, come indicato nel capitolo successivo.