Autosave: 20260210-040222
This commit is contained in:
parent
441b04ab78
commit
b2602b999f
Binary file not shown.
149
core/views.py
149
core/views.py
@ -927,8 +927,16 @@ def lpo_delete(request, pk):
|
|||||||
# --- Sales Returns ---
|
# --- Sales Returns ---
|
||||||
@login_required
|
@login_required
|
||||||
def sales_returns(request): return render(request, 'core/sales_returns.html', {'returns': SaleReturn.objects.all()})
|
def sales_returns(request): return render(request, 'core/sales_returns.html', {'returns': SaleReturn.objects.all()})
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def sale_return_create(request): return render(request, 'core/sale_return_create.html')
|
def sale_return_create(request):
|
||||||
|
customers = Customer.objects.all()
|
||||||
|
products = Product.objects.filter(is_active=True)
|
||||||
|
return render(request, 'core/sale_return_create.html', {
|
||||||
|
'customers': customers,
|
||||||
|
'products': products
|
||||||
|
})
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def sale_return_detail(request, pk):
|
def sale_return_detail(request, pk):
|
||||||
sale_return = get_object_or_404(SaleReturn, pk=pk)
|
sale_return = get_object_or_404(SaleReturn, pk=pk)
|
||||||
@ -937,16 +945,75 @@ def sale_return_detail(request, pk):
|
|||||||
'sale_return': sale_return,
|
'sale_return': sale_return,
|
||||||
'settings': settings
|
'settings': settings
|
||||||
})
|
})
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def delete_sale_return(request, pk): return redirect('sales_returns')
|
def delete_sale_return(request, pk): return redirect('sales_returns')
|
||||||
|
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
def create_sale_return_api(request): return JsonResponse({'success': True})
|
@login_required
|
||||||
|
def create_sale_return_api(request):
|
||||||
|
if request.method != 'POST':
|
||||||
|
return JsonResponse({'success': False, 'error': 'Invalid method'})
|
||||||
|
try:
|
||||||
|
data = json.loads(request.body)
|
||||||
|
customer_id = data.get('customer_id')
|
||||||
|
items = data.get('items', [])
|
||||||
|
|
||||||
|
customer = None
|
||||||
|
if customer_id:
|
||||||
|
customer = get_object_or_404(Customer, pk=customer_id)
|
||||||
|
|
||||||
|
with transaction.atomic():
|
||||||
|
sale_return = SaleReturn.objects.create(
|
||||||
|
customer=customer,
|
||||||
|
created_by=request.user,
|
||||||
|
total_amount=0,
|
||||||
|
return_number=f"SR-{int(timezone.now().timestamp())}",
|
||||||
|
notes=data.get('notes', '')
|
||||||
|
)
|
||||||
|
|
||||||
|
total = decimal.Decimal(0)
|
||||||
|
for item in items:
|
||||||
|
qty = decimal.Decimal(str(item.get('quantity', 0)))
|
||||||
|
price = decimal.Decimal(str(item.get('price', 0)))
|
||||||
|
line_total = qty * price
|
||||||
|
|
||||||
|
SaleReturnItem.objects.create(
|
||||||
|
sale_return=sale_return,
|
||||||
|
product_id=item['id'],
|
||||||
|
quantity=qty,
|
||||||
|
unit_price=price,
|
||||||
|
line_total=line_total
|
||||||
|
)
|
||||||
|
|
||||||
|
# Update stock: Returns from customer mean stock comes IN
|
||||||
|
product = Product.objects.get(pk=item['id'])
|
||||||
|
product.stock_quantity += qty
|
||||||
|
product.save()
|
||||||
|
|
||||||
|
total += line_total
|
||||||
|
|
||||||
|
sale_return.total_amount = total
|
||||||
|
sale_return.save()
|
||||||
|
|
||||||
|
return JsonResponse({'success': True, 'id': sale_return.id})
|
||||||
|
except Exception as e:
|
||||||
|
logger.exception("Error creating sale return")
|
||||||
|
return JsonResponse({'success': False, 'error': str(e)})
|
||||||
|
|
||||||
# --- Purchase Returns ---
|
# --- Purchase Returns ---
|
||||||
@login_required
|
@login_required
|
||||||
def purchase_returns(request): return render(request, 'core/purchase_returns.html', {'returns': PurchaseReturn.objects.all()})
|
def purchase_returns(request): return render(request, 'core/purchase_returns.html', {'returns': PurchaseReturn.objects.all()})
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def purchase_return_create(request): return render(request, 'core/purchase_return_create.html')
|
def purchase_return_create(request):
|
||||||
|
suppliers = Supplier.objects.filter(is_active=True)
|
||||||
|
products = Product.objects.filter(is_active=True)
|
||||||
|
return render(request, 'core/purchase_return_create.html', {
|
||||||
|
'suppliers': suppliers,
|
||||||
|
'products': products
|
||||||
|
})
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def purchase_return_detail(request, pk):
|
def purchase_return_detail(request, pk):
|
||||||
purchase_return = get_object_or_404(PurchaseReturn, pk=pk)
|
purchase_return = get_object_or_404(PurchaseReturn, pk=pk)
|
||||||
@ -955,10 +1022,59 @@ def purchase_return_detail(request, pk):
|
|||||||
'purchase_return': purchase_return,
|
'purchase_return': purchase_return,
|
||||||
'settings': settings
|
'settings': settings
|
||||||
})
|
})
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def delete_purchase_return(request, pk): return redirect('purchase_returns')
|
def delete_purchase_return(request, pk): return redirect('purchase_returns')
|
||||||
|
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
def create_purchase_return_api(request): return JsonResponse({'success': True})
|
@login_required
|
||||||
|
def create_purchase_return_api(request):
|
||||||
|
if request.method != 'POST':
|
||||||
|
return JsonResponse({'success': False, 'error': 'Invalid method'})
|
||||||
|
try:
|
||||||
|
data = json.loads(request.body)
|
||||||
|
supplier_id = data.get('supplier_id')
|
||||||
|
items = data.get('items', [])
|
||||||
|
|
||||||
|
supplier = get_object_or_404(Supplier, pk=supplier_id)
|
||||||
|
|
||||||
|
with transaction.atomic():
|
||||||
|
purchase_return = PurchaseReturn.objects.create(
|
||||||
|
supplier=supplier,
|
||||||
|
created_by=request.user,
|
||||||
|
total_amount=0,
|
||||||
|
return_number=f"PR-{int(timezone.now().timestamp())}",
|
||||||
|
notes=data.get('notes', '')
|
||||||
|
)
|
||||||
|
|
||||||
|
total = decimal.Decimal(0)
|
||||||
|
for item in items:
|
||||||
|
qty = decimal.Decimal(str(item.get('quantity', 0)))
|
||||||
|
cost = decimal.Decimal(str(item.get('price', 0))) # Frontend sends 'price'
|
||||||
|
line_total = qty * cost
|
||||||
|
|
||||||
|
PurchaseReturnItem.objects.create(
|
||||||
|
purchase_return=purchase_return,
|
||||||
|
product_id=item['id'],
|
||||||
|
quantity=qty,
|
||||||
|
cost_price=cost,
|
||||||
|
line_total=line_total
|
||||||
|
)
|
||||||
|
|
||||||
|
# Update stock: Returns to supplier mean stock goes OUT
|
||||||
|
product = Product.objects.get(pk=item['id'])
|
||||||
|
product.stock_quantity -= qty
|
||||||
|
product.save()
|
||||||
|
|
||||||
|
total += line_total
|
||||||
|
|
||||||
|
purchase_return.total_amount = total
|
||||||
|
purchase_return.save()
|
||||||
|
|
||||||
|
return JsonResponse({'success': True, 'id': purchase_return.id})
|
||||||
|
except Exception as e:
|
||||||
|
logger.exception("Error creating purchase return")
|
||||||
|
return JsonResponse({'success': False, 'error': str(e)})
|
||||||
|
|
||||||
# --- Other Stubs ---
|
# --- Other Stubs ---
|
||||||
@login_required
|
@login_required
|
||||||
@ -1033,13 +1149,34 @@ def add_sale_payment(request, pk):
|
|||||||
return redirect('invoices')
|
return redirect('invoices')
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def sale_receipt(request, pk): return render(request, 'core/sale_receipt.html')
|
def sale_receipt(request, pk):
|
||||||
|
sale = get_object_or_404(Sale, pk=pk)
|
||||||
|
settings = SystemSetting.objects.first()
|
||||||
|
amount_in_words = number_to_words_en(sale.total_amount)
|
||||||
|
return render(request, 'core/sale_receipt.html', {
|
||||||
|
'sale': sale,
|
||||||
|
'settings': settings,
|
||||||
|
'amount_in_words': amount_in_words
|
||||||
|
})
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def edit_invoice(request, pk): return redirect('invoices')
|
def edit_invoice(request, pk): return redirect('invoices')
|
||||||
@login_required
|
@login_required
|
||||||
def customer_payments(request): return render(request, 'core/customer_payments.html')
|
def customer_payments(request): return render(request, 'core/customer_payments.html')
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def customer_payment_receipt(request, pk): return render(request, 'core/payment_receipt.html')
|
def customer_payment_receipt(request, pk):
|
||||||
|
payment = get_object_or_404(SalePayment, pk=pk)
|
||||||
|
sale = payment.sale
|
||||||
|
settings = SystemSetting.objects.first()
|
||||||
|
amount_in_words = number_to_words_en(payment.amount)
|
||||||
|
return render(request, 'core/payment_receipt.html', {
|
||||||
|
'payment': payment,
|
||||||
|
'sale': sale,
|
||||||
|
'settings': settings,
|
||||||
|
'amount_in_words': amount_in_words
|
||||||
|
})
|
||||||
|
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
def hold_sale_api(request): return JsonResponse({'success': True})
|
def hold_sale_api(request): return JsonResponse({'success': True})
|
||||||
@csrf_exempt
|
@csrf_exempt
|
||||||
|
|||||||
17
patch_returns_setup.py
Normal file
17
patch_returns_setup.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
from core.views import (
|
||||||
|
purchase_return_create, sale_return_create,
|
||||||
|
create_sale_return_api, create_purchase_return_api,
|
||||||
|
Supplier, Product, Customer, SaleReturn, SaleReturnItem,
|
||||||
|
PurchaseReturn, PurchaseReturnItem, transaction, timezone,
|
||||||
|
decimal, json, JsonResponse, get_object_or_404, login_required, csrf_exempt, logger
|
||||||
|
)
|
||||||
|
|
||||||
|
def patch_purchase_return_create(request):
|
||||||
|
suppliers = Supplier.objects.filter(is_active=True)
|
||||||
|
products = Product.objects.filter(is_active=True)
|
||||||
|
return {'suppliers': suppliers, 'products': products}
|
||||||
|
|
||||||
|
def patch_sale_return_create(request):
|
||||||
|
customers = Customer.objects.all()
|
||||||
|
products = Product.objects.filter(is_active=True)
|
||||||
|
return {'customers': customers, 'products': products}
|
||||||
159
patch_returns_v3.py
Normal file
159
patch_returns_v3.py
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
file_path = 'core/views.py'
|
||||||
|
|
||||||
|
with open(file_path, 'r') as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
# Replacement 1: sale_return_create
|
||||||
|
old_sale_create = "def sale_return_create(request): return render(request, 'core/sale_return_create.html')"
|
||||||
|
new_sale_create = """def sale_return_create(request):
|
||||||
|
customers = Customer.objects.all()
|
||||||
|
products = Product.objects.filter(is_active=True)
|
||||||
|
return render(request, 'core/sale_return_create.html', {
|
||||||
|
'customers': customers,
|
||||||
|
'products': products
|
||||||
|
})"""
|
||||||
|
|
||||||
|
# Replacement 2: create_sale_return_api
|
||||||
|
old_sale_api = "@csrf_exempt\ndef create_sale_return_api(request): return JsonResponse({'success': True})"
|
||||||
|
new_sale_api = """@csrf_exempt
|
||||||
|
@login_required
|
||||||
|
def create_sale_return_api(request):
|
||||||
|
if request.method != 'POST':
|
||||||
|
return JsonResponse({'success': False, 'error': 'Invalid method'})
|
||||||
|
try:
|
||||||
|
data = json.loads(request.body)
|
||||||
|
customer_id = data.get('customer_id')
|
||||||
|
items = data.get('items', [])
|
||||||
|
|
||||||
|
customer = None
|
||||||
|
if customer_id:
|
||||||
|
customer = get_object_or_404(Customer, pk=customer_id)
|
||||||
|
|
||||||
|
with transaction.atomic():
|
||||||
|
sale_return = SaleReturn.objects.create(
|
||||||
|
customer=customer,
|
||||||
|
created_by=request.user,
|
||||||
|
total_amount=0,
|
||||||
|
return_number=f"SR-{{int(timezone.now().timestamp())}}",
|
||||||
|
notes=data.get('notes', '')
|
||||||
|
)
|
||||||
|
|
||||||
|
total = decimal.Decimal(0)
|
||||||
|
for item in items:
|
||||||
|
qty = decimal.Decimal(str(item.get('quantity', 0)))
|
||||||
|
price = decimal.Decimal(str(item.get('price', 0)))
|
||||||
|
line_total = qty * price
|
||||||
|
|
||||||
|
SaleReturnItem.objects.create(
|
||||||
|
sale_return=sale_return,
|
||||||
|
product_id=item['id'],
|
||||||
|
quantity=qty,
|
||||||
|
unit_price=price,
|
||||||
|
line_total=line_total
|
||||||
|
)
|
||||||
|
|
||||||
|
# Update stock: Returns from customer mean stock comes IN
|
||||||
|
product = Product.objects.get(pk=item['id'])
|
||||||
|
product.stock_quantity += qty
|
||||||
|
product.save()
|
||||||
|
|
||||||
|
total += line_total
|
||||||
|
|
||||||
|
sale_return.total_amount = total
|
||||||
|
sale_return.save()
|
||||||
|
|
||||||
|
return JsonResponse({'success': True, 'id': sale_return.id})
|
||||||
|
except Exception as e:
|
||||||
|
logger.exception("Error creating sale return")
|
||||||
|
return JsonResponse({'success': False, 'error': str(e)})"""
|
||||||
|
|
||||||
|
# Replacement 3: purchase_return_create
|
||||||
|
old_purchase_create = "def purchase_return_create(request): return render(request, 'core/purchase_return_create.html')"
|
||||||
|
new_purchase_create = """def purchase_return_create(request):
|
||||||
|
suppliers = Supplier.objects.filter(is_active=True)
|
||||||
|
products = Product.objects.filter(is_active=True)
|
||||||
|
return render(request, 'core/purchase_return_create.html', {
|
||||||
|
'suppliers': suppliers,
|
||||||
|
'products': products
|
||||||
|
})"""
|
||||||
|
|
||||||
|
# Replacement 4: create_purchase_return_api
|
||||||
|
old_purchase_api = "@csrf_exempt\ndef create_purchase_return_api(request): return JsonResponse({'success': True})"
|
||||||
|
new_purchase_api = """@csrf_exempt
|
||||||
|
@login_required
|
||||||
|
def create_purchase_return_api(request):
|
||||||
|
if request.method != 'POST':
|
||||||
|
return JsonResponse({'success': False, 'error': 'Invalid method'})
|
||||||
|
try:
|
||||||
|
data = json.loads(request.body)
|
||||||
|
supplier_id = data.get('supplier_id')
|
||||||
|
items = data.get('items', [])
|
||||||
|
|
||||||
|
supplier = get_object_or_404(Supplier, pk=supplier_id)
|
||||||
|
|
||||||
|
with transaction.atomic():
|
||||||
|
purchase_return = PurchaseReturn.objects.create(
|
||||||
|
supplier=supplier,
|
||||||
|
created_by=request.user,
|
||||||
|
total_amount=0,
|
||||||
|
return_number=f"PR-{{int(timezone.now().timestamp())}}",
|
||||||
|
notes=data.get('notes', '')
|
||||||
|
)
|
||||||
|
|
||||||
|
total = decimal.Decimal(0)
|
||||||
|
for item in items:
|
||||||
|
qty = decimal.Decimal(str(item.get('quantity', 0)))
|
||||||
|
cost = decimal.Decimal(str(item.get('price', 0)))
|
||||||
|
line_total = qty * cost
|
||||||
|
|
||||||
|
PurchaseReturnItem.objects.create(
|
||||||
|
purchase_return=purchase_return,
|
||||||
|
product_id=item['id'],
|
||||||
|
quantity=qty,
|
||||||
|
cost_price=cost,
|
||||||
|
line_total=line_total
|
||||||
|
)
|
||||||
|
|
||||||
|
# Update stock: Returns to supplier mean stock goes OUT
|
||||||
|
product = Product.objects.get(pk=item['id'])
|
||||||
|
product.stock_quantity -= qty
|
||||||
|
product.save()
|
||||||
|
|
||||||
|
total += line_total
|
||||||
|
|
||||||
|
purchase_return.total_amount = total
|
||||||
|
purchase_return.save()
|
||||||
|
|
||||||
|
return JsonResponse({'success': True, 'id': purchase_return.id})
|
||||||
|
except Exception as e:
|
||||||
|
logger.exception("Error creating purchase return")
|
||||||
|
return JsonResponse({'success': False, 'error': str(e)})"""
|
||||||
|
|
||||||
|
if old_sale_create in content:
|
||||||
|
content = content.replace(old_sale_create, new_sale_create)
|
||||||
|
print("Patched sale_return_create")
|
||||||
|
else:
|
||||||
|
print("Could not find sale_return_create stub")
|
||||||
|
|
||||||
|
if old_sale_api in content:
|
||||||
|
content = content.replace(old_sale_api, new_sale_api)
|
||||||
|
print("Patched create_sale_return_api")
|
||||||
|
else:
|
||||||
|
print("Could not find create_sale_return_api stub")
|
||||||
|
|
||||||
|
if old_purchase_create in content:
|
||||||
|
content = content.replace(old_purchase_create, new_purchase_create)
|
||||||
|
print("Patched purchase_return_create")
|
||||||
|
else:
|
||||||
|
print("Could not find purchase_return_create stub")
|
||||||
|
|
||||||
|
if old_purchase_api in content:
|
||||||
|
content = content.replace(old_purchase_api, new_purchase_api)
|
||||||
|
print("Patched create_purchase_return_api")
|
||||||
|
else:
|
||||||
|
print("Could not find create_purchase_return_api stub")
|
||||||
|
|
||||||
|
with open(file_path, 'w') as f:
|
||||||
|
f.write(content)
|
||||||
Loading…
x
Reference in New Issue
Block a user