refactor: organize code by domain-driven design
Refactoriza la estructura del proyecto siguiendo principios de Domain-Driven Design, organizando serializers, API views y servicios por dominios de negocio. Cambios principales: ## Serializers (serializers/) - Dividido serializers.py en módulos por dominio: * products.py: ProductSerializer, ListProductSerializer * customers.py: CustomerSerializer, ListCustomerSerializer * sales.py: SaleSerializer, SaleLineSerializer, CatalogSaleSerializer, etc. * payments.py: ReconciliationJarSerializer, PaymentMethodSerializer * __init__.py: Exporta todos los serializers para mantener compatibilidad ## API Views (api/) - Dividido api_views.py en módulos por dominio: * products.py: ProductView, ProductsFromTrytonView * customers.py: CustomerView, CustomersFromTrytonView * sales.py: SaleView, CatalogSaleView, SaleSummary, SalesForTrytonView, SalesToTrytonView * payments.py: ReconciliateJarView, ReconciliateJarModelView, PaymentMethodView, SalesForReconciliationView * admin.py: AdminCodeValidateView * __init__.py: Exporta todas las vistas para facilitar importaciones ## Services Layer (services/tryton/) - Nueva capa de servicios para lógica de negocio Tryton: * client.py: get_tryton_client(), TrytonSale, TrytonLineSale, configuración * products.py: ProductTrytonService - sincronización de productos * customers.py: CustomerTrytonService - sincronización de clientes * sales.py: SaleTrytonService - sincronización de ventas * __init__.py: Exporta servicios y utilidades ## Actualización de URLs - Actualizado urls.py para importar desde nuevos módulos - Mantiene todas las rutas existentes sin cambios ## Eliminación de archivos antiguos - Eliminado serializers.py (refactorizado a serializers/) - Eliminado api_views.py (refactorizado a api/) ## Beneficios ✅ Cohesión: Código organizado por dominio de negocio ✅ Separación de responsabilidades: API, Serializers y Services separados ✅ Mantenibilidad: Archivos más pequeños y enfocados ✅ Escalabilidad: Fácil agregar nuevos dominios ✅ Testabilidad: Mejor organización para pruebas por dominio ✅ Reutilización: Servicios Tryton pueden usarse desde cualquier vista ## Estructura final: - models/ (ya existía organizado por dominio) - serializers/ (nuevo, organizado por dominio) - api/ (nuevo, organizado por dominio) - services/tryton/ (nuevo, capa de servicios) Tests: 46 tests pasando ✓
This commit is contained in:
35
tienda_ilusion/don_confiao/serializers/__init__.py
Normal file
35
tienda_ilusion/don_confiao/serializers/__init__.py
Normal file
@@ -0,0 +1,35 @@
|
||||
from .products import ProductSerializer, ListProductSerializer
|
||||
from .customers import CustomerSerializer, ListCustomerSerializer
|
||||
from .sales import (
|
||||
SaleSerializer,
|
||||
SaleLineSerializer,
|
||||
CatalogSaleSerializer,
|
||||
CatalogSaleLineSerializer,
|
||||
SummarySaleLineSerializer,
|
||||
SaleSummarySerializer,
|
||||
SaleForRenconciliationSerializer,
|
||||
)
|
||||
from .payments import (
|
||||
ReconciliationJarSerializer,
|
||||
PaymentMethodSerializer,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
# Products
|
||||
"ProductSerializer",
|
||||
"ListProductSerializer",
|
||||
# Customers
|
||||
"CustomerSerializer",
|
||||
"ListCustomerSerializer",
|
||||
# Sales
|
||||
"SaleSerializer",
|
||||
"SaleLineSerializer",
|
||||
"CatalogSaleSerializer",
|
||||
"CatalogSaleLineSerializer",
|
||||
"SummarySaleLineSerializer",
|
||||
"SaleSummarySerializer",
|
||||
"SaleForRenconciliationSerializer",
|
||||
# Payments
|
||||
"ReconciliationJarSerializer",
|
||||
"PaymentMethodSerializer",
|
||||
]
|
||||
15
tienda_ilusion/don_confiao/serializers/customers.py
Normal file
15
tienda_ilusion/don_confiao/serializers/customers.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from ..models.customers import Customer
|
||||
|
||||
|
||||
class CustomerSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Customer
|
||||
fields = ["id", "name", "address", "email", "phone", "external_id"]
|
||||
|
||||
|
||||
class ListCustomerSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Customer
|
||||
fields = ["id", "name"]
|
||||
31
tienda_ilusion/don_confiao/serializers/payments.py
Normal file
31
tienda_ilusion/don_confiao/serializers/payments.py
Normal file
@@ -0,0 +1,31 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from ..models.payments import ReconciliationJar, PaymentMethods
|
||||
from .sales import SaleSerializer
|
||||
|
||||
|
||||
class ReconciliationJarSerializer(serializers.ModelSerializer):
|
||||
Sales = SaleSerializer(many=True, read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = ReconciliationJar
|
||||
fields = [
|
||||
"id",
|
||||
"date_time",
|
||||
"reconcilier",
|
||||
"cash_taken",
|
||||
"cash_discrepancy",
|
||||
"total_cash_purchases",
|
||||
"Sales",
|
||||
]
|
||||
|
||||
|
||||
class PaymentMethodSerializer(serializers.Serializer):
|
||||
text = serializers.CharField()
|
||||
value = serializers.CharField()
|
||||
|
||||
def to_representation(self, instance):
|
||||
return {
|
||||
"text": instance[1],
|
||||
"value": instance[0],
|
||||
}
|
||||
23
tienda_ilusion/don_confiao/serializers/products.py
Normal file
23
tienda_ilusion/don_confiao/serializers/products.py
Normal file
@@ -0,0 +1,23 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from ..models.products import Product, ProductCategory
|
||||
|
||||
|
||||
class ProductSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Product
|
||||
fields = [
|
||||
"id",
|
||||
"name",
|
||||
"active",
|
||||
"price",
|
||||
"measuring_unit",
|
||||
"categories",
|
||||
"external_id",
|
||||
]
|
||||
|
||||
|
||||
class ListProductSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Product
|
||||
fields = ["id", "name"]
|
||||
104
tienda_ilusion/don_confiao/serializers/sales.py
Normal file
104
tienda_ilusion/don_confiao/serializers/sales.py
Normal file
@@ -0,0 +1,104 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from ..models.sales import (
|
||||
Sale,
|
||||
SaleLine,
|
||||
CatalogSale,
|
||||
CatalogSaleLine,
|
||||
Payment,
|
||||
)
|
||||
from .products import ListProductSerializer
|
||||
from .customers import ListCustomerSerializer
|
||||
|
||||
|
||||
class SaleLineSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = SaleLine
|
||||
fields = ["id", "sale", "product", "unit_price", "quantity"]
|
||||
|
||||
|
||||
class SaleSerializer(serializers.ModelSerializer):
|
||||
total = serializers.ReadOnlyField(source="get_total")
|
||||
|
||||
class Meta:
|
||||
model = Sale
|
||||
fields = [
|
||||
"id",
|
||||
"customer",
|
||||
"date",
|
||||
"saleline_set",
|
||||
"total",
|
||||
"payment_method",
|
||||
"external_id",
|
||||
]
|
||||
|
||||
|
||||
class CatalogSaleLineSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = CatalogSaleLine
|
||||
read_only_fields = ["catalog_sale"]
|
||||
fields = [
|
||||
"id",
|
||||
"catalog_sale",
|
||||
"product",
|
||||
"unit_price",
|
||||
"quantity",
|
||||
]
|
||||
|
||||
|
||||
class CatalogSaleSerializer(serializers.ModelSerializer):
|
||||
catalogsaleline_set = CatalogSaleLineSerializer(many=True, required=False)
|
||||
total = serializers.ReadOnlyField(source="get_total")
|
||||
|
||||
class Meta:
|
||||
model = CatalogSale
|
||||
fields = [
|
||||
"id",
|
||||
"customer",
|
||||
"date",
|
||||
"catalogsaleline_set",
|
||||
"total",
|
||||
]
|
||||
|
||||
def create(self, validated_data):
|
||||
lines_data = validated_data.pop("catalogsaleline_set", [])
|
||||
catalog_sale = CatalogSale.objects.create(**validated_data)
|
||||
|
||||
for line_data in lines_data:
|
||||
CatalogSaleLine.objects.create(catalog_sale=catalog_sale, **line_data)
|
||||
|
||||
return catalog_sale
|
||||
|
||||
|
||||
class SummarySaleLineSerializer(serializers.ModelSerializer):
|
||||
product = ListProductSerializer()
|
||||
|
||||
class Meta:
|
||||
model = SaleLine
|
||||
fields = ["product", "quantity", "unit_price", "description"]
|
||||
|
||||
|
||||
class SaleSummarySerializer(serializers.ModelSerializer):
|
||||
customer = ListCustomerSerializer()
|
||||
lines = SummarySaleLineSerializer(many=True, source="saleline_set")
|
||||
|
||||
class Meta:
|
||||
model = Sale
|
||||
fields = ["id", "date", "customer", "payment_method", "lines"]
|
||||
|
||||
|
||||
class SaleForRenconciliationSerializer(serializers.Serializer):
|
||||
id = serializers.IntegerField()
|
||||
date = serializers.DateTimeField()
|
||||
payment_method = serializers.CharField()
|
||||
customer = serializers.SerializerMethodField()
|
||||
total = serializers.SerializerMethodField()
|
||||
|
||||
def get_customer(self, sale):
|
||||
return {
|
||||
"id": sale.customer.id,
|
||||
"name": sale.customer.name,
|
||||
}
|
||||
|
||||
def get_total(self, sale):
|
||||
return sale.get_total()
|
||||
Reference in New Issue
Block a user