@natrave/shared-entities 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.changeset/README.md +9 -0
- package/.changeset/config.json +11 -0
- package/.github/workflows/release.yml +80 -0
- package/.husky/pre-commit +4 -0
- package/.husky/pre-push +4 -0
- package/.lintstagedrc.json +5 -0
- package/.prettierignore +2 -0
- package/.prettierrc.json +12 -0
- package/CHANGELOG.md +13 -0
- package/eslint.config.js +84 -0
- package/package.json +52 -0
- package/src/app-auth/index.ts +5 -0
- package/src/app-auth/password-resets/index.ts +1 -0
- package/src/app-auth/password-resets/password-reset.entity.ts +52 -0
- package/src/app-auth/refresh-tokens/index.ts +1 -0
- package/src/app-auth/refresh-tokens/refresh-token.entity.ts +52 -0
- package/src/app-auth/user-auth-providers/enums/auth-provider.enum.ts +24 -0
- package/src/app-auth/user-auth-providers/index.ts +3 -0
- package/src/app-auth/user-auth-providers/user-auth-provider.entity.ts +58 -0
- package/src/app-auth/user-verifications/enums/verification-type.enum.ts +19 -0
- package/src/app-auth/user-verifications/index.ts +3 -0
- package/src/app-auth/user-verifications/user-verification.entity.ts +62 -0
- package/src/app-auth/users/index.ts +1 -0
- package/src/app-auth/users/user.entity.ts +149 -0
- package/src/app-auth/users/utils/format-data.utils.ts +38 -0
- package/src/common/utils/decimal-transformer.utils.ts +13 -0
- package/src/facilities/addresses/address.entity.ts +82 -0
- package/src/facilities/addresses/index.ts +1 -0
- package/src/facilities/facilities/enums/facility-status.enum.ts +25 -0
- package/src/facilities/facilities/facility.entity.ts +137 -0
- package/src/facilities/facilities/index.ts +3 -0
- package/src/facilities/facilities/utils/sanititze.utils.ts +19 -0
- package/src/facilities/facility-images/facility-image.entity.ts +64 -0
- package/src/facilities/facility-images/index.ts +1 -0
- package/src/facilities/facility-owners/facility-owner.entity.ts +74 -0
- package/src/facilities/facility-owners/index.ts +1 -0
- package/src/facilities/facility-owners/utils/sanitize.utils.ts +16 -0
- package/src/facilities/fields/enums/surface-type.enum.ts +35 -0
- package/src/facilities/fields/field.entity.ts +74 -0
- package/src/facilities/fields/index.ts +3 -0
- package/src/facilities/index.ts +5 -0
- package/src/index.ts +7 -0
- package/src/payments/index.ts +5 -0
- package/src/payments/payment-providers/enums/payment-provider-name.enum.ts +15 -0
- package/src/payments/payment-providers/index.ts +3 -0
- package/src/payments/payment-providers/payment-provider.entity.ts +61 -0
- package/src/payments/payments/enums/payment-method.enum.ts +20 -0
- package/src/payments/payments/enums/payment-status.enum.ts +45 -0
- package/src/payments/payments/index.ts +5 -0
- package/src/payments/payments/payment.entity.ts +84 -0
- package/src/payments/user-payment-providers/index.ts +1 -0
- package/src/payments/user-payment-providers/user-payment-provider.entity.ts +73 -0
- package/src/tournaments/index.ts +12 -0
- package/src/tournaments/tournament-facilities/index.ts +1 -0
- package/src/tournaments/tournament-facilities/tournament-facility.entity.ts +67 -0
- package/src/tournaments/tournament-format-configs/index.ts +1 -0
- package/src/tournaments/tournament-format-configs/tournament-format-config.entity.ts +69 -0
- package/src/tournaments/tournament-match-cards/index.ts +1 -0
- package/src/tournaments/tournament-match-cards/tournament-match-card.entity.ts +86 -0
- package/src/tournaments/tournament-match-goals/index.ts +1 -0
- package/src/tournaments/tournament-match-goals/tournament-match-goal.entity.ts +88 -0
- package/src/tournaments/tournament-match-schemas/index.ts +1 -0
- package/src/tournaments/tournament-match-schemas/tournament-match-schema.entity.ts +51 -0
- package/src/tournaments/tournament-matches/index.ts +1 -0
- package/src/tournaments/tournament-matches/tournament-match.entity.ts +101 -0
- package/src/tournaments/tournament-payments/index.ts +1 -0
- package/src/tournaments/tournament-payments/tournament-payment.entity.ts +67 -0
- package/src/tournaments/tournament-players/index.ts +1 -0
- package/src/tournaments/tournament-players/tournament-player.entity.ts +96 -0
- package/src/tournaments/tournament-prize-rules/index.ts +1 -0
- package/src/tournaments/tournament-prize-rules/tournament-prize-rule.entity.ts +65 -0
- package/src/tournaments/tournament-rules/index.ts +1 -0
- package/src/tournaments/tournament-rules/tournament-rule.entity.ts +81 -0
- package/src/tournaments/tournament-teams/index.ts +1 -0
- package/src/tournaments/tournament-teams/tournament-team.entity.ts +111 -0
- package/src/tournaments/tournament-teams/utils/invite-code-generator.ts +12 -0
- package/src/tournaments/tournaments/index.ts +1 -0
- package/src/tournaments/tournaments/tournament.entity.ts +153 -0
- package/tsconfig.json +29 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Entity,
|
|
3
|
+
Column,
|
|
4
|
+
PrimaryGeneratedColumn,
|
|
5
|
+
CreateDateColumn,
|
|
6
|
+
UpdateDateColumn,
|
|
7
|
+
DeleteDateColumn,
|
|
8
|
+
Unique,
|
|
9
|
+
OneToMany,
|
|
10
|
+
BeforeInsert,
|
|
11
|
+
} from 'typeorm';
|
|
12
|
+
|
|
13
|
+
import { PasswordReset } from 'app-auth/password-resets';
|
|
14
|
+
import { RefreshToken } from 'app-auth/refresh-tokens';
|
|
15
|
+
import { UserAuthProvider } from 'app-auth/user-auth-providers';
|
|
16
|
+
import { UserVerification } from 'app-auth/user-verifications';
|
|
17
|
+
import { UserPaymentProvider } from 'payments';
|
|
18
|
+
import { TournamentPlayer } from 'tournaments';
|
|
19
|
+
|
|
20
|
+
import { formatUserBeforeInsertData } from './utils/format-data.utils';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Entidade que representa um usuário.
|
|
24
|
+
*
|
|
25
|
+
* @remarks
|
|
26
|
+
* Esta entidade armazena os dados essenciais de um usuário, como nome, email, username, CPF, telefone e senha.
|
|
27
|
+
* Além disso, mantém a associação com outras entidades, como tokens de atualização, resets de senha,
|
|
28
|
+
* verificações, provedores de autenticação, sessões de jogo, jogadores de torneio e provedores de pagamento.
|
|
29
|
+
*
|
|
30
|
+
* @public
|
|
31
|
+
*/
|
|
32
|
+
@Entity('users')
|
|
33
|
+
@Unique(['email'])
|
|
34
|
+
@Unique(['username'])
|
|
35
|
+
@Unique(['phone'])
|
|
36
|
+
@Unique(['cpf'])
|
|
37
|
+
export class User {
|
|
38
|
+
@PrimaryGeneratedColumn('uuid')
|
|
39
|
+
id: string;
|
|
40
|
+
|
|
41
|
+
@Column({
|
|
42
|
+
name: 'numeric_id',
|
|
43
|
+
type: 'int',
|
|
44
|
+
unique: true,
|
|
45
|
+
nullable: false,
|
|
46
|
+
generated: 'increment',
|
|
47
|
+
})
|
|
48
|
+
numericId: number;
|
|
49
|
+
|
|
50
|
+
@CreateDateColumn({ name: 'created_at', type: 'timestamptz' })
|
|
51
|
+
createdAt: Date;
|
|
52
|
+
|
|
53
|
+
@UpdateDateColumn({ name: 'updated_at', type: 'timestamptz' })
|
|
54
|
+
updatedAt: Date;
|
|
55
|
+
|
|
56
|
+
@DeleteDateColumn({ name: 'deleted_at', type: 'timestamptz', nullable: true })
|
|
57
|
+
deletedAt?: Date;
|
|
58
|
+
|
|
59
|
+
@Column({ name: 'first_name', type: 'varchar', length: 255, nullable: true })
|
|
60
|
+
firstName?: string;
|
|
61
|
+
|
|
62
|
+
@Column({ name: 'last_name', type: 'varchar', length: 255, nullable: true })
|
|
63
|
+
lastName?: string;
|
|
64
|
+
|
|
65
|
+
@Column({ type: 'varchar', length: 255, unique: true })
|
|
66
|
+
email: string;
|
|
67
|
+
|
|
68
|
+
@Column({ type: 'varchar', length: 255, unique: true, nullable: true })
|
|
69
|
+
username: string;
|
|
70
|
+
|
|
71
|
+
@Column({ type: 'varchar', length: 14, nullable: true, unique: true })
|
|
72
|
+
cpf?: string;
|
|
73
|
+
|
|
74
|
+
@Column({
|
|
75
|
+
name: 'phone',
|
|
76
|
+
type: 'varchar',
|
|
77
|
+
length: 16,
|
|
78
|
+
unique: true,
|
|
79
|
+
nullable: true,
|
|
80
|
+
})
|
|
81
|
+
phone?: string;
|
|
82
|
+
|
|
83
|
+
@Column({
|
|
84
|
+
name: 'password_hash',
|
|
85
|
+
type: 'varchar',
|
|
86
|
+
length: 255,
|
|
87
|
+
nullable: true,
|
|
88
|
+
})
|
|
89
|
+
passwordHash: string | null;
|
|
90
|
+
|
|
91
|
+
@Column({ name: 'image_url', type: 'varchar', length: 500, nullable: true })
|
|
92
|
+
imageUrl?: string;
|
|
93
|
+
|
|
94
|
+
/** RELAÇÕES */
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Relação com os tokens de atualização do usuário.
|
|
98
|
+
*/
|
|
99
|
+
@OneToMany(() => RefreshToken, (refreshToken) => refreshToken.user)
|
|
100
|
+
refreshTokens: RefreshToken[];
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Relação com os resets de senha do usuário.
|
|
104
|
+
*/
|
|
105
|
+
@OneToMany(() => PasswordReset, (passwordReset) => passwordReset.user)
|
|
106
|
+
passwordResets: PasswordReset[];
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Relação com as verificações do usuário.
|
|
110
|
+
*/
|
|
111
|
+
@OneToMany(() => UserVerification, (verification) => verification.user)
|
|
112
|
+
verifications: UserVerification[];
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Relação com os provedores de autenticação associados ao usuário.
|
|
116
|
+
*/
|
|
117
|
+
@OneToMany(() => UserAuthProvider, (userAuthProvider) => userAuthProvider.user, {
|
|
118
|
+
cascade: true,
|
|
119
|
+
})
|
|
120
|
+
userAuthProviders: UserAuthProvider[];
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Relação com os jogadores de torneio associados ao usuário.
|
|
124
|
+
*/
|
|
125
|
+
@OneToMany(() => TournamentPlayer, (tournamentPlayer) => tournamentPlayer.user, {
|
|
126
|
+
cascade: true,
|
|
127
|
+
})
|
|
128
|
+
tournamentPlayers: TournamentPlayer[];
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Relação com os provedores de pagamento associados ao usuário.
|
|
132
|
+
*/
|
|
133
|
+
@OneToMany(() => UserPaymentProvider, (userPaymentProvider) => userPaymentProvider.user, {
|
|
134
|
+
cascade: true,
|
|
135
|
+
})
|
|
136
|
+
userPaymentProviders: UserPaymentProvider[];
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Prepara os dados do usuário antes de inserir no banco.
|
|
140
|
+
*
|
|
141
|
+
* @remarks
|
|
142
|
+
* A lógica de formatação e validação dos dados é delegada à função externa `formatUserData`,
|
|
143
|
+
* seguindo o princípio de responsabilidade única (SRP) e facilitando a manutenção e testabilidade do código.
|
|
144
|
+
*/
|
|
145
|
+
@BeforeInsert()
|
|
146
|
+
prepareData(): void {
|
|
147
|
+
formatUserBeforeInsertData(this);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formata os dados do usuário antes de inseri-los no banco.
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* Esta função ajusta os campos de email, username, CPF e telefone do usuário:
|
|
6
|
+
* - Converte email e username para minúsculas e remove espaços desnecessários.
|
|
7
|
+
* - Remove caracteres não numéricos do CPF.
|
|
8
|
+
* - Remove caracteres não numéricos do telefone, adiciona o código do Brasil (55) se necessário e prefixa com "+".
|
|
9
|
+
*
|
|
10
|
+
* @param user - A instância do usuário a ser formatada.
|
|
11
|
+
*/
|
|
12
|
+
export function formatUserBeforeInsertData(user: {
|
|
13
|
+
email?: string;
|
|
14
|
+
username?: string;
|
|
15
|
+
cpf?: string;
|
|
16
|
+
phone?: string;
|
|
17
|
+
}): void {
|
|
18
|
+
if (user.email) {
|
|
19
|
+
user.email = user.email.toLowerCase().trim();
|
|
20
|
+
}
|
|
21
|
+
if (user.username) {
|
|
22
|
+
user.username = user.username.toLowerCase().trim();
|
|
23
|
+
}
|
|
24
|
+
if (user.cpf) {
|
|
25
|
+
// Remove qualquer caractere que não seja número
|
|
26
|
+
user.cpf = user.cpf.replace(/\D/g, '').trim();
|
|
27
|
+
}
|
|
28
|
+
if (user.phone) {
|
|
29
|
+
// Remove todos os caracteres que não são números
|
|
30
|
+
user.phone = user.phone.replace(/\D/g, '').trim();
|
|
31
|
+
// Garante que o telefone tenha o código do Brasil (55)
|
|
32
|
+
if (!user.phone.startsWith('55')) {
|
|
33
|
+
user.phone = `55${user.phone}`;
|
|
34
|
+
}
|
|
35
|
+
// Adiciona o sinal de "+" ao início do telefone
|
|
36
|
+
user.phone = `+${user.phone}`;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const DecimalTransformer = {
|
|
2
|
+
to: (value: number): number => {
|
|
3
|
+
if (typeof value !== 'number' || isNaN(value)) {
|
|
4
|
+
return NaN;
|
|
5
|
+
}
|
|
6
|
+
return value;
|
|
7
|
+
},
|
|
8
|
+
from: (value: string): number => {
|
|
9
|
+
if (!value) return NaN;
|
|
10
|
+
const parsed = parseFloat(value.trim());
|
|
11
|
+
return isNaN(parsed) ? NaN : parsed;
|
|
12
|
+
},
|
|
13
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Entity,
|
|
3
|
+
Column,
|
|
4
|
+
PrimaryGeneratedColumn,
|
|
5
|
+
CreateDateColumn,
|
|
6
|
+
UpdateDateColumn,
|
|
7
|
+
OneToMany,
|
|
8
|
+
} from 'typeorm';
|
|
9
|
+
|
|
10
|
+
import { DecimalTransformer } from 'common/utils/decimal-transformer.utils';
|
|
11
|
+
import { Facility } from 'facilities/facilities/facility.entity';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Entidade que representa um endereço.
|
|
15
|
+
*
|
|
16
|
+
* @remarks
|
|
17
|
+
* Esta entidade armazena os dados de endereço, como rua, número, complemento, bairro, cidade, estado,
|
|
18
|
+
* código postal, país, latitude e longitude. Além disso, mantém a relação com o estabelecimentos associadas a este endereço.
|
|
19
|
+
*
|
|
20
|
+
* @public
|
|
21
|
+
*/
|
|
22
|
+
@Entity('addresses')
|
|
23
|
+
export class Address {
|
|
24
|
+
@PrimaryGeneratedColumn()
|
|
25
|
+
id: number;
|
|
26
|
+
|
|
27
|
+
@CreateDateColumn({ name: 'created_at', type: 'timestamptz' })
|
|
28
|
+
createdAt: Date;
|
|
29
|
+
|
|
30
|
+
@UpdateDateColumn({ name: 'updated_at', type: 'timestamptz' })
|
|
31
|
+
updatedAt: Date;
|
|
32
|
+
|
|
33
|
+
@Column({ name: 'street_address', type: 'varchar', length: 255 })
|
|
34
|
+
streetAddress: string;
|
|
35
|
+
|
|
36
|
+
@Column({ type: 'varchar', length: 10 })
|
|
37
|
+
number: string;
|
|
38
|
+
|
|
39
|
+
@Column({ type: 'varchar', length: 100, nullable: true })
|
|
40
|
+
complement?: string;
|
|
41
|
+
|
|
42
|
+
@Column({ type: 'varchar', length: 100 })
|
|
43
|
+
neighborhood: string;
|
|
44
|
+
|
|
45
|
+
@Column({ type: 'varchar', length: 100 })
|
|
46
|
+
city: string;
|
|
47
|
+
|
|
48
|
+
@Column({ type: 'varchar', length: 100 })
|
|
49
|
+
state: string;
|
|
50
|
+
|
|
51
|
+
@Column({ name: 'postal_code', type: 'varchar', length: 20 })
|
|
52
|
+
postalCode: string;
|
|
53
|
+
|
|
54
|
+
@Column({ type: 'varchar', length: 100 })
|
|
55
|
+
country: string;
|
|
56
|
+
|
|
57
|
+
@Column({
|
|
58
|
+
type: 'decimal',
|
|
59
|
+
precision: 10,
|
|
60
|
+
scale: 8,
|
|
61
|
+
transformer: DecimalTransformer,
|
|
62
|
+
})
|
|
63
|
+
latitude: number;
|
|
64
|
+
|
|
65
|
+
@Column({
|
|
66
|
+
type: 'decimal',
|
|
67
|
+
precision: 11,
|
|
68
|
+
scale: 8,
|
|
69
|
+
transformer: DecimalTransformer,
|
|
70
|
+
})
|
|
71
|
+
longitude: number;
|
|
72
|
+
|
|
73
|
+
/** RELAÇÕES */
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Relação com os estabelecimentos associadas a este endereço.
|
|
77
|
+
*/
|
|
78
|
+
@OneToMany(() => Facility, (facility) => facility.address, {
|
|
79
|
+
onDelete: 'CASCADE',
|
|
80
|
+
})
|
|
81
|
+
facilities: Facility[];
|
|
82
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Address } from './address.entity';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enum que representa os status dos estabelecimentos.
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* Este enum fornece valores para identificar o status de um estabelecimento,
|
|
6
|
+
* garantindo consistência ao referenciar o status na aplicação.
|
|
7
|
+
*
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
export enum FacilityStatus {
|
|
11
|
+
/**
|
|
12
|
+
* Estabelecimento pendente de aprovação.
|
|
13
|
+
*/
|
|
14
|
+
PENDING = 'pending',
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Estabelecimento aprovado.
|
|
18
|
+
*/
|
|
19
|
+
APPROVED = 'approved',
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Estabelecimento rejeitado.
|
|
23
|
+
*/
|
|
24
|
+
REJECTED = 'rejected',
|
|
25
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Entity,
|
|
3
|
+
Column,
|
|
4
|
+
PrimaryGeneratedColumn,
|
|
5
|
+
CreateDateColumn,
|
|
6
|
+
UpdateDateColumn,
|
|
7
|
+
DeleteDateColumn,
|
|
8
|
+
Unique,
|
|
9
|
+
OneToMany,
|
|
10
|
+
BeforeInsert,
|
|
11
|
+
BeforeUpdate,
|
|
12
|
+
ManyToOne,
|
|
13
|
+
JoinColumn,
|
|
14
|
+
Index,
|
|
15
|
+
} from 'typeorm';
|
|
16
|
+
|
|
17
|
+
import { Address } from 'facilities/addresses';
|
|
18
|
+
import { FacilityImage } from 'facilities/facility-images';
|
|
19
|
+
import { FacilityOwner } from 'facilities/facility-owners';
|
|
20
|
+
import { Field } from 'facilities/fields';
|
|
21
|
+
import { TournamentFacility } from 'tournaments';
|
|
22
|
+
|
|
23
|
+
import { FacilityStatus } from './enums/facility-status.enum';
|
|
24
|
+
import { sanitizeFacility } from './utils/sanititze.utils';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Entidade que representa um estabelecimento.
|
|
28
|
+
*
|
|
29
|
+
* @remarks
|
|
30
|
+
* Esta entidade armazena os dados de um estabelecimento, incluindo informações de contato,
|
|
31
|
+
* status e CNPJ. Além disso, mantém as relações com o proprietário, endereço,
|
|
32
|
+
* campos, usuários, imagens e torneios associados a este estabelecimento.
|
|
33
|
+
*
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
36
|
+
@Entity('facilities')
|
|
37
|
+
@Unique(['name', 'facilityOwnerId'])
|
|
38
|
+
@Index('idx_facility_owner', ['facilityOwnerId'])
|
|
39
|
+
@Index('idx_facility_address', ['addressId'])
|
|
40
|
+
@Index('idx_facility_status', ['status'])
|
|
41
|
+
export class Facility {
|
|
42
|
+
@PrimaryGeneratedColumn()
|
|
43
|
+
id: number;
|
|
44
|
+
|
|
45
|
+
@Column({ name: 'facility_owner_id', type: 'int' })
|
|
46
|
+
facilityOwnerId: number;
|
|
47
|
+
|
|
48
|
+
@Column({ name: 'address_id', type: 'int' })
|
|
49
|
+
addressId: number;
|
|
50
|
+
|
|
51
|
+
@CreateDateColumn({ name: 'created_at', type: 'timestamptz' })
|
|
52
|
+
createdAt: Date;
|
|
53
|
+
|
|
54
|
+
@UpdateDateColumn({ name: 'updated_at', type: 'timestamptz' })
|
|
55
|
+
updatedAt: Date;
|
|
56
|
+
|
|
57
|
+
@Column({ name: 'name', type: 'varchar', length: 255 })
|
|
58
|
+
name: string;
|
|
59
|
+
|
|
60
|
+
@Column({
|
|
61
|
+
name: 'contact_email',
|
|
62
|
+
type: 'varchar',
|
|
63
|
+
length: 255,
|
|
64
|
+
nullable: true,
|
|
65
|
+
})
|
|
66
|
+
contactEmail?: string;
|
|
67
|
+
|
|
68
|
+
@Column({ name: 'contact_phone', type: 'varchar', length: 16 })
|
|
69
|
+
contactPhone: string;
|
|
70
|
+
|
|
71
|
+
@Column({
|
|
72
|
+
type: 'enum',
|
|
73
|
+
enum: FacilityStatus,
|
|
74
|
+
enumName: 'facility_status',
|
|
75
|
+
})
|
|
76
|
+
status: FacilityStatus = FacilityStatus.PENDING;
|
|
77
|
+
|
|
78
|
+
@Column({ name: 'cnpj', type: 'varchar', length: 14, nullable: true })
|
|
79
|
+
cnpj?: string;
|
|
80
|
+
|
|
81
|
+
@DeleteDateColumn({ name: 'deleted_at', type: 'timestamptz', nullable: true })
|
|
82
|
+
deletedAt: Date | null = null;
|
|
83
|
+
|
|
84
|
+
/** RELAÇÕES */
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Relação com o endereço associado a este estabelecimento.
|
|
88
|
+
*/
|
|
89
|
+
@ManyToOne(() => Address, (address) => address.facilities, {
|
|
90
|
+
eager: true,
|
|
91
|
+
onDelete: 'CASCADE',
|
|
92
|
+
onUpdate: 'CASCADE',
|
|
93
|
+
})
|
|
94
|
+
@JoinColumn({ name: 'address_id' })
|
|
95
|
+
address: Address;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Relação com o owner associado a este estabelecimento.
|
|
99
|
+
*/
|
|
100
|
+
@ManyToOne(() => FacilityOwner, (owner) => owner.facilities, {
|
|
101
|
+
onDelete: 'CASCADE',
|
|
102
|
+
onUpdate: 'CASCADE',
|
|
103
|
+
})
|
|
104
|
+
@JoinColumn({ name: 'facility_owner_id' })
|
|
105
|
+
facilityOwner: FacilityOwner;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Relação com os campos associados a este estabelecimento.
|
|
109
|
+
*/
|
|
110
|
+
@OneToMany(() => Field, (field) => field.facility)
|
|
111
|
+
fields: Field[];
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Relação com as imagens do estabelecimento.
|
|
115
|
+
*/
|
|
116
|
+
@OneToMany(() => FacilityImage, (facilityImage) => facilityImage.facility)
|
|
117
|
+
facilityImages: FacilityImage[];
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Relação com os torneios associados a este estabelecimento.
|
|
121
|
+
*/
|
|
122
|
+
@OneToMany(() => TournamentFacility, (tournamentFacility) => tournamentFacility.facility)
|
|
123
|
+
tournamentFacilities: TournamentFacility[];
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Sanitiza os campos do estabelecimento antes de inserir ou atualizar o registro.
|
|
127
|
+
*
|
|
128
|
+
* @remarks
|
|
129
|
+
* A lógica de sanitização foi delegada à função externa `sanitizeFacility`,
|
|
130
|
+
* seguindo o princípio de responsabilidade única (SRP) para facilitar a manutenção e testabilidade.
|
|
131
|
+
*/
|
|
132
|
+
@BeforeInsert()
|
|
133
|
+
@BeforeUpdate()
|
|
134
|
+
sanitizeFields(): void {
|
|
135
|
+
sanitizeFacility(this);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sanitiza os campos do estabelecimento.
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* Esta função remove caracteres não numéricos do CNPJ e sanitiza o email de contato.
|
|
6
|
+
*
|
|
7
|
+
* @param facility - A instância do estabelecimento a ser sanitizada.
|
|
8
|
+
*/
|
|
9
|
+
export function sanitizeFacility(facility: { cnpj?: string; contactEmail?: string }): void {
|
|
10
|
+
if (facility.cnpj) {
|
|
11
|
+
facility.cnpj = facility.cnpj.replace(/[^\d]/g, '').trim();
|
|
12
|
+
if (facility.cnpj.length !== 14) {
|
|
13
|
+
facility.cnpj = undefined;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
if (facility.contactEmail) {
|
|
17
|
+
facility.contactEmail = facility.contactEmail.toLowerCase().trim();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Entity,
|
|
3
|
+
Column,
|
|
4
|
+
PrimaryGeneratedColumn,
|
|
5
|
+
CreateDateColumn,
|
|
6
|
+
UpdateDateColumn,
|
|
7
|
+
ManyToOne,
|
|
8
|
+
JoinColumn,
|
|
9
|
+
Index,
|
|
10
|
+
Unique,
|
|
11
|
+
} from 'typeorm';
|
|
12
|
+
|
|
13
|
+
import { Facility } from 'facilities/facilities';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Entidade que representa uma imagem de estabelecimento.
|
|
17
|
+
*
|
|
18
|
+
* @remarks
|
|
19
|
+
* Esta entidade armazena os dados de uma imagem associada a um estabelecimento,
|
|
20
|
+
* incluindo a URL, descrição e indicação se a imagem é a principal.
|
|
21
|
+
* Além disso, mantém a relação com o estabelecimento ao qual a imagem está associada.
|
|
22
|
+
*
|
|
23
|
+
* @public
|
|
24
|
+
*/
|
|
25
|
+
@Entity('facility_images')
|
|
26
|
+
@Index('IDX_facility_images_facilityId', ['facilityId'])
|
|
27
|
+
@Index('IDX_facility_images_unique_primary', ['facilityId'], {
|
|
28
|
+
unique: true,
|
|
29
|
+
where: `"is_primary" = true`,
|
|
30
|
+
})
|
|
31
|
+
@Unique('UQ_facility_images_facility_url', ['facilityId', 'url'])
|
|
32
|
+
export class FacilityImage {
|
|
33
|
+
@PrimaryGeneratedColumn()
|
|
34
|
+
id: number;
|
|
35
|
+
|
|
36
|
+
@Column({ name: 'facility_id', type: 'int' })
|
|
37
|
+
facilityId: number;
|
|
38
|
+
|
|
39
|
+
@CreateDateColumn({ name: 'created_at', type: 'timestamptz' })
|
|
40
|
+
createdAt: Date;
|
|
41
|
+
|
|
42
|
+
@UpdateDateColumn({ name: 'updated_at', type: 'timestamptz' })
|
|
43
|
+
updatedAt: Date;
|
|
44
|
+
|
|
45
|
+
@Column({ type: 'text' })
|
|
46
|
+
url: string;
|
|
47
|
+
|
|
48
|
+
@Column({ type: 'text', nullable: true, default: null })
|
|
49
|
+
description: string;
|
|
50
|
+
|
|
51
|
+
@Column({ name: 'is_primary', type: 'boolean', default: false })
|
|
52
|
+
isPrimary: boolean;
|
|
53
|
+
|
|
54
|
+
/** RELAÇÕES */
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Relação com o estabelecimento ao qual esta imagem está associada.
|
|
58
|
+
*/
|
|
59
|
+
@ManyToOne(() => Facility, (facility) => facility.facilityImages, {
|
|
60
|
+
onDelete: 'CASCADE',
|
|
61
|
+
})
|
|
62
|
+
@JoinColumn({ name: 'facility_id' })
|
|
63
|
+
facility: Facility;
|
|
64
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { FacilityImage } from './facility-image.entity';
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Entity,
|
|
3
|
+
Column,
|
|
4
|
+
PrimaryGeneratedColumn,
|
|
5
|
+
CreateDateColumn,
|
|
6
|
+
UpdateDateColumn,
|
|
7
|
+
Unique,
|
|
8
|
+
BeforeInsert,
|
|
9
|
+
BeforeUpdate,
|
|
10
|
+
OneToMany,
|
|
11
|
+
Index,
|
|
12
|
+
} from 'typeorm';
|
|
13
|
+
|
|
14
|
+
import { Facility } from 'facilities/facilities/facility.entity';
|
|
15
|
+
|
|
16
|
+
import { sanitizeFacilityOwner } from './utils/sanitize.utils';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Entidade que representa um proprietário de estabelecimento.
|
|
20
|
+
*
|
|
21
|
+
* @remarks
|
|
22
|
+
* Esta entidade armazena os dados de um proprietário, como nome, email de contato, CNPJ e telefone.
|
|
23
|
+
* Também mantém as relações com estabelecimentos.
|
|
24
|
+
*
|
|
25
|
+
* @public
|
|
26
|
+
*/
|
|
27
|
+
@Entity('facility_owners')
|
|
28
|
+
@Unique(['contactEmail'])
|
|
29
|
+
@Unique(['cnpj'])
|
|
30
|
+
export class FacilityOwner {
|
|
31
|
+
@PrimaryGeneratedColumn()
|
|
32
|
+
id: number;
|
|
33
|
+
|
|
34
|
+
@CreateDateColumn({ name: 'created_at', type: 'timestamptz' })
|
|
35
|
+
createdAt: Date;
|
|
36
|
+
|
|
37
|
+
@UpdateDateColumn({ name: 'updated_at', type: 'timestamptz' })
|
|
38
|
+
updatedAt: Date;
|
|
39
|
+
|
|
40
|
+
@Column({ type: 'varchar', length: 255 })
|
|
41
|
+
name: string;
|
|
42
|
+
|
|
43
|
+
@Index()
|
|
44
|
+
@Column({ name: 'contact_email', type: 'varchar', length: 255, nullable: true })
|
|
45
|
+
contactEmail: string;
|
|
46
|
+
|
|
47
|
+
@Index()
|
|
48
|
+
@Column({ name: 'cnpj', type: 'varchar', length: 14, nullable: true })
|
|
49
|
+
cnpj?: string;
|
|
50
|
+
|
|
51
|
+
@Column({ name: 'contact_phone', type: 'varchar', length: 16 })
|
|
52
|
+
contactPhone: string;
|
|
53
|
+
|
|
54
|
+
/** RELAÇÕES */
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Relação com os estabelecimentos associadas a este proprietário.
|
|
58
|
+
*/
|
|
59
|
+
@OneToMany(() => Facility, (facility) => facility.facilityOwner)
|
|
60
|
+
facilities: Facility[];
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Sanitiza os campos do proprietário antes de inserir ou atualizar o registro.
|
|
64
|
+
*
|
|
65
|
+
* @remarks
|
|
66
|
+
* A lógica de sanitização foi delegada à função externa `sanitizeFacilityOwner`,
|
|
67
|
+
* seguindo o princípio de responsabilidade única (SRP) e facilitando a manutenção e testabilidade do código.
|
|
68
|
+
*/
|
|
69
|
+
@BeforeInsert()
|
|
70
|
+
@BeforeUpdate()
|
|
71
|
+
sanitizeFields(): void {
|
|
72
|
+
sanitizeFacilityOwner(this);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { FacilityOwner } from './facility-owner.entity';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sanitiza os campos do proprietário do estabelecimento.
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* Esta função remove caracteres não numéricos do CNPJ e converte o email de contato para minúsculas, removendo espaços.
|
|
6
|
+
*
|
|
7
|
+
* @param owner - A instância de FacilityOwner a ser sanitizada.
|
|
8
|
+
*/
|
|
9
|
+
export function sanitizeFacilityOwner(owner: { cnpj?: string; contactEmail?: string }): void {
|
|
10
|
+
if (owner.cnpj) {
|
|
11
|
+
owner.cnpj = owner.cnpj.replace(/[^\d]/g, '').trim();
|
|
12
|
+
}
|
|
13
|
+
if (owner.contactEmail) {
|
|
14
|
+
owner.contactEmail = owner.contactEmail.toLowerCase().trim();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enum que representa os tipos de superfície de um campo.
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* Este enum fornece os valores possíveis para o tipo de superfície de um campo,
|
|
6
|
+
* permitindo diferenciar entre gramado, sintético, areia, madeira, entre outros.
|
|
7
|
+
*
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
export enum FieldSurfaceType {
|
|
11
|
+
/**
|
|
12
|
+
* Campo com superfície de grama natural.
|
|
13
|
+
*/
|
|
14
|
+
GRASS = 'grass',
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Campo com superfície de grama sintética (turf).
|
|
18
|
+
*/
|
|
19
|
+
TURF = 'turf',
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Campo com superfície de saibro (clay).
|
|
23
|
+
*/
|
|
24
|
+
CLAY = 'clay',
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Campo com superfície de areia.
|
|
28
|
+
*/
|
|
29
|
+
SAND = 'sand',
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Campo com superfície de madeira (indoor).
|
|
33
|
+
*/
|
|
34
|
+
HARDWOOD = 'hardwood',
|
|
35
|
+
}
|