diff --git a/appinfo/routes.php b/appinfo/routes.php index 34334e4..6f46037 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -25,6 +25,7 @@ 'klanten' => ['url' => 'api/klanten'], 'berichten' => ['url' => 'api/berichten'], 'contactmomenten' => ['url' => 'api/contactmomenten'], + 'medewerkers' => ['url' => 'api/medewerkers'], ], 'routes' => [ diff --git a/lib/Controller/MedewerkersController.php b/lib/Controller/MedewerkersController.php new file mode 100644 index 0000000..751d052 --- /dev/null +++ b/lib/Controller/MedewerkersController.php @@ -0,0 +1,134 @@ +request->getParams(); + + // Fetch employees based on filters and order + $data = $this->objectService->getResultArrayForRequest('medewerkers', $requestParams); + + // Return JSON response + return new JSONResponse($data); + } + + /** + * Read a single employee + * + * @NoAdminRequired + * @NoCSRFRequired + * + * @return JSONResponse + */ + public function show(string $id): JSONResponse + { + // Fetch the employee by its ID + $object = $this->objectService->getObject('medewerkers', $id); + + // Return the employee as a JSON response + return new JSONResponse($object); + } + + /** + * Create an employee + * + * @NoAdminRequired + * @NoCSRFRequired + * + * @return JSONResponse + */ + public function create(): JSONResponse + { + // Get all parameters from the request + $data = $this->request->getParams(); + + // Remove the 'id' field if it exists, as we're creating a new employee + unset($data['id']); + + // Save the new employee + $object = $this->objectService->saveObject('medewerkers', $data); + + // Return the created employee as a JSON response + return new JSONResponse($object); + } + + /** + * Update an employee + * + * @NoAdminRequired + * @NoCSRFRequired + * + * @return JSONResponse + */ + public function update(string $id): JSONResponse + { + // Get all parameters from the request + $data = $this->request->getParams(); + + // Save the updated employee + $object = $this->objectService->saveObject('medewerkers', $data); + + // Return the updated employee as a JSON response + return new JSONResponse($object); + } + + /** + * Delete an employee + * + * @NoAdminRequired + * @NoCSRFRequired + * + * @return JSONResponse + */ + public function destroy(string $id): JSONResponse + { + // Delete the employee + $result = $this->objectService->deleteObject('medewerkers', $id); + + // Return the result as a JSON response + return new JSONResponse(['success' => $result], $result === true ? '200' : '404'); + } + + /** + * Get audit trail for a specific employee + * + * @NoAdminRequired + * @NoCSRFRequired + * + * @return JSONResponse + */ + public function getAuditTrail(string $id): JSONResponse + { + $auditTrail = $this->objectService->getAuditTrail('medewerkers', $id); + return new JSONResponse($auditTrail); + } +} diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php index 20c8f27..31f7270 100644 --- a/lib/Controller/SettingsController.php +++ b/lib/Controller/SettingsController.php @@ -45,7 +45,7 @@ public function index(): JSONResponse { // Initialize the data array $data = []; - $data['objectTypes'] = ['berichten', 'besluiten', 'documenten', 'klanten', 'resultaten', 'taken', 'informatieobjecten', 'organisaties', 'personen', 'zaken', 'rollen', 'statusen', 'zaakeigenschappen', 'zaaktypen','contactmomenten']; + $data['objectTypes'] = ['berichten', 'besluiten', 'documenten', 'klanten', 'resultaten', 'taken', 'informatieobjecten', 'organisaties', 'personen', 'zaken', 'rollen', 'statusen', 'zaakeigenschappen', 'zaaktypen','contactmomenten', 'medewerkers']; $data['openRegisters'] = false; $data['availableRegisters'] = []; @@ -102,7 +102,10 @@ public function index(): JSONResponse 'zaaktypen_register' => '', 'contactmomenten_source' => 'internal', 'contactmomenten_schema' => '', - 'contactmomenten_register' => '' + 'contactmomenten_register' => '', + 'medewerkers_source' => 'internal', + 'medewerkers_schema' => '', + 'medewerkers_register' => '' ]; // Get the current values for the object types from the configuration diff --git a/src/entities/index.js b/src/entities/index.js index 6f68388..0b8f0bc 100644 --- a/src/entities/index.js +++ b/src/entities/index.js @@ -5,4 +5,5 @@ export * from './klanten/index.js' export * from './taak/index.js' export * from './bericht/index.js' export * from './rol/index.js' +export * from './medewerkers/index.js' export * from './contactmoment/index.js' diff --git a/src/entities/klanten/klanten.mock.ts b/src/entities/klanten/klanten.mock.ts index 842277e..95f3d62 100644 --- a/src/entities/klanten/klanten.mock.ts +++ b/src/entities/klanten/klanten.mock.ts @@ -10,7 +10,7 @@ export const mockKlantData = (): TKlant[] => [ achternaam: 'Doe', bsn: '1234567890', geboortedatum: '1990-01-01', - isMale: true, + geslacht: 'man', land: 'Nederland', telefoonnummer: '0612345678', emailadres: 'john.doe@example.com', diff --git a/src/entities/klanten/klanten.ts b/src/entities/klanten/klanten.ts index b3f7c4e..aa02342 100644 --- a/src/entities/klanten/klanten.ts +++ b/src/entities/klanten/klanten.ts @@ -11,7 +11,7 @@ export class Klant implements TKlant { public achternaam: string public bsn: string public geboortedatum: string - public isMale: boolean + public geslacht: "man" | "vrouw" | "overige" public land: string public telefoonnummer: string @@ -42,7 +42,7 @@ export class Klant implements TKlant { this.achternaam = source.achternaam || '' this.bsn = source.bsn || '' this.geboortedatum = source.geboortedatum || '' - this.isMale = source.isMale || false + this.geslacht = source.geslacht || null this.land = source.land || '' this.telefoonnummer = source.telefoonnummer || '' this.emailadres = source.emailadres || '' @@ -71,7 +71,7 @@ export class Klant implements TKlant { achternaam: z.string(), bsn: z.string(), geboortedatum: z.string(), - isMale: z.boolean(), + geslacht: z.enum(["man", "vrouw", "overige"]).or(z.null()), land: z.string(), telefoonnummer: z.string(), emailadres: z.string().email(), diff --git a/src/entities/klanten/klanten.types.ts b/src/entities/klanten/klanten.types.ts index 83c11bc..7d7c13b 100644 --- a/src/entities/klanten/klanten.types.ts +++ b/src/entities/klanten/klanten.types.ts @@ -8,7 +8,7 @@ export type TKlant = { achternaam: string; bsn: string; geboortedatum: string; - isMale: boolean; + geslacht: 'man' | 'vrouw' | 'overige'; land: string; telefoonnummer: string; emailadres: string; diff --git a/src/entities/medewerkers/index.js b/src/entities/medewerkers/index.js new file mode 100644 index 0000000..5e496d6 --- /dev/null +++ b/src/entities/medewerkers/index.js @@ -0,0 +1,3 @@ +export * from './medewerkers.ts' +export * from './medewerkers.types.ts' +export * from './medewerkers.mock.ts' diff --git a/src/entities/medewerkers/medewerkers.mock.ts b/src/entities/medewerkers/medewerkers.mock.ts new file mode 100644 index 0000000..5fd76c5 --- /dev/null +++ b/src/entities/medewerkers/medewerkers.mock.ts @@ -0,0 +1,14 @@ +import { Medewerker } from './medewerkers' +import { TMedewerker } from './medewerkers.types' + +export const mockMedewerkerData = (): TMedewerker[] => [ + { + id: '15551d6f-44e3-43f3-a9d2-59e583c91eb0', + voornaam: 'John', + tussenvoegsel: 'de', + achternaam: 'Doe', + email: 'john.doe@example.com', + }, +] + +export const mockMedewerker = (data: TMedewerker[] = mockMedewerkerData()): TMedewerker[] => data.map(item => new Medewerker(item)) diff --git a/src/entities/medewerkers/medewerkers.spec.ts b/src/entities/medewerkers/medewerkers.spec.ts new file mode 100644 index 0000000..0d77965 --- /dev/null +++ b/src/entities/medewerkers/medewerkers.spec.ts @@ -0,0 +1,12 @@ +import { Medewerker } from './medewerkers' +import { mockMedewerkerData } from './medewerkers.mock' + +describe('Medewerker Entity', () => { + it('should create a Medewerker entity with full data', () => { + const medewerker = new Medewerker(mockMedewerkerData()[0]) + + expect(medewerker).toBeInstanceOf(Medewerker) + expect(medewerker).toEqual(mockMedewerkerData()[0]) + expect(medewerker.validate().success).toBe(true) + }) +}) diff --git a/src/entities/medewerkers/medewerkers.ts b/src/entities/medewerkers/medewerkers.ts new file mode 100644 index 0000000..0f5eb9f --- /dev/null +++ b/src/entities/medewerkers/medewerkers.ts @@ -0,0 +1,33 @@ +import { SafeParseReturnType, z } from 'zod' +import { TMedewerker } from './medewerkers.types' + +export class Medewerker implements TMedewerker { + + public id: string + public voornaam: string + public tussenvoegsel: string + public achternaam: string + public email: string + + constructor(source: TMedewerker) { + this.id = source.id || '' + this.voornaam = source.voornaam || '' + this.tussenvoegsel = source.tussenvoegsel || '' + this.achternaam = source.achternaam || '' + this.email = source.email || '' + + } + + public validate(): SafeParseReturnType { + const schema = z.object({ + id: z.string().optional(), + voornaam: z.string().min(1), + tussenvoegsel: z.string(), + achternaam: z.string(), + email: z.string().email(), + }) + + return schema.safeParse(this) + } + +} diff --git a/src/entities/medewerkers/medewerkers.types.ts b/src/entities/medewerkers/medewerkers.types.ts new file mode 100644 index 0000000..7a50331 --- /dev/null +++ b/src/entities/medewerkers/medewerkers.types.ts @@ -0,0 +1,7 @@ +export type TMedewerker = { + id: string; + voornaam: string; + tussenvoegsel: string; + achternaam: string; + email: string; +} diff --git a/src/modals/Modals.vue b/src/modals/Modals.vue index 055d875..7cbe23d 100644 --- a/src/modals/Modals.vue +++ b/src/modals/Modals.vue @@ -12,13 +12,14 @@ import { navigationStore } from '../store/store.js' - + + @@ -37,6 +38,7 @@ import EditRol from './rollen/EditRol.vue' import ViewZaakAuditTrail from './zaken/ViewZaakAuditTrail.vue' import ViewKlantRegister from './klantRegister/ViewKlantRegister.vue' import DeleteContactMoment from './contactMomenten/DeleteContactMoment.vue' +import EditMedewerker from './medewerkers/EditMedewerker.vue' export default { name: 'Modals', components: { @@ -54,6 +56,7 @@ export default { ViewZaakAuditTrail, ViewKlantRegister, DeleteContactMoment, + EditMedewerker, }, } diff --git a/src/modals/contactMomenten/ContactMomentenForm.vue b/src/modals/contactMomenten/ContactMomentenForm.vue index 1dfafee..0db7624 100644 --- a/src/modals/contactMomenten/ContactMomentenForm.vue +++ b/src/modals/contactMomenten/ContactMomentenForm.vue @@ -1,5 +1,5 @@
@@ -180,13 +188,13 @@ import { navigationStore } from '../../store/store.js' - + - Zaak starten + Taak aanmaken - + @@ -205,6 +213,10 @@ import { navigationStore } from '../../store/store.js' Opslaan + @@ -215,6 +227,7 @@ import { NcButton, NcActions, NcLoadingIcon, NcDialog, NcTextArea, NcNoteCard, N // Forms import SearchKlantModal from '../../modals/klanten/SearchKlantModal.vue' +import TakenForm from '../../modals/taken/WidgetTaakForm.vue' // Icons import Plus from 'vue-material-design-icons/Plus.vue' @@ -248,6 +261,10 @@ export default { type: Boolean, default: false, }, + contactMomentId: { + type: String, + default: null, + }, }, data() { return { @@ -256,6 +273,8 @@ export default { error: false, titel: '', notitie: '', + status: null, + startDate: null, klantenLoading: false, zaken: [], taken: [], @@ -268,9 +287,13 @@ export default { selectedTaak: null, selectedProduct: null, startingType: 'all', + taakFormOpen: false, } }, mounted() { + if (this.contactMomentId) { + this.fetchContactMomentData(this.contactMomentId) + } }, methods: { // Modal functions @@ -302,6 +325,7 @@ export default { zaak: this.selectedZaak ?? '', taak: this.selectedTaak ?? '', product: this.selectedProduct ?? '', + status: this.status === 'gesloten' ? 'gesloten' : 'open', startDate: new Date().toISOString(), }), }, @@ -333,6 +357,30 @@ export default { this.searchKlantModalOpen = false }, + openTaakForm() { + this.taakFormOpen = true + taakStore.setTaakItem(null) + }, + + closeTaakForm() { + this.taakFormOpen = false + }, + + fetchContactMomentData(id) { + fetch(`/index.php/apps/zaakafhandelapp/api/contactmomenten/${id}`) + .then(response => response.json()) + .then(data => { + this.titel = data.titel + this.notitie = data.notitie + this.status = data.status + this.startDate = data.startDate + this.fetchKlantData(data.klant) + this.selectedZaak = data.zaak + this.selectedTaak = data.taak + this.selectedProduct = data.product + }) + }, + fetchKlantData(id) { fetch(`/index.php/apps/zaakafhandelapp/api/klanten/${id}`) .then(response => response.json()) @@ -469,4 +517,9 @@ div[class='modal-container']:has(.ContactMomentenForm) { justify-content: flex-end; gap: var(--zaa-margin-10); } + +.statusAndStartDateContainer { + display: flex; + gap: var(--zaa-margin-10); +} diff --git a/src/modals/klanten/EditKlant.vue b/src/modals/klanten/EditKlant.vue index 7f36202..34fb166 100644 --- a/src/modals/klanten/EditKlant.vue +++ b/src/modals/klanten/EditKlant.vue @@ -47,13 +47,18 @@ import { klantStore, navigationStore } from '../../store/store.js' :disabled="loading" input-label="Geboortedatum" />
- - Is een man? - + + + @@ -180,7 +185,6 @@ import { NcNoteCard, NcSelect, NcDateTimePicker, - NcCheckboxRadioSwitch, } from '@nextcloud/vue' import { countries } from '../../data/countries.js' @@ -200,7 +204,6 @@ export default { NcNoteCard, NcSelect, NcDateTimePicker, - NcCheckboxRadioSwitch, // Icons ContentSaveOutline, Cancel, @@ -226,7 +229,7 @@ export default { achternaam: '', bsn: '', geboortedatum: '', - isMale: false, + geslacht: '', land: '', telefoonnummer: '', emailadres: '', @@ -252,6 +255,13 @@ export default { { value: 'organisatie', label: 'Organisatie' }, ], }, + sexOptions: { + options: [ + { value: 'man', label: 'Man' }, + { value: 'vrouw', label: 'Vrouw' }, + { value: 'overige', label: 'Overige' }, + ], + }, } }, computed: { @@ -261,11 +271,12 @@ export default { }, updated() { if (navigationStore.modal === 'editKlant' && !this.hasUpdated) { - const klantType = this.typeOptions.options.find((option) => option.value === klantStore.klantItem?.type) const country = this.countryOptions.options.find((option) => option.id === klantStore.klantItem?.land) + const sex = this.sexOptions.options.find((option) => option.value === klantStore.klantItem?.geslacht) + if (klantStore.klantItem?.id) { this.klantItem = { ...klantStore.klantItem, @@ -275,7 +286,7 @@ export default { achternaam: klantStore.klantItem.achternaam || '', bsn: klantStore.klantItem.bsn || '', geboortedatum: klantStore.klantItem.geboortedatum ? new Date(klantStore.klantItem.geboortedatum) : '', - isMale: klantStore.klantItem.isMale || false, + geslacht: sex || { value: 'man', label: 'Man' }, land: country || '', telefoonnummer: klantStore.klantItem.telefoonnummer || '', emailadres: klantStore.klantItem.emailadres || '', @@ -313,7 +324,7 @@ export default { achternaam: '', bsn: '', geboortedatum: '', - isMale: false, + geslacht: { value: 'man', label: 'Man' }, land: '', telefoonnummer: '', emailadres: '', @@ -343,6 +354,7 @@ export default { type: this.klantItem.type.value, geboortedatum: this.klantItem.geboortedatum !== '' && new Date(this.klantItem.geboortedatum).toISOString(), land: this.klantItem.land.id, + geslacht: this.klantItem.geslacht.value, }) this.success = true this.loading = false @@ -361,7 +373,7 @@ export default { diff --git a/src/modals/klanten/SearchKlantModal.vue b/src/modals/klanten/SearchKlantModal.vue index 2f575f9..f0721b9 100644 --- a/src/modals/klanten/SearchKlantModal.vue +++ b/src/modals/klanten/SearchKlantModal.vue @@ -99,7 +99,7 @@ import { klantStore } from '../../store/store.js'
+import { medewerkerStore, navigationStore } from '../../store/store.js' + + + + + + + diff --git a/src/modals/medewerkers/SearchKlantModal.vue b/src/modals/medewerkers/SearchKlantModal.vue new file mode 100644 index 0000000..f0721b9 --- /dev/null +++ b/src/modals/medewerkers/SearchKlantModal.vue @@ -0,0 +1,381 @@ + + + + + + + + + diff --git a/src/modals/medewerkers/ViewKlantAuditTrail.vue b/src/modals/medewerkers/ViewKlantAuditTrail.vue new file mode 100644 index 0000000..f76ab55 --- /dev/null +++ b/src/modals/medewerkers/ViewKlantAuditTrail.vue @@ -0,0 +1,90 @@ + + + + + + + diff --git a/src/modals/taken/EditTaak.vue b/src/modals/taken/EditTaak.vue index 8e11757..e561a53 100644 --- a/src/modals/taken/EditTaak.vue +++ b/src/modals/taken/EditTaak.vue @@ -3,7 +3,7 @@ import { taakStore, navigationStore, klantStore } from '../../store/store.js'