farmcontrol-scheduler/src/database/schemas/management/documenttemplate.schema.js
Tom Butcher f9284ed1f2
Some checks failed
farmcontrol/farmcontrol-scheduler/pipeline/head There was a failure building this commit
Initial Commit
2026-09-06 23:06:27 +01:00

167 lines
4.3 KiB
JavaScript

import mongoose from 'mongoose';
import { generateId } from '../../utils.js';
const { Schema } = mongoose;
const RENDER_DOCUMENT_TEMPLATE_CALL =
/fc\.renderDocumentTemplate\s*\(\s*(['"])([^'"]+)\1/g;
function extractRenderDocumentTemplateReferences(content) {
if (content == null || typeof content !== 'string' || content === '') {
return [];
}
const references = [];
const seen = new Set();
const regex = new RegExp(RENDER_DOCUMENT_TEMPLATE_CALL.source, 'g');
let match;
while ((match = regex.exec(content)) !== null) {
const reference = match[2]?.trim();
if (!reference || seen.has(reference)) {
continue;
}
seen.add(reference);
references.push(reference);
}
return references;
}
function objectIdsFromFilterValue(value) {
if (value == null) {
return [];
}
if (value instanceof mongoose.Types.ObjectId) {
return [value];
}
if (typeof value === 'string' && /^[a-f\d]{24}$/i.test(value)) {
return [new mongoose.Types.ObjectId(value)];
}
if (Array.isArray(value)) {
return value.flatMap(objectIdsFromFilterValue);
}
if (typeof value === 'object') {
if (Array.isArray(value.$in)) {
return objectIdsFromFilterValue(value.$in);
}
if (value._id != null) {
return objectIdsFromFilterValue(value._id);
}
}
return [];
}
const documentTemplateSchema = new Schema(
{
_reference: { type: String, default: () => generateId()() },
name: {
type: String,
required: true,
unique: true,
},
objectType: { type: String, required: false },
tags: [{ type: String }],
active: {
type: Boolean,
required: true,
default: true,
},
global: {
type: Boolean,
required: true,
default: false,
},
parent: {
type: Schema.Types.ObjectId,
ref: 'documentTemplate',
required: false,
},
documentSize: {
type: Schema.Types.ObjectId,
ref: 'documentSize',
required: true,
},
documentPrinters: [
{
type: Schema.Types.ObjectId,
ref: 'documentPrinter',
required: false,
},
],
referencedTemplates: [
{
type: Schema.Types.ObjectId,
ref: 'documentTemplate',
required: false,
},
],
content: {
type: String,
required: false,
default: '<Container></Container>',
},
testObject: {
type: Schema.Types.ObjectId,
refPath: 'objectType',
required: false,
},
},
{ timestamps: true }
);
documentTemplateSchema.index({ name: 'text', tags: 'text', objectType: 'text' });
// Add virtual id getter
documentTemplateSchema.virtual('id').get(function () {
return this._id;
});
// Configure JSON serialization to include virtuals
documentTemplateSchema.set('toJSON', { virtuals: true });
documentTemplateSchema.statics.recalculate = async function (documentTemplate, user) {
const documentTemplateId = documentTemplate?._id || documentTemplate;
if (!documentTemplateId) {
return;
}
const stillExists = await this.exists({ _id: documentTemplateId });
if (!stillExists) {
return;
}
const { getFilter } = await import('../../../utils.js');
const references = extractRenderDocumentTemplateReferences(documentTemplate?.content);
const referencedTemplateIds = [];
const seenIds = new Set();
for (const reference of references) {
const filter = await getFilter({ parent: reference }, ['parent'], true, this);
const ids = objectIdsFromFilterValue(filter.parent);
for (const id of ids) {
const idString = String(id);
if (!idString || seenIds.has(idString)) {
continue;
}
seenIds.add(idString);
referencedTemplateIds.push(id);
}
}
if (documentTemplate && typeof documentTemplate === 'object' && !documentTemplate._bsontype) {
documentTemplate.referencedTemplates = referencedTemplateIds.map((id) => ({
_id: String(id),
}));
}
const { editObject } = await import('../../database.js');
await editObject({
model: this,
id: documentTemplateId,
updateData: { referencedTemplates: referencedTemplateIds },
user,
populate: [{ path: 'referencedTemplates', strictPopulate: false }],
recalculate: false,
});
};
export const documentTemplateModel = mongoose.model('documentTemplate', documentTemplateSchema);