Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,15 @@ coverage
.DS_Store
globalConfig.json
*.log
*.js
!jest.config.js
!jest.global-teardown.js
!jest.setup.js
!jest.setup.mongo-repl-set.js
!jest.setup.redis-mock.js
!jest-mongodb-config.js
!migrate-mongo-config.js
!/env.js
!convertors/**/*.js
!tools/**/*.js
!bin/**/*.js
29 changes: 29 additions & 0 deletions lib/utils/decl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* Decl of number
*
* @param value - value to decl
* @param titles - titles to decl: ['новое событие', 'новых события', 'новых событий']
* @example declOfNum(1, ['новое событие', 'новых события', 'новых событий']) -> 'новое событие'
* @example declOfNum(2, ['новое событие', 'новых события', 'новых событий']) -> 'новых события'
* @example declOfNum(10, ['новое событие', 'новых события', 'новых событий']) -> 'новых событий'
* @example declOfNum(21, ['новое событие', 'новых события', 'новых событий']) -> 'новое событие'
* @returns decl of number
*/
export function declOfNum(value: number, titles: string[]): string {
const decimalBase = 10;
const hundredBase = 100;
const minExclusiveTeens = 4;
const maxExclusiveTeens = 20;
const manyFormIndex = 2;
const maxCaseIndex = 5;
const declCases = [manyFormIndex, 0, 1, 1, 1, manyFormIndex];

const valueModHundred = value % hundredBase;
const valueModTen = value % decimalBase;
const isTeens = valueModHundred > minExclusiveTeens && valueModHundred < maxExclusiveTeens;
const caseIndex = isTeens
? manyFormIndex
: declCases[valueModTen < maxCaseIndex ? valueModTen : maxCaseIndex];

return titles[caseIndex];
}
52 changes: 52 additions & 0 deletions lib/utils/payday.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { HOURS_IN_DAY, MINUTES_IN_HOUR, SECONDS_IN_MINUTE, MS_IN_SEC } from './consts';

/**
* Milliseconds in day. Needs for calculating difference between dates in days.
*/
const MILLISECONDS_IN_DAY = HOURS_IN_DAY * MINUTES_IN_HOUR * SECONDS_IN_MINUTE * MS_IN_SEC;

/**
* Returns difference between now and payday in days
*
* Pay day is calculated by formula: paidUntil date or last charge date + 1 month
*
* @param date - last charge date
* @param paidUntil - paid until date
* @param isDebug - flag for debug purposes
*/
export function daysBeforePayday(date: Date, paidUntil: Date = null, isDebug = false): number {
const expectedPayDay = paidUntil ? new Date(paidUntil) : new Date(date);

if (isDebug) {
expectedPayDay.setDate(date.getDate() + 1);
} else if (!paidUntil) {
expectedPayDay.setMonth(date.getMonth() + 1);
}

const now = new Date().getTime();

return Math.floor((expectedPayDay.getTime() - now) / MILLISECONDS_IN_DAY);
}

/**
* Returns difference between payday and now in days
*
* Pay day is calculated by formula: paidUntil date or last charge date + 1 month
*
* @param date - last charge date
* @param paidUntil - paid until date
* @param isDebug - flag for debug purposes
*/
export function daysAfterPayday(date: Date, paidUntil: Date = null, isDebug = false): number {
const expectedPayDay = paidUntil ? new Date(paidUntil) : new Date(date);

if (isDebug) {
expectedPayDay.setDate(date.getDate() + 1);
} else if (!paidUntil) {
expectedPayDay.setMonth(date.getMonth() + 1);
}

const now = new Date().getTime();

return Math.floor((now - expectedPayDay.getTime()) / MILLISECONDS_IN_DAY);
}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"test:javascript": "jest workers/javascript",
"test:release": "jest workers/release",
"test:slack": "jest workers/slack",
"test:loop": "jest workers/loop",
"test:limiter": "jest workers/limiter --runInBand",
"test:grouper": "jest workers/grouper",
"test:diff": "jest ./workers/grouper/tests/diff.test.ts",
Expand All @@ -37,6 +38,7 @@
"run-sentry": "yarn worker hawk-worker-sentry",
"run-js": "yarn worker hawk-worker-javascript",
"run-slack": "yarn worker hawk-worker-slack",
"run-loop": "yarn worker hawk-worker-loop",
"run-grouper": "yarn worker hawk-worker-grouper",
"run-archiver": "yarn worker hawk-worker-archiver",
"run-accountant": "yarn worker hawk-worker-accountant",
Expand Down
23 changes: 22 additions & 1 deletion workers/email/scripts/emailOverview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { ObjectId } from 'mongodb';
import * as path from 'path';
import * as dotenv from 'dotenv';
import { HttpStatusCode } from '../../../lib/utils/consts';
import { daysAfterPayday } from '../../../lib/utils/payday';

