# Thinkrax Central

The back office for every Thinkrax SaaS product. Staff sign in here to verify
payments, activate subscriptions, manage shops and set prices.

Built on Laravel 13 + Livewire 4 + Tailwind 4. Intended to run on its own
subdomain, e.g. `admin.thinkrax.com`.

> This is one half of a pair. The other half — `thinkrax-pos` — is the product
> customers actually use. See `INSTALL.md` at the root of the delivery for how
> the two are wired together.

---

## Why it exists

Pakistani SaaS collections happen over Easypaisa, JazzCash and IBFT. None of
those gives a server-to-server callback, so there is nothing to trust
automatically. The honest design is the one this panel implements:

1. A shop pays and uploads the screenshot inside the product.
2. The payment lands here as **pending**, and the shop waits.
3. A human compares it to the bank or wallet statement.
4. Approve → the invoice is credited and the subscription goes live the same
   second. Reject → the shop gets a written reason it can act on.

Everything else in the panel exists to support that decision or to clean up
after it.

---

## What it does

**Verification queue** — one payment at a time with everything needed to judge
it on one screen: the screenshot, what the shop claims, what they owe, and two
warnings the reviewer would otherwise have to catch by memory:

- **Duplicate transaction ID** — the commonest fraud on manual rails is sending
  one screenshot twice. The panel looks for it.
- **Short payment** — approving credits the invoice but deliberately does *not*
  start the term until the invoice is settled in full.

After each decision it jumps straight to the next waiting payment, because
verification is done in batches and hunting for the next row is how backlogs
form.

**Shops** — every tenant across every product: full history, ledger of
subscriptions, invoices and payments, and the manual overrides:

| Override | What it does |
|---|---|
| Extend / shorten term | Adds days to whichever is later, today or the current end date |
| Change plan | Rewrites the entitlement snapshot; dates and invoices untouched |
| Grant a paid term | Records money collected outside the app, with a paid invoice |
| Cancel | Stops renewal; by default the shop keeps the days it paid for |
| Suspend / reinstate | Cuts access off, without touching the subscription dates |

Every one of them demands a written reason, and every one is logged.

**Catalogue** — products, plans and receiving accounts. A plan is a price, a set
of feature keys and a set of numeric caps; the keys come from
`config/thinkrax.php`, which mirrors what each product gates on, so a plan can
be composed here without opening the product's codebase.

**Reports** — revenue by month, method, plan and account; growth, honest trial
conversion (only trials that have actually ended are in the denominator) and a
win-back list of lapsed shops.

**System** — announcements pushed into every shop's dashboard, staff accounts,
a full audit trail, and panel settings.

---

## Roles

| Role | Can |
|---|---|
| Support | Read everything, change nothing |
| Accountant | Verify and reject payments |
| Admin | The above, plus shops, subscriptions, plans and accounts |
| Super Admin | Everything, including staff accounts |

There is **no public signup**. Accounts are created by a super admin, and a
deactivated account is signed out on its next request — a session outlives a
deactivation, and this panel can give subscriptions away.

---

## Install

```bash
composer install
cp .env.example .env
php artisan key:generate
php artisan storage:link

# Edit .env — DB_* points at the SHARED SaaS database. This project owns it.

php artisan migrate
php artisan db:seed
npm install && npm run build
```

Seeding creates a super admin (`admin@thinkrax.com` / `password` — change it
immediately), the Thinkrax POS product row, four starter plans, and three
**inactive** placeholder receiving accounts. They are inactive on purpose: put
your real Easypaisa, JazzCash and bank details in under *Receiving Accounts*
before switching them on, or shops will send money into a fictional wallet.

Then add one cron entry:

```
* * * * * cd /path/to/thinkrax-billing && php artisan schedule:run >> /dev/null 2>&1
```

### Payment screenshots

Screenshots are written by the **product** applications, not by this panel.
Point the `proofs` disk at the same storage they write to:

```env
PROOFS_DISK_ROOT=/var/www/thinkrax-pos/storage/app/public
PROOFS_DISK_URL=https://app.thinkrax.com/storage
```

On separate servers, use a shared bucket and switch the `proofs` disk in
`config/filesystems.php` to `s3`.

### A demo panel

```bash
php artisan db:seed --class=DemoSeeder
```

Twelve shops with a year of history, plus four payments left in the queue —
including one short payment and one duplicated transaction ID, so the warnings
have something to warn about.

---

## Adding a second product

1. Add a block to `config/thinkrax.php` under `products`, keyed by the product's
   slug, listing its feature and limit keys.
2. Add the product under *Products*, with the same slug.
3. Create its plans.

Nothing else in this panel changes.

---

## Tests

```bash
php artisan test
```

Covered: payment verification (full, partial, rejection, reopen, superseding an
old subscription, audit trail), manual overrides, tenant suspension and
reinstatement, access-state derivation, entitlement snapshots, and route-level
authorisation for every role.

---

## Scheduled work

| Command | When | Why |
|---|---|---|
| `central:daily-digest` | 08:00 | One summary of the queue, renewals and signups |
| `central:queue-reminder` | Hourly, 09:00–21:00 | Escalates payments waiting over 4 hours |
| `central:prune-notifications` | Weekly | The feed is not the archive; the audit log is |

---

© Thinkrax Technologies. Proprietary. Internal use only.
