498 lines
17 KiB
TypeScript
498 lines
17 KiB
TypeScript
'use server';
|
|
|
|
import { revalidatePath } from 'next/cache';
|
|
|
|
import { z } from 'zod';
|
|
|
|
import { authActionClient } from '@kit/next/safe-action';
|
|
import { todayISO } from '@kit/shared/dates';
|
|
import { getLogger } from '@kit/shared/logger';
|
|
import { getSupabaseServerClient } from '@kit/supabase/server-client';
|
|
|
|
import {
|
|
CreateMemberClubSchema,
|
|
UpdateMemberClubSchema,
|
|
CreateClubContactSchema,
|
|
UpdateClubContactSchema,
|
|
CreateClubRoleSchema,
|
|
CreateAssociationTypeSchema,
|
|
CreateClubFeeTypeSchema,
|
|
CreateClubFeeBillingSchema,
|
|
CreateClubNoteSchema,
|
|
CreateAssociationHistorySchema,
|
|
} from '../../schema/verband.schema';
|
|
import { createVerbandApi } from '../api';
|
|
|
|
const REVALIDATE_PATH = '/home/[account]/verband';
|
|
|
|
// =====================================================
|
|
// Clubs (Vereine)
|
|
// =====================================================
|
|
|
|
export const createClub = authActionClient
|
|
.inputSchema(CreateMemberClubSchema)
|
|
.action(async ({ parsedInput: input, ctx }) => {
|
|
const client = getSupabaseServerClient();
|
|
const logger = await getLogger();
|
|
const api = createVerbandApi(client);
|
|
const userId = ctx.user.id;
|
|
|
|
logger.info({ name: 'verband.club.create' }, 'Creating club...');
|
|
const result = await api.createClub(input, userId);
|
|
logger.info({ name: 'verband.club.create' }, 'Club created');
|
|
revalidatePath(REVALIDATE_PATH, 'page');
|
|
return { success: true, data: result };
|
|
});
|
|
|
|
export const updateClub = authActionClient
|
|
.inputSchema(UpdateMemberClubSchema)
|
|
.action(async ({ parsedInput: input, ctx }) => {
|
|
const client = getSupabaseServerClient();
|
|
const logger = await getLogger();
|
|
const api = createVerbandApi(client);
|
|
const userId = ctx.user.id;
|
|
|
|
logger.info({ name: 'verband.club.update' }, 'Updating club...');
|
|
const result = await api.updateClub(input, userId);
|
|
logger.info({ name: 'verband.club.update' }, 'Club updated');
|
|
revalidatePath(REVALIDATE_PATH, 'page');
|
|
return { success: true, data: result };
|
|
});
|
|
|
|
export const archiveClub = authActionClient
|
|
.inputSchema(
|
|
z.object({
|
|
clubId: z.string().uuid(),
|
|
accountId: z.string().uuid(),
|
|
}),
|
|
)
|
|
.action(async ({ parsedInput: input }) => {
|
|
const client = getSupabaseServerClient();
|
|
const logger = await getLogger();
|
|
const api = createVerbandApi(client);
|
|
|
|
logger.info({ name: 'verband.club.archive' }, 'Archiving club...');
|
|
await api.archiveClub(input.clubId);
|
|
logger.info({ name: 'verband.club.archive' }, 'Club archived');
|
|
revalidatePath(REVALIDATE_PATH, 'page');
|
|
return { success: true };
|
|
});
|
|
|
|
// =====================================================
|
|
// Contacts (Ansprechpartner)
|
|
// =====================================================
|
|
|
|
export const createContact = authActionClient
|
|
.inputSchema(CreateClubContactSchema)
|
|
.action(async ({ parsedInput: input }) => {
|
|
const client = getSupabaseServerClient();
|
|
const logger = await getLogger();
|
|
const api = createVerbandApi(client);
|
|
|
|
logger.info({ name: 'verband.contact.create' }, 'Creating contact...');
|
|
const result = await api.createContact(input);
|
|
logger.info({ name: 'verband.contact.create' }, 'Contact created');
|
|
revalidatePath(REVALIDATE_PATH, 'page');
|
|
return { success: true, data: result };
|
|
});
|
|
|
|
export const updateContact = authActionClient
|
|
.inputSchema(UpdateClubContactSchema)
|
|
.action(async ({ parsedInput: input }) => {
|
|
const client = getSupabaseServerClient();
|
|
const logger = await getLogger();
|
|
const api = createVerbandApi(client);
|
|
|
|
logger.info({ name: 'verband.contact.update' }, 'Updating contact...');
|
|
const result = await api.updateContact(input);
|
|
logger.info({ name: 'verband.contact.update' }, 'Contact updated');
|
|
revalidatePath(REVALIDATE_PATH, 'page');
|
|
return { success: true, data: result };
|
|
});
|
|
|
|
export const deleteContact = authActionClient
|
|
.inputSchema(
|
|
z.object({
|
|
contactId: z.string().uuid(),
|
|
}),
|
|
)
|
|
.action(async ({ parsedInput: input }) => {
|
|
const client = getSupabaseServerClient();
|
|
const logger = await getLogger();
|
|
const api = createVerbandApi(client);
|
|
|
|
logger.info({ name: 'verband.contact.delete' }, 'Deleting contact...');
|
|
await api.deleteContact(input.contactId);
|
|
logger.info({ name: 'verband.contact.delete' }, 'Contact deleted');
|
|
revalidatePath(REVALIDATE_PATH, 'page');
|
|
return { success: true };
|
|
});
|
|
|
|
// =====================================================
|
|
// Roles (Funktionen)
|
|
// =====================================================
|
|
|
|
export const createRole = authActionClient
|
|
.inputSchema(CreateClubRoleSchema)
|
|
.action(async ({ parsedInput: input }) => {
|
|
const client = getSupabaseServerClient();
|
|
const logger = await getLogger();
|
|
const api = createVerbandApi(client);
|
|
|
|
logger.info({ name: 'verband.role.create' }, 'Creating role...');
|
|
const result = await api.createRole(input);
|
|
logger.info({ name: 'verband.role.create' }, 'Role created');
|
|
revalidatePath(REVALIDATE_PATH, 'page');
|
|
return { success: true, data: result };
|
|
});
|
|
|
|
export const updateRole = authActionClient
|
|
.inputSchema(
|
|
z.object({
|
|
roleId: z.string().uuid(),
|
|
name: z.string().min(1).max(128).optional(),
|
|
description: z.string().max(512).optional(),
|
|
sortOrder: z.number().int().optional(),
|
|
}),
|
|
)
|
|
.action(async ({ parsedInput: input }) => {
|
|
const client = getSupabaseServerClient();
|
|
const logger = await getLogger();
|
|
const api = createVerbandApi(client);
|
|
|
|
const { roleId, ...updates } = input;
|
|
logger.info({ name: 'verband.role.update' }, 'Updating role...');
|
|
const result = await api.updateRole(roleId, updates);
|
|
logger.info({ name: 'verband.role.update' }, 'Role updated');
|
|
revalidatePath(REVALIDATE_PATH, 'page');
|
|
return { success: true, data: result };
|
|
});
|
|
|
|
export const deleteRole = authActionClient
|
|
.inputSchema(
|
|
z.object({
|
|
roleId: z.string().uuid(),
|
|
}),
|
|
)
|
|
.action(async ({ parsedInput: input }) => {
|
|
const client = getSupabaseServerClient();
|
|
const logger = await getLogger();
|
|
const api = createVerbandApi(client);
|
|
|
|
logger.info({ name: 'verband.role.delete' }, 'Deleting role...');
|
|
await api.deleteRole(input.roleId);
|
|
logger.info({ name: 'verband.role.delete' }, 'Role deleted');
|
|
revalidatePath(REVALIDATE_PATH, 'page');
|
|
return { success: true };
|
|
});
|
|
|
|
// =====================================================
|
|
// Association Types (Vereinstypen)
|
|
// =====================================================
|
|
|
|
export const createAssociationType = authActionClient
|
|
.inputSchema(CreateAssociationTypeSchema)
|
|
.action(async ({ parsedInput: input }) => {
|
|
const client = getSupabaseServerClient();
|
|
const logger = await getLogger();
|
|
const api = createVerbandApi(client);
|
|
|
|
logger.info(
|
|
{ name: 'verband.type.create' },
|
|
'Creating association type...',
|
|
);
|
|
const result = await api.createType(input);
|
|
logger.info({ name: 'verband.type.create' }, 'Association type created');
|
|
revalidatePath(REVALIDATE_PATH, 'page');
|
|
return { success: true, data: result };
|
|
});
|
|
|
|
export const updateAssociationType = authActionClient
|
|
.inputSchema(
|
|
z.object({
|
|
typeId: z.string().uuid(),
|
|
name: z.string().min(1).max(128).optional(),
|
|
description: z.string().max(512).optional(),
|
|
sortOrder: z.number().int().optional(),
|
|
}),
|
|
)
|
|
.action(async ({ parsedInput: input }) => {
|
|
const client = getSupabaseServerClient();
|
|
const logger = await getLogger();
|
|
const api = createVerbandApi(client);
|
|
|
|
const { typeId, ...updates } = input;
|
|
logger.info(
|
|
{ name: 'verband.type.update' },
|
|
'Updating association type...',
|
|
);
|
|
const result = await api.updateType(typeId, updates);
|
|
logger.info({ name: 'verband.type.update' }, 'Association type updated');
|
|
revalidatePath(REVALIDATE_PATH, 'page');
|
|
return { success: true, data: result };
|
|
});
|
|
|
|
export const deleteAssociationType = authActionClient
|
|
.inputSchema(
|
|
z.object({
|
|
typeId: z.string().uuid(),
|
|
}),
|
|
)
|
|
.action(async ({ parsedInput: input }) => {
|
|
const client = getSupabaseServerClient();
|
|
const logger = await getLogger();
|
|
const api = createVerbandApi(client);
|
|
|
|
logger.info(
|
|
{ name: 'verband.type.delete' },
|
|
'Deleting association type...',
|
|
);
|
|
await api.deleteType(input.typeId);
|
|
logger.info({ name: 'verband.type.delete' }, 'Association type deleted');
|
|
revalidatePath(REVALIDATE_PATH, 'page');
|
|
return { success: true };
|
|
});
|
|
|
|
// =====================================================
|
|
// Fee Types (Beitragsarten)
|
|
// =====================================================
|
|
|
|
export const createFeeType = authActionClient
|
|
.inputSchema(CreateClubFeeTypeSchema)
|
|
.action(async ({ parsedInput: input }) => {
|
|
const client = getSupabaseServerClient();
|
|
const logger = await getLogger();
|
|
const api = createVerbandApi(client);
|
|
|
|
logger.info({ name: 'verband.feeType.create' }, 'Creating fee type...');
|
|
const result = await api.createFeeType(input);
|
|
logger.info({ name: 'verband.feeType.create' }, 'Fee type created');
|
|
revalidatePath(REVALIDATE_PATH, 'page');
|
|
return { success: true, data: result };
|
|
});
|
|
|
|
export const updateFeeType = authActionClient
|
|
.inputSchema(
|
|
z.object({
|
|
feeTypeId: z.string().uuid(),
|
|
name: z.string().min(1).max(128).optional(),
|
|
description: z.string().max(512).optional(),
|
|
defaultAmount: z.number().min(0).optional(),
|
|
isActive: z.boolean().optional(),
|
|
}),
|
|
)
|
|
.action(async ({ parsedInput: input }) => {
|
|
const client = getSupabaseServerClient();
|
|
const logger = await getLogger();
|
|
const api = createVerbandApi(client);
|
|
|
|
const { feeTypeId, ...updates } = input;
|
|
logger.info({ name: 'verband.feeType.update' }, 'Updating fee type...');
|
|
const result = await api.updateFeeType(feeTypeId, updates);
|
|
logger.info({ name: 'verband.feeType.update' }, 'Fee type updated');
|
|
revalidatePath(REVALIDATE_PATH, 'page');
|
|
return { success: true, data: result };
|
|
});
|
|
|
|
export const deleteFeeType = authActionClient
|
|
.inputSchema(
|
|
z.object({
|
|
feeTypeId: z.string().uuid(),
|
|
}),
|
|
)
|
|
.action(async ({ parsedInput: input }) => {
|
|
const client = getSupabaseServerClient();
|
|
const logger = await getLogger();
|
|
const api = createVerbandApi(client);
|
|
|
|
logger.info({ name: 'verband.feeType.delete' }, 'Deleting fee type...');
|
|
await api.deleteFeeType(input.feeTypeId);
|
|
logger.info({ name: 'verband.feeType.delete' }, 'Fee type deleted');
|
|
revalidatePath(REVALIDATE_PATH, 'page');
|
|
return { success: true };
|
|
});
|
|
|
|
// =====================================================
|
|
// Fee Billings (Beitragsabrechnungen)
|
|
// =====================================================
|
|
|
|
export const createFeeBilling = authActionClient
|
|
.inputSchema(CreateClubFeeBillingSchema)
|
|
.action(async ({ parsedInput: input }) => {
|
|
const client = getSupabaseServerClient();
|
|
const logger = await getLogger();
|
|
const api = createVerbandApi(client);
|
|
|
|
logger.info({ name: 'verband.billing.create' }, 'Creating fee billing...');
|
|
const result = await api.createFeeBilling(input);
|
|
logger.info({ name: 'verband.billing.create' }, 'Fee billing created');
|
|
revalidatePath(REVALIDATE_PATH, 'page');
|
|
return { success: true, data: result };
|
|
});
|
|
|
|
export const updateFeeBilling = authActionClient
|
|
.inputSchema(
|
|
CreateClubFeeBillingSchema.partial().extend({
|
|
billingId: z.string().uuid(),
|
|
}),
|
|
)
|
|
.action(async ({ parsedInput: input }) => {
|
|
const client = getSupabaseServerClient();
|
|
const logger = await getLogger();
|
|
const api = createVerbandApi(client);
|
|
|
|
const { billingId, ...updates } = input;
|
|
logger.info({ name: 'verband.billing.update' }, 'Updating fee billing...');
|
|
const result = await api.updateFeeBilling(billingId, updates);
|
|
logger.info({ name: 'verband.billing.update' }, 'Fee billing updated');
|
|
revalidatePath(REVALIDATE_PATH, 'page');
|
|
return { success: true, data: result };
|
|
});
|
|
|
|
export const deleteFeeBilling = authActionClient
|
|
.inputSchema(
|
|
z.object({
|
|
billingId: z.string().uuid(),
|
|
}),
|
|
)
|
|
.action(async ({ parsedInput: input }) => {
|
|
const client = getSupabaseServerClient();
|
|
const logger = await getLogger();
|
|
const api = createVerbandApi(client);
|
|
|
|
logger.info({ name: 'verband.billing.delete' }, 'Deleting fee billing...');
|
|
await api.deleteFeeBilling(input.billingId);
|
|
logger.info({ name: 'verband.billing.delete' }, 'Fee billing deleted');
|
|
revalidatePath(REVALIDATE_PATH, 'page');
|
|
return { success: true };
|
|
});
|
|
|
|
export const markBillingPaid = authActionClient
|
|
.inputSchema(
|
|
z.object({
|
|
billingId: z.string().uuid(),
|
|
paidDate: z.string().optional(),
|
|
paymentMethod: z.string().optional(),
|
|
}),
|
|
)
|
|
.action(async ({ parsedInput: input }) => {
|
|
const client = getSupabaseServerClient();
|
|
const logger = await getLogger();
|
|
const api = createVerbandApi(client);
|
|
|
|
logger.info(
|
|
{ name: 'verband.billing.markPaid' },
|
|
'Marking billing as paid...',
|
|
);
|
|
const result = await api.updateFeeBilling(input.billingId, {
|
|
status: 'bezahlt',
|
|
paidDate: input.paidDate ?? todayISO(),
|
|
paymentMethod: input.paymentMethod as
|
|
| 'bar'
|
|
| 'lastschrift'
|
|
| 'ueberweisung'
|
|
| 'paypal'
|
|
| undefined,
|
|
});
|
|
logger.info({ name: 'verband.billing.markPaid' }, 'Billing marked as paid');
|
|
revalidatePath(REVALIDATE_PATH, 'page');
|
|
return { success: true, data: result };
|
|
});
|
|
|
|
// =====================================================
|
|
// Notes (Notizen / Aufgaben)
|
|
// =====================================================
|
|
|
|
export const createClubNote = authActionClient
|
|
.inputSchema(CreateClubNoteSchema)
|
|
.action(async ({ parsedInput: input }) => {
|
|
const client = getSupabaseServerClient();
|
|
const logger = await getLogger();
|
|
const api = createVerbandApi(client);
|
|
|
|
logger.info({ name: 'verband.note.create' }, 'Creating note...');
|
|
const result = await api.createNote(input);
|
|
logger.info({ name: 'verband.note.create' }, 'Note created');
|
|
revalidatePath(REVALIDATE_PATH, 'page');
|
|
return { success: true, data: result };
|
|
});
|
|
|
|
export const updateClubNote = authActionClient
|
|
.inputSchema(
|
|
CreateClubNoteSchema.partial().extend({
|
|
noteId: z.string().uuid(),
|
|
}),
|
|
)
|
|
.action(async ({ parsedInput: input }) => {
|
|
const client = getSupabaseServerClient();
|
|
const logger = await getLogger();
|
|
const api = createVerbandApi(client);
|
|
|
|
const { noteId, ...updates } = input;
|
|
logger.info({ name: 'verband.note.update' }, 'Updating note...');
|
|
const result = await api.updateNote(noteId, updates);
|
|
logger.info({ name: 'verband.note.update' }, 'Note updated');
|
|
revalidatePath(REVALIDATE_PATH, 'page');
|
|
return { success: true, data: result };
|
|
});
|
|
|
|
export const completeClubNote = authActionClient
|
|
.inputSchema(
|
|
z.object({
|
|
noteId: z.string().uuid(),
|
|
}),
|
|
)
|
|
.action(async ({ parsedInput: input }) => {
|
|
const client = getSupabaseServerClient();
|
|
const logger = await getLogger();
|
|
const api = createVerbandApi(client);
|
|
|
|
logger.info({ name: 'verband.note.complete' }, 'Completing note...');
|
|
const result = await api.completeNote(input.noteId);
|
|
logger.info({ name: 'verband.note.complete' }, 'Note completed');
|
|
revalidatePath(REVALIDATE_PATH, 'page');
|
|
return { success: true, data: result };
|
|
});
|
|
|
|
export const deleteClubNote = authActionClient
|
|
.inputSchema(
|
|
z.object({
|
|
noteId: z.string().uuid(),
|
|
}),
|
|
)
|
|
.action(async ({ parsedInput: input }) => {
|
|
const client = getSupabaseServerClient();
|
|
const logger = await getLogger();
|
|
const api = createVerbandApi(client);
|
|
|
|
logger.info({ name: 'verband.note.delete' }, 'Deleting note...');
|
|
await api.deleteNote(input.noteId);
|
|
logger.info({ name: 'verband.note.delete' }, 'Note deleted');
|
|
revalidatePath(REVALIDATE_PATH, 'page');
|
|
return { success: true };
|
|
});
|
|
|
|
// =====================================================
|
|
// Association History (Verbandshistorie)
|
|
// =====================================================
|
|
|
|
export const upsertAssociationHistory = authActionClient
|
|
.inputSchema(CreateAssociationHistorySchema)
|
|
.action(async ({ parsedInput: input }) => {
|
|
const client = getSupabaseServerClient();
|
|
const logger = await getLogger();
|
|
const api = createVerbandApi(client);
|
|
|
|
logger.info(
|
|
{ name: 'verband.history.upsert' },
|
|
'Upserting association history...',
|
|
);
|
|
const result = await api.upsertHistory(input);
|
|
logger.info(
|
|
{ name: 'verband.history.upsert' },
|
|
'Association history upserted',
|
|
);
|
|
revalidatePath(REVALIDATE_PATH, 'page');
|
|
return { success: true, data: result };
|
|
});
|