feat: cuentas por cobrar usa listado de clientes en vez de entidades contables
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
daf0b2c2a1
commit
6e281dfbda
@@ -61,8 +61,10 @@ func (Transaccion) TableName() string { return "contab_transacciones" }
|
||||
|
||||
type CuentaCobro struct {
|
||||
gorm.Model
|
||||
EntidadID uint `json:"entidad_id" gorm:"column:entidad_id;index;not null"`
|
||||
Entidad Entidad `json:"entidad" gorm:"foreignKey:EntidadID"`
|
||||
ClienteID uint `json:"cliente_id" gorm:"column:cliente_id;index;not null"`
|
||||
Cliente Cliente `json:"cliente" gorm:"foreignKey:ClienteID"`
|
||||
EntidadID *uint `json:"entidad_id" gorm:"column:entidad_id;index"`
|
||||
Entidad *Entidad `json:"entidad" gorm:"foreignKey:EntidadID"`
|
||||
Fecha time.Time `json:"fecha" gorm:"column:fecha;not null"`
|
||||
Descripcion string `json:"descripcion" gorm:"column:descripcion;type:text"`
|
||||
Valor float64 `json:"valor" gorm:"column:valor;not null"`
|
||||
@@ -260,11 +262,11 @@ func DeleteTransaccion(id uint) error {
|
||||
func GetAllCuentasCobro(limit, offset int, search string, estado string) ([]CuentaCobro, int64, error) {
|
||||
var items []CuentaCobro
|
||||
var total int64
|
||||
db := app.Http.Database.DB.Model(&CuentaCobro{}).Preload("Entidad").Preload("Transaccion")
|
||||
db := app.Http.Database.DB.Model(&CuentaCobro{}).Preload("Cliente").Preload("Entidad").Preload("Transaccion")
|
||||
if search != "" {
|
||||
db = db.Joins("JOIN contab_entidades ON contab_entidades.id = contab_cuentas_cobro.entidad_id").
|
||||
Where("contab_entidades.nombre ILIKE ? OR contab_cuentas_cobro.descripcion ILIKE ?",
|
||||
"%"+search+"%", "%"+search+"%")
|
||||
db = db.Joins("JOIN clientes ON clientes.id = contab_cuentas_cobro.cliente_id").
|
||||
Where("clientes.nombre ILIKE ? OR clientes.empresa ILIKE ? OR contab_cuentas_cobro.descripcion ILIKE ?",
|
||||
"%"+search+"%", "%"+search+"%", "%"+search+"%")
|
||||
}
|
||||
if estado != "" {
|
||||
db = db.Where("contab_cuentas_cobro.estado = ?", estado)
|
||||
@@ -463,10 +465,7 @@ func CreateCuentaCobro(cc *CuentaCobro) error {
|
||||
|
||||
func UpdateCuentaCobro(cc *CuentaCobro) error {
|
||||
return app.Http.Database.DB.Model(&CuentaCobro{}).Where("id = ?", cc.ID).Updates(map[string]interface{}{
|
||||
"entidad_id": cc.EntidadID,
|
||||
"fecha": cc.Fecha,
|
||||
"descripcion": cc.Descripcion,
|
||||
"valor": cc.Valor,
|
||||
"cliente_id": cc.ClienteID,
|
||||
"estado": cc.Estado,
|
||||
"fecha_vencimiento": cc.FechaVencimiento,
|
||||
"fecha_pago": cc.FechaPago,
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<thead class="bg-slate-50 text-slate-500 text-xs uppercase tracking-wide">
|
||||
<tr>
|
||||
<th class="px-4 py-3 text-left">Fecha</th>
|
||||
<th class="px-4 py-3 text-left">Entidad</th>
|
||||
<th class="px-4 py-3 text-left">Cliente</th>
|
||||
<th class="px-4 py-3 text-left">Descripción</th>
|
||||
<th class="px-4 py-3 text-right">Valor</th>
|
||||
<th class="px-4 py-3 text-left">Vence</th>
|
||||
@@ -41,7 +41,7 @@
|
||||
<template x-for="c in items" :key="c.ID">
|
||||
<tr class="hover:bg-slate-50">
|
||||
<td class="px-4 py-3 text-xs text-slate-500" x-text="formatDate(c.fecha)"></td>
|
||||
<td class="px-4 py-3 text-slate-700 font-medium" x-text="c.entidad?.nombre||'-'"></td>
|
||||
<td class="px-4 py-3 text-slate-700 font-medium" x-text="c.cliente?.nombre||'-'"></td>
|
||||
<td class="px-4 py-3 text-slate-600" x-text="c.descripcion"></td>
|
||||
<td class="px-4 py-3 text-right font-semibold text-amber-600" x-text="formatoCOP(c.valor)"></td>
|
||||
<td class="px-4 py-3 text-xs text-slate-500" x-text="formatDate(c.fecha_vencimiento)"></td>
|
||||
@@ -80,11 +80,11 @@
|
||||
<form @submit.prevent="save()">
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<div class="col-span-2">
|
||||
<label class="label">Entidad (quien debe)</label>
|
||||
<select x-model.number="form.entidad_id" class="input-field w-full" required>
|
||||
<label class="label">Cliente (quien debe)</label>
|
||||
<select x-model.number="form.cliente_id" class="input-field w-full" required>
|
||||
<option value="">Seleccionar...</option>
|
||||
<template x-for="e in entidades" :key="e.ID">
|
||||
<option :value="e.ID" x-text="e.nombre"></option>
|
||||
<template x-for="cl in clientes" :key="cl.ID">
|
||||
<option :value="cl.ID" x-text="cl.nombre + (cl.empresa ? ' — ' + cl.empresa : '')"></option>
|
||||
</template>
|
||||
</select>
|
||||
</div>
|
||||
@@ -149,10 +149,10 @@
|
||||
<script>
|
||||
function cobroApp() {
|
||||
return {
|
||||
items:[], entidades:[], total:0, totalPages:1, page:1, search:'', filtroEstado:'',
|
||||
items:[], clientes:[], total:0, totalPages:1, page:1, search:'', filtroEstado:'',
|
||||
loading:false, saving:false, showModal:false, showDelete:false, showPagarModal:false,
|
||||
deleteId:null, pagarId:null, pagoFecha:'', error:'',
|
||||
form:{ entidad_id:'', descripcion:'', valor:0, fecha:'', fecha_vencimiento:'', notas:'' },
|
||||
form:{ cliente_id:'', descripcion:'', valor:0, fecha:'', fecha_vencimiento:'', notas:'' },
|
||||
|
||||
async init(){ await this.load(); },
|
||||
|
||||
@@ -163,12 +163,12 @@ function cobroApp() {
|
||||
if(this.filtroEstado) params.set('estado',this.filtroEstado);
|
||||
const r=await axios.get('/app/contabilidad/cuentas-cobro/list?'+params.toString());
|
||||
this.items=r.data.items; this.total=r.data.total; this.totalPages=r.data.totalPages;
|
||||
const er=await axios.get('/app/contabilidad/entidades/select');
|
||||
this.entidades=er.data;
|
||||
const er=await axios.get('/app/api/clientes/select');
|
||||
this.clientes=er.data;
|
||||
} finally{ this.loading=false; }
|
||||
},
|
||||
|
||||
openCreate(){ this.editId=null; this.error=''; this.form={entidad_id:'',descripcion:'',valor:0,fecha:'',fecha_vencimiento:'',notas:''}; this.showModal=true; },
|
||||
openCreate(){ this.editId=null; this.error=''; this.form={cliente_id:'',descripcion:'',valor:0,fecha:'',fecha_vencimiento:'',notas:''}; this.showModal=true; },
|
||||
async save(){
|
||||
this.saving=true; this.error='';
|
||||
try {
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<thead class="bg-slate-50 text-slate-500 text-xs uppercase tracking-wide">
|
||||
<tr>
|
||||
<th class="px-4 py-3 text-left">Fecha</th>
|
||||
<th class="px-4 py-3 text-left">Entidad</th>
|
||||
<th class="px-4 py-3 text-left">Cliente</th>
|
||||
<th class="px-4 py-3 text-left">Descripción</th>
|
||||
<th class="px-4 py-3 text-right">Valor</th>
|
||||
<th class="px-4 py-3 text-left">Vence</th>
|
||||
@@ -38,7 +38,7 @@
|
||||
<template x-for="c in items" :key="c.ID">
|
||||
<tr class="hover:bg-slate-50">
|
||||
<td class="px-4 py-3 text-xs text-slate-500" x-text="formatDate(c.fecha)"></td>
|
||||
<td class="px-4 py-3 text-slate-700 font-medium" x-text="c.entidad?.nombre||'-'"></td>
|
||||
<td class="px-4 py-3 text-slate-700 font-medium" x-text="c.cliente?.nombre||'-'"></td>
|
||||
<td class="px-4 py-3 text-slate-600" x-text="c.descripcion"></td>
|
||||
<td class="px-4 py-3 text-right font-semibold text-amber-600" x-text="formatoCOP(c.valor)"></td>
|
||||
<td class="px-4 py-3 text-xs text-slate-500" x-text="formatDate(c.fecha_vencimiento)"></td>
|
||||
@@ -73,11 +73,11 @@
|
||||
<form @submit.prevent="save()">
|
||||
<div class="grid grid-cols-2 gap-3">
|
||||
<div class="col-span-2">
|
||||
<label class="label">Entidad (quien debe)</label>
|
||||
<select x-model.number="form.entidad_id" class="input-field w-full" required>
|
||||
<label class="label">Cliente (quien debe)</label>
|
||||
<select x-model.number="form.cliente_id" class="input-field w-full" required>
|
||||
<option value="">Seleccionar...</option>
|
||||
<template x-for="e in entidades" :key="e.ID">
|
||||
<option :value="e.ID" x-text="e.nombre"></option>
|
||||
<template x-for="cl in clientes" :key="cl.ID">
|
||||
<option :value="cl.ID" x-text="cl.nombre + (cl.empresa ? ' — ' + cl.empresa : '')"></option>
|
||||
</template>
|
||||
</select>
|
||||
</div>
|
||||
@@ -141,10 +141,10 @@
|
||||
<script>
|
||||
function cobroApp() {
|
||||
return {
|
||||
items:[], entidades:[], total:0, totalPages:1, page:1, search:'', filtroEstado:'',
|
||||
items:[], clientes:[], total:0, totalPages:1, page:1, search:'', filtroEstado:'',
|
||||
loading:false, saving:false, showModal:false, showDelete:false, showPagarModal:false,
|
||||
deleteId:null, pagarId:null, pagoFecha:'', error:'',
|
||||
form:{ entidad_id:'', descripcion:'', valor:0, fecha:'', fecha_vencimiento:'', notas:'' },
|
||||
form:{ cliente_id:'', descripcion:'', valor:0, fecha:'', fecha_vencimiento:'', notas:'' },
|
||||
|
||||
async init(){ await this.load(); },
|
||||
|
||||
@@ -155,12 +155,12 @@ function cobroApp() {
|
||||
if(this.filtroEstado) params.set('estado',this.filtroEstado);
|
||||
const r=await axios.get('/app/contabilidad/cuentas-cobro/list?'+params.toString());
|
||||
this.items=r.data.items; this.total=r.data.total; this.totalPages=r.data.totalPages;
|
||||
const er=await axios.get('/app/contabilidad/entidades/select');
|
||||
this.entidades=er.data;
|
||||
const er=await axios.get('/app/api/clientes/select');
|
||||
this.clientes=er.data;
|
||||
} finally{ this.loading=false; }
|
||||
},
|
||||
|
||||
openCreate(){ this.editId=null; this.error=''; this.form={entidad_id:'',descripcion:'',valor:0,fecha:'',fecha_vencimiento:'',notas:''}; this.showModal=true; },
|
||||
openCreate(){ this.editId=null; this.error=''; this.form={cliente_id:'',descripcion:'',valor:0,fecha:'',fecha_vencimiento:'',notas:''}; this.showModal=true; },
|
||||
async save(){
|
||||
this.saving=true; this.error='';
|
||||
try {
|
||||
|
||||
@@ -408,7 +408,7 @@ func GetCuentasCobro(c *fiber.Ctx) error {
|
||||
|
||||
func CreateCuentaCobro(c *fiber.Ctx) error {
|
||||
type Req struct {
|
||||
EntidadID uint `json:"entidad_id"`
|
||||
ClienteID uint `json:"cliente_id"`
|
||||
Fecha string `json:"fecha"`
|
||||
Descripcion string `json:"descripcion"`
|
||||
Valor float64 `json:"valor"`
|
||||
@@ -419,11 +419,11 @@ func CreateCuentaCobro(c *fiber.Ctx) error {
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
if req.EntidadID == 0 {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "entidad_id es requerido"})
|
||||
if req.ClienteID == 0 {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "cliente_id es requerido"})
|
||||
}
|
||||
cc := &models.CuentaCobro{
|
||||
EntidadID: req.EntidadID,
|
||||
ClienteID: req.ClienteID,
|
||||
Descripcion: req.Descripcion,
|
||||
Valor: req.Valor,
|
||||
Estado: "pendiente",
|
||||
|
||||
Reference in New Issue
Block a user