mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-10-14 17:54:42 +00:00
256 lines
7.8 KiB
Plaintext
256 lines
7.8 KiB
Plaintext
Project biergarten_app {
|
|
database_type: 'SQL Server'
|
|
Note: 'Generated from Database.Migrations/scripts/01-schema. Default schema is dbo.'
|
|
}
|
|
|
|
Table UserAccount {
|
|
UserAccountID uniqueidentifier [pk, default: `newid()`]
|
|
Username varchar(64) [not null, unique]
|
|
FirstName nvarchar(128) [not null]
|
|
LastName nvarchar(128) [not null]
|
|
Email varchar(128) [not null, unique]
|
|
CreatedAt datetime [not null, default: `getdate()`]
|
|
UpdatedAt datetime
|
|
DateOfBirth date [not null]
|
|
RowVersion rowversion
|
|
}
|
|
|
|
Table Photo {
|
|
PhotoID uniqueidentifier [pk, default: `newid()`]
|
|
Hyperlink nvarchar(256) [note: 'storage handled via filesystem/cloud service']
|
|
UploadedByID uniqueidentifier [not null]
|
|
UploadedAt datetime [not null, default: `getdate()`]
|
|
RowVersion rowversion
|
|
|
|
Note: 'A user account cannot be deleted while it has uploaded photos'
|
|
|
|
Indexes {
|
|
UploadedByID
|
|
}
|
|
}
|
|
|
|
Table UserAvatar {
|
|
UserAvatarID uniqueidentifier [pk, default: `newid()`]
|
|
UserProfileID uniqueidentifier [not null]
|
|
PhotoID uniqueidentifier [not null]
|
|
ValidFrom "datetime2(3)" [not null, default: `sysutcdatetime()`]
|
|
ValidTo "datetime2(3)" [note: 'NULL = currently active']
|
|
RowVersion rowversion
|
|
|
|
Note: 'Deleted when the user profile is deleted. At most one row per profile has ValidTo = NULL.'
|
|
|
|
Indexes {
|
|
UserProfileID [unique, name: 'UX_UserAvatar_ActiveOne', note: 'filtered: WHERE ValidTo IS NULL']
|
|
PhotoID [name: 'IX_UserAvatar_Photo']
|
|
}
|
|
}
|
|
|
|
Table UserProfile {
|
|
UserProfileID uniqueidentifier [pk, default: `newid()`]
|
|
Biography "nvarchar(max)" [not null]
|
|
UserAccountID uniqueidentifier [not null, unique]
|
|
RowVersion rowversion
|
|
|
|
Note: 'Deleted when the user account is deleted'
|
|
}
|
|
|
|
Table UserVerification {
|
|
UserVerificationID uniqueidentifier [pk, default: `newid()`]
|
|
UserAccountID uniqueidentifier [not null, unique]
|
|
VerificationDateTime datetime [not null, default: `getdate()`]
|
|
RowVersion rowversion
|
|
|
|
Note: 'Deleted when the user account is deleted'
|
|
}
|
|
|
|
Table UserCredential {
|
|
UserCredentialID uniqueidentifier [pk, default: `newid()`]
|
|
UserAccountID uniqueidentifier [not null]
|
|
CreatedAt datetime [not null, default: `getdate()`]
|
|
Expiry datetime [not null, default: `dateadd(day, 90, getdate())`]
|
|
Hash nvarchar(256) [not null, note: 'argon2 hash']
|
|
IsRevoked bit [not null, default: 0]
|
|
RevokedAt datetime
|
|
RowVersion rowversion
|
|
|
|
Note: 'Deleted when the user account is deleted'
|
|
|
|
Indexes {
|
|
UserAccountID
|
|
(UserAccountID, IsRevoked, Expiry) [name: 'IX_UserCredential_Account_Active', note: 'includes Hash']
|
|
}
|
|
}
|
|
|
|
Table UserFollow {
|
|
UserFollowID uniqueidentifier [pk, default: `newid()`]
|
|
UserAccountID uniqueidentifier [not null]
|
|
FollowingID uniqueidentifier [not null]
|
|
CreatedAt datetime [not null, default: `getdate()`]
|
|
RowVersion rowversion
|
|
|
|
Note: 'CHECK: UserAccountID != FollowingID (cannot follow own account)'
|
|
|
|
Indexes {
|
|
(UserAccountID, FollowingID)
|
|
(FollowingID, UserAccountID)
|
|
}
|
|
}
|
|
|
|
Table Country {
|
|
CountryID uniqueidentifier [pk, default: `newid()`]
|
|
CountryName nvarchar(100) [not null]
|
|
ISO3166_1 char(2) [not null, unique]
|
|
RowVersion rowversion
|
|
}
|
|
|
|
Table StateProvince {
|
|
StateProvinceID uniqueidentifier [pk, default: `newid()`]
|
|
StateProvinceName nvarchar(100) [not null]
|
|
ISO3166_2 char(6) [not null, unique, note: "e.g. 'US-CA' for California, 'CA-ON' for Ontario"]
|
|
CountryID uniqueidentifier [not null]
|
|
RowVersion rowversion
|
|
|
|
Indexes {
|
|
CountryID
|
|
}
|
|
}
|
|
|
|
Table City {
|
|
CityID uniqueidentifier [pk, default: `newid()`]
|
|
CityName nvarchar(100) [not null]
|
|
StateProvinceID uniqueidentifier [not null]
|
|
RowVersion rowversion
|
|
|
|
Indexes {
|
|
StateProvinceID
|
|
}
|
|
}
|
|
|
|
Table BreweryPost {
|
|
BreweryPostID uniqueidentifier [pk, default: `newid()`]
|
|
BreweryName nvarchar(256) [not null]
|
|
PostedByID uniqueidentifier [not null]
|
|
Description "nvarchar(max)" [not null]
|
|
CreatedAt datetime [not null, default: `getdate()`]
|
|
UpdatedAt datetime
|
|
RowVersion rowversion
|
|
|
|
Note: 'A user cannot be deleted if they have a post'
|
|
|
|
Indexes {
|
|
PostedByID
|
|
}
|
|
}
|
|
|
|
Table BreweryPostLocation {
|
|
BreweryPostLocationID uniqueidentifier [pk, default: `newid()`]
|
|
BreweryPostID uniqueidentifier [not null, unique]
|
|
AddressLine1 nvarchar(256) [not null]
|
|
AddressLine2 nvarchar(256)
|
|
PostalCode nvarchar(20) [not null]
|
|
CityID uniqueidentifier [not null]
|
|
Coordinates geography [note: 'spatial index deferred, see schema.sql history']
|
|
RowVersion rowversion
|
|
|
|
Indexes {
|
|
BreweryPostID
|
|
CityID
|
|
}
|
|
}
|
|
|
|
Table BreweryPostPhoto {
|
|
BreweryPostPhotoID uniqueidentifier [pk, default: `newid()`]
|
|
BreweryPostID uniqueidentifier [not null]
|
|
PhotoID uniqueidentifier [not null]
|
|
LinkedAt datetime [not null, default: `getdate()`]
|
|
RowVersion rowversion
|
|
|
|
Note: 'All photos linked to a post are deleted if the post is deleted'
|
|
|
|
Indexes {
|
|
(PhotoID, BreweryPostID)
|
|
(BreweryPostID, PhotoID)
|
|
}
|
|
}
|
|
|
|
Table BeerStyle {
|
|
BeerStyleID uniqueidentifier [pk, default: `newid()`]
|
|
StyleName nvarchar(100) [not null, unique]
|
|
Description "nvarchar(max)"
|
|
RowVersion rowversion
|
|
}
|
|
|
|
Table BeerPost {
|
|
BeerPostID uniqueidentifier [pk, default: `newid()`]
|
|
Name nvarchar(100) [not null]
|
|
Description "nvarchar(max)" [not null]
|
|
ABV "decimal(4,2)" [not null, note: 'CHECK ABV BETWEEN 0 AND 67']
|
|
IBU int [not null, note: 'CHECK IBU BETWEEN 0 AND 120']
|
|
PostedByID uniqueidentifier [not null]
|
|
BeerStyleID uniqueidentifier [not null]
|
|
BrewedByID uniqueidentifier [not null]
|
|
CreatedAt datetime [not null, default: `getdate()`]
|
|
UpdatedAt datetime
|
|
RowVersion rowversion
|
|
|
|
Indexes {
|
|
PostedByID
|
|
BeerStyleID
|
|
BrewedByID
|
|
}
|
|
}
|
|
|
|
Table BeerPostPhoto {
|
|
BeerPostPhotoID uniqueidentifier [pk, default: `newid()`]
|
|
BeerPostID uniqueidentifier [not null]
|
|
PhotoID uniqueidentifier [not null]
|
|
LinkedAt datetime [not null, default: `getdate()`]
|
|
RowVersion rowversion
|
|
|
|
Note: 'All photos linked to a beer post are deleted if the post is deleted'
|
|
|
|
Indexes {
|
|
(PhotoID, BeerPostID)
|
|
(BeerPostID, PhotoID)
|
|
}
|
|
}
|
|
|
|
Table BeerPostComment {
|
|
BeerPostCommentID uniqueidentifier [pk, default: `newid()`]
|
|
Comment nvarchar(250) [not null]
|
|
BeerPostID uniqueidentifier [not null]
|
|
CommentedByID uniqueidentifier [not null]
|
|
Rating int [not null, note: 'CHECK Rating BETWEEN 1 AND 5']
|
|
CreatedAt datetime [not null, default: `getdate()`]
|
|
UpdatedAt datetime
|
|
RowVersion rowversion
|
|
|
|
Indexes {
|
|
BeerPostID
|
|
CommentedByID
|
|
}
|
|
}
|
|
|
|
Ref: Photo.UploadedByID > UserAccount.UserAccountID [delete: no action]
|
|
Ref: UserAvatar.PhotoID > Photo.PhotoID [delete: no action]
|
|
Ref: UserAvatar.UserProfileID > UserProfile.UserProfileID [delete: cascade]
|
|
Ref: UserProfile.UserAccountID - UserAccount.UserAccountID [delete: cascade]
|
|
Ref: UserVerification.UserAccountID - UserAccount.UserAccountID [delete: cascade]
|
|
Ref: UserCredential.UserAccountID > UserAccount.UserAccountID [delete: cascade]
|
|
Ref: UserFollow.UserAccountID > UserAccount.UserAccountID [delete: no action]
|
|
Ref: UserFollow.FollowingID > UserAccount.UserAccountID [delete: no action]
|
|
Ref: StateProvince.CountryID > Country.CountryID
|
|
Ref: City.StateProvinceID > StateProvince.StateProvinceID
|
|
Ref: BreweryPost.PostedByID > UserAccount.UserAccountID [delete: no action]
|
|
Ref: BreweryPostLocation.BreweryPostID - BreweryPost.BreweryPostID [delete: cascade]
|
|
Ref: BreweryPostLocation.CityID > City.CityID
|
|
Ref: BreweryPostPhoto.BreweryPostID > BreweryPost.BreweryPostID [delete: cascade]
|
|
Ref: BreweryPostPhoto.PhotoID > Photo.PhotoID [delete: cascade]
|
|
Ref: BeerPost.PostedByID > UserAccount.UserAccountID [delete: no action]
|
|
Ref: BeerPost.BeerStyleID > BeerStyle.BeerStyleID
|
|
Ref: BeerPost.BrewedByID > BreweryPost.BreweryPostID
|
|
Ref: BeerPostPhoto.BeerPostID > BeerPost.BeerPostID [delete: cascade]
|
|
Ref: BeerPostPhoto.PhotoID > Photo.PhotoID [delete: cascade]
|
|
Ref: BeerPostComment.BeerPostID > BeerPost.BeerPostID
|
|
Ref: BeerPostComment.CommentedByID > UserAccount.UserAccountID [delete: no action]
|