Files
edr-platform/apps/edr-freight-api/src/modules/files/files.repository.ts

107 lines
3.2 KiB
TypeScript

import { BaseRepository } from "@edr/api-common";
import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { In, Repository } from "typeorm";
import { FileRecord } from "./entities/file.entity";
@Injectable()
export class FilesRepository extends BaseRepository<FileRecord> {
constructor(
@InjectRepository(FileRecord)
repository: Repository<FileRecord>,
) {
super(repository);
}
findByResource(resourceId: string, resource: string): Promise<FileRecord[]> {
return this.repository.find({ where: { resourceId, resource } });
}
/**
* Batch sibling of {@link findByResource} for hydrating a page of resources at
* once (a thread of chat messages, say) instead of one query per row.
*/
async findByResourceIds(
resourceIds: string[],
resource: string,
): Promise<FileRecord[]> {
if (resourceIds.length === 0) return [];
return this.repository.find({
where: { resourceId: In(resourceIds), resource },
order: { createdAt: "ASC" },
});
}
findByCode(
resourceId: string,
resource: string,
code: string,
): Promise<FileRecord | null> {
return this.repository.findOne({ where: { resourceId, resource, code } });
}
/**
* Retire the live version(s) of a document code. SOFT delete on purpose: the
* bytes and the row stay so the original upload can still be read back from
* the version history after staff replace it. Every normal read already
* filters soft-deleted rows, so callers see only the current version.
*
* `replacedBy` / `reason` are stamped on the retired row when a newer file is
* taking its place (as opposed to a plain removal).
*/
async deleteByCode(
resourceId: string,
resource: string,
code: string,
replacedBy?: { userId?: string | null; reason?: string | null },
): Promise<void> {
if (replacedBy) {
await this.repository.update(
{ resourceId, resource, code },
{
replacedByUserId: replacedBy.userId ?? null,
replaceReason: replacedBy.reason ?? null,
},
);
}
await this.repository.softDelete({ resourceId, resource, code });
}
/**
* Every version of one document code, newest first — superseded versions
* included. The only read that deliberately looks past the soft-delete filter.
*/
findVersionHistory(
resourceId: string,
resource: string,
code: string,
): Promise<FileRecord[]> {
return this.repository.find({
where: { resourceId, resource, code },
withDeleted: true,
order: { createdAt: "DESC" },
});
}
/**
* Documents belonging to any of the given resources that a reviewer has asked
* the customer to correct. Used by the approval gate, so it takes a list of
* resource ids (a company plus each of its company profiles) in one query.
*/
async findWithOpenChangeRequest(
resourceIds: string[],
resource: string,
): Promise<FileRecord[]> {
if (resourceIds.length === 0) return [];
return this.repository.find({
where: {
resourceId: In(resourceIds),
resource,
reviewStatus: "change_requested",
},
order: { createdAt: "ASC" },
});
}
}