orm (WIP)
This commit is contained in:
parent
bdd4042cef
commit
ceab3db8b4
@ -46,11 +46,16 @@ RUN echo "set -g theme_nerd_fonts yes" >> ~/.config/fish/config.fish \
|
||||
|
||||
# Installiere Deno
|
||||
ENV DENO_INSTALL=/deno
|
||||
RUN mkdir -p /deno \
|
||||
RUN mkdir -p ${DENO_INSTALL} \
|
||||
&& curl -fsSL https://deno.land/x/install/install.sh | sh \
|
||||
&& chown -R vscode /deno
|
||||
|
||||
ENV PATH=${DENO_INSTALL}/bin:/usr/local/go/bin:${PATH} \
|
||||
# Installiere Bun
|
||||
ENV BUN_INSTALL=/bun
|
||||
RUN mkdir -p ${BUN_INSTALL} \
|
||||
&& curl -fsSL https://bun.sh/install | bash
|
||||
|
||||
ENV PATH=${BUN_INSTALL}/bin:${DENO_INSTALL}/bin:/usr/local/go/bin:${PATH} \
|
||||
DENO_DIR=${DENO_INSTALL}/.cache/deno
|
||||
|
||||
RUN groupadd -r docker && usermod -aG docker $USERNAME
|
||||
@ -58,7 +63,7 @@ RUN groupadd -r docker && usermod -aG docker $USERNAME
|
||||
WORKDIR /workspace
|
||||
|
||||
# Zusätzliche Pakete installieren
|
||||
RUN apt-get update && apt-get install -y protobuf-compiler
|
||||
RUN apt-get update && apt-get install -y protobuf-compiler netcat
|
||||
|
||||
# Ports für React und Dart Services
|
||||
EXPOSE 3000 8080 4000
|
||||
|
@ -22,16 +22,17 @@
|
||||
],
|
||||
"features": {
|
||||
//"docker-in-docker": "latest",
|
||||
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}
|
||||
//"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}
|
||||
"ghcr.io/devcontainers/features/docker-in-docker:2": {}
|
||||
},
|
||||
"runArgs": ["--add-host=host.docker.internal:host-gateway"],
|
||||
//"runArgs": ["--add-host=host.docker.internal:host-gateway"],
|
||||
"postCreateCommand": "./.devcontainer/setup.sh",
|
||||
"remoteUser": "vscode",
|
||||
"updateRemoteUserUID": true,
|
||||
//"workspaceMount": "",
|
||||
//"workspaceFolder": "/workspaces",
|
||||
"mounts": [
|
||||
"type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock",
|
||||
//"type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock",
|
||||
"source=${localEnv:HOME}${localEnv:USERPROFILE}/.ssh,target=/home/vscode/.ssh-host,type=bind,consistency=cached"
|
||||
//"source=${localEnv:HOME}/.ssh,target=/home/vscode/.ssh,type=bind,consistency=cached"
|
||||
]
|
||||
|
@ -18,6 +18,7 @@ if [ -d "backend-dart" ]; then
|
||||
(
|
||||
cd backend-dart
|
||||
dart pub get
|
||||
bun install
|
||||
) &
|
||||
else
|
||||
echo "backend-dart directory not found, skipping..."
|
||||
|
23
README.md
23
README.md
@ -63,7 +63,7 @@ structured into well-defined layers with separation of concerns.
|
||||
|
||||
- PNPM: npm install -g pnpm
|
||||
|
||||
### Run Software
|
||||
# Run Software
|
||||
|
||||
You can start developing and hacking by starting the dev container. Besides that
|
||||
you can also install the dev environment on your host system. Make sure versions
|
||||
@ -90,6 +90,27 @@ go run cmd/actatempus/main.go # Backend on port 8080
|
||||
cd backend-dart
|
||||
dart run bin/backend_dart.dart # Backend on port 8080
|
||||
```
|
||||
## Databse
|
||||
|
||||
To simplify things, we chose to use prisma as orm. This enables us to use the same database definition for go and dart. Therefore also error prone manually written sql queries can be avoided.
|
||||
|
||||
In order to deploy the database schema you need to run
|
||||
|
||||
```bash
|
||||
bunx prisma db push
|
||||
```
|
||||
|
||||
The prisma cli can be initialized with the following command:
|
||||
```bash
|
||||
bunx prisma
|
||||
```
|
||||
More: https://www.prisma.io/docs/orm/tools/prisma-cli
|
||||
|
||||
### Bun Studio
|
||||
After deployment, data can be accessed via a webui:
|
||||
```bash
|
||||
bunx prisma studio
|
||||
```
|
||||
|
||||
# Known Issues
|
||||
|
||||
|
BIN
backend-dart/bun.lockb
Executable file
BIN
backend-dart/bun.lockb
Executable file
Binary file not shown.
2
backend-dart/gen-prisma.sh
Normal file
2
backend-dart/gen-prisma.sh
Normal file
@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
bun prisma generate
|
5
backend-dart/package.json
Normal file
5
backend-dart/package.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"prisma": "^6.1.0"
|
||||
}
|
||||
}
|
2679
backend-dart/prisma/lib/infrastructure/persistence/db/client.dart
Normal file
2679
backend-dart/prisma/lib/infrastructure/persistence/db/client.dart
Normal file
File diff suppressed because it is too large
Load Diff
531
backend-dart/prisma/lib/infrastructure/persistence/db/model.dart
Normal file
531
backend-dart/prisma/lib/infrastructure/persistence/db/model.dart
Normal file
@ -0,0 +1,531 @@
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'model.dart' as _i1;
|
||||
import 'prisma.dart' as _i2;
|
||||
|
||||
class Task {
|
||||
const Task({
|
||||
this.id,
|
||||
this.name,
|
||||
this.description,
|
||||
this.projectId,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.project,
|
||||
});
|
||||
|
||||
factory Task.fromJson(Map json) => Task(
|
||||
id: json['id'],
|
||||
name: json['name'],
|
||||
description: json['description'],
|
||||
projectId: json['projectId'],
|
||||
createdAt: switch (json['createdAt']) {
|
||||
DateTime value => value,
|
||||
String value => DateTime.parse(value),
|
||||
_ => json['createdAt']
|
||||
},
|
||||
updatedAt: switch (json['updatedAt']) {
|
||||
DateTime value => value,
|
||||
String value => DateTime.parse(value),
|
||||
_ => json['updatedAt']
|
||||
},
|
||||
project: json['project'] is Map
|
||||
? _i1.Project.fromJson(json['project'])
|
||||
: null,
|
||||
);
|
||||
|
||||
final String? id;
|
||||
|
||||
final String? name;
|
||||
|
||||
final String? description;
|
||||
|
||||
final String? projectId;
|
||||
|
||||
final DateTime? createdAt;
|
||||
|
||||
final DateTime? updatedAt;
|
||||
|
||||
final _i1.Project? project;
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'id': id,
|
||||
'name': name,
|
||||
'description': description,
|
||||
'projectId': projectId,
|
||||
'createdAt': createdAt?.toIso8601String(),
|
||||
'updatedAt': updatedAt?.toIso8601String(),
|
||||
'project': project?.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
class TimeEntry {
|
||||
const TimeEntry({
|
||||
this.id,
|
||||
this.startTime,
|
||||
this.endTime,
|
||||
this.description,
|
||||
this.userId,
|
||||
this.projectId,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.user,
|
||||
this.project,
|
||||
});
|
||||
|
||||
factory TimeEntry.fromJson(Map json) => TimeEntry(
|
||||
id: json['id'],
|
||||
startTime: switch (json['startTime']) {
|
||||
DateTime value => value,
|
||||
String value => DateTime.parse(value),
|
||||
_ => json['startTime']
|
||||
},
|
||||
endTime: switch (json['endTime']) {
|
||||
DateTime value => value,
|
||||
String value => DateTime.parse(value),
|
||||
_ => json['endTime']
|
||||
},
|
||||
description: json['description'],
|
||||
userId: json['userId'],
|
||||
projectId: json['projectId'],
|
||||
createdAt: switch (json['createdAt']) {
|
||||
DateTime value => value,
|
||||
String value => DateTime.parse(value),
|
||||
_ => json['createdAt']
|
||||
},
|
||||
updatedAt: switch (json['updatedAt']) {
|
||||
DateTime value => value,
|
||||
String value => DateTime.parse(value),
|
||||
_ => json['updatedAt']
|
||||
},
|
||||
user: json['user'] is Map ? _i1.User.fromJson(json['user']) : null,
|
||||
project: json['project'] is Map
|
||||
? _i1.Project.fromJson(json['project'])
|
||||
: null,
|
||||
);
|
||||
|
||||
final String? id;
|
||||
|
||||
final DateTime? startTime;
|
||||
|
||||
final DateTime? endTime;
|
||||
|
||||
final String? description;
|
||||
|
||||
final String? userId;
|
||||
|
||||
final String? projectId;
|
||||
|
||||
final DateTime? createdAt;
|
||||
|
||||
final DateTime? updatedAt;
|
||||
|
||||
final _i1.User? user;
|
||||
|
||||
final _i1.Project? project;
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'id': id,
|
||||
'startTime': startTime?.toIso8601String(),
|
||||
'endTime': endTime?.toIso8601String(),
|
||||
'description': description,
|
||||
'userId': userId,
|
||||
'projectId': projectId,
|
||||
'createdAt': createdAt?.toIso8601String(),
|
||||
'updatedAt': updatedAt?.toIso8601String(),
|
||||
'user': user?.toJson(),
|
||||
'project': project?.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
class Project {
|
||||
const Project({
|
||||
this.id,
|
||||
this.name,
|
||||
this.description,
|
||||
this.clientId,
|
||||
this.userId,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.tasks,
|
||||
this.timeEntries,
|
||||
this.user,
|
||||
this.$count,
|
||||
});
|
||||
|
||||
factory Project.fromJson(Map json) => Project(
|
||||
id: json['id'],
|
||||
name: json['name'],
|
||||
description: json['description'],
|
||||
clientId: json['clientId'],
|
||||
userId: json['userId'],
|
||||
createdAt: switch (json['createdAt']) {
|
||||
DateTime value => value,
|
||||
String value => DateTime.parse(value),
|
||||
_ => json['createdAt']
|
||||
},
|
||||
updatedAt: switch (json['updatedAt']) {
|
||||
DateTime value => value,
|
||||
String value => DateTime.parse(value),
|
||||
_ => json['updatedAt']
|
||||
},
|
||||
tasks: (json['tasks'] as Iterable?)
|
||||
?.map((json) => _i1.Task.fromJson(json)),
|
||||
timeEntries: (json['timeEntries'] as Iterable?)
|
||||
?.map((json) => _i1.TimeEntry.fromJson(json)),
|
||||
user: json['user'] is Map ? _i1.User.fromJson(json['user']) : null,
|
||||
$count: json['_count'] is Map
|
||||
? _i2.ProjectCountOutputType.fromJson(json['_count'])
|
||||
: null,
|
||||
);
|
||||
|
||||
final String? id;
|
||||
|
||||
final String? name;
|
||||
|
||||
final String? description;
|
||||
|
||||
final String? clientId;
|
||||
|
||||
final String? userId;
|
||||
|
||||
final DateTime? createdAt;
|
||||
|
||||
final DateTime? updatedAt;
|
||||
|
||||
final Iterable<_i1.Task>? tasks;
|
||||
|
||||
final Iterable<_i1.TimeEntry>? timeEntries;
|
||||
|
||||
final _i1.User? user;
|
||||
|
||||
final _i2.ProjectCountOutputType? $count;
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'id': id,
|
||||
'name': name,
|
||||
'description': description,
|
||||
'clientId': clientId,
|
||||
'userId': userId,
|
||||
'createdAt': createdAt?.toIso8601String(),
|
||||
'updatedAt': updatedAt?.toIso8601String(),
|
||||
'tasks': tasks?.map((e) => e.toJson()),
|
||||
'timeEntries': timeEntries?.map((e) => e.toJson()),
|
||||
'user': user?.toJson(),
|
||||
'_count': $count?.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
class User {
|
||||
const User({
|
||||
this.id,
|
||||
this.name,
|
||||
this.email,
|
||||
this.password,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.projects,
|
||||
this.timeEntries,
|
||||
this.$count,
|
||||
});
|
||||
|
||||
factory User.fromJson(Map json) => User(
|
||||
id: json['id'],
|
||||
name: json['name'],
|
||||
email: json['email'],
|
||||
password: json['password'],
|
||||
createdAt: switch (json['createdAt']) {
|
||||
DateTime value => value,
|
||||
String value => DateTime.parse(value),
|
||||
_ => json['createdAt']
|
||||
},
|
||||
updatedAt: switch (json['updatedAt']) {
|
||||
DateTime value => value,
|
||||
String value => DateTime.parse(value),
|
||||
_ => json['updatedAt']
|
||||
},
|
||||
projects: (json['projects'] as Iterable?)
|
||||
?.map((json) => _i1.Project.fromJson(json)),
|
||||
timeEntries: (json['timeEntries'] as Iterable?)
|
||||
?.map((json) => _i1.TimeEntry.fromJson(json)),
|
||||
$count: json['_count'] is Map
|
||||
? _i2.UserCountOutputType.fromJson(json['_count'])
|
||||
: null,
|
||||
);
|
||||
|
||||
final String? id;
|
||||
|
||||
final String? name;
|
||||
|
||||
final String? email;
|
||||
|
||||
final String? password;
|
||||
|
||||
final DateTime? createdAt;
|
||||
|
||||
final DateTime? updatedAt;
|
||||
|
||||
final Iterable<_i1.Project>? projects;
|
||||
|
||||
final Iterable<_i1.TimeEntry>? timeEntries;
|
||||
|
||||
final _i2.UserCountOutputType? $count;
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'id': id,
|
||||
'name': name,
|
||||
'email': email,
|
||||
'password': password,
|
||||
'createdAt': createdAt?.toIso8601String(),
|
||||
'updatedAt': updatedAt?.toIso8601String(),
|
||||
'projects': projects?.map((e) => e.toJson()),
|
||||
'timeEntries': timeEntries?.map((e) => e.toJson()),
|
||||
'_count': $count?.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
class CreateManyUserAndReturnOutputType {
|
||||
const CreateManyUserAndReturnOutputType({
|
||||
this.id,
|
||||
this.name,
|
||||
this.email,
|
||||
this.password,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
});
|
||||
|
||||
factory CreateManyUserAndReturnOutputType.fromJson(Map json) =>
|
||||
CreateManyUserAndReturnOutputType(
|
||||
id: json['id'],
|
||||
name: json['name'],
|
||||
email: json['email'],
|
||||
password: json['password'],
|
||||
createdAt: switch (json['createdAt']) {
|
||||
DateTime value => value,
|
||||
String value => DateTime.parse(value),
|
||||
_ => json['createdAt']
|
||||
},
|
||||
updatedAt: switch (json['updatedAt']) {
|
||||
DateTime value => value,
|
||||
String value => DateTime.parse(value),
|
||||
_ => json['updatedAt']
|
||||
},
|
||||
);
|
||||
|
||||
final String? id;
|
||||
|
||||
final String? name;
|
||||
|
||||
final String? email;
|
||||
|
||||
final String? password;
|
||||
|
||||
final DateTime? createdAt;
|
||||
|
||||
final DateTime? updatedAt;
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'id': id,
|
||||
'name': name,
|
||||
'email': email,
|
||||
'password': password,
|
||||
'createdAt': createdAt?.toIso8601String(),
|
||||
'updatedAt': updatedAt?.toIso8601String(),
|
||||
};
|
||||
}
|
||||
|
||||
class CreateManyProjectAndReturnOutputType {
|
||||
const CreateManyProjectAndReturnOutputType({
|
||||
this.id,
|
||||
this.name,
|
||||
this.description,
|
||||
this.clientId,
|
||||
this.userId,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.user,
|
||||
});
|
||||
|
||||
factory CreateManyProjectAndReturnOutputType.fromJson(Map json) =>
|
||||
CreateManyProjectAndReturnOutputType(
|
||||
id: json['id'],
|
||||
name: json['name'],
|
||||
description: json['description'],
|
||||
clientId: json['clientId'],
|
||||
userId: json['userId'],
|
||||
createdAt: switch (json['createdAt']) {
|
||||
DateTime value => value,
|
||||
String value => DateTime.parse(value),
|
||||
_ => json['createdAt']
|
||||
},
|
||||
updatedAt: switch (json['updatedAt']) {
|
||||
DateTime value => value,
|
||||
String value => DateTime.parse(value),
|
||||
_ => json['updatedAt']
|
||||
},
|
||||
user: json['user'] is Map ? _i1.User.fromJson(json['user']) : null,
|
||||
);
|
||||
|
||||
final String? id;
|
||||
|
||||
final String? name;
|
||||
|
||||
final String? description;
|
||||
|
||||
final String? clientId;
|
||||
|
||||
final String? userId;
|
||||
|
||||
final DateTime? createdAt;
|
||||
|
||||
final DateTime? updatedAt;
|
||||
|
||||
final _i1.User? user;
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'id': id,
|
||||
'name': name,
|
||||
'description': description,
|
||||
'clientId': clientId,
|
||||
'userId': userId,
|
||||
'createdAt': createdAt?.toIso8601String(),
|
||||
'updatedAt': updatedAt?.toIso8601String(),
|
||||
'user': user?.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
class CreateManyTimeEntryAndReturnOutputType {
|
||||
const CreateManyTimeEntryAndReturnOutputType({
|
||||
this.id,
|
||||
this.startTime,
|
||||
this.endTime,
|
||||
this.description,
|
||||
this.userId,
|
||||
this.projectId,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.user,
|
||||
this.project,
|
||||
});
|
||||
|
||||
factory CreateManyTimeEntryAndReturnOutputType.fromJson(Map json) =>
|
||||
CreateManyTimeEntryAndReturnOutputType(
|
||||
id: json['id'],
|
||||
startTime: switch (json['startTime']) {
|
||||
DateTime value => value,
|
||||
String value => DateTime.parse(value),
|
||||
_ => json['startTime']
|
||||
},
|
||||
endTime: switch (json['endTime']) {
|
||||
DateTime value => value,
|
||||
String value => DateTime.parse(value),
|
||||
_ => json['endTime']
|
||||
},
|
||||
description: json['description'],
|
||||
userId: json['userId'],
|
||||
projectId: json['projectId'],
|
||||
createdAt: switch (json['createdAt']) {
|
||||
DateTime value => value,
|
||||
String value => DateTime.parse(value),
|
||||
_ => json['createdAt']
|
||||
},
|
||||
updatedAt: switch (json['updatedAt']) {
|
||||
DateTime value => value,
|
||||
String value => DateTime.parse(value),
|
||||
_ => json['updatedAt']
|
||||
},
|
||||
user: json['user'] is Map ? _i1.User.fromJson(json['user']) : null,
|
||||
project: json['project'] is Map
|
||||
? _i1.Project.fromJson(json['project'])
|
||||
: null,
|
||||
);
|
||||
|
||||
final String? id;
|
||||
|
||||
final DateTime? startTime;
|
||||
|
||||
final DateTime? endTime;
|
||||
|
||||
final String? description;
|
||||
|
||||
final String? userId;
|
||||
|
||||
final String? projectId;
|
||||
|
||||
final DateTime? createdAt;
|
||||
|
||||
final DateTime? updatedAt;
|
||||
|
||||
final _i1.User? user;
|
||||
|
||||
final _i1.Project? project;
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'id': id,
|
||||
'startTime': startTime?.toIso8601String(),
|
||||
'endTime': endTime?.toIso8601String(),
|
||||
'description': description,
|
||||
'userId': userId,
|
||||
'projectId': projectId,
|
||||
'createdAt': createdAt?.toIso8601String(),
|
||||
'updatedAt': updatedAt?.toIso8601String(),
|
||||
'user': user?.toJson(),
|
||||
'project': project?.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
class CreateManyTaskAndReturnOutputType {
|
||||
const CreateManyTaskAndReturnOutputType({
|
||||
this.id,
|
||||
this.name,
|
||||
this.description,
|
||||
this.projectId,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.project,
|
||||
});
|
||||
|
||||
factory CreateManyTaskAndReturnOutputType.fromJson(Map json) =>
|
||||
CreateManyTaskAndReturnOutputType(
|
||||
id: json['id'],
|
||||
name: json['name'],
|
||||
description: json['description'],
|
||||
projectId: json['projectId'],
|
||||
createdAt: switch (json['createdAt']) {
|
||||
DateTime value => value,
|
||||
String value => DateTime.parse(value),
|
||||
_ => json['createdAt']
|
||||
},
|
||||
updatedAt: switch (json['updatedAt']) {
|
||||
DateTime value => value,
|
||||
String value => DateTime.parse(value),
|
||||
_ => json['updatedAt']
|
||||
},
|
||||
project: json['project'] is Map
|
||||
? _i1.Project.fromJson(json['project'])
|
||||
: null,
|
||||
);
|
||||
|
||||
final String? id;
|
||||
|
||||
final String? name;
|
||||
|
||||
final String? description;
|
||||
|
||||
final String? projectId;
|
||||
|
||||
final DateTime? createdAt;
|
||||
|
||||
final DateTime? updatedAt;
|
||||
|
||||
final _i1.Project? project;
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'id': id,
|
||||
'name': name,
|
||||
'description': description,
|
||||
'projectId': projectId,
|
||||
'createdAt': createdAt?.toIso8601String(),
|
||||
'updatedAt': updatedAt?.toIso8601String(),
|
||||
'project': project?.toJson(),
|
||||
};
|
||||
}
|
10218
backend-dart/prisma/lib/infrastructure/persistence/db/prisma.dart
Normal file
10218
backend-dart/prisma/lib/infrastructure/persistence/db/prisma.dart
Normal file
File diff suppressed because it is too large
Load Diff
BIN
backend-dart/prisma/prisma-query-engine
Executable file
BIN
backend-dart/prisma/prisma-query-engine
Executable file
Binary file not shown.
60
backend-dart/prisma/schema.prisma
Executable file
60
backend-dart/prisma/schema.prisma
Executable file
@ -0,0 +1,60 @@
|
||||
generator dartClient {
|
||||
provider = "dart run orm"
|
||||
output = "lib/infrastructure/persistence/db"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
// User Model
|
||||
model User {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
email String @unique
|
||||
password String
|
||||
projects Project[] // Beziehung zu Projekten
|
||||
timeEntries TimeEntry[] // Beziehung zu Zeiteinträgen
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
// Project Model
|
||||
model Project {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
description String?
|
||||
clientId String?
|
||||
tasks Task[] // Beziehung zu Aufgaben
|
||||
timeEntries TimeEntry[] // Beziehung zu Zeiteinträgen
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
// TimeEntry Model
|
||||
model TimeEntry {
|
||||
id String @id @default(uuid())
|
||||
startTime DateTime
|
||||
endTime DateTime
|
||||
description String?
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId String
|
||||
project Project @relation(fields: [projectId], references: [id])
|
||||
projectId String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
// Task Model (optional)
|
||||
model Task {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
description String?
|
||||
project Project @relation(fields: [projectId], references: [id])
|
||||
projectId String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
@ -11,29 +11,29 @@ services:
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
|
||||
pgadmin:
|
||||
image: dpage/pgadmin4:latest
|
||||
container_name: pgadmin
|
||||
environment:
|
||||
PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL:-admin@admin.com}
|
||||
PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD:-admin}
|
||||
#PGADMIN_CONFIG_SERVER_MODE: 'False'
|
||||
ports:
|
||||
- "5050:80"
|
||||
#pgadmin:
|
||||
# image: dpage/pgadmin4:latest
|
||||
# container_name: pgadmin
|
||||
# environment:
|
||||
# PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL:-admin@admin.com}
|
||||
# PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD:-admin}
|
||||
# #PGADMIN_CONFIG_SERVER_MODE: 'False'
|
||||
# ports:
|
||||
# - "5050:80"
|
||||
|
||||
redis:
|
||||
image: redis/redis-stack:latest
|
||||
#image: redis:latest
|
||||
container_name: redis-server
|
||||
ports:
|
||||
- "${REDIS_PORT:-6379}:6379"
|
||||
- "8001:8001" # RedisInsight WebUI
|
||||
#environment:
|
||||
# - REDIS_ARGS=--requirepass ${REDIS_PASSWORD:-password}
|
||||
volumes:
|
||||
- redis_data:/data
|
||||
- ./_common/docker/redis.conf:/usr/local/etc/redis/redis.conf
|
||||
#command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
|
||||
#redis:
|
||||
# image: redis/redis-stack:latest
|
||||
# #image: redis:latest
|
||||
# container_name: redis-server
|
||||
# ports:
|
||||
# - "${REDIS_PORT:-6379}:6379"
|
||||
# - "8001:8001" # RedisInsight WebUI
|
||||
# #environment:
|
||||
# # - REDIS_ARGS=--requirepass ${REDIS_PASSWORD:-password}
|
||||
# volumes:
|
||||
# - redis_data:/data
|
||||
# - ./_common/docker/redis.conf:/usr/local/etc/redis/redis.conf
|
||||
# #command: ["redis-server", "/usr/local/etc/redis/redis.conf"]
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
|
Loading…
x
Reference in New Issue
Block a user