Vendor & Multi-Store
The platform is a marketplace, not a single-seller shop. Independent vendors run their own stores, list their own products, and get paid out from the orders they fulfil.
Becoming a vendor
Onboarding is a real application flow, modelled by VendorApplication, which
moves through explicit states:
pending ──▶ invited ──▶ approved
│
└────────▶ rejected / expired
An application captures business details — business name, business type (individual, sole proprietorship, partnership, private limited, …) and a description — and is validated before it can be submitted. Invitations carry a 7-day expiry, so a stale invite link cannot be used indefinitely.
KYC
Before a vendor can transact, they complete Know Your Customer
verification. StoreKycDetail holds the store’s legal and payout
information — addresses, banking, identity — separately from the public store
profile. KYC is what gates a store from “registered” to “able to sell”.
The vendor dashboard
Once approved, a vendor manages their store through a dedicated dashboard
(VendorDashboardService, Vendor::* controllers):
- list and edit products, with an admin review step before products go live;
- track orders and shipments for their store;
- view payouts and settlement history.
Payouts
Vendor money is handled by the payments layer.
PayoutCalculationService works out what each vendor is owed from settled
orders, and Payout records track the money out the door — with
payout_mailer keeping vendors informed.
Authorization
Every vendor action is gated by Pundit policies. A vendor can only see and mutate their own store, products, and orders; the admin review workflow is a separate policy surface. The same policy objects guard the Product API, so there is one permission model, not two.
Key files
| Concern | Files |
|---|---|
| Models | VendorApplication, Store, StoreAddress, StoreKycDetail, Payout |
| Services | StoreRegistrationService, VendorDashboardService, PayoutCalculationService |
| UI | Vendor::StoreController, Vendor::ProductsController, store_mailer, payout_mailer |