Explorar o código

add:报销管理

zoie hai 1 ano
pai
achega
1fe5ae6b3b

+ 10 - 0
Nats/NatsServer/NatsERP_user.go

@@ -31,6 +31,16 @@ func Read_User_List_All() (user []userlibs.User, err error) {
 	return user, nil
 
 }
+func Read_User_List_T_uuid(T_name string, T_uuid_list []string, page, page_z int) (user []userlibs.User, cnt int64, err error) {
+	nats := natslibs.NewNats(Nats.Nats)
+	user, cnt, err = nats.Read_User_List_T_uuid(T_name, T_uuid_list, page, page_z)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return user, cnt, err
+	}
+	return user, cnt, nil
+
+}
 
 // 添加系统日志
 func AddSysLogs(T_class, T_title string, T_txt interface{}) {

+ 7 - 1
README.md

@@ -6,4 +6,10 @@ git config --global url."git@git.baozhida.cn/ERP_libs".insteadOf "http://120.55.
 
 ### 导入本地库
 
-go mod edit -replace git.baozhida.cn/ERP_libs=${Yours_Path}/ERP_libs
+go mod edit -replace git.baozhida.cn/ERP_libs=${Yours_Path}/ERP_libs
+
+
+### 注意事项
+在宝塔通过请求头获取数据
+在配置文件添加
+underscores_in_headers on

+ 4 - 5
conf/app.conf

@@ -7,11 +7,10 @@ copyrequestbody = true
 
 Sys_Name = "ERP_SALARY"
 # Nats
-# NatsServer_Url = "192.168.192.251:4222"
 NatsServer_Url = "175.178.229.79:4222"
-
+# NatsServer_Url = "127.0.0.1:4223"
 # Mysql 线上
-MysqlServer_UrlPort = "192.168.192.251:3306"
+MysqlServer_UrlPort = "127.0.0.1:3316"
 MysqlServer_Database = "erp_salary_test"
 MysqlServer_Username = "erp_salary_test"
 MysqlServer_Password = "784HzbWpj5LbzBHN"
@@ -19,12 +18,12 @@ MysqlServer_MaxIdleConnections = 100
 MysqlServer_MaxOpenConnections = 200
 
 # Redis
-Redis_address = "192.168.192.251:6379"
+Redis_address = "127.0.0.1:6378"
 Redis_password = ""
 Redis_dbNum = "1"
 
 # 路由排除信息
-FilterExcludeURL =
+FilterExcludeURL = 
 FilterOnlyLoginCheckURL =
 
 # 静态资源

+ 630 - 0
controllers/Reimburse.go

@@ -0,0 +1,630 @@
+package controllers
+
+import (
+	"ERP_salary/Nats/NatsServer"
+	"ERP_salary/conf"
+	"ERP_salary/logs"
+	"ERP_salary/models/Account"
+	"ERP_salary/models/Reimburse"
+	"encoding/json"
+	"fmt"
+	powerlibs "git.baozhida.cn/ERP_libs/Power"
+	userlibs "git.baozhida.cn/ERP_libs/User"
+	"git.baozhida.cn/ERP_libs/lib"
+	"github.com/beego/beego/v2/adapter/orm"
+	//"github.com/beego/beego/v2/client/orm"
+	beego "github.com/beego/beego/v2/server/web"
+	"math"
+	"time"
+)
+
+type ReimburseController struct {
+	beego.Controller
+	User userlibs.User
+}
+
+func (c *ReimburseController) Prepare() {
+	c.User = *Account.User_r
+}
+func (c *ReimburseController) CheckRBAC(T_power string) {
+	o := orm.NewOrm()
+	powerDao := powerlibs.NewPower(o)
+	power, err := powerDao.Read_Power_ByT_id(T_power)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "无权访问!"}
+		c.ServeJSON()
+		return
+	}
+
+	if power.T_menu == "*" {
+		return
+	}
+
+	api := Account.Read_API_List_ByPower(power.T_id, power.T_menu)
+	flag := false
+	for _, v := range api {
+		if v.T_uri == c.Ctx.Request.URL.Path {
+			flag = true
+			break
+		}
+	}
+	if !flag {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "无权访问!"}
+		c.ServeJSON()
+		return
+	}
+}
+func (c *ReimburseController) User_List() {
+	var r_jsons lib.R_JSONS
+	// 分页参数 初始化
+	page, _ := c.GetInt("page")
+	if page < 1 {
+		page = 1
+	}
+	page_z, _ := c.GetInt("page_z")
+	if page_z < 1 {
+		page_z = conf.Page_size
+	}
+
+	T_name := c.GetString("T_name")
+
+	ReimburseDao := Reimburse.NewReimburse(orm.NewOrm())
+
+	uuidList := ReimburseDao.Read_T_uuid_List()
+	if len(uuidList) == 0 {
+		c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
+		c.ServeJSON()
+		return
+	}
+
+	WaitAuditList := ReimburseDao.Read_T_uuid_List_by_State(Reimburse.WaitAudit)
+	WaitAuditListMap := make(map[string]struct{})
+	for _, v := range WaitAuditList {
+		WaitAuditListMap[v] = struct{}{}
+	}
+
+	type User struct {
+		userlibs.User
+		T_wait_audit bool `json:"T_wait_audit"`
+	}
+
+	R_List, R_cnt, err := NatsServer.Read_User_List_T_uuid(T_name, uuidList, page, page_z)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败"}
+		c.ServeJSON()
+		return
+	}
+
+	var U_List []User
+	for _, user := range R_List {
+		var T_wait_audit bool
+		if _, ok := WaitAuditListMap[user.T_uuid]; ok {
+			T_wait_audit = true
+		}
+		U_List = append(U_List, User{user, T_wait_audit})
+	}
+
+	r_jsons.Num = R_cnt
+	r_jsons.Data = U_List
+	r_jsons.Page = page
+	r_jsons.Page_size = int(math.Ceil(float64(R_cnt) / float64(page_z)))
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons}
+	c.ServeJSON()
+	return
+}
+
+// 消费类型
+
+func (c *ReimburseController) FeeType_List() {
+
+	type Reimburse_R struct {
+		Id         int
+		T_name     string
+		T_mid      int
+		T_State    int
+		FeeDetails []Reimburse.FeeType
+	}
+	var res []Reimburse_R
+	list := Reimburse.Read_FeeType_List()
+
+	for _, v := range list {
+		res = append(res, Reimburse_R{
+			Id:         v.Id,
+			T_name:     v.T_name,
+			T_mid:      v.T_mid,
+			T_State:    v.T_State,
+			FeeDetails: Reimburse.Read_FeeDetails_List(v.Id),
+		})
+	}
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: res}
+	c.ServeJSON()
+	return
+}
+
+//func (c *ReimburseController) FeeType_List() {
+//	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: Reimburse.Read_FeeType_List()}
+//	c.ServeJSON()
+//	return
+//}
+
+// 消费明细
+func (c *ReimburseController) FeeDetails_List() {
+	T_feeType, _ := c.GetInt("T_feeType")
+	if T_feeType == 0 {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_feeType Err!"}
+		c.ServeJSON()
+		return
+	}
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: Reimburse.Read_FeeDetails_List(T_feeType)}
+	c.ServeJSON()
+	return
+}
+
+// 管理元报销列表
+func (c *ReimburseController) Reimburse_List() {
+	// 分页参数 初始化
+	page, _ := c.GetInt("page")
+	if page < 1 {
+		page = 1
+	}
+	page_z, _ := c.GetInt("page_z")
+	if page_z < 1 {
+		page_z = conf.Page_size
+	}
+	T_uuid := c.GetString("T_uuid")
+
+	userList, _ := NatsServer.Read_User_List_All()
+	Account.Read_User_All_Map(userList)
+
+	ReimburseDao := Reimburse.NewReimburse(orm.NewOrm())
+	reimburse_List, num := ReimburseDao.Read_Reimburse_Finance_List(T_uuid, page, page_z)
+
+	var r_jsons lib.R_JSONS
+	r_jsons.Data = reimburse_List
+	r_jsons.Num = num
+	r_jsons.Page = page
+	r_jsons.Page_size = int(math.Ceil(float64(num) / float64(page_z)))
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons}
+	c.ServeJSON()
+	return
+}
+
+// 员工报销列表
+func (c *ReimburseController) Reimburse_User_List() {
+	// 分页参数 初始化
+	page, _ := c.GetInt("page")
+	if page < 1 {
+		page = 1
+	}
+	page_z, _ := c.GetInt("page_z")
+	if page_z < 1 {
+		page_z = conf.Page_size
+	}
+
+	userList, _ := NatsServer.Read_User_List_All()
+	Account.Read_User_All_Map(userList)
+
+	ReimburseDao := Reimburse.NewReimburse(orm.NewOrm())
+	reimburse_List, num := ReimburseDao.Read_Reimburse_List(c.User.T_uuid, page, page_z)
+
+	var r_jsons lib.R_JSONS
+	r_jsons.Data = reimburse_List
+	r_jsons.Num = num
+	r_jsons.Page = page
+	r_jsons.Page_size = int(math.Ceil(float64(num) / float64(page_z)))
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons}
+	c.ServeJSON()
+	return
+}
+
+func (c *ReimburseController) Reimburse_Add() {
+
+	type RequestBody struct {
+		User_tokey       string
+		ReimburseDetails []Reimburse.ReimburseDetails
+		T_money          float32
+	}
+
+	var body RequestBody
+	data := c.Ctx.Input.RequestBody
+	err := json.Unmarshal(data, &body)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "json.Unmarshal is err:" + err.Error()}
+		c.ServeJSON()
+	}
+
+	if len(body.ReimburseDetails) == 0 {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "报销明细不能为空"}
+		c.ServeJSON()
+		return
+	}
+
+	user_r, err := NatsServer.Verification(body.User_tokey, "")
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 201, Msg: "请重新登陆!"}
+		c.ServeJSON()
+		return
+	}
+	// 权限验证
+	c.CheckRBAC(user_r.T_power)
+
+	var_ := Reimburse.Reimburse{
+		T_uid:   user_r.T_uuid,
+		T_date:  time.Now().Format("2006-01-02"),
+		T_money: body.T_money,
+		T_State: Reimburse.WaitSubmit,
+	}
+
+	o := orm.NewOrm()
+	o.Begin()
+	ReimburseDao := Reimburse.NewReimburse(o)
+	ReimburseDetailsDao := Reimburse.NewReimburseDetails(o)
+
+	id, err := ReimburseDao.Add_Reimburse(var_)
+	if err != nil {
+		o.Rollback()
+		c.Data["json"] = lib.JSONS{Code: 203, Msg: "添加失败"}
+		c.ServeJSON()
+		return
+	}
+
+	for _, v := range body.ReimburseDetails {
+		reimburseDetails := Reimburse.ReimburseDetails{
+			T_reimburse_id:    int(id),
+			T_trip_start_time: v.T_trip_start_time,
+			T_trip_end_time:   v.T_trip_end_time,
+			T_trip_origin:     v.T_trip_origin,
+			T_trip_terminus:   v.T_trip_terminus,
+			T_fee_type:        v.T_fee_type,
+			T_fee_details:     v.T_fee_details,
+			T_money:           v.T_money,
+			T_reasons:         v.T_reasons,
+			T_project:         v.T_project,
+			T_img:             v.T_img,
+			T_State:           1,
+		}
+		_, err = ReimburseDetailsDao.Add_ReimburseDetails(reimburseDetails)
+		if err != nil {
+			o.Rollback()
+			c.Data["json"] = lib.JSONS{Code: 203, Msg: "添加失败"}
+			c.ServeJSON()
+			return
+		}
+
+	}
+	o.Commit()
+	NatsServer.AddUserLogs(c.User.T_uuid, "报销", "添加", var_)
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: id}
+	c.ServeJSON()
+	return
+}
+
+func (c *ReimburseController) Reimburse_Edit() {
+	type RequestBody struct {
+		User_tokey       string
+		ReimburseDetails []Reimburse.ReimburseDetails
+		T_money          float32
+		T_id             int
+	}
+
+	var body RequestBody
+	data := c.Ctx.Input.RequestBody
+	err := json.Unmarshal(data, &body)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "json.Unmarshal is err:" + err.Error()}
+		c.ServeJSON()
+	}
+
+	user_r, err := NatsServer.Verification(body.User_tokey, "")
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 201, Msg: "请重新登陆!"}
+		c.ServeJSON()
+		return
+	}
+	// 权限验证
+	c.CheckRBAC(user_r.T_power)
+
+	o := orm.NewOrm()
+	o.Begin()
+	ReimburseDao := Reimburse.NewReimburse(o)
+	ReimburseDetailsDao := Reimburse.NewReimburseDetails(o)
+
+	reimburse, err := ReimburseDao.Read_Reimburse_ById(body.T_id)
+	if err != nil {
+		o.Rollback()
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "Id Err"}
+		c.ServeJSON()
+		return
+	}
+
+	if len(body.ReimburseDetails) == 0 {
+		o.Rollback()
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "报销明细不能为空"}
+		c.ServeJSON()
+		return
+	}
+
+	reimburse.T_money = body.T_money
+	_, err = ReimburseDao.Update_Reimburse(reimburse, "T_money")
+	if err != nil {
+		o.Rollback()
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "Id Err"}
+		c.ServeJSON()
+		return
+	}
+
+	// 删除之前的报销明细
+	err = ReimburseDetailsDao.Delete_ReimburseDetails(body.T_id)
+	if err != nil {
+		o.Rollback()
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "修改失败"}
+		c.ServeJSON()
+		return
+	}
+
+	for _, v := range body.ReimburseDetails {
+		reimburseDetails := Reimburse.ReimburseDetails{
+			T_reimburse_id:    reimburse.Id,
+			T_trip_start_time: v.T_trip_start_time,
+			T_trip_end_time:   v.T_trip_end_time,
+			T_trip_origin:     v.T_trip_origin,
+			T_trip_terminus:   v.T_trip_terminus,
+			T_fee_type:        v.T_fee_type,
+			T_fee_details:     v.T_fee_details,
+			T_money:           v.T_money,
+			T_reasons:         v.T_reasons,
+			T_project:         v.T_project,
+			T_img:             v.T_img,
+			T_State:           1,
+		}
+		_, err = ReimburseDetailsDao.Add_ReimburseDetails(reimburseDetails)
+		if err != nil {
+			o.Rollback()
+			c.Data["json"] = lib.JSONS{Code: 202, Msg: "修改失败"}
+			c.ServeJSON()
+			return
+		}
+
+	}
+	o.Commit()
+
+	NatsServer.AddUserLogs(c.User.T_uuid, "报销", "修改", reimburse)
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: reimburse.Id}
+	c.ServeJSON()
+	return
+}
+func (c *ReimburseController) Reimburse_Del() {
+
+	T_id, _ := c.GetInt("T_id")
+
+	o := orm.NewOrm()
+	o.Begin()
+	ReimburseDao := Reimburse.NewReimburse(o)
+	ReimburseDetailsDao := Reimburse.NewReimburseDetails(o)
+
+	reimburse, err := ReimburseDao.Read_Reimburse_ById(T_id)
+	if err != nil {
+		o.Rollback()
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_id Err!"}
+		c.ServeJSON()
+		return
+	}
+	if reimburse.T_State == Reimburse.AuditPass || reimburse.T_State == Reimburse.RemitPart || reimburse.T_State == Reimburse.RemitAll {
+		o.Rollback()
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "合同已审核通过或已打款,禁止删除!"}
+		c.ServeJSON()
+		return
+	}
+
+	_, err = ReimburseDao.Delete_Reimburse(reimburse)
+	if err != nil {
+		o.Rollback()
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "删除失败!"}
+		c.ServeJSON()
+		return
+	}
+	//删除报销明细
+	err = ReimburseDetailsDao.Delete_ReimburseDetails(reimburse.Id)
+	if err != nil {
+		o.Rollback()
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "删除失败!"}
+		c.ServeJSON()
+		return
+	}
+	o.Commit()
+
+	NatsServer.AddUserLogs(c.User.T_uuid, "报销", "删除", err)
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: reimburse.Id}
+	c.ServeJSON()
+	return
+}
+func (c *ReimburseController) Reimburse_Get() {
+	logs.Info("header=======", c.Ctx.Request.Header.Get("User_tokey"))
+
+	T_id, _ := c.GetInt("T_id")
+
+	o := orm.NewOrm()
+	ReimburseDao := Reimburse.NewReimburse(o)
+	ReimburseDetailsDao := Reimburse.NewReimburseDetails(o)
+
+	Reimburse.Read_FeeType_All_Map()
+	reimburse, err := ReimburseDao.Read_Reimburse_ById(T_id)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_id Err!"}
+		c.ServeJSON()
+		return
+	}
+
+	//删除报销明细
+	reimburseDetailsList, err := ReimburseDetailsDao.Read_ReimburseDetailsList_ByT_reimburse_id(reimburse.Id)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败!"}
+		c.ServeJSON()
+		return
+	}
+
+	var pList []Reimburse.ReimburseDetails_R
+	for _, v := range reimburseDetailsList {
+		p := Reimburse.ReimburseDetailsToReimburseDetails_R(v)
+		pList = append(pList, p)
+	}
+
+	NatsServer.AddUserLogs(c.User.T_uuid, "报销", "删除", err)
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: Reimburse.ReimburseToReimburse_Detail(reimburse, pList)}
+	c.ServeJSON()
+	return
+}
+
+// 提交审核
+func (c *ReimburseController) Reimburse_Submit_Audit() {
+
+	T_id, _ := c.GetInt("T_id")
+
+	o := orm.NewOrm()
+	ReimburseDao := Reimburse.NewReimburse(o)
+
+	reimburse, err := ReimburseDao.Read_Reimburse_ById(T_id)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_id Err!"}
+		c.ServeJSON()
+		return
+	}
+	if c.User.T_uuid != reimburse.T_uid {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "没有权限!"}
+		c.ServeJSON()
+		return
+	}
+	if reimburse.T_State != Reimburse.WaitSubmit && reimburse.T_State != Reimburse.AuditUnPass {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("状态为%s,禁止提交审核!", Reimburse.Read_Audit_Get(reimburse.T_State))}
+		c.ServeJSON()
+		return
+	}
+
+	reimburse.T_State = Reimburse.WaitAudit
+	_, err = ReimburseDao.Update_Reimburse(reimburse, "T_State")
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "提交审核失败!"}
+		c.ServeJSON()
+		return
+	}
+	NatsServer.AddUserLogs(c.User.T_uuid, "报销", "提交审核", err)
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: T_id}
+	c.ServeJSON()
+	return
+}
+
+// 修改审核状态
+func (c *ReimburseController) Reimburse_Edit_Audit() {
+
+	T_id, _ := c.GetInt("T_id")
+	T_State, _ := c.GetInt("T_State")
+
+	o := orm.NewOrm()
+	ReimburseDao := Reimburse.NewReimburse(o)
+
+	reimburse, err := ReimburseDao.Read_Reimburse_ById(T_id)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_id Err!"}
+		c.ServeJSON()
+		return
+	}
+	if reimburse.T_State == Reimburse.WaitSubmit {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("状态为%s,禁止修改!", Reimburse.Read_Audit_Get(reimburse.T_State))}
+		c.ServeJSON()
+		return
+	}
+
+	if T_State == Reimburse.RemitPart || T_State == Reimburse.RemitAll {
+		if reimburse.T_State != Reimburse.AuditPass && reimburse.T_State != Reimburse.RemitPart {
+			c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("状态为%s,禁止修改!", Reimburse.Read_Audit_Get(reimburse.T_State))}
+			c.ServeJSON()
+			return
+		}
+	}
+
+	if T_State == Reimburse.AuditPass || T_State == Reimburse.AuditUnPass {
+		if reimburse.T_State != Reimburse.WaitAudit && T_State != Reimburse.AuditUnPass {
+			c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("状态为%s,禁止修改!", Reimburse.Read_Audit_Get(reimburse.T_State))}
+			c.ServeJSON()
+			return
+		}
+	}
+
+	reimburse.T_State = T_State
+	_, err = ReimburseDao.Update_Reimburse(reimburse, "T_State")
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "修改审核状态失败!"}
+		c.ServeJSON()
+		return
+	}
+	NatsServer.AddUserLogs(c.User.T_uuid, "报销", "修改审核状态", err)
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: T_id}
+	c.ServeJSON()
+	return
+}
+
+// 修改打款明细
+func (c *ReimburseController) Reimburse_Edit_Remit() {
+
+	T_id, _ := c.GetInt("T_id")
+	T_remit_detials := c.GetString("T_remit_detials")
+
+	o := orm.NewOrm()
+	ReimburseDao := Reimburse.NewReimburse(o)
+
+	reimburse, err := ReimburseDao.Read_Reimburse_ById(T_id)
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "T_id Err!"}
+		c.ServeJSON()
+		return
+	}
+
+	// 1 未提交审核 2 待审核 3 审核通过 4 审核不通过 5 已部分打款 6 已全部打款
+	if reimburse.T_State != Reimburse.AuditPass && reimburse.T_State != Reimburse.RemitPart && reimburse.T_State != Reimburse.RemitAll {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: fmt.Sprintf("状态为%s,禁止修改!", Reimburse.Read_Audit_Get(reimburse.T_State))}
+		c.ServeJSON()
+		return
+	}
+
+	remitList := Reimburse.ReimburseToRemitDetail(T_remit_detials)
+	var T_remit float32
+	for _, r := range remitList {
+		T_remit += r.T_money
+	}
+
+	if T_remit == 0 {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "打款金额不正确!"}
+		c.ServeJSON()
+		return
+	}
+
+	if T_remit == reimburse.T_money {
+		reimburse.T_State = Reimburse.RemitAll
+	} else if T_remit < reimburse.T_money {
+		reimburse.T_State = Reimburse.RemitPart
+	}
+
+	reimburse.T_remit = T_remit
+	reimburse.T_remit_detials = T_remit_detials
+	_, err = ReimburseDao.Update_Reimburse(reimburse, "T_State", "T_remit", "T_remit_detials")
+	if err != nil {
+		c.Data["json"] = lib.JSONS{Code: 202, Msg: "修改审核状态失败!"}
+		c.ServeJSON()
+		return
+	}
+	NatsServer.AddUserLogs(c.User.T_uuid, "报销", "修改打款明细", err)
+
+	c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: T_id}
+	c.ServeJSON()
+	return
+}

