Skip to main content
Restaurant Tech · Completed

ADP Payroll Scheduler

PAR-to-ADP payroll automation that saves 2 to 4 hours per biweekly cycle while preserving validation and audit trails.

PythonAWS LambdaMicrosoft GraphPDF Parsing

Outcome at a glance

  • Saves 2 to 4 hours per biweekly payroll cycle
  • Estimated 52 to 104 hours saved annually at the current cadence
  • Converts two unstructured PAR POS reports into validated ADP-ready files
  • Produces both an import file and an Excel audit trail
  • Supports scheduled cloud execution with a local fallback

Problem

Every two weeks, payroll staff had to turn two PAR POS reports into a format ADP could import. The source arrived as unstructured PDFs. Multi-job employees appeared on multiple rows, identifiers had to match, and tip calculations had to follow the configured business rules exactly.

The process consumed several hours and carried financial risk. A malformed row, missing employee match, or arithmetic error could delay payroll or create a correction cycle.

Approach

I built a Python pipeline that retrieves the reports from Outlook through Microsoft Graph, parses the PDFs with pdfplumber, consolidates the records with pandas, and generates ADP-compatible CSV and Excel output.

Validation happens before delivery. The pipeline checks required identifiers, row structure, totals, exclusions, and output shape. A failed check stops the run and creates an alert. A successful run sends the files and archives the output for audit and recovery.

Architecture

OutlookPAR POS PDFsSourceGraph APIMSAL authFetchpdfplumberregex extractParsepandasDecimal calculationsvalidate + auditTransformADP CSV+ Excel auditemail + S3OutputBiweekly payroll pipeline: PAR POS reports → validated ADP files
DiagramExpand for a closer read
ADP Payroll Scheduler pipeline

The cloud path runs in AWS Lambda and stores outputs in S3. DynamoDB tracks run history and batch identifiers. Secrets Manager holds credentials, EventBridge starts the biweekly workflow, and AWS CDK defines the infrastructure. The same processing code can run locally when a payroll deadline requires a fallback.

Exact financial arithmetic

Payroll calculations use Python Decimal values. Converting through strings prevents binary floating-point artifacts from entering money calculations, and rounding happens only at the output boundary.

from decimal import Decimal, ROUND_HALF_UP

def as_money(value: object) -> Decimal:
    amount = Decimal(str(value))
    return amount.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)

The processing order is explicit: parse source values, normalize employee identifiers, consolidate multi-job rows, apply the configured tip rules, validate totals, and then format the ADP output.

Reliability and recovery

Payroll cannot wait for someone to notice that a scheduled job failed. The system records each run, prevents duplicate processing, and supports a catch-up path after a missed scheduled execution. Alerts describe the failed validation without attaching sensitive employee data.

The audit workbook preserves the intermediate totals used to create the import file. Reviewers can check exceptions and approve the result without rebuilding the payroll by hand.

Result

The scheduler has saved 2 to 4 hours per biweekly cycle since January 2026. At 26 cycles per year, that is an estimated 52 to 104 hours of annual capacity. The workflow shifts staff time from transcription to exception review while keeping a recoverable audit trail.

Impact

What moved, what constrained it, and what trade-offs stayed visible.

Operational outcome, the limits around it, and the practical decisions that shaped the work.

Impact

Automated the biweekly PAR-to-ADP preparation workflow and saved 2 to 4 hours per cycle since January 2026, equivalent to an estimated 52 to 104 hours annually.

Constraints

Payroll data is sensitive, the source PDFs are unstructured, money calculations require exact rounding, and the workflow must recover before a fixed payroll deadline.

Trade-offs

Used line-oriented PDF parsing because the reports are not stable tables. Preserved both cloud execution and a local fallback because payroll continuity matters more than maintaining a single runtime path.

  • Architecture and selected implementation details are available on request