/**
* Merge email worker .env and root workers .env
Expand Down Expand Up @@ -147,6 +148,7 @@ class EmailTestServer {
user,
period: 10,
reason: 'error on the payment server side',
daysAfterPayday: await this.calculateDaysAfterPayday(workspace),
};

try {
Expand Down Expand Up @@ -210,7 +212,7 @@ class EmailTestServer {
*/
private sendHTML(html: string, response: http.ServerResponse): void {
response.writeHead(HttpStatusCode.Ok, {
'Content-Type': 'text/html',
'Content-Type': 'text/html; charset=utf-8',
});
response.write(html);
response.end();
Expand Down Expand Up @@ -323,6 +325,25 @@ class EmailTestServer {
return connection.collection('workspaces').findOne({ _id: new ObjectId(workspaceId) });
}

/**
* Calculate days after payday
* Return number of days after payday. If payday is in the future, return 0
*
* @param workspace - workspace data
* @returns {Promise<number>} number of days after payday
*/
private async calculateDaysAfterPayday(
workspace: WorkspaceDBScheme
): Promise<number> {
if (!workspace.lastChargeDate) {
return 0;
}

const days = daysAfterPayday(workspace.lastChargeDate, workspace.paidUntil);

return days > 0 ? days : 0;
}

/**
* Get user info
*
Expand Down
1 change: 1 addition & 0 deletions workers/email/src/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export default class EmailProvider extends NotificationsProvider {
switch (notification.type) {
case 'assignee': templateName = Templates.Assignee; break;
case 'block-workspace': templateName = Templates.BlockWorkspace; break;
case 'blocked-workspace-reminder': templateName = Templates.BlockedWorkspaceReminder; break;
case 'days-limit-almost-reached': templateName = Templates.DaysLimitAlmostReached; break;
case 'event': templateName = Templates.Event; break;
case 'events-limit-almost-reached': templateName = Templates.EventsLimitAlmostReached; break;
Expand Down
6 changes: 3 additions & 3 deletions workers/email/src/templates/components/layout.twig
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@
style="text-decoration: none; border-bottom: 1px solid #494F5E;">
<font color="#969FB3"
style="font-size: 13px; line-height: 1.46; letter-spacing: 0.16px; color: #969FB3;">
Unsubscribe
Отписаться
</font>
</a>
</td>
Expand All @@ -143,7 +143,7 @@
<a href="{{ host }}" style="text-decoration: none;">
<font color="#969FB3"
style="font-size: 13px; line-height: 1.46; letter-spacing: 0.16px; color: #969FB3;">
Hawk
Хоук
</font>
</a>
</td>
Expand All @@ -152,7 +152,7 @@
<td style="text-align: center">
<font color="#969FB3"
style="font-size: 13px; line-height: 1.46; letter-spacing: 0.16px; color: #969FB3;">
Errors tracking system
Российский трекер ошибок
</font>
</td>
</tr>
Expand Down
11 changes: 8 additions & 3 deletions workers/email/src/templates/emails/block-workspace/html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,26 @@
<td align="center" style="padding: 15px 0;">
<font color="#dbe6ff" style="font-size: 15px; text-align: center; color: #dbe6ff; letter-spacing: 0.4px;">
<span style="vertical-align: middle; display: inline-block;">
Workspace was blocked
«{{ workspace.name | escape }}» не принимает события
</span>
</font>
</td>
</tr>
<tr>
<td style="display: block; padding: 20px; margin-bottom: 30px; border-width: 1px; border-color: #494f5e; border-style: solid; border-radius: 10px; line-height: 1.47">
<font color="#dbe6ff" style="font-size: 15px; letter-spacing: 0.4px;">
Your workspace "{{ workspace.name | escape }}" was blocked because the plan was not renewed or events limit has been reached. Please, check payment settings and renew the plan.
<p style="margin-top: 0;">
Вы больше не отслеживаете новые ошибки, потому что закончился лимит или срок действия тарифного плана.
</p>
<p style="margin-bottom: 0;">
Чтобы продолжить получать события, выберите подходящий тарифный план и продлите подписку в настройках оплаты.
</p>
</font>
</td>
</tr>
<tr>
<td style="padding-right: 20px; padding-left: 20px; padding-bottom: 40px;">
{% include '../../components/button.twig' with {href: host ~ '/workspace/' ~ workspace._id ~ '/settings/billing', label: 'Go to payment settings'} %}
{% include '../../components/button.twig' with {href: host ~ '/workspace/' ~ workspace._id ~ '/settings/billing', label: workspace.tariffPlanId is same as('5f47f031ff71510040f433c1') ? 'Увеличить лимит от 99 ₽' : 'Открыть настройки'} %}
</td>
</tr>
{% endblock %}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Workspace {{ workspace.name | escape }} was blocked!
Мониторинг ошибок остановлен
12 changes: 7 additions & 5 deletions workers/email/src/templates/emails/block-workspace/text.twig
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
Your workspace "{{ workspace.name | escape }}" was blocked because the plan was not renewed or events limit has been reached.
Мониторинг ошибок остановлен

Please, check payment settings and renew the plan: {{ host }}/workspace/{{ workspace._id }}/settings/billing
Вы больше не отслеживаете новые ошибки «{{ workspace.name | escape }}», потому что закончился лимит или срок действия тарифного плана

Чтобы продолжить получать события, выберите подходящий тарифный план и продлите подписку в настройках оплаты: {{ host }}/workspace/{{ workspace._id }}/settings/billing

***

Hawk
Errors tracking system
Хоук
Российский трекер ошибок

Made by CodeX
Made by CodeX
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{% extends '../../components/layout.twig' %}

{% block header %}
{% include '../../components/workspace.twig' with {workspace: workspace} %}
{% endblock %}

{% block content %}
<tr>
<td>
<img src="{{ hostOfStatic }}/email/low-balance-icon.png" width="32" height="32" hspace="3" style="display: block; vertical-align: middle; margin: 23px auto 0;">
</td>
</tr>
<tr>
<td align="center" style="padding: 15px 0;">
<font color="#dbe6ff" style="font-size: 15px; text-align: center; color: #dbe6ff; letter-spacing: 0.4px;">
<span style="vertical-align: middle; display: inline-block;">
{{ daysAfterPayday }} {{ pluralize_ru(daysAfterPayday, ['день', 'дня', 'дней']) }} без мониторинга
</span>
</font>
</td>
</tr>
<tr>
<td style="display: block; padding: 20px; margin-bottom: 30px; border-width: 1px; border-color: #494f5e; border-style: solid; border-radius: 10px; line-height: 1.47">
<font color="#dbe6ff" style="font-size: 15px; letter-spacing: 0.4px;">
<p style="margin-top: 0;">
Напоминаем, что мониторинг ошибок в «{{ workspace.name | escape }}» всё ещё остановлен, потому что закончился лимит или срок действия тарифного плана.
</p>
<p style="margin-bottom: 0;">
Чтобы снова видеть актуальные события, выберите подходящий тарифный план и продлите подписку в настройках оплаты.
</p>
</font>
</td>
</tr>
<tr>
<td style="padding-right: 20px; padding-left: 20px; padding-bottom: 40px;">
{% include '../../components/button.twig' with {href: host ~ '/workspace/' ~ workspace._id ~ '/settings/billing', label: workspace.tariffPlanId is same as('5f47f031ff71510040f433c1') ? 'Выбрать тариф от 99 ₽' : 'Открыть настройки'} %}
</td>
</tr>
{% endblock %}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Требуется действие: мониторинг ошибок в {{ workspace.name }} не работает уже {{ daysAfterPayday }} {{ pluralize_ru(daysAfterPayday, ['день', 'дня', 'дней']) }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Требуется действие: мониторинг ошибок в {{ workspace.name }} не работает уже {{ daysAfterPayday }} {{ pluralize_ru(daysAfterPayday, ['день', 'дня', 'дней']) }}

Чтобы снова видеть актуальные события, выберите подходящий тарифный план и продлите подписку в настройках оплаты: {{ host }}/workspace/{{ workspace._id }}/settings/billing

***

Хоук
Российский трекер ошибок

Made by CodeX
26 changes: 26 additions & 0 deletions workers/email/src/templates/extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,29 @@ Twig.extendFilter('abbrNumber', (value: number): string => {
Twig.extendFilter('sortEvents', (events: TemplateEventData[]): TemplateEventData[] => {
return events.sort((a, b) => a.newCount - b.newCount);
});

/**
* Pluralize Russian words based on a number
*
* @param {number} n - the number to determine the form
* @param {string[]} forms - array of word forms [singular, few, many]
* @returns {string}
*/
Twig.extendFunction('pluralize_ru', (n: number, forms: string[]): string => {
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
if (n % 100 >= 11 && n % 100 <= 19) {
return forms[2];
}

// eslint-disable-next-line @typescript-eslint/no-magic-numbers
const last = n % 10;

if (last === 1) {
return forms[0];
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
} else if (last >= 2 && last <= 4) {
return forms[1];
} else {
return forms[2];
}
});
1 change: 1 addition & 0 deletions workers/email/src/templates/names.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
enum Templates {
Assignee = 'assignee',
BlockWorkspace = 'block-workspace',
BlockedWorkspaceReminder = 'blocked-workspace-reminder',
DaysLimitAlmostReached = 'days-limit-almost-reached',
Event = 'event',
EventsLimitAlmostReached = 'events-limit-almost-reached',
Expand Down
Loading
Loading