Implementation Plan: Enable FAF on Rental Orders
Status: Ready for Implementation
Date: April 24, 2026
Reference: ADR-002-FAF-on-Rental-Orders.md
Author: Cascade AI Assistant
Overview
This document provides a phased implementation plan for enabling Fuel Adjustment Factor (FAF) on rental orders. Each phase is designed to be implemented and tested independently.
Phase 1: Backend Repository Layer (Foundation) ✅ IMPLEMENTED
Objective: Implement core FAF calculation logic in the repository layer that all other components will use.
Files to Modify:
app/Repositories/OrderRentalRepository.php
Changes:
1.1 Update createDetail() Method (Lines ~1272-1342)
public static function createDetail(
$detail,
$code,
$type,
$date,
$price = 0,
$qty = 1,
$additionalData = [],
$additionalPrice = 0,
$isFromRunsheetGroup = 1
) {
// ... existing code ...
// Calculate FAF using FuelAdjustmentRepository (fresh from current Partner config)
$fafBaseAmount = $price * $qty;
$faf_total_amount = FuelAdjustmentRepository::calculateFAF($fafBaseAmount);
$fafConfig = FuelAdjustmentRepository::getFAFConfig();
$faf_applied_type = null;
$faf_applied_rate = 0;
if ($faf_total_amount > 0 && $fafConfig) {
$faf_applied_type = $fafConfig->faf_type;
$faf_applied_rate = $fafConfig->faf_value;
}
// Calculate subtotal including FAF
$baseSubtotal = $price * $qty;
$subtotalWithFAF = $baseSubtotal + $faf_total_amount;
$delivery = OrderDetail::create([
// ... existing fields ...
'subtotal' => $subtotalWithFAF, // Subtotal includes FAF
// ADD THESE FAF FIELDS:
'faf_applied_type' => $faf_applied_type,
'faf_applied_rate' => $faf_applied_rate,
'faf_total_amount' => $faf_total_amount,
// ... rest of fields ...
]);
return $delivery;
}
1.2 Update extraOrderDetailTask() Method (Lines ~785-889)
public static function extraOrderDetailTask($data, $order, $request)
{
// ... existing code ...
// Calculate FAF before creating order detail
$fafBaseAmount = $data['final_price'] * $data['quantity'];
$faf_total_amount = FuelAdjustmentRepository::calculateFAF($fafBaseAmount);
$fafConfig = FuelAdjustmentRepository::getFAFConfig();
$baseSubtotal = $data['final_price'] * $data['quantity'];
$subtotalWithFAF = $baseSubtotal + $faf_total_amount;
$newOrderDetail = OrderDetail::query()->create([
// ... existing fields ...
'price' => $data['final_price'],
'quantity' => $data['quantity'],
'subtotal' => $subtotalWithFAF, // Subtotal includes FAF
// ADD FAF FIELDS:
'faf_applied_type' => $faf_total_amount > 0 ? $fafConfig->faf_type : null,
'faf_applied_rate' => $faf_total_amount > 0 ? $fafConfig->faf_value : 0,
'faf_total_amount' => $faf_total_amount,
// ... rest of fields ...
]);
// ... rest of method ...
}
Testing Checklist:
- Test runsheet generates child order details with FAF
- Test empty task includes FAF in subtotal
- Test delivery task includes FAF in subtotal
- Test extra empty invoice includes FAF in subtotal
- Verify FAF calculation:
$price * $qtybase amount - Verify subtotal = base + FAF
Note: This createDetail() method is also called during rerun runsheet when FAF config changes. The fresh FAF calculation ensures new config is applied to future order details.
Phase 2: Backend Controllers (Manual Child Detail Creation) ✅ IMPLEMENTED
Objective: Add FAF to manual child order detail creation routes.
Files to Modify:
app/Http/Controllers/Admin/OrderController.php
Changes:
2.1 Update storePickupDate() Method (Lines ~4243-4293)
public function storePickupDate(Request $request, $id)
{
$order = Order::findOrFail($id);
$orderDetail = OrderDetail::findOrFail($request->change_over['order_detail_id']);
$newOrderDetail = DB::transaction(function () use ($request, $order, $orderDetail) {
// Calculate FAF before creating order detail
$fafBaseAmount = $request->change_over['price'] * $request->change_over['quantity'];
$faf_total_amount = FuelAdjustmentRepository::calculateFAF($fafBaseAmount);
$fafConfig = FuelAdjustmentRepository::getFAFConfig();
$baseSubtotal = $request->change_over['price'] * $request->change_over['quantity'];
$subtotalWithFAF = $baseSubtotal + $faf_total_amount;
$newOrderDetail = OrderDetail::create([
// ... existing fields ...
'subtotal' => $subtotalWithFAF, // Subtotal includes FAF
// ADD FAF FIELDS:
'faf_applied_type' => $faf_total_amount > 0 ? $fafConfig->faf_type : null,
'faf_applied_rate' => $faf_total_amount > 0 ? $fafConfig->faf_value : 0,
'faf_total_amount' => $faf_total_amount,
]);
$openStatus = Status::where([
'namespace' => 'task',
'name' => 'Open',
])->first();
TaskRepository::create('C', 'Pickup', $request->change_over['change_over_date'], $openStatus, $newOrderDetail, 0, 1);
return $newOrderDetail;
});
return [
'data' => $newOrderDetail,
'message' => 'date has ben created successfully',
'status' => 1
];
}
Testing Checklist:
- Test "Create Pickup Bin" from rental order page includes FAF
- Verify FAF fields in response data
- Verify subtotal includes FAF
Phase 3: Backend Controller FAF Updates ✅ IMPLEMENTED
Objective: Add FAF calculation and storage to backend controller methods that currently lack FAF support.
Backend FAF Status:
- ✅
ChangeOverController@store- Has FAF (lines 95-96, 125-126, 171-173) - ✅
OrderController@storePickupDate- Has FAF (Phase 2) - ✅
FrontBinController@postExtraInvoice- Has FAF viaOrderRentalRepository::extraOrderDetailTask(Phase 1) - ❌
RentalBinsController@storeRentalBinOrder- Missing FAF - ❌
RentalBinsController@storeChangeOver- Missing FAF - ❌
RentalBinsController@storeEmptyReturn- Missing FAF
3.1 Update RentalBinsController@storeRentalBinOrder (Line 1752)
Add FAF calculation before creating OrderDetail:
// Calculate FAF based on total price (price × quantity)
$totalPrice = $request->rental_order['price'] * $request->rental_order['quantity'];
$fafData = FuelAdjustmentRepository::calculateFAF($totalPrice, $order->customer_id);
$fafAmount = $fafData['faf_total_amount'];
// Include FAF in subtotal
$subtotal = $request->rental_order['grandTotal'] + $fafAmount;
Add FAF fields to OrderDetail create:
'faf_applied_type' => $fafData['faf_applied_type'],
'faf_applied_rate' => $fafData['faf_applied_rate'],
'faf_total_amount' => $fafAmount,
3.2 Update RentalBinsController@storeChangeOver (Line 695)
Add FAF calculation before creating OrderDetail:
// Calculate FAF based on total price (price × quantity)
$totalPrice = $change_over['price'] * $change_over['quantity'];
$fafData = FuelAdjustmentRepository::calculateFAF($totalPrice, $order->customer_id);
$fafAmount = $fafData['faf_total_amount'];
// Include FAF in subtotal
$subtotal = $change_over['grandTotal'] + $fafAmount;
Add FAF fields to OrderDetail create:
'faf_applied_type' => $fafData['faf_applied_type'],
'faf_applied_rate' => $fafData['faf_applied_rate'],
'faf_total_amount' => $fafAmount,
3.3 Update RentalBinsController@prepareEmptyReturn (Line 1136)
Add FAF calculation before returning data:
// Calculate FAF based on total price (price × quantity)
$totalPrice = $orderDetail['price'] * $orderDetail['quantity'];
$fafData = FuelAdjustmentRepository::calculateFAF($totalPrice, $order->customer_id);
$fafAmount = $fafData['faf_total_amount'];
// Include FAF in grandtotal
$grandtotal = @$orderDetail['grandTotal'] + $weightExtraPrice + $fafAmount;
Add FAF fields to return array:
'faf_applied_type' => $fafData['faf_applied_type'],
'faf_applied_rate' => $fafData['faf_applied_rate'],
'faf_total_amount' => $fafAmount,
Phase 4: Frontend Vue Components (FAF Display) ✅ IMPLEMENTED
Objective: Add FAF calculation and display to frontend components for transparency.
Files to Modify:
resources/js/components/AdminChangeOver.vue- Change Over form (non-rental) - Remove rental exclusion onlyresources/js/components/rental-bins/RentalBin.vue- Create Bin Rental Fee Orderresources/js/components/rental-bins/changeOverRentalBins.vue- Create Change Over (rental)resources/js/components/rental-bins/EmptyReturnRentalBins.vue- Create Empty and Returnresources/js/components/rental-bins/PickupDate.vue- Create Pickup Bin - Already has FAF (Phase 2)resources/js/components/front-bins/ExtraEmpty.vue- Create Empty (frontlift/wheelie bins) - Already has FAF (Phase 1)
Files NOT Modified:
AddServicePricing.vue- No FAF display in service pricing forms (admin aware from Partner config)EditServicePricing.vue- No FAF display in service pricing forms
Changes:
4.1 Update AdminChangeOver.vue (Lines ~1942-1965)
Remove rental exclusion:
// BEFORE (around line 1942):
if (this.order.is_rental) {
this.fafAmount = 0;
this.fafDisplayText = '';
return;
}
// AFTER:
// Remove this block - rental orders should now include FAF
Fix FAF calculation to include quantity:
// BEFORE (around line 1957):
const basePrice = parseFloat(this.orderDetail.price) || 0;
// AFTER:
const totalPrice = (parseFloat(this.orderDetail.price) || 0) * (this.orderDetail.quantity || 1);
Update FAF calculation to use totalPrice:
// BEFORE (around line 1960):
this.fafAmount = Math.round(basePrice * (this.faf_config.faf_value / 100) * 100) / 100;
// AFTER:
this.fafAmount = Math.round(totalPrice * (this.faf_config.faf_value / 100) * 100) / 100;
4.2 Update rental-bins/RentalBin.vue - Create Bin Rental Fee Order
Add FAF calculation method (reference AdminChangeOver.vue lines 1935-1960):
calculateFAF() {
if (!this.faf_config || !this.faf_config.has_faf) {
this.fafAmount = 0;
this.fafDisplayText = '';
return;
}
// Calculate total price (base price × quantity)
const totalPrice = (parseFloat(this.orderDetail.price) || 0) * (this.orderDetail.quantity || 1);
if (this.faf_config.faf_type === 'percentage') {
this.fafAmount = Math.round(totalPrice * (this.faf_config.faf_value / 100) * 100) / 100;
this.fafDisplayText = this.faf_config.faf_value + '%';
} else {
this.fafAmount = parseFloat(this.faf_config.faf_value) || 0;
this.fafDisplayText = '$' + this.fafAmount.toFixed(2);
}
}
Display FAF in order summary section.
4.3 Update rental-bins/changeOverRentalBins.vue - Create Change Over (Rental)
Add FAF calculation method (reference AdminChangeOver.vue lines 1935-1960).
Display FAF in order summary section.
4.4 Update rental-bins/EmptyReturnRentalBins.vue - Create Empty and Return
Add FAF calculation method (reference AdminChangeOver.vue lines 1935-1960).
Display FAF in order summary section.
4.5 rental-bins/PickupDate.vue - NO CHANGES NEEDED
Status: Already has FAF display (Phase 2).
4.6 front-bins/ExtraEmpty.vue - NO CHANGES NEEDED
Status: Already has FAF display (Phase 1).
4.7 AddServicePricing.vue - NO CHANGES NEEDED
Status: No FAF display in Service Pricing forms.
Reason: Admin is already aware of FAF enable/disable/type from Partner config page. FAF will be displayed on child order details and invoices.
4.8 EditServicePricing.vue - NO CHANGES NEEDED
Status: No FAF display in Service Pricing forms.
4.9 Pass faf_config from Controllers to Blade Views
Objective: Ensure faf_config is passed from controllers to Blade views so Vue components can receive it as a prop.
Controller Methods to Update:
4.9.1 RentalBinsController - createRentalBinOrder (line 1751-1768)
File: app/Http/Controllers/Admin/RentalBins/RentalBinsController.php
Add faf_config retrieval:
// Get FAF configuration from Partner model
$fafConfig = FuelAdjustmentRepository::getFAFConfig();
return view('admin.rental-bins.rental-bin', compact('order', 'services', 'fafConfig'));
4.9.2 RentalBinsController - createChangeOver (line 666-693)
File: app/Http/Controllers/Admin/RentalBins/RentalBinsController.php
Add faf_config retrieval:
// Get FAF configuration from Partner model
$fafConfig = FuelAdjustmentRepository::getFAFConfig();
return view('admin.rental-bins.change-over', compact(
'order',
'services',
'binWeights',
'drivers',
'wasteTypes',
'fafConfig'
));
4.9.3 RentalBinsController - createEmptyReturn (line 1041-1087)
File: app/Http/Controllers/Admin/RentalBins/RentalBinsController.php
Add faf_config retrieval:
// Get FAF configuration from Partner model
$fafConfig = FuelAdjustmentRepository::getFAFConfig();
return view('admin.rental-bins.empty-return', compact(
'order',
'orderDetails',
'binWeights',
'taskDetail',
'coupon',
'services',
'stations',
'drivers',
'binSizes',
'fafConfig'
));
4.9.4 RentalBinsController - editEmptyReturn (line 1090-1143)
File: app/Http/Controllers/Admin/RentalBins/RentalBinsController.php
Add faf_config retrieval:
// Get FAF configuration from Partner model
$fafConfig = FuelAdjustmentRepository::getFAFConfig();
return view('admin.rental-bins.edit-empty-return', compact(
'order',
'orderDetails',
'binWeights',
'taskDetail',
'coupon',
'services',
'stations',
'orderDetail',
'binWeights',
'drivers',
'binSizes',
'fafConfig'
));
Blade Views to Update:
4.9.5 admin/rental-bins/rental-bin.blade.php
File: resources/views/admin/rental-bins/rental-bin.blade.php
Add faf_config prop to rental-bin component:
<rental-bin
code="EBNZ-{{ strtoupper(Str::random(10)) }}"
order_from="admin"
url_to="{{ URL::to('/admin') }}"
date="{{ date('j F Y') }}"
:order="{{ json_encode($order, JSON_NUMERIC_CHECK) }}"
:details="{{ json_encode($order->details, JSON_NUMERIC_CHECK) }}"
:customer_="{{ json_encode($order->customer, JSON_NUMERIC_CHECK) }}"
price="0"
stripekey="{{ config('services.stripe.public_key') }}"
:pos_services="{{ json_encode($services, JSON_NUMERIC_CHECK)}}"
:faf_config="{{ json_encode($fafConfig) }}"
></rental-bin>
4.9.6 admin/rental-bins/change-over.blade.php
File: resources/views/admin/rental-bins/change-over.blade.php
Add faf_config prop to change-over-rental-bins component:
<change-over-rental-bins
code="EBNZ-{{ strtoupper(Str::random(10)) }}"
order_from="admin"
url_to="{{ URL::to('/admin') }}"
date="{{ date('j F Y') }}"
:order="{{ json_encode($order, JSON_NUMERIC_CHECK) }}"
:order_detail="{{ (isset($orderDetail))?json_encode($orderDetail, JSON_NUMERIC_CHECK):'null' }}"
:details="{{ json_encode($order->details, JSON_NUMERIC_CHECK) }}"
:customer_="{{ json_encode($order->customer, JSON_NUMERIC_CHECK) }}"
price="{{ json_encode($order->orderPricingModule->change_over_price, JSON_NUMERIC_CHECK) }}"
stripekey="{{ config('services.stripe.public_key') }}"
:pos_services="{{ json_encode($services, JSON_NUMERIC_CHECK) }}"
:bin_informations="{{ json_encode($binWeights, JSON_NUMERIC_CHECK) }}"
:drivers="{{ json_encode($drivers, JSON_NUMERIC_CHECK) }}"
:waste_types="{{ json_encode($wasteTypes, JSON_NUMERIC_CHECK) }}"
:faf_config="{{ json_encode($fafConfig) }}"
></change-over-rental-bins>
4.9.7 admin/rental-bins/empty-return.blade.php
File: resources/views/admin/rental-bins/empty-return.blade.php
Add faf_config prop to empty-return-rental-bins component:
<empty-return-rental-bins
:order_="{{ json_encode($order, JSON_NUMERIC_CHECK) }}"
order_from="admin"
:details="{{ json_encode($order->details, JSON_NUMERIC_CHECK) }}"
code="{{ 'EBNZ-'.strtoupper(Str::random(10)) }}"
date="{{ (\Carbon\Carbon::now())->format('Y-m-d') }}"
stripekey="{{ config('services.stripe.public_key') }}"
:customer_="{{ json_encode($order->customer, JSON_NUMERIC_CHECK) }}"
:pos_services="{{ json_encode($services, JSON_NUMERIC_CHECK)}}"
:stations="{{ json_encode($stations, JSON_NUMERIC_CHECK) }}"
:bin_informations="{{ json_encode($binWeights, JSON_NUMERIC_CHECK) }}"
:drivers="{{ json_encode($drivers, JSON_NUMERIC_CHECK) }}"
:bin_sizes="{{ json_encode($binSizes, JSON_NUMERIC_CHECK) }}"
:faf_config="{{ json_encode($fafConfig) }}"
></empty-return-rental-bins>
4.9.8 admin/rental-bins/edit-empty-return.blade.php
File: resources/views/admin/rental-bins/edit-empty-return.blade.php
Add faf_config prop to empty-return-rental-bins component:
<empty-return-rental-bins
:order_="{{ json_encode($order, JSON_NUMERIC_CHECK) }}"
order_from="admin"
:details="{{ json_encode($order->details, JSON_NUMERIC_CHECK) }}"
code="{{ 'EBNZ-'.strtoupper(Str::random(10)) }}"
date="{{ (\Carbon\Carbon::now())->format('Y-m-d') }}"
stripekey="{{ config('services.stripe.public_key') }}"
:customer_="{{ json_encode($order->customer, JSON_NUMERIC_CHECK) }}"
:pos_services="{{ json_encode($services, JSON_NUMERIC_CHECK) }}"
:stations="{{ json_encode($stations, JSON_NUMERIC_CHECK) }}"
:bin_informations="{{ json_encode($binWeights, JSON_NUMERIC_CHECK) }}"
:order_detail="{{ json_encode($orderDetail, JSON_NUMERIC_CHECK) }}"
:drivers="{{ json_encode($drivers, JSON_NUMERIC_CHECK) }}"
:bin_sizes="{{ json_encode($binSizes, JSON_NUMERIC_CHECK) }}"
:faf_config="{{ json_encode($fafConfig) }}"
></empty-return-rental-bins>
Note: AdminChangeOver.vue already receives faf_config from ChangeOverController.php (admin/change-over/update.blade.php).
Testing Checklist:
- Test FAF displays in AdminChangeOver.vue (after removing rental exclusion)
- Test FAF displays in rental-bins/RentalBin.vue
- Test FAF displays in rental-bins/changeOverRentalBins.vue
- Test FAF displays in rental-bins/EmptyReturnRentalBins.vue
- Verify FAF displays in rental-bins/PickupDate.vue (already working)
- Verify FAF displays in front-bins/ExtraEmpty.vue (already working)
- Verify NO FAF display in AddServicePricing.vue (as intended)
- Verify NO FAF display in EditServicePricing.vue (as intended)
- Verify FAF calculation matches backend
- Verify grand total includes FAF
- Verify faf_config is passed from controllers to Blade views
- Verify faf_config prop is received by Vue components
Phase 5: Testing & Validation ⏳ PENDING
Objective: Comprehensive testing of all FAF scenarios including rerun after config change.
Note on Rerun Runsheet:
When FAF config is updated, the system will trigger RerunRunsheetCalendar command starting from tomorrow's date. This will:
- Delete existing future child order details (from tomorrow onward)
- Regenerate them using the new FAF config via
OrderRentalRepository::createDetail() - Existing order details (today and past) remain unchanged
Test Scenarios:
4.1 Runsheet Flow Tests
- Generate runsheet for rental order with FAF enabled
- Verify child order details have FAF snapshot
- Verify subtotal includes FAF
- Generate runsheet with FAF disabled
- Verify FAF = 0 on child order details
4.2 Manual Creation Tests
- Create Pickup Bin manually - verify FAF
- Create Extra Empty Invoice - verify FAF
- Create Empty & Return - verify FAF (via runsheet)
- Create Change Over - verify FAF (via runsheet)
4.3 Rerun Tests (FAF Config Change)
- Update FAF config (enable/disable or change value)
- Trigger rerun runsheet from tomorrow's date
- Verify new FAF values applied to future order details only
- Verify existing order details (today/past) unchanged
- Verify existing invoices unchanged
- Verify active rental contracts get new FAF for future runsheets
4.4 Invoice Tests
- Generate invoice for rental order
- Verify FAF line item appears
- Verify FAF amount correct
- Test PDF invoice
- Test email invoice
4.5 Category Tests
- Test frontlift bin rental
- Test wheelie bin rental
- Test trash bag rental
- Test skip bin rental
4.6 Edge Cases
- Test FAF percentage type
- Test FAF fixed amount type
- Test FAF = 0 (disabled)
- Test quantity > 1
- Test price = 0 (pickup)
Phase 6: FAF Config Change Rerun ⏳ PENDING
Objective: Automatically rerun all active rental runsheets when FAF config changes, so future child order details use the new FAF rates.
Flow:
- Admin saves FAF config →
updateFAFConfig()detects change viawasChanged() - Dispatch
RerunRunsheetForFAFChangeJob - Job finds all active rental RunsheetGroups → dispatches
ScheduleGroupJobper group ScheduleGroupJobcallsRunsheetRentalRepository::changeTaskGroups()which handles deletion of future open tasks/details and regeneration
Reference: Same pattern as RunsheetGroupController::update() (lines 364-368) where ProgressHelper::setProgress() is called before dispatch(new ScheduleGroupJob()).
Files to Modify:
app/Http/Controllers/Admin/GeneralWasteBinHireController.php— add change detection + dispatchapp/Jobs/RerunRunsheetForFAFChangeJob.php— new file
Changes:
5.1 Add Change Detection in updateFAFConfig() (Lines ~220-263)
public function updateFAFConfig(Request $request, $supplier_id)
{
$partner = Partner::where('is_default', 1)->first();
// ... existing validation and auth checks ...
$partner->update([
'has_faf' => $validated['has_faf'] ?? false,
'faf_type' => ($validated['has_faf'] ?? false) ? $validated['faf_type'] : null,
'faf_value' => ($validated['has_faf'] ?? false) ? $validated['faf_value'] : null,
'faf_label' => $validated['faf_label'] ?? 'Fuel Adjustment Factor',
]);
// NEW: Trigger rerun if FAF config changed
if ($partner->wasChanged(['has_faf', 'faf_type', 'faf_value'])) {
dispatch(new RerunRunsheetForFAFChangeJob());
}
return response()->json([
'success' => true,
'message' => 'FAF configuration updated successfully'
]);
}
5.2 Create RerunRunsheetForFAFChangeJob
New File: app/Jobs/RerunRunsheetForFAFChangeJob.php
<?php
namespace App\Jobs;
use App\RunsheetGroup;
use App\Helpers\ProgressHelper;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class RerunRunsheetForFAFChangeJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public function __construct()
{
}
public function handle()
{
$runsheetGroups = RunsheetGroup::where('is_active', 1)
->whereIn('category', ['frontlift bin', 'wheelie bin', 'trash bag', 'skip bin', 'rental bin'])
->get();
foreach ($runsheetGroups as $runsheetGroup) {
ProgressHelper::setProgress($runsheetGroup->id, 0);
dispatch(new ScheduleGroupJob($runsheetGroup));
}
}
}
How it works:
ScheduleGroupJobreceives aRunsheetGroupand callsRunsheetRentalRepository::changeTaskGroups()changeTaskGroups()deletes future open tasks + child order details, then regenerates them viagetNextdateSchedule()orgenerateScheduleSession()- Regenerated child order details will pick up the new FAF config via
OrderRentalRepository::createDetail()(Phase 1)
Testing Checklist:
- Test FAF config change triggers
RerunRunsheetForFAFChangeJob - Test
wasChanged()returns false when FAF config unchanged - Test all active rental RunsheetGroups are processed
- Test
ProgressHelper::setProgress()is called before eachScheduleGroupJob - Test future child order details have updated FAF values
- Test existing order details (today/past) are NOT affected
- Test
changeTaskGroups()handles deletion + regeneration correctly
Phase 6: Cleanup (Optional) ⏳ PENDING
Objective: Remove dead code and finalize.
Files to Modify:
app/Repositories/FuelAdjustmentRepository.php
Changes:
6.1 Remove Rental Check (Optional)
// In applyFAFToOrderDetail() method (lines ~63-66)
// Remove or comment out:
// if ($order->is_rental) {
// return;
// }
Note: This method is dead code but cleaning it up prevents confusion.
Summary Table
| Phase | Status | Components | Test Focus |
|---|---|---|---|
| 1 | ✅ Done | Repository (createDetail, extraOrderDetailTask) | Runsheet flow, FAF calculation, subtotal |
| 2 | ✅ Done | Controller (storePickupDate) | Manual Pickup creation |
| 3 | ✅ Done | Backend Controllers (3 methods: storeRentalBinOrder, storeChangeOver, prepareEmptyReturn) | FAF calculation and storage in backend |
| 4 | ✅ Done | Vue (4 components: AdminChangeOver, RentalBin, changeOverRentalBins, EmptyReturnRentalBins) | FAF display in frontend |
| 5 | ⏳ Pending | All | End-to-end testing, edge cases |
| 6 | ⏳ Pending | FAF Config Change Rerun (RerunRunsheetForFAFChangeJob → ScheduleGroupJob) | Change detection, rerun trigger, updated FAF on future details |
| 7 | ⏳ Pending | Repository cleanup | Code cleanup |
Notes:
- Phase 3 adds backend FAF support to 3 controller methods that were missing it
- Phase 4 adds frontend FAF display to 4 Vue components (PickupDate and ExtraEmpty already have FAF from Phases 1-2)
AddServicePricing.vueandEditServicePricing.vuedo NOT show FAF (admin aware from Partner config)- When FAF config changes,
RerunRunsheetForFAFChangeJobdispatchesScheduleGroupJobper active RunsheetGroup —changeTaskGroups()handles deletion + regeneration wasChanged()is used to detect actual FAF config changes (no manual comparison needed)
End of Implementation Plan