enum in prisma instead of table - prisma

I have two tables in my Prisma db. One is for admins and the other is for users, and since they differ a lot from each other I decided not to create an isAdmin field. They have both in common the establishment that is described as a table (one-to-many relation), but it has only one field (name). I'd like to know whether it is a good idea to create an Enum to represent this field. My only doubt is that, since the values of the enums can change (adding more fields dynamically), it is not as good as creating a table
model Admin {
id String #id #default(uuid())
pin Int
establishment Establishment #relation(fields: [establishmentId], references: [id])
establishmentId Int
}
model User {
id String #id #default(uuid())
name String
balance Float #default(0)
establishment Establishment #relation(fields: [establishmentId], references: [id])
establishmentId Int
}
model Establishment {
id Int #id #default(autoincrement())
name String
}
This is how I've imagined the new data source to be like
model Admin {
id String #id #default(uuid())
pin Int
establishment Establishment
}
model User {
id String #id #default(uuid())
name String
balance Float #default(0)
establishment Establishment
}
enum Establishment {
ESTABLISHMENT1
ESTABLISHMENT2
}

If you are sure that you won't need to store any more fields for Establishment then the enums approach is good. But in case in future you are envisioning that there could be other common fields, then you would need to duplicate them in Users and Admins Table and Enums approach won't be a fit.
Another approach could be to use the check constraint on database level to only allow two valid values i.e. ESTABLISHMENT1 and ESTABLISHMENT2, this way you won't even need to define enums.

Related

GORM foreign key doesn't seem to add proper fields

I have the following model:
type Drink struct {
gorm.Model // Adds some metadata fields to the table
ID uuid.UUID `gorm:"type:uuid;primary key"`
Name string `gorm:"index;not null;"`
Volume float64 `gorm:"not null;type:decimal(10,2)"`
ABV float64 `gorm:"not null;type:decimal(10,2);"`
Price float64 `gorm:"not null;type:decimal(10,2);"`
Location Location `gorm:"ForeignKey:DrinkID;"`
}
type Location struct {
gorm.Model // Adds some metadata fields to the table
ID uuid.UUID `gorm:"primary key;type:uuid"`
DrinkID uuid.UUID
Name string `gorm:"not null;"`
Address string `gorm:"not null;type:decimal(10,2)"`
Phone int `gorm:"not null;type:decimal(10,0);"`
}
however, when I run the program, it adds both tables, however there is no location field in the Drink table.
My database looks like this after the migrations, regardless of whether I drop the tables previously:
I have a sneaking feeling it might be because I am not using the gorm default ID, but if that's the case can anyone point me to how to override the default ID with a UUID instead of a uint the proper way? or if that's not even the issue, please, I've been working on this for a few days now and I really don't want to take the "easy" road of just using the defaults gorm provides, I actually want to understand what is going on here and how to properly do what I am trying to do. I am getting no errors when running the API, and the migration appears to run as well, it's just the fields I have defined are not actually showing up in the database, which means that the frontend won't be able to add data properly.
What I WANT to happen here is that a list of stores will be available in the front-end, and when a user adds a drink, they will have to select from that list of stores. Each drink added should only have 1 store, as the drinks prices at different stores would be different. So technically there would be many "repeated" drinks in the drink table, but connected to different Locations.
First point is as you are using custom primary key, you should not use gorm.Model as it contains ID field in it. Reference
Second point is according to your description, store (location) has one to
many relationship with drink. That means a store can have multiple
drinks but a drink should belong to only one store. In one-to-many
relationship there should be a reference or relation id in the many
side. That means in your case in drink table. Then your struct
should look like this:
MyModel Struct
type MyModel struct {
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}
Location Struct (Store)
type Location struct {
MyModel
ID uuid.UUID `gorm:"primary key;type:uuid"`
// other columns...
Drinks []Drink
}
Drink Struct
type Drink struct {
MyModel
ID uuid.UUID `gorm:"type:uuid;primary key"`
//other columns...
LocationID uuid.UUID// This is important
}
Then gorm will automatically consider LocationID in drink table will be referring the ID field of Location Table. You can also explicitly instruct this to gorm using gorm:"foreignKey:LocationID;references:ID" in Location struct's Drinks array field.
Reference

Reuse same model for two fields in Prisma

My goal is for this:
I have a table of professions. A person can have two professions - a primary and secondary profession.
model Person {
id String #id #default(cuid())
PrimaryProfessionId String?
Secondary String?
PrimaryProfession Profession #relation(fields: [PrimaryProfessionId], references: [id])
SecondaryProfession Profession #relation(fields: [SecondaryProfessionId], references: [id], name: "secondaryProfession")
}
model Profession {
id String #id #default(cuid())
name String
Primary Person?
Secondary Person? #relation("secondaryProfession")
}
Trying to copy this: Prisma - How to point two fields to same model? but it doesnt work.
With current code I am getting error: Error parsing attribute "#relation": A one-to-one relation must use unique fields on the defining side.
What should I fix to make this work?

