Passed
Branch test/scrutinizer-config-backen... (e3cdc3)
by Karl
06:16
created

BicyclesService.createManyBikes   B

Complexity

Conditions 7

Size

Total Lines 28
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
cc 7
eloc 23
dl 0
loc 28
ccs 0
cts 6
cp 0
crap 56
rs 7.9279
c 0
b 0
f 0
1 7
import { Injectable } from '@nestjs/common';
2 7
import { InjectRepository } from '@nestjs/typeorm';
3 7
import { Repository } from 'typeorm';
4 7
import { Bicycle } from './entities/bicycle.entity';
5 7
import { NotFoundException } from '@nestjs/common';
0 ignored issues
show
introduced by
'@nestjs/common' import is duplicated.
Loading history...
6
import { UpdateBicycleDto } from './dto/update-bicycle.dto';
7
import { BicycleResponse } from './types/bicycle-response.interface';
8 7
import { getDistance } from 'src/utils/geo.utils';
9
import { CreateBicycleDto } from './dto/create-bicycle.dto';
10 7
import { City } from 'src/cities/entities/city.entity';
11
12
@Injectable()
13 7
export class BicyclesService {
14
  constructor(
15
    @InjectRepository(Bicycle)
16
    private readonly bicycleRepository: Repository<Bicycle>,
17
    @InjectRepository(City)
18
    private cityRepository: Repository<City>,
19
  ) {}
20
21
  async findAll(): Promise<Bicycle[]> {
22
    const bikes = await this.bicycleRepository.find({
23
      relations: {
24
        city: true,
25
      },
26
      select: {
27
        id: true,
28
        batteryLevel: true,
29
        latitude: true,
30
        longitude: true,
31
        status: true,
32
        createdAt: true,
33
        updatedAt: true,
34
        city: {
35
          name: true,
36
        },
37
      },
38
    });
39
40
    return bikes;
41
  }
42
43
  async setRented(bikeId: string): Promise<Bicycle> {
44
    const result = await this.bicycleRepository.update(
45
      { id: bikeId, status: 'Available' },
46
      { status: 'Rented' },
47
    );
48 1
    if (result.affected === 0) {
49
      throw new NotFoundException(
50
        "Bike couldn't be rented. Bike might not exist or it is not available.",
51
      );
52
    }
53
    return await this.findById(bikeId);
54
  }
55
56
  async createBike(createBicycleDto: CreateBicycleDto): Promise<Bicycle> {
57
    const bike = this.bicycleRepository.create({
58
      batteryLevel: createBicycleDto.batteryLevel ?? 100,
59
      latitude: createBicycleDto.latitude,
60
      longitude: createBicycleDto.longitude,
61
      status: createBicycleDto.status ?? 'Available',
62
    });
63
64 2
    const city = createBicycleDto.city ?? 'Göteborg';
65
    // Find the city by name
66
    const cityEntity = await this.cityRepository.findOne({
67
      where: { name: city },
68
    });
69
70 1
    if (cityEntity) {
71
      bike.city = cityEntity;
72
    }
73
74
    return await this.bicycleRepository.save(bike);
75
  }
76
77
  async createManyBikes(createBicycleDto: CreateBicycleDto[]): Promise<Bicycle[]> {
78
    const defaultCity = await this.cityRepository.findOne({
79
      where: { name: 'Göteborg' },
80
    });
81
    const Karlshamn = await this.cityRepository.findOne({
82
      where: { name: 'Karlshamn' },
83
    });
84
    const Jönköping = await this.cityRepository.findOne({
85
      where: { name: 'Jönköping' },
86
    });
87
88
    const bikes = createBicycleDto.map((bike) => {
89
      return this.bicycleRepository.create({
90
        batteryLevel: bike.batteryLevel ?? 100,
91
        latitude: bike.latitude,
92
        longitude: bike.longitude,
93
        status: bike.status ?? 'Available',
94
        city:
95
          bike.city === 'Jönköping'
96
            ? Jönköping
97
            : bike.city === 'Karlshamn'
98
              ? Karlshamn
99
              : defaultCity,
100
      });
101
    });
102
103
    return await this.bicycleRepository.save(bikes);
104
  }
105
106
  async findById(id: string): Promise<Bicycle> {
107
    const bike = await this.bicycleRepository.findOne({
108
      where: { id },
109
      relations: {
110
        city: true,
111
      },
112
    });
113 1
    if (!bike) {
114
      throw new NotFoundException('Bike not found');
115
    }
116
    return bike;
117
  }
118
119
  async update(id: string, updateBicycleDto: UpdateBicycleDto): Promise<Bicycle> {
120
    const bike = await this.findById(id);
121
122
    return this.bicycleRepository.save({ ...bike, ...updateBicycleDto });
123
  }
124
125
  async findByCity(cityName: 'Göteborg' | 'Jönköping' | 'Karlshamn'): Promise<Bicycle[]> {
126
    const bikes = await this.bicycleRepository.find({
127
      where: {
128
        city: {
129
          name: cityName,
130
        },
131
      },
132
      relations: ['city'],
133
    });
134
135
    return bikes;
136
  }
137
  async findByLocation(lat: number, lon: number, radius: number): Promise<Bicycle[]> {
138
    const allBikes = await this.findAll();
139
    const filteredBikes = allBikes.filter((bike) => {
140
      return getDistance(bike.latitude, bike.longitude, lat, lon) <= radius;
141
    });
142
    return filteredBikes;
143
  }
144
  async findByCityAndLocation(
145
    city: any,
146
    lat: number,
147
    lon: number,
148
    radius: number,
149
  ): Promise<Bicycle[]> {
150
    const bikesInCity = await this.findByCity(city);
151
    const filteredBikes = bikesInCity.filter((bike) => {
152
      return getDistance(bike.latitude, bike.longitude, lat, lon) <= radius;
153
    });
154
    return filteredBikes;
155
  }
156
157
  private toBicycleResponse(bike: Bicycle): BicycleResponse {
158
    return {
159
      id: bike.id,
160
      batteryLevel: bike.batteryLevel,
161
      latitude: bike.latitude,
162
      longitude: bike.longitude,
163
      status: bike.status,
164
      city: bike.city?.name,
165
      createdAt: bike.createdAt,
166
      updatedAt: bike.updatedAt,
167
    };
168
  }
169
170
  toBicycleResponses(bikes: Bicycle[]): BicycleResponse[] {
171
    return bikes.map((bike) => this.toBicycleResponse(bike));
172
  }
173
}
174