Skip to content

Commit

Permalink
Merge pull request #88 from nossas/feature/context-autofire
Browse files Browse the repository at this point in the history
Vizualização de indicadores de entrega desse e-mail no BONDE
  • Loading branch information
sergiomario authored Jul 2, 2024
2 parents 4d87b16 + c04237f commit 7fdaf99
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 13 deletions.
16 changes: 14 additions & 2 deletions packages/activists-api/src/resolvers/action/next.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,13 @@ describe('next proccess on BaseAction mailchimp tests', () => {
email_from: `${opts.widget.settings.sender_name} <${opts.widget.settings.sender_email}>`,
email_to: `${opts.activist.name} <${opts.activist.email}>`,
subject: opts.widget.settings.email_subject,
body: opts.widget.settings.email_text
body: opts.widget.settings.email_text,
context: {
autofire: true,
widget_id: opts.widget.id,
mobilization_id: opts.widget.block.mobilization.id,
community_id: opts.widget.block.mobilization.community.id
}
})
});
});
Expand All @@ -139,7 +145,13 @@ describe('next proccess on BaseAction mailchimp tests', () => {
email_from: opts.widget.block.mobilization.community.email_template_from,
email_to: `${opts.activist.name} <${opts.activist.email}>`,
subject: opts.widget.settings.email_subject,
body: opts.widget.settings.email_text
body: opts.widget.settings.email_text,
context: {
autofire: true,
widget_id: opts.widget.id,
mobilization_id: opts.widget.block.mobilization.id,
community_id: opts.widget.block.mobilization.community.id
}
})
});
});
Expand Down
12 changes: 10 additions & 2 deletions packages/activists-api/src/resolvers/action/next.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,22 @@ export default async <T>({ activist, widget }: IBaseAction<T>, done?: DoneAction
}

// Post-action
// Configurar contexto para categorizar mensagens no sendgrid
const context = {
widget_id:widget.id,
mobilization_id:widget.block.mobilization.id,
community_id:community.id,
autofire:true
}
const { email_subject, sender_email, sender_name, email_text } = widget.settings;

// TODO: Required fields to Notify "Pós-Ação"
const notifyOpts: any = {
email_from: community.email_template_from,
email_to: `${activist.name} <${activist.email}>`,
subject: email_subject,
body: email_text
body: email_text,
context
};

// TODO: Thing a better place to move this code
Expand All @@ -44,7 +52,7 @@ export default async <T>({ activist, widget }: IBaseAction<T>, done?: DoneAction

await NotificationsAPI.send(notifyOpts);

logger.child({ activist, widget }).info('action is done');
logger.child({ activist, widget, notifyOpts }).info('action is done');
};

// 0. trazer a função de processar pdf e inserir plip para remote schema
Expand Down
33 changes: 25 additions & 8 deletions packages/notifications/src/core/mail.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import logger, { apmAgent } from '../logger';
import nunjucks from 'nunjucks';

export interface MailSettings {
Expand Down Expand Up @@ -73,16 +74,32 @@ class Mail {
}

let categories: string[] = [];
if (context?.widget_id) {
categories = [...categories, `w${context?.widget_id}`]
}
if (context?.mobilization_id) {
categories = [...categories, `m${context?.mobilization_id}`]
}
if (context?.community_id) {
categories = [...categories, `c${context?.community_id}`]

if (!context.autofire) {
if (context?.widget_id) {
categories = [...categories, `w${context?.widget_id}`]
}
if (context?.mobilization_id) {
categories = [...categories, `m${context?.mobilization_id}`]
}
if (context?.community_id) {
categories = [...categories, `c${context?.community_id}`]
}
} else {
categories = [...categories, 'autofire']
if (context?.widget_id) {
categories = [...categories, `autofire-w${context?.widget_id}`]
}
if (context?.mobilization_id) {
categories = [...categories, `autofire-m${context?.mobilization_id}`]
}
if (context?.community_id) {
categories = [...categories, `autofire-c${context?.community_id}`]
}
}

logger.child({ categories }).info("Categorized Sendgrid Message");

return {
...message,
categories
Expand Down
96 changes: 96 additions & 0 deletions packages/notifications/src/graphql-api/resolvers/email_stats.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import logger, { apmAgent } from "../../logger";
import { client } from "../../core/elasticsearchdb";

interface EmailEvent {
email: string;
event: string;
timestamp: number;
sg_event_id: string;
sg_message_id: string;
useragent: string;
ip: string;
url: string;
}

interface EmailStatsResponse {
events: EmailEvent[];
stats: {
open: number;
delivered: number;
bounced: number;
processed: number;
click: number;
total: number;
};
}

interface EmailStatsArgs {
widget_id: number;
category?: string;
}


export default async (_: void, args: EmailStatsArgs): Promise<EmailStatsResponse> => {
const { widget_id, category } = args;
let categories: string[] = [];

if (category) {
categories.push(`${category}-w${widget_id}`);
} else {
categories.push(`w${widget_id}`);
}
const query = {
bool: {
must: [
{
terms: {
"category.keyword": categories
}
},
{
bool: {
should: [
{ match: { event: "delivered" } },
{ match: { event: "bounced" } },
{ match: { event: "processed" } },
{ match: { event: "click" } },
{ match: { event: "open" } }
]
}
}
]
}
};

try {
const { body } = await client.search({
index: "events-sendgrid-*",
body: { query: query }
});

const events = body.hits.hits.map((hit: any) => ({
email: hit._source.email,
event: hit._source.event,
timestamp: hit._source.timestamp,
sg_event_id: hit._source.sg_event_id,
sg_message_id: hit._source.sg_message_id,
useragent: hit._source.useragent,
ip: hit._source.ip,
url: hit._source.url,
}));

const stats = {
open: events.filter(event => event.event === "open").length,
delivered: events.filter(event => event.event === "delivered").length,
bounced: events.filter(event => event.event === "bounced").length,
processed: events.filter(event => event.event === "processed").length,
click: events.filter(event => event.event === "click").length,
total: events.length
};

return { events, stats };
} catch (error) {
logger.error(`Failed to fetch email stats`);
throw new Error(`Failed to fetch email stats`);
}
};
4 changes: 3 additions & 1 deletion packages/notifications/src/graphql-api/resolvers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import notify from './notify';
import activity_feed from "./activity_feed";
import activity_feed_total from './activity_feed_total';
import activity_feed_timestamp from "./activity_feed_timestamp";
import email_stats from './email_stats';

const resolverMap = {
Query: {
activity_feed,
activity_feed_total,
activity_feed_timestamp
activity_feed_timestamp,
email_stats
},
Mutation: {
notify
Expand Down
27 changes: 27 additions & 0 deletions packages/notifications/src/graphql-api/schema/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,37 @@ type ActivityFeedTimestampResponse {
max_timestamp: Int
}

type EmailEvent {
email: String
event: String
timestamp: Int
sg_event_id: String
sg_message_id: String
useragent: String
ip: String
url: String
}

type EmailStats {
open: Int
delivered: Int
bounced: Int
processed: Int
click: Int
total: Int
}

type EmailStatsResponse {
events: [EmailEvent]
stats: EmailStats
}

type Query {
activity_feed(filter: ActivityFeedFilter): ActivityFeedResponse
activity_feed_total(widget_id: Int!): ActivityFeedTotalResponse
activity_feed_timestamp: ActivityFeedTimestampResponse

email_stats(widget_id: Int!, category: String): EmailStatsResponse
}

type Mutation {
Expand Down

0 comments on commit 7fdaf99

Please sign in to comment.