add fuel subtype to fillup
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
</a> -->
|
||||
|
||||
<h1 align="center" style="margin-bottom:0">Hammond</h1>
|
||||
<p align="center">Current Version - 2021.07.14</p>
|
||||
<p align="center">Current Version - 2021.07.23</p>
|
||||
|
||||
<p align="center">
|
||||
A self-hosted vehicle expense tracking system with support for multiple users.
|
||||
|
||||
@@ -26,6 +26,7 @@ func RegisterVehicleController(router *gin.RouterGroup) {
|
||||
router.GET("/me/stats", getMystats)
|
||||
|
||||
router.GET("/vehicles/:id/fillups", getFillupsByVehicleId)
|
||||
router.GET("/vehicles/:id/fuelSubTypes", getFuelSubTypesByVehicleId)
|
||||
router.POST("/vehicles/:id/fillups", createFillup)
|
||||
router.GET("/vehicles/:id/fillups/:subId", getFillupById)
|
||||
router.PUT("/vehicles/:id/fillups/:subId", updateFillup)
|
||||
@@ -121,6 +122,22 @@ func getFillupsByVehicleId(c *gin.Context) {
|
||||
c.JSON(http.StatusUnprocessableEntity, common.NewValidatorError(err))
|
||||
}
|
||||
}
|
||||
func getFuelSubTypesByVehicleId(c *gin.Context) {
|
||||
|
||||
var searchByIdQuery models.SearchByIdQuery
|
||||
|
||||
if err := c.ShouldBindUri(&searchByIdQuery); err == nil {
|
||||
|
||||
fuelSubtypes, err := service.GetDistinctFuelSubtypesForVehicle(searchByIdQuery.Id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnprocessableEntity, common.NewError("getFuelSubTypesByVehicleId", err))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, fuelSubtypes)
|
||||
} else {
|
||||
c.JSON(http.StatusUnprocessableEntity, common.NewValidatorError(err))
|
||||
}
|
||||
}
|
||||
|
||||
func getExpensesByVehicleId(c *gin.Context) {
|
||||
|
||||
|
||||
@@ -119,6 +119,7 @@ type Fillup struct {
|
||||
Currency string `json:"currency"`
|
||||
DistanceUnit DistanceUnit `json:"distanceUnit"`
|
||||
Source string `json:"source"`
|
||||
FuelSubType string `json:"fuelSubType"`
|
||||
}
|
||||
|
||||
func (v *Fillup) FuelUnitDetail() EnumDetail {
|
||||
|
||||
@@ -50,6 +50,7 @@ type CreateFillupRequest struct {
|
||||
FillingStation string `form:"fillingStation" json:"fillingStation"`
|
||||
UserID string `form:"userId" json:"userId" binding:"required"`
|
||||
Date time.Time `form:"date" json:"date" binding:"required" time_format:"2006-01-02"`
|
||||
FuelSubType string `form:"fuelSubType" json:"fuelSubType"`
|
||||
}
|
||||
|
||||
type UpdateFillupRequest struct {
|
||||
|
||||
@@ -139,6 +139,7 @@ func CreateFillup(model models.CreateFillupRequest) (*db.Fillup, error) {
|
||||
Date: model.Date,
|
||||
Currency: user.Currency,
|
||||
DistanceUnit: user.DistanceUnit,
|
||||
FuelSubType: model.FuelSubType,
|
||||
Source: "API",
|
||||
}
|
||||
|
||||
@@ -196,6 +197,7 @@ func UpdateFillup(fillupId string, model models.UpdateFillupRequest) error {
|
||||
Comments: model.Comments,
|
||||
FillingStation: model.FillingStation,
|
||||
UserID: model.UserID,
|
||||
FuelSubType: model.FuelSubType,
|
||||
Date: model.Date,
|
||||
}).Error
|
||||
}
|
||||
@@ -235,6 +237,11 @@ func GetVehicleAttachments(vehicleId string) (*[]db.Attachment, error) {
|
||||
|
||||
return db.GetVehicleAttachments(vehicleId)
|
||||
}
|
||||
func GetDistinctFuelSubtypesForVehicle(vehicleId string) ([]string, error) {
|
||||
var names []string
|
||||
tx := db.DB.Model(&db.Fillup{}).Where("vehicle_id=? and fuel_sub_type is not null", vehicleId).Distinct().Pluck("fuel_sub_type", &names)
|
||||
return names, tx.Error
|
||||
}
|
||||
|
||||
func GetUserStats(userId string, model models.UserStatsQueryModel) ([]models.VehicleStatsModel, error) {
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
faTrash,
|
||||
faShare,
|
||||
faUserFriends,
|
||||
faTimesCircle,
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
||||
|
||||
@@ -51,6 +52,7 @@ library.add(
|
||||
faTrash,
|
||||
faShare,
|
||||
faUserFriends,
|
||||
faTimesCircle
|
||||
)
|
||||
Vue.use(Buefy, {
|
||||
defaultIconComponent: 'vue-fontawesome',
|
||||
|
||||
@@ -34,6 +34,7 @@ export default {
|
||||
quickEntry: null,
|
||||
myVehicles: [],
|
||||
users: [],
|
||||
fuelSubTypes: [],
|
||||
selectedVehicle: this.vehicle,
|
||||
fillupModel: this.fillup,
|
||||
processQuickEntry: false,
|
||||
@@ -46,6 +47,14 @@ export default {
|
||||
},
|
||||
...mapState('users', ['me']),
|
||||
...mapState('vehicles', ['fuelUnitMasters', 'fuelTypeMasters', 'vehicles']),
|
||||
filteredFuelSubtypes() {
|
||||
if (!this.fillupModel.fuelSubType) {
|
||||
return this.fuelSubTypes
|
||||
}
|
||||
return this.fuelSubTypes.filter((option) => {
|
||||
return option.toLowerCase().indexOf(this.fillupModel.fuelSubType.toLowerCase()) >= 0
|
||||
})
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
'fillupModel.fuelQuantity': function(old, newOne) {
|
||||
@@ -64,6 +73,7 @@ export default {
|
||||
this.myVehicles = this.vehicles
|
||||
this.selectedVehicle = this.vehicle
|
||||
this.fetchVehicleUsers()
|
||||
this.fetchVehicleFuelSubTypes()
|
||||
if (!this.fillup.id) {
|
||||
this.fillupModel = this.getEmptyFillup()
|
||||
this.fillupModel.userId = this.me.id
|
||||
@@ -82,6 +92,14 @@ export default {
|
||||
})
|
||||
.catch((err) => console.log(err))
|
||||
},
|
||||
fetchVehicleFuelSubTypes() {
|
||||
store
|
||||
.dispatch('vehicles/fetchFuelSubtypesByVehicleId', { vehicleId: this.selectedVehicle.id })
|
||||
.then((data) => {
|
||||
this.fuelSubTypes = data
|
||||
})
|
||||
.catch((err) => console.log(err))
|
||||
},
|
||||
getEmptyFillup() {
|
||||
return {
|
||||
vehicleId: this.selectedVehicle.id,
|
||||
@@ -96,6 +114,7 @@ export default {
|
||||
fillingStation: '',
|
||||
comments: '',
|
||||
userId: '',
|
||||
fuelSubType: '',
|
||||
}
|
||||
},
|
||||
async createFillup() {
|
||||
@@ -201,6 +220,17 @@ export default {
|
||||
>
|
||||
</b-datepicker>
|
||||
</b-field>
|
||||
<b-field label="Fuel Subtype">
|
||||
<b-autocomplete
|
||||
v-model="fillupModel.fuelSubType"
|
||||
:data="filteredFuelSubtypes"
|
||||
placeholder="Octane etc."
|
||||
clearable
|
||||
autofocus
|
||||
@select="(option) => (fillupModel.fuelSubType = option)"
|
||||
>
|
||||
</b-autocomplete>
|
||||
</b-field>
|
||||
<b-field label="Quantity*" addons>
|
||||
<b-input v-model.number="fillupModel.fuelQuantity" type="number" step=".001" min="0" expanded required></b-input>
|
||||
<b-select v-model="fillupModel.fuelUnit" placeholder="Fuel Unit" required>
|
||||
|
||||
@@ -181,7 +181,7 @@ export default {
|
||||
<table class="table is-hoverable">
|
||||
<tr>
|
||||
<td>Current Version</td>
|
||||
<td>2021.07.14</td>
|
||||
<td>2021.07.23</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Website</td>
|
||||
|
||||
@@ -311,6 +311,9 @@ export default {
|
||||
<b-table-column v-slot="props" field="date" label="Date" :td-attrs="columnTdAttrs" sortable date>
|
||||
{{ formatDate(props.row.date) }}
|
||||
</b-table-column>
|
||||
<b-table-column v-slot="props" field="fuelSubType" label="Fuel Sub Type" :td-attrs="columnTdAttrs">
|
||||
{{ props.row.fuelSubType }}
|
||||
</b-table-column>
|
||||
<b-table-column v-slot="props" field="fuelQuantity" label="Qty." :td-attrs="hiddenMobile" numeric>
|
||||
{{ `${props.row.fuelQuantity} ${props.row.fuelUnitDetail.short}` }}
|
||||
</b-table-column>
|
||||
|
||||
@@ -140,6 +140,12 @@ export const actions = {
|
||||
return data
|
||||
})
|
||||
},
|
||||
fetchFuelSubtypesByVehicleId({ commit, state, rootState }, { vehicleId, force }) {
|
||||
return axios.get(`/api/vehicles/${vehicleId}/fuelSubTypes`).then((response) => {
|
||||
const data = response.data
|
||||
return data
|
||||
})
|
||||
},
|
||||
fetchStatsByVehicleId({ commit, state, rootState }, { vehicleId, force }) {
|
||||
if (state.vehicleStats.has(vehicleId) && !force) {
|
||||
return Promise.resolve(state.vehicleStats.get(vehicleId))
|
||||
|
||||
Reference in New Issue
Block a user