Getting Started
Sellino POS — Point of Sale & Inventory System
Developed By: BugBuild Labs
Welcome to Sellino POS
Sellino POS is a complete point of sale, inventory and accounting system for real shops — supershop, grocery, pharmacy, fashion, hardware, restaurant and any counter-based retail business, running one outlet or a whole chain. From a single Laravel codebase you get the counter POS, the full back office, and a companion Flutter POS app.
This package ships two products that share one Laravel backend and database:
- Web Panel (Admin & POS) — this documentation. The Laravel control center: the POS terminal itself plus catalog, inventory, branches, cash, accounting, HR and reports.
- POS App — a Flutter counter app for Android and iOS (covered in the POS App tab).
This edition runs with SITE_MODE=pos-inventory. There is no customer storefront and no vendor marketplace — the panel shows only what a shop actually uses, and what separates one outlet from another is the branch, not a vendor.
Key Features:
- Fast POS sales with multi-payment (cash, bank, mobile money or mixed)
- Counters, cash registers, cash pickup and petty expenses
- Multi-branch — branch-bound warehouses, counters and staff, with branch-wise Profit & Loss
- Products with category, brand, unit, tax, attributes & variations
- Purchase orders, supplier dues and multi-warehouse stock with racks and lots
- Stock adjustment, damage, transfer and supplier returns; FIFO or average costing
- Sale edit & cancel, customer returns, replacements & refunds — stock and accounts corrected automatically
- Built-in double-entry accounting (Chart of Accounts, journals, banks, reconciliation)
- Coupons, flash sales, campaigns and membership points at the counter
- HR & Payroll with loans, advances and payroll journals
- Role-based access control, activity logs and multi-language (RTL/LTR)
- Push notifications (Firebase), local or S3-compatible media storage
- Barcode labels, thermal receipt printing and counter scanner support

