• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

teableio / teable / 8389034568

22 Mar 2024 10:38AM UTC coverage: 79.934% (+51.7%) from 28.208%
8389034568

Pull #487

github

web-flow
Merge 3045b1f94 into a06c6afb1
Pull Request #487: refactor: move zod schema to openapi

3263 of 3860 branches covered (84.53%)

67 of 70 new or added lines in 23 files covered. (95.71%)

762 existing lines in 27 files now uncovered.

25152 of 31466 relevant lines covered (79.93%)

1188.31 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

69.43
/apps/nestjs-backend/src/features/attachments/attachments-table.service.ts
1
import { Injectable } from '@nestjs/common';
2✔
2
import { FieldType } from '@teable/core';
2✔
3
import type { IAttachmentCellValue, IRecord } from '@teable/core';
2✔
4
import { PrismaService } from '@teable/db-main-prisma';
2✔
5
import type { Prisma } from '@teable/db-main-prisma';
2✔
6
import type { IChangeRecord } from '../../event-emitter/events';
2✔
7

2✔
8
@Injectable()
2✔
9
export class AttachmentsTableService {
2✔
10
  constructor(private readonly prismaService: PrismaService) {}
64✔
11

64✔
12
  private createUniqueKey(
64✔
13
    tableId: string,
4✔
14
    fieldId: string,
4✔
15
    recordId: string,
4✔
16
    attachmentId: string
4✔
17
  ) {
4✔
18
    return `${tableId}-${fieldId}-${recordId}-${attachmentId}`;
4✔
19
  }
4✔
20

64✔
21
  private async getAttachmentFields(tableId: string) {
64✔
22
    return await this.prismaService.txClient().field.findMany({
2,231✔
23
      where: { tableId, type: FieldType.Attachment, isLookup: null, deletedTime: null },
2,231✔
24
      select: { id: true },
2,231✔
25
    });
2,231✔
26
  }
2,231✔
27

64✔
28
  async createRecords(userId: string, tableId: string, records: IRecord[]) {
64✔
29
    const fieldRaws = await this.getAttachmentFields(tableId);
1,063✔
30
    const newAttachments: Prisma.AttachmentsTableCreateInput[] = [];
1,063✔
31
    records.forEach((record) => {
1,063✔
32
      const { id: recordId, fields } = record;
3,681✔
33
      fieldRaws.forEach(({ id }) => {
3,681✔
34
        const attachments = fields[id] as IAttachmentCellValue;
24✔
35
        attachments?.forEach((attachment) => {
24!
UNCOV
36
          newAttachments.push({
×
UNCOV
37
            tableId,
×
UNCOV
38
            recordId,
×
UNCOV
39
            name: attachment.name,
×
UNCOV
40
            fieldId: id,
×
UNCOV
41
            token: attachment.token,
×
UNCOV
42
            attachmentId: attachment.id,
×
UNCOV
43
            createdBy: userId,
×
UNCOV
44
          });
×
UNCOV
45
        });
×
46
      });
24✔
47
    });
3,681✔
48
    await this.prismaService.$tx(async (prisma) => {
1,063✔
49
      for (let i = 0; i < newAttachments.length; i++) {
1,063!
UNCOV
50
        await prisma.attachmentsTable.create({ data: newAttachments[i] });
×
UNCOV
51
      }
×
52
    });
1,063✔
53
  }
1,063✔
54

64✔
55
  async updateRecords(userId: string, tableId: string, records: IChangeRecord[]) {
64✔
56
    const fieldRaws = await this.getAttachmentFields(tableId);
1,168✔
57
    const newAttachments: Prisma.AttachmentsTableCreateInput[] = [];
1,168✔
58
    const needDelete: {
1,168✔
59
      tableId: string;
1,168✔
60
      fieldId: string;
1,168✔
61
      recordId: string;
1,168✔
62
      attachmentId: string;
1,168✔
63
    }[] = [];
1,168✔
64
    records.forEach((record) => {
1,168✔
65
      const { id: recordId, fields } = record;
46,264✔
66
      fieldRaws.forEach(({ id: fieldId }) => {
46,264✔
67
        const { newValue, oldValue } = fields[fieldId] || {};
498✔
68
        const newAttachmentsValue = newValue as IAttachmentCellValue;
498✔
69
        const newAttachmentsMap = new Map<string, boolean>();
498✔
70
        const oldAttachmentsValue = oldValue as IAttachmentCellValue;
498✔
71
        const oldAttachmentsMap = new Map<string, boolean>();
498✔
72
        newAttachmentsValue?.forEach((attachment) => {
498✔
73
          newAttachmentsMap.set(
2✔
74
            this.createUniqueKey(tableId, fieldId, recordId, attachment.id),
2✔
75
            true
2✔
76
          );
2✔
77
        });
2✔
78
        oldAttachmentsValue?.forEach((attachment) => {
498✔
UNCOV
79
          oldAttachmentsMap.set(
×
UNCOV
80
            this.createUniqueKey(tableId, fieldId, recordId, attachment.id),
×
UNCOV
81
            true
×
UNCOV
82
          );
×
UNCOV
83
        });
×
84
        oldAttachmentsValue?.forEach((attachment) => {
498!
UNCOV
85
          const uniqueKey = this.createUniqueKey(tableId, fieldId, recordId, attachment.id);
×
UNCOV
86
          if (newAttachmentsMap.has(uniqueKey)) {
×
87
            return;
×
88
          }
×
UNCOV
89
          needDelete.push({
×
UNCOV
90
            tableId,
×
UNCOV
91
            fieldId,
×
UNCOV
92
            recordId,
×
UNCOV
93
            attachmentId: attachment.id,
×
UNCOV
94
          });
×
UNCOV
95
        });
×
96
        newAttachmentsValue?.forEach((attachment) => {
498✔
97
          const uniqueKey = this.createUniqueKey(tableId, fieldId, recordId, attachment.id);
2✔
98
          if (oldAttachmentsMap.has(uniqueKey)) {
2!
99
            return;
×
100
          } else {
2✔
101
            newAttachments.push({
2✔
102
              tableId,
2✔
103
              recordId,
2✔
104
              name: attachment.name,
2✔
105
              fieldId,
2✔
106
              token: attachment.token,
2✔
107
              attachmentId: attachment.id,
2✔
108
              createdBy: userId,
2✔
109
            });
2✔
110
          }
2✔
111
        });
2✔
112
      });
498✔
113
    });
46,264✔
114

1,168✔
115
    await this.prismaService.$tx(async (prisma) => {
1,168✔
116
      needDelete.length && (await this.delete(needDelete));
1,164✔
117
      for (let i = 0; i < newAttachments.length; i++) {
428✔
118
        await prisma.attachmentsTable.create({ data: newAttachments[i] });
2✔
119
      }
2✔
120
    });
1,164✔
121
  }
1,164✔
122

64✔
123
  async delete(
64✔
UNCOV
124
    query: {
×
UNCOV
125
      tableId: string;
×
UNCOV
126
      recordId: string;
×
UNCOV
127
      fieldId: string;
×
UNCOV
128
      attachmentId?: string;
×
UNCOV
129
    }[]
×
UNCOV
130
  ) {
×
UNCOV
131
    if (!query.length) {
×
132
      return;
×
133
    }
×
UNCOV
134

×
UNCOV
135
    await this.prismaService.txClient().attachmentsTable.deleteMany({
×
UNCOV
136
      where: { OR: query },
×
UNCOV
137
    });
×
UNCOV
138
  }
×
139

64✔
140
  async deleteRecords(tableId: string, recordIds: string[]) {
64✔
141
    await this.prismaService.txClient().attachmentsTable.deleteMany({
20✔
142
      where: { tableId, recordId: { in: recordIds } },
20✔
143
    });
20✔
144
  }
20✔
145

64✔
146
  async deleteFields(tableId: string, fieldIds: string[]) {
64✔
147
    await this.prismaService.txClient().attachmentsTable.deleteMany({
56✔
148
      where: { tableId, fieldId: { in: fieldIds } },
56✔
149
    });
56✔
150
  }
56✔
151

64✔
152
  async deleteTable(tableId: string) {
64✔
UNCOV
153
    await this.prismaService.txClient().attachmentsTable.deleteMany({
×
UNCOV
154
      where: { tableId },
×
UNCOV
155
    });
×
UNCOV
156
  }
×
157
}
64✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc