forked from free-lancers/electricity_bill_calc_service
		
	enhance(calculate): 完善计算部分
This commit is contained in:
		| @@ -3,6 +3,7 @@ package calculate | ||||
| import ( | ||||
| 	"electricity_bill_calc/model" | ||||
| 	"electricity_bill_calc/types" | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/shopspring/decimal" | ||||
| ) | ||||
| @@ -42,6 +43,11 @@ type Meter struct { | ||||
| 	Poolings                []*Pooling | ||||
| } | ||||
|  | ||||
| type PrimaryTenementStatistics struct { | ||||
| 	Tenement model.Tenement | ||||
| 	Meters   []Meter | ||||
| } | ||||
|  | ||||
| type TenementCharge struct { | ||||
| 	Tenement     string | ||||
| 	Overall      model.ConsumptionUnit | ||||
| @@ -54,6 +60,7 @@ type TenementCharge struct { | ||||
| 	LossPooled   decimal.Decimal | ||||
| 	PublicPooled decimal.Decimal | ||||
| 	FinalCharges decimal.Decimal | ||||
| 	Loss         decimal.Decimal | ||||
| 	Submeters    []*Meter | ||||
| 	Poolings     []*Meter | ||||
| } | ||||
| @@ -90,3 +97,118 @@ type PoolingSummary struct { | ||||
| 	OverallAmount     decimal.Decimal | ||||
| 	PoolingProportion decimal.Decimal | ||||
| } | ||||
|  | ||||
| func FromReportSummary(summary *model.ReportSummary, pricingMode *model.ReportIndex) Summary { | ||||
| 	var parkPrice float64 | ||||
| 	switch pricingMode.PricePolicy { | ||||
| 	case model.PRICING_POLICY_CONSUMPTION: | ||||
| 		parkPrice = summary.ConsumptionFee.Decimal.InexactFloat64() / summary.Overall.Amount.InexactFloat64() | ||||
| 	case model.PRICING_POLICY_ALL: | ||||
| 		parkPrice = summary.Overall.Fee.InexactFloat64() / summary.Overall.Amount.InexactFloat64() | ||||
| 	default: | ||||
| 		fmt.Println("无法识别类型") | ||||
| 	} | ||||
|  | ||||
| 	flatAmount := summary.Overall.Amount.InexactFloat64() - | ||||
| 		summary.Critical.Amount.InexactFloat64() - | ||||
| 		summary.Peak.Amount.InexactFloat64() - | ||||
| 		summary.Valley.Amount.InexactFloat64() | ||||
|  | ||||
| 	flatFee := summary.Overall.Amount.InexactFloat64() - | ||||
| 		summary.Critical.Fee.InexactFloat64() - | ||||
| 		summary.Peak.Fee.InexactFloat64() - | ||||
| 		summary.Valley.Fee.InexactFloat64() | ||||
|  | ||||
| 	var OverallPrice float64 | ||||
| 	if summary.Overall.Amount.GreaterThan(decimal.Zero) { | ||||
| 		OverallPrice = parkPrice | ||||
| 	} else { | ||||
| 		OverallPrice = decimal.Zero.InexactFloat64() | ||||
| 	} | ||||
|  | ||||
| 	var CriticalPrice float64 | ||||
| 	if summary.Critical.Amount.GreaterThan(decimal.Zero) { | ||||
| 		CriticalPrice = summary.Critical.Fee.InexactFloat64() / summary.Critical.Amount.InexactFloat64() | ||||
| 	} else { | ||||
| 		CriticalPrice = decimal.Zero.InexactFloat64() | ||||
| 	} | ||||
|  | ||||
| 	var PeakPrice float64 | ||||
| 	if summary.Peak.Amount.GreaterThan(decimal.Zero) { | ||||
| 		PeakPrice = summary.Peak.Fee.InexactFloat64() / summary.Peak.Amount.InexactFloat64() | ||||
| 	} else { | ||||
| 		PeakPrice = decimal.Zero.InexactFloat64() | ||||
| 	} | ||||
|  | ||||
| 	var FlatPrice float64 | ||||
| 	if decimal.NewFromFloat(flatAmount).GreaterThan(decimal.Zero) { | ||||
| 		FlatPrice = flatFee / flatAmount | ||||
| 	} else { | ||||
| 		FlatPrice = decimal.Zero.InexactFloat64() | ||||
| 	} | ||||
|  | ||||
| 	var ValleyPrice float64 | ||||
| 	if summary.Valley.Amount.GreaterThan(decimal.Zero) { | ||||
| 		ValleyPrice = summary.Valley.Fee.InexactFloat64() / summary.Valley.Amount.InexactFloat64() | ||||
| 	} else { | ||||
| 		ValleyPrice = decimal.Zero.InexactFloat64() | ||||
| 	} | ||||
|  | ||||
| 	var LossDilutedPrice float64 | ||||
| 	if summary.Overall.Amount.GreaterThan(decimal.Zero) { | ||||
| 		LossDilutedPrice = parkPrice | ||||
| 	} else { | ||||
| 		LossDilutedPrice = decimal.Zero.InexactFloat64() | ||||
| 	} | ||||
|  | ||||
| 	_ = parkPrice | ||||
|  | ||||
| 	return Summary{ | ||||
| 		ReportId:    summary.ReportId, | ||||
| 		OverallArea: decimal.Zero, | ||||
| 		Overall: model.ConsumptionUnit{ | ||||
| 			Amount:     summary.Overall.Amount, | ||||
| 			Fee:        summary.Overall.Fee, | ||||
| 			Price:      decimal.NewFromFloat(OverallPrice), | ||||
| 			Proportion: decimal.NewFromFloat(1.0), | ||||
| 		}, | ||||
| 		ConsumptionFee: summary.ConsumptionFee.Decimal, | ||||
| 		Critical: model.ConsumptionUnit{ | ||||
| 			Amount:     summary.Critical.Amount, | ||||
| 			Fee:        summary.Critical.Fee, | ||||
| 			Price:      decimal.NewFromFloat(CriticalPrice), | ||||
| 			Proportion: decimal.NewFromFloat(summary.Critical.Amount.InexactFloat64() / summary.Overall.Amount.InexactFloat64()), | ||||
| 		}, | ||||
| 		Peak: model.ConsumptionUnit{ | ||||
| 			Amount:     summary.Peak.Amount, | ||||
| 			Fee:        summary.Peak.Fee, | ||||
| 			Price:      decimal.NewFromFloat(PeakPrice), | ||||
| 			Proportion: decimal.NewFromFloat(summary.Peak.Amount.InexactFloat64() / summary.Overall.Amount.InexactFloat64()), | ||||
| 		}, | ||||
| 		Flat: model.ConsumptionUnit{ | ||||
| 			Amount:     decimal.NewFromFloat(flatAmount), | ||||
| 			Fee:        decimal.NewFromFloat(flatFee), | ||||
| 			Price:      decimal.NewFromFloat(FlatPrice), | ||||
| 			Proportion: decimal.NewFromFloat(flatAmount / summary.Overall.Amount.InexactFloat64()), | ||||
| 		}, | ||||
| 		Valley: model.ConsumptionUnit{ | ||||
| 			Amount:     summary.Valley.Amount, | ||||
| 			Fee:        summary.Valley.Fee, | ||||
| 			Price:      decimal.NewFromFloat(ValleyPrice), | ||||
| 			Proportion: decimal.NewFromFloat(summary.Valley.Amount.InexactFloat64() / summary.Overall.Amount.InexactFloat64()), | ||||
| 		}, | ||||
| 		Loss:                         decimal.Zero, | ||||
| 		LossFee:                      decimal.Zero, | ||||
| 		LossProportion:               decimal.Zero, | ||||
| 		AuthoizeLoss:                 model.ConsumptionUnit{}, | ||||
| 		BasicFee:                     summary.BasicFee, | ||||
| 		BasicPooledPriceConsumption:  decimal.Zero, | ||||
| 		BasicPooledPriceArea:         decimal.Zero, | ||||
| 		AdjustFee:                    summary.AdjustFee, | ||||
| 		AdjustPooledPriceConsumption: decimal.Zero, | ||||
| 		AdjustPooledPriceArea:        decimal.Zero, | ||||
| 		LossDilutedPrice:             decimal.NewFromFloat(LossDilutedPrice), | ||||
| 		TotalConsumption:             decimal.Zero, | ||||
| 		FinalDilutedOverall:          decimal.Zero, | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -1,133 +0,0 @@ | ||||
| package model | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/shopspring/decimal" | ||||
| 	"github.com/uptrace/bun" | ||||
| ) | ||||
|  | ||||
| type EndUserDetail struct { | ||||
| 	bun.BaseModel         `bun:"table:end_user_detail,alias:eud"` | ||||
| 	CreatedAndModified    `bun:"extend"` | ||||
| 	ReportId              string              `bun:",pk,notnull" json:"reportId"` | ||||
| 	ParkId                string              `bun:",pk,notnull" json:"parkId"` | ||||
| 	MeterId               string              `bun:"meter_04kv_id,pk,notnull" json:"meterId"` | ||||
| 	Seq                   int64               `bun:"type:bigint,notnull" json:"seq"` | ||||
| 	Ratio                 decimal.Decimal     `bun:"type:numeric,notnull" json:"ratio"` | ||||
| 	Address               *string             `json:"address"` | ||||
| 	CustomerName          *string             `json:"customerName"` | ||||
| 	ContactName           *string             `json:"contactName"` | ||||
| 	ContactPhone          *string             `json:"contactPhone"` | ||||
| 	IsPublicMeter         bool                `bun:"public_meter,notnull" json:"isPublicMeter"` | ||||
| 	LastPeriodOverall     decimal.Decimal     `bun:"type:numeric,notnull" json:"lastPeriodOverall"` | ||||
| 	LastPeriodCritical    decimal.Decimal     `bun:"type:numeric,notnull" json:"lastPeriodCritical"` | ||||
| 	LastPeriodPeak        decimal.Decimal     `bun:"type:numeric,notnull" json:"lastPeriodPeak"` | ||||
| 	LastPeriodFlat        decimal.Decimal     `bun:"type:numeric,notnull" json:"lastPeriodFlat"` | ||||
| 	LastPeriodValley      decimal.Decimal     `bun:"type:numeric,notnull" json:"lastPeriodValley"` | ||||
| 	CurrentPeriodOverall  decimal.Decimal     `bun:"type:numeric,notnull" json:"currentPeriodOverall"` | ||||
| 	CurrentPeriodCritical decimal.Decimal     `bun:"type:numeric,notnull" json:"currentPeriodCritical"` | ||||
| 	CurrentPeriodPeak     decimal.Decimal     `bun:"type:numeric,notnull" json:"currentPeriodPeak"` | ||||
| 	CurrentPeriodFlat     decimal.Decimal     `bun:"type:numeric,notnull" json:"currentPeriodFlat"` | ||||
| 	CurrentPeriodValley   decimal.Decimal     `bun:"type:numeric,notnull" json:"currentPeriodValley"` | ||||
| 	AdjustOverall         decimal.Decimal     `bun:"type:numeric,notnull" json:"adjustOverall"` | ||||
| 	AdjustCritical        decimal.Decimal     `bun:"type:numeric,notnull" json:"adjustCritical"` | ||||
| 	AdjustPeak            decimal.Decimal     `bun:"type:numeric,notnull" json:"adjustPeak"` | ||||
| 	AdjustFlat            decimal.Decimal     `bun:"type:numeric,notnull" json:"adjustFlat"` | ||||
| 	AdjustValley          decimal.Decimal     `bun:"type:numeric,notnull" json:"adjustValley"` | ||||
| 	Overall               decimal.NullDecimal `bun:"type:numeric" json:"overall"` | ||||
| 	OverallFee            decimal.NullDecimal `bun:"type:numeric" json:"overallFee"` | ||||
| 	OverallProportion     decimal.Decimal     `bun:"type:numeric,notnull" json:"-"` | ||||
| 	Critical              decimal.NullDecimal `bun:"type:numeric" json:"critical"` | ||||
| 	CriticalFee           decimal.NullDecimal `bun:"type:numeric" json:"criticalFee"` | ||||
| 	Peak                  decimal.NullDecimal `bun:"type:numeric" json:"peak"` | ||||
| 	PeakFee               decimal.NullDecimal `bun:"type:numeric" json:"peakFee"` | ||||
| 	Flat                  decimal.NullDecimal `bun:"type:numeric" json:"flat"` | ||||
| 	FlatFee               decimal.NullDecimal `bun:"type:numeric" json:"flatFee"` | ||||
| 	Valley                decimal.NullDecimal `bun:"type:numeric" json:"valley"` | ||||
| 	ValleyFee             decimal.NullDecimal `bun:"type:numeric" json:"valleyFee"` | ||||
| 	BasicFeeDiluted       decimal.NullDecimal `bun:"type:numeric" json:"basicFeeDiluted"` | ||||
| 	AdjustFeeDiluted      decimal.NullDecimal `bun:"type:numeric" json:"adjustFeeDiluted"` | ||||
| 	LossDiluted           decimal.NullDecimal `bun:"type:numeric" json:"lossDiluted"` | ||||
| 	LossFeeDiluted        decimal.NullDecimal `bun:"type:numeric" json:"lossFeeDiluted"` | ||||
| 	FinalDiluted          decimal.NullDecimal `bun:"type:numeric" json:"finalDiluted"` | ||||
| 	FinalCharge           decimal.NullDecimal `bun:"type:numeric" json:"finalCharge"` | ||||
| 	Initialize            bool                `bun:"-" json:"-"` | ||||
| 	Origin                *Meter04KV          `bun:"rel:belongs-to,join:park_id=park_id,join:meter_04kv_id=code" json:"-"` | ||||
| 	Report                *Report             `bun:"rel:belongs-to,join:report_id=id" json:"-"` | ||||
| 	Park                  *Park               `bun:"rel:belongs-to,join:park_id=id" json:"-"` | ||||
| } | ||||
|  | ||||
| var _ bun.BeforeAppendModelHook = (*EndUserDetail)(nil) | ||||
|  | ||||
| func (d *EndUserDetail) BeforeAppendModel(ctx context.Context, query bun.Query) error { | ||||
| 	oprTime := time.Now() | ||||
| 	switch query.(type) { | ||||
| 	case *bun.InsertQuery: | ||||
| 		d.CreatedAt = oprTime | ||||
| 		d.LastModifiedAt = &oprTime | ||||
| 	case *bun.UpdateQuery: | ||||
| 		d.LastModifiedAt = &oprTime | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (d EndUserDetail) Validate() (bool, error) { | ||||
| 	lastPeriodSum := decimal.Sum(d.LastPeriodCritical, d.LastPeriodPeak, d.LastPeriodValley) | ||||
| 	if lastPeriodSum.GreaterThan(d.LastPeriodOverall) { | ||||
| 		return false, errors.New("上期峰谷计量总量大于上期总计电量") | ||||
| 	} | ||||
| 	currentPeriodSum := decimal.Sum(d.CurrentPeriodCritical, d.CurrentPeriodPeak, d.CurrentPeriodValley) | ||||
| 	if currentPeriodSum.GreaterThan(d.CurrentPeriodOverall) { | ||||
| 		return false, errors.New("本期峰谷计量总量大于本期总计电量") | ||||
| 	} | ||||
| 	return true, nil | ||||
| } | ||||
|  | ||||
| func (d *EndUserDetail) CalculatePeriod() { | ||||
| 	d.LastPeriodFlat = d.LastPeriodOverall.Sub(d.LastPeriodCritical).Sub(d.LastPeriodPeak).Sub(d.LastPeriodValley) | ||||
| 	d.CurrentPeriodFlat = d.CurrentPeriodOverall.Sub(d.CurrentPeriodCritical).Sub(d.CurrentPeriodPeak).Sub(d.CurrentPeriodValley) | ||||
| 	d.Overall = decimal.NewNullDecimal(d.CurrentPeriodOverall.Sub(d.LastPeriodOverall).Mul(d.Ratio).Add(d.AdjustOverall).RoundBank(2)) | ||||
| 	d.Critical = decimal.NewNullDecimal(d.CurrentPeriodCritical.Sub(d.LastPeriodCritical).Mul(d.Ratio).Add(d.AdjustCritical).RoundBank(2)) | ||||
| 	d.Peak = decimal.NewNullDecimal(d.CurrentPeriodPeak.Sub(d.LastPeriodPeak).Mul(d.Ratio).Add(d.AdjustPeak).RoundBank(2)) | ||||
| 	d.Flat = decimal.NewNullDecimal(d.CurrentPeriodFlat.Sub(d.LastPeriodFlat).Mul(d.Ratio).Add(d.AdjustFlat).RoundBank(2)) | ||||
| 	d.Valley = decimal.NewNullDecimal(d.CurrentPeriodValley.Sub(d.LastPeriodValley).Mul(d.Ratio).Add(d.AdjustValley).RoundBank(2)) | ||||
| } | ||||
|  | ||||
| type EndUserImport struct { | ||||
| 	MeterId               string              `excel:"meterId"` | ||||
| 	LastPeriodOverall     decimal.Decimal     `excel:"lastPeriodOverall"` | ||||
| 	CurrentPeriodOverall  decimal.Decimal     `excel:"currentPeriodOverall"` | ||||
| 	LastPeriodCritical    decimal.NullDecimal `excel:"lastPeriodCritical"` | ||||
| 	LastPeriodPeak        decimal.NullDecimal `excel:"lastPeriodPeak"` | ||||
| 	LastPeriodValley      decimal.NullDecimal `excel:"lastPeriodValley"` | ||||
| 	CurrentPeriodCritical decimal.NullDecimal `excel:"currentPeriodCritical"` | ||||
| 	CurrentPeriodPeak     decimal.NullDecimal `excel:"currentPeriodPeak"` | ||||
| 	CurrentPeriodValley   decimal.NullDecimal `excel:"currentPeriodValley"` | ||||
| 	AdjustOverall         decimal.Decimal     `excel:"adjustOverall"` | ||||
| 	AdjustCritical        decimal.NullDecimal `excel:"adjustCritical"` | ||||
| 	AdjustPeak            decimal.NullDecimal `excel:"adjustPeak"` | ||||
| 	AdjustFlat            decimal.NullDecimal `excel:"adjustFlat"` | ||||
| 	AdjustValley          decimal.NullDecimal `excel:"adjustValley"` | ||||
| } | ||||
|  | ||||
| type EndUserPeriodStat struct { | ||||
| 	CustomerName     string              `json:"customerName"` | ||||
| 	Address          string              `json:"address"` | ||||
| 	ParkId           string              `json:"parkId"` | ||||
| 	MeterId          string              `bun:"meter_04kv_id" json:"meterId"` | ||||
| 	IsPublicMeter    bool                `bun:"public_meter" json:"isPublicMeter"` | ||||
| 	Kind             int8                `bun:"-" json:"pvKind"` | ||||
| 	Overall          decimal.NullDecimal `json:"overall"` | ||||
| 	Critical         decimal.NullDecimal `json:"critical"` | ||||
| 	Peak             decimal.NullDecimal `json:"peak"` | ||||
| 	Valley           decimal.NullDecimal `json:"valley"` | ||||
| 	OverallFee       decimal.NullDecimal `json:"overallFee"` | ||||
| 	CriticalFee      decimal.NullDecimal `json:"criticalFee"` | ||||
| 	PeakFee          decimal.NullDecimal `json:"peakFee"` | ||||
| 	ValleyFee        decimal.NullDecimal `json:"valleyFee"` | ||||
| 	AdjustFee        decimal.NullDecimal `bun:"final_diluted" json:"adjustFee"` | ||||
| 	AdjustProportion decimal.NullDecimal `bun:"-" json:"adjustProportion"` | ||||
| } | ||||
| @@ -1,48 +0,0 @@ | ||||
| package model | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/shopspring/decimal" | ||||
| 	"github.com/uptrace/bun" | ||||
| ) | ||||
|  | ||||
| type MaintenanceFee struct { | ||||
| 	bun.BaseModel      `bun:"table:maintenance_fee,alias:m"` | ||||
| 	CreatedAndModified `bun:"extend"` | ||||
| 	Deleted            `bun:"extend"` | ||||
| 	Id                 string          `bun:",pk,notnull" json:"id"` | ||||
| 	ParkId             string          `bun:",notnull" json:"parkId"` | ||||
| 	Name               string          `bun:",notnull" json:"name"` | ||||
| 	Period             string          `bun:",notnull" json:"period"` | ||||
| 	Fee                decimal.Decimal `bun:"type:numeric,notnull" json:"fee"` | ||||
| 	Memo               *string         `bun:"type:text" json:"memo"` | ||||
| 	Enabled            bool            `bun:",notnull" json:"enabled"` | ||||
| 	Park               Park            `bun:"rel:belongs-to,join:park_id=id"` | ||||
| } | ||||
|  | ||||
| var _ bun.BeforeAppendModelHook = (*MaintenanceFee)(nil) | ||||
|  | ||||
| func (f *MaintenanceFee) BeforeAppendModel(ctx context.Context, query bun.Query) error { | ||||
| 	oprTime := time.Now() | ||||
| 	switch query.(type) { | ||||
| 	case *bun.InsertQuery: | ||||
| 		f.CreatedAt = oprTime | ||||
| 		f.LastModifiedAt = &oprTime | ||||
| 	case *bun.UpdateQuery: | ||||
| 		f.LastModifiedAt = &oprTime | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type AdditionalCharge struct { | ||||
| 	ParkId          string               `json:"parkId"` | ||||
| 	Period          string               `json:"period"` | ||||
| 	Fee             decimal.Decimal      `json:"fee"` | ||||
| 	Price           decimal.Decimal      `json:"price"` | ||||
| 	QuarterPrice    decimal.Decimal      `json:"quarterPrice"` | ||||
| 	SemiAnnualPrice decimal.Decimal      `json:"semiAnnualPrice"` | ||||
| 	Enterprise      UserDetailSimplified `json:"user"` | ||||
| 	Park            Park                 `json:"park"` | ||||
| } | ||||
| @@ -1,39 +0,0 @@ | ||||
| package model | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/shopspring/decimal" | ||||
| 	"github.com/uptrace/bun" | ||||
| ) | ||||
|  | ||||
| type Meter04KV struct { | ||||
| 	bun.BaseModel      `bun:"table:meter_04kv,alias:mt"` | ||||
| 	CreatedAndModified `bun:"extend"` | ||||
| 	Code               string          `bun:",pk,notnull" json:"code" excel:"code"` | ||||
| 	ParkId             string          `bun:",pk,notnull" json:"parkId"` | ||||
| 	Address            *string         `json:"address" excel:"address"` | ||||
| 	CustomerName       *string         `json:"customerName" excel:"name"` | ||||
| 	ContactName        *string         `json:"contactName" excel:"contact"` | ||||
| 	ContactPhone       *string         `json:"contactPhone" excel:"phone"` | ||||
| 	Ratio              decimal.Decimal `bun:"type:numeric,notnull" json:"ratio" excel:"ratio"` | ||||
| 	Seq                int64           `bun:"type:bigint,notnull" json:"seq" excel:"seq"` | ||||
| 	IsPublicMeter      bool            `bun:"public_meter,notnull" json:"isPublicMeter" excel:"public"` | ||||
| 	Enabled            bool            `bun:",notnull" json:"enabled"` | ||||
| 	ParkDetail         *Park           `bun:"rel:belongs-to,join:park_id=id" json:"-"` | ||||
| } | ||||
|  | ||||
| var _ bun.BeforeAppendModelHook = (*Meter04KV)(nil) | ||||
|  | ||||
| func (m *Meter04KV) BeforeAppendModel(ctx context.Context, query bun.Query) error { | ||||
| 	oprTime := time.Now() | ||||
| 	switch query.(type) { | ||||
| 	case *bun.InsertQuery: | ||||
| 		m.CreatedAt = oprTime | ||||
| 		m.LastModifiedAt = &oprTime | ||||
| 	case *bun.UpdateQuery: | ||||
| 		m.LastModifiedAt = &oprTime | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| @@ -1,6 +1,8 @@ | ||||
| package model | ||||
|  | ||||
| import ( | ||||
| 	"electricity_bill_calc/types" | ||||
|  | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/shopspring/decimal" | ||||
| @@ -31,3 +33,14 @@ type Park struct { | ||||
| 	LastModifiedAt   time.Time           `json:"lastModifiedAt"` | ||||
| 	DeletedAt        *time.Time          `json:"deletedAt"` | ||||
| } | ||||
|  | ||||
| type Parks struct { | ||||
| 	Park | ||||
| 	NormAuthorizedLossRate float64 `json:"norm_authorized_loss_rate"` | ||||
| } | ||||
|  | ||||
| type ParkPeriodStatistics struct { | ||||
| 	Id     string `json:"id"` | ||||
| 	Name   string `json:"name"` | ||||
| 	Period *types.DateRange | ||||
| } | ||||
|   | ||||
| @@ -1,116 +0,0 @@ | ||||
| package model | ||||
|  | ||||
| import "github.com/shopspring/decimal" | ||||
|  | ||||
| type PaidPart struct { | ||||
| 	Overall        decimal.Decimal     `json:"overall"` | ||||
| 	OverallPrice   decimal.Decimal     `json:"overallPrice"` | ||||
| 	ConsumptionFee decimal.Decimal     `json:"consumptionFee"` | ||||
| 	OverallFee     decimal.Decimal     `json:"overallFee"` | ||||
| 	Critical       decimal.NullDecimal `json:"critical"` | ||||
| 	CriticalPrice  decimal.NullDecimal `json:"criticalPrice"` | ||||
| 	CriticalFee    decimal.NullDecimal `json:"criticalFee"` | ||||
| 	Peak           decimal.NullDecimal `json:"peak"` | ||||
| 	PeakPrice      decimal.NullDecimal `json:"peakPrice"` | ||||
| 	PeakFee        decimal.NullDecimal `json:"peakFee"` | ||||
| 	Flat           decimal.NullDecimal `json:"flat"` | ||||
| 	FlatPrice      decimal.NullDecimal `json:"flatPrice"` | ||||
| 	FlatFee        decimal.NullDecimal `json:"flatFee"` | ||||
| 	Valley         decimal.NullDecimal `json:"valley"` | ||||
| 	ValleyPrice    decimal.NullDecimal `json:"valleyPrice"` | ||||
| 	ValleyFee      decimal.NullDecimal `json:"valleyFee"` | ||||
| 	BasicFee       decimal.Decimal     `json:"basicFee"` | ||||
| 	AdjustFee      decimal.Decimal     `json:"adjustFee"` | ||||
| } | ||||
|  | ||||
| type EndUserOverallPart struct { | ||||
| 	Overall       decimal.Decimal     `json:"overall"` | ||||
| 	OverallPrice  decimal.Decimal     `json:"overallPrice"` | ||||
| 	OverallFee    decimal.Decimal     `json:"consumptionFee"` | ||||
| 	Critical      decimal.NullDecimal `json:"critical"` | ||||
| 	CriticalPrice decimal.NullDecimal `json:"criticalPrice"` | ||||
| 	CriticalFee   decimal.NullDecimal `json:"criticalFee"` | ||||
| 	Peak          decimal.NullDecimal `json:"peak"` | ||||
| 	PeakPrice     decimal.NullDecimal `json:"peakPrice"` | ||||
| 	PeakFee       decimal.NullDecimal `json:"peakFee"` | ||||
| 	Flat          decimal.NullDecimal `json:"flat"` | ||||
| 	FlatPrice     decimal.NullDecimal `json:"flatPrice"` | ||||
| 	FlatFee       decimal.NullDecimal `json:"flatFee"` | ||||
| 	Valley        decimal.NullDecimal `json:"valley"` | ||||
| 	ValleyPrice   decimal.NullDecimal `json:"valleyPrice"` | ||||
| 	ValleyFee     decimal.NullDecimal `json:"valleyFee"` | ||||
| } | ||||
|  | ||||
| type ConsumptionOverallPart struct { | ||||
| 	Overall        decimal.Decimal     `json:"overall"` | ||||
| 	OverallPrice   decimal.Decimal     `json:"overallPrice"` | ||||
| 	ConsumptionFee decimal.Decimal     `json:"consumptionFee"` | ||||
| 	OverallFee     decimal.Decimal     `json:"overallFee"` | ||||
| 	Critical       decimal.NullDecimal `json:"critical"` | ||||
| 	CriticalPrice  decimal.NullDecimal `json:"criticalPrice"` | ||||
| 	CriticalFee    decimal.NullDecimal `json:"criticalFee"` | ||||
| 	Peak           decimal.NullDecimal `json:"peak"` | ||||
| 	PeakPrice      decimal.NullDecimal `json:"peakPrice"` | ||||
| 	PeakFee        decimal.NullDecimal `json:"peakFee"` | ||||
| 	Flat           decimal.NullDecimal `json:"flat"` | ||||
| 	FlatPrice      decimal.NullDecimal `json:"flatPrice"` | ||||
| 	FlatFee        decimal.NullDecimal `json:"flatFee"` | ||||
| 	Valley         decimal.NullDecimal `json:"valley"` | ||||
| 	ValleyPrice    decimal.NullDecimal `json:"valleyPrice"` | ||||
| 	ValleyFee      decimal.NullDecimal `json:"valleyFee"` | ||||
| 	Proportion     decimal.Decimal     `json:"proportion"` | ||||
| } | ||||
|  | ||||
| type LossPart struct { | ||||
| 	Quantity                decimal.Decimal `json:"quantity"` | ||||
| 	Price                   decimal.Decimal `json:"price"` | ||||
| 	ConsumptionFee          decimal.Decimal `json:"consumptionFee"` | ||||
| 	Proportion              decimal.Decimal `json:"proportion"` | ||||
| 	AuthorizeQuantity       decimal.Decimal `json:"authorizeQuantity"` | ||||
| 	AuthorizeConsumptionFee decimal.Decimal `json:"authorizeConsumptionFee"` | ||||
| } | ||||
|  | ||||
| type OtherShouldCollectionPart struct { | ||||
| 	LossFee   decimal.NullDecimal `json:"lossFee"` | ||||
| 	BasicFees decimal.Decimal     `json:"basicFees"` | ||||
| } | ||||
|  | ||||
| type MaintenancePart struct { | ||||
| 	BasicFees        decimal.Decimal `json:"basicFees"` | ||||
| 	LossFee          decimal.Decimal `json:"lossFee"` | ||||
| 	AdjustFee        decimal.Decimal `json:"adjustFee"` | ||||
| 	LossProportion   decimal.Decimal `json:"lossProportion"` | ||||
| 	AdjustProportion decimal.Decimal `json:"adjustProportion"` | ||||
| 	AdjustPrice      decimal.Decimal `json:"adjustPrice"` | ||||
| } | ||||
|  | ||||
| type EndUserSummary struct { | ||||
| 	CustomerName  *string             `json:"customerName"` | ||||
| 	Address       *string             `json:"address"` | ||||
| 	MeterId       string              `json:"meterId"` | ||||
| 	IsPublicMeter bool                `json:"isPublicMeter"` | ||||
| 	Overall       decimal.Decimal     `json:"overall"` | ||||
| 	OverallPrice  decimal.Decimal     `json:"overallPrice"` | ||||
| 	OverallFee    decimal.Decimal     `json:"overallFee"` | ||||
| 	Critical      decimal.NullDecimal `json:"critical"` | ||||
| 	CriticalFee   decimal.NullDecimal `json:"criticalFee"` | ||||
| 	Peak          decimal.NullDecimal `json:"peak"` | ||||
| 	PeakFee       decimal.NullDecimal `json:"peakFee"` | ||||
| 	Valley        decimal.NullDecimal `json:"valley"` | ||||
| 	ValleyFee     decimal.NullDecimal `json:"valleyFee"` | ||||
| 	Loss          decimal.Decimal     `json:"loss"` | ||||
| 	LossFee       decimal.Decimal     `json:"lossFee"` | ||||
| } | ||||
|  | ||||
| type Publicity struct { | ||||
| 	Report                   Report                    `json:"index"` | ||||
| 	User                     UserDetail                `json:"enterprise"` | ||||
| 	Park                     Park                      `json:"park"` | ||||
| 	Paid                     PaidPart                  `json:"paid"` | ||||
| 	EndUser                  ConsumptionOverallPart    `json:"endUserSum"` | ||||
| 	Loss                     LossPart                  `json:"loss"` | ||||
| 	PublicConsumptionOverall ConsumptionOverallPart    `json:"public"` | ||||
| 	OtherCollections         OtherShouldCollectionPart `json:"others"` | ||||
| 	Maintenance              MaintenancePart           `json:"maintenance"` | ||||
| 	EndUserDetails           []EndUserSummary          `json:"endUser"` | ||||
| } | ||||
| @@ -7,25 +7,27 @@ import ( | ||||
| ) | ||||
|  | ||||
| type ReportIndex struct { | ||||
| 	Id                    string          `json:"id"` | ||||
| 	Park                  string          `json:"parkId" db:"park_id"` | ||||
| 	Period                types.DateRange `json:"period"` | ||||
| 	Category              int16           `json:"category"` | ||||
| 	MeterType             int16           `json:"meter04kvType" db:"meter_04kv_type"` | ||||
| 	PricePolicy           int16           `json:"pricePolicy"` | ||||
| 	BasisPooled           int16           `json:"basisPooled"` | ||||
| 	AdjustPooled          int16           `json:"adjustPooled"` | ||||
| 	LossPooled            int16           `json:"lossPooled"` | ||||
| 	PublicPooled          int16           `json:"publicPooled"` | ||||
| 	Published             bool            `json:"published"` | ||||
| 	PublishedAt           *types.DateTime `json:"publishedAt" db:"published_at"` | ||||
| 	Withdraw              int16           `json:"withdraw"` | ||||
| 	LastWithdrawAppliedAt *types.DateTime `json:"lastWithdrawAppliedAt" db:"last_withdraw_applied_at"` | ||||
| 	LastWithdrawAuditAt   *types.DateTime `json:"lastWithdrawAuditAt" db:"last_withdraw_audit_at"` | ||||
| 	Status                *int16          `json:"status"` | ||||
| 	Message               *string         `json:"message"` | ||||
| 	CreatedAt             types.DateTime  `json:"createdAt" db:"created_at"` | ||||
| 	LastModifiedAt        types.DateTime  `json:"lastModifiedAt" db:"last_modified_at"` | ||||
| 	Id                          string          `json:"id"` | ||||
| 	Park                        string          `json:"parkId" db:"park_id"` | ||||
| 	Period                      types.DateRange `json:"period"` | ||||
| 	Category                    int16           `json:"category"` | ||||
| 	MeterType                   int16           `json:"meter04kvType" db:"meter_04kv_type"` | ||||
| 	PricePolicy                 int16           `json:"pricePolicy"` | ||||
| 	BasisPooled                 int16           `json:"basisPooled"` | ||||
| 	AdjustPooled                int16           `json:"adjustPooled"` | ||||
| 	LossPooled                  int16           `json:"lossPooled"` | ||||
| 	PublicPooled                int16           `json:"publicPooled"` | ||||
| 	Published                   bool            `json:"published"` | ||||
| 	PublishedAt                 *types.DateTime `json:"publishedAt" db:"published_at"` | ||||
| 	Withdraw                    int16           `json:"withdraw"` | ||||
| 	LastWithdrawAppliedAt       *types.DateTime `json:"lastWithdrawAppliedAt" db:"last_withdraw_applied_at"` | ||||
| 	LastWithdrawAuditAt         *types.DateTime `json:"lastWithdrawAuditAt" db:"last_withdraw_audit_at"` | ||||
| 	Status                      *int16          `json:"status"` | ||||
| 	Message                     *string         `json:"message"` | ||||
| 	CreatedAt                   types.DateTime  `json:"createdAt" db:"created_at"` | ||||
| 	LastModifiedAt              types.DateTime  `json:"lastModifiedAt" db:"last_modified_at"` | ||||
| 	AuthorizedLossRate          float64         `json:"authorized_loss_rate" db:"authorized_loss_rate"` | ||||
| 	AuthorizedLossRateIncrement float64         `json:"authorized_loss_rate_increment" db:"authorized_loss_rate_increment"` | ||||
| } | ||||
|  | ||||
| type ReportSummary struct { | ||||
|   | ||||
| @@ -1,119 +0,0 @@ | ||||
| package model | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
|  | ||||
| 	"github.com/shopspring/decimal" | ||||
| 	"github.com/uptrace/bun" | ||||
| ) | ||||
|  | ||||
| type ReportSummary struct { | ||||
| 	bun.BaseModel                 `bun:"table:report_summary,alias:rs"` | ||||
| 	ReportId                      string              `bun:",pk,notnull" json:"-"` | ||||
| 	Overall                       decimal.Decimal     `bun:"type:numeric,notnull" json:"overall"` | ||||
| 	OverallFee                    decimal.Decimal     `bun:"type:numeric,notnull" json:"overallFee"` | ||||
| 	ConsumptionFee                decimal.NullDecimal `bun:"type:numeric" json:"consumptionFee"` | ||||
| 	OverallPrice                  decimal.NullDecimal `bun:"type:numeric" json:"overallPrice"` | ||||
| 	Critical                      decimal.Decimal     `bun:"type:numeric,notnull" json:"critical"` | ||||
| 	CriticalFee                   decimal.Decimal     `bun:"type:numeric,notnull" json:"criticalFee"` | ||||
| 	CriticalPrice                 decimal.NullDecimal `bun:"type:numeric" json:"criticalPrice"` | ||||
| 	Peak                          decimal.Decimal     `bun:"type:numeric,notnull" json:"peak"` | ||||
| 	PeakFee                       decimal.Decimal     `bun:"type:numeric,notnull" json:"peakFee"` | ||||
| 	PeakPrice                     decimal.NullDecimal `bun:"type:numeric" json:"peakPrice"` | ||||
| 	Flat                          decimal.Decimal     `bun:"type:numeric,notnull" json:"flat"` | ||||
| 	FlatFee                       decimal.Decimal     `bun:"type:numeric,notnull" json:"flatFee"` | ||||
| 	FlatPrice                     decimal.NullDecimal `bun:"type:numeric" json:"flatPrice"` | ||||
| 	Valley                        decimal.Decimal     `bun:"type:numeric,notnull" json:"valley"` | ||||
| 	ValleyFee                     decimal.Decimal     `bun:"type:numeric,notnull" json:"valleyFee"` | ||||
| 	ValleyPrice                   decimal.NullDecimal `bun:"type:numeric" json:"valleyPrice"` | ||||
| 	Loss                          decimal.NullDecimal `bun:"type:numeric" json:"loss"` | ||||
| 	LossFee                       decimal.NullDecimal `bun:"type:numeric" json:"lossFee"` | ||||
| 	LossProportion                decimal.NullDecimal `bun:"type:numeric" json:"lossProportion"` | ||||
| 	AuthorizeLoss                 decimal.NullDecimal `bun:"type:numeric" json:"authorizeLoss"` | ||||
| 	AuthorizeLossFee              decimal.NullDecimal `bun:"type:numeric" json:"authorizeLossFee"` | ||||
| 	AuthorizeLossProportion       decimal.NullDecimal `bun:"type:numeric" json:"authorizeLossProportion"` | ||||
| 	BasicFee                      decimal.Decimal     `bun:"type:numeric,notnull" json:"basicFee"` | ||||
| 	BasicDilutedPrice             decimal.NullDecimal `bun:"type:numeric" json:"basicDilutedPrice"` | ||||
| 	AdjustFee                     decimal.Decimal     `bun:"type:numeric,notnull" json:"adjustFee"` | ||||
| 	AdjustDilutedPrice            decimal.NullDecimal `bun:"type:numeric" json:"adjustDilutedPrice"` | ||||
| 	MaintenanceDilutedPrice       decimal.NullDecimal `bun:"type:numeric" json:"maintencanceDilutedPrice"` | ||||
| 	LossDilutedPrice              decimal.NullDecimal `bun:"type:numeric" json:"lossDilutedPrice"` | ||||
| 	PublicConsumptionDilutedPrice decimal.NullDecimal `bun:"type:numeric" json:"publicConsumptionDilutedPrice"` | ||||
| 	MaintenanceOverall            decimal.NullDecimal `bun:"type:numeric" json:"maintenanceOverall"` | ||||
| 	FinalDilutedOverall           decimal.NullDecimal `bun:"type:numeric" json:"finalDilutedOverall"` | ||||
| 	Customers                     Consumptions        `bun:"type:jsonb" json:"customers"` | ||||
| 	Publics                       Consumptions        `bun:"type:jsonb" json:"publics"` | ||||
| } | ||||
|  | ||||
| type Consumptions struct { | ||||
| 	Consumption    decimal.NullDecimal `json:"consumption"` | ||||
| 	ConsumptionFee decimal.NullDecimal `json:"fee"` | ||||
| 	Critical       decimal.NullDecimal `json:"critical"` | ||||
| 	CriticalFee    decimal.NullDecimal `json:"criticalFee"` | ||||
| 	Peak           decimal.NullDecimal `json:"peak"` | ||||
| 	PeakFee        decimal.NullDecimal `json:"peakFee"` | ||||
| 	Flat           decimal.NullDecimal `json:"flat"` | ||||
| 	FlatFee        decimal.NullDecimal `json:"flatFee"` | ||||
| 	Valley         decimal.NullDecimal `json:"valley"` | ||||
| 	ValleyFee      decimal.NullDecimal `json:"valleyFee"` | ||||
| 	Proportion     decimal.NullDecimal `json:"proportion"` | ||||
| } | ||||
|  | ||||
| func NewConsumptions() Consumptions { | ||||
| 	return Consumptions{ | ||||
| 		Consumption:    decimal.NewNullDecimal(decimal.Zero), | ||||
| 		ConsumptionFee: decimal.NewNullDecimal(decimal.Zero), | ||||
| 		Critical:       decimal.NewNullDecimal(decimal.Zero), | ||||
| 		Peak:           decimal.NewNullDecimal(decimal.Zero), | ||||
| 		PeakFee:        decimal.NewNullDecimal(decimal.Zero), | ||||
| 		Flat:           decimal.NewNullDecimal(decimal.Zero), | ||||
| 		CriticalFee:    decimal.NewNullDecimal(decimal.Zero), | ||||
| 		FlatFee:        decimal.NewNullDecimal(decimal.Zero), | ||||
| 		Valley:         decimal.NewNullDecimal(decimal.Zero), | ||||
| 		ValleyFee:      decimal.NewNullDecimal(decimal.Zero), | ||||
| 		Proportion:     decimal.NewNullDecimal(decimal.Zero), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (s ReportSummary) Validate() (bool, error) { | ||||
| 	amountSum := decimal.Sum(s.Critical, s.Peak, s.Valley) | ||||
| 	if amountSum.GreaterThan(s.Overall) { | ||||
| 		return false, errors.New("峰谷计量总量大于总计电量") | ||||
| 	} | ||||
| 	feeSum := decimal.Sum(s.CriticalFee, s.PeakFee, s.ValleyFee) | ||||
| 	if feeSum.GreaterThan(s.OverallFee) { | ||||
| 		return false, errors.New("峰谷计量费用大于总计费用") | ||||
| 	} | ||||
| 	return true, nil | ||||
| } | ||||
|  | ||||
| func (s *ReportSummary) CalculatePrices() { | ||||
| 	s.ConsumptionFee = decimal.NewNullDecimal(s.OverallFee.Sub(s.BasicFee).Sub(s.AdjustFee)) | ||||
| 	if s.Overall.GreaterThan(decimal.Zero) { | ||||
| 		s.OverallPrice = decimal.NewNullDecimal(s.ConsumptionFee.Decimal.Div(s.Overall).RoundBank(8)) | ||||
| 	} else { | ||||
| 		s.OverallPrice = decimal.NewNullDecimal(decimal.Zero) | ||||
| 	} | ||||
| 	if s.Critical.GreaterThan(decimal.Zero) { | ||||
| 		s.CriticalPrice = decimal.NewNullDecimal(s.CriticalFee.Div(s.Critical).RoundBank(8)) | ||||
| 	} else { | ||||
| 		s.CriticalPrice = decimal.NewNullDecimal(decimal.Zero) | ||||
| 	} | ||||
| 	if s.Peak.GreaterThan(decimal.Zero) { | ||||
| 		s.PeakPrice = decimal.NewNullDecimal(s.PeakFee.Div(s.Peak).RoundBank(8)) | ||||
| 	} else { | ||||
| 		s.PeakPrice = decimal.NewNullDecimal(decimal.Zero) | ||||
| 	} | ||||
| 	if s.Valley.GreaterThan(decimal.Zero) { | ||||
| 		s.ValleyPrice = decimal.NewNullDecimal(s.ValleyFee.Div(s.Valley).RoundBank(8)) | ||||
| 	} else { | ||||
| 		s.ValleyPrice = decimal.NewNullDecimal(decimal.Zero) | ||||
| 	} | ||||
| 	s.Flat = s.Overall.Sub(s.Critical).Sub(s.Peak).Sub(s.Valley) | ||||
| 	s.FlatFee = s.ConsumptionFee.Decimal.Sub(s.CriticalFee).Sub(s.PeakFee).Sub(s.ValleyFee) | ||||
| 	if s.Flat.GreaterThan(decimal.Zero) { | ||||
| 		s.FlatPrice = decimal.NewNullDecimal(s.FlatFee.Div(s.Flat).RoundBank(8)) | ||||
| 	} else { | ||||
| 		s.FlatPrice = decimal.NewNullDecimal(decimal.Zero) | ||||
| 	} | ||||
| } | ||||
| @@ -1,32 +0,0 @@ | ||||
| package model | ||||
|  | ||||
| import "time" | ||||
|  | ||||
| type Created struct { | ||||
| 	CreatedAt time.Time `bun:"type:timestamptz,notnull" json:"createdAt" time_format:"simple_datetime" time_location:"shanghai"` | ||||
| } | ||||
|  | ||||
| type CreatedWithUser struct { | ||||
| 	Created   `bun:"extend"` | ||||
| 	CreatedBy *string `json:"createdBy"` | ||||
| } | ||||
|  | ||||
| type Deleted struct { | ||||
| 	DeletedAt *time.Time `bun:"type:timestamptz,soft_delete,nullzero" json:"deletedAt" time_format:"simple_datetime" time_location:"shanghai"` | ||||
| } | ||||
|  | ||||
| type DeletedWithUser struct { | ||||
| 	Deleted   `bun:"extend"` | ||||
| 	DeletedBy *string `json:"deletedBy"` | ||||
| } | ||||
|  | ||||
| type CreatedAndModified struct { | ||||
| 	Created        `bun:"extend"` | ||||
| 	LastModifiedAt *time.Time `bun:"type:timestamptz,nullzero" json:"lastModifiedAt" time_format:"simple_datetime" time_location:"shanghai"` | ||||
| } | ||||
|  | ||||
| type CreatedAndModifiedWithUser struct { | ||||
| 	CreatedAndModified `bun:"extend"` | ||||
| 	CreatedBy          *string `json:"createdBy"` | ||||
| 	LastModifiedBy     *string `json:"lastModifiedBy"` | ||||
| } | ||||
| @@ -21,3 +21,13 @@ type Tenement struct { | ||||
| 	LastModifiedAt types.DateTime  `json:"lastModifiedAt" db:"last_modified_at"` | ||||
| 	DeletedAt      *types.DateTime `json:"deletedAt" db:"deleted_at"` | ||||
| } | ||||
|  | ||||
| type TenementMeter struct { | ||||
| 	ParkId          string         `db:"park_id"` | ||||
| 	TenementId      string         `db:"tenement_id"` | ||||
| 	MeterId         string         `db:"meter_id"` | ||||
| 	ForeignRelation bool           `db:"foreign_relation"` | ||||
| 	AssociatedAt    types.DateTime `db:"associated_at"` | ||||
| 	DisassociatedAt types.DateTime `db:"disassociated_at"` | ||||
| 	SynchronizedAt  types.DateTime `db:"synchronized_at"` | ||||
| } | ||||
|   | ||||
							
								
								
									
										118
									
								
								model/types.go
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								model/types.go
									
									
									
									
									
								
							| @@ -1,118 +0,0 @@ | ||||
| package model | ||||
|  | ||||
| import ( | ||||
| 	"database/sql" | ||||
| 	"database/sql/driver" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| type Date struct { | ||||
| 	time.Time | ||||
| } | ||||
|  | ||||
| func NewDate(t time.Time) Date { | ||||
| 	loc, err := time.LoadLocation("Asia/Shanghai") | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	t = t.In(loc) | ||||
| 	return Date{ | ||||
| 		Time: time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, loc), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func NewEmptyDate() Date { | ||||
| 	loc, err := time.LoadLocation("Asia/Shanghai") | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	return Date{ | ||||
| 		Time: time.Time{}.In(loc), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func ParseDate(t string) (Date, error) { | ||||
| 	loc, err := time.LoadLocation("Asia/Shanghai") | ||||
| 	if err != nil { | ||||
| 		return NewEmptyDate(), fmt.Errorf("unable to load time zone, %w", err) | ||||
| 	} | ||||
| 	d, err := time.ParseInLocation("2006-01-02", t, loc) | ||||
| 	if err != nil { | ||||
| 		return NewEmptyDate(), fmt.Errorf("unable to parse given time, %w", err) | ||||
| 	} | ||||
| 	return Date{ | ||||
| 		Time: d, | ||||
| 	}, nil | ||||
| } | ||||
|  | ||||
| func (d Date) IsEmpty() bool { | ||||
| 	return d.Time.IsZero() | ||||
| } | ||||
|  | ||||
| func (d Date) Format(fmt string) string { | ||||
| 	return d.Time.Format(fmt) | ||||
| } | ||||
|  | ||||
| func (d Date) ToString() string { | ||||
| 	return d.Time.Format("2006-01-02") | ||||
| } | ||||
|  | ||||
| var _ driver.Valuer = (*Date)(nil) | ||||
|  | ||||
| func (d Date) Value() (driver.Value, error) { | ||||
| 	loc, err := time.LoadLocation("Asia/Shanghai") | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	return d.In(loc).Format("2006-01-02"), nil | ||||
| } | ||||
|  | ||||
| var _ sql.Scanner = (*Date)(nil) | ||||
|  | ||||
| // Scan scans the time parsing it if necessary using timeFormat. | ||||
| func (d *Date) Scan(src interface{}) (err error) { | ||||
| 	loc, err := time.LoadLocation("Asia/Shanghai") | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	switch src := src.(type) { | ||||
| 	case time.Time: | ||||
| 		*d = NewDate(src) | ||||
| 		return nil | ||||
| 	case string: | ||||
| 		d.Time, err = time.ParseInLocation("2006-01-02", src, loc) | ||||
| 		return err | ||||
| 	case []byte: | ||||
| 		d.Time, err = time.ParseInLocation("2006-01-02", string(src), loc) | ||||
| 		return err | ||||
| 	case nil: | ||||
| 		d.Time = time.Time{} | ||||
| 		return nil | ||||
| 	default: | ||||
| 		return fmt.Errorf("unsupported data type: %T", src) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| var _ json.Marshaler = (*Date)(nil) | ||||
|  | ||||
| func (d Date) MarshalJSON() ([]byte, error) { | ||||
| 	return json.Marshal(d.Time.Format("2006-01-02")) | ||||
| } | ||||
|  | ||||
| var _ json.Unmarshaler = (*Date)(nil) | ||||
|  | ||||
| func (d *Date) UnmarshalJSON(raw []byte) error { | ||||
| 	loc, err := time.LoadLocation("Asia/Shanghai") | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("unable to load time zone, %w", err) | ||||
| 	} | ||||
| 	var s string | ||||
| 	err = json.Unmarshal(raw, &s) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("unable to unmarshal value, %w", err) | ||||
| 	} | ||||
| 	d.Time, err = time.ParseInLocation("2006-01-02", s, loc) | ||||
| 	return err | ||||
| } | ||||
| @@ -1,43 +0,0 @@ | ||||
| package model | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/shopspring/decimal" | ||||
| 	"github.com/uptrace/bun" | ||||
| ) | ||||
|  | ||||
| type UserCharge struct { | ||||
| 	bun.BaseModel `bun:"table:user_charge,alias:c"` | ||||
| 	Created       `bun:"extend"` | ||||
| 	Seq           int64               `bun:"type:bigint,pk,notnull,autoincrement" json:"seq"` | ||||
| 	UserId        string              `bun:",notnull" json:"userId"` | ||||
| 	Fee           decimal.NullDecimal `bun:"type:numeric" json:"fee"` | ||||
| 	Discount      decimal.NullDecimal `bun:"type:numeric" json:"discount"` | ||||
| 	Amount        decimal.NullDecimal `bun:"type:numeric" json:"amount"` | ||||
| 	ChargeTo      Date                `bun:"type:date,notnull" json:"chargeTo"` | ||||
| 	Settled       bool                `bun:",notnull" json:"settled"` | ||||
| 	SettledAt     *time.Time          `bun:"type:timestamptz" json:"settledAt" time_format:"simple_datetime" time_location:"shanghai"` | ||||
| 	Cancelled     bool                `bun:",notnull" json:"cancelled"` | ||||
| 	CancelledAt   *time.Time          `bun:"type:timestamptz" json:"cancelledAt" time_format:"simple_datetime" time_location:"shanghai"` | ||||
| 	Refunded      bool                `bun:",notnull" json:"refunded"` | ||||
| 	RefundedAt    *time.Time          `bun:"type:timestamptz" json:"refundedAt" time_format:"simple_datetime" time_location:"shanghai"` | ||||
| 	Detail        *UserDetail         `bun:"rel:belongs-to,join:user_id=id" json:"-"` | ||||
| } | ||||
|  | ||||
| type ChargeWithName struct { | ||||
| 	UserDetail `bun:"extend"` | ||||
| 	UserCharge `bun:"extend"` | ||||
| } | ||||
|  | ||||
| var _ bun.BeforeAppendModelHook = (*UserCharge)(nil) | ||||
|  | ||||
| func (uc *UserCharge) BeforeAppendModel(ctx context.Context, query bun.Query) error { | ||||
| 	oprTime := time.Now() | ||||
| 	switch query.(type) { | ||||
| 	case *bun.InsertQuery: | ||||
| 		uc.CreatedAt = oprTime | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| @@ -1,69 +0,0 @@ | ||||
| package model | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/jinzhu/copier" | ||||
| 	"github.com/shopspring/decimal" | ||||
| 	"github.com/uptrace/bun" | ||||
| ) | ||||
|  | ||||
| type UserDetail struct { | ||||
| 	bun.BaseModel              `bun:"table:user_detail,alias:d"` | ||||
| 	CreatedAndModifiedWithUser `bun:"extend"` | ||||
| 	DeletedWithUser            `bun:"extend"` | ||||
| 	Id                         string          `bun:",pk,notnull" json:"-"` | ||||
| 	Name                       *string         `json:"name"` | ||||
| 	Abbr                       *string         `json:"abbr"` | ||||
| 	Region                     *string         `json:"region"` | ||||
| 	Address                    *string         `json:"address"` | ||||
| 	Contact                    *string         `json:"contact"` | ||||
| 	Phone                      *string         `json:"phone"` | ||||
| 	UnitServiceFee             decimal.Decimal `bun:"type:numeric,notnull" json:"unitServiceFee"` | ||||
| 	ServiceExpiration          Date            `bun:"type:date,notnull" json:"serviceExpiration"` | ||||
| } | ||||
|  | ||||
| type JoinedUserDetail struct { | ||||
| 	UserDetail `bun:"extend"` | ||||
| 	Id         string `json:"id"` | ||||
| 	Username   string `json:"username"` | ||||
| 	Type       int8   `json:"type"` | ||||
| 	Enabled    bool   `json:"enabled"` | ||||
| } | ||||
|  | ||||
| type FullJoinedUserDetail struct { | ||||
| 	UserDetail `bun:"extend"` | ||||
| 	User       `bun:"extend"` | ||||
| } | ||||
|  | ||||
| type UserDetailSimplified struct { | ||||
| 	bun.BaseModel `bun:"table:user_detail,alias:d"` | ||||
| 	Id            string  `bun:",pk,notnull" json:"id"` | ||||
| 	Name          *string `json:"name"` | ||||
| 	Abbr          *string `json:"abbr"` | ||||
| 	Region        *string `json:"region"` | ||||
| 	Address       *string `json:"address"` | ||||
| 	Contact       *string `json:"contact"` | ||||
| 	Phone         *string `json:"phone"` | ||||
| } | ||||
|  | ||||
| func FromUserDetail(user UserDetail) UserDetailSimplified { | ||||
| 	dest := UserDetailSimplified{} | ||||
| 	copier.Copy(&dest, user) | ||||
| 	return dest | ||||
| } | ||||
|  | ||||
| var _ bun.BeforeAppendModelHook = (*UserDetail)(nil) | ||||
|  | ||||
| func (d *UserDetail) BeforeAppendModel(ctx context.Context, query bun.Query) error { | ||||
| 	oprTime := time.Now() | ||||
| 	switch query.(type) { | ||||
| 	case *bun.InsertQuery: | ||||
| 		d.CreatedAt = oprTime | ||||
| 		d.LastModifiedAt = &oprTime | ||||
| 	case *bun.UpdateQuery: | ||||
| 		d.LastModifiedAt = &oprTime | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| @@ -1,35 +0,0 @@ | ||||
| package model | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/shopspring/decimal" | ||||
| 	"github.com/uptrace/bun" | ||||
| ) | ||||
|  | ||||
| type WillDilutedFee struct { | ||||
| 	bun.BaseModel      `bun:"table:will_diluted_fee,alias:w"` | ||||
| 	CreatedAndModified `bun:"extend"` | ||||
| 	Id                 string          `bun:",pk,notnull" json:"diluteId"` | ||||
| 	ReportId           string          `bun:",notnull" json:"reportId"` | ||||
| 	SourceId           *string         `json:"sourceId"` | ||||
| 	Name               string          `bun:",notnull" json:"name"` | ||||
| 	Fee                decimal.Decimal `bun:"type:numeric,notnull" json:"fee"` | ||||
| 	Memo               *string         `bun:"type:text" json:"memo"` | ||||
| 	Origin             *MaintenanceFee `bun:"rel:belongs-to,join:source_id=id"` | ||||
| } | ||||
|  | ||||
| var _ bun.BeforeAppendModelHook = (*WillDilutedFee)(nil) | ||||
|  | ||||
| func (d *WillDilutedFee) BeforeAppendModel(ctx context.Context, query bun.Query) error { | ||||
| 	oprTime := time.Now() | ||||
| 	switch query.(type) { | ||||
| 	case *bun.InsertQuery: | ||||
| 		d.CreatedAt = oprTime | ||||
| 		d.LastModifiedAt = &oprTime | ||||
| 	case *bun.UpdateQuery: | ||||
| 		d.LastModifiedAt = &oprTime | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										84
									
								
								model/withdraw.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								model/withdraw.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| package model | ||||
|  | ||||
| import ( | ||||
| 	"electricity_bill_calc/types" | ||||
| 	"github.com/shopspring/decimal" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| type Withdraw struct { | ||||
| 	Park   SimplifiedPark   `json:"park"` | ||||
| 	Report SimplifiedReport `json:"report"` | ||||
| 	User   UserInfos        `json:"user"` // 简易用户详细信息 | ||||
| } | ||||
|  | ||||
| // 简易园区信息 | ||||
| type SimplifiedPark struct { | ||||
| 	Address       *string `json:"address"`       // 园区地址 | ||||
| 	Area          *string `json:"area"`          // 园区面积 | ||||
| 	Capacity      *string `json:"capacity"`      // 供电容量 | ||||
| 	Category      int16   `json:"category"`      // 用电分类,0:两部制,1:单一峰谷,2:单一单一 | ||||
| 	Contact       *string `json:"contact"`       // 园区联系人 | ||||
| 	ID            string  `json:"id"`            // 园区ID | ||||
| 	Meter04KvType int16   `json:"meter04kvType"` // 户表计量类型,0:非峰谷,1:峰谷 | ||||
| 	Name          string  `json:"name"`          // 园区名称 | ||||
| 	Phone         *string `json:"phone"`         // 园区联系人电话 | ||||
| 	Region        *string `json:"region"`        // 园区所在行政区划 | ||||
| 	Tenement      *string `json:"tenement"`      // 园区住户数量 | ||||
| 	UserID        string  `json:"userId"`        // 园区所属用户ID | ||||
| } | ||||
|  | ||||
| // 简易核算报表信息 | ||||
| type SimplifiedReport struct { | ||||
| 	ID                    string  `json:"id"`                    // 报表ID | ||||
| 	LastWithdrawAppliedAt *string `json:"lastWithdrawAppliedAt"` // 最后一次申请撤回的时间,格式为 yyyy-MM-dd HH:mm:ss | ||||
| 	LastWithdrawAuditAt   *string `json:"lastWithdrawAuditAt"`   // 最后一次申请审核的时间,格式为 yyyy-MM-dd HH:mm:ss | ||||
| 	Message               *string `json:"message"`               // 当前状态的错误提示 | ||||
| 	ParkID                string  `json:"parkId"`                // 所属园区ID | ||||
| 	PeriodBegin           string  `json:"periodBegin"`           // 核算起始日期,格式为 yyyy-MM-dd | ||||
| 	PeriodEnd             string  `json:"periodEnd"`             // 核算结束日期,格式为 yyyy-MM-dd | ||||
| 	Published             bool    `json:"published"`             // 是否已发布 | ||||
| 	PublishedAt           *string `json:"publishedAt"`           // 发布时间 | ||||
| 	Status                float64 `json:"status,omitempty"`      // 当前状态,0:计算任务已队列,1:计算任务已完成,2:计算数据不足 | ||||
| 	Withdraw              int16   `json:"withdraw"`              // 报表撤回状态,0:未撤回,1:申请撤回中,2:申请拒绝,3:申请批准 | ||||
| } | ||||
|  | ||||
| // 简易用户信息 | ||||
| type UserInfos struct { | ||||
| 	Address *string `json:"address"` // 用户地址 | ||||
| 	Contact *string `json:"contact"` // 用户联系人 | ||||
| 	ID      string  `json:"id"`      // 用户ID | ||||
| 	Name    *string `json:"name"`    // 用户名称 | ||||
| 	Phone   *string `json:"phone"`   // 用户联系人电话 | ||||
| 	Region  *string `json:"region"`  // 用户所在行政区划 | ||||
| } | ||||
|  | ||||
| //用于映射数据库的报表结构体 | ||||
| type ReportRes struct { | ||||
| 	ReportId              string              `db:"report_id"` | ||||
| 	LastWithdrawAppliedAt *time.Time          `db:"last_withdraw_applied_at"` | ||||
| 	LastWithdrawAuditAt   *time.Time          `db:"last_withdraw_audit_at"` | ||||
| 	ParkID                string              `db:"report_park_id"` | ||||
| 	Period                types.DateRange     `db:"period"` | ||||
| 	Published             bool                `db:"published"` | ||||
| 	PublishedAt           *time.Time          `db: "published_at"` | ||||
| 	Withdraw              int16               `db:"withdraw"` | ||||
| 	ParkAddress           *string             `db:"park_address"` | ||||
| 	Area                  decimal.NullDecimal `db:"area"` | ||||
| 	Capacity              decimal.NullDecimal `db:"capacity"` | ||||
| 	Category              int16 | ||||
| 	ParkContact           *string             `db:"park_contact"` | ||||
| 	ParkId                string              `db:"park_id"` | ||||
| 	Meter04KVType         int16               `db:"meter_04kv_type"` | ||||
| 	ParkName              string              `db:"park_name"` | ||||
| 	ParkPhone             *string             `db:"park_phone"` | ||||
| 	ParkRegion            string              `db:"park_region"` | ||||
| 	TenementQuantity      decimal.NullDecimal `db:"tenement_quantity"` | ||||
| 	UserID                string              `db:"user_id"` | ||||
| 	Address               *string | ||||
| 	Contact               string  `db:"user_detail_contact"` | ||||
| 	ID                    string  `db:"ud_id"` | ||||
| 	Name                  *string `db:"user_detail_name"` | ||||
| 	Phone                 string  `db:"user_detail_phone"` | ||||
| 	Region                *string `db:"user_detail_region"` | ||||
| } | ||||
		Reference in New Issue
	
	Block a user