Skip to content

Commit 1750337

Browse files
authored
add "EXPORT" as engagement_type and add service name (#2572)
* add new column "service" and add "EXPORT" to engagement_type * use engagement_type "EXPORT" & insert service * insert "service" for engagement "ENRICH" & update unittest
1 parent f520d0a commit 1750337

File tree

8 files changed

+89
-27
lines changed

8 files changed

+89
-27
lines changed

backend/src/controllers/contacts.controller.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { User } from '@supabase/supabase-js';
22
import { NextFunction, Request, Response } from 'express';
33
import { Contacts } from '../db/interfaces/Contacts';
4-
import { Contact } from '../db/types';
4+
import { Contact, ExportService } from '../db/types';
55
import Billing from '../utils/billing-plugin';
66
import { ExportOptions, ExportType } from '../services/export/types';
77
import ExportFactory from '../services/export';
@@ -146,13 +146,15 @@ async function verifyCredits(
146146

147147
async function registerAndDeductCredits(
148148
userId: string,
149+
exportType: ExportType,
149150
availableUnits: number,
150151
contacts: Contacts,
151152
availableContacts: Contact[]
152153
) {
153154
if (availableContacts.length) {
154155
await contacts.registerExportedContacts(
155156
availableContacts.map(({ email }) => email),
157+
exportType as unknown as ExportService,
156158
userId
157159
);
158160
await Billing!.deductCustomerCredits(userId, availableUnits);
@@ -181,9 +183,10 @@ async function respondWithConfirmedContacts(
181183

182184
await registerAndDeductCredits(
183185
userId,
186+
exportType,
184187
availableUnits,
185188
contacts,
186-
availableContacts
189+
selectedContacts
187190
);
188191

189192
return res

backend/src/db/interfaces/Contacts.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import { Status } from '../../services/email-status/EmailStatusVerifier';
2-
import { Contact, EmailStatus, ExtractionResult, Tag } from '../types';
2+
import {
3+
Contact,
4+
EmailStatus,
5+
ExportService,
6+
ExtractionResult,
7+
Tag
8+
} from '../types';
39

410
export interface Contacts {
511
create(
@@ -18,5 +24,9 @@ export interface Contacts {
1824
getUnverifiedContacts(userId: string, emails: string[]): Promise<Contact[]>;
1925
getExportedContacts(userId: string, emails?: string[]): Promise<Contact[]>;
2026
getNonExportedContacts(userId: string, emails?: string[]): Promise<Contact[]>;
21-
registerExportedContacts(contactIds: string[], userId: string): Promise<void>;
27+
registerExportedContacts(
28+
contactIds: string[],
29+
exportService: ExportService,
30+
userId: string
31+
): Promise<void>;
2232
}

backend/src/db/pg/PgContacts.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
Contact,
99
EmailExtractionResult,
1010
EmailStatus,
11+
ExportService,
1112
ExtractionResult,
1213
FileExtractionResult,
1314
Tag
@@ -26,7 +27,7 @@ export default class PgContacts implements Contacts {
2627
JOIN private.engagement e
2728
ON e.email = contacts.email
2829
AND e.user_id = $1
29-
AND e.engagement_type = 'CSV'
30+
AND e.engagement_type = 'EXPORT'
3031
`;
3132

3233
private static readonly SELECT_NON_EXPORTED_CONTACTS = `
@@ -35,7 +36,7 @@ export default class PgContacts implements Contacts {
3536
LEFT JOIN private.engagement e
3637
ON e.email = contacts.email
3738
AND e.user_id = $1
38-
AND e.engagement_type = 'CSV'
39+
AND e.engagement_type = 'EXPORT'
3940
WHERE e.email IS NULL;
4041
`;
4142

@@ -51,7 +52,7 @@ export default class PgContacts implements Contacts {
5152
JOIN private.engagement e
5253
ON e.email = contacts.email
5354
AND e.user_id = $1
54-
AND e.engagement_type = 'CSV'
55+
AND e.engagement_type = 'EXPORT'
5556
`;
5657

5758
private static readonly SELECT_NON_EXPORTED_CONTACTS_BY_EMAILS = `
@@ -60,7 +61,7 @@ export default class PgContacts implements Contacts {
6061
LEFT JOIN private.engagement e
6162
ON e.email = contacts.email
6263
AND e.user_id = $1
63-
AND e.engagement_type = 'CSV'
64+
AND e.engagement_type = 'EXPORT'
6465
WHERE e.email IS NULL;
6566
`;
6667

@@ -71,7 +72,7 @@ export default class PgContacts implements Contacts {
7172
WHERE persons.email = update.email AND persons.user_id = %L AND persons.status IS NULL`;
7273

7374
private static readonly INSERT_EXPORTED_CONTACT =
74-
'INSERT INTO private.engagement (user_id, email, engagement_type) VALUES %L ON CONFLICT (email, user_id, engagement_type) DO NOTHING;';
75+
'INSERT INTO private.engagement (user_id, email, engagement_type, service) VALUES %L ON CONFLICT (email, user_id, engagement_type, service) DO NOTHING;';
7576

7677
private static readonly INSERT_MESSAGE_SQL = `
7778
INSERT INTO private.messages("channel","folder_path","date","message_id","references","list_id","conversation","user_id")
@@ -452,10 +453,11 @@ export default class PgContacts implements Contacts {
452453

453454
async registerExportedContacts(
454455
contactIds: string[],
456+
service: ExportService,
455457
userId: string
456458
): Promise<void> {
457459
try {
458-
const values = contactIds.map((id) => [userId, id, 'CSV']);
460+
const values = contactIds.map((id) => [userId, id, 'EXPORT', service]);
459461
await this.pool.query(format(PgContacts.INSERT_EXPORTED_CONTACT, values));
460462
} catch (error) {
461463
this.logger.error(error);

backend/src/db/supabase/engagements.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,19 @@ export default class Engagements {
99
private readonly logger: Logger
1010
) {}
1111

12-
async register(userId: string, emails: string[], type: EngagementType) {
12+
async register(
13+
enriched: {
14+
email: string;
15+
user_id: string;
16+
engagement_type: EngagementType;
17+
service: string;
18+
}[]
19+
) {
1320
try {
14-
const data = emails.map((email) => ({
15-
email,
16-
user_id: userId,
17-
engagement_type: type
18-
}));
1921
const { error } = await this.client
2022
.schema('private')
2123
.from('engagement')
22-
.upsert(data);
24+
.upsert(enriched);
2325
if (error) throw error;
2426
} catch (err) {
2527
const message = (err as Error).message || 'Unexpected error.';

backend/src/db/supabase/enrichments.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -153,18 +153,26 @@ export default class Enrichments {
153153
try {
154154
const task = this.ensureTask();
155155

156-
const enriched = result.map(({ data }) => data).flat();
156+
const enriched = result
157+
.map(({ data, engine }) => ({ data, engine }))
158+
.flat();
157159
task.details.total_enriched += enriched.length;
160+
158161
this.mergeTaskDetailsResult(result);
159162

160163
await this.tasks.update(task);
161164

162165
if (enriched.length) {
163-
await this.updateContacts(enriched);
166+
await this.updateContacts(enriched.map(({ data }) => data).flat());
164167
await this.engagements.register(
165-
task.userId,
166-
enriched.map((contact) => contact.email as string),
167-
'ENRICH'
168+
enriched.flatMap(({ data, engine }) =>
169+
data.map((contact) => ({
170+
email: contact.email as string,
171+
user_id: task.userId,
172+
engagement_type: 'ENRICH',
173+
service: engine
174+
}))
175+
)
168176
);
169177
}
170178
} catch (err) {

backend/src/db/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,3 +190,9 @@ export type Organization = {
190190
founder?: string;
191191
_domain?: string;
192192
};
193+
194+
export enum ExportService {
195+
CSV = 'csv',
196+
VCARD = 'vcard',
197+
GOOGLE_CONTACTS = 'google_contacts'
198+
}

backend/test/unit/database/enrichments.test.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -217,11 +217,14 @@ describe('Enrichments Class', () => {
217217
name: 'hello'
218218
}
219219
]);
220-
expect(mockEngagements.register).toHaveBeenCalledWith(
221-
userId,
222-
['test@example.com'],
223-
'ENRICH'
224-
);
220+
expect(mockEngagements.register).toHaveBeenCalledWith([
221+
{
222+
email: 'test@example.com',
223+
engagement_type: 'ENRICH',
224+
service: 'test',
225+
user_id: 'user-id'
226+
}
227+
]);
225228
expect(task.details.total_enriched).toBe(1);
226229
});
227230
});
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
ALTER TABLE private.engagement DROP CONSTRAINT engagement_pkey;
2+
ALTER TABLE private.engagement ADD COLUMN service TEXT;
3+
4+
UPDATE private.engagement
5+
SET service = CASE
6+
WHEN engagement_type::text = 'ENRICH' THEN 'thedig'
7+
WHEN engagement_type::text = 'CSV' THEN 'csv'
8+
END;
9+
10+
11+
ALTER TYPE private.engagement_type_enum RENAME TO engagement_type_enum_old;
12+
13+
CREATE TYPE private.engagement_type_enum AS ENUM ('EXPORT', 'ENRICH');
14+
15+
ALTER TABLE private.engagement
16+
ALTER COLUMN engagement_type TYPE private.engagement_type_enum
17+
USING (
18+
CASE
19+
WHEN engagement_type::text = 'CSV' THEN 'EXPORT'::private.engagement_type_enum
20+
ELSE engagement_type::text::private.engagement_type_enum
21+
END
22+
);
23+
24+
DROP TYPE private.engagement_type_enum_old;
25+
26+
ALTER TABLE private.engagement ALTER COLUMN service SET NOT NULL;
27+
ALTER TABLE private.engagement
28+
ADD CONSTRAINT engagement_pkey PRIMARY KEY (email, user_id, engagement_type, service);

0 commit comments

Comments
 (0)