guide changes
This commit is contained in:
@@ -444,7 +444,7 @@ func (ctl *TenantController) CreateTenantUser(c *fiber.Ctx) error {
|
||||
|
||||
func (ctl *TenantController) GetTenantInfo(c *fiber.Ctx) error {
|
||||
log.Printf("[DEBUG] GetTenantInfo OriginalURL: %s, Headers: %v", c.OriginalURL(), c.GetReqHeaders())
|
||||
|
||||
|
||||
// Parse tenant ID
|
||||
tidStr := c.Query("tenantid")
|
||||
if tidStr == "" {
|
||||
@@ -580,3 +580,133 @@ func (ctl *TenantController) GetTenantByKeyword(c *fiber.Ctx) error {
|
||||
"details": data,
|
||||
})
|
||||
}
|
||||
|
||||
// AssignStaff moves one of a merchant's people to a branch, or takes them off.
|
||||
//
|
||||
// `locationid` 0 unassigns, and is a real instruction rather than a missing
|
||||
// value — somebody can leave a shop before the next one opens, and the console
|
||||
// needs a way to say that which is not "delete the account".
|
||||
//
|
||||
// The tenant comes from the request and every check is scoped to it in the
|
||||
// query, so a userid belonging to another business matches nothing and the call
|
||||
// fails rather than moving a stranger's staff.
|
||||
func (ctl *TenantController) AssignStaff(c *fiber.Ctx) error {
|
||||
var input struct {
|
||||
Tenantid int `json:"tenantid"`
|
||||
Userid int `json:"userid"`
|
||||
Locationid int `json:"locationid"`
|
||||
Unassign bool `json:"unassign"`
|
||||
}
|
||||
if err := c.BodyParser(&input); err != nil {
|
||||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
|
||||
"code": http.StatusBadRequest, "status": false, "message": "Invalid input",
|
||||
})
|
||||
}
|
||||
if input.Tenantid <= 0 || input.Userid <= 0 {
|
||||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
|
||||
"code": http.StatusBadRequest, "status": false,
|
||||
"message": "tenantid and userid are required",
|
||||
})
|
||||
}
|
||||
|
||||
// The rule lives in services.ResolveAssignment so it can be tested without
|
||||
// a request: a zero locationid must never be read as "unassign", because a
|
||||
// dropped field looks exactly like one.
|
||||
location, err := services.ResolveAssignment(input.Locationid, input.Unassign)
|
||||
if err != nil {
|
||||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
|
||||
"code": http.StatusBadRequest, "status": false, "message": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
if err := ctl.tenantService.AssignStaffToBranch(input.Tenantid, input.Userid, location); err != nil {
|
||||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
|
||||
"code": http.StatusBadRequest, "status": false, "message": err.Error(),
|
||||
})
|
||||
}
|
||||
return c.JSON(fiber.Map{"code": 200, "status": true, "message": "Success"})
|
||||
}
|
||||
|
||||
// UpdateTenantProfile lets a merchant change their own business record.
|
||||
//
|
||||
// The body is read as a free-form map rather than into `models.Tenants`,
|
||||
// deliberately. Binding to the struct would make every column on the table a
|
||||
// candidate for writing and leave "which of these may a merchant set?" answered
|
||||
// by whichever fields a form happened to send. The allowlist in
|
||||
// services.TenantProfileUpdate answers it in one place instead, and everything
|
||||
// absent from a request is left alone rather than blanked.
|
||||
func (ctl *TenantController) UpdateTenantProfile(c *fiber.Ctx) error {
|
||||
fields := map[string]any{}
|
||||
if err := c.BodyParser(&fields); err != nil {
|
||||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
|
||||
"code": http.StatusBadRequest, "status": false, "message": "Invalid input",
|
||||
})
|
||||
}
|
||||
|
||||
// The row to write is named by `tenantid`, and it is the one value in the
|
||||
// body that is never a value to write.
|
||||
tenantID := 0
|
||||
switch id := fields["tenantid"].(type) {
|
||||
case float64:
|
||||
tenantID = int(id)
|
||||
case int:
|
||||
tenantID = id
|
||||
}
|
||||
if tenantID <= 0 {
|
||||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
|
||||
"code": http.StatusBadRequest, "status": false,
|
||||
"message": "tenantid is required",
|
||||
})
|
||||
}
|
||||
|
||||
if err := ctl.tenantService.UpdateTenantProfile(tenantID, fields); err != nil {
|
||||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
|
||||
"code": http.StatusBadRequest, "status": false, "message": err.Error(),
|
||||
})
|
||||
}
|
||||
return c.JSON(fiber.Map{"code": 200, "status": true, "message": "Success"})
|
||||
}
|
||||
|
||||
// UpdateOwnProfile lets somebody change their own name, mobile or email.
|
||||
//
|
||||
// Read as a map rather than into `models.User` for the same reason as the shop
|
||||
// profile: `app_users` keeps identity next to authorisation, so binding to the
|
||||
// struct would make `roleid`, `locationid`, `status`, `password` and `pin`
|
||||
// candidates for writing. The allowlist in services.OwnProfileUpdate answers
|
||||
// "what may a person change about themselves?" in one place.
|
||||
//
|
||||
// Scoped by userid AND tenantid — the existing `users/update` checks only the
|
||||
// userid, which is why the store user's account page has been read-only rather
|
||||
// than editable.
|
||||
func (ctl *TenantController) UpdateOwnProfile(c *fiber.Ctx) error {
|
||||
fields := map[string]any{}
|
||||
if err := c.BodyParser(&fields); err != nil {
|
||||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
|
||||
"code": http.StatusBadRequest, "status": false, "message": "Invalid input",
|
||||
})
|
||||
}
|
||||
|
||||
readID := func(key string) int {
|
||||
switch id := fields[key].(type) {
|
||||
case float64:
|
||||
return int(id)
|
||||
case int:
|
||||
return id
|
||||
}
|
||||
return 0
|
||||
}
|
||||
userID, tenantID := readID("userid"), readID("tenantid")
|
||||
if userID <= 0 || tenantID <= 0 {
|
||||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
|
||||
"code": http.StatusBadRequest, "status": false,
|
||||
"message": "userid and tenantid are both required",
|
||||
})
|
||||
}
|
||||
|
||||
if err := ctl.tenantService.UpdateOwnProfile(userID, tenantID, fields); err != nil {
|
||||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
|
||||
"code": http.StatusBadRequest, "status": false, "message": err.Error(),
|
||||
})
|
||||
}
|
||||
return c.JSON(fiber.Map{"code": 200, "status": true, "message": "Success"})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user