Server Requirements
Make sure your hosting meets these before installing the web backend. The built-in installer checks every item automatically on its first screen.
| Requirement | Minimum |
|---|---|
| PHP | 8.3 or higher |
| Laravel | 12.x (bundled with the source) |
| MySQL | 8.0 or higher |
| Web server | Apache or Nginx |
| Build tools | Composer, Node.js & NPM |
| SSL certificate | Recommended for production (HTTPS) |
Required PHP extensions
All of these must be enabled — most shared hosts have them on by default:
BCMath Ctype cURL Fileinfo GD JSON Mbstring OpenSSL PDO Tokenizer XML Zip MySQLi allow_url_fopen
Not sure your server qualifies? Open https://yourdomain.com/install — the installer's first step shows a live green/red check of every requirement and extension above, so you know exactly what to fix.
Database Setup (via cPanel)
Create a MySQL database before running the installer.
Step 1 – Login to cPanel:
Open your hosting cPanel (usually https://yourdomain.com/cpanel).
Step 2 – MySQL® Database Wizard:
Search and open MySQL® Database Wizard.
Step 3 – Create Database:
Enter a database name and click Next Step.
Step 4 – Create User:
Add a username and a strong password, then Create User. Save these securely.
Step 5 – Add User to Database:
Grant All Privileges and finish.
✅ Keep these three ready for the installer:
| Credential | Where you enter it |
|---|---|
| Database Name | Installer → Database Details (or DB_DATABASE in .env) |
| Database Username | Installer → Database Details (or DB_USERNAME) |
| Password | Installer → Database Details (or DB_PASSWORD) |
Host: on most cPanel/shared hosting the database host is localhost. Use that in the installer unless your provider says otherwise.
Package Contents & Source Code
Download Main_Files.zip from your CodeCanyon downloads and extract it locally. Inside you will find the full source for both products, each in its own folder:
| Folder | What it is |
|---|---|
WebSourceCode |
The Laravel backend — the admin panel, the POS terminal and the REST API the app runs on. This is what you install on your server (see Upload & Environment). |
PosAppSourceCode |
The Flutter POS app source (counter app for Android & iOS). Configure it against your server's API — see the POS App guide. |
Both connect to one Laravel backend and database — install WebSourceCode first, then point the app at its API URL.
Also in the package: this documentation, and the standard CodeCanyon licence & changelog. The .env file is not included — you create it during setup (it holds your private database and mail credentials).
Upload Files & Environment
Step 1 – Upload Application:
Extract Main_Files.zip, open the WebSourceCode folder and zip its contents. Upload that to public_html (or your domain root) and extract it on the server. Point your web root at the public/ folder.
Step 2 – Install dependencies (only if installing manually via SSH — skip on shared hosting where vendor files are already included):
composer install npm install && npm run build # optional — only if you edit resources/js or resources/css
Step 3 – Create the environment file — copy .env.example to .env:
cp .env.example .env
Step 4 – Set core values in .env. What each one actually changes:
Identity & mode — set these first
| Variable | What it does if you get it wrong |
|---|---|
APP_NAME | Shown in the panel title bar and outgoing mail. Cosmetic. |
APP_URL | Critical. Every generated link, image URL and payment callback is built from it. A wrong value breaks images in the apps and returns customers to the wrong host after payment. Must include the scheme, no trailing slash — https://shop.example.com. |
APP_ENV | production on a live server, local while developing. Laravel hides detailed errors and enables caching optimisations in production. |
APP_DEBUG | Must be false in production. Left true, any visitor who triggers an error sees your file paths, environment variables and database credentials on the error page. |
APP_KEY | The encryption key for sessions and encrypted columns. Leave it empty and run php artisan key:generate — never reuse someone else's. Changing it later invalidates existing sessions and any encrypted data. |
SITE_MODE | Selects the edition this install runs as — pos-inventory for this item. It decides which panels and routes exist at all (no storefront, no seller panel in POS mode). |
APP_INSTALLED | Set to true by the web installer when it finishes. Flipping it back to false re-opens the installer — only do that on a fresh database. |
APP_DEMO | Leave false. It enables the public demo's passwordless quick-login buttons for the accounts listed in APP_DEMO_EMAILS — intended only for a throwaway demo site, never a real shop. |
Database
| Variable | Notes |
|---|---|
DB_HOST, DB_PORT | Usually 127.0.0.1 and 3306. Shared hosts sometimes require localhost instead. |
DB_DATABASEDB_USERNAMEDB_PASSWORD | The database you created in cPanel. On cPanel these are usually prefixed with your account name (myacct_sellino). A wrong value stops the installer at its database step with a connection error. |
Mail — OTP and notifications depend on this
Mail is not configured in .env — set SMTP host, port, username, password, encryption and the from-address in Admin → Settings → Mail after installing (values are stored in the database). If mail is not working, email OTP, password reset and order mail all silently fail — configure it before going live, and use the panel's Test mail button. Where the host blocks SMTP ports, use the Gmail API transport instead (see Settings → Mail).
Performance & infrastructure — safe defaults ship in .env.example
| Variable | Impact |
|---|---|
QUEUE_CONNECTION | database queues mail, push and exports to a background worker — needs the queue worker running or those jobs never execute. sync runs them inline instead: no worker needed, but the user waits for every email. |
CACHE_STORE, SESSION_DRIVER | database or file works everywhere. redis is faster but needs a Redis server. |
SESSION_LIFETIME | Minutes before an idle panel user is logged out. Default 120. |
FILESYSTEM_DISK | public keeps uploads on the server; s3 sends them to your bucket using the AWS_* values below — see Storage. |
LOG_LEVEL | error in production keeps storage/logs small; debug while troubleshooting. |
BCRYPT_ROUNDS | Password hashing cost. Higher is safer but slower on weak shared hosting. Default 12 is fine. |
API, apps & real-time
| Variable | Impact |
|---|---|
APP_API_KEY | Fallback for the X-App-Key the apps send. The value saved in Settings → API Security wins over this. Empty = the check is off (fail-open). See Security. |
JWT_SECRET | Signs the app's login tokens. Generate your own (php artisan jwt:secret). Changing it logs out every app user immediately. |
JWT_TTL, JWT_REFRESH_TTL | Access-token and refresh-token lifetimes in minutes. Shorter is safer; the app refreshes automatically. |
REVERB_* | Websocket credentials for chat and live updates — only used if you run the Reverb daemon. See Real-time & Chat. |
FIREBASE_PROJECT_IDFIREBASE_CREDENTIALS | Push notifications. Optional — leave unset and everything else still works. See Common Setup. |
AWS_* | Only read when FILESYSTEM_DISK=s3. Works with any S3-compatible provider (Wasabi, DigitalOcean Spaces, R2). |
The .env file is secret. It holds your database password, app key, JWT secret and gateway keys. Never commit it to source control, never share it, and keep it outside public/ — which it already is by default.
Step 5 – Generate the app key:
php artisan key:generate
⚠ Important: Never skip php artisan key:generate — without a valid APP_KEY, sessions and encrypted data will break. (The web installer does this for you automatically.)
Step 6 – File permissions
The web server must be able to write to these paths — the installer's Permissions step checks each one:
| Path | Why it must be writable |
|---|---|
storage/ | Logs, cache, compiled views and uploaded media |
bootstrap/cache/ | Framework config & route cache |
.env | The installer writes your app key, DB and JWT config here |
Set them from SSH:
chmod -R 775 storage bootstrap/cache chmod 664 .env # If the web server runs as another user (e.g. www-data), also give it ownership: chown -R www-data:www-data storage bootstrap/cache .env
On cPanel (no SSH): use File Manager → right-click → Change Permissions and set 775 on storage and bootstrap/cache, and 664 on .env.
Installation
You can install with the web wizard (recommended for shared hosting) or the command line.
Web installer:
- Visit your domain in a browser — the installer opens automatically.
- It checks PHP version, extensions and folder permissions.
- Fill in the Database Details and create the Administrator Account (fields below).
- Click Install Now to run migrations & seed default data.
What you enter in the wizard
| Field | What to put |
|---|---|
| Database Details | |
| Database Host | localhost on most shared/cPanel hosting (change only if your provider says otherwise) |
| Database User | The MySQL username you created (see Database Setup) |
| Database Password | That user's password |
| Database Name | The database you created |
| Administrator Account (your first admin login) | |
| First Name / Last Name | The admin's name |
| Email Address | Admin login email — you sign in with this |
| Password | A strong admin password |
The web installer also generates the app key and the JWT secret automatically — nothing extra to do. When it finishes, sign in with the admin email & password you just set.
Command line (alternative)
On a VPS with SSH you can install without the wizard:
php artisan migrate --seed php artisan jwt:secret # API & mobile apps use JWT for login
The default seed creates the standard roles/permissions and demo settings; create your admin user with your own seeder or the app's user management after login.
Real-time chat: the live chat feature uses Laravel Reverb. On a local/VPS setup run php artisan reverb:start to enable websockets — see Real-time Chat.
Manual Database Migration (if the installer fails)
The web installer runs the migrations and seeders for you. If it times out, dies half-way, or your host blocks long-running requests, do the same work by hand over SSH — the result is identical.
1. Start from a clean database
Migrations are not re-runnable over a half-built schema. If the installer created some tables before failing, drop and recreate the database (or run php artisan migrate:fresh, which drops every table first).
2. Confirm .env is correct
php artisan config:clear php artisan migrate:status # proves the DB credentials work before you change anything
A connection error here means DB_DATABASE, DB_USERNAME, DB_PASSWORD or DB_HOST is wrong — fix that first, nothing else will work.
3. Run the migrations and seed the defaults
php artisan key:generate # only if APP_KEY is still empty
php artisan migrate --force # --force is required when APP_ENV=production
php artisan db:seed --force # currencies, countries, languages, settings,
# permissions, roles and the default admin user
php artisan storage:link # public symlink for uploaded media
4. Mark the install complete
Set APP_INSTALLED=true in .env — otherwise visiting the site re-opens the installer. Then warm the caches:
php artisan optimize:clear php artisan optimize
You can now log in at your admin URL with the seeded administrator account and change its password from Profile & Password.
Common failures
| Symptom | Cause & fix |
|---|---|
SQLSTATE[42000] … max key length | MySQL older than 8.0 (or MariaDB without innodb_large_prefix). Upgrade to MySQL 8.0+ as the requirements state. |
Base table or view already exists | A partial install left tables behind. Drop the database and start from step 1, or use php artisan migrate:fresh --force. |
| Installer page times out | Shared-host execution limit. Use these CLI steps instead — they have no time limit. |
Access denied for user | The DB user has no rights on that database. In cPanel, add the user to the database with All Privileges. |
| Blank page after install | Cached config from the failed attempt. Run php artisan optimize:clear, and check storage/logs/laravel.log. |
Upgrading an existing install? Run only php artisan migrate --force — never migrate:fresh or the plain db:seed, both of which will destroy or overwrite live data. Take a database backup first.
Queue Worker & Scheduler
Background jobs (emails, push notifications, media variants, backups) run through Laravel's queue, and timed jobs through the scheduler. Both are optional at first — but recommended in production.
- Queue driver —
.envships withQUEUE_CONNECTION=sync(jobs run inline, no worker needed). For production setQUEUE_CONNECTION=databaseand run a worker. - Run the worker —
php artisan queue:work. Keep it alive with Supervisor/systemd (same pattern as Reverb), or on shared hosting usephp artisan queue:work:daemon. - Scheduler — add one cron entry:
* * * * * cd /path-to-app && php artisan schedule:run >> /dev/null 2>&1. - Timed commands —
push-campaigns:dispatch-due(scheduled push campaigns),backup:database/backup:files(see Backups),currency:update-rates(nightly FX refresh when daily auto-update is on — see Currency Rates).
After changing QUEUE_CONNECTION or deploying new code, restart the worker: php artisan queue:restart.
Login & Security
The admin login link ends with a randomized security slug (set in config('site.admin_login_path')) so the admin panel is not at a guessable URL.
Login URLs (replace example.com with your own domain):
- Admin:
example.com/admin-7eP9kM4QX2pUoEic/login(slug fromconfig('site.admin_login_path')) - Customer:
example.com/login
Log in:
- Open the admin login link, enter your email and password, click Login.
- If two-step verification is on, enter the code emailed to you.
Forgot password: click Forgot password?, enter your email, type the emailed code, then set a new password.
Note: Never share your password. Change it from Profile & Password if anyone else may know it.


Dashboard
The first screen after login — a quick overview of your business.
- Summary cards: today's sales, orders, customers and revenue.
- Charts: sales and revenue trends at a glance.
- Left menu: opens every module, grouped exactly like this guide.
- Top-right menu: your profile, change password and logout.

Dashboard Styles (Admin Panel Look)
The admin panel itself ships with four looks. Open the style switcher from the top navbar — each entry shows a screenshot thumbnail of that style, so you pick by looking, not by guessing from a name.
| Style | What it looks like |
|---|---|
| Default | The original panel look — no extra stylesheet is loaded. |
| New | Refreshed cards, softer surfaces and updated stat tiles. |
| Glass | Glassmorphism — translucent, blurred panels. |
| Sidebar | Redesigned sidebar-led layout. |
- Per user, not per store — the choice is saved in your session and a one-year cookie, so it survives logout and follows that browser. Another admin can run a different style at the same time.
- Nothing else changes — only CSS. Data, permissions and every screen stay identical.
- This is the admin panel look. The customer-facing website and the apps are styled from Web Theme / App Theme.
Developers: styles are listed in config/dashboard_themes.php. A new style = one entry there (label + stylesheet + preview image) — the switcher, the page and the validation all read that one list.

Categories, Brands, Units & Tax
Supporting lists you set up once and reuse on every product. Open the screen, click Create, fill the fields, and Save.
- Categories & Subcategories (Products → Category) — organize products (e.g. Grocery → Rice) and let customers browse. Create the main category first, then pick a parent for subcategories. Each category takes two images: a banner/thumbnail and a small icon — the icon is what the POS category strips and the app's category grid show, so set it on every top-level category.
- Brands (Products → Brand) — manufacturers you sell, with a logo.
- Units (Products → Unit) — units of measure (pcs, kg, litre, box).
- Tax Rates (Products → Tax Rates) — VAT/GST percentages applied at sale.


Products & Attributes
Attributes (Products → Attributes / Attribute Values) are options like Size or Color with values (S/M/L, Red/Blue), used for products sold in variations.
The Products menu is split by source:
- In-House Products — owned by your own shop.
- All Products — combined list.
- Deleted Products — recycle bin to review/restore.
Add a product: Products → In-House → Create; fill name, category, brand, unit, price and photos; add a description; enable variations & set their prices; set stock (or manage in Product Stocks); Publish. Use the status switch to show/hide it in the shop.




Barcodes & Labels
Every variant carries its own SKU and barcode. Leave the barcode blank and the system generates one, or type the code already printed on the supplier's packaging so the shelf item scans as-is.
- Barcodes (Products → Barcodes) — pick products, choose a label size and print a sheet on a normal or label printer.
- At the counter — a USB or Bluetooth scanner types the code and presses Enter; the line lands in the cart. It works the same in the web POS and the POS app.
- Racks — a scanned item can be pinned to a warehouse rack so staff know where to pick it from.

Finding Products Fast
Everywhere you pick a product — the POS terminal, a purchase order, a stock adjustment — you get the same typo-tolerant search over name, SKU, barcode, category and brand, with live suggestions as you type.
- At the till — type part of a name, or scan a barcode and the item goes straight into the cart.
- Category and brand filters sit next to the search box so a cashier can browse when the customer does not know the name.
- Stock-aware — the POS grid only offers what the active branch's warehouse actually holds, so you cannot sell what is not there.
- Search Keywords (admin) — what staff searched for, including terms that returned nothing, which is a useful hint about what to stock.

Product Stocks & Purchase Orders
Product Stocks (Purchase & Stock → Product Stocks) shows how many units you have. Add stock with a stock entry (product, quantity, cost price); the system reduces it automatically as orders sell. Open a product for its full stock history.
Purchase Orders (Purchase & Stock → Purchase Order) record goods you buy from suppliers. A PO adds stock and creates a payable (what you owe). Choose the supplier, add products with quantity & cost, record any payment made, and Save — stock and supplier dues update automatically.


Adjustment · Damage · Transfer · Returns
- Stock Adjustment — manually correct counts (e.g. after a physical count).
- Damage — write off broken/expired goods so they leave sellable stock.
- Stock Transfer — move stock between warehouses/locations.
- Customer Returns — goods a customer sends back; records the refund and returns items to stock.
- Supplier Returns — goods you send back to a supplier; reduces stock and your supplier due.
Each works the same way: open the screen → Create → pick the product(s)/original order, set quantity & reason → Save.


Warehouses & Suppliers
Warehouses & Racks (Warehouse) — where stock physically lives. Warehouses are buildings/stores; racks are shelves inside them.
Suppliers — the companies you buy from. Each supplier keeps a due/payment ledger linked to purchase orders and supplier returns. Create a supplier with an opening balance, then open it to see purchases, returns and outstanding due.


Inventory Costing (FIFO / Weighted Average)
Every sale needs a cost to produce a true profit figure. Sellino tracks purchase cost in stock layers and picks the cost per sale using the method you choose in Settings → POS.
- FIFO (default) — the oldest purchase cost is consumed first.
- Weighted Average — a running average cost across all remaining stock.
- The chosen cost is snapshotted on the sale line, so a later purchase at a different price never rewrites past profit.
- Feeds COGS, gross profit and the Profit & Loss statement in Accounting, plus stock-valuation reports.
- The method is set once for the shop and applies to every branch, so cost of goods is comparable across outlets.
Pick it before you start trading. Changing the method re-values existing stock — the panel warns you before saving.

Sales
Sale List — every sale rung up at any counter, filterable by status, date, branch and payment state. Each row shows the invoice number, customer, total, what was paid and what is still due.
Sale Details & History — open a sale for its items, customer, payments and the branch and warehouse it belongs to. Footprints record who changed what and when.
Draft sales — a cart parked at the till stays a draft until it is paid. Recall it from the terminal to finish the sale, or cancel it; stock is only committed when the sale completes.
Dues & part payment — take part of the money now and the rest later. The balance shows on the customer's profile and in the due report until it is settled.
Counter invoices — print a thermal receipt at the till or share a PDF; the receipt logo and footer come from POS settings.


Sale Edit & Cancel
A sale that is still a draft — parked at the till, not yet paid — can be changed freely: add items, change quantity, remove a line, apply or drop a discount. Nothing is committed until payment completes, so stock and accounts stay untouched.
After payment
- Cancel — one click with an optional note. Stock goes back to the warehouse it came from and the journals are reversed, so the books show the sale never happened. The record stays for the audit trail; deleting is not the way to undo a sale.
- Return part of it — for "one item back, the rest stays", use a customer return instead of a cancel. That refunds only what came back and re-values the stock at its original cost.
- Fix a payment — take the remaining due, or record the refund of an overpayment, from the sale itself.
What happens to the money
| Change | Effect |
|---|---|
| Total goes up | The extra becomes amount due from the customer — collect it now or leave it on their account. |
| Total goes down | The difference is refunded from the register, or left as a credit on the customer's account. |
| Sale cancelled | Money already taken is refunded, stock returns and every related journal is reversed. |
Who may edit or cancel is a permission, so a cashier can sell all day without being able to rewrite yesterday's takings.
Returns, Replacements & Refunds
A customer brings something back: open the sale and raise a return (money back) or a replacement (swap for another item). Both walk through the same steps — request, inspect, then settle.
- Inspect — mark what actually came back and its condition. Good stock goes back on the shelf at its original cost; damaged stock is written off to the damage account instead of quietly inflating your inventory.
- Refund methods — cash from the register, bank/MFS transfer with a reference, or leave it as store credit against the customer.
- Replacement — hand over the new item, and any price difference is collected or refunded on the spot.
- Accounting — the sale's revenue, cost of goods and any membership points are reversed in proportion to what came back, so the books follow the goods.
Returning only part of a sale? Use a return rather than cancelling the whole sale — see Sale Edit & Cancel.

POS — Counters, Registers & Cash
The POS screen is where the shop actually earns. A sale takes seconds: scan or search, take the money, print the receipt — and behind it stock moves, the drawer balances and the books post themselves.
Before the first sale
- Counters (POS Management → Counters) — one per till. A counter belongs to a branch and has its own cash account in the Chart of Accounts.
- Cash Registers — open a shift with the float you put in the drawer; close it at shift end with the counted cash. Any difference is recorded with a reason, so a short drawer is a fact, not an argument.
- Cash Pickup — a manager taking cash from the drawer to the safe or bank records it here, and the expected drawer balance drops accordingly.
- Petty Expenses — small spending out of the drawer (tea, transport, a rickshaw fare) is booked as an expense against that register.
Selling
Open the POS screen, confirm the branch shown in the bar, pick the warehouse if you keep more than one, then scan or search products. Set quantity, give a line or bill discount, apply a coupon or redeem membership points, choose the customer (or leave it as walk-in), and take payment as cash, bank, mobile money or a mix. Change is calculated for you; the receipt prints to a thermal printer or shares as a PDF.
A cart you cannot finish now can be parked as a draft and recalled later from the sale list — useful when a customer goes back for one more item.
POS Settings
- Inventory Costing Method — FIFO (oldest purchase cost first) or Weighted Average. This drives cost of goods and profit. Changing it re-values existing stock, so the page asks you to confirm.
- Default Customer & Warehouse — what the POS screen pre-selects.
- Max discount, receipt logo & footer — cap what a cashier may give away, and brand the printed receipt.
The same till is in your pocket: the POS App runs the identical flow on Android and iOS, against the same counters and registers.




Branches (Multi-Outlet)
A branch is one physical outlet. It groups its own warehouses, its own counters and the staff who work there — so one install runs a single shop or a whole chain without the outlets stepping on each other.
Setting up
- Branches (Warehouse → Branches) — add a branch with a name, short code, address and phone.
- Assign each warehouse and each counter to its branch on their own edit screens.
- Assign staff to one or more branches on the user's edit screen, and mark one as their home branch.
How much a staff member may see
Each user carries a branch visibility setting, so a cashier does not read the whole chain's numbers:
| Setting | What they see |
|---|---|
| All branches | Everything — the default, and what an owner or accountant wants. |
| Assigned | Only the branches they are assigned to. |
| Own branch | Only the branch they are currently working in. |
| Self | Only the records they created themselves. |
At the till
The POS screen shows an active branch bar. Where a user may work in more than one branch it becomes a switcher; picking another branch reloads the product grid, the warehouse list and the register check, because all three belong to the branch. The POS App carries the same switcher.
Branch-wise money
Every sale, journal, counter and register records the branch it happened in, so Profit & Loss, Income Statement, Trial Balance and Balance Sheet can be filtered per branch — you can compare outlets, not just guess. Stock reports take a branch filter too, and stock transfers move goods between branches with request, approve and receive steps.
Upgrading an existing install? After php artisan migrate, run php artisan branches:backfill once. It creates a default "Main Branch" per owner and attaches existing warehouses, counters and past sales to it. Without it, branch-aware screens have nothing to point at.
Customers
Customers — everyone you have sold to. Add one at the counter in a few seconds (name and phone is enough), or open a profile for their full purchase history, outstanding dues and membership points.
Walk-in customer — sales that need no name go to the built-in walk-in account, so the day's takings still balance without cluttering your customer list.
Dues — a customer who pays part now and the rest later carries a balance you can see per customer and settle from the sale, with the journal posted automatically.
Suppliers live under Warehouses & Suppliers — they are who you buy from, customers are who you sell to.

Coupons, Campaigns & Membership
- Coupons (Promo → Coupons) — discount codes the cashier applies at the till (fixed amount or percentage, with usage limits and a date range).
- Flash Sales (Promo → Flash Sales) — time-limited price drops; the POS picks up the sale price automatically while it runs.
- Campaigns (Promo → Campaign) — themed groups of products and offers (Eid sale, winter clearance) with a date range.
- Membership (Membership Settings / Members) — the in-store points program used at the POS: earn rate, redeem value, minimum redeemable points and the purchase amount that auto-enrols a customer. See Membership Points for how it behaves at the counter.
Tip: Always set an end date so a promo does not run forever by accident.


Membership Points at the Counter
Membership is the in-store loyalty program: a customer joins a tier, earns points on what they buy, and spends those points as a discount on a later sale — all at the till.
- Tiers (Membership → Settings) — set the earn rate, the minimum purchase that qualifies, and how much a point is worth when redeemed.
- Members — join a customer at the counter; their point ledger shows every earn and redeem with the sale that caused it.
- Redeem at the till — the cashier applies points to the open sale, in full or partially, and the discount is split across the lines so returns refund correctly.
- Accounting — issued points are carried as a liability and released when they are spent, so profit is never overstated.
Points are earned and spent in the shop. There is no online wallet or affiliate program in this edition — those belong to the eCommerce product.

Accounting
Sellino POS includes a real double-entry accounting system. Sales, purchases, returns, expenses, cash movements and payroll post journal entries automatically against your Chart of Accounts (COA) — you do not book anything twice.
- Accounts & Banks — set up your COA, cash-in-hand, bank and mobile-money (MFS) accounts. Each counter gets its own cash account, which is why a drawer can be reconciled at all.
- Expenses, Transfers & Owner Money — record expenses, move money between accounts, and handle owner draw or investment.
- Journals, Transactions & Reconciliation — every journal entry, the transaction ledger, and bank reconciliation against an imported statement.
- Financial statements — Trial Balance, Income Statement (Profit & Loss) and Balance Sheet, built straight from the general ledger for any date range — and filterable per branch.
- Cost of goods sold — posted from the inventory costing layer, so gross profit is real cost, not an estimate.
- Stock adjustments post journals — an IN adjustment books an inventory gain, an OUT adjustment a loss, both valued at cost.
- Membership points are a liability — points you issue are carried until they are spent, so profit is not overstated by a discount you still owe.
Reference: see docs/wiki/ in the source for the journal mapping of each module, including returns and payroll.



HR & Payroll
Manage your staff from the same panel (HumanResource module).
- Employees & Structure — staff records, departments and designations.
- Attendance & Leave — daily attendance and leave requests/approvals.
- Payroll — monthly payroll generation, posted to accounting automatically. Loans and advances given to staff are tracked and recovered from payroll automatically, each with its own journal.
- Employee Loans — create a loan (status Pending, terms still editable), then Approve & Disburse from a cash/bank account to make it Active. Repayment happens automatically as a monthly installment inside payroll, or manually as an off-payroll cash repayment; when fully repaid it becomes Paid. Every step posts its journal to Accounting (employee-loan receivable account).
- Salary Advances — a one-shot advance disbursed from cash/bank and recovered in full from the salary of the month you choose; the payroll run deducts it and marks it Deducted. Journaled the same way on its own receivable account.
Good to know: only disbursed (Active) loans and advances are picked up by payroll — a pending request never touches anyone's salary. Cancelling an active, un-recovered loan/advance reverses its journal cleanly.



Reports
Decision-ready reports across the business, most exportable.
- Sales Reports — sales summary, by product, by category, by customer, profit and more.
- Inventory Reports — stock value, low-stock, movement, expiry and damage.
- Accounting & Cash Reports — trial balance, profit & loss, balance sheet, cash flow, day book and account ledgers.



Media Library & Picker
All uploaded images and videos live in one Media Library. Every image field in the panel — products, sliders, widgets, blogs, brands, categories — opens the same media picker, so you upload once and reuse everywhere.
- Browse & search — grid view with type filter and search over file name, title and alt text.
- Upload — single or multiple files, drag-and-drop. An identical file (same checksum) reuses the existing entry instead of storing a second copy.
- Edit details — rename, set title and alt text (good for SEO and accessibility).
- Usage — every file shows a used in N place(s) count, and you can list exactly where it is attached.
- Safe delete — a file still in use cannot be deleted; remove it from those places first.
- Automatic sizes — each upload is resized into named presets (thumbnail / medium / large) so lists and the app serve the right size.
- Staff see the shop's one media library; who may upload or delete is a permission.
Videos have their own size cap — set it in settings (media_video_max_mb, default 100 MB).
Website Pages (Privacy, Terms & Custom Pages)
Static content lives under Website → Pages — each page has a title, a slug and rich-text content, and is served on the site at its own URL.
- Legal pages ship ready — Privacy Policy, Terms & Conditions and Return & Refund Policy come with placeholder text. Review and rewrite them before launch — store review teams read them.
- The apps read the same pages — the POS app's sign-in screen links Privacy and Terms straight from here (unauthenticated, as app stores require), so one edit updates web and app together.
- Custom pages — add any number of extra pages (About, Delivery info…); each is served at its slug automatically.
- Widgets & Page Builder — the website's building blocks under Website → Widgets and Website → Page Builder, for installs that run a customer-facing site.
- Page create/edit/delete are individual permissions, like every other module.
Administration
- Users & Roles — role-based access control. Create roles with Read/Create/Update/Delete permissions per module, then assign staff to roles.
- Languages — add languages (with LTR/RTL), set the default, and translate phrases per module. Four packs ship ready: English, Bengali, Arabic and Hebrew (the last two RTL). The same translations feed the admin panel and the POS app through the API — translate once, everywhere updates. English is the fallback and cannot be deleted.
- Activity & Login Logs — audit trail of admin actions and login history.



Settings
- General — store name, contact, currency, timezone, date/time format, pagination and branding (logo/favicon).
- Appearance & Colors — primary/secondary colors, fonts and button shapes.
- Mail — standard SMTP, or the Gmail API transport (client ID, client secret, refresh token, from-name/address) when your host blocks SMTP ports 25/465/587 — common on cloud VPS providers. A Test mail button confirms either one.
- SMS / Push — SMS gateway, and push notifications used by the mobile apps.
- Media & Themes — see Media Library and Web / App Theme.
- Security — reCAPTCHA & API key; OTP channels & social login; backups.
- Payment Gateways — enable and key your gateways: SSLCommerz, bKash, Nagad, EPS for local payments and Stripe / PayPal for international cards — see Stripe, PayPal & Currency Rates. Use live keys over HTTPS.
- SEO, Menus, Login — meta/SEO defaults, navigation menus, and the admin login slug.
- Storage — keep uploads on local disk or point them at an S3-compatible bucket (see below).
- Preference Settings — feature switches for the modules you use.
Payment keys: test keys only process test transactions. Switch to live keys on an HTTPS domain before going live.


Web Theme / App Theme
Two theme pages style what your customers see — separate from the admin panel's own look (that is Dashboard Styles):
- Settings → Web Theme — colors and styling for the customer-facing website, on installs that run one.
- Settings → App Theme — how the mobile apps look, delivered live through the settings API: change a color here and the apps restyle on their next launch, no rebuild, no store update.
The App Theme page controls:
- Brand colors — primary/secondary body, text colors and the accent.
- Corner radii — per component: cards, buttons, inputs, chips, sheets, images, badges.
- Screen styles — pick a variant per screen (home, cart, product details, checkout, account) and per section (deals slider, category list, brand list, promo strip), with on/off toggles.
- Preset styles — start from a preset (e.g. classic / modern) and override its tokens.
Stripe, PayPal & Currency Rates
Local gateways (SSLCommerz, bKash, Nagad, EPS) charge in your store currency. Stripe and PayPal serve international cards — and card networks cannot charge BDT, so the system converts for you:
- The bill amount is converted from the store currency to the gateway currency (default USD, configurable) using your FX rates, and the customer's card is charged that amount.
- The charged amount and the exchange rate used are stored on the payment, so accounting always knows both sides of the conversion.
- Keys live in Settings → Payment Gateways — one on/off switch and key pair per gateway. Test keys only process test transactions; go live with live keys over HTTPS.
Currency Rates (Settings → Currency Rates)
- Per-currency exchange rates with your store currency as base — edit them by hand, or hit Fetch rates to pull live rates.
- Daily auto-update — a toggle that lets the scheduler run
currency:update-ratesnightly, keeping rates fresh without anyone touching the page.
Security (2FA, reCAPTCHA, API Key)
- Two-step verification — when enabled, admin login asks for a one-time code emailed to the user after the password step.
- Google reCAPTCHA (Settings → reCAPTCHA) — on/off switch plus site key and secret key. Protects the login form from bots. Get free keys from Google reCAPTCHA admin.
- Admin login slug — the admin panel URL is randomized, see Login & Security.
App API Key (Settings → API Security)
A shared key your own clients send as the X-App-Key header on every API request. Requests without it are rejected with 401, so random scripts hitting your API are turned away. The page shows a Protection active / disabled badge, lets you show / copy the key, tells you when it was last generated, and has a built-in How it works panel.
- Empty = off (fail-open) — with no key configured nothing is enforced, so an install that never opens this page keeps working.
- The blade website is exempt — browser requests from your own domain skip the check (a browser cannot hold a secret header); they are covered by session & CORS. Only non-browser callers need the key.
- Source — the key set here wins;
APP_API_KEYin.envis the fallback. A badge tells you which one is active (Managed here / From .env).
Where the key goes
| Client | Where you paste it |
|---|---|
| POS App | lib/core/env/prod_env.dart (and dev_env.dart for the dev key) → rebuild |
Regenerating breaks every installed app. The key is compiled into the POS app at build time — the moment you generate a new one, every app already on a phone gets 401 Unauthorized and stays broken until a new version carrying the new key is published to the stores and the user updates. Only regenerate if the key has leaked, or before your first release. The panel makes you tick a confirmation box first.
Scope: this is a casual outer filter, not strong security — a key shipped inside a mobile app can be extracted. Rate limiting is the real protection; the key removes low-effort noise and gives you a rotation kill-switch.
OTP & Social Login
OTP channels (Settings → Preference)
- Email OTP and Mobile OTP have separate on/off switches — run either, both, or neither. Codes are 4 digits.
- Used for customer signup / login verification and for verifying a changed email or phone number.
- Mobile OTP needs an SMS gateway configured in Settings → SMS; email OTP needs working mail.
- One identifier field — login, signup, OTP and password reset all take a single box where the customer types either an email or a phone number. A phone is stored in one canonical international form, so
01811843300,8801811843300and+8801811843300are the same person — no duplicate accounts, and no OTP sent to a number the customer cannot verify. Numbers typed without a country code are completed with your store's country. - Other switches on the same page: Order-placed email, Recently viewed, order-code and member-ID prefixes, and the barcode label defaults.
Social login (Settings → Social Login)
- Google and Facebook sign-in, each with its own on/off switch, client ID and client secret.
- Both off → only email/phone login is offered. Accounts created socially merge with an existing account on the same email.
Real-time & Chat (Reverb)
Live features — customer ↔ staff chat and live panel updates — ride on Laravel Reverb, a websocket server that ships with the item. It is fully optional: with the daemon off, everything else keeps working.
Settings → Realtime
- App id / key / secret — the credentials clients connect with; defaults come from
.env(REVERB_*), and values saved here win. - Host, port & scheme — what browsers and apps connect to (production:
https/wss on 443 behind your reverse proxy). - Server host & port — what the daemon itself binds to on the box.
Running the daemon
- Start it with
php artisan reverb:startand keep it alive with Supervisor / systemd — the same pattern as the queue worker. - The POS app does not use the websocket (it polls the API), so no app-side Reverb setting exists.
Push Notifications (Firebase)
Sellino POS sends push notifications to the POS app through Firebase Cloud Messaging (FCM) — for low stock, stock transfer requests, return requests and announcements to your staff. This is the server half, configured in Settings → Push.
- Create a free Firebase project and download its service-account JSON.
- On the Push page, tick Enable push notifications, upload the JSON (the Project ID auto-fills), and hit Test connection to confirm.
- Devices register automatically when a user signs in to an app, so notifications reach the right person on all their devices.
- Push campaigns — compose a promotional push, target an audience and send it now or schedule it; due campaigns are fanned out by the scheduler.
- Leave push disabled and everything else keeps working — it is fully optional.
Full procedure: the mobile apps also need their own Firebase config files, and iOS needs an APNs Auth Key. Because those steps are shared by the backend and both apps, they are documented once in Common Setup → Push Notifications (Firebase).
Note: Firebase is a Google service. A project is free to create, but any usage beyond its free tier is billed by Google and is not included in this item.
Storage (Local or S3-Compatible)
By default all uploaded media (product images, banners, attachments) is stored on your server's local disk — nothing to configure. When you outgrow that, switch to any S3-compatible bucket (AWS S3, DigitalOcean Spaces, Wasabi, MinIO, etc.) from Settings → Storage.
- Enter your bucket credentials on the Storage page and choose it as the active disk.
- Storage is per-file aware — files already saved locally keep serving from local, while new uploads go to the bucket, so switching over is safe and non-destructive.
- Great for scaling media off the app server and putting files behind a CDN.
Tip: Local disk is perfect to launch with. Move to a bucket only when your media volume or traffic calls for it.
Backups (Database & Files)
Two separate backup pages, both uploading to your own Google Drive: Settings → Database Backup and Settings → File Backup.
- Database Backup — dumps the MySQL database. Fields: enable switch, mysqldump path (leave default unless your host puts it elsewhere), and the Google Drive credentials.
- File Backup — archives the
public/directory (uploaded media). Adds a chunk size (MB) field so large archives upload in resumable parts. - Google Drive credentials — client ID, client secret, refresh token and target folder ID, from your own Google Cloud project. Drive storage cost is yours and not included.
- Run them —
php artisan backup:databaseandphp artisan backup:files. Automate with the scheduler cron entry.
Always take a fresh database and file backup before updating to a new version.
Troubleshooting
Most post-install issues come from server configuration, permissions or the .env file. Work through these before contacting support.
1. Blank page or HTTP 500 after install
- Open
storage/logs/laravel.log— it names the exact error. - Confirm
APP_KEYis set; if empty, runphp artisan key:generate. - Make sure the web root points to the
public/folder, not the project root.
2. "Permission denied" / cannot write to storage
chmod -R 775 storage bootstrap/cache; on cPanel set the folder owner to your hosting user.
3. Database connection error
- Verify
DB_HOST(usuallylocalhost),DB_DATABASE,DB_USERNAME,DB_PASSWORD. - Confirm the user is attached to the database with full privileges.
4. Changes in .env not taking effect
- After editing
.env, runphp artisan optimize:clearto reload config and routes.
5. Changes not showing / old data cached
- Clear caches:
php artisan optimize:clear.
6. POS says "no open register" and refuses to sell
- A sale needs a counter in the active branch and an open cash register on it. Create the counter, then open a register with its starting float.
- If the counter belongs to another branch, switch branch on the POS bar — a till is only usable in its own branch.
7. Emails / OTP not sending
- Complete Settings → Mail with valid SMTP host, port, encryption, username and password, then send a test. Many hosts block port 25 — use 465 (SSL) or 587 (TLS).
8. Branch screens are empty after an upgrade
- Run
php artisan branches:backfillonce. It creates a "Main Branch" and attaches your existing warehouses, counters and past sales to it. - The branch switcher hides itself when the operator may work in only one branch — that is expected, not a bug.
9. The POS app cannot reach the server
- Check
lib/core/env/prod_env.dart— the base URL and the app key must both match your server (Settings → API Security). A wrong key returns 401 before any screen loads. - On a device,
localhostis the phone itself — use the server's real address.
FAQ
Q: What's included in the purchase?
The Laravel web backend (admin panel + POS terminal + API), the Flutter POS App source, the database, and this documentation.
Q: What are the server requirements?
PHP 8.3+, Laravel 12.x, MySQL 8.0+, Composer, Node.js & NPM, with the standard PHP extensions enabled.
Q: Does it have an online store?
No — this is the POS edition. It is a shop system for counter selling, stock and accounts. If you also need a customer-facing webshop and a vendor marketplace, that is our separate eCommerce item.
Q: Can I run more than one shop from one install?
Yes. Create a branch per outlet, give each its own warehouses and counters, and assign staff to them. Reports and Profit & Loss can be read per branch or for the whole chain.
Q: Does the POS app need the web panel?
It needs the same server: the app talks to the API (/api/v10/staff/*) that runs alongside the panel. Both work on the same data, so a sale made on the phone shows on the panel immediately.
Q: Does the app work offline?
No. A sale is created on the server so stock and cash stay correct across every till at once, which needs a connection. Plan for a stable network at the counter.
Q: Can I change logo, colors and texts?
Yes — branding, theme and every phrase are managed from the admin panel, no rebuild required. The receipt logo and footer are set under POS settings.
Q: Does it support multiple languages?
Yes, with LTR/RTL support. Add languages and translate phrases under Administration → Languages.
Q: How does the customer pay?
At the counter: cash, bank, mobile money (MFS) or any mix of them on one bill, with change calculated for you. Online card gateways are not part of this edition — nobody checks out on a website here.
Q: What hardware do I need?
Nothing mandatory. A thermal ESC/POS receipt printer, a USB or Bluetooth barcode scanner and a cash drawer are all supported and are what most shops use. Hardware cost is not included.
Q: How do I update to a new version?
Back up your database and .env, replace the source files (keep .env and storage/), then run php artisan migrate and php artisan optimize:clear.
Q: I still need help — what should I do?
Check Troubleshooting and storage/logs/laravel.log first, then contact us via our profile with the exact error message.
Third-Party Services & Costs
This item is a software product only. Third-party services and their costs are not included in the item price — including web hosting and domain, payment gateway accounts (e.g. SSLCommerz, bKash), SMS gateway, push-notification services (Firebase / FCM), optional cloud storage (S3-compatible buckets), the Anthropic (Claude) API or any OpenAI-compatible AI provider used for AI auto-reply, Google services (reCAPTCHA keys, Google Drive for backups, Google social login), any external vision API used for search-by-image, Meta services (WhatsApp Cloud API, Facebook Messenger, Facebook Pixel), and Apple/Google developer accounts for publishing the mobile apps. You arrange and pay for these separately, and generate your own application key and credentials during setup.
Changelog
Version 1.0.0
- Initial release of Sellino POS — the point-of-sale edition of the Sellino platform (
SITE_MODE=pos-inventory). - POS terminal — search or scan, cart, line and bill discounts, coupons, membership redemption, multi-payment (cash, bank, MFS or mixed) with change, draft sales and thermal or PDF receipts.
- Counters, cash registers, cash pickup and petty expenses — open a shift with a float, close it against counted cash with a variance reason.
- Multi-branch — branches group warehouses, counters and staff; per-user branch visibility (all / assigned / own / self), a branch switcher at the till, and branch-wise Profit & Loss, Income Statement, Trial Balance and Balance Sheet.
- Catalog — products with category, brand, unit, tax, attributes and variations, plus barcode generation and label printing.
- Purchase & stock — purchase orders, suppliers and dues, multi-warehouse stock with racks, lots and layers, and full movement history.
- Stock operations — adjustment, damage, inter-warehouse and inter-branch transfer with request/approve/receive, and supplier returns.
- Inventory costing — FIFO or weighted average, with cost of goods posted on every sale.
- Returns, replacements and refunds — cash, bank or store credit, with stock and journals corrected in proportion.
- Double-entry accounting — Chart of Accounts, journals, banks and MFS accounts, deposits, fund transfers, owner money, expenses and bank reconciliation.
- Coupons, flash sales, campaigns and membership points at the counter, carried as a liability until redeemed.
- HR & Payroll — employees, departments, attendance, salary generation, loans and advances, all journaled.
- Reports — daily sales, sales summary, product and customer sales, cash register, cash pickup, stock, stock valuation, low stock, expiry, purchase summary, supplier dues, expenses and the full accounting set.
- Administration — users, roles and granular permissions, activity and login logs, multi-language with RTL/LTR.
- POS App (Flutter) — Android and iOS counter app: terminal, sales, cash, customers and loyalty, stock and reports, with the same branch switcher, thermal printing and barcode scanning.
- Push notifications (Firebase) and local or S3-compatible media storage.