- Transakcyjność D2D: 3MD
-
# RC+ czyli CrossSellopodobne dodatki do rezerwacji (zwane roboczo dalej CrossSellPlus)
## Co to ma być?
R+ - dodatek (w stylu upselli) do rezerwacji D2D (tylko do takiej rezerwacji. Krzysiu popraw mnie jeśli się mylę).
## TODOs
RC+
- modele i relacje
- ReservableExtra + STI
- ^ - obsługa obrazków
- ReservationReservableExtra
- menu do ReservationReservableExtras
- tagi do menu / Menuable :-)
- Rule
- serwisy
- Wyliczanie możliwości dodania RC+'a' z Ruli (RC+ Rule Resolver czy coś)
- Rekalkulacja kwoty rezerwacji z uwzględnieniem RC+
- końcówki (klient)
- Q: getReservationPossibilities(reservationID!, date!, approxStartHour!, numPeople!, definitiveStartHour, reservationExtras: [{id: 1, quantity: 5}])
ReservationAttempt {
reservationPossible: bool (definitiveStartHour?)
hours : [{ hour: "HH:MM", available: bool }]
availableReservationExtras: [
- id
- pic_url
- title
- desc: text
- price: decimal
]
- Q: reservableExtras(+filtry) (użyte do litingu doświadczeń)
- Q: reservableExtra (szczegóły RC+ z menu)
- M: createReservation oraz updateReservation(z RC+ami)
- końcówki (admin)
- CRUD R+ (typ, menus+tagi, opis,temat,zdjęcia,...) na poziomie restauracji
- CRUD Ruli do R+
- dodanie RRE do typu rezerwacji
## Dostępność dodatków
Jego dostępność może być ograniczona kalendarzem (jeśli nie ma żadnych ruli to jest dostępny we wszystkich stolikach, jeśli ma swoje rule to są ważniejsze), posiada minimalna długość slotu która "rozpycha" rezerwację D2D - o ile jest miejsce w kalendarzu D2D.
1) ograniczona rulesami
2) lub jeśli nie ma ruli - nieograniczona (poprawcie jeśli się mylę))
3) plany śledzenia stanu magazynowego zarzucono (poprawcie jeśli się mylę)
> :cherries: Minimalna długość slotu nie jest cechą RC+ rula, ale samego RC+. Oznacza spodziewaną prędkość przeżuwania :-) Nazwijmy to tymczasowo `eating_duration` (w minutach, żeby pasowało do slotów). :cherries: no chyba, że ustalimy, że eating_duration jest cechą dania i ~~jest wyliczane z dań jakie znajdą się w RC+ie~~, ale to by pewnie komplikowało rezerwacje i "wydłużanie slotu", bo trzeba by to gdzieś keszować, bo zestaw dań w określonym RC+ie może zmieniać się w czasie.
> **nic nie wyliczamy, duration jest jeden na poziomie RC+ i tyle**
> [name=Janek][color=green]
### rozpychanie czasu rezerwacji RC+ :cherries::cherries::cherries::cherries:
załóżmy że ktoś rezerwuje D2D na 90 min
i dodaję RC+ o nazwie "Tuzin Burgerów (Sharing)". Tak się składa, że jest wyceniony na 120 min.
System powinien rozszerzyć rezerwację o różnicę 120-90 min, czyli o 30 min (90 + 30)
> :cherries: Na start w wersji v0 możemy przyjąć że każdy R+ będzie się mieścił w defaultowym slocie. Przygotować się na to na przyszłość.
> [name=Paweł][color=red]
## Oczekiwane typy "dodatków":
- degustacja - zbudowana z dań, ma jedno menu (X dań w ramach menu) :cherries: Od tego zaczniemy. Reszta ma niższe prio.
- danie flagowe - raczej jedno danie (może więcej?), opis, cena
- shareing - na ile to jest osób, cena, dla ilu osób (+ od ilu osób go pokazujemy - żarłoki)
- menu lunchowe
> :cherries: Jak dla mnie z tego wynika że potrzebujemy dodać encję `Dish`, Danie, czy cokolwiek.
> Degustacja has many Dania i DanieFlagowe has_one Danie :-)
> Sharing być może też has_one Danie
> i Menu Lunchowe pewnie has_many Dania
> [name=Janek][color=green]
> Zdaje się że dania muszą należeć do restauracji - każda ma inne...
> [name=Krzysiek][color=green]
dania muszą posiadać tagi składników (ryba, mięso, krewetki)
Dochodzi cały moduł transakcyjności w D2D / anulacji i zwrotów (do ustalenia na jakich warunkach)
> :cherries: Jak dla mnie z tego wynika że potrzebujemy STI
> [name=Janek][color=green]
> :cherries: Zastanawiam się czy czyściej / wygodniej nie było by tagować całego R+ a nie dań. To ma służyć do szukania R+ które zawierają dane skłądniki w całym zestawie. Nie widzę w tej chwili zysku nad tagowaniem poszczególnych dań - a tylko utrudnienie w dodawaniu nowy R+ gdzie przy 7-daniowym R+ trzeba będzie otagować aż 7 dań - gdzie składniki mogą się powtarzać
> [name=Paweł][color=red]
```ruby
CrossSellPlus
self.abstract_class = true
has_many :cross_sell_plus_rules
has_many :dishes # lub has_one :dish
belongs_to :reservation # must be Daily
has_many :dish_tags, through: :dishes, source :tag
end
```
```plantuml
@startuml
skinparam stereotypeCBackgroundColor<<Done>> Green
class ReservableExtra <<Done>>{
+ name
+ pictureUrls
+ type: string // STI sub class
+ restaurant <----
+ eating_duration: int // minutes
+ rules[]
+ price: decimal
+ show_as_upsell: bool //TBC urżnąć
}
class Reservation {}
note top of ReservationCrossSellPlus #0F0: zakodzone
class ReservationCrossSellPlus {
+ reservation_id
+ cross_sell_plus_id
}
class Dish <<Done>> {
+ name
+ description
+ tags[]
}
note top of Dish #0F0: zakodzone
class DishTag {
+ name
}
class ReservableExtraRule {
+ reservable_extra
}
note top of ReservableExtra : STI Ober-Class
Dish ||--|{ DishTag
Restaurant <|-- ReservableExtra
ReservableExtra ||--|{ ReservableExtraRule : RC+ has many rules
ReservableExtra }|--|{ Dish : HABTM
Reservation }|--|| ReservationCrossSellPlus
ReservableExtra }|--|| ReservationCrossSellPlus
package ReservableExtras <<Node>> {
.ReservableExtra <|-- Degustation
.ReservableExtra <|-- FlagshipDish
.ReservableExtra <|-- ShareableDish : STI subclasses
.ReservableExtra <|-- LunchMenu
}
@enduml
```
### Jak mogłaby wyglądać Rula, żeby nie było wielu zagnieżdżonych modeli Rule->WeekDay->HourRange (która to cecha mnie szczególnie wk...)
```plantuml
@startuml
class ReservableExtraRule {
+ cross_sell_plus -> FK
+ dows:char[7]
+ active:bool
+ starts_at:int
+ ends_at:int
+ date_from:date_with_zone
+ date_to:date_with_zone
}
@enduml
```
- char(7) na oznaczenie dni tygodnia np. '1110111' (wszystko oprócz czwartków), albo nawet to samo jako char(1) konwertowany na array bitów (mniej czytelne potem co prawda
- date_from i date_to mogłyby być nullable i wtedy rozumiemy, że rule trwa w nieskończoność (jeśli enabled)
A najlepiej wywalić daty w cholerę dopóki biznes tego nie zażąda. (niech operują enabled/disabled). Taniej będzie się to liczyło.
> :cherries: No nie wiem. Ogarniczenia R+ mają być tez po to żeby go np ogarniczyć w trakcie trwania festiwalu. Wynika z tego że daty by się "przydały" bo inaczej musisz wyłączyć ograniczyć R+ i potem pamiętać zeby to cofnąć
> [name=Paweł][color=red]
## Brudnopis #ignore
#### O typach binarnych które pomogą z dows
https://www.postgresql.org/docs/9.0/datatype-binary.html
PG::TextDecoder::Bytea
PG::Connection.unescape_bytea(raw)
escape_bytea
https://apidock.com/rails/v5.0.0.1/ActiveRecord/ConnectionAdapters/PostgreSQL/OID/Bytea/deserialize
https://stackoverflow.com/questions/53808048/postgres-sql-read-binary-value-from-string-field
ReservationExtras
postgres bit mask
## Końcówki
dodać obrazek do RC+
- listing doświadczeń (RC+) per region
globalny
per restauracja
czyli jeden endpoint
filtrowanie:
region
restauracja
typ
paginacja (zwracać connection)
Mutacja: dodaj doświadczenie do Rezerwacji
ReservationAttempt
- reservation
- permitted ReservationReservableExtras (RC+'s)
query: rc+ details
query: getReservationPossibilities(
date!,
approxStartHour!,
numPeople!,
definitiveStartHour,
reservationExtrasIds)
returns: ReservationAttempt:
reservationPossible: bool (definitiveStartHour?)
hours : [{ hour: "HH:MM", available: bool }]
availableReservationExtras: [
- id
- pic_url
- title
- desc: text
- price: decimal
]
## Spotkanie 10 lutego - ustalenia
- tagujemy R+y, nie Dania
- rezygnujemy na razie z "rozpychania" slotów
- rezygnujemy z Dish i modelujemy to jak Menu Festivalowe
1 R+ ma jedno menu, i to menu ma swoje tagi. A R+ sam z siebie nie ma tagów
MenusTags
Muszą być rule - dać ilość sztuk/miejsc