BIN=BIN
img.png


+ 1 - 1
main.go

@@ -38,7 +38,7 @@ func main() {
 		// 可选参数"GET", "POST", "PUT", "DELETE", "OPTIONS" (*为所有)
 		AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
 		// 指的是允许的Header的种类
-		AllowHeaders: []string{"Origin", "Authorization", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Content-Type"},
+		AllowHeaders: []string{"Origin", "Authorization", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Content-Type", "User_tokey"},
 		// 公开的HTTP标头列表
 		ExposeHeaders: []string{"Content-Length", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Content-Type"},
 		// 如果设置,则允许共享身份验证凭据,例如cookie

+ 299 - 0
models/Reimburse/Reimburse.go

@@ -0,0 +1,299 @@
+package Reimburse
+
+import (
+	"ERP_salary/logs"
+	"ERP_salary/models/Account"
+	"fmt"
+	"git.baozhida.cn/ERP_libs/lib"
+	"github.com/beego/beego/v2/adapter/orm"
+	orm2 "github.com/beego/beego/v2/client/orm"
+	"strconv"
+	"strings"
+	"time"
+)
+
+const (
+	Delete      int = iota
+	WaitSubmit      // 待提交审核
+	WaitAudit       // 待审核
+	AuditPass       // 审核通过
+	AuditUnPass     // 审核不通过
+	RemitPart       // 部分打款
+	RemitAll        // 全部打款
+
+)
+
+var (
+	AuditMap = map[int]string{
+		WaitSubmit:  "待提交审核",
+		WaitAudit:   "待审核",
+		AuditPass:   "审核通过",
+		AuditUnPass: "审核不通过",
+		RemitPart:   "部分打款",
+		RemitAll:    "全部打款",
+	}
+)
+
+func Read_Audit_Get(Id int) string {
+	v, ok := AuditMap[Id]
+	if ok {
+		return v
+	} else {
+		return "未知状态"
+	}
+}
+
+// 报销
+type Reimburse struct {
+	Id              int       `orm:"column(ID);size(11);auto;pk"`
+	T_uid           string    `orm:"index;size(64);null"`                                   // 用户uuid
+	T_date          string    `orm:"size(64);null"`                                         // 提交日期,2023-08-11
+	T_money         float32   `orm:"digits(12);decimals(2)"`                                // 报销总金额
+	T_remit         float32   `orm:"digits(12);decimals(2)"`                                // 打款金额
+	T_State         int       `orm:"size(20);default(1)"`                                   // 0 删除 1 未提交审核 2 待审核 3 审核通过 4 审核不通过 5 已部分打款 6 已全部打款
+	T_remit_detials string    `orm:"digits(1024);decimals(2)"`                              // 打款明细 日期,打款金额|日期,打款金额|
+	CreateTime      time.Time `orm:"column(create_time);type(timestamp);null;auto_now_add"` //auto_now_add 第一次保存时才设置时间
+	UpdateTime      time.Time `orm:"column(update_time);type(timestamp);null;auto_now"`     //auto_now 每次 model 保存时都会对时间自动更新
+}
+
+func (t *Reimburse) TableName() string {
+	return "reimburse"
+}
+
+type ReimburseDaoImpl struct {
+	orm orm.Ormer
+}
+
+func NewReimburse(orm orm.Ormer) *ReimburseDaoImpl {
+	return &ReimburseDaoImpl{orm: orm}
+}
+func init() {
+	//注册模型
+	orm.Debug = true
+	orm.RegisterModel(new(Reimburse))
+}
+
+type Reimburse_R struct {
+	Id          int
+	T_uid       string  // 用户uuid
+	T_user_name string  // 用户名称
+	T_date      string  // 提交日期,2023-08-11
+	T_money     float32 // 报销总金额
+	T_remit     float32 // 打款金额
+	T_State     int     // 0 删除 1 未提交审核 2 待审核 3 审核通过 4 审核不通过 5 已部分打款 6 已全部打款
+
+}
+
+type RemitDetail_R struct {
+	T_time  string  // 打款时间
+	T_money float32 // 打款金额
+}
+type Reimburse_Detail struct {
+	Id                  int
+	T_uid               string               // 用户uuid
+	T_user_name         string               // 用户名称
+	T_date              string               // 提交日期,2023-08-11
+	T_money             float32              // 报销总金额
+	T_remit             float32              // 打款金额
+	T_State             int                  // 0 删除 1 未提交审核 2 待审核 3 审核通过 4 审核不通过 5 已部分打款 6 已全部打款
+	T_reimburse_details []ReimburseDetails_R // 报销明细
+	T_remit_detail      []RemitDetail_R      // 打款明细
+}
+
+// ---------------- 特殊方法 -------------------
+func ReimburseToReimburse_R(t Reimburse) (r Reimburse_R) {
+
+	r.Id = t.Id
+	r.T_uid = t.T_uid
+	r.T_user_name = Account.Read_User_T_name_Get(t.T_uid)
+	r.T_date = t.T_date
+	r.T_money = t.T_money
+	r.T_remit = t.T_remit
+	r.T_State = t.T_State
+	return r
+}
+func ReimburseToReimburse_Detail(t Reimburse, T_reimburse_details []ReimburseDetails_R) (r Reimburse_Detail) {
+
+	r.Id = t.Id
+	r.T_uid = t.T_uid
+	r.T_user_name = Account.Read_User_T_name_Get(t.T_uid)
+	r.T_date = t.T_date
+	r.T_money = t.T_money
+	r.T_remit = t.T_remit
+	r.T_State = t.T_State
+	r.T_reimburse_details = T_reimburse_details
+	r.T_remit_detail = ReimburseToRemitDetail(t.T_remit_detials)
+	return r
+}
+
+func ReimburseToRemitDetail(T_detail string) (r []RemitDetail_R) {
+
+	if len(T_detail) == 0 {
+		return
+	}
+
+	detailList := strings.Split(strings.Trim(T_detail, "|"), "|")
+
+	for _, detail := range detailList {
+
+		T_time := strings.Split(detail, ",")[0]
+		T_money := lib.StringToFloat64TwoDecimal(strings.Split(detail, ",")[1])
+
+		r = append(r, RemitDetail_R{
+			T_time:  T_time,
+			T_money: float32(T_money),
+		})
+	}
+	return r
+}
+
+func (dao *ReimburseDaoImpl) Read_Reimburse_ById(id int) (r Reimburse, err error) {
+	o := orm.NewOrm()
+	r = Reimburse{Id: id}
+	err = o.Read(&r)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return r, err
+	}
+	return r, err
+}
+
+// 添加
+func (dao *ReimburseDaoImpl) Add_Reimburse(m Reimburse) (id int64, err error) {
+	o := orm.NewOrm()
+	id, err = o.Insert(&m)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return
+	}
+	return
+}
+
+// 修改
+func (dao *ReimburseDaoImpl) Update_Reimburse(m Reimburse, cols ...string) (id int64, err error) {
+	o := orm.NewOrm()
+	id, err = o.Update(&m, cols...)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return
+	}
+	fmt.Println("Number of records updated in database:", id)
+	return id, nil
+}
+
+// 删除
+func (dao *ReimburseDaoImpl) Delete_Reimburse(m Reimburse) (id int64, err error) {
+
+	o := orm.NewOrm()
+	m.T_State = Delete
+	id, err = o.Update(&m, "T_State")
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return
+	}
+	fmt.Println("Number of records updated in database:", id)
+	return id, nil
+}
+
+// 获取列表
+func (dao *ReimburseDaoImpl) Read_Reimburse_List(T_uid string, page, page_z int) (r []Reimburse_R, cnt int64) {
+
+	o := orm.NewOrm()
+	// 也可以直接使用 Model 结构体作为表名
+	var map_r []Reimburse
+	qs := o.QueryTable(new(Reimburse))
+	var offset int64
+	if page <= 1 {
+		offset = 0
+	} else {
+		offset = int64((page - 1) * page_z)
+	}
+
+	cond := orm.NewCondition()
+	cond = cond.And("T_State__gt", Delete)
+	if len(T_uid) > 0 {
+		cond = cond.And("T_uid", T_uid)
+	}
+	var err error
+	_, err = qs.Limit(page_z, offset).SetCond((*orm2.Condition)(cond)).OrderBy("-Id").All(&map_r)
+
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return
+	}
+	cnt, err = qs.SetCond((*orm2.Condition)(cond)).Count()
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return
+	}
+
+	for _, v := range map_r {
+		r = append(r, ReimburseToReimburse_R(v))
+	}
+
+	return r, cnt
+
+}
+
+// 获取列表
+func (dao *ReimburseDaoImpl) Read_Reimburse_Finance_List(T_uuid string, page, page_z int) (r []Reimburse_R, cnt int64) {
+
+	o := orm.NewOrm()
+	// 也可以直接使用 Model 结构体作为表名
+	var map_r []Reimburse
+	qs := o.QueryTable(new(Reimburse))
+	var offset int64
+	if page <= 1 {
+		offset = 0
+	} else {
+		offset = int64((page - 1) * page_z)
+	}
+
+	cond := orm.NewCondition()
+	state := []int{WaitAudit, AuditPass, AuditUnPass, RemitPart, RemitAll}
+	cond = cond.And("T_uid", T_uuid).And("T_State__in", state)
+
+	var err error
+	_, err = qs.Limit(page_z, offset).SetCond((*orm2.Condition)(cond)).OrderBy("-Id").All(&map_r)
+
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return
+	}
+	cnt, err = qs.SetCond((*orm2.Condition)(cond)).Count()
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return
+	}
+
+	for _, v := range map_r {
+		r = append(r, ReimburseToReimburse_R(v))
+	}
+
+	return r, cnt
+
+}
+
+func (dao *ReimburseDaoImpl) Read_T_uuid_List_by_State(state int) (lists []string) {
+
+	o := orm.NewOrm()
+	sql := "SELECT DISTINCT t_uid FROM reimburse WHERE t__state =" + strconv.Itoa(state) + " LIMIT 0,1000"
+	_, err := o.Raw(sql).QueryRows(&lists)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return
+	}
+	return lists
+}
+
+func (dao *ReimburseDaoImpl) Read_T_uuid_List() (lists []string) {
+
+	o := orm.NewOrm()
+	sql := "SELECT DISTINCT t_uid FROM reimburse LIMIT 0,1000"
+	_, err := o.Raw(sql).QueryRows(&lists)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return
+	}
+	return lists
+}

