import { KintoneRestAPIClient } from '@kintone/rest-api-client'; import invariant from 'tiny-invariant'; import { loadPluginConfigLookup } from '../common/config'; import { filterConfigByPluginContext, getPluginContext } from '../common/context'; interface UpdateRecordAttachmentFieldValueItem { fileKey: string; } type UpdateRecordAttachmentFieldValue = UpdateRecordAttachmentFieldValueItem[]; ((PLUGIN_ID) => { kintone.events.on( ['app.record.create.show', 'app.record.edit.show', 'mobile.app.record.create.show', 'mobile.app.record.edit.show'], function ( event: | kintone.events.AppRecordCreateShowEvent | kintone.events.AppRecordEditShowEvent | kintone.events.MobileAppRecordCreateShowEvent | kintone.events.MobileAppRecordEditShowEvent, ) { const mappings = loadPluginConfigLookup(PLUGIN_ID); mappings?.forEach((mapping) => { if (mapping.destAttachmentFieldCode in event.record) { (event.record[mapping.destAttachmentFieldCode] as any).disabled = true; } }); return event; }, ); kintone.events.on( [ 'app.record.create.submit.success', 'app.record.edit.submit.success', 'mobile.app.record.create.submit.success', 'mobile.app.record.edit.submit.success', ], async ( event: | kintone.events.AppRecordCreateSubmitSuccessEvent | kintone.events.AppRecordEditSubmitSuccessEvent | kintone.events.MobileAppRecordCreateSubmitSuccessEvent | kintone.events.MobileAppRecordEditSubmitSuccessEvent, ) => { const context = await getPluginContext(event.appId, false); const mappings = filterConfigByPluginContext(loadPluginConfigLookup(PLUGIN_ID), context); if (mappings == null) { return event; } const client = new KintoneRestAPIClient(); await Promise.all( mappings.map(async (mapping) => { const lookupField = event.record[mapping.lookupFieldCode]; invariant( lookupField?.type === 'NUMBER' || lookupField?.type === 'SINGLE_LINE_TEXT', 'The field type of lookup field code must be number or single line text field.', ); const lookupFieldProperty = context.lookupFields.find((p) => p.code === mapping.lookupFieldCode); invariant(lookupFieldProperty != null, 'The property of lookup field not found.'); const destAttachmentField = event.record[mapping.destAttachmentFieldCode]; invariant( destAttachmentField?.type === 'FILE', 'The field type of destination attachment field code must be attachment field.', ); const updateFileKeys: UpdateRecordAttachmentFieldValue = []; if (lookupField.value !== '') { const res = await client.record .getRecords({ app: lookupFieldProperty.lookup.relatedApp.app, query: `${lookupFieldProperty.lookup.relatedKeyField} = "${lookupField.value?.replace(/[\\"]/g, '\\$&')}"`, totalCount: true, }) .catch(() => null); if (res != null && res.totalCount === '1') { const srcRecordId = res.records[0].$id; invariant(srcRecordId.type === '__ID__', 'The field of Source record ID not found.'); const srcAttachmentField = res.records[0][mapping.srcAttachmentFieldCode]; invariant( srcAttachmentField.type === 'FILE', 'The field type of source attachment field code must be attachment field.', ); destAttachmentField.value.forEach((destFileInfo) => { if ( srcAttachmentField.value.find( (srcFileInfo) => destFileInfo.name === srcFileInfo.name && destFileInfo.size === srcFileInfo.size && destFileInfo.contentType === srcFileInfo.contentType, ) != null ) { updateFileKeys.push({ fileKey: destFileInfo.fileKey }); } }); await Promise.all( srcAttachmentField.value .filter((srcFileInfo) => { return ( destAttachmentField.value.find( (destFileInfo) => destFileInfo.name === srcFileInfo.name && destFileInfo.size === srcFileInfo.size && destFileInfo.contentType === srcFileInfo.contentType, ) == null ); }) .map(async (srcFileInfo) => { return client.file .downloadFile({ fileKey: srcFileInfo.fileKey, }) .then((fileData) => { return client.file.uploadFile({ file: { name: srcFileInfo.name, data: new Blob([fileData], { type: srcFileInfo.contentType }), }, }); }) .then((fileKey) => { updateFileKeys.push(fileKey); }); }), ); } } if ( destAttachmentField.value.length !== updateFileKeys.length || destAttachmentField.value.every( (v) => destAttachmentField.value.filter((e) => e.fileKey === v.fileKey).length !== updateFileKeys.filter((e) => e.fileKey === v.fileKey).length, ) ) { await client.record.updateRecord({ app: event.appId, id: event.recordId, record: { [mapping.destAttachmentFieldCode]: { value: updateFileKeys, }, }, }); } }), ).catch((e) => { console.error(e); }); await new Promise((resolve) => setTimeout(resolve, 10000)); return event; }, ); })(kintone.$PLUGIN_ID);