name beim kopieren

This commit is contained in:
Bastian Wagner
2026-06-09 16:03:20 +02:00
parent 06c5b1768e
commit 16605c961f
18 changed files with 693 additions and 44 deletions

View File

@@ -3,10 +3,12 @@ import {
ForbiddenException,
Injectable,
NotFoundException,
Optional,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { randomUUID } from 'crypto';
import { Repository } from 'typeorm';
import { AuditLogService } from '../audit/audit-log.service';
import {
ListTemplate,
ListTemplateKind,
@@ -27,6 +29,8 @@ export class ListsService {
private readonly listsRepository: Repository<UserListEntity>,
@InjectRepository(UserListItemEntity)
private readonly listItemsRepository: Repository<UserListItemEntity>,
@Optional()
private readonly auditLogService?: AuditLogService,
) {}
async createList(ownerId: string, createDto: CreateListDto): Promise<UserList> {
@@ -39,7 +43,20 @@ export class ListsService {
items: [],
});
return this.toUserList(await this.listsRepository.save(list));
const savedList = await this.listsRepository.save(list);
await this.auditLogService?.record({
actorUserId: ownerId,
action: 'list.created',
entityType: 'list',
entityId: savedList.id,
metadata: {
name: savedList.name,
kind: savedList.kind,
},
});
return this.toUserList(savedList);
}
async createListFromTemplate(
@@ -75,7 +92,23 @@ export class ListsService {
),
});
return this.toUserList(await this.listsRepository.save(list));
const savedList = await this.listsRepository.save(list);
await this.auditLogService?.record({
actorUserId: ownerId,
action: 'list.created_from_template',
entityType: 'list',
entityId: savedList.id,
metadata: {
name: savedList.name,
kind: savedList.kind,
sourceTemplateId: template.id,
sourceTemplateName: template.name,
itemCount: savedList.items?.length ?? 0,
},
});
return this.toUserList(savedList);
}
async listLists(ownerId: string): Promise<UserList[]> {
@@ -111,13 +144,42 @@ export class ListsService {
list.kind = this.normalizeKind(updateDto.kind);
}
return this.toUserList(await this.listsRepository.save(list));
const savedList = await this.listsRepository.save(list);
await this.auditLogService?.record({
actorUserId: ownerId,
action: 'list.updated',
entityType: 'list',
entityId: savedList.id,
metadata: {
changedFields: Object.keys(updateDto).filter(
(field) => updateDto[field as keyof UpdateListDto] !== undefined,
),
name: savedList.name,
kind: savedList.kind,
},
});
return this.toUserList(savedList);
}
async deleteList(ownerId: string, listId: string): Promise<{ message: string }> {
const list = await this.findOwnedList(ownerId, listId);
const metadata = {
name: list.name,
kind: list.kind,
itemCount: list.items.length,
};
await this.listsRepository.remove(list);
await this.auditLogService?.record({
actorUserId: ownerId,
action: 'list.deleted',
entityType: 'list',
entityId: listId,
metadata,
});
return { message: 'List deleted.' };
}
@@ -134,6 +196,19 @@ export class ListsService {
list.items.push(savedItem);
await this.listsRepository.save(list);
await this.auditLogService?.record({
actorUserId: ownerId,
action: 'list.item_created',
entityType: 'list_item',
entityId: savedItem.id,
metadata: {
listId,
title: savedItem.title,
required: savedItem.required,
position: savedItem.position,
},
});
return this.getList(ownerId, listId);
}
@@ -146,6 +221,7 @@ export class ListsService {
): Promise<UserList> {
const list = await this.findOwnedList(ownerId, listId);
const item = this.findListItem(list, itemId);
const wasChecked = item.checked;
if (updateDto.title !== undefined) {
item.title = this.requireItemTitle(updateDto.title);
@@ -180,6 +256,29 @@ export class ListsService {
await this.listItemsRepository.save(item);
await this.listsRepository.save(list);
await this.auditLogService?.record({
actorUserId: ownerId,
action:
updateDto.checked === true
? 'list.item_checked'
: updateDto.checked === false
? 'list.item_unchecked'
: 'list.item_updated',
entityType: 'list_item',
entityId: item.id,
metadata: {
listId,
title: item.title,
changedFields: Object.keys(updateDto).filter(
(field) => updateDto[field as keyof UpdateListItemDto] !== undefined,
),
previousChecked: wasChecked,
checked: item.checked,
checkedAt: item.checkedAt,
checkedByName: item.checkedByName,
},
});
return this.getList(ownerId, listId);
}
@@ -204,6 +303,18 @@ export class ListsService {
await this.listItemsRepository.save(list.items);
await this.listsRepository.save(list);
await this.auditLogService?.record({
actorUserId: ownerId,
action: 'list.item_deleted',
entityType: 'list_item',
entityId: itemId,
metadata: {
listId,
title: itemToDelete.title,
position: itemToDelete.position,
},
});
return this.getList(ownerId, listId);
}