209 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			209 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package expense
 | |
| 
 | |
| import (
 | |
| 	"errors"
 | |
| 	"net/http"
 | |
| 	"strconv"
 | |
| 	"strings"
 | |
| 	"time"
 | |
| 
 | |
| 	"management/internal/db/model/form"
 | |
| 	db "management/internal/db/sqlc"
 | |
| 	"management/internal/global"
 | |
| 	"management/internal/global/html"
 | |
| 	"management/internal/global/know"
 | |
| 	"management/internal/middleware/manage/auth"
 | |
| 	"management/internal/pkg/convertor"
 | |
| 	"management/internal/router/manage/util"
 | |
| 	categoryservice "management/internal/service/category"
 | |
| 	projectservice "management/internal/service/project"
 | |
| 	"management/internal/tpl"
 | |
| 
 | |
| 	"github.com/jackc/pgx/v5/pgtype"
 | |
| )
 | |
| 
 | |
| func List(w http.ResponseWriter, r *http.Request) {
 | |
| 	ctx := r.Context()
 | |
| 	pp := projectservice.AllProjects(ctx)
 | |
| 	cc, _ := categoryservice.GetParentCategorySelectLetter(ctx, know.ExpenseCategory)
 | |
| 	tpl.HTML(w, r, "expense/list.tmpl", map[string]any{
 | |
| 		"Statuses":   html.NewSelectControls(global.Statuses, 0),
 | |
| 		"Projects":   html.NewSelectStringControls(pp, "0"),
 | |
| 		"Categories": html.NewSelectStringControls(cc, "0"),
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func PostList(w http.ResponseWriter, r *http.Request) {
 | |
| 	ctx := r.Context()
 | |
| 	project := convertor.ConvertInt[int64](r.PostFormValue("project"), 9999)
 | |
| 	if project == 0 {
 | |
| 		project = 9999
 | |
| 	}
 | |
| 	budget := convertor.ConvertInt[int64](r.PostFormValue("budget"), 9999)
 | |
| 	if budget == 0 {
 | |
| 		budget = 9999
 | |
| 	}
 | |
| 	category := convertor.ConvertInt[int32](r.PostFormValue("category"), 9999)
 | |
| 	if category == 0 {
 | |
| 		category = 9999
 | |
| 	}
 | |
| 
 | |
| 	title := strings.TrimSpace(r.PostFormValue("title"))
 | |
| 	var search string
 | |
| 	if len(title) > 0 {
 | |
| 		search = "%" + title + "%"
 | |
| 		if strings.HasSuffix(title, ":") {
 | |
| 			search = title[:len(title)-1] + "%"
 | |
| 		}
 | |
| 	}
 | |
| 	arg := &db.ListExpenseConditionParam{
 | |
| 		ProjectID:   project,
 | |
| 		BudgetID:    budget,
 | |
| 		ExpenseType: category,
 | |
| 		IsTitle:     len(search) > 0,
 | |
| 		Title:       search,
 | |
| 		Status:      util.ConvertInt16(r.PostFormValue("status"), 9999),
 | |
| 		PageID:      util.ConvertInt32(r.PostFormValue("page"), 1),
 | |
| 		PageSize:    util.ConvertInt32(r.PostFormValue("rows"), 10),
 | |
| 	}
 | |
| 	arg.TimeBegin, arg.TimeEnd = util.DefaultStartTimeAndEndTime(r.PostFormValue("timeBegin"), r.PostFormValue("timeEnd"))
 | |
| 	res, total, err := db.Engine.ListExpenseCondition(ctx, arg)
 | |
| 	if err != nil {
 | |
| 		http.Error(w, err.Error(), http.StatusInternalServerError)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	data := tpl.ResponseList{
 | |
| 		Code:    0,
 | |
| 		Message: "ok",
 | |
| 		Count:   total,
 | |
| 		Data:    res,
 | |
| 	}
 | |
| 	tpl.JSON(w, data)
 | |
| }
 | |
| 
 | |
| func Add(w http.ResponseWriter, r *http.Request) {
 | |
| 	tpl.HTML(w, r, "expense/edit.tmpl", map[string]any{
 | |
| 		"Item":     &form.ExpenseForm{},
 | |
| 		"Statuses": html.NewSelectControls(global.Statuses, 0),
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func Edit(w http.ResponseWriter, r *http.Request) {
 | |
| 	vars := r.URL.Query()
 | |
| 	id := util.ConvertInt[int64](vars.Get("id"), 0)
 | |
| 	expense := &form.ExpenseForm{}
 | |
| 	ctx := r.Context()
 | |
| 	if id > 0 {
 | |
| 		if cus, err := db.Engine.GetExpense(ctx, id); err == nil {
 | |
| 			expense = expense.ToForm(cus)
 | |
| 			if u, err := db.Engine.GetSysUser(ctx, cus.CreatedUserID); err == nil {
 | |
| 				expense.CreatedName = u.Username
 | |
| 			}
 | |
| 			if u, err := db.Engine.GetSysUser(ctx, cus.UpdatedUserID); err == nil {
 | |
| 				expense.UpdatedName = u.Username
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	tpl.HTML(w, r, "expense/edit.tmpl", map[string]any{
 | |
| 		"Item":     expense,
 | |
| 		"Statuses": html.NewSelectControls(global.Statuses, expense.Status),
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func Save(w http.ResponseWriter, r *http.Request) {
 | |
| 	ctx := r.Context()
 | |
| 	data, err := validForm(r)
 | |
| 	if err != nil {
 | |
| 		tpl.JSONERR(w, err.Error())
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	authUser := auth.AuthUser(ctx)
 | |
| 	if data.ID > 0 {
 | |
| 		arg := &db.UpdateExpenseParams{
 | |
| 			ID: data.ID,
 | |
| 			ProjectID: pgtype.Int8{
 | |
| 				Int64: data.ProjectID,
 | |
| 				Valid: true,
 | |
| 			},
 | |
| 			BudgetID: pgtype.Int8{
 | |
| 				Int64: data.BudgetID,
 | |
| 				Valid: true,
 | |
| 			},
 | |
| 			Amount: data.AmountF,
 | |
| 			ExpensesAt: pgtype.Timestamptz{
 | |
| 				Time:  data.ExpensesAt,
 | |
| 				Valid: true,
 | |
| 			},
 | |
| 			ExpensesType: pgtype.Int4{
 | |
| 				Int32: data.ExpensesType,
 | |
| 				Valid: true,
 | |
| 			},
 | |
| 			Remark: pgtype.Text{
 | |
| 				String: data.Remark,
 | |
| 				Valid:  true,
 | |
| 			},
 | |
| 			Status: pgtype.Int2{
 | |
| 				Int16: data.Status,
 | |
| 				Valid: true,
 | |
| 			},
 | |
| 			UpdatedUserID: pgtype.Int4{
 | |
| 				Int32: authUser.ID,
 | |
| 				Valid: true,
 | |
| 			},
 | |
| 		}
 | |
| 		_, err := db.Engine.UpdateExpense(ctx, arg)
 | |
| 		if err != nil {
 | |
| 			tpl.JSONERR(w, err.Error())
 | |
| 			return
 | |
| 		}
 | |
| 		tpl.JSONOK(w, "更新成功")
 | |
| 	} else {
 | |
| 		arg := &db.CreateExpenseParams{
 | |
| 			ProjectID:     data.ProjectID,
 | |
| 			BudgetID:      data.BudgetID,
 | |
| 			Amount:        data.AmountF,
 | |
| 			ExpensesAt:    data.ExpensesAt,
 | |
| 			ExpensesType:  data.ExpensesType,
 | |
| 			Remark:        data.Remark,
 | |
| 			Status:        data.Status,
 | |
| 			CreatedUserID: authUser.ID,
 | |
| 		}
 | |
| 		_, err := db.Engine.CreateExpense(ctx, arg)
 | |
| 		if err != nil {
 | |
| 			tpl.JSONERR(w, err.Error())
 | |
| 			return
 | |
| 		}
 | |
| 		tpl.JSONOK(w, "添加成功")
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func validForm(r *http.Request) (form.ExpenseForm, error) {
 | |
| 	var err error
 | |
| 	data := form.ExpenseForm{}
 | |
| 
 | |
| 	data.ID = convertor.ConvertInt[int64](r.PostFormValue("ID"), 0)
 | |
| 	data.ProjectID, err = strconv.ParseInt(r.PostFormValue("ProjectID"), 10, 64)
 | |
| 	if err != nil || data.ProjectID == 0 {
 | |
| 		return data, errors.New("项目不能为空")
 | |
| 	}
 | |
| 	data.BudgetID, err = strconv.ParseInt(r.PostFormValue("BudgetID"), 10, 64)
 | |
| 
 | |
| 	if err := data.AmountF.Scan(r.PostFormValue("Amount")); err != nil {
 | |
| 		return data, errors.New("报销金额格式错误")
 | |
| 	}
 | |
| 	data.ExpensesAt, err = time.ParseInLocation("2006-01-02", r.PostFormValue("ExpensesAt"), time.Local)
 | |
| 	if err != nil {
 | |
| 		return data, errors.New("报销时间格式错误")
 | |
| 	}
 | |
| 	expensesType, err := strconv.ParseInt(r.PostFormValue("ExpensesType"), 10, 64)
 | |
| 	if err != nil || expensesType == 0 {
 | |
| 		return data, errors.New("报销类型不能为空")
 | |
| 	}
 | |
| 	data.ExpensesType = int32(expensesType)
 | |
| 
 | |
| 	data.Status = convertor.ConvertInt[int16](r.PostFormValue("Status"), 9999)
 | |
| 	return data, nil
 | |
| }
 |