Przejdź do głównej zawartości

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 (patrz RemainingLimitCost).
  • 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 produkt ProductType.Service określony w usłudze jako stawka domyślna lub produkt ProductType.Rate okreś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ów RateScheduleItem, 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);
}