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.
func (h *StaffHandler) CreateStaff(c *gin.Context) {
	var data model.Staff
	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
	}
	if !service.ValideateJSONRequestAndSendAll(&data, c) {
		return
	}
	if err := h.repo.Create(&data); err != nil {
		log.Printf("Error creating staff in DB: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create staff record"})
		return
	}

	// TODO: implement a way to send refId after registering
	// TODO: Check if sending refID is needed?
	c.JSON(http.StatusCreated, gin.H{"Success": "Created new staff with id "})
}

Database Create

Required Fields

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

  1. who creates these ??
  2. 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.

  1. 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:

  1. Created a DTO for the combined staff and staff detail creation.
  2. Created a service layer with a transactional method to handle the creation of both models.
  3. Updated the handler to use the new service and DTO.
  4. 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

  1. Department
  2. DOJ
  3. StaffID
  4. Name
  5. Type
  6. Employment Type
  7. Email
  8. Phone
  9. Gender

staff_registration.png|900x333

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
Email 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
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
Email staff_additional_detail email email
Phone staff phone phone
Gender staff gender gender

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