taks-p.4.3
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
import type { Template } from '@pdfme/common';
|
||||
import type {
|
||||
DocumentTemplateMappingWithColumns,
|
||||
ResolvedDocumentTemplate,
|
||||
} from '@/features/foundation/document-template/types';
|
||||
import type { QuotationDocumentData } from '../types';
|
||||
import { buildPdfTopicPages } from './pdf-topic-engine';
|
||||
import { resolveTemplatePages } from './page-resolver';
|
||||
import { createRenderContext, resolveRenderPolicies } from './render-context';
|
||||
import type {
|
||||
BuiltSection,
|
||||
QuotationPdfRuntimeResult,
|
||||
RenderContext,
|
||||
ResolvedTemplate,
|
||||
SectionBuilder,
|
||||
} from './runtime-contracts';
|
||||
import { composeSections } from './section-composer';
|
||||
import { adaptTemplateForSectionRuntime } from './template-compatibility-adapter';
|
||||
import { assembleTemplate } from './template-assembler';
|
||||
|
||||
function cloneTemplate<T>(value: T): T {
|
||||
return JSON.parse(JSON.stringify(value)) as T;
|
||||
}
|
||||
|
||||
function createCustomerSectionBuilder(): SectionBuilder {
|
||||
return {
|
||||
role: 'customer',
|
||||
build(context: RenderContext): BuiltSection<'customer'> {
|
||||
const page = context.pages.byRole.customer?.[0] ?? null;
|
||||
const policy = context.policyBySection.get('customer');
|
||||
|
||||
if (!page) {
|
||||
return {
|
||||
role: 'customer',
|
||||
enabled: policy?.enabled ?? false,
|
||||
rendered: false,
|
||||
anchorPageIndex: null,
|
||||
pages: [],
|
||||
templateInputPatch: {},
|
||||
issues: [
|
||||
{
|
||||
code: 'MISSING_MARKER',
|
||||
severity: policy?.required ? 'error' : 'warning',
|
||||
message: 'Customer section page could not be resolved.',
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
role: 'customer',
|
||||
enabled: true,
|
||||
rendered: true,
|
||||
anchorPageIndex: page.pageIndex,
|
||||
pages: [cloneTemplate(page.schema)],
|
||||
templateInputPatch: {},
|
||||
issues: [],
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function createTopicSectionBuilder(): SectionBuilder {
|
||||
return {
|
||||
role: 'topics',
|
||||
build(context: RenderContext): BuiltSection<'topics'> {
|
||||
const page = context.pages.byRole.topics?.[0] ?? null;
|
||||
const policy = context.policyBySection.get('topics');
|
||||
|
||||
if (!page) {
|
||||
return {
|
||||
role: 'topics',
|
||||
enabled: policy?.enabled ?? false,
|
||||
rendered: false,
|
||||
anchorPageIndex: null,
|
||||
pages: [],
|
||||
templateInputPatch: {},
|
||||
issues: [
|
||||
{
|
||||
code: 'MISSING_MARKER',
|
||||
severity: policy?.required ? 'error' : 'warning',
|
||||
message: 'Topic section page could not be resolved.',
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
const built = buildPdfTopicPages(page.schema, context.documentData.topics.all, {
|
||||
basePageIndex: page.pageIndex,
|
||||
});
|
||||
|
||||
return {
|
||||
role: 'topics',
|
||||
enabled: true,
|
||||
rendered: true,
|
||||
anchorPageIndex: page.pageIndex,
|
||||
pages: built.pages,
|
||||
templateInputPatch: built.topicInputs,
|
||||
issues: built.issues,
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function getQuotationSectionBuilders(): SectionBuilder[] {
|
||||
return [createCustomerSectionBuilder(), createTopicSectionBuilder()];
|
||||
}
|
||||
|
||||
function createResolvedTemplate(
|
||||
template: ResolvedDocumentTemplate,
|
||||
): ResolvedTemplate {
|
||||
return {
|
||||
documentTemplate: template,
|
||||
schema: cloneTemplate(template.version.schemaJson as Template),
|
||||
};
|
||||
}
|
||||
|
||||
function createRuntimeErrorMessage(): string {
|
||||
return 'Quotation PDF runtime is invalid for the active document template.';
|
||||
}
|
||||
|
||||
export async function buildQuotationPdfRuntime(args: {
|
||||
documentData: QuotationDocumentData;
|
||||
template: ResolvedDocumentTemplate;
|
||||
mappings: DocumentTemplateMappingWithColumns[];
|
||||
templateInput: Record<string, unknown>;
|
||||
}): Promise<QuotationPdfRuntimeResult> {
|
||||
const resolvedTemplate = createResolvedTemplate(args.template);
|
||||
const compatibleTemplate = adaptTemplateForSectionRuntime(resolvedTemplate);
|
||||
const pages = resolveTemplatePages(compatibleTemplate);
|
||||
const policies = resolveRenderPolicies();
|
||||
const context = createRenderContext({
|
||||
documentData: args.documentData,
|
||||
template: resolvedTemplate,
|
||||
mappings: args.mappings,
|
||||
pages,
|
||||
policies,
|
||||
issues: pages.issues,
|
||||
});
|
||||
const composed = await composeSections(context, getQuotationSectionBuilders());
|
||||
const assembled = assembleTemplate({
|
||||
template: resolvedTemplate.schema,
|
||||
templateInput: args.templateInput,
|
||||
sections: composed.sections,
|
||||
});
|
||||
const issues = [...pages.issues, ...composed.issues, ...assembled.issues];
|
||||
const topicSection = composed.sections.find((section) => section.role === 'topics');
|
||||
|
||||
if (issues.some((issue) => issue.severity === 'error')) {
|
||||
throw new Error(createRuntimeErrorMessage(), { cause: issues });
|
||||
}
|
||||
|
||||
return {
|
||||
assembled,
|
||||
topicInputs: topicSection
|
||||
? (topicSection.templateInputPatch as Record<string, string[][]>)
|
||||
: {},
|
||||
issues,
|
||||
pages,
|
||||
policies,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user