package service import ( "context" "database/sql" "encoding/json" "fmt" "github.com/gogf/gf/frame/g" "strconv" "strings" dao "dashoo.cn/micro/app/dao/contract" customerDao "dashoo.cn/micro/app/dao/cust" model "dashoo.cn/micro/app/model/contract" workflowModel "dashoo.cn/micro/app/model/workflow" workflowService "dashoo.cn/micro/app/service/workflow" "dashoo.cn/opms_libary/utils" "dashoo.cn/opms_libary/micro_srv" "dashoo.cn/opms_libary/myerrors" "dashoo.cn/opms_libary/plugin/dingtalk/message" "dashoo.cn/opms_libary/plugin/dingtalk/workflow" "dashoo.cn/opms_libary/request" "github.com/gogf/gf/database/gdb" "github.com/gogf/gf/os/gtime" "github.com/gogf/gf/util/gvalid" ) type CtrContractInvoiceService struct { Dao *dao.CtrContractInvoiceDao ContractDao *dao.CtrContractDao CustomerDao *customerDao.CustCustomerDao ctrSrv *CtrContractService Tenant string userInfo request.UserInfo DataScope g.Map `json:"dataScope"` } func NewCtrContractInvoiceService(ctx context.Context) (*CtrContractInvoiceService, error) { tenant, err := micro_srv.GetTenant(ctx) if err != nil { return nil, myerrors.TipsError(fmt.Sprintf("获取租户码异常:%s", err.Error())) //fmt.Errorf("获取租户码异常:%s", err.Error()) } // 获取用户信息 userInfo, err := micro_srv.GetUserInfo(ctx) if err != nil { return nil, myerrors.TipsError(fmt.Sprintf("获取用户信息异常:%s", err.Error())) //fmt.Errorf("获取用户信息异常:%s", err.Error()) } ctrSrv, err := NewCtrContractService(ctx) if err != nil { return nil, err } return &CtrContractInvoiceService{ Dao: dao.NewCtrContractInvoiceDao(tenant), ContractDao: dao.NewCtrContractDao(tenant), CustomerDao: customerDao.NewCustCustomerDao(tenant), ctrSrv: ctrSrv, Tenant: tenant, userInfo: userInfo, DataScope: userInfo.DataScope, }, nil } func (s CtrContractInvoiceService) List(ctx context.Context, req *model.CtrContractInvoiceListReq) (int, []*model.CtrContractInvoice, error) { ctx = context.WithValue(ctx, "contextService", s) dao := s.Dao.As("invoice").LeftJoin(dao.CtrContract.Table, "contract", "contract.id=invoice.contract_id"). DataScope(ctx, "incharge_id", "contract") if req.SearchText != "" { likestr := fmt.Sprintf("%%%s%%", req.SearchText) dao = dao.Where("(invoice.cust_name LIKE ? || invoice.contract_code LIKE ?)", likestr, likestr) } if req.CustId != 0 { dao = dao.Where("invoice.cust_id = ?", req.CustId) } if req.CustName != "" { likestr := fmt.Sprintf("%%%s%%", req.CustName) dao = dao.Where("invoice.cust_name like ?", likestr) } if req.ContractId != 0 { dao = dao.Where("invoice.contract_id = ?", req.ContractId) } if req.ContractCode != "" { likestr := fmt.Sprintf("%%%s%%", req.ContractCode) dao = dao.Where("invoice.contract_code like ?", likestr) } if req.InvoiceType != "" { dao = dao.Where("invoice.invoice_type = ?", req.InvoiceType) } if req.ApproStatus != "" { dao = dao.Where("invoice.appro_status = ?", req.ApproStatus) } if req.InvoiceCode != "" { dao = dao.Where("invoice.invoice_code = ?", req.InvoiceCode) } if req.CourierCode != "" { dao = dao.Where("invoice.courier_code = ?", req.CourierCode) } if req.BeginTime != "" { dao = dao.Where("invoice.created_time > ?", req.BeginTime) } if req.EndTime != "" { dao = dao.Where("invoice.created_time < ?", req.EndTime) } total, err := dao.Count() if err != nil { return 0, nil, err } if req.PageNum != 0 { dao = dao.Page(req.GetPage()) } orderby := "invoice.created_time desc" if req.OrderBy != "" { orderby = req.OrderBy } dao = dao.Order(orderby) ents := []*model.CtrContractInvoice{} err = dao.Fields("invoice.*").Structs(&ents) if err != nil && err != sql.ErrNoRows { return 0, nil, err } return total, ents, err } func (s CtrContractInvoiceService) Add(ctx context.Context, req *model.CtrContractInvoiceAddReq) (int, error) { validErr := gvalid.CheckStruct(ctx, req, nil) if validErr != nil { return 0, myerrors.TipsError(validErr.Current().Error()) } c, err := s.ContractDao.Where("id = ?", req.ContractId).One() if err != nil { return 0, err } if c == nil { return 0, myerrors.TipsError(fmt.Sprintf("合同:%d 不存在", req.ContractId)) } if req.InvoiceCode != "" { ent, err := s.Dao.Where("invoice_code = ?", req.InvoiceCode).One() if err != nil { return 0, err } if ent != nil { return 0, myerrors.TipsError(fmt.Sprintf("发票号码:%s 已存在", req.InvoiceCode)) } } if req.CourierCode != "" { ent, err := s.Dao.Where("courier_code = ?", req.CourierCode).One() if err != nil { return 0, err } if ent != nil { return 0, myerrors.TipsError(fmt.Sprintf("快递单号:%s 已存在", req.CourierCode)) } } ent := model.CtrContractInvoice{ CustId: c.CustId, CustName: c.CustName, ContractId: req.ContractId, ContractCode: c.ContractCode, ContractAmount: c.ContractAmount, InvoiceAmount: req.InvoiceAmount, InvoiceDate: req.InvoiceDate, InvoiceType: req.InvoiceType, ApproStatus: "10", InvoiceCode: req.InvoiceCode, ActualInvoiceDate: req.ActualInvoiceDate, CourierCode: req.CourierCode, Remark: req.Remark, CreatedBy: int(s.userInfo.Id), CreatedName: s.userInfo.NickName, CreatedTime: gtime.Now(), UpdatedBy: int(s.userInfo.Id), UpdatedName: s.userInfo.NickName, UpdatedTime: gtime.Now(), } var id int txerr := s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error { invoiceId, err := tx.InsertAndGetId("ctr_contract_invoice", ent) if err != nil { return err } err = s.ctrSrv.AddDynamicsByCurrentUser(tx, req.ContractId, "创建发票", map[string]interface{}{ "id": invoiceId, "invoiceAmount": req.InvoiceAmount, "invoiceDate": req.InvoiceDate, "invoiceType": req.InvoiceType, "invoiceCode": req.InvoiceCode, "actualInvoiceDate": req.ActualInvoiceDate, "courierCode": req.CourierCode, }) if err != nil { return err } id = int(invoiceId) return nil }) return id, txerr } func (s CtrContractInvoiceService) Update(ctx context.Context, req *model.CtrContractInvoiceUpdateReq) error { validErr := gvalid.CheckStruct(ctx, req, nil) if validErr != nil { return myerrors.TipsError(validErr.Current().Error()) } ent, err := s.Dao.Where("id = ?", req.Id).One() if err != nil { return err } if ent == nil { return myerrors.TipsError(fmt.Sprintf("发票不存在: %d", req.Id)) } if req.InvoiceCode != "" { exist, err := s.Dao.Where("invoice_code = ?", req.InvoiceCode).One() if err != nil { return err } if exist != nil && exist.Id != req.Id { return myerrors.TipsError(fmt.Sprintf("发票号码: %s 已存在", req.InvoiceCode)) } } if req.CourierCode != "" { exist, err := s.Dao.Where("courier_code = ?", req.CourierCode).One() if err != nil { return err } if exist != nil && exist.Id != req.Id { return myerrors.TipsError(fmt.Sprintf("快递单号: %s 已存在", req.CourierCode)) } } toupdate := map[string]interface{}{} // if req.CustId != 0 { // toupdate["cust_id"] = req.CustId // } // if req.CustName != 0 { // toupdate["cust_name"] = req.CustName // } // if req.ContractId != 0 { // toupdate["contract_id"] = req.ContractId // } // if req.ContractCode != 0 { // toupdate["contract_code"] = req.ContractCode // } // if req.ContractAmount != 0 { // toupdate["contract_amount"] = req.ContractAmount // } if req.InvoiceAmount != nil { toupdate["invoice_amount"] = *req.InvoiceAmount } if req.InvoiceDate != nil { toupdate["invoice_date"] = req.InvoiceDate } if req.InvoiceType != "" { toupdate["invoice_type"] = req.InvoiceType } if req.ApproStatus != "" { toupdate["appro_status"] = req.ApproStatus } if req.InvoiceCode != "" { toupdate["invoice_code"] = req.InvoiceCode } if req.ActualInvoiceDate != nil { toupdate["actual_invoice_date"] = req.ActualInvoiceDate } if req.CourierCode != "" { toupdate["courier_code"] = req.CourierCode } if req.Remark != nil { toupdate["remark"] = *req.Remark } if len(toupdate) != 0 { toupdate["updated_by"] = int(s.userInfo.Id) toupdate["updated_name"] = s.userInfo.NickName toupdate["updated_time"] = gtime.Now() txerr := s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error { _, err = tx.Update("ctr_contract_invoice", toupdate, "id= ?", req.Id) if err != nil { return err } if req.InvoiceAmount != nil || req.ApproStatus != "" { err = s.ctrSrv.UpdateInvoiceAmount(tx, ent.ContractId) if err != nil { return err } } return nil }) if txerr != nil { return txerr } } return nil } var InvoiceApplyProcessCode = "PROC-D2F97FDE-6277-404D-89B5-91123FEBF1B8" // 申请发票 func (s CtrContractInvoiceService) InvoiceApply(ctx context.Context, req *model.CtrContractInvoiceInvoiceApplyReq) error { invoice, err := s.Dao.Where("id = ?", req.Id).One() if err != nil { return err } if invoice == nil { return myerrors.TipsError("发票不存在") } if invoice.ApproStatus != "10" { return myerrors.TipsError("发票当前状态不可提交审核") } contract, err := s.ContractDao.Where("id = ?", invoice.ContractId).One() if err != nil { return err } if contract == nil { return myerrors.TipsError("发票所属合同不存在") } cust, err := s.CustomerDao.Where("id = ?", invoice.CustId).One() if err != nil { return err } if cust == nil { return myerrors.TipsError("发票所属合同客户不存在") } allReceive := "未回全款" if req.AllReceive { allReceive = "已回全款" } product, err := s.ctrSrv.CtrProductDao.Where("contract_id = ?", contract.Id).All() if err != nil { return err } // productForm := []*workflow.StartProcessInstanceRequestFormComponentValuesDetails{} // for _, p := range product { // productForm = append(productForm, &workflow.StartProcessInstanceRequestFormComponentValuesDetails{ // Details: []*workflow.StartProcessInstanceRequestFormComponentValuesDetailsDetails{ // { // Id: utils.String("TextField_R967EJ9XVWW0"), // Name: utils.String("产品名称"), // Value: utils.String(p.ProdName), // }, // { // Id: utils.String("TextField_18AAHJYNVUBG0"), // Name: utils.String("产品型号"), // Value: utils.String(p.ProdCode), // }, // { // Id: utils.String("NumberField_1RFPF86Y699C0"), // Name: utils.String("产品数量"), // Value: utils.String(strconv.Itoa(p.ProdNum)), // }, // }, // }) // } productForm := []interface{}{} for _, p := range product { productForm = append(productForm, []*workflow.StartProcessInstanceRequestFormComponentValuesDetailsDetails{ { Id: utils.String("TextField_R967EJ9XVWW0"), Name: utils.String("产品名称"), Value: utils.String(p.ProdName), }, { Id: utils.String("TextField_18AAHJYNVUBG0"), Name: utils.String("产品型号"), Value: utils.String(p.ProdCode), }, { Id: utils.String("NumberField_1RFPF86Y699C0"), Name: utils.String("产品数量"), Value: utils.String(strconv.Itoa(p.ProdNum)), }, }) } productFormByte, err := json.Marshal(productForm) if err != nil { return err } workflowSrv, err := workflowService.NewFlowService(ctx) if err != nil { return err } bizCode := strings.Join([]string{ strconv.Itoa(invoice.Id), strconv.Itoa(s.userInfo.Id), }, ":") _, err = workflowSrv.StartProcessInstance(bizCode, "31", "", &workflow.StartProcessInstanceRequest{ ProcessCode: &InvoiceApplyProcessCode, FormComponentValues: []*workflow.StartProcessInstanceRequestFormComponentValues{ { Id: utils.String("DDSelectField_FSWX8IG61HC0"), Name: utils.String("单选框"), Value: utils.String(allReceive), }, { Id: utils.String("TextField_LUZ9EQ3IJB40"), Name: utils.String("合同编号"), Value: utils.String(contract.ContractCode), }, { Id: utils.String("TextField_A0V5RQK1BC80"), Name: utils.String("客户编号"), Value: utils.String(cust.CustCode), }, { Id: utils.String("TextField_1E2J1LS6H9HC0"), Name: utils.String("客户名称"), Value: utils.String(cust.CustName), }, { Id: utils.String("TableField_1IGTG9NX08U80"), Name: utils.String("表格"), // Details: productForm, Value: utils.String(string(productFormByte)), }, { Id: utils.String("MoneyField_1D8481FCI5FK0"), Name: utils.String("合同金额(元)"), Value: utils.String(strconv.FormatFloat(contract.ContractAmount, 'f', 2, 64)), }, { Id: utils.String("MoneyField_BQ2E2JGXHGO0"), Name: utils.String("回款金额(元)"), Value: utils.String(strconv.FormatFloat(req.ReceiveAmount, 'f', 2, 64)), }, { Id: utils.String("MoneyField_V47BSZICHIO0"), Name: utils.String("开票金额(元)"), Value: utils.String(strconv.FormatFloat(invoice.InvoiceAmount, 'f', 2, 64)), }, }, }) if err != nil { return err } _, err = s.Dao.Where("id = ?", invoice.Id).Data(map[string]interface{}{ "appro_status": 20, }).Update() return err } func InvoiceApplyApproval(ctx context.Context, flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error { tenant, err := micro_srv.GetTenant(ctx) if err != nil { return fmt.Errorf("获取租户码异常:%s", err.Error()) } invoiceDao := dao.NewCtrContractInvoiceDao(tenant) bizCode := strings.Split(flow.BizCode, ":") if len(bizCode) != 2 { return fmt.Errorf("申请发票审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id) } invoiceId, err := strconv.Atoi(bizCode[0]) if err != nil { return fmt.Errorf("申请发票审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id) } invoice, err := invoiceDao.Where("id = ?", invoiceId).One() if err != nil { return err } if invoice == nil { return fmt.Errorf("发票不存在:%s Id: %d", flow.BizCode, flow.Id) } if msg.ProcessType != "finish" && msg.ProcessType != "terminate" { return fmt.Errorf("无法识别的 ProcessType :%s", msg.ProcessType) } if msg.Result != "agree" && msg.Result != "refuse" && msg.Result != "" { return fmt.Errorf("无法识别的 Result :%s", msg.Result) } if msg.ProcessType == "terminate" { _, err = invoiceDao.Where("id = ?", invoiceId).Data(map[string]interface{}{ "appro_status": "50", }).Update() return err } pass := msg.Result == "agree" if !pass { _, err = invoiceDao.Where("id = ?", invoiceId).Data(map[string]interface{}{ "appro_status": "40", }).Update() return err } _, err = invoiceDao.Where("id = ?", invoiceId).Data(map[string]interface{}{ "appro_status": "30", }).Update() return err } func (s CtrContractInvoiceService) Delete(ctx context.Context, id []int) error { if len(id) == 0 { return nil } return s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error { contractId := map[int]bool{} for _, i := range id { ent := model.CtrContractInvoice{} err := tx.GetStruct(&ent, "select * from ctr_contract_invoice where id = ?", i) if err == sql.ErrNoRows { continue } if err != nil { return err } if ent.ApproStatus == "30" { contractId[ent.ContractId] = true } } _, err := tx.Delete("ctr_contract_invoice", "id in (?)", id) if err != nil { return err } for cid := range contractId { err = s.ctrSrv.UpdateInvoiceAmount(tx, cid) if err != nil { return err } } return nil }) }