bx-rest 0.22.0 → 0.24.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,3 @@
1
- import { DateTime } from 'luxon';
2
1
  import { switchMap, map, catchError, take, mergeMap as mergeMap$1 } from 'rxjs/operators';
3
2
  import { Subscription, of, throwError, from, forkJoin, last, shareReplay, mergeMap, concatMap, toArray, map as map$1, tap } from 'rxjs';
4
3
  import clone from 'just-clone';
@@ -102,8 +101,154 @@ class ToNumError extends Error {
102
101
  ].join('\n');
103
102
  }
104
103
  }
104
+ /** Соответствие токенов формата регулярным группам захвата. Порядок важен: длинные токены проверяются раньше коротких */
105
+ const DATE_FORMAT_TOKENS = [
106
+ ['yyyy', '(?<yyyy>\\d{4})'],
107
+ ['yy', '(?<yy>\\d{2})'],
108
+ ['MM', '(?<MM>\\d{2})'],
109
+ ['M', '(?<M>\\d{1,2})'],
110
+ ['dd', '(?<dd>\\d{2})'],
111
+ ['d', '(?<d>\\d{1,2})'],
112
+ ['HH', '(?<HH>\\d{2})'],
113
+ ['H', '(?<H>\\d{1,2})'],
114
+ ['mm', '(?<mm>\\d{2})'],
115
+ ['m', '(?<m>\\d{1,2})'],
116
+ ['ss', '(?<ss>\\d{2})'],
117
+ ['s', '(?<s>\\d{1,2})'],
118
+ ];
119
+ const DATE_FORMAT_TOKEN_REGEX = new RegExp(DATE_FORMAT_TOKENS.map(([token]) => token).join('|'), 'g');
120
+ const TIME_ONLY_TOKENS = new Set(['HH', 'H', 'mm', 'm', 'ss', 's']);
105
121
  /**
106
- * Преобразует значение в дату
122
+ * Выводит формат "только дата" из формата даты-и-времени — отрезает время и разделитель перед
123
+ * ним (например, `'dd.MM.yyyy HH:mm:ss'` → `'dd.MM.yyyy'`). Порядок день/месяц/год у полей
124
+ * "дата" и "дата-время" на одном портале Bitrix24 всегда согласован — различается только
125
+ * наличие `HH:mm:ss`, поэтому нет смысла заставлять вызывающего передавать оба формата и
126
+ * держать их в синхроне вручную.
127
+ */
128
+ function deriveDateOnlyFormat(dateTimeFormat) {
129
+ DATE_FORMAT_TOKEN_REGEX.lastIndex = 0;
130
+ let match;
131
+ while ((match = DATE_FORMAT_TOKEN_REGEX.exec(dateTimeFormat)) !== null) {
132
+ if (TIME_ONLY_TOKENS.has(match[0])) {
133
+ // Отрезаем любой разделитель перед временем, включая буквенный (например 'T' в ISO-стиле
134
+ // 'dd.MM.yyyyTHH:mm:ss'), а не только пунктуацию — останавливаемся на последнем символе,
135
+ // который реально относится к токенам даты (y/M/d).
136
+ const datePart = dateTimeFormat.slice(0, match.index).replace(/[^yMd]+$/, '');
137
+ return datePart || dateTimeFormat;
138
+ }
139
+ }
140
+ return dateTimeFormat;
141
+ }
142
+ function escapeRegExp(str) {
143
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
144
+ }
145
+ /**
146
+ * Форматы дат, которые Bitrix24 реально присылает в разных методах REST и на разных
147
+ * порталах — формат даты/времени в ответе зависит от настроек портала (Настройки → формат
148
+ * даты и времени), поэтому один захардкоженный шаблон не универсален. Если явный `format`,
149
+ * переданный в toDate(), не совпал со значением, перед тем как считать строку невалидной,
150
+ * пробуем эти варианты по очереди — они не пересекаются по разделителям/порядку токенов,
151
+ * так что ложных совпадений не будет.
152
+ */
153
+ const FALLBACK_DATE_FORMATS = [
154
+ 'dd.MM.yyyy HH:mm:ss',
155
+ 'yyyy-MM-dd HH:mm:ss',
156
+ 'dd.MM.yyyy',
157
+ 'yyyy-MM-dd',
158
+ ];
159
+ /**
160
+ * Разбирает строку даты по простому шаблону (yyyy, MM, dd, HH, mm, ss и их однобуквенные
161
+ * варианты, например 'dd.MM.yyyy HH:mm:ss'). Разделители между токенами берутся из шаблона
162
+ * как есть. Не поддерживает локали, названия месяцев и часовые пояса — для REST-ответов
163
+ * Bitrix24 они не требуются, значения всегда приходят в фиксированном числовом виде.
164
+ */
165
+ function parseDateWithFormat(val, format) {
166
+ const tokenMap = new Map(DATE_FORMAT_TOKENS);
167
+ let pattern = '';
168
+ let lastIndex = 0;
169
+ let match;
170
+ DATE_FORMAT_TOKEN_REGEX.lastIndex = 0;
171
+ while ((match = DATE_FORMAT_TOKEN_REGEX.exec(format)) !== null) {
172
+ pattern += escapeRegExp(format.slice(lastIndex, match.index));
173
+ pattern += tokenMap.get(match[0]);
174
+ lastIndex = match.index + match[0].length;
175
+ }
176
+ pattern += escapeRegExp(format.slice(lastIndex));
177
+ const result = new RegExp(`^${pattern}$`).exec(val);
178
+ if (!result?.groups) {
179
+ return null;
180
+ }
181
+ const g = result.groups;
182
+ const year = g['yyyy'] ? Number(g['yyyy']) : g['yy'] ? 2000 + Number(g['yy']) : new Date().getFullYear();
183
+ const month = Number(g['MM'] ?? g['M'] ?? 1);
184
+ const day = Number(g['dd'] ?? g['d'] ?? 1);
185
+ const hour = Number(g['HH'] ?? g['H'] ?? 0);
186
+ const minute = Number(g['mm'] ?? g['m'] ?? 0);
187
+ const second = Number(g['ss'] ?? g['s'] ?? 0);
188
+ // Токены — это просто "N цифр", без проверки диапазона (regex не отличит "13" месяца от
189
+ // "13" дня). Без этой проверки new Date() молча "перекатывает" переполнение на соседний
190
+ // месяц/год (например, месяц=13 → январь следующего года) вместо того, чтобы считать
191
+ // строку невалидной.
192
+ if (month < 1 || month > 12 || day < 1 || day > 31 || hour > 23 || minute > 59 || second > 59) {
193
+ return null;
194
+ }
195
+ const date = new Date(year, month - 1, day, hour, minute, second);
196
+ return isNaN(date.getTime()) ? null : date;
197
+ }
198
+ /**
199
+ * Последний резервный разбор — без знания конкретного формата. Работает только для чисто
200
+ * числовых дат (никаких названий месяцев/дней — для этого нужны locale-таблицы, а это как
201
+ * раз тот вес, ради ухода от которого luxon был убран из зависимостей).
202
+ *
203
+ * Идея: год — единственный сегмент длиной ровно 4 цифры, поэтому его позиция (первый или
204
+ * последний из трёх сегментов даты) однозначно опознаётся при любом разделителе (`.`, `-`,
205
+ * `/`, пробел...). Месяц по всем распространённым в мире соглашениям (ISO `yyyy-MM-dd` и
206
+ * европейское `dd.MM.yyyy`) стоит между годом и днём, поэтому берётся как средний сегмент.
207
+ * Время, если есть, всегда идёт как `HH:mm:ss` — этот порядок универсален.
208
+ *
209
+ * Не решает и не пытается решить неоднозначность день/месяц в чисто числовых форматах вида
210
+ * `MM/dd/yyyy` (США), где оба сегмента могут быть ≤12 — угадывать это без знания локали
211
+ * значило бы иногда молча путать день с месяцем, что хуже явной ошибки.
212
+ */
213
+ function parseDateHeuristically(val) {
214
+ const parts = val.match(/\d+/g);
215
+ if (!parts || parts.length < 3 || parts.length > 6) {
216
+ return null;
217
+ }
218
+ const [d0, d1, d2, ...timeParts] = parts;
219
+ const dateParts = [d0, d1, d2];
220
+ const yearIdx = dateParts.findIndex(p => p.length === 4);
221
+ // Год должен быть однозначно найден (ровно 4 цифры) и стоять с края, а не в середине —
222
+ // иначе позиция месяца/дня не определить безопасно.
223
+ if (yearIdx !== 0 && yearIdx !== 2) {
224
+ return null;
225
+ }
226
+ const year = Number(dateParts[yearIdx]);
227
+ const month = Number(dateParts[1]);
228
+ const day = Number(dateParts[yearIdx === 0 ? 2 : 0]);
229
+ if (month < 1 || month > 12 || day < 1 || day > 31) {
230
+ return null;
231
+ }
232
+ const [hh, mm, ss] = timeParts;
233
+ const hour = hh !== undefined ? Number(hh) : 0;
234
+ const minute = mm !== undefined ? Number(mm) : 0;
235
+ const second = ss !== undefined ? Number(ss) : 0;
236
+ if (hour > 23 || minute > 59 || second > 59) {
237
+ return null;
238
+ }
239
+ const date = new Date(year, month - 1, day, hour, minute, second);
240
+ return isNaN(date.getTime()) ? null : date;
241
+ }
242
+ /**
243
+ * Преобразует значение в дату.
244
+ *
245
+ * Если передан `format`, но значение ему не соответствует (см. FALLBACK_DATE_FORMATS —
246
+ * актуально для полей, где Bitrix24 отдаёт дату в формате, настроенном на портале, а не в
247
+ * том, что захардкожен в маппере), перед тем как считать значение невалидным, делаются ещё
248
+ * две попытки: другие распространённые форматы Bitrix24, а затем — позиционная эвристика
249
+ * (см. parseDateHeuristically), которая распознаёт практически любой чисто числовой формат
250
+ * даты независимо от разделителя. Если приложению точно известен формат конкретного портала,
251
+ * его стоит передавать явным `format` — это всегда приоритетнее угадывания.
107
252
  */
