Staff API
Multi-column
Todo
not done
path includes API/APIs/staff/
Done
done
path includes API/APIs/staff/
v0.0.1
Create New Staff
sequenceDiagram actor Admin as Admin actor Server as Server actor Database as Database Admin ->> Server: /staff/register + data Server ->> Server: Validates data Server ->> Database: Checks if the staff exists alt Exists Database ->> Server: Yes Server ->> Admin: Respinse : Account already Exists else Database->>Server: No Server ->> Database: create Database ->> Database: Creates Database ->> Server: Primary Key. Server --> Database: set new Primary key as staff_detail(primary_key) end Server ->> Admin: Reponse: staff{id} created successfully.
Database Create
Required Fields
required fields old ,
json
func (Staff) GetRequredFields() []string {
return []string{"join_date", "staff_id", "type", "full_name", "gender", "status"}
}
func (Staff) GetRequredStructFields() []string {
return []string{"JoinDate", "StaffID", "Type", "FullName", "Gender", "Status"}
}
Create New User In V0.0.1
curl -vX POST localhost:9090/api/v1/staff/ -H "Content-Type: application/json" \
-d '{"staff_id": "G1_EC","join_date": "2025-08-03T00:00:00Z","type": 1, "full_name": "Arun CS", "gender": "Male" , "status": 10 }'
The problem with this is that
- who creates these ??
- In staff_detail_model there is this
StaffID int `gorm:"column:staff_id;not null" json:"staff_id"`
which is the primary id of the newly created staff.
- The problem seen in above indicates that the staff must be created before staffdetail.
CreateStaff
Required Frelds
type NewStaffDetail struct {
RefID string `json:"ref_id"`
// NOTE: You wont find this field in any of the staff table , i am using this solely because of , StaffID will get confused with staff.StaffID and staffdetail.StaffID
DOB time.Time `json:"dob"`
LicenseExpire time.Time `json:"license_expire"`
BaggeExpire time.Time `json:"bagge_expire"`
NoOfExperience int `json:"no_of_experience"`
HIndex int `json:"h_index"`
Staff NewStaff `json:"staff"`
}
// Required Params of Staff table
type NewStaff struct {
JoinDate time.Time `json:"join_date"`
StaffID string `json:"staff_id"`
Type int `json:"type"`
FullName string `json:"full_name"`
Gender string `json:"gender,omitempty"`
Status int `json:"status,omitempty"`
}
Test API: CreateStaff
curl -vvvv localhost:9090/api/v1/staff/ -H "Content-Type: application/json" \
-d'{
"ref_id": "Arun CS",
"dob": "1990-05-15T00:00:00Z",
"license_expire": "2025-12-31T23:59:59Z",
"bagge_expire": "2023-06-30T23:59:59Z",
"no_of_experience": 10,
"h_index": 0,
"join_date": "2015-01-01T00:00:00Z",
"staff_id": "STAFF_1",
"type": 1,
"full_name": "Arun CS",
"gender": "M",
"status": 1
}'
We have now:
- Created a DTO for the combined staff and staff detail creation.
- Created a service layer with a transactional method to handle the creation of both models.
- Updated the handler to use the new service and DTO.
- Updated the routes to initialize the service and inject it into the handler.
Test API: CreateStaff
curl -vvvvvvvv localhost:9090/api/v1/staff/ -H "Content-Type: application/json" \
-d'{
"staff_id": "STAFF_3",
"full_name": "Arun CS",
"gender": "M"
}'
Test API: CreateStaff
curl -vvvvvvvv localhost:9090/api/v1/staff/ -H "Content-Type: application/json" \
-d'{
"ref_id": "STAFF_3",
"staff_id": "STAFF_1",
"full_name": "Arun CS",
"gender": "M"
}'
Default Values
Blank
Mandatory Fields
- Department
- DOJ
- StaffID
- Name
- Type
- Employment Type
- Phone
- Gender
Blank
type StaffRegistrationRequest struct {
DeptID int `json:"dept_id" binding:"required,min=1"`
JoinDate string `json:"join_date" binding:"required" validate:"datetime=2006-01-02"`
StaffID string `json:"staff_id" binding:"required,min=3,max=15"`
FullName string `json:"full_name" binding:"required,min=2,max=100"`
Type int `json:"type" binding:"required,oneof=1 2 3"`
ContractType int `json:"contract_type" binding:"required,min=1"`
Email string `json:"email" binding:"required,email,max=100"`
Phone string `json:"phone" binding:"required,min=10,max=15"`
Gender string `json:"gender" binding:"required,oneof=Male Female Other"`
}
Field | Table | Json ID | DB Field Name |
---|---|---|---|
Department | staff |
dept_id |
dept_id |
DOJ | staff |
join_date |
join_date |
StaffID | staff |
staff_id |
staff_id |
Name | staff |
full_name |
full_name |
Type | staff |
type |
type |
Employment Type | staff |
contract_type |
contract_type |
staff_additional_detail |
email |
email |
|
Phone | staff |
phone |
phone |
Gender | staff |
gender |
gender |
{
"dept_id": 5,
"join_date": "2025-01-15",
"staff_id": "STAFF_X",
"full_name": "Arun CS",
"type": 1,
"contract_type": 1,
"email": "aruncs31ss@gmail.com",
"phone": "+919747350199",
"gender": "Male"
}
```{ #staffaddm}
For staff#^fd85d7 table required fields are
{ #4e0782}
```go
type Staff struct {
// Required fields , only considering staff
UserID int `json:"user_id" binding:"required"`
StaffID string `json:"staff_id" binding:"required"`
JoinDate time.Time `json:"join_date" binding:"required"`
FullName string `json:"full_name" binding:"required"`
Gender string `json:"gender" binding:"required,oneof=Male Female Other"`
Type int `json:"type" binding:"required,oneof=1 2 3"` // 1=Teaching, 2=Non-Teaching, 3=Contract
Status int `json:"status" binding:"required,oneof=0 1 2" default:"1"` // 0=Inactive, 1=Active, 2=Suspended
}
Multi-column
Float
{
"staff": {
"user_id": 123,
"join_date": "2024-01-15",
"staff_id": "STF001",
"type": 1,
"full_name": "Dr. John Smith",
"gender": "Male",
"status": 1
}
}
New Admission Needed Fields
Old
// type NewStaffDetail struct {
// RefID string `json:"ref_id" binding:"required"`
// DOB time.Time `json:"dob" binding:"required default=1990-05-15T00:00:00Z"`
// LicenseExpire time.Time `json:"license_expire" binding:"required default=2023-06-30T23:59:59Z"`
// BaggeExpire time.Time `json:"bagge_expire" binding:"required default=2023-06-30T23:59:59Z"`
// NoOfExperience int `json:"no_of_experience" binding:"required default=1"`
// HIndex int `json:"h_index" binding:"required default=1" `
// NewStaff
// }
//
// // Required Params of Staff table
// type NewStaff struct {
// JoinDate time.Time `json:"join_date" binding:"required default=2000-06-30T23:59:59Z"`
// StaffID string `json:"staff_id" binding:"required"`
// Type int `json:"type" binding:"required" default=1`
// FullName string `json:"full_name" binding:"required"`
// Gender string `json:"gender,omitempty" binding:"required"`
// Status int `json:"status,omitempty" binding:"required default=3"`
// }
//
// type NewStaffDetail struct {
// RefID string `json:"ref_id" binding:"required"`
// DOB time.Time `json:"dob" binding:"required default=1990-05-15T00:00:00Z"`
// LicenseExpire time.Time `json:"license_expire" binding:"required default=2023-06-30T23:59:59Z"`
// BaggeExpire time.Time `json:"bagge_expire" binding:"required default=2023-06-30T23:59:59Z"`
// NoOfExperience int `json:"no_of_experience" binding:"required default=1"`
// HIndex int `json:"h_index" binding:"required default=1"`
// NewStaff
// }
//
// type NewStaff struct {
// JoinDate time.Time `json:"join_date" binding:"required default=2000-06-30T23:59:59Z"`
// StaffID string `json:"staff_id" binding:"required"` // TODO: Check if this is necessary
// Type int `json:"type" binding:"required default=1"`
// FullName string `json:"full_name" binding:"required"`
// Gender string `json:"gender,omitempty" binding:"required"`
// Status int `json:"status,omitempty" binding:"required default=3"`
// }
//
V 0.0.2
CreateStaff
Handler
type StaffWriter interface {
CreateStaff(c *gin.Context)
DeleteStaff(c *gin.Context)
}
CreateStaff
func (h *staffWriter) CreateStaff(c *gin.Context) {
var data dto.NewStaffAdmission
fmt.Println("Insider CreateStaff")
if err := c.ShouldBindJSON(&data); err != nil {
log.Printf("Error binding JSON: %v", err)
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request data", "details": err.Error()})
return
}
fmt.Println("Data received in CreateStaff:", data)
staff, err := h.staffService.CreateStaffWithDetails(&data)
if err != nil || staff == nil {
if errors.Is(err, utils.ErrStaffAlreadyExists) {
c.JSON(http.StatusNotAcceptable, gin.H{"error": "staff already exists", "details": "this staff_id " + data.StaffID + " already exists"})
return
} else {
c.JSON(http.StatusConflict, gin.H{"error": "staff already exists", "details": err.Error()})
return
}
}
c.JSON(http.StatusCreated, staff)
}
Depends on
- Service: [[]]
h.staffService.CreateStaffWithDetails(&data)