changing labels print

This commit is contained in:
Flatlogic Bot 2026-02-13 05:02:00 +00:00
parent be969df378
commit 07fac2272f
9 changed files with 200 additions and 53 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

29
check_libs.py Normal file
View File

@ -0,0 +1,29 @@
import os
from cffi import FFI
ffi = FFI()
def _dlopen(*names):
for name in names:
try:
lib = ffi.dlopen(name)
print(f"Loaded {name}")
return lib
except OSError as e:
print(f"Failed to load {name}: {e}")
return None
print("Checking gobject...")
_dlopen('libgobject-2.0-0', 'gobject-2.0-0', 'gobject-2.0', 'libgobject-2.0.so.0')
print("\nChecking pango...")
_dlopen('libpango-1.0-0', 'pango-1.0-0', 'pango-1.0', 'libpango-1.0.so.0')
print("\nChecking harfbuzz...")
_dlopen('libharfbuzz-0', 'harfbuzz', 'harfbuzz-0.0', 'libharfbuzz.so.0')
print("\nChecking fontconfig...")
_dlopen('libfontconfig-1', 'fontconfig-1', 'fontconfig', 'libfontconfig.so.1')
print("\nChecking pangoft2...")
_dlopen('libpangoft2-1.0-0', 'pangoft2-1.0-0', 'pangoft2-1.0', 'libpangoft2-1.0.so.0')

View File

