From b61141dbf32f62e618e14e9cf185948a2121376d Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Tue, 9 Jul 2024 13:54:24 +0530
Subject: [PATCH 01/40] feat: create schema for share

---
 src/server/api/schema/shares.ts | 130 ++++++++++++++++++++++++++++++++
 1 file changed, 130 insertions(+)
 create mode 100644 src/server/api/schema/shares.ts

diff --git a/src/server/api/schema/shares.ts b/src/server/api/schema/shares.ts
new file mode 100644
index 000000000..e733a609d
--- /dev/null
+++ b/src/server/api/schema/shares.ts
@@ -0,0 +1,130 @@
+import { z } from "@hono/zod-openapi";
+import {
+  SecuritiesStatusEnum,
+  ShareLegendsEnum,
+  VestingScheduleEnum,
+} from "@prisma/client";
+
+const VestingScheduleArr = Object.values(VestingScheduleEnum) as [
+  string,
+  ...string[],
+];
+const ShareLegendsArr = Object.values(ShareLegendsEnum) as [
+  string,
+  ...string[],
+];
+const SecuritiesStatusArr = Object.values(SecuritiesStatusEnum) as [
+  string,
+  ...string[],
+];
+
+export const ShareSchema = z
+  .object({
+    id: z.string().cuid().openapi({
+      description: "Share ID",
+      example: "cly13ipa40000i7ng42mv4x7b",
+    }),
+
+    status: z.enum(SecuritiesStatusArr).openapi({
+      description: "Security Status",
+      example: "DRAFT",
+    }),
+
+    certificateId: z.string().cuid().openapi({
+      description: "Certificate ID",
+      example: "cly13ipa40000i7ng42mv4x7b",
+    }),
+
+    quantity: z.number().openapi({
+      description: "Quantity of Shares",
+      example: 234,
+    }),
+
+    pricePerShare: z.number().nullable().openapi({
+      description: "Price Per Share",
+      example: 23.4,
+    }),
+
+    capitalContribution: z.number().optional().openapi({
+      description: "Total amount of money contributed",
+      example: 25.4,
+    }),
+
+    ipContribution: z.number().optional().openapi({
+      description: "Value of the intellectual property contributed",
+      example: 43.4,
+    }),
+
+    debtCancelled: z.number().optional().openapi({
+      description: "Amount of debt cancelled",
+      example: 54.54,
+    }),
+
+    otherContributions: z.number().optional().openapi({
+      description: "Other contributions",
+      example: 45.54,
+    }),
+
+    vestingSchedule: z.enum(VestingScheduleArr).openapi({
+      description: "Vesting Schedule",
+      example: "VESTING_0_0_0",
+    }),
+
+    companyLegends: z
+      .enum(ShareLegendsArr)
+      .array()
+      .openapi({
+        description: "Company Legends",
+        example: ["US_SECURITIES_ACT", "SALE_AND_ROFR"],
+      }),
+
+    issueDate: z.string().datetime().openapi({
+      description: "Issued Date",
+      example: "1970-01-01T00:00:00.000Z",
+    }),
+
+    rule144Date: z.string().datetime().optional().openapi({
+      description: "Rule 144 Date",
+      example: "1970-01-01T00:00:00.000Z",
+    }),
+
+    vestingStartDate: z.string().datetime().optional().openapi({
+      description: "Vesting Start Date",
+      example: "1970-01-01T00:00:00.000Z",
+    }),
+
+    boardApprovalDate: z.string().datetime().optional().openapi({
+      description: "Board Approval Date",
+      example: "1970-01-01T00:00:00.000Z",
+    }),
+
+    stakeholderId: z.string().cuid().openapi({
+      description: "StakeHolder ID",
+      example: "cly13ipa40000i7ng42mv4x7b",
+    }),
+
+    companyId: z.string().cuid().openapi({
+      description: "Company ID",
+      example: "cly13ipa40000i7ng42mv4x7b",
+    }),
+
+    shareClassId: z.string().cuid().openapi({
+      description: "ShareClass ID",
+      example: "cly13ipa40000i7ng42mv4x7b",
+    }),
+
+    createdAt: z.string().datetime().optional().openapi({
+      description: "Share Created at",
+      example: "1970-01-01T00:00:00.000Z",
+    }),
+
+    updatedAt: z.string().datetime().optional().openapi({
+      description: "Share Updated at",
+      example: "1970-01-01T00:00:00.000Z",
+    }),
+  })
+  .openapi({
+    description: "Get a Single Share by the ID",
+  });
+
+export type TShareSchema = z.infer<typeof ShareSchema>;

From 5142219618e01631ca7c0aacda89af8960f9361d Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Tue, 9 Jul 2024 13:56:09 +0530
Subject: [PATCH 02/40] feat: add getShareById route

---
 src/server/api/routes/company/share/getOne.ts | 93 +++++++++++++++++++
 1 file changed, 93 insertions(+)
 create mode 100644 src/server/api/routes/company/share/getOne.ts

diff --git a/src/server/api/routes/company/share/getOne.ts b/src/server/api/routes/company/share/getOne.ts
new file mode 100644
index 000000000..d87a516ba
--- /dev/null
+++ b/src/server/api/routes/company/share/getOne.ts
@@ -0,0 +1,93 @@
+import { withCompanyAuth } from "@/server/api/auth";
+import { ApiError, ErrorResponses } from "@/server/api/error";
+import type { PublicAPI } from "@/server/api/hono";
+import { ShareSchema, type TShareSchema } from "@/server/api/schema/shares";
+import { db } from "@/server/db";
+import { createRoute, z } from "@hono/zod-openapi";
+import type { Context } from "hono";
+
+const ParamsSchema = z.object({
+  id: z
+    .string()
+    .cuid()
+    .openapi({
+      description: "Company ID",
+      param: {
+        name: "id",
+        in: "path",
+      },
+
+      example: "clxwbok580000i7nge8nm1ry0",
+    }),
+  shareId: z
+    .string()
+    .cuid()
+    .openapi({
+      description: "Share ID",
+      param: {
+        name: "shareId",
+        in: "path",
+      },
+
+      example: "clyd3i9sw000008ij619eabva",
+    }),
+});
+
+const ResponseSchema = z
+  .object({
+    data: ShareSchema,
+  })
+  .openapi({
+    description: "Get a single Share by ID",
+  });
+
+const route = createRoute({
+  method: "get",
+  path: "/v1/companies/{id}/shares/{shareId}",
+  request: {
+    params: ParamsSchema,
+  },
+  responses: {
+    200: {
+      content: {
+        "application/json": {
+          schema: ResponseSchema,
+        },
+      },
+      description: "Retrieve the share for the company",
+    },
+    ...ErrorResponses,
+  },
+});
+
+const getOne = (app: PublicAPI) => {
+  app.openapi(route, async (c: Context) => {
+    const { company } = await withCompanyAuth(c);
+
+    // id destructured to companyId and shareId destructured to id
+    const { shareId: id } = c.req.param();
+
+    const share = (await db.share.findUnique({
+      where: {
+        id,
+        companyId: company.id,
+      },
+    })) as unknown as TShareSchema;
+
+    if (!share) {
+      throw new ApiError({
+        code: "NOT_FOUND",
+        message: "Share not found",
+      });
+    }
+
+    return c.json(
+      {
+        data: share,
+      },
+      200,
+    );
+  });
+};
+
+export default getOne;

From b66d2c92c2cb40f98a098df7a6abc4e6335933e5 Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Tue, 9 Jul 2024 13:58:44 +0530
Subject: [PATCH 03/40] feat: add getOne function in shareRoutes

---
 src/server/api/routes/company/share/index.ts | 8 ++++++++
 1 file changed, 8 insertions(+)
 create mode 100644 src/server/api/routes/company/share/index.ts

diff --git a/src/server/api/routes/company/share/index.ts b/src/server/api/routes/company/share/index.ts
new file mode 100644
index 000000000..929b30ab7
--- /dev/null
+++ b/src/server/api/routes/company/share/index.ts
@@ -0,0 +1,8 @@
+import type { PublicAPI } from "@/server/api/hono";
+import getOne from "./getOne";
+
+const shareRoutes = (api: PublicAPI) => {
+  getOne(api);
+};
+
+export default shareRoutes;

From 397d50ee6992aebcb7b49dc508e56ba21b248024 Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Tue, 9 Jul 2024 19:23:59 +0530
Subject: [PATCH 04/40] feat: add pagination query and response schema

---
 src/server/api/schema/pagination.ts | 65 +++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)
 create mode 100644 src/server/api/schema/pagination.ts

diff --git a/src/server/api/schema/pagination.ts b/src/server/api/schema/pagination.ts
new file mode 100644
index 000000000..aa5d10e1f
--- /dev/null
+++ b/src/server/api/schema/pagination.ts
@@ -0,0 +1,65 @@
+import { z } from "zod";
+
+export const PaginationQuerySchema = z.object({
+  limit: z
+    .preprocess(
+      (val) =>
+        val === undefined ? undefined : Number.parseInt(val as string, 10),
+      z.number().int().positive().min(1).max(50).default(10),
+    )
+    .openapi({
+      description: "Number of items to take",
+      param: {
+        name: "limit",
+        in: "query",
+      },
+      example: 10,
+      default: 10,
+      minimum: 5,
+      maximum: 50,
+    }),
+
+  cursor: z
+    .string()
+    .optional()
+    .openapi({
+      description: "Cursor for the next page",
+      param: {
+        name: "cursor",
+        in: "query",
+      },
+      example: "cly151kxq0000i7ngb3erchgo", // CUID of the last item
+    }),
+
+  total: z
+    .number()
+    .int()
+    .positive()
+    .optional()
+    .openapi({
+      description: "Total Number of Records",
+      param: {
+        name: "total",
+        in: "query",
+      },
+    }),
+});
+
+export type TPaginationQuerySchema = z.infer<typeof PaginationQuerySchema>;
+
+export const PaginationResponseSchema = z.object({
+  count: z.number().int().positive().openapi({
+    description: "Number of records returned",
+    example: 50,
+  }),
+
+  total: z.number().int().positive().openapi({
+    description: "Total number of records",
+    example: 100,
+  }),
+
+  cursor: z.string().optional().openapi({
+    description: "Next page cursor",
+    example: "cly151kxq0000i7ngb3erchgo",
+  }),
+});

From ac3f4b9cff3cc067986b1f7563c31618f3e56eb3 Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Tue, 9 Jul 2024 19:26:30 +0530
Subject: [PATCH 05/40] feat: add ProxyPrismaModel and proxy findMany method

---
 src/server/api/pagination/find-many.proxy.ts | 62 ++++++++++++++++++++
 src/server/api/pagination/prisma-proxy.ts    | 26 ++++++++
 src/server/api/pagination/types.ts           | 19 ++++++
 3 files changed, 107 insertions(+)
 create mode 100644 src/server/api/pagination/find-many.proxy.ts
 create mode 100644 src/server/api/pagination/prisma-proxy.ts
 create mode 100644 src/server/api/pagination/types.ts

diff --git a/src/server/api/pagination/find-many.proxy.ts b/src/server/api/pagination/find-many.proxy.ts
new file mode 100644
index 000000000..f1765fa98
--- /dev/null
+++ b/src/server/api/pagination/find-many.proxy.ts
@@ -0,0 +1,62 @@
+import type { PaginationData, ProxyFunctions } from "./types";
+
+interface Paginated<T> {
+  data: T[];
+  count: number;
+  total: number;
+  cursor?: string;
+}
+
+/**
+ * FindManyPaginated
+ *
+ * type of the findManyPaginated method
+ */
+export type FindManyPaginated<F extends ProxyFunctions> = {
+  findManyPaginated: (
+    data: Omit<Parameters<F["findMany"]>[0], "take" | "skip" | "cursor">,
+    pagination: PaginationData,
+  ) => Promise<Paginated<Awaited<ReturnType<F["findMany"]>>[0]>>;
+};
+
+/**
+ * makeFindManyPaginated
+ *
+ * factory function that creates the findManyPaginated method.
+ * this method is used to paginate the results of a findMany method.
+ * this method implements js proxy to intercept the call to findMany and add the pagination logic.
+ */
+export function makeFindManyPaginated(model: ProxyFunctions) {
+  return new Proxy(model.findMany, {
+    apply: async (target, thisArg, [data, paginationInfo]) => {
+      const limit = paginationInfo?.limit;
+      const cursor = paginationInfo?.cursor;
+
+      const query = data || {};
+      query.take = limit;
+      if (cursor) {
+        query.cursor = { id: cursor }; // Assuming `id` is the cursor field
+        query.skip = 1; // Skip the cursor item itself
+      }
+
+      const total =
+        paginationInfo?.total ||
+        (await model.count({
+          where: query.where,
+        }));
+
+      //@ts-ignore
+      const docs = await target.apply(thisArg, [query]);
+
+      const nextCursor =
+        docs.length === limit ? docs[docs.length - 1].id : null; // Assuming `id` is the cursor field
+
+      return {
+        data: docs,
+        count: docs.length,
+        total,
+        cursor: nextCursor,
+      };
+    },
+  });
+}
diff --git a/src/server/api/pagination/prisma-proxy.ts b/src/server/api/pagination/prisma-proxy.ts
new file mode 100644
index 000000000..ec490a956
--- /dev/null
+++ b/src/server/api/pagination/prisma-proxy.ts
@@ -0,0 +1,26 @@
+import {
+  type FindManyPaginated,
+  makeFindManyPaginated,
+} from "./find-many.proxy";
+import type { ProxyFunctions } from "./types";
+
+/**
+ * ProxyPrismaModel
+ *
+ * type of a prisma model with custom methods. to date, only findManyPaginated is implemented
+ */
+type ProxyPrismaModel<F extends ProxyFunctions> = F & FindManyPaginated<F>;
+
+/**
+ * ProxyPrismaModel
+ *
+ * the factory function that creates a ProxyPrismaModel. to date, only findManyPaginated is implemented.
+ */
+export function ProxyPrismaModel<F extends ProxyFunctions>(
+  model: F,
+): ProxyPrismaModel<F> {
+  Reflect.set(model, "findManyPaginated", makeFindManyPaginated(model));
+  // Reflect.set(model, 'anotherProxiedMethod', makeAnotherProxyMethod(model));
+  // ...
+  return model as ProxyPrismaModel<F>;
+}
diff --git a/src/server/api/pagination/types.ts b/src/server/api/pagination/types.ts
new file mode 100644
index 000000000..c6f6c70d3
--- /dev/null
+++ b/src/server/api/pagination/types.ts
@@ -0,0 +1,19 @@
+/**
+ * Pagination information
+ */
+export type PaginationData = {
+  limit: number;
+  cursor?: string;
+};
+
+/**
+ * Proxy functions
+ *
+ * used to create custom methods for prisma models
+ */
+export type ProxyFunctions = {
+  // biome-ignore lint/suspicious/noExplicitAny: <any is legal here>
+  findMany: (params: any, pagination: PaginationData) => Promise<any>;
+  // biome-ignore lint/suspicious/noExplicitAny: <any is legal here>
+  count: (params: any) => Promise<number>;
+};

From 411b3bb1e752f592d6e3af2d58d9ee52d8a46ed4 Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Wed, 10 Jul 2024 11:28:38 +0530
Subject: [PATCH 06/40] fix: update type of total

---
 src/server/api/schema/pagination.ts | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/src/server/api/schema/pagination.ts b/src/server/api/schema/pagination.ts
index aa5d10e1f..baeba0e66 100644
--- a/src/server/api/schema/pagination.ts
+++ b/src/server/api/schema/pagination.ts
@@ -32,10 +32,11 @@ export const PaginationQuerySchema = z.object({
     }),
 
   total: z
