Compare commits
No commits in common. "main" and "v2.8.14" have entirely different histories.
@ -1,11 +0,0 @@
|
||||
# BMC Hub v2.8.15
|
||||
|
||||
## ALSO-perioder på ordrelinjer
|
||||
|
||||
- Viser perioden fra `Actual Charge Interval` på en ny linje under produktnavnet.
|
||||
- Migration 248 retter eksisterende, ikke-eksporterede ALSO-ordrekladder.
|
||||
- Allerede eksporterede ordre ændres ikke.
|
||||
|
||||
## Opgradering
|
||||
|
||||
Kør `migrations/248_also_order_period_line_break.sql` efter deployment.
|
||||
@ -1,9 +0,0 @@
|
||||
# BMC Hub v2.8.16
|
||||
|
||||
## Flerlinjede ordrebeskrivelser
|
||||
|
||||
- Viser ordrelinjens produkt og ALSO-periode på separate linjer i både opret- og detaljevisningen.
|
||||
- Bruger et kompakt tekstområde ved redigering, så linjeskiftet bevares ved gem og eksport til e-conomic.
|
||||
- Viser linjeskift i forhåndsvisningen af en e-conomic-opdatering.
|
||||
|
||||
Der følger ingen ny databasemigration med denne release.
|
||||
@ -2027,7 +2027,7 @@ class AlsoService:
|
||||
description = line.get("product_name") or line.get("matched_product_name") or "Cloud abonnement"
|
||||
charge_period = _format_charge_period(line.get("charge_interval"))
|
||||
if charge_period:
|
||||
description = f"{description}\nPeriode: {charge_period}"
|
||||
description = f"{description} · Periode: {charge_period}"
|
||||
|
||||
draft_lines.append(
|
||||
{
|
||||
|
||||
@ -344,9 +344,9 @@
|
||||
const index = line.originalIndex;
|
||||
const isManual = line.source_type === 'manual';
|
||||
const descriptionField = isManual
|
||||
? `<textarea class="form-control form-control-sm" rows="2" style="min-width:260px; resize:vertical;"
|
||||
onchange="ordreLines[${index}].description = this.value;">${escapeHtml(line.description || '')}</textarea>`
|
||||
: `<span style="white-space:pre-line">${escapeHtml(line.description || '-')}</span>`;
|
||||
? `<input type="text" class="form-control form-control-sm" value="${escapeHtml(line.description || '')}"
|
||||
onchange="ordreLines[${index}].description = this.value;">`
|
||||
: escapeHtml(line.description || '-');
|
||||
|
||||
const manualActions = isManual
|
||||
? `
|
||||
|
||||
@ -473,9 +473,9 @@
|
||||
const isExportedLine = line.export_status === 'exported';
|
||||
const mayEditExportedDraft = isExportedLine && orderData && orderData.sync_status === 'exported' && !orderData.economic_invoice_number;
|
||||
const lockLine = isExportedLine && !mayEditExportedDraft;
|
||||
const descriptionField = `<textarea class="form-control form-control-sm" rows="2" style="min-width:260px; resize:vertical;"
|
||||
const descriptionField = `<input type="text" class="form-control form-control-sm" value="${escapeHtml(line.description || '')}"
|
||||
${lockLine ? 'disabled' : ''}
|
||||
onchange="orderLines[${index}].description = this.value;">${escapeHtml(line.description || '')}</textarea>`;
|
||||
onchange="orderLines[${index}].description = this.value;">`;
|
||||
|
||||
const exportStatus = line.export_status || '-';
|
||||
const statusBadge = exportStatus === 'exported'
|
||||
@ -890,7 +890,7 @@
|
||||
const before = data.before || {}, after = data.after || {};
|
||||
const rows = (after.lines || []).map((line, i) => {
|
||||
const old = (before.lines || [])[i] || {};
|
||||
return `<tr><td>${escapeHtml(line.product_number || '-')}</td><td style="white-space:pre-line">${escapeHtml(old.description)} → ${escapeHtml(line.description)}</td><td>${escapeHtml(old.quantity)} → ${escapeHtml(line.quantity)}</td><td>${escapeHtml(old.unit_price)} → ${escapeHtml(line.unit_price)}</td><td>${escapeHtml(old.discount_percentage)} → ${escapeHtml(line.discount_percentage)}</td></tr>`;
|
||||
return `<tr><td>${escapeHtml(line.product_number || '-')}</td><td>${escapeHtml(old.description)} → ${escapeHtml(line.description)}</td><td>${escapeHtml(old.quantity)} → ${escapeHtml(line.quantity)}</td><td>${escapeHtml(old.unit_price)} → ${escapeHtml(line.unit_price)}</td><td>${escapeHtml(old.discount_percentage)} → ${escapeHtml(line.discount_percentage)}</td></tr>`;
|
||||
}).join('');
|
||||
document.getElementById('economicUpdateComparison').innerHTML = `<div class="mb-3"><strong>Noter:</strong> ${escapeHtml(before.notes || '-')} → ${escapeHtml(after.notes || '-')}</div><div class="table-responsive"><table class="table table-sm"><thead><tr><th>Vare</th><th>Beskrivelse</th><th>Antal</th><th>Pris</th><th>Rabat %</th></tr></thead><tbody>${rows}</tbody></table></div>`;
|
||||
bootstrap.Modal.getOrCreateInstance(document.getElementById('economicUpdatePreviewModal')).show();
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
BEGIN;
|
||||
|
||||
-- Put the ALSO billing period on its own line for pending order drafts.
|
||||
UPDATE ordre_drafts
|
||||
SET lines_json = (
|
||||
SELECT jsonb_agg(
|
||||
CASE
|
||||
WHEN item->>'source_type' = 'also_cloud'
|
||||
AND COALESCE(item->>'description', '') LIKE '% · Periode: %'
|
||||
THEN jsonb_set(
|
||||
item,
|
||||
'{description}',
|
||||
to_jsonb(replace(item->>'description', ' · Periode: ', E'\nPeriode: '))
|
||||
)
|
||||
ELSE item
|
||||
END
|
||||
ORDER BY ordinality
|
||||
)
|
||||
FROM jsonb_array_elements(lines_json) WITH ORDINALITY AS source(item, ordinality)
|
||||
),
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE sync_status = 'pending'
|
||||
AND invoice_aggregate_key LIKE 'also-cloud-%'
|
||||
AND lines_json::text LIKE '% · Periode: %';
|
||||
|
||||
COMMIT;
|
||||
Loading…
Reference in New Issue
Block a user