refactor(bom): enforce canonical lot_mappings persistence

This commit is contained in:
Mikhail Chusavitin
2026-02-27 09:47:46 +03:00
parent e9230c0e58
commit 586114c79c
2 changed files with 86 additions and 18 deletions

View File

@@ -230,11 +230,15 @@
</tfoot>
</table>
</div>
<div class="mt-4 flex items-center gap-4">
<div class="mt-4 flex flex-wrap items-center gap-4">
<label class="text-sm font-medium text-gray-700">Своя цена:</label>
<input type="number" id="pricing-custom-price" step="0.01" min="0" placeholder="0.00"
class="w-40 px-3 py-2 border rounded focus:ring-2 focus:ring-blue-500"
oninput="onPricingCustomPriceInput()">
<label class="text-sm font-medium text-gray-700">Uplift:</label>
<input type="number" id="pricing-uplift" step="0.0001" min="0" placeholder="1.0000"
class="w-32 px-3 py-2 border rounded focus:ring-2 focus:ring-blue-500"
oninput="onPricingUpliftInput()">
<button onclick="setPricingCustomPriceFromVendor()" class="px-3 py-2 bg-gray-100 text-gray-700 rounded hover:bg-gray-200 border border-gray-300 text-sm">
Проставить цены BOM
</button>
@@ -2889,20 +2893,6 @@ function removeBOMAllocation(rowIdx, allocIdx) {
debouncedAutosaveBOM();
}
function toggleBOMBundle(rowIdx) {
const row = _findBOMRowBySource(rowIdx);
if (!row) return;
_ensureRowAllocations(row);
row.bundle_enabled = !row.bundle_enabled;
if (row.bundle_enabled && row.lot_allocations.length === 0) {
row.lot_allocations.push({ lot_name: row.resolved_lot || row.manual_lot || '', quantity: 1 });
}
if (!row.bundle_enabled) {
row.lot_allocations = [];
}
renderBOMTable();
}
function setBOMAllocationDraft(rowIdx, allocIdx, field, value, el) {
const row = _findBOMRowBySource(rowIdx);
if (!row) return;
@@ -3659,6 +3649,7 @@ function setPricingCustomPriceFromVendor() {
document.getElementById('pricing-total-vendor').textContent = hasAny ? formatCurrency(total) : '—';
document.getElementById('pricing-custom-price').value = hasAny ? total.toFixed(2) : '';
syncPricingLinkedInputs('price');
// Update discount info only
const rows2 = document.querySelectorAll('#pricing-table-body tr.pricing-row');
@@ -3674,12 +3665,48 @@ function setPricingCustomPriceFromVendor() {
}
}
function onPricingCustomPriceInput() {
const customPrice = parseFloat(document.getElementById('pricing-custom-price').value) || 0;
function getPricingEstimateTotal() {
const rows = document.querySelectorAll('#pricing-table-body tr.pricing-row');
let estimateTotal = 0;
rows.forEach(tr => { estimateTotal += parseFloat(tr.dataset.est) || 0; });
return estimateTotal;
}
function syncPricingLinkedInputs(source) {
const customPriceInput = document.getElementById('pricing-custom-price');
const upliftInput = document.getElementById('pricing-uplift');
if (!customPriceInput || !upliftInput) return;
const estimateTotal = getPricingEstimateTotal();
if (estimateTotal <= 0) {
upliftInput.value = '';
return;
}
if (source === 'price') {
const customPrice = parseFloat(customPriceInput.value) || 0;
upliftInput.value = customPrice > 0 ? (customPrice / estimateTotal).toFixed(4) : '';
return;
}
if (source === 'uplift') {
const uplift = parseFloat(upliftInput.value) || 0;
customPriceInput.value = uplift > 0 ? (estimateTotal * uplift).toFixed(2) : '';
}
}
function onPricingUpliftInput() {
syncPricingLinkedInputs('uplift');
const customPrice = parseFloat(document.getElementById('pricing-custom-price').value) || 0;
applyPricingCustomPrice(customPrice);
}
function onPricingCustomPriceInput() {
syncPricingLinkedInputs('price');
const customPrice = parseFloat(document.getElementById('pricing-custom-price').value) || 0;
applyPricingCustomPrice(customPrice);
}
function applyPricingCustomPrice(customPrice) {
const estimateTotal = getPricingEstimateTotal();
const rows = document.querySelectorAll('#pricing-table-body tr.pricing-row');
const vendorCells = document.querySelectorAll('#pricing-table-body .pricing-vendor-price');
const totalVendorEl = document.getElementById('pricing-total-vendor');