package booking import ( "fmt" "strconv" "time" u "github.com/rjNemo/underscore" "gorm.io/gorm" "github.com/rjNemo/rentease/internal/config" ) type Booking struct { From time.Time To time.Time gorm.Model Name string `gorm:"column:customer_name"` PhoneNumber string Email string Platform config.Platform ExternalID *string `gorm:"uniqueIndex:booking_external_id"` Items []Item Payments []Payment `gorm:"foreignKey:BookingID"` ID int CustomerNumber int `gorm:"column:customers"` PlatformFees float64 `gorm:"type:decimal(10,2)"` Canceled bool `gorm:"default:false"` } // NewBooking creates a new booking with the given parameters func NewBooking(from, to time.Time, name, phoneNumber, email, platform string, customerNumber int, platformFees float64, externalID *string, ) *Booking { return &Booking{ From: from, To: to, Name: name, PhoneNumber: phoneNumber, CustomerNumber: customerNumber, Email: email, Platform: config.Platform(platform), PlatformFees: platformFees, ExternalID: externalID, } } func (b Booking) InvoiceNumber(hc *config.Host) string { return fmt.Sprintf("%s%04s", hc.InvoicePrefix, strconv.Itoa(b.ID+hc.CustomerSeed)) } func (b Booking) ToInvoice(hc *config.Host) Invoice { total := u.Reduce(b.Items, func(i Item, sum float64) float64 { return sum + i.Price*float64(i.Quantity) }, 0.0) amountPaid := u.Reduce(b.Payments, func(i Payment, sum float64) float64 { return sum + i.Amount }, 0.0) return Invoice{ Host: *hc, Name: b.Name, PhoneNumber: b.PhoneNumber, CustomersNumber: b.CustomerNumber, Platform: b.Platform.ToFrench(), ID: b.InvoiceNumber(hc), From: b.From.Format("02/01/2006"), To: b.To.Format("02/01/2006"), Total: strconv.FormatFloat(total, 'f', 2, 64), AmountPaid: strconv.FormatFloat(amountPaid, 'f', 2, 64), BalanceDue: strconv.FormatFloat(total-amountPaid, 'f', 2, 64), Lines: u.Map(b.Items, func(i Item) InvoiceLine { return InvoiceLine{ Name: i.ToFrench(), Quantity: i.Quantity, Price: strconv.FormatFloat(i.Price, 'f', 2, 64), Total: strconv.FormatFloat(i.Price*float64(i.Quantity), 'f', 2, 64), } }), Payments: u.Map(b.Payments, func(p Payment) PaymentLine { return PaymentLine{ Date: p.CreatedAt.Format("02/01/2006"), Method: p.PaymentMethod.ToFrench(), Amount: strconv.FormatFloat(p.Amount, 'f', 2, 64), } }), } } // WithID returns a copy of the booking with the given ID func (b *Booking) WithID(id int) *Booking { b.ID = id return b } type Item struct { gorm.Model Item string PaymentMethod string PaymentStatus string `gorm:"default:Pending"` ID int BookingID int Quantity int Price float64 `gorm:"type:decimal(10,2)"` } // ToFrench translates the item name to french func (i Item) ToFrench() string { switch i.Item { case "T2": return "T2" case "T3": return "T3" case "Airport": return "Transport AƩroport" case "Port": return "Transport Gare Maritime" case "Transport": return "Transport" case "Taxes": return "Taxes de sejour" default: return i.Item } } type Payment struct { gorm.Model BookingID uint `gorm:"not null;index"` Booking Booking `gorm:"foreignKey:BookingID;constraint:OnDelete:CASCADE"` Amount float64 PaymentMethod config.PaymentMethod StripePaymentID *string `gorm:"size:255;uniqueIndex"` StripeStatus *string `gorm:"size:32"` }