Assets and Fleet
The Assets module (CrestApps.OrchardCore.Assets, with Assets.Abstractions and Assets.Core) keeps the things a business services or uses: its own vehicles, equipment and tools, and the units installed at its customers. It references no vertical, so field service, CRM and others build on it.
The admin screens are described in the User Manual: Assets.
Features
| Feature | Id | Depends on |
|---|---|---|
| Assets | CrestApps.OrchardCore.Assets | — |
| Fleet | CrestApps.OrchardCore.Assets.Fleet | Assets, Calendars Resources |
Records
All live in the Assets YesSql collection.
AssetType:Name,Category(Equipment,Vehicle,Tool,CustomerUnit,Component,Facility),Description,Attributes(AssetAttributeDefinition:Name,KindText, Number, Date or YesNo) andMeters(MeterDefinition:Name,Unit,Cumulative, true by default). Two attributes or meters can't share a name.Asset:Number(the nextA-00042when left empty, unique),Name,AssetTypeId,ProductId,SerialNumber,Manufacturer,Model,OwnerKind(Internal,Customer,Account,Contact) andOwnerId(required unless internal),Location(anAddress, with coordinates once geocoded; a changed address loses its old ones),ParentAssetId(the hierarchy; an asset can't be inside itself, directly or further up),Status(Active,InService,OutOfService,Retired),InstallDate,Warranty(StartDate,EndDate,Provider,Terms;Covers(date)),Attributes(values of its type's attributes, by name),Documents(media paths) andFleet.AssetMeterReading(only ever added):AssetId,Meter,Value,Utc,Source(Manual,WorkOrder,Api),SourceId,RecordedBy.
AssetService.RecordReadingAsync refuses a meter the asset's type doesn't have, and a reading of a cumulative meter lower than the last one before it. ReadingsAsync, ChildrenAsync and AncestorsAsync read an asset's history and hierarchy.
Owners
An asset is owned by the business, or by a customer, an account (of the Accounts module) or a CRM contact, picked in the editor by name. Each kind of owner is read from the shared parties: an IPartySource (Kind, SearchAsync, GetNamesAsync) of the party kind the owner kind maps to (AssetOwners.ToPartyKind), and only the kinds with a source can be chosen. The stored OwnerKind and OwnerId are unchanged; asset.ToParty() reads them as a PartyRef:
| Owner kind | Party kind and source | Comes with |
|---|---|---|
| Customer | User (the owner id is a user id): UserPartySource, by user name or email | OrchardCore.Users (registered by Assets) or the CrestApps Users module |
| Account | Account: AccountPartySource, the account types of IAccountContentTypeProvider, by display text; the editor's picker uses the Accounts search | Accounts (CrestApps.OrchardCore.Accounts) |
| Contact | Contact: content items with the Omnichannel Contact part, by display text (registered by Assets) | Omnichannel Management |
AssetOwnerDirectory names owners for the list, the asset's page and the editor; an owner it can't find shows its id. The editor's pickers search Admin/api/crestapps/assets/owners/search?kind=&query= (View assets), which returns up to 50 { value, text } items. The asset list filters by owner with ownerKind and ownerId, and its Add asset keeps that owner.
With Omnichannel Management on, a CRM contact's page, and with Accounts on, an account's page, show an Assets card: the first ten assets it owns by name, All when there are more, and Add an asset for it.
Fleet
For a vehicle, equipment or tool the business owns, AssetFleet keeps Schedulable, CalendarId, Plate, Vin, Capacity, FuelType, HomeBase, DefaultDriverWorkerId, CarriesStock and StockLocationId.
- Booking. A schedulable asset gets its own calendar of the Calendars Equipment type, which allows one booking at a time, so the calendar refuses a visit that overlaps another.
FleetCalendarHandlercreates it when the asset is saved, finds it again by source (Asset, the asset's id) and keeps its name. - Van stock. With Inventory on, an asset that carries stock gets its own Inventory
StockLocation, owned by the asset (OwnerKindAsset). Parts used on a job come off it withIInventoryService.ConsumeAsync. A van's location never fulfills orders.
Inventory changes
- Stock locations moved from the Inventory settings to a
StockLocationstore (ItemIdis the location id,Name,Address,Position,OwnerKind,OwnerId). A migration step moves the locations kept in the settings into it once it has run, keeping their ids and their order, so stock levels and movements still point at them; until thenInventoryLocationServicealso reads the settings. The settings page edits the site's own locations in the store; locations owned by other records are managed with their owner. StockMovementgainsReferenceTypeandReferenceId(indexed) besideOrderId, and theConsumedkind.IInventoryService.ConsumeAsync(stockItemId, locationId, quantity, referenceType, referenceId, reason, actor)uses units up at a location, refusing more than it has available, and records what they were for.
Extending
DisplayDriver<Asset>: adds a section to the asset editor (assets/edit/{id?}), which is built withIDisplayManager<Asset>. The built-in fields are one driver,AssetFields_EditatContent:1. Register yours withservices.AddDisplayDriver<Asset, TDriver>(), bind your own view model with the driver'sPrefix, and report errors under it ($"{Prefix}.Field"). The asset's own rules (AssetManager.ValidateAsync) run after every section and are reported under theAssetprefix. When anything fails the asset isn't saved and the editor cancels the session, so records a section wrote are not kept either.
Recipes and deployment
The Assets recipe step creates or updates asset types (Types) and assets (Assets, parents first) by ItemId, with the editor's checks. The Asset types and assets deployment step exports the types, and the assets unless told not to. Meter readings stay where they were taken.
Permissions
| Permission | Allows |
|---|---|
ManageAssets (Manage assets) | Asset types, assets and meter readings. |
ViewAssets (View assets) | The asset list and pages. Implied by Manage assets. |