# WBMCZ — Visit selling, advance payment, cart & seller dues

Everything below is Phase 1: buying a product and following the order through.

---

## 1. Run this first

**`ordmigration.php`** — upload it to the site root, open
`https://wbmcz.online/ordmigration.php` in a browser once, wait for the green
"Migration completed successfully", then **delete the file from the server**.

It is safe to run twice — every step checks whether it is already done.

### What it changes in the database

**Columns added to `seller_services` and `agency_services`**

| Column | Type | What it is for |
|---|---|---|
| `fulfilment` | VARCHAR(20) NULL | `visit`, `online`, or NULL = follow the category |
| `advance_mode` | VARCHAR(20) NULL | `company` / `fixed` / `percent`, or NULL = follow the category |
| `advance_amount` | DECIMAL(10,2) | used when the mode is `fixed` |
| `advance_percent` | DECIMAL(5,2) | used when the mode is `percent` |
| `allow_cart` | TINYINT(1) | can this go in the basket |
| `allow_code` | TINYINT(1) | can it be paid against a payment code |
| `visit_note` | VARCHAR(255) | what the customer is told about the visit |

**Same four settings added to `service_categories`** (`fulfilment`,
`advance_mode`, `advance_amount`, `advance_percent`) — these are the
category-wide default.

**New tables**

| Table | What it holds |
|---|---|
| `carts` | one row per product in a customer's basket |
| `order_items` | one row per product inside an order |
| `order_timeline` | every step an order went through, with who and when |
| `seller_collections` | what a seller says they took, and whether the office verified it |
| `seller_settlements` | money handed over between a seller and the company |

**28 columns added to `orders`** — `order_code`, `fulfilment`, `customer_type`,
`payment_mode`, `mrp`, `base_amount`, `discount_amount`, `paid_amount`,
`wallet_used`, `gateway_used`, `due_amount`, `collected_amount`,
`collected_mode`, `collected_at`, `collected_by`, `seller_payout`,
`company_profit`, `payment_code`, `payment_code_status`, `visit_status`,
`visit_at`, `stage`, `customer_name`, `customer_mobile`, `address`, `note`,
`item_count`, `updated_at`.

**Existing orders are not disturbed.** They are given an order code
(`WBMCZ-yymmdd-000123`), marked paid in full with nothing outstanding, given a
stage that matches their status, and one `order_items` row each.

---

## 2. New files

| File | What it is |
|---|---|
| `includes/purchase.php` | The engine. Pricing, the basket, placing orders, collections, seller dues, settlements. Nothing else contains money logic. |
| `product.php` | The product page — price for both kinds of customer, how it is delivered, the booking split, wallet, Add to Cart and Buy Now. |
| `cart.php` | The basket, each line priced for that buyer. |
| `checkout.php` | Three steps: details → payment → confirm. Handles the whole cart or one product (`checkout.php?id=123`). |
| `order.php` | Order tracking — the seven steps, full history, and a way to clear the balance online. |
| `admin/order_manage.php` | The office screen: orders with money outstanding, collections to verify, seller dues. |
| `seller/collections.php` | The seller screen: who to visit, record what was taken, and their own dues. |

## 3. Modified files

| File | What changed |
|---|---|
| `includes/shares.php` | Added `shares_company_earned()` and used it in `shares_distribute()`. **This fixes a real bug**: the company's profit was being reduced by the subscriber discount a second time, even for buyers who never got that discount. See §6. |
| `includes/theme.php` | Cart icon with a live count in the header; "My Cart" in the customer menu; "Visits & Money" in the seller menu. |
| `orders.php` | Shows the order code, what is paid and what is still owed, the real stage, and a **Track** button. |
| `category.php` | Visit products show "₹x to book · ₹y at the visit" and a **Book Now** button that opens the product page; every product gets a **Details** link. Online products still use the quick buy popup exactly as before. |
| `admin/product_management.php` | "How this product sells" section in the edit modal, and a Visit badge in the list. Also covers `admin/product_management_gov.php`, which includes this file. |
| `admin/services.php` | Category-level default, with a tick-box to push it down to every product in that category. |
| `admin/includes/sidebar.php` | Order Management now opens Visits & Collections, Verify Collections and Seller Dues. |
| `seller/services.php` | The same "how it is delivered" choice on the seller's own product form. |

---

## 4. How the money works

Take a product at **₹2,800**, seller's share **₹2,200**, company **₹600**.

- The booking amount defaults to **the company's own share — ₹600**.
- The customer pays ₹600 on the site and **₹2,200 at the visit**.
- That ₹2,200 is exactly what the seller was going to earn, so **nothing has to
  be handed over afterwards**.

Set the advance to anything else and the arithmetic still holds — it just means
money has to move between the seller and the office afterwards, and the Seller
Dues screen keeps the running total.

**Cash a seller holds is company money, not their earnings.** Their earnings
reach their wallet the usual way, through the share release when the order
completes. The two never mix.

```
holding = verified cash and seller-side online collections
        − what they have handed in
        + what the company has paid out to them
```

Three ways money can arrive at a visit:

| Mode | Counts against the seller's dues? |
|---|---|
| Cash | Yes — notes in their pocket |
| Online to seller (their own UPI / bank) | Yes — still theirs to hand over |
| Paid to company (our account or the gateway) | No — it never sat with them |

---

## 5. Wallet

Exactly as asked: a ₹500 service against a ₹200 wallet takes ₹200 from the
wallet and asks for ₹300. A ₹500 wallet pays for it outright and no card is
needed. The virtual wallet is spent before the main one, as everywhere else on
the site.

---

## 6. One bug fixed along the way

`shares_distribute()` worked out the company's share as
*price − seller − subscriber discount − referral − staff*, using the amount the
customer actually paid as the base.

For a **regular** customer no discount was ever given, so deducting it lost
₹100 of profit. For a **subscriber** the discount had already come off the
price they paid, so deducting it again lost the same ₹100 twice over.

On the example above the company was being credited ₹500 instead of ₹600 for a
regular sale, and ₹400 instead of ₹500 for a member sale.

The fix (`shares_company_earned()`) works the company's share out as whatever
the seller, the referrer and the staff do not take, on money that was really
taken. The admin breakdown table is unchanged — it still shows how the regular
price divides into all five parts, which is a different question.

Orders placed **before** the fix keep the figures they were written with; only
new sales are affected.

---

## 7. Worth knowing

- **Category first, product second.** A product left on "As the category"
  follows its category, so switching a whole category to visit selling reaches
  every product under it. A product deliberately set to one or the other keeps
  its own answer, and the category switch leaves it alone. There is also a
  tick-box on the category form to force the change onto every product.
- **A collection is a claim until the office verifies it.** Recording one does
  not move the order or the money by itself.
- Verifying is safe to repeat — the order's figures are recomputed from the
  verified collections each time, never added to a running total, so a double
  click or a rejection later both land on the right answer.
- **An order completes only when nothing is owed.** The Complete button refuses
  while there is a balance, and the seller's earning is released at that moment.
- Cancelling refunds what was paid online into the customer's wallet. Cash a
  seller already took is deliberately left alone — that is a conversation, not
  a button.
- Prices are never read from the form. Everything is recalculated on the server
  from the product row when the order is placed.
- Razorpay payments are verified against Razorpay's API before a rupee is
  recorded, the same way `category.php` has always done it.

---

## 8. Upload order

1. `ordmigration.php` → run it → delete it
2. `includes/purchase.php`, `includes/shares.php`, `includes/theme.php`
3. `product.php`, `cart.php`, `checkout.php`, `order.php`, `orders.php`, `category.php`
4. `admin/order_manage.php`, `admin/product_management.php`, `admin/services.php`, `admin/includes/sidebar.php`
5. `seller/collections.php`, `seller/services.php`
