feature/research-di #1

Merged
behnam merged 37 commits from feature/research-di into develop 2024-11-21 15:50:19 +00:00
9 changed files with 64 additions and 34 deletions
Showing only changes of commit 7046c5adc9 - Show all commits

View File

@ -1,5 +1,5 @@
import fetchCustomerInvoicesUsecase from "@/feature/core/customer-invoice/domain/usecase/fetch-customer-invoices-usecase";
export default function latestInvoicesController() {
return fetchCustomerInvoicesUsecase()
export default async function latestInvoicesController() {
return await fetchCustomerInvoicesUsecase()
}

View File

@ -2,12 +2,15 @@ import CreateRandomInvoiceContainer from '@/app/dashboard/components/client/crea
import latestInvoicesController from '@/app/dashboard/components/server/latest-invoices/latest-invoices-controller';
import { ArrowPathIcon } from '@heroicons/react/24/outline';
import clsx from 'clsx';
import { isLeft } from 'fp-ts/lib/Either';
import Image from 'next/image';
export default async function LatestInvoices() {
const latestInvoices = await latestInvoicesController();
const invoices = latestInvoices.map((invoice, i) => {
if (isLeft(latestInvoices)) return <div>Error</div>
const invoices = latestInvoices.right.map((invoice, i) => {
return (
<div
key={invoice.id}

View File

@ -0,0 +1,12 @@
import BaseFailure from "./base-failure";
/**
* Failure for params failure
*/
export default class ParamsFailure extends BaseFailure {
/* ------------------------------- Constructor ------------------------------ */
constructor() {
super("params");
}
/* -------------------------------------------------------------------------- */
}

View File

@ -1,7 +1,12 @@
import { sql } from "@/bootstrap/boundaries/db/db";
import ApiTask from "@/feature/common/data/api-task";
import { failureOr } from "@/feature/common/failures/failure-helpers";
import NetworkFailure from "@/feature/common/failures/network-failure";
import { formatCurrency } from "@/feature/common/feature-helpers";
import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice";
import CustomerInvoiceRepo from "@/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo";
import { pipe } from "fp-ts/lib/function";
import { tryCatch } from "fp-ts/lib/TaskEither";
import postgres from "postgres";
type customerInvoiceDbResponse = {
@ -13,22 +18,24 @@ type customerInvoiceDbResponse = {
}
export default class CustomerInvoiceDbRepo implements CustomerInvoiceRepo {
async fetchList(): Promise<CustomerInvoice[]> {
try {
const data = await sql`
fetchList(): ApiTask<CustomerInvoice[]> {
return pipe(
tryCatch(
async () => {
const response = await sql`
SELECT invoices.amount, customers.name, customers.image_url, customers.email, invoices.id
FROM invoices
JOIN customers ON invoices.customer_id = customers.id
ORDER BY invoices.date DESC
LIMIT 20 ` as postgres.RowList<customerInvoiceDbResponse[]>;
return this.customerInvoicesDto(data)
} catch (error) {
console.error('Database Error:', error);
throw new Error('Failed to fetch the latest invoices.');
return this.customerInvoicesDto(response)
},
(l) => failureOr(l, new NetworkFailure())
)
)
}
}
private customerInvoicesDto(dbCustomers: customerInvoiceDbResponse[]): CustomerInvoice[] {
return dbCustomers.map((customer) => this.customerInvoiceDto(customer));

View File

@ -1,7 +1,8 @@
import ApiTask from "@/feature/common/data/api-task"
import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice"
export default interface CustomerInvoiceRepo {
fetchList(): Promise<CustomerInvoice[]>
fetchList(): ApiTask<CustomerInvoice[]>
}
export const customerInvoiceRepoKey = "customerInvoiceRepoKey"

View File

@ -1,12 +1,12 @@
"use server"
import { ApiEither } from "@/feature/common/data/api-task";
import serverDi from "@/feature/common/server-di";
import CustomerInvoice from "@/feature/core/customer-invoice/domain/entity/customer-invoice";
import CustomerInvoiceRepo, { customerInvoiceRepoKey } from "@/feature/core/customer-invoice/domain/i-repo/customer-invoice-repo";
import { customerInvoiceModuleKey } from "@/feature/core/customer-invoice/invoice-module-key";
import { connection } from "next/server";
export default async function fetchCustomerInvoicesUsecase(): Promise<CustomerInvoice[]> {
export default async function fetchCustomerInvoicesUsecase(): Promise<ApiEither<CustomerInvoice[]>> {
connection()
const repo = serverDi(customerInvoiceModuleKey).resolve<CustomerInvoiceRepo>(customerInvoiceRepoKey)
return repo.fetchList()
return repo.fetchList()()
}

View File

@ -1,7 +1,8 @@
import ApiTask from "@/feature/common/data/api-task"
import Customer from "@/feature/core/customer/domain/entity/customer"
export default interface CustomerRepo {
fetchList(query: string): Promise<Customer[]>
fetchList(query: string): ApiTask<Customer[]>
fetchCustomersAmount(): Promise<number>
}

View File

@ -1,10 +1,11 @@
import ApiTask from "@/feature/common/data/api-task"
import { InvoiceParam } from "@/feature/core/invoice/domain/param/invoice-param"
import InvoiceStatusSummary from "@/feature/core/invoice/domain/value-object/invoice-status"
export default interface InvoiceRepo {
fetchAllInvoicesAmount(): Promise<number>
fetchInvoicesStatusSummary(): Promise<InvoiceStatusSummary>
createInvoice(params: InvoiceParam): Promise<string>
createInvoice(params: InvoiceParam): ApiTask<string>
}
export const invoiceRepoKey = "invoiceRepoKey"

View File

@ -1,19 +1,24 @@
"use server"
import { ApiEither } from "@/feature/common/data/api-task";
import ParamsFailure from "@/feature/common/failures/params-failure";
import serverDi from "@/feature/common/server-di";
import InvoiceRepo, { invoiceRepoKey } from "@/feature/core/invoice/domain/i-repo/invoice-repo";
import { InvoiceParam, invoiceSchema } from "@/feature/core/invoice/domain/param/invoice-param";
import { invoiceModuleKey } from "@/feature/core/invoice/invoice-module-key";
import { pipe } from "fp-ts/lib/function";
import { chain, fromNullable, left, map, right } from "fp-ts/lib/TaskEither";
export default async function createInvoiceUsecase(params: InvoiceParam): Promise<string | {errorMessage: string}> {
const isParamsValid = invoiceSchema.safeParse(params)
if (!isParamsValid) {
return {
errorMessage: "Please pass correct params"
}
}
export default async function createInvoiceUsecase(params: InvoiceParam): Promise<ApiEither<string>> {
const repo = serverDi(invoiceModuleKey).resolve<InvoiceRepo>(invoiceRepoKey)
return repo.createInvoice(params)
return pipe(
fromNullable(new ParamsFailure())(params),
map((params) => invoiceSchema.safeParse(params)),
chain((params) => {
const isParamsValid = invoiceSchema.safeParse(params)
if (!isParamsValid.success) left(new ParamsFailure())
return right(params.data as InvoiceParam)
}),
chain((params) => repo.createInvoice(params))
)()
}