diff --git a/README.md b/README.md index cd25810..e5030d5 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ The following environment variables can be used to configure the server: ```bash RPC_HOST=host:port NODE_ENV=develop/production -POSTGRES_CONNECTION_URL=postgres://username:password@host:port/database_name +DATABASE_URL=postgres://username:password@host:port/database_name ``` - __RPC_HOST__ is used for the connection with the [flotte-user-management server](https://github.com/fLotte-meets-HWR-DB/flotte-user-management). - __NODE_ENV__ will not check authentication if set to development diff --git a/src/app.ts b/src/app.ts index 0b5f44c..b921180 100644 --- a/src/app.ts +++ b/src/app.ts @@ -137,6 +137,8 @@ export async function getApp (connOptions: ConnectionOptions) { await cargoBikeAPI.populateCopyConfig(); } catch (err) { console.error(err); + // exit so docker can restart the container and reattempt + process.exit(1); } const server = new ApolloServer({ diff --git a/src/datasources/db/cargobikeAPI.ts b/src/datasources/db/cargobikeAPI.ts index 0a1c804..41d9867 100644 --- a/src/datasources/db/cargobikeAPI.ts +++ b/src/datasources/db/cargobikeAPI.ts @@ -237,12 +237,13 @@ export class CargoBikeAPI extends DataSource { } async createBikeEvent ({ bikeEvent }: { bikeEvent: any }) { - return (await this.connection.getRepository(BikeEvent) + const inserts = await this.connection.getRepository(BikeEvent) .createQueryBuilder('be') .insert() .values([bikeEvent]) .returning('*') - .execute()).generatedMaps[0]; + .execute(); + return await this.bikeEventById(inserts.identifiers[0].id); } async updateBikeEvent (bikeEvent: any, userId: number) { @@ -310,7 +311,7 @@ export class CargoBikeAPI extends DataSource { return (await this.connection.getRepository(BikeEventType) .createQueryBuilder('bet') .insert() - .values([{ name: bikeEventType }]) + .values([bikeEventType]) .returning('*') .execute())?.generatedMaps[0]; } @@ -564,6 +565,7 @@ export class CargoBikeAPI extends DataSource { delete cargoBike[value.key]; } }); + cargoBike.id = -1; return cargoBike; } diff --git a/src/datasources/db/participantAPI.ts b/src/datasources/db/participantAPI.ts index 8efd5b8..bd16bcf 100644 --- a/src/datasources/db/participantAPI.ts +++ b/src/datasources/db/participantAPI.ts @@ -25,7 +25,6 @@ import { Participant } from '../../model/Participant'; import { EngagementType } from '../../model/EngagementType'; import { ActionLogger, DBUtils, genDateRange, LockUtils } from './utils'; import { UserInputError } from 'apollo-server-express'; -import { GraphQLError } from 'graphql'; import { ResourceLockedError } from '../../errors/ResourceLockedError'; export class ParticipantAPI extends DataSource { @@ -230,7 +229,7 @@ export class ParticipantAPI extends DataSource { .createQueryBuilder('w') .relation(Participant, 'workshopIds') .of(participant.id) - .add(workshops); + .addAndRemove(workshops, await this.workshopsByParticipantId(participant.id)); }); !keepLock && await this.unlockParticipant(participant.id, userId); return await this.participantById(participant.id); diff --git a/src/datasources/db/workshopAPI.ts b/src/datasources/db/workshopAPI.ts index 9c0e510..de04f89 100644 --- a/src/datasources/db/workshopAPI.ts +++ b/src/datasources/db/workshopAPI.ts @@ -55,6 +55,8 @@ export class WorkshopAPI extends DataSource { async updateWorkshop (workshop: any, userId: number) { const keepLock = workshop.keepLock; delete workshop.keepLock; + const workshopTypeId = workshop.workshopTypeId; + delete workshop.workshopTypeId; await this.connection.transaction(async (entityManger: EntityManager) => { if (await LockUtils.isLocked(entityManger, Workshop, 'w', workshop.id, userId)) { throw new ResourceLockedError('Workshop', 'Attempting to update locked resource'); @@ -71,6 +73,11 @@ export class WorkshopAPI extends DataSource { throw new NotFoundError('Workshop', 'id', workshop.id); } }); + workshopTypeId && await entityManger.getRepository(Workshop) + .createQueryBuilder('w') + .relation(Workshop, 'workshopTypeId') + .of(workshop.id) + .set(workshopTypeId); }); !keepLock && await this.unlockWorkshop(workshop.id, userId); return await this.workshopById(workshop.id); @@ -134,6 +141,14 @@ export class WorkshopAPI extends DataSource { .getOne(); } + async workshopTypeByWorkshopId (id: number) { + return await this.connection.getRepository(Workshop) + .createQueryBuilder('w') + .relation(Workshop, 'workshopTypeId') + .of(id) + .loadOne(); + } + async workshopTypes (offset?: number, limit?: number) { return DBUtils.getAllEntity(this.connection, WorkshopType, 'wt', offset, limit); } diff --git a/src/index.ts b/src/index.ts index 7e183f0..2ee549c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,6 +23,10 @@ import { getApp, getConnectionOptions, userAPI } from './app'; app.listen(4000, async () => { await userAPI.createDefinedPermissions().catch( - err => console.log(err)); + err => { + console.log(err); + // exit so docker can restart the container and reattempt + process.exit(1); + }); }); })(); diff --git a/src/model/LendingStation.ts b/src/model/LendingStation.ts index 9df1441..24e6c9d 100644 --- a/src/model/LendingStation.ts +++ b/src/model/LendingStation.ts @@ -40,6 +40,12 @@ export class LoanPeriod { }) generalRemark: string; + @Column({ + nullable: true, + type: 'text' + }) + holidays: string; + /** * validity for loanPeriods */ @@ -120,6 +126,11 @@ export class LendingStation implements Lockable { }) organisationId: number; + @Column({ + nullable: true + }) + remark: string; + @Column({ nullable: true, type: 'timestamp' diff --git a/src/model/Workshop.ts b/src/model/Workshop.ts index 91e6b11..d44b415 100644 --- a/src/model/Workshop.ts +++ b/src/model/Workshop.ts @@ -60,7 +60,7 @@ export class Workshop implements Lockable { @JoinColumn({ name: 'trainer2Id' }) - trainer2: Participant; + trainer2Id: number; @Column({ nullable: true, diff --git a/src/resolvers/cargoBikeResolver.ts b/src/resolvers/cargoBikeResolver.ts index da64451..0d56bb9 100644 --- a/src/resolvers/cargoBikeResolver.ts +++ b/src/resolvers/cargoBikeResolver.ts @@ -220,6 +220,9 @@ export default { throw new PermissionError(); } }, + documents: (parent: any) => { + return (parent.documents) ? parent.documents : []; + }, isLockedByMe: (parent: any, __: any, { req }: { req: any }) => isLockedByMe(parent, { req }), isLocked: (parent: any, __: any, { req }: { req: any }) => isLocked(parent, { req }) }, @@ -227,6 +230,11 @@ export default { isLockedByMe: (parent: any, __: any, { req }: { req: any }) => isLockedByMe(parent, { req }), isLocked: (parent: any, __: any, { req }: { req: any }) => isLocked(parent, { req }) }, + InsuranceData: { + projectAllowance: (parent: any): any => { + return (parent.projectAllowance as string)?.replace(/€\$/, ''); + } + }, Mutation: { createCargoBike: (_: any, { cargoBike }: { cargoBike: any }, { dataSources, req }: { dataSources: any, req: any }) => { if (req.permissions.includes(Permission.WriteBike)) { @@ -368,9 +376,9 @@ export default { throw new PermissionError(); } }, - createBikeEventType: (_: any, { name }: { name: any }, { dataSources, req }: { dataSources: any, req: any }) => { + createBikeEventType: (_: any, { bikeEventType }: { bikeEventType: any }, { dataSources, req }: { dataSources: any, req: any }) => { if (req.permissions.includes(Permission.WriteEventType)) { - return dataSources.cargoBikeAPI.createBikeEventType(name); + return dataSources.cargoBikeAPI.createBikeEventType(bikeEventType); } else { throw new PermissionError(); } diff --git a/src/resolvers/workshopResolvers.ts b/src/resolvers/workshopResolvers.ts index 82fbd33..c148251 100644 --- a/src/resolvers/workshopResolvers.ts +++ b/src/resolvers/workshopResolvers.ts @@ -75,6 +75,13 @@ export default { throw new PermissionError(); } }, + workshopType (parent: any, _: any, { dataSources, req }: { dataSources: any; req: any }) { + if (req.permissions.includes(Permission.ReadWorkshop)) { + return dataSources.workshopAPI.workshopTypeByWorkshopId(parent.id); + } else { + throw new PermissionError(); + } + }, isLockedByMe: (parent: any, __: any, { req }: { req: any }) => isLockedByMe(parent, { req }), isLocked: (parent: any, __: any, { req }: { req: any }) => isLocked(parent, { req }) }, diff --git a/src/schema/type-defs.ts b/src/schema/type-defs.ts index a4e005c..8c2a4a8 100644 --- a/src/schema/type-defs.ts +++ b/src/schema/type-defs.ts @@ -723,6 +723,10 @@ export default gql` keepLock: Boolean } + input BikeEventTypeCreateInput { + name: String! + } + "(dt. Anbieter) bezieht sich auf die Beziehung einer Person oder Organisation zum Lastenrad" type Provider { id: ID! @@ -872,6 +876,7 @@ export default gql` "Total amount of cargoBikes currently assigned to the lending station" numCargoBikes: Int! organisation: Organisation + remark: String isLocked: Boolean! isLockedByMe: Boolean! "null if not locked by other user" @@ -889,6 +894,7 @@ export default gql` address: AddressCreateInput! loanPeriod: LoanPeriodInput organisationId: ID + remark: String } """ @@ -902,6 +908,7 @@ export default gql` address: AddressUpdateInput loanPeriod: LoanPeriodInput organisationId: ID + remark: String keepLock: Boolean } @@ -910,6 +917,7 @@ export default gql` """ type LoanPeriod { generalRemark: String + holidays: String mo: String tu: String we: String @@ -924,6 +932,7 @@ export default gql` """ input LoanPeriodInput { generalRemark: String + holidays: String mo: String tu: String we: String @@ -983,18 +992,21 @@ export default gql` street: String! number: String! zip: String! + city: String } input AddressCreateInput { street: String! number: String! zip: String! + city: String } input AddressUpdateInput { street: String number: String zip: String + city: String } type ActionLog { @@ -1123,7 +1135,7 @@ export default gql` """ BIKEEVENT """ - createBikeEventType(name: String!): BikeEventType! + createBikeEventType(bikeEventType: BikeEventTypeCreateInput!): BikeEventType! lockBikeEventType(id: ID!): BikeEventType! unlockBikeEventType(id:ID!): BikeEventType! updateBikeEventType(bikeEventType: BikeEventTypeUpdateInput!): BikeEventType!