H

Hero Ecotech

B2B
live

SAP-integrated B2B field-sales ordering app and backend.

Backend + app engineer2025 – 2026Core of a small teamAuribises TechnologiesEnterprise / ERP integration
Flutter
TypeScript
Express 5
Firebase
Algolia
SAP

Overview

A field-sales ordering app for B2B staff that talks to the customer's SAP ERP through a custom TypeScript backend. I built the backend integration and was effectively the only engineer on the Flutter app.

I was the only engineer on the Flutter app and built the backend's SAP integration, price-sync pipeline, and Algolia sync. A teammate set up the initial SAP data import.

How it works

1

Field-sales app

Flutter, staff place orders

2

TypeScript backend

Express, mediates every call

3

SAP ERP

Orders in, master data out

4

Firestore + Algolia

Synced data, fast search

The app only ever talks to my backend. The backend speaks SAP's language on one side and keeps Firestore and Algolia in step on the other.

Engineering challenges

01Talking to a legacy SAP system that wasn't built for this

Problem. Orders, customers, products and prices all live in the customer's SAP system, and SAP doesn't make itself easy to reach. It sat on a private IP but answered with a certificate for a hostname, so a normal HTTPS call just failed the check. Placing a sales order wasn't a simple POST either; SAP wanted a token handshake first.

Approach. For the TLS mismatch I told the request to use the right hostname for the certificate while still connecting to the IP, with the option of a proper CA cert and a dev-only switch that warns loudly if anyone turns the safety off. For orders I followed SAP's two-step flow: fetch the token, then send the order, and I pulled SAP's real response back out so the app could tell a genuine rejection apart from a dropped connection.

Outcome. The app could place real orders into SAP and stay in step with SAP's data over a connection an off-the-shelf HTTP client refuses to make.

02Keeping orders correct when several people order at once

Problem. Multiple staff place orders at the same time, so order numbers could clash. And an order's printed record could quietly change later if someone edited or removed the customer it pointed at.

Approach. Order numbers are handed out inside a Firestore transaction, so two orders can't grab the same one. Instead of pointing an order at a live customer record, I copy the customer details onto the order when it's created, so the history stays exactly as it was no matter what changes later. On the app side the order code is honest about failure, telling a network drop apart from the server saying no.

Outcome. No duplicate order numbers under load, order history that doesn't rewrite itself, and error messages that actually mean something.

03Moving large SAP data sets without falling over

Problem. Daily syncs pull big sets of customers, products and prices into Firestore and Algolia. Done naively, one oversized payload or one bad record would take the whole run down.

Approach. I raised the request limit for the bulk loads and processed them in batches that keep going even when a record fails, keeping the failed ones in an audit trail to look at later. The price sync runs as a series of named stages, so if it breaks the error says which stage and I'm not guessing. Product variants get a composite id so they map cleanly, and I tuned the batch size by watching it run rather than guessing.

Outcome. Syncs finish even when a few records are bad, failures are isolated and recorded, and a broken run points straight at its cause.

What I'd do differently

  • There are no automated tests around the SAP integration yet, and that fiddly, edge-case code is exactly what benefits most from them. It's the first thing I'd add.
  • The early TLS workaround on the app side was a stopgap. I documented it and removed it once the real certificate was fixed, but I'd reach for the proper fix first next time.