From fe794b385cc1fe28cb6d0731664a3023199843ac Mon Sep 17 00:00:00 2001
From: zhangqian <zhangqian@123.com>
Date: 星期一, 01 七月 2024 21:21:56 +0800
Subject: [PATCH] 增加月度统计出入库按类型汇总报表查询接口
---
models/month_stats.go | 2
request/report_forms_request.go | 5
controllers/report_forms_controller.go | 68 ++++++
models/warehouse_month_stats.go | 289 ++++++++++++++++++++++++++++
models/operation.go | 9
models/operation_details.go | 18 +
router/router.go | 2
service/warehouse_month_forms.go | 151 +++++++++++++++
8 files changed, 541 insertions(+), 3 deletions(-)
diff --git a/controllers/report_forms_controller.go b/controllers/report_forms_controller.go
index 660ebee..49e8fca 100644
--- a/controllers/report_forms_controller.go
+++ b/controllers/report_forms_controller.go
@@ -437,3 +437,71 @@
task.MonthStats()
util.ResponseFormat(c, code.Success, nil)
}
+
+// WarehouseMonthStats
+// @Tags 鎶ヨ〃
+// @Summary 浠撳簱鏈堝害缁熻搴撳瓨鎶ヨ〃
+// @Produce application/json
+// @Param object body request.GetMonthStats true "鏌ヨ鍙傛暟"
+// @Param Authorization header string true "token"
+// @Success 200 {object} util.ResponseList{data=[]models.MonthStats} "鎴愬姛"
+// @Router /api-wms/v1/forms/warehouseMonthStats [post]
+func (slf ReportFormsController) WarehouseMonthStats(c *gin.Context) {
+ var params request.GetMonthStats
+ if err := c.BindJSON(¶ms); err != nil {
+ util.ResponseFormat(c, code.RequestParamError, "鍙傛暟瑙f瀽澶辫触锛屾暟鎹被鍨嬮敊璇�")
+ return
+ }
+
+ if params.WarehouseID == 0 {
+ util.ResponseFormat(c, code.RequestParamError, "浠撳簱ID鍙傛暟缂哄け")
+ return
+ }
+
+ monthFormsService := service.NewWarehouseMonthFormsService()
+ total, err := monthFormsService.Count(params)
+ if err != nil {
+ logx.Errorf("MonthStats count err:%v", err)
+ util.ResponseFormat(c, code.InternalError, "鏌ヨ鎬绘暟澶辫触")
+ return
+ }
+
+ result, err := monthFormsService.Query(params)
+ if err != nil {
+ logx.Errorf("MonthStats query err:%v", err)
+ util.ResponseFormat(c, code.InternalError, "鏌ヨ澶辫触")
+ return
+ }
+
+ now := time.Now().Local()
+ today := now.Day()
+ nowMonth := now.Format("2006-01")
+
+ day, dateStr, _ := service.NewSystemConfigService().GetInventoryCutOffPoint()
+ if nowMonth == params.Date && today < day || today == day && now.Format("15:04") < dateStr { //鏈湀鏈嚦缁撶畻鏃堕棿鐐�
+ productIds := make([]string, 0, len(result))
+ for _, item := range result {
+ productIds = append(productIds, item.ProductId)
+ }
+ statsRecords, err := service.GetCurrentWarehouseStats(params.Date, params.WarehouseID, productIds)
+ if err != nil {
+ util.ResponseFormat(c, code.InternalError, "鍐呴儴閿欒")
+ return
+ }
+ statsMap := models.WarehouseMonthStatsMap(statsRecords)
+ for k, v := range result {
+ if statsMap[v.ProductId] == nil {
+ continue
+ }
+
+ result[k].OutputAmount = statsMap[v.ProductId].OutputAmount
+ result[k].EndAmount = statsMap[v.ProductId].EndAmount
+ result[k].InputAmount = statsMap[v.ProductId].InputAmount
+ result[k].InputItems = statsMap[v.ProductId].InputItems
+ result[k].OutputItems = statsMap[v.ProductId].OutputItems
+ }
+
+ }
+
+ util.ResponseFormatList(c, code.Success, result, int(total))
+}
diff --git a/models/month_stats.go b/models/month_stats.go
index 64e1111..f86026f 100644
--- a/models/month_stats.go
+++ b/models/month_stats.go
@@ -9,7 +9,7 @@
)
type (
- // MonthStats 绉诲姩鍘嗗彶
+ // MonthStats 鏈堝害缁熻
MonthStats struct {
WmsModel
Id int `json:"id" gorm:"column:id;primary_key;AUTO_INCREMENT"`
diff --git a/models/operation.go b/models/operation.go
index 740659d..826208d 100644
--- a/models/operation.go
+++ b/models/operation.go
@@ -196,6 +196,11 @@
return slf
}
+func (slf *OperationSearch) SetWarehouseId(warehouseId int) *OperationSearch {
+ slf.WarehouseId = warehouseId
+ return slf
+}
+
func (slf *OperationSearch) build() *gorm.DB {
var db = slf.Orm.Model(&Operation{})
@@ -277,6 +282,10 @@
db = db.Where("inventory_dealer_type in (?)", slf.InventoryDealerTypeIds)
}
+ if slf.WarehouseId != 0 {
+ db = db.Where("warehouse_id = ?", slf.WarehouseId)
+ }
+
return db
}
diff --git a/models/operation_details.go b/models/operation_details.go
index 16f65f4..8269f76 100644
--- a/models/operation_details.go
+++ b/models/operation_details.go
@@ -29,6 +29,7 @@
AuxiliaryUnit string `json:"auxiliaryUnit" gorm:"type:varchar(191);comment:杈呭姪鍗曚綅"`
Remark string `gorm:"type:varchar(1024);comment:澶囨敞" json:"remark"`
IsInternalOutput bool `json:"isInternalOutput"` //鏄惁璋冩嫧浜х敓鐨勫嚭搴�
+ DealerType string `json:"dealerType"` //鍑哄叆搴撶被鍨�
Cost decimal.Decimal `json:"cost" ` //鎴愭湰鍗曚环
SalePrice decimal.Decimal `json:"salePrice" ` //閿�鍞崟浠�
@@ -312,3 +313,20 @@
}
return result, nil
}
+
+type GroupByDealerTypeWarehouse struct {
+ DealerType string
+ ProductID string
+ Sum decimal.Decimal
+}
+
+func (slf *OperationDetailsSearch) GroupMultiSumAmount() ([]*GroupByDealerTypeWarehouse, error) {
+ var (
+ db = slf.build()
+ result = make([]*GroupByDealerTypeWarehouse, 0)
+ )
+ if err := db.Select("sum(amount) as sum, dealer_type, product_id").Group("product_id, dealer_type").Scan(&result).Error; err != nil {
+ return nil, fmt.Errorf("select group err: %v", err)
+ }
+ return result, nil
+}
diff --git a/models/warehouse_month_stats.go b/models/warehouse_month_stats.go
new file mode 100644
index 0000000..72f494c
--- /dev/null
+++ b/models/warehouse_month_stats.go
@@ -0,0 +1,289 @@
+package models
+
+import (
+ "fmt"
+ "github.com/shopspring/decimal"
+ "gorm.io/gorm"
+ "wms/pkg/mysqlx"
+)
+
+type (
+ // WarehouseMonthStats 鎸変粨搴撹繘琛屾湀搴︾粺璁�
+ WarehouseMonthStats struct {
+ WmsModel
+ Id int `json:"id" gorm:"column:id;primary_key;AUTO_INCREMENT"`
+ WarehouseId int `json:"warehouseId" gorm:"type:int;not null;default:0"` //浠撳簱ID
+ ProductId string `json:"productId" gorm:"type:varchar(255);not null;comment:浜у搧id"` //浜у搧id
+ ProductName string `json:"productName" gorm:"type:varchar(255);not null;comment:浜у搧鍚嶇О"` //浜у搧鍚嶇О
+ Unit string `json:"unit" gorm:"type:char(10);not null;comment:鍗曚綅"` //鍗曚綅
+ SalePrice decimal.Decimal `gorm:"type:decimal(35,18);comment:閿�鍞崟浠�" json:"salePrice"` //閿�鍞崟浠�
+
+ BeginAmount decimal.Decimal `json:"beginAmount" gorm:"type:decimal(30,10);not null;comment:鏁伴噺"` //鏈熷垵鏁伴噺
+ EndAmount decimal.Decimal `json:"amount" gorm:"type:decimal(30,10);not null;comment:鏁伴噺"` //鏈熸湯缁撲綑鏁伴噺
+
+ InputAmount decimal.Decimal `json:"inputAmount" gorm:"type:decimal(30,10);not null;comment:鏁伴噺"` //鍏ュ簱鏁伴噺
+ InputItems []*WarehouseStatsItems `json:"inputMoreUnitsArr"` //鍏ュ簱鏄庣粏
+
+ OutputAmount decimal.Decimal `json:"outputAmount" gorm:"type:decimal(30,10);not null;comment:鏁伴噺"` //鍑哄簱鏁伴噺
+ OutputItems []*WarehouseStatsItems `json:"outputMoreUnitsArr"` //鍑哄簱鏄庣粏
+
+ Date string `json:"date" gorm:"index;type:varchar(255); not null;default ''"` //鏃ユ湡 2024-04
+ }
+
+ WarehouseStatsItems struct {
+ WarehouseMonthStatsId int `json:"warehouseMonthStatsId"`
+ Name string `json:"name" gorm:"type:varchar(255);not null;default:''"` //鍏ュ簱鏉ユ簮锛屽嚭搴撳幓澶�
+ Amount decimal.Decimal `json:"amount" gorm:"type:decimal(30,10);not null;"` //鏁伴噺
+ }
+
+ WarehouseMonthStatsSearch struct {
+ WarehouseMonthStats
+ Order string
+ PageNum int
+ PageSize int
+ Keyword string
+ Orm *gorm.DB
+ Preload bool
+ Fields string
+ }
+)
+
+func (slf *WarehouseMonthStats) TableName() string {
+ return "wms_month_stats"
+}
+
+func NewWarehouseMonthStatsSearch() *WarehouseMonthStatsSearch {
+ return &WarehouseMonthStatsSearch{Orm: mysqlx.GetDB()}
+}
+
+func (slf *WarehouseMonthStatsSearch) SetOrm(tx *gorm.DB) *WarehouseMonthStatsSearch {
+ slf.Orm = tx
+ return slf
+}
+
+func (slf *WarehouseMonthStatsSearch) SetPage(page, size int) *WarehouseMonthStatsSearch {
+ slf.PageNum, slf.PageSize = page, size
+ return slf
+}
+
+func (slf *WarehouseMonthStatsSearch) SetOrder(order string) *WarehouseMonthStatsSearch {
+ slf.Order = order
+ return slf
+}
+
+func (slf *WarehouseMonthStatsSearch) SetID(id int) *WarehouseMonthStatsSearch {
+ slf.Id = id
+ return slf
+}
+
+func (slf *WarehouseMonthStatsSearch) SetKeyword(keyword string) *WarehouseMonthStatsSearch {
+ slf.Keyword = keyword
+ return slf
+}
+
+func (slf *WarehouseMonthStatsSearch) SetPreload(preload bool) *WarehouseMonthStatsSearch {
+ slf.Preload = preload
+ return slf
+}
+
+func (slf *WarehouseMonthStatsSearch) SetDate(date string) *WarehouseMonthStatsSearch {
+ slf.Date = date
+ return slf
+}
+
+func (slf *WarehouseMonthStatsSearch) SetFields(fields string) *WarehouseMonthStatsSearch {
+ slf.Fields = fields
+ return slf
+}
+
+func (slf *WarehouseMonthStatsSearch) build() *gorm.DB {
+ var db = slf.Orm.Model(&WarehouseMonthStats{})
+
+ if slf.Id != 0 {
+ db = db.Where("id = ?", slf.Id)
+ }
+
+ if slf.Order != "" {
+ db = db.Order(slf.Order)
+ }
+
+ if slf.Keyword != "" {
+ kw := fmt.Sprintf("%%%v%%", slf.Keyword)
+ db = db.Where("product_id like ? or product_name like ?", kw, kw)
+ }
+
+ if slf.Date != "" {
+ db = db.Where("date = ?", slf.Date)
+ }
+
+ if slf.Fields != "" {
+ db = db.Select(slf.Fields)
+ }
+
+ return db
+}
+
+// Create 鍗曟潯鎻掑叆
+func (slf *WarehouseMonthStatsSearch) Create(record *WarehouseMonthStats) error {
+ var db = slf.build()
+
+ if err := db.Create(record).Error; err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// CreateBatch 鎵归噺鎻掑叆
+func (slf *WarehouseMonthStatsSearch) CreateBatch(records []*WarehouseMonthStats) error {
+ var db = slf.build()
+
+ if err := db.Create(&records).Error; err != nil {
+ return fmt.Errorf("create batch err: %v, records: %+v", err, records)
+ }
+
+ return nil
+}
+
+func (slf *WarehouseMonthStatsSearch) Update(record *WarehouseMonthStats) error {
+ var db = slf.build()
+
+ if err := db.Omit("CreatedAt").Updates(record).Error; err != nil {
+ return fmt.Errorf("save err: %v, record: %+v", err, record)
+ }
+
+ return nil
+}
+
+func (slf *WarehouseMonthStatsSearch) 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 *WarehouseMonthStatsSearch) UpdateByQuery(query string, args []interface{}, upMap map[string]interface{}) error {
+ var (
+ db = slf.Orm.Table(slf.TableName()).Where(query, args...)
+ )
+
+ if err := db.Updates(upMap).Error; err != nil {
+ return fmt.Errorf("update by query err: %v, query: %s, args: %+v, upMap: %+v", err, query, args, upMap)
+ }
+
+ return nil
+}
+
+func (slf *WarehouseMonthStatsSearch) Delete() error {
+ var db = slf.build()
+ return db.Delete(&WarehouseMonthStats{}).Error
+}
+
+func (slf *WarehouseMonthStatsSearch) First() (*WarehouseMonthStats, error) {
+ var (
+ record = new(WarehouseMonthStats)
+ db = slf.build()
+ )
+
+ if err := db.First(record).Error; err != nil {
+ return record, err
+ }
+
+ return record, nil
+}
+
+func (slf *WarehouseMonthStatsSearch) Find() ([]*WarehouseMonthStats, int64, error) {
+ var (
+ records = make([]*WarehouseMonthStats, 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 *WarehouseMonthStatsSearch) FindNotTotal() ([]*WarehouseMonthStats, error) {
+ var (
+ records = make([]*WarehouseMonthStats, 0)
+ db = slf.build()
+ )
+
+ 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, fmt.Errorf("find records err: %v", err)
+ }
+
+ return records, nil
+}
+
+// FindByQuery 鎸囧畾鏉′欢鏌ヨ.
+func (slf *WarehouseMonthStatsSearch) FindByQuery(query string, args []interface{}) ([]*WarehouseMonthStats, int64, error) {
+ var (
+ records = make([]*WarehouseMonthStats, 0)
+ total int64
+ db = slf.Orm.Table(slf.TableName()).Where(query, args...)
+ )
+
+ if err := db.Count(&total).Error; err != nil {
+ return records, total, fmt.Errorf("find by query 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 by query records err: %v, query: %s, args: %+v", err, query, args)
+ }
+
+ return records, total, nil
+}
+
+// FindByQueryNotTotal 鎸囧畾鏉′欢鏌ヨ&涓嶆煡璇㈡�绘潯鏁�.
+func (slf *WarehouseMonthStatsSearch) FindByQueryNotTotal(query string, args []interface{}) ([]*WarehouseMonthStats, error) {
+ var (
+ records = make([]*WarehouseMonthStats, 0)
+ db = slf.Orm.Table(slf.TableName()).Where(query, args...)
+ )
+
+ 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, fmt.Errorf("find by query records err: %v, query: %s, args: %+v", err, query, args)
+ }
+
+ return records, nil
+}
+
+func WarehouseMonthStatsMap(records []*WarehouseMonthStats) (m map[string]*WarehouseMonthStats) {
+ m = make(map[string]*WarehouseMonthStats, len(records))
+ for _, record := range records {
+ m[record.ProductId] = record
+ }
+ return m
+}
+
+func (slf *WarehouseMonthStatsSearch) Count() (int64, error) {
+ var (
+ total int64
+ db = slf.build()
+ )
+ err := db.Count(&total).Error
+ return total, err
+}
diff --git a/request/report_forms_request.go b/request/report_forms_request.go
index 71b4c81..ca92133 100644
--- a/request/report_forms_request.go
+++ b/request/report_forms_request.go
@@ -28,8 +28,9 @@
type GetMonthStats struct {
PageInfo
- Keyword string `json:"keyword"`
- Date string `json:"date"`
+ Keyword string `json:"keyword"`
+ Date string `json:"date"`
+ WarehouseID int `json:"warehouseID"`
}
type DoMonthStats struct {
diff --git a/router/router.go b/router/router.go
index b76899e..f46070c 100644
--- a/router/router.go
+++ b/router/router.go
@@ -178,6 +178,8 @@
reportFormsAPI.POST("monthStats", reportFormsController.MonthStats) //鑾峰彇鏈堝害缁熻鎶ヨ〃
reportFormsAPI.POST("downloadMonthStats", reportFormsController.DownloadMonthStats) //涓嬭浇鏈堝害缁熻鎶ヨ〃
reportFormsAPI.POST("doMonthStats", reportFormsController.DoMonthStats) //鎵嬪姩璺戞湀搴︾粺璁″簱瀛樻姤琛�
+
+ reportFormsAPI.POST("warehouseMonthStats", reportFormsController.WarehouseMonthStats) //鎸変粨搴撹幏鍙栨湀搴︾粺璁℃姤琛�
}
//閲嶈璐ц鍒�
diff --git a/service/warehouse_month_forms.go b/service/warehouse_month_forms.go
new file mode 100644
index 0000000..1885a16
--- /dev/null
+++ b/service/warehouse_month_forms.go
@@ -0,0 +1,151 @@
+package service
+
+import (
+ "github.com/shopspring/decimal"
+ "time"
+ "wms/constvar"
+ "wms/models"
+ "wms/pkg/logx"
+ "wms/request"
+ "wms/utils"
+)
+
+type WarehouseMonthFormsService struct{}
+
+func NewWarehouseMonthFormsService() *WarehouseMonthFormsService {
+ return &WarehouseMonthFormsService{}
+}
+
+func (slf *WarehouseMonthFormsService) Query(params request.GetMonthStats) (result []*models.WarehouseMonthStats, err error) {
+ search := slf.BuildSearch(params)
+ search = search.SetPage(params.Page, params.PageSize)
+ return search.FindNotTotal()
+}
+
+func (slf *WarehouseMonthFormsService) BuildSearch(params request.GetMonthStats) (search *models.WarehouseMonthStatsSearch) {
+ search = models.NewWarehouseMonthStatsSearch().SetKeyword(params.Keyword).SetDate(params.Date)
+ return search
+}
+
+func (slf *WarehouseMonthFormsService) Count(params request.GetMonthStats) (total int64, err error) {
+ search := slf.BuildSearch(params)
+ return search.Count()
+}
+
+func (slf *WarehouseMonthFormsService) FetchAll(params request.GetMonthStats) (list []*models.WarehouseMonthStats, err error) {
+ total, err := slf.Count(params)
+ if err != nil {
+ return nil, err
+ }
+ list = make([]*models.WarehouseMonthStats, 0, total)
+ params.PageSize = 500
+ page := 1
+ for {
+ params.Page = page
+ data, err := slf.Query(params)
+ if err != nil {
+ return nil, err
+ }
+ if len(data) == 0 {
+ break
+ }
+ list = append(list, data...)
+ page++
+ }
+ return
+}
+
+func GetCurrentWarehouseStats(date string, warehouseId int, productIds []string) (statRecords []*models.WarehouseMonthStats, err error) {
+ //鏈湀鏈熷垵鏁伴噺/涓婃湀缁撲綑鏁伴噺
+ groupSumList, err := models.NewLocationProductAmountSearch().SetProductIds(productIds).GroupSum("product_id", "amount")
+ productIds = make([]string, 0, len(groupSumList))
+ for _, groupSum := range groupSumList {
+ productIds = append(productIds, groupSum.Class)
+ }
+ products, err := models.NewMaterialSearch().SetFields("id, name, unit, weight, more_unit, more_unit_value").SetIDs(productIds).FindNotTotal()
+ if err != nil {
+ logx.Errorf("MonthStats GetCurrentStats get products err:%v", err)
+ return
+ }
+ productMap := models.MaterialMap(products)
+
+ beginTime, endTime := utils.GetLastMonthPeriod()
+ inputMap, err := GetStatsMulti(beginTime, endTime, constvar.BaseOperationTypeIncoming, warehouseId)
+ if err != nil {
+ logx.Errorf("MonthStats GetStatsByOperationType input err:%v", err)
+ return
+ }
+
+ outputMap, err := GetStatsMulti(beginTime, endTime, constvar.BaseOperationTypeOutgoing, warehouseId)
+ if err != nil {
+ logx.Errorf("MonthStats GetStatsByOperationType output err:%v", err)
+ return
+ }
+
+ for _, groupSum := range groupSumList {
+ productId := groupSum.Class
+ if productMap[productId] == nil {
+ continue
+ }
+ product := productMap[productId]
+
+ amount := groupSum.Sum
+ record := models.WarehouseMonthStats{
+ WarehouseId: warehouseId,
+ ProductId: productId,
+ ProductName: product.Name,
+ Unit: product.Unit,
+ SalePrice: product.SalePrice,
+ EndAmount: amount,
+ InputAmount: SumMapAmount(inputMap[productId]),
+ InputItems: GetDealerItems(inputMap[productId]),
+ OutputAmount: SumMapAmount(outputMap[productId]),
+ OutputItems: GetDealerItems(outputMap[productId]),
+ Date: date,
+ }
+ statRecords = append(statRecords, &record)
+ }
+
+ return
+}
+
+func GetStatsMulti(beginTime, endTime time.Time, operationType constvar.BaseOperationType, warehouseId int) (m map[string]map[string]decimal.Decimal, err error) {
+ operationIds, err := models.NewOperationSearch().SetBaseOperationType(operationType).
+ SetFields("id").SetTimeBetween(beginTime, endTime).
+ SetWarehouseId(warehouseId).
+ FindIds()
+ if err != nil {
+ return
+ }
+ groupSumList, err := models.NewOperationDetailsSearch().SetOperationIds(operationIds).
+ SetFields("product_id, dealer_type, amount").
+ GroupMultiSumAmount()
+ if err != nil {
+ return
+ }
+ m = make(map[string]map[string]decimal.Decimal)
+ for _, v := range groupSumList {
+ if m[v.ProductID] == nil {
+ m[v.ProductID] = make(map[string]decimal.Decimal)
+ }
+ m[v.ProductID][v.DealerType] = v.Sum
+ }
+ return
+}
+
+func SumMapAmount(m map[string]decimal.Decimal) (sum decimal.Decimal) {
+ for _, v := range m {
+ sum = sum.Add(v)
+ }
+ return
+}
+
+func GetDealerItems(m map[string]decimal.Decimal) (items []*models.WarehouseStatsItems) {
+ for k, v := range m {
+ items = append(items, &models.WarehouseStatsItems{
+ Name: k,
+ Amount: v,
+ })
+ }
+ return
+}
--
Gitblit v1.8.0