842 lines
32 KiB
Python
842 lines
32 KiB
Python
from django.shortcuts import render, get_object_or_404, redirect
|
|
from django.db.models import Sum, Count, F
|
|
from django.db.models.functions import TruncDate, TruncMonth
|
|
from django.http import JsonResponse
|
|
from django.views.decorators.csrf import csrf_exempt
|
|
from .models import (
|
|
Product, Sale, Category, Unit, Customer, Supplier,
|
|
Purchase, PurchaseItem, PurchasePayment,
|
|
SaleItem, SalePayment, SystemSetting,
|
|
Quotation, QuotationItem,
|
|
SaleReturn, SaleReturnItem, PurchaseReturn, PurchaseReturnItem
|
|
)
|
|
import json
|
|
from datetime import timedelta
|
|
from django.utils import timezone
|
|
from django.contrib import messages
|
|
from django.utils.text import slugify
|
|
|
|
def index(request):
|
|
"""
|
|
Enhanced Meezan Dashboard View
|
|
"""
|
|
# Summary Stats
|
|
total_products = Product.objects.count()
|
|
total_sales_count = Sale.objects.count()
|
|
total_sales_amount = Sale.objects.aggregate(total=Sum('total_amount'))['total'] or 0
|
|
total_customers = Customer.objects.count()
|
|
|
|
# Stock Alert (Low stock < 5)
|
|
low_stock_products = Product.objects.filter(stock_quantity__lt=5)
|
|
|
|
# Recent Transactions
|
|
recent_sales = Sale.objects.order_by('-created_at')[:5]
|
|
|
|
# Chart Data: Sales for the last 7 days
|
|
seven_days_ago = timezone.now().date() - timedelta(days=6)
|
|
sales_over_time = Sale.objects.filter(created_at__date__gte=seven_days_ago) \
|
|
.annotate(date=TruncDate('created_at')) \
|
|
.values('date') \
|
|
.annotate(total=Sum('total_amount')) \
|
|
.order_by('date')
|
|
|
|
# Prepare data for Chart.js
|
|
chart_labels = []
|
|
chart_data = []
|
|
|
|
date_dict = {s['date']: float(s['total']) for s in sales_over_time}
|
|
for i in range(7):
|
|
date = seven_days_ago + timedelta(days=i)
|
|
chart_labels.append(date.strftime('%b %d'))
|
|
chart_data.append(date_dict.get(date, 0))
|
|
|
|
context = {
|
|
'total_products': total_products,
|
|
'total_sales_count': total_sales_count,
|
|
'total_sales_amount': total_sales_amount,
|
|
'total_customers': total_customers,
|
|
'low_stock_products': low_stock_products,
|
|
'recent_sales': recent_sales,
|
|
'chart_labels': json.dumps(chart_labels),
|
|
'chart_data': json.dumps(chart_data),
|
|
}
|
|
return render(request, 'core/index.html', context)
|
|
|
|
def inventory(request):
|
|
products = Product.objects.all().select_related('category', 'unit', 'supplier')
|
|
categories = Category.objects.all()
|
|
units = Unit.objects.all()
|
|
suppliers = Supplier.objects.all()
|
|
context = {
|
|
'products': products,
|
|
'categories': categories,
|
|
'units': units,
|
|
'suppliers': suppliers
|
|
}
|
|
return render(request, 'core/inventory.html', context)
|
|
|
|
def pos(request):
|
|
products = Product.objects.all().filter(stock_quantity__gt=0, is_active=True)
|
|
customers = Customer.objects.all()
|
|
categories = Category.objects.all()
|
|
context = {'products': products, 'customers': customers, 'categories': categories}
|
|
return render(request, 'core/pos.html', context)
|
|
|
|
def customers(request):
|
|
customers_list = Customer.objects.all().annotate(total_sales=Sum('sales__total_amount'))
|
|
context = {'customers': customers_list}
|
|
return render(request, 'core/customers.html', context)
|
|
|
|
def suppliers(request):
|
|
suppliers_list = Supplier.objects.all()
|
|
context = {'suppliers': suppliers_list}
|
|
return render(request, 'core/suppliers.html', context)
|
|
|
|
# --- Purchase Views ---
|
|
|
|
def purchases(request):
|
|
purchases_list = Purchase.objects.all().select_related('supplier').order_by('-created_at')
|
|
suppliers_list = Supplier.objects.all()
|
|
context = {'purchases': purchases_list, 'suppliers': suppliers_list}
|
|
return render(request, 'core/purchases.html', context)
|
|
|
|
def purchase_create(request):
|
|
products = Product.objects.filter(is_active=True)
|
|
suppliers = Supplier.objects.all()
|
|
return render(request, 'core/purchase_create.html', {'products': products, 'suppliers': suppliers})
|
|
|
|
def purchase_detail(request, pk):
|
|
purchase = get_object_or_404(Purchase, pk=pk)
|
|
settings = SystemSetting.objects.first()
|
|
return render(request, 'core/purchase_detail.html', {'purchase': purchase, 'settings': settings})
|
|
|
|
@csrf_exempt
|
|
def create_purchase_api(request):
|
|
if request.method == 'POST':
|
|
try:
|
|
data = json.loads(request.body)
|
|
supplier_id = data.get('supplier_id')
|
|
invoice_number = data.get('invoice_number', '')
|
|
items = data.get('items', [])
|
|
total_amount = data.get('total_amount', 0)
|
|
paid_amount = data.get('paid_amount', 0)
|
|
payment_type = data.get('payment_type', 'cash')
|
|
due_date = data.get('due_date')
|
|
notes = data.get('notes', '')
|
|
|
|
supplier = None
|
|
if supplier_id:
|
|
supplier = Supplier.objects.get(id=supplier_id)
|
|
|
|
purchase = Purchase.objects.create(
|
|
supplier=supplier,
|
|
invoice_number=invoice_number,
|
|
total_amount=total_amount,
|
|
paid_amount=paid_amount,
|
|
balance_due=float(total_amount) - float(paid_amount),
|
|
payment_type=payment_type,
|
|
due_date=due_date if due_date else None,
|
|
notes=notes
|
|
)
|
|
|
|
# Set status based on payments
|
|
if float(paid_amount) >= float(total_amount):
|
|
purchase.status = 'paid'
|
|
elif float(paid_amount) > 0:
|
|
purchase.status = 'partial'
|
|
else:
|
|
purchase.status = 'unpaid'
|
|
purchase.save()
|
|
|
|
# Record the initial payment if any
|
|
if float(paid_amount) > 0:
|
|
PurchasePayment.objects.create(
|
|
purchase=purchase,
|
|
amount=paid_amount,
|
|
payment_method=payment_type.capitalize(),
|
|
notes=_("Initial payment")
|
|
)
|
|
|
|
for item in items:
|
|
product = Product.objects.get(id=item['id'])
|
|
PurchaseItem.objects.create(
|
|
purchase=purchase,
|
|
product=product,
|
|
quantity=item['quantity'],
|
|
cost_price=item['price'],
|
|
line_total=item['line_total']
|
|
)
|
|
# Update Stock
|
|
product.stock_quantity += int(item['quantity'])
|
|
product.cost_price = item['price']
|
|
product.save()
|
|
|
|
return JsonResponse({'success': True, 'purchase_id': purchase.id})
|
|
except Exception as e:
|
|
return JsonResponse({'success': False, 'error': str(e)}, status=400)
|
|
return JsonResponse({'success': False, 'error': 'Invalid request'}, status=405)
|
|
|
|
def add_purchase_payment(request, pk):
|
|
purchase = get_object_or_404(Purchase, pk=pk)
|
|
if request.method == 'POST':
|
|
amount = request.POST.get('amount')
|
|
payment_date = request.POST.get('payment_date', timezone.now().date())
|
|
payment_method = request.POST.get('payment_method', 'Cash')
|
|
notes = request.POST.get('notes', '')
|
|
|
|
PurchasePayment.objects.create(
|
|
purchase=purchase,
|
|
amount=amount,
|
|
payment_date=payment_date,
|
|
payment_method=payment_method,
|
|
notes=notes
|
|
)
|
|
purchase.update_balance()
|
|
messages.success(request, _("Payment added successfully!"))
|
|
return redirect('purchases')
|
|
|
|
def delete_purchase(request, pk):
|
|
purchase = get_object_or_404(Purchase, pk=pk)
|
|
for item in purchase.items.all():
|
|
item.product.stock_quantity -= item.quantity
|
|
item.product.save()
|
|
|
|
purchase.delete()
|
|
messages.success(request, _("Purchase deleted successfully!"))
|
|
return redirect('purchases')
|
|
|
|
# --- Sale Views ---
|
|
|
|
def invoice_list(request):
|
|
sales = Sale.objects.all().order_by('-created_at')
|
|
customers = Customer.objects.all()
|
|
return render(request, 'core/invoices.html', {'sales': sales, 'customers': customers})
|
|
|
|
def invoice_create(request):
|
|
products = Product.objects.filter(is_active=True)
|
|
customers = Customer.objects.all()
|
|
return render(request, 'core/invoice_create.html', {'products': products, 'customers': customers})
|
|
|
|
def invoice_detail(request, pk):
|
|
sale = get_object_or_404(Sale, pk=pk)
|
|
settings = SystemSetting.objects.first()
|
|
return render(request, 'core/invoice_detail.html', {'sale': sale, 'settings': settings})
|
|
|
|
@csrf_exempt
|
|
def create_sale_api(request):
|
|
if request.method == 'POST':
|
|
try:
|
|
data = json.loads(request.body)
|
|
customer_id = data.get('customer_id')
|
|
invoice_number = data.get('invoice_number', '')
|
|
items = data.get('items', [])
|
|
total_amount = data.get('total_amount', 0)
|
|
paid_amount = data.get('paid_amount', 0)
|
|
discount = data.get('discount', 0)
|
|
payment_type = data.get('payment_type', 'cash')
|
|
due_date = data.get('due_date')
|
|
notes = data.get('notes', '')
|
|
|
|
customer = None
|
|
if customer_id:
|
|
customer = Customer.objects.get(id=customer_id)
|
|
|
|
sale = Sale.objects.create(
|
|
customer=customer,
|
|
invoice_number=invoice_number,
|
|
total_amount=total_amount,
|
|
paid_amount=paid_amount,
|
|
balance_due=float(total_amount) - float(paid_amount),
|
|
discount=discount,
|
|
payment_type=payment_type,
|
|
due_date=due_date if due_date else None,
|
|
notes=notes
|
|
)
|
|
|
|
# Set status based on payments
|
|
if float(paid_amount) >= float(total_amount):
|
|
sale.status = 'paid'
|
|
elif float(paid_amount) > 0:
|
|
sale.status = 'partial'
|
|
else:
|
|
sale.status = 'unpaid'
|
|
sale.save()
|
|
|
|
# Record initial payment if any
|
|
if float(paid_amount) > 0:
|
|
SalePayment.objects.create(
|
|
sale=sale,
|
|
amount=paid_amount,
|
|
payment_method=payment_type.capitalize(),
|
|
notes=_("Initial payment")
|
|
)
|
|
|
|
for item in items:
|
|
product = Product.objects.get(id=item['id'])
|
|
SaleItem.objects.create(
|
|
sale=sale,
|
|
product=product,
|
|
quantity=item['quantity'],
|
|
unit_price=item['price'],
|
|
line_total=item['line_total']
|
|
)
|
|
product.stock_quantity -= int(item['quantity'])
|
|
product.save()
|
|
|
|
settings = SystemSetting.objects.first()
|
|
if not settings:
|
|
settings = SystemSetting.objects.create()
|
|
|
|
return JsonResponse({
|
|
'success': True,
|
|
'sale_id': sale.id,
|
|
'business': {
|
|
'name': settings.business_name,
|
|
'address': settings.address,
|
|
'phone': settings.phone,
|
|
'email': settings.email,
|
|
'currency': settings.currency_symbol,
|
|
'vat_number': settings.vat_number,
|
|
'registration_number': settings.registration_number,
|
|
'logo_url': settings.logo.url if settings.logo else None
|
|
},
|
|
'sale': {
|
|
'id': sale.id,
|
|
'invoice_number': sale.invoice_number,
|
|
'created_at': sale.created_at.strftime("%Y-%m-%d %H:%M"),
|
|
'total': float(sale.total_amount),
|
|
'paid': float(sale.paid_amount),
|
|
'balance': float(sale.balance_due),
|
|
'items': [
|
|
{
|
|
'name_en': si.product.name_en,
|
|
'name_ar': si.product.name_ar,
|
|
'qty': si.quantity,
|
|
'price': float(si.unit_price),
|
|
'total': float(si.line_total)
|
|
} for si in sale.items.all()
|
|
]
|
|
}
|
|
})
|
|
except Exception as e:
|
|
return JsonResponse({'success': False, 'error': str(e)}, status=400)
|
|
return JsonResponse({'success': False, 'error': 'Invalid request'}, status=405)
|
|
|
|
def add_sale_payment(request, pk):
|
|
sale = get_object_or_404(Sale, pk=pk)
|
|
if request.method == 'POST':
|
|
amount = request.POST.get('amount')
|
|
payment_date = request.POST.get('payment_date', timezone.now().date())
|
|
payment_method = request.POST.get('payment_method', 'Cash')
|
|
notes = request.POST.get('notes', '')
|
|
|
|
SalePayment.objects.create(
|
|
sale=sale,
|
|
amount=amount,
|
|
payment_date=payment_date,
|
|
payment_method=payment_method,
|
|
notes=notes
|
|
)
|
|
sale.update_balance()
|
|
messages.success(request, _("Payment added successfully!"))
|
|
return redirect('invoices')
|
|
|
|
def delete_sale(request, pk):
|
|
sale = get_object_or_404(Sale, pk=pk)
|
|
for item in sale.items.all():
|
|
item.product.stock_quantity += item.quantity
|
|
item.product.save()
|
|
sale.delete()
|
|
messages.success(request, _("Sale deleted successfully!"))
|
|
return redirect('invoices')
|
|
|
|
# --- Quotation Views ---
|
|
|
|
def quotations(request):
|
|
quotations_list = Quotation.objects.all().order_by('-created_at')
|
|
customers = Customer.objects.all()
|
|
return render(request, 'core/quotations.html', {'quotations': quotations_list, 'customers': customers})
|
|
|
|
def quotation_create(request):
|
|
products = Product.objects.filter(is_active=True)
|
|
customers = Customer.objects.all()
|
|
return render(request, 'core/quotation_create.html', {'products': products, 'customers': customers})
|
|
|
|
def quotation_detail(request, pk):
|
|
quotation = get_object_or_404(Quotation, pk=pk)
|
|
settings = SystemSetting.objects.first()
|
|
return render(request, 'core/quotation_detail.html', {'quotation': quotation, 'settings': settings})
|
|
|
|
@csrf_exempt
|
|
def create_quotation_api(request):
|
|
if request.method == 'POST':
|
|
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', '')
|
|
|
|
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
|
|
)
|
|
|
|
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']
|
|
)
|
|
|
|
return JsonResponse({'success': True, 'quotation_id': quotation.id})
|
|
except Exception as e:
|
|
return JsonResponse({'success': False, 'error': str(e)}, status=400)
|
|
return JsonResponse({'success': False, 'error': 'Invalid request'}, status=405)
|
|
|
|
def convert_quotation_to_invoice(request, pk):
|
|
quotation = get_object_or_404(Quotation, pk=pk)
|
|
if quotation.status == 'converted':
|
|
messages.warning(request, _("This quotation has already been converted to an invoice."))
|
|
return redirect('invoices')
|
|
|
|
# Create Sale from Quotation
|
|
sale = Sale.objects.create(
|
|
customer=quotation.customer,
|
|
quotation=quotation,
|
|
total_amount=quotation.total_amount,
|
|
discount=quotation.discount,
|
|
balance_due=quotation.total_amount,
|
|
payment_type='cash',
|
|
status='unpaid',
|
|
notes=quotation.notes
|
|
)
|
|
|
|
# Create SaleItems and Update Stock
|
|
for item in quotation.items.all():
|
|
SaleItem.objects.create(
|
|
sale=sale,
|
|
product=item.product,
|
|
quantity=item.quantity,
|
|
unit_price=item.unit_price,
|
|
line_total=item.line_total
|
|
)
|
|
# Deduct Stock
|
|
item.product.stock_quantity -= item.quantity
|
|
item.product.save()
|
|
|
|
# Update Quotation Status
|
|
quotation.status = 'converted'
|
|
quotation.save()
|
|
|
|
messages.success(request, _("Quotation converted to Invoice successfully!"))
|
|
return redirect('invoice_detail', pk=sale.pk)
|
|
|
|
def delete_quotation(request, pk):
|
|
quotation = get_object_or_404(Quotation, pk=pk)
|
|
quotation.delete()
|
|
messages.success(request, _("Quotation deleted successfully!"))
|
|
return redirect('quotations')
|
|
|
|
# --- Sale Return Views ---
|
|
|
|
def sales_returns(request):
|
|
returns = SaleReturn.objects.all().order_by('-created_at')
|
|
return render(request, 'core/sales_returns.html', {'returns': returns})
|
|
|
|
def sale_return_create(request):
|
|
products = Product.objects.filter(is_active=True)
|
|
customers = Customer.objects.all()
|
|
sales = Sale.objects.all().order_by('-created_at')
|
|
return render(request, 'core/sale_return_create.html', {
|
|
'products': products,
|
|
'customers': customers,
|
|
'sales': sales
|
|
})
|
|
|
|
def sale_return_detail(request, pk):
|
|
sale_return = get_object_or_404(SaleReturn, pk=pk)
|
|
settings = SystemSetting.objects.first()
|
|
return render(request, 'core/sale_return_detail.html', {'sale_return': sale_return, 'settings': settings})
|
|
|
|
@csrf_exempt
|
|
def create_sale_return_api(request):
|
|
if request.method == 'POST':
|
|
try:
|
|
data = json.loads(request.body)
|
|
sale_id = data.get('sale_id')
|
|
customer_id = data.get('customer_id')
|
|
return_number = data.get('return_number', '')
|
|
items = data.get('items', [])
|
|
total_amount = data.get('total_amount', 0)
|
|
notes = data.get('notes', '')
|
|
|
|
customer = None
|
|
if customer_id:
|
|
customer = Customer.objects.get(id=customer_id)
|
|
|
|
sale = None
|
|
if sale_id:
|
|
sale = Sale.objects.get(id=sale_id)
|
|
|
|
sale_return = SaleReturn.objects.create(
|
|
sale=sale,
|
|
customer=customer,
|
|
return_number=return_number,
|
|
total_amount=total_amount,
|
|
notes=notes
|
|
)
|
|
|
|
for item in items:
|
|
product = Product.objects.get(id=item['id'])
|
|
SaleReturnItem.objects.create(
|
|
sale_return=sale_return,
|
|
product=product,
|
|
quantity=item['quantity'],
|
|
unit_price=item['price'],
|
|
line_total=item['line_total']
|
|
)
|
|
# Increase Stock for Sales Return
|
|
product.stock_quantity += int(item['quantity'])
|
|
product.save()
|
|
|
|
return JsonResponse({'success': True, 'return_id': sale_return.id})
|
|
except Exception as e:
|
|
return JsonResponse({'success': False, 'error': str(e)}, status=400)
|
|
return JsonResponse({'success': False, 'error': 'Invalid request'}, status=405)
|
|
|
|
def delete_sale_return(request, pk):
|
|
sale_return = get_object_or_404(SaleReturn, pk=pk)
|
|
for item in sale_return.items.all():
|
|
item.product.stock_quantity -= item.quantity
|
|
item.product.save()
|
|
sale_return.delete()
|
|
messages.success(request, _("Sale return deleted successfully!"))
|
|
return redirect('sales_returns')
|
|
|
|
|
|
# --- Purchase Return Views ---
|
|
|
|
def purchase_returns(request):
|
|
returns = PurchaseReturn.objects.all().order_by('-created_at')
|
|
return render(request, 'core/purchase_returns.html', {'returns': returns})
|
|
|
|
def purchase_return_create(request):
|
|
products = Product.objects.filter(is_active=True)
|
|
suppliers = Supplier.objects.all()
|
|
purchases = Purchase.objects.all().order_by('-created_at')
|
|
return render(request, 'core/purchase_return_create.html', {
|
|
'products': products,
|
|
'suppliers': suppliers,
|
|
'purchases': purchases
|
|
})
|
|
|
|
def purchase_return_detail(request, pk):
|
|
purchase_return = get_object_or_404(PurchaseReturn, pk=pk)
|
|
settings = SystemSetting.objects.first()
|
|
return render(request, 'core/purchase_return_detail.html', {'purchase_return': purchase_return, 'settings': settings})
|
|
|
|
@csrf_exempt
|
|
def create_purchase_return_api(request):
|
|
if request.method == 'POST':
|
|
try:
|
|
data = json.loads(request.body)
|
|
purchase_id = data.get('purchase_id')
|
|
supplier_id = data.get('supplier_id')
|
|
return_number = data.get('return_number', '')
|
|
items = data.get('items', [])
|
|
total_amount = data.get('total_amount', 0)
|
|
notes = data.get('notes', '')
|
|
|
|
supplier = None
|
|
if supplier_id:
|
|
supplier = Supplier.objects.get(id=supplier_id)
|
|
|
|
purchase = None
|
|
if purchase_id:
|
|
purchase = Purchase.objects.get(id=purchase_id)
|
|
|
|
purchase_return = PurchaseReturn.objects.create(
|
|
purchase=purchase,
|
|
supplier=supplier,
|
|
return_number=return_number,
|
|
total_amount=total_amount,
|
|
notes=notes
|
|
)
|
|
|
|
for item in items:
|
|
product = Product.objects.get(id=item['id'])
|
|
PurchaseReturnItem.objects.create(
|
|
purchase_return=purchase_return,
|
|
product=product,
|
|
quantity=item['quantity'],
|
|
cost_price=item['price'],
|
|
line_total=item['line_total']
|
|
)
|
|
# Decrease Stock for Purchase Return
|
|
product.stock_quantity -= int(item['quantity'])
|
|
product.save()
|
|
|
|
return JsonResponse({'success': True, 'return_id': purchase_return.id})
|
|
except Exception as e:
|
|
return JsonResponse({'success': False, 'error': str(e)}, status=400)
|
|
return JsonResponse({'success': False, 'error': 'Invalid request'}, status=405)
|
|
|
|
def delete_purchase_return(request, pk):
|
|
purchase_return = get_object_or_404(PurchaseReturn, pk=pk)
|
|
for item in purchase_return.items.all():
|
|
item.product.stock_quantity += item.quantity
|
|
item.product.save()
|
|
purchase_return.delete()
|
|
messages.success(request, _("Purchase return deleted successfully!"))
|
|
return redirect('purchase_returns')
|
|
|
|
# --- Other Management Views ---
|
|
|
|
def reports(request):
|
|
"""
|
|
Smart Reports View
|
|
"""
|
|
# Monthly Revenue
|
|
monthly_sales = Sale.objects.annotate(month=TruncMonth('created_at')) \
|
|
.values('month') \
|
|
.annotate(total=Sum('total_amount')) \
|
|
.order_by('-month')[:12]
|
|
|
|
# Top Selling Products
|
|
top_products = SaleItem.objects.values('product__name_en', 'product__name_ar') \
|
|
.annotate(total_qty=Sum('quantity'), revenue=Sum('line_total')) \
|
|
.order_by('-total_qty')[:5]
|
|
|
|
context = {
|
|
'monthly_sales': monthly_sales,
|
|
'top_products': top_products,
|
|
}
|
|
return render(request, 'core/reports.html', context)
|
|
|
|
def settings_view(request):
|
|
"""
|
|
Smart Admin Settings View
|
|
"""
|
|
settings = SystemSetting.objects.first()
|
|
if not settings:
|
|
settings = SystemSetting.objects.create()
|
|
|
|
if request.method == 'POST':
|
|
settings.business_name = request.POST.get('business_name')
|
|
settings.address = request.POST.get('address')
|
|
settings.phone = request.POST.get('phone')
|
|
settings.email = request.POST.get('email')
|
|
settings.currency_symbol = request.POST.get('currency_symbol')
|
|
settings.tax_rate = request.POST.get('tax_rate')
|
|
settings.vat_number = request.POST.get('vat_number')
|
|
settings.registration_number = request.POST.get('registration_number')
|
|
|
|
if 'logo' in request.FILES:
|
|
settings.logo = request.FILES['logo']
|
|
|
|
settings.save()
|
|
messages.success(request, "Settings updated successfully!")
|
|
return redirect('settings')
|
|
|
|
return render(request, 'core/settings.html', {'settings': settings})
|
|
|
|
def add_customer(request):
|
|
if request.method == 'POST':
|
|
name = request.POST.get('name')
|
|
phone = request.POST.get('phone')
|
|
email = request.POST.get('email')
|
|
address = request.POST.get('address')
|
|
Customer.objects.create(name=name, phone=phone, email=email, address=address)
|
|
messages.success(request, "Customer added successfully!")
|
|
return redirect('customers')
|
|
|
|
def edit_customer(request, pk):
|
|
customer = get_object_or_404(Customer, pk=pk)
|
|
if request.method == 'POST':
|
|
customer.name = request.POST.get('name')
|
|
customer.phone = request.POST.get('phone')
|
|
customer.email = request.POST.get('email')
|
|
customer.address = request.POST.get('address')
|
|
customer.save()
|
|
messages.success(request, "Customer updated successfully!")
|
|
return redirect('customers')
|
|
|
|
def delete_customer(request, pk):
|
|
customer = get_object_or_404(Customer, pk=pk)
|
|
customer.delete()
|
|
messages.success(request, "Customer deleted successfully!")
|
|
return redirect('customers')
|
|
|
|
def add_supplier(request):
|
|
if request.method == 'POST':
|
|
name = request.POST.get('name')
|
|
contact_person = request.POST.get('contact_person')
|
|
phone = request.POST.get('phone')
|
|
Supplier.objects.create(name=name, contact_person=contact_person, phone=phone)
|
|
messages.success(request, "Supplier added successfully!")
|
|
return redirect('suppliers')
|
|
|
|
def edit_supplier(request, pk):
|
|
supplier = get_object_or_404(Supplier, pk=pk)
|
|
if request.method == 'POST':
|
|
supplier.name = request.POST.get('name')
|
|
supplier.contact_person = request.POST.get('contact_person')
|
|
supplier.phone = request.POST.get('phone')
|
|
supplier.save()
|
|
messages.success(request, "Supplier updated successfully!")
|
|
return redirect('suppliers')
|
|
|
|
def delete_supplier(request, pk):
|
|
supplier = get_object_or_404(Supplier, pk=pk)
|
|
supplier.delete()
|
|
messages.success(request, "Supplier deleted successfully!")
|
|
return redirect('suppliers')
|
|
|
|
def add_product(request):
|
|
if request.method == 'POST':
|
|
name_en = request.POST.get('name_en')
|
|
name_ar = request.POST.get('name_ar')
|
|
category_id = request.POST.get('category')
|
|
unit_id = request.POST.get('unit')
|
|
supplier_id = request.POST.get('supplier')
|
|
sku = request.POST.get('sku')
|
|
cost_price = request.POST.get('cost_price', 0)
|
|
price = request.POST.get('price', 0)
|
|
vat = request.POST.get('vat', 0)
|
|
opening_stock = request.POST.get('opening_stock', 0)
|
|
stock_quantity = request.POST.get('stock_quantity', 0)
|
|
is_active = request.POST.get('is_active') == 'on'
|
|
|
|
category = get_object_or_404(Category, id=category_id)
|
|
unit = get_object_or_404(Unit, id=unit_id) if unit_id else None
|
|
supplier = get_object_or_404(Supplier, id=supplier_id) if supplier_id else None
|
|
|
|
product = Product.objects.create(
|
|
name_en=name_en,
|
|
name_ar=name_ar,
|
|
category=category,
|
|
unit=unit,
|
|
supplier=supplier,
|
|
sku=sku,
|
|
cost_price=cost_price,
|
|
price=price,
|
|
vat=vat,
|
|
opening_stock=opening_stock,
|
|
stock_quantity=stock_quantity,
|
|
is_active=is_active
|
|
)
|
|
|
|
if 'image' in request.FILES:
|
|
product.image = request.FILES['image']
|
|
product.save()
|
|
|
|
messages.success(request, "Product added successfully!")
|
|
return redirect('inventory')
|
|
|
|
def edit_product(request, pk):
|
|
product = get_object_or_404(Product, pk=pk)
|
|
if request.method == 'POST':
|
|
product.name_en = request.POST.get('name_en')
|
|
product.name_ar = request.POST.get('name_ar')
|
|
product.sku = request.POST.get('sku')
|
|
product.category = get_object_or_404(Category, id=request.POST.get('category'))
|
|
|
|
unit_id = request.POST.get('unit')
|
|
product.unit = get_object_or_404(Unit, id=unit_id) if unit_id else None
|
|
|
|
supplier_id = request.POST.get('supplier')
|
|
product.supplier = get_object_or_404(Supplier, id=supplier_id) if supplier_id else None
|
|
|
|
product.cost_price = request.POST.get('cost_price', 0)
|
|
product.price = request.POST.get('price', 0)
|
|
product.vat = request.POST.get('vat', 0)
|
|
product.opening_stock = request.POST.get('opening_stock', 0)
|
|
product.stock_quantity = request.POST.get('stock_quantity', 0)
|
|
product.is_active = request.POST.get('is_active') == 'on'
|
|
|
|
if 'image' in request.FILES:
|
|
product.image = request.FILES['image']
|
|
|
|
product.save()
|
|
messages.success(request, "Product updated successfully!")
|
|
return redirect('inventory')
|
|
return redirect('inventory')
|
|
|
|
def delete_product(request, pk):
|
|
product = get_object_or_404(Product, pk=pk)
|
|
product.delete()
|
|
messages.success(request, "Product deleted successfully!")
|
|
return redirect('inventory')
|
|
|
|
def add_category(request):
|
|
if request.method == 'POST':
|
|
name_en = request.POST.get('name_en')
|
|
name_ar = request.POST.get('name_ar')
|
|
slug = slugify(name_en)
|
|
Category.objects.create(name_en=name_en, name_ar=name_ar, slug=slug)
|
|
messages.success(request, "Category added successfully!")
|
|
return redirect('inventory')
|
|
|
|
def edit_category(request, pk):
|
|
category = get_object_or_404(Category, pk=pk)
|
|
if request.method == 'POST':
|
|
category.name_en = request.POST.get('name_en')
|
|
category.name_ar = request.POST.get('name_ar')
|
|
category.slug = slugify(category.name_en)
|
|
category.save()
|
|
messages.success(request, "Category updated successfully!")
|
|
return redirect('inventory')
|
|
|
|
def delete_category(request, pk):
|
|
category = get_object_or_404(Category, pk=pk)
|
|
category.delete()
|
|
messages.success(request, "Category deleted successfully!")
|
|
return redirect('inventory')
|
|
|
|
def add_unit(request):
|
|
if request.method == 'POST':
|
|
name_en = request.POST.get('name_en')
|
|
name_ar = request.POST.get('name_ar')
|
|
short_name = request.POST.get('short_name')
|
|
Unit.objects.create(name_en=name_en, name_ar=name_ar, short_name=short_name)
|
|
messages.success(request, "Unit added successfully!")
|
|
return redirect('inventory')
|
|
|
|
def edit_unit(request, pk):
|
|
unit = get_object_or_404(Unit, pk=pk)
|
|
if request.method == 'POST':
|
|
unit.name_en = request.POST.get('name_en')
|
|
unit.name_ar = request.POST.get('name_ar')
|
|
unit.short_name = request.POST.get('short_name')
|
|
unit.save()
|
|
messages.success(request, "Unit updated successfully!")
|
|
return redirect('inventory')
|
|
|
|
def delete_unit(request, pk):
|
|
unit = get_object_or_404(Unit, pk=pk)
|
|
unit.delete()
|
|
messages.success(request, "Unit deleted successfully!")
|
|
return redirect('inventory')
|
|
|
|
def barcode_labels(request):
|
|
products = Product.objects.filter(is_active=True).order_by('name_en')
|
|
context = {'products': products}
|
|
return render(request, 'core/barcode_labels.html', context)
|