|
@@ -0,0 +1,130 @@
|
|
|
+// package order -- сущность заказа бронирвоания
|
|
|
+package order
|
|
|
+
|
|
|
+import (
|
|
|
+ "encoding/json"
|
|
|
+ "fmt"
|
|
|
+ "strings"
|
|
|
+ "time"
|
|
|
+
|
|
|
+ "adt/pkg/alias"
|
|
|
+)
|
|
|
+
|
|
|
+// Order -- сущность заказа бронирования
|
|
|
+type Order struct {
|
|
|
+ Id_ alias.OrderId `json:"id"` // Номер заказа
|
|
|
+ HotelId_ alias.HotelId `json:"hotel_id"` // ID отеля
|
|
|
+ RoomID_ alias.RoomId `json:"room_id"` // ID номера в указанном отеле
|
|
|
+ UserEmail_ alias.Email `json:"email"` // Email пользователя
|
|
|
+ From_ time.Time `json:"from"` // Дата заезда
|
|
|
+ To_ time.Time `json:"to"` // Дата выезда включительно
|
|
|
+ LstDay_ []alias.Date `json:"lst_day"` // Список дней бронирования
|
|
|
+}
|
|
|
+
|
|
|
+// Unmarshall -- десерилаизует структуру Order из json
|
|
|
+func Unmarshall(binData []byte) (*Order, error) {
|
|
|
+ sf := &Order{}
|
|
|
+ err := json.Unmarshal(binData, sf)
|
|
|
+ if err != nil {
|
|
|
+ return nil, fmt.Errorf("order.Unmarshall(): in json.Unmarshal, err=\n\t%w", err)
|
|
|
+ }
|
|
|
+ if sf.HotelId_ == "" {
|
|
|
+ return nil, fmt.Errorf("order.Unmarshall(): hotel_id is empty")
|
|
|
+ }
|
|
|
+ if sf.RoomID_ == "" {
|
|
|
+ return nil, fmt.Errorf("order.Unmarshall(): room_id is empty")
|
|
|
+ }
|
|
|
+ if sf.UserEmail_ == "" {
|
|
|
+ return nil, fmt.Errorf("order.Unmarshall(): email is empty")
|
|
|
+ }
|
|
|
+ if sf.From_ == (time.Time{}) {
|
|
|
+ return nil, fmt.Errorf("order.Unmarshall(): from is empty")
|
|
|
+ }
|
|
|
+ { // Проверка email
|
|
|
+ if !strings.Contains(string(sf.UserEmail_), "@") {
|
|
|
+ return nil, fmt.Errorf("order.Unmarshall(): email(%q) not have @", sf.UserEmail_)
|
|
|
+ }
|
|
|
+ if !strings.Contains(string(sf.UserEmail_), ".") {
|
|
|
+ return nil, fmt.Errorf("order.Unmarshall(): email(%q) not have .", sf.UserEmail_)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if sf.To_ == (time.Time{}) {
|
|
|
+ return nil, fmt.Errorf("order.Unmarshall(): to is empty")
|
|
|
+ }
|
|
|
+ if err := sf.daysBetween(); err != nil {
|
|
|
+ return nil, fmt.Errorf("order.Unmarshall(): in calc daysBetween, err=\n\t%w", err)
|
|
|
+ }
|
|
|
+ sf.Id_ = alias.OrderId(fmt.Sprintf("%v.%v.%v.%v", sf.HotelId_, sf.RoomID_, sf.From(), sf.To()))
|
|
|
+ return sf, nil
|
|
|
+}
|
|
|
+
|
|
|
+// Marshall -- сериализует структуру Order
|
|
|
+func (sf *Order) Marshall() []byte {
|
|
|
+ binData, _ := json.Marshal(sf)
|
|
|
+ return binData
|
|
|
+}
|
|
|
+
|
|
|
+// Room -- возвращает ID номера в отеле
|
|
|
+func (sf *Order) Room() alias.RoomId {
|
|
|
+ return sf.RoomID_
|
|
|
+}
|
|
|
+
|
|
|
+// Hotel -- возвращает ID отеля
|
|
|
+func (sf *Order) Hotel() alias.HotelId {
|
|
|
+ return sf.HotelId_
|
|
|
+}
|
|
|
+
|
|
|
+// Id -- возвращает номер заказа
|
|
|
+func (sf *Order) Id() alias.OrderId {
|
|
|
+ return sf.Id_
|
|
|
+}
|
|
|
+
|
|
|
+func (sf *Order) daysBetween() error {
|
|
|
+ if sf.From_.After(sf.To_) {
|
|
|
+ return fmt.Errorf("Order.daysBetween(): from > to")
|
|
|
+ }
|
|
|
+ sf.LstDay_ = make([]alias.Date, 0)
|
|
|
+ cleanTo := cleanDay(sf.To_)
|
|
|
+ cleanNext := cleanDay(sf.From_)
|
|
|
+ for { // Перебор дней на добавление
|
|
|
+ cleanFrom := cleanDay(cleanNext)
|
|
|
+ if cleanFrom.After(cleanTo) {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ dateOrder := alias.Date(cleanNext.UTC().Format("2006-01-02"))
|
|
|
+ sf.LstDay_ = append(sf.LstDay_, dateOrder)
|
|
|
+ if len(sf.LstDay_) > 60 {
|
|
|
+ return fmt.Errorf("Order.daysBetween(): lst_day > 60")
|
|
|
+ }
|
|
|
+ cleanNext = cleanNext.AddDate(0, 0, 1)
|
|
|
+ }
|
|
|
+ if len(sf.LstDay_) == 0 {
|
|
|
+ return fmt.Errorf("Order.daysBetween(): lst_day is empty")
|
|
|
+ }
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+// Округялет дату до дня, FIXME: дата заезда и выезда в 12:00
|
|
|
+func cleanDay(timestamp time.Time) time.Time {
|
|
|
+ return time.Date(timestamp.Year(),
|
|
|
+ timestamp.Month(),
|
|
|
+ timestamp.Day(),
|
|
|
+ 0, 0, 0, 0,
|
|
|
+ time.UTC)
|
|
|
+}
|
|
|
+
|
|
|
+// listDay -- возвращает список дней бронирования
|
|
|
+func (sf *Order) ListDay() []alias.Date {
|
|
|
+ return sf.LstDay_
|
|
|
+}
|
|
|
+
|
|
|
+// To -- возвращает дату окончания бронирования (включительно)
|
|
|
+func (sf *Order) To() alias.Date {
|
|
|
+ return alias.Date(sf.To_.UTC().Format("2006-01-02"))
|
|
|
+}
|
|
|
+
|
|
|
+// From -- возвращает дату начала бронирования
|
|
|
+func (sf *Order) From() alias.Date {
|
|
|
+ return alias.Date(sf.From_.UTC().Format("2006-01-02"))
|
|
|
+}
|