+ 151 - 0
models/Reimburse/ReimburseDetails.go

@@ -0,0 +1,151 @@
+package Reimburse
+
+import (
+	"ERP_salary/logs"
+	"git.baozhida.cn/ERP_libs/lib"
+	"github.com/beego/beego/v2/adapter/orm"
+	orm2 "github.com/beego/beego/v2/client/orm"
+
+	//"github.com/beego/beego/v2/client/orm"
+	"time"
+)
+
+// 报销明细
+type ReimburseDetails struct {
+	Id                int       `orm:"column(ID);size(11);auto;pk"`
+	T_reimburse_id    int       `orm:"index;size(64);null"`                                   // 报销id
+	T_trip_start_time string    `orm:"size(64);null"`                                         // 出差开始时间
+	T_trip_end_time   string    `orm:"size(64);null"`                                         // 出差结束时间
+	T_trip_origin     string    `orm:"size(128);null"`                                        // 出差起点
+	T_trip_terminus   string    `orm:"size(128);null"`                                        // 出差起点
+	T_fee_type        int       `orm:"size(11);null"`                                         // 费用类型
+	T_fee_details     int       `orm:"size(11);null"`                                         // 费用明细
+	T_money           float32   `orm:"digits(12);decimals(2)"`                                // 费用金额
+	T_reasons         string    `orm:"size(1024);null"`                                       // 费用事由
+	T_project         string    `orm:"size(1024);null"`                                       // 涉及项目
+	T_img             string    `orm:"size(1024);null"`                                       // 图片链接
+	T_State           int       `orm:"size(20);default(1)"`                                   // 0 删除 1 正常
+	CreateTime        time.Time `orm:"column(create_time);type(timestamp);null;auto_now_add"` //auto_now_add 第一次保存时才设置时间
+	UpdateTime        time.Time `orm:"column(update_time);type(timestamp);null;auto_now"`     //auto_now 每次 model 保存时都会对时间自动更新
+}
+
+func (t *ReimburseDetails) TableName() string {
+	return "reimburse_details"
+}
+func init() {
+	//注册模型
+	orm.RegisterModel(new(ReimburseDetails))
+}
+
+type ReimburseDetails_R struct {
+	Id                 int
+	T_reimburse_id     int     // 报销id
+	T_trip_start_time  string  // 出差开始时间
+	T_trip_end_time    string  // 出差结束时间
+	T_trip_origin      string  // 出差起点
+	T_trip_terminus    string  // 出差起点
+	T_fee_type         int     // 费用类型
+	T_fee_type_name    string  // 费用类型名称
+	T_fee_details      int     // 费用明细
+	T_fee_details_name string  // 费用明细名称
+	T_money            float32 // 费用金额
+	T_reasons          string  // 费用事由
+	T_project          string  // 涉及项目
+	T_img              string  // 图片链接
+	T_State            int     // 0 删除 1 正常
+
+}
+
+// ---------------- 特殊方法 -------------------
+func ReimburseDetailsToReimburseDetails_R(t ReimburseDetails) (r ReimburseDetails_R) {
+	r.T_reimburse_id = t.T_reimburse_id
+	r.T_trip_start_time = t.T_trip_start_time
+	r.T_trip_end_time = t.T_trip_end_time
+	r.T_trip_origin = t.T_trip_origin
+	r.T_trip_terminus = t.T_trip_terminus
+	r.T_fee_type = t.T_fee_type
+	r.T_fee_type_name = Read_FeeType_Get(t.T_fee_type)
+	r.T_fee_details = t.T_fee_details
+	r.T_fee_details_name = Read_FeeType_Get(t.T_fee_details)
+	r.T_money = t.T_money
+	r.T_reasons = t.T_reasons
+	r.T_project = t.T_project
+	r.T_img = t.T_img
+	r.T_State = t.T_State
+	return r
+}
+
+type ReimburseDetailsDaoImpl struct {
+	orm orm.Ormer
+}
+
+func NewReimburseDetails(orm orm.Ormer) *ReimburseDetailsDaoImpl {
+	return &ReimburseDetailsDaoImpl{orm: orm}
+}
+
+func (dao *ReimburseDetailsDaoImpl) Add_ReimburseDetails(r ReimburseDetails) (id int64, err error) {
+	id, err = dao.orm.Insert(&r)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+	}
+	return id, err
+}
+
+// 获取 ById
+func (dao *ReimburseDetailsDaoImpl) Read_ReimburseDetailsList_ByT_reimburse_id(T_reimburse_id int) (r []ReimburseDetails, err error) {
+	qs := dao.orm.QueryTable(new(ReimburseDetails))
+
+	_, err = qs.Filter("T_reimburse_id", T_reimburse_id).Filter("T_State__gt", 0).All(&r)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+	}
+	return
+}
+
+// 修改
+func (dao *ReimburseDetailsDaoImpl) Update_ReimburseDetails(m ReimburseDetails, cols ...string) error {
+	_, err := dao.orm.Update(&m, cols...)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return err
+	}
+	return nil
+}
+
+// 删除
+func (dao *ReimburseDetailsDaoImpl) Delete_ReimburseDetails(T_reimburse_id int) error {
+	qs := dao.orm.QueryTable(new(ReimburseDetails))
+	//_, err := qs.Filter("T_reimburse_id", T_reimburse_id).Update(map[string]interface{}{
+	//	"T_State": 0,
+	//})
+
+	_, err := qs.Filter("T_reimburse_id", T_reimburse_id).Delete()
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+	}
+	return err
+}
+
+// 获取列表
+func (dao *ReimburseDetailsDaoImpl) Read_ReimburseDetails_List(T_reimburse_id string) (r_ []ReimburseDetails) {
+	var maps []ReimburseDetails
+	// 也可以直接使用 Model 结构体作为表名
+	qs := dao.orm.QueryTable(new(ReimburseDetails))
+	// 过滤
+	cond := orm.NewCondition()
+	cond = cond.And("T_State__gt", 0)
+
+	if len(T_reimburse_id) > 0 {
+		cond = cond.And("T_reimburse_id", T_reimburse_id)
+	}
+
+	// 查询
+	_, err := qs.SetCond((*orm2.Condition)(cond)).OrderBy("Id").All(&maps)
+
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return
+	}
+
+	return maps
+}

