TSK-1334 Vacancy application notification (#3108)

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Denis Bykhov 2023-04-28 14:22:39 +06:00 committed by GitHub
parent 082bc85ff2
commit 8acdcf7c73
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 65 additions and 10 deletions

View File

@ -1140,6 +1140,25 @@ export function createModel (builder: Builder): void {
recruit.ids.VacancyNotificationGroup recruit.ids.VacancyNotificationGroup
) )
builder.createDoc(
notification.class.NotificationType,
core.space.Model,
{
hidden: false,
generated: false,
label: recruit.string.CreateApplication,
group: recruit.ids.VacancyNotificationGroup,
field: 'space',
txClasses: [core.class.TxCreateDoc, core.class.TxUpdateDoc],
objectClass: recruit.class.Applicant,
spaceSubscribe: true,
providers: {
[notification.providers.PlatformNotification]: false
}
},
recruit.ids.ApplicationCreateNotification
)
generateClassNotificationTypes(builder, recruit.class.Vacancy, recruit.ids.VacancyNotificationGroup, [], ['comments']) generateClassNotificationTypes(builder, recruit.class.Vacancy, recruit.ids.VacancyNotificationGroup, [], ['comments'])
builder.createDoc( builder.createDoc(

View File

@ -72,7 +72,8 @@ export default mergeIds(recruitId, recruit, {
VacancyNotificationGroup: '' as Ref<NotificationGroup>, VacancyNotificationGroup: '' as Ref<NotificationGroup>,
CandidateNotificationGroup: '' as Ref<NotificationGroup>, CandidateNotificationGroup: '' as Ref<NotificationGroup>,
ApplicationNotificationGroup: '' as Ref<NotificationGroup>, ApplicationNotificationGroup: '' as Ref<NotificationGroup>,
AssigneeNotification: '' as Ref<NotificationType> AssigneeNotification: '' as Ref<NotificationType>,
ApplicationCreateNotification: '' as Ref<NotificationType>
}, },
component: { component: {
CreateApplication: '' as AnyComponent, CreateApplication: '' as AnyComponent,

View File

@ -111,6 +111,8 @@ export interface NotificationType extends Doc {
attachedToClass?: Ref<Class<Doc>> attachedToClass?: Ref<Class<Doc>>
// use for update/mixin txes // use for update/mixin txes
field?: string field?: string
// use for space collaborators, not object
spaceSubscribe?: boolean
// allowed providers and default value for it // allowed providers and default value for it
providers: Record<Ref<NotificationProvider>, boolean> providers: Record<Ref<NotificationProvider>, boolean>
// templates for email (and browser/push?) // templates for email (and browser/push?)

View File

@ -423,8 +423,14 @@ function isTypeMatched (
return true return true
} }
async function getMatchedTypes (control: TriggerControl, tx: TxCUD<Doc>): Promise<NotificationType[]> { async function getMatchedTypes (
const allTypes = await control.modelDb.findAll(notification.class.NotificationType, {}) control: TriggerControl,
tx: TxCUD<Doc>,
isSpace: boolean = false
): Promise<NotificationType[]> {
const allTypes = (await control.modelDb.findAll(notification.class.NotificationType, {})).filter((p) =>
isSpace ? p.spaceSubscribe === true : p.spaceSubscribe !== true
)
const extractedTx = TxProcessor.extractTx(tx) as TxCUD<Doc> const extractedTx = TxProcessor.extractTx(tx) as TxCUD<Doc>
const filtered: NotificationType[] = [] const filtered: NotificationType[] = []
for (const type of allTypes) { for (const type of allTypes) {
@ -444,11 +450,12 @@ async function isShouldNotify (
control: TriggerControl, control: TriggerControl,
tx: TxCUD<Doc>, tx: TxCUD<Doc>,
object: Doc, object: Doc,
user: Ref<Account> user: Ref<Account>,
isSpace: boolean
): Promise<NotifyResult> { ): Promise<NotifyResult> {
let allowed = false let allowed = false
const emailTypes: NotificationType[] = [] const emailTypes: NotificationType[] = []
const types = await getMatchedTypes(control, tx) const types = await getMatchedTypes(control, tx, isSpace)
for (const type of types) { for (const type of types) {
if (control.hierarchy.hasMixin(type, serverNotification.mixin.TypeMatch)) { if (control.hierarchy.hasMixin(type, serverNotification.mixin.TypeMatch)) {
const mixin = control.hierarchy.as(type, serverNotification.mixin.TypeMatch) const mixin = control.hierarchy.as(type, serverNotification.mixin.TypeMatch)
@ -476,11 +483,12 @@ async function getNotificationTxes (
object: Doc, object: Doc,
originTx: TxCUD<Doc>, originTx: TxCUD<Doc>,
target: Ref<Account>, target: Ref<Account>,
docUpdates: DocUpdates[] docUpdates: DocUpdates[],
isSpace: boolean
): Promise<Tx[]> { ): Promise<Tx[]> {
if (originTx.modifiedBy === target) return [] if (originTx.modifiedBy === target) return []
const res: Tx[] = [] const res: Tx[] = []
const allowed = await isShouldNotify(control, originTx, object, target) const allowed = await isShouldNotify(control, originTx, object, target, isSpace)
if (allowed.allowed) { if (allowed.allowed) {
const current = docUpdates.find((p) => p.user === target) const current = docUpdates.find((p) => p.user === target)
if (current === undefined) { if (current === undefined) {
@ -532,13 +540,14 @@ async function createCollabDocInfo (
collaborators: Ref<Account>[], collaborators: Ref<Account>[],
control: TriggerControl, control: TriggerControl,
originTx: TxCUD<Doc>, originTx: TxCUD<Doc>,
object: Doc object: Doc,
isSpace: boolean = false
): Promise<Tx[]> { ): Promise<Tx[]> {
let res: Tx[] = [] let res: Tx[] = []
const targets = new Set(collaborators) const targets = new Set(collaborators)
const docUpdates = await control.findAll(notification.class.DocUpdates, { attachedTo: object._id }) const docUpdates = await control.findAll(notification.class.DocUpdates, { attachedTo: object._id })
for (const target of targets) { for (const target of targets) {
res = res.concat(await getNotificationTxes(control, object, originTx, target, docUpdates)) res = res.concat(await getNotificationTxes(control, object, originTx, target, docUpdates, isSpace))
} }
return res return res
} }
@ -563,6 +572,27 @@ export function getMixinTx (
return tx return tx
} }
async function getSpaceCollabTxes (
control: TriggerControl,
doc: Doc,
tx: TxCUD<Doc>,
originTx: TxCUD<Doc>
): Promise<Tx[]> {
const space = (await control.findAll(core.class.Space, { _id: doc.space }))[0]
if (space === undefined) return []
const mixin = control.hierarchy.classHierarchyMixin<Doc, ClassCollaborators>(
space._class,
notification.mixin.ClassCollaborators
)
if (mixin !== undefined) {
const collabs = control.hierarchy.as<Doc, Collaborators>(space, notification.mixin.Collaborators)
if (collabs.collaborators !== undefined) {
return await createCollabDocInfo(collabs.collaborators, control, originTx, doc, true)
}
}
return []
}
/** /**
* @public * @public
*/ */
@ -574,8 +604,8 @@ export async function createCollaboratorDoc (
const res: Tx[] = [] const res: Tx[] = []
const hierarchy = control.hierarchy const hierarchy = control.hierarchy
const mixin = hierarchy.classHierarchyMixin(tx.objectClass, notification.mixin.ClassCollaborators) const mixin = hierarchy.classHierarchyMixin(tx.objectClass, notification.mixin.ClassCollaborators)
const doc = TxProcessor.createDoc2Doc(tx)
if (mixin !== undefined) { if (mixin !== undefined) {
const doc = TxProcessor.createDoc2Doc(tx)
const collaborators = await getDocCollaborators(doc, mixin, control) const collaborators = await getDocCollaborators(doc, mixin, control)
const mixinTx = getMixinTx(tx, control, collaborators) const mixinTx = getMixinTx(tx, control, collaborators)
@ -583,6 +613,7 @@ export async function createCollaboratorDoc (
res.push(mixinTx) res.push(mixinTx)
res.push(...notificationTxes) res.push(...notificationTxes)
} }
res.push(...(await getSpaceCollabTxes(control, doc, tx, originTx)))
return res return res
} }
@ -717,6 +748,8 @@ async function updateCollaboratorDoc (
res = res.concat(await createCollabDocInfo(collaborators, control, originTx, doc)) res = res.concat(await createCollabDocInfo(collaborators, control, originTx, doc))
} }
res = res.concat(await getSpaceCollabTxes(control, doc, tx, originTx))
return res return res
} }