From 893decfabce3ffa3da37dc5993095ba395a63921 Mon Sep 17 00:00:00 2001 From: Ryunosuke Tokinaga <59079411+toririm@users.noreply.github.com> Date: Mon, 23 Sep 2024 20:07:37 +0900 Subject: [PATCH 01/10] =?UTF-8?q?[/cashier-v2]=20=E9=87=91=E9=A1=8D?= =?UTF-8?q?=E4=B8=8D=E8=B6=B3=E6=99=82=E3=81=AB=E3=82=AA=E3=83=BC=E3=83=80?= =?UTF-8?q?=E3=83=BC=E3=82=92=E6=8F=90=E5=87=BA=E3=81=A7=E3=81=8D=E3=81=AA?= =?UTF-8?q?=E3=81=84=E3=82=88=E3=81=86=E3=81=AB=20(#140)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #127 --- app/routes/cashier-v2.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/routes/cashier-v2.tsx b/app/routes/cashier-v2.tsx index 5f1c593f..8b111435 100644 --- a/app/routes/cashier-v2.tsx +++ b/app/routes/cashier-v2.tsx @@ -38,6 +38,9 @@ export default function Cashier() { const chargeView: string | number = charge < 0 ? "不足しています" : charge; const submitOrder = () => { + if (charge < 0) { + return; + } if (orderItems.length === 0) { return; } From 7326558c9d1cdcd9f49f3f4009889bf1bc94e69a Mon Sep 17 00:00:00 2001 From: Lai_lai <131964508+Lailai0477@users.noreply.github.com> Date: Mon, 23 Sep 2024 21:35:52 +0900 Subject: [PATCH 02/10] =?UTF-8?q?=E6=B3=A8=E6=96=87=E3=83=87=E3=83=BC?= =?UTF-8?q?=E3=82=BF=E3=81=AE=E4=B8=80=E8=A6=A7=E3=83=9A=E3=83=BC=E3=82=B8?= =?UTF-8?q?=E3=82=92=E4=BD=9C=E3=82=8B=20(#143)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit close #147 ref #106 --- app/routes/_header.dashboard.tsx | 90 +++++++++++++++++++++++++++++++ bun.lockb | Bin 479920 -> 480264 bytes package.json | 1 + 3 files changed, 91 insertions(+) create mode 100644 app/routes/_header.dashboard.tsx diff --git a/app/routes/_header.dashboard.tsx b/app/routes/_header.dashboard.tsx new file mode 100644 index 00000000..16ac3cf5 --- /dev/null +++ b/app/routes/_header.dashboard.tsx @@ -0,0 +1,90 @@ +import type { MetaFunction } from "@remix-run/react"; +import { orderBy } from "firebase/firestore"; +import useSWRSubscription from "swr/subscription"; + +import dayjs from "dayjs"; +import { + Table, + TableBody, + TableCaption, + TableCell, + TableFooter, + TableHead, + TableHeader, + TableRow, +} from "~/components/ui/table"; +import { orderConverter } from "~/firebase/converter"; +import { collectionSub } from "~/firebase/subscription"; +import type { OrderEntity } from "~/models/order"; + +export const meta: MetaFunction = () => { + return [{ title: "注文状況" }]; +}; + +export default function Dashboard() { + const { data: orders } = useSWRSubscription( + "orders", + collectionSub({ converter: orderConverter }, orderBy("orderId", "desc")), + ); + const unseved = orders?.reduce((acc, cur) => { + if (cur.servedAt == null) { + return acc + 1; + } + return acc; + }, 0); + + return ( +
+
+

注文状況

+

提供待ちオーダー数:{unseved}

+
+ +
+
+ + + + + No. + 杯数 + 合計額 + 受付時刻 + 提供時刻 + 時間 + + + + {orders?.map((order) => ( + + {order.orderId} + {numOfCups(order)} + ¥{order.total} + {order.createdAt.toLocaleTimeString()} + + {order.servedAt == null + ? "未提供" + : order.servedAt?.toLocaleTimeString()} + + {diffTime(order)} + + ))} + + +
+
+
+
+ ); +} + +const numOfCups = (order: OrderEntity): number => { + return order.items.length; +}; + +const diffTime = (order: OrderEntity) => { + if (order.servedAt == null) return "未提供"; + return dayjs(dayjs(order.servedAt).diff(dayjs(order.createdAt))).format( + "m:ss", + ); +}; diff --git a/bun.lockb b/bun.lockb index 6a2e1d84951b979f71cd43d3fbc534d93eade757..a13a792b70fa26273ead20a9d350a9d0d7917ae5 100755 GIT binary patch delta 73726 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

