feat: T4 wave 3 - notifications per user, suggestions API, varroa bands, split/queen events
- Schema III: per-user notifications (broadcast fan-out migration, category, link, requiredPermissions filter), notification preferences and settings endpoints, calendar withdrawal switch, occupiedFrames - Suggestions API: list/summary with permission visibility and paging, accept/dismiss/reopen incl. bulk, SuggestionView on all responses - Varroa traffic light by season and method, young colonies, treatment effect window, sample-based percentage; shared withdrawal-window helper on Berlin calendar days; GET /varroa-measurements/thresholds - ColonySplit and QueenAssigned domain events with calendar and webhook handlers - Outbox claims compare against now() rounded to timestamp(3); fixes the flaky e2e claims of rows written with SQL now() Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
d99a697739
commit
f468dc5f75
87 files changed
+6022
-510
No files matched your search
@@ -17,6 +17,7 @@ import { MergeColonyDto } from './dto/merge-colony.dto';
|
||||
import { isLivingColonyStatus } from './colony-status';
|
||||
import { lockRowsForUpdate } from '../prisma/row-lock';
|
||||
import { colonyTransitionEvents, lockColony } from './colony-events';
|
||||
import { berlinToday, dayToDate } from '../common/dates';
|
||||
|
||||
export interface ColonyFilter {
|
||||
status?: ColonyStatus;
|
||||
@@ -194,9 +195,16 @@ export class ColoniesService {
|
||||
dto: SplitColonyDto,
|
||||
actingUserId: string,
|
||||
): Promise<Colony> {
|
||||
const parent = await this.findById(id);
|
||||
this.assertActive(parent);
|
||||
await this.findById(id);
|
||||
const today = berlinToday();
|
||||
const splitOn = dto.date ?? today;
|
||||
if (splitOn > today) {
|
||||
throw new BadRequestException('Das Datum liegt in der Zukunft.');
|
||||
}
|
||||
const queenSource = dto.queenSource ?? null;
|
||||
const child = await this.prisma.$transaction(async (tx) => {
|
||||
const parent = await lockColony(tx, id);
|
||||
this.assertActive(parent);
|
||||
const created = await tx.colony.create({
|
||||
data: {
|
||||
code: dto.code,
|
||||
@@ -205,12 +213,13 @@ export class ColoniesService {
|
||||
notes: dto.notes,
|
||||
},
|
||||
});
|
||||
await tx.colonyLineage.create({
|
||||
const lineage = await tx.colonyLineage.create({
|
||||
data: {
|
||||
type: 'SPLIT',
|
||||
fromColonyId: parent.id,
|
||||
toColonyId: created.id,
|
||||
date: new Date(),
|
||||
date: dayToDate(splitOn),
|
||||
queenSource,
|
||||
notes: dto.notes,
|
||||
},
|
||||
});
|
||||
@@ -224,6 +233,18 @@ export class ColoniesService {
|
||||
},
|
||||
tx,
|
||||
);
|
||||
await this.events.record(tx, {
|
||||
type: 'ColonySplit',
|
||||
aggregateType: 'Colony',
|
||||
aggregateId: created.id,
|
||||
actorUserId: actingUserId,
|
||||
payload: {
|
||||
parentColonyId: parent.id,
|
||||
lineageId: lineage.id,
|
||||
queenSource,
|
||||
splitOn,
|
||||
},
|
||||
});
|
||||
return created;
|
||||
});
|
||||
return child;
|
||||
|
||||
Reference in new issue
Block a user