# WBMCZ — deploy notes · 06 Sep 2026 (second pass)
## One entry per thing, access decides what shows, and a dashboard of real figures

No database change of any kind. Three files.

    admin/includes/sidebar.php     the menu, de-duplicated and access-aware
    admin/index.php                the dashboard, rebuilt
    includes/pipeline.php          the Product Requests desk now opens the full listing

Upload `includes/` first, then `admin/`.

---

## 1 · THE MENU HAD EVERYTHING TWICE

Service Management listed all eleven categories, then listed them **again** —
"Government Portals, Important Tools, Service Booking…" straight through, twice.
One run was the catalogue, the other was what sellers had submitted, but the menu
never said so, so it read as a bug. It was mine, from this morning.

Now: **eleven lines, one per category**, and that is the list.

What the second run was for has moved to where it belongs. Seller submissions are
a queue waiting on a decision, exactly like KYC and seller requests, so they sit
on the **Activity & Task** board with the rest of them. The Product Requests desk
gained an **"Open the full listing →"** link on every row, which opens that
category's review screen — the same screen, reached from the queue rather than
from a second menu.

### Also gone from the menu

| Was | Where it is now |
|---|---|
| Bulk Import (CSV) | the **Bulk upload** button inside each category |
| Sub Categories | the **Sub categories** button inside each category |
| All Products | dropped — the eleven categories are the list |
| KYC Questions | moved to **User Management**, next to KYC Pending |
| Subscribers (Subscription Management) | it was `users_pro.php` — the same page as **Pro User** |
| Visits & Collections ×3 | one line to `order_manage.php`; its three tabs are inside it, and deciding on them is done from the desks |
| SMS & OTP | it was listed **twice** in Website Settings. Once. |
| Customer Console | dropped — `users.php` is the screen the six split lists replaced. Say the word if you still want it. |

Service Management is now: eleven categories, then **Add / Edit Categories** —
the one screen that belongs to no single category and so has nowhere else to go.

---

## 2 · ACTIVITY & TASK IS ONE LINE

It was a folder of four: All Tasks, KYC Requests, Seller Requests, Office. All
four opened the same page on a different tab, so the tabs existed twice — once
across the top of the page, once down the side.

One link now. The page keeps every tab it had, and opens on whichever one the
person actually holds.

---

## 3 · THE SIDEBAR NOW OBEYS THE ACCESS YOU GRANT

Before, the menu was filtered by six coarse permissions — `manage_users`,
`manage_services` and four more. Meanwhile the pages themselves were checking the
fine-grained keys. So an employee given only the Free Users list still saw every
User Management line, clicked one, and hit *Access denied*.

The menu now reads the same keys the pages do. Two consequences:

* **A line you cannot open is not drawn**, and a folder left with nothing in it
  disappears rather than sitting there empty. So do the headings above them.
* **Nobody loses anything.** A role saved before the fine-grained system existed
  is expanded into every key of the modules it already held — so a role that was
  given "manage_services" still opens all eleven categories. What is new is the
  ability to give **less**: a role that ticks only *Open the Shopping page* now
  sees that one line and nothing else.

Super admin and any role holding `all` skip the filter entirely and see the whole
menu, as before.

34 permission keys are named in the menu; all 34 were checked against the
registry, because a key with a typo in it does not error — the line just quietly
never appears.

---

## 4 · THE DASHBOARD

The old one opened with four tiles and then a **Platform Modules** grid — Users,
Sellers, Staff List, Roles, Services, Orders, Transactions, Settings — every one
of which was a second copy of a sidebar entry. A menu inside a menu. It is gone.

What is there instead, in the order the office needs it:

**Waiting for somebody** — KYC to check · Seller requests · Product requests ·
Visits to make · Cash to verify · Open tickets. Each links straight to its desk on
the Activity & Task board, so a number leads to the work rather than to a screen
that shows the same number again.

**Money** — Total income · Expenses · Company income · Subscription income, then
This month (against last month) · Still to collect · Advances taken · Given to
subscribers.

**Orders** — Total (with this month and today) · Completed (with the percentage) ·
In progress · Cancelled or failed.

**People** — Members (free / pro / blocked) · Sellers active out of total ·
Joined by referral · Staff accounts. Then, when wallet access is granted: Held in
wallets · Bonus wallets · Collected by sellers · Sellers still holding.

**Where the money comes from** — completed orders by service, biggest first.
**Latest orders** — the last six. **Unread for you** — your own notifications.

### Every figure says what it counted

"Income" means four different things depending on who is asking, so each tile
carries a line underneath saying exactly what went into it. In particular:

* **Total income** — what customers paid on orders that reached *Completed*.
  Cancelled and failed orders are in no money figure anywhere on the page.
* **Expenses** — what leaves the company: the seller's cut, the referral and the
  staff share. Two places record these — the share ledger and the payout column
  on the order — and both are read, with the breakdown printed under the tile so
  a double count would be visible rather than buried.
* **Company income** — total income less those expenses.
* **Held in wallets** is labelled *members' money, not the company's*, because it
  is a liability and had been getting read as income.

### What the figures say today

    members                 418  (417 free, 1 pro)
    sellers                 9 active of 778
    staff accounts          5
    joined by referral      1
    orders                  54 — 28 completed, 4 cancelled/failed
    total income            ₹9,622.00
    expenses                ₹0.00
    company income          ₹9,622.00
    subscription income     ₹0.00
    held in wallets         ₹522.00
    open tickets            2

Two of those deserve a second look:

> **Expenses are ₹0.00 and so every rupee shows as company income.** That is
> honest — the `product_share_ledger` is empty and `orders.seller_payout` is zero
> on every row, so nothing has been recorded as leaving. The tile says so in
> words rather than pretending to a profit figure. It corrects itself the moment
> shares start being written.

> **778 sellers, 9 of them switched on.** The same figure as before; worth
> knowing what the other 769 are.

### The blocks are gated too

`dashboard.col.earning`, `.orders`, `.users`, `.wallet`, `.recent` — each block is
behind its own key. An employee given orders but not money sees the order block
and no empty money row where the numbers used to be. An account that can open the
dashboard but holds none of the blocks gets a short line saying so, not a blank
page.

---

## 5 · CHECKED

* all three files pass `php -l`
* 43 admin pages load with no fatal, no warning and no notice
* all 34 menu permission keys exist in the registry
* the menu source names the categories once, `wb_service_children` is gone, and
  "SMS & OTP" appears exactly once
* every dashboard figure was run as a separate query and matched

Still needs your eyes, because it is behind the sign-in: the menu with a real
session, and the dashboard with your own account.

---

## 6 · WHAT I HAVE NOT TOUCHED YET

* **Employee sidebar in practice.** The filtering is in and correct by the keys,
  but it has only been proved key by key — worth making one employee account with
  a narrow role and looking at what they get.
* **`users.php` (Customer Console)** is off the menu but still on disk.
* **Wallet and Payout desks** read `withdrawal_requests`, which does not exist in
  this database, so they always show 0. Nothing errors.
* The OTP text still ends with *"sent from GuestRAR"* until your own DLT header
  and templates are registered.
