feat: show prices for all mappings + remove VAT% display
Join price policies directly into get_mappings() query so single-article mappings display prices without extra API calls. Remove VAT percentage from kit price display. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -61,9 +61,14 @@ async def mappings_page(request: Request):
|
||||
async def list_mappings(search: str = "", page: int = 1, per_page: int = 50,
|
||||
sort_by: str = "sku", sort_dir: str = "asc",
|
||||
show_deleted: bool = False):
|
||||
app_settings = await sqlite_service.get_app_settings()
|
||||
id_pol = int(app_settings.get("id_pol") or 0) or None
|
||||
id_pol_productie = int(app_settings.get("id_pol_productie") or 0) or None
|
||||
|
||||
result = mapping_service.get_mappings(search=search, page=page, per_page=per_page,
|
||||
sort_by=sort_by, sort_dir=sort_dir,
|
||||
show_deleted=show_deleted)
|
||||
show_deleted=show_deleted,
|
||||
id_pol=id_pol, id_pol_productie=id_pol_productie)
|
||||
# Merge product names from web_products (R4)
|
||||
skus = list({m["sku"] for m in result.get("mappings", [])})
|
||||
product_names = await sqlite_service.get_web_products_batch(skus)
|
||||
|
||||
@@ -9,7 +9,8 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
def get_mappings(search: str = "", page: int = 1, per_page: int = 50,
|
||||
sort_by: str = "sku", sort_dir: str = "asc",
|
||||
show_deleted: bool = False):
|
||||
show_deleted: bool = False,
|
||||
id_pol: int = None, id_pol_productie: int = None):
|
||||
"""Get paginated mappings with optional search and sorting."""
|
||||
if database.pool is None:
|
||||
raise HTTPException(status_code=503, detail="Oracle unavailable")
|
||||
@@ -48,13 +49,28 @@ def get_mappings(search: str = "", page: int = 1, per_page: int = 50,
|
||||
params["search"] = search
|
||||
where = "WHERE " + " AND ".join(where_clauses) if where_clauses else ""
|
||||
|
||||
# Add price policy params
|
||||
params["id_pol"] = id_pol
|
||||
params["id_pol_prod"] = id_pol_productie
|
||||
|
||||
# Fetch ALL matching rows (no pagination yet — we need to group by SKU first)
|
||||
data_sql = f"""
|
||||
SELECT at.sku, at.codmat, na.denumire, na.um, at.cantitate_roa,
|
||||
at.activ, at.sters,
|
||||
TO_CHAR(at.data_creare, 'YYYY-MM-DD HH24:MI') as data_creare
|
||||
TO_CHAR(at.data_creare, 'YYYY-MM-DD HH24:MI') as data_creare,
|
||||
ROUND(CASE WHEN pp.preturi_cu_tva = 1
|
||||
THEN NVL(ppa.pret, 0)
|
||||
ELSE NVL(ppa.pret, 0) * NVL(ppa.proc_tvav, 1.19)
|
||||
END, 2) AS pret_cu_tva
|
||||
FROM ARTICOLE_TERTI at
|
||||
LEFT JOIN nom_articole na ON na.codmat = at.codmat
|
||||
LEFT JOIN crm_politici_pret_art ppa
|
||||
ON ppa.id_articol = na.id_articol
|
||||
AND ppa.id_pol = CASE
|
||||
WHEN TRIM(na.cont) IN ('341','345') AND :id_pol_prod IS NOT NULL
|
||||
THEN :id_pol_prod ELSE :id_pol END
|
||||
LEFT JOIN crm_politici_preturi pp
|
||||
ON pp.id_pol = ppa.id_pol
|
||||
{where}
|
||||
ORDER BY {order_clause}
|
||||
"""
|
||||
@@ -351,8 +367,10 @@ def get_component_prices(sku: str, id_pol: int, id_pol_productie: int = None) ->
|
||||
""", {"sku": sku})
|
||||
components = cur.fetchall()
|
||||
|
||||
if len(components) <= 1:
|
||||
return [] # Not a kit
|
||||
if len(components) == 0:
|
||||
return []
|
||||
if len(components) == 1 and (components[0][1] or 1) <= 1:
|
||||
return [] # True 1:1 mapping, no kit pricing needed
|
||||
|
||||
result = []
|
||||
for codmat, cant_roa, id_art, cont, denumire in components:
|
||||
|
||||
@@ -121,13 +121,14 @@ function renderTable(mappings, showDeleted) {
|
||||
}
|
||||
const deletedStyle = m.sters ? 'text-decoration:line-through;opacity:0.5;' : '';
|
||||
const isKitRow = (skuCodmatCount[m.sku] || 0) > 1;
|
||||
const priceSlot = isKitRow ? `<span class="kit-price-slot text-muted small ms-2" data-sku="${esc(m.sku)}" data-codmat="${esc(m.codmat)}"></span>` : '';
|
||||
const kitPriceSlot = isKitRow ? `<span class="kit-price-slot text-muted small ms-2" data-sku="${esc(m.sku)}" data-codmat="${esc(m.codmat)}"></span>` : '';
|
||||
const inlinePrice = m.pret_cu_tva ? `<span class="text-muted small ms-2">${parseFloat(m.pret_cu_tva).toFixed(2)} lei</span>` : '';
|
||||
html += `<div class="flat-row" style="padding-left:1.5rem;font-size:0.9rem;${deletedStyle}">
|
||||
<code>${esc(m.codmat)}</code>
|
||||
<span class="grow truncate text-muted" style="font-size:0.85rem">${esc(m.denumire || '')}</span>
|
||||
<span class="text-nowrap" style="font-size:0.875rem">
|
||||
<span class="${m.sters ? '' : 'editable'}" style="cursor:${m.sters ? 'default' : 'pointer'}"
|
||||
${m.sters ? '' : `onclick="editFlatValue(this, '${esc(m.sku)}', '${esc(m.codmat)}', 'cantitate_roa', ${m.cantitate_roa})"`}>x${m.cantitate_roa}</span>${priceSlot}
|
||||
${m.sters ? '' : `onclick="editFlatValue(this, '${esc(m.sku)}', '${esc(m.codmat)}', 'cantitate_roa', ${m.cantitate_roa})"`}>x${m.cantitate_roa}</span>${isKitRow ? kitPriceSlot : inlinePrice}
|
||||
</span>
|
||||
</div>`;
|
||||
|
||||
@@ -197,7 +198,7 @@ function renderKitPrices(sku, prices, container) {
|
||||
const codmat = slot.dataset.codmat;
|
||||
const p = prices.find(pr => pr.codmat === codmat);
|
||||
if (p && p.pret_cu_tva > 0) {
|
||||
slot.innerHTML = `${p.pret_cu_tva.toFixed(2)} lei (${p.ptva}%)`;
|
||||
slot.innerHTML = `${p.pret_cu_tva.toFixed(2)} lei`;
|
||||
total += p.pret_cu_tva * (p.cantitate_roa || 1);
|
||||
} else if (p) {
|
||||
slot.innerHTML = `<span class="text-muted">fără preț</span>`;
|
||||
|
||||
@@ -150,5 +150,5 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="{{ request.scope.get('root_path', '') }}/static/js/mappings.js?v=10"></script>
|
||||
<script src="{{ request.scope.get('root_path', '') }}/static/js/mappings.js?v=11"></script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user