Add products and sales management modules with database schema and validation

- Introduced `ProductsModule` to manage product data, including read and write controllers.
- Created database migrations for the `products`, `sales_requests`, `sales_orders`, `sales_invoices`, and related tables, including constraints and unique indexes.
- Implemented validation for product fields such as code, name, unit, and brand with corresponding utility functions.
- Developed service and repository layers for handling product and sales data operations.
- Added unit tests for the products and sales services, repositories, and controllers to ensure functionality and correctness.
- Updated application module to include the new `ProductsModule` and related sales modules for better organization.
This commit is contained in:
shancheas
2026-08-25 09:54:16 +07:00
parent ddbe8a9ef8
commit 34d4f2c120
82 changed files with 12609 additions and 2 deletions
@@ -0,0 +1,74 @@
import { DateTime } from '../../../common/value-objects/date-time/date-time';
import { Decimal } from '../../../common/value-objects/decimal/decimal';
import { Status } from '../../../common/value-objects/status/status';
export type PackingSlipLine = {
readonly id: string;
readonly productId: string;
readonly quantity: Decimal;
readonly price: Decimal;
};
export type PackingSlip = {
readonly id: string;
readonly code: string;
readonly salesOrderId: string | null;
readonly salesOrderNumber: string | null;
readonly date: DateTime;
readonly customerId: string;
readonly address: string;
readonly latitude: number | null;
readonly longitude: number | null;
readonly notes: string | null;
readonly products: readonly PackingSlipLine[];
readonly status: Status;
readonly createdAt: DateTime;
readonly updatedAt: DateTime;
readonly createdBy: string;
readonly updatedBy: string;
};
export type PackingSlipLineInput = {
readonly productId: string;
readonly quantity: Decimal;
readonly price: Decimal;
};
export type CreatePackingSlipInput = {
readonly code?: string;
readonly salesOrderId?: string | null;
readonly salesOrderNumber?: string | null;
readonly date: DateTime;
readonly customerId: string;
readonly address: string;
readonly latitude?: number | null;
readonly longitude?: number | null;
readonly notes?: string | null;
readonly products: readonly PackingSlipLineInput[];
readonly status?: Status;
readonly userId: string;
};
export type UpdatePackingSlipInput = {
readonly code?: string;
readonly salesOrderId?: string | null;
readonly salesOrderNumber?: string | null;
readonly date?: DateTime;
readonly customerId?: string;
readonly address?: string;
readonly latitude?: number | null;
readonly longitude?: number | null;
readonly notes?: string | null;
readonly products?: readonly PackingSlipLineInput[];
readonly userId: string;
};
export type ListPackingSlipsFilters = {
readonly code?: string;
readonly status?: string;
readonly customerId?: string;
readonly salesOrderId?: string;
readonly search?: string;
readonly limit: number;
readonly offset: number;
};