gold eggs backend
Some checks failed
Build and Push to Docker Hub / build-test-push (push) Failing after 1m55s

This commit is contained in:
2026-04-15 08:59:36 +02:00
commit ab73d05ecc
359 changed files with 14415 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
from .additional_cost import * # noqa
from .all_history import * # noqa
from .broken import * # noqa
from .courier import * # noqa
from .courier_history import * # noqa
from .courier_product import * # noqa
from .debt import * # noqa
from .group import * # noqa
from .history import * # noqa
from .invoice import * # noqa
from .location import * # noqa
from .market import * # noqa
from .monitoring import * # noqa
from .order import * # noqa
from .order_item import * # noqa
from .order_item import * # noqa
from .party import * # noqa
from .product import * # noqa
from .sklad import * # noqa
from .notification import * # noqa
from .daily_cost import * # noqa

View File

@@ -0,0 +1,25 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
from core.http.models import User
class AdditionalCost(models.Model):
user = models.ForeignKey(
to=User,
verbose_name=_("User"),
on_delete=models.CASCADE,
null=True,
blank=True,
)
reason = models.TextField(_("Name"))
price = models.DecimalField(_("Price"), max_digits=10, decimal_places=2)
created_at = models.DateTimeField(_("Created at"), auto_now_add=True)
updated_at = models.DateTimeField(_("Updated at"), auto_now=True)
class Meta:
verbose_name = _("Additional cost")
verbose_name_plural = _("Additional costs")
def __str__(self):
return self.reason

View File

@@ -0,0 +1,17 @@
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models
class AllHistory(models.Model):
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey("content_type", "object_id")
action = models.CharField(max_length=255, null=True, blank=True)
timestamp = models.DateTimeField(auto_now_add=True)
created_by = models.CharField(max_length=255, null=True, blank=True)
created_who = models.CharField(max_length=255, null=True, blank=True)
reason = models.TextField(null=True, blank=True)
class Meta:
ordering = ["-timestamp"]

View File

@@ -0,0 +1,50 @@
from django.db import models
from core.apps.eggs.models import group
from core.http.models import AbstractBaseModel
from core.http.models.user import User
class Broken(AbstractBaseModel):
user_id = models.ForeignKey(
to=User,
on_delete=models.CASCADE,
related_name="broken_eggs",
null=True,
blank=True,
)
group = models.ForeignKey(
group.Group, on_delete=models.CASCADE, related_name="brokens"
)
comment = models.TextField(verbose_name="Comment")
quantity = models.IntegerField(verbose_name="Quantity")
price = models.DecimalField(
max_digits=30, decimal_places=2, default=0, null=True, blank=True
)
def save(self, *args, **kwargs):
is_new = self.pk is None
if is_new:
if self.group.quantity < self.quantity:
raise ValueError(
"Quantity cannot be greater than group quantity"
)
self.group.quantity -= self.quantity
self.group.party_id.remaining_count -= self.quantity
self.group.broken_eggs += self.quantity
self.group.party_id.profit -= (
self.group.entry_price * self.quantity
)
self.group.party_id.broken_eggs += self.quantity
self.price = self.group.entry_price * self.quantity
self.group.save()
self.group.party_id.save()
super().save(*args, **kwargs)
def __str__(self):
return self.comment
class Meta:
verbose_name = "Broken"
verbose_name_plural = "Brokens"
db_table = "broken"

View File

@@ -0,0 +1,21 @@
"""
Courier model
"""
from django.db import models
from core.http.models import base
from core.http.models.user import User
class Courier(base.AbstractBaseModel):
user_id = models.ForeignKey(
to=User, on_delete=models.CASCADE, related_name="couriers"
)
def __str__(self):
return f"Courier - {self.user_id}"
class Meta:
verbose_name = "Courier"
verbose_name_plural = "Couriers"
db_table = "courier"

View File