108
253
  function toDate(val, format, opt, throwError = true) {
109
254
  if (val instanceof Date) {
@@ -111,10 +256,22 @@ function toDate(val, format, opt, throwError = true) {
111
256
  }
112
257
  else if (typeof val === 'string') {
113
258
  if (format) {
114
- if (opt) {
115
- return DateTime.fromFormat(val, format, opt).toJSDate();
259
+ const parsed = parseDateWithFormat(val, format);
260
+ if (parsed) {
261
+ return parsed;
262
+ }
263
+ for (const fallbackFormat of FALLBACK_DATE_FORMATS) {
264
+ if (fallbackFormat === format)
265
+ continue;
266
+ const fallbackParsed = parseDateWithFormat(val, fallbackFormat);
267
+ if (fallbackParsed) {
268
+ return fallbackParsed;
269
+ }
270
+ }
271
+ const heuristicParsed = parseDateHeuristically(val);
272
+ if (heuristicParsed) {
273
+ return heuristicParsed;
116
274
  }
117
- return DateTime.fromFormat(val, format).toJSDate();
118
275
  }
119
276
  else {
120
277
  return new Date(val);
@@ -255,6 +412,7 @@ var base = /*#__PURE__*/Object.freeze({
255
412
  __proto__: null,
256
413
  ToNumError: ToNumError,
257
414
  cropUrl: cropUrl,
415
+ deriveDateOnlyFormat: deriveDateOnlyFormat,
258
416
  getBase64File: getBase64File,
259
417
  getBase64FileLikeStr: getBase64FileLikeStr,
260
418
  getBaseUrlHttps: getBaseUrlHttps,
@@ -3493,34 +3651,12 @@ class BXRestNavvyUser {
3493
3651
  current() {
3494
3652
  return this.Navvy.simple(this.url.current, undefined, BXRestMapUser.current);
3495
3653
  }
3496
- /*
3497
- update(user: iBXRestUser, fieldUpdate: string[]) {
3498
-
3499
- if (fieldUpdate && fieldUpdate.length) {
3500
- let sendData: any = {
3501
- ID: user.ID,
3502
- }
3503
- const userBX = this.BXRestUserMap.BXtoHttp(user)
3504
- for (const field of fieldUpdate) {
3505
- if (userBX[field]) {
3506
- sendData[field] = userBX[field]
3507
- } else {
3508
- return throwError(() => 'One sent field is empty')
3509
- }
3510
- }
3511
- return this.http.post<iBXRestUserHttp[]>(
3512
- this.url.update,
3513
- sendData
3514
- )
3515
- } else {
3516
- return throwError(() => 'All sent field for edit is empty')
3517
- }
3518
- return this.Navvy.simple(
3519
- this.BXRestUser.update(user, fieldUpdate),
3520
- 'Не удалось обновить пользователя с ID' + user.ID
3521
- )
3654
+ /**
3655
+ * Обновляет данные пользователя. Доступно только пользователю с правами приглашения пользователей.
3656
+ */
3657
+ update(param) {
3658
+ return this.Navvy.simple(this.url.update, param);
3522
3659
  }
3523
- */
3524
3660
  search(params) {
3525
3661
  return this.Navvy.pagNav(this.url.search, params, BXRestMapUser.get);
3526
3662
  }
@@ -3542,69 +3678,6 @@ class BXRestNavvyUser {
3542
3678
  fields() {
3543
3679
  return this.Navvy.simple(this.url.fields);
3544
3680
  }
3545
- // getAll(params: iBXGetParam = {}): Observable<iBXRestUser [] | undefined> {
3546
- // if (!Object.keys(params).length) {
3547
- // params = clone(this.def.params)
3548
- // }
3549
- //
3550
- // const saveAllUser = compare(params, this.def.params)
3551
- // return this.user$.pipe(
3552
- // take(1),
3553
- // mergeMap(v => {
3554
- // if (v.load.all) {
3555
- // if (compare(this.def.params, params)) {
3556
- // return of(clone(v.data))
3557
- // }
3558
- // }
3559
- //
3560
- // return this.getEndArray(params).pipe(
3561
- // take(1),
3562
- // map(v => {
3563
- // if (v && v.result) {
3564
- // let cl = clone(v.result)
3565
- // return this.saveArrUser(cl)
3566
- // }
3567
- // return undefined
3568
- // }),
3569
- // )
3570
- // }),
3571
- // tap(v => {
3572
- // if (v && v.length && saveAllUser) {
3573
- // this.store.dispatch(loadAll({load: true}))
3574
- // }
3575
- // params.start = this.def.params.start
3576
- // })
3577
- // )
3578
- // }
3579
- // private saveArrUser(users: iBXRestUserHttp[]) {
3580
- // let result: iBXRestUser [] = []
3581
- // for (const user of users) {
3582
- // result.push(this.userMap.HttpToBX(user))
3583
- // }
3584
- // this.store.dispatch(saveArr({arr: result}))
3585
- //
3586
- // return result
3587
- // }
3588
- // getEndArray(params: UserFilter = {}): Observable<iHttpAnswerBX<iBXRestUserHttp[]> | undefined> {
3589
- // return this.get(params).pipe(
3590
- // mergeMap(items => {
3591
- // if (items && items.result && typeof items.result === 'object') {
3592
- // if (items.next) {
3593
- // params.start = items.next
3594
- // return this.getEndArray(params).pipe(map(vEnd => {
3595
- // if (vEnd && items.result && vEnd.result) {
3596
- // return {result: [...items.result, ...vEnd.result]}
3597
- // }
3598
- // return (items) ? items : undefined
3599
- // }))
3600
- // }
3601
- // return of(items)
3602
- // } else {
3603
- // return of(undefined)
3604
- // }
3605
- // }),
3606
- // )
3607
- // }
3608
3681
  /**
3609
3682
  * Дополняет параметры запроса пользователей значениями по умолчанию (ACTIVE, start).
3610
3683
  */
@@ -6100,24 +6173,6 @@ class BXRestNavvyOperationDiskStorage {
6100
6173
  }), shareReplay(1));
6101
6174
  }
6102
6175
  }
6103
- /*
6104
- private getforappEnd(){
6105
- console.log('this.BXRestDiskStorage.getforapp()', this.BXRestDiskStorage.getforapp())
6106
- let res = SessionStorage.getItem<iBXRestFolderInfo>(this.constructor.name + this.getforapp.name)
6107
- if(res){
6108
- return of({result: res})
6109
- } else {
6110
- console.log('this.BXRestDiskStorage.getforapp()', this.BXRestDiskStorage, this.BXRestDiskStorage.getforapp())
6111
- return this.BXRestDiskStorage.getforapp().pipe(
6112
- tap(v => {
6113
- if(v){
6114
- SessionStorage.setItem(this.constructor.name + this.getforapp.name, v)
6115
- }
6116
- })
6117
- )
6118
- }
6119
- }
6120
- */
6121
6176
  /**
6122
6177
  * Возвращает список файлов и папок в хранилище приложения.
6123
6178
  */
@@ -6164,24 +6219,6 @@ class BXRestNavvyDiskStorage {
6164
6219
  getForApp() {
6165
6220
  return this.Navvy.simple(this.url.getForApp);
6166
6221
  }
6167
- /*
6168
- private getforappEnd(){
6169
- console.log('this.BXRestDiskStorage.getforapp()', this.BXRestDiskStorage.getforapp())
6170
- let res = SessionStorage.getItem<iBXRestFolderInfo>(this.constructor.name + this.getforapp.name)
6171
- if(res){
6172
- return of({result: res})
6173
- } else {
6174
- console.log('this.BXRestDiskStorage.getforapp()', this.BXRestDiskStorage, this.BXRestDiskStorage.getforapp())
6175
- return this.BXRestDiskStorage.getforapp().pipe(
6176
- tap(v => {
6177
- if(v){
6178
- SessionStorage.setItem(this.constructor.name + this.getforapp.name, v)
6179
- }
6180
- })
6181
- )
6182
- }
6183
- }
6184
- */
6185
6222
  /**
6186
6223
  * Возвращает список файлов и папок в корне хранилища.
6187
6224
  */
@@ -6904,13 +6941,24 @@ class BXRestNavvyLog {
6904
6941
  }
6905
6942
 
6906
6943
  class BXRestMapCalendarEvent {
6907
- static getById(item) {
6908
- return (item) ? BXRestMapCalendarEvent.CalendarEventGetAnswerHttpToCalendarEventGetAnswer(item) : undefined;
6944
+ /**
6945
+ * @param item
6946
+ * @param dateTimeFormat Формат полей с датой и временем (`DATE_CREATE`, `DATE_FROM`, `DATE_TO`, `TIMESTAMP_X`
6947
+ * и т.д.). По умолчанию — распространённый на многих порталах `'dd.MM.yyyy HH:mm:ss'`, но реальный формат
6948
+ * зависит от настроек портала (Настройки → формат даты и времени) — если он известен, передавайте его явно.
6949
+ * Формат для полей только с датой (`EXDATE`, `RRULE.UNTIL`) выводится из этого же значения
6950
+ * (отбрасыванием `HH:mm:ss`) — передавать его отдельно не нужно.
6951
+ */
6952
+ static getById(item, dateTimeFormat = 'dd.MM.yyyy HH:mm:ss') {
6953
+ return (item) ? BXRestMapCalendarEvent.CalendarEventGetAnswerHttpToCalendarEventGetAnswer(item, dateTimeFormat) : undefined;
6909
6954
  }
6910
- static get(item) {
6911
- return (item) ? item.map(i => BXRestMapCalendarEvent.CalendarEventGetAnswerHttpToCalendarEventGetAnswer(i)) : undefined;
6955
+ /** @see getById */
6956
+ static get(item, dateTimeFormat = 'dd.MM.yyyy HH:mm:ss') {
6957
+ return (item) ? item.map(i => BXRestMapCalendarEvent.CalendarEventGetAnswerHttpToCalendarEventGetAnswer(i, dateTimeFormat)) : undefined;
6912
6958
  }
6913
- static CalendarEventGetAnswerHttpToCalendarEventGetAnswer(item) {
6959
+ /** @see getById */
6960
+ static CalendarEventGetAnswerHttpToCalendarEventGetAnswer(item, dateTimeFormat = 'dd.MM.yyyy HH:mm:ss') {
6961
+ const dateFormat = deriveDateOnlyFormat(dateTimeFormat);
6914
6962
  return {
6915
6963
  ...item,
6916
6964
  ID: toNum(item.ID),
@@ -6923,24 +6971,27 @@ class BXRestMapCalendarEvent {
6923
6971
  TZ_OFFSET_FROM: toNum(item.TZ_OFFSET_FROM),
6924
6972
  TZ_OFFSET_TO: toNum(item.TZ_OFFSET_TO),
6925
6973
  VERSION: toNum(item.VERSION),
6926
- DATE_CREATE: toDate(item.DATE_CREATE, 'dd.MM.yyyy HH:mm:ss'),
6927
- DATE_FROM: toDate(item.DATE_FROM, 'dd.MM.yyyy HH:mm:ss'),
6974
+ DATE_CREATE: toDate(item.DATE_CREATE, dateTimeFormat),
6975
+ DATE_FROM: toDate(item.DATE_FROM, dateTimeFormat),
6928
6976
  ORIGINAL_DATE_FROM: (item.ORIGINAL_DATE_FROM)
6929
- ? toDate(item.ORIGINAL_DATE_FROM, 'dd.MM.yyyy HH:mm:ss')
6977
+ ? toDate(item.ORIGINAL_DATE_FROM, dateTimeFormat)
6930
6978
  : null,
6931
- DATE_TO: toDate(item.DATE_TO, 'dd.MM.yyyy HH:mm:ss'),
6932
- TIMESTAMP_X: toDate(item.TIMESTAMP_X, 'dd.MM.yyyy HH:mm:ss'),
6979
+ DATE_TO: toDate(item.DATE_TO, dateTimeFormat),
6980
+ TIMESTAMP_X: toDate(item.TIMESTAMP_X, dateTimeFormat),
6933
6981
  DATE_FROM_TS_UTC: toNum(item.DATE_FROM_TS_UTC),
6934
6982
  DATE_TO_TS_UTC: toNum(item.DATE_TO_TS_UTC),
6935
6983
  DELETED: item.DELETED === 'Y',
6936
6984
  DT_LENGTH: toNum(item.DT_LENGTH),
6937
6985
  DT_SKIP_TIME: item.DT_SKIP_TIME === 'Y',
6938
6986
  MEETING_STATUS: item.MEETING_STATUS === 'Y',
6939
- EXDATE: item.EXDATE.split(';').map(dateStr => toDate(dateStr, 'dd.MM.yyyy')),
6987
+ // EXDATE и RRULE.UNTIL/'~UNTIL' у Bitrix нередко приходят пустой строкой (нет исключённых
6988
+ // дат повторения / правило повторения ограничено через COUNT, а не датой) — пустую строку
6989
+ // toDate() распарсить не может ни при каком формате, поэтому такие поля пропускаем до вызова
6990
+ EXDATE: item.EXDATE ? item.EXDATE.split(';').filter(Boolean).map(dateStr => toDate(dateStr, dateFormat)) : [],
6940
6991
  RRULE: (item.RRULE && typeof item.RRULE !== 'string') ? {
6941
6992
  ...item.RRULE,
6942
- UNTIL: toDate(item.RRULE.UNTIL, 'dd.MM.yyyy'),
6943
- '~UNTIL': toDate(item.RRULE['~UNTIL'], 'dd.MM.yyyy')
6993
+ UNTIL: item.RRULE.UNTIL ? toDate(item.RRULE.UNTIL, dateFormat) : null,
6994
+ '~UNTIL': item.RRULE['~UNTIL'] ? toDate(item.RRULE['~UNTIL'], dateFormat) : null
6944
6995
  } : null,
6945
6996
  ATTENDEE_LIST: (item.ATTENDEE_LIST) ? item.ATTENDEE_LIST.map(i => {
6946
6997
  return { id: i.id, entryId: toNum(i.entryId), status: i.status };
@@ -6976,10 +7027,16 @@ class BXRestNavvyRestCalendarEvent {
6976
7027
  // )
6977
7028
  // }
6978
7029
  this.get = Object.assign(
6979
- /** Возвращает список событий календаря, всегда весь список, паганации в методе нет да и не нужна */
6980
- (param) => this.Navvy.simple(this.url.get, param, BXRestMapCalendarEvent.get), {
6981
- /** Метод получает список будущих событий */
6982
- nearest: (param) => this.Navvy.simple(this.url.get.nearest, param, BXRestMapCalendarEvent.get),
7030
+ /**
7031
+ * Возвращает список событий календаря, всегда весь список, паганации в методе нет да и не нужна.
7032
+ *
7033
+ * @param param
7034
+ * @param dateTimeFormat Формат полей с датой и временем в ответе (см. {@link BXRestMapCalendarEvent.get}).
7035
+ * Передавайте явно, если формат дат на портале отличается от значения по умолчанию.
7036
+ */
7037
+ (param, dateTimeFormat) => this.Navvy.simple(this.url.get, param, (raw) => BXRestMapCalendarEvent.get(raw, dateTimeFormat)), {
7038
+ /** Метод получает список будущих событий. @see get */
7039
+ nearest: (param, dateTimeFormat) => this.Navvy.simple(this.url.get.nearest, param, (raw) => BXRestMapCalendarEvent.get(raw, dateTimeFormat)),
6983
7040
  });
6984
7041
  }
6985
7042
  /** Добавляет событие в календарь */
@@ -6994,24 +7051,37 @@ class BXRestNavvyRestCalendarEvent {
6994
7051
  update(param) {
6995
7052
  return this.Navvy.simple(this.url.update, param);
6996
7053
  }
6997
- /** Метод получает информацию о событии календаря по идентификатору */
6998
- getById(param) {
6999
- return this.Navvy.simple(this.url.getById, param, BXRestMapCalendarEvent.getById);
7054
+ /**
7055
+ * Метод получает информацию о событии календаря по идентификатору.
7056
+ *
7057
+ * @param param
7058
+ * @param dateTimeFormat Формат полей с датой и временем в ответе (см. {@link BXRestMapCalendarEvent.getById}).
7059
+ * Передавайте явно, если формат дат на портале отличается от значения по умолчанию.
7060
+ */
7061
+ getById(param, dateTimeFormat) {
7062
+ return this.Navvy.simple(this.url.getById, param, (raw) => BXRestMapCalendarEvent.getById(raw, dateTimeFormat));
7000
7063
  }
7001
7064
  }
7002
7065
 
7003
7066
  class BXRestMapCalendarSection {
7004
- static get(item) {
7005
- return (item) ? item.map(i => BXRestMapCalendarSection.CalendarSectionGetHttpToCalendarSectionGetHttp(i)) : undefined;
7067
+ /**
7068
+ * @param item
7069
+ * @param dateTimeFormat Формат полей `DATE_CREATE`/`TIMESTAMP_X`. По умолчанию — распространённый на многих
7070
+ * порталах `'dd.MM.yyyy HH:mm:ss'`, но реальный формат зависит от настроек портала (Настройки → формат
7071
+ * даты и времени) — если он известен, передавайте его явно.
7072
+ */
7073
+ static get(item, dateTimeFormat = 'dd.MM.yyyy HH:mm:ss') {
7074
+ return (item) ? item.map(i => BXRestMapCalendarSection.CalendarSectionGetHttpToCalendarSectionGetHttp(i, dateTimeFormat)) : undefined;
7006
7075
  }
7007
- static CalendarSectionGetHttpToCalendarSectionGetHttp(item) {
7076
+ /** @see get */
7077
+ static CalendarSectionGetHttpToCalendarSectionGetHttp(item, dateTimeFormat = 'dd.MM.yyyy HH:mm:ss') {
7008
7078
  return {
7009
7079
  ...item,
7010
7080
  ID: toNum(item.ID),
7011
7081
  OWNER_ID: toNum(item.OWNER_ID),
7012
7082
  CREATED_BY: toNum(item.CREATED_BY),
7013
- DATE_CREATE: toDate(item.DATE_CREATE, 'dd.MM.yyyy HH:mm:ss'),
7014
- TIMESTAMP_X: toDate(item.TIMESTAMP_X, 'dd.MM.yyyy HH:mm:ss')
7083
+ DATE_CREATE: toDate(item.DATE_CREATE, dateTimeFormat),
7084
+ TIMESTAMP_X: toDate(item.TIMESTAMP_X, dateTimeFormat)
7015
7085
  };
7016
7086
  }
7017
7087
  }
@@ -7030,9 +7100,15 @@ class BXRestNavvyRestCalendarSection {
7030
7100
  };
7031
7101
  this.Navvy = new Navvy();
7032
7102
  }
7033
- /** Возвращает описание разделов, всегда весь список, паганации в методе нет да и не нужна */
7034
- get(param) {
7035
- return this.Navvy.simple(this.url.get, param, BXRestMapCalendarSection.get);
7103
+ /**
7104
+ * Возвращает описание разделов, всегда весь список, паганации в методе нет да и не нужна.
7105
+ *
7106
+ * @param param
7107
+ * @param dateTimeFormat Формат полей `DATE_CREATE`/`TIMESTAMP_X` в ответе (см. {@link BXRestMapCalendarSection.get}).
7108
+ * Передавайте явно, если формат дат на портале отличается от значения по умолчанию.
7109
+ */
7110
+ get(param, dateTimeFormat) {
7111
+ return this.Navvy.simple(this.url.get, param, (raw) => BXRestMapCalendarSection.get(raw, dateTimeFormat));
7036
7112
  }
7037
7113
  /** Добавляет новый раздел */
7038
7114
  add(param) {
@@ -9430,22 +9506,29 @@ class BXRestMapCrmStatus {
9430
9506
  }
9431
9507
 
9432
9508
  class BXRestMapCrmCallList {
9433
- /** Преобразует данные списка обзвона из формата Bitrix24 в локальный формат. */
9434
- static get(value) {
9435
- return this.mapItem(value);
9509
+ /**
9510
+ * Преобразует данные списка обзвона из формата Bitrix24 в локальный формат.
9511
+ *
9512
+ * @param value
9513
+ * @param dateTimeFormat Формат поля `DATE_CREATE`. По умолчанию — `'yyyy-MM-dd HH:mm:ss'`, но реальный
9514
+ * формат зависит от настроек портала (Настройки → формат даты и времени) — если он известен,
9515
+ * передавайте его явно.
9516
+ */
9517
+ static get(value, dateTimeFormat = 'yyyy-MM-dd HH:mm:ss') {
9518
+ return this.mapItem(value, dateTimeFormat);
9436
9519
  }
9437
- /** Преобразует список обзвонов с учетом полей, выбранных через `SELECT`. */
9438
- static list(value) {
9439
- return value?.map(item => this.mapItem(item));
9520
+ /** Преобразует список обзвонов с учетом полей, выбранных через `SELECT`. @see get */
9521
+ static list(value, dateTimeFormat = 'yyyy-MM-dd HH:mm:ss') {
9522
+ return value?.map(item => this.mapItem(item, dateTimeFormat));
9440
9523
  }
9441
- static mapItem(value) {
9524
+ static mapItem(value, dateTimeFormat = 'yyyy-MM-dd HH:mm:ss') {
9442
9525
  if (!value)
9443
9526
  return undefined;
9444
9527
  const result = clone(value);
9445
9528
  if (value.ID !== undefined)
9446
9529
  result.ID = toNum(value.ID);
9447
9530
  if (value.DATE_CREATE !== undefined) {
9448
- result.DATE_CREATE = toDate(value.DATE_CREATE, 'yyyy-MM-dd HH:mm:ss');
9531
+ result.DATE_CREATE = toDate(value.DATE_CREATE, dateTimeFormat);
9449
9532
  }
9450
9533
  if (value.CREATED_BY_ID !== undefined)
9451
9534
  result.CREATED_BY_ID = toNum(value.CREATED_BY_ID);
@@ -11452,10 +11535,12 @@ class BXRestNavvyCrmCallList {
11452
11535
  * Участников можно получить через `items.get()`.
11453
11536
  *
11454
11537
  * @param param Идентификатор списка обзвона.
11538
+ * @param dateTimeFormat Формат поля `DATE_CREATE` в ответе (см. {@link BXRestMapCrmCallList.get}).
11539
+ * Передавайте явно, если формат дат на портале отличается от значения по умолчанию.
11455
11540
  * @see https://apidocs.bitrix24.ru/api-reference/crm/call-list/crm-calllist-get.html
11456
11541
  */
11457
- get(param) {
11458
- return this.Navvy.simple(this.url.get, param, BXRestMapCrmCallList.get);
11542
+ get(param, dateTimeFormat) {
11543
+ return this.Navvy.simple(this.url.get, param, (raw) => BXRestMapCrmCallList.get(raw, dateTimeFormat));
11459
11544
  }
11460
11545
  /**
11461
11546
  * Возвращает списки обзвона с выборкой полей, фильтрацией и сортировкой.
@@ -11463,10 +11548,12 @@ class BXRestNavvyCrmCallList {
11463
11548
  * Набор полей каждого элемента результата зависит от `SELECT`.
11464
11549
  *
11465
11550
  * @param param Выбираемые поля, фильтр и порядок сортировки.
11551
+ * @param dateTimeFormat Формат поля `DATE_CREATE` в ответе (см. {@link BXRestMapCrmCallList.list}).
11552
+ * Передавайте явно, если формат дат на портале отличается от значения по умолчанию.
11466
11553
  * @see https://apidocs.bitrix24.ru/api-reference/crm/call-list/crm-calllist-list.html
11467
11554
  */
11468
- list(param = {}) {
11469
- return this.Navvy.simple(this.url.list, param, BXRestMapCrmCallList.list);
11555
+ list(param = {}, dateTimeFormat) {
11556
+ return this.Navvy.simple(this.url.list, param, (raw) => BXRestMapCrmCallList.list(raw, dateTimeFormat));
11470
11557
  }
11471
11558
  /**
11472
11559
  * Возвращает справочник статусов обзвона.