mirror of
https://github.com/rjNemo/rentease.git
synced 2026-06-11 13:16:50 +00:00
Some checks failed
CI / checks (push) Has been cancelled
Enhance the booking sync logic to trim and match item names more robustly, falling back to creating a generic item when no host item is found. Add unit tests for item creation and fallback behavior in booking sync.
259 lines
6.4 KiB
Go
259 lines
6.4 KiB
Go
package booking
|
|
|
|
import (
|
|
"errors"
|
|
"log/slog"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/rjNemo/rentease/internal/config"
|
|
)
|
|
|
|
func TestParseFromAPI_CreatesItemsForBookingSync(t *testing.T) {
|
|
store := newStubStore()
|
|
parser := stubParser{
|
|
booking: Booking{
|
|
From: time.Date(2025, time.January, 1, 0, 0, 0, 0, time.UTC),
|
|
To: time.Date(2025, time.January, 4, 0, 0, 0, 0, time.UTC),
|
|
Name: "Jane Doe",
|
|
PhoneNumber: "123456",
|
|
Email: "jane@example.com",
|
|
Platform: config.Platform("Booking"),
|
|
CustomerNumber: 2,
|
|
PlatformFees: 15.0,
|
|
Items: []Item{{
|
|
Item: " T3 ",
|
|
Quantity: 3,
|
|
Price: 80.0,
|
|
PaymentMethod: "Card",
|
|
}},
|
|
},
|
|
}
|
|
|
|
svc, err := NewService(slog.Default(), store, parser, noopPDF{})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error creating service: %v", err)
|
|
}
|
|
|
|
booking, err := svc.ParseFromAPI("raw booking content")
|
|
if err != nil {
|
|
t.Fatalf("unexpected error parsing booking: %v", err)
|
|
}
|
|
|
|
if len(store.items) != 2 {
|
|
t.Fatalf("expected 2 items to be created (booking item + taxes), got %d", len(store.items))
|
|
}
|
|
|
|
if store.items[0].Item != "T3" {
|
|
t.Fatalf("expected base item to be trimmed to host item name, got %q", store.items[0].Item)
|
|
}
|
|
|
|
if store.items[1].Item != "Taxes" {
|
|
t.Fatalf("expected taxes item to be created, got %q", store.items[1].Item)
|
|
}
|
|
|
|
if len(booking.Items) != 2 {
|
|
t.Fatalf("expected booking to include created items, got %d", len(booking.Items))
|
|
}
|
|
}
|
|
|
|
func TestParseFromAPI_DoesNotCreateTaxesForNonBookingPlatform(t *testing.T) {
|
|
store := newStubStore()
|
|
parser := stubParser{
|
|
booking: Booking{
|
|
From: time.Date(2025, time.March, 1, 0, 0, 0, 0, time.UTC),
|
|
To: time.Date(2025, time.March, 3, 0, 0, 0, 0, time.UTC),
|
|
Name: "Alex Smith",
|
|
PhoneNumber: "987654",
|
|
Email: "alex@example.com",
|
|
Platform: config.Platform("AirBnb"),
|
|
CustomerNumber: 2,
|
|
Items: []Item{{
|
|
Item: "t2",
|
|
Quantity: 2,
|
|
Price: 59.0,
|
|
PaymentMethod: "Card",
|
|
}},
|
|
},
|
|
}
|
|
|
|
svc, err := NewService(slog.Default(), store, parser, noopPDF{})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error creating service: %v", err)
|
|
}
|
|
|
|
if _, err := svc.ParseFromAPI("raw booking content"); err != nil {
|
|
t.Fatalf("unexpected error parsing booking: %v", err)
|
|
}
|
|
|
|
if len(store.items) != 1 {
|
|
t.Fatalf("expected only base item without taxes for non-Booking platform, got %d items", len(store.items))
|
|
}
|
|
if store.items[0].Item != "T2" {
|
|
t.Fatalf("expected base item to match host item name, got %q", store.items[0].Item)
|
|
}
|
|
}
|
|
|
|
func TestParseFromAPI_CreatesFallbackItemWhenUnknown(t *testing.T) {
|
|
store := newStubStore()
|
|
parser := stubParser{
|
|
booking: Booking{
|
|
From: time.Date(2025, time.February, 1, 0, 0, 0, 0, time.UTC),
|
|
To: time.Date(2025, time.February, 2, 0, 0, 0, 0, time.UTC),
|
|
Name: "Jane Doe",
|
|
PhoneNumber: "123456",
|
|
Email: "jane@example.com",
|
|
Platform: config.Platform("Booking"),
|
|
CustomerNumber: 1,
|
|
Items: []Item{{
|
|
Item: "New Suite",
|
|
Quantity: 1,
|
|
Price: 120.0,
|
|
PaymentMethod: "Card",
|
|
}},
|
|
},
|
|
}
|
|
|
|
svc, err := NewService(slog.Default(), store, parser, noopPDF{})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error creating service: %v", err)
|
|
}
|
|
|
|
if _, err := svc.ParseFromAPI("raw booking content"); err != nil {
|
|
t.Fatalf("unexpected error parsing booking: %v", err)
|
|
}
|
|
|
|
if len(store.items) != 1 {
|
|
t.Fatalf("expected fallback item to be created, got %d items", len(store.items))
|
|
}
|
|
|
|
if store.items[0].Item != "New Suite" {
|
|
t.Fatalf("expected fallback item name to match parsed value, got %q", store.items[0].Item)
|
|
}
|
|
}
|
|
|
|
func TestParseFromAPI_NormalizesVerboseItemNameToHostItem(t *testing.T) {
|
|
store := newStubStore()
|
|
parser := stubParser{
|
|
booking: Booking{
|
|
From: time.Date(2025, time.April, 1, 0, 0, 0, 0, time.UTC),
|
|
To: time.Date(2025, time.April, 3, 0, 0, 0, 0, time.UTC),
|
|
Name: "Chris P Bacon",
|
|
PhoneNumber: "999999",
|
|
Email: "chris@example.com",
|
|
Platform: config.Platform("Booking"),
|
|
CustomerNumber: 2,
|
|
Items: []Item{{
|
|
Item: "One-Bedroom House (T2 - VillaFleurie au bourg du Gosier)",
|
|
Quantity: 2,
|
|
Price: 59.0,
|
|
PaymentMethod: "Card",
|
|
}},
|
|
},
|
|
}
|
|
|
|
svc, err := NewService(slog.Default(), store, parser, noopPDF{})
|
|
if err != nil {
|
|
t.Fatalf("unexpected error creating service: %v", err)
|
|
}
|
|
|
|
if _, err := svc.ParseFromAPI("raw booking content"); err != nil {
|
|
t.Fatalf("unexpected error parsing booking: %v", err)
|
|
}
|
|
|
|
if len(store.items) != 2 {
|
|
t.Fatalf("expected base item plus taxes, got %d items", len(store.items))
|
|
}
|
|
|
|
if store.items[0].Item != "T2" {
|
|
t.Fatalf("expected verbose item name to normalize to host item 'T2', got %q", store.items[0].Item)
|
|
}
|
|
}
|
|
|
|
type stubParser struct {
|
|
booking Booking
|
|
err error
|
|
}
|
|
|
|
func (p stubParser) Parse(rawContent string) (*Booking, error) {
|
|
if p.err != nil {
|
|
return nil, p.err
|
|
}
|
|
|
|
cp := p.booking
|
|
return &cp, nil
|
|
}
|
|
|
|
type stubStore struct {
|
|
bookings []*Booking
|
|
items []*Item
|
|
}
|
|
|
|
func newStubStore() *stubStore {
|
|
return &stubStore{
|
|
bookings: make([]*Booking, 0),
|
|
items: make([]*Item, 0),
|
|
}
|
|
}
|
|
|
|
func (s *stubStore) All() []*Line {
|
|
return nil
|
|
}
|
|
|
|
func (s *stubStore) Search(value string) []*Line {
|
|
return nil
|
|
}
|
|
|
|
func (s *stubStore) List(from, to time.Time) ([]*Line, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (s *stubStore) CardTotal(from, to time.Time) (float64, error) {
|
|
return 0, nil
|
|
}
|
|
|
|
func (s *stubStore) Get(id int) (*Booking, error) {
|
|
return nil, errors.New("not implemented")
|
|
}
|
|
|
|
func (s *stubStore) Create(b *Booking) error {
|
|
b.ID = len(s.bookings) + 1
|
|
s.bookings = append(s.bookings, b)
|
|
return nil
|
|
}
|
|
|
|
func (s *stubStore) Update(b *Booking) error {
|
|
return nil
|
|
}
|
|
|
|
func (s *stubStore) Cancel(id int) error {
|
|
return nil
|
|
}
|
|
|
|
func (s *stubStore) CreateItem(i *Item) error {
|
|
i.ID = len(s.items) + 1
|
|
s.items = append(s.items, i)
|
|
return nil
|
|
}
|
|
|
|
func (s *stubStore) PayItem(id int) (*Item, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (s *stubStore) GetItem(id int) (*Item, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (s *stubStore) UpdateItem(id int, item string, paymentMethod string, paymentStatus string, qty int, price float64) (*Item, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
type noopPDF struct{}
|
|
|
|
func (noopPDF) BuildInvoice(invoice Invoice) (string, error) {
|
|
return "", nil
|
|
}
|
|
|
|
func (noopPDF) BuildReport(report ReportData, period string, month, year int) (string, error) {
|
|
return "", nil
|
|
}
|