diff --git a/api/prisma/migrations/20240218163639_add_commentfield_to_anmeldung/migration.sql b/api/prisma/migrations/20240218163639_add_commentfield_to_anmeldung/migration.sql new file mode 100644 index 00000000..b8879afe --- /dev/null +++ b/api/prisma/migrations/20240218163639_add_commentfield_to_anmeldung/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Anmeldung" ADD COLUMN "comment" TEXT; diff --git a/api/prisma/schema.prisma b/api/prisma/schema.prisma index 441d5a26..43655702 100644 --- a/api/prisma/schema.prisma +++ b/api/prisma/schema.prisma @@ -208,6 +208,7 @@ model Anmeldung { mahlzeiten Mahlzeit[] uebernachtungsTage DateTime[] @db.Date tshirtBestellt Boolean @default(false) + comment String? createdAt DateTime @default(now()) } diff --git a/api/prisma/seeders/anmeldungen.ts b/api/prisma/seeders/anmeldungen.ts index 04aa6e48..fffef22c 100644 --- a/api/prisma/seeders/anmeldungen.ts +++ b/api/prisma/seeders/anmeldungen.ts @@ -69,6 +69,7 @@ async function create(prisma: PrismaClient, unterveranstaltung: Unterveranstaltu status: faker.helpers.enumValue(AnmeldungStatus), tshirtBestellt: faker.datatype.boolean(), personId: person.id, + comment: faker.lorem.sentence(), }, select: { id: true, diff --git a/api/src/services/account/accountGliederungAdminCreate.ts b/api/src/services/account/accountGliederungAdminCreate.ts index abd05e5f..20ccf27f 100644 --- a/api/src/services/account/accountGliederungAdminCreate.ts +++ b/api/src/services/account/accountGliederungAdminCreate.ts @@ -30,21 +30,6 @@ export const accountGliederungAdminCreateProcedure = defineProcedure({ protection: { type: 'public' }, inputSchema: ZAccountGliederungAdminCreateInput, async handler(options) { - const gliederung = await prisma.gliederung.findUniqueOrThrow({ - where: { - id: options.input.data.adminInGliederungId, - }, - select: { - id: true, - GliederungToAccount: { - select: { - accountId: true, - role: true, - }, - }, - }, - }) - let dlrgOauthId: undefined | string = undefined // check if jwtOAuthToken set and if so, check if it is valid // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions @@ -56,12 +41,6 @@ export const accountGliederungAdminCreateProcedure = defineProcedure({ dlrgOauthId = jwtOAuthTokenPayload.sub } - if (gliederung.GliederungToAccount.filter((relation) => relation.role === 'DELEGATIONSLEITER').length > 0) { - throw new TRPCError({ - code: 'FORBIDDEN', - message: 'Gliederung hat bereits einen Admin', - }) - } // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions if (!options.input.data.email) { throw new TRPCError({ diff --git a/api/src/services/account/accountVerwaltungPatch.ts b/api/src/services/account/accountVerwaltungPatch.ts index a2438df2..45c1b57a 100644 --- a/api/src/services/account/accountVerwaltungPatch.ts +++ b/api/src/services/account/accountVerwaltungPatch.ts @@ -3,6 +3,8 @@ import z from 'zod' import prisma from '../../prisma' import { defineProcedure } from '../../types/defineProcedure' +import logActivity from '../../util/activity' +import { sendMail } from '../../util/mail' export const accountVerwaltungPatchProcedure = defineProcedure({ key: 'verwaltungPatch', @@ -17,14 +19,49 @@ export const accountVerwaltungPatchProcedure = defineProcedure({ }), }), async handler(options) { - return prisma.account.update({ + const oldAccount = await prisma.account.findUniqueOrThrow({ + where: { + id: options.input.id, + }, + select: { + status: true, + }, + }) + + const account = await prisma.account.update({ where: { id: options.input.id, }, data: options.input.data, select: { id: true, + status: true, + email: true, + person: { + select: { + firstname: true, + lastname: true, + }, + }, }, }) + + if (oldAccount.status !== account.status) { + await logActivity({ + type: 'UPDATE', + description: `Account Status geändert auf ${account.status}`, + subjectType: 'account', + subjectId: account.id, + causerId: options.ctx.accountId, + }) + await sendMail({ + to: account.email, + subject: `Account ${account.status}`, + categories: ['account', 'status'], + html: `Hallo ${account.person.firstname} ${account.person.lastname},\n\n\nDein Accountstatus wurde auf ${account.status} geändert.\n\nViele Grüße,\nDein Orga-Team`, + }) + } + + return account }, }) diff --git a/api/src/services/anmeldung/anmeldungPublicCreate.ts b/api/src/services/anmeldung/anmeldungPublicCreate.ts index b5b2f0b0..02efa11f 100644 --- a/api/src/services/anmeldung/anmeldungPublicCreate.ts +++ b/api/src/services/anmeldung/anmeldungPublicCreate.ts @@ -17,6 +17,7 @@ export const anmeldungPublicCreateProcedure = defineProcedure({ uebernachtungsTage: z.array(z.date()).optional(), tshirtBestellt: z.boolean().optional(), email: z.string().email(), + comment: z.string().optional(), }), }), async handler(options) { @@ -52,6 +53,7 @@ export const anmeldungPublicCreateProcedure = defineProcedure({ : undefined, uebernachtungsTage: options.input.data.uebernachtungsTage, tshirtBestellt: options.input.data.tshirtBestellt, + comment: options.input.data.comment, createdAt: new Date(), }, }, diff --git a/chart/brahmsee-digital/templates/deployment-app.yaml b/chart/brahmsee-digital/templates/deployment-app.yaml index 73d2ba1d..4835a33b 100644 --- a/chart/brahmsee-digital/templates/deployment-app.yaml +++ b/chart/brahmsee-digital/templates/deployment-app.yaml @@ -55,6 +55,16 @@ spec: name: postgres key: uri + + # Meilisearch + - name: MEILISEARCH_HOST + value: {{ .Chart.Name }}-meilisearch-svc:7700 + - name: MEILISEARCH_KEY + valueFrom: + secretKeyRef: + name: meilisearch + key: key + # readinessProbe: # httpGet: # path: /ready diff --git a/chart/brahmsee-digital/templates/secrets.yaml b/chart/brahmsee-digital/templates/secrets.yaml index c620139f..67ea532f 100644 --- a/chart/brahmsee-digital/templates/secrets.yaml +++ b/chart/brahmsee-digital/templates/secrets.yaml @@ -32,7 +32,7 @@ stringData: --- apiVersion: v1 data: - key: {{ .Values.api.meilisearch.key | b64enc }} + key: {{ .Values.app.meilisearch.key | b64enc }} kind: Secret metadata: name: meilisearch diff --git a/frontend/src/components/BasicInputs/BasicTextArea.vue b/frontend/src/components/BasicInputs/BasicTextArea.vue index 6c238b33..6aefa82d 100644 --- a/frontend/src/components/BasicInputs/BasicTextArea.vue +++ b/frontend/src/components/BasicInputs/BasicTextArea.vue @@ -8,10 +8,12 @@ const props = withDefaults( defineProps< BasicInputDefaultProps & { cols?: number + rows?: number } >(), { cols: 3, + rows: 3, } ) const emit = defineEmits<{ @@ -33,6 +35,7 @@ const { model, errorMessage } = useValidationModel(props, emit) v-model="model" :name="id || name || label" :cols="cols" + :rows="rows" :placeholder="placeholder || label || name" :rules="rules" /> diff --git a/frontend/src/components/UIComponents/VeranstaltungCard.vue b/frontend/src/components/UIComponents/VeranstaltungCard.vue index 5fcdfb4b..df26ac45 100644 --- a/frontend/src/components/UIComponents/VeranstaltungCard.vue +++ b/frontend/src/components/UIComponents/VeranstaltungCard.vue @@ -2,10 +2,16 @@ import Badge from './Badge.vue' import Button from './Button.vue' +import { formatDate } from '@codeanker/helpers' + interface Props { veranstaltung: { id: number name: string + beginn: Date + ende: Date + + maxTeilnehmende: number } hasUnterveranstaltungen?: number } @@ -21,10 +27,14 @@ const { veranstaltung } = defineProps()

