- Rule configs with typed parsers and registry; Berlin day helpers - Schema: T4 enums, Suggestion table, feed vocabulary (feedStatus as ColonyCondition with legacy text mapping), split queen source, varroa sample size; migration harness for data migrations - SuggestionsService: propose/refresh/resolve/obsolete/expire, accept/dismiss/reopen incl. bulk, lock order, concurrency e2e - SeasonService: phenology-based segments, inspection/varroa due dates, queen age; TimeEventsStep with JobPartialFailure - Frontend: per-rule settings forms with visible value sources Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
73 lines
3.0 KiB
TypeScript
73 lines
3.0 KiB
TypeScript
import type { AutomationTriggerType } from '../../../generated/prisma';
|
|
import { RULE_CONFIG_PARSERS } from './rule-config.registry';
|
|
|
|
export interface RuleDefaults {
|
|
config: Record<string, unknown>;
|
|
actionTemplate: string;
|
|
/** Rules without a sensible built-in setting start switched off. */
|
|
active?: boolean;
|
|
}
|
|
|
|
/** Texts of the rules that create a task; the new rules have none yet. */
|
|
const ACTION_TEMPLATES: Record<AutomationTriggerType, string> = {
|
|
QUEENLESS_NO_EGGS:
|
|
'Kontrolle empfohlen: Königin nicht gesehen und keine Stifte vorhanden.',
|
|
VARROA_THRESHOLD: 'Behandlung prüfen: Varroa-Schwellenwert überschritten.',
|
|
FEED_STATUS_CRITICAL: 'Fütterung erforderlich: Futterstatus kritisch.',
|
|
SWARM_MOOD_HIGH:
|
|
'Schwarmkontrolle dringend: hohe Schwarmstimmung festgestellt.',
|
|
COLONY_HEALTH_CRITICAL: 'Kontrolle erforderlich: Gesundheitsstatus kritisch.',
|
|
STOCK_ITEM_LOW: 'Nachbestellung prüfen: Lagerartikel unter Mindestbestand.',
|
|
// Not task-generating rules like the ones above - `active` here toggles
|
|
// whether HoneyBatchesService/BottlingService auto-fill the batch/lot
|
|
// number from `config.format` instead of requiring manual entry.
|
|
HONEY_BATCH_NUMBER_FORMAT: '',
|
|
BOTTLING_LOT_NUMBER_FORMAT: '',
|
|
RAW_MATERIAL_LOT_NUMBER_FORMAT: '',
|
|
PRODUCTION_BATCH_NUMBER_FORMAT: '',
|
|
RAW_MATERIAL_LOW: 'Rohstoff unter Mindestmenge: Nachschub einplanen.',
|
|
TREATMENT_FOLLOW_UP: 'Behandlungserfolg kontrollieren',
|
|
FEEDING_FOLLOW_UP: 'Futterabnahme und Futtervorrat kontrollieren',
|
|
INSPECTION_INTERVAL: '',
|
|
QUEEN_CELLS_SWARM_CHECK: '',
|
|
QUEEN_ACCEPTANCE_CHECK: '',
|
|
SPLIT_SCHEDULE: '',
|
|
COLONY_ENDED_CLEANUP: '',
|
|
WITHDRAWAL_ENDED: '',
|
|
HONEY_WATER_CONTENT: '',
|
|
SEASON_AUTOPILOT: '',
|
|
PHENOLOGY: '',
|
|
};
|
|
|
|
// - RAW_MATERIAL_LOW: raw material lots carry no minimum of their own, so
|
|
// the minimum per kind (config.minGrams) lives on the rule - and without
|
|
// one there is nothing to compare, hence off by default.
|
|
// - Follow-up checks: how many days after a treatment or feeding a check
|
|
// makes sense depends on the product and the season, so there is no
|
|
// built-in interval - the beekeeper switches the rule on and sets
|
|
// config.dueInDays.
|
|
const INACTIVE_BY_DEFAULT: ReadonlySet<AutomationTriggerType> = new Set([
|
|
'RAW_MATERIAL_LOW',
|
|
'TREATMENT_FOLLOW_UP',
|
|
'FEEDING_FOLLOW_UP',
|
|
]);
|
|
|
|
function defaultsOf(trigger: AutomationTriggerType): RuleDefaults {
|
|
return {
|
|
config: structuredClone(RULE_CONFIG_PARSERS[trigger].defaults) as Record<
|
|
string,
|
|
unknown
|
|
>,
|
|
actionTemplate: ACTION_TEMPLATES[trigger],
|
|
...(INACTIVE_BY_DEFAULT.has(trigger) ? { active: false } : {}),
|
|
};
|
|
}
|
|
|
|
/** The rule rows created on first use; the config is the parser's default. */
|
|
export const DEFAULT_RULES: Record<AutomationTriggerType, RuleDefaults> =
|
|
Object.fromEntries(
|
|
(Object.keys(ACTION_TEMPLATES) as AutomationTriggerType[]).map(
|
|
(trigger) => [trigger, defaultsOf(trigger)],
|
|
),
|
|
) as Record<AutomationTriggerType, RuleDefaults>;
|