+ 71 - 0
models/Reimburse/feeType.go

@@ -0,0 +1,71 @@
+package Reimburse
+
+import (
+	"ERP_salary/logs"
+	"git.baozhida.cn/ERP_libs/lib"
+	"github.com/beego/beego/v2/adapter/orm"
+	"sync"
+)
+
+type FeeType struct {
+	Id      int    `orm:"column(ID);size(11);auto;pk"`
+	T_name  string `orm:"size(256);null"`       //  费用名称名称
+	T_mid   int    `orm:"size(256);null"`       //  FeeType.Id  T_mid=0 费用类型 T_mid>0费用明细
+	T_State int    `orm:"size(200);default(1)"` //  0删除  1 正常
+}
+
+var FeeType_list *sync.Map
+
+func init() {
+	//注册模型
+	orm.RegisterModel(new(FeeType))
+	FeeType_list = new(sync.Map)
+}
+
+// 获取全部
+func Read_FeeType_All_Map() {
+	logs.Println("=========== 初始化费用类型 =========")
+
+	o := orm.NewOrm()
+	var r []FeeType
+	qs := o.QueryTable(new(FeeType))
+	_, err := qs.Filter("T_State", 1).All(&r)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+	}
+
+	for _, v := range r {
+		FeeType_list.Store(v.Id, v.T_name)
+	}
+
+}
+func Read_FeeType_Get(Id int) string {
+	v, ok := FeeType_list.Load(Id)
+	if ok {
+		return v.(string)
+	} else {
+		return ""
+	}
+}
+
+func Read_FeeType_List() (r []FeeType) {
+	o := orm.NewOrm()
+	qs := o.QueryTable(new(FeeType))
+	_, err := qs.Filter("T_State", 1).Filter("T_mid", 0).All(&r)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return r
+	}
+	return r
+}
+
+func Read_FeeDetails_List(T_feeType int) (r []FeeType) {
+	o := orm.NewOrm()
+	qs := o.QueryTable(new(FeeType))
+	_, err := qs.Filter("T_State", 1).Filter("T_mid", T_feeType).All(&r)
+	if err != nil {
+		logs.Error(lib.FuncName(), err)
+		return r
+	}
+	return r
+}

