up
This commit is contained in:
@@ -20,9 +20,10 @@ type PortalUser struct {
|
||||
ClienteID *uint `json:"cliente_id" gorm:"column:cliente_id;index"` // nil si es partner
|
||||
Cliente *Cliente `json:"cliente" gorm:"foreignKey:ClienteID"`
|
||||
Rol string `json:"rol" gorm:"column:rol;default:'cliente'"` // cliente|partner
|
||||
Activo bool `json:"activo" gorm:"column:activo;default:true"`
|
||||
Notas string `json:"notas" gorm:"column:notas;type:text"`
|
||||
PortalAccesos []PortalAcceso `json:"portal_accesos" gorm:"foreignKey:PortalUserID"`
|
||||
Activo bool `json:"activo" gorm:"column:activo;default:true"`
|
||||
Notas string `json:"notas" gorm:"column:notas;type:text"`
|
||||
TelegramChatID string `json:"telegram_chat_id" gorm:"column:telegram_chat_id"`
|
||||
PortalAccesos []PortalAcceso `json:"portal_accesos" gorm:"foreignKey:PortalUserID"`
|
||||
}
|
||||
|
||||
func (PortalUser) TableName() string { return "portal_users" }
|
||||
@@ -71,12 +72,13 @@ func CreatePortalUser(u *PortalUser) error {
|
||||
|
||||
func UpdatePortalUser(u *PortalUser) error {
|
||||
return app.Http.Database.DB.Model(&PortalUser{}).Where("id = ?", u.ID).Updates(map[string]interface{}{
|
||||
"nombre": u.Nombre,
|
||||
"email": u.Email,
|
||||
"cliente_id": u.ClienteID,
|
||||
"rol": u.Rol,
|
||||
"activo": u.Activo,
|
||||
"notas": u.Notas,
|
||||
"nombre": u.Nombre,
|
||||
"email": u.Email,
|
||||
"cliente_id": u.ClienteID,
|
||||
"rol": u.Rol,
|
||||
"activo": u.Activo,
|
||||
"notas": u.Notas,
|
||||
"telegram_chat_id": u.TelegramChatID,
|
||||
}).Error
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
<th class="px-4 py-3 text-left">Rol</th>
|
||||
<th class="px-4 py-3 text-left">Cliente / Accesos</th>
|
||||
<th class="px-4 py-3 text-left">Estado</th>
|
||||
<th class="px-4 py-3 text-left">Telegram</th>
|
||||
<th class="px-4 py-3 text-left">Acciones</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -54,6 +55,10 @@
|
||||
<td class="px-4 py-3">
|
||||
<span :class="u.activo ? 'badge-green' : 'badge-slate'" class="badge" x-text="u.activo ? 'Activo' : 'Inactivo'"></span>
|
||||
</td>
|
||||
<td class="px-4 py-3 text-slate-500 text-xs">
|
||||
<span x-show="u.telegram_chat_id" x-text="u.telegram_chat_id" class="font-mono"></span>
|
||||
<span x-show="!u.telegram_chat_id" class="text-slate-300">—</span>
|
||||
</td>
|
||||
<td class="px-4 py-3 flex gap-2">
|
||||
<button @click="openEdit(u)" class="btn-icon text-yellow-500" title="Editar">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/></svg>
|
||||
@@ -101,6 +106,7 @@
|
||||
<input type="checkbox" x-model="form.activo" class="w-4 h-4">
|
||||
</div>
|
||||
<div><label class="label">Notas</label><textarea x-model="form.notas" class="input-field w-full" rows="2"></textarea></div>
|
||||
<div><label class="label">Chat ID de Telegram</label><input x-model="form.telegram_chat_id" class="input-field w-full font-mono" placeholder="Ej: 123456789"><p class="text-xs text-slate-400 mt-1">Se usa para enviar notificaciones al usuario vía Telegram.</p></div>
|
||||
</div>
|
||||
<p x-show="error" x-text="error" class="text-red-500 text-sm mt-3"></p>
|
||||
<div class="flex justify-end gap-3 mt-5">
|
||||
@@ -150,7 +156,7 @@ function portalUsuariosApp() {
|
||||
showModal: false, showDelete: false, showAccesoModal: false,
|
||||
editId: null, deleteId: null, error: '',
|
||||
accesoUserId: null, accesoClienteId: '',
|
||||
form: { nombre:'', email:'', password:'', rol:'cliente', cliente_id:'', activo:true, notas:'' },
|
||||
form: { nombre:'', email:'', password:'', rol:'cliente', cliente_id:'', activo:true, notas:'', telegram_chat_id:'' },
|
||||
|
||||
async init() { await this.load(); },
|
||||
|
||||
@@ -165,12 +171,12 @@ function portalUsuariosApp() {
|
||||
|
||||
openCreate() {
|
||||
this.editId=null; this.error='';
|
||||
this.form={nombre:'',email:'',password:'',rol:'cliente',cliente_id:'',activo:true,notas:''};
|
||||
this.form={nombre:'',email:'',password:'',rol:'cliente',cliente_id:'',activo:true,notas:'',telegram_chat_id:''};
|
||||
this.showModal=true;
|
||||
},
|
||||
openEdit(u) {
|
||||
this.editId=u.ID; this.error='';
|
||||
this.form={nombre:u.nombre,email:u.email,password:'',rol:u.rol,cliente_id:u.cliente_id||'',activo:u.activo,notas:u.notas||''};
|
||||
this.form={nombre:u.nombre,email:u.email,password:'',rol:u.rol,cliente_id:u.cliente_id||'',activo:u.activo,notas:u.notas||'',telegram_chat_id:u.telegram_chat_id||''};
|
||||
this.showModal=true;
|
||||
},
|
||||
async save() {
|
||||
|
||||
@@ -40,12 +40,13 @@ func LoadPortalUsuarios(c *fiber.Ctx) error {
|
||||
|
||||
func CreatePortalUsuario(c *fiber.Ctx) error {
|
||||
type Req struct {
|
||||
Nombre string `json:"nombre"`
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
ClienteID *uint `json:"cliente_id"`
|
||||
Rol string `json:"rol"`
|
||||
Notas string `json:"notas"`
|
||||
Nombre string `json:"nombre"`
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
ClienteID *uint `json:"cliente_id"`
|
||||
Rol string `json:"rol"`
|
||||
Notas string `json:"notas"`
|
||||
TelegramChatID string `json:"telegram_chat_id"`
|
||||
}
|
||||
var req Req
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
@@ -62,13 +63,14 @@ func CreatePortalUsuario(c *fiber.Ctx) error {
|
||||
req.Rol = "cliente"
|
||||
}
|
||||
u := &models.PortalUser{
|
||||
Nombre: req.Nombre,
|
||||
Email: strings.ToLower(strings.TrimSpace(req.Email)),
|
||||
Password: hashed,
|
||||
ClienteID: req.ClienteID,
|
||||
Rol: req.Rol,
|
||||
Activo: true,
|
||||
Notas: req.Notas,
|
||||
Nombre: req.Nombre,
|
||||
Email: strings.ToLower(strings.TrimSpace(req.Email)),
|
||||
Password: hashed,
|
||||
ClienteID: req.ClienteID,
|
||||
Rol: req.Rol,
|
||||
Activo: true,
|
||||
Notas: req.Notas,
|
||||
TelegramChatID: req.TelegramChatID,
|
||||
}
|
||||
if err := models.CreatePortalUser(u); err != nil {
|
||||
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
|
||||
@@ -83,25 +85,27 @@ func UpdatePortalUsuario(c *fiber.Ctx) error {
|
||||
return c.Status(400).JSON(fiber.Map{"error": "ID inválido"})
|
||||
}
|
||||
type Req struct {
|
||||
Nombre string `json:"nombre"`
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
ClienteID *uint `json:"cliente_id"`
|
||||
Rol string `json:"rol"`
|
||||
Activo bool `json:"activo"`
|
||||
Notas string `json:"notas"`
|
||||
Nombre string `json:"nombre"`
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
ClienteID *uint `json:"cliente_id"`
|
||||
Rol string `json:"rol"`
|
||||
Activo bool `json:"activo"`
|
||||
Notas string `json:"notas"`
|
||||
TelegramChatID string `json:"telegram_chat_id"`
|
||||
}
|
||||
var req Req
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(400).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
u := &models.PortalUser{
|
||||
Nombre: req.Nombre,
|
||||
Email: strings.ToLower(strings.TrimSpace(req.Email)),
|
||||
ClienteID: req.ClienteID,
|
||||
Rol: req.Rol,
|
||||
Activo: req.Activo,
|
||||
Notas: req.Notas,
|
||||
Nombre: req.Nombre,
|
||||
Email: strings.ToLower(strings.TrimSpace(req.Email)),
|
||||
ClienteID: req.ClienteID,
|
||||
Rol: req.Rol,
|
||||
Activo: req.Activo,
|
||||
Notas: req.Notas,
|
||||
TelegramChatID: req.TelegramChatID,
|
||||
}
|
||||
u.ID = uint(id)
|
||||
if err := models.UpdatePortalUser(u); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user