1+ from decimal import ROUND_HALF_UP , Decimal
2+
13from django .conf import settings
24from django .contrib .auth .models import AbstractUser
35from django .core .validators import MaxValueValidator , MinValueValidator
46from django .db import models
57
8+ PAYMENT_CHOICES = [
9+ ("COD" , "Cash on Delivery" ),
10+ ("UPI" , "UPI" ),
11+ ("CARD" , "Card" ),
12+ ]
13+
614
715class TimestampedModel (models .Model ):
816 created_at = models .DateTimeField (auto_now_add = True )
@@ -130,7 +138,7 @@ class ProductReview(TimestampedModel):
130138 validators = [MinValueValidator (1 ), MaxValueValidator (5 )]
131139 )
132140 review_text = models .TextField (blank = True )
133- image = models .ImageField (upload_to = "reviews/" , blank = True , null = True )
141+ # image = models.ImageField(upload_to="reviews/", blank=True, null=True)
134142
135143 class Meta :
136144 unique_together = ("user" , "product" ) # One review per user
@@ -139,6 +147,17 @@ def __str__(self):
139147 return f"{ self .user .username } - { self .product .product_name } "
140148
141149
150+ class ProductReviewImage (models .Model ):
151+ review = models .ForeignKey (
152+ ProductReview , related_name = "images" , on_delete = models .CASCADE
153+ )
154+ image = models .ImageField (upload_to = "product_review_images/" )
155+ uploaded_at = models .DateTimeField (auto_now_add = True )
156+
157+ def __str__ (self ):
158+ return f"ReviewImage { self .id } for Review { self .review .id } "
159+
160+
142161class Review (TimestampedModel ):
143162 technician = models .ForeignKey (
144163 Profile , on_delete = models .CASCADE , related_name = "reviews"
@@ -174,3 +193,103 @@ class Booking(models.Model):
174193
175194 def __str__ (self ):
176195 return f"Booking { self .pk } - { self .technician } for { self .user } "
196+
197+
198+ class Cart (TimestampedModel ):
199+ user = models .ForeignKey (
200+ settings .AUTH_USER_MODEL , on_delete = models .CASCADE , related_name = "carts"
201+ )
202+ is_active = models .BooleanField (default = True )
203+
204+ def __str__ (self ):
205+ return f"Cart { self .pk } - { self .user .username } "
206+
207+ @property
208+ def total (self ):
209+ total = sum ([item .total_price for item in self .items .all ()])
210+ return Decimal (total ).quantize (Decimal ("0.01" ), rounding = ROUND_HALF_UP )
211+
212+
213+ class CartItem (models .Model ):
214+ cart = models .ForeignKey (Cart , on_delete = models .CASCADE , related_name = "items" )
215+ product = models .ForeignKey ("Product" , on_delete = models .CASCADE )
216+ quantity = models .PositiveIntegerField (default = 1 )
217+ unit_price = models .DecimalField (max_digits = 10 , decimal_places = 2 )
218+ added_at = models .DateTimeField (auto_now_add = True )
219+
220+ class Meta :
221+ unique_together = ("cart" , "product" )
222+
223+ def __str__ (self ):
224+ return f"{ self .product .product_name } x { self .quantity } "
225+
226+ @property
227+ def total_price (self ):
228+ return (Decimal (self .unit_price ) * Decimal (self .quantity )).quantize (
229+ Decimal ("0.01" ), rounding = ROUND_HALF_UP
230+ )
231+
232+
233+ class Order (models .Model ):
234+ user = models .ForeignKey (
235+ settings .AUTH_USER_MODEL , on_delete = models .CASCADE , related_name = "orders"
236+ )
237+ cart = models .ForeignKey (Cart , on_delete = models .SET_NULL , null = True , blank = True )
238+ created_at = models .DateTimeField (auto_now_add = True )
239+ total = models .DecimalField (max_digits = 12 , decimal_places = 2 )
240+ address = models .JSONField (blank = True , null = True )
241+ payment_method = models .CharField (max_length = 10 , choices = PAYMENT_CHOICES )
242+ payment_done = models .BooleanField (default = False )
243+ technician = models .ForeignKey (
244+ "Profile" , on_delete = models .SET_NULL , null = True , blank = True
245+ )
246+ technician_fee = models .DecimalField (max_digits = 10 , decimal_places = 2 , default = 0 )
247+ booking = models .OneToOneField (
248+ "Booking" ,
249+ on_delete = models .SET_NULL ,
250+ null = True ,
251+ blank = True ,
252+ related_name = "order" ,
253+ )
254+ notes = models .TextField (blank = True , default = "" )
255+
256+ def __str__ (self ):
257+ return f"Order { self .pk } - { self .user .username } "
258+
259+
260+ class OrderItem (models .Model ):
261+ order = models .ForeignKey (Order , on_delete = models .CASCADE , related_name = "items" )
262+ product = models .ForeignKey ("Product" , on_delete = models .SET_NULL , null = True )
263+ unit_price = models .DecimalField (max_digits = 10 , decimal_places = 2 )
264+ quantity = models .PositiveIntegerField ()
265+ line_total = models .DecimalField (max_digits = 12 , decimal_places = 2 )
266+
267+ def __str__ (self ):
268+ return f"OrderItem { self .pk } for Order { self .order .pk } "
269+
270+
271+ class Notification (TimestampedModel ):
272+ recipient = models .ForeignKey (
273+ "Profile" , on_delete = models .CASCADE , related_name = "notifications"
274+ )
275+ title = models .CharField (max_length = 255 )
276+ message = models .TextField ()
277+ metadata = models .JSONField (blank = True , null = True )
278+ is_read = models .BooleanField (default = False )
279+
280+ def __str__ (self ):
281+ return f"Notification to { self .recipient } - { self .title } "
282+
283+
284+ class TechnicianReview (models .Model ):
285+ technician = models .ForeignKey (
286+ Profile , on_delete = models .CASCADE , related_name = "tech_reviews"
287+ )
288+ user = models .ForeignKey (User , on_delete = models .CASCADE )
289+ booking = models .OneToOneField (Booking , on_delete = models .CASCADE )
290+ rating = models .IntegerField ()
291+ comment = models .TextField (blank = True )
292+ created_at = models .DateTimeField (auto_now_add = True )
293+
294+ def __str__ (self ):
295+ return f"{ self .user } reviewed { self .technician } "
0 commit comments