# Semler
## Documentation
### Prerequisites
URL: `https://api.vwfs-dk.dev.dwp.vwfs.io/v1/bqs-case/case`
header: `x-api-key: xxx`
### Create Case
Send post request to `https://api.vwfs-dk.dev.dwp.vwfs.io/v1/bqs-case/case`.
Request body should look something like this sample:
#### Private example
```json
{
"agreementCode": 3700,
"externalSystemReference": "",
"brandCode": 10,
"calculation": {
"downPayment": 250000,
"duration": 6,
"interestRate": 7,
"residualValue": 2000000,
"dealerCommitmentCommission": 9000,
"administrationFee": 2000,
"admininstrationFeeIsManual": true,
"includeFees": false,
"isAdministrationFeeCapitalized": false,
"isDocumentFeeCapitalized": false,
"isInterestFixed": true
},
"caseVariables": [
{
"typeCode": 6310,
"moneyValue": "100000"
},
{
"typeCode": 3011,
"moneyValue": "2600000"
},
{
"typeCode": 3014,
"moneyValue": "2100000"
}
],
"caseObject": {
"accessories": [
{
"typeCode": 400,
"amount": 3000,
"description": "ServiceAbbonement"
},
{
"typeCode": 400,
"amount": 3000,
"description": "Test ekstra udstyr"
}
],
"expenses": [
{
"typeCode": 10002,
"openCharge": 5000
},
{
"typeCode": 10001,
"openCharge": 1180
}
],
"objectRegistry": {
"objectGroupCode": 17,
"mileage": 45000,
"agreedMileage": 30000,
"deliveryDate": "2024-07-01T00:00:00Z",
"description": "Lambo",
"isNew": true,
"makeName": "Lamboghini",
"registrationDate": "2022-01-02T00:00:00Z",
"serialNumber": "23234sdfsd",
"modelName": "LAmBBBBBO",
"modelYear": 2001,
"typeName": "Wruuuum",
"variables": [
{
"typeCode": 180,
"value": "Grøn"
},
{
"typeCode": 260,
"value": "Benzin"
}
]
},
"price": 3000000,
"originalRegistryFee": 260000,
"vatExempt": false
},
"customer": {
"details": {
"lastName": "jonas.jensen@vwsf.dk",
"type": "Private",
"createConsent": true
}
},
"dealer": 808,
"startConsent": true,
"startScoring": false
}
```
Values to watch for is Brandcode, Agreement and Dealer id.
#### Company example
```json
{
"agreementCode": 3600,
"externalSystemReference": "",
"brandCode": 4,
"dealer": 730,
"startScoring": false,
"startConsent": true,
"calculation": {
"downPayment": 50000,
"duration": 6,
"interestRate": 7,
"residualValue": 750000,
"dealerCommitmentCommission": 3500,
"administrationFee": 2500,
"admininstrationFeeIsManual": true,
"includeFees": false,
"isInterestFixed": true,
"isAdministrationFeeCapitalized": false
},
"caseVariables": [
{
"typeCode": 3000,
"moneyvalue": 15211
},
{
"typeCode": 3015,
"value": "true"
},
{
"typeCode": 3016,
"Value": "6"
}
],
"caseObject": {
"accessories": [
{
"typeCode": 400,
"amount": 0,
"description": "Ekstraudstyr"
}
],
"expenses": [
{
"typeCode": 10001,
"OpenCharge": 1180
},
{
"typeCode": 10010,
"amount": 50
},
{
"typeCode": 10009,
"amount": 1375
}
],
"objectRegistry": {
"objectGroupCode": 12,
"agreedMileage": 10000,
"deliveryDate": "2024-07-01T00:00:00Z",
"registrationDate": "2021-03-19T00:00:00Z",
"serialNumber": "WP0ZZZ99ZMS214814",
"description": "Porsche 911 Carrera S Coupe 3,0 B 450 HK PDK8",
"isNew": false,
"makeName": "Porsche",
"modelCode": "M01",
"modelName": "911",
"modelYear": 2021,
"typeName": "911 Carrera S Coupe 3,0 B 450 HK PDK8",
"variables": [
{
"typeCode": 180,
"value": "N0N078"
},
{
"typeCode": 190,
"value": "Agate Grey Metallak"
},
{
"typeCode": 320,
"moneyvalue": 1000000
},
{
"typeCode": 400,
"value": "M1"
},
{
"typeCode": 700,
"moneyvalue": 1947544
},
{
"typeCode": 730,
"value": "1"
},
{
"typeCode": 780,
"moneyvalue": 100000
},
{
"typeCode": 830,
"moneyvalue": 1947544
}
]
},
"price": 1000000,
"originalRegistryFee": 1149475,
"vatExempt": false
},
"customer": {
"details": {
"addresses": [
{
"eMail": "test@company.dk"
}
],
"type": "Company",
"organizationNumber": "76198268",
"createConsent": true
},
"signatories": [
{
"firstName": "Ma",
"lastName": "M",
"eMail": "xx.xx@vwsf.dk"
}
]
}
}
```
### Update case
Send put request to `https://api.vwfs-dk.dev.dwp.vwfs.io/v1/bqs-case/case/{sequence}`.
Requests to update case looks the same as create case. All fields are optional and only sent values will get updated.
```json
{
"agreementCode": 2700,
"externalSystemReference": "2ATT6-39000-F200",
"brandCode": 1,
"calculation": {
"monthlyAmount": 8000,
"administrationFee": 2000
}
}
```
A dealer should only be able change cases that it has created.
### Score customer
Send post request to `https://api.vwfs-dk.dev.dwp.vwfs.io/v1/bqs-case/case/{sequence}/score-customer`.
Body example:
```json
{
"organizationNumber": "76198268"
}
```
### Set business consent
Send post request to `https://api.vwfs-dk.dev.dwp.vwfs.io/v1/bqs-case/case/{sequence}/business-consent`.
Body example:
```json
{
"organizationNumber": "72639057",
"email": "email.example@vwsf.dk"
}
```
### Upload document
A dealer can upload a document to a case that they own
Send post request to `https://api.vwfs-dk.dev.dwp.vwfs.io/v1/bqs-case/document/{sequence}` as `form-data`.
- `file=path-to-file` file to upload
- `code=123` document definition code
Example curl request (This can be pasted into postman)
```sh
curl --location 'https://api.vwfs-dk.dev.dwp.vwfs.io/v1/bqs-case/document/406987' \
--header 'x-channel-id: xxx' \
--form 'file=@"file.pdf"' \
--form 'code="123"'
```
OR with file as base64 encoded string
```sh
curl --location 'https://api.vwfs-dk.dev.dwp.vwfs.io/v1/bqs-case/document/406987' \
--header 'x-channel-id: xxx' \
--form 'fileBase64=JVBERi0xLjMKJcTl8uXrp/Og0MTGCjMgMCBvYm...' \
--form 'code="123"'
```
### Create message (BQS webhook)
A user with the correct permissions can send messages for any case and dealer
#### Request
Send post request to `https://api.vwfs-dk.dev.dwp.vwfs.io/v1/bqs-case/message/case`
Request body sample:
```json
{
"case": {
"externalCaseId": "EC455732",
"preViewCaseId": 455732,
"dealerNumber": 976,
"userId": "User1",
"objectId": 789,
"contractId": "Contract1",
"customerId": 321,
"timestamp": "2022-01-01T00:00:00Z",
"startDate": "2022-01-01T00:00:00Z",
"creditApprovalDate": "2022-01-01T00:00:00Z",
"nominalInterestRate": 0.05,
"vinNumber": "1HGCM82633A123456",
"monthlyPriceIncludingVat": 500.00,
"leasingCode": "Lease123",
"depositAmountReceived": 1000.00,
"caseState": {
"state": "Open",
"stateMessage": "Case is open"
},
"caseActivity": [
{
"activityName": "Activity1",
"activityCode": 101,
"completed": true
}
]
}
}
```
#### Response
- 202 Accepted when a message is successfully created
- 400 Bad request if request is malformed with body
```json
// Example where the creditApprovalDate was a malformed date
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"errors": {
"createMessage": [
"The createMessage field is required."
],
"$.case.creditApprovalDate": [
"The JSON value could not be converted to System.DateTime. Path: $.case.creditApprovalDate | LineNumber: 11 | BytePositionInLine: 31."
]
},
"traceId": "00-3d6011a5df6260c1b61d5a565c859c62-96d2cc646c848d11-01"
}
```
- 401 Unauthorized if user is not authenticated
```json
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.2",
"title": "Unauthorized",
"status": 401,
"traceId": "00-ea0b5c1755a3e010729677bb5ee48a82-8613b9e0d345b818-01"
}
```
- 403 Forbidden
- 500 Internal server error in case of a unhandled exception
```json
{
"Message":"Some error message."
}
```
### Get messages
Users can get messages for a case id given their api-key can handle cases for a dealer id
#### Request
Send Get request to `https://api.vwfs-dk.dev.dwp.vwfs.io/v1/bqs-case/message/case/?from_date={ISODate}&pre_view_case_id={case_id}`
DateFormat example: `2024-03-01T08:20:17.414Z`
```json
{
"preViewCaseId": 455732,
"latestReceivedDate": "2024-05-22T15:21:05.987296+02:00",
"messages": [
{
"externalCaseId": "EC455732",
"preViewCaseId": 455732,
"dealerNumber": 976,
"userId": "User1",
"objectId": 789,
"contractId": "Contract1",
"customerId": 321,
"timestamp": "2022-01-01T01:00:00+01:00",
"startDate": "2022-01-01T01:00:00+01:00",
"creditApprovalDate": "2022-01-01T01:00:00+01:00",
"nominalInterestRate": 0.05,
"vinNumber": "1HGCM82633A123456",
"monthlyPriceIncludingVat": 500,
"leasingCode": "Lease123",
"depositAmountReceived": 1000,
"caseState": {
"state": "Open",
"stateMessage": "Case is open"
},
"caseActivity": [
{
"activityName": "Activity1",
"activityCode": 101,
"completed": true
}
]
}
]
}
```
## User management
Admins can manage other users permissions with management endpoints. Admins need the `Admin` role.
### Create permissions
POST `https://api.vwfs-dk.dev.dwp.vwfs.io/v1/bqs-case/management/`
To add permissions a valid api-key is needed. Use the `channel-id` of the api-key as `channelName`.
```json
{
"channelName": "vwfs-dk-example-public",
"roles": [
"case.write",
"case.read",
"message.read",
"document.write"
],
"allowedDealerCodes": [
921,
789,
737,
114,
755,
],
"allowedBrandCodes": [
4,
11
],
"allowedAgreements": [
3600,
3701
]
}
```
### Update permissions
PUT `https://api.vwfs-dk.dev.dwp.vwfs.io/v1/bqs-case/management/{channelname}`
> **Warning:** Requests to this endponts ***REPLACES*** all current stored roles and permissions.
(The `channelName` is required right now as well. Will be fixed)
```json
{
"channelName": "vwfs-dk-example-public",
"roles": [
"case.write",
"case.read",
"message.read",
"document.write"
],
"allowedDealerCodes": [
921,
789,
737,
114,
755,
],
"allowedBrandCodes": [
4,
11
],
"allowedAgreements": [
3600,
3701
]
}
```
### Get permissions
GET `https://api.vwfs-dk.dev.dwp.vwfs.io/v1/bqs-case/management/{channelname}`
Check a users permission by providing a `channelName` to the request. If no `channelName` is provided all permissions in the database are returned
```json
[
{
"channelName": "vwfs-dk-example-public",
"roles": [
"case.write",
"case.read",
"message.read",
"document.write"
],
"allowedDealerCodes": [
921,
789,
737,
114,
755,
],
"allowedBrandCodes": [
4,
11
],
"allowedAgreements": [
3600,
3701
]
},
{
"channelName": "vwfs-dk-message-example",
"roles": [
"message.write"
],
"allowedDealerCodes": [],
"allowedBrandCodes": [],
"allowedAgreements": []
},
{
"channelName": "vwfs-dk-integrationportal-admin-example",
"roles": [
"admin"
],
"allowedDealerCodes": [],
"allowedBrandCodes": [],
"allowedAgreements": []
},
]
```