The 2026-10-08 ask: open an account without four screens — cliente, propiedad, servicios and the saldo inicial, taken as the first payment. POST /customers/onboard writes it all in one Prisma transaction; a bad service or a taken folder number leaves nothing behind (rolled back on dev). A cash opening balance goes through the EFE receipt book inside that same transaction, so it gets its folio and its C<folio> credit; a check posts a CHECK DEPOSIT against the number given. /clientes/alta pre-fills the next free folder number and links the receipt for printing. The old customer-only form stays as "Solo cliente". Built without the screen sketch from the meeting (it never arrived); the fields are the legacy ones. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
57 lines
1.7 KiB
TypeScript
57 lines
1.7 KiB
TypeScript
import {
|
|
ArrayMaxSize,
|
|
IsArray,
|
|
IsEnum,
|
|
IsIn,
|
|
IsNumber,
|
|
IsOptional,
|
|
IsString,
|
|
MinLength,
|
|
ValidateNested,
|
|
} from "class-validator";
|
|
import { Type } from "class-transformer";
|
|
import { Currency } from "@jorgecuadros/database";
|
|
import { CreateCustomerDto } from "./create-customer.dto";
|
|
import { ServiceDto } from "../properties/property.dto";
|
|
|
|
/** The property, minus the customer it is being created for. */
|
|
export class OnboardPropertyDto {
|
|
@IsOptional() @IsString() addressLine1?: string;
|
|
@IsOptional() @IsString() addressLine2?: string;
|
|
@IsOptional() @IsString() phone1?: string;
|
|
}
|
|
|
|
/**
|
|
* The opening balance the office takes when an account is opened, captured as
|
|
* the customer's first payment. Cash issues an EFE receipt; a check posts a
|
|
* CHECK DEPOSIT against that check number.
|
|
*/
|
|
export class OpeningPaymentDto {
|
|
@IsIn(["CASH", "CHECK"]) method!: "CASH" | "CHECK";
|
|
@IsNumber() amount!: number;
|
|
@IsEnum(Currency) currency!: Currency;
|
|
@IsString() @MinLength(1) receivedAt!: string;
|
|
@IsOptional() @IsString() checkNumber?: string;
|
|
/** Cash only: dollars credited to a pesos ledger. */
|
|
@IsOptional() @IsNumber() exchangeRate?: number;
|
|
@IsOptional() @IsString() concept?: string;
|
|
}
|
|
|
|
/** One screen: cliente + propiedad + servicios + saldo inicial. */
|
|
export class OnboardCustomerDto {
|
|
@ValidateNested() @Type(() => CreateCustomerDto) customer!: CreateCustomerDto;
|
|
|
|
@IsOptional() @ValidateNested() @Type(() => OnboardPropertyDto)
|
|
property?: OnboardPropertyDto;
|
|
|
|
@IsOptional()
|
|
@IsArray()
|
|
@ArrayMaxSize(12)
|
|
@ValidateNested({ each: true })
|
|
@Type(() => ServiceDto)
|
|
services?: ServiceDto[];
|
|
|
|
@IsOptional() @ValidateNested() @Type(() => OpeningPaymentDto)
|
|
openingPayment?: OpeningPaymentDto;
|
|
}
|