salarybill
This commit is contained in:
parent
de6cfbc773
commit
54e05acc91
|
@ -13,6 +13,16 @@ var (
|
|||
StaffSalaryStatusPayed = 2
|
||||
)
|
||||
|
||||
type SalaryBillLine struct {
|
||||
Label string
|
||||
Value string
|
||||
}
|
||||
|
||||
type SalaryBillSection struct {
|
||||
Name string
|
||||
Line []*SalaryBillLine
|
||||
}
|
||||
|
||||
type StaffSalary struct {
|
||||
Id int64
|
||||
CorpId int64
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>工资单</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
background: linear-gradient(135deg, #e0f7fa 0%, #b2ebf2 100%);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.payroll-container {
|
||||
background: white;
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
|
||||
padding: 30px;
|
||||
width: 90%;
|
||||
max-width: 500px;
|
||||
animation: fadeIn 0.6s ease;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
color: #00838f;
|
||||
font-size: 28px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.section {
|
||||
background: #f9f9f9;
|
||||
border-radius: 10px;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #006064;
|
||||
font-size: 20px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
.info-row:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.total-row {
|
||||
font-weight: bold;
|
||||
font-size: 1.2em;
|
||||
color: #00838f;
|
||||
border-top: 2px solid #00838f;
|
||||
padding-top: 15px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="payroll-container">
|
||||
<h1>{{.title}}</h1>
|
||||
|
||||
{{range $i, $data := .datas}}
|
||||
<div class="section">
|
||||
<h2>{{.Name}}</h2>
|
||||
|
||||
{{range $j, $v := .Line}}
|
||||
<div class="info-row">
|
||||
<span class="info-label">{{ $v.Label }}</span>
|
||||
<span class="info-value">{{ $v.Value }}</span>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
|
||||
<div class="info-row total-row">
|
||||
<span class="info-label">实发工资</span>
|
||||
<span class="info-value">{{ .salary }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
3
go.mod
3
go.mod
|
@ -8,6 +8,7 @@ require (
|
|||
git.u8t.cn/open/gosdk v0.0.0-20250309163531-2f47649d3dbd
|
||||
github.com/ArtisanCloud/PowerWeChat/v3 v3.2.27
|
||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874
|
||||
github.com/fogleman/gg v1.3.0
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/go-co-op/gocron v1.37.0
|
||||
github.com/gogap/errors v0.0.0-20210818113853-edfbba0ddea9
|
||||
|
@ -49,6 +50,7 @@ require (
|
|||
github.com/go-sql-driver/mysql v1.7.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/gogap/stack v0.0.0-20150131034635-fef68dddd4f8 // indirect
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
|
@ -92,6 +94,7 @@ require (
|
|||
go.uber.org/zap v1.21.0 // indirect
|
||||
golang.org/x/arch v0.8.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
||||
golang.org/x/image v0.14.0 // indirect
|
||||
golang.org/x/net v0.27.0 // indirect
|
||||
golang.org/x/sys v0.31.0 // indirect
|
||||
golang.org/x/text v0.23.0 // indirect
|
||||
|
|
|
@ -92,3 +92,9 @@ func (s *Salary) SyncStaffSalary(ctx *gin.Context) {
|
|||
go new(worker.Staff).SyncStaffSalary(corp.Id, "")
|
||||
ctx.JSON(http.StatusOK, session.NewRspOk())
|
||||
}
|
||||
|
||||
func (s *Salary) Bill(ctx *gin.Context) {
|
||||
id := cast.ToInt64(ctx.Query("id"))
|
||||
|
||||
service.NewStaffSalary().Bill(id, ctx)
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ func initRoutge(engine *gin.Engine) {
|
|||
apiGroup.POST("/salary/pay", controller.NewSalary().Pay)
|
||||
apiGroup.PUT("/staff/salary", controller.NewSalary().Update)
|
||||
apiGroup.DELETE("/staff/salary", controller.NewSalary().Delete)
|
||||
noTokenGroup.GET("/staff/salary/bill", controller.NewSalary().Bill)
|
||||
|
||||
apiGroup.GET("/staff/suggest", controller.NewStaff().Suggest)
|
||||
apiGroup.POST("/staff/pay", controller.NewStaff().Pay)
|
||||
|
|
|
@ -426,3 +426,70 @@ func (s *StaffSalary) toExcel(filePath string, header []string, datas [][]string
|
|||
ctx.Writer.Header().Add("Content-Type", "application/msexcel")
|
||||
ctx.File(filePath)
|
||||
}
|
||||
|
||||
func (s *StaffSalary) Bill(id int64, ctx *gin.Context) {
|
||||
|
||||
salary, err := dao.NewStaffSalaryDao().Get(id)
|
||||
session.CheckDBError(err)
|
||||
session.CheckNilError(salary, "工资单不存在")
|
||||
corp, err := dao.NewCorpDao().Get(salary.CorpId)
|
||||
session.CheckDBError(err)
|
||||
session.CheckNilError(corp, "企业不存在")
|
||||
user, err := dao.NewStaffUserDao().Get(salary.UserId)
|
||||
session.CheckDBError(err)
|
||||
session.CheckNilError(user, "用户不存在")
|
||||
|
||||
datas := make([]*model.SalaryBillSection, 0)
|
||||
|
||||
baseDetail := make([]*model.SalaryBillLine, 0)
|
||||
baseDetail = append(baseDetail, &model.SalaryBillLine{Label: "员工姓名", Value: fmt.Sprintf("%s", user.Realname)})
|
||||
baseDetail = append(baseDetail, &model.SalaryBillLine{Label: "基本工资", Value: fmt.Sprintf("%s", user.GetSalary().Base)})
|
||||
baseDetail = append(baseDetail, &model.SalaryBillLine{Label: "出勤工资", Value: fmt.Sprintf("%s", user.GetSalary().Target)})
|
||||
datas = append(datas, &model.SalaryBillSection{
|
||||
Name: "基本信息",
|
||||
Line: baseDetail,
|
||||
})
|
||||
|
||||
salaryDetail := make([]*model.SalaryBillLine, 0)
|
||||
|
||||
salaryDetail = append(salaryDetail, &model.SalaryBillLine{Label: "出勤收入", Value: fmt.Sprintf("%.2f 元", salary.AttendSalary)})
|
||||
salaryDetail = append(salaryDetail, &model.SalaryBillLine{Label: "绩效收入", Value: fmt.Sprintf("%.2f 元", salary.TargetSalary)})
|
||||
|
||||
if salary.AwardSalary != 0 {
|
||||
salaryDetail = append(salaryDetail, &model.SalaryBillLine{Label: "奖金收入", Value: fmt.Sprintf("%.2f 元", salary.AwardSalary)})
|
||||
}
|
||||
if salary.OtherSalary != 0 {
|
||||
salaryDetail = append(salaryDetail, &model.SalaryBillLine{Label: "其他收入", Value: fmt.Sprintf("%.2f 元", salary.OtherSalary)})
|
||||
}
|
||||
if salary.SocialDeduct != 0 {
|
||||
salaryDetail = append(salaryDetail, &model.SalaryBillLine{Label: "社保扣除", Value: fmt.Sprintf("%.2f 元", salary.SocialDeduct)})
|
||||
}
|
||||
if salary.HouseDeduct != 0 {
|
||||
salaryDetail = append(salaryDetail, &model.SalaryBillLine{Label: "公积金扣除", Value: fmt.Sprintf("%.2f 元", salary.HouseDeduct)})
|
||||
}
|
||||
|
||||
salaryDetail = append(salaryDetail, &model.SalaryBillLine{Label: "个税扣除", Value: fmt.Sprintf("%.2f 元", salary.PersonalDeduct)})
|
||||
if salary.OtherSalary != 0 {
|
||||
salaryDetail = append(salaryDetail, &model.SalaryBillLine{Label: "其他扣除", Value: fmt.Sprintf("%.2f 元", salary.OtherSalary)})
|
||||
}
|
||||
datas = append(datas, &model.SalaryBillSection{
|
||||
Name: "工资明细",
|
||||
Line: salaryDetail,
|
||||
})
|
||||
|
||||
attendDetail := make([]*model.SalaryBillLine, 0)
|
||||
attendDetail = append(attendDetail, &model.SalaryBillLine{Label: "应出勤", Value: fmt.Sprintf("%d 天", salary.ShouldDay)})
|
||||
attendDetail = append(attendDetail, &model.SalaryBillLine{Label: "休假天数", Value: fmt.Sprintf("%.2f 天", salary.HolidayDay)})
|
||||
attendDetail = append(attendDetail, &model.SalaryBillLine{Label: "缺勤天数", Value: fmt.Sprintf("%.2f 天", float64(salary.ShouldDay)-salary.AttendDay-salary.HolidayDay)})
|
||||
attendDetail = append(attendDetail, &model.SalaryBillLine{Label: "实际出勤", Value: fmt.Sprintf("%.2f 天", salary.AttendDay)})
|
||||
datas = append(datas, &model.SalaryBillSection{
|
||||
Name: "出勤信息",
|
||||
Line: attendDetail,
|
||||
})
|
||||
|
||||
ctx.HTML(http.StatusOK, "salary_bill.html", gin.H{
|
||||
"title": "工资单",
|
||||
"salary": fmt.Sprintf("%.2f 元", salary.GetRealSalary()),
|
||||
"datas": datas,
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue