From 76a84d89d63041232c646ca28c59239dd00f7fc5 Mon Sep 17 00:00:00 2001
From: liujiandao <274878379@qq.com>
Date: 星期二, 30 四月 2024 09:58:46 +0800
Subject: [PATCH] 薪资计算
---
task/salary_statistics.go | 227 ++++++++++++++++
controllers/response/report_forms_response.go | 8
models/mini_dict.go | 20 +
controllers/report_forms_controller.go | 32 ++
controllers/request/worker_request.go | 1
controllers/salary_plan_controller.go | 70 ++++
go.mod | 3
utils/salary_calculate.go | 63 ++++
models/raw_silk_price_standard.go | 18 +
constvar/const.go | 18 +
models/salary_plan.go | 8
controllers/attendance_controller.go | 1
controllers/request/report_forms_request.go | 6
models/salary_report_form.go | 163 +++++++++++
go.sum | 2
models/work_type_manage.go | 11
models/salary_details.go | 158 +++++++++++
models/yield_register_item.go | 21 +
models/attendance_manage.go | 1
19 files changed, 813 insertions(+), 18 deletions(-)
diff --git a/constvar/const.go b/constvar/const.go
index 018497d..b89e679 100644
--- a/constvar/const.go
+++ b/constvar/const.go
@@ -107,3 +107,21 @@
FileTemplateCategory_JialianOutput = 15 //鍢夎仈鍑哄簱
FileTemplateCategory_JialianAttendance = 16 //鍢夎仈-鍛樺伐鑰冨嫟
)
+
+const (
+ DailySilkProduction = "鏃ヤ骇涓濋噺"
+ WasteSilkQuantity = "閲庣氦鏁伴噺"
+ RawSilkUnitPrice = "鐢熶笣鍗曚环"
+ WasteSilkUnitPrice = "閲庣氦鍗曚环"
+ BucketCount = "妗舵暟(鏃�)"
+ AttendanceDays = "鍑哄嫟澶╂暟"
+ GroupAverageMonthlyWage = "鍚岀粍鎸¤溅宸ユ湀骞冲潎宸ヨ祫"
+ GroupCarHeadWage = "鍚岀粍杞﹀ご宸ュ伐璧�"
+ WeekdayOvertimeHours = "宸ヤ綔鏃ュ姞鐝椂闀�"
+ FullAttendanceAward = "婊″嫟濂�"
+ WeekendOvertimeHours = "浼戞伅鏃ュ姞鐝椂闀�"
+ LeaveDays = "璇峰亣澶╂暟"
+ ApprenticeDays = "甯﹀緬澶╂暟"
+ TotalAttendanceDays = "鍑哄嫟澶╂暟"
+ Seniority = "宸ラ緞"
+)
diff --git a/controllers/attendance_controller.go b/controllers/attendance_controller.go
index 7d0d3f1..984b09a 100644
--- a/controllers/attendance_controller.go
+++ b/controllers/attendance_controller.go
@@ -114,6 +114,7 @@
for _, worker := range workers {
if attendance.WorkerId == worker.ID {
attendance.WorkTypeId = worker.WorkTypeId
+ attendance.PhoneNum = worker.PhoneNum
break
}
}
diff --git a/controllers/report_forms_controller.go b/controllers/report_forms_controller.go
new file mode 100644
index 0000000..b00be87
--- /dev/null
+++ b/controllers/report_forms_controller.go
@@ -0,0 +1,32 @@
+package controllers
+
+import (
+ "github.com/gin-gonic/gin"
+)
+
+type ReportFormsController struct {
+}
+
+// SalaryReportForms
+//
+// @Tags 鎶ヨ〃绠$悊
+// @Summary 钖祫鎶ヨ〃
+// @Produce application/json
+// @Param object body request.SalaryReportForms true "鍙傛暟"
+// @Param Authorization header string true "token"
+// @Success 200 {object} util.ResponseList{data=[]models.WorkTypeManage} "鎴愬姛"
+// @Router /api-jl/v1/forms/salaryReportForms [post]
+func (slf ReportFormsController) SalaryReportForms(c *gin.Context) {
+ //var params request.SalaryReportForms
+ //err := c.BindJSON(¶ms)
+ //if err != nil {
+ // util.ResponseFormat(c, code.RequestParamError, "鍙傛暟瑙f瀽澶辫触锛屾暟鎹被鍨嬮敊璇�")
+ // return
+ //}
+ //workers, err := models.NewWorkerSearch().SetPage(params.Page, params.PageSize).FindNotTotal()
+ //if err != nil {
+ // util.ResponseFormat(c, code.RequestParamError, err)
+ // return
+ //}
+
+}
diff --git a/controllers/request/report_forms_request.go b/controllers/request/report_forms_request.go
new file mode 100644
index 0000000..6ce2f3d
--- /dev/null
+++ b/controllers/request/report_forms_request.go
@@ -0,0 +1,6 @@
+package request
+
+type SalaryReportForms struct {
+ PageInfo
+ Month string `json:"month"`
+}
diff --git a/controllers/request/worker_request.go b/controllers/request/worker_request.go
index 1e15736..3ee1f39 100644
--- a/controllers/request/worker_request.go
+++ b/controllers/request/worker_request.go
@@ -23,6 +23,7 @@
}
type SalaryTypeValue struct {
+ Id uint `json:"id"`
Name string `json:"name"` //鍚嶇О
IsDefault bool `json:"isDefault"` //鏄惁鍙紪杈�
}
diff --git a/controllers/response/report_forms_response.go b/controllers/response/report_forms_response.go
new file mode 100644
index 0000000..598df6e
--- /dev/null
+++ b/controllers/response/report_forms_response.go
@@ -0,0 +1,8 @@
+package response
+
+type SalaryReportForms struct {
+ WorkerName string `json:"workerName"`
+ WorkerId string `json:"workerId"`
+ Phone string `json:"phone"`
+ WorkType string `json:"workType"`
+}
diff --git a/controllers/salary_plan_controller.go b/controllers/salary_plan_controller.go
index fb8d9aa..02109c9 100644
--- a/controllers/salary_plan_controller.go
+++ b/controllers/salary_plan_controller.go
@@ -127,23 +127,75 @@
util.ResponseFormat(c, code.RequestParamError, "绫诲瀷涓嶈兘涓虹┖")
return
}
- types := make([]*models.MiniDict, 0)
- for _, value := range params.Values {
+ miniDicts, err := models.NewMiniDictSearch().SetType(params.Type).FindNotTotal()
+ if err != nil {
+ util.ResponseFormat(c, code.RequestParamError, err)
+ return
+ }
+ dicts := params.Values
+ add := make([]*models.MiniDict, 0)
+ del := make([]uint, 0)
+ update := make([]*models.MiniDict, 0)
+ for _, mini := range miniDicts {
+ flag := true
+ for i, value := range dicts {
+ var dict models.MiniDict
+ dict.Name = value.Name
+ dict.IsDefault = value.IsDefault
+ dict.Type = params.Type
+ if value.Id == 0 {
+ add = append(add, &dict)
+ flag = false
+ if i < len(dicts)-1 {
+ dicts = append(dicts[:i], dicts[i+1:]...)
+ } else {
+ dicts = dicts[:i]
+ }
+ break
+ } else if value.Id == mini.ID {
+ update = append(update, &dict)
+ flag = false
+ if i < len(dicts)-1 {
+ dicts = append(dicts[:i], dicts[i+1:]...)
+ } else {
+ dicts = dicts[:i]
+ }
+ break
+ }
+ }
+ if flag {
+ del = append(del, mini.ID)
+ }
+ }
+ //鏂板鐨�
+ for _, value := range dicts {
var dict models.MiniDict
dict.Name = value.Name
dict.IsDefault = value.IsDefault
dict.Type = params.Type
- types = append(types, &dict)
+ add = append(add, &dict)
}
+
err = models.WithTransaction(func(db *gorm.DB) error {
- err = models.NewMiniDictSearch().SetOrm(db).SetType(params.Type).Delete()
- if err != nil {
- return err
+ if len(del) > 0 {
+ err = models.NewMiniDictSearch().SetOrm(db).SetIds(del).Delete()
+ if err != nil {
+ return err
+ }
}
- err = models.NewMiniDictSearch().SetOrm(db).CreateBatch(types)
- if err != nil {
- return err
+ if len(update) > 0 {
+ err = models.NewMiniDictSearch().SetOrm(db).SaveBatch(update)
+ if err != nil {
+ return err
+ }
}
+ if len(add) > 0 {
+ err = models.NewMiniDictSearch().SetOrm(db).CreateBatch(add)
+ if err != nil {
+ return err
+ }
+ }
+
return nil
})
if err != nil {
diff --git a/go.mod b/go.mod
index 9990c00..0b283cf 100644
--- a/go.mod
+++ b/go.mod
@@ -4,11 +4,13 @@
require (
basic.com/aps/nsqclient.git v0.0.0-20230517072415-37491f4a5d25
+ github.com/Knetic/govaluate v3.0.0+incompatible
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/gin-gonic/gin v1.9.1
github.com/golang-jwt/jwt/v4 v4.5.0
github.com/nsqio/go-nsq v1.1.0
github.com/shopspring/decimal v1.3.1
+ github.com/spf13/cast v1.6.0
github.com/spf13/viper v1.18.2
github.com/swaggo/files v1.0.1
github.com/swaggo/gin-swagger v1.6.0
@@ -64,7 +66,6 @@
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
- github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
diff --git a/go.sum b/go.sum
index 61b0da4..f0f9548 100644
--- a/go.sum
+++ b/go.sum
@@ -1,5 +1,7 @@
basic.com/aps/nsqclient.git v0.0.0-20230517072415-37491f4a5d25 h1:sZyNfIISgP1eoY94LG48Kav6HYVLem6EzaEbCeXlcXQ=
basic.com/aps/nsqclient.git v0.0.0-20230517072415-37491f4a5d25/go.mod h1:1RnwEtePLR7ATQorQTxdgvs1o7uuUy1Vw8W7GYtVnoY=
+github.com/Knetic/govaluate v3.0.0+incompatible h1:7o6+MAPhYTCF0+fdvoz1xDedhRb4f6s9Tn1Tt7/WTEg=
+github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
diff --git a/models/attendance_manage.go b/models/attendance_manage.go
index 26996cc..412bf42 100644
--- a/models/attendance_manage.go
+++ b/models/attendance_manage.go
@@ -26,6 +26,7 @@
WorkType WorkTypeManage `json:"workType" gorm:"foreignKey:WorkTypeId"`
Status constvar.AttendanceStatus `json:"status" gorm:"type:int(11);comment:鐘舵��"`
OverTimeDuration decimal.Decimal `json:"overTimeDuration" gorm:"type:decimal(20,2);comment:鍔犵彮鏃堕暱"`
+ PhoneNum string `gorm:"type:varchar(191);comment:鎵嬫満鍙�" json:"phoneNum"`
}
AttendanceManageSearch struct {
AttendanceManage
diff --git a/models/mini_dict.go b/models/mini_dict.go
index 729307e..8941a78 100644
--- a/models/mini_dict.go
+++ b/models/mini_dict.go
@@ -20,6 +20,7 @@
MiniDictSearch struct {
MiniDict
Order string
+ Ids []uint
PageNum int
PageSize int
Orm *gorm.DB
@@ -54,6 +55,11 @@
return slf
}
+func (slf *MiniDictSearch) SetIds(ids []uint) *MiniDictSearch {
+ slf.Ids = ids
+ return slf
+}
+
func (slf *MiniDictSearch) SetType(tp constvar.MiniDictType) *MiniDictSearch {
slf.Type = tp
return slf
@@ -74,6 +80,10 @@
if slf.ID > 0 {
db = db.Where("id = ?", slf.ID)
+ }
+
+ if len(slf.Ids) > 0 {
+ db = db.Where("id in (?)", slf.Ids)
}
if slf.Type > 0 {
@@ -128,6 +138,16 @@
return nil
}
+func (slf *MiniDictSearch) SaveBatch(record []*MiniDict) error {
+ var db = slf.build()
+
+ if err := db.Omit("CreatedAt").Save(record).Error; err != nil {
+ return fmt.Errorf("save err: %v, record: %+v", err, record)
+ }
+
+ return nil
+}
+
func (slf *MiniDictSearch) UpdateByMap(upMap map[string]interface{}) error {
var (
db = slf.build()
diff --git a/models/raw_silk_price_standard.go b/models/raw_silk_price_standard.go
index 05348ab..fea5114 100644
--- a/models/raw_silk_price_standard.go
+++ b/models/raw_silk_price_standard.go
@@ -20,10 +20,11 @@
}
RawSilkPriceStandardSearch struct {
RawSilkPriceStandard
- Order string
- PageNum int
- PageSize int
- Orm *gorm.DB
+ Order string
+ PageNum int
+ PageSize int
+ MarketNames []string
+ Orm *gorm.DB
}
)
@@ -55,6 +56,11 @@
return slf
}
+func (slf *RawSilkPriceStandardSearch) SetMarketNames(names []string) *RawSilkPriceStandardSearch {
+ slf.MarketNames = names
+ return slf
+}
+
func (slf *RawSilkPriceStandardSearch) build() *gorm.DB {
db := slf.Orm.Table(slf.TableName())
@@ -62,6 +68,10 @@
db = db.Where("id = ?", slf.ID)
}
+ if len(slf.MarketNames) > 0 {
+ db = db.Where("market_name in (?)", slf.MarketNames)
+ }
+
return db
}
diff --git a/models/salary_details.go b/models/salary_details.go
new file mode 100644
index 0000000..eec1e11
--- /dev/null
+++ b/models/salary_details.go
@@ -0,0 +1,158 @@
+package models
+
+import (
+ "fmt"
+ "github.com/shopspring/decimal"
+ "gorm.io/gorm"
+ "silkserver/pkg/mysqlx"
+)
+
+type (
+ //SalaryDetails 钖祫鏄庣粏琛�
+ SalaryDetails struct {
+ gorm.Model
+ SalaryDetailsId uint `json:"SalaryDetailsId" gorm:"type:int(11);comment:钖祫鎶ヨ〃id"`
+ SalaryTypeId uint `json:"salaryTypeId" gorm:"type:int(11);comment:钖祫绫诲瀷id"`
+ SalaryType MiniDict `json:"salaryType" gorm:"foreignKey:SalaryTypeId;references:ID"`
+ Amount decimal.Decimal `json:"amount" gorm:"type:decimal(20,3);comment:宸ヨ祫鍊�"`
+ }
+ SalaryDetailsSearch struct {
+ SalaryDetails
+ PageNum int
+ PageSize int
+ Preload bool
+ Orm *gorm.DB
+ }
+)
+
+func (slf SalaryDetails) TableName() string {
+ return "salary_details"
+}
+
+func NewSalaryDetailsSearch() *SalaryDetailsSearch {
+ return &SalaryDetailsSearch{Orm: mysqlx.GetDB()}
+}
+
+func (slf *SalaryDetailsSearch) SetOrm(tx *gorm.DB) *SalaryDetailsSearch {
+ slf.Orm = tx
+ return slf
+}
+
+func (slf *SalaryDetailsSearch) SetPage(page, size int) *SalaryDetailsSearch {
+ slf.PageNum, slf.PageSize = page, size
+ return slf
+}
+
+func (slf *SalaryDetailsSearch) SetPreload(preload bool) *SalaryDetailsSearch {
+ slf.Preload = preload
+ return slf
+}
+
+func (slf *SalaryDetailsSearch) build() *gorm.DB {
+ var db = slf.Orm.Table(slf.TableName())
+
+ if slf.Preload {
+ db = db.Model(SalaryDetails{}).Preload("SalaryType")
+ }
+
+ return db
+}
+
+// Create 鍗曟潯鎻掑叆
+func (slf *SalaryDetailsSearch) Create(record *SalaryDetails) error {
+ var db = slf.build()
+
+ if err := db.Create(record).Error; err != nil {
+ return fmt.Errorf("create err: %v, record: %+v", err, record)
+ }
+
+ return nil
+}
+
+// CreateBatch 鎵归噺鎻掑叆
+func (slf *SalaryDetailsSearch) CreateBatch(record []*SalaryDetails) error {
+ var db = slf.build()
+
+ if err := db.Create(record).Error; err != nil {
+ return fmt.Errorf("create err: %v, record: %+v", err, record)
+ }
+
+ return nil
+}
+
+func (slf *SalaryDetailsSearch) Save(record *SalaryDetails) error {
+ var db = slf.build()
+
+ if err := db.Omit("CreatedAt").Save(record).Error; err != nil {
+ return fmt.Errorf("save err: %v, record: %+v", err, record)
+ }
+
+ return nil
+}
+
+func (slf *SalaryDetailsSearch) UpdateByMap(upMap map[string]interface{}) error {
+ var (
+ db = slf.build()
+ )
+
+ if err := db.Updates(upMap).Error; err != nil {
+ return fmt.Errorf("update by map err: %v, upMap: %+v", err, upMap)
+ }
+
+ return nil
+}
+
+func (slf *SalaryDetailsSearch) Delete() error {
+ var db = slf.build()
+
+ if err := db.Unscoped().Delete(&SalaryDetails{}).Error; err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (slf *SalaryDetailsSearch) Find() ([]*SalaryDetails, int64, error) {
+ var (
+ records = make([]*SalaryDetails, 0)
+ total int64
+ db = slf.build()
+ )
+
+ if err := db.Count(&total).Error; err != nil {
+ return records, total, fmt.Errorf("find count err: %v", err)
+ }
+ if slf.PageNum*slf.PageSize > 0 {
+ db = db.Offset((slf.PageNum - 1) * slf.PageSize).Limit(slf.PageSize)
+ }
+ if err := db.Find(&records).Error; err != nil {
+ return records, total, fmt.Errorf("find records err: %v", err)
+ }
+
+ return records, total, nil
+}
+
+func (slf *SalaryDetailsSearch) FindNotTotal() ([]*SalaryDetails, error) {
+ var (
+ records = make([]*SalaryDetails, 0)
+ db = slf.build()
+ )
+
+ if err := db.Find(&records).Error; err != nil {
+ return records, fmt.Errorf("find records err: %v", err)
+ }
+
+ return records, nil
+}
+
+func (slf *SalaryDetailsSearch) Count() (int64, error) {
+ var (
+ total int64
+ db = slf.build()
+ )
+
+ if err := db.Count(&total).Error; err != nil {
+ return total, fmt.Errorf("find count err: %v", err)
+ }
+ return total, nil
+}
diff --git a/models/salary_plan.go b/models/salary_plan.go
index 1c326ec..55e84d6 100644
--- a/models/salary_plan.go
+++ b/models/salary_plan.go
@@ -10,8 +10,10 @@
//SalaryPlan 钖祫鏂规
SalaryPlan struct {
gorm.Model
- Name string `json:"name" gorm:"type:varchar(255);comment:钖祫鏂规鍚嶇О"`
- SalaryType string `json:"salaryType" gorm:"type:varchar(255);comment:钖祫绫诲瀷"`
+ Name string `json:"name" gorm:"type:varchar(255);comment:钖祫鏂规鍚嶇О"`
+ SalaryTypeId uint `json:"salaryTypeId" gorm:"type:int(11);comment:钖祫绫诲瀷id"`
+ SalaryType MiniDict `json:"salaryType" gorm:"foreignKey:SalaryTypeId;references:ID"`
+ //SalaryType string `json:"salaryType" gorm:"type:varchar(255);comment:钖祫绫诲瀷"`
SalaryFormula string `json:"salaryFormula" gorm:"type:varchar(255);comment:钖祫鍏紡"`
Cycle string `json:"cycle" gorm:"type:varchar(255);comment:鍛ㄦ湡"`
CreateTime string `json:"createTime" gorm:"type:varchar(255);comment:娣诲姞鏃堕棿"`
@@ -63,7 +65,7 @@
}
if slf.Preload {
- db = db.Model(&SalaryPlan{}).Preload("WorkTypes")
+ db = db.Model(&SalaryPlan{}).Preload("WorkTypes").Preload("SalaryType")
}
return db
diff --git a/models/salary_report_form.go b/models/salary_report_form.go
new file mode 100644
index 0000000..67aa59f
--- /dev/null
+++ b/models/salary_report_form.go
@@ -0,0 +1,163 @@
+package models
+
+import (
+ "fmt"
+ "github.com/shopspring/decimal"
+ "gorm.io/gorm"
+ "silkserver/pkg/mysqlx"
+)
+
+type (
+ // SalaryReportForm 钖祫鎶ヨ〃
+ SalaryReportForm struct {
+ gorm.Model
+ WorkerId string `json:"workerId" gorm:"type:varchar(255);comment:浜哄憳id"`
+ WorkerName string `json:"workerName" gorm:"type:varchar(255);comment:浜哄憳濮撳悕"`
+ Phone string `json:"phone" gorm:"type:varchar(255);comment:鐢佃瘽"`
+ WorkTypeId uint `json:"workTypeId" gorm:"type:int(11);comment:宸ョ绫诲瀷id"`
+ WorkType WorkTypeManage `json:"workType" gorm:"foreignKey:WorkTypeId;references:ID"`
+ Month string `json:"month" gorm:"type:varchar(255);comment:鏈堜唤"`
+ IssueSalary decimal.Decimal `json:"issueSalary" gorm:"type:decimal(20,3);comment:搴斿彂宸ヨ祫"`
+ Remark string `json:"remark" gorm:"type:varchar(255);comment:澶囨敞"`
+ Details []SalaryDetails `json:"details" gorm:"foreignKey:SalaryReportFormId;references:Id"`
+ }
+ SalaryReportFormSearch struct {
+ SalaryReportForm
+ PageNum int
+ PageSize int
+ Preload bool
+ Orm *gorm.DB
+ }
+)
+
+func (slf SalaryReportForm) TableName() string {
+ return "salary_report_form"
+}
+
+func NewSalaryReportFormSearch() *SalaryReportFormSearch {
+ return &SalaryReportFormSearch{Orm: mysqlx.GetDB()}
+}
+
+func (slf *SalaryReportFormSearch) SetOrm(tx *gorm.DB) *SalaryReportFormSearch {
+ slf.Orm = tx
+ return slf
+}
+
+func (slf *SalaryReportFormSearch) SetPage(page, size int) *SalaryReportFormSearch {
+ slf.PageNum, slf.PageSize = page, size
+ return slf
+}
+
+func (slf *SalaryReportFormSearch) SetPreload(preload bool) *SalaryReportFormSearch {
+ slf.Preload = preload
+ return slf
+}
+
+func (slf *SalaryReportFormSearch) build() *gorm.DB {
+ var db = slf.Orm.Table(slf.TableName())
+
+ if slf.Preload {
+ db = db.Model(SalaryReportForm{}).Preload("Details").Preload("WorkType")
+ }
+
+ return db
+}
+
+// Create 鍗曟潯鎻掑叆
+func (slf *SalaryReportFormSearch) Create(record *SalaryReportForm) error {
+ var db = slf.build()
+
+ if err := db.Create(record).Error; err != nil {
+ return fmt.Errorf("create err: %v, record: %+v", err, record)
+ }
+
+ return nil
+}
+
+// CreateBatch 鎵归噺鎻掑叆
+func (slf *SalaryReportFormSearch) CreateBatch(record []*SalaryReportForm) error {
+ var db = slf.build()
+
+ if err := db.Create(record).Error; err != nil {
+ return fmt.Errorf("create err: %v, record: %+v", err, record)
+ }
+
+ return nil
+}
+
+func (slf *SalaryReportFormSearch) Save(record *SalaryReportForm) error {
+ var db = slf.build()
+
+ if err := db.Omit("CreatedAt").Save(record).Error; err != nil {
+ return fmt.Errorf("save err: %v, record: %+v", err, record)
+ }
+
+ return nil
+}
+
+func (slf *SalaryReportFormSearch) UpdateByMap(upMap map[string]interface{}) error {
+ var (
+ db = slf.build()
+ )
+
+ if err := db.Updates(upMap).Error; err != nil {
+ return fmt.Errorf("update by map err: %v, upMap: %+v", err, upMap)
+ }
+
+ return nil
+}
+
+func (slf *SalaryReportFormSearch) Delete() error {
+ var db = slf.build()
+
+ if err := db.Unscoped().Delete(&SalaryReportForm{}).Error; err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (slf *SalaryReportFormSearch) Find() ([]*SalaryReportForm, int64, error) {
+ var (
+ records = make([]*SalaryReportForm, 0)
+ total int64
+ db = slf.build()
+ )
+
+ if err := db.Count(&total).Error; err != nil {
+ return records, total, fmt.Errorf("find count err: %v", err)
+ }
+ if slf.PageNum*slf.PageSize > 0 {
+ db = db.Offset((slf.PageNum - 1) * slf.PageSize).Limit(slf.PageSize)
+ }
+ if err := db.Find(&records).Error; err != nil {
+ return records, total, fmt.Errorf("find records err: %v", err)
+ }
+
+ return records, total, nil
+}
+
+func (slf *SalaryReportFormSearch) FindNotTotal() ([]*SalaryReportForm, error) {
+ var (
+ records = make([]*SalaryReportForm, 0)
+ db = slf.build()
+ )
+
+ if err := db.Find(&records).Error; err != nil {
+ return records, fmt.Errorf("find records err: %v", err)
+ }
+
+ return records, nil
+}
+
+func (slf *SalaryReportFormSearch) Count() (int64, error) {
+ var (
+ total int64
+ db = slf.build()
+ )
+
+ if err := db.Count(&total).Error; err != nil {
+ return total, fmt.Errorf("find count err: %v", err)
+ }
+ return total, nil
+}
diff --git a/models/work_type_manage.go b/models/work_type_manage.go
index e19ce79..d937a25 100644
--- a/models/work_type_manage.go
+++ b/models/work_type_manage.go
@@ -8,6 +8,7 @@
)
type (
+ //WorkTypeManage 宸ョ绠$悊
WorkTypeManage struct {
gorm.Model
WorkName string `json:"workName" gorm:"type:varchar(255);comment:宸ョ鍚嶇О"`
@@ -22,6 +23,7 @@
PageNum int
PageSize int
Preload bool
+ Ids []uint
Orm *gorm.DB
}
)
@@ -54,6 +56,11 @@
return slf
}
+func (slf *WorkTypeManageSearch) SetIds(ids []uint) *WorkTypeManageSearch {
+ slf.Ids = ids
+ return slf
+}
+
func (slf *WorkTypeManageSearch) build() *gorm.DB {
var db = slf.Orm.Table(slf.TableName())
@@ -61,6 +68,10 @@
db = db.Where("id = ?", slf.ID)
}
+ if len(slf.Ids) > 0 {
+ db = db.Where("id in (?)", slf.Ids)
+ }
+
if slf.Preload {
db = db.Model(WorkTypeManage{}).Preload("SalaryPlans")
}
diff --git a/models/yield_register_item.go b/models/yield_register_item.go
index e9a643a..92720c5 100644
--- a/models/yield_register_item.go
+++ b/models/yield_register_item.go
@@ -20,7 +20,9 @@
}
YieldRegisterItemSearch struct {
YieldRegisterItem
- Orm *gorm.DB
+ YieldRegisterIds []uint
+ CarNumbers []int
+ Orm *gorm.DB
}
)
@@ -42,6 +44,15 @@
return slf
}
+func (slf *YieldRegisterItemSearch) SetYieldRegisterIds(ids []uint) *YieldRegisterItemSearch {
+ slf.YieldRegisterIds = ids
+ return slf
+}
+func (slf *YieldRegisterItemSearch) SetCarNumbers(carNumbers []int) *YieldRegisterItemSearch {
+ slf.CarNumbers = carNumbers
+ return slf
+}
+
func (slf *YieldRegisterItemSearch) build() *gorm.DB {
db := slf.Orm.Table(slf.TableName())
@@ -49,6 +60,14 @@
db = db.Where("yield_register_id = ?", slf.YieldRegisterId)
}
+ if len(slf.YieldRegisterIds) > 0 {
+ db = db.Where("yield_register_id in (?)", slf.YieldRegisterIds)
+ }
+
+ if len(slf.CarNumbers) > 0 {
+ db = db.Where("car_number in (?)", slf.CarNumbers)
+ }
+
return db
}
diff --git a/task/salary_statistics.go b/task/salary_statistics.go
new file mode 100644
index 0000000..07e1a1e
--- /dev/null
+++ b/task/salary_statistics.go
@@ -0,0 +1,227 @@
+package task
+
+import (
+ "github.com/shopspring/decimal"
+ "silkserver/constvar"
+ "silkserver/models"
+ "silkserver/pkg/logx"
+ "silkserver/utils"
+ "strings"
+ "time"
+)
+
+func SalaryStatistics() {
+ lastMonthStart, lastMonthEnd := GetLastMonthPeriod()
+ month := lastMonthStart.Format("2006-01")
+
+ //鏌ヨ鑰冨嫟缁熻
+ startStr := lastMonthStart.Format("2006-01-02")
+ endStr := lastMonthEnd.Format("2006-01-02")
+ attendances, err := models.NewAttendanceManageSearch().SetMonth(month).FindNotTotal()
+ if err != nil {
+ logx.Error("SalaryStatistics 鏌ヨ鑰冨嫟缁熻 err: " + err.Error())
+ return
+ }
+
+ var reportForms []*models.SalaryReportForm
+ workTypeIdMap := make(map[uint]uint)
+ dataMap := make(map[string]utils.SalaryCalculateData)
+ for _, attendance := range attendances {
+ var rf models.SalaryReportForm
+ var data utils.SalaryCalculateData
+ if _, ok := dataMap[attendance.WorkerId]; ok {
+ data = dataMap[attendance.WorkerId]
+ }
+ rf.WorkerId = attendance.WorkerId
+ rf.WorkerName = attendance.WorkerName
+ rf.WorkTypeId = attendance.WorkTypeId
+ rf.Month = month
+ rf.Phone = attendance.PhoneNum
+ if attendance.WorkTypeId > 0 {
+ workTypeIdMap[attendance.WorkTypeId] = attendance.WorkTypeId
+ }
+ //宸ヤ綔鏃ュ姞鐝椂闀�
+ data.WeekdayOvertimeHours = data.WeekdayOvertimeHours.Add(attendance.OverTimeDuration)
+ //鍑哄嫟澶╂暟
+ if attendance.Status != constvar.Vacation {
+ data.TotalAttendanceDays = data.TotalAttendanceDays + 1
+ }
+ dataMap[attendance.WorkerId] = data
+ reportForms = append(reportForms, &rf)
+ }
+ workTypeIds := make([]uint, 0)
+ for _, v := range workTypeIdMap {
+ workTypeIds = append(workTypeIds, v)
+ }
+
+ //鏌ヨ宸ョ鐨勮柂璧勬柟妗堝拰鏂板绫诲瀷
+ workTypeManages, err := models.NewWorkTypeManageSearch().SetIds(workTypeIds).SetPreload(true).FindNotTotal()
+ if err != nil {
+ logx.Error("SalaryStatistics 鏌ヨ宸ョ鐨勮柂璧勬柟妗堝拰鏂板绫诲瀷 err: " + err.Error())
+ return
+ }
+ for _, form := range reportForms {
+ details := make([]models.SalaryDetails, 0)
+ issueSalary := decimal.NewFromInt(0)
+ for _, manage := range workTypeManages {
+ if form.WorkTypeId == manage.ID {
+ data := dataMap[form.WorkerId]
+ for _, plan := range manage.SalaryPlans {
+ formula := strings.ReplaceAll(plan.SalaryFormula, ",", "")
+ var detail models.SalaryDetails
+ detail.SalaryTypeId = plan.SalaryTypeId
+ amount := decimal.NewFromInt(0)
+ f := constvar.DailySilkProduction + "*" + constvar.RawSilkUnitPrice
+ if strings.Contains(formula, f) {
+ data, err = GetDailySilkProduction(startStr, endStr, form.WorkerId, data)
+ if err != nil {
+ logx.Error("SalaryStatistics 缁熻钖祫鍑洪敊 err: " + err.Error())
+ } else {
+ amount, err = utils.CalculateSalary(data, formula)
+ if err != nil {
+ logx.Error("SalaryStatistics 璁$畻钖祫鍑洪敊 err: " + err.Error())
+ }
+ }
+ }
+ detail.Amount = amount
+ issueSalary = issueSalary.Add(amount)
+ details = append(details, detail)
+ }
+ }
+ }
+ form.Details = details
+ form.IssueSalary = issueSalary
+ }
+
+ //鎻掑叆鏁版嵁搴�
+ err = models.NewSalaryReportFormSearch().CreateBatch(reportForms)
+ if err != nil {
+ logx.Error("SalaryStatistics 鎻掑叆鏁版嵁搴撳嚭閿� err: " + err.Error())
+ }
+}
+
+func GetDailySilkProduction(start, end, workerId string, data utils.SalaryCalculateData) (utils.SalaryCalculateData, error) {
+ //鏌ヨ鏈哄彴绠$悊
+ var cars []models.WorkerPosition
+ err := models.NewWorkerPositionSearch().Orm.Table("silk_worker_position").Where("worker_id = ? and start_date >= ? and "+
+ "end_date <= ?", workerId, start, end).Find(&cars).Error
+ if err != nil {
+ return data, err
+ }
+ endCarMap := make(map[int]int)
+ groupMap := make(map[int]int)
+ workshopMap := make(map[string]string)
+ for _, car := range cars {
+ endCarMap[car.EndWorkerPosition] = car.EndWorkerPosition
+ groupMap[car.WorkshopGroup] = car.WorkshopGroup
+ workshopMap[car.Workshop] = car.Workshop
+ }
+ groups := make([]int, 0)
+ workshops := make([]string, 0)
+ endCars := make([]int, 0)
+ for _, v := range endCarMap {
+ endCars = append(endCars, v)
+ }
+ for _, v := range workshopMap {
+ workshops = append(workshops, v)
+ }
+ for _, v := range groupMap {
+ groups = append(groups, v)
+ }
+
+ //鏌ヨ浜ч噺鐧昏琛�
+ var yield []models.YieldRegister
+ err = models.NewYieldRegisterSearch().Orm.Table("silk_yield_register").Where("workshop_number in (?) and group_number "+
+ "in (?) and create_time >= ? and create_time <= ?", workshops, groups, start, end).Find(&yield).Error
+ if err != nil {
+ return data, err
+ }
+ yieldRegisterIds := make([]uint, 0)
+ for _, register := range yield {
+ yieldRegisterIds = append(yieldRegisterIds, register.ID)
+ }
+ yieldMap := make(map[string]decimal.Decimal)
+ items, err := models.NewYieldRegisterItemSearch().SetYieldRegisterIds(yieldRegisterIds).SetCarNumbers(endCars).FindNotTotal()
+ if err != nil {
+ return data, err
+ }
+ for _, register := range yield {
+ for _, item := range items {
+ if register.ID == item.YieldRegisterId {
+ yieldMap[register.CreateTime] = item.PeopleYield
+ }
+ }
+ }
+ //鏌ヨ绾ゅ害鐧昏琛�
+ var fineness []models.FinenessRegister
+ markets := make([]string, 0)
+ err = models.NewFinenessRegisterSearch().Orm.Table("silk_fineness_register").Where("workshop in (?) and workshop_group "+
+ "in (?) and finish_date >= ? and finish_date <= ?", workshops, groups, start, end).Find(&fineness).Error
+ if err != nil {
+ return data, err
+ }
+ finenessIds := make([]uint, 0)
+ for _, register := range fineness {
+ finenessIds = append(finenessIds, register.ID)
+ markets = append(markets, register.Market)
+ }
+ var checkItems []models.FinenessCheckItem
+ err = models.NewFinenessCheckItemSearch().Orm.Table("silk_fineness_check_item").Where("fineness_register_id in (?) and "+
+ "position in (?)", finenessIds, endCars).Find(&checkItems).Error
+ if err != nil {
+ return data, err
+ }
+ checkMap := make(map[string]string)
+ marketMap := make(map[string]string)
+ for _, item := range checkItems {
+ for _, register := range fineness {
+ if item.FinenessRegisterID == register.ID {
+ checkMap[register.FinishDate] = item.FinenessGrade
+ marketMap[register.FinishDate] = register.Market
+ break
+ }
+ }
+ }
+ //鏌ヨ涓嶅悓搴勫彛涓嬬殑鐢熶笣瀹氫环
+ find, _, err := models.NewRawSilkPriceStandardSearch().SetMarketNames(markets).Find()
+ if err != nil {
+ return data, err
+ }
+ //璁$畻姣忔棩宸ヨ祫
+ total := decimal.NewFromInt(0)
+ for date, amount := range yieldMap {
+ grade := checkMap[date]
+ market := marketMap[date]
+ for _, standard := range find {
+ if standard.MarketName == market && standard.RawSilkGrade == grade {
+ h := amount.Mul(standard.PayStandard)
+ total = total.Add(h)
+ break
+ }
+ }
+ }
+ data.DailySilkProduction = total
+ data.RawSilkUnitPrice = decimal.NewFromInt(1)
+ return data, nil
+}
+
+// GetLastMonthPeriod 杩斿洖涓婁釜鏈堢殑鏈堝垵鏃堕棿鍜屾湀鏈椂闂�
+func GetLastMonthPeriod() (time.Time, time.Time) {
+ // 鑾峰彇褰撳墠鏃堕棿
+ now := time.Now()
+
+ // 璁$畻涓婁釜鏈堢殑骞翠唤鍜屾湀浠�
+ lastMonth := now.AddDate(0, -1, 0)
+ lastYear, lastMonthNum, _ := lastMonth.Date()
+
+ // 鑾峰彇涓婁釜鏈堢殑绗竴澶╃殑鏃ユ湡锛堝嵆涓婁釜鏈堟湀鍒濓級
+ firstDayOfLastMonth := time.Date(lastYear, lastMonthNum, 1, 0, 0, 0, 0, now.Location())
+
+ // 鑾峰彇鏈湀绗竴澶╃殑鏃ユ湡锛堝嵆鏈湀鏈堝垵锛�
+ firstDayOfThisMonth := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
+
+ // 涓婁釜鏈堟湀鏈椂闂村嵆涓烘湰鏈堟湀鍒濆噺鍘讳竴绉�
+ lastDayOfLastMonth := firstDayOfThisMonth.Add(-time.Second)
+
+ return firstDayOfLastMonth, lastDayOfLastMonth
+}
diff --git a/utils/salary_calculate.go b/utils/salary_calculate.go
new file mode 100644
index 0000000..b5c4618
--- /dev/null
+++ b/utils/salary_calculate.go
@@ -0,0 +1,63 @@
+package utils
+
+import (
+ "github.com/Knetic/govaluate"
+ "github.com/shopspring/decimal"
+ "strconv"
+ "strings"
+)
+
+// 钖祫璁$畻鏁版嵁
+type SalaryCalculateData struct {
+ DailySilkProduction decimal.Decimal `json:"dailySilkProduction"` // 鏃ヤ骇涓濋噺
+ WasteSilkQuantity decimal.Decimal `json:"wasteSilkQuantity"` // 閲庣氦鏁伴噺
+ RawSilkUnitPrice decimal.Decimal `json:"rawSilkUnitPrice"` // 鐢熶笣鍗曚环
+ WasteSilkUnitPrice decimal.Decimal `json:"wasteSilkUnitPrice"` // 閲庣氦鍗曚环
+ BucketCount decimal.Decimal `json:"bucketCount"` //妗舵暟(鏃�)
+ AttendanceDays int `json:"attendanceDays"` // 鍑哄嫟澶╂暟
+ GroupAverageMonthlyWage decimal.Decimal `json:"groupAverageMonthlyWage"` //鍚岀粍鎸¤溅宸ユ湀骞冲潎宸ヨ祫
+ GroupCarHeadWage decimal.Decimal `json:"groupCarHeadWage"` //鍚岀粍杞﹀ご宸ュ伐璧�
+
+ WeekdayOvertimeHours decimal.Decimal `json:"weekdayOvertimeHours"` // 宸ヤ綔鏃ュ姞鐝椂闀�
+ FullAttendanceAward int `json:"FullAttendanceAward"` // 婊″嫟濂�
+ WeekendOvertimeHours decimal.Decimal `json:"weekendOvertimeHours"` // 浼戞伅鏃ュ姞鐝椂闀�
+ LeaveDays decimal.Decimal `json:"LeaveDays"` //璇峰亣澶╂暟
+ ApprenticeDays decimal.Decimal `json:"apprenticeDays"` // 甯﹀緬澶╂暟
+ TotalAttendanceDays int `json:"totalAttendanceDays"` // 鍑哄嫟澶╂暟
+ Seniority decimal.Decimal `json:"seniority"` // 宸ラ緞
+}
+
+// CalculateSalary 璁$畻宸ヨ祫鐨勫嚱鏁�
+func CalculateSalary(date SalaryCalculateData, formula string) (decimal.Decimal, error) {
+ // 鏇挎崲鍏紡涓殑鍙橀噺
+ formula = strings.ReplaceAll(formula, "鏃ヤ骇涓濋噺", date.DailySilkProduction.String())
+ formula = strings.ReplaceAll(formula, "閲庣氦鏁伴噺", date.WasteSilkQuantity.String())
+ formula = strings.ReplaceAll(formula, "鐢熶笣鍗曚环", date.RawSilkUnitPrice.String())
+ formula = strings.ReplaceAll(formula, "閲庣氦鍗曚环", date.WasteSilkUnitPrice.String())
+ formula = strings.ReplaceAll(formula, "妗舵暟(鏃�)", date.BucketCount.String())
+ formula = strings.ReplaceAll(formula, "鍑哄嫟澶╂暟", strconv.Itoa(date.AttendanceDays))
+ formula = strings.ReplaceAll(formula, "鍚岀粍鎸¤溅宸ユ湀骞冲潎宸ヨ祫", date.GroupAverageMonthlyWage.String())
+ formula = strings.ReplaceAll(formula, "鍚岀粍杞﹀ご宸ュ伐璧�", date.GroupCarHeadWage.String())
+
+ formula = strings.ReplaceAll(formula, "宸ヤ綔鏃ュ姞鐝椂闀�", date.WeekdayOvertimeHours.String())
+ formula = strings.ReplaceAll(formula, "婊″嫟濂�", strconv.Itoa(date.FullAttendanceAward))
+ formula = strings.ReplaceAll(formula, "浼戞伅鏃ュ姞鐝椂闀�", date.WeekendOvertimeHours.String())
+ formula = strings.ReplaceAll(formula, "璇峰亣澶╂暟", date.LeaveDays.String())
+ formula = strings.ReplaceAll(formula, "甯﹀緬澶╂暟", date.ApprenticeDays.String())
+ formula = strings.ReplaceAll(formula, "鍑哄嫟澶╂暟", strconv.Itoa(date.TotalAttendanceDays))
+ formula = strings.ReplaceAll(formula, "宸ラ緞", date.Seniority.String())
+
+ // 浣跨敤 govaluate 搴撹绠楄〃杈惧紡
+ wage := decimal.NewFromInt(0)
+ expression, err := govaluate.NewEvaluableExpression(formula)
+ if err != nil {
+ return wage, err
+ }
+ parameters := make(map[string]interface{})
+ result, err := expression.Evaluate(parameters)
+ if err != nil {
+ return wage, err
+ }
+ wage = decimal.NewFromFloat(result.(float64))
+ return wage, nil
+}
--
Gitblit v1.8.0