Skip to content

Book 5, Chapter 22 — Logistics & Inbound Deliveries

STATIC ANALYSIS ONLY. Every technical claim carries a file:line cite. §7 separates CODE-PROVEN from INFERENCE. No app/DB was booted.


1. Purpose (plain language)

This chapter covers the inbound / logistics operations layer — the part of the ERP that moves physical goods into the company's branches and keeps the vehicles that do it accountable. Where Book 2 Chapter 9 (GRN / Goods Received) deals with the paperwork of receiving stock into inventory, this chapter deals with everything that happens before that paperwork can be signed off: a driver being assigned a collection, physically driving to a supplier or sister-branch, loading, driving back, and offloading at a designated point on site.

Concretely, five operational sub-systems live under the Delivery & Logistics → Logistics nav group:

  1. Inbound Deliveries — the driver-facing trip state machine that tracks a vehicle from "scheduled" through pickup, loading, transit and offloading, with GPS checkpoints, dashboard-photo/mileage evidence, and SMS notifications at each hop. Two document types feed it: SUPPLIER_COLLECTION (own-collection LPOs) and INTER_BRANCH_TRANSFER. Includes Inbound Delivery Merging (combine several small trips onto one truck) and Offloading Statuses (a branch-side arrival/offloading log shared with supplier-portal LPO deliveries).
  2. Small Packs — the interbranch small-parcel dispatch workflow (loading sheets → dispatch → driver receipt).
  3. Vehicle Inspection Routines — recurring checklist-based inspections assigned to vehicles and roles (distinct from the maintenance/service world of Ch21).
  4. Device Management (Device Center) — the operational repair + SIM-card lifecycle for hardware devices (boundary with Ch18 tracking devices stated in §5).
  5. Reports & Config — Vehicle Profitability, Procurement Jobs, the logistics dashboard, idle-vehicle tracking, and logistics penalty settings.

The single most important structural fact: an inbound delivery is the physical-receipt precursor to a GRN. When the tenant flag ENFORCE_DELIVERY_OFFLOADING_FOR_INBOUND_DELIVERIES is on, an own-collection LPO cannot be received (no GRN) until its inbound delivery has an offloading_end_time (app/Http/Controllers/Admin/ReceivePurchasedOrderController.php:1554-1577). That is the seam this chapter documents.


2. Users & roles (permissions)

The whole nav group is gated by delivery_and_logistics___view or super-admin role_id == 1 (resources/views/admin/includes/sidebar_includes/logistics.blade.php:43). Within it, each sub-item uses the codebase's can($action, $model) helper or a $my_permissions['<model>___<action>'] isset-check. Permission strings observed:

Sub-system Permission model string Actions seen in code
Inbound deliveries inbound-deliveries view, end-delivery, schedule-delivery, approve-mileage, apply-mileage-penalty (InboundDeliveryController.php:370,400,1370,1500+)
Delivery merging inbound-delivery-merging view, add (InboundDeliveryMergingController.php:24,103)
Offloading points offloading-points manage-offloading-points (OffloadingController.php:418)
Idle vehicles idle-vehicles view (nav logistics.blade.php:269)
Logistics settings logistics-settings view (nav logistics.blade.php:278)
Logistics dashboard logistics-dashboard view (nav logistics.blade.php:50)
Small packs small-packs view, store-loading-sheets, dispatched-loading-sheets (logistics.blade.php:288,301,308)
Inspection routines inspection-routines / vehicle-inspection-routines view (logistics.blade.php:318,325)
Inspection report vehicle-inspections-report view (logistics.blade.php:332)
Device management device-management, device-type, device-sim-card, device-repair, device-center view (logistics.blade.php:342-381)
Reports delivery-and-logistics-reports, vehicle-profitability-report, procurement-jobs-report view (logistics.blade.php:386-402)

