Skip to content

Commit

Permalink
Merge pull request #36 from redwoodjs/pp-create-invoice-services
Browse files Browse the repository at this point in the history
Billable: Create invoice services
  • Loading branch information
peterp authored Jan 13, 2025
2 parents b74afc9 + 1c70d81 commit 866ec6e
Show file tree
Hide file tree
Showing 22 changed files with 662 additions and 232 deletions.
4 changes: 3 additions & 1 deletion experiments/billable/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ Copy the ID that's spat out by this command, and update the wrangler.toml file.

```terminal
pnpm install
pnpm migrate:dev
npx prisma generate
pnpm build
pnpm seed
pnpm dev
```

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
-- DropTable
PRAGMA foreign_keys=off;
DROP TABLE "InvoiceItem";
PRAGMA foreign_keys=on;

-- DropTable
PRAGMA foreign_keys=off;
DROP TABLE "InvoiceTaxItem";
PRAGMA foreign_keys=on;

-- RedefineTables
PRAGMA defer_foreign_keys=ON;
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_Invoice" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"title" TEXT NOT NULL DEFAULT 'invoice',
"userId" INTEGER NOT NULL,
"number" TEXT NOT NULL,
"date" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"status" TEXT NOT NULL DEFAULT 'draft',
"supplierName" TEXT NOT NULL,
"supplierContact" TEXT NOT NULL,
"customer" TEXT NOT NULL,
"notesA" TEXT,
"notesB" TEXT,
"items" TEXT NOT NULL DEFAULT '[]',
"taxes" TEXT NOT NULL DEFAULT '[]',
CONSTRAINT "Invoice_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
INSERT INTO "new_Invoice" ("customer", "date", "id", "notesA", "notesB", "number", "status", "supplierContact", "supplierName", "title", "userId") SELECT "customer", "date", "id", "notesA", "notesB", "number", "status", "supplierContact", "supplierName", "title", "userId" FROM "Invoice";
DROP TABLE "Invoice";
ALTER TABLE "new_Invoice" RENAME TO "Invoice";
CREATE UNIQUE INDEX "Invoice_userId_number_key" ON "Invoice"("userId", "number");
PRAGMA foreign_keys=ON;
PRAGMA defer_foreign_keys=OFF;
32 changes: 17 additions & 15 deletions experiments/billable/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,7 @@
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"build": "npx tsx ./scripts/build.mts",
"dev": "while true; do NODE_ENV=development npx tsx ./scripts/runDevServer.mts; [ $? -eq 0 ] || break; done",
"seed": "pnpm worker:run ./src/scripts/seed.ts",
"migrate:dev": "npx wrangler d1 migrations apply DB --local",
"migrate:prd": "npx wrangler d1 migrations apply DB --remote",
"migrate:new": "npx tsx ./scripts/migrateNew.mts",
"worker:run": "npx tsx ./scripts/runWorkerScript.mts",
"codegen": "npx tsx ./scripts/codegen.mts",
"types": "pnpm codegen:types && tsc",
"deploy": "wrangler deploy",
"preview": "NODE_ENV=${NODE_ENV:-development} PREVIEW=1 npx tsx ./scripts/runPreviewServer.mts",
"format": "npx prettier --write ./src ./scripts"
},

"keywords": [],
"author": "",
"license": "UNLICENSED",
Expand Down Expand Up @@ -73,5 +60,20 @@
"prisma": {
"seed": "npx wrangler d1 execute billable --file prisma/seed.sql --local"
},
"packageManager": "[email protected]+sha512.c8180b3fbe4e4bca02c94234717896b5529740a6cbadf19fa78254270403ea2f27d4e1d46a08a0f56c89b63dc8ebfd3ee53326da720273794e6200fcf0d184ab"
"packageManager": "[email protected]+sha512.c8180b3fbe4e4bca02c94234717896b5529740a6cbadf19fa78254270403ea2f27d4e1d46a08a0f56c89b63dc8ebfd3ee53326da720273794e6200fcf0d184ab",
"scripts": {
"build": "npx tsx ./scripts/build.mts",
"build:vendor": "npx tsx ./scripts/buildVendorBundles.mts",
"dev": "while true; do NODE_ENV=development npx tsx ./scripts/runDevServer.mts; [ $? -eq 0 ] || break; done",
"seed": "pnpm worker:run ./src/scripts/seed.ts",
"migrate:dev": "npx wrangler d1 migrations apply DB --local",
"migrate:prd": "npx wrangler d1 migrations apply DB --remote",
"migrate:new": "npx tsx ./scripts/migrateNew.mts",
"worker:run": "npx tsx ./scripts/runWorkerScript.mts",
"codegen": "npx tsx ./scripts/codegen.mts",
"types": "pnpm codegen:types && tsc",
"deploy": "wrangler deploy",
"preview": "NODE_ENV=${NODE_ENV:-development} PREVIEW=1 npx tsx ./scripts/runPreviewServer.mts",
"format": "npx prettier --write ./src ./scripts"
}
}
32 changes: 8 additions & 24 deletions experiments/billable/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -12,38 +12,22 @@ datasource db {
}

