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:
@@ -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:
|
||||
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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 })
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
@@ -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
|
||||
|
||||
14
src/data/data-pools/shared.ts
Normal file
14
src/data/data-pools/shared.ts
Normal 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]
|
||||
}
|
||||
4
src/data/webhooks/order.d.ts
vendored
4
src/data/webhooks/order.d.ts
vendored
@@ -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
Reference in New Issue
Block a user