-
Notifications
You must be signed in to change notification settings - Fork 1
/
record.cljc
661 lines (540 loc) · 21.7 KB
/
record.cljc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
(ns kintone-client.record
(:require #?(:clj [clojure.core.async :refer [go go-loop <!]]
:cljs [cljs.core.async :refer [<!] :refer-macros [go go-loop]])
[kintone-client.constant.path.record :as path]
[kintone-client.protocols :as pt]
[kintone-client.types :as t]))
(defn get-record
"Retrieves details of 1 record from an app.
app - The kintone app ID.
integer
id - The record ID in kintone app.
integer"
[conn app id]
(let [url (pt/-url conn path/record)]
(pt/-get conn url {:params {:app app :id id}})))
(defn get-records-by-query
"Retrieves details of multiple records from an app using a query string.
app - The kintone app ID.
integer
opts
:fields - Sequence of field codes you want in the response.
sequence of string or nil
:query - The kintone query.
string or nil
A response map always contains the totalCount of query-matched records.
"
([conn app]
(get-records-by-query conn app nil))
([conn app {:keys [fields query]}]
(let [url (pt/-url conn path/records)
params (cond-> {:app app :totalCount true}
(seq fields) (assoc :fields fields)
(seq query) (assoc :query query))]
(pt/-get conn url {:params params}))))
(defn create-cursor
"CAUTION: Consider using get-all-records first (saves you from forgetting to delete cursor).
Use this only if get-all-records returns too many records to eat up the whole RAM of your machine.
Create a cursor that is used to retrieve records.
app - The kintone app ID.
integer
opts
:fields - Sequence of field codes you want in the response.
sequence of string or nil
:query - The kintone query. It can't have limit or offset.
string or nil
:size - Number of records to retrieve per request.
integer or nil
Default: 100.
Maximum: 500"
([conn app]
(create-cursor conn app nil))
([conn app {:keys [fields query size]}]
(let [url (pt/-url conn path/cursor)
size (or size 100)
params (cond-> {:app app :size size}
(seq fields) (assoc :fields fields)
(seq query) (assoc :query query))]
(pt/-post conn url {:params params}))))
(defn get-records-by-cursor
"CAUTION: Consider using get-all-records first (saves you from forgetting to delete cursor).
Use this only if get-all-records returns too many records to eat up the whole RAM of your machine.
Get one block of records with cursor.
:id - Cursor id
string"
[conn {:as cursor :keys [id]}]
(let [url (pt/-url conn path/cursor)
params {:id id}]
(pt/-get conn url {:params params})))
(defn get-all-records
"Get all records with cursor.
The cursor is released when all records are fetched.
app - The kintone app ID.
integer
opts
:fields - Sequence of field codes you want in the response.
sequence of string or nil
:query - The kintone query. It can't have limit or offset.
string or nil
:size - Number of records to retrieve per request.
integer or nil
Default: 100.
Maximum: 500"
([conn app]
(get-all-records conn app nil))
([conn app {:as opts :keys [fields query size]}]
(go
(let [res (<! (create-cursor conn app opts))
cursor (:res res)]
(if (:err res)
res
(loop [ret []]
(let [res (<! (get-records-by-cursor conn cursor))]
(if (:err res)
res
(let [{:keys [records next]} (:res res)
ret (apply conj ret records)]
(if next
(recur ret)
(t/->KintoneResponse {:records ret} nil)))))))))))
(defn delete-cursor
"CAUTION: Consider using get-all-records first (saves you from forgetting to delete cursor).
Use this only if get-all-records returns too many records to eat up the whole RAM of your machine.
Delete a cursor.
cursor - The kintone record cursor
A map has cursor id"
[conn {:as cursor :keys [id]}]
(let [url (pt/-url conn path/cursor)
params {:id id}]
(pt/-delete conn url {:params params})))
(defn add-record
"Add one record to an app.
app - The kintone app ID.
integer
record - The record data that you want to add to kintone app.
See API reference regarding record format."
([app record]
(t/map->BulkRequest {:method :POST
:path path/record
:payload {:app app
:record record}}))
([conn app record]
(let [url (pt/-url conn path/record)
params (cond-> {:app app}
(seq record) (assoc :record record))]
(pt/-post conn url {:params params}))))
(defn add-records
"
CAUTION: Consider using add-all-records first.
Use this only if add-all-records takes too many records to eat up the whole RAM of the machine.
Add multiple records to an app.
app - The kintone app ID.
integer
records - The sequence of record data that you want to add to kintone app.
The size of records must be 100 or less.
See API reference regarding record format.
If the request fail, all registration will be canceled."
([app records]
(t/map->BulkRequest {:method :POST
:path path/records
:payload {:app app
:records records}}))
([conn app records]
(let [url (pt/-url conn path/records)
params {:app app :records records}]
(pt/-post conn url {:params params}))))
(defn add-all-records
"Add Multiple Records to an app.
This API can add more than 100 records unlike `add-records`.
If the request fail, this will stop executing and
return the response that includes both of completed and failed values.
app - The kintone app ID.
integer.
records - The sequence of record data that you want to add to kintone app.
See API reference regarding record format."
[conn app records]
(go-loop [[records :as rests] (partition-all 100 records)
ret (t/->KintoneResponse nil nil)]
(if (empty? records)
ret
(let [res (<! (add-records conn app records))]
(if (:err res)
(t/->KintoneResponse (:res ret) (:err res))
(let [ids (vec (concat (:ids (:res ret))
(:ids (:res res))))
revisions (vec (concat (:revisions (:res ret))
(:revisions (:res res))))]
(recur (rest rests)
(t/->KintoneResponse {:ids ids :revisions revisions} nil))))))))
(defn- ->update-params
[{:keys [id update-key record revision]}]
(cond-> {:record record}
(not update-key) (assoc :id id)
(not id) (assoc :updateKey update-key)
revision (assoc :revision revision)))
(defn update-record
"Updates a record.
There must be :id or :update-key in the params.
app - The kintone app ID.
integer
params - A map of update request params.
:id - The record ID of the kintone app.
If :id is none or nil, :update-key is necessary.
integer
:update-key - The unique key of the record to be updated.
If :update-key is none or nil, :id is necessary.
string
:record - The record data that you want to update.
See API reference regarding record format.
:revision - The revision number of the record.
integer, optional"
([app {:as params :keys [id update-key record revision]}]
(t/map->BulkRequest
{:method :PUT
:path path/record
:payload (assoc (->update-params params)
:app app)}))
([conn app {:as params :keys [id update-key record revision]}]
(let [url (pt/-url conn path/record)
params (assoc (->update-params params)
:app app)]
(pt/-put conn url {:params params}))))
(defn update-records
"
CAUTION: Consider using update-all-records first.
Use this only if update-all-records takes too many records to eat up the whole RAM of the machine.
Updates details of multiple records in an app,
by specifying their record id, or a different unique key.
app - The kintone app ID.
integer
records - The record data that you want to update.
See API reference regarding record format.
The size of records must be 100 or less.
If the request fail, all updating will be canceled.
Each record must be following map.
:id - The record ID of the kintone app.
If :id is none or nil, :update-key is necessary.
integer
:update-key - The unique key of the record to be updated.
If :update-key is none or nil, :id is necessary.
string
:record - The record data that you want to update.
See API reference regarding record format.
:revision - The revision number of the record.
integer, optional"
([app records]
(t/map->BulkRequest
{:method :PUT
:path path/records
:payload {:app app
:records (mapv ->update-params records)}}))
([conn app records]
(let [url (pt/-url conn path/records)
records (mapv ->update-params records)
params {:app app
:records records}]
(pt/-put conn url {:params params}))))
(defn update-all-records
"Updates details of multiple records in an app,
by specifying their record id, or a different unique keys.
This API can update more than 100 records unlike `update-records`.
If the request fail, this will stop executing and
return the response that includes both of completed and failed values.
app - The kintone app ID.
integer
records - The record data that you want to update.
See API reference regarding record format.
If the request fail, all updating will be canceled."
[conn app records]
(go-loop [[records :as rests] (partition-all 100 records)
ret (t/->KintoneResponse nil nil)]
(if (empty? records)
ret
(let [res (<! (update-records conn app records))]
(if (:err res)
(t/->KintoneResponse (:res ret) (:err res))
(let [records (vec (concat (:records (:res ret))
(:records (:res res))))]
(recur (rest rests)
(t/->KintoneResponse {:records records} nil))))))))
(defn delete-records
"Deletes multiple records in an app.
app - The kintone app ID.
integer
ids - Sequence of record id that you want to delete.
The size of records must be 100 or less.
sequence of integer"
([app ids]
(t/map->BulkRequest {:method :DELETE
:path path/records
:payload {:app app
:ids ids}}))
([conn app ids]
(let [url (pt/-url conn path/records)
params {:app app
:ids ids}]
(pt/-delete conn url {:params params}))))
(defn delete-records-with-revision
"Deletes multiple records in an app.
app - The kintone app ID.
integer
params - params includes following keys.
The size of params must be 100 or less.
sequence of map
:id - record id that you want to delete.
integer
:revision - The revision number of the record.
integer"
([app params]
(t/map->BulkRequest {:method :DELETE
:path path/records
:payload {:app app
:ids (mapv :id params)
:revisions (mapv :revision params)}}))
([conn app params]
(let [url (pt/-url conn path/records)
params {:app app
:ids (mapv :id params)
:revisions (mapv :revision params)}]
(pt/-delete conn url {:params params}))))
(defn- get-id-from-record [record]
(when-let [sid (get-in record [:$id :value])]
#?(:clj (Long/parseLong sid)
:cljs (js/parseInt sid 10))))
(defn delete-all-records-by-query
"Deletes all records in an app by query string.
Can delete over 2000 records, but can't do rollback.
app - The kintone app ID.
integer
query - The kintone query. It can't have limit or offset.
string"
[conn app query]
(go
(let [res (<! (create-cursor conn app {:fields [:$id]
:query query
:size 500}))]
(if (:err res)
res
(loop []
(let [cursor (:res res)
res (<! (get-records-by-cursor conn cursor))]
(if (:err res)
res
(let [{:keys [records next]} (:res res)
ids (map get-id-from-record records)]
(if (empty? ids)
(t/->KintoneResponse {} nil)
(let [res (<! (delete-records conn app ids))]
(if (or (:err res) (not next))
res
(recur))))))))))))
(defn get-comments
"Retrieves multiple comments from a record in an app.
app - The kintone app ID.
integer
id - The record id.
integer
opts
:order - The sort order of the Comment ID.
Specifying \"asc\" will sort the comments in ascending order,
and \"desc\" will sort the comments in descending order.
:offset - This skips the retrieval of the first number of comments.
If it is 30, response skips the first 30 comments,
and retrieves from the 31st comment.
There is no maximum for this value.
:limit - The number of records to retrieve.
If it is 5, response retrieve the first 5 comments.
The default and maximum is 10 comments."
([conn app id]
(get-comments conn app id nil))
([conn app id {:as opts :keys [order offset limit]}]
(let [url (pt/-url conn path/comments)
params {:app app
:record id
:order (or order "desc")
:offset (or offset 0)
:limit (or limit 10)}]
(pt/-get conn url {:params params}))))
(defn add-comment
"Add a comment to a record in an app.
app - The kintone app ID.
integer
id - The record id.
integer
comment - A map including comment details.
:text - The comment text.
The maximum characters of the comment is 65535.
:mentions - A sequence including information to mention other users.
:code - The code the user, group or organization that will be mentioned.
The maximum number of mentions is 10.
The mentioned users will be placed in front of the comment text when the API succeeds.
:type - The type of the mentioned target.
USER or GROUP or ORGANIZATION"
[conn app id {:as comment :keys [text mentions]}]
(let [url (pt/-url conn path/comment)
params {:app app
:record id
:comment {:text text :mentions mentions}}]
(pt/-post conn url {:params params})))
(defn delete-comment
"Delete a comment in a record in an app
app - The kintone app ID.
integer
id - The record id.
integer
comment-id - The comment id.
integer"
[conn app id comment-id]
(let [url (pt/-url conn path/comment)
params {:app app
:record id
:comment comment-id}]
(pt/-delete conn url {:params params})))
(defn update-record-assignees
"Update assignees of a record.
app - The kintone app ID.
integer
id - The record id.
integer
assignees - The user codes of the assignees.
If empty, no users will be assigned.
The maximum number of assignees is 100.
sequence of string
revision - The revision number of the record.
integer, optional"
[conn app id assignees revision]
(let [url (pt/-url conn path/assignees)
params (cond-> {:app app
:record id
:assignees assignees}
revision (assoc :revision revision))]
(pt/-put conn url {:params params})))
(defn- ->status-record [{:keys [id action assignee revision]}]
(cond-> {:id id :action action}
assignee (assoc :assignee assignee)
revision (assoc :revision revision)))
(defn update-record-status
"Updates the Status of a record of an app.
app - The kintone app ID.
integer
params
:id - The record id.
integer
:action - The Action name of the action you want to run.
If the localization feature has been used
to apply multiple translations of the action,
specify the name of the action in the language settings
of the user that will run the API.
Note \"Action name\" refers to the text on the button
that is pressed to move Process Management on to the next status.
:assignee - The user code of the assignee.
If empty, no users will be assigned.
The maximum number of assignees is 100.
sequence of string
:revision - The revision number of the record.
integer, optional"
([app {:as params :keys [id action assignee revision]}]
(t/map->BulkRequest {:method :PUT
:path path/status
:payload (assoc (->status-record params)
:app app)}))
([conn app {:as params :keys [id action assignee revision]}]
(let [url (pt/-url conn path/status)
params (assoc (->status-record params)
:app app)]
(pt/-put conn url {:params params}))))
(defn update-records-status
"Updates the Status of multiple records of an app.
app - The kintone app ID.
integer
records - sequence of map.
each map has following keys.
The size must be 100 or less.
:id - The record id.
integer
:action - The Action name of the action you want to run.
If the localization feature has been used
to apply multiple translations of the action,
specify the name of the action in the language settings
of the user that will run the API.
Note \"Action name\" refers to the text on the button
that is pressed to move Process Management on to the next status.
:assignee - The user code of the assignee.
If empty, no users will be assigned.
The maximum number of assignees is 100.
sequence of string
:revision - The revision number of the record.
integer, optional"
([app [{:keys [id action assignee revision]} :as records]]
(t/map->BulkRequest {:method :PUT
:path path/statuses
:payload {:app app
:records (mapv ->status-record records)}}))
([conn app [{:keys [id action assignee revision]} :as records]]
(let [url (pt/-url conn path/statuses)
params {:app app
:records (mapv ->status-record records)}]
(pt/-put conn url {:params params}))))
(defn file-upload
"Uploads a file to kintone.
When a file is uploaded, it produces a file key.
Note that although this API uploads a file to kintone,
it does not upload the file to an attachment field of an App.
To upload the file to an Attachment field,
the file key is used with the Add Record or Update Record API.
file - (Clojure) File
(ClojureScript) File object
filename - The filename you want to set to
string, Only for ClojureScript"
#?(:clj
([conn file]
(let [url (pt/-url conn path/file)
multipart [{:name "file" :content file}]]
(pt/-multipart-post conn url {:multipart multipart})))
:cljs
([conn file filename]
(let [url (pt/-url conn path/file)
multipart (doto (js/FormData.)
(.append "file" file filename))]
(pt/-multipart-post conn url {:multipart multipart})))))
(defn file-download
"Download a file from an attachment field in an app.
file-key - The value(string) is set on the attachment field in the response
that is gotten from GET record APIs.
So the file-key is different from that
obtained from the response when using the Upload File API.
as - (Only Clojure) A keyword that is used for output coercion.
default :byte-array
See clj-http document for detail."
([conn file-key]
(let [url (pt/-url conn path/file)
params {:fileKey file-key}]
(pt/-get-blob conn url {:params params})))
#?(:clj
([conn file-key as]
(let [url (pt/-url conn path/file)
params {:fileKey file-key}]
(pt/-get-blob conn url {:params params :as as})))))
(defn bulk-request
"Runs multiple API requests to multiple apps in one go.
requests - The multiple request maps.
Its size must be 20 or less.
The following functions return a request map
which is used here when you does not pass the connection map to these.
- add-record
- add-records
- update-record
- update-records
- delete-records
- delete-records-with-revision
- update-record-status
- update-records-status"
[conn requests]
(let [url (pt/-url conn path/bulk-request)
requests (mapv (fn [{:as m :keys [path]}]
(-> m
(assoc :api (pt/-path conn path))
(dissoc :path)))
requests)
params {:requests requests}]
(pt/-post conn url {:params params})))