package booking import ( "fmt" "strconv" "time" u "github.com/rjNemo/underscore" "gorm.io/gorm" "github.com/rjNemo/rentease/config" ) type Service struct { db *gorm.DB } func NewService(db *gorm.DB) *Service { return &Service{db: db} } func (bs Service) All() []*Line { bookings := make([]*Line, 0) bs.db.Raw(` select bookings.id, customer_name, "from", "to", platform, sum(price * quantity) as total from bookings join items on bookings.id = items.booking_id group by bookings.id order by id desc; `). Scan(&bookings) return bookings } func (bs Service) Create(From time.Time, To time.Time, Name string, PhoneNumber string, Email string, Platform string, CustomerNumber int, PlatformFees float64, ) *Booking { b := &Booking{ Name: Name, PhoneNumber: PhoneNumber, CustomerNumber: CustomerNumber, Email: Email, From: From, To: To, Platform: Platform, PlatformFees: PlatformFees, } _ = bs.db.Create(b) return b } func (bs Service) One(id int) *Booking { b := &Booking{Id: id} bs.db.Preload("Items").First(b) return b } func (bs Service) CreateItem(bid int, item string, qty int, price float64, method string) *Item { i := &Item{ BookingId: bid, Item: item, Quantity: qty, Price: price, PaymentMethod: method, } _ = bs.db.Create(i) return i } type Report struct { Lines []*Line Total float64 PlatformFees float64 Fee float64 Profit float64 CardTotal float64 } type Line struct { From time.Time To time.Time CustomerName string Platform string Id int Total float64 PlatformFees float64 } func (l Line) InvoiceNumber(hc *config.Host) string { return fmt.Sprintf("%s%04s", hc.InvoicePrefix, strconv.Itoa(l.Id+hc.CustomerSeed)) } func (l Line) Fee() (f float64) { if l.Platform == "Other" { f = l.Total * 5 / 100 } else { f = l.Total * 10 / 100 } return f } func (l Line) Profit() float64 { return l.Total - l.PlatformFees - l.Fee() } func (bs Service) BuildReport(period string, month, year int) *Report { lines := make([]*Line, 0) var startDate time.Time var endDate time.Time if period == "month" { startDate = time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.UTC) endDate = time.Date(year, time.Month(month)+1, 1, 0, 0, 0, 0, time.UTC).Add(-24 * time.Hour) } else { startDate = time.Date(year, time.January, 1, 0, 0, 0, 0, time.UTC) endDate = time.Date(year, time.December, 31, 0, 0, 0, 0, time.UTC) } bs.db.Raw(` select bookings.id, customer_name, "from", "to", platform, sum(price * quantity) as total, platform_fees from bookings join items on bookings.id = items.booking_id where "to" between ? and ? group by bookings.id order by bookings.id; `, startDate.Format("2006-01-02"), endDate.Format("2006-01-02")). Scan(&lines) cardTotal := 0.0 bs.db.Raw(` select sum(total) from (select sum(price * quantity) as total from bookings join items on bookings.id = items.booking_id where "to" between ? and ? and payment_method = 'Card' group by booking_id) as t; `, startDate.Format("2006-01-02"), endDate.Format("2006-01-02")). Scan(&cardTotal) return &Report{ Total: u.Reduce(lines, func(l *Line, sum float64) float64 { return sum + l.Total }, 0.0), PlatformFees: u.Reduce(lines, func(l *Line, sum float64) float64 { return sum + l.PlatformFees }, 0.0), Fee: u.Reduce(lines, func(l *Line, sum float64) float64 { return sum + l.Fee() }, 0.0), Profit: u.Reduce(lines, func(l *Line, sum float64) float64 { return sum + l.Profit() }, 0.0), Lines: lines, CardTotal: cardTotal, } }