diff --git a/stationapi/proto b/stationapi/proto index b0508057..7eede39e 160000 --- a/stationapi/proto +++ b/stationapi/proto @@ -1 +1 @@ -Subproject commit b050805770f4063d509b3acb5016f9464dc96417 +Subproject commit 7eede39eb74fac9cde5e3ed0535cc1aff8b95580 diff --git a/stationapi/src/domain/repository/station_repository.rs b/stationapi/src/domain/repository/station_repository.rs index 9bb53d82..151c24a3 100644 --- a/stationapi/src/domain/repository/station_repository.rs +++ b/stationapi/src/domain/repository/station_repository.rs @@ -39,6 +39,10 @@ pub trait StationRepository: Send + Sync + 'static { transport_type: Option, ) -> Result, DomainError>; async fn get_by_line_group_id(&self, line_group_id: u32) -> Result, DomainError>; + async fn get_by_line_group_id_vec( + &self, + line_group_ids: &[u32], + ) -> Result, DomainError>; async fn get_route_stops( &self, from_station_id: u32, @@ -219,6 +223,24 @@ mod tests { Ok(result) } + async fn get_by_line_group_id_vec( + &self, + line_group_ids: &[u32], + ) -> Result, DomainError> { + let result: Vec = self + .stations + .values() + .filter(|station| { + station + .line_group_cd + .map(|v| line_group_ids.contains(&(v as u32))) + .unwrap_or(false) + }) + .cloned() + .collect(); + Ok(result) + } + async fn get_route_stops( &self, from_station_id: u32, diff --git a/stationapi/src/infrastructure/station_repository.rs b/stationapi/src/infrastructure/station_repository.rs index 0e111e88..d1615b68 100644 --- a/stationapi/src/infrastructure/station_repository.rs +++ b/stationapi/src/infrastructure/station_repository.rs @@ -272,6 +272,14 @@ impl StationRepository for MyStationRepository { InternalStationRepository::get_by_line_group_id(line_group_id, &mut conn).await } + async fn get_by_line_group_id_vec( + &self, + line_group_ids: &[u32], + ) -> Result, DomainError> { + let mut conn = self.pool.acquire().await?; + InternalStationRepository::get_by_line_group_id_vec(line_group_ids, &mut conn).await + } + async fn get_route_stops( &self, from_station_id: u32, @@ -1343,6 +1351,112 @@ impl InternalStationRepository { Ok(stations) } + async fn get_by_line_group_id_vec( + line_group_ids: &[u32], + conn: &mut PgConnection, + ) -> Result, DomainError> { + if line_group_ids.is_empty() { + return Ok(vec![]); + } + + let params = (1..=line_group_ids.len()) + .map(|i| format!("${i}")) + .collect::>() + .join(", "); + + let order_case = line_group_ids + .iter() + .enumerate() + .map(|(i, _)| format!("WHEN ${} THEN {}", i + 1 + line_group_ids.len(), i)) + .collect::>() + .join(" "); + + let query_str = format!( + r#"SELECT + s.station_cd, + s.station_g_cd, + s.station_name, + s.station_name_k, + s.station_name_r, + s.station_name_rn, + s.station_name_zh, + s.station_name_ko, + s.station_number1, + s.station_number2, + s.station_number3, + s.station_number4, + s.three_letter_code, + s.line_cd, + s.pref_cd, + s.post, + s.address, + s.lon, + s.lat, + s.open_ymd, + s.close_ymd, + s.e_status, + s.e_sort, + COALESCE(NULLIF(COALESCE(a.line_name, l.line_name), ''), NULL) AS line_name, + COALESCE(NULLIF(COALESCE(a.line_name_k, l.line_name_k), ''), NULL) AS line_name_k, + COALESCE(NULLIF(COALESCE(a.line_name_h, l.line_name_h), ''), NULL) AS line_name_h, + COALESCE(NULLIF(COALESCE(a.line_name_r, l.line_name_r), ''), NULL) AS line_name_r, + COALESCE(NULLIF(COALESCE(a.line_name_zh, l.line_name_zh), ''), NULL) AS line_name_zh, + COALESCE(NULLIF(COALESCE(a.line_name_ko, l.line_name_ko), ''), NULL) AS line_name_ko, + COALESCE(NULLIF(COALESCE(a.line_color_c, l.line_color_c), ''), NULL) AS line_color_c, + l.company_cd, + l.line_type, + l.line_symbol1, + l.line_symbol2, + l.line_symbol3, + l.line_symbol4, + l.line_symbol1_color, + l.line_symbol2_color, + l.line_symbol3_color, + l.line_symbol4_color, + l.line_symbol1_shape, + l.line_symbol2_shape, + l.line_symbol3_shape, + l.line_symbol4_shape, + COALESCE(l.average_distance, 0.0)::DOUBLE PRECISION AS average_distance, + sst.id AS sst_id, + sst.type_cd, + sst.line_group_cd, + sst.pass, + t.id AS type_id, + t.type_name, + t.type_name_k, + t.type_name_r, + t.type_name_zh, + t.type_name_ko, + t.color, + t.direction, + t.kind, + s.transport_type + FROM stations AS s + JOIN lines AS l ON l.line_cd = s.line_cd AND l.e_status = 0 + JOIN station_station_types AS sst ON sst.line_group_cd IN ( {params} ) AND sst.station_cd = s.station_cd + JOIN types AS t ON t.type_cd = sst.type_cd + LEFT JOIN line_aliases AS la ON la.station_cd = s.station_cd + LEFT JOIN aliases AS a ON a.id = la.alias_cd + WHERE + s.e_status = 0 + ORDER BY CASE sst.line_group_cd {order_case} END, sst.id"# + ); + + let mut query = sqlx::query_as::<_, StationRow>(&query_str); + for id in line_group_ids { + query = query.bind(*id as i32); + } + for id in line_group_ids { + query = query.bind(*id as i32); + } + + let rows = query.fetch_all(conn).await?; + let stations: Vec = rows.into_iter().map(|row| row.into()).collect(); + + Ok(stations) + } + async fn get_route_stops( from_station_id: u32, to_station_id: u32, diff --git a/stationapi/src/presentation/controller/grpc.rs b/stationapi/src/presentation/controller/grpc.rs index 6716fc0c..846d5f86 100644 --- a/stationapi/src/presentation/controller/grpc.rs +++ b/stationapi/src/presentation/controller/grpc.rs @@ -9,7 +9,8 @@ use crate::{ station_api_server::StationApi, GetConnectedStationsRequest, GetLineByIdListRequest, GetLineByIdRequest, GetLinesByNameRequest, GetRouteRequest, GetStationByCoordinatesRequest, GetStationByGroupIdRequest, GetStationByIdListRequest, GetStationByIdRequest, - GetStationByLineIdListRequest, GetStationByLineIdRequest, GetStationsByLineGroupIdRequest, + GetStationByLineIdListRequest, GetStationByLineIdRequest, + GetStationsByLineGroupIdListRequest, GetStationsByLineGroupIdRequest, GetStationsByNameRequest, GetTrainTypesByStationIdRequest, MultipleLineResponse, MultipleStationResponse, MultipleTrainTypeResponse, Route, RouteMinimalResponse, RouteResponse, RouteTypeResponse, SingleLineResponse, SingleStationResponse, @@ -231,6 +232,26 @@ impl StationApi for MyApi { } } + async fn get_stations_by_line_group_id_list( + &self, + request: tonic::Request, + ) -> Result, tonic::Status> { + let request_ref = request.get_ref(); + let line_group_ids = &request_ref.line_group_ids; + let transport_type = convert_transport_type(request_ref.transport_type); + + match self + .query_use_case + .get_stations_by_line_group_id_vec(line_group_ids, transport_type) + .await + { + Ok(stations) => Ok(Response::new(MultipleStationResponse { + stations: stations.into_iter().map(|station| station.into()).collect(), + })), + Err(err) => Err(PresentationalError::from(err).into()), + } + } + async fn get_train_types_by_station_id( &self, request: tonic::Request, @@ -765,6 +786,14 @@ mod tests { Ok(vec![]) } + async fn get_stations_by_line_group_id_vec( + &self, + _line_group_ids: &[u32], + _transport_type: TransportTypeFilter, + ) -> Result, UseCaseError> { + Ok(vec![]) + } + async fn get_train_types_by_station_id( &self, _station_id: u32, diff --git a/stationapi/src/use_case/interactor/query.rs b/stationapi/src/use_case/interactor/query.rs index 3f57c6bf..f3d48acc 100644 --- a/stationapi/src/use_case/interactor/query.rs +++ b/stationapi/src/use_case/interactor/query.rs @@ -389,6 +389,27 @@ where Ok(stations) } + async fn get_stations_by_line_group_id_vec( + &self, + line_group_ids: &[u32], + transport_type: TransportTypeFilter, + ) -> Result, UseCaseError> { + let stations = self + .station_repository + .get_by_line_group_id_vec(line_group_ids) + .await?; + + let stations: Vec = stations + .into_iter() + .filter(|s| matches_transport_filter(s.transport_type, transport_type)) + .collect(); + + let stations = self + .update_station_vec_with_attributes(stations, None, transport_type) + .await?; + + Ok(stations) + } fn get_station_numbers(&self, station: &Station) -> Vec { let line_symbols_raw = [ &station.line_symbol1, @@ -1370,6 +1391,12 @@ mod tests { async fn get_by_line_group_id(&self, _: u32) -> Result, DomainError> { Ok(vec![]) } + async fn get_by_line_group_id_vec( + &self, + _: &[u32], + ) -> Result, DomainError> { + Ok(vec![]) + } async fn get_route_stops( &self, _: u32, @@ -1762,6 +1789,12 @@ mod tests { async fn get_by_line_group_id(&self, _: u32) -> Result, DomainError> { Ok(vec![]) } + async fn get_by_line_group_id_vec( + &self, + _: &[u32], + ) -> Result, DomainError> { + Ok(vec![]) + } async fn get_route_stops( &self, _: u32, diff --git a/stationapi/src/use_case/traits/query.rs b/stationapi/src/use_case/traits/query.rs index 13c313c0..d134c7d4 100644 --- a/stationapi/src/use_case/traits/query.rs +++ b/stationapi/src/use_case/traits/query.rs @@ -82,6 +82,11 @@ pub trait QueryUseCase: Send + Sync + 'static { line_group_id: u32, transport_type: TransportTypeFilter, ) -> Result, UseCaseError>; + async fn get_stations_by_line_group_id_vec( + &self, + line_group_ids: &[u32], + transport_type: TransportTypeFilter, + ) -> Result, UseCaseError>; async fn get_train_types_by_station_id( &self, station_id: u32,