-
Notifications
You must be signed in to change notification settings - Fork 1
DemoScenariesRus_AdvancedLevel_PrivEth
Дополнительно к функционалу сценария Getting Started данный сценарий демонстрирует:
- передачу файлов
- контроль изменения статуса сделки в соответствии с картой статусов
- мониторинг изменения состояния сделок
Данный сценарий проводится в кластере Private Ethereum (PrivEth).
Участники сделки:
- Client1 (роль Role1) - узел PrivEth-1
- Client2 (роль Role2) - узел PrivEth-2
- Client3 (роль Role3) - узел PrivEth-3
Перед исполнением сценария рекомендуется создать на локальном компьютере тестовые файлы Status-1-1.dat, Status-2-1.dat, Status-2-2.dat. Хотя технические ограничения на размер файлов отсутствуют, для ускорения прохождения демо-сценария рекомендуется использовать файлы размером до 100 Kb.
Используется предустановленный смарт-контракт с типом сделки AdvancedDeal, со следующей картой переходов:
- New -> Status-1 -> Role1
- Status-1 -> Status-2 -> Role2
- Status-2 -> Status-3 -> Role3
- Status-3 -> Closed -> Role1,Role3
Сценарий заключается в последовательном исполнении следующих шагов:
- Client1 создает сделку с атрибутами DocNumber, DocDate, DocSumma
- Client1 переключает статус сделки в Status-1 с приложением файла Status-1-1.dat
- Убеждаемся в приходе изменения сделки и файлов на узлы Client1, Client2, Client3
- Client2 переключает статус сделки в Status-2 с приложением файлов Status-2-1.dat и Status-2-2.dat
- Убеждаемся в приходе изменения сделки и файлов на узлы Client1, Client2, Client3
- Client2 пытается переключить статус сделки в Status-4 (статус, несуществующий в карте сделки)
- Убеждаемся в отсутствии изменений в сделке на узлах Client1, Client2, Client3
- Client2 пытается переключить статус сделки в Status-3 (несоответствие ролевой модели карты сделки)
- Убеждаемся в отсутствии изменений в сделке на узлах Client1, Client2, Client3
- Client3 переключает статус сделки в Status-3
- Убеждаемся в приходе изменения сделки на узлы Client1, Client, Client3
- Client1 или Client3 переключает статус сделки в Closed
- Убеждаемся в приходе изменения сделки на узлы Client1, Client2, Client3
ВНИМАНИЕ! В запросах в заголовке CHANNEL необходимо использовать полученный Вами при регистрации персональный идентификатор. Это позволит не мешать одновременной работе нескольких пользователей, а также облегчит работу службы Технической поддержки при возникновении у Вас каких-либо вопросов. В примерах запросов используется персональный идентификатор Demo.
Создание сделки состоит из следующих шагов:
- Получение идентификатора сделки
- Собственно создание сделки
Используется вызов GET-метода /api/uid. Метод возвращает GUID, который может быть однократно использован для создания сделки
Пример вызова:
curl -X GET "http://democlient1.kekker.com/api/uid" -H "accept: text/plain" -H "Authorization: Basic S2Vra2VyVXNlcjp6RGZqbTMz" -H "channel: Demo"
Пример ответа:
"963f75e3-43b9-4aa6-a6cf-7c1d59b600da"
Используется вызов POST-метода /api/deals/. В качестве данных запроса указывается json-спецификация сделки, в нашем случае: { "dealUid": "[UID]", "kind": "AdvancedDeal", "parties": [ { "key": "CLIENT1", "role": "Role1" }, { "key": "ClIENT2", "role": "Role2" }, { "key": "ClIENT3", "role": "Role3" } ], "parameters": [ { "key": "DocNumber", "value": "Advanced-1" }, { "key": "DocDate", "value": "15.02.2020" }, { "key": "DocSumma", "value": "10000" } ], "parentDealUid": null }
Пример вызова:
curl -X POST "http://democlient1.kekker.com/api/deals" -H "accept: text/plain" -H "Content-Type: application/json-patch+json" -H "Authorization: Basic S2Vra2VyVXNlcjp6RGZqbTMz" -H "channel: Demo" -d "{ \"dealUid\": \"963f75e3-43b9-4aa6-a6cf-7c1d59b600da\", \"kind\": \"AdvancedDeal\", \"parties\": [ { \"key\": \"CLIENT1\", \"role\": \"Role1\" }, { \"key\": \"CLIENT2\", \"role\": \"Role2\" }, { \"key\": \"CLIENT3\", \"role\": \"Role3\" } ], \"parameters\": [ { \"key\": \"DocNumber\", \"value\": \"Advanced-1\" }, { \"key\": \"DocDate\", \"value\": \"15.02.2020\" },{ \"key\": \"DocSumma\", \"value\": \"10000\" } ], \"parentDealUid\": null}"
Если всё хорошо - ответ пустой.
Изменение состояния сделки в общем случае состоит из следующих шагов:
- Загрузка файлов, прикрепляемых к новому статусу сделки
- Собственно изменение состояния сделки
Используется вызов POST-метода /api/deals/files. В качестве полей в запросе передаются следующие данные:
- DealUid= [UID]
- FileKind = Status-1-1
- FormFile = @<путь к файлу>;type=text/plain
Пример вызова:
curl -X POST "http://democlient1.kekker.com/api/deals/files" -H "accept: text/plain" -H "Authorization: Basic S2Vra2VyVXNlcjp6RGZqbTMz" -H "channel: Demo" -H "Content-Type: multipart/form-data" -F "DealUid=963f75e3-43b9-4aa6-a6cf-7c1d59b600da" -F "FileKind=Status-1-1" -F "formFile=@C:/Kekker/Status-1-1.dat;type=text/plain"
Если всё хорошо - ответ пустой.
Используется вызов POST-метода /api/deals/setstatus. В качестве данных запроса указывается json-спецификация нового состояния сделки, в нашем случае: { "dealUid": "[UID]", "status": "Status-1_", "remark": "Status changed to Status-1 by CLIENT1", "parameters": [] }
Пример вызова:
curl -X POST "http://democlient1.kekker.com/api/deals/setstatus" -H "accept: text/plain" -H "Authorization: Basic S2Vra2VyVXNlcjp6RGZqbTMz" -H "Content-Type: application/json-patch+json" -H "channel: Demo" -d "{ \"dealUid\":\"963f75e3-43b9-4aa6-a6cf-7c1d59b600da\", \"status\":\"Status-1_\", \"remark\":\"Status changed to Status-1 by CLIENT1\", \"parameters\": []}"
Если всё хорошо - ответ пустой.
Получение информации по измененным сделкам в общем случае состоит из следующих шагов:
- Мониторинг событий по сделкам
- Извлечение данных сделки
- Отметка обработанного события
- Выгрузка файлов, связанных со сделкой
Используется вызов GET-метода /api/events/new. У запроса может задан набор фильтров, в нашем случае: take=10, eventTypes=StatusChanged (события изменения сделок по 10 штук)
Пример вызова (для клиента Client2):
curl -X GET "http://democlient2.kekker.com/api/events/new?take=10&eventTypes=StatusChanged" -H "accept: text/plain" -H "Authorization: Basic S2Vra2VyVXNlcjp6RGZqbTMz" -H "channel: Demo"
Пример ответа (если Вы исполняете данный сценарий после сценария Getting Started, то ответ будет содержать также события по демо-сделке FirstDeal):
[{"actor":{"key":"CLIENT1","role":"Role1"},"version":2,"state":"Status-1_","files":[{"fileUid":"4a16ba7f-a545-40c2-8191-7a805fc6ba31","filePath":"C:\KekkerWork\12\IPFS:QmfWLy31kzEPbzRbrys3qGJ34YmFsotuh3yFE8t6hu5XwP.dat","fileKind":"Status-1-1","state":"Status-1_","version":2}],"eventName":"StatusChanged","eventUid":"491bf13d-68f5-4017-8a13-df64b12d0132","dealUid":"963f75e3-43b9-4aa6-a6cf-7c1d59b600da","timestamp":"2020-02-16T08:20:14.17","active":true}]
В ответе, в каждой записи о событии, обращаем внимание на eventUid (идентификатор события) и dealUid (идентификатор сделки). В нашем
Используется вызов GET-метода /api/deals/{UID}. Где {UID} - идентификатор сделки
Пример запроса (для клиента Client2):
curl -X GET "http://democlient2.kekker.com/api/deals/963f75e3-43b9-4aa6-a6cf-7c1d59b600da" -H "accept: text/plain" -H "Authorization: Basic S2Vra2VyVXNlcjp6RGZqbTMz" -H "channel: Demo"
Пример ответа:
{"uid":"963f75e3-43b9-4aa6-a6cf-7c1d59b600da","kind":"AdvancedDeal","status":"Status-1_","remark":"Status changed to Status-1 by CLIENT1","parameters":[{"key":"DocNumber","value":"Advanced-1"},{"key":"DocDate","value":"15.02.2020"},{"key":"DocSumma","value":"10000"}],"parties":[{"key":"CLIENT1","role":"Role1"},{"key":"CLIENT2","role":"Role2"},{"key":"CLIENT3","role":"Role3"}],"files":[{"fileUid":"4a16ba7f-a545-40c2-8191-7a805fc6ba31","filePath":"C:\KekkerWork\12\IPFS:QmfWLy31kzEPbzRbrys3qGJ34YmFsotuh3yFE8t6hu5XwP.dat","fileKind":"Status-1-1","state":"Status-1_","version":2}],"history":[{"status":"Status-1_","party":{"key":"CLIENT1","role":"Role1"},"remark":"Status changed to Status-1 by CLIENT1","version":2}],"statusMap":[{"status":"*","statusNext":"Status-1_","role":"Role1"},{"status":"Status-1_.1","statusNext":"Status-2_","role":"Role2"},{"status":"Status-2_.1","statusNext":"Status-3_","role":"Role3"},{"status":"Status-3_.1","statusNext":"Closed___","role":"Role1"},{"status":"Status-3_.2","statusNext":"Closed___","role":"Role1"}]}
Используется вызов POST-метода /api/events/{UID}/ack. Где {UID} - идентификатор события (не сделки!)
Пример запроса (для клиента Client2):
curl -X POST "http://democlient2.kekker.com/api/events/491bf13d-68f5-4017-8a13-df64b12d0132/ack" -H "accept: text/plain" -H "Authorization: Basic S2Vra2VyVXNlcjp6RGZqbTMz" -H "channel: Demo" -H "content-length: 0"
Если всё хорошо - ответ пустой.
После того как все события в очереди обработаны - запрос /api/events/new выдаст пустой результат.
Если к сделки привязаны какие-либо файлы - в описании сделки будет присутствовать непустая коллекция files. Доступ к файлу может быть получен либо по указанному для него в поле filePath пути (если бизнес-приложение имеет прямой доступ к файловому пространству узла платформы), либо путем скачивания с использованием метода GET /api/deals/{UID}/files/{FileUID}, где {UID} - идентификатор сделки, а {FileUID} - идентификатор файла из поля fileUid.
Пример запроса файла (для узла 2):
curl -X GET "http://democlient2.kekker.com/api/deals/963f75e3-43b9-4aa6-a6cf-7c1d59b600da/files/4a16ba7f-a545-40c2-8191-7a805fc6ba31" -H "accept: text/plain" -H "Authorization: Basic S2Vra2VyVXNlcjp6RGZqbTMz" -H "channel: Demo"
Пример ответа:
Status-1-1.dat Test file for demo scenario Advanced Level
4. Client2 переключает статус сделки в Status-2 с приложением файлов Status-2-1.dat и Status-2-2.dat
Действуем аналогично шагу [2], только перед изменением статуса сделки вместо одного файла последовательно загружаем два.
Пример запросов:
curl -X POST "http://democlient2.kekker.com/api/deals/files" -H "accept: text/plain" -H "Authorization: Basic S2Vra2VyVXNlcjp6RGZqbTMz" -H "channel: Demo" -H "Content-Type: multipart/form-data" -F "DealUid=963f75e3-43b9-4aa6-a6cf-7c1d59b600da" -F "FileKind=Status-2-1" -F "formFile=@C:/Kekker/Status-2-1.dat;type=text/plain"
curl -X POST "http://democlient2.kekker.com/api/deals/files" -H "accept: text/plain" -H "Authorization: Basic S2Vra2VyVXNlcjp6RGZqbTMz" -H "channel: Demo" -H "Content-Type: multipart/form-data" -F "DealUid=963f75e3-43b9-4aa6-a6cf-7c1d59b600da" -F "FileKind=Status-2-2" -F "formFile=@C:/Kekker/Status-2-2.dat;type=text/plain"
curl -X POST "http://democlient2.kekker.com/api/deals/setstatus" -H "accept: text/plain" -H "Authorization: Basic S2Vra2VyVXNlcjp6RGZqbTMz" -H "Content-Type: application/json-patch+json" -H "channel: Demo" -d "{ \"dealUid\":\"963f75e3-43b9-4aa6-a6cf-7c1d59b600da\", \"status\":\"Status-2_\", \"remark\":\"Status changed to Status-2 by CLIENT2\", \"parameters\": []}"
Если всё хорошо - все ответы должны быть пустыми.
Действуем аналогично шагу [3], обращая внимание на изменение полей status и remark, а также коллекций history и file.
При этом следует отметить, что каждый файл привязан не только к некоторому статусу, но и к конкретному шагу истории изменения сделки, определяемому атрибутом version.
На этом и следующем шаге демонстрируется действие блокировочных механизмов, запрещающих изменение статуса сделки с нарушением присвоенной сделке карты изменения состояний. Карта изменения состояний содержится в описании сделки в коллекции "statusMap". Карта состоит из набора записей, декларирующих из какого статуса (поле status) в какой (поле statusNext) допустимо переключение и какой ролью (поле role) должен обладать участник сделки,имеющий право данное переключение сделать. При попытке переключить в неразрешенный статус или участником без надлежащей роли будет отклонена.
Механизм имеет два уровня действий:
- первый уровень осуществляется приложениями платформы, контролирующими операцию setStatus и выдающими соответствующее сообщение при попытке установить некорректный статус
- второй уровень реализован непосредственно в смарт-контракте сделки и блокирует попытки изменения на уровне технических транзакций DLT-платформы.
Попробуем перевести сделку в статус Status-4, отсутствующий в карте изменения статусов сделки.
Пример запроса:
curl -X POST "http://democlient2.kekker.com/api/deals/setstatus" -H "accept: text/plain" -H "Authorization: Basic S2Vra2VyVXNlcjp6RGZqbTMz" -H "Content-Type: application/json-patch+json" -H "channel: Demo" -d "{ \"dealUid\":\"963f75e3-43b9-4aa6-a6cf-7c1d59b600da\", \"status\":\"Status-4_\", \"remark\":\"Status changed to Status-4 by CLIENT2\", \"parameters\": []}"
Пример ответа:
{"ErrorMessage":"Status "Status-4_" not accepted for DealKind "AdvancedDeal""}
Чтобы убедится, что изменения сделки не произошло, можно некоторое время осуществлять мониторинг событий сделки или запрашивать ее состояние, как это описано в шаге [3].
8. Client2 пытается переключить статус сделки в Status-3 (несоответствие ролевой модели карты сделки)
Попробуем перевести сделку в статус Status-3, который допустим для данного состояния сделки, но роль участника Client2 не позволяет это сделать.
Пример запроса:
curl -X POST "http://democlient2.kekker.com/api/deals/setstatus" -H "accept: text/plain" -H "Authorization: Basic S2Vra2VyVXNlcjp6RGZqbTMz" -H "Content-Type: application/json-patch+json" -H "channel: Demo" -d "{ \"dealUid\":\"963f75e3-43b9-4aa6-a6cf-7c1d59b600da\", \"status\":\"Status-3_\", \"remark\":\"Status changed to Status-4 by CLIENT2\", \"parameters\": []}"
В данном случае ответ будет пустым.
Чтобы убедится, что изменения сделки не произошло, можно некоторое время осуществлять мониторинг событий сделки или запрашивать ее состояние, как это описано в шаге [3].
Используется вызов POST-метода /api/deals/setstatus. В качестве данных запроса указывается json-спецификация нового состояния сделки, в нашем случае: { "dealUid": "[UID]", "status": "Status-3_", "remark": "Status changed to Status-3 by CLIENT3", "parameters": [] }
Пример запроса:
curl -X POST "http://democlient3.kekker.com/api/deals/setstatus" -H "accept: text/plain" -H "Authorization: Basic S2Vra2VyVXNlcjp6RGZqbTMz" -H "Content-Type: application/json-patch+json" -H "channel: Demo" -d "{ \"dealUid\":\"963f75e3-43b9-4aa6-a6cf-7c1d59b600da\", \"status\":\"Status-3_\", \"remark\":\"Status changed to Status-3 by CLIENT3\", \"parameters\": []}"
Если всё хорошо - ответ должен быть пустым.
Аналогично шагу [3] получаем событие изменения и состояние сделки.
Пример запроса событий:
curl -X GET "http://democlient2.kekker.com/api/events/new?take=10&eventTypes=StatusChanged" -H "accept: text/plain" -H "Authorization: Basic S2Vra2VyVXNlcjp6RGZqbTMz" -H "channel: Demo"
Пример ответа:
[{"actor":{"key":"CLIENT3","role":"Role3"},"version":4,"state":"Status-3_","files":[],"eventName":"StatusChanged","eventUid":"f2e9da22-fc37-4978-b67a-88de8bd51bf5","dealUid":"963f75e3-43b9-4aa6-a6cf-7c1d59b600da","timestamp":"2020-02-17T21:14:07.017","active":true}]
Пример запроса состояния сделки:
curl -X GET "http://democlient2.kekker.com/api/deals/963f75e3-43b9-4aa6-a6cf-7c1d59b600da" -H "accept: text/plain" -H "Authorization: Basic S2Vra2VyVXNlcjp6RGZqbTMz" -H "channel: Demo"
Пример ответа:
{"uid":"963f75e3-43b9-4aa6-a6cf-7c1d59b600da","kind":"AdvancedDeal","status":"Status-3_","remark":"Status changed to Status-3 by CLIENT3","parameters":[{"key":"DocNumber","value":"Advanced-1"},{"key":"DocDate","value":"15.02.2020"},{"key":"DocSumma","value":"10000"}],"parties":[{"key":"CLIENT1","role":"Role1"},{"key":"CLIENT2","role":"Role2"},{"key":"CLIENT3","role":"Role3"}],"files":[{"fileUid":"4a16ba7f-a545-40c2-8191-7a805fc6ba31","filePath":"C:\KekkerWork\12\IPFS:QmfWLy31kzEPbzRbrys3qGJ34YmFsotuh3yFE8t6hu5XwP.dat","fileKind":"Status-1-1","state":"Status-1_","version":2},{"fileUid":"2d227f15-ed32-4897-b3db-14d7fee8f52b","filePath":"C:\KekkerWork\0c92523c7ffe4ead80cf3b4e767cb81c_Status-2-1.dat","fileKind":"Status-2-1","state":"Status-2_","version":3},{"fileUid":"9b36dd95-2469-4d5d-b731-413500c77b77","filePath":"C:\KekkerWork\13803fe2f92143749bf2f75a7a81fa3a_Status-2-2.dat","fileKind":"Status-2-2","state":"Status-2_","version":3},{"fileUid":"4a16ba7f-a545-40c2-8191-7a805fc6ba31","filePath":"C:\KekkerWork\12\IPFS:QmfWLy31kzEPbzRbrys3qGJ34YmFsotuh3yFE8t6hu5XwP.dat","fileKind":"Status-1-1","state":"Status-1_","version":2}],"history":[{"status":"Status-1_","party":{"key":"CLIENT1","role":"Role1"},"remark":"Status changed to Status-1 by CLIENT1","version":2},{"status":"Status-2_","party":{"key":"CLIENT2","role":"Role2"},"remark":"Status changed to Status-2 by CLIENT2","version":3},{"status":"Status-3_","party":{"key":"CLIENT3","role":"Role3"},"remark":"Status changed to Status-3 by CLIENT3","version":4}], "statusMap":[{"status":"*","statusNext":"Status-1_","role":"Role1"},{"status":"Status-1_.1","statusNext":"Status-2_","role":"Role2"},{"status":"Status-2_.1","statusNext":"Status-3_","role":"Role3"},{"status":"Status-3_.1","statusNext":"Closed___","role":"Role1"},{"status":"Status-3_.2","statusNext":"Closed___","role":"Role1"}]}
Используется вызов POST-метода /api/deals/setstatus. В качестве данных запроса указывается json-спецификация нового состояния сделки, в нашем случае в зависимости от участника, осуществляющего переключение это:
- для переключения участником Client1: { "dealUid": "[UID]", "status": "Closed___", "remark": "Deal closed by CLIENT1", "parameters": [] }
- для переключения участником Client3: { "dealUid": "[UID]", "status": "Closed___", "remark": "Deal closed by CLIENT3", "parameters": [] }
Пример запроса состояния сделки (для участников Client1 и Client3, соответственно):
curl -X POST "http://democlient1.kekker.com/api/deals/setstatus" -H "accept: text/plain" -H "Authorization: Basic S2Vra2VyVXNlcjp6RGZqbTMz" -H "Content-Type: application/json-patch+json" -H "channel: Demo" -d "{ \"dealUid\":\"963f75e3-43b9-4aa6-a6cf-7c1d59b600da\", \"status\":\"Closed___\", \"remark\":\"Deal closed by CLIENT1\", \"parameters\": []}"
или
curl -X POST "http://democlient3.kekker.com/api/deals/setstatus" -H "accept: text/plain" -H "Authorization: Basic S2Vra2VyVXNlcjp6RGZqbTMz" -H "Content-Type: application/json-patch+json" -H "channel: Demo" -d "{ \"dealUid\":\"963f75e3-43b9-4aa6-a6cf-7c1d59b600da\", \"status\":\"Closed___\", \"remark\":\"Deal closed by CLIENT3\", \"parameters\": []}"
Если всё хорошо - ответ должен быть пустым.
Аналогично шагу [3] получаем событие изменения и состояние сделки.
Пример запроса событий:
curl -X GET "http://democlient2.kekker.com/api/events/new?take=10&eventTypes=StatusChanged" -H "accept: text/plain" -H "Authorization: Basic S2Vra2VyVXNlcjp6RGZqbTMz" -H "channel: Demo"
Пример ответа:
[{"actor":{"key":"CLIENT1","role":"Role1"},"version":5,"state":"Closed___","files":[],"eventName":"StatusChanged","eventUid":"aa2f88a6-281b-49e7-803f-fb95c1027710","dealUid":"963f75e3-43b9-4aa6-a6cf-7c1d59b600da","timestamp":"2020-02-17T21:29:27.017","active":true}]
Пример запроса состояния сделки:
curl -X GET "http://democlient2.kekker.com/api/deals/963f75e3-43b9-4aa6-a6cf-7c1d59b600da" -H "accept: text/plain" -H "Authorization: Basic S2Vra2VyVXNlcjp6RGZqbTMz" -H "channel: Demo"
Пример ответа:
{"uid":"963f75e3-43b9-4aa6-a6cf-7c1d59b600da","kind":"AdvancedDeal","status":"Closed___","remark":"Deal closed by CLIENT1","parameters":[{"key":"DocNumber","value":"Advanced-1"},{"key":"DocDate","value":"15.02.2020"},{"key":"DocSumma","value":"10000"}],"parties":[{"key":"CLIENT1","role":"Role1"},{"key":"CLIENT2","role":"Role2"},{"key":"CLIENT3","role":"Role3"}],"files":[{"fileUid":"4a16ba7f-a545-40c2-8191-7a805fc6ba31","filePath":"C:\KekkerWork\12\IPFS:QmfWLy31kzEPbzRbrys3qGJ34YmFsotuh3yFE8t6hu5XwP.dat","fileKind":"Status-1-1","state":"Status-1_","version":2},{"fileUid":"2d227f15-ed32-4897-b3db-14d7fee8f52b","filePath":"C:\KekkerWork\0c92523c7ffe4ead80cf3b4e767cb81c_Status-2-1.dat","fileKind":"Status-2-1","state":"Status-2_","version":3},{"fileUid":"9b36dd95-2469-4d5d-b731-413500c77b77","filePath":"C:\KekkerWork\13803fe2f92143749bf2f75a7a81fa3a_Status-2-2.dat","fileKind":"Status-2-2","state":"Status-2_","version":3},{"fileUid":"4a16ba7f-a545-40c2-8191-7a805fc6ba31","filePath":"C:\KekkerWork\12\IPFS:QmfWLy31kzEPbzRbrys3qGJ34YmFsotuh3yFE8t6hu5XwP.dat","fileKind":"Status-1-1","state":"Status-1_","version":2}],"history":[{"status":"Status-1_","party":{"key":"CLIENT1","role":"Role1"},"remark":"Status changed to Status-1 by CLIENT1","version":2},{"status":"Status-2_","party":{"key":"CLIENT2","role":"Role2"},"remark":"Status changed to Status-2 by CLIENT2","version":3},{"status":"Status-3_","party":{"key":"CLIENT3","role":"Role3"},"remark":"Status changed to Status-3 by CLIENT3","version":4},{"status":"Closed___","party":{"key":"CLIENT1","role":"Role1"},"remark":"Deal closed by CLIENT1","version":5}],"statusMap":[{"status":"*","statusNext":"Status-1_","role":"Role1"},{"status":"Status-1_.1","statusNext":"Status-2_","role":"Role2"},{"status":"Status-2_.1","statusNext":"Status-3_","role":"Role3"},{"status":"Status-3_.1","statusNext":"Closed___","role":"Role1"},{"status":"Status-3_.2","statusNext":"Closed___","role":"Role1"}]}