-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: upgrade to response-rejection plugin
- Loading branch information
1 parent
d2f9756
commit e9c18ee
Showing
5 changed files
with
148 additions
and
63 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
'@flatfile/util-response-rejection': patch | ||
'@flatfile/plugin-webhook-egress': patch | ||
--- | ||
|
||
Upgrade to the @flatfile/util-response-rejection plugin to support deleting successfully submitted records or adding a status column to indicate successful/rejected records. |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,63 +1,156 @@ | ||
import api, { Flatfile } from '@flatfile/api' | ||
import { processRecords } from '@flatfile/util-common' | ||
|
||
export interface ResponseRejection { | ||
export interface RejectionResponse { | ||
id: string | ||
sheets: ResponseRejectionSheet[] | ||
message?: string | ||
deleteSubmitted?: boolean | ||
sheets: SheetRejections[] | ||
} | ||
|
||
export interface ResponseRejectionSheet { | ||
id: string | ||
name?: string | ||
rejectedRecords: ResponseRejectionRecord[] | ||
export interface SheetRejections { | ||
sheetId: string | ||
rejectedRecords: RecordRejections[] | ||
} | ||
|
||
export interface ResponseRejectionRecord { | ||
export interface RecordRejections { | ||
id: string | ||
values: { field: string; message: string }[] | ||
} | ||
|
||
export async function responseRejectionHandler( | ||
responseRejection: ResponseRejection | ||
): Promise<number> { | ||
responseRejection: RejectionResponse | ||
): Promise<void | Flatfile.JobCompleteDetails> { | ||
let totalRejectedRecords = 0 | ||
|
||
const results = await Promise.all( | ||
responseRejection.sheets.map((sheet) => updateSheet(sheet)) | ||
) | ||
totalRejectedRecords = results.reduce((acc, val) => acc + val, 0) | ||
// Using a for...of loop to handle asynchronous operations | ||
for (const sheet of responseRejection.sheets || []) { | ||
const count = await updateSheet(sheet, responseRejection.deleteSubmitted) | ||
totalRejectedRecords += count | ||
} | ||
|
||
const message = responseRejection.message ?? getMessage(totalRejectedRecords) | ||
const next = getNext(totalRejectedRecords) | ||
|
||
return { | ||
outcome: { | ||
heading: totalRejectedRecords > 0 ? 'Rejected Records' : 'Success!', | ||
acknowledge: true, | ||
...(next && { next }), | ||
message, | ||
}, | ||
} | ||
} | ||
|
||
function getMessage(totalRejectedRecords) { | ||
return totalRejectedRecords > 0 | ||
? `${totalRejectedRecords} record(s) were rejected during data submission. Review the rejection notes, fix, then resubmit.` | ||
: 'Data was successfully submitted.' | ||
} | ||
|
||
return totalRejectedRecords | ||
function getNext(totalRejectedRecords): Flatfile.JobOutcomeNext | undefined { | ||
return totalRejectedRecords > 0 | ||
? { | ||
type: 'url', | ||
url: '?filter=error', | ||
label: 'See rejections', | ||
} | ||
: undefined | ||
} | ||
|
||
async function updateSheet(sheet: ResponseRejectionSheet): Promise<number> { | ||
if (!sheet.rejectedRecords?.length) { | ||
return 0 | ||
async function updateSheet( | ||
sheetRejections: SheetRejections, | ||
deleteSubmitted: boolean | ||
): Promise<number> { | ||
if (!deleteSubmitted) { | ||
await addSubmissionStatusField(sheetRejections.sheetId) | ||
} | ||
|
||
const rejectedRecordsIds = sheet.rejectedRecords.map((record) => record.id) | ||
const sheetRecords = await api.records.get(sheet.id) | ||
await processRecords(sheetRejections.sheetId, async (records) => { | ||
await updateRecords(sheetRejections, records, deleteSubmitted) | ||
}) | ||
|
||
const rejectedSheetRecords: Flatfile.Record_[] = | ||
sheetRecords.data.records?.filter((record: Flatfile.Record_) => | ||
rejectedRecordsIds.includes(record.id) | ||
) | ||
return sheetRejections.rejectedRecords.length | ||
} | ||
|
||
async function addSubmissionStatusField(sheetId: string): Promise<void> { | ||
try { | ||
const { data: sheet } = await api.sheets.get(sheetId) | ||
if ( | ||
!sheet.config.fields.some((field) => field.key === 'submissionStatus') | ||
) { | ||
await api.sheets.addField(sheet.id, { | ||
key: 'submissionStatus', | ||
label: 'Submission Status', | ||
type: 'enum', | ||
readonly: true, | ||
config: { | ||
allowCustom: false, | ||
options: [ | ||
{ label: 'Rejected', value: 'rejected' }, | ||
{ label: 'Submitted', value: 'submitted' }, | ||
], | ||
}, | ||
}) | ||
} | ||
} catch (error) { | ||
console.error('Error adding rejection status field:', error) | ||
throw 'Error adding rejection status field' | ||
} | ||
} | ||
|
||
for (const record of rejectedSheetRecords || []) { | ||
const rejectedRecord: ResponseRejectionRecord = sheet.rejectedRecords.find( | ||
async function updateRecords( | ||
rejections: SheetRejections, | ||
records: Flatfile.RecordsWithLinks, | ||
deleteSubmitted: boolean | ||
): Promise<void> { | ||
records.forEach((record) => { | ||
const rejectedRecord = rejections.rejectedRecords.find( | ||
(item) => item.id === record.id | ||
) | ||
for (const value of rejectedRecord.values) { | ||
|
||
rejectedRecord?.values.forEach((value) => { | ||
if (record.values[value.field]) { | ||
record.values[value.field].messages = [ | ||
{ | ||
type: 'error', | ||
message: value.message, | ||
}, | ||
{ type: 'error', message: value.message }, | ||
] | ||
} | ||
}) | ||
|
||
if (!deleteSubmitted) { | ||
record.values['submissionStatus'].value = rejectedRecord | ||
? 'rejected' | ||
: 'submitted' | ||
} | ||
}) | ||
|
||
try { | ||
await api.records.update(rejections.sheetId, records) | ||
} catch (error) { | ||
console.error('Error updating records:', error) | ||
throw new Error('Error updating records') | ||
} | ||
|
||
if (deleteSubmitted && records.length !== rejections.rejectedRecords.length) { | ||
await deleteValidRecords(rejections.sheetId) | ||
} | ||
} | ||
|
||
await api.records.update(sheet.id, rejectedSheetRecords) | ||
return rejectedRecordsIds.length | ||
async function deleteValidRecords(sheetId: string): Promise<void> { | ||
try { | ||
const { data: sheet } = await api.sheets.get(sheetId) | ||
await api.jobs.create({ | ||
type: 'workbook', | ||
operation: 'delete-records', | ||
trigger: 'immediate', | ||
source: sheet.workbookId, | ||
config: { | ||
sheet: sheetId, | ||
filter: 'valid', | ||
}, | ||
}) | ||
} catch (error) { | ||
console.error('Error deleting all records:', error) | ||
throw new Error('Error deleting all records') | ||
} | ||
} |