2026-09-11 02:46:56 +02:00
|
|
|
/**
|
|
|
|
|
* application service
|
2026-09-24 11:51:24 +02:00
|
|
|
*
|
|
|
|
|
* `create` is overridden to fire the acknowledgement e-mail *after* the row is
|
|
|
|
|
* written, mirroring the event-registration service. The send is deliberately
|
|
|
|
|
* not awaited: a slow or failing SMTP call must never turn the application
|
|
|
|
|
* POST into a 502. The mail helper stamps `acknowledgementSentAt` only when
|
|
|
|
|
* the provider accepted the mail, and swallows and logs its own errors.
|
2026-09-11 02:46:56 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import { factories } from '@strapi/strapi';
|
|
|
|
|
|
2026-09-24 11:51:24 +02:00
|
|
|
import { sendApplicationAcknowledgement } from '../../../lib/application-mail';
|
|
|
|
|
|
|
|
|
|
const APPLICATIONS_UID = 'api::application.application';
|
|
|
|
|
const LOG_PREFIX = '[application]';
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The `opportunity` value a client may have sent is a documentId (what the
|
|
|
|
|
* REST API uses for relations), or a legacy numeric id. The Get Involved form
|
|
|
|
|
* sends none at all - an application is not always filed against a call.
|
|
|
|
|
*/
|
|
|
|
|
const readOpportunityReference = (value: unknown): { documentId?: string; id?: number } | undefined => {
|
|
|
|
|
if (typeof value === 'string' && value.length > 0) {
|
|
|
|
|
return { documentId: value };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (typeof value === 'number' && Number.isInteger(value)) {
|
|
|
|
|
return { id: value };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return undefined;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const readCreatedResult = (result: unknown): { documentId?: unknown; email?: unknown } =>
|
|
|
|
|
(typeof result === 'object' && result !== null ? result : {}) as {
|
|
|
|
|
documentId?: unknown;
|
|
|
|
|
email?: unknown;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default factories.createCoreService(APPLICATIONS_UID, ({ strapi }) => ({
|
|
|
|
|
async create(params: { data?: { opportunity?: unknown } } & Record<string, unknown>) {
|
|
|
|
|
const result = await super.create(params);
|
|
|
|
|
|
|
|
|
|
const { documentId, email } = readCreatedResult(result);
|
|
|
|
|
|
|
|
|
|
if (typeof documentId === 'string' && documentId.length > 0) {
|
|
|
|
|
if (typeof email === 'string' && email.length > 0) {
|
|
|
|
|
void sendApplicationAcknowledgement({
|
|
|
|
|
strapi,
|
|
|
|
|
to: email,
|
|
|
|
|
applicationDocumentId: documentId,
|
|
|
|
|
opportunityReference: readOpportunityReference(params.data?.opportunity),
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
strapi.log.warn(
|
|
|
|
|
`${LOG_PREFIX} no email on the created application; acknowledgement skipped.`,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
strapi.log.warn(
|
|
|
|
|
`${LOG_PREFIX} no document id on the created application; acknowledgement skipped.`,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
},
|
|
|
|
|
}));
|