Los precios ahora son coherentes

El precio segun divisas corresponde con el total, la divisa del SET es
la del origen siempre
This commit is contained in:
2026-01-02 11:42:37 +01:00
parent b1068502f2
commit fdd1de37d7
8 changed files with 242 additions and 58 deletions

View File

@@ -32,6 +32,7 @@ Propuestas:
- Docker (linux) o Docker desktop (widows - WSL)
- Ubuntu 24 o similar
- Terminal bash, zsh, sh o compatible
## Introduccion
@@ -40,6 +41,8 @@ El objetivo es tener un grupo compose con
- Una BDD para almacenar ejemplos
- Un servicio que envie peticiones periodicamente
### Docker
Este grupo tiene definida una red externa en el `docker-compose.yaml` que
tiene que coincidir con la red de los demás compose ejecutados, por ejemplo:

View File

@@ -8,14 +8,53 @@ import { ADDRESS } from "#data/data-pools/ADDRESS.js";
import { CUSTOMER } from "#data/data-pools/CUSTOMER.js";
import { FieldPool, PoolOf } from "#data/data-pools/pool.type.js";
import { Shopify } from "../webhooks/order";
import { PRICE_SET, randomPriceSet } from "./PRICE_SET";
import { CURRENCIES, pickCurrencies } from "./shared";
function genId(digits: number) {
return Math.floor(Math.random() * (10 ^ digits))
}
function generatePrice(enteros: number, decimales: number) {
return (Math.floor(
Math.random() * (10 ** (enteros + decimales + 1)))
/
(10 ** (decimales))
).toString()
}
export function generateOrder(pool: PoolOf<Shopify.Order>) {
const id = genId(8)
const price = generatePrice(2, 2)
const shopCurrency = pickCurrencies(CURRENCIES)
const ORDER = <Shopify.Order>{
...FieldPool.pickRandomOf(pool), // default para el resto de campos
id: id,
currency: shopCurrency,
current_subtotal_price: price,
current_subtotal_price_set: randomPriceSet({} as PoolOf<Shopify.PriceSet>, {
baseCurrency: shopCurrency,
basePrice: price
}),
}
return ORDER
}
/**
* TODO:
* - Hacer que el id sea coherente
* - Hacer que el precio sera coherente
*/
export const ORDER = new FieldPool<Shopify.Order>({
id: [1, 2, 3],
id: () => genId(8),
customer: CUSTOMER.randomValue,
shipping_address: ADDRESS.randomValue,
})
currency: () => pickCurrencies(CURRENCIES),
current_subtotal_price: () => generatePrice(2, 2),
current_subtotal_price_set: PRICE_SET.randomValue,
}, generateOrder)
export const INVALID_POOL = {

View File

@@ -1,40 +1,47 @@
import { Shopify } from "#data/webhooks/order.js";
import { FieldPool } from "./pool.type";
import { FieldPool, PoolOf } from "./pool.type";
import { CURRENCIES, generatePrice, pickCurrencies } from "./shared";
/**
* shop_money y presentment_money tienen una correlacion que no entiendo. Necesitaria una
* funcion aleatoria nueva
*/
export function randomPriceSet(pricePool: PoolOf<Shopify.PriceSet>, opts?: {
baseCurrency?: string,
basePrice?: string,
}) {
const basePrice = opts?.basePrice ?? generatePrice(3, 2)
const currencies = {
shop: opts?.baseCurrency ?? pickCurrencies(CURRENCIES),
presentment: pickCurrencies(CURRENCIES)
}
let presentmentPrice = basePrice
if (currencies.shop != currencies.presentment) {
presentmentPrice = generatePrice(3, 2)
}
return <Shopify.PriceSet>{
shop_money: {
amount: basePrice,
currency_code: currencies.shop
},
presentment_money: {
amount: presentmentPrice,
currency_code: currencies.presentment
}
}
}
export const PRICE_SET = new FieldPool<Shopify.PriceSet>({
shop_money: [
{
amount: "100.00",
currency_code: "USD"
},
{
amount: "45.50",
currency_code: "EUR"
},
{
amount: "12500",
currency_code: "JPY"
}
],
presentment_money: [
{
amount: "100.00",
currency_code: "USD"
},
{
amount: "39.95",
currency_code: "GBP"
},
{
amount: "12500",
currency_code: "JPY"
}
]
})
shop_money: () => ({
amount: generatePrice(3, 2),
currency_code: pickCurrencies(CURRENCIES)
}),
presentment_money: () => ({
amount: generatePrice(3, 2),
currency_code: pickCurrencies(CURRENCIES)
}),
}, randomPriceSet)

