feat: add TTR simulator and calculation engine, enhance member model with TTR adjustment constant
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 59s
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 59s
This commit is contained in:
@@ -59,6 +59,8 @@ class ClubService {
|
||||
{
|
||||
model: User,
|
||||
as: 'Users',
|
||||
where: { isHidden: false },
|
||||
required: false,
|
||||
through: {
|
||||
attributes: []
|
||||
}
|
||||
@@ -224,6 +226,8 @@ class ClubService {
|
||||
{
|
||||
model: User,
|
||||
as: 'user',
|
||||
where: { isHidden: false },
|
||||
required: true,
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import nodemailer from 'nodemailer';
|
||||
import User from '../models/User.js';
|
||||
|
||||
let transporter = null;
|
||||
|
||||
@@ -38,7 +39,32 @@ function getEmailTransportStatus() {
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeRecipientList(recipients) {
|
||||
const values = Array.isArray(recipients) ? recipients : [recipients];
|
||||
return values
|
||||
.flatMap((value) => String(value || '').split(','))
|
||||
.map((value) => value.trim().toLowerCase())
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
async function sendMail(mailOptions) {
|
||||
const recipients = normalizeRecipientList(mailOptions.to);
|
||||
if (recipients.length) {
|
||||
const suppressedUsers = await User.findAll({
|
||||
where: { email: recipients, suppressEmails: true },
|
||||
attributes: ['email'],
|
||||
});
|
||||
const suppressedEmails = new Set(suppressedUsers.map((user) => String(user.email).toLowerCase()));
|
||||
const allowedRecipients = recipients.filter((email) => !suppressedEmails.has(email));
|
||||
|
||||
if (!allowedRecipients.length) {
|
||||
console.info('[email] Delivery suppressed for hidden test account');
|
||||
return { suppressed: true, accepted: [], rejected: [] };
|
||||
}
|
||||
|
||||
mailOptions = { ...mailOptions, to: allowedRecipients.join(', ') };
|
||||
}
|
||||
|
||||
return getTransporter().sendMail({
|
||||
from: getDefaultFrom(),
|
||||
...mailOptions,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import UserClub from "../models/UserClub.js";
|
||||
import User from "../models/User.js";
|
||||
import Club from "../models/Club.js";
|
||||
import { checkAccess, getUserByToken, hasUserClubAccess } from "../utils/userUtils.js";
|
||||
import Member from "../models/Member.js";
|
||||
@@ -221,6 +222,17 @@ class MemberService {
|
||||
if (!showAll || showAll === 'false') {
|
||||
where['active'] = true;
|
||||
}
|
||||
const hiddenUsers = await User.findAll({
|
||||
where: { isHidden: true },
|
||||
attributes: ['id'],
|
||||
});
|
||||
const hiddenUserIds = hiddenUsers.map((user) => user.id);
|
||||
if (hiddenUserIds.length) {
|
||||
where[Op.or] = [
|
||||
{ userId: null },
|
||||
{ userId: { [Op.notIn]: hiddenUserIds } },
|
||||
];
|
||||
}
|
||||
const MemberContact = (await import('../models/MemberContact.js')).default;
|
||||
try {
|
||||
const members = await Member.findAll({
|
||||
|
||||
@@ -474,7 +474,13 @@ class PermissionService {
|
||||
|
||||
const userClubs = await UserClub.findAll({
|
||||
where: { clubId },
|
||||
include: [{ model: User, as: 'user', attributes: ['id', 'email'] }],
|
||||
include: [{
|
||||
model: User,
|
||||
as: 'user',
|
||||
attributes: ['id', 'email'],
|
||||
where: { isHidden: false },
|
||||
required: true,
|
||||
}],
|
||||
order: [[{ model: User, as: 'user' }, 'email', 'ASC']],
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user