|
| 1 | +-- A car bought on finance, and the instalments it owes. |
| 2 | +-- |
| 3 | +-- EMI became an expense category in 015, which made the cost recordable. It |
| 4 | +-- did not make it automatic: the same figure had to be typed on the same day |
| 5 | +-- every month for the length of the loan, and the month it was forgotten is |
| 6 | +-- the month the books stop matching the bank. |
| 7 | +-- |
| 8 | +-- So the loan is described once -- what it costs, which day it falls, when it |
| 9 | +-- started and how many instalments there are -- and the expenses are written |
| 10 | +-- from it. |
| 11 | +CREATE TABLE IF NOT EXISTS vehicle_loans ( |
| 12 | + id INT UNSIGNED NOT NULL AUTO_INCREMENT, |
| 13 | + vehicle_id INT UNSIGNED NOT NULL, |
| 14 | + |
| 15 | + -- Written onto each expense as the vendor, so a generated row reads like a |
| 16 | + -- typed one: "paid to HDFC" rather than a blank where the payee goes. |
| 17 | + lender VARCHAR(120) NULL, |
| 18 | + |
| 19 | + amount DECIMAL(12,2) NOT NULL, |
| 20 | + |
| 21 | + -- Which day of the month it falls on. Kept separately from first_due_on |
| 22 | + -- because the two can disagree honestly: a loan whose first instalment was |
| 23 | + -- taken on the 3rd because that was the day the money cleared may still be |
| 24 | + -- due on the 5th every month after. |
| 25 | + -- |
| 26 | + -- A day past the end of a short month is clamped to that month's last day |
| 27 | + -- when the dates are worked out. 31 means "the end of the month", which is |
| 28 | + -- what a bank means by it too. |
| 29 | + due_day TINYINT UNSIGNED NOT NULL, |
| 30 | + |
| 31 | + first_due_on DATE NOT NULL, |
| 32 | + |
| 33 | + -- How many there are in total, so the posting stops on its own. A loan that |
| 34 | + -- runs out and keeps writing expenses is worse than one that never started. |
| 35 | + instalments SMALLINT UNSIGNED NOT NULL, |
| 36 | + |
| 37 | + method ENUM('Cash','UPI','Card','Bank Transfer','Other') NOT NULL DEFAULT 'Bank Transfer', |
| 38 | + note VARCHAR(255) NULL, |
| 39 | + |
| 40 | + -- Closed early: the car was sold, or the loan was settled. Set rather than |
| 41 | + -- deleted, because the instalments already posted are real money that was |
| 42 | + -- really paid and the loan is the only explanation of them. |
| 43 | + ended_on DATE NULL, |
| 44 | + |
| 45 | + created_by INT UNSIGNED NULL, |
| 46 | + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| 47 | + updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, |
| 48 | + |
| 49 | + PRIMARY KEY (id), |
| 50 | + KEY ix_vehicle_loans_vehicle (vehicle_id), |
| 51 | + KEY ix_vehicle_loans_open (ended_on), |
| 52 | + CONSTRAINT fk_vehicle_loans_vehicle FOREIGN KEY (vehicle_id) REFERENCES vehicles (id) |
| 53 | +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; |
| 54 | + |
| 55 | +-- Which loan an expense came from, and which instalment of it. |
| 56 | +-- |
| 57 | +-- loan_seq is 1 for the first instalment, 2 for the second, and so on. The |
| 58 | +-- unique key across the pair is the whole of why this can be run as often as |
| 59 | +-- anyone likes: posting the same instalment twice is not a thing the code has |
| 60 | +-- to be careful about, it is a thing the database refuses. Two people opening |
| 61 | +-- the dashboard in the same second cannot produce two rows. |
| 62 | +-- |
| 63 | +-- Both NULL on a typed expense, and the unique key ignores those -- MySQL |
| 64 | +-- allows any number of rows where part of a unique key is NULL, which is |
| 65 | +-- exactly the behaviour wanted here. |
| 66 | +ALTER TABLE expenses |
| 67 | + ADD COLUMN loan_id INT UNSIGNED NULL AFTER booking_id; |
| 68 | + |
| 69 | +ALTER TABLE expenses |
| 70 | + ADD COLUMN loan_seq SMALLINT UNSIGNED NULL AFTER loan_id; |
| 71 | + |
| 72 | +ALTER TABLE expenses |
| 73 | + ADD UNIQUE KEY uq_expenses_loan_instalment (loan_id, loan_seq); |
| 74 | + |
| 75 | +ALTER TABLE expenses |
| 76 | + ADD CONSTRAINT fk_expenses_loan FOREIGN KEY (loan_id) REFERENCES vehicle_loans (id); |
0 commit comments