diff --git a/samples/MyCRM.Lodgement.Automation/MyCRM.Lodgement.Automation.csproj b/samples/MyCRM.Lodgement.Automation/MyCRM.Lodgement.Automation.csproj index 003a3f5..ecd6a51 100644 --- a/samples/MyCRM.Lodgement.Automation/MyCRM.Lodgement.Automation.csproj +++ b/samples/MyCRM.Lodgement.Automation/MyCRM.Lodgement.Automation.csproj @@ -4,7 +4,7 @@ Exe true full - net6.0 + net8.0 latest diff --git a/samples/MyCRM.Lodgement.Core/Enums/ApplicationScenario.cs b/samples/MyCRM.Lodgement.Core/Enums/ApplicationScenario.cs new file mode 100644 index 0000000..711163b --- /dev/null +++ b/samples/MyCRM.Lodgement.Core/Enums/ApplicationScenario.cs @@ -0,0 +1,9 @@ +using System.ComponentModel; + +namespace MyCRM.Lodgement.Common.Models; + +public enum LoanApplicationScenario +{ + [Description("NewLoanApplication")] + NewLoanApplication, +} \ No newline at end of file diff --git a/samples/MyCRM.Lodgement.Core/LixiPackageSamples/NewLoanApplication.json b/samples/MyCRM.Lodgement.Core/LixiPackageSamples/NewLoanApplication.json new file mode 100644 index 0000000..b70cc6b --- /dev/null +++ b/samples/MyCRM.Lodgement.Core/LixiPackageSamples/NewLoanApplication.json @@ -0,0 +1,1730 @@ +{ + "ProductionData": false, + "Content": { + "Application": { + "UniqueID": "LoanScenario-5542468-ZVVVNU1", + "Address": [ + { + "AustralianPostCode": "2640", + "AustralianState": "NSW", + "City": "Albury", + "Country": "AU", + "Latitude": -36.0741418, + "Longitude": 146.9101373, + "Suburb": "Albury", + "Type": "Standard", + "UniqueID": "Address_11696101", + "Standard": { + "StreetName": "Thurgoona", + "StreetNumber": "616", + "StreetType": "Street" + } + }, + { + "AustralianPostCode": "6059", + "AustralianState": "WA", + "City": "Dianella", + "Country": "AU", + "Latitude": -31.8891855, + "Longitude": 115.8697586, + "Suburb": "Dianella", + "Type": "Standard", + "UniqueID": "Address_11829994", + "Standard": { + "StreetName": "Booker", + "StreetNumber": "75", + "StreetType": "Street" + } + }, + { + "AustralianPostCode": "3978", + "AustralianState": "VIC", + "City": "clyde north", + "Country": "AU", + "Suburb": "clyde north", + "Type": "Standard", + "UniqueID": "Address_13531793", + "Standard": { + "StreetName": "harrys", + "StreetNumber": "12", + "StreetType": "Avenue" + } + }, + { + "AustralianPostCode": "4113", + "AustralianState": "QLD", + "City": "Runcorn", + "Country": "AU", + "Latitude": -27.587909, + "Longitude": 153.076485, + "Suburb": "Runcorn", + "Type": "Standard", + "UniqueID": "Address_13627215", + "Standard": { + "StreetName": "Diamond", + "StreetNumber": "8", + "StreetType": "Place", + "Unit": "unit 60" + } + }, + { + "AustralianPostCode": "4113", + "AustralianState": "QLD", + "City": "Runcorn", + "Country": "AU", + "Latitude": -27.587909, + "Longitude": 153.076485, + "Suburb": "Runcorn", + "Type": "Standard", + "UniqueID": "Address_13627292", + "Standard": { + "StreetName": "Diamond", + "StreetNumber": "8", + "StreetType": "Place", + "Unit": "unit 50" + } + }, + { + "AustralianPostCode": "4113", + "AustralianState": "QLD", + "City": "Runcorn", + "Country": "AU", + "Latitude": -27.5888638, + "Longitude": 153.0762382, + "Suburb": "Runcorn", + "Type": "Standard", + "UniqueID": "Address_13627438", + "Standard": { + "StreetName": "Diamond", + "StreetNumber": "20", + "StreetType": "Place" + } + }, + { + "AustralianPostCode": "4113", + "AustralianState": "QLD", + "City": "Runcorn", + "Country": "AU", + "Latitude": -27.5892457, + "Longitude": 153.0769254, + "Suburb": "Runcorn", + "Type": "Standard", + "UniqueID": "Address_13627498", + "Standard": { + "StreetName": "Diamond", + "StreetNumber": "45", + "StreetType": "Place" + } + }, + { + "AustralianPostCode": "3029", + "AustralianState": "VIC", + "City": "Tarneit", + "Country": "AU", + "Suburb": "Tarneit", + "Type": "Standard", + "UniqueID": "Address_11168887", + "Standard": { + "StreetName": "Lamington", + "StreetNumber": "18", + "StreetType": "Drive" + } + }, + { + "AustralianPostCode": "3124", + "AustralianState": "VIC", + "City": "Camberwell", + "Country": "AU", + "Latitude": -37.8281618, + "Longitude": 145.0587268, + "Suburb": "Camberwell", + "Type": "Standard", + "UniqueID": "Address_3510876", + "Standard": { + "StreetNumber": "19" + } + }, + { + "AustralianPostCode": "2000", + "AustralianState": "NSW", + "City": "", + "Country": "AU", + "Latitude": -33.8688197, + "Longitude": 151.2092955, + "Suburb": "", + "UniqueID": "Address_3386157" + }, + { + "AustralianPostCode": "4213", + "AustralianState": "QLD", + "City": "Mudgeeraba", + "Country": "AU", + "Latitude": -28.1040346, + "Longitude": 153.3530469, + "Suburb": "Mudgeeraba", + "Type": "Standard", + "UniqueID": "Address_8247579", + "Standard": { + "StreetName": "Strawberry", + "StreetNumber": "20-22", + "StreetType": "Road" + } + }, + { + "AustralianPostCode": "4000", + "AustralianState": "QLD", + "City": "Brisbane City", + "Country": "AU", + "Suburb": "Brisbane City", + "Type": "Standard", + "UniqueID": "Address_11087379", + "Standard": { + "StreetName": "Quay", + "StreetNumber": "111", + "StreetType": "Street" + } + }, + { + "AustralianPostCode": "4069", + "AustralianState": "QLD", + "City": "Fig Tree Pocket", + "Country": "AU", + "Latitude": -27.5286302, + "Longitude": 152.9664001, + "Suburb": "Fig Tree Pocket", + "Type": "Standard", + "UniqueID": "Address_11555582", + "Standard": { + "StreetName": "Oasis", + "StreetNumber": "9", + "StreetType": "Court" + } + }, + { + "AustralianPostCode": "4110", + "AustralianState": "QLD", + "City": "Pallara", + "Country": "AU", + "Latitude": -27.6174073, + "Longitude": 153.0116075, + "Suburb": "Pallara", + "Type": "Standard", + "UniqueID": "Address_12459614", + "Standard": { + "StreetName": "Ponting", + "StreetNumber": "95" + } + }, + { + "AustralianPostCode": "2000", + "AustralianState": "NSW", + "City": "Sydney", + "Country": "AU", + "Latitude": -33.869167, + "Longitude": 151.2087416, + "Suburb": "Sydney", + "Type": "Standard", + "UniqueID": "Address_3416383", + "Standard": { + "StreetNumber": "135" + } + }, + { + "AustralianPostCode": "4000", + "AustralianState": "QLD", + "City": "BRISBANE CITY", + "Country": "AU", + "Latitude": -27.4676885, + "Longitude": 153.0303725, + "Suburb": "BRISBANE CITY", + "Type": "Standard", + "UniqueID": "Address_807535", + "Standard": { + "Level": "26", + "StreetName": "EAGLE", + "StreetNumber": "111", + "StreetType": "Street" + } + } + ], + "BusinessChannel": { + "CompanyName": "TestBank", + "OtherIdentifier": "C9RZZZ", + "UniqueID": "Lender_5054", + "Contact": { + "WebAddress": "https://www.Lender.com.au/", + "OfficePhone": { + "Number": "02 9999 9999" + } + } + }, + "ContributionFunds": [ + { + "Amount": 200000, + "Description": "FUNDS_AVAILABLE", + "Type": "Genuine Savings", + "UniqueID": "Funds_28548183" + } + ], + "DetailedComment": [ + { + "ContextDescription": "Immediate goals & objectives", + "Comment": "Testing - SIT NextGen Submission" + }, + { + "ContextDescription": "Advisor Notes - ", + "Comment": "Testing - SIT NextGen Submission" + }, + { + "ContextDescription": "Lender and product selection rationale - Summary", + "Comment": "Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission

Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission Testing - SIT NextGen Submission" + } + ], + "Household": [ + { + "NumberOfAdults": 2, + "NumberOfDependants": 0, + "UniqueID": "Family_7102929", + "ExpenseDetails": { + "LivingExpense": [ + { + "Amount": 800, + "Category": "Groceries", + "Description": "Groceries", + "Frequency": "Monthly" + }, + { + "Amount": 3300, + "Category": "Primary Residence Running Costs", + "Description": "Electricity & Gas, Council Rates, Water & Sewer, Body Corporate", + "Frequency": "Monthly" + }, + { + "Amount": 1200, + "Category": "Investment Property Running Costs", + "Description": "Building Insurance", + "Frequency": "Monthly" + }, + { + "Amount": 260, + "Category": "Health Insurance", + "Description": "Health Insurance", + "Frequency": "Monthly" + }, + { + "Amount": 100, + "Category": "General Basic Insurances", + "Description": "Vehicle Insurance", + "Frequency": "Monthly" + }, + { + "Amount": 50, + "Category": "Medical and health", + "Description": "Medical & Health", + "Frequency": "Monthly" + }, + { + "Amount": 200, + "Category": "Clothing and personal care", + "Description": "Clothing & Footwear, Personal Care", + "Frequency": "Monthly" + }, + { + "Amount": 530, + "Category": "Recreation and entertainment", + "Description": "Cinema/Concerts/Memberships, Dining Out, Gym / Sports", + "Frequency": "Monthly" + }, + { + "Amount": 170, + "Category": "Telephone, internet, pay TV and media streaming subscriptions", + "Description": "Home/Mobile Phone, Internet, Pay TV & Media Streaming Subscriptions", + "Frequency": "Monthly" + }, + { + "Amount": 375, + "Category": "Transport", + "Description": "Petrol, Registration, Vehicle Maintenance, Tolls/Parking etc", + "Frequency": "Monthly" + } + ] + } + } + ], + "Insurance": [ + { + "Description": "Life Insurance", + "InsuranceType": "Life Insurance", + "InsuredAmount": 150000, + "OtherInsurerName": "", + "UniqueID": "Insurance_15254658", + "InsuredParty": [ + { + "x_InsuredParty": "Family_8477374" + }, + { + "x_InsuredParty": "Family_8477375" + } + ] + } + ], + "Liability": [ + { + "AnnualInterestRate": 0, + "ClearingFromThisLoan": false, + "ClearingFromThisLoanAmount": 0, + "CreditCardType": "MasterCard", + "CreditLimit": 15000, + "HasArrears": false, + "OutstandingBalance": 0, + "Type": "Credit Card", + "UniqueID": "FinancialLiability_45722253", + "AccountNumber": {}, + "ContinuingRepayment": [ + { + "LoanPaymentScheduleType": "Even Total Payments", + "PaymentType": "Principal and Interest", + "TaxDeductible": false + } + ], + "PercentOwned": { + "Proportions": "Specified", + "Owner": [ + { + "Percent": 50, + "x_Party": "Family_8477374" + }, + { + "Percent": 50, + "x_Party": "Family_8477375" + } + ] + }, + "Repayment": [ + { + "LoanPaymentScheduleType": "Even Total Payments", + "PaymentType": "Principal and Interest", + "Regular": true, + "RepaymentAmount": 0, + "RepaymentFrequency": "Monthly", + "TaxDeductible": false + } + ] + }, + { + "AnnualInterestRate": 0, + "ClearingFromThisLoan": false, + "ClearingFromThisLoanAmount": 0, + "CreditCardType": "Other Credit Card", + "CreditLimit": 17000, + "HasArrears": false, + "OutstandingBalance": 0, + "Type": "Credit Card", + "UniqueID": "FinancialLiability_45722241", + "AccountNumber": {}, + "ContinuingRepayment": [ + { + "LoanPaymentScheduleType": "Even Total Payments", + "PaymentType": "Principal and Interest", + "TaxDeductible": false + } + ], + "PercentOwned": { + "Proportions": "Specified", + "Owner": [ + { + "Percent": 100, + "x_Party": "Family_8477374" + }, + { + "Percent": 0, + "x_Party": "Family_8477375" + } + ] + }, + "Repayment": [ + { + "LoanPaymentScheduleType": "Even Total Payments", + "PaymentType": "Principal and Interest", + "Regular": true, + "RepaymentAmount": 0, + "RepaymentFrequency": "Monthly", + "TaxDeductible": false + } + ] + }, + { + "AnnualInterestRate": 0, + "ClearingFromThisLoan": false, + "ClearingFromThisLoanAmount": 415817, + "CreditLimit": 415817, + "HasArrears": false, + "OutstandingBalance": 415817, + "Type": "Mortgage Loan", + "UniqueID": "FinancialLiability_63101829", + "AccountNumber": { + "FinancialInstitution": "Other", + "OtherFIName": "ANZ Australia" + }, + "ContinuingRepayment": [ + { + "LoanPaymentScheduleType": "Even Total Payments", + "PaymentType": "Principal and Interest", + "TaxDeductible": false + } + ], + "OriginalTerm": { + "PaymentType": "Principal and Interest", + "PaymentTypeUnits": "Years", + "TotalTermDuration": 30 + }, + "PercentOwned": { + "Proportions": "Specified", + "Owner": [ + { + "Percent": 50, + "x_Party": "Family_8477374" + }, + { + "Percent": 50, + "x_Party": "Family_8477375" + } + ] + }, + "Repayment": [ + { + "LoanPaymentScheduleType": "Even Total Payments", + "PaymentType": "Principal and Interest", + "Regular": true, + "RepaymentAmount": 2666, + "RepaymentFrequency": "Monthly", + "TaxDeductible": false + } + ], + "Security": [ + { + "Priority": "First Mortgage", + "x_Security": "FinancialInfo_15708480" + } + ] + }, + { + "AnnualInterestRate": 5.2, + "ClearingFromThisLoan": false, + "ClearingFromThisLoanAmount": 203000, + "CreditLimit": 203000, + "HasArrears": false, + "OutstandingBalance": 203000, + "Type": "Mortgage Loan", + "UniqueID": "FinancialLiability_47859966", + "AccountNumber": { + "FinancialInstitution": "Other", + "OtherFIName": "Westpac" + }, + "ContinuingRepayment": [ + { + "LoanPaymentScheduleType": "Even Total Payments", + "PaymentType": "Principal and Interest", + "TaxDeductible": false + } + ], + "OriginalTerm": { + "PaymentType": "Principal and Interest", + "PaymentTypeUnits": "Years", + "TotalTermDuration": 30 + }, + "PercentOwned": { + "Proportions": "Specified", + "Owner": [ + { + "Percent": 100, + "x_Party": "Family_8477375" + }, + { + "Percent": 0, + "x_Party": "Family_8477374" + } + ] + }, + "Repayment": [ + { + "LoanPaymentScheduleType": "Even Total Payments", + "PaymentType": "Principal and Interest", + "Regular": true, + "RepaymentAmount": 1400, + "RepaymentFrequency": "Monthly", + "TaxDeductible": false + } + ], + "Security": [ + { + "Priority": "First Mortgage", + "x_Security": "FinancialInfo_13162992" + } + ] + }, + { + "AnnualInterestRate": 0, + "ClearingFromThisLoan": false, + "ClearingFromThisLoanAmount": 291476, + "CreditLimit": 291476, + "HasArrears": false, + "OutstandingBalance": 291476, + "Type": "Mortgage Loan", + "UniqueID": "FinancialLiability_55290391", + "AccountNumber": { + "FinancialInstitution": "Other", + "OtherFIName": "Adelaide Bank" + }, + "ContinuingRepayment": [ + { + "LoanPaymentScheduleType": "Even Total Payments", + "PaymentType": "Principal and Interest", + "TaxDeductible": true + } + ], + "OriginalTerm": { + "PaymentType": "Principal and Interest", + "PaymentTypeUnits": "Years", + "TotalTermDuration": 26 + }, + "PercentOwned": { + "Proportions": "Specified", + "Owner": [ + { + "Percent": 100, + "x_Party": "Family_8477375" + }, + { + "Percent": 0, + "x_Party": "Family_8477374" + } + ] + }, + "Repayment": [ + { + "LoanPaymentScheduleType": "Even Total Payments", + "PaymentType": "Principal and Interest", + "Regular": true, + "RepaymentAmount": 1902, + "RepaymentFrequency": "Monthly", + "TaxDeductible": true + } + ], + "Security": [ + { + "Priority": "First Mortgage", + "x_Security": "FinancialInfo_14381322" + } + ] + }, + { + "AnnualInterestRate": 7.15, + "ClearingFromThisLoan": false, + "ClearingFromThisLoanAmount": 875000, + "CreditLimit": 875000, + "HasArrears": false, + "OutstandingBalance": 875000, + "Type": "Mortgage Loan", + "UniqueID": "FinancialLiability_51868326", + "AccountNumber": { + "FinancialInstitution": "Other", + "OtherFIName": "Commonwealth Bank" + }, + "ContinuingRepayment": [ + { + "LoanPaymentScheduleType": "Even Total Payments", + "PaymentType": "Principal and Interest", + "TaxDeductible": false + } + ], + "OriginalTerm": { + "PaymentType": "Principal and Interest", + "PaymentTypeUnits": "Years", + "TotalTermDuration": 30 + }, + "PercentOwned": { + "Proportions": "Specified", + "Owner": [ + { + "Percent": 50, + "x_Party": "Family_8477374" + }, + { + "Percent": 50, + "x_Party": "Family_8477375" + } + ] + }, + "Repayment": [ + { + "LoanPaymentScheduleType": "Even Total Payments", + "PaymentType": "Principal and Interest", + "Regular": true, + "RepaymentAmount": 5909.81, + "RepaymentFrequency": "Monthly", + "TaxDeductible": false + } + ], + "Security": [ + { + "Priority": "First Mortgage", + "x_Security": "FinancialInfo_13821438" + } + ] + }, + { + "AnnualInterestRate": 0, + "ClearingFromThisLoan": false, + "ClearingFromThisLoanAmount": 785406, + "CreditLimit": 785406, + "HasArrears": false, + "OutstandingBalance": 785406, + "Type": "Mortgage Loan", + "UniqueID": "FinancialLiability_55290515", + "AccountNumber": { + "FinancialInstitution": "Other", + "OtherFIName": "Adelaide Bank" + }, + "ContinuingRepayment": [ + { + "LoanPaymentScheduleType": "Even Total Payments", + "PaymentType": "Principal and Interest", + "TaxDeductible": true + } + ], + "OriginalTerm": { + "PaymentType": "Principal and Interest", + "PaymentTypeUnits": "Years", + "TotalTermDuration": 29 + }, + "PercentOwned": { + "Proportions": "Specified", + "Owner": [ + { + "Percent": 50, + "x_Party": "Family_8477374" + }, + { + "Percent": 50, + "x_Party": "Family_8477375" + } + ] + }, + "Repayment": [ + { + "LoanPaymentScheduleType": "Even Total Payments", + "PaymentType": "Principal and Interest", + "Regular": true, + "RepaymentAmount": 5199, + "RepaymentFrequency": "Monthly", + "TaxDeductible": true + } + ], + "Security": [ + { + "Priority": "First Mortgage", + "x_Security": "FinancialInfo_14381339" + } + ] + } + ], + "LoanDetails": [ + { + "AmountRequested": 620000, + "LoanType": "Term Loan", + "LVR": 77.5, + "Secured": "true", + "StatementCycle": "Monthly", + "TaxDeductible": false, + "UniqueID": "LoanStructure_6717099", + "Borrowers": { + "Proportions": "Equal", + "Owner": [ + { + "Percent": 50, + "x_Party": "Family_8477374" + }, + { + "Percent": 50, + "x_Party": "Family_8477375" + } + ] + }, + "FeaturesSelected": { + "ChequeBook": false, + "CreditCard": false, + "RateLock": false, + "Redraw": true + }, + "LendingPurpose": [ + { + "IncludesRefinancing": false + }, + { + "ABSLendingPurpose": "Purchase a Property", + "ABSLendingPurposeCode": "ABS-129", + "PurposeAmount": 620000 + } + ], + "LoanPurpose": { + "PrimaryPurpose": "Owner Occupied" + }, + "ProposedRepayment": { + "RegularRepayment": [ + { + "Amount": 0, + "Frequency": "Monthly" + } + ] + }, + "Term": { + "PaymentType": "Principal and Interest", + "TotalTermDuration": 30, + "TotalTermType": "Total Term", + "TotalTermUnits": "Years" + } + } + ], + "NonRealEstateAsset": [ + { + "ToBeSold": false, + "ToBeUsedAsSecurity": false, + "Type": "Motor Vehicle and Transport", + "UniqueID": "FinancialInfo_12811548", + "EstimatedValue": { + "EstimateBasis": "Applicant Estimate", + "Value": 15000 + }, + "MotorVehicle": { + "Age": 9, + "Description": "2015 Hyundai (Luxury Car)", + "Make": "Hyundai", + "Type": "Car", + "Year": "2015" + }, + "PercentOwned": { + "Proportions": "Specified", + "Owner": [ + { + "Percent": 50, + "x_Party": "Family_8477374" + }, + { + "Percent": 50, + "x_Party": "Family_8477375" + } + ] + } + }, + { + "ToBeSold": false, + "ToBeUsedAsSecurity": false, + "Type": "Financial Asset", + "UniqueID": "FinancialInfo_12811552", + "EstimatedValue": { + "EstimateBasis": "Applicant Estimate", + "Value": 55000 + }, + "FinancialAsset": { + "Description": "ANZ Australia", + "Type": "Savings Account", + "AccountNumber": { + "FinancialInstitution": "Other", + "OtherFIName": "ANZ Australia" + } + }, + "PercentOwned": { + "Proportions": "Specified", + "Owner": [ + { + "Percent": 50, + "x_Party": "Family_8477374" + }, + { + "Percent": 50, + "x_Party": "Family_8477375" + } + ] + } + }, + { + "ToBeSold": false, + "ToBeUsedAsSecurity": false, + "Type": "Financial Asset", + "UniqueID": "FinancialInfo_12811556", + "EstimatedValue": { + "EstimateBasis": "Applicant Estimate", + "Value": 80000 + }, + "FinancialAsset": { + "Description": "", + "Type": "Superannuation", + "AccountNumber": { + "FinancialInstitution": "Other", + "OtherFIName": "" + } + }, + "PercentOwned": { + "Proportions": "Specified", + "Owner": [ + { + "Percent": 100, + "x_Party": "Family_8477375" + }, + { + "Percent": 0, + "x_Party": "Family_8477374" + } + ] + } + }, + { + "ToBeSold": false, + "ToBeUsedAsSecurity": false, + "Type": "Financial Asset", + "UniqueID": "FinancialInfo_12811554", + "EstimatedValue": { + "EstimateBasis": "Applicant Estimate", + "Value": 60000 + }, + "FinancialAsset": { + "Description": "", + "Type": "Superannuation", + "AccountNumber": { + "FinancialInstitution": "Other", + "OtherFIName": "" + } + }, + "PercentOwned": { + "Proportions": "Specified", + "Owner": [ + { + "Percent": 100, + "x_Party": "Family_8477374" + }, + { + "Percent": 0, + "x_Party": "Family_8477375" + } + ] + } + }, + { + "ToBeSold": false, + "ToBeUsedAsSecurity": false, + "Type": "Other", + "UniqueID": "FinancialInfo_15254658", + "EstimatedValue": { + "EstimateBasis": "Applicant Estimate", + "Value": 150000 + }, + "Insurance": [ + { + "x_Insurance": "Insurance_15254658" + } + ], + "OtherAsset": { + "Description": "Life Insurance", + "Type": "Other" + }, + "PercentOwned": { + "Proportions": "Specified", + "Owner": [ + { + "Percent": 50, + "x_Party": "Family_8477374" + }, + { + "Percent": 50, + "x_Party": "Family_8477375" + } + ] + } + } + ], + "Overview": { + "ApplicationType": "Loan", + "BrokerApplicationReferenceNumber": "5542468", + "IsBridgingFinance": false + }, + "PersonApplicant": [ + { + "ApplicantType": "Borrower", + "Citizenship": "AU", + "DateOfBirth": "1986-06-06", + "FirstHomeBuyer": false, + "Gender": "Female", + "HasPreviousName": false, + "IsExistingCustomer": false, + "MaritalStatus": "Single", + "MonthsInCurrentProfession": 3, + "MothersMaidenName": "", + "PrimaryApplicant": true, + "PrincipalForeignResidence": "AU", + "ResidencyStatus": "Permanently in Australia", + "UnderstandApplication": true, + "UniqueID": "Family_8477374", + "x_Household": "Family_7102929", + "YearsInCurrentProfession": 6, + "Contact": { + "PreferredContact": "Mobile", + "EmailAddress": [ + { + "Email": "testEmail@testcompany.com", + "EmailType": "Home" + } + ], + "Mobile": { + "AustralianDialingCode": "04", + "CountryCode": "61", + "Number": "0499999999" + }, + "PostSettlementAddress": { + "HousingStatus": "Own Home", + "x_ResidentialAddress": "Address_13627498" + }, + "PreviousAddress": { + "EndDate": "2018-07-01", + "HousingStatus": "Own Home", + "StartDate": "2011-07-01", + "x_ResidentialAddress": "Address_11168887", + "Duration": { + "Length": 84, + "Units": "Months" + } + } + }, + "Employment": [ + { + "PAYG": { + "Basis": "Full Time", + "Occupation": "Testing 2", + "OnProbation": false, + "PositionTitle": "Testing 2", + "StartDate": "2018-04-10", + "Status": "Primary", + "UniqueID": "Employment_5283447", + "x_Employer": "EmployerCompany_5283447", + "Duration": { + "Length": 75, + "Units": "Months" + }, + "Income": { + "GrossRegularOvertimeAmountConditionOfEmployment": false, + "GrossSalaryAmount": 90000, + "GrossSalaryFrequency": "Yearly", + "WorkAllowanceAmountConditionOfEmployment": false + } + } + }, + { + "PAYG": { + "Basis": "Full Time", + "EndDate": "2018-03-19", + "Occupation": "Testing", + "OnProbation": false, + "PositionTitle": "Testing", + "StartDate": "2012-07-07", + "Status": "Previous", + "UniqueID": "Employment_5283440", + "x_Employer": "EmployerCompany_5283440", + "Duration": { + "Length": 68, + "Units": "Months" + }, + "Income": { + "GrossRegularOvertimeAmountConditionOfEmployment": false, + "GrossSalaryAmount": 80000, + "GrossSalaryFrequency": "Yearly", + "WorkAllowanceAmountConditionOfEmployment": false + } + } + } + ], + "PersonName": { + "FirstName": "Wanda", + "KnownAs": "Wanda", + "MiddleNames": "", + "NameTitle": "Mrs", + "Surname": "Maximoff" + }, + "Privacy": { + "AllowCreditBureauIdentityCheck": true, + "AllowCreditCheck": true, + "AllowElectronicIdentityCheck": true, + "PrivacyActConsentSigned": true + }, + "ProofOfIdentity": [ + { + "CertifiedCopy": false, + "CountryOfIssue": "AU", + "DocumentNumber": "", + "DocumentType": "Other", + "ExpiryDate": "2027-09-23", + "IssuingOrganisation": "", + "MiddleNameOnDocument": "Wanda", + "NameOnDocument": "Wanda Maximoff", + "Original": false, + "OtherDescription": "Drivers Licence Australia", + "PlaceOfIssue": "" + } + ], + "ResponsibleLending": { + "AnticipatedChanges": false + } + }, + { + "ApplicantType": "Borrower", + "Citizenship": "AU", + "DateOfBirth": "1986-01-01", + "FirstHomeBuyer": false, + "Gender": "Male", + "HasPreviousName": false, + "IsExistingCustomer": false, + "MaritalStatus": "Single", + "MothersMaidenName": "", + "PrimaryApplicant": false, + "PrincipalForeignResidence": "AU", + "ResidencyStatus": "Permanently in Australia", + "UnderstandApplication": true, + "UniqueID": "Family_8477375", + "x_Household": "Family_7102929", + "YearsInCurrentProfession": 8, + "Contact": { + "PreferredContact": "Mobile", + "EmailAddress": [ + { + "Email": "testBroker@testCompany.com", + "EmailType": "Home" + } + ], + "Mobile": { + "AustralianDialingCode": "04", + "CountryCode": "61", + "Number": "0488888888" + }, + "PostSettlementAddress": { + "HousingStatus": "Own Home", + "x_ResidentialAddress": "Address_13627498" + }, + "PreviousAddress": { + "EndDate": "2018-07-01", + "HousingStatus": "Own Home", + "StartDate": "2011-07-01", + "x_ResidentialAddress": "Address_11168887", + "Duration": { + "Length": 84, + "Units": "Months" + } + } + }, + "Employment": [ + { + "PAYG": { + "Basis": "Full Time", + "Occupation": "Senior DevOps Engineer", + "OnProbation": false, + "PositionTitle": "Senior DevOps Engineer", + "StartDate": "2016-08-02", + "Status": "Primary", + "UniqueID": "Employment_4688212", + "x_Employer": "EmployerCompany_4688212", + "Duration": { + "Length": 96, + "Units": "Months" + }, + "Income": { + "GrossRegularOvertimeAmountConditionOfEmployment": false, + "GrossSalaryAmount": 5769, + "GrossSalaryFrequency": "Fortnightly", + "WorkAllowanceAmountConditionOfEmployment": false + } + } + } + ], + "PersonName": { + "FirstName": "Vision", + "KnownAs": "Vision", + "MiddleNames": "", + "NameTitle": "Mr", + "Surname": "Vis" + }, + "Privacy": { + "AllowCreditBureauIdentityCheck": true, + "AllowCreditCheck": true, + "AllowElectronicIdentityCheck": true, + "PrivacyActConsentSigned": true + }, + "ProofOfIdentity": [ + { + "CertifiedCopy": false, + "CountryOfIssue": "AU", + "DocumentNumber": "", + "DocumentType": "Other", + "ExpiryDate": "2027-09-22", + "IssuingOrganisation": "", + "MiddleNameOnDocument": "ion", + "NameOnDocument": "Vision Vis", + "Original": false, + "OtherDescription": "Drivers Licence Australia", + "PlaceOfIssue": "" + } + ], + "ResponsibleLending": { + "AnticipatedChanges": false + } + } + ], + "RealEstateAsset": [ + { + "ApprovalInPrinciple": false, + "Occupancy": "Owner Primary", + "PrimaryPurpose": "Owner Occupied", + "PrimaryUsage": "Residential", + "ToBeUsedAsSecurity": false, + "Transaction": "Owns", + "UniqueID": "FinancialInfo_15708480", + "x_Address": "Address_13531793", + "ContractDetails": {}, + "Encumbrance": [ + { + "EncumbranceType": "Mortgage", + "Priority": "First Mortgage", + "UniqueID": "FinancialLiability_10219681" + } + ], + "EstimatedValue": { + "EstimateBasis": "Applicant Estimate", + "Value": 453000 + }, + "PercentOwned": { + "Proportions": "Specified", + "Owner": [ + { + "Percent": 100, + "x_Party": "Family_8477374" + }, + { + "Percent": 0, + "x_Party": "Family_8477375" + } + ] + }, + "PropertyType": { + "PropertyTypeName": "Fully Detached House" + }, + "Residential": { + "Type": "Fully Detached House" + }, + "Zoning": { + "Type": "Residential" + } + }, + { + "ApprovalInPrinciple": false, + "Occupancy": "Owner Primary", + "PrimaryPurpose": "Investment", + "PrimaryUsage": "Residential", + "ToBeUsedAsSecurity": false, + "Transaction": "Owns", + "UniqueID": "FinancialInfo_13162992", + "x_Address": "Address_11168887", + "ContractDetails": {}, + "Encumbrance": [ + { + "EncumbranceType": "Mortgage", + "Priority": "First Mortgage", + "UniqueID": "FinancialLiability_7966108" + } + ], + "EstimatedValue": { + "EstimateBasis": "Certified Valuation", + "Value": 740000 + }, + "PercentOwned": { + "Proportions": "Specified", + "Owner": [ + { + "Percent": 100, + "x_Party": "Family_8477375" + }, + { + "Percent": 0, + "x_Party": "Family_8477374" + } + ] + }, + "PropertyType": { + "PropertyTypeName": "Fully Detached House" + }, + "Residential": { + "Type": "Fully Detached House" + }, + "Zoning": { + "Type": "Residential" + } + }, + { + "ApprovalInPrinciple": false, + "Occupancy": "Owner Primary", + "PrimaryPurpose": "Owner Occupied", + "PrimaryUsage": "Residential", + "ToBeUsedAsSecurity": false, + "Transaction": "Owns", + "UniqueID": "FinancialInfo_13790701", + "x_Address": "Address_8247579", + "ContractDetails": {}, + "EstimatedValue": { + "EstimateBasis": "Certified Valuation", + "Value": 1312908 + }, + "PercentOwned": { + "Proportions": "Specified", + "Owner": [ + { + "Percent": 50, + "x_Party": "Family_8477374" + }, + { + "Percent": 50, + "x_Party": "Family_8477375" + } + ] + }, + "PropertyType": { + "PropertyTypeName": "Fully Detached House" + }, + "Residential": { + "Type": "Fully Detached House" + }, + "Zoning": { + "Type": "Residential" + } + }, + { + "ApprovalInPrinciple": false, + "Occupancy": "Owner Primary", + "PrimaryPurpose": "Investment", + "PrimaryUsage": "Residential", + "ToBeUsedAsSecurity": false, + "Transaction": "Owns", + "UniqueID": "FinancialInfo_14381322", + "x_Address": "Address_11087379", + "ContractDetails": {}, + "Encumbrance": [ + { + "EncumbranceType": "Mortgage", + "Priority": "First Mortgage", + "UniqueID": "FinancialLiability_9060327" + } + ], + "EstimatedValue": { + "EstimateBasis": "Applicant Estimate", + "Value": 400000 + }, + "PercentOwned": { + "Proportions": "Specified", + "Owner": [ + { + "Percent": 100, + "x_Party": "Family_8477375" + }, + { + "Percent": 0, + "x_Party": "Family_8477374" + } + ] + }, + "PropertyType": { + "PropertyTypeName": "Std Apartment" + }, + "Residential": { + "Type": "Apartment Unit Flat" + }, + "Zoning": { + "Type": "Residential" + } + }, + { + "ApprovalInPrinciple": false, + "Occupancy": "Owner Primary", + "PrimaryPurpose": "Owner Occupied", + "PrimaryUsage": "Residential", + "ToBeUsedAsSecurity": false, + "Transaction": "Owns", + "UniqueID": "FinancialInfo_13821438", + "x_Address": "Address_11555582", + "ContractDetails": {}, + "Encumbrance": [ + { + "EncumbranceType": "Mortgage", + "Priority": "First Mortgage", + "UniqueID": "FinancialLiability_8539113" + } + ], + "EstimatedValue": { + "EstimateBasis": "Applicant Estimate", + "Value": 1980000 + }, + "PercentOwned": { + "Proportions": "Specified", + "Owner": [ + { + "Percent": 50, + "x_Party": "Family_8477374" + }, + { + "Percent": 50, + "x_Party": "Family_8477375" + } + ] + }, + "PropertyType": { + "PropertyTypeName": "Fully Detached House" + }, + "Residential": { + "Type": "Fully Detached House" + }, + "Zoning": { + "Type": "Residential" + } + }, + { + "ApprovalInPrinciple": false, + "Occupancy": "Owner Primary", + "PrimaryPurpose": "Investment", + "PrimaryUsage": "Residential", + "ToBeUsedAsSecurity": false, + "Transaction": "Owns", + "UniqueID": "FinancialInfo_14381339", + "x_Address": "Address_12459614", + "ContractDetails": {}, + "Encumbrance": [ + { + "EncumbranceType": "Mortgage", + "Priority": "First Mortgage", + "UniqueID": "FinancialLiability_9060352" + } + ], + "EstimatedValue": { + "EstimateBasis": "Applicant Estimate", + "Value": 1000000 + }, + "PercentOwned": { + "Proportions": "Specified", + "Owner": [ + { + "Percent": 50, + "x_Party": "Family_8477374" + }, + { + "Percent": 50, + "x_Party": "Family_8477375" + } + ] + }, + "PropertyType": { + "PropertyTypeName": "Fully Detached House" + }, + "Residential": { + "Type": "Fully Detached House" + }, + "Zoning": { + "Type": "Residential" + } + }, + { + "ApprovalInPrinciple": false, + "Construction": false, + "Holding": "Joint Tenants", + "Occupancy": "Owner Primary", + "PrimaryPurpose": "Owner Occupied", + "PrimarySecurity": true, + "PrimaryUsage": "Residential", + "Status": "Established", + "ToBeUsedAsSecurity": true, + "Transaction": "Purchasing", + "UniqueID": "SecurityInfo_5583881", + "x_Address": "Address_13627215", + "ContractDetails": { + "LicencedRealEstateAgentContract": true + }, + "EstimatedValue": { + "EstimateBasis": "Applicant Estimate", + "Value": 800000 + }, + "PercentOwned": { + "Proportions": "Specified", + "Owner": [ + { + "Percent": 50, + "x_Party": "Family_8477374" + }, + { + "Percent": 50, + "x_Party": "Family_8477375" + } + ] + }, + "PropertyType": { + "PropertyTypeName": "Fully Detached House" + }, + "Residential": { + "Type": "Fully Detached House" + }, + "Title": [ + { + "TenureType": "Other Title", + "TitleSystem": "Torrens" + } + ], + "Zoning": { + "Type": "Residential" + } + } + ], + "RelatedCompany": [ + { + "BusinessName": "Australian Council of Educational Research", + "CompanyName": "Australian Council of Educational Research", + "UniqueID": "EmployerCompany_4688212", + "Contact": { + "x_Address": "Address_3510876", + "OfficePhone": { + "Number": "61477777777" + } + } + }, + { + "BusinessName": "Testing 2", + "CompanyName": "Testing 2", + "UniqueID": "EmployerCompany_5283447", + "Contact": { + "x_Address": "Address_3386157", + "ContactPerson": { + "x_ContactPerson": "EmployerContact_5283447" + }, + "OfficePhone": { + "Number": "61400000000" + } + } + }, + { + "BusinessName": "Testing 1", + "CompanyName": "Testing 1", + "UniqueID": "EmployerCompany_5283440", + "Contact": { + "x_Address": "Address_3386157", + "ContactPerson": { + "x_ContactPerson": "EmployerContact_5283440" + }, + "OfficePhone": { + "Number": "61400000000" + } + } + } + ], + "RelatedPerson": [ + { + "UniqueID": "EmployerContact_5283447", + "Contact": { + "x_Address": "Address_3386157", + "Mobile": { + "Number": "61400000000" + } + }, + "PersonName": { + "FirstName": "Testing 2", + "KnownAs": "Testing 2" + } + }, + { + "UniqueID": "EmployerContact_5283440", + "Contact": { + "x_Address": "Address_3386157", + "Mobile": { + "Number": "61400101010" + } + }, + "PersonName": { + "FirstName": "Testing", + "KnownAs": "Testing 1" + } + } + ], + "SalesChannel": { + "Type": "Mortgage Broker", + "Aggregator": { + "ABN": "67666666666", + "LicenceNumber": "555555", + "LicenceType": "ACL", + "UniqueID": "Aggregator_2", + "Contact": { + "Email": "testcustomerservice@testCompany.com.au", + "x_Address": "Address_807535", + "OfficePhone": { + "Number": "1800 000 000(free call)" + } + } + }, + "Company": { + "ABN": "12313212312", + "CompanyName": "Test Company", + "LicenceNumber": "777777" + }, + "LoanWriter": { + "FirstName": "Jeremy", + "Surname": "Adviser", + "UniqueID": "Family_6430652", + "Contact": { + "Email": "testAdviser@testCompany.com.au", + "x_Address": "Address_3416383", + "Fax": {}, + "Mobile": { + "Number": "0400000000" + }, + "OfficePhone": { + "Number": "0222222222" + } + } + } + }, + "Summary": { + "Fee": [ + { + "Amount": 0, + "CapitaliseFee": false, + "PayFeesFrom": "Account", + "Type": "LMI" + } + ], + "LoanToValuationRatio": { + "ApplicationLVR": 77.5 + } + } + }, + "NeedsAnalysis": { + "Interview": {}, + "Preferences": { + "ConflictExists": false, + "InterestRateType": "Standard Variable", + "PreferredLenders": true, + "PreferredLendersDetails": ", ", + "FundsAccessTypeDetails": { + "OffsetAccount": { + "Importance": "Important", + "RisksExplained": true, + "Reason": { + "AllowsAccessToFunds": false, + "AllowsPayingOffLoanSooner": true, + "ForTaxPurposes": false, + "Other": false + } + }, + "Redraw": { + "Importance": "Important", + "RisksExplained": true, + "Reason": { + "FlexibilityToAccessPrepaidFundsIfNeeded": true, + "Other": false + } + } + }, + "InterestRateTypeDetails": { + "FixedAndVariableRate": { + "Importance": "Not Important" + }, + "FixedRate": { + "Importance": "Not Important" + }, + "VariableRate": { + "Importance": "Important", + "RisksExplained": true, + "Reason": { + "Flexibility": false, + "Other": false, + "PotentialRateDecreases": true + } + } + }, + "RepaymentTypeDetails": { + "InterestInAdvance": { + "Importance": "Not Important" + }, + "InterestOnly": { + "Importance": "Not Important" + }, + "LineOfCredit": { + "Importance": "Not Important" + }, + "PrincipalAndInterest": { + "Importance": "Important", + "RepaymentFrequency": "Weekly", + "RisksExplained": true + } + } + }, + "RetirementDetails": { + "Applicant": [ + { + "ImminentlyRetiring": false, + "IntendedRetirementAge": 70, + "UnderstandsImpactOnRetirementPlans": false, + "x_Applicant": "Family_8477374", + "RepaymentOptions": { + "CoApplicantIncome": false, + "DownsizingHome": false, + "IncomeFromOtherInvestments": false, + "Other": false, + "RecurringIncomeFromSuperannuation": false, + "RepaymentOfLoanPriorToRetirement": false, + "SaleOfAssets": true, + "Savings": false, + "SuperannuationLumpSumFollowingRetirement": false + } + }, + { + "ImminentlyRetiring": false, + "IntendedRetirementAge": 70, + "UnderstandsImpactOnRetirementPlans": false, + "x_Applicant": "Family_8477375", + "RepaymentOptions": { + "CoApplicantIncome": false, + "DownsizingHome": false, + "IncomeFromOtherInvestments": false, + "Other": false, + "RecurringIncomeFromSuperannuation": false, + "RepaymentOfLoanPriorToRetirement": false, + "SaleOfAssets": true, + "Savings": false, + "SuperannuationLumpSumFollowingRetirement": false + } + } + ] + } + } + }, + "Instructions": { + "ApplicationInstructions": { + "Submit": { + "AssessmentType": "Full", + "IsAccountVariation": false + } + } + }, + "Publisher": { + "LIXICode": "ZZZLO1" + }, + "Recipient": [ + { + "LIXICode": "ZZZANU1" + } + ], + "SchemaVersion": { + "GuidebookCode": "EGB-XD1ZZ3", + "LIXITransactionType": "CAL", + "LIXIVersion": "2.6.35" + } + +} \ No newline at end of file diff --git a/samples/MyCRM.Lodgement.Core/Models/SampleLodgementInformation.cs b/samples/MyCRM.Lodgement.Core/Models/SampleLodgementInformation.cs new file mode 100644 index 0000000..693203a --- /dev/null +++ b/samples/MyCRM.Lodgement.Core/Models/SampleLodgementInformation.cs @@ -0,0 +1,7 @@ +namespace MyCRM.Lodgement.Common.Models; + +public class SampleLodgementInformation +{ + public int LoanId { get; set; } + public LoanApplicationScenario Scenario { get; set; } +} \ No newline at end of file diff --git a/samples/MyCRM.Lodgement.Core/MyCRM.Lodgement.Common.csproj b/samples/MyCRM.Lodgement.Core/MyCRM.Lodgement.Common.csproj index 94612d1..f7fbacd 100644 --- a/samples/MyCRM.Lodgement.Core/MyCRM.Lodgement.Common.csproj +++ b/samples/MyCRM.Lodgement.Core/MyCRM.Lodgement.Common.csproj @@ -1,12 +1,18 @@ - net6.0 + net8.0 default - + + + + + + Always + diff --git a/samples/MyCRM.Lodgement.Core/Routes.cs b/samples/MyCRM.Lodgement.Core/Routes.cs index 3d8de3c..facbb42 100644 --- a/samples/MyCRM.Lodgement.Core/Routes.cs +++ b/samples/MyCRM.Lodgement.Core/Routes.cs @@ -4,5 +4,6 @@ public static class Routes { public const string Validate = "Validate"; public const string Submit = "Submit"; + public const string SumbitTestPackage = "SubmitTestPackage"; } } diff --git a/samples/MyCRM.Lodgement.Core/Utilities/ObjectSerializer.cs b/samples/MyCRM.Lodgement.Core/Utilities/ObjectSerializer.cs new file mode 100644 index 0000000..3253d6d --- /dev/null +++ b/samples/MyCRM.Lodgement.Core/Utilities/ObjectSerializer.cs @@ -0,0 +1,31 @@ +using System; +using System.IO; +using System.Xml.Serialization; +using MyCRMAPI.Lodgement.Models; +using Newtonsoft.Json.Linq; + +namespace MyCRM.Lodgement.Common.Utilities; + +public class ObjectSerializer +{ + + public static string Serialize(Package package ,string mediaType) + { + if (package == null) throw new ArgumentNullException(nameof(package)); + + return mediaType switch + { + "application/xml" => SerializeAsXml(package), + "application/json" => JObject.FromObject(package).ToString(), + _ => throw new NotImplementedException($"Media Type {mediaType} not supported.") + }; + } + + private static string SerializeAsXml(Package package) + { + using var writer = new StringWriter(); + var serializer = new XmlSerializer(package.GetType()); + serializer.Serialize(writer, package); + return writer.ToString(); + } +} diff --git a/samples/MyCRM.Lodgement.Sample.Tests/MyCRM.Lodgement.Sample.Tests.csproj b/samples/MyCRM.Lodgement.Sample.Tests/MyCRM.Lodgement.Sample.Tests.csproj index d05ff53..de664b2 100644 --- a/samples/MyCRM.Lodgement.Sample.Tests/MyCRM.Lodgement.Sample.Tests.csproj +++ b/samples/MyCRM.Lodgement.Sample.Tests/MyCRM.Lodgement.Sample.Tests.csproj @@ -1,7 +1,7 @@ - net6.0 + net8.0 false diff --git a/samples/MyCRM.Lodgement.Sample.Tests/Services/Client/LodgementClientTests.cs b/samples/MyCRM.Lodgement.Sample.Tests/Services/Client/LodgementClientTests.cs index b1f4084..e1d715c 100644 --- a/samples/MyCRM.Lodgement.Sample.Tests/Services/Client/LodgementClientTests.cs +++ b/samples/MyCRM.Lodgement.Sample.Tests/Services/Client/LodgementClientTests.cs @@ -10,6 +10,7 @@ using Moq; using MyCRM.Lodgement.Common.Models; using MyCRM.Lodgement.Sample.Services.Client; +using MyCRM.Lodgement.Sample.Services.LixiPackage; using MyCRM.Lodgement.Sample.Services.Settings; using MyCRMAPI.Lodgement.Models; using Newtonsoft.Json.Linq; @@ -28,12 +29,14 @@ private class DelegatingHandlerStub : DelegatingHandler private const string MediaType = "application/json"; private readonly Mock _httpClientFactoryMock; + private readonly Mock _lixiPackageService; private readonly Mock> _optionsMock; public LodgementClientTests() { _httpClientFactoryMock = new Mock(); _optionsMock = new Mock>(); + _lixiPackageService = new Mock(); } [Fact] @@ -64,6 +67,7 @@ public async Task WhenValidatingAndOkResult_ThenReturnValidationResult() .Returns(client); var target = new LodgementClient(_httpClientFactoryMock.Object, + _lixiPackageService.Object, _optionsMock.Object); var result = await target.Validate(package, CancellationToken.None); @@ -98,10 +102,11 @@ public async Task WhenSubmittingAndOkResult_ThenReturnSubmissionResult() .Returns(client); var target = new LodgementClient(_httpClientFactoryMock.Object, + _lixiPackageService.Object, _optionsMock.Object); - var result = await target.Validate(package, CancellationToken.None); - result.ExternalReferenceId.Should().Be(submissionResult.ReferenceId); + var result = await target.Submit(package, CancellationToken.None); + result.Result.ReferenceId.Should().Be(submissionResult.ReferenceId); } } } diff --git a/samples/MyCRM.Lodgement.Sample.Tests/StartupTests.cs b/samples/MyCRM.Lodgement.Sample.Tests/StartupTests.cs deleted file mode 100644 index 41cdc49..0000000 --- a/samples/MyCRM.Lodgement.Sample.Tests/StartupTests.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Threading.Tasks; -using FluentAssertions; -using Microsoft.AspNetCore.Mvc.Testing; -using Xunit; - -namespace MyCRM.Lodgement.Sample.Tests -{ - public class StartupTests : IClassFixture> - { - private const string TextHtml = "text/html; charset=utf-8"; - - private readonly WebApplicationFactory _factory; - - public StartupTests(WebApplicationFactory factory) => _factory = factory; - - [Theory] - [InlineData("/swagger")] - public async Task HtmlEndpointsRespondWithHtml(string url) - { - // Arrange - var client = _factory.CreateClient(); - - // Act - var response = await client.GetAsync(url); - - // Assert - response.EnsureSuccessStatusCode(); - response.Content.Headers.ContentType.ToString().Should().Be(TextHtml); - } - } -} diff --git a/samples/MyCRM.Lodgement.Sample/Contracts/PostTestPackageRequest.cs b/samples/MyCRM.Lodgement.Sample/Contracts/PostTestPackageRequest.cs new file mode 100644 index 0000000..68dd35e --- /dev/null +++ b/samples/MyCRM.Lodgement.Sample/Contracts/PostTestPackageRequest.cs @@ -0,0 +1,6 @@ +namespace MyCRM.Lodgement.Sample.Models; + +public record PostTestPackageRequest +{ + public required LoanApplicationScenario Scenario { get; init; } +} \ No newline at end of file diff --git a/samples/MyCRM.Lodgement.Sample/Controllers/BackchannelController.cs b/samples/MyCRM.Lodgement.Sample/Controllers/BackchannelController.cs index 7a04fbf..673b9ad 100644 --- a/samples/MyCRM.Lodgement.Sample/Controllers/BackchannelController.cs +++ b/samples/MyCRM.Lodgement.Sample/Controllers/BackchannelController.cs @@ -1,8 +1,4 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; -using MyCRMAPI.Lodgement.Models; +using MyCRMAPI.Lodgement.Models; namespace MyCRM.Lodgement.Sample.Controllers { diff --git a/samples/MyCRM.Lodgement.Sample/Controllers/LodgementSubmissionController.cs b/samples/MyCRM.Lodgement.Sample/Controllers/LodgementSubmissionController.cs index 67f8b69..4db1a7b 100644 --- a/samples/MyCRM.Lodgement.Sample/Controllers/LodgementSubmissionController.cs +++ b/samples/MyCRM.Lodgement.Sample/Controllers/LodgementSubmissionController.cs @@ -1,11 +1,4 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using MyCRM.Lodgement.Common; -using MyCRM.Lodgement.Common.Models; -using MyCRM.Lodgement.Sample.Services.Client; +using MyCRM.Lodgement.Sample.Mapping; using MyCRMAPI.Lodgement.Models; namespace MyCRM.Lodgement.Sample.Controllers @@ -36,5 +29,28 @@ public async Task Post(Package package, CancellationToken token) return Ok(resultOrError.Result); } + + + [HttpPost(Routes.SumbitTestPackage)] + [ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ValidationError))] + [ProducesResponseType(StatusCodes.Status500InternalServerError, Type = typeof(ProblemDetails))] + [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(SubmissionResult))] + public async Task PostTestPackage(PostTestPackageRequest request, CancellationToken token) + { + var model = request.MapToLodgementInformation(); + if (model is null) + { + return BadRequest(); + } + + var resultOrError = await _lodgementClient.SubmitSampleLixiPackage(model, token); + + if (resultOrError.IsError) + { + return BadRequest(resultOrError.Error); + } + + return Ok(resultOrError.Result); + } } } \ No newline at end of file diff --git a/samples/MyCRM.Lodgement.Sample/Controllers/LodgementValidationController.cs b/samples/MyCRM.Lodgement.Sample/Controllers/LodgementValidationController.cs index e3ed1d0..f949e53 100644 --- a/samples/MyCRM.Lodgement.Sample/Controllers/LodgementValidationController.cs +++ b/samples/MyCRM.Lodgement.Sample/Controllers/LodgementValidationController.cs @@ -1,12 +1,4 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using MyCRM.Lodgement.Common; -using MyCRM.Lodgement.Common.Models; -using MyCRM.Lodgement.Sample.Services.Client; -using MyCRMAPI.Lodgement.Models; +using MyCRMAPI.Lodgement.Models; namespace MyCRM.Lodgement.Sample.Controllers { diff --git a/samples/MyCRM.Lodgement.Sample/GlobalUsings.cs b/samples/MyCRM.Lodgement.Sample/GlobalUsings.cs new file mode 100644 index 0000000..e7e6cb2 --- /dev/null +++ b/samples/MyCRM.Lodgement.Sample/GlobalUsings.cs @@ -0,0 +1,20 @@ +// Global using directives +global using System; +global using System.Collections.Generic; +global using System.IO; +global using System.Threading; +global using System.Threading.Tasks; +global using Microsoft.AspNetCore.Http; +global using Microsoft.AspNetCore.Mvc; +global using Microsoft.Extensions.Configuration; +global using Microsoft.Extensions.DependencyInjection; +global using Microsoft.Extensions.Options; +global using Microsoft.OpenApi.Models; +global using MyCRM.Lodgement.Common; +global using MyCRM.Lodgement.Common.Models; +global using MyCRM.Lodgement.Sample.Models; +global using MyCRM.Lodgement.Sample.Services; +global using MyCRM.Lodgement.Sample.Services.Client; +global using MyCRM.Lodgement.Sample.Services.LixiPackage; +global using MyCRM.Lodgement.Sample.Services.Settings; +global using Newtonsoft.Json; \ No newline at end of file diff --git a/samples/MyCRM.Lodgement.Sample/Mapping/ContractMapping.cs b/samples/MyCRM.Lodgement.Sample/Mapping/ContractMapping.cs new file mode 100644 index 0000000..53fbb57 --- /dev/null +++ b/samples/MyCRM.Lodgement.Sample/Mapping/ContractMapping.cs @@ -0,0 +1,16 @@ +namespace MyCRM.Lodgement.Sample.Mapping; + +public static class ContractMapping +{ + public static SampleLodgementInformation MapToLodgementInformation(this PostTestPackageRequest request) + { + if(request is null) throw new ArgumentNullException(nameof(request), "Source model cannot be null."); + Random random = new Random(); + return new SampleLodgementInformation + { + LoanId = random.Next(0, int.MaxValue), + Scenario = request.Scenario + }; + } + +} \ No newline at end of file diff --git a/samples/MyCRM.Lodgement.Sample/MyCRM.Lodgement.Sample.csproj b/samples/MyCRM.Lodgement.Sample/MyCRM.Lodgement.Sample.csproj index d3a1e79..541964c 100644 --- a/samples/MyCRM.Lodgement.Sample/MyCRM.Lodgement.Sample.csproj +++ b/samples/MyCRM.Lodgement.Sample/MyCRM.Lodgement.Sample.csproj @@ -1,7 +1,7 @@ - net6.0 + net8.0 default diff --git a/samples/MyCRM.Lodgement.Sample/Program.cs b/samples/MyCRM.Lodgement.Sample/Program.cs index 42a471c..f240d60 100644 --- a/samples/MyCRM.Lodgement.Sample/Program.cs +++ b/samples/MyCRM.Lodgement.Sample/Program.cs @@ -1,20 +1,85 @@ -using Microsoft.AspNetCore.Hosting; +using System.Text.Json.Serialization; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.Diagnostics.HealthChecks; using Microsoft.Extensions.Hosting; -namespace MyCRM.Lodgement.Sample +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. +builder.Services.AddControllers(options => { options.Conventions.Add(new ApiExplorerConvention()); }) + .AddXmlSerializerFormatters() + .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); }); + + +//builder.Services.AddServicesSample(Configuration); + +// builder.Services.AddProblemDetails(options => +// { +// options.IncludeExceptionDetails = (context, ex) => false; +// }); + +builder.Services.AddHealthChecks().AddCheck("default", _ => HealthCheckResult.Healthy("The API is responding")); + +builder.Services.AddSwaggerGen(c => { - public class Program + c.CustomOperationIds(e => + e.ActionDescriptor.AttributeRouteInfo?.Name + ?? $"{e.ActionDescriptor.RouteValues["controller"]}_{e.ActionDescriptor.RouteValues["action"]}"); + c.SwaggerDoc(ApiExplorerConvention.LodgementApi, + new OpenApiInfo { Title = "MyCRM Lodgement API (v1)", Version = "v1" }); + c.SwaggerDoc(ApiExplorerConvention.BackchannelApi, + new OpenApiInfo { Title = "MyCRM Lodgement Backchannel API (v1)", Version = "v1" }); + + c.CustomSchemaIds(x => x.FullName); + + c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme + { + Description = @"JWT authorization header using the Bearer scheme.", + Name = "Authorization", + In = ParameterLocation.Header, + Type = SecuritySchemeType.Http, + Scheme = "Bearer" + }); + + c.AddSecurityRequirement(new OpenApiSecurityRequirement { - public static void Main(string[] args) { - CreateHostBuilder(args).Build().Run(); + new OpenApiSecurityScheme + { + Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }, + Scheme = "oauth2", + Name = "Bearer", + In = ParameterLocation.Header + }, + new List() } + }); +}); +var app = builder.Build(); - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - }); - } +if (!app.Environment.IsDevelopment()) +{ + app.UseExceptionHandler("/Error"); + // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. + app.UseHsts(); } + +app.UseHttpsRedirection(); +app.UseStaticFiles(); +app.UseRouting(); + +app.UseSwagger(); +app.UseSwaggerUI(c => +{ + c.SwaggerEndpoint($"{ApiExplorerConvention.LodgementApi}/swagger.json", "MyCRM Lodgement API (v1)"); + c.SwaggerEndpoint($"{ApiExplorerConvention.BackchannelApi}/swagger.json", "MyCRM LodgementApi Backchannel API (v1)"); +}); + +app.UseAuthorization(); + +app.UseEndpoints(endpoints => +{ + endpoints.MapControllers(); +}); + +app.Run(); \ No newline at end of file diff --git a/samples/MyCRM.Lodgement.Sample/Services/Client/ILodgementClient.cs b/samples/MyCRM.Lodgement.Sample/Services/Client/ILodgementClient.cs index 3a2d4b0..880643e 100644 --- a/samples/MyCRM.Lodgement.Sample/Services/Client/ILodgementClient.cs +++ b/samples/MyCRM.Lodgement.Sample/Services/Client/ILodgementClient.cs @@ -1,7 +1,4 @@ -using System.Threading; -using System.Threading.Tasks; -using MyCRM.Lodgement.Common.Models; -using MyCRMAPI.Lodgement.Models; +using MyCRMAPI.Lodgement.Models; namespace MyCRM.Lodgement.Sample.Services.Client { @@ -9,5 +6,7 @@ public interface ILodgementClient { Task Validate(Package package, CancellationToken token); Task> Submit(Package package, CancellationToken token); + Task> SubmitSampleLixiPackage( + SampleLodgementInformation lodgementInformation, CancellationToken token); } -} +} \ No newline at end of file diff --git a/samples/MyCRM.Lodgement.Sample/Services/Client/LodgementClient.cs b/samples/MyCRM.Lodgement.Sample/Services/Client/LodgementClient.cs index 0a82188..15dd49e 100644 --- a/samples/MyCRM.Lodgement.Sample/Services/Client/LodgementClient.cs +++ b/samples/MyCRM.Lodgement.Sample/Services/Client/LodgementClient.cs @@ -1,55 +1,67 @@ -using System; -using System.IO; -using System.Net; +using System.Net; using System.Net.Http; using System.Text; -using System.Threading; -using System.Threading.Tasks; -using System.Xml.Serialization; -using Microsoft.Extensions.Options; -using MyCRM.Lodgement.Common; -using MyCRM.Lodgement.Common.Models; -using MyCRM.Lodgement.Sample.Services.Settings; +using Microsoft.AspNetCore.Mvc.Formatters; +using MyCRM.Lodgement.Common.Utilities; using MyCRMAPI.Lodgement.Models; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; namespace MyCRM.Lodgement.Sample.Services.Client { public class LodgementClient : ILodgementClient { private readonly IHttpClientFactory _httpClientFactory; + private readonly ILixiPackageService _lixiPackageService; private readonly LodgementSettings _settings; - public LodgementClient(IHttpClientFactory httpClientFactory, + public LodgementClient(IHttpClientFactory httpClientFactory, + ILixiPackageService lixiPackageService, IOptions options) { _httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory)); + _lixiPackageService = lixiPackageService; _settings = options?.Value ?? throw new ArgumentNullException(nameof(options)); } public async Task Validate(Package package, CancellationToken token) { - if (package == null) throw new ArgumentNullException(nameof(package)); - using var response = await Send(package, Routes.Validate, token); return response.StatusCode switch { HttpStatusCode.OK => await ReadResponse(response.Content), - _ => throw new HttpRequestException($"Invalid response status code, {response.StatusCode} - {response.ReasonPhrase}") + _ => throw new HttpRequestException( + $"Invalid response status code, {response.StatusCode} - {response.ReasonPhrase}") }; } - public async Task> Submit(Package package, CancellationToken token) + public async Task> Submit(Package package, + CancellationToken token) { - if (package == null) throw new ArgumentNullException(nameof(package)); + using var response = await Send(package, Routes.Submit, token); + return response.StatusCode switch + { + HttpStatusCode.OK => await ReadResponse(response.Content), + HttpStatusCode.BadRequest => await ReadResponse(response.Content), + _ => throw new HttpRequestException( + $"Invalid response status code, {response.StatusCode} - {response.ReasonPhrase}") + }; + } + + public async Task> SubmitSampleLixiPackage( + SampleLodgementInformation lodgementInformation, CancellationToken token) + { + if (lodgementInformation.Scenario == null) + throw new ArgumentNullException(nameof(lodgementInformation.Scenario)); + + var package = await _lixiPackageService.CreatePackageAsync(lodgementInformation.LoanId, + lodgementInformation.Scenario, token); using var response = await Send(package, Routes.Submit, token); return response.StatusCode switch { HttpStatusCode.OK => await ReadResponse(response.Content), HttpStatusCode.BadRequest => await ReadResponse(response.Content), - _ => throw new HttpRequestException($"Invalid response status code, {response.StatusCode} - {response.ReasonPhrase}") + _ => throw new HttpRequestException( + $"Invalid response status code, {response.StatusCode} - {response.ReasonPhrase}") }; } @@ -58,8 +70,7 @@ private Task Send(Package package, string route, Cancellati if (package == null) throw new ArgumentNullException(nameof(package)); if (route == null) throw new ArgumentNullException(nameof(route)); - var payload = Serialize(package); - + var payload = ObjectSerializer.Serialize(package, _settings.MediaType); var message = new HttpRequestMessage(HttpMethod.Post, $"Lodgement/{route}") { Content = new StringContent(payload, Encoding.UTF8, _settings.MediaType) @@ -78,25 +89,5 @@ private static async Task ReadResponse(HttpContent content) where T : clas var ser = new JsonSerializer(); return ser.Deserialize(jsonReader); } - - private string Serialize(Package package) - { - if (package == null) throw new ArgumentNullException(nameof(package)); - - return _settings.MediaType switch - { - "application/xml" => SerializeAsXml(package), - "application/json" => JObject.FromObject(package).ToString(), - _ => throw new NotImplementedException($"Media Type {_settings.MediaType} not supported.") - }; - } - - private static string SerializeAsXml(Package package) - { - using var writer = new StringWriter(); - var serializer = new XmlSerializer(package.GetType()); - serializer.Serialize(writer, package); - return writer.ToString(); - } } } \ No newline at end of file diff --git a/samples/MyCRM.Lodgement.Sample/Services/LixiPackage/ILixiPackageService.cs b/samples/MyCRM.Lodgement.Sample/Services/LixiPackage/ILixiPackageService.cs new file mode 100644 index 0000000..163c555 --- /dev/null +++ b/samples/MyCRM.Lodgement.Sample/Services/LixiPackage/ILixiPackageService.cs @@ -0,0 +1,8 @@ +using MyCRMAPI.Lodgement.Models; + +namespace MyCRM.Lodgement.Sample.Services.LixiPackage; + +public interface ILixiPackageService +{ + Task CreatePackageAsync(int loanId, LoanApplicationScenario scenario, CancellationToken token = default); +} \ No newline at end of file diff --git a/samples/MyCRM.Lodgement.Sample/Services/LixiPackage/LixiPackageService.cs b/samples/MyCRM.Lodgement.Sample/Services/LixiPackage/LixiPackageService.cs new file mode 100644 index 0000000..90226d5 --- /dev/null +++ b/samples/MyCRM.Lodgement.Sample/Services/LixiPackage/LixiPackageService.cs @@ -0,0 +1,27 @@ +using MyCRMAPI.Lodgement.Models; + +namespace MyCRM.Lodgement.Sample.Services.LixiPackage; + +public class LixiPackageService : ILixiPackageService +{ + private readonly string _packagSamplesBasePath = AppDomain.CurrentDomain.BaseDirectory + "\\LixiPackageSamples\\"; + + public async Task CreatePackageAsync(int loanId, LoanApplicationScenario scenario, + CancellationToken token = default) + { + var packagePath = _packagSamplesBasePath + Enum.GetName(typeof(LoanApplicationScenario), scenario) + ".json"; + var package = await GetPackageFromJsonAsync(packagePath, token); + + package.ProductionData = YesNoList.No; + package.Content.Application.Overview.BrokerApplicationReferenceNumber = loanId.ToString(); + package.Content.Application.UniqueID = $"LoanScenario-{loanId}"; + + return package; + } + + private async Task GetPackageFromJsonAsync(string path, CancellationToken token) + { + var fileContent = await File.ReadAllTextAsync(path, token); + return JsonConvert.DeserializeObject(fileContent); + } +} \ No newline at end of file diff --git a/samples/MyCRM.Lodgement.Sample/Services/Client/ServiceCollectionExtensions.cs b/samples/MyCRM.Lodgement.Sample/Services/ServiceCollectionExtensions.cs similarity index 69% rename from samples/MyCRM.Lodgement.Sample/Services/Client/ServiceCollectionExtensions.cs rename to samples/MyCRM.Lodgement.Sample/Services/ServiceCollectionExtensions.cs index b514498..5c99bc9 100644 --- a/samples/MyCRM.Lodgement.Sample/Services/Client/ServiceCollectionExtensions.cs +++ b/samples/MyCRM.Lodgement.Sample/Services/ServiceCollectionExtensions.cs @@ -1,10 +1,4 @@ -using System; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; -using MyCRM.Lodgement.Sample.Services.Settings; - -namespace MyCRM.Lodgement.Sample.Services.Client +namespace MyCRM.Lodgement.Sample.Services.Client { public static class ServiceCollectionExtensions { @@ -28,5 +22,16 @@ public static IServiceCollection AddClient(this IServiceCollection services, ICo services.AddTransient(); return services; } + + public static IServiceCollection AddServicesSample(this IServiceCollection services, IConfiguration configuration) + { + if (services == null) throw new ArgumentNullException(nameof(services)); + if (configuration == null) throw new ArgumentNullException(nameof(configuration)); + + services.AddScoped(); + services.AddClient(configuration); + + return services; + } } } diff --git a/samples/MyCRM.Lodgement.Sample/Startup.cs b/samples/MyCRM.Lodgement.Sample/Startup.cs deleted file mode 100644 index 273e16c..0000000 --- a/samples/MyCRM.Lodgement.Sample/Startup.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System.Collections.Generic; -using Hellang.Middleware.ProblemDetails; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Diagnostics.HealthChecks; -using Microsoft.Extensions.Hosting; -using Microsoft.OpenApi.Models; -using MyCRM.Lodgement.Sample.Services; -using MyCRM.Lodgement.Sample.Services.Client; - -namespace MyCRM.Lodgement.Sample -{ - public class Startup - { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - // This method gets called by the runtime. Use this method to add services to the container. - public void ConfigureServices(IServiceCollection services) - { - services.AddControllers(options => - { - options.Conventions.Add(new ApiExplorerConvention()); - }) - .AddXmlSerializerFormatters(); - - services.AddClient(Configuration); - - services.AddProblemDetails(options => - { - options.IncludeExceptionDetails = (context, ex) => false; - }); - - services.AddHealthChecks().AddCheck("default", _ => HealthCheckResult.Healthy("The API is responding")); - - services.AddSwaggerGen(c => - { - c.CustomOperationIds(e => - e.ActionDescriptor.AttributeRouteInfo?.Name - ?? $"{e.ActionDescriptor.RouteValues["controller"]}_{e.ActionDescriptor.RouteValues["action"]}"); - - c.SwaggerDoc(ApiExplorerConvention.LodgementApi, new OpenApiInfo { Title = "MyCRM Lodgement API (v1)", Version = "v1" }); - c.SwaggerDoc(ApiExplorerConvention.BackchannelApi, new OpenApiInfo { Title = "MyCRM Lodgement Backchannel API (v1)", Version = "v1" }); - - c.CustomSchemaIds(x => x.FullName); - - c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme - { - Description = @"JWT authorization header using the Bearer scheme.", - Name = "Authorization", - In = ParameterLocation.Header, - Type = SecuritySchemeType.Http, - Scheme = "Bearer" - }); - - c.AddSecurityRequirement(new OpenApiSecurityRequirement - { - { - new OpenApiSecurityScheme - { - Reference = new OpenApiReference {Type = ReferenceType.SecurityScheme, Id = "Bearer"}, - Scheme = "oauth2", - Name = "Bearer", - In = ParameterLocation.Header - }, - new List() - } - }); - }); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.UseRouting(); - - app.UseSwagger(); - app.UseSwaggerUI(c => - { - c.SwaggerEndpoint($"{ApiExplorerConvention.LodgementApi}/swagger.json", "MyCRM Lodgement API (v1)"); - c.SwaggerEndpoint($"{ApiExplorerConvention.BackchannelApi}/swagger.json", "MyCRM LodgementApi Backchannel API (v1)"); - }); - - app.UseAuthorization(); - - app.UseEndpoints(endpoints => - { - endpoints.MapControllers(); - }); - } - } -}