@@ -0,0 +1,39 @@
"""
Couirier History model
"""
from django.db import models
from core.apps.eggs.models import courier, courier_product, group
from core.http.models import base
class CourierHistory(base.AbstractBaseModel):
courier_id = models.ForeignKey(
to=courier.Courier,
on_delete=models.CASCADE,
related_name="courier_histories",
)
courier_product_id = models.ForeignKey(
to=courier_product.CourierProduct,
on_delete=models.SET_NULL,
related_name="courier_histories",
null=True, # Allow NULL values
)
group_id = models.ForeignKey(
to=group.Group,
on_delete=models.SET_NULL,
null=True, # Allow NULL values
)
get_eggs = models.IntegerField()
return_eggs = models.IntegerField(null=True, blank=True)
broken_eggs = models.IntegerField(null=True, blank=True)
date = models.DateField(auto_now=True, null=True, blank=True)
def __str__(self) -> str:
return f"{self.courier_id}, {self.group_id}"
class Meta:
verbose_name = "CourierHistory"
verbose_name_plural = "CourierHistories"
db_table = "courier_history"

View File

@@ -0,0 +1,42 @@
"""
Courier Product model
"""
from django.core.validators import MinValueValidator
from django.db import models
from core.apps.eggs.models import courier, group
from core.http.models import base
class CourierProduct(base.AbstractBaseModel):
group_id = models.ForeignKey(
to=group.Group, on_delete=models.CASCADE, related_name="courier_groups"
)
count = models.IntegerField(
validators=[MinValueValidator(0)], verbose_name="Count of eggs"
)
courier_id = models.ForeignKey(
to=courier.Courier,
on_delete=models.CASCADE,
related_name="courier_products",
)
return_eggs = models.IntegerField(
default=0,
verbose_name="Return eggs",
validators=[MinValueValidator(0)],
null=True,
blank=True,
)
def clean(self):
if self.count < 0:
raise ValueError("Count must be greater than 0")
def __str__(self):
return f"Courier - {self.courier_id}, group_id - {self.group_id}"
class Meta:
verbose_name = "CourierProduct"
verbose_name_plural = "CourierProducts"
db_table = "courier_product"

View File

@@ -0,0 +1,14 @@
from django.db import models
from core.http.models import AbstractBaseModel
class DailyCost(AbstractBaseModel):
first_cost = models.DecimalField(max_digits=40, decimal_places=2)
second_cost = models.DecimalField(max_digits=40, decimal_places=2)
third_cost = models.DecimalField(max_digits=40, decimal_places=2)
class Meta:
verbose_name = "Daily Cost"
verbose_name_plural = "Daily Costs"
db_table = "daily_costs"

View File

@@ -0,0 +1,78 @@
from django.db import models
from rest_framework.exceptions import ValidationError
from core.http.models import AbstractBaseModel
class DebtTypeEnum(models.TextChoices):
ADDED = "added"
LOST = "lost"
class Debt(AbstractBaseModel):
market = models.ForeignKey(
to="Market", on_delete=models.CASCADE, related_name="debts"
)
debt_price = models.DecimalField(max_digits=30, decimal_places=2)
debt_type = models.CharField(
max_length=255,
choices=DebtTypeEnum.choices,
default=DebtTypeEnum.LOST.value,
)
def save(self, *args, **kwargs):
if self.pk is None:
if self.debt_type == DebtTypeEnum.ADDED.value:
# self.market.debt_paid -= self.debt_price
self.market.debt_unpaid += self.debt_price
elif self.debt_type == DebtTypeEnum.LOST.value:
if self.debt_price > self.market.debt_unpaid:
raise ValueError(
"Debt price cannot be greater than unpaid debt."
)
self.market.debt_paid += self.debt_price
self.market.debt_unpaid -= self.debt_price
else:
raise ValidationError(
detail={"debt_type": "invlaid debt_type"}
)
self.market.save()
super().save(*args, **kwargs)
def __str__(self):
return f"{self.debt_price} - {self.market.name}"
# from django.db import models
# from django.core.exceptions import ValidationError
#
#
# class Debt(AbstractBaseModel):
# market = models.ForeignKey(to="Market", on_delete=models.CASCADE)
# order = models.ForeignKey(to="Order", on_delete=models.CASCADE)
# debt_price = models.DecimalField(max_digits=30, decimal_places=2)
#
# def save(self, *args, **kwargs):
# if self.pk is None:
# if self.debt_price > self.market.debt_unpaid:
# raise ValidationError("Debt price cannot be greater than unpaid debt.")
#
# self.market.debt_paid += self.debt_price
# self.market.debt_unpaid -= self.debt_price
# self.market.save()
#
# self.order.price_paid += self.debt_price
# self.order.debt -= self.debt_price
# self.order.save()
#
# order_items = OrderItems.objects.filter(order_id=self.order.id)
# for item in order_items:
# party = item.courier_product_id.group_id.party_id
# if party:
# party.benefit += self.debt_price
# party.save()
#
# super().save(*args, **kwargs)
#
# def __str__(self):
# return f"{self.debt_price} - {self.market.name} - {self.order.id}"

