import Joi from "joi"; import { NullOr } from "../../../../utilities"; import { RuleValidator } from "../RuleValidator"; import { INullableValueObjectOptions, NullableValueObject, } from "./NullableValueObject"; import { Result } from "./Result"; export interface IQuantityOptions extends INullableValueObjectOptions {} export class Quantity extends NullableValueObject { protected static validate( value: NullOr, options: IQuantityOptions = {}, ) { const ruleNull = RuleValidator.RULE_ALLOW_NULL_OR_UNDEFINED.default(null); const ruleNumber = RuleValidator.RULE_IS_TYPE_NUMBER.label( options.label ? options.label : "quantity", ); const ruleString = RuleValidator.RULE_IS_TYPE_STRING.regex( /^[-]?\d+$/, ).label(options.label ? options.label : "quantity"); const rules = Joi.alternatives(ruleNull, ruleNumber, ruleString); return RuleValidator.validate>(rules, value); } public static create( value: NullOr, options: IQuantityOptions = {}, ) { const _options = { label: "quantity", ...options, }; const validationResult = Quantity.validate(value, _options); if (validationResult.isFailure) { return Result.fail(validationResult.error); } let _value: NullOr = null; if (typeof validationResult.object === "string") { _value = parseInt(validationResult.object, 10); } else { _value = validationResult.object; } return Result.ok(new Quantity(_value)); } public toNumber(): number { return this.isNull() ? 0 : Number(this.value); } public toString(): string { return this.isNull() ? "" : String(this.value); } public toPrimitive(): number { return this.toNumber(); } public increment(amount: number = 1) { const validationResult = Quantity.validate(amount); if (validationResult.isFailure) { return Result.fail(validationResult.error); } if (this.value === null) { return Quantity.create(amount); } return Quantity.create(this.value + amount); } public decrement(amount: number = 1) { const validationResult = Quantity.validate(amount); if (validationResult.isFailure) { return Result.fail(validationResult.error); } if (this.value === null) { return Quantity.create(amount); } return Quantity.create(this.value - amount); } }