model Invoice {
id Int @id @default(autoincrement())
title String @default("invoice")
id Int @id @default(autoincrement())
title String @default("invoice")
userId Int
user User @relation(fields: [userId], references: [id])
user User @relation(fields: [userId], references: [id])
number String
date DateTime @default(now())
status String @default("draft")
date DateTime @default(now())
status String @default("draft")
supplierName String
supplierContact String
customer String
notesA String?
notesB String?
items InvoiceItem[]
taxes InvoiceTaxItem[]
@@unique([userId, number])
}
items String @default("[]")
taxes String @default("[]")
model InvoiceItem {
id Int @id @default(autoincrement())
invoiceId Int
invoice Invoice @relation(fields: [invoiceId], references: [id])
description String
quantity Int
price Float
}

model InvoiceTaxItem {
id Int @id @default(autoincrement())
invoiceId Int
invoice Invoice @relation(fields: [invoiceId], references: [id])
description String
amount Float
@@unique([userId, number])
}

model User {
Expand Down
16 changes: 10 additions & 6 deletions experiments/billable/prisma/seed.sql
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
DELETE FROM Invoice;
DELETE FROM User;
DELETE FROM sqlite_sequence WHERE name IN ('User', 'Invoice');
VACUUM;

INSERT INTO User (id, email) VALUES (1, '[email protected]');

INSERT INTO Invoice (id, userId, number, customer, supplierName, supplierContact, notesA) VALUES (1, 1, '1', 'Acme Corp', 'Global Supplies Ltd', '123 Business Ave, Suite 400, Metro City, ST 12345', 'Bank account number 123-456-789, SWIFT: BKCHCNBJ110, IBAN: GB29 NWBK 6016 1331 9268 19');
INSERT INTO Invoice (id, userId, number, customer, supplierName, supplierContact, notesA, items, taxes) VALUES (1, 1, '1', 'Acme Corp', 'Global Supplies Ltd', '123 Business Ave, Suite 400, Metro City, ST 12345', 'Bank account number 123-456-789, SWIFT: BKCHCNBJ110, IBAN: GB29 NWBK 6016 1331 9268 19', '[{"description": "Professional Web Development Services", "price": 1200.00, "quantity": 1}, {"description": "UI/UX Design Package", "price": 800.00, "quantity": 1}, {"description": "Server Hosting (Monthly)", "price": 99.99, "quantity": 12}, {"description": "Technical Support Hours", "price": 75.00, "quantity": 10}]', '[{"description": "VAT", "amount": 0.14}]');

INSERT INTO Invoice (id, userId, number, customer, supplierName, supplierContact, notesA, items, taxes) VALUES (2, 1, '2', 'TechStart Inc', 'Global Supplies Ltd', '123 Business Ave, Suite 400, Metro City, ST 12345', 'Bank account number 123-456-789, SWIFT: BKCHCNBJ110', '[{"description": "Mobile App Development", "price": 3500.00, "quantity": 1}, {"description": "Cloud Infrastructure Setup", "price": 1200.00, "quantity": 1}]', '[{"description": "VAT", "amount": 0.15}, {"description": "City Tax", "amount": 0.02}]');

INSERT INTO InvoiceItem (id, invoiceId, description, price, quantity) VALUES (1, 1, 'Professional Web Development Services', 1200.00, 1);
INSERT INTO InvoiceItem (id, invoiceId, description, price, quantity) VALUES (2, 1, 'UI/UX Design Package', 800.00, 1);
INSERT INTO InvoiceItem (id, invoiceId, description, price, quantity) VALUES (3, 1, 'Server Hosting (Monthly)', 99.99, 12);
INSERT INTO InvoiceItem (id, invoiceId, description, price, quantity) VALUES (4, 1, 'Technical Support Hours', 75.00, 10);
INSERT INTO Invoice (id, userId, number, customer, supplierName, supplierContact, notesA, items, taxes) VALUES (3, 1, '3', 'Marketing Masters LLC\nAttn: John Smith\n555 Commerce St\nBusiness City, BZ 54321', 'Global Supplies Ltd', '123 Business Ave, Suite 400, Metro City, ST 12345', NULL, '[{"description": "Digital Marketing Campaign", "price": 2500.00, "quantity": 1}, {"description": "Social Media Management", "price": 800.00, "quantity": 3}, {"description": "Content Creation", "price": 450.00, "quantity": 5}]', '[{"description": "VAT", "amount": 0.14}]');

INSERT INTO InvoiceTaxItem (id, invoiceId, description, amount) VALUES (1, 1, 'VAT', 0.14);
INSERT INTO Invoice (id, userId, number, customer, supplierName, supplierContact, notesA, items, taxes) VALUES (4, 1, '4', 'Healthcare Solutions Corp', 'Global Supplies Ltd', '123 Business Ave, Suite 400, Metro City, ST 12345', 'Payment due within 30 days', '[{"description": "Medical Software License", "price": 5000.00, "quantity": 1}, {"description": "Staff Training", "price": 1200.00, "quantity": 2}, {"description": "Support Package", "price": 299.99, "quantity": 12}]', '[{"description": "VAT", "amount": 0.14}, {"description": "Service Tax", "amount": 0.03}]');
2 changes: 1 addition & 1 deletion experiments/billable/scripts/build.mts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const build = async () => {
console.log("Building...");

// context(justinvdm, 2024-12-05): Call indirectly to silence verbose output when VERBOSE is not set
await $`npx tsx ./scripts/buildVendorBundles.mts`;
await $`pnpm build:vendor`;

await $`pnpm prisma generate`;

Expand Down
23 changes: 23 additions & 0 deletions experiments/billable/scripts/buildVendorBundles.mts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const configs = {
],
logLevel: process.env.VERBOSE ? "info" : "error",
build: {
emptyOutDir: false,
sourcemap: true,
minify: MODE === "production",
},
Expand All @@ -39,11 +40,33 @@ const configs = {
},
},
}),
reactRSC: (): InlineConfig =>
mergeConfig(configs.common(), {
resolve: {
conditions: ["react-server"],
},
build: {
outDir: DEST_DIR,
optimizeDeps: {
noDiscovery: false,
esbuildOptions: {
conditions: ["react-server"],
},
},
lib: {
entry: resolve(SRC_DIR, "react-rsc.ts"),
name: "react-rsc",
formats: ["es"],
fileName: "react-rsc",
},
},
}),
};

