diff --git a/config/conf/redis.py b/config/conf/redis.py index 9242bbc..cc7fa6e 100644 --- a/config/conf/redis.py +++ b/config/conf/redis.py @@ -19,6 +19,27 @@ CACHEOPS = { "ops": "all", "timeout": 60 * 5, }, + "company.*": { + "ops": "all", + "timeout": 60 * 5 + }, + "products.*": { + "ops": "all", + "timeout": 60 * 5 + }, + "projects.*": { + "ops": "all", + "timeout": 60 * 5 + }, + "wherehouse.*": { + "ops": "all", + "timeout": 60 * 5 + }, + "shared.*": { + "ops": "all", + "timeout": 60 * 5 + }, + } CACHEOPS_DEGRADE_ON_FAILURE = True CACHEOPS_ENABLED = False \ No newline at end of file diff --git a/config/settings/base.py b/config/settings/base.py index 729d807..6d0e12c 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -23,6 +23,9 @@ APPS = [ 'core.apps.accounts', 'core.apps.shared', 'core.apps.company', + 'core.apps.wherehouse', + 'core.apps.products', + 'core.apps.projects', ] PACKAGES = [ diff --git a/config/urls.py b/config/urls.py index a70a5dc..e832e4c 100644 --- a/config/urls.py +++ b/config/urls.py @@ -16,6 +16,9 @@ urlpatterns = [ path('accounts/', include('core.apps.accounts.urls')), path('company/', include('core.apps.company.urls')), path('shared/', include('core.apps.shared.urls')), + path('wherehouses/', include('core.apps.wherehouse.urls')), + path('projects/', include('core.apps.projects.urls')), + path('products/', include('core.apps.products.urls')), ] )), diff --git a/core/apps/__init__.py b/core/apps/products/__init__.py similarity index 100% rename from core/apps/__init__.py rename to core/apps/products/__init__.py diff --git a/core/apps/products/admin/__init__.py b/core/apps/products/admin/__init__.py new file mode 100644 index 0000000..610e401 --- /dev/null +++ b/core/apps/products/admin/__init__.py @@ -0,0 +1 @@ +from .product import * \ No newline at end of file diff --git a/core/apps/products/admin/product.py b/core/apps/products/admin/product.py new file mode 100644 index 0000000..dd97893 --- /dev/null +++ b/core/apps/products/admin/product.py @@ -0,0 +1,9 @@ +from django.contrib import admin + +from core.apps.products.models.product import Product + + +@admin.register(Product) +class ProductAdmin(admin.ModelAdmin): + list_display = ['name'] + search_fields = ['name'] \ No newline at end of file diff --git a/core/apps/products/apps.py b/core/apps/products/apps.py new file mode 100644 index 0000000..a0bac1d --- /dev/null +++ b/core/apps/products/apps.py @@ -0,0 +1,9 @@ +from django.apps import AppConfig + + +class ProductsConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'core.apps.products' + + def ready(self): + from . import admin \ No newline at end of file diff --git a/core/apps/products/migrations/0001_initial.py b/core/apps/products/migrations/0001_initial.py new file mode 100644 index 0000000..1763c31 --- /dev/null +++ b/core/apps/products/migrations/0001_initial.py @@ -0,0 +1,27 @@ +# Generated by Django 5.2.4 on 2025-08-01 11:42 + +import uuid +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Product', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('name', models.CharField(max_length=200)), + ], + options={ + 'verbose_name': 'Mahsulotlar', + }, + ), + ] diff --git a/core/apps/products/migrations/0002_alter_product_options.py b/core/apps/products/migrations/0002_alter_product_options.py new file mode 100644 index 0000000..8b4a06e --- /dev/null +++ b/core/apps/products/migrations/0002_alter_product_options.py @@ -0,0 +1,17 @@ +# Generated by Django 5.2.4 on 2025-08-01 14:37 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('products', '0001_initial'), + ] + + operations = [ + migrations.AlterModelOptions( + name='product', + options={'verbose_name': 'Mahsulot', 'verbose_name_plural': 'Mahsulotlar'}, + ), + ] diff --git a/core/apps/products/migrations/__init__.py b/core/apps/products/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/apps/products/models/__init__.py b/core/apps/products/models/__init__.py new file mode 100644 index 0000000..610e401 --- /dev/null +++ b/core/apps/products/models/__init__.py @@ -0,0 +1 @@ +from .product import * \ No newline at end of file diff --git a/core/apps/products/models/product.py b/core/apps/products/models/product.py new file mode 100644 index 0000000..7239ed7 --- /dev/null +++ b/core/apps/products/models/product.py @@ -0,0 +1,15 @@ +from django.db import models +from django.utils.translation import gettext_lazy as _ + +from core.apps.shared.models import BaseModel + + +class Product(BaseModel): + name = models.CharField(max_length=200) + + def __str__(self): + return self.name + + class Meta: + verbose_name = _('Mahsulot') + verbose_name_plural = _("Mahsulotlar") \ No newline at end of file diff --git a/core/apps/products/serializers/__init__.py b/core/apps/products/serializers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/apps/products/serializers/product.py b/core/apps/products/serializers/product.py new file mode 100644 index 0000000..586b418 --- /dev/null +++ b/core/apps/products/serializers/product.py @@ -0,0 +1,11 @@ +from rest_framework import serializers + +from core.apps.products.models import Product + + +class ProductListSerializer(serializers.ModelSerializer): + class Meta: + model = Product + fields = [ + 'id', 'name' + ] \ No newline at end of file diff --git a/core/apps/products/urls.py b/core/apps/products/urls.py new file mode 100644 index 0000000..e101b31 --- /dev/null +++ b/core/apps/products/urls.py @@ -0,0 +1,11 @@ +from django.urls import path, include + +from core.apps.products.views import product as product_views + +urlpatterns = [ + path('product/', include( + [ + path('list/', product_views.ProductListApiView.as_view()), + ] + )) +] \ No newline at end of file diff --git a/core/apps/products/views/__init__.py b/core/apps/products/views/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/apps/products/views/product.py b/core/apps/products/views/product.py new file mode 100644 index 0000000..180cec1 --- /dev/null +++ b/core/apps/products/views/product.py @@ -0,0 +1,13 @@ +from rest_framework import generics, status +from rest_framework.response import Response + +from core.apps.products.models.product import Product +from core.apps.products.serializers import product as serializers +from core.apps.accounts.permissions.permissions import HasRolePermission + + +class ProductListApiView(generics.ListAPIView): + serializer_class = serializers.ProductListSerializer + queryset = Product.objects.all() + permission_classes = [HasRolePermission] + required_permissions = [] \ No newline at end of file diff --git a/core/apps/projects/__init__.py b/core/apps/projects/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/apps/projects/admin/__init__.py b/core/apps/projects/admin/__init__.py new file mode 100644 index 0000000..e2ebdf8 --- /dev/null +++ b/core/apps/projects/admin/__init__.py @@ -0,0 +1 @@ +from .project import * \ No newline at end of file diff --git a/core/apps/projects/admin/project.py b/core/apps/projects/admin/project.py new file mode 100644 index 0000000..7939908 --- /dev/null +++ b/core/apps/projects/admin/project.py @@ -0,0 +1,21 @@ +from django.contrib import admin + +from core.apps.projects.models.project import ProjectDepartment, Project + + +class ProjectDepartmentInline(admin.TabularInline): + model = ProjectDepartment + extra = 0 + + +@admin.register(Project) +class ProjectAdmin(admin.ModelAdmin): + list_display = ['name', 'location', 'start_date', 'end_date'] + search_fields = ['name'] + inlines = [ProjectDepartmentInline] + + +@admin.register(ProjectDepartment) +class ProjectDepartmentAdmin(admin.ModelAdmin): + list_display = ['name', 'project'] + search_fields = ['name'] \ No newline at end of file diff --git a/core/apps/projects/apps.py b/core/apps/projects/apps.py new file mode 100644 index 0000000..a9587eb --- /dev/null +++ b/core/apps/projects/apps.py @@ -0,0 +1,9 @@ +from django.apps import AppConfig + + +class ProjectsConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'core.apps.projects' + + def ready(self): + from . import admin \ No newline at end of file diff --git a/core/apps/projects/migrations/0001_initial.py b/core/apps/projects/migrations/0001_initial.py new file mode 100644 index 0000000..a2ea21e --- /dev/null +++ b/core/apps/projects/migrations/0001_initial.py @@ -0,0 +1,46 @@ +# Generated by Django 5.2.4 on 2025-08-01 14:55 + +import django.db.models.deletion +import uuid +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Project', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('name', models.CharField(max_length=200)), + ('location', models.CharField(max_length=200)), + ('start_date', models.DateField()), + ('end_date', models.DateField()), + ], + options={ + 'verbose_name': 'Loyiha', + 'verbose_name_plural': 'Loyihalar', + }, + ), + migrations.CreateModel( + name='ProjectDepartment', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('name', models.CharField(max_length=200)), + ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='project_departments', to='projects.project')), + ], + options={ + 'verbose_name': "Loyiha Bo'limi", + 'verbose_name_plural': "Loyiha Bo'limlari", + }, + ), + ] diff --git a/core/apps/projects/migrations/__init__.py b/core/apps/projects/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/apps/projects/models/__init__.py b/core/apps/projects/models/__init__.py new file mode 100644 index 0000000..e2ebdf8 --- /dev/null +++ b/core/apps/projects/models/__init__.py @@ -0,0 +1 @@ +from .project import * \ No newline at end of file diff --git a/core/apps/projects/models/project.py b/core/apps/projects/models/project.py new file mode 100644 index 0000000..77ad2c2 --- /dev/null +++ b/core/apps/projects/models/project.py @@ -0,0 +1,32 @@ +from django.db import models +from django.utils.translation import gettext_lazy as _ + +from core.apps.shared.models import BaseModel + + +class Project(BaseModel): + name = models.CharField(max_length=200) + location = models.CharField(max_length=200) + start_date = models.DateField() + end_date = models.DateField() + + def __str__(self): + return self.name + + class Meta: + verbose_name = _('Loyiha') + verbose_name_plural = _('Loyihalar') + + +class ProjectDepartment(BaseModel): + project = models.ForeignKey( + Project, on_delete=models.CASCADE, related_name='project_departments' + ) + name = models.CharField(max_length=200) + + def __str__(self): + return self.name + + class Meta: + verbose_name = _("Loyiha Bo'limi") + verbose_name_plural = _("Loyiha Bo'limlari") \ No newline at end of file diff --git a/core/apps/projects/serializers/__init__.py b/core/apps/projects/serializers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/apps/projects/serializers/project.py b/core/apps/projects/serializers/project.py new file mode 100644 index 0000000..e238e48 --- /dev/null +++ b/core/apps/projects/serializers/project.py @@ -0,0 +1,29 @@ +from rest_framework import serializers + +from core.apps.projects.models.project import Project, ProjectDepartment + + +class ProjectDepartmentListSerializer(serializers.ModelSerializer): + class Meta: + model = ProjectDepartment + fields = [ + 'id', 'name' + ] + + +class ProjectListSerializer(serializers.ModelSerializer): + class Meta: + model = Project + fields = [ + 'id', 'name', 'location', 'start_date', 'end_date' + ] + + +class ProjectDetailSerialzier(serializers.ModelSerializer): + project_departments = ProjectDepartmentListSerializer(many=True) + + class Meta: + model = Project + fields = [ + 'id', 'name', 'location', 'start_date', 'end_date', 'project_departments' + ] \ No newline at end of file diff --git a/core/apps/projects/urls.py b/core/apps/projects/urls.py new file mode 100644 index 0000000..4baf941 --- /dev/null +++ b/core/apps/projects/urls.py @@ -0,0 +1,12 @@ +from django.urls import path, include + +from core.apps.projects.views import project as project_views + +urlpatterns = [ + path('project/', include( + [ + path('list/', project_views.ProjectListApiView.as_view()), + path('/', project_views.ProjectDetailApiView.as_view()), + ] + )) +] \ No newline at end of file diff --git a/core/apps/projects/views/__init__.py b/core/apps/projects/views/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/apps/projects/views/project.py b/core/apps/projects/views/project.py new file mode 100644 index 0000000..d4048b9 --- /dev/null +++ b/core/apps/projects/views/project.py @@ -0,0 +1,21 @@ +from rest_framework import generics, status +from rest_framework.response import Response + +from core.apps.projects.models.project import Project, ProjectDepartment +from core.apps.projects.serializers import project as serializers +from core.apps.accounts.permissions.permissions import HasRolePermission + + +class ProjectListApiView(generics.ListAPIView): + serializer_class = serializers.ProjectListSerializer + queryset = Project.objects.all() + permission_classes = [HasRolePermission] + required_permissions = [] + + +class ProjectDetailApiView(generics.RetrieveAPIView): + serializer_class = serializers.ProjectDetailSerialzier + queryset = Project.objects.prefetch_related('project_departments') + permission_classes = [HasRolePermission] + required_permissions = [] + lookup_field = 'id' \ No newline at end of file diff --git a/core/apps/wherehouse/__init__.py b/core/apps/wherehouse/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/apps/wherehouse/admin/__init__.py b/core/apps/wherehouse/admin/__init__.py new file mode 100644 index 0000000..0a68aae --- /dev/null +++ b/core/apps/wherehouse/admin/__init__.py @@ -0,0 +1,3 @@ +from .wherehouse import * +from .inventory import * +from .stock_movement import * \ No newline at end of file diff --git a/core/apps/wherehouse/admin/inventory.py b/core/apps/wherehouse/admin/inventory.py new file mode 100644 index 0000000..d534a0d --- /dev/null +++ b/core/apps/wherehouse/admin/inventory.py @@ -0,0 +1,9 @@ +from django.contrib import admin + +from core.apps.wherehouse.models.inventory import Inventory + + +@admin.register(Inventory) +class InventoryAdmin(admin.ModelAdmin): + list_display = ['quantity', 'wherehouse', 'product'] + \ No newline at end of file diff --git a/core/apps/wherehouse/admin/stock_movement.py b/core/apps/wherehouse/admin/stock_movement.py new file mode 100644 index 0000000..ecce23c --- /dev/null +++ b/core/apps/wherehouse/admin/stock_movement.py @@ -0,0 +1,8 @@ +from django.contrib import admin + +from core.apps.wherehouse.models.stock_movemend import StockMovemend + + +@admin.register(StockMovemend) +class StockMovemendAdmin(admin.ModelAdmin): + list_display = ['wherehouse_to', 'wherehouse_from', 'product', 'quantity', 'movemend_type'] \ No newline at end of file diff --git a/core/apps/wherehouse/admin/wherehouse.py b/core/apps/wherehouse/admin/wherehouse.py new file mode 100644 index 0000000..502fc29 --- /dev/null +++ b/core/apps/wherehouse/admin/wherehouse.py @@ -0,0 +1,10 @@ +from django.contrib import admin + +from core.apps.wherehouse.models.wherehouse import WhereHouse + + +@admin.register(WhereHouse) +class WhereHouseAdmin(admin.ModelAdmin): + list_display = ['name', 'address', 'branch'] + search_fields = ['name', 'address'] + list_filter = ['branch'] \ No newline at end of file diff --git a/core/apps/wherehouse/apps.py b/core/apps/wherehouse/apps.py new file mode 100644 index 0000000..8fad9aa --- /dev/null +++ b/core/apps/wherehouse/apps.py @@ -0,0 +1,9 @@ +from django.apps import AppConfig + + +class WherehouseConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'core.apps.wherehouse' + + def ready(self): + from . import admin \ No newline at end of file diff --git a/core/apps/wherehouse/migrations/0001_initial.py b/core/apps/wherehouse/migrations/0001_initial.py new file mode 100644 index 0000000..a0efa6b --- /dev/null +++ b/core/apps/wherehouse/migrations/0001_initial.py @@ -0,0 +1,48 @@ +# Generated by Django 5.2.4 on 2025-08-01 11:42 + +import django.db.models.deletion +import uuid +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('company', '0002_rename_barnch_branch'), + ('products', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='WhereHouse', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('name', models.CharField(max_length=200)), + ('address', models.CharField(max_length=200)), + ('branch', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='wherehouses', to='company.branch')), + ], + options={ + 'verbose_name': 'omborxona', + 'verbose_name_plural': 'omborxonalar', + }, + ), + migrations.CreateModel( + name='Inventory', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('quantity', models.PositiveIntegerField(default=0)), + ('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='inventories', to='products.product')), + ('wherehouse', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='inventories', to='wherehouse.wherehouse')), + ], + options={ + 'verbose_name': 'inventar', + 'verbose_name_plural': 'inventarlar', + }, + ), + ] diff --git a/core/apps/wherehouse/migrations/0002_stockmovemend.py b/core/apps/wherehouse/migrations/0002_stockmovemend.py new file mode 100644 index 0000000..953bb14 --- /dev/null +++ b/core/apps/wherehouse/migrations/0002_stockmovemend.py @@ -0,0 +1,33 @@ +# Generated by Django 5.2.4 on 2025-08-01 14:37 + +import django.db.models.deletion +import uuid +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('products', '0002_alter_product_options'), + ('wherehouse', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='StockMovemend', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('quantity', models.PositiveIntegerField(default=0)), + ('movemend_type', models.CharField(choices=[('IN', 'in'), ('OUT', 'out'), ('TRANSFER', 'transfer')], max_length=20)), + ('product', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='stocks', to='products.product')), + ('wherehouse_from', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='stocks_from', to='wherehouse.wherehouse')), + ('wherehouse_to', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='stocks_to', to='wherehouse.wherehouse')), + ], + options={ + 'verbose_name': 'Mahsulotlarni kochirish', + 'verbose_name_plural': 'Mahsulotlarni kochirish', + }, + ), + ] diff --git a/core/apps/wherehouse/migrations/__init__.py b/core/apps/wherehouse/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/apps/wherehouse/models/__init__.py b/core/apps/wherehouse/models/__init__.py new file mode 100644 index 0000000..e75ed97 --- /dev/null +++ b/core/apps/wherehouse/models/__init__.py @@ -0,0 +1,3 @@ +from .inventory import * +from .wherehouse import * +from .stock_movemend import * \ No newline at end of file diff --git a/core/apps/wherehouse/models/inventory.py b/core/apps/wherehouse/models/inventory.py new file mode 100644 index 0000000..d0e2b7c --- /dev/null +++ b/core/apps/wherehouse/models/inventory.py @@ -0,0 +1,20 @@ +from django.db import models +from django.utils.translation import gettext_lazy as _ + +from core.apps.shared.models import BaseModel +from core.apps.wherehouse.models.wherehouse import WhereHouse +from core.apps.products.models.product import Product + + +class Inventory(BaseModel): + wherehouse = models.ForeignKey(WhereHouse, on_delete=models.CASCADE, related_name='inventories') + quantity = models.PositiveIntegerField(default=0) + product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='inventories') + + def __str__(self): + return f'{self.product} in {self.wherehouse}' + + class Meta: + verbose_name = _('inventar') + verbose_name_plural = _("inventarlar") + \ No newline at end of file diff --git a/core/apps/wherehouse/models/stock_movemend.py b/core/apps/wherehouse/models/stock_movemend.py new file mode 100644 index 0000000..c43acd3 --- /dev/null +++ b/core/apps/wherehouse/models/stock_movemend.py @@ -0,0 +1,33 @@ +from django.db import models +from django.utils.translation import gettext_lazy as _ + +from core.apps.shared.models import BaseModel +from core.apps.wherehouse.models.wherehouse import WhereHouse +from core.apps.products.models.product import Product + + +class StockMovemend(BaseModel): + TYPE = ( + ('IN', 'in'), + ('OUT', 'out'), + ('TRANSFER', 'transfer'), + ) + + wherehouse_to = models.ForeignKey( + WhereHouse, on_delete=models.CASCADE, related_name='stocks_to' + ) + wherehouse_from = models.ForeignKey( + WhereHouse, on_delete=models.CASCADE, related_name='stocks_from' + ) + product = models.ForeignKey( + Product, on_delete=models.CASCADE, related_name='stocks' + ) + quantity = models.PositiveIntegerField(default=0) + movemend_type = models.CharField(max_length=20, choices=TYPE) + + def __str__(self): + return f'{self.product} send from {self.wherehouse_from} to {self.wherehouse_to}' + + class Meta: + verbose_name = _('Mahsulotlarni kochirish') + verbose_name_plural = _('Mahsulotlarni kochirish') diff --git a/core/apps/wherehouse/models/wherehouse.py b/core/apps/wherehouse/models/wherehouse.py new file mode 100644 index 0000000..1ec1775 --- /dev/null +++ b/core/apps/wherehouse/models/wherehouse.py @@ -0,0 +1,18 @@ +from django.db import models +from django.utils.translation import gettext_lazy as _ + +from core.apps.shared.models import BaseModel +from core.apps.company.models.branch import Branch + + +class WhereHouse(BaseModel): + branch = models.ForeignKey(Branch, on_delete=models.CASCADE, related_name='wherehouses') + name = models.CharField(max_length=200) + address = models.CharField(max_length=200) + + def __str__(self): + return self.name + + class Meta: + verbose_name = _('omborxona') + verbose_name_plural = _('omborxonalar') \ No newline at end of file diff --git a/core/apps/wherehouse/serializers/__init__.py b/core/apps/wherehouse/serializers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/apps/wherehouse/serializers/inventory.py b/core/apps/wherehouse/serializers/inventory.py new file mode 100644 index 0000000..c7f03af --- /dev/null +++ b/core/apps/wherehouse/serializers/inventory.py @@ -0,0 +1,11 @@ +from rest_framework import serializers + +from core.apps.wherehouse.models.inventory import Inventory + + +class WhereHouseInventoryListSerializer(serializers.ModelSerializer): + class Meta: + model = Inventory + fields = [ + 'id', 'quantity', 'product' + ] \ No newline at end of file diff --git a/core/apps/wherehouse/serializers/wherehouse.py b/core/apps/wherehouse/serializers/wherehouse.py new file mode 100644 index 0000000..1fde238 --- /dev/null +++ b/core/apps/wherehouse/serializers/wherehouse.py @@ -0,0 +1,27 @@ +from rest_framework import serializers + +from core.apps.wherehouse.models.wherehouse import WhereHouse +from core.apps.wherehouse.serializers.inventory import WhereHouseInventoryListSerializer +from core.apps.company.serializers.branch import BranchListSerializer + + +class WhereHouseListSerializer(serializers.ModelSerializer): + branch = BranchListSerializer() + + class Meta: + model = WhereHouse + fields = [ + 'id', 'name', 'address', 'branch' + ] + + +class WhereHouseDetailSerializer(serializers.ModelSerializer): + branch = BranchListSerializer() + inventories = WhereHouseInventoryListSerializer(many=True) + + class Meta: + model = WhereHouse + fields = [ + 'id', 'name', 'address', 'branch', 'inventories' + ] + diff --git a/core/apps/wherehouse/urls.py b/core/apps/wherehouse/urls.py new file mode 100644 index 0000000..cba1e0f --- /dev/null +++ b/core/apps/wherehouse/urls.py @@ -0,0 +1,13 @@ +from django.urls import path, include + +from core.apps.wherehouse.views import wherehouse as wherehouse_views + + +urlpatterns = [ + path('wherehouse/', include( + [ + path('list/', wherehouse_views.WhereHouseListApiView.as_view()), + path('/', wherehouse_views.WhereHouseDetailApiView.as_view()), + ] + )) +] \ No newline at end of file diff --git a/core/apps/wherehouse/views/__init__.py b/core/apps/wherehouse/views/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/apps/wherehouse/views/wherehouse.py b/core/apps/wherehouse/views/wherehouse.py new file mode 100644 index 0000000..aa474b9 --- /dev/null +++ b/core/apps/wherehouse/views/wherehouse.py @@ -0,0 +1,21 @@ +from rest_framework import generics, status +from rest_framework.response import Response + +from core.apps.wherehouse.models import WhereHouse, Inventory +from core.apps.wherehouse.serializers import wherehouse as serializers +from core.apps.accounts.permissions.permissions import HasRolePermission + + +class WhereHouseListApiView(generics.ListAPIView): + serializer_class = serializers.WhereHouseListSerializer + queryset = WhereHouse.objects.select_related('branch') + permission_classes = [HasRolePermission] + required_permissions = [] + + +class WhereHouseDetailApiView(generics.RetrieveAPIView): + serializer_class = serializers.WhereHouseDetailSerializer + queryset = WhereHouse.objects.select_related('branch').prefetch_related('inventories') + permission_classes = [HasRolePermission] + required_permissions = [] + lookup_field = 'id'