-    .number()
-    .int()
-    .positive()
-    .optional()
+    .preprocess(
+      (val) =>
+        val === undefined ? undefined : Number.parseInt(val as string, 10),
+      z.number().int().positive().optional(),
+    )
     .openapi({
       description: "Total Number of Records",
       param: {

From 764fd80822d0535e6e37f6d621f886018a602e98 Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Wed, 10 Jul 2024 11:52:16 +0530
Subject: [PATCH 07/40] fix: type of ShareSchema

---
 src/server/api/schema/shares.ts | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/server/api/schema/shares.ts b/src/server/api/schema/shares.ts
index e733a609d..cc48d6275 100644
--- a/src/server/api/schema/shares.ts
+++ b/src/server/api/schema/shares.ts
@@ -45,22 +45,22 @@ export const ShareSchema = z
       example: 23.4,
     }),
 
-    capitalContribution: z.number().optional().openapi({
+    capitalContribution: z.number().nullable().openapi({
       description: "Total amount of money contributed",
       example: 25.4,
     }),
 
-    ipContribution: z.number().optional().openapi({
+    ipContribution: z.number().nullable().openapi({
       description: "Value of the intellectual property contributed",
       example: 43.4,
     }),
 
-    debtCancelled: z.number().optional().openapi({
+    debtCancelled: z.number().nullable().openapi({
       description: "Amount of debt cancelled",
       example: 54.54,
     }),
 
-    otherContributions: z.number().optional().openapi({
+    otherContributions: z.number().nullable().openapi({
       description: "Other contributions",
       example: 45.54,
     }),
@@ -83,12 +83,12 @@ export const ShareSchema = z
       example: "1970-01-01T00:00:00.000Z",
     }),
 
-    rule144Date: z.string().datetime().optional().openapi({
+    rule144Date: z.string().datetime().nullable().openapi({
       description: "Rule 144 Date",
       example: "1970-01-01T00:00:00.000Z",
     }),
 
-    vestingStartDate: z.string().datetime().optional().openapi({
+    vestingStartDate: z.string().datetime().nullable().openapi({
       description: "Vesting Start Date",
       example: "1970-01-01T00:00:00.000Z",
     }),

From 93e264a3ed1615afadeb07e3988bd9f1b8b5b16b Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Wed, 10 Jul 2024 12:26:38 +0530
Subject: [PATCH 08/40] feat: create getPaginatedShares method

---
 src/server/services/shares/getShares.ts | 42 +++++++++++++++++++++++++
 1 file changed, 42 insertions(+)
 create mode 100644 src/server/services/shares/getShares.ts

diff --git a/src/server/services/shares/getShares.ts b/src/server/services/shares/getShares.ts
new file mode 100644
index 000000000..095f8aa3b
--- /dev/null
+++ b/src/server/services/shares/getShares.ts
@@ -0,0 +1,42 @@
+import { ProxyPrismaModel } from "@/server/api/pagination/prisma-proxy";
+import { db } from "@/server/db";
+
+type GetPaginatedShares = {
+  companyId: string;
+  limit: number;
+  cursor?: string;
+  total?: number;
+};
+
+export const getPaginatedShares = async (payload: GetPaginatedShares) => {
+  const queryCriteria = {
+    where: {
+      companyId: payload.companyId,
+    },
+    orderBy: {
+      createdAt: "desc",
+    },
+  };
+
+  const paginationData = {
+    limit: payload.limit,
+    cursor: payload.cursor,
+    total: payload.total,
+  };
+
+  const prismaModel = ProxyPrismaModel(db.share);
+
+  const { data, count, total, cursor } = await prismaModel.findManyPaginated(
+    queryCriteria,
+    paginationData,
+  );
+
+  return {
+    data,
+    meta: {
+      count,
+      total,
+      cursor,
+    },
+  };
+};

From edeb00f2ebe8f31781b071f7ca0f29a65d549ee5 Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Wed, 10 Jul 2024 12:27:39 +0530
Subject: [PATCH 09/40] feat: create getMany routes

---
 .../api/routes/company/share/getMany.ts       | 80 +++++++++++++++++++
 1 file changed, 80 insertions(+)
 create mode 100644 src/server/api/routes/company/share/getMany.ts

diff --git a/src/server/api/routes/company/share/getMany.ts b/src/server/api/routes/company/share/getMany.ts
new file mode 100644
index 000000000..1dedc58a6
--- /dev/null
+++ b/src/server/api/routes/company/share/getMany.ts
@@ -0,0 +1,80 @@
+import { withCompanyAuth } from "@/server/api/auth";
+import { ErrorResponses } from "@/server/api/error";
+import type { PublicAPI } from "@/server/api/hono";
+import {
+  PaginationQuerySchema,
+  PaginationResponseSchema,
+} from "@/server/api/schema/pagination";
+import { ShareSchema } from "@/server/api/schema/shares";
+import { getPaginatedShares } from "@/server/services/shares/getShares";
+import { createRoute, z } from "@hono/zod-openapi";
+import type { Context } from "hono";
+
+const ParamsSchema = z.object({
+  id: z
+    .string()
+    .cuid()
+    .openapi({
+      description: "Company ID",
+      param: {
+        name: "id",
+        in: "path",
+      },
+
+      example: "clxwbok580000i7nge8nm1ry0",
+    }),
+});
+
+const ResponseSchema = z
+  .object({
+    data: z.array(ShareSchema),
+    meta: PaginationResponseSchema,
+  })
+  .openapi({
+    description: "Get Shares by Company ID",
+  });
+
+const route = createRoute({
+  method: "get",
+  path: "/v1/companies/{id}/shares",
+  request: {
+    params: ParamsSchema,
+    query: PaginationQuerySchema,
+  },
+  responses: {
+    200: {
+      content: {
+        "application/json": {
+          schema: ResponseSchema,
+        },
+      },
+      description: "Retrieve the share for the company",
+    },
+    ...ErrorResponses,
+  },
+});
+
+const getMany = (app: PublicAPI) => {
+  app.openapi(route, async (c: Context) => {
+    const { company } = await withCompanyAuth(c);
+
+    const { limit, cursor, total } = c.req.query();
+
+    const { data, meta } = await getPaginatedShares({
+      companyId: company.id,
+      limit: Number(limit),
+      cursor,
+      total: Number(total),
+    });
+
+    return c.json(
+      {
+        data,
+        meta,
+      },
+      200,
+    );
+  });
+};
+
+export default getMany;

From f8be63b8a9e6a7c20cb6d43d2b07a90b17b8d647 Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Wed, 10 Jul 2024 12:28:51 +0530
Subject: [PATCH 10/40] feat: integrate getMany route in shareRoutes

---
 src/server/api/routes/company/share/index.ts | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/server/api/routes/company/share/index.ts b/src/server/api/routes/company/share/index.ts
index 929b30ab7..e941a5229 100644
--- a/src/server/api/routes/company/share/index.ts
+++ b/src/server/api/routes/company/share/index.ts
@@ -1,8 +1,10 @@
 import type { PublicAPI } from "@/server/api/hono";
+import getMany from "./getMany";
 import getOne from "./getOne";
 
 const shareRoutes = (api: PublicAPI) => {
   getOne(api);
+  getMany(api);
 };
 
 export default shareRoutes;

From fc14896ab29cda08d288d2683f7005e112159261 Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Wed, 10 Jul 2024 14:44:54 +0530
Subject: [PATCH 11/40] feat: create AddShareSchema

---
 src/server/api/schema/shares.ts | 103 ++++++++++++++++++++++++++++++++
 1 file changed, 103 insertions(+)

diff --git a/src/server/api/schema/shares.ts b/src/server/api/schema/shares.ts
index cc48d6275..1f5ec353a 100644
--- a/src/server/api/schema/shares.ts
+++ b/src/server/api/schema/shares.ts
@@ -128,3 +128,106 @@ export const ShareSchema = z
   });
 
 export type TShareSchema = z.infer<typeof ShareSchema>;
+
+export const AddShareSchema = z
+  .object({
+    status: z.enum(SecuritiesStatusArr).openapi({
+      description: "Security Status",
+      example: "DRAFT",
+    }),
+
+    certificateId: z.string().openapi({
+      description: "Certificate ID",
+      example: "cly13ipa40000i7ng42mv4x7b",
+    }),
+
+    quantity: z.number().min(0).openapi({
+      description: "Quantity of Shares",
+      example: 234,
+    }),
+
+    pricePerShare: z.number().min(0).openapi({
+      description: "Price Per Share",
+      example: 23.4,
+    }),
+
+    capitalContribution: z.number().min(0).openapi({
+      description: "Total amount of money contributed",
+      example: 25.4,
+    }),
+
+    ipContribution: z.number().min(0).openapi({
+      description: "Value of the intellectual property contributed",
+      example: 43.4,
+    }),
+
+    debtCancelled: z.number().min(0).openapi({
+      description: "Amount of debt cancelled",
+      example: 54.54,
+    }),
+
+    otherContributions: z.number().min(0).openapi({
+      description: "Other contributions",
+      example: 45.54,
+    }),
+
+    vestingSchedule: z.enum(VestingScheduleArr).openapi({
+      description: "Vesting Schedule",
+      example: "VESTING_0_0_0",
+    }),
+
+    companyLegends: z
+      .enum(ShareLegendsArr)
+      .array()
+      .openapi({
+        description: "Company Legends",
+        example: ["US_SECURITIES_ACT", "SALE_AND_ROFR"],
+      }),
+
+    issueDate: z.string().datetime().openapi({
+      description: "Issued Date",
+      example: "1970-01-01T00:00:00.000Z",
+    }),
+
+    rule144Date: z.string().datetime().openapi({
+      description: "Rule 144 Date",
+      example: "1970-01-01T00:00:00.000Z",
+    }),
+
+    vestingStartDate: z.string().datetime().openapi({
+      description: "Vesting Start Date",
+      example: "1970-01-01T00:00:00.000Z",
+    }),
+
+    boardApprovalDate: z.string().datetime().openapi({
+      description: "Board Approval Date",
+      example: "1970-01-01T00:00:00.000Z",
+    }),
+
+    stakeholderId: z.string().cuid().openapi({
+      description: "StakeHolder ID",
+      example: "clydxglyl0000d94ff363egje",
+    }),
+
+    shareClassId: z.string().cuid().openapi({
+      description: "ShareClass ID",
+      example: "clycjzdqo000cjvsqr9rn6479",
+    }),
+
+    documents: z
+      .array(
+        z.object({
+          bucketId: z.string(),
+          name: z.string(),
+        }),
+      )
+      .openapi({
+        description: "Uploaded Documents",
+        example: [{ bucketId: "vbhjewhvjvj3", name: "Bucket Blue" }],
+      }),
+  })
+  .openapi({
+    description: "Create a Share",
+  });
+
+export type TAddShareSchema = z.infer<typeof AddShareSchema>;

From d92d789c9d2fa87244f8594278ff7c5397a2a2bd Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Wed, 10 Jul 2024 14:45:54 +0530
Subject: [PATCH 12/40] feat: create addShare function

---
 src/server/services/shares/addShare.ts | 65 ++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)
 create mode 100644 src/server/services/shares/addShare.ts

diff --git a/src/server/services/shares/addShare.ts b/src/server/services/shares/addShare.ts
new file mode 100644
index 000000000..dfd55e9f1
--- /dev/null
+++ b/src/server/services/shares/addShare.ts
@@ -0,0 +1,65 @@
+import { generatePublicId } from "@/common/id";
+import { db } from "@/server/db";
+import type { TypeZodAddShareMutationSchema } from "@/trpc/routers/securities-router/schema";
+
+interface AddShareType extends TypeZodAddShareMutationSchema {
+  companyId: string;
+  memberId: string;
+}
+
+export const addShare = async (input: AddShareType) => {
+  try {
+    await db.$transaction(async (tx) => {
+      const documents = input.documents;
+
+      const data = {
+        companyId: input.companyId,
+        stakeholderId: input.stakeholderId,
+        shareClassId: input.shareClassId,
+        status: input.status,
+        certificateId: input.certificateId,
+        quantity: input.quantity,
+        pricePerShare: input.pricePerShare,
+        capitalContribution: input.capitalContribution,
+        ipContribution: input.ipContribution,
+        debtCancelled: input.debtCancelled,
+        otherContributions: input.otherContributions,
+        vestingSchedule: input.vestingSchedule,
+        companyLegends: input.companyLegends,
+        issueDate: new Date(input.issueDate),
+        rule144Date: new Date(input.rule144Date),
+        vestingStartDate: new Date(input.vestingStartDate),
+        boardApprovalDate: new Date(input.boardApprovalDate),
+      };
+
+      console.log("The data inside addShare is :", input);
+
+      const share = await tx.share.create({ data });
+
+      const bulkDocuments = documents.map((doc) => ({
+        companyId: input.companyId,
+        uploaderId: input.memberId,
+        publicId: generatePublicId(),
+        name: doc.name,
+        bucketId: doc.bucketId,
+        shareId: share.id,
+      }));
+
+      await tx.document.createMany({
+        data: bulkDocuments,
+        skipDuplicates: true,
+      });
+    });
+
+    return {
+      success: true,
+      message: "🎉 Successfully added a share",
+    };
+  } catch (error) {
+    console.error("Error adding shares: ", error);
+    return {
+      success: false,
+      message: "Please use unique Certificate Id.",
+    };
+  }
+};

From 8b7b57097bf99657ae71f1a4f142f0e1c9cf0a30 Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Wed, 10 Jul 2024 14:52:01 +0530
Subject: [PATCH 13/40] feat: add createShare route

---
 src/server/api/routes/company/share/create.ts | 82 +++++++++++++++++++
 1 file changed, 82 insertions(+)
 create mode 100644 src/server/api/routes/company/share/create.ts

diff --git a/src/server/api/routes/company/share/create.ts b/src/server/api/routes/company/share/create.ts
new file mode 100644
index 000000000..00eee8c4e
--- /dev/null
+++ b/src/server/api/routes/company/share/create.ts
@@ -0,0 +1,82 @@
+import { withCompanyAuth } from "@/server/api/auth";
+import { ApiError, ErrorResponses } from "@/server/api/error";
+import type { PublicAPI } from "@/server/api/hono";
+import { AddShareSchema } from "@/server/api/schema/shares";
+import { addShare } from "@/server/services/shares/addShare";
+import { createRoute, z } from "@hono/zod-openapi";
+import type { Context } from "hono";
+
+const ParamsSchema = z.object({
+  id: z
+    .string()
+    .cuid()
+    .openapi({
+      description: "Company ID",
+      param: {
+        name: "id",
+        in: "path",
+      },
+
+      example: "clycjihpy0002c5fzcyf4gjjc",
+    }),
+});
+
+const ResponseSchema = z.object({
+  data: z.string(),
+});
+
+const route = createRoute({
+  method: "post",
+  path: "/v1/companies/{id}/shares",
+  request: {
+    params: ParamsSchema,
+    body: {
+      content: {
+        "application/json": {
+          schema: AddShareSchema,
+        },
+      },
+    },
+  },
+  responses: {
+    200: {
+      content: {
+        "application/json": {
+          schema: ResponseSchema,
+        },
+      },
+      description: "Created the Share Successfully",
+    },
+    ...ErrorResponses,
+  },
+});
+
+const create = (app: PublicAPI) => {
+  app.openapi(route, async (c: Context) => {
+    const { company, member } = await withCompanyAuth(c);
+
+    const body = await c.req.json();
+
+    const { success } = await addShare({
+      ...body,
+      companyId: company.id,
+      memberId: member.id,
+    });
+
+    if (!success) {
+      throw new ApiError({
+        code: "INTERNAL_SERVER_ERROR",
+        message: "Something went wrong, Please try again Later",
+      });
+    }
+
+    return c.json(
+      {
+        data: "Created the Share Successfully",
+      },
+      200,
+    );
+  });
+};
+
+export default create;

From 7fab72647d459cac9200fee0ea506653c2d2b3cf Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Wed, 10 Jul 2024 14:53:23 +0530
Subject: [PATCH 14/40] feat: integrate createShare route in shareRoutes

---
 src/server/api/routes/company/share/index.ts | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/server/api/routes/company/share/index.ts b/src/server/api/routes/company/share/index.ts
index e941a5229..1d6b8ef6c 100644
--- a/src/server/api/routes/company/share/index.ts
+++ b/src/server/api/routes/company/share/index.ts
@@ -1,10 +1,12 @@
 import type { PublicAPI } from "@/server/api/hono";
+import create from "./create";
 import getMany from "./getMany";
 import getOne from "./getOne";
 
 const shareRoutes = (api: PublicAPI) => {
   getOne(api);
   getMany(api);
+  create(api);
 };
 
 export default shareRoutes;

From 2b76e58a5fdea8117a9b99f1cca88c5bbc9e9269 Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Wed, 10 Jul 2024 16:57:39 +0530
Subject: [PATCH 15/40] feat: Audit the addShare action

---
 src/server/api/routes/company/share/create.ts | 12 ++++++++++-
 src/server/services/shares/addShare.ts        | 20 +++++++++++++++++++
 2 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/src/server/api/routes/company/share/create.ts b/src/server/api/routes/company/share/create.ts
index 00eee8c4e..a92ae0f3d 100644
--- a/src/server/api/routes/company/share/create.ts
+++ b/src/server/api/routes/company/share/create.ts
@@ -53,14 +53,24 @@ const route = createRoute({
 
 const create = (app: PublicAPI) => {
   app.openapi(route, async (c: Context) => {
-    const { company, member } = await withCompanyAuth(c);
+    const { company, member, user } = await withCompanyAuth(c);
 
     const body = await c.req.json();
 
+    const requestIP =
+      c.req.header("x-forwarded-for") ||
+      c.req.header("remoteAddr") ||
+      "Unknown IP";
+    const userAgent = c.req.header("User-Agent") || "";
+
     const { success } = await addShare({
       ...body,
       companyId: company.id,
       memberId: member.id,
+      requestIP,
+      userAgent,
+      userId: user.id,
+      userName: user.name,
     });
 
     if (!success) {
diff --git a/src/server/services/shares/addShare.ts b/src/server/services/shares/addShare.ts
index dfd55e9f1..586669577 100644
--- a/src/server/services/shares/addShare.ts
+++ b/src/server/services/shares/addShare.ts
@@ -1,10 +1,15 @@
 import { generatePublicId } from "@/common/id";
+import { Audit } from "@/server/audit";
 import { db } from "@/server/db";
 import type { TypeZodAddShareMutationSchema } from "@/trpc/routers/securities-router/schema";
 
 interface AddShareType extends TypeZodAddShareMutationSchema {
   companyId: string;
   memberId: string;
+  requestIP: string;
+  userAgent: string;
+  userId: string;
+  userName: string;
 }
 
 export const addShare = async (input: AddShareType) => {
@@ -49,6 +54,21 @@ export const addShare = async (input: AddShareType) => {
         data: bulkDocuments,
         skipDuplicates: true,
       });
+
+      await Audit.create(
+        {
+          action: "share.created",
+          companyId: input.companyId,
+          actor: { type: "user", id: input.userId },
+          context: {
+            userAgent: input.userAgent,
+            requestIp: input.requestIP,
+          },
+          target: [{ type: "share", id: share.id }],
+          summary: `${input.userName} added share for stakeholder ${input.stakeholderId}`,
+        },
+        tx,
+      );
     });
 
     return {

From c596d907dfb01c51041af782f29ff95fb36f8b49 Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Wed, 10 Jul 2024 18:45:25 +0530
Subject: [PATCH 16/40] feat: add UpdateShareSchema

---
 src/server/api/schema/shares.ts | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/server/api/schema/shares.ts b/src/server/api/schema/shares.ts
index 1f5ec353a..c837e42cd 100644
--- a/src/server/api/schema/shares.ts
+++ b/src/server/api/schema/shares.ts
@@ -231,3 +231,8 @@ export const AddShareSchema = z
   });
 
 export type TAddShareSchema = z.infer<typeof AddShareSchema>;
+
+export const UpdateShareSchema = AddShareSchema.omit({
+  documents: true,
+}).partial();
+export type TUpdateShareSchema = z.infer<typeof UpdateShareSchema>;

From 74a5bc6773e0acbcd5ef0eaa2fa47134f1146f0b Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Wed, 10 Jul 2024 18:46:17 +0530
Subject: [PATCH 17/40] feat: export AddShareType

---
 src/server/services/shares/addShare.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/server/services/shares/addShare.ts b/src/server/services/shares/addShare.ts
index 586669577..4557e1a97 100644
--- a/src/server/services/shares/addShare.ts
+++ b/src/server/services/shares/addShare.ts
@@ -3,7 +3,7 @@ import { Audit } from "@/server/audit";
 import { db } from "@/server/db";
 import type { TypeZodAddShareMutationSchema } from "@/trpc/routers/securities-router/schema";
 
-interface AddShareType extends TypeZodAddShareMutationSchema {
+export interface AddShareType extends TypeZodAddShareMutationSchema {
   companyId: string;
   memberId: string;
   requestIP: string;

From 4a4b1d9abe123cc2c70c47531ab5c5ce819b16f1 Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Wed, 10 Jul 2024 18:58:11 +0530
Subject: [PATCH 18/40] feat: create updateShare method

---
 src/server/services/shares/updateShare.ts | 77 +++++++++++++++++++++++
 1 file changed, 77 insertions(+)
 create mode 100644 src/server/services/shares/updateShare.ts

diff --git a/src/server/services/shares/updateShare.ts b/src/server/services/shares/updateShare.ts
new file mode 100644
index 000000000..d96786fd3
--- /dev/null
+++ b/src/server/services/shares/updateShare.ts
@@ -0,0 +1,77 @@
+import { Audit } from "@/server/audit";
+import { db } from "@/server/db";
+import type { AddShareType } from "./addShare";
+
+interface UpdateShareType extends AddShareType {
+  shareId: string;
+}
+
+export const updateShare = async (input: UpdateShareType) => {
+  try {
+    const existingShare = await db.share.findUnique({
+      where: {
+        id: input.shareId,
+      },
+    });
+
+    if (!existingShare) {
+      return {
+        success: false,
+        message: "Enter Valid Share ID",
+      };
+    }
+
+    await db.$transaction(async (tx) => {
+      const data = {
+        companyId: input.companyId,
+        stakeholderId: input.stakeholderId,
+        shareClassId: input.shareClassId,
+        status: input.status,
+        certificateId: input.certificateId,
+        quantity: input.quantity,
+        pricePerShare: input.pricePerShare,
+        capitalContribution: input.capitalContribution,
+        ipContribution: input.ipContribution,
+        debtCancelled: input.debtCancelled,
+        otherContributions: input.otherContributions,
+        vestingSchedule: input.vestingSchedule,
+        companyLegends: input.companyLegends,
+        issueDate: new Date(input.issueDate),
+        rule144Date: new Date(input.rule144Date),
+        vestingStartDate: new Date(input.vestingStartDate),
+        boardApprovalDate: new Date(input.boardApprovalDate),
+      };
+
+      const share = await tx.share.update({
+        where: { id: input.shareId },
+        data,
+      });
+
+      await Audit.create(
+        {
+          action: "share.updated",
+          companyId: input.companyId,
+          actor: { type: "user", id: input.userId },
+          context: {
+            userAgent: input.userAgent,
+            requestIp: input.requestIP,
+          },
+          target: [{ type: "share", id: share.id }],
+          summary: `${input.userName} updated share for stakeholder ${input.stakeholderId}`,
+        },
+        tx,
+      );
+    });
+
+    return {
+      success: true,
+      message: "🎉 Successfully Updated the share",
+    };
+  } catch (error) {
+    console.error("Error adding shares: ", error);
+    return {
+      success: false,
+      message: "Can't Update the Share now. Please try again later",
+    };
+  }
+};

From c3bd9e84557a3918da0571b46bd55808b3c004c5 Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Thu, 11 Jul 2024 10:44:36 +0530
Subject: [PATCH 19/40] feat: add updateShare route

---
 src/server/api/routes/company/share/update.ts | 116 ++++++++++++++++++
 1 file changed, 116 insertions(+)
 create mode 100644 src/server/api/routes/company/share/update.ts

diff --git a/src/server/api/routes/company/share/update.ts b/src/server/api/routes/company/share/update.ts
new file mode 100644
index 000000000..f71d53bd7
--- /dev/null
+++ b/src/server/api/routes/company/share/update.ts
@@ -0,0 +1,116 @@
+import { withCompanyAuth } from "@/server/api/auth";
+import { ApiError, ErrorResponses } from "@/server/api/error";
+import type { PublicAPI } from "@/server/api/hono";
+import { UpdateShareSchema } from "@/server/api/schema/shares";
+import { updateShare } from "@/server/services/shares/updateShare";
+import { createRoute, z } from "@hono/zod-openapi";
+import type { Context } from "hono";
+
+const ParamsSchema = z
+  .object({
+    id: z
+      .string()
+      .cuid()
+      .openapi({
+        description: "Company ID",
+        param: {
+          name: "id",
+          in: "path",
+        },
+
+        example: "clxwbok580000i7nge8nm1ry0",
+      }),
+    shareId: z
+      .string()
+      .cuid()
+      .openapi({
+        description: "Share ID",
+        param: {
+          name: "shareId",
+          in: "path",
+        },
+
+        example: "clyd3i9sw000008ij619eabva",
+      }),
+  })
+  .openapi({
+    description: "Update a Share by ID",
+  });
+
+const ResponseSchema = z
+  .object({
+    data: z.string(),
+  })
+  .openapi({
+    description: "Update a Share by ID",
+  });
+
+const route = createRoute({
+  method: "put",
+  path: "/v1/companies/{id}/shares/{shareId}",
+  request: {
+    params: ParamsSchema,
+    body: {
+      content: {
+        "application/json": {
+          schema: UpdateShareSchema,
+        },
+      },
+    },
+  },
+  responses: {
+    200: {
+      content: {
+        "application/json": {
+          schema: ResponseSchema,
+        },
+      },
+      description: "Retrieve the share for the company",
+    },
+    ...ErrorResponses,
+  },
+});
+
+const getOne = (app: PublicAPI) => {
+  app.openapi(route, async (c: Context) => {
+    //TODO : CHECK THIS PROPERLT
+
+    const { company, user, member } = await withCompanyAuth(c);
+
+    const { shareId: id } = c.req.param();
+
+    const body = await c.req.json();
+    const requestIP =
+      c.req.header("x-forwarded-for") ||
+      c.req.header("remoteAddr") ||
+      "Unknown IP";
+    const userAgent = c.req.header("User-Agent") || "";
+
+    const { success, message } = await updateShare({
+      ...body,
+      companyId: company.id,
+      memberId: member.id,
+      requestIP,
+      userAgent,
+      userId: user.id,
+      userName: user.name,
+      shareId: id,
+    });
+
+    if (!success) {
+      throw new ApiError({
+        code: "BAD_REQUEST",
+        message,
+      });
+    }
+
+    return c.json(
+      {
+        data: "Successfully Updated the Share",
+      },
+      200,
+    );
+  });
+};
+
+export default getOne;

From 219eb01810e21d4d1b8822e3ccbdc72f3b65b153 Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Thu, 11 Jul 2024 10:45:10 +0530
Subject: [PATCH 20/40] feat: integrate updateShare route

---
 src/server/api/routes/company/share/index.ts | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/server/api/routes/company/share/index.ts b/src/server/api/routes/company/share/index.ts
index 1d6b8ef6c..aae290e01 100644
--- a/src/server/api/routes/company/share/index.ts
+++ b/src/server/api/routes/company/share/index.ts
@@ -2,11 +2,13 @@ import type { PublicAPI } from "@/server/api/hono";
 import create from "./create";
 import getMany from "./getMany";
 import getOne from "./getOne";
+import update from "./update";
 
 const shareRoutes = (api: PublicAPI) => {
   getOne(api);
   getMany(api);
   create(api);
+  update(api);
 };
 
 export default shareRoutes;

From 786baa8525906fdae3d1d920052aede3f1c49acf Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Thu, 11 Jul 2024 11:37:35 +0530
Subject: [PATCH 21/40] feat: add deleteShare function

---
 src/server/services/shares/deleteShare.ts | 75 +++++++++++++++++++++++
 1 file changed, 75 insertions(+)
 create mode 100644 src/server/services/shares/deleteShare.ts

diff --git a/src/server/services/shares/deleteShare.ts b/src/server/services/shares/deleteShare.ts
new file mode 100644
index 000000000..3113baa84
--- /dev/null
+++ b/src/server/services/shares/deleteShare.ts
@@ -0,0 +1,75 @@
+import { Audit } from "@/server/audit";
+import { db } from "@/server/db";
+
+interface DeleteShareType {
+  user: {
+    id: string;
+    name: string;
+  };
+  shareId: string;
+  companyId: string;
+  userAgent: string;
+  requestIp: string;
+}
+
+export const deleteShare = async ({
+  shareId,
+  companyId,
+  requestIp,
+  userAgent,
+  user,
+}: DeleteShareType) => {
+  try {
+    const existingShare = await db.share.findUnique({
+      where: {
+        id: shareId,
+      },
+    });
+
+    if (!existingShare) {
+      return {
+        success: false,
+        message: "Enter Valid Share ID",
+      };
+    }
+
+    const share = await db.$transaction(async (tx) => {
+      const share = await tx.share.delete({
+        where: {
+          id: shareId,
+        },
+      });
+
+      const { stakeholderId } = share;
+
+      await Audit.create(
+        {
+          action: "share.deleted",
+          companyId,
+          actor: { type: "user", id: user.id },
+          context: {
+            userAgent,
+            requestIp,
+          },
+          target: [{ type: "share", id: shareId }],
+          summary: `${user.name} Deleted the share for stakeholder ${stakeholderId}`,
+        },
+        tx,
+      );
+
+      return share;
+    });
+
+    return {
+      success: true,
+      message: "🎉 Successfully Deleted the share",
+      share,
+    };
+  } catch (error) {
+    console.error("Error Deleting the share: ", error);
+    return {
+      success: false,
+      message: "Can't Delete the Share now. Please try again later",
+    };
+  }
+};

From 07fe412c9547e98c726bf99b670e11abfea0bb10 Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Thu, 11 Jul 2024 11:38:00 +0530
Subject: [PATCH 22/40] feat: add deleteShare route

---
 src/server/api/routes/company/share/delete.ts | 105 ++++++++++++++++++
 1 file changed, 105 insertions(+)
 create mode 100644 src/server/api/routes/company/share/delete.ts

diff --git a/src/server/api/routes/company/share/delete.ts b/src/server/api/routes/company/share/delete.ts
new file mode 100644
index 000000000..338c1fb46
--- /dev/null
+++ b/src/server/api/routes/company/share/delete.ts
@@ -0,0 +1,105 @@
+import { withCompanyAuth } from "@/server/api/auth";
+import { ApiError, ErrorResponses } from "@/server/api/error";
+import type { PublicAPI } from "@/server/api/hono";
+import { ShareSchema } from "@/server/api/schema/shares";
+import { deleteShare } from "@/server/services/shares/deleteShare";
+import { createRoute, z } from "@hono/zod-openapi";
+import type { Context } from "hono";
+
+const ParamsSchema = z
+  .object({
+    id: z
+      .string()
+      .cuid()
+      .openapi({
+        description: "Company ID",
+        param: {
+          name: "id",
+          in: "path",
+        },
+
+        example: "clxwbok580000i7nge8nm1ry0",
+      }),
+    shareId: z
+      .string()
+      .cuid()
+      .openapi({
+        description: "Share ID",
+        param: {
+          name: "shareId",
+          in: "path",
+        },
+
+        example: "clyd3i9sw000008ij619eabva",
+      }),
+  })
+  .openapi({
+    description: "Delete a Share by ID",
+  });
+
+const ResponseSchema = z
+  .object({
+    message: z.string(),
+    data: ShareSchema.optional(),
+  })
+  .openapi({
+    description: "Delete a Share by ID",
+  });
+
+const route = createRoute({
+  method: "delete",
+  path: "/v1/companies/{id}/shares/{shareId}",
+  request: {
+    params: ParamsSchema,
+  },
+  responses: {
+    200: {
+      content: {
+        "application/json": {
+          schema: ResponseSchema,
+        },
+      },
+      description: "Delete a Share by ID",
+    },
+    ...ErrorResponses,
+  },
+});
+
+const delete_ = (app: PublicAPI) => {
+  app.openapi(route, async (c: Context) => {
+    const { company, user } = await withCompanyAuth(c);
+
+    const { shareId: id } = c.req.param();
+
+    const requestIP =
+      c.req.header("x-forwarded-for") ||
+      c.req.header("remoteAddr") ||
+      "Unknown IP";
+    const userAgent = c.req.header("User-Agent") || "";
+
+    const { success, message, share } = await deleteShare({
+      companyId: company.id,
+      requestIp: requestIP,
+      userAgent,
+      shareId: id as string,
+      user: { id: user.id, name: user.name || "" },
+    });
+
+    if (!success && !share) {
+      throw new ApiError({
+        code: "BAD_REQUEST",
+        message,
+      });
+    }
+
+    return c.json(
+      {
+        message: "Successfully Deleted the Share",
+        data: share,
+      },
+      200,
+    );
+  });
+};
+
+export default delete_;

From 8d753ac7abde6cc4a44138883a780ed12ed67d0a Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Thu, 11 Jul 2024 11:38:57 +0530
Subject: [PATCH 23/40] feat: integrate deleteRoute in shareRoutes

---
 src/server/api/routes/company/share/index.ts | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/server/api/routes/company/share/index.ts b/src/server/api/routes/company/share/index.ts
index aae290e01..9450d7ef1 100644
--- a/src/server/api/routes/company/share/index.ts
+++ b/src/server/api/routes/company/share/index.ts
@@ -1,5 +1,6 @@
 import type { PublicAPI } from "@/server/api/hono";
 import create from "./create";
+import delete_ from "./delete";
 import getMany from "./getMany";
 import getOne from "./getOne";
 import update from "./update";
@@ -9,6 +10,7 @@ const shareRoutes = (api: PublicAPI) => {
   getMany(api);
   create(api);
   update(api);
+  delete_(api);
 };
 
 export default shareRoutes;

From cce66e505e13654bdcadfe700b4f38dd96c4a404 Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Thu, 11 Jul 2024 11:40:19 +0530
Subject: [PATCH 24/40] feat: call shareRoutes in index

---
 src/server/api/index.ts | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/server/api/index.ts b/src/server/api/index.ts
index a6165b81d..08dfd5b5d 100644
--- a/src/server/api/index.ts
+++ b/src/server/api/index.ts
@@ -1,9 +1,13 @@
 import { PublicAPI } from "./hono";
 import companyRoutes from "./routes/company";
+import shareRoutes from "./routes/company/share";
 
 export const api = PublicAPI();
 
 // RESTful routes for company
 companyRoutes(api);
 
+// RESTful routes for shares
+shareRoutes(api);
+
 export default api;

From 1f7a611fedd246215c45415565c9d83e25fe4d34 Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Thu, 11 Jul 2024 12:45:16 +0530
Subject: [PATCH 25/40] chore: cleanup types

---
 src/server/api/routes/company/share/create.ts |  6 ++++--
 src/server/api/routes/company/share/update.ts |  2 --
 src/server/services/shares/addShare.ts        | 10 ++++++----
 src/server/services/shares/updateShare.ts     |  4 ++--
 4 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/src/server/api/routes/company/share/create.ts b/src/server/api/routes/company/share/create.ts
index a92ae0f3d..0d180d7ac 100644
--- a/src/server/api/routes/company/share/create.ts
+++ b/src/server/api/routes/company/share/create.ts
@@ -69,8 +69,10 @@ const create = (app: PublicAPI) => {
       memberId: member.id,
       requestIP,
       userAgent,
-      userId: user.id,
-      userName: user.name,
+      user: {
+        id: user.id,
+        name: user.name,
+      },
     });
 
     if (!success) {
diff --git a/src/server/api/routes/company/share/update.ts b/src/server/api/routes/company/share/update.ts
index f71d53bd7..40dae5313 100644
--- a/src/server/api/routes/company/share/update.ts
+++ b/src/server/api/routes/company/share/update.ts
@@ -73,8 +73,6 @@ const route = createRoute({
 
 const getOne = (app: PublicAPI) => {
   app.openapi(route, async (c: Context) => {
-    //TODO : CHECK THIS PROPERLT
-
     const { company, user, member } = await withCompanyAuth(c);
 
     const { shareId: id } = c.req.param();
diff --git a/src/server/services/shares/addShare.ts b/src/server/services/shares/addShare.ts
index 4557e1a97..b46372fbb 100644
--- a/src/server/services/shares/addShare.ts
+++ b/src/server/services/shares/addShare.ts
@@ -8,8 +8,10 @@ export interface AddShareType extends TypeZodAddShareMutationSchema {
   memberId: string;
   requestIP: string;
   userAgent: string;
-  userId: string;
-  userName: string;
+  user: {
+    id: string;
+    name: string;
+  };
 }
 
 export const addShare = async (input: AddShareType) => {
@@ -59,13 +61,13 @@ export const addShare = async (input: AddShareType) => {
         {
           action: "share.created",
           companyId: input.companyId,
-          actor: { type: "user", id: input.userId },
+          actor: { type: "user", id: input.user.id },
           context: {
             userAgent: input.userAgent,
             requestIp: input.requestIP,
           },
           target: [{ type: "share", id: share.id }],
-          summary: `${input.userName} added share for stakeholder ${input.stakeholderId}`,
+          summary: `${input.user.name} added share for stakeholder ${input.stakeholderId}`,
         },
         tx,
       );
diff --git a/src/server/services/shares/updateShare.ts b/src/server/services/shares/updateShare.ts
index d96786fd3..dfacf67ed 100644
--- a/src/server/services/shares/updateShare.ts
+++ b/src/server/services/shares/updateShare.ts
@@ -51,13 +51,13 @@ export const updateShare = async (input: UpdateShareType) => {
         {
           action: "share.updated",
           companyId: input.companyId,
-          actor: { type: "user", id: input.userId },
+          actor: { type: "user", id: input.user.id },
           context: {
             userAgent: input.userAgent,
             requestIp: input.requestIP,
           },
           target: [{ type: "share", id: share.id }],
-          summary: `${input.userName} updated share for stakeholder ${input.stakeholderId}`,
+          summary: `${input.user.name} updated share for stakeholder ${input.stakeholderId}`,
         },
         tx,
       );

From b6b135af321db95a426e06ded31cee188dd90c9e Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Thu, 11 Jul 2024 12:51:17 +0530
Subject: [PATCH 26/40] chore: minor cleanups

---
 src/server/api/routes/company/share/getMany.ts | 2 +-
 src/server/api/routes/company/share/update.ts  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/server/api/routes/company/share/getMany.ts b/src/server/api/routes/company/share/getMany.ts
index 1dedc58a6..b60423733 100644
--- a/src/server/api/routes/company/share/getMany.ts
+++ b/src/server/api/routes/company/share/getMany.ts
@@ -48,7 +48,7 @@ const route = createRoute({
           schema: ResponseSchema,
         },
       },
-      description: "Retrieve the share for the company",
+      description: "Retrieve the shares for the company",
     },
     ...ErrorResponses,
   },
diff --git a/src/server/api/routes/company/share/update.ts b/src/server/api/routes/company/share/update.ts
index 40dae5313..b46e549ee 100644
--- a/src/server/api/routes/company/share/update.ts
+++ b/src/server/api/routes/company/share/update.ts
@@ -65,7 +65,7 @@ const route = createRoute({
           schema: ResponseSchema,
         },
       },
-      description: "Retrieve the share for the company",
+      description: "Update the Share by ID",
     },
     ...ErrorResponses,
   },

From 4f2c7da35d0adc0fe29b949f52121652a83bf65a Mon Sep 17 00:00:00 2001
From: Vishnu Kumar <vishnukumart96@gmail.com>
Date: Tue, 16 Jul 2024 15:03:53 +0530
Subject: [PATCH 27/40] feat: add share endpoints in postman/collections

---
 postman/collection.json | 164 +++++++++++++++++++++++++++++++++++++---
 1 file changed, 154 insertions(+), 10 deletions(-)

diff --git a/postman/collection.json b/postman/collection.json
index 52173fe1a..4b4c695c5 100644
--- a/postman/collection.json
+++ b/postman/collection.json
@@ -1,9 +1,9 @@
 {
   "info": {
-    "_postman_id": "209da849-6850-40d0-a4bf-1b7d004be7ce",
+    "_postman_id": "844d3aaf-c30d-4fc2-be1f-e2f41e9fc5e9",
     "name": "Captable API (v1)",
     "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
-    "_exporter_id": "36586471"
+    "_exporter_id": "28023741"
   },
   "item": [
     {
@@ -90,7 +90,10 @@
           "name": "Get a team member",
           "request": {
             "method": "GET",
-            "header": []
+            "header": [],
+            "url": {
+              "raw": ""
+            }
           },
           "response": []
         },
@@ -98,7 +101,10 @@
           "name": "List team members",
           "request": {
             "method": "GET",
-            "header": []
+            "header": [],
+            "url": {
+              "raw": ""
+            }
           },
           "response": []
         },
@@ -106,7 +112,10 @@
           "name": "Create a team member",
           "request": {
             "method": "GET",
-            "header": []
+            "header": [],
+            "url": {
+              "raw": ""
+            }
           },
           "response": []
         },
@@ -114,7 +123,10 @@
           "name": "Update a team member",
           "request": {
             "method": "GET",
-            "header": []
+            "header": [],
+            "url": {
+              "raw": ""
+            }
           },
           "response": []
         }
@@ -127,7 +139,10 @@
           "name": "Get a stakeholder",
           "request": {
             "method": "GET",
-            "header": []
+            "header": [],
+            "url": {
+              "raw": ""
+            }
           },
           "response": []
         },
@@ -135,7 +150,10 @@
           "name": "List stakeholders",
           "request": {
             "method": "GET",
-            "header": []
+            "header": [],
+            "url": {
+              "raw": ""
+            }
           },
           "response": []
         },
@@ -143,7 +161,10 @@
           "name": "Create a stakeholder",
           "request": {
             "method": "GET",
-            "header": []
+            "header": [],
+            "url": {
+              "raw": ""
+            }
           },
           "response": []
         },
@@ -151,7 +172,130 @@
           "name": "Update a stakeholder",
           "request": {
             "method": "GET",
-            "header": []
+            "header": [],
+            "url": {
+              "raw": ""
+            }
+          },
+          "response": []
+        }
+      ]
+    },
+    {
+      "name": "Share",
+      "item": [
+        {
+          "name": "Get a Share",
+          "request": {
+            "auth": {
+              "type": "bearer",
+              "bearer": [
+                {
+                  "key": "token",
+                  "value": "{{bearerToken}}",
+                  "type": "string"
+                }
+              ]
+            },
+            "method": "GET",
+            "header": [],
+            "url": {
+              "raw": "{{baseUrl}}/companies/{{companyId}}/shares/{{shareId}}",
+              "host": ["{{baseUrl}}"],
+              "path": ["companies", "{{companyId}}", "shares", "{{shareId}}"]
+            }
+          },
+          "response": []
+        },
+        {
+          "name": "List Shares",
+          "request": {
+            "auth": {
+              "type": "bearer",
+              "bearer": [
+                {
+                  "key": "token",
+                  "value": "{{bearerToken}}",
+                  "type": "string"
+                }
+              ]
+            },
+            "method": "GET",
+            "header": [],
+            "url": {
+              "raw": "{{baseUrl}}/companies/{{companyId}}/shares",
+              "host": ["{{baseUrl}}"],
+              "path": ["companies", "{{companyId}}", "shares"]
+            }
+          },
+          "response": []
+        },
+        {
+          "name": "Create Share",
+          "request": {
+            "auth": {
+              "type": "bearer",
+              "bearer": [
+                {
+                  "key": "token",
+                  "value": "{{bearerToken}}",
+                  "type": "string"
+                }
+              ]
+            },
+            "method": "POST",
+            "header": [],
+            "url": {
+              "raw": "{{baseUrl}}/companies/{{companyId}}/shares",
+              "host": ["{{baseUrl}}"],
+              "path": ["companies", "{{companyId}}", "shares"]
+            }
+          },
+          "response": []
+        },
+        {
+          "name": "Update Share",
+          "request": {
+            "auth": {
+              "type": "bearer",
+              "bearer": [
+                {
+                  "key": "token",
+                  "value": "{{bearerToken}}",
+                  "type": "string"
+                }
+              ]
+            },
+            "method": "PUT",
+            "header": [],
+            "url": {
+              "raw": "{{baseUrl}}/companies/{{companyId}}/shares/{{shareId}}",
+              "host": ["{{baseUrl}}"],
+              "path": ["companies", "{{companyId}}", "shares", "{{shareId}}"]
+            }
+          },
+          "response": []
+        },
+        {
+          "name": "Delete Share",
+          "request": {
+            "auth": {
+              "type": "bearer",
+              "bearer": [
+                {
+                  "key": "token",
+                  "value": "{{bearerToken}}",
+                  "type": "string"
+                }
+              ]
+            },
+            "method": "DELETE",
+            "header": [],
+            "url": {
+              "raw": "{{baseUrl}}/companies/{{companyId}}/shares/{{shareId}}",
+              "host": ["{{baseUrl}}"],
+              "path": ["companies", "{{companyId}}", "shares", "{{shareId}}"]
+            }
           },
           "response": []
         }

From 4b29db1bc2aa3ffdc7e94ecd9f3f9c757140af2f Mon Sep 17 00:00:00 2001
From: Puru D <puru@dahal.me>
Date: Sat, 20 Jul 2024 02:14:35 -0500
Subject: [PATCH 28/40] feat: update api pagination stuff

---
 src/server/api/pagination/find-many.proxy.ts | 22 +++++++++-----------
 src/server/api/pagination/types.ts           |  2 +-
 src/server/api/schema/pagination.ts          | 21 ++++---------------
 3 files changed, 15 insertions(+), 30 deletions(-)

diff --git a/src/server/api/pagination/find-many.proxy.ts b/src/server/api/pagination/find-many.proxy.ts
index f1765fa98..51fe96f12 100644
--- a/src/server/api/pagination/find-many.proxy.ts
+++ b/src/server/api/pagination/find-many.proxy.ts
@@ -3,8 +3,8 @@ import type { PaginationData, ProxyFunctions } from "./types";
 interface Paginated<T> {
   data: T[];
   count: number;
-  total: number;
-  cursor?: string;
+  total: number | null;
+  cursor: string | null;
 }
 
 /**
@@ -29,32 +29,30 @@ export type FindManyPaginated<F extends ProxyFunctions> = {
 export function makeFindManyPaginated(model: ProxyFunctions) {
   return new Proxy(model.findMany, {
     apply: async (target, thisArg, [data, paginationInfo]) => {
-      const limit = paginationInfo?.limit;
+      const take = paginationInfo?.take;
       const cursor = paginationInfo?.cursor;
 
       const query = data || {};
-      query.take = limit;
+      query.take = take;
       if (cursor) {
         query.cursor = { id: cursor }; // Assuming `id` is the cursor field
         query.skip = 1; // Skip the cursor item itself
       }
 
-      const total =
-        paginationInfo?.total ||
-        (await model.count({
-          where: query.where,
-        }));
+      const totalCount = await model.count({
+        where: query.where,
+      });
 
       //@ts-ignore
       const docs = await target.apply(thisArg, [query]);
 
-      const nextCursor =
-        docs.length === limit ? docs[docs.length - 1].id : null; // Assuming `id` is the cursor field
+      const nextCursor = docs.length === take ? docs[docs.length - 1].id : null; // Assuming `id` is the cursor field
 
       return {
         data: docs,
         count: docs.length,
-        total,
+        // Send totalCount only for first request, let client side manages it for subsequent requests.
+        total: totalCount,
         cursor: nextCursor,
       };
     },
diff --git a/src/server/api/pagination/types.ts b/src/server/api/pagination/types.ts
index c6f6c70d3..7a807219a 100644
--- a/src/server/api/pagination/types.ts
+++ b/src/server/api/pagination/types.ts
@@ -2,7 +2,7 @@
  * Pagination information
  */
 export type PaginationData = {
-  limit: number;
+  take: number;
   cursor?: string;
 };
 
diff --git a/src/server/api/schema/pagination.ts b/src/server/api/schema/pagination.ts
index baeba0e66..a2ad992ab 100644
--- a/src/server/api/schema/pagination.ts
+++ b/src/server/api/schema/pagination.ts
@@ -15,12 +15,13 @@ export const PaginationQuerySchema = z.object({
       },
       example: 10,
       default: 10,
-      minimum: 5,
+      minimum: 1,
       maximum: 50,
     }),
 
   cursor: z
     .string()
+    .cuid()
     .optional()
     .openapi({
       description: "Cursor for the next page",
@@ -30,20 +31,6 @@ export const PaginationQuerySchema = z.object({
       },
       example: "cly151kxq0000i7ngb3erchgo", // CUID of the last item
     }),
-
-  total: z
-    .preprocess(
-      (val) =>
-        val === undefined ? undefined : Number.parseInt(val as string, 10),
-      z.number().int().positive().optional(),
-    )
-    .openapi({
-      description: "Total Number of Records",
-      param: {
-        name: "total",
-        in: "query",
-      },
-    }),
 });
 
 export type TPaginationQuerySchema = z.infer<typeof PaginationQuerySchema>;
@@ -54,12 +41,12 @@ export const PaginationResponseSchema = z.object({
     example: 50,
   }),
 
-  total: z.number().int().positive().openapi({
+  total: z.number().int().positive().nullable().openapi({
     description: "Total number of records",
     example: 100,
   }),
 
-  cursor: z.string().optional().openapi({
+  cursor: z.string().nullable().openapi({
     description: "Next page cursor",
     example: "cly151kxq0000i7ngb3erchgo",
   }),

From e0f62d84cc089de0e4b16b861e390cd792fed5f3 Mon Sep 17 00:00:00 2001
From: Puru D <puru@dahal.me>
Date: Sat, 20 Jul 2024 01:58:16 -0500
Subject: [PATCH 29/40] feat: remove postman/collection

---
 postman/collection.json | 305 ----------------------------------------
 1 file changed, 305 deletions(-)
 delete mode 100644 postman/collection.json

diff --git a/postman/collection.json b/postman/collection.json
deleted file mode 100644
index 4b4c695c5..000000000
--- a/postman/collection.json
+++ /dev/null
@@ -1,305 +0,0 @@
-{
-  "info": {
-    "_postman_id": "844d3aaf-c30d-4fc2-be1f-e2f41e9fc5e9",
-    "name": "Captable API (v1)",
-    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
-    "_exporter_id": "28023741"
-  },
-  "item": [
-    {
-      "name": "Company",
-      "item": [
-        {
-          "name": "Get a company",
-          "request": {
-            "auth": {
-              "type": "bearer",
-              "bearer": [
-                {
-                  "key": "token",
-                  "value": "{{bearerToken}}",
-                  "type": "string"
-                }
-              ]
-            },
-            "method": "GET",
-            "header": [],
-            "url": {
-              "raw": "{{baseUrl}}/companies/{{companyId}}",
-              "host": ["{{baseUrl}}"],
-              "path": ["companies", "{{companyId}}"]
-            }
-          },
-          "response": []
-        },
-        {
-          "name": "List companies",
-          "request": {
-            "auth": {
-              "type": "bearer",
-              "bearer": [
-                {
-                  "key": "token",
-                  "value": "{{bearerToken}}",
-                  "type": "string"
-                }
-              ]
-            },
-            "method": "GET",
-            "header": [],
-            "url": {
-              "raw": "{{baseUrl}}/companies",
-              "host": ["{{baseUrl}}"],
-              "path": ["companies"]
-            }
-          },
-          "response": []
-        },
-        {
-          "name": "Create company",
-          "request": {
-            "method": "POST",
-            "header": [],
-            "url": {
-              "raw": "{{baseUrl}}/companies",
-              "host": ["{{baseUrl}}"],
-              "path": ["companies"]
-            }
-          },
-          "response": []
-        },
-        {
-          "name": "Update company",
-          "request": {
-            "method": "PUT",
-            "header": [],
-            "url": {
-              "raw": "{{baseUrl}}/companies/{{companyId}}",
-              "host": ["{{baseUrl}}"],
-              "path": ["companies", "{{companyId}}"]
-            }
-          },
-          "response": []
-        }
-      ]
-    },
-    {
-      "name": "Team",
-      "item": [
-        {
-          "name": "Get a team member",
-          "request": {
-            "method": "GET",
-            "header": [],
-            "url": {
-              "raw": ""
-            }
-          },
-          "response": []
-        },
-        {
-          "name": "List team members",
-          "request": {
-            "method": "GET",
-            "header": [],
-            "url": {
-              "raw": ""
-            }
-          },
-          "response": []
-        },
-        {
-          "name": "Create a team member",
-          "request": {
-            "method": "GET",
-            "header": [],
-            "url": {
-              "raw": ""
-            }
-          },
-          "response": []
-        },
-        {
-          "name": "Update a team member",
-          "request": {
-            "method": "GET",
-            "header": [],
-            "url": {
-              "raw": ""
-            }
-          },
-          "response": []
-        }
-      ]
-    },
-    {
-      "name": "Stakeholder",
-      "item": [
-        {
-          "name": "Get a stakeholder",
-          "request": {
-            "method": "GET",
-            "header": [],
-            "url": {
-              "raw": ""
-            }
-          },
-          "response": []
-        },
-        {
-          "name": "List stakeholders",
-          "request": {
-            "method": "GET",
-            "header": [],
-            "url": {
-              "raw": ""
-            }
-          },
-          "response": []
-        },
-        {
-          "name": "Create a stakeholder",
-          "request": {
-            "method": "GET",
-            "header": [],
-            "url": {
-              "raw": ""
-            }
-          },
-          "response": []
-        },
-        {
-          "name": "Update a stakeholder",
-          "request": {
-            "method": "GET",
-            "header": [],
-            "url": {
-              "raw": ""
-            }
-          },
-          "response": []
-        }
-      ]
-    },
-    {
-      "name": "Share",
-      "item": [
-        {
-          "name": "Get a Share",
-          "request": {
-            "auth": {
-              "type": "bearer",
-              "bearer": [
-                {
-                  "key": "token",
-                  "value": "{{bearerToken}}",
-                  "type": "string"
-                }
-              ]
-            },
-            "method": "GET",
-            "header": [],
-            "url": {
-              "raw": "{{baseUrl}}/companies/{{companyId}}/shares/{{shareId}}",
-              "host": ["{{baseUrl}}"],
-              "path": ["companies", "{{companyId}}", "shares", "{{shareId}}"]
-            }
-          },
-          "response": []
-        },
-        {
-          "name": "List Shares",
-          "request": {
-            "auth": {
-              "type": "bearer",
-              "bearer": [
-                {
-                  "key": "token",
-                  "value": "{{bearerToken}}",
-                  "type": "string"
-                }
-              ]
-            },
-            "method": "GET",
-            "header": [],
-            "url": {
-              "raw": "{{baseUrl}}/companies/{{companyId}}/shares",
-              "host": ["{{baseUrl}}"],
-              "path": ["companies", "{{companyId}}", "shares"]
-            }
-          },
-          "response": []
-        },
-        {
-          "name": "Create Share",
-          "request": {
-            "auth": {
-              "type": "bearer",
-              "bearer": [
-                {
-                  "key": "token",
-                  "value": "{{bearerToken}}",
-                  "type": "string"
-                }
-              ]
-            },
-            "method": "POST",
-            "header": [],
-            "url": {
-              "raw": "{{baseUrl}}/companies/{{companyId}}/shares",
-              "host": ["{{baseUrl}}"],
-              "path": ["companies", "{{companyId}}", "shares"]
-            }
-          },
-          "response": []
-        },
-        {
-          "name": "Update Share",
-          "request": {
-            "auth": {
-              "type": "bearer",
-              "bearer": [
-                {
-                  "key": "token",
-                  "value": "{{bearerToken}}",
-                  "type": "string"
-                }
-              ]
-            },
-            "method": "PUT",
-            "header": [],
-            "url": {
-              "raw": "{{baseUrl}}/companies/{{companyId}}/shares/{{shareId}}",
-              "host": ["{{baseUrl}}"],
-              "path": ["companies", "{{companyId}}", "shares", "{{shareId}}"]
-            }
-          },
-          "response": []
-        },
-        {
-          "name": "Delete Share",
-          "request": {
-            "auth": {
-              "type": "bearer",
-              "bearer": [
-                {
-                  "key": "token",
-                  "value": "{{bearerToken}}",
-                  "type": "string"
-                }
-              ]
-            },
-            "method": "DELETE",
-            "header": [],
-            "url": {
-              "raw": "{{baseUrl}}/companies/{{companyId}}/shares/{{shareId}}",
-              "host": ["{{baseUrl}}"],
-              "path": ["companies", "{{companyId}}", "shares", "{{shareId}}"]
-            }
-          },
-          "response": []
-        }
-      ]
-    }
-  ]
-}

From e17e2fb93b50db18b1e4e38acebfa3c6d74da895 Mon Sep 17 00:00:00 2001
From: Puru D <puru@dahal.me>
Date: Sat, 20 Jul 2024 04:31:22 -0500
Subject: [PATCH 30/40] fix: issues during issueing a share, and some openapi
 specs

---
 src/server/api/pagination/find-many.proxy.ts  |  1 -
 src/server/api/routes/company/share/create.ts |  9 ++++---
 src/server/api/routes/company/share/delete.ts |  3 +++
 .../api/routes/company/share/getMany.ts       |  3 +++
 src/server/api/routes/company/share/getOne.ts |  3 +++
 src/server/api/routes/company/share/update.ts |  3 +++
 src/server/api/schema/shares.ts               | 22 ++++++++--------
 src/server/services/shares/addShare.ts        | 26 ++++++++++---------
 8 files changed, 43 insertions(+), 27 deletions(-)

diff --git a/src/server/api/pagination/find-many.proxy.ts b/src/server/api/pagination/find-many.proxy.ts
index 51fe96f12..d1d3c3daa 100644
--- a/src/server/api/pagination/find-many.proxy.ts
+++ b/src/server/api/pagination/find-many.proxy.ts
@@ -51,7 +51,6 @@ export function makeFindManyPaginated(model: ProxyFunctions) {
       return {
         data: docs,
         count: docs.length,
-        // Send totalCount only for first request, let client side manages it for subsequent requests.
         total: totalCount,
         cursor: nextCursor,
       };
diff --git a/src/server/api/routes/company/share/create.ts b/src/server/api/routes/company/share/create.ts
index 0d180d7ac..839673b59 100644
--- a/src/server/api/routes/company/share/create.ts
+++ b/src/server/api/routes/company/share/create.ts
@@ -28,6 +28,9 @@ const ResponseSchema = z.object({
 const route = createRoute({
   method: "post",
   path: "/v1/companies/{id}/shares",
+  summary: "Issue shares",
+  description: "Issue shares to a stakeholder in a company.",
+  tags: ["Shares"],
   request: {
     params: ParamsSchema,
     body: {
@@ -45,7 +48,7 @@ const route = createRoute({
           schema: ResponseSchema,
         },
       },
-      description: "Created the Share Successfully",
+      description: "Issue shares",
     },
     ...ErrorResponses,
   },
@@ -78,13 +81,13 @@ const create = (app: PublicAPI) => {
     if (!success) {
       throw new ApiError({
         code: "INTERNAL_SERVER_ERROR",
-        message: "Something went wrong, Please try again Later",
+        message: "Something went wrong, please try again later",
       });
     }
 
     return c.json(
       {
-        data: "Created the Share Successfully",
+        data: "Successfully added the share",
       },
       200,
     );
diff --git a/src/server/api/routes/company/share/delete.ts b/src/server/api/routes/company/share/delete.ts
index c395d279e..6ff216e21 100644
--- a/src/server/api/routes/company/share/delete.ts
+++ b/src/server/api/routes/company/share/delete.ts
@@ -49,6 +49,9 @@ const ResponseSchema = z
 const route = createRoute({
   method: "delete",
   path: "/v1/companies/{id}/shares/{shareId}",
+  summary: "Delete issued shares",
+  description: "Delete a Share by ID",
+  tags: ["Shares"],
   request: {
     params: ParamsSchema,
   },
diff --git a/src/server/api/routes/company/share/getMany.ts b/src/server/api/routes/company/share/getMany.ts
index b60423733..6082e56f0 100644
--- a/src/server/api/routes/company/share/getMany.ts
+++ b/src/server/api/routes/company/share/getMany.ts
@@ -37,6 +37,9 @@ const ResponseSchema = z
 const route = createRoute({
   method: "get",
   path: "/v1/companies/{id}/shares",
+  summary: "Get list of issued shares",
+  description: "Get list of issued shares for a company",
+  tags: ["Shares"],
   request: {
     params: ParamsSchema,
     query: PaginationQuerySchema,
diff --git a/src/server/api/routes/company/share/getOne.ts b/src/server/api/routes/company/share/getOne.ts
index d87a516ba..223f565b2 100644
--- a/src/server/api/routes/company/share/getOne.ts
+++ b/src/server/api/routes/company/share/getOne.ts
@@ -44,6 +44,9 @@ const ResponseSchema = z
 const route = createRoute({
   method: "get",
   path: "/v1/companies/{id}/shares/{shareId}",
+  summary: "Get an issued share by ID",
+  description: "Get a single issued share record by ID",
+  tags: ["Shares"],
   request: {
     params: ParamsSchema,
   },
diff --git a/src/server/api/routes/company/share/update.ts b/src/server/api/routes/company/share/update.ts
index b46e549ee..e74904783 100644
--- a/src/server/api/routes/company/share/update.ts
+++ b/src/server/api/routes/company/share/update.ts
@@ -48,6 +48,9 @@ const ResponseSchema = z
 const route = createRoute({
   method: "put",
   path: "/v1/companies/{id}/shares/{shareId}",
+  summary: "Update issued shares by ID",
+  description: "Update issued shares by share ID",
+  tags: ["Shares"],
   request: {
     params: ParamsSchema,
     body: {
diff --git a/src/server/api/schema/shares.ts b/src/server/api/schema/shares.ts
index c837e42cd..f3ed4f59f 100644
--- a/src/server/api/schema/shares.ts
+++ b/src/server/api/schema/shares.ts
@@ -214,17 +214,17 @@ export const AddShareSchema = z
       example: "clycjzdqo000cjvsqr9rn6479",
     }),
 
-    documents: z
-      .array(
-        z.object({
-          bucketId: z.string(),
-          name: z.string(),
-        }),
-      )
-      .openapi({
-        description: "Uploaded Documents",
-        example: [{ bucketId: "vbhjewhvjvj3", name: "Bucket Blue" }],
-      }),
+    // documents: z
+    //   .array(
+    //     z.object({
+    //       bucketId: z.string(),
+    //       name: z.string(),
+    //     }),
+    //   )
+    //   .openapi({
+    //     description: "Uploaded Documents",
+    //     example: [{ bucketId: "vbhjewhvjvj3", name: "Bucket Blue" }],
+    //   }),
   })
   .openapi({
     description: "Create a Share",
diff --git a/src/server/services/shares/addShare.ts b/src/server/services/shares/addShare.ts
index b46372fbb..0c859171b 100644
--- a/src/server/services/shares/addShare.ts
+++ b/src/server/services/shares/addShare.ts
@@ -43,19 +43,21 @@ export const addShare = async (input: AddShareType) => {
 
       const share = await tx.share.create({ data });
 
-      const bulkDocuments = documents.map((doc) => ({
-        companyId: input.companyId,
-        uploaderId: input.memberId,
-        publicId: generatePublicId(),
-        name: doc.name,
-        bucketId: doc.bucketId,
-        shareId: share.id,
-      }));
+      if (documents && documents.length > 0) {
+        const bulkDocuments = documents.map((doc) => ({
+          companyId: input.companyId,
+          uploaderId: input.memberId,
+          publicId: generatePublicId(),
+          name: doc.name,
+          bucketId: doc.bucketId,
+          shareId: share.id,
+        }));
 
-      await tx.document.createMany({
-        data: bulkDocuments,
-        skipDuplicates: true,
-      });
+        await tx.document.createMany({
+          data: bulkDocuments,
+          skipDuplicates: true,
+        });
+      }
 
       await Audit.create(
         {

From 761f0782517eb7b48714939471c744e05ce039c7 Mon Sep 17 00:00:00 2001
From: Puru D <puru@dahal.me>
Date: Sat, 20 Jul 2024 04:38:39 -0500
Subject: [PATCH 31/40] feat: update share POST response with the data

---
 src/server/api/routes/company/share/create.ts | 12 ++++--------
 src/server/services/shares/addShare.ts        |  7 ++++---
 2 files changed, 8 insertions(+), 11 deletions(-)

diff --git a/src/server/api/routes/company/share/create.ts b/src/server/api/routes/company/share/create.ts
index 839673b59..2013cb40f 100644
--- a/src/server/api/routes/company/share/create.ts
+++ b/src/server/api/routes/company/share/create.ts
@@ -22,7 +22,8 @@ const ParamsSchema = z.object({
 });
 
 const ResponseSchema = z.object({
-  data: z.string(),
+  message: z.string(),
+  data: AddShareSchema,
 });
 
 const route = createRoute({
@@ -66,7 +67,7 @@ const create = (app: PublicAPI) => {
       "Unknown IP";
     const userAgent = c.req.header("User-Agent") || "";
 
-    const { success } = await addShare({
+    const { success, message, data } = await addShare({
       ...body,
       companyId: company.id,
       memberId: member.id,
@@ -85,12 +86,7 @@ const create = (app: PublicAPI) => {
       });
     }
 
-    return c.json(
-      {
-        data: "Successfully added the share",
-      },
-      200,
-    );
+    return c.json({ message, data }, 200);
   });
 };
 
diff --git a/src/server/services/shares/addShare.ts b/src/server/services/shares/addShare.ts
index 0c859171b..be322ba9c 100644
--- a/src/server/services/shares/addShare.ts
+++ b/src/server/services/shares/addShare.ts
@@ -16,7 +16,7 @@ export interface AddShareType extends TypeZodAddShareMutationSchema {
 
 export const addShare = async (input: AddShareType) => {
   try {
-    await db.$transaction(async (tx) => {
+    const share = await db.$transaction(async (tx) => {
       const documents = input.documents;
 
       const data = {
@@ -39,8 +39,6 @@ export const addShare = async (input: AddShareType) => {
         boardApprovalDate: new Date(input.boardApprovalDate),
       };
 
-      console.log("The data inside addShare is :", input);
-
       const share = await tx.share.create({ data });
 
       if (documents && documents.length > 0) {
@@ -73,11 +71,14 @@ export const addShare = async (input: AddShareType) => {
         },
         tx,
       );
+
+      return share;
     });
 
     return {
       success: true,
       message: "🎉 Successfully added a share",
+      data: share,
     };
   } catch (error) {
     console.error("Error adding shares: ", error);

From eb40fd587be49ec1835ccd9793575c68ca16b21e Mon Sep 17 00:00:00 2001
From: Puru D <puru@dahal.me>
Date: Sat, 20 Jul 2024 04:43:20 -0500
Subject: [PATCH 32/40] fix: some ts errors

---
 src/server/api/routes/company/share/create.ts | 24 +++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)

diff --git a/src/server/api/routes/company/share/create.ts b/src/server/api/routes/company/share/create.ts
index 2013cb40f..4970ddb6c 100644
--- a/src/server/api/routes/company/share/create.ts
+++ b/src/server/api/routes/company/share/create.ts
@@ -79,14 +79,34 @@ const create = (app: PublicAPI) => {
       },
     });
 
-    if (!success) {
+    if (!success || !data) {
       throw new ApiError({
         code: "INTERNAL_SERVER_ERROR",
         message: "Something went wrong, please try again later",
       });
     }
 
-    return c.json({ message, data }, 200);
+    // Ensure data matches ResponseSchema
+    const responseData = {
+      status: data.status as string, // Cast to string if necessary
+      certificateId: data.certificateId,
+      quantity: data.quantity,
+      pricePerShare: data.pricePerShare ?? 0,
+      capitalContribution: data.capitalContribution ?? 0,
+      ipContribution: data.ipContribution ?? 0,
+      debtCancelled: data.debtCancelled ?? 0,
+      otherContributions: data.otherContributions ?? 0,
+      vestingSchedule: data.vestingSchedule ?? "",
+      companyLegends: data.companyLegends ?? "", // Add missing fields
+      issueDate: data.issueDate ?? new Date().toISOString(), // Add missing fields
+      rule144Date: data.rule144Date ?? new Date().toISOString(), // Add missing fields
+      vestingStartDate: data.vestingStartDate ?? new Date().toISOString(), // Add missing fields
+      boardApprovalDate: data.boardApprovalDate ?? new Date().toISOString(), // Add boardApprovalDate
+      stakeholderId: data.stakeholderId ?? "", // Add stakeholderId
+      shareClassId: data.shareClassId,
+    };
+
+    return c.json({ message, data: responseData }, 200);
   });
 };
 

From cc66f3f819cd13e03a7022a91db0bfdeab74dee3 Mon Sep 17 00:00:00 2001
From: Puru D <puru@dahal.me>
Date: Sat, 20 Jul 2024 04:49:11 -0500
Subject: [PATCH 33/40] fix: build errors

---
 src/server/api/routes/company/share/getMany.ts | 4 ++--
 src/server/api/schema/shares.ts                | 4 +---
 src/server/services/shares/getShares.ts        | 4 ++--
 3 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/src/server/api/routes/company/share/getMany.ts b/src/server/api/routes/company/share/getMany.ts
index 6082e56f0..132673eda 100644
--- a/src/server/api/routes/company/share/getMany.ts
+++ b/src/server/api/routes/company/share/getMany.ts
@@ -61,11 +61,11 @@ const getMany = (app: PublicAPI) => {
   app.openapi(route, async (c: Context) => {
     const { company } = await withCompanyAuth(c);
 
-    const { limit, cursor, total } = c.req.query();
+    const { take, cursor, total } = c.req.query();
 
     const { data, meta } = await getPaginatedShares({
       companyId: company.id,
-      limit: Number(limit),
+      take: Number(take),
       cursor,
       total: Number(total),
     });
diff --git a/src/server/api/schema/shares.ts b/src/server/api/schema/shares.ts
index f3ed4f59f..65b40f6ea 100644
--- a/src/server/api/schema/shares.ts
+++ b/src/server/api/schema/shares.ts
@@ -232,7 +232,5 @@ export const AddShareSchema = z
 
 export type TAddShareSchema = z.infer<typeof AddShareSchema>;
 
-export const UpdateShareSchema = AddShareSchema.omit({
-  documents: true,
-}).partial();
+export const UpdateShareSchema = AddShareSchema.partial();
 export type TUpdateShareSchema = z.infer<typeof UpdateShareSchema>;
diff --git a/src/server/services/shares/getShares.ts b/src/server/services/shares/getShares.ts
index 095f8aa3b..815ed07d9 100644
--- a/src/server/services/shares/getShares.ts
+++ b/src/server/services/shares/getShares.ts
@@ -3,7 +3,7 @@ import { db } from "@/server/db";
 
 type GetPaginatedShares = {
   companyId: string;
-  limit: number;
+  take: number;
   cursor?: string;
   total?: number;
 };
@@ -19,7 +19,7 @@ export const getPaginatedShares = async (payload: GetPaginatedShares) => {
   };
 
   const paginationData = {
-    limit: payload.limit,
+    take: payload.take,
     cursor: payload.cursor,
     total: payload.total,
   };

From 9cc3a33448495a0f2ccd317b92f902e8a3b5b755 Mon Sep 17 00:00:00 2001
From: Puru D <puru@dahal.me>
Date: Sun, 21 Jul 2024 01:44:46 -0500
Subject: [PATCH 34/40] fix: pagination issues

---
 src/server/api/routes/company/share/getMany.ts |  3 ++-
 src/server/api/schema/pagination.ts            | 16 ++++++++++++----
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/src/server/api/routes/company/share/getMany.ts b/src/server/api/routes/company/share/getMany.ts
index 132673eda..7f84db132 100644
--- a/src/server/api/routes/company/share/getMany.ts
+++ b/src/server/api/routes/company/share/getMany.ts
@@ -2,6 +2,7 @@ import { withCompanyAuth } from "@/server/api/auth";
 import { ErrorResponses } from "@/server/api/error";
 import type { PublicAPI } from "@/server/api/hono";
 import {
+  DEFAULT_PAGINATION_LIMIT,
   PaginationQuerySchema,
   PaginationResponseSchema,
 } from "@/server/api/schema/pagination";
@@ -65,7 +66,7 @@ const getMany = (app: PublicAPI) => {
 
     const { data, meta } = await getPaginatedShares({
       companyId: company.id,
-      take: Number(take),
+      take: Number(take || DEFAULT_PAGINATION_LIMIT),
       cursor,
       total: Number(total),
     });
diff --git a/src/server/api/schema/pagination.ts b/src/server/api/schema/pagination.ts
index a2ad992ab..f1dd39b4e 100644
--- a/src/server/api/schema/pagination.ts
+++ b/src/server/api/schema/pagination.ts
@@ -1,11 +1,19 @@
 import { z } from "zod";
 
+export const DEFAULT_PAGINATION_LIMIT = 50;
+
 export const PaginationQuerySchema = z.object({
   limit: z
     .preprocess(
       (val) =>
         val === undefined ? undefined : Number.parseInt(val as string, 10),
-      z.number().int().positive().min(1).max(50).default(10),
+      z
+        .number()
+        .int()
+        .positive()
+        .min(1)
+        .max(50)
+        .default(DEFAULT_PAGINATION_LIMIT),
     )
     .openapi({
       description: "Number of items to take",
@@ -13,10 +21,10 @@ export const PaginationQuerySchema = z.object({
         name: "limit",
         in: "query",
       },
-      example: 10,
-      default: 10,
+      example: 25,
+      default: DEFAULT_PAGINATION_LIMIT,
       minimum: 1,
-      maximum: 50,
+      maximum: 250,
     }),
 
   cursor: z

From 963fdbb4e6ea9b52332648f05d96a0a6caafd44c Mon Sep 17 00:00:00 2001
From: Puru D <puru@dahal.me>
Date: Sun, 21 Jul 2024 01:59:37 -0500
Subject: [PATCH 35/40] chore: update file names

---
 src/components/ui/uploader.tsx                      |  4 +++-
 src/server/api/routes/company/share/create.ts       |  4 ++--
 src/server/api/routes/company/share/delete.ts       |  2 +-
 src/server/api/routes/company/share/getMany.ts      |  2 +-
 src/server/api/routes/company/share/update.ts       |  2 +-
 .../services/shares/{addShare.ts => add-share.ts}   |  0
 .../shares/{deleteShare.ts => delete-share.ts}      |  0
 .../services/shares/{getShares.ts => get-shares.ts} |  0
 .../shares/{updateShare.ts => update-share.ts}      | 13 +++++++------
 9 files changed, 15 insertions(+), 12 deletions(-)
 rename src/server/services/shares/{addShare.ts => add-share.ts} (100%)
 rename src/server/services/shares/{deleteShare.ts => delete-share.ts} (100%)
 rename src/server/services/shares/{getShares.ts => get-shares.ts} (100%)
 rename src/server/services/shares/{updateShare.ts => update-share.ts} (87%)

diff --git a/src/components/ui/uploader.tsx b/src/components/ui/uploader.tsx
index 1158329c4..842bc4319 100644
--- a/src/components/ui/uploader.tsx
+++ b/src/components/ui/uploader.tsx
@@ -106,7 +106,9 @@ export function Uploader({
       }
     } catch (error) {
       console.error("Error uploading file:", error);
-      toast.error("Uh oh! Something went wrong, please try again.");
+      toast.error(
+        "Uh oh! Something went wrong, please try again or contact support.",
+      );
     } finally {
       setUploading(false);
     }
diff --git a/src/server/api/routes/company/share/create.ts b/src/server/api/routes/company/share/create.ts
index 4970ddb6c..7838be479 100644
--- a/src/server/api/routes/company/share/create.ts
+++ b/src/server/api/routes/company/share/create.ts
@@ -2,7 +2,7 @@ import { withCompanyAuth } from "@/server/api/auth";
 import { ApiError, ErrorResponses } from "@/server/api/error";
 import type { PublicAPI } from "@/server/api/hono";
 import { AddShareSchema } from "@/server/api/schema/shares";
-import { addShare } from "@/server/services/shares/addShare";
+import { addShare } from "@/server/services/shares/add-share";
 import { createRoute, z } from "@hono/zod-openapi";
 import type { Context } from "hono";
 
@@ -82,7 +82,7 @@ const create = (app: PublicAPI) => {
     if (!success || !data) {
       throw new ApiError({
         code: "INTERNAL_SERVER_ERROR",
-        message: "Something went wrong, please try again later",
+        message: "Something went wrong, please try again or contact support.",
       });
     }
 
diff --git a/src/server/api/routes/company/share/delete.ts b/src/server/api/routes/company/share/delete.ts
index 6ff216e21..c2ce3f09f 100644
--- a/src/server/api/routes/company/share/delete.ts
+++ b/src/server/api/routes/company/share/delete.ts
@@ -2,7 +2,7 @@ import { withCompanyAuth } from "@/server/api/auth";
 import { ApiError, ErrorResponses } from "@/server/api/error";
 import type { PublicAPI } from "@/server/api/hono";
 import { ShareSchema } from "@/server/api/schema/shares";
-import { deleteShare } from "@/server/services/shares/deleteShare";
+import { deleteShare } from "@/server/services/shares/delete-share";
 import { createRoute, z } from "@hono/zod-openapi";
 import type { Context } from "hono";
 
diff --git a/src/server/api/routes/company/share/getMany.ts b/src/server/api/routes/company/share/getMany.ts
index 7f84db132..38cb8768a 100644
--- a/src/server/api/routes/company/share/getMany.ts
+++ b/src/server/api/routes/company/share/getMany.ts
@@ -7,7 +7,7 @@ import {
   PaginationResponseSchema,
 } from "@/server/api/schema/pagination";
 import { ShareSchema } from "@/server/api/schema/shares";
-import { getPaginatedShares } from "@/server/services/shares/getShares";
+import { getPaginatedShares } from "@/server/services/shares/get-shares";
 import { createRoute, z } from "@hono/zod-openapi";
 import type { Context } from "hono";
 
diff --git a/src/server/api/routes/company/share/update.ts b/src/server/api/routes/company/share/update.ts
index e74904783..f6bb48a36 100644
--- a/src/server/api/routes/company/share/update.ts
+++ b/src/server/api/routes/company/share/update.ts
@@ -2,7 +2,7 @@ import { withCompanyAuth } from "@/server/api/auth";
 import { ApiError, ErrorResponses } from "@/server/api/error";
 import type { PublicAPI } from "@/server/api/hono";
 import { UpdateShareSchema } from "@/server/api/schema/shares";
-import { updateShare } from "@/server/services/shares/updateShare";
+import { updateShare } from "@/server/services/shares/update-share";
 import { createRoute, z } from "@hono/zod-openapi";
 import type { Context } from "hono";
 
diff --git a/src/server/services/shares/addShare.ts b/src/server/services/shares/add-share.ts
similarity index 100%
rename from src/server/services/shares/addShare.ts
rename to src/server/services/shares/add-share.ts
diff --git a/src/server/services/shares/deleteShare.ts b/src/server/services/shares/delete-share.ts
similarity index 100%
rename from src/server/services/shares/deleteShare.ts
rename to src/server/services/shares/delete-share.ts
diff --git a/src/server/services/shares/getShares.ts b/src/server/services/shares/get-shares.ts
similarity index 100%
rename from src/server/services/shares/getShares.ts
rename to src/server/services/shares/get-shares.ts
diff --git a/src/server/services/shares/updateShare.ts b/src/server/services/shares/update-share.ts
similarity index 87%
rename from src/server/services/shares/updateShare.ts
rename to src/server/services/shares/update-share.ts
index dfacf67ed..43d48dd01 100644
--- a/src/server/services/shares/updateShare.ts
+++ b/src/server/services/shares/update-share.ts
@@ -1,6 +1,7 @@
+import { ApiError } from "@/server/api/error";
 import { Audit } from "@/server/audit";
 import { db } from "@/server/db";
-import type { AddShareType } from "./addShare";
+import type { AddShareType } from "./add-share";
 
 interface UpdateShareType extends AddShareType {
   shareId: string;
@@ -68,10 +69,10 @@ export const updateShare = async (input: UpdateShareType) => {
       message: "🎉 Successfully Updated the share",
     };
   } catch (error) {
-    console.error("Error adding shares: ", error);
-    return {
-      success: false,
-      message: "Can't Update the Share now. Please try again later",
-    };
+    console.error("updateShare", error);
+    throw new ApiError({
+      code: "INTERNAL_SERVER_ERROR",
+      message: "Something went wrong, please try again or contact support",
+    });
   }
 };

From 3e6bf3ab8df8cdad3343860e1c36a777e7a3b575 Mon Sep 17 00:00:00 2001
From: Puru D <puru@dahal.me>
Date: Sun, 21 Jul 2024 03:22:37 -0500
Subject: [PATCH 36/40] fix: issues with updating existing share & stakeholder

---
 src/server/api/routes/company/share/delete.ts | 34 +---------
 src/server/api/routes/company/share/getOne.ts |  4 +-
 src/server/api/routes/company/share/update.ts | 46 ++++++-------
 .../api/routes/company/stakeholder/update.ts  | 13 +---
 src/server/api/schema/shares.ts               | 43 +++++++++----
 src/server/api/schema/stakeholder.ts          | 15 ++++-
 src/server/services/shares/update-share.ts    | 64 ++++++++-----------
 .../stakeholder/update-stakeholder.ts         |  6 +-
 8 files changed, 102 insertions(+), 123 deletions(-)

diff --git a/src/server/api/routes/company/share/delete.ts b/src/server/api/routes/company/share/delete.ts
index c2ce3f09f..0edeb35ba 100644
--- a/src/server/api/routes/company/share/delete.ts
+++ b/src/server/api/routes/company/share/delete.ts
@@ -5,37 +5,7 @@ import { ShareSchema } from "@/server/api/schema/shares";
 import { deleteShare } from "@/server/services/shares/delete-share";
 import { createRoute, z } from "@hono/zod-openapi";
 import type { Context } from "hono";
-
-const ParamsSchema = z
-  .object({
-    id: z
-      .string()
-      .cuid()
-      .openapi({
-        description: "Company ID",
-        param: {
-          name: "id",
-          in: "path",
-        },
-
-        example: "clxwbok580000i7nge8nm1ry0",
-      }),
-    shareId: z
-      .string()
-      .cuid()
-      .openapi({
-        description: "Share ID",
-        param: {
-          name: "shareId",
-          in: "path",
-        },
-
-        example: "clyd3i9sw000008ij619eabva",
-      }),
-  })
-  .openapi({
-    description: "Delete a Share by ID",
-  });
+import { RequestParamsSchema } from "./update";
 
 const ResponseSchema = z
   .object({
@@ -53,7 +23,7 @@ const route = createRoute({
   description: "Delete a Share by ID",
   tags: ["Shares"],
   request: {
-    params: ParamsSchema,
+    params: RequestParamsSchema,
   },
   responses: {
     200: {
diff --git a/src/server/api/routes/company/share/getOne.ts b/src/server/api/routes/company/share/getOne.ts
index 223f565b2..a85ee6489 100644
--- a/src/server/api/routes/company/share/getOne.ts
+++ b/src/server/api/routes/company/share/getOne.ts
@@ -1,7 +1,7 @@
 import { withCompanyAuth } from "@/server/api/auth";
 import { ApiError, ErrorResponses } from "@/server/api/error";
 import type { PublicAPI } from "@/server/api/hono";
-import { ShareSchema, type TShareSchema } from "@/server/api/schema/shares";
+import { ShareSchema, type ShareSchemaType } from "@/server/api/schema/shares";
 import { db } from "@/server/db";
 import { createRoute, z } from "@hono/zod-openapi";
 import type { Context } from "hono";
@@ -75,7 +75,7 @@ const getOne = (app: PublicAPI) => {
         id,
         companyId: company.id,
       },
-    })) as unknown as TShareSchema;
+    })) as unknown as ShareSchemaType;
 
     if (!share) {
       throw new ApiError({
diff --git a/src/server/api/routes/company/share/update.ts b/src/server/api/routes/company/share/update.ts
index f6bb48a36..2bf9265ec 100644
--- a/src/server/api/routes/company/share/update.ts
+++ b/src/server/api/routes/company/share/update.ts
@@ -2,11 +2,13 @@ import { withCompanyAuth } from "@/server/api/auth";
 import { ApiError, ErrorResponses } from "@/server/api/error";
 import type { PublicAPI } from "@/server/api/hono";
 import { UpdateShareSchema } from "@/server/api/schema/shares";
+import type { UpdateShareSchemaType } from "@/server/api/schema/shares";
+import { getHonoUserAgent, getIp } from "@/server/api/utils";
 import { updateShare } from "@/server/services/shares/update-share";
 import { createRoute, z } from "@hono/zod-openapi";
 import type { Context } from "hono";
 
-const ParamsSchema = z
+export const RequestParamsSchema = z
   .object({
     id: z
       .string()
@@ -39,7 +41,8 @@ const ParamsSchema = z
 
 const ResponseSchema = z
   .object({
-    data: z.string(),
+    message: z.string(),
+    data: UpdateShareSchema,
   })
   .openapi({
     description: "Update a Share by ID",
@@ -52,7 +55,7 @@ const route = createRoute({
   description: "Update issued shares by share ID",
   tags: ["Shares"],
   request: {
-    params: ParamsSchema,
+    params: RequestParamsSchema,
     body: {
       content: {
         "application/json": {
@@ -76,38 +79,35 @@ const route = createRoute({
 
 const getOne = (app: PublicAPI) => {
   app.openapi(route, async (c: Context) => {
-    const { company, user, member } = await withCompanyAuth(c);
-
-    const { shareId: id } = c.req.param();
-
+    const { company, user } = await withCompanyAuth(c);
+    const { shareId } = c.req.param();
     const body = await c.req.json();
-    const requestIP =
-      c.req.header("x-forwarded-for") ||
-      c.req.header("remoteAddr") ||
-      "Unknown IP";
-    const userAgent = c.req.header("User-Agent") || "";
 
-    const { success, message } = await updateShare({
-      ...body,
+    const payload = {
+      shareId,
       companyId: company.id,
-      memberId: member.id,
-      requestIP,
-      userAgent,
-      userId: user.id,
-      userName: user.name,
-      shareId: id,
-    });
+      requestIp: getIp(c.req),
+      userAgent: getHonoUserAgent(c.req),
+      data: body as UpdateShareSchemaType,
+      user: {
+        id: user.id,
+        name: user.name as string,
+      },
+    };
+
+    const { success, message, data } = await updateShare(payload);
 
     if (!success) {
       throw new ApiError({
-        code: "BAD_REQUEST",
+        code: "NOT_FOUND",
         message,
       });
     }
 
     return c.json(
       {
-        data: "Successfully Updated the Share",
+        message,
+        data,
       },
       200,
     );
diff --git a/src/server/api/routes/company/stakeholder/update.ts b/src/server/api/routes/company/stakeholder/update.ts
index da4ed5522..57968ece7 100644
--- a/src/server/api/routes/company/stakeholder/update.ts
+++ b/src/server/api/routes/company/stakeholder/update.ts
@@ -14,17 +14,6 @@ import { createRoute, z } from "@hono/zod-openapi";
 import type { Context } from "hono";
 import { RequestParamsSchema } from "./delete";
 
-const RequestBodySchema = UpdateStakeholderSchema.refine(
-  (data) => {
-    return Object.values(data).some((value) => value !== undefined);
-  },
-  {
-    message: "At least one field must be provided to update.",
-  },
-).openapi({
-  description: "Update a stakeholder by ID",
-});
-
 const ResponseSchema = z
   .object({
     message: z.string(),
@@ -45,7 +34,7 @@ const route = createRoute({
     body: {
       content: {
         "application/json": {
-          schema: RequestBodySchema,
+          schema: UpdateStakeholderSchema,
         },
       },
     },
diff --git a/src/server/api/schema/shares.ts b/src/server/api/schema/shares.ts
index 65b40f6ea..a9e18c224 100644
--- a/src/server/api/schema/shares.ts
+++ b/src/server/api/schema/shares.ts
@@ -20,7 +20,7 @@ const SecuritiesStatusArr = Object.values(SecuritiesStatusEnum) as [
 
 export const ShareSchema = z
   .object({
-    id: z.string().cuid().openapi({
+    id: z.string().cuid().optional().openapi({
       description: "Share ID",
       example: "cly13ipa40000i7ng42mv4x7b",
     }),
@@ -30,39 +30,39 @@ export const ShareSchema = z
       example: "DRAFT",
     }),
 
-    certificateId: z.string().cuid().openapi({
+    certificateId: z.string().optional().openapi({
       description: "Certificate ID",
-      example: "cly13ipa40000i7ng42mv4x7b",
+      example: "123",
     }),
 
     quantity: z.number().openapi({
       description: "Quantity of Shares",
-      example: 234,
+      example: 5000,
     }),
 
     pricePerShare: z.number().nullable().openapi({
       description: "Price Per Share",
-      example: 23.4,
+      example: 1.25,
     }),
 
     capitalContribution: z.number().nullable().openapi({
       description: "Total amount of money contributed",
-      example: 25.4,
+      example: 250000,
     }),
 
     ipContribution: z.number().nullable().openapi({
       description: "Value of the intellectual property contributed",
-      example: 43.4,
+      example: 0,
     }),
 
     debtCancelled: z.number().nullable().openapi({
       description: "Amount of debt cancelled",
-      example: 54.54,
+      example: 0,
     }),
 
     otherContributions: z.number().nullable().openapi({
       description: "Other contributions",
-      example: 45.54,
+      example: 0,
     }),
 
     vestingSchedule: z.enum(VestingScheduleArr).openapi({
@@ -127,8 +127,6 @@ export const ShareSchema = z
     description: "Get a Single Share by the ID",
   });
 
-export type TShareSchema = z.infer<typeof ShareSchema>;
-
 export const AddShareSchema = z
   .object({
     status: z.enum(SecuritiesStatusArr).openapi({
@@ -230,7 +228,24 @@ export const AddShareSchema = z
     description: "Create a Share",
   });
 
-export type TAddShareSchema = z.infer<typeof AddShareSchema>;
+export const UpdateShareSchema = ShareSchema.omit({
+  id: true,
+  createdAt: true,
+  updatedAt: true,
+})
+  .partial()
+  .refine(
+    (data) => {
+      return Object.values(data).some((value) => value !== undefined);
+    },
+    {
+      message: "At least one field must be provided to update.",
+    },
+  )
+  .openapi({
+    description: "Update a share by ID",
+  });
 
-export const UpdateShareSchema = AddShareSchema.partial();
-export type TUpdateShareSchema = z.infer<typeof UpdateShareSchema>;
+export type ShareSchemaType = z.infer<typeof ShareSchema>;
+export type AddShareSchemaType = z.infer<typeof AddShareSchema>;
+export type UpdateShareSchemaType = z.infer<typeof UpdateShareSchema>;
diff --git a/src/server/api/schema/stakeholder.ts b/src/server/api/schema/stakeholder.ts
index c37cdc0f6..283e2fd73 100644
--- a/src/server/api/schema/stakeholder.ts
+++ b/src/server/api/schema/stakeholder.ts
@@ -80,12 +80,23 @@ export const StakeholderSchema = z.object({
 });
 
 export const AddStakeholderSchema = z.array(StakeholderSchema);
-
 export const UpdateStakeholderSchema = StakeholderSchema.omit({
   id: true,
   createdAt: true,
   updatedAt: true,
-});
+})
+  .partial()
+  .refine(
+    (data) => {
+      return Object.values(data).some((value) => value !== undefined);
+    },
+    {
+      message: "At least one field must be provided to update.",
+    },
+  )
+  .openapi({
+    description: "Update a stakeholder by ID",
+  });
 
 export type TStakeholderSchema = z.infer<typeof StakeholderSchema>;
 export type TAddStakeholderSchema = z.infer<typeof AddStakeholderSchema>;
diff --git a/src/server/services/shares/update-share.ts b/src/server/services/shares/update-share.ts
index 43d48dd01..673078374 100644
--- a/src/server/services/shares/update-share.ts
+++ b/src/server/services/shares/update-share.ts
@@ -1,72 +1,64 @@
 import { ApiError } from "@/server/api/error";
+import type { UpdateShareSchemaType } from "@/server/api/schema/shares";
 import { Audit } from "@/server/audit";
 import { db } from "@/server/db";
-import type { AddShareType } from "./add-share";
 
-interface UpdateShareType extends AddShareType {
+export type UpdateSharePayloadType = {
   shareId: string;
-}
+  companyId: string;
+  requestIp: string;
+  userAgent: string;
+  user: {
+    id: string;
+    name: string;
+  };
+  data: UpdateShareSchemaType;
+};
+
+export const updateShare = async (payload: UpdateSharePayloadType) => {
+  const { shareId, companyId, requestIp, userAgent, user, data } = payload;
 
-export const updateShare = async (input: UpdateShareType) => {
   try {
     const existingShare = await db.share.findUnique({
-      where: {
-        id: input.shareId,
-      },
+      where: { id: shareId },
     });
 
     if (!existingShare) {
       return {
         success: false,
-        message: "Enter Valid Share ID",
+        message: `Share with ID ${shareId} not be found`,
       };
     }
 
-    await db.$transaction(async (tx) => {
-      const data = {
-        companyId: input.companyId,
-        stakeholderId: input.stakeholderId,
-        shareClassId: input.shareClassId,
-        status: input.status,
-        certificateId: input.certificateId,
-        quantity: input.quantity,
-        pricePerShare: input.pricePerShare,
-        capitalContribution: input.capitalContribution,
-        ipContribution: input.ipContribution,
-        debtCancelled: input.debtCancelled,
-        otherContributions: input.otherContributions,
-        vestingSchedule: input.vestingSchedule,
-        companyLegends: input.companyLegends,
-        issueDate: new Date(input.issueDate),
-        rule144Date: new Date(input.rule144Date),
-        vestingStartDate: new Date(input.vestingStartDate),
-        boardApprovalDate: new Date(input.boardApprovalDate),
-      };
-
+    console.log({ data });
+    const share = await db.$transaction(async (tx) => {
       const share = await tx.share.update({
-        where: { id: input.shareId },
+        where: { id: shareId },
         data,
       });
 
       await Audit.create(
         {
           action: "share.updated",
-          companyId: input.companyId,
-          actor: { type: "user", id: input.user.id },
+          companyId: companyId,
+          actor: { type: "user", id: user.id },
           context: {
-            userAgent: input.userAgent,
-            requestIp: input.requestIP,
+            userAgent: userAgent,
+            requestIp: requestIp,
           },
           target: [{ type: "share", id: share.id }],
-          summary: `${input.user.name} updated share for stakeholder ${input.stakeholderId}`,
+          summary: `${user.name} updated share the share ID ${shareId}`,
         },
         tx,
       );
+
+      return share;
     });
 
     return {
       success: true,
-      message: "🎉 Successfully Updated the share",
+      message: "🎉 Successfully updated share.",
+      data: share,
     };
   } catch (error) {
     console.error("updateShare", error);
diff --git a/src/server/services/stakeholder/update-stakeholder.ts b/src/server/services/stakeholder/update-stakeholder.ts
index d8727b437..1b2dbb898 100644
--- a/src/server/services/stakeholder/update-stakeholder.ts
+++ b/src/server/services/stakeholder/update-stakeholder.ts
@@ -2,7 +2,7 @@ import type { TUpdateStakeholderSchema } from "@/server/api/schema/stakeholder";
 import { Audit } from "@/server/audit";
 import { db } from "@/server/db";
 
-export type UpdateStakeholderOptions = {
+export type UpdateStakeholderPayloadType = {
   stakeholderId: string;
   companyId: string;
   requestIp: string;
@@ -14,7 +14,9 @@ export type UpdateStakeholderOptions = {
   data: TUpdateStakeholderSchema;
 };
 
-export const updateStakeholder = async (payload: UpdateStakeholderOptions) => {
+export const updateStakeholder = async (
+  payload: UpdateStakeholderPayloadType,
+) => {
   const { requestIp, userAgent, user } = payload;
   const data = payload.data;
 

From 54964d798c98696c80ebf8fe0a61c7c5d8b8a1f8 Mon Sep 17 00:00:00 2001
From: Puru D <puru@dahal.me>
Date: Sun, 21 Jul 2024 03:33:02 -0500
Subject: [PATCH 37/40] fix: delete share endpoint

---
 src/server/api/error.ts                       |  2 ++
 src/server/api/routes/company/share/delete.ts | 29 ++++++++-----------
 src/server/services/shares/delete-share.ts    |  6 ++--
 3 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/src/server/api/error.ts b/src/server/api/error.ts
index a32df05f8..f1c41392b 100644
--- a/src/server/api/error.ts
+++ b/src/server/api/error.ts
@@ -19,6 +19,8 @@ const ErrorCode = z.enum([
   "METHOD_NOT_ALLOWED",
 ]);
 
+export type ErrorCodeType = z.infer<typeof ErrorCode>;
+
 function errorSchemaFactory(code: z.ZodEnum<[z.infer<typeof ErrorCode>]>) {
   return z.object({
     error: z.object({
diff --git a/src/server/api/routes/company/share/delete.ts b/src/server/api/routes/company/share/delete.ts
index 0edeb35ba..4e97eddf4 100644
--- a/src/server/api/routes/company/share/delete.ts
+++ b/src/server/api/routes/company/share/delete.ts
@@ -1,7 +1,11 @@
 import { withCompanyAuth } from "@/server/api/auth";
-import { ApiError, ErrorResponses } from "@/server/api/error";
+import {
+  ApiError,
+  type ErrorCodeType,
+  ErrorResponses,
+} from "@/server/api/error";
 import type { PublicAPI } from "@/server/api/hono";
-import { ShareSchema } from "@/server/api/schema/shares";
+import { getHonoUserAgent, getIp } from "@/server/api/utils";
 import { deleteShare } from "@/server/services/shares/delete-share";
 import { createRoute, z } from "@hono/zod-openapi";
 import type { Context } from "hono";
@@ -10,7 +14,6 @@ import { RequestParamsSchema } from "./update";
 const ResponseSchema = z
   .object({
     message: z.string(),
-    data: ShareSchema.optional(),
   })
   .openapi({
     description: "Delete a Share by ID",
@@ -41,34 +44,26 @@ const route = createRoute({
 const deleteOne = (app: PublicAPI) => {
   app.openapi(route, async (c: Context) => {
     const { company, user } = await withCompanyAuth(c);
-
     const { shareId: id } = c.req.param();
 
-    const requestIP =
-      c.req.header("x-forwarded-for") ||
-      c.req.header("remoteAddr") ||
-      "Unknown IP";
-    const userAgent = c.req.header("User-Agent") || "";
-
-    const { success, message, share } = await deleteShare({
+    const { success, code, message } = await deleteShare({
       companyId: company.id,
-      requestIp: requestIP,
-      userAgent,
+      requestIp: getIp(c.req),
+      userAgent: getHonoUserAgent(c.req),
       shareId: id as string,
       user: { id: user.id, name: user.name || "" },
     });
 
-    if (!success && !share) {
+    if (!success) {
       throw new ApiError({
-        code: "BAD_REQUEST",
+        code: code as ErrorCodeType,
         message,
       });
     }
 
     return c.json(
       {
-        message: "Successfully Deleted the Share",
-        data: share,
+        message: message,
       },
       200,
     );
diff --git a/src/server/services/shares/delete-share.ts b/src/server/services/shares/delete-share.ts
index 3113baa84..56bd05c4f 100644
--- a/src/server/services/shares/delete-share.ts
+++ b/src/server/services/shares/delete-share.ts
@@ -29,7 +29,8 @@ export const deleteShare = async ({
     if (!existingShare) {
       return {
         success: false,
-        message: "Enter Valid Share ID",
+        code: "NOT_FOUND",
+        message: `Share with ID ${shareId} not found`,
       };
     }
 
@@ -69,7 +70,8 @@ export const deleteShare = async ({
     console.error("Error Deleting the share: ", error);
     return {
       success: false,
-      message: "Can't Delete the Share now. Please try again later",
+      code: "INTERNAL_SERVER_ERROR",
+      message: "Error deleting the share, please try again or contact support.",
     };
   }
 };

From f36b9fecd9c7349ffdea7e9b162e71750b360d6c Mon Sep 17 00:00:00 2001
From: Puru D <puru@dahal.me>
Date: Sun, 21 Jul 2024 03:40:10 -0500
Subject: [PATCH 38/40] chore: some type safety issues

---
 src/server/api/routes/company/share/update.ts | 15 +++++++----
 src/server/api/schema/shares.ts               | 26 +++++++++----------
 2 files changed, 23 insertions(+), 18 deletions(-)

diff --git a/src/server/api/routes/company/share/update.ts b/src/server/api/routes/company/share/update.ts
index 2bf9265ec..467025a82 100644
--- a/src/server/api/routes/company/share/update.ts
+++ b/src/server/api/routes/company/share/update.ts
@@ -1,8 +1,10 @@
 import { withCompanyAuth } from "@/server/api/auth";
 import { ApiError, ErrorResponses } from "@/server/api/error";
 import type { PublicAPI } from "@/server/api/hono";
-import { UpdateShareSchema } from "@/server/api/schema/shares";
-import type { UpdateShareSchemaType } from "@/server/api/schema/shares";
+import {
+  UpdateShareSchema,
+  type UpdateShareSchemaType,
+} from "@/server/api/schema/shares";
 import { getHonoUserAgent, getIp } from "@/server/api/utils";
 import { updateShare } from "@/server/services/shares/update-share";
 import { createRoute, z } from "@hono/zod-openapi";
@@ -84,7 +86,7 @@ const getOne = (app: PublicAPI) => {
     const body = await c.req.json();
 
     const payload = {
-      shareId,
+      shareId: shareId as string,
       companyId: company.id,
       requestIp: getIp(c.req),
       userAgent: getHonoUserAgent(c.req),
@@ -106,8 +108,11 @@ const getOne = (app: PublicAPI) => {
 
     return c.json(
       {
-        message,
-        data,
+        message: message,
+        data: {
+          ...data,
+          issueDate: data?.issueDate.toISOString(), // Convert Date to string
+        } as UpdateShareSchemaType,
       },
       200,
     );
diff --git a/src/server/api/schema/shares.ts b/src/server/api/schema/shares.ts
index a9e18c224..52ba18a4f 100644
--- a/src/server/api/schema/shares.ts
+++ b/src/server/api/schema/shares.ts
@@ -22,7 +22,7 @@ export const ShareSchema = z
   .object({
     id: z.string().cuid().optional().openapi({
       description: "Share ID",
-      example: "cly13ipa40000i7ng42mv4x7b",
+      example: "clyvb2s8d0000f1ngd72y2cxw",
     }),
 
     status: z.enum(SecuritiesStatusArr).openapi({
@@ -80,22 +80,22 @@ export const ShareSchema = z
 
     issueDate: z.string().datetime().openapi({
       description: "Issued Date",
-      example: "1970-01-01T00:00:00.000Z",
+      example: "2024-01-01T00:00:00.000Z",
     }),
 
     rule144Date: z.string().datetime().nullable().openapi({
       description: "Rule 144 Date",
-      example: "1970-01-01T00:00:00.000Z",
+      example: "2024-01-01T00:00:00.000Z",
     }),
 
     vestingStartDate: z.string().datetime().nullable().openapi({
       description: "Vesting Start Date",
-      example: "1970-01-01T00:00:00.000Z",
+      example: "2024-01-01T00:00:00.000Z",
     }),
 
     boardApprovalDate: z.string().datetime().optional().openapi({
       description: "Board Approval Date",
-      example: "1970-01-01T00:00:00.000Z",
+      example: "2024-01-01T00:00:00.000Z",
     }),
 
     stakeholderId: z.string().cuid().openapi({
@@ -105,22 +105,22 @@ export const ShareSchema = z
 
     companyId: z.string().cuid().openapi({
       description: "Company ID",
-      example: "cly13ipa40000i7ng42mv4x7b",
+      example: "clyvb28ak0000f1ngcn2i0p2m",
     }),
 
     shareClassId: z.string().cuid().openapi({
       description: "ShareClass ID",
-      example: "cly13ipa40000i7ng42mv4x7b",
+      example: "clyvb2d8v0000f1ng1stpa38s",
     }),
 
     createdAt: z.string().datetime().optional().openapi({
       description: "Share Created at",
-      example: "1970-01-01T00:00:00.000Z",
+      example: "2024-01-01T00:00:00.000Z",
     }),
 
     updatedAt: z.string().datetime().optional().openapi({
       description: "Share Updated at",
-      example: "1970-01-01T00:00:00.000Z",
+      example: "2024-01-01T00:00:00.000Z",
     }),
   })
   .openapi({
@@ -184,22 +184,22 @@ export const AddShareSchema = z
 
     issueDate: z.string().datetime().openapi({
       description: "Issued Date",
-      example: "1970-01-01T00:00:00.000Z",
+      example: "2024-01-01T00:00:00.000Z",
     }),
 
     rule144Date: z.string().datetime().openapi({
       description: "Rule 144 Date",
-      example: "1970-01-01T00:00:00.000Z",
+      example: "2024-01-01T00:00:00.000Z",
     }),
 
     vestingStartDate: z.string().datetime().openapi({
       description: "Vesting Start Date",
-      example: "1970-01-01T00:00:00.000Z",
+      example: "2024-01-01T00:00:00.000Z",
     }),
 
     boardApprovalDate: z.string().datetime().openapi({
       description: "Board Approval Date",
-      example: "1970-01-01T00:00:00.000Z",
+      example: "2024-01-01T00:00:00.000Z",
     }),
 
     stakeholderId: z.string().cuid().openapi({

From 00386818c12e62f43e96a2b3aa25c182c99b112d Mon Sep 17 00:00:00 2001
From: Puru D <puru@dahal.me>
Date: Sun, 21 Jul 2024 03:53:27 -0500
Subject: [PATCH 39/40] fix: issues with share create endpoints

---
 src/server/api/routes/company/share/create.ts |  18 +--
 src/server/api/schema/shares.ts               | 111 ++----------------
 2 files changed, 16 insertions(+), 113 deletions(-)

diff --git a/src/server/api/routes/company/share/create.ts b/src/server/api/routes/company/share/create.ts
index 7838be479..d11c8231c 100644
--- a/src/server/api/routes/company/share/create.ts
+++ b/src/server/api/routes/company/share/create.ts
@@ -1,7 +1,8 @@
 import { withCompanyAuth } from "@/server/api/auth";
 import { ApiError, ErrorResponses } from "@/server/api/error";
 import type { PublicAPI } from "@/server/api/hono";
-import { AddShareSchema } from "@/server/api/schema/shares";
+import { CreateShareSchema } from "@/server/api/schema/shares";
+import { getHonoUserAgent, getIp } from "@/server/api/utils";
 import { addShare } from "@/server/services/shares/add-share";
 import { createRoute, z } from "@hono/zod-openapi";
 import type { Context } from "hono";
@@ -23,7 +24,7 @@ const ParamsSchema = z.object({
 
 const ResponseSchema = z.object({
   message: z.string(),
-  data: AddShareSchema,
+  data: CreateShareSchema,
 });
 
 const route = createRoute({
@@ -37,7 +38,7 @@ const route = createRoute({
     body: {
       content: {
         "application/json": {
-          schema: AddShareSchema,
+          schema: CreateShareSchema,
         },
       },
     },
@@ -58,21 +59,14 @@ const route = createRoute({
 const create = (app: PublicAPI) => {
   app.openapi(route, async (c: Context) => {
     const { company, member, user } = await withCompanyAuth(c);
-
     const body = await c.req.json();
 
-    const requestIP =
-      c.req.header("x-forwarded-for") ||
-      c.req.header("remoteAddr") ||
-      "Unknown IP";
-    const userAgent = c.req.header("User-Agent") || "";
-
     const { success, message, data } = await addShare({
       ...body,
       companyId: company.id,
       memberId: member.id,
-      requestIP,
-      userAgent,
+      requestIP: getIp(c.req),
+      userAgent: getHonoUserAgent(c.req),
       user: {
         id: user.id,
         name: user.name,
diff --git a/src/server/api/schema/shares.ts b/src/server/api/schema/shares.ts
index 52ba18a4f..fa7013b70 100644
--- a/src/server/api/schema/shares.ts
+++ b/src/server/api/schema/shares.ts
@@ -4,6 +4,7 @@ import {
   ShareLegendsEnum,
   VestingScheduleEnum,
 } from "@prisma/client";
+import { Share } from "next/font/google";
 
 const VestingScheduleArr = Object.values(VestingScheduleEnum) as [
   string,
@@ -127,106 +128,14 @@ export const ShareSchema = z
     description: "Get a Single Share by the ID",
   });
 
-export const AddShareSchema = z
-  .object({
-    status: z.enum(SecuritiesStatusArr).openapi({
-      description: "Security Status",
-      example: "DRAFT",
-    }),
-
-    certificateId: z.string().openapi({
-      description: "Certificate ID",
-      example: "cly13ipa40000i7ng42mv4x7b",
-    }),
-
-    quantity: z.number().min(0).openapi({
-      description: "Quantity of Shares",
-      example: 234,
-    }),
-
-    pricePerShare: z.number().min(0).openapi({
-      description: "Price Per Share",
-      example: 23.4,
-    }),
-
-    capitalContribution: z.number().min(0).openapi({
-      description: "Total amount of money contributed",
-      example: 25.4,
-    }),
-
-    ipContribution: z.number().min(0).openapi({
-      description: "Value of the intellectual property contributed",
-      example: 43.4,
-    }),
-
-    debtCancelled: z.number().min(0).openapi({
-      description: "Amount of debt cancelled",
-      example: 54.54,
-    }),
-
-    otherContributions: z.number().min(0).openapi({
-      description: "Other contributions",
-      example: 45.54,
-    }),
-
-    vestingSchedule: z.enum(VestingScheduleArr).openapi({
-      description: "Vesting Schedule",
-      example: "VESTING_0_0_0",
-    }),
-
-    companyLegends: z
-      .enum(ShareLegendsArr)
-      .array()
-      .openapi({
-        description: "Company Legends",
-        example: ["US_SECURITIES_ACT", "SALE_AND_ROFR"],
-      }),
-
-    issueDate: z.string().datetime().openapi({
-      description: "Issued Date",
-      example: "2024-01-01T00:00:00.000Z",
-    }),
-
-    rule144Date: z.string().datetime().openapi({
-      description: "Rule 144 Date",
-      example: "2024-01-01T00:00:00.000Z",
-    }),
-
-    vestingStartDate: z.string().datetime().openapi({
-      description: "Vesting Start Date",
-      example: "2024-01-01T00:00:00.000Z",
-    }),
-
-    boardApprovalDate: z.string().datetime().openapi({
-      description: "Board Approval Date",
-      example: "2024-01-01T00:00:00.000Z",
-    }),
-
-    stakeholderId: z.string().cuid().openapi({
-      description: "StakeHolder ID",
-      example: "clydxglyl0000d94ff363egje",
-    }),
-
-    shareClassId: z.string().cuid().openapi({
-      description: "ShareClass ID",
-      example: "clycjzdqo000cjvsqr9rn6479",
-    }),
-
-    // documents: z
-    //   .array(
-    //     z.object({
-    //       bucketId: z.string(),
-    //       name: z.string(),
-    //     }),
-    //   )
-    //   .openapi({
-    //     description: "Uploaded Documents",
-    //     example: [{ bucketId: "vbhjewhvjvj3", name: "Bucket Blue" }],
-    //   }),
-  })
-  .openapi({
-    description: "Create a Share",
-  });
+export const CreateShareSchema = ShareSchema.omit({
+  id: true,
+  createdAt: true,
+  updatedAt: true,
+  companyId: true,
+}).openapi({
+  description: "Issue shares to a stakeholder in a company.",
+});
 
 export const UpdateShareSchema = ShareSchema.omit({
   id: true,
@@ -247,5 +156,5 @@ export const UpdateShareSchema = ShareSchema.omit({
   });
 
 export type ShareSchemaType = z.infer<typeof ShareSchema>;
-export type AddShareSchemaType = z.infer<typeof AddShareSchema>;
+export type CreateShareSchemaType = z.infer<typeof CreateShareSchema>;
 export type UpdateShareSchemaType = z.infer<typeof UpdateShareSchema>;

From 9e2c6df44f67e12e864e8eed5e93efaf5612526f Mon Sep 17 00:00:00 2001
From: Puru D <puru@dahal.me>
Date: Sun, 21 Jul 2024 04:23:40 -0500
Subject: [PATCH 40/40] fix: build error

---
 .../migration.sql                             |  2 ++
 prisma/schema.prisma                          |  2 +-
 src/server/api/schema/shares.ts               | 28 ++++++++++---------
 src/server/services/shares/update-share.ts    | 10 +++++--
 4 files changed, 26 insertions(+), 16 deletions(-)
 create mode 100644 prisma/migrations/20240721090639_default_share_legends/migration.sql

diff --git a/prisma/migrations/20240721090639_default_share_legends/migration.sql b/prisma/migrations/20240721090639_default_share_legends/migration.sql
new file mode 100644
index 000000000..4139b2dd5
--- /dev/null
+++ b/prisma/migrations/20240721090639_default_share_legends/migration.sql
@@ -0,0 +1,2 @@
+-- AlterTable
+ALTER TABLE "Share" ALTER COLUMN "companyLegends" SET DEFAULT ARRAY[]::"ShareLegendsEnum"[];
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index dfe7f487e..79787279c 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -701,7 +701,7 @@ model Share {
   vestingYears    Int                 @default(0) // 0 means immediate vesting, 1 means vesting over 1 year
   vestingSchedule VestingScheduleEnum
 
-  companyLegends ShareLegendsEnum[]
+  companyLegends ShareLegendsEnum[] @default([])
 
   issueDate         DateTime
   rule144Date       DateTime?
diff --git a/src/server/api/schema/shares.ts b/src/server/api/schema/shares.ts
index fa7013b70..f7984b18e 100644
--- a/src/server/api/schema/shares.ts
+++ b/src/server/api/schema/shares.ts
@@ -21,7 +21,7 @@ const SecuritiesStatusArr = Object.values(SecuritiesStatusEnum) as [
 
 export const ShareSchema = z
   .object({
-    id: z.string().cuid().optional().openapi({
+    id: z.string().cuid().nullish().openapi({
       description: "Share ID",
       example: "clyvb2s8d0000f1ngd72y2cxw",
     }),
@@ -31,7 +31,7 @@ export const ShareSchema = z
       example: "DRAFT",
     }),
 
-    certificateId: z.string().optional().openapi({
+    certificateId: z.string().nullish().openapi({
       description: "Certificate ID",
       example: "123",
     }),
@@ -41,27 +41,27 @@ export const ShareSchema = z
       example: 5000,
     }),
 
-    pricePerShare: z.number().nullable().openapi({
+    pricePerShare: z.number().nullish().openapi({
       description: "Price Per Share",
       example: 1.25,
     }),
 
-    capitalContribution: z.number().nullable().openapi({
+    capitalContribution: z.number().nullish().openapi({
       description: "Total amount of money contributed",
       example: 250000,
     }),
 
-    ipContribution: z.number().nullable().openapi({
+    ipContribution: z.number().nullish().openapi({
       description: "Value of the intellectual property contributed",
       example: 0,
     }),
 
-    debtCancelled: z.number().nullable().openapi({
+    debtCancelled: z.number().nullish().openapi({
       description: "Amount of debt cancelled",
       example: 0,
     }),
 
-    otherContributions: z.number().nullable().openapi({
+    otherContributions: z.number().nullish().openapi({
       description: "Other contributions",
       example: 0,
     }),
@@ -74,27 +74,29 @@ export const ShareSchema = z
     companyLegends: z
       .enum(ShareLegendsArr)
       .array()
+      .default([])
+      .nullish()
       .openapi({
         description: "Company Legends",
         example: ["US_SECURITIES_ACT", "SALE_AND_ROFR"],
       }),
 
-    issueDate: z.string().datetime().openapi({
+    issueDate: z.string().datetime().nullish().openapi({
       description: "Issued Date",
       example: "2024-01-01T00:00:00.000Z",
     }),
 
-    rule144Date: z.string().datetime().nullable().openapi({
+    rule144Date: z.string().datetime().nullish().openapi({
       description: "Rule 144 Date",
       example: "2024-01-01T00:00:00.000Z",
     }),
 
-    vestingStartDate: z.string().datetime().nullable().openapi({
+    vestingStartDate: z.string().datetime().nullish().openapi({
       description: "Vesting Start Date",
       example: "2024-01-01T00:00:00.000Z",
     }),
 
-    boardApprovalDate: z.string().datetime().optional().openapi({
+    boardApprovalDate: z.string().datetime().nullish().openapi({
       description: "Board Approval Date",
       example: "2024-01-01T00:00:00.000Z",
     }),
@@ -114,12 +116,12 @@ export const ShareSchema = z
       example: "clyvb2d8v0000f1ng1stpa38s",
     }),
 
-    createdAt: z.string().datetime().optional().openapi({
+    createdAt: z.string().datetime().nullish().openapi({
       description: "Share Created at",
       example: "2024-01-01T00:00:00.000Z",
     }),
 
-    updatedAt: z.string().datetime().optional().openapi({
+    updatedAt: z.string().datetime().nullish().openapi({
       description: "Share Updated at",
       example: "2024-01-01T00:00:00.000Z",
     }),
diff --git a/src/server/services/shares/update-share.ts b/src/server/services/shares/update-share.ts
index 673078374..4d7ca7cc4 100644
--- a/src/server/services/shares/update-share.ts
+++ b/src/server/services/shares/update-share.ts
@@ -2,6 +2,7 @@ import { ApiError } from "@/server/api/error";
 import type { UpdateShareSchemaType } from "@/server/api/schema/shares";
 import { Audit } from "@/server/audit";
 import { db } from "@/server/db";
+import type { ShareLegendsEnum } from "@prisma/client";
 
 export type UpdateSharePayloadType = {
   shareId: string;
@@ -30,11 +31,16 @@ export const updateShare = async (payload: UpdateSharePayloadType) => {
       };
     }
 
-    console.log({ data });
+    const shareData = {
+      ...existingShare,
+      ...data,
+    };
+
     const share = await db.$transaction(async (tx) => {
       const share = await tx.share.update({
         where: { id: shareId },
-        data,
+        // @ts-ignore
+        data: shareData,
       });
 
       await Audit.create(
