Laravel in Jeddah
Laravel development for Jeddah retail and distribution
A Laravel development company for Jeddah retailers and distributors. Cash on delivery as a real order state, promotions that run on a lunar calendar, and a queue that has to survive one month a year.
Jeddah is where Saudi commerce is bought and sold, and its systems have a property that surprises anybody arriving from European e-commerce: the order is frequently not paid for.
Cash on delivery is normal here rather than marginal. That single fact reshapes the order model, the stock model and the reconciliation process, and it is the thing most e-commerce codebases get wrong on arrival because they were written on the assumption that money and commitment happen at the same moment.
Payment after delivery in Jeddah is a lifecycle, not a flag
In a prepaid system, the payment event and the order event are nearly simultaneous, so a boolean is almost enough.
With cash on delivery they are days apart and the sequence can fail at any point. The order is confirmed, stock is committed, a courier collects it, and then the customer is not home, or refuses it, or pays a different amount because something arrived damaged. Each of those is an ordinary Tuesday, not an exception.
So the order needs explicit states with recorded transitions - who moved it, when, and why - and the money needs to be a separate record that points at the order rather than a column on it. The practical test is whether the system can answer why a particular order is in its current state three weeks later. If the answer involves looking at courier emails, the model is wrong.
Laravel stock has to be released, not just reserved
The second consequence follows directly and causes more damage.
When payment confirms an order, stock movement has an obvious trigger. Without a payment event, stock is committed on confirmation - which means something has to give it back when an order is refused, abandoned or left undelivered. That release is the step that gets written last and tested least, and its absence is invisible until a sale exposes it as negative availability.
Reservations therefore need expiry built in from the start, and the expiry needs to be a scheduled job that can be reasoned about. Being safe to run twice matters particularly here, because a release job that runs twice must not credit stock twice.
Jeddah promotions run on a lunar calendar
This is the local detail that quietly produces wrong answers, and no library solves it on its own.
Promotional seasons, some accounting periods and a large share of the year's revenue sit on Hijri dates. Lunar months are 29 or 30 days, and the start of a month is not purely arithmetic, so a Hijri period converted to Gregorian once and stored cannot be projected into next year.
The reliable arrangement is that the business supplies the dates for the period ahead, the system stores both representations of them, and no code path converts between the two calendars at runtime. The same reasoning as money and dates generally: the conversion is the bug, and the way to avoid it is to record what was meant rather than recompute it.
Reconciling what a Jeddah courier collected against what was owed
Cash on delivery means a third party holds the money for several days, and the reconciliation of that is a real piece of accounting rather than an import script.
The courier sends a remittance - a file, a statement, sometimes a spreadsheet with a different layout each month - listing what they collected and what they are paying over, net of their fees. The application has its own view of what each shipment should have collected. Those two lists disagree, every cycle, and the differences are the interesting output.
A shipment collected for less than the order total because the customer refused one item at the door. A shipment marked delivered and collected that the application still shows as in transit, because the status update was missed. A shipment in the remittance that the application has no record of. Fees charged at a rate other than the contracted one. Each of those is a different problem with a different owner, and a reconciliation that produces one number - we are out by this much - has done almost none of the work.
So the reconciliation is per shipment, with a status per line, and the unmatched lines are a queue somebody works through rather than a total somebody accepts. Ageing matters too, because money held past the agreed remittance period is a receivable and should appear as one. The courier is a debtor, and treating them as a logistics integration rather than as an account is how a business discovers at year end that it is owed a material amount by a company it never invoiced.
Laravel stock across several Jeddah locations
Once there is more than one place stock can be, availability stops being a number and becomes a question about which place.
A store with shelf stock, a warehouse with bulk, stock in transit between them, and stock reserved against orders that have not yet been picked. A single quantity column cannot hold that, and the sum of all locations is the wrong answer to almost every question anybody asks - because stock in the warehouse does not help a customer standing in the store, and stock in transit is not available anywhere until it arrives.
So quantity is per location and per state, and availability is computed for a purpose. Available to promise for an online order depends on which locations can fulfil it; available for a walk-in depends on one. Transfers are documents with their own lifecycle, because stock that has left one location and not arrived at the other is somewhere, and the somewhere has to be accountable or the discrepancy appears as shrinkage.
Which location fulfils an order is a rule rather than a default, and the rule is commercial. Nearest to the customer, or the location with the oldest stock, or the one that minimises splitting the order, or whichever has capacity to pick today. Expressing that as a configurable rule with the decision recorded against the order is what lets the business change it without a release - and lets somebody answer why a Jeddah order shipped from somewhere else.
Commercially
Scope fixed in writing before work starts, priced per project. The country-level ground - data residency, e-invoicing, who contracts - is on the Saudi Arabia market page.
Invoiced by Codefacture Yazılım A.Ş. in Türkiye, in US dollars, by bank transfer, with no Turkish VAT under the export-of-services exemption.
