diff --git a/server/models/report.go b/server/models/report.go
index ffe44c2..bf0eedb 100644
--- a/server/models/report.go
+++ b/server/models/report.go
@@ -8,16 +8,19 @@ import (
)
type MileageModel struct {
- Date time.Time `form:"date" json:"date" binding:"required" time_format:"2006-01-02"`
- VehicleID string `form:"vehicleId" json:"vehicleId" binding:"required"`
- FuelUnit db.FuelUnit `form:"fuelUnit" json:"fuelUnit" binding:"required"`
- FuelQuantity float32 `form:"fuelQuantity" json:"fuelQuantity" binding:"required"`
- PerUnitPrice float32 `form:"perUnitPrice" json:"perUnitPrice" binding:"required"`
- Currency string `json:"currency"`
- DistanceUnit db.DistanceUnit `form:"distanceUnit" json:"distanceUnit"`
- Mileage float32 `form:"mileage" json:"mileage" binding:"mileage"`
- CostPerMile float32 `form:"costPerMile" json:"costPerMile" binding:"costPerMile"`
- OdoReading int `form:"odoReading" json:"odoReading" binding:"odoReading"`
+ Date time.Time `form:"date" json:"date" binding:"required" time_format:"2006-01-02"`
+ StartDate time.Time `form:"startDate" json:"startDate" binding:"required" time_format:"2006-01-02"`
+ EndDate time.Time `form:"endDate" json:"endDate" binding:"required" time_format:"2006-01-02"`
+ VehicleID string `form:"vehicleId" json:"vehicleId" binding:"required"`
+ FuelUnit db.FuelUnit `form:"fuelUnit" json:"fuelUnit" binding:"required"`
+ FuelQuantity float32 `form:"fuelQuantity" json:"fuelQuantity" binding:"required"`
+ PerUnitPrice float32 `form:"perUnitPrice" json:"perUnitPrice" binding:"required"`
+ Currency string `json:"currency"`
+ DistanceUnit db.DistanceUnit `form:"distanceUnit" json:"distanceUnit"`
+ Mileage float32 `form:"mileage" json:"mileage" binding:"mileage"`
+ CostPerMile float32 `form:"costPerMile" json:"costPerMile" binding:"costPerMile"`
+ OdoReading int `form:"odoReading" json:"odoReading" binding:"odoReading"`
+ DistanceTravel float32 `form:"distanceTravel" json:"distanceTravel" binding:"distanceTravel"`
}
func (v *MileageModel) FuelUnitDetail() db.EnumDetail {
diff --git a/server/service/reportService.go b/server/service/reportService.go
index 079adbf..bbaa7e3 100644
--- a/server/service/reportService.go
+++ b/server/service/reportService.go
@@ -9,6 +9,116 @@ import (
"hammond/models"
)
+type Range struct {
+ Start int
+ End int
+}
+
+func ComputeMileage_litre_100km(fillups []db.Fillup, mileages *[]models.MileageModel) {
+ var ranges []Range
+
+ // fillups ordered by odo descending
+ // travel from lower odo to higher
+ for i := len(fillups) - 1; i >= 0; i-- {
+ currentFillup := fillups[i]
+ currTankFull := currentFillup.IsTankFull != nil && *currentFillup.IsTankFull
+ if !currTankFull {
+ continue
+ }
+
+ for j := i-1; j >= 0; j-- {
+ lastFillup := fillups[j]
+ lastHasMissed := lastFillup.HasMissedFillup != nil && *lastFillup.HasMissedFillup
+ if lastHasMissed {
+ i = j + 1 // so that i loop lands on j in the next iter
+ break
+ }
+
+ lastTankFull := lastFillup.IsTankFull != nil && *lastFillup.IsTankFull
+ if lastTankFull {
+ ranges = append(ranges, Range{Start: i, End: j})
+ i = j + 1
+ break
+ }
+ }
+ }
+
+ for _, r := range ranges {
+ startFillup := fillups[r.Start]
+ endFillup := fillups[r.End]
+
+ mileage := models.MileageModel{
+ Date: startFillup.Date,
+ StartDate: startFillup.Date,
+ EndDate: endFillup.Date,
+ VehicleID: startFillup.VehicleID,
+ FuelUnit: db.LITRE,
+ FuelQuantity: 0,
+ PerUnitPrice: startFillup.PerUnitPrice,
+ OdoReading: 0,
+ DistanceTravel: 0,
+ Currency: startFillup.Currency,
+ DistanceUnit: db.KILOMETERS,
+ Mileage: 0,
+ CostPerMile: 0,
+ }
+
+ // This computes the distance traveled
+ startOdo := float32(startFillup.OdoReading)
+ endOdo := float32(endFillup.OdoReading)
+
+ // Convert into km if needed
+ if startFillup.DistanceUnit != mileage.DistanceUnit {
+ startOdo = common.MilesToKm(startOdo)
+ }
+ if endFillup.DistanceUnit != mileage.DistanceUnit {
+ endOdo = common.MilesToKm(endOdo)
+ }
+ mileage.DistanceTravel = endOdo - startOdo
+
+ // This computes the spent fuel
+ // first we convert into Litre
+ // reverse order...
+ // also should skip start fillup
+ for idx := r.Start-1; idx >= r.End; idx-- {
+ f := fillups[idx]
+ if (f.FuelUnit != mileage.FuelUnit) {
+ f.FuelUnit = mileage.FuelUnit
+ f.FuelQuantity = common.GallonToLitre(f.FuelQuantity)
+ }
+ // second sum them all
+ mileage.FuelQuantity += f.FuelQuantity
+ }
+ // third divide
+ mileage.Mileage = mileage.FuelQuantity / mileage.DistanceTravel
+ mileage.Mileage *= 100
+ // forth append
+ // append blank
+ // if last date != this date
+ // meaning has missing fillups
+ mileagesSize := len(*mileages)
+ if mileagesSize > 0 && ((*mileages)[mileagesSize-1].EndDate != mileage.StartDate) {
+ blankMileage := models.MileageModel {
+ Date: (*mileages)[mileagesSize-1].EndDate,
+ StartDate: (*mileages)[mileagesSize-1].EndDate,
+ EndDate: mileage.StartDate,
+ VehicleID: startFillup.VehicleID,
+ FuelUnit: db.LITRE,
+ FuelQuantity: 0,
+ PerUnitPrice: startFillup.PerUnitPrice,
+ OdoReading: 0,
+ DistanceTravel: 0,
+ Currency: startFillup.Currency,
+ DistanceUnit: db.KILOMETERS,
+ Mileage: 0,
+ CostPerMile: 0,
+ }
+ *mileages = append(*mileages, blankMileage)
+ }
+ *mileages = append(*mileages, mileage)
+ }
+}
+
func GetMileageByVehicleId(vehicleId string, since time.Time, mileageOption string) (mileage []models.MileageModel, err error) {
data, err := db.GetFillupsByVehicleIdSince(vehicleId, since)
if err != nil {
@@ -23,67 +133,75 @@ func GetMileageByVehicleId(vehicleId string, since time.Time, mileageOption stri
var mileages []models.MileageModel
- for i := 0; i < len(fillups)-1; i++ {
- last := i + 1
+ if mileageOption == "litre_100km" {
+ ComputeMileage_litre_100km(fillups, &mileages)
+ } else {
+
+ for i := 0; i < len(fillups)-1; i++ {
+ last := i + 1
+
+ currentFillup := fillups[i]
+ lastFillup := fillups[last]
+
+ mileage := models.MileageModel{
+ StartDate: currentFillup.Date,
+ EndDate: currentFillup.Date,
+ Date: currentFillup.Date,
+ VehicleID: currentFillup.VehicleID,
+ FuelUnit: currentFillup.FuelUnit,
+ FuelQuantity: currentFillup.FuelQuantity,
+ PerUnitPrice: currentFillup.PerUnitPrice,
+ OdoReading: currentFillup.OdoReading,
+ Currency: currentFillup.Currency,
+ DistanceUnit: currentFillup.DistanceUnit,
+ Mileage: 0,
+ CostPerMile: 0,
+ }
+
+ if currentFillup.IsTankFull != nil && *currentFillup.IsTankFull && (currentFillup.HasMissedFillup == nil || !(*currentFillup.HasMissedFillup)) {
+ currentOdoReading := float32(currentFillup.OdoReading);
+ lastFillupOdoReading := float32(lastFillup.OdoReading);
+ currentFuelQuantity := float32(currentFillup.FuelQuantity);
+ // If miles per gallon option and distanceUnit is km, convert from km to miles
+ // then check if fuel unit is litres. If it is, convert to gallons
+ if (mileageOption == "mpg" && mileage.DistanceUnit == db.KILOMETERS) {
+ currentOdoReading = common.KmToMiles(currentOdoReading);
+ lastFillupOdoReading = common.KmToMiles(lastFillupOdoReading);
+ if (mileage.FuelUnit == db.LITRE) {
+ currentFuelQuantity = common.LitreToGallon(currentFuelQuantity);
+ }
+ }
+
+ // If km_litre option or litre per 100km and distanceUnit is miles, convert from miles to km
+ // then check if fuel unit is not litres. If it isn't, convert to litres
+
+ if ((mileageOption == "km_litre" || mileageOption == "litre_100km") && mileage.DistanceUnit == db.MILES) {
+ currentOdoReading = common.MilesToKm(currentOdoReading);
+ lastFillupOdoReading = common.MilesToKm(lastFillupOdoReading);
+
+ if (mileage.FuelUnit == db.US_GALLON) {
+ currentFuelQuantity = common.GallonToLitre(currentFuelQuantity);
+ }
+ }
+
+
+
+
+ distance := float32(currentOdoReading - lastFillupOdoReading);
+ if (mileageOption == "litre_100km") {
+ mileage.Mileage = currentFuelQuantity / distance * 100;
+ } else {
+ mileage.Mileage = distance / currentFuelQuantity;
+ }
+
+ mileage.CostPerMile = distance / currentFillup.TotalAmount;
+
+ }
+
+ mileages = append(mileages, mileage)
+ }
+ }
- currentFillup := fillups[i]
- lastFillup := fillups[last]
-
- mileage := models.MileageModel{
- Date: currentFillup.Date,
- VehicleID: currentFillup.VehicleID,
- FuelUnit: currentFillup.FuelUnit,
- FuelQuantity: currentFillup.FuelQuantity,
- PerUnitPrice: currentFillup.PerUnitPrice,
- OdoReading: currentFillup.OdoReading,
- Currency: currentFillup.Currency,
- DistanceUnit: currentFillup.DistanceUnit,
- Mileage: 0,
- CostPerMile: 0,
- }
-
- if currentFillup.IsTankFull != nil && *currentFillup.IsTankFull && (currentFillup.HasMissedFillup == nil || !(*currentFillup.HasMissedFillup)) {
- currentOdoReading := float32(currentFillup.OdoReading);
- lastFillupOdoReading := float32(lastFillup.OdoReading);
- currentFuelQuantity := float32(currentFillup.FuelQuantity);
- // If miles per gallon option and distanceUnit is km, convert from km to miles
- // then check if fuel unit is litres. If it is, convert to gallons
- if (mileageOption == "mpg" && mileage.DistanceUnit == db.KILOMETERS) {
- currentOdoReading = common.KmToMiles(currentOdoReading);
- lastFillupOdoReading = common.KmToMiles(lastFillupOdoReading);
- if (mileage.FuelUnit == db.LITRE) {
- currentFuelQuantity = common.LitreToGallon(currentFuelQuantity);
- }
- }
-
- // If km_litre option or litre per 100km and distanceUnit is miles, convert from miles to km
- // then check if fuel unit is not litres. If it isn't, convert to litres
-
- if ((mileageOption == "km_litre" || mileageOption == "litre_100km") && mileage.DistanceUnit == db.MILES) {
- currentOdoReading = common.MilesToKm(currentOdoReading);
- lastFillupOdoReading = common.MilesToKm(lastFillupOdoReading);
-
- if (mileage.FuelUnit == db.US_GALLON) {
- currentFuelQuantity = common.GallonToLitre(currentFuelQuantity);
- }
- }
-
-
-
-
- distance := float32(currentOdoReading - lastFillupOdoReading);
- if (mileageOption == "litre_100km") {
- mileage.Mileage = currentFuelQuantity / distance * 100;
- } else {
- mileage.Mileage = distance / currentFuelQuantity;
- }
-
- mileage.CostPerMile = distance / currentFillup.TotalAmount;
-
- }
-
- mileages = append(mileages, mileage)
- }
if mileages == nil {
mileages = make([]models.MileageModel, 0)
}
diff --git a/ui/src/components/mileageTable.vue b/ui/src/components/mileageTable.vue
new file mode 100644
index 0000000..542afca
--- /dev/null
+++ b/ui/src/components/mileageTable.vue
@@ -0,0 +1,87 @@
+
+
+
+ {{ formatDate(data.date) }} - {{ (data.mileage).toFixed(2) }}