/** * TEMPLATE — custom fields declared in code (@suppa/sdk 1.38.0 or newer). * * Copy into the OWNER's entity file, or beside it. Replace `Tasks`/`category` * and the columns; keep the shape. Every line that departs from the shape is a * rule the gate blocks on — the code is in the comment. * * Doc: migrations.html#custom-fields, transcribed in references/custom-fields.md. */ import { Column, CustomFields, Entity, FieldTypeEnum, SystemBaseEntity, } from '@suppa/sdk'; /** * The nested class: a PLAIN class of columns. * * - no @Entity(), does not extend SystemBaseEntity, NEVER passed to * EntityModule.forFeature() (E124 — registering it makes the platform build * a plain table where the generated extension table belongs, breaking every * custom-field read and write) * - named after the owner by convention only: the TABLE is always * `{Owner}CustomFields`, whatever this class is called * - one class serves one owner (E130) * * Inside it the extension-mode restrictions apply: no `primary`, no * @OneToMany()/@ManyToManyBackRef() (E126); `nullable: false` needs a `default` * (E127). Every other house rule still binds — relation typing, no option at * its default, local enums unnamed, stubs for existing targets. */ export class TasksCustomFields { /** * One property = one custom field. EVERY column needs options.customFieldSets, * or it exists in the metadata and shows on no record (W621). A set binds the * owner to ONE context value; several entries = several contexts. * * contextField — a field ON THE OWNER (W622) * contextValue — a business key, never an id (W625): the value itself for a * text/number/boolean field, the STORED enum value for an * @Enum, an import key or representative value for a relation * required — default false; readOnly / defaultValue — default null * (defer to the field) */ @Column({ type: FieldTypeEnum.Numeric, nullable: true, title: { en: 'Budget', uk: 'Бюджет' }, options: { customFieldSets: [ { contextField: 'category', contextValue: 'design', required: true }, { contextField: 'category', contextValue: 'support' }, ], }, }) cfBudget?: number; @Column({ type: FieldTypeEnum.Text, nullable: true, title: { en: 'Client reference', uk: 'Референс клієнта' }, options: { customFieldSets: [{ contextField: 'category', contextValue: 'support' }], }, }) cfClientRef?: string; } @Entity({ name: 'Tasks', key: 'Tasks', importKeyFields: ['shortUID'] }) export class Tasks extends SystemBaseEntity { @Column({ name: 'shortUID', type: FieldTypeEnum.Text, nullable: false }) shortUID: string; @Column({ name: 'title', type: FieldTypeEnum.Text, nullable: false }) title: string; /** The context field the sets above key on. */ @Column({ name: 'category', type: FieldTypeEnum.Text }) category?: string; /** * The property MUST be named `customFields` (E125). The decorator implies * `options: { customFields: true }` — do not write the option beside it (W623). * On an entity you do NOT own, the columns still come from this file, but the * option has to be switched on once: suppa_update_entity_options(entity_name, * '{"customFields": true}'). */ @CustomFields(() => TasksCustomFields) customFields?: TasksCustomFields; } // Register ONLY the owner: // EntityModule.forFeature([Tasks], { seeds: [] })