Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/main/java/com/kintone/client/KintoneApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
import com.kintone.client.api.record.UpdateRecordStatusResponseBody;
import com.kintone.client.api.record.UpdateRecordStatusesResponseBody;
import com.kintone.client.api.record.UpdateRecordsResponseBody;
import com.kintone.client.api.record.UpsertRecordsResponseBody;
import com.kintone.client.api.schema.GetApiListResponseBody;
import com.kintone.client.api.space.AddGuestsResponseBody;
import com.kintone.client.api.space.AddSpaceFromTemplateResponseBody;
Expand Down Expand Up @@ -112,6 +113,7 @@ public enum KintoneApi {
GET_RECORDS(GET, "records", GetRecordsResponseBody.class),
ADD_RECORDS(POST, "records", AddRecordsResponseBody.class),
UPDATE_RECORDS(PUT, "records", UpdateRecordsResponseBody.class),
UPSERT_RECORDS(PUT, "records", UpsertRecordsResponseBody.class),
DELETE_RECORDS(DELETE, "records", DeleteRecordsResponseBody.class),
CREATE_CURSOR(POST, "records/cursor", CreateCursorResponseBody.class),
GET_RECORDS_BY_CURSOR(GET, "records/cursor", GetRecordsByCursorResponseBody.class),
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/com/kintone/client/RecordClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,15 @@
import com.kintone.client.api.record.UpdateRecordStatusesResponseBody;
import com.kintone.client.api.record.UpdateRecordsRequest;
import com.kintone.client.api.record.UpdateRecordsResponseBody;
import com.kintone.client.api.record.UpsertRecordsRequest;
import com.kintone.client.api.record.UpsertRecordsResponseBody;
import com.kintone.client.model.Order;
import com.kintone.client.model.record.PostedRecordComment;
import com.kintone.client.model.record.Record;
import com.kintone.client.model.record.RecordComment;
import com.kintone.client.model.record.RecordForUpdate;
import com.kintone.client.model.record.RecordRevision;
import com.kintone.client.model.record.RecordUpsertResult;
import com.kintone.client.model.record.StatusAction;
import com.kintone.client.model.record.UpdateKey;
import java.util.List;
Expand Down Expand Up @@ -535,6 +538,32 @@ public UpdateRecordsResponseBody updateRecords(UpdateRecordsRequest request) {
return client.call(KintoneApi.UPDATE_RECORDS, request, handlers);
}

/**
* Inserts or updates details of multiple records in an App, by specifying their record numbers,
* or their unique keys. If the record exists, it will be updated. If it does not exist, a new
* record will be created.
*
* @param app the App ID
* @param records a list of objects that include id/updateKey, revision and record objects
* @return a list of record update results. See {@link RecordUpsertResult}
*/
public List<RecordUpsertResult> upsertRecords(long app, List<RecordForUpdate> records) {
UpsertRecordsRequest req = new UpsertRecordsRequest();
req.setApp(app);
req.setRecords(records);
return upsertRecords(req).getRecords();
}

/**
* Inserts or updates details of multiple records in an App.
*
* @param request the request parameters. See {@link UpsertRecordsRequest}
* @return the response data. See {@link UpsertRecordsResponseBody}
*/
public UpsertRecordsResponseBody upsertRecords(UpsertRecordsRequest request) {
return client.call(KintoneApi.UPSERT_RECORDS, request, handlers);
}

/**
* Updates the Status of a record of an App, that was set with the Process Management feature.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.kintone.client.api.record;

import com.kintone.client.api.KintoneRequest;
import com.kintone.client.model.record.RecordForUpdate;
import java.util.List;
import lombok.Data;

/** A request object for Upsert Records API. */
@Data
public class UpsertRecordsRequest implements KintoneRequest {

/** The App ID (required). */
private Long app;

/** A list of objects that include id/updateKey, revision and record objects (required). */
private List<RecordForUpdate> records;

/**
* If set to true, the UPSERT mode will be enabled. In UPSERT mode, if the specified record
* exists, it will be updated. If it does not exist, a new record will be created (optional).
*/
private final Boolean upsert = true;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.kintone.client.api.record;

import com.kintone.client.api.KintoneResponseBody;
import com.kintone.client.model.record.RecordUpsertResult;
import java.util.List;
import lombok.Value;

/** A response object for Upsert Records API. */
@Value
public class UpsertRecordsResponseBody implements KintoneResponseBody {

/** A list of objects that include the record IDs, updated revisions, and operations. */
private final List<RecordUpsertResult> records;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.kintone.client.model.record;

/** The type of operation performed on a record when using UPSERT mode in Update Records API. */
public enum RecordOperationType {
/** An existing record was updated. */
UPDATE,

/** A new record was created. */
INSERT
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.kintone.client.model.record;

import lombok.Value;

/** A value that contains the record ID, revision, and operation, returned by Upsert Records API. */
@Value
public class RecordUpsertResult {

/** The Record ID */
private final long id;

/** The revision number of the record after updating or creating the record. */
private final long revision;

/**
* The operation that was performed. UPDATE (existing record was updated) or INSERT (new record
* was created). Null when not using UPSERT mode.
*/
private final RecordOperationType operation;
}
38 changes: 38 additions & 0 deletions src/test/java/com/kintone/client/RecordClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,15 @@
import com.kintone.client.api.record.UpdateRecordStatusesResponseBody;
import com.kintone.client.api.record.UpdateRecordsRequest;
import com.kintone.client.api.record.UpdateRecordsResponseBody;
import com.kintone.client.api.record.UpsertRecordsRequest;
import com.kintone.client.api.record.UpsertRecordsResponseBody;
import com.kintone.client.model.Order;
import com.kintone.client.model.record.Record;
import com.kintone.client.model.record.RecordComment;
import com.kintone.client.model.record.RecordForUpdate;
import com.kintone.client.model.record.RecordOperationType;
import com.kintone.client.model.record.RecordRevision;
import com.kintone.client.model.record.RecordUpsertResult;
import com.kintone.client.model.record.StatusAction;
import com.kintone.client.model.record.UpdateKey;
import java.util.Arrays;
Expand Down Expand Up @@ -548,6 +552,40 @@ public void updateRecords_UpdateRecordsRequest() {
assertThat(mockClient.getLastBody()).isEqualTo(req);
}

@Test
public void upsertRecords_long_List() {
RecordForUpdate up1 = new RecordForUpdate(1L, new Record());
RecordForUpdate up2 = new RecordForUpdate(new UpdateKey("text", "test"), new Record());
RecordUpsertResult result1 = new RecordUpsertResult(1, 2, RecordOperationType.UPDATE);
RecordUpsertResult result2 = new RecordUpsertResult(100, 2, RecordOperationType.INSERT);
mockClient.setResponseBody(new UpsertRecordsResponseBody(Arrays.asList(result1, result2)));

List<RecordForUpdate> records = Arrays.asList(up1, up2);
List<RecordUpsertResult> result = sut.upsertRecords(1, records);
assertThat(result).hasSize(2);
assertThat(result.get(0).getId()).isEqualTo(1);
assertThat(result.get(0).getRevision()).isEqualTo(2);
assertThat(result.get(0).getOperation()).isEqualTo(RecordOperationType.UPDATE);
assertThat(result.get(1).getId()).isEqualTo(100);
assertThat(result.get(1).getRevision()).isEqualTo(2);
assertThat(result.get(1).getOperation()).isEqualTo(RecordOperationType.INSERT);
assertThat(mockClient.getLastApi()).isEqualTo(KintoneApi.UPSERT_RECORDS);
assertThat(mockClient.getLastBody()).isInstanceOf(UpsertRecordsRequest.class);
UpsertRecordsRequest expected = new UpsertRecordsRequest().setApp(1L).setRecords(records);
assertThat(mockClient.getLastBody()).usingRecursiveComparison().isEqualTo(expected);
}

@Test
public void upsertRecords_UpsertRecordsRequest() {
UpsertRecordsRequest req = new UpsertRecordsRequest();
UpsertRecordsResponseBody resp = new UpsertRecordsResponseBody(Collections.emptyList());
mockClient.setResponseBody(resp);

assertThat(sut.upsertRecords(req)).isEqualTo(resp);
assertThat(mockClient.getLastApi()).isEqualTo(KintoneApi.UPSERT_RECORDS);
assertThat(mockClient.getLastBody()).isEqualTo(req);
}

@Test
public void updateRecordStatus_long_long_String() {
mockClient.setResponseBody(new UpdateRecordStatusResponseBody(10L));
Expand Down