Actor roles (inferred from behaviour, see §7): - Drivers — mobile-app users. Their vehicle carries a statuses() record with task_type = 'INBOUND_DELIVERY'; the mobile endpoints (getDriverTripDetails, updateDriverTrip, driverScheduleDelivery) drive the state machine (InboundDeliveryController.php:409,552,646). - Logistics / procurement back-office — schedule deliveries, merge, approve mileage, apply penalties, and force-complete via endDelivery (InboundDeliveryController.php:1354). - Branch receivers — record arrival/offloading via OffloadingController::updateDelivery (OffloadingController.php:445), scoped to auth()->user()->restaurant_id. - HQ roles — is_hq_role / config('app.allowed_role') see all branches in merging; others are scoped to their own branch (InboundDeliveryMergingController.php:44-48).


3. Processes (trigger → states → routes → outcome)

3.1 The inbound-delivery lifecycle

Trigger — creation. An inbound delivery is not created from the logistics nav. It is spawned upstream when an own-collection LPO is issued: BulkPurchasesController::… calls InboundDelivery::query()->create([...]) with document_type => 'SUPPLIER_COLLECTION', document_id => $lpo->id, tonnage/value, and a route_id, then ->createUpdatedFuelLpo() (BulkPurchasesController.php:1245-1262). Inter-branch transfers create deliveries analogously (document_type => 'INTER_BRANCH_TRANSFER', NInventoryLocationTransferController). The row starts at status = 'pending' (create_inbound_deliveries_table.php:37).

States (status string column). The driver mobile flow walks these in order, each transition handled by a handle* method dispatched from updateDriverTrip via a match (InboundDeliveryController.php:675-694):

pending
  └─(admin/driver schedule)──▶ scheduled          [vehicle status INBOUND_DELIVERY created; fuel LPO created; SMS to driver]
scheduled ─(Start Shift: photo+mileage+GPS)──────▶ enroute_to_pickup
enroute_to_pickup ─(Arrived at pickup)───────────▶ arrived_at_pickup   [SMS to doc creator]
arrived_at_pickup ─(Start Loading)───────────────▶ loading_started
  └─(INTER_BRANCH_TRANSFER + undispatched sheets)─▶ receive_items       [bins from InterbranchLoadingSheetDispatch]
loading_started ─(Loading Completed)─────────────▶ loading_completed   [SMS + alert]
loading_completed ─(Heading to dest)─────────────▶ enroute_to_destination
enroute_to_destination ─(Arrived, geo-fence chk)─▶ arrived_at_destination
arrived_at_destination ─(Start Offloading)───────▶ offloading_started
offloading_started ─(Complete, upload docs)──────▶ offloading_completed [recordVehicleRevenue()]
offloading_completed ─(End Shift: photo+mileage)─▶ complete             [vehicle → Idle; fuel LPO enriched w/ telematics; travel-GRN payout]

Terminal / shelved statuses: complete, archived, legacy closed (InboundDelivery.php:136-143). Archived is set when the linked LPO is hidden; archived deliveries can't be scheduled, completed, or route-changed (InboundDeliveryController.php:1366,1520 etc.).

Evidence & guards captured at each hop: - Shift start & end require a dashboard photo + numeric mileage (captureDashboardPhotoAndMileage, 422 if missing — InboundDeliveryController.php:1181-1202); photos land in public/uploads/inbound_delivery_dashboard_photos/. - GPS lat/long recorded at shift start, pickup arrival, destination arrival, shift end. - Destination arrival is geo-fence validated when both enable-geo-fencing and enforce-fueling-station-geo-fencing settings are on, using GeoFencingService against the branch polygon (InboundDeliveryController.php:1045-1093). - Pre-shift fueling can be mandatory (enable_pre_shift_fueling_for_deliveries setting): the shift can't start until a NewFuelEntry exists and is Fueled (InboundDeliveryController.php:806-828).

Outcome. On complete: the vehicle's active status is closed and a fresh "Idle" status opened (InboundDeliveryController.php:1307-1320); the pending fuel LPO is enriched with end-shift mileage/fuel-level from the telematics DB connection (best-effort, never blocks — 1289-1337); and applyTravelGrnPayoutOnDeliveryComplete runs. Vehicle revenue is booked in recordVehicleRevenue() — only for SUPPLIER_COLLECTION with a route_id, pulling revenue_estimate (or revenue_rate_per_km × actual mileage if the route is rate-based) from travel_grn_routes into the vehicle's revenues() (InboundDelivery.php:651-697).