+ 19 - 1
routers/router.go

@@ -22,5 +22,23 @@ func init() {
 		beego.NSRouter("/Excel", &controllers.SalaryController{}, "*:Salary_Excel"),         // 导出excel
 	)
 
-	beego.AddNamespace(ns)
+	ns2 := beego.NewNamespace("/Reimburse",
+		//-----------费用类型
+		beego.NSRouter("/FeeType/List", &controllers.ReimburseController{}, "*:FeeType_List"), //费用类型列表
+		//-----------费用明细
+		//beego.NSRouter("/FeeDetails/List", &controllers.ReimburseController{}, "*:FeeDetails_List"), // 费用明细列表
+		//-----------左侧员工列表(只显示提交过报销的)
+		beego.NSRouter("/User/List", &controllers.ReimburseController{}, "*:User_List"),                 // 左侧用户列表
+		beego.NSRouter("/List", &controllers.ReimburseController{}, "*:Reimburse_List"),                 // 管理员报销列表
+		beego.NSRouter("/User_List", &controllers.ReimburseController{}, "*:Reimburse_User_List"),       // 员工报销列表
+		beego.NSRouter("/Add", &controllers.ReimburseController{}, "*:Reimburse_Add"),                   // 添加报销
+		beego.NSRouter("/Edit", &controllers.ReimburseController{}, "*:Reimburse_Edit"),                 // 修改报销
+		beego.NSRouter("/Del", &controllers.ReimburseController{}, "*:Reimburse_Del"),                   // 删除报销
+		beego.NSRouter("/Get", &controllers.ReimburseController{}, "*:Reimburse_Get"),                   // 报销详情
+		beego.NSRouter("/Submit_Audit", &controllers.ReimburseController{}, "*:Reimburse_Submit_Audit"), // 提交审核
+		beego.NSRouter("/Edit_Audit", &controllers.ReimburseController{}, "*:Reimburse_Edit_Audit"),     // 修改审核状态
+		beego.NSRouter("/Edit_Remit", &controllers.ReimburseController{}, "*:Reimburse_Edit_Remit"),     // 修改打款明细
+	)
+
+	beego.AddNamespace(ns, ns2)
 }