Sale Customers
Location: dg_smart_pos_api/modules/SaleCustomers. Owns a standalone, lightweight customer directory captured at the point of sale: a SaleCustomer is keyed by name (unique per store), can be auto-created silently when a cashier types a name that doesn’t match an existing one, and is deliberately separate from the base customers table (debtors/suppliers) and from Repair’s own RepairCustomer.
Gated per store by the maintain_customer_data system config, enforced by the system.config:maintain_customer_data route middleware on the whole route group, confirmed in modules/SaleCustomers/Routes/sale_customers.php. App\Services\SaleService and Modules\Sales\Services\Api\SalesService both check the same flag directly before calling into this module; when it’s off, sale write paths skip customer linking entirely rather than calling in for a no-op.
Data model
Section titled “Data model”SaleCustomer-name,store(FK tostores, unique together withname),phone, soft-deletable.emailandshipping_addressare declared$fillableon the model (shipping_addresscast toarray), but neither column exists in the module’s migration; onlyid,name,store,phone, timestamps,deleted_at, anddeleted_byare actually created. No current controller code sets either field, so this is unused rather than actively broken, but don’t assume they can be written to yet.
SaleCustomerController::index/store/update/destroy is plain CRUD scoped to a store, with name required unique per store (sale_customers_store_name_unique) and phone validated against a Kenyan local-format regex (a leading 0 followed by 9 digits).
Auto-linking from a sale
Section titled “Auto-linking from a sale”SaleCustomerLinkingService::resolve() is the entry point sale write paths call when maintain_customer_data is on: given a typed customer_id, name, and phone, it resolves to a saved SaleCustomer, first by ID, then by a case-insensitive trimmed name match, then by creating a new row. Creation races are handled explicitly: a unique-constraint violation on (store, name) falls back to re-fetching and linking to whichever concurrent request won.
Route surface
Section titled “Route surface”All under auth:sanctum + system.config:maintain_customer_data, prefix store/{store}/sale-customers (note: not the {module}/stores/{store} + REST convention most other modules use), registered via modules/SaleCustomers/Routes/sale_customers.php (required once from routes/tenant.php):
| Method | Path | Controller method |
|---|---|---|
| GET | all |
index |
| POST | add |
store |
| PUT | {customer}/edit |
update |
| DELETE | {customer}/delete |
destroy |