PortaPro Docs

Win and serve customers

desktop_windows
Customer Portal
24/7 access to schedules, invoices, and service history.
price_change
Quotes & Invoices
View, approve, and pay documents online.
event_available
Online Booking
Customers book roll-offs and event rentals on your website and pay a deposit. Nothing is scheduled until you approve.
credit_card
Payment Processing
Secure online payments with flexible options.
sms
Inbox
Portal messages, text (SMS), and email in one inbox per customer, plus a Requests tab for everything customers ask for in the portal.
signature
E-Signatures
Sign contracts digitally with audit trails.
build
Service Checklists
Standardized pumping and cleaning workflows.
map
Venue Blueprinting
Pin inventory clusters on satellite maps, link to quotes, and send branded site plans.
mark_email_read
Email From Your Inbox
Send invoices, quotes, and sales email from your real address, with your real deliverability.

Run the field

assignment_add
Job Schedules & Dispatch
Create jobs, dispatch routes, and manage recurring service.
alt_route
Route Optimization
Routes planned around tank capacity, disposal-site hours, and service windows.
smartphone
Mobile App
Offline-first workflows for field operations.
location_on
Unit Pins
Every unit's exact spot on the site map. Drivers move pins from the field.
description
Services Hub
Service requests, checklists, and proof-of-work logs for every job.
sms
Team Chat
Channels and direct messages for drivers, dispatch, and the office.
connect_without_contact
Walkie-Talkie
Push-to-talk inside the PortaPro app, on the channels your crew already uses, with searchable transcripts.
phone_in_talk
Calls & Huddles
1:1 calls and channel huddles for your crew, plus meetings customers join from a browser.

Control the business

inventory
Equipment Inventory
Availability by date, so a weekend booking shows before the weekend.
festival
Event & Tent Rentals
Kits, tents booked by size, pull sheets, scan-back check-in, and charges for what comes back missing.
dashboard
Event Layouts
Tents and tables to scale on the venue or its floor plan, seating charts from the guest list, and a share link for comments and approval.
calendar_month
28 Day Invoicing
Bill every site automatically on the industry-standard 28-day cycle, with duplicate prevention built in.
attach_money
Bookkeeping & Billing
Quotes, invoices, expenses and receipts, bank reconciliation, and QuickBooks, Xero and FreshBooks sync.
group
Customer Accounts
Profiles, sites and locations, contacts, and history.
format_list_bulleted_add
Leads & Deals
The CRM built into PortaPro.
outdoor_garden
Temporary Fencing
Draw the fence on the satellite map or type the feet: panels, gates, stands, clamps and sandbags counted for you, screen priced by the foot.
Roll-Off Rentals
Live ledger for every container on the ground, overage and landfill disposal billed from the weight ticket, and dumpster requests from the customer portal.
local_shipping
Fleet Management
Maintenance, compliance, inspections, and vehicle tracking.
my_location
GPS Tracking
Plug-in trackers for the trucks, battery tags for the units, and an alert when a unit leaves its pin.
phone_in_talk
Business Phone
A real business line with an IVR, ring groups, voicemail, and recording. Click to dial, ring your cell, and every call logs itself on the customer.
manage_accounts
Team Management
Roles, the time clock, and the credentials about to expire.
person_add
Hiring
A careers page, an application built for CDL drivers, and a Hire button that turns the applicant into a team member.
wallet
Payroll
W-2 and 1099 payroll inside PortaPro. In beta, rolling out in stages.
bar_chart
Reporting & Analytics
Gallons by disposal site, overdue sites, and reports on your billing cycle.
water_drop
Septic Service
The tank on the customer's record, pump-out dates predicted, and every septic report form, from pumping to real estate transfer, shipped and attached to the job.
Also in PortaPro:QuickBooks Sync,Xero Sync,FreshBooks Sync,Claude & ChatGPT,Equipment Scanning,Shared Truck Devices,Consumables,Marketing Tools,Automated Review Requests,Septic Reminders,Celebrations,Help & Support

Run your portable sanitation operation from lead to ledger.

