Spaces:
Configuration error
Configuration error
Commit ·
158bb31
1
Parent(s): 1177d61
Deploy files from GitHub repository
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- main.go +5 -0
- models/database_orm_model.go +1 -1
- models/exception_model.go +18 -15
- models/request_model.go +116 -116
- response/api_response_v2.go +16 -1
- response/validation.go +14 -0
- services/cv_service.go +384 -343
- space/go.sum +2 -0
- space/models/database_orm_model.go +32 -31
- space/models/request_model.go +62 -59
- space/space/controller/quiz/list_quiz_controller.go +23 -0
- space/space/go.mod +4 -3
- space/space/router/quiz_route.go +1 -0
- space/space/services/academy_quiz_service.go +20 -3
- space/space/space/config/database_connection_config.go +3 -0
- space/space/space/controller/cv/cv_controller.go +288 -0
- space/space/space/models/database_orm_model.go +39 -0
- space/space/space/models/request_model.go +23 -0
- space/space/space/repositories/cv_repository.go +117 -0
- space/space/space/router/cv_route.go +18 -0
- space/space/space/services/cv_service.go +167 -0
- space/space/space/space/controller/user/user_profile_controller.go +21 -21
- space/space/space/space/controller/user/user_update_profile_controller.go +25 -25
- space/space/space/space/repositories/account_repository.go +87 -87
- space/space/space/space/services/external_authentication_service.go +81 -81
- space/space/space/space/services/user_profile_service.go +4 -4
- space/space/space/space/space/config/database_connection_config.go +4 -0
- space/space/space/space/space/controller/cv/cv_controller.go +267 -0
- space/space/space/space/space/main.go +9 -1
- space/space/space/space/space/middleware/authentication_middleware.go +7 -0
- space/space/space/space/space/models/database_orm_model.go +118 -33
- space/space/space/space/space/models/request_model.go +126 -51
- space/space/space/space/space/repositories/cv_repository.go +126 -0
- space/space/space/space/space/router/cv_route.go +26 -0
- space/space/space/space/space/router/router.go +11 -10
- space/space/space/space/space/router/server.go +4 -0
- space/space/space/space/space/services/cv_service.go +277 -0
- space/space/space/space/space/space/space/.gitignore +1 -0
- space/space/space/space/space/space/space/controller/health_check/health_check_controller.go +12 -8
- space/space/space/space/space/space/space/main.go +2 -2
- space/space/space/space/space/space/space/models/database_orm_model.go +207 -207
- space/space/space/space/space/space/space/models/exception_model.go +19 -13
- space/space/space/space/space/space/space/models/health_check_model.go +1 -3
- space/space/space/space/space/space/space/repositories/health_check_repository.go +12 -13
- space/space/space/space/space/space/space/response/api_response_v2.go +79 -0
- space/space/space/space/space/space/space/response/gorm.go +62 -0
- space/space/space/space/space/space/space/router/server.go +2 -2
- space/space/space/space/space/space/space/services/health_check_service.go +31 -0
- space/space/space/space/space/space/space/services/user_profile_service.go +115 -115
- space/space/space/space/space/space/space/space/Dockerfile +6 -0
main.go
CHANGED
|
@@ -9,6 +9,7 @@ import (
|
|
| 9 |
"api.qobiltu.id/router"
|
| 10 |
"api.qobiltu.id/services"
|
| 11 |
"api.qobiltu.id/utils"
|
|
|
|
| 12 |
"api.qobiltu.id/worker"
|
| 13 |
"github.com/hibiken/asynq"
|
| 14 |
"log/slog"
|
|
@@ -18,6 +19,10 @@ import (
|
|
| 18 |
|
| 19 |
func main() {
|
| 20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
// setup email sender
|
| 22 |
emailConfig := mail.Config{
|
| 23 |
Host: config.SMTP_HOST,
|
|
|
|
| 9 |
"api.qobiltu.id/router"
|
| 10 |
"api.qobiltu.id/services"
|
| 11 |
"api.qobiltu.id/utils"
|
| 12 |
+
"api.qobiltu.id/validation"
|
| 13 |
"api.qobiltu.id/worker"
|
| 14 |
"github.com/hibiken/asynq"
|
| 15 |
"log/slog"
|
|
|
|
| 19 |
|
| 20 |
func main() {
|
| 21 |
|
| 22 |
+
// setup validation
|
| 23 |
+
err := validation.New(validation.LocaleID)
|
| 24 |
+
utils.FatalIfErr("failed to setup validator", err)
|
| 25 |
+
|
| 26 |
// setup email sender
|
| 27 |
emailConfig := mail.Config{
|
| 28 |
Host: config.SMTP_HOST,
|
models/database_orm_model.go
CHANGED
|
@@ -268,7 +268,7 @@ type (
|
|
| 268 |
ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` // id
|
| 269 |
AccountID int64 `gorm:"column:account_id;not null" json:"account_id"` // id akun
|
| 270 |
Account *Account `gorm:"foreignKey:AccountID;constraint:OnDelete:CASCADE" json:"account,omitempty"` // relasi ke akun
|
| 271 |
-
LastEducation *string `gorm:"column:last_education" json:"last_education"`
|
| 272 |
EducationInstitute *string `gorm:"column:education_institute" json:"education_institute"` // institusi pendidikan
|
| 273 |
EducationMajor *string `gorm:"column:education_major" json:"education_major"` // jurusan pendidikan
|
| 274 |
YearStart *int `gorm:"column:year_start" json:"year_start"` // tahun masuk
|
|
|
|
| 268 |
ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` // id
|
| 269 |
AccountID int64 `gorm:"column:account_id;not null" json:"account_id"` // id akun
|
| 270 |
Account *Account `gorm:"foreignKey:AccountID;constraint:OnDelete:CASCADE" json:"account,omitempty"` // relasi ke akun
|
| 271 |
+
LastEducation *string `gorm:"column:last_education" json:"last_education" validate:""` // pendidikan terakhir
|
| 272 |
EducationInstitute *string `gorm:"column:education_institute" json:"education_institute"` // institusi pendidikan
|
| 273 |
EducationMajor *string `gorm:"column:education_major" json:"education_major"` // jurusan pendidikan
|
| 274 |
YearStart *int `gorm:"column:year_start" json:"year_start"` // tahun masuk
|
models/exception_model.go
CHANGED
|
@@ -1,23 +1,26 @@
|
|
| 1 |
package models
|
| 2 |
|
|
|
|
|
|
|
| 3 |
type Exception struct {
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
|
| 17 |
-
|
| 18 |
-
|
|
|
|
| 19 |
}
|
| 20 |
|
| 21 |
func (a Exception) Error() string {
|
| 22 |
-
|
| 23 |
}
|
|
|
|
| 1 |
package models
|
| 2 |
|
| 3 |
+
import "api.qobiltu.id/validation"
|
| 4 |
+
|
| 5 |
type Exception struct {
|
| 6 |
+
Unauthorized bool `json:"unauthorized,omitempty"`
|
| 7 |
+
BadRequest bool `json:"bad_request,omitempty"`
|
| 8 |
+
DataNotFound bool `json:"data_not_found,omitempty"`
|
| 9 |
+
InternalServerError bool `json:"internal_server_error,omitempty"`
|
| 10 |
+
DataDuplicate bool `json:"data_duplicate,omitempty"`
|
| 11 |
+
QueryError bool `json:"query_error,omitempty"`
|
| 12 |
+
InvalidPasswordLength bool `json:"invalid_password_length,omitempty"`
|
| 13 |
+
IsPassTheLimit bool `json:"is_pass_the_limit,omitempty"`
|
| 14 |
+
IsTimeOut bool `json:"is_time_out,omitempty"`
|
| 15 |
+
AttemptNotFound bool `json:"attempt_not_found,omitempty"`
|
| 16 |
+
Forbidden bool `json:"forbidden,omitempty"`
|
| 17 |
+
ValidationError bool `json:"validation_error,omitempty"`
|
| 18 |
|
| 19 |
+
Message string `json:"message,omitempty"`
|
| 20 |
+
Err error `json:"-"`
|
| 21 |
+
ValidationErrorFields []validation.ErrorMessage `json:"validation_error_fields,omitempty"`
|
| 22 |
}
|
| 23 |
|
| 24 |
func (a Exception) Error() string {
|
| 25 |
+
return a.Err.Error()
|
| 26 |
}
|
models/request_model.go
CHANGED
|
@@ -1,152 +1,152 @@
|
|
| 1 |
package models
|
| 2 |
|
| 3 |
import (
|
| 4 |
-
|
| 5 |
-
|
| 6 |
)
|
| 7 |
|
| 8 |
type LoginRequest struct {
|
| 9 |
-
|
| 10 |
-
|
| 11 |
}
|
| 12 |
|
| 13 |
type RegisterRequest struct {
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
}
|
| 19 |
|
| 20 |
type ChangePasswordRequest struct {
|
| 21 |
-
|
| 22 |
-
|
| 23 |
}
|
| 24 |
|
| 25 |
type CreateVerifyEmailRequest struct {
|
| 26 |
-
|
| 27 |
}
|
| 28 |
|
| 29 |
type OptionsRequest struct {
|
| 30 |
-
|
| 31 |
-
|
| 32 |
}
|
| 33 |
|
| 34 |
type ExternalAuthRequest struct {
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
}
|
| 40 |
|
| 41 |
type ForgotPasswordRequest struct {
|
| 42 |
-
|
| 43 |
}
|
| 44 |
type ValidateForgotPasswordRequest struct {
|
| 45 |
-
|
| 46 |
-
|
| 47 |
}
|
| 48 |
|
| 49 |
type QuestionQuizRequest struct {
|
| 50 |
-
|
| 51 |
}
|
| 52 |
|
| 53 |
type AnswerQuizRequest struct {
|
| 54 |
-
|
| 55 |
-
|
| 56 |
}
|
| 57 |
|
| 58 |
type (
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
)
|
|
|
|
| 1 |
package models
|
| 2 |
|
| 3 |
import (
|
| 4 |
+
"github.com/lib/pq"
|
| 5 |
+
"time"
|
| 6 |
)
|
| 7 |
|
| 8 |
type LoginRequest struct {
|
| 9 |
+
Email string `json:"email" binding:"required"`
|
| 10 |
+
Password string `json:"password" binding:"required"`
|
| 11 |
}
|
| 12 |
|
| 13 |
type RegisterRequest struct {
|
| 14 |
+
Name string `json:"name"`
|
| 15 |
+
Email string `json:"email" binding:"required,email"`
|
| 16 |
+
Phone int `json:"phone"`
|
| 17 |
+
Password string `json:"password" binding:"required"`
|
| 18 |
}
|
| 19 |
|
| 20 |
type ChangePasswordRequest struct {
|
| 21 |
+
OldPassword string `json:"old_password" binding:"required" `
|
| 22 |
+
NewPassword string `json:"new_password" binding:"required" `
|
| 23 |
}
|
| 24 |
|
| 25 |
type CreateVerifyEmailRequest struct {
|
| 26 |
+
Token uint `json:"token" binding:"required"`
|
| 27 |
}
|
| 28 |
|
| 29 |
type OptionsRequest struct {
|
| 30 |
+
OptionName string `json:"option_name" binding:"required"`
|
| 31 |
+
OptionValue []string `json:"option_values" binding:"required"`
|
| 32 |
}
|
| 33 |
|
| 34 |
type ExternalAuthRequest struct {
|
| 35 |
+
OauthID string `json:"oauth_id" binding:"required"`
|
| 36 |
+
OauthProvider string `json:"oauth_provider" binding:"required"`
|
| 37 |
+
IsAgreeTerms bool `json:"is_agree_terms"`
|
| 38 |
+
IsSexualDisease bool `json:"is_sexual_disease"`
|
| 39 |
}
|
| 40 |
|
| 41 |
type ForgotPasswordRequest struct {
|
| 42 |
+
Email string `json:"email" binding:"required,email"`
|
| 43 |
}
|
| 44 |
type ValidateForgotPasswordRequest struct {
|
| 45 |
+
Token uint `json:"token" binding:"required"`
|
| 46 |
+
NewPassword string `json:"new_password"`
|
| 47 |
}
|
| 48 |
|
| 49 |
type QuestionQuizRequest struct {
|
| 50 |
+
QuestionNo int `json:"question_no" binding:"required"`
|
| 51 |
}
|
| 52 |
|
| 53 |
type AnswerQuizRequest struct {
|
| 54 |
+
QuestionNo int `json:"question_no" binding:"required"`
|
| 55 |
+
Answer int `json:"answer" binding:"required"`
|
| 56 |
}
|
| 57 |
|
| 58 |
type (
|
| 59 |
+
PersonalityAndPreferenceCVRequest struct {
|
| 60 |
+
AccountID int64 `json:"-"`
|
| 61 |
+
PositiveTraits *string `json:"positive_traits"` // sifat positif
|
| 62 |
+
NegativeTraits *string `json:"negative_traits"` // sifat negatif
|
| 63 |
+
Hobbies *string `json:"hobbies"` // hobi
|
| 64 |
+
LifeGoals *string `json:"life_goals"` // target hidup
|
| 65 |
+
DailyActivities *string `json:"daily_activities"` // kegiatan sehari-hari
|
| 66 |
+
LeisureActivities *string `json:"leisure_activities"` // kegiatan waktu luang
|
| 67 |
+
Likes *string `json:"likes"` // hal yang disukai
|
| 68 |
+
Dislikes *string `json:"dislikes"` // hal yang tidak disukai
|
| 69 |
+
StressHandling *string `json:"stress_handling"` // cara mengatasi stres
|
| 70 |
+
AngerTriggers *string `json:"anger_triggers"` // pemicu amarah
|
| 71 |
+
FavoriteFoodAndDrinks *string `json:"favorite_food_and_drinks"` // makanan dan minuman favorit
|
| 72 |
+
CanCook *bool `json:"can_cook"` // bisa memasak
|
| 73 |
+
TypesOfDishesCooked *string `json:"types_of_dishes_cooked"` // jenis masakan yang bisa dimasak
|
| 74 |
+
MonthlyExpenses *string `json:"monthly_expenses" validate:"monthly_expenses"` // pengeluaran per bulan
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
FamilyMemberRequest struct {
|
| 78 |
+
AccountID int64 `json:"-"`
|
| 79 |
+
Role *string `json:"role" validate:"family_role"` // Peran dalam keluarga
|
| 80 |
+
Status *string `json:"status" validate:"life_status"` // Status (Hidup, Wafat)
|
| 81 |
+
Religion *string `json:"religion" validate:"religion"` // Agama
|
| 82 |
+
Job *string `json:"job"` // Pekerjaan
|
| 83 |
+
LastEducation *string `json:"last_education" validate:"last_education"` // Pendidikan terakhir
|
| 84 |
+
Age *int `json:"age"` // Usia
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
PhysicalAndHealthRequest struct {
|
| 88 |
+
AccountID int64 `json:"-"`
|
| 89 |
+
HeightInCm *int `json:"height_cm"` // Tinggi badan dalam satuan sentimeter
|
| 90 |
+
WeightInKg *int `json:"weight_kg"` // Berat badan dalam satuan kilogram
|
| 91 |
+
BodyShape *string `json:"body_shape" validate:"body_shape"` // Bentuk tubuh
|
| 92 |
+
SkinColor *string `json:"skin_color" validate:"skin_color"` // Warna kulit
|
| 93 |
+
HairType *string `json:"hair_type" validate:"hair_type"` // Tipe rambut
|
| 94 |
+
MedicalHistory *string `json:"medical_history"` // Riwayat penyakit
|
| 95 |
+
PhysicalDisorder *string `json:"physical_disorder"` // Cacat fisik
|
| 96 |
+
PhysicalTraits *string `json:"physical_traits"` // Ciri khas fisik
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
AccountDetailsRequest struct {
|
| 100 |
+
AccountID int64 `json:"-"`
|
| 101 |
+
FullName *string `json:"full_name"`
|
| 102 |
+
Gender *string `json:"gender" validate:"gender"`
|
| 103 |
+
DateOfBirth *time.Time `json:"date_of_birth"`
|
| 104 |
+
PlaceOfBirth *string `json:"place_of_birth"`
|
| 105 |
+
Domicile *string `json:"domicile"`
|
| 106 |
+
MaritalStatus *string `json:"marital_status" validate:"marital_status"`
|
| 107 |
+
LastEducation *string `json:"last_education" validate:"last_education"`
|
| 108 |
+
LastJob *string `json:"last_job"`
|
| 109 |
+
}
|
| 110 |
+
|
| 111 |
+
WorshipAndReligiousUnderstandingRequest struct {
|
| 112 |
+
AccountID int64 `json:"-"`
|
| 113 |
+
ObligatoryPrayer *string `json:"obligatory_prayer"` // sholat_wajib_5_waktu
|
| 114 |
+
CongregationalPrayer *string `json:"congregational_prayer"` // sholat_berjamaah_di_masjid
|
| 115 |
+
TahajjudPrayer *string `json:"tahajjud_prayer"` // sholat_tahajud
|
| 116 |
+
DhuhaPrayer *string `json:"dhuha_prayer"` // sholat_dhuha
|
| 117 |
+
QuranMemorization *string `json:"quran_memorization"` // hafalan_alquran
|
| 118 |
+
QuranReadingAbility *string `json:"quran_reading_ability" validate:"quran_reading_ability"` // kemampuan_baca_alquran
|
| 119 |
+
DaudFasting *string `json:"daud_fasting"` // puasa_daud
|
| 120 |
+
AyyamulBidhFasting *string `json:"ayyamul_bidh_fasting"` // puasa_ayyamul_bidh
|
| 121 |
+
HajjOrUmrah pq.StringArray `json:"hajj_or_umrah"` // ibadah_haji_umroh
|
| 122 |
+
ListeningToMusic *string `json:"listening_to_music"` // mendengarkan_musik
|
| 123 |
+
OpinionOnIkhtilat *string `json:"opinion_on_ikhtilat"` // pendapat_ikhtilat
|
| 124 |
+
OpinionOnTouchingNonMahram *string `json:"opinion_on_touching_non_mahram"` // pendapat_menyentuh_non_mahram
|
| 125 |
+
OpinionOnVeil *string `json:"opinion_on_veil"` // pendapat_tentang_cadar
|
| 126 |
+
WeeklyReligiousStudies *string `json:"weekly_religious_studies"` // kajian_yang_diikuti_dalam_sepekan
|
| 127 |
+
FollowedUstadz *string `json:"followed_ustadz"` // ustadz_yang_diikuti
|
| 128 |
+
}
|
| 129 |
+
|
| 130 |
+
EducationRequest struct {
|
| 131 |
+
AccountID int64 `json:"account_id"`
|
| 132 |
+
LastEducation *string `json:"last_education" validate:"last_education"` // pendidikan terakhir
|
| 133 |
+
EducationInstitute *string `json:"education_institute"` // institusi pendidikan
|
| 134 |
+
EducationMajor *string `json:"education_major"` // jurusan pendidikan
|
| 135 |
+
YearStart *int `json:"year_start"` // tahun masuk
|
| 136 |
+
YearGraduate *int `json:"year_graduate"` // tahun lulus
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
+
JobRequest struct {
|
| 140 |
+
AccountID int64 `json:"account_id"`
|
| 141 |
+
InstitutionName *string `json:"institution_name"` // nama instansi
|
| 142 |
+
CurrentJob *string `json:"current_job"` // pekerjaan saat ini
|
| 143 |
+
YearStartedWorking *int `json:"year_started_working"` // tahun mulai bekerja
|
| 144 |
+
MonthlyIncome *string `json:"monthly_income" validate:"monthly_income"` // penghasilan per bulan
|
| 145 |
+
IncomeSources pq.StringArray `json:"income_sources"` // sumber penghasilan
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
AchievementRequest struct {
|
| 149 |
+
AccountID int64 `json:"account_id"`
|
| 150 |
+
AchievementOrAward *string `json:"achievement_or_award"` // prestasi atau penghargaan
|
| 151 |
+
}
|
| 152 |
)
|
response/api_response_v2.go
CHANGED
|
@@ -3,6 +3,7 @@ package response
|
|
| 3 |
import (
|
| 4 |
"api.qobiltu.id/models"
|
| 5 |
"api.qobiltu.id/utils"
|
|
|
|
| 6 |
"errors"
|
| 7 |
"net/http"
|
| 8 |
|
|
@@ -39,7 +40,7 @@ func HandleError(c *gin.Context, err error) {
|
|
| 39 |
case exception.AttemptNotFound:
|
| 40 |
responseError(c, http.StatusNotFound, exception)
|
| 41 |
case exception.ValidationError:
|
| 42 |
-
|
| 43 |
default:
|
| 44 |
responseError(c, http.StatusInternalServerError, exception)
|
| 45 |
}
|
|
@@ -77,3 +78,17 @@ func responseError(c *gin.Context, status int, exception models.Exception) {
|
|
| 77 |
c.AbortWithStatusJSON(status, res)
|
| 78 |
return
|
| 79 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
import (
|
| 4 |
"api.qobiltu.id/models"
|
| 5 |
"api.qobiltu.id/utils"
|
| 6 |
+
"api.qobiltu.id/validation"
|
| 7 |
"errors"
|
| 8 |
"net/http"
|
| 9 |
|
|
|
|
| 40 |
case exception.AttemptNotFound:
|
| 41 |
responseError(c, http.StatusNotFound, exception)
|
| 42 |
case exception.ValidationError:
|
| 43 |
+
responseValidationError(c, http.StatusUnprocessableEntity, exception.ValidationErrorFields) // Gunakan fungsi khusus untuk validasi
|
| 44 |
default:
|
| 45 |
responseError(c, http.StatusInternalServerError, exception)
|
| 46 |
}
|
|
|
|
| 78 |
c.AbortWithStatusJSON(status, res)
|
| 79 |
return
|
| 80 |
}
|
| 81 |
+
|
| 82 |
+
func responseValidationError(c *gin.Context, status int, validationErrors []validation.ErrorMessage) {
|
| 83 |
+
res := models.ErrorResponse{
|
| 84 |
+
Status: "error",
|
| 85 |
+
Message: "Validasi data gagal.",
|
| 86 |
+
Errors: models.Exception{
|
| 87 |
+
ValidationError: true,
|
| 88 |
+
ValidationErrorFields: validationErrors,
|
| 89 |
+
},
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
c.AbortWithStatusJSON(status, res)
|
| 93 |
+
return
|
| 94 |
+
}
|
response/validation.go
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package response
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"api.qobiltu.id/models"
|
| 5 |
+
"api.qobiltu.id/validation"
|
| 6 |
+
)
|
| 7 |
+
|
| 8 |
+
func HandleValidationError(validationErrors []validation.ErrorMessage) error {
|
| 9 |
+
return models.Exception{
|
| 10 |
+
ValidationError: true,
|
| 11 |
+
Message: "Validation failed",
|
| 12 |
+
ValidationErrorFields: validationErrors,
|
| 13 |
+
}
|
| 14 |
+
}
|
services/cv_service.go
CHANGED
|
@@ -1,444 +1,485 @@
|
|
| 1 |
package services
|
| 2 |
|
| 3 |
import (
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
|
|
|
| 10 |
)
|
| 11 |
|
| 12 |
type CVService interface {
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
}
|
| 49 |
|
| 50 |
type cvService struct {
|
| 51 |
-
|
| 52 |
}
|
| 53 |
|
| 54 |
func NewCVService(cvRepository repositories.CVRepository) CVService {
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
}
|
| 59 |
|
| 60 |
func (s *cvService) SaveAccountDetails(ctx context.Context, req *models.AccountDetailsRequest) (*models.AccountDetails, error) {
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
}
|
| 90 |
|
| 91 |
func (s *cvService) GetAccountDetails(ctx context.Context, id int64) (*models.AccountDetails, error) {
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
}
|
| 98 |
|
| 99 |
func (s *cvService) SavePersonalityAndPreference(ctx context.Context, req *models.PersonalityAndPreferenceCVRequest) (*models.PersonalityAndPreferenceCV, error) {
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 133 |
}
|
| 134 |
|
| 135 |
func (s *cvService) GetPersonalityAndPreference(ctx context.Context, id int64) (*models.PersonalityAndPreferenceCV, error) {
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
|
| 141 |
-
|
| 142 |
}
|
| 143 |
|
| 144 |
func (s *cvService) CreateFamilyMember(ctx context.Context, req *models.FamilyMemberRequest) (*models.FamilyMemberCV, error) {
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 163 |
}
|
| 164 |
|
| 165 |
func (s *cvService) ListFamilyMember(ctx context.Context, accountID int64) ([]models.FamilyMemberCV, error) {
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
}
|
| 172 |
|
| 173 |
func (s *cvService) GetFamilyMember(ctx context.Context, id int64) (*models.FamilyMemberCV, error) {
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
}
|
| 180 |
|
| 181 |
func (s *cvService) DeleteFamilyMember(ctx context.Context, id int64) error {
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
}
|
| 188 |
|
| 189 |
func (s *cvService) UpdateFamilyMember(ctx context.Context, id int64, req *models.FamilyMemberRequest) (*models.FamilyMemberCV, error) {
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 208 |
}
|
| 209 |
|
| 210 |
func (s *cvService) SavePhysicalAndHealth(ctx context.Context, req *models.PhysicalAndHealthRequest) (*models.PhysicalAndHealthCV, error) {
|
| 211 |
-
|
| 212 |
-
|
| 213 |
-
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
|
| 226 |
-
|
| 227 |
-
|
| 228 |
-
|
| 229 |
-
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 240 |
}
|
| 241 |
|
| 242 |
func (s *cvService) GetPhysicalAndHealth(ctx context.Context, id int64) (*models.PhysicalAndHealthCV, error) {
|
| 243 |
-
|
| 244 |
-
|
| 245 |
-
|
| 246 |
-
|
| 247 |
-
|
| 248 |
}
|
| 249 |
|
| 250 |
func (s *cvService) SaveWorshipAndReligiousUnderstanding(ctx context.Context, req *models.WorshipAndReligiousUnderstandingRequest) (*models.WorshipAndReligiousUnderstandingCV, error) {
|
| 251 |
-
|
| 252 |
-
|
| 253 |
-
|
| 254 |
-
|
| 255 |
-
|
| 256 |
-
|
| 257 |
-
|
| 258 |
-
|
| 259 |
-
|
| 260 |
-
|
| 261 |
-
|
| 262 |
-
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
|
| 269 |
-
|
| 270 |
-
|
| 271 |
-
|
| 272 |
-
|
| 273 |
-
|
| 274 |
-
|
| 275 |
-
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
| 279 |
-
|
| 280 |
-
|
| 281 |
-
|
| 282 |
-
|
| 283 |
-
|
| 284 |
-
|
| 285 |
-
|
| 286 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 287 |
}
|
| 288 |
|
| 289 |
func (s *cvService) GetWorshipAndReligiousUnderstanding(ctx context.Context, id int64) (*models.WorshipAndReligiousUnderstandingCV, error) {
|
| 290 |
-
|
| 291 |
-
|
| 292 |
-
|
| 293 |
-
|
| 294 |
-
|
| 295 |
}
|
| 296 |
|
| 297 |
func (s *cvService) CreateEducation(ctx context.Context, req *models.EducationRequest) (*models.EducationCV, error) {
|
| 298 |
-
|
| 299 |
-
|
| 300 |
-
|
| 301 |
-
|
| 302 |
-
|
| 303 |
-
|
| 304 |
-
|
| 305 |
-
|
| 306 |
-
|
| 307 |
-
|
| 308 |
-
|
| 309 |
-
|
| 310 |
-
|
| 311 |
-
|
| 312 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 313 |
}
|
| 314 |
|
| 315 |
func (s *cvService) UpdateEducation(ctx context.Context, id int64, req *models.EducationRequest) (*models.EducationCV, error) {
|
| 316 |
-
|
| 317 |
-
|
| 318 |
-
|
| 319 |
-
|
| 320 |
-
|
| 321 |
-
|
| 322 |
-
|
| 323 |
-
|
| 324 |
-
|
| 325 |
-
|
| 326 |
-
|
| 327 |
-
|
| 328 |
-
|
| 329 |
-
|
| 330 |
-
|
| 331 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 332 |
}
|
| 333 |
|
| 334 |
func (s *cvService) ListEducation(ctx context.Context, accountID int64) ([]models.EducationCV, error) {
|
| 335 |
-
|
| 336 |
}
|
| 337 |
|
| 338 |
func (s *cvService) GetEducation(ctx context.Context, id int64) (*models.EducationCV, error) {
|
| 339 |
-
|
| 340 |
-
|
| 341 |
-
|
| 342 |
-
|
| 343 |
-
|
| 344 |
}
|
| 345 |
|
| 346 |
func (s *cvService) DeleteEducation(ctx context.Context, id int64) error {
|
| 347 |
-
|
| 348 |
}
|
| 349 |
|
| 350 |
func (s *cvService) CreateJob(ctx context.Context, req *models.JobRequest) (*models.JobCV, error) {
|
| 351 |
-
|
| 352 |
-
|
| 353 |
-
|
| 354 |
-
|
| 355 |
-
|
| 356 |
-
|
| 357 |
-
|
| 358 |
-
|
| 359 |
-
|
| 360 |
-
|
| 361 |
-
|
| 362 |
-
|
| 363 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 364 |
}
|
| 365 |
|
| 366 |
func (s *cvService) UpdateJob(ctx context.Context, id int64, req *models.JobRequest) (*models.JobCV, error) {
|
| 367 |
-
|
| 368 |
-
|
| 369 |
-
|
| 370 |
-
|
| 371 |
-
|
| 372 |
-
|
| 373 |
-
|
| 374 |
-
|
| 375 |
-
|
| 376 |
-
|
| 377 |
-
|
| 378 |
-
|
| 379 |
-
|
| 380 |
-
|
| 381 |
-
|
| 382 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 383 |
}
|
| 384 |
|
| 385 |
func (s *cvService) ListJob(ctx context.Context, accountID int64) ([]models.JobCV, error) {
|
| 386 |
-
|
| 387 |
}
|
| 388 |
|
| 389 |
func (s *cvService) GetJob(ctx context.Context, id int64) (*models.JobCV, error) {
|
| 390 |
-
|
| 391 |
-
|
| 392 |
-
|
| 393 |
-
|
| 394 |
-
|
| 395 |
}
|
| 396 |
|
| 397 |
func (s *cvService) DeleteJob(ctx context.Context, id int64) error {
|
| 398 |
-
|
| 399 |
}
|
| 400 |
|
| 401 |
func (s *cvService) CreateAchievement(ctx context.Context, req *models.AchievementRequest) (*models.AchievementCV, error) {
|
| 402 |
-
|
| 403 |
-
|
| 404 |
-
|
| 405 |
-
|
| 406 |
-
|
| 407 |
-
|
| 408 |
-
|
| 409 |
-
|
| 410 |
-
|
| 411 |
-
|
| 412 |
}
|
| 413 |
|
| 414 |
func (s *cvService) UpdateAchievement(ctx context.Context, id int64, req *models.AchievementRequest) (*models.AchievementCV, error) {
|
| 415 |
-
|
| 416 |
-
|
| 417 |
-
|
| 418 |
-
|
| 419 |
|
| 420 |
-
|
| 421 |
|
| 422 |
-
|
| 423 |
-
|
| 424 |
-
|
| 425 |
-
|
| 426 |
|
| 427 |
-
|
| 428 |
}
|
| 429 |
|
| 430 |
func (s *cvService) ListAchievement(ctx context.Context, accountID int64) ([]models.AchievementCV, error) {
|
| 431 |
-
|
| 432 |
}
|
| 433 |
|
| 434 |
func (s *cvService) GetAchievement(ctx context.Context, id int64) (*models.AchievementCV, error) {
|
| 435 |
-
|
| 436 |
-
|
| 437 |
-
|
| 438 |
-
|
| 439 |
-
|
| 440 |
}
|
| 441 |
|
| 442 |
func (s *cvService) DeleteAchievement(ctx context.Context, id int64) error {
|
| 443 |
-
|
| 444 |
}
|
|
|
|
| 1 |
package services
|
| 2 |
|
| 3 |
import (
|
| 4 |
+
"api.qobiltu.id/models"
|
| 5 |
+
"api.qobiltu.id/repositories"
|
| 6 |
+
"api.qobiltu.id/response"
|
| 7 |
+
"api.qobiltu.id/validation"
|
| 8 |
+
"context"
|
| 9 |
+
"errors"
|
| 10 |
+
"gorm.io/gorm"
|
| 11 |
)
|
| 12 |
|
| 13 |
type CVService interface {
|
| 14 |
+
SaveAccountDetails(ctx context.Context, req *models.AccountDetailsRequest) (*models.AccountDetails, error)
|
| 15 |
+
GetAccountDetails(ctx context.Context, id int64) (*models.AccountDetails, error)
|
| 16 |
+
|
| 17 |
+
SavePersonalityAndPreference(ctx context.Context, req *models.PersonalityAndPreferenceCVRequest) (*models.PersonalityAndPreferenceCV, error)
|
| 18 |
+
GetPersonalityAndPreference(ctx context.Context, id int64) (*models.PersonalityAndPreferenceCV, error)
|
| 19 |
+
|
| 20 |
+
CreateFamilyMember(ctx context.Context, req *models.FamilyMemberRequest) (*models.FamilyMemberCV, error)
|
| 21 |
+
UpdateFamilyMember(ctx context.Context, id int64, req *models.FamilyMemberRequest) (*models.FamilyMemberCV, error)
|
| 22 |
+
ListFamilyMember(ctx context.Context, accountID int64) ([]models.FamilyMemberCV, error)
|
| 23 |
+
GetFamilyMember(ctx context.Context, id int64) (*models.FamilyMemberCV, error)
|
| 24 |
+
DeleteFamilyMember(ctx context.Context, id int64) error
|
| 25 |
+
|
| 26 |
+
SavePhysicalAndHealth(ctx context.Context, req *models.PhysicalAndHealthRequest) (*models.PhysicalAndHealthCV, error)
|
| 27 |
+
GetPhysicalAndHealth(ctx context.Context, id int64) (*models.PhysicalAndHealthCV, error)
|
| 28 |
+
|
| 29 |
+
SaveWorshipAndReligiousUnderstanding(ctx context.Context, req *models.WorshipAndReligiousUnderstandingRequest) (*models.WorshipAndReligiousUnderstandingCV, error)
|
| 30 |
+
GetWorshipAndReligiousUnderstanding(ctx context.Context, id int64) (*models.WorshipAndReligiousUnderstandingCV, error)
|
| 31 |
+
|
| 32 |
+
CreateEducation(ctx context.Context, req *models.EducationRequest) (*models.EducationCV, error)
|
| 33 |
+
UpdateEducation(ctx context.Context, id int64, req *models.EducationRequest) (*models.EducationCV, error)
|
| 34 |
+
ListEducation(ctx context.Context, accountID int64) ([]models.EducationCV, error)
|
| 35 |
+
GetEducation(ctx context.Context, id int64) (*models.EducationCV, error)
|
| 36 |
+
DeleteEducation(ctx context.Context, id int64) error
|
| 37 |
+
|
| 38 |
+
CreateJob(ctx context.Context, req *models.JobRequest) (*models.JobCV, error)
|
| 39 |
+
UpdateJob(ctx context.Context, id int64, req *models.JobRequest) (*models.JobCV, error)
|
| 40 |
+
ListJob(ctx context.Context, accountID int64) ([]models.JobCV, error)
|
| 41 |
+
GetJob(ctx context.Context, id int64) (*models.JobCV, error)
|
| 42 |
+
DeleteJob(ctx context.Context, id int64) error
|
| 43 |
+
|
| 44 |
+
CreateAchievement(ctx context.Context, req *models.AchievementRequest) (*models.AchievementCV, error)
|
| 45 |
+
UpdateAchievement(ctx context.Context, id int64, req *models.AchievementRequest) (*models.AchievementCV, error)
|
| 46 |
+
ListAchievement(ctx context.Context, accountID int64) ([]models.AchievementCV, error)
|
| 47 |
+
GetAchievement(ctx context.Context, id int64) (*models.AchievementCV, error)
|
| 48 |
+
DeleteAchievement(ctx context.Context, id int64) error
|
| 49 |
}
|
| 50 |
|
| 51 |
type cvService struct {
|
| 52 |
+
cvRepository repositories.CVRepository
|
| 53 |
}
|
| 54 |
|
| 55 |
func NewCVService(cvRepository repositories.CVRepository) CVService {
|
| 56 |
+
return &cvService{
|
| 57 |
+
cvRepository: cvRepository,
|
| 58 |
+
}
|
| 59 |
}
|
| 60 |
|
| 61 |
func (s *cvService) SaveAccountDetails(ctx context.Context, req *models.AccountDetailsRequest) (*models.AccountDetails, error) {
|
| 62 |
+
if err := validation.Validate(req); err != nil {
|
| 63 |
+
return nil, response.HandleValidationError(err)
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
// Ambil data lama jika ada
|
| 67 |
+
accountDetails, err := s.cvRepository.GetAccountDetailsByAccountID(ctx, req.AccountID)
|
| 68 |
+
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
| 69 |
+
return nil, response.HandleGormError(err, "Internal Server Error")
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
// Apply perubahan
|
| 73 |
+
if accountDetails == nil {
|
| 74 |
+
accountDetails = &models.AccountDetails{}
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
accountDetails.AccountID = uint(req.AccountID)
|
| 78 |
+
accountDetails.FullName = req.FullName
|
| 79 |
+
accountDetails.Gender = req.Gender
|
| 80 |
+
accountDetails.DateOfBirth = req.DateOfBirth
|
| 81 |
+
accountDetails.PlaceOfBirth = req.PlaceOfBirth
|
| 82 |
+
accountDetails.Domicile = req.Domicile
|
| 83 |
+
accountDetails.MaritalStatus = req.MaritalStatus
|
| 84 |
+
accountDetails.LastEducation = req.LastEducation
|
| 85 |
+
accountDetails.LastJob = req.LastJob
|
| 86 |
+
|
| 87 |
+
// Simpan data
|
| 88 |
+
res, err := s.cvRepository.SaveAccountDetails(ctx, accountDetails)
|
| 89 |
+
if err != nil {
|
| 90 |
+
return nil, response.HandleGormError(err, "Internal Server Error")
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
return res, nil
|
| 94 |
}
|
| 95 |
|
| 96 |
func (s *cvService) GetAccountDetails(ctx context.Context, id int64) (*models.AccountDetails, error) {
|
| 97 |
+
res, err := s.cvRepository.GetAccountDetailsByAccountID(ctx, id)
|
| 98 |
+
if err != nil {
|
| 99 |
+
return nil, response.HandleGormError(err, "Data diri tidak ditemukan")
|
| 100 |
+
}
|
| 101 |
+
return res, nil
|
| 102 |
}
|
| 103 |
|
| 104 |
func (s *cvService) SavePersonalityAndPreference(ctx context.Context, req *models.PersonalityAndPreferenceCVRequest) (*models.PersonalityAndPreferenceCV, error) {
|
| 105 |
+
if err := validation.Validate(req); err != nil {
|
| 106 |
+
return nil, response.HandleValidationError(err)
|
| 107 |
+
}
|
| 108 |
+
|
| 109 |
+
// Ambil data lama jika ada
|
| 110 |
+
personalityAndPreference, err := s.cvRepository.GetPersonalityAndPreferenceByAccountID(ctx, req.AccountID)
|
| 111 |
+
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
| 112 |
+
return nil, response.HandleGormError(err, "Internal Server Error")
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
// Apply perubahan
|
| 116 |
+
if personalityAndPreference == nil {
|
| 117 |
+
personalityAndPreference = &models.PersonalityAndPreferenceCV{}
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
personalityAndPreference.AccountID = req.AccountID
|
| 121 |
+
personalityAndPreference.PositiveTraits = req.PositiveTraits
|
| 122 |
+
personalityAndPreference.NegativeTraits = req.NegativeTraits
|
| 123 |
+
personalityAndPreference.Hobbies = req.Hobbies
|
| 124 |
+
personalityAndPreference.LifeGoals = req.LifeGoals
|
| 125 |
+
personalityAndPreference.DailyActivities = req.DailyActivities
|
| 126 |
+
personalityAndPreference.LeisureActivities = req.LeisureActivities
|
| 127 |
+
personalityAndPreference.Likes = req.Likes
|
| 128 |
+
personalityAndPreference.Dislikes = req.Dislikes
|
| 129 |
+
personalityAndPreference.StressHandling = req.StressHandling
|
| 130 |
+
personalityAndPreference.AngerTriggers = req.AngerTriggers
|
| 131 |
+
personalityAndPreference.FavoriteFoodAndDrinks = req.FavoriteFoodAndDrinks
|
| 132 |
+
personalityAndPreference.CanCook = req.CanCook
|
| 133 |
+
personalityAndPreference.TypesOfDishesCooked = req.TypesOfDishesCooked
|
| 134 |
+
personalityAndPreference.MonthlyExpenses = req.MonthlyExpenses
|
| 135 |
+
|
| 136 |
+
res, err := s.cvRepository.SavePersonalityAndPreference(ctx, personalityAndPreference)
|
| 137 |
+
if err != nil {
|
| 138 |
+
return nil, response.HandleGormError(err, "Internal Server Error")
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
return res, nil
|
| 142 |
}
|
| 143 |
|
| 144 |
func (s *cvService) GetPersonalityAndPreference(ctx context.Context, id int64) (*models.PersonalityAndPreferenceCV, error) {
|
| 145 |
+
res, err := s.cvRepository.GetPersonalityAndPreferenceByAccountID(ctx, id)
|
| 146 |
+
if err != nil {
|
| 147 |
+
return nil, response.HandleGormError(err, "Internal Server Error")
|
| 148 |
+
}
|
| 149 |
|
| 150 |
+
return res, nil
|
| 151 |
}
|
| 152 |
|
| 153 |
func (s *cvService) CreateFamilyMember(ctx context.Context, req *models.FamilyMemberRequest) (*models.FamilyMemberCV, error) {
|
| 154 |
+
if err := validation.Validate(req); err != nil {
|
| 155 |
+
return nil, response.HandleValidationError(err)
|
| 156 |
+
}
|
| 157 |
+
|
| 158 |
+
// Mapping request ke model
|
| 159 |
+
familyMember := &models.FamilyMemberCV{
|
| 160 |
+
AccountID: req.AccountID,
|
| 161 |
+
Role: req.Role,
|
| 162 |
+
Status: req.Status,
|
| 163 |
+
Religion: req.Religion,
|
| 164 |
+
Job: req.Job,
|
| 165 |
+
LastEducation: req.LastEducation,
|
| 166 |
+
Age: req.Age,
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
// Simpan ke repository
|
| 170 |
+
res, err := s.cvRepository.SaveFamilyMember(ctx, familyMember)
|
| 171 |
+
if err != nil {
|
| 172 |
+
return nil, response.HandleGormError(err, "Gagal menyimpan anggota keluarga")
|
| 173 |
+
}
|
| 174 |
+
|
| 175 |
+
return res, nil
|
| 176 |
}
|
| 177 |
|
| 178 |
func (s *cvService) ListFamilyMember(ctx context.Context, accountID int64) ([]models.FamilyMemberCV, error) {
|
| 179 |
+
list, err := s.cvRepository.ListFamilyMember(ctx, accountID)
|
| 180 |
+
if err != nil {
|
| 181 |
+
return nil, response.HandleGormError(err, "Gagal mengambil daftar anggota keluarga")
|
| 182 |
+
}
|
| 183 |
+
return list, nil
|
| 184 |
}
|
| 185 |
|
| 186 |
func (s *cvService) GetFamilyMember(ctx context.Context, id int64) (*models.FamilyMemberCV, error) {
|
| 187 |
+
res, err := s.cvRepository.GetFamilyMember(ctx, id)
|
| 188 |
+
if err != nil {
|
| 189 |
+
return nil, response.HandleGormError(err, "Data anggota keluarga tidak ditemukan")
|
| 190 |
+
}
|
| 191 |
+
return res, nil
|
| 192 |
}
|
| 193 |
|
| 194 |
func (s *cvService) DeleteFamilyMember(ctx context.Context, id int64) error {
|
| 195 |
+
err := s.cvRepository.DeleteFamilyMember(ctx, id)
|
| 196 |
+
if err != nil {
|
| 197 |
+
return response.HandleGormError(err, "Gagal menghapus anggota keluarga")
|
| 198 |
+
}
|
| 199 |
+
return nil
|
| 200 |
}
|
| 201 |
|
| 202 |
func (s *cvService) UpdateFamilyMember(ctx context.Context, id int64, req *models.FamilyMemberRequest) (*models.FamilyMemberCV, error) {
|
| 203 |
+
if err := validation.Validate(req); err != nil {
|
| 204 |
+
return nil, response.HandleValidationError(err)
|
| 205 |
+
}
|
| 206 |
+
|
| 207 |
+
existing, err := s.cvRepository.GetFamilyMember(ctx, id)
|
| 208 |
+
if err != nil {
|
| 209 |
+
return nil, response.HandleGormError(err, "Data anggota keluarga tidak ditemukan")
|
| 210 |
+
}
|
| 211 |
+
|
| 212 |
+
existing.Role = req.Role
|
| 213 |
+
existing.Status = req.Status
|
| 214 |
+
existing.Religion = req.Religion
|
| 215 |
+
existing.Job = req.Job
|
| 216 |
+
existing.LastEducation = req.LastEducation
|
| 217 |
+
existing.Age = req.Age
|
| 218 |
+
|
| 219 |
+
updated, err := s.cvRepository.SaveFamilyMember(ctx, existing)
|
| 220 |
+
if err != nil {
|
| 221 |
+
return nil, response.HandleGormError(err, "Gagal memperbarui anggota keluarga")
|
| 222 |
+
}
|
| 223 |
+
|
| 224 |
+
return updated, nil
|
| 225 |
}
|
| 226 |
|
| 227 |
func (s *cvService) SavePhysicalAndHealth(ctx context.Context, req *models.PhysicalAndHealthRequest) (*models.PhysicalAndHealthCV, error) {
|
| 228 |
+
if err := validation.Validate(req); err != nil {
|
| 229 |
+
return nil, response.HandleValidationError(err)
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
// Cek apakah data sudah ada berdasarkan account_id
|
| 233 |
+
existing, err := s.cvRepository.GetPhysicalAndHealthByAccountID(ctx, req.AccountID)
|
| 234 |
+
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
| 235 |
+
return nil, response.HandleGormError(err, "Terjadi kesalahan saat mengambil data fisik dan kesehatan")
|
| 236 |
+
}
|
| 237 |
+
|
| 238 |
+
// Jika belum ada, buat objek baru
|
| 239 |
+
if existing == nil {
|
| 240 |
+
existing = &models.PhysicalAndHealthCV{}
|
| 241 |
+
}
|
| 242 |
+
|
| 243 |
+
// Mapping field dari request
|
| 244 |
+
existing.AccountID = req.AccountID
|
| 245 |
+
existing.HeightInCm = req.HeightInCm
|
| 246 |
+
existing.WeightInKg = req.WeightInKg
|
| 247 |
+
existing.BodyShape = req.BodyShape
|
| 248 |
+
existing.SkinColor = req.SkinColor
|
| 249 |
+
existing.HairType = req.HairType
|
| 250 |
+
existing.MedicalHistory = req.MedicalHistory
|
| 251 |
+
existing.PhysicalDisorder = req.PhysicalDisorder
|
| 252 |
+
existing.PhysicalTraits = req.PhysicalTraits
|
| 253 |
+
|
| 254 |
+
// Simpan data
|
| 255 |
+
res, err := s.cvRepository.SavePhysicalAndHealth(ctx, existing)
|
| 256 |
+
if err != nil {
|
| 257 |
+
return nil, response.HandleGormError(err, "Gagal menyimpan data fisik dan kesehatan")
|
| 258 |
+
}
|
| 259 |
+
|
| 260 |
+
return res, nil
|
| 261 |
}
|
| 262 |
|
| 263 |
func (s *cvService) GetPhysicalAndHealth(ctx context.Context, id int64) (*models.PhysicalAndHealthCV, error) {
|
| 264 |
+
res, err := s.cvRepository.GetPhysicalAndHealthByAccountID(ctx, id)
|
| 265 |
+
if err != nil {
|
| 266 |
+
return nil, response.HandleGormError(err, "Data fisik dan kesehatan tidak ditemukan")
|
| 267 |
+
}
|
| 268 |
+
return res, nil
|
| 269 |
}
|
| 270 |
|
| 271 |
func (s *cvService) SaveWorshipAndReligiousUnderstanding(ctx context.Context, req *models.WorshipAndReligiousUnderstandingRequest) (*models.WorshipAndReligiousUnderstandingCV, error) {
|
| 272 |
+
if err := validation.Validate(req); err != nil {
|
| 273 |
+
return nil, response.HandleValidationError(err)
|
| 274 |
+
}
|
| 275 |
+
|
| 276 |
+
// Cek apakah data sudah ada berdasarkan account_id
|
| 277 |
+
worshipAndReligiousUnderstanding, err := s.cvRepository.GetWorshipAndReligiousUnderstandingByAccountID(ctx, req.AccountID)
|
| 278 |
+
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
| 279 |
+
return nil, response.HandleGormError(err, "Terjadi kesalahan saat mengambil data agama dan pemahaman agama")
|
| 280 |
+
}
|
| 281 |
+
|
| 282 |
+
// Jika belum ada, buat objek baru
|
| 283 |
+
if worshipAndReligiousUnderstanding == nil {
|
| 284 |
+
worshipAndReligiousUnderstanding = &models.WorshipAndReligiousUnderstandingCV{}
|
| 285 |
+
}
|
| 286 |
+
|
| 287 |
+
// Mapping field dari request
|
| 288 |
+
worshipAndReligiousUnderstanding.AccountID = req.AccountID
|
| 289 |
+
worshipAndReligiousUnderstanding.ObligatoryPrayer = req.ObligatoryPrayer
|
| 290 |
+
worshipAndReligiousUnderstanding.CongregationalPrayer = req.CongregationalPrayer
|
| 291 |
+
worshipAndReligiousUnderstanding.TahajjudPrayer = req.TahajjudPrayer
|
| 292 |
+
worshipAndReligiousUnderstanding.DhuhaPrayer = req.DhuhaPrayer
|
| 293 |
+
worshipAndReligiousUnderstanding.QuranMemorization = req.QuranMemorization
|
| 294 |
+
worshipAndReligiousUnderstanding.QuranReadingAbility = req.QuranReadingAbility
|
| 295 |
+
worshipAndReligiousUnderstanding.DaudFasting = req.DaudFasting
|
| 296 |
+
worshipAndReligiousUnderstanding.AyyamulBidhFasting = req.AyyamulBidhFasting
|
| 297 |
+
worshipAndReligiousUnderstanding.HajjOrUmrah = req.HajjOrUmrah
|
| 298 |
+
worshipAndReligiousUnderstanding.ListeningToMusic = req.ListeningToMusic
|
| 299 |
+
worshipAndReligiousUnderstanding.OpinionOnIkhtilat = req.OpinionOnIkhtilat
|
| 300 |
+
worshipAndReligiousUnderstanding.OpinionOnTouchingNonMahram = req.OpinionOnTouchingNonMahram
|
| 301 |
+
worshipAndReligiousUnderstanding.OpinionOnVeil = req.OpinionOnVeil
|
| 302 |
+
worshipAndReligiousUnderstanding.WeeklyReligiousStudies = req.WeeklyReligiousStudies
|
| 303 |
+
worshipAndReligiousUnderstanding.FollowedUstadz = req.FollowedUstadz
|
| 304 |
+
|
| 305 |
+
// Simpan data
|
| 306 |
+
res, err := s.cvRepository.SaveWorshipAndReligiousUnderstanding(ctx, worshipAndReligiousUnderstanding)
|
| 307 |
+
if err != nil {
|
| 308 |
+
return nil, response.HandleGormError(err, "Internal Server Error")
|
| 309 |
+
}
|
| 310 |
+
|
| 311 |
+
return res, nil
|
| 312 |
}
|
| 313 |
|
| 314 |
func (s *cvService) GetWorshipAndReligiousUnderstanding(ctx context.Context, id int64) (*models.WorshipAndReligiousUnderstandingCV, error) {
|
| 315 |
+
res, err := s.cvRepository.GetWorshipAndReligiousUnderstandingByAccountID(ctx, id)
|
| 316 |
+
if err != nil {
|
| 317 |
+
return nil, response.HandleGormError(err, "Data agama dan pemahaman agama tidak ditemukan")
|
| 318 |
+
}
|
| 319 |
+
return res, nil
|
| 320 |
}
|
| 321 |
|
| 322 |
func (s *cvService) CreateEducation(ctx context.Context, req *models.EducationRequest) (*models.EducationCV, error) {
|
| 323 |
+
if err := validation.Validate(req); err != nil {
|
| 324 |
+
return nil, response.HandleValidationError(err)
|
| 325 |
+
}
|
| 326 |
+
|
| 327 |
+
edu := &models.EducationCV{
|
| 328 |
+
AccountID: req.AccountID,
|
| 329 |
+
LastEducation: req.LastEducation,
|
| 330 |
+
EducationInstitute: req.EducationInstitute,
|
| 331 |
+
EducationMajor: req.EducationMajor,
|
| 332 |
+
YearStart: req.YearStart,
|
| 333 |
+
YearGraduate: req.YearGraduate,
|
| 334 |
+
}
|
| 335 |
+
|
| 336 |
+
res, err := s.cvRepository.SaveEducation(ctx, edu)
|
| 337 |
+
if err != nil {
|
| 338 |
+
return nil, response.HandleGormError(err, "Gagal menambahkan data pendidikan")
|
| 339 |
+
}
|
| 340 |
+
|
| 341 |
+
return res, nil
|
| 342 |
}
|
| 343 |
|
| 344 |
func (s *cvService) UpdateEducation(ctx context.Context, id int64, req *models.EducationRequest) (*models.EducationCV, error) {
|
| 345 |
+
if err := validation.Validate(req); err != nil {
|
| 346 |
+
return nil, response.HandleValidationError(err)
|
| 347 |
+
}
|
| 348 |
+
|
| 349 |
+
edu, err := s.cvRepository.GetEducation(ctx, id)
|
| 350 |
+
if err != nil {
|
| 351 |
+
return nil, response.HandleGormError(err, "Data pendidikan tidak ditemukan")
|
| 352 |
+
}
|
| 353 |
+
|
| 354 |
+
edu.LastEducation = req.LastEducation
|
| 355 |
+
edu.EducationInstitute = req.EducationInstitute
|
| 356 |
+
edu.EducationMajor = req.EducationMajor
|
| 357 |
+
edu.YearStart = req.YearStart
|
| 358 |
+
edu.YearGraduate = req.YearGraduate
|
| 359 |
+
|
| 360 |
+
res, err := s.cvRepository.SaveEducation(ctx, edu)
|
| 361 |
+
if err != nil {
|
| 362 |
+
return nil, response.HandleGormError(err, "Gagal memperbarui data pendidikan")
|
| 363 |
+
}
|
| 364 |
+
return res, nil
|
| 365 |
}
|
| 366 |
|
| 367 |
func (s *cvService) ListEducation(ctx context.Context, accountID int64) ([]models.EducationCV, error) {
|
| 368 |
+
return s.cvRepository.ListEducation(ctx, accountID)
|
| 369 |
}
|
| 370 |
|
| 371 |
func (s *cvService) GetEducation(ctx context.Context, id int64) (*models.EducationCV, error) {
|
| 372 |
+
edu, err := s.cvRepository.GetEducation(ctx, id)
|
| 373 |
+
if err != nil {
|
| 374 |
+
return nil, response.HandleGormError(err, "Data pendidikan tidak ditemukan")
|
| 375 |
+
}
|
| 376 |
+
return edu, nil
|
| 377 |
}
|
| 378 |
|
| 379 |
func (s *cvService) DeleteEducation(ctx context.Context, id int64) error {
|
| 380 |
+
return s.cvRepository.DeleteEducation(ctx, id)
|
| 381 |
}
|
| 382 |
|
| 383 |
func (s *cvService) CreateJob(ctx context.Context, req *models.JobRequest) (*models.JobCV, error) {
|
| 384 |
+
if err := validation.Validate(req); err != nil {
|
| 385 |
+
return nil, response.HandleValidationError(err)
|
| 386 |
+
}
|
| 387 |
+
|
| 388 |
+
job := &models.JobCV{
|
| 389 |
+
AccountID: req.AccountID,
|
| 390 |
+
InstitutionName: req.InstitutionName,
|
| 391 |
+
CurrentJob: req.CurrentJob,
|
| 392 |
+
YearStartedWorking: req.YearStartedWorking,
|
| 393 |
+
MonthlyIncome: req.MonthlyIncome,
|
| 394 |
+
IncomeSources: req.IncomeSources,
|
| 395 |
+
}
|
| 396 |
+
res, err := s.cvRepository.SaveJob(ctx, job)
|
| 397 |
+
if err != nil {
|
| 398 |
+
return nil, response.HandleGormError(err, "Gagal menambahkan data pekerjaan")
|
| 399 |
+
}
|
| 400 |
+
return res, nil
|
| 401 |
}
|
| 402 |
|
| 403 |
func (s *cvService) UpdateJob(ctx context.Context, id int64, req *models.JobRequest) (*models.JobCV, error) {
|
| 404 |
+
if err := validation.Validate(req); err != nil {
|
| 405 |
+
return nil, response.HandleValidationError(err)
|
| 406 |
+
}
|
| 407 |
+
|
| 408 |
+
job, err := s.cvRepository.GetJob(ctx, id)
|
| 409 |
+
if err != nil {
|
| 410 |
+
return nil, response.HandleGormError(err, "Data pekerjaan tidak ditemukan")
|
| 411 |
+
}
|
| 412 |
+
|
| 413 |
+
job.InstitutionName = req.InstitutionName
|
| 414 |
+
job.CurrentJob = req.CurrentJob
|
| 415 |
+
job.YearStartedWorking = req.YearStartedWorking
|
| 416 |
+
job.MonthlyIncome = req.MonthlyIncome
|
| 417 |
+
job.IncomeSources = req.IncomeSources
|
| 418 |
+
|
| 419 |
+
res, err := s.cvRepository.SaveJob(ctx, job)
|
| 420 |
+
if err != nil {
|
| 421 |
+
return nil, response.HandleGormError(err, "Gagal memperbarui data pekerjaan")
|
| 422 |
+
}
|
| 423 |
+
return res, nil
|
| 424 |
}
|
| 425 |
|
| 426 |
func (s *cvService) ListJob(ctx context.Context, accountID int64) ([]models.JobCV, error) {
|
| 427 |
+
return s.cvRepository.ListJob(ctx, accountID)
|
| 428 |
}
|
| 429 |
|
| 430 |
func (s *cvService) GetJob(ctx context.Context, id int64) (*models.JobCV, error) {
|
| 431 |
+
job, err := s.cvRepository.GetJob(ctx, id)
|
| 432 |
+
if err != nil {
|
| 433 |
+
return nil, response.HandleGormError(err, "Data pekerjaan tidak ditemukan")
|
| 434 |
+
}
|
| 435 |
+
return job, nil
|
| 436 |
}
|
| 437 |
|
| 438 |
func (s *cvService) DeleteJob(ctx context.Context, id int64) error {
|
| 439 |
+
return s.cvRepository.DeleteJob(ctx, id)
|
| 440 |
}
|
| 441 |
|
| 442 |
func (s *cvService) CreateAchievement(ctx context.Context, req *models.AchievementRequest) (*models.AchievementCV, error) {
|
| 443 |
+
ach := &models.AchievementCV{
|
| 444 |
+
AccountID: req.AccountID,
|
| 445 |
+
AchievementOrAward: req.AchievementOrAward,
|
| 446 |
+
}
|
| 447 |
+
res, err := s.cvRepository.SaveAchievement(ctx, ach)
|
| 448 |
+
if err != nil {
|
| 449 |
+
return nil, response.HandleGormError(err, "Gagal menambahkan data prestasi")
|
| 450 |
+
}
|
| 451 |
+
|
| 452 |
+
return res, nil
|
| 453 |
}
|
| 454 |
|
| 455 |
func (s *cvService) UpdateAchievement(ctx context.Context, id int64, req *models.AchievementRequest) (*models.AchievementCV, error) {
|
| 456 |
+
ach, err := s.cvRepository.GetAchievement(ctx, id)
|
| 457 |
+
if err != nil {
|
| 458 |
+
return nil, response.HandleGormError(err, "Data prestasi tidak ditemukan")
|
| 459 |
+
}
|
| 460 |
|
| 461 |
+
ach.AchievementOrAward = req.AchievementOrAward
|
| 462 |
|
| 463 |
+
res, err := s.cvRepository.SaveAchievement(ctx, ach)
|
| 464 |
+
if err != nil {
|
| 465 |
+
return nil, response.HandleGormError(err, "Gagal memperbarui data prestasi")
|
| 466 |
+
}
|
| 467 |
|
| 468 |
+
return res, nil
|
| 469 |
}
|
| 470 |
|
| 471 |
func (s *cvService) ListAchievement(ctx context.Context, accountID int64) ([]models.AchievementCV, error) {
|
| 472 |
+
return s.cvRepository.ListAchievement(ctx, accountID)
|
| 473 |
}
|
| 474 |
|
| 475 |
func (s *cvService) GetAchievement(ctx context.Context, id int64) (*models.AchievementCV, error) {
|
| 476 |
+
ach, err := s.cvRepository.GetAchievement(ctx, id)
|
| 477 |
+
if err != nil {
|
| 478 |
+
return nil, response.HandleGormError(err, "Data prestasi tidak ditemukan")
|
| 479 |
+
}
|
| 480 |
+
return ach, nil
|
| 481 |
}
|
| 482 |
|
| 483 |
func (s *cvService) DeleteAchievement(ctx context.Context, id int64) error {
|
| 484 |
+
return s.cvRepository.DeleteAchievement(ctx, id)
|
| 485 |
}
|
space/go.sum
CHANGED
|
@@ -97,6 +97,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
|
| 97 |
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
| 98 |
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
| 99 |
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
|
|
|
|
|
|
| 100 |
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
| 101 |
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
| 102 |
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
|
|
|
| 97 |
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
| 98 |
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
| 99 |
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
| 100 |
+
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
| 101 |
+
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
| 102 |
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
| 103 |
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
| 104 |
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
space/models/database_orm_model.go
CHANGED
|
@@ -3,6 +3,7 @@ package models
|
|
| 3 |
import (
|
| 4 |
"time"
|
| 5 |
|
|
|
|
| 6 |
uuid "github.com/satori/go.uuid"
|
| 7 |
)
|
| 8 |
|
|
@@ -241,33 +242,33 @@ type (
|
|
| 241 |
}
|
| 242 |
|
| 243 |
WorshipAndReligiousUnderstandingCV struct {
|
| 244 |
-
ID int64
|
| 245 |
-
AccountID int64
|
| 246 |
-
Account *Account
|
| 247 |
-
ObligatoryPrayer *string
|
| 248 |
-
CongregationalPrayer *string
|
| 249 |
-
TahajjudPrayer *string
|
| 250 |
-
DhuhaPrayer *string
|
| 251 |
-
QuranMemorization *string
|
| 252 |
-
QuranReadingAbility *string
|
| 253 |
-
DaudFasting *string
|
| 254 |
-
AyyamulBidhFasting *string
|
| 255 |
-
HajjOrUmrah
|
| 256 |
-
ListeningToMusic *string
|
| 257 |
-
OpinionOnIkhtilat *string
|
| 258 |
-
OpinionOnTouchingNonMahram *string
|
| 259 |
-
OpinionOnVeil *string
|
| 260 |
-
WeeklyReligiousStudies *string
|
| 261 |
-
FollowedUstadz *string
|
| 262 |
-
CreatedAt time.Time
|
| 263 |
-
UpdatedAt time.Time
|
| 264 |
}
|
| 265 |
|
| 266 |
EducationCV struct {
|
| 267 |
ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` // id
|
| 268 |
AccountID int64 `gorm:"column:account_id;not null" json:"account_id"` // id akun
|
| 269 |
Account *Account `gorm:"foreignKey:AccountID;constraint:OnDelete:CASCADE" json:"account,omitempty"` // relasi ke akun
|
| 270 |
-
LastEducation *string `gorm:"column:last_education" json:"last_education"`
|
| 271 |
EducationInstitute *string `gorm:"column:education_institute" json:"education_institute"` // institusi pendidikan
|
| 272 |
EducationMajor *string `gorm:"column:education_major" json:"education_major"` // jurusan pendidikan
|
| 273 |
YearStart *int `gorm:"column:year_start" json:"year_start"` // tahun masuk
|
|
@@ -277,16 +278,16 @@ type (
|
|
| 277 |
}
|
| 278 |
|
| 279 |
JobCV struct {
|
| 280 |
-
ID int64
|
| 281 |
-
AccountID int64
|
| 282 |
-
Account *Account
|
| 283 |
-
InstitutionName *string
|
| 284 |
-
CurrentJob *string
|
| 285 |
-
YearStartedWorking *int
|
| 286 |
-
MonthlyIncome *string
|
| 287 |
-
IncomeSources
|
| 288 |
-
CreatedAt time.Time
|
| 289 |
-
UpdatedAt time.Time
|
| 290 |
}
|
| 291 |
|
| 292 |
AchievementCV struct {
|
|
|
|
| 3 |
import (
|
| 4 |
"time"
|
| 5 |
|
| 6 |
+
"github.com/lib/pq"
|
| 7 |
uuid "github.com/satori/go.uuid"
|
| 8 |
)
|
| 9 |
|
|
|
|
| 242 |
}
|
| 243 |
|
| 244 |
WorshipAndReligiousUnderstandingCV struct {
|
| 245 |
+
ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
|
| 246 |
+
AccountID int64 `gorm:"column:account_id;not null;unique" json:"account_id"`
|
| 247 |
+
Account *Account `gorm:"foreignKey:AccountID;constraint:OnDelete:CASCADE" json:"account,omitempty"`
|
| 248 |
+
ObligatoryPrayer *string `gorm:"column:obligatory_prayer" json:"obligatory_prayer"` // sholat_wajib_5_waktu
|
| 249 |
+
CongregationalPrayer *string `gorm:"column:congregational_prayer" json:"congregational_prayer"` // sholat_berjamaah_di_masjid
|
| 250 |
+
TahajjudPrayer *string `gorm:"column:tahajjud_prayer" json:"tahajjud_prayer"` // sholat_tahajud
|
| 251 |
+
DhuhaPrayer *string `gorm:"column:dhuha_prayer" json:"dhuha_prayer"` // sholat_dhuha
|
| 252 |
+
QuranMemorization *string `gorm:"column:quran_memorization" json:"quran_memorization"` // hafalan_alquran
|
| 253 |
+
QuranReadingAbility *string `gorm:"column:quran_reading_ability" json:"quran_reading_ability"` // kemampuan_baca_alquran
|
| 254 |
+
DaudFasting *string `gorm:"column:daud_fasting" json:"daud_fasting"` // puasa_daud
|
| 255 |
+
AyyamulBidhFasting *string `gorm:"column:ayyamul_bidh_fasting" json:"ayyamul_bidh_fasting"` // puasa_ayyamul_bidh
|
| 256 |
+
HajjOrUmrah pq.StringArray `gorm:"column:hajj_or_umrah;type:varchar(255)[]" json:"hajj_or_umrah"` // ibadah_haji_umroh
|
| 257 |
+
ListeningToMusic *string `gorm:"column:listening_to_music" json:"listening_to_music"` // mendengarkan_musik
|
| 258 |
+
OpinionOnIkhtilat *string `gorm:"column:opinion_on_ikhtilat" json:"opinion_on_ikhtilat"` // pendapat_ikhtilat
|
| 259 |
+
OpinionOnTouchingNonMahram *string `gorm:"column:opinion_on_touching_non_mahram" json:"opinion_on_touching_non_mahram"` // pendapat_menyentuh_non_mahram
|
| 260 |
+
OpinionOnVeil *string `gorm:"column:opinion_on_veil" json:"opinion_on_veil"` // pendapat_tentang_cadar
|
| 261 |
+
WeeklyReligiousStudies *string `gorm:"column:weekly_religious_studies" json:"weekly_religious_studies"` // kajian_yang_diikuti_dalam_sepekan
|
| 262 |
+
FollowedUstadz *string `gorm:"column:followed_ustadz" json:"followed_ustadz"` // ustadz_yang_diikuti
|
| 263 |
+
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"created_at"`
|
| 264 |
+
UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime" json:"updated_at"`
|
| 265 |
}
|
| 266 |
|
| 267 |
EducationCV struct {
|
| 268 |
ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` // id
|
| 269 |
AccountID int64 `gorm:"column:account_id;not null" json:"account_id"` // id akun
|
| 270 |
Account *Account `gorm:"foreignKey:AccountID;constraint:OnDelete:CASCADE" json:"account,omitempty"` // relasi ke akun
|
| 271 |
+
LastEducation *string `gorm:"column:last_education" json:"last_education" validate:""` // pendidikan terakhir
|
| 272 |
EducationInstitute *string `gorm:"column:education_institute" json:"education_institute"` // institusi pendidikan
|
| 273 |
EducationMajor *string `gorm:"column:education_major" json:"education_major"` // jurusan pendidikan
|
| 274 |
YearStart *int `gorm:"column:year_start" json:"year_start"` // tahun masuk
|
|
|
|
| 278 |
}
|
| 279 |
|
| 280 |
JobCV struct {
|
| 281 |
+
ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` // id
|
| 282 |
+
AccountID int64 `gorm:"column:account_id;not null" json:"account_id"` // id akun
|
| 283 |
+
Account *Account `gorm:"foreignKey:AccountID;constraint:OnDelete:CASCADE" json:"account,omitempty"` // relasi ke akun
|
| 284 |
+
InstitutionName *string `gorm:"column:institution_name" json:"institution_name"` // nama instansi
|
| 285 |
+
CurrentJob *string `gorm:"column:current_job" json:"current_job"` // pekerjaan saat ini
|
| 286 |
+
YearStartedWorking *int `gorm:"column:year_started_working" json:"year_started_working"` // tahun mulai bekerja
|
| 287 |
+
MonthlyIncome *string `gorm:"column:monthly_income" json:"monthly_income"` // penghasilan per bulan
|
| 288 |
+
IncomeSources pq.StringArray `gorm:"column:income_sources;type:varchar(255)[]" json:"income_sources"` // sumber penghasilan
|
| 289 |
+
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"created_at"` // tanggal dibuat
|
| 290 |
+
UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime" json:"updated_at"` // tanggal diperbarui
|
| 291 |
}
|
| 292 |
|
| 293 |
AchievementCV struct {
|
space/models/request_model.go
CHANGED
|
@@ -1,6 +1,9 @@
|
|
| 1 |
package models
|
| 2 |
|
| 3 |
-
import
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
type LoginRequest struct {
|
| 6 |
Email string `json:"email" binding:"required"`
|
|
@@ -55,91 +58,91 @@ type AnswerQuizRequest struct {
|
|
| 55 |
type (
|
| 56 |
PersonalityAndPreferenceCVRequest struct {
|
| 57 |
AccountID int64 `json:"-"`
|
| 58 |
-
PositiveTraits *string `json:"positive_traits"`
|
| 59 |
-
NegativeTraits *string `json:"negative_traits"`
|
| 60 |
-
Hobbies *string `json:"hobbies"`
|
| 61 |
-
LifeGoals *string `json:"life_goals"`
|
| 62 |
-
DailyActivities *string `json:"daily_activities"`
|
| 63 |
-
LeisureActivities *string `json:"leisure_activities"`
|
| 64 |
-
Likes *string `json:"likes"`
|
| 65 |
-
Dislikes *string `json:"dislikes"`
|
| 66 |
-
StressHandling *string `json:"stress_handling"`
|
| 67 |
-
AngerTriggers *string `json:"anger_triggers"`
|
| 68 |
-
FavoriteFoodAndDrinks *string `json:"favorite_food_and_drinks"`
|
| 69 |
-
CanCook *bool `json:"can_cook"`
|
| 70 |
-
TypesOfDishesCooked *string `json:"types_of_dishes_cooked"`
|
| 71 |
-
MonthlyExpenses *string `json:"monthly_expenses"`
|
| 72 |
}
|
| 73 |
|
| 74 |
FamilyMemberRequest struct {
|
| 75 |
AccountID int64 `json:"-"`
|
| 76 |
-
Role *string `json:"role"`
|
| 77 |
-
Status *string `json:"status"`
|
| 78 |
-
Religion *string `json:"religion"`
|
| 79 |
-
Job *string `json:"job"`
|
| 80 |
-
LastEducation *string `json:"last_education"` // Pendidikan terakhir
|
| 81 |
-
Age *int `json:"age"`
|
| 82 |
}
|
| 83 |
|
| 84 |
PhysicalAndHealthRequest struct {
|
| 85 |
AccountID int64 `json:"-"`
|
| 86 |
-
HeightInCm *int `json:"height_cm"`
|
| 87 |
-
WeightInKg *int `json:"weight_kg"`
|
| 88 |
-
BodyShape *string `json:"body_shape"`
|
| 89 |
-
SkinColor *string `json:"skin_color"`
|
| 90 |
-
HairType *string `json:"hair_type"`
|
| 91 |
-
MedicalHistory *string `json:"medical_history"`
|
| 92 |
-
PhysicalDisorder *string `json:"physical_disorder"`
|
| 93 |
-
PhysicalTraits *string `json:"physical_traits"`
|
| 94 |
}
|
| 95 |
|
| 96 |
AccountDetailsRequest struct {
|
| 97 |
AccountID int64 `json:"-"`
|
| 98 |
FullName *string `json:"full_name"`
|
| 99 |
-
Gender *string `json:"gender"`
|
| 100 |
DateOfBirth *time.Time `json:"date_of_birth"`
|
| 101 |
PlaceOfBirth *string `json:"place_of_birth"`
|
| 102 |
Domicile *string `json:"domicile"`
|
| 103 |
-
MaritalStatus *string `json:"marital_status"`
|
| 104 |
-
LastEducation *string `json:"last_education"`
|
| 105 |
LastJob *string `json:"last_job"`
|
| 106 |
}
|
| 107 |
|
| 108 |
WorshipAndReligiousUnderstandingRequest struct {
|
| 109 |
-
AccountID int64
|
| 110 |
-
ObligatoryPrayer *string
|
| 111 |
-
CongregationalPrayer *string
|
| 112 |
-
TahajjudPrayer *string
|
| 113 |
-
DhuhaPrayer *string
|
| 114 |
-
QuranMemorization *string
|
| 115 |
-
QuranReadingAbility *string
|
| 116 |
-
DaudFasting *string
|
| 117 |
-
AyyamulBidhFasting *string
|
| 118 |
-
HajjOrUmrah
|
| 119 |
-
ListeningToMusic *string
|
| 120 |
-
OpinionOnIkhtilat *string
|
| 121 |
-
OpinionOnTouchingNonMahram *string
|
| 122 |
-
OpinionOnVeil *string
|
| 123 |
-
WeeklyReligiousStudies *string
|
| 124 |
-
FollowedUstadz *string
|
| 125 |
}
|
| 126 |
|
| 127 |
EducationRequest struct {
|
| 128 |
AccountID int64 `json:"account_id"`
|
| 129 |
-
LastEducation *string `json:"last_education"`
|
| 130 |
-
EducationInstitute *string `json:"education_institute"`
|
| 131 |
-
EducationMajor *string `json:"education_major"`
|
| 132 |
-
YearStart *int `json:"year_start"`
|
| 133 |
-
YearGraduate *int `json:"year_graduate"`
|
| 134 |
}
|
| 135 |
|
| 136 |
JobRequest struct {
|
| 137 |
-
AccountID int64
|
| 138 |
-
InstitutionName *string
|
| 139 |
-
CurrentJob *string
|
| 140 |
-
YearStartedWorking *int
|
| 141 |
-
MonthlyIncome *string
|
| 142 |
-
IncomeSources
|
| 143 |
}
|
| 144 |
|
| 145 |
AchievementRequest struct {
|
|
|
|
| 1 |
package models
|
| 2 |
|
| 3 |
+
import (
|
| 4 |
+
"github.com/lib/pq"
|
| 5 |
+
"time"
|
| 6 |
+
)
|
| 7 |
|
| 8 |
type LoginRequest struct {
|
| 9 |
Email string `json:"email" binding:"required"`
|
|
|
|
| 58 |
type (
|
| 59 |
PersonalityAndPreferenceCVRequest struct {
|
| 60 |
AccountID int64 `json:"-"`
|
| 61 |
+
PositiveTraits *string `json:"positive_traits"` // sifat positif
|
| 62 |
+
NegativeTraits *string `json:"negative_traits"` // sifat negatif
|
| 63 |
+
Hobbies *string `json:"hobbies"` // hobi
|
| 64 |
+
LifeGoals *string `json:"life_goals"` // target hidup
|
| 65 |
+
DailyActivities *string `json:"daily_activities"` // kegiatan sehari-hari
|
| 66 |
+
LeisureActivities *string `json:"leisure_activities"` // kegiatan waktu luang
|
| 67 |
+
Likes *string `json:"likes"` // hal yang disukai
|
| 68 |
+
Dislikes *string `json:"dislikes"` // hal yang tidak disukai
|
| 69 |
+
StressHandling *string `json:"stress_handling"` // cara mengatasi stres
|
| 70 |
+
AngerTriggers *string `json:"anger_triggers"` // pemicu amarah
|
| 71 |
+
FavoriteFoodAndDrinks *string `json:"favorite_food_and_drinks"` // makanan dan minuman favorit
|
| 72 |
+
CanCook *bool `json:"can_cook"` // bisa memasak
|
| 73 |
+
TypesOfDishesCooked *string `json:"types_of_dishes_cooked"` // jenis masakan yang bisa dimasak
|
| 74 |
+
MonthlyExpenses *string `json:"monthly_expenses" validate:"monthly_expenses"` // pengeluaran per bulan
|
| 75 |
}
|
| 76 |
|
| 77 |
FamilyMemberRequest struct {
|
| 78 |
AccountID int64 `json:"-"`
|
| 79 |
+
Role *string `json:"role" validate:"family_role"` // Peran dalam keluarga
|
| 80 |
+
Status *string `json:"status" validate:"life_status"` // Status (Hidup, Wafat)
|
| 81 |
+
Religion *string `json:"religion" validate:"religion"` // Agama
|
| 82 |
+
Job *string `json:"job"` // Pekerjaan
|
| 83 |
+
LastEducation *string `json:"last_education" validate:"last_education"` // Pendidikan terakhir
|
| 84 |
+
Age *int `json:"age"` // Usia
|
| 85 |
}
|
| 86 |
|
| 87 |
PhysicalAndHealthRequest struct {
|
| 88 |
AccountID int64 `json:"-"`
|
| 89 |
+
HeightInCm *int `json:"height_cm"` // Tinggi badan dalam satuan sentimeter
|
| 90 |
+
WeightInKg *int `json:"weight_kg"` // Berat badan dalam satuan kilogram
|
| 91 |
+
BodyShape *string `json:"body_shape" validate:"body_shape"` // Bentuk tubuh
|
| 92 |
+
SkinColor *string `json:"skin_color" validate:"skin_color"` // Warna kulit
|
| 93 |
+
HairType *string `json:"hair_type" validate:"hair_type"` // Tipe rambut
|
| 94 |
+
MedicalHistory *string `json:"medical_history"` // Riwayat penyakit
|
| 95 |
+
PhysicalDisorder *string `json:"physical_disorder"` // Cacat fisik
|
| 96 |
+
PhysicalTraits *string `json:"physical_traits"` // Ciri khas fisik
|
| 97 |
}
|
| 98 |
|
| 99 |
AccountDetailsRequest struct {
|
| 100 |
AccountID int64 `json:"-"`
|
| 101 |
FullName *string `json:"full_name"`
|
| 102 |
+
Gender *string `json:"gender" validate:"gender"`
|
| 103 |
DateOfBirth *time.Time `json:"date_of_birth"`
|
| 104 |
PlaceOfBirth *string `json:"place_of_birth"`
|
| 105 |
Domicile *string `json:"domicile"`
|
| 106 |
+
MaritalStatus *string `json:"marital_status" validate:"marital_status"`
|
| 107 |
+
LastEducation *string `json:"last_education" validate:"last_education"`
|
| 108 |
LastJob *string `json:"last_job"`
|
| 109 |
}
|
| 110 |
|
| 111 |
WorshipAndReligiousUnderstandingRequest struct {
|
| 112 |
+
AccountID int64 `json:"-"`
|
| 113 |
+
ObligatoryPrayer *string `json:"obligatory_prayer"` // sholat_wajib_5_waktu
|
| 114 |
+
CongregationalPrayer *string `json:"congregational_prayer"` // sholat_berjamaah_di_masjid
|
| 115 |
+
TahajjudPrayer *string `json:"tahajjud_prayer"` // sholat_tahajud
|
| 116 |
+
DhuhaPrayer *string `json:"dhuha_prayer"` // sholat_dhuha
|
| 117 |
+
QuranMemorization *string `json:"quran_memorization"` // hafalan_alquran
|
| 118 |
+
QuranReadingAbility *string `json:"quran_reading_ability" validate:"quran_reading_ability"` // kemampuan_baca_alquran
|
| 119 |
+
DaudFasting *string `json:"daud_fasting"` // puasa_daud
|
| 120 |
+
AyyamulBidhFasting *string `json:"ayyamul_bidh_fasting"` // puasa_ayyamul_bidh
|
| 121 |
+
HajjOrUmrah pq.StringArray `json:"hajj_or_umrah"` // ibadah_haji_umroh
|
| 122 |
+
ListeningToMusic *string `json:"listening_to_music"` // mendengarkan_musik
|
| 123 |
+
OpinionOnIkhtilat *string `json:"opinion_on_ikhtilat"` // pendapat_ikhtilat
|
| 124 |
+
OpinionOnTouchingNonMahram *string `json:"opinion_on_touching_non_mahram"` // pendapat_menyentuh_non_mahram
|
| 125 |
+
OpinionOnVeil *string `json:"opinion_on_veil"` // pendapat_tentang_cadar
|
| 126 |
+
WeeklyReligiousStudies *string `json:"weekly_religious_studies"` // kajian_yang_diikuti_dalam_sepekan
|
| 127 |
+
FollowedUstadz *string `json:"followed_ustadz"` // ustadz_yang_diikuti
|
| 128 |
}
|
| 129 |
|
| 130 |
EducationRequest struct {
|
| 131 |
AccountID int64 `json:"account_id"`
|
| 132 |
+
LastEducation *string `json:"last_education" validate:"last_education"` // pendidikan terakhir
|
| 133 |
+
EducationInstitute *string `json:"education_institute"` // institusi pendidikan
|
| 134 |
+
EducationMajor *string `json:"education_major"` // jurusan pendidikan
|
| 135 |
+
YearStart *int `json:"year_start"` // tahun masuk
|
| 136 |
+
YearGraduate *int `json:"year_graduate"` // tahun lulus
|
| 137 |
}
|
| 138 |
|
| 139 |
JobRequest struct {
|
| 140 |
+
AccountID int64 `json:"account_id"`
|
| 141 |
+
InstitutionName *string `json:"institution_name"` // nama instansi
|
| 142 |
+
CurrentJob *string `json:"current_job"` // pekerjaan saat ini
|
| 143 |
+
YearStartedWorking *int `json:"year_started_working"` // tahun mulai bekerja
|
| 144 |
+
MonthlyIncome *string `json:"monthly_income" validate:"monthly_income"` // penghasilan per bulan
|
| 145 |
+
IncomeSources pq.StringArray `json:"income_sources"` // sumber penghasilan
|
| 146 |
}
|
| 147 |
|
| 148 |
AchievementRequest struct {
|
space/space/controller/quiz/list_quiz_controller.go
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package controller
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"strconv"
|
| 5 |
+
|
| 6 |
+
"api.qobiltu.id/controller"
|
| 7 |
+
"api.qobiltu.id/models"
|
| 8 |
+
"api.qobiltu.id/services"
|
| 9 |
+
"github.com/gin-gonic/gin"
|
| 10 |
+
)
|
| 11 |
+
|
| 12 |
+
func List(c *gin.Context) {
|
| 13 |
+
quizList := services.QuizListService{}
|
| 14 |
+
quizListController := controller.Controller[any, models.Academy, []models.Quiz]{
|
| 15 |
+
Service: &quizList.Service,
|
| 16 |
+
}
|
| 17 |
+
quizListController.HeaderParse(c, func() {
|
| 18 |
+
academy_id, _ := strconv.Atoi(c.Param("academy_id"))
|
| 19 |
+
quizList.Constructor.ID = uint(academy_id)
|
| 20 |
+
quizList.Retrieve()
|
| 21 |
+
quizListController.Response(c)
|
| 22 |
+
})
|
| 23 |
+
}
|
space/space/go.mod
CHANGED
|
@@ -4,11 +4,15 @@ go 1.24.0
|
|
| 4 |
|
| 5 |
require (
|
| 6 |
github.com/gin-gonic/gin v1.10.0
|
|
|
|
|
|
|
|
|
|
| 7 |
github.com/golang-jwt/jwt/v5 v5.2.1
|
| 8 |
github.com/gosimple/slug v1.15.0
|
| 9 |
github.com/hibiken/asynq v0.25.1
|
| 10 |
github.com/joho/godotenv v1.5.1
|
| 11 |
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible
|
|
|
|
| 12 |
github.com/redis/go-redis/v9 v9.7.0
|
| 13 |
github.com/satori/go.uuid v1.2.0
|
| 14 |
golang.org/x/crypto v0.36.0
|
|
@@ -31,9 +35,6 @@ require (
|
|
| 31 |
github.com/gin-contrib/sse v1.0.0 // indirect
|
| 32 |
github.com/go-logr/logr v1.4.2 // indirect
|
| 33 |
github.com/go-logr/stdr v1.2.2 // indirect
|
| 34 |
-
github.com/go-playground/locales v0.14.1 // indirect
|
| 35 |
-
github.com/go-playground/universal-translator v0.18.1 // indirect
|
| 36 |
-
github.com/go-playground/validator/v10 v10.25.0 // indirect
|
| 37 |
github.com/goccy/go-json v0.10.5 // indirect
|
| 38 |
github.com/google/s2a-go v0.1.9 // indirect
|
| 39 |
github.com/google/uuid v1.6.0 // indirect
|
|
|
|
| 4 |
|
| 5 |
require (
|
| 6 |
github.com/gin-gonic/gin v1.10.0
|
| 7 |
+
github.com/go-playground/locales v0.14.1
|
| 8 |
+
github.com/go-playground/universal-translator v0.18.1
|
| 9 |
+
github.com/go-playground/validator/v10 v10.25.0
|
| 10 |
github.com/golang-jwt/jwt/v5 v5.2.1
|
| 11 |
github.com/gosimple/slug v1.15.0
|
| 12 |
github.com/hibiken/asynq v0.25.1
|
| 13 |
github.com/joho/godotenv v1.5.1
|
| 14 |
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible
|
| 15 |
+
github.com/lib/pq v1.10.9
|
| 16 |
github.com/redis/go-redis/v9 v9.7.0
|
| 17 |
github.com/satori/go.uuid v1.2.0
|
| 18 |
golang.org/x/crypto v0.36.0
|
|
|
|
| 35 |
github.com/gin-contrib/sse v1.0.0 // indirect
|
| 36 |
github.com/go-logr/logr v1.4.2 // indirect
|
| 37 |
github.com/go-logr/stdr v1.2.2 // indirect
|
|
|
|
|
|
|
|
|
|
| 38 |
github.com/goccy/go-json v0.10.5 // indirect
|
| 39 |
github.com/google/s2a-go v0.1.9 // indirect
|
| 40 |
github.com/google/uuid v1.6.0 // indirect
|
space/space/router/quiz_route.go
CHANGED
|
@@ -9,6 +9,7 @@ import (
|
|
| 9 |
func QuizRoute(router *gin.Engine) {
|
| 10 |
routerGroup := router.Group("/api/v1/quiz")
|
| 11 |
{
|
|
|
|
| 12 |
routerGroup.POST("/:academy_id/:quiz_id/attempt", middleware.AuthUser, QuizController.Attempt)
|
| 13 |
routerGroup.GET("/:academy_id/:quiz_id/question", middleware.AuthUser, QuizController.Question)
|
| 14 |
routerGroup.PUT("/:academy_id/:quiz_id/choose-answer", middleware.AuthUser, QuizController.Answer)
|
|
|
|
| 9 |
func QuizRoute(router *gin.Engine) {
|
| 10 |
routerGroup := router.Group("/api/v1/quiz")
|
| 11 |
{
|
| 12 |
+
routerGroup.GET("/:academy_id/list", middleware.AuthUser, QuizController.List)
|
| 13 |
routerGroup.POST("/:academy_id/:quiz_id/attempt", middleware.AuthUser, QuizController.Attempt)
|
| 14 |
routerGroup.GET("/:academy_id/:quiz_id/question", middleware.AuthUser, QuizController.Question)
|
| 15 |
routerGroup.PUT("/:academy_id/:quiz_id/choose-answer", middleware.AuthUser, QuizController.Answer)
|
space/space/services/academy_quiz_service.go
CHANGED
|
@@ -2,12 +2,12 @@ package services
|
|
| 2 |
|
| 3 |
import (
|
| 4 |
"errors"
|
| 5 |
-
"fmt"
|
| 6 |
"time"
|
| 7 |
|
| 8 |
"api.qobiltu.id/models"
|
| 9 |
"api.qobiltu.id/repositories"
|
| 10 |
)
|
|
|
|
| 11 |
type AttemptQuizService struct {
|
| 12 |
Service[models.Quiz, models.QuizAttempt]
|
| 13 |
}
|
|
@@ -16,6 +16,10 @@ type SubmitQuizService struct {
|
|
| 16 |
Service[models.QuizAttempt, models.QuizResultResponse]
|
| 17 |
}
|
| 18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
func AuthorizeQuizwithAcademy(s *AttemptQuizService, next func()) {
|
| 20 |
academyRepo := repositories.GetAcademyByID(s.Constructor.AcademyID)
|
| 21 |
s.Error = academyRepo.RowsError
|
|
@@ -77,8 +81,8 @@ func (s *AttemptQuizService) Validate(userID uint, next func(latestAttemptRepo r
|
|
| 77 |
}
|
| 78 |
s.Error = errors.Join(allAttemptsRepo.RowsError, quizRepo.RowsError)
|
| 79 |
CheckUserAttemptLimit(s, allAttemptsRepo, quizRepo, userID, func() {
|
| 80 |
-
fmt.Println("accountID", userID)
|
| 81 |
-
fmt.Println("quizID", s.Constructor.ID)
|
| 82 |
latestAttemptRepo := repositories.GetUserLastAttempt(userID, s.Constructor.ID)
|
| 83 |
if latestAttemptRepo.NoRecord {
|
| 84 |
s.Exception.DataNotFound = true
|
|
@@ -125,6 +129,7 @@ func (s *AttemptQuizService) Create(userID uint) {
|
|
| 125 |
}
|
| 126 |
})
|
| 127 |
}
|
|
|
|
| 128 |
func (s *SubmitQuizService) Create(userID uint) {
|
| 129 |
quizAttemptRepo := repositories.GetAttemptById(s.Constructor.ID)
|
| 130 |
if quizAttemptRepo.NoRecord {
|
|
@@ -151,3 +156,15 @@ func (s *SubmitQuizService) Create(userID uint) {
|
|
| 151 |
|
| 152 |
return
|
| 153 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
|
| 3 |
import (
|
| 4 |
"errors"
|
|
|
|
| 5 |
"time"
|
| 6 |
|
| 7 |
"api.qobiltu.id/models"
|
| 8 |
"api.qobiltu.id/repositories"
|
| 9 |
)
|
| 10 |
+
|
| 11 |
type AttemptQuizService struct {
|
| 12 |
Service[models.Quiz, models.QuizAttempt]
|
| 13 |
}
|
|
|
|
| 16 |
Service[models.QuizAttempt, models.QuizResultResponse]
|
| 17 |
}
|
| 18 |
|
| 19 |
+
type QuizListService struct {
|
| 20 |
+
Service[models.Academy, []models.Quiz]
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
func AuthorizeQuizwithAcademy(s *AttemptQuizService, next func()) {
|
| 24 |
academyRepo := repositories.GetAcademyByID(s.Constructor.AcademyID)
|
| 25 |
s.Error = academyRepo.RowsError
|
|
|
|
| 81 |
}
|
| 82 |
s.Error = errors.Join(allAttemptsRepo.RowsError, quizRepo.RowsError)
|
| 83 |
CheckUserAttemptLimit(s, allAttemptsRepo, quizRepo, userID, func() {
|
| 84 |
+
// fmt.Println("accountID", userID)
|
| 85 |
+
// fmt.Println("quizID", s.Constructor.ID)
|
| 86 |
latestAttemptRepo := repositories.GetUserLastAttempt(userID, s.Constructor.ID)
|
| 87 |
if latestAttemptRepo.NoRecord {
|
| 88 |
s.Exception.DataNotFound = true
|
|
|
|
| 129 |
}
|
| 130 |
})
|
| 131 |
}
|
| 132 |
+
|
| 133 |
func (s *SubmitQuizService) Create(userID uint) {
|
| 134 |
quizAttemptRepo := repositories.GetAttemptById(s.Constructor.ID)
|
| 135 |
if quizAttemptRepo.NoRecord {
|
|
|
|
| 156 |
|
| 157 |
return
|
| 158 |
}
|
| 159 |
+
|
| 160 |
+
func (s *QuizListService) Retrieve() {
|
| 161 |
+
quizRepo := repositories.GetQuizbyAcademyId(s.Constructor.ID)
|
| 162 |
+
s.Error = quizRepo.RowsError
|
| 163 |
+
if quizRepo.NoRecord {
|
| 164 |
+
s.Exception.DataNotFound = true
|
| 165 |
+
s.Exception.Message = "There is no quiz with given academy ID!"
|
| 166 |
+
return
|
| 167 |
+
}
|
| 168 |
+
s.Result = quizRepo.Result
|
| 169 |
+
return
|
| 170 |
+
}
|
space/space/space/config/database_connection_config.go
CHANGED
|
@@ -74,6 +74,9 @@ func AutoMigrateAll(db *gorm.DB) {
|
|
| 74 |
&models.FamilyMemberCV{},
|
| 75 |
&models.PhysicalAndHealthCV{},
|
| 76 |
&models.WorshipAndReligiousUnderstandingCV{},
|
|
|
|
|
|
|
|
|
|
| 77 |
)
|
| 78 |
|
| 79 |
if err != nil {
|
|
|
|
| 74 |
&models.FamilyMemberCV{},
|
| 75 |
&models.PhysicalAndHealthCV{},
|
| 76 |
&models.WorshipAndReligiousUnderstandingCV{},
|
| 77 |
+
&models.EducationCV{},
|
| 78 |
+
&models.JobCV{},
|
| 79 |
+
&models.AchievementCV{},
|
| 80 |
)
|
| 81 |
|
| 82 |
if err != nil {
|
space/space/space/controller/cv/cv_controller.go
CHANGED
|
@@ -28,6 +28,24 @@ type CVController interface {
|
|
| 28 |
|
| 29 |
SaveWorshipAndReligiousUnderstanding(ctx *gin.Context)
|
| 30 |
GetWorshipAndReligiousUnderstanding(ctx *gin.Context)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
}
|
| 32 |
|
| 33 |
type cvController struct {
|
|
@@ -265,3 +283,273 @@ func (c *cvController) GetWorshipAndReligiousUnderstanding(ctx *gin.Context) {
|
|
| 265 |
|
| 266 |
response.HandleSuccess(ctx, http.StatusOK, "Get worship and religious understanding success", res, nil)
|
| 267 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
|
| 29 |
SaveWorshipAndReligiousUnderstanding(ctx *gin.Context)
|
| 30 |
GetWorshipAndReligiousUnderstanding(ctx *gin.Context)
|
| 31 |
+
|
| 32 |
+
CreateEducation(ctx *gin.Context)
|
| 33 |
+
UpdateEducation(ctx *gin.Context)
|
| 34 |
+
ListEducation(ctx *gin.Context)
|
| 35 |
+
GetEducation(ctx *gin.Context)
|
| 36 |
+
DeleteEducation(ctx *gin.Context)
|
| 37 |
+
|
| 38 |
+
CreateJob(ctx *gin.Context)
|
| 39 |
+
UpdateJob(ctx *gin.Context)
|
| 40 |
+
ListJob(ctx *gin.Context)
|
| 41 |
+
GetJob(ctx *gin.Context)
|
| 42 |
+
DeleteJob(ctx *gin.Context)
|
| 43 |
+
|
| 44 |
+
CreateAchievement(ctx *gin.Context)
|
| 45 |
+
UpdateAchievement(ctx *gin.Context)
|
| 46 |
+
ListAchievement(ctx *gin.Context)
|
| 47 |
+
GetAchievement(ctx *gin.Context)
|
| 48 |
+
DeleteAchievement(ctx *gin.Context)
|
| 49 |
}
|
| 50 |
|
| 51 |
type cvController struct {
|
|
|
|
| 283 |
|
| 284 |
response.HandleSuccess(ctx, http.StatusOK, "Get worship and religious understanding success", res, nil)
|
| 285 |
}
|
| 286 |
+
|
| 287 |
+
// --- Education ---
|
| 288 |
+
func (c *cvController) CreateEducation(ctx *gin.Context) {
|
| 289 |
+
var req models.EducationRequest
|
| 290 |
+
if err := ctx.ShouldBindJSON(&req); err != nil {
|
| 291 |
+
response.HandleError(ctx, err)
|
| 292 |
+
return
|
| 293 |
+
}
|
| 294 |
+
|
| 295 |
+
accountData := middleware.GetAccountData(ctx)
|
| 296 |
+
req.AccountID = int64(accountData.UserID)
|
| 297 |
+
|
| 298 |
+
res, err := c.cvService.CreateEducation(ctx, &req)
|
| 299 |
+
if err != nil {
|
| 300 |
+
response.HandleError(ctx, err)
|
| 301 |
+
return
|
| 302 |
+
}
|
| 303 |
+
|
| 304 |
+
response.HandleSuccess(ctx, http.StatusOK, "Education created successfully", res, nil)
|
| 305 |
+
}
|
| 306 |
+
|
| 307 |
+
func (c *cvController) UpdateEducation(ctx *gin.Context) {
|
| 308 |
+
idStr := ctx.Param("id")
|
| 309 |
+
id, err := strconv.ParseInt(idStr, 10, 64)
|
| 310 |
+
if err != nil {
|
| 311 |
+
response.HandleError(ctx, err)
|
| 312 |
+
return
|
| 313 |
+
}
|
| 314 |
+
|
| 315 |
+
var req models.EducationRequest
|
| 316 |
+
if err := ctx.ShouldBindJSON(&req); err != nil {
|
| 317 |
+
response.HandleError(ctx, err)
|
| 318 |
+
return
|
| 319 |
+
}
|
| 320 |
+
|
| 321 |
+
res, err := c.cvService.UpdateEducation(ctx, id, &req)
|
| 322 |
+
if err != nil {
|
| 323 |
+
response.HandleError(ctx, err)
|
| 324 |
+
return
|
| 325 |
+
}
|
| 326 |
+
|
| 327 |
+
response.HandleSuccess(ctx, http.StatusOK, "Education updated successfully", res, nil)
|
| 328 |
+
}
|
| 329 |
+
|
| 330 |
+
func (c *cvController) ListEducation(ctx *gin.Context) {
|
| 331 |
+
accountData := middleware.GetAccountData(ctx)
|
| 332 |
+
accountID := int64(accountData.UserID)
|
| 333 |
+
|
| 334 |
+
res, err := c.cvService.ListEducation(ctx, accountID)
|
| 335 |
+
if err != nil {
|
| 336 |
+
response.HandleError(ctx, err)
|
| 337 |
+
return
|
| 338 |
+
}
|
| 339 |
+
|
| 340 |
+
response.HandleSuccess(ctx, http.StatusOK, "List of education retrieved successfully", res, nil)
|
| 341 |
+
}
|
| 342 |
+
|
| 343 |
+
func (c *cvController) GetEducation(ctx *gin.Context) {
|
| 344 |
+
idStr := ctx.Param("id")
|
| 345 |
+
id, err := strconv.ParseInt(idStr, 10, 64)
|
| 346 |
+
if err != nil {
|
| 347 |
+
response.HandleError(ctx, err)
|
| 348 |
+
return
|
| 349 |
+
}
|
| 350 |
+
|
| 351 |
+
res, err := c.cvService.GetEducation(ctx, id)
|
| 352 |
+
if err != nil {
|
| 353 |
+
response.HandleError(ctx, err)
|
| 354 |
+
return
|
| 355 |
+
}
|
| 356 |
+
|
| 357 |
+
response.HandleSuccess(ctx, http.StatusOK, "Get education success", res, nil)
|
| 358 |
+
}
|
| 359 |
+
|
| 360 |
+
func (c *cvController) DeleteEducation(ctx *gin.Context) {
|
| 361 |
+
idStr := ctx.Param("id")
|
| 362 |
+
id, err := strconv.ParseInt(idStr, 10, 64)
|
| 363 |
+
if err != nil {
|
| 364 |
+
response.HandleError(ctx, err)
|
| 365 |
+
return
|
| 366 |
+
}
|
| 367 |
+
|
| 368 |
+
err = c.cvService.DeleteEducation(ctx, id)
|
| 369 |
+
if err != nil {
|
| 370 |
+
response.HandleError(ctx, err)
|
| 371 |
+
return
|
| 372 |
+
}
|
| 373 |
+
|
| 374 |
+
response.HandleSuccess(ctx, http.StatusOK, "Education deleted successfully", nil, nil)
|
| 375 |
+
}
|
| 376 |
+
|
| 377 |
+
// --- Job ---
|
| 378 |
+
func (c *cvController) CreateJob(ctx *gin.Context) {
|
| 379 |
+
var req models.JobRequest
|
| 380 |
+
if err := ctx.ShouldBindJSON(&req); err != nil {
|
| 381 |
+
response.HandleError(ctx, err)
|
| 382 |
+
return
|
| 383 |
+
}
|
| 384 |
+
|
| 385 |
+
accountData := middleware.GetAccountData(ctx)
|
| 386 |
+
req.AccountID = int64(accountData.UserID)
|
| 387 |
+
|
| 388 |
+
res, err := c.cvService.CreateJob(ctx, &req)
|
| 389 |
+
if err != nil {
|
| 390 |
+
response.HandleError(ctx, err)
|
| 391 |
+
return
|
| 392 |
+
}
|
| 393 |
+
|
| 394 |
+
response.HandleSuccess(ctx, http.StatusOK, "Job created successfully", res, nil)
|
| 395 |
+
}
|
| 396 |
+
|
| 397 |
+
func (c *cvController) UpdateJob(ctx *gin.Context) {
|
| 398 |
+
idStr := ctx.Param("id")
|
| 399 |
+
id, err := strconv.ParseInt(idStr, 10, 64)
|
| 400 |
+
if err != nil {
|
| 401 |
+
response.HandleError(ctx, err)
|
| 402 |
+
return
|
| 403 |
+
}
|
| 404 |
+
|
| 405 |
+
var req models.JobRequest
|
| 406 |
+
if err := ctx.ShouldBindJSON(&req); err != nil {
|
| 407 |
+
response.HandleError(ctx, err)
|
| 408 |
+
return
|
| 409 |
+
}
|
| 410 |
+
|
| 411 |
+
res, err := c.cvService.UpdateJob(ctx, id, &req)
|
| 412 |
+
if err != nil {
|
| 413 |
+
response.HandleError(ctx, err)
|
| 414 |
+
return
|
| 415 |
+
}
|
| 416 |
+
|
| 417 |
+
response.HandleSuccess(ctx, http.StatusOK, "Job updated successfully", res, nil)
|
| 418 |
+
}
|
| 419 |
+
|
| 420 |
+
func (c *cvController) ListJob(ctx *gin.Context) {
|
| 421 |
+
accountData := middleware.GetAccountData(ctx)
|
| 422 |
+
accountID := int64(accountData.UserID)
|
| 423 |
+
|
| 424 |
+
res, err := c.cvService.ListJob(ctx, accountID)
|
| 425 |
+
if err != nil {
|
| 426 |
+
response.HandleError(ctx, err)
|
| 427 |
+
return
|
| 428 |
+
}
|
| 429 |
+
|
| 430 |
+
response.HandleSuccess(ctx, http.StatusOK, "List of jobs retrieved successfully", res, nil)
|
| 431 |
+
}
|
| 432 |
+
|
| 433 |
+
func (c *cvController) GetJob(ctx *gin.Context) {
|
| 434 |
+
idStr := ctx.Param("id")
|
| 435 |
+
id, err := strconv.ParseInt(idStr, 10, 64)
|
| 436 |
+
if err != nil {
|
| 437 |
+
response.HandleError(ctx, err)
|
| 438 |
+
return
|
| 439 |
+
}
|
| 440 |
+
|
| 441 |
+
res, err := c.cvService.GetJob(ctx, id)
|
| 442 |
+
if err != nil {
|
| 443 |
+
response.HandleError(ctx, err)
|
| 444 |
+
return
|
| 445 |
+
}
|
| 446 |
+
|
| 447 |
+
response.HandleSuccess(ctx, http.StatusOK, "Get job success", res, nil)
|
| 448 |
+
}
|
| 449 |
+
|
| 450 |
+
func (c *cvController) DeleteJob(ctx *gin.Context) {
|
| 451 |
+
idStr := ctx.Param("id")
|
| 452 |
+
id, err := strconv.ParseInt(idStr, 10, 64)
|
| 453 |
+
if err != nil {
|
| 454 |
+
response.HandleError(ctx, err)
|
| 455 |
+
return
|
| 456 |
+
}
|
| 457 |
+
|
| 458 |
+
err = c.cvService.DeleteJob(ctx, id)
|
| 459 |
+
if err != nil {
|
| 460 |
+
response.HandleError(ctx, err)
|
| 461 |
+
return
|
| 462 |
+
}
|
| 463 |
+
|
| 464 |
+
response.HandleSuccess(ctx, http.StatusOK, "Job deleted successfully", nil, nil)
|
| 465 |
+
}
|
| 466 |
+
|
| 467 |
+
// --- Achievement ---
|
| 468 |
+
func (c *cvController) CreateAchievement(ctx *gin.Context) {
|
| 469 |
+
var req models.AchievementRequest
|
| 470 |
+
if err := ctx.ShouldBindJSON(&req); err != nil {
|
| 471 |
+
response.HandleError(ctx, err)
|
| 472 |
+
return
|
| 473 |
+
}
|
| 474 |
+
|
| 475 |
+
accountData := middleware.GetAccountData(ctx)
|
| 476 |
+
req.AccountID = int64(accountData.UserID)
|
| 477 |
+
|
| 478 |
+
res, err := c.cvService.CreateAchievement(ctx, &req)
|
| 479 |
+
if err != nil {
|
| 480 |
+
response.HandleError(ctx, err)
|
| 481 |
+
return
|
| 482 |
+
}
|
| 483 |
+
|
| 484 |
+
response.HandleSuccess(ctx, http.StatusOK, "Achievement created successfully", res, nil)
|
| 485 |
+
}
|
| 486 |
+
|
| 487 |
+
func (c *cvController) UpdateAchievement(ctx *gin.Context) {
|
| 488 |
+
idStr := ctx.Param("id")
|
| 489 |
+
id, err := strconv.ParseInt(idStr, 10, 64)
|
| 490 |
+
if err != nil {
|
| 491 |
+
response.HandleError(ctx, err)
|
| 492 |
+
return
|
| 493 |
+
}
|
| 494 |
+
|
| 495 |
+
var req models.AchievementRequest
|
| 496 |
+
if err := ctx.ShouldBindJSON(&req); err != nil {
|
| 497 |
+
response.HandleError(ctx, err)
|
| 498 |
+
return
|
| 499 |
+
}
|
| 500 |
+
|
| 501 |
+
res, err := c.cvService.UpdateAchievement(ctx, id, &req)
|
| 502 |
+
if err != nil {
|
| 503 |
+
response.HandleError(ctx, err)
|
| 504 |
+
return
|
| 505 |
+
}
|
| 506 |
+
|
| 507 |
+
response.HandleSuccess(ctx, http.StatusOK, "Achievement updated successfully", res, nil)
|
| 508 |
+
}
|
| 509 |
+
|
| 510 |
+
func (c *cvController) ListAchievement(ctx *gin.Context) {
|
| 511 |
+
accountData := middleware.GetAccountData(ctx)
|
| 512 |
+
accountID := int64(accountData.UserID)
|
| 513 |
+
|
| 514 |
+
res, err := c.cvService.ListAchievement(ctx, accountID)
|
| 515 |
+
if err != nil {
|
| 516 |
+
response.HandleError(ctx, err)
|
| 517 |
+
return
|
| 518 |
+
}
|
| 519 |
+
|
| 520 |
+
response.HandleSuccess(ctx, http.StatusOK, "List of achievements retrieved successfully", res, nil)
|
| 521 |
+
}
|
| 522 |
+
|
| 523 |
+
func (c *cvController) GetAchievement(ctx *gin.Context) {
|
| 524 |
+
idStr := ctx.Param("id")
|
| 525 |
+
id, err := strconv.ParseInt(idStr, 10, 64)
|
| 526 |
+
if err != nil {
|
| 527 |
+
response.HandleError(ctx, err)
|
| 528 |
+
return
|
| 529 |
+
}
|
| 530 |
+
|
| 531 |
+
res, err := c.cvService.GetAchievement(ctx, id)
|
| 532 |
+
if err != nil {
|
| 533 |
+
response.HandleError(ctx, err)
|
| 534 |
+
return
|
| 535 |
+
}
|
| 536 |
+
|
| 537 |
+
response.HandleSuccess(ctx, http.StatusOK, "Get achievement success", res, nil)
|
| 538 |
+
}
|
| 539 |
+
|
| 540 |
+
func (c *cvController) DeleteAchievement(ctx *gin.Context) {
|
| 541 |
+
idStr := ctx.Param("id")
|
| 542 |
+
id, err := strconv.ParseInt(idStr, 10, 64)
|
| 543 |
+
if err != nil {
|
| 544 |
+
response.HandleError(ctx, err)
|
| 545 |
+
return
|
| 546 |
+
}
|
| 547 |
+
|
| 548 |
+
err = c.cvService.DeleteAchievement(ctx, id)
|
| 549 |
+
if err != nil {
|
| 550 |
+
response.HandleError(ctx, err)
|
| 551 |
+
return
|
| 552 |
+
}
|
| 553 |
+
|
| 554 |
+
response.HandleSuccess(ctx, http.StatusOK, "Achievement deleted successfully", nil, nil)
|
| 555 |
+
}
|
space/space/space/models/database_orm_model.go
CHANGED
|
@@ -155,6 +155,7 @@ type Question struct {
|
|
| 155 |
type Quiz struct {
|
| 156 |
ID uint `gorm:"primaryKey" json:"id"`
|
| 157 |
AcademyID uint `json:"academy_id"`
|
|
|
|
| 158 |
Title string `json:"title"`
|
| 159 |
Description string `json:"description"`
|
| 160 |
AttemptLimit int `json:"attempt_limit"`
|
|
@@ -261,6 +262,41 @@ type (
|
|
| 261 |
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"created_at"`
|
| 262 |
UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime" json:"updated_at"`
|
| 263 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 264 |
)
|
| 265 |
|
| 266 |
// Gorm table name settings
|
|
@@ -290,3 +326,6 @@ func (PhysicalAndHealthCV) TableName() string { return "physical_and_heal
|
|
| 290 |
func (WorshipAndReligiousUnderstandingCV) TableName() string {
|
| 291 |
return "worship_and_religious_understanding_cv"
|
| 292 |
}
|
|
|
|
|
|
|
|
|
|
|
|
| 155 |
type Quiz struct {
|
| 156 |
ID uint `gorm:"primaryKey" json:"id"`
|
| 157 |
AcademyID uint `json:"academy_id"`
|
| 158 |
+
Slug string `json:"slug" gorm:"uniqueIndex" `
|
| 159 |
Title string `json:"title"`
|
| 160 |
Description string `json:"description"`
|
| 161 |
AttemptLimit int `json:"attempt_limit"`
|
|
|
|
| 262 |
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"created_at"`
|
| 263 |
UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime" json:"updated_at"`
|
| 264 |
}
|
| 265 |
+
|
| 266 |
+
EducationCV struct {
|
| 267 |
+
ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` // id
|
| 268 |
+
AccountID int64 `gorm:"column:account_id;not null" json:"account_id"` // id akun
|
| 269 |
+
Account *Account `gorm:"foreignKey:AccountID;constraint:OnDelete:CASCADE" json:"account,omitempty"` // relasi ke akun
|
| 270 |
+
LastEducation *string `gorm:"column:last_education" json:"last_education"` // pendidikan terakhir
|
| 271 |
+
EducationInstitute *string `gorm:"column:education_institute" json:"education_institute"` // institusi pendidikan
|
| 272 |
+
EducationMajor *string `gorm:"column:education_major" json:"education_major"` // jurusan pendidikan
|
| 273 |
+
YearStart *int `gorm:"column:year_start" json:"year_start"` // tahun masuk
|
| 274 |
+
YearGraduate *int `gorm:"column:year_graduate" json:"year_graduate"` // tahun lulus
|
| 275 |
+
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"created_at"` // tanggal dibuat
|
| 276 |
+
UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime" json:"updated_at"` // tanggal diperbarui
|
| 277 |
+
}
|
| 278 |
+
|
| 279 |
+
JobCV struct {
|
| 280 |
+
ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` // id
|
| 281 |
+
AccountID int64 `gorm:"column:account_id;not null" json:"account_id"` // id akun
|
| 282 |
+
Account *Account `gorm:"foreignKey:AccountID;constraint:OnDelete:CASCADE" json:"account,omitempty"` // relasi ke akun
|
| 283 |
+
InstitutionName *string `gorm:"column:institution_name" json:"institution_name"` // nama instansi
|
| 284 |
+
CurrentJob *string `gorm:"column:current_job" json:"current_job"` // pekerjaan saat ini
|
| 285 |
+
YearStartedWorking *int `gorm:"column:year_started_working" json:"year_started_working"` // tahun mulai bekerja
|
| 286 |
+
MonthlyIncome *string `gorm:"column:monthly_income" json:"monthly_income"` // penghasilan per bulan
|
| 287 |
+
IncomeSources *string `gorm:"column:income_sources" json:"income_sources"` // sumber penghasilan
|
| 288 |
+
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"created_at"` // tanggal dibuat
|
| 289 |
+
UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime" json:"updated_at"` // tanggal diperbarui
|
| 290 |
+
}
|
| 291 |
+
|
| 292 |
+
AchievementCV struct {
|
| 293 |
+
ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"` // id
|
| 294 |
+
AccountID int64 `gorm:"column:account_id;not null" json:"account_id"` // id akun
|
| 295 |
+
Account *Account `gorm:"foreignKey:AccountID;constraint:OnDelete:CASCADE" json:"account,omitempty"` // relasi ke akun
|
| 296 |
+
AchievementOrAward *string `gorm:"column:achievement_or_award" json:"achievement_or_award"` // prestasi atau penghargaan
|
| 297 |
+
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"created_at"` // tanggal dibuat
|
| 298 |
+
UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime" json:"updated_at"` // tanggal diperbarui
|
| 299 |
+
}
|
| 300 |
)
|
| 301 |
|
| 302 |
// Gorm table name settings
|
|
|
|
| 326 |
func (WorshipAndReligiousUnderstandingCV) TableName() string {
|
| 327 |
return "worship_and_religious_understanding_cv"
|
| 328 |
}
|
| 329 |
+
func (EducationCV) TableName() string { return "education_cv" }
|
| 330 |
+
func (JobCV) TableName() string { return "job_cv" }
|
| 331 |
+
func (AchievementCV) TableName() string { return "achievement_cv" }
|
space/space/space/models/request_model.go
CHANGED
|
@@ -123,4 +123,27 @@ type (
|
|
| 123 |
WeeklyReligiousStudies *string `json:"weekly_religious_studies"` // kajian_yang_diikuti_dalam_sepekan
|
| 124 |
FollowedUstadz *string `json:"followed_ustadz"` // ustadz_yang_diikuti
|
| 125 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 126 |
)
|
|
|
|
| 123 |
WeeklyReligiousStudies *string `json:"weekly_religious_studies"` // kajian_yang_diikuti_dalam_sepekan
|
| 124 |
FollowedUstadz *string `json:"followed_ustadz"` // ustadz_yang_diikuti
|
| 125 |
}
|
| 126 |
+
|
| 127 |
+
EducationRequest struct {
|
| 128 |
+
AccountID int64 `json:"account_id"`
|
| 129 |
+
LastEducation *string `json:"last_education"` // pendidikan terakhir
|
| 130 |
+
EducationInstitute *string `json:"education_institute"` // institusi pendidikan
|
| 131 |
+
EducationMajor *string `json:"education_major"` // jurusan pendidikan
|
| 132 |
+
YearStart *int `json:"year_start"` // tahun masuk
|
| 133 |
+
YearGraduate *int `json:"year_graduate"` // tahun lulus
|
| 134 |
+
}
|
| 135 |
+
|
| 136 |
+
JobRequest struct {
|
| 137 |
+
AccountID int64 `json:"account_id"`
|
| 138 |
+
InstitutionName *string `json:"institution_name"` // nama instansi
|
| 139 |
+
CurrentJob *string `json:"current_job"` // pekerjaan saat ini
|
| 140 |
+
YearStartedWorking *int `json:"year_started_working"` // tahun mulai bekerja
|
| 141 |
+
MonthlyIncome *string `json:"monthly_income"` // penghasilan per bulan
|
| 142 |
+
IncomeSources *string `json:"income_sources"` // sumber penghasilan
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
AchievementRequest struct {
|
| 146 |
+
AccountID int64 `json:"account_id"`
|
| 147 |
+
AchievementOrAward *string `json:"achievement_or_award"` // prestasi atau penghargaan
|
| 148 |
+
}
|
| 149 |
)
|
space/space/space/repositories/cv_repository.go
CHANGED
|
@@ -23,6 +23,21 @@ type CVRepository interface {
|
|
| 23 |
|
| 24 |
SaveWorshipAndReligiousUnderstanding(ctx context.Context, req *models.WorshipAndReligiousUnderstandingCV) (*models.WorshipAndReligiousUnderstandingCV, error)
|
| 25 |
GetWorshipAndReligiousUnderstandingByAccountID(ctx context.Context, accountID int64) (*models.WorshipAndReligiousUnderstandingCV, error)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
}
|
| 27 |
|
| 28 |
type cvRepository struct {
|
|
@@ -124,3 +139,105 @@ func (r *cvRepository) GetWorshipAndReligiousUnderstandingByAccountID(ctx contex
|
|
| 124 |
}
|
| 125 |
return &worshipAndReligiousUnderstanding, nil
|
| 126 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
|
| 24 |
SaveWorshipAndReligiousUnderstanding(ctx context.Context, req *models.WorshipAndReligiousUnderstandingCV) (*models.WorshipAndReligiousUnderstandingCV, error)
|
| 25 |
GetWorshipAndReligiousUnderstandingByAccountID(ctx context.Context, accountID int64) (*models.WorshipAndReligiousUnderstandingCV, error)
|
| 26 |
+
|
| 27 |
+
SaveEducation(ctx context.Context, req *models.EducationCV) (*models.EducationCV, error)
|
| 28 |
+
ListEducation(ctx context.Context, accountID int64) ([]models.EducationCV, error)
|
| 29 |
+
GetEducation(ctx context.Context, id int64) (*models.EducationCV, error)
|
| 30 |
+
DeleteEducation(ctx context.Context, id int64) error
|
| 31 |
+
|
| 32 |
+
SaveJob(ctx context.Context, req *models.JobCV) (*models.JobCV, error)
|
| 33 |
+
ListJob(ctx context.Context, accountID int64) ([]models.JobCV, error)
|
| 34 |
+
GetJob(ctx context.Context, id int64) (*models.JobCV, error)
|
| 35 |
+
DeleteJob(ctx context.Context, id int64) error
|
| 36 |
+
|
| 37 |
+
SaveAchievement(ctx context.Context, req *models.AchievementCV) (*models.AchievementCV, error)
|
| 38 |
+
ListAchievement(ctx context.Context, accountID int64) ([]models.AchievementCV, error)
|
| 39 |
+
GetAchievement(ctx context.Context, id int64) (*models.AchievementCV, error)
|
| 40 |
+
DeleteAchievement(ctx context.Context, id int64) error
|
| 41 |
}
|
| 42 |
|
| 43 |
type cvRepository struct {
|
|
|
|
| 139 |
}
|
| 140 |
return &worshipAndReligiousUnderstanding, nil
|
| 141 |
}
|
| 142 |
+
|
| 143 |
+
// SaveEducation menyimpan atau memperbarui data pendidikan ke database
|
| 144 |
+
func (r *cvRepository) SaveEducation(ctx context.Context, req *models.EducationCV) (*models.EducationCV, error) {
|
| 145 |
+
if err := r.db.WithContext(ctx).Save(req).Error; err != nil {
|
| 146 |
+
return req, err
|
| 147 |
+
}
|
| 148 |
+
return req, nil
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
// ListEducation mengambil daftar data pendidikan berdasarkan account_id
|
| 152 |
+
func (r *cvRepository) ListEducation(ctx context.Context, accountID int64) ([]models.EducationCV, error) {
|
| 153 |
+
var educations []models.EducationCV
|
| 154 |
+
if err := r.db.WithContext(ctx).Where("account_id = ?", accountID).Find(&educations).Error; err != nil {
|
| 155 |
+
return nil, err
|
| 156 |
+
}
|
| 157 |
+
return educations, nil
|
| 158 |
+
}
|
| 159 |
+
|
| 160 |
+
// GetEducation mengambil satu data pendidikan berdasarkan id
|
| 161 |
+
func (r *cvRepository) GetEducation(ctx context.Context, id int64) (*models.EducationCV, error) {
|
| 162 |
+
var education models.EducationCV
|
| 163 |
+
if err := r.db.WithContext(ctx).Where("id = ?", id).First(&education).Error; err != nil {
|
| 164 |
+
return nil, err
|
| 165 |
+
}
|
| 166 |
+
return &education, nil
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
// DeleteEducation menghapus data pendidikan berdasarkan id
|
| 170 |
+
func (r *cvRepository) DeleteEducation(ctx context.Context, id int64) error {
|
| 171 |
+
if err := r.db.WithContext(ctx).Where("id = ?", id).Delete(&models.EducationCV{}).Error; err != nil {
|
| 172 |
+
return err
|
| 173 |
+
}
|
| 174 |
+
return nil
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
// SaveJob menyimpan atau memperbarui data pekerjaan ke database
|
| 178 |
+
func (r *cvRepository) SaveJob(ctx context.Context, req *models.JobCV) (*models.JobCV, error) {
|
| 179 |
+
if err := r.db.WithContext(ctx).Save(req).Error; err != nil {
|
| 180 |
+
return req, err
|
| 181 |
+
}
|
| 182 |
+
return req, nil
|
| 183 |
+
}
|
| 184 |
+
|
| 185 |
+
// ListJob mengambil daftar data pekerjaan berdasarkan account_id
|
| 186 |
+
func (r *cvRepository) ListJob(ctx context.Context, accountID int64) ([]models.JobCV, error) {
|
| 187 |
+
var jobs []models.JobCV
|
| 188 |
+
if err := r.db.WithContext(ctx).Where("account_id = ?", accountID).Find(&jobs).Error; err != nil {
|
| 189 |
+
return nil, err
|
| 190 |
+
}
|
| 191 |
+
return jobs, nil
|
| 192 |
+
}
|
| 193 |
+
|
| 194 |
+
// GetJob mengambil satu data pekerjaan berdasarkan id
|
| 195 |
+
func (r *cvRepository) GetJob(ctx context.Context, id int64) (*models.JobCV, error) {
|
| 196 |
+
var job models.JobCV
|
| 197 |
+
if err := r.db.WithContext(ctx).Where("id = ?", id).First(&job).Error; err != nil {
|
| 198 |
+
return nil, err
|
| 199 |
+
}
|
| 200 |
+
return &job, nil
|
| 201 |
+
}
|
| 202 |
+
|
| 203 |
+
// DeleteJob menghapus data pekerjaan berdasarkan id
|
| 204 |
+
func (r *cvRepository) DeleteJob(ctx context.Context, id int64) error {
|
| 205 |
+
if err := r.db.WithContext(ctx).Where("id = ?", id).Delete(&models.JobCV{}).Error; err != nil {
|
| 206 |
+
return err
|
| 207 |
+
}
|
| 208 |
+
return nil
|
| 209 |
+
}
|
| 210 |
+
|
| 211 |
+
// SaveAchievement menyimpan atau memperbarui data prestasi ke database
|
| 212 |
+
func (r *cvRepository) SaveAchievement(ctx context.Context, req *models.AchievementCV) (*models.AchievementCV, error) {
|
| 213 |
+
if err := r.db.WithContext(ctx).Save(req).Error; err != nil {
|
| 214 |
+
return req, err
|
| 215 |
+
}
|
| 216 |
+
return req, nil
|
| 217 |
+
}
|
| 218 |
+
|
| 219 |
+
// ListAchievement mengambil daftar data prestasi berdasarkan account_id
|
| 220 |
+
func (r *cvRepository) ListAchievement(ctx context.Context, accountID int64) ([]models.AchievementCV, error) {
|
| 221 |
+
var achievements []models.AchievementCV
|
| 222 |
+
if err := r.db.WithContext(ctx).Where("account_id = ?", accountID).Find(&achievements).Error; err != nil {
|
| 223 |
+
return nil, err
|
| 224 |
+
}
|
| 225 |
+
return achievements, nil
|
| 226 |
+
}
|
| 227 |
+
|
| 228 |
+
// GetAchievement mengambil satu data prestasi berdasarkan id
|
| 229 |
+
func (r *cvRepository) GetAchievement(ctx context.Context, id int64) (*models.AchievementCV, error) {
|
| 230 |
+
var achievement models.AchievementCV
|
| 231 |
+
if err := r.db.WithContext(ctx).Where("id = ?", id).First(&achievement).Error; err != nil {
|
| 232 |
+
return nil, err
|
| 233 |
+
}
|
| 234 |
+
return &achievement, nil
|
| 235 |
+
}
|
| 236 |
+
|
| 237 |
+
// DeleteAchievement menghapus data prestasi berdasarkan id
|
| 238 |
+
func (r *cvRepository) DeleteAchievement(ctx context.Context, id int64) error {
|
| 239 |
+
if err := r.db.WithContext(ctx).Where("id = ?", id).Delete(&models.AchievementCV{}).Error; err != nil {
|
| 240 |
+
return err
|
| 241 |
+
}
|
| 242 |
+
return nil
|
| 243 |
+
}
|
space/space/space/router/cv_route.go
CHANGED
|
@@ -22,5 +22,23 @@ func (s *Server) CVRoute() {
|
|
| 22 |
|
| 23 |
routerGroup.POST("/worship-and-religious-understandings", s.cvController.SaveWorshipAndReligiousUnderstanding)
|
| 24 |
routerGroup.GET("/worship-and-religious-understandings", s.cvController.GetWorshipAndReligiousUnderstanding)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
}
|
| 26 |
}
|
|
|
|
| 22 |
|
| 23 |
routerGroup.POST("/worship-and-religious-understandings", s.cvController.SaveWorshipAndReligiousUnderstanding)
|
| 24 |
routerGroup.GET("/worship-and-religious-understandings", s.cvController.GetWorshipAndReligiousUnderstanding)
|
| 25 |
+
|
| 26 |
+
routerGroup.POST("/educations", s.cvController.CreateEducation)
|
| 27 |
+
routerGroup.GET("/educations", s.cvController.ListEducation)
|
| 28 |
+
routerGroup.GET("/educations/:id", s.cvController.GetEducation)
|
| 29 |
+
routerGroup.PUT("/educations/:id", s.cvController.UpdateEducation)
|
| 30 |
+
routerGroup.DELETE("/educations/:id", s.cvController.DeleteEducation)
|
| 31 |
+
|
| 32 |
+
routerGroup.POST("/jobs", s.cvController.CreateJob)
|
| 33 |
+
routerGroup.GET("/jobs", s.cvController.ListJob)
|
| 34 |
+
routerGroup.GET("/jobs/:id", s.cvController.GetJob)
|
| 35 |
+
routerGroup.PUT("/jobs/:id", s.cvController.UpdateJob)
|
| 36 |
+
routerGroup.DELETE("/jobs/:id", s.cvController.DeleteJob)
|
| 37 |
+
|
| 38 |
+
routerGroup.POST("/achievements", s.cvController.CreateAchievement)
|
| 39 |
+
routerGroup.GET("/achievements", s.cvController.ListAchievement)
|
| 40 |
+
routerGroup.GET("/achievements/:id", s.cvController.GetAchievement)
|
| 41 |
+
routerGroup.PUT("/achievements/:id", s.cvController.UpdateAchievement)
|
| 42 |
+
routerGroup.DELETE("/achievements/:id", s.cvController.DeleteAchievement)
|
| 43 |
}
|
| 44 |
}
|
space/space/space/services/cv_service.go
CHANGED
|
@@ -27,6 +27,24 @@ type CVService interface {
|
|
| 27 |
|
| 28 |
SaveWorshipAndReligiousUnderstanding(ctx context.Context, req *models.WorshipAndReligiousUnderstandingRequest) (*models.WorshipAndReligiousUnderstandingCV, error)
|
| 29 |
GetWorshipAndReligiousUnderstanding(ctx context.Context, id int64) (*models.WorshipAndReligiousUnderstandingCV, error)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
}
|
| 31 |
|
| 32 |
type cvService struct {
|
|
@@ -275,3 +293,152 @@ func (s *cvService) GetWorshipAndReligiousUnderstanding(ctx context.Context, id
|
|
| 275 |
}
|
| 276 |
return res, nil
|
| 277 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
|
| 28 |
SaveWorshipAndReligiousUnderstanding(ctx context.Context, req *models.WorshipAndReligiousUnderstandingRequest) (*models.WorshipAndReligiousUnderstandingCV, error)
|
| 29 |
GetWorshipAndReligiousUnderstanding(ctx context.Context, id int64) (*models.WorshipAndReligiousUnderstandingCV, error)
|
| 30 |
+
|
| 31 |
+
CreateEducation(ctx context.Context, req *models.EducationRequest) (*models.EducationCV, error)
|
| 32 |
+
UpdateEducation(ctx context.Context, id int64, req *models.EducationRequest) (*models.EducationCV, error)
|
| 33 |
+
ListEducation(ctx context.Context, accountID int64) ([]models.EducationCV, error)
|
| 34 |
+
GetEducation(ctx context.Context, id int64) (*models.EducationCV, error)
|
| 35 |
+
DeleteEducation(ctx context.Context, id int64) error
|
| 36 |
+
|
| 37 |
+
CreateJob(ctx context.Context, req *models.JobRequest) (*models.JobCV, error)
|
| 38 |
+
UpdateJob(ctx context.Context, id int64, req *models.JobRequest) (*models.JobCV, error)
|
| 39 |
+
ListJob(ctx context.Context, accountID int64) ([]models.JobCV, error)
|
| 40 |
+
GetJob(ctx context.Context, id int64) (*models.JobCV, error)
|
| 41 |
+
DeleteJob(ctx context.Context, id int64) error
|
| 42 |
+
|
| 43 |
+
CreateAchievement(ctx context.Context, req *models.AchievementRequest) (*models.AchievementCV, error)
|
| 44 |
+
UpdateAchievement(ctx context.Context, id int64, req *models.AchievementRequest) (*models.AchievementCV, error)
|
| 45 |
+
ListAchievement(ctx context.Context, accountID int64) ([]models.AchievementCV, error)
|
| 46 |
+
GetAchievement(ctx context.Context, id int64) (*models.AchievementCV, error)
|
| 47 |
+
DeleteAchievement(ctx context.Context, id int64) error
|
| 48 |
}
|
| 49 |
|
| 50 |
type cvService struct {
|
|
|
|
| 293 |
}
|
| 294 |
return res, nil
|
| 295 |
}
|
| 296 |
+
|
| 297 |
+
func (s *cvService) CreateEducation(ctx context.Context, req *models.EducationRequest) (*models.EducationCV, error) {
|
| 298 |
+
edu := &models.EducationCV{
|
| 299 |
+
AccountID: req.AccountID,
|
| 300 |
+
LastEducation: req.LastEducation,
|
| 301 |
+
EducationInstitute: req.EducationInstitute,
|
| 302 |
+
EducationMajor: req.EducationMajor,
|
| 303 |
+
YearStart: req.YearStart,
|
| 304 |
+
YearGraduate: req.YearGraduate,
|
| 305 |
+
}
|
| 306 |
+
|
| 307 |
+
res, err := s.cvRepository.SaveEducation(ctx, edu)
|
| 308 |
+
if err != nil {
|
| 309 |
+
return nil, response.HandleGormError(err, "Gagal menambahkan data pendidikan")
|
| 310 |
+
}
|
| 311 |
+
|
| 312 |
+
return res, nil
|
| 313 |
+
}
|
| 314 |
+
|
| 315 |
+
func (s *cvService) UpdateEducation(ctx context.Context, id int64, req *models.EducationRequest) (*models.EducationCV, error) {
|
| 316 |
+
edu, err := s.cvRepository.GetEducation(ctx, id)
|
| 317 |
+
if err != nil {
|
| 318 |
+
return nil, response.HandleGormError(err, "Data pendidikan tidak ditemukan")
|
| 319 |
+
}
|
| 320 |
+
|
| 321 |
+
edu.LastEducation = req.LastEducation
|
| 322 |
+
edu.EducationInstitute = req.EducationInstitute
|
| 323 |
+
edu.EducationMajor = req.EducationMajor
|
| 324 |
+
edu.YearStart = req.YearStart
|
| 325 |
+
edu.YearGraduate = req.YearGraduate
|
| 326 |
+
|
| 327 |
+
res, err := s.cvRepository.SaveEducation(ctx, edu)
|
| 328 |
+
if err != nil {
|
| 329 |
+
return nil, response.HandleGormError(err, "Gagal memperbarui data pendidikan")
|
| 330 |
+
}
|
| 331 |
+
return res, nil
|
| 332 |
+
}
|
| 333 |
+
|
| 334 |
+
func (s *cvService) ListEducation(ctx context.Context, accountID int64) ([]models.EducationCV, error) {
|
| 335 |
+
return s.cvRepository.ListEducation(ctx, accountID)
|
| 336 |
+
}
|
| 337 |
+
|
| 338 |
+
func (s *cvService) GetEducation(ctx context.Context, id int64) (*models.EducationCV, error) {
|
| 339 |
+
edu, err := s.cvRepository.GetEducation(ctx, id)
|
| 340 |
+
if err != nil {
|
| 341 |
+
return nil, response.HandleGormError(err, "Data pendidikan tidak ditemukan")
|
| 342 |
+
}
|
| 343 |
+
return edu, nil
|
| 344 |
+
}
|
| 345 |
+
|
| 346 |
+
func (s *cvService) DeleteEducation(ctx context.Context, id int64) error {
|
| 347 |
+
return s.cvRepository.DeleteEducation(ctx, id)
|
| 348 |
+
}
|
| 349 |
+
|
| 350 |
+
func (s *cvService) CreateJob(ctx context.Context, req *models.JobRequest) (*models.JobCV, error) {
|
| 351 |
+
job := &models.JobCV{
|
| 352 |
+
AccountID: req.AccountID,
|
| 353 |
+
InstitutionName: req.InstitutionName,
|
| 354 |
+
CurrentJob: req.CurrentJob,
|
| 355 |
+
YearStartedWorking: req.YearStartedWorking,
|
| 356 |
+
MonthlyIncome: req.MonthlyIncome,
|
| 357 |
+
IncomeSources: req.IncomeSources,
|
| 358 |
+
}
|
| 359 |
+
res, err := s.cvRepository.SaveJob(ctx, job)
|
| 360 |
+
if err != nil {
|
| 361 |
+
return nil, response.HandleGormError(err, "Gagal menambahkan data pekerjaan")
|
| 362 |
+
}
|
| 363 |
+
return res, nil
|
| 364 |
+
}
|
| 365 |
+
|
| 366 |
+
func (s *cvService) UpdateJob(ctx context.Context, id int64, req *models.JobRequest) (*models.JobCV, error) {
|
| 367 |
+
job, err := s.cvRepository.GetJob(ctx, id)
|
| 368 |
+
if err != nil {
|
| 369 |
+
return nil, response.HandleGormError(err, "Data pekerjaan tidak ditemukan")
|
| 370 |
+
}
|
| 371 |
+
|
| 372 |
+
job.InstitutionName = req.InstitutionName
|
| 373 |
+
job.CurrentJob = req.CurrentJob
|
| 374 |
+
job.YearStartedWorking = req.YearStartedWorking
|
| 375 |
+
job.MonthlyIncome = req.MonthlyIncome
|
| 376 |
+
job.IncomeSources = req.IncomeSources
|
| 377 |
+
|
| 378 |
+
res, err := s.cvRepository.SaveJob(ctx, job)
|
| 379 |
+
if err != nil {
|
| 380 |
+
return nil, response.HandleGormError(err, "Gagal memperbarui data pekerjaan")
|
| 381 |
+
}
|
| 382 |
+
return res, nil
|
| 383 |
+
}
|
| 384 |
+
|
| 385 |
+
func (s *cvService) ListJob(ctx context.Context, accountID int64) ([]models.JobCV, error) {
|
| 386 |
+
return s.cvRepository.ListJob(ctx, accountID)
|
| 387 |
+
}
|
| 388 |
+
|
| 389 |
+
func (s *cvService) GetJob(ctx context.Context, id int64) (*models.JobCV, error) {
|
| 390 |
+
job, err := s.cvRepository.GetJob(ctx, id)
|
| 391 |
+
if err != nil {
|
| 392 |
+
return nil, response.HandleGormError(err, "Data pekerjaan tidak ditemukan")
|
| 393 |
+
}
|
| 394 |
+
return job, nil
|
| 395 |
+
}
|
| 396 |
+
|
| 397 |
+
func (s *cvService) DeleteJob(ctx context.Context, id int64) error {
|
| 398 |
+
return s.cvRepository.DeleteJob(ctx, id)
|
| 399 |
+
}
|
| 400 |
+
|
| 401 |
+
func (s *cvService) CreateAchievement(ctx context.Context, req *models.AchievementRequest) (*models.AchievementCV, error) {
|
| 402 |
+
ach := &models.AchievementCV{
|
| 403 |
+
AccountID: req.AccountID,
|
| 404 |
+
AchievementOrAward: req.AchievementOrAward,
|
| 405 |
+
}
|
| 406 |
+
res, err := s.cvRepository.SaveAchievement(ctx, ach)
|
| 407 |
+
if err != nil {
|
| 408 |
+
return nil, response.HandleGormError(err, "Gagal menambahkan data prestasi")
|
| 409 |
+
}
|
| 410 |
+
|
| 411 |
+
return res, nil
|
| 412 |
+
}
|
| 413 |
+
|
| 414 |
+
func (s *cvService) UpdateAchievement(ctx context.Context, id int64, req *models.AchievementRequest) (*models.AchievementCV, error) {
|
| 415 |
+
ach, err := s.cvRepository.GetAchievement(ctx, id)
|
| 416 |
+
if err != nil {
|
| 417 |
+
return nil, response.HandleGormError(err, "Data prestasi tidak ditemukan")
|
| 418 |
+
}
|
| 419 |
+
|
| 420 |
+
ach.AchievementOrAward = req.AchievementOrAward
|
| 421 |
+
|
| 422 |
+
res, err := s.cvRepository.SaveAchievement(ctx, ach)
|
| 423 |
+
if err != nil {
|
| 424 |
+
return nil, response.HandleGormError(err, "Gagal memperbarui data prestasi")
|
| 425 |
+
}
|
| 426 |
+
|
| 427 |
+
return res, nil
|
| 428 |
+
}
|
| 429 |
+
|
| 430 |
+
func (s *cvService) ListAchievement(ctx context.Context, accountID int64) ([]models.AchievementCV, error) {
|
| 431 |
+
return s.cvRepository.ListAchievement(ctx, accountID)
|
| 432 |
+
}
|
| 433 |
+
|
| 434 |
+
func (s *cvService) GetAchievement(ctx context.Context, id int64) (*models.AchievementCV, error) {
|
| 435 |
+
ach, err := s.cvRepository.GetAchievement(ctx, id)
|
| 436 |
+
if err != nil {
|
| 437 |
+
return nil, response.HandleGormError(err, "Data prestasi tidak ditemukan")
|
| 438 |
+
}
|
| 439 |
+
return ach, nil
|
| 440 |
+
}
|
| 441 |
+
|
| 442 |
+
func (s *cvService) DeleteAchievement(ctx context.Context, id int64) error {
|
| 443 |
+
return s.cvRepository.DeleteAchievement(ctx, id)
|
| 444 |
+
}
|
space/space/space/space/controller/user/user_profile_controller.go
CHANGED
|
@@ -1,21 +1,21 @@
|
|
| 1 |
-
package user
|
| 2 |
-
|
| 3 |
-
import (
|
| 4 |
-
"api.qobiltu.id/controller"
|
| 5 |
-
"api.qobiltu.id/models"
|
| 6 |
-
"api.qobiltu.id/services"
|
| 7 |
-
"github.com/gin-gonic/gin"
|
| 8 |
-
)
|
| 9 |
-
|
| 10 |
-
func Profile(c *gin.Context) {
|
| 11 |
-
userProfile := services.UserProfileService{}
|
| 12 |
-
userProfileController := controller.Controller[any, models.AccountDetails, models.UserProfileResponse]{
|
| 13 |
-
Service: &userProfile.Service,
|
| 14 |
-
}
|
| 15 |
-
userProfileController.HeaderParse(c, func() {
|
| 16 |
-
userProfileController.Service.Constructor.AccountID = uint(userProfileController.AccountData.UserID)
|
| 17 |
-
userProfile.Retrieve()
|
| 18 |
-
userProfileController.Response(c)
|
| 19 |
-
},
|
| 20 |
-
)
|
| 21 |
-
}
|
|
|
|
| 1 |
+
package user
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"api.qobiltu.id/controller"
|
| 5 |
+
"api.qobiltu.id/models"
|
| 6 |
+
"api.qobiltu.id/services"
|
| 7 |
+
"github.com/gin-gonic/gin"
|
| 8 |
+
)
|
| 9 |
+
|
| 10 |
+
func Profile(c *gin.Context) {
|
| 11 |
+
userProfile := services.UserProfileService{}
|
| 12 |
+
userProfileController := controller.Controller[any, models.AccountDetails, models.UserProfileResponse]{
|
| 13 |
+
Service: &userProfile.Service,
|
| 14 |
+
}
|
| 15 |
+
userProfileController.HeaderParse(c, func() {
|
| 16 |
+
userProfileController.Service.Constructor.AccountID = uint(userProfileController.AccountData.UserID)
|
| 17 |
+
userProfile.Retrieve()
|
| 18 |
+
userProfileController.Response(c)
|
| 19 |
+
},
|
| 20 |
+
)
|
| 21 |
+
}
|
space/space/space/space/controller/user/user_update_profile_controller.go
CHANGED
|
@@ -1,25 +1,25 @@
|
|
| 1 |
-
package user
|
| 2 |
-
|
| 3 |
-
import (
|
| 4 |
-
"api.qobiltu.id/controller"
|
| 5 |
-
"api.qobiltu.id/models"
|
| 6 |
-
"api.qobiltu.id/services"
|
| 7 |
-
"github.com/gin-gonic/gin"
|
| 8 |
-
)
|
| 9 |
-
|
| 10 |
-
func UpdateProfile(c *gin.Context) {
|
| 11 |
-
userProfile := services.UserProfileService{}
|
| 12 |
-
userUpdateProfileController := controller.Controller[models.AccountDetails, models.AccountDetails, models.UserProfileResponse]{
|
| 13 |
-
Service: &userProfile.Service,
|
| 14 |
-
}
|
| 15 |
-
|
| 16 |
-
userUpdateProfileController.RequestJSON(c, func() {
|
| 17 |
-
userUpdateProfileController.Service.Constructor = userUpdateProfileController.Request
|
| 18 |
-
userUpdateProfileController.HeaderParse(c, func() {
|
| 19 |
-
userUpdateProfileController.Service.Constructor.AccountID =
|
| 20 |
-
|
| 21 |
-
})
|
| 22 |
-
userProfile.Update()
|
| 23 |
-
},
|
| 24 |
-
)
|
| 25 |
-
}
|
|
|
|
| 1 |
+
package user
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"api.qobiltu.id/controller"
|
| 5 |
+
"api.qobiltu.id/models"
|
| 6 |
+
"api.qobiltu.id/services"
|
| 7 |
+
"github.com/gin-gonic/gin"
|
| 8 |
+
)
|
| 9 |
+
|
| 10 |
+
func UpdateProfile(c *gin.Context) {
|
| 11 |
+
userProfile := services.UserProfileService{}
|
| 12 |
+
userUpdateProfileController := controller.Controller[models.AccountDetails, models.AccountDetails, models.UserProfileResponse]{
|
| 13 |
+
Service: &userProfile.Service,
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
userUpdateProfileController.RequestJSON(c, func() {
|
| 17 |
+
userUpdateProfileController.Service.Constructor = userUpdateProfileController.Request
|
| 18 |
+
userUpdateProfileController.HeaderParse(c, func() {
|
| 19 |
+
userUpdateProfileController.Service.Constructor.AccountID = userUpdateProfileController.AccountData.UserID
|
| 20 |
+
|
| 21 |
+
})
|
| 22 |
+
userProfile.Update()
|
| 23 |
+
},
|
| 24 |
+
)
|
| 25 |
+
}
|
space/space/space/space/repositories/account_repository.go
CHANGED
|
@@ -1,87 +1,87 @@
|
|
| 1 |
-
package repositories
|
| 2 |
-
|
| 3 |
-
import (
|
| 4 |
-
"api.qobiltu.id/models"
|
| 5 |
-
)
|
| 6 |
-
|
| 7 |
-
func GetAccountbyEmail(email string) Repository[models.Account, models.Account] {
|
| 8 |
-
repo := Construct[models.Account, models.Account](
|
| 9 |
-
models.Account{Email: email},
|
| 10 |
-
)
|
| 11 |
-
repo.Transactions(
|
| 12 |
-
WhereGivenConstructor[models.Account, models.Account],
|
| 13 |
-
Find[models.Account, models.Account],
|
| 14 |
-
)
|
| 15 |
-
return *repo
|
| 16 |
-
}
|
| 17 |
-
|
| 18 |
-
func GetAllAccount() Repository[models.Account, []models.Account] {
|
| 19 |
-
repo := Construct[models.Account, []models.Account](
|
| 20 |
-
models.Account{},
|
| 21 |
-
)
|
| 22 |
-
repo.Transactions(
|
| 23 |
-
Find[models.Account, []models.Account],
|
| 24 |
-
)
|
| 25 |
-
return *repo
|
| 26 |
-
}
|
| 27 |
-
func GetAccountById(accountId uint) Repository[models.Account, models.Account] {
|
| 28 |
-
repo := Construct[models.Account, models.Account](
|
| 29 |
-
models.Account{Id: accountId},
|
| 30 |
-
)
|
| 31 |
-
repo.Transactions(
|
| 32 |
-
WhereGivenConstructor[models.Account, models.Account],
|
| 33 |
-
Find[models.Account, models.Account],
|
| 34 |
-
)
|
| 35 |
-
return *repo
|
| 36 |
-
}
|
| 37 |
-
|
| 38 |
-
func UpdateAccount(account models.Account) Repository[models.Account, models.Account] {
|
| 39 |
-
repo := Construct[models.Account, models.Account](
|
| 40 |
-
account,
|
| 41 |
-
)
|
| 42 |
-
repo.Transaction.Save(&repo.Constructor)
|
| 43 |
-
repo.Result = repo.Constructor
|
| 44 |
-
return *repo
|
| 45 |
-
}
|
| 46 |
-
|
| 47 |
-
func GetDetailAccountById(accountId uint) Repository[models.AccountDetails, models.AccountDetails] {
|
| 48 |
-
repo := Construct[models.AccountDetails, models.AccountDetails](
|
| 49 |
-
models.AccountDetails{AccountID: accountId},
|
| 50 |
-
)
|
| 51 |
-
|
| 52 |
-
// fmt.Println("Account ID:", repo.Constructor.AccountID)
|
| 53 |
-
repo.Transactions(
|
| 54 |
-
WhereGivenConstructor[models.AccountDetails, models.AccountDetails],
|
| 55 |
-
Find[models.AccountDetails, models.AccountDetails],
|
| 56 |
-
)
|
| 57 |
-
return *repo
|
| 58 |
-
}
|
| 59 |
-
|
| 60 |
-
func CreateAccount(account models.Account) Repository[models.Account, models.Account] {
|
| 61 |
-
repo := Construct[models.Account, models.Account](
|
| 62 |
-
account,
|
| 63 |
-
)
|
| 64 |
-
Create(repo)
|
| 65 |
-
return *repo
|
| 66 |
-
}
|
| 67 |
-
|
| 68 |
-
func CreateAccountDetails(accountDetails models.AccountDetails) Repository[models.AccountDetails, models.AccountDetails] {
|
| 69 |
-
repo := Construct[models.AccountDetails, models.AccountDetails](
|
| 70 |
-
accountDetails,
|
| 71 |
-
)
|
| 72 |
-
Create(repo)
|
| 73 |
-
return *repo
|
| 74 |
-
}
|
| 75 |
-
|
| 76 |
-
func UpdateAccountDetails(accountDetails models.AccountDetails) Repository[models.AccountDetails, models.AccountDetails] {
|
| 77 |
-
repo := Construct[models.AccountDetails, models.AccountDetails](
|
| 78 |
-
models.AccountDetails{AccountID: accountDetails.AccountID},
|
| 79 |
-
)
|
| 80 |
-
repo.Transaction.Where("account_id = ?", accountDetails.AccountID).First(&repo.Constructor)
|
| 81 |
-
accountDetails.ID = repo.Constructor.ID
|
| 82 |
-
// fmt.Println(repo.Constructor)
|
| 83 |
-
// fmt.Println(accountDetails)
|
| 84 |
-
repo.Transaction.Updates(accountDetails)
|
| 85 |
-
repo.Result = accountDetails
|
| 86 |
-
return *repo
|
| 87 |
-
}
|
|
|
|
| 1 |
+
package repositories
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"api.qobiltu.id/models"
|
| 5 |
+
)
|
| 6 |
+
|
| 7 |
+
func GetAccountbyEmail(email string) Repository[models.Account, models.Account] {
|
| 8 |
+
repo := Construct[models.Account, models.Account](
|
| 9 |
+
models.Account{Email: email},
|
| 10 |
+
)
|
| 11 |
+
repo.Transactions(
|
| 12 |
+
WhereGivenConstructor[models.Account, models.Account],
|
| 13 |
+
Find[models.Account, models.Account],
|
| 14 |
+
)
|
| 15 |
+
return *repo
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
func GetAllAccount() Repository[models.Account, []models.Account] {
|
| 19 |
+
repo := Construct[models.Account, []models.Account](
|
| 20 |
+
models.Account{},
|
| 21 |
+
)
|
| 22 |
+
repo.Transactions(
|
| 23 |
+
Find[models.Account, []models.Account],
|
| 24 |
+
)
|
| 25 |
+
return *repo
|
| 26 |
+
}
|
| 27 |
+
func GetAccountById(accountId uint) Repository[models.Account, models.Account] {
|
| 28 |
+
repo := Construct[models.Account, models.Account](
|
| 29 |
+
models.Account{Id: accountId},
|
| 30 |
+
)
|
| 31 |
+
repo.Transactions(
|
| 32 |
+
WhereGivenConstructor[models.Account, models.Account],
|
| 33 |
+
Find[models.Account, models.Account],
|
| 34 |
+
)
|
| 35 |
+
return *repo
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
func UpdateAccount(account models.Account) Repository[models.Account, models.Account] {
|
| 39 |
+
repo := Construct[models.Account, models.Account](
|
| 40 |
+
account,
|
| 41 |
+
)
|
| 42 |
+
repo.Transaction.Save(&repo.Constructor)
|
| 43 |
+
repo.Result = repo.Constructor
|
| 44 |
+
return *repo
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
func GetDetailAccountById(accountId uint) Repository[models.AccountDetails, models.AccountDetails] {
|
| 48 |
+
repo := Construct[models.AccountDetails, models.AccountDetails](
|
| 49 |
+
models.AccountDetails{AccountID: accountId},
|
| 50 |
+
)
|
| 51 |
+
|
| 52 |
+
// fmt.Println("Account ID:", repo.Constructor.AccountID)
|
| 53 |
+
repo.Transactions(
|
| 54 |
+
WhereGivenConstructor[models.AccountDetails, models.AccountDetails],
|
| 55 |
+
Find[models.AccountDetails, models.AccountDetails],
|
| 56 |
+
)
|
| 57 |
+
return *repo
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
func CreateAccount(account models.Account) Repository[models.Account, models.Account] {
|
| 61 |
+
repo := Construct[models.Account, models.Account](
|
| 62 |
+
account,
|
| 63 |
+
)
|
| 64 |
+
Create(repo)
|
| 65 |
+
return *repo
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
func CreateAccountDetails(accountDetails models.AccountDetails) Repository[models.AccountDetails, models.AccountDetails] {
|
| 69 |
+
repo := Construct[models.AccountDetails, models.AccountDetails](
|
| 70 |
+
accountDetails,
|
| 71 |
+
)
|
| 72 |
+
Create(repo)
|
| 73 |
+
return *repo
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
func UpdateAccountDetails(accountDetails models.AccountDetails) Repository[models.AccountDetails, models.AccountDetails] {
|
| 77 |
+
repo := Construct[models.AccountDetails, models.AccountDetails](
|
| 78 |
+
models.AccountDetails{AccountID: accountDetails.AccountID},
|
| 79 |
+
)
|
| 80 |
+
repo.Transaction.Where("account_id = ?", accountDetails.AccountID).First(&repo.Constructor)
|
| 81 |
+
accountDetails.ID = repo.Constructor.ID
|
| 82 |
+
// fmt.Println(repo.Constructor)
|
| 83 |
+
// fmt.Println(accountDetails)
|
| 84 |
+
repo.Transaction.Updates(accountDetails)
|
| 85 |
+
repo.Result = accountDetails
|
| 86 |
+
return *repo
|
| 87 |
+
}
|
space/space/space/space/services/external_authentication_service.go
CHANGED
|
@@ -1,81 +1,81 @@
|
|
| 1 |
-
package services
|
| 2 |
-
|
| 3 |
-
import (
|
| 4 |
-
"context"
|
| 5 |
-
"errors"
|
| 6 |
-
|
| 7 |
-
"api.qobiltu.id/models"
|
| 8 |
-
"api.qobiltu.id/repositories"
|
| 9 |
-
uuid "github.com/satori/go.uuid"
|
| 10 |
-
"google.golang.org/api/idtoken"
|
| 11 |
-
)
|
| 12 |
-
|
| 13 |
-
type GoogleAuthService struct {
|
| 14 |
-
Service[models.ExternalAuth, models.AuthenticatedUser]
|
| 15 |
-
}
|
| 16 |
-
|
| 17 |
-
func (s *GoogleAuthService) Authenticate(isAgree bool) {
|
| 18 |
-
GoogleAuth := repositories.GetExternalAccountByOauthId(s.Constructor.OauthID)
|
| 19 |
-
payload, errGoogleAuth := idtoken.Validate(context.Background(), s.Constructor.OauthID, "")
|
| 20 |
-
s.Error = errGoogleAuth
|
| 21 |
-
if errGoogleAuth != nil {
|
| 22 |
-
s.Exception.Unauthorized = true
|
| 23 |
-
s.Exception.Message = "Oauth Provider Failed Login (Google Authentication)"
|
| 24 |
-
return
|
| 25 |
-
}
|
| 26 |
-
email := payload.Claims["email"]
|
| 27 |
-
checkRegisteredEmail := repositories.GetAccountbyEmail(email.(string))
|
| 28 |
-
if !checkRegisteredEmail.NoRecord {
|
| 29 |
-
token, _ := GenerateToken(&checkRegisteredEmail.Result)
|
| 30 |
-
checkRegisteredEmail.Result.Password = "SECRET"
|
| 31 |
-
s.Result = models.AuthenticatedUser{
|
| 32 |
-
Account: checkRegisteredEmail.Result,
|
| 33 |
-
Token: token,
|
| 34 |
-
}
|
| 35 |
-
return
|
| 36 |
-
}
|
| 37 |
-
if GoogleAuth.NoRecord {
|
| 38 |
-
if !isAgree {
|
| 39 |
-
s.Exception.BadRequest = true
|
| 40 |
-
s.Exception.Message = "Please agree to the terms and conditions to create an account"
|
| 41 |
-
return
|
| 42 |
-
}
|
| 43 |
-
s.Constructor.UUID = uuid.NewV4()
|
| 44 |
-
s.Constructor.OauthProvider = "Google"
|
| 45 |
-
|
| 46 |
-
createAccount := repositories.CreateAccount(models.Account{
|
| 47 |
-
UUID: uuid.NewV4(),
|
| 48 |
-
Email: email.(string),
|
| 49 |
-
IsEmailVerified: true,
|
| 50 |
-
})
|
| 51 |
-
|
| 52 |
-
s.Constructor.AccountID = createAccount.Result.Id
|
| 53 |
-
createGoogleAuth := repositories.CreateExternalAuth(s.Constructor)
|
| 54 |
-
|
| 55 |
-
GoogleAuth.Result.AccountID = createGoogleAuth.Result.AccountID
|
| 56 |
-
userProfile := UserProfileService{}
|
| 57 |
-
userProfile.Constructor.AccountID = GoogleAuth.Result.AccountID
|
| 58 |
-
userProfile.Create()
|
| 59 |
-
if userProfile.Error != nil {
|
| 60 |
-
s.Error = userProfile.Error
|
| 61 |
-
return
|
| 62 |
-
}
|
| 63 |
-
s.Error = createGoogleAuth.RowsError
|
| 64 |
-
s.Error = errors.Join(s.Error, createAccount.RowsError)
|
| 65 |
-
}
|
| 66 |
-
|
| 67 |
-
accountData := repositories.GetAccountById(GoogleAuth.Result.AccountID)
|
| 68 |
-
token, err_tok := GenerateToken(&accountData.Result)
|
| 69 |
-
|
| 70 |
-
if err_tok != nil {
|
| 71 |
-
s.Error = errors.Join(s.Error, err_tok)
|
| 72 |
-
}
|
| 73 |
-
|
| 74 |
-
accountData.Result.Password = "SECRET"
|
| 75 |
-
s.Result = models.AuthenticatedUser{
|
| 76 |
-
Account: accountData.Result,
|
| 77 |
-
Token: token,
|
| 78 |
-
}
|
| 79 |
-
s.Error = accountData.RowsError
|
| 80 |
-
|
| 81 |
-
}
|
|
|
|
| 1 |
+
package services
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"context"
|
| 5 |
+
"errors"
|
| 6 |
+
|
| 7 |
+
"api.qobiltu.id/models"
|
| 8 |
+
"api.qobiltu.id/repositories"
|
| 9 |
+
uuid "github.com/satori/go.uuid"
|
| 10 |
+
"google.golang.org/api/idtoken"
|
| 11 |
+
)
|
| 12 |
+
|
| 13 |
+
type GoogleAuthService struct {
|
| 14 |
+
Service[models.ExternalAuth, models.AuthenticatedUser]
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
func (s *GoogleAuthService) Authenticate(isAgree bool) {
|
| 18 |
+
GoogleAuth := repositories.GetExternalAccountByOauthId(s.Constructor.OauthID)
|
| 19 |
+
payload, errGoogleAuth := idtoken.Validate(context.Background(), s.Constructor.OauthID, "")
|
| 20 |
+
s.Error = errGoogleAuth
|
| 21 |
+
if errGoogleAuth != nil {
|
| 22 |
+
s.Exception.Unauthorized = true
|
| 23 |
+
s.Exception.Message = "Oauth Provider Failed Login (Google Authentication)"
|
| 24 |
+
return
|
| 25 |
+
}
|
| 26 |
+
email := payload.Claims["email"]
|
| 27 |
+
checkRegisteredEmail := repositories.GetAccountbyEmail(email.(string))
|
| 28 |
+
if !checkRegisteredEmail.NoRecord {
|
| 29 |
+
token, _ := GenerateToken(&checkRegisteredEmail.Result)
|
| 30 |
+
checkRegisteredEmail.Result.Password = "SECRET"
|
| 31 |
+
s.Result = models.AuthenticatedUser{
|
| 32 |
+
Account: checkRegisteredEmail.Result,
|
| 33 |
+
Token: token,
|
| 34 |
+
}
|
| 35 |
+
return
|
| 36 |
+
}
|
| 37 |
+
if GoogleAuth.NoRecord {
|
| 38 |
+
if !isAgree {
|
| 39 |
+
s.Exception.BadRequest = true
|
| 40 |
+
s.Exception.Message = "Please agree to the terms and conditions to create an account"
|
| 41 |
+
return
|
| 42 |
+
}
|
| 43 |
+
s.Constructor.UUID = uuid.NewV4()
|
| 44 |
+
s.Constructor.OauthProvider = "Google"
|
| 45 |
+
|
| 46 |
+
createAccount := repositories.CreateAccount(models.Account{
|
| 47 |
+
UUID: uuid.NewV4(),
|
| 48 |
+
Email: email.(string),
|
| 49 |
+
IsEmailVerified: true,
|
| 50 |
+
})
|
| 51 |
+
|
| 52 |
+
s.Constructor.AccountID = createAccount.Result.Id
|
| 53 |
+
createGoogleAuth := repositories.CreateExternalAuth(s.Constructor)
|
| 54 |
+
|
| 55 |
+
GoogleAuth.Result.AccountID = createGoogleAuth.Result.AccountID
|
| 56 |
+
userProfile := UserProfileService{}
|
| 57 |
+
userProfile.Constructor.AccountID = GoogleAuth.Result.AccountID
|
| 58 |
+
userProfile.Create()
|
| 59 |
+
if userProfile.Error != nil {
|
| 60 |
+
s.Error = userProfile.Error
|
| 61 |
+
return
|
| 62 |
+
}
|
| 63 |
+
s.Error = createGoogleAuth.RowsError
|
| 64 |
+
s.Error = errors.Join(s.Error, createAccount.RowsError)
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
accountData := repositories.GetAccountById(GoogleAuth.Result.AccountID)
|
| 68 |
+
token, err_tok := GenerateToken(&accountData.Result)
|
| 69 |
+
|
| 70 |
+
if err_tok != nil {
|
| 71 |
+
s.Error = errors.Join(s.Error, err_tok)
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
accountData.Result.Password = "SECRET"
|
| 75 |
+
s.Result = models.AuthenticatedUser{
|
| 76 |
+
Account: accountData.Result,
|
| 77 |
+
Token: token,
|
| 78 |
+
}
|
| 79 |
+
s.Error = accountData.RowsError
|
| 80 |
+
|
| 81 |
+
}
|
space/space/space/space/services/user_profile_service.go
CHANGED
|
@@ -53,12 +53,12 @@ func (s *UserProfileService) Create() {
|
|
| 53 |
return
|
| 54 |
}
|
| 55 |
s.Result = models.UserProfileResponse{
|
| 56 |
-
Account: repositories.GetAccountById(s.Constructor.AccountID).Result,
|
| 57 |
Details: userProfile.Result,
|
| 58 |
}
|
| 59 |
}
|
| 60 |
func (s *UserProfileService) Retrieve() {
|
| 61 |
-
userProfile := repositories.GetDetailAccountById(s.Constructor.AccountID)
|
| 62 |
s.Error = userProfile.RowsError
|
| 63 |
if userProfile.NoRecord {
|
| 64 |
s.Exception.DataNotFound = true
|
|
@@ -66,7 +66,7 @@ func (s *UserProfileService) Retrieve() {
|
|
| 66 |
return
|
| 67 |
}
|
| 68 |
s.Result = models.UserProfileResponse{
|
| 69 |
-
Account: repositories.GetAccountById(s.Constructor.AccountID).Result,
|
| 70 |
Details: userProfile.Result,
|
| 71 |
}
|
| 72 |
s.Result.Account.Password = "SECRET"
|
|
@@ -96,7 +96,7 @@ func (s *UserProfileService) Update() {
|
|
| 96 |
s.Exception.Message = "There is no account with given credentials!"
|
| 97 |
return
|
| 98 |
}
|
| 99 |
-
account := repositories.GetAccountById(s.Constructor.AccountID)
|
| 100 |
account.Result.IsDetailCompleted = (userProfile.Result.InitialName != "" &&
|
| 101 |
userProfile.Result.FullName != nil &&
|
| 102 |
userProfile.Result.DateOfBirth != nil &&
|
|
|
|
| 53 |
return
|
| 54 |
}
|
| 55 |
s.Result = models.UserProfileResponse{
|
| 56 |
+
Account: repositories.GetAccountById(uint(s.Constructor.AccountID)).Result,
|
| 57 |
Details: userProfile.Result,
|
| 58 |
}
|
| 59 |
}
|
| 60 |
func (s *UserProfileService) Retrieve() {
|
| 61 |
+
userProfile := repositories.GetDetailAccountById(uint(s.Constructor.AccountID))
|
| 62 |
s.Error = userProfile.RowsError
|
| 63 |
if userProfile.NoRecord {
|
| 64 |
s.Exception.DataNotFound = true
|
|
|
|
| 66 |
return
|
| 67 |
}
|
| 68 |
s.Result = models.UserProfileResponse{
|
| 69 |
+
Account: repositories.GetAccountById(uint(s.Constructor.AccountID)).Result,
|
| 70 |
Details: userProfile.Result,
|
| 71 |
}
|
| 72 |
s.Result.Account.Password = "SECRET"
|
|
|
|
| 96 |
s.Exception.Message = "There is no account with given credentials!"
|
| 97 |
return
|
| 98 |
}
|
| 99 |
+
account := repositories.GetAccountById(uint(s.Constructor.AccountID))
|
| 100 |
account.Result.IsDetailCompleted = (userProfile.Result.InitialName != "" &&
|
| 101 |
userProfile.Result.FullName != nil &&
|
| 102 |
userProfile.Result.DateOfBirth != nil &&
|
space/space/space/space/space/config/database_connection_config.go
CHANGED
|
@@ -70,6 +70,10 @@ func AutoMigrateAll(db *gorm.DB) {
|
|
| 70 |
&models.Question{},
|
| 71 |
&models.Answer{},
|
| 72 |
&models.UserAnswer{},
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
)
|
| 74 |
|
| 75 |
if err != nil {
|
|
|
|
| 70 |
&models.Question{},
|
| 71 |
&models.Answer{},
|
| 72 |
&models.UserAnswer{},
|
| 73 |
+
&models.PersonalityAndPreferenceCV{},
|
| 74 |
+
&models.FamilyMemberCV{},
|
| 75 |
+
&models.PhysicalAndHealthCV{},
|
| 76 |
+
&models.WorshipAndReligiousUnderstandingCV{},
|
| 77 |
)
|
| 78 |
|
| 79 |
if err != nil {
|
space/space/space/space/space/controller/cv/cv_controller.go
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package cv_controller
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"api.qobiltu.id/middleware"
|
| 5 |
+
"api.qobiltu.id/models"
|
| 6 |
+
"api.qobiltu.id/response"
|
| 7 |
+
"api.qobiltu.id/services"
|
| 8 |
+
"github.com/gin-gonic/gin"
|
| 9 |
+
"net/http"
|
| 10 |
+
"strconv"
|
| 11 |
+
)
|
| 12 |
+
|
| 13 |
+
type CVController interface {
|
| 14 |
+
SaveAccountDetails(ctx *gin.Context)
|
| 15 |
+
GetAccountDetails(ctx *gin.Context)
|
| 16 |
+
|
| 17 |
+
SavePersonalityAndPreference(ctx *gin.Context)
|
| 18 |
+
GetPersonalityAndPreference(ctx *gin.Context)
|
| 19 |
+
|
| 20 |
+
CreateFamilyMember(ctx *gin.Context)
|
| 21 |
+
UpdateFamilyMember(ctx *gin.Context)
|
| 22 |
+
ListFamilyMember(ctx *gin.Context)
|
| 23 |
+
GetFamilyMember(ctx *gin.Context)
|
| 24 |
+
DeleteFamilyMember(ctx *gin.Context)
|
| 25 |
+
|
| 26 |
+
SavePhysicalAndHealth(ctx *gin.Context)
|
| 27 |
+
GetPhysicalAndHealth(ctx *gin.Context)
|
| 28 |
+
|
| 29 |
+
SaveWorshipAndReligiousUnderstanding(ctx *gin.Context)
|
| 30 |
+
GetWorshipAndReligiousUnderstanding(ctx *gin.Context)
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
type cvController struct {
|
| 34 |
+
cvService services.CVService
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
func NewCVController(cvService services.CVService) CVController {
|
| 38 |
+
return &cvController{
|
| 39 |
+
cvService: cvService,
|
| 40 |
+
}
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
// --- Account Details ---
|
| 44 |
+
func (c *cvController) SaveAccountDetails(ctx *gin.Context) {
|
| 45 |
+
var req models.AccountDetailsRequest
|
| 46 |
+
if err := ctx.ShouldBindJSON(&req); err != nil {
|
| 47 |
+
response.HandleError(ctx, err)
|
| 48 |
+
return
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
accountData := middleware.GetAccountData(ctx)
|
| 52 |
+
req.AccountID = int64(accountData.UserID)
|
| 53 |
+
|
| 54 |
+
res, err := c.cvService.SaveAccountDetails(ctx, &req)
|
| 55 |
+
if err != nil {
|
| 56 |
+
response.HandleError(ctx, err)
|
| 57 |
+
return
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
response.HandleSuccess(ctx, http.StatusOK, "Account details saved", res, nil)
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
func (c *cvController) GetAccountDetails(ctx *gin.Context) {
|
| 64 |
+
accountData := middleware.GetAccountData(ctx)
|
| 65 |
+
accountID := int64(accountData.UserID)
|
| 66 |
+
|
| 67 |
+
res, err := c.cvService.GetAccountDetails(ctx, accountID)
|
| 68 |
+
if err != nil {
|
| 69 |
+
response.HandleError(ctx, err)
|
| 70 |
+
return
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
response.HandleSuccess(ctx, http.StatusOK, "Get account details success", res, nil)
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
// --- Personality & Preference ---
|
| 77 |
+
|
| 78 |
+
func (c *cvController) SavePersonalityAndPreference(ctx *gin.Context) {
|
| 79 |
+
var req models.PersonalityAndPreferenceCVRequest
|
| 80 |
+
if err := ctx.ShouldBindJSON(&req); err != nil {
|
| 81 |
+
response.HandleError(ctx, err)
|
| 82 |
+
return
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
accountData := middleware.GetAccountData(ctx)
|
| 86 |
+
req.AccountID = int64(accountData.UserID)
|
| 87 |
+
|
| 88 |
+
res, err := c.cvService.SavePersonalityAndPreference(ctx, &req)
|
| 89 |
+
if err != nil {
|
| 90 |
+
response.HandleError(ctx, err)
|
| 91 |
+
return
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
response.HandleSuccess(ctx, http.StatusOK, "Personality and Preference saved", res, nil)
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
func (c *cvController) GetPersonalityAndPreference(ctx *gin.Context) {
|
| 98 |
+
accountData := middleware.GetAccountData(ctx)
|
| 99 |
+
accountID := int64(accountData.UserID)
|
| 100 |
+
|
| 101 |
+
res, err := c.cvService.GetPersonalityAndPreference(ctx, accountID)
|
| 102 |
+
if err != nil {
|
| 103 |
+
response.HandleError(ctx, err)
|
| 104 |
+
return
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
response.HandleSuccess(ctx, http.StatusOK, "Get Personality and Preference success", res, nil)
|
| 108 |
+
}
|
| 109 |
+
|
| 110 |
+
// --- Family Member ---
|
| 111 |
+
|
| 112 |
+
func (c *cvController) CreateFamilyMember(ctx *gin.Context) {
|
| 113 |
+
var req models.FamilyMemberRequest
|
| 114 |
+
if err := ctx.ShouldBindJSON(&req); err != nil {
|
| 115 |
+
response.HandleError(ctx, err)
|
| 116 |
+
return
|
| 117 |
+
}
|
| 118 |
+
|
| 119 |
+
accountData := middleware.GetAccountData(ctx)
|
| 120 |
+
req.AccountID = int64(accountData.UserID)
|
| 121 |
+
|
| 122 |
+
res, err := c.cvService.CreateFamilyMember(ctx, &req)
|
| 123 |
+
if err != nil {
|
| 124 |
+
response.HandleError(ctx, err)
|
| 125 |
+
return
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
response.HandleSuccess(ctx, http.StatusOK, "Family member saved", res, nil)
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
func (c *cvController) UpdateFamilyMember(ctx *gin.Context) {
|
| 132 |
+
idStr := ctx.Param("id")
|
| 133 |
+
id, err := strconv.ParseInt(idStr, 10, 64)
|
| 134 |
+
if err != nil {
|
| 135 |
+
response.HandleError(ctx, err)
|
| 136 |
+
return
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
+
var req models.FamilyMemberRequest
|
| 140 |
+
if err := ctx.ShouldBindJSON(&req); err != nil {
|
| 141 |
+
response.HandleError(ctx, err)
|
| 142 |
+
return
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
res, err := c.cvService.UpdateFamilyMember(ctx, id, &req)
|
| 146 |
+
if err != nil {
|
| 147 |
+
response.HandleError(ctx, err)
|
| 148 |
+
return
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
response.HandleSuccess(ctx, http.StatusOK, "Family member updated", res, nil)
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
func (c *cvController) ListFamilyMember(ctx *gin.Context) {
|
| 155 |
+
accountData := middleware.GetAccountData(ctx)
|
| 156 |
+
accountID := int64(accountData.UserID)
|
| 157 |
+
|
| 158 |
+
list, err := c.cvService.ListFamilyMember(ctx, accountID)
|
| 159 |
+
if err != nil {
|
| 160 |
+
response.HandleError(ctx, err)
|
| 161 |
+
return
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
response.HandleSuccess(ctx, http.StatusOK, "List family members", list, nil)
|
| 165 |
+
}
|
| 166 |
+
|
| 167 |
+
func (c *cvController) GetFamilyMember(ctx *gin.Context) {
|
| 168 |
+
idStr := ctx.Param("id")
|
| 169 |
+
id, err := strconv.ParseInt(idStr, 10, 64)
|
| 170 |
+
if err != nil {
|
| 171 |
+
response.HandleError(ctx, err)
|
| 172 |
+
return
|
| 173 |
+
}
|
| 174 |
+
|
| 175 |
+
res, err := c.cvService.GetFamilyMember(ctx, id)
|
| 176 |
+
if err != nil {
|
| 177 |
+
response.HandleError(ctx, err)
|
| 178 |
+
return
|
| 179 |
+
}
|
| 180 |
+
|
| 181 |
+
response.HandleSuccess(ctx, http.StatusOK, "Get family member success", res, nil)
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
func (c *cvController) DeleteFamilyMember(ctx *gin.Context) {
|
| 185 |
+
idStr := ctx.Param("id")
|
| 186 |
+
id, err := strconv.ParseInt(idStr, 10, 64)
|
| 187 |
+
if err != nil {
|
| 188 |
+
response.HandleError(ctx, err)
|
| 189 |
+
return
|
| 190 |
+
}
|
| 191 |
+
|
| 192 |
+
err = c.cvService.DeleteFamilyMember(ctx, id)
|
| 193 |
+
if err != nil {
|
| 194 |
+
response.HandleError(ctx, err)
|
| 195 |
+
return
|
| 196 |
+
}
|
| 197 |
+
|
| 198 |
+
response.HandleSuccess(ctx, http.StatusOK, "Family member deleted", nil, nil)
|
| 199 |
+
}
|
| 200 |
+
|
| 201 |
+
// --- Physical and Health ---
|
| 202 |
+
|
| 203 |
+
func (c *cvController) SavePhysicalAndHealth(ctx *gin.Context) {
|
| 204 |
+
var req models.PhysicalAndHealthRequest
|
| 205 |
+
if err := ctx.ShouldBindJSON(&req); err != nil {
|
| 206 |
+
response.HandleError(ctx, err)
|
| 207 |
+
return
|
| 208 |
+
}
|
| 209 |
+
|
| 210 |
+
accountData := middleware.GetAccountData(ctx)
|
| 211 |
+
req.AccountID = int64(accountData.UserID)
|
| 212 |
+
|
| 213 |
+
res, err := c.cvService.SavePhysicalAndHealth(ctx, &req)
|
| 214 |
+
if err != nil {
|
| 215 |
+
response.HandleError(ctx, err)
|
| 216 |
+
return
|
| 217 |
+
}
|
| 218 |
+
|
| 219 |
+
response.HandleSuccess(ctx, http.StatusOK, "Physical and health saved", res, nil)
|
| 220 |
+
}
|
| 221 |
+
|
| 222 |
+
func (c *cvController) GetPhysicalAndHealth(ctx *gin.Context) {
|
| 223 |
+
accountData := middleware.GetAccountData(ctx)
|
| 224 |
+
accountID := int64(accountData.UserID)
|
| 225 |
+
|
| 226 |
+
res, err := c.cvService.GetPhysicalAndHealth(ctx, accountID)
|
| 227 |
+
if err != nil {
|
| 228 |
+
response.HandleError(ctx, err)
|
| 229 |
+
return
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
response.HandleSuccess(ctx, http.StatusOK, "Get physical and health success", res, nil)
|
| 233 |
+
}
|
| 234 |
+
|
| 235 |
+
// --- Worship and Religious Understanding ---
|
| 236 |
+
|
| 237 |
+
func (c *cvController) SaveWorshipAndReligiousUnderstanding(ctx *gin.Context) {
|
| 238 |
+
var req models.WorshipAndReligiousUnderstandingRequest
|
| 239 |
+
if err := ctx.ShouldBindJSON(&req); err != nil {
|
| 240 |
+
response.HandleError(ctx, err)
|
| 241 |
+
return
|
| 242 |
+
}
|
| 243 |
+
|
| 244 |
+
accountData := middleware.GetAccountData(ctx)
|
| 245 |
+
req.AccountID = int64(accountData.UserID)
|
| 246 |
+
|
| 247 |
+
res, err := c.cvService.SaveWorshipAndReligiousUnderstanding(ctx, &req)
|
| 248 |
+
if err != nil {
|
| 249 |
+
response.HandleError(ctx, err)
|
| 250 |
+
return
|
| 251 |
+
}
|
| 252 |
+
|
| 253 |
+
response.HandleSuccess(ctx, http.StatusOK, "Worship and religious understanding saved", res, nil)
|
| 254 |
+
}
|
| 255 |
+
|
| 256 |
+
func (c *cvController) GetWorshipAndReligiousUnderstanding(ctx *gin.Context) {
|
| 257 |
+
accountData := middleware.GetAccountData(ctx)
|
| 258 |
+
accountID := int64(accountData.UserID)
|
| 259 |
+
|
| 260 |
+
res, err := c.cvService.GetWorshipAndReligiousUnderstanding(ctx, accountID)
|
| 261 |
+
if err != nil {
|
| 262 |
+
response.HandleError(ctx, err)
|
| 263 |
+
return
|
| 264 |
+
}
|
| 265 |
+
|
| 266 |
+
response.HandleSuccess(ctx, http.StatusOK, "Get worship and religious understanding success", res, nil)
|
| 267 |
+
}
|
space/space/space/space/space/main.go
CHANGED
|
@@ -2,6 +2,7 @@ package main
|
|
| 2 |
|
| 3 |
import (
|
| 4 |
"api.qobiltu.id/config"
|
|
|
|
| 5 |
"api.qobiltu.id/controller/health_check"
|
| 6 |
"api.qobiltu.id/mail"
|
| 7 |
"api.qobiltu.id/repositories"
|
|
@@ -46,13 +47,20 @@ func main() {
|
|
| 46 |
healthCheckService := services.NewHealthCheckService(healthCheckRepository)
|
| 47 |
healthCheckController := health_check_controller.NewHealthCheckController(healthCheckService)
|
| 48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
// start task processor
|
| 50 |
err = taskProcessor.Start()
|
| 51 |
utils.FatalIfErr("failed to start task processor", err)
|
| 52 |
slog.Info("Task processor started")
|
| 53 |
|
| 54 |
// create server
|
| 55 |
-
s, err := router.NewServer(
|
|
|
|
|
|
|
|
|
|
| 56 |
utils.FatalIfErr("failed to create server", err)
|
| 57 |
|
| 58 |
// run server
|
|
|
|
| 2 |
|
| 3 |
import (
|
| 4 |
"api.qobiltu.id/config"
|
| 5 |
+
cv_controller "api.qobiltu.id/controller/cv"
|
| 6 |
"api.qobiltu.id/controller/health_check"
|
| 7 |
"api.qobiltu.id/mail"
|
| 8 |
"api.qobiltu.id/repositories"
|
|
|
|
| 47 |
healthCheckService := services.NewHealthCheckService(healthCheckRepository)
|
| 48 |
healthCheckController := health_check_controller.NewHealthCheckController(healthCheckService)
|
| 49 |
|
| 50 |
+
cvRepository := repositories.NewCVRepository(config.DB)
|
| 51 |
+
cvService := services.NewCVService(cvRepository)
|
| 52 |
+
cvController := cv_controller.NewCVController(cvService)
|
| 53 |
+
|
| 54 |
// start task processor
|
| 55 |
err = taskProcessor.Start()
|
| 56 |
utils.FatalIfErr("failed to start task processor", err)
|
| 57 |
slog.Info("Task processor started")
|
| 58 |
|
| 59 |
// create server
|
| 60 |
+
s, err := router.NewServer(
|
| 61 |
+
healthCheckController,
|
| 62 |
+
cvController,
|
| 63 |
+
)
|
| 64 |
utils.FatalIfErr("failed to create server", err)
|
| 65 |
|
| 66 |
// run server
|
space/space/space/space/space/middleware/authentication_middleware.go
CHANGED
|
@@ -33,5 +33,12 @@ func AuthUser(c *gin.Context) {
|
|
| 33 |
c.Abort()
|
| 34 |
return
|
| 35 |
}
|
|
|
|
| 36 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
}
|
|
|
|
| 33 |
c.Abort()
|
| 34 |
return
|
| 35 |
}
|
| 36 |
+
}
|
| 37 |
|
| 38 |
+
func GetAccountData(c *gin.Context) models.AccountData {
|
| 39 |
+
cParam, _ := c.Get("accountData")
|
| 40 |
+
if cParam != nil {
|
| 41 |
+
return cParam.(models.AccountData)
|
| 42 |
+
}
|
| 43 |
+
return models.AccountData{}
|
| 44 |
}
|
space/space/space/space/space/models/database_orm_model.go
CHANGED
|
@@ -18,19 +18,21 @@ type Account struct {
|
|
| 18 |
}
|
| 19 |
|
| 20 |
type AccountDetails struct {
|
| 21 |
-
ID uint64 `gorm:"primaryKey" json:"id"`
|
| 22 |
-
AccountID uint `json:"account_id"`
|
| 23 |
-
InitialName string `json:"initial_name"`
|
| 24 |
-
FullName *string `json:"full_name"`
|
| 25 |
-
DateOfBirth *time.Time `json:"date_of_birth"`
|
| 26 |
-
PlaceOfBirth *string `json:"place_of_birth"`
|
| 27 |
-
Domicile *string `json:"domicile"`
|
| 28 |
-
LastJob *string `json:"last_job"`
|
| 29 |
-
Gender *string `json:"gender"`
|
| 30 |
-
LastEducation *string `json:"last_education"`
|
| 31 |
-
MaritalStatus *string `json:"marital_status"`
|
| 32 |
-
Avatar *string `json:"avatar"`
|
| 33 |
-
PhoneNumber *string `json:"phone_number"`
|
|
|
|
|
|
|
| 34 |
}
|
| 35 |
|
| 36 |
type EmailVerification struct {
|
|
@@ -184,24 +186,107 @@ type QuizResult struct {
|
|
| 184 |
AverageScore float64 `gorm:"column:average_score" json:"average_score"`
|
| 185 |
}
|
| 186 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 187 |
// Gorm table name settings
|
| 188 |
-
func (Account) TableName() string
|
| 189 |
-
func (AccountDetails) TableName() string
|
| 190 |
-
func (EmailVerification) TableName() string
|
| 191 |
-
func (ExternalAuth) TableName() string
|
| 192 |
-
func (FCM) TableName() string
|
| 193 |
-
func (ForgotPassword) TableName() string
|
| 194 |
-
func (Academy) TableName() string
|
| 195 |
-
func (AcademyMaterial) TableName() string
|
| 196 |
-
func (AcademyContent) TableName() string
|
| 197 |
-
func (AcademyMaterialProgress) TableName() string
|
| 198 |
-
func (AcademyContentProgress) TableName() string
|
| 199 |
-
func (RegionProvince) TableName() string
|
| 200 |
-
func (RegionCity) TableName() string
|
| 201 |
-
func (Answer) TableName() string
|
| 202 |
-
func (Question) TableName() string
|
| 203 |
-
func (Quiz) TableName() string
|
| 204 |
-
func (QuizAttempt) TableName() string
|
| 205 |
-
func (UserAnswer) TableName() string
|
| 206 |
-
func (OptionCategory) TableName() string
|
| 207 |
-
func (OptionValues) TableName() string
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
}
|
| 19 |
|
| 20 |
type AccountDetails struct {
|
| 21 |
+
ID uint64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
|
| 22 |
+
AccountID uint `gorm:"column:account_id;not null;unique" json:"account_id"`
|
| 23 |
+
InitialName string `gorm:"column:initial_name;not null" json:"initial_name"`
|
| 24 |
+
FullName *string `gorm:"column:full_name" json:"full_name"`
|
| 25 |
+
DateOfBirth *time.Time `gorm:"column:date_of_birth" json:"date_of_birth"`
|
| 26 |
+
PlaceOfBirth *string `gorm:"column:place_of_birth" json:"place_of_birth"`
|
| 27 |
+
Domicile *string `gorm:"column:domicile" json:"domicile"`
|
| 28 |
+
LastJob *string `gorm:"column:last_job" json:"last_job"`
|
| 29 |
+
Gender *string `gorm:"column:gender" json:"gender"`
|
| 30 |
+
LastEducation *string `gorm:"column:last_education" json:"last_education"`
|
| 31 |
+
MaritalStatus *string `gorm:"column:marital_status" json:"marital_status"`
|
| 32 |
+
Avatar *string `gorm:"column:avatar" json:"avatar"`
|
| 33 |
+
PhoneNumber *string `gorm:"column:phone_number" json:"phone_number"`
|
| 34 |
+
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"created_at"`
|
| 35 |
+
UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime" json:"updated_at"`
|
| 36 |
}
|
| 37 |
|
| 38 |
type EmailVerification struct {
|
|
|
|
| 186 |
AverageScore float64 `gorm:"column:average_score" json:"average_score"`
|
| 187 |
}
|
| 188 |
|
| 189 |
+
type (
|
| 190 |
+
PersonalityAndPreferenceCV struct {
|
| 191 |
+
ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
|
| 192 |
+
AccountID int64 `gorm:"column:account_id;not null;unique" json:"account_id"`
|
| 193 |
+
Account *Account `gorm:"foreignKey:AccountID;constraint:OnDelete:CASCADE" json:"account,omitempty"`
|
| 194 |
+
PositiveTraits *string `gorm:"column:positive_traits" json:"positive_traits"` // sifat positif
|
| 195 |
+
NegativeTraits *string `gorm:"column:negative_traits" json:"negative_traits"` // sifat negatif
|
| 196 |
+
Hobbies *string `gorm:"column:hobbies" json:"hobbies"` // hobi
|
| 197 |
+
LifeGoals *string `gorm:"column:life_goals" json:"life_goals"` // target hidup
|
| 198 |
+
DailyActivities *string `gorm:"column:daily_activities" json:"daily_activities"` // kegiatan sehari-hari
|
| 199 |
+
LeisureActivities *string `gorm:"column:leisure_activities" json:"leisure_activities"` // kegiatan waktu luang
|
| 200 |
+
Likes *string `gorm:"column:likes" json:"likes"` // hal yang disukai
|
| 201 |
+
Dislikes *string `gorm:"column:dislikes" json:"dislikes"` // hal yang tidak disukai
|
| 202 |
+
StressHandling *string `gorm:"column:stress_handling" json:"stress_handling"` // cara mengatasi stres
|
| 203 |
+
AngerTriggers *string `gorm:"column:anger_triggers" json:"anger_triggers"` // pemicu amarah
|
| 204 |
+
FavoriteFoodAndDrinks *string `gorm:"column:favorite_food_and_drinks" json:"favorite_food_and_drinks"` // makanan dan minuman favorit
|
| 205 |
+
CanCook *bool `gorm:"column:can_cook" json:"can_cook"` // bisa memasak
|
| 206 |
+
TypesOfDishesCooked *string `gorm:"column:types_of_dishes_cooked" json:"types_of_dishes_cooked"` // jenis masakan yang bisa dimasak
|
| 207 |
+
MonthlyExpenses *string `gorm:"column:monthly_expenses" json:"monthly_expenses"` // pengeluaran per bulan
|
| 208 |
+
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"created_at"`
|
| 209 |
+
UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime" json:"updated_at"`
|
| 210 |
+
}
|
| 211 |
+
|
| 212 |
+
FamilyMemberCV struct {
|
| 213 |
+
ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
|
| 214 |
+
AccountID int64 `gorm:"column:account_id;not null" json:"account_id"`
|
| 215 |
+
Account *Account `gorm:"foreignKey:AccountID;constraint:OnDelete:CASCADE" json:"account,omitempty"`
|
| 216 |
+
Role *string `gorm:"column:role" json:"role"` // Peran dalam keluarga
|
| 217 |
+
Status *string `gorm:"column:status" json:"status"` // Status (Hidup, Wafat)
|
| 218 |
+
Religion *string `gorm:"column:religion" json:"religion"` // Agama
|
| 219 |
+
Job *string `gorm:"column:job" json:"job"` // Pekerjaan
|
| 220 |
+
LastEducation *string `gorm:"column:last_education" json:"last_education"` // Pendidikan terakhir
|
| 221 |
+
Age *int `gorm:"column:age" json:"age"` // Usia
|
| 222 |
+
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"created_at"`
|
| 223 |
+
UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime" json:"updated_at"`
|
| 224 |
+
}
|
| 225 |
+
|
| 226 |
+
PhysicalAndHealthCV struct {
|
| 227 |
+
ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
|
| 228 |
+
AccountID int64 `gorm:"column:account_id;not null;unique" json:"account_id"`
|
| 229 |
+
Account *Account `gorm:"foreignKey:AccountID;constraint:OnDelete:CASCADE" json:"account,omitempty"`
|
| 230 |
+
HeightInCm *int `gorm:"column:height_cm" json:"height_cm"` // Tinggi badan dalam satuan sentimeter
|
| 231 |
+
WeightInKg *int `gorm:"column:weight_kg" json:"weight_kg"` // Berat badan dalam satuan kilogram
|
| 232 |
+
BodyShape *string `gorm:"column:body_shape" json:"body_shape"` // Bentuk tubuh
|
| 233 |
+
SkinColor *string `gorm:"column:skin_color" json:"skin_color"` // Warna kulit
|
| 234 |
+
HairType *string `gorm:"column:hair_type" json:"hair_type"` // Tipe rambut
|
| 235 |
+
MedicalHistory *string `gorm:"column:medical_history" json:"medical_history"` // Riwayat penyakit
|
| 236 |
+
PhysicalDisorder *string `gorm:"column:physical_disorder" json:"physical_disorder"` // Cacat fisik
|
| 237 |
+
PhysicalTraits *string `gorm:"column:physical_traits" json:"physical_traits"` // Ciri khas fisik
|
| 238 |
+
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"created_at"` // Waktu data dibuat
|
| 239 |
+
UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime" json:"updated_at"` // Waktu data terakhir diperbarui
|
| 240 |
+
}
|
| 241 |
+
|
| 242 |
+
WorshipAndReligiousUnderstandingCV struct {
|
| 243 |
+
ID int64 `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
|
| 244 |
+
AccountID int64 `gorm:"column:account_id;not null;unique" json:"account_id"`
|
| 245 |
+
Account *Account `gorm:"foreignKey:AccountID;constraint:OnDelete:CASCADE" json:"account,omitempty"`
|
| 246 |
+
ObligatoryPrayer *string `gorm:"column:obligatory_prayer" json:"obligatory_prayer"` // sholat_wajib_5_waktu
|
| 247 |
+
CongregationalPrayer *string `gorm:"column:congregational_prayer" json:"congregational_prayer"` // sholat_berjamaah_di_masjid
|
| 248 |
+
TahajjudPrayer *string `gorm:"column:tahajjud_prayer" json:"tahajjud_prayer"` // sholat_tahajud
|
| 249 |
+
DhuhaPrayer *string `gorm:"column:dhuha_prayer" json:"dhuha_prayer"` // sholat_dhuha
|
| 250 |
+
QuranMemorization *string `gorm:"column:quran_memorization" json:"quran_memorization"` // hafalan_alquran
|
| 251 |
+
QuranReadingAbility *string `gorm:"column:quran_reading_ability" json:"quran_reading_ability"` // kemampuan_baca_alquran
|
| 252 |
+
DaudFasting *string `gorm:"column:daud_fasting" json:"daud_fasting"` // puasa_daud
|
| 253 |
+
AyyamulBidhFasting *string `gorm:"column:ayyamul_bidh_fasting" json:"ayyamul_bidh_fasting"` // puasa_ayyamul_bidh
|
| 254 |
+
HajjOrUmrah *string `gorm:"column:hajj_or_umrah" json:"hajj_or_umrah"` // ibadah_haji_umroh
|
| 255 |
+
ListeningToMusic *string `gorm:"column:listening_to_music" json:"listening_to_music"` // mendengarkan_musik
|
| 256 |
+
OpinionOnIkhtilat *string `gorm:"column:opinion_on_ikhtilat" json:"opinion_on_ikhtilat"` // pendapat_ikhtilat
|
| 257 |
+
OpinionOnTouchingNonMahram *string `gorm:"column:opinion_on_touching_non_mahram" json:"opinion_on_touching_non_mahram"` // pendapat_menyentuh_non_mahram
|
| 258 |
+
OpinionOnVeil *string `gorm:"column:opinion_on_veil" json:"opinion_on_veil"` // pendapat_tentang_cadar
|
| 259 |
+
WeeklyReligiousStudies *string `gorm:"column:weekly_religious_studies" json:"weekly_religious_studies"` // kajian_yang_diikuti_dalam_sepekan
|
| 260 |
+
FollowedUstadz *string `gorm:"column:followed_ustadz" json:"followed_ustadz"` // ustadz_yang_diikuti
|
| 261 |
+
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime" json:"created_at"`
|
| 262 |
+
UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime" json:"updated_at"`
|
| 263 |
+
}
|
| 264 |
+
)
|
| 265 |
+
|
| 266 |
// Gorm table name settings
|
| 267 |
+
func (Account) TableName() string { return "account" }
|
| 268 |
+
func (AccountDetails) TableName() string { return "account_details" }
|
| 269 |
+
func (EmailVerification) TableName() string { return "email_verifications" }
|
| 270 |
+
func (ExternalAuth) TableName() string { return "extern_auth" }
|
| 271 |
+
func (FCM) TableName() string { return "fcm" }
|
| 272 |
+
func (ForgotPassword) TableName() string { return "forgot_password" }
|
| 273 |
+
func (Academy) TableName() string { return "academy" }
|
| 274 |
+
func (AcademyMaterial) TableName() string { return "academy_materials" }
|
| 275 |
+
func (AcademyContent) TableName() string { return "academy_contents" }
|
| 276 |
+
func (AcademyMaterialProgress) TableName() string { return "academy_materials_progress" }
|
| 277 |
+
func (AcademyContentProgress) TableName() string { return "academy_contents_progress" }
|
| 278 |
+
func (RegionProvince) TableName() string { return "region_provinces" }
|
| 279 |
+
func (RegionCity) TableName() string { return "region_cities" }
|
| 280 |
+
func (Answer) TableName() string { return "answers" }
|
| 281 |
+
func (Question) TableName() string { return "questions" }
|
| 282 |
+
func (Quiz) TableName() string { return "quizzes" }
|
| 283 |
+
func (QuizAttempt) TableName() string { return "quiz_attempts" }
|
| 284 |
+
func (UserAnswer) TableName() string { return "user_answers" }
|
| 285 |
+
func (OptionCategory) TableName() string { return "option_categories" }
|
| 286 |
+
func (OptionValues) TableName() string { return "option_values" }
|
| 287 |
+
func (PersonalityAndPreferenceCV) TableName() string { return "personality_and_preference_cv" }
|
| 288 |
+
func (FamilyMemberCV) TableName() string { return "family_member_cv" }
|
| 289 |
+
func (PhysicalAndHealthCV) TableName() string { return "physical_and_health_cv" }
|
| 290 |
+
func (WorshipAndReligiousUnderstandingCV) TableName() string {
|
| 291 |
+
return "worship_and_religious_understanding_cv"
|
| 292 |
+
}
|
space/space/space/space/space/models/request_model.go
CHANGED
|
@@ -1,51 +1,126 @@
|
|
| 1 |
-
package models
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package models
|
| 2 |
+
|
| 3 |
+
import "time"
|
| 4 |
+
|
| 5 |
+
type LoginRequest struct {
|
| 6 |
+
Email string `json:"email" binding:"required"`
|
| 7 |
+
Password string `json:"password" binding:"required"`
|
| 8 |
+
}
|
| 9 |
+
|
| 10 |
+
type RegisterRequest struct {
|
| 11 |
+
Name string `json:"name"`
|
| 12 |
+
Email string `json:"email" binding:"required,email"`
|
| 13 |
+
Phone int `json:"phone"`
|
| 14 |
+
Password string `json:"password" binding:"required"`
|
| 15 |
+
}
|
| 16 |
+
|
| 17 |
+
type ChangePasswordRequest struct {
|
| 18 |
+
OldPassword string `json:"old_password" binding:"required" `
|
| 19 |
+
NewPassword string `json:"new_password" binding:"required" `
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
type CreateVerifyEmailRequest struct {
|
| 23 |
+
Token uint `json:"token" binding:"required"`
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
type OptionsRequest struct {
|
| 27 |
+
OptionName string `json:"option_name" binding:"required"`
|
| 28 |
+
OptionValue []string `json:"option_values" binding:"required"`
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
type ExternalAuthRequest struct {
|
| 32 |
+
OauthID string `json:"oauth_id" binding:"required"`
|
| 33 |
+
OauthProvider string `json:"oauth_provider" binding:"required"`
|
| 34 |
+
IsAgreeTerms bool `json:"is_agree_terms"`
|
| 35 |
+
IsSexualDisease bool `json:"is_sexual_disease"`
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
type ForgotPasswordRequest struct {
|
| 39 |
+
Email string `json:"email" binding:"required,email"`
|
| 40 |
+
}
|
| 41 |
+
type ValidateForgotPasswordRequest struct {
|
| 42 |
+
Token uint `json:"token" binding:"required"`
|
| 43 |
+
NewPassword string `json:"new_password"`
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
type QuestionQuizRequest struct {
|
| 47 |
+
QuestionNo int `json:"question_no" binding:"required"`
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
type AnswerQuizRequest struct {
|
| 51 |
+
QuestionNo int `json:"question_no" binding:"required"`
|
| 52 |
+
Answer int `json:"answer" binding:"required"`
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
type (
|
| 56 |
+
PersonalityAndPreferenceCVRequest struct {
|
| 57 |
+
AccountID int64 `json:"-"`
|
| 58 |
+
PositiveTraits *string `json:"positive_traits"` // sifat positif
|
| 59 |
+
NegativeTraits *string `json:"negative_traits"` // sifat negatif
|
| 60 |
+
Hobbies *string `json:"hobbies"` // hobi
|
| 61 |
+
LifeGoals *string `json:"life_goals"` // target hidup
|
| 62 |
+
DailyActivities *string `json:"daily_activities"` // kegiatan sehari-hari
|
| 63 |
+
LeisureActivities *string `json:"leisure_activities"` // kegiatan waktu luang
|
| 64 |
+
Likes *string `json:"likes"` // hal yang disukai
|
| 65 |
+
Dislikes *string `json:"dislikes"` // hal yang tidak disukai
|
| 66 |
+
StressHandling *string `json:"stress_handling"` // cara mengatasi stres
|
| 67 |
+
AngerTriggers *string `json:"anger_triggers"` // pemicu amarah
|
| 68 |
+
FavoriteFoodAndDrinks *string `json:"favorite_food_and_drinks"` // makanan dan minuman favorit
|
| 69 |
+
CanCook *bool `json:"can_cook"` // bisa memasak
|
| 70 |
+
TypesOfDishesCooked *string `json:"types_of_dishes_cooked"` // jenis masakan yang bisa dimasak
|
| 71 |
+
MonthlyExpenses *string `json:"monthly_expenses"` // pengeluaran per bulan
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
FamilyMemberRequest struct {
|
| 75 |
+
AccountID int64 `json:"-"`
|
| 76 |
+
Role *string `json:"role"` // Peran dalam keluarga
|
| 77 |
+
Status *string `json:"status"` // Status (Hidup, Wafat)
|
| 78 |
+
Religion *string `json:"religion"` // Agama
|
| 79 |
+
Job *string `json:"job"` // Pekerjaan
|
| 80 |
+
LastEducation *string `json:"last_education"` // Pendidikan terakhir
|
| 81 |
+
Age *int `json:"age"` // Usia
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
PhysicalAndHealthRequest struct {
|
| 85 |
+
AccountID int64 `json:"-"`
|
| 86 |
+
HeightInCm *int `json:"height_cm"` // Tinggi badan dalam satuan sentimeter
|
| 87 |
+
WeightInKg *int `json:"weight_kg"` // Berat badan dalam satuan kilogram
|
| 88 |
+
BodyShape *string `json:"body_shape"` // Bentuk tubuh
|
| 89 |
+
SkinColor *string `json:"skin_color"` // Warna kulit
|
| 90 |
+
HairType *string `json:"hair_type"` // Tipe rambut
|
| 91 |
+
MedicalHistory *string `json:"medical_history"` // Riwayat penyakit
|
| 92 |
+
PhysicalDisorder *string `json:"physical_disorder"` // Cacat fisik
|
| 93 |
+
PhysicalTraits *string `json:"physical_traits"` // Ciri khas fisik
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
+
AccountDetailsRequest struct {
|
| 97 |
+
AccountID int64 `json:"-"`
|
| 98 |
+
FullName *string `json:"full_name"`
|
| 99 |
+
Gender *string `json:"gender"`
|
| 100 |
+
DateOfBirth *time.Time `json:"date_of_birth"`
|
| 101 |
+
PlaceOfBirth *string `json:"place_of_birth"`
|
| 102 |
+
Domicile *string `json:"domicile"`
|
| 103 |
+
MaritalStatus *string `json:"marital_status"`
|
| 104 |
+
LastEducation *string `json:"last_education"`
|
| 105 |
+
LastJob *string `json:"last_job"`
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
+
WorshipAndReligiousUnderstandingRequest struct {
|
| 109 |
+
AccountID int64 `json:"-"`
|
| 110 |
+
ObligatoryPrayer *string `json:"obligatory_prayer"` // sholat_wajib_5_waktu
|
| 111 |
+
CongregationalPrayer *string `json:"congregational_prayer"` // sholat_berjamaah_di_masjid
|
| 112 |
+
TahajjudPrayer *string `json:"tahajjud_prayer"` // sholat_tahajud
|
| 113 |
+
DhuhaPrayer *string `json:"dhuha_prayer"` // sholat_dhuha
|
| 114 |
+
QuranMemorization *string `json:"quran_memorization"` // hafalan_alquran
|
| 115 |
+
QuranReadingAbility *string `json:"quran_reading_ability"` // kemampuan_baca_alquran
|
| 116 |
+
DaudFasting *string `json:"daud_fasting"` // puasa_daud
|
| 117 |
+
AyyamulBidhFasting *string `json:"ayyamul_bidh_fasting"` // puasa_ayyamul_bidh
|
| 118 |
+
HajjOrUmrah *string `json:"hajj_or_umrah"` // ibadah_haji_umroh
|
| 119 |
+
ListeningToMusic *string `json:"listening_to_music"` // mendengarkan_musik
|
| 120 |
+
OpinionOnIkhtilat *string `json:"opinion_on_ikhtilat"` // pendapat_ikhtilat
|
| 121 |
+
OpinionOnTouchingNonMahram *string `json:"opinion_on_touching_non_mahram"` // pendapat_menyentuh_non_mahram
|
| 122 |
+
OpinionOnVeil *string `json:"opinion_on_veil"` // pendapat_tentang_cadar
|
| 123 |
+
WeeklyReligiousStudies *string `json:"weekly_religious_studies"` // kajian_yang_diikuti_dalam_sepekan
|
| 124 |
+
FollowedUstadz *string `json:"followed_ustadz"` // ustadz_yang_diikuti
|
| 125 |
+
}
|
| 126 |
+
)
|
space/space/space/space/space/repositories/cv_repository.go
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package repositories
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"api.qobiltu.id/models"
|
| 5 |
+
"context"
|
| 6 |
+
"gorm.io/gorm"
|
| 7 |
+
)
|
| 8 |
+
|
| 9 |
+
type CVRepository interface {
|
| 10 |
+
SaveAccountDetails(ctx context.Context, req *models.AccountDetails) (*models.AccountDetails, error)
|
| 11 |
+
GetAccountDetailsByAccountID(ctx context.Context, accountID int64) (*models.AccountDetails, error)
|
| 12 |
+
|
| 13 |
+
SavePersonalityAndPreference(ctx context.Context, req *models.PersonalityAndPreferenceCV) (*models.PersonalityAndPreferenceCV, error)
|
| 14 |
+
GetPersonalityAndPreferenceByAccountID(ctx context.Context, accountID int64) (*models.PersonalityAndPreferenceCV, error)
|
| 15 |
+
|
| 16 |
+
SaveFamilyMember(ctx context.Context, req *models.FamilyMemberCV) (*models.FamilyMemberCV, error)
|
| 17 |
+
ListFamilyMember(ctx context.Context, accountID int64) ([]models.FamilyMemberCV, error)
|
| 18 |
+
GetFamilyMember(ctx context.Context, id int64) (*models.FamilyMemberCV, error)
|
| 19 |
+
DeleteFamilyMember(ctx context.Context, id int64) error
|
| 20 |
+
|
| 21 |
+
SavePhysicalAndHealth(ctx context.Context, req *models.PhysicalAndHealthCV) (*models.PhysicalAndHealthCV, error)
|
| 22 |
+
GetPhysicalAndHealthByAccountID(ctx context.Context, accountID int64) (*models.PhysicalAndHealthCV, error)
|
| 23 |
+
|
| 24 |
+
SaveWorshipAndReligiousUnderstanding(ctx context.Context, req *models.WorshipAndReligiousUnderstandingCV) (*models.WorshipAndReligiousUnderstandingCV, error)
|
| 25 |
+
GetWorshipAndReligiousUnderstandingByAccountID(ctx context.Context, accountID int64) (*models.WorshipAndReligiousUnderstandingCV, error)
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
type cvRepository struct {
|
| 29 |
+
db *gorm.DB
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
func NewCVRepository(db *gorm.DB) CVRepository {
|
| 33 |
+
return &cvRepository{
|
| 34 |
+
db: db,
|
| 35 |
+
}
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
func (r *cvRepository) SaveAccountDetails(ctx context.Context, req *models.AccountDetails) (*models.AccountDetails, error) {
|
| 39 |
+
if err := r.db.WithContext(ctx).Save(req).Error; err != nil {
|
| 40 |
+
return req, err
|
| 41 |
+
}
|
| 42 |
+
return req, nil
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
func (r *cvRepository) GetAccountDetailsByAccountID(ctx context.Context, accountID int64) (*models.AccountDetails, error) {
|
| 46 |
+
var accountDetails models.AccountDetails
|
| 47 |
+
if err := r.db.WithContext(ctx).Where("account_id = ?", accountID).First(&accountDetails).Error; err != nil {
|
| 48 |
+
return nil, err
|
| 49 |
+
}
|
| 50 |
+
return &accountDetails, nil
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
func (r *cvRepository) SavePersonalityAndPreference(ctx context.Context, req *models.PersonalityAndPreferenceCV) (*models.PersonalityAndPreferenceCV, error) {
|
| 54 |
+
if err := r.db.WithContext(ctx).Save(req).Error; err != nil {
|
| 55 |
+
return req, err
|
| 56 |
+
}
|
| 57 |
+
return req, nil
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
func (r *cvRepository) GetPersonalityAndPreferenceByAccountID(ctx context.Context, accountID int64) (*models.PersonalityAndPreferenceCV, error) {
|
| 61 |
+
var personalityAndPreference models.PersonalityAndPreferenceCV
|
| 62 |
+
if err := r.db.WithContext(ctx).Where("account_id = ?", accountID).First(&personalityAndPreference).Error; err != nil {
|
| 63 |
+
return nil, err
|
| 64 |
+
}
|
| 65 |
+
return &personalityAndPreference, nil
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
func (r *cvRepository) SaveFamilyMember(ctx context.Context, req *models.FamilyMemberCV) (*models.FamilyMemberCV, error) {
|
| 69 |
+
if err := r.db.WithContext(ctx).Save(req).Error; err != nil {
|
| 70 |
+
return req, err
|
| 71 |
+
}
|
| 72 |
+
return req, nil
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
func (r *cvRepository) GetFamilyMember(ctx context.Context, id int64) (*models.FamilyMemberCV, error) {
|
| 76 |
+
var familyMember models.FamilyMemberCV
|
| 77 |
+
if err := r.db.WithContext(ctx).Where("id = ?", id).First(&familyMember).Error; err != nil {
|
| 78 |
+
return nil, err
|
| 79 |
+
}
|
| 80 |
+
return &familyMember, nil
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
func (r *cvRepository) DeleteFamilyMember(ctx context.Context, id int64) error {
|
| 84 |
+
if err := r.db.WithContext(ctx).Where("id = ?", id).Delete(&models.FamilyMemberCV{}).Error; err != nil {
|
| 85 |
+
return err
|
| 86 |
+
}
|
| 87 |
+
return nil
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
func (r *cvRepository) ListFamilyMember(ctx context.Context, accountID int64) ([]models.FamilyMemberCV, error) {
|
| 91 |
+
familyMembers := make([]models.FamilyMemberCV, 0)
|
| 92 |
+
if err := r.db.WithContext(ctx).Where("account_id = ?", accountID).Find(&familyMembers).Error; err != nil {
|
| 93 |
+
return nil, err
|
| 94 |
+
}
|
| 95 |
+
return familyMembers, nil
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
func (r *cvRepository) SavePhysicalAndHealth(ctx context.Context, req *models.PhysicalAndHealthCV) (*models.PhysicalAndHealthCV, error) {
|
| 99 |
+
if err := r.db.WithContext(ctx).Save(req).Error; err != nil {
|
| 100 |
+
return req, err
|
| 101 |
+
}
|
| 102 |
+
return req, nil
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
func (r *cvRepository) GetPhysicalAndHealthByAccountID(ctx context.Context, accountID int64) (*models.PhysicalAndHealthCV, error) {
|
| 106 |
+
var physicalAndHealth models.PhysicalAndHealthCV
|
| 107 |
+
if err := r.db.WithContext(ctx).Where("account_id = ?", accountID).First(&physicalAndHealth).Error; err != nil {
|
| 108 |
+
return nil, err
|
| 109 |
+
}
|
| 110 |
+
return &physicalAndHealth, nil
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
func (r *cvRepository) SaveWorshipAndReligiousUnderstanding(ctx context.Context, req *models.WorshipAndReligiousUnderstandingCV) (*models.WorshipAndReligiousUnderstandingCV, error) {
|
| 114 |
+
if err := r.db.WithContext(ctx).Save(req).Error; err != nil {
|
| 115 |
+
return req, err
|
| 116 |
+
}
|
| 117 |
+
return req, nil
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
func (r *cvRepository) GetWorshipAndReligiousUnderstandingByAccountID(ctx context.Context, accountID int64) (*models.WorshipAndReligiousUnderstandingCV, error) {
|
| 121 |
+
var worshipAndReligiousUnderstanding models.WorshipAndReligiousUnderstandingCV
|
| 122 |
+
if err := r.db.WithContext(ctx).Where("account_id = ?", accountID).First(&worshipAndReligiousUnderstanding).Error; err != nil {
|
| 123 |
+
return nil, err
|
| 124 |
+
}
|
| 125 |
+
return &worshipAndReligiousUnderstanding, nil
|
| 126 |
+
}
|
space/space/space/space/space/router/cv_route.go
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package router
|
| 2 |
+
|
| 3 |
+
import "api.qobiltu.id/middleware"
|
| 4 |
+
|
| 5 |
+
func (s *Server) CVRoute() {
|
| 6 |
+
routerGroup := s.router.Group("/api/v1/cv").Use(middleware.AuthUser)
|
| 7 |
+
{
|
| 8 |
+
routerGroup.POST("/account-details", s.cvController.SaveAccountDetails)
|
| 9 |
+
routerGroup.GET("/account-details", s.cvController.GetAccountDetails)
|
| 10 |
+
|
| 11 |
+
routerGroup.POST("/personality-and-preferences", s.cvController.SavePersonalityAndPreference)
|
| 12 |
+
routerGroup.GET("/personality-and-preferences", s.cvController.GetPersonalityAndPreference)
|
| 13 |
+
|
| 14 |
+
routerGroup.POST("/family-members", s.cvController.CreateFamilyMember)
|
| 15 |
+
routerGroup.GET("/family-members", s.cvController.ListFamilyMember)
|
| 16 |
+
routerGroup.GET("/family-members/:id", s.cvController.GetFamilyMember)
|
| 17 |
+
routerGroup.PUT("/family-members/:id", s.cvController.UpdateFamilyMember)
|
| 18 |
+
routerGroup.DELETE("/family-members/:id", s.cvController.DeleteFamilyMember)
|
| 19 |
+
|
| 20 |
+
routerGroup.POST("/physical-and-healths", s.cvController.SavePhysicalAndHealth)
|
| 21 |
+
routerGroup.GET("/physical-and-healths", s.cvController.GetPhysicalAndHealth)
|
| 22 |
+
|
| 23 |
+
routerGroup.POST("/worship-and-religious-understandings", s.cvController.SaveWorshipAndReligiousUnderstanding)
|
| 24 |
+
routerGroup.GET("/worship-and-religious-understandings", s.cvController.GetWorshipAndReligiousUnderstanding)
|
| 25 |
+
}
|
| 26 |
+
}
|
space/space/space/space/space/router/router.go
CHANGED
|
@@ -1,20 +1,21 @@
|
|
| 1 |
package router
|
| 2 |
|
| 3 |
import (
|
| 4 |
-
|
| 5 |
)
|
| 6 |
|
| 7 |
func (s *Server) setupRoutes() {
|
| 8 |
|
| 9 |
-
|
| 10 |
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
|
| 18 |
-
|
| 19 |
-
|
|
|
|
| 20 |
}
|
|
|
|
| 1 |
package router
|
| 2 |
|
| 3 |
import (
|
| 4 |
+
"api.qobiltu.id/controller"
|
| 5 |
)
|
| 6 |
|
| 7 |
func (s *Server) setupRoutes() {
|
| 8 |
|
| 9 |
+
s.router.GET("/", controller.HomeController)
|
| 10 |
|
| 11 |
+
AuthRoute(s.router)
|
| 12 |
+
UserRoute(s.router)
|
| 13 |
+
EmailRoute(s.router)
|
| 14 |
+
OptionsRoute(s.router)
|
| 15 |
+
AcademyRoute(s.router)
|
| 16 |
+
QuizRoute(s.router)
|
| 17 |
|
| 18 |
+
// another way to register routes
|
| 19 |
+
s.HealthCheckRoute()
|
| 20 |
+
s.CVRoute()
|
| 21 |
}
|
space/space/space/space/space/router/server.go
CHANGED
|
@@ -1,6 +1,7 @@
|
|
| 1 |
package router
|
| 2 |
|
| 3 |
import (
|
|
|
|
| 4 |
"api.qobiltu.id/controller/health_check"
|
| 5 |
"github.com/gin-gonic/gin"
|
| 6 |
)
|
|
@@ -8,10 +9,12 @@ import (
|
|
| 8 |
type Server struct {
|
| 9 |
router *gin.Engine
|
| 10 |
healthCheckController health_check_controller.HealthCheckController
|
|
|
|
| 11 |
}
|
| 12 |
|
| 13 |
func NewServer(
|
| 14 |
healthCheckController health_check_controller.HealthCheckController,
|
|
|
|
| 15 |
) (*Server, error) {
|
| 16 |
|
| 17 |
router := gin.Default()
|
|
@@ -19,6 +22,7 @@ func NewServer(
|
|
| 19 |
|
| 20 |
server := &Server{
|
| 21 |
healthCheckController: healthCheckController,
|
|
|
|
| 22 |
router: router,
|
| 23 |
}
|
| 24 |
|
|
|
|
| 1 |
package router
|
| 2 |
|
| 3 |
import (
|
| 4 |
+
cv_controller "api.qobiltu.id/controller/cv"
|
| 5 |
"api.qobiltu.id/controller/health_check"
|
| 6 |
"github.com/gin-gonic/gin"
|
| 7 |
)
|
|
|
|
| 9 |
type Server struct {
|
| 10 |
router *gin.Engine
|
| 11 |
healthCheckController health_check_controller.HealthCheckController
|
| 12 |
+
cvController cv_controller.CVController
|
| 13 |
}
|
| 14 |
|
| 15 |
func NewServer(
|
| 16 |
healthCheckController health_check_controller.HealthCheckController,
|
| 17 |
+
cvController cv_controller.CVController,
|
| 18 |
) (*Server, error) {
|
| 19 |
|
| 20 |
router := gin.Default()
|
|
|
|
| 22 |
|
| 23 |
server := &Server{
|
| 24 |
healthCheckController: healthCheckController,
|
| 25 |
+
cvController: cvController,
|
| 26 |
router: router,
|
| 27 |
}
|
| 28 |
|
space/space/space/space/space/services/cv_service.go
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package services
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"api.qobiltu.id/models"
|
| 5 |
+
"api.qobiltu.id/repositories"
|
| 6 |
+
"api.qobiltu.id/response"
|
| 7 |
+
"context"
|
| 8 |
+
"errors"
|
| 9 |
+
"gorm.io/gorm"
|
| 10 |
+
)
|
| 11 |
+
|
| 12 |
+
type CVService interface {
|
| 13 |
+
SaveAccountDetails(ctx context.Context, req *models.AccountDetailsRequest) (*models.AccountDetails, error)
|
| 14 |
+
GetAccountDetails(ctx context.Context, id int64) (*models.AccountDetails, error)
|
| 15 |
+
|
| 16 |
+
SavePersonalityAndPreference(ctx context.Context, req *models.PersonalityAndPreferenceCVRequest) (*models.PersonalityAndPreferenceCV, error)
|
| 17 |
+
GetPersonalityAndPreference(ctx context.Context, id int64) (*models.PersonalityAndPreferenceCV, error)
|
| 18 |
+
|
| 19 |
+
CreateFamilyMember(ctx context.Context, req *models.FamilyMemberRequest) (*models.FamilyMemberCV, error)
|
| 20 |
+
UpdateFamilyMember(ctx context.Context, id int64, req *models.FamilyMemberRequest) (*models.FamilyMemberCV, error)
|
| 21 |
+
ListFamilyMember(ctx context.Context, accountID int64) ([]models.FamilyMemberCV, error)
|
| 22 |
+
GetFamilyMember(ctx context.Context, id int64) (*models.FamilyMemberCV, error)
|
| 23 |
+
DeleteFamilyMember(ctx context.Context, id int64) error
|
| 24 |
+
|
| 25 |
+
SavePhysicalAndHealth(ctx context.Context, req *models.PhysicalAndHealthRequest) (*models.PhysicalAndHealthCV, error)
|
| 26 |
+
GetPhysicalAndHealth(ctx context.Context, id int64) (*models.PhysicalAndHealthCV, error)
|
| 27 |
+
|
| 28 |
+
SaveWorshipAndReligiousUnderstanding(ctx context.Context, req *models.WorshipAndReligiousUnderstandingRequest) (*models.WorshipAndReligiousUnderstandingCV, error)
|
| 29 |
+
GetWorshipAndReligiousUnderstanding(ctx context.Context, id int64) (*models.WorshipAndReligiousUnderstandingCV, error)
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
type cvService struct {
|
| 33 |
+
cvRepository repositories.CVRepository
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
func NewCVService(cvRepository repositories.CVRepository) CVService {
|
| 37 |
+
return &cvService{
|
| 38 |
+
cvRepository: cvRepository,
|
| 39 |
+
}
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
func (s *cvService) SaveAccountDetails(ctx context.Context, req *models.AccountDetailsRequest) (*models.AccountDetails, error) {
|
| 43 |
+
// Ambil data lama jika ada
|
| 44 |
+
accountDetails, err := s.cvRepository.GetAccountDetailsByAccountID(ctx, req.AccountID)
|
| 45 |
+
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
| 46 |
+
return nil, response.HandleGormError(err, "Internal Server Error")
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
// Apply perubahan
|
| 50 |
+
if accountDetails == nil {
|
| 51 |
+
accountDetails = &models.AccountDetails{}
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
accountDetails.AccountID = uint(req.AccountID)
|
| 55 |
+
accountDetails.FullName = req.FullName
|
| 56 |
+
accountDetails.Gender = req.Gender
|
| 57 |
+
accountDetails.DateOfBirth = req.DateOfBirth
|
| 58 |
+
accountDetails.PlaceOfBirth = req.PlaceOfBirth
|
| 59 |
+
accountDetails.Domicile = req.Domicile
|
| 60 |
+
accountDetails.MaritalStatus = req.MaritalStatus
|
| 61 |
+
accountDetails.LastEducation = req.LastEducation
|
| 62 |
+
accountDetails.LastJob = req.LastJob
|
| 63 |
+
|
| 64 |
+
// Simpan data
|
| 65 |
+
res, err := s.cvRepository.SaveAccountDetails(ctx, accountDetails)
|
| 66 |
+
if err != nil {
|
| 67 |
+
return nil, response.HandleGormError(err, "Internal Server Error")
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
return res, nil
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
func (s *cvService) GetAccountDetails(ctx context.Context, id int64) (*models.AccountDetails, error) {
|
| 74 |
+
res, err := s.cvRepository.GetAccountDetailsByAccountID(ctx, id)
|
| 75 |
+
if err != nil {
|
| 76 |
+
return nil, response.HandleGormError(err, "Data diri tidak ditemukan")
|
| 77 |
+
}
|
| 78 |
+
return res, nil
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
func (s *cvService) SavePersonalityAndPreference(ctx context.Context, req *models.PersonalityAndPreferenceCVRequest) (*models.PersonalityAndPreferenceCV, error) {
|
| 82 |
+
// Ambil data lama jika ada
|
| 83 |
+
personalityAndPreference, err := s.cvRepository.GetPersonalityAndPreferenceByAccountID(ctx, req.AccountID)
|
| 84 |
+
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
| 85 |
+
return nil, response.HandleGormError(err, "Internal Server Error")
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
// Apply perubahan
|
| 89 |
+
if personalityAndPreference == nil {
|
| 90 |
+
personalityAndPreference = &models.PersonalityAndPreferenceCV{}
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
personalityAndPreference.AccountID = req.AccountID
|
| 94 |
+
personalityAndPreference.PositiveTraits = req.PositiveTraits
|
| 95 |
+
personalityAndPreference.NegativeTraits = req.NegativeTraits
|
| 96 |
+
personalityAndPreference.Hobbies = req.Hobbies
|
| 97 |
+
personalityAndPreference.LifeGoals = req.LifeGoals
|
| 98 |
+
personalityAndPreference.DailyActivities = req.DailyActivities
|
| 99 |
+
personalityAndPreference.LeisureActivities = req.LeisureActivities
|
| 100 |
+
personalityAndPreference.Likes = req.Likes
|
| 101 |
+
personalityAndPreference.Dislikes = req.Dislikes
|
| 102 |
+
personalityAndPreference.StressHandling = req.StressHandling
|
| 103 |
+
personalityAndPreference.AngerTriggers = req.AngerTriggers
|
| 104 |
+
personalityAndPreference.FavoriteFoodAndDrinks = req.FavoriteFoodAndDrinks
|
| 105 |
+
personalityAndPreference.CanCook = req.CanCook
|
| 106 |
+
personalityAndPreference.TypesOfDishesCooked = req.TypesOfDishesCooked
|
| 107 |
+
personalityAndPreference.MonthlyExpenses = req.MonthlyExpenses
|
| 108 |
+
|
| 109 |
+
res, err := s.cvRepository.SavePersonalityAndPreference(ctx, personalityAndPreference)
|
| 110 |
+
if err != nil {
|
| 111 |
+
return nil, response.HandleGormError(err, "Internal Server Error")
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
return res, nil
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
func (s *cvService) GetPersonalityAndPreference(ctx context.Context, id int64) (*models.PersonalityAndPreferenceCV, error) {
|
| 118 |
+
res, err := s.cvRepository.GetPersonalityAndPreferenceByAccountID(ctx, id)
|
| 119 |
+
if err != nil {
|
| 120 |
+
return nil, response.HandleGormError(err, "Internal Server Error")
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
return res, nil
|
| 124 |
+
}
|
| 125 |
+
|
| 126 |
+
func (s *cvService) CreateFamilyMember(ctx context.Context, req *models.FamilyMemberRequest) (*models.FamilyMemberCV, error) {
|
| 127 |
+
// Mapping request ke model
|
| 128 |
+
familyMember := &models.FamilyMemberCV{
|
| 129 |
+
AccountID: req.AccountID,
|
| 130 |
+
Role: req.Role,
|
| 131 |
+
Status: req.Status,
|
| 132 |
+
Religion: req.Religion,
|
| 133 |
+
Job: req.Job,
|
| 134 |
+
LastEducation: req.LastEducation,
|
| 135 |
+
Age: req.Age,
|
| 136 |
+
}
|
| 137 |
+
|
| 138 |
+
// Simpan ke repository
|
| 139 |
+
res, err := s.cvRepository.SaveFamilyMember(ctx, familyMember)
|
| 140 |
+
if err != nil {
|
| 141 |
+
return nil, response.HandleGormError(err, "Gagal menyimpan anggota keluarga")
|
| 142 |
+
}
|
| 143 |
+
|
| 144 |
+
return res, nil
|
| 145 |
+
}
|
| 146 |
+
|
| 147 |
+
func (s *cvService) ListFamilyMember(ctx context.Context, accountID int64) ([]models.FamilyMemberCV, error) {
|
| 148 |
+
list, err := s.cvRepository.ListFamilyMember(ctx, accountID)
|
| 149 |
+
if err != nil {
|
| 150 |
+
return nil, response.HandleGormError(err, "Gagal mengambil daftar anggota keluarga")
|
| 151 |
+
}
|
| 152 |
+
return list, nil
|
| 153 |
+
}
|
| 154 |
+
|
| 155 |
+
func (s *cvService) GetFamilyMember(ctx context.Context, id int64) (*models.FamilyMemberCV, error) {
|
| 156 |
+
res, err := s.cvRepository.GetFamilyMember(ctx, id)
|
| 157 |
+
if err != nil {
|
| 158 |
+
return nil, response.HandleGormError(err, "Data anggota keluarga tidak ditemukan")
|
| 159 |
+
}
|
| 160 |
+
return res, nil
|
| 161 |
+
}
|
| 162 |
+
|
| 163 |
+
func (s *cvService) DeleteFamilyMember(ctx context.Context, id int64) error {
|
| 164 |
+
err := s.cvRepository.DeleteFamilyMember(ctx, id)
|
| 165 |
+
if err != nil {
|
| 166 |
+
return response.HandleGormError(err, "Gagal menghapus anggota keluarga")
|
| 167 |
+
}
|
| 168 |
+
return nil
|
| 169 |
+
}
|
| 170 |
+
|
| 171 |
+
func (s *cvService) UpdateFamilyMember(ctx context.Context, id int64, req *models.FamilyMemberRequest) (*models.FamilyMemberCV, error) {
|
| 172 |
+
existing, err := s.cvRepository.GetFamilyMember(ctx, id)
|
| 173 |
+
if err != nil {
|
| 174 |
+
return nil, response.HandleGormError(err, "Data anggota keluarga tidak ditemukan")
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
existing.Role = req.Role
|
| 178 |
+
existing.Status = req.Status
|
| 179 |
+
existing.Religion = req.Religion
|
| 180 |
+
existing.Job = req.Job
|
| 181 |
+
existing.LastEducation = req.LastEducation
|
| 182 |
+
existing.Age = req.Age
|
| 183 |
+
|
| 184 |
+
updated, err := s.cvRepository.SaveFamilyMember(ctx, existing)
|
| 185 |
+
if err != nil {
|
| 186 |
+
return nil, response.HandleGormError(err, "Gagal memperbarui anggota keluarga")
|
| 187 |
+
}
|
| 188 |
+
|
| 189 |
+
return updated, nil
|
| 190 |
+
}
|
| 191 |
+
|
| 192 |
+
func (s *cvService) SavePhysicalAndHealth(ctx context.Context, req *models.PhysicalAndHealthRequest) (*models.PhysicalAndHealthCV, error) {
|
| 193 |
+
// Cek apakah data sudah ada berdasarkan account_id
|
| 194 |
+
existing, err := s.cvRepository.GetPhysicalAndHealthByAccountID(ctx, req.AccountID)
|
| 195 |
+
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
| 196 |
+
return nil, response.HandleGormError(err, "Terjadi kesalahan saat mengambil data fisik dan kesehatan")
|
| 197 |
+
}
|
| 198 |
+
|
| 199 |
+
// Jika belum ada, buat objek baru
|
| 200 |
+
if existing == nil {
|
| 201 |
+
existing = &models.PhysicalAndHealthCV{}
|
| 202 |
+
}
|
| 203 |
+
|
| 204 |
+
// Mapping field dari request
|
| 205 |
+
existing.AccountID = req.AccountID
|
| 206 |
+
existing.HeightInCm = req.HeightInCm
|
| 207 |
+
existing.WeightInKg = req.WeightInKg
|
| 208 |
+
existing.BodyShape = req.BodyShape
|
| 209 |
+
existing.SkinColor = req.SkinColor
|
| 210 |
+
existing.HairType = req.HairType
|
| 211 |
+
existing.MedicalHistory = req.MedicalHistory
|
| 212 |
+
existing.PhysicalDisorder = req.PhysicalDisorder
|
| 213 |
+
existing.PhysicalTraits = req.PhysicalTraits
|
| 214 |
+
|
| 215 |
+
// Simpan data
|
| 216 |
+
res, err := s.cvRepository.SavePhysicalAndHealth(ctx, existing)
|
| 217 |
+
if err != nil {
|
| 218 |
+
return nil, response.HandleGormError(err, "Gagal menyimpan data fisik dan kesehatan")
|
| 219 |
+
}
|
| 220 |
+
|
| 221 |
+
return res, nil
|
| 222 |
+
}
|
| 223 |
+
|
| 224 |
+
func (s *cvService) GetPhysicalAndHealth(ctx context.Context, id int64) (*models.PhysicalAndHealthCV, error) {
|
| 225 |
+
res, err := s.cvRepository.GetPhysicalAndHealthByAccountID(ctx, id)
|
| 226 |
+
if err != nil {
|
| 227 |
+
return nil, response.HandleGormError(err, "Data fisik dan kesehatan tidak ditemukan")
|
| 228 |
+
}
|
| 229 |
+
return res, nil
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
func (s *cvService) SaveWorshipAndReligiousUnderstanding(ctx context.Context, req *models.WorshipAndReligiousUnderstandingRequest) (*models.WorshipAndReligiousUnderstandingCV, error) {
|
| 233 |
+
// Cek apakah data sudah ada berdasarkan account_id
|
| 234 |
+
worshipAndReligiousUnderstanding, err := s.cvRepository.GetWorshipAndReligiousUnderstandingByAccountID(ctx, req.AccountID)
|
| 235 |
+
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
| 236 |
+
return nil, response.HandleGormError(err, "Terjadi kesalahan saat mengambil data agama dan pemahaman agama")
|
| 237 |
+
}
|
| 238 |
+
|
| 239 |
+
// Jika belum ada, buat objek baru
|
| 240 |
+
if worshipAndReligiousUnderstanding == nil {
|
| 241 |
+
worshipAndReligiousUnderstanding = &models.WorshipAndReligiousUnderstandingCV{}
|
| 242 |
+
}
|
| 243 |
+
|
| 244 |
+
// Mapping field dari request
|
| 245 |
+
worshipAndReligiousUnderstanding.AccountID = req.AccountID
|
| 246 |
+
worshipAndReligiousUnderstanding.ObligatoryPrayer = req.ObligatoryPrayer
|
| 247 |
+
worshipAndReligiousUnderstanding.CongregationalPrayer = req.CongregationalPrayer
|
| 248 |
+
worshipAndReligiousUnderstanding.TahajjudPrayer = req.TahajjudPrayer
|
| 249 |
+
worshipAndReligiousUnderstanding.DhuhaPrayer = req.DhuhaPrayer
|
| 250 |
+
worshipAndReligiousUnderstanding.QuranMemorization = req.QuranMemorization
|
| 251 |
+
worshipAndReligiousUnderstanding.QuranReadingAbility = req.QuranReadingAbility
|
| 252 |
+
worshipAndReligiousUnderstanding.DaudFasting = req.DaudFasting
|
| 253 |
+
worshipAndReligiousUnderstanding.AyyamulBidhFasting = req.AyyamulBidhFasting
|
| 254 |
+
worshipAndReligiousUnderstanding.HajjOrUmrah = req.HajjOrUmrah
|
| 255 |
+
worshipAndReligiousUnderstanding.ListeningToMusic = req.ListeningToMusic
|
| 256 |
+
worshipAndReligiousUnderstanding.OpinionOnIkhtilat = req.OpinionOnIkhtilat
|
| 257 |
+
worshipAndReligiousUnderstanding.OpinionOnTouchingNonMahram = req.OpinionOnTouchingNonMahram
|
| 258 |
+
worshipAndReligiousUnderstanding.OpinionOnVeil = req.OpinionOnVeil
|
| 259 |
+
worshipAndReligiousUnderstanding.WeeklyReligiousStudies = req.WeeklyReligiousStudies
|
| 260 |
+
worshipAndReligiousUnderstanding.FollowedUstadz = req.FollowedUstadz
|
| 261 |
+
|
| 262 |
+
// Simpan data
|
| 263 |
+
res, err := s.cvRepository.SaveWorshipAndReligiousUnderstanding(ctx, worshipAndReligiousUnderstanding)
|
| 264 |
+
if err != nil {
|
| 265 |
+
return nil, response.HandleGormError(err, "Internal Server Error")
|
| 266 |
+
}
|
| 267 |
+
|
| 268 |
+
return res, nil
|
| 269 |
+
}
|
| 270 |
+
|
| 271 |
+
func (s *cvService) GetWorshipAndReligiousUnderstanding(ctx context.Context, id int64) (*models.WorshipAndReligiousUnderstandingCV, error) {
|
| 272 |
+
res, err := s.cvRepository.GetWorshipAndReligiousUnderstandingByAccountID(ctx, id)
|
| 273 |
+
if err != nil {
|
| 274 |
+
return nil, response.HandleGormError(err, "Data agama dan pemahaman agama tidak ditemukan")
|
| 275 |
+
}
|
| 276 |
+
return res, nil
|
| 277 |
+
}
|
space/space/space/space/space/space/space/.gitignore
CHANGED
|
@@ -6,3 +6,4 @@ README.md
|
|
| 6 |
.error
|
| 7 |
logs/
|
| 8 |
.idea
|
|
|
|
|
|
| 6 |
.error
|
| 7 |
logs/
|
| 8 |
.idea
|
| 9 |
+
my-notes
|
space/space/space/space/space/space/space/controller/health_check/health_check_controller.go
CHANGED
|
@@ -3,29 +3,33 @@ package health_check_controller
|
|
| 3 |
import (
|
| 4 |
"api.qobiltu.id/models"
|
| 5 |
"api.qobiltu.id/response"
|
| 6 |
-
"api.qobiltu.id/services
|
| 7 |
"github.com/gin-gonic/gin"
|
| 8 |
"net/http"
|
| 9 |
)
|
| 10 |
|
| 11 |
-
type HealthCheckController
|
| 12 |
-
|
| 13 |
}
|
| 14 |
|
| 15 |
-
|
| 16 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
healthCheckService: healthCheckService,
|
| 18 |
}
|
| 19 |
}
|
| 20 |
|
| 21 |
-
func (
|
| 22 |
req := models.HealthCheckRequest{}
|
| 23 |
|
| 24 |
-
res, err :=
|
| 25 |
if err != nil {
|
| 26 |
response.HandleError(ctx, err)
|
| 27 |
return
|
| 28 |
}
|
| 29 |
|
| 30 |
-
response.HandleSuccess(ctx, "Service
|
| 31 |
}
|
|
|
|
| 3 |
import (
|
| 4 |
"api.qobiltu.id/models"
|
| 5 |
"api.qobiltu.id/response"
|
| 6 |
+
"api.qobiltu.id/services"
|
| 7 |
"github.com/gin-gonic/gin"
|
| 8 |
"net/http"
|
| 9 |
)
|
| 10 |
|
| 11 |
+
type HealthCheckController interface {
|
| 12 |
+
Check(ctx *gin.Context)
|
| 13 |
}
|
| 14 |
|
| 15 |
+
type healthCheckController struct {
|
| 16 |
+
healthCheckService services.HealthCheckService
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
func NewHealthCheckController(healthCheckService services.HealthCheckService) HealthCheckController {
|
| 20 |
+
return &healthCheckController{
|
| 21 |
healthCheckService: healthCheckService,
|
| 22 |
}
|
| 23 |
}
|
| 24 |
|
| 25 |
+
func (c *healthCheckController) Check(ctx *gin.Context) {
|
| 26 |
req := models.HealthCheckRequest{}
|
| 27 |
|
| 28 |
+
res, err := c.healthCheckService.Check(ctx, &req)
|
| 29 |
if err != nil {
|
| 30 |
response.HandleError(ctx, err)
|
| 31 |
return
|
| 32 |
}
|
| 33 |
|
| 34 |
+
response.HandleSuccess(ctx, http.StatusOK, "Service OK", res, nil)
|
| 35 |
}
|
space/space/space/space/space/space/space/main.go
CHANGED
|
@@ -6,7 +6,7 @@ import (
|
|
| 6 |
"api.qobiltu.id/mail"
|
| 7 |
"api.qobiltu.id/repositories"
|
| 8 |
"api.qobiltu.id/router"
|
| 9 |
-
"api.qobiltu.id/services
|
| 10 |
"api.qobiltu.id/utils"
|
| 11 |
"api.qobiltu.id/worker"
|
| 12 |
"github.com/hibiken/asynq"
|
|
@@ -43,7 +43,7 @@ func main() {
|
|
| 43 |
|
| 44 |
// setup repo, service, and controller
|
| 45 |
healthCheckRepository := repositories.NewHealthCheckRepository(config.DB)
|
| 46 |
-
healthCheckService :=
|
| 47 |
healthCheckController := health_check_controller.NewHealthCheckController(healthCheckService)
|
| 48 |
|
| 49 |
// start task processor
|
|
|
|
| 6 |
"api.qobiltu.id/mail"
|
| 7 |
"api.qobiltu.id/repositories"
|
| 8 |
"api.qobiltu.id/router"
|
| 9 |
+
"api.qobiltu.id/services"
|
| 10 |
"api.qobiltu.id/utils"
|
| 11 |
"api.qobiltu.id/worker"
|
| 12 |
"github.com/hibiken/asynq"
|
|
|
|
| 43 |
|
| 44 |
// setup repo, service, and controller
|
| 45 |
healthCheckRepository := repositories.NewHealthCheckRepository(config.DB)
|
| 46 |
+
healthCheckService := services.NewHealthCheckService(healthCheckRepository)
|
| 47 |
healthCheckController := health_check_controller.NewHealthCheckController(healthCheckService)
|
| 48 |
|
| 49 |
// start task processor
|
space/space/space/space/space/space/space/models/database_orm_model.go
CHANGED
|
@@ -1,207 +1,207 @@
|
|
| 1 |
-
package models
|
| 2 |
-
|
| 3 |
-
import (
|
| 4 |
-
"time"
|
| 5 |
-
|
| 6 |
-
uuid "github.com/satori/go.uuid"
|
| 7 |
-
)
|
| 8 |
-
|
| 9 |
-
type Account struct {
|
| 10 |
-
Id uint `gorm:"primaryKey" json:"id"`
|
| 11 |
-
UUID uuid.UUID `gorm:"type:uuid" json:"uuid" `
|
| 12 |
-
Email string `gorm:"uniqueIndex" json:"email"`
|
| 13 |
-
Password string `json:"password"`
|
| 14 |
-
IsEmailVerified bool `json:"is_email_verified"`
|
| 15 |
-
IsDetailCompleted bool `json:"is_detail_completed"`
|
| 16 |
-
CreatedAt time.Time `json:"created_at"`
|
| 17 |
-
DeletedAt *time.Time `json:"deleted_at" gorm:"default:null"`
|
| 18 |
-
}
|
| 19 |
-
|
| 20 |
-
type AccountDetails struct {
|
| 21 |
-
ID
|
| 22 |
-
AccountID uint `json:"account_id"`
|
| 23 |
-
InitialName string `json:"initial_name"`
|
| 24 |
-
FullName *string `json:"full_name"`
|
| 25 |
-
DateOfBirth *time.Time `json:"date_of_birth"`
|
| 26 |
-
PlaceOfBirth *string `json:"place_of_birth"`
|
| 27 |
-
Domicile *string `json:"domicile"`
|
| 28 |
-
LastJob *string `json:"last_job"`
|
| 29 |
-
Gender *
|
| 30 |
-
LastEducation *string `json:"last_education"`
|
| 31 |
-
MaritalStatus *string `json:"marital_status"`
|
| 32 |
-
Avatar *string `json:"avatar"`
|
| 33 |
-
PhoneNumber *string `json:"phone_number"`
|
| 34 |
-
}
|
| 35 |
-
|
| 36 |
-
type EmailVerification struct {
|
| 37 |
-
ID uint `gorm:"primaryKey" json:"id"`
|
| 38 |
-
UUID uuid.UUID `gorm:"type:uuid" json:"uuid" `
|
| 39 |
-
Token uint `json:"token"`
|
| 40 |
-
AccountID uint `json:"account_id"`
|
| 41 |
-
IsExpired bool `json:"is_expired"`
|
| 42 |
-
CreatedAt time.Time `json:"created_at"`
|
| 43 |
-
ExpiredAt time.Time `json:"expired_at"`
|
| 44 |
-
}
|
| 45 |
-
|
| 46 |
-
type ExternalAuth struct {
|
| 47 |
-
ID uint `gorm:"primaryKey" json:"id"`
|
| 48 |
-
UUID uuid.UUID `gorm:"type:uuid" json:"uuid" `
|
| 49 |
-
OauthID string `json:"oauth_id"`
|
| 50 |
-
AccountID uint `json:"account_id"`
|
| 51 |
-
OauthProvider string `json:"oauth_provider"`
|
| 52 |
-
}
|
| 53 |
-
|
| 54 |
-
type FCM struct {
|
| 55 |
-
ID uint `gorm:"primaryKey" json:"id"`
|
| 56 |
-
AccountID uint `json:"account_id"`
|
| 57 |
-
FCMToken string `json:"fcm_token"`
|
| 58 |
-
}
|
| 59 |
-
|
| 60 |
-
type ForgotPassword struct {
|
| 61 |
-
ID uint `gorm:"primaryKey" json:"id"`
|
| 62 |
-
UUID uuid.UUID `gorm:"type:uuid" json:"uuid" `
|
| 63 |
-
Token uint `json:"token"`
|
| 64 |
-
AccountID uint `json:"account_id"`
|
| 65 |
-
IsExpired bool `json:"is_expired"`
|
| 66 |
-
CreatedAt time.Time `json:"created_at"`
|
| 67 |
-
ExpiredAt time.Time `json:"expired_at"`
|
| 68 |
-
}
|
| 69 |
-
|
| 70 |
-
type Academy struct {
|
| 71 |
-
ID uint `gorm:"primaryKey" json:"id"`
|
| 72 |
-
UUID uuid.UUID `gorm:"type:uuid" json:"uuid"`
|
| 73 |
-
Title string `json:"title"`
|
| 74 |
-
Slug string `json:"slug" gorm:"uniqueIndex" `
|
| 75 |
-
TotalMaterial int `json:"total_material"`
|
| 76 |
-
CompletedMaterial int `json:"completed_material"`
|
| 77 |
-
IsCompletedRead bool `json:"is_read"`
|
| 78 |
-
IsPassedExam bool `json:"is_exam"`
|
| 79 |
-
Description string `json:"description"`
|
| 80 |
-
}
|
| 81 |
-
|
| 82 |
-
type AcademyMaterial struct {
|
| 83 |
-
ID uint `gorm:"primaryKey" json:"id"`
|
| 84 |
-
UUID uuid.UUID `gorm:"type:uuid" json:"uuid"`
|
| 85 |
-
AcademyID uint `json:"academy_id"`
|
| 86 |
-
Title string `json:"title"`
|
| 87 |
-
Slug string `json:"slug" gorm:"uniqueIndex"`
|
| 88 |
-
IsCompleted bool `json:"is_completed"`
|
| 89 |
-
Description string `json:"description"`
|
| 90 |
-
}
|
| 91 |
-
|
| 92 |
-
type AcademyContent struct {
|
| 93 |
-
ID uint `gorm:"primaryKey" json:"id"`
|
| 94 |
-
UUID uuid.UUID `json:"uuid"`
|
| 95 |
-
Title string `json:"title"`
|
| 96 |
-
Order uint `json:"order"`
|
| 97 |
-
AcademyMaterialID uint `json:"academy_material_id"`
|
| 98 |
-
Description string `json:"description"`
|
| 99 |
-
}
|
| 100 |
-
type OptionCategory struct {
|
| 101 |
-
ID uint `gorm:"primaryKey" json:"id"`
|
| 102 |
-
OptionName string `json:"option_name"`
|
| 103 |
-
OptionSlug string `json:"option_slug" gorm:"uniqueIndex"`
|
| 104 |
-
}
|
| 105 |
-
|
| 106 |
-
type OptionValues struct {
|
| 107 |
-
ID uint `gorm:"primaryKey" json:"id"`
|
| 108 |
-
OptionCategoryID uint `json:"option_category_id"`
|
| 109 |
-
OptionValue string `json:"option_value"`
|
| 110 |
-
}
|
| 111 |
-
type AcademyMaterialProgress struct {
|
| 112 |
-
ID uint `gorm:"primaryKey" json:"id"`
|
| 113 |
-
UUID uuid.UUID `gorm:"type:uuid" json:"uuid"`
|
| 114 |
-
AccountID uint `json:"account_id"`
|
| 115 |
-
AcademyMaterialID uint `json:"academy_material_id"`
|
| 116 |
-
Progress uint `json:"progress"`
|
| 117 |
-
}
|
| 118 |
-
|
| 119 |
-
type AcademyContentProgress struct {
|
| 120 |
-
ID uint `gorm:"primaryKey" json:"id"`
|
| 121 |
-
UUID uuid.UUID `gorm:"type:uuid" json:"uuid"`
|
| 122 |
-
AccountID uint `json:"account_id"`
|
| 123 |
-
AcademyID uint `json:"academy_id"`
|
| 124 |
-
}
|
| 125 |
-
|
| 126 |
-
type RegionProvince struct {
|
| 127 |
-
ID uint `json:"id"`
|
| 128 |
-
Name string `json:"name"`
|
| 129 |
-
Code string `json:"code"`
|
| 130 |
-
}
|
| 131 |
-
|
| 132 |
-
type RegionCity struct {
|
| 133 |
-
ID uint `json:"id"`
|
| 134 |
-
Type string `json:"type"`
|
| 135 |
-
Name string `json:"name"`
|
| 136 |
-
Code string `json:"code"`
|
| 137 |
-
FullCode string `json:"full_code"`
|
| 138 |
-
ProvinceID uint `json:"province_id"`
|
| 139 |
-
}
|
| 140 |
-
type Answer struct {
|
| 141 |
-
ID uint `gorm:"primaryKey" json:"id"`
|
| 142 |
-
QuestionID uint `json:"question_id"`
|
| 143 |
-
Content string `json:"content"`
|
| 144 |
-
IsCorrect bool `json:"-"`
|
| 145 |
-
}
|
| 146 |
-
type Question struct {
|
| 147 |
-
ID uint `gorm:"primaryKey" json:"id"`
|
| 148 |
-
QuizID uint `json:"quiz_id"`
|
| 149 |
-
Content string `json:"content"`
|
| 150 |
-
Order int `json:"order"`
|
| 151 |
-
CorrectAnswer uint `json:"-"`
|
| 152 |
-
}
|
| 153 |
-
type Quiz struct {
|
| 154 |
-
ID uint `gorm:"primaryKey" json:"id"`
|
| 155 |
-
AcademyID uint `json:"academy_id"`
|
| 156 |
-
Title string `json:"title"`
|
| 157 |
-
Description string `json:"description"`
|
| 158 |
-
AttemptLimit int `json:"attempt_limit"`
|
| 159 |
-
TimeLimit int `json:"time_limit"`
|
| 160 |
-
MinScore int `json:"min_score"`
|
| 161 |
-
CreatedAt time.Time `json:"created_at"`
|
| 162 |
-
}
|
| 163 |
-
|
| 164 |
-
type QuizAttempt struct {
|
| 165 |
-
ID uint `gorm:"primaryKey" json:"id"`
|
| 166 |
-
AccountID uint `json:"user_id"`
|
| 167 |
-
QuizID uint `json:"quiz_id"`
|
| 168 |
-
StartedAt time.Time `json:"started_at"`
|
| 169 |
-
DueAt time.Time `json:"due_at"`
|
| 170 |
-
FinishedAt *time.Time `json:"finished_at"`
|
| 171 |
-
Score float64 `json:"score"`
|
| 172 |
-
}
|
| 173 |
-
type UserAnswer struct {
|
| 174 |
-
ID uint `gorm:"primaryKey" json:"id"`
|
| 175 |
-
QuizAttemptID uint `json:"quiz_attempt_id"`
|
| 176 |
-
QuestionID uint `json:"question_id"`
|
| 177 |
-
SelectedAnswer uint `json:"selected_answer"`
|
| 178 |
-
IsCorrect bool `json:"is_correct"`
|
| 179 |
-
}
|
| 180 |
-
type QuizResult struct {
|
| 181 |
-
QuizAttemptID uint `gorm:"column:quiz_attempt_id" json:"quiz_attempt_id"`
|
| 182 |
-
TotalQuestions int `gorm:"column:total_questions" json:"total_questions"`
|
| 183 |
-
CorrectAnswers int `gorm:"column:correct_answers" json:"correct_answers"`
|
| 184 |
-
AverageScore float64 `gorm:"column:average_score" json:"average_score"`
|
| 185 |
-
}
|
| 186 |
-
|
| 187 |
-
// Gorm table name settings
|
| 188 |
-
func (Account) TableName() string { return "account" }
|
| 189 |
-
func (AccountDetails) TableName() string { return "account_details" }
|
| 190 |
-
func (EmailVerification) TableName() string { return "email_verifications" }
|
| 191 |
-
func (ExternalAuth) TableName() string { return "extern_auth" }
|
| 192 |
-
func (FCM) TableName() string { return "fcm" }
|
| 193 |
-
func (ForgotPassword) TableName() string { return "forgot_password" }
|
| 194 |
-
func (Academy) TableName() string { return "academy" }
|
| 195 |
-
func (AcademyMaterial) TableName() string { return "academy_materials" }
|
| 196 |
-
func (AcademyContent) TableName() string { return "academy_contents" }
|
| 197 |
-
func (AcademyMaterialProgress) TableName() string { return "academy_materials_progress" }
|
| 198 |
-
func (AcademyContentProgress) TableName() string { return "academy_contents_progress" }
|
| 199 |
-
func (RegionProvince) TableName() string { return "region_provinces" }
|
| 200 |
-
func (RegionCity) TableName() string { return "region_cities" }
|
| 201 |
-
func (Answer) TableName() string { return "answers" }
|
| 202 |
-
func (Question) TableName() string { return "questions" }
|
| 203 |
-
func (Quiz) TableName() string { return "quizzes" }
|
| 204 |
-
func (QuizAttempt) TableName() string { return "quiz_attempts" }
|
| 205 |
-
func (UserAnswer) TableName() string { return "user_answers" }
|
| 206 |
-
func (OptionCategory) TableName() string { return "option_categories" }
|
| 207 |
-
func (OptionValues) TableName() string { return "option_values" }
|
|
|
|
| 1 |
+
package models
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"time"
|
| 5 |
+
|
| 6 |
+
uuid "github.com/satori/go.uuid"
|
| 7 |
+
)
|
| 8 |
+
|
| 9 |
+
type Account struct {
|
| 10 |
+
Id uint `gorm:"primaryKey" json:"id"`
|
| 11 |
+
UUID uuid.UUID `gorm:"type:uuid" json:"uuid" `
|
| 12 |
+
Email string `gorm:"uniqueIndex" json:"email"`
|
| 13 |
+
Password string `json:"password"`
|
| 14 |
+
IsEmailVerified bool `json:"is_email_verified"`
|
| 15 |
+
IsDetailCompleted bool `json:"is_detail_completed"`
|
| 16 |
+
CreatedAt time.Time `json:"created_at"`
|
| 17 |
+
DeletedAt *time.Time `json:"deleted_at" gorm:"default:null"`
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
type AccountDetails struct {
|
| 21 |
+
ID uint64 `gorm:"primaryKey" json:"id"`
|
| 22 |
+
AccountID uint `json:"account_id"`
|
| 23 |
+
InitialName string `json:"initial_name"`
|
| 24 |
+
FullName *string `json:"full_name"`
|
| 25 |
+
DateOfBirth *time.Time `json:"date_of_birth"`
|
| 26 |
+
PlaceOfBirth *string `json:"place_of_birth"`
|
| 27 |
+
Domicile *string `json:"domicile"`
|
| 28 |
+
LastJob *string `json:"last_job"`
|
| 29 |
+
Gender *string `json:"gender"`
|
| 30 |
+
LastEducation *string `json:"last_education"`
|
| 31 |
+
MaritalStatus *string `json:"marital_status"`
|
| 32 |
+
Avatar *string `json:"avatar"`
|
| 33 |
+
PhoneNumber *string `json:"phone_number"`
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
type EmailVerification struct {
|
| 37 |
+
ID uint `gorm:"primaryKey" json:"id"`
|
| 38 |
+
UUID uuid.UUID `gorm:"type:uuid" json:"uuid" `
|
| 39 |
+
Token uint `json:"token"`
|
| 40 |
+
AccountID uint `json:"account_id"`
|
| 41 |
+
IsExpired bool `json:"is_expired"`
|
| 42 |
+
CreatedAt time.Time `json:"created_at"`
|
| 43 |
+
ExpiredAt time.Time `json:"expired_at"`
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
type ExternalAuth struct {
|
| 47 |
+
ID uint `gorm:"primaryKey" json:"id"`
|
| 48 |
+
UUID uuid.UUID `gorm:"type:uuid" json:"uuid" `
|
| 49 |
+
OauthID string `json:"oauth_id"`
|
| 50 |
+
AccountID uint `json:"account_id"`
|
| 51 |
+
OauthProvider string `json:"oauth_provider"`
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
type FCM struct {
|
| 55 |
+
ID uint `gorm:"primaryKey" json:"id"`
|
| 56 |
+
AccountID uint `json:"account_id"`
|
| 57 |
+
FCMToken string `json:"fcm_token"`
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
type ForgotPassword struct {
|
| 61 |
+
ID uint `gorm:"primaryKey" json:"id"`
|
| 62 |
+
UUID uuid.UUID `gorm:"type:uuid" json:"uuid" `
|
| 63 |
+
Token uint `json:"token"`
|
| 64 |
+
AccountID uint `json:"account_id"`
|
| 65 |
+
IsExpired bool `json:"is_expired"`
|
| 66 |
+
CreatedAt time.Time `json:"created_at"`
|
| 67 |
+
ExpiredAt time.Time `json:"expired_at"`
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
type Academy struct {
|
| 71 |
+
ID uint `gorm:"primaryKey" json:"id"`
|
| 72 |
+
UUID uuid.UUID `gorm:"type:uuid" json:"uuid"`
|
| 73 |
+
Title string `json:"title"`
|
| 74 |
+
Slug string `json:"slug" gorm:"uniqueIndex" `
|
| 75 |
+
TotalMaterial int `json:"total_material"`
|
| 76 |
+
CompletedMaterial int `json:"completed_material"`
|
| 77 |
+
IsCompletedRead bool `json:"is_read"`
|
| 78 |
+
IsPassedExam bool `json:"is_exam"`
|
| 79 |
+
Description string `json:"description"`
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
type AcademyMaterial struct {
|
| 83 |
+
ID uint `gorm:"primaryKey" json:"id"`
|
| 84 |
+
UUID uuid.UUID `gorm:"type:uuid" json:"uuid"`
|
| 85 |
+
AcademyID uint `json:"academy_id"`
|
| 86 |
+
Title string `json:"title"`
|
| 87 |
+
Slug string `json:"slug" gorm:"uniqueIndex"`
|
| 88 |
+
IsCompleted bool `json:"is_completed"`
|
| 89 |
+
Description string `json:"description"`
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
type AcademyContent struct {
|
| 93 |
+
ID uint `gorm:"primaryKey" json:"id"`
|
| 94 |
+
UUID uuid.UUID `json:"uuid"`
|
| 95 |
+
Title string `json:"title"`
|
| 96 |
+
Order uint `json:"order"`
|
| 97 |
+
AcademyMaterialID uint `json:"academy_material_id"`
|
| 98 |
+
Description string `json:"description"`
|
| 99 |
+
}
|
| 100 |
+
type OptionCategory struct {
|
| 101 |
+
ID uint `gorm:"primaryKey" json:"id"`
|
| 102 |
+
OptionName string `json:"option_name"`
|
| 103 |
+
OptionSlug string `json:"option_slug" gorm:"uniqueIndex"`
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
type OptionValues struct {
|
| 107 |
+
ID uint `gorm:"primaryKey" json:"id"`
|
| 108 |
+
OptionCategoryID uint `json:"option_category_id"`
|
| 109 |
+
OptionValue string `json:"option_value"`
|
| 110 |
+
}
|
| 111 |
+
type AcademyMaterialProgress struct {
|
| 112 |
+
ID uint `gorm:"primaryKey" json:"id"`
|
| 113 |
+
UUID uuid.UUID `gorm:"type:uuid" json:"uuid"`
|
| 114 |
+
AccountID uint `json:"account_id"`
|
| 115 |
+
AcademyMaterialID uint `json:"academy_material_id"`
|
| 116 |
+
Progress uint `json:"progress"`
|
| 117 |
+
}
|
| 118 |
+
|
| 119 |
+
type AcademyContentProgress struct {
|
| 120 |
+
ID uint `gorm:"primaryKey" json:"id"`
|
| 121 |
+
UUID uuid.UUID `gorm:"type:uuid" json:"uuid"`
|
| 122 |
+
AccountID uint `json:"account_id"`
|
| 123 |
+
AcademyID uint `json:"academy_id"`
|
| 124 |
+
}
|
| 125 |
+
|
| 126 |
+
type RegionProvince struct {
|
| 127 |
+
ID uint `json:"id"`
|
| 128 |
+
Name string `json:"name"`
|
| 129 |
+
Code string `json:"code"`
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
type RegionCity struct {
|
| 133 |
+
ID uint `json:"id"`
|
| 134 |
+
Type string `json:"type"`
|
| 135 |
+
Name string `json:"name"`
|
| 136 |
+
Code string `json:"code"`
|
| 137 |
+
FullCode string `json:"full_code"`
|
| 138 |
+
ProvinceID uint `json:"province_id"`
|
| 139 |
+
}
|
| 140 |
+
type Answer struct {
|
| 141 |
+
ID uint `gorm:"primaryKey" json:"id"`
|
| 142 |
+
QuestionID uint `json:"question_id"`
|
| 143 |
+
Content string `json:"content"`
|
| 144 |
+
IsCorrect bool `json:"-"`
|
| 145 |
+
}
|
| 146 |
+
type Question struct {
|
| 147 |
+
ID uint `gorm:"primaryKey" json:"id"`
|
| 148 |
+
QuizID uint `json:"quiz_id"`
|
| 149 |
+
Content string `json:"content"`
|
| 150 |
+
Order int `json:"order"`
|
| 151 |
+
CorrectAnswer uint `json:"-"`
|
| 152 |
+
}
|
| 153 |
+
type Quiz struct {
|
| 154 |
+
ID uint `gorm:"primaryKey" json:"id"`
|
| 155 |
+
AcademyID uint `json:"academy_id"`
|
| 156 |
+
Title string `json:"title"`
|
| 157 |
+
Description string `json:"description"`
|
| 158 |
+
AttemptLimit int `json:"attempt_limit"`
|
| 159 |
+
TimeLimit int `json:"time_limit"`
|
| 160 |
+
MinScore int `json:"min_score"`
|
| 161 |
+
CreatedAt time.Time `json:"created_at"`
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
type QuizAttempt struct {
|
| 165 |
+
ID uint `gorm:"primaryKey" json:"id"`
|
| 166 |
+
AccountID uint `json:"user_id"`
|
| 167 |
+
QuizID uint `json:"quiz_id"`
|
| 168 |
+
StartedAt time.Time `json:"started_at"`
|
| 169 |
+
DueAt time.Time `json:"due_at"`
|
| 170 |
+
FinishedAt *time.Time `json:"finished_at"`
|
| 171 |
+
Score float64 `json:"score"`
|
| 172 |
+
}
|
| 173 |
+
type UserAnswer struct {
|
| 174 |
+
ID uint `gorm:"primaryKey" json:"id"`
|
| 175 |
+
QuizAttemptID uint `json:"quiz_attempt_id"`
|
| 176 |
+
QuestionID uint `json:"question_id"`
|
| 177 |
+
SelectedAnswer uint `json:"selected_answer"`
|
| 178 |
+
IsCorrect bool `json:"is_correct"`
|
| 179 |
+
}
|
| 180 |
+
type QuizResult struct {
|
| 181 |
+
QuizAttemptID uint `gorm:"column:quiz_attempt_id" json:"quiz_attempt_id"`
|
| 182 |
+
TotalQuestions int `gorm:"column:total_questions" json:"total_questions"`
|
| 183 |
+
CorrectAnswers int `gorm:"column:correct_answers" json:"correct_answers"`
|
| 184 |
+
AverageScore float64 `gorm:"column:average_score" json:"average_score"`
|
| 185 |
+
}
|
| 186 |
+
|
| 187 |
+
// Gorm table name settings
|
| 188 |
+
func (Account) TableName() string { return "account" }
|
| 189 |
+
func (AccountDetails) TableName() string { return "account_details" }
|
| 190 |
+
func (EmailVerification) TableName() string { return "email_verifications" }
|
| 191 |
+
func (ExternalAuth) TableName() string { return "extern_auth" }
|
| 192 |
+
func (FCM) TableName() string { return "fcm" }
|
| 193 |
+
func (ForgotPassword) TableName() string { return "forgot_password" }
|
| 194 |
+
func (Academy) TableName() string { return "academy" }
|
| 195 |
+
func (AcademyMaterial) TableName() string { return "academy_materials" }
|
| 196 |
+
func (AcademyContent) TableName() string { return "academy_contents" }
|
| 197 |
+
func (AcademyMaterialProgress) TableName() string { return "academy_materials_progress" }
|
| 198 |
+
func (AcademyContentProgress) TableName() string { return "academy_contents_progress" }
|
| 199 |
+
func (RegionProvince) TableName() string { return "region_provinces" }
|
| 200 |
+
func (RegionCity) TableName() string { return "region_cities" }
|
| 201 |
+
func (Answer) TableName() string { return "answers" }
|
| 202 |
+
func (Question) TableName() string { return "questions" }
|
| 203 |
+
func (Quiz) TableName() string { return "quizzes" }
|
| 204 |
+
func (QuizAttempt) TableName() string { return "quiz_attempts" }
|
| 205 |
+
func (UserAnswer) TableName() string { return "user_answers" }
|
| 206 |
+
func (OptionCategory) TableName() string { return "option_categories" }
|
| 207 |
+
func (OptionValues) TableName() string { return "option_values" }
|
space/space/space/space/space/space/space/models/exception_model.go
CHANGED
|
@@ -1,17 +1,23 @@
|
|
| 1 |
package models
|
| 2 |
|
| 3 |
type Exception struct {
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
}
|
|
|
|
| 1 |
package models
|
| 2 |
|
| 3 |
type Exception struct {
|
| 4 |
+
Unauthorized bool `json:"unauthorized,omitempty"`
|
| 5 |
+
BadRequest bool `json:"bad_request,omitempty"`
|
| 6 |
+
DataNotFound bool `json:"data_not_found,omitempty"`
|
| 7 |
+
InternalServerError bool `json:"internal_server_error,omitempty"`
|
| 8 |
+
DataDuplicate bool `json:"data_duplicate,omitempty"`
|
| 9 |
+
QueryError bool `json:"query_error,omitempty"`
|
| 10 |
+
InvalidPasswordLength bool `json:"invalid_password_length,omitempty"`
|
| 11 |
+
IsPassTheLimit bool `json:"is_pass_the_limit,omitempty"`
|
| 12 |
+
IsTimeOut bool `json:"is_time_out,omitempty"`
|
| 13 |
+
AttemptNotFound bool `json:"attempt_not_found,omitempty"`
|
| 14 |
+
Forbidden bool `json:"forbidden,omitempty"`
|
| 15 |
+
ValidationError bool `json:"validation_error,omitempty"`
|
| 16 |
+
|
| 17 |
+
Message string `json:"message,omitempty"`
|
| 18 |
+
Err error `json:"-"`
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
func (a Exception) Error() string {
|
| 22 |
+
return a.Err.Error()
|
| 23 |
}
|
space/space/space/space/space/space/space/models/health_check_model.go
CHANGED
|
@@ -1,8 +1,6 @@
|
|
| 1 |
package models
|
| 2 |
|
| 3 |
-
type HealthCheckRequest struct
|
| 4 |
-
ExampleCallback func() (string, string)
|
| 5 |
-
}
|
| 6 |
|
| 7 |
type HealthCheckResponse struct {
|
| 8 |
DatabaseStatus string `json:"database_status"`
|
|
|
|
| 1 |
package models
|
| 2 |
|
| 3 |
+
type HealthCheckRequest struct{}
|
|
|
|
|
|
|
| 4 |
|
| 5 |
type HealthCheckResponse struct {
|
| 6 |
DatabaseStatus string `json:"database_status"`
|
space/space/space/space/space/space/space/repositories/health_check_repository.go
CHANGED
|
@@ -7,29 +7,25 @@ import (
|
|
| 7 |
"gorm.io/gorm"
|
| 8 |
)
|
| 9 |
|
| 10 |
-
type HealthCheckRepository
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
db *gorm.DB
|
| 12 |
}
|
| 13 |
|
| 14 |
-
func NewHealthCheckRepository(db *gorm.DB)
|
| 15 |
-
return &
|
| 16 |
db: db,
|
| 17 |
}
|
| 18 |
}
|
| 19 |
|
| 20 |
-
func (r *
|
| 21 |
-
res := &models.HealthCheckResponse{}
|
| 22 |
-
|
| 23 |
err := config.RunTx(ctx, r.db, func(tx *gorm.DB) error {
|
| 24 |
if err := tx.Exec("SELECT 1").Error; err != nil {
|
| 25 |
return err
|
| 26 |
}
|
| 27 |
-
|
| 28 |
-
// call logic from service if needed
|
| 29 |
-
// instead of writing the logic in the repository
|
| 30 |
-
// and make sure the param consist of the ctx and request
|
| 31 |
-
res.DatabaseStatus, res.RedisStatus = req.ExampleCallback()
|
| 32 |
-
|
| 33 |
return nil
|
| 34 |
})
|
| 35 |
|
|
@@ -37,5 +33,8 @@ func (r *HealthCheckRepository) Check(ctx context.Context, req *models.HealthChe
|
|
| 37 |
return nil, err
|
| 38 |
}
|
| 39 |
|
| 40 |
-
return
|
|
|
|
|
|
|
|
|
|
| 41 |
}
|
|
|
|
| 7 |
"gorm.io/gorm"
|
| 8 |
)
|
| 9 |
|
| 10 |
+
type HealthCheckRepository interface {
|
| 11 |
+
Check(ctx context.Context, req *models.HealthCheckRequest) (*models.HealthCheckResponse, error)
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
type healthCheckRepository struct {
|
| 15 |
db *gorm.DB
|
| 16 |
}
|
| 17 |
|
| 18 |
+
func NewHealthCheckRepository(db *gorm.DB) HealthCheckRepository {
|
| 19 |
+
return &healthCheckRepository{
|
| 20 |
db: db,
|
| 21 |
}
|
| 22 |
}
|
| 23 |
|
| 24 |
+
func (r *healthCheckRepository) Check(ctx context.Context, req *models.HealthCheckRequest) (*models.HealthCheckResponse, error) {
|
|
|
|
|
|
|
| 25 |
err := config.RunTx(ctx, r.db, func(tx *gorm.DB) error {
|
| 26 |
if err := tx.Exec("SELECT 1").Error; err != nil {
|
| 27 |
return err
|
| 28 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
return nil
|
| 30 |
})
|
| 31 |
|
|
|
|
| 33 |
return nil, err
|
| 34 |
}
|
| 35 |
|
| 36 |
+
return &models.HealthCheckResponse{
|
| 37 |
+
DatabaseStatus: "OK",
|
| 38 |
+
RedisStatus: "OK",
|
| 39 |
+
}, nil
|
| 40 |
}
|
space/space/space/space/space/space/space/response/api_response_v2.go
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package response
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"api.qobiltu.id/models"
|
| 5 |
+
"api.qobiltu.id/utils"
|
| 6 |
+
"errors"
|
| 7 |
+
"net/http"
|
| 8 |
+
|
| 9 |
+
"github.com/gin-gonic/gin"
|
| 10 |
+
)
|
| 11 |
+
|
| 12 |
+
func HandleError(c *gin.Context, err error) {
|
| 13 |
+
var exception models.Exception
|
| 14 |
+
|
| 15 |
+
if errors.As(err, &exception) {
|
| 16 |
+
utils.LogError(exception.Err)
|
| 17 |
+
|
| 18 |
+
switch {
|
| 19 |
+
case exception.DataDuplicate:
|
| 20 |
+
responseError(c, http.StatusConflict, exception)
|
| 21 |
+
case exception.Unauthorized:
|
| 22 |
+
responseError(c, http.StatusUnauthorized, exception)
|
| 23 |
+
case exception.DataNotFound:
|
| 24 |
+
responseError(c, http.StatusNotFound, exception)
|
| 25 |
+
case exception.Forbidden:
|
| 26 |
+
responseError(c, http.StatusForbidden, exception)
|
| 27 |
+
case exception.BadRequest:
|
| 28 |
+
responseError(c, http.StatusBadRequest, exception)
|
| 29 |
+
case exception.InternalServerError:
|
| 30 |
+
responseError(c, http.StatusInternalServerError, exception)
|
| 31 |
+
case exception.QueryError:
|
| 32 |
+
responseError(c, http.StatusInternalServerError, exception)
|
| 33 |
+
case exception.InvalidPasswordLength:
|
| 34 |
+
responseError(c, http.StatusBadRequest, exception)
|
| 35 |
+
case exception.IsPassTheLimit:
|
| 36 |
+
responseError(c, http.StatusTooManyRequests, exception)
|
| 37 |
+
case exception.IsTimeOut:
|
| 38 |
+
responseError(c, http.StatusRequestTimeout, exception)
|
| 39 |
+
case exception.AttemptNotFound:
|
| 40 |
+
responseError(c, http.StatusNotFound, exception)
|
| 41 |
+
case exception.ValidationError:
|
| 42 |
+
responseError(c, http.StatusUnprocessableEntity, exception)
|
| 43 |
+
default:
|
| 44 |
+
responseError(c, http.StatusInternalServerError, exception)
|
| 45 |
+
}
|
| 46 |
+
} else {
|
| 47 |
+
utils.LogError(err)
|
| 48 |
+
responseError(c, http.StatusInternalServerError, models.Exception{
|
| 49 |
+
InternalServerError: true,
|
| 50 |
+
Message: "Internal Server Error",
|
| 51 |
+
})
|
| 52 |
+
}
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
func HandleSuccess(c *gin.Context, status int, msg string, data any, metaData any) {
|
| 56 |
+
res := models.SuccessResponse{
|
| 57 |
+
Status: "success",
|
| 58 |
+
Message: msg,
|
| 59 |
+
Data: data,
|
| 60 |
+
MetaData: metaData,
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
c.JSON(status, res)
|
| 64 |
+
return
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
func responseError(c *gin.Context, status int, exception models.Exception) {
|
| 68 |
+
message := exception.Message
|
| 69 |
+
exception.Message = ""
|
| 70 |
+
|
| 71 |
+
res := models.ErrorResponse{
|
| 72 |
+
Status: "error",
|
| 73 |
+
Message: message,
|
| 74 |
+
Errors: exception,
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
c.AbortWithStatusJSON(status, res)
|
| 78 |
+
return
|
| 79 |
+
}
|
space/space/space/space/space/space/space/response/gorm.go
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package response
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"api.qobiltu.id/models"
|
| 5 |
+
"errors"
|
| 6 |
+
"strings"
|
| 7 |
+
|
| 8 |
+
"gorm.io/gorm"
|
| 9 |
+
)
|
| 10 |
+
|
| 11 |
+
func HandleGormError(err error, fallbackMessage string) error {
|
| 12 |
+
if err == nil {
|
| 13 |
+
return nil
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
if errors.Is(err, gorm.ErrRecordNotFound) {
|
| 17 |
+
return models.Exception{
|
| 18 |
+
Message: "Data not found",
|
| 19 |
+
DataNotFound: true,
|
| 20 |
+
Err: err,
|
| 21 |
+
}
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
lowerErr := strings.ToLower(err.Error())
|
| 25 |
+
if strings.Contains(lowerErr, "duplicated key") || strings.Contains(lowerErr, "unique constraint") || strings.Contains(lowerErr, "duplicate entry") {
|
| 26 |
+
return models.Exception{
|
| 27 |
+
Message: "Data already exists",
|
| 28 |
+
DataDuplicate: true,
|
| 29 |
+
Err: err,
|
| 30 |
+
}
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
if strings.Contains(lowerErr, "password") && strings.Contains(lowerErr, "length") {
|
| 34 |
+
return models.Exception{
|
| 35 |
+
Message: "Invalid password length",
|
| 36 |
+
InvalidPasswordLength: true,
|
| 37 |
+
Err: err,
|
| 38 |
+
}
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
if strings.Contains(lowerErr, "permission denied") || strings.Contains(lowerErr, "forbidden") {
|
| 42 |
+
return models.Exception{
|
| 43 |
+
Message: "Access forbidden",
|
| 44 |
+
Forbidden: true,
|
| 45 |
+
Err: err,
|
| 46 |
+
}
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
if errors.As(err, &gorm.ErrInvalidData) {
|
| 50 |
+
return models.Exception{
|
| 51 |
+
Message: "Invalid data format",
|
| 52 |
+
BadRequest: true,
|
| 53 |
+
Err: err,
|
| 54 |
+
}
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
return models.Exception{
|
| 58 |
+
Message: fallbackMessage,
|
| 59 |
+
InternalServerError: true,
|
| 60 |
+
Err: err,
|
| 61 |
+
}
|
| 62 |
+
}
|
space/space/space/space/space/space/space/router/server.go
CHANGED
|
@@ -7,11 +7,11 @@ import (
|
|
| 7 |
|
| 8 |
type Server struct {
|
| 9 |
router *gin.Engine
|
| 10 |
-
healthCheckController
|
| 11 |
}
|
| 12 |
|
| 13 |
func NewServer(
|
| 14 |
-
healthCheckController
|
| 15 |
) (*Server, error) {
|
| 16 |
|
| 17 |
router := gin.Default()
|
|
|
|
| 7 |
|
| 8 |
type Server struct {
|
| 9 |
router *gin.Engine
|
| 10 |
+
healthCheckController health_check_controller.HealthCheckController
|
| 11 |
}
|
| 12 |
|
| 13 |
func NewServer(
|
| 14 |
+
healthCheckController health_check_controller.HealthCheckController,
|
| 15 |
) (*Server, error) {
|
| 16 |
|
| 17 |
router := gin.Default()
|
space/space/space/space/space/space/space/services/health_check_service.go
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
package services
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"api.qobiltu.id/models"
|
| 5 |
+
"api.qobiltu.id/repositories"
|
| 6 |
+
"api.qobiltu.id/response"
|
| 7 |
+
"context"
|
| 8 |
+
)
|
| 9 |
+
|
| 10 |
+
type HealthCheckService interface {
|
| 11 |
+
Check(ctx context.Context, req *models.HealthCheckRequest) (*models.HealthCheckResponse, error)
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
type healthCheckService struct {
|
| 15 |
+
healthCheckRepository repositories.HealthCheckRepository
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
func NewHealthCheckService(healthCheckRepository repositories.HealthCheckRepository) HealthCheckService {
|
| 19 |
+
return &healthCheckService{
|
| 20 |
+
healthCheckRepository: healthCheckRepository,
|
| 21 |
+
}
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
func (s *healthCheckService) Check(ctx context.Context, req *models.HealthCheckRequest) (*models.HealthCheckResponse, error) {
|
| 25 |
+
res, err := s.healthCheckRepository.Check(ctx, req)
|
| 26 |
+
if err != nil {
|
| 27 |
+
return nil, response.HandleGormError(err, "Internal Server Error")
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
return res, nil
|
| 31 |
+
}
|
space/space/space/space/space/space/space/services/user_profile_service.go
CHANGED
|
@@ -1,115 +1,115 @@
|
|
| 1 |
-
package services
|
| 2 |
-
|
| 3 |
-
import (
|
| 4 |
-
"regexp"
|
| 5 |
-
"strconv"
|
| 6 |
-
"strings"
|
| 7 |
-
|
| 8 |
-
"api.qobiltu.id/models"
|
| 9 |
-
"api.qobiltu.id/repositories"
|
| 10 |
-
)
|
| 11 |
-
|
| 12 |
-
type UserProfileService struct {
|
| 13 |
-
Service[models.AccountDetails, models.UserProfileResponse]
|
| 14 |
-
}
|
| 15 |
-
|
| 16 |
-
// SanitizePhoneNumber membersihkan dan menormalkan nomor telepon ke format +62
|
| 17 |
-
func SanitizePhoneNumber(input string) string {
|
| 18 |
-
// Hilangkan semua spasi dan strip
|
| 19 |
-
input = strings.ReplaceAll(input, " ", "")
|
| 20 |
-
input = strings.ReplaceAll(input, "-", "")
|
| 21 |
-
input = strings.ReplaceAll(input, "(", "")
|
| 22 |
-
input = strings.ReplaceAll(input, ")", "")
|
| 23 |
-
|
| 24 |
-
// Hilangkan semua karakter non-digit kecuali +
|
| 25 |
-
re := regexp.MustCompile(`[^0-9\+]`)
|
| 26 |
-
input = re.ReplaceAllString(input, "")
|
| 27 |
-
|
| 28 |
-
// Handle nomor diawali 0 (contoh: 0812...) menjadi +62812...
|
| 29 |
-
if strings.HasPrefix(input, "0") {
|
| 30 |
-
input = "+62" + input[1:]
|
| 31 |
-
}
|
| 32 |
-
|
| 33 |
-
// Handle jika diawali dengan 62 tanpa + (contoh: 62812...)
|
| 34 |
-
if strings.HasPrefix(input, "62") && !strings.HasPrefix(input, "+62") {
|
| 35 |
-
input = "+" + input
|
| 36 |
-
}
|
| 37 |
-
|
| 38 |
-
// Handle jika tidak ada awalan +62 sama sekali (contoh: 8123456789)
|
| 39 |
-
if !strings.HasPrefix(input, "+62") {
|
| 40 |
-
if strings.HasPrefix(input, "8") {
|
| 41 |
-
input = "+62" + input
|
| 42 |
-
}
|
| 43 |
-
}
|
| 44 |
-
|
| 45 |
-
return input
|
| 46 |
-
}
|
| 47 |
-
func (s *UserProfileService) Create() {
|
| 48 |
-
userProfile := repositories.CreateAccountDetails(s.Constructor)
|
| 49 |
-
s.Error = userProfile.RowsError
|
| 50 |
-
if userProfile.NoRecord {
|
| 51 |
-
s.Exception.DataNotFound = true
|
| 52 |
-
s.Exception.Message = "There is no account with given credentials!"
|
| 53 |
-
return
|
| 54 |
-
}
|
| 55 |
-
s.Result = models.UserProfileResponse{
|
| 56 |
-
Account: repositories.GetAccountById(s.Constructor.AccountID).Result,
|
| 57 |
-
Details: userProfile.Result,
|
| 58 |
-
}
|
| 59 |
-
}
|
| 60 |
-
func (s *UserProfileService) Retrieve() {
|
| 61 |
-
userProfile := repositories.GetDetailAccountById(s.Constructor.AccountID)
|
| 62 |
-
s.Error = userProfile.RowsError
|
| 63 |
-
if userProfile.NoRecord {
|
| 64 |
-
s.Exception.DataNotFound = true
|
| 65 |
-
s.Exception.Message = "There is no account with given credentials!"
|
| 66 |
-
return
|
| 67 |
-
}
|
| 68 |
-
s.Result = models.UserProfileResponse{
|
| 69 |
-
Account: repositories.GetAccountById(s.Constructor.AccountID).Result,
|
| 70 |
-
Details: userProfile.Result,
|
| 71 |
-
}
|
| 72 |
-
s.Result.Account.Password = "SECRET"
|
| 73 |
-
}
|
| 74 |
-
|
| 75 |
-
func (s *UserProfileService) Update() {
|
| 76 |
-
if s.Constructor.PhoneNumber != nil {
|
| 77 |
-
phoneNumber := *s.Constructor.PhoneNumber
|
| 78 |
-
*s.Constructor.PhoneNumber = SanitizePhoneNumber(phoneNumber)
|
| 79 |
-
}
|
| 80 |
-
usersCount := repositories.GetAllAccount().RowsCount
|
| 81 |
-
var initialName string
|
| 82 |
-
if s.Constructor.Gender != nil {
|
| 83 |
-
if *s.Constructor.Gender {
|
| 84 |
-
initialName = "IKH_"
|
| 85 |
-
} else {
|
| 86 |
-
initialName = "AKH_"
|
| 87 |
-
}
|
| 88 |
-
}
|
| 89 |
-
|
| 90 |
-
initialName += strconv.Itoa(usersCount)
|
| 91 |
-
s.Constructor.InitialName = initialName
|
| 92 |
-
userProfile := repositories.UpdateAccountDetails(s.Constructor)
|
| 93 |
-
s.Error = userProfile.RowsError
|
| 94 |
-
if userProfile.NoRecord {
|
| 95 |
-
s.Exception.DataNotFound = true
|
| 96 |
-
s.Exception.Message = "There is no account with given credentials!"
|
| 97 |
-
return
|
| 98 |
-
}
|
| 99 |
-
account := repositories.GetAccountById(s.Constructor.AccountID)
|
| 100 |
-
account.Result.IsDetailCompleted = (userProfile.Result.InitialName != "" &&
|
| 101 |
-
userProfile.Result.FullName != nil &&
|
| 102 |
-
userProfile.Result.DateOfBirth != nil &&
|
| 103 |
-
userProfile.Result.PlaceOfBirth != nil &&
|
| 104 |
-
userProfile.Result.Domicile != nil &&
|
| 105 |
-
userProfile.Result.LastJob != nil &&
|
| 106 |
-
userProfile.Result.Gender != nil &&
|
| 107 |
-
userProfile.Result.LastEducation != nil &&
|
| 108 |
-
userProfile.Result.MaritalStatus != nil)
|
| 109 |
-
repositories.UpdateAccount(account.Result)
|
| 110 |
-
s.Result = models.UserProfileResponse{
|
| 111 |
-
Account: account.Result,
|
| 112 |
-
Details: userProfile.Result,
|
| 113 |
-
}
|
| 114 |
-
s.Result.Account.Password = "SECRET"
|
| 115 |
-
}
|
|
|
|
| 1 |
+
package services
|
| 2 |
+
|
| 3 |
+
import (
|
| 4 |
+
"regexp"
|
| 5 |
+
"strconv"
|
| 6 |
+
"strings"
|
| 7 |
+
|
| 8 |
+
"api.qobiltu.id/models"
|
| 9 |
+
"api.qobiltu.id/repositories"
|
| 10 |
+
)
|
| 11 |
+
|
| 12 |
+
type UserProfileService struct {
|
| 13 |
+
Service[models.AccountDetails, models.UserProfileResponse]
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
// SanitizePhoneNumber membersihkan dan menormalkan nomor telepon ke format +62
|
| 17 |
+
func SanitizePhoneNumber(input string) string {
|
| 18 |
+
// Hilangkan semua spasi dan strip
|
| 19 |
+
input = strings.ReplaceAll(input, " ", "")
|
| 20 |
+
input = strings.ReplaceAll(input, "-", "")
|
| 21 |
+
input = strings.ReplaceAll(input, "(", "")
|
| 22 |
+
input = strings.ReplaceAll(input, ")", "")
|
| 23 |
+
|
| 24 |
+
// Hilangkan semua karakter non-digit kecuali +
|
| 25 |
+
re := regexp.MustCompile(`[^0-9\+]`)
|
| 26 |
+
input = re.ReplaceAllString(input, "")
|
| 27 |
+
|
| 28 |
+
// Handle nomor diawali 0 (contoh: 0812...) menjadi +62812...
|
| 29 |
+
if strings.HasPrefix(input, "0") {
|
| 30 |
+
input = "+62" + input[1:]
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
// Handle jika diawali dengan 62 tanpa + (contoh: 62812...)
|
| 34 |
+
if strings.HasPrefix(input, "62") && !strings.HasPrefix(input, "+62") {
|
| 35 |
+
input = "+" + input
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
// Handle jika tidak ada awalan +62 sama sekali (contoh: 8123456789)
|
| 39 |
+
if !strings.HasPrefix(input, "+62") {
|
| 40 |
+
if strings.HasPrefix(input, "8") {
|
| 41 |
+
input = "+62" + input
|
| 42 |
+
}
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
return input
|
| 46 |
+
}
|
| 47 |
+
func (s *UserProfileService) Create() {
|
| 48 |
+
userProfile := repositories.CreateAccountDetails(s.Constructor)
|
| 49 |
+
s.Error = userProfile.RowsError
|
| 50 |
+
if userProfile.NoRecord {
|
| 51 |
+
s.Exception.DataNotFound = true
|
| 52 |
+
s.Exception.Message = "There is no account with given credentials!"
|
| 53 |
+
return
|
| 54 |
+
}
|
| 55 |
+
s.Result = models.UserProfileResponse{
|
| 56 |
+
Account: repositories.GetAccountById(s.Constructor.AccountID).Result,
|
| 57 |
+
Details: userProfile.Result,
|
| 58 |
+
}
|
| 59 |
+
}
|
| 60 |
+
func (s *UserProfileService) Retrieve() {
|
| 61 |
+
userProfile := repositories.GetDetailAccountById(s.Constructor.AccountID)
|
| 62 |
+
s.Error = userProfile.RowsError
|
| 63 |
+
if userProfile.NoRecord {
|
| 64 |
+
s.Exception.DataNotFound = true
|
| 65 |
+
s.Exception.Message = "There is no account with given credentials!"
|
| 66 |
+
return
|
| 67 |
+
}
|
| 68 |
+
s.Result = models.UserProfileResponse{
|
| 69 |
+
Account: repositories.GetAccountById(s.Constructor.AccountID).Result,
|
| 70 |
+
Details: userProfile.Result,
|
| 71 |
+
}
|
| 72 |
+
s.Result.Account.Password = "SECRET"
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
func (s *UserProfileService) Update() {
|
| 76 |
+
if s.Constructor.PhoneNumber != nil {
|
| 77 |
+
phoneNumber := *s.Constructor.PhoneNumber
|
| 78 |
+
*s.Constructor.PhoneNumber = SanitizePhoneNumber(phoneNumber)
|
| 79 |
+
}
|
| 80 |
+
usersCount := repositories.GetAllAccount().RowsCount
|
| 81 |
+
var initialName string
|
| 82 |
+
if s.Constructor.Gender != nil {
|
| 83 |
+
if strings.ToLower(*s.Constructor.Gender) == "laki-laki" {
|
| 84 |
+
initialName = "IKH_"
|
| 85 |
+
} else {
|
| 86 |
+
initialName = "AKH_"
|
| 87 |
+
}
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
initialName += strconv.Itoa(usersCount)
|
| 91 |
+
s.Constructor.InitialName = initialName
|
| 92 |
+
userProfile := repositories.UpdateAccountDetails(s.Constructor)
|
| 93 |
+
s.Error = userProfile.RowsError
|
| 94 |
+
if userProfile.NoRecord {
|
| 95 |
+
s.Exception.DataNotFound = true
|
| 96 |
+
s.Exception.Message = "There is no account with given credentials!"
|
| 97 |
+
return
|
| 98 |
+
}
|
| 99 |
+
account := repositories.GetAccountById(s.Constructor.AccountID)
|
| 100 |
+
account.Result.IsDetailCompleted = (userProfile.Result.InitialName != "" &&
|
| 101 |
+
userProfile.Result.FullName != nil &&
|
| 102 |
+
userProfile.Result.DateOfBirth != nil &&
|
| 103 |
+
userProfile.Result.PlaceOfBirth != nil &&
|
| 104 |
+
userProfile.Result.Domicile != nil &&
|
| 105 |
+
userProfile.Result.LastJob != nil &&
|
| 106 |
+
userProfile.Result.Gender != nil &&
|
| 107 |
+
userProfile.Result.LastEducation != nil &&
|
| 108 |
+
userProfile.Result.MaritalStatus != nil)
|
| 109 |
+
repositories.UpdateAccount(account.Result)
|
| 110 |
+
s.Result = models.UserProfileResponse{
|
| 111 |
+
Account: account.Result,
|
| 112 |
+
Details: userProfile.Result,
|
| 113 |
+
}
|
| 114 |
+
s.Result.Account.Password = "SECRET"
|
| 115 |
+
}
|
space/space/space/space/space/space/space/space/Dockerfile
CHANGED
|
@@ -25,6 +25,12 @@ FROM alpine:latest
|
|
| 25 |
# Set working directory
|
| 26 |
WORKDIR /app
|
| 27 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
# Copy hasil build dari builder ke image runtime
|
| 29 |
COPY --from=builder /app/main .
|
| 30 |
|
|
|
|
| 25 |
# Set working directory
|
| 26 |
WORKDIR /app
|
| 27 |
|
| 28 |
+
# Install tzdata
|
| 29 |
+
RUN apk update && apk add --no-cache tzdata
|
| 30 |
+
|
| 31 |
+
# Set the timezone environment variable
|
| 32 |
+
ENV TZ="Asia/Jakarta"
|
| 33 |
+
|
| 34 |
# Copy hasil build dari builder ke image runtime
|
| 35 |
COPY --from=builder /app/main .
|
| 36 |
|