207 lines
7.2 KiB
Python
207 lines
7.2 KiB
Python
import os
|
|
|
|
file_path = 'core/views.py'
|
|
|
|
# New Implementations
|
|
edit_invoice_code = """
|
|
@login_required
|
|
def edit_invoice(request, pk):
|
|
sale = get_object_or_404(Sale, pk=pk)
|
|
customers = Customer.objects.all()
|
|
products = Product.objects.filter(is_active=True).select_related('category')
|
|
payment_methods = PaymentMethod.objects.filter(is_active=True)
|
|
site_settings = SystemSetting.objects.first()
|
|
|
|
decimal_places = 2
|
|
if site_settings:
|
|
decimal_places = site_settings.decimal_places
|
|
|
|
# Serialize items for Vue
|
|
cart_items = []
|
|
for item in sale.items.all().select_related('product'):
|
|
cart_items.append({
|
|
'id': item.product.id,
|
|
'name_en': item.product.name_en,
|
|
'name_ar': item.product.name_ar,
|
|
'sku': item.product.sku,
|
|
'price': float(item.unit_price),
|
|
'quantity': float(item.quantity),
|
|
'stock': float(item.product.stock_quantity)
|
|
})
|
|
|
|
cart_json = json.dumps(cart_items)
|
|
|
|
# Get first payment method if exists
|
|
payment_method_id = ""
|
|
first_payment = sale.payments.first()
|
|
if first_payment and first_payment.payment_method:
|
|
payment_method_id = first_payment.payment_method.id
|
|
|
|
context = {
|
|
'sale': sale,
|
|
'customers': customers,
|
|
'products': products,
|
|
'payment_methods': payment_methods,
|
|
'site_settings': site_settings,
|
|
'decimal_places': decimal_places,
|
|
'cart_json': cart_json,
|
|
'payment_method_id': payment_method_id
|
|
}
|
|
return render(request, 'core/invoice_edit.html', context)
|
|
"""
|
|
|
|
sale_receipt_code = """
|
|
@login_required
|
|
def sale_receipt(request, pk):
|
|
sale = get_object_or_404(Sale, pk=pk)
|
|
settings = SystemSetting.objects.first()
|
|
return render(request, 'core/sale_receipt.html', {
|
|
'sale': sale,
|
|
'settings': settings
|
|
})
|
|
"""
|
|
|
|
update_sale_api_code = """
|
|
@csrf_exempt
|
|
def update_sale_api(request, pk):
|
|
if request.method != 'POST':
|
|
return JsonResponse({'success': False, 'error': 'Invalid request method'})
|
|
|
|
try:
|
|
sale = Sale.objects.get(pk=pk)
|
|
data = json.loads(request.body)
|
|
|
|
customer_id = data.get('customer_id')
|
|
items = data.get('items', [])
|
|
discount = decimal.Decimal(str(data.get('discount', 0)))
|
|
paid_amount = decimal.Decimal(str(data.get('paid_amount', 0)))
|
|
payment_type = data.get('payment_type', 'cash')
|
|
payment_method_id = data.get('payment_method_id')
|
|
due_date = data.get('due_date')
|
|
notes = data.get('notes', '')
|
|
invoice_number = data.get('invoice_number')
|
|
|
|
if not items:
|
|
return JsonResponse({'success': False, 'error': 'No items in sale'})
|
|
|
|
with transaction.atomic():
|
|
# 1. Revert Stock
|
|
for item in sale.items.all():
|
|
product = item.product
|
|
product.stock_quantity += item.quantity
|
|
product.save()
|
|
|
|
# 2. Delete existing items
|
|
sale.items.all().delete()
|
|
|
|
# 3. Update Sale Details
|
|
if customer_id:
|
|
sale.customer_id = customer_id
|
|
else:
|
|
sale.customer = None
|
|
|
|
sale.discount = discount
|
|
sale.notes = notes
|
|
if invoice_number:
|
|
sale.invoice_number = invoice_number
|
|
|
|
if due_date:
|
|
sale.due_date = due_date
|
|
else:
|
|
sale.due_date = None
|
|
|
|
# 4. Create New Items and Deduct Stock
|
|
subtotal = decimal.Decimal(0)
|
|
|
|
for item_data in items:
|
|
product = Product.objects.get(pk=item_data['id'])
|
|
quantity = decimal.Decimal(str(item_data['quantity']))
|
|
price = decimal.Decimal(str(item_data['price']))
|
|
|
|
# Deduct stock
|
|
product.stock_quantity -= quantity
|
|
product.save()
|
|
|
|
line_total = price * quantity
|
|
subtotal += line_total
|
|
|
|
SaleItem.objects.create(
|
|
sale=sale,
|
|
product=product,
|
|
quantity=quantity,
|
|
unit_price=price,
|
|
line_total=line_total
|
|
)
|
|
|
|
sale.subtotal = subtotal
|
|
sale.total_amount = subtotal - discount
|
|
|
|
# 5. Handle Payments
|
|
if payment_type == 'credit':
|
|
sale.status = 'unpaid'
|
|
sale.paid_amount = 0
|
|
sale.balance_due = sale.total_amount
|
|
sale.payments.all().delete()
|
|
|
|
elif payment_type == 'cash':
|
|
sale.status = 'paid'
|
|
sale.paid_amount = sale.total_amount
|
|
sale.balance_due = 0
|
|
|
|
sale.payments.all().delete()
|
|
SalePayment.objects.create(
|
|
sale=sale,
|
|
amount=sale.total_amount,
|
|
payment_method_id=payment_method_id if payment_method_id else None,
|
|
payment_date=timezone.now().date(),
|
|
notes='Full Payment (Edit)'
|
|
)
|
|
|
|
elif payment_type == 'partial':
|
|
sale.paid_amount = paid_amount
|
|
sale.balance_due = sale.total_amount - paid_amount
|
|
if sale.balance_due <= 0:
|
|
sale.status = 'paid'
|
|
sale.balance_due = 0
|
|
else:
|
|
sale.status = 'partial'
|
|
|
|
sale.payments.all().delete()
|
|
SalePayment.objects.create(
|
|
sale=sale,
|
|
amount=paid_amount,
|
|
payment_method_id=payment_method_id if payment_method_id else None,
|
|
payment_date=timezone.now().date(),
|
|
notes='Partial Payment (Edit)'
|
|
)
|
|
|
|
sale.save()
|
|
|
|
return JsonResponse({'success': True, 'sale_id': sale.id})
|
|
|
|
except Sale.DoesNotExist:
|
|
return JsonResponse({'success': False, 'error': 'Sale not found'})
|
|
except Product.DoesNotExist:
|
|
return JsonResponse({'success': False, 'error': 'Product not found'})
|
|
except Exception as e:
|
|
return JsonResponse({'success': False, 'error': str(e)})
|
|
"""
|
|
|
|
with open(file_path, 'r') as f:
|
|
content = f.read()
|
|
|
|
# Replace stubs
|
|
content = content.replace("def sale_receipt(request, pk): return redirect('invoices')", sale_receipt_code)
|
|
content = content.replace("def edit_invoice(request, pk): return redirect('invoices')", edit_invoice_code)
|
|
content = content.replace("@csrf_exempt\ndef update_sale_api(request, pk): return JsonResponse({'success': False})", update_sale_api_code)
|
|
|
|
# Handle potential whitespace variations if single-line replace fails
|
|
if "def edit_invoice(request, pk): return redirect('invoices')" in content: # Check if it persisted
|
|
pass # worked
|
|
else:
|
|
# Fallback for manual check if needed (it should work given exact match from read_file)
|
|
pass
|
|
|
|
with open(file_path, 'w') as f:
|
|
f.write(content)
|