One system, 46 features, no per-user or per-vehicle fees or limitations.See all featuresarrow_forward

Learn & Discover

calculate
ROI Calculator
Estimate time, labor, fuel, and cost savings with PortaPro.
route
Route Efficiency Simulator
See how optimized routing can increase weekly service stops.
scale
Dumpster Weight Calculator
Estimate debris weight and the roll-off size it needs.

Support & Training

headset_mic
Support
Submit a request, email our team, or book a call.
support
Help Centeropen_in_new
Guides, documentation, and step-by-step setup resources.
favorite
Our Promise
Why we refuse to let software get worse over time.

GPS Asset & Vehicle Tracking

How GPS tracking works
location_on
Unit tracking device
A sealed battery tag inside the unit. It reports when the unit moves, and the battery lasts five to seven years.
navigation
Vehicle tracker
Plugs into the truck's OBD-II port. Live location, plus odometer and fuel on supported trucks.

Solutions

local_shipping
In the Field
A service day from the yard to the invoice, and where each job goes wrong.
wc
Portable toilet operators
Same-day missed stops, proof for every stop, and rate card invoices.
water_drop
Septic operators
Pump-outs predicted from the tank, and the county's own forms filled from the job.
water_drop
Grease trap service
Each trap on its own cadence, and the FOG 25% rule measured.
Roll-off haulers
Days past term, tons over the allowance, and landfill fees on one final invoice.
celebration
Tent and party rentals
A tent booked by size, packages as one line, every chair checked in.
festival
Event and festival operators
A site plan on the quote, and a weekend priced as a weekend.
account_balance
Municipal contracts
Invoices before the period with the PO printed, and a record of every park visit.
domain
Multi-location operators
Several yards, service territories, divisions, and roles in one account.
Why Operators SwitchPricing
Sign Inrocket_launchStart Free Trial
homeHelp Centerchevron_rightCustomer Managementchevron_rightFront-Load Recurring Service with Included Pulls

Front-Load Recurring Service with Included Pulls

schedule14 min read
calendar_todayUpdated October 10, 2026
front-loadper-tripincluded pullsextra pullsallowancelate pullday-of-weekskills routingskipped statusphase G

On this page

FTL-1: What Per-Trip Billing DoesFTL-2: Configure a Per-Trip Rate Card RowFTL-3: The Allowance Math (What You'll See on Invoices)FTL-4: Generate the Cycle InvoiceFTL-5: Chronological Pull Splitting (Why It's In Date Order)FTL-6: Editing a Rate Card Without Losing Attribution (Phase G Fix)FTL-7: Offline Service Marking + RPC Attribution (Phase B)FTL-8: Skills Routing for Front-Load (Phase E → Phase F)FTL-9: Skipped Job StatusFTL-10: Cycle-Close Visibility (Phase D)FTL-11: What Broke in the Merge (R2 Fix, July 2026)FTL-12: TroubleshootingFTL-13: Related Articles

Need more help?

Need more help?

Contact Us

Have questions about PortaPro? Fill out the form below and our team will get back to you within 24 hours.

Or schedule a quick call at a time that works best for you.

Contact Us

Have questions about PortaPro? Fill out the form below and our team will get back to you within 24 hours.

Or schedule a quick call at a time that works best for you.

PortaPro

Contact:
support@portaprosoftware.com

© 2026 PortaPro. All rights reserved.
All-in-one software for portable sanitation operators.

Quick Links

PricingROI CalculatorDumpster Weight CalculatorFree TemplatesSeptic Rules by StateCompare SoftwareBlogIn The Field

Platform

DispatchBillingFleet ManagementCustomer Portal

Support

Contact supportGetting set upHelp Centeropen_in_newStatusCareers

Company

TermsPrivacyCookie PolicySecurityAccessibilityAbout

Serving operators across North America. Proudly Built in America. 100% US Customer Support

Privacy Policy·Terms of Service·Accessibility·Contact

