Development walkthrough
Payment, sourcing and speed
What was built across three phases, how it was done, and the result of every test.
Abad Naseer · 8 August 2026 · measured on the development server, 25,631 products
Three pieces of work, all built and running on the development server:
Each section says what the problem was, what changed, and how. Every screenshot is real output from the development server. The last section lists each test and its result.
| Environment | Development server, marketz.smartzees.com |
| Catalog | 25,631 products |
| Measured | 8 August 2026 |
| Code | github.com/jafgithub/aichat-v2-abad, branch main |

The assistant as a shopper sees it.

| Before | After | |
|---|---|---|
| Answering a search | 3.8 to 4.7 seconds | 0.07 to 0.26 seconds |
| Answering by voice | Recording ran to a 15 second limit, then 3 to 21 seconds to understand it | About 4 seconds once the shopper stops speaking |
| Taking payment | Not possible | Stripe and PayPal |
| Order status | Always "confirmed", even unpaid | Unpaid until the provider confirms |
| A product we do not stock | A dead end | Can be requested and ordered |
| Staff view of orders | None | At /admin |
| Selling the last unit twice | Possible | Prevented |
| Double clicking Confirm | Created two orders | Returns the original |
| Product names | 2,292 showed "Member?s Mark" | 1,919 repaired |
| Automated tests | 38 | 104 |

Four faults were found in that same order path while adding payment. They mattered little when nothing was being charged, and a great deal once it was.
| Fault | Why it happened |
|---|---|
| The same unit could be sold twice | Checking the stock and reducing it were separate steps |
| A double click created two orders | Nothing recognised a repeated request |
| One shopper had two customer records | Email matching with nothing in the database enforcing it |
| A stalled mail server hung the checkout | Emails were sent while the shopper waited, with no time limit |
Stripe is used through its own hosted payment page, so card details never touch our site. It covers cards, Apple Pay and Google Pay together. PayPal is separate, and brings Venmo.


Each attempt carries a one-off key. The same key arriving again returns the order already created, and the database enforces it even if both arrive at once.

Reducing stock is one database instruction that only succeeds if there is enough left. No gap between checking and taking.



A page at /admin listing orders, payment attempts and takings, with a count of orders awaiting payment. It is protected by a token that is entered once.

A shopper asking for something outside the catalog got whatever happened to share a word or two with what they asked for. No way to say "we can get it", and no record that anyone had asked.



Both found by checking the live database rather than trusting the description of it in the code.
| What we assumed | What is true | What we did |
|---|---|---|
| The database numbers new products | It does not, they would all be zero and the second would fail | Number them from 900,000,000 up, clear of the client's own range |
| The picture field holds a web address | It holds thirty characters, enough for a filename | Widened it on our copy only |
New products stay on our side and are not written into the client's catalog. His system numbers its own products, and writing into it needs his agreement first. The mechanism is designed and can be switched on when he is ready.



A correction worth making plainly. An earlier version of this document said a spoken reply took 3.2 seconds. That figure came from a test clip of three words, and it was not what shoppers were experiencing.
Watching real use showed two separate problems:
| Problem | Cause | Fixed |
|---|---|---|
| Recordings ran to the 15 second limit | How loud counts as silence was a fixed number chosen in advance. In a room noisier than that number, the level never drops below it, so the turn never ends. | Yes. It now listens to the room first and sets the bar above whatever it finds. |
| One transcription in five took 13 to 21 seconds | The speech service itself, unrelated to how long the clip is. A clean clip never stalls. | Bounded. It now gives up after 12 seconds and asks the shopper to repeat, because a quick "say that again" beats a very slow answer. |
So a shopper could finish speaking and then wait for the recorder to give up before anything was even sent. Measured again after the fix, a spoken reply takes about four seconds once they stop talking.
Going below that needs continuous streaming audio instead of a recording, which is a larger piece of work and has not been started.
2,292 of the 25,631 product names contained a question mark where another character belonged, so shoppers read "Member?s Mark". The original character is genuinely gone: it is stored as a literal question mark, and the client's own database has the same.
1,919 of them were apostrophes and have been repaired. The remaining 381 are accented letters and symbols, not apostrophes, and replacing those blindly would make them worse:
| Stored | Should be | A blanket replace would give |
|---|---|---|
| Jalape?o | Jalapeño | Jalape'o |
| Nestl? | Nestlé | Nestl' |
| Cr?me | Crème | Cr'me |
| Enfamil? | probably a trademark symbol | Enfamil' |
Those 381 span 110 different words and need a decision per brand, so they were left alone. The repair script lists them.

Two things to know. This fixes our copy only; the client's own data still has the broken names. And a catalog import copies his names over ours, so the repair has to be re-run after each import. It is written to be safe to run repeatedly.
These run in about a second and are checked on every change. They went from 38 to 104.

| What is tested | Tests | Covers |
|---|---|---|
| Stock and orders | 14 | Overselling, releasing stock after a failed payment, duplicate orders, one customer per email |
| Adding a product from elsewhere | 18 | Product numbering, required fields, no duplicates, over-long picture addresses |
| Reply wording | 34 | Every reply a shopper can see, numbering matching the list, no stray characters |
| Understanding what was said | 18 | "add item 2" and "add item two" meaning the same thing |
| Catalog search | 20 | Results identical to the old method, category filters, empty catalog |
Each of these was run against the running system, not in isolation.
| Check | Result |
|---|---|
| Both services running, catalog loaded | Pass, 25,631 products |
| Payment methods available | Pass, Stripe and PayPal |
| An order is created unpaid | Pass, status "pending" |
| The same request twice | Pass, returned the original order |
| Two shoppers, one unit left | Pass, one accepted, one refused, stock zero |
| A genuine payment confirmation | Pass, order confirmed |
| The same confirmation replayed | Pass, ignored |
| A forged payment confirmation | Pass, refused |
| Searching outside the catalog | Pass, results returned |
| Requesting one of those products | Pass, created and added to the cart |
| Requesting the same one again | Pass, reused, no duplicate |
| Search speed | Pass, 0.07 to 0.26 seconds |
| Product names | Pass, nothing left to repair |
| Test data removed afterwards | Pass, catalog back to 25,631 |


Not every experiment was kept. Two were tried and abandoned, both recorded here because the reasoning matters as much as the result.
A faster model for understanding speech. It saves about half a second per spoken reply and mishears more often. A misheard order costs more than half a second saves.
Replacing every question mark in a product name. It would have repaired 1,919 names and damaged 381 others.
Stated plainly so nothing here is taken for more than it is.
Payment through Stripe and PayPal on test credentials. Requesting products we do not stock. Searches answering in under a quarter of a second. The staff view. The repaired product names.
| Going live with payments | Which country the business is registered in, and when to swap the test credentials for real ones |
| Appearing in Google | Whether product barcodes exist anywhere in the product data. Without them a Google listing cannot be submitted |
| Requested products | Who confirms the price and availability, and how the shopper is told |
| How the assistant sounds | Six to ten replies written in the voice it should have. Worth more than any technical change |