From 0c2436ba0de6d3afe12ef7c1d9a641eab0afb546 Mon Sep 17 00:00:00 2001 From: leonnicolas Date: Thu, 17 Sep 2020 15:48:33 +0200 Subject: [PATCH] src/resolvers/* added cargobike and lendingstations resolvers --- src/datasources/db/cargobikeAPI.ts | 90 ++++++----- src/datasources/db/lendingstationAPI.ts | 38 ++++- src/index.ts | 8 +- src/model/LendingStation.ts | 11 +- src/model/Provider.ts | 21 ++- src/resolvers/cargobikeResolver.ts | 18 ++- src/resolvers/lendingstationResolvers.ts | 11 +- src/schema/type-defs.ts | 193 +++++++++++++++++++---- 8 files changed, 292 insertions(+), 98 deletions(-) diff --git a/src/datasources/db/cargobikeAPI.ts b/src/datasources/db/cargobikeAPI.ts index 5e07c96..b195b9a 100644 --- a/src/datasources/db/cargobikeAPI.ts +++ b/src/datasources/db/cargobikeAPI.ts @@ -12,14 +12,24 @@ export class CargoBikeAPI extends DataSource { this.connection = getConnection(); } + async getCargoBikes () { + return await this.connection.createQueryBuilder() + .select('cargoBikes') + .from(CargoBike, 'cargoBikes') + .getMany(); + } + /** - * Finds cargo bike by id + * Finds cargo bike by id, retuns error if id not found + * @param param0 id of bike */ async findCargoBikeById ({ id }:{id: any}) { - return { - id, - name: 'token' - }; + return await this.connection.manager + .createQueryBuilder() + .select('cargoBike') + .from(CargoBike, 'cargoBike') + .where('cargoBike.id = :id', { id }) + .getOne() || new GraphQLError('ID not found'); } async updateBike ({ id, name }:{id:any, name: string }) { @@ -39,47 +49,43 @@ export class CargoBikeAPI extends DataSource { } /** - * Creates or Updates CargoBike - * Will create bike, if no id given, else it will update bike with given id. - * @param param0 cargoBike to be updated or created + * Updates CargoBike and return updated cargoBike + * @param param0 cargoBike to be updated */ async updateCargoBike ({ cargoBike }:{ cargoBike: any }) { - if (cargoBike.id) { - // update bike with given id - const bike = await this.connection.manager.createQueryBuilder() - .select('cargoBike') - .from(CargoBike, 'cargoBike') - .where('cargoBike.id = :id', { id: cargoBike.id }) - .getOne(); - if (bike) { - // bike exists - await this.connection - .createQueryBuilder() - .update(CargoBike) - .set({ ...cargoBike }) - .where('id = :id', { id: bike.id }) - .execute(); - return await this.connection - .createQueryBuilder() - .select('cargoBike') - .from(CargoBike, 'cargoBike') - .where('cargoBike.id = :id', { id: bike.id }) - .getOne(); - } else { - return new GraphQLError('ID not in database'); - } - } else { - // create new bike - const inserts = await this.connection.manager + const bike = await this.connection.manager.createQueryBuilder() + .select('cargoBike') + .from(CargoBike, 'cargoBike') + .where('cargoBike.id = :id', { id: cargoBike.id }) + .getOne(); + if (bike) { + await this.connection .createQueryBuilder() - .insert() - .into(CargoBike) - .values([cargoBike]) - .returning('*') + .update(CargoBike) + .set({ ...cargoBike }) + .where('id = :id', { id: bike.id }) .execute(); - const newbike = inserts.generatedMaps[0]; - newbike.id = inserts.identifiers[0].id; - return newbike; + return await this.findCargoBikeById({ id: bike.id }); + } else { + return new GraphQLError('ID not in database'); } } + + /** + * createCargoBike + * created CargoBike and returns created bike with new ID + * @param param0 cargoBike to be created + */ + async createCargoBike ({ cargoBike }: { cargoBike: any }) { + const inserts = await this.connection.manager + .createQueryBuilder() + .insert() + .into(CargoBike) + .values([cargoBike]) + .returning('*') + .execute(); + const newbike = inserts.generatedMaps[0]; + newbike.id = inserts.identifiers[0].id; + return newbike; + } } diff --git a/src/datasources/db/lendingstationAPI.ts b/src/datasources/db/lendingstationAPI.ts index 475b912..ddf0ec8 100644 --- a/src/datasources/db/lendingstationAPI.ts +++ b/src/datasources/db/lendingstationAPI.ts @@ -1,5 +1,7 @@ import { DataSource } from 'apollo-datasource'; +import { GraphQLError } from 'graphql'; import { Connection, getConnection } from 'typeorm'; +import { LendingStation } from '../../model/LendingStation'; export class LendingStationAPI extends DataSource { connection : Connection @@ -8,7 +10,41 @@ export class LendingStationAPI extends DataSource { this.connection = getConnection(); } + async createLendingStation ({ lendingStation }:{ lendingStation: any }) { + console.log(lendingStation); + const inserts = await this.connection.manager + .createQueryBuilder() + .insert() + .into(LendingStation) + .values([lendingStation]) + .returning('*') + .execute(); + const newLendingStaion = inserts.generatedMaps[0]; + newLendingStaion.id = inserts.identifiers[0].id; + return newLendingStaion; + } + async updateLendingStation ({ lendingStation }:{ lendingStation: any }) { - return lendingStation; + const oldLendingStation = await this.connection.manager.createQueryBuilder() + .select('lendingStation') + .from(LendingStation, 'lendingStation') + .where('lendingStation.id = :id', { id: lendingStation.id }) + .getOne(); + if (oldLendingStation) { + await this.connection + .createQueryBuilder() + .update(LendingStation) + .set({ ...lendingStation }) + .where('id = :id', { id: lendingStation.id }) + .execute(); + return await this.connection + .createQueryBuilder() + .select('lendingStation') + .from(LendingStation, 'lendingStation') + .where('lendingStation.id = :id', { id: lendingStation.id }) + .getOne(); + } else { + return new GraphQLError('ID not in database'); + } } } diff --git a/src/index.ts b/src/index.ts index 93d7e86..1e2bc45 100644 --- a/src/index.ts +++ b/src/index.ts @@ -20,6 +20,8 @@ import { Organization } from './model/Organization'; import { Provider } from './model/Provider'; import { Engagement } from './model/Engagement'; import { Workshop } from './model/Workshop'; +import { LendingStationAPI } from './datasources/db/lendingstationAPI'; +import lendingstationResolvers from './resolvers/lendingstationResolvers'; require('dotenv').config(); @@ -77,10 +79,14 @@ createConnection({ const userAPI = new UserServerAPI(process.env.RPC_HOST); const server = new ApolloServer({ - resolvers: [bikeresolver], + resolvers: [ + bikeresolver, + lendingstationResolvers + ], typeDefs, dataSources: () => ({ cargoBikeAPI: new CargoBikeAPI(), + lendingStationAPI: new LendingStationAPI(), userAPI }), context: (req: any) => { diff --git a/src/model/LendingStation.ts b/src/model/LendingStation.ts index b7ed521..642c5d5 100644 --- a/src/model/LendingStation.ts +++ b/src/model/LendingStation.ts @@ -3,6 +3,7 @@ import { ContactInformation } from './ContactInformation'; import { LoanPeriod } from './LoanPeriod'; import { CargoBike } from './CargoBike'; import { Organization } from './Organization'; +import { Address } from './Provider'; @Entity() export class LendingStation { @@ -16,14 +17,8 @@ export class LendingStation { @JoinTable() contactInformation: ContactInformation[]; - @Column() - addressStreet: string; - - @Column() - addressStreetNo: string; - - @Column() - addressZip: string; + @Column(type => Address) + address: Address; @OneToMany(type => LoanPeriod, loanPeriod => loanPeriod.lendingStation) loanPeriods: LoanPeriod[]; diff --git a/src/model/Provider.ts b/src/model/Provider.ts index c908d8d..963dbb4 100644 --- a/src/model/Provider.ts +++ b/src/model/Provider.ts @@ -5,6 +5,17 @@ import { ContactInformation } from './ContactInformation'; import { LendingStation } from './LendingStation'; import { Organization } from './Organization'; +export class Address { + @Column() + street: string; + + @Column() + number: string; + + @Column() + zip: string; +} + @Entity() export class Provider { @PrimaryGeneratedColumn() @@ -18,14 +29,8 @@ export class Provider { }) formularName: String; - @Column() - street: string; - - @Column() - number: string; - - @Column() - zip: string; + @Column(type => Address) + address: Address; @OneToMany(type => ContactInformation, contactInformation => contactInformation.provider) contactInformation: ContactInformation[]; diff --git a/src/resolvers/cargobikeResolver.ts b/src/resolvers/cargobikeResolver.ts index bac8517..10dd4f2 100644 --- a/src/resolvers/cargobikeResolver.ts +++ b/src/resolvers/cargobikeResolver.ts @@ -3,12 +3,19 @@ import { GraphQLError } from 'graphql'; export default { Query: { - cargobikeById: (_: any, { id }:{id: any}, { dataSources, req }:{dataSources: any, req: any }) => { + cargoBikeById: (_: any, { id }:{id: any}, { dataSources, req }:{dataSources: any, req: any }) => { if (req.permissions.includes(Permission.ReadBike)) { return dataSources.cargoBikeAPI.findCargoBikeById({ id }); } else { return new GraphQLError('Insufficient Permissions'); } + }, + cargoBikes: (_: any, __: any, { dataSources, req }: { dataSources: any, req: any }) => { + if (req.permissions.includes(Permission.ReadBike)) { + return dataSources.cargoBikeAPI.getCargoBikes(); + } else { + return new GraphQLError('Insufficiant Permissions'); + } } }, Mutation: { @@ -19,7 +26,14 @@ export default { return new GraphQLError('Insufficient Permissions'); } }, - cargoBike: (_: any, { cargoBike }: { cargoBike: any }, { dataSources, req }:{dataSources: any, req: any }) => { + createCargoBike: (_: any, { cargoBike }: { cargoBike: any }, { dataSources, req }:{dataSources: any, req: any }) => { + if (req.permissions.includes(Permission.WriteBike)) { + return dataSources.cargoBikeAPI.createCargoBike({ cargoBike }); + } else { + return new GraphQLError('Insufficient Permissions'); + } + }, + updateCargoBike: (_: any, { cargoBike }: { cargoBike: any }, { dataSources, req }:{dataSources: any, req: any }) => { if (req.permissions.includes(Permission.WriteBike)) { return dataSources.cargoBikeAPI.updateCargoBike({ cargoBike }); } else { diff --git a/src/resolvers/lendingstationResolvers.ts b/src/resolvers/lendingstationResolvers.ts index 3508edc..028c7eb 100644 --- a/src/resolvers/lendingstationResolvers.ts +++ b/src/resolvers/lendingstationResolvers.ts @@ -6,9 +6,16 @@ export default { Query: { }, Mutation: { - lendingStation: (_: any, { lendingStation }:{ lendingStation: LendingStation }, { dataSources, req }:{dataSources: any, req: any }) => { + createLendingStation: (_: any, { lendingStation }:{ lendingStation: LendingStation }, { dataSources, req }:{dataSources: any, req: any }) => { if (req.permissions.includes(Permission.WriteBike)) { - return new GraphQLError('Not implemented'); + return dataSources.lendingStationAPI.createLendingStation({ lendingStation }); + } else { + return new GraphQLError('Insufficient Permissions'); + } + }, + updateLendingStation: (_: any, { lendingStation }:{ lendingStation: LendingStation }, { dataSources, req }:{dataSources: any, req: any }) => { + if (req.permissions.includes(Permission.WriteBike)) { + return dataSources.lendingStationAPI.updateLendingStation({ lendingStation }); } else { return new GraphQLError('Insufficient Permissions'); } diff --git a/src/schema/type-defs.ts b/src/schema/type-defs.ts index 7329234..9fa24ef 100644 --- a/src/schema/type-defs.ts +++ b/src/schema/type-defs.ts @@ -46,9 +46,7 @@ type CargoBike { lockedUntil: Date } -input CargoBikeInput { - "if null, then new bike will be created, else old bike will be updated." - id: ID +input CargoBikeCreateInput { "see column A in info tabelle" group: Group! name: String! @@ -61,15 +59,15 @@ input CargoBikeInput { Safety is a custom type, that stores information about security features. TODO: Should this be calles Security? """ - security: SecurityInput! + security: SecurityCreateInput! """ Does not refere to an extra table in the database. """ - technicalEquipment: TechnicalEquipmentInput! + technicalEquipment: TechnicalEquipmentCreateInput! """ Does not refere to an extra table in the database. """ - dimensionsAndLoad: DimensionsAndLoadInput! + dimensionsAndLoad: DimensionsAndLoadCreateInput! "Refers to equipment that is not unique. See kommentierte info tabelle -> Fragen -> Frage 2" otherEquipment: [String] @@ -77,8 +75,42 @@ input CargoBikeInput { stickerBikeNameState: StickerBikeNameState note: String provider: String - insuranceData: InsuranceDataInput! - taxes: TaxesInput + insuranceData: InsuranceDataCreateInput! + taxes: TaxesCreateInput +} + +input CargoBikeUpdateInput { + id: ID! + "see column A in info tabelle" + group: Group + name: String + modelName: String + numberOfWheels: Int + forCargo: Boolean + forChildren: Boolean + numberOfChildren: Int + """ + Safety is a custom type, that stores information about security features. + TODO: Should this be calles Security? + """ + security: SecurityUpdateInput + """ + Does not refere to an extra table in the database. + """ + technicalEquipment: TechnicalEquipmentUpdateInput + """ + Does not refere to an extra table in the database. + """ + dimensionsAndLoad: DimensionsAndLoadUpdateInput + "Refers to equipment that is not unique. See kommentierte info tabelle -> Fragen -> Frage 2" + otherEquipment: [String] + + "Sticker State" + stickerBikeNameState: StickerBikeNameState + note: String + provider: String + insuranceData: InsuranceDataUpdateInput + taxes: TaxesUpdateInput } type InsuranceData { @@ -100,7 +132,7 @@ type InsuranceData { notes: String } -input InsuranceDataInput { +input InsuranceDataCreateInput { """ Eventuelly, this field will become an enum or a seperate data table and user can choose from a pool of insurance companies. """ @@ -119,6 +151,25 @@ input InsuranceDataInput { notes: String } +input InsuranceDataUpdateInput { + """ + Eventuelly, this field will become an enum or a seperate data table and user can choose from a pool of insurance companies. + """ + name: String + benefactor: String + billing: String + noPnP: String + "eg. Anbieter, flotte, eigenleistung" + maintananceResponsible: String + maintananceBenefactor: String + maintananceAgreement: String + hasFixedRate: Boolean! + fixedRate: Float + "Projektzuschuss" + projectAllowance: Float + notes: String +} + enum Group{ KL LI @@ -179,11 +230,16 @@ type Taxes { organizationArea: OrganizationArea } -input TaxesInput { +input TaxesCreateInput { costCenter: String! organizationArea: OrganizationArea } +input TaxesUpdateInput { + costCenter: String + organizationArea: OrganizationArea +} + enum OrganizationArea { IB ZB @@ -255,7 +311,7 @@ type DimensionsAndLoad { bikeWeight: Float } -input DimensionsAndLoadInput { +input DimensionsAndLoadCreateInput { hasCoverBox: Boolean! lockable: Boolean! boxLength: Float! @@ -270,6 +326,21 @@ input DimensionsAndLoadInput { bikeWeight: Float } +input DimensionsAndLoadUpdateInput { + hasCoverBox: Boolean + lockable: Boolean + boxLength: Float + boxWidth: Float + boxHeight: Float + maxWeightBox: Float + maxWeightLuggageRack: Float + maxWeightTotal: Float + bikeLength: Float + bikeWidth: Float + bikeHeight: Float + bikeWeight: Float +} + """ Some Technical Info about the bike. This should be 1-1 Relation with the CargoBike. @@ -282,13 +353,20 @@ type TechnicalEquipment { specialFeatures: String } -input TechnicalEquipmentInput { +input TechnicalEquipmentCreateInput { bicycleShift: String! isEBike: Boolean! hasLightSystem: Boolean! specialFeatures: String } +input TechnicalEquipmentUpdateInput { + bicycleShift: String + isEBike: Boolean + hasLightSystem: Boolean + specialFeatures: String +} + """ The Security Info about the bike. his should be 1-1 Relation with the CargoBike. @@ -302,7 +380,7 @@ type Security { adfcCoding: String } -input SecurityInput { +input SecurityCreateInput { frameNumber: String! keyNumberFrameLock: String keyNumberAXAChain: String @@ -310,6 +388,14 @@ input SecurityInput { adfcCoding: String } +input SecurityUpdateInput { + frameNumber: String + keyNumberFrameLock: String + keyNumberAXAChain: String + policeCoding: String + adfcCoding: String +} + enum StickerBikeNameState { OK IMPROVE @@ -346,8 +432,21 @@ type ContactInformation { note: String } -input ContactInformationInput { - id: ID +input ContactInformationCreateInput { + name: String + firstName: String + retiredAt: Date + phoneExtern: String + phone2Extern: String + phoneIntern: String + phone2Intern: String + emailExtern: String + emailIntern: String + note: String +} + +input ContactInformationUpdateInput { + id: ID! name: String firstName: String retiredAt: Date @@ -382,13 +481,21 @@ type LendingStation { loanPeriods: [LoanPeriod]! } -input LendingStationInput { - id: ID +input LendingStationCreateInput { + name: String! + contactInformation: [ContactInformationCreateInput]! + address: AddressCreateInput! + loanTimes: LoanTimesInput + loanPeriods: [LoanPeriodCreateInput]! +} + +input LendingStationUpdateInput { + id: ID! name: String - contactInformation: [ContactInformationInput] - address: AddressInput + contactInformation: [ContactInformationUpdateInput] + address: AddressUpdateInput loanTimes: LoanTimesInput - loanPeriods: [LoanPeriodInput] + loanPeriods: [LoanPeriodUpdateInput] } """ @@ -426,17 +533,25 @@ type LoanPeriod { from: Date! to: Date note: String - lendingstation: LendingStation! - cargobike: CargoBike! + lendingStation: LendingStation! + cargoBike: CargoBike! +} + +input LoanPeriodCreateInput { + from: Date + to: Date + note: String + lendingStationID: LendingStationCreateInput + cargoBikeID: CargoBikeCreateInput } -input LoanPeriodInput { - id: ID +input LoanPeriodUpdateInput { + id: ID! from: Date to: Date note: String - lendingstationID: Int! - cargobikeID: Int! + lendingStation: LendingStationUpdateInput + cargoBike: CargoBikeUpdateInput } type Address { @@ -445,17 +560,23 @@ type Address { zip: String! } -input AddressInput { +input AddressCreateInput { street: String! number: String! zip: String! } +input AddressUpdateInput { + street: String + number: String + zip: String +} + type Query { - cargobikeById(id:ID!): CargoBike + cargoBikeById(id:ID!): CargoBike "!!!!" - cargobikes: [CargoBike]! - cargobikesByProvider(providerId:ID!): [CargoBike]! + cargoBikes: [CargoBike]! + cargoBikesByProvider(providerId:ID!): [CargoBike]! providerById(id:ID!): Provider providers: [Provider]! participantById(id:ID!): Participant @@ -468,10 +589,14 @@ type Query { type Mutation { "for testing" addBike(id: ID!, name: String): CargoBike! - "if id: null, then new bike will be created, else old bike will be updated" - cargoBike(cargoBike: CargoBikeInput!): CargoBike! - "if id: null, then new lending station will be created, else existing one will be updated" - lendingStation(lendingStation: LendingStationInput): LendingStation! + "creates new cargoBike and returns cargobike with new ID" + createCargoBike(cargoBike: CargoBikeCreateInput!): CargoBike! + "updates cargoBike of given ID with supplied fields and returns updated cargoBike" + updateCargoBike(cargoBike: CargoBikeUpdateInput!): CargoBike! + "creates new lendingStation and returns lendingStation with new ID" + createLendingStation(lendingStation: LendingStationCreateInput): LendingStation! + "updates lendingStation of given ID with supplied fields and returns updated lendingStation" + updateLendingStation(lendingstation: LendingStationUpdateInput!): LendingStation! } `;