View File

@@ -1,4 +1,4 @@
import { describe, test } from "vitest";
import { describe, expect, test } from "vitest";
import { ORDER } from "./ORDER";
import { CUSTOMER } from "./CUSTOMER";
import { ADDRESS } from "./ADDRESS";
@@ -10,19 +10,20 @@ describe("Test pool", () => {
const costumers = [
CUSTOMER.randomValue()
]
console.log("Costumers", costumers)
expect(costumers[0]).toBeDefined()
})
test("generacion de address", () => {
const costumers = [
const address = [
ADDRESS.randomValue()
]
console.log("ADDRESS", costumers)
expect(address[0]).toBeDefined()
})
test("generacion de 3 order distintos", () => {
const orders = [
ORDER.randomValue(),
]
console.log(orders)
console.dir(orders, { depth: null })
})
})

View File

@@ -7,9 +7,12 @@ import { NullablePartial } from "#shared/NullablePartail.js";
* - Una funcion que devuelve un valor geneerado del mismo tipo que el campo original
*/
export type PoolOf<T> = {
[K in keyof T]: T[K][] | (() => T[K]);
//[K in keyof T]: T[K][] | (() => T[K]);
[K in keyof T]: PoolField<T[K]>;
};
export type PoolField<T> = T[] | (() => T);
/**
*/
@@ -18,22 +21,26 @@ function getRandomOf<T>(pool: PoolOf<T>) {
const options = pool
if (options == undefined) throw new Error("El campo no existe en la pool")
for (const optKey in options) {
const field: T[keyof T][] | (() => T[keyof T]) = options[optKey as keyof typeof options]
if (field == undefined) continue;
if (typeof field === "function") {
mock[optKey as keyof typeof mock] = field()
} else {
const examplesLen = field.length
if (examplesLen == undefined) continue;
const seleccionado = field[Math.floor(Math.random() * examplesLen)]
mock[optKey as keyof typeof mock] = seleccionado as any // no se como resolver el tipo aqui, se confia que en el ejemplo esté bien
}
const field: PoolField<T[keyof T]> = options[optKey as keyof typeof options]
const fieldValue = getRandomOfField(field)
mock[optKey as keyof typeof mock] = fieldValue // no se como resolver el tipo aqui, se confia que en el ejemplo esté bien
}
return mock
}
function getRandomOfField<T>(field: PoolField<T> | undefined) {
if (field == undefined) return undefined;
if (typeof field === "function") {
return field()
} else {
const examplesLen = field.length
if (examplesLen == undefined) return undefined;
const seleccionado = field[Math.floor(Math.random() * examplesLen)]
return seleccionado
}
}
/**
* Un FieldPool es un wraper de PoolOf que asocia una funcion
* aleatoria personalizada al tipo de la pool
@@ -46,13 +53,17 @@ export class FieldPool<T> {
constructor(
pool: PoolOf<T>,
randFunc?: <T>(pool: PoolOf<T>) => T
randFunc?: (pool: PoolOf<T>) => T
) {
this.pool = pool
if (randFunc != undefined) {
this.randomFunc = randFunc
}
}
public static pickRandomOfField = getRandomOfField
public static pickRandomOf = getRandomOf
private randomFunc(pool: PoolOf<T>) {
const mock: NullablePartial<T> = {}
const options = pool

View File

@@ -0,0 +1,14 @@
export function generatePrice(enteros: number, decimales: number) {
return (Math.floor(Math.random() * (10 ^ enteros)) / (10 ^ decimales)).toString()
}
export const CURRENCIES = ["USD", "EUR", "JPY"]
export function pickCurrencies(currencies: string[]) {
if (currencies.length == 1) return currencies[0]
const max = currencies.length
const min = 0
const select = Math.floor(Math.random() * (max - min)) + min
return currencies[select]
}

View File

@@ -147,6 +147,9 @@ export declare namespace Shopify {
user_agent: string,
}>
/**
* https://shopify.dev/docs/api/admin-graphql/2026-01/objects/MoneyBag
*/
export type PriceSet = NullablePartial<{
shop_money: {
amount: string,
@@ -158,6 +161,7 @@ export declare namespace Shopify {
}
}>
export type MoneyBag = PriceSet
// Webhook orders/create
export type OrderCreate = Order

File diff suppressed because one or more lines are too long