mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 21:01:08 +02:00
fix(contacts): clean up orphaned photos on duplicate merge
DuplicatesService.mergeContacts() now deletes S3 photos of merged contacts before removing them from the DB. Photos that were adopted by the primary contact (via mergeContactData) are preserved. - Import PhotoModule in DuplicatesModule - Inject PhotoService into DuplicatesService - Add photo cleanup loop before DB deletion - Update test mock Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
3ac976f600
commit
b38e5aecf9
3 changed files with 19 additions and 2 deletions
|
|
@ -1,6 +1,7 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { NotFoundException } from '@nestjs/common';
|
||||
import { DuplicatesService } from '../duplicates.service';
|
||||
import { PhotoService } from '../../photo/photo.service';
|
||||
import { DATABASE_CONNECTION } from '../../db/database.module';
|
||||
|
||||
describe('DuplicatesService', () => {
|
||||
|
|
@ -110,6 +111,10 @@ describe('DuplicatesService', () => {
|
|||
provide: DATABASE_CONNECTION,
|
||||
useValue: mockDb,
|
||||
},
|
||||
{
|
||||
provide: PhotoService,
|
||||
useValue: { deletePhotoByUrl: jest.fn() },
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@ import { Module } from '@nestjs/common';
|
|||
import { DuplicatesController } from './duplicates.controller';
|
||||
import { DuplicatesService } from './duplicates.service';
|
||||
import { DatabaseModule } from '../db/database.module';
|
||||
import { PhotoModule } from '../photo/photo.module';
|
||||
|
||||
@Module({
|
||||
imports: [DatabaseModule],
|
||||
imports: [DatabaseModule, PhotoModule],
|
||||
controllers: [DuplicatesController],
|
||||
providers: [DuplicatesService],
|
||||
exports: [DuplicatesService],
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { DATABASE_CONNECTION } from '../db/database.module';
|
|||
import { Database } from '../db/connection';
|
||||
import { contacts } from '../db/schema';
|
||||
import type { Contact } from '../db/schema';
|
||||
import { PhotoService } from '../photo/photo.service';
|
||||
|
||||
export interface DuplicateGroup {
|
||||
id: string;
|
||||
|
|
@ -19,7 +20,10 @@ export interface MergeResult {
|
|||
|
||||
@Injectable()
|
||||
export class DuplicatesService {
|
||||
constructor(@Inject(DATABASE_CONNECTION) private db: Database) {}
|
||||
constructor(
|
||||
@Inject(DATABASE_CONNECTION) private db: Database,
|
||||
private readonly photoService: PhotoService
|
||||
) {}
|
||||
|
||||
/** Maximum number of duplicate groups to return per match type */
|
||||
private static readonly MAX_GROUPS_PER_TYPE = 50;
|
||||
|
|
@ -322,6 +326,13 @@ export class DuplicatesService {
|
|||
.where(eq(contacts.id, primaryId))
|
||||
.returning();
|
||||
|
||||
// Clean up photos of merged contacts (skip if photo was adopted by primary)
|
||||
for (const mergedContact of contactsToMerge) {
|
||||
if (mergedContact.photoUrl && mergedContact.photoUrl !== updatedContact.photoUrl) {
|
||||
await this.photoService.deletePhotoByUrl(mergedContact.photoUrl);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete merged contacts
|
||||
await this.db
|
||||
.delete(contacts)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue