Person, ContactInformation, participant: read and create

pull/14/head
leonnicolas 4 years ago
parent 9ba635d943
commit 7b48573eb3
No known key found for this signature in database
GPG Key ID: 088D0743E2B65C07

@ -2,6 +2,7 @@ import { DataSource } from 'apollo-datasource';
import { Connection, getConnection } from 'typeorm'; import { Connection, getConnection } from 'typeorm';
import { ContactInformation } from '../../model/ContactInformation'; import { ContactInformation } from '../../model/ContactInformation';
import { LendingStation } from '../../model/LendingStation'; import { LendingStation } from '../../model/LendingStation';
import { Person } from '../../model/Person';
export class ContactInformationAPI extends DataSource { export class ContactInformationAPI extends DataSource {
connection : Connection connection : Connection
@ -47,6 +48,67 @@ export class ContactInformationAPI extends DataSource {
.loadMany(); .loadMany();
} }
async createPerson (person: any) {
const inserts = await this.connection.getRepository(Person)
.createQueryBuilder('person')
.insert()
.values([person])
.returning('*')
.execute();
inserts.generatedMaps[0].id = inserts.identifiers[0].id;
return inserts.generatedMaps[0];
}
/**
* Return person by ID
* @param id
*/
async personById (id: number) {
return await this.connection.getRepository(Person)
.createQueryBuilder('person')
.select()
.where('person.id = :id', { id: id })
.getOne();
}
async persons (offset: number, limit: number) {
return await this.connection.getRepository(Person)
.createQueryBuilder('person')
.select()
.skip(offset)
.take(limit)
.execute();
}
async personByContactInformationId (id: number) {
return await this.connection.getRepository(ContactInformation)
.createQueryBuilder('ci')
.relation(ContactInformation, 'personId')
.of(id)
.loadOne();
}
async createContactInformation (contactInformation: any) {
const inserts = await this.connection.getRepository(ContactInformation)
.createQueryBuilder('contactInformation')
.insert()
.into(ContactInformation)
.values([contactInformation])
.returning('*')
.execute();
return inserts.generatedMaps[0];
}
async contactInformationByPersonId (id: number) {
const res = await this.connection.getRepository(ContactInformation)
.createQueryBuilder('ci')
.select()
.where('ci."personId" = :id', { id: id })
.getMany();
console.log(res);
return res;
}
async contactInformationByContactPersonId (id: number) { async contactInformationByContactPersonId (id: number) {
/* return (await this.connection.getRepository(ContactPerson) /* return (await this.connection.getRepository(ContactPerson)
.createQueryBuilder('contactPerson') .createQueryBuilder('contactPerson')

@ -1,10 +1,11 @@
import { DataSource } from 'apollo-datasource'; import { DataSource } from 'apollo-datasource';
import { GraphQLError } from 'graphql'; import { GraphQLError } from 'graphql';
import { Connection, getConnection } from 'typeorm'; import { Connection, EntityManager, getConnection } from 'typeorm';
import { CargoBike } from '../../model/CargoBike'; import { CargoBike } from '../../model/CargoBike';
import { ContactInformation } from '../../model/ContactInformation'; import { ContactInformation } from '../../model/ContactInformation';
import { Engagement } from '../../model/Engagement'; import { Engagement } from '../../model/Engagement';
import { Participant } from '../../model/Participant'; import { Participant } from '../../model/Participant';
import { EngagementType } from '../../model/EngagementType';
export class ParticipantAPI extends DataSource { export class ParticipantAPI extends DataSource {
connection : Connection connection : Connection
@ -78,6 +79,12 @@ export class ParticipantAPI extends DataSource {
.getOne(); .getOne();
} }
async engagementTypeByEngagementId (id: number) {
return await this.connection.getRepository(Engagement)
.createQueryBuilder('engagement')
.relation(Engagement, 'engageMent');
}
async contactInformationById (id: number) { async contactInformationById (id: number) {
return await this.connection.getRepository(ContactInformation) return await this.connection.getRepository(ContactInformation)
.createQueryBuilder('contactInformation') .createQueryBuilder('contactInformation')
@ -87,14 +94,11 @@ export class ParticipantAPI extends DataSource {
} }
async contactInformationByParticipantId (id: number) { async contactInformationByParticipantId (id: number) {
const ret = (await this.connection.getRepository(Participant) return await this.connection.manager
.createQueryBuilder('participant') .createQueryBuilder()
.leftJoinAndSelect('participant.contactInformation', 'contactInformation') .relation(Participant, 'contactInformationId')
.where('participant."contactInformationId" = "contactInformation".id') .of(id)
.andWhere('participant.id = :id', { id: id }) .loadOne();
.printSql()
.getOne());
return (ret) ? ret.contactInformation : null;
} }
/** /**
@ -102,7 +106,7 @@ export class ParticipantAPI extends DataSource {
* @param participant to be created * @param participant to be created
*/ */
async createParticipant (participant: any) { async createParticipant (participant: any) {
let count = this.connection.getRepository(ContactInformation) /* let count = this.connection.getRepository(ContactInformation)
.createQueryBuilder('contactInformation') .createQueryBuilder('contactInformation')
.select() .select()
.where('contactInformation.id = :id', { id: participant.contactInformationId }) .where('contactInformation.id = :id', { id: participant.contactInformationId })
@ -119,31 +123,37 @@ export class ParticipantAPI extends DataSource {
.getCount(); .getCount();
if ((await count) !== 0) { if ((await count) !== 0) {
return new GraphQLError('contactInformationId already used by other participant.'); return new GraphQLError('contactInformationId already used by other participant.');
} } */
const inserts = await this.connection.getRepository(Participant) let inserts: any;
await this.connection.transaction(async (entityManager: EntityManager) => {
inserts = await entityManager.getRepository(Participant)
.createQueryBuilder('participant') .createQueryBuilder('participant')
.insert() .insert()
.into(Participant) .into(Participant)
.values([participant]) .values([participant])
.returning('*') .returning('*')
.execute(); .execute();
await this.connection.getRepository(Participant) /* await entityManager.getRepository(Participant)
.createQueryBuilder('participant') .createQueryBuilder('participant')
.relation(Participant, 'contactInformation') .relation(Participant, 'contactInformation')
.of(inserts.identifiers[0].id) .of(inserts.identifiers[0].id)
.set(participant.contactInformationId); .set(participant.contactInformationId);
return this.getParticipantById(inserts.identifiers[0].id); */
} });
/* const inserts = await this.connection.getRepository(Participant)
async createContactInformation (contactInformation: any) { .createQueryBuilder('participant')
const inserts = await this.connection.getRepository(ContactInformation)
.createQueryBuilder('contactInformation')
.insert() .insert()
.into(ContactInformation) .into(Participant)
.values([contactInformation]) .values([participant])
.returning('*') .returning('*')
.execute(); .execute();
return this.contactInformationById(inserts.identifiers[0].id); await this.connection.getRepository(Participant)
.createQueryBuilder('participant')
.relation(Participant, 'contactInformation')
.of(inserts.identifiers[0].id)
.set(participant.contactInformationId);
*/
return this.getParticipantById(inserts.identifiers[0].id);
} }
async createEngagement (engagement: any) { async createEngagement (engagement: any) {
@ -166,16 +176,27 @@ export class ParticipantAPI extends DataSource {
.values([engagement]) .values([engagement])
.returning('*') .returning('*')
.execute(); .execute();
this.connection.getRepository(Engagement) await this.connection.getRepository(Engagement)
.createQueryBuilder('engagement') .createQueryBuilder('engagement')
.relation(Engagement, 'cargoBike') .relation(Engagement, 'cargoBike')
.of(inserts.identifiers[0].id) .of(inserts.identifiers[0].id)
.set(engagement.cargoBikeId); .set(engagement.cargoBikeId);
this.connection.getRepository(Engagement) await this.connection.getRepository(Engagement)
.createQueryBuilder('engagement') .createQueryBuilder('engagement')
.relation(Engagement, 'participant') .relation(Engagement, 'participant')
.of(inserts.identifiers[0].id) .of(inserts.identifiers[0].id)
.set(engagement.participantId); .set(engagement.participantId);
return this.engagementById(inserts.identifiers[0].id); return this.engagementById(inserts.identifiers[0].id);
} }
async createEngagementType (engagementType: any) {
const inserts = await this.connection.getRepository(EngagementType)
.createQueryBuilder('et')
.insert()
.values([engagementType])
.returning('*')
.execute();
inserts.generatedMaps[0].id = inserts.identifiers[0].id;
return inserts.generatedMaps[0];
}
} }

@ -3,6 +3,8 @@ export enum Permission {
ReadBike = 'BIKE_READ', ReadBike = 'BIKE_READ',
WriteBike = 'BIKE_WRITE', WriteBike = 'BIKE_WRITE',
WriteEquipmentType = 'EQUIPMENT_TYPE_WRITE', WriteEquipmentType = 'EQUIPMENT_TYPE_WRITE',
WritePerson = 'PERSON_WRITE',
ReadPerson = 'PERSON_READ'
} }
// Permissions where the creation will be requested on startup // Permissions where the creation will be requested on startup
@ -18,5 +20,13 @@ export const requiredPermissions = [
{ {
name: Permission.WriteEquipmentType, name: Permission.WriteEquipmentType,
description: 'Allows the modification of EquipmentTypes' description: 'Allows the modification of EquipmentTypes'
},
{
name: Permission.WritePerson,
description: 'Allows the modification of Persons and contact information'
},
{
name: Permission.ReadPerson,
description: 'Allows reading of contact information'
} }
]; ];