Manual override. endDelivery lets the back-office force a delivery to complete without the driver's own photo/mileage evidence (e.g. dead phone). It requires a mandatory reason, records ended_by + end_reason, and — by explicit design comment — remains available even when ENFORCE_TRAVEL_GRN_COMPLETION_FOR_PAYOUT is on (InboundDeliveryController.php:1346-1470).

3.2 Route & vehicle changes, mileage penalties

Routes can be changed mid-trip: changeRoute validates a new_route_id / new_route_type (supplier_route | inter_branch) + reason, then $delivery->changeRoute(...) records an InboundDeliveryRouteChange and (per route names) requires approval via routeChangeApprovals / approveRouteChange / rejectRouteChange (InboundDeliveryController.php:1500+, routes logistics.php:157-165). Vehicle changes go through a dedicated InboundDeliveryVehicleChangeService (change-vehicle, logistics.php:164).

Mileage approval & penalties. After a trip, an approver enters authoritative start/end mileage via approveMileage; when ENFORCE_TRAVEL_GRN_COMPLETION_FOR_PAYOUT is on, mileage can only be adjusted downwards from the driver-recorded distance (InboundDeliveryController.php:1500+). Over-mileage triggers applyMileagePenalty, writing an inbound_delivery_mileage_penalties row (recorded vs approved distance, variance_km, penalty_amount, status pending→approved/cancelled) and ultimately an EmployeePenalty (InboundDeliveryController.php:1856).

3.3 Merging (Inbound Delivery Merging)

inbound-delivery-merging.index lists un-merged, non-completed deliveries in a date window (InboundDeliveryMergingController.php:37-50). The user picks ≥2 (only pending/scheduled are eligible — 223-236), reviews a computed stop order, then mergeDeliveries (101-221): - creates a new parent InboundDelivery with document_type = 'MERGED_DELIVERY', document_id = 0, a generated MRG-#### document number, and summed tonnage/value; - writes an InboundDeliveryMerge row per original delivery and InboundDeliveryRouteStop rows for the pickup/dropoff sequence; - flags the originals is_merged_delivery = true, reassigns them to the chosen vehicle/driver, releases the other vehicles (new "Delivery merged - vehicle unassigned" status), and reparents their documents.

During the driver flow, merged parents cascade status changes to their originalDeliveries() (InboundDeliveryController.php:850-1041,1276-1285).

3.4 Offloading (branch-side)

Independent of the driver's own trip state, branch staff record offloading against both inbound deliveries and supplier-portal LPOs. updateDelivery enforces a strict 3-step sequence arrival → start_offloading → end_offloading, each writing an OffloadingLog row and (for inbound deliveries) mutating status/timestamps (OffloadingController.php:445-652): - arrival — requires the delivery to be enroute_to_destination. - start_offloading — requires an approved offloading_point_id. - end_offloading — requires manpower (int) + note; sets offloading_end_time.

offloading.admin-logs.view renders the branch-scoped log dashboard; adminLogs groups logs per entity and computes offloading duration (OffloadingController.php:752-890). Offloading points are branch-scoped capacity units (max_trucks_at_a_go, approval status, linked bin locations) managed via offloading-points CRUD (OffloadingController.php:116-221).

3.5 The inbound → offload → GRN handoff (Mermaid)

flowchart TD
    A[Own-collection LPO issued<br/>BulkPurchasesController] -->|InboundDelivery::create<br/>SUPPLIER_COLLECTION| B[InboundDelivery status=pending]
    B -->|schedule| C[Driver trip state machine<br/>scheduled → … → enroute_to_destination]
    C -->|GPS arrival| D[OffloadingLog: arrival]
    D -->|approved offloading point| E[OffloadingLog: start_offloading]
    E -->|manpower + note| F[OffloadingLog: end_offloading<br/>offloading_end_time set]
    F --> G[status=complete<br/>recordVehicleRevenue → travel_grn_routes]
    G -.->|ENFORCE_DELIVERY_OFFLOADING_<br/>FOR_INBOUND_DELIVERIES| H{GRN gate}
    H -->|offloading_end_time present| I[ReceivePurchasedOrderController<br/>allows GRN → Book 2 Ch9]
    H -->|missing| J[422: 'delivery must be offloaded first']

