first commit
This commit is contained in:
558
storage/postgresql.go
Normal file
558
storage/postgresql.go
Normal file
@@ -0,0 +1,558 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/google/uuid"
|
||||
_ "github.com/lib/pq"
|
||||
"github.com/paulmach/orb"
|
||||
"github.com/paulmach/orb/geojson"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/viper"
|
||||
"solidarity-service/internal"
|
||||
"solidarity-service/servers/utils"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type PostgresqlStorage struct {
|
||||
DbConnection *sql.DB
|
||||
Schema string
|
||||
Tables map[string]string
|
||||
}
|
||||
|
||||
func NewPostgresqlStorage(cfg *viper.Viper) (PostgresqlStorage, error) {
|
||||
var (
|
||||
host = cfg.GetString("storage.db.psql.host")
|
||||
port = cfg.GetString("storage.db.psql.port")
|
||||
user = cfg.GetString("storage.db.psql.user")
|
||||
password = cfg.GetString("storage.db.psql.password")
|
||||
dbname = cfg.GetString("storage.db.psql.dbname")
|
||||
sslmode = cfg.GetString("storage.db.psql.sslmode")
|
||||
pg_schema = cfg.GetString("storage.db.psql.schema")
|
||||
pgtables_drivers = cfg.GetString("storage.db.psql.tables.drivers")
|
||||
pgtables_passengers = cfg.GetString("storage.db.psql.tables.passengers")
|
||||
pgtables_bookings = cfg.GetString("storage.db.psql.tables.bookings")
|
||||
)
|
||||
portInt, _ := strconv.Atoi(port)
|
||||
psqlconn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=%s", host, portInt, user, password, dbname, sslmode)
|
||||
db, err := sql.Open("postgres", psqlconn)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("opening connection to postgresql failed")
|
||||
return PostgresqlStorage{}, fmt.Errorf("connection to postgresql failed")
|
||||
}
|
||||
err = db.Ping()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("ping to postgresql failed")
|
||||
return PostgresqlStorage{}, fmt.Errorf("connection to postgresql database failed")
|
||||
}
|
||||
return PostgresqlStorage{
|
||||
DbConnection: db,
|
||||
Schema: pg_schema,
|
||||
Tables: map[string]string{
|
||||
"drivers": fmt.Sprintf("%s.%s", pg_schema, pgtables_drivers),
|
||||
"bookings": fmt.Sprintf("%s.%s", pg_schema, pgtables_bookings),
|
||||
"passengers": fmt.Sprintf("%s.%s", pg_schema, pgtables_passengers),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s PostgresqlStorage) CreatePassenger(passenger internal.Passenger) (err error) {
|
||||
_, err = uuid.Parse(passenger.Passenger.ID)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Postgresql Storage CreatePassenger invalid ID")
|
||||
return err
|
||||
}
|
||||
if passenger.Passenger_pickup_date == 0 {
|
||||
errMsg := "Postgresql Storage CreatePassenger empty UNIX pickup Date timestamp"
|
||||
log.Error().Err(err).Msg(errMsg)
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
if passenger.Passenger.Alias == "" || passenger.Passenger.Operator == "" {
|
||||
errMsg := "Postgresql Storage CreatePassenger empty alias or operator FQDN."
|
||||
log.Error().Msg(errMsg)
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
preferencesJSON, err := json.Marshal(passenger.Preferences)
|
||||
if err != nil {
|
||||
errMsg := "Postgresql Storage CreatePassenger Error encoding Preferences to JSON"
|
||||
log.Error().Err(err).Msg(errMsg)
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
departureJSON, err := json.Marshal(passenger.Passenger_departure_address)
|
||||
if err != nil {
|
||||
errMsg := "Postgresql Storage CreatePassenger Error encoding departure Feature to JSON"
|
||||
log.Error().Err(err).Msg(errMsg)
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
|
||||
destinationJSON, err := json.Marshal(passenger.Passenger_destination_address)
|
||||
if err != nil {
|
||||
errMsg := "Postgresql Storage CreatePassenger Error converting destination Feature to JSON"
|
||||
log.Error().Err(err).Msg(errMsg)
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
_, err = s.DbConnection.Exec(fmt.Sprintf("INSERT INTO %s (passenger_id, passenger_departure_route, passenger_destination_route, alias, last_name, first_name, grade, picture, verified_identity, operator, preferences, passenger_pickup_date) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12)", s.Tables["passengers"]),
|
||||
passenger.Passenger.ID,
|
||||
departureJSON,
|
||||
destinationJSON,
|
||||
passenger.Passenger.Alias,
|
||||
passenger.Passenger.LastName,
|
||||
passenger.Passenger.FirstName,
|
||||
passenger.Passenger.Grade,
|
||||
passenger.Passenger.Picture,
|
||||
passenger.Passenger.VerifiedIdentity,
|
||||
passenger.Passenger.Operator,
|
||||
preferencesJSON,
|
||||
passenger.Passenger_pickup_date)
|
||||
if err != nil {
|
||||
errMsg := "Postgresql Storage CreatePassenger Error inserting data into the database"
|
||||
log.Error().Err(err).Msg(errMsg)
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s PostgresqlStorage) GetPassenger(passengerID string) (passenger internal.Passenger, err error) {
|
||||
var preferencesJSON []byte
|
||||
var departure_address []byte
|
||||
var destination_address []byte
|
||||
err = s.DbConnection.QueryRow(fmt.Sprintf("SELECT passenger_departure_route, passenger_destination_route, alias, last_name, first_name, grade, picture, verified_identity, operator, preferences, passenger_pickup_date , passenger_id FROM %s WHERE passenger_id = $1", s.Tables["passengers"]), passengerID).
|
||||
Scan(
|
||||
&departure_address,
|
||||
&destination_address,
|
||||
&passenger.Passenger.Alias,
|
||||
&passenger.Passenger.LastName,
|
||||
&passenger.Passenger.FirstName,
|
||||
&passenger.Passenger.Grade,
|
||||
&passenger.Passenger.Picture,
|
||||
&passenger.Passenger.VerifiedIdentity,
|
||||
&passenger.Passenger.Operator,
|
||||
&preferencesJSON,
|
||||
&passenger.Passenger_pickup_date,
|
||||
&passenger.Passenger.ID,
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
errMsg := "Postgresql Storage GetPassenger Error querying data from the database"
|
||||
log.Error().Err(err).Msg(errMsg)
|
||||
return passenger, errors.New(errMsg)
|
||||
}
|
||||
|
||||
err = json.Unmarshal(preferencesJSON, &passenger.Preferences)
|
||||
if err != nil {
|
||||
errMsg := "Postgresql Storage GetPassenger Error decoding Preferences from JSON"
|
||||
log.Error().Err(err).Msg(errMsg)
|
||||
return passenger, errors.New(errMsg)
|
||||
}
|
||||
passenger.Passenger_destination_address, err = geojson.UnmarshalFeature(destination_address)
|
||||
if err != nil {
|
||||
errMsg := "Postgresql Storage GetPassenger Error decoding Passenger destination route into GeoJSON"
|
||||
log.Error().Err(err).Msg(errMsg)
|
||||
return passenger, errors.New(errMsg)
|
||||
}
|
||||
passenger.Passenger_departure_address, err = geojson.UnmarshalFeature(departure_address)
|
||||
if err != nil {
|
||||
errMsg := "Postgresql Storage GetPassenger Error decoding Passenger departure route into GeoJSON"
|
||||
log.Error().Err(err).Msg(errMsg)
|
||||
return passenger, errors.New(errMsg)
|
||||
}
|
||||
return passenger, nil
|
||||
}
|
||||
|
||||
func (s PostgresqlStorage) CreateDriver(driver internal.Driver) (err error) {
|
||||
var availabilities []byte
|
||||
_, err = uuid.Parse(driver.Driver.ID)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Postgresql Storage CreateDriver invalid ID")
|
||||
return err
|
||||
}
|
||||
departureJSON, err := json.Marshal(driver.Driver_departure_address)
|
||||
if err != nil {
|
||||
errMsg := "Postgresql Storage CreateDriver Error encoding departure Feature to JSON"
|
||||
log.Error().Err(err).Msg(errMsg)
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
preferencesJSON, err := json.Marshal(driver.Preferences)
|
||||
if err != nil {
|
||||
errMsg := "Postgresql Storage CreateDriver Error encoding Preferences to JSON"
|
||||
log.Error().Err(err).Msg(errMsg)
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
carJSON, err := json.Marshal(driver.Car)
|
||||
if err != nil {
|
||||
errMsg := "Postgresql Storage CreateDriver Error encoding Car to JSON"
|
||||
log.Error().Err(err).Msg(errMsg)
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
if driver.Driver.Alias == "" || driver.Driver.Operator == "" {
|
||||
errMsg := "Postgresql Storage CreateDriver empty alias or operator FQDN."
|
||||
log.Error().Msg(errMsg)
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
if driver.AvailabilitiesType != internal.Punctual && driver.AvailabilitiesType != internal.Regular {
|
||||
errMsg := "Postgresql Storage CreateDriver invalid Availabilities Type"
|
||||
log.Error().Msg(errMsg)
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
if driver.Radius == 0 {
|
||||
errMsg := "Postgresql Storage CreateDriver Radius has to be defined"
|
||||
log.Error().Msg(errMsg)
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
switch driver.AvailabilitiesType {
|
||||
case internal.Punctual:
|
||||
availabilities, err = json.Marshal(driver.PunctualAvailabilities)
|
||||
if err != nil {
|
||||
errMsg := "Postgresql Storage CreateDriver error converting Punctual availabilities"
|
||||
log.Error().Msg(errMsg)
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
case internal.Regular:
|
||||
availabilities, err = json.Marshal(driver.RegularAvailabilities)
|
||||
if err != nil {
|
||||
errMsg := "Postgresql Storage CreateDriver error converting Regular availabilities"
|
||||
log.Error().Msg(errMsg)
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
}
|
||||
_, err = s.DbConnection.Exec(fmt.Sprintf("INSERT INTO %s (driver_id,driver_departure_route,driver_radius,last_name,first_name,grade,alias,picture,verified_identity,preferences,availabilities_type,availabilities,operator , car) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14)", s.Tables["drivers"]),
|
||||
driver.Driver.ID,
|
||||
departureJSON,
|
||||
driver.Radius,
|
||||
driver.Driver.LastName,
|
||||
driver.Driver.FirstName,
|
||||
driver.Driver.Grade,
|
||||
driver.Driver.Alias,
|
||||
driver.Driver.Picture,
|
||||
driver.Driver.VerifiedIdentity,
|
||||
preferencesJSON,
|
||||
driver.AvailabilitiesType,
|
||||
string(availabilities),
|
||||
driver.Driver.Operator,
|
||||
carJSON,
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
errMsg := "Postgresql Storage CreateDriver Error inserting data into the database"
|
||||
log.Error().Err(err).Msg(errMsg)
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s PostgresqlStorage) GetDriver(driverID string) (driver internal.Driver, err error) {
|
||||
var preferencesJSON []byte
|
||||
var departureAddress []byte
|
||||
var availabilitiesJSON []byte
|
||||
var carJSON []byte
|
||||
err = s.DbConnection.QueryRow(fmt.Sprintf("SELECT driver_departure_route, driver_radius, last_name, first_name, grade, alias, picture, verified_identity, preferences, availabilities_type, availabilities, operator , driver_id , car FROM %s WHERE driver_id = $1", s.Tables["drivers"]), driverID).
|
||||
Scan(
|
||||
&departureAddress,
|
||||
&driver.Radius,
|
||||
&driver.Driver.LastName,
|
||||
&driver.Driver.FirstName,
|
||||
&driver.Driver.Grade,
|
||||
&driver.Driver.Alias,
|
||||
&driver.Driver.Picture,
|
||||
&driver.Driver.VerifiedIdentity,
|
||||
&preferencesJSON,
|
||||
&driver.AvailabilitiesType,
|
||||
&availabilitiesJSON,
|
||||
&driver.Driver.Operator,
|
||||
&driver.Driver.ID,
|
||||
&carJSON,
|
||||
)
|
||||
if err != nil {
|
||||
errMsg := "Postgresql Storage GetDriver Error querying data from the database"
|
||||
log.Error().Err(err).Msg(errMsg)
|
||||
return driver, errors.New(errMsg)
|
||||
}
|
||||
|
||||
err = json.Unmarshal(preferencesJSON, &driver.Preferences)
|
||||
if err != nil {
|
||||
errMsg := "Postgresql Storage GetDriver Error decoding Preferences from JSON"
|
||||
log.Error().Err(err).Msg(errMsg)
|
||||
return driver, errors.New(errMsg)
|
||||
}
|
||||
err = json.Unmarshal(carJSON, &driver.Car)
|
||||
if err != nil {
|
||||
errMsg := "Postgresql Storage GetDriver Error decoding Car from JSON"
|
||||
log.Error().Err(err).Msg(errMsg)
|
||||
return driver, errors.New(errMsg)
|
||||
}
|
||||
driver.Driver_departure_address, err = geojson.UnmarshalFeature(departureAddress)
|
||||
if err != nil {
|
||||
errMsg := "Postgresql Storage GetDriver Error decoding Driver departure route into GeoJSON"
|
||||
log.Error().Err(err).Msg(errMsg)
|
||||
return driver, errors.New(errMsg)
|
||||
}
|
||||
|
||||
switch driver.AvailabilitiesType {
|
||||
case internal.Regular:
|
||||
err = json.Unmarshal(availabilitiesJSON, &driver.RegularAvailabilities)
|
||||
if err != nil {
|
||||
errMsg := "Postgresql Storage GetDriver Error decoding Regular Availabilities from JSON"
|
||||
log.Error().Err(err).Msg(errMsg)
|
||||
return driver, errors.New(errMsg)
|
||||
}
|
||||
case internal.Punctual:
|
||||
err = json.Unmarshal(availabilitiesJSON, &driver.PunctualAvailabilities)
|
||||
if err != nil {
|
||||
errMsg := "Postgresql Storage GetDriver Error decoding Punctual Availabilities from JSON"
|
||||
log.Error().Err(err).Msg(errMsg)
|
||||
return driver, errors.New(errMsg)
|
||||
}
|
||||
default:
|
||||
errMsg := "Postgresql Storage GetDriver Invalid Availabilities Type"
|
||||
log.Error().Msg(errMsg)
|
||||
return driver, errors.New(errMsg)
|
||||
}
|
||||
|
||||
return driver, nil
|
||||
}
|
||||
|
||||
func (s PostgresqlStorage) CreateBooking(booking internal.BookingRequest) (err error) {
|
||||
_, err = uuid.Parse(booking.Driver_id)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Postgresql Storage CreateBooking invalid Driver ID")
|
||||
return err
|
||||
}
|
||||
_, err = uuid.Parse(booking.Passenger_id)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Postgresql Storage CreateBooking invalid Passenger ID")
|
||||
return err
|
||||
}
|
||||
_, err = uuid.Parse(booking.ID)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Postgresql Storage CreateBooking invalid Booking ID")
|
||||
return err
|
||||
}
|
||||
if booking.Operator == "" {
|
||||
log.Error().Err(err).Msg("Postgresql Storage CreateBooking empty operator")
|
||||
return err
|
||||
}
|
||||
_, err = s.DbConnection.Exec(fmt.Sprintf("INSERT INTO %s (booking_id , passenger_id , driver_id , operator, booking_status) VALUES ($1,$2,$3,$4,$5)", s.Tables["bookings"]),
|
||||
booking.ID,
|
||||
booking.Passenger_id,
|
||||
booking.Driver_id,
|
||||
booking.Operator,
|
||||
booking.Status,
|
||||
)
|
||||
if err != nil {
|
||||
errMsg := "Postgresql Storage CreateBooking Error inserting data into the database"
|
||||
log.Error().Err(err).Msg(errMsg)
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s PostgresqlStorage) GetBooking(id string) (booking internal.Booking, err error) {
|
||||
err = s.DbConnection.QueryRow(fmt.Sprintf("SELECT booking_id , passenger_id , driver_id , booking_status FROM %s WHERE booking_id = $1", s.Tables["bookings"]), id).
|
||||
Scan(
|
||||
&booking.ID,
|
||||
&booking.Passenger.ID,
|
||||
&booking.Driver.ID,
|
||||
&booking.Status,
|
||||
)
|
||||
fmt.Println(err)
|
||||
if err != nil {
|
||||
errMsg := "Postgresql Storage GetBooking Error getting booking"
|
||||
log.Error().Err(err).Msg(errMsg)
|
||||
return booking, errors.New(errMsg + err.Error())
|
||||
}
|
||||
passenger, err := s.GetPassenger(booking.Passenger.ID)
|
||||
if err != nil {
|
||||
errMsg := "Postgresql Storage GetBooking Error getting passenger"
|
||||
log.Error().Err(err).Msg(errMsg)
|
||||
return booking, errors.New(errMsg + err.Error())
|
||||
}
|
||||
booking.Passenger = passenger.Passenger
|
||||
booking.PassengerPickupAddress = passenger.Passenger_departure_address
|
||||
booking.PassengerDropAddress = passenger.Passenger_destination_address
|
||||
driver, err := s.GetDriver(booking.Driver.ID)
|
||||
if err != nil {
|
||||
errMsg := "Postgresql Storage GetBooking Error getting driver"
|
||||
log.Error().Err(err).Msg(errMsg)
|
||||
return booking, errors.New(errMsg + err.Error())
|
||||
}
|
||||
booking.Driver = driver.Driver
|
||||
return booking, nil
|
||||
}
|
||||
|
||||
func (s PostgresqlStorage) UpdateBookingStatus(id string, status internal.BookingStatus) (err error) {
|
||||
_, err = uuid.Parse(id)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Postgresql Storage UpdateBookingStatus invalid Booking ID")
|
||||
return err
|
||||
}
|
||||
_, err = s.GetBooking(id)
|
||||
if err != nil {
|
||||
return errors.New(err.Error())
|
||||
}
|
||||
query := fmt.Sprintf("UPDATE %s SET booking_status = $1 WHERE booking_id = $2", s.Tables["bookings"])
|
||||
_, err = s.DbConnection.Exec(query, status, id)
|
||||
if err != nil {
|
||||
errMsg := "Postgresql Storage UpdateBookingStatus Error updating booking status"
|
||||
log.Error().Err(err).Msg(errMsg)
|
||||
return errors.New(errMsg)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s PostgresqlStorage) FilterUserBookingsByStatus(user_type string, status internal.BookingStatus, user_id string) (bookings []internal.Booking, err error) {
|
||||
_, err = uuid.Parse(user_id)
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid uuid")
|
||||
}
|
||||
|
||||
if user_type != "driver" && user_type != "passenger" {
|
||||
return nil, errors.New("invalid user type")
|
||||
}
|
||||
switch user_type {
|
||||
case "driver":
|
||||
rows, err := s.DbConnection.Query(fmt.Sprintf("SELECT booking_id, passenger_id, driver_id, booking_status FROM %s WHERE driver_id = $1 AND booking_status = $2", s.Tables["bookings"]),
|
||||
user_id, status)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var booking internal.Booking
|
||||
if err := rows.Scan(&booking.ID, &booking.Passenger.ID, &booking.Driver.ID, &booking.Status); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bookings = append(bookings, booking)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case "passenger":
|
||||
rows, err := s.DbConnection.Query(fmt.Sprintf("SELECT booking_id, passenger_id, driver_id, booking_status FROM %s WHERE passenger_id = $1 AND booking_status = $2", s.Tables["bookings"]),
|
||||
user_id, status)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var booking internal.Booking
|
||||
if err := rows.Scan(&booking.ID, &booking.Passenger.ID, &booking.Driver.ID, &booking.Status); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bookings = append(bookings, booking)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
}
|
||||
return bookings, nil
|
||||
}
|
||||
|
||||
func (s PostgresqlStorage) GetAllDrivers(date int64) (drivers []internal.Driver, err error) {
|
||||
rows, err := s.DbConnection.Query(fmt.Sprintf("SELECT driver_id, driver_departure_route, driver_radius, last_name, first_name, grade, alias, picture, verified_identity, preferences, availabilities_type, availabilities, operator, car FROM %s", s.Tables["drivers"]))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for rows.Next() {
|
||||
var driver internal.Driver
|
||||
var departureRoute []byte
|
||||
var preferencesJSON []byte
|
||||
var availabilitiesJSON []byte
|
||||
var carJSON []byte
|
||||
|
||||
if err := rows.Scan(
|
||||
&driver.Driver.ID,
|
||||
&departureRoute,
|
||||
&driver.Radius,
|
||||
&driver.Driver.LastName,
|
||||
&driver.Driver.FirstName,
|
||||
&driver.Driver.Grade,
|
||||
&driver.Driver.Alias,
|
||||
&driver.Driver.Picture,
|
||||
&driver.Driver.VerifiedIdentity,
|
||||
&preferencesJSON,
|
||||
&driver.AvailabilitiesType,
|
||||
&availabilitiesJSON,
|
||||
&driver.Driver.Operator,
|
||||
&carJSON,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(departureRoute, &driver.Driver_departure_address); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := json.Unmarshal(preferencesJSON, &driver.Preferences); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := json.Unmarshal(carJSON, &driver.Car); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Filter drivers based on date matching punctual or regular availabilities.
|
||||
if driver.AvailabilitiesType == internal.Punctual {
|
||||
if err := json.Unmarshal(availabilitiesJSON, &driver.PunctualAvailabilities); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Convert the date to the day of the week and make it lowercase.
|
||||
dayOfWeek := strings.ToLower(time.Unix(date, 0).UTC().Format("Mon"))
|
||||
|
||||
for _, avail := range driver.PunctualAvailabilities {
|
||||
// Extract the day part of the punctual driver's date and compare.
|
||||
availDate := time.Unix(avail.Date, 0)
|
||||
if strings.ToLower(availDate.Format("Mon")) == dayOfWeek {
|
||||
drivers = append(drivers, driver)
|
||||
break
|
||||
}
|
||||
}
|
||||
} else if driver.AvailabilitiesType == internal.Regular {
|
||||
if err := json.Unmarshal(availabilitiesJSON, &driver.RegularAvailabilities); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Convert the date to the day of the week and make it lowercase.
|
||||
dayOfWeek := strings.ToLower(time.Unix(date, 0).UTC().Format("Mon"))
|
||||
for _, avail := range driver.RegularAvailabilities {
|
||||
if strings.ToLower(avail.DayOfWeek) == dayOfWeek {
|
||||
drivers = append(drivers, driver)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return drivers, nil
|
||||
}
|
||||
|
||||
func (s PostgresqlStorage) DriverJourneys(departure_route *geojson.Feature, departure_date int64) (drivers []internal.Driver, err error) {
|
||||
allDrivers, err := s.GetAllDrivers(departure_date)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, driver := range allDrivers {
|
||||
// Check if the departure route is the same as the driver's departure route.
|
||||
if departure_route.Point().Y() == driver.Driver_departure_address.Point().Y() && departure_route.Point().X() == driver.Driver_departure_address.Point().X() {
|
||||
drivers = append(drivers, driver)
|
||||
} else {
|
||||
// Calculate the distance between the departure point and the driver's departure route.
|
||||
coords1 := departure_route.Geometry.(orb.Point)
|
||||
coords2 := driver.Driver_departure_address.Geometry.(orb.Point)
|
||||
distance := utils.Haversine(coords1[1], coords1[0], coords2[1], coords2[0])
|
||||
if int64(distance) <= int64(driver.Radius) {
|
||||
drivers = append(drivers, driver)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return drivers, nil
|
||||
}
|
||||
168
storage/postgresql/schema.hcl
Normal file
168
storage/postgresql/schema.hcl
Normal file
@@ -0,0 +1,168 @@
|
||||
|
||||
table "passengers" {
|
||||
schema = schema.solidarity_service
|
||||
column "passenger_id" {
|
||||
null = false
|
||||
type = uuid
|
||||
}
|
||||
column "passenger_departure_route" {
|
||||
null = false
|
||||
type = jsonb
|
||||
}
|
||||
column "passenger_destination_route" {
|
||||
null = false
|
||||
type = jsonb
|
||||
}
|
||||
column "alias" {
|
||||
null = false
|
||||
type = varchar(15)
|
||||
}
|
||||
column "last_name" {
|
||||
null = true
|
||||
type = text
|
||||
}
|
||||
column "first_name" {
|
||||
null = true
|
||||
type = text
|
||||
}
|
||||
column "grade" {
|
||||
null = true
|
||||
type = int
|
||||
}
|
||||
column "picture" {
|
||||
null = true
|
||||
type = varchar(200)
|
||||
}
|
||||
column "verified_identity"{
|
||||
null = true
|
||||
type = bool
|
||||
}
|
||||
column "operator" {
|
||||
null = false
|
||||
type = varchar(35)
|
||||
}
|
||||
column "preferences" {
|
||||
null = true
|
||||
type = jsonb
|
||||
}
|
||||
column "passenger_pickup_date" {
|
||||
null = false
|
||||
type = int
|
||||
}
|
||||
primary_key {
|
||||
columns = [column.passenger_id]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
table "drivers" {
|
||||
schema = schema.solidarity_service
|
||||
column "driver_id" {
|
||||
null = false
|
||||
type = uuid
|
||||
}
|
||||
column "driver_departure_route" {
|
||||
null = false
|
||||
type = jsonb
|
||||
}
|
||||
column "driver_radius" {
|
||||
null = false
|
||||
type = integer
|
||||
}
|
||||
column "last_name" {
|
||||
null = true
|
||||
type = text
|
||||
}
|
||||
column "first_name" {
|
||||
null = true
|
||||
type = text
|
||||
}
|
||||
column "grade" {
|
||||
null = true
|
||||
type = int
|
||||
}
|
||||
column "alias" {
|
||||
null = false
|
||||
type = varchar(15)
|
||||
}
|
||||
column "picture" {
|
||||
null = true
|
||||
type = text
|
||||
}
|
||||
column "verified_identity"{
|
||||
null = true
|
||||
type = bool
|
||||
}
|
||||
column "preferences" {
|
||||
null = true
|
||||
type = jsonb
|
||||
}
|
||||
column "availabilities_type" {
|
||||
null = false
|
||||
type = enum.availabilities_type
|
||||
}
|
||||
column "availabilities" {
|
||||
null = false
|
||||
type = jsonb
|
||||
}
|
||||
column "car" {
|
||||
null = true
|
||||
type = jsonb
|
||||
}
|
||||
column "operator" {
|
||||
null = false
|
||||
type = varchar(35)
|
||||
}
|
||||
primary_key {
|
||||
columns = [column.driver_id]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
table "bookings" {
|
||||
schema = schema.solidarity_service
|
||||
column "booking_id" {
|
||||
null = false
|
||||
type = uuid
|
||||
}
|
||||
column "driver_id" {
|
||||
null = false
|
||||
type = uuid
|
||||
}
|
||||
column "operator" {
|
||||
null = false
|
||||
type = varchar(35)
|
||||
}
|
||||
column "passenger_id" {
|
||||
null = false
|
||||
type = uuid
|
||||
}
|
||||
column "booking_status" {
|
||||
null = false
|
||||
type = enum.booking_status
|
||||
}
|
||||
primary_key {
|
||||
columns = [column.booking_id]
|
||||
}
|
||||
foreign_key "bookings_driver_id_fkey" {
|
||||
columns = [column.driver_id]
|
||||
ref_columns = [table.drivers.column.driver_id]
|
||||
}
|
||||
foreign_key "group_members_passenger_id_fkey" {
|
||||
columns = [column.passenger_id]
|
||||
ref_columns = [table.passengers.column.passenger_id]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum "booking_status" {
|
||||
schema = schema.solidarity_service
|
||||
values = ["INITIATED", "WAITING_PASSENGER_CONFIRMATION", "WAITING_DRIVER_CONFIRMATION", "CONFIRMED", "CANCELLED", "COMPLETED_PENDING_VALIDATION", "VALIDATED"]
|
||||
}
|
||||
enum "availabilities_type" {
|
||||
schema = schema.solidarity_service
|
||||
values = ["PUNCTUAL","REGULAR"]
|
||||
}
|
||||
|
||||
schema "solidarity_service" {
|
||||
}
|
||||
34
storage/storage.go
Normal file
34
storage/storage.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/paulmach/orb/geojson"
|
||||
"github.com/spf13/viper"
|
||||
"solidarity-service/internal"
|
||||
)
|
||||
|
||||
type Storage interface {
|
||||
CreatePassenger(passenger internal.Passenger) (err error)
|
||||
GetPassenger(passengerID string) (passenger internal.Passenger, err error)
|
||||
CreateDriver(driver internal.Driver) (err error)
|
||||
GetDriver(driverID string) (driver internal.Driver, err error)
|
||||
GetBooking(id string) (booking internal.Booking, err error)
|
||||
CreateBooking(booking internal.BookingRequest) (err error)
|
||||
UpdateBookingStatus(id string, status internal.BookingStatus) (err error)
|
||||
FilterUserBookingsByStatus(user_type string, status internal.BookingStatus, user_id string) (bookings []internal.Booking, err error)
|
||||
DriverJourneys(departure_route *geojson.Feature, departure_date int64) (drivers []internal.Driver, err error)
|
||||
GetAllDrivers(date int64) (drivers []internal.Driver, err error)
|
||||
}
|
||||
|
||||
func NewStorage(cfg *viper.Viper) (Storage, error) {
|
||||
var (
|
||||
storage_type = cfg.GetString("storage.db.type")
|
||||
)
|
||||
switch storage_type {
|
||||
case "psql":
|
||||
s, err := NewPostgresqlStorage(cfg)
|
||||
return s, err
|
||||
default:
|
||||
return nil, fmt.Errorf("storage type %v is not supported", storage_type)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user