feat(wine): added "volume" to the wine model and improved standard drinks logic

This commit is contained in:
nostrdev-com 2025-04-04 16:41:45 +03:00
parent 4fb326630c
commit b02d4889ff
6 changed files with 64 additions and 16 deletions

@ -4,7 +4,9 @@ import {
Viticulture, Viticulture,
BottleClosure, BottleClosure,
VintageOptions, VintageOptions,
WineRegion StandardDrinks,
WineRegion,
WineVolume
} from '../types' } from '../types'
import { Alpha2Code } from 'i18n-iso-countries' import { Alpha2Code } from 'i18n-iso-countries'
import { CurrencyCode } from 'currency-codes-ts/dist/types' import { CurrencyCode } from 'currency-codes-ts/dist/types'
@ -23,8 +25,9 @@ export class Wine {
public producerId: ObjectId, // product producer public producerId: ObjectId, // product producer
public varietal: string, // if more than one, list as 'blend' public varietal: string, // if more than one, list as 'blend'
public vintage: number | VintageOptions, // year, nv (non-vintage) or mv (multi-vintage) public vintage: number | VintageOptions, // year, nv (non-vintage) or mv (multi-vintage)
public volume: WineVolume, // bottle volume
public alcohol: number, // alcohol percentage public alcohol: number, // alcohol percentage
public standardDrinks100ml: StandardDrinks100ml, // an amount of standard drinks per 100ml in AU, UK and US public standardDrinks: StandardDrinks, // an amount of standard drinks per 100ml and bottle in AU, UK and US
public viticulture: Viticulture, // viticulture public viticulture: Viticulture, // viticulture
public sulfites: number, // parts per million public sulfites: number, // parts per million
public filtered: boolean, // is wine filtered (fined (egg or fish)) public filtered: boolean, // is wine filtered (fined (egg or fish))

@ -5,7 +5,8 @@ import {
wineValidation, wineValidation,
handleReqError, handleReqError,
handleReqSuccess, handleReqSuccess,
alcoholToStandardDrinks alcoholToStandardDrinks,
volumeToMl
} from '../utils' } from '../utils'
import Joi from 'joi' import Joi from 'joi'
@ -76,7 +77,10 @@ winesRouter.post('/', async (req: Request, res: Response) => {
} }
} }
wine.standardDrinks100ml = alcoholToStandardDrinks(wine.alcohol) wine.standardDrinks = alcoholToStandardDrinks(
wine.alcohol,
volumeToMl(wine.volume)
)
const result = await collections.wines?.insertOne(wine) const result = await collections.wines?.insertOne(wine)

@ -66,8 +66,7 @@ export enum VintageOptions {
MV = 'mv' MV = 'mv'
} }
export interface StandardDrinks100ml { export interface StandardDrinks {
AU: number '100ml': { AU: number; UK: number; US: number }
UK: number bottle: { AU: number; UK: number; US: number }
US: number
} }

@ -22,3 +22,15 @@ export interface WineRegion {
| string[] | string[]
| { [key: string]: string[] | { [key: string]: string[] } } | { [key: string]: string[] | { [key: string]: string[] } }
} }
export enum WineVolume {
'0.05L' = '0.05L',
'0.187L' = '0.187L',
'0.375L' = '0.375L',
'0.5L' = '0.5L',
'0.75L' = '0.75L',
'1.5L' = '1.5L',
'3L' = '3L',
'6L' = '6L',
'12L' = '12L'
}

@ -1,10 +1,36 @@
import { StandardDrinks100ml } from '../types' import { StandardDrinks, WineVolume } from '../types'
import { roundToOneDecimal } from './' import { roundToOneDecimal } from './'
export const alcoholToStandardDrinks = ( export const alcoholToStandardDrinks = (
alcohol: number alcohol: number,
): StandardDrinks100ml => ({ bottle: number
UK: roundToOneDecimal(10 * alcohol), ): StandardDrinks => {
AU: roundToOneDecimal(7.91 * alcohol), const UK100ml = roundToOneDecimal(10 * alcohol)
US: roundToOneDecimal(5.64 * alcohol) const AU100ml = roundToOneDecimal(7.91 * alcohol)
}) const US100ml = roundToOneDecimal(5.64 * alcohol)
const bottleMultiplier = bottle / 100
return {
'100ml': {
UK: UK100ml,
AU: AU100ml,
US: US100ml
},
bottle: {
UK: UK100ml * bottleMultiplier,
AU: AU100ml * bottleMultiplier,
US: US100ml * bottleMultiplier
}
}
}
export const volumeToMl = (volume: WineVolume): number => {
if (volume.endsWith('L')) {
const volumeMl = volume.replace('L', '')
return Number(volumeMl) * 1000
}
throw new Error('Not supported volume type')
}

@ -4,7 +4,8 @@ import {
VintageOptions, VintageOptions,
BottleClosure, BottleClosure,
Viticulture, Viticulture,
WineRegion WineRegion,
WineVolume
} from '../../types' } from '../../types'
import { wineRegionsMap, isObject } from '../' import { wineRegionsMap, isObject } from '../'
@ -261,6 +262,9 @@ export const wineValidation = (data: unknown): Joi.ValidationResult =>
vintage: Joi.alternatives() vintage: Joi.alternatives()
.try(Joi.string().valid(...Object.values(VintageOptions)), Joi.number()) .try(Joi.string().valid(...Object.values(VintageOptions)), Joi.number())
.required(), .required(),
volume: Joi.string()
.valid(...Object.values(WineVolume))
.required(),
alcohol: Joi.number().min(0).max(0.99).required(), alcohol: Joi.number().min(0).max(0.99).required(),
viticulture: Joi.string() viticulture: Joi.string()
.valid(...Object.values(Viticulture)) .valid(...Object.values(Viticulture))