How can I filter by a value inside a pivot table (using Prisma)?

I'm building a bike rental app where users can reserve bikes for a certain number of days. Bikes and users have a many-to-many relationship, there's a bike_user pivot table that contains the information about reservation start and end dates. See the diagram:
My schema looks kinda like this:
model User {
id String #id #default(cuid())
username String #unique
email String #unique
rented_bikes BikeUser[]
}
model Bike {
id String #id #default(cuid())
model String
color String
rented_by_users BikeUser[]
}
model BikeUser {
user User #relation(fields: [userId], references: [id])
userId String
bike Bike #relation(fields: [bikeId], references: [id])
bikeId String
reservation_start_date DateTime
reservation_end_date String
##id([userId, bikeId])
}
My goal is to take a range of dates, and filter the bikes, showing only the ones that haven't been reserved between these two dates.
Can you please help me figure out how to do this?

What is the best way to model a one-to-many relationship that also has a "selected" object in Prisma?

In our app, a user can be a member of many organizations. While viewing the site, they are generally viewing it through one of those organizations. This is the selected organization.
Is the following model the best way to model that? Is there a way to model it so you don't have to have the selectedBy and selectedById on the Membership and just have the selectedMembershipId on the User with a foreign key to the Membership?
model User {
id Int #id #default(autoincrement())
memberships Membership[] #relation("Memberships")
selectedMembership Membership? #relation("Selection")
}
model Membership {
id Int #id #default(autoincrement())
user User #relation("Memberships", fields: [userId], references: [id])
userId Int
selectedBy User? #relation("Selection", fields: [selectedById], references: [id])
selectedById Int? #unique
organization Organization #relation(fields: [orgId], references: [id])
orgId Int
role MemberRole
##unique([userId, orgId])
}
It's not possible to do precisely what you're hoping to. The syntax for relations in prisma calls for having a relation field (To the best of my understanding, that's what you would prefer not to have in your schema).
Since it's a one-to-one relation, if you prefer, you could do it the other way around, and have a selectedMembershipId foreign key on the User side and only have the selectedBy relation field on the Membership side like this:
model User {
id Int #id #default(autoincrement())
memberships Membership[] #relation("Memberships")
selectedMembership Membership? #relation("Selection", fields: [selectedMembershipId], references: [id])
selectedMembershipId Int? #unique
}
model Membership {
id Int #id #default(autoincrement())
user User #relation("Memberships", fields: [userId], references: [id])
userId Int
selectedBy User? #relation("Selection")
...
}
However, this is really a matter of preference regarding which side to keep the foreign key. In my opinion, the way you're handling your schema is the most reasonable way to model the relationship in Prisma.

JaVers, SpringDatat, JPA: Querying for Entity Update inside a Collection

I'm new to Stackoverflow, so I will make my best to conforms with usage. I was wondering if there were a way to get a complete list of changes/snapshots of a given Entity. For now it works well with edition of Singular Properties, as well as Addition and Deletion to Collection Property. But I'm unable to find when a Child Entity in the Collection Property was updated.
Given two Entities, and a LinkEntity:
#Entity
class Person {
#Id
Long id;
#OneToMany(mappedBy = "person", cascade = CascadeType.ALL)
Set<LinkAddress> addresses;
}
#Entity
class Address {
#Id
Long id;
#OneToMany(mappedBy = "address")
Set<Address> persons;
}
#Entity
class LinkPersonAddress {
#Id
Long id;
#ManyToOne
#ShallowReference
Person person;
#ManyToOne
#ShallowReference
Address address;
String linkType;
}
My use case is following. I get a specific Person by Id #1, and then mutate the type of specific Address (ie. HOME --> WORK). I save the Person back with the modified Set and let JPA Cascade my changes. Although all Spring Data Repositories for Person, Address, and LinkPersonAddress are annotated with #JaversSpringDataAuditable, I cannot retrieve this "update" using Javers QueryBuilder with the class Person and Id #1. It makes sense as I should query the class LinkPersonAddress instead, but how can I specify that I want only the changes from LinkPersonAddress relevant to Person with Id #1.
PS: Please apologize any typos in code snippets, as I didn't write it in my Dev Environment.
Let's start from the mapping. You did it wrong, Address is a classical ValueObject (see https://javers.org/documentation/domain-configuration/#value-object) not Entity. Because:
Address doesn't have its own identity (primary key genereted by a db sequence doesn't count)
Address is owned by the Person Entity. Person with its Addresses forms the Aggregate.
When you correct the mapping, you can use ChildValueObjects filter, see https://javers.org/documentation/jql-examples/#child-value-objects-filter