@ -5,9 +5,14 @@
<div class="container-fluid mt-4 mb-5 no-print">
<div class="d-flex justify-content-between align-items-center mb-4">
<h2 class="h4 mb-0"><i class="bi bi-upc-scan me-2"></i>Barcode Label Printing</h2>
<button id="printQueueBtn" class="btn btn-primary">
<i class="bi bi-printer me-2"></i>Print Label Queue
</button>
<div class="d-flex gap-2">
<button id="clearQueueBtn" class="btn btn-outline-danger">
<i class="bi bi-trash me-2"></i>Clear Queue
</button>
<button id="printQueueBtn" class="btn btn-primary">
<i class="bi bi-printer me-2"></i>Print Label Queue
</button>
</div>
</div>
<div class="row">
@ -132,24 +137,17 @@
<!-- Live Preview -->
<div class="card shadow-sm border-0">
<div class="card-header bg-white py-3 d-flex justify-content-between align-items-center">
<h5 class="card-title mb-0">3. Live Preview (Single Label)</h5>
<h5 class="card-title mb-0">3. Live Preview (Queue Preview)</h5>
<button type="button" class="btn btn-sm btn-success" id="printPreviewBtn">
<i class="bi bi-printer me-1"></i>Print This Label
<i class="bi bi-printer me-1"></i>Print All in Queue
</button>
</div>
<div class="card-body text-center bg-light p-5">
<div id="previewContainer" class="d-inline-block bg-white shadow-sm p-3 border">
<div id="previewLabelContent">
<div class="preview-name fw-bold small mb-1">Product Name</div>
<svg id="previewBarcode"></svg>
<div class="preview-footer d-flex justify-content-between mt-1 small">
<span class="preview-sku">SKU12345</span>
<span class="preview-price fw-bold">OMR 0.000</span>
</div>
</div>
<div class="card-body text-center bg-light p-4">
<div id="previewContainer" class="d-flex flex-wrap justify-content-center gap-3">
<!-- Dynamic preview labels will be injected here -->
</div>
<div class="mt-3 text-muted small">
Note: This is a preview of the layout. Actual print layout depends on settings above.
Note: This preview shows one of each product in your queue. Actual sheet layout will be generated on print.
</div>
</div>
</div>
@ -481,6 +479,17 @@ document.addEventListener('DOMContentLoaded', function() {
printQueueBtn.addEventListener('click', handlePrintQueue);
}
const clearQueueBtn = document.getElementById('clearQueueBtn');
if (clearQueueBtn) {
clearQueueBtn.addEventListener('click', function() {
if (confirm("Are you sure you want to clear the entire queue?")) {
queue.length = 0;
renderQueue();
updatePreview();
}
});
}
function handlePrintQueue() {
if (queue.length === 0) return;
preparePrint();
@ -491,7 +500,7 @@ document.addEventListener('DOMContentLoaded', function() {
const printPreviewBtn = document.getElementById('printPreviewBtn');
if (printPreviewBtn) {
printPreviewBtn.addEventListener('click', printSingleFromPreview);
printPreviewBtn.addEventListener('click', handlePrintQueue);
}
// Product Search
@ -514,38 +523,90 @@ document.addEventListener('DOMContentLoaded', function() {
// --- PREVIEW LOGIC ---
function updatePreview() {
let product = null;
const container = document.getElementById('previewContainer');
if (!container) return;
container.innerHTML = '';
// Items to show: either everything in the queue, or the last added if queue is empty
let itemsToShow = [];
if (queue.length > 0) {
product = queue[queue.length - 1];
itemsToShow = [...queue];
} else if (lastAddedProduct) {
product = lastAddedProduct;
itemsToShow = [lastAddedProduct];
}
if (!product) return;
const previewName = document.querySelector('.preview-name');
const previewSku = document.querySelector('.preview-sku');
const previewPrice = document.querySelector('.preview-price');
if (previewName) previewName.innerHTML = (product.nameAr ? `<div class='text-end'>${product.nameAr}</div>` : '') + `<div>${product.name}</div>`;
if (previewSku) previewSku.innerText = product.sku;
if (previewPrice) previewPrice.innerText = 'OMR ' + parseFloat(product.price).toFixed(3);
try {
if (typeof JsBarcode !== 'undefined') {
JsBarcode("#previewBarcode", product.sku, {
format: "CODE128", width: 2, height: 40, displayValue: false, margin: 0
});
}
} catch(e) {}
if (itemsToShow.length === 0) {
container.innerHTML = '<div class="py-4 text-muted">No items selected for preview</div>';
return;
}
const labelType = document.getElementById('labelType').value;
const showName = document.getElementById('showName').checked;
const showPrice = document.getElementById('showPrice').checked;
const showSKU = document.getElementById('showSKU').checked;
if (previewName) previewName.style.display = showName ? '' : 'none';
if (previewPrice) previewPrice.style.display = showPrice ? '' : 'none';
if (previewSku) previewSku.style.display = showSKU ? '' : 'none';
itemsToShow.forEach((p, idx) => {
const previewItem = document.createElement('div');
previewItem.className = 'bg-white shadow-sm border p-2 d-flex flex-column align-items-center justify-content-center position-relative';
// Apply approximate styles based on labelType for the preview
let pWidth = "180px";
let pHeight = "auto";
let minHeight = "100px";
if (labelType === 'l7651') { pWidth = "150px"; minHeight = "80px"; }
else if (labelType === 'l7656') { pWidth = "180px"; minHeight = "50px"; }
else if (labelType === 'a4-40') { pWidth = "160px"; minHeight = "90px"; }
previewItem.style.width = pWidth;
previewItem.style.minHeight = minHeight;
let content = '';
if (p.qty > 1) {
content += `<span class="badge bg-secondary position-absolute top-0 end-0 m-1" title="Quantity to print">${p.qty}x</span>`;
}
if (labelType === 'l7656') {
content = `<div class="d-flex align-items-center justify-content-between w-100 gap-2">`;
if (showName) content += `<div class="small fw-bold text-start" style="font-size: 0.7rem; max-width: 60px;">${p.nameAr ? p.nameAr + " " : ""}${p.name}</div>`;
content += `<svg class="preview-barcode-item"></svg>`;
if (showPrice) content += `<div class="small fw-bold" style="font-size: 0.7rem;">${parseFloat(p.price).toFixed(3)}</div>`;
content += `</div>`;
} else {
if (showName) {
content += `<div class="fw-bold small mb-1 w-100 text-center text-truncate" title="${p.name}">`;
if (p.nameAr) content += `<div class="text-muted" style="font-size: 0.7rem">${p.nameAr}</div>`;
content += `${p.name}</div>`;
}
content += `<svg class="preview-barcode-item"></svg>`;
if (showSKU || showPrice) {
content += `<div class="d-flex justify-content-between w-100 mt-1" style="font-size: 0.7rem;">`;
if (showSKU) content += `<span class="text-muted">${p.sku}</span>`;
if (showPrice) content += `<span class="fw-bold text-success">OMR ${parseFloat(p.price).toFixed(3)}</span>`;
content += `</div>`;
}
}
previewItem.innerHTML = content;
container.appendChild(previewItem);
// Render barcode
const svgEl = previewItem.querySelector('.preview-barcode-item');
if (svgEl && typeof JsBarcode !== 'undefined') {
let bWidth = 1.2;
let bHeight = 30;
if (labelType === 'l7651') { bWidth = 0.9; bHeight = 20; }
else if (labelType === 'l7656') { bWidth = 0.8; bHeight = 15; }
else if (labelType === 'price-tag') { bWidth = 0.8; bHeight = 15; }
try {
JsBarcode(svgEl, p.sku, {
format: "CODE128", width: bWidth, height: bHeight, displayValue: false, margin: 0
});
} catch(e) {}
}
});
}
// --- DIRECT PRINT ---
@ -560,16 +621,6 @@ document.addEventListener('DOMContentLoaded', function() {
performDirectPrint(product);
}
function printSingleFromPreview() {
let product = null;
if (queue.length > 0) {
product = queue[queue.length - 1];
} else if (lastAddedProduct) {
product = lastAddedProduct;
}
if (product) performDirectPrint(product);
}
function performDirectPrint(product) {
document.body.classList.add('direct-print-mode');
printArea.innerHTML = '';
@ -718,7 +769,7 @@ document.addEventListener('DOMContentLoaded', function() {
}
// --- SETUP LISTENERS ---
document.getElementById('labelType').addEventListener('change', () => preparePrint());
document.getElementById('labelType').addEventListener('change', () => { updatePreview(); preparePrint(); });
document.getElementById('showName').addEventListener('change', () => { updatePreview(); preparePrint(); });
document.getElementById('showPrice').addEventListener('change', () => { updatePreview(); preparePrint(); });
document.getElementById('showSKU').addEventListener('change', () => { updatePreview(); preparePrint(); });

View File

@ -172,4 +172,5 @@ urlpatterns = [
# Database Backup/Restore
path('settings/backup/', views.backup_database, name='backup_database'),
path('settings/restore/', views.restore_database, name='restore_database'),
path('api/test-pdf/', views.test_pdf_view, name='test_pdf_view'),
]

View File

@ -43,6 +43,16 @@ logger = logging.getLogger(__name__)
# --- Basic Views ---
def test_pdf_view(request):
from weasyprint import HTML
html_string = "<h1>Test PDF</h1>"
pdf = HTML(string=html_string).write_pdf()
return HttpResponse(pdf, content_type='application/pdf')
@login_required
def dashboard(request):
return redirect('core:index')
@login_required
def index(request):
settings = SystemSetting.objects.first()

33
reproduce_error.py Normal file
View File

@ -0,0 +1,33 @@
import os
import django
from django.conf import settings as django_settings
from django.template.loader import render_to_string
from django.test import RequestFactory
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
django.setup()
from core.views import generate_pdf_file
from core.models import Sale
def test_pdf():
try:
sale = Sale.objects.first()
if not sale:
print("No sales found")
return
request = RequestFactory().get('/')
context = {'sale': sale} # Simplified context
print("Testing PDF generation...")
pdf = generate_pdf_file('pdf/invoice_pdf.html', context, request)
print(f"PDF generated successfully, size: {len(pdf)}")
except Exception as e:
print(f"Caught error: {e}")
import traceback
traceback.print_exc()
if __name__ == "__main__":
test_pdf()

23
test_weasyprint.py Normal file
View File

@ -0,0 +1,23 @@
import os
import sys
import django
from django.conf import settings as django_settings
from django.template.loader import render_to_string
# Setup Django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
django.setup()
def test_pdf():
from weasyprint import HTML
print("Imported weasyprint")
html_string = "<h1>Test</h1>"
try:
pdf = HTML(string=html_string).write_pdf()
print(f"Success! PDF size: {len(pdf)}")
except Exception as e:
print(f"Failed: {e}")
if __name__ == "__main__":
test_pdf()