Commit ecb358bc authored by Enrico Bollen's avatar Enrico Bollen 💬
Browse files

Merge branch 'let-us-finish-dis' into dev

# Conflicts:
#	api/rest/routes/appointment_router.go
#	api/rest/routes/building_router.go.disabled
#	database/mongo/repositories/building_repository.go.disabled
#	database/mongo/repositories/room_repository.go
#	database/mongo/repositories/room_repository_test.go
#	internal/services/appointment_service.go
#	internal/services/room_service_test.go
parents 7c9cd786 7ba856d5
Pipeline #1853 failed with stages
in 54 seconds
package restapi
import (
"encoding/json"
"fmt"
"net/http"
u "git.coco.study/fvitt/good2go/api/rest/utils"
"git.coco.study/fvitt/good2go/internal/model"
s "git.coco.study/fvitt/good2go/internal/services"
"github.com/gorilla/mux"
)
type appointmentRouter struct{}
var (
// AppointmentRouter handles appointment requests
AppointmentRouter = &appointmentRouter{}
)
func createAppointment(res http.ResponseWriter, req *http.Request) {
type appointmentDTO struct {
RoomID int
}
var r model.Room
err := json.NewDecoder(req.Body).Decode(&r)
if err != nil {
http.Error(res, err.Error(), http.StatusBadRequest)
return
}
room, err := s.RoomService.CreateRoom(&r)
if err != nil {
fmt.Println(err)
}
err = u.SendJSON(res).Encode(room)
if err != nil {
fmt.Println(err)
}
}
func getAppointment(res http.ResponseWriter, req *http.Request) {
}
func getAllAppointments(res http.ResponseWriter, req *http.Request) {
}
func updateAppointment(res http.ResponseWriter, req *http.Request) {
}
func deleteAppointment(res http.ResponseWriter, req *http.Request) {
}
// AttachRouter Creates and attaches a sub-router to the given routers
func (a appointmentRouter) AttachRouter(router *mux.Router) {
r := router.PathPrefix("/appointments").Subrouter().StrictSlash(true)
// CREATE
r.HandleFunc("/", createAppointment).Methods("POST")
// READ
r.HandleFunc("/{id}", getAppointment).Methods("GET")
r.HandleFunc("/", getAllAppointments).Methods("GET")
// UPDATE
r.HandleFunc("/{id}", updateAppointment).Methods("PUT")
// DELETE
r.HandleFunc("/{id}", deleteAppointment).Methods("DELETE")
}
package restapi
import (
"encoding/json"
"fmt"
"log"
"net/http"
u "git.coco.study/fvitt/good2go/api/rest/utils"
"git.coco.study/fvitt/good2go/internal/model"
s "git.coco.study/fvitt/good2go/internal/services"
"github.com/gorilla/mux"
)
type buildingRouter struct{}
var (
// BuildingRouter Handles requests to /building
BuildingRouter = &buildingRouter{}
)
func createBuilding(res http.ResponseWriter, req *http.Request) {
panic("Eyyyyyy")
// Parse incoming body
var buildingDTO model.Building
err := json.NewDecoder(req.Body).Decode(&model.Building{})
if err != nil {
http.Error(res, err.Error(), http.StatusBadRequest)
return
}
fmt.Print("2")
// Create a new building instance/save it to db
building, err := s.BuildingService.CreateBuilding(&buildingDTO)
if err != nil {
http.Error(res, err.Error(), http.StatusBadRequest)
return
}
fmt.Print(building)
// Return new building
err = u.SendJSON(res).Encode(building)
if err != nil {
fmt.Println(err)
}
}
func getBuilding(res http.ResponseWriter, req *http.Request) {
buildingID := mux.Vars(req)["buildingID"]
building, buildingErr := s.BuildingService.GetBuilding(buildingID)
if buildingErr == nil {
u.SendJSON(res).Encode(building)
} else {
http.Error(res, buildingErr.Error(), http.StatusNotFound)
}
}
func getAllBuildings(res http.ResponseWriter, req *http.Request) {
buildings, err := s.BuildingService.GetAllBuildings()
if err != nil {
http.Error(res, err.Error(), http.StatusBadRequest)
return
}
err = u.SendJSON(res).Encode(buildings)
if err != nil {
fmt.Println(err)
}
}
func deleteBuilding(res http.ResponseWriter, req *http.Request) {
buildingID := mux.Vars(req)["buildingID"]
err := s.BuildingService.DeleteBuilding(buildingID)
if err != nil {
http.Error(res, err.Error(), http.StatusBadRequest)
log.Fatal(err)
}
res.WriteHeader(http.StatusOK)
}
// AttachRouter initialize Router
func (a buildingRouter) AttachRouter(router *mux.Router) {
r := router.PathPrefix("/buildings").Subrouter().StrictSlash(true)
// CREATE
r.HandleFunc("/", createBuilding).Methods("POST")
// // READ
r.HandleFunc("/{buildingID}", getBuilding).Methods("GET")
r.HandleFunc("/", getAllBuildings).Methods("GET")
// // DELETE
r.HandleFunc("/{buildingID}", deleteBuilding).Methods("DELETE")
}
......@@ -12,7 +12,6 @@ import (
var (
RoomRepo *repositories.Repository
BuildingRepo *repositories.Repository
AppointmentRepo *repositories.Repository
)
......@@ -34,10 +33,6 @@ func Init() (*mongo.Client, context.Context) {
Col: db.Collection("rooms"),
}
BuildingRepo = &repositories.Repository{
Col: db.Collection("buildings"),
}
AppointmentRepo = &repositories.Repository{
Col: db.Collection("appointments"),
}
......
package repositories
import (
"git.coco.study/fvitt/good2go/internal/model"
"go.mongodb.org/mongo-driver/mongo"
)
type AppointmentRepository interface {
CreateRoom(r *model.Appointment) (*model.Appointment, error)
UpdateRoom(r *model.Appointment)
GetRoom(document interface{}) (room *model.Appointment, err error)
GetAllRooms() []model.Room
ConnectTo(c *mongo.Collection) *Repository
}
// func (repo *Repository) findAppointmentByID(roomID string) (*model.Appointment, error) {
// }
package repositories
import (
"context"
"log"
"time"
"git.coco.study/fvitt/good2go/database/mongo/utils"
"git.coco.study/fvitt/good2go/internal/model"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
)
type BuildingRepository interface {
CreateBuilding(building *model.Building) (*mongo.InsertOneResult, error)
GetBuildingById(id interface{}) (*model.Building, error)
GetBuilding(filter *bson.M) (*model.Building, error)
UpdateBuilding(id interface{}, building *model.Building) (*mongo.UpdateResult, error)
}
func (repo *Repository) GetBuildingById(buildingID string) (*model.Building, error) {
//ctx, cancel := utils.CreateTimeoutCTX(5 * time.Second)
// defer cancel()
id, err := primitive.ObjectIDFromHex(buildingID)
if err != nil {
return nil, err
}
res := repo.Col.FindOne(context.TODO(), bson.M{"_id": id})
Building := model.Building{}
err = res.Decode(&Building)
if err != nil {
return nil, err
}
return &Building, err
}
func (repo *Repository) CreateBuilding(building *model.Building) (*model.Building, error) {
ctx, cancel := utils.CreateTimeoutCTX(time.Second * 10)
defer cancel()
// Create
insertedRes, err := repo.Col.InsertOne(ctx, &building)
if err != nil {
return nil, err
}
// Get
res := repo.Col.FindOne(ctx, bson.M{"_id": insertedRes.InsertedID})
// Decode
result := model.Building{}
err = res.Decode(&result)
if err != nil {
return nil, err
}
return &result, nil
}
func (repo *Repository) UpdateBuilding(building *model.Building) (*mongo.UpdateResult, error) {
ctx, cancel := utils.CreateTimeoutCTX(time.Second * 10)
defer cancel()
res, err := repo.Col.ReplaceOne(ctx, bson.M{"_id": &building.ID}, &building)
if err != nil {
return nil, err
}
return res, nil
}
func (repo *Repository) GetAllBuildings() ([]*model.Building, error) {
ctx, cancel := utils.CreateTimeoutCTX(time.Second * 10)
defer cancel()
res, err := repo.Col.Find(ctx, bson.M{})
if err != nil {
return nil, err
}
var buildings []*model.Building
if err = res.All(ctx, &buildings); err != nil {
log.Fatal(err)
}
return buildings, nil
}
func (repo *Repository) DeleteBuilding(buildingID string) error {
ctx, cancel := utils.CreateTimeoutCTX(5 * time.Second)
defer cancel()
id, err := primitive.ObjectIDFromHex(buildingID)
if err != nil {
return err
}
_, err = repo.Col.DeleteOne(ctx, bson.M{"_id": id})
return err
}
......@@ -69,32 +69,21 @@ func (repo *Repository) insertOne(document interface{}) (*model.Room, error) {
return &r, err
}
func (repo *Repository) updateOne(document interface{}) (*model.Room, error) {
func (repo *Repository) updateOne(room *model.Room) (*model.Room, error) {
ctx, cancel := utils.CreateTimeoutCTX(5 * time.Second)
defer cancel()
insertedResult, err := repo.Col.UpdateOne(ctx, document, document)
_, err := repo.Col.ReplaceOne(ctx, bson.M{"number": room.Number}, room)
if err != nil {
fmt.Println(err)
}
// Find
result := repo.Col.FindOne(ctx, bson.M{"_id": insertedResult.UpsertedID})
// Decode
var r model.Room
err = result.Decode(&r)
if err != nil {
return nil, err
}
// Return created entity
return &r, err
return room, err
}
func (repo *Repository) CreateRoom(r *model.Room) (*model.Room, error) {
//Check if room with same room number exists
......
......@@ -5,6 +5,7 @@ import (
"testing"
"git.coco.study/fvitt/good2go/internal/model"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
)
......@@ -24,7 +25,7 @@ func Test_roomRepository_CreateRoom(t *testing.T) {
fmt.Println(err)
}
room, err := repo.GetRoomByNumber(100)
room, err := repo.GetRoomByID(100)
if err != nil {
t.Error(err)
}
......@@ -42,7 +43,7 @@ func Test_roomRepository_UpdateRoom(t *testing.T) {
Capacity: 22,
})
room, err := repo.GetRoomByNumber(100)
room, err := repo.GetRoomByID(100)
if err != nil {
t.Error(err)
}
......@@ -53,6 +54,23 @@ func Test_roomRepository_UpdateRoom(t *testing.T) {
}
func Test_roomRepository_GetRoom(t *testing.T) {
_, err := repo.CreateRoom(&model.Room{Number: 420, Capacity: 22})
if err != nil {
fmt.Println(err)
panic(err)
}
_, err = repo.GetRoom(bson.M{
"number": 420,
})
if err != nil {
t.Error(err)
}
}
func Test_roomRepository_GetAllRooms(t *testing.T) {
rooms := repo.GetAllRooms()
......
......@@ -3,8 +3,11 @@ module git.coco.study/fvitt/good2go
go 1.14
require (
github.com/cespare/reflex v0.2.0 // indirect
github.com/getsentry/sentry-go v0.6.1
github.com/gorilla/mux v1.7.4
github.com/joho/godotenv v1.3.0
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/ogier/pflag v0.0.1 // indirect
go.mongodb.org/mongo-driver v1.3.4
)
......@@ -8,6 +8,8 @@ github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqR
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
github.com/cespare/reflex v0.2.0 h1:6d9WpWJseKjJvZEevKP7Pk42nPx2+BUTqmhNk8wZPwM=
github.com/cespare/reflex v0.2.0/go.mod h1:ooqOLJ4algvHP/oYvKWfWJ9tFUzCLDk5qkIJduMYrgI=
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
......@@ -26,6 +28,7 @@ github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHj
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4/go.mod h1:T9YF2M40nIgbVgp3rreNmTged+9HrbNTIQf1PsaIiTA=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
github.com/getsentry/sentry-go v0.6.1 h1:K84dY1/57OtWhdyr5lbU78Q/+qgzkEyGc/ud+Sipi5k=
......@@ -102,6 +105,8 @@ github.com/kataras/golog v0.0.9/go.mod h1:12HJgwBIZFNGL0EJnMRhmvGA0PQGx8VFwrZtM4
github.com/kataras/iris/v12 v12.0.1/go.mod h1:udK4vLQKkdDqMGJJVd/msuMtN6hpYJhg/lSzuxjhO+U=
github.com/kataras/neffos v0.0.10/go.mod h1:ZYmJC07hQPW67eKuzlfY7SO3bC0mw83A3j6im82hfqw=
github.com/kataras/pio v0.0.0-20190103105442-ea782b38602d/go.mod h1:NV88laa9UiiDuX9AhMbDPkGYSPugBOV6yTZB1l2K9Z0=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.9.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
......@@ -112,6 +117,7 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
......@@ -137,6 +143,8 @@ github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOA
github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM=
github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/ogier/pflag v0.0.1 h1:RW6JSWSu/RkSatfcLtogGfFgpim5p7ARQ10ECk5O750=
github.com/ogier/pflag v0.0.1/go.mod h1:zkFki7tvTa0tafRvTBIZTvzYyAu6kQhPZFnshFFPE+g=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
......@@ -234,6 +242,7 @@ golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
......
......@@ -21,20 +21,25 @@ func (a *appointmentService) AddAppointment(reqAppoint model.Appointment) (room
selectedRooms[0].AddAppointment(reqAppoint)
room = selectedRooms[0]
}
r.RoomRepo.UpdateRoom(room)
return room, err
}
// DeleteAppointment deletes an appointment on higher level.
// Takes room number and start date, finds room and deletes appointment.
func (a *appointmentService) DeleteAppointment(roomNo int, startDate string) (err error) {
func (a *appointmentService) DeleteAppointment(roomNumber int, startDate string) (err error) {
room, err := r.RoomRepo.GetRoomByNumber(roomNo)
room, err := r.RoomRepo.GetRoomByNumber(roomNumber)
if err != nil {
return err
}
room.DeleteAppointment(startDate)
r.RoomRepo.UpdateRoom(room)
return
}
......
......@@ -6,7 +6,8 @@ import (
"git.coco.study/fvitt/good2go/internal/model"
)
func TestRoomService_CreateRoom(t *testing.T) {
func TestBuildingService_CreateRoom(t *testing.T) {
BuildDefBuilding()
sampleRoom := model.Room{Capacity: 20, Number: 200}
room, err := RoomService.CreateRoom(&sampleRoom)
if err != nil {
......@@ -28,8 +29,30 @@ func TestRoomService_CreateRoom(t *testing.T) {
}
func TestRoomService_GetAllRooms(t *testing.T) {
roomsMap := RoomService.GetAllRooms()
func TestBuildingService_GetRoom(t *testing.T) {
BuildDefBuilding()
// try to get an actual room
room, err := RoomService.GetAllRooms()[0]
if err != nil {
t.Error(err)
}
if room.Number != 200 {
t.Error("got wrong room, expected 200, got: ", room.Number)
}
err = nil
room = nil
// pass wrong room id
room, err = BuildingService.GetRoom("1")
if err == nil {
t.Error("error expected, got: ", err)
}
}
func TestBuildingService_GetAllRooms(t *testing.T) {
BuildDefBuilding()
roomsMap, _ := BuildingService.GetAllRooms()
if len(roomsMap) <= 0 {
t.Error("did not get any room, expected one")
}
......@@ -41,27 +64,31 @@ func TestRoomService_GetAllRooms(t *testing.T) {
}
}
func TestRoomService_DeleteRoom(t *testing.T) {
err := RoomService.DeleteRoom(200)
func TestBuildingService_DeleteRoom(t *testing.T) {
BuildDefBuilding()
err := BuildingService.DeleteRoom("0")
if err != nil {
t.Error(err)
}
rooms := RoomService.GetAllRooms()
if len(rooms) != 0 {
t.Error("too many rooms left, expected 0, got: ", len(rooms))
building, err := BuildingService.GetBuilding("0")
if err == nil {
if len(building.Rooms) > 0 {
t.Error("too many rooms left, expected 0, got: ", len(building.Rooms))
}
}
// produce error
err = RoomService.DeleteRoom(200)
err = BuildingService.DeleteRoom("1")
if err == nil {
t.Error("expected error, got: ", err)
}
}
func TestRoomService_UpdateRoomCapacity(t *testing.T) {
room, err := RoomService.UpdateRoomCapacity(200, 20)
room2, err := RoomService.GetRoomByNumber(200)
func TestBuildingService_UpdateRoomCapacity(t *testing.T) {
BuildDefBuilding()
room, err := BuildingService.UpdateRoomCapacity("0", 20)
room2, err := BuildingService.GetRoom("0")
if err != nil {
t.Error(err)