rentease/internal/booking/service.go

152 lines
3.7 KiB
Go

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,
}
}