3.6 Idle vehicles, dashboard, settings

  • Idle vehicles (idle.vehicles.index, IdleVehicleController) lists vehicles whose latest status is idle/unassigned and lets a user record a reason (updateReason, logistics.php:190-192).
  • Logistics dashboard (LogisticsDashboardController::index) renders logistics.dashboard.index with a vehicles modal and a daily report drill-down by branch/date (DailyLogisticsReportController, logistics.php:31-35).
  • Logistics settings (LogisticsSettingsController) manages processing-time penalty schemes via InboundDeliveryPenaltyService — banded rows in inbound_delivery_processing_penalties (min_minutes, max_minutes, penalty_amount, is_active, sort_order) with store/update/delete actions (LogisticsSettingsController.php:22-60, logistics.php:194-197).

3.7 Reports

  • Vehicle Profitability (vehicle-profitability-report.index) — costs vs revenues per vehicle, joining fuel, travel-GRN revenue, tracking devices, and shift schedules (VehicleProfitabilityReportController.php:47,286,413,533). Rendered from logistics.vehicle_profitability_report.* views.
  • Procurement Jobs (procurement-jobs-report.index + /data) — a DataTables-style report over procurement/collection jobs (ProcurementJobsReportController.php:26,92).

4. Tables touched & key data (misspellings verbatim)

Inbound / offloading core: - inbound_deliveries — the trip record. Columns include document_number (unique), document_type, document_id, pickup_location_id, destination_branch_id, vehicle_id, driver_id, delivery_date, the timestamp chain (shift_start_time, pickup_arrival_time, loading_start_time/_end_time, delivery_start_time, destination_arrival_time, offloading_start_time/_end_time, shift_end_time), tonnage, value, pickup_location_name, destination_location_name, status (default pending) (create_inbound_deliveries_table.php:14-38). Later migrations add route_id, is_merged_delivery, GPS lat/long + mileage checkpoints, dashboard-photo columns, shift_mileage_approved_at/_by, ended_by, end_reason (migration list under database/migrations/). - inbound_delivery_documents — uploaded delivery notes / supplier invoices / dashboard photos (document_name, document_path, delivery_id). - inbound_delivery_route_changes — route change audit + approval fields. - route_change_requests — separate route-change-request table (create_route_change_requests_table.php). - inbound_delivery_merges — merged_delivery_id, original_delivery_id, merged_by_user_id, merged_at. - inbound_delivery_route_stops — merged-delivery stop sequence (merged_delivery_id, route_sequence, location_name, action_type, original_delivery_id, location_description). - inbound_delivery_offloading_logs — offloading log; action_type enum ['arrival','start_offloading','end_offloading'], offloading_point_id, manpower, note, recorded_by, actioned_at; later gains purchase_order_id so LPO deliveries share the same log table (create_inbound_delivery_offloading_logs_table.php, add_purchase_order_id_to_offloading_logs_table.php). - offloading_points / offloading_points_bin_locations / offloading_point_slot_bookings — offloading point master, pivot to bin locations, and slot bookings (max_trucks_at_ago column — note the missing "at-a-go" in the migration filename add_max_trucks_at_ago_to_offloading_points_table.php). - inbound_delivery_mileage_penalties — recorded_distance, approved_distance, variance_km, penalty_amount, status, plus later route context + approved_by. - inbound_delivery_penalty_bands (migration) and inbound_delivery_processing_penalties (actual table used by settings) — banded processing-time penalties. - customer_offloading_time_logs, delivery_schedule_route_stops — supporting logs/stops.

Interbranch small-parcel (feeds receive_items): - interbranch_loading_sheet_dispatches / interbranch_loading_sheet_dispatch_items — per-bin dispatch sheets with dispatch_status, received_at, loaded_quantity, UOM columns (InboundDeliveryController.php:696-801).

Cross-referenced (owned elsewhere): travel_grn_routes (revenue estimate/rate — Book 2 GRN world), inter_branch_travel_grn_route_rates, wa_purchase_orders, vehicles, vehicle statuses/revenues, new_fuel_entries, and the external telematics connection's vehicle_telematics table.

