.,
This commit is contained in:
parent
47802ab932
commit
23cfe70578
@ -128,6 +128,7 @@ export const QuoteEdit = () => {
|
||||
|
||||
const onSubmit: SubmitHandler<QuoteDataForm> = async (data) => {
|
||||
// Transformación del form -> typo de request
|
||||
console.log(data);
|
||||
mutate(data, {
|
||||
onError: (error) => {
|
||||
console.debug(error);
|
||||
@ -163,19 +164,17 @@ export const QuoteEdit = () => {
|
||||
|
||||
if (name === "items") {
|
||||
const { items } = value;
|
||||
let quoteSubtotal = MoneyValue.create().object;
|
||||
|
||||
let quoteSubtotal = MoneyValue.create({
|
||||
amount: 0,
|
||||
scale: 4,
|
||||
}).object;
|
||||
|
||||
// Recálculo líneas
|
||||
items &&
|
||||
items.map((item, index) => {
|
||||
const itemTotals = calculateItemTotals(item);
|
||||
|
||||
if (itemTotals === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
quoteSubtotal = quoteSubtotal.add(itemTotals.totalPrice);
|
||||
|
||||
setValue(`items.${index}.subtotal_price`, itemTotals.subtotalPrice.toObject());
|
||||
setValue(`items.${index}.total_price`, itemTotals.totalPrice.toObject());
|
||||
});
|
||||
@ -186,15 +185,11 @@ export const QuoteEdit = () => {
|
||||
|
||||
if (name.endsWith("quantity") || name.endsWith("unit_price") || name.endsWith("discount")) {
|
||||
const { items } = value;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
|
||||
const [, indexString, fieldName] = String(name).split(".");
|
||||
const index = parseInt(indexString);
|
||||
|
||||
const itemTotals = calculateItemTotals(items[index]);
|
||||
if (itemTotals === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
setValue(`items.${index}.subtotal_price`, itemTotals.subtotalPrice.toObject());
|
||||
setValue(`items.${index}.total_price`, itemTotals.totalPrice.toObject());
|
||||
|
||||
@ -206,7 +201,7 @@ export const QuoteEdit = () => {
|
||||
}, [watch, getValues, setValue]);
|
||||
|
||||
if (isSubmitting) {
|
||||
return <LoadingOverlay />;
|
||||
return <LoadingOverlay title='Guardando cotización' />;
|
||||
}
|
||||
|
||||
if (status === "error") {
|
||||
|
||||
@ -1,13 +1,32 @@
|
||||
import { MoneyValue, Percentage, Quantity } from "@shared/contexts";
|
||||
|
||||
export const calculateItemTotals = (item: any) => {
|
||||
console.log(item);
|
||||
|
||||
const { quantity: quantity_dto, unit_price: unit_price_dto, discount: discount_dto } = item;
|
||||
|
||||
/*if (quantity_dto.amount === null || unit_price_dto.amount === null) {
|
||||
return null;
|
||||
}*/
|
||||
if (quantity_dto.amount === null || unit_price_dto.amount === null) {
|
||||
return {
|
||||
quantity: Quantity.create({
|
||||
amount: quantity_dto.amount,
|
||||
scale: 0,
|
||||
}).object,
|
||||
unitPrice: MoneyValue.create({
|
||||
amount: unit_price_dto.amount,
|
||||
scale: 4,
|
||||
}).object,
|
||||
subtotalPrice: MoneyValue.create({
|
||||
amount: null,
|
||||
scale: 4,
|
||||
}).object,
|
||||
discount: Percentage.create({
|
||||
amount: discount_dto.amount,
|
||||
scale: 2,
|
||||
}).object,
|
||||
totalPrice: MoneyValue.create({
|
||||
amount: null,
|
||||
scale: 4,
|
||||
}).object,
|
||||
};
|
||||
}
|
||||
|
||||
const quantityOrError = Quantity.create(quantity_dto);
|
||||
if (quantityOrError.isFailure) {
|
||||
|
||||
@ -16,6 +16,8 @@ export class ArticleIdentifier extends NullableValueObject<number> {
|
||||
) {
|
||||
const ruleNull = RuleValidator.RULE_ALLOW_NULL_OR_UNDEFINED.default(null);
|
||||
|
||||
const ruleEmpty = RuleValidator.RULE_ALLOW_EMPTY.default(null);
|
||||
|
||||
const ruleNumber = RuleValidator.RULE_IS_TYPE_NUMBER.label(
|
||||
options.label ? options.label : "ArticleIdentifier"
|
||||
);
|
||||
@ -24,11 +26,15 @@ export class ArticleIdentifier extends NullableValueObject<number> {
|
||||
options.label ? options.label : "ArticleIdentifier"
|
||||
);
|
||||
|
||||
const rules = Joi.alternatives(ruleNull, ruleNumber, ruleString);
|
||||
const rules = Joi.alternatives(ruleNull, ruleEmpty, ruleNumber, ruleString);
|
||||
|
||||
return RuleValidator.validate<NullOr<number>>(rules, value);
|
||||
}
|
||||
|
||||
private static sanitize(value: NullOr<number | string>): NullOr<number> {
|
||||
return value ? Number(value) : null;
|
||||
}
|
||||
|
||||
public static create(value: NullOr<number | string>, options: IArticleIdentifierOptions = {}) {
|
||||
const _options = {
|
||||
label: "ArticleIdentifier",
|
||||
@ -49,7 +55,7 @@ export class ArticleIdentifier extends NullableValueObject<number> {
|
||||
_value = validationResult.object;
|
||||
}
|
||||
|
||||
return Result.ok<ArticleIdentifier>(new ArticleIdentifier(_value));
|
||||
return Result.ok<ArticleIdentifier>(new ArticleIdentifier(ArticleIdentifier.sanitize(_value)));
|
||||
}
|
||||
|
||||
public toNumber(): number {
|
||||
|
||||
@ -117,7 +117,6 @@ export class UpdateQuoteUseCase
|
||||
|
||||
try {
|
||||
await transaction.complete(async (t) => {
|
||||
console.log(t);
|
||||
quoteRepo = quoteRepository({ transaction: t });
|
||||
await quoteRepo.update(quote);
|
||||
});
|
||||
|
||||
@ -53,7 +53,9 @@ export class QuoteItem extends Entity<IQuoteItemProps> implements IQuoteItem {
|
||||
}
|
||||
|
||||
get subtotalPrice(): MoneyValue {
|
||||
return this.unitPrice.multiply(this.quantity.toNumber());
|
||||
return this.quantity.isNull() || this.unitPrice.isNull()
|
||||
? MoneyValue.create({ amount: null, scale: 4 }).object
|
||||
: this.unitPrice.multiply(this.quantity.toNumber());
|
||||
}
|
||||
|
||||
get discount(): Percentage {
|
||||
@ -61,6 +63,8 @@ export class QuoteItem extends Entity<IQuoteItemProps> implements IQuoteItem {
|
||||
}
|
||||
|
||||
get totalPrice(): MoneyValue {
|
||||
return this.subtotalPrice.subtract(this.subtotalPrice.percentage(this.discount.toNumber()));
|
||||
return this.subtotalPrice.isNull()
|
||||
? MoneyValue.create({ amount: null, scale: 4 }).object
|
||||
: this.subtotalPrice.subtract(this.subtotalPrice.percentage(this.discount.toNumber()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ const quoteItemPresenter = (
|
||||
): IGetQuote_QuoteItem_Response_DTO[] =>
|
||||
items.totalCount > 0
|
||||
? items.items.map((item: QuoteItem) => ({
|
||||
article_id: item.articleId ?? "",
|
||||
article_id: item.articleId.toString(),
|
||||
description: item.description.toString(),
|
||||
quantity: item.quantity.toObject(),
|
||||
unit_price: item.unitPrice.toObject(),
|
||||
|
||||
@ -36,7 +36,7 @@ export const UpdateQuotePresenter: IUpdateQuotePresenter = {
|
||||
const quoteItemPresenter = (items: ICollection<QuoteItem>, context: ISalesContext) =>
|
||||
items.totalCount > 0
|
||||
? items.items.map((item: QuoteItem) => ({
|
||||
article_id: item.articleId ?? "",
|
||||
article_id: item.articleId.toString(),
|
||||
description: item.description.toString(),
|
||||
quantity: item.quantity.toObject(),
|
||||
unit_price: item.unitPrice.toObject(),
|
||||
|
||||
@ -3,7 +3,7 @@ import DineroFactory, { Currency, Dinero } from "dinero.js";
|
||||
|
||||
import Joi from "joi";
|
||||
import { isNull } from "lodash";
|
||||
import { NullOr, UndefinedOr } from "../../../../utilities";
|
||||
import { NullOr } from "../../../../utilities";
|
||||
import { DomainError, handleDomainError } from "../errors";
|
||||
import { RuleValidator } from "../RuleValidator";
|
||||
import { CurrencyData } from "./CurrencyData";
|
||||
@ -11,12 +11,10 @@ import { Result } from "./Result";
|
||||
import { IValueObjectOptions, ValueObject } from "./ValueObject";
|
||||
|
||||
export interface IMoneyValueOptions extends IValueObjectOptions {
|
||||
defaultValue?: number;
|
||||
locale: string;
|
||||
}
|
||||
|
||||
export const defaultMoneyValueOptions: IMoneyValueOptions = {
|
||||
defaultValue: 0,
|
||||
locale: "es-ES",
|
||||
};
|
||||
|
||||
@ -50,7 +48,7 @@ const defaultMoneyValueProps = {
|
||||
};
|
||||
|
||||
interface IMoneyValue {
|
||||
toPrimitive(): UndefinedOr<number>;
|
||||
toPrimitive(): NullOr<number>;
|
||||
toPrimitives(): MoneyValueObject;
|
||||
isEmpty(): boolean;
|
||||
toString(): string;
|
||||
@ -92,9 +90,6 @@ export class MoneyValue extends ValueObject<Dinero> implements IMoneyValue {
|
||||
public static readonly DEFAULT_SCALE = defaultMoneyValueProps.scale;
|
||||
public static readonly DEFAULT_CURRENCY_CODE = defaultMoneyValueProps.currencyCode;
|
||||
|
||||
private static readonly MIN_VALUE = Number.MIN_VALUE;
|
||||
private static readonly MAX_VALUE = Number.MAX_VALUE;
|
||||
|
||||
private readonly _isNull: boolean;
|
||||
private readonly _options: IMoneyValueOptions;
|
||||
|
||||
@ -103,12 +98,7 @@ export class MoneyValue extends ValueObject<Dinero> implements IMoneyValue {
|
||||
.optional() // <- undefined
|
||||
.valid(null); // <- null
|
||||
|
||||
const ruleNumber = Joi.number()
|
||||
.optional()
|
||||
.default(0)
|
||||
.min(-1000)
|
||||
.max(this.MAX_VALUE)
|
||||
.label(options.label ? options.label : "amount");
|
||||
const ruleNumber = Joi.number().label(options.label ? options.label : "amount");
|
||||
|
||||
const rules = Joi.alternatives(ruleNull, ruleNumber);
|
||||
|
||||
@ -154,7 +144,7 @@ export class MoneyValue extends ValueObject<Dinero> implements IMoneyValue {
|
||||
const _currency = CurrencyData.createFromCode(currencyCode).object.code;
|
||||
|
||||
const prop = DineroFactory({
|
||||
amount: !isNull(_amount) ? Number(_amount) : options.defaultValue,
|
||||
amount: Number(_amount),
|
||||
currency: _currency as Currency,
|
||||
precision: scale,
|
||||
}).setLocale(options.locale);
|
||||
@ -287,8 +277,8 @@ export class MoneyValue extends ValueObject<Dinero> implements IMoneyValue {
|
||||
return this._isNull ? {} : this.props?.toJSON();
|
||||
}
|
||||
|
||||
public toPrimitive(): UndefinedOr<number> {
|
||||
return this._isNull ? undefined : Number(this.props?.getAmount());
|
||||
public toPrimitive(): NullOr<number> {
|
||||
return this._isNull ? null : Number(this.props?.getAmount());
|
||||
}
|
||||
|
||||
public toPrimitives(): MoneyValueObject {
|
||||
@ -308,7 +298,16 @@ export class MoneyValue extends ValueObject<Dinero> implements IMoneyValue {
|
||||
}
|
||||
|
||||
public convertScale(newScale: number, roundingMode: RoundingMode = "HALF_UP"): MoneyValue {
|
||||
return MoneyValue.createFromDinero(this.props.convertPrecision(newScale, roundingMode)).object;
|
||||
if (this._isNull) {
|
||||
return MoneyValue.create({
|
||||
amount: null,
|
||||
scale: newScale,
|
||||
currencyCode: this.getCurrency().code,
|
||||
}).object;
|
||||
} else {
|
||||
return MoneyValue.createFromDinero(this.props.convertPrecision(newScale, roundingMode))
|
||||
.object;
|
||||
}
|
||||
}
|
||||
|
||||
public getCurrency(): CurrencyData {
|
||||
|
||||
@ -22,7 +22,7 @@ interface IPercentage {
|
||||
}
|
||||
|
||||
export interface PercentageObject {
|
||||
amount: number;
|
||||
amount: number | null;
|
||||
scale: number;
|
||||
}
|
||||
|
||||
@ -259,7 +259,7 @@ export class Percentage extends NullableValueObject<IPercentage> {
|
||||
|
||||
public toObject(): PercentageObject {
|
||||
return {
|
||||
amount: this.isNull() ? 0 : Number(this.amount),
|
||||
amount: this.amount,
|
||||
scale: this.scale,
|
||||
};
|
||||
}
|
||||
|
||||
@ -195,7 +195,7 @@ export class Quantity extends NullableValueObject<IQuantity> {
|
||||
}
|
||||
|
||||
get scale(): number {
|
||||
return this.isNull() ? 0 : Number(this.props?.scale);
|
||||
return Number(this.props?.scale);
|
||||
}
|
||||
|
||||
public getAmount(): NullOr<number> {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user