package bulletins_handler import ( "log" "net/http" "strconv" "time" "autolibrary.top/webserver/utils" "autolibrary.top/webserver/backend/database/bulletins_database" "autolibrary.top/webserver/backend/models/bulletins_model" "github.com/gin-gonic/gin" ) /* These handlers are used to manage bulletins. */ // GET /bulletins?date={yyyy-MM-dd}&time={HH:mm:ss}&range_hour={0 try to get bulletins, but got invalid (date=%s, time=%s, tz=%s) parameters: %v", dateStr, timeStr, loc.String(), err) c.JSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": "GET > try to get bulletins, but got invalid parameters: 'date' or 'time'", "data": nil, }) return } rangeHours, err := strconv.Atoi(rangeHourStr) if err != nil { log.Printf("[E] GET > try to get bulletins, but got invalid (range_hour=%s) parameter: %v", rangeHourStr, err) c.JSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": "GET > try to get bulletins, but got invalid parameter: 'range_hour'", "data": nil, }) return } startOfDateTime := dateTime endOfDateTime := startOfDateTime.Add(time.Duration(rangeHours)*time.Hour) startOfDateTimeStr := startOfDateTime.Format(time.RFC3339) endOfDateTimeStr := endOfDateTime.Format(time.RFC3339) var bulletins []bulletins_model.Bulletin result := bulletins_database.DB.Where( "date_time >= ? AND date_time < ? AND is_deleted = ?", startOfDateTime, endOfDateTime, false, ).Find(&bulletins) if result.Error != nil { log.Printf("[E] GET > occur an error when get bulletins from %s to %s: %v", startOfDateTimeStr, endOfDateTimeStr, result.Error) c.JSON(http.StatusInternalServerError, gin.H{ "code": http.StatusInternalServerError, "msg": "GET > occur an error when get bulletins", "data": nil, }) return } var deleteIds []int64 result = bulletins_database.DB.Model(bulletins_model.Bulletin{}).Where( "date_time >= ? AND date_time < ? AND is_deleted = ?", startOfDateTime, endOfDateTime, true, ).Pluck("id", &deleteIds) if result.Error != nil { log.Printf("[E] GET > occur an error when get bulletins from %s to %s: %v", startOfDateTimeStr, endOfDateTimeStr, result.Error) c.JSON(http.StatusInternalServerError, gin.H{ "code": http.StatusInternalServerError, "msg": "GET > occur an error when get bulletins", "data": nil, }) return } data := gin.H{ "bulletins": bulletins, "delete_ids": deleteIds, } log.Printf("[I] GET > get bulletins from %s to %s successfully", startOfDateTimeStr, endOfDateTimeStr) c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "GET > get bulletins successful", "data": data, }) } // GET /bulletins/:id func GetBulletinByID(c *gin.Context) { id, err := strconv.Atoi(c.Param("id")) if err != nil { log.Printf("[E] GET > try to get bulletin, but got invalid id parameter: %v", err) c.JSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": "GET > try to get bulletin, but got invalid id", "data": nil, }) return } var bulletin bulletins_model.Bulletin result := bulletins_database.DB.Where("is_deleted = ?", false).First(&bulletin, id) if result.Error != nil { log.Printf("[E] GET > bulletin (id=%d) can not found: %v", id, result.Error) c.JSON(http.StatusNotFound, gin.H{ "code": http.StatusNotFound, "msg": "GET > bulletin can not found", "data": nil, }) return } log.Printf("[I] GET > get bulletin (id=%d) successfully", id) c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "GET > get bulletin successful", "data": bulletin, }) } // POST /bulletins func PostBulletin(c *gin.Context) { var bulletin bulletins_model.Bulletin if err := c.ShouldBindJSON(&bulletin); err != nil { log.Printf("[E] POST > try to create bulletin, but got invalid request data: %v", err) c.JSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": "POST > try to create bulletin, but got invalid request data", "data": nil, }) return } bulletin.CreateAt = utils.NowInShanghai() // set default value to make sure the bulletin is not edited and not deleted before // get into the database bulletin.IsEdited = false bulletin.IsDeleted = false result := bulletins_database.DB.Create(&bulletin) if result.Error != nil { log.Printf("[E] POST > occur an error when create bulletin: %v", result.Error) c.JSON(http.StatusInternalServerError, gin.H{ "code": http.StatusInternalServerError, "msg": "POST > occur an error when create bulletin", "data": nil, }) return } dataTimeStr := bulletin.DateTime.Format(time.RFC3339) id := strconv.FormatUint(uint64(bulletin.ID), 10) log.Printf("[I] POST > create bulletin (id=%s, date_time=%s) successful", id, dataTimeStr) c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "POST > create bulletin successful", "data": bulletin, }) } // PUT /bulletins/:id func PutBulletinByID(c *gin.Context) { id, err := strconv.Atoi(c.Param("id")) if err != nil { log.Printf("[E] PUT > try to update bulletin, but got invalid id parameter: %v", err) c.JSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": "PUT > try to update bulletin, but got invalid id", "data": nil, }) return } var updateBulletin bulletins_model.Bulletin if err := c.ShouldBindJSON(&updateBulletin); err != nil { log.Printf("[E] PUT > try to update bulletin, but got invalid request data: %v", err) c.JSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": "PUT > try to update bulletin, but got invalid request data", "data": nil, }) return } var existingBulletin bulletins_model.Bulletin result := bulletins_database.DB.Where("is_deleted = ?", false).First(&existingBulletin, id) if result.Error != nil { log.Printf("[E] PUT > bulletin (id=%d) can not found: %v", id, result.Error) c.JSON(http.StatusNotFound, gin.H{ "code": http.StatusNotFound, "msg": "PUT > bulletin can not found", "data": nil, }) return } // keep the original date time updateBulletin.DateTime = existingBulletin.DateTime // set last edit time to current time updateBulletin.LastEditAt = utils.NowInShanghai() // set is edited to true updateBulletin.IsEdited = true result = bulletins_database.DB.Model(&existingBulletin).Where("id = ?", id).Updates(updateBulletin) if result.Error != nil { log.Printf("[E] PUT > occur an error when update bulletin (id=%d): %v", id, result.Error) c.JSON(http.StatusInternalServerError, gin.H{ "code": http.StatusInternalServerError, "msg": "PUT > occur an error when update bulletin", "data": nil, }) return } // post check after update var updatedBulletin bulletins_model.Bulletin if result = bulletins_database.DB.Where("is_deleted = ?", false).First(&updatedBulletin, id); result.Error == nil { log.Printf("[I] PUT > update bulletin (id=%d) successful", id) c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "PUT > update bulletin successful", "data": updatedBulletin, }) } else { log.Printf("[E] PUT > update successful but failed to retrieve updated bulletin (id=%d): %v", id, result.Error) c.JSON(http.StatusInternalServerError, gin.H{ "code": http.StatusInternalServerError, "msg": "PUT > update successful but failed to retrieve updated bulletin", "data": nil, }) } } // DELETE /bulletins/:id func DeleteBulletinByID(c *gin.Context) { id, err := strconv.Atoi(c.Param("id")) if err != nil { log.Printf("[E] DELETE > try to delete bulletin, but got invalid id: %v", err) c.JSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": "DELETE > try to delete bulletin, but got invalid id", "data": nil, }) return } // soft delete, actually is a update operation var existingBulletin bulletins_model.Bulletin result := bulletins_database.DB.Where("is_deleted = ?", false).First(&existingBulletin, id) if result.Error != nil { log.Printf("[E] DELETE > bulletin (id=%d) can not found: %v", id, result.Error) c.JSON(http.StatusNotFound, gin.H{ "code": http.StatusNotFound, "msg": "DELETE > bulletin can not found", "data": nil, }) return } // set is_deleted to true existingBulletin.IsDeleted = true result = bulletins_database.DB.Model(&existingBulletin).Where("id = ?", id).Updates(existingBulletin) if result.Error != nil { log.Printf("[E] DELETE > occur an error when soft delete bulletin (id=%d): %v", id, result.Error) c.JSON(http.StatusInternalServerError, gin.H{ "code": http.StatusInternalServerError, "msg": "DELETE > occur an error when soft delete bulletin", "data": nil, }) return } // post check after soft delete var deletedBulletin bulletins_model.Bulletin if result = bulletins_database.DB.Where("is_deleted = ?", true).First(&deletedBulletin, id); result.Error == nil { log.Printf("[I] DELETE > soft delete bulletin (id=%d) successful", id) c.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "DELETE > soft delete bulletin successful", "data": deletedBulletin, }) } else { log.Printf("[E] DELETE > soft delete successful but failed to retrieve deleted bulletin (id=%d): %v", id, result.Error) c.JSON(http.StatusInternalServerError, gin.H{ "code": http.StatusInternalServerError, "msg": "DELETE > soft delete successful but failed to retrieve deleted bulletin", "data": nil, }) } }