@ -1,4 +1,4 @@
import { PrimaryGeneratedColumn, Column, Entity, ManyToOne, OneToOne } from 'typeorm'; import { PrimaryGeneratedColumn, Column, Entity, ManyToOne, OneToOne, JoinColumn } from 'typeorm';
import { Lockable } from './CargoBike'; import { Lockable } from './CargoBike';
import { Person } from './Person'; import { Person } from './Person';
import { Address } from './Provider'; import { Address } from './Provider';
@ -9,13 +9,19 @@ export class ContactInformation implements Lockable {
@PrimaryGeneratedColumn() @PrimaryGeneratedColumn()
id: number; id: number;
@ManyToOne(type => Person, person => person.contactInformation) @ManyToOne(type => Person, person => person.contactInformationIds, {
person: Person; nullable: false
@OneToOne(type => Participant, participant => participant.contactInformation, { })
@JoinColumn({
name: 'personId'
})
personId: number;
@OneToOne(type => Participant, participant => participant.contactInformationId, {
nullable: true nullable: true
}) })
participant: Participant; participantId: number;
@Column(type => { @Column(type => {
return Address; return Address;

@ -21,16 +21,11 @@ export class Engagement {
@ManyToOne(type => EngagementType, engagementType => engagementType.engagementIds) @ManyToOne(type => EngagementType, engagementType => engagementType.engagementIds)
engagementTypeId: number; engagementTypeId: number;
// I have to find out how typorm will map the datetange data type.
@Column({ @Column({
type: 'date' type: 'daterange'
}) })
from: Date; dateRange: Date[];
@Column({
type: 'date',
nullable: true
})
to: Date;
@Column() @Column()
roleCoordinator: boolean; roleCoordinator: boolean;

@ -12,7 +12,8 @@ export class EngagementType implements Lockable {
@Column({ @Column({
type: 'text', type: 'text',
nullable: true nullable: false,
default: ''
}) })
description: string; description: string;

@ -10,7 +10,8 @@ export class Participant {
id: number; id: number;
@Column({ @Column({
type: 'date' type: 'date',
default: () => 'CURRENT_DATE'
}) })
start: Date; start: Date;
@ -20,11 +21,13 @@ export class Participant {
}) })
end: Date; end: Date;
@OneToOne(type => ContactInformation, contactInformation => contactInformation.participant, { @OneToOne(type => ContactInformation, contactInformation => contactInformation.participantId, {
nullable: true nullable: false
}) })
@JoinColumn() @JoinColumn({
contactInformation: ContactInformation; name: 'contactInformationId'
})
contactInformationId: number;
@Column({ @Column({
nullable: true nullable: true
@ -61,6 +64,9 @@ export class Participant {
}) })
employeeADFC: boolean; employeeADFC: boolean;
@Column() @Column({
nullable: false,
default: false
})
memberADFC: boolean; memberADFC: boolean;
} }

@ -13,8 +13,8 @@ export class Person implements Lockable {
@Column() @Column()
name: string; name: string;
@OneToMany(type => ContactInformation, contactInformation => contactInformation.person) @OneToMany(type => ContactInformation, contactInformation => contactInformation.personId)
contactInformation: ContactInformation; contactInformationIds: number[];
@Column({ @Column({
nullable: true nullable: true

@ -1,14 +1,22 @@
import { GraphQLError } from 'graphql'; import { GraphQLError } from 'graphql';
import { Permission } from '../datasources/userserver/permission'; import { Permission } from '../datasources/userserver/permission';
import { Person } from '../model/Person';
export default { export default {
Query: { Query: {
contactInformation: (_: any, { offset, limit }: { offset: number, limit: number }, { dataSources, req }: { dataSources: any, req: any }) => { contactInformation: (_: any, { offset, limit }: { offset: number, limit: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteBike)) { if (req.permissions.includes(Permission.ReadPerson)) {
return dataSources.contactInformationAPI.contactInformation(offset, limit); return dataSources.contactInformationAPI.contactInformation(offset, limit);
} else { } else {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
},
persons: (_: any, { offset, limit }: { offset: number, limit: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.ReadPerson)) {
return dataSources.contactInformationAPI.persons(offset, limit);
} else {
return new GraphQLError('Insufficient Permissions');
}
} }
}, },
ContactPerson: { ContactPerson: {
@ -20,6 +28,25 @@ export default {
} }
} }
}, },
Person: {
contactInformation: (parent: Person, __: any, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.ReadPerson)) {
return dataSources.contactInformationAPI.contactInformationByPersonId(parent.id);
} else {
return new GraphQLError('Insufficient Permissions');
}
}
},
ContactInformation: {
person: (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.ReadPerson)) {
console.log(parent);
return dataSources.contactInformationAPI.personByContactInformationId(parent.id);
} else {
return new GraphQLError('Insufficient Permissions');
}
}
},
Mutation: { Mutation: {
createContactPerson: (_: any, { contactPerson }: { contactPerson: any }, { dataSources, req }: { dataSources: any, req: any }) => { createContactPerson: (_: any, { contactPerson }: { contactPerson: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteBike)) { if (req.permissions.includes(Permission.WriteBike)) {
@ -34,6 +61,20 @@ export default {
} else { } else {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
},
createContactInformation: (_: any, { contactInformation }: { contactInformation: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteBike)) {
return dataSources.contactInformationAPI.createContactInformation(contactInformation);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
createPerson: (_: any, { person }: { person: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WritePerson)) {
return dataSources.contactInformationAPI.createPerson(person);
} else {
return new GraphQLError('Insufficient Permissions');
}
} }
} }
}; };

@ -1,5 +1,6 @@
import { GraphQLError } from 'graphql'; import { GraphQLError } from 'graphql';
import { Permission } from '../datasources/userserver/permission'; import { Permission } from '../datasources/userserver/permission';
import { EngagementType } from '../model/EngagementType';
export default { export default {
Query: { Query: {
@ -23,7 +24,7 @@ export default {
return dataSources.participantAPI.engagementByParticipantId(parent.id); return dataSources.participantAPI.engagementByParticipantId(parent.id);
}, },
contactInformation (parent: any, _: any, { dataSources, req }: { dataSources: any, req: any }) { contactInformation (parent: any, _: any, { dataSources, req }: { dataSources: any, req: any }) {
return (dataSources.contactInformationAPI.contactInformationByParticipantId(parent.id)); return (dataSources.participantAPI.contactInformationByParticipantId(parent.id));
} }
}, },
Engagement: { Engagement: {
@ -32,6 +33,17 @@ export default {
}, },
participant (parent: any, _: any, { dataSources, req }: { dataSources: any, req: any }) { participant (parent: any, _: any, { dataSources, req }: { dataSources: any, req: any }) {
return dataSources.participantAPI.participantByEngagementId(parent.id); return dataSources.participantAPI.participantByEngagementId(parent.id);
},
engagementType (parent: any, _: any, { dataSources, req }: { dataSources: any; req: any }): Promise<EngagementType> {
return dataSources.participantAPI.engagementTypeByEngagementId(parent.id);
},
from (parent: any) {
// TODO
return parent.dateRange;
},
to (parent: any) {
// TODO
return parent.dateRange;
} }
}, },
Mutation: { Mutation: {
@ -42,16 +54,16 @@ export default {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
}, },
createContactInformation: (_: any, { contactInformation }: { contactInformation: any }, { dataSources, req }: { dataSources: any, req: any }) => { createEngagement: (_: any, { engagement }: { engagement: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteBike)) { if (req.permissions.includes(Permission.WriteBike)) {
return dataSources.participantAPI.createContactInformation(contactInformation); return dataSources.participantAPI.createEngagement(engagement);
} else { } else {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
}, },
createEngagement: (_: any, { engagement }: { engagement: any }, { dataSources, req }: { dataSources: any, req: any }) => { createEngagementType: (_: any, { engagementType }: { engagementType: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteBike)) { if (req.permissions.includes(Permission.WriteBike)) {
return dataSources.participantAPI.createEngagement(engagement); return dataSources.participantAPI.createEngagementType(engagementType);
} else { } else {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }

@ -215,13 +215,8 @@ type Participant {
usernamefLotte: String usernamefLotte: String
usernameSlack: String usernameSlack: String
memberADFC: Boolean! memberADFC: Boolean!
locationZIPs: [String] locationZIPs: [String]!
memberCoreTeam: Boolean! memberCoreTeam: Boolean!
"Date of workshop to become Mentor dt. Pate"
workshopMentor: Date
"Date of last Erste Hilfe Kurs?"
workshopAmbulance: Date
""" """
Note the kommentierte Infodaten Tabelle. Note the kommentierte Infodaten Tabelle.
This value is calculated form other values. This value is calculated form other values.
@ -229,32 +224,38 @@ type Participant {
and is either Mentor dt. Pate or Partner Mentor dt. Partnerpate for at least one bike. and is either Mentor dt. Pate or Partner Mentor dt. Partnerpate for at least one bike.
""" """
distributedActiveBikeParte: Boolean! distributedActiveBikeParte: Boolean!
reserve: String
engagement: [Engagement] engagement: [Engagement]
} }
input ParticipantCreateInput { input ParticipantCreateInput {
start: Date! "if not set, CURRENT_DATE will be used"
start: Date
end: Date end: Date
"must create contactinformation first, if you want to use new" "must create contactinformation first, if you want to use new"
contactInformationId: ID! contactInformationId: ID!
usernamefLotte: String usernamefLotte: String
usernameSlack: String usernameSlack: String
"default: false"
memberADFC: Boolean! memberADFC: Boolean!
locationZIPs: [String] locationZIPs: [String]!
memberCoreTeam: Boolean! "default: false"
memberCoreTeam: Boolean
"Date of workshop to become Mentor dt. Pate" }
workshopMentor: Date
"Date of last Erste Hilfe Kurs?"
workshopAmbulance: Date
reserve: String type EngagementType {
id: ID!
name: String!
description: String!
} }
input EngagementTypeCreateInput {
name: String!
description: String
}
type Engagement { type Engagement {
id: ID! id: ID!
engagementType: EngagementType!
from: Date! from: Date!
to: Date to: Date
participant: Participant participant: Participant
@ -270,7 +271,10 @@ type Engagement {
} }
input EngagementCreateInput { input EngagementCreateInput {
from: Date! engagementTypeId: ID!
"will use CURRENT_DATE if not set"
from: Date
"will use infinit if not set"
to: Date to: Date
participantId: ID! participantId: ID!
cargoBikeId: ID! cargoBikeId: ID!
@ -542,44 +546,48 @@ input ProviderCreateInput {
cargoBikeIds: [ID]! cargoBikeIds: [ID]!
} }
type ContactInformation { """
A Person can have several instances of contact information.
The reason for this is, that some people have info for interns and externals that are different.
"""
type Person {
id: ID! id: ID!
name: String! name: String!
firstName: String firstName: String!
retiredAt: Date contactInformation: [ContactInformation]
phoneExtern: String
phone2Extern: String
phoneIntern: String
phone2Intern: String
emailExtern: String
emailIntern: String
note: String
} }
input ContactInformationCreateInput { input PersonCreateInput {
name: String! name: String!
firstName: String! firstName: String!
retiredAt: Date }
phoneExtern: String
phone2Extern: String type ContactInformation {
phoneIntern: String id: ID!
phone2Intern: String person: Person!
emailExtern: String phone: String
emailIntern: String phone2: String
email: String
email2: String
note: String
}
input ContactInformationCreateInput {
personId: ID!
phone: String
phone2: String
email: String
email2: String
note: String note: String
} }
input ContactInformationUpdateInput { input ContactInformationUpdateInput {
id: ID! id: ID!
name: String personId: ID
firstName: String phone: String
retiredAt: Date phone2: String
phoneExtern: String email: String
phone2Extern: String email2: String
phoneIntern: String
phone2Intern: String
emailExtern: String
emailIntern: String
note: String note: String
} }
@ -744,6 +752,7 @@ type Query {
lendingStations(offset: Int!, limit: Int!): [LendingStation]! lendingStations(offset: Int!, limit: Int!): [LendingStation]!
timeframes(offset: Int!, limit: Int!): [TimeFrame]! timeframes(offset: Int!, limit: Int!): [TimeFrame]!
contactInformation(offset: Int!, limit: Int!): [ContactInformation]! contactInformation(offset: Int!, limit: Int!): [ContactInformation]!
persons(offset: Int!, limit: Int!): [Person]
"returns BikeEvent with CargoBike" "returns BikeEvent with CargoBike"
bikeEventById(id:ID!): BikeEvent! bikeEventById(id:ID!): BikeEvent!
} }
@ -777,6 +786,8 @@ type Mutation {
createParticipant(participant: ParticipantCreateInput!): Participant! createParticipant(participant: ParticipantCreateInput!): Participant!
"create new contactInfo" "create new contactInfo"
createContactInformation(contactInformation: ContactInformationCreateInput!): ContactInformation! createContactInformation(contactInformation: ContactInformationCreateInput!): ContactInformation!
createPerson(person: PersonCreateInput!): Person!
createEngagementType(engagementType: EngagementTypeCreateInput!): EngagementType!
"create Engagement" "create Engagement"
createEngagement(engagement: EngagementCreateInput): Engagement! createEngagement(engagement: EngagementCreateInput): Engagement!
"createContactPerson, return null if contactInformationId does not exist" "createContactPerson, return null if contactInformationId does not exist"

Loading…
Cancel
Save