4b. Small Packs, Inspection Routines & Device Management

Small Packs (SmallPacksContoller.php — note the misspelling Contoller). Workflow: bin managers assemble dispatch batches, then process_dispatch marks a dispatch as dispatched (sets dispatch time, dispatcher, propagates dispatched_quantity from total_quantity), guarding against pending auto-breaks / unreceived dispatches (SmallPacksContoller.php:32,131-216,219,270). Routes small-packs.store-loading-sheets / .dispatched / .dispatched-view (sales_and_receivables.php:251-257); permissions small-packs___store-loading-sheets, ___dispatched-loading-sheets, ___dispatched-sheets-view. Tables: - sale_center_small_pack_dispatches — parent dispatch (sale_center_small_pack_id, created_by, document_no, timestamps). - sale_center_small_pack_dispatch_items — line items (total_quantity, dispatched_quantity). - sale_center_small_pack_dispatch_statuses — per-bin state (dispatched flag, dispatch_time, dispatcher_id, received flag). - sale_center_small_pack_items, plus wa_inventory_items, wa_unit_of_measures (bins), users, routes. - On receipt: small_pack_received_items / small_pack_received_grn_items (feed GRN of received small packs).

Vehicle Inspection Routines (VehicleInspectionRoutineController.php) — a checklist/compliance engine, explicitly not the maintenance/service world (Ch21). A routine defines a frequency (daily/weekly/monthly/specific_date/custom + JSON frequency_config) and inspection_timing (start_of_shift/end_of_shift/both); VehicleInspectionService::generateDueInspections() materialises due vehicle_inspections per assigned vehicle (:59-79,84-121). Checklist items carry dynamic fields (text/number/image/dropdown/location) and photo/notes requirements. Inspectors are assigned by role; a separate approver-role set can approve completed inspections (approved_by, approval_ok, approval_notes — distinct from submitted_by). Routes vehicle-inspection-routines.* (resource + tasks/vehicles/roles/run-inspections) and vehicle-inspections.report/.detail/.approve (sales_and_receivables.php:260-292); permissions vehicle-inspection-routines___view/add/edit, vehicle-inspections-report___view. Tables: - vehicle_inspection_routines (name, frequency, frequency_config, inspection_timing, specific_date, is_active, created_by, soft-deletes). - vehicle_inspection_checklist_items + vehicle_inspection_checklist_item_fields (dynamic field defs). - vehicle_inspection_routine_vehicles (pivot, nullable route_id), vehicle_inspection_routine_users (inspector roles), vehicle_inspection_routine_approver_roles (approver roles). - vehicle_inspections (routine_id, vehicle_id, assigned_user_id, scheduled_date, status pending/in_progress/completed/failed/skipped, has_defects, started/completed_at, approval fields, soft-deletes). - vehicle_inspection_results (per-item pass/fail/na, is_defect, photo_path, JSON field_values).

Device Management (Device Center) — the operational repair + SIM lifecycle for portable hardware (phones/tablets), built on the Device model / devices table (device_type_id, model, serial_no, device_no, branch_id, simcard_id). This is a different data model from Ch18's tracking devices (TrackingDevice / tracking_devices, GPS command fields), which is the boundary stated in §5. Controllers & tables: - DeviceCenterController — device master + allocation/return (with OTP receipt verification) + bulk upload/allocate. Tables devices, device_logs (issue/return audit: issued_to, issued_by, date_issued, verify_otp, is_received), sim_card_to_devices (SIM↔device history). Permissions device-center___view/add/show/edit/bulk-upload/bulk-allocate (DeviceCenterController.php:41-705); routes device-center.* (logistics.php:130-147). - DeviceTypeController — device_types (title) CRUD; perms device-type___view/add/edit/delete. - DeviceSimCardController — device_sim_cards (phone_number) CRUD; perms device-sim-card___view/add/edit/delete. - DeviceRepairController — device_repairs (device_id, status, repair_cost, charge_to, charged_user, comment, complete_date, completed_by, completed_comment); perms device-repair___view/add/edit/delete; routes device-repair.* resource (logistics.php:150).