View File

@@ -0,0 +1,52 @@
"""
Groups model
"""
from django.core.validators import MinValueValidator
from django.db import models
from core.apps.eggs.models import party
from core.apps.eggs.models import product
from core.http.models import base
class Group(base.AbstractBaseModel):
product_id = models.ForeignKey(
to=product.Product, on_delete=models.CASCADE, related_name="groups"
)
party_id = models.ForeignKey(
to=party.Party,
on_delete=models.CASCADE,
related_name="groups",
blank=True,
null=True,
)
entry_price = models.DecimalField(max_digits=30, decimal_places=2)
unit_price = models.DecimalField(max_digits=30, decimal_places=2)
wholesale_price = models.DecimalField(max_digits=30, decimal_places=2)
quantity = models.IntegerField(
validators=[MinValueValidator(0)], default=0
)
broken_eggs = models.IntegerField(
validators=[MinValueValidator(0)], default=0
)
date = models.DateTimeField(auto_now=True)
name = models.CharField(max_length=255, blank=True, null=True)
def clean(self):
if self.quantity < 0:
raise ValueError("Quantity can't be negative")
# def save(self, *args, **kwargs):
# self.party_id.count += self.quantity
# self.party_id.price += self.entry_price * self.quantity
# self.party_id.save()
# super().save(*args, **kwargs)
def __str__(self) -> str:
return f"{self.product_id}, Quantity - {self.quantity}"
class Meta:
verbose_name = "Group"
verbose_name_plural = "Groups"
db_table = "group"

View File

@@ -0,0 +1,26 @@
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models
from core.http.models import User
class History(models.Model):
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey("content_type", "object_id")
action = models.CharField(max_length=255)
user_id = models.ForeignKey(
to=User, on_delete=models.CASCADE, related_name="history"
)
avatar = models.ImageField(
upload_to="history_avatars/", null=True, blank=True
)
timestamp = models.DateTimeField(auto_now_add=True)
created_by = models.CharField(max_length=255, null=True, blank=True)
created_who = models.CharField(max_length=255, null=True, blank=True)
comment = models.CharField(max_length=255, null=True, blank=True)
reason = models.CharField(max_length=255, null=True, blank=True)
class Meta:
ordering = ["-timestamp"]

View File

@@ -0,0 +1,23 @@
"""
Invoice model
"""
from django.db import models
from core.apps.eggs.models import party
class Invoice(models.Model):
name = models.CharField(max_length=256)
price = models.DecimalField(max_digits=30, decimal_places=2)
party_id = models.ForeignKey(
to=party.Party, on_delete=models.CASCADE, related_name="invoices"
)
def __str__(self) -> str:
return f"{self.name}, {self.price}"
class Meta:
verbose_name = "Invoice"
verbose_name_plural = "Invoices"
db_table = "invoice"

View File

@@ -0,0 +1,21 @@
"""
Location model
"""
from django.db import models
from core.http.models import base
class Location(base.AbstractBaseModel):
long = models.FloatField(null=True, blank=True)
lat = models.FloatField(null=True, blank=True)
label = models.TextField()
def __str__(self) -> str:
return f"{self.long}, {self.lat}"
class Meta:
verbose_name = "Location"
verbose_name_plural = "Locations"
db_table = "location"

View File

