Работа с контр-предложениями посредством XIMSS API
1. Создание контр-предложения
Контр-предложение позволяет участнику события предложить новое время и/или длительность события. Для создания контр-предложения существующий calendarAccept расширяется двумя новыми атрибутами:
proposedTimeStart - новое время начала события,
proposedDuration - предлагаемая длительность события в секундах.
По полю uid идентифицируется событие, на которое создается контр-предложение. В поле replyComment записывается комментарий участника, сопровождающий новое предложение. Метод vcalendar method устанавливается как "COUNTER". Каждый участник может сделать неограниченное количество контр-предложений на событие, но каждое новое контр-предложение будет затирать предыдущее.
Пример запроса:
<calendarAccept calendar="Calendar-CM-0" id="2" PARTSTAT="TENTATIVE" proposedDuration="3600" proposedTimeStart="20241217T222413">
<icalendar xmlns="urn:ietf:params:xml:ns:xcal">
<vcalendar method="COUNTER">
<vevent>
<organizer>organizer@example.com</organizer>
<summary>Team Meeting</summary>
<uid>123456789</uid>
<dtstart>20241217T182413</dtstart>
<dtend>20241217T192413</dtend>
<priority>5</priority>
<sequence>0</sequence>
<busystatus>BUSY</busystatus>
<attendee CN="John Doe" ROLE="REQ-PARTICIPANT" RSVP="true">johndoe@example.com</attendee>
</vevent>
</vcalendar>
</icalendar>
<replyComment>Looking forward to the meeting!</replyComment>
</calendarAccept>
При создании контр-предложения организатору отправляется почтовое уведомление.
2. Просмотр контр-предложений
Для поиска событий и просмотра связанных контр-предложений используются операции findEvents и calendarRead.
Использование findEvents
Запрос findEvents возвращает список событий в указанном временном интервале. Если событие содержит контр-предложение, возвращается тег hasCounters со значением true.
Пример запроса:
input:
<findEvents calendar="Calendar-CM-0" id="4" items="0" timeFrom="20241226T000000" timeTill="20241227T000000" />
output:
<events id="4" calendar="Calendar-CM-0" timeFrom="20241226T000000" timeTill="20241227T000000" items="1">
<event UID="2" itemUID="867600962.6.test_pollxxrqiowdoqg" timeFrom="20241226T083205" duration="3600" busystatus="BUSY" priority="5" organizer="yes" attendees="3">
<summary>This is a default event with a default name</summary>
<hasCounters>true</hasCounters>
</event>
</events>
Использование calendarRead
При открытии события в календаре организатора через calendarRead возвращаются теги counter, содержащие детали каждого контр-предложения: время начала, время окончания, временную метку, комментарий (если есть) и email автора контр-предложения. Число тегов counter соответствует количеству участников, сделавших контр-предложения.
Пример запроса:
<calendarRead calendar="Calendar-CM-0" id="5" UID="3" />
Пример ответа:
<counter CN="test_rinpmrdwuojudpu@dm.test" COMMENT="Looking forward to the meeting!" DTEND="20250121T140928Z" DTSTAMP="20250121T113928Z" DTSTART="20250121T133928Z">test_rinpmrdwuojudpu@dm.test</counter>
<counter CN="test_ulgxqnagosnuwlv@dm.test" COMMENT="Looking forward to the meeting!" DTEND="20250114T133316Z" DTSTAMP="20250114T120316Z" DTSTART="20250114T130316Z">test_ulgxqnagosnuwlv@dm.test</counter>
В календаре участника возвращается только один тег counter, так как участник может сделать только одно контр-предложение.
Пример ответа:
<counter COMMENT="Looking forward to the meeting!" DTEND="20250114T133316Z" DTSTAMP="20250114T060316Z" DTSTART="20250114T130316Z" />
3. Принятие COUNTER организатором
Принятие контр-предложения выполняется через операцию calendarPublish. После обновления события:
Запрос findEvents больше не возвращает тег hasCounters.
Запрос calendarRead больше не возвращает теги counter.
Пример запроса:
<calendarPublish calendar="Calendar-CM-0" id="4">
<icalendar xmlns="urn:ietf:params:xml:ns:xcal">
<vcalendar method="PUBLISH">
<vevent>
<organizer xmlns="">test_svTMBLerAyANhCa@dm.test</organizer>
<summary xmlns="">This is a default event with a default name</summary>
<dtstart xmlns="">20241226T161335</dtstart>
<dtend xmlns="">20241226T171335</dtend>
<priority xmlns="">5</priority>
<sequence xmlns="">0</sequence>
<busystatus xmlns="">BUSY</busystatus>
<uid xmlns="">a6c6000d-b841-464c-9ccb-444d01b05c98</uid>
<attendee xmlns="" CN="test_hmQzuLXvYUDfYwm@dm.test" ROLE="REQ-PARTICIPANT" RSVP="true">mailto:test_hmQzuLXvYUDfYwm@dm.test</attendee>
<attendee xmlns="" CN="test_IhUkBsmHSfvDAMi@dm.test" ROLE="REQ-PARTICIPANT" RSVP="true">mailto:test_IhUkBsmHSfvDAMi@dm.test</attendee>
<attendee xmlns="" CN="test_svTMBLerAyANhCa@dm.test" ROLE="REQ-PARTICIPANT" RSVP="true">mailto:test_svTMBLerAyANhCa@dm.test</attendee>
</vevent>
</vcalendar>
</icalendar>
</calendarPublish>
4. Отклонение COUNTER организатором
Отклонение контр-предложения выполняется через calendarDecline, который был дополнен новым атрибутом:
- attendeeEmail — email участника, чье контр-предложение отклоняется.
Для удаления контр-предложения исключительно из календаря организатора (без уведомления участника) используется атрибут sendReply, установленный в no. Если он не задан, то по умолчанию равен yes. При наличии комментария в replyComment уведомление отправляется участнику в любом случае.
Пример запроса:
<calendarDecline attendeeEmail="test_AFIupljYoUYUudi@dm.test" calendar="Calendar-CM-0" id="4" sendReply="no">
<icalendar xmlns="urn:ietf:params:xml:ns:xcal">
<vcalendar method="DECLINECOUNTER">
<vevent>
<organizer xmlns="">mailto:test_PDlFeDcjMSEqcRk@dm.test</organizer>
<summary xmlns="">This is a default event with a default name</summary>
<uid xmlns="">63c96617-0444-4256-abdb-e3a1b5d4ba76</uid>
<dtstart xmlns="">20241226T133713</dtstart>
<dtend xmlns="">20241226T143713</dtend>
<priority xmlns="">5</priority>
<sequence xmlns="">0</sequence>
<attendee xmlns="" CN="mailto:test_AFIupljYoUYUudi@dm.test" ROLE="REQ-PARTICIPANT" RSVP="true">mailto:test_AFIupljYoUYUudi@dm.test</attendee>
<attendee xmlns="" CN="mailto:test_lYHYugddTQglibH@dm.test" ROLE="REQ-PARTICIPANT" RSVP="true">mailto:test_lYHYugddTQglibH@dm.test</attendee>
<attendee xmlns="" CN="mailto:test_PDlFeDcjMSEqcRk@dm.test" ROLE="REQ-PARTICIPANT" RSVP="true">mailto:test_PDlFeDcjMSEqcRk@dm.test</attendee>
</vevent>
</vcalendar>
</icalendar>
<replyComment>I'm sorry, but I can't take the counter proposal.</replyComment>
</calendarDecline>
Структура хранения контр-предложения в базе данных (X-CGATE-COUNTER)
X-CGATE-COUNTER;
COMMENT="Looking forward to the meeting!";
DTSTAMP=20250121T113047Z;
DTSTART=20250121T123047Z;
DTEND=20250121T130047Z;
CN="test_timpwywlttclckx@dm.test":
MAILTO:test_timpwywlttclckx@dm.test
Контр-предложение в данном формате представляет собой строку параметров, хранящую альтернативное время встречи, комментарий и информацию об участнике, сделавшем предложение.
Разберем состав этой записи:
X-CGATE-COUNTER (Ключ для хранения контр-предложения) Используется как идентификатор контр-предложения в системе. Предотвращает конфликты с другими календарными системами (Google, Apple, MS Exchange).
COMMENT="Looking forward to the meeting!" (Комментарий) Текстовый комментарий от участника.
DTSTAMP=20250121T113047Z (Временная метка контр-предложения) Время создания контр-предложения. Позволяет определить, когда было отправлено предложение. Полезно для обработки последовательности изменений.
DTSTART=20250121T123047Z (Предложенное время начала) Дата и время начала предложенного слота. Формат UTC.
DTEND=20250121T130047Z (Предложенное время окончания) Дата и время окончания предложенного слота. Формат UTC (YYYYMMDDTHHMMSSZ).
CN="test_timpwywlttclckx@dm.test" (Имя участника, отправившего контр-предложение) Common Name (CN) участника.
MAILTO:test_timpwywlttclckx@dm.test (Email участника) Email-адрес участника, предложившего изменения.