5. Interactions with other modules

Book 2 Ch9 — GRN (the primary seam). The inbound delivery is the physical half of receiving; the GRN is the inventory half. The link is inbound_deliveries.document_id → wa_purchase_orders.id (documentPurchaseOrder(), InboundDelivery.php:232). When ENFORCE_DELIVERY_OFFLOADING_FOR_INBOUND_DELIVERIES is enabled, ReceivePurchasedOrderController refuses to receive an own-collection LPO whose delivery lacks offloading_end_time, returning a 422 (ReceivePurchasedOrderController.php:1554-1577). It also reads the original delivery's route to pre-populate GRN route info (:1027-1028). Offloading points are tied to inventory bin locations (wa_unit_of_measures) so offloading knows where on site stock lands (OffloadingController.php:83-110,125).

Fuel (Ch19) — cross-reference only. Scheduling a delivery calls createUpdatedFuelLpo(), creating/attaching a NewFuelEntry; completion enriches it with telematics mileage/fuel. Fuel LPO creation/approval is Ch19's lane; this chapter only triggers it.

Vehicle register & tracking devices (Ch18) — boundary (confirmed). These are two separate data models, not one. Ch18 owns the vehicle GPS/telematics device master via TrackingDevice → table tracking_devices (columns on_command, off_command, buzzer commands) and its assignment to a vehicle (TrackingDevicesController::index does TrackingDevice::query()->withCount(['vehicles'])), plus the raw telematics feed used here for mileage/fuel enrichment. This chapter's Device Center owns portable-hardware operations via a different Device model → table devices, covering the repair workflow (device_repairs) and SIM-card lifecycle (device_sim_cards, sim_card_to_devices, device_logs). Same word "device", different tables — that is the boundary. Vehicle revenue booked here surfaces in Ch18's vehicle P&L via vehicles.revenues.

Route compliance / inspections (Ch21) — boundary. Ch21 covers vehicle service/maintenance and route-compliance. This chapter's Vehicle Inspection Routines are recurring checklists (tasks assigned to vehicles + roles, run on a schedule) — an operational readiness check, not a service job. They share the vehicles register but are a separate data model (see §4b).

Sales & inventory (Small Packs). Small-pack dispatch draws on interbranch transfer / sale-center small-pack tables and feeds branch receipt + GRN of the received small packs (small_pack_received_grn_items).


6. Alternatives & variants (flags / tenant)

Settings / flags observed to change behaviour: - ENFORCE_DELIVERY_OFFLOADING_FOR_INBOUND_DELIVERIES — gates GRN on offloading completion (ReceivePurchasedOrderController.php:1564). - ENFORCE_TRAVEL_GRN_COMPLETION_FOR_PAYOUT — forces mileage to only be adjusted downwards on approval, and governs travel-GRN payout; the manual endDelivery override is deliberately exempt (InboundDeliveryController.php:1349,1500+). - enable_pre_shift_fueling_for_deliveries — blocks shift start until the vehicle is fuelled (InboundDeliveryController.php:806-828). - enable-geo-fencing + enforce-fueling-station-geo-fencing + geo-fencing-threshold — gate destination-arrival on proximity (InboundDeliveryController.php:1047-1067). - Route-based revenue: travel_grn_routes.calculate_revenue_per_rate / revenue_rate_per_km switch flat-estimate vs actual-mileage revenue (InboundDelivery.php:673-683). - Document-type variants: SUPPLIER_COLLECTION, INTER_BRANCH_TRANSFER, MERGED_DELIVERY change document lookups, required upload docs (Delivery Note + Supplier Invoice vs Inter Branch Transfer Note), booking-slot behaviour, and whether receive_items (bin receipt) appears (InboundDeliveryController.php:429-508,489-494). - Branch scoping: HQ roles (is_hq_role / config('app.allowed_role')) see all branches; others are restricted to their own in merging and offloading (InboundDeliveryMergingController.php:44). - Supplier portal integration: offloading and slot lookups call an external SUPPLIER_PORTAL_URI via ApiService, degrading gracefully on failure (OffloadingController.php:256-283, InboundDeliveryController.php:512-539).


