mirror of
https://github.com/documenso/documenso.git
synced 2026-10-01 01:04:38 +10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7f053e6fd | ||
|
|
b75a66d5c0 |
@@ -37,7 +37,7 @@ import { useMemo } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { Link, useNavigate } from 'react-router';
|
||||
import { match } from 'ts-pattern';
|
||||
import type { z } from 'zod';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { AdminOrganisationDeleteDialog } from '~/components/dialogs/admin-organisation-delete-dialog';
|
||||
import { AdminOrganisationMemberDeleteDialog } from '~/components/dialogs/admin-organisation-member-delete-dialog';
|
||||
@@ -563,11 +563,15 @@ const GenericOrganisationAdminForm = ({ organisation }: OrganisationAdminFormOpt
|
||||
);
|
||||
};
|
||||
|
||||
const ZUpdateOrganisationBillingFormSchema = ZUpdateAdminOrganisationRequestSchema.shape.data.pick({
|
||||
claims: true,
|
||||
customerId: true,
|
||||
originalSubscriptionClaimId: true,
|
||||
});
|
||||
const ZUpdateOrganisationBillingFormSchema = ZUpdateAdminOrganisationRequestSchema.shape.data
|
||||
.pick({
|
||||
claims: true,
|
||||
customerId: true,
|
||||
originalSubscriptionClaimId: true,
|
||||
})
|
||||
.extend({
|
||||
notifyOrganisation: z.boolean(),
|
||||
});
|
||||
|
||||
type TUpdateOrganisationBillingFormSchema = z.infer<typeof ZUpdateOrganisationBillingFormSchema>;
|
||||
|
||||
@@ -614,19 +618,31 @@ const OrganisationAdminForm = ({ organisation, licenseFlags }: OrganisationAdmin
|
||||
emailTransportId: organisation.organisationClaim.emailTransportId ?? null,
|
||||
},
|
||||
originalSubscriptionClaimId: organisation.organisationClaim.originalSubscriptionClaimId || '',
|
||||
notifyOrganisation: true,
|
||||
},
|
||||
});
|
||||
|
||||
const onSubmit = async (values: TUpdateOrganisationBillingFormSchema) => {
|
||||
const onSubmit = async ({ notifyOrganisation, ...values }: TUpdateOrganisationBillingFormSchema) => {
|
||||
try {
|
||||
await updateOrganisation({
|
||||
const { isNotificationSent } = await updateOrganisation({
|
||||
organisationId: organisation.id,
|
||||
data: values,
|
||||
notifyOrganisation,
|
||||
});
|
||||
|
||||
form.setValue('notifyOrganisation', false);
|
||||
|
||||
const description = match({ notifyOrganisation, isNotificationSent })
|
||||
.with({ isNotificationSent: true }, () => t`Organisation has been updated and its owner has been notified`)
|
||||
.with(
|
||||
{ notifyOrganisation: true },
|
||||
() => t`Organisation has been updated. No limits changed, so no notification was sent`,
|
||||
)
|
||||
.otherwise(() => t`Organisation has been updated successfully`);
|
||||
|
||||
toast({
|
||||
title: t`Success`,
|
||||
description: t`Organisation has been updated successfully`,
|
||||
description,
|
||||
duration: 5000,
|
||||
});
|
||||
} catch (err) {
|
||||
@@ -919,6 +935,31 @@ const OrganisationAdminForm = ({ organisation, licenseFlags }: OrganisationAdmin
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="notifyOrganisation"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<div className="flex items-center">
|
||||
<FormControl>
|
||||
<Checkbox id="notify-organisation" checked={field.value} onCheckedChange={field.onChange} />
|
||||
</FormControl>
|
||||
|
||||
<label className="ml-2 text-muted-foreground text-sm" htmlFor="notify-organisation">
|
||||
<Trans>Notify the organisation about limit changes</Trans>
|
||||
</label>
|
||||
</div>
|
||||
<FormDescription>
|
||||
<Trans>
|
||||
Emails the organisation owner to let them know their limits have been updated. No email is sent if no
|
||||
limits changed.
|
||||
</Trans>
|
||||
</FormDescription>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button type="submit" loading={form.formState.isSubmitting}>
|
||||
<Trans>Update</Trans>
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
import { SUPPORT_EMAIL } from '@documenso/lib/constants/app';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
|
||||
import { Body, Container, Head, Hr, Html, Preview, Section, Text } from '../components';
|
||||
import { TemplateBrandingLogo } from '../template-components/template-branding-logo';
|
||||
import { TemplateFooter } from '../template-components/template-footer';
|
||||
|
||||
export type OrganisationLimitsUpdatedEmailProps = {
|
||||
assetBaseUrl: string;
|
||||
organisationName: string;
|
||||
};
|
||||
|
||||
export const OrganisationLimitsUpdatedEmailTemplate = ({
|
||||
assetBaseUrl = 'http://localhost:3002',
|
||||
organisationName = 'Organisation Name',
|
||||
}: OrganisationLimitsUpdatedEmailProps) => {
|
||||
const { _ } = useLingui();
|
||||
|
||||
return (
|
||||
<Html>
|
||||
<Head />
|
||||
<Body className="mx-auto my-auto font-sans">
|
||||
<Preview>{_(ORGANISATION_LIMITS_UPDATED_SUBJECT)}</Preview>
|
||||
|
||||
<Section className="bg-background text-muted-foreground">
|
||||
<Container className="mx-auto mt-8 mb-2 max-w-xl rounded-lg border border-border border-solid p-2 backdrop-blur-sm">
|
||||
<TemplateBrandingLogo assetBaseUrl={assetBaseUrl} className="mb-4 h-6 p-2" />
|
||||
|
||||
<Section className="p-2 text-muted-foreground">
|
||||
<Text className="text-center font-medium text-foreground text-lg">
|
||||
{_(ORGANISATION_LIMITS_UPDATED_SUBJECT)}
|
||||
</Text>
|
||||
|
||||
<div className="mx-auto my-2 w-fit rounded-lg bg-muted px-4 py-2 font-medium text-base text-muted-foreground">
|
||||
{organisationName}
|
||||
</div>
|
||||
|
||||
<Text className="text-center text-base">
|
||||
<Trans>We've updated the usage limits for your organisation.</Trans>
|
||||
</Text>
|
||||
|
||||
<Text className="text-center text-base">
|
||||
<Trans>
|
||||
If you recently received an email regarding your usage limits, this change was made in response to
|
||||
that.
|
||||
</Trans>
|
||||
</Text>
|
||||
|
||||
<Text className="text-center text-base">
|
||||
<Trans>If you have any questions, please contact support at {SUPPORT_EMAIL}.</Trans>
|
||||
</Text>
|
||||
</Section>
|
||||
</Container>
|
||||
|
||||
<Hr className="mx-auto mt-12 max-w-xl" />
|
||||
|
||||
<Container className="mx-auto max-w-xl">
|
||||
<TemplateFooter isDocument={false} />
|
||||
</Container>
|
||||
</Section>
|
||||
</Body>
|
||||
</Html>
|
||||
);
|
||||
};
|
||||
|
||||
export const ORGANISATION_LIMITS_UPDATED_SUBJECT = msg`Your organisation limits have been updated`;
|
||||
|
||||
export default OrganisationLimitsUpdatedEmailTemplate;
|
||||
@@ -7,6 +7,7 @@ import { SEND_DOCUMENT_CREATED_FROM_DIRECT_TEMPLATE_EMAIL_JOB_DEFINITION } from
|
||||
import { SEND_DOCUMENT_DELETED_EMAILS_JOB_DEFINITION } from './definitions/emails/send-document-deleted-emails';
|
||||
import { SEND_DOCUMENT_PENDING_EMAIL_JOB_DEFINITION } from './definitions/emails/send-document-pending-email';
|
||||
import { SEND_ORGANISATION_LIMIT_ALERT_EMAIL_JOB_DEFINITION } from './definitions/emails/send-organisation-limit-alert-email';
|
||||
import { SEND_ORGANISATION_LIMITS_UPDATED_EMAIL_JOB_DEFINITION } from './definitions/emails/send-organisation-limits-updated-email';
|
||||
import { SEND_ORGANISATION_MEMBER_JOINED_EMAIL_JOB_DEFINITION } from './definitions/emails/send-organisation-member-joined-email';
|
||||
import { SEND_ORGANISATION_MEMBER_LEFT_EMAIL_JOB_DEFINITION } from './definitions/emails/send-organisation-member-left-email';
|
||||
import { SEND_OWNER_RECIPIENT_EXPIRED_EMAIL_JOB_DEFINITION } from './definitions/emails/send-owner-recipient-expired-email';
|
||||
@@ -43,6 +44,7 @@ export const jobsClient = new JobClient([
|
||||
SEND_ORGANISATION_MEMBER_JOINED_EMAIL_JOB_DEFINITION,
|
||||
SEND_ORGANISATION_MEMBER_LEFT_EMAIL_JOB_DEFINITION,
|
||||
SEND_ORGANISATION_LIMIT_ALERT_EMAIL_JOB_DEFINITION,
|
||||
SEND_ORGANISATION_LIMITS_UPDATED_EMAIL_JOB_DEFINITION,
|
||||
SEND_TEAM_DELETED_EMAIL_JOB_DEFINITION,
|
||||
SEAL_DOCUMENT_JOB_DEFINITION,
|
||||
SEAL_DOCUMENT_SWEEP_JOB_DEFINITION,
|
||||
|
||||
@@ -129,6 +129,7 @@ export const run = async ({
|
||||
text: `
|
||||
Organisation: ${organisation.name}
|
||||
Organisation ID: ${organisation.id}
|
||||
Admin URL: ${NEXT_PUBLIC_WEBAPP_URL()}/admin/organisations/${organisation.id}
|
||||
Organisation Claim Original ID: ${organisation.organisationClaim.originalSubscriptionClaimId}
|
||||
Email Quota: ${organisation.monthlyStats[0]?.emailCount || 0}/${organisation.organisationClaim.emailQuota ?? 'Unlimited'}
|
||||
API Quota: ${organisation.monthlyStats[0]?.apiCount || 0}/${organisation.organisationClaim.apiQuota ?? 'Unlimited'}
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
import OrganisationLimitsUpdatedEmailTemplate, {
|
||||
ORGANISATION_LIMITS_UPDATED_SUBJECT,
|
||||
} from '@documenso/email/templates/organisation-limits-updated';
|
||||
import { prisma } from '@documenso/prisma';
|
||||
import { createElement } from 'react';
|
||||
|
||||
import { getI18nInstance } from '../../../client-only/providers/i18n-server';
|
||||
import { NEXT_PUBLIC_WEBAPP_URL } from '../../../constants/app';
|
||||
import { getEmailContext } from '../../../server-only/email/get-email-context';
|
||||
import { renderEmailWithI18N } from '../../../utils/render-email-with-i18n';
|
||||
import type { JobRunIO } from '../../client/_internal/job';
|
||||
import type { TSendOrganisationLimitsUpdatedEmailJobDefinition } from './send-organisation-limits-updated-email';
|
||||
|
||||
export const run = async ({
|
||||
payload,
|
||||
io,
|
||||
}: {
|
||||
payload: TSendOrganisationLimitsUpdatedEmailJobDefinition;
|
||||
io: JobRunIO;
|
||||
}) => {
|
||||
const organisation = await prisma.organisation.findFirstOrThrow({
|
||||
where: {
|
||||
id: payload.organisationId,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
owner: {
|
||||
select: {
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const { branding, emailLanguage, senderEmail, emailTransport } = await getEmailContext({
|
||||
emailType: 'INTERNAL',
|
||||
source: {
|
||||
type: 'organisation',
|
||||
organisationId: organisation.id,
|
||||
},
|
||||
});
|
||||
|
||||
await io.runTask('send-organisation-limits-updated-email', async () => {
|
||||
const emailContent = createElement(OrganisationLimitsUpdatedEmailTemplate, {
|
||||
assetBaseUrl: NEXT_PUBLIC_WEBAPP_URL(),
|
||||
organisationName: organisation.name,
|
||||
});
|
||||
|
||||
const [html, text] = await Promise.all([
|
||||
renderEmailWithI18N(emailContent, { lang: emailLanguage, branding }),
|
||||
renderEmailWithI18N(emailContent, { lang: emailLanguage, branding, plainText: true }),
|
||||
]);
|
||||
|
||||
const i18n = await getI18nInstance(emailLanguage);
|
||||
|
||||
await emailTransport.sendMail({
|
||||
to: organisation.owner.email,
|
||||
from: senderEmail,
|
||||
subject: i18n._(ORGANISATION_LIMITS_UPDATED_SUBJECT),
|
||||
html,
|
||||
text,
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import type { JobDefinition } from '../../client/_internal/job';
|
||||
|
||||
const SEND_ORGANISATION_LIMITS_UPDATED_EMAIL_JOB_DEFINITION_ID = 'send.organisation-limits-updated.email';
|
||||
|
||||
const SEND_ORGANISATION_LIMITS_UPDATED_EMAIL_JOB_DEFINITION_SCHEMA = z.object({
|
||||
organisationId: z.string(),
|
||||
});
|
||||
|
||||
export type TSendOrganisationLimitsUpdatedEmailJobDefinition = z.infer<
|
||||
typeof SEND_ORGANISATION_LIMITS_UPDATED_EMAIL_JOB_DEFINITION_SCHEMA
|
||||
>;
|
||||
|
||||
export const SEND_ORGANISATION_LIMITS_UPDATED_EMAIL_JOB_DEFINITION = {
|
||||
id: SEND_ORGANISATION_LIMITS_UPDATED_EMAIL_JOB_DEFINITION_ID,
|
||||
name: 'Send Organisation Limits Updated Email',
|
||||
version: '1.0.0',
|
||||
trigger: {
|
||||
name: SEND_ORGANISATION_LIMITS_UPDATED_EMAIL_JOB_DEFINITION_ID,
|
||||
schema: SEND_ORGANISATION_LIMITS_UPDATED_EMAIL_JOB_DEFINITION_SCHEMA,
|
||||
},
|
||||
handler: async ({ payload, io }) => {
|
||||
const handler = await import('./send-organisation-limits-updated-email.handler');
|
||||
|
||||
await handler.run({ payload, io });
|
||||
},
|
||||
} as const satisfies JobDefinition<
|
||||
typeof SEND_ORGANISATION_LIMITS_UPDATED_EMAIL_JOB_DEFINITION_ID,
|
||||
TSendOrganisationLimitsUpdatedEmailJobDefinition
|
||||
>;
|
||||
@@ -310,7 +310,7 @@ msgstr "{0}-Feld"
|
||||
#. placeholder {1}: envelope.title
|
||||
#: packages/lib/jobs/definitions/emails/send-signing-email.handler.ts
|
||||
msgid "{0} has invited you to {recipientActionVerb} the document \"{1}\"."
|
||||
msgstr "{0} hat Sie eingeladen, das Dokument \"{1}\" {recipientActionVerb}."
|
||||
msgstr "{0} hat Sie eingeladen, das Dokument \"{1}\" zu {recipientActionVerb}."
|
||||
|
||||
#. placeholder {0}: organisation.name
|
||||
#: apps/remix/app/components/general/settings-upsell/branding-upsell.tsx
|
||||
@@ -321,7 +321,7 @@ msgstr ""
|
||||
#. placeholder {0}: team.name
|
||||
#: packages/lib/jobs/definitions/emails/send-signing-email.handler.ts
|
||||
msgid "{0} invited you to {recipientActionVerb} a document"
|
||||
msgstr "{0} hat dich eingeladen, ein Dokument {recipientActionVerb}"
|
||||
msgstr "{0} hat dich eingeladen, ein Dokument zu {recipientActionVerb}"
|
||||
|
||||
#. placeholder {0}: remaining.documents
|
||||
#. placeholder {1}: quota.documents
|
||||
@@ -336,7 +336,7 @@ msgstr "{0} von {1} Dokumenten verbleibend in diesem Monat."
|
||||
#. placeholder {2}: envelope.title
|
||||
#: packages/lib/server-only/document/resend-document.ts
|
||||
msgid "{0} on behalf of \"{1}\" has invited you to {recipientActionVerb} the document \"{2}\"."
|
||||
msgstr "{0} im Namen von \"{1}\" hat Sie eingeladen, das Dokument \"{2}\" {recipientActionVerb}."
|
||||
msgstr "{0} im Namen von \"{1}\" hat Sie eingeladen, das Dokument \"{2}\" zu {recipientActionVerb}."
|
||||
|
||||
#. placeholder {0}: planClaim.name
|
||||
#: apps/remix/app/components/general/settings-org-switcher.tsx
|
||||
@@ -407,15 +407,15 @@ msgstr "{inviterName} hat das Dokument<0/>\"{documentName}\" storniert"
|
||||
#. placeholder {0}: _(actionVerb).toLowerCase()
|
||||
#: packages/email/template-components/template-document-invite.tsx
|
||||
msgid "{inviterName} has invited you to {0}<0/>\"{documentName}\""
|
||||
msgstr "{inviterName} hat dich eingeladen, {0}<0/>\"{documentName}\""
|
||||
msgstr "{inviterName} hat dich eingeladen, zu {0}<0/>\"{documentName}\""
|
||||
|
||||
#: packages/email/templates/document-invite.tsx
|
||||
msgid "{inviterName} has invited you to {action} {documentName}"
|
||||
msgstr "{inviterName} hat dich eingeladen, {action} {documentName}"
|
||||
msgstr "{inviterName} hat dich eingeladen, zu {action} {documentName}"
|
||||
|
||||
#: packages/email/templates/document-invite.tsx
|
||||
msgid "{inviterName} has invited you to {action} the document \"{documentName}\"."
|
||||
msgstr "{inviterName} hat Sie eingeladen, das Dokument \"{documentName}\" {action}."
|
||||
msgstr "{inviterName} hat Sie eingeladen, das Dokument \"{documentName}\" zu {action}."
|
||||
|
||||
#: packages/email/templates/recipient-removed-from-document.tsx
|
||||
msgid "{inviterName} has removed you from the document {documentName}."
|
||||
@@ -429,16 +429,16 @@ msgstr "{inviterName} hat dich aus dem Dokument<0/>\"{documentName}\" entfernt"
|
||||
#. placeholder {1}: envelope.title
|
||||
#: packages/lib/jobs/definitions/emails/send-signing-email.handler.ts
|
||||
msgid "{inviterName} on behalf of \"{0}\" has invited you to {recipientActionVerb} the document \"{1}\"."
|
||||
msgstr "{inviterName} im Auftrag von \"{0}\" hat Sie eingeladen, das Dokument \"{1}\" {recipientActionVerb}."
|
||||
msgstr "{inviterName} im Auftrag von \"{0}\" hat Sie eingeladen, das Dokument \"{1}\" zu {recipientActionVerb}."
|
||||
|
||||
#. placeholder {0}: _(actionVerb).toLowerCase()
|
||||
#: packages/email/template-components/template-document-invite.tsx
|
||||
msgid "{inviterName} on behalf of \"{teamName}\" has invited you to {0}<0/>\"{documentName}\""
|
||||
msgstr "{inviterName} im Namen von \"{teamName}\" hat dich eingeladen, {0}<0/>\"{documentName}\""
|
||||
msgstr "{inviterName} im Namen von \"{teamName}\" hat dich eingeladen, zu {0}<0/>\"{documentName}\""
|
||||
|
||||
#: packages/email/templates/document-invite.tsx
|
||||
msgid "{inviterName} on behalf of \"{teamName}\" has invited you to {action} {documentName}"
|
||||
msgstr "{inviterName} im Namen von \"{teamName}\" hat Sie eingeladen, das Dokument {documentName} {action}"
|
||||
msgstr "{inviterName} im Namen von \"{teamName}\" hat Sie eingeladen, das Dokument {documentName} zu {action}"
|
||||
|
||||
#: apps/remix/app/components/dialogs/envelopes-bulk-download-dialog.tsx
|
||||
msgid "{MAX_BULK_DOWNLOAD_ENVELOPES, plural, one {You can download up to # document at a time. Deselect some documents to continue.} other {You can download up to # documents at a time. Deselect some documents to continue.}}"
|
||||
@@ -517,11 +517,11 @@ msgstr "{subscriptionClaimCount, plural, one {# Abonnementsanforderung} other {#
|
||||
#. placeholder {0}: _(actionVerb).toLowerCase()
|
||||
#: packages/email/template-components/template-document-invite.tsx
|
||||
msgid "{teamName} has invited you to {0}<0/>\"{documentName}\""
|
||||
msgstr "{teamName} hat dich eingeladen, {0}<0/>\"{documentName}\""
|
||||
msgstr "{teamName} hat dich eingeladen, zu {0}<0/>\"{documentName}\""
|
||||
|
||||
#: packages/email/templates/document-invite.tsx
|
||||
msgid "{teamName} has invited you to {action} {documentName}"
|
||||
msgstr "{teamName} hat Sie eingeladen, {action} {documentName}"
|
||||
msgstr "{teamName} hat Sie eingeladen, zu {action} {documentName}"
|
||||
|
||||
#: apps/remix/app/components/general/app-command-menu.tsx
|
||||
msgid "{totalVisibleCount, plural, one {# item} other {# items}}"
|
||||
@@ -9344,7 +9344,7 @@ msgstr "Erinnerung: {0}"
|
||||
#: packages/lib/jobs/definitions/internal/process-signing-reminder.handler.ts
|
||||
#: packages/lib/server-only/document/resend-document.ts
|
||||
msgid "Reminder: {0} invited you to {recipientActionVerb} a document"
|
||||
msgstr "Erinnerung: {0} hat dich eingeladen, ein Dokument {recipientActionVerb}"
|
||||
msgstr "Erinnerung: {0} hat dich eingeladen, ein Dokument zu {recipientActionVerb}"
|
||||
|
||||
#. placeholder {0}: _(actionVerb).toLowerCase()
|
||||
#: packages/email/template-components/template-document-reminder.tsx
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
export type OrganisationLimits = {
|
||||
documentQuota: number | null;
|
||||
emailQuota: number | null;
|
||||
apiQuota: number | null;
|
||||
teamCount: number;
|
||||
memberCount: number;
|
||||
recipientCount: number;
|
||||
envelopeItemCount: number;
|
||||
};
|
||||
|
||||
const ORGANISATION_LIMIT_KEYS = [
|
||||
'documentQuota',
|
||||
'emailQuota',
|
||||
'apiQuota',
|
||||
'teamCount',
|
||||
'memberCount',
|
||||
'recipientCount',
|
||||
'envelopeItemCount',
|
||||
] as const satisfies (keyof OrganisationLimits)[];
|
||||
|
||||
export const hasOrganisationLimitsChanged = (
|
||||
previous: OrganisationLimits,
|
||||
next: Partial<OrganisationLimits>,
|
||||
): boolean => {
|
||||
return ORGANISATION_LIMIT_KEYS.some((key) => next[key] !== undefined && next[key] !== previous[key]);
|
||||
};
|
||||
@@ -1,4 +1,6 @@
|
||||
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
||||
import { jobs } from '@documenso/lib/jobs/client';
|
||||
import { hasOrganisationLimitsChanged } from '@documenso/lib/universal/organisation-limit-changes';
|
||||
import { prisma } from '@documenso/prisma';
|
||||
|
||||
import { adminProcedure } from '../trpc';
|
||||
@@ -11,11 +13,12 @@ export const updateAdminOrganisationRoute = adminProcedure
|
||||
.input(ZUpdateAdminOrganisationRequestSchema)
|
||||
.output(ZUpdateAdminOrganisationResponseSchema)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const { organisationId, data } = input;
|
||||
const { organisationId, data, notifyOrganisation } = input;
|
||||
|
||||
ctx.logger.info({
|
||||
input: {
|
||||
organisationId,
|
||||
notifyOrganisation,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -34,6 +37,8 @@ export const updateAdminOrganisationRoute = adminProcedure
|
||||
|
||||
const { name, url, customerId, claims, originalSubscriptionClaimId } = data;
|
||||
|
||||
const isLimitsChanged = claims ? hasOrganisationLimitsChanged(organisation.organisationClaim, claims) : false;
|
||||
|
||||
await prisma.organisation.update({
|
||||
where: {
|
||||
id: organisationId,
|
||||
@@ -54,4 +59,26 @@ export const updateAdminOrganisationRoute = adminProcedure
|
||||
originalSubscriptionClaimId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!notifyOrganisation) {
|
||||
return { isNotificationSent: false };
|
||||
}
|
||||
|
||||
if (!isLimitsChanged) {
|
||||
ctx.logger.info({
|
||||
msg: 'Skipping organisation limits updated email, no limits changed',
|
||||
organisationId,
|
||||
});
|
||||
|
||||
return { isNotificationSent: false };
|
||||
}
|
||||
|
||||
await jobs.triggerJob({
|
||||
name: 'send.organisation-limits-updated.email',
|
||||
payload: {
|
||||
organisationId,
|
||||
},
|
||||
});
|
||||
|
||||
return { isNotificationSent: true };
|
||||
});
|
||||
|
||||
@@ -26,8 +26,11 @@ export const ZUpdateAdminOrganisationRequestSchema = z.object({
|
||||
customerId: z.string().optional(),
|
||||
originalSubscriptionClaimId: z.string().optional(),
|
||||
}),
|
||||
notifyOrganisation: z.boolean().optional(),
|
||||
});
|
||||
|
||||
export const ZUpdateAdminOrganisationResponseSchema = z.void();
|
||||
export const ZUpdateAdminOrganisationResponseSchema = z.object({
|
||||
isNotificationSent: z.boolean(),
|
||||
});
|
||||
|
||||
export type TUpdateAdminOrganisationRequest = z.infer<typeof ZUpdateAdminOrganisationRequestSchema>;
|
||||
|
||||
Reference in New Issue
Block a user