@@ -0,0 +1,48 @@
"""
Market model
"""
from django.core.validators import MinValueValidator
from django.db import models
from core.apps.eggs.models import location
from core.http.models import base
from core.http.models.user import User
class Market(base.AbstractBaseModel):
name = models.CharField(max_length=255)
company_name = models.CharField(max_length=255)
user_id = models.ForeignKey(to=User, on_delete=models.CASCADE)
avatar = models.ImageField(
upload_to="market_avatar/",
blank=True,
null=True,
default="market_avatar/default.png",
)
phone = models.CharField(max_length=20)
location_id = models.ForeignKey(
to=location.Location,
on_delete=models.CASCADE,
related_name="market_location",
)
debt_paid = models.DecimalField(
max_digits=10,
decimal_places=2,
default=0,
validators=[MinValueValidator(0)],
)
debt_unpaid = models.DecimalField(
max_digits=10,
decimal_places=2,
default=0,
validators=[MinValueValidator(0)],
)
def __str__(self):
return f"{self.name} - {self.phone}"
class Meta:
verbose_name = "Market"
verbose_name_plural = "Markets"
db_table = "market"

View File

@@ -0,0 +1,26 @@
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models
from core.http.models import User
class Monitoring(models.Model):
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey("content_type", "object_id")
action = models.CharField(max_length=255)
user_id = models.ForeignKey(
to=User, on_delete=models.CASCADE, related_name="monitoring"
)
timestamp = models.DateTimeField(auto_now_add=True)
created_by = models.CharField(max_length=255, null=True, blank=True)
created_who = models.CharField(max_length=255, null=True, blank=True)
comment = models.CharField(max_length=255, null=True, blank=True)
reason = models.CharField(max_length=255, null=True, blank=True)
price = models.DecimalField(
max_digits=30, decimal_places=2, default=0, null=True, blank=True
)
class Meta:
ordering = ["-timestamp"]

View File

@@ -0,0 +1,25 @@
from django.db import models
from core.http.models import AbstractBaseModel
class Notification(AbstractBaseModel):
title = models.CharField(max_length=255, verbose_name="Title")
body = models.TextField(verbose_name="Body")
user = models.ForeignKey(
"http.User",
on_delete=models.CASCADE,
related_name="notifications",
verbose_name="User",
null=True,
blank=True,
)
is_read = models.BooleanField(default=False, verbose_name="Is read")
is_sending = models.BooleanField(default=False, verbose_name="Is sending")
def __str__(self) -> str:
return self.title
class Meta:
verbose_name = "Notification"
verbose_name_plural = "Notifications"

View File

@@ -0,0 +1,55 @@
"""
Order model
"""
from django.db import models, transaction
from django.db.models import F
from core.apps.eggs.models import Location, courier, location, market
from core.http.models import base
class Order(base.AbstractBaseModel):
STATUS_CHOICES = (
("pending", "Pending"),
("delivery", "Delivery"),
("success", "Success"),
("done", "Done"),
("cancel", "Cancel"),
)
courier_id = models.ForeignKey(
to=courier.Courier,
on_delete=models.CASCADE,
related_name="orders",
null=True,
blank=True,
)
market_id = models.ForeignKey(
to=market.Market,
on_delete=models.CASCADE,
related_name="orders",
null=True,
blank=True,
)
data = models.DateTimeField(auto_now_add=True)
status = models.CharField(
max_length=255, choices=STATUS_CHOICES, default="pending"
)
comment = models.TextField(blank=True, null=True)
price = models.DecimalField(max_digits=30, decimal_places=2, default=0)
price_paid = models.DecimalField(
max_digits=30, decimal_places=2, default=0
)
debt = models.DecimalField(max_digits=30, decimal_places=2, default=0)
location_id = models.ForeignKey(
Location, on_delete=models.CASCADE, null=True
)
count = models.IntegerField(null=True, blank=True, default=0)
def __str__(self):
return f"Order - {self.id}, status - {self.status}"
class Meta:
verbose_name = "Order"
verbose_name_plural = "Orders"
db_table = "order"

View File

