forked from free-lancers/electricity_bill_calc_service
		
	feat(invoice):基本完成商户发票记录功能,待测。
This commit is contained in:
		
							
								
								
									
										227
									
								
								controller/invoice.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										227
									
								
								controller/invoice.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,227 @@ | |||||||
|  | package controller | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"electricity_bill_calc/logger" | ||||||
|  | 	"electricity_bill_calc/model" | ||||||
|  | 	"electricity_bill_calc/repository" | ||||||
|  | 	"electricity_bill_calc/response" | ||||||
|  | 	"electricity_bill_calc/security" | ||||||
|  | 	"electricity_bill_calc/service" | ||||||
|  | 	"electricity_bill_calc/tools" | ||||||
|  | 	"electricity_bill_calc/types" | ||||||
|  | 	"electricity_bill_calc/vo" | ||||||
|  |  | ||||||
|  | 	"github.com/gofiber/fiber/v2" | ||||||
|  | 	"github.com/jinzhu/copier" | ||||||
|  | 	"go.uber.org/zap" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var invoiceLog = logger.Named("Controller", "Invoice") | ||||||
|  |  | ||||||
|  | func InitializeInvoiceHandler(router *fiber.App) { | ||||||
|  | 	router.Get("/invoice", security.MustAuthenticated, listInvoices) | ||||||
|  | 	router.Post("/invoice", security.EnterpriseAuthorize, createNewInvoiceRecord) | ||||||
|  | 	router.Post("/invoice/precalculate", security.EnterpriseAuthorize, testCalculateInvoice) | ||||||
|  | 	router.Get("/invoice/:code", security.EnterpriseAuthorize, getInvoiceDetail) | ||||||
|  | 	router.Delete("/invoice/:code", security.EnterpriseAuthorize, deleteInvoiceRecord) | ||||||
|  | 	router.Get("/uninvoiced/tenemennt/:tid/report", security.EnterpriseAuthorize, getUninvoicedTenementReports) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 列出指定园区中的符合条件的发票记录 | ||||||
|  | func listInvoices(c *fiber.Ctx) error { | ||||||
|  | 	invoiceLog.Info("列出指定园区中的符合条件的发票记录") | ||||||
|  | 	result := response.NewResult(c) | ||||||
|  | 	session, err := _retreiveSession(c) | ||||||
|  | 	if err != nil { | ||||||
|  | 		invoiceLog.Error("列出指定园区中的符合条件的发票记录失败,不能获取到有效的用户会话。", zap.Error(err)) | ||||||
|  | 		return result.Unauthorized("未能获取到有效的用户会话。") | ||||||
|  | 	} | ||||||
|  | 	park := tools.EmptyToNil(c.Query("park")) | ||||||
|  | 	if session.Type == model.USER_TYPE_ENT && park != nil && len(*park) > 0 { | ||||||
|  | 		pass, err := checkParkBelongs(*park, invoiceLog, c, &result) | ||||||
|  | 		if err != nil || !pass { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	startDate, err := types.ParseDatep(c.Query("start_date")) | ||||||
|  | 	if err != nil { | ||||||
|  | 		invoiceLog.Error("列出指定园区中的符合条件的发票记录失败,开始日期参数解析错误。", zap.Error(err)) | ||||||
|  | 		return result.BadRequest("开始日期参数解析错误。") | ||||||
|  | 	} | ||||||
|  | 	endDate, err := types.ParseDatep(c.Query("end_date")) | ||||||
|  | 	if err != nil { | ||||||
|  | 		invoiceLog.Error("列出指定园区中的符合条件的发票记录失败,结束日期参数解析错误。", zap.Error(err)) | ||||||
|  | 		return result.BadRequest("结束日期参数解析错误。") | ||||||
|  | 	} | ||||||
|  | 	keyword := tools.EmptyToNil(c.Query("keyword")) | ||||||
|  | 	page := c.QueryInt("page", 1) | ||||||
|  | 	invoices, total, err := repository.InvoiceRepository.ListInvoice(park, startDate, endDate, keyword, uint(page)) | ||||||
|  | 	if err != nil { | ||||||
|  | 		invoiceLog.Error("列出指定园区中的符合条件的发票记录失败,检索符合条件的发票记录出现错误。", zap.Error(err)) | ||||||
|  | 		return result.Error(fiber.StatusInternalServerError, "检索符合条件的发票记录出现错误。") | ||||||
|  | 	} | ||||||
|  | 	var invoiceResponse []*vo.InvoiceResponse | ||||||
|  | 	copier.Copy(&invoiceResponse, &invoices) | ||||||
|  | 	return result.Success( | ||||||
|  | 		"已经获取到符合条件的发票列表。", | ||||||
|  | 		response.NewPagedResponse(page, total).ToMap(), | ||||||
|  | 		fiber.Map{ | ||||||
|  | 			"invoices": invoiceResponse, | ||||||
|  | 		}, | ||||||
|  | 	) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 获取指定发票的详细信息 | ||||||
|  | func getInvoiceDetail(c *fiber.Ctx) error { | ||||||
|  | 	result := response.NewResult(c) | ||||||
|  | 	invoiceNo := tools.EmptyToNil(c.Params("code")) | ||||||
|  | 	invoiceLog.Info("获取指定发票的详细信息", zap.Stringp("InvoiceNo", invoiceNo)) | ||||||
|  | 	if invoiceNo == nil { | ||||||
|  | 		invoiceLog.Error("获取指定发票的详细信息失败,未指定发票编号。") | ||||||
|  | 		return result.BadRequest("未指定发票编号。") | ||||||
|  | 	} | ||||||
|  | 	session, err := _retreiveSession(c) | ||||||
|  | 	if err != nil { | ||||||
|  | 		invoiceLog.Error("获取指定发票的详细信息失败,不能获取到有效的用户会话。", zap.Error(err)) | ||||||
|  | 		return result.Unauthorized("未能获取到有效的用户会话。") | ||||||
|  | 	} | ||||||
|  | 	pass, err := repository.InvoiceRepository.IsBelongsTo(*invoiceNo, session.Uid) | ||||||
|  | 	if err != nil { | ||||||
|  | 		invoiceLog.Error("获取指定发票的详细信息失败,检查发票所属权时出现错误。", zap.Error(err)) | ||||||
|  | 		return result.Error(fiber.StatusInternalServerError, "检查发票所属权时出现错误。") | ||||||
|  | 	} | ||||||
|  | 	if !pass { | ||||||
|  | 		invoiceLog.Error("获取指定发票的详细信息失败,发票不属于当前用户。") | ||||||
|  | 		return result.Forbidden("不能访问不属于自己的发票。") | ||||||
|  | 	} | ||||||
|  | 	invoice, err := repository.InvoiceRepository.GetInvoiceDetail(*invoiceNo) | ||||||
|  | 	if err != nil { | ||||||
|  | 		invoiceLog.Error("获取指定发票的详细信息失败,检索发票信息时出现错误。", zap.Error(err)) | ||||||
|  | 		return result.Error(fiber.StatusInternalServerError, "检索发票信息时出现错误。") | ||||||
|  | 	} | ||||||
|  | 	if invoice == nil { | ||||||
|  | 		invoiceLog.Error("获取指定发票的详细信息失败,指定发票不存在。") | ||||||
|  | 		return result.NotFound("指定发票不存在。") | ||||||
|  | 	} | ||||||
|  | 	var invoiceResponse vo.ExtendedInvoiceResponse | ||||||
|  | 	copier.Copy(&invoiceResponse, &invoice) | ||||||
|  | 	return result.Success( | ||||||
|  | 		"已经获取到指定发票的详细信息。", | ||||||
|  | 		fiber.Map{ | ||||||
|  | 			"invoice": invoiceResponse, | ||||||
|  | 		}, | ||||||
|  | 	) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 获取指定商户下所有尚未开票的核算项目 | ||||||
|  | func getUninvoicedTenementReports(c *fiber.Ctx) error { | ||||||
|  | 	result := response.NewResult(c) | ||||||
|  | 	tenement := tools.EmptyToNil(c.Params("tid")) | ||||||
|  | 	invoiceLog.Info("获取指定商户下所有尚未开票的核算项目", zap.Stringp("Tenement", tenement)) | ||||||
|  | 	if tenement == nil { | ||||||
|  | 		invoiceLog.Error("获取指定商户下所有尚未开票的核算项目失败,未指定商户。") | ||||||
|  | 		return result.BadRequest("未指定商户。") | ||||||
|  | 	} | ||||||
|  | 	session, err := _retreiveSession(c) | ||||||
|  | 	if err != nil { | ||||||
|  | 		invoiceLog.Error("获取指定商户下所有尚未开票的核算项目失败,不能获取到有效的用户会话。", zap.Error(err)) | ||||||
|  | 		return result.Unauthorized("未能获取到有效的用户会话。") | ||||||
|  | 	} | ||||||
|  | 	pass, err := repository.TenementRepository.IsTenementBelongs(*tenement, session.Uid) | ||||||
|  | 	if err != nil { | ||||||
|  | 		invoiceLog.Error("获取指定商户下所有尚未开票的核算项目失败,检查商户所属权时出现错误。", zap.Error(err)) | ||||||
|  | 		return result.Error(fiber.StatusInternalServerError, "检查商户所属权时出现错误。") | ||||||
|  | 	} | ||||||
|  | 	if !pass { | ||||||
|  | 		invoiceLog.Error("获取指定商户下所有尚未开票的核算项目失败,商户不属于当前用户。") | ||||||
|  | 		return result.Forbidden("不能访问不属于自己的商户。") | ||||||
|  | 	} | ||||||
|  | 	reports, err := repository.InvoiceRepository.ListUninvoicedTenementCharges(*tenement) | ||||||
|  | 	if err != nil { | ||||||
|  | 		invoiceLog.Error("获取指定商户下所有尚未开票的核算项目失败,检索核算项目时出现错误。", zap.Error(err)) | ||||||
|  | 		return result.Error(fiber.StatusInternalServerError, "检索核算项目时出现错误。") | ||||||
|  | 	} | ||||||
|  | 	return result.Success( | ||||||
|  | 		"已经获取到指定商户下所有尚未开票的核算项目。", | ||||||
|  | 		fiber.Map{ | ||||||
|  | 			"records": reports, | ||||||
|  | 		}, | ||||||
|  | 	) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 试计算指定发票的票面信息 | ||||||
|  | func testCalculateInvoice(c *fiber.Ctx) error { | ||||||
|  | 	result := response.NewResult(c) | ||||||
|  | 	var form vo.InvoiceCreationForm | ||||||
|  | 	if err := c.BodyParser(&form); err != nil { | ||||||
|  | 		invoiceLog.Error("试计算指定发票的票面信息失败,请求表单数据解析错误。", zap.Error(err)) | ||||||
|  | 		return result.BadRequest("请求表单数据解析错误。") | ||||||
|  | 	} | ||||||
|  | 	invoiceLog.Info("试计算指定发票的票面信息", zap.String("Park", form.Park), zap.String("Tenement", form.Tenement)) | ||||||
|  | 	if pass, err := checkParkBelongs(form.Park, invoiceLog, c, &result); err != nil || !pass { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	total, cargos, err := service.InvoiceService.TestCalculateInvoice(form.Park, form.Tenement, form.TaxMethod, form.TaxRate, form.Covers) | ||||||
|  | 	if err != nil { | ||||||
|  | 		invoiceLog.Error("试计算指定发票的票面信息失败,试计算发票时出现错误。", zap.Error(err)) | ||||||
|  | 		return result.Error(fiber.StatusInternalServerError, "试计算发票时出现错误。") | ||||||
|  | 	} | ||||||
|  | 	return result.Success( | ||||||
|  | 		"已经计算出指定发票的票面信息。", | ||||||
|  | 		fiber.Map{ | ||||||
|  | 			"total":  total, | ||||||
|  | 			"cargos": cargos, | ||||||
|  | 		}, | ||||||
|  | 	) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 创建一个新的发票记录 | ||||||
|  | func createNewInvoiceRecord(c *fiber.Ctx) error { | ||||||
|  | 	result := response.NewResult(c) | ||||||
|  | 	var form vo.ExtendedInvoiceCreationForm | ||||||
|  | 	if err := c.BodyParser(&form); err != nil { | ||||||
|  | 		invoiceLog.Error("创建一个新的发票记录失败,请求表单数据解析错误。", zap.Error(err)) | ||||||
|  | 		return result.BadRequest("请求表单数据解析错误。") | ||||||
|  | 	} | ||||||
|  | 	invoiceLog.Info("创建一个新的发票记录", zap.String("Park", form.Park), zap.String("Tenement", form.Tenement)) | ||||||
|  | 	if pass, err := checkParkBelongs(form.Park, invoiceLog, c, &result); err != nil || !pass { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	err := service.InvoiceService.SaveInvoice(form.Park, form.Tenement, form.InvoiceNo, form.InvoiceType, form.TaxMethod, form.TaxRate, form.Covers) | ||||||
|  | 	if err != nil { | ||||||
|  | 		invoiceLog.Error("创建一个新的发票记录失败,保存发票时出现错误。", zap.Error(err)) | ||||||
|  | 		return result.Error(fiber.StatusInternalServerError, "保存发票时出现错误。") | ||||||
|  | 	} | ||||||
|  | 	return result.Created("已经创建了一个新的发票记录。") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 删除指定的发票记录 | ||||||
|  | func deleteInvoiceRecord(c *fiber.Ctx) error { | ||||||
|  | 	result := response.NewResult(c) | ||||||
|  | 	invoiceNo := tools.EmptyToNil(c.Params("code")) | ||||||
|  | 	invoiceLog.Info("删除指定的发票记录", zap.Stringp("InvoiceNo", invoiceNo)) | ||||||
|  | 	if invoiceNo == nil { | ||||||
|  | 		invoiceLog.Error("删除指定的发票记录失败,未指定发票编号。") | ||||||
|  | 		return result.BadRequest("未指定发票编号。") | ||||||
|  | 	} | ||||||
|  | 	session, err := _retreiveSession(c) | ||||||
|  | 	if err != nil { | ||||||
|  | 		invoiceLog.Error("删除指定的发票记录失败,不能获取到有效的用户会话。", zap.Error(err)) | ||||||
|  | 		return result.Unauthorized("未能获取到有效的用户会话。") | ||||||
|  | 	} | ||||||
|  | 	pass, err := repository.InvoiceRepository.IsBelongsTo(*invoiceNo, session.Uid) | ||||||
|  | 	if err != nil { | ||||||
|  | 		invoiceLog.Error("删除指定的发票记录失败,检查发票所属权时出现错误。", zap.Error(err)) | ||||||
|  | 		return result.Error(fiber.StatusInternalServerError, "检查发票所属权时出现错误。") | ||||||
|  | 	} | ||||||
|  | 	if !pass { | ||||||
|  | 		invoiceLog.Error("删除指定的发票记录失败,发票不属于当前用户。") | ||||||
|  | 		return result.Forbidden("不能删除不属于自己的发票。") | ||||||
|  | 	} | ||||||
|  | 	err = service.InvoiceService.DeleteInvoice(*invoiceNo) | ||||||
|  | 	if err != nil { | ||||||
|  | 		invoiceLog.Error("删除指定的发票记录失败,删除发票时出现错误。", zap.Error(err)) | ||||||
|  | 		return result.Error(fiber.StatusInternalServerError, "删除发票时出现错误。") | ||||||
|  | 	} | ||||||
|  | 	return result.Success("已经删除了指定的发票记录。") | ||||||
|  | } | ||||||
| @@ -49,6 +49,7 @@ func App() *fiber.App { | |||||||
| 	controller.InitializeChargeHandlers(app) | 	controller.InitializeChargeHandlers(app) | ||||||
| 	controller.InitializeParkHandlers(app) | 	controller.InitializeParkHandlers(app) | ||||||
| 	controller.InitializeMeterHandlers(app) | 	controller.InitializeMeterHandlers(app) | ||||||
|  | 	controller.InitializeInvoiceHandler(app) | ||||||
|  |  | ||||||
| 	return app | 	return app | ||||||
| } | } | ||||||
|   | |||||||
| @@ -25,3 +25,15 @@ type InvoiceCreationForm struct { | |||||||
| 	TaxRate   decimal.NullDecimal `json:"taxRate"` | 	TaxRate   decimal.NullDecimal `json:"taxRate"` | ||||||
| 	Covers    []string            `json:"covers"` | 	Covers    []string            `json:"covers"` | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type ExtendedInvoiceResponse struct { | ||||||
|  | 	InvoiceResponse | ||||||
|  | 	Cargos []*model.InvoiceCargo             `json:"cargos"` | ||||||
|  | 	Covers []*model.SimplifiedTenementCharge `json:"covers"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type ExtendedInvoiceCreationForm struct { | ||||||
|  | 	InvoiceCreationForm | ||||||
|  | 	InvoiceType *string `json:"invoiceType"` | ||||||
|  | 	InvoiceNo   string  `json:"invoiceNo"` | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user