Usługi Płatne za Czas
Przegląd
Aplikacja Syrve POS może być używana nie tylko do sprzedaży towarów i przedmiotów, ale także do usług rozliczanych za czas. Przykładem mogą być miejsca, gdzie klienci płacą za czas spędzony na miejscu (parki wodne, kręgielnie, antykawiarnie). W tym artykule używamy bilardu jako przykładu tematu.
Start & Stop
Usługę rozpoczynasz i zatrzymujesz. System śledzi czas podczas trwania usługi; „ilość” rośnie, a tym samym rośnie całkowita kwota. Gdy usługa zostanie zatrzymana, licznik czasu również się zatrzymuje. Klienci płacą tylko za czas gry.
Klienci mogą wybrać zapłatę za określony czas z góry. W takim przypadku usługa jest opłacona w całości, nawet jeśli klient zdecyduje się wyjść wcześniej. Załóżmy, że gość kupuje godzinę bilarda. W tym przypadku limit czasu i cena są ustalone i nie zmienią się, w przeciwieństwie do „ilości”, która będzie rosła wraz z upływem czasu. Po osiągnięciu limitu usługa zatrzyma się automatycznie. Alternatywnie, klienci mogą wybrać zapłatę po zakończeniu usługi za całkowity czas gry. W tym przypadku limit czasu nie jest ustawiony, a czas będzie kontynuowany aż do osiągnięcia maksymalnego dozwolonego czasu 12 godzin.
Rozpoczęcie i zatrzymanie może być powiązane z dodatkową akcją związaną ze stołem, przy którym składane jest zamówienie. W przypadku bilarda może to być włączenie światła nad stołem podczas gry: domyślnie światła są wyłączone, gdy usługa się rozpoczyna, światło zapala się, a gdy usługa się zatrzymuje, światło gaśnie. Tworzy to ograniczenie — nie więcej niż jedna jednocześnie działająca usługa na stół. Na razie to ograniczenie dotyczy wszystkich stołów, niezależnie od tego, czy takie dodatkowe akcje są ustawione, czy nie. W późniejszych wersjach to ograniczenie nie będzie dotyczyć stołów lub usług bez powiązań z urządzeniami zewnętrznymi.
Stawki
Cena usługi może zależeć od dnia tygodnia i zmieniać się w czasie. Istnieją dwa typy stawek:
- Według pory dnia — w środku dnia usługa może być tańsza niż wieczorem, co pomaga wyrównać okresy o niskim i wysokim popycie.
- Według czasu trwania usługi — pierwsza godzina może być najdroższa, podczas gdy każda kolejna godzina jest tańsza od poprzedniej, co zachęca do zakupu większej ilości czasu.
Czas jest śledzony według następujących zasad:
- Należy ustawić jednostkę pomiaru. Czas usługi jest zaokrąglany w górę do najbliższego rozliczanego interwału, na przykład, jeśli ustawione jest rozliczanie godzinowe, a czas od rozpoczęcia usługi wynosi 70 minut, klient powinien zapłacić za dwie godziny.
- Można ustawić minimalny czas trwania usługi. W takim przypadku, jeśli usługa jest używana tylko przez 10 minut, a minimalny czas trwania to pół godziny, klient zapłaci za pół godziny, nawet jeśli naliczanie za minuty jest włączone. Jeśli usługa z tymi samymi ustawieniami jest używana przez 31 minut, klient zapłaci tylko za 31 minut.
- W miarę upływu czasu system automatycznie przełącza się między stawkami i zapisuje czas usługi wykorzystany pod każdą stawką. Okresy odpowiadające różnym stawkom są wyceniane inaczej.
Struktura Danych
Usługa
IOrderServiceItem — pozycja zamówienia odpowiadająca usłudze rozliczanej za czas. Znajduje się w kolekcji IOrder.Items razem z pozycjami jedzenia (IOrderCookingItem).
Usługa płatna za czas jest produktem (IProduct) w menu o typie ProductType.Service i posiada parametry naliczania IProduct.RateSchedule (jeśli parametry naliczania nie są ustawione, usługa nie ma stawek rozliczanych za czas i może być dodana do zamówienia i opłacona jak zwykły produkt).
Kluczowe właściwości usługi płatnej za czas:
Service— produkt powiązany z usługą definiuje dostępność w menu, cenę bazową (stawka domyślna) itd.Periods— lista interwałów usługi reprezentujących różne stawki. Po rozpoczęciu usługi pierwszy okres zostanie dodany do listy. Czas i wartość okresu będą rosły aż do włączenia kolejnej stawki, co spowoduje dodanie drugiego okresu itd. Każda stawka ma przypisany jeden okres (interwał): jeśli — zgodnie ze skalą stawek — stawki są włączane na przemian, czas spędzony w pierwszym okresie będzie się zwiększał, potem to samo będzie dotyczyć drugiego okresu, a następnie znowu pierwszego.IsStarted— czy usługa jest obecnie uruchomiona.Price— bazowa cena jednostkowa (niektóre okresy mogą mieć różne stawki).TimeLimit— limit czasu. Jeśli jest ustawiony, usługa zatrzyma się automatycznie po osiągnięciu limitu. Nawet jeśli zatrzymasz usługę wcześniej, cały czas usługi musi zostać opłacony, w takim przypadku wykorzystany czas jest rejestrowany i opłacany według wcześniej skonfigurowanych okresów, natomiast niewykorzystany czas — według samej usługi (patrzRemainingLimitCost).RemainingLimitCost— cena niewykorzystanego czasu. Jeśli limit nie jest ustawiony, wynosi 0. Gdy limit jest ustawiony, należna jest pełna cena limitu czasowego (usługa nie została jeszcze rozpoczęta, nie wykorzystano zamówionego czasu). Z czasem całkowita wartość limitu czasowego będzie malała (aż do zera), podczas gdy wartość okresu będzie rosła (niewykorzystany czas limitu będzie się zmniejszał, a wykorzystany czas zwiększał).Cost— całkowita wartość usługi obejmuje kwoty zgromadzone we wszystkich okresach oraz wartość niewykorzystanego czasu.ResultSum— całkowita wartość usługi, włączając rabaty, dopłaty i VAT.
Okres Usługi
IOrderServiceItemPeriod — okres, w którym usługa działa według określonej stawki, obejmujący wszystkie przedziały czasowe pod tą stawką.
Kluczowe właściwości okresu usługi:
Service— produkt powiązany ze stawką okresu. Alternatywnie jest to produktProductType.Serviceokreślony w usłudze jako stawka domyślna lub produktProductType.Rateokreślony w skali stawek.Price— cena za jednostkę czasu.ElapsedTime— całkowity czas, przez jaki usługa była używana według danej stawki. Jeśli usługa była uruchamiana i zatrzymywana wielokrotnie lub stawki były przełączane na przemian, system połączy wszystkie przedziały czasowe związane z tą stawką w jeden. Będzie to dokładny, niezaokrąglony okres czasu. System rejestruje rzeczywisty czas, jednak gość zapłaci za czas zaokrąglony. Na przykład, jeśli usługa jest rozliczana godzinowo, a ElapsedTime wynosi tylko 10 minut, wartość okresu będzie odpowiadać jednej godzinie i nie zmieni się przez kolejne 50 minut pod tą stawką.Cost— ogólna wartość okresu. Jest już uwzględniona w wartości usługi (zarówno ogólnej, jak i całkowitej), dlatego nie ma potrzeby ich sumowania. Ta właściwość służy jedynie do rozbicia kosztu usługi na stawki.
Ustawienia stawek
RateSchedule — tryb naliczania: według czasu usługi lub według pory dnia.
TimingMode— tryb naliczania: według czasu usługi lub według pory dnia.Items— skala stawek, lista elementówRateScheduleItem, które definiują przedziały czasowe z innymi stawkami niż stawka bazowa. Przedział czasowy (RateScheduleInterval) jest określony przez dzień tygodnia oraz przesunięcie początku i końca przedziału względem początku skali stawek. W zależności od wybranego trybu naliczania (TimingMode), skala zaczyna się wraz z dniem (cała skala to [0;24) godzin) lub wraz z usługą (cała skala to [0;12] godzin). Takie przedziały czasowe na pewno się nie nakładają. Jeśli lista jest pusta, stawka bazowa jest aktywna przez cały czas.TimingStep— jednostka pomiaru. Rzeczywisty czas usługi jest zaokrąglany w górę do najbliższego kroku stawki.MinimumDuration— minimalny czas trwania usługi lub null, jeśli dolny limit nie jest ustawiony.
Zarządzanie usługą
AddOrderServiceItem — dodawanie usługi do zamówienia.
StartService — rozpoczęcie usługi.
StopService — zatrzymanie usługi. Jeśli zostanie wydrukowany rachunek gościa lub zamówienie zostanie opłacone, usługa zatrzyma się automatycznie.
Przykłady
SamplePlugin dołączony do SDK pokazuje przykłady dodawania, rozpoczynania i zatrzymywania usługi — metody [StartService] i [StopService] w klasie EditorTester:
private static void StartService()
{
var order = PluginContext.Operations.GetOrders().Last(x => x.Status == OrderStatus.New);
var serviceProduct = PluginContext.Operations.GetActiveProducts().Last(x => x.Type == ProductType.Service && x.RateSchedule != null);
var credentials = PluginContext.Operations.GetCredentials();
var service = PluginContext.Operations.AddOrderServiceItem(serviceProduct, order, order.Guests.Last(), credentials, TimeSpan.FromHours(2));
PluginContext.Operations.StartService(credentials, order, service);
}
private static void StopService()
{
var order = PluginContext.Operations.GetOrders().Last(x => x.Status == OrderStatus.New);
var service = order.Items.OfType<IOrderServiceItem>().Last(x => x.IsStarted);
PluginContext.Operations.StopService(PluginContext.Operations.GetCredentials(), order, service);
}