{{ veranstaltung.name }}

-

Beschreibung der Veranstaltung

+ +

+ vom {{ formatDate(veranstaltung.beginn) }} bis + {{ formatDate(veranstaltung.ende) }} +

- 10 - /500 Plätzen + + Insgesamt {{ veranstaltung.maxTeilnehmende }} Plätze

Ausschreibung erstellt - - diff --git a/frontend/src/components/forms/person/FormPersonGeneral.vue b/frontend/src/components/forms/person/FormPersonGeneral.vue index 2f54c5b3..dab2652f 100644 --- a/frontend/src/components/forms/person/FormPersonGeneral.vue +++ b/frontend/src/components/forms/person/FormPersonGeneral.vue @@ -16,6 +16,7 @@ import FormTShirtBestellungGeneral from './FormTShirtBestellungGeneral.vue' import { apiClient } from '@/api' import BasicCheckbox from '@/components/BasicInputs/BasicCheckbox.vue' +import BasicTextArea from '@/components/BasicInputs/BasicTextArea.vue' import BasicTypeahead from '@/components/BasicInputs/BasicTypeahead.vue' import Button from '@/components/UIComponents/Button.vue' import Loading from '@/components/UIComponents/Loading.vue' @@ -32,6 +33,7 @@ export interface FormPersonGeneralSubmit { essgewohnheiten: IEssgewohnheiten tshirt: ITShirtBestellung gliederung: Gliederung + comment: string } type Person = Awaited @@ -90,6 +92,8 @@ const essgewohnheitenForm = ref({ weitereIntoleranzen: props.person?.weitereIntoleranzen ?? [], }) +const comment = ref('') + const tshirtForm = ref({ bestellen: false, groesse: props.person?.konfektionsgroesse ?? 'JUNIOR_122_128', @@ -109,6 +113,7 @@ const submit = () => { essgewohnheiten: essgewohnheitenForm.value, notfallKontakte: notfallKontakteForm.value, tshirt: tshirtForm.value, + comment: comment.value, }) } @@ -144,6 +149,13 @@ const submit = () => {
+ +
+