x0uoHP6cASis2AvN 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 Cy#Iy( delta 72900 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 Date: Mon, 23 Sep 2024 21:36:05 +0900 Subject: [PATCH 03/10] =?UTF-8?q?=E4=B8=8D=E8=A6=81=E3=81=AA=E3=82=A4?= =?UTF-8?q?=E3=83=B3=E3=83=9D=E3=83=BC=E3=83=88=E3=82=92=E5=BC=BE=E3=81=8F?= =?UTF-8?q?Biome=20rule=20(#146)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- biome.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/biome.json b/biome.json index 4c004f93..b1bf8f06 100644 --- a/biome.json +++ b/biome.json @@ -10,6 +10,9 @@ "enabled": true, "rules": { "recommended": true, + "correctness": { + "noUnusedImports": "warn" + }, "nursery": { "useSortedClasses": "warn" } From c98e9d39d774e253c621e4c81d556d131e469251 Mon Sep 17 00:00:00 2001 From: Ryunosuke Tokinaga <59079411+toririm@users.noreply.github.com> Date: Mon, 23 Sep 2024 22:30:05 +0900 Subject: [PATCH 04/10] =?UTF-8?q?[=E3=82=B9=E3=82=AD=E3=83=BC=E3=83=9E?= =?UTF-8?q?=E6=A1=882]=20assignee=20=E3=82=92=20item=20=E3=81=8C=E6=8C=81?= =?UTF-8?q?=E3=81=A4=20(#138)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit close #139 close #141 # カップ別指名を実現するためのスキーマ変更案2 orderの中に含まれる個々のitemがassigneeプロパティを持つ 下記の例では - ひんやりだいだいを"3"番ドリッパー - だいだいオレをてけとさん が担当することを示している。 ```jsonc { id: "...", orderId: 104, createdAt: ..., servedAt: null, items: [ { id: "...", name: "だいだいブレンド", price: 300, type: "hot", assignee: null }, { id: "...", name: "ひんやりだいだい", price: 300, type: "ice", assignee: "3" }, { id: "...", name: "だいだいオレ", price: 400, type: "ore", assignee: "てけと" } ], total: 1000, orderReady: false, description: "この人OBらしいよ~。全然名前知らんかったけど(笑)" } ``` ## メリット - assignee と item を確実に結びつけることができる ## デメリット - item が場面によっては不要な情報を持つ - ref: このケースでは、アイテムの新規作成時も assignee を null として扱う --- app/models/item.ts | 7 +++++-- app/models/order.test.ts | 3 +++ app/models/order.ts | 24 ++++++++++++------------ app/repositories/item.test.ts | 2 ++ app/repositories/order.test.ts | 20 +++++++++++++------- app/routes/_header.casher.tsx | 16 ++++++++++++---- 6 files changed, 47 insertions(+), 25 deletions(-) diff --git a/app/models/item.ts b/app/models/item.ts index 6acbd573..be59053f 100644 --- a/app/models/item.ts +++ b/app/models/item.ts @@ -11,6 +11,7 @@ export const itemSchema = z.object({ required_error: "種類が未選択です", invalid_type_error: "不正な種類です", }), + assignee: z.string().nullable(), }); export type Item = z.infer; @@ -33,10 +34,11 @@ export class ItemEntity implements Item { public readonly name: string, public readonly price: number, public readonly type: ItemType, + public assignee: string | null, ) {} - static createNew({ name, price, type }: Item): ItemEntity { - return new ItemEntity(undefined, name, price, type); + static createNew({ name, price, type }: Omit): ItemEntity { + return new ItemEntity(undefined, name, price, type, null); } static fromItem(item: WithId): WithId { @@ -45,6 +47,7 @@ export class ItemEntity implements Item { item.name, item.price, item.type, + item.assignee, ) as WithId; } } diff --git a/app/models/order.test.ts b/app/models/order.test.ts index 095c3869..be3969e3 100644 --- a/app/models/order.test.ts +++ b/app/models/order.test.ts @@ -18,12 +18,14 @@ describe("[unit] order entity", () => { name: "item1", price: 100, type: "hot", + assignee: null, }, { id: "2", name: "item2", price: 341, type: "ice", + assignee: null, }, ]; order.items.push(...items); @@ -34,6 +36,7 @@ describe("[unit] order entity", () => { name: "item3", price: 100, type: "ore", + assignee: null, }); expect(order.total).toBe(541); }); diff --git a/app/models/order.ts b/app/models/order.ts index 6ffc339c..0c7a894e 100644 --- a/app/models/order.ts +++ b/app/models/order.ts @@ -8,9 +8,9 @@ export const orderSchema = z.object({ createdAt: z.date(), servedAt: z.date().nullable(), items: z.array(itemSchema.required()), - assignee: z.string().nullable(), total: z.number(), orderReady: z.boolean(), + description: z.string(), }); export type Order = z.infer; @@ -23,9 +23,9 @@ export class OrderEntity implements Order { private readonly _createdAt: Date, private _servedAt: Date | null, private _items: WithId[], - private _assignee: string | null, private _total: number, private _orderReady: boolean, + private _description: string, ) {} static createNew({ orderId }: { orderId: number }): OrderEntity { @@ -35,9 +35,9 @@ export class OrderEntity implements Order { new Date(), null, [], - null, 0, false, + "", ); } @@ -48,9 +48,9 @@ export class OrderEntity implements Order { order.createdAt, order.servedAt, order.items, - order.assignee, order.total, order.orderReady, + order.description, ) as WithId; } @@ -81,13 +81,6 @@ export class OrderEntity implements Order { this._items = items; } - get assignee() { - return this._assignee; - } - set assignee(assignee: string | null) { - this._assignee = assignee; - } - get total() { // items の更新に合わせて total を自動で計算する // その代わり total は直接更新できない @@ -100,6 +93,13 @@ export class OrderEntity implements Order { return this._orderReady; } + get description() { + return this._description; + } + set description(description: string) { + this._description = description; + } + // -------------------------------------------------- // methods // -------------------------------------------------- @@ -121,9 +121,9 @@ export class OrderEntity implements Order { createdAt: this.createdAt, servedAt: this.servedAt, items: this.items, - assignee: this.assignee, total: this.total, orderReady: this.orderReady, + description: this.description, }; } } diff --git a/app/repositories/item.test.ts b/app/repositories/item.test.ts index a2654227..17cd9592 100644 --- a/app/repositories/item.test.ts +++ b/app/repositories/item.test.ts @@ -43,8 +43,10 @@ describe("[db] itemRepository", async () => { }); test("itemRepository.save (update)", async () => { + savedItemHoge.assignee = "toririm"; const savedItem = await itemRepository.save(savedItemHoge); expect(savedItem.id).toEqual(savedItemHoge.id); + expect(savedItem.assignee).toEqual("toririm"); }); test("itemRepository.findById", async () => { diff --git a/app/repositories/order.test.ts b/app/repositories/order.test.ts index 25a6962e..a22cf273 100644 --- a/app/repositories/order.test.ts +++ b/app/repositories/order.test.ts @@ -21,7 +21,7 @@ const isEmulatorRunning = async (): Promise => { describe("[db] orderRepository", async () => { // To use this environment, firebase emulator must be running. - let savedOrderHoge: WithId; + let savedOrderChange: WithId; let orderRepository: OrderRepository; beforeAll(async () => { @@ -47,15 +47,21 @@ describe("[db] orderRepository", async () => { test("orderRepository.save (create)", async () => { const order = OrderEntity.createNew({ orderId: 2024 }); - savedOrderHoge = await orderRepository.save(order); - expect(savedOrderHoge.id).toBeDefined(); + savedOrderChange = await orderRepository.save(order); + expect(savedOrderChange.id).toBeDefined(); }); test("orderRepository.save (update)", async () => { - savedOrderHoge.assignee = "hoge"; - const savedOrder = await orderRepository.save(savedOrderHoge); - expect(savedOrder.id).toEqual(savedOrderHoge.id); - expect(savedOrder.assignee).toEqual("hoge"); + savedOrderChange.items.push({ + id: "1", + name: "item1", + price: 100, + type: "hot", + assignee: null, + }); + const savedOrder = await orderRepository.save(savedOrderChange); + expect(savedOrder.id).toEqual(savedOrderChange.id); + expect(savedOrder.items).toEqual(savedOrderChange.items); }); test("orderRepository.findById", async () => { diff --git a/app/routes/_header.casher.tsx b/app/routes/_header.casher.tsx index ccd71888..9d8e6e8c 100644 --- a/app/routes/_header.casher.tsx +++ b/app/routes/_header.casher.tsx @@ -44,9 +44,9 @@ const mockOrder: Order = { // price: 300, // }, ], - assignee: "1st", total: 0, orderReady: false, + description: "", }; export default function Casher() { @@ -207,7 +207,13 @@ export const clientAction: ClientActionFunction = async ({ request }) => { const newItem = submission.value; // あとでマシなエラーハンドリングにする - const savedItem = await itemRepository.save(ItemEntity.createNew(newItem)); + const savedItem = await itemRepository.save( + ItemEntity.createNew({ + name: newItem.name, + price: newItem.price, + type: newItem.type, + }), + ); console.log("Document written with ID: ", savedItem.id); return new Response(null, { status: 204 }); @@ -236,10 +242,11 @@ export class ItemEntity implements Item { public readonly name: string, public readonly price: number, public readonly type: ItemType, + public assignee: string | null, ) {} - static createNew({ name, price, type }: Item): ItemEntity { - return new ItemEntity(undefined, name, price, type); + static createNew({ name, price, type }: Omit): ItemEntity { + return new ItemEntity(undefined, name, price, type, null); } static fromItem(item: WithId): WithId { @@ -248,6 +255,7 @@ export class ItemEntity implements Item { item.name, item.price, item.type, + item.assignee, ) as WithId; } } From 9e00a008e7d0ee103ad35688fc20438e44931c19 Mon Sep 17 00:00:00 2001 From: Ryunosuke Tokinaga <59079411+toririm@users.noreply.github.com> Date: Mon, 23 Sep 2024 23:58:31 +0900 Subject: [PATCH 05/10] =?UTF-8?q?=E3=82=A2=E3=82=A4=E3=83=86=E3=83=A0?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0=E3=81=A7=E3=81=8D=E3=81=AA=E3=81=84=E5=95=8F?= =?UTF-8?q?=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3=20(#148)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/routes/items/actions/addItem.ts | 4 +++- app/routes/items/route.tsx | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/routes/items/actions/addItem.ts b/app/routes/items/actions/addItem.ts index dbece28b..7825584e 100644 --- a/app/routes/items/actions/addItem.ts +++ b/app/routes/items/actions/addItem.ts @@ -7,7 +7,9 @@ import { itemRepository } from "~/repositories/item"; // TODO(toririm): テストを書く export const addItem: ClientActionFunction = async ({ request }) => { const formData = await request.formData(); - const submission = parseWithZod(formData, { schema: itemSchema }); + const submission = parseWithZod(formData, { + schema: itemSchema.omit({ assignee: true }), + }); if (submission.status !== "success") { console.error("Invalid form data", submission.reply()); diff --git a/app/routes/items/route.tsx b/app/routes/items/route.tsx index c0f83f81..e5365255 100644 --- a/app/routes/items/route.tsx +++ b/app/routes/items/route.tsx @@ -34,7 +34,9 @@ export default function Item() { const [form, fields] = useForm({ lastResult: navigation.state === "idle" ? lastResult : null, onValidate({ formData }) { - return parseWithZod(formData, { schema: itemSchema }); + return parseWithZod(formData, { + schema: itemSchema.omit({ assignee: true }), + }); }, shouldValidate: "onBlur", shouldRevalidate: "onInput", From 4cd82d94280a75acc8c76662b3271815fe5af3d2 Mon Sep 17 00:00:00 2001 From: Ryunosuke Tokinaga <59079411+toririm@users.noreply.github.com> Date: Tue, 24 Sep 2024 00:24:06 +0900 Subject: [PATCH 06/10] =?UTF-8?q?JSON.stringify=E3=81=A7""=E3=81=8Cnull?= =?UTF-8?q?=E3=81=AB=E5=A4=89=E6=8F=9B=E3=81=95=E3=82=8C=E3=82=8B=E3=81=AE?= =?UTF-8?q?=E3=81=A7=E3=82=B9=E3=82=AD=E3=83=BC=E3=83=9E=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=20(#149)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/order.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/models/order.ts b/app/models/order.ts index 0c7a894e..0f5774ef 100644 --- a/app/models/order.ts +++ b/app/models/order.ts @@ -10,7 +10,7 @@ export const orderSchema = z.object({ items: z.array(itemSchema.required()), total: z.number(), orderReady: z.boolean(), - description: z.string(), + description: z.string().nullable(), }); export type Order = z.infer; @@ -25,7 +25,7 @@ export class OrderEntity implements Order { private _items: WithId[], private _total: number, private _orderReady: boolean, - private _description: string, + private _description: string | null, ) {} static createNew({ orderId }: { orderId: number }): OrderEntity { @@ -37,7 +37,7 @@ export class OrderEntity implements Order { [], 0, false, - "", + null, ); } @@ -96,7 +96,7 @@ export class OrderEntity implements Order { get description() { return this._description; } - set description(description: string) { + set description(description: string | null) { this._description = description; } From 20b583e795130b5397fb68a7b3a032c6ab339269 Mon Sep 17 00:00:00 2001 From: Astalum <131961897+Astalum@users.noreply.github.com> Date: Thu, 26 Sep 2024 01:47:56 +0900 Subject: [PATCH 07/10] =?UTF-8?q?/casher:=20ItemEntity=E3=82=92import?= =?UTF-8?q?=E3=81=AB=E5=A4=89=E6=9B=B4=20(#150)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixes #116 ItemEntityをコピペからimportに変更 --------- Co-authored-by: toririm --- app/routes/_header.casher.tsx | 30 ++---------------------------- bun.lockb | Bin 480264 -> 480264 bytes 2 files changed, 2 insertions(+), 28 deletions(-) diff --git a/app/routes/_header.casher.tsx b/app/routes/_header.casher.tsx index 9d8e6e8c..5f7905ff 100644 --- a/app/routes/_header.casher.tsx +++ b/app/routes/_header.casher.tsx @@ -28,7 +28,8 @@ import { import { itemConverter } from "~/firebase/converter"; import { collectionSub } from "~/firebase/subscription"; import type { WithId } from "~/lib/typeguard"; -import { type Item, type ItemType, itemSchema } from "~/models/item"; +import { type Item, itemSchema } from "~/models/item"; +import { ItemEntity } from "~/models/item"; import type { Order } from "~/models/order"; import { itemRepository } from "~/repositories/item"; @@ -232,30 +233,3 @@ function mockOrderInitialize() { mockOrder.total = 0; console.log(mockOrder); } - -export class ItemEntity implements Item { - // TODO(toririm) - // ゲッターやセッターを使う際にはすべてのプロパティにアンスコをつけてprivateにする - // 実装の詳細は OrderEntity を参照 - private constructor( - public readonly id: string | undefined, - public readonly name: string, - public readonly price: number, - public readonly type: ItemType, - public assignee: string | null, - ) {} - - static createNew({ name, price, type }: Omit): ItemEntity { - return new ItemEntity(undefined, name, price, type, null); - } - - static fromItem(item: WithId): WithId { - return new ItemEntity( - item.id, - item.name, - item.price, - item.type, - item.assignee, - ) as WithId; - } -} diff --git a/bun.lockb b/bun.lockb index a13a792b70fa26273ead20a9d350a9d0d7917ae5..3ce2aa3f8469fa99740a75b9d394f1a9bec6f05d 100755 GIT binary patch delta 41 ucmeBJA=|M+wxNZwg{g&k3rq21PR2MxJwqTeZm)UF0>rG_YaX-p6aWA;=?`N7 delta 41 qcmeBJA=|M+wxNZwg{g&k3rq21P9_E@Xs>z90>rG_YaX-p6aWAf9}Tkr From 19361eb89410d968d20d23afda9b69ae00b5a9e2 Mon Sep 17 00:00:00 2001 From: Astalum <131961897+Astalum@users.noreply.github.com> Date: Fri, 27 Sep 2024 18:50:25 +0900 Subject: [PATCH 08/10] =?UTF-8?q?/casher:=20=E4=B8=8D=E8=A6=81=E3=81=AA?= =?UTF-8?q?=E9=96=A2=E6=95=B0=E3=82=B3=E3=83=B3=E3=83=9D=E3=83=BC=E3=83=8D?= =?UTF-8?q?=E3=83=B3=E3=83=88=E3=82=92=E5=89=8A=E9=99=A4=20(#152)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix #117 --- app/routes/_header.casher.tsx | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/app/routes/_header.casher.tsx b/app/routes/_header.casher.tsx index 5f7905ff..a82f38bd 100644 --- a/app/routes/_header.casher.tsx +++ b/app/routes/_header.casher.tsx @@ -123,7 +123,9 @@ export default function Casher() { console.log(mockOrder); }} > - {trashIcon()} +

