CREATE TABLE "workgroups" (
"idx" INTEGER,
"name" TEXT NOT NULL UNIQUE,
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "users" (
"idx" INTEGER,
"name" TEXT NOT NULL UNIQUE,
"hash" TEXT,
"perm" INTEGER,
"active" INTEGER,
"expires" TEXT,
"wrkgrp" INTEGER,
"phone" TEXT,
"email" TEXT,
FOREIGN KEY("wrkgrp") REFERENCES "workgroups"("idx"),
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "states" (
"idx" INTEGER,
"name" TEXT NOT NULL UNIQUE,
"desc" TEXT,
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "countries" (
"idx" INTEGER,
"code2" TEXT NOT NULL UNIQUE,
"code3" TEXT NOT NULL UNIQUE,
"name" TEXT NOT NULL,
"nameiso" TEXT,
"capital" TEXT,
"remark" TEXT,
PRIMARY KEY("idx" AUTOINCREMENT)
);
INSERT INTO "countries" VALUES (1,'XX','XXX','None','','None','');
INSERT INTO "countries" VALUES (2,'KR','KRO','Kronos','','First City','');
INSERT INTO "countries" VALUES (3,'VK','VUL','Vulcan','','ShiKahr','');
CREATE TABLE IF NOT EXISTS "cities" (
"idx" INTEGER,
"name" TEXT NOT NULL UNIQUE,
"remark" TEXT,
"country" INTEGER,
FOREIGN KEY("country") REFERENCES "countries"("idx"),
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "contacts" (
"idx" INTEGER,
"name" TEXT NOT NULL UNIQUE,
"phone" TEXT,
"mobile" TEXT,
"email" TEXT,
"company" INTEGER,
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "owners" (
"idx" INTEGER,
"name" TEXT NOT NULL UNIQUE,
"alias" TEXT,
"title" TEXT,
"phone" TEXT,
"cell" TEXT,
"fax" TEXT,
"email" TEXT,
"logo" TEXT,
"address" TEXT,
"country" INTEGER,
"city" INTEGER,
FOREIGN KEY("country") REFERENCES "countries"("idx"),
FOREIGN KEY("city") REFERENCES "cities"("idx"),
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "customers" (
"idx" INTEGER,
"name" TEXT NOT NULL UNIQUE,
"phone" TEXT,
"email" TEXT,
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "categories" (
"idx" INTEGER,
"name" TEXT NOT NULL UNIQUE,
"desc" TEXT,
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "vatrates" (
"idx" INTEGER,
"name" TEXT NOT NULL UNIQUE,
"rate" REAL,
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "receipts" (
"idx" INTEGER,
"name" TEXT NOT NULL UNIQUE,
"desc" REAL,
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "companies" (
"idx" INTEGER,
"company" TEXT NOT NULL UNIQUE,
"taxid" TEXT,
"vatrate" INTEGER,
"receipt" INTEGER,
"phone" TEXT,
"mobile" TEXT,
"address" TEXT,
"city" TEXT,
"state" TEXT,
"zip" TEXT,
"remark" TEXT,
FOREIGN KEY("vatrate") REFERENCES "vatrates"("idx"),
FOREIGN KEY("receipt") REFERENCES "receipts"("idx"),
FOREIGN KEY("city") REFERENCES "cities"("idx"),
FOREIGN KEY("state") REFERENCES "states"("idx"),
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "vendors" (
"idx" INTEGER,
"vendor" TEXT NOT NULL UNIQUE,
"name" TEXT,
"lastname" TEXT,
"phone" TEXT,
"mobile" TEXT,
"email" TEXT,
"website" TEXT,
"address" TEXT,
"state" INTEGER,
"zip" TEXT,
"city" INTEGER,
"remark" TEXT,
"category" INTEGER,
"discount" REAL,
"company" INTEGER,
"contact" INTEGER,
FOREIGN KEY("city") REFERENCES "cities"("idx"),
FOREIGN KEY("state") REFERENCES "states"("idx"),
FOREIGN KEY("category") REFERENCES "categories"("idx"),
FOREIGN KEY("company") REFERENCES "companies"("idx"),
FOREIGN KEY("contact") REFERENCES "contacts"("idx"),
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "families" (
"idx" INTEGER,
"name" TEXT NOT NULL UNIQUE,
"desc" TEXT,
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "subgroups" (
"idx" INTEGER,
"name" TEXT NOT NULL UNIQUE,
"desc" TEXT,
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "composites" (
"idx" INTEGER,
"name" TEXT NOT NULL UNIQUE,
"desc" TEXT,
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "sizes" (
"idx" INTEGER,
"name" TEXT NOT NULL UNIQUE,
"desc" TEXT,
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "mod1s" (
"idx" INTEGER,
"name" TEXT NOT NULL UNIQUE,
"desc" TEXT,
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "mod2s" (
"idx" INTEGER,
"name" TEXT NOT NULL UNIQUE,
"desc" TEXT,
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "units" (
"idx" INTEGER,
"name" TEXT NOT NULL UNIQUE,
"desc" TEXT,
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "materials" (
"idx" INTEGER,
"name" TEXT NOT NULL UNIQUE,
"desc" TEXT,
"code" TEXT UNIQUE,
"family" INTEGER,
"sgroup" INTEGER,
"compo" INTEGER,
"msize" INTEGER,
"mod1" INTEGER,
"mod2" INTEGER,
"price" REAL,
"unit" INTEGER,
FOREIGN KEY("family") REFERENCES "families"("idx"),
FOREIGN KEY("sgroup") REFERENCES "subgroups"("idx"),
FOREIGN KEY("compo") REFERENCES "composites"("idx"),
FOREIGN KEY("msize") REFERENCES "sizes"("idx"),
FOREIGN KEY("mod1") REFERENCES "mod1s"("idx"),
FOREIGN KEY("mod2") REFERENCES "mod2s"("idx"),
FOREIGN KEY("unit") REFERENCES "units"("idx"),
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "tools" (
"idx" INTEGER,
"name" TEXT NOT NULL UNIQUE,
"desc" TEXT,
"price" REAL,
"qty" REAL,
"unit" INTEGER,
FOREIGN KEY("unit") REFERENCES "units"("idx"),
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "tasks" (
"idx" INTEGER,
"name" TEXT NOT NULL UNIQUE,
"desc" TEXT,
"price" REAL,
"qty" REAL,
"unit" INTEGER,
FOREIGN KEY("unit") REFERENCES "units"("idx"),
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "equipments" ( -- An equipment is a device
"idx" INTEGER,
"name" TEXT NOT NULL UNIQUE,
"desc" TEXT, -- Usually is a human readable name that include relevant information, ie: Self Tapping Screw CSK Phillip 4x25mm inox.
"json" TEXT, -- The definition of the equipment in json format. It is more flexible to define any kind of equipment
"price" REAL,
"qty" REAL,
"unit" INTEGER,
FOREIGN KEY("unit") REFERENCES "units"("idx"),
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "budgets"
(
"idx" INTEGER,
"name" TEXT NOT NULL UNIQUE,
"desc" TEXT,
"state" INTEGER,
"contractor" INTEGER,
"client" INTEGER,
"address" TEXT,
"creation" TEXT,
FOREIGN KEY("state") REFERENCES "states"("idx"),
FOREIGN KEY("client") REFERENCES "customers"("idx"),
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "bom" (
"idx" INTEGER,
"hash" TEXT NOT NULL UNIQUE,
"material" INTEGER,
"budget" INTEGER,
"qty" REAL,
FOREIGN KEY("material") REFERENCES "materials"("idx"),
FOREIGN KEY("budget") REFERENCES "budgets"("idx"),
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "accounts" (
"idx" INTEGER,
"name" TEXT NOT NULL UNIQUE,
"owner" TEXT,
"desc" TEXT,
PRIMARY KEY("idx" AUTOINCREMENT)
);
CREATE TABLE "transactions" (
"idx" INTEGER,
"name" TEXT NOT NULL UNIQUE,
"time" TEXT,
"desc" TEXT,
"account" INTEGER,
"operator" INTEGER,
"category" INTEGER,
"tags" TEXT,
"state" INTEGER,
"outflow" REAL,
"inflow" REAL,
"remark" TEXT,
FOREIGN KEY("operator") REFERENCES "users"("idx"),
FOREIGN KEY("category") REFERENCES "categories"("idx"),
FOREIGN KEY("state") REFERENCES "states"("idx"),
FOREIGN KEY("account") REFERENCES "accounts"("idx"),
PRIMARY KEY("idx" AUTOINCREMENT)
);
(22-03-2024, 02:58)tercoide escribió: acompaño en la decisión y ayudaré en lo que pueda
' Gambas class file
Export
Property Read Name As String '' User name
Property Read Active As Integer '' User active = 1 , non active = 0
Property Read Level As String '' User access level.
Property Read Phone As String
Property Read Email As String
Property Read Idx As Integer
Property Read Hash As String
Property Read Data As Data
Property View As String '' Mode
Property Table As String '' Table name, current table
Private $Name As String
Private $Hash As String
Private $Expire As String
Private $Level As Integer
Private $Active As Integer
Private $Phone As String
Private $Email As String
Private $Idx As Integer
Private $View As String
Private $Table As String '' Table name
Private $Data As Data
Public Sub _new(sName As String, sPwd As String, dt As Data, sHide As String)
$Data = dt
$Name = sName
$Hash = Crypt.SHA256(sPwd, sHide)
End
Private Function View_Read() As String
Return $View
End
Private Sub View_Write(Value As String)
$View = Value
End
Private Function Name_Read() As String
Return $Name
End
Private Sub Name_Write(Value As String)
$Name = Value
End
Private Function Table_Read() As String
Return $Table
End
Private Sub Table_Write(Value As String)
$Table = Value
End
Private Function Level_Read() As String
Return $Level
End
Private Function Email_Read() As String
Return $Email
End
Private Function Idx_Read() As Integer
Return $Idx
End
Private Function Hash_Read() As String
Return $Hash
End
Private Function Data_Read() As Data
Return $Data
End
Private Function Active_Read() As Integer
Return $Active
End
Private Function Phone_Read() As String
Return $Phone
End
Cita:El nombre Session creo que ya existe en gambas así que le puse Logon.class la idea es que todos los datos relativos a l usuario estén ahí.Pues para bases Sqlite, es decir locales, sí puede ser la manera... aunque no entiendo muy bien el enrevesamiento si ya dispones de la Bd. Para bases compartidas en tiempo real con otros usuarios, no. Almacenar datos que no se estén modificando en el momento en local es alejar la información disponible de la existente en la BD. La información del usuario, salvo cuando lo creas o modificas, es algo innecesario y peligroso mantenerla en local. Otro usuario o él mismo puede estar modificándo esa información mientras dura nuestra sesión y entrar en contradicciones.
No se si es la manera correcta de manejar estas cosas.
' Gambas class file
Property idusuarios As Integer Use $idusuarios
Property nick As String Use $nick
Property idpersona As Integer Use $idpersona
Property nombre As String Use $nombre
Property permisos As String Use $permisos
Property clave As String Use $clave
Public Function valida(snick As String, pass As String) As Boolean
Dim reg As Result
Dim Conn As New Connection 'Se abre una nueva conexión que se cierra después porque el usuario no puede validarse a sí mismo. Eso lo hace el usuario Administrador.
Conn.type = "mysql"
Conn.host = "mihost"
Conn.user = "Admin"
Conn.Password = "PUFGVng¡bVZ4ZzJWG2RsV-9GMlI¡" 'En la empresa se usaba un sistema de encriptación propio. Si no es el caso, aquí se puede descargar del servidor un archivo con la clave vía ssh o algo así y comparar después.
Conn.Name = "MiBD"
Conn.Open
If Not Conn.Opened Then
Message.Error("No se pudieron abrir las bases de datos. Compruebe su conexión a Internet.")
Return False
Else
reg = Conn.exec("select * from Usuarios where nick = &1 and activo=True", snick)
If reg.Available Then
If pass = reg!clave Then
$idusuarios = reg!idusuarios
$nick = reg!nick
$idpersona = reg!idpersona
$nombre = reg!nombre
$clave = pass
$permisos = reg!permisos
Conn.Close
Return True
Endif
Endif
Return False
Catch
Message("Error: " & Error.Text & "\nEn: " & Error.where)
End
(24-03-2024, 14:03)Shordi escribió: Pues para bases Sqlite, es decir locales, sí puede ser la manera... aunque no entiendo muy bien el enrevesamiento si ya dispones de la Bd. Para bases compartidas en tiempo real con otros usuarios, no. Almacenar datos que no se estén modificando en el momento en local es alejar la información disponible de la existente en la BD. La información del usuario, salvo cuando lo creas o modificas, es algo innecesario y peligroso mantenerla en local. Otro usuario o él mismo puede estar modificándo esa información mientras dura nuestra sesión y entrar en contradicciones.
Así: abres la sesión utilizando un nombre de usuario genérico (este tipo de usuario es muy común aunque yo me opongo radicalmente a su uso) digamos el usuario "Contabilidad", y mientras estás trabajando en la contabilidad otro usuario cambia la contraseña, por ejemplo. Eso deja tu hash local obsoleto y si en algún momento quieres volver a validarlo o quieres regrabar los datos que leiste de la BD, ya estás en problemas.
(24-03-2024, 14:05)jguardon escribió: yo tiraría para una base de datos postgres en un contenedor Docker, porque así es muy fácil levantarla, replicarla y poder trabajar localmente sin romper la del servidor, etc. Hoy día, en desarrollos profesionales es la manera preferida de trabajar. ¿Qué os parece?
(24-03-2024, 14:05)jguardon escribió: ...pero no he visto realmente un croquis, diagrama o planteamiento de qué programa se va a realizar...
Cita:No estoy hablando de guardar nada en local, los datos siempre se guardan en la base de datos, sea la que sea.Me he explicado mal usando "almacenar". No hablo de guardar en disco. Una colección de datos en memoria ram también es local. Si conectamos nuestro supuesto programa a las 9 de la mañana, cargando los datos en esa colección y no lo vamos a cerrar hasta las 14 horas que nos vamos a casa, estamos guardando en local los datos durante 5 horas. Si luego usamos esos datos, estamos cinco horas desfasados con respecto al resto de usuarios.
Cita:yo tiraría para una base de datos postgres en un contenedor Docker, porque así es muy fácil levantarla, replicarla y poder trabajar localmente sin romper la del servidor, etc. Hoy día, en desarrollos profesionales es la manera preferida de trabajar. ¿Qué os parece?
(24-03-2024, 19:23)Shordi escribió: Con la base creada y la gente con capacidad de conectarse con ella no hace falta replicarla para nada y, desde luego, crear una BD en SQLite para hacer un programa de prueba que luego haya que reprogramar para que se adapte a la BD "buena", es una pérdida de tiempo, recursos y algo completamente inútil.
(24-03-2024, 19:23)Shordi escribió: ¿Quién ha trabajado alguna vez con PostGre?
(24-03-2024, 19:23)Shordi escribió: Si hay que modificar la estructura que se acordó, se pide al encargado de la BD.
(24-03-2024, 19:23)Shordi escribió: No olvidemos que la idea es crear, probar y pulir un equipo de desarrollo en el foro, no hacer algo que esté a la ultima y que nadie, al final, entienda ¿Quién sabe montar un docker? (¿quién sabe qué es un docker, si a eso vamos?) ¿Qué servidor y qué potencia se necesita para montar uno que resuelva relativamente bien el tema? (En mi anterior empresa, cuando montamos un docker tuvimos que comprar un super ordenata (2.500€, me dice mi vieja memoria) para manejarlo con fluidez), etc. etc.
(24-03-2024, 19:23)Shordi escribió: Por otra parte hay una cosa que se llama la "Curva de aprendizaje grupal", que es la misma que la personal pero para el equipo. Habrá gente que esté aburrida de manejar BBDD y otra que nunca en su vida lo ha hecho, habrá gente que configure servidores desde 0 antes de desayunar y otra para la que eso sea un escollo insalvable. Si esto fuese una empresa departamental, no problema. Se asigna a cada uno el rol que mejor cuadre a su background (como se dice ahora) y a los demás les importa un pepino cómo o qué hace dentro de él. Sólo importan los resultados. Pero, repito, esto es un desarrollo de prueba entre amigos y colegas sólo por divertirse y probarse y creo que todo interesa a todos... más o menos por lo que entrar en honduras sobre instalación de servidores y BBDD mega potentes, etc, me parece un error.