order.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // package order -- сущность заказа бронирвоания
  2. package order
  3. import (
  4. "encoding/json"
  5. "fmt"
  6. "strings"
  7. "time"
  8. "adt/pkg/alias"
  9. )
  10. // Order -- сущность заказа бронирования
  11. type Order struct {
  12. Id_ alias.OrderId `json:"id"` // Номер заказа
  13. HotelId_ alias.HotelId `json:"hotel_id"` // ID отеля
  14. RoomID_ alias.RoomId `json:"room_id"` // ID номера в указанном отеле
  15. UserEmail_ alias.Email `json:"email"` // Email пользователя
  16. From_ time.Time `json:"from"` // Дата заезда
  17. To_ time.Time `json:"to"` // Дата выезда включительно
  18. LstDay_ []alias.Date `json:"lst_day"` // Список дней бронирования
  19. }
  20. // Unmarshall -- десерилаизует структуру Order из json
  21. func Unmarshall(binData []byte) (*Order, error) {
  22. sf := &Order{}
  23. err := json.Unmarshal(binData, sf)
  24. if err != nil {
  25. return nil, fmt.Errorf("order.Unmarshall(): in json.Unmarshal, err=\n\t%w", err)
  26. }
  27. if sf.HotelId_ == "" {
  28. return nil, fmt.Errorf("order.Unmarshall(): hotel_id is empty")
  29. }
  30. if sf.RoomID_ == "" {
  31. return nil, fmt.Errorf("order.Unmarshall(): room_id is empty")
  32. }
  33. if sf.UserEmail_ == "" {
  34. return nil, fmt.Errorf("order.Unmarshall(): email is empty")
  35. }
  36. if sf.From_ == (time.Time{}) {
  37. return nil, fmt.Errorf("order.Unmarshall(): from is empty")
  38. }
  39. { // Проверка email
  40. if !strings.Contains(string(sf.UserEmail_), "@") {
  41. return nil, fmt.Errorf("order.Unmarshall(): email(%q) not have @", sf.UserEmail_)
  42. }
  43. if !strings.Contains(string(sf.UserEmail_), ".") {
  44. return nil, fmt.Errorf("order.Unmarshall(): email(%q) not have .", sf.UserEmail_)
  45. }
  46. }
  47. if sf.To_ == (time.Time{}) {
  48. return nil, fmt.Errorf("order.Unmarshall(): to is empty")
  49. }
  50. if err := sf.daysBetween(); err != nil {
  51. return nil, fmt.Errorf("order.Unmarshall(): in calc daysBetween, err=\n\t%w", err)
  52. }
  53. sf.Id_ = alias.OrderId(fmt.Sprintf("%v.%v.%v.%v", sf.HotelId_, sf.RoomID_, sf.From(), sf.To()))
  54. return sf, nil
  55. }
  56. // Marshall -- сериализует структуру Order
  57. func (sf *Order) Marshall() []byte {
  58. binData, _ := json.Marshal(sf)
  59. return binData
  60. }
  61. // Room -- возвращает ID номера в отеле
  62. func (sf *Order) Room() alias.RoomId {
  63. return sf.RoomID_
  64. }
  65. // Hotel -- возвращает ID отеля
  66. func (sf *Order) Hotel() alias.HotelId {
  67. return sf.HotelId_
  68. }
  69. // Id -- возвращает номер заказа
  70. func (sf *Order) Id() alias.OrderId {
  71. return sf.Id_
  72. }
  73. func (sf *Order) daysBetween() error {
  74. if sf.From_.After(sf.To_) {
  75. return fmt.Errorf("Order.daysBetween(): from > to")
  76. }
  77. sf.LstDay_ = make([]alias.Date, 0)
  78. cleanTo := cleanDay(sf.To_)
  79. cleanNext := cleanDay(sf.From_)
  80. for { // Перебор дней на добавление
  81. cleanFrom := cleanDay(cleanNext)
  82. if cleanFrom.After(cleanTo) {
  83. break
  84. }
  85. dateOrder := alias.Date(cleanNext.UTC().Format("2006-01-02"))
  86. sf.LstDay_ = append(sf.LstDay_, dateOrder)
  87. if len(sf.LstDay_) > 60 {
  88. return fmt.Errorf("Order.daysBetween(): lst_day > 60")
  89. }
  90. cleanNext = cleanNext.AddDate(0, 0, 1)
  91. }
  92. if len(sf.LstDay_) == 0 {
  93. return fmt.Errorf("Order.daysBetween(): lst_day is empty")
  94. }
  95. return nil
  96. }
  97. // Округялет дату до дня, FIXME: дата заезда и выезда в 12:00
  98. func cleanDay(timestamp time.Time) time.Time {
  99. return time.Date(timestamp.Year(),
  100. timestamp.Month(),
  101. timestamp.Day(),
  102. 0, 0, 0, 0,
  103. time.UTC)
  104. }
  105. // listDay -- возвращает список дней бронирования
  106. func (sf *Order) ListDay() []alias.Date {
  107. return sf.LstDay_
  108. }
  109. // To -- возвращает дату окончания бронирования (включительно)
  110. func (sf *Order) To() alias.Date {
  111. return alias.Date(sf.To_.UTC().Format("2006-01-02"))
  112. }
  113. // From -- возвращает дату начала бронирования
  114. func (sf *Order) From() alias.Date {
  115. return alias.Date(sf.From_.UTC().Format("2006-01-02"))
  116. }