This article covers PortaPro's per-trip billing model, the way front-load dumpster service, pump service, and any other "recurring pull" work is billed. If your customer has containers that get serviced on a schedule (weekly, twice-weekly, day-of-week specific) and you want their monthly invoice to say "4 pulls included in base rate, 2 extra pulls at $75 each," this is the workflow.

If you're doing roll-off *terms* (delivery, swaps, pickup, one final statement) see the Roll-Off Swap Cycle Workflow. If you're doing recurring portable-toilet rentals, see the Long-Term Rental Workflow, the two workflows share the Rate Card infrastructure, but per-trip billing has extra machinery for allowances, extra pulls, and late-pull labeling.

---

FTL-1: What Per-Trip Billing Does

The one-line summary

Per-trip billing counts how many times a unit at a customer's site was *serviced* (pulled, dumped, pumped) during the billing cycle and prices it: first N pulls are included in the base rate at $0, extra pulls beyond N bill at the per-pull rate, and any pulls that should have been in the previous cycle but arrived late get their own labeled line.

Why the split matters

"You got 6 pulls this month and pay $600" isn't what the customer wants to see. They want to see:

  • "4 pulls included in base rate", the ones they already paid for as part of their monthly service
  • "2 extra pulls @ $75/pull beyond 4 included", the actual charge that changes cycle to cycle
  • If any pulls from *last* month landed late (paperwork lag): "1 late pull from previous cycle @ $75/pull", clearly separated so the customer knows it's a catch-up, not double-billing
  • This is how the industry has priced front-load service for decades. PortaPro renders every rate card row that has an allowance this way automatically.

    When to use per-trip vs. cycle rental

    Per-tripCycle rental
    Line itemsIncluded / extra pulls / late pullsOne flat line per period
    Rate card field`included_pulls_per_cycle` set`included_pulls_per_cycle = 0`
    Best forFront-load, pump service, dumpster servicePortable toilets, generator rentals, ongoing units

    Set the allowance on the Rate Card row and PortaPro switches modes. No global setting, no separate menu, it's a per-row decision.

    ---

    FTL-2: Configure a Per-Trip Rate Card Row

    Step 1: Open the site's Rate Card

  • From the customer profile → Sites tab → the service location
  • Click Rate Card (or + Add Row to create your first row)
  • Step 2: Fill in the row for per-trip billing

  • Product, the container type (front-load 2-yard, pump service, etc.)
  • Unit type / label, human-readable name shown on invoices
  • Quantity, how many of this type at this site
  • Rate Period, Per Trip / Per Pull. This is what puts the row in per-trip mode; the *Included pulls / cycle* field only appears once it's selected.
  • Rate, the per-pull rate (what a pull costs, and what an "extra" pull costs when there's an allowance)
  • Included pulls per cycle, the allowance N. Leave blank/0 to bill every pull at the per-pull rate.
  • Frequency, required, and it's what actually produces the billable pulls: frequency generates the service jobs, and completing those jobs is what gets counted and billed. A per-trip row with no frequency generates no jobs and bills $0. Leave it blank only for genuine on-call service, where you create each job by hand.
  • Service day of week, which day the driver services this row (e.g. Tuesday for a Tuesday route). Drives skills routing and the driver's route plan.
  • Effective from / to, when this row starts/stops being active
  • Step 3: Save

    That's it. From the next cycle forward, PortaPro:

  • Auto-generates a service job on each `service_day_of_week` for the row
  • Counts every completed service on that row inside the cycle window
  • Computes the allowance split at cycle-close time and emits the labeled lines
  • The day-of-week generator (Phase A)

    When a per-trip row has a `service_day_of_week` set, PortaPro's job generator (which runs when a rate card is saved and again nightly) creates a service job for every occurrence of that weekday in the coming week. So a Tuesday+Friday row on a bi-weekly site creates two jobs each week automatically. Completing those jobs feeds the pull count.

    The dedup key `(auto_generated_from_recurring_unit_id, auto_generated_for_date)` ensures the nightly cron never spawns a duplicate, a row change won't re-open an already-serviced date's job.

    ---

    FTL-3: The Allowance Math (What You'll See on Invoices)

    Say the customer's Rate Card has a per-trip row: 1 front-load dumpster, `included_pulls_per_cycle = 4`, rate $75.

    Cycle with exactly 4 pulls: PortaPro emits one $0 line:

  • "Front-load 2-yard, 4 pulls, included in base rate (4 of 4 included) (Mar 4 – Mar 25)"
  • Cycle with 6 pulls: PortaPro emits two lines:

  • "Front-load 2-yard, 4 pulls, included in base rate (4 of 4 included) (Mar 4 – Mar 18)", $0
  • "Front-load 2-yard, 2 extra pulls @ $75/pull beyond 4 included (Mar 22 – Mar 29)", $150
  • Cycle with 3 pulls (under): PortaPro emits one $0 line:

  • "Front-load 2-yard, 3 pulls, included in base rate (3 of 4 included) (Mar 4 – Mar 18)"
  • Under-consumption doesn't credit the customer, that's what "included" means. If you want under-consumption to credit the customer, add a manual credit; PortaPro won't do it automatically because industry pricing treats included pulls as bundled.

    Late pulls from previous cycle

    If a service was completed with a scheduled date *before* the current cycle's window opened (paperwork lag, driver marked a Feb 27 pull complete on Mar 3), that pull is a late pull from the previous cycle and gets its own labeled line:

  • "Front-load 2-yard, 1 late pull from previous cycle @ $75/pull (Feb 27)", $75
  • Late pulls do not consume the current cycle's allowance, they're an explicit catch-up. If they did, one late pull would eat a customer's Mar-1 allowance slot and shove a Mar-4 pull into overage.

    The Rate Card row id stamp

    Every emitted line stamps `invoice_items.source_rate_card_row_id` back to the row that produced it. This lets PortaPro's cycle-close tools:

  • Show operators which rows produced overage this cycle
  • Match up top-up pulls from mid-cycle draft edits
  • Preserve provenance across Rate Card edits (the row-id survives now, see FTL-6)
  • ---

    FTL-4: Generate the Cycle Invoice

    Manual cycle generation:

  • Customer profile → Sites → Rate Card
  • Generate cycle invoice (the current cycle), or ⋮ → Bill previous cycle for the cycle that just closed
  • Open the draft on the customer's Financial tab and check each row's included, extra and late pull lines before you send
  • Automatic cycle generation happens on the schedule you set in Settings → Finance → Cycle Automation.

    What the operator warning about "extra pulls" surfaces

    At cycle-close time, PortaPro shows a review flag if any per-trip row went over its allowance for the cycle:

  • "3 extra pulls this cycle across 2 sites ($225)", heads-up so you can decide whether it's a normal overage or a signal that this customer needs their allowance bumped
  • This is only informational, the invoice generates normally either way. The flag lets you check the pattern before you send.

    ---

    FTL-5: Chronological Pull Splitting (Why It's In Date Order)

    `buildPerTripRowLines` sorts the cycle's completed pulls by scheduled date before splitting. So "the first 4 included" always means the first 4 chronologically, not the first 4 by ID or by weight.

    This matters when a customer disputes: you can point at the invoice's date range in each line ("included: Mar 4 – Mar 18") and prove exactly which pulls were included and which were overage.

    If two pulls fell on the same date (a make-up + a scheduled together), the tiebreaker is job id, deterministic, but rarely visible.

    ---

    FTL-6: Editing a Rate Card Without Losing Attribution (Phase G Fix)

    Every Rate Card edit used to delete every row for the site and re-insert them. The row ids rotated every save. Downstream tables that referenced those ids (`jobs.auto_generated_from_recurring_unit_id`, `maintenance_reports.recurring_unit_id`, `invoice_items.source_rate_card_row_id`) all lost their links, which caused:

  • The nightly generator re-spawned duplicate jobs on day-of-week rows after any rate-card edit (the dedup key was gone)
  • Historical attribution went dead ("who created this pull?", unlinked)
  • Top-up matches at cycle-close broke
  • Fix (July 2026, Phase G): the RPC is now an id-preserving upsert. Editing a row updates it in place; only genuinely new rows insert; only rows the operator actually removed delete. Row ids survive.

    There's also a partial-writer clobber fix: multiple internal writers (rate modal, day-of-week feature, billing dates feature) each send *some* of the row's columns. The old RPC nulled anything a writer didn't send. Now, a writer omitting a column keeps the existing value, so editing the rate doesn't wipe the weekday anchor, and editing the day-of-week doesn't wipe billing dates.

    You won't see this fix in the UI. You'll see its absence: the nightly generator behaves normally after edits, cycle-close top-up matches work, and historical attribution stays intact.

    ---

    FTL-7: Offline Service Marking + RPC Attribution (Phase B)

    Drivers on-scene without cell signal can still complete service. The mobile app queues the completion in IndexedDB and syncs when signal returns.

    What lands correctly in the sync:

  • The pull is stamped `billable = true` if the row is per-trip
  • The service report is attributed to the driver via `driver_id`
  • The recurring unit id is preserved (Phase G, above) so the pull matches back to its Rate Card row
  • The `auto_generated_for_date` is set to the scheduled date, not the sync date
  • This matters for the late-pull line above (FTL-3): the sync's timestamp isn't the pull's date. A driver who marks a Feb 27 pull complete on Mar 3 gets it attributed to Feb 27 correctly.

    ---

    FTL-8: Skills Routing for Front-Load (Phase E → Phase F)

    Front-load routes are picky: a route needs a rear-loader capable of front-load lift, a driver certified on the equipment, sometimes a specific yard load-out. PortaPro's route planner reads two matching tables to decide:

  • Vehicle skills (`vehicles.skills` array), what a vehicle *can* do (front-load lift, pump, roll-off hoist)
  • Driver skills (`driver_skills` rows), what a driver is qualified to operate
  • Phase F extended this so the planner treats sanitation and containers as separate skill families, a driver certified on portable-toilet service isn't auto-assigned to a front-load run and vice versa unless they're certified on both. This prevents the classic mis-route where a portable-toilet driver gets a container job they don't have the truck for.

    You configure skills in Settings → Team → Skills and per-vehicle in the vehicle detail drawer. New drivers default to their trained skills; edit as they gain certifications.

    ---

    FTL-9: Skipped Job Status

    Sometimes a driver arrives and can't complete the service, the gate's locked, the customer moved the container, the address is wrong. Marking the job `completed` would consume the customer's allowance for a pull that never happened. Marking it `cancelled` loses the attempt history.

    PortaPro has a distinct `skipped` status for this:

  • The job is stamped `skipped` with a reason
  • No pull count is added to the cycle
  • The row stays visible in dispatch history (not memory-holed)
  • The customer's next scheduled service still happens
  • If the skip results in a dry-run fee (customer's fault: they forgot to unlock the gate), attach a manual fee to the job and it sweeps into the cycle invoice per Scenario 5.

    ---

    FTL-10: Cycle-Close Visibility (Phase D)

    Before you close a cycle, PortaPro surfaces a pre-close review panel showing:

  • Extra pulls across the customer base, total dollar amount + count of sites over allowance
  • Late pulls captured this cycle, count + dollar amount
  • Unpriced service sites, sites where a job completed but no Rate Card row matched (surface + fix before you invoice)
  • Autopay-ready customers vs autopay-broken customers (missing card, expired card, disconnected Stripe)
  • The panel is informational, you can generate cycle invoices without it, but it lets you catch data problems the last two months looking at Stripe's dashboard would have missed.

    ---

    FTL-11: What Broke in the Merge (R2 Fix, July 2026)

    Full transparency: earlier in July, a branch merge into dev-staging accidentally reverted the entire per-trip allowance loop to its pre-allowance version. The main invoice generator lost its calls to `buildPerTripRowLines`, every cycle invoice would have been billed as one giant line at the per-pull rate with no allowance split, no included lines, no late-pull labels.

    Worse: the code was still trying to *report* the extra-pull totals ("`perTripExtraPulls`" / "`perTripOverageAmount`") in its return block, but those accumulators had been dropped from the loop. So cycle invoices would have written to the database successfully, then thrown a `ReferenceError` at the return statement, showing the operator a failure toast on an invoice that actually got created.

    The R2 fix: the per-trip loop was recomposed around `buildPerTripRowLines` (the same helper the draft top-up path uses, so the two never disagree). The counters, the `unpricedSites` warning, the `source_rate_card_row_id` stamp, and the chronological staging were all restored. As of the July 2026 dev-staging deploy, this is bit-identical to the pre-merge behavior plus the allowance split, plus the late-pull line.

    You won't have seen this because it was caught and fixed in the same reconciliation pass before it could ship to production. Documenting here so if a customer asks "why did my March invoice look different from April's" the answer is available.

    ---

    FTL-12: Troubleshooting

    "The cycle invoice for a per-trip customer just shows one big line, no included / overage split."

    The Rate Card row's `included_pulls_per_cycle` is 0 or missing. Set it to the allowance number and regenerate.

    "The 'extra pulls beyond N' line is showing on a customer who was under allowance."

    Under-consumption doesn't create an overage line, verify the pull count with the driver's completed jobs. If you're seeing an overage line for 0 or under, that's a bug; report it.

    "Late-pull line showed up on a fresh customer with no previous cycle."

    A pull is late if `scheduled_date < cycle window start`. Check that the customer's cycle billing_start_date is set correctly; if a driver completed a pull for a date before the cycle even opened, it's technically "late from before the account started." Adjust the pull's date, or accept the labeling.

    "The nightly generator created duplicate service jobs after I edited the Rate Card."

    This was the pre-Phase-G bug. Update to the latest deploy (post-July-2026). If you still see it, the dedup key `(auto_generated_from_recurring_unit_id, auto_generated_for_date)` isn't preserving through the RPC, verify the migration `20261008_01` is applied.

    "I edited a row's rate and the day-of-week got wiped to null."

    Same pre-July-2026 bug, partial-writer clobbering. Update to the latest deploy. Post-fix, the RPC preserves omitted columns.

    "A driver marked a pull skipped but the customer got charged for it."

    Skipped pulls do NOT bill. If it billed, verify the job's actual status, some operators write `skipped` in notes but mark the job `completed`. Only the enum status is authoritative.

    "The pre-close review says '3 unpriced sites.'"

    Those sites have completed jobs but no matching Rate Card row (or the row's `product_id` doesn't match the job's product). Open each unpriced site, either create the missing row or fix the product mismatch, then regenerate. Unpriced sites bill at $0 on the invoice, a silent revenue leak if you don't fix them.

    "The operator warning says '2 extra pulls' but the invoice shows 3."

    The counters are refreshed on generation. If the review panel shows a stale count, click Refresh or regenerate; the panel counts from the last generation, not real-time.

    "A driver-skills mismatch blocked a dispatch."

    Check the driver's `driver_skills` rows and the vehicle's `skills` array. For a container job, both need containers; for portable-toilet service, both need sanitation. If both parts of the pair have the right skill and the planner still refuses, the job's product may be miscategorized, the routing engine reads `products.product_type` to decide the required skill.

    ---

    FTL-13: Related Articles

  • Long-Term Rental Workflow (portable-toilet recurring cycles, shared Rate Card infrastructure)
  • Roll-Off Swap Cycle Workflow (term-based billing with final statements)
  • Weekend Event Rental Workflow (per-event windows and public accept + pay)
  • Cycle Close & Invoicing (advanced: proration, credits, autopay)
  • Emergency / On-Call Jobs (surcharges and job fees that ride the cycle)
  • Skills, Vehicles & Route Planning (configuring sanitation/containers skills, driver certifications)
  • Was this article helpful?

    Related Articles

    menu_book

    The Customer Hub and the Customer Profile

    8 min read

    chevron_right
    menu_book

    Adding Customers and Contacts

    7 min read

    chevron_right
    menu_book

    Customer Sites

    5 min read

    chevron_right