package service import ( "bytes" "context" "encoding/json" "errors" "fmt" "os" "regexp" "time" cml04eventer "git.espin.casa/albert/cml04-eventer" "git.espin.casa/albert/cml04-mediciones-service/internal/storage" "git.espin.casa/albert/cml04-mediciones-service/internal/types" "golang.org/x/crypto/bcrypt" ) type IService interface { /* REST */ // from rest CreateTolerance(ctx context.Context, req types.CreateToleranceReq) (res types.CreateToleranceRes, err error) GetTolerance(ctx context.Context, req types.GetToleranciaReq) (res types.GetToleranciaRes, err error) // production orders from SAP GetProductionOrder(ctx context.Context, req types.GetProductionOrderReq) (res types.GetProductionOrderRes, err error) GetProductionOrders(ctx context.Context, req types.GetProductionOrdersReq) (res types.GetProductionOrdersRes, err error) // mediciones GetMedicion(ctx context.Context, req types.GetMedicionReq) (types.GetMedicionRes, error) GetMediciones(ctx context.Context, req types.GetMedicionesReq) (types.GetMedicionesRes, error) PostMediciones(ctx context.Context, req types.PostMedicionesReq) (types.PostMedicionesRes, error) // Ususarios GetUsuario(ctx context.Context, req types.GetUsuarioReq) (types.GetUsuarioRes, error) CreateUsuario(ctx context.Context, req types.CreateUsuarioReq) (types.CreateUsuarioRes, error) ValidarUsuario(ctx context.Context, req types.ValidarUsuarioReq) (types.ValidarUsuarioRes, error) /* NSQ */ ProcessEvent(ctx context.Context, event *cml04eventer.Event) error CreateProductionOrder(ctx context.Context, po *types.OrdenFabricacion) error /* Excel */ GetExcel(ctx context.Context, req types.GetExcelReq) (types.GetExcelRes, error) } type service struct { storage storage.IStorage file *os.File } // GetExcel implements IService. func (s *service) GetExcel(ctx context.Context, req types.GetExcelReq) (types.GetExcelRes, error) { // get mediciones from database mediciones, err := s.storage.GetExcel(ctx, req.Product, req.StartTime, req.EndTime) if err != nil { return types.GetExcelRes{}, err } return types.GetExcelRes{ Mediciones: mediciones, TimeStamp: time.Now().UTC().Format(time.RFC3339), }, nil } // ValidarUsuario implements IService. func (s *service) ValidarUsuario(ctx context.Context, req types.ValidarUsuarioReq) (types.ValidarUsuarioRes, error) { // get user from database user, err := s.storage.GetUser(ctx, req.Email) if err != nil { return types.ValidarUsuarioRes{}, err } // password from request pass := req.Pass // hash from database hash := user.Password // compare hash and pass if err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(pass)); err != nil { return types.ValidarUsuarioRes{}, err } return types.ValidarUsuarioRes{ Message: "user validated success", TimeStamp: time.Now().UTC().Format(time.RFC3339), }, nil } func checkEmail(email string) bool { // regular expression for validate email regex := `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$` // compile regular expression pattern := regexp.MustCompile(regex) // check if string match pattern return pattern.MatchString(email) } func encryptPass(pass string) (string, error) { res, err := bcrypt.GenerateFromPassword([]byte(pass), bcrypt.DefaultCost) if err != nil { return "", err } return string(res), nil } // CreateUsuario implements IService. func (s *service) CreateUsuario(ctx context.Context, req types.CreateUsuarioReq) (types.CreateUsuarioRes, error) { // user var holder user := req.Usuario // encrypt user pass pass, err := encryptPass(user.Password) if err != nil { return types.CreateUsuarioRes{}, err } // assign hash based on password user.Password = pass // check if email is correct if !checkEmail(user.Email) { return types.CreateUsuarioRes{}, errors.New("email format is not correct") } // create user if err := s.storage.CreateUser(ctx, user); err != nil { return types.CreateUsuarioRes{}, err } // done return types.CreateUsuarioRes{ Message: fmt.Sprintf("create user: %s success", user.Email), TimeStamp: time.Now().UTC().Format(time.RFC3339), }, nil } // GetUsuario implements IService. func (s *service) GetUsuario(ctx context.Context, req types.GetUsuarioReq) (types.GetUsuarioRes, error) { user, err := s.storage.GetUser(ctx, req.Email) if err != nil { return types.GetUsuarioRes{}, err } return types.GetUsuarioRes{ Usuario: user, TimeStamp: time.Now().Format(time.RFC3339), }, nil } // GetMedicion implements IService. func (s *service) GetMedicion(ctx context.Context, req types.GetMedicionReq) (types.GetMedicionRes, error) { medicion, err := s.storage.GetMedicion(ctx, req.MedicionID) if err != nil { return types.GetMedicionRes{}, err } return types.GetMedicionRes{ Medicion: medicion, TimeStamp: time.Now().Format(time.RFC3339), }, nil } // GetMediciones implements IService. func (s *service) GetMediciones(ctx context.Context, req types.GetMedicionesReq) (types.GetMedicionesRes, error) { mediciones, err := s.storage.GetMediciones(ctx, req.POrderNo) if err != nil { return types.GetMedicionesRes{}, nil } return types.GetMedicionesRes{ Mediciones: mediciones, TimeStamp: time.Now().Format(time.RFC3339), }, nil } // PostMediciones implements IService. func (s *service) PostMediciones(ctx context.Context, req types.PostMedicionesReq) (types.PostMedicionesRes, error) { if err := s.storage.PostMediciones(ctx, req.Medicion); err != nil { return types.PostMedicionesRes{}, err } return types.PostMedicionesRes{ Message: "post mediciones success", TimeStamp: time.Now().Format(time.RFC3339), }, nil } // GetProductionOrders implements IService. func (s *service) GetProductionOrders(ctx context.Context, req types.GetProductionOrdersReq) (res types.GetProductionOrdersRes, err error) { pos, err := s.storage.GetProductionOrders(ctx, req.Limit) if err != nil { return types.GetProductionOrdersRes{}, err } return types.GetProductionOrdersRes{ OrdenFabricacion: pos, TimeStamp: time.Now().Format(time.RFC3339), }, nil } // GetProductionOrder implements IService. func (s *service) GetProductionOrder(ctx context.Context, req types.GetProductionOrderReq) (types.GetProductionOrderRes, error) { po, err := s.storage.GetProductionOrder(ctx, req.PoNo) if err != nil { return types.GetProductionOrderRes{}, err } return types.GetProductionOrderRes{ OrdenFabricacion: po, TimeStamp: time.Now().UTC().Format(time.RFC3339), }, nil } // CreateTolerance implements IService. func (s *service) CreateTolerance(ctx context.Context, req types.CreateToleranceReq) (res types.CreateToleranceRes, err error) { // insert product tolerance into storage database if err := s.storage.CreateTolerance(ctx, req.Tolerancia); err != nil { return types.CreateToleranceRes{}, err } return types.CreateToleranceRes{ Message: "create tolerance sucess", TimeStamp: time.Now().UTC().Format(time.RFC3339), }, nil } // GetTolerancia implements IService. func (s *service) GetTolerance(ctx context.Context, req types.GetToleranciaReq) (res types.GetToleranciaRes, err error) { // request product tolerance storage database tolerance, err := s.storage.GetProductTolerance(ctx, req.Medida) // handle error if err != nil { return types.GetToleranciaRes{}, err } return types.GetToleranciaRes{ Tolerancia: tolerance, TimeStamp: time.Now().UTC().Format(time.RFC3339), }, nil } // CreateProductionOrder implements IService. func (s *service) CreateProductionOrder(ctx context.Context, po *types.OrdenFabricacion) error { return s.storage.CreateProductionOrder(ctx, po) } // ProcessEvent implements IService. func (s *service) ProcessEvent(ctx context.Context, event *cml04eventer.Event) error { // create buffer buffer := bytes.NewBuffer(event.EventData) // get event message subject subject, err := event.EventMeta.Get("subject") // handle error if err != nil { return err } switch subject { case "sap.in.telegramas.z_sms_10001": // Production order telegram // holder h := &types.T10001{} // decode if err := json.NewDecoder(buffer).Decode(h); err != nil { return err } po := &types.OrdenFabricacion{ Inst: h.Inst, DateTime: h.DateTime, POrderNo: h.POrderNo, SchedulNo: h.SchedulNo, SeqNumber: h.SeqNumber, PptimeWfc: h.PptimeWfc, PptimeMsc: h.PptimeMsc, SteelGrad: h.SteelGrad, ITemp: h.ITemp, IHeight: h.IHeight, IWidth: h.IWidth, ISection: h.ISection, HeatingSt: h.HeatingSt, FTarTemp: h.FTarTemp, FSection: h.FSection, FSectType: h.FSectType, TotWeight: h.TotWeight, TBeamBla: h.TBeamBla, TCustOrd: h.TCustOrd, TestLen: h.TestLen, PostFlag: h.PostFlag, ModuloX: h.ModuloX, OvWTolU: h.OvWTolU, OvWTolL: h.OvWTolL, OvHTolU: h.OvHTolU, OvHTolL: h.OvHTolL, WeTTolU: h.WeTTolU, WeTTolL: h.WeTTolL, WeHTolU: h.WeHTolU, WeHTolL: h.WeHTolL, FlWDsU: h.FlWDsU, FlWDsL: h.FlWDsL, FlWOsU: h.FlWOsU, FlWOsL: h.FlWOsL, WeMetTU: h.WeMetTU, WeMetTL: h.WeMetTL, WeCenTol: h.WeCenTol, WeSquTol: h.WeSquTol, FlParTol: h.FlParTol, BdRollID: h.BdRollID, UrRollID: h.UrRollID, EdRollID: h.EdRollID, UfRollID: h.UfRollID, SmRollID: h.SmRollID, Grupo6: h.Grupo6, StName: h.StName, StWeighM: h.StWeighM, StLen1: h.StLen1, StLen2: h.StLen2, StLen3: h.StLen3, StLen4: h.StLen4, StLen5: h.StLen5, StLen6: h.StLen6, StLen7: h.StLen7, StLen8: h.StLen8, StLen9: h.StLen9, StLen10: h.StLen10, StLen11: h.StLen11, StLen12: h.StLen12, Marfab: h.Marfab, Sortb: h.Sortb, } // create production order if err := s.CreateProductionOrder(ctx, po); err != nil { return err } } return nil } func NewService(storage storage.IStorage) IService { f, err := os.Create("events.dat") if err != nil { panic(err) } return &service{ storage: storage, file: f, } }