Autosave: 20260213-030304

This commit is contained in:
Flatlogic Bot 2026-02-13 03:03:06 +00:00
parent 7166fdc776
commit 3360fbcad2
10 changed files with 179 additions and 55 deletions

View File

@ -155,6 +155,8 @@ SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SAMESITE = "None"
CSRF_COOKIE_SAMESITE = "None"
SECURE_CROSS_ORIGIN_OPENER_POLICY = None
SECURE_REFERRER_POLICY = 'no-referrer-when-downgrade'
# X_FRAME_OPTIONS = 'SAMEORIGIN'
# Email Settings

View File

@ -20,12 +20,11 @@ try:
except ImportError:
pass
# --- FIX: Preload libraries for WeasyPrint/Pango ---
# Manually load libraries using absolute paths
import ctypes
import ctypes.util
# --- WeasyPrint Library Preloading ---
import traceback
import sys
import ctypes
import ctypes.util
lib_paths = [
'/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0',
@ -42,31 +41,13 @@ for path in lib_paths:
except OSError:
pass
# Try to import weasyprint
try:
import weasyprint
except Exception as e:
# Log error to file and stderr
error_msg = f"WeasyPrint Import Error: {str(e)}\n{traceback.format_exc()}"
sys.stderr.write(error_msg)
try:
with open("weasyprint_wsgi_error.log", "w") as f:
f.write(error_msg)
except Exception:
pass
# Fallback to mock
import types
class MockHTML:
def __init__(self, string=None, base_url=None):
pass
def write_pdf(self, target=None):
raise OSError("WeasyPrint system dependencies are missing. PDF generation is disabled.")
mock_wp = types.ModuleType("weasyprint")
mock_wp.HTML = MockHTML
sys.modules["weasyprint"] = mock_wp
# ---------------------------------------------------
with open("/tmp/weasyprint_wsgi_error.log", "w") as f:
f.write(error_msg)
# -------------------------------------
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')

View File

@ -34,7 +34,6 @@
{% block head %}{% endblock %}
</head>
<body>
<div id="wrapper">
<!-- Sidebar -->
{% if user.is_authenticated %}

View File

@ -636,7 +636,12 @@ def sale_receipt(request, pk):
@login_required
def quotations(request):
quotations = Quotation.objects.all().order_by('-created_at')
quotations_qs = Quotation.objects.all().order_by('-created_at')
paginator = Paginator(quotations_qs, 20)
page_number = request.GET.get('page')
quotations = paginator.get_page(page_number)
return render(request, 'core/quotations.html', {'quotations': quotations})
@login_required
@ -690,11 +695,60 @@ def delete_quotation(request, pk):
messages.success(request, _("Quotation deleted."))
return redirect('quotations')
@csrf_exempt
@login_required
def create_quotation_api(request):
# Simplified API stub
return JsonResponse({'success': True})
if request.method != 'POST':
return JsonResponse({'success': False, 'error': 'Method not allowed'})
try:
data = json.loads(request.body)
customer_id = data.get('customer_id')
quotation_number = data.get('quotation_number')
items = data.get('items', [])
total_amount = data.get('total_amount', 0)
discount = data.get('discount', 0)
valid_until = data.get('valid_until')
terms_and_conditions = data.get('terms_and_conditions', '')
notes = data.get('notes', '')
if not items:
return JsonResponse({'success': False, 'error': _('Cannot save an empty quotation.')})
with transaction.atomic():
customer = None
if customer_id:
customer = Customer.objects.get(id=customer_id)
quotation = Quotation.objects.create(
customer=customer,
quotation_number=quotation_number,
total_amount=total_amount,
discount=discount,
valid_until=valid_until if valid_until else None,
terms_and_conditions=terms_and_conditions,
notes=notes,
created_by=request.user
)
for item in items:
product = Product.objects.get(id=item['id'])
QuotationItem.objects.create(
quotation=quotation,
product=product,
quantity=item['quantity'],
unit_price=item['price'],
line_total=item['line_total']
)
messages.success(request, _("Quotation created successfully."))
return JsonResponse({'success': True, 'quotation_id': quotation.id})
except Customer.DoesNotExist:
return JsonResponse({'success': False, 'error': _('Customer not found.')})
except Product.DoesNotExist:
return JsonResponse({'success': False, 'error': _('One or more products not found.')})
except Exception as e:
logger.error(f"Error creating quotation: {str(e)}")
return JsonResponse({'success': False, 'error': str(e)})
# --- Sales Returns ---

View File

@ -14,9 +14,7 @@ def main():
except ImportError:
pass
# --- FIX: Preload libraries for WeasyPrint/Pango ---
# Manually load libraries using absolute paths since LD_LIBRARY_PATH
# changes don't affect dlopen() in the running process.
# --- WeasyPrint Library Preloading ---
import ctypes
import ctypes.util
import traceback
@ -34,34 +32,15 @@ def main():
try:
ctypes.CDLL(path)
except OSError:
# Continue even if one fails
pass
# Try to import weasyprint to see if it works
try:
import weasyprint
except Exception as e:
# Log the specific error for debugging
error_msg = f"WeasyPrint Import Error: {str(e)}\n{traceback.format_exc()}"
sys.stderr.write(error_msg)
try:
with open("weasyprint_error.log", "w") as f:
f.write(error_msg)
except Exception:
pass
# Fallback to mock if system dependencies are missing or import fails
import types
class MockHTML:
def __init__(self, string=None, base_url=None):
pass
def write_pdf(self, target=None):
raise OSError("WeasyPrint system dependencies are missing. PDF generation is disabled.")
mock_wp = types.ModuleType("weasyprint")
mock_wp.HTML = MockHTML
sys.modules["weasyprint"] = mock_wp
# ---------------------------------------------------
with open("/tmp/weasyprint_error.log", "w") as f:
f.write(error_msg)
# -------------------------------------
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
try:

52
test_pos_render.py Normal file
View File

@ -0,0 +1,52 @@
import os
import django
from django.conf import settings
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
django.setup()
from django.template.loader import render_to_string
from django.test import RequestFactory
from core.models import Product, SystemSetting, Category, PaymentMethod
def test_pos_render():
factory = RequestFactory()
request = factory.get('/pos/')
s_settings = SystemSetting.objects.first()
products = Product.objects.filter(is_active=True)
categories = Category.objects.all()
payment_methods = PaymentMethod.objects.all()
context = {
'products': products,
'customers': [],
'categories': categories,
'payment_methods': payment_methods,
'settings': s_settings,
'site_settings': s_settings,
'active_session': None,
'LANGUAGE_CODE': 'en'
}
rendered = render_to_string('core/pos.html', context, request=request)
print(f"Total Products Checked: {products.count()}")
# Check for image URLs
for product in products:
if product.image:
url = product.image.url
if url in rendered:
print(f"Product {product.name_en} image URL FOUND: {url}")
else:
# Check for escaped URL
from django.utils.html import escape
if escape(url) in rendered:
print(f"Product {product.name_en} image URL FOUND (escaped): {escape(url)}")
else:
print(f"Product {product.name_en} image URL MISSING: {url}")
else:
print(f"Product {product.name_en} has no image in DB")
if __name__ == "__main__":
test_pos_render()

57
test_render.py Normal file
View File

@ -0,0 +1,57 @@
import os
import django
from django.conf import 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.models import SystemSetting, Product, Customer, Sale, Category, PaymentMethod
from django.utils import timezone
import datetime
def test_render():
factory = RequestFactory()
request = factory.get('/')
# Simulate a user
from django.contrib.auth.models import User
user = User.objects.first()
request.user = user
settings_obj = SystemSetting.objects.first()
context = {
'site_settings': settings_obj,
'settings': settings_obj,
'total_sales_amount': 0,
'total_receivables': 0,
'total_payables': 0,
'total_sales_count': 0,
'total_products': 0,
'total_customers': 0,
'monthly_labels': [],
'monthly_data': [],
'chart_labels': [],
'chart_data': [],
'category_labels': [],
'category_data': [],
'payment_labels': [],
'payment_data': [],
'top_products': [],
'low_stock_count': 0,
'low_stock_products': [],
'expired_count': 0,
'recent_sales': [],
}
try:
html = render_to_string('core/index.html', context, request=request)
print(f"Render successful, length: {len(html)}")
if len(html) < 100:
print("HTML is too short!")
print(html)
except Exception as e:
print(f"Render failed: {e}")
if __name__ == "__main__":
test_render()