【发布时间】:2021-01-17 17:31:15
【问题描述】:
编辑(添加实际模型和细节)
**
好的,所以这个问题会有点冗长,实际上有四个模型。每当我创建发票时,我需要添加来自我使用循环的前端的发票详细信息并将所有这些添加到我的数据库中。下一部分是在 Ledger 表和 ProductQuantity 表中创建一条记录,为此我必须重复我在 InvoiceCreateAndGetByIdOnly中编写的代码>。我有许多更新多个模型的视图,并且我重复了很多代码。如您所见,serializers.py 非常薄,而 views.py 非常厚。就像 InvoiceCreate 视图一样,我还有其他视图可以更新 Ledger 和 ProductQuantity 模型,所以我必须重做我的 views.py 一遍又一遍
models.py
>class Invoice(models.Model):
invoice_id = models.AutoField(primary_key=True, editable=False)
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
date = models.DateField(default=datetime.date(datetime.now()))
builty_num = models.CharField(max_length=100, blank=True)
total_amount = models.FloatField(validators=[MinValueValidator(0.0)])
discount = models.FloatField(default=0.0, validators=[MinValueValidator(0.0)])
overflow = models.FloatField(default=0.0, validators=[MinValueValidator(0.0)])
class InvoiceDetail(models.Model):
invoice = models.ForeignKey(Invoice, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
warehouse = models.ForeignKey(Warehouse, on_delete=models.CASCADE)
rate = models.FloatField(validators=[MinValueValidator(0.0)])
num_thaan = models.PositiveIntegerField(validators=[MinValueValidator(1)])
gazaana_per_thaan = models.FloatField(validators=[MinValueValidator(0.0)])
class Ledger(models.Model):
TYPE = (
('D','Debit'),
('C','Credit'),
)
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
invoice = models.ForeignKey(Invoice, null=True, on_delete=models.CASCADE)
return_invoice = models.ForeignKey(ReturnInvoice, null=True, on_delete=models.CASCADE)
cash = models.ForeignKey(CashDetail, null=True, on_delete=models.CASCADE)
cheque = models.ForeignKey(ChequeDetail, null=True, on_delete=models.CASCADE)
cheque_transfer = models.ForeignKey(ChequeTransfer, null=True, on_delete=models.CASCADE)
bank = models.ForeignKey(BankTransfer, null=True, on_delete=models.CASCADE)
date = models.DateField(default=datetime.date(datetime.now()))
detail = models.TextField()
transaction_type = models.CharField(max_length=1, choices=TYPE)
amount = models.FloatField(validators=[MinValueValidator(0.0)])
balance = models.FloatField(validators=[MinValueValidator(0.0)])
balance_status = models.CharField(max_length=6)
class ProductQuantity(models.Model):
TYPE = (
('+','Add'),
('-','Subtract'),
)
invoice_id_add = models.ForeignKey(StockInvoice, on_delete=models.CASCADE, null=True)
invoice_id_sub = models.ForeignKey(Invoice, on_delete=models.CASCADE, null=True)
invoice_id_return = models.ForeignKey(ReturnInvoice, on_delete=models.CASCADE, null=True)
invoice_id_stock_return = models.ForeignKey(StockReturnInvoice, on_delete=models.CASCADE, null=True)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
warehouse = models.ForeignKey(Warehouse, on_delete=models.CASCADE)
date = models.DateField(default=datetime.date(datetime.now()))
num_thaan = models.PositiveIntegerField()
rate = models.FloatField(validators=[MinValueValidator(0.0)])
gazaana_per_thaan = models.FloatField(validators=[MinValueValidator(0.0)])
quantity = models.FloatField(validators=[MinValueValidator(0.0)])
transaction_type = models.CharField(max_length=1, choices=TYPE)
views.py
>class InvoiceCreateAndGetByIdOnly(APIView):
"""
only handle post/get request when the invoice is created,
update ledger accordingly and updates quantity in ProductQuantity
"""
permission_classes = [canEditInvoice]
def get(self, request):
if 'invoice_id' in request.query_params:
query = Invoice.objects.filter(
invoice_id = request.query_params['invoice_id']
)
return Response(InvoiceSerializer(query,many=True).data)
query = Invoice.objects.all()
return Response(InvoiceSerializer(query, many=True).data)
def post(self, request):
allData = request.data
data = request.data
invoice_detail = data.pop('invoice_set')
serializer_invoice = InvoiceSerializer(data=request.data)
if serializer_invoice.is_valid():
invoice = serializer_invoice.create(
validated_data=serializer_invoice.validated_data
)
invoice_detail_array = []
"""adding invoice_id to the invoice_detail_set"""
for detail in invoice_detail:
isValid = False
detail['invoice'] = invoice.invoice_id
invoice_detail_array.append(detail)
serializer_new = InvoiceDetailSerializer(data=detail)
if serializer_new.is_valid():
isValid = True
else:
Invoice.objects.filter(invoice_id=invoice.invoice_id).delete()
return Response(
serializer_new.errors,
status=status.HTTP_400_BAD_REQUEST
)
for detail in invoice_detail_array:
quantity , thaan = ProductQuantity.get_quantity(
product=detail['product'],
warehouse=detail['warehouse'],
gazaana=detail['gazaana_per_thaan']
)
if(thaan < detail['num_thaan']):
Invoice.objects.filter(invoice_id=invoice.invoice_id).delete()
return Response(
{'error':'less thaan in stock'},
status=status.HTTP_400_BAD_REQUEST
)
if(quantity < (detail['num_thaan'] * detail['gazaana_per_thaan'])):
Invoice.objects.filter(invoice_id=invoice.invoice_id).delete()
return Response(
{'error':'less quantity in stock'},
status=status.HTTP_400_BAD_REQUEST
)
quantity = {
'invoice_id_sub' : invoice.invoice_id,
'product': detail['product'],
'warehouse': detail['warehouse'],
'date': invoice.date,
'num_thaan': detail['num_thaan'],
'rate': detail['rate'],
'quantity': detail['num_thaan'] * detail['gazaana_per_thaan'],
'gazaana_per_thaan': detail['gazaana_per_thaan'],
'transaction_type': '-'
}
serializer_new = InvoiceDetailSerializer(data=detail)
serializer_product_quantity = ProductQuantitySerializer(data=quantity)
if(serializer_new.is_valid()):
invoice_detail = serializer_new.create(
validated_data=serializer_new.validated_data
)
if(serializer_product_quantity.is_valid()):
product_quantity_detail = serializer_product_quantity.create(
validated_data=serializer_product_quantity.validated_data)
invoice_db = Invoice.objects.get(invoice_id=invoice.invoice_id)
invoice_detail_db = InvoiceDetail.objects.all().filter(invoice=invoice_db.invoice_id)
detail = " "
for obj in invoice_detail_db:
detail += (
str(obj.num_thaan) + " thaan " +
str(obj.gazaana_per_thaan) + " gaz " +
str(obj.product) + " @ PKR " +
str(obj.rate) + "\n"
)
balance = Ledger.get_balance(invoice_db.customer.customer_id)
new_balance = balance - invoice_db.total_amount - invoice_db.overflow + invoice_db.discount
status_ledger = ""
if( new_balance == 0):
status_ledger = "Nill"
elif( new_balance > 0):
status_ledger = "Credit"
elif( new_balance < 0):
status_ledger = "Debit"
data_ledger = {
'customer': invoice_db.customer.customer_id,
'invoice' : invoice_db.invoice_id,
'date' : invoice_db.date,
'transaction_type' : 'D',
'amount' : invoice_db.total_amount + invoice_db.overflow - invoice_db.discount ,
'detail' : detail,
'balance': abs(new_balance),
'balance_status': status_ledger,
}
serializer_ledger = LedgerSerializer(data=data_ledger)
if serializer_ledger.is_valid():
ledger_instance = serializer_ledger.create(
validated_data=serializer_ledger.validated_data
)
else:
return Response(
serializer_ledger.errors,
status=status.HTTP_400_BAD_REQUEST
)
return Response({
"message":"invoice successfully created",
"data":allData
}, status=status.HTTP_201_CREATED)
return Response(
serializer_invoice.errors,
status=status.HTTP_400_BAD_REQUEST
)
serializers.py
>class LedgerSerializer(serializers.ModelSerializer):
class Meta:
model = Ledger
fields = '__all__'
class InvoiceSerializer(serializers.ModelSerializer):
invoice_detail = serializers.SerializerMethodField('get_invoice_details')
def get_invoice_details(self,obj):
return InvoiceDetailSerializer(InvoiceDetail.objects.filter(invoice=obj),many=True).data
class Meta:
model = Invoice
# fields = '__all__'
fields = ['invoice_detail', 'customer', 'builty_num','date', 'total_amount', 'invoice_id', 'overflow', 'discount']
class InvoiceDetailSerializer(serializers.ModelSerializer):
class Meta:
model = InvoiceDetail
fields = '__all__'
class ProductQuantitySerializer(serializers.ModelSerializer):
class Meta:
model = ProductQuantity
fields = '__all__'
【问题讨论】:
-
你能举个具体的例子吗?目前尚不清楚问题是什么以及您期望什么。
-
@BriseBalloches,我刚刚更新了问题并添加了所有详细信息,如果您需要更多详细信息,请告诉我。
标签: python django serialization django-rest-framework