import type { DocumentField, FillDataResponse, FillFieldValue } from './types';
|
|
import { parseTag, primaryFieldTag } from './tags';
|
|
export interface DraftField extends DocumentField {
|
checkboxGroupCode?: string;
|
checkboxGroupMaxSelected?: null | number;
|
checkboxGroupMinSelected?: number;
|
documentValue: FillFieldValue;
|
draftValue: FillFieldValue;
|
formulaMessage?: string;
|
formulaStatus?: 'ERROR' | 'MISSING_INPUT' | 'SUCCESS';
|
readOnly?: boolean;
|
required?: boolean;
|
requiredKnown?: boolean;
|
valueSource?: string;
|
}
|
|
function isEmpty(value: FillFieldValue): boolean {
|
return typeof value === 'string' && value.trim() === '';
|
}
|
|
export function isReferenceTag(tag: string): boolean {
|
return parseTag(tag)?.type === 'reference';
|
}
|
|
function dataTagForDocumentTag(tag: string): string {
|
return primaryFieldTag(tag) ?? tag;
|
}
|
|
function sourceValue(field: DocumentField, data: FillDataResponse): FillFieldValue | undefined {
|
const source = data.fields[dataTagForDocumentTag(field.tag)];
|
if (source?.type !== field.type) return undefined;
|
if (field.type === 'checkbox') return Boolean(source.value);
|
return typeof source.value === 'string' ? source.value : '';
|
}
|
|
function requiredMetadata(field: DocumentField, data: FillDataResponse) {
|
const direct = data.fields[dataTagForDocumentTag(field.tag)];
|
if (direct) return { required: direct.required === true, requiredKnown: true };
|
const parsed = parseTag(field.tag);
|
if (parsed?.type !== 'repeat') {
|
return { required: false, requiredKnown: false };
|
}
|
const matching = Object.entries(data.fields).find(([tag]) => {
|
const candidate = parseTag(tag);
|
return candidate?.type === 'repeat'
|
&& candidate.groupCode === parsed.groupCode && candidate.fieldCode === parsed.fieldCode;
|
});
|
return matching
|
? { required: matching[1].required === true, requiredKnown: true }
|
: { required: false, requiredKnown: false };
|
}
|
|
function checkboxGroupMetadata(field: DocumentField, data: FillDataResponse) {
|
if (field.type !== 'checkbox') return {};
|
const parsed = parseTag(field.tag);
|
if (!parsed || parsed.type === 'reference') return {};
|
const direct = data.fields[field.tag];
|
if (direct?.checkboxGroupCode) return checkboxGroupRule(direct);
|
if (parsed.type !== 'repeat') return {};
|
const matching = Object.entries(data.fields).find(([tag, candidate]) => {
|
const candidateTag = parseTag(tag);
|
return candidate.checkboxGroupCode
|
&& candidateTag?.type === 'repeat'
|
&& candidateTag.groupCode === parsed.groupCode
|
&& candidateTag.fieldCode === parsed.fieldCode;
|
});
|
if (matching?.[1].checkboxGroupCode) {
|
return checkboxGroupRule(matching[1]);
|
}
|
const configured = data.repeatGroups.find((group) => group.groupCode === parsed.groupCode)
|
?.checkboxGroups?.[parsed.fieldCode];
|
return configured
|
? { checkboxGroupCode: configured, checkboxGroupMaxSelected: 1, checkboxGroupMinSelected: 0 }
|
: {};
|
}
|
|
function checkboxGroupRule(field: FillDataResponse['fields'][string]) {
|
return {
|
checkboxGroupCode: field.checkboxGroupCode,
|
checkboxGroupMaxSelected: field.checkboxGroupMaxSelected,
|
checkboxGroupMinSelected: field.checkboxGroupMinSelected,
|
};
|
}
|
|
function fieldMetadata(field: DocumentField, data: FillDataResponse) {
|
const source = data.fields[dataTagForDocumentTag(field.tag)];
|
return {
|
...checkboxGroupMetadata(field, data),
|
...(source?.formulaMessage ? { formulaMessage: source.formulaMessage } : {}),
|
...(source?.formulaStatus ? { formulaStatus: source.formulaStatus } : {}),
|
...(source?.readOnly === true ? { readOnly: true } : {}),
|
...(source?.valueSource ? { valueSource: source.valueSource } : {}),
|
...requiredMetadata(field, data),
|
};
|
}
|
|
export function buildDraftFields(
|
documentFields: DocumentField[],
|
data: FillDataResponse,
|
options: { ignoreDataValues?: boolean; preferData?: boolean } = {},
|
): DraftField[] {
|
return documentFields.map((field) => {
|
let draftValue = field.currentValue;
|
const value = options.ignoreDataValues ? undefined : sourceValue(field, data);
|
if (value !== undefined) {
|
if (options.preferData || field.type === 'checkbox') draftValue = value;
|
else if (isEmpty(field.currentValue) && !isEmpty(value)) draftValue = value;
|
}
|
return { ...field, ...fieldMetadata(field, data), documentValue: field.currentValue, draftValue };
|
});
|
}
|