@@ -0,0 +1,43 @@
"""
Order Items model
"""
import decimal
from django.db import models
from core.apps.eggs.models import courier_product, group, order
from core.http.models import base
class OrderItems(base.AbstractBaseModel):
SALE_TYPE_CHOICES = (
("optom", "Optom"),
("dona", "Dona"),
)
group_id = models.ForeignKey(
group.Group, on_delete=models.CASCADE, null=True
)
count = models.IntegerField()
discount = models.DecimalField(
max_digits=10, decimal_places=2, null=True, blank=True
)
courier_product_id = models.ForeignKey(
to=courier_product.CourierProduct,
on_delete=models.CASCADE,
null=True,
blank=True,
)
order_id = models.ForeignKey(
order.Order, on_delete=models.CASCADE, related_name="order_items"
)
sale_type = models.CharField(max_length=10, choices=SALE_TYPE_CHOICES)
def __str__(self):
return f"Product - {self.group_id}, count - {self.count}"
class Meta:
verbose_name = "OrderItem"
verbose_name_plural = "OrderItems"
db_table = "order_item"

View File

@@ -0,0 +1,85 @@
"""
Party model
"""
from django.db import models
from django.db.models import Sum
from core.http.models import base
from core.http.models.user import User
class Party(base.AbstractBaseModel):
user_id = models.ForeignKey(
to=User, on_delete=models.CASCADE, related_name="parties"
)
# umumiy soni
count = models.IntegerField(default=0, null=True, blank=True)
# sotilgan soni
sold_count = models.IntegerField(default=0, null=True, blank=True)
# qolgan soni
remaining_count = models.IntegerField(default=0, null=True, blank=True)
# tushum
benefit = models.DecimalField(
max_digits=30, decimal_places=2, default=0, null=True, blank=True
)
# foyda
profit = models.DecimalField(
max_digits=30, decimal_places=2, default=0, null=True, blank=True
)
# partiya narxi
cost = models.DecimalField(
max_digits=30, decimal_places=2, default=0, null=True, blank=True
)
# umumiy narxi
total_cost = models.DecimalField(
max_digits=30, decimal_places=2, default=0, null=True, blank=True
)
broken_eggs = models.IntegerField(default=0, null=True, blank=True)
courier_eggs = models.IntegerField(default=0, null=True, blank=True)
@staticmethod
def get_total_benefit():
return Party.objects.aggregate(
total_count=Sum("count"), # umumiy mahsulot soni
total_sold_count=Sum(
"sold_count"
), # umumiy sotilgan mahsulot soni
total_remaining_count=Sum(
"remaining_count"
), # umumiy qolgan mahsulot soni
total_broken_eggs=Sum("broken_eggs"), # umumiy singan soni
total_courier_eggs=Sum(
"courier_eggs"
), # umumiy kuryerlar tomonidan olingan soni
)
def clean(self):
if self.count < 0:
raise ValueError("Count can't be negative")
if self.sold_count < 0:
raise ValueError("Sold count can't be negative")
if self.remaining_count < 0:
raise ValueError("Remaining count can't be negative")
if self.benefit < 0:
raise ValueError("Benefit can't be negative")
if self.cost < 0:
raise ValueError("Cost can't be negative")
if self.total_cost < 0:
raise ValueError("Total cost can't be negative")
def update_total_cost(self):
total_invoice_price = (
self.invoices.aggregate(Sum("price"))["price__sum"] or 0
)
self.total_cost = self.cost + total_invoice_price
self.profit -= total_invoice_price
self.save()
def __str__(self):
return f"User - {self.user_id}, price - {self.benefit}"
class Meta:
verbose_name = "Party"
verbose_name_plural = "Parties"
db_table = "party"

View File

@@ -0,0 +1,19 @@
"""
Product model
"""
from django.db import models
from core.http.models import base
class Product(base.AbstractBaseModel):
name = models.CharField(max_length=255)
def __str__(self):
return f"Product - {self.name}"
class Meta:
verbose_name = "Product"
verbose_name_plural = "Products"
db_table = "product"

View File

@@ -0,0 +1,17 @@
from django.db import models
from core.http.models import base
from core.http.models.user import User
class Sklad(base.AbstractBaseModel):
user_id = models.ForeignKey(
to=User, on_delete=models.CASCADE, related_name="sklad"
)
def __str__(self):
return f"Sklad - {self.user_id}"
class Meta:
verbose_name_plural = "Sklad"
db_table = "sklad"