Skip to main content
Technical ManualLooking for step-by-step instructions? In the User Manual: Trip Log

Mileage

The Mileage module keeps the trip log of the business vehicles and works out the standard mileage deduction. It replaces the legacy trip log (BOOK-37), which had no rate, deduction or report.

ProjectsCrestApps.Almohaseb.Mileage (module), CrestApps.Almohaseb.Mileage.Core (parts, indexes, rules, report, service)
FeatureCrestApps.Almohaseb.Mileage (Trip log), enabled by both business recipes; depends on the foundation, OrchardCore.Contents and CrestApps.OrchardCore.ContentFields.Address

Content types​

MileageMigrations.CreateAsync (version 1) defines three creatable, listable, securable types, so a business can add its own fields:

TypePartHolds
AlmohasebTripAlmohasebTripPart, plus the type's own part with the From and To CrestApps AddressFieldsDate, VehicleId, StartOdometer, EndOdometer, Miles, IsBusiness (default true), Purpose
AlmohasebVehicleAlmohasebVehiclePartName, Plate (upper-cased), IsActive
AlmohasebMileageRateAlmohasebMileageRatePartEffectiveFrom, RatePerMile (dollars, up to four decimals), Source (the publication)

The trip editor is four cards: Trip (date, vehicle, business trip, purpose), From, To and Miles (odometer readings and miles). TripPartDisplayDriver.Edit returns AlmohasebTripPart_Edit (Parts:0%Trip;0) and AlmohasebTripPart_Miles_Edit (Parts:3%Miles;3) from one model, and the module's placement.json places the From and To address fields (AddressField_Edit, differentiators AlmohasebTrip-From and AlmohasebTrip-To) in their cards and the type's part wrappers in the Trip card.

MileageIndexProvider maps the published versions to TripPartIndex (ContentItemId, Date, VehicleId, Miles, IsBusiness; indexed on Date, VehicleId), VehiclePartIndex (ContentItemId, Name, IsActive) and MileageRatePartIndex (ContentItemId, EffectiveFrom).

The legacy trip copied the business name, address, EIN and TR number into every trip ("Default Start Address"); trips no longer hold business identity data.

Rules​

TripRules.Normalize trims the purpose and, when both readings are noted and the end is not below the start, sets Miles to their difference. TripRules.Validate(TripPart) returns MileageValidationCodes: DateRequired, OdometerNegative, OdometerOrder, MilesRequired (zero or negative), MilesPrecision (more than two decimals), PurposeRequired (a business trip). A start reading of 0 is valid (the legacy validator rejected it). TripRules.Validate(MileageRatePart) requires an effective date and a rate above 0, at most 10 and with at most four decimals. The drivers (TripPartDisplayDriver, VehiclePartDisplayDriver, MileageRatePartDisplayDriver) turn the codes into model errors and set the display text.

Rates are data​

The rates are content items, not constants: the IRS sets them yearly and changed the 2026 rate on July 1 (Announcement 2026-11). The business recipes seed 2024 to 2026 (mlr-2024, mlr-2025, mlr-2026, mlr-2026h2) with their sources. When tax content is published by the platform (CrestApps.Almohaseb.TaxContent), it will supply these rates; until then a business adds new ones itself.

Report​

MileageReport is pure: FindRate(rates, date) is the rate with the latest EffectiveFrom on or before the date; Build(trips, rates) orders the trips by date, gives each business trip round2(miles × rate) (MidpointRounding.AwayFromZero), counts business trips with no rate (TripsWithoutRate), and totals by vehicle and overall (MileageVehicleTotal: total and business miles, deduction, BusinessPercent). IMileageService (MileageService) reads the published trips of a range, optionally of one vehicle, and every rate, and builds the report; it also lists vehicles.

MileageDeductionReport (almohaseb-mileage, category Taxes, ViewAlmohasebMileageReport) is a CrestApps report, registered by MileageReportsStartup with [RequireFeatures("CrestApps.OrchardCore.Reports")]: the summary (total and business miles, business use, deduction, business trips without a rate), By vehicle with more than one vehicle, and Trips. The range defaults to the current year in the business time zone; MileageReportFilterDisplayDriver adds the vehicle (filter key AlmohasebMileageVehicle). Export comes from CrestApps Reports. Admin/Almohaseb/Mileage/Report redirects to the report.

The deduction is not posted: it is a tax-return figure, and the standard mileage method does not record an expense in the books.

Admin​

The Mileage menu (id almohasebMileage, icon fa-car) has Trips, Vehicles and Mileage rates (the content lists of the types, shown with ListContent_{type}); the mileage report is under Reports.

Permissions​

PermissionAllows
ViewAlmohasebMileageReportThe mileage report and its CSV

Trips, vehicles and rates use the Orchard Core content permissions of their types.

See also​

  • Assets, for the vehicle as a fixed asset