Ausgehende SEPA-Mandate einführen #183
This commit is contained in:
@@ -11,7 +11,7 @@ import {
|
||||
sql,
|
||||
} from "drizzle-orm"
|
||||
|
||||
import { authProfiles, costcentres } from "../../../db/schema";
|
||||
import { authProfiles, costcentres, customers, entitybankaccounts } from "../../../db/schema";
|
||||
import { resourceConfig } from "../../utils/resource.config";
|
||||
import { useNextNumberRangeNumber } from "../../utils/functions";
|
||||
import { getHistoryEntityLabel, insertHistoryItem } from "../../utils/history";
|
||||
@@ -365,6 +365,50 @@ function prepareEntityBankAccountPayload(payload: Record<string, any>, requireAl
|
||||
return { data: result }
|
||||
}
|
||||
|
||||
async function validateOutgoingSepaMandatePayload(
|
||||
server: FastifyInstance,
|
||||
tenantId: number,
|
||||
payload: Record<string, any>,
|
||||
existing: Record<string, any> | null = null
|
||||
) {
|
||||
const customerId = Number(payload.customer ?? existing?.customer)
|
||||
const bankaccountId = Number(payload.bankaccount ?? existing?.bankaccount)
|
||||
|
||||
if (!customerId || !bankaccountId) {
|
||||
return "Kunde und Bankverbindung sind Pflichtfelder."
|
||||
}
|
||||
|
||||
const [customer] = await server.db
|
||||
.select()
|
||||
.from(customers)
|
||||
.where(and(eq(customers.id, customerId), eq(customers.tenant, tenantId)))
|
||||
.limit(1)
|
||||
|
||||
if (!customer) {
|
||||
return "Kunde nicht gefunden."
|
||||
}
|
||||
|
||||
const [bankaccount] = await server.db
|
||||
.select()
|
||||
.from(entitybankaccounts)
|
||||
.where(and(eq(entitybankaccounts.id, bankaccountId), eq(entitybankaccounts.tenant, tenantId)))
|
||||
.limit(1)
|
||||
|
||||
if (!bankaccount) {
|
||||
return "Bankverbindung nicht gefunden."
|
||||
}
|
||||
|
||||
const assignedBankAccountIds = Array.isArray((customer.infoData as any)?.bankAccountIds)
|
||||
? (customer.infoData as any).bankAccountIds.map((id: any) => Number(id))
|
||||
: []
|
||||
|
||||
if (!assignedBankAccountIds.includes(bankaccountId)) {
|
||||
return "Die Bankverbindung ist dem ausgewählten Kunden nicht zugeordnet."
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export default async function resourceRoutes(server: FastifyInstance) {
|
||||
|
||||
// -------------------------------------------------------------
|
||||
@@ -796,6 +840,13 @@ export default async function resourceRoutes(server: FastifyInstance) {
|
||||
}
|
||||
}
|
||||
|
||||
if (resource === "outgoingsepamandates") {
|
||||
const validationError = await validateOutgoingSepaMandatePayload(server, req.user.tenant_id, createData)
|
||||
if (validationError) {
|
||||
return reply.code(400).send({ error: validationError })
|
||||
}
|
||||
}
|
||||
|
||||
if (config.numberRangeHolder && !body[config.numberRangeHolder]) {
|
||||
const numberRangeResource = resource === "members" ? "customers" : resource
|
||||
const result = await useNextNumberRangeNumber(server, req.user.tenant_id, numberRangeResource)
|
||||
@@ -809,6 +860,17 @@ export default async function resourceRoutes(server: FastifyInstance) {
|
||||
|
||||
const [created] = await server.db.insert(table).values(createData).returning()
|
||||
|
||||
if (resource === "outgoingsepamandates" && created?.defaultMandate) {
|
||||
await server.db
|
||||
.update(table)
|
||||
.set({ defaultMandate: false })
|
||||
.where(and(
|
||||
eq(table.tenant, req.user.tenant_id),
|
||||
eq(table.customer, created.customer),
|
||||
sql`${table.id} <> ${created.id}`
|
||||
))
|
||||
}
|
||||
|
||||
if (["products", "services", "hourrates"].includes(resource)) {
|
||||
await recalculateServicePricesForTenant(server, req.user.tenant_id, req.user?.user_id || null);
|
||||
}
|
||||
@@ -917,6 +979,13 @@ export default async function resourceRoutes(server: FastifyInstance) {
|
||||
}
|
||||
}
|
||||
|
||||
if (resource === "outgoingsepamandates") {
|
||||
const validationError = await validateOutgoingSepaMandatePayload(server, tenantId, data, oldRecord)
|
||||
if (validationError) {
|
||||
return reply.code(400).send({ error: validationError })
|
||||
}
|
||||
}
|
||||
|
||||
Object.keys(data).forEach((key) => {
|
||||
const value = data[key]
|
||||
const shouldNormalize =
|
||||
@@ -934,6 +1003,17 @@ export default async function resourceRoutes(server: FastifyInstance) {
|
||||
updateWhereCond = applyResourceWhereFilters(resource, table, updateWhereCond)
|
||||
const [updated] = await server.db.update(table).set(data).where(updateWhereCond).returning()
|
||||
|
||||
if (resource === "outgoingsepamandates" && updated?.defaultMandate) {
|
||||
await server.db
|
||||
.update(table)
|
||||
.set({ defaultMandate: false })
|
||||
.where(and(
|
||||
eq(table.tenant, tenantId),
|
||||
eq(table.customer, updated.customer),
|
||||
sql`${table.id} <> ${updated.id}`
|
||||
))
|
||||
}
|
||||
|
||||
if (["products", "services", "hourrates"].includes(resource)) {
|
||||
await recalculateServicePricesForTenant(server, tenantId, userId);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user