@@ -220,14 +222,6 @@ export const clientAction: ClientActionFunction = async ({ request }) => { return new Response(null, { status: 204 }); }; -function trashIcon() { - return ( -
- -
- ); -} - function mockOrderInitialize() { mockOrder.items = []; mockOrder.total = 0; From 59fde2a39b6d5cfe06a9a5d0a9ed0fcb0049e5fb Mon Sep 17 00:00:00 2001 From: Ryunosuke Tokinaga <59079411+toririm@users.noreply.github.com> Date: Fri, 27 Sep 2024 19:30:43 +0900 Subject: [PATCH 09/10] =?UTF-8?q?[=E3=82=B9=E3=82=AD=E3=83=BC=E3=83=9E?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3]=20`order`=20=E5=89=B2=E5=BC=95=E3=81=A8?= =?UTF-8?q?=E3=81=8A=E9=A0=90=E3=81=8B=E3=82=8A=E9=87=91=E9=A1=8D=E3=81=AE?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0=20(#153)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Close #151 --- app/models/order.test.ts | 66 +++++++++++++++++++++++++++-- app/models/order.ts | 80 ++++++++++++++++++++++++++++++++++- app/routes/_header.casher.tsx | 7 +++ 3 files changed, 148 insertions(+), 5 deletions(-) diff --git a/app/models/order.test.ts b/app/models/order.test.ts index be3969e3..dde0798e 100644 --- a/app/models/order.test.ts +++ b/app/models/order.test.ts @@ -1,10 +1,10 @@ import { describe, expect, test } from "bun:test"; import type { WithId } from "~/lib/typeguard"; -import type { ItemEntity } from "./item"; +import { type Item, ItemEntity } from "./item"; import { OrderEntity } from "./order"; describe("[unit] order entity", () => { - test("order total auto calc", () => { + test("total auto calc", () => { const order = OrderEntity.createNew({ orderId: 2024 }); expect(order.total).toBe(0); @@ -41,7 +41,7 @@ describe("[unit] order entity", () => { expect(order.total).toBe(541); }); - test("order beReady", () => { + test("beReady", () => { const order = OrderEntity.createNew({ orderId: 2024 }); expect(order.orderReady).toBe(false); @@ -49,7 +49,7 @@ describe("[unit] order entity", () => { expect(order.orderReady).toBe(true); }); - test("order beServed", () => { + test("beServed", () => { const order = OrderEntity.createNew({ orderId: 2024 }); expect(order.servedAt).toBe(null); @@ -57,4 +57,62 @@ describe("[unit] order entity", () => { expect(order.servedAt).not.toBe(null); expect(order.servedAt).toBeInstanceOf(Date); }); + + test("billingAmount", () => { + const order = OrderEntity.createNew({ orderId: 2024 }); + expect(order.billingAmount).toBe(0); + + const items: WithId[] = [ + { + id: "1", + name: "item1", + price: 400, + type: "hot", + assignee: null, + }, + { + id: "2", + name: "item2", + price: 500, + type: "ice", + assignee: null, + }, + ]; + const itemEntities = items.map((item) => ItemEntity.fromItem(item)); + + order.items = itemEntities; + expect(order.billingAmount).toBe(900); + + const previousOrder = OrderEntity.fromOrder({ + id: "1", + orderId: 99999, + createdAt: new Date(), + servedAt: null, + items: itemEntities.slice(0, 1), + total: 900, + orderReady: false, + description: null, + billingAmount: 900, + received: 0, + discountInfo: { + previousOrderId: null, + validCups: 0, + discount: 0, + }, + }); + + order.applyDiscount(previousOrder); + expect(order.discountInfo.previousOrderId).toBe(99999); + expect(order.discountInfo.validCups).toBe(1); + expect(order.discountInfo.discount).toBe(100); + expect(order.billingAmount).toBe(800); + }); + + test("received", () => { + const order = OrderEntity.createNew({ orderId: 2024 }); + expect(order.received).toBe(0); + + order.received = 1000; + expect(order.received).toBe(1000); + }); }); diff --git a/app/models/order.ts b/app/models/order.ts index 0f5774ef..559366eb 100644 --- a/app/models/order.ts +++ b/app/models/order.ts @@ -8,12 +8,43 @@ export const orderSchema = z.object({ createdAt: z.date(), servedAt: z.date().nullable(), items: z.array(itemSchema.required()), - total: z.number(), + total: z.number(), // sum of item.price orderReady: z.boolean(), description: z.string().nullable(), + billingAmount: z.number(), // total - discount + received: z.number(), // お預かり金額 + discountInfo: z.object({ + previousOrderId: z.number().nullable(), + validCups: z.number(), // min(this.items.length, previousOrder.items.length) + discount: z.number(), // validCups * 100 + }), }); export type Order = z.infer; +type DiscountInfo = Order["discountInfo"]; + +const DISCOUNT_RATE_PER_CUP = 100; + +// OrderEntity の内部でのみ使うクラス +class DiscountInfoEntity implements DiscountInfo { + constructor( + readonly previousOrderId: number | null, + readonly validCups: number, + ) {} + + get discount() { + return this.validCups * DISCOUNT_RATE_PER_CUP; + } + + static fromDiscountInfo( + discountInfo: Omit, + ): DiscountInfoEntity { + return new DiscountInfoEntity( + discountInfo.previousOrderId, + discountInfo.validCups, + ); + } +} export class OrderEntity implements Order { // 全てのプロパティを private にして外部からの直接アクセスを禁止 @@ -26,6 +57,9 @@ export class OrderEntity implements Order { private _total: number, private _orderReady: boolean, private _description: string | null, + private _billingAmount: number, + private _received: number, + private _discountInfo: DiscountInfoEntity = new DiscountInfoEntity(null, 0), ) {} static createNew({ orderId }: { orderId: number }): OrderEntity { @@ -38,6 +72,8 @@ export class OrderEntity implements Order { 0, false, null, + 0, + 0, ); } @@ -51,6 +87,9 @@ export class OrderEntity implements Order { order.total, order.orderReady, order.description, + order.billingAmount, + order.received, + DiscountInfoEntity.fromDiscountInfo(order.discountInfo), ) as WithId; } @@ -100,10 +139,32 @@ export class OrderEntity implements Order { this._description = description; } + get billingAmount() { + this._billingAmount = this.total - this._discountInfo.discount; + return this._billingAmount; + } + + get received() { + return this._received; + } + set received(received: number) { + this._received = received; + } + + get discountInfo() { + return this._discountInfo; + } + // -------------------------------------------------- // methods // -------------------------------------------------- + _getCoffeeCount() { + // milk 以外のアイテムの数を返す + // TODO(toririm): このメソッドは items が変更された時だけでいい + return this.items.filter((item) => item.type !== "milk").length; + } + beReady() { // orderReady は false -> true にしか変更できないようにする this._orderReady = true; @@ -114,6 +175,20 @@ export class OrderEntity implements Order { this._servedAt = new Date(); } + /* このメソッドのみで discountInfo を更新する */ + applyDiscount(previousOrder: OrderEntity) { + const validCups = Math.min( + this._getCoffeeCount(), + previousOrder._getCoffeeCount(), + ); + + this._discountInfo = DiscountInfoEntity.fromDiscountInfo({ + previousOrderId: previousOrder.orderId, + validCups, + }); + return this._discountInfo; + } + toOrder(): Order { return { id: this.id, @@ -124,6 +199,9 @@ export class OrderEntity implements Order { total: this.total, orderReady: this.orderReady, description: this.description, + billingAmount: this.billingAmount, + received: this.received, + discountInfo: this.discountInfo, }; } } diff --git a/app/routes/_header.casher.tsx b/app/routes/_header.casher.tsx index a82f38bd..3d12a61d 100644 --- a/app/routes/_header.casher.tsx +++ b/app/routes/_header.casher.tsx @@ -48,6 +48,13 @@ const mockOrder: Order = { total: 0, orderReady: false, description: "", + discountInfo: { + previousOrderId: null, + validCups: 0, + discount: 0, + }, + received: 0, + billingAmount: 0, }; export default function Casher() { From 7d9c2205897cab606448c34fa2727c57a1a21b9c Mon Sep 17 00:00:00 2001 From: Ryunosuke Tokinaga <59079411+toririm@users.noreply.github.com> Date: Sat, 28 Sep 2024 00:47:38 +0900 Subject: [PATCH 10/10] =?UTF-8?q?JSON.stringify=E3=81=A7nested=E3=81=AAcla?= =?UTF-8?q?ss=E3=81=8C=E9=81=A9=E5=88=87=E3=81=AB=E8=A7=A3=E9=87=88?= =?UTF-8?q?=E3=81=95=E3=82=8C=E3=81=AA=E3=81=84=E3=81=AE=E3=81=A7=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3=20(#155)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ゲッターが読まれず、privateなプロパティであってもプロパティが優先されてしまう --- app/models/item.ts | 3 --- app/models/order.ts | 18 ++++++++++-------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/app/models/item.ts b/app/models/item.ts index be59053f..211cc3bd 100644 --- a/app/models/item.ts +++ b/app/models/item.ts @@ -26,9 +26,6 @@ export const type2label = { } as const satisfies Record; export class ItemEntity implements Item { - // TODO(toririm) - // ゲッターやセッターを使う際にはすべてのプロパティにアンスコをつけてprivateにする - // 実装の詳細は OrderEntity を参照 private constructor( public readonly id: string | undefined, public readonly name: string, diff --git a/app/models/order.ts b/app/models/order.ts index 559366eb..5516d1a5 100644 --- a/app/models/order.ts +++ b/app/models/order.ts @@ -30,18 +30,14 @@ class DiscountInfoEntity implements DiscountInfo { constructor( readonly previousOrderId: number | null, readonly validCups: number, + readonly discount: number, ) {} - get discount() { - return this.validCups * DISCOUNT_RATE_PER_CUP; - } - - static fromDiscountInfo( - discountInfo: Omit, - ): DiscountInfoEntity { + static fromDiscountInfo(discountInfo: DiscountInfo): DiscountInfoEntity { return new DiscountInfoEntity( discountInfo.previousOrderId, discountInfo.validCups, + discountInfo.discount, ); } } @@ -59,7 +55,11 @@ export class OrderEntity implements Order { private _description: string | null, private _billingAmount: number, private _received: number, - private _discountInfo: DiscountInfoEntity = new DiscountInfoEntity(null, 0), + private _discountInfo: DiscountInfoEntity = new DiscountInfoEntity( + null, + 0, + 0, + ), ) {} static createNew({ orderId }: { orderId: number }): OrderEntity { @@ -181,10 +181,12 @@ export class OrderEntity implements Order { this._getCoffeeCount(), previousOrder._getCoffeeCount(), ); + const discount = validCups * DISCOUNT_RATE_PER_CUP; this._discountInfo = DiscountInfoEntity.fromDiscountInfo({ previousOrderId: previousOrder.orderId, validCups, + discount, }); return this._discountInfo; }