From 92ec3cd111e738b36940745d3fd921dffc51562d Mon Sep 17 00:00:00 2001
From: Ricardo <ricardofaria170@gmail.com>
Date: Mon, 24 Mar 2025 10:52:07 -0300
Subject: [PATCH] Issue#13: ADD buy implant route

---
 ...rk_phoenix.sql => 0000_nervous_wiccan.sql} |  9 ++--
 src/db/migrations/meta/0000_snapshot.json     | 30 ++++++-----
 src/db/migrations/meta/_journal.json          |  4 +-
 src/db/migrations/relations.ts                | 21 --------
 src/db/schema.ts                              |  6 +--
 src/handlers/implants.ts                      | 52 ++++++++++++++++++-
 src/handlers/user.ts                          |  1 -
 7 files changed, 78 insertions(+), 45 deletions(-)
 rename src/db/migrations/{0000_sad_dark_phoenix.sql => 0000_nervous_wiccan.sql} (80%)
 delete mode 100644 src/db/migrations/relations.ts

diff --git a/src/db/migrations/0000_sad_dark_phoenix.sql b/src/db/migrations/0000_nervous_wiccan.sql
similarity index 80%
rename from src/db/migrations/0000_sad_dark_phoenix.sql
rename to src/db/migrations/0000_nervous_wiccan.sql
index 33355cc..95ab7ca 100644
--- a/src/db/migrations/0000_sad_dark_phoenix.sql
+++ b/src/db/migrations/0000_nervous_wiccan.sql
@@ -10,11 +10,12 @@ CREATE TABLE "implants" (
 	CONSTRAINT "implants_id_unique" UNIQUE("id")
 );
 --> statement-breakpoint
