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,
|
async def list_mappings(search: str = "", page: int = 1, per_page: int = 50,
|
||||||
sort_by: str = "sku", sort_dir: str = "asc",
|
sort_by: str = "sku", sort_dir: str = "asc",
|
||||||
show_deleted: bool = False):
|
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,
|
result = mapping_service.get_mappings(search=search, page=page, per_page=per_page,
|
||||||
sort_by=sort_by, sort_dir=sort_dir,
|
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)
|
# Merge product names from web_products (R4)
|
||||||
skus = list({m["sku"] for m in result.get("mappings", [])})
|
skus = list({m["sku"] for m in result.get("mappings", [])})
|
||||||
product_names = await sqlite_service.get_web_products_batch(skus)
|
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,
|
def get_mappings(search: str = "", page: int = 1, per_page: int = 50,
|
||||||
sort_by: str = "sku", sort_dir: str = "asc",
|
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."""
|
"""Get paginated mappings with optional search and sorting."""
|
||||||
if database.pool is None:
|
if database.pool is None:
|
||||||
raise HTTPException(status_code=503, detail="Oracle unavailable")
|
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
|
params["search"] = search
|
||||||
where = "WHERE " + " AND ".join(where_clauses) if where_clauses else ""
|
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)
|
# Fetch ALL matching rows (no pagination yet — we need to group by SKU first)
|
||||||
data_sql = f"""
|
data_sql = f"""
|
||||||
SELECT at.sku, at.codmat, na.denumire, na.um, at.cantitate_roa,
|
SELECT at.sku, at.codmat, na.denumire, na.um, at.cantitate_roa,
|
||||||
at.activ, at.sters,
|
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
|
FROM ARTICOLE_TERTI at
|
||||||
LEFT JOIN nom_articole na ON na.codmat = at.codmat
|
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}
|
{where}
|
||||||
ORDER BY {order_clause}
|
ORDER BY {order_clause}
|
||||||
"""
|
"""
|
||||||
@@ -351,8 +367,10 @@ def get_component_prices(sku: str, id_pol: int, id_pol_productie: int = None) ->
|
|||||||
""", {"sku": sku})
|
""", {"sku": sku})
|
||||||
components = cur.fetchall()
|
components = cur.fetchall()
|
||||||
|
|
||||||
if len(components) <= 1:
|
if len(components) == 0:
|
||||||
return [] # Not a kit
|
return []
|
||||||
|
if len(components) == 1 and (components[0][1] or 1) <= 1:
|
||||||
|
return [] # True 1:1 mapping, no kit pricing needed
|
||||||
|
|
||||||
result = []
|
result = []
|
||||||
for codmat, cant_roa, id_art, cont, denumire in components:
|
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 deletedStyle = m.sters ? 'text-decoration:line-through;opacity:0.5;' : '';
|
||||||
const isKitRow = (skuCodmatCount[m.sku] || 0) > 1;
|
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}">
|
html += `<div class="flat-row" style="padding-left:1.5rem;font-size:0.9rem;${deletedStyle}">
|
||||||
<code>${esc(m.codmat)}</code>
|
<code>${esc(m.codmat)}</code>
|
||||||
<span class="grow truncate text-muted" style="font-size:0.85rem">${esc(m.denumire || '')}</span>
|
<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="text-nowrap" style="font-size:0.875rem">
|
||||||
<span class="${m.sters ? '' : 'editable'}" style="cursor:${m.sters ? 'default' : 'pointer'}"
|
<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>
|
</span>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
@@ -197,7 +198,7 @@ function renderKitPrices(sku, prices, container) {
|
|||||||
const codmat = slot.dataset.codmat;
|
const codmat = slot.dataset.codmat;
|
||||||
const p = prices.find(pr => pr.codmat === codmat);
|
const p = prices.find(pr => pr.codmat === codmat);
|
||||||
if (p && p.pret_cu_tva > 0) {
|
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);
|
total += p.pret_cu_tva * (p.cantitate_roa || 1);
|
||||||
} else if (p) {
|
} else if (p) {
|
||||||
slot.innerHTML = `<span class="text-muted">fără preț</span>`;
|
slot.innerHTML = `<span class="text-muted">fără preț</span>`;
|
||||||
|
|||||||
@@ -150,5 +150,5 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block scripts %}
|
{% 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 %}
|
{% endblock %}
|
||||||
|
|||||||
Reference in New Issue
Block a user