all
This commit is contained in:
1 parent
90125aede9
commit
2d6c29a1f3
404 files changed
+126983
-85
No files matched your search
@@ -0,0 +1,18 @@
|
||||
import { Body, Controller, Inject, Post } from "@nestjs/common";
|
||||
import type { LoginInput } from "../../dtos/auth.dto.js";
|
||||
import {
|
||||
AUTH_SERVICE,
|
||||
type IAuthService,
|
||||
} from "./interfaces/auth-service.interface.js";
|
||||
|
||||
@Controller("auth")
|
||||
export class AuthController {
|
||||
constructor(
|
||||
@Inject(AUTH_SERVICE) private readonly authService: IAuthService,
|
||||
) {}
|
||||
|
||||
@Post("login")
|
||||
login(@Body() body: LoginInput) {
|
||||
return this.authService.login(body);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { UserModule } from "../user/user.module.js";
|
||||
import { AuthController } from "./auth.controller.js";
|
||||
import { AuthService } from "./auth.service.js";
|
||||
import { AUTH_SERVICE } from "./interfaces/auth-service.interface.js";
|
||||
|
||||
@Module({
|
||||
imports: [UserModule],
|
||||
controllers: [AuthController],
|
||||
providers: [{ provide: AUTH_SERVICE, useClass: AuthService }],
|
||||
})
|
||||
export class AuthModule {}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Inject, Injectable, UnauthorizedException } from "@nestjs/common";
|
||||
import type { LoginInput } from "../../dtos/auth.dto.js";
|
||||
import type { User } from "../../entities/user.entity.js";
|
||||
import {
|
||||
USER_SERVICE,
|
||||
type IUserService,
|
||||
} from "../user/interfaces/user-service.interface.js";
|
||||
import type { IAuthService } from "./interfaces/auth-service.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class AuthService implements IAuthService {
|
||||
constructor(
|
||||
@Inject(USER_SERVICE) private readonly userService: IUserService,
|
||||
) {}
|
||||
|
||||
async login({ id, password }: LoginInput): Promise<User> {
|
||||
const user = await this.userService.verifyCredentials({ id, password });
|
||||
if (!user) {
|
||||
throw new UnauthorizedException("Credenciales inválidas");
|
||||
}
|
||||
return user;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import type { LoginInput } from "../../../dtos/auth.dto.js";
|
||||
import type { User } from "../../../entities/user.entity.js";
|
||||
|
||||
export const AUTH_SERVICE = Symbol("AUTH_SERVICE");
|
||||
|
||||
export interface IAuthService {
|
||||
login(input: LoginInput): Promise<User>;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Inject,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
Patch,
|
||||
Post,
|
||||
} from "@nestjs/common";
|
||||
import type {
|
||||
CreateCartProductInput,
|
||||
UpdateCartProductInput,
|
||||
} from "../../dtos/cart-product.dto.js";
|
||||
import { CART_PRODUCT_SERVICE } from "./interfaces/cart-product-service.interface.js";
|
||||
import type { ICartProductService } from "./interfaces/cart-product-service.interface.js";
|
||||
|
||||
@Controller("cart-products")
|
||||
export class CartProductController {
|
||||
constructor(
|
||||
@Inject(CART_PRODUCT_SERVICE)
|
||||
private readonly cartProductService: ICartProductService,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
findAll() {
|
||||
return this.cartProductService.findAll();
|
||||
}
|
||||
|
||||
@Get(":cartId/:historyId")
|
||||
findOne(
|
||||
@Param("cartId", ParseIntPipe) cartId: number,
|
||||
@Param("historyId", ParseIntPipe) historyId: number,
|
||||
) {
|
||||
return this.cartProductService.findById({ cartId, historyId });
|
||||
}
|
||||
|
||||
@Post()
|
||||
create(@Body() body: CreateCartProductInput) {
|
||||
return this.cartProductService.create(body);
|
||||
}
|
||||
|
||||
@Patch(":cartId/:historyId")
|
||||
update(
|
||||
@Param("cartId", ParseIntPipe) cartId: number,
|
||||
@Param("historyId", ParseIntPipe) historyId: number,
|
||||
@Body() body: UpdateCartProductInput,
|
||||
) {
|
||||
return this.cartProductService.update({ cartId, historyId }, body);
|
||||
}
|
||||
|
||||
@Delete(":cartId/:historyId")
|
||||
remove(
|
||||
@Param("cartId", ParseIntPipe) cartId: number,
|
||||
@Param("historyId", ParseIntPipe) historyId: number,
|
||||
) {
|
||||
return this.cartProductService.delete({ cartId, historyId });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { CART_PRODUCT_REPOSITORY } from "./interfaces/cart-product-repository.interface.js";
|
||||
import { CART_PRODUCT_SERVICE } from "./interfaces/cart-product-service.interface.js";
|
||||
import { CartProductController } from "./cart-product.controller.js";
|
||||
import { CartProductRepository } from "./cart-product.repository.js";
|
||||
import { CartProductService } from "./cart-product.service.js";
|
||||
|
||||
@Module({
|
||||
controllers: [CartProductController],
|
||||
providers: [
|
||||
{ provide: CART_PRODUCT_REPOSITORY, useClass: CartProductRepository },
|
||||
{ provide: CART_PRODUCT_SERVICE, useClass: CartProductService },
|
||||
],
|
||||
exports: [CART_PRODUCT_SERVICE],
|
||||
})
|
||||
export class CartProductModule {}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { BaseRepository } from "../../common/base.repository.js";
|
||||
import type {
|
||||
CreateCartProductInput,
|
||||
UpdateCartProductInput,
|
||||
} from "../../dtos/cart-product.dto.js";
|
||||
import type {
|
||||
CartProduct,
|
||||
CartProductKey,
|
||||
} from "../../entities/cart-product.entity.js";
|
||||
import type { ICartProductRepository } from "./interfaces/cart-product-repository.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class CartProductRepository
|
||||
extends BaseRepository<
|
||||
CartProduct,
|
||||
CreateCartProductInput,
|
||||
UpdateCartProductInput,
|
||||
CartProductKey
|
||||
>
|
||||
implements ICartProductRepository
|
||||
{
|
||||
protected readonly columns = ["cartId", "historyId", "quantity"] as const;
|
||||
|
||||
protected get model() {
|
||||
return this.db.orm.public.CartProduct;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import { Inject, Injectable } from "@nestjs/common";
|
||||
import { BaseService } from "../../common/base.service.js";
|
||||
import type {
|
||||
CreateCartProductInput,
|
||||
UpdateCartProductInput,
|
||||
} from "../../dtos/cart-product.dto.js";
|
||||
import type {
|
||||
CartProduct,
|
||||
CartProductKey,
|
||||
} from "../../entities/cart-product.entity.js";
|
||||
import {
|
||||
CART_PRODUCT_REPOSITORY,
|
||||
type ICartProductRepository,
|
||||
} from "./interfaces/cart-product-repository.interface.js";
|
||||
import type { ICartProductService } from "./interfaces/cart-product-service.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class CartProductService
|
||||
extends BaseService<
|
||||
CartProduct,
|
||||
CreateCartProductInput,
|
||||
UpdateCartProductInput,
|
||||
CartProductKey
|
||||
>
|
||||
implements ICartProductService
|
||||
{
|
||||
constructor(
|
||||
@Inject(CART_PRODUCT_REPOSITORY) repository: ICartProductRepository,
|
||||
) {
|
||||
super(repository);
|
||||
}
|
||||
|
||||
protected override notFoundMessage(where: CartProductKey): string {
|
||||
return `CartProduct (${where.cartId}, ${where.historyId}) not found`;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import type { IRepository } from "../../../common/repository.interface.js";
|
||||
import type {
|
||||
CartProduct,
|
||||
CartProductKey,
|
||||
} from "../../../entities/cart-product.entity.js";
|
||||
import type {
|
||||
CreateCartProductInput,
|
||||
UpdateCartProductInput,
|
||||
} from "../../../dtos/cart-product.dto.js";
|
||||
|
||||
export const CART_PRODUCT_REPOSITORY = Symbol("CART_PRODUCT_REPOSITORY");
|
||||
|
||||
export type ICartProductRepository = IRepository<
|
||||
CartProduct,
|
||||
CreateCartProductInput,
|
||||
UpdateCartProductInput,
|
||||
CartProductKey
|
||||
>;
|
||||
@@ -0,0 +1,18 @@
|
||||
import type { IService } from "../../../common/service.interface.js";
|
||||
import type {
|
||||
CartProduct,
|
||||
CartProductKey,
|
||||
} from "../../../entities/cart-product.entity.js";
|
||||
import type {
|
||||
CreateCartProductInput,
|
||||
UpdateCartProductInput,
|
||||
} from "../../../dtos/cart-product.dto.js";
|
||||
|
||||
export const CART_PRODUCT_SERVICE = Symbol("CART_PRODUCT_SERVICE");
|
||||
|
||||
export type ICartProductService = IService<
|
||||
CartProduct,
|
||||
CreateCartProductInput,
|
||||
UpdateCartProductInput,
|
||||
CartProductKey
|
||||
>;
|
||||
@@ -0,0 +1,26 @@
|
||||
import { Body, Controller, Get, Inject, Param, ParseIntPipe, Post } from "@nestjs/common";
|
||||
import type { CreateCashMovementInput } from "../../dtos/cash-movement.dto.js";
|
||||
import { CASH_MOVEMENT_SERVICE } from "./interfaces/cash-movement-service.interface.js";
|
||||
import type { ICashMovementService } from "./interfaces/cash-movement-service.interface.js";
|
||||
|
||||
@Controller("cash-movements")
|
||||
export class CashMovementController {
|
||||
constructor(
|
||||
@Inject(CASH_MOVEMENT_SERVICE) private readonly cashMovementService: ICashMovementService,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
findAll() {
|
||||
return this.cashMovementService.findAll();
|
||||
}
|
||||
|
||||
@Get(":id")
|
||||
findOne(@Param("id", ParseIntPipe) id: number) {
|
||||
return this.cashMovementService.findById({ id });
|
||||
}
|
||||
|
||||
@Post()
|
||||
create(@Body() body: CreateCashMovementInput) {
|
||||
return this.cashMovementService.create(body);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { CASH_MOVEMENT_REPOSITORY } from "./interfaces/cash-movement-repository.interface.js";
|
||||
import { CASH_MOVEMENT_SERVICE } from "./interfaces/cash-movement-service.interface.js";
|
||||
import { CashMovementController } from "./cash-movement.controller.js";
|
||||
import { CashMovementRepository } from "./cash-movement.repository.js";
|
||||
import { CashMovementService } from "./cash-movement.service.js";
|
||||
|
||||
@Module({
|
||||
controllers: [CashMovementController],
|
||||
providers: [
|
||||
{ provide: CASH_MOVEMENT_REPOSITORY, useClass: CashMovementRepository },
|
||||
{ provide: CASH_MOVEMENT_SERVICE, useClass: CashMovementService },
|
||||
],
|
||||
exports: [CASH_MOVEMENT_SERVICE],
|
||||
})
|
||||
export class CashMovementModule {}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { Inject, Injectable } from "@nestjs/common";
|
||||
import { DB } from "../../database/database.tokens.js";
|
||||
import type { Database } from "../../prisma/db.js";
|
||||
import type { CashMovement, CashMovementKey } from "../../entities/cash-movement.entity.js";
|
||||
import type { CreateCashMovementInput } from "../../dtos/cash-movement.dto.js";
|
||||
import type { ICashMovementRepository } from "./interfaces/cash-movement-repository.interface.js";
|
||||
|
||||
const COLUMNS = ["id", "sessionId", "type", "amount", "reason", "userId", "createdAt"] as const;
|
||||
|
||||
@Injectable()
|
||||
export class CashMovementRepository implements ICashMovementRepository {
|
||||
constructor(@Inject(DB) private readonly db: Database) {}
|
||||
|
||||
private get model() {
|
||||
return this.db.orm.public.CashMovement;
|
||||
}
|
||||
|
||||
findAll(): Promise<CashMovement[]> {
|
||||
return this.model.select(...COLUMNS).all().toArray();
|
||||
}
|
||||
|
||||
findById(where: CashMovementKey): Promise<CashMovement | null> {
|
||||
return this.model.select(...COLUMNS).where(where).first();
|
||||
}
|
||||
|
||||
create(data: CreateCashMovementInput): Promise<CashMovement> {
|
||||
return this.model.select(...COLUMNS).create(data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { Inject, Injectable, NotFoundException } from "@nestjs/common";
|
||||
import type { CashMovement, CashMovementKey } from "../../entities/cash-movement.entity.js";
|
||||
import type { CreateCashMovementInput } from "../../dtos/cash-movement.dto.js";
|
||||
import {
|
||||
CASH_MOVEMENT_REPOSITORY,
|
||||
type ICashMovementRepository,
|
||||
} from "./interfaces/cash-movement-repository.interface.js";
|
||||
import type { ICashMovementService } from "./interfaces/cash-movement-service.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class CashMovementService implements ICashMovementService {
|
||||
constructor(
|
||||
@Inject(CASH_MOVEMENT_REPOSITORY) private readonly repository: ICashMovementRepository,
|
||||
) {}
|
||||
|
||||
findAll(): Promise<CashMovement[]> {
|
||||
return this.repository.findAll();
|
||||
}
|
||||
|
||||
async findById(where: CashMovementKey): Promise<CashMovement> {
|
||||
const movement = await this.repository.findById(where);
|
||||
if (!movement) {
|
||||
throw new NotFoundException(`CashMovement ${where.id} not found`);
|
||||
}
|
||||
return movement;
|
||||
}
|
||||
|
||||
create(data: CreateCashMovementInput): Promise<CashMovement> {
|
||||
return this.repository.create(data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import type { CashMovement, CashMovementKey } from "../../../entities/cash-movement.entity.js";
|
||||
import type { CreateCashMovementInput } from "../../../dtos/cash-movement.dto.js";
|
||||
|
||||
export const CASH_MOVEMENT_REPOSITORY = Symbol("CASH_MOVEMENT_REPOSITORY");
|
||||
|
||||
export interface ICashMovementRepository {
|
||||
findAll(): Promise<CashMovement[]>;
|
||||
findById(where: CashMovementKey): Promise<CashMovement | null>;
|
||||
create(data: CreateCashMovementInput): Promise<CashMovement>;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import type { CashMovement, CashMovementKey } from "../../../entities/cash-movement.entity.js";
|
||||
import type { CreateCashMovementInput } from "../../../dtos/cash-movement.dto.js";
|
||||
|
||||
export const CASH_MOVEMENT_SERVICE = Symbol("CASH_MOVEMENT_SERVICE");
|
||||
|
||||
export interface ICashMovementService {
|
||||
findAll(): Promise<CashMovement[]>;
|
||||
findById(where: CashMovementKey): Promise<CashMovement>;
|
||||
create(data: CreateCashMovementInput): Promise<CashMovement>;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { Body, Controller, Delete, Get, Inject, Param, ParseIntPipe, Patch, Post } from "@nestjs/common";
|
||||
import type {
|
||||
CreateCashRegisterSessionInput,
|
||||
UpdateCashRegisterSessionInput,
|
||||
} from "../../dtos/cash-register-session.dto.js";
|
||||
import { CASH_REGISTER_SESSION_SERVICE } from "./interfaces/cash-register-session-service.interface.js";
|
||||
import type { ICashRegisterSessionService } from "./interfaces/cash-register-session-service.interface.js";
|
||||
|
||||
@Controller("cash-register-sessions")
|
||||
export class CashRegisterSessionController {
|
||||
constructor(
|
||||
@Inject(CASH_REGISTER_SESSION_SERVICE)
|
||||
private readonly sessionService: ICashRegisterSessionService,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
findAll() {
|
||||
return this.sessionService.findAll();
|
||||
}
|
||||
|
||||
@Get(":id")
|
||||
findOne(@Param("id", ParseIntPipe) id: number) {
|
||||
return this.sessionService.findById({ id });
|
||||
}
|
||||
|
||||
@Post()
|
||||
create(@Body() body: CreateCashRegisterSessionInput) {
|
||||
return this.sessionService.create(body);
|
||||
}
|
||||
|
||||
@Patch(":id")
|
||||
update(@Param("id", ParseIntPipe) id: number, @Body() body: UpdateCashRegisterSessionInput) {
|
||||
return this.sessionService.update({ id }, body);
|
||||
}
|
||||
|
||||
@Delete(":id")
|
||||
remove(@Param("id", ParseIntPipe) id: number) {
|
||||
return this.sessionService.delete({ id });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { CASH_REGISTER_SESSION_REPOSITORY } from "./interfaces/cash-register-session-repository.interface.js";
|
||||
import { CASH_REGISTER_SESSION_SERVICE } from "./interfaces/cash-register-session-service.interface.js";
|
||||
import { CashRegisterSessionController } from "./cash-register-session.controller.js";
|
||||
import { CashRegisterSessionRepository } from "./cash-register-session.repository.js";
|
||||
import { CashRegisterSessionService } from "./cash-register-session.service.js";
|
||||
|
||||
@Module({
|
||||
controllers: [CashRegisterSessionController],
|
||||
providers: [
|
||||
{ provide: CASH_REGISTER_SESSION_REPOSITORY, useClass: CashRegisterSessionRepository },
|
||||
{ provide: CASH_REGISTER_SESSION_SERVICE, useClass: CashRegisterSessionService },
|
||||
],
|
||||
exports: [CASH_REGISTER_SESSION_SERVICE],
|
||||
})
|
||||
export class CashRegisterSessionModule {}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { BaseRepository } from "../../common/base.repository.js";
|
||||
import type {
|
||||
CreateCashRegisterSessionInput,
|
||||
UpdateCashRegisterSessionInput,
|
||||
} from "../../dtos/cash-register-session.dto.js";
|
||||
import type {
|
||||
CashRegisterSession,
|
||||
CashRegisterSessionKey,
|
||||
} from "../../entities/cash-register-session.entity.js";
|
||||
import type { ICashRegisterSessionRepository } from "./interfaces/cash-register-session-repository.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class CashRegisterSessionRepository
|
||||
extends BaseRepository<
|
||||
CashRegisterSession,
|
||||
CreateCashRegisterSessionInput,
|
||||
UpdateCashRegisterSessionInput,
|
||||
CashRegisterSessionKey
|
||||
>
|
||||
implements ICashRegisterSessionRepository
|
||||
{
|
||||
protected readonly columns = [
|
||||
"id",
|
||||
"inventoryId",
|
||||
"openedById",
|
||||
"closedById",
|
||||
"openingCash",
|
||||
"closingCash",
|
||||
"expectedCash",
|
||||
"status",
|
||||
"openedAt",
|
||||
"closedAt",
|
||||
] as const;
|
||||
|
||||
protected get model() {
|
||||
return this.db.orm.public.CashRegisterSession;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
import { BadRequestException, Inject, Injectable } from "@nestjs/common";
|
||||
import { BaseService } from "../../common/base.service.js";
|
||||
import type {
|
||||
CreateCashRegisterSessionInput,
|
||||
UpdateCashRegisterSessionInput,
|
||||
} from "../../dtos/cash-register-session.dto.js";
|
||||
import type {
|
||||
CashRegisterSession,
|
||||
CashRegisterSessionKey,
|
||||
} from "../../entities/cash-register-session.entity.js";
|
||||
import {
|
||||
CASH_REGISTER_SESSION_REPOSITORY,
|
||||
type ICashRegisterSessionRepository,
|
||||
} from "./interfaces/cash-register-session-repository.interface.js";
|
||||
import type { ICashRegisterSessionService } from "./interfaces/cash-register-session-service.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class CashRegisterSessionService
|
||||
extends BaseService<
|
||||
CashRegisterSession,
|
||||
CreateCashRegisterSessionInput,
|
||||
UpdateCashRegisterSessionInput,
|
||||
CashRegisterSessionKey
|
||||
>
|
||||
implements ICashRegisterSessionService
|
||||
{
|
||||
constructor(
|
||||
@Inject(CASH_REGISTER_SESSION_REPOSITORY)
|
||||
private readonly sessionRepository: ICashRegisterSessionRepository,
|
||||
) {
|
||||
super(sessionRepository);
|
||||
}
|
||||
|
||||
override async create(data: CreateCashRegisterSessionInput): Promise<CashRegisterSession> {
|
||||
const all = await this.sessionRepository.findAll();
|
||||
const alreadyOpen = all.some((s) => s.inventoryId === data.inventoryId && s.status === "open");
|
||||
if (alreadyOpen) {
|
||||
throw new BadRequestException("Ya hay una caja abierta en este almacén");
|
||||
}
|
||||
return this.sessionRepository.create(data);
|
||||
}
|
||||
|
||||
override async update(
|
||||
where: CashRegisterSessionKey,
|
||||
data: UpdateCashRegisterSessionInput,
|
||||
): Promise<CashRegisterSession> {
|
||||
const current = await this.findById(where);
|
||||
if (data.status === "closed" && current.status === "closed") {
|
||||
throw new BadRequestException("Esta caja ya está cerrada");
|
||||
}
|
||||
const payload =
|
||||
data.status === "closed" && !data.closedAt
|
||||
? { ...data, closedAt: new Date().toISOString() }
|
||||
: data;
|
||||
return this.sessionRepository.update(where, payload);
|
||||
}
|
||||
|
||||
protected override notFoundMessage(where: CashRegisterSessionKey): string {
|
||||
return `CashRegisterSession ${where.id} not found`;
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
import type { IRepository } from "../../../common/repository.interface.js";
|
||||
import type {
|
||||
CashRegisterSession,
|
||||
CashRegisterSessionKey,
|
||||
} from "../../../entities/cash-register-session.entity.js";
|
||||
import type {
|
||||
CreateCashRegisterSessionInput,
|
||||
UpdateCashRegisterSessionInput,
|
||||
} from "../../../dtos/cash-register-session.dto.js";
|
||||
|
||||
export const CASH_REGISTER_SESSION_REPOSITORY = Symbol("CASH_REGISTER_SESSION_REPOSITORY");
|
||||
|
||||
export type ICashRegisterSessionRepository = IRepository<
|
||||
CashRegisterSession,
|
||||
CreateCashRegisterSessionInput,
|
||||
UpdateCashRegisterSessionInput,
|
||||
CashRegisterSessionKey
|
||||
>;
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
import type { IService } from "../../../common/service.interface.js";
|
||||
import type {
|
||||
CashRegisterSession,
|
||||
CashRegisterSessionKey,
|
||||
} from "../../../entities/cash-register-session.entity.js";
|
||||
import type {
|
||||
CreateCashRegisterSessionInput,
|
||||
UpdateCashRegisterSessionInput,
|
||||
} from "../../../dtos/cash-register-session.dto.js";
|
||||
|
||||
export const CASH_REGISTER_SESSION_SERVICE = Symbol("CASH_REGISTER_SESSION_SERVICE");
|
||||
|
||||
export type ICashRegisterSessionService = IService<
|
||||
CashRegisterSession,
|
||||
CreateCashRegisterSessionInput,
|
||||
UpdateCashRegisterSessionInput,
|
||||
CashRegisterSessionKey
|
||||
>;
|
||||
@@ -0,0 +1,53 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Inject,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
Patch,
|
||||
Post,
|
||||
} from "@nestjs/common";
|
||||
import type {
|
||||
CreateCategoryInput,
|
||||
UpdateCategoryInput,
|
||||
} from "../../dtos/category.dto.js";
|
||||
import { CATEGORY_SERVICE } from "./interfaces/category-service.interface.js";
|
||||
import type { ICategoryService } from "./interfaces/category-service.interface.js";
|
||||
|
||||
@Controller("categories")
|
||||
export class CategoryController {
|
||||
constructor(
|
||||
@Inject(CATEGORY_SERVICE)
|
||||
private readonly categoryService: ICategoryService,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
findAll() {
|
||||
return this.categoryService.findAll();
|
||||
}
|
||||
|
||||
@Get(":id")
|
||||
findOne(@Param("id", ParseIntPipe) id: number) {
|
||||
return this.categoryService.findById({ id });
|
||||
}
|
||||
|
||||
@Post()
|
||||
create(@Body() body: CreateCategoryInput) {
|
||||
return this.categoryService.create(body);
|
||||
}
|
||||
|
||||
@Patch(":id")
|
||||
update(
|
||||
@Param("id", ParseIntPipe) id: number,
|
||||
@Body() body: UpdateCategoryInput,
|
||||
) {
|
||||
return this.categoryService.update({ id }, body);
|
||||
}
|
||||
|
||||
@Delete(":id")
|
||||
remove(@Param("id", ParseIntPipe) id: number) {
|
||||
return this.categoryService.delete({ id });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { CATEGORY_REPOSITORY } from "./interfaces/category-repository.interface.js";
|
||||
import { CATEGORY_SERVICE } from "./interfaces/category-service.interface.js";
|
||||
import { CategoryController } from "./category.controller.js";
|
||||
import { CategoryRepository } from "./category.repository.js";
|
||||
import { CategoryService } from "./category.service.js";
|
||||
|
||||
@Module({
|
||||
controllers: [CategoryController],
|
||||
providers: [
|
||||
{ provide: CATEGORY_REPOSITORY, useClass: CategoryRepository },
|
||||
{ provide: CATEGORY_SERVICE, useClass: CategoryService },
|
||||
],
|
||||
exports: [CATEGORY_SERVICE],
|
||||
})
|
||||
export class CategoryModule {}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { BaseRepository } from "../../common/base.repository.js";
|
||||
import type {
|
||||
CreateCategoryInput,
|
||||
UpdateCategoryInput,
|
||||
} from "../../dtos/category.dto.js";
|
||||
import type { Category, CategoryKey } from "../../entities/category.entity.js";
|
||||
import type { ICategoryRepository } from "./interfaces/category-repository.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class CategoryRepository
|
||||
extends BaseRepository<
|
||||
Category,
|
||||
CreateCategoryInput,
|
||||
UpdateCategoryInput,
|
||||
CategoryKey
|
||||
>
|
||||
implements ICategoryRepository
|
||||
{
|
||||
protected readonly columns = ["id", "name", "createdAt"] as const;
|
||||
|
||||
protected get model() {
|
||||
return this.db.orm.public.Category;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { Inject, Injectable } from "@nestjs/common";
|
||||
import { BaseService } from "../../common/base.service.js";
|
||||
import type {
|
||||
CreateCategoryInput,
|
||||
UpdateCategoryInput,
|
||||
} from "../../dtos/category.dto.js";
|
||||
import type { Category, CategoryKey } from "../../entities/category.entity.js";
|
||||
import {
|
||||
CATEGORY_REPOSITORY,
|
||||
type ICategoryRepository,
|
||||
} from "./interfaces/category-repository.interface.js";
|
||||
import type { ICategoryService } from "./interfaces/category-service.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class CategoryService
|
||||
extends BaseService<
|
||||
Category,
|
||||
CreateCategoryInput,
|
||||
UpdateCategoryInput,
|
||||
CategoryKey
|
||||
>
|
||||
implements ICategoryService
|
||||
{
|
||||
constructor(@Inject(CATEGORY_REPOSITORY) repository: ICategoryRepository) {
|
||||
super(repository);
|
||||
}
|
||||
|
||||
protected override notFoundMessage(where: CategoryKey): string {
|
||||
return `Category ${where.id} not found`;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import type { IRepository } from "../../../common/repository.interface.js";
|
||||
import type {
|
||||
Category,
|
||||
CategoryKey,
|
||||
} from "../../../entities/category.entity.js";
|
||||
import type {
|
||||
CreateCategoryInput,
|
||||
UpdateCategoryInput,
|
||||
} from "../../../dtos/category.dto.js";
|
||||
|
||||
export const CATEGORY_REPOSITORY = Symbol("CATEGORY_REPOSITORY");
|
||||
|
||||
export type ICategoryRepository = IRepository<
|
||||
Category,
|
||||
CreateCategoryInput,
|
||||
UpdateCategoryInput,
|
||||
CategoryKey
|
||||
>;
|
||||
@@ -0,0 +1,18 @@
|
||||
import type { IService } from "../../../common/service.interface.js";
|
||||
import type {
|
||||
Category,
|
||||
CategoryKey,
|
||||
} from "../../../entities/category.entity.js";
|
||||
import type {
|
||||
CreateCategoryInput,
|
||||
UpdateCategoryInput,
|
||||
} from "../../../dtos/category.dto.js";
|
||||
|
||||
export const CATEGORY_SERVICE = Symbol("CATEGORY_SERVICE");
|
||||
|
||||
export type ICategoryService = IService<
|
||||
Category,
|
||||
CreateCategoryInput,
|
||||
UpdateCategoryInput,
|
||||
CategoryKey
|
||||
>;
|
||||
@@ -0,0 +1,34 @@
|
||||
import { Body, Controller, Delete, Get, Inject, Param, ParseIntPipe, Patch, Post } from "@nestjs/common";
|
||||
import type { CreateCustomerInput, UpdateCustomerInput } from "../../dtos/customer.dto.js";
|
||||
import { CUSTOMER_SERVICE } from "./interfaces/customer-service.interface.js";
|
||||
import type { ICustomerService } from "./interfaces/customer-service.interface.js";
|
||||
|
||||
@Controller("customers")
|
||||
export class CustomerController {
|
||||
constructor(@Inject(CUSTOMER_SERVICE) private readonly customerService: ICustomerService) {}
|
||||
|
||||
@Get()
|
||||
findAll() {
|
||||
return this.customerService.findAll();
|
||||
}
|
||||
|
||||
@Get(":id")
|
||||
findOne(@Param("id", ParseIntPipe) id: number) {
|
||||
return this.customerService.findById({ id });
|
||||
}
|
||||
|
||||
@Post()
|
||||
create(@Body() body: CreateCustomerInput) {
|
||||
return this.customerService.create(body);
|
||||
}
|
||||
|
||||
@Patch(":id")
|
||||
update(@Param("id", ParseIntPipe) id: number, @Body() body: UpdateCustomerInput) {
|
||||
return this.customerService.update({ id }, body);
|
||||
}
|
||||
|
||||
@Delete(":id")
|
||||
remove(@Param("id", ParseIntPipe) id: number) {
|
||||
return this.customerService.delete({ id });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { CUSTOMER_REPOSITORY } from "./interfaces/customer-repository.interface.js";
|
||||
import { CUSTOMER_SERVICE } from "./interfaces/customer-service.interface.js";
|
||||
import { CustomerController } from "./customer.controller.js";
|
||||
import { CustomerRepository } from "./customer.repository.js";
|
||||
import { CustomerService } from "./customer.service.js";
|
||||
|
||||
@Module({
|
||||
controllers: [CustomerController],
|
||||
providers: [
|
||||
{ provide: CUSTOMER_REPOSITORY, useClass: CustomerRepository },
|
||||
{ provide: CUSTOMER_SERVICE, useClass: CustomerService },
|
||||
],
|
||||
exports: [CUSTOMER_SERVICE],
|
||||
})
|
||||
export class CustomerModule {}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { BaseRepository } from "../../common/base.repository.js";
|
||||
import type { CreateCustomerInput, UpdateCustomerInput } from "../../dtos/customer.dto.js";
|
||||
import type { Customer, CustomerKey } from "../../entities/customer.entity.js";
|
||||
import type { ICustomerRepository } from "./interfaces/customer-repository.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class CustomerRepository
|
||||
extends BaseRepository<Customer, CreateCustomerInput, UpdateCustomerInput, CustomerKey>
|
||||
implements ICustomerRepository
|
||||
{
|
||||
protected readonly columns = ["id", "name", "phone", "email", "taxId", "createdAt"] as const;
|
||||
|
||||
protected get model() {
|
||||
return this.db.orm.public.Customer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Inject, Injectable } from "@nestjs/common";
|
||||
import { BaseService } from "../../common/base.service.js";
|
||||
import type { CreateCustomerInput, UpdateCustomerInput } from "../../dtos/customer.dto.js";
|
||||
import type { Customer, CustomerKey } from "../../entities/customer.entity.js";
|
||||
import {
|
||||
CUSTOMER_REPOSITORY,
|
||||
type ICustomerRepository,
|
||||
} from "./interfaces/customer-repository.interface.js";
|
||||
import type { ICustomerService } from "./interfaces/customer-service.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class CustomerService
|
||||
extends BaseService<Customer, CreateCustomerInput, UpdateCustomerInput, CustomerKey>
|
||||
implements ICustomerService
|
||||
{
|
||||
constructor(@Inject(CUSTOMER_REPOSITORY) repository: ICustomerRepository) {
|
||||
super(repository);
|
||||
}
|
||||
|
||||
protected override notFoundMessage(where: CustomerKey): string {
|
||||
return `Customer ${where.id} not found`;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import type { IRepository } from "../../../common/repository.interface.js";
|
||||
import type { Customer, CustomerKey } from "../../../entities/customer.entity.js";
|
||||
import type { CreateCustomerInput, UpdateCustomerInput } from "../../../dtos/customer.dto.js";
|
||||
|
||||
export const CUSTOMER_REPOSITORY = Symbol("CUSTOMER_REPOSITORY");
|
||||
|
||||
export type ICustomerRepository = IRepository<
|
||||
Customer,
|
||||
CreateCustomerInput,
|
||||
UpdateCustomerInput,
|
||||
CustomerKey
|
||||
>;
|
||||
@@ -0,0 +1,12 @@
|
||||
import type { IService } from "../../../common/service.interface.js";
|
||||
import type { Customer, CustomerKey } from "../../../entities/customer.entity.js";
|
||||
import type { CreateCustomerInput, UpdateCustomerInput } from "../../../dtos/customer.dto.js";
|
||||
|
||||
export const CUSTOMER_SERVICE = Symbol("CUSTOMER_SERVICE");
|
||||
|
||||
export type ICustomerService = IService<
|
||||
Customer,
|
||||
CreateCustomerInput,
|
||||
UpdateCustomerInput,
|
||||
CustomerKey
|
||||
>;
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import type {
|
||||
InventoryMovement,
|
||||
InventoryMovementKey,
|
||||
} from "../../../entities/inventory-movement.entity.js";
|
||||
import type { CreateInventoryMovementInput } from "../../../dtos/inventory-movement.dto.js";
|
||||
|
||||
export const INVENTORY_MOVEMENT_REPOSITORY = Symbol(
|
||||
"INVENTORY_MOVEMENT_REPOSITORY",
|
||||
);
|
||||
|
||||
export interface IInventoryMovementRepository {
|
||||
findAll(): Promise<InventoryMovement[]>;
|
||||
findById(where: InventoryMovementKey): Promise<InventoryMovement | null>;
|
||||
create(data: CreateInventoryMovementInput): Promise<InventoryMovement>;
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
import type {
|
||||
InventoryMovement,
|
||||
InventoryMovementKey,
|
||||
} from "../../../entities/inventory-movement.entity.js";
|
||||
import type { CreateInventoryMovementInput } from "../../../dtos/inventory-movement.dto.js";
|
||||
|
||||
export const INVENTORY_MOVEMENT_SERVICE = Symbol("INVENTORY_MOVEMENT_SERVICE");
|
||||
|
||||
export interface IInventoryMovementService {
|
||||
findAll(): Promise<InventoryMovement[]>;
|
||||
findById(where: InventoryMovementKey): Promise<InventoryMovement>;
|
||||
create(data: CreateInventoryMovementInput): Promise<InventoryMovement>;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { Body, Controller, Get, Inject, Param, ParseIntPipe, Post } from "@nestjs/common";
|
||||
import type { CreateInventoryMovementInput } from "../../dtos/inventory-movement.dto.js";
|
||||
import {
|
||||
INVENTORY_MOVEMENT_SERVICE,
|
||||
type IInventoryMovementService,
|
||||
} from "./interfaces/inventory-movement-service.interface.js";
|
||||
|
||||
@Controller("inventory-movements")
|
||||
export class InventoryMovementController {
|
||||
constructor(
|
||||
@Inject(INVENTORY_MOVEMENT_SERVICE)
|
||||
private readonly inventoryMovementService: IInventoryMovementService,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
findAll() {
|
||||
return this.inventoryMovementService.findAll();
|
||||
}
|
||||
|
||||
@Get(":id")
|
||||
findOne(@Param("id", ParseIntPipe) id: number) {
|
||||
return this.inventoryMovementService.findById({ id });
|
||||
}
|
||||
|
||||
@Post()
|
||||
create(@Body() body: CreateInventoryMovementInput) {
|
||||
return this.inventoryMovementService.create(body);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { ProductModule } from "../product/product.module.js";
|
||||
import { SupplierModule } from "../supplier/supplier.module.js";
|
||||
import { WarehouseModule } from "../warehouse/warehouse.module.js";
|
||||
import { INVENTORY_MOVEMENT_REPOSITORY } from "./interfaces/inventory-movement-repository.interface.js";
|
||||
import { INVENTORY_MOVEMENT_SERVICE } from "./interfaces/inventory-movement-service.interface.js";
|
||||
import { InventoryMovementController } from "./inventory-movement.controller.js";
|
||||
import { InventoryMovementRepository } from "./inventory-movement.repository.js";
|
||||
import { InventoryMovementService } from "./inventory-movement.service.js";
|
||||
|
||||
@Module({
|
||||
imports: [WarehouseModule, ProductModule, SupplierModule],
|
||||
controllers: [InventoryMovementController],
|
||||
providers: [
|
||||
{ provide: INVENTORY_MOVEMENT_REPOSITORY, useClass: InventoryMovementRepository },
|
||||
{ provide: INVENTORY_MOVEMENT_SERVICE, useClass: InventoryMovementService },
|
||||
],
|
||||
exports: [INVENTORY_MOVEMENT_SERVICE],
|
||||
})
|
||||
export class InventoryMovementModule {}
|
||||
@@ -0,0 +1,43 @@
|
||||
import { Inject, Injectable } from "@nestjs/common";
|
||||
import { DB } from "../../database/database.tokens.js";
|
||||
import type { Database } from "../../prisma/db.js";
|
||||
import type {
|
||||
InventoryMovement,
|
||||
InventoryMovementKey,
|
||||
} from "../../entities/inventory-movement.entity.js";
|
||||
import type { CreateInventoryMovementInput } from "../../dtos/inventory-movement.dto.js";
|
||||
import type { IInventoryMovementRepository } from "./interfaces/inventory-movement-repository.interface.js";
|
||||
|
||||
const COLUMNS = [
|
||||
"id",
|
||||
"productId",
|
||||
"inventoryId",
|
||||
"type",
|
||||
"quantity",
|
||||
"reason",
|
||||
"userId",
|
||||
"createdAt",
|
||||
] as const;
|
||||
|
||||
@Injectable()
|
||||
export class InventoryMovementRepository
|
||||
implements IInventoryMovementRepository
|
||||
{
|
||||
constructor(@Inject(DB) private readonly db: Database) {}
|
||||
|
||||
private get model() {
|
||||
return this.db.orm.public.InventoryMovement;
|
||||
}
|
||||
|
||||
findAll(): Promise<InventoryMovement[]> {
|
||||
return this.model.select(...COLUMNS).all().toArray();
|
||||
}
|
||||
|
||||
findById(where: InventoryMovementKey): Promise<InventoryMovement | null> {
|
||||
return this.model.select(...COLUMNS).where(where).first();
|
||||
}
|
||||
|
||||
create(data: CreateInventoryMovementInput): Promise<InventoryMovement> {
|
||||
return this.model.select(...COLUMNS).create(data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
import { BadRequestException, Inject, Injectable, NotFoundException } from "@nestjs/common";
|
||||
import {
|
||||
PRODUCT_SERVICE,
|
||||
type IProductService,
|
||||
} from "../product/interfaces/product-service.interface.js";
|
||||
import {
|
||||
SUPPLIER_SERVICE,
|
||||
type ISupplierService,
|
||||
} from "../supplier/interfaces/supplier-service.interface.js";
|
||||
import {
|
||||
WAREHOUSE_SERVICE,
|
||||
type IWarehouseService,
|
||||
} from "../warehouse/interfaces/warehouse-service.interface.js";
|
||||
import type {
|
||||
InventoryMovement,
|
||||
InventoryMovementKey,
|
||||
} from "../../entities/inventory-movement.entity.js";
|
||||
import type { CreateInventoryMovementInput } from "../../dtos/inventory-movement.dto.js";
|
||||
import {
|
||||
INVENTORY_MOVEMENT_REPOSITORY,
|
||||
type IInventoryMovementRepository,
|
||||
} from "./interfaces/inventory-movement-repository.interface.js";
|
||||
import type { IInventoryMovementService } from "./interfaces/inventory-movement-service.interface.js";
|
||||
|
||||
/**
|
||||
* El stock de un almacén nunca se edita directamente: cada cambio queda
|
||||
* registrado como un movimiento (entrada/salida), que es quien ajusta
|
||||
* `Warehouse.stock`. Una entrada además actualiza `Supplier.lastSupply`
|
||||
* cuando el producto tiene proveedor asociado.
|
||||
*/
|
||||
@Injectable()
|
||||
export class InventoryMovementService implements IInventoryMovementService {
|
||||
constructor(
|
||||
@Inject(INVENTORY_MOVEMENT_REPOSITORY)
|
||||
private readonly repository: IInventoryMovementRepository,
|
||||
@Inject(WAREHOUSE_SERVICE) private readonly warehouseService: IWarehouseService,
|
||||
@Inject(PRODUCT_SERVICE) private readonly productService: IProductService,
|
||||
@Inject(SUPPLIER_SERVICE) private readonly supplierService: ISupplierService,
|
||||
) {}
|
||||
|
||||
findAll(): Promise<InventoryMovement[]> {
|
||||
return this.repository.findAll();
|
||||
}
|
||||
|
||||
async findById(where: InventoryMovementKey): Promise<InventoryMovement> {
|
||||
const movement = await this.repository.findById(where);
|
||||
if (!movement) {
|
||||
throw new NotFoundException(`InventoryMovement ${where.id} not found`);
|
||||
}
|
||||
return movement;
|
||||
}
|
||||
|
||||
async create(data: CreateInventoryMovementInput): Promise<InventoryMovement> {
|
||||
if (data.quantity <= 0) {
|
||||
throw new BadRequestException("La cantidad debe ser mayor a cero");
|
||||
}
|
||||
if (data.type !== "in" && data.type !== "out") {
|
||||
throw new BadRequestException('El tipo debe ser "in" o "out"');
|
||||
}
|
||||
|
||||
const key = { inventoryId: data.inventoryId, productId: data.productId };
|
||||
const existing = await this.warehouseService
|
||||
.findById(key)
|
||||
.catch(() => null);
|
||||
|
||||
if (data.type === "out") {
|
||||
const currentStock = existing?.stock ?? 0;
|
||||
if (currentStock < data.quantity) {
|
||||
throw new BadRequestException("Stock insuficiente para registrar la salida");
|
||||
}
|
||||
await this.warehouseService.update(key, { stock: currentStock - data.quantity });
|
||||
} else {
|
||||
if (existing) {
|
||||
await this.warehouseService.update(key, { stock: existing.stock + data.quantity });
|
||||
} else {
|
||||
await this.warehouseService.create({ ...key, stock: data.quantity });
|
||||
}
|
||||
|
||||
const product = await this.productService.findById({ id: data.productId }).catch(() => null);
|
||||
if (product?.supplierId) {
|
||||
await this.supplierService.update(
|
||||
{ id: product.supplierId },
|
||||
{ lastSupply: new Date().toISOString() },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return this.repository.create(data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import type { IRepository } from "../../../common/repository.interface.js";
|
||||
import type {
|
||||
Inventory,
|
||||
InventoryKey,
|
||||
} from "../../../entities/inventory.entity.js";
|
||||
import type {
|
||||
CreateInventoryInput,
|
||||
UpdateInventoryInput,
|
||||
} from "../../../dtos/inventory.dto.js";
|
||||
|
||||
export const INVENTORY_REPOSITORY = Symbol("INVENTORY_REPOSITORY");
|
||||
|
||||
export type IInventoryRepository = IRepository<
|
||||
Inventory,
|
||||
CreateInventoryInput,
|
||||
UpdateInventoryInput,
|
||||
InventoryKey
|
||||
>;
|
||||
@@ -0,0 +1,18 @@
|
||||
import type { IService } from "../../../common/service.interface.js";
|
||||
import type {
|
||||
Inventory,
|
||||
InventoryKey,
|
||||
} from "../../../entities/inventory.entity.js";
|
||||
import type {
|
||||
CreateInventoryInput,
|
||||
UpdateInventoryInput,
|
||||
} from "../../../dtos/inventory.dto.js";
|
||||
|
||||
export const INVENTORY_SERVICE = Symbol("INVENTORY_SERVICE");
|
||||
|
||||
export type IInventoryService = IService<
|
||||
Inventory,
|
||||
CreateInventoryInput,
|
||||
UpdateInventoryInput,
|
||||
InventoryKey
|
||||
>;
|
||||
@@ -0,0 +1,53 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Inject,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
Patch,
|
||||
Post,
|
||||
} from "@nestjs/common";
|
||||
import type {
|
||||
CreateInventoryInput,
|
||||
UpdateInventoryInput,
|
||||
} from "../../dtos/inventory.dto.js";
|
||||
import { INVENTORY_SERVICE } from "./interfaces/inventory-service.interface.js";
|
||||
import type { IInventoryService } from "./interfaces/inventory-service.interface.js";
|
||||
|
||||
@Controller("inventories")
|
||||
export class InventoryController {
|
||||
constructor(
|
||||
@Inject(INVENTORY_SERVICE)
|
||||
private readonly inventoryService: IInventoryService,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
findAll() {
|
||||
return this.inventoryService.findAll();
|
||||
}
|
||||
|
||||
@Get(":id")
|
||||
findOne(@Param("id", ParseIntPipe) id: number) {
|
||||
return this.inventoryService.findById({ id });
|
||||
}
|
||||
|
||||
@Post()
|
||||
create(@Body() body: CreateInventoryInput) {
|
||||
return this.inventoryService.create(body);
|
||||
}
|
||||
|
||||
@Patch(":id")
|
||||
update(
|
||||
@Param("id", ParseIntPipe) id: number,
|
||||
@Body() body: UpdateInventoryInput,
|
||||
) {
|
||||
return this.inventoryService.update({ id }, body);
|
||||
}
|
||||
|
||||
@Delete(":id")
|
||||
remove(@Param("id", ParseIntPipe) id: number) {
|
||||
return this.inventoryService.delete({ id });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { INVENTORY_REPOSITORY } from "./interfaces/inventory-repository.interface.js";
|
||||
import { INVENTORY_SERVICE } from "./interfaces/inventory-service.interface.js";
|
||||
import { InventoryController } from "./inventory.controller.js";
|
||||
import { InventoryRepository } from "./inventory.repository.js";
|
||||
import { InventoryService } from "./inventory.service.js";
|
||||
|
||||
@Module({
|
||||
controllers: [InventoryController],
|
||||
providers: [
|
||||
{ provide: INVENTORY_REPOSITORY, useClass: InventoryRepository },
|
||||
{ provide: INVENTORY_SERVICE, useClass: InventoryService },
|
||||
],
|
||||
exports: [INVENTORY_SERVICE],
|
||||
})
|
||||
export class InventoryModule {}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { BaseRepository } from "../../common/base.repository.js";
|
||||
import type {
|
||||
CreateInventoryInput,
|
||||
UpdateInventoryInput,
|
||||
} from "../../dtos/inventory.dto.js";
|
||||
import type {
|
||||
Inventory,
|
||||
InventoryKey,
|
||||
} from "../../entities/inventory.entity.js";
|
||||
import type { IInventoryRepository } from "./interfaces/inventory-repository.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class InventoryRepository
|
||||
extends BaseRepository<
|
||||
Inventory,
|
||||
CreateInventoryInput,
|
||||
UpdateInventoryInput,
|
||||
InventoryKey
|
||||
>
|
||||
implements IInventoryRepository
|
||||
{
|
||||
protected readonly columns = ["id", "name"] as const;
|
||||
|
||||
protected get model() {
|
||||
return this.db.orm.public.Inventory;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { Inject, Injectable } from "@nestjs/common";
|
||||
import { BaseService } from "../../common/base.service.js";
|
||||
import type {
|
||||
CreateInventoryInput,
|
||||
UpdateInventoryInput,
|
||||
} from "../../dtos/inventory.dto.js";
|
||||
import type {
|
||||
Inventory,
|
||||
InventoryKey,
|
||||
} from "../../entities/inventory.entity.js";
|
||||
import {
|
||||
INVENTORY_REPOSITORY,
|
||||
type IInventoryRepository,
|
||||
} from "./interfaces/inventory-repository.interface.js";
|
||||
import type { IInventoryService } from "./interfaces/inventory-service.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class InventoryService
|
||||
extends BaseService<
|
||||
Inventory,
|
||||
CreateInventoryInput,
|
||||
UpdateInventoryInput,
|
||||
InventoryKey
|
||||
>
|
||||
implements IInventoryService
|
||||
{
|
||||
constructor(@Inject(INVENTORY_REPOSITORY) repository: IInventoryRepository) {
|
||||
super(repository);
|
||||
}
|
||||
|
||||
protected override notFoundMessage(where: InventoryKey): string {
|
||||
return `Inventory ${where.id} not found`;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import type { IRepository } from "../../../common/repository.interface.js";
|
||||
import type { OperatingDay, OperatingDayKey } from "../../../entities/operating-day.entity.js";
|
||||
import type { CreateOperatingDayInput, UpdateOperatingDayInput } from "../../../dtos/operating-day.dto.js";
|
||||
|
||||
export const OPERATING_DAY_REPOSITORY = Symbol("OPERATING_DAY_REPOSITORY");
|
||||
|
||||
export type IOperatingDayRepository = IRepository<
|
||||
OperatingDay,
|
||||
CreateOperatingDayInput,
|
||||
UpdateOperatingDayInput,
|
||||
OperatingDayKey
|
||||
>;
|
||||
@@ -0,0 +1,12 @@
|
||||
import type { IService } from "../../../common/service.interface.js";
|
||||
import type { OperatingDay, OperatingDayKey } from "../../../entities/operating-day.entity.js";
|
||||
import type { CreateOperatingDayInput, UpdateOperatingDayInput } from "../../../dtos/operating-day.dto.js";
|
||||
|
||||
export const OPERATING_DAY_SERVICE = Symbol("OPERATING_DAY_SERVICE");
|
||||
|
||||
export type IOperatingDayService = IService<
|
||||
OperatingDay,
|
||||
CreateOperatingDayInput,
|
||||
UpdateOperatingDayInput,
|
||||
OperatingDayKey
|
||||
>;
|
||||
@@ -0,0 +1,37 @@
|
||||
import { Body, Controller, Delete, Get, Inject, Param, ParseIntPipe, Patch, Post } from "@nestjs/common";
|
||||
import type { CreateOperatingDayInput, UpdateOperatingDayInput } from "../../dtos/operating-day.dto.js";
|
||||
import { OPERATING_DAY_SERVICE } from "./interfaces/operating-day-service.interface.js";
|
||||
import type { IOperatingDayService } from "./interfaces/operating-day-service.interface.js";
|
||||
|
||||
@Controller("operating-days")
|
||||
export class OperatingDayController {
|
||||
constructor(
|
||||
@Inject(OPERATING_DAY_SERVICE)
|
||||
private readonly operatingDayService: IOperatingDayService,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
findAll() {
|
||||
return this.operatingDayService.findAll();
|
||||
}
|
||||
|
||||
@Get(":id")
|
||||
findOne(@Param("id", ParseIntPipe) id: number) {
|
||||
return this.operatingDayService.findById({ id });
|
||||
}
|
||||
|
||||
@Post()
|
||||
create(@Body() body: CreateOperatingDayInput) {
|
||||
return this.operatingDayService.create(body);
|
||||
}
|
||||
|
||||
@Patch(":id")
|
||||
update(@Param("id", ParseIntPipe) id: number, @Body() body: UpdateOperatingDayInput) {
|
||||
return this.operatingDayService.update({ id }, body);
|
||||
}
|
||||
|
||||
@Delete(":id")
|
||||
remove(@Param("id", ParseIntPipe) id: number) {
|
||||
return this.operatingDayService.delete({ id });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { CashRegisterSessionModule } from "../cash-register-session/cash-register-session.module.js";
|
||||
import { OPERATING_DAY_REPOSITORY } from "./interfaces/operating-day-repository.interface.js";
|
||||
import { OPERATING_DAY_SERVICE } from "./interfaces/operating-day-service.interface.js";
|
||||
import { OperatingDayController } from "./operating-day.controller.js";
|
||||
import { OperatingDayRepository } from "./operating-day.repository.js";
|
||||
import { OperatingDayService } from "./operating-day.service.js";
|
||||
|
||||
@Module({
|
||||
imports: [CashRegisterSessionModule],
|
||||
controllers: [OperatingDayController],
|
||||
providers: [
|
||||
{ provide: OPERATING_DAY_REPOSITORY, useClass: OperatingDayRepository },
|
||||
{ provide: OPERATING_DAY_SERVICE, useClass: OperatingDayService },
|
||||
],
|
||||
exports: [OPERATING_DAY_SERVICE],
|
||||
})
|
||||
export class OperatingDayModule {}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { BaseRepository } from "../../common/base.repository.js";
|
||||
import type { CreateOperatingDayInput, UpdateOperatingDayInput } from "../../dtos/operating-day.dto.js";
|
||||
import type { OperatingDay, OperatingDayKey } from "../../entities/operating-day.entity.js";
|
||||
import type { IOperatingDayRepository } from "./interfaces/operating-day-repository.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class OperatingDayRepository
|
||||
extends BaseRepository<OperatingDay, CreateOperatingDayInput, UpdateOperatingDayInput, OperatingDayKey>
|
||||
implements IOperatingDayRepository
|
||||
{
|
||||
protected readonly columns = ["id", "date", "status", "openedById", "closedById", "openedAt", "closedAt"] as const;
|
||||
|
||||
protected get model() {
|
||||
return this.db.orm.public.OperatingDay;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import { BadRequestException, Inject, Injectable } from "@nestjs/common";
|
||||
import { BaseService } from "../../common/base.service.js";
|
||||
import type { CreateOperatingDayInput, UpdateOperatingDayInput } from "../../dtos/operating-day.dto.js";
|
||||
import type { OperatingDay, OperatingDayKey } from "../../entities/operating-day.entity.js";
|
||||
import {
|
||||
CASH_REGISTER_SESSION_SERVICE,
|
||||
type ICashRegisterSessionService,
|
||||
} from "../cash-register-session/interfaces/cash-register-session-service.interface.js";
|
||||
import { OPERATING_DAY_REPOSITORY, type IOperatingDayRepository } from "./interfaces/operating-day-repository.interface.js";
|
||||
import type { IOperatingDayService } from "./interfaces/operating-day-service.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class OperatingDayService
|
||||
extends BaseService<OperatingDay, CreateOperatingDayInput, UpdateOperatingDayInput, OperatingDayKey>
|
||||
implements IOperatingDayService
|
||||
{
|
||||
constructor(
|
||||
@Inject(OPERATING_DAY_REPOSITORY)
|
||||
private readonly operatingDayRepository: IOperatingDayRepository,
|
||||
@Inject(CASH_REGISTER_SESSION_SERVICE)
|
||||
private readonly sessionService: ICashRegisterSessionService,
|
||||
) {
|
||||
super(operatingDayRepository);
|
||||
}
|
||||
|
||||
override async create(data: CreateOperatingDayInput): Promise<OperatingDay> {
|
||||
const all = await this.operatingDayRepository.findAll();
|
||||
const alreadyOpen = all.some((d) => d.status === "open");
|
||||
if (alreadyOpen) {
|
||||
throw new BadRequestException("Ya hay una fecha de operación abierta");
|
||||
}
|
||||
return this.operatingDayRepository.create(data);
|
||||
}
|
||||
|
||||
override async update(where: OperatingDayKey, data: UpdateOperatingDayInput): Promise<OperatingDay> {
|
||||
const current = await this.findById(where);
|
||||
|
||||
if (data.status === "closed") {
|
||||
if (current.status === "closed") {
|
||||
throw new BadRequestException("Esta fecha de operación ya está cerrada");
|
||||
}
|
||||
const sessions = await this.sessionService.findAll();
|
||||
const hasOpenSession = sessions.some((s) => s.status === "open");
|
||||
if (hasOpenSession) {
|
||||
throw new BadRequestException("No se puede cerrar el día de operación con cajas abiertas");
|
||||
}
|
||||
if (!data.closedById) {
|
||||
throw new BadRequestException("Falta indicar quién cierra la fecha de operación");
|
||||
}
|
||||
|
||||
const closed = await this.operatingDayRepository.update(where, {
|
||||
...data,
|
||||
closedAt: data.closedAt ?? new Date().toISOString(),
|
||||
});
|
||||
await this.operatingDayRepository.create({ openedById: data.closedById });
|
||||
return closed;
|
||||
}
|
||||
|
||||
return this.operatingDayRepository.update(where, data);
|
||||
}
|
||||
|
||||
protected override notFoundMessage(where: OperatingDayKey): string {
|
||||
return `OperatingDay ${where.id} not found`;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import type { IRepository } from "../../../common/repository.interface.js";
|
||||
import type { Payment, PaymentKey } from "../../../entities/payment.entity.js";
|
||||
import type {
|
||||
CreatePaymentInput,
|
||||
UpdatePaymentInput,
|
||||
} from "../../../dtos/payment.dto.js";
|
||||
|
||||
export const PAYMENT_REPOSITORY = Symbol("PAYMENT_REPOSITORY");
|
||||
|
||||
export type IPaymentRepository = IRepository<
|
||||
Payment,
|
||||
CreatePaymentInput,
|
||||
UpdatePaymentInput,
|
||||
PaymentKey
|
||||
>;
|
||||
@@ -0,0 +1,15 @@
|
||||
import type { IService } from "../../../common/service.interface.js";
|
||||
import type { Payment, PaymentKey } from "../../../entities/payment.entity.js";
|
||||
import type {
|
||||
CreatePaymentInput,
|
||||
UpdatePaymentInput,
|
||||
} from "../../../dtos/payment.dto.js";
|
||||
|
||||
export const PAYMENT_SERVICE = Symbol("PAYMENT_SERVICE");
|
||||
|
||||
export type IPaymentService = IService<
|
||||
Payment,
|
||||
CreatePaymentInput,
|
||||
UpdatePaymentInput,
|
||||
PaymentKey
|
||||
>;
|
||||
@@ -0,0 +1,52 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Inject,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
Patch,
|
||||
Post,
|
||||
} from "@nestjs/common";
|
||||
import type {
|
||||
CreatePaymentInput,
|
||||
UpdatePaymentInput,
|
||||
} from "../../dtos/payment.dto.js";
|
||||
import { PAYMENT_SERVICE } from "./interfaces/payment-service.interface.js";
|
||||
import type { IPaymentService } from "./interfaces/payment-service.interface.js";
|
||||
|
||||
@Controller("payments")
|
||||
export class PaymentController {
|
||||
constructor(
|
||||
@Inject(PAYMENT_SERVICE) private readonly paymentService: IPaymentService,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
findAll() {
|
||||
return this.paymentService.findAll();
|
||||
}
|
||||
|
||||
@Get(":id")
|
||||
findOne(@Param("id", ParseIntPipe) id: number) {
|
||||
return this.paymentService.findById({ id });
|
||||
}
|
||||
|
||||
@Post()
|
||||
create(@Body() body: CreatePaymentInput) {
|
||||
return this.paymentService.create(body);
|
||||
}
|
||||
|
||||
@Patch(":id")
|
||||
update(
|
||||
@Param("id", ParseIntPipe) id: number,
|
||||
@Body() body: UpdatePaymentInput,
|
||||
) {
|
||||
return this.paymentService.update({ id }, body);
|
||||
}
|
||||
|
||||
@Delete(":id")
|
||||
remove(@Param("id", ParseIntPipe) id: number) {
|
||||
return this.paymentService.delete({ id });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { PAYMENT_REPOSITORY } from "./interfaces/payment-repository.interface.js";
|
||||
import { PAYMENT_SERVICE } from "./interfaces/payment-service.interface.js";
|
||||
import { PaymentController } from "./payment.controller.js";
|
||||
import { PaymentRepository } from "./payment.repository.js";
|
||||
import { PaymentService } from "./payment.service.js";
|
||||
|
||||
@Module({
|
||||
controllers: [PaymentController],
|
||||
providers: [
|
||||
{ provide: PAYMENT_REPOSITORY, useClass: PaymentRepository },
|
||||
{ provide: PAYMENT_SERVICE, useClass: PaymentService },
|
||||
],
|
||||
exports: [PAYMENT_SERVICE],
|
||||
})
|
||||
export class PaymentModule {}
|
||||
@@ -0,0 +1,37 @@
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { BaseRepository } from "../../common/base.repository.js";
|
||||
import type {
|
||||
CreatePaymentInput,
|
||||
UpdatePaymentInput,
|
||||
} from "../../dtos/payment.dto.js";
|
||||
import type { Payment, PaymentKey } from "../../entities/payment.entity.js";
|
||||
import type { IPaymentRepository } from "./interfaces/payment-repository.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class PaymentRepository
|
||||
extends BaseRepository<
|
||||
Payment,
|
||||
CreatePaymentInput,
|
||||
UpdatePaymentInput,
|
||||
PaymentKey
|
||||
>
|
||||
implements IPaymentRepository
|
||||
{
|
||||
protected readonly columns = [
|
||||
"id",
|
||||
"cartId",
|
||||
"userId",
|
||||
"amount",
|
||||
"orderId",
|
||||
"terminalId",
|
||||
"status",
|
||||
"paid",
|
||||
"paymentMethod",
|
||||
"paidAt",
|
||||
"createdAt",
|
||||
] as const;
|
||||
|
||||
protected get model() {
|
||||
return this.db.orm.public.Payment;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { Inject, Injectable } from "@nestjs/common";
|
||||
import { BaseService } from "../../common/base.service.js";
|
||||
import type {
|
||||
CreatePaymentInput,
|
||||
UpdatePaymentInput,
|
||||
} from "../../dtos/payment.dto.js";
|
||||
import type { Payment, PaymentKey } from "../../entities/payment.entity.js";
|
||||
import {
|
||||
PAYMENT_REPOSITORY,
|
||||
type IPaymentRepository,
|
||||
} from "./interfaces/payment-repository.interface.js";
|
||||
import type { IPaymentService } from "./interfaces/payment-service.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class PaymentService
|
||||
extends BaseService<
|
||||
Payment,
|
||||
CreatePaymentInput,
|
||||
UpdatePaymentInput,
|
||||
PaymentKey
|
||||
>
|
||||
implements IPaymentService
|
||||
{
|
||||
constructor(@Inject(PAYMENT_REPOSITORY) repository: IPaymentRepository) {
|
||||
super(repository);
|
||||
}
|
||||
|
||||
protected override notFoundMessage(where: PaymentKey): string {
|
||||
return `Payment ${where.id} not found`;
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
import type { IRepository } from "../../../common/repository.interface.js";
|
||||
import type {
|
||||
ProductCategory,
|
||||
ProductCategoryKey,
|
||||
} from "../../../entities/product-category.entity.js";
|
||||
import type {
|
||||
CreateProductCategoryInput,
|
||||
UpdateProductCategoryInput,
|
||||
} from "../../../dtos/product-category.dto.js";
|
||||
|
||||
export const PRODUCT_CATEGORY_REPOSITORY = Symbol(
|
||||
"PRODUCT_CATEGORY_REPOSITORY",
|
||||
);
|
||||
|
||||
export type IProductCategoryRepository = IRepository<
|
||||
ProductCategory,
|
||||
CreateProductCategoryInput,
|
||||
UpdateProductCategoryInput,
|
||||
ProductCategoryKey
|
||||
>;
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
import type { IService } from "../../../common/service.interface.js";
|
||||
import type {
|
||||
ProductCategory,
|
||||
ProductCategoryKey,
|
||||
} from "../../../entities/product-category.entity.js";
|
||||
import type {
|
||||
CreateProductCategoryInput,
|
||||
UpdateProductCategoryInput,
|
||||
} from "../../../dtos/product-category.dto.js";
|
||||
|
||||
export const PRODUCT_CATEGORY_SERVICE = Symbol("PRODUCT_CATEGORY_SERVICE");
|
||||
|
||||
export type IProductCategoryService = IService<
|
||||
ProductCategory,
|
||||
CreateProductCategoryInput,
|
||||
UpdateProductCategoryInput,
|
||||
ProductCategoryKey
|
||||
>;
|
||||
@@ -0,0 +1,47 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Inject,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
Post,
|
||||
} from "@nestjs/common";
|
||||
import type { CreateProductCategoryInput } from "../../dtos/product-category.dto.js";
|
||||
import { PRODUCT_CATEGORY_SERVICE } from "./interfaces/product-category-service.interface.js";
|
||||
import type { IProductCategoryService } from "./interfaces/product-category-service.interface.js";
|
||||
|
||||
@Controller("product-categories")
|
||||
export class ProductCategoryController {
|
||||
constructor(
|
||||
@Inject(PRODUCT_CATEGORY_SERVICE)
|
||||
private readonly productCategoryService: IProductCategoryService,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
findAll() {
|
||||
return this.productCategoryService.findAll();
|
||||
}
|
||||
|
||||
@Get(":productId/:categoryId")
|
||||
findOne(
|
||||
@Param("productId", ParseIntPipe) productId: number,
|
||||
@Param("categoryId", ParseIntPipe) categoryId: number,
|
||||
) {
|
||||
return this.productCategoryService.findById({ productId, categoryId });
|
||||
}
|
||||
|
||||
@Post()
|
||||
create(@Body() body: CreateProductCategoryInput) {
|
||||
return this.productCategoryService.create(body);
|
||||
}
|
||||
|
||||
@Delete(":productId/:categoryId")
|
||||
remove(
|
||||
@Param("productId", ParseIntPipe) productId: number,
|
||||
@Param("categoryId", ParseIntPipe) categoryId: number,
|
||||
) {
|
||||
return this.productCategoryService.delete({ productId, categoryId });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { PRODUCT_CATEGORY_REPOSITORY } from "./interfaces/product-category-repository.interface.js";
|
||||
import { PRODUCT_CATEGORY_SERVICE } from "./interfaces/product-category-service.interface.js";
|
||||
import { ProductCategoryController } from "./product-category.controller.js";
|
||||
import { ProductCategoryRepository } from "./product-category.repository.js";
|
||||
import { ProductCategoryService } from "./product-category.service.js";
|
||||
|
||||
@Module({
|
||||
controllers: [ProductCategoryController],
|
||||
providers: [
|
||||
{
|
||||
provide: PRODUCT_CATEGORY_REPOSITORY,
|
||||
useClass: ProductCategoryRepository,
|
||||
},
|
||||
{ provide: PRODUCT_CATEGORY_SERVICE, useClass: ProductCategoryService },
|
||||
],
|
||||
exports: [PRODUCT_CATEGORY_SERVICE],
|
||||
})
|
||||
export class ProductCategoryModule {}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { BaseRepository } from "../../common/base.repository.js";
|
||||
import type {
|
||||
CreateProductCategoryInput,
|
||||
UpdateProductCategoryInput,
|
||||
} from "../../dtos/product-category.dto.js";
|
||||
import type {
|
||||
ProductCategory,
|
||||
ProductCategoryKey,
|
||||
} from "../../entities/product-category.entity.js";
|
||||
import type { IProductCategoryRepository } from "./interfaces/product-category-repository.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class ProductCategoryRepository
|
||||
extends BaseRepository<
|
||||
ProductCategory,
|
||||
CreateProductCategoryInput,
|
||||
UpdateProductCategoryInput,
|
||||
ProductCategoryKey
|
||||
>
|
||||
implements IProductCategoryRepository
|
||||
{
|
||||
protected readonly columns = ["productId", "categoryId"] as const;
|
||||
|
||||
protected get model() {
|
||||
return this.db.orm.public.ProductCategory;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import { Inject, Injectable } from "@nestjs/common";
|
||||
import { BaseService } from "../../common/base.service.js";
|
||||
import type {
|
||||
CreateProductCategoryInput,
|
||||
UpdateProductCategoryInput,
|
||||
} from "../../dtos/product-category.dto.js";
|
||||
import type {
|
||||
ProductCategory,
|
||||
ProductCategoryKey,
|
||||
} from "../../entities/product-category.entity.js";
|
||||
import {
|
||||
PRODUCT_CATEGORY_REPOSITORY,
|
||||
type IProductCategoryRepository,
|
||||
} from "./interfaces/product-category-repository.interface.js";
|
||||
import type { IProductCategoryService } from "./interfaces/product-category-service.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class ProductCategoryService
|
||||
extends BaseService<
|
||||
ProductCategory,
|
||||
CreateProductCategoryInput,
|
||||
UpdateProductCategoryInput,
|
||||
ProductCategoryKey
|
||||
>
|
||||
implements IProductCategoryService
|
||||
{
|
||||
constructor(
|
||||
@Inject(PRODUCT_CATEGORY_REPOSITORY) repository: IProductCategoryRepository,
|
||||
) {
|
||||
super(repository);
|
||||
}
|
||||
|
||||
protected override notFoundMessage(where: ProductCategoryKey): string {
|
||||
return `ProductCategory (${where.productId}, ${where.categoryId}) not found`;
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
import type { IRepository } from "../../../common/repository.interface.js";
|
||||
import type {
|
||||
ProductHistory,
|
||||
ProductHistoryKey,
|
||||
} from "../../../entities/product-history.entity.js";
|
||||
import type {
|
||||
CreateProductHistoryInput,
|
||||
UpdateProductHistoryInput,
|
||||
} from "../../../dtos/product-history.dto.js";
|
||||
|
||||
export const PRODUCT_HISTORY_REPOSITORY = Symbol("PRODUCT_HISTORY_REPOSITORY");
|
||||
|
||||
export type IProductHistoryRepository = IRepository<
|
||||
ProductHistory,
|
||||
CreateProductHistoryInput,
|
||||
UpdateProductHistoryInput,
|
||||
ProductHistoryKey
|
||||
>;
|
||||
@@ -0,0 +1,18 @@
|
||||
import type { IService } from "../../../common/service.interface.js";
|
||||
import type {
|
||||
ProductHistory,
|
||||
ProductHistoryKey,
|
||||
} from "../../../entities/product-history.entity.js";
|
||||
import type {
|
||||
CreateProductHistoryInput,
|
||||
UpdateProductHistoryInput,
|
||||
} from "../../../dtos/product-history.dto.js";
|
||||
|
||||
export const PRODUCT_HISTORY_SERVICE = Symbol("PRODUCT_HISTORY_SERVICE");
|
||||
|
||||
export type IProductHistoryService = IService<
|
||||
ProductHistory,
|
||||
CreateProductHistoryInput,
|
||||
UpdateProductHistoryInput,
|
||||
ProductHistoryKey
|
||||
>;
|
||||
@@ -0,0 +1,53 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Inject,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
Patch,
|
||||
Post,
|
||||
} from "@nestjs/common";
|
||||
import type {
|
||||
CreateProductHistoryInput,
|
||||
UpdateProductHistoryInput,
|
||||
} from "../../dtos/product-history.dto.js";
|
||||
import { PRODUCT_HISTORY_SERVICE } from "./interfaces/product-history-service.interface.js";
|
||||
import type { IProductHistoryService } from "./interfaces/product-history-service.interface.js";
|
||||
|
||||
@Controller("product-history")
|
||||
export class ProductHistoryController {
|
||||
constructor(
|
||||
@Inject(PRODUCT_HISTORY_SERVICE)
|
||||
private readonly productHistoryService: IProductHistoryService,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
findAll() {
|
||||
return this.productHistoryService.findAll();
|
||||
}
|
||||
|
||||
@Get(":id")
|
||||
findOne(@Param("id", ParseIntPipe) id: number) {
|
||||
return this.productHistoryService.findById({ id });
|
||||
}
|
||||
|
||||
@Post()
|
||||
create(@Body() body: CreateProductHistoryInput) {
|
||||
return this.productHistoryService.create(body);
|
||||
}
|
||||
|
||||
@Patch(":id")
|
||||
update(
|
||||
@Param("id", ParseIntPipe) id: number,
|
||||
@Body() body: UpdateProductHistoryInput,
|
||||
) {
|
||||
return this.productHistoryService.update({ id }, body);
|
||||
}
|
||||
|
||||
@Delete(":id")
|
||||
remove(@Param("id", ParseIntPipe) id: number) {
|
||||
return this.productHistoryService.delete({ id });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { PRODUCT_HISTORY_REPOSITORY } from "./interfaces/product-history-repository.interface.js";
|
||||
import { PRODUCT_HISTORY_SERVICE } from "./interfaces/product-history-service.interface.js";
|
||||
import { ProductHistoryController } from "./product-history.controller.js";
|
||||
import { ProductHistoryRepository } from "./product-history.repository.js";
|
||||
import { ProductHistoryService } from "./product-history.service.js";
|
||||
|
||||
@Module({
|
||||
controllers: [ProductHistoryController],
|
||||
providers: [
|
||||
{ provide: PRODUCT_HISTORY_REPOSITORY, useClass: ProductHistoryRepository },
|
||||
{ provide: PRODUCT_HISTORY_SERVICE, useClass: ProductHistoryService },
|
||||
],
|
||||
exports: [PRODUCT_HISTORY_SERVICE],
|
||||
})
|
||||
export class ProductHistoryModule {}
|
||||
@@ -0,0 +1,36 @@
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { BaseRepository } from "../../common/base.repository.js";
|
||||
import type {
|
||||
CreateProductHistoryInput,
|
||||
UpdateProductHistoryInput,
|
||||
} from "../../dtos/product-history.dto.js";
|
||||
import type {
|
||||
ProductHistory,
|
||||
ProductHistoryKey,
|
||||
} from "../../entities/product-history.entity.js";
|
||||
import type { IProductHistoryRepository } from "./interfaces/product-history-repository.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class ProductHistoryRepository
|
||||
extends BaseRepository<
|
||||
ProductHistory,
|
||||
CreateProductHistoryInput,
|
||||
UpdateProductHistoryInput,
|
||||
ProductHistoryKey
|
||||
>
|
||||
implements IProductHistoryRepository
|
||||
{
|
||||
protected readonly columns = [
|
||||
"id",
|
||||
"productId",
|
||||
"unitPrice",
|
||||
"costUnit",
|
||||
"status",
|
||||
"createdAt",
|
||||
"soldAt",
|
||||
] as const;
|
||||
|
||||
protected get model() {
|
||||
return this.db.orm.public.ProductHistory;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import { Inject, Injectable } from "@nestjs/common";
|
||||
import { BaseService } from "../../common/base.service.js";
|
||||
import type {
|
||||
CreateProductHistoryInput,
|
||||
UpdateProductHistoryInput,
|
||||
} from "../../dtos/product-history.dto.js";
|
||||
import type {
|
||||
ProductHistory,
|
||||
ProductHistoryKey,
|
||||
} from "../../entities/product-history.entity.js";
|
||||
import {
|
||||
PRODUCT_HISTORY_REPOSITORY,
|
||||
type IProductHistoryRepository,
|
||||
} from "./interfaces/product-history-repository.interface.js";
|
||||
import type { IProductHistoryService } from "./interfaces/product-history-service.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class ProductHistoryService
|
||||
extends BaseService<
|
||||
ProductHistory,
|
||||
CreateProductHistoryInput,
|
||||
UpdateProductHistoryInput,
|
||||
ProductHistoryKey
|
||||
>
|
||||
implements IProductHistoryService
|
||||
{
|
||||
constructor(
|
||||
@Inject(PRODUCT_HISTORY_REPOSITORY) repository: IProductHistoryRepository,
|
||||
) {
|
||||
super(repository);
|
||||
}
|
||||
|
||||
protected override notFoundMessage(where: ProductHistoryKey): string {
|
||||
return `ProductHistory ${where.id} not found`;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import type { IRepository } from "../../../common/repository.interface.js";
|
||||
import type { Product, ProductKey } from "../../../entities/product.entity.js";
|
||||
import type {
|
||||
CreateProductInput,
|
||||
UpdateProductInput,
|
||||
} from "../../../dtos/product.dto.js";
|
||||
|
||||
export const PRODUCT_REPOSITORY = Symbol("PRODUCT_REPOSITORY");
|
||||
|
||||
export type IProductRepository = IRepository<
|
||||
Product,
|
||||
CreateProductInput,
|
||||
UpdateProductInput,
|
||||
ProductKey
|
||||
>;
|
||||
@@ -0,0 +1,15 @@
|
||||
import type { IService } from "../../../common/service.interface.js";
|
||||
import type { Product, ProductKey } from "../../../entities/product.entity.js";
|
||||
import type {
|
||||
CreateProductInput,
|
||||
UpdateProductInput,
|
||||
} from "../../../dtos/product.dto.js";
|
||||
|
||||
export const PRODUCT_SERVICE = Symbol("PRODUCT_SERVICE");
|
||||
|
||||
export type IProductService = IService<
|
||||
Product,
|
||||
CreateProductInput,
|
||||
UpdateProductInput,
|
||||
ProductKey
|
||||
>;
|
||||
@@ -0,0 +1,52 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Inject,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
Patch,
|
||||
Post,
|
||||
} from "@nestjs/common";
|
||||
import type {
|
||||
CreateProductInput,
|
||||
UpdateProductInput,
|
||||
} from "../../dtos/product.dto.js";
|
||||
import { PRODUCT_SERVICE } from "./interfaces/product-service.interface.js";
|
||||
import type { IProductService } from "./interfaces/product-service.interface.js";
|
||||
|
||||
@Controller("products")
|
||||
export class ProductController {
|
||||
constructor(
|
||||
@Inject(PRODUCT_SERVICE) private readonly productService: IProductService,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
findAll() {
|
||||
return this.productService.findAll();
|
||||
}
|
||||
|
||||
@Get(":id")
|
||||
findOne(@Param("id", ParseIntPipe) id: number) {
|
||||
return this.productService.findById({ id });
|
||||
}
|
||||
|
||||
@Post()
|
||||
create(@Body() body: CreateProductInput) {
|
||||
return this.productService.create(body);
|
||||
}
|
||||
|
||||
@Patch(":id")
|
||||
update(
|
||||
@Param("id", ParseIntPipe) id: number,
|
||||
@Body() body: UpdateProductInput,
|
||||
) {
|
||||
return this.productService.update({ id }, body);
|
||||
}
|
||||
|
||||
@Delete(":id")
|
||||
remove(@Param("id", ParseIntPipe) id: number) {
|
||||
return this.productService.delete({ id });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { PRODUCT_REPOSITORY } from "./interfaces/product-repository.interface.js";
|
||||
import { PRODUCT_SERVICE } from "./interfaces/product-service.interface.js";
|
||||
import { ProductController } from "./product.controller.js";
|
||||
import { ProductRepository } from "./product.repository.js";
|
||||
import { ProductService } from "./product.service.js";
|
||||
|
||||
@Module({
|
||||
controllers: [ProductController],
|
||||
providers: [
|
||||
{ provide: PRODUCT_REPOSITORY, useClass: ProductRepository },
|
||||
{ provide: PRODUCT_SERVICE, useClass: ProductService },
|
||||
],
|
||||
exports: [PRODUCT_SERVICE],
|
||||
})
|
||||
export class ProductModule {}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { BaseRepository } from "../../common/base.repository.js";
|
||||
import type {
|
||||
CreateProductInput,
|
||||
UpdateProductInput,
|
||||
} from "../../dtos/product.dto.js";
|
||||
import type { Product, ProductKey } from "../../entities/product.entity.js";
|
||||
import type { IProductRepository } from "./interfaces/product-repository.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class ProductRepository
|
||||
extends BaseRepository<
|
||||
Product,
|
||||
CreateProductInput,
|
||||
UpdateProductInput,
|
||||
ProductKey
|
||||
>
|
||||
implements IProductRepository
|
||||
{
|
||||
protected readonly columns = [
|
||||
"id",
|
||||
"name",
|
||||
"description",
|
||||
"sku",
|
||||
"barcode",
|
||||
"minStock",
|
||||
"imageUrl",
|
||||
"createdAt",
|
||||
"supplierId",
|
||||
] as const;
|
||||
|
||||
protected get model() {
|
||||
return this.db.orm.public.Product;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { Inject, Injectable } from "@nestjs/common";
|
||||
import { BaseService } from "../../common/base.service.js";
|
||||
import type {
|
||||
CreateProductInput,
|
||||
UpdateProductInput,
|
||||
} from "../../dtos/product.dto.js";
|
||||
import type { Product, ProductKey } from "../../entities/product.entity.js";
|
||||
import {
|
||||
PRODUCT_REPOSITORY,
|
||||
type IProductRepository,
|
||||
} from "./interfaces/product-repository.interface.js";
|
||||
import type { IProductService } from "./interfaces/product-service.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class ProductService
|
||||
extends BaseService<
|
||||
Product,
|
||||
CreateProductInput,
|
||||
UpdateProductInput,
|
||||
ProductKey
|
||||
>
|
||||
implements IProductService
|
||||
{
|
||||
constructor(@Inject(PRODUCT_REPOSITORY) repository: IProductRepository) {
|
||||
super(repository);
|
||||
}
|
||||
|
||||
protected override notFoundMessage(where: ProductKey): string {
|
||||
return `Product ${where.id} not found`;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import type { IRepository } from "../../../common/repository.interface.js";
|
||||
import type {
|
||||
ShopCart,
|
||||
ShopCartKey,
|
||||
} from "../../../entities/shop-cart.entity.js";
|
||||
import type {
|
||||
CreateShopCartInput,
|
||||
UpdateShopCartInput,
|
||||
} from "../../../dtos/shop-cart.dto.js";
|
||||
|
||||
export const SHOP_CART_REPOSITORY = Symbol("SHOP_CART_REPOSITORY");
|
||||
|
||||
export type IShopCartRepository = IRepository<
|
||||
ShopCart,
|
||||
CreateShopCartInput,
|
||||
UpdateShopCartInput,
|
||||
ShopCartKey
|
||||
>;
|
||||
@@ -0,0 +1,18 @@
|
||||
import type { IService } from "../../../common/service.interface.js";
|
||||
import type {
|
||||
ShopCart,
|
||||
ShopCartKey,
|
||||
} from "../../../entities/shop-cart.entity.js";
|
||||
import type {
|
||||
CreateShopCartInput,
|
||||
UpdateShopCartInput,
|
||||
} from "../../../dtos/shop-cart.dto.js";
|
||||
|
||||
export const SHOP_CART_SERVICE = Symbol("SHOP_CART_SERVICE");
|
||||
|
||||
export type IShopCartService = IService<
|
||||
ShopCart,
|
||||
CreateShopCartInput,
|
||||
UpdateShopCartInput,
|
||||
ShopCartKey
|
||||
>;
|
||||
@@ -0,0 +1,53 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Inject,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
Patch,
|
||||
Post,
|
||||
} from "@nestjs/common";
|
||||
import type {
|
||||
CreateShopCartInput,
|
||||
UpdateShopCartInput,
|
||||
} from "../../dtos/shop-cart.dto.js";
|
||||
import { SHOP_CART_SERVICE } from "./interfaces/shop-cart-service.interface.js";
|
||||
import type { IShopCartService } from "./interfaces/shop-cart-service.interface.js";
|
||||
|
||||
@Controller("shop-carts")
|
||||
export class ShopCartController {
|
||||
constructor(
|
||||
@Inject(SHOP_CART_SERVICE)
|
||||
private readonly shopCartService: IShopCartService,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
findAll() {
|
||||
return this.shopCartService.findAll();
|
||||
}
|
||||
|
||||
@Get(":id")
|
||||
findOne(@Param("id", ParseIntPipe) id: number) {
|
||||
return this.shopCartService.findById({ id });
|
||||
}
|
||||
|
||||
@Post()
|
||||
create(@Body() body: CreateShopCartInput) {
|
||||
return this.shopCartService.create(body);
|
||||
}
|
||||
|
||||
@Patch(":id")
|
||||
update(
|
||||
@Param("id", ParseIntPipe) id: number,
|
||||
@Body() body: UpdateShopCartInput,
|
||||
) {
|
||||
return this.shopCartService.update({ id }, body);
|
||||
}
|
||||
|
||||
@Delete(":id")
|
||||
remove(@Param("id", ParseIntPipe) id: number) {
|
||||
return this.shopCartService.delete({ id });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { SHOP_CART_REPOSITORY } from "./interfaces/shop-cart-repository.interface.js";
|
||||
import { SHOP_CART_SERVICE } from "./interfaces/shop-cart-service.interface.js";
|
||||
import { ShopCartController } from "./shop-cart.controller.js";
|
||||
import { ShopCartRepository } from "./shop-cart.repository.js";
|
||||
import { ShopCartService } from "./shop-cart.service.js";
|
||||
|
||||
@Module({
|
||||
controllers: [ShopCartController],
|
||||
providers: [
|
||||
{ provide: SHOP_CART_REPOSITORY, useClass: ShopCartRepository },
|
||||
{ provide: SHOP_CART_SERVICE, useClass: ShopCartService },
|
||||
],
|
||||
exports: [SHOP_CART_SERVICE],
|
||||
})
|
||||
export class ShopCartModule {}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { BaseRepository } from "../../common/base.repository.js";
|
||||
import type {
|
||||
CreateShopCartInput,
|
||||
UpdateShopCartInput,
|
||||
} from "../../dtos/shop-cart.dto.js";
|
||||
import type { ShopCart, ShopCartKey } from "../../entities/shop-cart.entity.js";
|
||||
import type { IShopCartRepository } from "./interfaces/shop-cart-repository.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class ShopCartRepository
|
||||
extends BaseRepository<
|
||||
ShopCart,
|
||||
CreateShopCartInput,
|
||||
UpdateShopCartInput,
|
||||
ShopCartKey
|
||||
>
|
||||
implements IShopCartRepository
|
||||
{
|
||||
protected readonly columns = [
|
||||
"id",
|
||||
"totalPrice",
|
||||
"discount",
|
||||
"status",
|
||||
"createdAt",
|
||||
"userId",
|
||||
"customerId",
|
||||
] as const;
|
||||
|
||||
protected get model() {
|
||||
return this.db.orm.public.ShopCart;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { Inject, Injectable } from "@nestjs/common";
|
||||
import { BaseService } from "../../common/base.service.js";
|
||||
import type {
|
||||
CreateShopCartInput,
|
||||
UpdateShopCartInput,
|
||||
} from "../../dtos/shop-cart.dto.js";
|
||||
import type { ShopCart, ShopCartKey } from "../../entities/shop-cart.entity.js";
|
||||
import {
|
||||
SHOP_CART_REPOSITORY,
|
||||
type IShopCartRepository,
|
||||
} from "./interfaces/shop-cart-repository.interface.js";
|
||||
import type { IShopCartService } from "./interfaces/shop-cart-service.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class ShopCartService
|
||||
extends BaseService<
|
||||
ShopCart,
|
||||
CreateShopCartInput,
|
||||
UpdateShopCartInput,
|
||||
ShopCartKey
|
||||
>
|
||||
implements IShopCartService
|
||||
{
|
||||
constructor(@Inject(SHOP_CART_REPOSITORY) repository: IShopCartRepository) {
|
||||
super(repository);
|
||||
}
|
||||
|
||||
protected override notFoundMessage(where: ShopCartKey): string {
|
||||
return `ShopCart ${where.id} not found`;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import type { IRepository } from "../../../common/repository.interface.js";
|
||||
import type {
|
||||
Supplier,
|
||||
SupplierKey,
|
||||
} from "../../../entities/supplier.entity.js";
|
||||
import type {
|
||||
CreateSupplierInput,
|
||||
UpdateSupplierInput,
|
||||
} from "../../../dtos/supplier.dto.js";
|
||||
|
||||
export const SUPPLIER_REPOSITORY = Symbol("SUPPLIER_REPOSITORY");
|
||||
|
||||
export type ISupplierRepository = IRepository<
|
||||
Supplier,
|
||||
CreateSupplierInput,
|
||||
UpdateSupplierInput,
|
||||
SupplierKey
|
||||
>;
|
||||
@@ -0,0 +1,18 @@
|
||||
import type { IService } from "../../../common/service.interface.js";
|
||||
import type {
|
||||
Supplier,
|
||||
SupplierKey,
|
||||
} from "../../../entities/supplier.entity.js";
|
||||
import type {
|
||||
CreateSupplierInput,
|
||||
UpdateSupplierInput,
|
||||
} from "../../../dtos/supplier.dto.js";
|
||||
|
||||
export const SUPPLIER_SERVICE = Symbol("SUPPLIER_SERVICE");
|
||||
|
||||
export type ISupplierService = IService<
|
||||
Supplier,
|
||||
CreateSupplierInput,
|
||||
UpdateSupplierInput,
|
||||
SupplierKey
|
||||
>;
|
||||
@@ -0,0 +1,53 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Inject,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
Patch,
|
||||
Post,
|
||||
} from "@nestjs/common";
|
||||
import type {
|
||||
CreateSupplierInput,
|
||||
UpdateSupplierInput,
|
||||
} from "../../dtos/supplier.dto.js";
|
||||
import { SUPPLIER_SERVICE } from "./interfaces/supplier-service.interface.js";
|
||||
import type { ISupplierService } from "./interfaces/supplier-service.interface.js";
|
||||
|
||||
@Controller("suppliers")
|
||||
export class SupplierController {
|
||||
constructor(
|
||||
@Inject(SUPPLIER_SERVICE)
|
||||
private readonly supplierService: ISupplierService,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
findAll() {
|
||||
return this.supplierService.findAll();
|
||||
}
|
||||
|
||||
@Get(":id")
|
||||
findOne(@Param("id", ParseIntPipe) id: number) {
|
||||
return this.supplierService.findById({ id });
|
||||
}
|
||||
|
||||
@Post()
|
||||
create(@Body() body: CreateSupplierInput) {
|
||||
return this.supplierService.create(body);
|
||||
}
|
||||
|
||||
@Patch(":id")
|
||||
update(
|
||||
@Param("id", ParseIntPipe) id: number,
|
||||
@Body() body: UpdateSupplierInput,
|
||||
) {
|
||||
return this.supplierService.update({ id }, body);
|
||||
}
|
||||
|
||||
@Delete(":id")
|
||||
remove(@Param("id", ParseIntPipe) id: number) {
|
||||
return this.supplierService.delete({ id });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { SUPPLIER_REPOSITORY } from "./interfaces/supplier-repository.interface.js";
|
||||
import { SUPPLIER_SERVICE } from "./interfaces/supplier-service.interface.js";
|
||||
import { SupplierController } from "./supplier.controller.js";
|
||||
import { SupplierRepository } from "./supplier.repository.js";
|
||||
import { SupplierService } from "./supplier.service.js";
|
||||
|
||||
@Module({
|
||||
controllers: [SupplierController],
|
||||
providers: [
|
||||
{ provide: SUPPLIER_REPOSITORY, useClass: SupplierRepository },
|
||||
{ provide: SUPPLIER_SERVICE, useClass: SupplierService },
|
||||
],
|
||||
exports: [SUPPLIER_SERVICE],
|
||||
})
|
||||
export class SupplierModule {}
|
||||
@@ -0,0 +1,30 @@
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { BaseRepository } from "../../common/base.repository.js";
|
||||
import type {
|
||||
CreateSupplierInput,
|
||||
UpdateSupplierInput,
|
||||
} from "../../dtos/supplier.dto.js";
|
||||
import type { Supplier, SupplierKey } from "../../entities/supplier.entity.js";
|
||||
import type { ISupplierRepository } from "./interfaces/supplier-repository.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class SupplierRepository
|
||||
extends BaseRepository<
|
||||
Supplier,
|
||||
CreateSupplierInput,
|
||||
UpdateSupplierInput,
|
||||
SupplierKey
|
||||
>
|
||||
implements ISupplierRepository
|
||||
{
|
||||
protected readonly columns = [
|
||||
"id",
|
||||
"name",
|
||||
"lastSupply",
|
||||
"createdAt",
|
||||
] as const;
|
||||
|
||||
protected get model() {
|
||||
return this.db.orm.public.Supplier;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { Inject, Injectable } from "@nestjs/common";
|
||||
import { BaseService } from "../../common/base.service.js";
|
||||
import type {
|
||||
CreateSupplierInput,
|
||||
UpdateSupplierInput,
|
||||
} from "../../dtos/supplier.dto.js";
|
||||
import type { Supplier, SupplierKey } from "../../entities/supplier.entity.js";
|
||||
import {
|
||||
SUPPLIER_REPOSITORY,
|
||||
type ISupplierRepository,
|
||||
} from "./interfaces/supplier-repository.interface.js";
|
||||
import type { ISupplierService } from "./interfaces/supplier-service.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class SupplierService
|
||||
extends BaseService<
|
||||
Supplier,
|
||||
CreateSupplierInput,
|
||||
UpdateSupplierInput,
|
||||
SupplierKey
|
||||
>
|
||||
implements ISupplierService
|
||||
{
|
||||
constructor(@Inject(SUPPLIER_REPOSITORY) repository: ISupplierRepository) {
|
||||
super(repository);
|
||||
}
|
||||
|
||||
protected override notFoundMessage(where: SupplierKey): string {
|
||||
return `Supplier ${where.id} not found`;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import type { IRepository } from "../../../common/repository.interface.js";
|
||||
import type { User, UserKey } from "../../../entities/user.entity.js";
|
||||
import type {
|
||||
CreateUserInput,
|
||||
UpdateUserInput,
|
||||
} from "../../../dtos/user.dto.js";
|
||||
|
||||
export const USER_REPOSITORY = Symbol("USER_REPOSITORY");
|
||||
|
||||
export type IUserRepository = IRepository<
|
||||
User,
|
||||
CreateUserInput,
|
||||
UpdateUserInput,
|
||||
UserKey
|
||||
> & {
|
||||
findWithPassword(
|
||||
where: UserKey,
|
||||
): Promise<{ id: number; password: string } | null>;
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
import type { IService } from "../../../common/service.interface.js";
|
||||
import type { User, UserKey } from "../../../entities/user.entity.js";
|
||||
import type {
|
||||
CreateUserInput,
|
||||
UpdateUserInput,
|
||||
} from "../../../dtos/user.dto.js";
|
||||
|
||||
export const USER_SERVICE = Symbol("USER_SERVICE");
|
||||
|
||||
export type IUserService = IService<
|
||||
User,
|
||||
CreateUserInput,
|
||||
UpdateUserInput,
|
||||
UserKey
|
||||
> & {
|
||||
verifyCredentials(input: {
|
||||
id: number;
|
||||
password: string;
|
||||
}): Promise<User | null>;
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Inject,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
Patch,
|
||||
Post,
|
||||
} from "@nestjs/common";
|
||||
import type { CreateUserInput, UpdateUserInput } from "../../dtos/user.dto.js";
|
||||
import { USER_SERVICE } from "./interfaces/user-service.interface.js";
|
||||
import type { IUserService } from "./interfaces/user-service.interface.js";
|
||||
|
||||
@Controller("users")
|
||||
export class UserController {
|
||||
constructor(
|
||||
@Inject(USER_SERVICE) private readonly userService: IUserService,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
findAll() {
|
||||
return this.userService.findAll();
|
||||
}
|
||||
|
||||
@Get(":id")
|
||||
findOne(@Param("id", ParseIntPipe) id: number) {
|
||||
return this.userService.findById({ id });
|
||||
}
|
||||
|
||||
@Post()
|
||||
create(@Body() body: CreateUserInput) {
|
||||
return this.userService.create(body);
|
||||
}
|
||||
|
||||
@Patch(":id")
|
||||
update(@Param("id", ParseIntPipe) id: number, @Body() body: UpdateUserInput) {
|
||||
return this.userService.update({ id }, body);
|
||||
}
|
||||
|
||||
@Delete(":id")
|
||||
remove(@Param("id", ParseIntPipe) id: number) {
|
||||
return this.userService.delete({ id });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { USER_REPOSITORY } from "./interfaces/user-repository.interface.js";
|
||||
import { USER_SERVICE } from "./interfaces/user-service.interface.js";
|
||||
import { UserController } from "./user.controller.js";
|
||||
import { UserRepository } from "./user.repository.js";
|
||||
import { UserService } from "./user.service.js";
|
||||
|
||||
@Module({
|
||||
controllers: [UserController],
|
||||
providers: [
|
||||
{ provide: USER_REPOSITORY, useClass: UserRepository },
|
||||
{ provide: USER_SERVICE, useClass: UserService },
|
||||
],
|
||||
exports: [USER_SERVICE],
|
||||
})
|
||||
export class UserModule {}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { BaseRepository } from "../../common/base.repository.js";
|
||||
import type { CreateUserInput, UpdateUserInput } from "../../dtos/user.dto.js";
|
||||
import type { User, UserKey } from "../../entities/user.entity.js";
|
||||
import type { IUserRepository } from "./interfaces/user-repository.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class UserRepository
|
||||
extends BaseRepository<User, CreateUserInput, UpdateUserInput, UserKey>
|
||||
implements IUserRepository
|
||||
{
|
||||
// `password` is deliberately excluded from every read/write return value.
|
||||
protected readonly columns = [
|
||||
"id",
|
||||
"name",
|
||||
"email",
|
||||
"role",
|
||||
"createdAt",
|
||||
"updatedAt",
|
||||
] as const;
|
||||
|
||||
protected get model() {
|
||||
return this.db.orm.public.User;
|
||||
}
|
||||
|
||||
override findById(where: UserKey): Promise<User | null> {
|
||||
return this.model
|
||||
.select(...this.columns)
|
||||
.where(where)
|
||||
.first();
|
||||
}
|
||||
|
||||
override create(data: CreateUserInput): Promise<User> {
|
||||
return this.model.select(...this.columns).create(data);
|
||||
}
|
||||
|
||||
findWithPassword(
|
||||
where: UserKey,
|
||||
): Promise<{ id: number; password: string } | null> {
|
||||
return this.model.select("id", "password").where(where).first();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import { Inject, Injectable } from "@nestjs/common";
|
||||
import { BaseService } from "../../common/base.service.js";
|
||||
import { hashPassword, verifyPassword } from "../../common/password.util.js";
|
||||
import type { CreateUserInput, UpdateUserInput } from "../../dtos/user.dto.js";
|
||||
import type { User, UserKey } from "../../entities/user.entity.js";
|
||||
import {
|
||||
USER_REPOSITORY,
|
||||
type IUserRepository,
|
||||
} from "./interfaces/user-repository.interface.js";
|
||||
import type { IUserService } from "./interfaces/user-service.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class UserService
|
||||
extends BaseService<User, CreateUserInput, UpdateUserInput, UserKey>
|
||||
implements IUserService
|
||||
{
|
||||
constructor(
|
||||
@Inject(USER_REPOSITORY) private readonly userRepository: IUserRepository,
|
||||
) {
|
||||
super(userRepository);
|
||||
}
|
||||
|
||||
override async create(data: CreateUserInput): Promise<User> {
|
||||
return super.create({
|
||||
...data,
|
||||
password: await hashPassword(data.password),
|
||||
});
|
||||
}
|
||||
|
||||
override async update(where: UserKey, data: UpdateUserInput): Promise<User> {
|
||||
const patch = data.password
|
||||
? { ...data, password: await hashPassword(data.password) }
|
||||
: data;
|
||||
return super.update(where, patch);
|
||||
}
|
||||
|
||||
async verifyCredentials({
|
||||
id,
|
||||
password,
|
||||
}: {
|
||||
id: number;
|
||||
password: string;
|
||||
}): Promise<User | null> {
|
||||
const record = await this.userRepository.findWithPassword({ id });
|
||||
if (!record || !(await verifyPassword(password, record.password))) {
|
||||
return null;
|
||||
}
|
||||
return this.userRepository.findById({ id });
|
||||
}
|
||||
|
||||
protected override notFoundMessage(where: UserKey): string {
|
||||
return `User ${where.id} not found`;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import type { IRepository } from "../../../common/repository.interface.js";
|
||||
import type {
|
||||
Warehouse,
|
||||
WarehouseKey,
|
||||
} from "../../../entities/warehouse.entity.js";
|
||||
import type {
|
||||
CreateWarehouseInput,
|
||||
UpdateWarehouseInput,
|
||||
} from "../../../dtos/warehouse.dto.js";
|
||||
|
||||
export const WAREHOUSE_REPOSITORY = Symbol("WAREHOUSE_REPOSITORY");
|
||||
|
||||
export type IWarehouseRepository = IRepository<
|
||||
Warehouse,
|
||||
CreateWarehouseInput,
|
||||
UpdateWarehouseInput,
|
||||
WarehouseKey
|
||||
>;
|
||||
@@ -0,0 +1,18 @@
|
||||
import type { IService } from "../../../common/service.interface.js";
|
||||
import type {
|
||||
Warehouse,
|
||||
WarehouseKey,
|
||||
} from "../../../entities/warehouse.entity.js";
|
||||
import type {
|
||||
CreateWarehouseInput,
|
||||
UpdateWarehouseInput,
|
||||
} from "../../../dtos/warehouse.dto.js";
|
||||
|
||||
export const WAREHOUSE_SERVICE = Symbol("WAREHOUSE_SERVICE");
|
||||
|
||||
export type IWarehouseService = IService<
|
||||
Warehouse,
|
||||
CreateWarehouseInput,
|
||||
UpdateWarehouseInput,
|
||||
WarehouseKey
|
||||
>;
|
||||
@@ -0,0 +1,60 @@
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Inject,
|
||||
Param,
|
||||
ParseIntPipe,
|
||||
Patch,
|
||||
Post,
|
||||
} from "@nestjs/common";
|
||||
import type {
|
||||
CreateWarehouseInput,
|
||||
UpdateWarehouseInput,
|
||||
} from "../../dtos/warehouse.dto.js";
|
||||
import { WAREHOUSE_SERVICE } from "./interfaces/warehouse-service.interface.js";
|
||||
import type { IWarehouseService } from "./interfaces/warehouse-service.interface.js";
|
||||
|
||||
@Controller("warehouses")
|
||||
export class WarehouseController {
|
||||
constructor(
|
||||
@Inject(WAREHOUSE_SERVICE)
|
||||
private readonly warehouseService: IWarehouseService,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
findAll() {
|
||||
return this.warehouseService.findAll();
|
||||
}
|
||||
|
||||
@Get(":inventoryId/:productId")
|
||||
findOne(
|
||||
@Param("inventoryId", ParseIntPipe) inventoryId: number,
|
||||
@Param("productId", ParseIntPipe) productId: number,
|
||||
) {
|
||||
return this.warehouseService.findById({ inventoryId, productId });
|
||||
}
|
||||
|
||||
@Post()
|
||||
create(@Body() body: CreateWarehouseInput) {
|
||||
return this.warehouseService.create(body);
|
||||
}
|
||||
|
||||
@Patch(":inventoryId/:productId")
|
||||
update(
|
||||
@Param("inventoryId", ParseIntPipe) inventoryId: number,
|
||||
@Param("productId", ParseIntPipe) productId: number,
|
||||
@Body() body: UpdateWarehouseInput,
|
||||
) {
|
||||
return this.warehouseService.update({ inventoryId, productId }, body);
|
||||
}
|
||||
|
||||
@Delete(":inventoryId/:productId")
|
||||
remove(
|
||||
@Param("inventoryId", ParseIntPipe) inventoryId: number,
|
||||
@Param("productId", ParseIntPipe) productId: number,
|
||||
) {
|
||||
return this.warehouseService.delete({ inventoryId, productId });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { WAREHOUSE_REPOSITORY } from "./interfaces/warehouse-repository.interface.js";
|
||||
import { WAREHOUSE_SERVICE } from "./interfaces/warehouse-service.interface.js";
|
||||
import { WarehouseController } from "./warehouse.controller.js";
|
||||
import { WarehouseRepository } from "./warehouse.repository.js";
|
||||
import { WarehouseService } from "./warehouse.service.js";
|
||||
|
||||
@Module({
|
||||
controllers: [WarehouseController],
|
||||
providers: [
|
||||
{ provide: WAREHOUSE_REPOSITORY, useClass: WarehouseRepository },
|
||||
{ provide: WAREHOUSE_SERVICE, useClass: WarehouseService },
|
||||
],
|
||||
exports: [WAREHOUSE_SERVICE],
|
||||
})
|
||||
export class WarehouseModule {}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { Injectable } from "@nestjs/common";
|
||||
import { BaseRepository } from "../../common/base.repository.js";
|
||||
import type {
|
||||
CreateWarehouseInput,
|
||||
UpdateWarehouseInput,
|
||||
} from "../../dtos/warehouse.dto.js";
|
||||
import type {
|
||||
Warehouse,
|
||||
WarehouseKey,
|
||||
} from "../../entities/warehouse.entity.js";
|
||||
import type { IWarehouseRepository } from "./interfaces/warehouse-repository.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class WarehouseRepository
|
||||
extends BaseRepository<
|
||||
Warehouse,
|
||||
CreateWarehouseInput,
|
||||
UpdateWarehouseInput,
|
||||
WarehouseKey
|
||||
>
|
||||
implements IWarehouseRepository
|
||||
{
|
||||
protected readonly columns = ["inventoryId", "productId", "stock"] as const;
|
||||
|
||||
protected get model() {
|
||||
return this.db.orm.public.Warehouse;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { Inject, Injectable } from "@nestjs/common";
|
||||
import { BaseService } from "../../common/base.service.js";
|
||||
import type {
|
||||
CreateWarehouseInput,
|
||||
UpdateWarehouseInput,
|
||||
} from "../../dtos/warehouse.dto.js";
|
||||
import type {
|
||||
Warehouse,
|
||||
WarehouseKey,
|
||||
} from "../../entities/warehouse.entity.js";
|
||||
import {
|
||||
WAREHOUSE_REPOSITORY,
|
||||
type IWarehouseRepository,
|
||||
} from "./interfaces/warehouse-repository.interface.js";
|
||||
import type { IWarehouseService } from "./interfaces/warehouse-service.interface.js";
|
||||
|
||||
@Injectable()
|
||||
export class WarehouseService
|
||||
extends BaseService<
|
||||
Warehouse,
|
||||
CreateWarehouseInput,
|
||||
UpdateWarehouseInput,
|
||||
WarehouseKey
|
||||
>
|
||||
implements IWarehouseService
|
||||
{
|
||||
constructor(@Inject(WAREHOUSE_REPOSITORY) repository: IWarehouseRepository) {
|
||||
super(repository);
|
||||
}
|
||||
|
||||
protected override notFoundMessage(where: WarehouseKey): string {
|
||||
return `Warehouse (${where.inventoryId}, ${where.productId}) not found`;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user