-CREATE TABLE "pursaches" (
+CREATE TABLE "purchases" (
 	"id" serial PRIMARY KEY NOT NULL,
 	"user_id" integer NOT NULL,
+	"implant_id" integer NOT NULL,
 	"created_at" timestamp DEFAULT now() NOT NULL,
-	CONSTRAINT "pursaches_id_unique" UNIQUE("id")
+	CONSTRAINT "purchases_id_unique" UNIQUE("id")
 );
 --> statement-breakpoint
 CREATE TABLE "users" (
@@ -34,5 +35,5 @@ CREATE TABLE "users" (
 	CONSTRAINT "users_cpf_unique" UNIQUE("cpf")
 );
 --> statement-breakpoint
-ALTER TABLE "pursaches" ADD CONSTRAINT "pursaches_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
-ALTER TABLE "pursaches" ADD CONSTRAINT "pursaches_user_id_implants_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."implants"("id") ON DELETE cascade ON UPDATE no action;
\ No newline at end of file
+ALTER TABLE "purchases" ADD CONSTRAINT "purchases_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
+ALTER TABLE "purchases" ADD CONSTRAINT "purchases_implant_id_implants_id_fk" FOREIGN KEY ("implant_id") REFERENCES "public"."implants"("id") ON DELETE cascade ON UPDATE no action;
\ No newline at end of file
diff --git a/src/db/migrations/meta/0000_snapshot.json b/src/db/migrations/meta/0000_snapshot.json
index 614afe0..d624d9f 100644
--- a/src/db/migrations/meta/0000_snapshot.json
+++ b/src/db/migrations/meta/0000_snapshot.json
@@ -1,5 +1,5 @@
 {
-  "id": "15e4aa47-1bc6-462d-9d9d-8c0a45e69908",
+  "id": "0de8e822-0ca4-43f4-9002-743d449c49ce",
   "prevId": "00000000-0000-0000-0000-000000000000",
   "version": "7",
   "dialect": "postgresql",
@@ -70,8 +70,8 @@
       "checkConstraints": {},
       "isRLSEnabled": false
     },
-    "public.pursaches": {
-      "name": "pursaches",
+    "public.purchases": {
+      "name": "purchases",
       "schema": "",
       "columns": {
         "id": {
@@ -86,6 +86,12 @@
           "primaryKey": false,
           "notNull": true
         },
+        "implant_id": {
+          "name": "implant_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
         "created_at": {
           "name": "created_at",
           "type": "timestamp",
@@ -96,9 +102,9 @@
       },
       "indexes": {},
       "foreignKeys": {
-        "pursaches_user_id_users_id_fk": {
-          "name": "pursaches_user_id_users_id_fk",
-          "tableFrom": "pursaches",
+        "purchases_user_id_users_id_fk": {
+          "name": "purchases_user_id_users_id_fk",
+          "tableFrom": "purchases",
           "tableTo": "users",
           "columnsFrom": [
             "user_id"
@@ -109,12 +115,12 @@
           "onDelete": "cascade",
           "onUpdate": "no action"
         },
-        "pursaches_user_id_implants_id_fk": {
-          "name": "pursaches_user_id_implants_id_fk",
-          "tableFrom": "pursaches",
+        "purchases_implant_id_implants_id_fk": {
+          "name": "purchases_implant_id_implants_id_fk",
+          "tableFrom": "purchases",
           "tableTo": "implants",
           "columnsFrom": [
-            "user_id"
+            "implant_id"
           ],
           "columnsTo": [
             "id"
@@ -125,8 +131,8 @@
       },
       "compositePrimaryKeys": {},
       "uniqueConstraints": {
-        "pursaches_id_unique": {
-          "name": "pursaches_id_unique",
+        "purchases_id_unique": {
+          "name": "purchases_id_unique",
           "nullsNotDistinct": false,
           "columns": [
             "id"
diff --git a/src/db/migrations/meta/_journal.json b/src/db/migrations/meta/_journal.json
index cf82cce..a13f913 100644
--- a/src/db/migrations/meta/_journal.json
+++ b/src/db/migrations/meta/_journal.json
@@ -5,8 +5,8 @@
     {
       "idx": 0,
       "version": "7",
-      "when": 1742562467060,
-      "tag": "0000_sad_dark_phoenix",
+      "when": 1742907485976,
+      "tag": "0000_nervous_wiccan",
       "breakpoints": true
     }
   ]
diff --git a/src/db/migrations/relations.ts b/src/db/migrations/relations.ts
deleted file mode 100644
index 37e7bfe..0000000
--- a/src/db/migrations/relations.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { relations } from "drizzle-orm/relations";
-import { users, pursaches, implants } from "./schema";
-
-export const pursachesRelations = relations(pursaches, ({one}) => ({
-	user: one(users, {
-		fields: [pursaches.userId],
-		references: [users.id]
-	}),
-	implant: one(implants, {
-		fields: [pursaches.userId],
-		references: [implants.id]
-	}),
-}));
-
-export const usersRelations = relations(users, ({many}) => ({
-	pursaches: many(pursaches),
-}));
-
-export const implantsRelations = relations(implants, ({many}) => ({
-	pursaches: many(pursaches),
-}));
\ No newline at end of file
diff --git a/src/db/schema.ts b/src/db/schema.ts
index 0d5e011..90c8d70 100644
--- a/src/db/schema.ts
+++ b/src/db/schema.ts
@@ -23,12 +23,12 @@ export const bodyPartsEnum = pgEnum('bodyPartsEnum', [
   'Legs',
 ]);
 
-export const purchasesTable = pgTable('pursaches', {
+export const purchasesTable = pgTable("purchases", {
   id: serial('id').primaryKey().unique().notNull(),
   user_id: integer('user_id').notNull().references(() => usersTable.id, { onDelete: "cascade" }),
-  implant_id: integer('user_id').notNull().references(() => implantsTable.id, { onDelete: "cascade" }),
+  implant_id: integer('implant_id').notNull().references(() => implantsTable.id, { onDelete: "cascade" }),
   created_at: timestamp('created_at').notNull().defaultNow(),
-}) 
+});
 
 export const usersTable = pgTable("users", {
     id: serial('id').primaryKey().unique().notNull(),
diff --git a/src/handlers/implants.ts b/src/handlers/implants.ts
index 7e81b92..df3c5c3 100644
--- a/src/handlers/implants.ts
+++ b/src/handlers/implants.ts
@@ -1,5 +1,5 @@
 import { type Request, type Response } from 'express';
-import { implantsTable } from '@/db/schema';
+import { implantsTable, purchasesTable, usersTable} from '@/db/schema';
 import { db } from "@/db";
 import { eq } from 'drizzle-orm';
 import { implantSchema, updateImplantSchema } from '@/validators/implantsValidator';
@@ -101,7 +101,7 @@ export default class implant{
     }
 
     static async implantCreate(req: Request, res: Response){
-        const implant_package = implant.implantRequestUnzip(req);setInterval
+        const implant_package = implant.implantRequestUnzip(req);
         if (!implant_package.success)
         {
             return res.status(400).json("Invalid Request");
@@ -122,4 +122,52 @@ export default class implant{
             return res.status(500).json({ error: "User Creation Error"});
         }
     }
+
+    static async implantBuy (req: Request, res: Response): Promise<any>{
+        try{
+            const { buyer_id, product_id } = req.body;
+
+            const user = await db.select().from(usersTable).where(eq(usersTable.id, buyer_id));
+            const cyberPart = await db.select().from(implantsTable).where(eq(implantsTable.id, product_id));
+
+            
+
+            if (!user || !cyberPart)
+                return res.status(404).json({ erro: "User or implant not found" });
+
+            var userMoney = parseFloat(user.money);
+            const implantPrice = parseFloat(cyberPart.price);
+            var userCyberPsychosis = parseInt(user.cyberpsychosis, 10);
+            const userCyberLimit = parseInt(user.cyberLimit, 10);
+            const implantCyberCost = parseInt(cyberPart.cyberCost, 10)
+
+            if (userMoney < implantPrice)
+                return res.status(404).json({ erro: "Insufficient money" });
+
+            userMoney -= implantPrice;
+            userCyberPsychosis += implantCyberCost;
+
+            if (userCyberPsychosis >= userCyberLimit)
+                return res.status(404).json({ error: "Impossible to use implant, risk of cyberpsychosis is too high" });
+            
+            const updated_user = await db.update(usersTable)
+            .set({
+                money: userMoney.toString(),
+                cyberpsychosis: userCyberPsychosis.toString()
+            }).where(eq(usersTable.id, buyer_id)).returning();
+            
+            const purchase = await db.insert(purchasesTable)
+            .values({   
+                user_id: buyer_id,
+                implant_id: product_id,
+            }).returning();
+            
+            return res.status(200)
+            .json({ message: "Implant bought successfully", 
+                purchase, user: updated_user });
+        } catch (error) {
+            console.error(error);
+            return res.status(500).json({ error: "Erro ao realizar a compra" });
+        }
+    }
 }
diff --git a/src/handlers/user.ts b/src/handlers/user.ts
index 8f8ce48..7708db7 100644
--- a/src/handlers/user.ts
+++ b/src/handlers/user.ts
@@ -132,7 +132,6 @@ export default class User{
   
     static readUser = async (req: Request, res: Response): Promise<any> => {
       try {
-        
         // extrair id da requisição
         const { id } = req.params; 
 
-- 
GitLab