Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Invoiceiq Bundle Laravel Package

mlucas/invoiceiq-bundle

InvoiceIQ Bundle provides a Laravel/PHP integration for InvoiceIQ, making it easy to connect your application to InvoiceIQ services for invoice creation, management, and billing workflows.

View on GitHub
Deep Wiki
Context7

Getting Started

  • composer require <vendor>/invoiceiq — the service provider and the POST /_invoiceiq/validate route are auto-discovered; there is nothing to register by hand.

  • Publish and skim the config first: php artisan vendor:publish --tag=invoiceiq-config. That file is the map for everything else (OCR driver, tolerance thresholds, storage toggle).

  • Send your first request with curl before writing any code:

    curl -X POST https://app.test/_invoiceiq/validate \
      -H "Accept: application/json" \
      -F "file=@storage/app/fixtures/invoice-001.pdf"
    

    You get a JSON rapport back: extracted fields, totals/VAT checks, duplicate flag.

  • Read the OCR stub caveat before you demo anything. In v0.1.0 extraction does not really happen. Start by exercising the pipeline end-to-end with a fixture that already yields text (or bind a fake extractor — see below), so you are testing the parser and the checks, not an empty string. Everything downstream of extraction is real; extraction is not.

  • First real use case: a supplier-invoice intake form. User uploads a PDF, your controller forwards it, you read the report, and you route low-confidence documents to a human review queue rather than auto-approving.

Implementation Patterns

Call the service, not the route, from server-side code. The HTTP endpoint is convenient for external callers and for a quick smoke test, but inside your own app an extra loopback request buys you nothing and costs you a timeout budget. Resolve the underlying validator/report service from the container and pass it the uploaded file directly; keep the route for third parties and for the JS front end.

Wrap the report in a DTO immediately. A 0.x JSON contract will move. One mapper class that turns the raw array into your own value object means a key rename in 0.2.0 is a one-file diff instead of a grep across the codebase.

Use pre_validate for context, post_validate for consequences. Attach your tenant id, upload id, or expected vendor in pre_validate; persist the report, write an audit row, or notify an approver in post_validate. Both fire synchronously inside the request — implement ShouldQueue on any listener that touches the database heavily or calls an external API, or your endpoint latency becomes your listener latency.

Persist the report yourself. Storage is OFF by default, so the report is ephemeral. Write it to your own table (invoice_id, report_json, created_at, plus the raw text if you can get it) — you will want it for debugging and for the duplicate check.

Duplicate detection needs a corpus, and storage is the corpus. With local storage disabled there is nothing to compare against across requests, so the duplicate check is close to a no-op in the default configuration. Either enable storage, or maintain your own fingerprint index (vendor + invoice number + total + date) and treat the package's flag as one signal among several.

Bulk intake belongs in a job. One queued job per file, with Http::pool or a bus batch, explicit timeout and a retry policy. Never loop over fifty uploads inside a web request.

In tests, fake the driver and Http::fake() the endpoint. Bind a fake extractor that returns a canned text blob per fixture filename; then your suite covers parser and checks deterministically without depending on the stub's behaviour changing under you.

Treat the report as advisory. Surface confidence, per-check pass/fail and reasons, and always allow a manual override that records who overrode what and why. The checks are arithmetic heuristics, not an audit opinion.

Gotchas and Tips

  • The OCR stub is the headline risk. Anything you build assuming real text extraction will look fine in dev with fixtures and fail on real scans. Confirm the driver binding before promising a go-live date, and put a feature flag in front of the intake form.
  • The route is probably unauthenticated. Anything under /_invoiceiq/ is a public file-upload endpoint by default. Put it behind auth/signed middleware, add throttle, and validate MIME type and size — an open upload endpoint that hands files to an OCR engine is an easy resource-exhaustion target.
  • CSRF. If the route resolves inside the web group, browser POSTs need a _token and multipart forms will 419 in ways that look like a parsing bug. Either exclude the path in VerifyCsrfToken or consume it from the api group.
  • post_max_size / upload_max_filesize beat Laravel validation. Big scans get rejected by PHP before your max: rule ever runs, and the failure looks like an empty request rather than a 422. Set both, and set an explicit client timeout — OCR on a multi-page PDF easily exceeds the default.
  • Storage ON means PII retention. Invoices carry names, addresses, and bank details. Turning the toggle on needs a disk choice, a pruning policy, and an answer to "how long do we keep this". Do not flip it on casually in a shared bucket.
  • Duplicate false positives are normal. Re-sent invoices, credit notes, and recurring subscription invoices with identical amounts all look like duplicates. Never block on the flag; surface it with the reason and let a human decide.
  • VAT mismatches are often legitimate. Rounding, reverse charge, exempt lines, and mixed-rate invoices all trip the check. Make the tolerance configurable and default it generously rather than hardcoding a cent.
  • Events fire per request and in-process. Two listeners doing HTTP calls will quietly make a 300 ms endpoint into a 3 s endpoint. Queue them.
  • Debug by stage. The pipeline is extract → parse → check. Log the intermediate text before the parser; if the report comes back with every check empty, you are almost always looking at an empty extraction, not a parser logic error.
  • Pin ^0.1 and read each changelog. No breaking changes in this release, but pre-1.0 packages reserve the right. The JSON shape and event payloads are the two things most likely to move — keep both behind your own layer and upgrades stay cheap.

Extension points worth knowing: the OCR driver contract (swap the stub for a real engine without touching the parser), the two events, and the config tolerance/threshold block.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle