Files

128 lines
5.2 KiB
Markdown
Raw Permalink Normal View History

# Migration state — investigated before writing D0 / percent
Requested by the user before any new migration is written. All findings are from
**read-only** queries; nothing was reset and `_prisma_migrations` was not touched.
## The five questions
### 1. Is `20260917120000_customer_name_parts_and_percent` recorded as applied?
**Yes — but as a no-op.**
```
migration_name 20260917120000_customer_name_parts_and_percent
finished_at 2026-09-18T16:03:33.956Z
rolled_back_at null
applied_steps_count 0 <-- zero steps ran
```
`finished_at` is set and `rolled_back_at` is null, so **Prisma considers it
applied and will never re-run it**. `applied_steps_count = 0` says no SQL
statement was ever executed by it.
### 2. What is in its SQL file?
**Comments only — no executable statement.** The file is a placeholder that
explains itself: it says the columns were added "directly against the live DB"
and that it was recreated as an empty no-op so `prisma migrate status` would
stop erroring on a missing directory.
### 3. Does `schema.prisma` declare `firstName` / `lastName` / `productPercent`?
**No.** `grep` over `prisma/schema.prisma` finds none of the three. The
`Customer` model has `fullName` and nothing else name-related.
### 4. Do the columns exist in the database?
**No.** Querying `information_schema.columns` for `Customer` and those names
returns only `fullName`:
```
firstName absent
lastName absent
productPercent absent
makingChargeOffsetPercent absent
fullName present
```
**So the placeholder file's own comment is wrong.** It claims the columns "already
exist live"; they do not, at least not in this database (`gold_banking` on
localhost). Whatever database that comment described, it was not this one.
**Consequence for the runtime:** none, and this is the good news. Prisma Client
generates from `schema.prisma`, and the schema does not mention these fields
either. Schema and database agree — both lack the columns. There is **no drift
that could make Prisma Client throw at runtime**. The only thing that is wrong is
the placeholder's comment.
### 5. `prisma migrate status` (read-only)
```
9 migrations found in prisma/migrations
Following migration have not yet been applied:
20260922000000_customer_otp
```
Note on that line: the OTP table **does exist** — stage 2 created it with
`prisma db execute`, which runs SQL without writing a ledger row. So the schema
is correct but the ledger entry is missing, and `migrate deploy` would try to
run it again. The SQL is written with `CREATE TABLE IF NOT EXISTS`, the indexes
with `IF NOT EXISTS`, and the FK inside a `DO $$ ... EXCEPTION WHEN
duplicate_object` block, so a re-run is harmless. Still worth resolving cleanly —
see the recommendation.
### 6. Where did the file come from?
```
b80fa9b Redesign product detail page and fix icon/cart reactivity bugs
```
A single commit, and the message has nothing to do with migrations — the
placeholder was swept in as collateral to an unrelated frontend change.
---
## Recommendation
**The placeholder is recorded as applied, so per the user's rule it must not be
edited.** It stays exactly as it is.
1. **Leave `20260917120000_...` untouched.** Editing a migration Prisma has
recorded would make its checksum mismatch and break `migrate status` for
everyone. Its only sin is a misleading comment, and a follow-up migration
makes that harmless.
2. **Write the D0 and `percent` work as a new, additive migration** with a fresh
timestamp. It adds the columns the placeholder never added. Written to be
idempotent (`IF NOT EXISTS`) so it is safe on a database where someone *did*
apply the columns by hand.
3. **Resolve the OTP ledger entry** with
`npx prisma migrate resolve --applied 20260922000000_customer_otp`.
That writes the ledger row without running SQL, which is exactly right here
since the table already exists. **Needs the user's approval before running**,
as it writes to `_prisma_migrations`.
4. **Never** `migrate reset`, and never edit `_prisma_migrations` by hand.
---
## Naming: one field, not two
The user asked for a single final name. **`productPercent` is dropped;
`makingChargeOffsetPercent` is the name.**
Reason: the reference has **three unrelated things** all called `percent`, and a
vague name is how they got confused in the first place (the target currently
reads the wrong one — CUST-02):
| Reference `percent` | Where | What it is |
|---|---|---|
| `customers.percent` | `customer_add.php:32` | a **per-customer making-charge offset**, used only to shift catalogue filter bounds (`ApiMobileController.php:391-396,76-77`) |
| `ConfigStatic['percent']` | `AdminController.php:903,994` | the **wallet cashback rate**: `total_weight × percent/100` |
| `order_item.percent` | `MajorOrderController.php:220` | the **per-line making charge** on a wholesale order |
`productPercent` would read as "a percent belonging to a product", which is the
third meaning, not the first. `makingChargeOffsetPercent` says which of the
three it is. It is mapped back to the legacy key `percent` in `toRow()`, so the
admin panel's field name does not change.
`productPercent` is not created, so there is no duplicate field.