fix: minibar deposit — использовать актуальную цену из справочника, а не историческую
Ранее в форме удержания депозита показывалась цена на момент уборки (price_per_unit). Теперь используется текущая цена позиции (mi.price) — чтобы изменения цен сразу отражались в счёте. Если цена менялась — показываем индикатор ↑ с tooltip. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -72,7 +72,7 @@ function DepositWidget({ slug, bookingId }: { slug: string; bookingId: string })
|
||||
const [yookassaMsg, setYookassaMsg] = useState<string | null>(null)
|
||||
const [releaseError, setReleaseError] = useState<string | null>(null)
|
||||
const [presets, setPresets] = useState<DepositPreset[]>([])
|
||||
const [minibarItems, setMinibarItems] = useState<Array<{ itemName: string; quantity: number; pricePerUnit: number; lineTotal: number }>>([])
|
||||
const [minibarItems, setMinibarItems] = useState<Array<{ itemName: string; quantity: number; recordedPrice: number; currentPrice: number; lineTotal: number }>>([])
|
||||
const [minibarTotal, setMinibarTotal] = useState(0)
|
||||
|
||||
useEffect(() => {
|
||||
@@ -330,20 +330,32 @@ function DepositWidget({ slug, bookingId }: { slug: string; bookingId: string })
|
||||
</button>
|
||||
</div>
|
||||
<div className="divide-y divide-amber-100 dark:divide-amber-900/40">
|
||||
{minibarItems.map((it, i) => (
|
||||
<div key={i} className="flex items-center justify-between px-3 py-1.5">
|
||||
<span className="text-xs text-amber-800 dark:text-amber-300 flex-1">
|
||||
{it.itemName} × {it.quantity} <span className="text-amber-500 dark:text-amber-500">({formatCurrency(it.pricePerUnit)} / шт.)</span>
|
||||
</span>
|
||||
<span className="text-xs font-medium text-amber-800 dark:text-amber-300 mr-2">{formatCurrency(it.lineTotal)}</span>
|
||||
<button
|
||||
onClick={() => addReleaseItem(`${it.itemName} × ${it.quantity}`, it.lineTotal)}
|
||||
className="text-xs text-amber-600 dark:text-amber-400 hover:underline font-medium shrink-0"
|
||||
>
|
||||
+ Добавить
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
{minibarItems.map((it, i) => {
|
||||
const priceChanged = Math.abs(it.currentPrice - it.recordedPrice) > 0.001
|
||||
return (
|
||||
<div key={i} className="flex items-center justify-between px-3 py-1.5 gap-2">
|
||||
<span className="text-xs text-amber-800 dark:text-amber-300 flex-1 min-w-0">
|
||||
{it.itemName} × {it.quantity}
|
||||
{' '}
|
||||
<span className={priceChanged ? 'text-orange-500 dark:text-orange-400' : 'text-amber-500'}>
|
||||
({formatCurrency(it.currentPrice)} / шт.)
|
||||
</span>
|
||||
{priceChanged && (
|
||||
<span className="ml-1 text-orange-500 dark:text-orange-400" title={`Цена изменена с ${formatCurrency(it.recordedPrice)}`}>
|
||||
↑
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
<span className="text-xs font-medium text-amber-800 dark:text-amber-300 shrink-0">{formatCurrency(it.lineTotal)}</span>
|
||||
<button
|
||||
onClick={() => addReleaseItem(`${it.itemName} × ${it.quantity}`, it.lineTotal)}
|
||||
className="text-xs text-amber-600 dark:text-amber-400 hover:underline font-medium shrink-0"
|
||||
>
|
||||
+ Добавить
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -806,7 +806,7 @@ export const api = {
|
||||
req<void>('DELETE', `/api/hotels/${slug}/bookings/${bookingId}/deposit`),
|
||||
|
||||
getMinibarForBooking: (slug: string, bookingId: string) =>
|
||||
req<{ items: Array<{ itemName: string; quantity: number; pricePerUnit: number; lineTotal: number }>; total: number }>(
|
||||
req<{ items: Array<{ itemName: string; quantity: number; recordedPrice: number; currentPrice: number; lineTotal: number }>; total: number }>(
|
||||
'GET', `/api/hotels/${slug}/bookings/${bookingId}/deposit/minibar`,
|
||||
),
|
||||
|
||||
|
||||
Reference in New Issue
Block a user