export const buildVendorBundles = async () => {
console.log("Building vendor bundles...");
await build(configs.reactSSR());
await build(configs.reactRSC());
};

if (import.meta.url === new URL(process.argv[1], import.meta.url).href) {
Expand Down
12 changes: 8 additions & 4 deletions experiments/billable/scripts/configs/vite.mts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export const viteConfigs = {
optimizeDeps: {
noDiscovery: false,
esbuildOptions: {
conditions: ["module", "workerd"],
conditions: ["module", "workerd", "react-server"],
},
include: [
"react",
Expand All @@ -93,9 +93,13 @@ export const viteConfigs = {
},
},
resolve: {
alias: {
"vendor/react-ssr": resolve(VENDOR_DIST_DIR, "react-ssr.js"),
},
alias: [{
find: "vendor/react-ssr",
replacement: resolve(VENDOR_DIST_DIR, "react-ssr.js"),
}, {
find: /^react$/,
replacement: resolve(VENDOR_DIST_DIR, "react-rsc.js"),
}]
},
server: {
hmr: true,
Expand Down
2 changes: 1 addition & 1 deletion experiments/billable/scripts/runDevServer.mts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { $ } from "./lib/$.mjs";

const setup = ({ silent = false } = {}) => async () => {
// context(justinvdm, 2024-12-05): Call indirectly to silence verbose output when VERBOSE is not set
await $`npx tsx ./scripts/buildVendorBundles.mts`;
await $`pnpm build:vendor`;

// context(justinvdm, 2024-11-28): Types don't affect runtime, so we don't need to block the dev server on them
void codegen({ silent });
Expand Down
149 changes: 0 additions & 149 deletions experiments/billable/src/app/InvoiceDetailPage.tsx

This file was deleted.

Loading

0 comments on commit 866ec6e

Please sign in to comment.