7. Open questions — CODE-PROVEN vs INFERENCE

CODE-PROVEN: - The full inbound-delivery status chain and its handle* dispatch (InboundDeliveryController.php:675-694 and each handler). - GRN is gated on offloading_end_time under the enforcement flag (ReceivePurchasedOrderController.php:1554-1577). - Delivery rows are created upstream from own-collection LPOs with document_type = SUPPLIER_COLLECTION (BulkPurchasesController.php:1245-1262). - Offloading is a shared 3-step log across inbound deliveries and portal LPOs, in one table with two nullable FKs (OffloadingController.php:445-652, offloading-logs migration). - Merging creates a MERGED_DELIVERY parent + merge/route-stop rows and reassigns vehicles (InboundDeliveryMergingController.php:101-221). - Revenue booking only fires for SUPPLIER_COLLECTION with a route (InboundDelivery.php:651-697); INTER_BRANCH has no rates "yet" (code comment :657). - Penalty settings are banded processing-time rows in inbound_delivery_processing_penalties (LogisticsSettingsController.php:29).

INFERENCE (needs runtime/permission-seed confirmation): - The exact human roles behind each permission string (driver vs logistics-officer vs branch-receiver) — inferred from behaviour, not from a role/permission seeder (not read here). - Whether route_change_requests and inbound_delivery_route_changes are both live or one is legacy — both migrations exist; only routeChanges()→InboundDeliveryRouteChange is wired in the model (InboundDelivery.php:260). - inbound_delivery_penalty_bands migration exists but settings use inbound_delivery_processing_penalties; the bands table may be unused/legacy — not confirmed. - Precise GRN write-back (does completing offloading auto-create a GRN, or merely unlock manual GRN?) — code shows gating, not auto-creation; auto-creation not observed.


8. Source references

  • Nav: resources/views/admin/includes/sidebar_includes/logistics.blade.php:43-410
  • Routes: routes/modules/logistics.php:31-197; routes/web.php:633-638 (offloading), :5314-5315 (profitability); routes/modules/sales_and_receivables.php:251-286 (small packs, inspections)
  • Inbound controller: app/Http/Controllers/Admin/InboundDeliveryController.php (index :46, listing :57, driver flow :409-1344, endDelivery :1354, scheduleDelivery, changeRoute, approveMileage :1500+)
  • Merging: app/Http/Controllers/Admin/InboundDeliveryMergingController.php:1-453
  • Offloading: app/Http/Controllers/Admin/OffloadingController.php:1-891
  • GRN seam: app/Http/Controllers/Admin/ReceivePurchasedOrderController.php:1027-1028,1554-1577
  • Delivery creation seam: app/Http/Controllers/Admin/BulkPurchasesController.php:1245-1262
  • Model: app/Models/InboundDelivery.php (statuses :122-148, relations :200-263, recordVehicleRevenue :651-697)
  • Migrations: database/migrations/2025_06_25_215414_create_inbound_deliveries_table.php; ..._create_inbound_delivery_offloading_logs_table.php; ..._create_inbound_delivery_merges_table.php; ..._create_inbound_delivery_route_stops_table.php; ..._create_inbound_delivery_mileage_penalties_table.php; ..._create_inbound_delivery_penalty_bands_table.php; ..._create_interbranch_loading_sheet_dispatches_table.php
  • Reports/settings: VehicleProfitabilityReportController.php, ProcurementJobsReportController.php, LogisticsDashboardController.php, IdleVehicleController.php, LogisticsSettingsController.php
  • Small packs: app/Http/Controllers/Admin/SmallPacksContoller.php:32,131-290
  • Inspections: app/Http/Controllers/Admin/VehicleInspectionRoutineController.php:38,59-121,202-405,408-543; models app/Models/VehicleInspection.php, VehicleInspectionRoutine.php
  • Device management: app/Http/Controllers/Admin/DeviceCenterController.php, DeviceTypeController.php, DeviceSimCardController.php, DeviceRepairController.php; models app/Models/Device.php (this chapter) vs app/Models/TrackingDevice.php (Ch18)