Tres conflictos en frontend, todos por adiciones en el mismo punto: - crm/types.ts y sidebar/modules.ts: se conservan las dos partes. - crm/AccountFields.svelte: main pasó toda la pestaña fiscal a selects de crmCatalogs. Régimen fiscal y uso de CFDI se quedan con los catálogos del SAT (tax_regime_id / cfdi_use_id), que son las claves que viajan en el CFDI y que el PAC valida contra c_RegimenFiscal y c_UsoCFDI; el catálogo configurable del CRM no las garantiza. Método de pago, forma de pago y moneda sí toman la versión de main. Las tres resoluciones son idénticas a las de feature/AS-timbrado-cfdi-ingreso, donde este mismo merge ya se resolvió y se verificó, para que las dos ramas no diverjan de criterio. Además, un choque que git no detecta: las dos ramas salieron de d5e6f7a8b9c0 y crearon una migración con el mismo id, e6f7a8b9c0d1 —catálogos SAT aquí, catalog_items del CRM en main—. Los archivos se llaman distinto, así que el merge pasa limpio y el problema sólo aparece al arrancar Alembic, con la revisión duplicada y dos cabezas. Se renumera la de facturación a g1h2i3j4k5l6 y se encadena detrás del carril EFC (c5d6e7f8a9b0). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
105 lines
4.6 KiB
Python
105 lines
4.6 KiB
Python
from datetime import datetime
|
|
from decimal import Decimal
|
|
|
|
from pydantic import BaseModel, ConfigDict, EmailStr, Field
|
|
|
|
|
|
class AccountBase(BaseModel):
|
|
# Datos generales
|
|
name: str = Field(..., min_length=1, max_length=255)
|
|
trade_name: str | None = Field(None, max_length=255)
|
|
rfc: str | None = Field(None, max_length=13)
|
|
curp: str | None = Field(None, max_length=18)
|
|
record_type: str = Field("cliente", max_length=20) # cliente | prospecto
|
|
person_type: str | None = Field(None, max_length=10) # fisica | moral
|
|
industry: str | None = Field(None, max_length=120)
|
|
industry_other: str | None = Field(None, max_length=120)
|
|
account_type: str | None = Field(None, max_length=40)
|
|
status: str = Field("active", max_length=20) # active | inactive
|
|
# Comercial
|
|
commercial_classification: str | None = Field(None, max_length=20)
|
|
preferred_contact_method: str | None = Field(None, max_length=20)
|
|
preferred_contact_other: str | None = Field(None, max_length=120)
|
|
language: str | None = Field(None, max_length=40)
|
|
email: EmailStr | None = None
|
|
phone: str | None = Field(None, max_length=40)
|
|
website: str | None = Field(None, max_length=255)
|
|
commercial_observations: str | None = None # observaciones generales
|
|
# Fiscal
|
|
tax_regime: str | None = Field(None, max_length=120)
|
|
cfdi_use: str | None = Field(None, max_length=60)
|
|
# Claves contra los catálogos del SAT; sustituyen al texto libre de arriba al timbrar.
|
|
tax_regime_id: int | None = Field(None, description="c_RegimenFiscal del receptor")
|
|
cfdi_use_id: int | None = Field(None, description="c_UsoCFDI del receptor")
|
|
payment_method: str | None = Field(None, max_length=60)
|
|
payment_form: str | None = Field(None, max_length=60)
|
|
currency: str | None = Field(None, max_length=3)
|
|
credit_limit: Decimal | None = Field(None, ge=0, max_digits=14, decimal_places=2)
|
|
credit_days: int | None = Field(None, ge=0)
|
|
commercial_terms: str | None = None
|
|
# Aduanero / ubicación
|
|
patente_aduanal: str | None = Field(None, max_length=20)
|
|
address: str | None = None
|
|
city: str | None = Field(None, max_length=120)
|
|
state: str | None = Field(None, max_length=120)
|
|
country: str | None = Field("MEX", max_length=3)
|
|
# Observaciones
|
|
notes: str | None = None
|
|
internal_notes: str | None = None
|
|
owner_user_id: str | None = Field(None, max_length=64)
|
|
|
|
|
|
class AccountCreate(AccountBase):
|
|
pass
|
|
|
|
|
|
class AccountUpdate(BaseModel):
|
|
name: str | None = Field(None, min_length=1, max_length=255)
|
|
trade_name: str | None = Field(None, max_length=255)
|
|
rfc: str | None = Field(None, max_length=13)
|
|
curp: str | None = Field(None, max_length=18)
|
|
record_type: str | None = Field(None, max_length=20)
|
|
person_type: str | None = Field(None, max_length=10)
|
|
industry: str | None = Field(None, max_length=120)
|
|
industry_other: str | None = Field(None, max_length=120)
|
|
account_type: str | None = Field(None, max_length=40)
|
|
status: str | None = Field(None, max_length=20)
|
|
commercial_classification: str | None = Field(None, max_length=20)
|
|
preferred_contact_method: str | None = Field(None, max_length=20)
|
|
preferred_contact_other: str | None = Field(None, max_length=120)
|
|
language: str | None = Field(None, max_length=40)
|
|
email: EmailStr | None = None
|
|
phone: str | None = Field(None, max_length=40)
|
|
website: str | None = Field(None, max_length=255)
|
|
commercial_observations: str | None = None
|
|
tax_regime: str | None = Field(None, max_length=120)
|
|
cfdi_use: str | None = Field(None, max_length=60)
|
|
tax_regime_id: int | None = None
|
|
cfdi_use_id: int | None = None
|
|
payment_method: str | None = Field(None, max_length=60)
|
|
payment_form: str | None = Field(None, max_length=60)
|
|
currency: str | None = Field(None, max_length=3)
|
|
credit_limit: Decimal | None = Field(None, ge=0, max_digits=14, decimal_places=2)
|
|
credit_days: int | None = Field(None, ge=0)
|
|
commercial_terms: str | None = None
|
|
patente_aduanal: str | None = Field(None, max_length=20)
|
|
address: str | None = None
|
|
city: str | None = Field(None, max_length=120)
|
|
state: str | None = Field(None, max_length=120)
|
|
country: str | None = Field(None, max_length=3)
|
|
notes: str | None = None
|
|
internal_notes: str | None = None
|
|
owner_user_id: str | None = Field(None, max_length=64)
|
|
|
|
|
|
class AccountResponse(AccountBase):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: int
|
|
tenant_id: int
|
|
company_id: int
|
|
created_by: str | None = None
|
|
updated_by: str | None = None
|
|
created_at: datetime
|
|
updated_at: datetime
|