Add username field to DCA clients: update database schema, CRUD operations, and UI components to support username functionality for improved user experience.

This commit is contained in:
padreug 2025-06-18 17:04:54 +02:00
parent 1d9cda3931
commit b615ed0504
5 changed files with 35 additions and 11 deletions

View file

@ -59,13 +59,14 @@ async def create_dca_client(data: CreateDcaClientData) -> DcaClient:
await db.execute( await db.execute(
""" """
INSERT INTO myextension.dca_clients INSERT INTO myextension.dca_clients
(id, user_id, wallet_id, dca_mode, fixed_mode_daily_limit, status, created_at, updated_at) (id, user_id, wallet_id, username, dca_mode, fixed_mode_daily_limit, status, created_at, updated_at)
VALUES (:id, :user_id, :wallet_id, :dca_mode, :fixed_mode_daily_limit, :status, :created_at, :updated_at) VALUES (:id, :user_id, :wallet_id, :username, :dca_mode, :fixed_mode_daily_limit, :status, :created_at, :updated_at)
""", """,
{ {
"id": client_id, "id": client_id,
"user_id": data.user_id, "user_id": data.user_id,
"wallet_id": data.wallet_id, "wallet_id": data.wallet_id,
"username": data.username,
"dca_mode": data.dca_mode, "dca_mode": data.dca_mode,
"fixed_mode_daily_limit": data.fixed_mode_daily_limit, "fixed_mode_daily_limit": data.fixed_mode_daily_limit,
"status": "active", "status": "active",

View file

@ -176,3 +176,15 @@ async def m008_add_last_poll_tracking(db):
ADD COLUMN last_successful_poll TIMESTAMP; ADD COLUMN last_successful_poll TIMESTAMP;
""" """
) )
async def m009_add_username_to_dca_clients(db):
"""
Add username field to DCA clients table for better user experience.
"""
await db.execute(
"""
ALTER TABLE myextension.dca_clients
ADD COLUMN username TEXT;
"""
)

View file

@ -10,6 +10,7 @@ from pydantic import BaseModel
class CreateDcaClientData(BaseModel): class CreateDcaClientData(BaseModel):
user_id: str user_id: str
wallet_id: str wallet_id: str
username: str
dca_mode: str = "flow" # 'flow' or 'fixed' dca_mode: str = "flow" # 'flow' or 'fixed'
fixed_mode_daily_limit: Optional[int] = None fixed_mode_daily_limit: Optional[int] = None
@ -18,6 +19,7 @@ class DcaClient(BaseModel):
id: str id: str
user_id: str user_id: str
wallet_id: str wallet_id: str
username: Optional[str]
dca_mode: str dca_mode: str
fixed_mode_daily_limit: Optional[int] fixed_mode_daily_limit: Optional[int]
status: str status: str
@ -26,6 +28,7 @@ class DcaClient(BaseModel):
class UpdateDcaClientData(BaseModel): class UpdateDcaClientData(BaseModel):
username: Optional[str] = None
dca_mode: Optional[str] = None dca_mode: Optional[str] = None
fixed_mode_daily_limit: Optional[int] = None fixed_mode_daily_limit: Optional[int] = None
status: Optional[str] = None status: Optional[str] = None

View file

@ -11,6 +11,7 @@ window.app = Vue.createApp({
// Table configurations // Table configurations
clientsTable: { clientsTable: {
columns: [ columns: [
{ name: 'username', align: 'left', label: 'Username', field: 'username' },
{ name: 'user_id', align: 'left', label: 'User ID', field: 'user_id' }, { name: 'user_id', align: 'left', label: 'User ID', field: 'user_id' },
{ name: 'wallet_id', align: 'left', label: 'Wallet ID', field: 'wallet_id' }, { name: 'wallet_id', align: 'left', label: 'Wallet ID', field: 'wallet_id' },
{ name: 'dca_mode', align: 'left', label: 'DCA Mode', field: 'dca_mode' }, { name: 'dca_mode', align: 'left', label: 'DCA Mode', field: 'dca_mode' },
@ -50,7 +51,7 @@ window.app = Vue.createApp({
// Quick deposit form // Quick deposit form
quickDepositForm: { quickDepositForm: {
client_id: '', selectedClient: null,
amount: null, amount: null,
notes: '' notes: ''
}, },
@ -230,6 +231,7 @@ window.app = Vue.createApp({
const testData = { const testData = {
user_id: this.g.user.id, user_id: this.g.user.id,
wallet_id: this.g.user.wallets[0].id, wallet_id: this.g.user.wallets[0].id,
username: this.g.user.username || `user_${this.g.user.id.substring(0, 8)}`,
dca_mode: 'flow' dca_mode: 'flow'
} }
@ -256,7 +258,7 @@ window.app = Vue.createApp({
async sendQuickDeposit() { async sendQuickDeposit() {
try { try {
const data = { const data = {
client_id: this.quickDepositForm.client_id, client_id: this.quickDepositForm.selectedClient?.value,
amount: this.quickDepositForm.amount, amount: this.quickDepositForm.amount,
currency: 'GTQ', currency: 'GTQ',
notes: this.quickDepositForm.notes notes: this.quickDepositForm.notes
@ -273,7 +275,7 @@ window.app = Vue.createApp({
// Reset form // Reset form
this.quickDepositForm = { this.quickDepositForm = {
client_id: '', selectedClient: null,
amount: null, amount: null,
notes: '' notes: ''
} }
@ -320,7 +322,7 @@ window.app = Vue.createApp({
addDepositDialog(client) { addDepositDialog(client) {
this.depositFormDialog.data = { this.depositFormDialog.data = {
client_id: client.id, client_id: client.id,
client_name: `${client.user_id.substring(0, 8)}...`, client_name: client.username || `${client.user_id.substring(0, 8)}...`,
currency: 'GTQ' currency: 'GTQ'
} }
this.depositFormDialog.show = true this.depositFormDialog.show = true
@ -712,7 +714,7 @@ window.app = Vue.createApp({
clientOptions() { clientOptions() {
return this.dcaClients.map(client => ({ return this.dcaClients.map(client => ({
label: `${client.user_id.substring(0, 8)}... (${client.dca_mode})`, label: `${client.username || client.user_id.substring(0, 8) + '...'} (${client.dca_mode})`,
value: client.id value: client.id
})) }))
}, },

View file

@ -43,7 +43,8 @@
<template v-slot:body="props"> <template v-slot:body="props">
<q-tr :props="props"> <q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props"> <q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.field == 'user_id'">${ col.value.substring(0, 8) }...</div> <div v-if="col.field == 'username'">${ col.value || 'No username' }</div>
<div v-else-if="col.field == 'user_id'">${ col.value.substring(0, 8) }...</div>
<div v-else-if="col.field == 'wallet_id'">${ col.value.substring(0, 8) }...</div> <div v-else-if="col.field == 'wallet_id'">${ col.value.substring(0, 8) }...</div>
<div v-else-if="col.field == 'status'"> <div v-else-if="col.field == 'status'">
<q-badge :color="col.value === 'active' ? 'green' : 'red'"> <q-badge :color="col.value === 'active' ? 'green' : 'red'">
@ -107,8 +108,7 @@
<q-select <q-select
filled filled
dense dense
emit-value v-model="quickDepositForm.selectedClient"
v-model="quickDepositForm.client_id"
:options="clientOptions" :options="clientOptions"
label="Select Client *" label="Select Client *"
option-label="label" option-label="label"
@ -131,7 +131,7 @@
unelevated unelevated
color="primary" color="primary"
type="submit" type="submit"
:disable="!quickDepositForm.client_id || !quickDepositForm.amount" :disable="!quickDepositForm.selectedClient || !quickDepositForm.amount"
>Add Deposit</q-btn >Add Deposit</q-btn
> >
</div> </div>
@ -462,6 +462,12 @@
<div class="text-h6 q-mb-md">Client Details</div> <div class="text-h6 q-mb-md">Client Details</div>
<div v-if="clientDetailsDialog.data"> <div v-if="clientDetailsDialog.data">
<q-list> <q-list>
<q-item v-if="clientDetailsDialog.data.username">
<q-item-section>
<q-item-label caption>Username</q-item-label>
<q-item-label>${ clientDetailsDialog.data.username }</q-item-label>
</q-item-section>
</q-item>
<q-item> <q-item>
<q-item-section> <q-item-section>
<q-item-label caption>User ID</q-item-label> <q-item-label caption>User ID</q-item-label>